sasso 0.14.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48e0d49603b5fa0b739a8f52c44b52b6dffdf7ead5561fab036584829f0c5b57
4
- data.tar.gz: 5dc5d4d1d8dab9d7202465f73a989e9e4cb6aed5b25811d5d090b3e100edf575
3
+ metadata.gz: 5375e3b9612d974d4b5f5f36e046604d966aea2b4a52868bdaa038dc092e7877
4
+ data.tar.gz: 97824cb45d07e6cd9604ae7d272f938ec3fa7da712a7977c41a4a675e98cd8e1
5
5
  SHA512:
6
- metadata.gz: 5a5fc9a1351d5b31b705c9763ca0c5bf4981d5c56782f949099a1228e14be24fc8aef56866c3cad7624655883dda2383eb792376b864aab3d359cd56eba5cc47
7
- data.tar.gz: f6b9ae0fd2f91181439c7bfda2002aeb4845a6219ab41055cffe8a5ac41a02d54d3ed30d0fad54fe2e6311b55c7ab77ff4fd0151b3a1f41a0e13f90a498375e0
6
+ metadata.gz: 8e6baf70058cafc8af867676a249b9ef99e81fcea9e30622545d5f4fd3f9a1691a4569ce7fd4cc6ba9c890f60a1638d958b26b777303c08a3ab24f18bdcf59d0
7
+ data.tar.gz: b8a69b394fdafe059cc15436f75363b623fb17443fc3ae6f7beda5d4440826bd635f23bd2c17c7b2cb27ed8bbd6f497834673b05609fb7826e702ccac75668e0
data/CHANGELOG.md CHANGED
@@ -9,6 +9,126 @@ the gem independently of the crate.
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.21.0] - 2026-10-30
13
+
14
+ _Adopts core `sasso` 0.21.0, nine core releases at once (0.15.0 through 0.21.0)._
15
+
16
+ _The Ruby API is backward compatible and gains one option. The compiler is not:
17
+ some stylesheets that compiled before now fail, and some CSS changes meaning,
18
+ not only bytes. Read **New errors** first, then the output changes marked
19
+ **meaning**._
20
+
21
+ ### Added
22
+
23
+ - **`silence_deprecations:`** (dart-sass `silenceDeprecations`): deprecation ids,
24
+ as Strings or Symbols, whose warnings are dropped wherever they are raised.
25
+ Every other diagnostic still comes through. The core drops a silenced id before
26
+ its repetition cap, so unlike filtering inside `on_warn:` it leaves no
27
+ "N repetitive deprecation warnings omitted" footer. Ids the compiler never
28
+ emits are accepted, as dart accepts them (core 0.17.0).
29
+
30
+ ### Changed (new errors — stylesheets that compiled before)
31
+
32
+ - **A built-in rejects an argument name it does not declare** (core 0.19.1).
33
+ `math.max(1, 2, $x: 999)` was `999`; it is now `Error: No parameter named $x.`
34
+ The color constructors are not checked yet.
35
+ - **An argument given both by position and by name is an error** (0.19.2).
36
+ `color.mix(red, blue, 10%, $color1: green)` was `rgb(10%, 0%, 90%)`; it is now
37
+ `Argument $color1 was passed both by position and by name.`
38
+ - **`@use "sass:color" as *` no longer exposes the members dart removed from
39
+ `sass:color`**, so `saturate(#abcdef, 10%)` reached that way fails (0.19.0).
40
+ - **The color functions reject `var()`, `env()` and a calc that cannot fold**,
41
+ for example `color.invert(var(--c))` (0.19.0).
42
+ - **Plain CSS rejects every `#{…}`**, where some positions used to drop it
43
+ silently, and a style rule inside a keyframe frame of a `.css` file is an
44
+ error (0.19.0).
45
+ - **Selectors follow dart's grammar** (0.19.3). Malformed attributes (`[a=1]`,
46
+ `[a==b]`, `[]`), characters that start no selector (`a^b`), invalid keyframe
47
+ stops (`10px`) and a raw line break inside a quoted string now fail.
48
+
49
+ ### Changed (output)
50
+
51
+ As with 0.14.0, byte-compared output (snapshot tests, asset digests, build
52
+ caches) will differ. Entries marked **meaning** change what a browser does.
53
+
54
+ - **meaning:** **compressed `color()` is valid CSS again** (0.17.0).
55
+ `color(display-p3 0.5 0.2 0.9)` compressed to `color(display-p3.5.2.9)`,
56
+ which browsers drop; it is now `color(display-p3 .5 .2 .9)`.
57
+ - **meaning:** **a non-ASCII space is no longer whitespace** (0.19.3). An NBSP
58
+ inside a selector stays part of it: `[a="x<NBSP>y"]` was rewritten to
59
+ `[a="x y"]`, and `a<NBSP>b` became a descendant selector. Output containing one
60
+ now carries `@charset "UTF-8";`.
61
+ - **meaning:** **whitespace inside a quoted attribute value is kept**:
62
+ `[a="x y"]` used to collapse to `[a="x y"]` (0.19.3). A quoted `(` or `[`
63
+ no longer swallows the rest of the selector list.
64
+ - **meaning:** **an empty at-rule survives compression**: `@font-face {}`
65
+ compressed to nothing and is now `@font-face{}` (0.19.0).
66
+ - **meaning:** **plain `.css` loaded through `@use`/`@import` keeps rules it used
67
+ to drop** (`@keyframes`, a custom `@function`, an at-rule nested in a style
68
+ rule), and stops hoisting at-rules out of a keyframe frame (0.19.0).
69
+ - **meaning:** **legacy color edge cases follow dart**. A degenerate color such
70
+ as `hsl(0, 100%, calc(-infinity * 1%))` is a color rather than a string, so
71
+ `color.mix()` on it gives `hsl(0, 0%, 0%)` instead of `rgb(NaN%, NaN%, NaN%)`.
72
+ `color.change()` on an hsl color no longer flips its hue (0.19.0).
73
+ - **Compressed colors and numbers serialize the way dart's do**, about 1,400
74
+ cases (0.19.0). For example, `oklab(1% 0 0)` compresses to `oklab(.01 0 0)`.
75
+ - **The `rgb()`/`hsl()` form choice follows dart's rules** in both styles
76
+ (0.19.0).
77
+ - **A calc writes `+ -n` as `- n` in compressed output too** (0.17.0).
78
+ - **A `round()` that cannot be folded is a calculation**, so compressed output
79
+ drops the space after its commas (0.19.0).
80
+ - `@import` modifiers are written verbatim, a newline in a complex selector puts
81
+ the next one on its own line, and compressed `[a="x y" i]` drops the space
82
+ before `i` (0.19.0, 0.19.3).
83
+
84
+ ### Changed (diagnostics)
85
+
86
+ - **New warning: `bogus-combinators`** (0.17.0), when a rule whose selector has
87
+ a repeated or leading combinator (`a > + b`) is dropped. sasso already dropped
88
+ those rules, as dart does, but said nothing; the warning is the only sign that
89
+ the CSS lost them. Use `silence_deprecations: [:"bogus-combinators"]` to
90
+ silence it.
91
+ - **New deprecation: `color-module-compat`** (0.19.0), e.g. for
92
+ `color.grayscale(1)`.
93
+ - **CSS filter functions no longer raise `global-builtin`**: for example,
94
+ `filter: grayscale(1)` (0.18.0).
95
+ - **Messages follow dart's wording** for a removed `sass:color` member, a type
96
+ error, which now names the parameter (`$number: (1 2) is not a number.`), and
97
+ a missing attribute operator (0.19.0, 0.19.3).
98
+ - **A stack frame names a path relative to the working directory**, not a
99
+ `file://` URL (0.19.0).
100
+
101
+ ### Changed (build)
102
+
103
+ - **The extension depends on the core with `default-features = false`.** Core
104
+ 0.19.0 added a default-on `cli-clock` feature that pulls `chrono` into Windows
105
+ builds for the CLI's `--watch` timestamp. The library never uses it, so the
106
+ native extension keeps its zero-dependency build.
107
+
108
+ ### Performance
109
+
110
+ The library compile path is faster in every core release in this range, with
111
+ byte-identical output in the releases that only make it faster (0.20.0, 0.21.0).
112
+ Measured as instruction counts on the core's real-world corpus, 0.20.0 alone cut
113
+ vuetify by 24%, bulma by 21% and bootstrap by 8%. 0.21.0 cut uswds by 41%, by
114
+ speeding up variables reached through `@use … as *`.
115
+
116
+ ## [0.14.1] - 2026-10-30
117
+
118
+ _A gem-only patch. The bundled core compiler is still `sasso` 0.14.0, so
119
+ `Sasso::CORE_VERSION` reports 0.14.0 and the CSS output is unchanged._
120
+
121
+ ### Added
122
+
123
+ - **Ruby 4.0 support.** The precompiled platform gems now carry a Ruby 4.0
124
+ binary, and CI tests against 4.0. Previously 4.0 fell back to the source gem,
125
+ which did not compile.
126
+
127
+ ### Fixed
128
+
129
+ - **The source gem compiles on Ruby 4.0.** The extension now builds against
130
+ magnus 0.8 instead of 0.7, whose bindings do not match the Ruby 4.0 headers.
131
+
12
132
  ## [0.14.0] - 2026-09-17
13
133
 
14
134
  _The gem version now tracks the core compiler's. It jumps 0.2.7 → 0.14.0 to meet
@@ -33,7 +153,10 @@ ways listed below._
33
153
 
34
154
  The gem's Ruby API is unchanged, but the CSS it emits moved with the core. If
35
155
  you byte-compare output — snapshot tests, asset digests, build caches — expect
36
- diffs. The CSS is equivalent; only its spelling changed.
156
+ diffs. Every change below is **serialization only** — the CSS still means what
157
+ it meant — with **one exception, the first**: `whiteness()` / `blackness()` stop
158
+ being evaluated, which makes the declaration around them invalid, so a browser
159
+ drops it. That one is worth grepping for; the rest are safe to re-baseline.
37
160
 
38
161
  - **Global `whiteness()` / `blackness()` are no longer built-ins** (core 0.9.0):
39
162
  they are `sass:color`-only, so the bare call is now an unknown function and
data/Cargo.lock CHANGED
@@ -106,21 +106,21 @@ dependencies = [
106
106
 
107
107
  [[package]]
108
108
  name = "magnus"
109
- version = "0.7.1"
109
+ version = "0.8.4"
110
110
  source = "registry+https://github.com/rust-lang/crates.io-index"
111
- checksum = "3d87ae53030f3a22e83879e666cb94e58a7bdf31706878a0ba48752994146dab"
111
+ checksum = "e76237a607e1dea288dd0ef0c6c8f49037df2152d14bb52b3542c46522d9e6fc"
112
112
  dependencies = [
113
113
  "magnus-macros",
114
114
  "rb-sys",
115
- "rb-sys-env",
115
+ "rb-sys-env 0.2.3",
116
116
  "seq-macro",
117
117
  ]
118
118
 
119
119
  [[package]]
120
120
  name = "magnus-macros"
121
- version = "0.6.0"
121
+ version = "0.8.0"
122
122
  source = "registry+https://github.com/rust-lang/crates.io-index"
123
- checksum = "5968c820e2960565f647819f5928a42d6e874551cab9d88d75e3e0660d7f71e3"
123
+ checksum = "47607461fd8e1513cb4f2076c197d8092d921a1ea75bd08af97398f593751892"
124
124
  dependencies = [
125
125
  "proc-macro2",
126
126
  "quote",
@@ -197,6 +197,12 @@ version = "0.1.2"
197
197
  source = "registry+https://github.com/rust-lang/crates.io-index"
198
198
  checksum = "a35802679f07360454b418a5d1735c89716bde01d35b1560fc953c1415a0b3bb"
199
199
 
200
+ [[package]]
201
+ name = "rb-sys-env"
202
+ version = "0.2.3"
203
+ source = "registry+https://github.com/rust-lang/crates.io-index"
204
+ checksum = "cca7ad6a7e21e72151d56fe2495a259b5670e204c3adac41ee7ef676ea08117a"
205
+
200
206
  [[package]]
201
207
  name = "regex"
202
208
  version = "1.12.4"
@@ -238,15 +244,15 @@ version = "0.1.0"
238
244
  dependencies = [
239
245
  "magnus",
240
246
  "rb-sys",
241
- "rb-sys-env",
242
- "sasso 0.14.0",
247
+ "rb-sys-env 0.1.2",
248
+ "sasso 0.21.0",
243
249
  ]
244
250
 
245
251
  [[package]]
246
252
  name = "sasso"
247
- version = "0.14.0"
253
+ version = "0.21.0"
248
254
  source = "registry+https://github.com/rust-lang/crates.io-index"
249
- checksum = "f6ae98548b2e9447aca2340b1c082c82d06721586708b808c52e2f908499c2f8"
255
+ checksum = "4de32df330f2607c02458791223064ee98752e719e6f85804953229533c32448"
250
256
 
251
257
  [[package]]
252
258
  name = "seq-macro"
data/README.md CHANGED
@@ -19,9 +19,21 @@ gem "sasso"
19
19
  $ bundle install
20
20
  ```
21
21
 
22
- Precompiled native gems ship for common platforms (Linux gnu/musl, macOS, and
23
- Windows on x86_64/arm64), so no Rust toolchain is needed. On other platforms the
24
- gem compiles from source via `cargo` (needs a Rust toolchain).
22
+ **Ruby 3.2, 3.3, 3.4 and 4.0** are supported, and CI tests each of them on
23
+ Linux and macOS. Ruby 4.0 needs sasso 0.14.1 or later.
24
+
25
+ Precompiled native gems for all four Ruby versions ship for these platforms, so
26
+ they need no Rust toolchain:
27
+
28
+ | OS | platforms |
29
+ |---|---|
30
+ | Linux (glibc) | `x86_64-linux`, `aarch64-linux` |
31
+ | Linux (musl) | `x86_64-linux-musl`, `aarch64-linux-musl` |
32
+ | macOS | `x86_64-darwin`, `arm64-darwin` |
33
+ | Windows | `x64-mingw-ucrt` |
34
+
35
+ On any other platform the gem compiles from source with `cargo`, which needs a
36
+ Rust toolchain.
25
37
 
26
38
  ## Usage
27
39
 
@@ -57,6 +69,7 @@ Sasso.compile("app/assets/stylesheets/application.scss",
57
69
  | `source_map_include_sources:` | `false` | embed each source's text in the map's `sourcesContent` |
58
70
  | `quiet:` | `false` | print no `@warn`/`@debug`/deprecation diagnostics |
59
71
  | `quiet_deps:` | `false` | drop deprecation warnings raised inside dependencies |
72
+ | `silence_deprecations:` | `[]` | deprecation ids (Strings or Symbols) whose warnings are dropped |
60
73
  | `on_warn:` | `nil` | a callable receiving each diagnostic; replaces the stderr printing |
61
74
 
62
75
  ### Source maps
@@ -75,8 +88,7 @@ r.source_map["sources"] # => ["application.scss"]
75
88
  ### Diagnostics
76
89
 
77
90
  `@warn`, `@debug` and deprecation warnings print to `$stderr` by default, the
78
- same dart-style block the `sasso` CLI and dart-sass print. Two ways to change
79
- that:
91
+ same dart-style block the `sasso` CLI and dart-sass print. To change that:
80
92
 
81
93
  ```ruby
82
94
  # Silence them entirely:
@@ -86,10 +98,12 @@ Sasso.compile_string(scss, quiet: true)
86
98
  # resolved through a load path. The entry stylesheet's own still print.
87
99
  Sasso.compile_string(scss, load_paths: ["vendor/stylesheets"], quiet_deps: true)
88
100
 
101
+ # Silence particular deprecations by id (dart-sass `silenceDeprecations`),
102
+ # wherever they are raised. Every other diagnostic still prints.
103
+ Sasso.compile_string(scss, silence_deprecations: [:import, "color-functions"])
104
+
89
105
  # Or take delivery yourself, which suppresses the printing:
90
106
  Sasso.compile_string(scss, url: "in.scss", on_warn: ->(d) {
91
- next if d[:deprecation_id] == "color-functions"
92
-
93
107
  Rails.logger.warn(d[:formatted]) # the block the compiler would have printed
94
108
  })
95
109
  ```
data/ext/sasso/Cargo.toml CHANGED
@@ -21,7 +21,7 @@ crate-type = ["cdylib"]
21
21
 
22
22
  [dependencies]
23
23
  # Build-time only — NOT runtime gem deps, preserving sasso's zero-runtime-dep promise.
24
- magnus = "0.7"
24
+ magnus = "0.8"
25
25
  # Direct dep (magnus pulls it transitively too) so its `links = "rb"` exposes
26
26
  # the `DEP_RB_*` env to OUR build.rs — `rb_sys_env::activate()` needs it, and
27
27
  # cargo only forwards a linked dep's metadata to its DIRECT dependents.
@@ -29,7 +29,7 @@ rb-sys = "0.9"
29
29
  # The published core compiler, pinned exactly to the API surface this binding
30
30
  # targets. Renamed to `sasso_core` so this package can be named `sasso` (a
31
31
  # package may not depend on a crate of its own name without a rename).
32
- sasso_core = { package = "sasso", version = "=0.14.0" }
32
+ sasso_core = { package = "sasso", version = "=0.21.0", default-features = false }
33
33
 
34
34
  [build-dependencies]
35
35
  rb-sys-env = "0.1"
data/ext/sasso/src/lib.rs CHANGED
@@ -31,18 +31,22 @@ fn flag(ruby: &Ruby, opts: RHash, key: &str, default: bool) -> Result<bool, Erro
31
31
  Ok(opt::<bool>(ruby, opts, key)?.unwrap_or(default))
32
32
  }
33
33
 
34
- /// Read `load_paths` as filesystem paths.
35
- fn load_paths(ruby: &Ruby, opts: RHash) -> Result<Vec<PathBuf>, Error> {
36
- match opt::<RArray>(ruby, opts, "load_paths")? {
37
- Some(a) => Ok(a
38
- .to_vec::<String>()?
39
- .into_iter()
40
- .map(PathBuf::from)
41
- .collect()),
34
+ /// Read an optional list of strings; a missing key is an empty list.
35
+ fn strings(ruby: &Ruby, opts: RHash, key: &str) -> Result<Vec<String>, Error> {
36
+ match opt::<RArray>(ruby, opts, key)? {
37
+ Some(a) => a.to_vec::<String>(),
42
38
  None => Ok(Vec::new()),
43
39
  }
44
40
  }
45
41
 
42
+ /// Read `load_paths` as filesystem paths.
43
+ fn load_paths(ruby: &Ruby, opts: RHash) -> Result<Vec<PathBuf>, Error> {
44
+ Ok(strings(ruby, opts, "load_paths")?
45
+ .into_iter()
46
+ .map(PathBuf::from)
47
+ .collect())
48
+ }
49
+
46
50
  /// One `@warn` / `@debug` / deprecation diagnostic, copied out of the borrowed
47
51
  /// `WarnEvent` so it outlives the compile that produced it.
48
52
  ///
@@ -145,6 +149,11 @@ fn native_compile(ruby: &Ruby, source: String, opts: RHash) -> Result<RArray, Er
145
149
  copts = copts.with_quiet_deps(importer.dependencies());
146
150
  }
147
151
 
152
+ // dart-sass `silenceDeprecations`: dropped by id before the per-id cap, so
153
+ // a silenced deprecation leaves no "N repetitive warnings omitted" footer.
154
+ // Ids the core never emits are accepted and do nothing, as in dart.
155
+ copts = copts.with_silenced_deprecations(strings(ruby, opts, "silence_deprecations")?);
156
+
148
157
  // "stderr" leaves `Options::warn` unset, which is what makes the core print
149
158
  // its own dart-style block — the default path installs no handler and pays
150
159
  // nothing, not even the sink's allocation. Only "capture" allocates.
data/lib/sasso/version.rb CHANGED
@@ -6,5 +6,5 @@ module Sasso
6
6
  # (ext/sasso/Cargo.toml). A gem-only fix takes the next patch, so the gem may
7
7
  # sit ahead of the crate within a minor — `Sasso::CORE_VERSION` reads the
8
8
  # version out of the linked binary and is the authority on what is loaded.
9
- VERSION = "0.14.0"
9
+ VERSION = "0.21.0"
10
10
  end
data/lib/sasso.rb CHANGED
@@ -59,6 +59,8 @@ module Sasso
59
59
  # charset: false => omit the @charset/BOM prefix on non-ASCII output
60
60
  # quiet: true => print no @warn/@debug/deprecation diagnostics at all
61
61
  # quiet_deps: true => drop deprecation warnings raised inside dependencies
62
+ # silence_deprecations: deprecation ids (Strings or Symbols) whose warnings
63
+ # are dropped, e.g. [:import, "global-builtin"]
62
64
  # on_warn: a callable receiving each diagnostic as a Hash (see WARNING_KEYS);
63
65
  # taking delivery this way replaces the default stderr printing
64
66
  #
@@ -67,7 +69,8 @@ module Sasso
67
69
  def compile_string(source, style: :expanded, syntax: :scss, indented: false,
68
70
  load_paths: [], url: nil, alert_ascii: false,
69
71
  source_map: false, source_map_include_sources: false,
70
- charset: true, quiet: false, quiet_deps: false, on_warn: nil)
72
+ charset: true, quiet: false, quiet_deps: false,
73
+ silence_deprecations: [], on_warn: nil)
71
74
  syntax = :sass if indented
72
75
  validate!(style, STYLES, :style)
73
76
  validate!(syntax, SYNTAXES, :syntax)
@@ -83,6 +86,7 @@ module Sasso
83
86
  source_map_include_sources: source_map_include_sources,
84
87
  charset: charset,
85
88
  quiet_deps: quiet_deps,
89
+ silence_deprecations: Array(silence_deprecations).map(&:to_s),
86
90
  warnings: warnings_mode(quiet, on_warn),
87
91
  })
88
92
  # Deliver first, raise second: a compile can warn and then fail, and those
data/sig/sasso.rbs CHANGED
@@ -37,6 +37,7 @@ module Sasso
37
37
  ?url: String?, ?alert_ascii: bool,
38
38
  ?source_map: bool, ?source_map_include_sources: bool,
39
39
  ?charset: bool, ?quiet: bool, ?quiet_deps: bool,
40
+ ?silence_deprecations: Array[String | Symbol],
40
41
  ?on_warn: (^(warning) -> void)?) -> (String | CompileResult)
41
42
  def self.compile: (untyped path, **untyped opts) -> (String | CompileResult)
42
43
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sasso
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - momiji-rs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-09-17 00:00:00.000000000 Z
11
+ date: 2026-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rb_sys