Skip to content

fix: preserve resolved text weights through a typography token - #42

Merged
owjs3901 merged 2 commits into
mainfrom
integration/text-weight-preservation
Sep 12, 2026
Merged

fix: preserve resolved text weights through a typography token#42
owjs3901 merged 2 commits into
mainfrom
integration/text-weight-preservation

Conversation

@owjs3901

Copy link
Copy Markdown
Contributor

A text node whose segments share a typography token can still override the weight per run. Both text emitters suppressed fontWeight whenever a token was present, so alternating 400/700 runs came out uniform - and since missing bold changes glyph advances, a lost weight became a layout defect: one 36px line wrapped where the design does not wrap, and every section below inherited the displacement.

Measured on about against Figma's reference PNG, paired against a baseline built from main, identical theme hash 67d6de70e679 on both sides:

Width Before After Design height Height before Height after
360 7.44% 7.46% 7240 7240 7240
992 6.90% 4.06% 5619 5656 5620
1920 4.19% 2.41% 4757 4794 4758

The 37px overshoot at both wider widths collapses to 1px. landing, popup, grid and keyframes are unchanged. Mobile's +0.02pp is the cost of correct bold runs and is left in the record rather than smoothed away.

Segment-sourced weights are attributed to styledTextSegments in the source map; explicit node weights keep their node-property mapping, so the provenance says which one supplied the number.

Korean keeps word-break: keep-all

The worker also implemented removing the Korean keep-all heuristic. Figma breaks Korean within words, so deleting it measurably narrows the gap - 7.46% to 7.25% at 360, 4.06% to 3.98% at 992.

It is not shipped, by the owner's decision. It buys 0.21pp on one screen by chopping every Korean word in every generated screen, and it breaks 38 attributes across 17 plugin byte-parity goldens. Figma's Korean line breaking is a limitation to compensate for, not a specification to reproduce - the same call the plugin makes deliberately in its own text renderer:

// Add wordBreak: keep-all for Korean text
if (hasKorean) {
  defaultProps.wordBreak = 'keep-all'
}

korean_characters_keep_words_whole locks it so a later fidelity pass cannot quietly reverse it, with the reasoning recorded on segments_contain_korean. Keeping it is also what holds 16 of the 17 goldens at parity: one golden changes here, for a segment that explicitly carries weight 400.

On the numbers

thresholds.json is deliberately unchanged. The harness does not reproduce absolute figures across sessions - the same commit and binary produced about theme d3137cabf5a5/11.24% in one session and 67d6de70e679/7.44% in another, and isolating each group into a fresh acquisition process does not fix it. Only the paired delta is trustworthy, so lowering an entry would assert a reproducibility that does not exist yet. Harness determinism is tracked separately; docs/about-vertical-geometry.md records the evidence.

Both the worker and I measured this independently and reached identical figures to the decimal.

Gates: fmt 0, clippy --locked --workspace --all-targets --all-features -D warnings 0, cargo test --workspace 1059 passed / 0 failed / 2 ignored, insta --check no drift, stdio_smoke 2 passed.

@owjs3901
owjs3901 merged commit d039623 into main Sep 12, 2026
8 checks passed
@owjs3901
owjs3901 deleted the integration/text-weight-preservation branch September 12, 2026 18:16
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