npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mdmaid

v0.1.12

Published

Markdown + Mermaid made simple - A powerful markdown renderer with first-class Mermaid diagram support

Readme

mdmaid

Markdown + Mermaid rendering library

A preconfigured markdown renderer with Mermaid diagram support. Built for personal use across mdmaid.nvim and oles.md blog.

What it does today

  • Markdown → HTML via remark (GFM, slug, autolink-headings)
  • Mermaid code blocks → <div class="mermaid"> (client-side rendering)
  • SSR module - Server-side mermaid → SVG rendering with font embedding
  • Bundled font - Departure Mono included for consistent diagram rendering
  • CLI for quick rendering and dev server with live reload
  • Dev server extras: ToC sidebar, image zoom, print styles

Installation

npm install mdmaid

# For SSR (optional)
npm install puppeteer

Usage

Markdown Rendering

import { renderMarkdown } from 'mdmaid';

const html = await renderMarkdown(`
# Hello

\`\`\`mermaid
graph TD
    A[Start] --> B[End]
\`\`\`
`);
// Returns HTML with <div class="mermaid">...</div>
// Mermaid renders client-side

Server-Side Mermaid Rendering

Render mermaid diagrams to SVG on the server (requires puppeteer):

import { renderMermaidToSVG, closeBrowser, DEFAULT_FONT } from 'mdmaid/ssr';

// Use the bundled Departure Mono font
const svg = await renderMermaidToSVG('graph TD; A-->B;', {
  fonts: [DEFAULT_FONT],
  embedFonts: true,
});

await closeBrowser();

Or with custom fonts:

const svg = await renderMermaidToSVG('graph TD; A-->B;', {
  fonts: [
    // Local font file
    { family: 'My Font', path: './fonts/MyFont.woff2' },
    // Or external URL
    { family: 'Fira Code', url: 'https://example.com/FiraCode.woff2' },
  ],
  mermaid: { theme: 'default' },
  embedFonts: true,
});

Batch Rendering

More efficient for multiple diagrams:

import { renderMermaidBatch, closeBrowser } from 'mdmaid/ssr';

const svgs = await renderMermaidBatch(
  ['graph TD; A-->B;', 'sequenceDiagram; A->>B: Hi'],
  { embedFonts: true }
);

await closeBrowser();

Dark Mode Options

Option 1: CSS Invert (simple, used in oles.md)

Render once in light theme, use CSS to invert in dark mode:

.dark .mermaid img { filter: invert(1); }
/* or with Tailwind: className="dark:invert" */

Option 2: Dual Theme Rendering

Render separate versions for light and dark:

import { renderMermaidWithThemes, closeBrowser } from 'mdmaid/ssr';

const results = await renderMermaidWithThemes(
  'graph TD; A-->B;',
  ['default', 'dark'],  // themes to render
  { embedFonts: true }
);

// results[0] = { theme: 'default', svg: '<svg>...</svg>' }
// results[1] = { theme: 'dark', svg: '<svg>...</svg>' }

await closeBrowser();

CLI

# Render markdown to stdout
mdmaid README.md

# Render to file
mdmaid README.md -o output.html

# Dev server with live reload
mdmaid serve docs/index.md --watch --port 3333

# Batch render mermaid diagrams to SVG (requires puppeteer)
mdmaid render-diagrams _posts/ --out public/diagrams/ --manifest

API Reference

Core

renderMarkdown(markdown, options?)

const html = await renderMarkdown(content, {
  sanitize: false,  // HTML sanitization (default: false)
});

extractMermaidBlocks(markdown)

const blocks = extractMermaidBlocks(content);
// ['graph TD\n  A --> B', 'sequenceDiagram\n  ...']

SSR (mdmaid/ssr)

renderMermaidToSVG(code, options?)

Render single diagram to SVG.

renderMermaidBatch(codes, options?)

Render multiple diagrams efficiently (reuses browser).

renderMermaidWithThemes(code, themes?, options?)

Render diagram with multiple themes for light/dark mode.

renderMermaidBatchWithThemes(codes, themes?, options?)

Batch render with multiple themes.

closeBrowser()

Clean up puppeteer browser when done.

DEFAULT_FONT

Bundled Departure Mono font config. Use for consistent rendering:

import { DEFAULT_FONT } from 'mdmaid/ssr';
// { family: 'Departure Mono', path: '...', weight: 400, style: 'normal' }

Options

interface MermaidSSROptions {
  fonts?: FontConfig[];       // Fonts to use
  mermaid?: MermaidConfig;    // Mermaid configuration
  puppeteer?: PuppeteerConfig; // Puppeteer launch options
  embedFonts?: boolean;       // Embed fonts in SVG (default: false)
}

interface FontConfig {
  family: string;             // Font family name
  path?: string;              // Local file path (.woff2, .woff, .ttf)
  url?: string;               // External URL (CDN, direct font file)
  weight?: number;            // Font weight (default: 400)
  style?: string;             // Font style (default: 'normal')
}

Dev Server Features

  • Live reload on file changes
  • Auto-generated Table of Contents sidebar
  • Image magnifier (hold Z or click to zoom)
  • Print-friendly styles

Ideas Still Being Explored

Layout & Responsiveness

The pain:

  • Diagrams clip on mobile / narrow containers
  • No text wrapping in nodes (manual <br> hell)
  • Large diagrams become unreadable thumbnails

Potential approach:

  • Smart container-aware rendering
  • Pan/zoom for large diagrams
  • Viewport-based sizing hints

Validation & Error Handling

The pain:

  • Works in VS Code, breaks on GitHub (version mismatch)
  • Single typo → ugly error block on published site
  • No graceful fallback

Potential approach:

  • Pre-flight syntax validation
  • Graceful error states
  • Version compatibility checking

Accessibility

The pain: SVG diagrams are invisible to screen readers. accTitle and accDescr exist but nobody knows about them.

Potential approach:

  • Auto-generate descriptions from diagram structure
  • Enforce/encourage accessibility metadata
  • Semantic alternatives for simple diagrams

Puppeteer-free SSR

Current SSR requires puppeteer. Exploring:

  • jsdom-based rendering
  • WASM-based mermaid

The Honest Truth

This library exists because I needed shared rendering logic between my Neovim plugin and my blog.

The SSR module is extracted from oles.md and works. The "ideas" above are things that would be nice to have but aren't priorities.

Development

npm install
npm run build
npm run dev  # watch mode

# Test locally
node bin/mdmaid.js test.md -o test-output.html
node bin/mdmaid.js serve test.md --watch

License

MIT