Skip to content

Stop normalizing url() quote style#233

Merged
bartveneman merged 3 commits into
mainfrom
claude/print-url-no-quote-normalization
Jul 20, 2026
Merged

Stop normalizing url() quote style#233
bartveneman merged 3 commits into
mainfrom
claude/print-url-no-quote-normalization

Conversation

@bartveneman

Copy link
Copy Markdown
Member

Summary

  • print_url previously re-quoted every url(...) to double quotes (falling back to single quotes when the value contained a "), and for data: URLs went further — escaping/re-picking quotes when the value contained both quote types (%22-encoding a literal " inside the URL).
  • This is surprising for authors who deliberately chose a quote style, and the data: URL escaping could alter the URL's actual encoded content.
  • print_url now only lowercases a leading url( keyword and otherwise prints the node's raw text, leaving quote style (and unquoted url()s) exactly as written — matching the "don't touch quotes" strategy already used for @import URLs in the at-rule prelude printer.

Note: this changes formatter output for any url(...) that isn't already double-quoted — worth a heads up if you version by output stability, since previously-normalized quotes will now be preserved as-authored instead.

Test plan

  • Updated the 5 existing tests that asserted the old quote-normalizing/escaping behavior in test/values.test.ts and test/declarations.test.ts to reflect pass-through behavior
  • npx tsc --noEmit, npx vitest run, npx oxlint, npx oxfmt --check all clean

Generated by Claude Code

print_url previously re-quoted every url() to double quotes (falling
back to single when the value contained a double quote), and for
data: URLs went further, escaping/re-picking quotes when the value
contained both quote types. That's surprising for authors who
deliberately chose a quote style, and the data: URL escaping could
alter the URL's actual content (%22-encoding a literal double quote
inside it).

print_url now only lowercases a leading `url(` keyword and otherwise
prints the node's raw text, leaving quote style (and unquoted url()s)
exactly as written. Updated the tests that asserted the old
quote-normalizing/escaping behavior.
@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

🎉 Package Size Decrease

📦 Package 📏 Base Size 📏 Source Size 📈 Size Change
@projectwallace/format-css 8.7 kB 8.7 kB -12 B

bartveneman pushed a commit that referenced this pull request Jul 20, 2026
These two changes are broader than the at-rule prelude rework this PR
is otherwise scoped to (they touch existing declaration/selector
printing that predates this branch), so they're moving to their own
PRs (#232 and #233) for focused review and testing.

Reverted print_list's function-name lowercasing, format_declaration's
property lowercasing, print_attribute_selector, print_pseudo_selector,
the type/universal selector printer, and print_atrule's name
lowercasing back to their original (unshared) form, and print_url back
to its original quote-normalizing behavior with print_prelude_url
restored as its own function.

The two new call sites this branch actually introduces —
print_media_feature and print_prelude_function's custom-property-style
name handling — keep their `--`-aware lowercasing, just inlined
instead of calling the (now removed from this branch) shared helper.
Comment thread src/lib/index.ts Outdated
} else {
inner = print_string(value)
let text = node.text
if (/^url\(/i.test(text)) {

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.

I don't understand, could a Url evr not have this 'url(' prefix?

A Url node's text always starts with url( (any casing) by
construction -- that's what makes the parser tag it as a Url node in
the first place, confirmed empirically across url(), URL(), quoted
and unquoted forms. The regex test guarding the slice was dead code.
@bartveneman
bartveneman merged commit d2c892a into main Jul 20, 2026
8 checks passed
@bartveneman
bartveneman deleted the claude/print-url-no-quote-normalization branch July 20, 2026 18:20
bartveneman pushed a commit that referenced this pull request Jul 20, 2026
#232 and #233 merged to main and landed in this branch via the merge
of main above. Point print_media_feature and print_prelude_function at
the real print_identifier() instead of their local duplicated
ternaries.

print_prelude_url stays a separate function from print_url, despite
looking identical at a glance: an @import specifier's Url node can
also be a bare string (@import "foo";) with no url( prefix, unlike
value-position url() where a string is always its own String node
type, never Url. Verified empirically -- unifying the two functions
broke `@import "foo";` (prints as `@import url(";`) since print_url's
now-unconditional slice(4) assumes a url( prefix that isn't always
there in this context.
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.

2 participants