mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-28 11:49:37 +02:00
Compare commits
329 Commits
d782e4bb17
...
renovate/p
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a33d7df0b2 | ||
![]() |
7effdc147b | ||
![]() |
6e67515f41 | ||
![]() |
d5c4eff251 | ||
![]() |
5324fd8dfd | ||
![]() |
37e3a6951b | ||
![]() |
0de0b063e4 | ||
![]() |
619515e5a9 | ||
![]() |
59c8b07509 | ||
![]() |
9e72bbf62d | ||
![]() |
2a2c46f1e2 | ||
![]() |
f25df353d4 | ||
![]() |
398345a8bc | ||
![]() |
7fd2d94ef7 | ||
![]() |
bcc1472b9d | ||
![]() |
ddc1cfe6c8 | ||
![]() |
18e9c1174d | ||
![]() |
789018abf6 | ||
![]() |
16569b295b | ||
![]() |
11a35c11ee | ||
![]() |
216be22801 | ||
![]() |
e87f77a865 | ||
![]() |
a9579083bf | ||
![]() |
6fd78d0856 | ||
![]() |
994f7df29a | ||
![]() |
531f5e9380 | ||
![]() |
dc11b8645c | ||
![]() |
ad4c227477 | ||
![]() |
181af8167b | ||
![]() |
799d2ed547 | ||
![]() |
a44e3e992c | ||
![]() |
ca5b370ffb | ||
![]() |
08160a74b4 | ||
![]() |
6d221fb3ca | ||
![]() |
8b20907141 | ||
![]() |
d318f1a13c | ||
![]() |
525a7de8ae | ||
![]() |
a459c436c9 | ||
![]() |
1c2a0020bd | ||
![]() |
141c6b3808 | ||
![]() |
8d4ffdf808 | ||
![]() |
32106e259c | ||
![]() |
450754221e | ||
![]() |
7a4f5b62c9 | ||
![]() |
b36edd557e | ||
![]() |
5e3b5e8f36 | ||
![]() |
764b315dc1 | ||
![]() |
47c0d2d040 | ||
![]() |
ac3b777bf6 | ||
![]() |
cf08ba0ef8 | ||
![]() |
166782cd38 | ||
![]() |
b37eb6d0d1 | ||
![]() |
f759f5dcf7 | ||
![]() |
80bcefe321 | ||
![]() |
70cbbe69d8 | ||
![]() |
baf4093e8d | ||
![]() |
fd185f7694 | ||
![]() |
027d7b6368 | ||
![]() |
7986b66a88 | ||
![]() |
edb0edc451 | ||
![]() |
b511a2e9be | ||
![]() |
4829dfa8c5 | ||
![]() |
b80ea26a2b | ||
![]() |
f88986a87d | ||
![]() |
e16f0848ab | ||
![]() |
e7811886c3 | ||
![]() |
32eda8565c | ||
![]() |
2812a0d12a | ||
![]() |
25fa26d915 | ||
![]() |
62915183b1 | ||
![]() |
6874ab3fb6 | ||
![]() |
040af4f545 | ||
![]() |
65ca3eabfd | ||
![]() |
8b9bbad842 | ||
![]() |
d2773db7dc | ||
![]() |
3840451fda | ||
![]() |
cfe9238882 | ||
![]() |
9c85521e16 | ||
![]() |
8a565bce92 | ||
![]() |
baf510b935 | ||
![]() |
c1f2d052be | ||
![]() |
bce40e180a | ||
![]() |
0dd46a3543 | ||
![]() |
f81e63663c | ||
![]() |
7109e3a17f | ||
![]() |
e0bd51941e | ||
![]() |
38f4e67ca7 | ||
![]() |
681d829227 | ||
![]() |
164e44c3d9 | ||
![]() |
f47dec3680 | ||
![]() |
88dc4beade | ||
![]() |
e9232088c0 | ||
![]() |
e96614ab86 | ||
![]() |
73115cb416 | ||
![]() |
480438bd52 | ||
![]() |
34fc8bddc4 | ||
![]() |
4dd89e439f | ||
![]() |
150177c449 | ||
![]() |
bf58ed2b53 | ||
![]() |
827ced0014 | ||
![]() |
133d46bde2 | ||
![]() |
e1017266ac | ||
![]() |
404fdaf2ff | ||
![]() |
2e1d156d66 | ||
![]() |
e863ad1547 | ||
![]() |
e231b692fd | ||
![]() |
68c365f906 | ||
![]() |
494c7294cb | ||
![]() |
fb20ee99eb | ||
![]() |
1a22154a3a | ||
![]() |
2972bf25bf | ||
![]() |
6b1a7a9e1a | ||
![]() |
33bc4a0b4e | ||
![]() |
c6f25167a2 | ||
![]() |
a150f92fb0 | ||
![]() |
5d31ded7a0 | ||
![]() |
0ed31bfa2c | ||
![]() |
51b9185a6b | ||
![]() |
b219497847 | ||
![]() |
7e96c89be5 | ||
![]() |
16a8d0e794 | ||
![]() |
7bb9981d8a | ||
![]() |
ea3d38bf64 | ||
![]() |
8f628b85e5 | ||
![]() |
defc922acd | ||
![]() |
88ae8d1f2b | ||
![]() |
8c7c9ac38a | ||
![]() |
0e146d50f7 | ||
![]() |
454e1e3927 | ||
![]() |
4f9875fd4e | ||
![]() |
82800a2c84 | ||
![]() |
27e700debd | ||
![]() |
01e47333d5 | ||
![]() |
d47ba7c2d1 | ||
![]() |
b1c4eb3f5c | ||
![]() |
869709a75f | ||
![]() |
310fcd2292 | ||
![]() |
85e9ca2a0f | ||
![]() |
65d225cb2c | ||
![]() |
04b6fc1280 | ||
![]() |
21eddc3f23 | ||
![]() |
f46a151075 | ||
![]() |
b7e9d02b7c | ||
![]() |
0ef3130510 | ||
![]() |
862d40cc3a | ||
![]() |
4b63214a72 | ||
![]() |
4937ebc058 | ||
![]() |
00f5700320 | ||
![]() |
e32dc8513f | ||
![]() |
50127f3ffe | ||
![]() |
29bb0e3dca | ||
![]() |
1221de4c2d | ||
![]() |
c41e08cb7a | ||
![]() |
4760ed8893 | ||
![]() |
31ecf31c2e | ||
![]() |
b52766653c | ||
![]() |
6d9fad01a9 | ||
![]() |
8322a63598 | ||
![]() |
075e1b5e1f | ||
![]() |
3c9bd7be29 | ||
![]() |
6995248443 | ||
![]() |
93467a6fce | ||
![]() |
95d48e3497 | ||
![]() |
202172135d | ||
![]() |
b94ab243a8 | ||
![]() |
11c8848e1f | ||
![]() |
231fcc700f | ||
![]() |
8ba7520acc | ||
![]() |
e0a5a2489d | ||
![]() |
bd400a5130 | ||
![]() |
d35f84f337 | ||
![]() |
af3bbdc591 | ||
![]() |
8813cf2c94 | ||
![]() |
d145c0e910 | ||
![]() |
8dadb853a0 | ||
![]() |
29886b8dd4 | ||
![]() |
e438e035bc | ||
![]() |
2bc5b6d2fa | ||
![]() |
e0b45c2d2b | ||
![]() |
d4c76968e9 | ||
![]() |
a700e8bf97 | ||
![]() |
7091792694 | ||
![]() |
efd94b705d | ||
![]() |
2cfebef122 | ||
![]() |
9ec989e633 | ||
![]() |
61d9143acb | ||
![]() |
c88f74a6ee | ||
![]() |
6377d6f64d | ||
![]() |
1b0bc05fc2 | ||
![]() |
45edeb9307 | ||
![]() |
211974b2b7 | ||
![]() |
1f5ad3e315 | ||
![]() |
d7848e8a3d | ||
![]() |
c0e2d4a23b | ||
![]() |
89b9f0df70 | ||
![]() |
e9011567bd | ||
![]() |
7171237b96 | ||
![]() |
0429970d58 | ||
![]() |
ecad9cee6c | ||
![]() |
066883f4cd | ||
![]() |
1e8a9f76a9 | ||
![]() |
e42fdf1c54 | ||
![]() |
c75566ddc3 | ||
![]() |
7bdcf93412 | ||
![]() |
d86e46b705 | ||
![]() |
96778f7789 | ||
![]() |
d4c058bd56 | ||
![]() |
b638a0a9c1 | ||
![]() |
fd9aa36c77 | ||
![]() |
46a9f1b31e | ||
![]() |
83c6224cc0 | ||
![]() |
d8161b1923 | ||
![]() |
8223141af9 | ||
![]() |
99f98a6876 | ||
![]() |
ef28f548df | ||
![]() |
e448c53b53 | ||
![]() |
71e09bcaef | ||
![]() |
cad144734d | ||
![]() |
5e57f22e23 | ||
![]() |
fc2c32603d | ||
![]() |
8c7da5af56 | ||
![]() |
4b89af3aca | ||
![]() |
c534d3d364 | ||
![]() |
4db72f5357 | ||
![]() |
2aa8330279 | ||
![]() |
803e2e14be | ||
![]() |
685516a85e | ||
![]() |
880f7454a3 | ||
![]() |
7e9577dffd | ||
![]() |
cba659d097 | ||
![]() |
f7a0844a31 | ||
![]() |
2817383714 | ||
![]() |
1f46c9e9bb | ||
![]() |
ec7099dc27 | ||
![]() |
180dc7bdff | ||
![]() |
cc9581842d | ||
![]() |
a716a525c3 | ||
![]() |
e6ee145edf | ||
![]() |
5cc264feb7 | ||
![]() |
690cc73259 | ||
![]() |
b9ef683fb6 | ||
![]() |
6a6289f2aa | ||
![]() |
accb4c6369 | ||
![]() |
52be254ad3 | ||
![]() |
9c071a9064 | ||
![]() |
91d7229f1b | ||
![]() |
60feec465b | ||
![]() |
d1ae687d1e | ||
![]() |
7af6723ac0 | ||
![]() |
da90f6760b | ||
![]() |
d74013c642 | ||
![]() |
ce996346f8 | ||
![]() |
29edfa7f56 | ||
![]() |
14a4ab81c9 | ||
![]() |
13d72262d9 | ||
![]() |
62dee0bad4 | ||
![]() |
9e81e1146a | ||
![]() |
2260948b7b | ||
![]() |
186429ae32 | ||
![]() |
657a9ef785 | ||
![]() |
4f24489d81 | ||
![]() |
11abfc9ae5 | ||
![]() |
227cef05b3 | ||
![]() |
2a514fa69e | ||
![]() |
80c6faf4d5 | ||
![]() |
81b0ffb92a | ||
![]() |
9f6ee53382 | ||
![]() |
3248bf3da4 | ||
![]() |
e7a7ff8a2a | ||
![]() |
68fc68c239 | ||
![]() |
769b362005 | ||
![]() |
e4d3aa4610 | ||
![]() |
716548548a | ||
![]() |
aeaf626bb5 | ||
![]() |
4bece53a3c | ||
![]() |
297be4a868 | ||
![]() |
fb6ace73b5 | ||
![]() |
096fbe933e | ||
![]() |
e539909e87 | ||
![]() |
cfc76ef1cb | ||
![]() |
bf362673fc | ||
![]() |
d042b21b12 | ||
![]() |
677ff82d13 | ||
![]() |
981829a426 | ||
![]() |
327a5aa9fd | ||
![]() |
20a18971ea | ||
![]() |
e1e36dfcb3 | ||
![]() |
848f69a75c | ||
![]() |
99dbeba407 | ||
![]() |
d525acc05b | ||
![]() |
1d3681053b | ||
![]() |
93df13898f | ||
![]() |
e32e80ea7f | ||
![]() |
3256807d25 | ||
![]() |
0133f1c0c5 | ||
![]() |
12e01bdb5c | ||
![]() |
a776b4f0ab | ||
![]() |
8d79bc9b19 | ||
![]() |
ecf7ab4355 | ||
![]() |
c61a431e2d | ||
![]() |
526b35c602 | ||
![]() |
8090580c67 | ||
![]() |
9d685178d2 | ||
![]() |
17142ef8d7 | ||
![]() |
4915545429 | ||
![]() |
334fe87bc6 | ||
![]() |
283e7810d2 | ||
![]() |
237d01d510 | ||
![]() |
bcd3e33243 | ||
![]() |
b2754bc553 | ||
![]() |
b65a73f432 | ||
![]() |
afeb761296 | ||
![]() |
3abcfbb8d2 | ||
![]() |
ee82694645 | ||
![]() |
ea72740d1f | ||
![]() |
427dc38857 | ||
![]() |
ec21042c53 | ||
![]() |
4a86b68e01 | ||
![]() |
012530e98e | ||
![]() |
a4a27611dd | ||
![]() |
5055ade44e | ||
![]() |
b61bec8faf | ||
![]() |
76d073b027 | ||
![]() |
8693be56ee | ||
![]() |
cc476d59d1 | ||
![]() |
8314554eb5 | ||
![]() |
b7c03dc27e | ||
![]() |
c7f2f609a9 | ||
![]() |
4c3de3a1ec |
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@mermaid-js/mermaid-zenuml': patch
|
||||
---
|
||||
|
||||
Fixed a critical bug that the ZenUML diagram is not rendered.
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
chore: Remove the "-beta" suffix from the XYChart, Block, Sankey diagrams to reflect their stable status
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Position the edge label in state diagram correctly relative to the edge
|
5
.changeset/deep-pumas-run.md
Normal file
5
.changeset/deep-pumas-run.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
chore: Fix mindmap rendering in docs and apply tidytree layout
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Apply correct dateFormat in Gantt chart to show only day when specified
|
5
.changeset/four-eyes-wish.md
Normal file
5
.changeset/four-eyes-wish.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Ensure edge label color is applied when using classDef with edge IDs
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: handle exclude dates properly in Gantt charts when using dateFormat: 'YYYY-MM-DD HH:mm:ss'
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: fixed connection gaps in flowchart for roundedRect, stadium and diamond shape
|
@@ -1,7 +0,0 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
'@mermaid-js/layout-tidy-tree': minor
|
||||
'@mermaid-js/layout-elk': minor
|
||||
---
|
||||
|
||||
feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Update casing of ID in requirement diagram
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
---
|
||||
|
||||
feat: Added support for per link curve styling in flowchart diagram using edge ids
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Make flowchart elk detector regex match less greedy
|
@@ -1,8 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix(block): overflowing blocks no longer affect later lines
|
||||
|
||||
This may change the layout of block diagrams that have overflowing lines
|
||||
(i.e. block diagrams that use up more columns that the `columns` specifier).
|
5
.changeset/moody-fans-try.md
Normal file
5
.changeset/moody-fans-try.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Resolve gantt chart crash due to invalid array length
|
@@ -1,7 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: log warning for blocks exceeding column width
|
||||
|
||||
This update adds a validation check that logs a warning message when a block's width exceeds the defined column layout.
|
5
.changeset/proud-colts-smell.md
Normal file
5
.changeset/proud-colts-smell.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
---
|
||||
|
||||
feat: Add IDs in architecture diagrams
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Add escaped class literal name on namespace
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Allow equals sign in sequenceDiagram labels
|
9
.changeset/revert-marked-dependency.md
Normal file
9
.changeset/revert-marked-dependency.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
chore: revert marked dependency from ^15.0.7 to ^16.0.0
|
||||
|
||||
- Reverted marked package version to ^16.0.0 for better compatibility
|
||||
- This is a dependency update that maintains API compatibility
|
||||
- All tests pass with the updated version
|
@@ -1,9 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
Add validation for negative values in pie charts:
|
||||
|
||||
Prevents crashes during parsing by validating values post-parsing.
|
||||
|
||||
Provides clearer, user-friendly error messages for invalid negative inputs.
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
chore: migrate to class-based ArchitectureDB implementation
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: node border style for handdrawn shapes
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Update flowchart direction TD's behavior to be the same as TB
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: correctly render non-directional lines for '---' in block diagrams
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
chore: Update packet diagram to use new class-based database structure
|
@@ -2,6 +2,7 @@
|
||||
Ashish Jain
|
||||
cpettitt
|
||||
Dong Cai
|
||||
fourcube
|
||||
knsv
|
||||
Knut Sveidqvist
|
||||
Nikolay Rozhkov
|
||||
|
@@ -5,8 +5,10 @@ bmatrix
|
||||
braintree
|
||||
catmull
|
||||
compositTitleSize
|
||||
cose
|
||||
curv
|
||||
doublecircle
|
||||
elem
|
||||
elems
|
||||
gantt
|
||||
gitgraph
|
||||
|
@@ -1,4 +1,5 @@
|
||||
BRANDES
|
||||
Buzan
|
||||
circo
|
||||
handDrawn
|
||||
KOEPF
|
||||
|
1
.github/lychee.toml
vendored
1
.github/lychee.toml
vendored
@@ -59,6 +59,7 @@ exclude = [
|
||||
"https://huehive.co",
|
||||
"https://foswiki.org",
|
||||
"https://www.gnu.org",
|
||||
"https://redmine.org",
|
||||
"https://mermaid-preview.com"
|
||||
]
|
||||
|
||||
|
10
.github/workflows/codeql.yml
vendored
10
.github/workflows/codeql.yml
vendored
@@ -26,8 +26,8 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ['javascript']
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
language: ['javascript', 'actions']
|
||||
# CodeQL supports [ 'actions', 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
uses: github/codeql-action/init@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21
|
||||
with:
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
languages: ${{ matrix.language }}
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
uses: github/codeql-action/autobuild@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
@@ -62,4 +62,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
uses: github/codeql-action/analyze@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21
|
||||
|
5
.github/workflows/e2e-applitools.yml
vendored
5
.github/workflows/e2e-applitools.yml
vendored
@@ -23,9 +23,6 @@ env:
|
||||
jobs:
|
||||
e2e-applitools:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
|
||||
options: --user 1001
|
||||
steps:
|
||||
- if: ${{ ! env.USE_APPLI }}
|
||||
name: Warn if not using Applitools
|
||||
@@ -56,7 +53,7 @@ jobs:
|
||||
args: -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH"
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
|
||||
id: cypress
|
||||
with:
|
||||
start: pnpm run dev
|
||||
|
6
.github/workflows/e2e-timings.yml
vendored
6
.github/workflows/e2e-timings.yml
vendored
@@ -27,12 +27,12 @@ jobs:
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
- name: Install dependencies
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
|
||||
with:
|
||||
runTests: false
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
|
||||
id: cypress
|
||||
with:
|
||||
install: false
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Commit and create pull request
|
||||
uses: peter-evans/create-pull-request@1310d7dab503600742045e6fd4b84dda64352858
|
||||
uses: peter-evans/create-pull-request@915d841dae6a4f191bb78faf61a257411d7be4d2
|
||||
with:
|
||||
add-paths: |
|
||||
cypress/timings.json
|
||||
|
10
.github/workflows/e2e.yml
vendored
10
.github/workflows/e2e.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
||||
node-version-file: '.node-version'
|
||||
- name: Cache snapshots
|
||||
id: cache-snapshot
|
||||
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: ./cypress/snapshots
|
||||
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
|
||||
@@ -59,7 +59,7 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
|
||||
with:
|
||||
# just perform install
|
||||
runTests: false
|
||||
@@ -95,13 +95,13 @@ jobs:
|
||||
# These cached snapshots are downloaded, providing the reference snapshots.
|
||||
- name: Cache snapshots
|
||||
id: cache-snapshot
|
||||
uses: actions/cache/restore@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||
uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: ./cypress/snapshots
|
||||
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
|
||||
|
||||
- name: Install dependencies
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
|
||||
with:
|
||||
runTests: false
|
||||
|
||||
@@ -117,7 +117,7 @@ jobs:
|
||||
# Install NPM dependencies, cache them correctly
|
||||
# and run all Cypress tests
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
|
||||
id: cypress
|
||||
with:
|
||||
install: false
|
||||
|
2
.github/workflows/link-checker.yml
vendored
2
.github/workflows/link-checker.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- name: Restore lychee cache
|
||||
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: .lycheecache
|
||||
key: cache-lychee-${{ github.sha }}
|
||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
- name: Create Release Pull Request or Publish to npm
|
||||
id: changesets
|
||||
uses: changesets/action@c8bada60c408975afd1a20b3db81d6eee6789308 # v1.4.9
|
||||
uses: changesets/action@06245a4e0a36c064a573d4150030f5ec548e4fcc # v1.4.10
|
||||
with:
|
||||
version: pnpm changeset:version
|
||||
publish: pnpm changeset:publish
|
||||
|
6
.github/workflows/scorecard.yml
vendored
6
.github/workflows/scorecard.yml
vendored
@@ -20,18 +20,18 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run analysis
|
||||
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
|
||||
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
publish_results: true
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
- name: Upload to code-scanning
|
||||
uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
uses: github/codeql-action/upload-sarif@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
2
.github/workflows/update-browserlist.yml
vendored
2
.github/workflows/update-browserlist.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
message: 'chore: update browsers list'
|
||||
push: false
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||
with:
|
||||
branch: update-browserslist
|
||||
title: Update Browserslist
|
||||
|
@@ -14,7 +14,7 @@ interface CodeObject {
|
||||
mermaid: CypressMermaidConfig;
|
||||
}
|
||||
|
||||
const utf8ToB64 = (str: string): string => {
|
||||
export const utf8ToB64 = (str: string): string => {
|
||||
return Buffer.from(decodeURIComponent(encodeURIComponent(str))).toString('base64');
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ const batchId: string =
|
||||
'mermaid-batch-' +
|
||||
(Cypress.env('useAppli')
|
||||
? Date.now().toString()
|
||||
: Cypress.env('CYPRESS_COMMIT') || Date.now().toString());
|
||||
: (Cypress.env('CYPRESS_COMMIT') ?? Date.now().toString()));
|
||||
|
||||
export const mermaidUrl = (
|
||||
graphStr: string | string[],
|
||||
@@ -61,9 +61,7 @@ export const imgSnapshotTest = (
|
||||
sequence: {
|
||||
...(_options.sequence ?? {}),
|
||||
actorFontFamily: 'courier',
|
||||
noteFontFamily: _options.sequence?.noteFontFamily
|
||||
? _options.sequence.noteFontFamily
|
||||
: 'courier',
|
||||
noteFontFamily: _options.sequence?.noteFontFamily ?? 'courier',
|
||||
messageFontFamily: 'courier',
|
||||
},
|
||||
};
|
||||
|
@@ -98,12 +98,12 @@ describe('Configuration', () => {
|
||||
it('should handle arrowMarkerAbsolute set to true', () => {
|
||||
renderGraph(
|
||||
`flowchart TD
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
B --> C{Let me think}
|
||||
C -->|One| D[Laptop]
|
||||
C -->|Two| E[iPhone]
|
||||
C -->|Three| F[fa:fa-car Car]
|
||||
`,
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
B --> C{Let me think}
|
||||
C -->|One| D[Laptop]
|
||||
C -->|Two| E[iPhone]
|
||||
C -->|Three| F[fa:fa-car Car]
|
||||
`,
|
||||
{
|
||||
arrowMarkerAbsolute: true,
|
||||
}
|
||||
@@ -113,8 +113,7 @@ describe('Configuration', () => {
|
||||
cy.get('path')
|
||||
.first()
|
||||
.should('have.attr', 'marker-end')
|
||||
.should('exist')
|
||||
.and('include', 'url(http\\:\\/\\/localhost');
|
||||
.and('include', 'url(http://localhost');
|
||||
});
|
||||
});
|
||||
it('should not taint the initial configuration when using multiple directives', () => {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { mermaidUrl } from '../../helpers/util.ts';
|
||||
import { imgSnapshotTest, mermaidUrl, utf8ToB64 } from '../../helpers/util.ts';
|
||||
describe('XSS', () => {
|
||||
it('should handle xss in tags', () => {
|
||||
const str =
|
||||
@@ -141,4 +141,37 @@ describe('XSS', () => {
|
||||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
});
|
||||
|
||||
it('should sanitize icon labels in architecture diagrams', () => {
|
||||
const str = JSON.stringify({
|
||||
code: `architecture-beta
|
||||
group api(cloud)[API]
|
||||
service db "<img src=x onerror=\\"xssAttack()\\">" [Database] in api`,
|
||||
});
|
||||
imgSnapshotTest(utf8ToB64(str), {}, true);
|
||||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
});
|
||||
|
||||
it('should sanitize katex blocks', () => {
|
||||
const str = JSON.stringify({
|
||||
code: `sequenceDiagram
|
||||
participant A as Alice<img src="x" onerror="xssAttack()">$$\\text{Alice}$$
|
||||
A->>John: Hello John, how are you?`,
|
||||
});
|
||||
imgSnapshotTest(utf8ToB64(str), {}, true);
|
||||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
});
|
||||
|
||||
it('should sanitize labels', () => {
|
||||
const str = JSON.stringify({
|
||||
code: `erDiagram
|
||||
"<img src=x onerror=xssAttack()>" ||--|| ENTITY2 : "<img src=x onerror=xssAttack()>"
|
||||
`,
|
||||
});
|
||||
imgSnapshotTest(utf8ToB64(str), {}, true);
|
||||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
});
|
||||
});
|
||||
|
@@ -524,5 +524,18 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
it('should handle an empty class body with empty braces', () => {
|
||||
imgSnapshotTest(
|
||||
` classDiagram
|
||||
class FooBase~T~ {}
|
||||
class Bar {
|
||||
+Zip
|
||||
+Zap()
|
||||
}
|
||||
FooBase <|-- Ba
|
||||
`,
|
||||
{ flowchart: { defaultRenderer: 'elk' } }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -109,7 +109,7 @@ describe('Flowchart ELK', () => {
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
verifyNumber(maxWidthValue, 380);
|
||||
verifyNumber(maxWidthValue, 380, 15);
|
||||
});
|
||||
});
|
||||
it('8-elk: should render a flowchart when useMaxWidth is false', () => {
|
||||
@@ -128,7 +128,7 @@ describe('Flowchart ELK', () => {
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
verifyNumber(width, 380);
|
||||
verifyNumber(width, 380, 15);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
@@ -1053,6 +1053,21 @@ flowchart LR
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('6647-elk: should keep node order when using elk layout unless it would add crossings', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart TB
|
||||
a --> a1 & a2 & a3 & a4
|
||||
b --> b1 & b2
|
||||
b2 --> b3
|
||||
b1 --> b4
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Title and arrow styling #4813', () => {
|
||||
|
@@ -1118,7 +1118,7 @@ end
|
||||
imgSnapshotTest(
|
||||
`flowchart TB
|
||||
A(["Start"]) --> n1["Untitled Node"]
|
||||
A --> n2["Untitled Node"]
|
||||
A --> n2["Untitled Node"]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
@@ -1127,7 +1127,7 @@ end
|
||||
imgSnapshotTest(
|
||||
`flowchart BT
|
||||
n2["Untitled Node"] --> n1["Diamond"]
|
||||
n1@{ shape: diam}
|
||||
n1@{ shape: diam}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
@@ -1138,7 +1138,7 @@ end
|
||||
n2["Untitled Node"] --> n1["Rounded Rectangle"]
|
||||
n3["Untitled Node"] --> n1
|
||||
n1@{ shape: rounded}
|
||||
n3@{ shape: rect}
|
||||
n3@{ shape: rect}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
@@ -1164,4 +1164,39 @@ end
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
describe('when rendering unsuported markdown', () => {
|
||||
const graph = `flowchart TB
|
||||
mermaid{"What is\nyourmermaid version?"} --> v10["<11"] --"\`<**1**1\`"--> fine["No bug"]
|
||||
mermaid --> v11[">= v11"] -- ">= v11" --> broken["Affected by https://github.com/mermaid-js/mermaid/issues/5824"]
|
||||
subgraph subgraph1["\`How to fix **fix**\`"]
|
||||
broken --> B["B"]
|
||||
end
|
||||
githost["Github, Gitlab, BitBucket, etc."]
|
||||
githost2["\`Github, Gitlab, BitBucket, etc.\`"]
|
||||
a["1."]
|
||||
b["- x"]
|
||||
`;
|
||||
|
||||
it('should render raw strings', () => {
|
||||
imgSnapshotTest(graph);
|
||||
});
|
||||
|
||||
it('should render raw strings with htmlLabels: false', () => {
|
||||
imgSnapshotTest(graph, { htmlLabels: false });
|
||||
});
|
||||
});
|
||||
|
||||
it('V2 - 17: should apply class def colour to edge label', () => {
|
||||
imgSnapshotTest(
|
||||
` graph LR
|
||||
id1(Start) link@-- "Label" -->id2(Stop)
|
||||
style id1 fill:#f9f,stroke:#333,stroke-width:4px
|
||||
|
||||
class id2 myClass
|
||||
classDef myClass fill:#bbf,stroke:#f66,stroke-width:2px,color:white,stroke-dasharray: 5 5
|
||||
class link myClass
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -803,4 +803,34 @@ describe('Gantt diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should handle numeric timestamps with dateFormat x', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gantt
|
||||
title Process time profile (ms)
|
||||
dateFormat x
|
||||
axisFormat %L
|
||||
tickInterval 250millisecond
|
||||
|
||||
section Pipeline
|
||||
Parse JSON p1: 000, 120
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should handle numeric timestamps with dateFormat X', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gantt
|
||||
title Process time profile (ms)
|
||||
dateFormat X
|
||||
axisFormat %L
|
||||
tickInterval 250millisecond
|
||||
|
||||
section Pipeline
|
||||
Parse JSON p1: 000, 120
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
79
cypress/integration/rendering/mindmap-tidy-tree.spec.js
Normal file
79
cypress/integration/rendering/mindmap-tidy-tree.spec.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('Mindmap Tidy Tree', () => {
|
||||
it('1-tidy-tree: should render a simple mindmap without children', () => {
|
||||
imgSnapshotTest(
|
||||
` ---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
A
|
||||
B
|
||||
`
|
||||
);
|
||||
});
|
||||
it('2-tidy-tree: should render a simple mindmap', () => {
|
||||
imgSnapshotTest(
|
||||
` ---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap is a long thing))
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
`
|
||||
);
|
||||
});
|
||||
it('3-tidy-tree: should render a mindmap with different shapes', () => {
|
||||
imgSnapshotTest(
|
||||
` ---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
Origins
|
||||
Long history
|
||||
::icon(fa fa-book)
|
||||
Popularisation
|
||||
British popular psychology author Tony Buzan
|
||||
Research
|
||||
On effectiveness<br/>and features
|
||||
On Automatic creation
|
||||
Uses
|
||||
Creative techniques
|
||||
Strategic planning
|
||||
Argument mapping
|
||||
Tools
|
||||
id)I am a cloud(
|
||||
id))I am a bang((
|
||||
Tools
|
||||
`
|
||||
);
|
||||
});
|
||||
it('4-tidy-tree: should render a mindmap with children', () => {
|
||||
imgSnapshotTest(
|
||||
` ---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
((This is a mindmap))
|
||||
child1
|
||||
grandchild 1
|
||||
grandchild 2
|
||||
child2
|
||||
grandchild 3
|
||||
grandchild 4
|
||||
child3
|
||||
grandchild 5
|
||||
grandchild 6
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
@@ -228,25 +228,21 @@ root
|
||||
`mindmap
|
||||
id1[\`**Start** with
|
||||
a second line 😎\`]
|
||||
id2[\`The dog in **the** hog... a *very long text* about it
|
||||
Word!\`]
|
||||
`
|
||||
id2[\`The dog in **the** hog... a *very long text* about it Word!\`]`
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('Include char sequence "graph" in text (#6795)', () => {
|
||||
it('has a label with char sequence "graph"', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
mindmap
|
||||
` mindmap
|
||||
root
|
||||
Photograph
|
||||
Waterfall
|
||||
Landscape
|
||||
Geography
|
||||
Mountains
|
||||
Rocks
|
||||
`,
|
||||
Rocks`,
|
||||
{ flowchart: { defaultRenderer: 'elk' } }
|
||||
);
|
||||
});
|
||||
|
659
cypress/integration/rendering/sequencediagram-v2.spec.js
Normal file
659
cypress/integration/rendering/sequencediagram-v2.spec.js
Normal file
@@ -0,0 +1,659 @@
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
const looks = ['classic'];
|
||||
const participantTypes = [
|
||||
{ type: 'participant', display: 'participant' },
|
||||
{ type: 'actor', display: 'actor' },
|
||||
{ type: 'boundary', display: 'boundary' },
|
||||
{ type: 'control', display: 'control' },
|
||||
{ type: 'entity', display: 'entity' },
|
||||
{ type: 'database', display: 'database' },
|
||||
{ type: 'collections', display: 'collections' },
|
||||
{ type: 'queue', display: 'queue' },
|
||||
];
|
||||
|
||||
const restrictedTypes = ['boundary', 'control', 'entity', 'database', 'collections', 'queue'];
|
||||
|
||||
const interactionTypes = ['->>', '-->>', '->', '-->', '-x', '--x', '->>+', '-->>+'];
|
||||
|
||||
const notePositions = ['left of', 'right of', 'over'];
|
||||
|
||||
function getParticipantLine(name, type, alias) {
|
||||
if (restrictedTypes.includes(type)) {
|
||||
return ` participant ${name}@{ "type" : "${type}" }\n`;
|
||||
} else if (alias) {
|
||||
return ` participant ${name}@{ "type" : "${type}" } \n`;
|
||||
} else {
|
||||
return ` participant ${name}@{ "type" : "${type}" }\n`;
|
||||
}
|
||||
}
|
||||
|
||||
looks.forEach((look) => {
|
||||
describe(`Sequence Diagram Tests - ${look} look`, () => {
|
||||
it('should render all participant types', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
participantTypes.forEach((pt, index) => {
|
||||
const name = `${pt.display}${index}`;
|
||||
diagramCode += getParticipantLine(name, pt.type);
|
||||
});
|
||||
for (let i = 0; i < participantTypes.length - 1; i++) {
|
||||
diagramCode += ` ${participantTypes[i].display}${i} ->> ${participantTypes[i + 1].display}${i + 1}: Message ${i}\n`;
|
||||
}
|
||||
imgSnapshotTest(diagramCode, { look, sequence: { diagramMarginX: 50, diagramMarginY: 10 } });
|
||||
});
|
||||
|
||||
it('should render all interaction types', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
diagramCode += getParticipantLine('A', 'actor');
|
||||
diagramCode += getParticipantLine('B', 'boundary');
|
||||
interactionTypes.forEach((interaction, index) => {
|
||||
diagramCode += ` A ${interaction} B: ${interaction} message ${index}\n`;
|
||||
});
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render participant creation and destruction', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
participantTypes.forEach((pt, index) => {
|
||||
const name = `${pt.display}${index}`;
|
||||
diagramCode += getParticipantLine('A', pt.type);
|
||||
diagramCode += getParticipantLine('B', pt.type);
|
||||
diagramCode += ` create participant ${name}@{ "type" : "${pt.type}" }\n`;
|
||||
diagramCode += ` A ->> ${name}: Hello ${pt.display}\n`;
|
||||
if (index % 2 === 0) {
|
||||
diagramCode += ` destroy ${name}\n`;
|
||||
}
|
||||
});
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render notes in all positions', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
diagramCode += getParticipantLine('A', 'actor');
|
||||
diagramCode += getParticipantLine('B', 'boundary');
|
||||
notePositions.forEach((position, index) => {
|
||||
diagramCode += ` Note ${position} A: Note ${position} ${index}\n`;
|
||||
});
|
||||
diagramCode += ` A ->> B: Message with notes\n`;
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render parallel interactions', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
participantTypes.slice(0, 4).forEach((pt, index) => {
|
||||
diagramCode += getParticipantLine(`${pt.display}${index}`, pt.type);
|
||||
});
|
||||
diagramCode += ` par Parallel actions\n`;
|
||||
for (let i = 0; i < 3; i += 2) {
|
||||
diagramCode += ` ${participantTypes[i].display}${i} ->> ${participantTypes[i + 1].display}${i + 1}: Message ${i}\n`;
|
||||
if (i < participantTypes.length - 2) {
|
||||
diagramCode += ` and\n`;
|
||||
}
|
||||
}
|
||||
diagramCode += ` end\n`;
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render alternative flows', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
diagramCode += getParticipantLine('A', 'actor');
|
||||
diagramCode += getParticipantLine('B', 'boundary');
|
||||
diagramCode += ` alt Successful case\n`;
|
||||
diagramCode += ` A ->> B: Request\n`;
|
||||
diagramCode += ` B -->> A: Success\n`;
|
||||
diagramCode += ` else Failure case\n`;
|
||||
diagramCode += ` A ->> B: Request\n`;
|
||||
diagramCode += ` B --x A: Failure\n`;
|
||||
diagramCode += ` end\n`;
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render loops', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
participantTypes.slice(0, 3).forEach((pt, index) => {
|
||||
diagramCode += getParticipantLine(`${pt.display}${index}`, pt.type);
|
||||
});
|
||||
diagramCode += ` loop For each participant\n`;
|
||||
for (let i = 0; i < 3; i++) {
|
||||
diagramCode += ` ${participantTypes[0].display}0 ->> ${participantTypes[1].display}1: Message ${i}\n`;
|
||||
}
|
||||
diagramCode += ` end\n`;
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render boxes around groups', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
diagramCode += ` box Group 1\n`;
|
||||
participantTypes.slice(0, 3).forEach((pt, index) => {
|
||||
diagramCode += ` ${getParticipantLine(`${pt.display}${index}`, pt.type)}`;
|
||||
});
|
||||
diagramCode += ` end\n`;
|
||||
diagramCode += ` box rgb(200,220,255) Group 2\n`;
|
||||
participantTypes.slice(3, 6).forEach((pt, index) => {
|
||||
diagramCode += ` ${getParticipantLine(`${pt.display}${index}`, pt.type)}`;
|
||||
});
|
||||
diagramCode += ` end\n`;
|
||||
diagramCode += ` ${participantTypes[0].display}0 ->> ${participantTypes[3].display}0: Cross-group message\n`;
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render with different font settings', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
participantTypes.slice(0, 3).forEach((pt, index) => {
|
||||
diagramCode += getParticipantLine(`${pt.display}${index}`, pt.type);
|
||||
});
|
||||
diagramCode += ` ${participantTypes[0].display}0 ->> ${participantTypes[1].display}1: Regular message\n`;
|
||||
diagramCode += ` Note right of ${participantTypes[1].display}1: Regular note\n`;
|
||||
imgSnapshotTest(diagramCode, {
|
||||
look,
|
||||
sequence: {
|
||||
actorFontFamily: 'courier',
|
||||
actorFontSize: 14,
|
||||
messageFontFamily: 'Arial',
|
||||
messageFontSize: 12,
|
||||
noteFontFamily: 'times',
|
||||
noteFontSize: 16,
|
||||
noteAlign: 'left',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Additional tests for specific combinations
|
||||
describe('Sequence Diagram Special Cases', () => {
|
||||
it('should render complex sequence with all features', () => {
|
||||
const diagramCode = `
|
||||
sequenceDiagram
|
||||
box rgb(200,220,255) Authentication
|
||||
actor User
|
||||
participant LoginUI@{ "type": "boundary" }
|
||||
participant AuthService@{ "type": "control" }
|
||||
participant UserDB@{ "type": "database" }
|
||||
end
|
||||
|
||||
box rgb(200,255,220) Order Processing
|
||||
participant Order@{ "type": "entity" }
|
||||
participant OrderQueue@{ "type": "queue" }
|
||||
participant AuditLogs@{ "type": "collections" }
|
||||
end
|
||||
|
||||
User ->> LoginUI: Enter credentials
|
||||
LoginUI ->> AuthService: Validate
|
||||
AuthService ->> UserDB: Query user
|
||||
UserDB -->> AuthService: User data
|
||||
alt Valid credentials
|
||||
AuthService -->> LoginUI: Success
|
||||
LoginUI -->> User: Welcome
|
||||
|
||||
par Place order
|
||||
User ->> Order: New order
|
||||
Order ->> OrderQueue: Process
|
||||
and
|
||||
Order ->> AuditLogs: Record
|
||||
end
|
||||
|
||||
loop Until confirmed
|
||||
OrderQueue ->> Order: Update status
|
||||
Order -->> User: Notification
|
||||
end
|
||||
else Invalid credentials
|
||||
AuthService --x LoginUI: Failure
|
||||
LoginUI --x User: Retry
|
||||
end
|
||||
`;
|
||||
imgSnapshotTest(diagramCode, {});
|
||||
});
|
||||
|
||||
it('should render with wrapped messages and notes', () => {
|
||||
const diagramCode = `
|
||||
sequenceDiagram
|
||||
participant A
|
||||
participant B
|
||||
|
||||
A ->> B: This is a very long message that should wrap properly in the diagram rendering
|
||||
Note over A,B: This is a very long note that should also wrap properly when rendered in the diagram
|
||||
|
||||
par Wrapped parallel
|
||||
A ->> B: Parallel message 1<br>with explicit line break
|
||||
and
|
||||
B ->> A: Parallel message 2<br>with explicit line break
|
||||
end
|
||||
|
||||
loop Wrapped loop
|
||||
Note right of B: This is a long note<br>in a loop
|
||||
A ->> B: Message in loop
|
||||
end
|
||||
`;
|
||||
imgSnapshotTest(diagramCode, { sequence: { wrap: true } });
|
||||
});
|
||||
describe('Sequence Diagram Rendering with Different Participant Types', () => {
|
||||
it('should render a sequence diagram with various participant types', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant User@{ "type": "actor" }
|
||||
participant AuthService@{ "type": "control" }
|
||||
participant UI@{ "type": "boundary" }
|
||||
participant OrderController@{ "type": "control" }
|
||||
participant Product@{ "type": "entity" }
|
||||
participant MongoDB@{ "type": "database" }
|
||||
participant Products@{ "type": "collections" }
|
||||
participant OrderQueue@{ "type": "queue" }
|
||||
User ->> UI: Login request
|
||||
UI ->> AuthService: Validate credentials
|
||||
AuthService -->> UI: Authentication token
|
||||
UI ->> OrderController: Place order
|
||||
OrderController ->> Product: Check availability
|
||||
Product -->> OrderController: Available
|
||||
OrderController ->> MongoDB: Save order
|
||||
MongoDB -->> OrderController: Order saved
|
||||
OrderController ->> OrderQueue: Process payment
|
||||
OrderQueue -->> User: Order confirmation
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('should render participant creation and destruction with different types', () => {
|
||||
imgSnapshotTest(`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "boundary" }
|
||||
Alice->>Bob: Hello Bob, how are you ?
|
||||
Bob->>Alice: Fine, thank you. And you?
|
||||
create participant Carl@{ "type" : "control" }
|
||||
Alice->>Carl: Hi Carl!
|
||||
create actor D as Donald
|
||||
Carl->>D: Hi!
|
||||
destroy Carl
|
||||
Alice-xCarl: We are too many
|
||||
destroy Bob
|
||||
Bob->>Alice: I agree
|
||||
`);
|
||||
});
|
||||
|
||||
it('should handle complex interactions between different participant types', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
box rgb(200,220,255) Authentication
|
||||
participant User@{ "type": "actor" }
|
||||
participant LoginUI@{ "type": "boundary" }
|
||||
participant AuthService@{ "type": "control" }
|
||||
participant UserDB@{ "type": "database" }
|
||||
end
|
||||
|
||||
box rgb(200,255,220) Order Processing
|
||||
participant Order@{ "type": "entity" }
|
||||
participant OrderQueue@{ "type": "queue" }
|
||||
participant AuditLogs@{ "type": "collections" }
|
||||
end
|
||||
|
||||
User ->> LoginUI: Enter credentials
|
||||
LoginUI ->> AuthService: Validate
|
||||
AuthService ->> UserDB: Query user
|
||||
UserDB -->> AuthService: User data
|
||||
|
||||
alt Valid credentials
|
||||
AuthService -->> LoginUI: Success
|
||||
LoginUI -->> User: Welcome
|
||||
|
||||
par Place order
|
||||
User ->> Order: New order
|
||||
Order ->> OrderQueue: Process
|
||||
and
|
||||
Order ->> AuditLogs: Record
|
||||
end
|
||||
|
||||
loop Until confirmed
|
||||
OrderQueue ->> Order: Update status
|
||||
Order -->> User: Notification
|
||||
end
|
||||
else Invalid credentials
|
||||
AuthService --x LoginUI: Failure
|
||||
LoginUI --x User: Retry
|
||||
end
|
||||
`,
|
||||
{ sequence: { useMaxWidth: false } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render parallel processes with different participant types', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Customer@{ "type": "actor" }
|
||||
participant Frontend@{ "type": "participant" }
|
||||
participant PaymentService@{ "type": "boundary" }
|
||||
participant InventoryManager@{ "type": "control" }
|
||||
participant Order@{ "type": "entity" }
|
||||
participant OrdersDB@{ "type": "database" }
|
||||
participant NotificationQueue@{ "type": "queue" }
|
||||
|
||||
Customer ->> Frontend: Place order
|
||||
Frontend ->> Order: Create order
|
||||
par Parallel Processing
|
||||
Order ->> PaymentService: Process payment
|
||||
and
|
||||
Order ->> InventoryManager: Reserve items
|
||||
end
|
||||
PaymentService -->> Order: Payment confirmed
|
||||
InventoryManager -->> Order: Items reserved
|
||||
Order ->> OrdersDB: Save finalized order
|
||||
OrdersDB -->> Order: Order saved
|
||||
Order ->> NotificationQueue: Send confirmation
|
||||
NotificationQueue -->> Customer: Order confirmation
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
it('should render different participant types with notes and loops', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Admin
|
||||
participant Dashboard
|
||||
participant AuthService@{ "type" : "boundary" }
|
||||
participant UserManager@{ "type" : "control" }
|
||||
participant UserProfile@{ "type" : "entity" }
|
||||
participant UserDB@{ "type" : "database" }
|
||||
participant Logs@{ "type" : "database" }
|
||||
|
||||
Admin ->> Dashboard: Open user management
|
||||
loop Authentication check
|
||||
Dashboard ->> AuthService: Verify admin rights
|
||||
AuthService ->> Dashboard: Access granted
|
||||
end
|
||||
Dashboard ->> UserManager: List users
|
||||
UserManager ->> UserDB: Query users
|
||||
UserDB ->> UserManager: Return user data
|
||||
Note right of UserDB: Encrypted data<br/>requires decryption
|
||||
UserManager ->> UserProfile: Format profiles
|
||||
UserProfile ->> UserManager: Formatted data
|
||||
UserManager ->> Dashboard: Display users
|
||||
Dashboard ->> Logs: Record access
|
||||
Logs ->> Admin: Audit trail
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('should render different participant types with alternative flows', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Client
|
||||
participant MobileApp
|
||||
participant CloudService@{ "type" : "boundary" }
|
||||
participant DataProcessor@{ "type" : "control" }
|
||||
participant Transaction@{ "type" : "entity" }
|
||||
participant TransactionsDB@{ "type" : "database" }
|
||||
participant EventBus@{ "type" : "queue" }
|
||||
|
||||
Client ->> MobileApp: Initiate transaction
|
||||
MobileApp ->> CloudService: Authenticate
|
||||
alt Authentication successful
|
||||
CloudService -->> MobileApp: Auth token
|
||||
MobileApp ->> DataProcessor: Process data
|
||||
DataProcessor ->> Transaction: Create transaction
|
||||
Transaction ->> TransactionsDB: Save record
|
||||
TransactionsDB -->> Transaction: Confirmation
|
||||
Transaction ->> EventBus: Publish event
|
||||
EventBus -->> Client: Notification
|
||||
else Authentication failed
|
||||
CloudService -->> MobileApp: Error
|
||||
MobileApp -->> Client: Show error
|
||||
end
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('should render different participant types with wrapping text', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant B@{ "type" : "boundary" }
|
||||
participant C@{ "type" : "control" }
|
||||
participant E@{ "type" : "entity" }
|
||||
participant DB@{ "type" : "database" }
|
||||
participant COL@{ "type" : "collections" }
|
||||
participant Q@{ "type" : "queue" }
|
||||
|
||||
FE ->> B: Another long message<br/>with explicit<br/>line breaks
|
||||
B -->> FE: Response message that is also quite long and needs to wrap
|
||||
FE ->> C: Process data
|
||||
C ->> E: Validate
|
||||
E -->> C: Validation result
|
||||
C ->> DB: Save
|
||||
DB -->> C: Save result
|
||||
C ->> COL: Log
|
||||
COL -->> Q: Forward
|
||||
Q -->> LongNameUser: Final response with confirmation of all actions taken
|
||||
`,
|
||||
{ sequence: { wrap: true } }
|
||||
);
|
||||
});
|
||||
|
||||
describe('Sequence Diagram - New Participant Types with Long Notes and Messages', () => {
|
||||
it('should render long notes left of boundary', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "boundary" }
|
||||
actor Bob
|
||||
Alice->>Bob: Hola
|
||||
Note left of Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render wrapped long notes left of control', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "control" }
|
||||
actor Bob
|
||||
Alice->>Bob: Hola
|
||||
Note left of Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render long notes right of entity', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "entity" }
|
||||
actor Bob
|
||||
Alice->>Bob: Hola
|
||||
Note right of Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render wrapped long notes right of database', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "database" }
|
||||
actor Bob
|
||||
Alice->>Bob: Hola
|
||||
Note right of Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render long notes over collections', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "collections" }
|
||||
actor Bob
|
||||
Alice->>Bob: Hola
|
||||
Note over Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render wrapped long notes over queue', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "queue" }
|
||||
actor Bob
|
||||
Alice->>Bob: Hola
|
||||
Note over Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render notes over actor and boundary', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Alice
|
||||
participant Charlie@{ "type" : "boundary" }
|
||||
note over Alice: Some note
|
||||
note over Charlie: Other note
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render long messages from database to collections', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "database" }
|
||||
participant Bob@{ "type" : "collections" }
|
||||
Alice->>Bob: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render wrapped long messages from control to entity', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "control" }
|
||||
participant Bob@{ "type" : "entity" }
|
||||
Alice->>Bob:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render long messages from queue to boundary', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "queue" }
|
||||
participant Bob@{ "type" : "boundary" }
|
||||
Alice->>Bob: I'm short
|
||||
Bob->>Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render wrapped long messages from actor to database', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Alice
|
||||
participant Bob@{ "type" : "database" }
|
||||
Alice->>Bob: I'm short
|
||||
Bob->>Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('svg size', () => {
|
||||
it('should render a sequence diagram when useMaxWidth is true (default)', () => {
|
||||
renderGraph(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Alice
|
||||
participant Bob@{ "type" : "boundary" }
|
||||
participant John@{ "type" : "control" }
|
||||
Alice ->> Bob: Hello Bob, how are you?
|
||||
Bob-->>John: How about you John?
|
||||
Bob--x Alice: I am good thanks!
|
||||
Bob-x John: I am good thanks!
|
||||
Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
|
||||
Bob-->Alice: Checking with John...
|
||||
alt either this
|
||||
Alice->>John: Yes
|
||||
else or this
|
||||
Alice->>John: No
|
||||
else or this will happen
|
||||
Alice->John: Maybe
|
||||
end
|
||||
par this happens in parallel
|
||||
Alice -->> Bob: Parallel message 1
|
||||
and
|
||||
Alice -->> John: Parallel message 2
|
||||
end
|
||||
`,
|
||||
{ sequence: { useMaxWidth: true } }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
expect(svg).to.have.attr('width', '100%');
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
expect(maxWidthValue).to.be.within(820 * 0.95, 820 * 1.05);
|
||||
});
|
||||
});
|
||||
|
||||
it('should render a sequence diagram when useMaxWidth is false', () => {
|
||||
renderGraph(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Alice
|
||||
participant Bob@{ "type" : "boundary" }
|
||||
participant John@{ "type" : "control" }
|
||||
Alice ->> Bob: Hello Bob, how are you?
|
||||
Bob-->>John: How about you John?
|
||||
Bob--x Alice: I am good thanks!
|
||||
Bob-x John: I am good thanks!
|
||||
Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
|
||||
Bob-->Alice: Checking with John...
|
||||
alt either this
|
||||
Alice->>John: Yes
|
||||
else or this
|
||||
Alice->>John: No
|
||||
else or this will happen
|
||||
Alice->John: Maybe
|
||||
end
|
||||
par this happens in parallel
|
||||
Alice -->> Bob: Parallel message 1
|
||||
and
|
||||
Alice -->> John: Parallel message 2
|
||||
end
|
||||
`,
|
||||
{ sequence: { useMaxWidth: false } }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
expect(width).to.be.within(820 * 0.95, 820 * 1.05);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@@ -893,6 +893,17 @@ describe('Sequence diagram', () => {
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle bidirectional arrows with autonumber', () => {
|
||||
imgSnapshotTest(`
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant A
|
||||
participant B
|
||||
A<<->>B: This is a bidirectional message
|
||||
A->B: This is a normal message`);
|
||||
});
|
||||
|
||||
it('should support actor links and properties when not mirrored EXPERIMENTAL: USE WITH CAUTION', () => {
|
||||
//Be aware that the syntax for "properties" is likely to be changed.
|
||||
imgSnapshotTest(
|
||||
|
@@ -32,26 +32,8 @@
|
||||
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Recursive:wght@300..1000&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<style>
|
||||
.recursive-mermaid {
|
||||
font-family: 'Recursive', sans-serif;
|
||||
font-optical-sizing: auto;
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-variation-settings:
|
||||
'slnt' 0,
|
||||
'CASL' 0,
|
||||
'CRSV' 0.5,
|
||||
'MONO' 0;
|
||||
}
|
||||
|
||||
body {
|
||||
/* background: rgb(221, 208, 208); */
|
||||
/* background: #333; */
|
||||
@@ -63,9 +45,7 @@
|
||||
h1 {
|
||||
color: grey;
|
||||
}
|
||||
.mermaid {
|
||||
border: 1px solid red;
|
||||
}
|
||||
|
||||
.mermaid2 {
|
||||
display: none;
|
||||
}
|
||||
@@ -103,11 +83,6 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.class2 {
|
||||
fill: red;
|
||||
fill-opacity: 1;
|
||||
}
|
||||
|
||||
/* tspan {
|
||||
font-size: 6px !important;
|
||||
} */
|
||||
@@ -130,7 +105,237 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart-elk TB
|
||||
c1-->a2
|
||||
subgraph one
|
||||
a1-->a2
|
||||
end
|
||||
subgraph two
|
||||
b1-->b2
|
||||
end
|
||||
subgraph three
|
||||
c1-->c2
|
||||
end
|
||||
one --> two
|
||||
three --> two
|
||||
two --> c2
|
||||
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart TB
|
||||
|
||||
process_C
|
||||
subgraph container_Alpha
|
||||
subgraph process_B
|
||||
pppB
|
||||
end
|
||||
subgraph process_A
|
||||
pppA
|
||||
end
|
||||
process_B-->|via_AWSBatch|container_Beta
|
||||
process_A-->|messages|container_Beta
|
||||
end
|
||||
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart TB
|
||||
subgraph container_Beta
|
||||
process_C
|
||||
end
|
||||
subgraph container_Alpha
|
||||
subgraph process_B
|
||||
pppB
|
||||
end
|
||||
subgraph process_A
|
||||
pppA
|
||||
end
|
||||
process_B-->|via_AWSBatch|container_Beta
|
||||
process_A-->|messages|container_Beta
|
||||
end
|
||||
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart TB
|
||||
subgraph container_Beta
|
||||
process_C
|
||||
end
|
||||
|
||||
process_B-->|via_AWSBatch|container_Beta
|
||||
|
||||
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
classDiagram
|
||||
note "I love this diagram!\nDo you love it?"
|
||||
Class01 <|-- AveryLongClass : Cool
|
||||
<<interface>> Class01
|
||||
Class03 "1" *-- "*" Class04
|
||||
Class05 "1" o-- "many" Class06
|
||||
Class07 "1" .. "*" Class08
|
||||
Class09 "1" --> "*" C2 : Where am i?
|
||||
Class09 "*" --* "*" C3
|
||||
Class09 "1" --|> "1" Class07
|
||||
Class12 <|.. Class08
|
||||
Class11 ..>Class12
|
||||
Class07 : equals()
|
||||
Class07 : Object[] elementData
|
||||
Class01 : size()
|
||||
Class01 : int chimp
|
||||
Class01 : int gorilla
|
||||
Class01 : -int privateChimp
|
||||
Class01 : +int publicGorilla
|
||||
Class01 : #int protectedMarmoset
|
||||
Class08 <--> C2: Cool label
|
||||
class Class10 {
|
||||
<<service>>
|
||||
int id
|
||||
test()
|
||||
}
|
||||
note for Class10 "Cool class\nI said it's very cool class!"
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
requirementDiagram
|
||||
requirement test_req {
|
||||
id: 1
|
||||
text: the test text.
|
||||
risk: high
|
||||
verifymethod: test
|
||||
}
|
||||
|
||||
element test_entity {
|
||||
type: simulation
|
||||
}
|
||||
|
||||
test_entity - satisfies -> test_req
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart-elk TB
|
||||
internet
|
||||
nat
|
||||
router
|
||||
compute1
|
||||
|
||||
subgraph project
|
||||
router
|
||||
nat
|
||||
subgraph subnet1
|
||||
compute1
|
||||
end
|
||||
end
|
||||
|
||||
%% router --> subnet1
|
||||
subnet1 --> nat
|
||||
%% nat --> internet
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart-elk TB
|
||||
internet
|
||||
nat
|
||||
router
|
||||
lb1
|
||||
lb2
|
||||
compute1
|
||||
compute2
|
||||
subgraph project
|
||||
router
|
||||
nat
|
||||
subgraph subnet1
|
||||
compute1
|
||||
lb1
|
||||
end
|
||||
subgraph subnet2
|
||||
compute2
|
||||
lb2
|
||||
end
|
||||
end
|
||||
internet --> router
|
||||
router --> subnet1 & subnet2
|
||||
subnet1 & subnet2 --> nat --> internet
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
elk:
|
||||
mergeEdges: false
|
||||
forceNodeModelOrder: false
|
||||
considerModelOrder: NONE
|
||||
|
||||
---
|
||||
flowchart TB
|
||||
a --> a1 & a2 & a3 & a4
|
||||
b --> b1 & b2
|
||||
b2 --> b3
|
||||
b1 --> b4</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
treemap
|
||||
"Section 1"
|
||||
"Leaf 1.1": 12
|
||||
"Section 1.2":::class1
|
||||
"Leaf 1.2.1": 12
|
||||
"Section 2"
|
||||
"Leaf 2.1": 20:::class1
|
||||
"Leaf 2.2": 25
|
||||
"Leaf 2.3": 12
|
||||
|
||||
</pre>
|
||||
<pre id="diagram5" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
flowchart:
|
||||
curve: rounded
|
||||
---
|
||||
flowchart LR
|
||||
I["fa:fa-code Text"] -- Mermaid js --> D["Use<br/>the<br/>editor!"]
|
||||
I --> D & D
|
||||
D@{ shape: question}
|
||||
I@{ shape: question}
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
@@ -157,275 +362,107 @@
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
layout: elk
|
||||
flowchart:
|
||||
curve: linear
|
||||
---
|
||||
mindmap
|
||||
root((mindmap is a long thing))
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
A
|
||||
B
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
A
|
||||
a
|
||||
apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
b
|
||||
c
|
||||
d
|
||||
B
|
||||
apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
D
|
||||
apa5[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
flowchart LR
|
||||
A[A] --> B[B]
|
||||
A[A] --- B([C])
|
||||
A@{ shape: diamond}
|
||||
%%B@{ shape: diamond}
|
||||
|
||||
</pre>
|
||||
|
||||
<pre id="diagram4" class="mermaid">
|
||||
treemap
|
||||
"Section 1"
|
||||
"Leaf 1.1": 12
|
||||
"Section 1.2":::class1
|
||||
"Leaf 1.2.1": 12
|
||||
"Section 2"
|
||||
"Leaf 2.1": 20:::class1
|
||||
"Leaf 2.2": 25
|
||||
"Leaf 2.3": 12
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
flowchart:
|
||||
curve: linear
|
||||
---
|
||||
flowchart LR
|
||||
A[A] -- Mermaid js --> B[B]
|
||||
A[A] -- Mermaid js --- B[B]
|
||||
A@{ shape: diamond}
|
||||
B@{ shape: diamond}
|
||||
|
||||
classDef class1 fill:red,color:blue,stroke:#FFD600;
|
||||
|
||||
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
flowchart:
|
||||
curve: rounded
|
||||
---
|
||||
flowchart LR
|
||||
D["Use the editor"] -- Mermaid js --> I["fa:fa-code Text"]
|
||||
I --> D & D
|
||||
D@{ shape: question}
|
||||
I@{ shape: question}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
flowchart:
|
||||
curve: rounded
|
||||
elk:
|
||||
nodePlacementStrategy: NETWORK_SIMPLEX
|
||||
---
|
||||
flowchart LR
|
||||
D["Use the editor"] -- Mermaid js --> I["fa:fa-code Text"]
|
||||
D --> I & I
|
||||
a["a"]
|
||||
D@{ shape: trap-b}
|
||||
I@{ shape: lean-l}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
treemap:
|
||||
valueFormat: '$0,0'
|
||||
layout: elk
|
||||
|
||||
---
|
||||
treemap
|
||||
"Budget"
|
||||
"Operations"
|
||||
"Salaries": 7000
|
||||
"Equipment": 2000
|
||||
"Supplies": 1000
|
||||
"Marketing"
|
||||
"Advertising": 4000
|
||||
"Events": 1000
|
||||
flowchart LR
|
||||
%% subgraph s1["Untitled subgraph"]
|
||||
C["Evaluate"]
|
||||
%% end
|
||||
|
||||
</pre
|
||||
>
|
||||
B --> C
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
treemap
|
||||
title Accessible Treemap Title
|
||||
"Category A"
|
||||
"Item A1": 10
|
||||
"Item A2": 20
|
||||
"Category B"
|
||||
"Item B1": 15
|
||||
"Item B2": 25
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
a
|
||||
apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
b
|
||||
apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
flowchart:
|
||||
//curve: linear
|
||||
---
|
||||
flowchart LR
|
||||
%% A ==> B
|
||||
%% A2 --> B2
|
||||
A{A} --> B((Bo boo)) & B & B & B
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
flowchart TB
|
||||
A --> n0["1"]
|
||||
A --> n1["2"]
|
||||
A --> n2["3"]
|
||||
A --> n3["4"] --> Q & R & S & T
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart TB
|
||||
A --> n0["1"]
|
||||
A --> n1["2"]
|
||||
A --> n2["3"]
|
||||
A --> n3["4"] --> Q & R & S & T
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: dagre
|
||||
---
|
||||
mindmap
|
||||
root((mindmap is a long thing))
|
||||
Origins
|
||||
Long history
|
||||
::icon(fa fa-book)
|
||||
Popularisation
|
||||
British popular psychology author Tony Buzan
|
||||
Research
|
||||
On effectiveness<br/>and features
|
||||
On Automatic creation
|
||||
Uses
|
||||
Creative techniques
|
||||
Strategic planning
|
||||
Argument mapping
|
||||
Tools
|
||||
Pen and paper
|
||||
Mermaid
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: cose-bilkent
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
Origins
|
||||
Long history
|
||||
::icon(fa fa-book)
|
||||
Popularisation
|
||||
British popular psychology author Tony Buzan
|
||||
Research
|
||||
On effectiveness<br/>and features
|
||||
On Automatic creation
|
||||
Uses
|
||||
Creative techniques
|
||||
Strategic planning
|
||||
Argument mapping
|
||||
Tools
|
||||
Pen and paper
|
||||
Mermaid
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
Origins
|
||||
Long history
|
||||
::icon(fa fa-book)
|
||||
Popularisation
|
||||
British popular psychology author Tony Buzan
|
||||
Research
|
||||
On effectiveness<br/>and features
|
||||
On Automatic creation
|
||||
Uses
|
||||
Creative techniques
|
||||
Strategic planning
|
||||
Argument mapping
|
||||
Tools
|
||||
Pen and paper
|
||||
Mermaid
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: cose-bilkent
|
||||
theme: default
|
||||
look: classic
|
||||
---
|
||||
flowchart LR
|
||||
root{mindmap} --- Origins --- Europe
|
||||
Origins --> Asia
|
||||
root --- Background --- Rich
|
||||
Background --- Poor
|
||||
subgraph apa
|
||||
Background
|
||||
Poor
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
subgraph s1["APA"]
|
||||
D{"Use the editor"}
|
||||
end
|
||||
subgraph S2["S2"]
|
||||
s1
|
||||
I>"fa:fa-code Text"]
|
||||
E["E"]
|
||||
end
|
||||
D -- Mermaid js --> I
|
||||
D --> I & E
|
||||
E --> I
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
root{mindmap} --- Origins --- Europe
|
||||
Origins --> Asia
|
||||
root --- Background --- Rich
|
||||
Background --- Poor
|
||||
|
||||
|
||||
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart
|
||||
D(("for D"))
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
A e1@==> B
|
||||
e1@{ animate: true}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
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">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -450,7 +487,7 @@ config:
|
||||
end
|
||||
end
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -463,45 +500,7 @@ config:
|
||||
D-->I
|
||||
D-->I
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
a
|
||||
subgraph s0["APA"]
|
||||
subgraph s8["APA"]
|
||||
subgraph s1["APA"]
|
||||
D{"X"}
|
||||
E[Q]
|
||||
end
|
||||
subgraph s3["BAPA"]
|
||||
F[Q]
|
||||
I
|
||||
end
|
||||
D --> I
|
||||
D --> I
|
||||
D --> I
|
||||
|
||||
I{"X"}
|
||||
end
|
||||
end
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
a
|
||||
D{"Use the editor"}
|
||||
|
||||
D -- Mermaid js --> I{"fa:fa-code Text"}
|
||||
D-->I
|
||||
D-->I
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -540,7 +539,7 @@ flowchart LR
|
||||
n8@{ shape: rect}
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -556,7 +555,7 @@ flowchart LR
|
||||
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -565,7 +564,7 @@ flowchart LR
|
||||
A{A} --> B & C
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -577,7 +576,7 @@ flowchart LR
|
||||
end
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -595,7 +594,7 @@ flowchart LR
|
||||
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
kanban:
|
||||
@@ -614,81 +613,81 @@ kanban
|
||||
task3[💻 Develop login feature]@{ ticket: 103 }
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
nA[Default] --> A@{ icon: 'fa:bell', form: 'rounded' }
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
nA[Style] --> A@{ icon: 'fa:bell', form: 'rounded' }
|
||||
style A fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
nA[Class] --> A@{ icon: 'fa:bell', form: 'rounded' }
|
||||
A:::AClass
|
||||
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
nA[Class] --> A@{ icon: 'logos:aws', form: 'rounded' }
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
nA[Default] --> A@{ icon: 'fa:bell', form: 'square' }
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
nA[Style] --> A@{ icon: 'fa:bell', form: 'square' }
|
||||
style A fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
nA[Class] --> A@{ icon: 'fa:bell', form: 'square' }
|
||||
A:::AClass
|
||||
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
nA[Class] --> A@{ icon: 'logos:aws', form: 'square' }
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
nA[Default] --> A@{ icon: 'fa:bell', form: 'circle' }
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
nA[Style] --> A@{ icon: 'fa:bell', form: 'circle' }
|
||||
style A fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
nA[Class] --> A@{ icon: 'fa:bell', form: 'circle' }
|
||||
A:::AClass
|
||||
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
nA[Class] --> A@{ icon: 'logos:aws', form: 'circle' }
|
||||
A:::AClass
|
||||
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
flowchart LR
|
||||
nA[Style] --> A@{ icon: 'logos:aws', form: 'circle' }
|
||||
style A fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
kanban
|
||||
id2[In progress]
|
||||
docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' }
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
kanban:
|
||||
@@ -752,18 +751,22 @@ kanban
|
||||
alert('It worked');
|
||||
}
|
||||
await mermaid.initialize({
|
||||
// theme: 'forest',
|
||||
// theme: 'base',
|
||||
// theme: 'default',
|
||||
// theme: 'forest',
|
||||
// handDrawnSeed: 12,
|
||||
// look: 'handDrawn',
|
||||
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
|
||||
// layout: 'dagre',
|
||||
// layout: 'elk',
|
||||
layout: 'elk',
|
||||
// layout: 'fixed',
|
||||
// htmlLabels: false,
|
||||
flowchart: { titleTopMargin: 10 },
|
||||
fontFamily: "'Recursive', sans-serif",
|
||||
|
||||
// fontFamily: 'Caveat',
|
||||
// fontFamily: 'Kalam',
|
||||
// fontFamily: 'courier',
|
||||
fontFamily: 'arial',
|
||||
sequence: {
|
||||
actorFontFamily: 'courier',
|
||||
noteFontFamily: 'courier',
|
||||
|
@@ -101,14 +101,7 @@
|
||||
C
|
||||
D
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
mindmap
|
||||
root((mindmap is a long thing))
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
</pre>
|
||||
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
@@ -369,6 +362,10 @@
|
||||
<hr />
|
||||
<script type="module">
|
||||
import mermaid from '/mermaid.esm.mjs';
|
||||
import tidytree from '/mermaid-layout-tidy-tree.esm.mjs';
|
||||
import layouts from './mermaid-layout-elk.esm.mjs';
|
||||
mermaid.registerLayoutLoaders(layouts);
|
||||
mermaid.registerLayoutLoaders(tidytree);
|
||||
mermaid.initialize({
|
||||
theme: 'default',
|
||||
logLevel: 3,
|
||||
|
@@ -41,10 +41,6 @@ graph TB
|
||||
const { svg } = await mermaid.render('d22', value);
|
||||
console.log(svg);
|
||||
el.innerHTML = svg;
|
||||
// mermaid.test1('first_slow', 1200).then((r) => console.info(r));
|
||||
// mermaid.test1('second_fast', 200).then((r) => console.info(r));
|
||||
// mermaid.test1('third_fast', 200).then((r) => console.info(r));
|
||||
// mermaid.test1('forth_slow', 1200).then((r) => console.info(r));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import externalExample from './mermaid-example-diagram.esm.mjs';
|
||||
import layouts from './mermaid-layout-elk.esm.mjs';
|
||||
import tidyTree from './mermaid-layout-tidy-tree.esm.mjs';
|
||||
import zenUml from './mermaid-zenuml.esm.mjs';
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
|
||||
@@ -65,6 +66,7 @@ const contentLoaded = async function () {
|
||||
await mermaid.registerExternalDiagrams([externalExample, zenUml]);
|
||||
|
||||
mermaid.registerLayoutLoaders(layouts);
|
||||
mermaid.registerLayoutLoaders(tidyTree);
|
||||
mermaid.initialize(graphObj.mermaid);
|
||||
/**
|
||||
* CC-BY-4.0
|
||||
@@ -182,7 +184,7 @@ const contentLoadedApi = async function () {
|
||||
for (let i = 0; i < numCodes; i++) {
|
||||
const { svg, bindFunctions } = await mermaid.render('newid' + i, graphObj.code[i], divs[i]);
|
||||
div.innerHTML = svg;
|
||||
bindFunctions(div);
|
||||
bindFunctions?.(div);
|
||||
}
|
||||
} else {
|
||||
const div = document.createElement('div');
|
||||
@@ -194,7 +196,7 @@ const contentLoadedApi = async function () {
|
||||
const { svg, bindFunctions } = await mermaid.render('newid', graphObj.code, div);
|
||||
div.innerHTML = svg;
|
||||
console.log(div.innerHTML);
|
||||
bindFunctions(div);
|
||||
bindFunctions?.(div);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -2,219 +2,227 @@
|
||||
"durations": [
|
||||
{
|
||||
"spec": "cypress/integration/other/configuration.spec.js",
|
||||
"duration": 5672
|
||||
"duration": 5841
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/other/external-diagrams.spec.js",
|
||||
"duration": 1990
|
||||
"duration": 2138
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/other/ghsa.spec.js",
|
||||
"duration": 3186
|
||||
"duration": 3370
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/other/iife.spec.js",
|
||||
"duration": 1948
|
||||
"duration": 2052
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/other/interaction.spec.js",
|
||||
"duration": 11938
|
||||
"duration": 12243
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/other/rerender.spec.js",
|
||||
"duration": 1932
|
||||
"duration": 2065
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/other/xss.spec.js",
|
||||
"duration": 27237
|
||||
"duration": 31288
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/appli.spec.js",
|
||||
"duration": 3170
|
||||
"duration": 3421
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/architecture.spec.ts",
|
||||
"duration": 104
|
||||
"duration": 97
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/block.spec.js",
|
||||
"duration": 17390
|
||||
"duration": 18500
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/c4.spec.js",
|
||||
"duration": 5296
|
||||
"duration": 5793
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/classDiagram-elk-v3.spec.js",
|
||||
"duration": 39004
|
||||
"duration": 40966
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/classDiagram-handDrawn-v3.spec.js",
|
||||
"duration": 37653
|
||||
"duration": 39176
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/classDiagram-v2.spec.js",
|
||||
"duration": 23278
|
||||
"duration": 23468
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/classDiagram-v3.spec.js",
|
||||
"duration": 36645
|
||||
"duration": 38291
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/classDiagram.spec.js",
|
||||
"duration": 15418
|
||||
"duration": 16949
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/conf-and-directives.spec.js",
|
||||
"duration": 9684
|
||||
"duration": 9480
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/current.spec.js",
|
||||
"duration": 2570
|
||||
"duration": 2753
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/erDiagram-unified.spec.js",
|
||||
"duration": 84687
|
||||
"duration": 88028
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/erDiagram.spec.js",
|
||||
"duration": 14819
|
||||
"duration": 15615
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/errorDiagram.spec.js",
|
||||
"duration": 3371
|
||||
"duration": 3706
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/flowchart-elk.spec.js",
|
||||
"duration": 39925
|
||||
"duration": 43905
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/flowchart-handDrawn.spec.js",
|
||||
"duration": 34694
|
||||
"duration": 31217
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/flowchart-icon.spec.js",
|
||||
"duration": 7137
|
||||
"duration": 7531
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/flowchart-shape-alias.spec.ts",
|
||||
"duration": 24740
|
||||
"duration": 25423
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/flowchart-v2.spec.js",
|
||||
"duration": 42077
|
||||
"duration": 49664
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/flowchart.spec.js",
|
||||
"duration": 30642
|
||||
"duration": 32525
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/gantt.spec.js",
|
||||
"duration": 18085
|
||||
"duration": 20915
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/gitGraph.spec.js",
|
||||
"duration": 50107
|
||||
"duration": 53556
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/iconShape.spec.ts",
|
||||
"duration": 276279
|
||||
"duration": 283038
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/imageShape.spec.ts",
|
||||
"duration": 56505
|
||||
"duration": 59434
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/info.spec.ts",
|
||||
"duration": 3036
|
||||
"duration": 3101
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/journey.spec.js",
|
||||
"duration": 6889
|
||||
"duration": 7099
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/kanban.spec.ts",
|
||||
"duration": 7353
|
||||
"duration": 7567
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/katex.spec.js",
|
||||
"duration": 3580
|
||||
"duration": 3817
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/marker_unique_id.spec.js",
|
||||
"duration": 2508
|
||||
"duration": 2624
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/mindmap-tidy-tree.spec.js",
|
||||
"duration": 4246
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/mindmap.spec.ts",
|
||||
"duration": 10939
|
||||
"duration": 11967
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/newShapes.spec.ts",
|
||||
"duration": 149102
|
||||
"duration": 151914
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/oldShapes.spec.ts",
|
||||
"duration": 113987
|
||||
"duration": 116698
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/packet.spec.ts",
|
||||
"duration": 4060
|
||||
"duration": 4967
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/pie.spec.ts",
|
||||
"duration": 5715
|
||||
"duration": 6700
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/quadrantChart.spec.js",
|
||||
"duration": 8945
|
||||
"duration": 8963
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/radar.spec.js",
|
||||
"duration": 5337
|
||||
"duration": 5540
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/requirement.spec.js",
|
||||
"duration": 2643
|
||||
"duration": 2782
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/requirementDiagram-unified.spec.js",
|
||||
"duration": 52072
|
||||
"duration": 54797
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/sankey.spec.ts",
|
||||
"duration": 6692
|
||||
"duration": 6914
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/sequencediagram-v2.spec.js",
|
||||
"duration": 20481
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/sequencediagram.spec.js",
|
||||
"duration": 35721
|
||||
"duration": 38490
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/stateDiagram-v2.spec.js",
|
||||
"duration": 26030
|
||||
"duration": 30766
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/stateDiagram.spec.js",
|
||||
"duration": 16333
|
||||
"duration": 16705
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/theme.spec.js",
|
||||
"duration": 29287
|
||||
"duration": 30928
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/timeline.spec.ts",
|
||||
"duration": 8491
|
||||
"duration": 8424
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/treemap.spec.ts",
|
||||
"duration": 12291
|
||||
"duration": 12533
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/xyChart.spec.js",
|
||||
"duration": 20651
|
||||
"duration": 21197
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/zenuml.spec.js",
|
||||
"duration": 3218
|
||||
"duration": 3455
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"lib": ["es2020", "dom"],
|
||||
"types": ["cypress", "node", "@argos-ci/cypress/dist/support.d.ts"],
|
||||
"types": ["cypress", "node", "@argos-ci/cypress/support"],
|
||||
"allowImportingTsExtensions": true,
|
||||
"noEmit": true
|
||||
},
|
||||
|
@@ -11,7 +11,7 @@
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
|
@@ -20,14 +20,14 @@
|
||||
width: 800
|
||||
nodeAlignment: left
|
||||
---
|
||||
sankey
|
||||
sankey
|
||||
a,b,8
|
||||
b,c,8
|
||||
c,d,8
|
||||
d,e,8
|
||||
|
||||
|
||||
x,c,4
|
||||
c,y,4
|
||||
c,y,4
|
||||
</pre>
|
||||
|
||||
<h2>Energy flow</h2>
|
||||
|
@@ -6,7 +6,7 @@
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
1. [How to add title to flowchart?](https://github.com/mermaid-js/mermaid/issues/556#issuecomment-363182217)
|
||||
1. [How to add title to flowchart?](https://github.com/mermaid-js/mermaid/issues/1433#issuecomment-1991554712)
|
||||
2. [How to specify custom CSS file?](https://github.com/mermaidjs/mermaid.cli/pull/24#issuecomment-373402785)
|
||||
3. [How to fix tooltip misplacement issue?](https://github.com/mermaid-js/mermaid/issues/542#issuecomment-3343564621)
|
||||
4. [How to specify gantt diagram xAxis format?](https://github.com/mermaid-js/mermaid/issues/269#issuecomment-373229136)
|
||||
|
40
docs/config/layouts.md
Normal file
40
docs/config/layouts.md
Normal file
@@ -0,0 +1,40 @@
|
||||
> **Warning**
|
||||
>
|
||||
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
|
||||
>
|
||||
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/layouts.md](../../packages/mermaid/src/docs/config/layouts.md).
|
||||
|
||||
# Layouts
|
||||
|
||||
This page lists the available layout algorithms supported in Mermaid diagrams.
|
||||
|
||||
## Supported Layouts
|
||||
|
||||
- **elk**: [ELK (Eclipse Layout Kernel)](https://www.eclipse.org/elk/)
|
||||
- **tidy-tree**: Tidy tree layout for hierarchical diagrams [Tidy Tree Configuration](/config/tidy-tree)
|
||||
- **cose-bilkent**: Cose Bilkent layout for force-directed graphs
|
||||
- **dagre**: Dagre layout for layered graphs
|
||||
|
||||
## How to Use
|
||||
|
||||
You can specify the layout in your diagram's YAML config or initialization options. For example:
|
||||
|
||||
```mermaid-example
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
graph TD;
|
||||
A-->B;
|
||||
B-->C;
|
||||
```
|
||||
|
||||
```mermaid
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
graph TD;
|
||||
A-->B;
|
||||
B-->C;
|
||||
```
|
@@ -19,6 +19,7 @@
|
||||
- [addDirective](functions/addDirective.md)
|
||||
- [getConfig](functions/getConfig.md)
|
||||
- [getSiteConfig](functions/getSiteConfig.md)
|
||||
- [getUserDefinedConfig](functions/getUserDefinedConfig.md)
|
||||
- [reset](functions/reset.md)
|
||||
- [sanitize](functions/sanitize.md)
|
||||
- [saveConfigFromInitialize](functions/saveConfigFromInitialize.md)
|
||||
|
19
docs/config/setup/config/functions/getUserDefinedConfig.md
Normal file
19
docs/config/setup/config/functions/getUserDefinedConfig.md
Normal file
@@ -0,0 +1,19 @@
|
||||
> **Warning**
|
||||
>
|
||||
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
|
||||
>
|
||||
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/config/functions/getUserDefinedConfig.md](../../../../../packages/mermaid/src/docs/config/setup/config/functions/getUserDefinedConfig.md).
|
||||
|
||||
[**mermaid**](../../README.md)
|
||||
|
||||
---
|
||||
|
||||
# Function: getUserDefinedConfig()
|
||||
|
||||
> **getUserDefinedConfig**(): [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md)
|
||||
|
||||
Defined in: [packages/mermaid/src/config.ts:252](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L252)
|
||||
|
||||
## Returns
|
||||
|
||||
[`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md)
|
@@ -12,4 +12,4 @@
|
||||
|
||||
> `const` **configKeys**: `Set`<`string`>
|
||||
|
||||
Defined in: [packages/mermaid/src/defaultConfig.ts:290](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L290)
|
||||
Defined in: [packages/mermaid/src/defaultConfig.ts:292](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L292)
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
# Interface: ExternalDiagramDefinition
|
||||
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:94](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L94)
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L96)
|
||||
|
||||
## Properties
|
||||
|
||||
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/diagram-api/types.ts:94](https://github.com/me
|
||||
|
||||
> **detector**: `DiagramDetector`
|
||||
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L96)
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:98](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L98)
|
||||
|
||||
---
|
||||
|
||||
@@ -26,7 +26,7 @@ Defined in: [packages/mermaid/src/diagram-api/types.ts:96](https://github.com/me
|
||||
|
||||
> **id**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:95](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L95)
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:97](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L97)
|
||||
|
||||
---
|
||||
|
||||
@@ -34,4 +34,4 @@ Defined in: [packages/mermaid/src/diagram-api/types.ts:95](https://github.com/me
|
||||
|
||||
> **loader**: `DiagramLoader`
|
||||
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:97](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L97)
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:99](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L99)
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
# Interface: LayoutData
|
||||
|
||||
Defined in: [packages/mermaid/src/rendering-util/types.ts:170](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L170)
|
||||
Defined in: [packages/mermaid/src/rendering-util/types.ts:168](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L168)
|
||||
|
||||
## Indexable
|
||||
|
||||
@@ -22,7 +22,7 @@ Defined in: [packages/mermaid/src/rendering-util/types.ts:170](https://github.co
|
||||
|
||||
> **config**: [`MermaidConfig`](MermaidConfig.md)
|
||||
|
||||
Defined in: [packages/mermaid/src/rendering-util/types.ts:173](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L173)
|
||||
Defined in: [packages/mermaid/src/rendering-util/types.ts:171](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L171)
|
||||
|
||||
---
|
||||
|
||||
@@ -30,7 +30,7 @@ Defined in: [packages/mermaid/src/rendering-util/types.ts:173](https://github.co
|
||||
|
||||
> **edges**: `Edge`\[]
|
||||
|
||||
Defined in: [packages/mermaid/src/rendering-util/types.ts:172](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L172)
|
||||
Defined in: [packages/mermaid/src/rendering-util/types.ts:170](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L170)
|
||||
|
||||
---
|
||||
|
||||
@@ -38,4 +38,4 @@ Defined in: [packages/mermaid/src/rendering-util/types.ts:172](https://github.co
|
||||
|
||||
> **nodes**: `Node`\[]
|
||||
|
||||
Defined in: [packages/mermaid/src/rendering-util/types.ts:171](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L171)
|
||||
Defined in: [packages/mermaid/src/rendering-util/types.ts:169](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L169)
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
# Interface: LayoutLoaderDefinition
|
||||
|
||||
Defined in: [packages/mermaid/src/rendering-util/render.ts:21](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L21)
|
||||
Defined in: [packages/mermaid/src/rendering-util/render.ts:24](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L24)
|
||||
|
||||
## Properties
|
||||
|
||||
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/rendering-util/render.ts:21](https://github.co
|
||||
|
||||
> `optional` **algorithm**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/rendering-util/render.ts:24](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L24)
|
||||
Defined in: [packages/mermaid/src/rendering-util/render.ts:27](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L27)
|
||||
|
||||
---
|
||||
|
||||
@@ -26,7 +26,7 @@ Defined in: [packages/mermaid/src/rendering-util/render.ts:24](https://github.co
|
||||
|
||||
> **loader**: `LayoutLoader`
|
||||
|
||||
Defined in: [packages/mermaid/src/rendering-util/render.ts:23](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L23)
|
||||
Defined in: [packages/mermaid/src/rendering-util/render.ts:26](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L26)
|
||||
|
||||
---
|
||||
|
||||
@@ -34,4 +34,4 @@ Defined in: [packages/mermaid/src/rendering-util/render.ts:23](https://github.co
|
||||
|
||||
> **name**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/rendering-util/render.ts:22](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L22)
|
||||
Defined in: [packages/mermaid/src/rendering-util/render.ts:25](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L25)
|
||||
|
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/config.type.ts:58](https://github.com/mermaid-
|
||||
|
||||
> `optional` **altFontFamily**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:122](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L122)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:132](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L132)
|
||||
|
||||
---
|
||||
|
||||
@@ -26,7 +26,7 @@ Defined in: [packages/mermaid/src/config.type.ts:122](https://github.com/mermaid
|
||||
|
||||
> `optional` **architecture**: `ArchitectureDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:194](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L194)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:204](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L204)
|
||||
|
||||
---
|
||||
|
||||
@@ -34,7 +34,7 @@ Defined in: [packages/mermaid/src/config.type.ts:194](https://github.com/mermaid
|
||||
|
||||
> `optional` **arrowMarkerAbsolute**: `boolean`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:141](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L141)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:151](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L151)
|
||||
|
||||
Controls whether or arrow markers in html code are absolute paths or anchors.
|
||||
This matters if you are using base tag settings.
|
||||
@@ -45,7 +45,7 @@ This matters if you are using base tag settings.
|
||||
|
||||
> `optional` **block**: `BlockDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:201](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L201)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:211](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L211)
|
||||
|
||||
---
|
||||
|
||||
@@ -53,7 +53,7 @@ Defined in: [packages/mermaid/src/config.type.ts:201](https://github.com/mermaid
|
||||
|
||||
> `optional` **c4**: `C4DiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:198](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L198)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:208](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L208)
|
||||
|
||||
---
|
||||
|
||||
@@ -61,7 +61,7 @@ Defined in: [packages/mermaid/src/config.type.ts:198](https://github.com/mermaid
|
||||
|
||||
> `optional` **class**: `ClassDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:187](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L187)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:197](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L197)
|
||||
|
||||
---
|
||||
|
||||
@@ -69,7 +69,7 @@ Defined in: [packages/mermaid/src/config.type.ts:187](https://github.com/mermaid
|
||||
|
||||
> `optional` **darkMode**: `boolean`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:113](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L113)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:123](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L123)
|
||||
|
||||
---
|
||||
|
||||
@@ -77,7 +77,7 @@ Defined in: [packages/mermaid/src/config.type.ts:113](https://github.com/mermaid
|
||||
|
||||
> `optional` **deterministicIds**: `boolean`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:174](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L174)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:184](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L184)
|
||||
|
||||
This option controls if the generated ids of nodes in the SVG are
|
||||
generated randomly or based on a seed.
|
||||
@@ -93,7 +93,7 @@ should not change unless content is changed.
|
||||
|
||||
> `optional` **deterministicIDSeed**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:181](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L181)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:191](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L191)
|
||||
|
||||
This option is the optional seed for deterministic ids.
|
||||
If set to `undefined` but deterministicIds is `true`, a simple number iterator is used.
|
||||
@@ -105,7 +105,7 @@ You can set this attribute to base the seed on a static string.
|
||||
|
||||
> `optional` **dompurifyConfig**: `Config`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:203](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L203)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:213](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L213)
|
||||
|
||||
---
|
||||
|
||||
@@ -115,12 +115,24 @@ Defined in: [packages/mermaid/src/config.type.ts:203](https://github.com/mermaid
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:91](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L91)
|
||||
|
||||
#### considerModelOrder?
|
||||
|
||||
> `optional` **considerModelOrder**: `"NONE"` | `"NODES_AND_EDGES"` | `"PREFER_EDGES"` | `"PREFER_NODES"`
|
||||
|
||||
Preserves the order of nodes and edges in the model file if this does not lead to additional edge crossings. Depending on the strategy this is not always possible since the node and edge order might be conflicting.
|
||||
|
||||
#### cycleBreakingStrategy?
|
||||
|
||||
> `optional` **cycleBreakingStrategy**: `"GREEDY"` | `"DEPTH_FIRST"` | `"INTERACTIVE"` | `"MODEL_ORDER"` | `"GREEDY_MODEL_ORDER"`
|
||||
|
||||
This strategy decides how to find cycles in the graph and deciding which edges need adjustment to break loops.
|
||||
|
||||
#### forceNodeModelOrder?
|
||||
|
||||
> `optional` **forceNodeModelOrder**: `boolean`
|
||||
|
||||
The node order given by the model does not change to produce a better layout. E.g. if node A is before node B in the model this is not changed during crossing minimization. This assumes that the node model order is already respected before crossing minimization. This can be achieved by setting considerModelOrder.strategy to NODES_AND_EDGES.
|
||||
|
||||
#### mergeEdges?
|
||||
|
||||
> `optional` **mergeEdges**: `boolean`
|
||||
@@ -139,7 +151,7 @@ Elk specific option affecting how nodes are placed.
|
||||
|
||||
> `optional` **er**: `ErDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:189](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L189)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:199](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L199)
|
||||
|
||||
---
|
||||
|
||||
@@ -147,7 +159,7 @@ Defined in: [packages/mermaid/src/config.type.ts:189](https://github.com/mermaid
|
||||
|
||||
> `optional` **flowchart**: `FlowchartDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:182](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L182)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:192](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L192)
|
||||
|
||||
---
|
||||
|
||||
@@ -155,7 +167,7 @@ Defined in: [packages/mermaid/src/config.type.ts:182](https://github.com/mermaid
|
||||
|
||||
> `optional` **fontFamily**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:121](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L121)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:131](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L131)
|
||||
|
||||
Specifies the font to be used in the rendered diagrams.
|
||||
Can be any possible CSS `font-family`.
|
||||
@@ -167,7 +179,7 @@ See <https://developer.mozilla.org/en-US/docs/Web/CSS/font-family>
|
||||
|
||||
> `optional` **fontSize**: `number`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:205](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L205)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:215](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L215)
|
||||
|
||||
---
|
||||
|
||||
@@ -175,7 +187,7 @@ Defined in: [packages/mermaid/src/config.type.ts:205](https://github.com/mermaid
|
||||
|
||||
> `optional` **forceLegacyMathML**: `boolean`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:163](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L163)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:173](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L173)
|
||||
|
||||
This option forces Mermaid to rely on KaTeX's own stylesheet for rendering MathML. Due to differences between OS
|
||||
fonts and browser's MathML implementation, this option is recommended if consistent rendering is important.
|
||||
@@ -187,7 +199,7 @@ If set to true, ignores legacyMathML.
|
||||
|
||||
> `optional` **gantt**: `GanttDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:184](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L184)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:194](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L194)
|
||||
|
||||
---
|
||||
|
||||
@@ -195,7 +207,7 @@ Defined in: [packages/mermaid/src/config.type.ts:184](https://github.com/mermaid
|
||||
|
||||
> `optional` **gitGraph**: `GitGraphDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:197](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L197)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:207](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L207)
|
||||
|
||||
---
|
||||
|
||||
@@ -213,7 +225,7 @@ Defines the seed to be used when using handDrawn look. This is important for the
|
||||
|
||||
> `optional` **htmlLabels**: `boolean`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:114](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L114)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:124](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L124)
|
||||
|
||||
---
|
||||
|
||||
@@ -221,7 +233,7 @@ Defined in: [packages/mermaid/src/config.type.ts:114](https://github.com/mermaid
|
||||
|
||||
> `optional` **journey**: `JourneyDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:185](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L185)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:195](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L195)
|
||||
|
||||
---
|
||||
|
||||
@@ -229,7 +241,7 @@ Defined in: [packages/mermaid/src/config.type.ts:185](https://github.com/mermaid
|
||||
|
||||
> `optional` **kanban**: `KanbanDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:196](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L196)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:206](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L206)
|
||||
|
||||
---
|
||||
|
||||
@@ -247,7 +259,7 @@ Defines which layout algorithm to use for rendering the diagram.
|
||||
|
||||
> `optional` **legacyMathML**: `boolean`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:156](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L156)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:166](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L166)
|
||||
|
||||
This option specifies if Mermaid can expect the dependent to include KaTeX stylesheets for browsers
|
||||
without their own MathML implementation. If this option is disabled and MathML is not supported, the math
|
||||
@@ -260,7 +272,7 @@ fall back to legacy rendering for KaTeX.
|
||||
|
||||
> `optional` **logLevel**: `0` | `2` | `1` | `"trace"` | `"debug"` | `"info"` | `"warn"` | `"error"` | `"fatal"` | `3` | `4` | `5`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:127](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L127)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:137](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L137)
|
||||
|
||||
This option decides the amount of logging to be used by mermaid.
|
||||
|
||||
@@ -280,7 +292,7 @@ Defines which main look to use for the diagram.
|
||||
|
||||
> `optional` **markdownAutoWrap**: `boolean`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:206](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L206)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:216](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L216)
|
||||
|
||||
---
|
||||
|
||||
@@ -308,7 +320,7 @@ The maximum allowed size of the users text diagram
|
||||
|
||||
> `optional` **mindmap**: `MindmapDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:195](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L195)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:205](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L205)
|
||||
|
||||
---
|
||||
|
||||
@@ -316,7 +328,7 @@ Defined in: [packages/mermaid/src/config.type.ts:195](https://github.com/mermaid
|
||||
|
||||
> `optional` **packet**: `PacketDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:200](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L200)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:210](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L210)
|
||||
|
||||
---
|
||||
|
||||
@@ -324,7 +336,7 @@ Defined in: [packages/mermaid/src/config.type.ts:200](https://github.com/mermaid
|
||||
|
||||
> `optional` **pie**: `PieDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:190](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L190)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:200](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L200)
|
||||
|
||||
---
|
||||
|
||||
@@ -332,7 +344,7 @@ Defined in: [packages/mermaid/src/config.type.ts:190](https://github.com/mermaid
|
||||
|
||||
> `optional` **quadrantChart**: `QuadrantChartConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:191](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L191)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:201](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L201)
|
||||
|
||||
---
|
||||
|
||||
@@ -340,7 +352,7 @@ Defined in: [packages/mermaid/src/config.type.ts:191](https://github.com/mermaid
|
||||
|
||||
> `optional` **radar**: `RadarDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:202](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L202)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:212](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L212)
|
||||
|
||||
---
|
||||
|
||||
@@ -348,7 +360,7 @@ Defined in: [packages/mermaid/src/config.type.ts:202](https://github.com/mermaid
|
||||
|
||||
> `optional` **requirement**: `RequirementDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:193](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L193)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:203](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L203)
|
||||
|
||||
---
|
||||
|
||||
@@ -356,7 +368,7 @@ Defined in: [packages/mermaid/src/config.type.ts:193](https://github.com/mermaid
|
||||
|
||||
> `optional` **sankey**: `SankeyDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:199](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L199)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:209](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L209)
|
||||
|
||||
---
|
||||
|
||||
@@ -364,7 +376,7 @@ Defined in: [packages/mermaid/src/config.type.ts:199](https://github.com/mermaid
|
||||
|
||||
> `optional` **secure**: `string`\[]
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:148](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L148)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:158](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L158)
|
||||
|
||||
This option controls which `currentConfig` keys are considered secure and
|
||||
can only be changed via call to `mermaid.initialize`.
|
||||
@@ -376,7 +388,7 @@ This prevents malicious graph directives from overriding a site's default securi
|
||||
|
||||
> `optional` **securityLevel**: `"strict"` | `"loose"` | `"antiscript"` | `"sandbox"`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:131](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L131)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:141](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L141)
|
||||
|
||||
Level of trust for parsed diagram
|
||||
|
||||
@@ -386,7 +398,7 @@ Level of trust for parsed diagram
|
||||
|
||||
> `optional` **sequence**: `SequenceDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:183](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L183)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:193](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L193)
|
||||
|
||||
---
|
||||
|
||||
@@ -394,7 +406,7 @@ Defined in: [packages/mermaid/src/config.type.ts:183](https://github.com/mermaid
|
||||
|
||||
> `optional` **startOnLoad**: `boolean`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:135](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L135)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:145](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L145)
|
||||
|
||||
Dictates whether mermaid starts on Page load
|
||||
|
||||
@@ -404,7 +416,7 @@ Dictates whether mermaid starts on Page load
|
||||
|
||||
> `optional` **state**: `StateDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:188](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L188)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:198](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L198)
|
||||
|
||||
---
|
||||
|
||||
@@ -412,7 +424,7 @@ Defined in: [packages/mermaid/src/config.type.ts:188](https://github.com/mermaid
|
||||
|
||||
> `optional` **suppressErrorRendering**: `boolean`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:212](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L212)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:222](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L222)
|
||||
|
||||
Suppresses inserting 'Syntax error' diagram in the DOM.
|
||||
This is useful when you want to control how to handle syntax errors in your application.
|
||||
@@ -450,7 +462,7 @@ Defined in: [packages/mermaid/src/config.type.ts:65](https://github.com/mermaid-
|
||||
|
||||
> `optional` **timeline**: `TimelineDiagramConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:186](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L186)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:196](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L196)
|
||||
|
||||
---
|
||||
|
||||
@@ -458,7 +470,7 @@ Defined in: [packages/mermaid/src/config.type.ts:186](https://github.com/mermaid
|
||||
|
||||
> `optional` **wrap**: `boolean`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:204](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L204)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:214](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L214)
|
||||
|
||||
---
|
||||
|
||||
@@ -466,4 +478,4 @@ Defined in: [packages/mermaid/src/config.type.ts:204](https://github.com/mermaid
|
||||
|
||||
> `optional` **xyChart**: `XYChartConfig`
|
||||
|
||||
Defined in: [packages/mermaid/src/config.type.ts:192](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L192)
|
||||
Defined in: [packages/mermaid/src/config.type.ts:202](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L202)
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
# Interface: ParseOptions
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:76](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L76)
|
||||
Defined in: [packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L88)
|
||||
|
||||
## Properties
|
||||
|
||||
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:76](https://github.com/mermaid-js/mer
|
||||
|
||||
> `optional` **suppressErrors**: `boolean`
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:81](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L81)
|
||||
Defined in: [packages/mermaid/src/types.ts:93](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L93)
|
||||
|
||||
If `true`, parse will return `false` instead of throwing error when the diagram is invalid.
|
||||
The `parseError` function will not be called.
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
# Interface: ParseResult
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:84](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L84)
|
||||
Defined in: [packages/mermaid/src/types.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L96)
|
||||
|
||||
## Properties
|
||||
|
||||
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:84](https://github.com/mermaid-js/mer
|
||||
|
||||
> **config**: [`MermaidConfig`](MermaidConfig.md)
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:92](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L92)
|
||||
Defined in: [packages/mermaid/src/types.ts:104](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L104)
|
||||
|
||||
The config passed as YAML frontmatter or directives
|
||||
|
||||
@@ -28,6 +28,6 @@ The config passed as YAML frontmatter or directives
|
||||
|
||||
> **diagramType**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L88)
|
||||
Defined in: [packages/mermaid/src/types.ts:100](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L100)
|
||||
|
||||
The diagram type, e.g. 'flowchart', 'sequence', etc.
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
# Interface: RenderOptions
|
||||
|
||||
Defined in: [packages/mermaid/src/rendering-util/render.ts:7](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L7)
|
||||
Defined in: [packages/mermaid/src/rendering-util/render.ts:10](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L10)
|
||||
|
||||
## Properties
|
||||
|
||||
@@ -18,4 +18,4 @@ Defined in: [packages/mermaid/src/rendering-util/render.ts:7](https://github.com
|
||||
|
||||
> `optional` **algorithm**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/rendering-util/render.ts:8](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L8)
|
||||
Defined in: [packages/mermaid/src/rendering-util/render.ts:11](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L11)
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
# Interface: RenderResult
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:102](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L102)
|
||||
Defined in: [packages/mermaid/src/types.ts:114](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L114)
|
||||
|
||||
## Properties
|
||||
|
||||
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:102](https://github.com/mermaid-js/me
|
||||
|
||||
> `optional` **bindFunctions**: (`element`) => `void`
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:120](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L120)
|
||||
Defined in: [packages/mermaid/src/types.ts:132](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L132)
|
||||
|
||||
Bind function to be called after the svg has been inserted into the DOM.
|
||||
This is necessary for adding event listeners to the elements in the svg.
|
||||
@@ -45,7 +45,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
|
||||
|
||||
> **diagramType**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:110](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L110)
|
||||
Defined in: [packages/mermaid/src/types.ts:122](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L122)
|
||||
|
||||
The diagram type, e.g. 'flowchart', 'sequence', etc.
|
||||
|
||||
@@ -55,6 +55,6 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
|
||||
|
||||
> **svg**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/types.ts:106](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L106)
|
||||
Defined in: [packages/mermaid/src/types.ts:118](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L118)
|
||||
|
||||
The svg code for the rendered graph.
|
||||
|
@@ -12,4 +12,4 @@
|
||||
|
||||
> **SVG** = `d3.Selection`<`SVGSVGElement`, `unknown`, `Element` | `null`, `unknown`>
|
||||
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:126](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L126)
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:128](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L128)
|
||||
|
@@ -12,4 +12,4 @@
|
||||
|
||||
> **SVGGroup** = `d3.Selection`<`SVGGElement`, `unknown`, `Element` | `null`, `unknown`>
|
||||
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:128](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L128)
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:130](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L130)
|
||||
|
@@ -4,28 +4,19 @@
|
||||
>
|
||||
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/tidy-tree.md](../../packages/mermaid/src/docs/config/tidy-tree.md).
|
||||
|
||||
# Tidy-tree Layout Instructions
|
||||
# Tidy-tree Layout
|
||||
|
||||
Instructions to use the Tidy-tree layout algorithm.
|
||||
The **tidy-tree** layout arranges nodes in a hierarchical, tree-like structure. It is especially useful for diagrams where parent-child relationships are important, such as mindmaps.
|
||||
|
||||
## Getting Started
|
||||
## Features
|
||||
|
||||
### Installation
|
||||
- Organizes nodes in a tidy, non-overlapping tree
|
||||
- Ideal for mindmaps and hierarchical data
|
||||
- Automatically adjusts spacing for readability
|
||||
|
||||
```bash
|
||||
npm install non-layered-tidy-tree-layout
|
||||
# or
|
||||
yarn add non-layered-tidy-tree-layout
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
|
||||
There's also a built version: `dist/non-layered-tidy-tree-layout.js` for use with browser `<script>` tag, or as a Javascript module.
|
||||
|
||||
## Tidy tree Layouts
|
||||
|
||||
Mermaid also supports a Tidy Tree layout for mindmaps.
|
||||
|
||||
```
|
||||
```mermaid-example
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
@@ -38,26 +29,61 @@ root((mindmap is a long thing))
|
||||
D
|
||||
```
|
||||
|
||||
### With bundlers
|
||||
|
||||
```sh
|
||||
npm install @mermaid-js/layout-tidy-tree
|
||||
```mermaid
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap is a long thing))
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
```
|
||||
|
||||
```ts
|
||||
import mermaid from 'mermaid';
|
||||
import tidyTreeLayouts from '@mermaid-js/layout-tidy-tree';
|
||||
|
||||
mermaid.registerLayoutLoaders(tidyTreeLayouts);
|
||||
```mermaid-example
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
Origins
|
||||
Long history
|
||||
::icon(fa fa-book)
|
||||
Popularisation
|
||||
British popular psychology author Tony Buzan
|
||||
Research
|
||||
On effectiveness<br/>and features
|
||||
On Automatic creation
|
||||
Uses
|
||||
Creative techniques
|
||||
Strategic planning
|
||||
Argument mapping
|
||||
```
|
||||
|
||||
### With CDN
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
||||
import tidyTreeLayouts from 'https://cdn.jsdelivr.net/npm/@mermaid-js/layout-tidy-tree@0/dist/mermaid-layout-tidy-tree.esm.min.mjs';
|
||||
|
||||
mermaid.registerLayoutLoaders(tidyTreeLayouts);
|
||||
</script>
|
||||
```mermaid
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
Origins
|
||||
Long history
|
||||
::icon(fa fa-book)
|
||||
Popularisation
|
||||
British popular psychology author Tony Buzan
|
||||
Research
|
||||
On effectiveness<br/>and features
|
||||
On Automatic creation
|
||||
Uses
|
||||
Creative techniques
|
||||
Strategic planning
|
||||
Argument mapping
|
||||
```
|
||||
|
||||
## Note
|
||||
|
||||
- Currently, tidy-tree is primarily supported for mindmap diagrams.
|
||||
|
@@ -73,7 +73,7 @@ To add an integration to this list, see the [Integrations - create page](./integ
|
||||
- [Obsidian](https://help.obsidian.md/Editing+and+formatting/Advanced+formatting+syntax#Diagram) ✅
|
||||
- [Outline](https://docs.getoutline.com/s/guide/doc/diagrams-KQiKoT4wzK) ✅
|
||||
- [Redmine](https://redmine.org)
|
||||
- [Mermaid Macro](https://www.redmine.org/plugins/redmine_mermaid_macro)
|
||||
- [Mermaid Macro](https://redmine.org/plugins/redmine_mermaid_macro)
|
||||
- [Markdown for mermaid plugin](https://github.com/jamieh-mongolian/markdown-for-mermaid-plugin)
|
||||
- [redmine-mermaid](https://github.com/styz/redmine_mermaid)
|
||||
- Visual Studio Code [Polyglot Interactive Notebooks](https://github.com/dotnet/interactive#net-interactive)
|
||||
@@ -117,7 +117,7 @@ Content Management Systems/Enterprise Content Management
|
||||
- [Grav CMS](https://getgrav.org/)
|
||||
- [Mermaid Diagrams Plugin](https://github.com/DanielFlaum/grav-plugin-mermaid-diagrams)
|
||||
- [GitLab Markdown Adapter](https://github.com/Goutte/grav-plugin-gitlab-markdown-adapter)
|
||||
- [Tiki](https://tiki.org)
|
||||
- [Tiki Wiki CMS Groupware](https://tiki.org)
|
||||
- [Tracker Entity Relationship Diagram](https://doc.tiki.org/Tracker-Entity-Relationship-Diagram)
|
||||
- [VitePress](https://vitepress.vuejs.org/)
|
||||
- [Plugin for Mermaid.js](https://emersonbottero.github.io/vitepress-plugin-mermaid/)
|
||||
|
@@ -6,6 +6,78 @@
|
||||
|
||||
# Blog
|
||||
|
||||
## [The Essential Guide to Mermaid Chart Plugin for VS Code \[08/2025\]](https://docs.mermaidchart.com/blog/posts/the-essential-guide-to-mermaid-chart-plugin-for-vs-code-08-2025)
|
||||
|
||||
9/9/2025 • 5 mins
|
||||
|
||||
Creating diagrams in VS Code has never been easier—the Mermaid VS Code plugin transforms text-based syntax into clear, professional visuals right inside your editor. With live previews, smart editing, and AI-powered diagram generation, it removes the friction from visualization so you can focus on coding.
|
||||
|
||||
## [How to Create Perfect Flowcharts Using AI in 2025 Step-by-Step Guide](https://docs.mermaidchart.com/blog/posts/how-to-create-perfect-flowcharts-using-ai-in-2025-step-by-step-guide)
|
||||
|
||||
7/22/2025 • 8 mins
|
||||
|
||||
In 2025, AI tools make creating flowcharts faster and easier than ever. With Mermaid’s AI flowchart generator, you can turn plain text into clear, accurate diagrams in seconds. This guide walks through how it works and how to get the most out of it for technical and business workflows alike.
|
||||
|
||||
## [Mermaid introduces the Visual Editor for Entity Relationship diagrams](https://docs.mermaidchart.com/blog/posts/mermaid-introduces-the-visual-editor-for-entity-relationship-diagrams)
|
||||
|
||||
7/15/2025 • 7 mins
|
||||
|
||||
Mermaid just introduced a Visual Editor for Entity Relationship diagrams, letting anyone map database structures through a simple point-and-click interface instead of code. This no-code ER builder now sits alongside Mermaid’s editors for flowcharts, sequence, and class diagrams, enabling teams to craft and share polished data models for apps, AI, and business processes.
|
||||
|
||||
## [Mermaid supports Treemap Diagrams now!!!](https://docs.mermaidchart.com/blog/posts/mermaid-have-treemap-diagrams-now)
|
||||
|
||||
7/3/2025 • 4 mins
|
||||
|
||||
Mermaid has introduced Treemap diagrams, currently in beta, enhancing hierarchical data visualization. Treemap diagrams use nested rectangles to represent data relationships, focusing on size and proportions. They offer various applications, including budget visualization and market analysis. With simple syntax and customization options, users can effectively present complex data hierarchies.
|
||||
|
||||
## [AI Diagram Generators and Data Visualization: Best Practices](https://docs.mermaidchart.com/blog/posts/ai-diagram-generators-and-data-visualization-best-practices)
|
||||
|
||||
7/2/2025 • 6 mins
|
||||
|
||||
AI diagram generators transform complex data into clear, interactive visuals – enabling faster analysis, better decisions, and stronger collaboration across teams. By combining automation with manual refinement, these tools empower anyone to communicate insights effectively, regardless of technical skill level.
|
||||
|
||||
## [How to Choose the Best AI Diagram Generator for Your Needs (2025)](https://docs.mermaidchart.com/blog/posts/how-to-choose-the-best-ai-diagram-generator-for-your-needs-2025)
|
||||
|
||||
6/26/2025 • 14 mins
|
||||
|
||||
AI diagram generators are transforming how developers visualize and communicate complex systems, reducing hours of manual work into minutes. With tools like Mermaid AI, users benefit from both code-based and visual editing, enabling seamless collaboration and precision. Whether you’re diagramming workflows, software architecture, or data relationships, the right AI tool can significantly boost productivity and streamline communication.
|
||||
|
||||
## [5 Time-Saving Tips for Using Mermaid’s AI Diagram Generator Effectively](https://docs.mermaidchart.com/blog/posts/5-time-saving-tips-for-using-mermaids-ai-diagram-generator-effectively)
|
||||
|
||||
6/11/2025 • 10 mins
|
||||
|
||||
See how developers can save time and boost productivity using Mermaid Chart’s AI diagram generator. Learn five practical tips that help turn plain language into powerful, professional diagrams.
|
||||
|
||||
## [Enhancing Team Collaboration with AI-Powered Diagrams](https://docs.mermaidchart.com/blog/posts/enhancing-team-collaboration-with-ai-powered-diagrams)
|
||||
|
||||
5/27/2025 • 6 mins
|
||||
|
||||
Software teams move fast, but old-school diagramming tools can’t keep up. Mermaid Chart replaces static slides and whiteboards with real-time, AI-generated visuals that evolve with your code and ideas. Just describe a process in plain English, and watch it come to life.
|
||||
|
||||
## [What is an AI Diagram Generator? Benefits and Use Cases](https://docs.mermaidchart.com/blog/posts/what-is-an-ai-diagram-generator-benefits-and-use-cases)
|
||||
|
||||
5/22/2025 • 6 mins
|
||||
|
||||
Discover how AI diagram generators like Mermaid Chart transform developer workflows. Instantly turn text into flowcharts, ERDs, and system diagrams, no manual drag-and-drop needed. Learn how it works, key benefits, and real-world use cases.
|
||||
|
||||
## [How to Use Mermaid Chart as an AI Diagram Generator for Developers](https://docs.mermaidchart.com/blog/posts/how-to-use-mermaid-chart-as-an-ai-diagram-generator)
|
||||
|
||||
5/21/2025 • 9 mins
|
||||
|
||||
Would an AI diagram generator make your life easier? We think it would!
|
||||
|
||||
## [Mermaid Chart VS Code Plugin: Create and Edit Mermaid.js Diagrams in Visual Studio Code](https://docs.mermaidchart.com/blog/posts/mermaid-chart-vs-code-plugin-create-and-edit-mermaid-js-diagrams-in-visual-studio-code)
|
||||
|
||||
3/21/2025 • 5 mins
|
||||
|
||||
The Mermaid Chart VS Code Plugin is a powerful developer diagramming tool that brings Mermaid.js diagramming directly into your Visual Studio Code environment. Whether you’re visualizing software architecture, documenting API flows, fixing bad documentation, or managing flowcharts and sequence diagrams, this plugin integrates seamlessly into your workflow. Key Features of the Mermaid Chart VS Code \[…]
|
||||
|
||||
## [Mermaid Chart: The Evolution of Mermaid](https://docs.mermaidchart.com/blog/posts/mermaid-chart-the-evolution-of-mermaid)
|
||||
|
||||
1/30/2025 • 3 mins
|
||||
|
||||
Mermaid revolutionized diagramming with its simple, markdown-style syntax, empowering millions of developers worldwide. Now, Mermaid Chart takes it further with AI-powered visuals, a GUI for seamless editing, real-time collaboration, and advanced design tools. Experience the next generation of diagramming—faster, smarter, and built for modern teams. Try Mermaid Chart today!
|
||||
|
||||
## [GUI for editing Mermaid Class Diagrams](https://docs.mermaidchart.com/blog/posts/gui-for-editing-mermaid-class-diagrams)
|
||||
|
||||
1/17/2025 • 5 mins
|
||||
|
@@ -194,7 +194,7 @@ architecture-beta
|
||||
## Icons
|
||||
|
||||
By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`.
|
||||
Users can use any of the 200,000+ icons available in iconify.design, or [add custom icons](../config/icons.md).
|
||||
Users can use any of the 200,000+ icons available in iconify.design, or add other custom icons, by [registering an icon pack](../config/icons.md).
|
||||
|
||||
After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack.
|
||||
|
||||
|
@@ -324,56 +324,55 @@ This syntax creates a node A as a rectangle. It renders in the same way as `A["A
|
||||
|
||||
Below is a comprehensive list of the newly introduced shapes and their corresponding semantic meanings, short names, and aliases:
|
||||
|
||||
| **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** |
|
||||
| --------------------------------- | ---------------------- | ----------------- | ------------------------------ | ---------------------------------------------------------------- |
|
||||
| Bang | Bang | `bang` | Bang | `bang` |
|
||||
| Card | Notched Rectangle | `notch-rect` | Represents a card | `card`, `notched-rectangle` |
|
||||
| Cloud | Cloud | `cloud` | cloud | `cloud` |
|
||||
| Collate | Hourglass | `hourglass` | Represents a collate operation | `collate`, `hourglass` |
|
||||
| Com Link | Lightning Bolt | `bolt` | Communication link | `com-link`, `lightning-bolt` |
|
||||
| Comment | Curly Brace | `brace` | Adds a comment | `brace-l`, `comment` |
|
||||
| Comment Right | Curly Brace | `brace-r` | Adds a comment | |
|
||||
| Comment with braces on both sides | Curly Braces | `braces` | Adds a comment | |
|
||||
| Data Input/Output | Lean Right | `lean-r` | Represents input or output | `in-out`, `lean-right` |
|
||||
| Data Input/Output | Lean Left | `lean-l` | Represents output or input | `lean-left`, `out-in` |
|
||||
| Database | Cylinder | `cyl` | Database storage | `cylinder`, `database`, `db` |
|
||||
| Decision | Diamond | `diam` | Decision-making step | `decision`, `diamond`, `question` |
|
||||
| Default Mindmap Node | defaultMindmapNode | `default-mindmap` | defaultMindmapNode | `default-mindmap`, `defaultMindmapNode` |
|
||||
| Delay | Half-Rounded Rectangle | `delay` | Represents a delay | `half-rounded-rectangle` |
|
||||
| Direct Access Storage | Horizontal Cylinder | `h-cyl` | Direct access storage | `das`, `horizontal-cylinder` |
|
||||
| Disk Storage | Lined Cylinder | `lin-cyl` | Disk storage | `disk`, `lined-cylinder` |
|
||||
| Display | Curved Trapezoid | `curv-trap` | Represents a display | `curved-trapezoid`, `display` |
|
||||
| Divided Process | Divided Rectangle | `div-rect` | Divided process shape | `div-proc`, `divided-process`, `divided-rectangle` |
|
||||
| Document | Document | `doc` | Represents a document | `doc`, `document` |
|
||||
| Event | Rounded Rectangle | `rounded` | Represents an event | `event` |
|
||||
| Extract | Triangle | `tri` | Extraction process | `extract`, `triangle` |
|
||||
| Fork/Join | Filled Rectangle | `fork` | Fork or join in process flow | `join` |
|
||||
| Internal Storage | Window Pane | `win-pane` | Internal storage | `internal-storage`, `window-pane` |
|
||||
| Junction | Filled Circle | `f-circ` | Junction point | `filled-circle`, `junction` |
|
||||
| Lined Document | Lined Document | `lin-doc` | Lined document | `lined-document` |
|
||||
| Lined/Shaded Process | Lined Rectangle | `lin-rect` | Lined process shape | `lin-proc`, `lined-process`, `lined-rectangle`, `shaded-process` |
|
||||
| Loop Limit | Trapezoidal Pentagon | `notch-pent` | Loop limit step | `loop-limit`, `notched-pentagon` |
|
||||
| Manual File | Flipped Triangle | `flip-tri` | Manual file operation | `flipped-triangle`, `manual-file` |
|
||||
| Manual Input | Sloped Rectangle | `sl-rect` | Manual input step | `manual-input`, `sloped-rectangle` |
|
||||
| Manual Operation | Trapezoid Base Top | `trap-t` | Represents a manual task | `inv-trapezoid`, `manual`, `trapezoid-top` |
|
||||
| Multi-Document | Stacked Document | `docs` | Multiple documents | `documents`, `st-doc`, `stacked-document` |
|
||||
| Multi-Process | Stacked Rectangle | `st-rect` | Multiple processes | `processes`, `procs`, `stacked-rectangle` |
|
||||
| Odd | Odd | `odd` | Odd shape | |
|
||||
| Paper Tape | Flag | `flag` | Paper tape | `paper-tape` |
|
||||
| Prepare Conditional | Hexagon | `hex` | Preparation or condition step | `hexagon`, `prepare` |
|
||||
| Priority Action | Trapezoid Base Bottom | `trap-b` | Priority action | `priority`, `trapezoid`, `trapezoid-bottom` |
|
||||
| Process | Rectangle | `rect` | Standard process shape | `proc`, `process`, `rectangle` |
|
||||
| Start | Circle | `circle` | Starting point | `circ` |
|
||||
| Start | Small Circle | `sm-circ` | Small starting point | `small-circle`, `start` |
|
||||
| Stop | Double Circle | `dbl-circ` | Represents a stop point | `double-circle` |
|
||||
| Stop | Framed Circle | `fr-circ` | Stop point | `framed-circle`, `stop` |
|
||||
| Stored Data | Bow Tie Rectangle | `bow-rect` | Stored data | `bow-tie-rectangle`, `stored-data` |
|
||||
| Subprocess | Framed Rectangle | `fr-rect` | Subprocess | `framed-rectangle`, `subproc`, `subprocess`, `subroutine` |
|
||||
| Summary | Crossed Circle | `cross-circ` | Summary | `crossed-circle`, `summary` |
|
||||
| Tagged Document | Tagged Document | `tag-doc` | Tagged document | `tag-doc`, `tagged-document` |
|
||||
| Tagged Process | Tagged Rectangle | `tag-rect` | Tagged process | `tag-proc`, `tagged-process`, `tagged-rectangle` |
|
||||
| Terminal Point | Stadium | `stadium` | Terminal point | `pill`, `terminal` |
|
||||
| Text Block | Text Block | `text` | Text block | |
|
||||
| **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** |
|
||||
| --------------------------------- | ---------------------- | -------------- | ------------------------------ | ---------------------------------------------------------------- |
|
||||
| Bang | Bang | `bang` | Bang | `bang` |
|
||||
| Card | Notched Rectangle | `notch-rect` | Represents a card | `card`, `notched-rectangle` |
|
||||
| Cloud | Cloud | `cloud` | cloud | `cloud` |
|
||||
| Collate | Hourglass | `hourglass` | Represents a collate operation | `collate`, `hourglass` |
|
||||
| Com Link | Lightning Bolt | `bolt` | Communication link | `com-link`, `lightning-bolt` |
|
||||
| Comment | Curly Brace | `brace` | Adds a comment | `brace-l`, `comment` |
|
||||
| Comment Right | Curly Brace | `brace-r` | Adds a comment | |
|
||||
| Comment with braces on both sides | Curly Braces | `braces` | Adds a comment | |
|
||||
| Data Input/Output | Lean Right | `lean-r` | Represents input or output | `in-out`, `lean-right` |
|
||||
| Data Input/Output | Lean Left | `lean-l` | Represents output or input | `lean-left`, `out-in` |
|
||||
| Database | Cylinder | `cyl` | Database storage | `cylinder`, `database`, `db` |
|
||||
| Decision | Diamond | `diam` | Decision-making step | `decision`, `diamond`, `question` |
|
||||
| Delay | Half-Rounded Rectangle | `delay` | Represents a delay | `half-rounded-rectangle` |
|
||||
| Direct Access Storage | Horizontal Cylinder | `h-cyl` | Direct access storage | `das`, `horizontal-cylinder` |
|
||||
| Disk Storage | Lined Cylinder | `lin-cyl` | Disk storage | `disk`, `lined-cylinder` |
|
||||
| Display | Curved Trapezoid | `curv-trap` | Represents a display | `curved-trapezoid`, `display` |
|
||||
| Divided Process | Divided Rectangle | `div-rect` | Divided process shape | `div-proc`, `divided-process`, `divided-rectangle` |
|
||||
| Document | Document | `doc` | Represents a document | `doc`, `document` |
|
||||
| Event | Rounded Rectangle | `rounded` | Represents an event | `event` |
|
||||
| Extract | Triangle | `tri` | Extraction process | `extract`, `triangle` |
|
||||
| Fork/Join | Filled Rectangle | `fork` | Fork or join in process flow | `join` |
|
||||
| Internal Storage | Window Pane | `win-pane` | Internal storage | `internal-storage`, `window-pane` |
|
||||
| Junction | Filled Circle | `f-circ` | Junction point | `filled-circle`, `junction` |
|
||||
| Lined Document | Lined Document | `lin-doc` | Lined document | `lined-document` |
|
||||
| Lined/Shaded Process | Lined Rectangle | `lin-rect` | Lined process shape | `lin-proc`, `lined-process`, `lined-rectangle`, `shaded-process` |
|
||||
| Loop Limit | Trapezoidal Pentagon | `notch-pent` | Loop limit step | `loop-limit`, `notched-pentagon` |
|
||||
| Manual File | Flipped Triangle | `flip-tri` | Manual file operation | `flipped-triangle`, `manual-file` |
|
||||
| Manual Input | Sloped Rectangle | `sl-rect` | Manual input step | `manual-input`, `sloped-rectangle` |
|
||||
| Manual Operation | Trapezoid Base Top | `trap-t` | Represents a manual task | `inv-trapezoid`, `manual`, `trapezoid-top` |
|
||||
| Multi-Document | Stacked Document | `docs` | Multiple documents | `documents`, `st-doc`, `stacked-document` |
|
||||
| Multi-Process | Stacked Rectangle | `st-rect` | Multiple processes | `processes`, `procs`, `stacked-rectangle` |
|
||||
| Odd | Odd | `odd` | Odd shape | |
|
||||
| Paper Tape | Flag | `flag` | Paper tape | `paper-tape` |
|
||||
| Prepare Conditional | Hexagon | `hex` | Preparation or condition step | `hexagon`, `prepare` |
|
||||
| Priority Action | Trapezoid Base Bottom | `trap-b` | Priority action | `priority`, `trapezoid`, `trapezoid-bottom` |
|
||||
| Process | Rectangle | `rect` | Standard process shape | `proc`, `process`, `rectangle` |
|
||||
| Start | Circle | `circle` | Starting point | `circ` |
|
||||
| Start | Small Circle | `sm-circ` | Small starting point | `small-circle`, `start` |
|
||||
| Stop | Double Circle | `dbl-circ` | Represents a stop point | `double-circle` |
|
||||
| Stop | Framed Circle | `fr-circ` | Stop point | `framed-circle`, `stop` |
|
||||
| Stored Data | Bow Tie Rectangle | `bow-rect` | Stored data | `bow-tie-rectangle`, `stored-data` |
|
||||
| Subprocess | Framed Rectangle | `fr-rect` | Subprocess | `framed-rectangle`, `subproc`, `subprocess`, `subroutine` |
|
||||
| Summary | Crossed Circle | `cross-circ` | Summary | `crossed-circle`, `summary` |
|
||||
| Tagged Document | Tagged Document | `tag-doc` | Tagged document | `tag-doc`, `tagged-document` |
|
||||
| Tagged Process | Tagged Rectangle | `tag-rect` | Tagged process | `tag-proc`, `tagged-process`, `tagged-rectangle` |
|
||||
| Terminal Point | Stadium | `stadium` | Terminal point | `pill`, `terminal` |
|
||||
| Text Block | Text Block | `text` | Text block | |
|
||||
|
||||
### Example Flowchart with New Shapes
|
||||
|
||||
@@ -986,11 +985,23 @@ flowchart TD
|
||||
- `b`
|
||||
- **w**: The width of the image. If not defined, this will default to the natural width of the image.
|
||||
- **h**: The height of the image. If not defined, this will default to the natural height of the image.
|
||||
- **constraint**: Determines if the image should constrain the node size. This setting also ensures the image maintains its original aspect ratio, adjusting the height (`h`) accordingly to the width (`w`). If not defined, this will default to `off` Possible values are:
|
||||
- **constraint**: Determines if the image should constrain the node size. This setting also ensures the image maintains its original aspect ratio, adjusting the width (`w`) accordingly to the height (`h`). If not defined, this will default to `off` Possible values are:
|
||||
- `on`
|
||||
- `off`
|
||||
|
||||
These new shapes provide additional flexibility and visual appeal to your flowcharts, making them more informative and engaging.
|
||||
If you want to resize an image, but keep the same aspect ratio, set `h`, and set `constraint: on` to constrain the aspect ratio. E.g.
|
||||
|
||||
```mermaid-example
|
||||
flowchart TD
|
||||
%% My image with a constrained aspect ratio
|
||||
A@{ img: "https://mermaid.js.org/favicon.svg", label: "My example image label", pos: "t", h: 60, constraint: "on" }
|
||||
```
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
%% My image with a constrained aspect ratio
|
||||
A@{ img: "https://mermaid.js.org/favicon.svg", label: "My example image label", pos: "t", h: 60, constraint: "on" }
|
||||
```
|
||||
|
||||
## Links between nodes
|
||||
|
||||
@@ -1819,7 +1830,7 @@ config:
|
||||
graph LR
|
||||
```
|
||||
|
||||
#### Edge level curve style using Edge IDs (v\<MERMAID_RELEASE_VERSION>+)
|
||||
#### Edge level curve style using Edge IDs (v11.10.0+)
|
||||
|
||||
You can assign IDs to [edges](#attaching-an-id-to-edges). After assigning an ID you can modify the line style by modifying the edge's `curve` property using the following syntax:
|
||||
|
||||
|
@@ -39,7 +39,7 @@ Drawing a pie chart is really simple in mermaid.
|
||||
|
||||
**Note:**
|
||||
|
||||
> Pie chart values must be **positive numbers greater than zero**.\
|
||||
> Pie chart values must be **positive numbers greater than zero**.
|
||||
> **Negative values are not allowed** and will result in an error.
|
||||
|
||||
\[pie] \[showData] (OPTIONAL)
|
||||
|
@@ -74,6 +74,126 @@ sequenceDiagram
|
||||
Bob->>Alice: Hi Alice
|
||||
```
|
||||
|
||||
### Boundary
|
||||
|
||||
If you want to use the boundary symbol for a participant, use the JSON configuration syntax as shown below.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "boundary" }
|
||||
participant Bob
|
||||
Alice->>Bob: Request from boundary
|
||||
Bob->>Alice: Response to boundary
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "boundary" }
|
||||
participant Bob
|
||||
Alice->>Bob: Request from boundary
|
||||
Bob->>Alice: Response to boundary
|
||||
```
|
||||
|
||||
### Control
|
||||
|
||||
If you want to use the control symbol for a participant, use the JSON configuration syntax as shown below.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "control" }
|
||||
participant Bob
|
||||
Alice->>Bob: Control request
|
||||
Bob->>Alice: Control response
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "control" }
|
||||
participant Bob
|
||||
Alice->>Bob: Control request
|
||||
Bob->>Alice: Control response
|
||||
```
|
||||
|
||||
### Entity
|
||||
|
||||
If you want to use the entity symbol for a participant, use the JSON configuration syntax as shown below.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "entity" }
|
||||
participant Bob
|
||||
Alice->>Bob: Entity request
|
||||
Bob->>Alice: Entity response
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "entity" }
|
||||
participant Bob
|
||||
Alice->>Bob: Entity request
|
||||
Bob->>Alice: Entity response
|
||||
```
|
||||
|
||||
### Database
|
||||
|
||||
If you want to use the database symbol for a participant, use the JSON configuration syntax as shown below.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "database" }
|
||||
participant Bob
|
||||
Alice->>Bob: DB query
|
||||
Bob->>Alice: DB result
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "database" }
|
||||
participant Bob
|
||||
Alice->>Bob: DB query
|
||||
Bob->>Alice: DB result
|
||||
```
|
||||
|
||||
### Collections
|
||||
|
||||
If you want to use the collections symbol for a participant, use the JSON configuration syntax as shown below.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "collections" }
|
||||
participant Bob
|
||||
Alice->>Bob: Collections request
|
||||
Bob->>Alice: Collections response
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "collections" }
|
||||
participant Bob
|
||||
Alice->>Bob: Collections request
|
||||
Bob->>Alice: Collections response
|
||||
```
|
||||
|
||||
### Queue
|
||||
|
||||
If you want to use the queue symbol for a participant, use the JSON configuration syntax as shown below.
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "queue" }
|
||||
participant Bob
|
||||
Alice->>Bob: Queue message
|
||||
Bob->>Alice: Queue response
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "queue" }
|
||||
participant Bob
|
||||
Alice->>Bob: Queue message
|
||||
Bob->>Alice: Queue response
|
||||
```
|
||||
|
||||
### Aliases
|
||||
|
||||
The actor can have a convenient identifier and a descriptive label.
|
||||
|
@@ -38,3 +38,5 @@ Each user journey is split into sections, these describe the part of the task
|
||||
the user is trying to complete.
|
||||
|
||||
Tasks syntax is `Task name: <score>: <comma separated list of actors>`
|
||||
|
||||
Score is a number between 1 and 5, inclusive.
|
||||
|
@@ -138,7 +138,7 @@ xychart
|
||||
|
||||
## Chart Theme Variables
|
||||
|
||||
Themes for xychart resides inside xychart attribute so to set the variables use this syntax:
|
||||
Themes for xychart reside inside the `xychart` attribute, allowing customization through the following syntax:
|
||||
|
||||
```yaml
|
||||
---
|
||||
@@ -163,6 +163,52 @@ config:
|
||||
| yAxisLineColor | Color of the y-axis line |
|
||||
| plotColorPalette | String of colors separated by comma e.g. "#f3456, #43445" |
|
||||
|
||||
### Setting Colors for Lines and Bars
|
||||
|
||||
To set the color for lines and bars, use the `plotColorPalette` parameter. Colors in the palette will correspond sequentially to the elements in your chart (e.g., first bar/line will use the first color specified in the palette).
|
||||
|
||||
```mermaid-example
|
||||
---
|
||||
config:
|
||||
themeVariables:
|
||||
xyChart:
|
||||
plotColorPalette: '#000000, #0000FF, #00FF00, #FF0000'
|
||||
---
|
||||
xychart
|
||||
title "Different Colors in xyChart"
|
||||
x-axis "categoriesX" ["Category 1", "Category 2", "Category 3", "Category 4"]
|
||||
y-axis "valuesY" 0 --> 50
|
||||
%% Black line
|
||||
line [10,20,30,40]
|
||||
%% Blue bar
|
||||
bar [20,30,25,35]
|
||||
%% Green bar
|
||||
bar [15,25,20,30]
|
||||
%% Red line
|
||||
line [5,15,25,35]
|
||||
```
|
||||
|
||||
```mermaid
|
||||
---
|
||||
config:
|
||||
themeVariables:
|
||||
xyChart:
|
||||
plotColorPalette: '#000000, #0000FF, #00FF00, #FF0000'
|
||||
---
|
||||
xychart
|
||||
title "Different Colors in xyChart"
|
||||
x-axis "categoriesX" ["Category 1", "Category 2", "Category 3", "Category 4"]
|
||||
y-axis "valuesY" 0 --> 50
|
||||
%% Black line
|
||||
line [10,20,30,40]
|
||||
%% Blue bar
|
||||
bar [20,30,25,35]
|
||||
%% Green bar
|
||||
bar [15,25,20,30]
|
||||
%% Red line
|
||||
line [5,15,25,35]
|
||||
```
|
||||
|
||||
## Example on config and theme
|
||||
|
||||
```mermaid-example
|
||||
|
@@ -1 +0,0 @@
|
||||
The instructions for Tidy-Tree layout can be found in [Tidy Tree Configuration](/config/tidy-tree)
|
54
package.json
54
package.json
@@ -63,36 +63,36 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@applitools/eyes-cypress": "^3.44.9",
|
||||
"@argos-ci/cypress": "^5.0.2",
|
||||
"@applitools/eyes-cypress": "^3.55.2",
|
||||
"@argos-ci/cypress": "^6.1.1",
|
||||
"@changesets/changelog-github": "^0.5.1",
|
||||
"@changesets/cli": "^2.27.12",
|
||||
"@changesets/cli": "^2.29.7",
|
||||
"@cspell/eslint-plugin": "^8.19.4",
|
||||
"@cypress/code-coverage": "^3.12.49",
|
||||
"@cypress/code-coverage": "^3.14.6",
|
||||
"@eslint/js": "^9.26.0",
|
||||
"@rollup/plugin-typescript": "^12.1.2",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "^5.0.0",
|
||||
"@rollup/plugin-typescript": "^12.1.4",
|
||||
"@types/cors": "^2.8.19",
|
||||
"@types/express": "^5.0.3",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"@types/lodash": "^4.17.15",
|
||||
"@types/lodash": "^4.17.20",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"@types/node": "^22.13.5",
|
||||
"@types/node": "^22.18.6",
|
||||
"@types/rollup-plugin-visualizer": "^5.0.3",
|
||||
"@vitest/coverage-v8": "^3.0.6",
|
||||
"@vitest/spy": "^3.0.6",
|
||||
"@vitest/ui": "^3.0.6",
|
||||
"@vitest/coverage-v8": "^3.2.4",
|
||||
"@vitest/spy": "^3.2.4",
|
||||
"@vitest/ui": "^3.2.4",
|
||||
"ajv": "^8.17.1",
|
||||
"chokidar": "3.6.0",
|
||||
"concurrently": "^9.1.2",
|
||||
"concurrently": "^9.2.1",
|
||||
"cors": "^2.8.5",
|
||||
"cpy-cli": "^5.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"cspell": "^9.1.3",
|
||||
"cypress": "^14.5.1",
|
||||
"cspell": "^9.2.1",
|
||||
"cypress": "^14.5.4",
|
||||
"cypress-image-snapshot": "^4.0.1",
|
||||
"cypress-split": "^1.24.14",
|
||||
"esbuild": "^0.25.0",
|
||||
"cypress-split": "^1.24.23",
|
||||
"esbuild": "^0.25.10",
|
||||
"eslint": "^9.26.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-cypress": "^4.3.0",
|
||||
@@ -106,30 +106,30 @@
|
||||
"eslint-plugin-tsdoc": "^0.4.0",
|
||||
"eslint-plugin-unicorn": "^59.0.1",
|
||||
"express": "^5.1.0",
|
||||
"globals": "^16.0.0",
|
||||
"globby": "^14.0.2",
|
||||
"globals": "^16.4.0",
|
||||
"globby": "^14.1.0",
|
||||
"husky": "^9.1.7",
|
||||
"jest": "^30.0.4",
|
||||
"jest": "^30.1.3",
|
||||
"jison": "^0.4.18",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsdom": "^26.1.0",
|
||||
"langium-cli": "3.3.0",
|
||||
"lint-staged": "^16.1.2",
|
||||
"lint-staged": "^16.1.6",
|
||||
"markdown-table": "^3.0.4",
|
||||
"nyc": "^17.1.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"prettier": "^3.5.2",
|
||||
"prettier-plugin-jsdoc": "^1.3.2",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-jsdoc": "^1.3.3",
|
||||
"rimraf": "^6.0.1",
|
||||
"rollup-plugin-visualizer": "^6.0.3",
|
||||
"start-server-and-test": "^2.0.10",
|
||||
"start-server-and-test": "^2.1.2",
|
||||
"tslib": "^2.8.1",
|
||||
"tsx": "^4.7.3",
|
||||
"tsx": "^4.20.5",
|
||||
"typescript": "~5.7.3",
|
||||
"typescript-eslint": "^8.38.0",
|
||||
"vite": "^7.0.3",
|
||||
"vite": "^7.0.7",
|
||||
"vite-plugin-istanbul": "^7.0.0",
|
||||
"vitest": "^3.0.6"
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"nyc": {
|
||||
"report-dir": "coverage/cypress"
|
||||
|
@@ -3,6 +3,7 @@
|
||||
"version": "1.0.0",
|
||||
"description": "Mermaid examples package",
|
||||
"author": "Sidharth Vinod",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"module": "./dist/mermaid-examples.core.mjs",
|
||||
"types": "./dist/mermaid.d.ts",
|
||||
@@ -27,9 +28,6 @@
|
||||
"devDependencies": {
|
||||
"mermaid": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"mermaid": "workspace:~"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
|
@@ -37,12 +37,12 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^7.0.4",
|
||||
"@braintree/sanitize-url": "^7.1.1",
|
||||
"d3": "^7.9.0",
|
||||
"khroma": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^9.1.2",
|
||||
"concurrently": "^9.2.1",
|
||||
"mermaid": "workspace:*",
|
||||
"rimraf": "^6.0.1"
|
||||
},
|
||||
|
@@ -1,5 +1,27 @@
|
||||
# @mermaid-js/layout-elk
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800), [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20), [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05), [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8)]:
|
||||
- mermaid@11.11.0
|
||||
|
||||
## 0.1.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6857](https://github.com/mermaid-js/mermaid/pull/6857) [`b9ef683`](https://github.com/mermaid-js/mermaid/commit/b9ef683fb67b8959abc455d6cc5266c37ba435f6) Thanks [@knsv](https://github.com/knsv)! - feat: Exposing elk configuration forceNodeModelOrder and considerModelOrder to the mermaid configuration
|
||||
|
||||
- [#6849](https://github.com/mermaid-js/mermaid/pull/6849) [`2260948`](https://github.com/mermaid-js/mermaid/commit/2260948b7bda08f00616c2ce678bed1da69eb96c) Thanks [@anderium](https://github.com/anderium)! - Make elk not force node model order, but strongly consider it instead
|
||||
|
||||
- Updated dependencies [[`b9ef683`](https://github.com/mermaid-js/mermaid/commit/b9ef683fb67b8959abc455d6cc5266c37ba435f6), [`2c0931d`](https://github.com/mermaid-js/mermaid/commit/2c0931da46794b49d2523211e25f782900c34e94), [`33e08da`](https://github.com/mermaid-js/mermaid/commit/33e08daf175125295a06b1b80279437004a4e865), [`814b68b`](https://github.com/mermaid-js/mermaid/commit/814b68b4a94813f7c6b3d7fb4559532a7bab2652), [`fce7cab`](https://github.com/mermaid-js/mermaid/commit/fce7cabb71d68a20a66246fe23d066512126a412), [`fc07f0d`](https://github.com/mermaid-js/mermaid/commit/fc07f0d8abca49e4f887d7457b7b94fb07d1e3da), [`12e01bd`](https://github.com/mermaid-js/mermaid/commit/12e01bdb5cacf3569133979a5a4f1d8973e9aec1), [`01aaef3`](https://github.com/mermaid-js/mermaid/commit/01aaef39b4a1ec8bc5a0c6bfa3a20b712d67f4dc), [`daf8d8d`](https://github.com/mermaid-js/mermaid/commit/daf8d8d3befcd600618a629977b76463b38d0ad9), [`c36cd05`](https://github.com/mermaid-js/mermaid/commit/c36cd05c45ac3090181152b4dae41f8d7b569bd6), [`8bb29fc`](https://github.com/mermaid-js/mermaid/commit/8bb29fc879329ad109898e4025b4f4eba2ab0649), [`71b04f9`](https://github.com/mermaid-js/mermaid/commit/71b04f93b07f876df2b30656ef36036c1d0e4e4f), [`c99bce6`](https://github.com/mermaid-js/mermaid/commit/c99bce6bab4c7ce0b81b66d44f44853ce4aeb1c3), [`6cc1926`](https://github.com/mermaid-js/mermaid/commit/6cc192680a2531cab28f87a8061a53b786e010f3), [`9da6fb3`](https://github.com/mermaid-js/mermaid/commit/9da6fb39ae278401771943ac85d6d1b875f78cf1), [`e48b0ba`](https://github.com/mermaid-js/mermaid/commit/e48b0ba61dab7f95aa02da603b5b7d383b894932), [`4d62d59`](https://github.com/mermaid-js/mermaid/commit/4d62d5963238400270e9314c6e4d506f48147074), [`e9ce8cf`](https://github.com/mermaid-js/mermaid/commit/e9ce8cf4da9062d85098042044822100889bb0dd), [`9258b29`](https://github.com/mermaid-js/mermaid/commit/9258b2933bbe1ef41087345ffea3731673671c49), [`da90f67`](https://github.com/mermaid-js/mermaid/commit/da90f6760b6efb0da998bcb63b75eecc29e06c08), [`0133f1c`](https://github.com/mermaid-js/mermaid/commit/0133f1c0c5cff4fc4c8e0b99e9cf0b3d49dcbe71), [`895f9d4`](https://github.com/mermaid-js/mermaid/commit/895f9d43ff98ca05ebfba530789f677f31a011ff)]:
|
||||
- mermaid@11.10.0
|
||||
|
||||
## 0.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@mermaid-js/layout-elk",
|
||||
"version": "0.1.8",
|
||||
"version": "0.2.0",
|
||||
"description": "ELK layout engine for mermaid",
|
||||
"module": "dist/mermaid-layout-elk.core.mjs",
|
||||
"types": "dist/layouts.d.ts",
|
||||
|
67
packages/mermaid-layout-elk/src/__tests__/geometry.spec.ts
Normal file
67
packages/mermaid-layout-elk/src/__tests__/geometry.spec.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import {
|
||||
intersection,
|
||||
ensureTrulyOutside,
|
||||
makeInsidePoint,
|
||||
tryNodeIntersect,
|
||||
replaceEndpoint,
|
||||
type RectLike,
|
||||
type P,
|
||||
} from '../geometry.js';
|
||||
|
||||
const approx = (a: number, b: number, eps = 1e-6) => Math.abs(a - b) < eps;
|
||||
|
||||
describe('geometry helpers', () => {
|
||||
it('intersection: vertical approach hits bottom border', () => {
|
||||
const rect: RectLike = { x: 0, y: 0, width: 100, height: 50 };
|
||||
const h = rect.height / 2; // 25
|
||||
const outside: P = { x: 0, y: 100 };
|
||||
const inside: P = { x: 0, y: 0 };
|
||||
const res = intersection(rect, outside, inside);
|
||||
expect(approx(res.x, 0)).toBe(true);
|
||||
expect(approx(res.y, h)).toBe(true);
|
||||
});
|
||||
|
||||
it('ensureTrulyOutside nudges near-boundary point outward', () => {
|
||||
const rect: RectLike = { x: 0, y: 0, width: 100, height: 50 };
|
||||
// near bottom boundary (y ~ h)
|
||||
const near: P = { x: 0, y: rect.height / 2 - 0.2 };
|
||||
const out = ensureTrulyOutside(rect, near, 10);
|
||||
expect(out.y).toBeGreaterThan(rect.height / 2);
|
||||
});
|
||||
|
||||
it('makeInsidePoint keeps x for vertical and y from center', () => {
|
||||
const rect: RectLike = { x: 10, y: 5, width: 100, height: 50 };
|
||||
const outside: P = { x: 10, y: 40 };
|
||||
const center: P = { x: 99, y: -123 }; // center y should be used
|
||||
const inside = makeInsidePoint(rect, outside, center);
|
||||
expect(inside.x).toBe(outside.x);
|
||||
expect(inside.y).toBe(center.y);
|
||||
});
|
||||
|
||||
it('tryNodeIntersect returns null for wrong-side intersections', () => {
|
||||
const rect: RectLike = { x: 0, y: 0, width: 100, height: 50 };
|
||||
const outside: P = { x: -50, y: 0 };
|
||||
const node = { intersect: () => ({ x: 10, y: 0 }) } as any; // right side of center
|
||||
const res = tryNodeIntersect(node, rect, outside);
|
||||
expect(res).toBeNull();
|
||||
});
|
||||
|
||||
it('replaceEndpoint dedup removes end/start appropriately', () => {
|
||||
const pts: P[] = [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 1, y: 1 },
|
||||
];
|
||||
// remove duplicate end
|
||||
replaceEndpoint(pts, 'end', { x: 1, y: 1 });
|
||||
expect(pts.length).toBe(1);
|
||||
|
||||
const pts2: P[] = [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 1, y: 1 },
|
||||
];
|
||||
// remove duplicate start
|
||||
replaceEndpoint(pts2, 'start', { x: 0, y: 0 });
|
||||
expect(pts2.length).toBe(1);
|
||||
});
|
||||
});
|
209
packages/mermaid-layout-elk/src/geometry.ts
Normal file
209
packages/mermaid-layout-elk/src/geometry.ts
Normal file
@@ -0,0 +1,209 @@
|
||||
/* Geometry utilities extracted from render.ts for reuse and testing */
|
||||
|
||||
export interface P {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
export interface RectLike {
|
||||
x: number; // center x
|
||||
y: number; // center y
|
||||
width: number;
|
||||
height: number;
|
||||
padding?: number;
|
||||
}
|
||||
|
||||
export interface NodeLike {
|
||||
intersect?: (p: P) => P | null;
|
||||
}
|
||||
|
||||
export const EPS = 1;
|
||||
export const PUSH_OUT = 10;
|
||||
|
||||
export const onBorder = (bounds: RectLike, p: P, tol = 0.5): boolean => {
|
||||
const halfW = bounds.width / 2;
|
||||
const halfH = bounds.height / 2;
|
||||
const left = bounds.x - halfW;
|
||||
const right = bounds.x + halfW;
|
||||
const top = bounds.y - halfH;
|
||||
const bottom = bounds.y + halfH;
|
||||
|
||||
const onLeft = Math.abs(p.x - left) <= tol && p.y >= top - tol && p.y <= bottom + tol;
|
||||
const onRight = Math.abs(p.x - right) <= tol && p.y >= top - tol && p.y <= bottom + tol;
|
||||
const onTop = Math.abs(p.y - top) <= tol && p.x >= left - tol && p.x <= right + tol;
|
||||
const onBottom = Math.abs(p.y - bottom) <= tol && p.x >= left - tol && p.x <= right + tol;
|
||||
return onLeft || onRight || onTop || onBottom;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compute intersection between a rectangle (center x/y, width/height) and the line
|
||||
* segment from insidePoint -\> outsidePoint. Returns the point on the rectangle border.
|
||||
*
|
||||
* This version avoids snapping to outsidePoint when certain variables evaluate to 0
|
||||
* (previously caused vertical top/bottom cases to miss the border). It only enforces
|
||||
* axis-constant behavior for purely vertical/horizontal approaches.
|
||||
*/
|
||||
export const intersection = (node: RectLike, outsidePoint: P, insidePoint: P): P => {
|
||||
const x = node.x;
|
||||
const y = node.y;
|
||||
|
||||
const dx = Math.abs(x - insidePoint.x);
|
||||
const w = node.width / 2;
|
||||
let r = insidePoint.x < outsidePoint.x ? w - dx : w + dx;
|
||||
const h = node.height / 2;
|
||||
|
||||
const Q = Math.abs(outsidePoint.y - insidePoint.y);
|
||||
const R = Math.abs(outsidePoint.x - insidePoint.x);
|
||||
|
||||
if (Math.abs(y - outsidePoint.y) * w > Math.abs(x - outsidePoint.x) * h) {
|
||||
// Intersection is top or bottom of rect.
|
||||
const q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y;
|
||||
r = (R * q) / Q;
|
||||
const res = {
|
||||
x: insidePoint.x < outsidePoint.x ? insidePoint.x + r : insidePoint.x - R + r,
|
||||
y: insidePoint.y < outsidePoint.y ? insidePoint.y + Q - q : insidePoint.y - Q + q,
|
||||
};
|
||||
|
||||
// Keep axis-constant special-cases only
|
||||
if (R === 0) {
|
||||
res.x = outsidePoint.x;
|
||||
}
|
||||
if (Q === 0) {
|
||||
res.y = outsidePoint.y;
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
// Intersection on sides of rect
|
||||
if (insidePoint.x < outsidePoint.x) {
|
||||
r = outsidePoint.x - w - x;
|
||||
} else {
|
||||
r = x - w - outsidePoint.x;
|
||||
}
|
||||
const q = (Q * r) / R;
|
||||
let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x - R + r;
|
||||
let _y = insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q;
|
||||
|
||||
// Only handle axis-constant cases
|
||||
if (R === 0) {
|
||||
_x = outsidePoint.x;
|
||||
}
|
||||
if (Q === 0) {
|
||||
_y = outsidePoint.y;
|
||||
}
|
||||
|
||||
return { x: _x, y: _y };
|
||||
}
|
||||
};
|
||||
|
||||
export const outsideNode = (node: RectLike, point: P): boolean => {
|
||||
const x = node.x;
|
||||
const y = node.y;
|
||||
const dx = Math.abs(point.x - x);
|
||||
const dy = Math.abs(point.y - y);
|
||||
const w = node.width / 2;
|
||||
const h = node.height / 2;
|
||||
return dx >= w || dy >= h;
|
||||
};
|
||||
|
||||
export const ensureTrulyOutside = (bounds: RectLike, p: P, push = PUSH_OUT): P => {
|
||||
const dx = Math.abs(p.x - bounds.x);
|
||||
const dy = Math.abs(p.y - bounds.y);
|
||||
const w = bounds.width / 2;
|
||||
const h = bounds.height / 2;
|
||||
if (Math.abs(dx - w) < EPS || Math.abs(dy - h) < EPS) {
|
||||
const dirX = p.x - bounds.x;
|
||||
const dirY = p.y - bounds.y;
|
||||
const len = Math.sqrt(dirX * dirX + dirY * dirY);
|
||||
if (len > 0) {
|
||||
return {
|
||||
x: bounds.x + (dirX / len) * (len + push),
|
||||
y: bounds.y + (dirY / len) * (len + push),
|
||||
};
|
||||
}
|
||||
}
|
||||
return p;
|
||||
};
|
||||
|
||||
export const makeInsidePoint = (bounds: RectLike, outside: P, center: P): P => {
|
||||
const isVertical = Math.abs(outside.x - bounds.x) < EPS;
|
||||
const isHorizontal = Math.abs(outside.y - bounds.y) < EPS;
|
||||
return {
|
||||
x: isVertical
|
||||
? outside.x
|
||||
: outside.x < bounds.x
|
||||
? bounds.x - bounds.width / 4
|
||||
: bounds.x + bounds.width / 4,
|
||||
y: isHorizontal ? outside.y : center.y,
|
||||
};
|
||||
};
|
||||
|
||||
export const tryNodeIntersect = (node: NodeLike, bounds: RectLike, outside: P): P | null => {
|
||||
if (!node?.intersect) {
|
||||
return null;
|
||||
}
|
||||
const res = node.intersect(outside);
|
||||
if (!res) {
|
||||
return null;
|
||||
}
|
||||
const wrongSide =
|
||||
(outside.x < bounds.x && res.x > bounds.x) || (outside.x > bounds.x && res.x < bounds.x);
|
||||
if (wrongSide) {
|
||||
return null;
|
||||
}
|
||||
const dist = Math.hypot(outside.x - res.x, outside.y - res.y);
|
||||
if (dist <= EPS) {
|
||||
return null;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
export const fallbackIntersection = (bounds: RectLike, outside: P, center: P): P => {
|
||||
const inside = makeInsidePoint(bounds, outside, center);
|
||||
return intersection(bounds, outside, inside);
|
||||
};
|
||||
|
||||
export const computeNodeIntersection = (
|
||||
node: NodeLike,
|
||||
bounds: RectLike,
|
||||
outside: P,
|
||||
center: P
|
||||
): P => {
|
||||
const outside2 = ensureTrulyOutside(bounds, outside);
|
||||
return tryNodeIntersect(node, bounds, outside2) ?? fallbackIntersection(bounds, outside2, center);
|
||||
};
|
||||
|
||||
export const replaceEndpoint = (
|
||||
points: P[],
|
||||
which: 'start' | 'end',
|
||||
value: P | null | undefined,
|
||||
tol = 0.1
|
||||
) => {
|
||||
if (!value || points.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (which === 'start') {
|
||||
if (
|
||||
points.length > 0 &&
|
||||
Math.abs(points[0].x - value.x) < tol &&
|
||||
Math.abs(points[0].y - value.y) < tol
|
||||
) {
|
||||
// duplicate start remove it
|
||||
points.shift();
|
||||
} else {
|
||||
points[0] = value;
|
||||
}
|
||||
} else {
|
||||
const last = points.length - 1;
|
||||
if (
|
||||
points.length > 0 &&
|
||||
Math.abs(points[last].x - value.x) < tol &&
|
||||
Math.abs(points[last].y - value.y) < tol
|
||||
) {
|
||||
// duplicate end remove it
|
||||
points.pop();
|
||||
} else {
|
||||
points[last] = value;
|
||||
}
|
||||
}
|
||||
};
|
@@ -1,11 +1,26 @@
|
||||
import type { InternalHelpers, LayoutData, RenderOptions, SVG, SVGGroup } from 'mermaid';
|
||||
// @ts-ignore TODO: Investigate D3 issue
|
||||
import { curveLinear } from 'd3';
|
||||
import ELK from 'elkjs/lib/elk.bundled.js';
|
||||
import type { InternalHelpers, LayoutData, RenderOptions, SVG, SVGGroup } from 'mermaid';
|
||||
import { type TreeData, findCommonAncestor } from './find-common-ancestor.js';
|
||||
|
||||
import {
|
||||
type P,
|
||||
type RectLike,
|
||||
outsideNode,
|
||||
computeNodeIntersection,
|
||||
replaceEndpoint,
|
||||
onBorder,
|
||||
} from './geometry.js';
|
||||
|
||||
type Node = LayoutData['nodes'][number];
|
||||
// Used to calculate distances in order to avoid floating number rounding issues when comparing floating numbers
|
||||
const epsilon = 0.0001;
|
||||
|
||||
// Minimal structural type to avoid depending on d3 Selection typings
|
||||
interface D3Selection<T extends Element> {
|
||||
node(): T | null;
|
||||
attr(name: string, value: string): D3Selection<T>;
|
||||
}
|
||||
|
||||
interface LabelData {
|
||||
width: number;
|
||||
height: number;
|
||||
@@ -16,18 +31,9 @@ interface LabelData {
|
||||
interface NodeWithVertex extends Omit<Node, 'domId'> {
|
||||
children?: LayoutData['nodes'];
|
||||
labelData?: LabelData;
|
||||
domId?: Node['domId'] | SVGGroup | d3.Selection<SVGAElement, unknown, Element | null, unknown>;
|
||||
}
|
||||
interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
function distance(p1?: Point, p2?: Point): number {
|
||||
if (!p1 || !p2) {
|
||||
return 0;
|
||||
}
|
||||
return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
|
||||
domId?: D3Selection<SVGAElement | SVGGElement>;
|
||||
}
|
||||
|
||||
export const render = async (
|
||||
data4Layout: LayoutData,
|
||||
svg: SVG,
|
||||
@@ -61,39 +67,26 @@ export const render = async (
|
||||
|
||||
// Add the element to the DOM
|
||||
if (!node.isGroup) {
|
||||
// Create a clean node object for ELK with only the properties it expects
|
||||
const child: NodeWithVertex = {
|
||||
id: node.id,
|
||||
width: node.width,
|
||||
height: node.height,
|
||||
// Store the original node data for later use
|
||||
label: node.label,
|
||||
isGroup: node.isGroup,
|
||||
shape: node.shape,
|
||||
padding: node.padding,
|
||||
cssClasses: node.cssClasses,
|
||||
cssStyles: node.cssStyles,
|
||||
look: node.look,
|
||||
// Include parentId for subgraph processing
|
||||
parentId: node.parentId,
|
||||
};
|
||||
const child = node as NodeWithVertex;
|
||||
graph.children.push(child);
|
||||
nodeDb[node.id] = child;
|
||||
nodeDb[node.id] = node;
|
||||
|
||||
const childNodeEl = await insertNode(nodeEl, node, { config, dir: node.dir });
|
||||
const boundingBox = childNodeEl.node()!.getBBox();
|
||||
// Store the domId separately for rendering, not in the ELK graph
|
||||
child.domId = childNodeEl;
|
||||
child.calcIntersect = node.calcIntersect;
|
||||
child.width = boundingBox.width;
|
||||
child.height = boundingBox.height;
|
||||
} else {
|
||||
// A subgraph
|
||||
const child: NodeWithVertex & { children: NodeWithVertex[] } = {
|
||||
...node,
|
||||
domId: undefined,
|
||||
children: [],
|
||||
};
|
||||
// Let elk render with the copy
|
||||
graph.children.push(child);
|
||||
// Save the original containing the intersection function
|
||||
nodeDb[node.id] = child;
|
||||
await addVertices(nodeEl, nodeArr, child, node.id);
|
||||
|
||||
@@ -168,7 +161,7 @@ export const render = async (
|
||||
height: node.height,
|
||||
};
|
||||
if (node.isGroup) {
|
||||
log.debug('id abc88 subgraph = ', node.id, node.x, node.y, node.labelData);
|
||||
log.debug('Id abc88 subgraph = ', node.id, node.x, node.y, node.labelData);
|
||||
const subgraphEl = subgraphsEl.insert('g').attr('class', 'subgraph');
|
||||
// TODO use faster way of cloning
|
||||
const clusterNode = JSON.parse(JSON.stringify(node));
|
||||
@@ -177,10 +170,10 @@ export const render = async (
|
||||
clusterNode.width = Math.max(clusterNode.width, node.labelData.width);
|
||||
await insertCluster(subgraphEl, clusterNode);
|
||||
|
||||
log.debug('id (UIO)= ', node.id, node.width, node.shape, node.labels);
|
||||
log.debug('Id (UIO)= ', node.id, node.width, node.shape, node.labels);
|
||||
} else {
|
||||
log.info(
|
||||
'id NODE = ',
|
||||
'Id NODE = ',
|
||||
node.id,
|
||||
node.x,
|
||||
node.y,
|
||||
@@ -222,25 +215,19 @@ export const render = async (
|
||||
});
|
||||
});
|
||||
|
||||
subgraphs.forEach(function (subgraph: { id: string | number }) {
|
||||
const data: any = { id: subgraph.id };
|
||||
if (parentLookupDb.parentById[subgraph.id] !== undefined) {
|
||||
data.parent = parentLookupDb.parentById[subgraph.id];
|
||||
}
|
||||
});
|
||||
return parentLookupDb;
|
||||
};
|
||||
|
||||
const getEdgeStartEndPoint = (edge: any) => {
|
||||
const source: any = edge.start;
|
||||
const target: any = edge.end;
|
||||
// edge.start and edge.end are IDs (string/number) in our layout data
|
||||
const sourceId: string | number = edge.start;
|
||||
const targetId: string | number = edge.end;
|
||||
|
||||
// Save the original source and target
|
||||
const sourceId = source;
|
||||
const targetId = target;
|
||||
const source = sourceId;
|
||||
const target = targetId;
|
||||
|
||||
const startNode = nodeDb[edge.start.id];
|
||||
const endNode = nodeDb[edge.end.id];
|
||||
const startNode = nodeDb[sourceId];
|
||||
const endNode = nodeDb[targetId];
|
||||
|
||||
if (!startNode || !endNode) {
|
||||
return { source, target };
|
||||
@@ -263,6 +250,112 @@ export const render = async (
|
||||
/**
|
||||
* Add edges to graph based on parsed graph definition
|
||||
*/
|
||||
// Edge helper maps and utilities (de-duplicated)
|
||||
const ARROW_MAP: Record<string, [string, string]> = {
|
||||
arrow_open: ['arrow_open', 'arrow_open'],
|
||||
arrow_cross: ['arrow_open', 'arrow_cross'],
|
||||
double_arrow_cross: ['arrow_cross', 'arrow_cross'],
|
||||
arrow_point: ['arrow_open', 'arrow_point'],
|
||||
double_arrow_point: ['arrow_point', 'arrow_point'],
|
||||
arrow_circle: ['arrow_open', 'arrow_circle'],
|
||||
double_arrow_circle: ['arrow_circle', 'arrow_circle'],
|
||||
};
|
||||
|
||||
const computeStroke = (
|
||||
stroke: string | undefined,
|
||||
defaultStyle?: string,
|
||||
defaultLabelStyle?: string
|
||||
) => {
|
||||
// Defaults correspond to 'normal'
|
||||
let thickness = 'normal';
|
||||
let pattern = 'solid';
|
||||
let style = '';
|
||||
let labelStyle = '';
|
||||
|
||||
if (stroke === 'dotted') {
|
||||
pattern = 'dotted';
|
||||
style = 'fill:none;stroke-width:2px;stroke-dasharray:3;';
|
||||
} else if (stroke === 'thick') {
|
||||
thickness = 'thick';
|
||||
style = 'stroke-width: 3.5px;fill:none;';
|
||||
} else {
|
||||
// normal
|
||||
style = defaultStyle ?? 'fill:none;';
|
||||
if (defaultLabelStyle !== undefined) {
|
||||
labelStyle = defaultLabelStyle;
|
||||
}
|
||||
}
|
||||
return { thickness, pattern, style, labelStyle };
|
||||
};
|
||||
|
||||
const getCurve = (edgeInterpolate: any, edgesDefaultInterpolate: any, confCurve: any) => {
|
||||
if (edgeInterpolate !== undefined) {
|
||||
return interpolateToCurve(edgeInterpolate, curveLinear);
|
||||
}
|
||||
if (edgesDefaultInterpolate !== undefined) {
|
||||
return interpolateToCurve(edgesDefaultInterpolate, curveLinear);
|
||||
}
|
||||
// @ts-ignore TODO: fix this
|
||||
return interpolateToCurve(confCurve, curveLinear);
|
||||
};
|
||||
const buildEdgeData = (
|
||||
edge: any,
|
||||
defaults: {
|
||||
defaultStyle?: string;
|
||||
defaultLabelStyle?: string;
|
||||
defaultInterpolate?: any;
|
||||
confCurve: any;
|
||||
},
|
||||
common: any
|
||||
) => {
|
||||
const edgeData: any = { style: '', labelStyle: '' };
|
||||
edgeData.minlen = edge.length || 1;
|
||||
// maintain legacy behavior
|
||||
edge.text = edge.label;
|
||||
|
||||
// Arrowhead fill vs none
|
||||
edgeData.arrowhead = edge.type === 'arrow_open' ? 'none' : 'normal';
|
||||
|
||||
// Arrow types
|
||||
const arrowMap = ARROW_MAP[edge.type] ?? ARROW_MAP.arrow_open;
|
||||
edgeData.arrowTypeStart = arrowMap[0];
|
||||
edgeData.arrowTypeEnd = arrowMap[1];
|
||||
|
||||
// Optional edge label positioning flags
|
||||
edgeData.startLabelRight = edge.startLabelRight;
|
||||
edgeData.endLabelLeft = edge.endLabelLeft;
|
||||
|
||||
// Stroke
|
||||
const strokeRes = computeStroke(edge.stroke, defaults.defaultStyle, defaults.defaultLabelStyle);
|
||||
edgeData.thickness = strokeRes.thickness;
|
||||
edgeData.pattern = strokeRes.pattern;
|
||||
edgeData.style = (edgeData.style || '') + (strokeRes.style || '');
|
||||
edgeData.labelStyle = (edgeData.labelStyle || '') + (strokeRes.labelStyle || '');
|
||||
|
||||
// Curve
|
||||
// @ts-ignore - defaults.confCurve is present at runtime but missing in type
|
||||
edgeData.curve = getCurve(edge.interpolate, defaults.defaultInterpolate, defaults.confCurve);
|
||||
|
||||
// Arrowhead style + labelpos when we have label text
|
||||
const hasText = (edge?.text ?? '') !== '';
|
||||
if (hasText) {
|
||||
edgeData.arrowheadStyle = 'fill: #333';
|
||||
edgeData.labelpos = 'c';
|
||||
} else if (edge.style !== undefined) {
|
||||
edgeData.arrowheadStyle = 'fill: #333';
|
||||
}
|
||||
|
||||
edgeData.labelType = edge.labelType;
|
||||
edgeData.label = (edge?.text ?? '').replace(common.lineBreakRegex, '\n');
|
||||
|
||||
if (edge.style === undefined) {
|
||||
edgeData.style = edgeData.style ?? 'stroke: #333; stroke-width: 1.5px;fill:none;';
|
||||
}
|
||||
|
||||
edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:');
|
||||
return edgeData;
|
||||
};
|
||||
|
||||
const addEdges = async function (
|
||||
dataForLayout: { edges: any; direction?: string },
|
||||
graph: {
|
||||
@@ -284,7 +377,6 @@ export const render = async (
|
||||
const edges = dataForLayout.edges;
|
||||
const labelsEl = svg.insert('g').attr('class', 'edgeLabels');
|
||||
const linkIdCnt: any = {};
|
||||
const dir = dataForLayout.direction || 'DOWN';
|
||||
let defaultStyle: string | undefined;
|
||||
let defaultLabelStyle: string | undefined;
|
||||
|
||||
@@ -314,105 +406,24 @@ export const render = async (
|
||||
linkIdCnt[linkIdBase]++;
|
||||
log.info('abc78 new entry', linkIdBase, linkIdCnt[linkIdBase]);
|
||||
}
|
||||
const linkId = linkIdBase + '_' + linkIdCnt[linkIdBase];
|
||||
const linkId = linkIdBase; // + '_' + linkIdCnt[linkIdBase];
|
||||
edge.id = linkId;
|
||||
log.info('abc78 new link id to be used is', linkIdBase, linkId, linkIdCnt[linkIdBase]);
|
||||
const linkNameStart = 'LS_' + edge.start;
|
||||
const linkNameEnd = 'LE_' + edge.end;
|
||||
|
||||
const edgeData: any = { style: '', labelStyle: '' };
|
||||
edgeData.minlen = edge.length || 1;
|
||||
edge.text = edge.label;
|
||||
// Set link type for rendering
|
||||
if (edge.type === 'arrow_open') {
|
||||
edgeData.arrowhead = 'none';
|
||||
} else {
|
||||
edgeData.arrowhead = 'normal';
|
||||
}
|
||||
|
||||
// Check of arrow types, placed here in order not to break old rendering
|
||||
edgeData.arrowTypeStart = 'arrow_open';
|
||||
edgeData.arrowTypeEnd = 'arrow_open';
|
||||
|
||||
/* eslint-disable no-fallthrough */
|
||||
switch (edge.type) {
|
||||
case 'double_arrow_cross':
|
||||
edgeData.arrowTypeStart = 'arrow_cross';
|
||||
case 'arrow_cross':
|
||||
edgeData.arrowTypeEnd = 'arrow_cross';
|
||||
break;
|
||||
case 'double_arrow_point':
|
||||
edgeData.arrowTypeStart = 'arrow_point';
|
||||
case 'arrow_point':
|
||||
edgeData.arrowTypeEnd = 'arrow_point';
|
||||
break;
|
||||
case 'double_arrow_circle':
|
||||
edgeData.arrowTypeStart = 'arrow_circle';
|
||||
case 'arrow_circle':
|
||||
edgeData.arrowTypeEnd = 'arrow_circle';
|
||||
break;
|
||||
}
|
||||
|
||||
let style = '';
|
||||
let labelStyle = '';
|
||||
|
||||
edgeData.startLabelRight = edge.startLabelRight;
|
||||
edgeData.endLabelLeft = edge.endLabelLeft;
|
||||
|
||||
switch (edge.stroke) {
|
||||
case 'normal':
|
||||
style = 'fill:none;';
|
||||
if (defaultStyle !== undefined) {
|
||||
style = defaultStyle;
|
||||
}
|
||||
if (defaultLabelStyle !== undefined) {
|
||||
labelStyle = defaultLabelStyle;
|
||||
}
|
||||
edgeData.thickness = 'normal';
|
||||
edgeData.pattern = 'solid';
|
||||
break;
|
||||
case 'dotted':
|
||||
edgeData.thickness = 'normal';
|
||||
edgeData.pattern = 'dotted';
|
||||
edgeData.style = 'fill:none;stroke-width:2px;stroke-dasharray:3;';
|
||||
break;
|
||||
case 'thick':
|
||||
edgeData.thickness = 'thick';
|
||||
edgeData.pattern = 'solid';
|
||||
edgeData.style = 'stroke-width: 3.5px;fill:none;';
|
||||
break;
|
||||
}
|
||||
|
||||
edgeData.style = edgeData.style += style;
|
||||
edgeData.labelStyle = edgeData.labelStyle += labelStyle;
|
||||
|
||||
const conf = getConfig();
|
||||
if (edge.interpolate !== undefined) {
|
||||
edgeData.curve = interpolateToCurve(edge.interpolate, curveLinear);
|
||||
} else if (edges.defaultInterpolate !== undefined) {
|
||||
edgeData.curve = interpolateToCurve(edges.defaultInterpolate, curveLinear);
|
||||
} else {
|
||||
// @ts-ignore TODO: fix this
|
||||
edgeData.curve = interpolateToCurve(conf.curve, curveLinear);
|
||||
}
|
||||
|
||||
if (edge.text === undefined) {
|
||||
if (edge.style !== undefined) {
|
||||
edgeData.arrowheadStyle = 'fill: #333';
|
||||
}
|
||||
} else {
|
||||
edgeData.arrowheadStyle = 'fill: #333';
|
||||
edgeData.labelpos = 'c';
|
||||
}
|
||||
|
||||
edgeData.labelType = edge.labelType;
|
||||
edgeData.label = (edge?.text || '').replace(common.lineBreakRegex, '\n');
|
||||
|
||||
if (edge.style === undefined) {
|
||||
edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none;';
|
||||
}
|
||||
|
||||
edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:');
|
||||
const edgeData = buildEdgeData(
|
||||
edge,
|
||||
{
|
||||
defaultStyle,
|
||||
defaultLabelStyle,
|
||||
defaultInterpolate: edges.defaultInterpolate,
|
||||
// @ts-ignore - conf.curve exists at runtime but is missing from typing
|
||||
confCurve: conf.curve,
|
||||
},
|
||||
common
|
||||
);
|
||||
|
||||
edgeData.id = linkId;
|
||||
edgeData.classes = 'flowchart-link ' + linkNameStart + ' ' + linkNameEnd;
|
||||
@@ -421,13 +432,11 @@ export const render = async (
|
||||
|
||||
// calculate start and end points of the edge, note that the source and target
|
||||
// can be modified for shapes that have ports
|
||||
// @ts-ignore TODO: fix this
|
||||
const { source, target, sourceId, targetId } = getEdgeStartEndPoint(edge, dir);
|
||||
|
||||
const { source, target, sourceId, targetId } = getEdgeStartEndPoint(edge);
|
||||
log.debug('abc78 source and target', source, target);
|
||||
// Add the edge to the graph
|
||||
graph.edges.push({
|
||||
// @ts-ignore TODO: fix this
|
||||
id: 'e' + edge.start + edge.end,
|
||||
...edge,
|
||||
sources: [source],
|
||||
targets: [target],
|
||||
@@ -461,6 +470,7 @@ export const render = async (
|
||||
case 'RL':
|
||||
return 'LEFT';
|
||||
case 'TB':
|
||||
case 'TD': // TD is an alias for TB in Mermaid
|
||||
return 'DOWN';
|
||||
case 'BT':
|
||||
return 'UP';
|
||||
@@ -484,6 +494,203 @@ export const render = async (
|
||||
}
|
||||
}
|
||||
|
||||
// Node bounds helpers (global)
|
||||
const getEffectiveGroupWidth = (node: any): number => {
|
||||
const labelW = node?.labels?.[0]?.width ?? 0;
|
||||
const padding = node?.padding ?? 0;
|
||||
return Math.max(node.width ?? 0, labelW + padding);
|
||||
};
|
||||
|
||||
const boundsFor = (node: any): RectLike => {
|
||||
const width = node?.isGroup ? getEffectiveGroupWidth(node) : node.width;
|
||||
return {
|
||||
x: node.offset.posX + node.width / 2,
|
||||
y: node.offset.posY + node.height / 2,
|
||||
width,
|
||||
height: node.height,
|
||||
padding: node.padding,
|
||||
};
|
||||
};
|
||||
// Helper utilities for endpoint handling around cutter2
|
||||
type Side = 'start' | 'end';
|
||||
const approxEq = (a: number, b: number, eps = 1e-6) => Math.abs(a - b) < eps;
|
||||
const isCenterApprox = (pt: P, node: { x: number; y: number }) =>
|
||||
approxEq(pt.x, node.x) && approxEq(pt.y, node.y);
|
||||
|
||||
const getCandidateBorderPoint = (
|
||||
points: P[],
|
||||
node: any,
|
||||
side: Side
|
||||
): { candidate: P; centerApprox: boolean } => {
|
||||
if (!points?.length) {
|
||||
return { candidate: { x: node.x, y: node.y } as P, centerApprox: true };
|
||||
}
|
||||
if (side === 'start') {
|
||||
const first = points[0];
|
||||
const centerApprox = isCenterApprox(first, node);
|
||||
const candidate = centerApprox && points.length > 1 ? points[1] : first;
|
||||
return { candidate, centerApprox };
|
||||
} else {
|
||||
const last = points[points.length - 1];
|
||||
const centerApprox = isCenterApprox(last, node);
|
||||
const candidate = centerApprox && points.length > 1 ? points[points.length - 2] : last;
|
||||
return { candidate, centerApprox };
|
||||
}
|
||||
};
|
||||
|
||||
const dropAutoCenterPoint = (points: P[], side: Side, doDrop: boolean) => {
|
||||
if (!doDrop) {
|
||||
return;
|
||||
}
|
||||
if (side === 'start') {
|
||||
if (points.length > 0) {
|
||||
points.shift();
|
||||
}
|
||||
} else {
|
||||
if (points.length > 0) {
|
||||
points.pop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const applyStartIntersectionIfNeeded = (points: P[], startNode: any, startBounds: RectLike) => {
|
||||
let firstOutsideStartIndex = -1;
|
||||
for (const [i, p] of points.entries()) {
|
||||
if (outsideNode(startBounds, p)) {
|
||||
firstOutsideStartIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (firstOutsideStartIndex !== -1) {
|
||||
const outsidePointForStart = points[firstOutsideStartIndex];
|
||||
const startCenter = points[0];
|
||||
const startIntersection = computeNodeIntersection(
|
||||
startNode,
|
||||
startBounds,
|
||||
outsidePointForStart,
|
||||
startCenter
|
||||
);
|
||||
replaceEndpoint(points, 'start', startIntersection);
|
||||
log.debug('UIO cutter2: start-only intersection applied', { startIntersection });
|
||||
}
|
||||
};
|
||||
|
||||
const applyEndIntersectionIfNeeded = (points: P[], endNode: any, endBounds: RectLike) => {
|
||||
let outsideIndexForEnd = -1;
|
||||
for (let i = points.length - 1; i >= 0; i--) {
|
||||
if (outsideNode(endBounds, points[i])) {
|
||||
outsideIndexForEnd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (outsideIndexForEnd !== -1) {
|
||||
const outsidePointForEnd = points[outsideIndexForEnd];
|
||||
const endCenter = points[points.length - 1];
|
||||
const endIntersection = computeNodeIntersection(
|
||||
endNode,
|
||||
endBounds,
|
||||
outsidePointForEnd,
|
||||
endCenter
|
||||
);
|
||||
replaceEndpoint(points, 'end', endIntersection);
|
||||
log.debug('UIO cutter2: end-only intersection applied', { endIntersection });
|
||||
}
|
||||
};
|
||||
|
||||
const cutter2 = (startNode: any, endNode: any, _points: any[]) => {
|
||||
const startBounds = boundsFor(startNode);
|
||||
const endBounds = boundsFor(endNode);
|
||||
|
||||
if (_points.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Copy the original points array
|
||||
const points: P[] = [..._points] as P[];
|
||||
|
||||
// The first point is the center of sNode, the last point is the center of eNode
|
||||
const startCenter = points[0];
|
||||
const endCenter = points[points.length - 1];
|
||||
|
||||
// Minimal, structured logging for diagnostics
|
||||
log.debug('PPP cutter2: bounds', { startBounds, endBounds });
|
||||
log.debug('PPP cutter2: original points', _points);
|
||||
|
||||
let firstOutsideStartIndex = -1;
|
||||
|
||||
// Single iteration through the array
|
||||
for (const [i, point] of points.entries()) {
|
||||
if (firstOutsideStartIndex === -1 && outsideNode(startBounds, point)) {
|
||||
firstOutsideStartIndex = i;
|
||||
}
|
||||
if (outsideNode(endBounds, point)) {
|
||||
// keep scanning; we'll also scan from the end for the last outside point
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate intersection with start node if we found a point outside it
|
||||
if (firstOutsideStartIndex !== -1) {
|
||||
const outsidePointForStart = points[firstOutsideStartIndex];
|
||||
const startIntersection = computeNodeIntersection(
|
||||
startNode,
|
||||
startBounds,
|
||||
outsidePointForStart,
|
||||
startCenter
|
||||
);
|
||||
log.debug('UIO cutter2: start intersection', startIntersection);
|
||||
replaceEndpoint(points, 'start', startIntersection);
|
||||
}
|
||||
|
||||
// Calculate intersection with end node
|
||||
let outsidePointForEnd = null;
|
||||
let outsideIndexForEnd = -1;
|
||||
|
||||
for (let i = points.length - 1; i >= 0; i--) {
|
||||
if (outsideNode(endBounds, points[i])) {
|
||||
outsidePointForEnd = points[i];
|
||||
outsideIndexForEnd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!outsidePointForEnd && points.length > 1) {
|
||||
outsidePointForEnd = points[points.length - 2];
|
||||
outsideIndexForEnd = points.length - 2;
|
||||
}
|
||||
|
||||
if (outsidePointForEnd) {
|
||||
const endIntersection = computeNodeIntersection(
|
||||
endNode,
|
||||
endBounds,
|
||||
outsidePointForEnd,
|
||||
endCenter
|
||||
);
|
||||
log.debug('UIO cutter2: end intersection', { endIntersection, outsideIndexForEnd });
|
||||
replaceEndpoint(points, 'end', endIntersection);
|
||||
}
|
||||
|
||||
// Final cleanup: Check if the last point is too close to the previous point
|
||||
if (points.length > 1) {
|
||||
const lastPoint = points[points.length - 1];
|
||||
const secondLastPoint = points[points.length - 2];
|
||||
const distance = Math.sqrt(
|
||||
(lastPoint.x - secondLastPoint.x) ** 2 + (lastPoint.y - secondLastPoint.y) ** 2
|
||||
);
|
||||
if (distance < 2) {
|
||||
log.debug('UIO cutter2: trimming tail point (too close)', {
|
||||
distance,
|
||||
lastPoint,
|
||||
secondLastPoint,
|
||||
});
|
||||
points.pop();
|
||||
}
|
||||
}
|
||||
|
||||
log.debug('UIO cutter2: final points', points);
|
||||
|
||||
return points;
|
||||
};
|
||||
|
||||
// @ts-ignore - ELK is not typed
|
||||
const elk = new ELK();
|
||||
const element = svg.select('g');
|
||||
@@ -495,14 +702,19 @@ export const render = async (
|
||||
id: 'root',
|
||||
layoutOptions: {
|
||||
'elk.hierarchyHandling': 'INCLUDE_CHILDREN',
|
||||
'elk.layered.crossingMinimization.forceNodeModelOrder': true,
|
||||
'elk.algorithm': algorithm,
|
||||
'nodePlacement.strategy': data4Layout.config.elk?.nodePlacementStrategy,
|
||||
'elk.layered.mergeEdges': data4Layout.config.elk?.mergeEdges,
|
||||
'elk.direction': 'DOWN',
|
||||
'spacing.baseValue': 35,
|
||||
'spacing.baseValue': 40,
|
||||
'elk.layered.crossingMinimization.forceNodeModelOrder':
|
||||
data4Layout.config.elk?.forceNodeModelOrder,
|
||||
'elk.layered.considerModelOrder.strategy': data4Layout.config.elk?.considerModelOrder,
|
||||
'elk.layered.unnecessaryBendpoints': true,
|
||||
'elk.layered.cycleBreaking.strategy': data4Layout.config.elk?.cycleBreakingStrategy,
|
||||
|
||||
// 'elk.layered.cycleBreaking.strategy': 'GREEDY_MODEL_ORDER',
|
||||
// 'elk.layered.cycleBreaking.strategy': 'MODEL_ORDER',
|
||||
// 'spacing.nodeNode': 20,
|
||||
// 'spacing.nodeNodeBetweenLayers': 25,
|
||||
// 'spacing.edgeNode': 20,
|
||||
@@ -510,22 +722,28 @@ export const render = async (
|
||||
// 'spacing.edgeEdge': 10,
|
||||
// 'spacing.edgeEdgeBetweenLayers': 20,
|
||||
// 'spacing.nodeSelfLoop': 20,
|
||||
|
||||
// Tweaking options
|
||||
// 'nodePlacement.favorStraightEdges': true,
|
||||
// 'elk.layered.nodePlacement.favorStraightEdges': true,
|
||||
// 'nodePlacement.feedbackEdges': true,
|
||||
// 'elk.layered.wrapping.multiEdge.improveCuts': true,
|
||||
// 'elk.layered.wrapping.multiEdge.improveWrappedEdges': true,
|
||||
'elk.layered.wrapping.multiEdge.improveCuts': true,
|
||||
'elk.layered.wrapping.multiEdge.improveWrappedEdges': true,
|
||||
// 'elk.layered.wrapping.strategy': 'MULTI_EDGE',
|
||||
// 'elk.layered.edgeRouting.selfLoopDistribution': 'EQUALLY',
|
||||
// 'elk.layered.mergeHierarchyEdges': true,
|
||||
// 'elk.layered.wrapping.strategy': 'SINGLE_EDGE',
|
||||
'elk.layered.edgeRouting.selfLoopDistribution': 'EQUALLY',
|
||||
'elk.layered.mergeHierarchyEdges': true,
|
||||
|
||||
// 'elk.layered.feedbackEdges': true,
|
||||
// 'elk.layered.crossingMinimization.semiInteractive': true,
|
||||
// 'elk.layered.edgeRouting.splines.sloppy.layerSpacingFactor': 1,
|
||||
// 'elk.layered.edgeRouting.polyline.slopedEdgeZoneWidth': 4.0,
|
||||
// 'elk.layered.wrapping.validify.strategy': 'LOOK_BACK',
|
||||
// 'elk.insideSelfLoops.activate': true,
|
||||
// 'elk.separateConnectedComponents': true,
|
||||
// 'elk.alg.layered.options.EdgeStraighteningStrategy': 'NONE',
|
||||
// 'elk.layered.considerModelOrder.strategy': 'NODES_AND_EDGES', // NODES_AND_EDGES
|
||||
// 'elk.layered.considerModelOrder.strategy': 'EDGES', // NODES_AND_EDGES
|
||||
// 'elk.layered.wrapping.cutting.strategy': 'ARD', // NODES_AND_EDGES
|
||||
},
|
||||
children: [],
|
||||
@@ -535,7 +753,7 @@ export const render = async (
|
||||
log.info('Drawing flowchart using v4 renderer', elk);
|
||||
|
||||
// Set the direction of the graph based on the parsed information
|
||||
const dir = data4Layout.direction || 'DOWN';
|
||||
const dir = data4Layout.direction ?? 'DOWN';
|
||||
elkGraph.layoutOptions['elk.direction'] = dir2ElkDirection(dir);
|
||||
|
||||
// Create the lookup db for the subgraphs and their children to used when creating
|
||||
@@ -566,15 +784,16 @@ export const render = async (
|
||||
|
||||
// Subgraph
|
||||
if (parentLookupDb.childrenById[node.id] !== undefined) {
|
||||
// Set label and adjust node width separately (avoid side effects in labels array)
|
||||
node.labels = [
|
||||
{
|
||||
text: node.label,
|
||||
width: node?.labelData?.width || 50,
|
||||
height: node?.labelData?.height || 50,
|
||||
width: node?.labelData?.width ?? 50,
|
||||
height: node?.labelData?.height ?? 50,
|
||||
},
|
||||
(node.width = node.width + 2 * node.padding),
|
||||
log.debug('UIO node label', node?.labelData?.width, node.padding),
|
||||
];
|
||||
node.width = node.width + 2 * node.padding;
|
||||
log.debug('UIO node label', node?.labelData?.width, node.padding);
|
||||
node.layoutOptions = {
|
||||
'spacing.baseValue': 30,
|
||||
'nodeLabels.placement': '[H_CENTER V_TOP, INSIDE]',
|
||||
@@ -638,7 +857,7 @@ export const render = async (
|
||||
try {
|
||||
g = await elk.layout(elkGraph);
|
||||
log.debug('APA01 after - success');
|
||||
log.debug('APA01 layout result:', JSON.stringify(g, null, 2));
|
||||
log.info('APA01 layout result:', JSON.stringify(g, null, 2));
|
||||
} catch (error) {
|
||||
log.error('APA01 ELK layout error:', error);
|
||||
throw error;
|
||||
@@ -699,10 +918,10 @@ export const render = async (
|
||||
// sw = Math.max(bbox.width, startNode.width, startNode.labels[0].width);
|
||||
sw = Math.max(startNode.width, startNode.labels[0].width + startNode.padding);
|
||||
// sw = startNode.width;
|
||||
log.debug(
|
||||
log.info(
|
||||
'UIO width',
|
||||
startNode.id,
|
||||
startNode.with,
|
||||
startNode.width,
|
||||
'bbox.width=',
|
||||
bbox.width,
|
||||
'lw=',
|
||||
@@ -722,7 +941,7 @@ export const render = async (
|
||||
log.debug(
|
||||
'UIO width',
|
||||
startNode.id,
|
||||
startNode.with,
|
||||
startNode.width,
|
||||
bbox.width,
|
||||
'EW = ',
|
||||
ew,
|
||||
@@ -730,38 +949,109 @@ export const render = async (
|
||||
startNode.innerHTML
|
||||
);
|
||||
}
|
||||
startNode.x = startNode.offset.posX + startNode.width / 2;
|
||||
startNode.y = startNode.offset.posY + startNode.height / 2;
|
||||
endNode.x = endNode.offset.posX + endNode.width / 2;
|
||||
endNode.y = endNode.offset.posY + endNode.height / 2;
|
||||
|
||||
if (startNode.calcIntersect) {
|
||||
const intersection = startNode.calcIntersect(
|
||||
{
|
||||
x: startNode.offset.posX + startNode.width / 2,
|
||||
y: startNode.offset.posY + startNode.height / 2,
|
||||
width: startNode.width,
|
||||
height: startNode.height,
|
||||
},
|
||||
edge.points[0]
|
||||
);
|
||||
// Only add center points for non-subgraph nodes or when the edge path doesn't already end near the target
|
||||
const shouldAddStartCenter = startNode.shape !== 'rect33';
|
||||
const shouldAddEndCenter = endNode.shape !== 'rect33';
|
||||
|
||||
if (distance(intersection, edge.points[0]) > epsilon) {
|
||||
edge.points.unshift(intersection);
|
||||
}
|
||||
}
|
||||
if (endNode.calcIntersect) {
|
||||
const intersection = endNode.calcIntersect(
|
||||
{
|
||||
x: endNode.offset.posX + endNode.width / 2,
|
||||
y: endNode.offset.posY + endNode.height / 2,
|
||||
width: endNode.width,
|
||||
height: endNode.height,
|
||||
},
|
||||
edge.points[edge.points.length - 1]
|
||||
);
|
||||
|
||||
if (distance(intersection, edge.points[edge.points.length - 1]) > epsilon) {
|
||||
edge.points.push(intersection);
|
||||
}
|
||||
if (shouldAddStartCenter) {
|
||||
edge.points.unshift({
|
||||
x: startNode.x,
|
||||
y: startNode.y,
|
||||
});
|
||||
}
|
||||
|
||||
if (shouldAddEndCenter) {
|
||||
edge.points.push({
|
||||
x: endNode.x,
|
||||
y: endNode.y,
|
||||
});
|
||||
}
|
||||
|
||||
// Debug and sanitize points around cutter2
|
||||
const prevPoints = Array.isArray(edge.points) ? [...edge.points] : [];
|
||||
const endBounds = boundsFor(endNode);
|
||||
log.debug(
|
||||
'PPP cutter2: Points before cutter2:',
|
||||
JSON.stringify(edge.points),
|
||||
'endBounds:',
|
||||
endBounds,
|
||||
onBorder(endBounds, edge.points[edge.points.length - 1])
|
||||
);
|
||||
// Block for reducing variable scope and guardrails for the cutter function
|
||||
{
|
||||
const startBounds = boundsFor(startNode);
|
||||
const endBounds = boundsFor(endNode);
|
||||
|
||||
const startIsGroup = !!startNode?.isGroup;
|
||||
const endIsGroup = !!endNode?.isGroup;
|
||||
|
||||
const { candidate: startCandidate, centerApprox: startCenterApprox } =
|
||||
getCandidateBorderPoint(prevPoints as P[], startNode, 'start');
|
||||
const { candidate: endCandidate, centerApprox: endCenterApprox } =
|
||||
getCandidateBorderPoint(prevPoints as P[], endNode, 'end');
|
||||
|
||||
const skipStart = startIsGroup && onBorder(startBounds, startCandidate);
|
||||
const skipEnd = endIsGroup && onBorder(endBounds, endCandidate);
|
||||
|
||||
dropAutoCenterPoint(prevPoints as P[], 'start', skipStart && startCenterApprox);
|
||||
dropAutoCenterPoint(prevPoints as P[], 'end', skipEnd && endCenterApprox);
|
||||
|
||||
if (skipStart || skipEnd) {
|
||||
if (!skipStart) {
|
||||
applyStartIntersectionIfNeeded(prevPoints as P[], startNode, startBounds);
|
||||
}
|
||||
if (!skipEnd) {
|
||||
applyEndIntersectionIfNeeded(prevPoints as P[], endNode, endBounds);
|
||||
}
|
||||
|
||||
log.debug('PPP cutter2: skipping cutter2 due to on-border group endpoint(s)', {
|
||||
skipStart,
|
||||
skipEnd,
|
||||
startCenterApprox,
|
||||
endCenterApprox,
|
||||
startCandidate,
|
||||
endCandidate,
|
||||
});
|
||||
edge.points = prevPoints;
|
||||
} else {
|
||||
edge.points = cutter2(startNode, endNode, prevPoints);
|
||||
}
|
||||
}
|
||||
log.debug('PPP cutter2: Points after cutter2:', JSON.stringify(edge.points));
|
||||
const hasNaN = (pts: { x: number; y: number }[]) =>
|
||||
pts?.some((p) => !Number.isFinite(p?.x) || !Number.isFinite(p?.y));
|
||||
if (!Array.isArray(edge.points) || edge.points.length < 2 || hasNaN(edge.points)) {
|
||||
log.warn(
|
||||
'POI cutter2: Invalid points from cutter2, falling back to prevPoints',
|
||||
edge.points
|
||||
);
|
||||
// Fallback to previous points and strip any invalid ones just in case
|
||||
const cleaned = prevPoints.filter((p) => Number.isFinite(p?.x) && Number.isFinite(p?.y));
|
||||
edge.points = cleaned.length >= 2 ? cleaned : prevPoints;
|
||||
}
|
||||
log.debug('UIO cutter2: Points after cutter2 (sanitized):', edge.points);
|
||||
// Remove consecutive duplicate points to avoid zero-length segments in path builders
|
||||
const deduped = edge.points.filter(
|
||||
(p: { x: number; y: number }, i: number, arr: { x: number; y: number }[]) => {
|
||||
if (i === 0) {
|
||||
return true;
|
||||
}
|
||||
const prev = arr[i - 1];
|
||||
return Math.abs(p.x - prev.x) > 1e-6 || Math.abs(p.y - prev.y) > 1e-6;
|
||||
}
|
||||
);
|
||||
if (deduped.length !== edge.points.length) {
|
||||
log.debug('UIO cutter2: removed consecutive duplicate points', {
|
||||
before: edge.points,
|
||||
after: deduped,
|
||||
});
|
||||
}
|
||||
edge.points = deduped;
|
||||
const paths = insertEdge(
|
||||
edgesEl,
|
||||
edge,
|
||||
@@ -769,8 +1059,10 @@ export const render = async (
|
||||
data4Layout.type,
|
||||
startNode,
|
||||
endNode,
|
||||
data4Layout.diagramId
|
||||
data4Layout.diagramId,
|
||||
true
|
||||
);
|
||||
log.info('APA12 edge points after insert', JSON.stringify(edge.points));
|
||||
|
||||
edge.x = edge.labels[0].x + offset.x + edge.labels[0].width / 2;
|
||||
edge.y = edge.labels[0].y + offset.y + edge.labels[0].height / 2;
|
||||
|
12
packages/mermaid-layout-tidy-tree/CHANGELOG.md
Normal file
12
packages/mermaid-layout-tidy-tree/CHANGELOG.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# @mermaid-js/layout-tidy-tree
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800), [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20), [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05), [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8)]:
|
||||
- mermaid@11.11.0
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@mermaid-js/layout-tidy-tree",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"description": "Tidy-tree layout engine for mermaid",
|
||||
"module": "dist/mermaid-layout-tidy-tree.core.mjs",
|
||||
"types": "dist/layouts.d.ts",
|
||||
|
@@ -1,4 +1,7 @@
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import { executeTidyTreeLayout, validateLayoutData } from './layout.js';
|
||||
import type { LayoutResult } from './types.js';
|
||||
import type { LayoutData, MermaidConfig } from 'mermaid';
|
||||
|
||||
// Mock non-layered-tidy-tree-layout
|
||||
vi.mock('non-layered-tidy-tree-layout', () => ({
|
||||
@@ -42,10 +45,6 @@ vi.mock('non-layered-tidy-tree-layout', () => ({
|
||||
})),
|
||||
}));
|
||||
|
||||
import { executeTidyTreeLayout, validateLayoutData } from './layout.js';
|
||||
import type { LayoutResult } from './types.js';
|
||||
import type { LayoutData, MermaidConfig } from 'mermaid';
|
||||
|
||||
describe('Tidy-Tree Layout Algorithm', () => {
|
||||
let mockConfig: MermaidConfig;
|
||||
let mockLayoutData: LayoutData;
|
||||
@@ -209,7 +208,7 @@ describe('Tidy-Tree Layout Algorithm', () => {
|
||||
|
||||
describe('executeTidyTreeLayout function', () => {
|
||||
it('should execute layout algorithm successfully', async () => {
|
||||
const result: LayoutResult = await executeTidyTreeLayout(mockLayoutData, mockConfig);
|
||||
const result: LayoutResult = await executeTidyTreeLayout(mockLayoutData);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result.nodes).toBeDefined();
|
||||
@@ -219,7 +218,7 @@ describe('Tidy-Tree Layout Algorithm', () => {
|
||||
});
|
||||
|
||||
it('should return positioned nodes with coordinates', async () => {
|
||||
const result: LayoutResult = await executeTidyTreeLayout(mockLayoutData, mockConfig);
|
||||
const result: LayoutResult = await executeTidyTreeLayout(mockLayoutData);
|
||||
|
||||
expect(result.nodes.length).toBeGreaterThan(0);
|
||||
result.nodes.forEach((node) => {
|
||||
@@ -231,7 +230,7 @@ describe('Tidy-Tree Layout Algorithm', () => {
|
||||
});
|
||||
|
||||
it('should return positioned edges with coordinates', async () => {
|
||||
const result: LayoutResult = await executeTidyTreeLayout(mockLayoutData, mockConfig);
|
||||
const result: LayoutResult = await executeTidyTreeLayout(mockLayoutData);
|
||||
|
||||
expect(result.edges.length).toBeGreaterThan(0);
|
||||
result.edges.forEach((edge) => {
|
||||
@@ -251,7 +250,7 @@ describe('Tidy-Tree Layout Algorithm', () => {
|
||||
edges: [],
|
||||
};
|
||||
|
||||
await expect(executeTidyTreeLayout(emptyData, mockConfig)).rejects.toThrow(
|
||||
await expect(executeTidyTreeLayout(emptyData)).rejects.toThrow(
|
||||
'No nodes found in layout data'
|
||||
);
|
||||
});
|
||||
@@ -259,7 +258,7 @@ describe('Tidy-Tree Layout Algorithm', () => {
|
||||
it('should throw error for missing nodes', async () => {
|
||||
const invalidData = { ...mockLayoutData, nodes: [] };
|
||||
|
||||
await expect(executeTidyTreeLayout(invalidData, mockConfig)).rejects.toThrow(
|
||||
await expect(executeTidyTreeLayout(invalidData)).rejects.toThrow(
|
||||
'No nodes found in layout data'
|
||||
);
|
||||
});
|
||||
@@ -271,14 +270,14 @@ describe('Tidy-Tree Layout Algorithm', () => {
|
||||
nodes: [mockLayoutData.nodes[0]],
|
||||
};
|
||||
|
||||
const result = await executeTidyTreeLayout(singleNodeData, mockConfig);
|
||||
const result = await executeTidyTreeLayout(singleNodeData);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.nodes).toHaveLength(1);
|
||||
expect(result.edges).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should create bidirectional dual-tree layout with alternating left/right children', async () => {
|
||||
const result = await executeTidyTreeLayout(mockLayoutData, mockConfig);
|
||||
const result = await executeTidyTreeLayout(mockLayoutData);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result.nodes).toHaveLength(5);
|
||||
@@ -383,7 +382,7 @@ describe('Tidy-Tree Layout Algorithm', () => {
|
||||
],
|
||||
};
|
||||
|
||||
const result = await executeTidyTreeLayout(testData, mockConfig);
|
||||
const result = await executeTidyTreeLayout(testData);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result.nodes).toHaveLength(3);
|
||||
|
@@ -1,12 +1,13 @@
|
||||
import type { LayoutData } from 'mermaid';
|
||||
import type { Bounds, Point } from 'mermaid/src/types.js';
|
||||
import { BoundingBox, Layout } from 'non-layered-tidy-tree-layout';
|
||||
import type { MermaidConfig, LayoutData } from 'mermaid';
|
||||
import type {
|
||||
LayoutResult,
|
||||
TidyTreeNode,
|
||||
PositionedNode,
|
||||
PositionedEdge,
|
||||
Node,
|
||||
Edge,
|
||||
LayoutResult,
|
||||
Node,
|
||||
PositionedEdge,
|
||||
PositionedNode,
|
||||
TidyTreeNode,
|
||||
} from './types.js';
|
||||
|
||||
/**
|
||||
@@ -19,10 +20,7 @@ import type {
|
||||
* @param config - Mermaid configuration object
|
||||
* @returns Promise resolving to layout result with positioned nodes and edges
|
||||
*/
|
||||
export function executeTidyTreeLayout(
|
||||
data: LayoutData,
|
||||
_config: MermaidConfig
|
||||
): Promise<LayoutResult> {
|
||||
export function executeTidyTreeLayout(data: LayoutData): Promise<LayoutResult> {
|
||||
let intersectionShift = 50;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -46,35 +44,23 @@ export function executeTidyTreeLayout(
|
||||
|
||||
let leftResult = null;
|
||||
let rightResult = null;
|
||||
let leftBoundingBox = null;
|
||||
let rightBoundingBox = null;
|
||||
|
||||
if (leftTree) {
|
||||
const leftLayoutResult = layout.layout(leftTree);
|
||||
leftResult = leftLayoutResult.result;
|
||||
leftBoundingBox = leftLayoutResult.boundingBox;
|
||||
}
|
||||
|
||||
if (rightTree) {
|
||||
const rightLayoutResult = layout.layout(rightTree);
|
||||
rightResult = rightLayoutResult.result;
|
||||
rightBoundingBox = rightLayoutResult.boundingBox;
|
||||
}
|
||||
|
||||
const positionedNodes = combineAndPositionTrees(
|
||||
rootNode,
|
||||
leftResult,
|
||||
rightResult,
|
||||
leftBoundingBox,
|
||||
rightBoundingBox,
|
||||
data
|
||||
);
|
||||
const positionedNodes = combineAndPositionTrees(rootNode, leftResult, rightResult);
|
||||
const positionedEdges = calculateEdgePositions(
|
||||
data.edges,
|
||||
positionedNodes,
|
||||
intersectionShift
|
||||
);
|
||||
|
||||
resolve({
|
||||
nodes: positionedNodes,
|
||||
edges: positionedEdges,
|
||||
@@ -203,10 +189,7 @@ function convertNodeToTidyTreeTransposed(
|
||||
function combineAndPositionTrees(
|
||||
rootNode: TidyTreeNode,
|
||||
leftResult: TidyTreeNode | null,
|
||||
rightResult: TidyTreeNode | null,
|
||||
_leftBoundingBox: any,
|
||||
_rightBoundingBox: any,
|
||||
_data: LayoutData
|
||||
rightResult: TidyTreeNode | null
|
||||
): PositionedNode[] {
|
||||
const positionedNodes: PositionedNode[] = [];
|
||||
|
||||
@@ -383,11 +366,7 @@ function positionRightTreeBidirectional(
|
||||
* @param lineEnd - Ending point of the line
|
||||
* @returns The intersection point
|
||||
*/
|
||||
function computeCircleEdgeIntersection(
|
||||
circle: { x: number; y: number; width: number; height: number },
|
||||
lineStart: { x: number; y: number },
|
||||
lineEnd: { x: number; y: number }
|
||||
): { x: number; y: number } {
|
||||
function computeCircleEdgeIntersection(circle: Bounds, lineStart: Point, lineEnd: Point): Point {
|
||||
const radius = Math.min(circle.width, circle.height) / 2;
|
||||
|
||||
const dx = lineEnd.x - lineStart.x;
|
||||
@@ -407,53 +386,65 @@ function computeCircleEdgeIntersection(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate intersection point of a line with a rectangle
|
||||
* This is a simplified version that we'll use instead of importing from mermaid
|
||||
*/
|
||||
function intersection(
|
||||
node: { x: number; y: number; width?: number; height?: number },
|
||||
point1: { x: number; y: number },
|
||||
point2: { x: number; y: number }
|
||||
): { x: number; y: number } {
|
||||
const nodeWidth = node.width ?? 100;
|
||||
const nodeHeight = node.height ?? 50;
|
||||
function intersection(node: PositionedNode, outsidePoint: Point, insidePoint: Point): Point {
|
||||
const x = node.x;
|
||||
const y = node.y;
|
||||
|
||||
const centerX = node.x;
|
||||
const centerY = node.y;
|
||||
|
||||
const dx = point2.x - point1.x;
|
||||
const dy = point2.y - point1.y;
|
||||
|
||||
if (dx === 0 && dy === 0) {
|
||||
return { x: centerX, y: centerY };
|
||||
if (!node.width || !node.height) {
|
||||
return { x: outsidePoint.x, y: outsidePoint.y };
|
||||
}
|
||||
const dx = Math.abs(x - insidePoint.x);
|
||||
const w = node?.width / 2;
|
||||
let r = insidePoint.x < outsidePoint.x ? w - dx : w + dx;
|
||||
const h = node.height / 2;
|
||||
|
||||
const halfWidth = nodeWidth / 2;
|
||||
const halfHeight = nodeHeight / 2;
|
||||
const Q = Math.abs(outsidePoint.y - insidePoint.y);
|
||||
const R = Math.abs(outsidePoint.x - insidePoint.x);
|
||||
|
||||
let intersectionX = centerX;
|
||||
let intersectionY = centerY;
|
||||
if (Math.abs(y - outsidePoint.y) * w > Math.abs(x - outsidePoint.x) * h) {
|
||||
// Intersection is top or bottom of rect.
|
||||
const q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y;
|
||||
r = (R * q) / Q;
|
||||
const res = {
|
||||
x: insidePoint.x < outsidePoint.x ? insidePoint.x + r : insidePoint.x - R + r,
|
||||
y: insidePoint.y < outsidePoint.y ? insidePoint.y + Q - q : insidePoint.y - Q + q,
|
||||
};
|
||||
|
||||
if (Math.abs(dx) > Math.abs(dy)) {
|
||||
if (dx > 0) {
|
||||
intersectionX = centerX + halfWidth;
|
||||
intersectionY = centerY + (halfWidth * dy) / dx;
|
||||
} else {
|
||||
intersectionX = centerX - halfWidth;
|
||||
intersectionY = centerY - (halfWidth * dy) / dx;
|
||||
if (r === 0) {
|
||||
res.x = outsidePoint.x;
|
||||
res.y = outsidePoint.y;
|
||||
}
|
||||
if (R === 0) {
|
||||
res.x = outsidePoint.x;
|
||||
}
|
||||
if (Q === 0) {
|
||||
res.y = outsidePoint.y;
|
||||
}
|
||||
|
||||
return res;
|
||||
} else {
|
||||
if (dy > 0) {
|
||||
intersectionY = centerY + halfHeight;
|
||||
intersectionX = centerX + (halfHeight * dx) / dy;
|
||||
if (insidePoint.x < outsidePoint.x) {
|
||||
r = outsidePoint.x - w - x;
|
||||
} else {
|
||||
intersectionY = centerY - halfHeight;
|
||||
intersectionX = centerX - (halfHeight * dx) / dy;
|
||||
r = x - w - outsidePoint.x;
|
||||
}
|
||||
}
|
||||
const q = (Q * r) / R;
|
||||
let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x - R + r;
|
||||
let _y = insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q;
|
||||
|
||||
return { x: intersectionX, y: intersectionY };
|
||||
if (r === 0) {
|
||||
_x = outsidePoint.x;
|
||||
_y = outsidePoint.y;
|
||||
}
|
||||
if (R === 0) {
|
||||
_x = outsidePoint.x;
|
||||
}
|
||||
if (Q === 0) {
|
||||
_y = outsidePoint.y;
|
||||
}
|
||||
|
||||
return { x: _x, y: _y };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -102,7 +102,7 @@ export const render = async (
|
||||
}),
|
||||
};
|
||||
|
||||
const layoutResult = await executeTidyTreeLayout(updatedLayoutData, data4Layout.config);
|
||||
const layoutResult = await executeTidyTreeLayout(updatedLayoutData);
|
||||
// Step 3: Position the nodes based on bidirectional layout results
|
||||
log.debug('Positioning nodes based on bidirectional layout results');
|
||||
|
||||
|
@@ -1,5 +1,14 @@
|
||||
# @mermaid-js/mermaid-zenuml
|
||||
|
||||
## 0.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6798](https://github.com/mermaid-js/mermaid/pull/6798) [`3ffe961`](https://github.com/mermaid-js/mermaid/commit/3ffe9618aebc9ac96de6e3c826481f542f18c2a9) Thanks [@MrCoder](https://github.com/MrCoder)! - Fixed a critical bug that the ZenUML diagram is not rendered.
|
||||
|
||||
- Updated dependencies [[`b9ef683`](https://github.com/mermaid-js/mermaid/commit/b9ef683fb67b8959abc455d6cc5266c37ba435f6), [`2c0931d`](https://github.com/mermaid-js/mermaid/commit/2c0931da46794b49d2523211e25f782900c34e94), [`33e08da`](https://github.com/mermaid-js/mermaid/commit/33e08daf175125295a06b1b80279437004a4e865), [`814b68b`](https://github.com/mermaid-js/mermaid/commit/814b68b4a94813f7c6b3d7fb4559532a7bab2652), [`fce7cab`](https://github.com/mermaid-js/mermaid/commit/fce7cabb71d68a20a66246fe23d066512126a412), [`fc07f0d`](https://github.com/mermaid-js/mermaid/commit/fc07f0d8abca49e4f887d7457b7b94fb07d1e3da), [`12e01bd`](https://github.com/mermaid-js/mermaid/commit/12e01bdb5cacf3569133979a5a4f1d8973e9aec1), [`01aaef3`](https://github.com/mermaid-js/mermaid/commit/01aaef39b4a1ec8bc5a0c6bfa3a20b712d67f4dc), [`daf8d8d`](https://github.com/mermaid-js/mermaid/commit/daf8d8d3befcd600618a629977b76463b38d0ad9), [`c36cd05`](https://github.com/mermaid-js/mermaid/commit/c36cd05c45ac3090181152b4dae41f8d7b569bd6), [`8bb29fc`](https://github.com/mermaid-js/mermaid/commit/8bb29fc879329ad109898e4025b4f4eba2ab0649), [`71b04f9`](https://github.com/mermaid-js/mermaid/commit/71b04f93b07f876df2b30656ef36036c1d0e4e4f), [`c99bce6`](https://github.com/mermaid-js/mermaid/commit/c99bce6bab4c7ce0b81b66d44f44853ce4aeb1c3), [`6cc1926`](https://github.com/mermaid-js/mermaid/commit/6cc192680a2531cab28f87a8061a53b786e010f3), [`9da6fb3`](https://github.com/mermaid-js/mermaid/commit/9da6fb39ae278401771943ac85d6d1b875f78cf1), [`e48b0ba`](https://github.com/mermaid-js/mermaid/commit/e48b0ba61dab7f95aa02da603b5b7d383b894932), [`4d62d59`](https://github.com/mermaid-js/mermaid/commit/4d62d5963238400270e9314c6e4d506f48147074), [`e9ce8cf`](https://github.com/mermaid-js/mermaid/commit/e9ce8cf4da9062d85098042044822100889bb0dd), [`9258b29`](https://github.com/mermaid-js/mermaid/commit/9258b2933bbe1ef41087345ffea3731673671c49), [`da90f67`](https://github.com/mermaid-js/mermaid/commit/da90f6760b6efb0da998bcb63b75eecc29e06c08), [`0133f1c`](https://github.com/mermaid-js/mermaid/commit/0133f1c0c5cff4fc4c8e0b99e9cf0b3d49dcbe71), [`895f9d4`](https://github.com/mermaid-js/mermaid/commit/895f9d43ff98ca05ebfba530789f677f31a011ff)]:
|
||||
- mermaid@11.10.0
|
||||
|
||||
## 0.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@mermaid-js/mermaid-zenuml",
|
||||
"version": "0.2.1",
|
||||
"version": "0.2.2",
|
||||
"description": "MermaidJS plugin for ZenUML integration",
|
||||
"module": "dist/mermaid-zenuml.core.mjs",
|
||||
"types": "dist/detector.d.ts",
|
||||
@@ -33,7 +33,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@zenuml/core": "^3.35.2"
|
||||
"@zenuml/core": "^3.41.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mermaid": "workspace:^"
|
||||
|
@@ -1,5 +1,86 @@
|
||||
# mermaid
|
||||
|
||||
## 11.11.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#6704](https://github.com/mermaid-js/mermaid/pull/6704) [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05) Thanks [@omkarht](https://github.com/omkarht)! - feat: Added support for new participant types (`actor`, `boundary`, `control`, `entity`, `database`, `collections`, `queue`) in `sequenceDiagram`.
|
||||
|
||||
- [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6905](https://github.com/mermaid-js/mermaid/pull/6905) [`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Render newlines as spaces in class diagrams
|
||||
|
||||
- [#6886](https://github.com/mermaid-js/mermaid/pull/6886) [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Handle arrows correctly when auto number is enabled
|
||||
|
||||
## 11.10.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#6744](https://github.com/mermaid-js/mermaid/pull/6744) [`daf8d8d`](https://github.com/mermaid-js/mermaid/commit/daf8d8d3befcd600618a629977b76463b38d0ad9) Thanks [@SpecularAura](https://github.com/SpecularAura)! - feat: Added support for per link curve styling in flowchart diagram using edge ids
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#6857](https://github.com/mermaid-js/mermaid/pull/6857) [`b9ef683`](https://github.com/mermaid-js/mermaid/commit/b9ef683fb67b8959abc455d6cc5266c37ba435f6) Thanks [@knsv](https://github.com/knsv)! - feat: Exposing elk configuration forceNodeModelOrder and considerModelOrder to the mermaid configuration
|
||||
|
||||
- [#6653](https://github.com/mermaid-js/mermaid/pull/6653) [`2c0931d`](https://github.com/mermaid-js/mermaid/commit/2c0931da46794b49d2523211e25f782900c34e94) Thanks [@darshanr0107](https://github.com/darshanr0107)! - chore: Remove the "-beta" suffix from the XYChart, Block, Sankey diagrams to reflect their stable status
|
||||
|
||||
- [#6683](https://github.com/mermaid-js/mermaid/pull/6683) [`33e08da`](https://github.com/mermaid-js/mermaid/commit/33e08daf175125295a06b1b80279437004a4e865) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Position the edge label in state diagram correctly relative to the edge
|
||||
|
||||
- [#6693](https://github.com/mermaid-js/mermaid/pull/6693) [`814b68b`](https://github.com/mermaid-js/mermaid/commit/814b68b4a94813f7c6b3d7fb4559532a7bab2652) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Apply correct dateFormat in Gantt chart to show only day when specified
|
||||
|
||||
- [#6734](https://github.com/mermaid-js/mermaid/pull/6734) [`fce7cab`](https://github.com/mermaid-js/mermaid/commit/fce7cabb71d68a20a66246fe23d066512126a412) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: handle exclude dates properly in Gantt charts when using dateFormat: 'YYYY-MM-DD HH:mm:ss'
|
||||
|
||||
- [#6733](https://github.com/mermaid-js/mermaid/pull/6733) [`fc07f0d`](https://github.com/mermaid-js/mermaid/commit/fc07f0d8abca49e4f887d7457b7b94fb07d1e3da) Thanks [@omkarht](https://github.com/omkarht)! - fix: fixed connection gaps in flowchart for roundedRect, stadium and diamond shape
|
||||
|
||||
- [#6876](https://github.com/mermaid-js/mermaid/pull/6876) [`12e01bd`](https://github.com/mermaid-js/mermaid/commit/12e01bdb5cacf3569133979a5a4f1d8973e9aec1) Thanks [@sidharthv96](https://github.com/sidharthv96)! - fix: sanitize icon labels and icon SVGs
|
||||
|
||||
Resolves CVE-2025-54880 reported by @fourcube
|
||||
|
||||
- [#6801](https://github.com/mermaid-js/mermaid/pull/6801) [`01aaef3`](https://github.com/mermaid-js/mermaid/commit/01aaef39b4a1ec8bc5a0c6bfa3a20b712d67f4dc) Thanks [@sidharthv96](https://github.com/sidharthv96)! - fix: Update casing of ID in requirement diagram
|
||||
|
||||
- [#6796](https://github.com/mermaid-js/mermaid/pull/6796) [`c36cd05`](https://github.com/mermaid-js/mermaid/commit/c36cd05c45ac3090181152b4dae41f8d7b569bd6) Thanks [@HashanCP](https://github.com/HashanCP)! - fix: Make flowchart elk detector regex match less greedy
|
||||
|
||||
- [#6702](https://github.com/mermaid-js/mermaid/pull/6702) [`8bb29fc`](https://github.com/mermaid-js/mermaid/commit/8bb29fc879329ad109898e4025b4f4eba2ab0649) Thanks [@qraqras](https://github.com/qraqras)! - fix(block): overflowing blocks no longer affect later lines
|
||||
|
||||
This may change the layout of block diagrams that have overflowing lines
|
||||
(i.e. block diagrams that use up more columns that the `columns` specifier).
|
||||
|
||||
- [#6717](https://github.com/mermaid-js/mermaid/pull/6717) [`71b04f9`](https://github.com/mermaid-js/mermaid/commit/71b04f93b07f876df2b30656ef36036c1d0e4e4f) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: log warning for blocks exceeding column width
|
||||
|
||||
This update adds a validation check that logs a warning message when a block's width exceeds the defined column layout.
|
||||
|
||||
- [#6820](https://github.com/mermaid-js/mermaid/pull/6820) [`c99bce6`](https://github.com/mermaid-js/mermaid/commit/c99bce6bab4c7ce0b81b66d44f44853ce4aeb1c3) Thanks [@kriss-u](https://github.com/kriss-u)! - fix: Add escaped class literal name on namespace
|
||||
|
||||
- [#6332](https://github.com/mermaid-js/mermaid/pull/6332) [`6cc1926`](https://github.com/mermaid-js/mermaid/commit/6cc192680a2531cab28f87a8061a53b786e010f3) Thanks [@ajuckel](https://github.com/ajuckel)! - fix: Allow equals sign in sequenceDiagram labels
|
||||
|
||||
- [#6651](https://github.com/mermaid-js/mermaid/pull/6651) [`9da6fb3`](https://github.com/mermaid-js/mermaid/commit/9da6fb39ae278401771943ac85d6d1b875f78cf1) Thanks [@darshanr0107](https://github.com/darshanr0107)! - Add validation for negative values in pie charts:
|
||||
|
||||
Prevents crashes during parsing by validating values post-parsing.
|
||||
|
||||
Provides clearer, user-friendly error messages for invalid negative inputs.
|
||||
|
||||
- [#6803](https://github.com/mermaid-js/mermaid/pull/6803) [`e48b0ba`](https://github.com/mermaid-js/mermaid/commit/e48b0ba61dab7f95aa02da603b5b7d383b894932) Thanks [@omkarht](https://github.com/omkarht)! - chore: migrate to class-based ArchitectureDB implementation
|
||||
|
||||
- [#6838](https://github.com/mermaid-js/mermaid/pull/6838) [`4d62d59`](https://github.com/mermaid-js/mermaid/commit/4d62d5963238400270e9314c6e4d506f48147074) Thanks [@saurabhg772244](https://github.com/saurabhg772244)! - fix: node border style for handdrawn shapes
|
||||
|
||||
- [#6739](https://github.com/mermaid-js/mermaid/pull/6739) [`e9ce8cf`](https://github.com/mermaid-js/mermaid/commit/e9ce8cf4da9062d85098042044822100889bb0dd) Thanks [@kriss-u](https://github.com/kriss-u)! - fix: Update flowchart direction TD's behavior to be the same as TB
|
||||
|
||||
- [#6833](https://github.com/mermaid-js/mermaid/pull/6833) [`9258b29`](https://github.com/mermaid-js/mermaid/commit/9258b2933bbe1ef41087345ffea3731673671c49) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: correctly render non-directional lines for '---' in block diagrams
|
||||
|
||||
- [#6855](https://github.com/mermaid-js/mermaid/pull/6855) [`da90f67`](https://github.com/mermaid-js/mermaid/commit/da90f6760b6efb0da998bcb63b75eecc29e06c08) Thanks [@sidharthv96](https://github.com/sidharthv96)! - fix: fallback to raw text instead of rendering _Unsupported markdown_ or empty blocks
|
||||
|
||||
Instead of printing **Unsupported markdown: XXX**, or empty blocks when using a markdown feature
|
||||
that Mermaid does not yet support when `htmlLabels: true`(default) or `htmlLabels: false`,
|
||||
fallback to the raw markdown text.
|
||||
|
||||
- [#6876](https://github.com/mermaid-js/mermaid/pull/6876) [`0133f1c`](https://github.com/mermaid-js/mermaid/commit/0133f1c0c5cff4fc4c8e0b99e9cf0b3d49dcbe71) Thanks [@sidharthv96](https://github.com/sidharthv96)! - fix: sanitize KATEX blocks
|
||||
|
||||
Resolves CVE-2025-54881 reported by @fourcube
|
||||
|
||||
- [#6804](https://github.com/mermaid-js/mermaid/pull/6804) [`895f9d4`](https://github.com/mermaid-js/mermaid/commit/895f9d43ff98ca05ebfba530789f677f31a011ff) Thanks [@omkarht](https://github.com/omkarht)! - chore: Update packet diagram to use new class-based database structure
|
||||
|
||||
## 11.9.0
|
||||
|
||||
### Minor Changes
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mermaid",
|
||||
"version": "11.9.0",
|
||||
"version": "11.11.0",
|
||||
"description": "Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.",
|
||||
"type": "module",
|
||||
"module": "./dist/mermaid.core.mjs",
|
||||
@@ -67,29 +67,29 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^7.0.4",
|
||||
"@iconify/utils": "^2.1.33",
|
||||
"@braintree/sanitize-url": "^7.1.1",
|
||||
"@iconify/utils": "^3.0.2",
|
||||
"@mermaid-js/parser": "workspace:^",
|
||||
"@types/d3": "^7.4.3",
|
||||
"cytoscape": "^3.29.3",
|
||||
"cytoscape": "^3.33.1",
|
||||
"cytoscape-cose-bilkent": "^4.1.0",
|
||||
"cytoscape-fcose": "^2.2.0",
|
||||
"d3": "^7.9.0",
|
||||
"d3-sankey": "^0.12.3",
|
||||
"dagre-d3-es": "7.0.11",
|
||||
"dayjs": "^1.11.13",
|
||||
"dompurify": "^3.2.5",
|
||||
"dayjs": "^1.11.18",
|
||||
"dompurify": "^3.2.7",
|
||||
"katex": "^0.16.22",
|
||||
"khroma": "^2.1.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"marked": "^15.0.7",
|
||||
"marked": "^16.3.0",
|
||||
"roughjs": "^4.6.6",
|
||||
"stylis": "^4.3.6",
|
||||
"ts-dedent": "^2.2.0",
|
||||
"uuid": "^11.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@adobe/jsonschema2md": "^8.0.2",
|
||||
"@adobe/jsonschema2md": "^8.0.5",
|
||||
"@iconify/types": "^2.0.0",
|
||||
"@types/cytoscape": "^3.21.9",
|
||||
"@types/cytoscape-fcose": "^2.2.4",
|
||||
@@ -105,30 +105,30 @@
|
||||
"@types/stylis": "^4.2.7",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"ajv": "^8.17.1",
|
||||
"canvas": "^3.1.0",
|
||||
"canvas": "^3.2.0",
|
||||
"chokidar": "3.6.0",
|
||||
"concurrently": "^9.1.2",
|
||||
"concurrently": "^9.2.1",
|
||||
"csstree-validator": "^4.0.1",
|
||||
"globby": "^14.0.2",
|
||||
"globby": "^14.1.0",
|
||||
"jison": "^0.4.18",
|
||||
"js-base64": "^3.7.7",
|
||||
"js-base64": "^3.7.8",
|
||||
"jsdom": "^26.1.0",
|
||||
"json-schema-to-typescript": "^15.0.4",
|
||||
"micromatch": "^4.0.8",
|
||||
"path-browserify": "^1.0.1",
|
||||
"prettier": "^3.5.2",
|
||||
"prettier": "^3.6.2",
|
||||
"remark": "^15.0.1",
|
||||
"remark-frontmatter": "^5.0.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"rimraf": "^6.0.1",
|
||||
"start-server-and-test": "^2.0.10",
|
||||
"type-fest": "^4.35.0",
|
||||
"typedoc": "^0.28.9",
|
||||
"typedoc-plugin-markdown": "^4.8.0",
|
||||
"start-server-and-test": "^2.1.2",
|
||||
"type-fest": "^4.41.0",
|
||||
"typedoc": "^0.28.13",
|
||||
"typedoc-plugin-markdown": "^4.8.1",
|
||||
"typescript": "~5.7.3",
|
||||
"unist-util-flatmap": "^1.0.0",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"vitepress": "^1.0.2",
|
||||
"vitepress": "^1.6.4",
|
||||
"vitepress-plugin-search": "1.0.4-alpha.22"
|
||||
},
|
||||
"files": [
|
||||
|
@@ -78,3 +78,187 @@ describe('when working with site config', () => {
|
||||
expect(config_4.altFontFamily).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUserDefinedConfig', () => {
|
||||
beforeEach(() => {
|
||||
configApi.reset();
|
||||
});
|
||||
|
||||
it('should return empty object when no user config is defined', () => {
|
||||
const userConfig = configApi.getUserDefinedConfig();
|
||||
expect(userConfig).toEqual({});
|
||||
});
|
||||
|
||||
it('should return config from initialize only', () => {
|
||||
const initConfig: MermaidConfig = { theme: 'dark', fontFamily: 'Arial' };
|
||||
configApi.saveConfigFromInitialize(initConfig);
|
||||
|
||||
const userConfig = configApi.getUserDefinedConfig();
|
||||
expect(userConfig).toEqual(initConfig);
|
||||
});
|
||||
|
||||
it('should return config from directives only', () => {
|
||||
const directive1: MermaidConfig = { layout: 'elk', fontSize: 14 };
|
||||
const directive2: MermaidConfig = { theme: 'forest' };
|
||||
|
||||
configApi.addDirective(directive1);
|
||||
configApi.addDirective(directive2);
|
||||
|
||||
expect(configApi.getUserDefinedConfig()).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fontFamily": "Arial",
|
||||
"fontSize": 14,
|
||||
"layout": "elk",
|
||||
"theme": "forest",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should combine initialize config and directives', () => {
|
||||
const initConfig: MermaidConfig = { theme: 'dark', fontFamily: 'Arial', layout: 'dagre' };
|
||||
const directive1: MermaidConfig = { layout: 'elk', fontSize: 14 };
|
||||
const directive2: MermaidConfig = { theme: 'forest' };
|
||||
|
||||
configApi.saveConfigFromInitialize(initConfig);
|
||||
configApi.addDirective(directive1);
|
||||
configApi.addDirective(directive2);
|
||||
|
||||
const userConfig = configApi.getUserDefinedConfig();
|
||||
expect(userConfig).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fontFamily": "Arial",
|
||||
"fontSize": 14,
|
||||
"layout": "elk",
|
||||
"theme": "forest",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should handle nested config objects properly', () => {
|
||||
const initConfig: MermaidConfig = {
|
||||
flowchart: { nodeSpacing: 50, rankSpacing: 100 },
|
||||
theme: 'default',
|
||||
};
|
||||
const directive: MermaidConfig = {
|
||||
flowchart: { nodeSpacing: 75, curve: 'basis' },
|
||||
mindmap: { padding: 20 },
|
||||
};
|
||||
|
||||
configApi.saveConfigFromInitialize(initConfig);
|
||||
configApi.addDirective(directive);
|
||||
|
||||
const userConfig = configApi.getUserDefinedConfig();
|
||||
expect(userConfig).toMatchInlineSnapshot(`
|
||||
{
|
||||
"flowchart": {
|
||||
"curve": "basis",
|
||||
"nodeSpacing": 75,
|
||||
"rankSpacing": 100,
|
||||
},
|
||||
"mindmap": {
|
||||
"padding": 20,
|
||||
},
|
||||
"theme": "default",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should handle complex nested overrides', () => {
|
||||
const initConfig: MermaidConfig = {
|
||||
flowchart: {
|
||||
nodeSpacing: 50,
|
||||
rankSpacing: 100,
|
||||
curve: 'linear',
|
||||
},
|
||||
theme: 'default',
|
||||
};
|
||||
const directive1: MermaidConfig = {
|
||||
flowchart: {
|
||||
nodeSpacing: 75,
|
||||
},
|
||||
fontSize: 12,
|
||||
};
|
||||
const directive2: MermaidConfig = {
|
||||
flowchart: {
|
||||
curve: 'basis',
|
||||
nodeSpacing: 100,
|
||||
},
|
||||
mindmap: {
|
||||
padding: 15,
|
||||
},
|
||||
};
|
||||
|
||||
configApi.saveConfigFromInitialize(initConfig);
|
||||
configApi.addDirective(directive1);
|
||||
configApi.addDirective(directive2);
|
||||
|
||||
const userConfig = configApi.getUserDefinedConfig();
|
||||
expect(userConfig).toMatchInlineSnapshot(`
|
||||
{
|
||||
"flowchart": {
|
||||
"curve": "basis",
|
||||
"nodeSpacing": 100,
|
||||
"rankSpacing": 100,
|
||||
},
|
||||
"fontSize": 12,
|
||||
"mindmap": {
|
||||
"padding": 15,
|
||||
},
|
||||
"theme": "default",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should return independent copies (not references)', () => {
|
||||
const initConfig: MermaidConfig = { theme: 'dark', flowchart: { nodeSpacing: 50 } };
|
||||
configApi.saveConfigFromInitialize(initConfig);
|
||||
|
||||
const userConfig1 = configApi.getUserDefinedConfig();
|
||||
const userConfig2 = configApi.getUserDefinedConfig();
|
||||
|
||||
userConfig1.theme = 'neutral';
|
||||
userConfig1.flowchart!.nodeSpacing = 999;
|
||||
|
||||
expect(userConfig2).toMatchInlineSnapshot(`
|
||||
{
|
||||
"flowchart": {
|
||||
"nodeSpacing": 50,
|
||||
},
|
||||
"theme": "dark",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should handle edge cases with undefined values', () => {
|
||||
const initConfig: MermaidConfig = { theme: 'dark', layout: undefined };
|
||||
const directive: MermaidConfig = { fontSize: 14, fontFamily: undefined };
|
||||
|
||||
configApi.saveConfigFromInitialize(initConfig);
|
||||
configApi.addDirective(directive);
|
||||
|
||||
expect(configApi.getUserDefinedConfig()).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fontSize": 14,
|
||||
"layout": undefined,
|
||||
"theme": "dark",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should retain config from initialize after reset', () => {
|
||||
const initConfig: MermaidConfig = { theme: 'dark' };
|
||||
const directive: MermaidConfig = { layout: 'elk' };
|
||||
|
||||
configApi.saveConfigFromInitialize(initConfig);
|
||||
configApi.addDirective(directive);
|
||||
|
||||
expect(configApi.getUserDefinedConfig()).toMatchInlineSnapshot(`
|
||||
{
|
||||
"layout": "elk",
|
||||
"theme": "dark",
|
||||
}
|
||||
`);
|
||||
|
||||
configApi.reset();
|
||||
});
|
||||
});
|
||||
|
@@ -248,3 +248,17 @@ const checkConfig = (config: MermaidConfig) => {
|
||||
issueWarning('LAZY_LOAD_DEPRECATED');
|
||||
}
|
||||
};
|
||||
|
||||
export const getUserDefinedConfig = (): MermaidConfig => {
|
||||
let userConfig: MermaidConfig = {};
|
||||
|
||||
if (configFromInitialize) {
|
||||
userConfig = assignWithDepth(userConfig, configFromInitialize);
|
||||
}
|
||||
|
||||
for (const d of directives) {
|
||||
userConfig = assignWithDepth(userConfig, d);
|
||||
}
|
||||
|
||||
return userConfig;
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user