2015-05-15 23 views
6

Mam pewne problemy z uzyskaniem atrybucyjnego filtru sass do pracy z node-sass zamiast z alternatywą ruby. Mam następującą konfigurację w moim pliku config.yml:Symfony asset sass filter via node-sass?

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)%" 

Chociaż ta wyzwala odpowiednią komendę node-sass, nie jestem pewien, że konfiguracja jest poprawna. Jeśli usuniemy ruby: null, spróbuję uruchomić C:\Program Files...\path\to\ruby.exe %%USERPROFILE%%\\AppData\\Roaming\\npm\\node-sass, co jest całkowicie błędne. Ale posiadanie ruby: null również nie rozwiązuje problemu, ponieważ ustawia błędne argumenty (tj. --load-path zamiast --include-path), które również psują rzeczy.

Czy ktoś wie, jak ustawić filtr sass za pomocą node zamiast ruby?

Odpowiedz

5

Chciałbym udostępnić moje rozwiązanie tego problemu każdemu, kto również może go doświadczać.

Wygląda na to, że BaseSassFilter nadaje się do pracy tylko z wersją ruby. Dlatego postanowiłem stworzyć własny filtr. Oto moja klasa:

<?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) 
    { 
    } 
} 

Następnie w config.yml dodać następujące:

assetic: 
    filters: 
     nodesass: 
      bin: "%sass.bin%" 
      resource: '%kernel.root_dir%/config/filters/nodesass.xml' 
      style: compressed 
      apply_to: "\.scss%" 

W app/config/filters/nodesass.xml dodać następujące 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> 

ten powinien dostać rzeczy działa na teraz.

+0

Dobra robota. Powinno to nastąpić w repozytorium aktywów, ja również zarządzam aktywami głównie za pośrednictwem węzła bez rubinu. – gremo

+0

Sprawdzę, czy jeszcze nie naprawili tego w najnowszych wersjach i zrobili PR, gdy mam trochę czasu w tej sprawie. :) – tftd

+0

OK i tak dziękuję - spędziłem kilka godzin mieszając się z load-path (ruby sass) vs load-import (node-sass) ... aby w końcu zdać sobie sprawę, że filtry sass mają być używane z rubinami :) – gremo