Escape " and & in inline style attribute values#36
Merged
Conversation
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 `&` → `&` and `"` → `"`. 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.
This was referenced May 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Renderer bug found while dogfooding the Phase 8 release page. A
fontFamilyvalue of'"Inter", system-ui, sans-serif'(double quotes around the family) was interpolated raw intostyle="...", so the inner"prematurely closed the outer HTML attribute. Everything after the inner"— including thecolordeclaration 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 thestyleattribute. 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:
renderNode(text + frame wrapper)<img style="...">border-radius: 50%fallback pathWhy 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
test-style-attr-escape.ts(7 assertions):"round-trips through", color survives in the same style attribute, browser-side computed style matches input,&also escaped.npm run bench— corpus scores unchanged (77 / 98 / 74).npm run build— type-check clean.