Rich text / foldkit-richtext-markdown

Print a document

ts
import * as RichText from 'foldkit-richtext'
import { print } from 'foldkit-richtext-markdown'

const document = RichText.decodeDocument({
  version: 1,
  children: [
    {
      type: 'Paragraph',
      id: 'p',
      children: [{ type: 'Text', id: 't', text: 'hello', marks: [] }],
    },
  ],
})

const { markdown, diagnostics } = print(document)

markdown // 'hello\n'
diagnostics // []

diagnostics names every kind or mark the mapping has no syntax for. A block kind with no syntax prints its content rather than losing it; a preserved Unknown block is reported and skipped, because its payload is opaque.

DocumentMarkdown
Paragraph, Headingthe text, and #…######
Quote> on every line, a blank one included
List, ListItem, TaskItem- / 1. and - [x]; a nested block stays aligned under its marker, and a list right after another of the same kind takes the other marker (*, )) so it reads back as its own list
CodeBlocka fence, its language, the text verbatim, and a fence longer than any backticks inside
ThematicBreak---
Image![alt](src) on its own line
FootnoteRef on a run[^label] in place of the label the run shows
FootnoteDefinition[^label]: and its first block, later lines indented four
Table, TableRow, TableCella GFM pipe table, the first row as its header (TableRow.header)
Bold, Italic, Code, Strikethrough, Link**, *, backticks, ~~, [label](href), with the link outermost

Text is escaped so it cannot become markup: a backslash before an inline delimiter (and before ! and |, which could start an image or a table), and before a block marker — or a 1. — that would open a paragraph's line. A leading space becomes  . Where CommonMark would not let a delimiter open or close because punctuation sits on one side and a letter on the other (x**(a)**y), the letter is written as a character reference (x**(a)**y), which reads back as the same letter. An empty task item prints as - [ ], which GFM alone would read as text; parse reads an item holding only [ ] or [x] back as that empty task.