rehype-mermaid

A rehype plugin that renders Mermaid diagrams into inline SVG, PNG, or client-side markup inside a unified/remark/rehype pipeline.

Library
npm
v3.0.0
193stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
36/100Needs Attention
Development Activity8
Maintenance20
Community44
Maturity52
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
78/100Good
Architecture85
Code Quality88
Innovation82
Learning Curve55

rehype-mermaid is a rehype plugin that finds <pre class="mermaid"> and <code class="language-mermaid"> elements in a HAST tree and replaces them with a rendered version of the diagram. It slots directly into the unified/remark/rehype ecosystem, so it works out of the box with remark-rehype output, react-markdown, and MDX compilation pipelines without any extra glue code.

It supports four rendering strategies: inline SVG (the default, embedding the diagram markup directly in the document), an <img> tag with a base64 PNG or SVG data URI, or a pre-mermaid passthrough strategy that leaves the raw diagram for Mermaid to render client-side. Outside the browser it uses Playwright (via the companion mermaid-isomorphic package) as an optional peer dependency to headlessly render diagrams during a build step, so consumers only pay the Playwright cost when they actually need server/build-time rendering.

Options cover responsive dark-mode output via a <picture> element, a custom errorFallback handler for diagrams that fail to parse, and a colorScheme override that otherwise falls back to detecting a document’s <meta name="color-scheme"> tag. The plugin batches all diagrams in a file into a single render call, which keeps large documents with many diagrams from paying a per-diagram browser round trip.

What You Get

  • A single default-exported unified/rehype plugin (rehypeMermaid) that drops into an existing unified().use() chain with no other wiring
  • Four rendering strategies (inline-svg, img-png, img-svg, pre-mermaid) covering static builds, email/RSS-safe images, and client-rendered diagrams
  • Optional responsive dark-mode output via a <picture> element with a light/dark source pair
  • A pluggable errorFallback hook so a broken diagram can render a fallback node instead of failing the whole build
  • Automatic color-scheme detection from a document’s <meta name="color-scheme"> tag when no explicit colorScheme option is given
  • Batched rendering of all diagrams in a file through a single Playwright-backed render pass via the companion mermaid-isomorphic package

Common Use Cases

  • Rendering Mermaid diagrams to static SVG at build time for a documentation site built with MDX or a markdown static site generator
  • Adding Mermaid support to a react-markdown powered page via MarkdownAsync/MarkdownHooks, without shipping the full Mermaid client bundle
  • Generating PNG diagram images for contexts that can’t execute JavaScript or inline SVG, such as emails or RSS feeds
  • Using the pre-mermaid strategy to defer diagram rendering to the browser via the client-side mermaid package when a site already loads it

Under The Hood

Architecture The entire plugin lives in one file, src/rehype-mermaid.ts. rehypeMermaid(options) validates the strategy option, constructs a renderer via mermaid-isomorphic’s createMermaidRenderer, and returns a unified transformer (ast, file). That transformer walks the HAST tree with unist-util-visit-parents, using isMermaidElement to match <pre class="mermaid"> and <code class="language-mermaid"> nodes (carefully skipping <code> elements that have non-whitespace sibling content inside their wrapping <pre>), and collects each match as a CodeInstance holding its diagram text and inclusive ancestor chain. For the synchronous pre-mermaid strategy, matched nodes are swapped in place immediately; for the other three strategies, all collected diagrams are rendered together in one batched call (plus a second batched call for dark-mode variants when dark is set), and Promise.all resolves both passes before nodes are replaced with either an inline SVG fragment (fromHtmlIsomorphic) or an <img>/<picture> element (toImageElement). Error handling is centralized in handleError, which defers to a caller-supplied errorFallback or throws a fatal VFileMessage with a stable ruleId. The clean separation between tree-matching, batched rendering, and result-to-HAST serialization means a change to the underlying Mermaid renderer would only touch the middle layer.

Tech Stack Written in strict-mode TypeScript targeting ES2022 with Node16 module resolution and verbatimModuleSyntax, built as an ESM-only composite TypeScript project via tsc --build. It sits squarely in the unified/hast ecosystem: unified for the plugin contract, hast-util-from-html-isomorphic and hast-util-to-text for HAST parsing/serialization, unist-util-visit-parents for tree traversal, and vfile/vfile-message for diagnostics. Actual diagram rendering is delegated to the same author’s mermaid-isomorphic package, which can render in a real browser or headlessly through an optional playwright peer dependency — so consumers who only need client-side rendering never have to install Playwright. mini-svg-data-uri and space-separated-tokens handle small serialization/parsing chores.

Code Quality Testing uses Node’s built-in node:test runner together with snapshot-fixtures, which drives 14 fixture directories (covering plain code blocks, pre/code element combinations, sibling text and element edge cases, and all four color-scheme detection permutations) through each rendering strategy and diffs the Prettier-formatted output against committed snapshots; PNG-strategy fixtures are explicitly marked ignore since PNG output isn’t pixel-perfect across platforms, while SVG and pre-mermaid fixtures are asserted exactly. c8 measures coverage. CI runs ESLint, Prettier, and remark --frail lint passes plus the test suite across a Node 18/20/22/24 matrix. No untyped code paths and no swallowed errors were found — failures either hit the caller’s errorFallback or become fatal VFileMessages.

API Design The public surface is a single default export plus one options interface, matching the exact unified().use(plugin, options) convention every rehype/remark plugin author already knows — there is no bespoke setup step. Every option (strategy, dark, colorScheme, errorFallback, prefix, mermaidConfig, launchOptions) is documented with TSDoc directly above its declaration, and the README walks through remark, React, and MDX integration with copy-pasteable examples for each. The only friction point is implicit: consumers doing non-browser rendering must separately install and configure Playwright, a detail covered in the README’s installation section rather than surfaced by the API itself.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search