The sass
extension for HHVM gives you an object-oriented system of parsing Sass from within your PHP applications. Under the hood it uses libsass, a C library to parse and compile sass/scss files that does not require ruby.
It is based on the sass extension for php.
Sass is a CSS pre-processor language to add on exciting, new, awesome features to CSS. Sass was the first language of its kind and by far the most mature and up to date codebase.
Sass was originally created by Hampton Catlin (@hcatlin). The extension and continuing evolution of the language has all been the result of years of work by Natalie Weizenbaum (@nex4) and Chris Eppstein (@chriseppstein).
For more information about Sass itself, please visit http://sass-lang.com
Requires HHVM 3.6 or later and either the hhvm source tree (use the variable $HPHP_HOME to point to your hhvm source tree) or the hhvm-dev package.
Update the submodule with
git submodule update --init --recursive
and then run
./build.sh
To enable the extension, you need to have the following section in your PHP ini file:
hhvm.dynamic_extension_path = /path/to/hhvm/extensions
hhvm.dynamic_extensions[sass] = sass.so
Where /path/to/hhvm/extensions
is a folder containing all HHVM extensions,
and sass.so
is in it. This will cause the extension to be loaded when the
virtual machine starts up.
To run the test suite:
$ cd /path/to/extension
$ ./test.sh
If you have the complete hhvm source tree you can run the tests with the test runner.
HPHP_HOME=/path/to/hhvm/source ./test.sh
This extension has a very simple API. You can find the entire API here.
$sass = new Sass();
$css = $sass->compile($source);
You can compile a file with compileFile()
:
$sass = new Sass();
$css = $sass->compileFile($file);
You can set the include path for the library to use:
$sass = new Sass();
$sass->addIncludePath('/tmp');
$css = $sass->compile($source);
The style of the compiled css can be changed:
$sass->setStyle(Sass::STYLE_EXPANDED)->setLinefeed("\r\n")->setIndent("\t");
Sass syntax is supported as well.
$sass->setSyntax(Sass::SYNTAX_SASS);
There are 2 ways to generate maps.
You can embed them in the compiled css as data uri ...
$css = $sass->embedMap(true)->compile($source);
or the map can be generated as a separate file as well.
$cssAndMap = $sass->compileFileWithMap($file);
// Or with an alternative map file name ...
// The file won't be written to the filesystem.
$cssAndMap = $sass->compileFileWithMap($file, $mapfile);
$cssAndMap
is a shape (an array for the runtime) containing the elements "css" and "map", where "css" contains the compiled css (duh) and "map" contains the source map output.
The sourceRoot property of the map files can be set with:
$css = $sass->setSourceRoot('/herp/derp/');
If there's a problem with compiling your SCSS or Sass, the extension will throw a SassException
:
$sass = new Sass();
try {
$css = $sass->compile('asdf');
} catch (SassException $e) {
// $e->getMessage() --> 'Invalid CSS after "asdf": expected "{", was ""'
$css = null;
}
SassException
has some additional methods to get more information about the compilation error like the sources file name, line and column number and a formatted error message.
$e->getSourceFile();
$e->getSourceLine();
$e->getSourceColumn();
$e->getFormattedMessage();
It is possible to provide custom functions and custom importers written in PHP to libsass which can be called from your sass source code.
$css = (new Sass())
->addFunction('inline-image($url)', function (ImmVector<SassValue> $args): SassValue {
// Missing a sensible amount of error checking and type checks.
$path = $args[0]->unquote(); // instanceof SassString
$img = file_get_contents((string)$path);
return (new SassString())->setValue('url("data:image/png;base64,'.base64_encode($img).'")');
})
->addImporter('http', function (string $curPath, string $prevPath): ?Traversable<?SassImport> {
// here the scss could be fetched with eg. curl
if (preg_match('/^https?:\/\//', $curPath)) {
return [
(new SassImport())
->setPath($curPath)
->setSource('.remote { border: 1px solid #000; }')
];
}
// let another importer or libsass handle the import.
return null;
}, 2)
->compile('
@import "http://example.org/scss/remote.scss";
#myimage {
background-image: inline-image("path/to/bg.png");
}
');
Result:
.remote {
border: 1px solid #000;
}
#myimage {
background-image: url("data:image/png;base64,iVBORw0KGgoA[...]mCC=");
}
For more details on how to use custom functions and custom importers please check out the tests directory.