Back to Plate

Editor Protocol Matrix for Plate

docs/editor-behavior/editor-protocol-matrix.md

53.0.5165.2 KB
Original Source

Editor Protocol Matrix for Plate

This is the exhaustive scenario matrix for editor behavior.

It is intentionally different from the other docs in this directory:

If someone asks, "Do we cover every key, boundary, selection shape, and container interaction?", this is the file that should answer that.

For current in-scope families, the rows are filled. Future releases may still add deferred families or entirely new scenario classes.

Purpose

Use this file to:

Do not use this file as:

  • the readable spec
  • the release gate
  • a place to inherit stale assumptions from old repos

Relationship To Other Files

FileJob
markdown-standards.mdmethodology and authority model
markdown-editing-spec.mdnormative family-level law
markdown-parity-matrix.mdrelease-gate coverage by family
editor-protocol-matrix.mdexhaustive scenario matrix

Source Of Authority

This file must follow the authority stack in markdown-standards.md.

That means each family-level table should only give routing hints.

Actual rows still choose authority explicitly.

Each family should name likely:

  1. Syntax / Serialization Ref
  2. Common UX Candidates
  3. Common Cross-Checks / Adjacent Refs
  4. Fallback Needed?

Do not cite stale editor-protocol GitHub issues as authority.

If an older issue happens to describe a useful scenario, port the scenario into this file in Plate's current vocabulary and then drop the link.

Row Schema

Each scenario row should eventually answer:

ColumnMeaning
Familymarkdown-native, markdown extension, block-editor-native, styling/layout, collaboration, cross-surface
Entityparagraph, table cell, link, mention, media, etc.
Node Modelblock non-void, block void atom, inline non-void span, inline void atom, leaf mark, text token, overlay / no node
Contextroot, quote, list, table, column, closed container, open container, adjacent to atom, etc.
Selectioncollapsed, expanded-inline, expanded-multiblock, backward, cell-range, node-selected
Caret / Edgestart, middle, end, before atom, after atom, first visual line, last visual line
Input, , , , , arrows, ⇧+arrow, ⌘+A, copy, paste, hover, plain-click, mod-click, drag, delete command
Expectedsplit, reset, lift, unwrap, select container, delete atom, keep native, no-op, etc.
Authoritysyntax ref + primary/secondary UX refs
Spec IDcanonical ID from the readable spec when one exists
Evidencecurrent tests or implementation seams
Statusone of the statuses below

Status Meaning

  • seeded family is listed, but scenarios are not expanded yet
  • specified scenario has a chosen rule in the readable spec and is not currently parked as a deferred runtime/product lane
  • tested scenario is backed by one or more real tests
  • partial some parts exist, but the scenario still needs refinement
  • deferred scenario or family is intentionally deferred to a later release even if the readable law already names the intended behavior

Interaction Classes Still Outside The Current Content-Editing Matrix

These are real editor-protocol dimensions, but they are not part of the current content-editing completion claim yet.

They live in the deferred integration red suite at apps/www/src/__tests__/package-integration/__deferred__/.

Run them explicitly with pnpm test:deferred.

Interaction ClassPrimary AuthoritySecondary RefCurrent State
Clipboard variantsTypora for general markdown-first clipboard semantics, Google Docs for table and document fidelityMilkdown, current package integration seamsspecified
Mouse drag / mouse selectionGoogle Docs for document selection, Notion for block drag semanticsMilkdown, current DnD and selection seamsspecified
Interactive preview / navigationstrongest owner by surface: Typora for markdown-native spans and HTML-block edit entry, Obsidian for dual-mode and note-linked navigation surfaces, Google Docs for linear heading navigation, Notion for block-editor-native referencesMilkdown, current package and docs seamsspecified
Navigation feedback / target flashstrongest owner by target surface, with one shared editor-scoped feedback primitivecurrent package and docs seamsspecified
Platform shortcutsstrongest product authority for the owning surfacecurrent hotkey and selection seamsspecified
Delete command variantsTypora for paragraph, code, and math delete-range semantics; Google Docs for table row and column destructive commandscurrent delete transforms and menu-like seamsspecified
IME / compositionplatform text-editing norms with product-specific owner behaviorcurrent atom/code/table seamsspecified

Protocol Families

These are the families that need scenario-complete coverage.

FamilyCommon Syntax / Serialization CandidatesCommon UX CandidatesCommon Cross-Checks / Adjacent RefsFallback Needed?Current State
Markdown-native structural keysCommonMarkTyporaMilkdownonly when refs are silent or incompatibletested
Markdown extensionsGFM / GitHub Docs / LaTeX-style math / local MDX contractsTypora, GitHub Docs, Google Docs, or Obsidian depending on the surfaceMilkdown, Notion, current package behaviorsometimestested
Block-editor-native elementslocal serialized shapeNotion and the strongest adjacent mainstream product for the concrete elementMilkdown, current package behaviorsometimestested except deferred toggle
Styling / layoutlocal serialized shape + HTML/CSS expectationsGoogle Docs and the strongest document-style precedent for the concrete surfaceNotion, current package behaviorsometimestested
Cross-surface interactionsmixed by owning surfaceTypora, Obsidian, Google Docs, Notion, or a local shared contract depending on the active surfaceMilkdown and current package seamsoftenspecified
Collaboration / editor-onlylocal serialized shape or editor-only contractGoogle Docs and the strongest collaboration precedent for the concrete surfaceNotion, current package behaviorsometimesdeferred

Entity Model Map

This is the canonical model map for the current feature set.

Scenario rows below inherit the entity model from this table unless a row says otherwise.

FamilyEntityNode ModelAffinity / Boundary Policy
markdown-nativeparagraphblock non-voidn/a
markdown-nativeheadingblock non-voidn/a
markdown-nativeblockquoteblock non-void containern/a
markdown-nativelist itemblock non-void containern/a
markdown-nativelinkinline non-void spandirectional
markdown-nativeimageblock void media atomn/a
markdown-nativesoft markleaf markdirectional
markdown-nativehard markleaf markhard
markdown-nativecode blockblock non-void ownern/a
markdown-nativethematic breakblock void atomn/a
markdown-nativehard line breaktext tokenn/a
markdown-extensiontask list itemblock non-void containern/a
markdown-extensiontableblock non-void grid ownern/a
markdown-extensioninline mathinline void atomn/a
markdown-extensionblock mathblock void atomn/a
markdown-extensionautolink literalinline non-void link spandirectional
markdown-extensionfootnote referenceinline void atomn/a
markdown-extensionfootnote definitionblock non-void containern/a
markdown-extensionemoji shortcodetext token after parsen/a
block-editor-nativementioninline void atomn/a
block-editor-nativedateinline void atomn/a
block-editor-nativecalloutblock non-void containern/a
block-editor-nativetoggleblock non-void containern/a
block-editor-nativeTOCblock void atomn/a
block-editor-nativecolumn group / itemblock non-void containern/a
block-editor-nativemedia embedblock void atomn/a
block-editor-nativemedia blockblock void media atomn/a
block-editor-nativecaptionblock non-void helpern/a
block-editor-nativecode drawing / excalidrawblock void atomn/a
styling/layoutblock style propertyblock non-void propertyn/a
styling/layoutstyle markleaf markdirectional
collaborationcommentleaf metadata markoutward
collaborationsuggestionleaf metadata mark plus block wrapperoutward
collaborationdiscussionoverlay / anchor surfacen/a
collaborationyjs cursor overlayoverlay / no noden/a

Protocol Rows

These are the first real protocol rows. They are grouped by family and should be extended until every in-scope feature family is scenario-complete.

Markdown-Native Structural Keys

FamilyEntityContextSelectionCaret / EdgeInputExpectedAuthoritySpec IDEvidenceStatus
markdown-nativeparagraphrootcollapsedmiddlesplit paragraph into two blocksCommonMark + Typora / MilkdownEDIT-P-ENTER-001withBreakRules.spec.tsxtested
markdown-nativeparagraphrootcollapsedempty blockkeep generic root split behaviorCommonMark + Typora / MilkdownEDIT-P-ENTER-EMPTY-001withBreakRules.spec.tsxtested
markdown-nativeparagraphrootcollapsedblock start, non-emptymerge with previous block when validTypora / MilkdownEDIT-P-BS-START-001withMergeRules.spec.tsxtested
markdown-nativeparagraphrootcollapsedempty blockmerge into previous blockTypora / MilkdownEDIT-P-BS-START-EMPTY-001withMergeRules.spec.tsxtested
markdown-nativeparagraphrootcollapsedblock startindent paragraphTypora / MilkdownEDIT-P-TAB-001withIndent.spec.tsxtested
markdown-nativeparagraphrootcollapsedindented paragraphoutdent paragraphTypora / MilkdownEDIT-P-STAB-001withIndent.spec.tsxtested
markdown-nativeparagraphrootexpanded-inlinesame blockreplace the selection with one paragraph split resultCommonMark + Typora / MilkdownEDIT-SEL-ENTER-001withBreakRules.spec.tsxtested
markdown-nativeparagraphrootexpanded-inlinesame blockdelete the selected text in place and keep the paragraph wrapperTypora / MilkdownEDIT-SEL-BS-001withDeleteRules.spec.tsxtested
markdown-nativeparagraphrootexpanded-inlinesame blockdelete the selected text in place and keep the paragraph wrapperTypora / MilkdownEDIT-SEL-BS-001withDeleteRules.spec.tsxtested
markdown-nativeparagraphrootexpanded-multiblockmixed blocksreplace the selection with one paragraph split result without orphaning surrounding structureTypora / MilkdownEDIT-SEL-ENTER-001withBreakRules.spec.tsxtested
markdown-nativeparagraphrootexpanded-multiblockmixed blocksremove the selection without corrupting surrounding structureTypora / MilkdownEDIT-SEL-BS-001withDeleteRules.spec.tsxtested
markdown-nativeparagraphrootbackward expanded-multiblockmixed blocksuse the same structural cleanup as forward expanded deleteTypora / MilkdownEDIT-SEL-BS-001withDeleteRules.spec.tsxtested
markdown-nativeheadingrootcollapsedmiddlesplit heading, reset new block to paragraphTypora / MilkdownEDIT-H-ENTER-001withBreakRules.spec.tsxtested
markdown-nativeheadingrootcollapsedendinsert paragraph after headingTypora / MilkdownEDIT-H-ENTER-END-001withBreakRules.spec.tsxtested
markdown-nativeheadingrootcollapsedblock startreset heading to paragraphTypora / MilkdownEDIT-H-BS-START-001withDeleteRules.spec.tsxtested
markdown-nativeheadingrootcollapsedempty headingreset empty heading to empty paragraphTypora / MilkdownEDIT-H-BS-START-EMPTY-001withDeleteRules.spec.tsxtested
markdown-nativeheadingrootexpanded-inlinesame headingreplace the selection and reset the trailing block to paragraphTypora / MilkdownEDIT-H-ENTER-001withBreakRules.spec.tsxtested
markdown-nativeheadingrootexpanded-inlinesame headingdelete the selection in place and keep the heading typeTypora / MilkdownwithDeleteRules.spec.tsxtested
markdown-nativeheadingrootexpanded-multiblockheading into paragraphremove the selection and keep the surviving heading boundary coherentTypora / MilkdownEDIT-SEL-BS-001withDeleteRules.spec.tsxtested
markdown-nativelist itemlistcollapsedmiddlesplit itemCommonMark + Typora / MilkdownEDIT-LIST-ENTER-001withList.spec.tsxtested
markdown-nativelist itemlistcollapsedempty nested itemoutdent one levelTypora / MilkdownEDIT-LIST-ENTER-EMPTY-001withList.spec.tsxtested
markdown-nativelist itemlistcollapsedempty root itemexit list to paragraphTypora / MilkdownEDIT-LIST-ENTER-EMPTY-ROOT-001withList.spec.tsxtested
markdown-nativelist itemlistcollapsedblock startremove one list layerTypora / MilkdownEDIT-LIST-BS-START-001withDeleteRules.spec.tsxtested
markdown-nativelist itemlistcollapsednested itemindent one list levelTypora / MilkdownEDIT-LIST-TAB-001withList.spec.tsxtested
markdown-nativelist itemlistcollapsednested itemoutdent one list levelTypora / MilkdownEDIT-LIST-STAB-001withList.spec.tsxtested
markdown-nativeblockquotequotecollapsedmiddlesplit quoted blockCommonMark + Typora / MilkdownEDIT-BQ-ENTER-001withBreakRules.spec.tsxtested
markdown-nativeblockquotequotecollapsedempty top-level quoted blockexit one quote levelTypora / MilkdownEDIT-BQ-ENTER-EMPTY-001withBreakRules.spec.tsxtested
markdown-nativeblockquotenested quotecollapsedempty quoted blockexit one quote level onlyTypora / MilkdownEDIT-BQ-ENTER-EMPTY-NESTED-001withBreakRules.spec.tsxtested
markdown-nativeblockquotenested quotecollapsedmiddlesplit the current inner quoted block and keep both blocks inside the same inner quoteCommonMark + Typora / MilkdownEDIT-BQ-ENTER-001withBreakRules.spec.tsxtested
markdown-nativeblockquotequotecollapsedblock startlift one quote levelTypora / MilkdownEDIT-BQ-BS-START-001withDeleteRules.spec.tsxtested
markdown-nativeblockquotequotecollapsedempty non-first blockdelete in place inside quote before liftingTypora / MilkdownEDIT-BQ-BS-START-EMPTY-NONFIRST-001withDeleteRules.spec.tsxtested
markdown-nativeblockquotenested quotecollapsedfirst block startlift one inner quote level and keep outer quote intactTypora / MilkdownEDIT-BQ-BS-START-001withDeleteRules.spec.tsxtested
markdown-nativeblockquotenested quotecollapsedempty non-first blockdelete in place inside the same inner quote before liftingTypora / MilkdownEDIT-BQ-BS-START-EMPTY-NONFIRST-001withDeleteRules.spec.tsxtested
markdown-nativeblockquotequote with nested listcollapsedquoted list item at block startremove the list layer before the quote layerTypora / MilkdownEDIT-LIST-BS-START-001withDeleteRules.spec.tsxtested
markdown-nativeblockquotequotecollapsedquoted paragraphlift one quote level after indent is exhaustedTypora / MilkdownEDIT-BQ-STAB-001withIndent.spec.tsxtested
markdown-nativeblockquotequotecollapsedquoted paragraphkeep tab editor-owned via indentTypora / MilkdownEDIT-BQ-TAB-001withIndent.spec.tsxtested
markdown-nativeblockquotenested quoteexpanded-multiblockmixed inner quote blocksoutdent all selected quoted blocks one quote level after stronger ownersTypora / MilkdownEDIT-SEL-STAB-001withIndent.spec.tsxtested
markdown-nativesoft markparagraphcollapsedmark boundaryinsert textdirectional boundary for soft marks such as bold, italic, and strikethroughTypora / MilkdownEDIT-AFF-MARK-001AffinityPlugin.spec.tsx, basic-marks.spec.tsxspecified
markdown-nativelinkparagraphcollapsedbefore link endinsert textextend link when affinity comes from linked sideCommonMark + Typora / MilkdownEDIT-AFF-LINK-001AffinityPlugin.spec.tsxtested
markdown-nativelinkparagraphcollapsedbefore link startinsert textkeep text outside link when affinity comes from plain sideCommonMark + Typora / MilkdownEDIT-AFF-LINK-001AffinityPlugin.spec.tsxtested
markdown-nativehard markparagraphcollapsedmark boundaryinsert texthard boundary for inline code / kbdTypora / MilkdownEDIT-AFF-HARD-001AffinityPlugin.spec.tsxtested
markdown-nativecode blockcode blockcollapsedmiddleinsert code line break inside blockCommonMark + Typora / MilkdownEDIT-CB-ENTER-001withCodeBlock.spec.tsxtested
markdown-nativecode blockcode blockexpanded-inlineone code linereplace the selection with a code-local line splitCommonMark + Typora / MilkdownEDIT-CB-ENTER-001withCodeBlock.spec.tsxtested
markdown-nativecode blockcode blockcollapsedfirst non-empty line startkeep deletion local to the code line instead of unwrappingTypora / MilkdownEDIT-CB-BS-START-001withCodeBlock.spec.tsxtested
markdown-nativecode blockcode blockcollapsedempty non-first line startmerge the empty line into the previous code line and keep the code blockTypora / MilkdownEDIT-CB-BS-START-001withCodeBlock.spec.tsxtested
markdown-nativecode blockcode blockcollapsedempty blockunwrap to paragraphTypora / MilkdownEDIT-CB-BS-START-EMPTY-001withCodeBlock.spec.tsxtested
markdown-nativecode blockcode blockexpanded-multilinemany linesindent every selected code lineTypora / MilkdownEDIT-CB-TAB-001withCodeBlock.spec.tsxtested
markdown-nativecode blockcode blockexpanded-multilinemany linesoutdent every selected code lineTypora / MilkdownEDIT-CB-STAB-001withCodeBlock.spec.tsxtested
markdown-nativecode blockcode blockinside blockany⌘+Aexpand the selection to the whole code blockTypora / MilkdownwithCodeBlock.spec.tsxtested
markdown-extensionmath blockmath blockcollapsedfirst non-empty line startkeep deletion inside math editing instead of generic block exitTypora / Milkdown with local owner decisionEDIT-MATH-BS-START-001markdown-editing-reference-audit.mdspecified
markdown-extensionmath blockmath blockcollapsedempty blockexit the empty math block to a paragraphTypora / Delete Range with local owner decisionEDIT-MATH-BS-START-EMPTY-001markdown-editing-reference-audit.mdspecified
markdown-extensionmath blockmath blockcollapsedanykeep tab owned by math editing unless a stronger math surface overrides itlocal owner decision informed by Typora / MilkdownEDIT-MATH-TAB-001markdown-editing-spec.mdspecified
markdown-nativehard line breakparagraphcollapsedinlineserializepreserve explicit hard breakCommonMark + Typora / MilkdownEDIT-HARD-*commonmarkSurface.spec.tstested
markdown-nativehard line breakblockquotecollapsedinlineserializepreserve quoted hard break and trailing break semanticsCommonMark + Typora / MilkdownEDIT-HARD-*commonmarkSurface.spec.tstested
markdown-nativethematic breakrootcollapsedadjacent block boundarycreate an adjacent paragraph instead of text inside the breakCommonMark + Typora / MilkdownEDIT-HR-ENTER-001markdown-editing-reference-audit.mdspecified
markdown-nativeatomic blockadjacent block boundarycollapsedblock start before atomic nodeselect or remove according to atomic ownership instead of generic mergelocal owner decisionEDIT-ATOMIC-BS-START-001markdown-editing-spec.mdspecified

Tables

FamilyEntityContextSelectionCaret / EdgeInputExpectedAuthoritySpec IDEvidenceStatus
markdown-extensiontable celltablecollapsedinside cellkeep Enter inside the same cellGFM + Google Docs / NotionEDIT-TABLE-ENTER-001withTable.spec.tsxtested
markdown-extensiontable celltablecollapsedcell startkeep backspace inside current cellGFM + Google Docs / NotionEDIT-TABLE-BS-START-001withTable.spec.tsxtested
markdown-extensiontable celltablecollapsedcurrent cellmove to next cellGoogle Docs / NotionEDIT-TABLE-TAB-001withTable.spec.tsxtested
markdown-extensiontable celltablecollapsedcurrent cellmove to previous cellGoogle Docs / NotionEDIT-TABLE-STAB-001withTable.spec.tsxtested
markdown-extensiontable celltablecollapsedlast visual linemove to cell belowGoogle Docs / NotionEDIT-TABLE-ARROWDOWN-MULTIBLOCK-001withTable.spec.tsxtested
markdown-extensiontable celltablecollapsedfirst visual linemove to cell aboveGoogle Docs / NotionEDIT-TABLE-ARROWUP-MULTIBLOCK-001withTable.spec.tsxtested
markdown-extensiontabletableexpanded-outwardanchor in cell, focus after tabledrag selectclamp focus to the end of the table instead of extending native selection past itGoogle Docs / NotionwithApplyTable.spec.tsxtested
markdown-extensiontabletablebackward expanded-outwardanchor after table, focus in celldrag selectclamp backward focus to the point before the tableGoogle Docs / NotionwithApplyTable.spec.tsxtested
markdown-extensiontabletablecell-rangen/acopycopy selected cells as a subtableGoogle Docs / NotionwithGetFragmentTable.spec.tsxtested
markdown-extensiontabletablemany cells selectedn/apaste / insert blocksreplace or expand selected cells according to table rulesGoogle Docs / NotionwithInsertFragmentTable.spec.tsxtested
markdown-extensiontabletablecollapsed in celln/afirst ⌘+Aselect the whole table when the caret is inside itGoogle Docs / NotionwithTable.spec.tsxtested
markdown-extensiontabletablecell-rangen/a⇧+arrowexpand selection across cellsGoogle Docs / NotiononKeyDownTable.spec.tsx, withTableCellSelection.spec.tsxtested
markdown-extensiontabletablecell-rangen/aaddMarkapply the mark to every selected text node across cellsGoogle Docs / NotionwithTableCellSelection.spec.tsxtested
markdown-extensiontabletablecell-rangen/aremoveMarkremove only the requested mark across selected cellsGoogle Docs / NotionwithTableCellSelection.spec.tsxtested
markdown-extensiontabletablecell-rangen/amarks()return only marks shared by every selected text nodeGoogle Docs / NotionwithTableCellSelection.spec.tsxtested
markdown-extensiontableadjacent block after tablecollapsedblock startmove selection toward the adjacent table instead of deleting through a cell boundaryGoogle Docs / NotionwithDeleteTable.spec.tsxtested
markdown-extensiontabletablecell-rangen/adeleteFragmentclear selected cell contents while keeping the table shape intactGoogle Docs / NotionwithDeleteTable.spec.tsxtested
markdown-extensiontabletablenode-selected tablen/asecond ⌘+Aescalate from table selection to document selectionGoogle Docs / NotionwithTable.spec.tsxtested
markdown-extensiontable rowtablecollapsed in rowcurrent rowinsert row afterinsert a row with empty cells after the current row and move selection into it when requestedGoogle Docs / NotionEDIT-TABLE-ROW-INSERT-001insertTableRow.spec.tsxtested
markdown-extensiontable rowtablecollapsed in rowcurrent rowinsert row beforeinsert a row with empty cells before the current row and move selection into it when requestedGoogle Docs / NotionEDIT-TABLE-ROW-INSERT-002insertTableRow.spec.tsxtested
markdown-extensiontable columntablecollapsed in columncurrent columninsert column afterinsert a column with empty cells after the current column and move selection into it when requestedGoogle Docs / NotionEDIT-TABLE-COL-INSERT-001insertTableColumn.spec.tsxtested
markdown-extensiontable columntablecollapsed in columncurrent columninsert column beforeinsert a column with empty cells before the current column and move selection into it when requestedGoogle Docs / NotionEDIT-TABLE-COL-INSERT-002insertTableColumn.spec.tsxtested
markdown-extensiontable rowmerged tablecollapsed / expandedcurrent rowdelete rowremove the current row and repair row spans instead of corrupting the merged tableGoogle Docs / NotionEDIT-TABLE-ROW-DELETE-001transforms/deleteRow.spec.tsx, merge/deleteRow.spec.tsx, merge/deleteRowWhenExpanded.spec.tstested
markdown-extensiontable columnmerged tablecollapsed / expandedcurrent columndelete columnremove the current column and repair col spans instead of corrupting the merged tableGoogle Docs / NotionEDIT-TABLE-COL-DELETE-001transforms/deleteColumn.spec.tsx, merge/deleteColumn.spec.tsxtested

Other Markdown Extensions

FamilyEntityContextSelectionCaret / EdgeInputExpectedAuthoritySpec IDEvidenceStatus
markdown-extensiontask list itemlistround-tripchecked / uncheckedserialize / deserializepreserve todo checked state through markdown package surfacesGFM + Typora / MilkdownEDIT-TASK-*taskList.spec.ts, deserializeMdList.spec.tsx, listToMdastTree.spec.tstested
markdown-extensiontask list itemlistcollapseditem endinsert a new todo line with the same checked-state formattingTypora / MilkdownEDIT-LIST-ENTER-001withInsertBreakList.spec.tsxtested
markdown-extensiontask list itemlistexpanded-inlineinside itemfollow the normal list split path while preserving todo metadataTypora / MilkdownEDIT-LIST-ENTER-001withInsertBreakList.spec.tsxtested
markdown-extensionstrikethroughparagraphround-tripinline markserialize / deserializepreserve ~~strike~~ as a markdown markGFM + Typora / MilkdowncommonmarkSurface.spec.ts, serializeInlineMd.spec.ts, BaseMarkPlugins.spec.tstested
markdown-extensionhighlightparagraphround-tripinline markserialize / deserializepreserve highlight as <mark>...</mark> MDX text elementslocal MDX mark contract informed by Typora / MilkdownEDIT-MARK-MDX-001mdxMarks.spec.tsx, BaseHighlightPlugin.tstested
markdown-extensionsubscriptparagraphround-tripinline markserialize / deserializepreserve subscript as <sub>...</sub> MDX text elementslocal MDX mark contract informed by Typora / MilkdownEDIT-MARK-MDX-002mdxMarks.spec.tsx, BaseSubscriptPlugin.tstested
markdown-extensionsuperscriptparagraphround-tripinline markserialize / deserializepreserve superscript as <sup>...</sup> MDX text elementslocal MDX mark contract informed by Typora / MilkdownEDIT-MARK-MDX-003mdxMarks.spec.tsx, BaseSuperscriptPlugin.tstested
markdown-extensioninline mathparagraphcollapsed / expandedinsertion pointinsert inline equationinsert an inline void equation and use selected text as the default expressionremark-math + Typora / MilkdownEDIT-MATH-INLINE-INSERT-001insertInlineEquation.spec.ts, BaseInlineEquationPlugin.spec.tstested
markdown-extensioninline mathinline equation inputcollapsedinput left / right edgeArrowLeft / ArrowRighthand control back to the editor at text edgesTypora / MilkdownEDIT-MATH-INLINE-ARROW-001useEquationInput.spec.tsxtested
markdown-extensionblock mathrootcollapsedinsertion pointinsert equationinsert a void block equation at the requested pathremark-math + Typora / MilkdownEDIT-MATH-BLOCK-INSERT-001insertEquation.spec.ts, BaseEquationPlugin.spec.tstested
markdown-extensionblock mathnext blockcollapsedblock start after equationmove selection onto the equation instead of deleting through itTypora / MilkdownEDIT-MATH-BLOCK-BS-START-001BaseEquationPlugin.spec.tstested
markdown-extensionautolink literalparagraphcollapsedend of URL candidatetype space / finalize the URL as a link using the current autolink heuristics and serialize plain URL links back to bare URL markdownGFM / GitHub Docs + Typora / MilkdownEDIT-AFF-LINK-001withLink.spec.tsx, gfmSurface.spec.tstested
markdown-extensionfootnote definitionparagraph / blockround-tripfootnote definition blockserialize / deserializepreserve footnote definitions as dedicated footnoteDefinition blocks with an identifier and block childrenGFM / GitHub DocsEDIT-FOOTNOTE-DEF-001gfmSurface.spec.ts, packages/footnote/src/lib/BaseFootnoteDefinitionPlugin.ts, defaultRules.tstested
markdown-extensionfootnote referenceparagraphround-tripfootnote reference tokenserialize / deserializepreserve footnote references as dedicated inline footnoteReference elements with an identifierGFM / GitHub DocsEDIT-FOOTNOTE-REF-001gfmSurface.spec.ts, packages/footnote/src/lib/BaseFootnoteReferencePlugin.ts, defaultRules.tstested
markdown-extensionfootnote package surfaceeditorcollapsed / expandedinsertion pointinsert footnoteinsert a reference, create a missing definition, seed the definition from the current selection when expanded, and focus the definition bodyTypora-informed package contract + GFM / GitHub DocsEDIT-FOOTNOTE-INSERT-001insertFootnote.spec.ts, BaseFootnotePlugins.spec.tstested
markdown-extensionfootnote package surfaceeditoranyunresolved identifiercreate definitioncreate the missing definition for an existing identifier without inserting another reference and optionally focus the new definition bodylocal product contract informed by explicit repair flowsEDIT-FOOTNOTE-PKG-001createFootnoteDefinition.spec.ts, BaseFootnoteReferencePlugin.ts, content/(plugins)/(elements)/footnote.mdxtested
markdown-extensionfootnote referenceparagraphcollapsedrendered superscripthovershow footnote content preview instead of entering generic text editingTypora + GFM / GitHub DocsEDIT-FOOTNOTE-PREVIEW-001markdown-reference.json, content/(plugins)/(elements)/footnote.mdxspecified
markdown-extensionfootnote referenceparagraphcollapsedrendered superscriptmod-clickscroll to the matching footnote definition and land a collapsed caret at the start of its body; if unresolved, create the missing definition and focus it instead of failing silentlyTypora + GFM / GitHub Docs + local unresolved-repair contractEDIT-FOOTNOTE-NAV-001what-s-new-0-9-84.json, content/(plugins)/(elements)/footnote.mdx, focusFootnoteDefinition.ts, createFootnoteDefinition.spec.ts, footnote-node.spec.tsxtested
markdown-extensionfootnote definitionfootnote definition blockcollapsedbacklink surfaceplain-clickscroll back to the matching reference and prefer the nearest stable insertion point outside the ref; atom-selection fallback must show a visible target state and suppress generic formatting chromeTypora + GFM / GitHub DocsEDIT-FOOTNOTE-NAV-002what-s-new-0-9-84.json, content/(plugins)/(elements)/footnote.mdx, focusFootnoteReference.tsspecified
cross-surfacenavigation feedbackfootnote definition targetafter footnote ref jumpcollapsedlanded definition bodybriefly highlight the landed definition target while preserving the caret at the definition startlocal shared navigation-feedback contract informed by Typora / Obsidian / Google DocsEDIT-NAV-FEEDBACK-*markdown-editing-spec.md, focusFootnoteDefinition.tsspecified
cross-surfacenavigation feedbackfootnote reference targetafter footnote backlink jumpcollapsedlanded reference vicinitybriefly highlight the landed reference target while preserving the adjacent caret point or explicit fallback selection statelocal shared navigation-feedback contract informed by Typora / Obsidian / Google DocsEDIT-NAV-FEEDBACK-*markdown-editing-spec.md, focusFootnoteReference.tsspecified
markdown-extensionfootnote package surfaceeditoranyidentifier lookupdefinition / references / preview lookupresolve through one lazy registry-backed index per editor instead of rescanning the whole document or copying preview text onto referenceslocal package contract informed by performance-first editor ownershipEDIT-FOOTNOTE-PKG-001registry.ts, footnoteRegistry.spec.ts, BaseFootnoteReferencePlugin.tstested
markdown-extensionfootnote package surfaceeditoranyidentifier statusresolved / duplicate detectionexpose unresolved and duplicate-definition status through package helpers instead of making every render layer rediscover it independentlylocal package contract informed by performance-first editor ownershipEDIT-FOOTNOTE-PKG-001registry.ts, footnoteRegistry.spec.ts, BaseFootnoteReferencePlugin.tstested
markdown-extensionfootnote definition seteditorduplicate definitions presentsame identifier reused across multiple definitionsnormalize / repair duplicate definitionskeep the first definition canonical, keep later duplicates explicit invalid definitions, and only renumber on explicit repair action instead of silently merging or renumberinglocal owner decision after GFM / GitHub Docs silence on duplicate-definition repair semanticsEDIT-FOOTNOTE-DUP-001markdown-editing-spec.md, content/(plugins)/(elements)/footnote.mdx, footnoteRegistry.spec.ts, footnote-node.spec.tsxtested
markdown-extensionfootnote package surfaceeditorn/an/atoolbar / slashapp-level toolbar and slash-command entries should call the same footnote insert transform instead of inventing separate creation logiclocal package contract informed by Typora / Notion-style insertion chromeEDIT-FOOTNOTE-PKG-001transforms.ts, transforms-classic.ts, insert-toolbar-button.tsx, insert-toolbar-classic-button.tsx, slash-node.tsxspecified
markdown-extensionemoji shortcodeparagraphround-tripshortcode tokenserialize / deserializeaccept :shortcode: input in the default markdown profile, normalize it to unicode text, and serialize the unicode text back outlocal remark plugin contract informed by Typora / GitHub DocsEDIT-EMOJI-001emojiSurface.spec.tsx, packages/markdown/src/lib/__tests__/createTestEditor.tsx, apps/www/src/registry/components/editor/plugins/markdown-kit.tsxtested
markdown-nativeimageparagraphround-tripwidth / height present on nodeserializekeep plain markdown limited to alt, src, and optional title; width and height remain HTML/MDX-onlyCommonMark + Typora / MilkdownEDIT-IMG-*commonmarkSurface.spec.ts, defaultRules.spec.tstested

Block-Editor-Native Elements

FamilyEntityContextSelectionCaret / EdgeInputExpectedAuthoritySpec IDEvidenceStatus
block-editor-nativecalloutcalloutcollapsednon-empty contentinsert soft break inside calloutlocal callout contract informed by Notion / MilkdownEDIT-CALLOUT-ENTER-001withBreakRules.spec.tsxtested
block-editor-nativecalloutcalloutcollapsedempty blockreset to paragraphlocal callout contract informed by Notion / MilkdownEDIT-CALLOUT-ENTER-EMPTY-001withBreakRules.spec.tsxtested
block-editor-nativecalloutcalloutcollapsedblock startreset to paragraphlocal callout contract informed by Notion / MilkdownEDIT-CALLOUT-BS-START-001withDeleteRules.spec.tsxtested
block-editor-nativementionparagraphcollapsedblock end insertioninsert mentioninsert mention atom and optional trailing spacelocal mention contract informed by Notion / MilkdownEDIT-MENTION-INSERT-END-001getMentionOnSelectItem.spec.tsxtested
block-editor-nativementionparagraphcollapsedmid-block insertioninsert mentioninsert mention atom without trailing spacelocal mention contract informed by Notion / MilkdownEDIT-MENTION-INSERT-MID-001getMentionOnSelectItem.spec.tsxtested
block-editor-nativementionparagraphcollapsedafter mentiondelete whole mention atomlocal mention contract informed by Notion / MilkdownEDIT-MENTION-BS-START-001BaseMentionPlugin.spec.tsxtested
block-editor-nativementionparagraphcollapsedbefore mentiondelete whole mention atomlocal mention contract informed by Notion / MilkdownEDIT-MENTION-DEL-END-001BaseMentionPlugin.spec.tsxtested
block-editor-nativementionparagraphcollapsedbefore mentionmove into the mention child so the inline void stays keyboard-accessiblelocal mention contract informed by Notion / MilkdownBaseMentionPlugin.spec.tsxtested
block-editor-nativementionparagraphcollapsedafter mentionmove into the mention child so the inline void stays keyboard-accessiblelocal mention contract informed by Notion / MilkdownBaseMentionPlugin.spec.tsxtested
block-editor-nativedateparagraphcollapsedinsertioninsert dateinsert date atom plus trailing spacelocal date contract informed by Notion / Google DocsEDIT-DATE-INSERT-001insertDate.spec.tsxtested
block-editor-nativedateparagraphcollapsedafter datedelete whole date atomlocal date contract informed by Notion / Google DocsEDIT-DATE-BS-START-001BaseDatePlugin.spec.tsxtested
block-editor-nativedateparagraphcollapsedbefore datedelete whole date atomlocal date contract informed by Notion / Google DocsEDIT-DATE-DEL-END-001BaseDatePlugin.spec.tsxtested
block-editor-nativedateparagraphcollapsedbefore datemove into the date child so the inline void stays keyboard-accessiblelocal date contract informed by Notion / Google DocsBaseDatePlugin.spec.tsx, isPointNextToNode.spec.tsxtested
block-editor-nativedateparagraphcollapsedafter datemove into the date child so the inline void stays keyboard-accessiblelocal date contract informed by Notion / Google DocsBaseDatePlugin.spec.tsx, isPointNextToNode.spec.tsxtested
block-editor-nativedatemarkdown / mdxround-tripcanonical or legacy date elementserialize / deserializecanonicalize safe date input into one YYYY-MM-DD node value, write canonical dates as <date value=\"...\" />, and preserve non-normalizable legacy child text on a raw fallback pathlocal MDX date contractEDIT-DATE-MDX-001dateElement.spec.ts, content/(plugins)/(serializing)/markdown.mdxtested
block-editor-nativedatemarkdown / mdxround-triplegacy child-text <date>...</date>deserializeaccept legacy child-text date input for compatibility even though canonical write output uses attribute formlocal MDX date contractEDIT-DATE-MDX-001dateElement.spec.tstested
block-editor-nativedaterender layerinline chipcanonical node.date or raw fallback textrenderbundled UI derives relative labels from canonical YYYY-MM-DD values without timezone drift and renders raw fallback text literallylocal current date render contract layered on top of the MDX payload contractEDIT-DATE-MDX-*date-node.spec.tsx, date-node-static.spec.tsx, content/(plugins)/(elements)/date.mdxtested
block-editor-nativedatemarkdown / mdxround-tripdisplay-vs-value, locale/timezone, or richer date payloadserialize / deserializeheavier serialized date semantics beyond the current canonical attribute writer remain deferred until a separate date-expansion lane chooses them explicitlylocal MDX date contract with no stronger external authority yetEDIT-DATE-MDX-*markdown-editing-spec.md, content/(plugins)/(elements)/date.mdx, content/(plugins)/(serializing)/markdown.mdxdeferred
block-editor-nativetocrootcollapsedinsertioninsert tocinsert atomic TOC blocklocal TOC contract informed by Notion conventionsEDIT-TOC-INSERT-001insertToc.spec.tstested
block-editor-nativetoctoc blocknode-selected / collapsedselected TOCdelete TOC blocklocal TOC contract informed by Notion conventionsEDIT-TOC-DEL-SELECTED-001BaseTocPlugin.spec.tstested
block-editor-nativetocnext blockcollapsedstart of next blockmove selection onto TOC instead of deleting through itlocal TOC contract informed by Notion conventionsEDIT-TOC-BS-NEXT-001BaseTocPlugin.spec.tstested
block-editor-nativetocnext blockcollapsedstart of next blockmove selection onto the TOC instead of entering its empty childlocal TOC contract informed by Notion conventionsBaseTocPlugin.spec.tstested
block-editor-nativetoctoc blocknode-selectedselected TOCkeep the TOC atomic instead of creating text inside itlocal TOC contract informed by Notion conventionsBaseTocPlugin.spec.tstested
block-editor-nativetoctoc blocknode-selectedselected TOCmove focus onward or fall through, never tab into TOC textlocal TOC contract informed by Notion conventionsBaseTocPlugin.spec.tstested
block-editor-nativecolumnsparagraphcollapsedtoggle actiontoggle columnswrap content into first column and create empty siblingslocal column contract informed by Notion layout behaviorEDIT-COLUMN-TOGGLE-001toggleColumnGroup.spec.tsxtested
block-editor-nativecolumnscolumn groupcollapsedset columnsupdate layoutpreserve content and redistribute widthslocal column contract informed by Notion layout behaviorEDIT-COLUMN-SET-001setColumns.spec.tsxtested
block-editor-nativecolumnscolumninside columnselection in textfirst ⌘+Aselect the containing columnlocal column contract informed by Notion layout behaviorwithColumn.spec.tstested
block-editor-nativecolumnscolumn groupcolumn already selectedsecond ⌘+Aselect the parent column grouplocal column contract informed by Notion layout behaviorwithColumn.spec.tstested
block-editor-nativecolumnsparagraph inside columncollapsedmiddlesplit inside the same column and keep the column group intactlocal column contract informed by Notion layout behaviorwithColumn.spec.tstested
block-editor-nativecolumnsparagraph inside columncollapsedblock startrespect the contained block owner before any column-group unwraplocal column contract informed by Notion layout behaviorwithColumn.spec.tstested
block-editor-nativecolumnsparagraph inside columncollapsedanydefer to the stronger local owner; columns are not a direct tab ownerlocal column contract informed by Notion layout behaviorwithColumn.spec.tstested
block-editor-nativemediaparagraphcollapsedinsert mediatoolbar / URL insertinsert image or media embed according to chosen typelocal media contract informed by Notion / DocsinsertMedia.spec.tstested
block-editor-nativemedia void blocknext blockcollapsedblock start after mediamove selection onto the media node instead of deleting through itlocal media contract informed by Notion / DocsEDIT-MEDIA-*BaseMediaPluginContracts.spec.tstested
block-editor-nativemediamarkdown / mdxround-tripfile/audio/video/embedserialize / deserializepreserve media node shape and MDX attributeslocal media contract informed by Notion / DocsEDIT-MEDIA-*mediaSurface.spec.ts, parseAttributes.spec.tstested
block-editor-nativemedia embededitorcollapsedpasted URL or iframe codeinsert embednormalize supported iframe or provider input into a canonical embed url plus current normalized metadata instead of storing raw iframe markuplocal media contract informed by Notion / DocsEDIT-MEDIA-*parseIframeUrl.spec.ts, parseVideoUrl.spec.ts, parseTwitterUrl.spec.ts, insertMediaEmbed.spec.ts, insertMedia.spec.tstested
block-editor-nativemedia embededitorcollapsedallowlisted twitter/x sharing snippetinsert / edit embedextract the canonical status URL and reuse the existing twitter embed path instead of storing the raw snippetlocal media contract informed by Notion / DocsEDIT-MEDIA-*parseIframeUrl.spec.ts, BaseMediaEmbedPlugin.spec.ts, submitFloatingMedia.spec.tstested
block-editor-nativemedia embedrender layerrendered video or embed nodesupported provider metadatarendercurrent render layer may choose provider-specific preview paths from normalized provider / id / url metadata and prefer optional sourceUrl for edit surfaces without reparsing raw input in app codelocal current media render contract layered on top of the normalized embed contractEDIT-MEDIA-*useMediaState.spec.ts, media-video-node.spec.tsx, content/(plugins)/(elements)/media.mdxtested
block-editor-nativemedia placeholdereditorupload placeholderupload completesreplace placeholderreplace the placeholder with the final media node and rewrite upload history so undo/redo tracks the real media nodelocal media contract informed by Notion / DocsEDIT-MEDIA-*BasePlaceholderPlugin.spec.ts, history.spec.ts, media-placeholder-node.tsxtested
block-editor-nativemedia authoringlocal video / audioeditorlocal file insertion or drag / droppath policyfollow the same image-path policy family for local media files instead of inventing a separate local-media path contractTypora + local media contractEDIT-MEDIA-*media-authoring-and-path-policy.md, images.json, media.jsonspecified
block-editor-nativemedia embededitornon-allowlisted script-based sharing snippetpaste embed codetrust boundarydo not treat arbitrary script-based embed markup as baseline behavior; only explicit allowlisted transforms may extract canonical embed URLsTypora + local trust boundaryEDIT-MEDIA-*media-authoring-and-path-policy.md, media.jsonspecified
block-editor-nativemedia embededitorPDF iframe snippetpaste embed codebaseline supportdo not assume PDF iframe support as a baseline current embed path just because generic iframe syntax existsTypora + local product decisionEDIT-MEDIA-*media-authoring-and-path-policy.md, media.jsonspecified
block-editor-nativemedia / embedmarkdown / mdxround-trip / authoringbroader authoring/path-policy, PDF, or open-ended script embedsserialize / deserialize / editbroader media/embed product semantics beyond the current normalized url / provider / id / optional sourceUrl contract remain deferred until a separate media-expansion lane locks themlocal media contract informed by Notion / Docs with thin external evidence beyond current package behaviorEDIT-MEDIA-*markdown-editing-spec.md, content/(plugins)/(elements)/media.mdxdeferred
block-editor-nativecaptionmedia hostcollapsedmove down from hostmove focus into captionlocal caption contract informed by Notion / DocsEDIT-CAPTION-*withCaption.spec.tsxtested
block-editor-nativecaptionmedia hostcollapsedmove down from disallowed blockfall through, do not claim movementlocal caption contract informed by Notion / DocsEDIT-CAPTION-*withCaption.spec.tsxtested
block-editor-nativetoggletoggletitle row / nested contentcollapsed / / open toggles create nested paragraphs, closed toggles insert the next toggle after hidden content, start-delete removes the toggle shell, and nested content yields to stronger child owners before toggle claims tabNotion / MilkdownEDIT-TOGGLE-*packages/toggle/src/lib/BaseTogglePlugin.spec.ts, packages/toggle/src/react/withToggle.spec.tsxspecified
block-editor-nativecode drawingeditoratomic blockn/ainsert / delete boundaryinsertion creates one atomic drawing block and adjacent destructive movement targets the block boundary instead of generic mergeNotion-like board tools / local package contractEDIT-DRAWING-*insertCodeDrawing.spec.ts, BaseCodeDrawingPlugin.spec.tsspecified
block-editor-nativeexcalidraweditoratomic blockn/ainsert / delete boundaryinsertion creates one atomic excalidraw block and adjacent destructive movement targets the block boundary instead of generic mergeNotion-like board tools / local package contractEDIT-DRAWING-*insertExcalidraw.spec.ts, BaseExcalidrawPlugin.spec.tsspecified

Styling / Layout

FamilyEntityContextSelectionCaret / EdgeInputExpectedAuthoritySpec IDEvidenceStatus
styling/layoutindentparagraph / quotecollapsedany / adjust paragraph indent without stealing stronger ownersGoogle Docs / NotionEDIT-INDENT-*withIndent.spec.tsx, setIndent.spec.ts, withList.spec.tsxtested
styling/layouttext alignblockblock selectionanyset / clear alignset alignment prop or clear to defaultlocal block style contract informed by Google Docs / NotionEDIT-ALIGN-*BaseTextAlignPlugin.spec.tstested
styling/layouttext indentblockblock selectionanyset / clear text indentset textIndent prop or clear to defaultlocal block style contract informed by Google Docs / NotionEDIT-TEXT-INDENT-*BaseTextIndentPlugin.spec.tstested
styling/layoutline heightblockblock selectionanyset / clear line heightset lineHeight prop or clear to defaultlocal style contract informed by Google Docs / NotionEDIT-LINE-HEIGHT-*BaseLineHeightPlugin.spec.tstested
styling/layoutfont familymarked textcollapsed / expandedboundaryadd markapply fontFamily leaf marklocal style contract informed by Google Docs / NotionEDIT-STYLE-*BaseFontFamilyPlugin.spec.tstested
styling/layoutfont sizemarked textcollapsed / expandedboundaryadd markapply fontSize leaf marklocal style contract informed by Google Docs / NotionEDIT-STYLE-*BaseFontSizePlugin.spec.tstested
styling/layoutfont weightmarked textcollapsed / expandedboundaryadd markapply fontWeight leaf marklocal style contract informed by Google Docs / NotionEDIT-STYLE-*BaseFontWeightPlugin.spec.tstested
styling/layoutfont colormarked textcollapsed / expandedboundaryadd markapply color leaf marklocal style contract informed by Google Docs / NotionEDIT-STYLE-*BaseFontColorPlugin.spec.tstested
styling/layoutfont backgroundmarked textcollapsed / expandedboundaryadd markapply backgroundColor leaf marklocal style contract informed by Google Docs / NotionEDIT-STYLE-*BaseFontBackgroundColorPlugin.spec.tstested

Collaboration / Editor-Only

FamilyEntityContextSelectionCaret / EdgeInputExpectedAuthoritySpec IDEvidenceStatus
collaborationcommenteditor-onlyanyanycreate/remove/overlapcomments attach metadata to text ranges, survive editing as marks, and stay excluded from markdown serializationeditor-only contract + Google Docs / NotionEDIT-COMMENT-*family matrix onlyspecified
collaborationsuggestioneditor-onlyanyanyinsert/delete/accept/rejectsuggestions wrap editing intent in metadata, preserve accept/reject semantics, and stay excluded from markdown serializationeditor-only contract + Google Docs / NotionEDIT-SUGGESTION-*family matrix onlyspecified
collaborationdiscussioneditor-onlyanyanydiscussion anchor / block discussiondiscussion anchors attach to content as editor-only references and stay outside markdown serializationeditor-only contract + Google Docs / NotionEDIT-DISCUSSION-*family matrix onlyspecified
collaborationyjseditor-onlyanyanycursor / presence / collaboration policypresence and remote cursors are runtime collaboration state layered over the editor, not persisted markdown contenteditor-only contract + Google Docs / Figma / NotionEDIT-COLLAB-*family matrix onlyspecified

These rows are still part of the markdown-native family, but they are worth tracking separately because link behavior is much denser than the current law shows.

FamilyEntityContextSelectionCaret / EdgeInputExpectedAuthoritySpec IDEvidenceStatus
markdown-nativelinkparagraphcollapsedplain textpaste URLinsert a link with the pasted URL textCommonMark + Typora / MilkdownEDIT-AFF-LINK-001withLink.spec.tsxtested
markdown-nativelinkparagraphexpanded-inlineselected plain textpaste URLkeep selected text as link text by defaultCommonMark + Typora / MilkdownwithLink.spec.tsxtested
markdown-nativelinkparagraphexpanded-inlineselected plain textpaste URL with keepSelectedTextOnPaste: falsereplace selected text with URL textCommonMark + Typora / MilkdownwithLink.spec.tsxtested
markdown-nativelinkparagraphcollapsedrendered linkplain-clickexpand the link for editing instead of navigating away immediatelyTyporaEDIT-LINK-CLICK-001markdown-reference.json, content/(plugins)/(elements)/link.mdxspecified
markdown-nativelinkparagraphcollapsedrendered linkmod-clickopen the target in the browserTyporaEDIT-LINK-CLICK-002markdown-reference.json, content/(plugins)/(elements)/link.mdxspecified
markdown-nativelinkparagraphcollapsedend of URL texttype spacewrap preceding URL as a linkCommonMark + Typora / MilkdownwithLink.spec.tsxtested
markdown-nativelinkparagraphcollapsedend of visible URL texttype space with getUrlHrefwrap visible text with computed hrefCommonMark + Typora / MilkdownwithLink.spec.tsxtested
markdown-nativelinkparagraphcollapsedinside existing linktype spacedo not wrap againCommonMark + Typora / MilkdownwithLink.spec.tsxtested
markdown-nativelinkparagraphcollapsedend of autolink candidatefinalize autolink before creating the next blockCommonMark + Typora / MilkdownwithLink.spec.tsxtested
markdown-nativelinkparagraphcollapsedempty link after deletionnormalizeremove empty link wrapperCommonMark + Typora / MilkdownwithLink.spec.tsxtested
markdown-nativelinkparagraphcollapsed or expandedinside/outside linkupsert URL/textpreserve marks, update href/text, or unwrap according to transform intentCommonMark + Typora / MilkdownupsertLink.spec.tsx, unwrapLink.spec.tsxtested

Media / Caption Depth Backfill

FamilyEntityContextSelectionCaret / EdgeInputExpectedAuthoritySpec IDEvidenceStatus
block-editor-nativemedia embedparagraphcollapsedwith selection parentinsert embedinsert embed node at the parent path with nextBlock semanticslocal media contract informed by Notion / docsEDIT-MEDIA-*insertMediaEmbed.spec.tstested
block-editor-nativemedia embedparagraphno selectionn/ainsert embedno-oplocal media contract informed by Notion / docsEDIT-MEDIA-*insertMediaEmbed.spec.tstested
block-editor-nativeimage uploadeditordata transfer with image filen/ainsert datacurrent default path ignores upload without a configured overridelocal media contract informed by Notion / docsEDIT-MEDIA-*withImageUpload.spec.tsxtested
block-editor-nativeimage uploadeditorno filesn/ainsert datafall through to default insert data behaviorlocal media contract informed by Notion / docsEDIT-MEDIA-*withImageUpload.spec.tsxtested
block-editor-nativeimage uploadeditornon-image filen/ainsert dataignore non-image file without changing editorlocal media contract informed by Notion / docsEDIT-MEDIA-*withImageUpload.spec.tsxtested
block-editor-nativetoceditable documentn/agenerated entryplain-clicknavigate to the matching heading while keeping the TOC non-editable; do not place a caret in the landed heading or enter block-selection mode as a side effectlocal TOC contract informed by Notion block shell plus Typora / Google Docs heading navigationEDIT-TOC-NAV-001content/(plugins)/(elements)/toc.mdx, markdown-editing-spec.md, navigation-search-outline-and-toc.mdspecified
block-editor-nativetocreadonly documentn/agenerated entryplain-clicknavigate to the matching heading without selection or edit-entry side effectslocal TOC contract informed by Typora / Google Docs heading navigationEDIT-TOC-NAV-001content/(plugins)/(elements)/toc.mdx, markdown-editing-spec.md, navigation-search-outline-and-toc.mdspecified
block-editor-nativetoceditable / readonly documentn/afocused generated entry / Spaceperform the same navigation as pointer activation while keeping the entry keyboard-accessible and avoiding hidden editor-selection focus trapslocal TOC contract informed by Typora / Google Docs heading navigation and Obsidian-style navigation chrome pressureEDIT-TOC-NAV-002markdown-editing-spec.md, navigation-search-outline-and-toc.md, linking-navigation-and-search.mdspecified
block-editor-nativetoctoc blockgenerated entry setcurrent active sectionscroll / editkeep exactly one TOC entry marked current so the live TOC reflects the heading nearest the current document positionlocal TOC contract informed by Typora / Google Docs heading navigation plus current Plate TOC observer surfacesEDIT-TOC-NAV-003useContentController.spec.tsx, useTocElement.spec.tsx, toc-node.spec.tsxtested
block-editor-nativecaptionmedia hostcollapsedarrow-up from caption boundarystore focusEndPath when caption has contentlocal caption contract informed by Notion / DocsEDIT-CAPTION-*withCaption.spec.tsxtested
block-editor-nativecaptionmedia hostcollapsedarrow-up from caption boundaryskip delayed focus when caption is emptylocal caption contract informed by Notion / DocsEDIT-CAPTION-*withCaption.spec.tsxtested

Cross-Surface Interaction Backfill

FamilyEntityContextSelectionCaret / EdgeInputExpectedAuthoritySpec IDEvidenceStatus
cross-surfacesource-entry surfacerendered markdown-native surfacecollapsedsource-editable targetplain-clickprefer source-oriented edit entry over passive preview-only behaviorTyporaEDIT-INTERACT-*links-images-and-html-behavior.md, source-entry-surface.md, markdown-editing-spec.mdspecified
cross-surfacesource-entry surfacerendered markdown-native surfacecollapsedopenable targetmod-clickopen or jump to the target instead of entering edit modeTyporaEDIT-INTERACT-*links-images-and-html-behavior.md, source-entry-surface.md, markdown-editing-spec.mdspecified
cross-surfaceclipboardmixed rich selectionanyn/acopyexpose rich and plain clipboard representations together while preserving the strongest available structureTypora for general markdown-first clipboard semantics, Google Docs for table/document fidelityEDIT-CLIPBOARD-*copy-and-paste.json, MarkdownPlugin.spec.ts, PlateView.tsx, withSetFragmentDataTable.spec.tsxpartial
cross-surfaceclipboardeditorclipboard carries html plus plain textn/apasteprefer HTML reconstruction, then fall back to markdown source or plain text without dropping structure too earlyTypora for general markdown-first paste semantics, Google Docs for table/document fidelityEDIT-CLIPBOARD-*copy-and-paste.json, MarkdownPlugin.spec.ts, withInsertFragmentTable.spec.tsxspecified
cross-surfacedelete commandparagraphcollapsedcurrent sentencedelete commanddelete the current sentence instead of treating the action like block removalTyporaEDIT-CMD-DELETE-*delete-range.jsonspecified
cross-surfacedelete commandtablecollapsedcurrent rowdelete commanddelete the current row instead of applying generic text deletion inside the active cellGoogle Docs + TyporaEDIT-CMD-DELETE-*delete-range.json, transforms/deleteRow.spec.tsx, merge/deleteRow.spec.tsxspecified
cross-surfacedelete commandcode blockcollapsedcurrent linedelete commanddelete the current code line like a code editor instead of structurally exiting the blockTyporaEDIT-CMD-DELETE-*delete-range.json, withCodeBlock.spec.tsxspecified
cross-surfacedelete commandmath blockcollapsedcurrent linedelete commanddelete the current math line like a code-like editing surface instead of structurally exiting the blockTyporaEDIT-CMD-DELETE-*delete-range.json, markdown-editing-reference-audit.mdspecified
cross-surfacesearchdocumentcollapsedcurrent caretopen findopen current-file search without changing document structureTyporaEDIT-SEARCH-*search.json, shortcut-keys.jsondeferred
cross-surfacesearchdocumentcollapsedactive selectionopen search from selectionseed the search surface from the current selection instead of discarding it and reopening with an empty queryObsidian for selected-text search kickoff, Typora as the current-file find secondary checkEDIT-SEARCH-*Search.md, search.json, shortcut-keys.jsondeferred
cross-surfacesearchdocumentcollapsedcurrent caretfind next / previousmove to the next or previous match from the active search state instead of restarting generic navigationTyporaEDIT-SEARCH-*search.json, shortcut-keys.json, what-s-new-0-9-54.jsondeferred
cross-surfacesearchdocumentcollapsedcurrent selectionjump to selectionscroll and focus the active selection instead of changing document contentTyporaEDIT-SEARCH-*shortcut-keys.jsondeferred
cross-surfacesearchdocumentcollapsed / expandedactive matchreplacereplace only the matched range and preserve surrounding block structure instead of degrading into raw text replacement across unrelated nodesTyporaEDIT-SEARCH-*search.json, shortcut-keys.json, content/(plugins)/(functionality)/find-replace.mdxdeferred
cross-surfacenavigation feedbacksearch targetafter search jumpcollapsed / expandednavigation completesbriefly highlight the landed search target while preserving active search state and the landed caret or selectionlocal shared navigation-feedback contract informed by Typora / Obsidian / Google DocsEDIT-NAV-FEEDBACK-*markdown-editing-spec.md, search.json, Search.mddeferred
cross-surfaceoutlinedocument heading treen/aoutline itemplain-clicknavigate to the matching heading and keep current-section highlighting coherent while editing and scrolling; do not create landed caret or block-selection state as a side effectObsidian for persistent outline chrome, Google Docs for linear heading jump, Typora as markdown-first secondary checkEDIT-INTERACT-*Outline.md, outline.json, markdown-editing-spec.mdspecified
cross-surfaceoutlinedocument heading treen/afocused outline item / Spaceperform the same navigation as pointer activation while keeping the outline keyboard-accessibleObsidian for persistent outline chrome, Google Docs for linear heading jumpEDIT-INTERACT-*Outline.md, outline.json, markdown-editing-spec.mdspecified
cross-surfaceoutlinedocument heading treen/acurrent active sectionscroll / edithighlight the current heading in the outline while the user edits or scrolls through the documentGoogle Docs for linear document navigation, Obsidian as persistent-outline pressureEDIT-INTERACT-*outline.json, Outline.mdspecified
cross-surfaceoutlinedocument heading treen/afilter inputsearch headersfilter the outline to quickly locate target headings without changing document contentTypora + Google Docs-style document navigationEDIT-SEARCH-*outline.json, what-s-new-0-9-61.jsondeferred
cross-surfacenavigation feedbackheading targetafter TOC / outline jumpn/anavigation completesbriefly highlight the landed heading while preserving the navigation result and current-section statelocal shared navigation-feedback contract informed by Obsidian / Google DocsEDIT-NAV-FEEDBACK-*markdown-editing-spec.md, toc.mdx, Outline.mdspecified
cross-surfacetyped syntax-trigger conversionmarkdown-native source syntaxcollapsed / expanded-inlineincomplete or ambiguous sourcetype intermediate delimiter or partial source entrykeep the source literal instead of converting earlyTypora primary; Obsidian and Milkdown as conversion-boundary counterweightsEDIT-CONVERT-001input-autoformat-lanes.md, math-delimiters-and-pair-settings.md, markdown-editing-spec.mdspecified
cross-surfacetyped syntax-trigger conversionmarkdown-native source syntaxcollapsed / expanded-inlineexplicit completing triggertype the completing trigger for the surfaceconvert only at an explicit boundary and preserve the subfamily's explicit re-entry path instead of leaving passive preview-only outputTypora primary; Obsidian and Milkdown as row-specific cross-checksEDIT-CONVERT-002input-autoformat-lanes.md, math-delimiters-and-pair-settings.md, markdown-editing-spec.mdspecified
cross-surfacehtml blockmarkdown / mdxround-trip / edit-entry fallbackraw HTML block in markdown inputdeserializepreserve the HTML block as editable source text instead of dropping attributes or degrading it into lossy fallback textCommonMark HTML block semantics + Typora source-entry pressureEDIT-INTERACT-*deserializeMd.spec.ts, customMdxDeserialize.spec.ts, links-images-and-html-behavior.mdtested
cross-surfacehtml blockhtml blockcollapsednon-interactive region of a richer rendered html surfaceplain-click / mod-click / cursor-entryenter HTML-block edit mode instead of treating the block as pure rendered output chromeTypora + CommonMark HTML block semanticsEDIT-INTERACT-*html.jsondeferred
cross-surfaceimage authoringeditorcollapsedinsertion pointdrag / drop / paste imagefollow the active image path policy and insert an image surface without forcing raw file URLs into generic textTypora for markdown-native authoring expectations, local media contract for current package seamsEDIT-IMG-*images.json, upload-image.json, withImageUpload.spec.tsxspecified
cross-surfaceimage authoringmarkdown imagecollapsedrendered imageplain-clickprefer source editing when the image surface is directly editableTyporaEDIT-IMG-*markdown-reference.json, images.jsonspecified
cross-surfaceimage authoringmarkdown imagecollapsedexisting image sourcemove / copy image path actionrewrite the stored path and keep markdown references coherent when the product exposes explicit path-management actionsTyporaEDIT-IMG-*images.jsonspecified
cross-surfacemedia authoringvideo / audio / embed blockcollapsedinsertion pointdrag / drop or paste supported mediafollow the same active path-policy family as images instead of inventing a separate media path modelTypora for path expectations, local media contract for current package seamsEDIT-MEDIA-*media.json, withImageUpload.spec.tsxspecified
cross-surfaceblock shorthand autoformatparagraphcollapsedblock starttype # retag the current block into a heading when the shorthand closesCommonMark heading syntax + Typora / MilkdownEDIT-PROFILE-AUTOFMT-BLOCK-001markdown-shorthand-and-inline-autoformat.md, input-autoformat-lanes.md, withAutoformat/block/heading.spec.tsxspecified
cross-surfaceblock shorthand autoformatparagraph / quote paragraphcollapsedblock starttype > wrap the current block in a blockquote container, including nested quote entry when the rule allows same-type wrappingCommonMark blockquote syntax + Typora / MilkdownEDIT-PROFILE-AUTOFMT-BLOCK-002markdown-shorthand-and-inline-autoformat.md, input-autoformat-lanes.md, apps/www/src/__tests__/package-integration/autoformat/blockquote.slow.tsxspecified
cross-surfaceblock shorthand autoformatparagraphcollapsedblock starttype - / * / 1. / 1) convert the block into a list item and preserve explicit ordered starts when suppliedCommonMark / GFM list syntax + Typora / MilkdownEDIT-PROFILE-AUTOFMT-BLOCK-003markdown-shorthand-and-inline-autoformat.md, input-autoformat-lanes.md, apps/www/src/__tests__/package-integration/autoformat/list.slow.tsxspecified
cross-surfaceblock shorthand autoformatparagraphcollapsedblock starttype [] / [x] current kit creates unchecked or checked todo items from condensed task shorthandlocal current task-shorthand contract informed by Typora / Milkdown task syntaxEDIT-PROFILE-AUTOFMT-BLOCK-004apps/www/src/registry/components/editor/plugins/autoformat-kit.tsx, apps/www/src/__tests__/package-integration/autoformat/list.slow.tsxspecified
cross-surfaceblock shorthand autoformatparagraphcollapsedfence triggertype the third backtick of a triple-backtick sequencecurrent kit promotes immediately into a code block owner when the triple-backtick shorthand closeslocal current code-fence trigger contract informed by Typora code-fence docsEDIT-PROFILE-AUTOFMT-BLOCK-005markdown-shorthand-and-inline-autoformat.md, withAutoformat/block/code-block.spec.tsxspecified
cross-surfaceblock shorthand autoformatparagraphcollapsedhr triggertype --- / —- / ___ current kit inserts a horizontal rule and a trailing paragraph immediately when the shorthand closeslocal current HR shorthand contract informed by Typora thematic-break docsEDIT-PROFILE-AUTOFMT-BLOCK-006markdown-shorthand-and-inline-autoformat.md, apps/www/src/registry/components/editor/plugins/autoformat-kit.tsxspecified
cross-surfaceinline mark autoformatparagraphcollapsedvalid delimiter spantype closing * / _ / ~~ / `convert the delimited span to the target mark and remove the wrappersCommonMark / GFM + Typora / MilkdownEDIT-PROFILE-AUTOFMT-MARK-001markdown-shorthand-and-inline-autoformat.md, input-autoformat-lanes.md, withAutoformat/mark/basic-marks.spec.tsxspecified
cross-surfaceinline mark autoformatparagraphcollapsedvalid == / ~ / ^ spantype closing delimiterconvert the delimited span to highlight, subscript, or superscript mark and remove the wrappersTypora + local current mark contractEDIT-PROFILE-AUTOFMT-MARK-002markdown-shorthand-and-inline-autoformat.md, apps/www/src/registry/components/editor/plugins/autoformat-kit.tsxspecified
cross-surfaceinline mark autoformatparagraphcollapsedvalid composed delimiter spantype closing delimiter for *** or related compositionsapply the configured combined marks in one passlocal current mark-composition contract informed by markdown delimiter nestingEDIT-PROFILE-AUTOFMT-MARK-003withAutoformat/mark/multiple-marks.spec.tsx, withAutoformat/markup.spec.tsxspecified
cross-surfaceinline mark autoformatparagraphcollapsedinvalid / intra-word delimiter runtype closing delimiterleave the text literal instead of forcing a markMilkdown explicit + local current testsEDIT-PROFILE-AUTOFMT-MARK-004input-autoformat-lanes.md, withAutoformat/invalid.spec.tsx, withAutoformat/ignoreTrim.spec.tsxspecified
cross-surfaceinline mark autoformatparagraphcollapsedoverlapping == triggertype closing = around texthighlight-mark autoformat wins before equality-symbol substitution in current app-kit rule orderlocal current rule-order contractEDIT-PROFILE-AUTOFMT-MARK-005apps/www/src/registry/components/editor/plugins/autoformat-kit.tsx, packages/autoformat/src/lib/rules/math/autoformatEquality.tsspecified
cross-surfacetext-substitution autoformatparagraphcollapsedquote triggertype a straight quote in a valid smart-quote contextreplace straight quotes with smart quotes in placemainstream typographic norms + local current contractEDIT-PROFILE-AUTOFMT-TEXT-001withAutoformat/text.spec.tsx, autoformatSmartQuotes.tsspecified
cross-surfacetext-substitution autoformatparagraphcollapsedpunctuation shorthandtype -- / ... / >> / <<replace the shorthand with typographic punctuation in placemainstream typographic norms + local current contractEDIT-PROFILE-AUTOFMT-TEXT-002withAutoformat/text.spec.tsx, autoformatPunctuation.tsspecified
cross-surfacetext-substitution autoformatparagraphcollapsedsymbol shorthandtype -> / (tm) / 1/2 / >= or another configured symbol sequencereplace the shorthand with the configured symbol in placelocal current shorthand contract with thinner external groundingEDIT-PROFILE-AUTOFMT-TEXT-003text-substitution-autoformat-authority.md, withAutoformat/text.spec.tsx, autoformatMath.spec.tsspecified
cross-surfacetext-substitution autoformatparagraphcollapsedimmediately after a text substitutionpress with undo-on-delete enabledrestore the original shorthand instead of deleting the formatted symbol directlylocal current contractEDIT-PROFILE-AUTOFMT-TEXT-004AutoformatPlugin.spec.tsx, withAutoformat/trigger.spec.tsxspecified
cross-surfaceautoformat gatingcode blockcollapsedinside code blocktype a matching shorthandkeep the text literal because the current app kits disable autoformat inside code blockslocal current kit contractEDIT-PROFILE-AUTOFMT-TEXT-005apps/www/src/registry/components/editor/plugins/autoformat-kit.tsxspecified
cross-surfacelink automdparagraphcollapsedcomplete [text](url source entrytype )create a structured inline link span from markdown source entry when the link-automd surface is enabledCommonMark link syntax + Typora / MilkdownEDIT-INTERACT-LINK-AUTOMD-001markdown-shorthand-and-inline-autoformat.md, input-autoformat-lanes.md, packages/link/src/lib/automd/linkAutomdInputRule.spec.tsx, apps/www/src/__tests__/package-integration/link/link-automd.slow.tsxtested
cross-surfacestrict modemarkdown inputcollapsedmalformed heading or list-following paragraph syntaxtype markdown syntax with strict mode enabledkeep malformed source as text until it satisfies stricter markdown structure rulesTypora + CommonMark / GFM strict syntax expectationsEDIT-PROFILE-STRICT-*strict-mode.jsonspecified
cross-surfaceauto pairmarkdown inputcollapsedopening bracket or quotetype pair opener with auto pair enabledinsert the matching closer using standard editor pairing behaviorTypora + mainstream code-editor normsEDIT-PROFILE-AUTOPAIR-*auto-pair.jsonspecified
cross-surfaceauto pairmarkdown inputexpanded-inlineselected texttype markdown-sensitive pair with auto pair enabledwrap the selection instead of blindly inserting a closing pair for ambiguous markdown symbolsTypora + mainstream code-editor normsEDIT-PROFILE-AUTOPAIR-*auto-pair.jsonspecified
cross-surfacemath delimiter triggerparagraphexpanded-inlineselected texttype $wrap the selection in inline-math delimiters when the math-trigger surface is enabledObsidian explicit; Typora and Milkdown adjacentEDIT-PROFILE-MATH-TRIGGER-001math-delimiters-and-pair-settings.mddeferred
cross-surfacemath delimiter triggerparagraphcollapsedcomplete $... source before the carettype closing $convert the completed delimiter run into an inline math node on explicit completion instead of pairing on the opening delimiterlocal current rich-mode conversion decision informed by source-preserving conversion law, with Typora / Milkdown adjacentEDIT-PROFILE-MATH-TRIGGER-002packages/autoformat/src/lib/rules/math/autoformatMathInput.spec.tsx, apps/www/src/__tests__/package-integration/math/math-trigger.slow.tsx, markdown-editing-spec.mdtested
cross-surfacemath delimiter triggerparagraphcollapsedline contains $$ onlypress promote into block math editing instead of leaving raw text when the trigger surface is enabledTypora + Milkdown explicit; Obsidian explicit for standalone-line $$ block detection and preview, not the same promotion mechanicEDIT-PROFILE-MATH-TRIGGER-003packages/autoformat/src/lib/rules/math/autoformatMathInput.spec.tsx, apps/www/src/__tests__/package-integration/math/math-trigger.slow.tsx, markdown-editing-spec.mdtested

Practical Use

If a row only exists in the parity matrix, it is not protocol-complete yet.