From c897a4d5535d5f6f40bb35876653ccee828ad674 Mon Sep 17 00:00:00 2001 From: Igor Hlina Date: Thu, 21 Apr 2016 16:58:20 +0200 Subject: [PATCH 1/4] Create JS fixtures for Sprockets3 tests --- tests/Assetic/Test/Filter/fixtures/sprockets3/brokenDeps.js | 4 ++++ tests/Assetic/Test/Filter/fixtures/sprockets3/circular.js | 3 +++ tests/Assetic/Test/Filter/fixtures/sprockets3/circularBack.js | 3 +++ tests/Assetic/Test/Filter/fixtures/sprockets3/lib/bar/bar.js | 1 + tests/Assetic/Test/Filter/fixtures/sprockets3/lib/foo/foo.js | 1 + tests/Assetic/Test/Filter/fixtures/sprockets3/lib/main.js | 3 +++ tests/Assetic/Test/Filter/fixtures/sprockets3/require.js | 4 ++++ tests/Assetic/Test/Filter/fixtures/sprockets3/requireTree.js | 3 +++ 8 files changed, 22 insertions(+) create mode 100644 tests/Assetic/Test/Filter/fixtures/sprockets3/brokenDeps.js create mode 100644 tests/Assetic/Test/Filter/fixtures/sprockets3/circular.js create mode 100644 tests/Assetic/Test/Filter/fixtures/sprockets3/circularBack.js create mode 100644 tests/Assetic/Test/Filter/fixtures/sprockets3/lib/bar/bar.js create mode 100644 tests/Assetic/Test/Filter/fixtures/sprockets3/lib/foo/foo.js create mode 100644 tests/Assetic/Test/Filter/fixtures/sprockets3/lib/main.js create mode 100644 tests/Assetic/Test/Filter/fixtures/sprockets3/require.js create mode 100644 tests/Assetic/Test/Filter/fixtures/sprockets3/requireTree.js diff --git a/tests/Assetic/Test/Filter/fixtures/sprockets3/brokenDeps.js b/tests/Assetic/Test/Filter/fixtures/sprockets3/brokenDeps.js new file mode 100644 index 000000000..043fc94dd --- /dev/null +++ b/tests/Assetic/Test/Filter/fixtures/sprockets3/brokenDeps.js @@ -0,0 +1,4 @@ +//= require libxyz/main +//= require bar + +/* brokenDeps.js */ diff --git a/tests/Assetic/Test/Filter/fixtures/sprockets3/circular.js b/tests/Assetic/Test/Filter/fixtures/sprockets3/circular.js new file mode 100644 index 000000000..d4447c356 --- /dev/null +++ b/tests/Assetic/Test/Filter/fixtures/sprockets3/circular.js @@ -0,0 +1,3 @@ +//= require circularBack + +/* circular.js */ diff --git a/tests/Assetic/Test/Filter/fixtures/sprockets3/circularBack.js b/tests/Assetic/Test/Filter/fixtures/sprockets3/circularBack.js new file mode 100644 index 000000000..a386ef0ec --- /dev/null +++ b/tests/Assetic/Test/Filter/fixtures/sprockets3/circularBack.js @@ -0,0 +1,3 @@ +//= require circular + +/* circularBack.js */ diff --git a/tests/Assetic/Test/Filter/fixtures/sprockets3/lib/bar/bar.js b/tests/Assetic/Test/Filter/fixtures/sprockets3/lib/bar/bar.js new file mode 100644 index 000000000..37d49fa71 --- /dev/null +++ b/tests/Assetic/Test/Filter/fixtures/sprockets3/lib/bar/bar.js @@ -0,0 +1 @@ +/* lib/bar/bar.js */ diff --git a/tests/Assetic/Test/Filter/fixtures/sprockets3/lib/foo/foo.js b/tests/Assetic/Test/Filter/fixtures/sprockets3/lib/foo/foo.js new file mode 100644 index 000000000..33791f9e4 --- /dev/null +++ b/tests/Assetic/Test/Filter/fixtures/sprockets3/lib/foo/foo.js @@ -0,0 +1 @@ +/* lib/foo/foo.js */ diff --git a/tests/Assetic/Test/Filter/fixtures/sprockets3/lib/main.js b/tests/Assetic/Test/Filter/fixtures/sprockets3/lib/main.js new file mode 100644 index 000000000..f11be60be --- /dev/null +++ b/tests/Assetic/Test/Filter/fixtures/sprockets3/lib/main.js @@ -0,0 +1,3 @@ +//= require ./foo/foo + +/* lib/main.js */ diff --git a/tests/Assetic/Test/Filter/fixtures/sprockets3/require.js b/tests/Assetic/Test/Filter/fixtures/sprockets3/require.js new file mode 100644 index 000000000..54ae4c547 --- /dev/null +++ b/tests/Assetic/Test/Filter/fixtures/sprockets3/require.js @@ -0,0 +1,4 @@ +//= require lib/main +//= require bar + +/* require.js */ diff --git a/tests/Assetic/Test/Filter/fixtures/sprockets3/requireTree.js b/tests/Assetic/Test/Filter/fixtures/sprockets3/requireTree.js new file mode 100644 index 000000000..8a3243b74 --- /dev/null +++ b/tests/Assetic/Test/Filter/fixtures/sprockets3/requireTree.js @@ -0,0 +1,3 @@ +//= require_tree ./lib + +/* requireTree.js */ From 152a1e91fdf8ed2cd946e022b90a703e74d1e5ce Mon Sep 17 00:00:00 2001 From: Igor Hlina Date: Thu, 21 Apr 2016 16:58:31 +0200 Subject: [PATCH 2/4] Create CSS fixtures for Sprockets3 tests --- .../Test/Filter/fixtures/sprockets3/lib/bootstrap.css | 5 +++++ tests/Assetic/Test/Filter/fixtures/sprockets3/main.css | 3 +++ 2 files changed, 8 insertions(+) create mode 100644 tests/Assetic/Test/Filter/fixtures/sprockets3/lib/bootstrap.css create mode 100644 tests/Assetic/Test/Filter/fixtures/sprockets3/main.css diff --git a/tests/Assetic/Test/Filter/fixtures/sprockets3/lib/bootstrap.css b/tests/Assetic/Test/Filter/fixtures/sprockets3/lib/bootstrap.css new file mode 100644 index 000000000..cc1ca9dcc --- /dev/null +++ b/tests/Assetic/Test/Filter/fixtures/sprockets3/lib/bootstrap.css @@ -0,0 +1,5 @@ +/* bootstrap.css */ + +body { + background-color: #fff; +} diff --git a/tests/Assetic/Test/Filter/fixtures/sprockets3/main.css b/tests/Assetic/Test/Filter/fixtures/sprockets3/main.css new file mode 100644 index 000000000..6bc50e135 --- /dev/null +++ b/tests/Assetic/Test/Filter/fixtures/sprockets3/main.css @@ -0,0 +1,3 @@ +/*= require lib/bootstrap */ + +/* main.css */ From c4016e9fd0d524910c1358e574b2054830b0a072 Mon Sep 17 00:00:00 2001 From: Igor Hlina Date: Thu, 21 Apr 2016 16:59:00 +0200 Subject: [PATCH 3/4] Implement Sprockets3 filter, tests --- src/Assetic/Filter/Sprockets3Filter.php | 110 ++++++++++++++++++ .../Test/Filter/Sprockets3FilterTest.php | 105 +++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 src/Assetic/Filter/Sprockets3Filter.php create mode 100644 tests/Assetic/Test/Filter/Sprockets3FilterTest.php diff --git a/src/Assetic/Filter/Sprockets3Filter.php b/src/Assetic/Filter/Sprockets3Filter.php new file mode 100644 index 000000000..e246649e7 --- /dev/null +++ b/src/Assetic/Filter/Sprockets3Filter.php @@ -0,0 +1,110 @@ + + */ +class Sprockets3Filter extends BaseProcessFilter +{ + /** @var array */ + private $includeDirs = array(); + + /** @var string */ + private $rubyBin; + + /** @var NULL|string */ + private $sprockets3Lib; + + + /** + * @param string $sprocketsLib Path to the Sprockets lib/ directory + * @param string $rubyBin Path to the ruby binary + */ + public function __construct($sprocketsLib = null, $rubyBin = '/usr/bin/ruby') + { + $this->sprockets3Lib = $sprocketsLib; + $this->rubyBin = $rubyBin; + } + + /** + * @param string $directory + */ + public function addIncludeDir($directory) + { + $this->includeDirs[] = $directory; + } + + /** + * @param AssetInterface $asset + * @return string + */ + public function filterLoad(AssetInterface $asset) + { + $scriptSrc = <<sprockets3Lib) + ? sprintf("File.join(%s, 'sprockets')", var_export($this->sprockets3Lib, true)) + : "sprockets"; + $appends = array_reduce($this->includeDirs, function($memo, $dir) { + $memo .= 'environment.append_path('. var_export($dir, true) .")\n"; + return $memo; + }); + $script = FilesystemUtils::createTemporaryFile('sprockets3_script_'); + $scriptSrc = sprintf($scriptSrc, + $sprocket3LibImport, + $appends, + var_export(basename($asset->getSourcePath()), true) + ); + file_put_contents($script, $scriptSrc); + + $processBuilder = $this->createProcessBuilder(array($this->rubyBin, $script)); + $process = $processBuilder->getProcess(); + $exitCode = $process->run(); + unlink($script); + + if ($exitCode !== 0) { + throw FilterException::fromProcess($process)->setInput($asset->getContent()); + } + + $result = $process->getOutput(); + $asset->setContent($result); + + return $result; + } + + /** + * @param AssetInterface $asset + */ + public function filterDump(AssetInterface $asset) + { + } +} diff --git a/tests/Assetic/Test/Filter/Sprockets3FilterTest.php b/tests/Assetic/Test/Filter/Sprockets3FilterTest.php new file mode 100644 index 000000000..707fa21ad --- /dev/null +++ b/tests/Assetic/Test/Filter/Sprockets3FilterTest.php @@ -0,0 +1,105 @@ +findExecutable('ruby', 'RUBY_BIN')) { + $this->markTestSkipped('Unable to locate `ruby` executable.'); + } + + if (!isset($_SERVER['SPROCKETS3_LIB'])) { + $this->markTestSkipped('There is no SPROCKETS3_LIB environment variable.'); + } + + $this->filter = new Sprockets3Filter($_SERVER['SPROCKETS3_LIB'], $rubyBin); + } + + /** + * @expectedException \Assetic\Exception\FilterException + * @expectedExceptionMessageRegExp ~couldn't find file 'libxyz\/main'~ + */ + public function testFilerThrows() + { + $asset = new FileAsset(__DIR__ . '/fixtures/sprockets3/brokenDeps.js'); + $asset->load(); + + $this->filter->addIncludeDir(__DIR__ . '/fixtures/sprockets3'); + $this->filter->filterLoad($asset); + } + + public function testFilterLoad() + { + $asset = new FileAsset(__DIR__ . '/fixtures/sprockets3/require.js'); + $asset->load(); + + $this->filter->addIncludeDir(__DIR__ . '/fixtures/sprockets3'); + $this->filter->addIncludeDir(__DIR__ . '/fixtures/sprockets3/lib/bar'); + $this->filter->filterLoad($asset); + + $this->assertContains('/* lib/foo/foo.js */', $asset->getContent()); + $this->assertContains('/* lib/bar/bar.js */', $asset->getContent()); + $this->assertContains('/* lib/main.js */', $asset->getContent()); + $this->assertContains('/* require.js */', $asset->getContent()); + } + + public function testRequireTree() + { + $asset = new FileAsset(__DIR__ . '/fixtures/sprockets3/requireTree.js'); + $asset->load(); + + $this->filter->addIncludeDir(__DIR__ . '/fixtures/sprockets3'); + $this->filter->filterLoad($asset); + + $this->assertContains('/* lib/foo/foo.js */', $asset->getContent()); + $this->assertContains('/* lib/bar/bar.js */', $asset->getContent()); + $this->assertContains('/* lib/main.js */', $asset->getContent()); + $this->assertContains('/* requireTree.js */', $asset->getContent()); + } + + public function testCircularDeps() + { + $asset = new FileAsset(__DIR__ . '/fixtures/sprockets3/circular.js'); + $asset->load(); + + $this->filter->addIncludeDir(__DIR__ . '/fixtures/sprockets3'); + $this->filter->filterLoad($asset); + + $this->assertContains('/* circularBack.js */', $asset->getContent()); + $this->assertContains('/* circular.js */', $asset->getContent()); + } + + public function testCss() + { + $asset = new FileAsset(__DIR__ . '/fixtures/sprockets3/main.css'); + $asset->load(); + + $this->filter->addIncludeDir(__DIR__ . '/fixtures/sprockets3'); + $this->filter->filterLoad($asset); + + $this->assertContains('/* bootstrap.css */', $asset->getContent()); + $this->assertContains('/* main.css */', $asset->getContent()); + } +} From cbd26c789ba2b1252cbde3c9b868ef40579599a8 Mon Sep 17 00:00:00 2001 From: Igor Hlina Date: Thu, 21 Apr 2016 17:02:35 +0200 Subject: [PATCH 4/4] Update docs --- README.md | 1 + docs/en/concepts.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 7ec0058aa..c30827e32 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,7 @@ The core provides the following filters in the `Assetic\Filter` namespace: * `ScssphpFilter`: parses SCSS using scssphp * `SeparatorFilter`: inserts a separator between assets to prevent merge failures * `SprocketsFilter`: Sprockets Javascript dependency management + * `Sprockets3Filter`: Sprockets v3 Javascript/CSS dependency management * `StylusFilter`: parses STYL into CSS * `TypeScriptFilter`: parses TypeScript into Javascript * `UglifyCssFilter`: minifies CSS diff --git a/docs/en/concepts.md b/docs/en/concepts.md index 7af7b1f2f..0317ad3ac 100644 --- a/docs/en/concepts.md +++ b/docs/en/concepts.md @@ -32,6 +32,7 @@ filter: * pngout * SASS * Sprockets (version 1) + * Sprockets3 (version 3) * Stylus * YUI Compressor