UNPKG

11.4 kBJavaScriptView Raw
1import { D as DEFAULT_STATE_TYPE, a as DIVIDER_TYPE, S as STMT_RELATION, b as STMT_STATE, c as DEFAULT_NESTED_DOC_DIR, p as parser, d as db, s as styles } from "./styles-2797ae0f.js";
2import * as graphlib from "dagre-d3-es/src/graphlib/index.js";
3import { select } from "d3";
4import { l as log, c as getConfig, u as utils, i as configureSvgSize, e as common } from "./mermaid-a953d906.js";
5import { r as render } from "./index-05087a90.js";
6import "ts-dedent";
7import "dayjs/esm/index.js";
8import "@braintree/sanitize-url";
9import "dompurify";
10import "khroma";
11import "lodash-es/memoize.js";
12import "stylis";
13import "lodash-es/isEmpty.js";
14import "dagre-d3-es/src/dagre/index.js";
15import "dagre-d3-es/src/graphlib/json.js";
16import "./edges-97052da4.js";
17import "./createText-2f679d62.js";
18import "mdast-util-from-markdown";
19import "./svgDraw-6750006d.js";
20const SHAPE_STATE = "rect";
21const SHAPE_STATE_WITH_DESC = "rectWithTitle";
22const SHAPE_START = "start";
23const SHAPE_END = "end";
24const SHAPE_DIVIDER = "divider";
25const SHAPE_GROUP = "roundedWithTitle";
26const SHAPE_NOTE = "note";
27const SHAPE_NOTEGROUP = "noteGroup";
28const CSS_DIAGRAM = "statediagram";
29const CSS_STATE = "state";
30const CSS_DIAGRAM_STATE = `${CSS_DIAGRAM}-${CSS_STATE}`;
31const CSS_EDGE = "transition";
32const CSS_NOTE = "note";
33const CSS_NOTE_EDGE = "note-edge";
34const CSS_EDGE_NOTE_EDGE = `${CSS_EDGE} ${CSS_NOTE_EDGE}`;
35const CSS_DIAGRAM_NOTE = `${CSS_DIAGRAM}-${CSS_NOTE}`;
36const CSS_CLUSTER = "cluster";
37const CSS_DIAGRAM_CLUSTER = `${CSS_DIAGRAM}-${CSS_CLUSTER}`;
38const CSS_CLUSTER_ALT = "cluster-alt";
39const CSS_DIAGRAM_CLUSTER_ALT = `${CSS_DIAGRAM}-${CSS_CLUSTER_ALT}`;
40const PARENT = "parent";
41const NOTE = "note";
42const DOMID_STATE = "state";
43const DOMID_TYPE_SPACER = "----";
44const NOTE_ID = `${DOMID_TYPE_SPACER}${NOTE}`;
45const PARENT_ID = `${DOMID_TYPE_SPACER}${PARENT}`;
46const G_EDGE_STYLE = "fill:none";
47const G_EDGE_ARROWHEADSTYLE = "fill: #333";
48const G_EDGE_LABELPOS = "c";
49const G_EDGE_LABELTYPE = "text";
50const G_EDGE_THICKNESS = "normal";
51let nodeDb = {};
52let graphItemCount = 0;
53const setConf = function(cnf) {
54 const keys = Object.keys(cnf);
55 for (const key of keys) {
56 cnf[key];
57 }
58};
59const getClasses = function(text, diagramObj) {
60 log.trace("Extracting classes");
61 diagramObj.db.clear();
62 try {
63 diagramObj.parser.parse(text);
64 diagramObj.db.extract(diagramObj.db.getRootDocV2());
65 return diagramObj.db.getClasses();
66 } catch (e) {
67 return e;
68 }
69};
70function getClassesFromDbInfo(dbInfoItem) {
71 if (dbInfoItem === void 0 || dbInfoItem === null) {
72 return "";
73 } else {
74 if (dbInfoItem.classes) {
75 return dbInfoItem.classes.join(" ");
76 } else {
77 return "";
78 }
79 }
80}
81function stateDomId(itemId = "", counter = 0, type = "", typeSpacer = DOMID_TYPE_SPACER) {
82 const typeStr = type !== null && type.length > 0 ? `${typeSpacer}${type}` : "";
83 return `${DOMID_STATE}-${itemId}${typeStr}-${counter}`;
84}
85const setupNode = (g, parent, parsedItem, diagramStates, diagramDb, altFlag) => {
86 const itemId = parsedItem.id;
87 const classStr = getClassesFromDbInfo(diagramStates[itemId]);
88 if (itemId !== "root") {
89 let shape = SHAPE_STATE;
90 if (parsedItem.start === true) {
91 shape = SHAPE_START;
92 }
93 if (parsedItem.start === false) {
94 shape = SHAPE_END;
95 }
96 if (parsedItem.type !== DEFAULT_STATE_TYPE) {
97 shape = parsedItem.type;
98 }
99 if (!nodeDb[itemId]) {
100 nodeDb[itemId] = {
101 id: itemId,
102 shape,
103 description: common.sanitizeText(itemId, getConfig()),
104 classes: `${classStr} ${CSS_DIAGRAM_STATE}`
105 };
106 }
107 const newNode = nodeDb[itemId];
108 if (parsedItem.description) {
109 if (Array.isArray(newNode.description)) {
110 newNode.shape = SHAPE_STATE_WITH_DESC;
111 newNode.description.push(parsedItem.description);
112 } else {
113 if (newNode.description.length > 0) {
114 newNode.shape = SHAPE_STATE_WITH_DESC;
115 if (newNode.description === itemId) {
116 newNode.description = [parsedItem.description];
117 } else {
118 newNode.description = [newNode.description, parsedItem.description];
119 }
120 } else {
121 newNode.shape = SHAPE_STATE;
122 newNode.description = parsedItem.description;
123 }
124 }
125 newNode.description = common.sanitizeTextOrArray(newNode.description, getConfig());
126 }
127 if (newNode.description.length === 1 && newNode.shape === SHAPE_STATE_WITH_DESC) {
128 newNode.shape = SHAPE_STATE;
129 }
130 if (!newNode.type && parsedItem.doc) {
131 log.info("Setting cluster for ", itemId, getDir(parsedItem));
132 newNode.type = "group";
133 newNode.dir = getDir(parsedItem);
134 newNode.shape = parsedItem.type === DIVIDER_TYPE ? SHAPE_DIVIDER : SHAPE_GROUP;
135 newNode.classes = newNode.classes + " " + CSS_DIAGRAM_CLUSTER + " " + (altFlag ? CSS_DIAGRAM_CLUSTER_ALT : "");
136 }
137 const nodeData = {
138 labelStyle: "",
139 shape: newNode.shape,
140 labelText: newNode.description,
141 // typeof newNode.description === 'object'
142 // ? newNode.description[0]
143 // : newNode.description,
144 classes: newNode.classes,
145 style: "",
146 //styles.style,
147 id: itemId,
148 dir: newNode.dir,
149 domId: stateDomId(itemId, graphItemCount),
150 type: newNode.type,
151 padding: 15
152 //getConfig().flowchart.padding
153 };
154 nodeData.centerLabel = true;
155 if (parsedItem.note) {
156 const noteData = {
157 labelStyle: "",
158 shape: SHAPE_NOTE,
159 labelText: parsedItem.note.text,
160 classes: CSS_DIAGRAM_NOTE,
161 // useHtmlLabels: false,
162 style: "",
163 // styles.style,
164 id: itemId + NOTE_ID + "-" + graphItemCount,
165 domId: stateDomId(itemId, graphItemCount, NOTE),
166 type: newNode.type,
167 padding: 15
168 //getConfig().flowchart.padding
169 };
170 const groupData = {
171 labelStyle: "",
172 shape: SHAPE_NOTEGROUP,
173 labelText: parsedItem.note.text,
174 classes: newNode.classes,
175 style: "",
176 // styles.style,
177 id: itemId + PARENT_ID,
178 domId: stateDomId(itemId, graphItemCount, PARENT),
179 type: "group",
180 padding: 0
181 //getConfig().flowchart.padding
182 };
183 graphItemCount++;
184 const parentNodeId = itemId + PARENT_ID;
185 g.setNode(parentNodeId, groupData);
186 g.setNode(noteData.id, noteData);
187 g.setNode(itemId, nodeData);
188 g.setParent(itemId, parentNodeId);
189 g.setParent(noteData.id, parentNodeId);
190 let from = itemId;
191 let to = noteData.id;
192 if (parsedItem.note.position === "left of") {
193 from = noteData.id;
194 to = itemId;
195 }
196 g.setEdge(from, to, {
197 arrowhead: "none",
198 arrowType: "",
199 style: G_EDGE_STYLE,
200 labelStyle: "",
201 classes: CSS_EDGE_NOTE_EDGE,
202 arrowheadStyle: G_EDGE_ARROWHEADSTYLE,
203 labelpos: G_EDGE_LABELPOS,
204 labelType: G_EDGE_LABELTYPE,
205 thickness: G_EDGE_THICKNESS
206 });
207 } else {
208 g.setNode(itemId, nodeData);
209 }
210 }
211 if (parent && parent.id !== "root") {
212 log.trace("Setting node ", itemId, " to be child of its parent ", parent.id);
213 g.setParent(itemId, parent.id);
214 }
215 if (parsedItem.doc) {
216 log.trace("Adding nodes children ");
217 setupDoc(g, parsedItem, parsedItem.doc, diagramStates, diagramDb, !altFlag);
218 }
219};
220const setupDoc = (g, parentParsedItem, doc, diagramStates, diagramDb, altFlag) => {
221 log.trace("items", doc);
222 doc.forEach((item) => {
223 switch (item.stmt) {
224 case STMT_STATE:
225 setupNode(g, parentParsedItem, item, diagramStates, diagramDb, altFlag);
226 break;
227 case DEFAULT_STATE_TYPE:
228 setupNode(g, parentParsedItem, item, diagramStates, diagramDb, altFlag);
229 break;
230 case STMT_RELATION:
231 {
232 setupNode(g, parentParsedItem, item.state1, diagramStates, diagramDb, altFlag);
233 setupNode(g, parentParsedItem, item.state2, diagramStates, diagramDb, altFlag);
234 const edgeData = {
235 id: "edge" + graphItemCount,
236 arrowhead: "normal",
237 arrowTypeEnd: "arrow_barb",
238 style: G_EDGE_STYLE,
239 labelStyle: "",
240 label: common.sanitizeText(item.description, getConfig()),
241 arrowheadStyle: G_EDGE_ARROWHEADSTYLE,
242 labelpos: G_EDGE_LABELPOS,
243 labelType: G_EDGE_LABELTYPE,
244 thickness: G_EDGE_THICKNESS,
245 classes: CSS_EDGE
246 };
247 g.setEdge(item.state1.id, item.state2.id, edgeData, graphItemCount);
248 graphItemCount++;
249 }
250 break;
251 }
252 });
253};
254const getDir = (parsedItem, defaultDir = DEFAULT_NESTED_DOC_DIR) => {
255 let dir = defaultDir;
256 if (parsedItem.doc) {
257 for (let i = 0; i < parsedItem.doc.length; i++) {
258 const parsedItemDoc = parsedItem.doc[i];
259 if (parsedItemDoc.stmt === "dir") {
260 dir = parsedItemDoc.value;
261 }
262 }
263 }
264 return dir;
265};
266const draw = async function(text, id, _version, diag) {
267 log.info("Drawing state diagram (v2)", id);
268 nodeDb = {};
269 diag.db.getDirection();
270 const { securityLevel, state: conf } = getConfig();
271 const nodeSpacing = conf.nodeSpacing || 50;
272 const rankSpacing = conf.rankSpacing || 50;
273 log.info(diag.db.getRootDocV2());
274 diag.db.extract(diag.db.getRootDocV2());
275 log.info(diag.db.getRootDocV2());
276 const diagramStates = diag.db.getStates();
277 const g = new graphlib.Graph({
278 multigraph: true,
279 compound: true
280 }).setGraph({
281 rankdir: getDir(diag.db.getRootDocV2()),
282 nodesep: nodeSpacing,
283 ranksep: rankSpacing,
284 marginx: 8,
285 marginy: 8
286 }).setDefaultEdgeLabel(function() {
287 return {};
288 });
289 setupNode(g, void 0, diag.db.getRootDocV2(), diagramStates, diag.db, true);
290 let sandboxElement;
291 if (securityLevel === "sandbox") {
292 sandboxElement = select("#i" + id);
293 }
294 const root = securityLevel === "sandbox" ? select(sandboxElement.nodes()[0].contentDocument.body) : select("body");
295 const svg = root.select(`[id="${id}"]`);
296 const element = root.select("#" + id + " g");
297 await render(element, g, ["barb"], CSS_DIAGRAM, id);
298 const padding = 8;
299 utils.insertTitle(svg, "statediagramTitleText", conf.titleTopMargin, diag.db.getDiagramTitle());
300 const bounds = svg.node().getBBox();
301 const width = bounds.width + padding * 2;
302 const height = bounds.height + padding * 2;
303 svg.attr("class", CSS_DIAGRAM);
304 const svgBounds = svg.node().getBBox();
305 configureSvgSize(svg, height, width, conf.useMaxWidth);
306 const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`;
307 log.debug(`viewBox ${vBox}`);
308 svg.attr("viewBox", vBox);
309 const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label');
310 for (const label of labels) {
311 const dim = label.getBBox();
312 const rect = document.createElementNS("http://www.w3.org/2000/svg", SHAPE_STATE);
313 rect.setAttribute("rx", 0);
314 rect.setAttribute("ry", 0);
315 rect.setAttribute("width", dim.width);
316 rect.setAttribute("height", dim.height);
317 label.insertBefore(rect, label.firstChild);
318 }
319};
320const renderer = {
321 setConf,
322 getClasses,
323 draw
324};
325const diagram = {
326 parser,
327 db,
328 renderer,
329 styles,
330 init: (cnf) => {
331 if (!cnf.state) {
332 cnf.state = {};
333 }
334 cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
335 db.clear();
336 }
337};
338export {
339 diagram
340};