mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-10-26 22:37:03 +00:00
92305fba4d
ProseMirror lets a mark sit on an inline atom (a hard break, an inline attachment image or chip). Bolding, striking or linking a range that held one marked it, and markdown or HTML parsing marked it when the source wrapped it (**a\ b**). y-tiptap never writes marks on non-text inline nodes to the Y.Doc, so that tab's editor held a document its own Y.Doc did not. It flushed one body while every other tab, a reload and the materializer derived another. This is the ~0.7% tab divergence materializerParity found. Measured: both Y.Docs identical, and only the marking tab's ProseMirror doc differs; a one-tab repro with no relay reproduces it 4 of 4. InlineAtomNoMarks (extensions/inlineAtomNoMarks.ts) is an appendTransaction plugin that strips marks from inline non-text nodes in the same update. It fires only on AddMarkStep, AddNodeMarkStep, or a replace whose slice holds a marked atom, so typing pays nothing. It is registered in Editor.svelte and the headless materializer. No node spec or persisted shape changes, so no SCHEMA_VERSION question; NodeSpec.marks cannot do this, since it governs a node's content (measured: it left the marks in place). One-time normalisation: a body holding a mark across a hard break (**a\ b**) flushes as **a**\ **b**, the form every Y-derived door already produced, so this touches only bodies that already flip-flopped. It is stable from then on. materializerParity: MAX_TAB_DISAGREEMENTS 2 -> 0. The corpus is regenerated; seed-300922 is now a case. The generator is not deterministic run to run (Yjs client ids), so a regen also rewrites a couple of other cases' expectations; each corpus is self-consistent. Claude-Session: https://claude.ai/code/session_01Q9WssCjFuHjSfLABoW4tmS