The Problem
Developers using Mermaid often need diagram output that works in terminals, CI logs, or environments without a DOM. The upstream renderer is SVG‑only, heavy, and hard‑to‑theme, forcing teams to write custom post‑processing or maintain separate rendering pipelines.
What This Does
beautiful-mermaid supplies a pure‑TypeScript engine that converts Mermaid source into either SVG (via src/renderer.ts and src/theme.ts) or ASCII/Unicode art (via src/ascii/index.ts, src/ascii/draw.ts, src/ascii/canvas.ts). The public API lives in src/index.ts and re‑exports the two entry functions renderMermaid and renderMermaidAscii. Themes are defined in src/theme.ts and applied without touching the DOM, leveraging the shiki highlighter for colour palettes.
How It Is Wired
Execution begins at src/index.ts:
renderMermaid→ parses the diagram withsrc/parser.ts, builds a layout throughsrc/layout.ts(which delegates tosrc/dagre-adapter.tsfor graph positioning), then renders SVG withsrc/renderer.ts.renderMermaidAscii→ callssrc/ascii/index.ts, which creates anAsciiCanvas(src/ascii/canvas.ts), runs the ASCII draw routine (src/ascii/draw.ts), and finally produces a string.
Key dependencies:
src/layout.tsimports the most modules (15 outgoing edges) and is the primary stability hotspot (instability 0.71).src/ascii/draw.tsparticipates in a circular import withsrc/ascii/grid.ts; both pull types from each other, inflating the blast radius for any change to grid logic.- Theme handling (
src/theme.ts) and style constants (src/styles.ts) are pure data modules with zero outgoing imports, making them safe to modify.
The import graph shows 51 internal modules and 112 edges; only two modules are involved in cycles, limiting the risk of widespread ripple effects, but the cycle in the ASCII path adds cognitive load.
How To Use It
# Clone the repo
git clone https://github.com/moses-y/beautiful-mermaid
cd beautiful-mermaid
# Install dependencies (npm is inferred from package.json)
npm install
# Build the library (tsup config present)
npm run build # runs tsup as defined in package.json scripts
Render SVG
import { renderMermaid } from './src/index.js';
const svg = await renderMermaid(`
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Action]
B -->|No| D[End]
`);
console.log(svg);
Render ASCII
import { renderMermaidAscii } from './src/index.js';
const ascii = renderMermaidAscii('graph LR; A --> B --> C');
console.log(ascii);
The library also ships a browser bundle (dist/beautiful-mermaid.browser.global.js) referenced in the README, but no additional configuration files are required.
Real‑World Use
A CI pipeline can embed diagram generation in markdown reports. For example, a test suite could call renderMermaidAscii on a generated flowchart and paste the result into a GitHub Actions log, giving reviewers a quick visual without opening a browser.
import { renderMermaidAscii } from 'beautiful-mermaid';
import fs from 'fs';
const diagram = fs.readFileSync('src/__tests__/testdata/ascii/cls_basic.txt', 'utf8');
console.log(renderMermaidAscii(diagram));
Code Health & Issues
- High (soundness) – Import cycle:
src/ascii/draw.ts↔src/ascii/grid.ts. Break the cycle by extracting shared types into a separate module. - High (clarity) – Duplicated code blocks: 47 identical 6‑line snippets across
samples-data.tsand multiple test files. Consolidate into shared helpers. - High (cognitive load) – Oversized files:
samples-data.ts,index.ts,src/layout.tseach exceed 900 lines; consider splitting by responsibility. - Medium – High branching density:
src/ascii/index.ts,src/ascii/draw.ts,src/dagre-adapter.tscontain >19 branch points in <65 lines, making them harder to reason about. Refactor to strategy tables or smaller functions. - Dependency drift:
@dagrejs/dagre(^1.1.8),typescript(^5.0.0),shiki(^3.19.0) are 1–2 major versions behind current releases, potentially missing bug fixes and performance improvements. - Missing lockfile: No
package-lock.jsonorpnpm-lock.yaml; reproducible builds rely on thebun.lockwhich is not used by npm. Add an npm lockfile. - CI present: GitHub Actions workflow (
.github/workflows/ci.yml) runs the test suite, indicating basic quality gates are in place.
The Bottom Line
beautiful-mermaid delivers a functional, zero‑DOM Mermaid renderer with both SVG and terminal‑friendly ASCII outputs. The core architecture is clear, but the codebase suffers from a few large, tightly coupled modules and outdated dependencies. It is suitable for teams that need fast diagram rendering in non‑browser contexts, provided they allocate effort to refactor the identified hot spots and bring the dependency versions up‑to‑date.