Problem
Text nodes in Figma can have character-level style overrides — different fill colors, font weights, font sizes per character run. Currently the emitter applies only the outer text node style, so mixed-color text (e.g. one word blue, rest black) renders entirely in the outer color.
Example from FSE Pilot Build Theme: the heading "We're all about Lego" has the word "Lego" in blue (#0000ff or brand color), but the emitter outputs the entire heading as a single text node with one color.
How Figma encodes this
Text nodes carry:
characters — the full string
characterStyleOverrides — array of style-table IDs, one entry per character (0 = base style, N = override)
styleOverrideTable — map from override ID to style object with fills, fontFamily, fontWeight, fontSize, fontStyle, etc.
Proposed fix
In StaticHtmlEmitter, when emitting a TEXT node:
- Check if
characterStyleOverrides is non-empty and has more than one distinct value
- If so, split
characters into runs by contiguous style ID
- For each run, look up the override in
styleOverrideTable and emit a <span> with inline color:, font-weight:, font-style: etc. where those override the base
- Wrap all runs inside the outer element (h1, p, etc.)
When all characters share the same style (the common case), emit as today (no spans).
Impact
Color/weight emphasis within text nodes — a common pattern in marketing and editorial designs.
Problem
Text nodes in Figma can have character-level style overrides — different fill colors, font weights, font sizes per character run. Currently the emitter applies only the outer text node style, so mixed-color text (e.g. one word blue, rest black) renders entirely in the outer color.
Example from FSE Pilot Build Theme: the heading "We're all about Lego" has the word "Lego" in blue (
#0000ffor brand color), but the emitter outputs the entire heading as a single text node with one color.How Figma encodes this
Text nodes carry:
characters— the full stringcharacterStyleOverrides— array of style-table IDs, one entry per character (0 = base style, N = override)styleOverrideTable— map from override ID to style object withfills,fontFamily,fontWeight,fontSize,fontStyle, etc.Proposed fix
In
StaticHtmlEmitter, when emitting a TEXT node:characterStyleOverridesis non-empty and has more than one distinct valuecharactersinto runs by contiguous style IDstyleOverrideTableand emit a<span>with inlinecolor:,font-weight:,font-style:etc. where those override the baseWhen all characters share the same style (the common case), emit as today (no spans).
Impact
Color/weight emphasis within text nodes — a common pattern in marketing and editorial designs.