@brrock/excalidraw-mermaid 1.1.4 → 1.2.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 +75 -13
- package/dist/index.d.ts +125 -30
- package/dist/index.js +2 -2
- package/package.json +3 -5
package/README.md
CHANGED
|
@@ -20,8 +20,13 @@ npm install mermaid
|
|
|
20
20
|
|
|
21
21
|
## Usage
|
|
22
22
|
|
|
23
|
+
### Simple Example
|
|
24
|
+
|
|
23
25
|
```ts
|
|
24
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
parseMermaidToExcalidraw,
|
|
28
|
+
serializeToExcalidraw,
|
|
29
|
+
} from "@brrock/excalidraw-mermaid";
|
|
25
30
|
|
|
26
31
|
const diagramDefinition = `
|
|
27
32
|
graph TD
|
|
@@ -29,21 +34,82 @@ const diagramDefinition = `
|
|
|
29
34
|
`;
|
|
30
35
|
|
|
31
36
|
try {
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
// 1. Convert Mermaid to Excalidraw results (elements and binary files)
|
|
38
|
+
const result = await parseMermaidToExcalidraw(diagramDefinition);
|
|
39
|
+
|
|
40
|
+
// 2. (Optional) Serialize to the full .excalidraw file format
|
|
41
|
+
const fullScene = serializeToExcalidraw(result);
|
|
42
|
+
|
|
43
|
+
console.log(fullScene);
|
|
34
44
|
} catch (e) {
|
|
35
|
-
//
|
|
45
|
+
// Handle parse/validation errors
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## API
|
|
50
|
+
|
|
51
|
+
### `parseMermaidToExcalidraw(definition, config?)`
|
|
52
|
+
|
|
53
|
+
Converts a Mermaid diagram definition to Excalidraw results.
|
|
54
|
+
|
|
55
|
+
**Parameters:**
|
|
56
|
+
|
|
57
|
+
- `definition` (string): The Mermaid diagram definition.
|
|
58
|
+
- `config` (MermaidConfig, optional): Configuration for the Mermaid parser.
|
|
59
|
+
|
|
60
|
+
**Returns:**
|
|
61
|
+
|
|
62
|
+
- `Promise<MermaidToExcalidrawResult>`: An object containing `elements` and `files`.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
interface MermaidToExcalidrawResult {
|
|
66
|
+
elements: ExcalidrawElementSkeleton[];
|
|
67
|
+
files?: BinaryFiles;
|
|
36
68
|
}
|
|
37
69
|
```
|
|
38
70
|
|
|
39
|
-
###
|
|
71
|
+
### `serializeToExcalidraw(result)`
|
|
72
|
+
|
|
73
|
+
Wraps the conversion result into a full Excalidraw file structure. This function automatically expands intermediate skeletons into final Excalidraw elements (e.g., separating text labels from shapes and linking them via `containerId`), making the result ready to be saved as an `.excalidraw` file or imported directly.
|
|
74
|
+
|
|
75
|
+
**Parameters:**
|
|
40
76
|
|
|
41
|
-
|
|
77
|
+
- `result` (MermaidToExcalidrawResult): The output from `parseMermaidToExcalidraw`.
|
|
42
78
|
|
|
43
|
-
|
|
79
|
+
**Returns:**
|
|
44
80
|
|
|
45
|
-
- `
|
|
46
|
-
|
|
81
|
+
- `ExcalidrawScene`: A complete Excalidraw scene object.
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
interface ExcalidrawScene {
|
|
85
|
+
type: "excalidraw";
|
|
86
|
+
version: 2;
|
|
87
|
+
source: string;
|
|
88
|
+
elements: ExcalidrawElement[]; // Final expanded elements
|
|
89
|
+
appState: {
|
|
90
|
+
gridSize: number;
|
|
91
|
+
viewBackgroundColor: string;
|
|
92
|
+
// ... other app state defaults
|
|
93
|
+
};
|
|
94
|
+
files: BinaryFiles;
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### `validateMermaid(mermaidStr)`
|
|
99
|
+
|
|
100
|
+
Helper to validate Mermaid syntax before attempting conversion.
|
|
101
|
+
|
|
102
|
+
**Parameters:**
|
|
103
|
+
|
|
104
|
+
- `mermaidStr` (string): The Mermaid diagram definition.
|
|
105
|
+
|
|
106
|
+
**Returns:**
|
|
107
|
+
|
|
108
|
+
- `Promise<boolean>`: True if valid, throws or returns false otherwise (depending on mermaid version).
|
|
109
|
+
|
|
110
|
+
## Configuration
|
|
111
|
+
|
|
112
|
+
### `MermaidConfig`
|
|
47
113
|
|
|
48
114
|
```ts
|
|
49
115
|
interface MermaidConfig {
|
|
@@ -59,10 +125,6 @@ interface MermaidConfig {
|
|
|
59
125
|
}
|
|
60
126
|
```
|
|
61
127
|
|
|
62
|
-
#### `validateMermaid(mermaidStr)`
|
|
63
|
-
|
|
64
|
-
Validates a Mermaid diagram string.
|
|
65
|
-
|
|
66
128
|
### Supported Diagram Types
|
|
67
129
|
|
|
68
130
|
- Flowchart
|
package/dist/index.d.ts
CHANGED
|
@@ -1,25 +1,117 @@
|
|
|
1
1
|
//#region src/types/excalidraw.d.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Excalidraw types based on the official Excalidraw scene format.
|
|
4
|
+
* References:
|
|
5
|
+
* - https://raw.githubusercontent.com/excalidraw/excalidraw/master/packages/excalidraw/element/types.ts
|
|
6
|
+
* - https://raw.githubusercontent.com/excalidraw/excalidraw/master/packages/excalidraw/data/types.ts
|
|
7
|
+
*/
|
|
8
|
+
type FileId = string & {
|
|
9
|
+
_brand: "FileId";
|
|
10
|
+
};
|
|
11
|
+
type DataURL = string & {
|
|
12
|
+
_brand: "DataURL";
|
|
13
|
+
};
|
|
6
14
|
type StrokeStyle = "solid" | "dashed" | "dotted";
|
|
15
|
+
type FillStyle = "hachure" | "cross-hachure" | "solid" | "zigzag";
|
|
7
16
|
type Arrowhead = "arrow" | "bar" | "dot" | "triangle" | "triangle_outline" | "diamond" | "diamond_outline";
|
|
8
17
|
type VerticalAlign = "top" | "middle" | "bottom";
|
|
9
18
|
type TextAlign = "left" | "center" | "right";
|
|
10
19
|
type ElementStatus = "pending" | "saved" | "error";
|
|
11
|
-
type
|
|
12
|
-
|
|
20
|
+
type Roundness = {
|
|
21
|
+
type: number;
|
|
22
|
+
value?: number;
|
|
13
23
|
};
|
|
14
|
-
interface
|
|
15
|
-
id:
|
|
24
|
+
interface ExcalidrawElementBase {
|
|
25
|
+
id: string;
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
strokeColor: string;
|
|
29
|
+
backgroundColor: string;
|
|
30
|
+
fillStyle: FillStyle;
|
|
31
|
+
strokeWidth: number;
|
|
32
|
+
strokeStyle: StrokeStyle;
|
|
33
|
+
roughness: number;
|
|
34
|
+
opacity: number;
|
|
35
|
+
width: number;
|
|
36
|
+
height: number;
|
|
37
|
+
angle: number;
|
|
38
|
+
seed: number;
|
|
39
|
+
version: number;
|
|
40
|
+
versionNonce: number;
|
|
41
|
+
isDeleted: boolean;
|
|
42
|
+
groupIds: readonly string[];
|
|
43
|
+
frameId: string | null;
|
|
44
|
+
boundElements: readonly {
|
|
45
|
+
type: "text" | "arrow";
|
|
46
|
+
id: string;
|
|
47
|
+
}[] | null;
|
|
48
|
+
updated: number;
|
|
49
|
+
link: string | null;
|
|
50
|
+
locked: boolean;
|
|
51
|
+
type: string;
|
|
52
|
+
index: string;
|
|
53
|
+
}
|
|
54
|
+
interface ExcalidrawGenericElement extends ExcalidrawElementBase {
|
|
55
|
+
type: "rectangle" | "diamond" | "ellipse" | "selection";
|
|
56
|
+
roundness: Roundness | null;
|
|
57
|
+
}
|
|
58
|
+
interface ExcalidrawTextElement extends ExcalidrawElementBase {
|
|
59
|
+
type: "text";
|
|
60
|
+
text: string;
|
|
61
|
+
fontSize: number;
|
|
62
|
+
fontFamily: number;
|
|
63
|
+
textAlign: TextAlign;
|
|
64
|
+
verticalAlign: VerticalAlign;
|
|
65
|
+
containerId: string | null;
|
|
66
|
+
originalText: string;
|
|
67
|
+
autoResize?: boolean;
|
|
68
|
+
lineHeight?: number;
|
|
69
|
+
}
|
|
70
|
+
interface ExcalidrawLinearElement extends ExcalidrawElementBase {
|
|
71
|
+
type: "arrow" | "line";
|
|
72
|
+
points: readonly number[][];
|
|
73
|
+
lastCommittedPoint?: readonly number[] | null;
|
|
74
|
+
startBinding?: {
|
|
75
|
+
elementId: string;
|
|
76
|
+
focus: number;
|
|
77
|
+
gap: number;
|
|
78
|
+
} | null;
|
|
79
|
+
endBinding?: {
|
|
80
|
+
elementId: string;
|
|
81
|
+
focus: number;
|
|
82
|
+
gap: number;
|
|
83
|
+
} | null;
|
|
84
|
+
startArrowhead: Arrowhead | null;
|
|
85
|
+
endArrowhead: Arrowhead | null;
|
|
86
|
+
}
|
|
87
|
+
type ExcalidrawElement = ExcalidrawGenericElement | ExcalidrawTextElement | ExcalidrawLinearElement;
|
|
88
|
+
type AppState = {
|
|
89
|
+
gridSize: number | null;
|
|
90
|
+
gridStep: number;
|
|
91
|
+
gridModeEnabled: boolean;
|
|
92
|
+
viewBackgroundColor: string;
|
|
93
|
+
lockedMultiSelections: Record<string, boolean>;
|
|
94
|
+
theme?: "light" | "dark";
|
|
95
|
+
name?: string;
|
|
96
|
+
[key: string]: any;
|
|
97
|
+
};
|
|
98
|
+
type BinaryFileData = {
|
|
16
99
|
mimeType: string;
|
|
17
|
-
|
|
18
|
-
|
|
100
|
+
id: FileId;
|
|
101
|
+
dataURL: DataURL;
|
|
102
|
+
created: number;
|
|
19
103
|
lastRetrieved?: number;
|
|
20
104
|
status?: ElementStatus;
|
|
21
|
-
}
|
|
105
|
+
};
|
|
22
106
|
type BinaryFiles = Record<FileId, BinaryFileData>;
|
|
107
|
+
interface ExcalidrawScene {
|
|
108
|
+
type: "excalidraw";
|
|
109
|
+
version: 2;
|
|
110
|
+
source: string;
|
|
111
|
+
elements: readonly ExcalidrawElement[];
|
|
112
|
+
appState: Partial<AppState>;
|
|
113
|
+
files: BinaryFiles;
|
|
114
|
+
}
|
|
23
115
|
interface ElementLabel {
|
|
24
116
|
text: string;
|
|
25
117
|
fontSize?: number;
|
|
@@ -31,33 +123,36 @@ interface ElementLabel {
|
|
|
31
123
|
}
|
|
32
124
|
interface ExcalidrawElementSkeleton {
|
|
33
125
|
id?: string;
|
|
34
|
-
type:
|
|
126
|
+
type: string;
|
|
35
127
|
x?: number;
|
|
36
128
|
y?: number;
|
|
37
129
|
width?: number;
|
|
38
130
|
height?: number;
|
|
39
131
|
angle?: number;
|
|
40
132
|
groupIds?: string[];
|
|
41
|
-
roundness?: Roundness;
|
|
42
133
|
strokeWidth?: number;
|
|
43
134
|
strokeColor?: string;
|
|
44
135
|
backgroundColor?: string;
|
|
45
136
|
strokeStyle?: StrokeStyle;
|
|
46
|
-
fillStyle?:
|
|
137
|
+
fillStyle?: FillStyle;
|
|
138
|
+
roughness?: number;
|
|
139
|
+
opacity?: number;
|
|
140
|
+
seed?: number;
|
|
141
|
+
version?: number;
|
|
142
|
+
versionNonce?: number;
|
|
143
|
+
isDeleted?: boolean;
|
|
144
|
+
boundElements?: {
|
|
145
|
+
id: string;
|
|
146
|
+
type: "text" | "arrow";
|
|
147
|
+
}[] | null;
|
|
148
|
+
updated?: number;
|
|
149
|
+
link?: string | null;
|
|
150
|
+
locked?: boolean;
|
|
151
|
+
index?: string;
|
|
152
|
+
label?: ElementLabel;
|
|
153
|
+
points?: number[][];
|
|
47
154
|
startArrowhead?: Arrowhead | null;
|
|
48
155
|
endArrowhead?: Arrowhead | null;
|
|
49
|
-
points?: number[][];
|
|
50
|
-
label?: ElementLabel;
|
|
51
|
-
text?: string;
|
|
52
|
-
fontSize?: number;
|
|
53
|
-
fontFamily?: number;
|
|
54
|
-
textAlign?: TextAlign;
|
|
55
|
-
verticalAlign?: VerticalAlign;
|
|
56
|
-
link?: string | null;
|
|
57
|
-
fileId?: FileId;
|
|
58
|
-
status?: ElementStatus;
|
|
59
|
-
name?: string;
|
|
60
|
-
children?: string[];
|
|
61
156
|
start?: {
|
|
62
157
|
id?: string;
|
|
63
158
|
type?: string;
|
|
@@ -66,12 +161,11 @@ interface ExcalidrawElementSkeleton {
|
|
|
66
161
|
id?: string;
|
|
67
162
|
type?: string;
|
|
68
163
|
};
|
|
164
|
+
[key: string]: any;
|
|
69
165
|
}
|
|
70
|
-
//#endregion
|
|
71
|
-
//#region src/interfaces.d.ts
|
|
72
166
|
interface MermaidToExcalidrawResult {
|
|
73
167
|
elements: ExcalidrawElementSkeleton[];
|
|
74
|
-
files
|
|
168
|
+
files: BinaryFiles;
|
|
75
169
|
}
|
|
76
170
|
//#endregion
|
|
77
171
|
//#region src/validateMermaid.d.ts
|
|
@@ -113,5 +207,6 @@ interface ExcalidrawConfig {
|
|
|
113
207
|
fontSize?: number;
|
|
114
208
|
}
|
|
115
209
|
declare const parseMermaidToExcalidraw: (definition: string, config?: MermaidConfig) => Promise<MermaidToExcalidrawResult>;
|
|
210
|
+
declare const serializeToExcalidraw: (result: MermaidToExcalidrawResult) => ExcalidrawScene;
|
|
116
211
|
//#endregion
|
|
117
|
-
export { ExcalidrawConfig, MermaidConfig, parseMermaidToExcalidraw, validateMermaid };
|
|
212
|
+
export { ExcalidrawConfig, MermaidConfig, parseMermaidToExcalidraw, serializeToExcalidraw, validateMermaid };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"mermaid";const t={rect:`rectangle`,circle:`ellipse`},n={startOnLoad:!1,flowchart:{curve:`linear`},themeVariables:{fontSize:`${20*1.25}px`},maxEdges:500,maxTextSize:5e4};
|
|
2
|
-
`),b=e=>{let t={type:`line`,x:e.startX,y:e.startY,points:[[0,0],[e.endX-e.startX,e.endY-e.startY]],width:e.endX-e.startX,height:e.endY-e.startY,strokeStyle:e.strokeStyle||`solid`,strokeColor:e.strokeColor||`#000`,strokeWidth:e.strokeWidth||1};return e.groupId&&Object.assign(t,{groupIds:[e.groupId]}),e.id&&Object.assign(t,{id:e.id}),t},x=e=>{let t={type:`text`,x:e.x,y:e.y,width:e.width,height:e.height,text:y(e.text)||``,fontSize:e.fontSize,verticalAlign:`middle`};return e.groupId&&Object.assign(t,{groupIds:[e.groupId]}),e.id&&Object.assign(t,{id:e.id}),t},S=e=>{let t={};e.type===`rectangle`&&e.subtype===`activation`&&(t={backgroundColor:`#e9ecef`,fillStyle:`solid`});let n={id:e.id,type:e.type,x:e.x,y:e.y,width:e.width,height:e.height,label:{text:y(e?.label?.text||``),fontSize:e?.label?.fontSize,verticalAlign:e.label?.verticalAlign||`middle`,strokeColor:e.label?.color||`#000`,groupIds:e.groupId?[e.groupId]:[]},strokeStyle:e?.strokeStyle,strokeWidth:e?.strokeWidth,strokeColor:e?.strokeColor,backgroundColor:e?.bgColor,fillStyle:`solid`,...t};return e.groupId&&Object.assign(n,{groupIds:[e.groupId]}),n},C=e=>{let t={type:`arrow`,x:e.startX,y:e.startY,points:e.points||[[0,0],[e.endX-e.startX,e.endY-e.startY]],width:e.endX-e.startX,height:e.endY-e.startY,strokeStyle:e?.strokeStyle||`solid`,endArrowhead:e?.endArrowhead||null,startArrowhead:e?.startArrowhead||null,label:{text:y(e?.label?.text||``),fontSize:16},roundness:{type:2},start:e.start,end:e.end};return e.groupId&&Object.assign(t,{groupIds:[e.groupId]}),t},w=new r({converter:e=>{let t=[],n=[];if(Object.values(e.nodes).forEach(e=>{!e||!e.length||e.forEach(e=>{let r;switch(e.type){case`line`:r=b(e);break;case`rectangle`:case`ellipse`:r=S(e);break;case`text`:r=x(e);break;default:throw`unknown type ${e.type}`}e.type===`rectangle`&&e?.subtype===`activation`?n.push(r):t.push(r)})}),Object.values(e.lines).forEach(e=>{e&&t.push(b(e))}),Object.values(e.arrows).forEach(e=>{e&&(t.push(C(e)),e.sequenceNumber&&t.push(S(e.sequenceNumber)))}),t.push(...n),e.loops){let{lines:n,texts:r,nodes:i}=e.loops;n.forEach(e=>{t.push(b(e))}),r.forEach(e=>{t.push(x(e))}),i.forEach(e=>{t.push(S(e))})}return e.groups&&e.groups.forEach(e=>{let{actorKeys:n,name:r}=e,i=1/0,a=1/0,o=0,s=0;if(!n.length)return;t.filter(e=>{if(e.id){let t=e.id.indexOf(`-`),r=e.id.substring(0,t);return n.includes(r)}}).forEach(e=>{if(e.x===void 0||e.y===void 0||e.width===void 0||e.height===void 0)throw Error(`Actor attributes missing ${e}`);i=Math.min(i,e.x),a=Math.min(a,e.y),o=Math.max(o,e.x+e.width),s=Math.max(s,e.y+e.height)});let c=i-10,l=a-10,u=o-i+20,d=s-a+20,f=_(),p=S({type:`rectangle`,x:c,y:l,width:u,height:d,bgColor:e.fill,id:f});t.unshift(p);let m=_(),h=[f];t.forEach(e=>{if(e.type!==`frame`){if(e.x===void 0||e.y===void 0||e.width===void 0||e.height===void 0)throw Error(`Element attributes missing ${e}`);if(e.x>=i&&e.x+e.width<=o&&e.y>=a&&e.y+e.height<=s){let t=e.id||_();e.id||Object.assign(e,{id:t}),h.push(t)}}});let g={type:`frame`,id:m,name:r,children:h};t.push(g)}),{elements:t}}}),ee=new r({converter:e=>{let t=[];return Object.values(e.nodes).forEach(e=>{!e||!e.length||e.forEach(e=>{let n;switch(e.type){case`line`:n=b(e);break;case`rectangle`:case`ellipse`:n=S(e);break;case`text`:n=x(e);break;default:throw`unknown type ${e.type}`}t.push(n)})}),Object.values(e.lines).forEach(e=>{e&&t.push(b(e))}),Object.values(e.arrows).forEach(e=>{if(!e)return;let n=C(e);t.push(n)}),Object.values(e.text).forEach(e=>{let n=x(e);t.push(n)}),Object.values(e.namespaces).forEach(n=>{let r=n.classes||{},i=Object.keys(r),a=[...i],o=[...e.lines,...e.arrows,...e.text];i.forEach(e=>{let t=o.filter(t=>t.metadata&&t.metadata.classId===e).map(e=>e.id);t.length&&a.push(...t)});let s={type:`frame`,id:_(),name:n.id,children:a};t.push(s)}),{elements:t}}}),T=(e,t={})=>{switch(e.type){case`graphImage`:return v.convert(e,t);case`flowchart`:return g.convert(e,t);case`sequence`:return w.convert(e,t);case`class`:return ee.convert(e,t);default:throw Error(`graphToExcalidraw: unknown graph type "${e.type}, only flowcharts are supported!"`)}},E=e=>{e=O(e);let t=e.replace(/#(\d+);/g,`&#$1;`).replace(/#([a-z]+);/g,`&$1;`),n=document.createElement(`textarea`);return n.innerHTML=t,n.value},D=e=>{let t=e.getAttribute(`transform`)?.match(/translate\(([ \d.-]+),\s*([\d.-]+)\)/),n=0,r=0;return t&&(n=Number(t[1]),r=Number(t[2])),{transformX:n,transformY:r}},te=e=>{let t=e;return t=t.replace(/style.*:\S*#.*;/g,e=>e.substring(0,e.length-1)),t=t.replace(/classDef.*:\S*#.*;/g,e=>e.substring(0,e.length-1)),t=t.replace(/#\w+;/g,e=>{let t=e.substring(1,e.length-1);return/^\+?\d+$/.test(t)?`fl°°${t}¶ß`:`fl°${t}¶ß`}),t},O=function(e){return e.replace(/fl°°/g,`#`).replace(/fl°/g,`&`).replace(/¶ß/g,`;`)},k=(e,t={x:0,y:0})=>{if(e.tagName.toLowerCase()!==`path`)throw Error(`Invalid input: Expected an HTMLElement of tag "path", got ${e.tagName}`);let n=e.getAttribute(`d`);if(!n)throw Error(`Path element does not contain a "d" attribute`);let r=n.split(/(?=[LM])/),i=r[0].substring(1).split(`,`).map(e=>parseFloat(e)),a=r[r.length-1].substring(1).split(`,`).map(e=>parseFloat(e)),o=r.map(e=>{let t=e.substring(1).split(`,`).map(e=>parseFloat(e));return{x:t[0],y:t[1]}}).filter((e,t,n)=>{if(t===0||t===n.length-1)return!0;if(e.x===n[t-1].x&&e.y===n[t-1].y)return!1;if(t===n.length-2&&(n[t-1].x===e.x||n[t-1].y===e.y)){let t=n[n.length-1];return Math.hypot(t.x-e.x,t.y-e.y)>20}return e.x!==n[t-1].x||e.y!==n[t-1].y}).map(e=>({x:e.x+t.x,y:e.y+t.y}));return{startX:i[0]+t.x,startY:i[1]+t.y,endX:a[0]+t.x,endY:a[1]+t.y,reflectionPoints:o}},A=(e,t)=>{let n=e.nodes.map(e=>e.startsWith(`flowchart-`)?e.split(`-`)[1]:e),r=t.querySelector(`[id='${e.id}']`);if(!r)throw Error(`SubGraph element not found`);let i=N(r,t),a=r.getBBox(),o={width:a.width,height:a.height};return e.classes=void 0,e.dir=void 0,{...e,nodeIds:n,...i,...o,text:E(e.title)}},j=(e,t,n)=>{let r=t.querySelector(`[id*="flowchart-${e.id}-"]`);if(!r)return;let i;r.parentElement?.tagName.toLowerCase()===`a`&&(i=r.parentElement.getAttribute(`xlink:href`));let a=N(i?r.parentElement:r,t),o=r.getBBox(),s={width:o.width,height:o.height},c=r.querySelector(`.label-container`)?.getAttribute(`style`),l=r.querySelector(`.label`)?.getAttribute(`style`),u={};c?.split(`;`).forEach(e=>{if(!e)return;let t=e.split(`:`)[0].trim();u[t]=e.split(`:`)[1].trim()});let d={};if(l?.split(`;`).forEach(e=>{if(!e)return;let t=e.split(`:`)[0].trim();d[t]=e.split(`:`)[1].trim()}),e.classes){let t=n[e.classes];t&&(t.styles?.forEach(e=>{let[t,n]=e.split(`:`);u[t.trim()]=n.trim()}),t.textStyles?.forEach(e=>{let[t,n]=e.split(`:`);d[t.trim()]=n.trim()}))}return{id:e.id,labelType:e.labelType,text:E(e.text),type:e.type,link:i||void 0,...a,...s,containerStyle:u,labelStyle:d}},M=(e,t,n)=>{let r=n.querySelector(`[id*="L-${e.start}-${e.end}-${t}"]`);if(!r)throw Error(`Edge element not found`);let i=k(r,N(r,n));return e.length=void 0,{...e,...i,text:E(e.text)}},N=(e,t)=>{if(!e)throw Error(`Element not found`);let n=e.parentElement?.parentElement,r=e.childNodes[0],i={x:0,y:0};if(r){let{transformX:e,transformY:t}=D(r),n=r.getBBox();i={x:Number(r.getAttribute(`x`))||e+n.x||0,y:Number(r.getAttribute(`y`))||t+n.y||0}}let{transformX:a,transformY:o}=D(e),s={x:a+i.x,y:o+i.y};for(;n&&n.id!==t.id;){if(n.classList.value===`root`&&n.hasAttribute(`transform`)){let{transformX:e,transformY:t}=D(n);s.x+=e,s.y+=t}n=n.parentElement}return s},ne=(e,t)=>{e.parse();let n=e.parser.yy,r=n.getVertices(),i=n.getClasses();Object.keys(r).forEach(e=>{r[e]=j(r[e],t,i)});let a=new Map,o=n.getEdges().filter(e=>t.querySelector(`[id*="L-${e.start}-${e.end}"]`)).map(e=>{let n=`${e.start}-${e.end}`,r=a.get(n)||0;return a.set(n,r+1),M(e,r,t)});return{type:`flowchart`,subGraphs:n.getSubGraphs().map(e=>A(e,t)),vertices:r,edges:o}},re=(e,t)=>{let n={};t?.label&&(n.label={text:E(t.label),fontSize:16});let r=e.tagName;if(r===`line`)n.startX=Number(e.getAttribute(`x1`)),n.startY=Number(e.getAttribute(`y1`)),n.endX=Number(e.getAttribute(`x2`)),n.endY=Number(e.getAttribute(`y2`));else if(r===`path`){let t=e.getAttribute(`d`);if(!t)throw Error(`Path element does not contain a "d" attribute`);let r=t.split(/(?=[LC])/),i=r[0].substring(1).split(`,`).map(e=>parseFloat(e)),a=[];r.forEach(e=>{let t=e.substring(1).trim().split(` `).map(e=>{let[t,n]=e.split(`,`);return[parseFloat(t)-i[0],parseFloat(n)-i[1]]});a.push(...t)});let o=a[a.length-1];n.startX=i[0],n.startY=i[1],n.endX=o[0],n.endY=o[1],n.points=a}return t?.label&&(n.startY-=10,n.endY-=10),n.strokeColor=e.getAttribute(`stroke`),n.strokeWidth=Number(e.getAttribute(`stroke-width`)),n.type=`arrow`,n.strokeStyle=t?.strokeStyle||`solid`,n.startArrowhead=t?.startArrowhead||null,n.endArrowhead=t?.endArrowhead||null,n},P=(e,t,n,r,i)=>{let a={};return a.type=`arrow`,a.startX=e,a.startY=t,a.endX=n,a.endY=r,Object.assign(a,{...i}),a},F=(e,t,n,r)=>({type:`text`,x:e,y:t,text:n,width:r?.width||20,height:r?.height||20,fontSize:r?.fontSize||20,id:r?.id,groupId:r?.groupId,metadata:r?.metadata}),I=(e,t,n)=>{let r={},i=Number(e.getAttribute(`x`)),a=Number(e.getAttribute(`y`));r.type=`text`,r.text=E(t),n?.id&&(r.id=n.id),n?.groupId&&(r.groupId=n.groupId);let o=e.getBBox();return r.width=o.width,r.height=o.height,r.x=i-o.width/2,r.y=a,r.fontSize=parseInt(getComputedStyle(e).fontSize),r},L=(e,t,n={})=>{let r={};r.type=t;let{label:i,subtype:a,id:o,groupId:s}=n;r.id=o,s&&(r.groupId=s),i&&(r.label={text:E(i.text),fontSize:16,verticalAlign:i?.verticalAlign});let c=e.getBBox();switch(r.x=c.x,r.y=c.y,r.width=c.width,r.height=c.height,r.subtype=a,a){case`highlight`:let t=e.getAttribute(`fill`);t&&(r.bgColor=t);break;case`note`:r.strokeStyle=`dashed`;break}return r},R=(e,t,n,r,i,a)=>{let o={};return o.startX=t,o.startY=n,o.endX=r,a?.groupId&&(o.groupId=a.groupId),a?.id&&(o.id=a.id),o.endY=i,o.strokeColor=e.getAttribute(`stroke`),o.strokeWidth=Number(e.getAttribute(`stroke-width`)),o.type=`line`,o},z={0:`SOLID`,1:`DOTTED`,3:`SOLID_CROSS`,4:`DOTTED_CROSS`,5:`SOLID_OPEN`,6:`DOTTED_OPEN`,24:`SOLID_POINT`,25:`DOTTED_POINT`},B={SOLID:0,DOTTED:1,NOTE:2,SOLID_CROSS:3,DOTTED_CROSS:4,SOLID_OPEN:5,DOTTED_OPEN:6,LOOP_START:10,LOOP_END:11,ALT_START:12,ALT_ELSE:13,ALT_END:14,OPT_START:15,OPT_END:16,ACTIVE_START:17,ACTIVE_END:18,PAR_START:19,PAR_AND:20,PAR_END:21,RECT_START:22,RECT_END:23,SOLID_POINT:24,DOTTED_POINT:25,AUTONUMBER:26,CRITICAL_START:27,CRITICAL_OPTION:28,CRITICAL_END:29,BREAK_START:30,BREAK_END:31,PAR_OVER_START:32},V=e=>{let t;switch(e){case B.SOLID:case B.SOLID_CROSS:case B.SOLID_OPEN:case B.SOLID_POINT:t=`solid`;break;case B.DOTTED:case B.DOTTED_CROSS:case B.DOTTED_OPEN:case B.DOTTED_POINT:t=`dotted`;break;default:t=`solid`;break}return t},H=(e,t)=>{if(e.nextElementSibling?.classList.contains(`sequenceNumber`)){let n=e.nextElementSibling?.textContent;if(!n)throw Error(`sequence number not present`);let r={type:`rectangle`,x:t.startX-10,y:t.startY-15,label:{text:n,fontSize:14},bgColor:`#e9ecef`,height:30,subtype:`sequence`};Object.assign(t,{sequenceNumber:r})}},U=(e,n,r)=>{if(!e)throw`root node not found`;let i=_(),a=Array.from(e.children),o=[];return a.forEach((e,a)=>{let s=`${r?.id}-${a}`,c;switch(e.tagName){case`line`:c=R(e,Number(e.getAttribute(`x1`)),Number(e.getAttribute(`y1`)),Number(e.getAttribute(`x2`)),Number(e.getAttribute(`y2`)),{groupId:i,id:s});break;case`text`:c=I(e,n,{groupId:i,id:s});break;case`circle`:c=L(e,`ellipse`,{label:e.textContent?{text:e.textContent}:void 0,groupId:i,id:s});default:c=L(e,t[e.tagName],{label:e.textContent?{text:e.textContent}:void 0,groupId:i,id:s})}o.push(c)}),o},W=(e,t)=>{let n=Array.from(t.querySelectorAll(`.actor-top`)),r=Array.from(t.querySelectorAll(`.actor-bottom`)),i=[],a=[];return Object.values(e).forEach((e,t)=>{let o=n.find(t=>t.getAttribute(`name`)===e.name),s=r.find(t=>t.getAttribute(`name`)===e.name);if(!o||!s)throw`root not found`;let c=e.description;if(e.type===`participant`){let t=L(o,`rectangle`,{id:`${e.name}-top`,label:{text:c},subtype:`actor`});if(!t)throw`Top Node element not found!`;i.push([t]);let n=L(s,`rectangle`,{id:`${e.name}-bottom`,label:{text:c},subtype:`actor`});i.push([n]);let r=o?.parentElement?.previousElementSibling;if(r?.tagName!==`line`)throw`Line not found`;let l=Number(r.getAttribute(`x1`));if(!t.height)throw`Top node element height is null`;let u=t.y+t.height,d=n.y,f=R(r,l,u,Number(r.getAttribute(`x2`)),d);a.push(f)}else if(e.type===`actor`){let t=U(o,c,{id:`${e.name}-top`});i.push(t);let n=U(s,c,{id:`${e.name}-bottom`});i.push(n);let r=o.previousElementSibling;if(r?.tagName!==`line`)throw`Line not found`;let l=Number(r.getAttribute(`x1`)),u=Number(r.getAttribute(`y1`)),d=Number(r.getAttribute(`x2`)),f=n.find(e=>e.type===`ellipse`);if(f){let e=f.y,t=R(r,l,u,d,e);a.push(t)}}}),{nodes:i,lines:a}},G=(e,t)=>{let n=[],r=Array.from(t.querySelectorAll(`[class*="messageLine"]`)),i=Object.keys(z),a=e.filter(e=>i.includes(e.type.toString()));return r.forEach((e,t)=>{let r=a[t],i=z[r.type],o=re(e,{label:r?.message,strokeStyle:V(r.type),endArrowhead:i===`SOLID_OPEN`||i===`DOTTED_OPEN`?null:`arrow`});H(e,o),n.push(o)}),n},K=(e,t)=>{let n=Array.from(t.querySelectorAll(`.note`)).map(e=>e.parentElement),r=e.filter(e=>e.type===B.NOTE),i=[];return n.forEach((e,t)=>{if(!e)return;let n=e.firstChild,a=r[t].message,o=L(n,`rectangle`,{label:{text:a},subtype:`note`});i.push(o)}),i},q=e=>{let t=Array.from(e.querySelectorAll(`[class*=activation]`)),n=[];return t.forEach(e=>{let t=L(e,`rectangle`,{label:{text:``},subtype:`activation`});n.push(t)}),n},J=(e,t)=>{let n=Array.from(t.querySelectorAll(`.loopLine`)),r=[],i=[],a=[];n.forEach(e=>{let t=R(e,Number(e.getAttribute(`x1`)),Number(e.getAttribute(`y1`)),Number(e.getAttribute(`x2`)),Number(e.getAttribute(`y2`)));t.strokeStyle=`dotted`,t.strokeColor=`#adb5bd`,t.strokeWidth=2,r.push(t)});let o=Array.from(t.querySelectorAll(`.loopText`)),s=e.filter(e=>e.type===B.CRITICAL_START).map(e=>e.message);o.forEach(e=>{let t=e.textContent||``,n=I(e,t),r=t.match(/\[(.*?)\]/)?.[1]||``;s.includes(r)&&(n.x+=16),i.push(n)});let c=Array.from(t?.querySelectorAll(`.labelBox`)),l=Array.from(t?.querySelectorAll(`.labelText`));return c.forEach((e,t)=>{let n=L(e,`rectangle`,{label:{text:l[t]?.textContent||``}});n.strokeColor=`#adb5bd`,n.bgColor=`#e9ecef`,n.width=void 0,a.push(n)}),{lines:r,texts:i,nodes:a}},Y=e=>{let t=Array.from(e.querySelectorAll(`.rect`)).filter(e=>e.parentElement?.tagName!==`g`),n=[];return t.forEach(e=>{let t=L(e,`rectangle`,{label:{text:``},subtype:`highlight`});n.push(t)}),n},ie=(e,t)=>{e.parse();let n=e.parser.yy,r=[],i=n.getBoxes(),a=Y(t),{nodes:o,lines:s}=W(n.getActors(),t),c=n.getMessages(),l=G(c,t),u=K(c,t),d=q(t),f=J(c,t);return r.push(a),r.push(...o),r.push(u),r.push(d),{type:`sequence`,lines:s,arrows:l,nodes:r,loops:f,groups:i}},X={AGGREGATION:0,EXTENSION:1,COMPOSITION:2,DEPENDENCY:3,LOLLIPOP:4},Z={LINE:0,DOTTED_LINE:1},ae=e=>{let t;switch(e){case Z.LINE:t=`solid`;break;case Z.DOTTED_LINE:t=`dotted`;break;default:t=`solid`}return t},Q=e=>{let t;switch(e){case X.AGGREGATION:t=`diamond_outline`;break;case X.COMPOSITION:t=`diamond`;break;case X.EXTENSION:t=`triangle_outline`;break;case`none`:t=null;break;case X.DEPENDENCY:default:t=`arrow`;break}return t},oe=(e,t)=>{let n=[],r=[],i=[];return Object.values(e).forEach(e=>{let{domId:a,id:o}=e,s=_(),c=t.querySelector(`[data-id=${o}]`);if(!c)throw Error(`DOM Node with id ${a} not found`);let{transformX:l,transformY:u}=D(c),d=L(c.firstChild,`rectangle`,{id:o,groupId:s});d.x+=l,d.y+=u,d.metadata={classId:o},n.push(d),Array.from(c.querySelectorAll(`.divider`)).forEach(e=>{let t=R(e,Number(e.getAttribute(`x1`)),Number(e.getAttribute(`y1`)),Number(e.getAttribute(`x2`)),Number(e.getAttribute(`y2`)),{groupId:s,id:_()});t.startX+=l,t.startY+=u,t.endX+=l,t.endY+=u,t.metadata={classId:o},r.push(t)});let f=c.querySelector(`.label`)?.children;if(!f)throw`label nodes not found`;Array.from(f).forEach(e=>{let t=e.textContent;if(!t)return;let n=_(),{transformX:r,transformY:a}=D(e),c=e.getBBox(),d=F(l+r,u+a+10,t,{width:c.width,height:c.height,id:n,groupId:s,metadata:{classId:o}});i.push(d)})}),{nodes:n,lines:r,text:i}},se=(e,t)=>{let n=[`triangle_outline`,`diamond`,`diamond_outline`],r=t.startArrowhead&&n.includes(t.startArrowhead),i=t.endArrowhead&&n.includes(t.endArrowhead);return!i&&!r?t:(r&&(e===`LR`?t.startX-=16:e===`RL`?t.startX+=16:e===`TB`?t.startY-=16:e===`BT`&&(t.startY+=16)),i&&(e===`LR`?t.endX+=16:e===`RL`?t.endX-=16:e===`TB`?t.endY+=16:e===`BT`&&(t.endY-=16)),t)},ce=(e,t,n,r)=>{let i=n.querySelector(`.edgePaths`)?.children;if(!i)throw Error(`No Edges found!`);let a=[],o=[];return e.forEach((e,n)=>{let{id1:s,id2:c,relation:l}=e,u=t.find(e=>e.id===s),d=t.find(e=>e.id===c),f=ae(l.lineType),p=Q(l.type1),m=Q(l.type2),h=k(i[n]),g=se(r,P(h.startX,h.startY,h.endX,h.endY,{strokeStyle:f,startArrowhead:p,endArrowhead:m,label:e.title?{text:e.title}:void 0,start:{type:`rectangle`,id:u.id},end:{type:`rectangle`,id:d.id}}));a.push(g);let{relationTitle1:_,relationTitle2:v}=e,y,b;if(_&&_!==`none`){switch(r){case`TB`:y=g.startX-20,g.endX<g.startX&&(y-=15),b=g.startY+15;break;case`BT`:y=g.startX+20,g.endX>g.startX&&(y+=15),b=g.startY-15;break;case`LR`:y=g.startX+20,b=g.startY+15,g.endY>g.startY&&(b+=15);break;case`RL`:y=g.startX-20,b=g.startY-15,g.startY>g.endY&&(b-=15);break;default:y=g.startX-20,b=g.startY+15}let e=F(y,b,_,{fontSize:16});o.push(e)}if(v&&v!==`none`){switch(r){case`TB`:y=g.endX+20,g.endX<g.startX&&(y+=15),b=g.endY-15;break;case`BT`:y=g.endX-20,g.endX>g.startX&&(y-=15),b=g.endY+15;break;case`LR`:y=g.endX-20,b=g.endY-15,g.endY>g.startY&&(b-=15);break;case`RL`:y=g.endX+20,b=g.endY+15,g.startY>g.endY&&(b+=15);break;default:y=g.endX+20,b=g.endY-15}let e=F(y,b,v,{fontSize:16});o.push(e)}}),{arrows:a,text:o}},le=(e,t,n)=>{let r=[],i=[];return e.forEach(e=>{let{id:a,text:o,class:s}=e,c=t.querySelector(`#${a}`);if(!c)throw Error(`Node with id ${a} not found!`);let{transformX:l,transformY:u}=D(c),d=c.firstChild,f=L(d,`rectangle`,{id:a,subtype:`note`,label:{text:o}});if(Object.assign(f,{x:f.x+l,y:f.y+u}),r.push(f),s){let e=n.find(e=>e.id===s);if(!e)throw Error(`class node with id ${s} not found!`);let t=f.x+(f.width||0)/2,r=f.y+(f.height||0),a=t,o=e.y,c=P(t,r,a,o,{strokeStyle:`dotted`,startArrowhead:null,endArrowhead:null,start:{id:f.id,type:`rectangle`},end:{id:e.id,type:`rectangle`}});i.push(c)}}),{notes:r,connectors:i}},$=(e,t)=>{e.parse();let n=e.parser.yy,r=n.getDirection(),i=[],a=[],o=[],s=[],c=n.getNamespaces(),l=n.getClasses();if(Object.keys(l).length){let e=oe(l,t);i.push(e.nodes),a.push(...e.lines),o.push(...e.text),s.push(...e.nodes)}let{arrows:u,text:d}=ce(n.getRelations(),s,t,r),{notes:f,connectors:p}=le(n.getNotes(),t,s);return i.push(f),u.push(...p),o.push(...d),{type:`class`,nodes:i,lines:a,arrows:u,text:o,namespaces:c}},ue=e=>{let t=e.querySelector(`svg`);if(!t)throw Error(`SVG element not found`);let n=t.getBoundingClientRect(),r=n.width,i=n.height;t.setAttribute(`width`,`${r}`),t.setAttribute(`height`,`${i}`);let a=unescape(encodeURIComponent(t.outerHTML));return{type:`graphImage`,mimeType:`image/svg+xml`,dataURL:`data:image/svg+xml;base64,${btoa(a)}`,width:r,height:i}},de=async(t,r=n)=>{e.initialize({...n,...r});let i=await e.mermaidAPI.getDiagramFromText(te(t)),{svg:a}=await e.render(`mermaid-to-excalidraw`,t),o=document.createElement(`div`);o.setAttribute(`style`,`opacity: 0; position: relative; z-index: -1;`),o.innerHTML=a,o.id=`mermaid-diagram`,document.body.appendChild(o);let s;switch(i.type){case`flowchart-v2`:s=ne(i,o);break;case`sequence`:s=ie(i,o);break;case`classDiagram`:s=$(i,o);break;default:s=ue(o)}return o.remove(),s};async function fe(t){return e.parse(t,{suppressErrors:!0})}const pe=async(e,t)=>{let n=t||{},r=parseInt(n.themeVariables?.fontSize??``)||20;return T(await de(e,{...n,themeVariables:{...n.themeVariables,fontSize:`${r*1.25}px`}}),{fontSize:r})};export{pe as parseMermaidToExcalidraw,fe as validateMermaid};
|
|
1
|
+
import e from"mermaid";const t={rect:`rectangle`,circle:`ellipse`},n={startOnLoad:!1,flowchart:{curve:`linear`},themeVariables:{fontSize:`${20*1.25}px`},maxEdges:500,maxTextSize:5e4},r=()=>Math.random().toString(36).substring(2,11),i=e=>`a${e.toString(36).padStart(2,`0`)}`,a=e=>{let t=[];for(let n=0;n<e.length;n++){let{label:a,...o}=e[n],s=o.id||r(),c=o.seed||Math.floor(Math.random()*1e6),l={...o,id:s,x:o.x||0,y:o.y||0,width:o.width||0,height:o.height||0,angle:o.angle||0,strokeColor:o.strokeColor||`#1e1e1e`,backgroundColor:o.backgroundColor||`transparent`,fillStyle:o.fillStyle||`solid`,strokeWidth:o.strokeWidth||2,strokeStyle:o.strokeStyle||`solid`,roughness:o.roughness||1,opacity:o.opacity||100,groupIds:o.groupIds||[],roundness:o.roundness||null,seed:c,version:o.version||1,versionNonce:o.versionNonce||Math.floor(Math.random()*1e6),isDeleted:o.isDeleted??!1,boundElements:o.boundElements||[],updated:o.updated||Date.now(),link:o.link||null,locked:o.locked??!1,frameId:null,index:o.index||i(n)};if(a){let e=r(),n=a.fontSize||20,i=a.text||``,o=i.length*n*.6,u=n*1.25,d={id:e,type:`text`,x:l.x+(l.width-o)/2,y:l.y+(l.height-u)/2,width:o,height:u,angle:0,text:i,fontSize:n,fontFamily:a.fontFamily||5,textAlign:a.textAlign||`center`,verticalAlign:a.verticalAlign||`middle`,containerId:s,strokeColor:a.strokeColor||l.strokeColor,backgroundColor:`transparent`,fillStyle:`solid`,strokeWidth:2,strokeStyle:`solid`,roughness:1,opacity:100,groupIds:a.groupIds||l.groupIds,seed:c+1,version:1,versionNonce:Math.floor(Math.random()*1e6),isDeleted:!1,updated:Date.now(),link:null,locked:!1,frameId:null,boundElements:[],originalText:i,autoResize:!0,lineHeight:1.25,index:l.index+`V`};l.boundElements=[...l.boundElements||[],{id:e,type:`text`}],t.push(l),t.push(d)}else t.push(l)}return t};var o=class{constructor({converter:e}){this.convert=(e,t)=>this.converter(e,{...t,fontSize:t.fontSize||20}),this.converter=e}};let s=function(e){return e.ROUND=`round`,e.STADIUM=`stadium`,e.DOUBLECIRCLE=`doublecircle`,e.CIRCLE=`circle`,e.DIAMOND=`diamond`,e}({}),c=function(e){return e.COLOR=`color`,e}({}),l=function(e){return e.FILL=`fill`,e.STROKE=`stroke`,e.STROKE_WIDTH=`stroke-width`,e.STROKE_DASHARRAY=`stroke-dasharray`,e}({});const u=[[/\*\*\*(.*?)\*\*\*/g,`$1`],[/\*\*(.*?)\*\*/g,`$1`],[/\*(.*?)\*/g,`$1`],[/__(.*?)__/g,`$1`],[/_(.*?)_/g,`$1`],[/~~(.*?)~~/g,`$1`],[/~~(.*?)~~/g,`$1`],[/`(.*?)`/g,`$1`],[/\[(.*?)\]\(.*?\)/g,`$1`],[/!\[.*?\]\(.*?\)/g,``],[/^#+\s+/gm,``],[/^[-*+]\s+/gm,``],[/^\d+\.\s+/gm,``],[/^>\s+/gm,``]],d=e=>{let t=e;for(let[e,n]of u)t=t.replace(e,n);return t.trim()},f={arrow_circle:{endArrowhead:`dot`},arrow_cross:{endArrowhead:`bar`},arrow_open:{endArrowhead:null,startArrowhead:null},double_arrow_circle:{endArrowhead:`dot`,startArrowhead:`dot`},double_arrow_cross:{endArrowhead:`bar`,startArrowhead:`bar`},double_arrow_point:{endArrowhead:`arrow`,startArrowhead:`arrow`}},p=e=>f[e],m=e=>{let t=e.text;return e.labelType===`markdown`&&(t=d(e.text)),h(t)},h=e=>e.replace(/\s?(fa|fab):[a-zA-Z0-9-]+/g,``),g=e=>{let t={};return Object.keys(e).forEach(n=>{switch(n){case l.FILL:t.backgroundColor=e[n],t.fillStyle=`solid`;break;case l.STROKE:t.strokeColor=e[n];break;case l.STROKE_WIDTH:t.strokeWidth=Number(e[n]?.split(`px`)[0]);break;case l.STROKE_DASHARRAY:t.strokeStyle=`dashed`;break}}),t},_=e=>{let t={};return Object.keys(e).forEach(n=>{switch(n){case c.COLOR:t.strokeColor=e[n];break}}),t},v=e=>{let t={};e.subGraphs.map(n=>{n.nodeIds.forEach(r=>{t[n.id]={id:n.id,parent:null,isLeaf:!1},t[r]={id:r,parent:n.id,isLeaf:e.vertices[r]!==void 0}})});let n={};return[...Object.keys(e.vertices),...e.subGraphs.map(e=>e.id)].forEach(e=>{if(!t[e])return;let r=t[e],i=[];for(r.isLeaf||i.push(`subgraph_group_${r.id}`);r.parent;)i.push(`subgraph_group_${r.parent}`),r=t[r.parent];n[e]=i}),{getGroupIds:e=>n[e]||[],getParentId:e=>t[e]?t[e].parent:null}},y=new o({converter:(e,t)=>{let n=[],r=t.fontSize,{getGroupIds:i,getParentId:a}=v(e);return e.subGraphs.reverse().forEach(e=>{let t=i(e.id),a={id:e.id,type:`rectangle`,groupIds:t,x:e.x,y:e.y,width:e.width,height:e.height,label:{groupIds:t,text:m(e),fontSize:r,verticalAlign:`top`}};n.push(a)}),Object.values(e.vertices).forEach(e=>{if(!e)return;let t=i(e.id),a=g(e.containerStyle),o=_(e.labelStyle),c={id:e.id,type:`rectangle`,groupIds:t,x:e.x,y:e.y,width:e.width,height:e.height,strokeWidth:2,label:{groupIds:t,text:m(e),fontSize:r,...o},link:e.link||null,...a};switch(e.type){case s.STADIUM:c={...c,roundness:{type:3}};break;case s.ROUND:c={...c,roundness:{type:3}};break;case s.DOUBLECIRCLE:{t.push(`doublecircle_${e.id}}`);let i={type:`ellipse`,groupIds:t,x:e.x+5,y:e.y+5,width:e.width-10,height:e.height-10,strokeWidth:2,roundness:{type:3},label:{groupIds:t,text:m(e),fontSize:r}};c={...c,groupIds:t,type:`ellipse`},n.push(i);break}case s.CIRCLE:c.type=`ellipse`;break;case s.DIAMOND:c.type=`diamond`;break}n.push(c)}),e.edges.forEach(e=>{let t=[],o=a(e.start),s=a(e.end);o&&o===s&&(t=i(o));let{startX:c,startY:l,reflectionPoints:u}=e,d=u.map(e=>[e.x-u[0].x,e.y-u[0].y]),f=p(e.type),h={id:`${e.start}_${e.end}`,type:`arrow`,groupIds:t,x:c,y:l,strokeWidth:e.stroke===`thick`?4:2,strokeStyle:e.stroke===`dotted`?`dashed`:void 0,points:d,...e.text?{label:{text:m(e),fontSize:r,groupIds:t}}:{},roundness:{type:2},...f},g=n.find(t=>t.id===e.start),_=n.find(t=>t.id===e.end);!g||!_||(h.start={id:g.id||``},h.end={id:_.id||``},n.push(h))}),{elements:n}}});function b(){return Math.random().toString(36).substring(2,9)}const ee=new o({converter:e=>{let t=b(),{width:n,height:r}=e,i={type:`image`,x:0,y:0,width:n,height:r,status:`saved`,fileId:t};return{files:{[t]:{id:t,mimeType:e.mimeType,dataURL:e.dataURL}},elements:[i]}}}),x=e=>e.replace(/\\n/g,`
|
|
2
|
+
`),S=e=>{let t={type:`line`,x:e.startX,y:e.startY,points:[[0,0],[e.endX-e.startX,e.endY-e.startY]],width:e.endX-e.startX,height:e.endY-e.startY,strokeStyle:e.strokeStyle||`solid`,strokeColor:e.strokeColor||`#000`,strokeWidth:e.strokeWidth||1};return e.groupId&&Object.assign(t,{groupIds:[e.groupId]}),e.id&&Object.assign(t,{id:e.id}),t},C=e=>{let t={type:`text`,x:e.x,y:e.y,width:e.width,height:e.height,text:x(e.text)||``,fontSize:e.fontSize,verticalAlign:`middle`};return e.groupId&&Object.assign(t,{groupIds:[e.groupId]}),e.id&&Object.assign(t,{id:e.id}),t},w=e=>{let t={};e.type===`rectangle`&&e.subtype===`activation`&&(t={backgroundColor:`#e9ecef`,fillStyle:`solid`});let n={id:e.id,type:e.type,x:e.x,y:e.y,width:e.width,height:e.height,label:{text:x(e?.label?.text||``),fontSize:e?.label?.fontSize,verticalAlign:e.label?.verticalAlign||`middle`,strokeColor:e.label?.color||`#000`,groupIds:e.groupId?[e.groupId]:[]},strokeStyle:e?.strokeStyle,strokeWidth:e?.strokeWidth,strokeColor:e?.strokeColor,backgroundColor:e?.bgColor,fillStyle:`solid`,...t};return e.groupId&&Object.assign(n,{groupIds:[e.groupId]}),n},T=e=>{let t={type:`arrow`,x:e.startX,y:e.startY,points:e.points||[[0,0],[e.endX-e.startX,e.endY-e.startY]],width:e.endX-e.startX,height:e.endY-e.startY,strokeStyle:e?.strokeStyle||`solid`,endArrowhead:e?.endArrowhead||null,startArrowhead:e?.startArrowhead||null,label:{text:x(e?.label?.text||``),fontSize:16},roundness:{type:2},start:e.start,end:e.end};return e.groupId&&Object.assign(t,{groupIds:[e.groupId]}),t},E=new o({converter:e=>{let t=[],n=[];if(Object.values(e.nodes).forEach(e=>{!e||!e.length||e.forEach(e=>{let r;switch(e.type){case`line`:r=S(e);break;case`rectangle`:case`ellipse`:r=w(e);break;case`text`:r=C(e);break;default:throw`unknown type ${e.type}`}e.type===`rectangle`&&e?.subtype===`activation`?n.push(r):t.push(r)})}),Object.values(e.lines).forEach(e=>{e&&t.push(S(e))}),Object.values(e.arrows).forEach(e=>{e&&(t.push(T(e)),e.sequenceNumber&&t.push(w(e.sequenceNumber)))}),t.push(...n),e.loops){let{lines:n,texts:r,nodes:i}=e.loops;n.forEach(e=>{t.push(S(e))}),r.forEach(e=>{t.push(C(e))}),i.forEach(e=>{t.push(w(e))})}return e.groups&&e.groups.forEach(e=>{let{actorKeys:n,name:r}=e,i=1/0,a=1/0,o=0,s=0;if(!n.length)return;t.filter(e=>{if(e.id){let t=e.id.indexOf(`-`),r=e.id.substring(0,t);return n.includes(r)}}).forEach(e=>{if(e.x===void 0||e.y===void 0||e.width===void 0||e.height===void 0)throw Error(`Actor attributes missing ${e}`);i=Math.min(i,e.x),a=Math.min(a,e.y),o=Math.max(o,e.x+e.width),s=Math.max(s,e.y+e.height)});let c=i-10,l=a-10,u=o-i+20,d=s-a+20,f=b(),p=w({type:`rectangle`,x:c,y:l,width:u,height:d,bgColor:e.fill,id:f});t.unshift(p);let m=b(),h=[f];t.forEach(e=>{if(e.type!==`frame`){if(e.x===void 0||e.y===void 0||e.width===void 0||e.height===void 0)throw Error(`Element attributes missing ${e}`);if(e.x>=i&&e.x+e.width<=o&&e.y>=a&&e.y+e.height<=s){let t=e.id||b();e.id||Object.assign(e,{id:t}),h.push(t)}}});let g={type:`frame`,id:m,name:r,children:h};t.push(g)}),{elements:t}}}),D=new o({converter:e=>{let t=[];return Object.values(e.nodes).forEach(e=>{!e||!e.length||e.forEach(e=>{let n;switch(e.type){case`line`:n=S(e);break;case`rectangle`:case`ellipse`:n=w(e);break;case`text`:n=C(e);break;default:throw`unknown type ${e.type}`}t.push(n)})}),Object.values(e.lines).forEach(e=>{e&&t.push(S(e))}),Object.values(e.arrows).forEach(e=>{if(!e)return;let n=T(e);t.push(n)}),Object.values(e.text).forEach(e=>{let n=C(e);t.push(n)}),Object.values(e.namespaces).forEach(n=>{let r=n.classes||{},i=Object.keys(r),a=[...i],o=[...e.lines,...e.arrows,...e.text];i.forEach(e=>{let t=o.filter(t=>t.metadata&&t.metadata.classId===e).map(e=>e.id);t.length&&a.push(...t)});let s={type:`frame`,id:b(),name:n.id,children:a};t.push(s)}),{elements:t}}}),te=(e,t={})=>{switch(e.type){case`graphImage`:return ee.convert(e,t);case`flowchart`:return y.convert(e,t);case`sequence`:return E.convert(e,t);case`class`:return D.convert(e,t);default:throw Error(`graphToExcalidraw: unknown graph type "${e.type}, only flowcharts are supported!"`)}},O=e=>{e=j(e);let t=e.replace(/#(\d+);/g,`&#$1;`).replace(/#([a-z]+);/g,`&$1;`),n=document.createElement(`textarea`);return n.innerHTML=t,n.value},k=e=>{let t=e.getAttribute(`transform`)?.match(/translate\(([ \d.-]+),\s*([\d.-]+)\)/),n=0,r=0;return t&&(n=Number(t[1]),r=Number(t[2])),{transformX:n,transformY:r}},A=e=>{let t=e;return t=t.replace(/style.*:\S*#.*;/g,e=>e.substring(0,e.length-1)),t=t.replace(/classDef.*:\S*#.*;/g,e=>e.substring(0,e.length-1)),t=t.replace(/#\w+;/g,e=>{let t=e.substring(1,e.length-1);return/^\+?\d+$/.test(t)?`fl°°${t}¶ß`:`fl°${t}¶ß`}),t},j=function(e){return e.replace(/fl°°/g,`#`).replace(/fl°/g,`&`).replace(/¶ß/g,`;`)},M=(e,t={x:0,y:0})=>{if(e.tagName.toLowerCase()!==`path`)throw Error(`Invalid input: Expected an HTMLElement of tag "path", got ${e.tagName}`);let n=e.getAttribute(`d`);if(!n)throw Error(`Path element does not contain a "d" attribute`);let r=n.split(/(?=[LM])/),i=r[0].substring(1).split(`,`).map(e=>parseFloat(e)),a=r[r.length-1].substring(1).split(`,`).map(e=>parseFloat(e)),o=r.map(e=>{let t=e.substring(1).split(`,`).map(e=>parseFloat(e));return{x:t[0],y:t[1]}}).filter((e,t,n)=>{if(t===0||t===n.length-1)return!0;if(e.x===n[t-1].x&&e.y===n[t-1].y)return!1;if(t===n.length-2&&(n[t-1].x===e.x||n[t-1].y===e.y)){let t=n[n.length-1];return Math.hypot(t.x-e.x,t.y-e.y)>20}return e.x!==n[t-1].x||e.y!==n[t-1].y}).map(e=>({x:e.x+t.x,y:e.y+t.y}));return{startX:i[0]+t.x,startY:i[1]+t.y,endX:a[0]+t.x,endY:a[1]+t.y,reflectionPoints:o}},N=(e,t)=>{let n=e.nodes.map(e=>e.startsWith(`flowchart-`)?e.split(`-`)[1]:e),r=t.querySelector(`[id='${e.id}']`);if(!r)throw Error(`SubGraph element not found`);let i=I(r,t),a=r.getBBox(),o={width:a.width,height:a.height};return e.classes=void 0,e.dir=void 0,{...e,nodeIds:n,...i,...o,text:O(e.title)}},P=(e,t,n)=>{let r=t.querySelector(`[id*="flowchart-${e.id}-"]`);if(!r)return;let i;r.parentElement?.tagName.toLowerCase()===`a`&&(i=r.parentElement.getAttribute(`xlink:href`));let a=I(i?r.parentElement:r,t),o=r.getBBox(),s={width:o.width,height:o.height},c=r.querySelector(`.label-container`)?.getAttribute(`style`),l=r.querySelector(`.label`)?.getAttribute(`style`),u={};c?.split(`;`).forEach(e=>{if(!e)return;let t=e.split(`:`)[0].trim();u[t]=e.split(`:`)[1].trim()});let d={};if(l?.split(`;`).forEach(e=>{if(!e)return;let t=e.split(`:`)[0].trim();d[t]=e.split(`:`)[1].trim()}),e.classes){let t=n[e.classes];t&&(t.styles?.forEach(e=>{let[t,n]=e.split(`:`);u[t.trim()]=n.trim()}),t.textStyles?.forEach(e=>{let[t,n]=e.split(`:`);d[t.trim()]=n.trim()}))}return{id:e.id,labelType:e.labelType,text:O(e.text),type:e.type,link:i||void 0,...a,...s,containerStyle:u,labelStyle:d}},F=(e,t,n)=>{let r=n.querySelector(`[id*="L-${e.start}-${e.end}-${t}"]`);if(!r)throw Error(`Edge element not found`);let i=M(r,I(r,n));return e.length=void 0,{...e,...i,text:O(e.text)}},I=(e,t)=>{if(!e)throw Error(`Element not found`);let n=e.parentElement?.parentElement,r=e.childNodes[0],i={x:0,y:0};if(r){let{transformX:e,transformY:t}=k(r),n=r.getBBox();i={x:Number(r.getAttribute(`x`))||e+n.x||0,y:Number(r.getAttribute(`y`))||t+n.y||0}}let{transformX:a,transformY:o}=k(e),s={x:a+i.x,y:o+i.y};for(;n&&n.id!==t.id;){if(n.classList.value===`root`&&n.hasAttribute(`transform`)){let{transformX:e,transformY:t}=k(n);s.x+=e,s.y+=t}n=n.parentElement}return s},ne=(e,t)=>{e.parse();let n=e.parser.yy,r=n.getVertices(),i=n.getClasses();Object.keys(r).forEach(e=>{r[e]=P(r[e],t,i)});let a=new Map,o=n.getEdges().filter(e=>t.querySelector(`[id*="L-${e.start}-${e.end}"]`)).map(e=>{let n=`${e.start}-${e.end}`,r=a.get(n)||0;return a.set(n,r+1),F(e,r,t)});return{type:`flowchart`,subGraphs:n.getSubGraphs().map(e=>N(e,t)),vertices:r,edges:o}},re=(e,t)=>{let n={};t?.label&&(n.label={text:O(t.label),fontSize:16});let r=e.tagName;if(r===`line`)n.startX=Number(e.getAttribute(`x1`)),n.startY=Number(e.getAttribute(`y1`)),n.endX=Number(e.getAttribute(`x2`)),n.endY=Number(e.getAttribute(`y2`));else if(r===`path`){let t=e.getAttribute(`d`);if(!t)throw Error(`Path element does not contain a "d" attribute`);let r=t.split(/(?=[LC])/),i=r[0].substring(1).split(`,`).map(e=>parseFloat(e)),a=[];r.forEach(e=>{let t=e.substring(1).trim().split(` `).map(e=>{let[t,n]=e.split(`,`);return[parseFloat(t)-i[0],parseFloat(n)-i[1]]});a.push(...t)});let o=a[a.length-1];n.startX=i[0],n.startY=i[1],n.endX=o[0],n.endY=o[1],n.points=a}return t?.label&&(n.startY-=10,n.endY-=10),n.strokeColor=e.getAttribute(`stroke`),n.strokeWidth=Number(e.getAttribute(`stroke-width`)),n.type=`arrow`,n.strokeStyle=t?.strokeStyle||`solid`,n.startArrowhead=t?.startArrowhead||null,n.endArrowhead=t?.endArrowhead||null,n},L=(e,t,n,r,i)=>{let a={};return a.type=`arrow`,a.startX=e,a.startY=t,a.endX=n,a.endY=r,Object.assign(a,{...i}),a},R=(e,t,n,r)=>({type:`text`,x:e,y:t,text:n,width:r?.width||20,height:r?.height||20,fontSize:r?.fontSize||20,id:r?.id,groupId:r?.groupId,metadata:r?.metadata}),z=(e,t,n)=>{let r={},i=Number(e.getAttribute(`x`)),a=Number(e.getAttribute(`y`));r.type=`text`,r.text=O(t),n?.id&&(r.id=n.id),n?.groupId&&(r.groupId=n.groupId);let o=e.getBBox();return r.width=o.width,r.height=o.height,r.x=i-o.width/2,r.y=a,r.fontSize=parseInt(getComputedStyle(e).fontSize),r},B=(e,t,n={})=>{let r={};r.type=t;let{label:i,subtype:a,id:o,groupId:s}=n;r.id=o,s&&(r.groupId=s),i&&(r.label={text:O(i.text),fontSize:16,verticalAlign:i?.verticalAlign});let c=e.getBBox();switch(r.x=c.x,r.y=c.y,r.width=c.width,r.height=c.height,r.subtype=a,a){case`highlight`:let t=e.getAttribute(`fill`);t&&(r.bgColor=t);break;case`note`:r.strokeStyle=`dashed`;break}return r},V=(e,t,n,r,i,a)=>{let o={};return o.startX=t,o.startY=n,o.endX=r,a?.groupId&&(o.groupId=a.groupId),a?.id&&(o.id=a.id),o.endY=i,o.strokeColor=e.getAttribute(`stroke`),o.strokeWidth=Number(e.getAttribute(`stroke-width`)),o.type=`line`,o},H={0:`SOLID`,1:`DOTTED`,3:`SOLID_CROSS`,4:`DOTTED_CROSS`,5:`SOLID_OPEN`,6:`DOTTED_OPEN`,24:`SOLID_POINT`,25:`DOTTED_POINT`},U={SOLID:0,DOTTED:1,NOTE:2,SOLID_CROSS:3,DOTTED_CROSS:4,SOLID_OPEN:5,DOTTED_OPEN:6,LOOP_START:10,LOOP_END:11,ALT_START:12,ALT_ELSE:13,ALT_END:14,OPT_START:15,OPT_END:16,ACTIVE_START:17,ACTIVE_END:18,PAR_START:19,PAR_AND:20,PAR_END:21,RECT_START:22,RECT_END:23,SOLID_POINT:24,DOTTED_POINT:25,AUTONUMBER:26,CRITICAL_START:27,CRITICAL_OPTION:28,CRITICAL_END:29,BREAK_START:30,BREAK_END:31,PAR_OVER_START:32},W=e=>{let t;switch(e){case U.SOLID:case U.SOLID_CROSS:case U.SOLID_OPEN:case U.SOLID_POINT:t=`solid`;break;case U.DOTTED:case U.DOTTED_CROSS:case U.DOTTED_OPEN:case U.DOTTED_POINT:t=`dotted`;break;default:t=`solid`;break}return t},G=(e,t)=>{if(e.nextElementSibling?.classList.contains(`sequenceNumber`)){let n=e.nextElementSibling?.textContent;if(!n)throw Error(`sequence number not present`);let r={type:`rectangle`,x:t.startX-10,y:t.startY-15,label:{text:n,fontSize:14},bgColor:`#e9ecef`,height:30,subtype:`sequence`};Object.assign(t,{sequenceNumber:r})}},K=(e,n,r)=>{if(!e)throw`root node not found`;let i=b(),a=Array.from(e.children),o=[];return a.forEach((e,a)=>{let s=`${r?.id}-${a}`,c;switch(e.tagName){case`line`:c=V(e,Number(e.getAttribute(`x1`)),Number(e.getAttribute(`y1`)),Number(e.getAttribute(`x2`)),Number(e.getAttribute(`y2`)),{groupId:i,id:s});break;case`text`:c=z(e,n,{groupId:i,id:s});break;case`circle`:c=B(e,`ellipse`,{label:e.textContent?{text:e.textContent}:void 0,groupId:i,id:s});default:c=B(e,t[e.tagName],{label:e.textContent?{text:e.textContent}:void 0,groupId:i,id:s})}o.push(c)}),o},q=(e,t)=>{let n=Array.from(t.querySelectorAll(`.actor-top`)),r=Array.from(t.querySelectorAll(`.actor-bottom`)),i=[],a=[];return Object.values(e).forEach((e,t)=>{let o=n.find(t=>t.getAttribute(`name`)===e.name),s=r.find(t=>t.getAttribute(`name`)===e.name);if(!o||!s)throw`root not found`;let c=e.description;if(e.type===`participant`){let t=B(o,`rectangle`,{id:`${e.name}-top`,label:{text:c},subtype:`actor`});if(!t)throw`Top Node element not found!`;i.push([t]);let n=B(s,`rectangle`,{id:`${e.name}-bottom`,label:{text:c},subtype:`actor`});i.push([n]);let r=o?.parentElement?.previousElementSibling;if(r?.tagName!==`line`)throw`Line not found`;let l=Number(r.getAttribute(`x1`));if(!t.height)throw`Top node element height is null`;let u=t.y+t.height,d=n.y,f=V(r,l,u,Number(r.getAttribute(`x2`)),d);a.push(f)}else if(e.type===`actor`){let t=K(o,c,{id:`${e.name}-top`});i.push(t);let n=K(s,c,{id:`${e.name}-bottom`});i.push(n);let r=o.previousElementSibling;if(r?.tagName!==`line`)throw`Line not found`;let l=Number(r.getAttribute(`x1`)),u=Number(r.getAttribute(`y1`)),d=Number(r.getAttribute(`x2`)),f=n.find(e=>e.type===`ellipse`);if(f){let e=f.y,t=V(r,l,u,d,e);a.push(t)}}}),{nodes:i,lines:a}},J=(e,t)=>{let n=[],r=Array.from(t.querySelectorAll(`[class*="messageLine"]`)),i=Object.keys(H),a=e.filter(e=>i.includes(e.type.toString()));return r.forEach((e,t)=>{let r=a[t],i=H[r.type],o=re(e,{label:r?.message,strokeStyle:W(r.type),endArrowhead:i===`SOLID_OPEN`||i===`DOTTED_OPEN`?null:`arrow`});G(e,o),n.push(o)}),n},Y=(e,t)=>{let n=Array.from(t.querySelectorAll(`.note`)).map(e=>e.parentElement),r=e.filter(e=>e.type===U.NOTE),i=[];return n.forEach((e,t)=>{if(!e)return;let n=e.firstChild,a=r[t].message,o=B(n,`rectangle`,{label:{text:a},subtype:`note`});i.push(o)}),i},ie=e=>{let t=Array.from(e.querySelectorAll(`[class*=activation]`)),n=[];return t.forEach(e=>{let t=B(e,`rectangle`,{label:{text:``},subtype:`activation`});n.push(t)}),n},ae=(e,t)=>{let n=Array.from(t.querySelectorAll(`.loopLine`)),r=[],i=[],a=[];n.forEach(e=>{let t=V(e,Number(e.getAttribute(`x1`)),Number(e.getAttribute(`y1`)),Number(e.getAttribute(`x2`)),Number(e.getAttribute(`y2`)));t.strokeStyle=`dotted`,t.strokeColor=`#adb5bd`,t.strokeWidth=2,r.push(t)});let o=Array.from(t.querySelectorAll(`.loopText`)),s=e.filter(e=>e.type===U.CRITICAL_START).map(e=>e.message);o.forEach(e=>{let t=e.textContent||``,n=z(e,t),r=t.match(/\[(.*?)\]/)?.[1]||``;s.includes(r)&&(n.x+=16),i.push(n)});let c=Array.from(t?.querySelectorAll(`.labelBox`)),l=Array.from(t?.querySelectorAll(`.labelText`));return c.forEach((e,t)=>{let n=B(e,`rectangle`,{label:{text:l[t]?.textContent||``}});n.strokeColor=`#adb5bd`,n.bgColor=`#e9ecef`,n.width=void 0,a.push(n)}),{lines:r,texts:i,nodes:a}},oe=e=>{let t=Array.from(e.querySelectorAll(`.rect`)).filter(e=>e.parentElement?.tagName!==`g`),n=[];return t.forEach(e=>{let t=B(e,`rectangle`,{label:{text:``},subtype:`highlight`});n.push(t)}),n},se=(e,t)=>{e.parse();let n=e.parser.yy,r=[],i=n.getBoxes(),a=oe(t),{nodes:o,lines:s}=q(n.getActors(),t),c=n.getMessages(),l=J(c,t),u=Y(c,t),d=ie(t),f=ae(c,t);return r.push(a),r.push(...o),r.push(u),r.push(d),{type:`sequence`,lines:s,arrows:l,nodes:r,loops:f,groups:i}},X={AGGREGATION:0,EXTENSION:1,COMPOSITION:2,DEPENDENCY:3,LOLLIPOP:4},Z={LINE:0,DOTTED_LINE:1},ce=e=>{let t;switch(e){case Z.LINE:t=`solid`;break;case Z.DOTTED_LINE:t=`dotted`;break;default:t=`solid`}return t},Q=e=>{let t;switch(e){case X.AGGREGATION:t=`diamond_outline`;break;case X.COMPOSITION:t=`diamond`;break;case X.EXTENSION:t=`triangle_outline`;break;case`none`:t=null;break;case X.DEPENDENCY:default:t=`arrow`;break}return t},le=(e,t)=>{let n=[],r=[],i=[];return Object.values(e).forEach(e=>{let{domId:a,id:o}=e,s=b(),c=t.querySelector(`[data-id=${o}]`);if(!c)throw Error(`DOM Node with id ${a} not found`);let{transformX:l,transformY:u}=k(c),d=B(c.firstChild,`rectangle`,{id:o,groupId:s});d.x+=l,d.y+=u,d.metadata={classId:o},n.push(d),Array.from(c.querySelectorAll(`.divider`)).forEach(e=>{let t=V(e,Number(e.getAttribute(`x1`)),Number(e.getAttribute(`y1`)),Number(e.getAttribute(`x2`)),Number(e.getAttribute(`y2`)),{groupId:s,id:b()});t.startX+=l,t.startY+=u,t.endX+=l,t.endY+=u,t.metadata={classId:o},r.push(t)});let f=c.querySelector(`.label`)?.children;if(!f)throw`label nodes not found`;Array.from(f).forEach(e=>{let t=e.textContent;if(!t)return;let n=b(),{transformX:r,transformY:a}=k(e),c=e.getBBox(),d=R(l+r,u+a+10,t,{width:c.width,height:c.height,id:n,groupId:s,metadata:{classId:o}});i.push(d)})}),{nodes:n,lines:r,text:i}},ue=(e,t)=>{let n=[`triangle_outline`,`diamond`,`diamond_outline`],r=t.startArrowhead&&n.includes(t.startArrowhead),i=t.endArrowhead&&n.includes(t.endArrowhead);return!i&&!r?t:(r&&(e===`LR`?t.startX-=16:e===`RL`?t.startX+=16:e===`TB`?t.startY-=16:e===`BT`&&(t.startY+=16)),i&&(e===`LR`?t.endX+=16:e===`RL`?t.endX-=16:e===`TB`?t.endY+=16:e===`BT`&&(t.endY-=16)),t)},de=(e,t,n,r)=>{let i=n.querySelector(`.edgePaths`)?.children;if(!i)throw Error(`No Edges found!`);let a=[],o=[];return e.forEach((e,n)=>{let{id1:s,id2:c,relation:l}=e,u=t.find(e=>e.id===s),d=t.find(e=>e.id===c),f=ce(l.lineType),p=Q(l.type1),m=Q(l.type2),h=M(i[n]),g=ue(r,L(h.startX,h.startY,h.endX,h.endY,{strokeStyle:f,startArrowhead:p,endArrowhead:m,label:e.title?{text:e.title}:void 0,start:{type:`rectangle`,id:u.id},end:{type:`rectangle`,id:d.id}}));a.push(g);let{relationTitle1:_,relationTitle2:v}=e,y,b;if(_&&_!==`none`){switch(r){case`TB`:y=g.startX-20,g.endX<g.startX&&(y-=15),b=g.startY+15;break;case`BT`:y=g.startX+20,g.endX>g.startX&&(y+=15),b=g.startY-15;break;case`LR`:y=g.startX+20,b=g.startY+15,g.endY>g.startY&&(b+=15);break;case`RL`:y=g.startX-20,b=g.startY-15,g.startY>g.endY&&(b-=15);break;default:y=g.startX-20,b=g.startY+15}let e=R(y,b,_,{fontSize:16});o.push(e)}if(v&&v!==`none`){switch(r){case`TB`:y=g.endX+20,g.endX<g.startX&&(y+=15),b=g.endY-15;break;case`BT`:y=g.endX-20,g.endX>g.startX&&(y-=15),b=g.endY+15;break;case`LR`:y=g.endX-20,b=g.endY-15,g.endY>g.startY&&(b-=15);break;case`RL`:y=g.endX+20,b=g.endY+15,g.startY>g.endY&&(b+=15);break;default:y=g.endX+20,b=g.endY-15}let e=R(y,b,v,{fontSize:16});o.push(e)}}),{arrows:a,text:o}},fe=(e,t,n)=>{let r=[],i=[];return e.forEach(e=>{let{id:a,text:o,class:s}=e,c=t.querySelector(`#${a}`);if(!c)throw Error(`Node with id ${a} not found!`);let{transformX:l,transformY:u}=k(c),d=c.firstChild,f=B(d,`rectangle`,{id:a,subtype:`note`,label:{text:o}});if(Object.assign(f,{x:f.x+l,y:f.y+u}),r.push(f),s){let e=n.find(e=>e.id===s);if(!e)throw Error(`class node with id ${s} not found!`);let t=f.x+(f.width||0)/2,r=f.y+(f.height||0),a=t,o=e.y,c=L(t,r,a,o,{strokeStyle:`dotted`,startArrowhead:null,endArrowhead:null,start:{id:f.id,type:`rectangle`},end:{id:e.id,type:`rectangle`}});i.push(c)}}),{notes:r,connectors:i}},pe=(e,t)=>{e.parse();let n=e.parser.yy,r=n.getDirection(),i=[],a=[],o=[],s=[],c=n.getNamespaces(),l=n.getClasses();if(Object.keys(l).length){let e=le(l,t);i.push(e.nodes),a.push(...e.lines),o.push(...e.text),s.push(...e.nodes)}let{arrows:u,text:d}=de(n.getRelations(),s,t,r),{notes:f,connectors:p}=fe(n.getNotes(),t,s);return i.push(f),u.push(...p),o.push(...d),{type:`class`,nodes:i,lines:a,arrows:u,text:o,namespaces:c}},$=e=>{let t=e.querySelector(`svg`);if(!t)throw Error(`SVG element not found`);let n=t.getBoundingClientRect(),r=n.width,i=n.height;t.setAttribute(`width`,`${r}`),t.setAttribute(`height`,`${i}`);let a=unescape(encodeURIComponent(t.outerHTML));return{type:`graphImage`,mimeType:`image/svg+xml`,dataURL:`data:image/svg+xml;base64,${btoa(a)}`,width:r,height:i}},me=async(t,r=n)=>{e.initialize({...n,...r});let i=await e.mermaidAPI.getDiagramFromText(A(t)),{svg:a}=await e.render(`mermaid-to-excalidraw`,t),o=document.createElement(`div`);o.setAttribute(`style`,`opacity: 0; position: relative; z-index: -1;`),o.innerHTML=a,o.id=`mermaid-diagram`,document.body.appendChild(o);let s;switch(i.type){case`flowchart-v2`:s=ne(i,o);break;case`sequence`:s=se(i,o);break;case`classDiagram`:s=pe(i,o);break;default:s=$(o)}return o.remove(),s};async function he(t){return e.parse(t,{suppressErrors:!0})}const ge=async(e,t)=>{let n=t||{},r=parseInt(n.themeVariables?.fontSize??``)||20;return te(await me(e,{...n,themeVariables:{...n.themeVariables,fontSize:`${r*1.25}px`}}),{fontSize:r})},_e=e=>({type:`excalidraw`,version:2,source:`https://excalidraw.com`,elements:a(e.elements),appState:{gridSize:20,gridStep:5,gridModeEnabled:!1,viewBackgroundColor:`#ffffff`,lockedMultiSelections:{}},files:e.files||{}});export{ge as parseMermaidToExcalidraw,_e as serializeToExcalidraw,he as validateMermaid};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brrock/excalidraw-mermaid",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A parser to convert Mermaid diagrams to Excalidraw format",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -37,9 +37,6 @@
|
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"mermaid": "^10.9.0 || ^11.0.0"
|
|
39
39
|
},
|
|
40
|
-
"dependencies": {
|
|
41
|
-
"nanoid": "^5.1.6"
|
|
42
|
-
},
|
|
43
40
|
"devDependencies": {
|
|
44
41
|
"@excalidraw/eslint-config": "^1.0.3",
|
|
45
42
|
"@typescript-eslint/eslint-plugin": "^8.56.0",
|
|
@@ -50,6 +47,7 @@
|
|
|
50
47
|
"prettier": "^2.8.8",
|
|
51
48
|
"tsdown": "^0.20.3",
|
|
52
49
|
"typescript": "^5.9.3",
|
|
53
|
-
"vitest": "^3.0.0"
|
|
50
|
+
"vitest": "^3.0.0",
|
|
51
|
+
"@types/bun": "latest"
|
|
54
52
|
}
|
|
55
53
|
}
|