` inside the paragraph: the text after the colon
+ disappeared and React threw a hydration error. Unknown text directives now go
+ back to literal text, in both `
` and the per-page Markdown output.
+
## [0.5.0] — 2026-08-30
### Added
diff --git a/README.md b/README.md
index b8f7d2d..73c7035 100644
--- a/README.md
+++ b/README.md
@@ -79,6 +79,7 @@ To embed the engine in an existing Next.js app or build a custom theme from scra
| **AI ask-box** | BYO model (Anthropic, OpenAI, or Google) and API key. Answers are grounded in your actual content with cited sources. |
| **`/llms.txt` out of the box** | The [llms.txt](https://llmstxt.org) convention — a curated index and full-corpus export for LLMs and agentic tools. |
| **Full-text search** | [Pagefind](https://pagefind.app/) indexes your built HTML at deploy time. Fast, client-side, no server required. |
+| **Diagrams** | ` ```mermaid ` fences become zoomable, pannable diagrams themed to your site — with a fullscreen view, minimap, and SVG download. Mermaid only loads on pages that have one. |
| **Blog & changelog** | Drop files in `content/blog/` or `content/changelog/` — routes and nav links appear automatically. |
| **Own your deployment** | A normal Next.js app. Ship to Vercel, AWS Amplify, a container, or a subpath on an existing site. |
| **Genuinely open** | MIT licensed. No telemetry, no required account, no lock-in. |
diff --git a/examples/inkform-docs/content/docs/docs.json b/examples/inkform-docs/content/docs/docs.json
index a6999e7..96b0ec8 100644
--- a/examples/inkform-docs/content/docs/docs.json
+++ b/examples/inkform-docs/content/docs/docs.json
@@ -35,6 +35,7 @@
{ "title": "Add a Blog to an Existing Site", "slug": "guides/blog-in-existing-site", "file": "guides/blog-in-existing-site.mdx", "icon": "layers" },
{ "title": "Changelog", "slug": "guides/changelog", "file": "guides/changelog.mdx", "icon": "map" },
{ "title": "Widgets", "slug": "guides/widgets", "file": "guides/widgets.mdx", "icon": "blocks" },
+ { "title": "Diagrams", "slug": "guides/diagrams", "file": "guides/diagrams.mdx", "icon": "image" },
{ "title": "Comments, Reactions & Subscribe Forms", "slug": "guides/interactive", "file": "guides/interactive.mdx", "icon": "heart" },
{ "title": "Claude Code Skill", "slug": "guides/claude-code-skill", "file": "guides/claude-code-skill.mdx", "icon": "sparkles" }
]
diff --git a/examples/inkform-docs/content/docs/guides/diagrams.mdx b/examples/inkform-docs/content/docs/guides/diagrams.mdx
new file mode 100644
index 0000000..015a09e
--- /dev/null
+++ b/examples/inkform-docs/content/docs/guides/diagrams.mdx
@@ -0,0 +1,182 @@
+---
+title: Diagrams
+description: Mermaid diagrams in any MDX page — written as a fenced code block, rendered as a zoomable, pannable figure.
+---
+
+# Diagrams
+
+Write a fenced code block with the language set to `mermaid` and it renders as a diagram:
+
+````md
+```mermaid
+flowchart LR
+ Draft --> Review --> Publish
+```
+````
+
+```mermaid title="The smallest useful diagram"
+flowchart LR
+ Draft --> Review --> Publish
+```
+
+Hover a diagram (or tab to it) for the toolbar: zoom, copy the source, download an SVG, or open it fullscreen. In fullscreen there's a minimap for finding your way around large graphs.
+
+## Setup
+
+Diagrams are opt-in, because `mermaid` is a large install and plenty of docs sites never draw one. The scaffolded templates already have it on. For an existing site:
+
+```bash
+npm i mermaid
+```
+
+```ts
+// mdx-components.tsx
+import { mdxComponents } from '@inkform/framework/components';
+import { Mermaid } from '@inkform/framework/mermaid';
+
+export const siteMdxComponents = mdxComponents({ Mermaid });
+```
+
+Without that registration, `mermaid` fences still build — they render as a plain block of source, so nothing breaks while you decide.
+
+Readers only download mermaid on pages that have a diagram, and only when one is about to scroll into view. Pages without diagrams ship none of it.
+
+## Captions
+
+Put `title="…"` (or `caption="…"`) after the language. It shows under the diagram, names the fullscreen view and the downloaded file, and is what screen readers announce.
+
+````md
+```mermaid title="Request lifecycle"
+sequenceDiagram
+ ...
+```
+````
+
+```mermaid title="Request lifecycle"
+sequenceDiagram
+ participant B as Browser
+ participant E as Edge
+ participant A as App
+ participant D as Database
+ B->>E: GET /docs/quickstart
+ E->>E: Cache lookup
+ alt cache hit
+ E-->>B: 200 (cached HTML)
+ else cache miss
+ E->>A: Render page
+ A->>D: Load content
+ D-->>A: MDX source
+ A-->>E: HTML
+ E-->>B: 200
+ end
+```
+
+The JSX form works too, if you're building the source in an expression:
+
+```mdx
+ B`} />
+```
+
+## Moving around
+
+| Where | Zoom | Pan |
+| --- | --- | --- |
+| In the page | Ctrl /⌘ + scroll, trackpad pinch, double-click, or `+` / `-` | Drag once zoomed in, or arrow keys |
+| Fullscreen | Scroll, pinch, double-click | Drag, arrow keys, or click the minimap |
+| Touch | Pinch | One finger once zoomed in |
+
+A plain scroll over an inline diagram scrolls the page, not the diagram, so long posts don't trap the reader. `0` resets to fit.
+
+## Theming
+
+Diagrams take their colors from the site's `--fw-*` tokens, so they match whichever theme you run, and they redraw when the reader switches between light and dark. Styles written in the diagram itself (`style A fill:#111,color:#fff`) still win.
+
+## Big graphs
+
+Large diagrams are where the viewer earns its keep. Open this one fullscreen and use the minimap:
+
+```mermaid title="Content pipeline, end to end"
+flowchart TD
+ subgraph Authoring
+ A1[Write MDX] --> A2[Preview locally]
+ A2 --> A3{Looks right?}
+ A3 -- no --> A1
+ A3 -- yes --> A4[Open PR]
+ end
+ subgraph Review
+ A4 --> R1[CI: typecheck + tests]
+ R1 --> R2[CI: link check]
+ R2 --> R3[Preview deploy]
+ R3 --> R4{Approved?}
+ R4 -- changes --> A1
+ end
+ subgraph Build
+ R4 -- merge --> B1[Load content]
+ B1 --> B2[Parse frontmatter]
+ B2 --> B3[Compile MDX]
+ B3 --> B4[Highlight code]
+ B3 --> B5[Collect headings]
+ B5 --> B6[Build TOC]
+ B1 --> B7[Parse OpenAPI]
+ B7 --> B8[Operation pages]
+ B4 --> B9[Static HTML]
+ B6 --> B9
+ B8 --> B9
+ end
+ subgraph Ship
+ B9 --> S1[Pagefind index]
+ B9 --> S2[llms.txt]
+ B9 --> S3[Per-page .md]
+ S1 --> S4[Deploy]
+ S2 --> S4
+ S3 --> S4
+ S4 --> S5((Live))
+ end
+```
+
+## Other diagram types
+
+Anything Mermaid supports renders — state machines, ER diagrams, Gantt charts, mindmaps, and more.
+
+```mermaid title="Subscription states"
+stateDiagram-v2
+ [*] --> Trial
+ Trial --> Active: pays
+ Trial --> Expired: 14 days
+ Active --> PastDue: card fails
+ PastDue --> Active: retry succeeds
+ PastDue --> Canceled: 3 failures
+ Active --> Canceled: cancels
+ Canceled --> [*]
+```
+
+```mermaid title="What a docs site needs"
+mindmap
+ root((Docs site))
+ Content
+ Guides
+ API reference
+ Changelog
+ Discovery
+ Search
+ llms.txt
+ Per-page Markdown
+ Trust
+ Versioning
+ Examples that run
+```
+
+```mermaid title="Where the time goes"
+pie
+ "Writing" : 45
+ "Review" : 25
+ "Diagrams" : 20
+ "Deploy" : 10
+```
+
+## Writing diagrams with AI
+
+Mermaid is plain text, and it's the diagram format language models write most reliably — ask for "a Mermaid flowchart of …" and paste the result into a fence. The source stays in your MDX, so it diffs, reviews, and renders on GitHub too. The per-page Markdown (any URL + `.md`) and `llms.txt` output keep the fence as-is, so agents reading your docs see the diagram source rather than an image.
+
+If the source has a syntax error, the page shows mermaid's error message next to the source instead of an empty box.
diff --git a/examples/inkform-docs/content/docs/reference/framework-api.mdx b/examples/inkform-docs/content/docs/reference/framework-api.mdx
index 6b2c819..f593f67 100644
--- a/examples/inkform-docs/content/docs/reference/framework-api.mdx
+++ b/examples/inkform-docs/content/docs/reference/framework-api.mdx
@@ -66,7 +66,8 @@ Types: `OpenApiModel`, `ApiOperation`, `ApiParam`, `ApiBody`, `ApiResponse`,
| Export | Notes |
| --- | --- |
-| `Mdx({ source, components? })` | Async server component. Renders an MDX string with GFM, `:::callout` directives, Shiki-highlighted code, heading slugs, and all built-in blocks. Self-wraps output in `.fw-prose`. |
+| `Mdx({ source, components? })` | Async server component. Renders an MDX string with GFM, `:::callout` directives, Shiki-highlighted code, ` ```mermaid ` fences as ``, heading slugs, and all built-in blocks. Self-wraps output in `.fw-prose`. |
+| `remarkMermaid` | The remark plugin behind the fence → `` conversion, for hosts running their own MDX pipeline. |
## `@inkform/framework/docs-shell`
@@ -86,10 +87,20 @@ The built-in MDX block library — `Note`, `Tip`, `Info`, `Warning`, `Danger`,
`Check` (callout variants), `Card`, `CardGroup`, `Columns`, `Steps`/`Step`,
`Tabs`/`Tab`, `CodeGroup`, `Accordion`/`AccordionGroup`, `ParamField`,
`ResponseField`, `Expandable`, `Frame`, `Tooltip`, `Embed`, `Hero`,
-`AuthorBio`, `RelatedPosts`, `NewsletterCTA`, and `ApiLink`. Also exports
+`AuthorBio`, `RelatedPosts`, `NewsletterCTA`, `ApiLink`, and `Mermaid` (the static
+source-block fallback — see `./mermaid` below). Also exports
`mdxComponents(customWidgets)` — merges your `widgets/index.ts` registry with
every built-in block into the map ` ` expects.
+## `@inkform/framework/mermaid`
+
+Opt-in; needs the `mermaid` package installed (an optional peer dependency). See
+[Diagrams](/guides/diagrams).
+
+| Export | Notes |
+| --- | --- |
+| `Mermaid({ chart, caption? })` | Client component. Register with `mdxComponents({ Mermaid })`. Lazy-loads mermaid and the viewer when the diagram nears the viewport; themed from `--fw-*` tokens; pan/zoom, fullscreen with minimap, copy source, SVG download. |
+
## `@inkform/framework/scalar-theme`
| Export | Notes |
diff --git a/examples/inkform-docs/mdx-components.tsx b/examples/inkform-docs/mdx-components.tsx
index 70bba3b..1a38b58 100644
--- a/examples/inkform-docs/mdx-components.tsx
+++ b/examples/inkform-docs/mdx-components.tsx
@@ -1,4 +1,5 @@
import { mdxComponents } from '@inkform/framework/components';
+import { Mermaid } from '@inkform/framework/mermaid';
import widgets from '@/widgets';
/**
@@ -7,5 +8,9 @@ import widgets from '@/widgets';
* Tabs, CodeGroup, Accordion, ParamField, …). Custom widgets registered in
* widgets/index.ts are merged in here, so in MDX/CMS content
* resolves to the real component instead of the unknown-component fallback.
+ *
+ * Mermaid makes ```mermaid fences interactive diagrams (pan, zoom,
+ * fullscreen). Not drawing diagrams? Drop this import and the `mermaid`
+ * dependency — fences then render as a plain source block.
*/
-export const siteMdxComponents = mdxComponents(widgets);
+export const siteMdxComponents = mdxComponents({ Mermaid, ...widgets });
diff --git a/examples/inkform-docs/package.json b/examples/inkform-docs/package.json
index e1e586a..02c23ba 100644
--- a/examples/inkform-docs/package.json
+++ b/examples/inkform-docs/package.json
@@ -12,8 +12,9 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
- "@inkform/framework": "^0.5.0",
+ "@inkform/framework": "^0.6.0",
"lucide-react": "^0.483.0",
+ "mermaid": "^12.0.0",
"next": "16.3.6",
"react": "19.2.1",
"react-dom": "19.2.1"
diff --git a/examples/markdown-docs/package.json b/examples/markdown-docs/package.json
index 9dd95b0..8812637 100644
--- a/examples/markdown-docs/package.json
+++ b/examples/markdown-docs/package.json
@@ -12,7 +12,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
- "@inkform/framework": "^0.5.0",
+ "@inkform/framework": "^0.6.0",
"lucide-react": "^0.483.0",
"next": "16.3.6",
"react": "19.2.1",
diff --git a/examples/pokeapi-docs/package.json b/examples/pokeapi-docs/package.json
index fc7ca16..b7387be 100644
--- a/examples/pokeapi-docs/package.json
+++ b/examples/pokeapi-docs/package.json
@@ -13,7 +13,7 @@
"test:e2e": "playwright test"
},
"dependencies": {
- "@inkform/framework": "^0.5.0",
+ "@inkform/framework": "^0.6.0",
"lucide-react": "^0.483.0",
"next": "16.3.6",
"react": "19.2.1",
diff --git a/package-lock.json b/package-lock.json
index d1216b7..575aadc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -26,8 +26,9 @@
"version": "0.2.0",
"license": "MIT",
"dependencies": {
- "@inkform/framework": "^0.5.0",
+ "@inkform/framework": "^0.6.0",
"lucide-react": "^0.483.0",
+ "mermaid": "^12.0.0",
"next": "16.3.6",
"react": "19.2.1",
"react-dom": "19.2.1"
@@ -45,7 +46,7 @@
"version": "0.2.0",
"license": "MIT",
"dependencies": {
- "@inkform/framework": "^0.5.0",
+ "@inkform/framework": "^0.6.0",
"lucide-react": "^0.483.0",
"next": "16.3.6",
"react": "19.2.1",
@@ -64,7 +65,7 @@
"version": "0.2.0",
"license": "MIT",
"dependencies": {
- "@inkform/framework": "^0.5.0",
+ "@inkform/framework": "^0.6.0",
"lucide-react": "^0.483.0",
"next": "16.3.6",
"react": "19.2.1",
@@ -175,6 +176,28 @@
"zod": "^3.25.76 || ^4.1.8"
}
},
+ "node_modules/@antfu/install-pkg": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-2.1.0.tgz",
+ "integrity": "sha512-sdg9NxU3zR4Mnawfbc/x6GB5Wf17WYud5qOuEuxXjaKpYpMkISSJEjItGebXJ2bQ4DIcly4NYH23mtkGJjvKUw==",
+ "license": "MIT",
+ "dependencies": {
+ "package-manager-detector": "^1.8.0",
+ "tinyexec": "^1.3.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@antfu/install-pkg/node_modules/tinyexec": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.1.tgz",
+ "integrity": "sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@babel/code-frame": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
@@ -198,6 +221,51 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@braintree/sanitize-url": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.2.tgz",
+ "integrity": "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==",
+ "license": "MIT"
+ },
+ "node_modules/@chevrotain/cst-dts-gen": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.1.2.tgz",
+ "integrity": "sha512-XTsjvDVB5nDZBQB8o0o/0ozNelQtn2KrUVteIHSlPd2VAV2utEb6JzyCJaJ8tGxACR4RiBNWy5uYUHX2eji88Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@chevrotain/gast": "11.1.2",
+ "@chevrotain/types": "11.1.2",
+ "lodash-es": "4.17.23"
+ }
+ },
+ "node_modules/@chevrotain/gast": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.1.2.tgz",
+ "integrity": "sha512-Z9zfXR5jNZb1Hlsd/p+4XWeUFugrHirq36bKzPWDSIacV+GPSVXdk+ahVWZTwjhNwofAWg/sZg58fyucKSQx5g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@chevrotain/types": "11.1.2",
+ "lodash-es": "4.17.23"
+ }
+ },
+ "node_modules/@chevrotain/regexp-to-ast": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.1.2.tgz",
+ "integrity": "sha512-nMU3Uj8naWer7xpZTYJdxbAs6RIv/dxYzkYU8GSwgUtcAAlzjcPfX1w+RKRcYG8POlzMeayOQ/znfwxEGo5ulw==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@chevrotain/types": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.1.2.tgz",
+ "integrity": "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@chevrotain/utils": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.1.2.tgz",
+ "integrity": "sha512-4mudFAQ6H+MqBTfqLmU7G1ZwRzCLfJEooL/fsF6rCX5eePMbGhoy5n4g+G4vlh2muDcsCTJtL+uKbOzWxs5LHA==",
+ "license": "Apache-2.0"
+ },
"node_modules/@clack/core": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@clack/core/-/core-0.4.1.tgz",
@@ -683,6 +751,23 @@
"hono": "^4"
}
},
+ "node_modules/@iconify/types": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
+ "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
+ "license": "MIT"
+ },
+ "node_modules/@iconify/utils": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.7.tgz",
+ "integrity": "sha512-JZHlwdID+dy+lTgbYC8NEC4zeugqeYsc6jewvzb4c58kHauJn+X7rNwQjxz5p2qSjqaEeQoLkCIQ9v/H4PK0/w==",
+ "license": "MIT",
+ "dependencies": {
+ "@antfu/install-pkg": "^2.0.1",
+ "@iconify/types": "^2.0.0",
+ "import-meta-resolve": "^4.2.0"
+ }
+ },
"node_modules/@img/colour": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
@@ -1325,6 +1410,18 @@
"react": ">=16"
}
},
+ "node_modules/@mermaid-js/parser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-2.0.0.tgz",
+ "integrity": "sha512-K8BeapFUfrfxbRAUQAG5oBOCwo1+bNWzaVnPxTCutkfrTBn6T/j91FIhqxWJ32SUeQ9T3iy1zcmPZ5ROZEvDrg==",
+ "license": "MIT",
+ "dependencies": {
+ "@chevrotain/types": "~11.1.2"
+ },
+ "engines": {
+ "node": ">=22.12.0"
+ }
+ },
"node_modules/@modelcontextprotocol/sdk": {
"version": "1.30.1",
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.30.1.tgz",
@@ -1629,6 +1726,12 @@
"win32"
]
},
+ "node_modules/@panzoom/panzoom": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/@panzoom/panzoom/-/panzoom-4.6.2.tgz",
+ "integrity": "sha512-Zn3B5/hwa6eYIPRSKX0xf2clv8nviTX8AnAU5kU/EugiTDhG41ya2wlBqYrZJYCWQROr/5XkWObZhIkepi89qw==",
+ "license": "MIT"
+ },
"node_modules/@playwright/test": {
"version": "1.63.0",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.63.0.tgz",
@@ -2282,6 +2385,259 @@
"assertion-error": "^2.0.1"
}
},
+ "node_modules/@types/d3": {
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz",
+ "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-array": "*",
+ "@types/d3-axis": "*",
+ "@types/d3-brush": "*",
+ "@types/d3-chord": "*",
+ "@types/d3-color": "*",
+ "@types/d3-contour": "*",
+ "@types/d3-delaunay": "*",
+ "@types/d3-dispatch": "*",
+ "@types/d3-drag": "*",
+ "@types/d3-dsv": "*",
+ "@types/d3-ease": "*",
+ "@types/d3-fetch": "*",
+ "@types/d3-force": "*",
+ "@types/d3-format": "*",
+ "@types/d3-geo": "*",
+ "@types/d3-hierarchy": "*",
+ "@types/d3-interpolate": "*",
+ "@types/d3-path": "*",
+ "@types/d3-polygon": "*",
+ "@types/d3-quadtree": "*",
+ "@types/d3-random": "*",
+ "@types/d3-scale": "*",
+ "@types/d3-scale-chromatic": "*",
+ "@types/d3-selection": "*",
+ "@types/d3-shape": "*",
+ "@types/d3-time": "*",
+ "@types/d3-time-format": "*",
+ "@types/d3-timer": "*",
+ "@types/d3-transition": "*",
+ "@types/d3-zoom": "*"
+ }
+ },
+ "node_modules/@types/d3-array": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz",
+ "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-axis": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz",
+ "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "node_modules/@types/d3-brush": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz",
+ "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "node_modules/@types/d3-chord": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz",
+ "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-color": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
+ "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-contour": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz",
+ "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-array": "*",
+ "@types/geojson": "*"
+ }
+ },
+ "node_modules/@types/d3-delaunay": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
+ "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-dispatch": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz",
+ "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-drag": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz",
+ "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "node_modules/@types/d3-dsv": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz",
+ "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-ease": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
+ "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-fetch": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz",
+ "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-dsv": "*"
+ }
+ },
+ "node_modules/@types/d3-force": {
+ "version": "3.0.10",
+ "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz",
+ "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-format": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz",
+ "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-geo": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.1.tgz",
+ "integrity": "sha512-65Emv9fQiQQqphLlRkuQ5ypPsOmWPhtBGCMv61JDPEPMvsx+gzhGf74yw1a78xFKPj6zw4AgQICJoQv0vK9M2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/geojson": "*"
+ }
+ },
+ "node_modules/@types/d3-hierarchy": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz",
+ "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-interpolate": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
+ "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-color": "*"
+ }
+ },
+ "node_modules/@types/d3-path": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz",
+ "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-polygon": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz",
+ "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-quadtree": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz",
+ "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-random": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.4.tgz",
+ "integrity": "sha512-UHYId5WTCx4L4YNel7NU00XUXXgvgpgZOvp10PuvsQENjMDXhh2RyFc0KBjO7B45ne4Ha1yVH7ii0vnzKkuzWA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-scale": {
+ "version": "4.0.9",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz",
+ "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-time": "*"
+ }
+ },
+ "node_modules/@types/d3-scale-chromatic": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
+ "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-selection": {
+ "version": "3.0.12",
+ "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.12.tgz",
+ "integrity": "sha512-Qe/KWYhEiIIxGs7HrAAjMfShxKldx19SJtr5zu53f3afPsdZNz7HHtdTLXo/kqeiWNXVycI24kSnfzBYkTzpgw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-shape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.2.0.tgz",
+ "integrity": "sha512-kVd74ta9eof3eJOvbNd1vGKS/XERRyQbT26Og63hIsvDO84cjD5gEOhsXf26w3FSoNlPVz84DOFcKv/oou+fMw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-path": "*"
+ }
+ },
+ "node_modules/@types/d3-time": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz",
+ "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-time-format": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz",
+ "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-timer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
+ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-transition": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz",
+ "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "node_modules/@types/d3-zoom": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz",
+ "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-interpolate": "*",
+ "@types/d3-selection": "*"
+ }
+ },
"node_modules/@types/debug": {
"version": "4.1.13",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz",
@@ -2313,6 +2669,12 @@
"@types/estree": "*"
}
},
+ "node_modules/@types/geojson": {
+ "version": "7946.0.16",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
+ "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
+ "license": "MIT"
+ },
"node_modules/@types/hast": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz",
@@ -2372,6 +2734,13 @@
"@types/react": "^19.3.0"
}
},
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/@types/unist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
@@ -2384,6 +2753,16 @@
"integrity": "sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==",
"license": "ISC"
},
+ "node_modules/@upsetjs/venn.js": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@upsetjs/venn.js/-/venn.js-2.0.0.tgz",
+ "integrity": "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==",
+ "license": "MIT",
+ "optionalDependencies": {
+ "d3-selection": "^3.0.0",
+ "d3-transition": "^3.0.1"
+ }
+ },
"node_modules/@vercel/oidc": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.2.0.tgz",
@@ -2804,147 +3183,696 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/character-entities-html4": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
- "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "node_modules/character-entities-html4": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
+ "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
+ "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-reference-invalid": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
+ "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/check-error": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz",
+ "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ }
+ },
+ "node_modules/chevrotain": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.1.2.tgz",
+ "integrity": "sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@chevrotain/cst-dts-gen": "11.1.2",
+ "@chevrotain/gast": "11.1.2",
+ "@chevrotain/regexp-to-ast": "11.1.2",
+ "@chevrotain/types": "11.1.2",
+ "@chevrotain/utils": "11.1.2",
+ "lodash-es": "4.17.23"
+ }
+ },
+ "node_modules/client-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
+ "license": "MIT"
+ },
+ "node_modules/collapse-white-space": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz",
+ "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/comma-separated-tokens": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
+ "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
+ "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
+ "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.6.0"
+ }
+ },
+ "node_modules/cors": {
+ "version": "2.8.6",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
+ "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/cose-base": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz",
+ "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==",
+ "license": "MIT",
+ "dependencies": {
+ "layout-base": "^1.0.0"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "license": "MIT"
+ },
+ "node_modules/cytoscape": {
+ "version": "3.34.3",
+ "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.34.3.tgz",
+ "integrity": "sha512-yfYGhRcGAntq6YBD583j4n0Eg3jIxvWmZtz/5uz9UYkeIStSlMxuUja+ec5j3iBD8nv1rwaOAYMW09tBdkSeaQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/cytoscape-cose-bilkent": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz",
+ "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "cose-base": "^1.0.0"
+ },
+ "peerDependencies": {
+ "cytoscape": "^3.2.0"
+ }
+ },
+ "node_modules/cytoscape-fcose": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz",
+ "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==",
+ "license": "MIT",
+ "dependencies": {
+ "cose-base": "^2.2.0"
+ },
+ "peerDependencies": {
+ "cytoscape": "^3.2.0"
+ }
+ },
+ "node_modules/cytoscape-fcose/node_modules/cose-base": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz",
+ "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==",
+ "license": "MIT",
+ "dependencies": {
+ "layout-base": "^2.0.0"
+ }
+ },
+ "node_modules/cytoscape-fcose/node_modules/layout-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz",
+ "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==",
+ "license": "MIT"
+ },
+ "node_modules/d3": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz",
+ "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "3",
+ "d3-axis": "3",
+ "d3-brush": "3",
+ "d3-chord": "3",
+ "d3-color": "3",
+ "d3-contour": "4",
+ "d3-delaunay": "6",
+ "d3-dispatch": "3",
+ "d3-drag": "3",
+ "d3-dsv": "3",
+ "d3-ease": "3",
+ "d3-fetch": "3",
+ "d3-force": "3",
+ "d3-format": "3",
+ "d3-geo": "3",
+ "d3-hierarchy": "3",
+ "d3-interpolate": "3",
+ "d3-path": "3",
+ "d3-polygon": "3",
+ "d3-quadtree": "3",
+ "d3-random": "3",
+ "d3-scale": "4",
+ "d3-scale-chromatic": "3",
+ "d3-selection": "3",
+ "d3-shape": "3",
+ "d3-time": "3",
+ "d3-time-format": "4",
+ "d3-timer": "3",
+ "d3-transition": "3",
+ "d3-zoom": "3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-array": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
+ "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
+ "license": "ISC",
+ "dependencies": {
+ "internmap": "1 - 2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-axis": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz",
+ "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-brush": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz",
+ "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-drag": "2 - 3",
+ "d3-interpolate": "1 - 3",
+ "d3-selection": "3",
+ "d3-transition": "3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-chord": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz",
+ "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-path": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-color": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
+ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-contour": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz",
+ "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "^3.2.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-delaunay": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
+ "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==",
+ "license": "ISC",
+ "dependencies": {
+ "delaunator": "5"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-dispatch": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
+ "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-drag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
+ "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-selection": "3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-dsv": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz",
+ "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
+ "license": "ISC",
+ "dependencies": {
+ "commander": "7",
+ "iconv-lite": "0.6",
+ "rw": "1"
+ },
+ "bin": {
+ "csv2json": "bin/dsv2json.js",
+ "csv2tsv": "bin/dsv2dsv.js",
+ "dsv2dsv": "bin/dsv2dsv.js",
+ "dsv2json": "bin/dsv2json.js",
+ "json2csv": "bin/json2dsv.js",
+ "json2dsv": "bin/json2dsv.js",
+ "json2tsv": "bin/json2dsv.js",
+ "tsv2csv": "bin/dsv2dsv.js",
+ "tsv2json": "bin/dsv2json.js"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-dsv/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/d3-ease": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
+ "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-fetch": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz",
+ "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dsv": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-force": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
+ "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-quadtree": "1 - 3",
+ "d3-timer": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-format": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz",
+ "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-geo": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz",
+ "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "2.5.0 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-hierarchy": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz",
+ "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-interpolate": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
+ "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-color": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-polygon": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz",
+ "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-quadtree": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
+ "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-random": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz",
+ "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-sankey": {
+ "version": "0.12.3",
+ "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz",
+ "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "d3-array": "1 - 2",
+ "d3-shape": "^1.2.0"
}
},
- "node_modules/character-entities-legacy": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
- "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "node_modules/d3-sankey/node_modules/d3-array": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
+ "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "internmap": "^1.0.0"
}
},
- "node_modules/character-reference-invalid": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
- "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
+ "node_modules/d3-sankey/node_modules/d3-path": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
+ "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==",
+ "license": "BSD-3-Clause"
},
- "node_modules/check-error": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz",
- "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 16"
+ "node_modules/d3-sankey/node_modules/d3-shape": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
+ "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "d3-path": "1"
}
},
- "node_modules/client-only": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
- "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
- "license": "MIT"
+ "node_modules/d3-sankey/node_modules/internmap": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz",
+ "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==",
+ "license": "ISC"
},
- "node_modules/collapse-white-space": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz",
- "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "node_modules/d3-scale": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
+ "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "2.10.0 - 3",
+ "d3-format": "1 - 3",
+ "d3-interpolate": "1.2.0 - 3",
+ "d3-time": "2.1.1 - 3",
+ "d3-time-format": "2 - 4"
+ },
+ "engines": {
+ "node": ">=12"
}
},
- "node_modules/comma-separated-tokens": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
- "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
+ "node_modules/d3-scale-chromatic": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
+ "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-color": "1 - 3",
+ "d3-interpolate": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
}
},
- "node_modules/content-disposition": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
- "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==",
- "license": "MIT",
+ "node_modules/d3-selection": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
+ "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
+ "license": "ISC",
"engines": {
- "node": ">=18"
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-shape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+ "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-path": "^3.1.0"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "engines": {
+ "node": ">=12"
}
},
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
- "license": "MIT",
+ "node_modules/d3-time": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "2 - 3"
+ },
"engines": {
- "node": ">= 0.6"
+ "node": ">=12"
}
},
- "node_modules/cookie": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
- "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
- "license": "MIT",
+ "node_modules/d3-time-format": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
+ "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-time": "1 - 3"
+ },
"engines": {
- "node": ">= 0.6"
+ "node": ">=12"
}
},
- "node_modules/cookie-signature": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
- "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
- "license": "MIT",
+ "node_modules/d3-timer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+ "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+ "license": "ISC",
"engines": {
- "node": ">=6.6.0"
+ "node": ">=12"
}
},
- "node_modules/cors": {
- "version": "2.8.6",
- "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
- "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
- "license": "MIT",
+ "node_modules/d3-transition": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
+ "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
+ "license": "ISC",
"dependencies": {
- "object-assign": "^4",
- "vary": "^1"
+ "d3-color": "1 - 3",
+ "d3-dispatch": "1 - 3",
+ "d3-ease": "1 - 3",
+ "d3-interpolate": "1 - 3",
+ "d3-timer": "1 - 3"
},
"engines": {
- "node": ">= 0.10"
+ "node": ">=12"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "peerDependencies": {
+ "d3-selection": "2 - 3"
}
},
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
- "license": "MIT",
+ "node_modules/d3-zoom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
+ "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
+ "license": "ISC",
"dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
+ "d3-dispatch": "1 - 3",
+ "d3-drag": "2 - 3",
+ "d3-interpolate": "1 - 3",
+ "d3-selection": "2 - 3",
+ "d3-transition": "2 - 3"
},
"engines": {
- "node": ">= 8"
+ "node": ">=12"
}
},
- "node_modules/csstype": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
- "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "node_modules/dagre-d3-es": {
+ "version": "7.0.14",
+ "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.14.tgz",
+ "integrity": "sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg==",
+ "license": "MIT",
+ "dependencies": {
+ "d3": "^7.9.0",
+ "lodash-es": "^4.17.21"
+ }
+ },
+ "node_modules/dayjs": {
+ "version": "1.11.23",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.23.tgz",
+ "integrity": "sha512-QDTCU0M0MxR3hQfnlDJfwekQiaanm1ubOD231u73WBckQ/fsamwRLiE2GBz6D3a/xF1NgfiDLJjXBa1hYOYTtQ==",
"license": "MIT"
},
"node_modules/debug": {
@@ -2987,6 +3915,15 @@
"node": ">=6"
}
},
+ "node_modules/delaunator": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz",
+ "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==",
+ "license": "ISC",
+ "dependencies": {
+ "robust-predicates": "^3.0.2"
+ }
+ },
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -3028,6 +3965,15 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/dompurify": {
+ "version": "3.4.16",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.16.tgz",
+ "integrity": "sha512-sqo+pNp3qRhCIpbgRi1y8Tgk27Bo2Ry7w0dC1NBeNTdZChWjz9Xb/KOoZbRP/R6pQZ80Qw8YhXw13hWWBbMRnQ==",
+ "license": "(MPL-2.0 OR Apache-2.0)",
+ "optionalDependencies": {
+ "@types/trusted-types": "^2.0.7"
+ }
+ },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -3048,6 +3994,12 @@
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"license": "MIT"
},
+ "node_modules/elkjs": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz",
+ "integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==",
+ "license": "EPL-2.0"
+ },
"node_modules/emoji-regex-xs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz",
@@ -3112,6 +4064,18 @@
"node": ">= 0.4"
}
},
+ "node_modules/es-toolkit": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.52.0.tgz",
+ "integrity": "sha512-XTNEJQh1tY1ZJVcf6ayP/2n4ZPyaHlW2FWs7xvw5ddPuhUVjLD3olQVQS7kf58JbAB48iL0uL/jerTrjtV3lDA==",
+ "license": "MIT",
+ "workspaces": [
+ "docs",
+ "benchmarks",
+ "tests/types",
+ "tests/browser-compat"
+ ]
+ },
"node_modules/esast-util-from-estree": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz",
@@ -3623,6 +4587,12 @@
"node": ">=6.0"
}
},
+ "node_modules/hachure-fill": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz",
+ "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==",
+ "license": "MIT"
+ },
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
@@ -3887,6 +4857,16 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/import-meta-resolve": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz",
+ "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
@@ -3899,6 +4879,15 @@
"integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==",
"license": "MIT"
},
+ "node_modules/internmap": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
+ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/ip-address": {
"version": "10.7.2",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.2.tgz",
@@ -4055,6 +5044,36 @@
"node": ">=0.10.0"
}
},
+ "node_modules/katex": {
+ "version": "0.16.47",
+ "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
+ "integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
+ "funding": [
+ "https://opencollective.com/katex",
+ "https://github.com/sponsors/katex"
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^8.3.0"
+ },
+ "bin": {
+ "katex": "cli.js"
+ }
+ },
+ "node_modules/katex/node_modules/commander": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+ "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/khroma": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz",
+ "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw=="
+ },
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -4064,6 +5083,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/layout-base": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz",
+ "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==",
+ "license": "MIT"
+ },
"node_modules/leven": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-4.1.0.tgz",
@@ -4076,6 +5101,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/lodash-es": {
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
+ "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
+ "license": "MIT"
+ },
"node_modules/longest-streak": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
@@ -4134,6 +5165,18 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/marked": {
+ "version": "16.4.2",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz",
+ "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==",
+ "license": "MIT",
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 20"
+ }
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -4476,6 +5519,40 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/mermaid": {
+ "version": "12.0.0",
+ "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-12.0.0.tgz",
+ "integrity": "sha512-/wQXC9iBxoGV8p3erbvaXs9h77VyLDBH6GdayVjj3hEcSQhFU4N1WUhUppotCEqlIxI2pRMwjwBSwTB1MfZBgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@braintree/sanitize-url": "^7.1.2",
+ "@iconify/utils": "^3.0.2",
+ "@mermaid-js/parser": "^2.0.0",
+ "@types/d3": "^7.4.3",
+ "@upsetjs/venn.js": "^2.0.0",
+ "chevrotain": "~11.1.2",
+ "cytoscape": "^3.34.0",
+ "cytoscape-cose-bilkent": "^4.1.0",
+ "cytoscape-fcose": "^2.2.0",
+ "d3": "^7.9.0",
+ "d3-sankey": "^0.12.3",
+ "dagre-d3-es": "7.0.14",
+ "dayjs": "^1.11.21",
+ "dompurify": "^3.4.12",
+ "elkjs": "^0.9.3",
+ "es-toolkit": "^1.45.1",
+ "katex": "^0.16.47",
+ "khroma": "^2.1.0",
+ "marked": "^16.3.0",
+ "roughjs": "^4.6.6",
+ "stylis": "^4.3.6",
+ "ts-dedent": "^2.2.0",
+ "uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0"
+ },
+ "engines": {
+ "node": ">=22.12.0"
+ }
+ },
"node_modules/micromark": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
@@ -5418,6 +6495,12 @@
"regex-recursion": "^5.1.1"
}
},
+ "node_modules/package-manager-detector": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.8.0.tgz",
+ "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==",
+ "license": "MIT"
+ },
"node_modules/pagefind": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.5.2.tgz",
@@ -5489,6 +6572,12 @@
"node": ">= 0.8"
}
},
+ "node_modules/path-data-parser": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz",
+ "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==",
+ "license": "MIT"
+ },
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -5581,6 +6670,22 @@
"node": ">=20"
}
},
+ "node_modules/points-on-curve": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz",
+ "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==",
+ "license": "MIT"
+ },
+ "node_modules/points-on-path": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz",
+ "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==",
+ "license": "MIT",
+ "dependencies": {
+ "path-data-parser": "0.1.0",
+ "points-on-curve": "0.2.0"
+ }
+ },
"node_modules/postcss": {
"version": "8.5.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz",
@@ -5999,6 +7104,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/robust-predicates": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz",
+ "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==",
+ "license": "Unlicense"
+ },
"node_modules/rollup": {
"version": "4.63.5",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.63.5.tgz",
@@ -6045,6 +7156,18 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/roughjs": {
+ "version": "4.6.6",
+ "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz",
+ "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==",
+ "license": "MIT",
+ "dependencies": {
+ "hachure-fill": "^0.5.2",
+ "path-data-parser": "^0.1.0",
+ "points-on-curve": "^0.2.0",
+ "points-on-path": "^0.2.1"
+ }
+ },
"node_modules/router": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
@@ -6061,6 +7184,12 @@
"node": ">= 18"
}
},
+ "node_modules/rw": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
+ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
@@ -6463,6 +7592,12 @@
}
}
},
+ "node_modules/stylis": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.4.0.tgz",
+ "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==",
+ "license": "MIT"
+ },
"node_modules/tagged-tag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz",
@@ -6565,6 +7700,15 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/ts-dedent": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.3.0.tgz",
+ "integrity": "sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.10"
+ }
+ },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -6790,6 +7934,19 @@
"node": ">= 0.8"
}
},
+ "node_modules/uuid": {
+ "version": "14.0.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.2.tgz",
+ "integrity": "sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist-node/bin/uuid"
+ }
+ },
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -7135,13 +8292,14 @@
},
"packages/framework": {
"name": "@inkform/framework",
- "version": "0.5.0",
+ "version": "0.6.0",
"license": "MIT",
"dependencies": {
"@ai-sdk/anthropic": "^4.0.16",
"@ai-sdk/google": "^4.0.18",
"@ai-sdk/openai": "^4.0.16",
"@modelcontextprotocol/sdk": "^1.29.0",
+ "@panzoom/panzoom": "^4.6.2",
"@scalar/json-magic": "^0.12.19",
"@scalar/openapi-parser": "^0.28.10",
"@scalar/openapi-types": "^0.9.3",
@@ -7161,6 +8319,7 @@
},
"devDependencies": {
"@types/react": "^19",
+ "mermaid": "^12.0.0",
"tsx": "^4.23.1",
"typescript": "^5",
"vitest": "^3.2.4"
@@ -7169,9 +8328,15 @@
"node": ">=22"
},
"peerDependencies": {
+ "mermaid": ">=11",
"next": ">=16",
"react": ">=19",
"react-dom": ">=19"
+ },
+ "peerDependenciesMeta": {
+ "mermaid": {
+ "optional": true
+ }
}
},
"templates/canopy": {
@@ -7179,8 +8344,9 @@
"version": "0.1.0",
"license": "MIT",
"dependencies": {
- "@inkform/framework": "^0.5.0",
+ "@inkform/framework": "^0.6.0",
"lucide-react": "^0.483.0",
+ "mermaid": "^12.0.0",
"next": "16.3.6",
"react": "19.2.1",
"react-dom": "19.2.1"
@@ -7198,8 +8364,9 @@
"version": "0.1.0",
"license": "MIT",
"dependencies": {
- "@inkform/framework": "^0.5.0",
+ "@inkform/framework": "^0.6.0",
"lucide-react": "^0.483.0",
+ "mermaid": "^12.0.0",
"next": "16.3.6",
"react": "19.2.1",
"react-dom": "19.2.1"
@@ -7217,8 +8384,9 @@
"version": "0.1.0",
"license": "MIT",
"dependencies": {
- "@inkform/framework": "^0.5.0",
+ "@inkform/framework": "^0.6.0",
"lucide-react": "^0.483.0",
+ "mermaid": "^12.0.0",
"next": "16.3.6",
"react": "19.2.1",
"react-dom": "19.2.1"
diff --git a/package.json b/package.json
index 0b8fee0..1523b8a 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
"@modelcontextprotocol/sdk": {
"@hono/node-server": "2.0.12"
},
- "@hono/node-server": "2.0.12"
+ "@hono/node-server": "2.0.12",
+ "lodash-es": "^4.18.1"
}
}
diff --git a/packages/framework/README.md b/packages/framework/README.md
index 578c30a..99d8e28 100644
--- a/packages/framework/README.md
+++ b/packages/framework/README.md
@@ -17,6 +17,8 @@ anywhere Next.js runs (Vercel, AWS Amplify, a Node server, a container).
- **MDX rendering** with GFM, `:::callout` directives, and Shiki syntax
highlighting (``).
+- **Mermaid diagrams** — ` ```mermaid ` fences render as zoomable, pannable
+ figures with a fullscreen view and minimap (`./mermaid`, opt-in: `npm i mermaid`).
- **A `docs.json` content model** — Mintlify-style tabs → groups → pages, with
anchors, navbar links, nested pages, and versioning hints. Pure, no IO.
- **OpenAPI → API Reference** — parse a JSON/YAML spec into a normalized model,
@@ -77,7 +79,8 @@ Content lives under `content/{docs,blog,changelog}` (override the root with
| `./content` | filesystem loaders: `loadDocsConfig`, `loadDocPage`, `loadBlogPosts`, `loadOpenApiSpec`, `extractHeadings` |
| `./nav` | `DocsConfig`, `docTabs`, `listDocPages`, `docNeighbours` |
| `./openapi` | `parseOpenApi`, `normalizeOperations`, `operationNavGroups`, `curlExample`, `sampleFromSchema` |
-| `./mdx` | `` |
+| `./mdx` | ``, `remarkMermaid` |
+| `./mermaid` | `` — interactive diagram viewer (needs the optional `mermaid` peer) |
| `./components` | the MDX component kit + `mdxComponents()` |
| `./docs-shell` | ``, ``, ``, ``, `` — also mounts the Pagefind highlight effect, see below |
| `./api-reference` | ``, `` |
diff --git a/packages/framework/package.json b/packages/framework/package.json
index 75160b0..9a51d37 100644
--- a/packages/framework/package.json
+++ b/packages/framework/package.json
@@ -1,6 +1,6 @@
{
"name": "@inkform/framework",
- "version": "0.5.0",
+ "version": "0.6.0",
"description": "Standalone Next.js + MDX framework for documentation, API reference (OpenAPI), blog, and changelog sites. The rendering engine behind the inkform docs themes — usable on its own.",
"license": "MIT",
"author": "Charan",
@@ -27,7 +27,8 @@
"api-reference",
"changelog",
"blog",
- "static-site"
+ "static-site",
+ "mermaid"
],
"main": "./src/index.ts",
"exports": {
@@ -45,6 +46,7 @@
"./ai": "./src/ai/index.ts",
"./llms-txt": "./src/llms-txt.ts",
"./mdx": "./src/mdx.tsx",
+ "./mermaid": "./src/mermaid/index.tsx",
"./markdown": "./src/markdown.ts",
"./components": "./src/components.tsx",
"./docs-shell": "./src/docs-shell.tsx",
@@ -76,13 +78,20 @@
"peerDependencies": {
"next": ">=16",
"react": ">=19",
- "react-dom": ">=19"
+ "react-dom": ">=19",
+ "mermaid": ">=11"
+ },
+ "peerDependenciesMeta": {
+ "mermaid": {
+ "optional": true
+ }
},
"dependencies": {
"@ai-sdk/anthropic": "^4.0.16",
"@ai-sdk/google": "^4.0.18",
"@ai-sdk/openai": "^4.0.16",
"@modelcontextprotocol/sdk": "^1.29.0",
+ "@panzoom/panzoom": "^4.6.2",
"@scalar/json-magic": "^0.12.19",
"@scalar/openapi-parser": "^0.28.10",
"@scalar/openapi-types": "^0.9.3",
@@ -102,6 +111,7 @@
},
"devDependencies": {
"@types/react": "^19",
+ "mermaid": "^12.0.0",
"tsx": "^4.23.1",
"typescript": "^5",
"vitest": "^3.2.4"
diff --git a/packages/framework/src/components.tsx b/packages/framework/src/components.tsx
index 785321e..94138ef 100644
--- a/packages/framework/src/components.tsx
+++ b/packages/framework/src/components.tsx
@@ -330,6 +330,32 @@ export function Frame({ caption, children }: FrameProps) {
);
}
+/* ---------------------------------------------------------------------------
+ * Mermaid (static fallback)
+ * -------------------------------------------------------------------------*/
+
+export interface MermaidSourceProps {
+ chart?: string;
+ caption?: string;
+}
+
+/**
+ * What ```mermaid fences render as by default: the diagram source as a plain
+ * block. The interactive renderer is opt-in so sites that never draw diagrams
+ * don't install mermaid — register it with
+ * `mdxComponents({ Mermaid })` from `@inkform/framework/mermaid`.
+ */
+export function MermaidSource({ chart = '', caption }: MermaidSourceProps) {
+ return (
+
+
+ {chart.trim()}
+
+ {caption && {caption} }
+
+ );
+}
+
/* ---------------------------------------------------------------------------
* Tooltip
* -------------------------------------------------------------------------*/
@@ -528,6 +554,7 @@ const BUILTINS: Record>> = {
// Misc
Expandable: Expandable as React.ComponentType>,
Frame: Frame as React.ComponentType>,
+ Mermaid: MermaidSource as React.ComponentType>,
Tooltip: Tooltip as unknown as React.ComponentType>,
// Media / embeds
Embed: Embed as React.ComponentType>,
diff --git a/packages/framework/src/glyphs.tsx b/packages/framework/src/glyphs.tsx
index b441438..cefa047 100644
--- a/packages/framework/src/glyphs.tsx
+++ b/packages/framework/src/glyphs.tsx
@@ -1,8 +1,8 @@
import * as React from 'react';
/**
- * Shared dependency-free stroke glyphs used by the AI-tool menu and page
- * actions (copy / check / external-link / text icons). Single-color
+ * Shared dependency-free stroke glyphs used by the AI-tool menu, page
+ * actions, and the Mermaid diagram toolbar. Single-color
* `currentColor` strokes, sized to match the menu's 15px icon slots.
*/
@@ -49,3 +49,63 @@ export function TextGlyph() {
);
}
+
+export function PlusGlyph() {
+ return (
+
+
+
+
+ );
+}
+
+export function MinusGlyph() {
+ return (
+
+
+
+ );
+}
+
+/** Four inward corners — "fit to view". */
+export function FitGlyph() {
+ return (
+
+
+
+
+
+
+ );
+}
+
+/** Four outward corners — "expand to fullscreen". */
+export function ExpandGlyph() {
+ return (
+
+
+
+
+
+
+ );
+}
+
+export function DownloadGlyph() {
+ return (
+
+
+
+
+
+ );
+}
+
+export function CloseGlyph() {
+ return (
+
+
+
+
+ );
+}
diff --git a/packages/framework/src/markdown.test.ts b/packages/framework/src/markdown.test.ts
index 069de26..79de8ee 100644
--- a/packages/framework/src/markdown.test.ts
+++ b/packages/framework/src/markdown.test.ts
@@ -7,6 +7,11 @@ const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..
const POKEAPI_CONTENT_ROOT = path.join(REPO_ROOT, 'examples', 'pokeapi-docs', 'content');
describe('processMarkdown', () => {
+ it('keeps inline colons that remark-directive would read as text directives', () => {
+ const md = processMarkdown('Google studied teams ([re:Work](https://example.com)).\n');
+ expect(md).toContain('[re:Work](https://example.com)');
+ });
+
it('strips imports/exports but keeps the body', () => {
const md = processMarkdown(
`import { Playground } from '@/widgets';
diff --git a/packages/framework/src/markdown.ts b/packages/framework/src/markdown.ts
index e2b3fa2..d4c5dd1 100644
--- a/packages/framework/src/markdown.ts
+++ b/packages/framework/src/markdown.ts
@@ -107,7 +107,8 @@ const mdxTextHandler = mdxJsxHandlers.mdxJsxTextElement!;
* toMarkdown handlers:
* - drop `mdxjsEsm` (imports/exports are machinery, not content)
* - `:::callout` directives → blockquote
- * - leaf/text directives → their children (or drop when empty)
+ * - leaf directives → their children (or drop when empty); inline `:name`
+ * text directives → back to the literal text
*/
function remarkPlainMarkdown() {
return (tree: Root) => {
@@ -128,8 +129,15 @@ function remarkPlainMarkdown() {
delete directive.attributes;
return;
}
- case 'leafDirective':
case 'textDirective': {
+ // Inline `:word` is almost always prose ("re:Work"), not a directive:
+ // put the colon and name back rather than dropping them.
+ const name = (n as { name?: string }).name ?? '';
+ const restored = [{ type: 'text', value: `:${name}` } as Node, ...((n.children ?? []) as Node[])];
+ (parent.children as Node[]).splice(index, 1, ...restored);
+ return;
+ }
+ case 'leafDirective': {
const children = (n.children ?? []) as Node[];
// Replace the directive node with its children (or drop it). Spliced
// in place so `visit`'s index stays valid for the remaining siblings.
diff --git a/packages/framework/src/mdx.tsx b/packages/framework/src/mdx.tsx
index a17978d..a4fd003 100644
--- a/packages/framework/src/mdx.tsx
+++ b/packages/framework/src/mdx.tsx
@@ -4,30 +4,11 @@ import remarkGfm from 'remark-gfm';
import remarkDirective from 'remark-directive';
import rehypePrettyCode from 'rehype-pretty-code';
import rehypeSlug from 'rehype-slug';
-import { visit } from 'unist-util-visit';
import { mdxComponents } from './components';
+import { remarkCallouts } from './remark-directives';
+import { remarkMermaid } from './remark-mermaid';
-const CALLOUT_NAMES = new Set(['info', 'warning', 'error', 'success', 'note', 'tip']);
-
-type DirectiveNode = {
- type: string;
- name?: string;
- data?: { hName?: string; hProperties?: Record };
-};
-
-/** Map `:::info … :::` (remark-directive) onto the component. */
-function remarkCallouts() {
- return (tree: Parameters[0]) => {
- visit(tree, (node) => {
- const n = node as DirectiveNode;
- if ((n.type === 'containerDirective' || n.type === 'leafDirective') && n.name && CALLOUT_NAMES.has(n.name)) {
- n.data ??= {};
- n.data.hName = 'Callout';
- n.data.hProperties = { type: n.name };
- }
- });
- };
-}
+export { remarkMermaid } from './remark-mermaid';
const prettyCodeOptions = {
theme: { light: 'github-light', dark: 'github-dark' },
@@ -42,7 +23,8 @@ type MdxProps = {
/**
* Renders an MDX string (the body the editor commits) to React. Supports GFM,
- * `:::callout` directives, fenced code with Shiki highlighting, rehype-slug for
+ * `:::callout` directives, fenced code with Shiki highlighting, ```mermaid
+ * fences as diagrams, rehype-slug for
* heading IDs (matching extractHeadings slugs → TOC anchor links), and all
* built-in components. Unknown components render a visible fallback (never crash
* the build).
@@ -60,7 +42,7 @@ export async function Mdx({ source, components }: MdxProps) {
// the v6 RCE guard (`blockDangerousJS: true`, the secure default) in place.
blockJS: false,
mdxOptions: {
- remarkPlugins: [remarkGfm, remarkDirective, remarkCallouts],
+ remarkPlugins: [remarkGfm, remarkDirective, remarkCallouts, remarkMermaid],
// eslint-disable-next-line @typescript-eslint/no-explicit-any
rehypePlugins: [rehypeSlug, [rehypePrettyCode as any, prettyCodeOptions]],
},
diff --git a/packages/framework/src/mermaid/index.tsx b/packages/framework/src/mermaid/index.tsx
new file mode 100644
index 0000000..62c2782
--- /dev/null
+++ b/packages/framework/src/mermaid/index.tsx
@@ -0,0 +1,339 @@
+'use client';
+
+/**
+ * @inkform/framework/mermaid — the interactive diagram renderer.
+ *
+ * Opt-in: needs the `mermaid` package installed alongside the framework
+ * (`npm i mermaid`), then register it so ```mermaid fences use it instead of
+ * the built-in static source block:
+ *
+ * import { mdxComponents } from '@inkform/framework/components';
+ * import { Mermaid } from '@inkform/framework/mermaid';
+ * export const siteMdxComponents = mdxComponents({ Mermaid });
+ *
+ * Readers only pay for mermaid on pages that have a diagram, and only once
+ * the diagram is about to scroll into view — it's a dynamic import.
+ */
+
+import * as React from 'react';
+import { copyText } from '../clipboard';
+import { CheckGlyph, CloseGlyph, CopyGlyph, DownloadGlyph, ExpandGlyph, FitGlyph, MinusGlyph, PlusGlyph } from '../glyphs';
+import { renderDiagram, themeConfig } from './render';
+import type { ViewerApi } from './viewer';
+
+// The pan/zoom viewer (and @panzoom/panzoom) is its own chunk too, so a site
+// that registers everywhere adds almost nothing to pages without
+// a diagram.
+const loadViewer = () => import('./viewer');
+const DiagramViewer = React.lazy(() => loadViewer().then((m) => ({ default: m.DiagramViewer })));
+
+export interface MermaidProps {
+ /** Mermaid source. ```mermaid fences are passed in as this prop. */
+ chart?: string;
+ /** Shown under the diagram and used as its accessible name. */
+ caption?: string;
+}
+
+/* ---------------------------------------------------------------------------
+ * Hooks
+ * -------------------------------------------------------------------------*/
+
+function subscribeTheme(onChange: () => void) {
+ const mo = new MutationObserver(onChange);
+ mo.observe(document.documentElement, { attributes: true, attributeFilter: ['class', 'data-theme'] });
+ return () => mo.disconnect();
+}
+
+const isDark = () => {
+ const html = document.documentElement;
+ return html.classList.contains('dark') || html.dataset.theme === 'dark';
+};
+
+/** Tracks the `html.dark` class (or `data-theme="dark"`) the theme toggle sets. */
+function useDarkMode() {
+ return React.useSyncExternalStore(subscribeTheme, isDark, () => false);
+}
+
+/** True once `ref` comes within ~one screen of the viewport. Never flips back. */
+function useNearViewport(ref: React.RefObject) {
+ const [near, setNear] = React.useState(false);
+ React.useEffect(() => {
+ const el = ref.current;
+ if (!el || near) return;
+ if (typeof IntersectionObserver === 'undefined') {
+ setNear(true);
+ return;
+ }
+ const io = new IntersectionObserver(
+ (entries) => {
+ if (entries.some((e) => e.isIntersecting)) {
+ setNear(true);
+ io.disconnect();
+ }
+ },
+ { rootMargin: '600px 0px' },
+ );
+ io.observe(el);
+ return () => io.disconnect();
+ }, [ref, near]);
+ return near;
+}
+
+/* ---------------------------------------------------------------------------
+ * Helpers
+ * -------------------------------------------------------------------------*/
+
+let renderCount = 0;
+
+function errorMessage(err: unknown): string {
+ const raw = err instanceof Error ? err.message : String(err);
+ return raw.replace(/^Error:\s*/, '').trim() || 'Unknown error';
+}
+
+function slugify(text: string | undefined): string {
+ const slug = (text ?? '')
+ .toLowerCase()
+ .replace(/[^a-z0-9]+/g, '-')
+ .replace(/^-|-$/g, '');
+ return slug || 'diagram';
+}
+
+/** Standalone SVG file: natural size, page background baked in. */
+function downloadSvg(svg: string, name: string, background: string) {
+ const doc = new DOMParser().parseFromString(svg, 'image/svg+xml');
+ const root = doc.documentElement;
+ const vb = root.getAttribute('viewBox')?.split(/[\s,]+/).map(Number);
+ if (vb?.length === 4) {
+ root.setAttribute('width', String(vb[2]));
+ root.setAttribute('height', String(vb[3]));
+ }
+ root.removeAttribute('style');
+ root.setAttribute('style', `background-color: ${background}`);
+ const xml = `\n${new XMLSerializer().serializeToString(root)}`;
+ const url = URL.createObjectURL(new Blob([xml], { type: 'image/svg+xml' }));
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = `${name}.svg`;
+ a.click();
+ setTimeout(() => URL.revokeObjectURL(url), 1000);
+}
+
+/* ---------------------------------------------------------------------------
+ * Toolbar
+ * -------------------------------------------------------------------------*/
+
+interface ToolbarProps {
+ scale: number;
+ api: React.RefObject;
+ copied: boolean;
+ onCopy: () => void;
+ onDownload: () => void;
+ onExpand?: () => void;
+ onClose?: () => void;
+}
+
+function ToolButton({ label, onClick, children }: { label: string; onClick: () => void; children: React.ReactNode }) {
+ return (
+
+ {children}
+
+ );
+}
+
+function Toolbar({ scale, api, copied, onCopy, onDownload, onExpand, onClose }: ToolbarProps) {
+ return (
+
+
api.current?.zoomOut()}>
+
+
+
api.current?.reset()}
+ >
+ {Math.round(scale * 100)}%
+
+
api.current?.zoomIn()}>
+
+
+ {onClose && (
+
api.current?.reset()}>
+
+
+ )}
+
+
+ {copied ? : }
+
+
+
+
+ {onExpand && (
+
+
+
+ )}
+ {onClose && (
+ <>
+
+
+
+
+ >
+ )}
+
+ );
+}
+
+/* ---------------------------------------------------------------------------
+ * Mermaid
+ * -------------------------------------------------------------------------*/
+
+type Rendered = { svg: string; id: string } | { error: string } | null;
+
+/**
+ * Interactive Mermaid diagram: themed from the site's --fw-* tokens (and
+ * re-rendered when light/dark flips), pan + zoom inline, a fullscreen view
+ * with a minimap, copy-source and SVG download. Invalid source shows the
+ * parse error next to the source instead of an empty box.
+ */
+export function Mermaid({ chart = '', caption }: MermaidProps) {
+ const source = chart.trim();
+ const label = caption ?? 'Diagram';
+ const figureRef = React.useRef(null);
+ const dialogRef = React.useRef(null);
+ const inlineApi = React.useRef(null);
+ const fullApi = React.useRef(null);
+ const near = useNearViewport(figureRef);
+ const dark = useDarkMode();
+ const [rendered, setRendered] = React.useState(null);
+ const [scale, setScale] = React.useState(1);
+ const [fullScale, setFullScale] = React.useState(1);
+ const [open, setOpen] = React.useState(false);
+ const [copied, setCopied] = React.useState(false);
+
+ React.useEffect(() => {
+ const el = figureRef.current;
+ if (!near || !source || !el) return;
+ let cancelled = false;
+ // A fresh id per render: mermaid removes any existing element with the id
+ // it's given, which would yank the diagram on screen during a re-theme.
+ const id = `fw-mermaid-${++renderCount}`;
+ void loadViewer();
+ renderDiagram(id, source, themeConfig(el, dark))
+ .then(({ svg }) => !cancelled && setRendered({ svg, id }))
+ .catch((err) => !cancelled && setRendered({ error: errorMessage(err) }));
+ return () => {
+ cancelled = true;
+ };
+ }, [near, source, dark]);
+
+ React.useEffect(() => {
+ const dialog = dialogRef.current;
+ if (!open || !dialog) return;
+ dialog.showModal();
+ const html = document.documentElement;
+ const prev = html.style.overflow;
+ html.style.overflow = 'hidden';
+ return () => {
+ html.style.overflow = prev;
+ };
+ }, [open]);
+
+ const onCopy = async () => {
+ if (await copyText(source)) {
+ setCopied(true);
+ setTimeout(() => setCopied(false), 1500);
+ }
+ };
+
+ const svg = rendered && 'svg' in rendered ? rendered : null;
+ const onDownload = () => {
+ if (!svg || !figureRef.current) return;
+ const bg = getComputedStyle(figureRef.current).getPropertyValue('--fw-bg').trim() || 'transparent';
+ downloadSvg(svg.svg, slugify(caption), bg);
+ };
+
+ // The fullscreen copy lives in the same document, so its ids (markers,
+ // scoped