fix: better list children rendering logic#478
Draft
eszlamczyk wants to merge 16 commits into
Draft
Conversation
eszlamczyk
commented
Jul 1, 2026
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?
Fixes #243 — lists containing block children (fenced code blocks, nested sublists) rendered broken: markers
were lost or drawn inside code blocks, checked-task strikethrough bled across code, and code blocks ignored
list indentation.
Root cause: list styling was applied post-hoc — children rendered list-ignorant, then
ListItemRendererstamped indent/marker metadata over the result, which broke whenever an item's first child wasn't plain text.
This PR moves list layout to a top-down model:
Shared parser (
packages/core/cpp)wrapListItemInlineRunspost-pass: md4c emits bare inline children for tight list items; they're now wrappedin synthetic
Paragraphnodes (markedtight), so renderers only ever see block children. One change coversiOS, Android (JNI) and web (rebuilt
md4c.js; web renderers needed no changes).iOS
BaseRendereris now a template method (renderNode:= snapshot scope →renderNodeContent:→ restore).RenderContext.snapshotScope/restoreScopereplaces the per-renderer@try/@finallypartial restores and stopsblock-style state leaking between sibling blocks.
RenderContext.accumulatedIndent:ListItemRendererpushes the item indent around its children;CodeBlockRendererfolds it into its paragraph style andCodeBlockBackgroundinsets the background rect —code blocks in list items now render indented under the item content (CommonMark behavior).
ENRMListMarkerDescriptors planted on the item's first content character(appending when one already exists).
ListMarkerDrawerdraws every descriptor at its own gutter — fixesmissing markers on code-block-first items, draws both markers (browser-style) for sublist-first items, and no
longer duplicates markers per paragraph in loose items.
Android (mirror)
BlockStyleContext.accumulatedIndent→CodeBlockSpan.leadingIndent(leading margin + background inset).BaseListSpansplit into segments around code blocks (keeps the metric-affecting span off code text), singledrawsMarkerowner per item; when the item starts with a code block/sublist, a zero-marginListMarkerAnchorSpandraws the marker instead.applyCheckedDecorationsexcludes code-block ranges — no more strikethrough across code in checked tasks;inline-code backgrounds and line-height spans are list-margin aware.
Not in scope (pre-existing): ordered-list
startis ignored by the parser (1.+ nested2. xrenders1. 1. x).Testing
yarntest:e2e:mobile --include-tags list,code_block,task_list.Screenshots
PR Checklist