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

@mermanjs/node

v0.10.0

Published

Experimental native Node.js and static-site rendering bindings for Merman.

Readme

@mermanjs/node

Native Mermaid-compatible SVG rendering for Node.js 22+ and static-site build pipelines, without Chromium, a browser-WASM fallback, or a postinstall binary download.

Version 0.10.0 targets Mermaid 12.3.0 and uses Node binding API 1, Options JSON schema 3, and theme execution evidence schema 2. Keep the loader and native platform package at the same exact version and source revision. Check the host installation guide for verified versions and channel availability, and the stable upgrade guide for migration. The package remains experimental.

Version 0.10.0-alpha.1 retains Mermaid 12.2.0 and theme execution evidence schema 1; Node binding API 1 and Options JSON schema 3 are unchanged. Upgrade the loader and platform package together and update evidence consumers for the render-evidence changes.

Quick start

Install the loader package, not a platform package:

npm install --save-exact @mermanjs/[email protected]
import { createNodeEngine } from "@mermanjs/node";

const engine = await createNodeEngine();

try {
  const svg = await engine.renderSvg("flowchart TD\nA --> B");
  console.log(svg);
} finally {
  await engine.dispose();
}

Create an engine once, reuse it for related work, and dispose it during teardown.

Compiled themes

The catalog groups 11 designs with 14 concrete presets, including paper-cut, carbon-copy, and pop-art. Editor, Gruvbox, and Ayu provide both Light and Dark; other designs declare their own modes.

Select a preset through the top-level theme group in Options JSON schema 3. Discover preset IDs through the initialized engine's theme catalog:

const catalog = JSON.parse(engine.metadataJson("theme-catalog"));
const themedSvg = await engine.renderSvg("flowchart LR\nA --> B", {
  optionsJson: JSON.stringify({ version: 3, theme: { preset: "editor", appearance: "dark" } }),
});

Each catalog preset represents one design. supported_appearances, default_appearance, and appearances describe its modes; each mode contains the exact concrete_preset_id, swatches, family scope, and application notes. Catalog available admits every appearance under the current resource policy. All built-in presets remain alpha with empty appearance-specific qualified_cells; availability and unknown profile/admission IDs never establish portable output. Flowchart glow and shadow effects support documented shapes in Classic and Neo; other families retain their own look and output restrictions. SVG fonts resolve on the viewing host; exported recipes do not embed them.

The async authoring helpers use the same queue, cancellation, and JSON operations as rendering:

const recipe = await engine.exportThemePreset("editor");
const editableJson = JSON.stringify(recipe, null, 2);
const importedRecipe = JSON.parse(editableJson);
const inspection = await engine.materializeTheme({
  schema_version: 1, action: "inspect", recipe: importedRecipe,
});
const snapshot = await engine.materializeTheme({
  schema_version: 1, action: "materialize", recipe: importedRecipe, appearance: "dark",
});
const svg = await engine.renderSvg("flowchart LR\nA[Review] --> B[Publish]", {
  optionsJson: JSON.stringify({ theme: { recipe: importedRecipe, appearance: "dark" } }),
});

Save editableJson, edit its design values, and reload the edited JSON in place of the round-trip string above. Keep schema_version, kind, and the complete recipe for customization and exchange. Shared values live in recipe.design; local exceptions live in recipe.design.appearances. snapshot.spec is a concrete snapshot, while inspect reports every declared mode and reference provenance. Omitted appearance uses the declared default; an explicit unsupported value fails. Resolve Follow-app/editor in the host before submitting light or dark. A supplied theme replaces the complete previous selection; null clears it.

materializeTheme() also accepts raw design JSON or raw request text, preserving duplicate-key admission in Rust. describeThemeSupport() queries renderer mechanisms. Generic and synchronous callers can continue using executeOperation() or executeOperationSync() with the same three operation IDs; no additional native entry point is required. See the theme guide for authoring and portability, and the current Node changelog for upgrade actions.

SVG output pipelines

renderSvg() and renderSvgSync() use the parity pipeline by default. This preserves the Mermaid-compatible SVG structure for trusted input and parity-sensitive consumers. parity is not a browser DOM-admission or sanitization check.

For a resvg/usvg consumer that cannot display HTML labels, select resvg-safe explicitly:

const options = {
  optionsJson: JSON.stringify({ svg: { pipeline: "resvg-safe" } }),
};
const svg = await engine.renderSvg(source, options);

The supported pipeline values are parity, readable, and resvg-safe. readable is an advanced text overlay for consumers that ignore HTML labels; browsers can display both copies and show overlapping text. Use parity for browser display. resvg-safe also removes unsupported styles, so it is not a lossless replacement for readable. HTML embedding still requires a host-owned admission policy; selecting a pipeline alone does not establish browser DOM safety.

The resvg-safe pipeline removes browser-only content such as active elements and foreignObject labels. It does not provide browser Document or owner-document admission APIs; use @mermanjs/web* for browser DOM mounting.

Supported hosts

  • macOS arm64 and x64
  • Linux arm64 and x64 with glibc or musl
  • Windows x64 with MSVC
  • Node.js >=22

The root loader selects one matching exact-version @mermanjs/node-<platform> optional dependency. Do not install platform packages directly. The loader contains no native or WASM binary and never downloads one during installation or runtime.

If the native addon is installed but the host dynamic loader rejects it (for example because the glibc baseline is too new), construction throws MermanNativeLoadError with the target package name and an explicit suggestion to use @mermanjs/node-wasm. It does not silently switch transports.

Capability boundary

The package provides deterministic static SVG with math, Cytoscape and ELK layouts, metadata, layout plans, runtime-catalog inspection, and generic admitted operations. GNU Linux targets retain glibc 2.31 as their compatibility floor. Binary export, analysis, ASCII, text-measurement callbacks, browser fallback, and runtime downloads are outside this package surface. Requests for unavailable optional capabilities return Merman's typed missing-capability error.

Render formulas with the ordinary SVG methods:

const formula = await engine.renderSvg('flowchart LR\nA["$$x^2$$"]');

The runtime catalog advertises math for both the native and explicit Node-WASM products. The default interactive resource profile admits formulas; an explicitly constrained profile rejects them even when math is compiled. For untrusted input, enforce host execution, memory, and concurrency limits alongside the selected resource profile.

Lifecycle and concurrency

The Promise-based API uses a bounded queue. An AbortSignal cancels queued work immediately and requests cooperative cancellation after Rust work starts; started work stops at the next renderer or transport-admission checkpoint and reports Merman's typed cancellation details. Per-operation timeoutMs values use a monotonic Rust deadline and must be integers from 0 through 4,294,967,295. dispose() waits for active work to settle and rejects new work once teardown begins.

Use renderSvgSync() only for an explicitly synchronous static-site build path. It refuses to run while asynchronous operations are active or queued.

Loaded icon packs

Load Iconify pack JSON in the host and pass its text as a constructor service:

import { readFile } from "node:fs/promises";
import { createNodeEngine } from "@mermanjs/node";

const json = await readFile("./icons.json", "utf8");
const engine = await createNodeEngine({
  iconPacks: [{ json, registrationName: "app" }],
});
try {
  const svg = await engine.renderSvg('flowchart TD\nA@{ icon: "app:rocket", label: "Launch" }');
  console.log(svg);
} finally {
  await engine.dispose();
}

The example assumes the pack contains rocket. json must be the loaded JSON string. Omit registrationName to use the pack's prefix. A registered icon takes precedence over a matching built-in icon in that engine. Packs are admitted once into immutable engine-local state; changing the original array or rendering through another engine does not change it. Per-request options preserve the installed registry.

iconPacks belongs to CreateNodeEngineOptions, separately from bindingOptions. An omitted value or [] retains ordinary rendering. The constructor performs no network or filesystem access. The fixed pack/content limits advertised by the icon-registry constructor contract apply across native and Node-WASM. Content failures retain MermanOperationError.iconRegistryDetails, and resource failures also retain resourceDetails. A failed constructor publishes no engine. Dispose engines when their build or request scope ends.

See the Node.js package guide for source-checkout development, package verification, and release design.