Skip to content

fix(markdown_parser): fix lazy continuation at nested list marker indent#9776

Merged
dyc3 merged 2 commits intobiomejs:mainfrom
jfmcdowell:fix/md-list-continuation-indent-off-by-one
Apr 2, 2026
Merged

fix(markdown_parser): fix lazy continuation at nested list marker indent#9776
dyc3 merged 2 commits intobiomejs:mainfrom
jfmcdowell:fix/md-list-continuation-indent-off-by-one

Conversation

@jfmcdowell
Copy link
Copy Markdown
Contributor

@jfmcdowell jfmcdowell commented Apr 2, 2026

Note

This PR was created with AI assistance (Claude Code).

Summary

Two fixes to lazy continuation handling when a line's indent equals the nested list marker column:

  1. Ownership: changed <= to < in check_continuation_indent (list.rs:2083) so the line can reach the lazy continuation check at line 2091 instead of being prematurely assigned to the parent item.
  2. Structural emission: added MdContinuationIndent emission on the lazy path, matching the sufficient-indent path at line 2052. Without this, the indent spaces were parsed as MD_TEXTUAL_LITERAL instead of MD_INDENT_CHAR inside a structural MdContinuationIndent node.

Example:

- outer
  - nested paragraph
  lazy line

Previously lazy line was assigned to the outer item. Now it correctly lazy-continues the nested paragraph per CommonMark §5.2, with the leading spaces represented structurally.

Test Plan

  • New CST snapshot fixture: tests/md_test_suite/ok/lazy_continuation_at_marker_indent.md — locks in both ownership and structural indent behavior.
  • cargo test -p biome_markdown_parser quick_test — HTML output verified against commonmark.js reference.
  • just test-crate biome_markdown_parser — all passed (79 snapshot tests).
  • just test-markdown-conformance — 652/652.
  • just f
  • just l

Docs

N/A.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 2, 2026

⚠️ No Changeset found

Latest commit: 2e71c60

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions github-actions bot added A-Parser Area: parser L-Markdown Language: Markdown labels Apr 2, 2026
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Apr 2, 2026

Merging this PR will not alter performance

✅ 28 untouched benchmarks
⏩ 228 skipped benchmarks1


Comparing jfmcdowell:fix/md-list-continuation-indent-off-by-one (2e71c60) with main (35305c9)

Open in CodSpeed

Footnotes

  1. 228 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Change `<=` to `<` in `check_continuation_indent` so a line at exactly
the nested marker's indent column can lazily continue the nested
paragraph per CommonMark §5.2, instead of being incorrectly assigned
to the parent item.

Emit the available indent as a structural MdContinuationIndent node
on the lazy path, matching the sufficient-indent path, so indent
spaces appear as MD_INDENT_CHAR rather than MD_TEXTUAL_LITERAL.
@jfmcdowell jfmcdowell force-pushed the fix/md-list-continuation-indent-off-by-one branch from a282821 to 06201a2 Compare April 2, 2026 17:15
@jfmcdowell jfmcdowell marked this pull request as ready for review April 2, 2026 17:43
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 2, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9829d11c-7059-4be8-a4e6-fffff379a6dc

📥 Commits

Reviewing files that changed from the base of the PR and between 06201a2 and 2e71c60.

📒 Files selected for processing (1)
  • crates/biome_markdown_parser/src/syntax/list.rs

Walkthrough

The patch changes continuation-indent handling in the Markdown list parser by removing an early break for lazy continuations at the marker column. For the lazy-continuation path (!state.last_block_was_paragraph) the parser now emits an MD_CONTINUATION_INDENT structural node with the current indent, returns LoopAction::FallThrough, and restores virtual_line_start via VirtualLineRestore::Restore(prev_virtual) instead of breaking. Tests and fixtures were added/updated to validate lazy continuation at the nested marker indent.

Possibly related PRs

Suggested reviewers

  • dyc3
  • ematipico
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarises the main change: fixing lazy continuation handling at nested list marker indentation in the markdown parser.
Description check ✅ Passed The description clearly explains both fixes (ownership and structural emission), includes a concrete example, and documents the test verification performed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
crates/biome_markdown_parser/src/syntax/list.rs (1)

2080-2087: Drop the now-unreachable guard.

Line 2012 already exits on indent < state.marker_indent, so this branch can no longer fire after the <=< change. Keeping it here makes the lazy-continuation rules look more complicated than they are.

♻️ Suggested tidy-up
-        // If the line's indent falls strictly below the nested marker column,
-        // it belongs to the parent item. Lines at exactly marker_indent may
-        // still lazily continue the nested paragraph per CommonMark §5.2.
-        if state.marker_indent > 0 && indent < state.marker_indent {
-            return ContinuationResult {
-                action: LoopAction::Break,
-                restore: VirtualLineRestore::None,
-            };
-        }
-
         // Lazy continuation per CommonMark §5.2
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/biome_markdown_parser/src/syntax/list.rs` around lines 2080 - 2087,
Remove the now-unreachable guard that checks "if state.marker_indent > 0 &&
indent < state.marker_indent" and returns ContinuationResult { action:
LoopAction::Break, restore: VirtualLineRestore::None }; since earlier logic
already returns when indent < state.marker_indent (see the earlier exit at line
~2012), delete this whole branch from the function (references:
state.marker_indent, indent, ContinuationResult, LoopAction::Break,
VirtualLineRestore::None) so the lazy-continuation rules are clearer and no dead
branch remains.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/biome_markdown_parser/src/syntax/list.rs`:
- Around line 2080-2087: Remove the now-unreachable guard that checks "if
state.marker_indent > 0 && indent < state.marker_indent" and returns
ContinuationResult { action: LoopAction::Break, restore:
VirtualLineRestore::None }; since earlier logic already returns when indent <
state.marker_indent (see the earlier exit at line ~2012), delete this whole
branch from the function (references: state.marker_indent, indent,
ContinuationResult, LoopAction::Break, VirtualLineRestore::None) so the
lazy-continuation rules are clearer and no dead branch remains.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8534c162-6072-47b2-b554-90ecc437b4bb

📥 Commits

Reviewing files that changed from the base of the PR and between 35305c9 and 06201a2.

⛔ Files ignored due to path filters (3)
  • crates/biome_markdown_parser/tests/md_test_suite/ok/lazy_continuation_at_marker_indent.md.snap is excluded by !**/*.snap and included by **
  • crates/biome_markdown_parser/tests/md_test_suite/ok/list_continuation_edge_cases.md.snap is excluded by !**/*.snap and included by **
  • crates/biome_markdown_parser/tests/md_test_suite/ok/list_indentation.md.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (3)
  • crates/biome_markdown_parser/src/syntax/list.rs
  • crates/biome_markdown_parser/tests/md_test_suite/ok/lazy_continuation_at_marker_indent.md
  • crates/biome_markdown_parser/tests/spec_test.rs

@dyc3 dyc3 merged commit 383cdfa into biomejs:main Apr 2, 2026
16 checks passed
@jfmcdowell jfmcdowell deleted the fix/md-list-continuation-indent-off-by-one branch April 13, 2026 12:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Parser Area: parser L-Markdown Language: Markdown

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants