Back to Plate

Markdown Editing Reference Audit

docs/editor-behavior/markdown-editing-reference-audit.md

53.0.533.6 KB
Original Source

Markdown Editing Reference Audit

This is the first side-by-side audit of markdown-editing-spec.md against the local Typora corpus and the upstream Milkdown raw clone.

It is not the whole external-reference story anymore. Obsidian is now a separate stronger product reference for dual-mode editing, linked-note navigation, backlinks, block references, and search chrome.

Primary reference: Typora.
Companion reference: Milkdown.

Broad corpus work is done. For Batch 1, do not do more broad scanning. Either use the locked reference-backed rows below, or use the explicit Plate-owned decisions called out here.

Method

  • Use explicit evidence first.
  • Treat silence as a gap, not as fake agreement.
  • When Typora is explicit and Milkdown is merely compatible, that is enough to lock the markdown_typora profile.
  • When Typora and Milkdown pull in different directions, push the behavior down into profile-owned policy instead of hard-coding one global default.

Result Labels

  • agree: both references explicitly support the direction
  • partial: one reference is explicit or both are only indirectly supportive
  • gap: no direct evidence worth locking
  • tension: current draft spec is too confident for the evidence
  • diverge: Typora and Milkdown clearly want different behavior

Primary Moves

  • Lock now:
    • EDIT-P-ENTER-001
    • EDIT-H-ENTER-END-001
    • EDIT-LIST-ENTER-001
    • EDIT-LIST-ENTER-EMPTY-001
    • EDIT-BQ-ENTER-001
    • EDIT-MATH-ENTER-001
    • EDIT-TABLE-TAB-001
  • Revise now:
    • EDIT-AFF-LINK-001
    • EDIT-AFF-MARK-001
    • EDIT-AFF-HARD-001
  • Lock as Plate decisions now:
    • EDIT-LIST-ENTER-EMPTY-ROOT-001
    • EDIT-LIST-BS-START-001
    • EDIT-LIST-BS-START-EMPTY-001
    • EDIT-LIST-BS-START-EMPTY-ROOT-001
    • EDIT-BQ-ENTER-EMPTY-001
    • EDIT-BQ-ENTER-EMPTY-NESTED-001
    • EDIT-BQ-BS-START-001
    • EDIT-BQ-BS-START-EMPTY-NONFIRST-001
    • EDIT-BQ-BS-START-ONLY-001
    • EDIT-BQ-STAB-001
    • EDIT-BQ-LIST-ENTER-EMPTY-001
    • EDIT-BQ-LIST-BS-START-001
    • EDIT-BQ-LIST-STAB-001
    • EDIT-CB-ENTER-001
    • EDIT-CB-BS-START-001
    • EDIT-CB-BS-START-EMPTY-LINE-001
    • EDIT-CB-BS-START-EMPTY-001
    • EDIT-CB-TAB-001
    • EDIT-CB-STAB-001
    • EDIT-TABLE-STAB-001
  • Keep open:
    • paragraph and heading destructive fallback outside owned containers
    • table Enter and table Backspace@start
    • math-block tab semantics
    • expanded structural selections
    • toggle behavior

Evidence Map

Global Invariants

IDTyporaMilkdownAuditMove
EDIT-GLOBAL-001block-local commands exist for quote, list, code, math, tabletests show table, list, code, and math all own local behaviorpartialkeep as default law, do not lock yet
EDIT-GLOBAL-002nested quote creation and indent/outdent imply stepwise structurenested list tests outdent one level at a timepartialkeep proposed
EDIT-GLOBAL-003no direct docnested list double-Enter exits one list level, not allpartialkeep proposed
EDIT-GLOBAL-004Delete Range explicitly deletes the current empty block instead of inventing structural lifttransform/preserve-empty-line.spec.ts deletes the last empty line and list tests stay stepwise when structure changespartiallock as the default destructive rule: same-container empty-block delete/merge first, structural lift second
EDIT-GLOBAL-005no direct docno structural selection proofgapkeep open

Paragraph

IDTyporaMilkdownAuditMove
EDIT-P-ENTER-001Markdown Reference and Shortcut Keys explicitly define Enter as new paragraphe2e/tests/shortcut/system.spec.ts explicitly splits into two paragraphsagreelock
EDIT-P-ENTER-EMPTY-001docs describe paragraph creation, but not the empty-root edgetransform/preserve-empty-line.spec.ts shows empty-doc Enter can serialize as `
`tensionkeep open
EDIT-P-BS-START-001no start-Backspace paragraph ruleno direct testgapkeep open
EDIT-P-BS-START-EMPTY-001Delete Range explicitly deletes the current empty blocktransform/preserve-empty-line.spec.ts deletes the last empty line on Backspaceagreelock
EDIT-P-TAB-001Shortcut Keys maps Tab to paragraph-layer indentno plain-paragraph Tab proofpartialalign with Typora: plain paragraphs keep Tab editor-owned and indent
EDIT-P-STAB-001Shortcut Keys maps Shift+Tab to paragraph-layer outdentno plain-paragraph Shift+Tab proofpartialalign with Typora: plain paragraphs keep Shift+Tab editor-owned and outdent

Heading

IDTyporaMilkdownAuditMove
EDIT-H-ENTER-001heading creation is documented, middle split is notheading input exists, middle split is not testedgapkeep local policy only after direct tests
EDIT-H-ENTER-END-001heading is created by typing # ... then Returninput/heading.spec.ts shows Enter after heading moves to the next block lanepartiallock for markdown-first profile
EDIT-H-BS-START-001paragraph reset exists as a command, not as Backspace@startparagraph reset exists as a command, not as Backspace@startgaplock as Plate decision: one resets a heading to paragraph before any merge
EDIT-H-BS-START-EMPTY-001Delete Range implies empty heading blocks are deleted as empty blocksno direct testpartiallock as Plate decision: one resets an empty heading to an empty paragraph before any merge

List Item

IDTyporaMilkdownAuditMove
EDIT-LIST-ENTER-001list typing model implies continuation, but the docs stop short of spelling out split rulesinput/{bullet-list,ordered-list}.spec.ts explicitly split non-empty itemspartiallock
EDIT-LIST-ENTER-EMPTY-001no explicit nested empty-item exit docinput/{bullet-list,ordered-list}.spec.ts explicitly outdent one level on empty nested itempartiallock
EDIT-LIST-ENTER-EMPTY-ROOT-001no direct docno direct testgaplock as Plate decision: empty top-level list item exits to paragraph
EDIT-LIST-BS-START-001no direct doclist setup uses Backspace as a step-down from the current list layer before retypingpartiallock as Plate decision: non-empty list item removes one list layer before dropping content
EDIT-LIST-BS-START-EMPTY-001no direct doclist setup uses Backspace from the fresh empty item lane before nested re-entrypartiallock as Plate decision: empty nested list item outdents one list level
EDIT-LIST-BS-START-EMPTY-ROOT-001Delete Range implies empty blocks delete in place, but does not describe list-root exitno direct testgaplock as Plate decision: empty top-level list item exits to paragraph
EDIT-LIST-TAB-001Shortcut Keys explicitly expose indent, and lists are the clearest fitshortcut/list.spec.ts exposes equivalent indent via command shortcut, not Tabpartiallock behavior, keep exact binding profile-owned
EDIT-LIST-STAB-001Shortcut Keys explicitly expose outdentshortcut/list.spec.ts exposes equivalent outdent via command shortcut, not Shift+Tabpartiallock behavior, keep exact binding profile-owned

Blockquote

IDTyporaMilkdownAuditMove
EDIT-BQ-ENTER-001Markdown Reference explicitly says Typora inserts the proper > or line breakinput/blockquote.spec.ts explicitly keeps the next paragraph inside the quoteagreelock
EDIT-BQ-ENTER-EMPTY-001no direct exit docno direct empty-exit testgaplock as Plate decision: empty top-level quote paragraph exits one quote level
EDIT-BQ-ENTER-EMPTY-NESTED-001nesting is documented, nested exit is notno direct testgaplock as Plate decision: empty nested quote paragraph exits to the parent quote level
EDIT-BQ-BS-START-001no direct docno direct testgaplock as Plate decision: non-empty quoted paragraph removes one quote level from the current block only
EDIT-BQ-BS-START-EMPTY-NONFIRST-001Delete Range implies an empty block should be deleted in place before a structural escapeno direct quote-specific testpartiallock as Plate decision: empty non-first quoted paragraph deletes or merges inside the quote
EDIT-BQ-BS-START-ONLY-001no direct docno direct testgaplock as Plate decision: first empty quote paragraph with no previous sibling exits one quote level
EDIT-BQ-STAB-001generic outdent exists, but quote-specific outdent is not documentedno direct testgaplock as Plate decision: outdent one quote level
EDIT-BQ-TAB-001generic indent exists, so quote paragraphs should not fall out of the editor on plain Tabno direct testpartialalign with Typora: quoted paragraphs inherit paragraph indent behavior on plain Tab without changing quote depth

Quote + List Interaction

IDTyporaMilkdownAuditMove
EDIT-BQ-LIST-ENTER-EMPTY-001no direct docno direct testgaplock as Plate decision: list owns the first exit step, quote owns the second
EDIT-BQ-LIST-BS-START-001no direct docno direct testgaplock as Plate decision: list owns the first outdent step, quote owns the second
EDIT-BQ-LIST-STAB-001no direct docno direct testgaplock as Plate decision: outdent list first, then quote

Code Block

IDTyporaMilkdownAuditMove
EDIT-CB-ENTER-001code fences are treated as an editing mode, but enter-line indentation is not directly documentedCrepe code blocks are real code editors, but there is no explicit Enter indentation testpartiallock as Plate decision: Enter inserts a code line and preserves indentation
EDIT-CB-BS-START-001Delete Range treats code blocks like code editors for line deletion, not paragraph-like exitsCrepe code blocks are real code-editor surfacespartiallock as Plate decision: non-empty code-line Backspace@start stays inside the code block
EDIT-CB-BS-START-EMPTY-LINE-001code blocks follow code-editor line behaviorCrepe code blocks are real code-editor surfacespartiallock as Plate decision: empty non-first code line merges with the previous line
EDIT-CB-BS-START-EMPTY-001Delete Range says empty code blocks are deleted as empty blocksno direct testpartiallock as Plate decision: empty code block unwraps on Backspace@start
EDIT-CB-TAB-001Code Fences docs focus on configurable Shift+Tab behavior and auto-indent, not plain Tabno direct testtensionlock as Plate decision: Tab indents selected code lines
EDIT-CB-STAB-001Code Fences explicitly expose Shift+Tab behavior for selected code, but the exact indent/outdent polarity is not clean enough to lock from docs aloneno direct testtensionlock as Plate decision: Shift+Tab outdents selected code lines

Math Block

IDTyporaMilkdownAuditMove
EDIT-MATH-ENTER-001Math and Academic Functions explicitly enters math-edit mode on $$ + Return and exits via arrows or mod-Entercrepe/latex.spec.ts explicitly creates a block math editor and uses ArrowUp to editagreelock
EDIT-MATH-BS-START-001math blocks are treated like code-editing mode, not paragraph modecrepe/latex.spec.ts keeps deletion inside inline math editing, not structural exitpartiallock as Plate decision: non-empty math block keeps deletion inside math editing
EDIT-MATH-BS-START-EMPTY-001Delete Range says empty math blocks are deleted as empty blocksno block-math Backspace@start testpartiallock as Plate decision: empty math block exits the block
EDIT-MATH-TAB-001no direct docno direct testgaplock as Plate decision: keep tab owned by math editing unless a stronger math surface overrides it

Table Cell

IDTyporaMilkdownAuditMove
EDIT-TABLE-TAB-001Table Editing explicitly says newer versions add rows by pressing Tabcrepe/table.spec.ts explicitly uses Tab to move across cellsagreelock
EDIT-TABLE-STAB-001no direct reverse-navigation docno explicit Shift+Tab testgaplock as Plate decision: Shift+Tab moves to the previous cell
EDIT-TABLE-ENTER-001table docs focus on creation and row tools, not paragraph splitting inside a cellno direct testgaplock as Plate decision: Enter stays inside the cell
EDIT-TABLE-BS-START-001Delete Range and Table Editing keep destructive table actions row-scoped or command-scoped, not implicit escape from a cellinput/table.spec.ts only covers deleting a list item after a tablepartiallock as Plate decision: Backspace@start stays inside the cell and does not escape the table

Toggle

IDTyporaMilkdownAuditMove
EDIT-TOGGLE-ENTER-001not a native Typora markdown blockno markdown-native referencegapdefer to non-markdown profile work
EDIT-TOGGLE-BS-START-001not a native Typora markdown blockno markdown-native referencegapdefer to non-markdown profile work
EDIT-TOGGLE-TAB-001not a native Typora markdown blockno markdown-native referencegapdefer to non-markdown profile work

Thematic Break And Atomic Blocks

IDTyporaMilkdownAuditMove
EDIT-HR-ENTER-001HR creation is documented, behavior around an existing HR is notHR creation is tested, adjacent Enter is notgaplock as Plate decision: create an adjacent paragraph instead of editing inside the HR
EDIT-ATOMIC-BS-START-001no direct docno direct testgaplock as Plate decision: atomic owners win over generic merge

Expanded Selection Rules

IDTyporaMilkdownAuditMove
EDIT-SEL-ENTER-001no structural selection docno structural selection + Enter testgaplock from existing protocol behavior: replace the selection without corrupting structure
EDIT-SEL-BS-001no structural selection docno structural selection + Backspace testgaplock from existing protocol behavior: delete the selection without corrupting structure
EDIT-SEL-STAB-001no structural selection docno structural multi-block outdent testgaplock from existing protocol behavior: outdent all selected blocks one owned level

Affinity Rules

IDTyporaMilkdownAuditMove
EDIT-AFF-LINK-001Markdown Reference says moving into a span expands it into markdown sourceplugin/clipboard.spec.ts, component-link-tooltip.md, and crepe/top-bar/config.ts keep link marks active and can extend a link on pastedivergeresolve against the strongest mainstream editor precedent instead of inheriting a Plate-only default
EDIT-AFF-MARK-001span elements expand into source when the cursor moves into themplugin/automd.spec.ts plus crepe/top-bar/config.ts favor inclusive stored-mark behaviordivergeresolve toward dominant rich-text boundary typing, not Typora source expansion or legacy Plate behavior
EDIT-AFF-HARD-001Typora behaves like hard boundaries around many span elementsMilkdown defaults are soft and inclusivedivergekeep source-biased hard boundaries for source-like inline nodes such as inline code

What This Means

This audit is no longer the release checklist. The readable law and protocol matrix have moved forward since the first Typora/Milkdown pass.

One later synthesis step matters for markdown-native interaction law:

  • links, markdown images, and HTML blocks now share an explicit source-entry-surface interaction family
  • that synthesis comes from the compiled Typora research in docs/research/sources/typora/links-images-and-html-behavior.md plus the derived concept / decision pages in docs/research
  • typed syntax-trigger conversions such as link automd and math delimiter triggers now sit under the same broader source-preserving conversion idea: preserve source until the boundary is explicit, then convert without losing a path back into source-oriented editing or an explicit editor

Use this file for:

  • direct reference evidence
  • explicit divergence records
  • reminders about where Plate had to choose

Do not use this file as the current source of truth for lock state. That now lives in:

The old EDIT-AFF-MARK-001 divergence still matters as audit history, but it is no longer an unresolved blocker. The current law has already chosen a mark affinity direction in markdown-editing-spec.md.

Everything here should now be read as audit history unless it directly contradicts the current law.

Typora Drift Watchlist

The old inline watchlist lived here.

Now that Typora has a real research layer, use these entrypoints instead:

Use those pages as drift checks when the readable law or protocol matrix starts to feel too static or too anchored to older Typora behavior.

Milkdown Research Entry Points

For broader Milkdown repo navigation and source clustering, use:

Obsidian Research Entry Points

For mode architecture, linked-note navigation, and richer markdown-workspace search/product chrome, use:

Do not force those Obsidian lanes back into the first Typora / Milkdown row audit. They are a newer authority layer, and they win in different product surfaces.

That now includes math-trigger authority pressure:

  • Obsidian is explicit for conservative $ selection-wrap and $$ line-shaped block detection / preview
  • Typora and Milkdown remain stronger for aggressive $ pair-on-type and $$ plus Enter promotion

Do not flatten that into one fake “math trigger winner.”

Autoformat Research Entry Points

For markdown-triggered autoformat and shorthand work, use:

Use those pages for:

  • block shorthand authority
  • markdown-delimiter mark autoformat
  • invalid-match guardrails
  • explicit thinner authority on symbol-substitution shorthand
  • link-automd boundary decisions
  • current-kit quirk normalization decisions

For TOC and outline activation, the compiled refs establish:

  • heading-navigation intent
  • current-section highlighting pressure
  • TOC token creation and auto-update expectations

They do not directly settle:

  • whether editable-surface activation should place a caret in the landed heading
  • whether activation should enter block-selection mode
  • exact keyboard-activation semantics for generated TOC / outline controls

Treat those focus and selection details as local Plate navigation-control policy, informed by Typora / Obsidian / Google Docs, until stronger direct evidence lands.