zombie-mermaid 5.2.0 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -28,12 +28,25 @@ Ultra-fast, fully themeable, zero DOM dependencies. A maintained fork of [`beaut
28
28
 
29
29
  ## Why This Fork Exists
30
30
 
31
- `beautiful-mermaid` is a genuinely good library — fast, beautiful, and works everywhere from rich UIs to plain terminals. But upstream development has stalled: dozens of [pull requests](https://github.com/lukilabs/beautiful-mermaid/pulls) sit open, some for over half a year, and nothing has merged in months — by most definitions, it's dead. I maintain `zombie-mermaid` as the fork that won't stay buried: pulling in upstream fixes, giving PRs stuck in the upstream queue a home, and actually shipping releases. Craft and Craft Agents aren't part of this project's process going forward; this is an independently maintained continuation.
31
+ `beautiful-mermaid` is a genuinely good library — fast, beautiful, and works everywhere from rich UIs to plain terminals. Checkable facts, as of 2026-10-13: the last push to upstream's `main` was 2026-05-06 and its latest release is v1.1.2 (2026-02-26); it has [43 open pull requests](https://github.com/lukilabs/beautiful-mermaid/pulls) (19 opened before 2026-04-13) and [50 open issues](https://github.com/lukilabs/beautiful-mermaid/issues) (live counts at those links; the figures above are a dated snapshot). I maintain `zombie-mermaid` as the fork that won't stay buried: pulling in upstream fixes, giving PRs stuck in the upstream queue a home, and actually shipping releases. Craft and Craft Agents aren't part of this project's process going forward; this is an independently maintained continuation.
32
32
 
33
- This isn't just a claim — see **[what this fork fixes](https://dfadler.github.io/zombie-mermaid/fork-fixes.html)** for an evidence-based before/after showcase: every bug listed there is rendered by the actual pre-fix and post-fix code, not described from memory.
33
+ This isn't just a claim — see **[what this fork fixes](https://dfadler.github.io/zombie-mermaid/fork-fixes.html)** for an evidence-based before/after showcase (37 fixes as of 2026-10-13): every bug listed there is rendered by the actual pre-fix and post-fix code, not described from memory.
34
34
 
35
35
  It's still MIT-licensed, still built on the same foundation, and still credits the original authors — including the ASCII rendering engine's origins — in [Attribution](#attribution) below.
36
36
 
37
+ ### Migrating from `beautiful-mermaid`
38
+
39
+ Swap the package (`npm uninstall beautiful-mermaid && npm install zombie-mermaid`, Node.js 24+) and change the import path; `renderMermaidSVG`, `renderMermaidSVGAsync`, `renderMermaidASCII` and `parseMermaid` keep the same signatures. In browsers and bundlers, also register `elkjs` once (Node, Bun, the CLI and MCP do it for you):
40
+
41
+ ```ts
42
+ import ELK from 'elkjs/lib/elk.bundled.js'
43
+ import { registerElk, renderMermaidSVG } from 'zombie-mermaid'
44
+
45
+ registerElk(ELK) // once, before the first render
46
+ ```
47
+
48
+ Some fixes change existing output, so diff your stored diagrams first: see the [migration guide](docs/migrating-from-beautiful-mermaid.md) and the [`elkjs` guide](docs/guides/elkjs-optional-peer.md).
49
+
37
50
  ## The Problem With Default Mermaid Rendering
38
51
 
39
52
  Diagrams are essential for AI-assisted programming. When you're working with an AI coding assistant, being able to visualize data flows, state machines, and system architecture—directly in your terminal or chat interface—makes complex concepts instantly graspable.
package/dist/cli.js CHANGED
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as V } from "node:module";
3
3
  import { extname as H, format as q, parse as D } from "node:path";
4
- import { THEMES as B, escapeXml as j, isDirection as K, isWideChar as J } from "@zombie-mermaid/core";
5
- import { access as Z, readFile as F, writeFile as Q } from "node:fs/promises";
6
- import { diagramColorsToAsciiTheme as ee, renderMermaidASCII as O } from "@zombie-mermaid/ascii-renderer";
4
+ import { MermaidParseError as j, THEMES as B, escapeXml as K, isDirection as J, isWideChar as Z } from "@zombie-mermaid/core";
5
+ import { access as Q, readFile as F, writeFile as ee } from "node:fs/promises";
6
+ import { diagramColorsToAsciiTheme as te, renderMermaidASCII as O } from "@zombie-mermaid/ascii-renderer";
7
7
  import "@zombie-mermaid/mermaid-parser";
8
- import { registerElk as te, renderMermaidSVG as M, validateMermaid as ne } from "@zombie-mermaid/svg-renderer";
9
- import { createServer as re } from "node:http";
10
- import { StdioServerTransport as oe } from "@modelcontextprotocol/sdk/server/stdio.js";
11
- import { createMcpServer as ie } from "@zombie-mermaid/mcp";
12
- import ae from "elkjs/lib/elk.bundled.js";
13
- var se = 3e3;
8
+ import { registerElk as ne, renderMermaidSVG as M, validateMermaid as re } from "@zombie-mermaid/svg-renderer";
9
+ import { createServer as oe } from "node:http";
10
+ import { StdioServerTransport as ie } from "@modelcontextprotocol/sdk/server/stdio.js";
11
+ import { createMcpServer as ae } from "@zombie-mermaid/mcp";
12
+ import se from "elkjs/lib/elk.bundled.js";
13
+ var de = 3e3;
14
14
  var G = {
15
15
  ".svg": "svg",
16
16
  ".txt": "ascii",
@@ -18,7 +18,7 @@ var G = {
18
18
  ".htm": "html",
19
19
  ".png": "png"
20
20
  };
21
- function de(e) {
21
+ function ce(e) {
22
22
  if (!(e === void 0 || e === "-"))
23
23
  return G[H(e).toLowerCase()];
24
24
  }
@@ -45,7 +45,7 @@ var w = {
45
45
  label: "the PNG rasterization"
46
46
  }
47
47
  }, T = Object.keys(w);
48
- function ce(e, n) {
48
+ function le(e, n) {
49
49
  const t = D(e);
50
50
  return q({
51
51
  dir: t.dir,
@@ -53,22 +53,22 @@ function ce(e, n) {
53
53
  ext: n
54
54
  });
55
55
  }
56
- function le(e) {
56
+ function me(e) {
57
57
  const [n, ...t] = e;
58
58
  if (n === void 0) return { command: "help" };
59
59
  if (n === "--help" || n === "-h") return { command: "help" };
60
60
  if (n === "--version" || n === "-v") return { command: "version" };
61
61
  if (n === "themes") return { command: "themes" };
62
- if (n === "render") return pe(t);
62
+ if (n === "render") return fe(t);
63
63
  if (n === "validate") {
64
- const r = t.find((a, c) => c > 0 || a.startsWith("-"));
64
+ const r = t.find((a, d) => d > 0 || a.startsWith("-"));
65
65
  if (r !== void 0) throw new Error(`Unexpected argument: ${r}`);
66
66
  return {
67
67
  command: "validate",
68
68
  input: t[0]
69
69
  };
70
70
  }
71
- if (n === "web") return fe(t);
71
+ if (n === "web") return he(t);
72
72
  if (n === "mcp") return { command: "mcp" };
73
73
  throw new Error(`Unknown command: ${n}`);
74
74
  }
@@ -78,7 +78,7 @@ function z(e, n, t) {
78
78
  if (!/^\d+$/.test(r)) throw new Error(`${t} requires a non-negative integer, got: "${r}"`);
79
79
  return Number(r);
80
80
  }
81
- function me(e, n, t) {
81
+ function ue(e, n, t) {
82
82
  const r = e[n + 1];
83
83
  if (n + 1 >= e.length || r === void 0) throw new Error(`${t} requires a value ("auto" or a positive integer)`);
84
84
  if (r === "auto") return "auto";
@@ -86,15 +86,15 @@ function me(e, n, t) {
86
86
  if (!/^\d+$/.test(r) || a === 0 || !Number.isSafeInteger(a)) throw new Error(`${t} requires "auto" or a positive integer, got: "${r}"`);
87
87
  return a;
88
88
  }
89
- function ue(e, n, t) {
89
+ function pe(e, n, t) {
90
90
  const r = e[n + 1];
91
91
  if (n + 1 >= e.length || r === void 0) throw new Error(`${t} requires a value (one of TD, TB, BT, LR, RL)`);
92
92
  const a = r.toUpperCase();
93
- if (!K(a)) throw new Error(`${t} requires one of TD, TB, BT, LR, RL, got: "${r}"`);
93
+ if (!J(a)) throw new Error(`${t} requires one of TD, TB, BT, LR, RL, got: "${r}"`);
94
94
  return a;
95
95
  }
96
- function pe(e) {
97
- let n, t = !1, r = !1, a = !1, c = !1, l = !1, m, g = !1, E, S, k, s, u = !1, p = !1, h, b, i = 0;
96
+ function fe(e) {
97
+ let n, t = !1, r = !1, a = !1, d = !1, l = !1, m, g = !1, E, S, k, s, u = !1, p = !1, h, b, i = 0;
98
98
  for (; i < e.length; ) {
99
99
  const o = e[i];
100
100
  if (o === void 0) throw new Error(`parseArgs: index ${i} out of range while parsing arguments`);
@@ -105,7 +105,7 @@ function pe(e) {
105
105
  else if (o === "--resolve-colors")
106
106
  a = !0, i++;
107
107
  else if (o === "--html")
108
- c = !0, i++;
108
+ d = !0, i++;
109
109
  else if (o === "--png")
110
110
  l = !0, i++;
111
111
  else if (o === "-o" || o === "--output") {
@@ -127,9 +127,9 @@ function pe(e) {
127
127
  else if (o === "--hyperlinks")
128
128
  p = !0, i++;
129
129
  else if (o === "-w" || o === "--max-width")
130
- h = me(e, i, o), i += 2;
130
+ h = ue(e, i, o), i += 2;
131
131
  else if (o === "--direction")
132
- b = ue(e, i, o), i += 2;
132
+ b = pe(e, i, o), i += 2;
133
133
  else if (!o.startsWith("-") || o === "-") {
134
134
  if (o === "-") throw new Error("Unexpected argument: - (use -o - to write output to stdout; omit the input file to read stdin)");
135
135
  if (n !== void 0) throw new Error(`Unexpected argument: ${o} (input file already set to "${n}")`);
@@ -138,30 +138,30 @@ function pe(e) {
138
138
  }
139
139
  const v = {
140
140
  svg: r,
141
- html: c,
141
+ html: d,
142
142
  png: l
143
143
  }, y = T.filter((o) => v[o]);
144
144
  if (y.length > 1) {
145
- const [o, d] = y;
146
- throw new Error(`${w[o].flag} and ${w[d].flag} cannot both be set — they would write different content to the same output path. Run the command twice with different -o paths for each.`);
145
+ const [o, c] = y;
146
+ throw new Error(`${w[o].flag} and ${w[c].flag} cannot both be set — they would write different content to the same output path. Run the command twice with different -o paths for each.`);
147
147
  }
148
- const f = de(m);
148
+ const f = ce(m);
149
149
  if (f !== void 0 && f !== "ascii") {
150
- const o = T.find((d) => d !== f && v[d]);
150
+ const o = T.find((c) => c !== f && v[c]);
151
151
  if (o !== void 0) {
152
- const d = w[f], $ = w[o];
153
- throw new Error(`-o ${m} has ${d.article} ${d.ext} extension, but ${$.flag} output would be written to it. Use a ${$.ext} path (or -o - for stdout) for ${$.label}.`);
152
+ const c = w[f], $ = w[o];
153
+ throw new Error(`-o ${m} has ${c.article} ${c.ext} extension, but ${$.flag} output would be written to it. Use a ${$.ext} path (or -o - for stdout) for ${$.label}.`);
154
154
  }
155
- f === "svg" ? r = !0 : f === "html" ? c = !0 : l = !0;
155
+ f === "svg" ? r = !0 : f === "html" ? d = !0 : l = !0;
156
156
  } else if (f === "ascii") {
157
- const o = T.find((d) => v[d]);
157
+ const o = T.find((c) => v[c]);
158
158
  if (o !== void 0) {
159
- const d = w[o];
160
- throw new Error(`-o ${m} has a .txt extension, but ${d.flag} output would be written to it. Use a ${d.ext} path (or -o - for stdout) instead.`);
159
+ const c = w[o];
160
+ throw new Error(`-o ${m} has a .txt extension, but ${c.flag} output would be written to it. Use a ${c.ext} path (or -o - for stdout) instead.`);
161
161
  }
162
162
  t = !0;
163
163
  }
164
- if (!t && !r && !c && !l) {
164
+ if (!t && !r && !d && !l) {
165
165
  if (m !== void 0 && m !== "-") {
166
166
  const o = Object.keys(G).join(", ");
167
167
  throw new Error(`Cannot infer an output format from "${m}" — pass --ascii, --svg, --html, or --png, or use a recognised extension (${o})`);
@@ -170,7 +170,7 @@ function pe(e) {
170
170
  }
171
171
  const C = {
172
172
  svg: r,
173
- html: c,
173
+ html: d,
174
174
  png: l
175
175
  }, x = T.find((o) => C[o]);
176
176
  if (m === "-" && t && x !== void 0) {
@@ -178,9 +178,9 @@ function pe(e) {
178
178
  throw new Error(`-o - would send both ASCII and ${o} to stdout; drop --ascii, or write the ${o} to a file path`);
179
179
  }
180
180
  if (x !== void 0 && m === void 0) {
181
- const { flag: o, ext: d } = w[x];
181
+ const { flag: o, ext: c } = w[x];
182
182
  if (n === void 0) throw new Error(`${o} needs -o <path> (or -o - for stdout) when reading from stdin — there is no input file name to derive an output name from`);
183
- m = ce(n, d);
183
+ m = le(n, c);
184
184
  }
185
185
  if (h !== void 0 && !t) throw new Error("-w/--max-width requires --ascii");
186
186
  if (p && !t) throw new Error("--hyperlinks requires --ascii");
@@ -191,7 +191,7 @@ function pe(e) {
191
191
  ascii: t,
192
192
  svg: r,
193
193
  resolveColors: a,
194
- html: c,
194
+ html: d,
195
195
  png: l,
196
196
  output: m,
197
197
  force: g,
@@ -205,8 +205,8 @@ function pe(e) {
205
205
  direction: b
206
206
  };
207
207
  }
208
- function fe(e) {
209
- let n = se, t = 0;
208
+ function he(e) {
209
+ let n = de, t = 0;
210
210
  for (; t < e.length; ) {
211
211
  const r = e[t];
212
212
  if (r === void 0) throw new Error(`parseArgs: index ${t} out of range while parsing arguments`);
@@ -219,52 +219,51 @@ function fe(e) {
219
219
  port: n
220
220
  };
221
221
  }
222
- var he = /\p{Mn}|\p{Me}/u;
223
- function ge(e) {
224
- return he.test(e);
222
+ var ge = /\p{Mn}|\p{Me}/u;
223
+ function ve(e) {
224
+ return ge.test(e);
225
225
  }
226
- var ve = new Intl.Segmenter(void 0, { granularity: "grapheme" }), we = "️";
227
- function be(e) {
226
+ var we = new Intl.Segmenter(void 0, { granularity: "grapheme" }), be = "️";
227
+ function ye(e) {
228
228
  if (/^[\x20-\x7e]*$/.test(e)) return e.split("");
229
229
  const n = [];
230
- for (const { segment: t } of ve.segment(e)) n.push(t);
230
+ for (const { segment: t } of we.segment(e)) n.push(t);
231
231
  return n;
232
232
  }
233
- function ye(e) {
234
- if (e.includes(we)) return 2;
233
+ function xe(e) {
234
+ if (e.includes(be)) return 2;
235
235
  let n = !1, t = !1;
236
236
  for (const r of e)
237
- J(r) && (n = !0), ge(r) || (t = !0);
237
+ Z(r) && (n = !0), ve(r) || (t = !0);
238
238
  return n ? 2 : t ? 1 : 0;
239
239
  }
240
- function xe(e) {
240
+ function Ee(e) {
241
241
  let n = 0;
242
- for (const t of be(e)) n += ye(t);
242
+ for (const t of ye(e)) n += xe(t);
243
243
  return n;
244
244
  }
245
- var Ee = /\x1b\]8;[^\x07\x1b]*(?:\x1b\\|\x07)/g;
246
- function Se(e) {
247
- return e.replace(Ee, "");
245
+ var Se = /\x1b\]8;[^\x07\x1b]*(?:\x1b\\|\x07)/g;
246
+ function ke(e) {
247
+ return e.replace(Se, "");
248
248
  }
249
- var ke = /^Line (\d+): ([\s\S]*)$/;
250
- function Ce(e, n) {
251
- const t = ke.exec(e);
252
- if (t === null) return;
253
- const r = Number(t[1]), a = n.split(/\r?\n/)[r - 1];
254
- if (!(!Number.isSafeInteger(r) || r < 1 || a === void 0))
249
+ var Ce = /^Line (\d+): ([\s\S]*)$/;
250
+ function Te(e, n) {
251
+ if (!(e instanceof j) || e.line === void 0) return;
252
+ const { line: t, message: r } = e, a = Ce.exec(r), d = n.split(/\r?\n/)[t - 1];
253
+ if (!(t < 1 || d === void 0))
255
254
  return {
256
- line: r,
257
- sourceLine: a,
258
- message: t[2] ?? ""
255
+ line: t,
256
+ sourceLine: d,
257
+ message: a?.[2] ?? r
259
258
  };
260
259
  }
261
260
  function W(e, n) {
262
261
  if (!(e instanceof Error)) return e;
263
- const t = Ce(e.message, n);
262
+ const t = Te(e, n);
264
263
  return t === void 0 ? e : /* @__PURE__ */ new Error(`${e.message}
265
264
  ${t.line} | ${t.sourceLine}`);
266
265
  }
267
- var Te = `// @ts-check
266
+ var Ae = `// @ts-check
268
267
  /// <reference lib="dom" />
269
268
  // ============================================================================
270
269
  // Client script for the CLI's self-contained HTML viewer (\`render --html\`).
@@ -556,7 +555,7 @@ var Te = `// @ts-check
556
555
  fit()
557
556
  stage.focus({ preventScroll: true })
558
557
  })()
559
- `, Ae = `
558
+ `, Ie = `
560
559
  :root {
561
560
  color-scheme: light dark;
562
561
  --bg: #f4f4f5;
@@ -663,16 +662,16 @@ var Te = `// @ts-check
663
662
  #diagram { position: static; transform: none !important; }
664
663
  }
665
664
  `.trim();
666
- function Ie(e) {
665
+ function Me(e) {
667
666
  const n = e.title?.trim() || "Mermaid diagram";
668
667
  return `<!doctype html>
669
668
  <html lang="en">
670
669
  <head>
671
670
  <meta charset="utf-8" />
672
671
  <meta name="viewport" content="width=device-width, initial-scale=1" />
673
- <title>${j(n)}</title>
672
+ <title>${K(n)}</title>
674
673
  <style>
675
- ${Ae}
674
+ ${Ie}
676
675
  </style>
677
676
  </head>
678
677
  <body>
@@ -690,13 +689,13 @@ ${e.svg}
690
689
  <button id="theme" type="button" aria-pressed="false" aria-label="Switch to dark mode (T)">Dark</button>
691
690
  </div>
692
691
  <script>
693
- ${Te}
692
+ ${Ae}
694
693
  <\/script>
695
694
  </body>
696
695
  </html>
697
696
  `;
698
697
  }
699
- async function Me(e) {
698
+ async function ze(e) {
700
699
  let n;
701
700
  try {
702
701
  n = await import("@resvg/resvg-js");
@@ -707,16 +706,16 @@ ${r}`);
707
706
  }
708
707
  return (await n.renderAsync(e)).asPng();
709
708
  }
710
- var ze = 80, P = 1, L = 1, R = 0, $e = /\x1b\[[0-9;]*m/g;
709
+ var $e = 80, P = 1, L = 1, R = 0, Pe = /\x1b\[[0-9;]*m/g;
711
710
  function _(e) {
712
711
  return e.split(`
713
- `).reduce((n, t) => Math.max(n, xe(Se(t.replace($e, "")))), 0);
712
+ `).reduce((n, t) => Math.max(n, Ee(ke(t.replace(Pe, "")))), 0);
714
713
  }
715
- function Pe(e) {
716
- return e !== "auto" ? e : process.stdout.columns ?? ze;
714
+ function Le(e) {
715
+ return e !== "auto" ? e : process.stdout.columns ?? $e;
717
716
  }
718
- async function Le(e, n, t, r) {
719
- const a = n ?? process.stdout, c = r ?? process.stderr;
717
+ async function Re(e, n, t, r) {
718
+ const a = n ?? process.stdout, d = r ?? process.stderr;
720
719
  let l;
721
720
  if (e.input !== void 0) l = await F(e.input, "utf-8");
722
721
  else if (t !== void 0) l = t;
@@ -726,33 +725,33 @@ async function Le(e, n, t, r) {
726
725
  }
727
726
  if (l.trim().length === 0) throw new Error("Empty input — provide a Mermaid diagram via file or stdin");
728
727
  try {
729
- await Re(e, l, a, c);
728
+ await Be(e, l, a, d);
730
729
  } catch (m) {
731
730
  throw W(m, l);
732
731
  }
733
732
  }
734
- async function Re(e, n, t, r) {
733
+ async function Be(e, n, t, r) {
735
734
  let a;
736
735
  if (e.theme !== void 0 && (a = B[e.theme], a === void 0)) {
737
736
  const s = Object.keys(B).join(", ");
738
737
  throw new Error(`Unknown theme: "${e.theme}". Available themes: ${s}`);
739
738
  }
740
- const c = e.svg && e.output === "-", l = e.html && e.output === "-", m = e.png && e.output === "-", g = e.ascii && !e.svg && !e.html && !e.png && e.output !== void 0 && e.output !== "-" ? e.output : void 0, E = e.svg && !c ? e.output : void 0, S = e.html && !l ? e.output : void 0, k = e.png && !m ? e.output : void 0;
739
+ const d = e.svg && e.output === "-", l = e.html && e.output === "-", m = e.png && e.output === "-", g = e.ascii && !e.svg && !e.html && !e.png && e.output !== void 0 && e.output !== "-" ? e.output : void 0, E = e.svg && !d ? e.output : void 0, S = e.html && !l ? e.output : void 0, k = e.png && !m ? e.output : void 0;
741
740
  for (const s of [
742
741
  g,
743
742
  E,
744
743
  S,
745
744
  k
746
- ]) s !== void 0 && await Be(s, e.force);
745
+ ]) s !== void 0 && await Oe(s, e.force);
747
746
  if (e.ascii) {
748
747
  const s = a && g === void 0 ? {
749
748
  colorMode: "auto",
750
- theme: ee(a)
749
+ theme: te(a)
751
750
  } : { colorMode: "none" };
752
751
  e.paddingX !== void 0 && (s.paddingX = e.paddingX), e.paddingY !== void 0 && (s.paddingY = e.paddingY), e.borderPadding !== void 0 && (s.boxBorderPadding = e.borderPadding), e.coords && (s.showCoords = !0), e.direction !== void 0 && (s.direction = e.direction), e.hyperlinks && g === void 0 && (s.hyperlinks = !0);
753
752
  let u = O(n, s);
754
753
  if (e.maxWidth !== void 0) {
755
- const p = Pe(e.maxWidth);
754
+ const p = Le(e.maxWidth);
756
755
  let h = _(u), b = !1;
757
756
  if (h > p) {
758
757
  const i = s.paddingX ?? 5, v = s.paddingY ?? 5, y = s.boxBorderPadding ?? 1, f = Math.min(i, P), C = Math.min(v, L), x = Math.min(y, R);
@@ -762,8 +761,8 @@ async function Re(e, n, t, r) {
762
761
  paddingX: f,
763
762
  paddingY: C,
764
763
  boxBorderPadding: x
765
- }), d = _(o);
766
- d < h && (u = o, h = d, b = !0);
764
+ }), c = _(o);
765
+ c < h && (u = o, h = c, b = !0);
767
766
  }
768
767
  }
769
768
  if (h > p) {
@@ -783,10 +782,10 @@ async function Re(e, n, t, r) {
783
782
  };
784
783
  e.direction !== void 0 && (s.direction = e.direction);
785
784
  const u = M(n, s);
786
- await I(A(c, E), u, t, e.force);
785
+ await I(A(d, E), u, t, e.force);
787
786
  }
788
787
  if (e.html) {
789
- const s = M(n, a ?? {}), u = e.input ? D(e.input).name : void 0, p = Ie({
788
+ const s = M(n, a ?? {}), u = e.input ? D(e.input).name : void 0, p = Me({
790
789
  svg: s,
791
790
  title: u
792
791
  });
@@ -798,7 +797,7 @@ async function Re(e, n, t, r) {
798
797
  resolveColors: !0
799
798
  };
800
799
  e.direction !== void 0 && (s.direction = e.direction);
801
- const u = M(n, s), p = await Me(u);
800
+ const u = M(n, s), p = await ze(u);
802
801
  await I(A(m, k), p, t, e.force);
803
802
  }
804
803
  }
@@ -814,25 +813,25 @@ async function I(e, n, t, r) {
814
813
  t.write(n);
815
814
  break;
816
815
  case "file":
817
- await Oe(e.path, n, r);
816
+ await _e(e.path, n, r);
818
817
  }
819
818
  }
820
819
  function X(e) {
821
820
  return /* @__PURE__ */ new Error(`Refusing to overwrite existing file "${e}" — pass --force to replace it`);
822
821
  }
823
- async function Be(e, n) {
822
+ async function Oe(e, n) {
824
823
  if (n) return;
825
824
  let t = !0;
826
825
  try {
827
- await Z(e);
826
+ await Q(e);
828
827
  } catch {
829
828
  t = !1;
830
829
  }
831
830
  if (t) throw X(e);
832
831
  }
833
- async function Oe(e, n, t) {
832
+ async function _e(e, n, t) {
834
833
  try {
835
- await Q(e, n, {
834
+ await ee(e, n, {
836
835
  encoding: "utf-8",
837
836
  flag: t ? "w" : "wx"
838
837
  });
@@ -846,7 +845,7 @@ async function Y() {
846
845
  n.on("data", (a) => e.push(a)), n.on("end", () => t(e.join(""))), n.on("error", r);
847
846
  });
848
847
  }
849
- async function _e(e, n) {
848
+ async function Ne(e, n) {
850
849
  let t;
851
850
  if (e.input !== void 0) t = await F(e.input, "utf-8");
852
851
  else if (n !== void 0) t = n;
@@ -857,30 +856,30 @@ async function _e(e, n) {
857
856
  const r = t;
858
857
  if (r.trim().length === 0) throw new Error("Empty input — provide a Mermaid diagram via file or stdin");
859
858
  try {
860
- ne(r);
859
+ re(r);
861
860
  } catch (a) {
862
861
  throw W(a, r);
863
862
  }
864
863
  console.log("valid");
865
864
  }
866
- var Ne = 1e6;
867
- function De(e) {
865
+ var De = 1e6;
866
+ function Fe(e) {
868
867
  return new Promise((n, t) => {
869
868
  const r = [];
870
869
  let a = 0;
871
- e.on("data", (c) => {
872
- if (a += c.length, a > Ne) {
870
+ e.on("data", (d) => {
871
+ if (a += d.length, a > De) {
873
872
  t(/* @__PURE__ */ new Error("Request body too large")), e.destroy();
874
873
  return;
875
874
  }
876
- r.push(c);
875
+ r.push(d);
877
876
  }), e.on("end", () => n(Buffer.concat(r).toString("utf-8"))), e.on("error", t);
878
877
  });
879
878
  }
880
879
  function U(e) {
881
880
  return typeof e == "object" && e !== null;
882
881
  }
883
- function Fe(e) {
882
+ function Ge(e) {
884
883
  let n;
885
884
  try {
886
885
  n = JSON.parse(e);
@@ -902,9 +901,9 @@ function N(e, n, t) {
902
901
  "Content-Length": Buffer.byteLength(r)
903
902
  }), e.end(r);
904
903
  }
905
- async function Ge(e, n) {
904
+ async function We(e, n) {
906
905
  try {
907
- const { source: t, format: r } = Fe(await De(e));
906
+ const { source: t, format: r } = Ge(await Fe(e));
908
907
  N(n, 200, {
909
908
  output: r === "svg" ? M(t) : O(t),
910
909
  format: r
@@ -913,7 +912,7 @@ async function Ge(e, n) {
913
912
  N(n, 400, { error: t instanceof Error ? t.message : String(t) });
914
913
  }
915
914
  }
916
- var We = `<!doctype html>
915
+ var Xe = `<!doctype html>
917
916
  <html lang="en">
918
917
  <head>
919
918
  <meta charset="utf-8" />
@@ -979,56 +978,56 @@ var We = `<!doctype html>
979
978
  </body>
980
979
  </html>
981
980
  `;
982
- function Xe() {
983
- return re((e, n) => {
981
+ function Ye() {
982
+ return oe((e, n) => {
984
983
  const t = (e.url ?? "/").split("?")[0];
985
984
  if (e.method === "GET" && (t === "/" || t === "")) {
986
- n.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }), n.end(We);
985
+ n.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }), n.end(Xe);
987
986
  return;
988
987
  }
989
988
  if (e.method === "POST" && t === "/render") {
990
- Ge(e, n);
989
+ We(e, n);
991
990
  return;
992
991
  }
993
992
  n.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" }), n.end("Not found");
994
993
  });
995
994
  }
996
- function Ye(e) {
995
+ function Ue(e) {
997
996
  return new Promise((n, t) => {
998
- const r = Xe();
997
+ const r = Ye();
999
998
  r.once("error", t), r.listen(e, "127.0.0.1", () => {
1000
999
  r.removeListener("error", t), n(r);
1001
1000
  });
1002
1001
  });
1003
1002
  }
1004
- async function Ue(e, n = console.log) {
1005
- const t = await Ye(e.port), r = t.address();
1003
+ async function Ve(e, n = console.log) {
1004
+ const t = await Ue(e.port), r = t.address();
1006
1005
  return n(`zombie-mermaid web running at http://localhost:${U(r) && typeof r.port == "number" ? r.port : e.port}`), t;
1007
1006
  }
1008
- async function Ve(e = (n) => console.error(n)) {
1009
- const n = ie(), t = new oe();
1007
+ async function He(e = (n) => console.error(n)) {
1008
+ const n = ae(), t = new ie();
1010
1009
  return await n.connect(t), e("zombie-mermaid MCP server running on stdio (experimental — feedback welcome: https://github.com/dfadler/zombie-mermaid/issues)"), n;
1011
1010
  }
1012
- function He() {
1011
+ function qe() {
1013
1012
  const e = V(import.meta.url)("../package.json");
1014
1013
  return typeof e == "object" && e !== null && "version" in e && typeof e.version == "string" ? e.version : "unknown";
1015
1014
  }
1016
- te(ae);
1017
- var qe = He();
1018
- async function je() {
1015
+ ne(se);
1016
+ var je = qe();
1017
+ async function Ke() {
1019
1018
  const e = process.argv.slice(2);
1020
1019
  let n;
1021
1020
  try {
1022
- n = le(e);
1021
+ n = me(e);
1023
1022
  } catch (t) {
1024
1023
  console.error(`Error: ${t instanceof Error ? t.message : String(t)}`), process.exit(1);
1025
1024
  }
1026
1025
  switch (n.command) {
1027
1026
  case "help":
1028
- Ke();
1027
+ Je();
1029
1028
  break;
1030
1029
  case "version":
1031
- console.log(`zombie-mermaid ${qe}`);
1030
+ console.log(`zombie-mermaid ${je}`);
1032
1031
  break;
1033
1032
  case "themes":
1034
1033
  console.log(`Available themes:
@@ -1037,34 +1036,34 @@ async function je() {
1037
1036
  break;
1038
1037
  case "render":
1039
1038
  try {
1040
- await Le(n);
1039
+ await Re(n);
1041
1040
  } catch (t) {
1042
1041
  console.error(`Error: ${t instanceof Error ? t.message : String(t)}`), process.exit(1);
1043
1042
  }
1044
1043
  break;
1045
1044
  case "validate":
1046
1045
  try {
1047
- await _e(n);
1046
+ await Ne(n);
1048
1047
  } catch (t) {
1049
1048
  console.error(`Error: ${t instanceof Error ? t.message : String(t)}`), process.exit(1);
1050
1049
  }
1051
1050
  break;
1052
1051
  case "web":
1053
1052
  try {
1054
- await Ue(n);
1053
+ await Ve(n);
1055
1054
  } catch (t) {
1056
1055
  console.error(`Error: ${t instanceof Error ? t.message : String(t)}`), process.exit(1);
1057
1056
  }
1058
1057
  break;
1059
1058
  case "mcp":
1060
1059
  try {
1061
- await Ve();
1060
+ await He();
1062
1061
  } catch (t) {
1063
1062
  console.error(`Error: ${t instanceof Error ? t.message : String(t)}`), process.exit(1);
1064
1063
  }
1065
1064
  }
1066
1065
  }
1067
- function Ke() {
1066
+ function Je() {
1068
1067
  console.log(`
1069
1068
  zombie-mermaid — render Mermaid diagrams from the command line
1070
1069
 
@@ -1139,7 +1138,7 @@ Options:
1139
1138
  -v, --version Show version
1140
1139
  `.trim());
1141
1140
  }
1142
- je();
1141
+ Ke();
1143
1142
  export {
1144
- je as main
1143
+ Ke as main
1145
1144
  };
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@zombie-mermaid/core"),t=require("@zombie-mermaid/mermaid-parser"),n=require("@zombie-mermaid/ascii-renderer"),r=require("@zombie-mermaid/svg-renderer");Object.defineProperty(exports,"DEFAULTS",{enumerable:!0,get:function(){return e.DEFAULTS}}),Object.defineProperty(exports,"ElkNotRegisteredError",{enumerable:!0,get:function(){return r.ElkNotRegisteredError}}),Object.defineProperty(exports,"THEMES",{enumerable:!0,get:function(){return e.THEMES}}),Object.defineProperty(exports,"createLayoutCache",{enumerable:!0,get:function(){return r.createLayoutCache}}),Object.defineProperty(exports,"fromShikiTheme",{enumerable:!0,get:function(){return e.fromShikiTheme}}),Object.defineProperty(exports,"parseMermaid",{enumerable:!0,get:function(){return t.parseMermaid}}),Object.defineProperty(exports,"registerElk",{enumerable:!0,get:function(){return r.registerElk}}),Object.defineProperty(exports,"renderMermaid",{enumerable:!0,get:function(){return r.renderMermaid}}),Object.defineProperty(exports,"renderMermaidASCII",{enumerable:!0,get:function(){return n.renderMermaidASCII}}),Object.defineProperty(exports,"renderMermaidAscii",{enumerable:!0,get:function(){return n.renderMermaidAscii}}),Object.defineProperty(exports,"renderMermaidSVG",{enumerable:!0,get:function(){return r.renderMermaidSVG}}),Object.defineProperty(exports,"renderMermaidSVGAsync",{enumerable:!0,get:function(){return r.renderMermaidSVGAsync}}),Object.defineProperty(exports,"renderMermaidSync",{enumerable:!0,get:function(){return r.renderMermaidSync}}),Object.defineProperty(exports,"themeCssVariables",{enumerable:!0,get:function(){return r.themeCssVariables}}),Object.defineProperty(exports,"validateMermaid",{enumerable:!0,get:function(){return r.validateMermaid}});
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@zombie-mermaid/core"),t=require("@zombie-mermaid/mermaid-parser"),n=require("@zombie-mermaid/ascii-renderer"),r=require("@zombie-mermaid/svg-renderer");Object.defineProperty(exports,"DEFAULTS",{enumerable:!0,get:function(){return e.DEFAULTS}}),Object.defineProperty(exports,"DEFAULT_RENDER_LIMITS",{enumerable:!0,get:function(){return e.DEFAULT_RENDER_LIMITS}}),Object.defineProperty(exports,"ElkNotRegisteredError",{enumerable:!0,get:function(){return r.ElkNotRegisteredError}}),Object.defineProperty(exports,"LimitExceededError",{enumerable:!0,get:function(){return e.LimitExceededError}}),Object.defineProperty(exports,"THEMES",{enumerable:!0,get:function(){return e.THEMES}}),Object.defineProperty(exports,"createLayoutCache",{enumerable:!0,get:function(){return r.createLayoutCache}}),Object.defineProperty(exports,"fromShikiTheme",{enumerable:!0,get:function(){return e.fromShikiTheme}}),Object.defineProperty(exports,"parseMermaid",{enumerable:!0,get:function(){return t.parseMermaid}}),Object.defineProperty(exports,"registerElk",{enumerable:!0,get:function(){return r.registerElk}}),Object.defineProperty(exports,"renderMermaid",{enumerable:!0,get:function(){return r.renderMermaid}}),Object.defineProperty(exports,"renderMermaidASCII",{enumerable:!0,get:function(){return n.renderMermaidASCII}}),Object.defineProperty(exports,"renderMermaidAscii",{enumerable:!0,get:function(){return n.renderMermaidAscii}}),Object.defineProperty(exports,"renderMermaidSVG",{enumerable:!0,get:function(){return r.renderMermaidSVG}}),Object.defineProperty(exports,"renderMermaidSVGAsync",{enumerable:!0,get:function(){return r.renderMermaidSVGAsync}}),Object.defineProperty(exports,"renderMermaidSync",{enumerable:!0,get:function(){return r.renderMermaidSync}}),Object.defineProperty(exports,"themeCssVariables",{enumerable:!0,get:function(){return r.themeCssVariables}}),Object.defineProperty(exports,"validateMermaid",{enumerable:!0,get:function(){return r.validateMermaid}});
package/dist/index.d.cts CHANGED
@@ -2,6 +2,7 @@ import { AsciiRenderOptions } from '@zombie-mermaid/ascii-renderer';
2
2
  import { ClassRenderOptions } from '@zombie-mermaid/core';
3
3
  import { CommonRenderOptions } from '@zombie-mermaid/core';
4
4
  import { createLayoutCache } from '@zombie-mermaid/svg-renderer';
5
+ import { DEFAULT_RENDER_LIMITS } from '@zombie-mermaid/core';
5
6
  import { DEFAULTS } from '@zombie-mermaid/core';
6
7
  import { DiagramColors } from '@zombie-mermaid/core';
7
8
  import { Direction } from '@zombie-mermaid/core';
@@ -11,11 +12,13 @@ import { ErRenderOptions } from '@zombie-mermaid/core';
11
12
  import { FlowchartRenderOptions } from '@zombie-mermaid/core';
12
13
  import { fromShikiTheme } from '@zombie-mermaid/core';
13
14
  import { LayoutCache } from '@zombie-mermaid/svg-renderer';
15
+ import { LimitExceededError } from '@zombie-mermaid/core';
14
16
  import { MermaidGraph } from '@zombie-mermaid/core';
15
17
  import { NodeInteraction } from '@zombie-mermaid/core';
16
18
  import { parseMermaid } from '@zombie-mermaid/mermaid-parser';
17
19
  import { PositionedGraph } from '@zombie-mermaid/core';
18
20
  import { registerElk } from '@zombie-mermaid/svg-renderer';
21
+ import { RenderLimits } from '@zombie-mermaid/core';
19
22
  import { renderMermaid } from '@zombie-mermaid/svg-renderer';
20
23
  import { renderMermaidASCII } from '@zombie-mermaid/ascii-renderer';
21
24
  import { renderMermaidAscii } from '@zombie-mermaid/ascii-renderer';
@@ -38,6 +41,8 @@ export { CommonRenderOptions }
38
41
 
39
42
  export { createLayoutCache }
40
43
 
44
+ export { DEFAULT_RENDER_LIMITS }
45
+
41
46
  export { DEFAULTS }
42
47
 
43
48
  export { DiagramColors }
@@ -56,6 +61,8 @@ export { fromShikiTheme }
56
61
 
57
62
  export { LayoutCache }
58
63
 
64
+ export { LimitExceededError }
65
+
59
66
  export { MermaidGraph }
60
67
 
61
68
  export { NodeInteraction }
@@ -66,6 +73,8 @@ export { PositionedGraph }
66
73
 
67
74
  export { registerElk }
68
75
 
76
+ export { RenderLimits }
77
+
69
78
  export { renderMermaid }
70
79
 
71
80
  export { renderMermaidASCII }
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import { AsciiRenderOptions } from '@zombie-mermaid/ascii-renderer';
2
2
  import { ClassRenderOptions } from '@zombie-mermaid/core';
3
3
  import { CommonRenderOptions } from '@zombie-mermaid/core';
4
4
  import { createLayoutCache } from '@zombie-mermaid/svg-renderer';
5
+ import { DEFAULT_RENDER_LIMITS } from '@zombie-mermaid/core';
5
6
  import { DEFAULTS } from '@zombie-mermaid/core';
6
7
  import { DiagramColors } from '@zombie-mermaid/core';
7
8
  import { Direction } from '@zombie-mermaid/core';
@@ -11,11 +12,13 @@ import { ErRenderOptions } from '@zombie-mermaid/core';
11
12
  import { FlowchartRenderOptions } from '@zombie-mermaid/core';
12
13
  import { fromShikiTheme } from '@zombie-mermaid/core';
13
14
  import { LayoutCache } from '@zombie-mermaid/svg-renderer';
15
+ import { LimitExceededError } from '@zombie-mermaid/core';
14
16
  import { MermaidGraph } from '@zombie-mermaid/core';
15
17
  import { NodeInteraction } from '@zombie-mermaid/core';
16
18
  import { parseMermaid } from '@zombie-mermaid/mermaid-parser';
17
19
  import { PositionedGraph } from '@zombie-mermaid/core';
18
20
  import { registerElk } from '@zombie-mermaid/svg-renderer';
21
+ import { RenderLimits } from '@zombie-mermaid/core';
19
22
  import { renderMermaid } from '@zombie-mermaid/svg-renderer';
20
23
  import { renderMermaidASCII } from '@zombie-mermaid/ascii-renderer';
21
24
  import { renderMermaidAscii } from '@zombie-mermaid/ascii-renderer';
@@ -38,6 +41,8 @@ export { CommonRenderOptions }
38
41
 
39
42
  export { createLayoutCache }
40
43
 
44
+ export { DEFAULT_RENDER_LIMITS }
45
+
41
46
  export { DEFAULTS }
42
47
 
43
48
  export { DiagramColors }
@@ -56,6 +61,8 @@ export { fromShikiTheme }
56
61
 
57
62
  export { LayoutCache }
58
63
 
64
+ export { LimitExceededError }
65
+
59
66
  export { MermaidGraph }
60
67
 
61
68
  export { NodeInteraction }
@@ -66,6 +73,8 @@ export { PositionedGraph }
66
73
 
67
74
  export { registerElk }
68
75
 
76
+ export { RenderLimits }
77
+
69
78
  export { renderMermaid }
70
79
 
71
80
  export { renderMermaidASCII }
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { DEFAULTS as e, THEMES as t, fromShikiTheme as n } from "@zombie-mermaid/core";
2
- import { parseMermaid as r } from "@zombie-mermaid/mermaid-parser";
3
- import { renderMermaidASCII as i, renderMermaidAscii as a } from "@zombie-mermaid/ascii-renderer";
4
- import { ElkNotRegisteredError as o, createLayoutCache as s, registerElk as c, renderMermaid as l, renderMermaidSVG as u, renderMermaidSVGAsync as d, renderMermaidSync as f, themeCssVariables as p, validateMermaid as m } from "@zombie-mermaid/svg-renderer";
5
- export { e as DEFAULTS, o as ElkNotRegisteredError, t as THEMES, s as createLayoutCache, n as fromShikiTheme, r as parseMermaid, c as registerElk, l as renderMermaid, i as renderMermaidASCII, a as renderMermaidAscii, u as renderMermaidSVG, d as renderMermaidSVGAsync, f as renderMermaidSync, p as themeCssVariables, m as validateMermaid };
1
+ import { DEFAULTS as e, DEFAULT_RENDER_LIMITS as t, LimitExceededError as n, THEMES as r, fromShikiTheme as i } from "@zombie-mermaid/core";
2
+ import { parseMermaid as a } from "@zombie-mermaid/mermaid-parser";
3
+ import { renderMermaidASCII as o, renderMermaidAscii as s } from "@zombie-mermaid/ascii-renderer";
4
+ import { ElkNotRegisteredError as c, createLayoutCache as l, registerElk as u, renderMermaid as d, renderMermaidSVG as f, renderMermaidSVGAsync as p, renderMermaidSync as m, themeCssVariables as h, validateMermaid as g } from "@zombie-mermaid/svg-renderer";
5
+ export { e as DEFAULTS, t as DEFAULT_RENDER_LIMITS, c as ElkNotRegisteredError, n as LimitExceededError, r as THEMES, l as createLayoutCache, i as fromShikiTheme, a as parseMermaid, u as registerElk, d as renderMermaid, o as renderMermaidASCII, s as renderMermaidAscii, f as renderMermaidSVG, p as renderMermaidSVGAsync, m as renderMermaidSync, h as themeCssVariables, g as validateMermaid };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zombie-mermaid",
3
- "version": "5.2.0",
3
+ "version": "5.3.0",
4
4
  "license": "MIT",
5
5
  "description": "Render Mermaid diagrams as beautiful SVGs or ASCII art. Ultra-fast, fully themeable, zero DOM dependencies. Maintained fork of beautiful-mermaid.",
6
6
  "type": "module",
@@ -90,14 +90,16 @@
90
90
  "@modelcontextprotocol/sdk": "^1.30.0",
91
91
  "elkjs": "^0.11.0",
92
92
  "entities": "^7.0.1",
93
- "@zombie-mermaid/ascii-renderer": "5.2.0",
94
- "@zombie-mermaid/core": "5.2.0",
95
- "@zombie-mermaid/mcp": "5.2.0",
96
- "@zombie-mermaid/svg-renderer": "5.2.0",
97
- "@zombie-mermaid/mermaid-parser": "5.2.0"
93
+ "@zombie-mermaid/ascii-renderer": "5.3.0",
94
+ "@zombie-mermaid/mermaid-parser": "5.3.0",
95
+ "@zombie-mermaid/mcp": "5.3.0",
96
+ "@zombie-mermaid/core": "5.3.0",
97
+ "@zombie-mermaid/svg-renderer": "5.3.0"
98
98
  },
99
99
  "devDependencies": {
100
+ "@arethetypeswrong/cli": "0.18.5",
100
101
  "@axe-core/playwright": "^4.13.0",
102
+ "@fast-check/vitest": "0.5.0",
101
103
  "@changesets/changelog-github": "^1.0.0",
102
104
  "@changesets/cli": "^3.0.1",
103
105
  "@microsoft/api-extractor": "^7.59.0",
@@ -114,12 +116,14 @@
114
116
  "esbuild": "^0.28.2",
115
117
  "eslint": "^10.9.1",
116
118
  "eslint-config-prettier": "^10.1.8",
119
+ "fast-check": "4.10.2",
117
120
  "fontkit": "^2.0.4",
118
121
  "jsdom": "^30.0.1",
119
122
  "lightningcss": "^1.33.0",
120
123
  "marked": "^18.0.11",
121
124
  "mermaid": "12.1.0",
122
125
  "prettier": "^3.9.6",
126
+ "publint": "0.3.25",
123
127
  "react": "^19.2.8",
124
128
  "react-dom": "^19.2.8",
125
129
  "shiki": "^3.19.0",
@@ -137,6 +141,7 @@
137
141
  },
138
142
  "scripts": {
139
143
  "test": "vitest run -c config/vitest.config.ts",
144
+ "test:shuffle": "vitest run -c config/vitest.config.ts --sequence.shuffle.files --sequence.shuffle.tests",
140
145
  "test:watch": "vitest -c config/vitest.config.ts",
141
146
  "test:coverage": "vitest run -c config/vitest.config.ts --coverage",
142
147
  "test:visual": "playwright test",
@@ -166,6 +171,7 @@
166
171
  "check:changesets": "tsx scripts/check-changesets.ts",
167
172
  "check:docs": "tsx scripts/check-docs.ts",
168
173
  "smoke:packed": "node scripts/smoke-test-packed.mjs",
174
+ "check:package-types": "scripts/check-package-types.sh",
169
175
  "check:bundle-size": "tsx scripts/check-bundle-size.ts",
170
176
  "generate:hero": "tsx scripts/generate-hero.ts",
171
177
  "build:mono-font": "tsx scripts/build-mono-font-subset.ts && prettier --write demo/components/generated/mono-font-subset.ts demo/styles.css packages/svg-renderer/src/generated/mono-font-subset.ts",