A Robo Less taskjának kibővítése

A Robo egy egyszerű és elegáns feladat végrehajtó. A Less taskja szintén egyszerű, de inkább buta, mint elegáns. Ha a less fájlok különböző mappák között vannak szétszórva, akkor két megoldás közül választhatunk. Vagy CSS fordítás előtt átírjuk a fájlokat vagy kibővítjük a Less taskot és felokosítjuk.

A problémába nagyon hamar bele lehet ütközni, elég ha két külön mappában tároljuk a less fájlokat, a fordító scriptet pedig egy harmadikban. Vegyük a következő szerkezetet:

  • css mappa
    • bootstrap mappa
      • bootstrap.less
    • testreszabott css mappa
      • main.less
  • RoboFile.php

A fájlszerkezetben kínálja magát a megoldás, hogy a main.less fájlban relatívan hivatkozzunk a testvérmappában lévő fájlokra, pl. így:

/* töltsük be a bootstrap fájlokat */
@import "../bootstrap/bootstrap.less";

Azonban ha nekiállunk a beépített (0.5.3-as verziónál) Less taskkal fordítani a fájlokat, hibaüzenet fog minket fogadni:

[Less_Exception_Parser]
  File `../bootstrap/bootstrap.less` not found.

Az egyik megoldás az lenne, hogy fordítás előtt lecseréljük az összes elérési utat vagy abszolútra vagy a fordító scripthez képest relatívra. Ebben segítségünkre lehet a Replace task.

A másik megoldás, hogy kibővítjük és felokosítjuk a Less taskot. Ez már félig rendelkezésünkre is áll, mert a Less task által használt less.php támogatja az útvonalak behelyettesítését.

Új, okosabb Less compiler hozzáadásához szükségünk lesz egy traitre és egy LessTaskot kibővítő osztályra:

trait MyLess
{
    function taskMyLess($input)
    {
        return new MyLessTask($input);
    }
}

class MyLessTask extends \Robo\Task\Assets\Less
{
    protected $directories = [];

    protected function myless($file)
    {
        $lessCode = file_get_contents($file);
        $parser = new Less_Parser();
        $parser->SetImportDirs($this->directories);
        $parser->parse($lessCode);
        return $parser->getCss();
    }

    public function setImportPaths($paths) {
        $this->directories = $paths;
        return $this;
    }

    protected function lessCompilers()
    {
        return [
            'lessphp', //https://github.com/leafo/lessphp
            'less', // https://github.com/oyejorge/less.php,
            'myless', // https://github.com/oyejorge/less.php, but with advanced options
        ];
    }
}

A kódon látjuk, hogy az eredeti Less taskot kibővítettük egy setImportPaths nevű metódussal, amit felhasználhatunk a fordítás során, hogy megadjuk a less.php fordítónak az útvonalakat. Az új feladatot így használhatjuk fel:

class RoboFile extends \Robo\Tasks
{
    // használjuk az új taskunkat
    use MyLess;

    public function makecss () {
        $this->taskMyLess([
            'css/testreszabott css mappa/main.less' => 'dist/main.css'
        ])
        ->setImportPaths([
            '/var/www/project/css/bootstrap'=>'../bootstrap',
        ])
        ->compiler('myless')
        ->run();
    }
}

Ezt meghívva már sikeres fordítást kell kapnunk:

[MyLessTask] Wrote CSS to dist/main.css

A kódot alapul véve nagyon egyszerűen létrehozhatunk más CSS fordítókat is, akár SCSS fordítót is. A bejegyzés írásának napjaiban merge-elve lett az Scss taskot létrehozó pull requestem, Scsshez nyugodtan használjuk azt.