zombie-mermaid 3.0.0 → 3.1.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
@@ -18,7 +18,7 @@ Ultra-fast, fully themeable, zero DOM dependencies. A maintained fork of [`beaut
18
18
  [![CI](https://github.com/dfadler/zombie-mermaid/actions/workflows/ci.yml/badge.svg)](https://github.com/dfadler/zombie-mermaid/actions/workflows/ci.yml)
19
19
  [![codecov](https://codecov.io/gh/dfadler/zombie-mermaid/branch/main/graph/badge.svg)](https://codecov.io/gh/dfadler/zombie-mermaid)
20
20
  [![Bundle Size](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/dfadler/zombie-mermaid/main/badges/bundle-size.json)](#bundle-size)
21
- [![Socket Security](https://socket.dev/api/badge/npm/package/zombie-mermaid)](https://socket.dev/npm/package/zombie-mermaid)
21
+ [![Socket Security](https://badge.socket.dev/npm/package/zombie-mermaid)](https://socket.dev/npm/package/zombie-mermaid)
22
22
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
23
23
 
24
24
  </div>
@@ -47,9 +47,12 @@ Diagrams are essential for AI-assisted programming. When you're working with an
47
47
  ### Bundle Size
48
48
 
49
49
  The **Bundle Size** badge above tracks the gzipped size of `zombie-mermaid`'s
50
- main entry point (`dist/index.js`) and updates automatically with every
51
- release — the same badge/CI-tracked pattern already backing the coverage and
52
- CI status badges. Need ASCII rendering only? `import { renderMermaidASCII }
50
+ main entry point (`dist/index.js`) together with the `@zombie-mermaid/*`
51
+ workspace packages it imports (third-party dependencies such as ELK.js are not
52
+ counted), and updates automatically with every release — the same
53
+ badge/CI-tracked pattern already backing the coverage and CI status badges.
54
+ The standalone renderer packages under [Packages](#packages) get the same
55
+ measurement for their own dependency closure. Need ASCII rendering only? `import { renderMermaidASCII }
53
56
  from 'zombie-mermaid/ascii'` skips [ELK.js](https://github.com/kieler/elkjs),
54
57
  the layout engine the SVG renderer depends on, for a substantially smaller
55
58
  bundle.
@@ -77,6 +80,8 @@ bun add zombie-mermaid
77
80
  pnpm add zombie-mermaid
78
81
  ```
79
82
 
83
+ Only need one output format? `@zombie-mermaid/ascii-renderer` and `@zombie-mermaid/svg-renderer` are published standalone — see [Packages](#packages) below.
84
+
80
85
  ## Quick Start
81
86
 
82
87
  ### SVG Output
@@ -163,7 +168,7 @@ hyperlinks — off by default, since terminal and pager support varies (see
163
168
 
164
169
  > 🧪 **Experimental — shipped to gauge interest, not a finished or best-effort implementation.** This is a first cut covering the common case; the tool surface may change based on feedback. Try it and [open an issue](https://github.com/dfadler/zombie-mermaid/issues/new) with what you'd want from it.
165
170
 
166
- `zombie-mermaid mcp` starts a [Model Context Protocol](https://modelcontextprotocol.io/) server on stdio, exposing the library's rendering as four tools: `render_mermaid_svg`, `render_mermaid_ascii`, `check_mermaid_sequence_activations`, and `fix_mermaid_sequence_activations`. Point an MCP client (Claude Desktop, Claude Code, or anything else that speaks MCP) at it to render Mermaid diagrams directly in a conversation, without shelling out to the CLI or importing the library.
171
+ `zombie-mermaid mcp` starts a [Model Context Protocol](https://modelcontextprotocol.io/) server on stdio, exposing the library's rendering as six tools: `render_mermaid_svg`, `render_mermaid_ascii`, `check_mermaid_sequence_activations`, `fix_mermaid_sequence_activations`, `list_themes`, and `list_diagram_types`. `render_mermaid_svg` also takes optional `bg`/`fg` hex color overrides (applied on top of `theme`) and an optional `outputPath` that writes the SVG to disk and returns `{ saved, size }` instead of the SVG text. `outputPath` must end in `.svg` and resolve inside the server's working directory (the directory your MCP client launched it from); its parent directory must already exist, symlinks and non-regular files are refused, and an existing `.svg` file at that path is overwritten. Point an MCP client (Claude Desktop, Claude Code, or anything else that speaks MCP) at it to render Mermaid diagrams directly in a conversation, without shelling out to the CLI or importing the library.
167
172
 
168
173
  Example Claude Desktop / Claude Code MCP server config:
169
174
 
@@ -212,6 +217,20 @@ the package.
212
217
 
213
218
  ---
214
219
 
220
+ ## Packages
221
+
222
+ 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:
223
+
224
+ - **[`@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.
225
+ [![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)
226
+ - **[`@zombie-mermaid/svg-renderer`](packages/svg-renderer)** — the ELK.js-backed SVG layout and rendering engine, also published standalone.
227
+ [![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)
228
+ - `@zombie-mermaid/core`, `@zombie-mermaid/mermaid-parser`, `@zombie-mermaid/mcp` — shared types/theming, the diagram parsers, and the MCP server implementation, respectively. Published under the scope (so the names can't be squatted) and version-locked with the rest, but internal-only: no standalone support commitment beyond backing the umbrella and the two renderer packages above.
229
+
230
+ See [docs/decisions/monorepo-conversion.md](docs/decisions/monorepo-conversion.md) for the full package-split and publish-strategy history.
231
+
232
+ ---
233
+
215
234
  ## Docs
216
235
 
217
236
  - [Guides](docs/guides/) — task-oriented walkthroughs: [browsing the samples](docs/guides/samples.md), [choosing a theme](docs/guides/theming.md), [using the HTML viewer](docs/guides/html-viewer.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zombie-mermaid",
3
- "version": "3.0.0",
3
+ "version": "3.1.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,11 +90,11 @@
90
90
  "@modelcontextprotocol/sdk": "^1.30.0",
91
91
  "elkjs": "^0.11.0",
92
92
  "entities": "^7.0.1",
93
- "@zombie-mermaid/ascii-renderer": "3.0.0",
94
- "@zombie-mermaid/core": "3.0.0",
95
- "@zombie-mermaid/mcp": "3.0.0",
96
- "@zombie-mermaid/mermaid-parser": "3.0.0",
97
- "@zombie-mermaid/svg-renderer": "3.0.0"
93
+ "@zombie-mermaid/ascii-renderer": "3.1.0",
94
+ "@zombie-mermaid/core": "3.1.0",
95
+ "@zombie-mermaid/svg-renderer": "3.1.0",
96
+ "@zombie-mermaid/mermaid-parser": "3.1.0",
97
+ "@zombie-mermaid/mcp": "3.1.0"
98
98
  },
99
99
  "devDependencies": {
100
100
  "@changesets/changelog-github": "^1.0.0",
@@ -293,6 +293,33 @@ describe('renderMermaidSVG – custom class names on rendered elements', () => {
293
293
  expect(svg).toContain('<g class="node highlight" data-id="B"')
294
294
  })
295
295
 
296
+ // Upstream lukilabs/beautiful-mermaid#81: a className with no matching
297
+ // classDef must still reach the `class` attribute so consumers can style it
298
+ // with their own CSS.
299
+ it('emits class names from `:::` and `class X name` even with no classDef', () => {
300
+ const svg = renderMermaidSVG(`graph LR
301
+ A[Start]:::foo --> B[End]
302
+ A --> C[Other]
303
+ class B bar`)
304
+ expect(svg).toContain('<g class="node foo" data-id="A"')
305
+ expect(svg).toContain('<g class="node bar" data-id="B"')
306
+ expect(svg).toContain('<g class="node" data-id="C"')
307
+ })
308
+
309
+ it('drops class names that are not valid CSS identifiers instead of emitting them', () => {
310
+ const svg = renderMermaidSVG(`graph LR
311
+ A --> B
312
+ A --> C
313
+ class A 1bad
314
+ class B foo.bar
315
+ class C ok_name`)
316
+ expect(svg).toContain('<g class="node" data-id="A"')
317
+ expect(svg).toContain('<g class="node" data-id="B"')
318
+ expect(svg).toContain('<g class="node ok_name" data-id="C"')
319
+ expect(svg).not.toContain('1bad')
320
+ expect(svg).not.toContain('foo.bar')
321
+ })
322
+
296
323
  it('renders only the base class when no custom class is assigned (no regression)', () => {
297
324
  const svg = renderMermaidSVG('graph LR\n A[Start] --> B[End]')
298
325
  expect(svg).toContain('<g class="node" data-id="A"')
@@ -163,7 +163,10 @@ describe('edge curve styles (#198 row 9)', () => {
163
163
  * diagram traces the path Mermaid would draw, so an approximation that
164
164
  * merely looks smooth is still wrong. These values were taken from
165
165
  * d3-shape 3.2.0's own `curveBasis` output for the same points — d3
166
- * serializes at 3 decimals, hence the rounding.
166
+ * serializes at 3 decimals; `pointsToPath` itself now rounds every
167
+ * coordinate to 2 decimals via the `f` tagged template (ported from
168
+ * lukilabs/beautiful-mermaid#77), so the expected values below are d3's
169
+ * reference geometry rounded to that same coarser precision.
167
170
  *
168
171
  * An earlier implementation led in at the midpoint `(p0 + p1) / 2` and
169
172
  * emitted a single cubic ending at `(p1 + p2) / 2`; it satisfied every
@@ -172,15 +175,15 @@ describe('edge curve styles (#198 row 9)', () => {
172
175
  it('matches d3 curveBasis geometry exactly', () => {
173
176
  const round = (d: string) =>
174
177
  (d.match(/[MLC]|-?\d+(?:\.\d+)?/g) ?? []).map((t) =>
175
- /[MLC]/.test(t) ? t : +(+t).toFixed(3),
178
+ /[MLC]/.test(t) ? t : +(+t).toFixed(2),
176
179
  )
177
180
 
178
181
  // prettier-ignore
179
182
  expect(round(pointsToPath(points, 'basis'))).toEqual([
180
183
  'M', 0, 0,
181
- 'L', 1.667, 1.667,
182
- 'C', 3.333, 3.333, 6.667, 6.667, 10, 6.667,
183
- 'C', 13.333, 6.667, 16.667, 3.333, 18.333, 1.667,
184
+ 'L', 1.67, 1.67,
185
+ 'C', 3.33, 3.33, 6.67, 6.67, 10, 6.67,
186
+ 'C', 13.33, 6.67, 16.67, 3.33, 18.33, 1.67,
184
187
  'L', 20, 0,
185
188
  ])
186
189
  })