fix(editor): four things that were quietly not working - #16
Merged
christianhuening merged 1 commit intoSep 5, 2026
Merged
Conversation
Found while building the Tiptap 3 baseline coverage. All four predate that
work; each was reproduced before being fixed, and each fix was verified by
reverting it and watching the new test go red.
List keyboard shortcuts threw. Renaming a node does not rewrite the options
its own commands read: BulletList and OrderedList resolve
`options.itemTypeName`, still the camelCase "listItem", so
`toggleBulletList()` raised "There is no node type named 'listItem'" and
Mod-Shift-8 / Mod-Shift-7 did nothing but log. The toolbar buttons pass both
names explicitly, which is why only the shortcuts were affected. ListItem
declares bulletListTypeName/orderedListTypeName too, but nothing in v2 reads
them -- its keymaps pass `this.name` -- so they are deliberately left alone
rather than configured to no effect.
Link titles were dropped. tools/schema.json declares `title` on the link
mark and both from_markdown and to_markdown honour it, but Tiptap's Link has
no such attribute and ProseMirror discards what its schema does not declare.
So `[text](url "title")` survived import and was rewritten without the title
the first time anyone edited the document -- in storage, for every reader.
The parity check added in the previous commit now catches this class outright,
so UNIMPLEMENTED_ATTRS is empty and should stay that way.
Peer colours were an unsupported format. y-prosemirror accepts only
`#rrggbb` for a caret; colorFor() emitted `hsl()`, so every collaborative
session logged "A user uses an unsupported color format" once per peer. v2
still renders the caret, so this was noise rather than breakage -- but the
successor extension replaces a non-matching colour with `transparent`, which
would have made every remote caret invisible. Same palette, converted rather
than re-picked: no avatar changes colour.
Three CSS selectors matched nothing. A React node view's outer element is
Tiptap's own `div.react-renderer`, and the NodeViewWrapper carrying our
attributes renders inside it -- so `.ProseMirror > pre` and
`.ProseMirror > [data-testid=…]` never selected anything. The failure was
invisible because `.ProseMirror > *` still applied: code blocks, Mermaid
diagrams and Excalidraw boards were held at the 712px prose measure in wide
mode instead of taking their own width. Retargeted at the `node-<type>` class
Tiptap stamps on the wrapper. Regression covered in doc-width.spec.ts by
measuring rendered widths, which fails against the old selectors.
Also dead: a `.collaboration-cursor__selection` rule. y-prosemirror emits
`.ProseMirror-yjs-selection` with the peer's colour set inline, so the rule
neither matched nor could have overridden anything. Removed.
Not fixed here, deliberately: to_markdown's `_ => {}` arm silently discards
an unknown mark. tracing is not a dependency of knot-markdown, and the
extension-set and parity checks now prevent an unknown mark being written at
all, which is a stronger guarantee than a log line.
18 e2e specs across doc-width, mermaid, excalidraw, editor-toolbar,
two-users-converge, import-markdown, import-export and collab pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
christianhuening
merged commit Sep 5, 2026
19c90d6
into
chore/pre-tiptap3-groundwork
5 checks passed
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.
Stacked on #15 — the parity and extension-set checks added there are what surfaced most of these. Retarget to
mainonce #15 merges.All four predate that work. Each was reproduced first, then fixed, then verified by reverting the fix and watching the new test go red.
List keyboard shortcuts threw
toggleBulletList()raisedThere is no node type named 'listItem', so Mod+Shift+8 and Mod+Shift+7 did nothing but log. Renaming a node doesn't rewrite the options its own commands read —options.itemTypeNamewas still"listItem".The toolbar buttons pass both names explicitly, which is why only the shortcuts were affected and nobody noticed.
Link titles were dropped
tools/schema.jsondeclarestitleon the link mark and bothfrom_markdownandto_markdownhonour it — but Tiptap's Link has no such attribute, and ProseMirror discards what its schema doesn't declare.[text](url "title")survived import and was rewritten without the title the first time anyone edited the document. In storage, for every reader, silently.UNIMPLEMENTED_ATTRSinschema.test.tsis now empty and should stay that way.Peer colours were an unsupported format
y-prosemirror accepts only
#rrggbbfor a caret;colorFor()emittedhsl(), so every collaborative session logsA user uses an unsupported color formatonce per peer. v2 still renders the caret, so this is noise rather than breakage today — but the successor extension replaces a non-matching colour withtransparent, which would make every remote caret invisible. Fixing it now also closes migration blocker B4.Same palette, converted rather than re-picked —
hsl(0,70%,45%)→#c32222. No avatar changes colour.Three CSS selectors matched nothing
A React node view's outer element is Tiptap's own
div.react-renderer; theNodeViewWrappercarrying our attributes renders inside it. So.ProseMirror > preand.ProseMirror > [data-testid=…]never selected anything.The failure was invisible because
.ProseMirror > *still applied — code blocks, Mermaid diagrams and Excalidraw boards were held at the 712px prose measure in wide mode instead of taking their own width. My own regression from the width feature in 0.4.0.Retargeted at the
node-<type>class Tiptap stamps on the wrapper, confirmed against a DOM dump from Chromium rather than inference. Covered indoc-width.spec.tsby measuring rendered widths; that test fails against the old selectors.A
.collaboration-cursor__selectionrule was dead too — y-prosemirror emits.ProseMirror-yjs-selectionwith the colour set inline, so it neither matched nor could have overridden anything. Removed.Deliberately not fixed
to_markdown.rs's_ => {}arm silently discards an unknown mark.tracingisn't a dependency ofknot-markdown, and the extension-set and parity checks now prevent an unknown mark being written at all — a stronger guarantee than a log line.tsc,eslint --max-warnings 0, 151 unit tests, and 18 e2e specs across doc-width, mermaid, excalidraw, editor-toolbar, two-users-converge, import-markdown, import-export and collab.🤖 Generated with Claude Code