Skip to content
Snippets Groups Projects
Commit dded40f3 authored by Angie Byron's avatar Angie Byron
Browse files

Issue #1784774 by mcjim, Rob Loach: Added Assetic component to core.

parent c556fa32
No related branches found
No related tags found
2 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10
Showing
with 1188 additions and 12 deletions
......@@ -11,7 +11,8 @@
"symfony/routing": "2.1.*",
"symfony/yaml": "2.1.*",
"twig/twig": "1.8.*",
"doctrine/common": "2.3.*"
"doctrine/common": "2.3.*",
"kriswallsmith/assetic": "1.1.*"
},
"minimum-stability": "beta"
"minimum-stability": "alpha"
}
......@@ -25,6 +25,10 @@
"package": "symfony/http-kernel",
"version": "v2.1.0-RC2"
},
{
"package": "symfony/process",
"version": "v2.1.0-RC2"
},
{
"package": "symfony/routing",
"version": "v2.1.0-RC2"
......@@ -36,13 +40,17 @@
{
"package": "twig/twig",
"version": "v1.8.3"
},
{
"package": "kriswallsmith/assetic",
"version": "v1.1.0-alpha1"
}
],
"packages-dev": null,
"aliases": [
],
"minimum-stability": "beta",
"minimum-stability": "alpha",
"stability-flags": [
]
......
......@@ -9,6 +9,7 @@
'Twig_' => $vendorDir . '/twig/twig/lib/',
'Symfony\\Component\\Yaml' => $vendorDir . '/symfony/yaml/',
'Symfony\\Component\\Routing' => $vendorDir . '/symfony/routing/',
'Symfony\\Component\\Process' => $vendorDir . '/symfony/process/',
'Symfony\\Component\\HttpKernel' => $vendorDir . '/symfony/http-kernel/',
'Symfony\\Component\\HttpFoundation' => $vendorDir . '/symfony/http-foundation/',
'Symfony\\Component\\EventDispatcher' => $vendorDir . '/symfony/event-dispatcher/',
......@@ -16,4 +17,5 @@
'Symfony\\Component\\ClassLoader' => $vendorDir . '/symfony/class-loader/',
'SessionHandlerInterface' => $vendorDir . '/symfony/http-foundation/Symfony/Component/HttpFoundation/Resources/stubs',
'Doctrine\\Common' => $vendorDir . '/doctrine/common/lib/',
'Assetic' => $vendorDir . '/kriswallsmith/assetic/src/',
);
......@@ -3,7 +3,7 @@
"name": "twig/twig",
"version": "v1.8.3",
"version_normalized": "1.8.3.0",
"time": "2012-06-18 19:48:16",
"time": "2012-06-18 18:48:16",
"source": {
"type": "git",
"url": "git://github.com/fabpot/Twig.git",
......@@ -58,7 +58,7 @@
"version": "v2.1.0-RC2",
"version_normalized": "2.1.0.0-RC2",
"target-dir": "Symfony/Component/ClassLoader",
"time": "2012-08-27 15:51:49",
"time": "2012-08-27 14:51:49",
"source": {
"type": "git",
"url": "https://github.com/symfony/ClassLoader",
......@@ -113,7 +113,7 @@
"version": "v2.1.0-RC2",
"version_normalized": "2.1.0.0-RC2",
"target-dir": "Symfony/Component/DependencyInjection",
"time": "2012-08-28 07:54:42",
"time": "2012-08-28 06:54:42",
"source": {
"type": "git",
"url": "https://github.com/symfony/DependencyInjection",
......@@ -172,7 +172,7 @@
"name": "doctrine/common",
"version": "2.3.0-RC2",
"version_normalized": "2.3.0.0-RC2",
"time": "2012-08-29 14:06:32",
"time": "2012-08-29 13:06:32",
"source": {
"type": "git",
"url": "https://github.com/doctrine/common",
......@@ -249,7 +249,7 @@
"version": "v2.1.0-RC2",
"version_normalized": "2.1.0.0-RC2",
"target-dir": "Symfony/Component/HttpFoundation",
"time": "2012-08-22 13:48:41",
"time": "2012-08-22 12:48:41",
"source": {
"type": "git",
"url": "https://github.com/symfony/HttpFoundation",
......@@ -302,7 +302,7 @@
"version": "v2.1.0-RC2",
"version_normalized": "2.1.0.0-RC2",
"target-dir": "Symfony/Component/EventDispatcher",
"time": "2012-08-22 13:48:41",
"time": "2012-08-22 12:48:41",
"source": {
"type": "git",
"url": "https://github.com/symfony/EventDispatcher",
......@@ -361,7 +361,7 @@
"version": "v2.1.0-RC2",
"version_normalized": "2.1.0.0-RC2",
"target-dir": "Symfony/Component/HttpKernel",
"time": "2012-08-28 08:00:18",
"time": "2012-08-28 07:00:18",
"source": {
"type": "git",
"url": "https://github.com/symfony/HttpKernel",
......@@ -433,7 +433,7 @@
"version": "v2.1.0-RC2",
"version_normalized": "2.1.0.0-RC2",
"target-dir": "Symfony/Component/Routing",
"time": "2012-08-28 07:54:42",
"time": "2012-08-28 06:54:42",
"source": {
"type": "git",
"url": "https://github.com/symfony/Routing",
......@@ -496,7 +496,7 @@
"version": "v2.1.0-RC2",
"version_normalized": "2.1.0.0-RC2",
"target-dir": "Symfony/Component/Yaml",
"time": "2012-08-22 13:48:41",
"time": "2012-08-22 12:48:41",
"source": {
"type": "git",
"url": "https://github.com/symfony/Yaml",
......@@ -542,5 +542,115 @@
"Symfony\\Component\\Yaml": ""
}
}
},
{
"name": "symfony/process",
"version": "v2.1.0-RC2",
"version_normalized": "2.1.0.0-RC2",
"target-dir": "Symfony/Component/Process",
"time": "2012-08-26 06:13:51",
"source": {
"type": "git",
"url": "https://github.com/symfony/Process",
"reference": "v2.1.0-RC2"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/Process/zipball/v2.1.0-RC2",
"reference": "v2.1.0-RC2",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"installation-source": "dist",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
}
],
"description": "Symfony Process Component",
"homepage": "http://symfony.com",
"autoload": {
"psr-0": {
"Symfony\\Component\\Process": ""
}
}
},
{
"name": "kriswallsmith/assetic",
"version": "v1.1.0-alpha1",
"version_normalized": "1.1.0.0-alpha1",
"time": "2012-08-28 05:33:44",
"source": {
"type": "git",
"url": "http://github.com/kriswallsmith/assetic.git",
"reference": "v1.1.0-alpha1"
},
"dist": {
"type": "zip",
"url": "https://github.com/kriswallsmith/assetic/zipball/v1.1.0-alpha1",
"reference": "v1.1.0-alpha1",
"shasum": ""
},
"require": {
"php": ">=5.3.1",
"symfony/process": "2.1.*"
},
"require-dev": {
"twig/twig": ">=1.6.0,<2.0",
"leafo/lessphp": "*",
"leafo/scssphp": "*",
"ptachoire/cssembed": "*"
},
"suggest": {
"twig/twig": "Assetic provides the integration with the Twig templating engine",
"leafo/lessphp": "Assetic provides the integration with the lessphp LESS compiler",
"leafo/scssphp": "Assetic provides the integration with the scssphp SCSS compiler",
"ptachoire/cssembed": "Assetic provides the integration with phpcssembed to embed data uris"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
},
"installation-source": "dist",
"license": [
"MIT"
],
"authors": [
{
"name": "Kris Wallsmith",
"email": "kris.wallsmith@gmail.com",
"homepage": "http://kriswallsmith.net/"
}
],
"description": "Asset Management for PHP",
"homepage": "https://github.com/kriswallsmith/assetic",
"keywords": [
"assets",
"compression",
"minification"
],
"autoload": {
"psr-0": {
"Assetic": "src/"
}
}
}
]
phpunit.xml
vendor/
composer.phar
composer.lock
language: php
php:
- 5.3
- 5.4
before_script:
- wget http://getcomposer.org/composer.phar
- php composer.phar install --dev
- git clone https://github.com/kamicane/packager.git vendor/packager --quiet --depth 1
- git clone https://github.com/leafo/lessphp.git vendor/lessphp --quiet --depth 1
- git clone https://github.com/mrclay/minify.git vendor/minify --quiet --depth 1
- svn checkout http://cssmin.googlecode.com/svn/trunk/ vendor/cssmin --quiet
- wget --quiet -O javascript-packer.zip "http://joliclic.free.fr/php/javascript-packer/telechargement.php?id=2&action=telecharger" && mkdir -p vendor/packer && unzip -qq javascript-packer.zip -d vendor/packer; rm javascript-packer.zip
script: phpunit --configuration phpunit.travis.xml
1.0.4 (August 28, 2012)
-----------------------
* Fixed the Twig tag to avoid a fatal error when left unclosed
* Added the HashableInterface for non-serialiable filters
* Fixed a bug for compass on windows
1.0.3 (March 2, 2012)
---------------------
* Added "boring" option to Compass filter
* Fixed accumulation of load paths in Compass filter
* Fixed issues in CssImport and CssRewrite filters
1.0.2 (August 26, 2011)
-----------------------
* Twig 1.2 compatibility
* Fixed filtering of large LessCSS assets
* Fixed escaping of commands on Windows
* Misc fixes to Compass filter
* Removed default CssEmbed charset
1.0.1 (July 15, 2011)
---------------------
* Fixed Twig error handling
* Removed use of STDIN
* Added inheritance of environment variables
* Fixed Compass on Windows
* Improved escaping of commands
1.0.0 (July 10, 2011)
---------------------
* Initial release
1.1.0-alpha1 (August 28, 2012)
------------------------------
* Added pure php css embed filter
* Added Scssphp support
* Added support for Google Closure language option
* Added a way to set a specific ruby path for CompassFilter and SassFilter
* Ensure uniqueness of temporary files created by the compressor filter. Fixed #61
* Added Compass option for generated_images_path (for generated Images/Sprites)
* Added PackerFilter
* Add the way to contact closure compiler API using curl, if available and allow_url_fopen is off
* Added filters for JSMin and JSMinPlus
* Added the UglifyJsFilter
* Improved the error message in getModifiedTime when a file asset uses an invalid file
* added support for asset variables:
Asset variables allow you to pre-compile your assets for a finite set of known
variable values, and then to simply deliver the correct asset version at runtime.
For example, this is helpful for assets with language, or browser-specific code.
* Removed the copy-paste of the Symfony2 Process component and use the original one
* Added ability to pass variables into lessphp filter
* Added google closure stylesheets jar filter
* Added the support of `--bare` for the CoffeeScriptFilter
Copyright (c) 2010-2012 OpenSky Project Inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# Assetic ![project status](http://stillmaintained.com/kriswallsmith/assetic.png) #
Assetic is an asset management framework for PHP.
``` php
<?php
use Assetic\Asset\AssetCollection;
use Assetic\Asset\FileAsset;
use Assetic\Asset\GlobAsset;
$js = new AssetCollection(array(
new GlobAsset('/path/to/js/*'),
new FileAsset('/path/to/another.js'),
));
// the code is merged when the asset is dumped
echo $js->dump();
```
Assets
------
An Assetic asset is something with filterable content that can be loaded and
dumped. An asset also includes metadata, some of which can be manipulated and
some of which is immutable.
| **Property** | **Accessor** | **Mutator** |
|--------------|-----------------|---------------|
| content | getContent | setContent |
| mtime | getLastModified | n/a |
| source root | getSourceRoot | n/a |
| source path | getSourcePath | n/a |
| target path | getTargetPath | setTargetPath |
Filters
-------
Filters can be applied to manipulate assets.
``` php
<?php
use Assetic\Asset\AssetCollection;
use Assetic\Asset\FileAsset;
use Assetic\Asset\GlobAsset;
use Assetic\Filter\LessFilter;
use Assetic\Filter\Yui;
$css = new AssetCollection(array(
new FileAsset('/path/to/src/styles.less', array(new LessFilter())),
new GlobAsset('/path/to/css/*'),
), array(
new Yui\CssCompressorFilter('/path/to/yuicompressor.jar'),
));
// this will echo CSS compiled by LESS and compressed by YUI
echo $css->dump();
```
The filters applied to the collection will cascade to each asset leaf if you
iterate over it.
``` php
<?php
foreach ($css as $leaf) {
// each leaf is compressed by YUI
echo $leaf->dump();
}
```
The core provides the following filters in the `Assetic\Filter` namespace:
* `CoffeeScriptFilter`: compiles CoffeeScript into Javascript
* `CssEmbedFilter`: embeds image data in your stylesheets
* `CssImportFilter`: inlines imported stylesheets
* `CssMinFilter`: minifies CSS
* `CssRewriteFilter`: fixes relative URLs in CSS assets when moving to a new URL
* `GoogleClosure\CompilerApiFilter`: compiles Javascript using the Google Closure Compiler API
* `GoogleClosure\CompilerJarFilter`: compiles Javascript using the Google Closure Compiler JAR
* `JpegoptimFilter`: optimize your JPEGs
* `JpegtranFilter`: optimize your JPEGs
* `LessFilter`: parses LESS into CSS (using less.js with node.js)
* `LessphpFilter`: parses LESS into CSS (using lessphp)
* `OptiPngFilter`: optimize your PNGs
* `PackerFilter`: compresses Javascript using Dean Edwards's Packer
* `PngoutFilter`: optimize your PNGs
* `CompassFilter`: Compass CSS authoring framework
* `Sass\SassFilter`: parses SASS into CSS
* `Sass\ScssFilter`: parses SCSS into CSS
* `SprocketsFilter`: Sprockets Javascript dependency management
* `StylusFilter`: parses STYL into CSS
* `Yui\CssCompressorFilter`: compresses CSS using the YUI compressor
* `Yui\JsCompressorFilter`: compresses Javascript using the YUI compressor
Asset Manager
-------------
An asset manager is provided for organizing assets.
``` php
<?php
use Assetic\AssetManager;
use Assetic\Asset\FileAsset;
use Assetic\Asset\GlobAsset;
$am = new AssetManager();
$am->set('jquery', new FileAsset('/path/to/jquery.js'));
$am->set('base_css', new GlobAsset('/path/to/css/*'));
```
The asset manager can also be used to reference assets to avoid duplication.
``` php
<?php
use Assetic\Asset\AssetCollection;
use Assetic\Asset\AssetReference;
use Assetic\Asset\FileAsset;
$am->set('my_plugin', new AssetCollection(array(
new AssetReference($am, 'jquery'),
new FileAsset('/path/to/jquery.plugin.js'),
)));
```
Filter Manager
--------------
A filter manager is also provided for organizing filters.
``` php
<?php
use Assetic\FilterManager;
use Assetic\Filter\Sass\SassFilter;
use Assetic\Filter\Yui;
$fm = new FilterManager();
$fm->set('sass', new SassFilter('/path/to/parser/sass'));
$fm->set('yui_css', new Yui\CssCompressorFilter('/path/to/yuicompressor.jar'));
```
Asset Factory
-------------
If you'd rather not create all these objects by hand, you can use the asset
factory, which will do most of the work for you.
``` php
<?php
use Assetic\Factory\AssetFactory;
$factory = new AssetFactory('/path/to/asset/directory/');
$factory->setAssetManager($am);
$factory->setFilterManager($fm);
$factory->setDebug(true);
$css = $factory->createAsset(array(
'@reset', // load the asset manager's "reset" asset
'css/src/*.scss', // load every scss files from "/path/to/asset/directory/css/src/"
), array(
'scss', // filter through the filter manager's "scss" filter
'?yui_css', // don't use this filter in debug mode
));
echo $css->dump();
```
Prefixing a filter name with a question mark, as `yui_css` is here, will cause
that filter to be omitted when the factory is in debug mode.
Caching
-------
A simple caching mechanism is provided to avoid unnecessary work.
``` php
<?php
use Assetic\Asset\AssetCache;
use Assetic\Asset\FileAsset;
use Assetic\Cache\FilesystemCache;
use Assetic\Filter\Yui;
$yui = new Yui\JsCompressorFilter('/path/to/yuicompressor.jar');
$js = new AssetCache(
new FileAsset('/path/to/some.js', array($yui)),
new FilesystemCache('/path/to/cache')
);
// the YUI compressor will only run on the first call
$js->dump();
$js->dump();
$js->dump();
```
Static Assets
-------------
Alternatively you can just write filtered assets to your web directory and be
done with it.
``` php
<?php
use Assetic\AssetWriter;
$writer = new AssetWriter('/path/to/web');
$writer->writeManagerAssets($am);
```
Twig
----
To use the Assetic [Twig][3] extension you must register it to your Twig
environment:
``` php
<?php
$twig->addExtension(new AsseticExtension($factory, $debug));
```
Once in place, the extension exposes a stylesheets and a javascripts tag with a syntax similar
to what the asset factory uses:
``` html+jinja
{% stylesheets '/path/to/sass/main.sass' filter='sass,?yui_css' output='css/all.css' %}
<link href="{{ asset_url }}" type="text/css" rel="stylesheet" />
{% endstylesheets %}
```
This example will render one `link` element on the page that includes a URL
where the filtered asset can be found.
When the extension is in debug mode, this same tag will render multiple `link`
elements, one for each asset referenced by the `css/src/*.sass` glob. The
specified filters will still be applied, unless they are marked as optional
using the `?` prefix.
This behavior can also be triggered by setting a `debug` attribute on the tag:
``` html+jinja
{% stylesheets 'css/*' debug=true %} ... {% stylesheets %}
```
These assets need to be written to the web directory so these URLs don't
return 404 errors.
``` php
<?php
use Assetic\AssetWriter;
use Assetic\Extension\Twig\TwigFormulaLoader;
use Assetic\Extension\Twig\TwigResource;
use Assetic\Factory\LazyAssetManager;
$am = new LazyAssetManager($factory);
// enable loading assets from twig templates
$am->setLoader('twig', new TwigFormulaLoader($twig));
// loop through all your templates
foreach ($templates as $template) {
$resource = new TwigResource($twigLoader, $template);
$am->addResource($resource, 'twig');
}
$writer = new AssetWriter('/path/to/web');
$writer->writeManagerAssets($am);
```
---
Assetic is based on the Python [webassets][1] library (available on
[GitHub][2]).
[1]: http://elsdoerfer.name/docs/webassets
[2]: https://github.com/miracle2k/webassets
[3]: http://twig.sensiolabs.org
{
"name": "kriswallsmith/assetic",
"minimum-stability": "dev",
"description": "Asset Management for PHP",
"keywords": ["assets", "compression", "minification"],
"homepage": "https://github.com/kriswallsmith/assetic",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Kris Wallsmith",
"email": "kris.wallsmith@gmail.com",
"homepage": "http://kriswallsmith.net/"
}
],
"require": {
"php": ">=5.3.1",
"symfony/process": "2.1.*"
},
"require-dev": {
"twig/twig": ">=1.6.0,<2.0",
"leafo/lessphp": "*",
"leafo/scssphp": "*",
"ptachoire/cssembed": "*"
},
"minimum-stability": "dev",
"suggest": {
"twig/twig": "Assetic provides the integration with the Twig templating engine",
"leafo/lessphp": "Assetic provides the integration with the lessphp LESS compiler",
"leafo/scssphp": "Assetic provides the integration with the scssphp SCSS compiler",
"ptachoire/cssembed": "Assetic provides the integration with phpcssembed to embed data uris"
},
"autoload": {
"psr-0": { "Assetic": "src/" }
},
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
}
}
Building and Dumping Assets
---------------------------
The is the simplest approach to using Assetic. It involves two steps:
1. Create a PHP script in your web directory that uses the Assetic OOP API to
create and output an asset.
2. Reference that file from your template.
For example, you could create a file in your web directory at
`assets/javascripts.php` with the following code:
use Assetic\Asset\AssetCollection;
use Assetic\Asset\FileAsset;
use Assetic\Filter\Yui\JsCompressorFilter as YuiCompressorFilter;
$js = new AssetCollection(array(
new FileAsset(__DIR__.'/jquery.js'),
new FileAsset(__DIR__.'/application.js'),
), array(
new YuiCompressorFilter('/path/to/yuicompressor.jar'),
));
header('Content-Type: application/js');
echo $js->dump();
In your HTML template you would include this generated Javascript using a
simple `<script>` tag:
<script src="/assets/javascripts.php"></script>
Next: [Basic Concepts](concepts.md)
In order to use the Assetic OOP API you must first understand the two central
concepts of Assetic: assets and filters.
### What is an Asset?
As asset is an object that has content and metadata which can be loaded and
dumped. Your assets will probably fall into three categories: Javascripts,
stylesheets and images. Most assets will be loaded from files in your
filesystem, but they can also be loaded via HTTP, a database, from a string,
or virtually anything else. All that an asset has to do is fulfill Assetic's
basic asset interface.
### What is a Filter?
A filter is an object that acts upon an asset's content when that asset is
loaded and/or dumped. Similar to assets, a filter can do virtually anything,
as long as it implements Assetic's filter interface.
Here is a list of some of the tools that can be applied to assets using a
filter:
* CoffeeScript
* CssEmbed
* CssMin
* Google Closure Compiler
* jpegoptim
* jpegtran
* Less
* LessPHP
* optipng
* Packager
* pngout
* SASS
* Sprockets (version 1)
* Stylus
* YUI Compressor
### Using Assets and Filters
You need to start by creating an asset object. This will probably mean
instantiating a `FileAsset` instance, which takes a filesystem path as its
first argument:
$asset = new Assetic\Asset\FileAsset('/path/to/main.css');
Once you have an asset you can begin adding filters to it by calling
`ensureFilter()`. For example, you can add a filter that applies the YUI
Compressor to the contents of the asset:
$yui = new Assetic\Filter\Yui\CssCompressorFilter('/path/to/yui.jar');
$asset->ensureFilter($yui);
Once you've added as many filters as you'd like you can output the finished
asset to the browser:
header('Content-Type: text/css');
echo $asset->dump();
### Asset Collections
It is a good idea to combine assets of the same type into a single file to
avoid unnecessary HTTP requests. You can do this in Assetic using the
`AssetCollection` class. This class is just like any other asset in Assetic's
eyes as it implements the asset interface, but under the hood it allows you to
combine multiple assets into one.
use Assetic\Asset\AssetCollection;
$asset = new AssetCollection(array(
new FileAsset('/path/to/js/jquery.js'),
new FileAsset('/path/to/js/jquery.plugin.js'),
new FileAsset('/path/to/js/application.js'),
));
### Nested Asset Collections
The collection class implements the asset interface and all assets passed into
a collection must implement the same interface, which means you can easily
nest collections within one another:
use Assetic\Asset\AssetCollection;
use Assetic\Asset\GlobAsset;
use Assetic\Asset\HttpAsset;
$asset = new AssetCollection(array(
new HttpAsset('http://example.com/jquery.min.js'),
new GlobAsset('/path/to/js/*'),
));
The `HttpAsset` class is a special asset class that loads a file over HTTP;
`GlobAsset` is a special asset collection class that loads files based on a
filesystem glob -- both implement the asset interface.
This concept of nesting asset collection become even more powerful when you
start applying different sets of filters to each collection. Imagine some of
your application's stylesheets are written in SASS, while some are written in
vanilla CSS. You can combine all of these into one seamless CSS asset:
use Assetic\Asset\AssetCollection;
use Assetic\Asset\GlobAsset;
use Assetic\Filter\SassFilter;
use Assetic\Filter\Yui\CssCompressorFilter;
$css = new AssetCollection(array(
new GlobAsset('/path/to/sass/*.sass', array(new SassFilter())),
new GlobAsset('/path/to/css/*.css'),
), array(
new YuiCompressorFilter('/path/to/yuicompressor.jar'),
));
You'll notice I've also applied the YUI compressor filter to the combined
asset so all CSS will be minified.
### Iterating over an Asset Collection
Once you have an asset collection you can iterate over it like you would a
plain old PHP array:
echo "Source paths:\n";
foreach ($collection as $asset) {
echo ' - '.$asset->getSourcePath()."\n";
}
The asset collection iterates recursively, which means you will only see the
"leaf" assets during iteration. Iteration also includes a smart filter which
ensures you only see each asset once, even if the same asset has been included
multiple times.
Next: [Defining Assets "On The Fly"](define.md)
Defining Assets "On The Fly"
----------------------------
The second approach to using Assetic involves defining your application's
assets "on the fly" in your templates, instead of in an isolated PHP file.
Using this approach, your PHP template would look something like this:
<script src="<?php echo assetic_javascripts('js/*', 'yui_js') ?>"></script>
This call to `assetic_javascripts()` serves a dual purpose. It will be read by
the Assetic "formula loader" which will extract an asset "formula" that can be
used to build, dump and output the asset. It will also be executed when the
template is rendered, at which time the path to the output asset is output.
Assetic includes the following templating helper functions:
* `assetic_image()`
* `assetic_javascripts()`
* `assetic_stylesheets()`
Defining assets on the fly is a much more sophisticated technique and
therefore relies on services to do the heavy lifting. The main one being the
asset factory.
### Asset Factory
The asset factory knows how to create asset objects using only arrays and
scalar values as input. This is the same string syntax used by the `assetic_*`
template helper functions.
use Assetic\Factory\AssetFactory;
$factory = new AssetFactory('/path/to/web');
$js = $factory->createAsset(array(
'js/jquery.js',
'js/jquery.plugin.js',
'js/application.js',
));
### Filter Manager
You can also apply filters to asset created by the factory. To do this you
must setup a `FilterManager`, which organizes filters by a name.
use Assetic\FilterManager;
use Assetic\Filter\GoogleClosure\ApiFilter as ClosureFilter;
$fm = new FilterManager();
$fm->set('closure', new ClosureFilter());
$factory->setFilterManager($fm);
$js = $factory->createAsset('js/*', 'closure');
This code creates an instance of the Google Closure Compiler filter and
assigns it the name `closure` using a filter manager. This filter manager is
then injected into the asset factory, making the filter available as `closure`
when creating assets.
### Debug Mode
The asset factory also introduces the concept of a debug mode. This mode
allows you to omit certain filters from assets the factory creates depending
on whether it is enabled or not.
For example, the YUI Compressor is awesome, but it is only appropriate in a
production environment as it is very difficult to debug minified Javascript.
use Asset\Factory\AssetFactory;
$factory = new AssetFactory('/path/to/web', true); // debug mode is on
$factory->setFilterManager($fm);
$js = $factory->createAsset('js/*', '?closure');
By prefixing the `closure` filter's name with a question mark, we are telling
the factory this filter is optional and should only be applied with debug mode
is off.
### Asset Manager and Asset References
The asset factory provides another special string syntax that allows you to
reference assets you defined elsewhere. These are called "asset references"
and involve an asset manager which, similar to the filter manager, organizes
assets by name.
use Assetic\AssetManager;
use Assetic\Asset\FileAsset;
use Assetic\Factory\AssetFactory;
$am = new AssetManager();
$am->set('jquery', new FileAsset('/path/to/jquery.js'));
$factory = new AssetFactory('/path/to/web');
$factory->setAssetManager($am);
$js = $factory->createAsset(array(
'@jquery',
'js/application.js',
));
### Extracting Assets from Templates
Once you've defined a set of assets in your templates you must use the
"formula loader" service to extract these asset definitions.
use Assetic\Factory\Loader\FunctionCallsFormulaLoader;
use Assetic\Factory\Resource\FileResource;
$loader = new FunctionCallsFormulaLoader($factory);
$formulae = $loader->load(new FileResource('/path/to/template.php'));
These asset formulae aren't much use by themselves. They each include just
enough information for the asset factory to create the intended asset object.
In order for these to be useful they must be wrapped in the special
`LazyAssetManager`.
### The Lazy Asset Manager
This service is a composition of the asset factory and one or more formula
loaders. It acts as the glue between these services behind the scenes, but can
be used just like a normal asset manager on the surface.
use Assetic\Asset\FileAsset;
use Assetic\Factory\LazyAssetManager;
use Assetic\Factory\Loader\FunctionCallsFormulaLoader;
use Assetic\Factory\Resource\DirectoryResource;
$am = new LazyAssetManager($factory);
$am->set('jquery', new FileAsset('/path/to/jquery.js'));
$am->setLoader('php', new FunctionCallsFormulaLoader($factory));
$am->addResource(new DirectoryResource('/path/to/templates', '/\.php$/'), 'php');
### Asset Writer
Finally, once you've create an asset manager that knows about every asset
you've defined in your templates, you must use an asset writer to actually
create the files your templates are going to be referencing.
use Assetic\AssetWriter;
$writer = new AssetWriter('/path/to/web');
$writer->writeManagerAssets($am);
After running this script, all of the assets in your asset manager will be
loaded into memory, filtered with their configured filters and dumped to your
web directory as static files, ready to be served.
Table Of Contents
-----------------
1. [Introduction](introduction.md)
2. [Building and Dumping Assets](build.md)
3. [Basic Concepts](concepts.md)
4. [Defining Assets "On The Fly"](define.md)
What is Assetic?
----------------
Assetic is an asset management framework for PHP 5.3. Assetic enables you to
use a variety of third party tools that will help bring order to your
application's Javascripts, stylesheets and images.
How Do I Use Assetic?
---------------------
There are two distinct approaches you can take when using Assetic:
1. Build, dump and output assets in PHP files that you reference directly
from your templates
2. Defining assets in your templates ("on the fly") and use a loader to
extract, dump and output them
The first approach is simpler, but the second, with all its moving parts,
offers more flexibility and opportunity for optimization.
Next: [Building and Dumping Assets](build.md)
アセットのビルドとダンプ
---------------------------
Asseticを使う一番単純な方法は、次の2ステップからなります。
1. 公開領域内にPHPスクリプトを作成し、Assetic OOP APIを使用してアセットの作成・出力を行う
2. テンプレートから上記のファイルを参照する
例えば、公開領域内に`assets/javascripts.php`ファイルを作成し、
下記のようなコードを記述します。
use Assetic\Asset\AssetCollection;
use Assetic\Asset\FileAsset;
use Assetic\Filter\Yui\JsCompressorFilter as YuiCompressorFilter;
$js = new AssetCollection(array(
new FileAsset(__DIR__.'/jquery.js'),
new FileAsset(__DIR__.'/application.js'),
), array(
new YuiCompressorFilter('/path/to/yuicompressor.jar'),
));
header('Content-Type: application/js');
echo $js->dump();
HTMLテンプレート側では、単に`<script>`タグを用いて、生成されたJavascriptをインクルードすることになります。
<script src="/assets/javascripts.php"></script>
Next: [コンセプト](concepts.md)
Assetic OOP APIを使用するためには、まず、[アセット」と「フィルタ」の2つの重要なコンセプトを理解する必要があります。
### アセット
アセットとは、読み込み、及びダンプが可能な、コンテンツとメタデータを内包しているオブジェクトの事を指します。
大体の場合において3つのカテゴリー、すなわち、Javascriptとスタイルシート、画像のどれかに属することになるでしょう。
読み込みの方法としては、ファイルシステムからがほとんどですが、
HTTPやデータベース経由でも、文字列としてでも読み込みが可能で、事実上あらゆるものが読み込み可能です。
Asseticのアセットインターフェースを満足させさえすれば良いのです。
### フィルタ
フィルタは、アセットが読み込まれる、かつ/もしくは、ダンプされる際に、
アセットコンテンツに対して作用するオブジェクトです。
アセットと同様に、Asseticのフィルタインターフェースを実装することで、
どのような作用も可能になります。
フィルタを用いて、アセットに適用できるツール群の一覧です。
* CoffeeScript
* CssEmbed
* CssMin
* Google Closure Compiler
* jpegoptim
* jpegtran
* Less
* LessPHP
* optipng
* Packager
* pngout
* SASS
* Sprockets (version 1)
* Stylus
* YUI Compressor
### アセットとフィルタの使用
まずはアセットオブジェクトを作成することから始まります。
多くの場合は`FileAsset`をインスタンス化し、ファイルシステムのパスを第一引数に渡します。
$asset = new Assetic\Asset\FileAsset('/path/to/main.css');
アセットオブジェクトを作成したら、`ensureFilter()`を呼び、フィルタを追加します。
例えば、アセットコンテンツにYUI Compressorを適用してみましょう。
$yui = new Assetic\Filter\Yui\CssCompressorFilter('/path/to/yui.jar');
$asset->ensureFilter($yui);
任意のフィルタを追加したら、完成したアセットをブラウザに出力してみましょう。
header('Content-Type: text/css');
echo $asset->dump();
### アセットコレクション
1つのファイルに同じ種類のアセットをまとめて、不要なHTTPリクエストを抑えてみるのも良いでしょう。
Asseticでは`AsseticColletion`クラスを使用することで可能となります。
Assetic内部的には、このクラス自体は他のアセットと同様に、アセットインターフェースを実装したものですが、
複数のアセットを1つにまとめることが可能になります。
use Assetic\Asset\AssetCollection;
$asset = new AssetCollection(array(
new FileAsset('/path/to/js/jquery.js'),
new FileAsset('/path/to/js/jquery.plugin.js'),
new FileAsset('/path/to/js/application.js'),
));
### ネストしたアセットコレクション
コレクションクラス自体がアセットインターフェースを実装し、コレクション内のアセットも同様に
アセットインターフェースを実装しているので、簡単にネストすることができます。
use Assetic\Asset\AssetCollection;
use Assetic\Asset\GlobAsset;
use Assetic\Asset\HttpAsset;
$asset = new AssetCollection(array(
new HttpAsset('http://example.com/jquery.min.js'),
new GlobAsset('/path/to/js/*'),
));
`HttpAsset`は、HTTP経由でファイルを読み込むアセットクラス。
`GlobAsset`は、ファイルシステムのglobを基にファイル群を読み込むアセットコレクションクラス。
両者ともにアセットインターフェースを実装しています。
このネストしたアセットコレクションという概念は、コレクションそれぞれに異なる
フィルタ群を適用しようとしたときに、効果を発揮します。
例えば、スタイルシートがSAASで記述されたものと、vanilla CSSを用いて記述されたものからなる
アプリケーションを考えた場合、次のようにして、全てを1つのシームレスなCSSアセットにまとめることができます。
use Assetic\Asset\AssetCollection;
use Assetic\Asset\GlobAsset;
use Assetic\Filter\SassFilter;
use Assetic\Filter\Yui\CssCompressorFilter;
$css = new AssetCollection(array(
new GlobAsset('/path/to/sass/*.sass', array(new SassFilter())),
new GlobAsset('/path/to/css/*.css'),
), array(
new YuiCompressorFilter('/path/to/yuicompressor.jar'),
));
上記の例では、1つにまとめられたCSSを、さらにYUI compressorフィルタを適用することで、全体を圧縮しています。
### アセットコレクションのイテレーション
アセットコレクションは、旧来のPHP配列のように、イテレートできます。
echo "Source paths:\n";
foreach ($collection as $asset) {
echo ' - '.$asset->getSourcePath()."\n";
}
アセットコレクションのイテレーションは再帰的で、「葉」にあたるアセットの取得を行います。
また、気の利いたフィルタを内蔵しているので、同じアセットがコレクション内に複数存在する場合でも、
一度だけのインクルードが保証されます。
Next: [アセットを「オンザフライ」で定義する](define.md)
アセットの「オンザフライ」な定義
----------------------------------------
Asseticの使用方法二つ目は、独立したPHPファイルを使用する代わりに、
テンプレートで「オンザフライ」にアセット定義をする方法です。
このアプローチでは、PHPテンプレートは下記のようになります。
<script src="<?php echo assetic_javascripts('js/*', 'yui_js') ?>"></script>
`assetic_javascripts()`の呼び出しは2つの目的を兼ねています。
まず、「フォーミュラローダー」により走査され、アセットの構築、ダンプ、及び出力を行うための「フォーミュラ(処方箋)」が抽出されます。
また、テンプレートのレンダー時にも実行され、アセットの出力パスが出力されます。
Asseticには下記のようなヘルパー関数があります。
* `assetic_image()`
* `assetic_javascripts()`
* `assetic_stylesheets()`
アセットをオンザフライに定義するということは、より高度なテクニックであり、
そのため、重い仕事をするサービスに依存することになります。
そのうちの重要なものがアセットファクトリです。
### アセットファクトリ
アセットファクトリは、アセットオブジェクトを、配列とスカラ値のみから、
どのように作成するのか把握しています。
`assetic_*`ヘルパー関数で使用する記法と同様のものとなります。
use Assetic\Factory\AssetFactory;
$factory = new AssetFactory('/path/to/web');
$js = $factory->createAsset(array(
'js/jquery.js',
'js/jquery.plugin.js',
'js/application.js',
));
### フィルタマネージャー
ファクトリによって作成されたアセットに対しても、フィルタを適用することができます。
そのためには、`FilterManager`を設定して、名前を定義しフィルタを構成します。
use Assetic\FilterManager;
use Assetic\Filter\GoogleClosure\ApiFilter as ClosureFilter;
$fm = new FilterManager();
$fm->set('closure', new ClosureFilter());
$factory->setFilterManager($fm);
$js = $factory->createAsset('js/*', 'closure');
上記の例では、Google Closure Compilerフィルタをインスタンス化し、
フィルタマネージャーを通じて`closure`という名前をつけています。
このフィルタマネージャーをアセットファクトリに渡すことで、
アセット作成時には、`closure`という名前でフィルタを使用できるようになります。
### デバッグモード
アセットファクトリは、デバッグモードというコンセプトも取り入れており、
デバッグモードの設定により、ファクトリが作成するアセットから、
特定のフィルタを除外することができます。
たとえば、YUI Compressorは大変素晴らしいのですが、圧縮されたJavascriptを
デバッグするのは大変難しく、プロダクション環境でのみの使用が適切でしょう。
use Asset\Factory\AssetFactory;
$factory = new AssetFactory('/path/to/web', true); // デバッグモードON
$factory->setFilterManager($fm);
$js = $factory->createAsset('js/*', '?closure');
フィルタ名`closure`の前にクエスチョンマークを記述すると、ファクトリに対して、
このフィルタはオプションであり、
デバッグモードがOFFの時にのみ適用するように通知することができます。
### アセットマネージャーとアセットリファレンス
アセットファクトリにはもう一つ特別な記法があり、別の場所で定義した
アセットを参照することができるようになります。
これを「アセットリファレンス」と呼び、アセットマネージャーを通じて、
フィルタマネージャーと同様の、名前によるアセットの構成が可能です。
use Assetic\AssetManager;
use Assetic\Asset\FileAsset;
use Assetic\Factory\AssetFactory;
$am = new AssetManager();
$am->set('jquery', new FileAsset('/path/to/jquery.js'));
$factory = new AssetFactory('/path/to/web');
$factory->setAssetManager($am);
$js = $factory->createAsset(array(
'@jquery',
'js/application.js',
));
### テンプレートからのアセット抽出
テンプレート内でアセット群を定義したら、「フォーミュラローダー」サービスを使用して、
アセットの定義を抽出します。
use Assetic\Factory\Loader\FunctionCallsFormulaLoader;
use Assetic\Factory\Resource\FileResource;
$loader = new FunctionCallsFormulaLoader($factory);
$formulae = $loader->load(new FileResource('/path/to/template.php'));
これらのフォーミュラ自体は、それ自体で使途はあまりなく、
アセットファクトリが目的のアセットオブジェクトを作成するに足る情報しか持っていません。
`LazyAssetManager`でラップすることで有益なものとなります。
### レイジーなアセットマネージャー
このサービスは、アセットファクトリと、1つ以上のフォーミュラローダーから成っており、
裏方のサービス間のグルとして動作しますが、表面上では、通常のアセットマネージャーと同じように使用することができます。
use Assetic\Asset\FileAsset;
use Assetic\Factory\LazyAssetManager;
use Assetic\Factory\Loader\FunctionCallsFormulaLoader;
use Assetic\Factory\Resource\DirectoryResource;
$am = new LazyAssetManager($factory);
$am->set('jquery', new FileAsset('/path/to/jquery.js'));
$am->setLoader('php', new FunctionCallsFormulaLoader($factory));
$am->addResource(new DirectoryResource('/path/to/templates', '/\.php$/'), 'php');
### アセットライター
作成したアセットマネージャーが、テンプレート内で定義した全てのアセットを把握したら、
アセットライターを使用して、テンプレートが参照することになる実際のファイルを作成します。
use Assetic\AssetWriter;
$writer = new AssetWriter('/path/to/web');
$writer->writeManagerAssets($am);
上記のスクリプトを実行すると、アセットマネージャー内のすべてのアセットがメモリに読み込まれ、
指定したフィルタが適用された後、公開領域に静的ファイルとしてダンプされ、準備完了となります。
目次
-----
1. [イントロダクション](introduction.md)
2. [アセットの構築とダンプ](build.md)
3. [コンセプト](concepts.md)
4. [アセットを「オンザフライ」で定義する](define.md)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment