Skip to content

Escape " and & in inline style attribute values#36

Merged
vicmaster merged 1 commit into
masterfrom
fix/escape-style-attr
May 17, 2026
Merged

Escape " and & in inline style attribute values#36
vicmaster merged 1 commit into
masterfrom
fix/escape-style-attr

Conversation

@vicmaster
Copy link
Copy Markdown
Owner

Summary

Renderer bug found while dogfooding the Phase 8 release page. A fontFamily value of '"Inter", system-ui, sans-serif' (double quotes around the family) was interpolated raw into style="...", so the inner " prematurely closed the outer HTML attribute. Everything after the inner " — including the color declaration on the same node — was lost as malformed HTML and text rendered un-styled.

The fix routes built CSS through escapeStyleValue (replaces && and "") before interpolation into the style attribute. The browser parses the escaped attribute back to the original CSS string, but the inline attribute stays well-formed.

Applied at all three interpolation sites:

  • Main renderNode (text + frame wrapper)
  • Image wrapper's nested <img style="...">
  • Ellipse border-radius: 50% fallback path

Why this matters

The GUIDELINES doc already recommends single-quoted families ('Segoe UI') inside double-quoted JSON values. The bug is when authors follow the doc but flip the quote convention — a perfectly reasonable thing to do given JSON allows either escaping pattern. The renderer should be robust to either.

Test plan

  • New test-style-attr-escape.ts (7 assertions): " round-trips through &quot;, color survives in the same style attribute, browser-side computed style matches input, & also escaped.
  • Full smoke suite (20 tests) — all pass.
  • npm run bench — corpus scores unchanged (77 / 98 / 74).
  • npm run build — type-check clean.

Found while dogfooding the Phase 8 release page: a fontFamily of
'"Inter", system-ui, sans-serif' (double-quoted family) interpolated
raw into `style="..."` prematurely closed the outer HTML attribute.
Everything after the inner `"` was lost as malformed HTML, including
the `color` declaration — text rendered un-styled.

Now the renderer routes the styles string through `escapeStyleValue`
before interpolation, replacing `&` → `&amp;` and `"` → `&quot;`. The
browser parses the escaped attribute back to the same CSS string but
the inline `style=` attribute stays well-formed.

Applied at all three sites that interpolate built CSS into an
attribute: the main renderNode (text/frame wrapper), the image
wrapper's nested img `style`, and the ellipse-with-border-radius
fallback path.

The GUIDELINES doc already recommends single-quoted families ('Segoe
UI') inside double-quoted JSON values, so this also catches users who
follow the documentation literally but flip the quote convention.
@vicmaster vicmaster merged commit d0946c1 into master May 17, 2026
@vicmaster vicmaster deleted the fix/escape-style-attr branch May 17, 2026 12:49
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.

1 participant