Visitar URL original
fix(extension-list): use item's own indent as base for ordered-list markdown nesting by codewithsupra · Pull Request #7998 · ueberdosis/tiptap · GitHub
Skip to content

fix(extension-list): use item's own indent as base for ordered-list markdown nesting - #7998

Merged
arnaugomez merged 2 commits into
ueberdosis:mainfrom
codewithsupra:fix/ordered-list-indented-markdown-inline-parsing
Jul 6, 2026
Merged

arnaugomez merged 2 commits into
ueberdosis:mainfrom
codewithsupra:fix/ordered-list-indented-markdown-inline-parsing

Conversation

@codewithsupra

Copy link
Copy Markdown
Contributor

Fixes #7966.

Indented ordered list items lose inline formatting when parsed as markdown. Minimal repro from the issue:

manager.parse('1. bold item') -- correct: "bold" gets a bold mark
manager.parse(' 1. bold item') -- broken: literal text "bold item", no mark

The only difference is a single leading space before the marker (the case that occurs when a top-level ordered list is itself nested inside another list).

Root cause: OrderedList's custom markdown tokenizer (packages/extension-list/src/ordered-list/ordered-list.ts) calls buildNestedStructure(listItems, 0, lexer) with a hardcoded baseIndent of 0. collectOrderedListItems() correctly records each item's actual indentation (indent: 1 for a line with one leading space), but buildNestedStructure() only includes an item if item.indent === baseIndent. With the hardcoded 0, an indented top-level item never matches its own list's base indent, so buildNestedStructure() silently returns zero items and the tokenizer bails out. That fallback path skips this extension's inline tokenizer, so bold/italic markup ends up as literal text.

I confirmed this by logging the intermediate arrays: for ' 1. bold item', listItems[0].indent is 1, buildNestedStructure(listItems, 0, lexer) returns [], and the tokenizer falls back -- reproducing the exact broken output from the issue.

Fix: derive baseIndent from the first collected item's own indent instead of hardcoding it to 0.

Tests: added a test to packages/extension-list/tests/orderedListType.spec.ts asserting that the indented and non-indented inputs parse to identical JSON, both with the bold mark applied. Verified the test actually catches the bug by reverting only the one-line fix (keeping the test) and confirming it fails with the exact broken output described in the issue, then restoring the fix and confirming it passes. Full monorepo suite (1365 tests) passes with no regressions.

Added a patch-level changeset for @tiptap/extension-list.

…arkdown nesting

Fixes ueberdosis#7966

The custom ordered-list markdown tokenizer's buildNestedStructure()
was always called with a hardcoded baseIndent of 0. When the first
collected list item's actual indentation was non-zero (e.g. a single
leading space before the marker, which happens when a top-level
ordered list is itself nested inside another list), the item's indent
never matched baseIndent, so buildNestedStructure() produced zero
items and the tokenizer bailed out (returned undefined).

That fallback path does not run the item's content back through this
extension's inline tokenizer, so markdown like ' 1. **bold** item'
(leading space) parsed the whole remainder as literal text instead of
producing a bold mark — while '1. **bold** item' (no leading space)
worked correctly, since it happened to match the hardcoded baseIndent
of 0.

Fix: derive baseIndent from the first collected item's own indent
instead of hardcoding it to 0.

Verified by reverting only the one-line fix (keeping the new test) and
confirming the test fails with the exact broken output described in
the issue, then passes again with the fix restored. Full monorepo
suite (1365 tests) passes with no regressions.
@changeset-bot

changeset-bot Bot commented Jul 5, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1f3ca7a

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/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/starter-kit 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

@netlify

netlify Bot commented Jul 5, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for tiptap-embed ready!

Name Link
🔨 Latest commit 2b611ab
🔍 Latest deploy log https://app.netlify.com/projects/tiptap-embed/deploys/6a4be918a923a1000818fccc
😎 Deploy Preview https://deploy-preview-7998--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.

Comment on lines +246 to +253
// The first collected item defines the indentation level of this list.
// Using a hardcoded 0 here meant an indented top-level list (e.g. one
// space before the marker, as can happen when nested inside another
// list) never matched its own indent in buildNestedStructure, silently
// produced zero items, and made this tokenizer bail out — falling back
// to marked's default list handling, which does not run this list's
// items back through this extension's inline tokenizer.
const items = buildNestedStructure(listItems, listItems[0].indent, lexer)

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.

In the comment, do not mention how it was configured in the past

Using a hardcoded 0 here meant...

Instead, explain how it is configured now and why. For example, you can explain why it passes the indentation level of the list and not a hardcoded 0, and what would happen if we passed a hardcoded 0.

Addresses review feedback: the comment explained what the old (buggy)
code did instead of describing the current code and why it's written
this way.
@arnaugomez
arnaugomez merged commit 94de762 into ueberdosis:main Jul 6, 2026
13 checks passed
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.

Indented ordered list markdown does not parse inline formatting correctly

2 participants