├── .gitignore
├── .travis.yml
├── composer.json
├── phpunit.xml
├── readme.md
├── src
├── Barryvdh
│ └── Assetic
│ │ ├── AsseticServiceProvider.php
│ │ ├── CheckedAssetWriter.php
│ │ ├── Console
│ │ └── AsseticBuildCommand.php
│ │ └── Dumper.php
└── config
│ ├── .gitkeep
│ └── config.php
└── tests
└── .gitkeep
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | composer.phar
3 | composer.lock
4 | .DS_Store
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.3
5 | - 5.4
6 | - 5.5
7 |
8 | before_script:
9 | - curl -s http://getcomposer.org/installer | php
10 | - php composer.phar install --dev
11 |
12 | script: phpunit
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "barryvdh/laravel-assetic",
3 | "description": "",
4 | "authors": [
5 | {
6 | "name": "Barry vd. Heuvel",
7 | "email": "barryvdh@gmail.com"
8 | }
9 | ],
10 | "require": {
11 | "php": ">=5.3.0",
12 | "illuminate/support": "4.x",
13 | "kriswallsmith/assetic": "~1.2",
14 | "symfony/finder": "~2.3"
15 | },
16 | "suggest": {
17 | "twig/twig": "~1.14"
18 | },
19 | "autoload": {
20 | "psr-0": {
21 | "Barryvdh\\Assetic": "src/"
22 | }
23 | },
24 | "extra": {
25 | "branch-alias": {
26 | "dev-master": "0.1-dev"
27 | }
28 | },
29 | "minimum-stability": "dev"
30 | }
31 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 | ./tests/
16 |
17 |
18 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | ## Assetic for Laravel
2 |
3 | A ServiceProvider based on https://github.com/mheap/Silex-Assetic
4 |
5 | Install via composer, add the ServiceProvider and configure assets/filters in the config.
6 |
7 | Add this package to composer.json
8 |
9 | "require": {
10 | ..
11 | "barryvdh/laravel-assetic": "0.1.x"
12 | }
13 |
14 | And run `composer update`. If you get the error, **barryvdh/laravel-assetic dev-master requires kriswallsmith/assetic ~1.2 -> no matching package found**, you might need to add or change your composer.json settings to the following:
15 |
16 | {
17 |
18 | ...
19 | "minimum-stability": "dev",
20 | "prefer-stable": true
21 |
22 | }
23 |
24 |
25 | Then add the ServiceProvider to the providers array in app/config/app.php
26 |
27 | 'providers' => array(
28 | ..
29 | 'Barryvdh\Assetic\AsseticServiceProvider',
30 | )
31 |
32 | Finally publish the config file (`php artisan config:publish barryvdh/laravel-assetic`) and add your filters to the config.
33 |
34 | // app/config/packages/barryvdh/laravel-assetic/config.php
35 | 'filter_manager' => function(FilterManager $fm){
36 | $fm->set('less', new \Assetic\Filter\LessphpFilter());
37 | $fm->set('cssmin', new Assetic\Filter\CssMinFilter);
38 | $fm->set('jsmin', new Assetic\Filter\JSMinFilter);
39 | $fm->set('cssrewrite', new Assetic\Filter\CssRewriteFilter());
40 | },
41 |
42 |
43 | When Twig is installed, the Assetic Extension can be used. Be sure to include the AsseticServiceProvider AFTER the TwigServiceProvider
44 |
--------------------------------------------------------------------------------
/src/Barryvdh/Assetic/AsseticServiceProvider.php:
--------------------------------------------------------------------------------
1 | app;
40 |
41 | /**
42 | * Asset Factory configuration happens here
43 | */
44 | $app['assetic'] = $app->share(function () use ($app) {
45 | $app['assetic.path_to_web'] = $app['config']->get('laravel-assetic::config.path_to_web');
46 | if( $app['config']->has('laravel-assetic::config.path_to_source')){
47 | $app['assetic.path_to_source'] = $app['config']->get('laravel-assetic::config.path_to_source');
48 | }
49 | $app['assetic.options'] = $app['config']->get('laravel-assetic::config.options');
50 |
51 | // initializing lazy asset manager
52 | if (isset($app['assetic.formulae']) &&
53 | !is_array($app['assetic.formulae']) &&
54 | !empty($app['assetic.formulae'])
55 | ) {
56 | $app['assetic.lazy_asset_manager'];
57 | }
58 |
59 | return $app['assetic.factory'];
60 | });
61 |
62 | /**
63 | * Factory
64 | *
65 | * @return \Assetic\Factory\AssetFactory
66 | */
67 | $app['assetic.factory'] = $app->share(function () use ($app) {
68 | $root = isset($app['assetic.path_to_source']) ? $app['assetic.path_to_source'] : $app['assetic.path_to_web'];
69 | $factory = new AssetFactory($root, $app['assetic.options']['debug']);
70 | $factory->setAssetManager($app['assetic.asset_manager']);
71 | $factory->setFilterManager($app['assetic.filter_manager']);
72 |
73 |
74 | if($app['config']->get('laravel-assetic::config.cachebusting') and ! $app['assetic.options']['debug'] ){
75 | $factory->addWorker(new CacheBustingWorker());
76 | }
77 |
78 |
79 | return $factory;
80 | });
81 |
82 | /**
83 | * Asset writer, writes to the 'assetic.path_to_web' folder
84 | *
85 | * @return \Assetic\AssetWriter
86 | */
87 | $app['assetic.asset_writer'] = $app->share(function () use ($app) {
88 | return new CheckedAssetWriter($app['assetic.path_to_web']);
89 | });
90 |
91 | /**
92 | * Asset manager
93 | *
94 | * @return \Assetic\AssetManager
95 | */
96 | $app['assetic.asset_manager'] = $app->share(function () use ($app) {
97 | $am = new AssetManager();
98 | if($app['config']->has('laravel-assetic::config.asset_manager')){
99 | $callback = $app['config']->get('laravel-assetic::config.asset_manager');
100 | if(is_callable($callback)){
101 | $callback($am);
102 | }
103 | }
104 | return $am;
105 | });
106 |
107 | /**
108 | * Filter manager
109 | *
110 | * @return \Assetic\FilterManager
111 | */
112 | $app['assetic.filter_manager'] = $app->share(function () use ($app) {
113 | $fm = new FilterManager();
114 |
115 | if($app['config']->has('laravel-assetic::config.filter_manager')){
116 | $callback = $app['config']->get('laravel-assetic::config.filter_manager');
117 | if(is_callable($callback)){
118 | $callback($fm);
119 | }
120 | }
121 |
122 | return $fm;
123 | });
124 |
125 | /**
126 | * Lazy asset manager for loading assets from $app['assetic.formulae']
127 | * (will be later maybe removed)
128 | */
129 | $app['assetic.lazy_asset_manager'] = $app->share(function () use ($app) {
130 | $formulae = isset($app['assetic.formulae']) ? $app['assetic.formulae'] : array();
131 | $options = $app['assetic.options'];
132 | $lazy = new LazyAssetmanager($app['assetic.factory']);
133 |
134 | if (empty($formulae)) {
135 | return $lazy;
136 | }
137 |
138 | foreach ($formulae as $name => $formula) {
139 | $lazy->setFormula($name, $formula);
140 | }
141 |
142 | if ($options['formulae_cache_dir'] !== null && $options['debug'] !== true) {
143 | foreach ($lazy->getNames() as $name) {
144 | $lazy->set($name, new AssetCache(
145 | $lazy->get($name),
146 | new FilesystemCache($options['formulae_cache_dir'])
147 | ));
148 | }
149 | }
150 |
151 | return $lazy;
152 | });
153 |
154 | $app['assetic.dumper'] = $app->share(function () use ($app) {
155 | return new Dumper(
156 | $app['assetic.asset_manager'],
157 | $app['assetic.lazy_asset_manager'],
158 | $app['assetic.asset_writer'],
159 | $app['view']->getFinder()
160 | );
161 | });
162 |
163 | $app['command.assetic.build'] = $app->share(function($app)
164 | {
165 | return new Console\AsseticBuildCommand();
166 | });
167 | $this->commands('command.assetic.build');
168 | }
169 |
170 | public function boot(){
171 | $app = $this->app;
172 | $this->package('barryvdh/laravel-assetic');
173 |
174 | // Register our filters to use
175 | if (isset($app['assetic.filters']) && is_callable($app['assetic.filters'])) {
176 | $app['assetic.filters']($app['assetic.filter_manager']);
177 | }
178 |
179 | if (isset($app['twig'])) {
180 | $app['twig']->addExtension(new AsseticExtension($app['assetic']));
181 |
182 | $app->extend('assetic.lazy_asset_manager', function ($am, $app) {
183 | $am->setLoader('twig', new TwigFormulaLoader($app['twig']));
184 | return $am;
185 | });
186 |
187 | $app->extend('assetic.dumper', function ($helper, $app) {
188 | $helper->setTwig($app['twig'], $app['twig.loader']);
189 | return $helper;
190 | });
191 | }
192 |
193 | /**
194 | * Writes down all lazy asset manager and asset managers assets
195 | */
196 | $app->after(function () use ($app) {
197 | // Boot assetic
198 | $assetic = $app['assetic'];
199 |
200 | if (!isset($app['assetic.options']['auto_dump_assets']) ||
201 | !$app['assetic.options']['auto_dump_assets']) {
202 | return;
203 | }
204 | $helper = $app['assetic.dumper'];
205 | if (isset($app['twig'])) {
206 | $helper->addTwigAssets();
207 | }
208 | $helper->dumpAssets();
209 | });
210 | }
211 |
212 | /**
213 | * Get the services provided by the provider.
214 | *
215 | * @return array
216 | */
217 | public function provides()
218 | {
219 | return array('assetic', 'assetic.factory', 'assetic.dumper', 'assetic.filters',
220 | 'assetic.asset_manager', 'assetic.filtermanager', 'assetic.lazy_asset_manager',
221 | 'assetic.asset_writer', 'command.assetic.build');
222 | }
223 |
224 | }
225 |
--------------------------------------------------------------------------------
/src/Barryvdh/Assetic/CheckedAssetWriter.php:
--------------------------------------------------------------------------------
1 |
13 | * @author Johannes M. Schmitt
14 | */
15 | class CheckedAssetWriter extends AssetWriter
16 | {
17 | private $dir;
18 | private $values;
19 |
20 | /**
21 | * Constructor.
22 | *
23 | * @param string $dir The base web directory
24 | * @param array $values Variable values
25 | *
26 | * @throws \InvalidArgumentException if a variable value is not a string
27 | */
28 | public function __construct($dir, array $values = array())
29 | {
30 | foreach ($values as $var => $vals) {
31 | foreach ($vals as $value) {
32 | if (!is_string($value)) {
33 | throw new \InvalidArgumentException(sprintf('All variable values must be strings, but got %s for variable "%s".', json_encode($value), $var));
34 | }
35 | }
36 | }
37 |
38 | $this->dir = $dir;
39 | $this->values = $values;
40 | }
41 |
42 |
43 | public function writeAsset(AssetInterface $asset)
44 | {
45 | foreach (VarUtils::getCombinations($asset->getVars(), $this->values) as $combination) {
46 | $asset->setValues($combination);
47 |
48 | $path = $this->dir.'/'.VarUtils::resolve(
49 | $asset->getTargetPath(),
50 | $asset->getVars(),
51 | $asset->getValues()
52 | );
53 |
54 | if (!is_dir($path) && (!file_exists($path) || filemtime($path) <= $asset->getLastModified())){
55 | static::write(
56 | $path,
57 | $asset->dump()
58 | );
59 | }
60 | }
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/Barryvdh/Assetic/Console/AsseticBuildCommand.php:
--------------------------------------------------------------------------------
1 | info('Starting Assetic building..');
45 | $app = $this->laravel;
46 |
47 | // Boot assetic
48 | $assetic = $app['assetic'];
49 |
50 | $helper = $app['assetic.dumper'];
51 | if (isset($app['twig'])) {
52 | $helper->addTwigAssets();
53 | }
54 | $helper->dumpAssets();
55 |
56 | $this->info('Done building assets!');
57 |
58 | }
59 |
60 |
61 |
62 | /**
63 | * Get the console command arguments.
64 | *
65 | * @return array
66 | */
67 | protected function getArguments()
68 | {
69 | return array();
70 | }
71 |
72 | /**
73 | * Get the console command options.
74 | *
75 | * @return array
76 | */
77 | protected function getOptions()
78 | {
79 | return array();
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/Barryvdh/Assetic/Dumper.php:
--------------------------------------------------------------------------------
1 | viewfinder = $viewfinder;
58 | $this->am = $am;
59 | $this->lam = $lam;
60 | $this->writer = $writer;
61 |
62 | }
63 |
64 | /**
65 | * @param \Twig_Environment $twig
66 | * @param \Twig_Loader_Filesystem $loader
67 | */
68 | public function setTwig(\Twig_Environment $twig, \Twig_LoaderInterface $loader)
69 | {
70 | $this->twig = $twig;
71 | $this->loader = $loader;
72 | }
73 |
74 | /**
75 | * Locates twig templates and adds their defined assets to the lazy asset manager
76 | */
77 | public function addTwigAssets()
78 | {
79 | if (!$this->twig instanceof \Twig_Environment) {
80 | throw new \LogicException('Twig environment not set');
81 | }
82 |
83 | $finder = new Finder();
84 | $viewfinder = $this->viewfinder;
85 |
86 | if ( count($viewfinder->getPaths()) > 0 ) {
87 | $iterator = $finder->files()->in($viewfinder->getPaths());
88 |
89 | foreach ($iterator as $file) {
90 | $resource = new TwigResource($this->loader, $file->getRelativePathname());
91 | $this->lam->addResource($resource, 'twig');
92 | }
93 | }
94 | }
95 |
96 | /**
97 | * Dumps all the assets
98 | */
99 | public function dumpAssets()
100 | {
101 | $this->dumpManagerAssets($this->am);
102 | $this->dumpManagerAssets($this->lam);
103 | }
104 |
105 | /**
106 | * Dumps the assets of given manager
107 | *
108 | * Doesn't use AssetWriter::writeManagerAssets since we also want to dump non-combined assets
109 | * (for example, when using twig extension in debug mode).
110 | *
111 | * @param AssetManager $am
112 | */
113 | protected function dumpManagerAssets(AssetManager $am)
114 | {
115 | foreach ($am->getNames() as $name) {
116 | $asset = $am->get($name);
117 |
118 | if ($am instanceof LazyAssetManager) {
119 | $formula = $am->getFormula($name);
120 | }
121 |
122 | $this->writer->writeAsset($asset);
123 |
124 | if (!isset($formula[2])) {
125 | continue;
126 | }
127 |
128 | $debug = isset($formula[2]['debug']) ? $formula[2]['debug'] : $am->isDebug();
129 | $combine = isset($formula[2]['combine']) ? $formula[2]['combine'] : null;
130 |
131 | if (null !== $combine ? !$combine : $debug) {
132 | foreach ($asset as $leaf) {
133 | $this->writer->writeAsset($leaf);
134 | }
135 | }
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/src/config/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/barryvdh/laravel-assetic/827f2223d4b0b314705a3b7387a2ff06546ba6f8/src/config/.gitkeep
--------------------------------------------------------------------------------
/src/config/config.php:
--------------------------------------------------------------------------------
1 | true,
19 |
20 | 'options' => array(
21 |
22 | 'debug' => \Config::get('app.debug'),
23 |
24 | 'formulae_cache_dir' => storage_path().'/cache/assetic',
25 |
26 | 'auto_dump_assets' => \Config::get('app.debug')
27 |
28 | ),
29 |
30 | /*
31 | |--------------------------------------------------------------------------
32 | | Filter Manager
33 | |--------------------------------------------------------------------------
34 | |
35 | | A filter manager is also provided for organizing filters.
36 | |
37 | */
38 | 'filter_manager' => function(FilterManager $fm){
39 | // $fm->set('sass', new SassFilter('/path/to/parser/sass'));
40 | // $fm->set('yui_css', new Yui\CssCompressorFilter('/path/to/yuicompressor.jar'));
41 | },
42 |
43 | /*
44 | |--------------------------------------------------------------------------
45 | | Asset Manager
46 | |--------------------------------------------------------------------------
47 | |
48 | | An asset manager is provided for organizing assets.
49 | |
50 | */
51 | 'asset_manager' => function(AssetManager $am){
52 | // $am->set('jquery', new FileAsset('/path/to/jquery.js'));
53 | // $am->set('base_css', new GlobAsset('/path/to/css/*'));
54 | },
55 |
56 | 'path_to_web' => public_path(),
57 |
58 | //'path_to_source' => public_path(), // When path_to_source is not set, it is the same as path_to_web
59 |
60 |
61 | );
62 |
--------------------------------------------------------------------------------
/tests/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/barryvdh/laravel-assetic/827f2223d4b0b314705a3b7387a2ff06546ba6f8/tests/.gitkeep
--------------------------------------------------------------------------------