fix(tiptap): prevent star accumulation when bold text contains a link#481
Draft
hendrikheil wants to merge 8 commits into
Draft
fix(tiptap): prevent star accumulation when bold text contains a link#481hendrikheil wants to merge 8 commits into
hendrikheil wants to merge 8 commits into
Conversation
When a paragraph like `**text **[link](url)**.**` was opened in the TipTap editor and saved, the link gained extra `**` markers on each cycle (visible as `****` in the rendered markdown). Root cause was a three-step chain: 1. `comarkToTiptap` / `createMark`: nested `strong > strong` produced duplicate bold marks on the link text node (e.g. `[link, bold, bold]`). 2. `createParagraphElement` / `getMarkInfo`: a text node with 2+ marks returned `null`, so the link text was split into its own block instead of staying inside the surrounding bold run. 3. The block wrap path returned a raw `ComarkElement` that `.flat()` then spread into individual tokens, corrupting the sibling list. Fixes: - `createMark`: skip adding a mark that is already present in the accumulated set, preventing duplicate bold marks on nested same-type elements (mirrors TipTap's own schema deduplication). - `getMarkInfo`: for a text node whose marks contain exactly one structural (non-link) mark, return that mark — keeping the node grouped with its surrounding bold/italic block. - Mark stripping in the block-wrap path: only remove the block mark (e.g. bold), preserving link and other inline marks so they survive as child elements. - Multi-item block return value: wrap the ComarkElement in an array so the outer `.flat()` treats it as a single sibling, not spreading its contents into the parent list. Fixes nuxt-content#470 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
|
@hendrikheil is attempting to deploy a commit to the Nuxt Team on Vercel. A member of the Team first needs to authorize it. |
commit: |
- Use `m.type in markToTag` in `getMarkInfo` instead of `m.type !== 'link'`, making markToTag the single source of truth for block-grouping marks - Remove the redundant `length === 1` branch in `getMarkInfo`; the filter handles it uniformly - Simplify `createMark` dedup to a type-only check; structural marks carry no distinguishing attrs so JSON.stringify comparison was unnecessary - Collapse the two-step mark-strip into a single `|| undefined` assignment - Hoist the shared test fixture to describe-block scope Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three adjacent <strong> siblings (from a bold text, bold link, and bold period) were rendered as **a****b****c** instead of **a b c** because `mergeSiblingsWithSameTag` only merged pairs separated by a single space and did not absorb any further adjacent same-tag siblings that followed. Fix by adding an inner continuation loop after the space-separator merge and a new adjacent-sibling merge path, both using `absorb` (which spreads sibling children into the accumulator to preserve the existing flat-merge semantics). The em/em case (*y **x***) is unaffected. Closes nuxt-content#470 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
Problem
Opening and saving a file containing a pattern like
**text **[link](url)**.**caused**markers to multiply on each save cycle. After one round-trip through the editor the link gained extra stars, producing****sequences in the rendered markdown.Reported in #470 ("MDC autoformatter constantly breaking links and formatting").
Root cause
A three-step chain in the TipTap ↔ ComarkTree conversion layer:
Step 1 —
comarkToTiptap/createMarkWhen traversing
["strong", {}, "text", ["strong", {}, ["a", ...]]], the outerstrongadds aboldmark, and the innerstrongadds a secondboldmark. The link text node ended up with[link, bold, bold]marks instead of[link, bold].Step 2 —
tiptapToComark/createParagraphElement/getMarkInfogetMarkInfoonly returned a mark when a text node had exactly one mark. With[link, bold](after TipTap's own deduplication), the link text returnednull, so it was split into a separate block instead of staying inside the surrounding bold run. Three separatestrongsiblings were produced instead of one.Step 3 —
.flat()on the block resultThe multi-item block path returned a raw
ComarkElement..flat()then spread its children into the parent list, corrupting the node structure.Fixes
comarkToTiptapcreateMarktiptapToComarkgetMarkInfotiptapToComarkmark-strippingtiptapToComarkblock-wrap returnComarkElementin an array so.flat()treats it as one siblingResult
**that contain it **[here](/url)**.**now round-trips stably to**that contain it [here](/url).**— one bold run, link preserved, no extra stars.Tests
New test file
tiptapToComark.test.ts:strongparent with text + link + text as direct children****All 337 tests pass.