docs(formatter_css): record divergences found in mdn-content (css-in-md) (#27327)

This commit is contained in:
leaysgur committed 2026-10-05 00:25:07 +00:00
1 parent e9ae2d8fa6
commit 51506c662f
15 files changed
+361 -8

No files matched your search

+155 -4
View File
@@ -273,24 +273,30 @@ Prettier keeps it verbatim because postcss swallows the run as an opaque prelude
Selector-position Sass interpolation normalizes inner spaces like value-position interpolation does in both formatters;
Prettier keeps SELECTOR interpolation verbatim.
## warn-error-requote
## prelude-string-requote
- Why: uniform-rule (option governs: singleQuote)
- Pin: `tests/fixtures/format/scss/unknown-at-rule-edges.scss`
- Pin: `tests/fixtures/format/scss/unknown-at-rule-edges.scss`, `tests/fixtures/format/css/prelude-string-requote.css`
```scss
/* input */
@error 'single quotes get normalized';
@keyframes 'validString' {}
/* ours */
@error "single quotes get normalized";
@keyframes "validString" {
}
/* prettier */
@error 'single quotes get normalized';
@keyframes 'validString' {
}
```
`@warn` / `@error` prelude strings re-quote per the `singleQuote` option: `oxc-css-parser` parses them as `SassExpr`, so they go through the structured printer (see `at_rule.rs`);
Prettier keeps them as a raw string verbatim.
A string in an at-rule prelude we parse typed re-quotes per the `singleQuote` option:
the `@warn` / `@error` prelude (a `SassExpr`) and a `@keyframes` name (`at_rule.rs` `write_keyframes_name`) go through the structured printer;
Prettier keeps the at-rule params as a raw string verbatim.
Every other string in a declaration value re-quotes per the same option in both formatters.
## call-after-line-comment-indent
@@ -1385,3 +1391,148 @@ At-rule names, property names, media feature names and the prelude keywords next
Values keep their case (`LANDSCAPE`, `FLEX`), as in any declaration: a value may be a case-sensitive custom ident (`animation-name`, `grid-area`).
So do case-sensitive names (`layer(FOO)`) and any identifier carrying a variable or interpolation marker (`@media @PHONE`, `#{$Q}`).
Prettier lowercases only what its `maybeToLowerCase` reaches (at-rule names, `media-feature`, declaration props) and prints the neighbouring keywords as its media-query parser or value parser hands them over: verbatim.
## missed-semicolon-accepted
- Why: uniform-rule (acceptance: the grammar owner decides)
- Pin: `tests/fixtures/format/css/missed-semicolon-accepted.css`
```css
/* input */
a {
left: 0
top: 0;
}
/* ours */
a {
left: 0 top: 0;
}
/* prettier: CssSyntaxError: Missed semicolon, the input is left as-is */
```
A `;`-less declaration runs to the next `;`: `oxc-css-parser` reads one declaration, a value being any component-value run (css-syntax-3; its README "Acceptance");
postcss rejects a value with a `word:` after its first word.
Same tokens, so same meaning: a browser drops the whole declaration either way.
SCSS / Less keep rejecting it (dart-sass / lessc), so those stay as-is.
## combinator-spacing
- Why: uniform-rule (same construct, same output: the `>` / `+` / `~` combinators)
- Pin: `tests/fixtures/format/css/combinator-spacing.css`
```css
/* input */
col.selected||td {}
col.selected || td {}
.a^b {}
.a^^b {}
/* ours */
col.selected || td {
}
col.selected || td {
}
.a ^ b {
}
.a ^^ b {
}
/* prettier */
col.selected||td {
}
col.selected||td {
}
.a^b {
}
.a^^b {
}
```
Every combinator other than the descendant one prints with a space on each side (`selector.rs` `write_combinator`);
Prettier spaces only `>` / `+` / `~` / `>>>`, prints the others as written, and glues a spaced `||` too.
## document-url-brace
- Why: uniform-rule (same construct, same output: `@document url("x") {`)
- Pin: `tests/fixtures/format/css/document-url-brace.css`
```css
/* input */
@document url("https://www.example.com/") {}
/* ours */
@document url("https://www.example.com/") {
}
/* prettier */
@document url("https://www.example.com/")
{
}
```
The typed `@document` / `@-moz-document` prelude keeps the `{` on its line;
Prettier takes the `//` of `https://` for a line comment and moves the `{` to its own line.
A raw prelude (unknown at-rule params) still takes the same `//` test as Prettier (`comments.rs` `last_line_has_inline_comment`), so there the two agree.
## value-semicolon-glue
- Why: uniform-rule (same construct, same output: the SCSS `if()` branch separator; prettier/prettier#19384)
- Pin: `tests/fixtures/format/css/value-semicolon-glue.css`
```css
/* input */
a {
b: if(media(width < 700px): 1 ; else: 2);
c: foo(x ; y);
}
/* ours */
a {
b: if(media(width < 700px): 1; else: 2);
c: foo(x; y);
}
/* prettier */
a {
b: if(media(width < 700px): 1 ; else: 2);
c: foo(x ; y);
}
```
A `;` in a value glues to what precedes it, in every dialect (`value.rs` `base_separator`);
Prettier glues it only between SCSS `if()` branches and keeps the source space elsewhere.
## supports-function-args-indent
- Why: uniform-rule (same construct, same output: the function in a declaration value)
- Pin: `tests/fixtures/format/css/supports-function-args-indent.css`
```css
/* input */
@supports not (clip-path: shape(from center left, curve by 200px 0 with 50% -50% from start / 50% 0 from origin, close)) {}
/* ours */
@supports not (
clip-path: shape(
from center left,
curve by 200px 0 with 50% -50% from start / 50% 0 from origin,
close
)
) {
}
/* prettier */
@supports not (
clip-path: shape(
from center left,
curve by 200px 0 with 50% -50% from start / 50% 0 from origin,
close
)
) {
}
```
A broken function call inside a `@supports` declaration indents its arguments one level, as the same declaration does inside a rule;
Prettier indents the arguments and `)` one level further there, its prelude value group adding its own indent.
@@ -0,0 +1,5 @@
/* DIVERGENCES.md#combinator-spacing */
col.selected||td {}
col.selected || td {}
.a^b {}
.a^^b {}
@@ -0,0 +1,38 @@
---
source: crates/oxc_formatter_css/tests/fixtures/mod.rs
---
==================== Input ====================
/* DIVERGENCES.md#combinator-spacing */
col.selected||td {}
col.selected || td {}
.a^b {}
.a^^b {}
==================== Output ====================
------------------
{ printWidth: 80 }
------------------
/* DIVERGENCES.md#combinator-spacing */
col.selected || td {
}
col.selected || td {
}
.a ^ b {
}
.a ^^ b {
}
-------------------
{ printWidth: 100 }
-------------------
/* DIVERGENCES.md#combinator-spacing */
col.selected || td {
}
col.selected || td {
}
.a ^ b {
}
.a ^^ b {
}
===================== End =====================
@@ -0,0 +1,2 @@
/* DIVERGENCES.md#document-url-brace */
@document url("https://www.example.com/") {}
@@ -0,0 +1,23 @@
---
source: crates/oxc_formatter_css/tests/fixtures/mod.rs
---
==================== Input ====================
/* DIVERGENCES.md#document-url-brace */
@document url("https://www.example.com/") {}
==================== Output ====================
------------------
{ printWidth: 80 }
------------------
/* DIVERGENCES.md#document-url-brace */
@document url("https://www.example.com/") {
}
-------------------
{ printWidth: 100 }
-------------------
/* DIVERGENCES.md#document-url-brace */
@document url("https://www.example.com/") {
}
===================== End =====================
@@ -0,0 +1,5 @@
/* DIVERGENCES.md#missed-semicolon-accepted */
a {
left: 0
top: 0;
}
@@ -0,0 +1,28 @@
---
source: crates/oxc_formatter_css/tests/fixtures/mod.rs
---
==================== Input ====================
/* DIVERGENCES.md#missed-semicolon-accepted */
a {
left: 0
top: 0;
}
==================== Output ====================
------------------
{ printWidth: 80 }
------------------
/* DIVERGENCES.md#missed-semicolon-accepted */
a {
left: 0 top: 0;
}
-------------------
{ printWidth: 100 }
-------------------
/* DIVERGENCES.md#missed-semicolon-accepted */
a {
left: 0 top: 0;
}
===================== End =====================
@@ -0,0 +1,3 @@
/* DIVERGENCES.md#prelude-string-requote */
@keyframes 'validString' {
}
@@ -0,0 +1,24 @@
---
source: crates/oxc_formatter_css/tests/fixtures/mod.rs
---
==================== Input ====================
/* DIVERGENCES.md#prelude-string-requote */
@keyframes 'validString' {
}
==================== Output ====================
------------------
{ printWidth: 80 }
------------------
/* DIVERGENCES.md#prelude-string-requote */
@keyframes "validString" {
}
-------------------
{ printWidth: 100 }
-------------------
/* DIVERGENCES.md#prelude-string-requote */
@keyframes "validString" {
}
===================== End =====================
@@ -0,0 +1,3 @@
/* DIVERGENCES.md#supports-function-args-indent */
@supports not (clip-path: shape(from center left, curve by 200px 0 with 50% -50% from start / 50% 0 from origin, close)) {
}
@@ -0,0 +1,36 @@
---
source: crates/oxc_formatter_css/tests/fixtures/mod.rs
---
==================== Input ====================
/* DIVERGENCES.md#supports-function-args-indent */
@supports not (clip-path: shape(from center left, curve by 200px 0 with 50% -50% from start / 50% 0 from origin, close)) {
}
==================== Output ====================
------------------
{ printWidth: 80 }
------------------
/* DIVERGENCES.md#supports-function-args-indent */
@supports not (
clip-path: shape(
from center left,
curve by 200px 0 with 50% -50% from start / 50% 0 from origin,
close
)
) {
}
-------------------
{ printWidth: 100 }
-------------------
/* DIVERGENCES.md#supports-function-args-indent */
@supports not (
clip-path: shape(
from center left,
curve by 200px 0 with 50% -50% from start / 50% 0 from origin,
close
)
) {
}
===================== End =====================
@@ -0,0 +1,5 @@
/* DIVERGENCES.md#value-semicolon-glue */
a {
b: if(media(width < 700px): 1 ; else: 2);
c: foo(x ; y);
}
@@ -0,0 +1,30 @@
---
source: crates/oxc_formatter_css/tests/fixtures/mod.rs
---
==================== Input ====================
/* DIVERGENCES.md#value-semicolon-glue */
a {
b: if(media(width < 700px): 1 ; else: 2);
c: foo(x ; y);
}
==================== Output ====================
------------------
{ printWidth: 80 }
------------------
/* DIVERGENCES.md#value-semicolon-glue */
a {
b: if(media(width < 700px): 1; else: 2);
c: foo(x; y);
}
-------------------
{ printWidth: 100 }
-------------------
/* DIVERGENCES.md#value-semicolon-glue */
a {
b: if(media(width < 700px): 1; else: 2);
c: foo(x; y);
}
===================== End =====================
@@ -2,7 +2,7 @@
trailing `//` before a block, interpolated names
(the `UnknownSassAtRule` statement path).
`@error`/`@warn` re-quote strings to the preferred quote
(DIVERGES, see DIVERGENCES.md#warn-error-requote). */
(DIVERGES, see DIVERGENCES.md#prelude-string-requote). */
@a:b;
@foo (x);
@foo /* gap */ bar;
@@ -6,7 +6,7 @@ source: crates/oxc_formatter_css/tests/fixtures/mod.rs
trailing `//` before a block, interpolated names
(the `UnknownSassAtRule` statement path).
`@error`/`@warn` re-quote strings to the preferred quote
(DIVERGES, see DIVERGENCES.md#warn-error-requote). */
(DIVERGES, see DIVERGENCES.md#prelude-string-requote). */
@a:b;
@foo (x);
@foo /* gap */ bar;
@@ -35,7 +35,7 @@ source: crates/oxc_formatter_css/tests/fixtures/mod.rs
trailing `//` before a block, interpolated names
(the `UnknownSassAtRule` statement path).
`@error`/`@warn` re-quote strings to the preferred quote
(DIVERGES, see DIVERGENCES.md#warn-error-requote). */
(DIVERGES, see DIVERGENCES.md#prelude-string-requote). */
@a:b;
@foo (x);
@foo /* gap */ bar;
@@ -63,7 +63,7 @@ source: crates/oxc_formatter_css/tests/fixtures/mod.rs
trailing `//` before a block, interpolated names
(the `UnknownSassAtRule` statement path).
`@error`/`@warn` re-quote strings to the preferred quote
(DIVERGES, see DIVERGENCES.md#warn-error-requote). */
(DIVERGES, see DIVERGENCES.md#prelude-string-requote). */
@a:b;
@foo (x);
@foo /* gap */ bar;