Rsass 0.26.0 released
Posted 2022-09-18 20:04. Tagged rust, project, css, rsass, sass.
More than three months after the last release, is is now the time to announce rsass 0.26.0. There is a bunch of breaking changes and a bunch of improvements. The changelog has the whole (too long) list.
But this time, some of the changes may go a bit deeper. As usual, the breaking changes is breaking mainly to users who in some way modify the global context from rust code, maybe by providing their own builtin functions or maybe just by inserting a global variable.
Also this time, there is an improved way of calling ructe from a cargo
build.rs program, see the Cargo section below.
Builtin functions and their arguments
BuiltinFn is now a
dyn Fn(&ResolvedArgs) -> Result<Value, CallError> + Send + Sync
(earlier, the argument was a
ScopeRef and the error type was
ResolvedArgs type provides functions
get_map to get an
argument converted to a specific type, either by
TryFrom<Value> for the
type or by a given conversion function.
If the conversion fails, the (display formatted) error will be combined
with the argument name into a
There is also similar
get_opt_map for optional arguments
(i.e. arguments where
null values are allowed).
If something other than argument parsing can go wrong in your function,
::AtError (and a
CallError from that) is probably
the best way to handle that.
Contexts and files
The easiest way to get some css data is still like this:
let css = compile_scss_path?;
The body of that function now looks like this:
let = for_path?; context.with_format.transform
FsContext is a specialization of
Context for loading files
from the file system.
Apart from loading files, the
Context also provides the global
Scope, which can be modified to provide extra “builtin” variables,
functions or modules.
For a full example, see the
Here’s a tiny example providing the global variable
let = for_path?; context.get_scope.define?; context.transform
When running ructe from a cargo
build.rs program, the following way of
calling rsass can be used:
let = for_path?; context.transform
This doesn’t look like a big change, but using a
is just type alias for a
Context where the loader is a
have two benefits:
First, the path is resolved relative to the crate root (the directory
Cargo.toml) rather than the current working directory.
Secondly, both for the given path and for any paths loaded when handling
the scss (due to e.g.
special messages telling cargo that those files are used in the build, so
build.rs program gets reexecuted if needed when rebuilding the
Updating ructe to 0.15.0 includes an update of rsass to 0.26.0.
Ructe also declares a built-in function,
static_name, that takes the
source name of a static file and returns an url name, i.e. a name
including a content hash for cache-busting.
Earlier versions of rsass had an
rsass::Error enum with lots of variants
that was returned from most functions in the crate.
In this version, there is still an
Error enum, but it has fewer variants
(and the fallback variant with just a message string is used a lot less,
even though some uses still remains).
Many of the old variants are now covered by
Error::Invalid(Invalid, SourcePos), which holds an
Invalid (what went wrong) and a
(where it happened).
Internally, some functions now returns a
Result<T, Invalid> to be
combined with a source position as the error propagates.
Other functions have other specific error types, such as
CallError mentioned above.
More to come
Rsass is far from done.
Lots of things remains before I’ll call it 1.0.
Probably the biggest one is placeholder selectors and the
To be able to do that, there are two things missing; selector functions
and a css data tree.
Many selector functions require a deeper understanding of css selectors than what is currently encoded, to be able to answer questions like “do this complex selector select a proper subset of what that complex selector selects”. I’m not yet sure how a css selector should be represented in rsass to be able to do that efficiently.
Css output is almost just a list of rules, but there is also
directives, such as
@media, which contains another list of rules and
Currently, rsass has a data type for a single css rule, but when a rule is
completed it is written to an output buffer, and that buffer is the only
representation of the completed css.
To be able to find earlier rules to extend, a full data tree is needed.
That should also provide some nice separation between the transformation
(sass to css) and the formatting (css data model to css text buffer).
So, lots more to come at https://github.com/kaj/rsass. I hope to see you there!