Skip to content

Latest commit

 

History

History
181 lines (118 loc) · 7.06 KB

File metadata and controls

181 lines (118 loc) · 7.06 KB

react-markdown 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, and the same default URL policy. Where behaviour differs, the difference is listed below rather than smoothed over.

Measured against react-markdown@10.1.0 by rendering identical input through both packages and comparing normalized HTML. 39 comparisons across 11 props; 39 produce identical markup.

Matrix

Prop Status Cases matching Evidence
children compatible 4/4 tests/compatibility.test.tsx › children
components compatible 4/4 tests/compatibility.test.tsx › components
remarkPlugins compatible 4/4 tests/compatibility.test.tsx › remarkPlugins
rehypePlugins compatible 3/3 tests/compatibility.test.tsx › rehypePlugins
remarkRehypeOptions compatible 3/3 tests/compatibility.test.tsx › remarkRehypeOptions
allowedElements compatible 4/4 tests/compatibility.test.tsx › allowedElements
disallowedElements compatible 3/3 tests/compatibility.test.tsx › disallowedElements
allowElement compatible 3/3 tests/compatibility.test.tsx › allowElement
unwrapDisallowed compatible 3/3 tests/compatibility.test.tsx › unwrapDisallowed
urlTransform compatible 4/4 tests/compatibility.test.tsx › urlTransform
skipHtml compatible 4/4 tests/compatibility.test.tsx › skipHtml
className intentionally different — tests/compatibility.test.tsx › beyond the prop surface (react-markdown throws / this renderer ignores)
MarkdownAsync, MarkdownHooks not supported yet — tests/compatibility.test.tsx › beyond the prop surface (exports are absent from @react-markdown-kit/renderer)
remarkPlugins on a precompiled document compatible with documented change — tests/compatibility.test.tsx › beyond the prop surface (remark-gfm produces a table from a string but not from a document compiled without it)

Counts

  • compatible: 11
  • intentionally different: 1
  • not supported yet: 1
  • compatible with documented change: 1

Notes

children — compatible

A Markdown string as children renders the same tree.

Inputs compared:

  • identical — headings and emphasis
  • identical — lists, code and quotes
  • identical — links, reference links and hard breaks
  • identical — empty string

components — compatible

Element-name keys map to React components; the same props arrive.

Inputs compared:

  • identical — heading override
  • identical — anchor override receives href
  • identical — paragraph override
  • identical — several overrides at once

remarkPlugins — compatible

Both tree-transforming plugins and dialect plugins (remark-gfm) behave the same.

Inputs compared:

  • identical — remark-gfm tables
  • identical — remark-gfm task list and strikethrough
  • identical — remark-gfm autolinks and footnotes
  • identical — custom mdast transform

rehypePlugins — compatible

hast plugins run after mdast->hast and before the content policy.

Inputs compared:

  • identical — attribute stamping
  • identical — class injection
  • identical — plugin plus components

remarkRehypeOptions — compatible

Options reach remark-rehype, including footnote labels and clobber prefixes.

Inputs compared:

  • identical — footnote label
  • identical — clobber prefix
  • identical — footnote back-label

allowedElements — compatible

Only the listed tag names survive; children of a removed element go with it.

Inputs compared:

  • identical — paragraphs only
  • identical — headings and text
  • identical — nothing allowed
  • identical — inline allowed inside removed block

disallowedElements — compatible

The listed tag names are removed, everything else stays.

Inputs compared:

  • identical — drop headings
  • identical — drop emphasis
  • identical — drop lists

allowElement — compatible

The predicate receives (element, index, parent) and removing is the same decision.

Inputs compared:

  • identical — reject by tag name
  • identical — reject by index
  • identical — reject by parent tag

unwrapDisallowed — compatible

A removed element is replaced by its children rather than dropped.

Inputs compared:

  • identical — unwrap emphasis
  • identical — unwrap heading
  • identical — unwrap via allowElement

urlTransform — compatible

Runs on every URL attribute; returning an empty string blanks it. The default algorithm is the same one react-markdown ships.

Inputs compared:

  • identical — rewrite href
  • identical — blank everything
  • identical — default blocks javascript:
  • identical — default keeps mailto:

skipHtml — compatible

Same meaning and the same default. Both packages default to false, rendering raw HTML as visible escaped text rather than executing it; skipHtml: true removes it in both. An earlier revision of this renderer defaulted to true, which was the only behavioural difference on this prop and amounted to silently dropping content the author wrote. Neither package executes raw HTML without an explicit rehype-raw opt-in.

Inputs compared:

  • identical — default (unset)
  • identical — skipHtml true
  • identical — skipHtml false
  • identical — dangerous html, default

className — intentionally different

react-markdown 10 throws Unexpected className prop, remove it. This renderer has no className prop either, but ignores it at runtime rather than throwing; TypeScript rejects it. Use components or the opt-in classNames hooks. Migrating JavaScript code that still passes className will lose the wrapper silently instead of failing loudly.

Evidence: react-markdown throws / this renderer ignores.

MarkdownAsync, MarkdownHooks — not supported yet

react-markdown 10 exports MarkdownAsync and MarkdownHooks for plugins that need async work. This renderer is synchronous only; there is no equivalent export, and an async remark/rehype plugin will not work.

Evidence: exports are absent from @react-markdown-kit/renderer.

remarkPlugins on a precompiled document — compatible with documented change

react-markdown only ever takes a string, so every plugin runs at parse time. This renderer also accepts an already-compiled MarkdownDocument, and a plugin that changes the dialect (remark-gfm and anything else registering micromark extensions) cannot apply to text that has already been parsed. Tree-transforming plugins still run. Compile with the same extensions you render with, or pass the string.

Evidence: remark-gfm produces a table from a string but not from a document compiled without it.

What is not covered here

Everything outside the prop surface — bundle size, the MarkdownDocument input, presets, extensions, the editor and variables packages — has no react-markdown equivalent and is not a compatibility question.