Skip to content

fix(codegen): keep a percentage line advance when the font size is bound to a variable - #58

Merged
owjs3901 merged 1 commit into
dev-five-git:mainfrom
forestream:fix/percent-line-advance-on-variable-font-size
Sep 14, 2026
Merged

owjs3901 merged 1 commit into
dev-five-git:mainfrom
forestream:fix/percent-line-advance-on-variable-font-size

Conversation

@forestream

Copy link
Copy Markdown
Contributor

What

validate_line_metrics refused any TEXT whose lineHeight is PERCENT while its fontSize is bound to a variable:

Text node '...' cannot represent a size-dependent line advance without resolved
fontSize and lineHeight; variable sizes require mode-aware metrics.

The guard is right about the danger and wrong about the representation.

Right: a pixel advance derived from a resolved size is only true in the mode that resolved it. Emitting lineHeight="27px" for a size that a variable can change publishes a number that silently stops matching.

Wrong: the value was representable all along. A Figma PERCENT line height and a CSS percentage line-height mean the same thing — both scale with whatever font size applies. Leaving the ratio alone is exact under every mode, not approximate under one.

So line_height now keeps the ratio when the size is bound, and line_height_font_size is what decides that: a bound size is withheld from the conversion rather than being trusted as a constant.

Scope of the change

  • Unbound sizes keep the pixel conversion. Every golden is unchanged — which is also the evidence that no existing screen relied on the refusal.
  • The refusal now fires only when the percentage itself is missing, which is the case that genuinely carries no value to emit.
  • The theme path is untouched. generate_devup_json still refuses a bound size, and variable_font_size_cannot_publish_a_fixed_percentage_advance still passes: a typography token records one pair of numbers for all of its uses and cannot carry a ratio the way an element can.

Evidence

A 1920-wide screen from a design system that binds every type size to a variable. Before: no code at all — the export failed at projection-and-write with DEVUP_CODEGEN_FAILED, and so did all three of its separately addressable siblings. After:

  • 71 texts keep lineHeight="150%"
  • 6 unbound texts keep their pixel advance (lineHeight="21px")
  • 1,430 lines of tsx where there was previously none

Tests

integer_line_advance::variable_font_size_keeps_the_percentage_advance_instead_of_a_pixel_one — new; asserts the ratio is emitted and the pixel form is not. Fails before the change.

Gates

Gate Result
cargo fmt --all -- --check pass
cargo clippy --locked --workspace --all-targets --all-features -- -D warnings pass, zero warnings
cargo test --workspace --release pass except visual_compare::symlink_escape_refused_before_read, which fails identically on an unmodified tree (Windows symlink privilege)

…und to a variable

A pixel advance derived from a resolved size is only true in the mode that
resolved it, so the guard refused a PERCENT line height whose font size was
variable-bound. The value was representable all along: a Figma PERCENT line
height and a CSS percentage line-height both scale with the applied font size,
so the ratio is exact under every mode.

Unbound sizes keep the pixel conversion and every golden is unchanged. The
refusal now fires only when the percentage itself is missing. The theme path is
untouched: a typography token records one pair of numbers for all of its uses
and still refuses a bound size.
@owjs3901
owjs3901 merged commit 64974d6 into dev-five-git:main Sep 14, 2026
8 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