Skip to content

fix: preserve lazy continuation lines in ordered lists (CommonMark)#7694

Open
bdbch wants to merge 4 commits intomainfrom
fix/ordered-list-lazy-continuation
Open

fix: preserve lazy continuation lines in ordered lists (CommonMark)#7694
bdbch wants to merge 4 commits intomainfrom
fix/ordered-list-lazy-continuation

Conversation

@bdbch
Copy link
Copy Markdown
Member

@bdbch bdbch commented Apr 3, 2026

Changes Overview

Fix ordered-list markdown parsing so non-indented lazy continuation lines are kept as part of the current list item (CommonMark §5.3). This prevents continuation text from being dropped when marked is configured with breaks: true and preserves nested list behavior.

Implementation Approach

  • Updated collectOrderedListItems in packages/extension-list/src/ordered-list/utils.ts to track whether a blank line has been seen and treat non-indented, non-list lines before a blank line as "lazy continuation" belonging to the current list item.
  • Added contentLines on OrderedListItem, splitItemContent(), and isBlockContentLine() helpers to separate paragraph (inline) lines from block-level lines.
  • Updated buildNestedStructure() to create the first paragraph using lexer.inlineTokens() for the joined paragraph lines (so breaks: true produces hardBreak tokens), and to parse later block content through lexer.blockTokens() so nested lists / block nodes remain intact.
  • Added a focused regression test packages/markdown/__tests__/ordered-list-lazy-continuation.spec.ts that runs with markedOptions: { breaks: true } and verifies lazy continuation, nested bullet preservation, and blank-line termination.
  • Added a changeset: .changeset/ordered-list-lazy-continuation.md.

Testing Done

  • Ran the new focused spec: pnpm vitest run packages/markdown/__tests__/ordered-list-lazy-continuation.spec.ts — all tests passed.
  • Ran the markdown conversion suite: pnpm vitest run packages/markdown/__tests__/conversion.spec.ts — all tests passed.
  • Verified the repository commit includes the changeset and tests.

Verification Steps

  • Checkout branch: git fetch && git checkout fix/ordered-list-lazy-continuation
  • Run the focused spec:
pnpm vitest run packages/markdown/__tests__/ordered-list-lazy-continuation.spec.ts
  • Run the markdown conversion suite to ensure no regressions:
pnpm vitest run packages/markdown/__tests__/conversion.spec.ts

Additional Notes

  • The change keeps blank-line semantics intact: a non-indented continuation line before a blank line is part of the previous list item; a non-indented line after a blank line terminates the list.
  • The fix is intentionally conservative: paragraph (inline) lines are tokenized with inlineTokens() to preserve hardBreak nodes when breaks: true, while later block content is parsed via blockTokens() to retain nested lists and block nodes.

Checklist

  • I have created a changeset for this PR.
  • My changes do not break the library (local markdown tests passed).
  • I have added tests where applicable.
  • I have followed the project guidelines.
  • I have fixed any lint issues.

Related Issues

Fixes: #7677

…s\n\nAdd regression test; ensure non-indented continuation lines before a blank line remain part of the current list item. Fixes #7677.
Copilot AI review requested due to automatic review settings April 3, 2026 10:38
@netlify
Copy link
Copy Markdown

netlify bot commented Apr 3, 2026

Deploy Preview for tiptap-embed ready!

Name Link
🔨 Latest commit d755a5d
🔍 Latest deploy log https://app.netlify.com/projects/tiptap-embed/deploys/69cf9e4a5783ce00092b2ef1
😎 Deploy Preview https://deploy-preview-7694--tiptap-embed.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 3, 2026

🦋 Changeset detected

Latest commit: d755a5d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 72 packages
Name Type
@tiptap/extension-list Patch
@tiptap/extension-bullet-list Patch
@tiptap/extension-ordered-list Patch
@tiptap/starter-kit Patch
@tiptap/extension-list-item Patch
@tiptap/extension-list-keymap Patch
@tiptap/extension-task-item Patch
@tiptap/extension-task-list Patch
@tiptap/core Patch
@tiptap/extension-audio Patch
@tiptap/extension-blockquote Patch
@tiptap/extension-bold Patch
@tiptap/extension-bubble-menu Patch
@tiptap/extension-code-block-lowlight Patch
@tiptap/extension-code-block Patch
@tiptap/extension-code Patch
@tiptap/extension-collaboration-caret Patch
@tiptap/extension-collaboration Patch
@tiptap/extension-color Patch
@tiptap/extension-details Patch
@tiptap/extension-document Patch
@tiptap/extension-drag-handle-react Patch
@tiptap/extension-drag-handle-vue-2 Patch
@tiptap/extension-drag-handle-vue-3 Patch
@tiptap/extension-drag-handle Patch
@tiptap/extension-emoji Patch
@tiptap/extension-file-handler Patch
@tiptap/extension-floating-menu Patch
@tiptap/extension-font-family Patch
@tiptap/extension-hard-break Patch
@tiptap/extension-heading Patch
@tiptap/extension-highlight Patch
@tiptap/extension-horizontal-rule Patch
@tiptap/extension-image Patch
@tiptap/extension-invisible-characters Patch
@tiptap/extension-italic Patch
@tiptap/extension-link Patch
@tiptap/extension-mathematics Patch
@tiptap/extension-mention Patch
@tiptap/extension-node-range Patch
@tiptap/extension-paragraph Patch
@tiptap/extension-strike Patch
@tiptap/extension-subscript Patch
@tiptap/extension-superscript Patch
@tiptap/extension-table-of-contents Patch
@tiptap/extension-table Patch
@tiptap/extension-text-align Patch
@tiptap/extension-text-style Patch
@tiptap/extension-text Patch
@tiptap/extension-twitch Patch
@tiptap/extension-typography Patch
@tiptap/extension-underline Patch
@tiptap/extension-unique-id Patch
@tiptap/extension-youtube Patch
@tiptap/extensions Patch
@tiptap/html Patch
@tiptap/markdown Patch
@tiptap/pm Patch
@tiptap/react Patch
@tiptap/static-renderer Patch
@tiptap/suggestion Patch
@tiptap/vue-2 Patch
@tiptap/vue-3 Patch
@tiptap/extension-character-count Patch
@tiptap/extension-dropcursor Patch
@tiptap/extension-focus Patch
@tiptap/extension-gapcursor Patch
@tiptap/extension-history Patch
@tiptap/extension-placeholder Patch
@tiptap/extension-table-cell Patch
@tiptap/extension-table-header Patch
@tiptap/extension-table-row Patch

Not sure what this means? Click here to learn what changesets are.

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

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the ordered-list Markdown tokenizer in @tiptap/extension-list to better match CommonMark behavior for “lazy continuation lines”, ensuring non-indented continuation lines remain inside the current ordered list item (until a blank line ends the item). It also adds Markdown-level regression tests to confirm parsing behavior (including marked line-break handling).

Changes:

  • Adjust ordered-list item collection to include non-indented lazy continuation lines until a blank line or the next ordered list marker.
  • Split list-item content into “paragraph” vs “block” parts to preserve inline continuation while still allowing nested block parsing.
  • Add Markdown parsing regression tests and a changeset for the user-facing behavior change.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
packages/markdown/__tests__/ordered-list-lazy-continuation.spec.ts Adds regression tests covering lazy continuation lines, nested bullets, and blank-line termination.
packages/extension-list/src/ordered-list/utils.ts Implements updated ordered-list item collection and content splitting to preserve lazy continuations.
.changeset/ordered-list-lazy-continuation.md Adds a patch changeset documenting the ordered-list parsing fix.

Comment on lines +27 to +37
function isBlockContentLine(line: string): boolean {
const trimmedLine = line.trimStart()

return (
/^[-+*]\s+/.test(trimmedLine) ||
/^\d+\.\s+/.test(trimmedLine) ||
/^>\s?/.test(trimmedLine) ||
/^```/.test(trimmedLine) ||
/^~~~/.test(trimmedLine)
)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could there be other block content elements that are not covered here?

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.

OrderedList markdownTokenizer drops lazy continuation lines (CommonMark)

3 participants