v0.16.0 - MIT - dart-sass 1.104.1
Sass, in Rust.
Compile Sass to CSS with no Node, no libsass and no subprocess. A library, a command-line binary, and a WebAssembly module that compiles a whole design system in a browser tab.
$
cargo add accent-sass
use accent_sass::{Options, from_string};
let css = from_string(
"$gap: 1rem;\na { padding: $gap * 2; }".to_owned(),
&Options::default(),
)?;
assert_eq!(css, "a {\n padding: 2rem;\n}\n");
// No Node, no libsass, no subprocess. The same
// compiler runs in a browser:
// import { compileString } from "@zoosky/accent-sass";
The pipeline
Source in, CSS out, checked against the reference
The first three stages are what any Sass compiler does. The fourth is why this one can claim parity rather than resemblance: every build compiles four real frameworks with both engines and fails on a single differing colour value.
-
parse
Source text to an AST, in SCSS, the indented syntax, or plain CSS. The syntax follows the file extension unless you override it.
-
evaluate
Modules, mixins, functions and colour maths. `@use` and `@forward` resolve through a filesystem you can replace.
-
serialize
Expanded or compressed CSS, with `@charset` handling that matches the reference implementation.
-
verify
Bulma, Pico, Foundation and USWDS compiled with both engines on every commit. A differing colour value fails the build.
Conformance
The reference implementation is the test
dart-sass 1.104.1 is the reference, and a deviation from it is a bug rather than a dialect. The numbers below come from the official spec suite and from the framework corpus CI compiles on every commit.
What you get
What the compiler actually promises
A short list, because each item is something the code is arranged around rather than something it happens to do.
Parity is the contract
dart-sass is the reference implementation, currently 1.104.1. Where output deliberately differs, the reason is written next to the test. A re-baselined expectation that nobody checked against the reference is how wrong behaviour gets frozen, so it is not allowed.
Real frameworks, every commit
Bulma, Pico, Foundation and USWDS compile with both engines in CI, and any differing colour value fails the job. All four compile byte-identically to dart-sass; for USWDS that is 32,781 lines on both sides, comments included.
The filesystem is a seam
Options::fs takes any Fs implementation, so a host that already holds its stylesheets never writes them to disk. MemoryFs ships as one, and is what the browser build resolves imports through.
It runs in a browser
A WebAssembly build exposes compileString and compile with dart-sass's option names. The demo on this site compiles USWDS -- 605 stylesheets -- client side, with nothing sent anywhere.
Compile Sass at build time
accent_sass::include! compiles a stylesheet into your binary during cargo build, tracked for incremental rebuilds. No asset pipeline, no build script, no runtime cost.
A C ABI for plugin hosts
The wasi-exports feature exposes a C ABI for wasm32-wasip1, so a host can instantiate the compiler once and compile many stylesheets without paying process startup for each.
Why a Rust implementation
dart-sass is the reference implementation and it is written in Dart. A Rust program that wants Sass has three options: shell out to a Node or Dart process, bind to the deprecated libsass, or use a native port. The first adds a runtime to your deployment; the second stopped at a dialect of Sass that has since moved on.
This is the third. It is a fork of
connorskees/grass, whose last release
was 0.13.4 in August 2024, and it carries the modern Dart Sass features
upstream has not released -- the colour spaces, color.channel, the module
system corners, the calculation long tail -- so that a Rust program can build
Bulma or USWDS without another toolchain in the picture.
Parity with dart-sass is the goal rather than an aspiration to approximate it. Where the two cannot agree, the difference is written down rather than emulated silently; Compatibility is the list.
Watch it compile a design system, live
The demo holds Bulma and USWDS in memory and compiles them in your browser. Change a theme token and the whole framework rebuilds from source -- not a layer of CSS pasted on top.