Rsass 0.27.0 released

Posted 2023-01-17 21:06. Tagged , , , , .

Again, after almost four months since the last release, it is time to announce rsass 0.27.0. There is a bunch of breaking changes and a bunch of improvements.

This time, one change may seem drastic: The rsass crate no longer contains the command-line program rsass. Instead, that is now provided by a separate rsass-cli crate. So you no longer have to enable a “commandline” feature, instead you can install the command line interface with:

:; cargo install rsass-cli

There is also a new rsass-macros crate. Read on into the Macros section for that.


In case you just want some to get some constant css from scss source in a rust project, you can now use a macro for that, and may no longer need a build.rs. To use this, you need to add rsass-macros as a dependency. You should not need rsass as a build dependency anymore.

use rsass_macros::scss;

const CSS: &str = scss!("p { em { font-style: italic; } font: serif; }");

Now CSS is a regular const &'static str, that can be used any way such a constant can be used, containing the resulting css code in compressed format. (You don’t have to write out the type, I’m just showing it in the example.)

I think this is kind of a big deal, since “just want some to get some constant css from scss source in a rust project” was pretty much the main reason for me to start this project, and is probably still the main reason for anyone to use it.

If you prefer to keep your scss code in a separate file, you can do so like this:

use rsass_macros::include_scss;

const CSS: &str = include_scss!("resources/example.scss");

The argument to the include_scss! macros should be a path relative to the project directory (the directory containing your Cargo.toml file).

Thanks to Frédéric Nieto for contributing the base of this crate.

A css document tree

Previously, the main work-driving routine of rsass, the (private) output::transform module, worked by looking at each sass::Item and writing some css output to a Vec<u8> buffer.

Now, it still looks at each sass::Item, but rather than just creating css text directly, it creates css::Items as needed, and pushes them onto the current css context. That context may be a CssData root context, or it may be a special context in for example an @media rule (which itself creates a css::Item representing the full at-rule including it’s contents, which is added to the parent context). When all of the sass is transformed, the CssData represents the full resulting css, and can be serialized to a Vec<u8> with its into_buffer method.

All of this is a refactorization that makes much of the transform code simpler. It is also a preparation for supporting the @extend directive: Now that we have a CssData representation, it is possible to write methods that query it for existing rules to extend, and to let it contain placeholder rules which can be queried, but which are ignored by the into_buffer serialization.

Everything else

There is a bunch of changes related to the SourceFile and SourcePos types. The SourcePos used to have a string field containing a copy of the relevant line. Now, it holds a SourceFile (which is internally reference-counted) instead, so keeping a lot of SourcePos data in the sass and css data representation should be cheaper in terms of memory use and allocations.

Dart sass improved some numeric handling, so I could too. I mainly removed some special cases, as the new sass behavior was closer to the default rust behavior. There is also new variables $epsilon, $max-safe-integer, $min-safe-integer, $max-number, and $min-number in sass:math, now supported by rsass.

There was a bunch of other changes as well. See the changelog for the whole list.


Write a comment

Basic markdown is accepted.

Your name (or pseudonym).

Not published, except as gravatar.

Your presentation / homepage (if any).