zombie-mermaid 3.2.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/dist/cli.js +1 -0
- package/dist/index.cjs +1 -3
- package/dist/index.d.cts +2 -6
- package/dist/index.d.ts +2 -6
- package/dist/index.js +5 -435
- package/package.json +13 -11
- package/src/__tests__/ascii-draw-bundles.test.ts +4 -2
- package/src/__tests__/ascii-edge-bundling-routing.test.ts +1 -1
- package/src/__tests__/ascii-edge-cross-style-overlap.test.ts +1 -1
- package/src/__tests__/ascii-grid-deep-chain.test.ts +1 -1
- package/src/__tests__/ascii-nested-subgraph-sibling-order-444.test.ts +1 -1
- package/src/__tests__/ascii-nonmember-beside-frame-1283.test.ts +108 -0
- package/src/__tests__/ascii-package-boundary.test.ts +4 -6
- package/src/__tests__/ascii-parallel-edges-329.test.ts +1 -1
- package/src/__tests__/ascii-parallel-lane-border-1230.test.ts +71 -0
- package/src/__tests__/ascii-reverse-direction-edges-629.test.ts +1 -1
- package/src/__tests__/ascii-stacked-frame-geometry-1285.test.ts +93 -0
- package/src/__tests__/ascii-subgraph-bbox.test.ts +1 -1
- package/src/__tests__/ascii-subgraph-later-edgeless-301.test.ts +1 -1
- package/src/__tests__/class-parser.test.ts +30 -10
- package/src/__tests__/class-styling.test.ts +7 -3
- package/src/__tests__/compound-flat-layout.test.ts +901 -0
- package/src/__tests__/edge-approach-direction.test.ts +1 -1
- package/src/__tests__/elk-layout-cache.test.ts +1 -1
- package/src/__tests__/er-integration.test.ts +7 -4
- package/src/__tests__/expanded-shapes.test.ts +1 -1
- package/src/__tests__/flowchart-back-edge-prereversal-1239.test.ts +212 -0
- package/src/__tests__/flowchart-syntax-gaps.test.ts +1 -1
- package/src/__tests__/interactivity-config.test.ts +1 -1
- package/src/__tests__/layout-engine.test.ts +1 -1
- package/src/__tests__/linkstyle.test.ts +1 -1
- package/src/__tests__/multiline-labels.test.ts +1 -1
- package/src/__tests__/parser.test.ts +28 -1
- package/src/__tests__/render-options-per-type.test.ts +1 -1
- package/src/__tests__/self-loop-edges.test.ts +1 -1
- package/src/__tests__/state-composite-order-1287.test.ts +132 -0
- package/src/__tests__/state-flow-order-1240.test.ts +113 -0
- package/src/__tests__/state-styling.test.ts +1 -1
- package/src/__tests__/styles.test.ts +20 -1
- package/src/__tests__/subgraph-title-edge-gap-1239.test.ts +238 -0
- package/src/__tests__/svg-csp-style-options.test.ts +2 -1
- package/src/__tests__/workspace-package-boundaries.test.ts +11 -25
- package/src/index.ts +1 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/src/parser.ts +0 -1308
package/README.md
CHANGED
|
@@ -48,11 +48,14 @@ Diagrams are essential for AI-assisted programming. When you're working with an
|
|
|
48
48
|
|
|
49
49
|
The **Bundle Size** badge above tracks the gzipped size of `zombie-mermaid`'s
|
|
50
50
|
main entry point (`dist/index.js`) together with the `@zombie-mermaid/*`
|
|
51
|
-
workspace packages it imports
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
workspace packages it imports, **plus the SVG renderer's third-party
|
|
52
|
+
dependencies** ([ELK.js](https://github.com/kieler/elkjs) and `entities`,
|
|
53
|
+
which make up most of the SVG renderer's real weight), and updates
|
|
54
|
+
automatically with every release — the same badge/CI-tracked pattern already
|
|
55
|
+
backing the coverage and CI status badges. The standalone renderer packages
|
|
56
|
+
under [Packages](#packages) get the same measurement for their own dependency
|
|
57
|
+
closure: the SVG badge is labelled "incl. deps" because it counts ELK.js and
|
|
58
|
+
`entities`, while the ASCII renderer has no third-party dependencies to count. Need ASCII rendering only? `import { renderMermaidASCII }
|
|
56
59
|
from 'zombie-mermaid/ascii'` skips [ELK.js](https://github.com/kieler/elkjs),
|
|
57
60
|
the layout engine the SVG renderer depends on, for a substantially smaller
|
|
58
61
|
bundle.
|
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ import { extname as V, format as H, parse as G } from "node:path";
|
|
|
4
4
|
import { THEMES as B, escapeXml as q, isDirection as j, isWideChar as K } from "@zombie-mermaid/core";
|
|
5
5
|
import { access as J, readFile as Z, writeFile as Q } from "node:fs/promises";
|
|
6
6
|
import { diagramColorsToAsciiTheme as ee, renderMermaidASCII as O } from "@zombie-mermaid/ascii-renderer";
|
|
7
|
+
import "@zombie-mermaid/mermaid-parser";
|
|
7
8
|
import { renderMermaidSVG as z } from "@zombie-mermaid/svg-renderer";
|
|
8
9
|
import { createServer as te } from "node:http";
|
|
9
10
|
import { StdioServerTransport as ne } from "@modelcontextprotocol/sdk/server/stdio.js";
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@zombie-mermaid/core"),t=require("@zombie-mermaid/mermaid-parser"),n=require("@zombie-mermaid/ascii-renderer"),r=require("@zombie-mermaid/svg-renderer");function
|
|
2
|
-
`).map(e=>e.trim())),r=c((0,e.splitStatementsByLine)(t));if(r.length===0)throw Error(`Empty mermaid diagram`);let i=r[0],a=/^stateDiagram(-v2)?\s*$/i.test(i.text)?d(r):u(r);return a.initConfig=n,a}function u(t){let n=t[0];if(n===void 0)throw Error(`parseFlowchart called with no lines`);let r=n.text,s=r.match(/^(?:graph|flowchart)\s+(TD|TB|LR|BT|RL)\s*$/i);if(!s){let e=r.match(/^(?:graph|flowchart)\b\s*(.*)$/i);if(e){let t=e[1].trim();throw Error(t.length>0?`Line ${n.line}: Invalid direction "${t}" in header "${r}". Expected one of: TD, TB, LR, BT, RL.`:`Line ${n.line}: Missing direction in header "${r}". Expected e.g. "graph TD" or "flowchart LR" — one of: TD, TB, LR, BT, RL.`)}let t=o(r),i=t&&t.toLowerCase()!==r.trim().toLowerCase()?` Did you mean "${t}"?`:``;throw Error(`Line ${n.line}: Invalid mermaid header: "${r}".${i} Supported headers: ${a}.`)}let c={direction:(0,e.toDirection)(s[1]),nodes:new Map,edges:[],subgraphs:[],classDefs:new Map,classAssignments:new Map,nodeStyles:new Map,linkStyles:new Map,interactions:new Map},l=[];for(let n=1;n<t.length;n++){let r=t[n].text;if((0,e.tryApplyClassDef)(r,c)||(0,e.tryApplyClassAssignment)(r,c)||(0,e.tryApplyStyleStatement)(r,c))continue;if(/^click\s+/i.test(r)){w(r,c);continue}if(E(r,c))continue;let a=r.match(/^linkStyle\s+(default|[\d,\s]+)\s+(.+)$/);if(a){let t=a[1].trim(),n=(0,e.parseStyleProps)(a[2]);if(t==="default")c.linkStyles.set(`default`,{...c.linkStyles.get(`default`),...n});else{let e=t.split(`,`).map(e=>parseInt(e.trim(),10));for(let t of e)isNaN(t)||c.linkStyles.set(t,{...c.linkStyles.get(t),...n})}continue}let o=r.match(/^direction\s+(TD|TB|LR|BT|RL)\s*$/i);if(o&&l.length>0){l[l.length-1].direction=(0,e.toDirection)(o[1]);continue}let s=r.match(/^subgraph\s+(.+)$/);if(s){let t=s[1].trim(),n=t.match(/^([^\s[]+)\s*\[(.+)\]$/),r,a;n?(r=n[1],a=(0,e.normalizeBrTags)(i(n[2]))):(a=(0,e.normalizeBrTags)(i(t)),r=a.replace(/\s+/g,`_`).replace(/[^\p{L}\p{N}_-]/gu,``));let o={id:r,label:a,nodeIds:[],children:[]};l.push(o);continue}if(r===`end`){let e=l.pop();e&&(l.length>0?l[l.length-1].children.push(e):c.subgraphs.push(e));continue}A(r,c,l)}return c}function d(t){let n={direction:`TD`,nodes:new Map,edges:[],subgraphs:[],classDefs:new Map,classAssignments:new Map,nodeStyles:new Map,linkStyles:new Map,interactions:new Map},r=[],i=new Set,a=0,o=0;for(let s=1;s<t.length;s++){let c=t[s].text;if((0,e.tryApplyClassDef)(c,n)||(0,e.tryApplyClassAssignment)(c,n)||(0,e.tryApplyStyleStatement)(c,n))continue;let l=c.match(/^direction\s+(TD|TB|LR|BT|RL)\s*$/i);if(l){r.length>0?r[r.length-1].direction=(0,e.toDirection)(l[1]):n.direction=(0,e.toDirection)(l[1]);continue}let u=c.match(/^linkStyle\s+(default|[\d,\s]+)\s+(.+)$/);if(u){let t=u[1].trim(),r=(0,e.parseStyleProps)(u[2]);if(t==="default")n.linkStyles.set(`default`,{...n.linkStyles.get(`default`),...r});else{let e=t.split(`,`).map(e=>parseInt(e.trim(),10));for(let t of e)isNaN(t)||n.linkStyles.set(t,{...n.linkStyles.get(t),...r})}continue}if(E(c,n))continue;let d=c.match(/^state\s+(?:"([^"]+)"\s+as\s+)?([\w\p{L}]+)\s*\{$/u);if(d){let e=d[1]??d[2],t=d[2],a={id:t,label:e,nodeIds:[],children:[]};r.push(a),i.add(t),n.nodes.delete(t);continue}if(c===`}`){let e=r.pop();e&&(r.length>0?r[r.length-1].children.push(e):n.subgraphs.push(e));continue}let h=c.match(/^state\s+"([^"]+)"\s+as\s+([\w\p{L}]+)\s*$/u);if(h){let t=(0,e.normalizeBrTags)(h[1]),i=h[2];f(n,r,i,t);continue}let g=c.match(/^(\[\*\]|[\w\p{L}-]+)(?::::([\w][\w-]*))?\s*(?:([\w-]+)@)?-->\s*(\[\*\]|[\w\p{L}-]+)(?::::([\w][\w-]*))?(?:\s*:\s*(.+))?$/u);if(g){let t=g[1],s=g[2],c=g[3],l=g[4],u=g[5],d=g[6]?.trim(),f=d?(0,e.normalizeBrTags)(d):void 0;t===`[*]`?(a++,t=`_start${a>1?a:``}`,p(n,r,{id:t,label:``,shape:`state-start`})):i.has(t)||m(n,r,t),l===`[*]`?(o++,l=`_end${o>1?o:``}`,p(n,r,{id:l,label:``,shape:`state-end`})):i.has(l)||m(n,r,l),s!==void 0&&n.classAssignments.set(t,s),u!==void 0&&n.classAssignments.set(l,u),n.edges.push({source:t,target:l,label:f,style:`solid`,hasArrowStart:!1,hasArrowEnd:!0,...c===void 0?{}:{id:c}});continue}let _=c.match(/^([\w\p{L}-]+):::([\w][\w-]*)\s*$/u);if(_){let e=_[1];i.has(e)||m(n,r,e),n.classAssignments.set(e,_[2]);continue}let v=c.match(/^([\w\p{L}-]+)\s*:\s*(.+)$/u);if(v){let t=v[1];f(n,r,t,(0,e.normalizeBrTags)(v[2].trim()));continue}}for(let e of n.classAssignments.keys())!n.nodes.has(e)&&!i.has(e)&&m(n,[],e);return n}function f(e,t,n,r){let i=e.nodes.get(n);i&&(i.label=r),p(e,t,{id:n,label:r,shape:`rounded`})}function p(e,t,n){if(e.nodes.has(n.id)||e.nodes.set(n.id,n),t.length>0){let e=t[t.length-1];e.nodeIds.includes(n.id)||e.nodeIds.push(n.id)}}function m(e,t,n){if(!e.nodes.has(n))p(e,t,{id:n,label:n,shape:`rounded`});else if(t.length>0){let e=t[t.length-1];e.nodeIds.includes(n)||e.nodeIds.push(n)}}var h=/^(<|o|x)?(-{2,}|={2,}|-\.+-|~{3,})(>|o|x)?(?:\|([^|]*)\|)?/,g=new Set([`--`,`==`]);function _(e){if(e===`o`)return`circle`;if(e===`x`)return`cross`}var v=/^(<|o|x)?(--|-\.|==)\s+(.+?)\s+(-{2,}[>ox]|={2,}[>ox]|\.+-[>ox]|-{3,}|={3,}|-\.+-)/,y=[{regex:/^([\w\p{L}-]+)\(\(\(((?:"[^"]*"|(?!\)\)\)).)+)\)\)\)/u,shape:`doublecircle`},{regex:/^([\w\p{L}-]+)\(\[((?:"[^"]*"|(?!\]\)).)+)\]\)/u,shape:`stadium`},{regex:/^([\w\p{L}-]+)\(\(((?:"[^"]*"|(?!\)\)).)+)\)\)/u,shape:`circle`},{regex:/^([\w\p{L}-]+)\[\[((?:"[^"]*"|(?!\]\]).)+)\]\]/u,shape:`subroutine`},{regex:/^([\w\p{L}-]+)\[\(((?:"[^"]*"|(?!\)\]).)+)\)\]/u,shape:`cylinder`},{regex:/^([\w\p{L}-]+)\[\/((?:"[^"]*"|(?![\\/]\]).)+)([\\/])\]/u,shape:e=>e===`\\`?`trapezoid`:`parallelogram`},{regex:/^([\w\p{L}-]+)\[\\((?:"[^"]*"|(?![\\/]\]).)+)([\\/])\]/u,shape:e=>e===`/`?`trapezoid-alt`:`parallelogram-alt`},{regex:/^([\w\p{L}-]+)>((?:"[^"]*"|(?!\]).)+)\]/u,shape:`asymmetric`},{regex:/^([\w\p{L}-]+)\{\{((?:"[^"]*"|(?!\}\}).)+)\}\}/u,shape:`hexagon`},{regex:/^([\w\p{L}-]+)\[((?:"[^"]*"|(?!\]).)+)\]/u,shape:`rectangle`},{regex:/^([\w\p{L}-]+)\(((?:"[^"]*"|(?!\)).)+)\)/u,shape:`rounded`},{regex:/^([\w\p{L}-]+)\{((?:"[^"]*"|(?!\}).)+)\}/u,shape:`diamond`}],b=/^([\w\p{L}]+(?:-[\w\p{L}]+)*)/u,x=/^([\w\p{L}-]+)(?=@\{)/u;function S(e){if(e.shape)return(0,t.resolveShapeName)(e.shape)??`rectangle`;if(e.icon!==void 0||e.img!==void 0)switch(e.form?.toLowerCase()){case`circle`:return`circle`;case`rounded`:return`rounded`;default:return`rectangle`}return`rectangle`}function C(e,t){return t.label!==void 0&&t.label.length>0?t.label:t.icon?t.icon:t.img?t.img:e}function w(t,n){(0,e.applyClickStatement)(t,n.interactions)}var T=/^([\w-]+)(?=@\{)/;function E(e,n){let r=e.match(T);if(!r||!n.edges.some(e=>e.id===r[1]))return!1;let i=(0,t.matchExpandedBlock)(e.slice(r[1].length));return i?(D(n,r[1],(0,t.parseExpandedMeta)(i.body)),!0):!1}function D(e,t,n){for(let r of e.edges)r.id===t&&(n.animate!==void 0&&(r.animate=n.animate.toLowerCase()!==`false`),n.animation!==void 0&&(r.animate=!0))}var O=/^:::([\w][\w-]*)/,k=/^([\w\p{L}-]+):::([\w][\w-]*)/u;function A(t,n,r){let i=t.trim(),a=j(i,n,r);if(!a||a.ids.length===0)return;i=a.remaining.trim();let o=a.ids;for(;i.length>0;){let t,a,s,c,l,u,d,f=i.match(/^([\w-]+)@(?=[-=<~ox])/);f&&(d=f[1],i=i.slice(f[0].length));let p=i.match(h),m=p?.[2],y=p?.[1],b=p?.[3];if(p&&m!==void 0&&!(y===void 0&&b===void 0&&g.has(m))){t=y!==void 0,l=_(y);let n=p[4]?.trim();c=n?(0,e.normalizeBrTags)(n):void 0,i=i.slice(p[0].length).trim(),a=F(m),s=b!==void 0,u=_(b)}else{let n=i.match(v);if(!n)break;t=!!n[1],l=_(n[1]);let r=n[3].trim();c=r?(0,e.normalizeBrTags)(r):void 0;let o=n[2],d=n[4];i=i.slice(n[0].length).trim(),a=I(o,d),u=_(d.slice(-1)),s=d.endsWith(`>`)||u!==void 0}let x=j(i,n,r);if(!x||x.ids.length===0)break;i=x.remaining.trim();for(let e of o)for(let r of x.ids)n.edges.push({source:e,target:r,label:c,style:a,hasArrowStart:t,hasArrowEnd:s,...l===void 0?{}:{startMarker:l},...u===void 0?{}:{endMarker:u},...d===void 0?{}:{id:d}});o=x.ids}}function j(e,t,n){let r=M(e,t,n);if(!r)return null;let i=[r.id],a=r.remaining.trim();for(;a.startsWith(`&`);){a=a.slice(1).trim();let e=M(a,t,n);if(!e)break;i.push(e.id),a=e.remaining.trim()}return{ids:i,remaining:a}}function M(n,r,i){let a=null,o=n,s,c=o.match(k);c&&(s=c[2],o=c[1]+o.slice(c[0].length));let l=o.match(x);if(l){let n=l[1],s=(0,t.matchExpandedBlock)(o.slice(n.length));if(s){let c=(0,t.parseExpandedMeta)(s.body);N(r,i,{id:n,label:(0,e.normalizeBrTags)(C(n,c)),shape:S(c)}),a=n,o=o.slice(n.length+s.length)}}if(a===null)for(let{regex:t,shape:n}of y){let s=o.match(t);if(s){a=s[1];let t=(0,e.normalizeBrTags)(s[2]),c=typeof n==`function`?n(s[3]??``):n;N(r,i,{id:a,label:t,shape:c}),o=o.slice(s[0].length);break}}if(a===null){let e=o.match(b);e&&(a=e[1],r.nodes.has(a)||N(r,i,{id:a,label:a,shape:`rectangle`}),o=o.slice(e[0].length))}if(a===null)return null;s&&r.classAssignments.set(a,s);let u=o.match(O);return u&&(r.classAssignments.set(a,u[1]),o=o.slice(u[0].length)),{id:a,remaining:o}}function N(e,t,n){e.nodes.has(n.id)||e.nodes.set(n.id,n),P(t,n.id)}function P(e,t){if(e.length>0){let n=e[e.length-1];n.nodeIds.includes(t)||n.nodeIds.push(t)}}function F(e){return e.startsWith(`~`)?`invisible`:e.includes(`.`)?`dotted`:e.startsWith(`=`)?`thick`:`solid`}function I(e,t){return e.includes(`.`)||t.includes(`.`)?`dotted`:e.startsWith(`=`)||t.startsWith(`=`)?`thick`:`solid`}Object.defineProperty(exports,"DEFAULTS",{enumerable:!0,get:function(){return e.DEFAULTS}}),Object.defineProperty(exports,"THEMES",{enumerable:!0,get:function(){return e.THEMES}}),Object.defineProperty(exports,"createLayoutCache",{enumerable:!0,get:function(){return r.createLayoutCache}}),Object.defineProperty(exports,"fromShikiTheme",{enumerable:!0,get:function(){return e.fromShikiTheme}}),exports.parseMermaid=l,Object.defineProperty(exports,"renderMermaid",{enumerable:!0,get:function(){return r.renderMermaid}}),Object.defineProperty(exports,"renderMermaidASCII",{enumerable:!0,get:function(){return n.renderMermaidASCII}}),Object.defineProperty(exports,"renderMermaidAscii",{enumerable:!0,get:function(){return n.renderMermaidAscii}}),Object.defineProperty(exports,"renderMermaidSVG",{enumerable:!0,get:function(){return r.renderMermaidSVG}}),Object.defineProperty(exports,"renderMermaidSVGAsync",{enumerable:!0,get:function(){return r.renderMermaidSVGAsync}}),Object.defineProperty(exports,"renderMermaidSync",{enumerable:!0,get:function(){return r.renderMermaidSync}}),Object.defineProperty(exports,"themeCssVariables",{enumerable:!0,get:function(){return r.themeCssVariables}});
|
|
3
|
-
//# sourceMappingURL=index.cjs.map
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@zombie-mermaid/core"),t=require("@zombie-mermaid/mermaid-parser"),n=require("@zombie-mermaid/ascii-renderer"),r=require("@zombie-mermaid/svg-renderer");Object.defineProperty(exports,"DEFAULTS",{enumerable:!0,get:function(){return e.DEFAULTS}}),Object.defineProperty(exports,"THEMES",{enumerable:!0,get:function(){return e.THEMES}}),Object.defineProperty(exports,"createLayoutCache",{enumerable:!0,get:function(){return r.createLayoutCache}}),Object.defineProperty(exports,"fromShikiTheme",{enumerable:!0,get:function(){return e.fromShikiTheme}}),Object.defineProperty(exports,"parseMermaid",{enumerable:!0,get:function(){return t.parseMermaid}}),Object.defineProperty(exports,"renderMermaid",{enumerable:!0,get:function(){return r.renderMermaid}}),Object.defineProperty(exports,"renderMermaidASCII",{enumerable:!0,get:function(){return n.renderMermaidASCII}}),Object.defineProperty(exports,"renderMermaidAscii",{enumerable:!0,get:function(){return n.renderMermaidAscii}}),Object.defineProperty(exports,"renderMermaidSVG",{enumerable:!0,get:function(){return r.renderMermaidSVG}}),Object.defineProperty(exports,"renderMermaidSVGAsync",{enumerable:!0,get:function(){return r.renderMermaidSVGAsync}}),Object.defineProperty(exports,"renderMermaidSync",{enumerable:!0,get:function(){return r.renderMermaidSync}}),Object.defineProperty(exports,"themeCssVariables",{enumerable:!0,get:function(){return r.themeCssVariables}});
|
package/dist/index.d.cts
CHANGED
|
@@ -11,6 +11,7 @@ import { fromShikiTheme } from '@zombie-mermaid/core';
|
|
|
11
11
|
import { LayoutCache } from '@zombie-mermaid/svg-renderer';
|
|
12
12
|
import { MermaidGraph } from '@zombie-mermaid/core';
|
|
13
13
|
import { NodeInteraction } from '@zombie-mermaid/core';
|
|
14
|
+
import { parseMermaid } from '@zombie-mermaid/mermaid-parser';
|
|
14
15
|
import { PositionedGraph } from '@zombie-mermaid/core';
|
|
15
16
|
import { renderMermaid } from '@zombie-mermaid/svg-renderer';
|
|
16
17
|
import { renderMermaidASCII } from '@zombie-mermaid/ascii-renderer';
|
|
@@ -51,12 +52,7 @@ export { MermaidGraph }
|
|
|
51
52
|
|
|
52
53
|
export { NodeInteraction }
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
* Parse Mermaid text into a logical graph structure.
|
|
56
|
-
* Auto-detects diagram type (flowchart or state diagram).
|
|
57
|
-
* Throws on invalid/unsupported input.
|
|
58
|
-
*/
|
|
59
|
-
export declare function parseMermaid(text: string): MermaidGraph;
|
|
55
|
+
export { parseMermaid }
|
|
60
56
|
|
|
61
57
|
export { PositionedGraph }
|
|
62
58
|
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { fromShikiTheme } from '@zombie-mermaid/core';
|
|
|
11
11
|
import { LayoutCache } from '@zombie-mermaid/svg-renderer';
|
|
12
12
|
import { MermaidGraph } from '@zombie-mermaid/core';
|
|
13
13
|
import { NodeInteraction } from '@zombie-mermaid/core';
|
|
14
|
+
import { parseMermaid } from '@zombie-mermaid/mermaid-parser';
|
|
14
15
|
import { PositionedGraph } from '@zombie-mermaid/core';
|
|
15
16
|
import { renderMermaid } from '@zombie-mermaid/svg-renderer';
|
|
16
17
|
import { renderMermaidASCII } from '@zombie-mermaid/ascii-renderer';
|
|
@@ -51,12 +52,7 @@ export { MermaidGraph }
|
|
|
51
52
|
|
|
52
53
|
export { NodeInteraction }
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
* Parse Mermaid text into a logical graph structure.
|
|
56
|
-
* Auto-detects diagram type (flowchart or state diagram).
|
|
57
|
-
* Throws on invalid/unsupported input.
|
|
58
|
-
*/
|
|
59
|
-
export declare function parseMermaid(text: string): MermaidGraph;
|
|
55
|
+
export { parseMermaid }
|
|
60
56
|
|
|
61
57
|
export { PositionedGraph }
|
|
62
58
|
|
package/dist/index.js
CHANGED
|
@@ -1,435 +1,5 @@
|
|
|
1
|
-
import { DEFAULTS as e, THEMES as t,
|
|
2
|
-
import {
|
|
3
|
-
import { renderMermaidASCII as
|
|
4
|
-
import { createLayoutCache as
|
|
5
|
-
|
|
6
|
-
function C(e) {
|
|
7
|
-
let t = e.trim();
|
|
8
|
-
return t.length >= 2 && (t[0] === "\"" && t[t.length - 1] === "\"" || t[0] === "'" && t[t.length - 1] === "'") ? t.slice(1, -1) : t;
|
|
9
|
-
}
|
|
10
|
-
var w = "\"graph <dir>\"/\"flowchart <dir>\" (dir: TD, TB, LR, BT, RL), \"stateDiagram-v2\", \"sequenceDiagram\", \"classDiagram\", \"erDiagram\", \"xychart-beta\", \"C4Context\"/\"C4Container\"/\"C4Component\"/\"C4Dynamic\"/\"C4Deployment\", \"architecture-beta\"";
|
|
11
|
-
function T(e) {
|
|
12
|
-
let t = e.trim().toLowerCase();
|
|
13
|
-
if (/^sequence/.test(t)) return "sequenceDiagram";
|
|
14
|
-
if (/^class/.test(t)) return "classDiagram";
|
|
15
|
-
if (/^er/.test(t)) return "erDiagram";
|
|
16
|
-
if (/^xychart/.test(t)) return "xychart-beta";
|
|
17
|
-
if (/^state/.test(t)) return "stateDiagram-v2";
|
|
18
|
-
}
|
|
19
|
-
var E = /^(?:[\w-]+@)?<?(?:-{2,}|={2,}|-\.+-?|~{3,})/;
|
|
20
|
-
function D(e) {
|
|
21
|
-
let t = [];
|
|
22
|
-
for (let n of e) n.forEach((e, n) => {
|
|
23
|
-
if (n === 0 && t.length > 0 && E.test(e.text)) {
|
|
24
|
-
let n = t[t.length - 1];
|
|
25
|
-
t[t.length - 1] = {
|
|
26
|
-
text: `${n.text} ${e.text}`,
|
|
27
|
-
line: n.line
|
|
28
|
-
};
|
|
29
|
-
} else t.push(e);
|
|
30
|
-
});
|
|
31
|
-
return t;
|
|
32
|
-
}
|
|
33
|
-
function O(e) {
|
|
34
|
-
let t = r(e.split("\n").map((e) => e.trim())), n = D(s(e));
|
|
35
|
-
if (n.length === 0) throw Error("Empty mermaid diagram");
|
|
36
|
-
let i = n[0], a = /^stateDiagram(-v2)?\s*$/i.test(i.text) ? A(n) : k(n);
|
|
37
|
-
return a.initConfig = t, a;
|
|
38
|
-
}
|
|
39
|
-
function k(e) {
|
|
40
|
-
let t = e[0];
|
|
41
|
-
if (t === void 0)
|
|
42
|
-
/* v8 ignore next */
|
|
43
|
-
throw Error("parseFlowchart called with no lines");
|
|
44
|
-
let n = t.text, r = n.match(/^(?:graph|flowchart)\s+(TD|TB|LR|BT|RL)\s*$/i);
|
|
45
|
-
if (!r) {
|
|
46
|
-
let e = n.match(/^(?:graph|flowchart)\b\s*(.*)$/i);
|
|
47
|
-
if (e) {
|
|
48
|
-
let r = e[1].trim();
|
|
49
|
-
throw Error(r.length > 0 ? `Line ${t.line}: Invalid direction "${r}" in header "${n}". Expected one of: TD, TB, LR, BT, RL.` : `Line ${t.line}: Missing direction in header "${n}". Expected e.g. "graph TD" or "flowchart LR" — one of: TD, TB, LR, BT, RL.`);
|
|
50
|
-
}
|
|
51
|
-
let r = T(n), i = r && r.toLowerCase() !== n.trim().toLowerCase() ? ` Did you mean "${r}"?` : "";
|
|
52
|
-
throw Error(`Line ${t.line}: Invalid mermaid header: "${n}".${i} Supported headers: ${w}.`);
|
|
53
|
-
}
|
|
54
|
-
let i = {
|
|
55
|
-
direction: c(r[1]),
|
|
56
|
-
nodes: /* @__PURE__ */ new Map(),
|
|
57
|
-
edges: [],
|
|
58
|
-
subgraphs: [],
|
|
59
|
-
classDefs: /* @__PURE__ */ new Map(),
|
|
60
|
-
classAssignments: /* @__PURE__ */ new Map(),
|
|
61
|
-
nodeStyles: /* @__PURE__ */ new Map(),
|
|
62
|
-
linkStyles: /* @__PURE__ */ new Map(),
|
|
63
|
-
interactions: /* @__PURE__ */ new Map()
|
|
64
|
-
}, s = [];
|
|
65
|
-
for (let t = 1; t < e.length; t++) {
|
|
66
|
-
let n = e[t].text;
|
|
67
|
-
if (u(n, i) || l(n, i) || d(n, i)) continue;
|
|
68
|
-
if (/^click\s+/i.test(n)) {
|
|
69
|
-
U(n, i);
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
if (G(n, i)) continue;
|
|
73
|
-
let r = n.match(/^linkStyle\s+(default|[\d,\s]+)\s+(.+)$/);
|
|
74
|
-
if (r) {
|
|
75
|
-
let e = r[1].trim(), t = o(r[2]);
|
|
76
|
-
if (e === "default") i.linkStyles.set("default", {
|
|
77
|
-
...i.linkStyles.get("default"),
|
|
78
|
-
...t
|
|
79
|
-
});
|
|
80
|
-
else {
|
|
81
|
-
let n = e.split(",").map((e) => parseInt(e.trim(), 10));
|
|
82
|
-
for (let e of n) isNaN(e) || i.linkStyles.set(e, {
|
|
83
|
-
...i.linkStyles.get(e),
|
|
84
|
-
...t
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
let f = n.match(/^direction\s+(TD|TB|LR|BT|RL)\s*$/i);
|
|
90
|
-
if (f && s.length > 0) {
|
|
91
|
-
s[s.length - 1].direction = c(f[1]);
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
let p = n.match(/^subgraph\s+(.+)$/);
|
|
95
|
-
if (p) {
|
|
96
|
-
let e = p[1].trim(), t = e.match(/^([^\s[]+)\s*\[(.+)\]$/), n, r;
|
|
97
|
-
t ? (n = t[1], r = a(C(t[2]))) : (r = a(C(e)), n = r.replace(/\s+/g, "_").replace(/[^\p{L}\p{N}_-]/gu, ""));
|
|
98
|
-
let i = {
|
|
99
|
-
id: n,
|
|
100
|
-
label: r,
|
|
101
|
-
nodeIds: [],
|
|
102
|
-
children: []
|
|
103
|
-
};
|
|
104
|
-
s.push(i);
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
if (n === "end") {
|
|
108
|
-
let e = s.pop();
|
|
109
|
-
e && (s.length > 0 ? s[s.length - 1].children.push(e) : i.subgraphs.push(e));
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
Y(n, i, s);
|
|
113
|
-
}
|
|
114
|
-
return i;
|
|
115
|
-
}
|
|
116
|
-
function A(e) {
|
|
117
|
-
let t = {
|
|
118
|
-
direction: "TD",
|
|
119
|
-
nodes: /* @__PURE__ */ new Map(),
|
|
120
|
-
edges: [],
|
|
121
|
-
subgraphs: [],
|
|
122
|
-
classDefs: /* @__PURE__ */ new Map(),
|
|
123
|
-
classAssignments: /* @__PURE__ */ new Map(),
|
|
124
|
-
nodeStyles: /* @__PURE__ */ new Map(),
|
|
125
|
-
linkStyles: /* @__PURE__ */ new Map(),
|
|
126
|
-
interactions: /* @__PURE__ */ new Map()
|
|
127
|
-
}, n = [], r = /* @__PURE__ */ new Set(), i = 0, s = 0;
|
|
128
|
-
for (let f = 1; f < e.length; f++) {
|
|
129
|
-
let p = e[f].text;
|
|
130
|
-
if (u(p, t) || l(p, t) || d(p, t)) continue;
|
|
131
|
-
let m = p.match(/^direction\s+(TD|TB|LR|BT|RL)\s*$/i);
|
|
132
|
-
if (m) {
|
|
133
|
-
n.length > 0 ? n[n.length - 1].direction = c(m[1]) : t.direction = c(m[1]);
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
let h = p.match(/^linkStyle\s+(default|[\d,\s]+)\s+(.+)$/);
|
|
137
|
-
if (h) {
|
|
138
|
-
let e = h[1].trim(), n = o(h[2]);
|
|
139
|
-
if (e === "default") t.linkStyles.set("default", {
|
|
140
|
-
...t.linkStyles.get("default"),
|
|
141
|
-
...n
|
|
142
|
-
});
|
|
143
|
-
else {
|
|
144
|
-
let r = e.split(",").map((e) => parseInt(e.trim(), 10));
|
|
145
|
-
for (let e of r) isNaN(e) || t.linkStyles.set(e, {
|
|
146
|
-
...t.linkStyles.get(e),
|
|
147
|
-
...n
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
if (G(p, t)) continue;
|
|
153
|
-
let g = p.match(/^state\s+(?:"([^"]+)"\s+as\s+)?([\w\p{L}]+)\s*\{$/u);
|
|
154
|
-
if (g) {
|
|
155
|
-
let e = g[1] ?? g[2], i = g[2], a = {
|
|
156
|
-
id: i,
|
|
157
|
-
label: e,
|
|
158
|
-
nodeIds: [],
|
|
159
|
-
children: []
|
|
160
|
-
};
|
|
161
|
-
n.push(a), r.add(i), t.nodes.delete(i);
|
|
162
|
-
continue;
|
|
163
|
-
}
|
|
164
|
-
if (p === "}") {
|
|
165
|
-
let e = n.pop();
|
|
166
|
-
e && (n.length > 0 ? n[n.length - 1].children.push(e) : t.subgraphs.push(e));
|
|
167
|
-
continue;
|
|
168
|
-
}
|
|
169
|
-
let _ = p.match(/^state\s+"([^"]+)"\s+as\s+([\w\p{L}]+)\s*$/u);
|
|
170
|
-
if (_) {
|
|
171
|
-
let e = a(_[1]), r = _[2];
|
|
172
|
-
j(t, n, r, e);
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
let v = p.match(/^(\[\*\]|[\w\p{L}-]+)(?::::([\w][\w-]*))?\s*(?:([\w-]+)@)?-->\s*(\[\*\]|[\w\p{L}-]+)(?::::([\w][\w-]*))?(?:\s*:\s*(.+))?$/u);
|
|
176
|
-
if (v) {
|
|
177
|
-
let e = v[1], o = v[2], c = v[3], l = v[4], u = v[5], d = v[6]?.trim(), f = d ? a(d) : void 0;
|
|
178
|
-
e === "[*]" ? (i++, e = `_start${i > 1 ? i : ""}`, M(t, n, {
|
|
179
|
-
id: e,
|
|
180
|
-
label: "",
|
|
181
|
-
shape: "state-start"
|
|
182
|
-
})) : r.has(e) || N(t, n, e), l === "[*]" ? (s++, l = `_end${s > 1 ? s : ""}`, M(t, n, {
|
|
183
|
-
id: l,
|
|
184
|
-
label: "",
|
|
185
|
-
shape: "state-end"
|
|
186
|
-
})) : r.has(l) || N(t, n, l), o !== void 0 && t.classAssignments.set(e, o), u !== void 0 && t.classAssignments.set(l, u), t.edges.push({
|
|
187
|
-
source: e,
|
|
188
|
-
target: l,
|
|
189
|
-
label: f,
|
|
190
|
-
style: "solid",
|
|
191
|
-
hasArrowStart: !1,
|
|
192
|
-
hasArrowEnd: !0,
|
|
193
|
-
...c === void 0 ? {} : { id: c }
|
|
194
|
-
});
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
let y = p.match(/^([\w\p{L}-]+):::([\w][\w-]*)\s*$/u);
|
|
198
|
-
if (y) {
|
|
199
|
-
let e = y[1];
|
|
200
|
-
r.has(e) || N(t, n, e), t.classAssignments.set(e, y[2]);
|
|
201
|
-
continue;
|
|
202
|
-
}
|
|
203
|
-
let b = p.match(/^([\w\p{L}-]+)\s*:\s*(.+)$/u);
|
|
204
|
-
if (b) {
|
|
205
|
-
let e = b[1];
|
|
206
|
-
j(t, n, e, a(b[2].trim()));
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
for (let e of t.classAssignments.keys()) !t.nodes.has(e) && !r.has(e) && N(t, [], e);
|
|
211
|
-
return t;
|
|
212
|
-
}
|
|
213
|
-
function j(e, t, n, r) {
|
|
214
|
-
let i = e.nodes.get(n);
|
|
215
|
-
i && (i.label = r), M(e, t, {
|
|
216
|
-
id: n,
|
|
217
|
-
label: r,
|
|
218
|
-
shape: "rounded"
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
function M(e, t, n) {
|
|
222
|
-
if (e.nodes.has(n.id) || e.nodes.set(n.id, n), t.length > 0) {
|
|
223
|
-
let e = t[t.length - 1];
|
|
224
|
-
e.nodeIds.includes(n.id) || e.nodeIds.push(n.id);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
function N(e, t, n) {
|
|
228
|
-
if (!e.nodes.has(n)) M(e, t, {
|
|
229
|
-
id: n,
|
|
230
|
-
label: n,
|
|
231
|
-
shape: "rounded"
|
|
232
|
-
});
|
|
233
|
-
else if (t.length > 0) {
|
|
234
|
-
let e = t[t.length - 1];
|
|
235
|
-
e.nodeIds.includes(n) || e.nodeIds.push(n);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
var P = /^(<|o|x)?(-{2,}|={2,}|-\.+-|~{3,})(>|o|x)?(?:\|([^|]*)\|)?/, F = /* @__PURE__ */ new Set(["--", "=="]);
|
|
239
|
-
function I(e) {
|
|
240
|
-
if (e === "o") return "circle";
|
|
241
|
-
if (e === "x") return "cross";
|
|
242
|
-
}
|
|
243
|
-
var L = /^(<|o|x)?(--|-\.|==)\s+(.+?)\s+(-{2,}[>ox]|={2,}[>ox]|\.+-[>ox]|-{3,}|={3,}|-\.+-)/, R = [
|
|
244
|
-
{
|
|
245
|
-
regex: /^([\w\p{L}-]+)\(\(\(((?:"[^"]*"|(?!\)\)\)).)+)\)\)\)/u,
|
|
246
|
-
shape: "doublecircle"
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
regex: /^([\w\p{L}-]+)\(\[((?:"[^"]*"|(?!\]\)).)+)\]\)/u,
|
|
250
|
-
shape: "stadium"
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
regex: /^([\w\p{L}-]+)\(\(((?:"[^"]*"|(?!\)\)).)+)\)\)/u,
|
|
254
|
-
shape: "circle"
|
|
255
|
-
},
|
|
256
|
-
{
|
|
257
|
-
regex: /^([\w\p{L}-]+)\[\[((?:"[^"]*"|(?!\]\]).)+)\]\]/u,
|
|
258
|
-
shape: "subroutine"
|
|
259
|
-
},
|
|
260
|
-
{
|
|
261
|
-
regex: /^([\w\p{L}-]+)\[\(((?:"[^"]*"|(?!\)\]).)+)\)\]/u,
|
|
262
|
-
shape: "cylinder"
|
|
263
|
-
},
|
|
264
|
-
{
|
|
265
|
-
regex: /^([\w\p{L}-]+)\[\/((?:"[^"]*"|(?![\\/]\]).)+)([\\/])\]/u,
|
|
266
|
-
shape: (e) => e === "\\" ? "trapezoid" : "parallelogram"
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
regex: /^([\w\p{L}-]+)\[\\((?:"[^"]*"|(?![\\/]\]).)+)([\\/])\]/u,
|
|
270
|
-
shape: (e) => e === "/" ? "trapezoid-alt" : "parallelogram-alt"
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
regex: /^([\w\p{L}-]+)>((?:"[^"]*"|(?!\]).)+)\]/u,
|
|
274
|
-
shape: "asymmetric"
|
|
275
|
-
},
|
|
276
|
-
{
|
|
277
|
-
regex: /^([\w\p{L}-]+)\{\{((?:"[^"]*"|(?!\}\}).)+)\}\}/u,
|
|
278
|
-
shape: "hexagon"
|
|
279
|
-
},
|
|
280
|
-
{
|
|
281
|
-
regex: /^([\w\p{L}-]+)\[((?:"[^"]*"|(?!\]).)+)\]/u,
|
|
282
|
-
shape: "rectangle"
|
|
283
|
-
},
|
|
284
|
-
{
|
|
285
|
-
regex: /^([\w\p{L}-]+)\(((?:"[^"]*"|(?!\)).)+)\)/u,
|
|
286
|
-
shape: "rounded"
|
|
287
|
-
},
|
|
288
|
-
{
|
|
289
|
-
regex: /^([\w\p{L}-]+)\{((?:"[^"]*"|(?!\}).)+)\}/u,
|
|
290
|
-
shape: "diamond"
|
|
291
|
-
}
|
|
292
|
-
], z = /^([\w\p{L}]+(?:-[\w\p{L}]+)*)/u, B = /^([\w\p{L}-]+)(?=@\{)/u;
|
|
293
|
-
function V(e) {
|
|
294
|
-
if (e.shape) return m(e.shape) ?? "rectangle";
|
|
295
|
-
if (e.icon !== void 0 || e.img !== void 0) switch (e.form?.toLowerCase()) {
|
|
296
|
-
case "circle": return "circle";
|
|
297
|
-
case "rounded": return "rounded";
|
|
298
|
-
default: return "rectangle";
|
|
299
|
-
}
|
|
300
|
-
return "rectangle";
|
|
301
|
-
}
|
|
302
|
-
function H(e, t) {
|
|
303
|
-
return t.label !== void 0 && t.label.length > 0 ? t.label : t.icon ? t.icon : t.img ? t.img : e;
|
|
304
|
-
}
|
|
305
|
-
function U(e, t) {
|
|
306
|
-
n(e, t.interactions);
|
|
307
|
-
}
|
|
308
|
-
var W = /^([\w-]+)(?=@\{)/;
|
|
309
|
-
function G(e, t) {
|
|
310
|
-
let n = e.match(W);
|
|
311
|
-
if (!n || !t.edges.some((e) => e.id === n[1])) return !1;
|
|
312
|
-
let r = f(e.slice(n[1].length));
|
|
313
|
-
return r ? (K(t, n[1], p(r.body)), !0) : !1;
|
|
314
|
-
}
|
|
315
|
-
function K(e, t, n) {
|
|
316
|
-
for (let r of e.edges) r.id === t && (n.animate !== void 0 && (r.animate = n.animate.toLowerCase() !== "false"), n.animation !== void 0 && (r.animate = !0));
|
|
317
|
-
}
|
|
318
|
-
var q = /^:::([\w][\w-]*)/, J = /^([\w\p{L}-]+):::([\w][\w-]*)/u;
|
|
319
|
-
function Y(e, t, n) {
|
|
320
|
-
let r = e.trim(), i = X(r, t, n);
|
|
321
|
-
if (!i || i.ids.length === 0) return;
|
|
322
|
-
r = i.remaining.trim();
|
|
323
|
-
let o = i.ids;
|
|
324
|
-
for (; r.length > 0;) {
|
|
325
|
-
let e, i, s, c, l, u, d, f = r.match(/^([\w-]+)@(?=[-=<~ox])/);
|
|
326
|
-
f && (d = f[1], r = r.slice(f[0].length));
|
|
327
|
-
let p = r.match(P), m = p?.[2], h = p?.[1], g = p?.[3];
|
|
328
|
-
if (p && m !== void 0 && !(h === void 0 && g === void 0 && F.has(m))) {
|
|
329
|
-
e = h !== void 0, l = I(h);
|
|
330
|
-
let t = p[4]?.trim();
|
|
331
|
-
c = t ? a(t) : void 0, r = r.slice(p[0].length).trim(), i = ee(m), s = g !== void 0, u = I(g);
|
|
332
|
-
} else {
|
|
333
|
-
let t = r.match(L);
|
|
334
|
-
if (!t) break;
|
|
335
|
-
e = !!t[1], l = I(t[1]);
|
|
336
|
-
let n = t[3].trim();
|
|
337
|
-
c = n ? a(n) : void 0;
|
|
338
|
-
let o = t[2], d = t[4];
|
|
339
|
-
r = r.slice(t[0].length).trim(), i = te(o, d), u = I(d.slice(-1)), s = d.endsWith(">") || u !== void 0;
|
|
340
|
-
}
|
|
341
|
-
let _ = X(r, t, n);
|
|
342
|
-
if (!_ || _.ids.length === 0) break;
|
|
343
|
-
r = _.remaining.trim();
|
|
344
|
-
for (let n of o) for (let r of _.ids) t.edges.push({
|
|
345
|
-
source: n,
|
|
346
|
-
target: r,
|
|
347
|
-
label: c,
|
|
348
|
-
style: i,
|
|
349
|
-
hasArrowStart: e,
|
|
350
|
-
hasArrowEnd: s,
|
|
351
|
-
...l === void 0 ? {} : { startMarker: l },
|
|
352
|
-
...u === void 0 ? {} : { endMarker: u },
|
|
353
|
-
...d === void 0 ? {} : { id: d }
|
|
354
|
-
});
|
|
355
|
-
o = _.ids;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
function X(e, t, n) {
|
|
359
|
-
let r = Z(e, t, n);
|
|
360
|
-
if (!r) return null;
|
|
361
|
-
let i = [r.id], a = r.remaining.trim();
|
|
362
|
-
for (; a.startsWith("&");) {
|
|
363
|
-
a = a.slice(1).trim();
|
|
364
|
-
let e = Z(a, t, n);
|
|
365
|
-
if (!e) break;
|
|
366
|
-
i.push(e.id), a = e.remaining.trim();
|
|
367
|
-
}
|
|
368
|
-
return {
|
|
369
|
-
ids: i,
|
|
370
|
-
remaining: a
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
function Z(e, t, n) {
|
|
374
|
-
let r = null, i = e, o, s = i.match(J);
|
|
375
|
-
s && (o = s[2], i = s[1] + i.slice(s[0].length));
|
|
376
|
-
let c = i.match(B);
|
|
377
|
-
if (c) {
|
|
378
|
-
let e = c[1], o = f(i.slice(e.length));
|
|
379
|
-
if (o) {
|
|
380
|
-
let s = p(o.body);
|
|
381
|
-
Q(t, n, {
|
|
382
|
-
id: e,
|
|
383
|
-
label: a(H(e, s)),
|
|
384
|
-
shape: V(s)
|
|
385
|
-
}), r = e, i = i.slice(e.length + o.length);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
if (r === null) for (let { regex: e, shape: o } of R) {
|
|
389
|
-
let s = i.match(e);
|
|
390
|
-
if (s) {
|
|
391
|
-
r = s[1];
|
|
392
|
-
let e = a(s[2]), c = typeof o == "function" ? o(s[3] ?? "") : o;
|
|
393
|
-
Q(t, n, {
|
|
394
|
-
id: r,
|
|
395
|
-
label: e,
|
|
396
|
-
shape: c
|
|
397
|
-
}), i = i.slice(s[0].length);
|
|
398
|
-
break;
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
if (r === null) {
|
|
402
|
-
let e = i.match(z);
|
|
403
|
-
e && (r = e[1], t.nodes.has(r) || Q(t, n, {
|
|
404
|
-
id: r,
|
|
405
|
-
label: r,
|
|
406
|
-
shape: "rectangle"
|
|
407
|
-
}), i = i.slice(e[0].length));
|
|
408
|
-
}
|
|
409
|
-
if (r === null) return null;
|
|
410
|
-
o && t.classAssignments.set(r, o);
|
|
411
|
-
let l = i.match(q);
|
|
412
|
-
return l && (t.classAssignments.set(r, l[1]), i = i.slice(l[0].length)), {
|
|
413
|
-
id: r,
|
|
414
|
-
remaining: i
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
function Q(e, t, n) {
|
|
418
|
-
e.nodes.has(n.id) || e.nodes.set(n.id, n), $(t, n.id);
|
|
419
|
-
}
|
|
420
|
-
function $(e, t) {
|
|
421
|
-
if (e.length > 0) {
|
|
422
|
-
let n = e[e.length - 1];
|
|
423
|
-
n.nodeIds.includes(t) || n.nodeIds.push(t);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
function ee(e) {
|
|
427
|
-
return e.startsWith("~") ? "invisible" : e.includes(".") ? "dotted" : e.startsWith("=") ? "thick" : "solid";
|
|
428
|
-
}
|
|
429
|
-
function te(e, t) {
|
|
430
|
-
return e.includes(".") || t.includes(".") ? "dotted" : e.startsWith("=") || t.startsWith("=") ? "thick" : "solid";
|
|
431
|
-
}
|
|
432
|
-
//#endregion
|
|
433
|
-
export { e as DEFAULTS, t as THEMES, _ as createLayoutCache, i as fromShikiTheme, O as parseMermaid, v as renderMermaid, h as renderMermaidASCII, g as renderMermaidAscii, y as renderMermaidSVG, b as renderMermaidSVGAsync, x as renderMermaidSync, S as themeCssVariables };
|
|
434
|
-
|
|
435
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import { DEFAULTS as e, THEMES as t, fromShikiTheme as n } from "@zombie-mermaid/core";
|
|
2
|
+
import { parseMermaid as r } from "@zombie-mermaid/mermaid-parser";
|
|
3
|
+
import { renderMermaidASCII as i, renderMermaidAscii as a } from "@zombie-mermaid/ascii-renderer";
|
|
4
|
+
import { createLayoutCache as o, renderMermaid as s, renderMermaidSVG as c, renderMermaidSVGAsync as l, renderMermaidSync as u, themeCssVariables as d } from "@zombie-mermaid/svg-renderer";
|
|
5
|
+
export { e as DEFAULTS, t as THEMES, o as createLayoutCache, n as fromShikiTheme, r as parseMermaid, s as renderMermaid, i as renderMermaidASCII, a as renderMermaidAscii, c as renderMermaidSVG, l as renderMermaidSVGAsync, u as renderMermaidSync, d as themeCssVariables };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zombie-mermaid",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Render Mermaid diagrams as beautiful SVGs or ASCII art. Ultra-fast, fully themeable, zero DOM dependencies. Maintained fork of beautiful-mermaid.",
|
|
6
6
|
"type": "module",
|
|
@@ -84,17 +84,17 @@
|
|
|
84
84
|
"README.md"
|
|
85
85
|
],
|
|
86
86
|
"engines": {
|
|
87
|
-
"node": ">=
|
|
87
|
+
"node": ">=24"
|
|
88
88
|
},
|
|
89
89
|
"dependencies": {
|
|
90
90
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
91
91
|
"elkjs": "^0.11.0",
|
|
92
92
|
"entities": "^7.0.1",
|
|
93
|
-
"@zombie-mermaid/ascii-renderer": "
|
|
94
|
-
"@zombie-mermaid/
|
|
95
|
-
"@zombie-mermaid/
|
|
96
|
-
"@zombie-mermaid/
|
|
97
|
-
"@zombie-mermaid/svg-renderer": "
|
|
93
|
+
"@zombie-mermaid/ascii-renderer": "4.1.0",
|
|
94
|
+
"@zombie-mermaid/core": "4.1.0",
|
|
95
|
+
"@zombie-mermaid/mcp": "4.1.0",
|
|
96
|
+
"@zombie-mermaid/mermaid-parser": "4.1.0",
|
|
97
|
+
"@zombie-mermaid/svg-renderer": "4.1.0"
|
|
98
98
|
},
|
|
99
99
|
"devDependencies": {
|
|
100
100
|
"@changesets/changelog-github": "^1.0.0",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"@testing-library/react": "^16.3.3",
|
|
106
106
|
"@testing-library/user-event": "^14.6.7",
|
|
107
107
|
"@types/jsdom": "^30.0.0",
|
|
108
|
-
"@types/node": "^
|
|
108
|
+
"@types/node": "^24.13.6",
|
|
109
109
|
"@types/react": "^19.2.18",
|
|
110
110
|
"@types/react-dom": "^19.2.7",
|
|
111
111
|
"@vitest/coverage-v8": "^4.1.11",
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"shiki": "^3.19.0",
|
|
125
125
|
"subset-font": "^2.7.0",
|
|
126
126
|
"tsx": "^4.23.12",
|
|
127
|
-
"typescript": "^
|
|
127
|
+
"typescript": "^6.0.3",
|
|
128
128
|
"typescript-eslint": "^8.68.0",
|
|
129
129
|
"unplugin-dts": "^1.0.3",
|
|
130
130
|
"vite": "^8.2.2",
|
|
@@ -159,9 +159,10 @@
|
|
|
159
159
|
"bench:mcp": "tsx scripts/bench-mcp.ts",
|
|
160
160
|
"check:bundle-size": "tsx scripts/check-bundle-size.ts",
|
|
161
161
|
"generate:hero": "tsx scripts/generate-hero.ts",
|
|
162
|
-
"build:mono-font": "tsx scripts/build-mono-font-subset.ts && prettier --write demo/components/generated/mono-font-subset.ts demo/styles.css packages/
|
|
162
|
+
"build:mono-font": "tsx scripts/build-mono-font-subset.ts && prettier --write demo/components/generated/mono-font-subset.ts demo/styles.css packages/svg-renderer/src/generated/mono-font-subset.ts",
|
|
163
163
|
"generate:primitives-classes": "tsx scripts/generate-primitives-classes.ts && prettier --write demo/components/generated/primitives-classes.ts",
|
|
164
164
|
"generate:logo-lockup": "tsx scripts/generate-logo-lockup.ts",
|
|
165
|
+
"docs:scripts": "tsx scripts/generate-development-scripts-doc.ts && prettier --write docs/development-scripts.md",
|
|
165
166
|
"badge:bundle-size": "tsx scripts/generate-bundle-badge.ts",
|
|
166
167
|
"visual-diff": "tsx scripts/visual-diff.ts",
|
|
167
168
|
"form-diff": "tsx scripts/form-diff.ts",
|
|
@@ -179,6 +180,7 @@
|
|
|
179
180
|
"dashboard": "scripts/tsx-css.sh packages/site/dashboard.ts",
|
|
180
181
|
"dashboard:data": "tsx scripts/generate-dashboard-data.ts",
|
|
181
182
|
"upstream:pr-candidates": "tsx scripts/list-upstream-pr-rescue-candidates.ts",
|
|
182
|
-
"audit:responsive": "tsx scripts/audit-responsive.ts"
|
|
183
|
+
"audit:responsive": "tsx scripts/audit-responsive.ts",
|
|
184
|
+
"layout:oracle": "tsx scripts/layout-oracle.ts"
|
|
183
185
|
}
|
|
184
186
|
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* with that input.
|
|
16
16
|
*/
|
|
17
17
|
import { describe, it, expect } from 'vitest'
|
|
18
|
-
import { parseMermaid } from '
|
|
18
|
+
import { parseMermaid } from '@zombie-mermaid/mermaid-parser'
|
|
19
19
|
import { convertToAsciiGraph } from '../../packages/ascii-renderer/src/converter.ts'
|
|
20
20
|
import { createMapping } from '../../packages/ascii-renderer/src/grid.ts'
|
|
21
21
|
import type {
|
|
@@ -97,7 +97,9 @@ describe('draw-bundles: rendered fan-in/fan-out diagrams', () => {
|
|
|
97
97
|
|
|
98
98
|
it('draws a fan-out bundle with one arrowhead per target (unicode)', () => {
|
|
99
99
|
const out = renderMermaidASCII(FAN_OUT, { useAscii: false })
|
|
100
|
-
|
|
100
|
+
// The source sits centred over its two targets, so the shared trunk
|
|
101
|
+
// leaves its bottom border and splits at a ┴ directly beneath it.
|
|
102
|
+
expect(out).toMatch(/┌─+┴─+┐/)
|
|
101
103
|
expect(out.match(/▼/g)).toHaveLength(2)
|
|
102
104
|
})
|
|
103
105
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* code with the same direction-confusion risk the TD side had.
|
|
16
16
|
*/
|
|
17
17
|
import { describe, it, expect } from 'vitest'
|
|
18
|
-
import { parseMermaid } from '
|
|
18
|
+
import { parseMermaid } from '@zombie-mermaid/mermaid-parser'
|
|
19
19
|
import { convertToAsciiGraph } from '../../packages/ascii-renderer/src/converter.ts'
|
|
20
20
|
import { createMapping } from '../../packages/ascii-renderer/src/grid.ts'
|
|
21
21
|
import {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* do with subgraphs — this repro has none).
|
|
18
18
|
*/
|
|
19
19
|
import { describe, it, expect } from 'vitest'
|
|
20
|
-
import { parseMermaid } from '
|
|
20
|
+
import { parseMermaid } from '@zombie-mermaid/mermaid-parser'
|
|
21
21
|
import { convertToAsciiGraph } from '../../packages/ascii-renderer/src/converter.ts'
|
|
22
22
|
import { createMapping } from '../../packages/ascii-renderer/src/grid.ts'
|
|
23
23
|
import {
|