Skip to content

MDX Renderer [@m2d/react-markdown]

testMaintainabilitycodecovVersionDownloadsnpm bundle size

✨ A modern, SSR-compatible Markdown renderer for React with full MDAST/HAST access — built for customization, performance, and document generation - docx/pdf.


🔥 Why @m2d/react-markdown?

@m2d/react-markdown goes beyond traditional React Markdown libraries by focusing on:

  • Server-side rendering (SSR) without hooks
  • Full JSX children support (not just strings)
  • Access to raw MDAST & HAST trees
  • Drop-in plugin support via Unified (remark, rehype, etc.)
  • Custom component overrides per tag
  • Integration with tools like mdast2docx

Compared to react-markdown, this library offers:

Feature@m2d/react-markdownreact-markdown
Full JSX support (not just strings)
SSR-safe (no hooks)
Client Side component with memoization
MDAST + HAST access via astRef
Component-level overrides
Unified plugin support
Tiny bundle (minzipped)~35 kB~45 kB
Built-in DOCX-friendly AST output

📦 Installation

pnpm add @m2d/react-markdown

or

npm install @m2d/react-markdown

or

yarn add @m2d/react-markdown

🚀 Server vs Client

By default, this package is SSR-safe and has no client-specific hooks.

✅ Server (default):

import{Md}from"@m2d/react-markdown";

🔁 Client (for dynamic reactivity/memoization):

import{Md}from"@m2d/react-markdown/client";

This version supports client-side behavior with memoization and dynamic JSX rendering.


⚡ Example: Rendering + Exporting DOCX

import{Md}from"@m2d/react-markdown/client";import{toDocx}from"mdast2docx";import{useRef}from"react";constastRef=useRef([]);exportdefaultfunctionPage(){return(<><MdastRef={astRef}>{`# Hello\n\nThis is **Markdown**.`}</Md><buttononClick={()=>{constdoc=toDocx(astRef.current[0].mdast);// Save or download doc}}>
Export to DOCX
</button></>);}

Note for Server Component use you can replace useRef with custom ref object const astRef = {current: undefined} as AstRef


🧠 JSX-Aware Parsing

Unlike most markdown renderers, @m2d/react-markdown supports arbitrary JSX as children:

import{Mdx}from"@m2d/react-markdown/server";// ...<Mdx><article>{"# Markdown Heading\n\nSome **rich** content."}</article></Mdx>;

astRef.current is an array — one per Markdown string — each with { mdast, hast }. The default <Md> export accepts only string children for better optimization.


🎨 Component Overrides

import{Md}from"@m2d/react-markdown";import{Unwrap,Omit}from"@m2d/react-markdown/server";<Mdcomponents={{em: Unwrap,blockquote: Omit,code: props=><CodeBlock{...props}/>,}}>{`*em is unwrapped*\n\n> blockquote is removed`}</Md>;

Use the built-in helpers:

  • Unwrap – renders only children
  • Omit – removes element and content entirely
  • CodeBlock - it is your custom component

🔌 Plugin Support (Unified)

Use any remark or rehype plugin:

<MdremarkPlugins={[remarkGfm]}rehypePlugins={[rehypeSlug,rehypeAutolinkHeadings]}>{markdown}</Md>

📂 Accessing MDAST + HAST

typeastRef={current: {mdast: Root;hast: HastRoot}[];};

Useful for:

  • 📄 DOCX export (mdast2docx)
  • 🧪 AST testing or analysis
  • 🛠️ Custom tree manipulation

📊 Performance

TL;DR:@m2d/react-markdown performs competitively with react-markdown, especially on medium and large documents.

👉 See full benchmarks →

Benchmarks include:

  • Multiple markdown fixture types (short, long, complex, deeply nested)
  • Plugin configurations like remark-gfm, remark-math, rehype-raw
  • Visual comparisons using interactive Mermaid xychart-beta charts
  • Ops/sec, ±%, and future memory profiling

💬 Upcoming Changes – Seeking Feedback

We're proposing a major change to the internal astRef structure to better support MDX-style custom components and rendering flexibility:

👉 Join the discussion →

Key goals:

  • Allow <Md> to embed child components like JSX/MDX
  • Simplify recursive rendering model
  • Improve performance and reduce abstraction overhead

🧭 Roadmap

  • 🔄 Merge JSX + <Md> segments into unified AST
  • 🧪 Structural test utilities
  • 🧑‍🏫 Next.js + DOCX example

🌍 Related Projects


🙏 Acknowledgements

We are deeply grateful to the open-source community whose work made this project possible.

  • 🌱 react-markdown – For pioneering a React-based Markdown renderer. This library builds on its ideas while extending flexibility and SSR-readiness.
  • 🛠 unified – The brilliant engine powering our markdown-to-AST transformations.
  • remark and rehype – For their modular ecosystems that make parsing and rendering delightful.
  • 🧾 mdast2docx – Our sister project that inspired the MDAST-first architecture of this library.

💖 To the maintainers, contributors, and communities behind these projects — thank you for your generosity, vision, and dedication to making the web better for everyone.


📘 License

Licensed under the MPL-2.0.

💡 Want to support this project? Sponsor or check out our courses!


Built with ❤️ by Mayank Kumar Chaudhari

About

SSR-ready React Markdown renderer with MDAST reuse, JSX support, and unified plugin pipeline.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

13 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages