Releases: zoosky/accent-sass
Release list
accent-sass 0.16.0
Install
[dependencies]
accent-sass = "0.16.0"Published to crates.io as accent-sass, accent_sass_compiler and accent-sass-macro. Documentation: https://zoosky.github.io/accent-sass.
The browser package is published to npm as @zoosky/accent-sass, at the same version:
npm install @zoosky/accent-sassSixty merged pull requests since 0.15.0: a JavaScript API and a C ABI for the WebAssembly builds, --check on the command line, the move of the reference implementation to dart-sass 1.104.1, the first deprecation warning, and a run of fixes that bring @extend, builtin calls, selectors and error positions in line with dart-sass.
The minor version rises because four changes are breaking while the major version is 0: @extend across a media query is an error, builtin calls are checked against dart-sass's parameter lists, seven inputs dart-sass refuses are rejected, and a selector whose combinators cannot match is omitted.
Against the pinned sass-spec revision (b39c32768) the suite stands at 14,147 of 14,266 passing, measured on macOS 2026-09-13; the Linux CI runner reports two fewer, the same offset as before. This release moved the pin from 4a9eea66, which added 48 runs, so the count is not directly comparable with 0.15.0's 13,926 of 14,218. Bulma, Pico, Foundation and USWDS compile byte-identically to dart-sass 1.104.1.
Added
- a C ABI for WebAssembly hosts, behind the
wasi-exportsfeature.accent_sass_alloc,accent_sass_dealloc,accent_sass_compile_string,accent_sass_compile_pathandaccent_sass_result_freeturn thewasm32-wasip1cdylib into a reactor a plugin host instantiates once and calls many times, instead of paying process startup per stylesheet. Strings cross as UTF-8 in linear memory and a result is three 32-bit words: status, pointer, length. Built with the workspace'ssmallprofile, the module is 1.31 MiB against 2.42 MiB underrelease - options for that C ABI.
accent_sass_options_newreturns an opaque handle a host fills in and passes toaccent_sass_compile_string_with_optionsoraccent_sass_compile_path_with_options, which covers output style, entry point syntax, load paths,charset,alertAsciiandquiet. The setters are named after dart-sass's JavaScript API so this ABI and the browser binding do not drift apart; a value the ABI does not define is refused rather than rounded to a default.accent_sass_compile_stringandaccent_sass_compile_pathare unchanged and still compile with defaults - a JavaScript API for the browser build.
compileString(source, options)andcompile(path, options)joinfrom_string, which keeps working. The options arestyle,syntax,loadPaths,files,url,charset,alertAscii,quietandlogger, named after dart-sass's JavaScript API wherever it has a name for the same knob; a failed compile throws anErrorcarryingmessage,formatted,file,lineandcolumn, andindex.d.tsdeclares the surface with real types. Before this the package exported one function withStdFsbehind it, so every@usefailed at run time withCan't find stylesheet to import.and a page could compile a single stylesheet and nothing else MemoryFsandfrom_string_with_file_nameare public. The browser binding resolves imports throughMemoryFs, and making it a public type rather than something private to the binding is what letscargo testreach it: the bindings themselves exist only onwasm32-unknown-unknown. It also stands on its own for a host that already holds its stylesheets, such as a CMS compiling a theme out of a database--checkon the command line, which compiles and writes nothing. Given an output file it compares the CSS it produced against what that file already holds, so a job can ask whether committed CSS is still what the Sass produces without a build step, a temporary file or adiff. It exits3on a stale or missing output file and1on a stylesheet that does not compile, which keeps "your CSS is out of date" and "your Sass is broken" apart in a log;2is still clap's usage error. Writing nothing is the point of the mode: it reports whether a build is current without being able to change the answer- deprecation warnings, starting with
bogus-combinators. A style rule whose selector has a leading, trailing or repeated combinator, and an@extendinside one, now warn as dart-sass 1.104.1 does: the same message, and a source frame that marks the selector and the declaration, comment or at-rule that makes it a problem.a > {b: c}was silently dropped from the output before, and now says why. After five warnings of one deprecation the rest are counted, and the count is reported at the end Logger::deprecationandLogger::repetitive_deprecations_omitted, with theDeprecationandDeprecationWarningtypes they receive. Both methods have defaults, so an existing logger keeps compiling: a deprecation reaches it throughLogger::warnwith the message alone, and the count is dropped.DeprecationWarning::formattedholds the full textStdLoggerprintsOptions::verboseand--verbose, which report every deprecation warning instead of counting the ones after the fifth.--verbosewas accepted and hidden before, and did nothing--indentedworks, and is no longer hidden. It reads the entry point as the indented syntax whatever the file is called. That matters most for--stdin, which is the one input route with no extension to infer a syntax from, and the route the flag exists to serve
Changed
- the reference implementation moves from dart-sass 1.103.1 to 1.104.1, and the changes of both releases are followed. A loud comment written above
@useor@forwardis written once, where it stands. Exact negative zero prints as-0rather than0, so it keeps its sign when used in a CSS calculation;math.round,math.ceil,math.floorand the calculationround()still return0, because dart-sass rounds to an integer. A colour channel that isNaNor negative zero becomes0, and so does a hue that is infinite:hsl(math.div(1, 0), 50%, 50%)is nowhsl(0, 50%, 50%)rather thanhsl(calc(NaN), 50%, 50%). As in dart-sass,color.change()on an rgb colour keeps such a channel until the colour is converted to another space, andred(),green()andblue()read a-0channel back as0 - Breaking:
@extendacross a media query is an error. An@extendwritten inside@mediamay only extend a selector in the identical query; extending across queries would need the extended rule to exist in a context it was never written for. It extended silently before, which is worse than refusing: the check was commented out and the store never recorded a selector's media context at all, so every selector looked top-level.!optionaldoes not silence it, since it says the extension need not match anything rather than that a wrong match is allowed - Breaking: builtin calls are checked against dart-sass's parameter lists. Builtins read their arguments by position with no declared parameter list, so an unknown name could not be rejected and a real one could not be found:
map.remove($key: 1)andlist.join(c, d, $invalid: true)compiled. All 196 registrations now carry the parameter list dart-sass 1.103.1 declares, overloads included, and a call picks its overload, is verified against it, and has its named arguments bound to their declared positions. The unknown-name error says "parameter", as dart-sass does, for user-defined functions too - Breaking: seven inputs dart-sass refuses are rejected. A style rule inside a keyframe block,
@mixin --aand@include --a(plain CSS is getting mixins of its own and--names are reserved for them), a custom property nested beneath another declaration, and an unbalanced bracket in a selector. The bracket tracking also closes ten fixtures in the indented syntax, where a newline inside a bracket no longer ends the selector - Breaking: a selector whose combinators cannot match is omitted. Two combinators in a row, more than one leading combinator, or a trailing one make a selector bogus, so a rule left with nothing visible is not printed and a useless selector can no longer act as an extender. The rules are ported from the dart-sass 1.104.0 source, which hides such selectors when writing CSS rather than in the evaluator, so
selector.parse(":is(.a > + .b)")still keeps its argument.selector.replace()raises dart-sass's "components may not be empty" where it used to panic - Breaking: two parse errors say what dart-sass 1.104.1 says. Where a selector should start but nothing does, the error is
expected end of rule.rather thanexpected "}"., and text that starts no rule, such as! {}or a!optionalon a line of its own in the indented syntax, isunrecognized syntaxover that text. An unclosed block reports what its contents expected, so@function foo() {anda {foo: {bar: redsayExpected identifier.as dart-sass does
Fixed
- an error points where dart-sass points. Input that ends early was reported one column short, on its last character rather than just past it, and an input ending in a newline highlighted the newline across the line. A missing expression highlighted everything back to the start of the expression, so
a {b: 1 + ;}underlined1 +where dart-sass puts one caret at the;. As in dart-sass, an "expected" error whose place is the start of a line now points at the end of the line before it, and a missing expression directly after#{highlights the#{. Only the caret moved; no message changed - ten command-line flags consumed the argument after them.
--indented,--update,--no-error-css,--no-source-map, `--embed-sources...