Skip to main content

Compatibility

This renderer is not a drop-in replacement for react-markdown. It is a different package with a compatible surface for the props people actually migrate. Same prop names, same meanings, same default URL policy. Where behaviour differs, the difference is listed rather than smoothed over.

The numbers below come from a test that renders identical input through both packages and compares normalized HTML. It regenerates docs/COMPATIBILITY.md on every run, so that file is the authority and this page is the summary.

Result

Measured against react-markdown@10.1.0. 39 comparisons across 11 props, and 39 produce identical markup.

StatusCount
Compatible11
Intentionally different1
Not supported yet1
Compatible with a documented change1

The 11 compatible props

PropWhat was compared
childrenHeadings, emphasis, lists, code, quotes, links, hard breaks, empty string
componentsElement-name keys map to components, and the same props arrive
remarkPluginsTree transforms and dialect plugins, including remark-gfm
rehypePluginshast plugins running after mdast to hast and before the content policy
remarkRehypeOptionsFootnote label, back-label and clobber prefix
allowedElementsOnly listed tags survive, and children of a removed element go with it
disallowedElementsListed tags are removed and everything else stays
allowElementThe predicate receives element, index and parent
unwrapDisallowedA removed element is replaced by its children
urlTransformRuns on every URL attribute, with the same default algorithm
skipHtmlSame meaning and the same false default

Both packages default skipHtml to false, so raw HTML renders as visible escaped text. Neither executes raw HTML without an explicit rehype-raw opt-in.

The rows that differ

className is intentionally different

react-markdown 10 throws on a className prop. This renderer has no className prop either, and TypeScript rejects it, but at runtime it is ignored rather than thrown.

JavaScript code that still passes className loses the wrapper silently instead of failing loudly. Use components or the opt-in classNames hooks described in styling.

MarkdownAsync and MarkdownHooks are not supported yet

react-markdown 10 exports both for plugins that need async work. This renderer is synchronous only. There is no equivalent export, and an async remark or rehype plugin will not run.

remarkPlugins on a precompiled document has a documented change

react-markdown only ever takes a string, so every plugin runs at parse time. This renderer also accepts an already-compiled MarkdownDocument.

A plugin that changes the dialect, such as remark-gfm, cannot apply to text that was already parsed. Tree-transforming plugins still run. Compile with the same extensions you render with, or pass the string.

// The plugin cannot add table syntax to text that is already a tree.
const document = compileMarkdown(source, { preset: gfmPreset })
<Markdown document={document} />

What is not covered

Everything outside the prop surface has no react-markdown equivalent, so it is not a compatibility question. That includes bundle size, the MarkdownDocument input, presets, extensions, the editor and the template engine.

Migrating

The migration guide walks through the codemod and the manual steps. The claims on this page are generated from tests, so check the matrix for your pinned version before you plan a migration.