Skip to content

feat(fmt): use lax-css for CSS, SCSS, and Less#35160

Open
bartlomieju wants to merge 11 commits into
mainfrom
feat/lax-css-formatter
Open

feat(fmt): use lax-css for CSS, SCSS, and Less#35160
bartlomieju wants to merge 11 commits into
mainfrom
feat/lax-css-formatter

Conversation

@bartlomieju

@bartlomieju bartlomieju commented Jun 11, 2026

Copy link
Copy Markdown
Member

Routes CSS, SCSS, and Less formatting through lax-css instead of malva, and
removes malva from the dependency tree entirely. lax-css
(https://github.com/bartlomieju/lax) is built on the semantics-free parsing
model from CSS Syntax Level 3: it never reinterprets tokens, only adjusts
whitespace, so unknown at-rules, Tailwind arbitrary values, and future syntax
format correctly instead of being mangled or rejected. This fixes the property
casing loss in unknown at-rules (#26420) and the parse error on
::slotted(* + *) (#34582), neither of which can be fixed upstream in malva.
Author line breaks inside values are preserved, which also addresses the value
collapsing complaints from #29326.

Style blocks in HTML and components and CSS-in-JS tagged templates also go
through lax-css; the @dpr1nt placeholders pass through all positions
untouched, so the Less wrapper hack in format_embedded_css is gone. Inline
style="" attributes are formatted with lax-css's single-line mode, which
normalizes whitespace around colons and between declarations without inserting
line breaks (line breaks are not allowed in an attribute value); like the rest
of the formatter it never invents or drops tokens, so a trailing ; the author
omitted is not added.

The indented Sass syntax (.sass) is no longer supported: it was the only
format still routed through malva, and lax-css does not parse it. Prettier and
Biome do not support indented Sass either. .sass is dropped from the fmt
extension dispatch, --ext, the help text, and the LSP LanguageId enum, so
editors leave it untouched rather than mis-formatting it; .scss is
unaffected. Upgrade churn on files already formatted by deno fmt is near zero
except selector lists, which now always break one per line like Prettier and
Biome.

Fixes #26420
Fixes #34582

Style blocks in HTML and components and CSS-in-JS tagged templates now
go through lax-css as well; the @dpr1nt placeholders pass through all
positions untouched, so the Less wrapper hack is no longer needed.
Style attribute contents are kept as written. malva remains only for
the indented Sass syntax, which now prints a deprecation warning.
@bartlomieju bartlomieju marked this pull request as ready for review June 12, 2026 06:42
@bartlomieju

Copy link
Copy Markdown
Member Author

I think we should remove support for Sass syntax and remove malva completely from dependency list.

Per review feedback, drop the indented Sass (.sass) special case that was
still routed through malva, and remove malva from the dependency list
entirely. lax-css continues to handle CSS, SCSS, and Less.

.sass is no longer a supported format: removed from the fmt extension
dispatch, is_supported_ext_fmt, the --ext value list, the help text, and
the LSP LanguageId enum (so editors treat it as Unknown rather than
mis-formatting it as TypeScript).
@bartlomieju bartlomieju changed the title feat(fmt): use lax-css for formatting CSS, SCSS, and Less files feat(fmt): use lax-css for CSS, SCSS, and Less, replacing malva Jun 13, 2026
.sass is no longer a supported format, so the LSP returns no formatting
edits for it. Drop the sass fixture and its formatting assertion from the
test, which now covers css, scss, and less.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure about these, need to verify before landing

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto - why is this file changed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably have semicolon at the end

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

lax-css 0.2.2 normalizes whitespace around selector combinators
(#app>.btn -> #app > .btn) and writes empty rules as {}, both matching
the previous malva output. Regenerates the affected CSS, markdown, and
svelte fixtures and the lsp empty-rule expectation.
@bartlomieju bartlomieju changed the title feat(fmt): use lax-css for CSS, SCSS, and Less, replacing malva feat(fmt): use lax-css for CSS, SCSS, and Less Jun 13, 2026
# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	cli/Cargo.toml
Inline style="" attributes were passed through unformatted, which left
inconsistent output like `width : Xpx; height:1px`. Format them with
lax-css's new singleLine mode (lax-css 0.2.3), which normalizes
whitespace around colons and between declarations without inserting line
breaks. Like the rest of the formatter it never invents or drops tokens.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deno fmt crash with Lit css + slotted owl selector fmt does not preserve CSS property casing

1 participant