-
Notifications
You must be signed in to change notification settings - Fork 1
/
feed.xml
658 lines (648 loc) · 68.7 KB
/
feed.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Sass Blog</title>
<id>https://sass-lang.com/blog</id>
<link href="https://sass-lang.com/blog"/>
<link href="https://sass-lang.com/feed.xml" rel="self"/>
<updated>2023-05-20T00:00:00Z</updated>
<entry>
<title>Request for Comments: New Embedded Protocol</title>
<link href="https://sass-lang.com/blog/rfc-embedded-protocol-2/" rel="alternate"/>
<id>https://sass-lang.com/blog/rfc-embedded-protocol-2/</id>
<published>2023-05-20T00:00:00Z</published>
<updated>2023-05-20T00:00:00Z</updated>
<author>
<name>Natalie Weizenbaum</name>
</author>
<content type="html"><p>If you’re not an author of a host package for the Embedded Sass Protocol, you
can skip this blog post—although if you’re a big enough nerd, you may find it
interesting regardless!</p>
<p>We’re planning to make a number of breaking changes to the Embedded Sass
Protocol, and we want your feedback before we lock in the new way of doing
things. We intend to make a number of breaking changes all at once to keep the
total number of disruptions to a minimum.</p>
<p>We’re planning two major breaking changes:</p>
<ol>
<li>
<p>The Dart Sass embedded host will no longer be released as a separate
executable. It will now be bundled into the main Dart Sass executable,
accessible by running <code>sass --embedded</code>.</p>
</li>
<li>
<p>Every packet in the embedded protocol now includes a compilation ID as part
of the packet structure, rather than declaring it in the protocol buffer
definitions.</p>
</li>
</ol>
<p>We’re using this opportunity to also introduce three much smaller breaking
changes:</p>
<ol>
<li>
<p>The specification for the embedded protocol and the protocol buffer
definition have been moved to <a href="https://github.com/sass/sass/blob/main/spec/embedded-protocol.md">the Sass language repository</a> so that they can
be updated at the same time as changes to the language and the JS API.</p>
</li>
<li>
<p>The embedded protocol now explicitly declares optional fields using the
protocol buffers language feature. This means that “default values” for
various fields are no longer considered to be unset.</p>
</li>
<li>
<p>The <code>CompilationSuccess.loaded_urls</code> field has been moved to
<code>CompilationResult.loaded_urls</code> so that it’s available even when a
compilation fails. This allows watcher implementations to know which files to
watch to redo a failed compilation.</p>
</li>
</ol>
<p>The repository-organization changes have already been made, but the changes to
the protocol itself are fully documented <a href="https://github.com/sass/sass/blob/main/accepted/embedded-protocol-2.md">in a proposal in the language
repository</a>.</p>
<h2 id="combining-executables" tabindex="-1">Combining Executables<a class="anchor" href="https://sass-lang.com/blog/rfc-embedded-protocol-2/#combining-executables"><span class="visuallyhidden">Combining Executables permalink</span></a></h2>
<p>The primary benefit of folding Embedded Dart Sass into the main Dart Sass
executable is to provide embedded hosts an easy way to expose the standard Dart
Sass command-line API to users. Now every user who installs any embedded host
will have the full Dart Sass executable available to them at native Dart VM
speeds.</p>
<p>This also helps simplify the Sass team’s organization by reducing the number of
separate repositories and release processes we need to manage.</p>
<h2 id="wire-level-compilation-id" tabindex="-1">Wire-Level Compilation ID<a class="anchor" href="https://sass-lang.com/blog/rfc-embedded-protocol-2/#wire-level-compilation-id"><span class="visuallyhidden">Wire-Level Compilation ID permalink</span></a></h2>
<p>We’re pulling the compilation ID out to the protocol level in order to provide
better concurrency, particularly on the side of the embedded compiler. Sass
compilations done by the embedded compiler don’t share any state between one
another, which means that they could in theory be run in totally separate worker
threads. However, with the embedded protocol as it exists today, directing each
message to the correct worker thread requires parsing the entire message on the
main thread to determine which compilation it belongs to, then parsing it
<em>again</em> in the worker thread to actually handle it.</p>
<p>Making the compilation ID part of the protocol itself solves this issue. Each
endpoint can read the ID, look up the worker thread that’s handling the
compilation, and pass the message on to that thread without parsing the rest of
the message. This makes concurrency both easier and more efficient, which will
help ensure that large compilations happen as fast as possible.</p>
</content>
</entry>
<entry>
<title>Sass and Native Nesting</title>
<link href="https://sass-lang.com/blog/sass-and-native-nesting/" rel="alternate"/>
<id>https://sass-lang.com/blog/sass-and-native-nesting/</id>
<published>2023-03-29T22:30:00Z</published>
<updated>2023-03-29T22:30:00Z</updated>
<author>
<name>Natalie Weizenbaum</name>
</author>
<content type="html"><p>The stable release of Chrome 112, which is releasing today, is the first stable
browser to add support for the new <a href="https://drafts.csswg.org/css-nesting/">native CSS nesting feature</a>. This
feature—inspired by Sass’s nesting—adds the ability to nest style rules in plain
CSS, and even uses Sass’s convention of <code>&amp;</code> to refer to the parent selector.</p>
<p>We here at Sass HQ are honored every time our language design inspires
improvements in CSS itself. We’re excited to see the usability and clarity
benefits of nesting brought to even more CSS authors as more browsers continue
to roll out support for this feature.</p>
<h2 id="the-future-of-sass-nesting" tabindex="-1">The Future of Sass Nesting<a class="anchor" href="https://sass-lang.com/blog/sass-and-native-nesting/#the-future-of-sass-nesting"><span class="visuallyhidden">The Future of Sass Nesting permalink</span></a></h2>
<p>This raises an important question, though: what will happen to Sass’s nesting?
First of all, we won’t ever change existing valid Sass code so that it starts
emitting CSS that’s incompatible with widely-used browsers. This means that even
if we did decide to phase out Sass nesting and just emit plain CSS nesting
instead, we wouldn’t do so until <a href="https://github.com/sass/dart-sass#browser-compatibility">98% of the global browser market share</a>
supported native nesting.</p>
<p>More importantly, though, <strong>native CSS nesting is subtly incompatible with Sass
nesting</strong>. This affects three different cases:</p>
<ol>
<li>
<p>Native CSS nesting implicitly wraps the parent selector in <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:is"><code>:is()</code></a>, while
Sass copies its text into the resolved selector. That means that</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.foo, #bar </span><span class="token punctuation">{</span>
<span class="token selector">.baz </span><span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>produces the selector <code>.foo .baz, #bar .baz</code> in Sass but <code>:is(.foo, #bar) .baz</code> in native CSS. This changes the specificity: <code>:is()</code> always has the
specificity of its <em>most specific selector</em>, so <code>:is(.foo, #bar) .baz</code> will
match</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span>foo</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span>baz</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
<p>with specificity 1 0 1 in native CSS and 0 0 2 in Sass even though neither
element is matched by ID.</p>
</li>
<li>
<p>Also because native CSS nesting uses <code>:is()</code>, a parent selector with
descendant combinators will behave differently.</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.foo .bar </span><span class="token punctuation">{</span>
<span class="token selector">.green-theme <span class="token parent important">&amp;</span> </span><span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>produces the selector <code>.green-theme .foo .bar</code> in Sass, but in native CSS it
produces <code>.green-theme :is(.foo .bar)</code>. This means that the native CSS
version will match</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span>foo</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>green-theme<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span>bar</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
<p>but Sass will not, since the element matching <code>.foo</code> is outside the element
matching <code>.green-theme</code>.</p>
</li>
<li>
<p>Sass nesting and native CSS nesting both support syntax that looks like
<code>&amp;foo</code>, but it means different things. In Sass, this adds a suffix to the
parent selector, so</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.foo </span><span class="token punctuation">{</span>
<span class="token selector"><span class="token parent important">&amp;</span>-suffix </span><span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>produces the selector <code>.foo-suffix</code>. But in native CSS, this adds a type
selector to the parent selector, so</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.foo </span><span class="token punctuation">{</span>
<span class="token selector"><span class="token parent important">&amp;</span>div </span><span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>produces the selector <code>div.foo</code> (where Sass would produce <code>.foodiv</code> instead).
Native CSS nesting has no way to add a suffix to a selector like Sass.</p>
</li>
</ol>
<h3 id="design-commitments" tabindex="-1">Design Commitments<a class="anchor" href="https://sass-lang.com/blog/sass-and-native-nesting/#design-commitments"><span class="visuallyhidden">Design Commitments permalink</span></a></h3>
<p>When considering how to handle this new CSS feature, we have two important
design commitments to keep in mind:</p>
<ul>
<li>
<p>We’re committed to being a CSS superset. All valid CSS that’s supported by a
real browser should also work in Sass with the same semantics.</p>
</li>
<li>
<p>We’re committed to backwards compatibility. As much as possible, we want to
avoid changing the semantics of existing stylesheets, and if we need to do so
we want to give users as much time and resources as possible to make the
change gracefully.</p>
</li>
</ul>
<p>In most cases, remaining a CSS superset trumps backwards compatibility. However,
nesting is one of the oldest and most widely-used Sass features so we’re
particularly reluctant to change it, especially in ways that would drop support
for widely-used features like <code>&amp;-suffix</code> that don’t have an elegant equivalent
in native CSS.</p>
<h3 id="the-plan-for-sass" tabindex="-1">The Plan for Sass<a class="anchor" href="https://sass-lang.com/blog/sass-and-native-nesting/#the-plan-for-sass"><span class="visuallyhidden">The Plan for Sass permalink</span></a></h3>
<p><strong>In the short term</strong>, we don’t intend to change anything about Sass nesting.
Sass will simply not support plain CSS nesting unless we can do so in a way
that’s fully compatible with existing Sass behavior.</p>
<p>We <em>will</em> add support for parsing plain CSS nesting in <code>.css</code> files. This
nesting won’t be resolved in any way; Sass will just emit it as-is.</p>
<p><strong>In the long term</strong>, once <a href="https://caniuse.com/css-matches-pseudo"><code>:is()</code> is supported by 98% of the global browser
market share</a>, we’ll start transitioning Sass to emit <code>:is()</code> when resolving
Sass nesting. This will make Sass behave like CSS in the first two behavioral
incompatibilities. We will consider this a breaking change, and release it as
part of a major version release to avoid unexpectedly breaking existing
stylesheets. We’ll do our best to make this transition as smooth as possible
using the <a href="https://sass-lang.com/documentation/cli/migrator">Sass Migrator</a>.</p>
<p>We will <em>not</em> drop our current behavior for <code>&amp;-suffix</code> unless we can come up
with a comparably ergonomic way to represent it that’s more compatible with CSS.
This behavior is too important to existing Sass users, and the benefit of the
plain CSS version is not strong enough to override that.</p>
</content>
</entry>
<entry>
<title>Security Alert: Tar Permissions</title>
<link href="https://sass-lang.com/blog/security-alert-tar-permissions/" rel="alternate"/>
<id>https://sass-lang.com/blog/security-alert-tar-permissions/</id>
<published>2022-12-10T00:00:00Z</published>
<updated>2022-12-10T00:00:00Z</updated>
<author>
<name>Natalie Weizenbaum</name>
</author>
<content type="html"><p>The Sass team was recently alerted by prolific external contributor <a href="https://github.com/ntkme">@ntkme</a> to
a security issue in our release process.</p>
<h2 id="tl-dr" tabindex="-1">TL;DR<a class="anchor" href="https://sass-lang.com/blog/security-alert-tar-permissions/#tl-dr"><span class="visuallyhidden">TL;DR permalink</span></a></h2>
<p>If you’re using Linux or Mac OS, run <code>ls -ax path/to/sass</code>. If the last group of
letters in the first column contains <code>w</code>, you’re vulnerable:</p>
<pre><code>Vulnerable:
-rwxr-xrwx 1 nweiz primarygroup 407 Dec 13 12:33 sass-1.56.2/sass
Not vulnerable:
-rwxr-xr-x 1 nweiz primarygroup 407 Dec 13 12:33 sass-1.56.2/sass
</code></pre>
<p>If you’re using the <code>sass-embedded</code> package, do the same thing for
<code>node_modules/sass-embedded/dist/lib/src/vendor/dart-sass-embedded/dart-sass-embedded</code>.</p>
<h2 id="who-s-affected" tabindex="-1">Who’s Affected?<a class="anchor" href="https://sass-lang.com/blog/security-alert-tar-permissions/#who-s-affected"><span class="visuallyhidden">Who’s Affected? permalink</span></a></h2>
<p>While we don’t expect this issue to be a problem for the vast majority of users,
it does affect the following groups:</p>
<ul>
<li>
<p>Users who downloaded the stand-alone Dart Sass, Dart Sass Embedded, or Sass
Migrator <code>.tar.gz</code> archives from the Dart Sass website and extracted them as
the Unix root user.</p>
</li>
<li>
<p>Users who installed the <code>sass-embedded</code> npm package as the Unix root user
prior to version 1.54.5.</p>
</li>
<li>
<p>Users who installed the “non-native” version of the community-maintained
<code>sass-embedded</code> RubyGems package as the Unix root user prior to version
1.56.2.</p>
</li>
<li>
<p>Users on multi-user systems who downloaded the stand-alone Dart Sass, Dart
Sass Embedded, or Sass Migrator <code>.tar.gz</code> archives from the Dart Sass website
and explicitly passed the <code>-p</code>/<code>--preserve-permissions</code> flag when extracting
them.</p>
</li>
</ul>
<p>Users who installed Dart Sass via the <code>sass</code> npm package, Homebrew, or
Chocolatey are categorically not at risk, nor are users on Windows.</p>
<p>We strongly recommend that users in these vulnerable groups delete and
re-install Sass. All the <code>.tar.gz</code> files on GitHub have been scrubbed to remove
the vulnerability, so you can reinstall the same version you were previously
using without needing to upgrade to the latest version.</p>
<p>This is a privilege-escalation issue, which means it could allow a hypothetical
attacker with access to a low-privilege account on your computer to escalate
their access to your account’s privileges. However, this also means that it’s
not a risk <em>unless</em> an attacker already has access to an account on your
machine.</p>
<h2 id="what-went-wrong" tabindex="-1">What went wrong?<a class="anchor" href="https://sass-lang.com/blog/security-alert-tar-permissions/#what-went-wrong"><span class="visuallyhidden">What went wrong? permalink</span></a></h2>
<p>We were inadvertently uploading <code>.tar.gz</code> archives with permissions metadata
indicating that executable files could be overwritten by all users, not just the
owner.</p>
<p>In most cases, this metadata is ignored when extracting the archives and the
permissions are set to only be writable by the user doing the extraction.
However, when extracting archives as the Unix root user or explicitly passing
the <code>-p</code>/<code>--preserve-permissions</code> flag, the permissions for the extracted files
are set according to the archive’s metadata. Because the metadata was incorrect,
an attacker with access to a low-privilege account would be able to overwrite
the executable file and escalate their privileges once it’s executed.</p>
<h2 id="how-did-this-happen" tabindex="-1">How did this happen?<a class="anchor" href="https://sass-lang.com/blog/security-alert-tar-permissions/#how-did-this-happen"><span class="visuallyhidden">How did this happen? permalink</span></a></h2>
<p>Dart Sass is automatically deployed to various different release platforms using
a Dart package called <a href="https://pub.dev/packages/cli_pkg"><code>cli_pkg</code></a>, which is also written maintained by the Sass
team. This package uses the Dart <a href="https://pub.dev/packages/archive"><code>archive</code></a> package to generate <code>.tar.gz</code> files
for stand-alone release packages which are then uploaded to GitHub, and when
initially writing the code to use this package I wrote the following function:</p>
<pre class="language-dart"><code class="language-dart"><span class="token class-name">ArchiveFile</span> <span class="token function">fileFromBytes</span><span class="token punctuation">(</span><span class="token class-name">String</span> path<span class="token punctuation">,</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span>int<span class="token punctuation">></span></span> data<span class="token punctuation">,</span>
<span class="token punctuation">{</span>bool executable <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">></span>
<span class="token class-name">ArchiveFile</span><span class="token punctuation">(</span>path<span class="token punctuation">,</span> data<span class="token punctuation">.</span>length<span class="token punctuation">,</span> data<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span>mode <span class="token operator">=</span> executable <span class="token operator">?</span> <span class="token number">495</span> <span class="token punctuation">:</span> <span class="token number">428</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span>lastModTime <span class="token operator">=</span> <span class="token class-name">DateTime</span><span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>millisecondsSinceEpoch <span class="token operator">~/</span> <span class="token number">1000</span><span class="token punctuation">;</span></code></pre>
<p>My intention was to set the executable mode to <code>755</code> (read/write/execute for the
owner, read/execute only for the other users) and the non-executable mode to
<code>644</code> (read/write for the owner, read-only for other users). However, Dart
doesn’t support literal octal numbers and I must have done the decimal-to-octal
conversion wrong. The actual permissions that got set were <code>757</code>
(read/write/execute for the owner <strong>and other users</strong>, read/execute for the
group) and <code>654</code> (read/write for the owner, read/execute for the group, and
read-only for other users).</p>
<p>This went unnoticed for several years, until @ntkme notified us of the issue
last week and provided a fix to <code>cli_pkg</code>.</p>
<h2 id="what-s-been-done" tabindex="-1">What’s been done?<a class="anchor" href="https://sass-lang.com/blog/security-alert-tar-permissions/#what-s-been-done"><span class="visuallyhidden">What’s been done? permalink</span></a></h2>
<p>We’ve released <code>cli_pkg</code> 2.1.7 which sets the archive permissions correctly. In
addition, we’ve updated all <code>.tar.gz</code> files in the Dart Sass, Dart Sass
Embedded, and Sass Migrator repositories to correctly limit write permissions to
only the owner of the files. We’re announcing the vulnerability here and on the
<a href="https://twitter.com/SassCSS">@SassCSS Twitter account</a>.</p>
</content>
</entry>
<entry>
<title>Request for Comments: Color Spaces</title>
<link href="https://sass-lang.com/blog/request-for-comments-color-spaces/" rel="alternate"/>
<id>https://sass-lang.com/blog/request-for-comments-color-spaces/</id>
<published>2022-09-21T21:00:00Z</published>
<updated>2022-09-21T21:00:00Z</updated>
<author>
<name>Miriam Suzanne and Natalie Weizenbaum</name>
</author>
<content type="html"><p>There’s been a lot of exciting work in the CSS color specifications lately, and
as it begins to land in browsers we’ve been preparing to add support for it in
Sass as well. The first and largest part of that is adding support for <em>color
spaces</em> to Sass, which represents a huge (but largely backwards-compatible)
rethinking of the way colors work.</p>
<p>Historically, all colors in CSS have existed in the same color space, known as
“sRGB”. Whether you represent them as a hex code, an <code>hsl()</code> function, or a
color name, they represented the same set of visible colors you could tell a
screen to display. While this is conceptually simple, there are some major
downsides:</p>
<ul>
<li>
<p>As monitors have improved over time, they’ve become capable of displaying more
colors than can be represented in the sRGB color space.</p>
</li>
<li>
<p>sRGB, even when you’re using it via <code>hsl()</code>, doesn’t correspond very well with
how humans perceive colors. Cyan looks noticeably lighter than purple with the
same saturation and lightness values.</p>
</li>
<li>
<p>There’s no way to represent domain- or device-specific color spaces, such as
the <a href="https://en.wikipedia.org/wiki/CMYK_color_model">CMYK</a> color space that’s used by printers.</p>
</li>
</ul>
<p>Color spaces solve all of these problems. Now not every color has a red, green,
and blue channel (which can be interpreted as hue, saturation, and lightness).
Instead, every color has a specific <em>color space</em> which specifies which
channels it has. For example, the color <code>oklch(80% 50% 90deg)</code> has <code>oklch</code> as
its color space, <code>80%</code> lightness, <code>50%</code> chroma, and <code>90deg</code> hue.</p>
<h2 id="color-spaces-in-sass" tabindex="-1">Color Spaces in Sass<a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#color-spaces-in-sass"><span class="visuallyhidden">Color Spaces in Sass permalink</span></a></h2>
<p>Today we’re announcing <a href="https://github.com/sass/sass/blob/main/proposal/color-4-new-spaces.md">a proposal for how to handle color spaces in Sass</a>. In
addition to expanding Sass’s color values to support color spaces, this proposal
defines Sassified versions of all the color functions in <a href="https://www.w3.org/TR/css-color-4/">CSS Color Level
4</a>.</p>
<h3 id="rules-of-thumb" tabindex="-1">Rules of Thumb<a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#rules-of-thumb"><span class="visuallyhidden">Rules of Thumb permalink</span></a></h3>
<p>There are several rules of thumb for working with color spaces in Sass:</p>
<ul>
<li>
<p>The <code>rgb</code>, <code>hsl</code>, and <code>hwb</code> spaces are considered “legacy spaces”, and will
often get special handling for the sake of backwards compatibility. Colors
defined using hex notation or CSS color names are considered part of the <code>rgb</code>
color space. Legacy colors are emitted in the most compatible format. This
matches CSS’s own backwards-compatibility behavior.</p>
</li>
<li>
<p>Otherwise, any color defined in a given space will remain in that space, and
be emitted in that space.</p>
</li>
<li>
<p>Authors can explicitly convert a color’s space by using <code>color.to-space()</code>.
This can be useful to enforce non-legacy behavior, by converting into a
non-legacy space, or to ensure the color output is compatible with older
browsers by converting colors into a legacy space before emitting.</p>
</li>
<li>
<p>The <code>srgb</code> color space is equivalent to <code>rgb</code>, except that one is a legacy
space, and the other is not. They also use different coordinate systems, with
<code>rgb()</code> accepting a range from 0-255, and <code>srgb</code> using a range of 0-1.</p>
</li>
<li>
<p>Color functions that allow specifying a color space for manipulation will
always use the source color space by default. When an explicit space is
provided for manipulation, the resulting color will still be returned in the
same space as the origin color. For <code>color.mix()</code>, the first color parameter
is considered the origin color.</p>
</li>
<li>
<p>All legacy and RGB-style spaces represent bounded gamuts of color. Since
mapping colors into gamut is a lossy process, it should generally be left to
browsers, which can map colors as-needed, based on the capabilities of a
display. For that reason, out-of-gamut channel values are maintained by Sass
whenever possible, even when converting into gamut-bounded color spaces. The
only exception is that <code>hsl</code> and <code>hwb</code> color spaces are not able to express
out-of-gamut color, so converting colors into those spaces will gamut-map the
colors as well. Authors can also perform explicit gamut mapping with the
<code>color.to-gamut()</code> function.</p>
</li>
<li>
<p>Legacy browsers require colors in the <code>srgb</code> gamut. However, most modern
displays support the wider <code>display-p3</code> gamut.</p>
</li>
</ul>
<h3 id="standard-css-color-functions" tabindex="-1">Standard CSS Color Functions<a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#standard-css-color-functions"><span class="visuallyhidden">Standard CSS Color Functions permalink</span></a></h3>
<h4 id="oklab-and-oklch" tabindex="-1"><code>oklab()</code> and <code>oklch()</code><a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#oklab-and-oklch"><span class="visuallyhidden">oklab() and oklch() permalink</span></a></h4>
<p>The <code>oklab()</code> (cubic) and <code>oklch()</code> (cylindrical) functions provide access to an
unbounded gamut of colors in a perceptually uniform space. Authors can use these
functions to define reliably uniform colors. For example, the following colors
are perceptually similar in lightness and saturation:</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$pink</span></span><span class="token punctuation">:</span> <span class="token function">oklch</span><span class="token punctuation">(</span>64% 0.196 353<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// hsl(329.8 70.29% 58.75%)</span>
<span class="token property"><span class="token variable">$blue</span></span><span class="token punctuation">:</span> <span class="token function">oklch</span><span class="token punctuation">(</span>64% 0.196 253<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// hsl(207.4 99.22% 50.69%)</span></code></pre>
<p>The <code>oklch()</code> format uses consistent “lightness” and “chroma” values, while the
<code>hsl()</code> format shows dramatic changes in both “lightness” and “saturation”. As
such, <code>oklch</code> is often the best space for consistent transforms.</p>
<h4 id="lab-and-lch" tabindex="-1"><code>lab()</code> and <code>lch()</code><a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#lab-and-lch"><span class="visuallyhidden">lab() and lch() permalink</span></a></h4>
<p>The <code>lab()</code> and <code>lch()</code> functions provide access to an unbounded gamut of colors
in a space that’s less perpetually-uniform but more widely-adopted than OKLab
and OKLCH.</p>
<h4 id="hwb" tabindex="-1"><code>hwb()</code><a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#hwb"><span class="visuallyhidden">hwb() permalink</span></a></h4>
<p>Sass now supports a top-level <code>hwb()</code> function that uses the same syntax as
CSS’s built-in <code>hwb()</code> syntax.</p>
<h4 id="color" tabindex="-1"><code>color()</code><a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#color"><span class="visuallyhidden">color() permalink</span></a></h4>
<p>The new <code>color()</code> function provides access to a number of specialty spaces. Most
notably, <code>display-p3</code> is a common space for wide-gamut monitors, making it
likely one of the more popular options for authors who simply want access to a
wider range of colors. For example, P3 greens are significantly ‘brighter’ and
more saturated than the greens available in sRGB:</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$fallback-green</span></span><span class="token punctuation">:</span> <span class="token function">rgb</span><span class="token punctuation">(</span>0% 100% 0%<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$brighter-green</span></span><span class="token punctuation">:</span> <span class="token function">color</span><span class="token punctuation">(</span>display-p3 0 1 0<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Sass will natively support all predefined color spaces declared in the Colors
Level 4 specification. It will also support unknown color spaces, although these
can’t be converted to and from any other color space.</p>
<h3 id="new-sass-color-functions" tabindex="-1">New Sass Color Functions<a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#new-sass-color-functions"><span class="visuallyhidden">New Sass Color Functions permalink</span></a></h3>
<h4 id="color-channel" tabindex="-1"><code>color.channel()</code><a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#color-channel"><span class="visuallyhidden">color.channel() permalink</span></a></h4>
<p>This function returns the value of a single channel in a color. By default, it
only supports channels that are available in the color’s own space, but you can
pass the <code>$space</code> parameter to return the value of the channel after converting
to the given space.</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$brand</span></span><span class="token punctuation">:</span> <span class="token function">hsl</span><span class="token punctuation">(</span>0 100% 25.1%<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// result: 25.1%</span>
<span class="token property"><span class="token variable">$hsl-lightness</span></span><span class="token punctuation">:</span> color.<span class="token function">channel</span><span class="token punctuation">(</span><span class="token variable">$brand</span><span class="token punctuation">,</span> <span class="token string">"lightness"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// result: 37.67%</span>
<span class="token property"><span class="token variable">$oklch-lightness</span></span><span class="token punctuation">:</span> color.<span class="token function">channel</span><span class="token punctuation">(</span><span class="token variable">$brand</span><span class="token punctuation">,</span> <span class="token string">"lightness"</span><span class="token punctuation">,</span> <span class="token property"><span class="token variable">$space</span></span><span class="token punctuation">:</span> oklch<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h4 id="color-space" tabindex="-1"><code>color.space()</code><a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#color-space"><span class="visuallyhidden">color.space() permalink</span></a></h4>
<p>This function returns the name of the color’s space.</p>
<pre class="language-scss"><code class="language-scss"><span class="token comment">// result: hsl</span>
<span class="token property"><span class="token variable">$hsl-space</span></span><span class="token punctuation">:</span> color.<span class="token function">space</span><span class="token punctuation">(</span><span class="token function">hsl</span><span class="token punctuation">(</span>0 100% 25.1%<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// result: oklch</span>
<span class="token property"><span class="token variable">$oklch-space</span></span><span class="token punctuation">:</span> color.<span class="token function">space</span><span class="token punctuation">(</span><span class="token function">oklch</span><span class="token punctuation">(</span>37.7% 38.75% 29.23deg<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h4 id="color-is-in-gamut-color-is-legacy" tabindex="-1"><code>color.is-in-gamut()</code>, <code>color.is-legacy()</code><a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#color-is-in-gamut-color-is-legacy"><span class="visuallyhidden">color.is-in-gamut(), color.is-legacy() permalink</span></a></h4>
<p>These functions return various facts about the color. <code>color.is-in-gamut()</code>
returns whether the color is in-gamut for its color space (as opposed to having
one or more of its channels out of bounds, like <code>rgb(300 0 0)</code>).
<code>color.is-legacy()</code> returns whether the color is a legacy color in the <code>rgb</code>,
<code>hsl</code>, or <code>hwb</code> color space.</p>
<h4 id="color-is-powerless" tabindex="-1"><code>color.is-powerless()</code><a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#color-is-powerless"><span class="visuallyhidden">color.is-powerless() permalink</span></a></h4>
<p>This function returns whether a given channel is “powerless” in the given color.
This is a special state that’s defined for individual color spaces, which
indicates that a channel’s value won’t affect how a color is displayed.</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$grey</span></span><span class="token punctuation">:</span> <span class="token function">hsl</span><span class="token punctuation">(</span>0 0% 60%<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// result: true, because saturation is 0</span>
<span class="token property"><span class="token variable">$hue-powerless</span></span><span class="token punctuation">:</span> color.<span class="token function">is-powerless</span><span class="token punctuation">(</span><span class="token variable">$grey</span><span class="token punctuation">,</span> <span class="token string">"hue"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// result: false</span>
<span class="token property"><span class="token variable">$hue-powerless</span></span><span class="token punctuation">:</span> color.<span class="token function">is-powerless</span><span class="token punctuation">(</span><span class="token variable">$grey</span><span class="token punctuation">,</span> <span class="token string">"lightness"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h4 id="color-same" tabindex="-1"><code>color.same()</code><a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#color-same"><span class="visuallyhidden">color.same() permalink</span></a></h4>
<p>This function returns whether two colors will be displayed the same way, even if
this requires converting between spaces. This is unlike the <code>==</code> operator, which
always considers colors in different non-legacy spaces to be inequal.</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$orange-rgb</span></span><span class="token punctuation">:</span> #ff5f00<span class="token punctuation">;</span>
<span class="token property"><span class="token variable">$orange-oklch</span></span><span class="token punctuation">:</span> <span class="token function">oklch</span><span class="token punctuation">(</span>68.72% 20.966858279% 41.4189852913deg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// result: false</span>
<span class="token property"><span class="token variable">$equal</span></span><span class="token punctuation">:</span> <span class="token variable">$orange-rgb</span> <span class="token operator">==</span> <span class="token variable">$orange-oklch</span><span class="token punctuation">;</span>
<span class="token comment">// result: true</span>
<span class="token property"><span class="token variable">$same</span></span><span class="token punctuation">:</span> color.<span class="token function">same</span><span class="token punctuation">(</span><span class="token variable">$orange-rgb</span><span class="token punctuation">,</span> <span class="token variable">$orange-oklch</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="existing-sass-color-functions" tabindex="-1">Existing Sass Color Functions<a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#existing-sass-color-functions"><span class="visuallyhidden">Existing Sass Color Functions permalink</span></a></h3>
<h4 id="color-scale-color-adjust-and-color-change" tabindex="-1"><code>color.scale()</code>, <code>color.adjust()</code>, and <code>color.change()</code><a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#color-scale-color-adjust-and-color-change"><span class="visuallyhidden">color.scale(), color.adjust(), and color.change() permalink</span></a></h4>
<p>By default, all Sass color transformations are handled and returned in the color
space of the original color parameter. However, all relevant functions now allow
specifying an explicit color space for transformations. For example, lightness &amp;
darkness adjustments are most reliable in <code>oklch</code>:</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$brand</span></span><span class="token punctuation">:</span> <span class="token function">hsl</span><span class="token punctuation">(</span>0 100% 25.1%<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// result: hsl(0 100% 43.8%)</span>
<span class="token property"><span class="token variable">$hsl-lightness</span></span><span class="token punctuation">:</span> color.<span class="token function">scale</span><span class="token punctuation">(</span><span class="token variable">$brand</span><span class="token punctuation">,</span> <span class="token property"><span class="token variable">$lightness</span></span><span class="token punctuation">:</span> 25%<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// result: hsl(5.76 56% 45.4%)</span>
<span class="token property"><span class="token variable">$oklch-lightness</span></span><span class="token punctuation">:</span> color.<span class="token function">scale</span><span class="token punctuation">(</span><span class="token variable">$brand</span><span class="token punctuation">,</span> <span class="token property"><span class="token variable">$lightness</span></span><span class="token punctuation">:</span> 25%<span class="token punctuation">,</span> <span class="token property"><span class="token variable">$space</span></span><span class="token punctuation">:</span> oklch<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Note that the returned color is still emitted in the original color space, even
when the adjustment is performed in a different space.</p>
<h4 id="color-mix" tabindex="-1"><code>color.mix()</code><a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#color-mix"><span class="visuallyhidden">color.mix() permalink</span></a></h4>
<p>The <code>color.mix()</code> function will retain its existing behavior for legacy color
spaces, but for new color spaces it will match CSS’s “color interpolation”
specification. This is how CSS computes which color to use in between two colors
in a gradient or an animation.</p>
<h4 id="deprecations" tabindex="-1">Deprecations<a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#deprecations"><span class="visuallyhidden">Deprecations permalink</span></a></h4>
<p>A number of existing functions only make sense for legacy colors, and so are
being deprecated in favor of color-space-friendly functions like
<code>color.channel()</code> and <code>color.adjust()</code>:</p>
<ul>
<li><code>color.red()</code></li>
<li><code>color.green()</code></li>
<li><code>color.blue()</code></li>
<li><code>color.hue()</code></li>
<li><code>color.saturation()</code></li>
<li><code>color.lightness()</code></li>
<li><code>color.whiteness()</code></li>
<li><code>color.blackness()</code></li>
<li><code>adjust-hue()</code></li>
<li><code>saturate()</code></li>
<li><code>desaturate()</code></li>
<li><code>transparentize()</code>/<code>fade-out()</code></li>
<li><code>opacify()</code>/<code>fade-in()</code></li>
<li><code>lighten()</code>/<code>darken()</code></li>
</ul>
<h2 id="let-us-know-what-you-think" tabindex="-1">Let Us Know What You Think!<a class="anchor" href="https://sass-lang.com/blog/request-for-comments-color-spaces/#let-us-know-what-you-think"><span class="visuallyhidden">Let Us Know What You Think! permalink</span></a></h2>
<p>There’s lots more detail to this proposal, and it’s not set in stone yet. We
want your feedback on it! Read it over <a href="https://github.com/sass/sass/blob/main/proposal/color-4-new-spaces.md#deprecated-functions">on GitHub</a>, and <a href="https://github.com/sass/sass/issues/new">file an issue</a> with any
thoughts or concerns you may have.</p>
</content>
</entry>
<entry>
<title>Request for Comments: Strict Unary Operators</title>
<link href="https://sass-lang.com/blog/request-for-comments-strict-unary-operators/" rel="alternate"/>
<id>https://sass-lang.com/blog/request-for-comments-strict-unary-operators/</id>
<published>2022-06-15T23:30:00Z</published>
<updated>2022-06-15T23:30:00Z</updated>
<author>
<name>Natalie Weizenbaum</name>
</author>
<content type="html"><p>Do you know what <code>margin: $a -$b</code> does in Sass? If you said &quot;the same thing as
<code>margin: $a (-$b)</code>, I’m sorry, but you’re wrong. It’s <em>actually</em> the same thing
as <code>margin: $a - $b</code>. Don’t worry, you’re not the first person to get tripped up
by this weird corner of Sass’s parser! But our new language proposal aims to fix
that.</p>
<p>In the <a href="https://github.com/sass/sass/blob/main/accepted/strict-unary.md">Strict Unary Operators</a> proposal, which is currently open for community
feedback, we propose to first deprecate and then eventually disallow expressions
of the form <code>$a -$b</code>. We know deprecations are never pleasant, but this should
be fairly painless as they go: you can simply write <code>$a - $b</code> or <code>$a (-$b)</code>,
depending which you intend. We’ll also provide a <a href="https://sass-lang.com/documentation/cli/migrator">Sass migrator</a> migration to
automatically update your stylesheets.</p>
<p><strong>Deprecated:</strong></p>
<ul>
<li><code>$a -$b</code> will no longer be allowed, because it’s unclear what the author
intended and the current behavior is likely to be incorrect.</li>
</ul>
<p><strong>Still allowed:</strong></p>
<ul>
<li>
<p><code>$a - $b</code> will continue to work, since it’s clearly supposed to indicate
subtraction.</p>
</li>
<li>
<p><code>$a (-$b)</code> will continue to work, since the parentheses make the unary minus
unambiguous.</p>
</li>
</ul>
<p>The <code>$a - $b</code> or <code>$a (-$b)</code> options are supported by all widely-used Sass
versions, so there shouldn’t be any trouble for libraries to avoid this
deprecation warning and continue to support older Sass versions. In addition,
you can always use the <a href="https://sass-lang.com/documentation/cli/dart-sass/#quiet-deps"><code>--quiet-deps</code> command-line flag</a> or the <a href="https://sass-lang.com/documentation/js-api/interfaces/Options/#quietDeps"><code>quietDeps</code> JS
API option</a> to silence warnings from dependencies you don’t control.</p>
<h2 id="why-does-it-work-this-way" tabindex="-1">Why does it work this way?<a class="anchor" href="https://sass-lang.com/blog/request-for-comments-strict-unary-operators/#why-does-it-work-this-way"><span class="visuallyhidden">Why does it work this way? permalink</span></a></h2>
<p>Why, you might wonder, does <code>$a -$b</code> parse this way in the first place? The
short answer is, “because other programming languages do it that way”. In most
programming languages, operators are parsed the same way regardless of the
whitespace that may or may not surround them. If you parse <code>$a - $b</code> as
subtraction, you should parse <code>$a -$b</code> as subtraction as well.</p>
<p>The problem for Sass is that we also inherit CSS’s use of space-separated lists
of values, so in some contexts users expect to be able to write two expressions
next to one another and have them parse the same way they would if they were
each used on their own. These two principles come into conflict and produce the
confusion this proposal seeks to address.</p>
<h2 id="why-not-just-change-the-way-it-works" tabindex="-1">Why not just change the way it works?<a class="anchor" href="https://sass-lang.com/blog/request-for-comments-strict-unary-operators/#why-not-just-change-the-way-it-works"><span class="visuallyhidden">Why not just change the way it works? permalink</span></a></h2>
<p>In theory, we could change Sass so that <code>$a -$b</code> parses the same as <code>$a (-$b)</code>:
a space-separated list of two values, the latter with a unary minus. We chose
not to do that for two reasons:</p>
<ol>
<li>
<p>Pragmatically, it’s more painful to make a breaking change that changes the
behavior of existing syntax than it is to make one that just forbids the
syntax entirely. It requires more releases and more different versions of
Sass with different behaviors. It also opens the door for a stylesheet that
upgrades many versions at once to switch to the new behavior <em>without
producing an error</em>, which could lead to the worst-case scenario: shipping
incorrect styles.</p>
</li>
<li>
<p>It’s not obvious that <code>$a -$b</code> <em>should</em> parse as <code>$a (-$b)</code> in every case.
Users coming from other programming languages may expect it to parse the same
way it does in those languages. Even in Sass, <code>$a -$b</code> will continue to be a
valid binary operation within <code>calc()</code>. It may not be elegant style, but
sometimes formatting isn’t at the top of an author’s mind!</p>
</li>
</ol>
<h2 id="let-us-know-what-you-think" tabindex="-1">Let us know what you think!<a class="anchor" href="https://sass-lang.com/blog/request-for-comments-strict-unary-operators/#let-us-know-what-you-think"><span class="visuallyhidden">Let us know what you think! permalink</span></a></h2>
<p>If you’ve got thoughts or opinions about this change, please read over <a href="https://github.com/sass/sass/blob/main/accepted/strict-unary.md">the full
proposal</a> and then <a href="https://github.com/sass/sass/issues/new">file an issue</a> with your feedback. We’ll be leaving this
open to comments for a month, after which we’ll finalize the proposal and start
implementing it.</p>
</content>
</entry>
<entry>
<title>Embedded Sass is Live</title>
<link href="https://sass-lang.com/blog/embedded-sass-is-live/" rel="alternate"/>
<id>https://sass-lang.com/blog/embedded-sass-is-live/</id>
<published>2022-02-01T10:00:00Z</published>
<updated>2022-02-01T10:00:00Z</updated>
<author>
<name>Natalie Weizenbaum</name>
</author>
<content type="html"><p>After several years of planning and development, I’m excited to finally announce
the stable release of Embedded Dart Sass along with its first official wrapper,
the <a href="https://www.npmjs.com/package/sass-embedded"><code>sass-embedded</code></a> package available now on npm!</p>
<p>Embedded Sass is an ongoing effort to make a highly-performant Sass library
available to as many different languages as possible, starting with Node.js.
Although Node.js already has access to the pure-JS <code>sass</code> package, the nature of
JavaScript inherently limits how quickly this package can process large Sass
files especially in asynchronous mode. We expect <code>sass-embedded</code> to be a major
boon to developers for whom compilation speed is a concern, particularly the
remaining users of <code>node-sass</code> for whom performance has been a major reason to
avoid Dart Sass.</p>
<p>The <code>sass-embedded</code> package fully supports the <a href="https://sass-lang.com/documentation/js-api/#md:usage">new JS API</a> as well as the
<a href="https://sass-lang.com/documentation/js-api/#md:legacy-api">legacy API</a> other than a few cosmetic options. You can use it as a drop-in
replacement for the <code>sass</code> package, and it should work with all the same build
plugins and libraries. Note that <code>sass-embedded</code> is a bit faster in
<em>asynchronous</em> mode than it is in synchronous mode (whereas the <code>sass</code> package
was faster in synchronous mode). For substantial Sass files, running
<code>sass-embedded</code> in either mode will generally be much faster than <code>sass</code>.</p>
<p>In order to limit the confusion about which version of which package supports
which feature, the <code>sass-embedded</code> package will always have the same version as
the <code>sass</code> package. When new features are added to the JS API, they’ll be
supported at the same time in both packages, and when new language features are
added to Sass they’ll always be included in a new <code>sass-embedded</code> release
straight away.</p>
<h2 id="how-it-works" tabindex="-1">How it Works<a class="anchor" href="https://sass-lang.com/blog/embedded-sass-is-live/#how-it-works"><span class="visuallyhidden">How it Works permalink</span></a></h2>
<p>Embedded Sass is composed of three parts:</p>
<ol>
<li>
<p><a href="https://github.com/sass/dart-sass-embedded">The compiler</a>, a Dart executable that wraps Dart Sass and does the actual
heavy lifting of parsing and compiling the files. Dart native executables are
generally much faster than JavaScript, so using them for the
computationally-intensive work of stylesheet evaluation is where Embedded
Sass gets its speed.</p>
</li>
<li>
<p><a href="https://github.com/sass/embedded-host-node">The host</a>, a library in any language (in this case JavaScript) that provides a
usable end-user API for invoking the compiler. The host provides callers with
configuration options, including the ability to define custom importers and
Sass functions that are used by the compilation.</p>
</li>
<li>
<p><a href="https://github.com/sass/embedded-protocol">The protocol</a>, a <a href="https://en.wikipedia.org/wiki/Protocol_Buffers">protocol-buffer</a>-based specification of how the host and
the compiler communicate with one another. This communication happens over
the standard input and output streams of the compiler executable, which is
invoked by the host to perform each compilation.</p>
</li>
</ol>
<h2 id="other-languages" tabindex="-1">Other Languages<a class="anchor" href="https://sass-lang.com/blog/embedded-sass-is-live/#other-languages"><span class="visuallyhidden">Other Languages permalink</span></a></h2>
<p>Embedded Sass was designed in part as a way for languages other than JavaScript
to have access to the full power of Sass compilation with custom importers and
functions, similarly to how C++ wrappers for <a href="https://sass-lang.com/libsass">LibSass</a> worked in the past. We
hope that community members will use this protocol to implement embedded hosts
for many other popular frontend languages. If you end up doing so, message us
<a href="https://twitter.com/SassCSS">on Twitter</a> or <a href="https://gitter.im/sass/sass">Gitter</a> and we’ll link it on this site!</p>
</content>
</entry>
</feed>