Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/sprockets3 #801

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions docs/en/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ filter:
* pngout
* SASS
* Sprockets (version 1)
* Sprockets3 (version 3)
* Stylus
* YUI Compressor

Expand Down
110 changes: 110 additions & 0 deletions src/Assetic/Filter/Sprockets3Filter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php

/*
* This file is part of the Assetic package, an OpenSky project.
*
* (c) 2010-2014 OpenSky Project Inc
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Assetic\Filter;

use Assetic\Asset\AssetInterface;
use Assetic\Exception\FilterException;
use Assetic\Util\FilesystemUtils;

/**
* Runs assets through Sprockets3.
* Requires Sprockets 3.x.
*
* @link https://github.com/rails/sprockets/tree/3.x
* @link https://rubygems.org/gems/sprockets
*
* @author Igor Hlina <[email protected]>
*/
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 = <<<EOF
#!/usr/bin/env ruby

require %s

environment = Sprockets::Environment.new
%s

print environment.find_asset(%s)

EOF;
$sprocket3LibImport = ($this->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)
{
}
}
105 changes: 105 additions & 0 deletions tests/Assetic/Test/Filter/Sprockets3FilterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php

/*
* This file is part of the Assetic package, an OpenSky project.
*
* (c) 2010-2014 OpenSky Project Inc
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Assetic\Test\Filter;

use Assetic\Asset\FileAsset;
use Assetic\Filter\Sprockets3Filter;
use Assetic\Util\FilesystemUtils;

/**
* @group integration
*/
class Sprockets3FilterTest extends FilterTestCase
{
/** @var Sprockets3Filter */
private $filter;


protected function setUp()
{
if (!$rubyBin = $this->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());
}
}
4 changes: 4 additions & 0 deletions tests/Assetic/Test/Filter/fixtures/sprockets3/brokenDeps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//= require libxyz/main
//= require bar

/* brokenDeps.js */
3 changes: 3 additions & 0 deletions tests/Assetic/Test/Filter/fixtures/sprockets3/circular.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//= require circularBack

/* circular.js */
3 changes: 3 additions & 0 deletions tests/Assetic/Test/Filter/fixtures/sprockets3/circularBack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//= require circular

/* circularBack.js */
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* lib/bar/bar.js */
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* bootstrap.css */

body {
background-color: #fff;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* lib/foo/foo.js */
3 changes: 3 additions & 0 deletions tests/Assetic/Test/Filter/fixtures/sprockets3/lib/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//= require ./foo/foo

/* lib/main.js */
3 changes: 3 additions & 0 deletions tests/Assetic/Test/Filter/fixtures/sprockets3/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/*= require lib/bootstrap */

/* main.css */
4 changes: 4 additions & 0 deletions tests/Assetic/Test/Filter/fixtures/sprockets3/require.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//= require lib/main
//= require bar

/* require.js */
3 changes: 3 additions & 0 deletions tests/Assetic/Test/Filter/fixtures/sprockets3/requireTree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//= require_tree ./lib

/* requireTree.js */