diff --git a/.changeset/crazy-jobs-see.md b/.changeset/crazy-jobs-see.md
new file mode 100644
index 00000000000..fb56d3f0877
--- /dev/null
+++ b/.changeset/crazy-jobs-see.md
@@ -0,0 +1,5 @@
+---
+'@mermaid-js/mermaid-local-editor': patch
+---
+
+feat: add local editor package for Mermaid diagrams
diff --git a/package.json b/package.json
index b307db8f11a..a64c75bf385 100644
--- a/package.json
+++ b/package.json
@@ -15,9 +15,15 @@
"git graph"
],
"scripts": {
+ "clean": "rimraf packages/mermaid/dist",
+ "copy:dompurify": "cpy node_modules/.pnpm/dompurify@*/node_modules/dompurify/dist/purify.min.js packages/mermaid/dist/mermaid-local-editor/vendor/ --flat",
+ "copy:mermaid": "cpy packages/mermaid/dist/mermaid.min.js packages/mermaid/dist/mermaid-local-editor/vendor/ --flat",
+ "copy:editor": "cpy \"packages/mermaid-local-editor/static/**/*\" packages/mermaid/dist/mermaid-local-editor",
+ "serve:dist": "sirv packages/mermaid/dist/mermaid-local-editor --port 8081 --dev --no-clear",
"build": "pnpm build:esbuild && pnpm build:types",
"build:esbuild": "pnpm run -r clean && tsx .esbuild/build.ts",
"build:mermaid": "pnpm build:esbuild --mermaid",
+ "build:mermaid:full": "pnpm clean && pnpm build:mermaid && pnpm copy:editor && pnpm copy:mermaid && pnpm copy:dompurify && pnpm serve:dist",
"build:viz": "pnpm build:esbuild --visualize",
"build:types": "pnpm --filter mermaid types:build-config && tsx .build/types.ts",
"build:types:watch": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly --watch",
@@ -133,6 +139,7 @@
"prettier-plugin-jsdoc": "^1.3.3",
"rimraf": "^6.0.1",
"rollup-plugin-visualizer": "^6.0.5",
+ "sirv-cli": "^3.0.1",
"start-server-and-test": "^2.1.3",
"tslib": "^2.8.1",
"tsx": "^4.20.6",
diff --git a/packages/mermaid-local-editor/README.md b/packages/mermaid-local-editor/README.md
new file mode 100644
index 00000000000..31943ec3468
--- /dev/null
+++ b/packages/mermaid-local-editor/README.md
@@ -0,0 +1,74 @@
+# Mermaid Local Editor
+
+Standalone local editor for Mermaid diagrams.
+Runs entirely from `dist/` with no external dependencies.
+
+---
+
+## Usage
+
+```sh
+pnpm build:mermaid:full
+```
+
+---
+
+## Build Pipeline
+
+The `build:mermaid:full` command performs the following steps:
+
+1. **Clean**
+
+ Removes the existing build output:
+
+ ```sh
+ pnpm clean
+ ```
+
+2. **Build Mermaid**
+
+ Compiles Mermaid using the repository build pipeline:
+
+ ```sh
+ pnpm build:mermaid
+ ```
+
+3. **Copy Editor**
+
+ Copies the local editor sources into the distribution directory:
+
+ ```sh
+ pnpm copy:editor
+ ```
+
+4. **Bundle Dependencies**
+
+ Copies required runtime dependencies into the editor bundle:
+
+ ```sh
+ pnpm copy:mermaid
+ pnpm copy:dompurify
+ ```
+
+5. **Serve**
+
+ Starts a local static server:
+
+ ```sh
+ pnpm serve:dist
+ ```
+
+---
+
+## Output
+
+After build, the editor is available at [`packages/mermaid/dist/mermaid-local-editor/`](../mermaid/dist/mermaid-local-editor):
+
+---
+
+## Notes
+
+- No external CDN dependencies are used
+- DOMPurify is bundled locally
+- The editor is fully offline-capable
+- Designed to run directly from the `dist/` directory
diff --git a/packages/mermaid-local-editor/package.json b/packages/mermaid-local-editor/package.json
new file mode 100644
index 00000000000..b7c18bbbc1b
--- /dev/null
+++ b/packages/mermaid-local-editor/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "@mermaid-js/mermaid-local-editor",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module"
+}
diff --git a/packages/mermaid-local-editor/static/app.js b/packages/mermaid-local-editor/static/app.js
new file mode 100644
index 00000000000..7d448d8414c
--- /dev/null
+++ b/packages/mermaid-local-editor/static/app.js
@@ -0,0 +1,80 @@
+import { initMermaid, state, IS_E2E } from './js/config.js';
+import { createStorage } from './js/storage.js';
+import { renderDiagram } from './js/renderer.js';
+import { setupUI, refreshList } from './js/ui.js';
+import { createNavigation } from './js/navigation.js';
+
+initMermaid();
+
+const srcPanel = document.getElementById('srcPanel');
+const preview = document.getElementById('preview');
+const diagramsSelect = document.getElementById('diagrams');
+const nameInput = document.getElementById('name');
+const storage = createStorage();
+const navigation = createNavigation({
+ state,
+ preview,
+ srcPanel,
+ applyTransform,
+});
+
+function render() {
+ void renderDiagram({
+ srcValue: srcPanel.value,
+ preview,
+ state,
+ IS_E2E,
+ applyTransform,
+ rebuildNavNodes: navigation.rebuildNavNodes,
+ });
+}
+
+function load(name) {
+ storage.setCurrent(name);
+ const d = storage.diagrams[name];
+
+ srcPanel.value = d.src;
+
+ // restore the view
+ state.scale = d.view?.scale ?? 1;
+ state.panX = d.view?.panX ?? 0;
+ state.panY = d.view?.panY ?? 0;
+
+ refreshList({ diagramsSelect, nameInput, storage });
+ render();
+ requestAnimationFrame(applyTransform);
+}
+
+function applyTransform() {
+ if (!state.iframeRef) {
+ return;
+ }
+
+ const svg = state.iframeRef.contentDocument?.querySelector('svg');
+ if (!svg) {
+ return;
+ }
+
+ state.panY = Math.max(-20000, Math.min(20000, state.panY));
+ state.panX = Math.max(-20000, Math.min(20000, state.panX));
+
+ svg.style.transform = `translate(${state.panX}px, ${state.panY}px) scale(${state.scale})`;
+
+ storage.updateCurrent({
+ view: { scale: state.scale, panX: state.panX, panY: state.panY },
+ });
+}
+
+setupUI({
+ src: srcPanel,
+ diagramsSelect,
+ nameInput,
+ storage,
+ state,
+ render,
+ load,
+ applyTransform,
+});
+
+navigation.setupKeyboardNav();
+load(storage.current);
diff --git a/packages/mermaid-local-editor/static/index.html b/packages/mermaid-local-editor/static/index.html
new file mode 100644
index 00000000000..7018d92707c
--- /dev/null
+++ b/packages/mermaid-local-editor/static/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+ Mermaid Local Editor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/mermaid-local-editor/static/js/config.js b/packages/mermaid-local-editor/static/js/config.js
new file mode 100644
index 00000000000..ed71337d365
--- /dev/null
+++ b/packages/mermaid-local-editor/static/js/config.js
@@ -0,0 +1,24 @@
+/* global mermaid */
+
+export const IS_E2E = navigator.webdriver || location.search.includes('graph=');
+
+export function initMermaid() {
+ mermaid.initialize({
+ startOnLoad: false,
+ theme: 'dark',
+ securityLevel: 'strict',
+ deterministicIds: true,
+ fontFamily: 'Arial',
+ htmlLabels: false,
+ flowchart: {
+ useMaxWidth: false,
+ },
+ });
+}
+
+export let state = {
+ scale: 1,
+ panX: 0,
+ panY: 0,
+ iframeRef: null,
+};
diff --git a/packages/mermaid-local-editor/static/js/navigation.js b/packages/mermaid-local-editor/static/js/navigation.js
new file mode 100644
index 00000000000..254f33ad5e4
--- /dev/null
+++ b/packages/mermaid-local-editor/static/js/navigation.js
@@ -0,0 +1,96 @@
+export function createNavigation({ state, preview, srcPanel, applyTransform }) {
+ let navNodes = [];
+ let navIndex = 0;
+
+ function rebuildNavNodes() {
+ navNodes = [];
+ navIndex = 0;
+
+ const svg = state.iframeRef?.contentDocument?.querySelector('svg');
+ if (!svg) {
+ return;
+ }
+
+ navNodes = [...svg.querySelectorAll('g.node')];
+ navIndex = 0;
+
+ if (navNodes.length) {
+ highlightCurrentNode();
+ centerCurrentNode();
+ }
+ }
+
+ function highlightCurrentNode() {
+ const svg = state.iframeRef?.contentDocument?.querySelector('svg');
+ if (!svg) {
+ return;
+ }
+
+ svg
+ .querySelectorAll('g.node.selected-node')
+ .forEach((n) => n.classList.remove('selected-node'));
+
+ const node = navNodes[navIndex];
+ if (node) {
+ node.classList.add('selected-node');
+ }
+ }
+
+ function centerCurrentNode() {
+ const node = navNodes[navIndex];
+ if (!node) {
+ return;
+ }
+
+ const nodeRect = node.getBoundingClientRect();
+ const contRect = preview.getBoundingClientRect();
+
+ const nodeCenterY = nodeRect.top + nodeRect.height / 6;
+ const contCenterY = contRect.top + contRect.height / 6;
+ const deltaY = contCenterY - nodeCenterY;
+
+ // Intentionally biased to upper-left instead of strict center,
+ // so forward nodes remain visible in LR / TD diagrams.
+ const nodeCenterX = nodeRect.left + nodeRect.width / 6;
+ const contCenterX = contRect.left + contRect.width / 6;
+ const deltaX = contCenterX - nodeCenterX;
+
+ state.panX += deltaX;
+ state.panY += deltaY;
+
+ applyTransform();
+ }
+
+ function setupKeyboardNav() {
+ window.addEventListener('keydown', (e) => {
+ if (document.activeElement === srcPanel) {
+ return;
+ }
+
+ if (e.key === 'ArrowDown') {
+ e.preventDefault();
+ if (!navNodes.length) {
+ rebuildNavNodes();
+ }
+ navIndex = Math.min(navIndex + 1, navNodes.length - 1);
+ highlightCurrentNode();
+ centerCurrentNode();
+ }
+
+ if (e.key === 'ArrowUp') {
+ e.preventDefault();
+ if (!navNodes.length) {
+ rebuildNavNodes();
+ }
+ navIndex = Math.max(navIndex - 1, 0);
+ highlightCurrentNode();
+ centerCurrentNode();
+ }
+ });
+ }
+
+ return {
+ rebuildNavNodes,
+ setupKeyboardNav,
+ };
+}
diff --git a/packages/mermaid-local-editor/static/js/renderer.js b/packages/mermaid-local-editor/static/js/renderer.js
new file mode 100644
index 00000000000..f4c1b67df54
--- /dev/null
+++ b/packages/mermaid-local-editor/static/js/renderer.js
@@ -0,0 +1,157 @@
+/* global mermaid, DOMPurify */
+
+export async function renderDiagram({
+ srcValue,
+ preview,
+ state,
+ IS_E2E,
+ applyTransform,
+ rebuildNavNodes,
+}) {
+ try {
+ const { svg } = await mermaid.render(IS_E2E ? 'm1' : 'm' + Date.now(), srcValue);
+
+ preview.replaceChildren();
+
+ if (IS_E2E) {
+ const cleanSvg = DOMPurify.sanitize(svg, {
+ ADD_TAGS: ['foreignObject'],
+ ADD_ATTR: ['xmlns'],
+ });
+
+ const doc = new DOMParser().parseFromString(cleanSvg, 'image/svg+xml');
+ preview.replaceChildren(doc.documentElement);
+ return;
+ }
+
+ const iframe = document.createElement('iframe');
+ iframe.sandbox = 'allow-same-origin';
+ iframe.style.width = '100%';
+ iframe.style.height = '100%';
+ iframe.style.border = 'none';
+
+ preview.appendChild(iframe);
+ state.iframeRef = iframe;
+
+ const cleanSvg = DOMPurify.sanitize(svg, {
+ ADD_TAGS: ['foreignObject'],
+ ADD_ATTR: ['xmlns'],
+ });
+
+ const parsed = new DOMParser().parseFromString(cleanSvg, 'image/svg+xml');
+ const svgEl = parsed.documentElement;
+
+ svgEl.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
+
+ svgEl.querySelectorAll('*').forEach((el) => {
+ [...el.attributes].forEach((attr) => {
+ if (attr.name.startsWith('on')) {
+ el.removeAttribute(attr.name);
+ }
+ });
+ });
+
+ const doc = iframe.contentDocument;
+ doc.open();
+ doc.close();
+ doc.body.appendChild(doc.importNode(svgEl, true));
+
+ setTimeout(() => {
+ rebuildNavNodes();
+ }, 0);
+
+ requestAnimationFrame(() => {
+ const svgEl = iframe.contentDocument?.querySelector('svg');
+ if (!svgEl) {
+ return;
+ }
+
+ svgEl.style.transformOrigin = '0 0';
+ svgEl.style.display = 'block';
+ });
+
+ const style = doc.createElement('style');
+ style.textContent = `
+ text { fill: #e6e6e6 !important; }
+ .node rect, .node polygon, .node path {
+ transition: fill 120ms ease, filter 120ms ease;
+ }
+
+ .node:hover rect,
+ .node:hover polygon,
+ .node:hover path {
+ fill: rgba(0, 170, 255, 0.25);
+ filter: drop-shadow(0 0 11px rgba(0, 170, 255, 0.6));
+ }
+
+ g.node.selected-node rect,
+ g.node.selected-node polygon,
+ g.node.selected-node path {
+ fill: rgba(0, 170, 255, 0.35) !important;
+ stroke: #00aaff !important;
+ stroke-width: 2px !important;
+ filter: drop-shadow(0 0 16px rgba(0, 170, 255, 1)) !important;
+ }
+
+ g.node.selected-node text {
+ fill: #ffffff !important;
+ font-weight: bold !important;
+ }
+
+ body {
+ margin: 0;
+ overflow: hidden;
+ }
+ `;
+ doc.head.appendChild(style);
+
+ iframe.addEventListener('load', () => {
+ window.focus();
+ });
+
+ doc.onwheel = null;
+ doc.onmousedown = null;
+ doc.onmouseup = null;
+ doc.onmousemove = null;
+
+ let isPanningLocal = false;
+ let startXLocal = 0;
+ let startYLocal = 0;
+
+ doc.onwheel = (e) => {
+ e.preventDefault();
+ state.scale += e.deltaY * -0.0015;
+ state.scale = Math.min(Math.max(0.2, state.scale), 4);
+ applyTransform();
+ };
+
+ doc.onmousedown = (e) => {
+ isPanningLocal = true;
+ startXLocal = e.clientX - state.panX;
+ startYLocal = e.clientY - state.panY;
+ doc.body.style.cursor = 'grabbing';
+ };
+
+ doc.onmouseup = () => {
+ isPanningLocal = false;
+ doc.body.style.cursor = 'default';
+ };
+
+ doc.onmousemove = (e) => {
+ if (!isPanningLocal) {
+ return;
+ }
+ state.panX = e.clientX - startXLocal;
+ state.panY = e.clientY - startYLocal;
+ applyTransform();
+ };
+ } catch (e) {
+ preview.replaceChildren();
+
+ const pre = document.createElement('pre');
+ pre.style.color = '#ff6b6b';
+ pre.textContent = e.message;
+
+ preview.appendChild(pre);
+ }
+}
diff --git a/packages/mermaid-local-editor/static/js/storage.js b/packages/mermaid-local-editor/static/js/storage.js
new file mode 100644
index 00000000000..5cf4668432e
--- /dev/null
+++ b/packages/mermaid-local-editor/static/js/storage.js
@@ -0,0 +1,50 @@
+export function createStorage() {
+ let diagrams = JSON.parse(localStorage.getItem('mermaid-diagrams') || '{}');
+ let current = localStorage.getItem('mermaid-current') || 'main';
+
+ if (!diagrams[current]) {
+ diagrams[current] = {
+ src: `flowchart LR\n UI --> RuntimeBus --> Orchestrator --> Agents`,
+ view: { scale: 1, panX: 0, panY: 0 },
+ };
+ }
+
+ function save() {
+ localStorage.setItem('mermaid-diagrams', JSON.stringify(diagrams));
+ localStorage.setItem('mermaid-current', current);
+ }
+
+ return {
+ get diagrams() {
+ return diagrams;
+ },
+ get current() {
+ return current;
+ },
+
+ setCurrent(name) {
+ current = name;
+ save();
+ },
+
+ updateCurrent(data) {
+ diagrams[current] = { ...diagrams[current], ...data };
+ save();
+ },
+
+ deleteCurrent() {
+ delete diagrams[current];
+ current = Object.keys(diagrams)[0] || 'main';
+ save();
+ },
+
+ create(name) {
+ diagrams[name] = {
+ src: 'flowchart LR\n A --> B',
+ view: { scale: 1, panX: 0, panY: 0 },
+ };
+ current = name;
+ save();
+ },
+ };
+}
diff --git a/packages/mermaid-local-editor/static/js/ui.js b/packages/mermaid-local-editor/static/js/ui.js
new file mode 100644
index 00000000000..6d5c03228a9
--- /dev/null
+++ b/packages/mermaid-local-editor/static/js/ui.js
@@ -0,0 +1,117 @@
+export function refreshList({ diagramsSelect, nameInput, storage }) {
+ diagramsSelect.innerHTML = '';
+ Object.keys(storage.diagrams).forEach((k) => {
+ const opt = document.createElement('option');
+ opt.value = k;
+ opt.textContent = k;
+ diagramsSelect.appendChild(opt);
+ });
+ diagramsSelect.value = storage.current;
+ nameInput.value = storage.current;
+}
+
+export function setupUI({
+ src,
+ diagramsSelect,
+ nameInput,
+ storage,
+ state,
+ render,
+ load,
+ applyTransform,
+}) {
+ document.getElementById('save').onclick = () => {
+ const name = nameInput.value.trim();
+ if (!name) {
+ return;
+ }
+
+ storage.setCurrent(name);
+ storage.updateCurrent({
+ src: src.value,
+ view: { scale: state.scale, panX: state.panX, panY: state.panY },
+ });
+ refreshList({ diagramsSelect, nameInput, storage });
+ };
+
+ document.getElementById('new').onclick = () => {
+ const name = prompt('Enter diagram name');
+ if (!name) {
+ return;
+ }
+
+ storage.create(name);
+ load(name);
+ };
+
+ document.getElementById('del').onclick = () => {
+ if (!confirm(`Delete diagram "${storage.current}"?`)) {
+ return;
+ }
+
+ storage.deleteCurrent();
+ load(storage.current);
+ };
+
+ document.getElementById('resetView').onclick = () => {
+ state.scale = 1;
+ state.panX = 0;
+ state.panY = 0;
+ applyTransform(); // this will save the reset to storage.diagrams[storage.current].view
+ };
+
+ document.getElementById('exportSvg').onclick = () => {
+ if (!state.iframeRef) {
+ return;
+ }
+
+ const svg = state.iframeRef.contentDocument?.querySelector('svg');
+ if (!svg) {
+ return;
+ }
+
+ const blob = new Blob([svg.outerHTML], { type: 'image/svg+xml' });
+ const url = URL.createObjectURL(blob);
+
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = `${storage.current}.svg`;
+ a.click();
+
+ URL.revokeObjectURL(url);
+ };
+
+ diagramsSelect.onchange = () => load(diagramsSelect.value);
+
+ let saveTimer;
+ src.addEventListener('input', () => {
+ render();
+
+ clearTimeout(saveTimer);
+ saveTimer = setTimeout(() => {
+ if (storage.diagrams[storage.current]) {
+ storage.updateCurrent({ src: src.value });
+ }
+ }, 300);
+ });
+
+ const toolbar = document.getElementById('srcPanel');
+ const toggleToolbarBtn = document.getElementById('toggleToolbar');
+
+ let toolbarCollapsed = localStorage.getItem('toolbar-collapsed') === '1';
+
+ function applyToolbarState() {
+ toolbar.classList.toggle('collapsed', toolbarCollapsed);
+ toggleToolbarBtn.textContent = toolbarCollapsed ? '☰' : '✕';
+ toggleToolbarBtn.title = toolbarCollapsed ? 'Show toolbar' : 'Hide toolbar';
+ }
+
+ toggleToolbarBtn.onclick = () => {
+ toolbarCollapsed = !toolbarCollapsed;
+ localStorage.setItem('toolbar-collapsed', toolbarCollapsed ? '1' : '0');
+ applyToolbarState();
+ };
+
+ applyToolbarState();
+ refreshList({ diagramsSelect, nameInput, storage });
+}
diff --git a/packages/mermaid-local-editor/static/styles.css b/packages/mermaid-local-editor/static/styles.css
new file mode 100644
index 00000000000..1559f434586
--- /dev/null
+++ b/packages/mermaid-local-editor/static/styles.css
@@ -0,0 +1,111 @@
+body {
+ margin: 0;
+ display: grid;
+ grid-template-rows: 40px 1fr;
+ height: 100vh;
+ background: #0f1115;
+ color: #ddd;
+}
+#toolbar {
+ position: relative;
+ display: flex;
+ gap: 8px;
+ padding: 6px 10px;
+ background: #0b0d12;
+ border-bottom: 1px solid #222;
+ transition:
+ transform 0.25s ease,
+ opacity 0.2s ease,
+ height 0.25s ease;
+ will-change: transform, opacity, height;
+}
+#toolbar input,
+#toolbar select,
+#toolbar button {
+ background: #111;
+ color: #ddd;
+ border: 1px solid #333;
+ padding: 4px 8px;
+}
+#srcPanel {
+ z-index: 1000;
+}
+#srcPanel.collapsed {
+ transform: translateY(-100%);
+ opacity: 0;
+ height: 0;
+ padding: 0 8px;
+ overflow: hidden;
+}
+
+/* Node highlight styling */
+svg .node rect,
+svg .node polygon,
+svg .node path {
+ transition:
+ fill 120ms ease,
+ filter 120ms ease;
+}
+
+svg .node:hover rect,
+svg .node:hover polygon,
+svg .node:hover path {
+ fill: rgba(0, 170, 255, 0.25); /* fon */
+ filter: drop-shadow(0 0 11px rgba(0, 170, 255, 0.6)); /* glow */
+}
+
+/* Keyboard-selected node styling */
+svg g.node.selected-node rect,
+svg g.node.selected-node polygon,
+svg g.node.selected-node path {
+ fill: rgba(0, 170, 255, 0.28);
+ filter: drop-shadow(0 0 14px rgba(0, 170, 255, 0.9));
+ transition:
+ fill 120ms ease,
+ filter 120ms ease;
+}
+
+p,
+div,
+div > * {
+ user-select: none;
+}
+
+#toggleToolbar {
+ cursor: pointer;
+ background: #1f2020;
+ color: #ccc;
+ border: 1px solid #2a2a2a;
+ border-radius: 6px;
+ padding: 4px 8px;
+}
+
+#preview svg {
+ width: 100%;
+ height: auto;
+ padding: 12px;
+ position: relative;
+ overflow: visible;
+ display: block; /* removes inline centering */
+ margin: 0; /* removes auto-indents */
+ transform-origin: 0 0; /* transformation anchor */
+}
+#preview svg g {
+ transform-origin: 0 0;
+}
+#main {
+ display: grid;
+ grid-template-columns: 0.5fr 1fr;
+ height: calc(100vh - 40px);
+ overflow: hidden;
+}
+textarea {
+ width: 100%;
+ height: 100%;
+ background: #0b0d12;
+ color: #e6e6e6;
+ border: none;
+ padding: 12px;
+ font-family: monospace;
+ font-size: 14px;
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index edc7575b012..afcc5230ec1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -199,6 +199,9 @@ importers:
rollup-plugin-visualizer:
specifier: ^6.0.5
version: 6.0.5(rollup@4.60.1)
+ sirv-cli:
+ specifier: ^3.0.1
+ version: 3.0.1
start-server-and-test:
specifier: ^2.1.3
version: 2.1.3
@@ -468,6 +471,8 @@ importers:
specifier: ^2.0.2
version: 2.0.2
+ packages/mermaid-local-editor: {}
+
packages/mermaid-zenuml:
dependencies:
'@zenuml/core':
@@ -4874,6 +4879,10 @@ packages:
resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
engines: {node: ^14.18.0 || >=16.10.0}
+ console-clear@1.1.1:
+ resolution: {integrity: sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==}
+ engines: {node: '>=4'}
+
console.table@0.10.0:
resolution: {integrity: sha512-dPyZofqggxuvSf7WXvNjuRfnsOk1YazkVP8FdxH4tcH2c37wc79/Yl6Bhr7Lsu00KMgy2ql/qCMuNu8xctZM8g==}
engines: {node: '> 0.10'}
@@ -6224,6 +6233,10 @@ packages:
resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==}
engines: {node: '>=8.0.0'}
+ get-port@5.1.1:
+ resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==}
+ engines: {node: '>=8'}
+
get-proto@1.0.1:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'}
@@ -7224,6 +7237,10 @@ packages:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
+ kleur@4.1.5:
+ resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
+ engines: {node: '>=6'}
+
kolorist@1.8.0:
resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
@@ -7309,6 +7326,10 @@ packages:
resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==}
engines: {node: '>=6.11.5'}
+ local-access@1.1.0:
+ resolution: {integrity: sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw==}
+ engines: {node: '>=6'}
+
local-pkg@1.1.2:
resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==}
engines: {node: '>=14'}
@@ -8748,6 +8769,10 @@ packages:
rxjs@7.8.2:
resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==}
+ sade@1.8.1:
+ resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
+ engines: {node: '>=6'}
+
safe-array-concat@1.1.3:
resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
engines: {node: '>=0.4'}
@@ -8805,6 +8830,10 @@ packages:
resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==}
engines: {node: '>=10'}
+ semiver@1.1.0:
+ resolution: {integrity: sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==}
+ engines: {node: '>=6'}
+
semver@5.7.2:
resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
hasBin: true
@@ -8946,6 +8975,11 @@ packages:
simple-get@4.0.1:
resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
+ sirv-cli@3.0.1:
+ resolution: {integrity: sha512-ICXaF2u6IQhLZ0EXF6nqUF4YODfSQSt+mGykt4qqO5rY+oIiwdg7B8w2PVDBJlQulaS2a3J8666CUoDoAuCGvg==}
+ engines: {node: '>=18'}
+ hasBin: true
+
sirv@3.0.2:
resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==}
engines: {node: '>=18'}
@@ -9356,6 +9390,10 @@ packages:
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
+ tinydate@1.3.0:
+ resolution: {integrity: sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==}
+ engines: {node: '>=4'}
+
tinyexec@0.3.2:
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
@@ -15242,6 +15280,8 @@ snapshots:
consola@3.4.2: {}
+ console-clear@1.1.1: {}
+
console.table@0.10.0:
dependencies:
easy-table: 1.1.0
@@ -16990,6 +17030,8 @@ snapshots:
get-package-type@0.1.0: {}
+ get-port@5.1.1: {}
+
get-proto@1.0.1:
dependencies:
dunder-proto: 1.0.1
@@ -18208,6 +18250,8 @@ snapshots:
kind-of@6.0.3: {}
+ kleur@4.1.5: {}
+
kolorist@1.8.0: {}
ky@0.30.0: {}
@@ -18314,6 +18358,8 @@ snapshots:
loader-runner@4.3.0: {}
+ local-access@1.1.0: {}
+
local-pkg@1.1.2:
dependencies:
mlly: 1.8.0
@@ -19982,6 +20028,10 @@ snapshots:
dependencies:
tslib: 2.8.1
+ sade@1.8.1:
+ dependencies:
+ mri: 1.2.0
+
safe-array-concat@1.1.3:
dependencies:
call-bind: 1.0.9
@@ -20042,6 +20092,8 @@ snapshots:
'@types/node-forge': 1.3.14
node-forge: 1.3.1
+ semiver@1.1.0: {}
+
semver@5.7.2: {}
semver@6.3.1: {}
@@ -20259,6 +20311,17 @@ snapshots:
once: 1.4.0
simple-concat: 1.0.1
+ sirv-cli@3.0.1:
+ dependencies:
+ console-clear: 1.1.1
+ get-port: 5.1.1
+ kleur: 4.1.5
+ local-access: 1.1.0
+ sade: 1.8.1
+ semiver: 1.1.0
+ sirv: 3.0.2
+ tinydate: 1.3.0
+
sirv@3.0.2:
dependencies:
'@polka/url': 1.0.0-next.29
@@ -20759,6 +20822,8 @@ snapshots:
tinybench@2.9.0: {}
+ tinydate@1.3.0: {}
+
tinyexec@0.3.2: {}
tinyexec@1.0.1: {}
diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json
index 7b7934881a3..d030d903688 100644
--- a/tsconfig.eslint.json
+++ b/tsconfig.eslint.json
@@ -18,6 +18,9 @@
"./demos/dev",
"./vite.config.ts",
"./vitest.workspace.js",
- "eslint.config.js"
+ "eslint.config.js",
+ "packages/mermaid-local-editor/static/js/**/*.js",
+ "packages/mermaid-local-editor/**/*.js",
+ "packages/mermaid-local-editor/**/*.html"
]
}