Skip to content

md2docx/react-markdown

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

MDX Renderer [@m2d/react-markdown]

test Maintainability codecov Version Downloads npm 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-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

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";

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:

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";

<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:

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

πŸ“‚ Accessing MDAST + HAST

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 β†’

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

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •