Merge branch 'develop' of https://github.com/mermaid-js/mermaid into saurabh/refactor/convert-classDb-to-class

This commit is contained in:
saurabhg772244
2025-01-23 14:59:41 +05:30
38 changed files with 1453 additions and 1154 deletions

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
Fixes for consistent edge id creation & handling edge cases for animate edge feature

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
Fix for issue #6195 - allowing @ signs inside node labels

View File

@@ -0,0 +1,8 @@
---
'mermaid': minor
---
Flowchart new syntax for node metadata bugs
- Incorrect label mapping for nodes when using `&`
- Syntax error when `}` with trailing spaces before new line

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each flowchart

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Gantt, Sankey and User Journey diagram are now able to pick font-family from mermaid config.

View File

@@ -1076,4 +1076,41 @@ end
);
});
});
describe('New @ sytax for node metadata edge cases', () => {
it('should be possible to use @ syntax to add labels on multi nodes', () => {
imgSnapshotTest(
`flowchart TB
n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"}
`,
{}
);
});
it('should be possible to use @ syntax to add labels with trail spaces and &', () => {
imgSnapshotTest(
`flowchart TB
n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"}
`,
{}
);
});
it('should be possible to use @ syntax to add labels with trail spaces', () => {
imgSnapshotTest(
`flowchart TB
n2["label for n2"]
n4@{ label: "labe for n4"}
n5@{ label: "labe for n5"}
`,
{}
);
});
it('should be possible to use @ syntax to add labels with trail spaces and edge/link', () => {
imgSnapshotTest(
`flowchart TD
A["A"] --> B["for B"] & C@{ label: "for c"} & E@{label : "for E"}
D@{label: "for D"}
`,
{}
);
});
});
});

View File

@@ -78,9 +78,11 @@
font-family: monospace;
font-size: 72px;
}
pre {
width: 100%;
}
/* tspan {
font-size: 6px !important;
} */
@@ -103,16 +105,20 @@
</head>
<body>
<pre id="diagram4" class="mermaid2">
<pre id="diagram4" class="mermaid">
flowchart LR
A --> B
AB["apa@apa@"] --> B(("`apa@apa`"))
</pre>
<pre id="diagram4" class="mermaid">
flowchart
D(("for D"))
</pre>
<pre id="diagram4" class="mermaid">
flowchart LR
A e1@==> B
e1@{ animate: true}
</pre>
<pre id="diagram4" class="mermaid2">
<pre id="diagram4" class="mermaid">
flowchart LR
A e1@--> B
classDef animate stroke-width:2,stroke-dasharray:10\,8,stroke-dashoffset:-180,animation: edge-animation-frame 6s linear infinite, stroke-linecap: round
@@ -126,7 +132,7 @@ flowchart LR
class e1 animate
</pre>
<h2>Mermaid - edge-animation-slow</h2>
<pre id="diagram4" class="mermaid">
<pre id="diagram4" class="mermaid2">
flowchart LR
A e1@--> B
e1@{ animation: fast}
@@ -428,7 +434,10 @@ kanban
window.callback = function () {
alert('A callback was triggered');
};
mermaid.initialize({
function callback() {
alert('It worked');
}
await mermaid.initialize({
// theme: 'base',
// theme: 'default',
// theme: 'forest',
@@ -440,9 +449,11 @@ kanban
// layout: 'fixed',
// htmlLabels: false,
flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
// fontFamily: 'courier',
fontFamily: 'arial',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
@@ -454,10 +465,9 @@ kanban
fontSize: 12,
logLevel: 0,
securityLevel: 'loose',
callback,
});
function callback() {
alert('It worked');
}
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);

View File

@@ -62,56 +62,23 @@
<body style="display: flex; gap: 2rem; flex-direction: row">
<pre id="diagram4" class="mermaid">
flowchart LR
A@{ icon: "fa:window-minimize", form: circle }
E@{ icon: "fa:window-minimize", form: circle }
B@{ icon: "fa:bell", form: circle }
B2@{ icon: "fa:bell", form: circle }
C@{ icon: "fa:address-book", form: square }
D@{ icon: "fa:star-half", form: square }
A --> E
B --> B2
flowchart
A --> A
subgraph B
B1 --> B1
end
subgraph C
subgraph C1
C2 --> C2
subgraph D
D1 --> D1
end
D --> D
end
C1 --> C1
end
</pre>
<pre id="diagram4" class="mermaid2">
flowchart TB
A --test2--> B2@{ icon: "fa:bell", form: "rounded", label: "B2 aiduaid uyawduad uaduabd uyduadb", pos: "b" }
B2 --test--> C
D --> B2 --> E
style B2 fill:#f9f,stroke:#333,stroke-width:4px
</pre
>
<pre id="diagram43" class="mermaid2">
flowchart BT
A --test2--> B2@{ icon: "fa:bell", form: "square", label: "B2", pos: "t", h: 40, w: 30 }
B2 --test--> C
D --> B2 --> E
</pre
>
<pre id="diagram4" class="mermaid2">
flowchart BT
A --test2--> B2@{ icon: "fa:bell", label: "B2 awiugdawu uydgayuiwd wuydguy", pos: "b", h: 40, w: 30 }
B2 --test--> C
</pre
>
<pre id="diagram43" class="mermaid2">
flowchart BT
A --test2--> B2@{ icon: "fa:bell", label: "B2 dawuygd ayuwgd uy", pos: "t", h: 40, w: 30 }
B2 --test--> C
</pre
>
<pre id="diagram6" class="mermaid2">
flowchart TB
A --> B2@{ icon: "fa:bell", form: "circle", label: "test augfuyfavf ydvaubfuac", pos: "t", w: 200, h: 100 } --> C
</pre
>
<pre id="diagram6" class="mermaid2">
flowchart TB
A --> B2@{ icon: "fa:bell", form: "circle", label: "test augfuyfavf ydvaubfuac", pos: "b", w: 200, h: 100 } --> C
D --> B2 --> E
</pre
>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';

View File

@@ -20,7 +20,7 @@
#### Defined in
[packages/mermaid/src/rendering-util/types.ts:147](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L147)
[packages/mermaid/src/rendering-util/types.ts:148](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L148)
---
@@ -30,7 +30,7 @@
#### Defined in
[packages/mermaid/src/rendering-util/types.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L146)
[packages/mermaid/src/rendering-util/types.ts:147](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L147)
---
@@ -40,4 +40,4 @@
#### Defined in
[packages/mermaid/src/rendering-util/types.ts:145](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L145)
[packages/mermaid/src/rendering-util/types.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L146)

View File

@@ -1,9 +1,11 @@
import flowDb from './flowDb.js';
import { FlowDB } from './flowDb.js';
import type { FlowSubGraph } from './types.js';
describe('flow db subgraphs', () => {
let flowDb: FlowDB;
let subgraphs: FlowSubGraph[];
beforeEach(() => {
flowDb = new FlowDB();
subgraphs = [
{ nodes: ['a', 'b', 'c', 'e'] },
{ nodes: ['f', 'g', 'h'] },
@@ -44,8 +46,9 @@ describe('flow db subgraphs', () => {
});
describe('flow db addClass', () => {
let flowDb: FlowDB;
beforeEach(() => {
flowDb.clear();
flowDb = new FlowDB();
});
it('should detect many classes', () => {
flowDb.addClass('a,b', ['stroke-width: 8px']);
@@ -65,3 +68,33 @@ describe('flow db addClass', () => {
expect(classes.get('a')?.styles).toEqual(['stroke-width: 8px']);
});
});
describe('flow db class', () => {
let flowDb: FlowDB;
beforeEach(() => {
flowDb = new FlowDB();
});
// This is to ensure that functions used in flow JISON are exposed as function from FlowDB
it('should have functions used in flow JISON as own property', () => {
const functionsUsedInParser = [
'setDirection',
'addSubGraph',
'setAccTitle',
'setAccDescription',
'addVertex',
'addLink',
'setClass',
'destructLink',
'addClass',
'setClickEvent',
'setTooltip',
'setLink',
'updateLink',
'updateLinkInterpolate',
] as const satisfies (keyof FlowDB)[];
for (const fun of functionsUsedInParser) {
expect(Object.hasOwn(flowDb, fun)).toBe(true);
}
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,17 @@
import type { MermaidConfig } from '../../config.type.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';
// @ts-ignore: JISON doesn't support types
import flowParser from './parser/flow.jison';
//import flowParser from './parser/flow.jison';
import flowParser from './parser/flowParser.ts';
import flowStyles from './styles.js';
export const diagram = {
parser: flowParser,
db: flowDb,
get db() {
return new FlowDB();
},
renderer,
styles: flowStyles,
init: (cnf: MermaidConfig) => {
@@ -20,7 +23,5 @@ export const diagram = {
}
cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
setConfig({ flowchart: { arrowMarkerAbsolute: cnf.arrowMarkerAbsolute } });
flowDb.clear();
flowDb.setGen('gen-2');
},
};

View File

@@ -7,7 +7,6 @@ import { getRegisteredLayoutAlgorithm, render } from '../../rendering-util/rende
import { setupViewPortForSVG } from '../../rendering-util/setupViewPortForSVG.js';
import type { LayoutData } from '../../rendering-util/types.js';
import utils from '../../utils.js';
import { getDirection } from './flowDb.js';
export const getClasses = function (
text: string,
@@ -37,7 +36,7 @@ export const draw = async function (text: string, id: string, _version: string,
log.debug('Data: ', data4Layout);
// Create the root SVG
const svg = getDiagramElement(id, securityLevel);
const direction = getDirection();
const direction = diag.db.getDirection();
data4Layout.type = diag.type;
data4Layout.layoutAlgorithm = getRegisteredLayoutAlgorithm(layout);

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
setConfig({
@@ -8,7 +8,7 @@ setConfig({
describe('[Arrows] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
});

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
import { cleanupComments } from '../../../diagram-api/comments.js';
@@ -9,7 +9,7 @@ setConfig({
describe('[Comments] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
});

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
setConfig({
@@ -8,7 +8,7 @@ setConfig({
describe('when parsing directions', function () {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
flow.parser.yy.setGen('gen-2');
});

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
setConfig({
@@ -63,7 +63,7 @@ const regularEdges = [
describe('[Edges] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
});

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
setConfig({
@@ -8,7 +8,7 @@ setConfig({
describe('[Text] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
});

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
import { vi } from 'vitest';
const spyOn = vi.spyOn;
@@ -9,7 +9,9 @@ setConfig({
});
describe('[Interactions] when parsing', () => {
let flowDb;
beforeEach(function () {
flowDb = new FlowDB();
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
setConfig({
@@ -8,7 +8,7 @@ setConfig({
describe('[Lines] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
});

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
setConfig({
@@ -8,7 +8,7 @@ setConfig({
describe('parsing a flow chart with markdown strings', function () {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
});

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
setConfig({
@@ -8,7 +8,7 @@ setConfig({
describe('when parsing directions', function () {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
flow.parser.yy.setGen('gen-2');
});
@@ -290,4 +290,126 @@ describe('when parsing directions', function () {
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
expect(data4Layout.nodes[0].label).toEqual('This is a string with}');
});
it('should be possible to use @ syntax to add labels on multi nodes', function () {
const res = flow.parser.parse(`flowchart TB
n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"}
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(3);
expect(data4Layout.nodes[0].label).toEqual('label for n2');
expect(data4Layout.nodes[1].label).toEqual('labe for n4');
expect(data4Layout.nodes[2].label).toEqual('labe for n5');
});
it('should be possible to use @ syntax to add labels on multi nodes with edge/link', function () {
const res = flow.parser.parse(`flowchart TD
A["A"] --> B["for B"] & C@{ label: "for c"} & E@{label : "for E"}
D@{label: "for D"}
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(5);
expect(data4Layout.nodes[0].label).toEqual('A');
expect(data4Layout.nodes[1].label).toEqual('for B');
expect(data4Layout.nodes[2].label).toEqual('for c');
expect(data4Layout.nodes[3].label).toEqual('for E');
expect(data4Layout.nodes[4].label).toEqual('for D');
});
it('should be possible to use @ syntax in labels', function () {
const res = flow.parser.parse(`flowchart TD
A["@A@"] --> B["@for@ B@"] & C@{ label: "@for@ c@"} & E{"\`@for@ E@\`"} & D(("@for@ D@"))
H1{{"@for@ H@"}}
H2{{"\`@for@ H@\`"}}
Q1{"@for@ Q@"}
Q2{"\`@for@ Q@\`"}
AS1>"@for@ AS@"]
AS2>"\`@for@ AS@\`"]
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(11);
expect(data4Layout.nodes[0].label).toEqual('@A@');
expect(data4Layout.nodes[1].label).toEqual('@for@ B@');
expect(data4Layout.nodes[2].label).toEqual('@for@ c@');
expect(data4Layout.nodes[3].label).toEqual('@for@ E@');
expect(data4Layout.nodes[4].label).toEqual('@for@ D@');
expect(data4Layout.nodes[5].label).toEqual('@for@ H@');
expect(data4Layout.nodes[6].label).toEqual('@for@ H@');
expect(data4Layout.nodes[7].label).toEqual('@for@ Q@');
expect(data4Layout.nodes[8].label).toEqual('@for@ Q@');
expect(data4Layout.nodes[9].label).toEqual('@for@ AS@');
expect(data4Layout.nodes[10].label).toEqual('@for@ AS@');
});
it('should handle unique edge creation with using @ and &', function () {
const res = flow.parser.parse(`flowchart TD
A & B e1@--> C & D
A1 e2@--> C1 & D1
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(7);
expect(data4Layout.edges.length).toBe(6);
expect(data4Layout.edges[0].id).toEqual('L_A_C_0');
expect(data4Layout.edges[1].id).toEqual('L_A_D_0');
expect(data4Layout.edges[2].id).toEqual('e1');
expect(data4Layout.edges[3].id).toEqual('L_B_D_0');
expect(data4Layout.edges[4].id).toEqual('e2');
expect(data4Layout.edges[5].id).toEqual('L_A1_D1_0');
});
it('should handle redefine same edge ids again', function () {
const res = flow.parser.parse(`flowchart TD
A & B e1@--> C & D
A1 e1@--> C1 & D1
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(7);
expect(data4Layout.edges.length).toBe(6);
expect(data4Layout.edges[0].id).toEqual('L_A_C_0');
expect(data4Layout.edges[1].id).toEqual('L_A_D_0');
expect(data4Layout.edges[2].id).toEqual('e1');
expect(data4Layout.edges[3].id).toEqual('L_B_D_0');
expect(data4Layout.edges[4].id).toEqual('L_A1_C1_0');
expect(data4Layout.edges[5].id).toEqual('L_A1_D1_0');
});
it('should handle overriding edge animate again', function () {
const res = flow.parser.parse(`flowchart TD
A e1@--> B
C e2@--> D
E e3@--> F
e1@{ animate: true }
e2@{ animate: false }
e3@{ animate: true }
e3@{ animate: false }
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(6);
expect(data4Layout.edges.length).toBe(3);
expect(data4Layout.edges[0].id).toEqual('e1');
expect(data4Layout.edges[0].animate).toEqual(true);
expect(data4Layout.edges[1].id).toEqual('e2');
expect(data4Layout.edges[1].animate).toEqual(false);
expect(data4Layout.edges[2].id).toEqual('e3');
expect(data4Layout.edges[2].animate).toEqual(false);
});
it.skip('should be possible to use @ syntax to add labels with trail spaces', function () {
const res = flow.parser.parse(
`flowchart TB
n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"} `
);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(3);
expect(data4Layout.nodes[0].label).toEqual('label for n2');
expect(data4Layout.nodes[1].label).toEqual('labe for n4');
expect(data4Layout.nodes[2].label).toEqual('labe for n5');
});
});

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
setConfig({
@@ -31,7 +31,7 @@ const specialChars = ['#', ':', '0', '&', ',', '*', '.', '\\', 'v', '-', '/', '_
describe('[Singlenodes] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
});

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
setConfig({
@@ -8,7 +8,7 @@ setConfig({
describe('[Style] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
flow.parser.yy.setGen('gen-2');
});

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
setConfig({
@@ -8,7 +8,7 @@ setConfig({
describe('[Text] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
});

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
setConfig({
@@ -8,7 +8,7 @@ setConfig({
describe('when parsing flowcharts', function () {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
flow.parser.yy.setGen('gen-2');
});

View File

@@ -141,7 +141,7 @@ that id.
.*direction\s+RL[^\n]* return 'direction_rl';
.*direction\s+LR[^\n]* return 'direction_lr';
[^\s]+\@(?=[^\{]) { return 'LINK_ID'; }
[^\s\"]+\@(?=[^\{\"]) { return 'LINK_ID'; }
[0-9]+ return 'NUM';
\# return 'BRKT';
":::" return 'STYLE_SEPARATOR';
@@ -399,7 +399,7 @@ shapeData:
;
vertexStatement: vertexStatement link node shapeData
{ /* console.warn('vs shapeData',$vertexStatement.stmt,$node, $shapeData);*/ yy.addVertex($node[0],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData); yy.addLink($vertexStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($vertexStatement.nodes) } }
{ /* console.warn('vs shapeData',$vertexStatement.stmt,$node, $shapeData);*/ yy.addVertex($node[$node.length-1],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData); yy.addLink($vertexStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($vertexStatement.nodes) } }
| vertexStatement link node
{ /*console.warn('vs',$vertexStatement.stmt,$node);*/ yy.addLink($vertexStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($vertexStatement.nodes) } }
| vertexStatement link node spaceList
@@ -407,7 +407,7 @@ vertexStatement: vertexStatement link node shapeData
|node spaceList { /*console.warn('vertexStatement: node spaceList', $node);*/ $$ = {stmt: $node, nodes:$node }}
|node shapeData {
/*console.warn('vertexStatement: node shapeData', $node[0], $shapeData);*/
yy.addVertex($node[0],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData);
yy.addVertex($node[$node.length-1],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData);
$$ = {stmt: $node, nodes:$node, shapeData: $shapeData}
}
|node { /* console.warn('vertexStatement: single node', $node); */ $$ = {stmt: $node, nodes:$node }}
@@ -416,7 +416,7 @@ vertexStatement: vertexStatement link node shapeData
node: styledVertex
{ /*console.warn('nod', $styledVertex);*/ $$ = [$styledVertex];}
| node shapeData spaceList AMP spaceList styledVertex
{ yy.addVertex($node[0],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData); $$ = $node.concat($styledVertex); /*console.warn('pip2', $node[0], $styledVertex, $$);*/ }
{ yy.addVertex($node[$node.length-1],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData); $$ = $node.concat($styledVertex); /*console.warn('pip2', $node[0], $styledVertex, $$);*/ }
| node spaceList AMP spaceList styledVertex
{ $$ = $node.concat($styledVertex); /*console.warn('pip', $node[0], $styledVertex, $$);*/ }
;

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { cleanupComments } from '../../../diagram-api/comments.js';
import { setConfig } from '../../../config.js';
@@ -9,7 +9,7 @@ setConfig({
describe('parsing a flow chart', function () {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
});

View File

@@ -0,0 +1,12 @@
// @ts-ignore: JISON doesn't support types
import flowJisonParser from './flow.jison';
const newParser = Object.assign({}, flowJisonParser);
newParser.parse = (src: string): unknown => {
// remove the trailing whitespace after closing curly braces when ending a line break
const newSrc = src.replace(/}\s*\n/g, '}\n');
return flowJisonParser.parse(newSrc);
};
export default newParser;

View File

@@ -1,5 +1,5 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { FlowDB } from '../flowDb.js';
import flow from './flowParser.ts';
import { setConfig } from '../../../config.js';
setConfig({
@@ -8,7 +8,7 @@ setConfig({
describe('when parsing subgraphs', function () {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy = new FlowDB();
flow.parser.yy.clear();
flow.parser.yy.setGen('gen-2');
});

View File

@@ -53,6 +53,7 @@ export interface FlowText {
}
export interface FlowEdge {
isUserDefinedId: boolean;
start: string;
end: string;
interpolate?: string;

View File

@@ -1,7 +1,7 @@
const getStyles = (options) =>
`
.mermaid-main-font {
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
font-family: ${options.fontFamily};
}
.exclude-range {
@@ -45,7 +45,7 @@ const getStyles = (options) =>
.sectionTitle {
text-anchor: start;
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
font-family: ${options.fontFamily};
}
@@ -86,13 +86,13 @@ const getStyles = (options) =>
.taskText {
text-anchor: middle;
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
font-family: ${options.fontFamily};
}
.taskTextOutsideRight {
fill: ${options.taskTextDarkColor};
text-anchor: start;
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
font-family: ${options.fontFamily};
}
.taskTextOutsideLeft {
@@ -248,7 +248,7 @@ const getStyles = (options) =>
text-anchor: middle;
font-size: 18px;
fill: ${options.titleColor || options.textColor};
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
font-family: ${options.fontFamily};
}
`;

View File

@@ -4,11 +4,13 @@ import parser from './parser/sankey.jison';
import db from './sankeyDB.js';
import renderer from './sankeyRenderer.js';
import { prepareTextForParsing } from './sankeyUtils.js';
import sankeyStyles from './styles.js';
const originalParse = parser.parse.bind(parser);
parser.parse = (text: string) => originalParse(prepareTextForParsing(text));
export const diagram: DiagramDefinition = {
styles: sankeyStyles,
parser,
db,
renderer,

View File

@@ -136,7 +136,6 @@ export const draw = function (text: string, id: string, _version: string, diagOb
svg
.append('g')
.attr('class', 'node-labels')
.attr('font-family', 'sans-serif')
.attr('font-size', 14)
.selectAll('text')
.data(graph.nodes)

View File

@@ -0,0 +1,6 @@
const getStyles = (options) =>
`.label {
font-family: ${options.fontFamily};
}`;
export default getStyles;

View File

@@ -1,7 +1,6 @@
const getStyles = (options) =>
`.label {
font-family: 'trebuchet ms', verdana, arial, sans-serif;
font-family: var(--mermaid-font-family);
font-family: ${options.fontFamily};
color: ${options.textColor};
}
.mouth {
@@ -79,8 +78,7 @@ const getStyles = (options) =>
text-align: center;
max-width: 200px;
padding: 2px;
font-family: 'trebuchet ms', verdana, arial, sans-serif;
font-family: var(--mermaid-font-family);
font-family: ${options.fontFamily};
font-size: 12px;
background: ${options.tertiaryColor};
border: 1px solid ${options.border2};

View File

@@ -71,6 +71,7 @@ import { Diagram } from './Diagram.js';
import { decodeEntities, encodeEntities } from './utils.js';
import { toBase64 } from './utils/base64.js';
import { ClassDB } from './diagrams/class/classDb.js';
import { FlowDB } from './diagrams/flowchart/flowDb.js';
/**
* @see https://vitest.dev/guide/mocking.html Mock part of a module
@@ -834,6 +835,58 @@ graph TD;A--x|text including URL space|B;`)
expect(diagram).toBeInstanceOf(Diagram);
expect(diagram.type).toBe('flowchart-v2');
});
it('should not modify db when rendering different diagrams', async () => {
const flowDiagram1 = await mermaidAPI.getDiagramFromText(
`flowchart LR
A -- text --> B -- text2 --> C`
);
const flwoDiagram2 = await mermaidAPI.getDiagramFromText(
`flowchart TD
A -- text --> B -- text2 --> C`
);
// Since flowDiagram will return new Db object each time, we can compare the db to be different.
expect(flowDiagram1.db).not.toBe(flwoDiagram2.db);
assert(flowDiagram1.db instanceof FlowDB);
assert(flwoDiagram2.db instanceof FlowDB);
expect(flowDiagram1.db.getDirection()).not.toEqual(flwoDiagram2.db.getDirection());
const classDiagram1 = await mermaidAPI.getDiagramFromText(
`stateDiagram
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]`
);
const classDiagram2 = await mermaidAPI.getDiagramFromText(
`stateDiagram
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]`
);
// Since sequenceDiagram will return same Db object each time, we can compare the db to be same.
expect(classDiagram1.db).toBe(classDiagram2.db);
});
});
// Sequence Diagram currently uses a singleton DB, so this test will fail
it.fails('should not modify db when rendering different sequence diagrams', async () => {
const sequenceDiagram1 = await mermaidAPI.getDiagramFromText(
`sequenceDiagram
Alice->>Bob: Hello Bob, how are you?
Bob-->>John: How about you John?`
);
const sequenceDiagram2 = await mermaidAPI.getDiagramFromText(
`sequenceDiagram
Alice->>Bob: Hello Bob, how are you?
Bob-->>John: How about you John?`
);
expect(sequenceDiagram1.db).not.toBe(sequenceDiagram2.db);
});
it('should not modify db when rendering different diagrams', async () => {

View File

@@ -125,6 +125,7 @@ export interface Edge {
pattern?: string;
thickness?: 'normal' | 'thick' | 'invisible' | 'dotted';
look?: string;
isUserDefinedId?: boolean;
}
export interface RectOptions {