← All products
KAI-15 Idea high

P2.1 · ProseMirror ↔ Markdown converter with unit tests

Why this is a separate ticket

Linear stores issue descriptions as ProseMirror JSON, not markdown. The API accepts markdown on write, but reads return ProseMirror. The conversion is the single highest-risk piece of the whole product.

What

Module src/convert/ with two entry points:

  • proseMirrorToMarkdown(doc: PMNode): string
  • markdownToProseMirror(md: string): PMNode

Nodes to support

  • Headings h1–h6
  • Paragraphs
  • Bold, italic, strikethrough, inline code
  • Code blocks with language hint
  • Ordered and unordered lists, including nested lists (main gotcha)
  • Links
  • Linear user mentions (@usermention node with userId)
  • Issue references (KAI-12 → Linear renders as a link)
  • Images / attachments
  • Blockquotes
  • Horizontal rules

Technical approach

  • Use prosemirror-markdown as a starting point but override the schema to match Linear's (which differs slightly from commonmark).
  • Inspect Linear's schema by pulling a rich issue via the API and logging the returned ProseMirror structure.

Acceptance criteria

  • 25+ fixture files: each is a ProseMirror JSON doc. Test: markdownToProseMirror(proseMirrorToMarkdown(fixture)) === fixture structurally (with a deep-equal ignoring whitespace-only differences).
  • Lossless roundtrip on 95%+ of fixtures. Document the 5% known-lossy cases in a LIMITATIONS.md.
  • Handles nested list depth ≥ 3.
Updated
2026-04-22