Commit f51a2635 by Qiang Xue

new asset management WIP

parent 280c2ca0
{
"directory" : "web/assets"
}
\ No newline at end of file
{
"name": "yii2-basic",
"version": "1.0.0",
"dependencies": {
},
"devDependencies": {
}
}
...@@ -30,7 +30,7 @@ instead of adding a new one. If you don't provide it, the JS code itself will be ...@@ -30,7 +30,7 @@ instead of adding a new one. If you don't provide it, the JS code itself will be
An external script can be added like the following: An external script can be added like the following:
```php ```php
$this->registerJsFile('http://example.com/js/main.js', [JqueryAsset::className()]); $this->registerJsFile('http://example.com/js/main.js', ['depends' => [JqueryAsset::className()]]);
``` ```
The arguments for [[yii\web\View::registerJsFile()|registerJsFile()]] are similar to those for The arguments for [[yii\web\View::registerJsFile()|registerJsFile()]] are similar to those for
...@@ -76,16 +76,19 @@ If you want to specify additional properties of the style tag, pass an array of ...@@ -76,16 +76,19 @@ If you want to specify additional properties of the style tag, pass an array of
If you need to make sure there's only a single style tag use fourth argument as was mentioned in meta tags description. If you need to make sure there's only a single style tag use fourth argument as was mentioned in meta tags description.
```php ```php
$this->registerCssFile("http://example.com/css/themes/black-and-white.css", [BootstrapAsset::className()], ['media' => 'print'], 'css-print-theme'); $this->registerCssFile("http://example.com/css/themes/black-and-white.css", [
'depends' => [BootstrapAsset::className()],
'media' => 'print',
], 'css-print-theme');
``` ```
The code above will add a link to CSS file to the head section of the page. The code above will add a link to CSS file to the head section of the page.
* The first argument specifies the CSS file to be registered. * The first argument specifies the CSS file to be registered.
* The second argument specifies that this CSS file depends on [[yii\bootstrap\BootstrapAsset|BootstrapAsset]], meaning it will be added * The second argument specifies the HTML attributes for the resulting `<link>` tag. The option `depends`
AFTER the CSS files in [[yii\bootstrap\BootstrapAsset|BootstrapAsset]]. Without this dependency specification, the relative order is specially handled. It specifies which asset bundles this CSS file depends on. In this case, the dependent
between this CSS file and the [[yii\bootstrap\BootstrapAsset|BootstrapAsset]] CSS files would be undefined. asset bundle is [[yii\bootstrap\BootstrapAsset|BootstrapAsset]]. This means the CSS file will be added
* The third argument specifies the attributes for the resulting `<link>` tag. *after* the CSS files in [[yii\bootstrap\BootstrapAsset|BootstrapAsset]].
* The last argument specifies an ID identifying this CSS file. If it is not provided, the URL of the CSS file will be * The last argument specifies an ID identifying this CSS file. If it is not provided, the URL of the CSS file will be
used instead. used instead.
......
...@@ -76,7 +76,7 @@ class can be placed anywhere but the convention for it is to be under `assets` d ...@@ -76,7 +76,7 @@ class can be placed anywhere but the convention for it is to be under `assets` d
Additionally you may specify `$jsOptions`, `$cssOptions` and `$publishOptions` that will be passed to Additionally you may specify `$jsOptions`, `$cssOptions` and `$publishOptions` that will be passed to
[[yii\web\View::registerJsFile()]], [[yii\web\View::registerCssFile()]] and [[yii\web\AssetManager::publish()]] [[yii\web\View::registerJsFile()]], [[yii\web\View::registerCssFile()]] and [[yii\web\AssetManager::publish()]]
respectively during registering and publising an asset. For more details on this see [Setting special options](#setting-special-options). respectively during registering and publishing an asset. For more details on this see [Setting special options](#setting-special-options).
[alias]: basics.md#path-aliases "Yii Path alias" [alias]: basics.md#path-aliases "Yii Path alias"
...@@ -89,16 +89,16 @@ following way: ...@@ -89,16 +89,16 @@ following way:
```php ```php
class LanguageAsset extends AssetBundle class LanguageAsset extends AssetBundle
{ {
public $language; public static $language;
public $sourcePath = '@app/assets/language'; public $sourcePath = '@app/assets/language';
public $js = [ public $js = [
]; ];
public function registerAssetFiles($view) public function init()
{ {
$language = $this->language ? $this->language : Yii::$app->language; parent::init();
$language = self::$language ? self::$language : Yii::$app->language;
$this->js[] = 'language-' . $language . '.js'; $this->js[] = 'language-' . $language . '.js';
parent::registerAssetFiles($view);
} }
} }
``` ```
...@@ -106,7 +106,8 @@ class LanguageAsset extends AssetBundle ...@@ -106,7 +106,8 @@ class LanguageAsset extends AssetBundle
In order to set language use the following code when registering an asset bundle in a view: In order to set language use the following code when registering an asset bundle in a view:
```php ```php
LanguageAsset::register($this)->language = $language; LanguageAsset::$language = $language;
LanguageAsset::register($this);
``` ```
......
...@@ -319,11 +319,10 @@ PHP; ...@@ -319,11 +319,10 @@ PHP;
$url = ArrayHelper::remove($params, 'url'); $url = ArrayHelper::remove($params, 'url');
$key = ArrayHelper::remove($params, 'key', null); $key = ArrayHelper::remove($params, 'key', null);
$depends = ArrayHelper::remove($params, 'depends', null);
if (isset($params['position'])) if (isset($params['position']))
$params['position'] = $this->getViewConstVal($params['position'], View::POS_END); $params['position'] = $this->getViewConstVal($params['position'], View::POS_END);
Yii::$app->getView()->registerJsFile($url, $depends, $params, $key); Yii::$app->getView()->registerJsFile($url, $params, $key);
} }
/** /**
...@@ -379,9 +378,8 @@ PHP; ...@@ -379,9 +378,8 @@ PHP;
$url = ArrayHelper::remove($params, 'url'); $url = ArrayHelper::remove($params, 'url');
$key = ArrayHelper::remove($params, 'key', null); $key = ArrayHelper::remove($params, 'key', null);
$depends = ArrayHelper::remove($params, 'depends', null);
Yii::$app->getView()->registerCssFile($url, $depends, $params, $key); Yii::$app->getView()->registerCssFile($url, $params, $key);
} }
/** /**
......
...@@ -319,4 +319,15 @@ class BaseUrl ...@@ -319,4 +319,15 @@ class BaseUrl
return $url; return $url;
} }
/**
* Returns a value indicating whether a URL is relative.
* A relative URL does not have host info part.
* @param string $url the URL to be checked
* @return boolean whether the URL is relative
*/
public static function isRelative($url)
{
return strncmp($url, '//', 2) && strpos($url, '://') === false;
}
} }
...@@ -26,41 +26,21 @@ use yii\base\Object; ...@@ -26,41 +26,21 @@ use yii\base\Object;
class AssetBundle extends Object class AssetBundle extends Object
{ {
/** /**
* @var string the root directory of the source asset files. A source asset file * @var string the directory that contains the asset files in this bundle.
* is a file that is part of your source code repository of your Web application.
* *
* You must set this property if the directory containing the source asset files * The value of this property can be prefixed to every relative asset file path listed in [[js]] and [[css]]
* is not Web accessible (this is usually the case for extensions). * to form an absolute file path. If this property is null (meaning not set), the value of
* * [[AssetManager::basePath]] will be used instead.
* By setting this property, the asset manager will publish the source asset files
* to a Web-accessible directory [[basePath]].
*
* You can use either a directory or an alias of the directory.
*/
public $sourcePath;
/**
* @var string the Web-accessible directory that contains the asset files in this bundle.
*
* If [[sourcePath]] is set, this property will be *overwritten* by [[AssetManager]]
* when it publishes the asset files from [[sourcePath]].
*
* If the bundle contains any assets that are specified in terms of relative file path,
* then this property must be set either manually or automatically (by [[AssetManager]] via
* asset publishing).
* *
* You can use either a directory or an alias of the directory. * You can use either a directory or an alias of the directory.
*/ */
public $basePath; public $basePath;
/** /**
* @var string the base URL that will be prefixed to the asset files for them to * @var string the base URL for the relative asset files listed in [[js]] and [[css]].
* be accessed via Web server.
* *
* If [[sourcePath]] is set, this property will be *overwritten* by [[AssetManager]] * The value of this property will be prefixed to every relative asset file path listed in [[js]] and [[css]]
* when it publishes the asset files from [[sourcePath]]. * when they are being registered in a view so that they can be Web accessible.
* * If this property is null (meaning not set), the value of [[AssetManager::baseUrl]] will be used instead.
* If the bundle contains any assets that are specified in terms of relative file path,
* then this property must be set either manually or automatically (by asset manager via
* asset publishing).
* *
* You can use either a URL or an alias of the URL. * You can use either a URL or an alias of the URL.
*/ */
...@@ -80,16 +60,16 @@ class AssetBundle extends Object ...@@ -80,16 +60,16 @@ class AssetBundle extends Object
public $depends = []; public $depends = [];
/** /**
* @var array list of JavaScript files that this bundle contains. Each JavaScript file can * @var array list of JavaScript files that this bundle contains. Each JavaScript file can
* be either a file path (without leading slash) relative to [[basePath]] or a URL representing * be either a file path (without leading slash) relative to [[basePath]] and [[baseUrl]],
* an external JavaScript file. * or a URL representing an external JavaScript file.
* *
* Note that only forward slash "/" can be used as directory separator. * Note that only forward slash "/" can be used as directory separators.
*/ */
public $js = []; public $js = [];
/** /**
* @var array list of CSS files that this bundle contains. Each CSS file can * @var array list of CSS files that this bundle contains. Each CSS file can
* be either a file path (without leading slash) relative to [[basePath]] or a URL representing * be either a file path (without leading slash) relative to [[basePath]] and [[baseUrl]],
* an external CSS file. * or a URL representing an external CSS file.
* *
* Note that only forward slash "/" can be used as directory separator. * Note that only forward slash "/" can be used as directory separator.
*/ */
...@@ -104,15 +84,11 @@ class AssetBundle extends Object ...@@ -104,15 +84,11 @@ class AssetBundle extends Object
* when registering the CSS files in this bundle. * when registering the CSS files in this bundle.
*/ */
public $cssOptions = []; public $cssOptions = [];
/**
* @var array the options to be passed to [[AssetManager::publish()]] when the asset bundle
* is being published.
*/
public $publishOptions = [];
/** /**
* @param View $view * Registers this asset bundle with a view.
* @param View $view the view to be registered with
* @return static the registered asset bundle instance * @return static the registered asset bundle instance
*/ */
public static function register($view) public static function register($view)
...@@ -126,9 +102,6 @@ class AssetBundle extends Object ...@@ -126,9 +102,6 @@ class AssetBundle extends Object
*/ */
public function init() public function init()
{ {
if ($this->sourcePath !== null) {
$this->sourcePath = rtrim(Yii::getAlias($this->sourcePath), '/\\');
}
if ($this->basePath !== null) { if ($this->basePath !== null) {
$this->basePath = rtrim(Yii::getAlias($this->basePath), '/\\'); $this->basePath = rtrim(Yii::getAlias($this->basePath), '/\\');
} }
...@@ -136,58 +109,4 @@ class AssetBundle extends Object ...@@ -136,58 +109,4 @@ class AssetBundle extends Object
$this->baseUrl = rtrim(Yii::getAlias($this->baseUrl), '/'); $this->baseUrl = rtrim(Yii::getAlias($this->baseUrl), '/');
} }
} }
/**
* Registers the CSS and JS files with the given view.
* @param \yii\web\View $view the view that the asset files are to be registered with.
*/
public function registerAssetFiles($view)
{
foreach ($this->js as $js) {
if ($js[0] !== '/' && $js[0] !== '.' && strpos($js, '://') === false) {
$view->registerJsFile($this->baseUrl . '/' . $js, [], $this->jsOptions);
} else {
$view->registerJsFile($js, [], $this->jsOptions);
}
}
foreach ($this->css as $css) {
if ($css[0] !== '/' && $css[0] !== '.' && strpos($css, '://') === false) {
$view->registerCssFile($this->baseUrl . '/' . $css, [], $this->cssOptions);
} else {
$view->registerCssFile($css, [], $this->cssOptions);
}
}
}
/**
* Publishes the asset bundle if its source code is not under Web-accessible directory.
* It will also try to convert non-CSS or JS files (e.g. LESS, Sass) into the corresponding
* CSS or JS files using [[AssetManager::converter|asset converter]].
* @param AssetManager $am the asset manager to perform the asset publishing
*/
public function publish($am)
{
if ($this->sourcePath !== null && !isset($this->basePath, $this->baseUrl)) {
list ($this->basePath, $this->baseUrl) = $am->publish($this->sourcePath, $this->publishOptions);
}
$converter = $am->getConverter();
foreach ($this->js as $i => $js) {
if (strpos($js, '/') !== 0 && strpos($js, '://') === false) {
if (isset($this->basePath, $this->baseUrl)) {
$this->js[$i] = $converter->convert($js, $this->basePath);
} else {
$this->js[$i] = '/' . $js;
}
}
}
foreach ($this->css as $i => $css) {
if (strpos($css, '/') !== 0 && strpos($css, '://') === false) {
if (isset($this->basePath, $this->baseUrl)) {
$this->css[$i] = $converter->convert($css, $this->basePath);
} else {
$this->css[$i] = '/' . $css;
}
}
}
}
} }
...@@ -15,8 +15,7 @@ namespace yii\web; ...@@ -15,8 +15,7 @@ namespace yii\web;
*/ */
class JqueryAsset extends AssetBundle class JqueryAsset extends AssetBundle
{ {
public $sourcePath = '@vendor/yiisoft/jquery';
public $js = [ public $js = [
'jquery.js', 'jquery/dist/jquery.js',
]; ];
} }
...@@ -8,9 +8,9 @@ ...@@ -8,9 +8,9 @@
namespace yii\web; namespace yii\web;
use Yii; use Yii;
use yii\helpers\ArrayHelper;
use yii\helpers\Html; use yii\helpers\Html;
use yii\base\InvalidConfigException; use yii\base\InvalidConfigException;
use yii\helpers\Url;
/** /**
* View represents a view object in the MVC pattern. * View represents a view object in the MVC pattern.
...@@ -261,7 +261,7 @@ class View extends \yii\base\View ...@@ -261,7 +261,7 @@ class View extends \yii\base\View
foreach ($bundle->depends as $dep) { foreach ($bundle->depends as $dep) {
$this->registerAssetFiles($dep); $this->registerAssetFiles($dep);
} }
$bundle->registerAssetFiles($this); $this->getAssetManager()->registerAssetFiles($this, $bundle);
} }
unset($this->assetBundles[$name]); unset($this->assetBundles[$name]);
} }
...@@ -360,23 +360,27 @@ class View extends \yii\base\View ...@@ -360,23 +360,27 @@ class View extends \yii\base\View
/** /**
* Registers a CSS file. * Registers a CSS file.
* @param string $url the CSS file to be registered. * @param string $url the CSS file to be registered.
* @param array $depends the names of the asset bundles that this CSS file depends on * @param array $options the HTML attributes for the link tag. Please refer to [[Html::cssFile()]] for
* @param array $options the HTML attributes for the link tag. * the supported options. The following options are specially handled and are not treated as HTML attributes:
* Please refer to [[Html::cssFile()]] for supported options. *
* - `depends`: array, specifies the names of the asset bundles that this CSS file depends on.
*
* @param string $key the key that identifies the CSS script file. If null, it will use * @param string $key the key that identifies the CSS script file. If null, it will use
* $url as the key. If two CSS files are registered with the same key, the latter * $url as the key. If two CSS files are registered with the same key, the latter
* will overwrite the former. * will overwrite the former.
*/ */
public function registerCssFile($url, $depends = [], $options = [], $key = null) public function registerCssFile($url, $options = [], $key = null)
{ {
$url = Yii::getAlias($url); $url = Yii::getAlias($url);
$key = $key ?: $url; $key = $key ?: $url;
$depends = ArrayHelper::remove($options, 'depends', []);
if (empty($depends)) { if (empty($depends)) {
$this->cssFiles[$key] = Html::cssFile($url, $options); $this->cssFiles[$key] = Html::cssFile($url, $options);
} else { } else {
$am = $this->getAssetManager(); $this->getAssetManager()->bundles[$key] = new AssetBundle([
$am->bundles[$key] = new AssetBundle([ 'baseUrl' => '',
'css' => [Url::to($url)], 'css' => [$url],
'cssOptions' => $options, 'cssOptions' => $options,
'depends' => (array) $depends, 'depends' => (array) $depends,
]); ]);
...@@ -414,14 +418,14 @@ class View extends \yii\base\View ...@@ -414,14 +418,14 @@ class View extends \yii\base\View
/** /**
* Registers a JS file. * Registers a JS file.
* @param string $url the JS file to be registered. * @param string $url the JS file to be registered.
* @param array $depends the names of the asset bundles that this JS file depends on * @param array $options the HTML attributes for the script tag. The following options are specially handled
* @param array $options the HTML attributes for the script tag. A special option * and are not treated as HTML attributes:
* named "position" is supported which specifies where the JS script tag should be inserted
* in a page. The possible values of "position" are:
* *
* - [[POS_HEAD]]: in the head section * - `depends`: array, specifies the names of the asset bundles that this JS file depends on.
* - [[POS_BEGIN]]: at the beginning of the body section * - `position`: specifies where the JS script tag should be inserted in a page. The possible values are:
* - [[POS_END]]: at the end of the body section. This is the default value. * * [[POS_HEAD]]: in the head section
* * [[POS_BEGIN]]: at the beginning of the body section
* * [[POS_END]]: at the end of the body section. This is the default value.
* *
* Please refer to [[Html::jsFile()]] for other supported options. * Please refer to [[Html::jsFile()]] for other supported options.
* *
...@@ -429,18 +433,19 @@ class View extends \yii\base\View ...@@ -429,18 +433,19 @@ class View extends \yii\base\View
* $url as the key. If two JS files are registered with the same key, the latter * $url as the key. If two JS files are registered with the same key, the latter
* will overwrite the former. * will overwrite the former.
*/ */
public function registerJsFile($url, $depends = [], $options = [], $key = null) public function registerJsFile($url, $options = [], $key = null)
{ {
$url = Yii::getAlias($url); $url = Yii::getAlias($url);
$key = $key ?: $url; $key = $key ?: $url;
$depends = ArrayHelper::remove($options, 'depends', []);
if (empty($depends)) { if (empty($depends)) {
$position = isset($options['position']) ? $options['position'] : self::POS_END; $position = ArrayHelper::remove($options, 'position', self::POS_END);
unset($options['position']);
$this->jsFiles[$position][$key] = Html::jsFile($url, $options); $this->jsFiles[$position][$key] = Html::jsFile($url, $options);
} else { } else {
$am = $this->getAssetManager(); $this->getAssetManager()->bundles[$key] = new AssetBundle([
$am->bundles[$key] = new AssetBundle([ 'baseUrl' => '',
'js' => [Url::to($url)], 'js' => [$url],
'jsOptions' => $options, 'jsOptions' => $options,
'depends' => (array) $depends, 'depends' => (array) $depends,
]); ]);
......
...@@ -15,9 +15,8 @@ namespace yii\web; ...@@ -15,9 +15,8 @@ namespace yii\web;
*/ */
class YiiAsset extends AssetBundle class YiiAsset extends AssetBundle
{ {
public $sourcePath = '@yii/assets';
public $js = [ public $js = [
'yii.js', 'yii2/assets/yii.js',
]; ];
public $depends = [ public $depends = [
'yii\web\JqueryAsset', 'yii\web\JqueryAsset',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment