Markdown

The round trip through Markdown, and what it loses.

Markdown is an export and an import, not the stored format. The document stays JSON; contentToMarkdown writes GFM and contentFromMarkdown reads it, over the registry's own features.

## Writing inside your own app

Rich text with **bold**, _italic_ and a [link](https://ui.voila.dev). Type / for a block, or select text for the floating toolbar.

<callout icon="💡">
  Every block on this page is one feature definition.
</callout>

* Lists, with Tab to nest
* Tables, images, embeds

> And a quote, for when someone else said it better.
import { contentFromMarkdown, contentToMarkdown } from "@voila.dev/ui/content-editor";
 
const markdown = contentToMarkdown(value, { features: FEATURES });
const value = contentFromMarkdown(markdown, { features: FEATURES });

What crosses how

Paragraphs, marks, headings, links, lists, quotes, dividers and tables are GFM. An image is an mdast image, its caption as the title. A callout and the four embeds, which Markdown has no words for, cross as MDX elements named after their type (<callout icon="💡">, <youtube-video videoId="…" />): a plain Markdown reader sees the tag, an MDX reader gets the node back.

What Markdown loses is named on each rule (markdown.loss): an image's width and height today. A test asserts that loss, so a Plate upgrade that starts carrying it shows up red rather than silently.

Importing existing content

contentFromMarkdown reads Markdown a human wrote: # headings, - lists, **bold**, links. Run scrubImportedContent over the result when the source carried stray line breaks or zero-width characters, the usual souvenirs of a migration.