Skip to content

Keep quoted CSS URLs whole when they contain a parenthesis (4.1.1) - #243

Merged
freshlogic merged 2 commits into
mainfrom
fix-css-url-quotes
Oct 23, 2026
Merged

freshlogic merged 2 commits into
mainfrom
fix-css-url-quotes

Conversation

@freshlogic

Copy link
Copy Markdown
Member

Why

4.1.0 breaks most of the CSS in about 7 stylesheets on every site, and 28 on admin.stores.com. These are the pages/*, links/* and analytics stylesheets, plus everything that includes the SDK's Bootstrap.

The cause is an old bug in electricity's url(...) rewriting that 4.1.0 made visible:

  1. Bootstrap's navbar toggler uses a quoted data URI that contains rgba(0, 0, 0, 0.5).
  2. The rewriter stopped at the first ), found no file at that "path", and wrote the URL back without its opening ", leaving a stray " behind.
  3. The browser reads that stray " as the start of a string, and a string runs until the next line break.
    • In readable or UglifyCSS output, that cost one rule.
    • In 4.1.0's compressed output, the whole file is one line, so the string runs to the end and the browser drops every rule after it.

Rules the browser kept, measured by loading the files in Chrome:

Stylesheet Readable 4.0.0 (UglifyCSS) 4.1.0 This fix
morningsave.com pages/index.css 5,756 5,756 616 5,755
meh.com links/list.css 2,515 2,515 972 2,514
admin.stores.com upload/index.css 2,112 — 1,610 2,111

The one-rule difference left with the fix is an empty .bootstrap { } block, which compressed output drops.

This is what fails admin.stores.com's /upload accessibility test on main. Its .ext-chip rule comes after the toggler, so the labels rendered unstyled. The same commit with electricity 4.0.0 passes.

What changed

  • lib/processor.js: a quoted URL now ends at its matching closing quote (url\((['"]?)(.*?)\1\)), and a URL that doesn't match a file is left exactly as written instead of losing its quotes.
  • A new test compiles a .scss fixture with such a data URI and checks that the URL stays whole. It fails on 4.1.0 and passes with this fix.
  • Version 4.1.1 and a changelog entry.

Sites depend on ~4.1.0, so they pick up 4.1.1 on their next CI run or deploy without any package bumps.

Testing

  • npm test: 66 of 66 pass, and npx eslint . is clean.
  • Compiled every stylesheet that had a broken url(...) on all 12 sites (126 files) with this fix and loaded each in Chrome in both compressed and readable form. All of them keep every rule except the empty .bootstrap { } block, and no unquoted URL containing a quote is left.

🤖 Generated with Claude Code

freshlogic and others added 2 commits October 23, 2026 13:16
The url() rewriter stopped at the first ")", so a quoted data URI such
as Bootstrap's navbar toggler SVG, which contains "rgba(0, 0, 0, 0.5)",
was cut short. When no file matched, it was written back without its
opening quote, leaving a stray quote behind. With 4.1.0's compressed
output on a single line, that stray quote opened a string that ran to
the end of the file, and browsers dropped every rule after it (up to
89% of the rules in the sites' pages/*, links/* and analytics
stylesheets).

A quoted URL now ends at its matching closing quote, and a URL that
doesn't match a file is left exactly as written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 40002061135

Coverage remained the same at 100.0%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: 4 of 4 lines across 1 file are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 561
Covered Lines: 561
Line Coverage: 100.0%
Relevant Branches: 120
Covered Branches: 120
Branch Coverage: 100.0%
Branches in Coverage %: Yes
Coverage Strength: 22.3 hits per line

💛 - Coveralls

@freshlogic
freshlogic merged commit b92e803 into main Oct 23, 2026
2 checks passed
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