From 690fe200f06a22181c3c28a425c9f999331f4c2f Mon Sep 17 00:00:00 2001 From: Charan Date: Sun, 27 Sep 2026 19:03:50 +0530 Subject: [PATCH 1/3] feat(mermaid): interactive Mermaid diagrams (0.6.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ```mermaid fences (and ) now render as diagrams: pan, zoom (Ctrl/⌘+wheel, pinch, double-click, keyboard), a fullscreen view with a minimap, copy source, and SVG download. Colors derive from the --fw-* tokens and re-render on light/dark switches; captions come from the fence meta (```mermaid title="…"). Opt-in: `mermaid` is an optional peer dependency and the viewer lives at @inkform/framework/mermaid. Without it, fences render as a static source block. Templates ship with it enabled. Both mermaid and the viewer are lazy chunks loaded only when a diagram nears the viewport. Also: remarkMermaid exported from ./mdx, docs page + API reference, templates/examples bumped to ^0.6.0, lodash-es override (^4.18.1) for the advisory pulled in through mermaid's deps. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01EaJaU595iENT8fc7mcHDWC --- CHANGELOG.md | 22 + README.md | 1 + examples/inkform-docs/content/docs/docs.json | 1 + .../content/docs/guides/diagrams.mdx | 182 +++ .../content/docs/reference/framework-api.mdx | 15 +- examples/inkform-docs/mdx-components.tsx | 7 +- examples/inkform-docs/package.json | 3 +- examples/markdown-docs/package.json | 2 +- examples/pokeapi-docs/package.json | 2 +- package-lock.json | 1392 +++++++++++++++-- package.json | 3 +- packages/framework/README.md | 5 +- packages/framework/package.json | 16 +- packages/framework/src/components.tsx | 27 + packages/framework/src/glyphs.tsx | 64 +- packages/framework/src/mdx.tsx | 8 +- packages/framework/src/mermaid/index.tsx | 339 ++++ packages/framework/src/mermaid/render.ts | 185 +++ packages/framework/src/mermaid/viewer.tsx | 307 ++++ .../framework/src/remark-mermaid.test.tsx | 52 + packages/framework/src/remark-mermaid.ts | 52 + packages/framework/src/styles.css | 1 + packages/framework/src/styles/mermaid.css | 391 +++++ skills/inkform-framework/SKILL.md | 18 + templates/canopy/mdx-components.tsx | 7 +- templates/canopy/package.json | 3 +- templates/galley/mdx-components.tsx | 7 +- templates/galley/package.json | 3 +- templates/shadcn/mdx-components.tsx | 7 +- templates/shadcn/package.json | 3 +- 30 files changed, 2992 insertions(+), 133 deletions(-) create mode 100644 examples/inkform-docs/content/docs/guides/diagrams.mdx create mode 100644 packages/framework/src/mermaid/index.tsx create mode 100644 packages/framework/src/mermaid/render.ts create mode 100644 packages/framework/src/mermaid/viewer.tsx create mode 100644 packages/framework/src/remark-mermaid.test.tsx create mode 100644 packages/framework/src/remark-mermaid.ts create mode 100644 packages/framework/src/styles/mermaid.css diff --git a/CHANGELOG.md b/CHANGELOG.md index 74113c7..6f2e2d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,28 @@ All notable changes to this project are documented here. Format loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions track `packages/framework`'s own `package.json`. +## [0.6.0] — 2026-09-27 + +### Added + +- **Mermaid diagrams** (`@inkform/framework/mermaid`) — ` ```mermaid ` fences + (or ``) render as interactive diagrams: Ctrl/⌘ + scroll, + pinch, double-click, or keyboard to zoom; drag to pan; a fullscreen view with a + minimap for large graphs; copy source and SVG download. Colors come from the + `--fw-*` tokens and follow light/dark switches. A caption goes in the fence + meta: ` ```mermaid title="…" `. +- **Opt-in by design** — `mermaid` is an optional peer dependency. Sites that + never draw diagrams don't install it; unregistered fences render as a plain + source block. The scaffolded templates ship with it on. Readers only download + mermaid (and the viewer) on pages that have a diagram, when it nears the + viewport. +- `remarkMermaid`, exported from `@inkform/framework/mdx`, for hosts with their + own MDX pipeline. + +### Changed + +- Templates and examples now depend on `@inkform/framework@^0.6.0`. + ## [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/mdx.tsx b/packages/framework/src/mdx.tsx index a17978d..ef4445c 100644 --- a/packages/framework/src/mdx.tsx +++ b/packages/framework/src/mdx.tsx @@ -6,6 +6,9 @@ import rehypePrettyCode from 'rehype-pretty-code'; import rehypeSlug from 'rehype-slug'; import { visit } from 'unist-util-visit'; import { mdxComponents } from './components'; +import { remarkMermaid } from './remark-mermaid'; + +export { remarkMermaid } from './remark-mermaid'; const CALLOUT_NAMES = new Set(['info', 'warning', 'error', 'success', 'note', 'tip']); @@ -42,7 +45,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 +64,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 ( + + ); +} + +function Toolbar({ scale, api, copied, onCopy, onDownload, onExpand, onClose }: ToolbarProps) { + return ( +
+ api.current?.zoomOut()}> + + + + api.current?.zoomIn()}> + + + {onClose && ( + api.current?.reset()}> + + + )} +
+ ); +} + +/* --------------------------------------------------------------------------- + * 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