css+layout: implement word-break:break-all and overflow-wrap:break-word - #243
Merged
Merged
Conversation
An unbreakable "word" wider than its own line always overflowed its container instead of wrapping. Confirmed on three independent real pages: pkg.go.dev's own file/directory listings (word-break:break-all and :break-word), news.ycombinator.com's story headline links (word-break:break-word), and developer.mozilla.org, which sets overflow-wrap:break-word on <html> itself, inherited page-wide. Both properties (and word-break:break-word's deprecated alias) OR into one css.Style.BreaksOverlongWords() check, kept as two separate fields rather than one shared boolean so an unrelated word-break:normal can never silently cancel an independent overflow-wrap:break-word from a different declaration. layoutInline's splitOverlongWord tries splitting the leading overlong item at a rune boundary right before forceOne's own unconditional overflow, on exactly the item forceOne would otherwise place whole. Scoped to exactly the one evidenced effect (avoid overflow), not break-all's stronger "break eagerly" behaviour, overflow-wrap:anywhere's intrinsic-sizing effect, word-break:keep-all, or splitting within a glued run — none of which have a confirmed real-world trigger here. Also documents columns/column-count (found the same round, real trigger on pkg.go.dev's own file list, but a genuinely new multi-column layout algorithm — deferred to its own round) and a pre-existing, unrelated forceOne/glueRun inconsistency found while testing this (an overflowing glued run splits at its glue seam; not fixed, no confirmed trigger). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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
word-break/overflow-wrapwere entirely unimplemented: an unbreakable "word" wider than its own line always overflowed its container instead of wrapping. Confirmed on three independent real pages: pkg.go.dev's own file/directory listings (word-break:break-alland:break-word), news.ycombinator.com's story headline links (word-break:break-word), and developer.mozilla.org, which setsoverflow-wrap:break-wordonhtmlitself — inherited page-wide.word-break:break-word's deprecated alias) OR into onecss.Style.BreaksOverlongWords()check, kept as two separate fields (WordBreakAll,OverflowWrapAnywhere) rather than one shared boolean — collapsing them at parse time would let an unrelatedword-break:normalon a later declaration silently cancel an independent, earlieroverflow-wrap:break-word, which real CSS's cascade would not do.layout/layout.go's newsplitOverlongWordtries splitting the leading overlong item at a rune boundary right beforeforceOne's own unconditional overflow, on exactly the itemforceOnewould otherwise place whole.break-all's stronger "break eagerly even when a word already fits" behaviour,overflow-wrap:anywhere's distinct intrinsic-sizing effect,word-break:keep-all(no CJK line-breaking to suppress), or splitting within a glued run (152,3<sup>†</sup>-shaped) — none of which have a confirmed real-world trigger here.columns/column-countin FIDELITY.md's Known Gaps (found the same round via the same CSS-property audit, real trigger on pkg.go.dev's own file list, but a genuinely new multi-column layout algorithm — deferred to its own round) and a pre-existing, unrelatedforceOne/glueRuninconsistency found while testing this fix (an overflowing glued run splits at its own glue seam; not fixed here, no confirmed real-world trigger for that specific combination).Test plan
go build ./...,go vet ./...,go test ./...all greenlayoutback to its 100.0% ratchet floor — an initial version ofsplitOverlongWordhad unreachable defensive code the floor caught immediately; simplified rather than tested around)css/parse_test.go(TestApplyWordBreak/TestApplyOverflowWrap/TestBreaksOverlongWords— every value, the deprecated alias,unset, explicitinherit,inheritFrom) andlayout/layout_test.go(six tests: the unaffected default, both properties independently reaching the same split, no effect on already-fitting text, inheritance to a descendant, the single-rune-cannot-split edge, and the pre-existing glued-run behaviour)css/parse.go/css/value.go/layout/layout.goalone (keeping the new tests) fails to even compile (s.WordBreakAll undefined)columnsgap)🤖 Generated with Claude Code