I'm having some difficulties getting an assetic sass filter to work with node-sass
instead of the ruby alternative. I have the following configuration in my config.yml
file:
assetic:
debug: "%kernel.debug%"
use_controller: false
bundles: [ ]
write-to: "%kernel.root_dir%/../web/assets"
read_from: "%kernel.root_dir%/../web/assets"
node: "%%PROGRAMFILES%%\nodejs\\node.exe"
node_paths: ["%%USERPROFILE%%\\AppData\\Roaming\\npm\\node_modules"]
sass: "%%USERPROFILE%%\\AppData\\Roaming\\npm\\node-sass"
ruby: null
filters:
cssrewrite: ~
scss:
output-style: compressed
apply_to: "\.(scss|sass|css)%"
Although this triggers the right node-sass
command, I'm not sure the configuration is correct. If I remove ruby: null
it tries to run C:\Program Files...\path\to\ruby.exe %%USERPROFILE%%\\AppData\\Roaming\\npm\\node-sass
which is totally wrong. But having ruby: null
doesn't solve the problem as well, because it sets the wrong arguments (i.e --load-path
instead of --include-path
) and that messes things as well.
Does anybody know how to set the sass
filter with node
instead of ruby
?
I'd like to share my solution to this issue for anybody out there who might be experiencing it as well.
It appears that the BaseSassFilter
is suited to work only with the ruby version. So I decided to create my own filter. Here is my class:
<?php
namespace App\YourBundle\Assetic\Filter;
use Assetic\Asset\AssetInterface;
use Assetic\Exception\FilterException;
use Assetic\Filter\Sass\BaseSassFilter;
use Assetic\Filter\Sass\SassFilter;
/**
* This class is based on Assetic\Filter\Sass\SassFilter and is slightly modified to work with node-sass instead of Ruby.
*/
class NodeSassFilter extends BaseSassFilter
{
const STYLE_NESTED = 'nested';
const STYLE_EXPANDED = 'expanded';
const STYLE_COMPACT = 'compact';
const STYLE_COMPRESSED = 'compressed';
private $sassPath;
private $scss;
private $style;
private $quiet;
private $cacheLocation;
public function __construct($sassPath = '/usr/bin/node-sass')
{
$this->sassPath = $sassPath;
$this->cacheLocation = realpath(sys_get_temp_dir());
}
public function setScss($scss)
{
$this->scss = $scss;
}
public function setStyle($style)
{
$this->style = $style;
}
public function setQuiet($quiet)
{
$this->quiet = $quiet;
}
public function filterLoad(AssetInterface $asset)
{
$sassProcessArgs = array($this->sassPath);
$pb = $this->createProcessBuilder($sassProcessArgs);
if ($dir = $asset->getSourceDirectory()) {
$pb->add('--include-path')->add($dir);
}
if ($this->style) {
$pb->add('--output-style')->add($this->style);
}
if ($this->quiet) {
$pb->add('--quiet');
}
// input
$pb->add($input = tempnam(sys_get_temp_dir(), 'assetic_sass'));
file_put_contents($input, $asset->getContent());
$proc = $pb->getProcess();
$code = $proc->run();
unlink($input);
if (0 !== $code) {
throw FilterException::fromProcess($proc)->setInput($asset->getContent());
}
$asset->setContent($proc->getOutput());
}
public function filterDump(AssetInterface $asset)
{
}
}
Then, in your config.yml
you add the following:
assetic:
filters:
nodesass:
bin: "%sass.bin%"
resource: '%kernel.root_dir%/config/filters/nodesass.xml'
style: compressed
apply_to: "\.scss%"
In app/config/filters/nodesass.xml
you add the following xml:
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="assetic.filter.nodesass.class">App\YourBundle\Assetic\Filter\NodeSassFilter</parameter>
<parameter key="assetic.filter.nodesass.bin">%assetic.sass.bin%</parameter>
<parameter key="assetic.filter.nodesass.timeout">240</parameter>
<parameter key="assetic.filter.nodesass.style">null</parameter>
<parameter key="assetic.filter.nodesass.load_paths" type="collection" />
</parameters>
<services>
<service id="assetic.filter.nodesass" class="%assetic.filter.nodesass.class%">
<tag name="assetic.filter" alias="nodesass" />
<argument>%assetic.filter.nodesass.bin%</argument>
<call method="setTimeout"><argument>%assetic.filter.nodesass.timeout%</argument></call>
<call method="setStyle"><argument>%assetic.filter.nodesass.style%</argument></call>
<call method="setLoadPaths"><argument>%assetic.filter.nodesass.load_paths%</argument></call>
</service>
</services>
</container>
This should get things working for now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With