mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-23 17:29:54 +02:00
convert flowDb to class.
This commit is contained in:
@@ -1,9 +1,11 @@
|
|||||||
import flowDb from './flowDb.js';
|
import { FlowDb } from './flowDb.js';
|
||||||
import type { FlowSubGraph } from './types.js';
|
import type { FlowSubGraph } from './types.js';
|
||||||
|
|
||||||
describe('flow db subgraphs', () => {
|
describe('flow db subgraphs', () => {
|
||||||
|
let flowDb: FlowDb;
|
||||||
let subgraphs: FlowSubGraph[];
|
let subgraphs: FlowSubGraph[];
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
flowDb = new FlowDb();
|
||||||
subgraphs = [
|
subgraphs = [
|
||||||
{ nodes: ['a', 'b', 'c', 'e'] },
|
{ nodes: ['a', 'b', 'c', 'e'] },
|
||||||
{ nodes: ['f', 'g', 'h'] },
|
{ nodes: ['f', 'g', 'h'] },
|
||||||
@@ -44,8 +46,9 @@ describe('flow db subgraphs', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('flow db addClass', () => {
|
describe('flow db addClass', () => {
|
||||||
|
let flowDb: FlowDb;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
flowDb.clear();
|
flowDb = new FlowDb();
|
||||||
});
|
});
|
||||||
it('should detect many classes', () => {
|
it('should detect many classes', () => {
|
||||||
flowDb.addClass('a,b', ['stroke-width: 8px']);
|
flowDb.addClass('a,b', ['stroke-width: 8px']);
|
||||||
|
@@ -27,32 +27,43 @@ import type {
|
|||||||
import type { NodeMetaData } from '../../types.js';
|
import type { NodeMetaData } from '../../types.js';
|
||||||
|
|
||||||
const MERMAID_DOM_ID_PREFIX = 'flowchart-';
|
const MERMAID_DOM_ID_PREFIX = 'flowchart-';
|
||||||
let vertexCounter = 0;
|
|
||||||
let config = getConfig();
|
|
||||||
let vertices = new Map<string, FlowVertex>();
|
|
||||||
let edges: FlowEdge[] & { defaultInterpolate?: string; defaultStyle?: string[] } = [];
|
|
||||||
let classes = new Map<string, FlowClass>();
|
|
||||||
let subGraphs: FlowSubGraph[] = [];
|
|
||||||
let subGraphLookup = new Map<string, FlowSubGraph>();
|
|
||||||
let tooltips = new Map<string, string>();
|
|
||||||
let subCount = 0;
|
|
||||||
let firstGraphFlag = true;
|
|
||||||
let direction: string;
|
|
||||||
|
|
||||||
let version: string; // As in graph
|
export class FlowDb {
|
||||||
|
private vertexCounter = 0;
|
||||||
|
private config = getConfig();
|
||||||
|
private vertices = new Map<string, FlowVertex>();
|
||||||
|
private edges: FlowEdge[] & { defaultInterpolate?: string; defaultStyle?: string[] } = [];
|
||||||
|
private classes = new Map<string, FlowClass>();
|
||||||
|
private subGraphs: FlowSubGraph[] = [];
|
||||||
|
private subGraphLookup = new Map<string, FlowSubGraph>();
|
||||||
|
private tooltips = new Map<string, string>();
|
||||||
|
private subCount = 0;
|
||||||
|
private firstGraphFlag = true;
|
||||||
|
private direction: string | undefined;
|
||||||
|
|
||||||
|
private version: string | undefined; // As in graph
|
||||||
|
|
||||||
|
private secCount = -1;
|
||||||
|
private posCrossRef: number[] = [];
|
||||||
|
|
||||||
// Functions to be run after graph rendering
|
// Functions to be run after graph rendering
|
||||||
let funs: ((element: Element) => void)[] = []; // cspell:ignore funs
|
private funs: ((element: Element) => void)[] = []; // cspell:ignore funs
|
||||||
|
|
||||||
const sanitizeText = (txt: string) => common.sanitizeText(txt, config);
|
constructor() {
|
||||||
|
this.funs.push(this.setupToolTips);
|
||||||
|
this.clear();
|
||||||
|
this.setGen('gen-2');
|
||||||
|
}
|
||||||
|
|
||||||
|
private sanitizeText = (txt: string) => common.sanitizeText(txt, this.config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to lookup domId from id in the graph definition.
|
* Function to lookup domId from id in the graph definition.
|
||||||
*
|
*
|
||||||
* @param id - id of the node
|
* @param id - id of the node
|
||||||
*/
|
*/
|
||||||
export const lookUpDomId = function (id: string) {
|
public lookUpDomId = (id: string) => {
|
||||||
for (const vertex of vertices.values()) {
|
for (const vertex of this.vertices.values()) {
|
||||||
if (vertex.id === id) {
|
if (vertex.id === id) {
|
||||||
return vertex.domId;
|
return vertex.domId;
|
||||||
}
|
}
|
||||||
@@ -63,7 +74,7 @@ export const lookUpDomId = function (id: string) {
|
|||||||
/**
|
/**
|
||||||
* Function called by parser when a node definition has been found
|
* Function called by parser when a node definition has been found
|
||||||
*/
|
*/
|
||||||
export const addVertex = function (
|
public addVertex = (
|
||||||
id: string,
|
id: string,
|
||||||
textObj: FlowText,
|
textObj: FlowText,
|
||||||
type: FlowVertexTypeParam,
|
type: FlowVertexTypeParam,
|
||||||
@@ -72,29 +83,29 @@ export const addVertex = function (
|
|||||||
dir: string,
|
dir: string,
|
||||||
props = {},
|
props = {},
|
||||||
shapeData: any
|
shapeData: any
|
||||||
) {
|
) => {
|
||||||
// console.log('addVertex', id, shapeData);
|
// console.log('addVertex', id, shapeData);
|
||||||
if (!id || id.trim().length === 0) {
|
if (!id || id.trim().length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let txt;
|
let txt;
|
||||||
|
|
||||||
let vertex = vertices.get(id);
|
let vertex = this.vertices.get(id);
|
||||||
if (vertex === undefined) {
|
if (vertex === undefined) {
|
||||||
vertex = {
|
vertex = {
|
||||||
id,
|
id,
|
||||||
labelType: 'text',
|
labelType: 'text',
|
||||||
domId: MERMAID_DOM_ID_PREFIX + id + '-' + vertexCounter,
|
domId: MERMAID_DOM_ID_PREFIX + id + '-' + this.vertexCounter,
|
||||||
styles: [],
|
styles: [],
|
||||||
classes: [],
|
classes: [],
|
||||||
};
|
};
|
||||||
vertices.set(id, vertex);
|
this.vertices.set(id, vertex);
|
||||||
}
|
}
|
||||||
vertexCounter++;
|
this.vertexCounter++;
|
||||||
|
|
||||||
if (textObj !== undefined) {
|
if (textObj !== undefined) {
|
||||||
config = getConfig();
|
this.config = getConfig();
|
||||||
txt = sanitizeText(textObj.text.trim());
|
txt = this.sanitizeText(textObj.text.trim());
|
||||||
vertex.labelType = textObj.type;
|
vertex.labelType = textObj.type;
|
||||||
// strip quotes if string starts and ends with a quote
|
// strip quotes if string starts and ends with a quote
|
||||||
if (txt.startsWith('"') && txt.endsWith('"')) {
|
if (txt.startsWith('"') && txt.endsWith('"')) {
|
||||||
@@ -110,12 +121,12 @@ export const addVertex = function (
|
|||||||
vertex.type = type;
|
vertex.type = type;
|
||||||
}
|
}
|
||||||
if (style !== undefined && style !== null) {
|
if (style !== undefined && style !== null) {
|
||||||
style.forEach(function (s) {
|
style.forEach((s) => {
|
||||||
vertex.styles.push(s);
|
vertex.styles.push(s);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (classes !== undefined && classes !== null) {
|
if (classes !== undefined && classes !== null) {
|
||||||
classes.forEach(function (s) {
|
classes.forEach((s) => {
|
||||||
vertex.classes.push(s);
|
vertex.classes.push(s);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -187,7 +198,7 @@ export const addVertex = function (
|
|||||||
* Function called by parser when a link/edge definition has been found
|
* Function called by parser when a link/edge definition has been found
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const addSingleLink = function (_start: string, _end: string, type: any) {
|
private addSingleLink = (_start: string, _end: string, type: any) => {
|
||||||
const start = _start;
|
const start = _start;
|
||||||
const end = _end;
|
const end = _end;
|
||||||
|
|
||||||
@@ -196,7 +207,7 @@ export const addSingleLink = function (_start: string, _end: string, type: any)
|
|||||||
const linkTextObj = type.text;
|
const linkTextObj = type.text;
|
||||||
|
|
||||||
if (linkTextObj !== undefined) {
|
if (linkTextObj !== undefined) {
|
||||||
edge.text = sanitizeText(linkTextObj.text.trim());
|
edge.text = this.sanitizeText(linkTextObj.text.trim());
|
||||||
|
|
||||||
// strip quotes if string starts and ends with a quote
|
// strip quotes if string starts and ends with a quote
|
||||||
if (edge.text.startsWith('"') && edge.text.endsWith('"')) {
|
if (edge.text.startsWith('"') && edge.text.endsWith('"')) {
|
||||||
@@ -211,12 +222,12 @@ export const addSingleLink = function (_start: string, _end: string, type: any)
|
|||||||
edge.length = type.length > 10 ? 10 : type.length;
|
edge.length = type.length > 10 ? 10 : type.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edges.length < (config.maxEdges ?? 500)) {
|
if (this.edges.length < (this.config.maxEdges ?? 500)) {
|
||||||
log.info('Pushing edge...');
|
log.info('Pushing edge...');
|
||||||
edges.push(edge);
|
this.edges.push(edge);
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Edge limit exceeded. ${edges.length} edges found, but the limit is ${config.maxEdges}.
|
`Edge limit exceeded. ${this.edges.length} edges found, but the limit is ${this.config.maxEdges}.
|
||||||
|
|
||||||
Initialize mermaid with maxEdges set to a higher number to allow more edges.
|
Initialize mermaid with maxEdges set to a higher number to allow more edges.
|
||||||
You cannot set this config via configuration inside the diagram as it is a secure config.
|
You cannot set this config via configuration inside the diagram as it is a secure config.
|
||||||
@@ -225,11 +236,11 @@ You have to call mermaid.initialize.`
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addLink = function (_start: string[], _end: string[], type: unknown) {
|
public addLink = (_start: string[], _end: string[], type: unknown) => {
|
||||||
log.info('addLink', _start, _end, type);
|
log.info('addLink', _start, _end, type);
|
||||||
for (const start of _start) {
|
for (const start of _start) {
|
||||||
for (const end of _end) {
|
for (const end of _end) {
|
||||||
addSingleLink(start, end, type);
|
this.addSingleLink(start, end, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -238,15 +249,12 @@ export const addLink = function (_start: string[], _end: string[], type: unknown
|
|||||||
* Updates a link's line interpolation algorithm
|
* Updates a link's line interpolation algorithm
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const updateLinkInterpolate = function (
|
public updateLinkInterpolate = (positions: ('default' | number)[], interpolate: string) => {
|
||||||
positions: ('default' | number)[],
|
positions.forEach((pos) => {
|
||||||
interpolate: string
|
|
||||||
) {
|
|
||||||
positions.forEach(function (pos) {
|
|
||||||
if (pos === 'default') {
|
if (pos === 'default') {
|
||||||
edges.defaultInterpolate = interpolate;
|
this.edges.defaultInterpolate = interpolate;
|
||||||
} else {
|
} else {
|
||||||
edges[pos].interpolate = interpolate;
|
this.edges[pos].interpolate = interpolate;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -255,43 +263,43 @@ export const updateLinkInterpolate = function (
|
|||||||
* Updates a link with a style
|
* Updates a link with a style
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const updateLink = function (positions: ('default' | number)[], style: string[]) {
|
public updateLink = (positions: ('default' | number)[], style: string[]) => {
|
||||||
positions.forEach(function (pos) {
|
positions.forEach((pos) => {
|
||||||
if (typeof pos === 'number' && pos >= edges.length) {
|
if (typeof pos === 'number' && pos >= this.edges.length) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`The index ${pos} for linkStyle is out of bounds. Valid indices for linkStyle are between 0 and ${
|
`The index ${pos} for linkStyle is out of bounds. Valid indices for linkStyle are between 0 and ${
|
||||||
edges.length - 1
|
this.edges.length - 1
|
||||||
}. (Help: Ensure that the index is within the range of existing edges.)`
|
}. (Help: Ensure that the index is within the range of existing edges.)`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (pos === 'default') {
|
if (pos === 'default') {
|
||||||
edges.defaultStyle = style;
|
this.edges.defaultStyle = style;
|
||||||
} else {
|
} else {
|
||||||
// if (utils.isSubstringInArray('fill', style) === -1) {
|
// if (utils.isSubstringInArray('fill', style) === -1) {
|
||||||
// style.push('fill:none');
|
// style.push('fill:none');
|
||||||
// }
|
// }
|
||||||
edges[pos].style = style;
|
this.edges[pos].style = style;
|
||||||
// if edges[pos].style does have fill not set, set it to none
|
// if edges[pos].style does have fill not set, set it to none
|
||||||
if (
|
if (
|
||||||
(edges[pos]?.style?.length ?? 0) > 0 &&
|
(this.edges[pos]?.style?.length ?? 0) > 0 &&
|
||||||
!edges[pos]?.style?.some((s) => s?.startsWith('fill'))
|
!this.edges[pos]?.style?.some((s) => s?.startsWith('fill'))
|
||||||
) {
|
) {
|
||||||
edges[pos]?.style?.push('fill:none');
|
this.edges[pos]?.style?.push('fill:none');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addClass = function (ids: string, style: string[]) {
|
public addClass = (ids: string, style: string[]) => {
|
||||||
ids.split(',').forEach(function (id) {
|
ids.split(',').forEach((id) => {
|
||||||
let classNode = classes.get(id);
|
let classNode = this.classes.get(id);
|
||||||
if (classNode === undefined) {
|
if (classNode === undefined) {
|
||||||
classNode = { id, styles: [], textStyles: [] };
|
classNode = { id, styles: [], textStyles: [] };
|
||||||
classes.set(id, classNode);
|
this.classes.set(id, classNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (style !== undefined && style !== null) {
|
if (style !== undefined && style !== null) {
|
||||||
style.forEach(function (s) {
|
style.forEach((s) => {
|
||||||
if (/color/.exec(s)) {
|
if (/color/.exec(s)) {
|
||||||
const newStyle = s.replace('fill', 'bgFill'); // .replace('color', 'fill');
|
const newStyle = s.replace('fill', 'bgFill'); // .replace('color', 'fill');
|
||||||
classNode.textStyles.push(newStyle);
|
classNode.textStyles.push(newStyle);
|
||||||
@@ -306,22 +314,22 @@ export const addClass = function (ids: string, style: string[]) {
|
|||||||
* Called by parser when a graph definition is found, stores the direction of the chart.
|
* Called by parser when a graph definition is found, stores the direction of the chart.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const setDirection = function (dir: string) {
|
public setDirection = (dir: string) => {
|
||||||
direction = dir;
|
this.direction = dir;
|
||||||
if (/.*</.exec(direction)) {
|
if (/.*</.exec(this.direction)) {
|
||||||
direction = 'RL';
|
this.direction = 'RL';
|
||||||
}
|
}
|
||||||
if (/.*\^/.exec(direction)) {
|
if (/.*\^/.exec(this.direction)) {
|
||||||
direction = 'BT';
|
this.direction = 'BT';
|
||||||
}
|
}
|
||||||
if (/.*>/.exec(direction)) {
|
if (/.*>/.exec(this.direction)) {
|
||||||
direction = 'LR';
|
this.direction = 'LR';
|
||||||
}
|
}
|
||||||
if (/.*v/.exec(direction)) {
|
if (/.*v/.exec(this.direction)) {
|
||||||
direction = 'TB';
|
this.direction = 'TB';
|
||||||
}
|
}
|
||||||
if (direction === 'TD') {
|
if (this.direction === 'TD') {
|
||||||
direction = 'TB';
|
this.direction = 'TB';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -331,31 +339,31 @@ export const setDirection = function (dir: string) {
|
|||||||
* @param ids - Comma separated list of ids
|
* @param ids - Comma separated list of ids
|
||||||
* @param className - Class to add
|
* @param className - Class to add
|
||||||
*/
|
*/
|
||||||
export const setClass = function (ids: string, className: string) {
|
public setClass = (ids: string, className: string) => {
|
||||||
for (const id of ids.split(',')) {
|
for (const id of ids.split(',')) {
|
||||||
const vertex = vertices.get(id);
|
const vertex = this.vertices.get(id);
|
||||||
if (vertex) {
|
if (vertex) {
|
||||||
vertex.classes.push(className);
|
vertex.classes.push(className);
|
||||||
}
|
}
|
||||||
const subGraph = subGraphLookup.get(id);
|
const subGraph = this.subGraphLookup.get(id);
|
||||||
if (subGraph) {
|
if (subGraph) {
|
||||||
subGraph.classes.push(className);
|
subGraph.classes.push(className);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setTooltip = function (ids: string, tooltip: string) {
|
public setTooltip = (ids: string, tooltip: string) => {
|
||||||
if (tooltip === undefined) {
|
if (tooltip === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tooltip = sanitizeText(tooltip);
|
tooltip = this.sanitizeText(tooltip);
|
||||||
for (const id of ids.split(',')) {
|
for (const id of ids.split(',')) {
|
||||||
tooltips.set(version === 'gen-1' ? lookUpDomId(id) : id, tooltip);
|
this.tooltips.set(this.version === 'gen-1' ? this.lookUpDomId(id) : id, tooltip);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setClickFun = function (id: string, functionName: string, functionArgs: string) {
|
private setClickFun = (id: string, functionName: string, functionArgs: string) => {
|
||||||
const domId = lookUpDomId(id);
|
const domId = this.lookUpDomId(id);
|
||||||
// if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
|
// if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
|
||||||
if (getConfig().securityLevel !== 'loose') {
|
if (getConfig().securityLevel !== 'loose') {
|
||||||
return;
|
return;
|
||||||
@@ -383,15 +391,15 @@ const setClickFun = function (id: string, functionName: string, functionArgs: st
|
|||||||
argList.push(id);
|
argList.push(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
const vertex = vertices.get(id);
|
const vertex = this.vertices.get(id);
|
||||||
if (vertex) {
|
if (vertex) {
|
||||||
vertex.haveCallback = true;
|
vertex.haveCallback = true;
|
||||||
funs.push(function () {
|
this.funs.push(() => {
|
||||||
const elem = document.querySelector(`[id="${domId}"]`);
|
const elem = document.querySelector(`[id="${domId}"]`);
|
||||||
if (elem !== null) {
|
if (elem !== null) {
|
||||||
elem.addEventListener(
|
elem.addEventListener(
|
||||||
'click',
|
'click',
|
||||||
function () {
|
() => {
|
||||||
utils.runFunc(functionName, ...argList);
|
utils.runFunc(functionName, ...argList);
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
@@ -408,19 +416,19 @@ const setClickFun = function (id: string, functionName: string, functionArgs: st
|
|||||||
* @param linkStr - URL to create a link for
|
* @param linkStr - URL to create a link for
|
||||||
* @param target - Target attribute for the link
|
* @param target - Target attribute for the link
|
||||||
*/
|
*/
|
||||||
export const setLink = function (ids: string, linkStr: string, target: string) {
|
public setLink = (ids: string, linkStr: string, target: string) => {
|
||||||
ids.split(',').forEach(function (id) {
|
ids.split(',').forEach((id) => {
|
||||||
const vertex = vertices.get(id);
|
const vertex = this.vertices.get(id);
|
||||||
if (vertex !== undefined) {
|
if (vertex !== undefined) {
|
||||||
vertex.link = utils.formatUrl(linkStr, config);
|
vertex.link = utils.formatUrl(linkStr, this.config);
|
||||||
vertex.linkTarget = target;
|
vertex.linkTarget = target;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setClass(ids, 'clickable');
|
this.setClass(ids, 'clickable');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTooltip = function (id: string) {
|
public getTooltip = (id: string) => {
|
||||||
return tooltips.get(id);
|
return this.tooltips.get(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -430,66 +438,69 @@ export const getTooltip = function (id: string) {
|
|||||||
* @param functionName - Function to be called on click
|
* @param functionName - Function to be called on click
|
||||||
* @param functionArgs - Arguments to be passed to the function
|
* @param functionArgs - Arguments to be passed to the function
|
||||||
*/
|
*/
|
||||||
export const setClickEvent = function (ids: string, functionName: string, functionArgs: string) {
|
public setClickEvent = (ids: string, functionName: string, functionArgs: string) => {
|
||||||
ids.split(',').forEach(function (id) {
|
ids.split(',').forEach((id) => {
|
||||||
setClickFun(id, functionName, functionArgs);
|
this.setClickFun(id, functionName, functionArgs);
|
||||||
});
|
});
|
||||||
setClass(ids, 'clickable');
|
this.setClass(ids, 'clickable');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const bindFunctions = function (element: Element) {
|
public bindFunctions = (element: Element) => {
|
||||||
funs.forEach(function (fun) {
|
this.funs.forEach((fun) => {
|
||||||
fun(element);
|
fun(element);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
export const getDirection = function () {
|
public getDirection = () => {
|
||||||
return direction.trim();
|
return this.direction?.trim();
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Retrieval function for fetching the found nodes after parsing has completed.
|
* Retrieval function for fetching the found nodes after parsing has completed.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const getVertices = function () {
|
public getVertices = () => {
|
||||||
return vertices;
|
return this.vertices;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieval function for fetching the found links after parsing has completed.
|
* Retrieval function for fetching the found links after parsing has completed.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const getEdges = function () {
|
public getEdges = () => {
|
||||||
return edges;
|
return this.edges;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieval function for fetching the found class definitions after parsing has completed.
|
* Retrieval function for fetching the found class definitions after parsing has completed.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const getClasses = function () {
|
public getClasses = () => {
|
||||||
return classes;
|
return this.classes;
|
||||||
};
|
};
|
||||||
|
|
||||||
const setupToolTips = function (element: Element) {
|
private setupToolTips = (element: Element) => {
|
||||||
let tooltipElem = select('.mermaidTooltip');
|
let tooltipElem = select('.mermaidTooltip');
|
||||||
// @ts-ignore TODO: fix this
|
// @ts-ignore TODO: fix this
|
||||||
if ((tooltipElem._groups || tooltipElem)[0][0] === null) {
|
if ((tooltipElem._groups || tooltipElem)[0][0] === null) {
|
||||||
// @ts-ignore TODO: fix this
|
// @ts-ignore TODO: fix this
|
||||||
tooltipElem = select('body').append('div').attr('class', 'mermaidTooltip').style('opacity', 0);
|
tooltipElem = select('body')
|
||||||
|
.append('div')
|
||||||
|
.attr('class', 'mermaidTooltip')
|
||||||
|
.style('opacity', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const svg = select(element).select('svg');
|
const svg = select(element).select('svg');
|
||||||
|
|
||||||
const nodes = svg.selectAll('g.node');
|
const nodes = svg.selectAll('g.node');
|
||||||
nodes
|
nodes
|
||||||
.on('mouseover', function () {
|
.on('mouseover', (e: MouseEvent) => {
|
||||||
const el = select(this);
|
const el = select(e.currentTarget as Element);
|
||||||
const title = el.attr('title');
|
const title = el.attr('title');
|
||||||
|
|
||||||
// Don't try to draw a tooltip if no data is provided
|
// Don't try to draw a tooltip if no data is provided
|
||||||
if (title === null) {
|
if (title === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const rect = (this as Element)?.getBoundingClientRect();
|
const rect = (e.currentTarget as Element)?.getBoundingClientRect();
|
||||||
|
|
||||||
tooltipElem.transition().duration(200).style('opacity', '.9');
|
tooltipElem.transition().duration(200).style('opacity', '.9');
|
||||||
tooltipElem
|
tooltipElem
|
||||||
@@ -499,53 +510,52 @@ const setupToolTips = function (element: Element) {
|
|||||||
tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '<br/>'));
|
tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '<br/>'));
|
||||||
el.classed('hover', true);
|
el.classed('hover', true);
|
||||||
})
|
})
|
||||||
.on('mouseout', function () {
|
.on('mouseout', (e: MouseEvent) => {
|
||||||
tooltipElem.transition().duration(500).style('opacity', 0);
|
tooltipElem.transition().duration(500).style('opacity', 0);
|
||||||
const el = select(this);
|
const el = select(e.currentTarget as Element);
|
||||||
el.classed('hover', false);
|
el.classed('hover', false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
funs.push(setupToolTips);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the internal graph db so that a new graph can be parsed.
|
* Clears the internal graph db so that a new graph can be parsed.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const clear = function (ver = 'gen-1') {
|
public clear = (ver = 'gen-1') => {
|
||||||
vertices = new Map();
|
this.vertices = new Map();
|
||||||
classes = new Map();
|
this.classes = new Map();
|
||||||
edges = [];
|
this.edges = [];
|
||||||
funs = [setupToolTips];
|
this.funs = [this.setupToolTips];
|
||||||
subGraphs = [];
|
this.subGraphs = [];
|
||||||
subGraphLookup = new Map();
|
this.subGraphLookup = new Map();
|
||||||
subCount = 0;
|
this.subCount = 0;
|
||||||
tooltips = new Map();
|
this.tooltips = new Map();
|
||||||
firstGraphFlag = true;
|
this.firstGraphFlag = true;
|
||||||
version = ver;
|
this.version = ver;
|
||||||
config = getConfig();
|
this.config = getConfig();
|
||||||
commonClear();
|
commonClear();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setGen = (ver: string) => {
|
public setGen = (ver: string) => {
|
||||||
version = ver || 'gen-2';
|
this.version = ver || 'gen-2';
|
||||||
};
|
};
|
||||||
|
|
||||||
export const defaultStyle = function () {
|
public defaultStyle = () => {
|
||||||
return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;';
|
return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;';
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addSubGraph = function (
|
public addSubGraph = (
|
||||||
_id: { text: string },
|
_id: { text: string },
|
||||||
list: string[],
|
list: string[],
|
||||||
_title: { text: string; type: string }
|
_title: { text: string; type: string }
|
||||||
) {
|
) => {
|
||||||
let id: string | undefined = _id.text.trim();
|
let id: string | undefined = _id.text.trim();
|
||||||
let title = _title.text;
|
let title = _title.text;
|
||||||
if (_id === _title && /\s/.exec(_title.text)) {
|
if (_id === _title && /\s/.exec(_title.text)) {
|
||||||
id = undefined;
|
id = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function uniq(a: any[]) {
|
const uniq = (a: any[]) => {
|
||||||
const prims: any = { boolean: {}, number: {}, string: {} };
|
const prims: any = { boolean: {}, number: {}, string: {} };
|
||||||
const objs: any[] = [];
|
const objs: any[] = [];
|
||||||
|
|
||||||
@@ -566,19 +576,19 @@ export const addSubGraph = function (
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
return { nodeList, dir };
|
return { nodeList, dir };
|
||||||
}
|
};
|
||||||
|
|
||||||
const { nodeList, dir } = uniq(list.flat());
|
const { nodeList, dir } = uniq(list.flat());
|
||||||
if (version === 'gen-1') {
|
if (this.version === 'gen-1') {
|
||||||
for (let i = 0; i < nodeList.length; i++) {
|
for (let i = 0; i < nodeList.length; i++) {
|
||||||
nodeList[i] = lookUpDomId(nodeList[i]);
|
nodeList[i] = this.lookUpDomId(nodeList[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
id = id ?? 'subGraph' + subCount;
|
id = id ?? 'subGraph' + this.subCount;
|
||||||
title = title || '';
|
title = title || '';
|
||||||
title = sanitizeText(title);
|
title = this.sanitizeText(title);
|
||||||
subCount = subCount + 1;
|
this.subCount = this.subCount + 1;
|
||||||
const subGraph = {
|
const subGraph = {
|
||||||
id: id,
|
id: id,
|
||||||
nodes: nodeList,
|
nodes: nodeList,
|
||||||
@@ -591,34 +601,33 @@ export const addSubGraph = function (
|
|||||||
log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir);
|
log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir);
|
||||||
|
|
||||||
// Remove the members in the new subgraph if they already belong to another subgraph
|
// Remove the members in the new subgraph if they already belong to another subgraph
|
||||||
subGraph.nodes = makeUniq(subGraph, subGraphs).nodes;
|
subGraph.nodes = this.makeUniq(subGraph, this.subGraphs).nodes;
|
||||||
subGraphs.push(subGraph);
|
this.subGraphs.push(subGraph);
|
||||||
subGraphLookup.set(id, subGraph);
|
this.subGraphLookup.set(id, subGraph);
|
||||||
return id;
|
return id;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPosForId = function (id: string) {
|
private getPosForId = (id: string) => {
|
||||||
for (const [i, subGraph] of subGraphs.entries()) {
|
for (const [i, subGraph] of this.subGraphs.entries()) {
|
||||||
if (subGraph.id === id) {
|
if (subGraph.id === id) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
let secCount = -1;
|
|
||||||
const posCrossRef: number[] = [];
|
private indexNodes2 = (id: string, pos: number): { result: boolean; count: number } => {
|
||||||
const indexNodes2 = function (id: string, pos: number): { result: boolean; count: number } {
|
const nodes = this.subGraphs[pos].nodes;
|
||||||
const nodes = subGraphs[pos].nodes;
|
this.secCount = this.secCount + 1;
|
||||||
secCount = secCount + 1;
|
if (this.secCount > 2000) {
|
||||||
if (secCount > 2000) {
|
|
||||||
return {
|
return {
|
||||||
result: false,
|
result: false,
|
||||||
count: 0,
|
count: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
posCrossRef[secCount] = pos;
|
this.posCrossRef[this.secCount] = pos;
|
||||||
// Check if match
|
// Check if match
|
||||||
if (subGraphs[pos].id === id) {
|
if (this.subGraphs[pos].id === id) {
|
||||||
return {
|
return {
|
||||||
result: true,
|
result: true,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -628,10 +637,10 @@ const indexNodes2 = function (id: string, pos: number): { result: boolean; count
|
|||||||
let count = 0;
|
let count = 0;
|
||||||
let posCount = 1;
|
let posCount = 1;
|
||||||
while (count < nodes.length) {
|
while (count < nodes.length) {
|
||||||
const childPos = getPosForId(nodes[count]);
|
const childPos = this.getPosForId(nodes[count]);
|
||||||
// Ignore regular nodes (pos will be -1)
|
// Ignore regular nodes (pos will be -1)
|
||||||
if (childPos >= 0) {
|
if (childPos >= 0) {
|
||||||
const res = indexNodes2(id, childPos);
|
const res = this.indexNodes2(id, childPos);
|
||||||
if (res.result) {
|
if (res.result) {
|
||||||
return {
|
return {
|
||||||
result: true,
|
result: true,
|
||||||
@@ -650,29 +659,29 @@ const indexNodes2 = function (id: string, pos: number): { result: boolean; count
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDepthFirstPos = function (pos: number) {
|
public getDepthFirstPos = (pos: number) => {
|
||||||
return posCrossRef[pos];
|
return this.posCrossRef[pos];
|
||||||
};
|
};
|
||||||
export const indexNodes = function () {
|
public indexNodes = () => {
|
||||||
secCount = -1;
|
this.secCount = -1;
|
||||||
if (subGraphs.length > 0) {
|
if (this.subGraphs.length > 0) {
|
||||||
indexNodes2('none', subGraphs.length - 1);
|
this.indexNodes2('none', this.subGraphs.length - 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getSubGraphs = function () {
|
public getSubGraphs = () => {
|
||||||
return subGraphs;
|
return this.subGraphs;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const firstGraph = () => {
|
public firstGraph = () => {
|
||||||
if (firstGraphFlag) {
|
if (this.firstGraphFlag) {
|
||||||
firstGraphFlag = false;
|
this.firstGraphFlag = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const destructStartLink = (_str: string): FlowLink => {
|
private destructStartLink = (_str: string): FlowLink => {
|
||||||
let str = _str.trim();
|
let str = _str.trim();
|
||||||
let type = 'arrow_open';
|
let type = 'arrow_open';
|
||||||
|
|
||||||
@@ -704,7 +713,7 @@ const destructStartLink = (_str: string): FlowLink => {
|
|||||||
return { type, stroke };
|
return { type, stroke };
|
||||||
};
|
};
|
||||||
|
|
||||||
const countChar = (char: string, str: string) => {
|
private countChar = (char: string, str: string) => {
|
||||||
const length = str.length;
|
const length = str.length;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
for (let i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
@@ -715,7 +724,7 @@ const countChar = (char: string, str: string) => {
|
|||||||
return count;
|
return count;
|
||||||
};
|
};
|
||||||
|
|
||||||
const destructEndLink = (_str: string) => {
|
private destructEndLink = (_str: string) => {
|
||||||
const str = _str.trim();
|
const str = _str.trim();
|
||||||
let line = str.slice(0, -1);
|
let line = str.slice(0, -1);
|
||||||
let type = 'arrow_open';
|
let type = 'arrow_open';
|
||||||
@@ -755,7 +764,7 @@ const destructEndLink = (_str: string) => {
|
|||||||
stroke = 'invisible';
|
stroke = 'invisible';
|
||||||
}
|
}
|
||||||
|
|
||||||
const dots = countChar('.', line);
|
const dots = this.countChar('.', line);
|
||||||
|
|
||||||
if (dots) {
|
if (dots) {
|
||||||
stroke = 'dotted';
|
stroke = 'dotted';
|
||||||
@@ -765,11 +774,11 @@ const destructEndLink = (_str: string) => {
|
|||||||
return { type, stroke, length };
|
return { type, stroke, length };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const destructLink = (_str: string, _startStr: string) => {
|
public destructLink = (_str: string, _startStr: string) => {
|
||||||
const info = destructEndLink(_str);
|
const info = this.destructEndLink(_str);
|
||||||
let startInfo;
|
let startInfo;
|
||||||
if (_startStr) {
|
if (_startStr) {
|
||||||
startInfo = destructStartLink(_startStr);
|
startInfo = this.destructStartLink(_startStr);
|
||||||
|
|
||||||
if (startInfo.stroke !== info.stroke) {
|
if (startInfo.stroke !== info.stroke) {
|
||||||
return { type: 'INVALID', stroke: 'INVALID' };
|
return { type: 'INVALID', stroke: 'INVALID' };
|
||||||
@@ -799,7 +808,7 @@ export const destructLink = (_str: string, _startStr: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Todo optimizer this by caching existing nodes
|
// Todo optimizer this by caching existing nodes
|
||||||
const exists = (allSgs: FlowSubGraph[], _id: string) => {
|
public exists = (allSgs: FlowSubGraph[], _id: string) => {
|
||||||
for (const sg of allSgs) {
|
for (const sg of allSgs) {
|
||||||
if (sg.nodes.includes(_id)) {
|
if (sg.nodes.includes(_id)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -811,21 +820,21 @@ const exists = (allSgs: FlowSubGraph[], _id: string) => {
|
|||||||
* Deletes an id from all subgraphs
|
* Deletes an id from all subgraphs
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
const makeUniq = (sg: FlowSubGraph, allSubgraphs: FlowSubGraph[]) => {
|
public makeUniq = (sg: FlowSubGraph, allSubgraphs: FlowSubGraph[]) => {
|
||||||
const res: string[] = [];
|
const res: string[] = [];
|
||||||
sg.nodes.forEach((_id, pos) => {
|
sg.nodes.forEach((_id, pos) => {
|
||||||
if (!exists(allSubgraphs, _id)) {
|
if (!this.exists(allSubgraphs, _id)) {
|
||||||
res.push(sg.nodes[pos]);
|
res.push(sg.nodes[pos]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return { nodes: res };
|
return { nodes: res };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const lex = {
|
public lex = {
|
||||||
firstGraph,
|
firstGraph: this.firstGraph,
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTypeFromVertex = (vertex: FlowVertex): ShapeID => {
|
private getTypeFromVertex = (vertex: FlowVertex): ShapeID => {
|
||||||
if (vertex.img) {
|
if (vertex.img) {
|
||||||
return 'imageSquare';
|
return 'imageSquare';
|
||||||
}
|
}
|
||||||
@@ -855,8 +864,8 @@ const getTypeFromVertex = (vertex: FlowVertex): ShapeID => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const findNode = (nodes: Node[], id: string) => nodes.find((node) => node.id === id);
|
private findNode = (nodes: Node[], id: string) => nodes.find((node) => node.id === id);
|
||||||
const destructEdgeType = (type: string | undefined) => {
|
private destructEdgeType = (type: string | undefined) => {
|
||||||
let arrowTypeStart = 'none';
|
let arrowTypeStart = 'none';
|
||||||
let arrowTypeEnd = 'arrow_point';
|
let arrowTypeEnd = 'arrow_point';
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -876,7 +885,7 @@ const destructEdgeType = (type: string | undefined) => {
|
|||||||
return { arrowTypeStart, arrowTypeEnd };
|
return { arrowTypeStart, arrowTypeEnd };
|
||||||
};
|
};
|
||||||
|
|
||||||
const addNodeFromVertex = (
|
private addNodeFromVertex = (
|
||||||
vertex: FlowVertex,
|
vertex: FlowVertex,
|
||||||
nodes: Node[],
|
nodes: Node[],
|
||||||
parentDB: Map<string, string>,
|
parentDB: Map<string, string>,
|
||||||
@@ -887,10 +896,10 @@ const addNodeFromVertex = (
|
|||||||
const parentId = parentDB.get(vertex.id);
|
const parentId = parentDB.get(vertex.id);
|
||||||
const isGroup = subGraphDB.get(vertex.id) ?? false;
|
const isGroup = subGraphDB.get(vertex.id) ?? false;
|
||||||
|
|
||||||
const node = findNode(nodes, vertex.id);
|
const node = this.findNode(nodes, vertex.id);
|
||||||
if (node) {
|
if (node) {
|
||||||
node.cssStyles = vertex.styles;
|
node.cssStyles = vertex.styles;
|
||||||
node.cssCompiledStyles = getCompiledStyles(vertex.classes);
|
node.cssCompiledStyles = this.getCompiledStyles(vertex.classes);
|
||||||
node.cssClasses = vertex.classes.join(' ');
|
node.cssClasses = vertex.classes.join(' ');
|
||||||
} else {
|
} else {
|
||||||
const baseNode = {
|
const baseNode = {
|
||||||
@@ -900,14 +909,14 @@ const addNodeFromVertex = (
|
|||||||
parentId,
|
parentId,
|
||||||
padding: config.flowchart?.padding || 8,
|
padding: config.flowchart?.padding || 8,
|
||||||
cssStyles: vertex.styles,
|
cssStyles: vertex.styles,
|
||||||
cssCompiledStyles: getCompiledStyles(['default', 'node', ...vertex.classes]),
|
cssCompiledStyles: this.getCompiledStyles(['default', 'node', ...vertex.classes]),
|
||||||
cssClasses: 'default ' + vertex.classes.join(' '),
|
cssClasses: 'default ' + vertex.classes.join(' '),
|
||||||
dir: vertex.dir,
|
dir: vertex.dir,
|
||||||
domId: vertex.domId,
|
domId: vertex.domId,
|
||||||
look,
|
look,
|
||||||
link: vertex.link,
|
link: vertex.link,
|
||||||
linkTarget: vertex.linkTarget,
|
linkTarget: vertex.linkTarget,
|
||||||
tooltip: getTooltip(vertex.id),
|
tooltip: this.getTooltip(vertex.id),
|
||||||
icon: vertex.icon,
|
icon: vertex.icon,
|
||||||
pos: vertex.pos,
|
pos: vertex.pos,
|
||||||
img: vertex.img,
|
img: vertex.img,
|
||||||
@@ -925,16 +934,16 @@ const addNodeFromVertex = (
|
|||||||
nodes.push({
|
nodes.push({
|
||||||
...baseNode,
|
...baseNode,
|
||||||
isGroup: false,
|
isGroup: false,
|
||||||
shape: getTypeFromVertex(vertex),
|
shape: this.getTypeFromVertex(vertex),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function getCompiledStyles(classDefs: string[]) {
|
private getCompiledStyles = (classDefs: string[]) => {
|
||||||
let compiledStyles: string[] = [];
|
let compiledStyles: string[] = [];
|
||||||
for (const customClass of classDefs) {
|
for (const customClass of classDefs) {
|
||||||
const cssClass = classes.get(customClass);
|
const cssClass = this.classes.get(customClass);
|
||||||
if (cssClass?.styles) {
|
if (cssClass?.styles) {
|
||||||
compiledStyles = [...compiledStyles, ...(cssClass.styles ?? [])].map((s) => s.trim());
|
compiledStyles = [...compiledStyles, ...(cssClass.styles ?? [])].map((s) => s.trim());
|
||||||
}
|
}
|
||||||
@@ -943,14 +952,14 @@ function getCompiledStyles(classDefs: string[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return compiledStyles;
|
return compiledStyles;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const getData = () => {
|
public getData = () => {
|
||||||
const config = getConfig();
|
const config = getConfig();
|
||||||
const nodes: Node[] = [];
|
const nodes: Node[] = [];
|
||||||
const edges: Edge[] = [];
|
const edges: Edge[] = [];
|
||||||
|
|
||||||
const subGraphs = getSubGraphs();
|
const subGraphs = this.getSubGraphs();
|
||||||
const parentDB = new Map<string, string>();
|
const parentDB = new Map<string, string>();
|
||||||
const subGraphDB = new Map<string, boolean>();
|
const subGraphDB = new Map<string, boolean>();
|
||||||
|
|
||||||
@@ -974,7 +983,7 @@ export const getData = () => {
|
|||||||
labelStyle: '',
|
labelStyle: '',
|
||||||
parentId: parentDB.get(subGraph.id),
|
parentId: parentDB.get(subGraph.id),
|
||||||
padding: 8,
|
padding: 8,
|
||||||
cssCompiledStyles: getCompiledStyles(subGraph.classes),
|
cssCompiledStyles: this.getCompiledStyles(subGraph.classes),
|
||||||
cssClasses: subGraph.classes.join(' '),
|
cssClasses: subGraph.classes.join(' '),
|
||||||
shape: 'rect',
|
shape: 'rect',
|
||||||
dir: subGraph.dir,
|
dir: subGraph.dir,
|
||||||
@@ -983,14 +992,14 @@ export const getData = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const n = getVertices();
|
const n = this.getVertices();
|
||||||
n.forEach((vertex) => {
|
n.forEach((vertex) => {
|
||||||
addNodeFromVertex(vertex, nodes, parentDB, subGraphDB, config, config.look || 'classic');
|
this.addNodeFromVertex(vertex, nodes, parentDB, subGraphDB, config, config.look || 'classic');
|
||||||
});
|
});
|
||||||
|
|
||||||
const e = getEdges();
|
const e = this.getEdges();
|
||||||
e.forEach((rawEdge, index) => {
|
e.forEach((rawEdge, index) => {
|
||||||
const { arrowTypeStart, arrowTypeEnd } = destructEdgeType(rawEdge.type);
|
const { arrowTypeStart, arrowTypeEnd } = this.destructEdgeType(rawEdge.type);
|
||||||
const styles = [...(e.defaultStyle ?? [])];
|
const styles = [...(e.defaultStyle ?? [])];
|
||||||
|
|
||||||
if (rawEdge.style) {
|
if (rawEdge.style) {
|
||||||
@@ -1023,41 +1032,11 @@ export const getData = () => {
|
|||||||
return { nodes, edges, other: {}, config };
|
return { nodes, edges, other: {}, config };
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
public defaultConfig = () => defaultConfig.flowchart;
|
||||||
defaultConfig: () => defaultConfig.flowchart,
|
public setAccTitle = setAccTitle;
|
||||||
setAccTitle,
|
public setAccDescription = setAccDescription;
|
||||||
getAccTitle,
|
public setDiagramTitle = setDiagramTitle;
|
||||||
getAccDescription,
|
public getAccTitle = getAccTitle;
|
||||||
getData,
|
public getAccDescription = getAccDescription;
|
||||||
setAccDescription,
|
public getDiagramTitle = getDiagramTitle;
|
||||||
addVertex,
|
}
|
||||||
lookUpDomId,
|
|
||||||
addLink,
|
|
||||||
updateLinkInterpolate,
|
|
||||||
updateLink,
|
|
||||||
addClass,
|
|
||||||
setDirection,
|
|
||||||
setClass,
|
|
||||||
setTooltip,
|
|
||||||
getTooltip,
|
|
||||||
setClickEvent,
|
|
||||||
setLink,
|
|
||||||
bindFunctions,
|
|
||||||
getDirection,
|
|
||||||
getVertices,
|
|
||||||
getEdges,
|
|
||||||
getClasses,
|
|
||||||
clear,
|
|
||||||
setGen,
|
|
||||||
defaultStyle,
|
|
||||||
addSubGraph,
|
|
||||||
getDepthFirstPos,
|
|
||||||
indexNodes,
|
|
||||||
getSubGraphs,
|
|
||||||
destructLink,
|
|
||||||
lex,
|
|
||||||
exists,
|
|
||||||
makeUniq,
|
|
||||||
setDiagramTitle,
|
|
||||||
getDiagramTitle,
|
|
||||||
};
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import type { MermaidConfig } from '../../config.type.js';
|
import type { MermaidConfig } from '../../config.type.js';
|
||||||
import { setConfig } from '../../diagram-api/diagramAPI.js';
|
import { setConfig } from '../../diagram-api/diagramAPI.js';
|
||||||
import flowDb from './flowDb.js';
|
import { FlowDb } from './flowDb.js';
|
||||||
import renderer from './flowRenderer-v3-unified.js';
|
import renderer from './flowRenderer-v3-unified.js';
|
||||||
// @ts-ignore: JISON doesn't support types
|
// @ts-ignore: JISON doesn't support types
|
||||||
import flowParser from './parser/flow.jison';
|
import flowParser from './parser/flow.jison';
|
||||||
@@ -8,7 +8,9 @@ import flowStyles from './styles.js';
|
|||||||
|
|
||||||
export const diagram = {
|
export const diagram = {
|
||||||
parser: flowParser,
|
parser: flowParser,
|
||||||
db: flowDb,
|
get db() {
|
||||||
|
return new FlowDb();
|
||||||
|
},
|
||||||
renderer,
|
renderer,
|
||||||
styles: flowStyles,
|
styles: flowStyles,
|
||||||
init: (cnf: MermaidConfig) => {
|
init: (cnf: MermaidConfig) => {
|
||||||
@@ -20,7 +22,5 @@ export const diagram = {
|
|||||||
}
|
}
|
||||||
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||||
setConfig({ flowchart: { arrowMarkerAbsolute: cnf.arrowMarkerAbsolute } });
|
setConfig({ flowchart: { arrowMarkerAbsolute: cnf.arrowMarkerAbsolute } });
|
||||||
flowDb.clear();
|
|
||||||
flowDb.setGen('gen-2');
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@@ -7,7 +7,6 @@ import { getRegisteredLayoutAlgorithm, render } from '../../rendering-util/rende
|
|||||||
import { setupViewPortForSVG } from '../../rendering-util/setupViewPortForSVG.js';
|
import { setupViewPortForSVG } from '../../rendering-util/setupViewPortForSVG.js';
|
||||||
import type { LayoutData } from '../../rendering-util/types.js';
|
import type { LayoutData } from '../../rendering-util/types.js';
|
||||||
import utils from '../../utils.js';
|
import utils from '../../utils.js';
|
||||||
import { getDirection } from './flowDb.js';
|
|
||||||
|
|
||||||
export const getClasses = function (
|
export const getClasses = function (
|
||||||
text: string,
|
text: string,
|
||||||
@@ -37,7 +36,7 @@ export const draw = async function (text: string, id: string, _version: string,
|
|||||||
log.debug('Data: ', data4Layout);
|
log.debug('Data: ', data4Layout);
|
||||||
// Create the root SVG
|
// Create the root SVG
|
||||||
const svg = getDiagramElement(id, securityLevel);
|
const svg = getDiagramElement(id, securityLevel);
|
||||||
const direction = getDirection();
|
const direction = diag.db.getDirection();
|
||||||
|
|
||||||
data4Layout.type = diag.type;
|
data4Layout.type = diag.type;
|
||||||
data4Layout.layoutAlgorithm = getRegisteredLayoutAlgorithm(layout);
|
data4Layout.layoutAlgorithm = getRegisteredLayoutAlgorithm(layout);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ setConfig({
|
|||||||
|
|
||||||
describe('[Arrows] when parsing', () => {
|
describe('[Arrows] when parsing', () => {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
import { cleanupComments } from '../../../diagram-api/comments.js';
|
import { cleanupComments } from '../../../diagram-api/comments.js';
|
||||||
@@ -9,7 +9,7 @@ setConfig({
|
|||||||
|
|
||||||
describe('[Comments] when parsing', () => {
|
describe('[Comments] when parsing', () => {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ setConfig({
|
|||||||
|
|
||||||
describe('when parsing directions', function () {
|
describe('when parsing directions', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
flow.parser.yy.setGen('gen-2');
|
flow.parser.yy.setGen('gen-2');
|
||||||
});
|
});
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ const doubleEndedEdges = [
|
|||||||
|
|
||||||
describe('[Edges] when parsing', () => {
|
describe('[Edges] when parsing', () => {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ setConfig({
|
|||||||
|
|
||||||
describe('[Text] when parsing', () => {
|
describe('[Text] when parsing', () => {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
import { vi } from 'vitest';
|
import { vi } from 'vitest';
|
||||||
@@ -9,7 +9,9 @@ setConfig({
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('[Interactions] when parsing', () => {
|
describe('[Interactions] when parsing', () => {
|
||||||
|
let flowDb;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
flowDb = new FlowDb();
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = flowDb;
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
});
|
});
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ setConfig({
|
|||||||
|
|
||||||
describe('[Lines] when parsing', () => {
|
describe('[Lines] when parsing', () => {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ setConfig({
|
|||||||
|
|
||||||
describe('parsing a flow chart with markdown strings', function () {
|
describe('parsing a flow chart with markdown strings', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ setConfig({
|
|||||||
|
|
||||||
describe('when parsing directions', function () {
|
describe('when parsing directions', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
flow.parser.yy.setGen('gen-2');
|
flow.parser.yy.setGen('gen-2');
|
||||||
});
|
});
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ const specialChars = ['#', ':', '0', '&', ',', '*', '.', '\\', 'v', '-', '/', '_
|
|||||||
|
|
||||||
describe('[Singlenodes] when parsing', () => {
|
describe('[Singlenodes] when parsing', () => {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ setConfig({
|
|||||||
|
|
||||||
describe('[Style] when parsing', () => {
|
describe('[Style] when parsing', () => {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
flow.parser.yy.setGen('gen-2');
|
flow.parser.yy.setGen('gen-2');
|
||||||
});
|
});
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ setConfig({
|
|||||||
|
|
||||||
describe('[Text] when parsing', () => {
|
describe('[Text] when parsing', () => {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ setConfig({
|
|||||||
|
|
||||||
describe('when parsing flowcharts', function () {
|
describe('when parsing flowcharts', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
flow.parser.yy.setGen('gen-2');
|
flow.parser.yy.setGen('gen-2');
|
||||||
});
|
});
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { cleanupComments } from '../../../diagram-api/comments.js';
|
import { cleanupComments } from '../../../diagram-api/comments.js';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
@@ -9,7 +9,7 @@ setConfig({
|
|||||||
|
|
||||||
describe('parsing a flow chart', function () {
|
describe('parsing a flow chart', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDb } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flow.jison';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ setConfig({
|
|||||||
|
|
||||||
describe('when parsing subgraphs', function () {
|
describe('when parsing subgraphs', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = new FlowDb();
|
||||||
flow.parser.yy.clear();
|
flow.parser.yy.clear();
|
||||||
flow.parser.yy.setGen('gen-2');
|
flow.parser.yy.setGen('gen-2');
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user