mdx-render
Version:
A modern, SSR-friendly React Markdown renderer that preserves the MDAST tree for reuse (e.g., mdast2docx), supports full JSX children, unified plugins, and component overrides.
243 lines (166 loc) โข 7.92 kB
Markdown
# MDX Renderer [`@m2d/react-markdown`] <img src="https://raw.githubusercontent.com/mayank1513/mayank1513/main/popper.png" style="height: 40px"/>
[](https://github.com/md2docx/react-markdown/actions/workflows/test.yml)
[](https://codeclimate.com/github/md2docx/react-markdown/maintainability)
[](https://codecov.io/gh/md2docx/react-markdown)
[](https://www.npmjs.com/package/@m2d/react-markdown)
[](https://www.npmjs.com/package/@m2d/react-markdown)

> โจ 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`](https://github.com/md2docx/mdast2docx)**
Compared to `react-markdown`, this library offers:
| Feature | `@m2d/react-markdown` โ
| `react-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
```bash
pnpm add @m2d/react-markdown
```
**_or_**
```bash
npm install @m2d/react-markdown
```
**_or_**
```bash
yarn add @m2d/react-markdown
```
## ๐ Server vs Client
By default, this package is SSR-safe and has **no client-specific hooks**.
### โ
Server (default):
```tsx
import { Md } from "@m2d/react-markdown";
```
### ๐ Client (for dynamic reactivity/memoization):
```tsx
import { Md } from "@m2d/react-markdown/client";
```
This version supports client-side behavior with memoization and dynamic JSX rendering.
## โก Example: Rendering + Exporting DOCX
```tsx
import { Md } from "@m2d/react-markdown/client";
import { toDocx } from "mdast2docx";
import { useRef } from "react";
const astRef = useRef([]);
export default function Page() {
return (
<>
<Md astRef={astRef}>{`# Hello\n\nThis is **Markdown**.`}</Md>
<button
onClick={() => {
const doc = 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**:
```tsx
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
```tsx
import { Md } from "@m2d/react-markdown";
import { Unwrap, Omit } from "@m2d/react-markdown/server";
<Md
components={{
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:
```tsx
<Md remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeSlug, rehypeAutolinkHeadings]}>
{markdown}
</Md>
```
## ๐ Accessing MDAST + HAST
```ts
type astRef = {
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 โ](./benchmark.md)
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 โ](https://github.com/md2docx/react-markdown/discussions/3)
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
- [x] ๐งช Structural test utilities
- [x] ๐งโ๐ซ Next.js + DOCX example
## ๐ Related Projects
- [`mdast2docx`](https://github.com/md2docx/mdast2docx) โ Convert MDAST โ `.docx`
- [`unified`](https://unifiedjs.com/) โ Syntax tree ecosystem
- [`react-markdown`](https://github.com/remarkjs/react-markdown) โ Popular alternative (less customizable)
## ๐ Acknowledgements
We are deeply grateful to the open-source community whose work made this project possible.
- ๐ฑ **[react-markdown](https://github.com/remarkjs/react-markdown)** โ For pioneering a React-based Markdown renderer. This library builds on its ideas while extending flexibility and SSR-readiness.
- ๐ **[unified](https://github.com/unifiedjs/unified)** โ The brilliant engine powering our markdown-to-AST transformations.
- โจ **[remark](https://github.com/remarkjs/remark)** and **[rehype](https://github.com/rehypejs/rehype)** โ For their modular ecosystems that make parsing and rendering delightful.
- ๐งพ **[mdast2docx](https://github.com/md2docx/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](https://www.mozilla.org/en-US/MPL/2.0/).
> ๐ก Want to support this project? [Sponsor](https://github.com/sponsors/mayank1513) or check out our [courses](https://mayank-chaudhari.vercel.app/courses)!
<p align="center" style="text-align:center">Built with โค๏ธ by <a href="https://mayank-chaudhari.vercel.app" target="_blank">Mayank Kumar Chaudhari</a></p>