zombie-mermaid 4.2.3 → 5.0.1

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
@@ -54,21 +54,22 @@ automatically with every release:
54
54
  and `@zombie-mermaid/mermaid-parser`. It has no third-party dependencies, so
55
55
  this is what `zombie-mermaid/ascii` costs.
56
56
  - **svg-renderer (incl. deps)** — the SVG renderer, core and parser, **plus its
57
- third-party dependencies**. Nearly all of the weight is
58
- [ELK.js](https://github.com/kieler/elkjs), the layout engine: about 466 KB
59
- gzipped on its own, shipped as one pre-bundled file that can't be
60
- tree-shaken. `entities` is counted tree-shaken, since the renderer uses one
61
- function from it.
57
+ third-party dependencies**, reported two ways: the base figure, and the figure
58
+ with [ELK.js](https://github.com/kieler/elkjs) (the layout engine) registered.
59
+ ELK.js is an optional peer: about 466 KB gzipped on its own, one pre-bundled
60
+ file that can't be tree-shaken, and only shipped if your app registers it
61
+ (see [the migration guide](docs/guides/elkjs-optional-peer.md)). `entities` is
62
+ counted tree-shaken, since the renderer uses one function from it.
62
63
 
63
64
  Both figures gzip a plain concatenation of the built files, so they approximate
64
65
  what you'd ship, not what any particular bundler emits. The umbrella
65
66
  `zombie-mermaid` entry re-exports both renderers; its all-in total is
66
67
  [![All-in size](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/dfadler/zombie-mermaid/main/badges/bundle-size.json)](#bundle-size), the worst case. With a
67
68
  bundler, importing only `renderMermaidASCII` from the root drops the SVG
68
- renderer and ELK.js (every package here is `"sideEffects": false`). Without a
69
- bundler — Node, a CLI, a serverless function — the root entry loads ELK.js at
70
- startup even for ASCII-only use, so import from `zombie-mermaid/ascii` instead
71
- (see [ASCII Output](#ascii-output)).
69
+ renderer (every package here is `"sideEffects": false`), and the root entry no
70
+ longer includes ELK.js unless you register it. Without a bundler — Node, a CLI, a
71
+ serverless function — you can import from `zombie-mermaid/ascii` to skip loading
72
+ the SVG renderer at all (see [ASCII Output](#ascii-output)).
72
73
 
73
74
  ## Features
74
75
 
@@ -93,6 +94,10 @@ bun add zombie-mermaid
93
94
  pnpm add zombie-mermaid
94
95
  ```
95
96
 
97
+ > **Upgrading from 4.x?** `elkjs` is now an optional peer dependency: browser and
98
+ > bundler apps must call `registerElk(ELK)` once. See the
99
+ > [migration guide](docs/guides/elkjs-optional-peer.md).
100
+
96
101
  Only need one output format? `@zombie-mermaid/ascii-renderer` and `@zombie-mermaid/svg-renderer` are published standalone — see [Packages](#packages) below.
97
102
 
98
103
  ## Quick Start
@@ -112,6 +117,22 @@ const svg = renderMermaidSVG(`
112
117
 
113
118
  Rendering is **fully synchronous** — no `await`, no promises. The ELK.js layout engine runs synchronously via a FakeWorker bypass, so you get your SVG string instantly.
114
119
 
120
+ Flowchart, state, class, ER and architecture diagrams are laid out by
121
+ [`elkjs`](https://github.com/kieler/elkjs), an **optional peer dependency**.
122
+ Under Node and Bun it is loaded automatically. In a browser or bundler, register
123
+ it once (`npm install elkjs`):
124
+
125
+ ```typescript
126
+ import ELK from 'elkjs/lib/elk.bundled.js'
127
+ import { registerElk } from 'zombie-mermaid'
128
+
129
+ registerElk(ELK)
130
+ ```
131
+
132
+ Sequence, pie, xychart and C4 diagrams, and all ASCII output, need no `elkjs`
133
+ and no registration. Rendering a graph diagram with no `elkjs` available throws an
134
+ `ElkNotRegisteredError` that says how to fix it.
135
+
115
136
  Need async? Use `renderMermaidSVGAsync()` — same output, returns a `Promise<string>`.
116
137
 
117
138
  ### ASCII Output
@@ -131,10 +152,9 @@ const ascii = renderMermaidASCII(`graph LR; A --> B --> C`)
131
152
  ```
132
153
 
133
154
  ASCII-only consumers (a CLI, a terminal UI, a serverless function) can import
134
- from `zombie-mermaid/ascii` instead of the package root. The root entry
135
- statically pulls in `elkjs` for the SVG layout engine — over 1.4MB minified —
136
- even if you never call `renderMermaidSVG`. The `/ascii` subpath never imports
137
- it:
155
+ from `zombie-mermaid/ascii` instead of the package root. The root entry also
156
+ loads the SVG renderer (about 74 KB gzipped, plus `elkjs` only if you register
157
+ it); the `/ascii` subpath never touches either:
138
158
 
139
159
  ```typescript
140
160
  import { renderMermaidASCII } from 'zombie-mermaid/ascii'
@@ -234,7 +254,7 @@ the package.
234
254
 
235
255
  This repo is a pnpm-workspace monorepo. Most consumers only need the umbrella `zombie-mermaid` package above; internally it's built from workspace packages under `packages/`, all published under the `@zombie-mermaid` npm scope and version-locked with it:
236
256
 
237
- - **[`@zombie-mermaid/ascii-renderer`](packages/ascii-renderer)** — the ASCII/Unicode renderer, published standalone for anyone who wants terminal output without `svg-renderer`'s `elkjs` dependency. The exact code `zombie-mermaid/ascii` re-exports.
257
+ - **[`@zombie-mermaid/ascii-renderer`](packages/ascii-renderer)** — the ASCII/Unicode renderer, published standalone for anyone who wants terminal output without `svg-renderer` or `elkjs`. The exact code `zombie-mermaid/ascii` re-exports.
238
258
  [![npm](https://img.shields.io/npm/v/@zombie-mermaid/ascii-renderer.svg)](https://www.npmjs.com/package/@zombie-mermaid/ascii-renderer) [![gzip size](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/dfadler/zombie-mermaid/main/badges/bundle-size-ascii-renderer.json)](#bundle-size)
239
259
  - **[`@zombie-mermaid/svg-renderer`](packages/svg-renderer)** — the ELK.js-backed SVG layout and rendering engine, also published standalone.
240
260
  [![npm](https://img.shields.io/npm/v/@zombie-mermaid/svg-renderer.svg)](https://www.npmjs.com/package/@zombie-mermaid/svg-renderer) [![gzip size](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/dfadler/zombie-mermaid/main/badges/bundle-size-svg-renderer.json)](#bundle-size)
package/dist/cli.js CHANGED
@@ -5,11 +5,12 @@ import { THEMES as B, escapeXml as q, isDirection as j, isWideChar as K } from "
5
5
  import { access as J, readFile as Z, writeFile as Q } from "node:fs/promises";
6
6
  import { diagramColorsToAsciiTheme as ee, renderMermaidASCII as O } from "@zombie-mermaid/ascii-renderer";
7
7
  import "@zombie-mermaid/mermaid-parser";
8
- import { renderMermaidSVG as z } from "@zombie-mermaid/svg-renderer";
9
- import { createServer as te } from "node:http";
10
- import { StdioServerTransport as ne } from "@modelcontextprotocol/sdk/server/stdio.js";
11
- import { createMcpServer as re } from "@zombie-mermaid/mcp";
12
- var oe = 3e3;
8
+ import { registerElk as te, renderMermaidSVG as z } from "@zombie-mermaid/svg-renderer";
9
+ import { createServer as ne } from "node:http";
10
+ import { StdioServerTransport as re } from "@modelcontextprotocol/sdk/server/stdio.js";
11
+ import { createMcpServer as oe } from "@zombie-mermaid/mcp";
12
+ import ie from "elkjs/lib/elk.bundled.js";
13
+ var ae = 3e3;
13
14
  var W = {
14
15
  ".svg": "svg",
15
16
  ".txt": "ascii",
@@ -17,7 +18,7 @@ var W = {
17
18
  ".htm": "html",
18
19
  ".png": "png"
19
20
  };
20
- function ie(e) {
21
+ function se(e) {
21
22
  if (!(e === void 0 || e === "-"))
22
23
  return W[V(e).toLowerCase()];
23
24
  }
@@ -44,7 +45,7 @@ var v = {
44
45
  label: "the PNG rasterization"
45
46
  }
46
47
  }, A = Object.keys(v);
47
- function ae(e, n) {
48
+ function de(e, n) {
48
49
  const t = G(e);
49
50
  return H({
50
51
  dir: t.dir,
@@ -52,24 +53,24 @@ function ae(e, n) {
52
53
  ext: n
53
54
  });
54
55
  }
55
- function se(e) {
56
+ function ce(e) {
56
57
  const [n, ...t] = e;
57
58
  if (n === void 0) return { command: "help" };
58
59
  if (n === "--help" || n === "-h") return { command: "help" };
59
60
  if (n === "--version" || n === "-v") return { command: "version" };
60
61
  if (n === "themes") return { command: "themes" };
61
- if (n === "render") return le(t);
62
- if (n === "web") return me(t);
62
+ if (n === "render") return ue(t);
63
+ if (n === "web") return pe(t);
63
64
  if (n === "mcp") return { command: "mcp" };
64
65
  throw new Error(`Unknown command: ${n}`);
65
66
  }
66
- function P(e, n, t) {
67
+ function $(e, n, t) {
67
68
  const r = e[n + 1];
68
69
  if (n + 1 >= e.length || r === void 0) throw new Error(`${t} requires a numeric value`);
69
70
  if (!/^\d+$/.test(r)) throw new Error(`${t} requires a non-negative integer, got: "${r}"`);
70
71
  return Number(r);
71
72
  }
72
- function de(e, n, t) {
73
+ function le(e, n, t) {
73
74
  const r = e[n + 1];
74
75
  if (n + 1 >= e.length || r === void 0) throw new Error(`${t} requires a value ("auto" or a positive integer)`);
75
76
  if (r === "auto") return "auto";
@@ -77,14 +78,14 @@ function de(e, n, t) {
77
78
  if (!/^\d+$/.test(r) || s === 0 || !Number.isSafeInteger(s)) throw new Error(`${t} requires "auto" or a positive integer, got: "${r}"`);
78
79
  return s;
79
80
  }
80
- function ce(e, n, t) {
81
+ function me(e, n, t) {
81
82
  const r = e[n + 1];
82
83
  if (n + 1 >= e.length || r === void 0) throw new Error(`${t} requires a value (one of TD, TB, BT, LR, RL)`);
83
84
  const s = r.toUpperCase();
84
85
  if (!j(s)) throw new Error(`${t} requires one of TD, TB, BT, LR, RL, got: "${r}"`);
85
86
  return s;
86
87
  }
87
- function le(e) {
88
+ function ue(e) {
88
89
  let n, t = !1, r = !1, s = !1, m = !1, c = !1, d, E = !1, S, k, g, C, T = !1, b = !1, a, u, i = 0;
89
90
  for (; i < e.length; ) {
90
91
  const o = e[i];
@@ -108,19 +109,19 @@ function le(e) {
108
109
  if (i + 1 >= e.length) throw new Error("--theme requires a theme name");
109
110
  S = e[i + 1], i += 2;
110
111
  } else if (o === "-x" || o === "--paddingX")
111
- k = P(e, i, o), i += 2;
112
+ k = $(e, i, o), i += 2;
112
113
  else if (o === "-y" || o === "--paddingY")
113
- g = P(e, i, o), i += 2;
114
+ g = $(e, i, o), i += 2;
114
115
  else if (o === "-p" || o === "--borderPadding")
115
- C = P(e, i, o), i += 2;
116
+ C = $(e, i, o), i += 2;
116
117
  else if (o === "--coords")
117
118
  T = !0, i++;
118
119
  else if (o === "--hyperlinks")
119
120
  b = !0, i++;
120
121
  else if (o === "-w" || o === "--max-width")
121
- a = de(e, i, o), i += 2;
122
+ a = le(e, i, o), i += 2;
122
123
  else if (o === "--direction")
123
- u = ce(e, i, o), i += 2;
124
+ u = me(e, i, o), i += 2;
124
125
  else if (!o.startsWith("-") || o === "-") {
125
126
  if (o === "-") throw new Error("Unexpected argument: - (use -o - to write output to stdout; omit the input file to read stdin)");
126
127
  if (n !== void 0) throw new Error(`Unexpected argument: ${o} (input file already set to "${n}")`);
@@ -136,7 +137,7 @@ function le(e) {
136
137
  const [o, l] = w;
137
138
  throw new Error(`${v[o].flag} and ${v[l].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.`);
138
139
  }
139
- const p = ie(d);
140
+ const p = se(d);
140
141
  if (p !== void 0 && p !== "ascii") {
141
142
  const o = A.find((l) => l !== p && h[l]);
142
143
  if (o !== void 0) {
@@ -171,7 +172,7 @@ function le(e) {
171
172
  if (f !== void 0 && d === void 0) {
172
173
  const { flag: o, ext: l } = v[f];
173
174
  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`);
174
- d = ae(n, l);
175
+ d = de(n, l);
175
176
  }
176
177
  if (a !== void 0 && !t) throw new Error("-w/--max-width requires --ascii");
177
178
  if (b && !t) throw new Error("--hyperlinks requires --ascii");
@@ -196,13 +197,13 @@ function le(e) {
196
197
  direction: u
197
198
  };
198
199
  }
199
- function me(e) {
200
- let n = oe, t = 0;
200
+ function pe(e) {
201
+ let n = ae, t = 0;
201
202
  for (; t < e.length; ) {
202
203
  const r = e[t];
203
204
  if (r === void 0) throw new Error(`parseArgs: index ${t} out of range while parsing arguments`);
204
205
  if (r === "--port")
205
- n = P(e, t, r), t += 2;
206
+ n = $(e, t, r), t += 2;
206
207
  else throw new Error(`Unknown flag: ${r}`);
207
208
  }
208
209
  return {
@@ -210,33 +211,34 @@ function me(e) {
210
211
  port: n
211
212
  };
212
213
  }
213
- var ue = /\p{Mn}|\p{Me}/u;
214
- function pe(e) {
215
- return ue.test(e);
214
+ var he = /\p{Mn}|\p{Me}/u;
215
+ function fe(e) {
216
+ return he.test(e);
216
217
  }
217
- var he = new Intl.Segmenter(void 0, { granularity: "grapheme" }), fe = "️";
218
- function ge(e) {
218
+ var ge = new Intl.Segmenter(void 0, { granularity: "grapheme" }), ve = "️";
219
+ function we(e) {
220
+ if (/^[\x20-\x7e]*$/.test(e)) return e.split("");
219
221
  const n = [];
220
- for (const { segment: t } of he.segment(e)) n.push(t);
222
+ for (const { segment: t } of ge.segment(e)) n.push(t);
221
223
  return n;
222
224
  }
223
- function ve(e) {
224
- if (e.includes(fe)) return 2;
225
+ function be(e) {
226
+ if (e.includes(ve)) return 2;
225
227
  let n = !1, t = !1;
226
228
  for (const r of e)
227
- K(r) && (n = !0), pe(r) || (t = !0);
229
+ K(r) && (n = !0), fe(r) || (t = !0);
228
230
  return n ? 2 : t ? 1 : 0;
229
231
  }
230
- function we(e) {
232
+ function ye(e) {
231
233
  let n = 0;
232
- for (const t of ge(e)) n += ve(t);
234
+ for (const t of we(e)) n += be(t);
233
235
  return n;
234
236
  }
235
- var be = /\x1b\]8;[^\x07\x1b]*(?:\x1b\\|\x07)/g;
236
- function ye(e) {
237
- return e.replace(be, "");
237
+ var xe = /\x1b\]8;[^\x07\x1b]*(?:\x1b\\|\x07)/g;
238
+ function Ee(e) {
239
+ return e.replace(xe, "");
238
240
  }
239
- var xe = `// @ts-check
241
+ var Se = `// @ts-check
240
242
  /// <reference lib="dom" />
241
243
  // ============================================================================
242
244
  // Client script for the CLI's self-contained HTML viewer (\`render --html\`).
@@ -528,7 +530,7 @@ var xe = `// @ts-check
528
530
  fit()
529
531
  stage.focus({ preventScroll: true })
530
532
  })()
531
- `, Ee = `
533
+ `, ke = `
532
534
  :root {
533
535
  color-scheme: light dark;
534
536
  --bg: #f4f4f5;
@@ -635,7 +637,7 @@ var xe = `// @ts-check
635
637
  #diagram { position: static; transform: none !important; }
636
638
  }
637
639
  `.trim();
638
- function Se(e) {
640
+ function Ce(e) {
639
641
  const n = e.title?.trim() || "Mermaid diagram";
640
642
  return `<!doctype html>
641
643
  <html lang="en">
@@ -644,7 +646,7 @@ function Se(e) {
644
646
  <meta name="viewport" content="width=device-width, initial-scale=1" />
645
647
  <title>${q(n)}</title>
646
648
  <style>
647
- ${Ee}
649
+ ${ke}
648
650
  </style>
649
651
  </head>
650
652
  <body>
@@ -662,13 +664,13 @@ ${e.svg}
662
664
  <button id="theme" type="button" aria-pressed="false" aria-label="Switch to dark mode (T)">Dark</button>
663
665
  </div>
664
666
  <script>
665
- ${xe}
667
+ ${Se}
666
668
  <\/script>
667
669
  </body>
668
670
  </html>
669
671
  `;
670
672
  }
671
- async function ke(e) {
673
+ async function Te(e) {
672
674
  let n;
673
675
  try {
674
676
  n = await import("@resvg/resvg-js");
@@ -679,22 +681,22 @@ ${r}`);
679
681
  }
680
682
  return (await n.renderAsync(e)).asPng();
681
683
  }
682
- var Ce = 80, $ = 1, L = 1, R = 0, Te = /\x1b\[[0-9;]*m/g;
684
+ var Ae = 80, P = 1, L = 1, R = 0, Ie = /\x1b\[[0-9;]*m/g;
683
685
  function D(e) {
684
686
  return e.split(`
685
- `).reduce((n, t) => Math.max(n, we(ye(t.replace(Te, "")))), 0);
687
+ `).reduce((n, t) => Math.max(n, ye(Ee(t.replace(Ie, "")))), 0);
686
688
  }
687
- function Ae(e) {
688
- return e !== "auto" ? e : process.stdout.columns ?? Ce;
689
+ function Me(e) {
690
+ return e !== "auto" ? e : process.stdout.columns ?? Ae;
689
691
  }
690
- async function Ie(e, n, t, r) {
692
+ async function ze(e, n, t, r) {
691
693
  const s = n ?? process.stdout, m = r ?? process.stderr;
692
694
  let c;
693
695
  if (e.input !== void 0) c = await Z(e.input, "utf-8");
694
696
  else if (t !== void 0) c = t;
695
697
  else {
696
698
  if (process.stdin.isTTY) throw new Error("No input file specified and stdin is a terminal. Pipe a diagram or pass a file path.");
697
- c = await Pe();
699
+ c = await Le();
698
700
  }
699
701
  if (c = c.trim(), c.length === 0) throw new Error("Empty input — provide a Mermaid diagram via file or stdin");
700
702
  let d;
@@ -708,7 +710,7 @@ async function Ie(e, n, t, r) {
708
710
  C,
709
711
  T,
710
712
  b
711
- ]) a !== void 0 && await Me(a, e.force);
713
+ ]) a !== void 0 && await $e(a, e.force);
712
714
  if (e.ascii) {
713
715
  const a = d && g === void 0 ? {
714
716
  colorMode: "auto",
@@ -717,10 +719,10 @@ async function Ie(e, n, t, r) {
717
719
  e.paddingX !== void 0 && (a.paddingX = e.paddingX), e.paddingY !== void 0 && (a.paddingY = e.paddingY), e.borderPadding !== void 0 && (a.boxBorderPadding = e.borderPadding), e.coords && (a.showCoords = !0), e.direction !== void 0 && (a.direction = e.direction), e.hyperlinks && g === void 0 && (a.hyperlinks = !0);
718
720
  let u = O(c, a);
719
721
  if (e.maxWidth !== void 0) {
720
- const i = Ae(e.maxWidth);
722
+ const i = Me(e.maxWidth);
721
723
  let h = D(u), w = !1;
722
724
  if (h > i) {
723
- const p = a.paddingX ?? 5, y = a.paddingY ?? 5, f = a.boxBorderPadding ?? 1, o = Math.min(p, $), l = Math.min(y, L), x = Math.min(f, R);
725
+ const p = a.paddingX ?? 5, y = a.paddingY ?? 5, f = a.boxBorderPadding ?? 1, o = Math.min(p, P), l = Math.min(y, L), x = Math.min(f, R);
724
726
  if (o < p || l < y || x < f) {
725
727
  const _ = O(c, {
726
728
  ...a,
@@ -732,10 +734,10 @@ async function Ie(e, n, t, r) {
732
734
  }
733
735
  }
734
736
  if (h > i) {
735
- const p = e.maxWidth === "auto" ? "detected terminal width" : "--max-width", y = w ? `Compact spacing (-x ${$} -y ${L} -p ${R}) was already applied automatically. ` : "", f = w ? "Try a narrower direction (LR vs TD), shorter labels, or widen your terminal." : "Try -x/-y/-p for tighter spacing, a narrower direction (LR vs TD), or widen your terminal.";
737
+ const p = e.maxWidth === "auto" ? "detected terminal width" : "--max-width", y = w ? `Compact spacing (-x ${P} -y ${L} -p ${R}) was already applied automatically. ` : "", f = w ? "Try a narrower direction (LR vs TD), shorter labels, or widen your terminal." : "Try -x/-y/-p for tighter spacing, a narrower direction (LR vs TD), or widen your terminal.";
736
738
  m.write(`Warning: ASCII output is ${h} columns wide, exceeding ${p} of ${i}. ${y}zombie-mermaid does not reflow diagram structure to fit (no label wrapping or direction-flip cascade — see https://github.com/dfadler/zombie-mermaid/issues/335). ${f}
737
739
  `);
738
- } else w && m.write(`Note: ASCII output exceeded ${i} columns at the requested spacing; applied compact spacing automatically (-x ${$} -y ${L} -p ${R}) to fit.
740
+ } else w && m.write(`Note: ASCII output exceeded ${i} columns at the requested spacing; applied compact spacing automatically (-x ${P} -y ${L} -p ${R}) to fit.
739
741
  `);
740
742
  }
741
743
  await M(I(g === void 0, g), u + `
@@ -751,7 +753,7 @@ async function Ie(e, n, t, r) {
751
753
  await M(I(E, C), u, s, e.force);
752
754
  }
753
755
  if (e.html) {
754
- const a = z(c, d ?? {}), u = e.input ? G(e.input).name : void 0, i = Se({
756
+ const a = z(c, d ?? {}), u = e.input ? G(e.input).name : void 0, i = Ce({
755
757
  svg: a,
756
758
  title: u
757
759
  });
@@ -763,7 +765,7 @@ async function Ie(e, n, t, r) {
763
765
  resolveColors: !0
764
766
  };
765
767
  e.direction !== void 0 && (a.direction = e.direction);
766
- const u = z(c, a), i = await ke(u);
768
+ const u = z(c, a), i = await Te(u);
767
769
  await M(I(k, b), i, s, e.force);
768
770
  }
769
771
  }
@@ -779,13 +781,13 @@ async function M(e, n, t, r) {
779
781
  t.write(n);
780
782
  break;
781
783
  case "file":
782
- await ze(e.path, n, r);
784
+ await Pe(e.path, n, r);
783
785
  }
784
786
  }
785
787
  function X(e) {
786
788
  return /* @__PURE__ */ new Error(`Refusing to overwrite existing file "${e}" — pass --force to replace it`);
787
789
  }
788
- async function Me(e, n) {
790
+ async function $e(e, n) {
789
791
  if (n) return;
790
792
  let t = !0;
791
793
  try {
@@ -795,7 +797,7 @@ async function Me(e, n) {
795
797
  }
796
798
  if (t) throw X(e);
797
799
  }
798
- async function ze(e, n, t) {
800
+ async function Pe(e, n, t) {
799
801
  try {
800
802
  await Q(e, n, {
801
803
  encoding: "utf-8",
@@ -805,19 +807,19 @@ async function ze(e, n, t) {
805
807
  throw !t && r instanceof Error && "code" in r && r.code === "EEXIST" ? X(e) : r;
806
808
  }
807
809
  }
808
- async function Pe() {
810
+ async function Le() {
809
811
  const e = [], n = process.stdin;
810
812
  return n.setEncoding("utf-8"), new Promise((t, r) => {
811
813
  n.on("data", (s) => e.push(s)), n.on("end", () => t(e.join(""))), n.on("error", r);
812
814
  });
813
815
  }
814
- var $e = 1e6;
815
- function Le(e) {
816
+ var Re = 1e6;
817
+ function Be(e) {
816
818
  return new Promise((n, t) => {
817
819
  const r = [];
818
820
  let s = 0;
819
821
  e.on("data", (m) => {
820
- if (s += m.length, s > $e) {
822
+ if (s += m.length, s > Re) {
821
823
  t(/* @__PURE__ */ new Error("Request body too large")), e.destroy();
822
824
  return;
823
825
  }
@@ -828,7 +830,7 @@ function Le(e) {
828
830
  function Y(e) {
829
831
  return typeof e == "object" && e !== null;
830
832
  }
831
- function Re(e) {
833
+ function Oe(e) {
832
834
  let n;
833
835
  try {
834
836
  n = JSON.parse(e);
@@ -850,9 +852,9 @@ function F(e, n, t) {
850
852
  "Content-Length": Buffer.byteLength(r)
851
853
  }), e.end(r);
852
854
  }
853
- async function Be(e, n) {
855
+ async function _e(e, n) {
854
856
  try {
855
- const { source: t, format: r } = Re(await Le(e));
857
+ const { source: t, format: r } = Oe(await Be(e));
856
858
  F(n, 200, {
857
859
  output: r === "svg" ? z(t) : O(t),
858
860
  format: r
@@ -861,7 +863,7 @@ async function Be(e, n) {
861
863
  F(n, 400, { error: t instanceof Error ? t.message : String(t) });
862
864
  }
863
865
  }
864
- var Oe = `<!doctype html>
866
+ var Ne = `<!doctype html>
865
867
  <html lang="en">
866
868
  <head>
867
869
  <meta charset="utf-8" />
@@ -927,55 +929,56 @@ var Oe = `<!doctype html>
927
929
  </body>
928
930
  </html>
929
931
  `;
930
- function _e() {
931
- return te((e, n) => {
932
+ function De() {
933
+ return ne((e, n) => {
932
934
  const t = (e.url ?? "/").split("?")[0];
933
935
  if (e.method === "GET" && (t === "/" || t === "")) {
934
- n.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }), n.end(Oe);
936
+ n.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }), n.end(Ne);
935
937
  return;
936
938
  }
937
939
  if (e.method === "POST" && t === "/render") {
938
- Be(e, n);
940
+ _e(e, n);
939
941
  return;
940
942
  }
941
943
  n.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" }), n.end("Not found");
942
944
  });
943
945
  }
944
- function Ne(e) {
946
+ function Fe(e) {
945
947
  return new Promise((n, t) => {
946
- const r = _e();
948
+ const r = De();
947
949
  r.once("error", t), r.listen(e, "127.0.0.1", () => {
948
950
  r.removeListener("error", t), n(r);
949
951
  });
950
952
  });
951
953
  }
952
- async function De(e, n = console.log) {
953
- const t = await Ne(e.port), r = t.address();
954
+ async function Ge(e, n = console.log) {
955
+ const t = await Fe(e.port), r = t.address();
954
956
  return n(`zombie-mermaid web running at http://localhost:${Y(r) && typeof r.port == "number" ? r.port : e.port}`), t;
955
957
  }
956
- async function Fe(e = (n) => console.error(n)) {
957
- const n = re(), t = new ne();
958
+ async function We(e = (n) => console.error(n)) {
959
+ const n = oe(), t = new re();
958
960
  return await n.connect(t), e("zombie-mermaid MCP server running on stdio (experimental — feedback welcome: https://github.com/dfadler/zombie-mermaid/issues)"), n;
959
961
  }
960
- function Ge() {
962
+ function Xe() {
961
963
  const e = U(import.meta.url)("../package.json");
962
964
  return typeof e == "object" && e !== null && "version" in e && typeof e.version == "string" ? e.version : "unknown";
963
965
  }
964
- var We = Ge();
965
- async function Xe() {
966
+ te(ie);
967
+ var Ye = Xe();
968
+ async function Ue() {
966
969
  const e = process.argv.slice(2);
967
970
  let n;
968
971
  try {
969
- n = se(e);
972
+ n = ce(e);
970
973
  } catch (t) {
971
974
  console.error(`Error: ${t instanceof Error ? t.message : String(t)}`), process.exit(1);
972
975
  }
973
976
  switch (n.command) {
974
977
  case "help":
975
- Ye();
978
+ Ve();
976
979
  break;
977
980
  case "version":
978
- console.log(`zombie-mermaid ${We}`);
981
+ console.log(`zombie-mermaid ${Ye}`);
979
982
  break;
980
983
  case "themes":
981
984
  console.log(`Available themes:
@@ -984,27 +987,27 @@ async function Xe() {
984
987
  break;
985
988
  case "render":
986
989
  try {
987
- await Ie(n);
990
+ await ze(n);
988
991
  } catch (t) {
989
992
  console.error(`Error: ${t instanceof Error ? t.message : String(t)}`), process.exit(1);
990
993
  }
991
994
  break;
992
995
  case "web":
993
996
  try {
994
- await De(n);
997
+ await Ge(n);
995
998
  } catch (t) {
996
999
  console.error(`Error: ${t instanceof Error ? t.message : String(t)}`), process.exit(1);
997
1000
  }
998
1001
  break;
999
1002
  case "mcp":
1000
1003
  try {
1001
- await Fe();
1004
+ await We();
1002
1005
  } catch (t) {
1003
1006
  console.error(`Error: ${t instanceof Error ? t.message : String(t)}`), process.exit(1);
1004
1007
  }
1005
1008
  }
1006
1009
  }
1007
- function Ye() {
1010
+ function Ve() {
1008
1011
  console.log(`
1009
1012
  zombie-mermaid — render Mermaid diagrams from the command line
1010
1013
 
@@ -1078,7 +1081,7 @@ Options:
1078
1081
  -v, --version Show version
1079
1082
  `.trim());
1080
1083
  }
1081
- Xe();
1084
+ Ue();
1082
1085
  export {
1083
- Xe as main
1086
+ Ue as main
1084
1087
  };
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,"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,"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}});
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}});
package/dist/index.d.cts CHANGED
@@ -5,6 +5,8 @@ import { createLayoutCache } from '@zombie-mermaid/svg-renderer';
5
5
  import { DEFAULTS } from '@zombie-mermaid/core';
6
6
  import { DiagramColors } from '@zombie-mermaid/core';
7
7
  import { Direction } from '@zombie-mermaid/core';
8
+ import { ElkConstructor } from '@zombie-mermaid/core';
9
+ import { ElkNotRegisteredError } from '@zombie-mermaid/svg-renderer';
8
10
  import { ErRenderOptions } from '@zombie-mermaid/core';
9
11
  import { FlowchartRenderOptions } from '@zombie-mermaid/core';
10
12
  import { fromShikiTheme } from '@zombie-mermaid/core';
@@ -13,6 +15,7 @@ import { MermaidGraph } from '@zombie-mermaid/core';
13
15
  import { NodeInteraction } from '@zombie-mermaid/core';
14
16
  import { parseMermaid } from '@zombie-mermaid/mermaid-parser';
15
17
  import { PositionedGraph } from '@zombie-mermaid/core';
18
+ import { registerElk } from '@zombie-mermaid/svg-renderer';
16
19
  import { renderMermaid } from '@zombie-mermaid/svg-renderer';
17
20
  import { renderMermaidASCII } from '@zombie-mermaid/ascii-renderer';
18
21
  import { renderMermaidAscii } from '@zombie-mermaid/ascii-renderer';
@@ -40,6 +43,10 @@ export { DiagramColors }
40
43
 
41
44
  export { Direction }
42
45
 
46
+ export { ElkConstructor }
47
+
48
+ export { ElkNotRegisteredError }
49
+
43
50
  export { ErRenderOptions }
44
51
 
45
52
  export { FlowchartRenderOptions }
@@ -56,6 +63,8 @@ export { parseMermaid }
56
63
 
57
64
  export { PositionedGraph }
58
65
 
66
+ export { registerElk }
67
+
59
68
  export { renderMermaid }
60
69
 
61
70
  export { renderMermaidASCII }