Skip to content

fix(codegen): preserve hard-break spaces in height-auto text - #49

Merged
owjs3901 merged 2 commits into
mainfrom
integration/hard-break-whitespace
Sep 13, 2026
Merged

fix(codegen): preserve hard-break spaces in height-auto text#49
owjs3901 merged 2 commits into
mainfrom
integration/hard-break-whitespace

Conversation

@owjs3901

Copy link
Copy Markdown
Contributor

A space the designer typed before an explicit line break is collapsed away by CSS, so a paragraph reads one way in Figma and another on screen.

Screen Before After
about-422-3376 5.51% 5.43%
about-422-3180 3.01% 2.93%
landing-833-3640 4.99% 4.78%
notice-422-6914 3.84% 3.74%

The other eleven screens are unchanged.

This continues an existing rule rather than inventing one

W8 established that painted text must equal characters - it stopped JSX inserting a space the design does not have, and stopped a design line break becoming a space. It then reported the remaining collapse as an explicit finding because no emission it had could avoid it. pre-wrap avoids it for a bounded case, so that case moves from reported to fixed and DEVUP_CODEGEN_TEXT_WHITESPACE_COLLAPSE stays for everything still unavoidable. One lossy fidelity impact is retired rather than left double-counted beside the diagnostic.

The condition is narrow on purpose: TEXT whose inline width Figma fixes while height grows (textAutoResize == HEIGHT), no positive maxLines, no list options, no tabs, and a space actually adjacent to a break. HUG text is excluded because pre-wrap counts trailing spaces in max-content width and would change intrinsic sizing; clamped text keeps its existing projection.

On the four goldens

Four plugin goldens gain six whiteSpace attributes. This is the opposite case to Korean keep-all, and the distinction is the whole argument.

With keep-all, matching Figma would have produced worse Korean - words chopped mid-break - so the compensation was deliberately kept and the pixel gain rejected. Here the design contains a space and CSS eats it, so preserving it makes the output match the source. The plugin drops that space; here the plugin is the one diverging from the design.

Each golden was reviewed against its collected fixture: 165 (node 1:18), 191 (107:32), 252 (284:18751/18753/18754), 253 (213:7494). Six attribute additions, no other output change, only those four checksums touched, corpus back to 268/268.

docs/about-landing-mobile-golden-review.md records the per-node review so a future reader can tell these two cases apart without re-deriving them - they look superficially identical and the answers are opposite.

Verification

Measured independently with binaries built from main and this branch, full 15-screen acquire and render on each side, repeated. My figures match the worker's to the decimal, and the baseline run fails correctly against all four tightened thresholds - confirming the two runs measure different code rather than reusing inputs.

New label derived-hard-break-whitespace states it preserves source whitespace without claiming intrinsic HUG sizing, glyph parity or identical wrapping. No viewport, breakpoint or node id in production code.

Gates: fmt 0, clippy 0, cargo test --workspace 1084 passed / 0 failed / 2 ignored, insta --check no drift, corpus 268/268.

Still open

A separate hero-export defect is quantified in the report but not fixed: it needs an isolated-fill export contract with crop and multi-paint validation first. Left documented rather than forced.

@owjs3901
owjs3901 merged commit 3e593b4 into main Sep 13, 2026
8 checks passed
@owjs3901
owjs3901 deleted the integration/hard-break-whitespace branch September 13, 2026 13: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