Skip to content

ringself/sass.js

 
 

Repository files navigation

Sass.js

Sass parser in JavaScript. This is a convenience API for emscripted libsass (at v3.1.0). If you're looking to run Sass in node, you're probably looking for node-sass. Sass.js and node-sass should generate the same results.

A fair warning: minified it's 2.2MB, gzipped it's 611KB. node-sass is about 20 times faster than Sass.js

see the live demo

Loading the Sass.js API

Sass.js comes in two flavors – the synchronous in-document sass.js and the asynchronous worker sass.worker.js. The primary API - wrapping the Emscripten runtime - is provided with sass.js (it is used internally by sass.worker.js as well). sass.worker.js mimics the same API (adding callbacks for the asynchronous part) and passes all the function calls through to the web worker.

<script> // loading libsass.worker Sass.initialize('https://github.com/ringself/dist/worker.min.js'); var scss = '$someVar: 123px; .some-selector { width: $someVar; }'; Sass.compile(scss, function(css) { console.log(css); }); </script>">
<script src="dist/sass.worker.js"></script>
<script>
  // loading libsass.worker
  Sass.initialize('dist/worker.min.js');

  var scss = '$someVar: 123px; .some-selector { width: $someVar; }';
  Sass.compile(scss, function(css) {
      console.log(css);
  });
</script>

It is possible - but not recommended to use Sass.js without in the main RunLoop instead of using a Worker:

<script> var scss = '$someVar: 123px; .some-selector { width: $someVar; }'; var css = Sass.compile(scss); console.log(css); </script>">
<script src="dist/sass.min.js"></script>
<script>
  var scss = '$someVar: 123px; .some-selector { width: $someVar; }';
  var css = Sass.compile(scss);
  console.log(css);
</script>

You can - for debugging purposes - load sass.js from source files. Emscripten litters the global scope with ~400 variables, so this MUST never be used in production!

Note: you need to have run grunt build:libsass before this is possible

<script src=https://github.com/ringself/"src/sass.js"> <script> var scss = '$someVar: 123px; .some-selector { width: $someVar; }'; var css = Sass.compile(scss); console.log(css); </script>">
<script src="libsass/libsass/lib/libsass.js"></script>
<script src="src/sass.js"></script>
<script>
  var scss = '$someVar: 123px; .some-selector { width: $someVar; }';
  var css = Sass.compile(scss);
  console.log(css);
</script>

Using the Sass.js API

// compile text to SCSS
Sass.compile(text, function callback(result) {
  // (string) result is the compiled CSS
});

// set compile style options
Sass.options({
  // format output: nested, expanded, compact, compressed
  style: Sass.style.nested,
  // add line comments to output: none, default
  comments: Sass.comments.none
}, function callback(){});

// register a file to be available for @import
Sass.writeFile(filename, text, function callback(success) {
  // (boolean) success is
  //   `true` when the write was OK,
  //   `false` when it failed
});

// remove a file
Sass.removeFile(filename, function callback(success) {
  // (boolean) success is
  //   `true` when deleting the file was OK,
  //   `false` when it failed
});

// get a file's content
Sass.readFile(filename, function callback(content) {
  // (string) content is the file's content,
  //   `undefined` when the read failed
});

// list all files (regardless of directory structure)
Sass.listFiles(function callback(list) {
  // (array) list contains the paths of all registered files
});

// preload a set of files
// see chapter »Working With Files« below
Sass.preloadFiles(remoteUrlBase, localDirectory, filesMap, callback);

// register a set of files to be (synchronously) loaded when required
// see chapter »Working With Files« below
Sass.lazyFiles(remoteUrlBase, localDirectory, filesMap, callback);

Using the synchronous, non-worker API

// compile text to SCSS
var result = Sass.compile(text);

// set compile style options
Sass.options({
  // format output: nested, expanded, compact, compressed
  style: Sass.style.nested,
  // add line comments to output: none, default
  comments: Sass.comments.none
});

// register a file to be available for @import
var success = Sass.writeFile(filename, text);

// remove a file
var success = Sass.removeFile(filename);

// get a file's content
var content = Sass.readFile(filename);

// list all files (regardless of directory structure)
var list = Sass.listFiles();

// preload a set of files
// see chapter »Working With Files« below
Sass.preloadFiles(remoteUrlBase, localDirectory, filesMap, callback);

Working With Files

Chances are you want to use one of the readily available Sass mixins (e.g. drublic/sass-mixins or Bourbon). While Sass.js doesn't feature a full-blown "loadBurbon()", registering individual files is possible:

Sass.writeFile('one.scss', '.one { width: 123px; }');
Sass.writeFile('some-dir/two.scss', '.two { width: 123px; }');
Sass.compile('@import "one"; @import "some-dir/two";', function(result) {
  console.log(result);
});

outputs

.one {
  width: 123px; }

.two {
  width: 123px; }

To make things somewhat more comfortable, Sass.js provides 2 methods to load batches of files. Sass.lazyFiles() registers the files and only loads them when they're loaded by libsass - the catch is this HTTP request has to be made synchronously (and thus only works within the WebWorker). Sass.preloadFiles() downloads the registered files immediately (asynchronously, also working in the synchronous API):

// HTTP requests are made relative to worker
var base = '../scss/';
// equals 'http://medialize.github.io/sass.js/scss/'

// the directory files should be made available in
var directory = '';

// the files to load (relative to both base and directory)
var files = [
  'demo.scss',
  'example.scss',
  '_importable.scss',
  'deeper/_some.scss',
];

// register the files to load when necessary
Sass.lazyFiles(base, directory, files, function() { console.log('files registered, not loaded') });

// download the files immediately
Sass.preloadFiles(base, directory, files, function() { console.log('files loaded') });

Note that Sass.lazyFiles() can slow down the perceived performance of Sass.compile() because of the synchronous HTTP requests. They're made in sequence, not in parallel.

While Sass.js does not plan on providing file maps to SASS projects, it contains two mappings to serve as an example how your project can approach the problem: maps/bourbon.js and maps/drublic-sass-mixins.js.


Building Sass.js

grunt build
# destination:
#   dist/sass.js
#   dist/sass.min.js
#   dist/sass.worker.js
#   dist/worker.js
#   dist/worker.min.js

Building libsass.js

# using grunt:
grunt build:libsass
# using bash:
(cd libsass && build-libsass.sh)

# destination:
#   libsass/libsass/lib/libsass.js

Changelog

master

  • adding SassWorker._eval() to execute arbitrary code in the worker context. This is used for development/debugging
  • adding Sass.lazyFiles() and Sass.preloadFiles()
  • fixing the hiding of internal script errors

0.6.3 (March 3rd 2015)

  • fixing invalid source error handling (#23)

0.6.2 (January 22nd 2015)

  • fixing Makefile.patch for "memory file" to work with emscripten 1.29

0.6.1 (January 5th 2015)

  • fixing Makefile.patch to work with libsass 3.1.0
  • upgrading to libsass 3.1.0

0.6.0 (December 23rd 2014)

  • adding grunt build:libsass to make libsass.js (#15)
  • making absolute paths work via symlinks (#19)

0.5.0 (August 31st 2014)

0.4.0 (June 6th 2014)

0.3.0 (April 5th 2014)

0.2.0 (January 16th 2014)

  • using libsass at v1.0.1 (instead of building from master)
  • adding grunt build to generate dist files
  • adding mocha tests grunt test

0.1.0 (January 13th 2014)

  • Initial Sass.js

Authors

License

Sass.js is - as libsass and Emscripten are - published under the MIT License.

About

Sass.js - API for emscripted libsass to run in the browser

Resources

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 59.4%
  • CSS 20.1%
  • HTML 14.2%
  • C++ 2.8%
  • Diff 2.3%
  • Shell 1.2%