mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-28 07:03:17 +08:00
Merge branch 'develop' into patch-1
This commit is contained in:
commit
3536ceb5d3
5
.changeset/bright-ads-exist.md
Normal file
5
.changeset/bright-ads-exist.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes for consistent edge id creation & handling edge cases for animate edge feature
|
5
.changeset/chatty-elephants-warn.md
Normal file
5
.changeset/chatty-elephants-warn.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix for issue #6195 - allowing @ signs inside node labels
|
5
.changeset/chilly-years-cheat.md
Normal file
5
.changeset/chilly-years-cheat.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each class diagram
|
5
.changeset/dull-tips-cough.md
Normal file
5
.changeset/dull-tips-cough.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: revert state db to resolve getData returning empty nodes and edges
|
8
.changeset/great-ghosts-rule.md
Normal file
8
.changeset/great-ghosts-rule.md
Normal 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
|
5
.changeset/many-brooms-promise.md
Normal file
5
.changeset/many-brooms-promise.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Adding support for animation of flowchart edges
|
5
.changeset/new-kiwis-listen.md
Normal file
5
.changeset/new-kiwis-listen.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each flowchart
|
5
.changeset/stupid-dots-do.md
Normal file
5
.changeset/stupid-dots-do.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: Gantt, Sankey and User Journey diagram are now able to pick font-family from mermaid config.
|
5
.changeset/witty-crews-smell.md
Normal file
5
.changeset/witty-crews-smell.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
`mermaidAPI.getDiagramFromText()` now returns a new different db for each state diagram
|
2
.github/workflows/autofix.yml
vendored
2
.github/workflows/autofix.yml
vendored
@ -42,4 +42,4 @@ jobs:
|
|||||||
working-directory: ./packages/mermaid
|
working-directory: ./packages/mermaid
|
||||||
run: pnpm run docs:build
|
run: pnpm run docs:build
|
||||||
|
|
||||||
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c # main
|
- uses: autofix-ci/action@551dded8c6cc8a1054039c8bc0b8b48c51dfc6ef # main
|
||||||
|
20
.github/workflows/e2e.yml
vendored
20
.github/workflows/e2e.yml
vendored
@ -7,6 +7,9 @@ on:
|
|||||||
- master
|
- master
|
||||||
- release/**
|
- release/**
|
||||||
pull_request:
|
pull_request:
|
||||||
|
issue_comment:
|
||||||
|
types:
|
||||||
|
- created
|
||||||
merge_group:
|
merge_group:
|
||||||
|
|
||||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@ -28,8 +31,12 @@ env:
|
|||||||
) ||
|
) ||
|
||||||
github.event.before
|
github.event.before
|
||||||
}}
|
}}
|
||||||
|
# Check if this is a new comment with '/visual-test'
|
||||||
|
RUN_VISUAL_TEST: >-
|
||||||
|
${{ github.event_name == 'issue_comment' && github.event.action == 'created' && contains(github.event.comment.body, '/visual-test') && github.event.issue.pull_request != null }}
|
||||||
jobs:
|
jobs:
|
||||||
cache:
|
cache:
|
||||||
|
if: ${{ github.event_name != 'issue_comment' || contains(github.event.comment.body, '/visual-test') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
|
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
|
||||||
@ -127,16 +134,17 @@ jobs:
|
|||||||
# e.g. if this action was run from a fork
|
# e.g. if this action was run from a fork
|
||||||
record: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
record: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
||||||
env:
|
env:
|
||||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
# Only set Argos environment variables if the visual test comment trigger is present
|
||||||
VITEST_COVERAGE: true
|
ARGOS_TOKEN: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.ARGOS_TOKEN || '' }}
|
||||||
|
ARGOS_PARALLEL: ${{ env.RUN_VISUAL_TEST == 'true' }}
|
||||||
|
ARGOS_PARALLEL_TOTAL: ${{ env.RUN_VISUAL_TEST == 'true' && strategy.job-total || 1 }}
|
||||||
|
ARGOS_PARALLEL_INDEX: ${{ env.RUN_VISUAL_TEST == 'true' && matrix.containers || 1 }}
|
||||||
CYPRESS_COMMIT: ${{ github.sha }}
|
CYPRESS_COMMIT: ${{ github.sha }}
|
||||||
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
|
CYPRESS_RECORD_KEY: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY || ''}}
|
||||||
ARGOS_PARALLEL: true
|
|
||||||
ARGOS_PARALLEL_TOTAL: ${{ strategy.job-total }}
|
|
||||||
ARGOS_PARALLEL_INDEX: ${{ matrix.containers }}
|
|
||||||
SPLIT: ${{ strategy.job-total }}
|
SPLIT: ${{ strategy.job-total }}
|
||||||
SPLIT_INDEX: ${{ strategy.job-index }}
|
SPLIT_INDEX: ${{ strategy.job-index }}
|
||||||
SPLIT_FILE: 'cypress/timings.json'
|
SPLIT_FILE: 'cypress/timings.json'
|
||||||
|
VITEST_COVERAGE: true
|
||||||
|
|
||||||
- name: Upload Coverage to Codecov
|
- name: Upload Coverage to Codecov
|
||||||
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
|
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
|
||||||
|
2
.github/workflows/scorecard.yml
vendored
2
.github/workflows/scorecard.yml
vendored
@ -26,7 +26,7 @@ jobs:
|
|||||||
results_format: sarif
|
results_format: sarif
|
||||||
publish_results: true
|
publish_results: true
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20
|
uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.pre.node20
|
||||||
with:
|
with:
|
||||||
name: SARIF file
|
name: SARIF file
|
||||||
path: results.sarif
|
path: results.sarif
|
||||||
|
@ -23,7 +23,7 @@ export default eyesPlugin(
|
|||||||
});
|
});
|
||||||
// copy any needed variables from process.env to config.env
|
// copy any needed variables from process.env to config.env
|
||||||
config.env.useAppli = process.env.USE_APPLI ? true : false;
|
config.env.useAppli = process.env.USE_APPLI ? true : false;
|
||||||
config.env.useArgos = !!process.env.CI;
|
config.env.useArgos = !!process.env.CI && !!process.env.ARGOS_TOKEN;
|
||||||
|
|
||||||
if (config.env.useArgos) {
|
if (config.env.useArgos) {
|
||||||
registerArgosTask(on, config, {
|
registerArgosTask(on, config, {
|
||||||
|
@ -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"}
|
||||||
|
`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -78,35 +78,78 @@
|
|||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-size: 72px;
|
font-size: 72px;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tspan {
|
/* tspan {
|
||||||
font-size: 6px !important;
|
font-size: 6px !important;
|
||||||
} */
|
} */
|
||||||
|
/* .flowchart-link {
|
||||||
|
stroke-dasharray: 4, 4 !important;
|
||||||
|
animation: flow 1s linear infinite;
|
||||||
|
animation: dashdraw 4.93282s linear infinite;
|
||||||
|
stroke-width: 2px !important;
|
||||||
|
} */
|
||||||
|
|
||||||
|
@keyframes dashdraw {
|
||||||
|
from {
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*stroke-width:2;stroke-dasharray:10.000000,9.865639;stroke-dashoffset:-198.656393;animation: 4.932820s linear infinite;*/
|
||||||
|
/* stroke-width:2;stroke-dasharray:10.000000,9.865639;stroke-dashoffset:-198.656393;animation: dashdraw 4.932820s linear infinite;*/
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid">
|
||||||
---
|
|
||||||
config:
|
|
||||||
layout: elk
|
|
||||||
---
|
|
||||||
flowchart LR
|
flowchart LR
|
||||||
subgraph S2
|
AB["apa@apa@"] --> B(("`apa@apa`"))
|
||||||
subgraph s1["APA"]
|
|
||||||
D{"Use the editor"}
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
D -- Mermaid js --> I{"fa:fa-code Text"}
|
|
||||||
D --> I
|
|
||||||
D --> I
|
|
||||||
|
|
||||||
end
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<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="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
|
||||||
|
class e1 animate
|
||||||
|
</pre>
|
||||||
|
<h2>infinite</h2>
|
||||||
|
<pre id="diagram4" class="mermaid2">
|
||||||
|
flowchart LR
|
||||||
|
A e1@--> B
|
||||||
|
classDef animate stroke-dasharray: 9\,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||||
|
class e1 animate
|
||||||
|
</pre>
|
||||||
|
<h2>Mermaid - edge-animation-slow</h2>
|
||||||
|
<pre id="diagram4" class="mermaid2">
|
||||||
|
flowchart LR
|
||||||
|
A e1@--> B
|
||||||
|
e1@{ animation: fast}
|
||||||
|
</pre>
|
||||||
|
<h2>Mermaid - edge-animation-fast</h2>
|
||||||
|
<pre id="diagram4" class="mermaid2">
|
||||||
|
flowchart LR
|
||||||
|
A e1@--> B
|
||||||
|
classDef animate stroke-dasharray: 1000,stroke-dashoffset: 1000,animation: dash 10s linear;
|
||||||
|
class e1 edge-animation-fast
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<pre id="diagram4" class="mermaid2">
|
||||||
|
|
||||||
|
info </pre
|
||||||
|
>
|
||||||
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
@ -131,7 +174,7 @@ config:
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
@ -144,7 +187,7 @@ config:
|
|||||||
D-->I
|
D-->I
|
||||||
D-->I
|
D-->I
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
@ -183,7 +226,7 @@ flowchart LR
|
|||||||
n8@{ shape: rect}
|
n8@{ shape: rect}
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
@ -199,7 +242,7 @@ flowchart LR
|
|||||||
|
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
@ -208,7 +251,7 @@ flowchart LR
|
|||||||
A{A} --> B & C
|
A{A} --> B & C
|
||||||
</pre
|
</pre
|
||||||
>
|
>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
@ -220,7 +263,7 @@ flowchart LR
|
|||||||
end
|
end
|
||||||
</pre
|
</pre
|
||||||
>
|
>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
@ -391,7 +434,10 @@ kanban
|
|||||||
window.callback = function () {
|
window.callback = function () {
|
||||||
alert('A callback was triggered');
|
alert('A callback was triggered');
|
||||||
};
|
};
|
||||||
mermaid.initialize({
|
function callback() {
|
||||||
|
alert('It worked');
|
||||||
|
}
|
||||||
|
await mermaid.initialize({
|
||||||
// theme: 'base',
|
// theme: 'base',
|
||||||
// theme: 'default',
|
// theme: 'default',
|
||||||
// theme: 'forest',
|
// theme: 'forest',
|
||||||
@ -403,9 +449,11 @@ kanban
|
|||||||
// layout: 'fixed',
|
// layout: 'fixed',
|
||||||
// htmlLabels: false,
|
// htmlLabels: false,
|
||||||
flowchart: { titleTopMargin: 10 },
|
flowchart: { titleTopMargin: 10 },
|
||||||
|
|
||||||
// fontFamily: 'Caveat',
|
// fontFamily: 'Caveat',
|
||||||
// fontFamily: 'Kalam',
|
// fontFamily: 'Kalam',
|
||||||
// fontFamily: 'courier',
|
// fontFamily: 'courier',
|
||||||
|
fontFamily: 'arial',
|
||||||
sequence: {
|
sequence: {
|
||||||
actorFontFamily: 'courier',
|
actorFontFamily: 'courier',
|
||||||
noteFontFamily: 'courier',
|
noteFontFamily: 'courier',
|
||||||
@ -417,10 +465,9 @@ kanban
|
|||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
logLevel: 0,
|
logLevel: 0,
|
||||||
securityLevel: 'loose',
|
securityLevel: 'loose',
|
||||||
|
callback,
|
||||||
});
|
});
|
||||||
function callback() {
|
|
||||||
alert('It worked');
|
|
||||||
}
|
|
||||||
mermaid.parseError = function (err, hash) {
|
mermaid.parseError = function (err, hash) {
|
||||||
console.error('In parse error:');
|
console.error('In parse error:');
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
@ -62,56 +62,23 @@
|
|||||||
|
|
||||||
<body style="display: flex; gap: 2rem; flex-direction: row">
|
<body style="display: flex; gap: 2rem; flex-direction: row">
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid">
|
||||||
flowchart LR
|
flowchart
|
||||||
A@{ icon: "fa:window-minimize", form: circle }
|
A --> A
|
||||||
E@{ icon: "fa:window-minimize", form: circle }
|
subgraph B
|
||||||
B@{ icon: "fa:bell", form: circle }
|
B1 --> B1
|
||||||
B2@{ icon: "fa:bell", form: circle }
|
end
|
||||||
C@{ icon: "fa:address-book", form: square }
|
subgraph C
|
||||||
D@{ icon: "fa:star-half", form: square }
|
subgraph C1
|
||||||
A --> E
|
C2 --> C2
|
||||||
B --> B2
|
subgraph D
|
||||||
|
D1 --> D1
|
||||||
|
end
|
||||||
|
D --> D
|
||||||
|
end
|
||||||
|
C1 --> C1
|
||||||
|
end
|
||||||
|
|
||||||
</pre>
|
</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">
|
<script type="module">
|
||||||
import mermaid from './mermaid.esm.mjs';
|
import mermaid from './mermaid.esm.mjs';
|
||||||
import layouts from './mermaid-layout-elk.esm.mjs';
|
import layouts from './mermaid-layout-elk.esm.mjs';
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/mermaid/src/rendering-util/types.ts:144](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L144)
|
[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
|
#### Defined in
|
||||||
|
|
||||||
[packages/mermaid/src/rendering-util/types.ts:143](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L143)
|
[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
|
#### Defined in
|
||||||
|
|
||||||
[packages/mermaid/src/rendering-util/types.ts:142](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L142)
|
[packages/mermaid/src/rendering-util/types.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L146)
|
||||||
|
@ -19,4 +19,4 @@ The `parseError` function will not be called.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/mermaid/src/types.ts:59](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L59)
|
[packages/mermaid/src/types.ts:64](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L64)
|
||||||
|
@ -18,7 +18,7 @@ The config passed as YAML frontmatter or directives
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/mermaid/src/types.ts:70](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L70)
|
[packages/mermaid/src/types.ts:75](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L75)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -30,4 +30,4 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/mermaid/src/types.ts:66](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L66)
|
[packages/mermaid/src/types.ts:71](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L71)
|
||||||
|
@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/mermaid/src/types.ts:98](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L98)
|
[packages/mermaid/src/types.ts:103](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L103)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L88)
|
[packages/mermaid/src/types.ts:93](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L93)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -63,4 +63,4 @@ The svg code for the rendered graph.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/mermaid/src/types.ts:84](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L84)
|
[packages/mermaid/src/types.ts:89](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L89)
|
||||||
|
@ -99,8 +99,7 @@ Blogging frameworks and platforms
|
|||||||
- [Nextra](https://nextra.site/)
|
- [Nextra](https://nextra.site/)
|
||||||
- [Mermaid](https://nextra.site/docs/guide/mermaid)
|
- [Mermaid](https://nextra.site/docs/guide/mermaid)
|
||||||
- [WordPress](https://wordpress.org)
|
- [WordPress](https://wordpress.org)
|
||||||
- [WordPress Markdown Editor](https://wordpress.org/plugins/wp-githuber-md)
|
- [MerPRess](https://wordpress.org/plugins/merpress/)
|
||||||
- [WP-ReliableMD](https://wordpress.org/plugins/wp-reliablemd/)
|
|
||||||
|
|
||||||
### CMS/ECM
|
### CMS/ECM
|
||||||
|
|
||||||
|
@ -1183,6 +1183,91 @@ flowchart TB
|
|||||||
B --> D
|
B --> D
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Attaching an ID to Edges
|
||||||
|
|
||||||
|
Mermaid now supports assigning IDs to edges, similar to how IDs and metadata can be attached to nodes. This feature lays the groundwork for more advanced styling, classes, and animation capabilities on edges.
|
||||||
|
|
||||||
|
**Syntax:**
|
||||||
|
|
||||||
|
To give an edge an ID, prepend the edge syntax with the ID followed by an `@` character. For example:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
flowchart LR
|
||||||
|
A e1@–> B
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
A e1@–> B
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, `e1` is the ID of the edge connecting `A` to `B`. You can then use this ID in later definitions or style statements, just like with nodes.
|
||||||
|
|
||||||
|
### Turning an Animation On
|
||||||
|
|
||||||
|
Once you have assigned an ID to an edge, you can turn on animations for that edge by defining the edge’s properties:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
flowchart LR
|
||||||
|
A e1@==> B
|
||||||
|
e1@{ animate: true }
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
A e1@==> B
|
||||||
|
e1@{ animate: true }
|
||||||
|
```
|
||||||
|
|
||||||
|
This tells Mermaid that the edge `e1` should be animated.
|
||||||
|
|
||||||
|
### Selecting Type of Animation
|
||||||
|
|
||||||
|
In the initial version, two animation speeds are supported: `fast` and `slow`. Selecting a specific animation type is a shorthand for enabling animation and setting the animation speed in one go.
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
flowchart LR
|
||||||
|
A e1@–> B
|
||||||
|
e1@{ animation: fast }
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
A e1@–> B
|
||||||
|
e1@{ animation: fast }
|
||||||
|
```
|
||||||
|
|
||||||
|
This is equivalent to `{ animate: true, animation: fast }`.
|
||||||
|
|
||||||
|
### Using classDef Statements for Animations
|
||||||
|
|
||||||
|
You can also animate edges by assigning a class to them and then defining animation properties in a `classDef` statement. For example:
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
flowchart LR
|
||||||
|
A e1@–> B
|
||||||
|
classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||||
|
class e1 animate
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
A e1@–> B
|
||||||
|
classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||||
|
class e1 animate
|
||||||
|
```
|
||||||
|
|
||||||
|
In this snippet:
|
||||||
|
|
||||||
|
- `e1@-->` creates an edge with ID `e1`.
|
||||||
|
- `classDef animate` defines a class named `animate` with styling and animation properties.
|
||||||
|
- `class e1 animate` applies the `animate` class to the edge `e1`.
|
||||||
|
|
||||||
|
**Note on Escaping Commas:**
|
||||||
|
When setting the `stroke-dasharray` property, remember to escape commas as `\,` since commas are used as delimiters in Mermaid’s style definitions.
|
||||||
|
|
||||||
## New arrow types
|
## New arrow types
|
||||||
|
|
||||||
There are new types of arrows supported:
|
There are new types of arrows supported:
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,11 @@
|
|||||||
import { parser } from './parser/classDiagram.jison';
|
import { parser } from './parser/classDiagram.jison';
|
||||||
import classDb from './classDb.js';
|
import { ClassDB } from './classDb.js';
|
||||||
|
|
||||||
describe('class diagram, ', function () {
|
describe('class diagram, ', function () {
|
||||||
describe('when parsing data from a classDiagram it', function () {
|
describe('when parsing data from a classDiagram it', function () {
|
||||||
|
let classDb;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
classDb = new ClassDB();
|
||||||
parser.yy = classDb;
|
parser.yy = classDb;
|
||||||
parser.yy.clear();
|
parser.yy.clear();
|
||||||
});
|
});
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import type { DiagramDefinition } from '../../diagram-api/types.js';
|
import type { DiagramDefinition } from '../../diagram-api/types.js';
|
||||||
// @ts-ignore: JISON doesn't support types
|
// @ts-ignore: JISON doesn't support types
|
||||||
import parser from './parser/classDiagram.jison';
|
import parser from './parser/classDiagram.jison';
|
||||||
import db from './classDb.js';
|
import { ClassDB } from './classDb.js';
|
||||||
import styles from './styles.js';
|
import styles from './styles.js';
|
||||||
import renderer from './classRenderer-v3-unified.js';
|
import renderer from './classRenderer-v3-unified.js';
|
||||||
|
|
||||||
export const diagram: DiagramDefinition = {
|
export const diagram: DiagramDefinition = {
|
||||||
parser,
|
parser,
|
||||||
db,
|
get db() {
|
||||||
|
return new ClassDB();
|
||||||
|
},
|
||||||
renderer,
|
renderer,
|
||||||
styles,
|
styles,
|
||||||
init: (cnf) => {
|
init: (cnf) => {
|
||||||
@ -15,6 +17,5 @@ export const diagram: DiagramDefinition = {
|
|||||||
cnf.class = {};
|
cnf.class = {};
|
||||||
}
|
}
|
||||||
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||||
db.clear();
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/unbound-method -- Broken for Vitest mocks, see https://github.com/vitest-dev/eslint-plugin-vitest/pull/286 */
|
||||||
// @ts-expect-error Jison doesn't export types
|
// @ts-expect-error Jison doesn't export types
|
||||||
import { parser } from './parser/classDiagram.jison';
|
import { parser } from './parser/classDiagram.jison';
|
||||||
import classDb from './classDb.js';
|
import { ClassDB } from './classDb.js';
|
||||||
import { vi, describe, it, expect } from 'vitest';
|
import { vi, describe, it, expect } from 'vitest';
|
||||||
import type { ClassMap, NamespaceNode } from './classTypes.js';
|
import type { ClassMap, NamespaceNode } from './classTypes.js';
|
||||||
const spyOn = vi.spyOn;
|
const spyOn = vi.spyOn;
|
||||||
@ -10,8 +11,9 @@ const abstractCssStyle = 'font-style:italic;';
|
|||||||
|
|
||||||
describe('given a basic class diagram, ', function () {
|
describe('given a basic class diagram, ', function () {
|
||||||
describe('when parsing class definition', function () {
|
describe('when parsing class definition', function () {
|
||||||
|
let classDb: ClassDB;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
classDb.clear();
|
classDb = new ClassDB();
|
||||||
parser.yy = classDb;
|
parser.yy = classDb;
|
||||||
});
|
});
|
||||||
it('should handle classes within namespaces', () => {
|
it('should handle classes within namespaces', () => {
|
||||||
@ -564,8 +566,9 @@ class C13["With Città foreign language"]
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('when parsing class defined in brackets', function () {
|
describe('when parsing class defined in brackets', function () {
|
||||||
|
let classDb: ClassDB;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
classDb.clear();
|
classDb = new ClassDB();
|
||||||
parser.yy = classDb;
|
parser.yy = classDb;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -656,8 +659,9 @@ class C13["With Città foreign language"]
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('when parsing comments', function () {
|
describe('when parsing comments', function () {
|
||||||
|
let classDb: ClassDB;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
classDb.clear();
|
classDb = new ClassDB();
|
||||||
parser.yy = classDb;
|
parser.yy = classDb;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -746,8 +750,9 @@ foo()
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('when parsing click statements', function () {
|
describe('when parsing click statements', function () {
|
||||||
|
let classDb: ClassDB;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
classDb.clear();
|
classDb = new ClassDB();
|
||||||
parser.yy = classDb;
|
parser.yy = classDb;
|
||||||
});
|
});
|
||||||
it('should handle href link', function () {
|
it('should handle href link', function () {
|
||||||
@ -857,8 +862,9 @@ foo()
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('when parsing annotations', function () {
|
describe('when parsing annotations', function () {
|
||||||
|
let classDb: ClassDB;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
classDb.clear();
|
classDb = new ClassDB();
|
||||||
parser.yy = classDb;
|
parser.yy = classDb;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -921,8 +927,9 @@ foo()
|
|||||||
|
|
||||||
describe('given a class diagram with members and methods ', function () {
|
describe('given a class diagram with members and methods ', function () {
|
||||||
describe('when parsing members', function () {
|
describe('when parsing members', function () {
|
||||||
|
let classDb: ClassDB;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
classDb.clear();
|
classDb = new ClassDB();
|
||||||
parser.yy = classDb;
|
parser.yy = classDb;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -980,8 +987,9 @@ describe('given a class diagram with members and methods ', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('when parsing method definition', function () {
|
describe('when parsing method definition', function () {
|
||||||
|
let classDb: ClassDB;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
classDb.clear();
|
classDb = new ClassDB();
|
||||||
parser.yy = classDb;
|
parser.yy = classDb;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1067,8 +1075,9 @@ describe('given a class diagram with members and methods ', function () {
|
|||||||
|
|
||||||
describe('given a class diagram with generics, ', function () {
|
describe('given a class diagram with generics, ', function () {
|
||||||
describe('when parsing valid generic classes', function () {
|
describe('when parsing valid generic classes', function () {
|
||||||
|
let classDb: ClassDB;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
classDb.clear();
|
classDb = new ClassDB();
|
||||||
parser.yy = classDb;
|
parser.yy = classDb;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1180,8 +1189,9 @@ namespace space {
|
|||||||
|
|
||||||
describe('given a class diagram with relationships, ', function () {
|
describe('given a class diagram with relationships, ', function () {
|
||||||
describe('when parsing basic relationships', function () {
|
describe('when parsing basic relationships', function () {
|
||||||
|
let classDb: ClassDB;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
classDb.clear();
|
classDb = new ClassDB();
|
||||||
parser.yy = classDb;
|
parser.yy = classDb;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1714,7 +1724,9 @@ class Class2
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('when parsing classDiagram with text labels', () => {
|
describe('when parsing classDiagram with text labels', () => {
|
||||||
|
let classDb: ClassDB;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
classDb = new ClassDB();
|
||||||
parser.yy = classDb;
|
parser.yy = classDb;
|
||||||
parser.yy.clear();
|
parser.yy.clear();
|
||||||
});
|
});
|
||||||
@ -1897,3 +1909,40 @@ class C13["With Città foreign language"]
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('class db class', () => {
|
||||||
|
let classDb: ClassDB;
|
||||||
|
beforeEach(() => {
|
||||||
|
classDb = new ClassDB();
|
||||||
|
});
|
||||||
|
// This is to ensure that functions used in class JISON are exposed as function from ClassDB
|
||||||
|
it('should have functions used in class JISON as own property', () => {
|
||||||
|
const functionsUsedInParser = [
|
||||||
|
'addRelation',
|
||||||
|
'cleanupLabel',
|
||||||
|
'setAccTitle',
|
||||||
|
'setAccDescription',
|
||||||
|
'addClassesToNamespace',
|
||||||
|
'addNamespace',
|
||||||
|
'setCssClass',
|
||||||
|
'addMembers',
|
||||||
|
'addClass',
|
||||||
|
'setClassLabel',
|
||||||
|
'addAnnotation',
|
||||||
|
'addMember',
|
||||||
|
'addNote',
|
||||||
|
'defineClass',
|
||||||
|
'setDirection',
|
||||||
|
'relationType',
|
||||||
|
'lineType',
|
||||||
|
'setClickEvent',
|
||||||
|
'setTooltip',
|
||||||
|
'setLink',
|
||||||
|
'setCssStyle',
|
||||||
|
] as const satisfies (keyof ClassDB)[];
|
||||||
|
|
||||||
|
for (const fun of functionsUsedInParser) {
|
||||||
|
expect(Object.hasOwn(classDb, fun)).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import type { DiagramDefinition } from '../../diagram-api/types.js';
|
import type { DiagramDefinition } from '../../diagram-api/types.js';
|
||||||
// @ts-ignore: JISON doesn't support types
|
// @ts-ignore: JISON doesn't support types
|
||||||
import parser from './parser/classDiagram.jison';
|
import parser from './parser/classDiagram.jison';
|
||||||
import db from './classDb.js';
|
import { ClassDB } from './classDb.js';
|
||||||
import styles from './styles.js';
|
import styles from './styles.js';
|
||||||
import renderer from './classRenderer-v3-unified.js';
|
import renderer from './classRenderer-v3-unified.js';
|
||||||
|
|
||||||
export const diagram: DiagramDefinition = {
|
export const diagram: DiagramDefinition = {
|
||||||
parser,
|
parser,
|
||||||
db,
|
get db() {
|
||||||
|
return new ClassDB();
|
||||||
|
},
|
||||||
renderer,
|
renderer,
|
||||||
styles,
|
styles,
|
||||||
init: (cnf) => {
|
init: (cnf) => {
|
||||||
@ -15,6 +17,5 @@ export const diagram: DiagramDefinition = {
|
|||||||
cnf.class = {};
|
cnf.class = {};
|
||||||
}
|
}
|
||||||
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||||
db.clear();
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { parser } from './classDiagram.jison';
|
import { parser } from './classDiagram.jison';
|
||||||
import classDb from '../classDb.js';
|
import { ClassDB } from '../classDb.js';
|
||||||
|
|
||||||
describe('class diagram', function () {
|
describe('class diagram', function () {
|
||||||
|
let classDb;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
classDb = new ClassDB();
|
||||||
parser.yy = classDb;
|
parser.yy = classDb;
|
||||||
parser.yy.clear();
|
parser.yy.clear();
|
||||||
});
|
});
|
||||||
|
@ -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']);
|
||||||
@ -65,3 +68,33 @@ describe('flow db addClass', () => {
|
|||||||
expect(classes.get('a')?.styles).toEqual(['stroke-width: 8px']);
|
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
@ -1,14 +1,17 @@
|
|||||||
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';
|
||||||
|
import flowParser from './parser/flowParser.ts';
|
||||||
import flowStyles from './styles.js';
|
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 +23,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,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
setConfig({
|
setConfig({
|
||||||
@ -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,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
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,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
setConfig({
|
setConfig({
|
||||||
@ -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,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
setConfig({
|
setConfig({
|
||||||
@ -39,10 +39,31 @@ const doubleEndedEdges = [
|
|||||||
{ edgeStart: '<==', edgeEnd: '==>', stroke: 'thick', type: 'double_arrow_point' },
|
{ edgeStart: '<==', edgeEnd: '==>', stroke: 'thick', type: 'double_arrow_point' },
|
||||||
{ edgeStart: '<-.', edgeEnd: '.->', stroke: 'dotted', type: 'double_arrow_point' },
|
{ edgeStart: '<-.', edgeEnd: '.->', stroke: 'dotted', type: 'double_arrow_point' },
|
||||||
];
|
];
|
||||||
|
const regularEdges = [
|
||||||
|
{ edgeStart: '--', edgeEnd: '--x', stroke: 'normal', type: 'arrow_cross' },
|
||||||
|
{ edgeStart: '==', edgeEnd: '==x', stroke: 'thick', type: 'arrow_cross' },
|
||||||
|
{ edgeStart: '-.', edgeEnd: '.-x', stroke: 'dotted', type: 'arrow_cross' },
|
||||||
|
{ edgeStart: '--', edgeEnd: '--o', stroke: 'normal', type: 'arrow_circle' },
|
||||||
|
{ edgeStart: '==', edgeEnd: '==o', stroke: 'thick', type: 'arrow_circle' },
|
||||||
|
{ edgeStart: '-.', edgeEnd: '.-o', stroke: 'dotted', type: 'arrow_circle' },
|
||||||
|
{ edgeStart: '--', edgeEnd: '-->', stroke: 'normal', type: 'arrow_point' },
|
||||||
|
{ edgeStart: '==', edgeEnd: '==>', stroke: 'thick', type: 'arrow_point' },
|
||||||
|
{ edgeStart: '-.', edgeEnd: '.->', stroke: 'dotted', type: 'arrow_point' },
|
||||||
|
|
||||||
|
{ edgeStart: '--', edgeEnd: '----x', stroke: 'normal', type: 'arrow_cross' },
|
||||||
|
{ edgeStart: '==', edgeEnd: '====x', stroke: 'thick', type: 'arrow_cross' },
|
||||||
|
{ edgeStart: '-.', edgeEnd: '...-x', stroke: 'dotted', type: 'arrow_cross' },
|
||||||
|
{ edgeStart: '--', edgeEnd: '----o', stroke: 'normal', type: 'arrow_circle' },
|
||||||
|
{ edgeStart: '==', edgeEnd: '====o', stroke: 'thick', type: 'arrow_circle' },
|
||||||
|
{ edgeStart: '-.', edgeEnd: '...-o', stroke: 'dotted', type: 'arrow_circle' },
|
||||||
|
{ edgeStart: '--', edgeEnd: '---->', stroke: 'normal', type: 'arrow_point' },
|
||||||
|
{ edgeStart: '==', edgeEnd: '====>', stroke: 'thick', type: 'arrow_point' },
|
||||||
|
{ edgeStart: '-.', edgeEnd: '...->', stroke: 'dotted', type: 'arrow_point' },
|
||||||
|
];
|
||||||
|
|
||||||
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();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -67,6 +88,74 @@ describe('[Edges] when parsing', () => {
|
|||||||
expect(edges[0].type).toBe('arrow_circle');
|
expect(edges[0].type).toBe('arrow_circle');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('edges with ids', function () {
|
||||||
|
describe('open ended edges with ids and labels', function () {
|
||||||
|
regularEdges.forEach((edgeType) => {
|
||||||
|
it(`should handle ${edgeType.stroke} ${edgeType.type} with no text`, function () {
|
||||||
|
const res = flow.parser.parse(
|
||||||
|
`flowchart TD;\nA e1@${edgeType.edgeStart}${edgeType.edgeEnd} B;`
|
||||||
|
);
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
const edges = flow.parser.yy.getEdges();
|
||||||
|
expect(vert.get('A').id).toBe('A');
|
||||||
|
expect(vert.get('B').id).toBe('B');
|
||||||
|
expect(edges.length).toBe(1);
|
||||||
|
expect(edges[0].id).toBe('e1');
|
||||||
|
expect(edges[0].start).toBe('A');
|
||||||
|
expect(edges[0].end).toBe('B');
|
||||||
|
expect(edges[0].type).toBe(`${edgeType.type}`);
|
||||||
|
expect(edges[0].text).toBe('');
|
||||||
|
expect(edges[0].stroke).toBe(`${edgeType.stroke}`);
|
||||||
|
});
|
||||||
|
it(`should handle ${edgeType.stroke} ${edgeType.type} with text`, function () {
|
||||||
|
const res = flow.parser.parse(
|
||||||
|
`flowchart TD;\nA e1@${edgeType.edgeStart}${edgeType.edgeEnd} B;`
|
||||||
|
);
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
const edges = flow.parser.yy.getEdges();
|
||||||
|
expect(vert.get('A').id).toBe('A');
|
||||||
|
expect(vert.get('B').id).toBe('B');
|
||||||
|
expect(edges.length).toBe(1);
|
||||||
|
expect(edges[0].id).toBe('e1');
|
||||||
|
expect(edges[0].start).toBe('A');
|
||||||
|
expect(edges[0].end).toBe('B');
|
||||||
|
expect(edges[0].type).toBe(`${edgeType.type}`);
|
||||||
|
expect(edges[0].text).toBe('');
|
||||||
|
expect(edges[0].stroke).toBe(`${edgeType.stroke}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should handle normal edges where you also have a node with metadata', function () {
|
||||||
|
const res = flow.parser.parse(`flowchart LR
|
||||||
|
A id1@-->B
|
||||||
|
A@{ shape: 'rect' }
|
||||||
|
`);
|
||||||
|
const edges = flow.parser.yy.getEdges();
|
||||||
|
|
||||||
|
expect(edges[0].id).toBe('id1');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('double ended edges with ids and labels', function () {
|
||||||
|
doubleEndedEdges.forEach((edgeType) => {
|
||||||
|
it(`should handle ${edgeType.stroke} ${edgeType.type} with text`, function () {
|
||||||
|
const res = flow.parser.parse(
|
||||||
|
`flowchart TD;\nA e1@${edgeType.edgeStart} label ${edgeType.edgeEnd} B;`
|
||||||
|
);
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
const edges = flow.parser.yy.getEdges();
|
||||||
|
expect(vert.get('A').id).toBe('A');
|
||||||
|
expect(vert.get('B').id).toBe('B');
|
||||||
|
expect(edges.length).toBe(1);
|
||||||
|
expect(edges[0].id).toBe('e1');
|
||||||
|
expect(edges[0].start).toBe('A');
|
||||||
|
expect(edges[0].end).toBe('B');
|
||||||
|
expect(edges[0].type).toBe(`${edgeType.type}`);
|
||||||
|
expect(edges[0].text).toBe('label');
|
||||||
|
expect(edges[0].stroke).toBe(`${edgeType.stroke}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('edges', function () {
|
describe('edges', function () {
|
||||||
doubleEndedEdges.forEach((edgeType) => {
|
doubleEndedEdges.forEach((edgeType) => {
|
||||||
it(`should handle ${edgeType.stroke} ${edgeType.type} with no text`, function () {
|
it(`should handle ${edgeType.stroke} ${edgeType.type} with no text`, function () {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
setConfig({
|
setConfig({
|
||||||
@ -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,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
import { vi } from 'vitest';
|
import { vi } from 'vitest';
|
||||||
const spyOn = vi.spyOn;
|
const spyOn = vi.spyOn;
|
||||||
@ -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,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
setConfig({
|
setConfig({
|
||||||
@ -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,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
setConfig({
|
setConfig({
|
||||||
@ -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,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
setConfig({
|
setConfig({
|
||||||
@ -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');
|
||||||
});
|
});
|
||||||
@ -251,7 +251,7 @@ describe('when parsing directions', function () {
|
|||||||
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
|
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
|
||||||
expect(data4Layout.nodes[0].label).toEqual('This is a<br/>multiline string');
|
expect(data4Layout.nodes[0].label).toEqual('This is a<br/>multiline string');
|
||||||
});
|
});
|
||||||
it(' should be possible to use } in strings', function () {
|
it('should be possible to use } in strings', function () {
|
||||||
const res = flow.parser.parse(`flowchart TB
|
const res = flow.parser.parse(`flowchart TB
|
||||||
A@{
|
A@{
|
||||||
label: "This is a string with }"
|
label: "This is a string with }"
|
||||||
@ -264,7 +264,7 @@ describe('when parsing directions', function () {
|
|||||||
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
|
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
|
||||||
expect(data4Layout.nodes[0].label).toEqual('This is a string with }');
|
expect(data4Layout.nodes[0].label).toEqual('This is a string with }');
|
||||||
});
|
});
|
||||||
it(' should be possible to use @ in strings', function () {
|
it('should be possible to use @ in strings', function () {
|
||||||
const res = flow.parser.parse(`flowchart TB
|
const res = flow.parser.parse(`flowchart TB
|
||||||
A@{
|
A@{
|
||||||
label: "This is a string with @"
|
label: "This is a string with @"
|
||||||
@ -277,7 +277,7 @@ describe('when parsing directions', function () {
|
|||||||
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
|
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
|
||||||
expect(data4Layout.nodes[0].label).toEqual('This is a string with @');
|
expect(data4Layout.nodes[0].label).toEqual('This is a string with @');
|
||||||
});
|
});
|
||||||
it(' should be possible to use @ in strings', function () {
|
it('should be possible to use @ in strings', function () {
|
||||||
const res = flow.parser.parse(`flowchart TB
|
const res = flow.parser.parse(`flowchart TB
|
||||||
A@{
|
A@{
|
||||||
label: "This is a string with}"
|
label: "This is a string with}"
|
||||||
@ -290,4 +290,126 @@ describe('when parsing directions', function () {
|
|||||||
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
|
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
|
||||||
expect(data4Layout.nodes[0].label).toEqual('This is a string with}');
|
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');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
setConfig({
|
setConfig({
|
||||||
@ -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,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
setConfig({
|
setConfig({
|
||||||
@ -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,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
setConfig({
|
setConfig({
|
||||||
@ -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,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
setConfig({
|
setConfig({
|
||||||
@ -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');
|
||||||
});
|
});
|
||||||
|
@ -141,6 +141,7 @@ that id.
|
|||||||
.*direction\s+RL[^\n]* return 'direction_rl';
|
.*direction\s+RL[^\n]* return 'direction_rl';
|
||||||
.*direction\s+LR[^\n]* return 'direction_lr';
|
.*direction\s+LR[^\n]* return 'direction_lr';
|
||||||
|
|
||||||
|
[^\s\"]+\@(?=[^\{\"]) { return 'LINK_ID'; }
|
||||||
[0-9]+ return 'NUM';
|
[0-9]+ return 'NUM';
|
||||||
\# return 'BRKT';
|
\# return 'BRKT';
|
||||||
":::" return 'STYLE_SEPARATOR';
|
":::" return 'STYLE_SEPARATOR';
|
||||||
@ -201,7 +202,9 @@ that id.
|
|||||||
"*" return 'MULT';
|
"*" return 'MULT';
|
||||||
"#" return 'BRKT';
|
"#" return 'BRKT';
|
||||||
"&" return 'AMP';
|
"&" return 'AMP';
|
||||||
([A-Za-z0-9!"\#$%&'*+\.`?\\_\/]|\-(?=[^\>\-\.])|=(?!=))+ return 'NODE_STRING';
|
([A-Za-z0-9!"\#$%&'*+\.`?\\_\/]|\-(?=[^\>\-\.])|=(?!=))+ {
|
||||||
|
return 'NODE_STRING';
|
||||||
|
}
|
||||||
"-" return 'MINUS'
|
"-" return 'MINUS'
|
||||||
[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|
|
[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|
|
||||||
[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|
|
[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|
|
||||||
@ -361,7 +364,7 @@ spaceList
|
|||||||
|
|
||||||
statement
|
statement
|
||||||
: vertexStatement separator
|
: vertexStatement separator
|
||||||
{ /* console.warn('finat vs', $vertexStatement.nodes); */ $$=$vertexStatement.nodes}
|
{ $$=$vertexStatement.nodes}
|
||||||
| styleStatement separator
|
| styleStatement separator
|
||||||
{$$=[];}
|
{$$=[];}
|
||||||
| linkStyleStatement separator
|
| linkStyleStatement separator
|
||||||
@ -396,7 +399,7 @@ shapeData:
|
|||||||
;
|
;
|
||||||
|
|
||||||
vertexStatement: vertexStatement link node 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
|
| vertexStatement link node
|
||||||
{ /*console.warn('vs',$vertexStatement.stmt,$node);*/ yy.addLink($vertexStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($vertexStatement.nodes) } }
|
{ /*console.warn('vs',$vertexStatement.stmt,$node);*/ yy.addLink($vertexStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($vertexStatement.nodes) } }
|
||||||
| vertexStatement link node spaceList
|
| vertexStatement link node spaceList
|
||||||
@ -404,7 +407,7 @@ vertexStatement: vertexStatement link node shapeData
|
|||||||
|node spaceList { /*console.warn('vertexStatement: node spaceList', $node);*/ $$ = {stmt: $node, nodes:$node }}
|
|node spaceList { /*console.warn('vertexStatement: node spaceList', $node);*/ $$ = {stmt: $node, nodes:$node }}
|
||||||
|node shapeData {
|
|node shapeData {
|
||||||
/*console.warn('vertexStatement: node shapeData', $node[0], $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}
|
$$ = {stmt: $node, nodes:$node, shapeData: $shapeData}
|
||||||
}
|
}
|
||||||
|node { /* console.warn('vertexStatement: single node', $node); */ $$ = {stmt: $node, nodes:$node }}
|
|node { /* console.warn('vertexStatement: single node', $node); */ $$ = {stmt: $node, nodes:$node }}
|
||||||
@ -413,7 +416,7 @@ vertexStatement: vertexStatement link node shapeData
|
|||||||
node: styledVertex
|
node: styledVertex
|
||||||
{ /*console.warn('nod', $styledVertex);*/ $$ = [$styledVertex];}
|
{ /*console.warn('nod', $styledVertex);*/ $$ = [$styledVertex];}
|
||||||
| node shapeData spaceList AMP spaceList 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 spaceList AMP spaceList styledVertex
|
||||||
{ $$ = $node.concat($styledVertex); /*console.warn('pip', $node[0], $styledVertex, $$);*/ }
|
{ $$ = $node.concat($styledVertex); /*console.warn('pip', $node[0], $styledVertex, $$);*/ }
|
||||||
;
|
;
|
||||||
@ -472,6 +475,8 @@ link: linkStatement arrowText
|
|||||||
{$$ = $linkStatement;}
|
{$$ = $linkStatement;}
|
||||||
| START_LINK edgeText LINK
|
| START_LINK edgeText LINK
|
||||||
{var inf = yy.destructLink($LINK, $START_LINK); $$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length,"text":$edgeText};}
|
{var inf = yy.destructLink($LINK, $START_LINK); $$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length,"text":$edgeText};}
|
||||||
|
| LINK_ID START_LINK edgeText LINK
|
||||||
|
{var inf = yy.destructLink($LINK, $START_LINK); $$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length,"text":$edgeText, "id": $LINK_ID};}
|
||||||
;
|
;
|
||||||
|
|
||||||
edgeText: edgeTextToken
|
edgeText: edgeTextToken
|
||||||
@ -487,6 +492,8 @@ edgeText: edgeTextToken
|
|||||||
|
|
||||||
linkStatement: LINK
|
linkStatement: LINK
|
||||||
{var inf = yy.destructLink($LINK);$$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length};}
|
{var inf = yy.destructLink($LINK);$$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length};}
|
||||||
|
| LINK_ID LINK
|
||||||
|
{var inf = yy.destructLink($LINK);$$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length, "id": $LINK_ID};}
|
||||||
;
|
;
|
||||||
|
|
||||||
arrowText:
|
arrowText:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
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();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
12
packages/mermaid/src/diagrams/flowchart/parser/flowParser.ts
Normal file
12
packages/mermaid/src/diagrams/flowchart/parser/flowParser.ts
Normal 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;
|
@ -1,5 +1,5 @@
|
|||||||
import flowDb from '../flowDb.js';
|
import { FlowDB } from '../flowDb.js';
|
||||||
import flow from './flow.jison';
|
import flow from './flowParser.ts';
|
||||||
import { setConfig } from '../../../config.js';
|
import { setConfig } from '../../../config.js';
|
||||||
|
|
||||||
setConfig({
|
setConfig({
|
||||||
@ -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');
|
||||||
});
|
});
|
||||||
|
@ -53,6 +53,7 @@ export interface FlowText {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface FlowEdge {
|
export interface FlowEdge {
|
||||||
|
isUserDefinedId: boolean;
|
||||||
start: string;
|
start: string;
|
||||||
end: string;
|
end: string;
|
||||||
interpolate?: string;
|
interpolate?: string;
|
||||||
@ -62,6 +63,10 @@ export interface FlowEdge {
|
|||||||
length?: number;
|
length?: number;
|
||||||
text: string;
|
text: string;
|
||||||
labelType: 'text';
|
labelType: 'text';
|
||||||
|
classes: string[];
|
||||||
|
id?: string;
|
||||||
|
animation?: 'fast' | 'slow';
|
||||||
|
animate?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FlowClass {
|
export interface FlowClass {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const getStyles = (options) =>
|
const getStyles = (options) =>
|
||||||
`
|
`
|
||||||
.mermaid-main-font {
|
.mermaid-main-font {
|
||||||
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
font-family: ${options.fontFamily};
|
||||||
}
|
}
|
||||||
|
|
||||||
.exclude-range {
|
.exclude-range {
|
||||||
@ -45,7 +45,7 @@ const getStyles = (options) =>
|
|||||||
|
|
||||||
.sectionTitle {
|
.sectionTitle {
|
||||||
text-anchor: start;
|
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 {
|
.taskText {
|
||||||
text-anchor: middle;
|
text-anchor: middle;
|
||||||
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
font-family: ${options.fontFamily};
|
||||||
}
|
}
|
||||||
|
|
||||||
.taskTextOutsideRight {
|
.taskTextOutsideRight {
|
||||||
fill: ${options.taskTextDarkColor};
|
fill: ${options.taskTextDarkColor};
|
||||||
text-anchor: start;
|
text-anchor: start;
|
||||||
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
font-family: ${options.fontFamily};
|
||||||
}
|
}
|
||||||
|
|
||||||
.taskTextOutsideLeft {
|
.taskTextOutsideLeft {
|
||||||
@ -248,7 +248,7 @@ const getStyles = (options) =>
|
|||||||
text-anchor: middle;
|
text-anchor: middle;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
fill: ${options.titleColor || options.textColor};
|
fill: ${options.titleColor || options.textColor};
|
||||||
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
font-family: ${options.fontFamily};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -4,11 +4,13 @@ import parser from './parser/sankey.jison';
|
|||||||
import db from './sankeyDB.js';
|
import db from './sankeyDB.js';
|
||||||
import renderer from './sankeyRenderer.js';
|
import renderer from './sankeyRenderer.js';
|
||||||
import { prepareTextForParsing } from './sankeyUtils.js';
|
import { prepareTextForParsing } from './sankeyUtils.js';
|
||||||
|
import sankeyStyles from './styles.js';
|
||||||
|
|
||||||
const originalParse = parser.parse.bind(parser);
|
const originalParse = parser.parse.bind(parser);
|
||||||
parser.parse = (text: string) => originalParse(prepareTextForParsing(text));
|
parser.parse = (text: string) => originalParse(prepareTextForParsing(text));
|
||||||
|
|
||||||
export const diagram: DiagramDefinition = {
|
export const diagram: DiagramDefinition = {
|
||||||
|
styles: sankeyStyles,
|
||||||
parser,
|
parser,
|
||||||
db,
|
db,
|
||||||
renderer,
|
renderer,
|
||||||
|
@ -136,7 +136,6 @@ export const draw = function (text: string, id: string, _version: string, diagOb
|
|||||||
svg
|
svg
|
||||||
.append('g')
|
.append('g')
|
||||||
.attr('class', 'node-labels')
|
.attr('class', 'node-labels')
|
||||||
.attr('font-family', 'sans-serif')
|
|
||||||
.attr('font-size', 14)
|
.attr('font-size', 14)
|
||||||
.selectAll('text')
|
.selectAll('text')
|
||||||
.data(graph.nodes)
|
.data(graph.nodes)
|
||||||
|
6
packages/mermaid/src/diagrams/sankey/styles.js
Normal file
6
packages/mermaid/src/diagrams/sankey/styles.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
const getStyles = (options) =>
|
||||||
|
`.label {
|
||||||
|
font-family: ${options.fontFamily};
|
||||||
|
}`;
|
||||||
|
|
||||||
|
export default getStyles;
|
@ -15,6 +15,5 @@ export const diagram: DiagramDefinition = {
|
|||||||
cnf.state = {};
|
cnf.state = {};
|
||||||
}
|
}
|
||||||
cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||||
db.clear();
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -15,6 +15,5 @@ export const diagram: DiagramDefinition = {
|
|||||||
cnf.state = {};
|
cnf.state = {};
|
||||||
}
|
}
|
||||||
cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||||
db.clear();
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
const getStyles = (options) =>
|
const getStyles = (options) =>
|
||||||
`.label {
|
`.label {
|
||||||
font-family: 'trebuchet ms', verdana, arial, sans-serif;
|
font-family: ${options.fontFamily};
|
||||||
font-family: var(--mermaid-font-family);
|
|
||||||
color: ${options.textColor};
|
color: ${options.textColor};
|
||||||
}
|
}
|
||||||
.mouth {
|
.mouth {
|
||||||
@ -79,8 +78,7 @@ const getStyles = (options) =>
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
font-family: 'trebuchet ms', verdana, arial, sans-serif;
|
font-family: ${options.fontFamily};
|
||||||
font-family: var(--mermaid-font-family);
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
background: ${options.tertiaryColor};
|
background: ${options.tertiaryColor};
|
||||||
border: 1px solid ${options.border2};
|
border: 1px solid ${options.border2};
|
||||||
|
@ -94,8 +94,7 @@ Blogging frameworks and platforms
|
|||||||
- [Nextra](https://nextra.site/)
|
- [Nextra](https://nextra.site/)
|
||||||
- [Mermaid](https://nextra.site/docs/guide/mermaid)
|
- [Mermaid](https://nextra.site/docs/guide/mermaid)
|
||||||
- [WordPress](https://wordpress.org)
|
- [WordPress](https://wordpress.org)
|
||||||
- [WordPress Markdown Editor](https://wordpress.org/plugins/wp-githuber-md)
|
- [MerPRess](https://wordpress.org/plugins/merpress/)
|
||||||
- [WP-ReliableMD](https://wordpress.org/plugins/wp-reliablemd/)
|
|
||||||
|
|
||||||
### CMS/ECM
|
### CMS/ECM
|
||||||
|
|
||||||
|
@ -711,6 +711,67 @@ flowchart TB
|
|||||||
B --> D
|
B --> D
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Attaching an ID to Edges
|
||||||
|
|
||||||
|
Mermaid now supports assigning IDs to edges, similar to how IDs and metadata can be attached to nodes. This feature lays the groundwork for more advanced styling, classes, and animation capabilities on edges.
|
||||||
|
|
||||||
|
**Syntax:**
|
||||||
|
|
||||||
|
To give an edge an ID, prepend the edge syntax with the ID followed by an `@` character. For example:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
A e1@–> B
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, `e1` is the ID of the edge connecting `A` to `B`. You can then use this ID in later definitions or style statements, just like with nodes.
|
||||||
|
|
||||||
|
### Turning an Animation On
|
||||||
|
|
||||||
|
Once you have assigned an ID to an edge, you can turn on animations for that edge by defining the edge’s properties:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
A e1@==> B
|
||||||
|
e1@{ animate: true }
|
||||||
|
```
|
||||||
|
|
||||||
|
This tells Mermaid that the edge `e1` should be animated.
|
||||||
|
|
||||||
|
### Selecting Type of Animation
|
||||||
|
|
||||||
|
In the initial version, two animation speeds are supported: `fast` and `slow`. Selecting a specific animation type is a shorthand for enabling animation and setting the animation speed in one go.
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
A e1@–> B
|
||||||
|
e1@{ animation: fast }
|
||||||
|
```
|
||||||
|
|
||||||
|
This is equivalent to `{ animate: true, animation: fast }`.
|
||||||
|
|
||||||
|
### Using classDef Statements for Animations
|
||||||
|
|
||||||
|
You can also animate edges by assigning a class to them and then defining animation properties in a `classDef` statement. For example:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
A e1@–> B
|
||||||
|
classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||||
|
class e1 animate
|
||||||
|
```
|
||||||
|
|
||||||
|
In this snippet:
|
||||||
|
|
||||||
|
- `e1@-->` creates an edge with ID `e1`.
|
||||||
|
- `classDef animate` defines a class named `animate` with styling and animation properties.
|
||||||
|
- `class e1 animate` applies the `animate` class to the edge `e1`.
|
||||||
|
|
||||||
|
**Note on Escaping Commas:**
|
||||||
|
When setting the `stroke-dasharray` property, remember to escape commas as `\,` since commas are used as delimiters in Mermaid’s style definitions.
|
||||||
|
|
||||||
## New arrow types
|
## New arrow types
|
||||||
|
|
||||||
There are new types of arrows supported:
|
There are new types of arrows supported:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
import { assert, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
// Mocks and mocking
|
// Mocks and mocking
|
||||||
@ -69,6 +69,8 @@ import { compile, serialize } from 'stylis';
|
|||||||
import { Diagram } from './Diagram.js';
|
import { Diagram } from './Diagram.js';
|
||||||
import { decodeEntities, encodeEntities } from './utils.js';
|
import { decodeEntities, encodeEntities } from './utils.js';
|
||||||
import { toBase64 } from './utils/base64.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
|
* @see https://vitest.dev/guide/mocking.html Mock part of a module
|
||||||
@ -832,5 +834,93 @@ graph TD;A--x|text including URL space|B;`)
|
|||||||
expect(diagram).toBeInstanceOf(Diagram);
|
expect(diagram).toBeInstanceOf(Diagram);
|
||||||
expect(diagram.type).toBe('flowchart-v2');
|
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 flowDiagram2 = 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(flowDiagram2.db);
|
||||||
|
assert(flowDiagram1.db instanceof FlowDB);
|
||||||
|
assert(flowDiagram2.db instanceof FlowDB);
|
||||||
|
expect(flowDiagram1.db.getDirection()).not.toEqual(flowDiagram2.db.getDirection());
|
||||||
|
|
||||||
|
const classDiagram1 = await mermaidAPI.getDiagramFromText(
|
||||||
|
`classDiagram
|
||||||
|
direction TB
|
||||||
|
class Student {
|
||||||
|
-idCard : IdCard
|
||||||
|
}
|
||||||
|
class IdCard{
|
||||||
|
-id : int
|
||||||
|
-name : string
|
||||||
|
}
|
||||||
|
class Bike{
|
||||||
|
-id : int
|
||||||
|
-name : string
|
||||||
|
}
|
||||||
|
Student "1" --o "1" IdCard : carries
|
||||||
|
Student "1" --o "1" Bike : rides`
|
||||||
|
);
|
||||||
|
const classDiagram2 = await mermaidAPI.getDiagramFromText(
|
||||||
|
`classDiagram
|
||||||
|
direction LR
|
||||||
|
class Student {
|
||||||
|
-idCard : IdCard
|
||||||
|
}
|
||||||
|
class IdCard{
|
||||||
|
-id : int
|
||||||
|
-name : string
|
||||||
|
}
|
||||||
|
class Bike{
|
||||||
|
-id : int
|
||||||
|
-name : string
|
||||||
|
}
|
||||||
|
Student "1" --o "1" IdCard : carries
|
||||||
|
Student "1" --o "1" Bike : rides`
|
||||||
|
);
|
||||||
|
// Since classDiagram will return new Db object each time, we can compare the db to be different.
|
||||||
|
expect(classDiagram1.db).not.toBe(classDiagram2.db);
|
||||||
|
assert(classDiagram1.db instanceof ClassDB);
|
||||||
|
assert(classDiagram2.db instanceof ClassDB);
|
||||||
|
expect(classDiagram1.db.getDirection()).not.toEqual(classDiagram2.db.getDirection());
|
||||||
|
|
||||||
|
const sequenceDiagram1 = await mermaidAPI.getDiagramFromText(
|
||||||
|
`sequenceDiagram
|
||||||
|
Alice->>+John: Hello John, how are you?
|
||||||
|
Alice->>+John: John, can you hear me?
|
||||||
|
John-->>-Alice: Hi Alice, I can hear you!
|
||||||
|
John-->>-Alice: I feel great!`
|
||||||
|
);
|
||||||
|
const sequenceDiagram2 = await mermaidAPI.getDiagramFromText(
|
||||||
|
`sequenceDiagram
|
||||||
|
Alice->>+John: Hello John, how are you?
|
||||||
|
Alice->>+John: John, can you hear me?
|
||||||
|
John-->>-Alice: Hi Alice, I can hear you!
|
||||||
|
John-->>-Alice: I feel great!`
|
||||||
|
);
|
||||||
|
// Since sequenceDiagram will return same Db object each time, we can compare the db to be same.
|
||||||
|
expect(sequenceDiagram1.db).toBe(sequenceDiagram2.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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -9,6 +9,7 @@ import { curveBasis, line, select } from 'd3';
|
|||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import createLabel from './createLabel.js';
|
import createLabel from './createLabel.js';
|
||||||
import { addEdgeMarkers } from './edgeMarker.ts';
|
import { addEdgeMarkers } from './edgeMarker.ts';
|
||||||
|
import { isLabelStyle } from './shapes/handDrawnShapeStyles.js';
|
||||||
|
|
||||||
const edgeLabels = new Map();
|
const edgeLabels = new Map();
|
||||||
const terminalLabels = new Map();
|
const terminalLabels = new Map();
|
||||||
@ -428,6 +429,13 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
|||||||
let pointsHasChanged = false;
|
let pointsHasChanged = false;
|
||||||
const tail = startNode;
|
const tail = startNode;
|
||||||
var head = endNode;
|
var head = endNode;
|
||||||
|
const edgeClassStyles = [];
|
||||||
|
for (const key in edge.cssCompiledStyles) {
|
||||||
|
if (isLabelStyle(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
edgeClassStyles.push(edge.cssCompiledStyles[key]);
|
||||||
|
}
|
||||||
|
|
||||||
if (head.intersect && tail.intersect) {
|
if (head.intersect && tail.intersect) {
|
||||||
points = points.slice(1, edge.points.length - 1);
|
points = points.slice(1, edge.points.length - 1);
|
||||||
@ -501,6 +509,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
|||||||
let svgPath;
|
let svgPath;
|
||||||
let linePath = lineFunction(lineData);
|
let linePath = lineFunction(lineData);
|
||||||
const edgeStyles = Array.isArray(edge.style) ? edge.style : [edge.style];
|
const edgeStyles = Array.isArray(edge.style) ? edge.style : [edge.style];
|
||||||
|
|
||||||
if (edge.look === 'handDrawn') {
|
if (edge.look === 'handDrawn') {
|
||||||
const rc = rough.svg(elem);
|
const rc = rough.svg(elem);
|
||||||
Object.assign([], lineData);
|
Object.assign([], lineData);
|
||||||
@ -521,12 +530,27 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
|||||||
svgPath.attr('d', d);
|
svgPath.attr('d', d);
|
||||||
elem.node().appendChild(svgPath.node());
|
elem.node().appendChild(svgPath.node());
|
||||||
} else {
|
} else {
|
||||||
|
const stylesFromClasses = edgeClassStyles.join(';');
|
||||||
|
const styles = edgeStyles ? edgeStyles.reduce((acc, style) => acc + style + ';', '') : '';
|
||||||
|
let animationClass = '';
|
||||||
|
if (edge.animate) {
|
||||||
|
animationClass = ' edge-animation-fast';
|
||||||
|
}
|
||||||
|
if (edge.animation) {
|
||||||
|
animationClass = ' edge-animation-' + edge.animation;
|
||||||
|
}
|
||||||
svgPath = elem
|
svgPath = elem
|
||||||
.append('path')
|
.append('path')
|
||||||
.attr('d', linePath)
|
.attr('d', linePath)
|
||||||
.attr('id', edge.id)
|
.attr('id', edge.id)
|
||||||
.attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : ''))
|
.attr(
|
||||||
.attr('style', edgeStyles ? edgeStyles.reduce((acc, style) => acc + ';' + style, '') : '');
|
'class',
|
||||||
|
' ' +
|
||||||
|
strokeClasses +
|
||||||
|
(edge.classes ? ' ' + edge.classes : '') +
|
||||||
|
(animationClass ? animationClass : '')
|
||||||
|
)
|
||||||
|
.attr('style', stylesFromClasses ? stylesFromClasses + ';' + styles + ';' : styles);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEBUG code, DO NOT REMOVE
|
// DEBUG code, DO NOT REMOVE
|
||||||
|
@ -32,7 +32,28 @@ export const styles2Map = (styles: string[]) => {
|
|||||||
});
|
});
|
||||||
return styleMap;
|
return styleMap;
|
||||||
};
|
};
|
||||||
|
export const isLabelStyle = (key: string) => {
|
||||||
|
return (
|
||||||
|
key === 'color' ||
|
||||||
|
key === 'font-size' ||
|
||||||
|
key === 'font-family' ||
|
||||||
|
key === 'font-weight' ||
|
||||||
|
key === 'font-style' ||
|
||||||
|
key === 'text-decoration' ||
|
||||||
|
key === 'text-align' ||
|
||||||
|
key === 'text-transform' ||
|
||||||
|
key === 'line-height' ||
|
||||||
|
key === 'letter-spacing' ||
|
||||||
|
key === 'word-spacing' ||
|
||||||
|
key === 'text-shadow' ||
|
||||||
|
key === 'text-overflow' ||
|
||||||
|
key === 'white-space' ||
|
||||||
|
key === 'word-wrap' ||
|
||||||
|
key === 'word-break' ||
|
||||||
|
key === 'overflow-wrap' ||
|
||||||
|
key === 'hyphens'
|
||||||
|
);
|
||||||
|
};
|
||||||
export const styles2String = (node: Node) => {
|
export const styles2String = (node: Node) => {
|
||||||
const { stylesArray } = compileStyles(node);
|
const { stylesArray } = compileStyles(node);
|
||||||
const labelStyles: string[] = [];
|
const labelStyles: string[] = [];
|
||||||
@ -42,26 +63,7 @@ export const styles2String = (node: Node) => {
|
|||||||
|
|
||||||
stylesArray.forEach((style) => {
|
stylesArray.forEach((style) => {
|
||||||
const key = style[0];
|
const key = style[0];
|
||||||
if (
|
if (isLabelStyle(key)) {
|
||||||
key === 'color' ||
|
|
||||||
key === 'font-size' ||
|
|
||||||
key === 'font-family' ||
|
|
||||||
key === 'font-weight' ||
|
|
||||||
key === 'font-style' ||
|
|
||||||
key === 'text-decoration' ||
|
|
||||||
key === 'text-align' ||
|
|
||||||
key === 'text-transform' ||
|
|
||||||
key === 'line-height' ||
|
|
||||||
key === 'letter-spacing' ||
|
|
||||||
key === 'word-spacing' ||
|
|
||||||
key === 'text-shadow' ||
|
|
||||||
key === 'text-overflow' ||
|
|
||||||
key === 'white-space' ||
|
|
||||||
key === 'word-wrap' ||
|
|
||||||
key === 'word-break' ||
|
|
||||||
key === 'overflow-wrap' ||
|
|
||||||
key === 'hyphens'
|
|
||||||
) {
|
|
||||||
labelStyles.push(style.join(':') + ' !important');
|
labelStyles.push(style.join(':') + ' !important');
|
||||||
} else {
|
} else {
|
||||||
nodeStyles.push(style.join(':') + ' !important');
|
nodeStyles.push(style.join(':') + ' !important');
|
||||||
|
@ -96,11 +96,14 @@ export interface Edge {
|
|||||||
label?: string;
|
label?: string;
|
||||||
classes?: string;
|
classes?: string;
|
||||||
style?: string[];
|
style?: string[];
|
||||||
|
animate?: boolean;
|
||||||
|
animation?: 'fast' | 'slow';
|
||||||
// Properties common to both Flowchart and State Diagram edges
|
// Properties common to both Flowchart and State Diagram edges
|
||||||
arrowhead?: string;
|
arrowhead?: string;
|
||||||
arrowheadStyle?: string;
|
arrowheadStyle?: string;
|
||||||
arrowTypeEnd?: string;
|
arrowTypeEnd?: string;
|
||||||
arrowTypeStart?: string;
|
arrowTypeStart?: string;
|
||||||
|
cssCompiledStyles?: string[];
|
||||||
// Flowchart specific properties
|
// Flowchart specific properties
|
||||||
defaultInterpolate?: string;
|
defaultInterpolate?: string;
|
||||||
end?: string;
|
end?: string;
|
||||||
@ -122,6 +125,7 @@ export interface Edge {
|
|||||||
pattern?: string;
|
pattern?: string;
|
||||||
thickness?: 'normal' | 'thick' | 'invisible' | 'dotted';
|
thickness?: 'normal' | 'thick' | 'invisible' | 'dotted';
|
||||||
look?: string;
|
look?: string;
|
||||||
|
isUserDefinedId?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RectOptions {
|
export interface RectOptions {
|
||||||
|
@ -27,7 +27,28 @@ const getStyles = (
|
|||||||
font-size: ${options.fontSize};
|
font-size: ${options.fontSize};
|
||||||
fill: ${options.textColor}
|
fill: ${options.textColor}
|
||||||
}
|
}
|
||||||
|
@keyframes edge-animation-frame {
|
||||||
|
from {
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes dash {
|
||||||
|
to {
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& .edge-animation-slow {
|
||||||
|
stroke-dasharray: 9,5 !important;
|
||||||
|
stroke-dashoffset: 900;
|
||||||
|
animation: dash 50s linear infinite;
|
||||||
|
stroke-linecap: round;
|
||||||
|
}
|
||||||
|
& .edge-animation-fast {
|
||||||
|
stroke-dasharray: 9,5 !important;
|
||||||
|
stroke-dashoffset: 900;
|
||||||
|
animation: dash 20s linear infinite;
|
||||||
|
stroke-linecap: round;
|
||||||
|
}
|
||||||
/* Classes common for multiple diagrams */
|
/* Classes common for multiple diagrams */
|
||||||
|
|
||||||
& .error-icon {
|
& .error-icon {
|
||||||
|
@ -12,6 +12,11 @@ export interface NodeMetaData {
|
|||||||
assigned?: string;
|
assigned?: string;
|
||||||
ticket?: string;
|
ticket?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface EdgeMetaData {
|
||||||
|
animation?: 'fast' | 'slow';
|
||||||
|
animate?: boolean;
|
||||||
|
}
|
||||||
import type { MermaidConfig } from './config.type.js';
|
import type { MermaidConfig } from './config.type.js';
|
||||||
|
|
||||||
export interface Point {
|
export interface Point {
|
||||||
|
@ -937,8 +937,12 @@ export const getEdgeId = (
|
|||||||
counter?: number;
|
counter?: number;
|
||||||
prefix?: string;
|
prefix?: string;
|
||||||
suffix?: string;
|
suffix?: string;
|
||||||
}
|
},
|
||||||
|
id?: string
|
||||||
) => {
|
) => {
|
||||||
|
if (id) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
return `${prefix ? `${prefix}_` : ''}${from}_${to}_${counter}${suffix ? `_${suffix}` : ''}`;
|
return `${prefix ? `${prefix}_` : ''}${from}_${to}_${counter}${suffix ? `_${suffix}` : ''}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
3062
pnpm-lock.yaml
generated
3062
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user