Skip to content

Don't treat SCSS !default/!global inside strings as flags#19404

Open
patrickwehbe wants to merge 4 commits into
prettier:mainfrom
patrickwehbe:fix/scss-directive-in-string-19203
Open

Don't treat SCSS !default/!global inside strings as flags#19404
patrickwehbe wants to merge 4 commits into
prettier:mainfrom
patrickwehbe:fix/scss-directive-in-string-19203

Conversation

@patrickwehbe

Copy link
Copy Markdown

Description

Fixes #19203.

!default and !global inside a string or function argument were treated as Sass declaration flags. The flag text was sliced off the value, which injected a stray space:

/* input */
$a: "!default";
$b: unquote("!default");
$c: url("x!global");

/* before */
$a: " !default";
$b: unquote(" !default");
$c: url("x !global");

Cause

The directives were detected with /(\s*)(!default).*$/ and /(\s*)(!global).*$/. The .*$ matches the flag text anywhere in the value, including inside strings and url(...) / function arguments, after which everything from the match onward is sliced off.

Fix

In #19245 fisker suggested tightening the pattern to /(\s*)(!default)\s?$/ so it only matches a trailing flag. That is the right direction, but it drops the existing support for a flag followed by a comment, e.g. green !global /* note */, which has a snapshot in tests/format/scss/comments/variable-declaration.scss.

So the patterns now match the flag only when it sits at the end of the value, optionally followed by block comments:

const DEFAULT_SCSS_DIRECTIVE = /(\s*)(!default)(?:\s|\/\*.*?\*\/)*$/s;
const GLOBAL_SCSS_DIRECTIVE = /(\s*)(!global)(?:\s|\/\*.*?\*\/)*$/s;

Flag text inside a string or function no longer matches, while genuine trailing flags keep working, including a flag after a quoted value ($d: "!default" !default;) and a flag followed by a comment.

/* after */
$a: "!default";
$b: unquote("!default");
$c: url("x!global");

$d: "!default" !default;
$e: map-get($map, "!default") !default;

Tests

Added tests/format/scss/flag/19203.scss covering the in-string, url(...), and function-argument cases, plus mixed cases where a string value is followed by a real trailing flag. The existing flag and comments snapshots are unchanged, so genuine flags and flag-with-comment behavior are preserved.

Checklist

  • I've added tests to confirm my change works.
  • (If changing the API or CLI) I've documented the changes I've made (in the docs/ directory).
  • (If the change is user-facing) I've added my changes to changelog_unreleased/*/XXXX.md file following changelog_unreleased/TEMPLATE.md.
  • I've read the contributing guidelines.
  • I did not use AI to generate this PR.
  • (If the above is not checked) I have reviewed the AI-generated content before submitting.

Patrick Wehbe added 2 commits June 19, 2026 22:27
The directive regexes matched `!default`/`!global` anywhere in a
declaration value via `.*$`, so the text was picked up as a Sass flag
even when it appeared inside a string, `url(...)`, or another function
argument. The matched part was then sliced off the value, injecting a
stray space (e.g. `$a: "!default"` became `$a: " !default"`).

Tighten the patterns so a flag is only recognized when it sits at the
end of the value, optionally followed by block comments. Text inside a
string or function no longer matches, while genuine trailing flags
(including a flag after a quoted value, and a flag followed by a
comment) keep working.

Fixes prettier#19203
@netlify

netlify Bot commented Jun 19, 2026

Copy link
Copy Markdown

Deploy Preview for prettier ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 4ce673b
🔍 Latest deploy log https://app.netlify.com/projects/prettier/deploys/6a390acf53a63a0009d6ef4f
😎 Deploy Preview https://deploy-preview-19404--prettier.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

$k: "!default" !default;
$l: "!global" !global;
$m: map-get($map, "!default") !default;
$n: map-get($map, "!global") !global;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you add some tests for cases that have comments after !default/!global?

@patrickwehbe

Copy link
Copy Markdown
Author

Added cases for a genuine flag followed by single, multiple, and multiline block comments, plus one combined with the flag text inside a string. Snapshot regenerated and FULL_TEST passes.

@fisker

fisker commented Jun 22, 2026

Copy link
Copy Markdown
Member

SCSS also allow single line comments // comment.

@patrickwehbe

Copy link
Copy Markdown
Author

Added single-line comment cases too. postcss-scss keeps a trailing // comment out of the value, so the flag is still detected and the value is left alone (the regex's comment branch only needs to handle block comments that land inside the value). Snapshot updated, FULL_TEST passes.

@fisker

fisker commented Jun 22, 2026

Copy link
Copy Markdown
Member
$t: 1 !default // trailing comment
;
$u: 1 !global // trailing comment
;
$v: "!default" !default // trailing comment
;

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.

SCSS !default / !global inside strings are treated as declaration flags

2 participants