Skip to content

Fix a blank line with partial indent evicting a list item early - #629

Open
afonsojanu wants to merge 1 commit into
commonmark:masterfrom
afonsojanu:fix/blank-line-partial-indent-evicts-list-item
Open

Fix a blank line with partial indent evicting a list item early#629
afonsojanu wants to merge 1 commit into
commonmark:masterfrom
afonsojanu:fix/blank-line-partial-indent-evicts-list-item

Conversation

@afonsojanu

Copy link
Copy Markdown

Fixes #618.

A blank line inside a list item made up only of spaces short of the item's own indent width would end the item early and push whatever came after out as a sibling paragraph, even though a fully empty blank line or one padded out to the full indent width kept the item open.

The three shapes from the issue only diverge when the item's opening line is a link reference definition on its own. Once the reference resolves, finalize() frees that now-empty paragraph, and parse_node_item_prefix was using container->first_child == NULL as a stand-in for "the opening line was blank", since normally that's the only way an item ends up childless at this point. A reference-only opening line hits the same childless state for a different reason entirely, so a later short blank line got misread as "this item never had anything in it." A blank line with zero or full-width indent happens to avoid the branch in parse_node_item_prefix that even looks at first_child, which is why only the partial-indent case showed the bug.

Added a CMARK_NODE__ITEM_HAD_CONTENT flag, set on the item when a reference-only paragraph belonging to it gets freed, and checked alongside first_child. Added a regression test using the exact input from the issue.

Ran the full local suite (api tests, CommonMark spec tests, smart punctuation tests, regression tests) before and after. Confirmed the new case fails without the blocks.c change (reverted it locally, rebuilt, saw the failure) and passes with it restored.

Reported in commonmark#618: a blank line inside a list item, made up only of
spaces that fall short of the item's own indent width, would end the
item and push whatever came after out as a sibling paragraph, even
though a fully empty blank line or one padded to the full indent width
kept the item open just fine.

The three cases only diverge when the item's opening line consisted
solely of a link reference definition. Once the reference resolves,
finalize() frees that now-empty paragraph, and parse_node_item_prefix
was using container->first_child == NULL as a proxy for "the opening
line was blank", since that's normally the only way an item ends up
childless. A reference-only opening line hits the same childless state
for an unrelated reason, so a later short blank line got read as "this
item never had anything in it" and the item closed prematurely. A
blank line with zero or full-width indent happened to avoid the branch
in parse_node_item_prefix that checks first_child at all, which is why
only the partial-indent case showed the bug.

Added a CMARK_NODE__ITEM_HAD_CONTENT flag, set on the item when a
reference-only paragraph belonging to it is freed, and checked
alongside first_child in parse_node_item_prefix. Added a regression
test to test/regression.txt using the exact shape from the issue.

Ran the full local suite (api tests, CommonMark spec tests, smart
punctuation tests, and the regression suite) before and after: all
green after, and the new case fails without the fix, confirmed by
temporarily reverting just the blocks.c change and rebuilding.
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.

Single-space blank line evicts a list-item continuation

1 participant