Repository navigation
fix(ios): retain intrinsic width for explicit line breaks - #1017
Merged
Merged
Conversation
…not re-wrap Walk the line fragments once: stop at the first soft wrap (report maxWidth, as before) and otherwise return a tight width that adds each line's head indent and negative tail indent to its used rect. TextKit's usedRect leaves both out, so lists, code blocks and blockquotes measured narrower than they need and re-wrapped once Yoga handed the width back as the frame. Hard breaks are any newlineCharacterSet member at a fragment's end, and the scan exits early once the width reaches maxWidth. ENRMFinalizeMeasuredTextSize reads the layout manager's own text storage and drops its text parameter. Tests render real markdown through the parser and renderer and assert that relaying at the measured width keeps the line count and height, which fails on the previous implementation for lists, code blocks and blockquotes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
3 of 6 tasks
eszlamczyk
approved these changes
Oct 16, 2026
Comment on lines
+33
to
+36
| typedef struct { | ||
| BOOL hasSoftWrap; | ||
| CGFloat tightWidth; | ||
| } ENRMLineFragmentScan; |
Collaborator
There was a problem hiding this comment.
I feel like this struct is unnecessary. The logic assumed here is something like:
If there is a soft wrap we use maxWidth else we use MIN(maxWidth, calculatedLineWidth) I feel like it would be easy to remove this flag (and this struct at all and just return maxWidth in the early return paths.
The caller then becomes
CGFloat contentWidth = ENRMContentWidth(layoutManager, maxWidth);
if (contentWidth > 0) measuredWidth = contentWidth;Soft wrap and reaching maxWidth both resolve to maxWidth, and tightWidth was incomplete whenever hasSoftWrap was set, so the struct carried no information the caller needed. Pass usedRect width as the fallback instead of a 0 sentinel so a zero maxWidth still clamps to 0.
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.
What/Why?
Short text such as
one\n\ntwoin a content-sized view expands tomaxWidthon iOS because measurement treats any second line fragment as a soft wrap. Content broken only by explicit newlines now keeps its tight width; soft-wrapped content still reportsmaxWidthso flexShrink cannot re-wrap it.This carries @Yash-Singh1's #991 (bd6f647) unchanged as the first commit plus one follow-up. #991 comes from an organization-owned fork, which GitHub does not let maintainers push to, so the follow-up lands here. #991 stays open for the discussion there and closes when this merges; both commits keep their authorship.
Closes #990.
Follow-up commit on top of #991
usedRect.size.widthis not the width the content needs: TextKit's used rect starts at the head indent and never includes a negativetailIndent. Lists, code blocks and blockquotes rely on both, so once the pin stopped applying to them they measured too narrow and re-wrapped when Yoga handed the width back as the frame. Single-line lists already had this onmain; multi-line lists and every code block and blockquote were protected by the pin.ENRMScanLineFragmentswalks the fragments once. It stops at the first soft wrap and reportsmaxWidth. Otherwise it returns a tight width that adds each line's head indent and negative tail indent to its used rect, which is direction and alignment independent.newlineCharacterSetmember at a fragment's end.maxWidthand bails out on fragments past anumberOfLinesclamp.ENRMFinalizeMeasuredTextSizereads the layout manager's own text storage and drops itstextparameter.TextMeasurementTests.mm, named by feature like fix: size ordered list markers to their widest number #1015. Every case renders real markdown with non-zero code block and blockquote padding. Tight cases assert the width is belowmaxWidthand that relaying at it keeps the line count and height, which fails on the previous implementation for lists, code blocks and blockquotes.Testing
maxWidth.- alpha beta\n- gammawent from 2 to 3 lines,1. alpha beta\n2. gammafrom 2 to 4, a two-line fenced block from 5 to 6, a blockquote from 4 to 5. After: unchanged.PR Checklist
🤖 Generated with Claude Code