Compare commits

...

569 Commits

Author SHA1 Message Date
Knut Sveidqvist
820603e475 MC-2620 Cleanup 2025-02-11 11:04:55 +01:00
Knut Sveidqvist
4636305783 Using intersect function 2025-02-11 10:36:00 +01:00
Knut Sveidqvist
2247bc583f Fix for generateRoundedPath 2025-02-11 10:04:26 +01:00
Knut Sveidqvist
fa51a37d8c Merge in latest 2025-02-10 15:29:31 +01:00
Knut Sveidqvist
e6e88cef15 WIP Merge in latest 2025-02-10 14:44:54 +01:00
Knut Sveidqvist
2e47e17d28 Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2025-01-31 15:17:59 +01:00
Knut Sveidqvist
79218398ee Fix for lifelines color in default theme 2025-01-31 15:15:55 +01:00
Ashish Jain
01010465dd Merge pull request #34 from Mermaid-Chart/mc-2642-fix-for-class-diagram-markers
Mc 2642 fix for class diagram markers
2025-01-30 12:06:58 +01:00
Knut Sveidqvist
c3b78a37a6 MC-2642 Removing code that makes class diagram arrows go wrong 2025-01-29 16:54:44 +01:00
Ashish Jain
7e9a29f486 MC-2572 fix for class diagram broken edges 2025-01-29 12:03:29 +01:00
Ashish Jain
5d1c619ca5 Update alana version to 11.4.1-b.11 2025-01-28 13:16:40 +01:00
Ashish Jain
23c00bf7ca Merge pull request #33 from Mermaid-Chart/redux-dark-theme-update
updated redux-dark theme
2025-01-28 13:09:18 +01:00
omkarht
b3a2794f1f updated redux-dark theme 2025-01-28 17:17:27 +05:30
Ashish Jain
7513d0e39a Merge pull request #31 from Mermaid-Chart/set-default-font-family-to-arial
Set default font family to "Arial" for all themes
2025-01-28 12:39:35 +01:00
Saurabh Gore
571bbab859 Added "Recursive Variable" font for redux theme 2025-01-28 16:58:50 +05:30
Ashish Jain
88b28e8fc3 Merge pull request #32 from Mermaid-Chart/shape-theme-styling-issue-fix
fixed issues of  border radius and styling, label padding
2025-01-28 11:08:59 +01:00
Ashish Jain
579d1ee33c Merge from upstream mermaid OS develop 2025-01-28 10:56:26 +01:00
Saurabh Gore
13e3d7293e Remove "trebuchet ms", verdana from font family 2025-01-28 12:32:50 +05:30
omkarht
db2295db24 fixed issues of padding and border radius and border styling 2025-01-27 20:10:50 +05:30
Saurabh Gore
aa28880be7 Set default font family to arial for all themes 2025-01-27 19:24:29 +05:30
Ashish Jain
463d42b86d Merge pull request #30 from Mermaid-Chart/mc-2560-dotted-lines-neo
MC-2560 Reviving dotted lines for flowcharts
2025-01-24 15:59:47 +01:00
Knut Sveidqvist
ba0b945821 MC-2560 Reviving dotted lines for flowcharts 2025-01-24 15:49:11 +01:00
Ashish Jain
bf39ae7369 Merge pull request #29 from Mermaid-Chart/redux-theme
Updated html-label alignment for shapes
2025-01-24 15:17:45 +01:00
Ashish Jain
4911b63e44 Merge from upstream mermaid OS develop 2025-01-24 15:15:55 +01:00
omkarht
d52e3d1931 updated html-label alignment for shapes 2025-01-24 17:55:02 +05:30
Ashish Jain
0d308fdffe Merge from upstream mermaid OS develop 2025-01-24 12:47:42 +01:00
Ashish Jain
fb19255f10 Merge pull request #28 from Mermaid-Chart/animations-for-neo-look
#MC-2558 Handling animations for look neo
2025-01-24 12:26:05 +01:00
Ashish Jain
2ef6760cbc Increase size limit of diagrams 2025-01-24 12:18:49 +01:00
Ashish Jain
2f525434fd Merge pull request #27 from Mermaid-Chart/redux-theme
Resolved the issue for shapes  where the drop-shadow was being applied to themes other than Redux.
2025-01-24 12:14:49 +01:00
Knut Sveidqvist
49bdd11011 #MC-2558 Handling animations for look neo 2025-01-24 11:44:05 +01:00
omkarht
f785b47b1d Resolved the issue where the drop-shadow was being applied to themes other than Redux. 2025-01-24 15:20:38 +05:30
Ashish Jain
f7772b440d Merge pull request #25 from Mermaid-Chart/redux-theme
Redux theme
2025-01-23 14:41:45 +01:00
Ashish Jain
5bee403c33 Merge pull request #26 from Mermaid-Chart/2542-astar-exposing-intersection
MC-2542 exposing calcIntersect for use in A* Path finding
2025-01-23 14:32:40 +01:00
Knut Sveidqvist
d7535a9e4d MC-2542 Exposing calcIntersect function 2025-01-23 12:03:54 +01:00
Ashish Jain
fd8f95b628 Fix for default curve on flowchart edge 2025-01-23 11:36:06 +01:00
omkarht
78c63d3dc1 minor adjustment for double circle shape for drop-shadow 2025-01-23 15:17:34 +05:30
omkarht
9c89d3401a Merge branch 'neo-new-shapes' of https://github.com/Mermaid-Chart/alana-mermaid into redux-theme 2025-01-23 14:58:48 +05:30
omkarht
7fbc873fd0 updated drop shadow styling for small shapes 2025-01-23 12:27:47 +05:30
Ashish Jain
1089ec0963 Update alana version to 11.4.1-b.7 2025-01-22 23:56:34 +01:00
Ashish Jain
7df125ab59 Merge from upstream mermaid OS develop 2025-01-22 23:42:47 +01:00
omkarht
7425430b80 updated Label and Stroke color for redux theme 2025-01-22 19:30:12 +05:30
omkarht
2674bb80ab minor adjustment of padding for some shapes 2025-01-22 18:57:25 +05:30
omkarht
d4441e0200 updated padding for set of shapes [Left Curly Brace , Right Curly Brace, Curly Braces ] 2025-01-21 20:25:38 +05:30
omkarht
8bc898ddf1 shapes updated for drop shadow syling in redux theme 2025-01-21 20:01:37 +05:30
omkarht
7afd7a9729 Third Set of shapes updated for drop shadow syling in redux theme 2025-01-21 19:06:04 +05:30
omkarht
fa4d93483a Second Set of shapes updated for drop shadow syling in redux theme 2025-01-21 18:32:01 +05:30
omkarht
7d11a9578a First Set of shapes updated for drop shadow syling in redux theme 2025-01-21 16:08:11 +05:30
omkarht
5b6c5412cd Draft of fifth set of shapes [Lined Process, Delay, Multiprocess, Stored Data, Internal storage] 2025-01-17 13:06:53 +05:30
omkarht
51756edefc Draft of fourth set of shapes [ Document, Tagged Document, Paper Tape, Lined Document, Multiple Documents] 2025-01-16 21:21:31 +05:30
omkarht
4e685b74a7 Draft of third set of shapes [Divided Process, Manual Input,Subprocess, Horizontal Cylinder, Loop Limit] 2025-01-16 17:04:54 +05:30
Knut Sveidqvist
259af0fb77 Tmp removal of edge id handling 2025-01-16 11:08:15 +01:00
omkarht
6e3c37c98b Draft of second set of shapes [Card, Cylinder, Reversed Trapezoid, Odd, Tagged Rect] 2025-01-15 20:49:53 +05:30
Ashish Jain
9114f65dbe Update alana version to 11.4.1-b.4 2025-01-15 13:50:13 +01:00
Ashish Jain
6d73220348 Merge branch 'develop' of github.com:mermaid-js/mermaid into neo-new-shapes 2025-01-15 13:46:01 +01:00
Ashish Jain
e07fd6d98c Update alana version to 11.4.1-b.3 2025-01-15 13:09:21 +01:00
Ashish Jain
e6d45da81e Merge from upstream mermaid OS develop 2025-01-15 12:58:13 +01:00
Knut Sveidqvist
619a1df26e Updated to handle arrow heads differently between noe/classic 2025-01-10 11:44:14 +01:00
Knut Sveidqvist
7491c78c8c Tuning 2024-12-20 15:57:58 +01:00
Knut Sveidqvist
f0fdf91379 Adjustment for point 2024-12-20 15:36:16 +01:00
Knut Sveidqvist
0bf4aa3e82 Fix for arrow point 2024-12-20 15:28:08 +01:00
Knut Sveidqvist
9bf2bda539 Fix for arrow cross 2024-12-20 15:13:52 +01:00
Knut Sveidqvist
35aa869adc Draft of first set of shapes 2024-12-20 12:38:49 +01:00
Knut Sveidqvist
bf20e0615a Redux themes 2024-12-20 11:07:53 +01:00
Knut Sveidqvist
2352b422db #2028 Adding legacy code 2024-12-19 16:12:44 +01:00
Knut Sveidqvist
48a0d41a81 WIP 2024-12-13 10:15:00 +01:00
Knut Sveidqvist
e75260ac07 Initial skeleton setup 2024-12-13 09:12:39 +01:00
Knut Sveidqvist
b5ef6d2e23 Placement draft 2024-12-09 09:29:45 +01:00
Knut Sveidqvist
8277579259 #6097 Handling hourglass and lightningBolt 2024-12-03 10:49:43 +01:00
Knut Sveidqvist
8336d1cf2d #6097 Next shapes, learn-right and card 2024-12-03 10:23:02 +01:00
Knut Sveidqvist
3c93e4640a #6097 Next batch of shapes 2024-11-30 13:42:50 +01:00
Knut Sveidqvist
0c28593ea5 #6097 Implemented calcIntersect for the first round of shapes 2024-11-30 10:54:18 +01:00
Knut Sveidqvist
33d8b1a78d #6097 Added scaffolding for the new function in all shapes 2024-11-30 09:49:54 +01:00
Knut Sveidqvist
1e3ea13323 Fix for when last point is on the intersection 2024-11-29 09:07:47 +01:00
Knut Sveidqvist
4c8c48cde9 Generic solution for intersection of shapes with elk 2024-11-28 14:31:54 +01:00
Ashish Jain
38250af678 Merge from upstream mermaid to sync elk 0.1.7 2024-11-27 18:26:24 +01:00
Knut Sveidqvist
c8e50276e8 Added changeset 2024-11-27 15:54:05 +01:00
Knut Sveidqvist
1e6419a63f #6088 Updated offset calculations 2024-11-27 15:52:24 +01:00
Ashish Jain
de08b8244f Merge from upstream mermaid to sync 11.4.1 2024-11-27 12:25:04 +01:00
pbrolin47
41fdfd4c5c Merge pull request #21 from Mermaid-Chart/fix/classBox-neo-default
Fix invisible divider lines on classBox when using neo-default
2024-11-26 10:30:57 +01:00
yari-dewalt
81c2f0f7a9 Add 'neo-line' class to divider lines when appropriate 2024-11-22 08:29:52 -08:00
Ashish Jain
fee2ad565d chore: update alana version to 11.4.0-b.3 2024-11-21 14:49:58 +01:00
pbrolin47
725e25ad88 Merge pull request #20 from Mermaid-Chart/yari/classBox-neofication
"classBox" Shape Neofication and Resize Support
2024-11-21 11:01:44 +01:00
Ashish Jain
cb03af5214 Merge pull request #19 from Mermaid-Chart/fix-edge-flickring-on-delete-node
edge flickring fix while deleting nodes
2024-11-20 13:12:12 +01:00
Feroz Mujawar
4a812a964d fix scenario where two nodes have multiple edges 2024-11-19 12:10:02 +05:30
yari-dewalt
c4d06cd4fd Fix methodsAreaPlacement 2024-11-15 09:40:49 -08:00
Feroz Mujawar
ae2c533aca edge flickring fix while deleting nodes 2024-11-15 17:56:41 +05:30
yari-dewalt
1598ac713f Update testing html files 2024-11-14 10:35:03 -08:00
yari-dewalt
45d8a815dc Make node compatible with neo look and resizing 2024-11-14 10:33:24 -08:00
yari-dewalt
82b421696b Add support for positions 2024-11-14 10:32:44 -08:00
Ashish Jain
e98ab130cc Merge pull request #13 from Mermaid-Chart/fix-node-resize-intersection
fix intersection required object read from db while resizing node
2024-11-11 10:51:53 +01:00
Feroz Mujawar
ddeab2f705 lint fix 2024-11-11 14:34:54 +05:30
Feroz Mujawar
b08cd5dbba Merge branch 'neo-new-shapes' of https://github.com/Mermaid-Chart/alana-mermaid into fix-node-resize-intersection 2024-11-08 20:21:25 +05:30
Ashish Jain
e842cf582b Merge pull request #18 from Mermaid-Chart/MC-2265/fix-failing-e2e-shapes-test
MC-2265: Fix all failing E2E tests in Mermaid Alana
2024-11-08 15:28:03 +01:00
Alois Klink
6db6beca4b Merge pull request #16 from Mermaid-Chart/alana-11.4.0-megre
Merge mermaid 11.4.0 (develop) to neo-new-shapes in Alana
2024-11-08 14:04:38 +00:00
Alois Klink
35fea81209 Merge remote-tracking branch 'origin/alana-11.4.0-megre'; commit '1388662132cc829f9820c2e9970ae04e2dd90588' into MC-2265/fix-failing-e2e-shapes-test
Merges https://github.com/mermaid-js/mermaid/pull/6038 into
Mermaid Alana, fixing the broken E2E test.

See: https://github.com/mermaid-js/mermaid/pull/6038
See: https://mermaidchart.atlassian.net/browse/MC-2265
2024-11-08 22:29:56 +09:00
Ashish Jain
13d4a238d4 Merge pull request #15 from Mermaid-Chart/ci/disable-argos-in-ci
ci: disable Argos in CI
2024-11-07 14:14:45 +01:00
Alois Klink
c7171fa7b1 test(e2e): fix state diagram useMaxWidth tests
These tests assume that we're using `look: classic, theme: default`,
otherwise the widths are off.

However, since
3dc66a64c (MC-1730 Making neo the default theme, 2024-08-06),
`neo` is now the default look and theme in Alana Mermaid.

Fixes: 3dc66a64c7
2024-11-07 22:13:21 +09:00
Ashish Jain
861599245d Merge from upstream mermaid os 11.4.0 develop 2024-11-07 13:58:42 +01:00
Alois Klink
f550f17dc0 ci: disable Argos in CI
Argos only works in open-source repos, it doesn't work for this private
repo.
2024-11-07 21:49:01 +09:00
Alois Klink
191cd27b2b Merge pull request #14 from Mermaid-Chart/merge-fix/make-parse-error-on-invalid-shape
Merge https://github.com/mermaid-js/mermaid/pull/6002
2024-11-07 12:40:51 +00:00
Ashish Jain
4ad85974c6 Merge pull request #11 from Mermaid-Chart/merge-refactor/improving-rendering-shape-types
Merge https://github.com/mermaid-js/mermaid/pull/5974
2024-11-07 13:34:51 +01:00
Alois Klink
91ed9bb9c2 Merge commit '848be3d1297b833c4e8b2e25fabafec4d7c4db02' into merge-fix/make-parse-error-on-invalid-shape
Pulls PR https://github.com/mermaid-js/mermaid/pull/6002 into Alana.

Fixes a semantic merge conflict in
- `docs/config/setup/interfaces/mermaid.LayoutData.md`

See: https://github.com/mermaid-js/mermaid/pull/6002
2024-10-30 22:31:31 +09:00
Feroz Mujawar
18fd67300f fix intersection required object read from db while resizing node 2024-10-29 14:23:37 +05:30
Alois Klink
93239b5f34 Merge commit 'f8746bee0454b01378726d04f9c65bbc3974eb3a' into merge-refactor/improving-rendering-shape-types
See https://github.com/mermaid-js/mermaid/pull/5974

Conflicts:
	docs/config/setup/interfaces/mermaid.RenderResult.md
	packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts
2024-10-28 21:03:19 +09:00
Ashish Jain
807820f199 Update alana version to v11.3.0-b.4 2024-10-23 10:47:08 +02:00
Knut Sveidqvist
030aeb8c88 Merge pull request #12 from Mermaid-Chart/subgraph-NaN-fix
fix NaN error while adding subgraph
2024-10-22 16:58:18 +02:00
Feroz Mujawar
0d1212e463 fix NaN error while adding subgraph 2024-10-22 19:42:27 +05:30
Alois Klink
92d706f677 Merge commit '16a5fc05d65165f02966eb7f33154f136394a534' into merge-refactor/improving-rendering-shape-types
See https://github.com/mermaid-js/mermaid/pull/5974

There were a lot of merge conflicts!

Conflicts:
	packages/mermaid/src/rendering-util/rendering-elements/shapes/bowTieRect.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/card.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/crossedCircle.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/cylinder.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/drawRect.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/filledCircle.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/flippedTriangle.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/hourglass.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/lightningBolt.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/linedCylinder.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRect.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/shadedProcess.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/stateStart.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedRect.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedWaveEdgedRectangle.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/tiltedCylinder.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/triangle.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts
	packages/mermaid/src/rendering-util/rendering-elements/shapes/windowPane.ts
2024-10-18 02:49:26 +09:00
Ashish Jain
44e7e68e0b Update alana version to v11.3.0-b.3 2024-10-17 10:57:28 +02:00
Knut Sveidqvist
7d59a624d7 Updating fontsize to 14px 2024-10-16 18:25:27 +02:00
Ashish Jain
e2dc9e557c Update alana version to v11.3.0-b.2 2024-10-16 14:54:25 +02:00
Knut Sveidqvist
c7adb37a1f Fix for points to rearrange function for issue when using dagre 2024-10-16 13:52:06 +02:00
Ashish Jain
3b5ca1c638 Updated alana version to v11.3.0-b.1 2024-10-10 14:47:01 +02:00
omkarht
ff9fffef90 fixed resizing issue for iconCircle shape 2024-10-10 17:04:37 +05:30
saurabhg772244
71d6ded224 Fix path highlight for neo icons 2024-10-10 10:23:06 +05:30
Alois Klink
5ecd12de1c Merge pull request #10 from Mermaid-Chart/export-calcIntersections-and-calcNodeIntersections
Export `calcIntersections, calcNodeIntersections`
2024-10-09 22:25:58 +09:00
Alois Klink
ee4991f3e7 docs: regenerate docs 2024-10-09 21:55:04 +09:00
Ashish Jain
1028ca2ffc Merge branch 'develop' of github.com:mermaid-js/mermaid into neo-new-shapes 2024-10-09 13:24:46 +02:00
saurabhg772244
edce46b305 Merge branch 'neo-new-shapes' of mermaid.github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-10-09 16:51:50 +05:30
saurabhg772244
2509511135 Fixed neo look for color icons 2024-10-09 16:50:46 +05:30
Alois Klink
c76a513417 Merge branch 'neo-new-shapes' into export-calcIntersections-and-calcNodeIntersections 2024-10-09 19:31:52 +09:00
Sidharth Vinod
3968010d6b skip ts build in alana 2024-10-09 15:51:37 +05:30
Sidharth Vinod
122a44024c fix: change package json import path 2024-10-09 15:44:57 +05:30
Ashish Jain
654c00f88c Update alana version 2024-10-09 11:47:47 +02:00
Ashish Jain
c5acf870de Fix broken unit test 2024-10-09 11:34:14 +02:00
Ashish Jain
c73f8d0990 Merge from upstream mermaid os develop 2024-10-09 11:19:40 +02:00
omkarht
aa91874d9e resolved edge intersection calculation issue for square and rounded form of icon shape 2024-10-08 19:51:28 +05:30
omkarht
42fe55e2bc updated iconCircle shape 2024-10-07 11:53:24 +05:30
omkarht
3bcbad7fa1 upated iconRounded shape 2024-10-07 11:52:08 +05:30
Alois Klink
32ff6ec50f Export calcIntersections, calcNodeIntersections
Support doing:

```js
import { calcIntersections, calcNodeIntersections } from '@mermaid-chart/mermaid';
```

This means we can eventually stop doing `window.calcIntersections` and
`window.calcNodeIntersections`.
2024-10-04 19:57:35 +09:00
Ashish Jain
0198f0e798 Update alana version 2024-10-03 15:42:48 +02:00
Knut Sveidqvist
9aded56538 Updating image and diamond dimension handling 2024-10-03 15:32:07 +02:00
Knut Sveidqvist
b52b54086e Fixed sizing of diamond shape 2024-10-03 07:59:55 +02:00
Ashish Jain
31c01b1795 fix for label positioning for brace-l & brace-r shapes 2024-10-02 21:33:44 +02:00
Ashish Jain
90b200ed2e Merge commit 2024-10-02 21:22:58 +02:00
Ashish Jain
971a166073 fix for label positioning for brances shape 2024-10-02 21:22:01 +02:00
Knut Sveidqvist
4e25bf5db9 Adding handling of self-loops into update position 2024-10-02 21:06:01 +02:00
Ashish Jain
962fcb8ba8 fix for label positioning divided rect 2024-10-02 20:59:21 +02:00
Knut Sveidqvist
b3f2ba8bb8 Fix for intersecrtion calculations for start shape sm-circ 2024-10-02 20:36:10 +02:00
Ashish Jain
bda37516b8 fix for label positioning triangle and flipped triangle 2024-10-02 19:43:54 +02:00
Ashish Jain
0aebb941e9 Updated alana version 2024-10-02 14:45:35 +02:00
Knut Sveidqvist
36df0e340e Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-10-02 14:37:03 +02:00
Ashish Jain
1d8c4fd279 merge from upstream 2024-10-02 14:36:41 +02:00
Knut Sveidqvist
c1377f9075 Adjusted fixed height settings odd 2024-10-02 14:36:19 +02:00
Ashish Jain
c6fd62ab7d fix for min size for flag 2024-10-02 14:07:45 +02:00
Ashish Jain
2abdece0f2 fix for min size for tagged rect 2024-10-02 13:34:28 +02:00
Knut Sveidqvist
ed1427ed31 Adjusted fixed height settings tag-doc 2024-10-02 13:22:38 +02:00
Knut Sveidqvist
36f1dc8541 Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-10-02 09:47:22 +02:00
Knut Sveidqvist
7a7d161a61 Fix for tag-doc 2024-10-02 09:46:58 +02:00
Ashish Jain
a2d64a82c5 fix for min size for more shapes 2024-10-02 09:45:55 +02:00
Ashish Jain
f1674b8b04 fix for min size for more shapes 2024-10-01 23:45:32 +02:00
Ashish Jain
eb346e1c51 fix for min size for several shapes 2024-10-01 21:35:30 +02:00
Ashish Jain
d2dfb639c8 fix for min size for several shapes 2024-10-01 18:52:26 +02:00
Alois Klink
5363e9545e Merge 'aloisklink:fix/5904-ban-dompurify-3.1.7' into neo-new-shapes
This prevents DOMPurify 3.1.7 from being installed.
2024-10-02 00:27:19 +09:00
omkarht
42fd9836f0 updated curly-brace shapes 2024-10-01 18:56:29 +05:30
Knut Sveidqvist
bda3bfd2a7 test html file 2024-10-01 14:50:20 +02:00
Knut Sveidqvist
834fa07991 Updated shapes using the set width/height 2024-10-01 14:18:40 +02:00
Knut Sveidqvist
491aa7d9ff Mermaid version v11.2.0-b.12 2024-09-30 15:04:25 +02:00
Knut Sveidqvist
6cf07067e2 Default size for circle 2024-09-30 14:57:14 +02:00
Knut Sveidqvist
d0881534c1 Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-09-30 14:54:40 +02:00
Knut Sveidqvist
f10d148097 Adjusted min values 2024-09-30 14:53:33 +02:00
Per Brolin
f5545d094f Set a smaller default size for stateStart and stateEnd 2024-09-30 13:16:44 +02:00
Per Brolin
c36bdf12a0 Merge branch 'perb-fix-circles-resize' into neo-new-shapes 2024-09-30 10:58:54 +02:00
Per Brolin
92f67af6af Merge branch 'neo-new-shapes' into perb-fix-circles-resize 2024-09-30 10:56:08 +02:00
Per Brolin
d175e9a403 Fixed default size if not provided in height/width 2024-09-30 10:48:15 +02:00
Per Brolin
2ce57e4cf4 Fix default size if width/height not provided 2024-09-30 10:45:52 +02:00
Per Brolin
a7a9185222 Fix default size if not provided 2024-09-30 10:44:01 +02:00
Per Brolin
edc2ac7fea Fixed double circle 2024-09-30 10:35:13 +02:00
Per Brolin
221d59cbfc Fix problem with circle 2024-09-30 10:26:00 +02:00
Knut Sveidqvist
e8472c3647 Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-09-30 10:16:38 +02:00
Knut Sveidqvist
414f666417 Better handling of subgraphs without positions 2024-09-30 10:11:38 +02:00
Per Brolin
5ad1a6082b Merge branch 'neo-new-shapes' into perb-fix-circles-resize 2024-09-29 22:45:46 +02:00
Per Brolin
32d7f470dc fix remaining rendering of circles 2024-09-29 22:40:08 +02:00
Ashish Jain
9b269ecf3b fix for trapezoidal pentagon 2024-09-29 20:42:01 +02:00
Per Brolin
8fa8fd6abd WIP. Updated size-testet 2024-09-29 20:36:36 +02:00
omkarht
9957d3101f updated multiWaveEdgedRectangle shape 2024-09-28 23:52:00 +05:30
Ashish Jain
22982baf1a fix for flipped triangle 2024-09-28 12:35:44 +02:00
Ashish Jain
d3b51e2282 fix for triangle 2024-09-28 12:35:01 +02:00
Knut Sveidqvist
d9b2220085 Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-09-27 17:36:43 +02:00
Knut Sveidqvist
e2ecb8e180 TaggedWaveEdged Rect 2024-09-27 17:35:44 +02:00
Alois Klink
68ba79259a fix: fix sizing of bow-rect in fixed layout
OMG, I never want to hear 'sagitta', 'ellipse', and 'Elliptic integral'
again. This shape was painful to fix.
2024-09-28 00:20:14 +09:00
Knut Sveidqvist
0f7e14ba70 Update for stadium shape 2024-09-27 16:59:37 +02:00
Knut Sveidqvist
59f28810d5 lin-doc shape fixed 2024-09-27 16:26:44 +02:00
Knut Sveidqvist
00b32d07fe Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-09-27 16:15:06 +02:00
Knut Sveidqvist
bf57a283d3 Trapezoids and document 2024-09-27 16:14:28 +02:00
Alois Klink
ee2e6a2c2c fix: fix sizing of tag-rect in fixed layout 2024-09-27 23:05:40 +09:00
Alois Klink
9caa46cfd2 fix: fix sizing of st-rect in fixed layout 2024-09-27 23:05:40 +09:00
Alois Klink
2566f1cab8 fix: fix sizing of sl-rect in fixed layout 2024-09-27 23:05:40 +09:00
Alois Klink
aae4e6f048 fix: fix sizing of win-pane in fixed layout 2024-09-27 23:05:40 +09:00
Alois Klink
b32acb619c fix: fix sizing of div-rect in fixed layout 2024-09-27 23:05:40 +09:00
Alois Klink
1510939196 fix: fix sizing of lin-rect in fixed layout 2024-09-27 23:05:40 +09:00
Alois Klink
a8db94fd1a fix: fix sizing of notch-rect in fixed layout 2024-09-27 23:05:40 +09:00
Alois Klink
c72d774519 fix: fix sizing of fr-rect in fixed layout 2024-09-27 23:05:40 +09:00
Ashish Jain
437f2c0be2 fix for half-rounded-rectangle 2024-09-27 16:03:13 +02:00
omkarht
82e8eb97cc updated waveRectangle shape 2024-09-27 19:20:29 +05:30
Ashish Jain
c7a2023661 fix for curved trapezoid 2024-09-27 14:43:34 +02:00
Ashish Jain
0b0c0fc1f1 lin cyl 2024-09-27 14:13:54 +02:00
Ashish Jain
ba51f4ab38 fix cylr & h-cyl 2024-09-27 13:55:22 +02:00
Knut Sveidqvist
c3838305b3 Lean-left 2024-09-27 13:44:44 +02:00
Knut Sveidqvist
5b7dfbad94 Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-09-27 13:41:12 +02:00
Knut Sveidqvist
b47168b064 Lean-right and question 2024-09-27 13:40:32 +02:00
saurabhg772244
2c0d48eef5 updated shapes 2024-09-27 17:07:53 +05:30
Knut Sveidqvist
1ef4c42bcf Updating odd shape 2024-09-27 11:59:05 +02:00
saurabhg772244
9da6321c4b updated lightning bolt shape 2024-09-27 15:25:19 +05:30
Ashish Jain
b99e080337 suport dynamic resizing of rect shape 2024-09-27 10:24:29 +02:00
saurabhg772244
7a9ec739d9 fixed lightning bolt shape 2024-09-27 12:17:31 +05:30
Knut Sveidqvist
390025c085 Fix for sizing of Stadium 2024-09-26 19:55:32 +02:00
Knut Sveidqvist
e4abc39572 Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-09-26 19:51:21 +02:00
Knut Sveidqvist
b0abb44928 Fix for width calculations in Rect 2024-09-26 19:41:35 +02:00
Knut Sveidqvist
0afd83a0c3 Adding size-tester for checking size calculations with fixed sizes 2024-09-26 18:26:49 +02:00
Alois Klink
0a355968c4 fix(types): improve mermaid.parse types
It looks like
8873ffca1 (chore: Overload parse type to be more specific., 2023-12-08)
got overwritten in the merge from Mermaid v11.
2024-09-27 01:07:34 +09:00
Knut Sveidqvist
2a05b479ae Removing wrap 2024-09-26 16:21:28 +02:00
Knut Sveidqvist
9e3bd1fb19 Fix for text sizing calculations ans possibly insertion of a bug 2024-09-26 15:33:02 +02:00
Knut Sveidqvist
0ba4265bc3 Handle fixed size for hexagon 2024-09-26 13:20:44 +02:00
Knut Sveidqvist
a94ad012c4 Fix for resizing of circle 2024-09-26 13:13:37 +02:00
Ashish Jain
bcfc5e0ce4 update version to v11.2.0-b.8 2024-09-24 15:13:43 +02:00
Ashish Jain
210cd35422 Merge branch 'knsv/new-shapes' of github.com:mermaid-js/mermaid into neo-new-shapes 2024-09-24 15:11:43 +02:00
Ashish Jain
2aaf1b9619 update version to v11.2.0-b.7 2024-09-24 11:13:10 +02:00
Ashish Jain
e63f533f3c Merge branch 'knsv/new-shapes' of github.com:mermaid-js/mermaid into neo-new-shapes 2024-09-24 11:12:00 +02:00
saurabhg772244
3a3ea06413 fixed hover highlight for crossed circle multiRect and multiWavedEgeRect 2024-09-24 14:18:51 +05:30
saurabhg772244
5a1640ee34 updated neo look for shaded process and divided process 2024-09-24 13:46:25 +05:30
saurabhg772244
633328c9da fixed padding in neo look for icon square and rounded 2024-09-24 11:53:55 +05:30
Ashish Jain
51aba30620 update version to v11.2.0-b.6 2024-09-23 18:01:28 +02:00
Ashish Jain
f720f2cb13 Merge from Upstream new-shapes branch 2024-09-23 17:52:40 +02:00
saurabhg772244
02a03e3d60 fixed multirect for shadow 2024-09-23 19:54:11 +05:30
Knut Sveidqvist
97dec4e4cb Decreasing drop shadow for neo-dark 2024-09-23 15:10:42 +02:00
Knut Sveidqvist
bb755c6e99 Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-09-23 15:00:06 +02:00
Knut Sveidqvist
65d47dea24 Fix for issues with comment shapes in neo-dark 2024-09-23 14:57:18 +02:00
saurabhg772244
6934c3eb5a Updated padding for neo look 2024-09-23 17:08:17 +05:30
saurabhg772244
4d2ffc46d0 updated padding for curley brace shape 2024-09-23 16:46:44 +05:30
saurabhg772244
2f2fc1b4f1 updated window pane for new look 2024-09-23 15:48:46 +05:30
Knut Sveidqvist
7dcd2758b2 Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-09-23 10:23:54 +02:00
Knut Sveidqvist
1a974eeb39 Fix for state diagram curve 2024-09-23 10:19:55 +02:00
Ashish Jain
7272e7297c update version to v11.2.0-b.5 2024-09-23 10:05:07 +02:00
Ashish Jain
c94c3d7c86 Merge from Upstream new-shapes branch 2024-09-23 09:43:33 +02:00
Knut Sveidqvist
3fc723003c Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-09-20 15:10:43 +02:00
Knut Sveidqvist
6d64c75121 Fix for image 2024-09-20 15:09:29 +02:00
Ashish Jain
62bcfefa7c update version to v11.2.0-b.4 2024-09-20 13:59:00 +02:00
Ashish Jain
401590c010 Merge from Upstream new-shapes branch 2024-09-20 12:31:07 +02:00
saurabhg772244
b301138d93 neoify icon shape 2024-09-20 15:45:17 +05:30
Ashish Jain
cf53340672 fix lint issue 2024-09-20 11:07:33 +02:00
Ashish Jain
a07b61fdf1 Merge branch 'knsv/new-shapes' of github.com:mermaid-js/mermaid into neo-new-shapes 2024-09-20 10:59:25 +02:00
Knut Sveidqvist
e67894fbb3 Adding config for chose edge type and adding debug option for curves. Mermaid version 11.2.0-b.3 2024-09-19 14:54:58 +02:00
Knut Sveidqvist
fa638da9fc Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-09-19 14:28:38 +02:00
Knut Sveidqvist
b9ae52e1c2 Configurable debugging of edge points 2024-09-19 14:28:33 +02:00
Knut Sveidqvist
5348e74475 Handling of rounded paths 2024-09-19 14:01:17 +02:00
Ashish Jain
aa41c67266 Merge from upstream new-shapes branch 2024-09-19 13:28:34 +02:00
Knut Sveidqvist
6184510439 Mermaid version 11.2.0-a.10 2024-09-18 13:49:50 +02:00
Sidharth Vinod
faed69c86e chore: Bump versions 2024-09-17 21:35:26 +05:30
Sidharth Vinod
16a75de518 Merge branch 'knsv/new-shapes' into neo-new-shapes
* knsv/new-shapes:
  chore: changeset
  [autofix.ci] apply automated fixes
  test: fix gantt.spec.js type error
  test: await on `expect().resolves/rejects`
  build(types): disable preserveSymlinks in tsconfig
2024-09-17 21:02:04 +05:30
Ashish Jain
a23132e1f2 Merge from upstream new-shapes branch 2024-09-17 09:57:30 +02:00
Ashish Jain
2bc6ac4a76 fix prettier lint error 2024-09-17 08:41:34 +02:00
Ashish Jain
776cb92e3e fix unit test 2024-09-17 08:39:18 +02:00
Ashish Jain
2a7c3dc436 fix lint error for unused variables 2024-09-17 00:02:00 +02:00
Ashish Jain
032a8cbbee Merge pull request #8 from Mermaid-Chart/sidv/configReturn
fix: Change return type from parse
2024-09-16 23:43:28 +02:00
Ashish Jain
3d767cbc06 Merge branch 'neo-new-shapes' into sidv/configReturn 2024-09-16 23:37:14 +02:00
Knut Sveidqvist
eee669f1ee New mermaid version 11.1.0-b.12 2024-09-16 15:41:34 +02:00
Knut Sveidqvist
d85889c200 Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-09-16 15:38:29 +02:00
Knut Sveidqvist
ff3418c520 Adding intersection calculation for new nodes 2024-09-16 15:38:05 +02:00
Sidharth Vinod
7b0b548d05 Merge branch 'neo-new-shapes' into sidv/configReturn
* neo-new-shapes:
  update type check for getTypeFromVertex
  [autofix.ci] apply automated fixes
  fixed build error
  Updated readme for renderOptions parameter and renamed to use kabab case
  Updated icon shape for background colour and icon colour
  Moving case check to parsing
  Adding case check
  Updated shape aliases
  Updated type
  Throwing error for invalid shape
  Updated insertNode to pass optional config
  Fix for amp and adjusted tests
  WIP
  Removing the ending @ sign in the shape data
2024-09-16 18:35:08 +05:30
Ashish Jain
48791aac13 Merge from upstream newShapes branch 2024-09-16 14:59:46 +02:00
Sidharth Vinod
c8381d0fca fix: ParseResult type 2024-09-16 15:59:03 +05:30
Sidharth Vinod
2bb1a2c4f2 Merge branch 'neo-new-shapes' into sidv/configReturn
* neo-new-shapes:
  Mermaid version b.10
  Fix for issue with incorrect calculations of which edge a line intersects with
2024-09-16 14:46:46 +05:30
Knut Sveidqvist
3730f1afbb Mermaid version b.10 2024-09-16 10:04:10 +02:00
Sidharth Vinod
e0c2b832a9 Bump version 2024-09-13 23:18:20 +05:30
Sidharth Vinod
4cbb0004be fix: Remove changes to parse 2024-09-13 20:54:59 +05:30
Sidharth Vinod
19e79fda73 feat: Add title to parseResult 2024-09-13 19:49:24 +05:30
Knut Sveidqvist
05989d06fa Fix for issue with incorrect calculations of which edge a line intersects with 2024-09-13 08:37:07 +02:00
Sidharth Vinod
71889fd135 chore: Remove type from ParseResult 2024-09-13 12:00:05 +05:30
Sidharth Vinod
eca19efa32 Merge branch 'knsv/new-shapes' of https://github.com/mermaid-js/mermaid into sidv/configReturn
* 'knsv/new-shapes' of https://github.com/mermaid-js/mermaid:
2024-09-12 15:47:20 +05:30
Sidharth Vinod
4841b7d3d9 Merge branch 'develop' of https://github.com/mermaid-js/mermaid into sidv/configReturn
* 'develop' of https://github.com/mermaid-js/mermaid:
  #5787 Fix for issue with labels in firefox
2024-09-12 15:41:31 +05:30
Sidharth Vinod
dd01f3d52c revert import changes 2024-09-12 15:33:03 +05:30
Sidharth Vinod
dc642fb5bc Build docs 2024-09-12 15:23:11 +05:30
Sidharth Vinod
ef428dc555 Merge branch 'neo-new-shapes' of https://github.com/Mermaid-Chart/alana-mermaid into sidv/configReturn
* 'neo-new-shapes' of https://github.com/Mermaid-Chart/alana-mermaid: (45 commits)
  updated styles, testcases and fixed html labels for image shape
  MC-1733 Reset layout
  updated ImageSqaure shape
  updated styles
  updated pos changes
  fixed html labels for icon shape
  updated test cases
  Added rounded icon shape
  Updated circle icon
  updated image shape
  Updated labels for shapes
  updated icon square and icon
  MC-1733 Reset layout
  Updated logic for vertex label
  Updated test cases
  Update .changeset/rude-meals-invite.md
  changesets
  added neo-fication and shape-resize for linedCylinder shape
  added neo-fication for curvedTrapezoid shape
  Version Packages
  ...
2024-09-12 15:19:21 +05:30
Ashish Jain
d964893a5d Merge branch 'knsv/new-shapes' of github.com:mermaid-js/mermaid into neo-new-shapes 2024-09-12 10:48:18 +02:00
Ashish Jain
7ef296a9cf Merge from upstream newShapes branch 2024-09-11 14:41:52 +02:00
Knut Sveidqvist
acd66a5eb4 MC-1733 Reset layout 2024-09-11 13:57:32 +02:00
Sidharth Vinod
db6242590e Fix result type 2024-09-10 18:41:59 +05:30
Knut Sveidqvist
1efc794056 Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes 2024-09-10 13:43:38 +02:00
Knut Sveidqvist
d1395d05e2 MC-1733 Reset layout 2024-09-10 13:39:13 +02:00
Sidharth Vinod
888f668f5e chore: Fix imports 2024-09-10 17:08:29 +05:30
Sidharth Vinod
d0caa2b3e0 test: Fix parse tests 2024-09-10 17:08:15 +05:30
Ashish Jain
900c8a4209 Replace with relative path 2024-09-10 13:19:32 +02:00
Sidharth Vinod
5ab955b6b3 fix: Change return type from parse 2024-09-10 14:18:34 +05:30
omkarht
fd8542080d added neo-fication and shape-resize for linedCylinder shape 2024-09-09 19:10:03 +05:30
omkarht
040a989c3d added neo-fication for curvedTrapezoid shape 2024-09-09 18:54:43 +05:30
Sidharth Vinod
638be1992d Merge remote-tracking branch 'upstream/develop' into neo-new-shapes
* upstream/develop: (27 commits)
  [autofix.ci] apply automated fixes
  fix: Return type, make config non optional
  [autofix.ci] apply automated fixes
  Create red-beans-cross.md
  chore(deps): update dependency eslint-plugin-jsdoc to v50
  remove tsconfig compiler option paths
  linting
  replace mermaid/dist with relative paths
  chore: add git command and set safe dir
  chore: Fix check
  feat: Preview release
  feat: Return parsed config from `mermaid.parse`
  Version Packages
  Adding changeset
  Cleanup of test-file
  Updated cypress test for self-loops
  Fix for issues with self loops
  docs: Fix SMW link
  add blog post - architecture diagrams
  more , linting
  ...
2024-09-09 18:30:31 +05:30
Ashish Jain
13b96ad6c0 Merge branch 'knsv/new-shapes' of github.com:mermaid-js/mermaid into neo-new-shapes 2024-09-06 14:59:14 +02:00
Ashish Jain
f9d5128c91 Merge from upsteam, updated to version v11.1.0-b6 2024-09-05 13:42:04 +02:00
Ashish Jain
35f2e4f5fa Merge branch 'knsv/new-shapes' of github.com:mermaid-js/mermaid into neo-new-shapes 2024-09-05 13:40:07 +02:00
Ashish Jain
2244c1fa87 Merge from upsteam, updated to version v11.1.0-b5 2024-09-05 12:04:41 +02:00
Per Brolin
791b442089 fix-architecture-styling 2024-09-05 12:02:21 +02:00
Ashish Jain
e180ad0666 Merge branch 'knsv/new-shapes' of github.com:mermaid-js/mermaid into neo-new-shapes 2024-09-05 12:01:39 +02:00
Ashish Jain
1b67997da2 Merge from upsteam, updated to version v11.1.0-b4 2024-09-05 10:58:04 +02:00
Per Brolin
c18ee0381c Merge branch 'pebr-fix-arch-neo-reboot' into neo-new-shapes 2024-09-04 16:56:44 +02:00
Per Brolin
8d91622235 MC-2029: Fix styling for neo-dark 2024-09-04 16:24:19 +02:00
Per Brolin
19f98c1c72 MC-2029: Corrected dashed border 2024-09-04 16:17:01 +02:00
Per Brolin
afe32f2f8c MC-2029: Updated lockfile 2024-09-04 16:10:01 +02:00
Per Brolin
b214f30e96 MC-2029: Added styling 2024-09-04 16:08:47 +02:00
Per Brolin
415eb26335 MC-2029: Added demo page with architecture neo 2024-09-04 15:54:39 +02:00
Ashish Jain
8fd57abc81 Fix support for fixed layout for flowchart 2024-09-04 13:38:10 +02:00
omkarht
165a4f6825 updated trapezoidalPentagon shape 2024-09-04 13:58:45 +05:30
omkarht
1e7a5a4408 updated taggedWaveEdgedRectangle shape 2024-09-04 13:17:31 +05:30
omkarht
acb569193b updated waveEdgedRectangle shape 2024-09-04 11:53:42 +05:30
saurabhg772244
1b6d627bd3 updated styles for shapes 2024-09-03 18:29:42 +05:30
omkarht
ea987171b2 implemented neo-fication and shape resize for waveRectangle, taggedWaveEdgedRectangle, multiWaveEdgedRectangle shapes 2024-09-03 18:01:15 +05:30
Ashish Jain
b84617c915 Updated versions 2024-09-03 12:26:52 +02:00
Ashish Jain
0e2753814a merge commit 2024-09-03 11:57:12 +02:00
Ashish Jain
11bb1a4a17 Merge from upstream 2024-09-03 11:55:46 +02:00
omkarht
46aba3dfe9 implemented neo-fication and shape resize for flippedTriangle, taggedRect, triangle waveEdgedRectangle shapes 2024-09-03 15:21:57 +05:30
omkarht
0764dca3ce implemented neo-fication for bowTieRect shape 2024-09-03 13:33:09 +05:30
omkarht
83493f26b7 implemented neo-fication for multiRect, slopedRect, waveEdgedRectangle shapes 2024-09-02 21:00:12 +05:30
Knut Sveidqvist
5673dd7ebc Mermaid version 11.0.2-b.9 2024-09-02 11:51:03 +02:00
Knut Sveidqvist
fabecc4abd Incorrect mermaid version, was already published by someone else 2024-09-02 11:50:13 +02:00
Knut Sveidqvist
7603a51302 MC-1801 Fix for issue with markers using fixed layout 2024-09-02 11:46:32 +02:00
Knut Sveidqvist
dedf2d25e3 MC-1801 Fix for link id issue and intersection calculations 2024-08-29 11:58:30 +02:00
Ashish Jain
b011b628ad Updated package versions 2024-08-29 10:00:08 +02:00
Ashish Jain
db3541047a Merge branch 'knsv/new-shapes' of github.com:mermaid-js/mermaid into neo-new-shapes 2024-08-28 14:36:44 +02:00
Ashish Jain
bd5a9cc21e Merge from Upstream 2024-08-28 14:33:13 +02:00
Knut Sveidqvist
62f887b3c3 Alana version 11.0.2-b.5, Updated calcIntersections allowing mouse coordinates 2024-08-28 11:45:20 +02:00
Knut Sveidqvist
9c2d7b1dad Fix for fixed position 2024-08-27 16:11:16 +02:00
Ashish Jain
fd47e4eb2f fix fixed layout 2024-08-27 15:54:31 +02:00
Ashish Jain
327ea728ac fix fixed layout 2024-08-27 15:30:37 +02:00
Ashish Jain
96974c9007 updated version 2024-08-27 15:14:27 +02:00
Ashish Jain
c00707165f fix lint & typescript issues 2024-08-27 15:13:39 +02:00
Ashish Jain
dc2ecc9f19 fix mermiad version placeholder 2024-08-27 15:12:49 +02:00
Ashish Jain
41b8a1e6f4 Merge from Upstream & fix version 2024-08-27 14:41:03 +02:00
Ashish Jain
d421cfb1fd Merge branch 'knsv/new-shapes' of github.com:mermaid-js/mermaid into neo-new-shapes 2024-08-27 14:22:19 +02:00
Ashish Jain
ba978e86ae Merge from Upstream 2024-08-27 14:21:46 +02:00
Knut Sveidqvist
1483e9245e Merge remote-tracking branch 'os_repo/knsv/new-shapes' into neo-new-shapes 2024-08-26 12:17:37 +02:00
Ashish Jain
6a53d87742 Merge from upstream new-shapes branch 2024-08-21 17:24:47 +02:00
Ashish Jain
a7b771a622 Merge from upstream new-shapes branch 2024-08-21 16:27:55 +02:00
Knut Sveidqvist
c6acf84e43 Mermaid version 11.0.0-b.74, handling of default positions in subgraphs for fixed layout 2024-08-20 13:35:40 +02:00
Knut Sveidqvist
e9b91485f4 Updated intersection calculations , Mermaid version 11.0.0-b.73 2024-08-15 18:26:23 +02:00
Knut Sveidqvist
a0a03b932d Updated intersection calculations , Mermaid version 11.0.0-b.73 2024-08-15 18:25:24 +02:00
Knut Sveidqvist
9acf55069c Mermaid version 11.0.0-b.67, handling of fixed layout without defined positions 2024-08-15 14:11:02 +02:00
Ashish Jain
4878cb9356 Export types & version upgrade 2024-08-15 12:46:48 +02:00
Ashish Jain
b6725eae94 Export types & version upgrade 2024-08-15 12:08:02 +02:00
Knut Sveidqvist
2415e8652a Updated intersection calculations , Mermaid version 11.0.0-b.64 2024-08-15 12:05:59 +02:00
Knut Sveidqvist
941a1723d8 Mermaid version 11.0.0-b.63 2024-08-14 14:05:57 +02:00
Knut Sveidqvist
43b038547e Merge remote-tracking branch 'os_repo/develop' into alanaV11 2024-08-13 14:08:55 +02:00
Ashish Jain
8a22615dbf Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-08-09 15:47:22 +02:00
Ashish Jain
947b59d392 merge from upstream mermaid 2024-08-09 15:18:41 +02:00
Ashish Jain
58694ecd29 merge from upstream mermaid 2024-08-09 15:17:25 +02:00
Knut Sveidqvist
8e3cb5fb1b Fix for fixed layout, mermaid v11.0.0-b.61 2024-08-08 09:49:16 +02:00
Knut Sveidqvist
534cf32231 Removing console.logs 2024-08-06 15:14:34 +02:00
Knut Sveidqvist
41484b2272 MC-1730 Fix for subroutine shape 2024-08-06 15:03:19 +02:00
Knut Sveidqvist
992095d0f8 Mermaid version 11.0.0-b.58 2024-08-06 14:29:52 +02:00
Knut Sveidqvist
3321f6472f Adding subroutine fill 2024-08-06 14:29:33 +02:00
Ashish Jain
2ee94eb9ae updated package version 2024-08-06 12:02:31 +02:00
Ashish Jain
2114e3e0fc fix NaN values in viewBox for sequence diagram 2024-08-06 10:55:30 +02:00
Knut Sveidqvist
87011c6ab4 MC-1730 Better elk publish 2024-08-06 10:33:33 +02:00
Knut Sveidqvist
3dc66a64c7 MC-1730 Making neo the default theme 2024-08-06 10:27:06 +02:00
Alois Klink
64cc767dd5 fix: add mc mermaid theme to types 2024-08-05 23:08:59 +09:00
Knut Sveidqvist
04a704c068 MC-1730 Fix for id handling in elk 2024-08-05 16:02:50 +02:00
Ashish Jain
cef45c023f fix edge id for elk 2024-08-05 15:48:53 +02:00
Knut Sveidqvist
61100d81b1 Updated version of elk renderer 0.0.15 2024-08-05 13:12:29 +02:00
Knut Sveidqvist
29a9c16ab6 Updated mermaid version to 11.0.0-b.55 2024-08-05 13:11:28 +02:00
Knut Sveidqvist
ba20d6c627 #5237 Fix for issue with edge routing for elk layout 2024-08-05 13:09:13 +02:00
Knut Sveidqvist
ca7ddbfe8a MC-1730 Fixed border-color for statediagram notes 2024-08-05 11:04:25 +02:00
Knut Sveidqvist
c33aa50916 Mermaid version 11.0.0-b.54 2024-08-02 18:01:19 +02:00
Steph
b153203338 Merge branch 'alanaV11' of https://github.com/Mermaid-Chart/alana-mermaid into alanaV11 2024-08-02 08:23:41 -07:00
Steph
f834dba3ff update gradient colors for neo-dark 2024-08-02 08:21:58 -07:00
Knut Sveidqvist
640c502346 MC-1730 Fix for flowchart arrows without arrowheads 2024-08-02 17:16:40 +02:00
Knut Sveidqvist
34ecbba275 Mermaid version 11.0.0-b.53 with neo colors for gantt chart 2024-08-02 12:18:28 +02:00
Knut Sveidqvist
930a33d351 Updated version 11.0.0-b.52 2024-08-02 12:11:12 +02:00
Knut Sveidqvist
fda930ec64 Merge branch 'alanaV11' of github.com:Mermaid-Chart/alana-mermaid into alanaV11 2024-08-02 11:48:14 +02:00
Knut Sveidqvist
f93e331be5 Updating the color scales for the neo theme 2024-08-02 11:47:57 +02:00
Ashish Jain
7396c485db fix for parser module for pie 2024-08-02 11:21:38 +02:00
Knut Sveidqvist
85e7af566e Mermaid v11.0.0-b.50 2024-08-01 16:12:11 +02:00
Knut Sveidqvist
36c90cf90e #5237 Fix for issue with styling rectWithTitle 2024-08-01 16:09:32 +02:00
Knut Sveidqvist
6346e29f6a 5237 Fix for edges to diamond shapes and new mermaid version 2024-07-31 15:07:28 +02:00
Knut Sveidqvist
04b31b8672 MC-1730 Adding mc theme 2024-07-22 12:52:22 +02:00
Knut Sveidqvist
2eddee90e0 MC-1730 Adding mc theme 2024-07-22 12:52:16 +02:00
Knut Sveidqvist
63f9043d40 Mermaid version 11.0.0-b.46 2024-07-22 11:06:31 +02:00
Knut Sveidqvist
e019a60bdd MC-1730 Adding neo and neo-dark to valid themes 2024-07-22 11:03:09 +02:00
Knut Sveidqvist
0a4ace5128 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-07-22 11:01:51 +02:00
Knut Sveidqvist
7156735394 MC-1730 Fix for failing unit-test 2024-07-22 10:12:03 +02:00
Ashish Jain
64a5c11318 Fix broken unit test 2024-07-19 15:40:20 +02:00
Ashish Jain
05abfd132b lint fixes 2024-07-19 14:55:51 +02:00
Knut Sveidqvist
31370ed240 Merge branch 'alanaV11' of github.com:Mermaid-Chart/alana-mermaid into alanaV11 2024-07-19 14:30:01 +02:00
Knut Sveidqvist
e6722bc7f6 MC-1730 Lint fixes 2024-07-19 14:29:52 +02:00
Ashish Jain
3f0e18cb94 fix lint issue 2024-07-19 14:27:00 +02:00
Knut Sveidqvist
cc0dcd68f8 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-07-19 14:15:08 +02:00
Ashish Jain
9a2865c64a Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-07-15 11:50:37 +02:00
Ashish Jain
2c25197d65 MC-1730 Fix flowchart subgraph id isue 2024-07-10 15:29:26 +02:00
Ashish Jain
2d6a5ade9d MC-1730 Updated version 2024-07-10 14:53:11 +02:00
Ashish Jain
7ad9b84319 Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-07-10 14:45:02 +02:00
Ashish Jain
ff0322a5dd MC-1730 Updated version 2024-07-10 11:28:26 +02:00
Ashish Jain
9aa01d8a39 Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-07-10 11:27:21 +02:00
Ashish Jain
04ad2ae3dd MC-1730 Fix for data-et as cluster 2024-07-08 16:07:59 +02:00
Ashish Jain
d7497c179e MC-1730 Fix for data-et as cluster 2024-07-08 14:52:07 +02:00
Ashish Jain
df7de0e796 MC-1730 Merge from mermaid v11 2024-07-08 14:10:59 +02:00
Ashish Jain
55d4e83732 Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-07-04 22:12:00 +02:00
Ashish Jain
9e01da0d04 Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-07-04 21:45:32 +02:00
Knut Sveidqvist
476b7a12d7 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-07-03 15:47:46 +02:00
Knut Sveidqvist
40063d0982 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-07-03 14:52:56 +02:00
Knut Sveidqvist
25703ea8c1 Latest merge from mermaid b38 2024-07-03 14:06:54 +02:00
Knut Sveidqvist
87f333b0d5 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-07-03 14:00:08 +02:00
Knut Sveidqvist
ae046ff4dd Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-07-02 11:06:36 +02:00
Knut Sveidqvist
5f35f6c37d Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-07-02 10:41:56 +02:00
Knut Sveidqvist
3b7fb45ee6 MC-1799 Reviving the fixed layout 2024-07-01 13:39:11 +02:00
Ashish Jain
0ab49e1e3d Update version 2024-07-01 11:26:30 +02:00
Ashish Jain
442d5077d3 Merge from mermaid 2024-07-01 11:16:19 +02:00
Knut Sveidqvist
834afef2c0 MC-1730 Styling of the subprocess class with neo 2024-06-30 12:24:07 +02:00
Knut Sveidqvist
0b4dbeda8c Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-29 21:23:56 +02:00
Knut Sveidqvist
84fc95d7cf Divider layout fix 2024-06-28 17:50:24 +02:00
Knut Sveidqvist
bbe71f5367 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-28 15:40:46 +02:00
Knut Sveidqvist
9528b5f391 Merge from mermaid 2024-06-28 09:00:33 +02:00
Ashish Jain
23180d35ac MC-1730 Adding data-id, data-node, and data-et attr for dividers. Also, updated version 2024-06-27 16:05:15 +02:00
Ashish Jain
35ae14681e MC-1730 Updated version 2024-06-26 15:50:59 +02:00
Ashish Jain
9bfd6517ac Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-06-26 15:48:07 +02:00
Knut Sveidqvist
bebc2ba4e9 Merge branch 'alanaV11' of github.com:Mermaid-Chart/alana-mermaid into alanaV11 2024-06-26 09:22:47 +02:00
Knut Sveidqvist
93b4699189 Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-06-26 09:22:13 +02:00
Ashish Jain
5feb3beb8b Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-06-24 12:10:01 +02:00
Ashish Jain
11c3ef1c8b MC-1730 Updated version 2024-06-24 11:36:38 +02:00
Ashish Jain
f967ee935d Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-06-24 11:34:41 +02:00
Knut Sveidqvist
20a273a853 Merge branches 'alanaV11' and 'alanaV11' of github.com:Mermaid-Chart/alana-mermaid into alanaV11 2024-06-24 11:31:35 +02:00
Knut Sveidqvist
e451f83b08 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-24 11:30:30 +02:00
Ashish Jain
948781cbce MC-1730 Updated version 2024-06-20 15:45:42 +02:00
Ashish Jain
cdf75558b5 Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-06-20 15:43:44 +02:00
Knut Sveidqvist
f8c16f577b New build b.26 2024-06-20 15:31:39 +02:00
Knut Sveidqvist
823035abd8 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-20 15:29:36 +02:00
Ashish Jain
82f1344af6 MC-1730 Updated version 2024-06-20 14:14:32 +02:00
Ashish Jain
ab626fac9e Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-06-20 14:13:52 +02:00
Ashish Jain
4fa080df9d #5237 Add data-id attr for edge 2024-06-20 13:31:44 +02:00
Ashish Jain
c5186b0df2 Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-06-20 13:30:58 +02:00
Knut Sveidqvist
b9dda2797a Merge branch 'alanaV11' of github.com:Mermaid-Chart/alana-mermaid into alanaV11 2024-06-19 13:56:59 +02:00
Knut Sveidqvist
d898cc6a67 New build numbers 2024-06-19 13:43:28 +02:00
Knut Sveidqvist
01b7074203 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-19 13:38:38 +02:00
Per Brolin
c4685fb0ff Merge branch 'pebr/neo-style' into alanaV11 2024-06-19 11:53:14 +02:00
Per Brolin
96c8e544ec MC-1765: Added specific end-state class 2024-06-19 11:52:28 +02:00
Knut Sveidqvist
c406e6cefe Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-19 10:57:31 +02:00
Per Brolin
31936cf6cb MC-1765: Merge from AlanaV11 to pebr/neo-style 2024-06-19 09:53:06 +02:00
Per Brolin
d6e8419360 MC-1765: Removed curvature from inner rect composite 2024-06-19 09:49:04 +02:00
Knut Sveidqvist
37e43c0be4 Merge branch 'alanaV11' of github.com:Mermaid-Chart/alana-mermaid into alanaV11 2024-06-18 16:02:02 +02:00
Knut Sveidqvist
9510b2e138 MC-1730 Selector for gradients 2024-06-18 16:00:57 +02:00
Knut Sveidqvist
4bd6e3a70c MC-1730 Selector for gradients 2024-06-18 15:58:50 +02:00
Ashish Jain
54a6a996aa Fix database shapes neo look for flowchart 2024-06-18 15:58:09 +02:00
Per Brolin
ba6f2b26a6 Merge branch 'alanaV11' into pebr/neo-style 2024-06-18 15:43:20 +02:00
Per Brolin
9cac8cc472 MC-1765: WIP Added some flow chart shapes 2024-06-18 15:42:29 +02:00
Ashish Jain
416a9fa069 Fix different shapes neo look for flowchart 2024-06-18 15:35:16 +02:00
Ashish Jain
1c1dbe0eb7 Fix different shapes neo look for flowchart 2024-06-18 15:33:28 +02:00
Knut Sveidqvist
0520226b5b Merge branch 'alanaV11' of github.com:Mermaid-Chart/alana-mermaid into alanaV11 2024-06-18 15:11:35 +02:00
Knut Sveidqvist
e7d9e1b223 MC-1730 Putting shadows back 2024-06-18 15:10:47 +02:00
Per Brolin
d5735fd721 Merge branch 'pebr/neo-style' into alanaV11 2024-06-18 15:09:36 +02:00
Per Brolin
1e47c8a70e Merge branch 'alanaV11' into pebr/neo-style 2024-06-18 15:05:46 +02:00
Knut Sveidqvist
838b2ce391 Merge branch 'alanaV11' of github.com:Mermaid-Chart/alana-mermaid into alanaV11 2024-06-18 15:04:10 +02:00
Knut Sveidqvist
9b310df58a MC-1730 Updated gradient settings 2024-06-18 15:00:51 +02:00
Per Brolin
7f8ca0c77e Merge branch 'alanaV11' into pebr/neo-style 2024-06-18 14:59:02 +02:00
Per Brolin
444bad5f20 MC-1765 WIP Added test-grid for states 2024-06-18 14:58:34 +02:00
Ashish Jain
0d630862ee Fix odd (asymmetrical) shape & hexagon shape neo look for flowchart 2024-06-18 14:51:14 +02:00
Knut Sveidqvist
7297b9bc42 MC-1730 Updated gradient settings 2024-06-18 14:42:00 +02:00
Ashish Jain
92e6f52168 Fix double circle shape neo look for flowchart 2024-06-18 14:31:17 +02:00
Ashish Jain
2007cab5ee Fix circle shape neo look for flowchart 2024-06-18 14:16:28 +02:00
Knut Sveidqvist
86d75373ca MC-1730 Neo look for subgraphs 2024-06-18 14:15:53 +02:00
Ashish Jain
41a5f2dacd Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-06-18 14:07:16 +02:00
Knut Sveidqvist
f431020b6b MC-1730 Cleanup of gradients, adding neo-dark 2024-06-18 14:04:41 +02:00
Ashish Jain
736181bf3d fix neo look for stadium shape in flowchart 2024-06-18 13:59:17 +02:00
Per Brolin
ace39a2154 MC-1765: WIP Test Grid of shapes and themes 2024-06-18 13:30:31 +02:00
Per Brolin
959d8cb606 Merge branch 'pebr/neo-style' into alanaV11 2024-06-18 13:03:08 +02:00
Per Brolin
f96c6462de Merge branch 'alanaV11' into pebr/neo-style 2024-06-18 13:02:22 +02:00
Per Brolin
74ef8b53f1 MC-1765: WIP. Gradiant 2024-06-18 13:00:37 +02:00
Per Brolin
3780659337 MC-1765: WIP Support for Gradient-theme 2024-06-18 12:59:04 +02:00
Knut Sveidqvist
ea87596363 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-18 12:40:09 +02:00
Knut Sveidqvist
caff6662a0 MC-1730 Repplying rectClass efter merge conflict 2024-06-18 11:26:11 +02:00
Knut Sveidqvist
ce7e738843 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-18 11:19:56 +02:00
Per Brolin
9591159901 Corrected end-state for neo 2024-06-17 20:40:48 +02:00
Per Brolin
ced34394bb Updated label padding, and set rx, ry for neo-style class 2024-06-17 20:15:04 +02:00
Per Brolin
1cdafaac80 Merge branch 'alanaV11' into pebr/neo-style 2024-06-17 15:40:02 +02:00
Per Brolin
0fc2f3c85f Corrected minor typo 2024-06-17 15:39:00 +02:00
Knut Sveidqvist
ea0b4f3e95 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-17 14:44:57 +02:00
Per Brolin
8aefe293b0 MC-1765: Merge branch 'alanaV11' into pebr/neo-style 2024-06-17 08:53:17 +02:00
Per Brolin
757f5c395c MC-1765: Added drop-shadow for circles and polygons 2024-06-17 08:47:44 +02:00
Knut Sveidqvist
0a08cfd573 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-14 17:40:42 +02:00
Per Brolin
582035ef9b MC-1765: Added column for classic, default as comparison 2024-06-14 15:29:08 +02:00
Per Brolin
2f6d728123 Added attribute data-look to composite and nested states 2024-06-14 14:45:24 +02:00
Knut Sveidqvist
61b8c9b639 New mermaid version bete-20 2024-06-14 14:24:04 +02:00
Knut Sveidqvist
729cbec78d Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-14 14:18:06 +02:00
Per Brolin
ccdaa6333e Renamed test file and added new file to check neo and themes 2024-06-14 13:49:14 +02:00
Per Brolin
bbb118547e Removed temp override of look 2024-06-14 11:40:58 +02:00
Per Brolin
04159a8427 MC-1765: Removed hard-coded setting of look in render-utils 2024-06-14 11:36:34 +02:00
Knut Sveidqvist
4838023a0b MC-1730 Latest fixes from mermaid 2024-06-13 17:02:49 +02:00
Per Brolin
d70ffe93bb MCC-1765: Added styling of neo class and removed override in drawRect 2024-06-13 13:44:34 +02:00
Per Brolin
10e9a30769 Merge branch 'pebr/neo-style' into alanaV11 2024-06-13 13:34:05 +02:00
Ashish Jain
9d590bc587 updated version 2024-06-13 11:10:37 +02:00
Ashish Jain
69871c94c4 updated version 7 data-node true attr 2024-06-13 11:09:59 +02:00
Per Brolin
2c2b86dc9d Merge branch 'alanaV11' into pebr/neo-style 2024-06-13 10:11:15 +02:00
Per Brolin
8b278d483a MC-1765: Added todo-list to keep track 2024-06-13 10:10:37 +02:00
Knut Sveidqvist
9fbad9c9c1 MC-1730 Applying look to nodes 2024-06-13 10:01:20 +02:00
Per Brolin
2130839770 Merge branch 'alanaV11' into pebr/neo-style 2024-06-13 08:36:34 +02:00
Per Brolin
f22f319599 Fixed so padding of Node labels is working for neo and other theme 2024-06-13 08:35:26 +02:00
Per Brolin
f17d788ac8 Set a less prominent color in nested composite state and added demo page of styling 2024-06-12 14:54:03 +02:00
Ashish Jain
67cf57ae4f added logging for config 2024-06-12 14:45:54 +02:00
Ashish Jain
8ff462f01c Updated version 2024-06-12 14:34:14 +02:00
Ashish Jain
183b83b1ff Adding data-et and data-id for cluster in rendering-util 2024-06-12 14:33:22 +02:00
Knut Sveidqvist
0dd6db67e8 Fix for paddings in square rect 2024-06-12 13:49:37 +02:00
Per Brolin
7ff731163f Added rendering of neo-style in state-refactor 2024-06-12 13:31:01 +02:00
Knut Sveidqvist
7c851bc849 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-12 12:38:29 +02:00
Knut Sveidqvist
2df39e3658 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-12 11:46:46 +02:00
Knut Sveidqvist
29e73ed2dc Verisons 2024-06-12 11:46:32 +02:00
Ashish Jain
32f6c9eefa Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-06-12 11:37:13 +02:00
Per Brolin
3af2c29d8f Clean-up to avoid code duplication. Corrected neo-optins according to stephs design 2024-06-12 10:38:54 +02:00
Per Brolin
6842b316ec Correccted bug with innen height in composite diags 2024-06-12 08:49:58 +02:00
Per Brolin
979a9b08f9 Merge branch 'alanaV11' into pebr/neo-style 2024-06-11 16:14:34 +02:00
Per Brolin
d3ec33cfe7 Set line-height of label so bbox is height of line 2024-06-11 16:13:55 +02:00
Knut Sveidqvist
80295c3cc2 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-11 15:04:06 +02:00
Knut Sveidqvist
a4777bd44d Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-11 14:48:03 +02:00
Per Brolin
efe8573c06 Merge branch 'pebr/neo-style' into alanaV11 2024-06-11 13:44:41 +02:00
Per Brolin
a9aa8b7f1a Commit prior work by knsv 2024-06-11 13:43:54 +02:00
Knut Sveidqvist
58f5f4a35d Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-11 13:28:47 +02:00
Per Brolin
6dcdec0126 Removed border for neo as UX-design by steph 2024-06-10 15:26:20 +02:00
Per Brolin
4eea7ff5da Corrected options rx,ry for roundedRect when not neo 2024-06-10 14:15:43 +02:00
Per Brolin
15d35387a0 Removed slick 2024-06-10 13:56:21 +02:00
Per Brolin
8b7001b8e3 Removed useRough in favor of node.look 2024-06-10 13:55:08 +02:00
Per Brolin
4fe7e062b5 Removed some hard coding form review 2024-06-10 12:02:15 +02:00
Per Brolin
b41431b378 Merge branch 'alanaV11' into pebr/neo-style 2024-06-10 10:24:43 +02:00
Knut Sveidqvist
1bf4cca3a3 Local package for layout 2024-06-09 19:01:34 +02:00
Knut Sveidqvist
edd4457154 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-09 18:28:31 +02:00
Per Brolin
36de3dca62 Added fix for handling y-alignment of labels of different font-sizes for composite states 2024-06-09 17:33:58 +02:00
Per Brolin
51da34b831 Replaced hard-coded node.look by checking diagram config and cleanup styling a bit 2024-06-07 15:14:26 +02:00
Knut Sveidqvist
59130ca107 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-06-04 16:42:10 +02:00
Per Brolin
544d17db95 WIP:Updated edge-arrow and correct styling pars from figma 2024-06-04 15:11:13 +02:00
Per Brolin
ce6aa48511 WIP: Changed drop-shadow and background of states and composite-states 2024-06-04 12:17:27 +02:00
Per Brolin
03ba130764 Made drop-shadow less prominent and set new arrow-type 2024-06-03 15:42:49 +02:00
Knut Sveidqvist
a36f1d1656 #MC-1733 Support for subgraphs in fixed layout 2024-06-03 15:02:05 +02:00
Ashish Jain
8d1539f2d7 Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-06-03 14:43:40 +02:00
Ashish Jain
0393e4018b Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-06-03 14:23:37 +02:00
Per Brolin
195ea6405a Merge branch 'alanaV11' into pebr/neo-style 2024-06-03 13:33:26 +02:00
Per Brolin
9fca13ca19 Added first initial styling for neo for state diagrams 2024-06-03 13:10:05 +02:00
Knut Sveidqvist
b9b678a429 #MC-1733 New fixed layout-algorithm for mermaid, nodes and edges 2024-05-31 16:20:24 +02:00
Knut Sveidqvist
648d804d03 Merge remote-tracking branch 'os_repo/5237-unified-layout-common-renderer' into alanaV11 2024-05-31 13:26:10 +02:00
Knut Sveidqvist
344f7a9060 #5237 Bugfixes 2024-05-31 11:29:27 +02:00
Knut Sveidqvist
520e06d2eb #5237 State diagram bugfixes 2024-05-31 10:52:23 +02:00
Knut Sveidqvist
8bb340182c Decorating edges and nodes 2024-05-29 15:58:50 +02:00
Knut Sveidqvist
a62239d9bc Merge branch 'alanaV11' of github.com:Mermaid-Chart/alana-mermaid into alanaV11 2024-05-29 15:56:54 +02:00
Knut Sveidqvist
b390fbe1cb Decorating edges and nodes 2024-05-29 15:56:43 +02:00
Ashish Jain
e416ac1c0b refactor: added look to nodes and edges 2024-05-29 14:27:48 +02:00
Knut Sveidqvist
4538f5b8c6 pnpm-lock fix 2024-05-28 10:39:22 +02:00
Knut Sveidqvist
b2ccec0efa Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-05-28 10:30:04 +02:00
knsv
e52ad8edc2 Update docs 2024-05-24 15:06:03 +00:00
Knut Sveidqvist
be604703aa Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-05-24 17:01:29 +02:00
Knut Sveidqvist
2ba93dd30d Merge branch '5237-unified-layout-common-renderer' of github.com:mermaid-js/mermaid into alanaV11 2024-05-24 17:00:31 +02:00
sidharthv96
a54e1a854b Update docs 2024-05-24 11:09:36 +00:00
Sidharth Vinod
ea56c64c7b Merge branch 'develop' into alana
* develop: (355 commits)
  Create FUNDING.json
  Update pnpm to v9
  Tiny improvements to Diagram Syntax sidebar
  chore(deps): update all patch dependencies
  chore: address @Yokozuna59's code reviews
  refactor: remove non-null assertion operator
  chore: remove unrefSubSchemas
  chore: Build config types before building types
  chore: Ignore `vite.config.ts.timestamp-`
  chore(deps): update all patch dependencies
  Update docs
  chore: Update ordering
  Added to "others" section on integration with Astro
  feat: use standard edge id function for class,flow,state diagram
  feat(utils): create a standard edge id function
  chore: update browsers list
  chore: rm autocompleted import
  trigger e2e again
  feat(state): add from, to in edge
  fix: classrenderer v2 using in op
  ...
2024-05-24 16:33:41 +05:30
Knut Sveidqvist
1089c4029c Merge branch 'master' of github.com:mermaid-js/mermaid into develop 2024-05-24 08:33:22 +02:00
Knut Sveidqvist
bca86cce52 Merge branch 'master' of github.com:mermaid-js/mermaid into develop 2024-05-14 13:09:24 +02:00
Knut Sveidqvist
d14a399801 10.9.0-b.5 2024-03-18 10:41:33 +01:00
Knut Sveidqvist
949a06b00f Adding the missing id prefix 2024-03-18 10:40:57 +01:00
Knut Sveidqvist
0b88e0a8a9 Adding missing id 2024-03-15 15:19:04 +01:00
Knut Sveidqvist
ec4f0120ef Adding missing id 2024-03-14 16:01:46 +01:00
Knut Sveidqvist
51b1216a46 Merge branch 'develop' of github.com:Mermaid-Chart/alana-mermaid into develop 2024-03-14 15:49:29 +01:00
Knut Sveidqvist
f353f3b28c Updated changes for 10.9.0-b.2 2024-03-14 15:49:10 +01:00
knsv
f0f1bec9ce Update docs 2024-03-06 10:14:35 +00:00
Knut Sveidqvist
f5bd82461e MC-1278 version 10.9.0-b.1 2024-03-06 11:10:03 +01:00
Knut Sveidqvist
b5f70cd45e MC-1278 Merging mermaid 10.9 2024-03-06 10:37:53 +01:00
Knut Sveidqvist
c2b640aa86 Updated changes for b.8 2024-03-01 18:03:00 +01:00
Knut Sveidqvist
f5bf2563cf Removing tagging from sequence diagram footer 2024-02-28 17:59:03 +01:00
Knut Sveidqvist
26c7ee15e9 MC-1278 Removing tagging of footer participants 2024-02-28 15:06:53 +01:00
Knut Sveidqvist
8f7fd8329d MC-1278 Adding additional data to messages 2024-02-21 11:34:01 +01:00
knsv
a41488a849 Update docs 2024-02-16 11:15:25 +00:00
Knut Sveidqvist
762daac854 MC-1278 Making adding data-et and data-id to life-lines and actors 2024-02-16 12:10:12 +01:00
Knut Sveidqvist
f1e5bd37ae Merge branch 'release/10.8.0' of github.com:mermaid-js/mermaid into develop 2024-02-02 11:11:46 +01:00
Knut Sveidqvist
ae307831eb Merge from release/10.8.0 2024-02-02 09:55:30 +01:00
Knut Sveidqvist
976a39ea54 Merge branch 'perf/add-dompurify-hooks-once-only' into develop 2024-01-25 18:25:10 +01:00
Alois Klink
0ff611b729 perf: prevent adding multiple DOMPurify hooks
Currently, everytime `removeScript()` is called, the same DOMPurify
hooks are getting added again and again.
2024-01-25 16:48:17 +00:00
Knut Sveidqvist
6c2ded389f Merge branch 'master' of github.com:mermaid-js/mermaid into develop 2024-01-16 10:13:15 +01:00
Knut Sveidqvist
5b3b73ba49 Support for ids on edges 2023-12-08 17:38:49 +01:00
Knut Sveidqvist
ce4318a419 POC Changes 2023-11-13 15:38:03 +01:00
194 changed files with 27510 additions and 4488 deletions

View File

@@ -0,0 +1,5 @@
---
'@mermaid-js/layout-elk': patch
---
fix: Updated offset calculations for diamond shape when handling intersections

View File

@@ -47,6 +47,7 @@ mdbook
Mermerd
mkdocs
Nextra
NODECOUNT
nodenext
npmjs
pageview
@@ -58,6 +59,7 @@ presetAttributify
pyplot
redmine
rehype
RIGHTDOWN
roughjs
rscratch
shiki
@@ -67,6 +69,7 @@ sphinxcontrib
ssim
stylis
Swimm
topdown
tsbuildinfo
tseslint
Tuleap

View File

@@ -39,6 +39,7 @@ jobs:
pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage
- name: Verify out-of-tree build with TypeScript
if: ${{ github.repository == 'mermaid-js/mermaid' }}
run: |
pnpm test:check:tsc

24
.vscode/launch.json vendored
View File

@@ -12,18 +12,18 @@
"args": ["run", "${relativeFile}"],
"smartStep": true,
"console": "integratedTerminal"
},
{
"name": "Docs generation",
"type": "node",
"request": "launch",
"args": ["scripts/docs.cli.mts"],
// we'll need to change this to --import in Node.JS v20.6.0 and up
"runtimeArgs": ["--loader", "tsx/esm"],
"cwd": "${workspaceRoot}/packages/mermaid",
"skipFiles": ["<node_internals>/**", "**/node_modules/**"],
"smartStep": true,
"internalConsoleOptions": "openOnSessionStart"
}
// {
// "name": "Docs generation",
// "type": "node",
// "request": "launch",
// "args": ["scripts/docs.cli.mts"],
// // we'll need to change this to --import in Node.JS v20.6.0 and up
// "runtimeArgs": ["--loader", "tsx/esm"],
// "cwd": "${workspaceRoot}/packages/mermaid",
// "skipFiles": ["<node_internals>/**", "**/node_modules/**"],
// "smartStep": true,
// "internalConsoleOptions": "openOnSessionStart"
// }
]
}

9
Pulling-from-remote.md Normal file
View File

@@ -0,0 +1,9 @@
Pulling from remote repo
```
git remote add os_repo git@github.com:mermaid-js/mermaid.git
git pull os_repo main
git pull os_repo
git pull os_repo master
git pull os_repo 5237-unified-layout-common-renderer
```

View File

@@ -23,7 +23,11 @@ export default eyesPlugin(
});
// copy any needed variables from process.env to config.env
config.env.useAppli = process.env.USE_APPLI ? true : false;
config.env.useArgos = !!process.env.CI && !!process.env.ARGOS_TOKEN;
// only use Argos on CI in the mermaid-js/mermaid repository
config.env.useArgos =
!!process.env.CI &&
process.env.GITHUB_REPOSITORY === 'mermaid-js/mermaid' &&
!!process.env.ARGOS_TOKEN;
if (config.env.useArgos) {
registerArgosTask(on, config, {

View File

@@ -460,7 +460,7 @@ stateDiagram-v2
[*] --> State1
State1 --> [*]
`,
{ state: { useMaxWidth: true } }
{ state: { useMaxWidth: true }, look: 'classic' }
);
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
@@ -482,7 +482,7 @@ stateDiagram-v2
[*] --> State1
State1 --> [*]
`,
{ state: { useMaxWidth: false } }
{ state: { useMaxWidth: false }, look: 'classic' }
);
cy.get('svg').should((svg) => {
// const height = parseFloat(svg.attr('height'));

View File

@@ -338,7 +338,7 @@ describe('State diagram', () => {
[*] --> State1
State1 --> [*]
`,
{ state: { useMaxWidth: true } }
{ state: { useMaxWidth: true }, look: 'classic', theme: 'default' }
);
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
@@ -361,7 +361,7 @@ describe('State diagram', () => {
[*] --> State1
State1 --> [*]
`,
{ state: { useMaxWidth: false } }
{ state: { useMaxWidth: false }, look: 'classic', theme: 'default' }
);
cy.get('svg').should((svg) => {
// const height = parseFloat(svg.attr('height'));

221
cypress/platform/ash.html Normal file
View File

@@ -0,0 +1,221 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&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=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
body {
/* background: rgb(221, 208, 208); */
/* background: #333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 {
color: grey;
}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
/* background-color: #efefef;
background-image: radial-gradient(#fff 51%, transparent 91%),
radial-gradient(#fff 51%, transparent 91%);
background-size: 20px 20px;
background-position:
0 0,
10px 10px;
background-repeat: repeat; */
}
.malware {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
/* tspan {
font-size: 6px !important;
} */
</style>
</head>
<body>
<pre id="diagram" class="mermaid">
flowchart
node
rounded(rounded)
id1([This is the text in the box])
id2((circle))
id3(((double circle)))
id4>Asymetrical]
id5{This is the text in the box}
id6{{This is the text in the box}}
id7[/This is the text in the box/]
id8[\This is the text in the box\]
A[/Christmas\]
B[\Christmas/]
sub[[subroutine]]
db[(Database)]
</pre
>
<pre id="diagram" class="mermaid">
---
config:
theme: default
look: classic
---
flowchart
node
rounded(rounded)
id1([This is the text in the box])
id2((circle))
id3(((double circle)))
id4>Asymetrical]
id5{This is the text in the box}
id6{{This is the text in the box}}
id7[/This is the text in the box/]
id8[\This is the text in the box\]
B[/Christmas\]
sub[[subroutine]]
db[(Database)]
</pre
>
<pre id="diagram" class="mermaid">
stateDiagram
[*] --> Active
Active --> Inactive
Inactive --> Active
Active --> [*]
</pre>
<pre id="diagram" class="mermaid2">
flowchart
a_a(Aftonbladet) --> b_b[gorilla]:::apa --> c_c{chimp}:::apa -->a_a
a_a --> c --> d_d --> c_c
classDef apa fill:#f9f,stroke:#333,stroke-width:4px;
class a_a apa;
click a_a "http://www.aftonbladet.se" "bookmark"
click c_c callback "new tooltip"
</pre
>
<pre id="diagram2" class="mermaid2">
flowchart LR
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
</pre>
<pre id="diagram3" class="mermaid2">
flowchart LR
A:::foo & B:::bar --> C:::foobar
classDef foo stroke:#f00
classDef bar stroke:#0f0
classDef ash color:red
class C ash
style C stroke:#00f, fill:black
</pre>
<pre id="diagram4" class="mermaid2">
stateDiagram
A:::foo
B:::bar --> C:::foobar
classDef foo stroke:#f00
classDef bar stroke:#0f0
style C stroke:#00f, fill:black, color:white
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err);
};
window.callback = function () {
alert('A callback was triggered');
};
mermaid.initialize({
theme: 'neo',
look: 'neo',
// handdrawnSeed: 12,
// look: 'handdrawn',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre',
// layout: 'elk',
// layout: 'fixed',
// htmlLabels: false,
flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
// fontFamily: 'courier',
fontFamily: 'arial',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
fontSize: 12,
logLevel: 0,
securityLevel: 'loose',
});
function callback() {
alert('It worked');
}
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
</script>
</body>
</html>

View File

@@ -0,0 +1,164 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&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=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
body {
/* background: rgb(221, 208, 208); */
background: #333;
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 {
color: grey;
}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
/* background-color: #efefef;
background-image: radial-gradient(#fff 51%, transparent 91%),
radial-gradient(#fff 51%, transparent 91%);
background-size: 20px 20px;
background-position:
0 0,
10px 10px;
background-repeat: repeat; */
}
.malware {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
/* tspan {
font-size: 6px !important;
} */
</style>
</head>
<body>
<pre id="diagram" class="mermaid">
flowchart
A --> B & C
subgraph apa
D --> E
end
</pre
>
<pre id="diagram2" class="mermaid2">
flowchart LR
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
</pre>
<pre id="diagram3" class="mermaid2">
flowchart LR
A:::foo & B:::bar --> C:::foobar
classDef foo stroke:#f00
classDef bar stroke:#0f0
classDef ash color:red
class C ash
style C stroke:#00f, fill:black
</pre>
<pre id="diagram4" class="mermaid2">
stateDiagram
A:::foo
B:::bar --> C:::foobar
classDef foo stroke:#f00
classDef bar stroke:#0f0
style C stroke:#00f, fill:black, color:white
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err);
};
window.callback = function () {
alert('A callback was triggered');
};
mermaid.initialize({
theme: 'neo-dark',
// handdrawnSeed: 12,
look: 'neo',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre',
// layout: 'elk',
// layout: 'fixed',
// htmlLabels: false,
flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
// fontFamily: 'courier',
fontFamily: 'arial',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
fontSize: 12,
logLevel: 0,
securityLevel: 'loose',
});
function callback() {
alert('It worked');
}
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
</script>
</body>
</html>

View File

@@ -0,0 +1,206 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&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=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
body {
/* background: rgb(221, 208, 208); */
/* background: #333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 {
color: grey;
}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
/* background-color: #efefef;
background-image: radial-gradient(#fff 51%, transparent 91%),
radial-gradient(#fff 51%, transparent 91%);
background-size: 20px 20px;
background-position:
0 0,
10px 10px;
background-repeat: repeat; */
}
.malware {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
/* tspan {
font-size: 6px !important;
} */
</style>
</head>
<body>
<pre id="diagram" class="mermaid"></pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err);
};
mermaid.initialize({
startOnLoad: false,
// look: 'handdrawn',
// layout: 'elk',
fontFamily: 'Kalam',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
flowchart: {
// curve: 'cardinal',
// edgeDebug: true,
},
logLevel: 0,
});
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
let code = `---
config:
state:
curve: line
---
stateDiagram
S:S
T:T
U:U
state Z {
state X {
Y:Ypsilon
}
}
A
S --> T: angrepp
T --> U
T --> V
C
D
E
`;
code = `
flowchart TB
n3["Untitled Node"] --> n5["Untitled Node"] & n6["Untitled Node"] & n7["Untitled Node"] & n8["Untitled Node"] & n9["Untitled Node"]
`;
let positions = {
nodes: {
S: { x: 0, y: 0 },
T: { x: 100, y: 100, width: 100, height: 100 },
U: { x: 250, y: 260 },
V: { x: 300, y: 120 },
Z: { x: 300, y: 10, width: 160, height: 100 },
X: { x: 300, y: 20, width: 80, height: 60 },
Y: { x: 300, y: 30, width: 50, height: 20 },
A: { x: 300, y: 75, width: 20, height: 20 },
},
edges: {
edge0: {
points: [
{ x: 0, y: 0 },
{ x: 50, y: 0 },
{ x: 100, y: 100 },
],
},
edge1: {
// points: [
// { x: 100, y: 100 },
// { x: 200, y: 200 },
// ],
points: [
{ x: 100, y: 100 },
{ x: 150, y: 120 },
{ x: 190.19453144073486, y: 120 },
{ x: 190.19453144073486, y: 152.1556251525879 },
{ x: 250, y: 152.1556251525879 },
{ x: 250, y: 160 },
],
},
edge2: {
points: [
{ x: 100, y: 100 },
{ x: 175, y: 80 },
{ x: 200, y: 120 },
{ x: 300, y: 100 },
],
},
},
};
positions = JSON.parse(
'{"nodes":{"n3":{"x":360.885009765625,"y":7.677405834197998,"width":120.59375,"height":45.00000762939453},"n5":{"x":546.1309814453125,"y":190.24496459960938,"width":120.59375,"height":45},"n6":{"x":694.6719360351562,"y":167.00001525878906,"width":120.59375,"height":45},"n7":{"x":72.29684925079346,"y":167.00001525878906,"width":120.59370994567871,"height":45},"n8":{"x":250.27700805664062,"y":183.1090545654297,"width":120.59375,"height":45},"n9":{"x":393.2580871582031,"y":197.45834350585938,"width":120.59375,"height":45}},"edges":{"L_n3_n5_0":{"points":[{"x":383.71510673157036,"y":30.177409648895264},{"x":383.71510673157036,"y":98.96118712425232},{"x":523.300888350029,"y":98.96118712425232},{"x":523.300888350029,"y":167.74496459960938}],"start":"n3","end":"n5"},"L_n3_n6_1":{"points":[{"x":408.02337350122014,"y":30.177409648895264},{"x":408.02337350122014,"y":87.33871245384216},{"x":647.533580291497,"y":87.33871245384216},{"x":647.533580291497,"y":144.50001525878906}],"start":"n3","end":"n6"},"L_n3_n7_2":{"points":[{"x":320.12974762228504,"y":30.177409648895264},{"x":270.12974762228504,"y":87.33871245384216},{"x":113.05210448440184,"y":87.33871245384216},{"x":113.05210448440184,"y":144.50001525878906}],"start":"n3","end":"n7"},"L_n3_n8_3":{"points":[{"x":346.6989693425486,"y":30.177409648895264},{"x":346.6989693425486,"y":95.39323210716248},{"x":264.4630460745863,"y":95.39323210716248},{"x":264.4630460745863,"y":160.6090545654297}],"start":"n3","end":"n8"},"L_n3_n9_4":{"points":[{"x":364.7230894682698,"y":30.177409648895264},{"x":364.7230894682698,"y":102.56787657737732},{"x":389.42000810627434,"y":102.56787657737732},{"x":389.42000810627434,"y":174.95834350585938}],"start":"n3","end":"n9"}}}'
);
// console.log('positions:', positions);
const { svg } = await mermaid.render('the-id-of-the-svg', code, undefined, positions);
// if (window?.calcIntersections2) {
// const int = await calcIntersections2(
// { id: 'a', shape: 'rect', x: 100, y: 100, width: 100, height: 100 },
// { id: 'a', shape: 'rect', x: 300, y: 100, width: 100, height: 100 }
// );
// console.log('Intersections', int);
// } else {
// console.error('calcIntersections not found');
// }
// console.log(JSON.stringify(positions));
const elem = document.querySelector('#diagram');
elem.innerHTML = svg;
</script>
</body>
</html>

View File

@@ -0,0 +1,272 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&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=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Recursive:wght@300..1000&display=swap"
rel="stylesheet"
/>
<style>
.recursive-500 {
font-family: 'Recursive', 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; */
/* font-family: 'Arial'; */
font-family: 'Recursive', serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
font-variation-settings:
'slnt' 0,
'CASL' 0,
'CRSV' 0.5,
'MONO' 0;
/* color: white; */
/* font-size: 18px !important; */
}
.gridify.tiny {
background-image: linear-gradient(
transparent 11px,
rgba(220, 220, 200, 0.8) 12px,
transparent 12px
),
linear-gradient(90deg, transparent 11px, rgba(220, 220, 200, 0.8) 12px, transparent 12px);
background-size:
100% 12px,
12px 100%;
}
.gridify.dots {
background-image: radial-gradient(
circle at center,
rgba(220, 220, 200, 0.8) 1px,
transparent 1px
);
background-size: 24px 24px;
}
h1 {
color: grey;
}
.mermaid2 {
display: none;
}
.mermaid svg {
font-size: 16px !important;
font-family: 'Recursive', serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
font-variation-settings:
'slnt' 0,
'CASL' 0,
'CRSV' 0.5,
'MONO' 0;
}
pre {
width: 100%;
/*box-shadow: 4px 4px 0px 0px #0000000F;*/
}
</style>
</head>
<body class="gridify dots">
<p class="mb-20">Test Diagram</p>
<div class="w-full h-64">
<pre id="diagram4" class="mermaid">
---
config:
theme: neo
layout: dagre
---
flowchart TD
A{"Diamond"} --- n1["Rectangle"] & n2["Rounded"] & n3(["Stadium"])
n1 --x n4["Rounded"]
n2 --o n5["Hexagon"]
n3 --> n6["Parallelogram"]
n5 o--o n7["Trapezoid"]
n4 x--x n8["Lean Right"]
n6 <--> n9(("Circle"))
n8 --> n10["Rose"]
n7 --> n11["Pine"]
n9 --> n12["Peach"]
n2@{ shape: rounded}
n4@{ shape: rounded}
n5@{ shape: hex}
n6@{ shape: lean-l}
n7@{ shape: trap-b}
n8@{ shape: lean-r}
n10:::Rose
n11:::Pine
n12:::Peach
classDef Rose stroke-width:1px, stroke-dasharray:none, stroke:#FF5978, fill:#FFDFE5, color:#8E2236
classDef Pine stroke-width:1px, stroke-dasharray:none, stroke:#254336, fill:#27654A, color:#FFFFFF
classDef Peach stroke-width:1px, stroke-dasharray:none, stroke:#FBB35A, fill:#FFEFDB, color:#8F632D
n10 --x End
n11 --x End
n12 --x End
</pre
>
<pre id="diagram4" class="mermaid">
---
config:
look: classic
theme: forest
layout: dagre
---
flowchart TD
A{"Diamond"} --- n1["Rectangle"] & n2["Rounded"] & n3(["Stadium"])
n1 --x n4["Rounded"]
n2 --o n5["Hexagon"]
n3 --> n6["Parallelogram"]
n5 o--o n7["Trapezoid"]
n4 x--x n8["Lean Right"]
n6 <--> n9(("Circle"))
n8 --> n10["Rose"]
n7 --> n11["Pine"]
n9 --> n12["Peach"]
n2@{ shape: rounded}
n4@{ shape: rounded}
n5@{ shape: hex}
n6@{ shape: lean-l}
n7@{ shape: trap-b}
n8@{ shape: lean-r}
n10:::Rose
n11:::Pine
n12:::Peach
classDef Rose stroke-width:1px, stroke-dasharray:none, stroke:#FF5978, fill:#FFDFE5, color:#8E2236
classDef Pine stroke-width:1px, stroke-dasharray:none, stroke:#254336, fill:#27654A, color:#FFFFFF
classDef Peach stroke-width:1px, stroke-dasharray:none, stroke:#FBB35A, fill:#FFEFDB, color:#8F632D
n10 --x End
n11 --x End
n12 --x End
</pre
>
</div>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
const staticBellIconPack = {
prefix: 'fa6-regular',
icons: {
bell: {
body: '<path fill="currentColor" d="M224 0c-17.7 0-32 14.3-32 32v19.2C119 66 64 130.6 64 208v25.4c0 45.4-15.5 89.5-43.8 124.9L5.3 377c-5.8 7.2-6.9 17.1-2.9 25.4S14.8 416 24 416h400c9.2 0 17.6-5.3 21.6-13.6s2.9-18.2-2.9-25.4l-14.9-18.6c-28.3-35.5-43.8-79.6-43.8-125V208c0-77.4-55-142-128-156.8V32c0-17.7-14.3-32-32-32m0 96c61.9 0 112 50.1 112 112v25.4c0 47.9 13.9 94.6 39.7 134.6H72.3c25.8-40 39.7-86.7 39.7-134.6V208c0-61.9 50.1-112 112-112m64 352H160c0 17 6.7 33.3 18.7 45.3S207 512 224 512s33.3-6.7 45.3-18.7S288 465 288 448"/>',
width: 448,
},
},
width: 512,
height: 512,
};
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos@1/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () => staticBellIconPack,
},
]);
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err);
};
window.callback = function () {
alert('A callback was triggered');
};
function callback() {
alert('It worked');
}
await mermaid.initialize({
startOnLoad: false,
theme: 'redux',
// theme: 'default',
// theme: 'forest',
// handDrawnSeed: 12,
look: 'neo',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre',
// layout: 'elk',
// layout: 'fixed',
// htmlLabels: false,
flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
// fontFamily: 'courier',
fontFamily: 'Recursive',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
kanban: {
htmlLabels: false,
},
fontSize: 16,
logLevel: 0,
securityLevel: 'loose',
callback,
});
// setTimeout(() => {
mermaid.init(undefined, document.querySelectorAll('.mermaid'));
// }, 1000);
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
</script>
</body>
</html>

View File

@@ -0,0 +1,306 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&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=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
body {
/* background: rgb(221, 208, 208); */
/* background: #333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 {
color: grey;
}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
/* background-color: #efefef;
background-image: radial-gradient(#fff 51%, transparent 91%),
radial-gradient(#fff 51%, transparent 91%);
background-size: 20px 20px;
background-position:
0 0,
10px 10px;
background-repeat: repeat; */
}
.malware {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
/* tspan {
font-size: 6px !important;
} */
</style>
</head>
<body>
<pre id="diagram" class="mermaid"></pre>
<pre id="diagram2" class="mermaid"></pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err);
};
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
let code = `
stateDiagram
S:S
T:T
U:U
state Z {
state X {
Y:Ypsilon
}
}
A
S --> T: angrepp
S --> T: angrepp
T --> U
Y --> V
C
D
E
`;
code = `
flowchart TB
c1-->a2
subgraph one
a1-->a2
end
subgraph two
b1-->b2
end
subgraph three
c1-->c2
end
`;
// code = `
// flowchart BT
// A
// subgraph one
// a1 --> a2
// end
// subgraph two
// a3
// end
// `;
// code = `
// flowchart TB
// subgraph one
// a1-->a2
// end`;
// let positions = JSON.parse(
// '{"nodes":{"S":{"x":30.78125,"y":43.5},"Y":{"x":127.94140625,"y":50}},"edges":{}}'
// );
function exctractPositions(svg) {
const positions = { nodes: {}, edges: {} };
// Extract the viewbox paddings - TOSDO: update in collab
const viewBox = svg.getAttribute('viewBox').split(' ');
const viewBoxX = parseFloat(viewBox[0]);
const viewBoxY = parseFloat(viewBox[1]);
// console.log('viewBox:', viewBoxX, viewBoxY);
svg.querySelectorAll('[data-et="node"]').forEach((node) => {
if (node.tagName === 'g') {
// console.log('node:', node);
const id = node.dataset.id;
const bbox = node.getBBox();
const transform = node.getAttribute('transform');
const x = parseFloat(transform.split(',')[0].split('(')[1]);
const y = parseFloat(transform.split(',')[1].split(')')[0]);
// Get the bounding rectangle of the element
const rect = node.getBoundingClientRect();
// Get the absolute position relative to the document
const absoluteX = rect.left + window.pageXOffset + viewBoxX;
const absoluteY = rect.top + window.pageYOffset + viewBoxY;
positions.nodes[id] = {
x: absoluteX + rect.width / 2,
y: absoluteY + rect.height / 2,
width: rect.width,
height: rect.height,
};
}
});
svg.querySelectorAll('[data-et="cluster"]').forEach((node) => {
// console.log('cluster:', node);
if (node.tagName === 'g') {
const id = node.dataset.id;
// console.log('cluster:', node);
const transform = node.getAttribute('transform');
const rect = node.getBoundingClientRect();
// Get the absolute position relative to the document
const absoluteX = rect.left + window.pageXOffset + viewBoxX;
const absoluteY = rect.top + window.pageYOffset + viewBoxY;
positions.nodes[id] = {
x: absoluteX + rect.width / 2,
y: absoluteY + rect.height / 2,
width: rect.width,
height: rect.height,
};
}
});
svg.querySelectorAll('[data-et="edge"]').forEach((edge) => {
// if (node.tagName === 'g') {
const path = edge.getBoundingClientRect();
// Get the absolute position relative to the document
const absoluteX = path.left + window.pageXOffset + viewBoxX;
const absoluteY = path.top + window.pageYOffset + viewBoxY;
console.log(
'absoluteX:',
absoluteX,
'absoluteY:',
absoluteY,
'offset',
window.pageXOffset
);
const id = edge.dataset.id;
const points = JSON.parse(atob(edge.dataset.points));
console.log('edge:', points, absoluteX, absoluteY);
let minX = 10000;
let minY = 10000;
points.forEach((point) => {
if (point.x < minX) {
minX = point.x;
}
if (point.y < minY) {
minY = point.y;
}
});
let dx = absoluteX - minX;
let dy = absoluteY - minY;
if (dx < 1) {
dx = 0;
}
if (dy < 1) {
dy = 0;
}
positions.edges[id] = {
points: points.map((point) => {
console.log('point:', point.y, absoluteY);
return {
x: point.x + dx,
y: point.y + dy,
};
}),
};
// }
});
return positions;
}
const mode = 'reset';
if (mode === 'reset') {
mermaid.initialize({
startOnLoad: false,
layout: 'elk',
fontFamily: 'Kalam',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
logLevel: 5,
});
const { svg } = await mermaid.render('the-id-of-the-svg', code);
const elem = document.querySelector('#diagram');
elem.innerHTML = svg;
elem.classList.remove('mermaid');
const positions = exctractPositions(elem.firstChild);
// console.log('Positions:', JSON.stringify(positions));
const { svg: svg2 } = await mermaid.render(
'the-id-of-the-svg2',
'---\n config:\n layout: fixed\n---' + code,
undefined,
positions
);
// console.log('svg2', svg2);
const elem2 = document.querySelector('#diagram2');
elem2.innerHTML = svg2;
} else {
mermaid.initialize({
startOnLoad: false,
// look: 'handdrawn',
layout: 'fixed',
fontFamily: 'Kalam',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
logLevel: 0,
});
const { svg } = await mermaid.render('the-id-of-the-svg', code, undefined, positions);
// console.log(JSON.stringify(positions));
const elem = document.querySelector('#diagram');
elem.innerHTML = svg;
}
</script>
</body>
</html>

View File

@@ -78,77 +78,86 @@
font-family: monospace;
font-size: 72px;
}
pre {
width: 100%;
}
/* tspan {
font-size: 6px !important;
} */
/* .flowchart-link {
stroke-dasharray: 4, 4 !important;
animation: flow 1s linear infinite;
animation: dashdraw 4.93282s linear infinite;
stroke-width: 2px !important;
} */
@keyframes dashdraw {
from {
stroke-dashoffset: 0;
}
}
/*stroke-width:2;stroke-dasharray:10.000000,9.865639;stroke-dashoffset:-198.656393;animation: 4.932820s linear infinite;*/
/* stroke-width:2;stroke-dasharray:10.000000,9.865639;stroke-dashoffset:-198.656393;animation: dashdraw 4.932820s linear infinite;*/
</style>
</head>
<body>
<pre id="diagram4" class="mermaid">
flowchart LR
AB["apa@apa@"] --> B(("`apa@apa`"))
</pre>
<pre id="diagram4" class="mermaid">
flowchart
D(("for D"))
</pre>
<pre id="diagram4" class="mermaid">
flowchart LR
A e1@==> B
e1@{ animate: true}
---
config:
look: classic
theme: forest
layout: dagre
---
flowchart LR
A["A"] --> C
B("B B B B B") --> C[/"C C C C C"/]
C@{ shape: circle }
%%C@{ shape: question }
C@{ shape: stadium }
</pre>
<pre id="diagram4" class="mermaid">
---
config:
look: classic
layout: elk
---
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
n1["n1"] --- C
B("Continue") --> C[/"Evaluate"/]
C -- One --> D["Option 1"]
C -- Two --> E["Option 2"]
C -- Three --> F["fa:fa-car Option 3"]
C@{ shape: db }
</pre>
<h2>infinite</h2>
<pre id="diagram4" class="mermaid2">
---
config:
layout: elk
---
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>
%% subgraph s1["Untitled subgraph"]
C{"Evaluate"}
%% end
B --> C
</pre>
<pre id="diagram4" class="mermaid2">
---
config:
look: neo
layout: elk
---
flowchart LR
%% A ==> B
%% A2 --> B2
D --> I((I the Circle))
D --> I
</pre>
<pre id="diagram4" class="mermaid2">
---
config:
layout: elk
---
flowchart LR
subgraph S2
subgraph s1["APA"]
D{"Use the editor"}
end
info </pre
>
D -- Mermaid js --> I(("fa:fa-code Text"))
D --> I
D --> E --> I
end
</pre>
<pre id="diagram4" class="mermaid2">
---
config:
@@ -434,13 +443,10 @@ kanban
window.callback = function () {
alert('A callback was triggered');
};
function callback() {
alert('It worked');
}
await mermaid.initialize({
mermaid.initialize({
// theme: 'base',
// theme: 'default',
// theme: 'forest',
theme: 'forest',
// handDrawnSeed: 12,
// look: 'handDrawn',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
@@ -448,12 +454,10 @@ kanban
// layout: 'elk',
// layout: 'fixed',
// htmlLabels: false,
flowchart: { titleTopMargin: 10 },
flowchart: { titleTopMargin: 10, useMaxWidth: false },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
// fontFamily: 'courier',
fontFamily: 'arial',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
@@ -465,9 +469,10 @@ kanban
fontSize: 12,
logLevel: 0,
securityLevel: 'loose',
callback,
});
function callback() {
alert('It worked');
}
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);

View File

@@ -1,103 +1,173 @@
<!doctype html>
<html lang="en">
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Mindmap Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&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=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
div.mermaid {
/* font-family: 'trebuchet ms', verdana, arial; */
font-family: 'Courier New', Courier, monospace !important;
body {
/* background: rgb(221, 208, 208); */
/* background: #333; */
font-family: 'Arial';
/* color: white; */
/* font-size: 18px !important; */
}
h1 {
color: grey;
}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
/* background-color: #efefef;
background-image: radial-gradient(#fff 51%, transparent 91%),
radial-gradient(#fff 51%, transparent 91%);
background-size: 20px 20px;
background-position:
0 0,
10px 10px;
background-repeat: repeat; */
}
.malware {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
pre {
width: 100%;
}
/* tspan {
font-size: 6px !important;
} */
</style>
</head>
<body>
<h1>Mindmap diagram demo</h1>
<pre class="mermaid">
mindmap
root
child1((Circle))
grandchild 1
grandchild 2
child2(Round rectangle)
grandchild 3
grandchild 4
child3[Square]
grandchild 5
::icon(mdi mdi-fire)
gc6((grand<br/>child 6))
::icon(mdi mdi-fire)
gc7((grand<br/>grand<br/>child 8))
</pre>
<h2>Mindmap with root wrapping text and a shape</h2>
<pre class="mermaid">
mindmap
root[A root with a long text that wraps to keep the node size in check]
</pre>
<div class="flex gap-4">
<pre id="diagram4" class="mermaid">
---
config:
look: classic
theme: forest
layout: elk
---
flowchart LR
n1["n1"] --> C
n2("n2") --> C
C@{ shape: circle }
</pre
>
<pre id="diagram4" class="mermaid">
---
config:
look: neo
theme: redux
layout: elk
---
flowchart LR
n1["n1"] --> C
n2("n2") --> C
C@{ shape: circle }
</pre
>
<pre id="diagram4" class="mermaid">
---
config:
look: handDrawn
theme: forest
layout: elk
---
flowchart LR
n1["n1"] --> C
n2("n2") --> C
C@{ shape: circle }
</pre
>
</div>
<script type="module">
// import mermaid from './mermaid.esm.mjs';
import mermaid from '../../packages/mermaid/dist/mermaid.esm.mjs';
// import mermaidMindmap from './mermaid-mindmap.esm.mjs';
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
// import mermaidMindmap from 'https://cdn.jsdelivr.net/npm/@mermaid-js/mermaid-mindmap@9.3.0/+esm';
// await mermaid.registerExternalDiagrams([mermaidMindmap]);
const staticBellIconPack = {
prefix: 'fa6-regular',
icons: {
bell: {
body: '<path fill="currentColor" d="M224 0c-17.7 0-32 14.3-32 32v19.2C119 66 64 130.6 64 208v25.4c0 45.4-15.5 89.5-43.8 124.9L5.3 377c-5.8 7.2-6.9 17.1-2.9 25.4S14.8 416 24 416h400c9.2 0 17.6-5.3 21.6-13.6s2.9-18.2-2.9-25.4l-14.9-18.6c-28.3-35.5-43.8-79.6-43.8-125V208c0-77.4-55-142-128-156.8V32c0-17.7-14.3-32-32-32m0 96c61.9 0 112 50.1 112 112v25.4c0 47.9 13.9 94.6 39.7 134.6H72.3c25.8-40 39.7-86.7 39.7-134.6V208c0-61.9 50.1-112 112-112m64 352H160c0 17 6.7 33.3 18.7 45.3S207 512 224 512s33.3-6.7 45.3-18.7S288 465 288 448"/>',
width: 448,
},
},
width: 512,
height: 512,
};
const ALLOWED_TAGS = [
'a',
'b',
'blockquote',
'br',
'dd',
'div',
'dl',
'dt',
'em',
'foreignObject',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'h7',
'h8',
'hr',
'i',
'li',
'ul',
'ol',
'p',
'pre',
'span',
'strike',
'strong',
'table',
'tbody',
'td',
'tfoot',
'th',
'thead',
'tr',
];
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos@1/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () => staticBellIconPack,
},
]);
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
console.error('Mermaid error: ', err);
};
window.callback = function () {
alert('A callback was triggered');
};
mermaid.initialize({
theme: 'base',
startOnLoad: true,
flowchart: { titleTopMargin: 10, useMaxWidth: false },
fontSize: 12,
logLevel: 0,
flowchart: {
useMaxWidth: false,
htmlLabels: true,
},
gantt: {
useMaxWidth: false,
},
useMaxWidth: false,
securityLevel: 'loose',
});
function callback() {
alert('It worked');

View File

@@ -0,0 +1,171 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&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=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
body {
font-family: 'Arial';
background-color: #333;
}
h3 {
color: white;
}
</style>
</head>
<body>
<div class="flex w-full">
<div id="diagram-fixed"></div>
<div id="diagram-normal"></div>
</div>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err);
};
mermaid.initialize({
startOnLoad: false,
//look: 'handdrawn',
// layout: 'fixed',
theme: 'neo-dark',
//layout: 'elk',
fontFamily: 'Kalam',
logLevel: 1,
});
// let shape = 'rect'; // Done
//let shape = 'rounded'; // Done
//let shape = 'stadium'; // Done
// let shape = 'fr-rect'; // Done
// let shape = 'cyl'; // Done
//let shape = 'circle'; // Done
// let shape = 'odd'; // Done
// let shape = 'diam'; //Done
// let shape = 'hex'; // Done
// let shape = 'lean-r'; // Done
// let shape = 'lean-l'; // Done
// let shape = 'trap-b'; // Done
// let shape = 'trap-t'; // Done
// let shape = 'dbl-circ'; // Done
// let shape = 'text'; // Done
// let shape = 'notch-rect'; // Done
// let shape = 'lin-rect'; // Done
//let shape = 'sm-circ'; // Done
// let shape = 'fr-circ'; //Done
//let shape = 'fork'; // Done
//let shape = 'hourglass'; //Done
// let shape = 'bolt'; //Done
// let shape = 'doc'; // Done
// let shape = 'delay'; // Done
// let shape = 'h-cyl'; // Done
// let shape = 'lin-cyl'; // Done
// let shape = 'curv-trap'; // Done
// let shape = 'div-rect'; // Done
//let shape = 'tri'; // Done
// let shape = 'win-pane'; //Done
// let shape = 'f-circ'; // Done
// let shape = 'lin-doc'; // Done
// let shape = 'notch-pent'; // Done
// let shape = 'flip-tri'; // Done
// let shape = 'sl-rect'; // Done
// let shape = 'cross-circ'; // Done
// let shape = 'bow-rect'; // Done
// let shape = 'st-rect'; // Done
// let shape = 'flag';
// let shape = 'docs';
// let shape = 'brace';
// let shape = 'brace-r';
// let shape = 'braces';
// let shape = 'tag-doc';
let configFixed = `---
config:
layout: fixed
---
`;
let code = `flowchart TB
%% n80["APA ksldj hfaskljdh aklsjdhf klasjdhf klasjhf klsajdh klasjdhf klasjdhf klasjdh klasjhf klasjdh klajsdhfklasjdhf kljadh fklasjdhf klajsdhf lkasdhf klajsdhf klasjdhfklasjdh klasjhf klasdfh klasdfh aklsjfh akjshkasldfh klasdfh klasjh fklsjhf klasdhf kljasdhf klasdhf klj"]
%% n80@{ shape: '${shape}'}
n81@{ label: "Ashish", shape: '${shape}'}
%%n82@{ label: "n82", shape: '${shape}'}
%%n83@{ label: "n83", shape: '${shape}'}
`;
let positions = {
edges: {},
nodes: {
n81: {
x: 0,
y: 10,
width: 107.7,
height: 65,
},
n80: {
x: -400,
y: 10,
width: 1,
height: 1,
},
n82: {
x: 0,
y: 110,
},
n83: {
x: 80,
y: 10,
},
n84: {
x: 1200,
y: 10,
width: 300,
height: 200,
},
},
};
console.log(configFixed + code);
const { svg } = await mermaid.render(
'the-id-of-the-svg-1',
configFixed + code,
undefined,
positions
);
const elem = document.querySelector('#diagram-fixed');
elem.innerHTML = svg;
const { svg: svg2 } = await mermaid.render('the-id-of-the-svg-2', code, undefined, positions);
const elem2 = document.querySelector('#diagram-normal');
elem2.innerHTML = svg2;
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,248 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&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=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Recursive:wght@300..1000&display=swap"
rel="stylesheet"
/>
<style>
.recursive-500 {
font-family: 'Recursive', 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; */
/* font-family: 'Arial'; */
font-family: 'Recursive', serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
font-variation-settings:
'slnt' 0,
'CASL' 0,
'CRSV' 0.5,
'MONO' 0;
/* color: white; */
/* font-size: 18px !important; */
}
.gridify.tiny {
background-image: linear-gradient(
transparent 11px,
rgba(220, 220, 200, 0.8) 12px,
transparent 12px
),
linear-gradient(90deg, transparent 11px, rgba(220, 220, 200, 0.8) 12px, transparent 12px);
background-size:
100% 12px,
12px 100%;
}
.gridify.dots {
background-image: radial-gradient(
circle at center,
rgba(220, 220, 200, 0.8) 1px,
transparent 1px
);
background-size: 24px 24px;
}
h1 {
color: grey;
}
.mermaid2 {
display: none;
}
.mermaid svg {
font-size: 16px !important;
font-family: 'Recursive', serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
font-variation-settings:
'slnt' 0,
'CASL' 0,
'CRSV' 0.5,
'MONO' 0;
}
pre {
width: 100%;
/*box-shadow: 4px 4px 0px 0px #0000000F;*/
}
</style>
</head>
<body class="gridify dots">
<p class="mb-20">Test Diagram</p>
<div class="w-full h-64">
<pre style="display: none">
---
config:
theme: neo
layout: dagre
---
flowchart TD
A{"Cylinder"} --- n1["Rectangle"] & n2["Rounded"] & n3(["Stadium"])
n1 --x n4["Rounded"]
n2 --o n5["Hexagon"]
n3 --> n6["Parallelogram"]
n5 o--o n7["Trapezoid"]
n4 x--x n8["Lean Right"]
n6 <--> n9(("Circle"))
n8 --> n10["Rose"]
n7 --> n11["Pine"]
n9 --> n12["Peach"]
n2@{ shape: rounded}
n4@{ shape: rounded}
n5@{ shape: hex}
n6@{ shape: lean-l}
n7@{ shape: trap-b}
n8@{ shape: lean-r}
n10:::Rose
n11:::Pine
n12:::Peach
classDef Rose stroke-width:1px, stroke-dasharray:none, stroke:#FF5978, fill:#FFDFE5, color:#8E2236
classDef Pine stroke-width:1px, stroke-dasharray:none, stroke:#254336, fill:#27654A, color:#FFFFFF
classDef Peach stroke-width:1px, stroke-dasharray:none, stroke:#FBB35A, fill:#FFEFDB, color:#8F632D
n10 --x End
n11 --x End
n12 --x End
</pre
>
<pre id="diagram4" class="mermaid">
---
config:
theme: neo
layout: dagre
---
flowchart TD
n1["Cylinder"]
n1@{ shape: database}
</pre
>
</div>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
const staticBellIconPack = {
prefix: 'fa6-regular',
icons: {
bell: {
body: '<path fill="currentColor" d="M224 0c-17.7 0-32 14.3-32 32v19.2C119 66 64 130.6 64 208v25.4c0 45.4-15.5 89.5-43.8 124.9L5.3 377c-5.8 7.2-6.9 17.1-2.9 25.4S14.8 416 24 416h400c9.2 0 17.6-5.3 21.6-13.6s2.9-18.2-2.9-25.4l-14.9-18.6c-28.3-35.5-43.8-79.6-43.8-125V208c0-77.4-55-142-128-156.8V32c0-17.7-14.3-32-32-32m0 96c61.9 0 112 50.1 112 112v25.4c0 47.9 13.9 94.6 39.7 134.6H72.3c25.8-40 39.7-86.7 39.7-134.6V208c0-61.9 50.1-112 112-112m64 352H160c0 17 6.7 33.3 18.7 45.3S207 512 224 512s33.3-6.7 45.3-18.7S288 465 288 448"/>',
width: 448,
},
},
width: 512,
height: 512,
};
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos@1/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () => staticBellIconPack,
},
]);
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err);
};
window.callback = function () {
alert('A callback was triggered');
};
function callback() {
alert('It worked');
}
await mermaid.initialize({
startOnLoad: false,
theme: 'redux',
// theme: 'default',
// theme: 'forest',
// handDrawnSeed: 12,
look: 'neo',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre',
// layout: 'elk',
// layout: 'fixed',
// htmlLabels: false,
flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
// fontFamily: 'courier',
fontFamily: 'Recursive',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
kanban: {
htmlLabels: false,
},
fontSize: 16,
logLevel: 0,
securityLevel: 'loose',
callback,
});
// setTimeout(() => {
mermaid.init(undefined, document.querySelectorAll('.mermaid'));
// }, 1000);
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
</script>
</body>
</html>

View File

@@ -4,28 +4,60 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&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=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
/* background: #333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 {
color: grey;
}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
/* background-color: #efefef;
background-image: radial-gradient(#fff 51%, transparent 91%),
radial-gradient(#fff 51%, transparent 91%);
background-size: 20px 20px;
background-position:
0 0,
10px 10px;
background-repeat: repeat; */
}
.malware {
position: fixed;
bottom: 0;
@@ -41,34 +73,75 @@
font-family: monospace;
font-size: 72px;
}
/* tspan {
font-size: 6px !important;
} */
</style>
</head>
<body>
<div>Security check</div>
<pre id="diagram" class="mermaid">
flowchart LR
A-->B
</pre
>
<pre id="diagram" class="mermaid2">
mindmap
root
ch1
ch2
</pre
stateDiagram-v2
direction LR
[*] --> Active
state Active {
direction BT
[*] --> Inner
Inner --> NumLockOn : EvNumLockPressed
}
%% Outer --> Inner
</pre
>
<script src="./packages/mermaid-mindmap/dist/mermaid-mindmap-detector.js"></script>
<script src="./packages/mermaid-mindmap/dist/mermaid-example-diagram-detector.js"></script>
<script src="./packages/mermaid/dist/mermaid.esm.mjs"></script>
<script>
<pre id="diagram" class="mermaid">
stateDiagram-v2
[*] --> First
state First {
[*] --> second
second --> [*]
}
</pre>
<pre id="diagram" class="mermaid2">
flowchart LR
A[Start] --Some text--> B(Continue)
B --> C{Evaluate}
C -- One --> D[Option 1]
C -- Two --> E[Option 2]
C -- Three --> F[fa:fa-car Option 3]
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
console.error('Mermaid error: ', err);
};
mermaid.initialize({
startOnLoad: true,
theme: 'neo',
handdrawnSeed: 12,
look: 'neo',
//layout: 'elk',
'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre',
// layout: 'elk',
flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
//fontFamily: 'Kalam',
fontFamily: 'Arial',
sequence: {
actorFontFamily: 'arial',
noteFontFamily: 'arial',
messageFontFamily: 'arial',
},
fontSize: 10,
logLevel: 0,
basePath: './packages/',
// themeVariables: {relationLabelColor: 'red'}
htmlLabels: true,
});
function callback() {
alert('It worked');
@@ -77,6 +150,10 @@ A-->B
console.error('In parse error:');
console.error(err);
};
// 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>

View File

@@ -0,0 +1,307 @@
<html>
<head>
<script src="//unpkg.com/alpinejs" defer></script>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&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=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
body {
font-family: 'Arial';
}
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
th,
td {
border: 1px solid black;
padding: 10px;
text-align: center;
vertical-align: middle;
}
.separator {
height: 20px;
background-color: #f0f0f0;
}
.vertical-header {
text-align: center;
}
.collapsible {
background-color: #f9f9f9;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.active,
.collapsible:hover {
background-color: #ccc;
}
.collapsible:after {
content: '\002B';
color: #777;
font-weight: bold;
float: right;
margin-left: 2px;
}
.active:after {
content: '\2212';
}
.content {
padding: 0 5px;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: #f1f1f1;
}
.content .pre-scrollable {
max-height: 200px;
overflow-y: scroll;
}
</style>
</head>
<body>
<script>
const data = {
shapes: [
{
descr: 'Stadium shape',
code: `
flowchart LR
id1([This is the text in the box])
`,
},
{
descr: 'Sub-Routine shape',
code: `
flowchart LR
id1[[This is the text in the box]]
`,
},
{
descr: 'Cylindrical shape',
code: `
flowchart LR
id1[(Database)]
`,
},
{
descr: 'Circle shape',
code: `
flowchart LR
id1((Circle))
`,
},
{
descr: 'Double Circle shape',
code: `
flowchart LR
id1(((Circle)))
`,
},
{
descr: 'Asymmetric shape',
code: `
flowchart LR
id1>This is the text in the box]
`,
},
{
descr: 'Rhombus/Diamond/Question shape',
code: `
flowchart LR
id1{This is the text in the box}
`,
},
{
descr: 'Hexagon shape',
code: `
flowchart LR
id1{{This is the text in the box}}
`,
},
{
descr: 'Parallelogram shape',
code: `
flowchart TD
id1[/This is the text in the box/]
`,
},
{
descr: 'Parallelogram Alt shape',
code: `
flowchart TD
id1[\This is the text in the box\]
`,
},
{
descr: 'Trapezoid shape',
code: `
flowchart TD
A[/Christmas\\]
`,
},
{
descr: 'Trapezoid Alt shape',
code: `
flowchart TD
id1[\\This is the text in the box\\]
`,
},
{
descr: 'Rect with rounded corner',
code: `
flowchart LR
id1(This is the text in the box)
`,
},
{
descr: 'Rect with sharp corner',
code: `
flowchart LR
id1[This is the text in the box]
`,
},
],
looks: ['classic', 'handdrawn', 'neo'],
// looks: ['classic'],
layouts: ['elk', 'dagre'],
// layouts: ['elk'],
themes: ['default', 'neo'],
// themes: ['default'],
};
function generateMermaidCode(layout, look, theme, shape) {
return `---
config:
layout: ${layout}
look: ${look}
theme: ${theme}
---
${shape.code}
`;
}
</script>
<table x-data="data">
<tr>
<th></th>
<template x-for="layout in layouts">
<template x-for="look in looks">
<template x-for="theme in themes">
<th x-text="layout + '-' + look + '-' + theme "></th>
</template>
</template>
</template>
</tr>
<template x-for="shape in shapes">
<tr>
<th class="vertical-header">
<button class="collapsible" x-text="shape.descr">Sub-Routine shape</button>
<div class="content">
<div class="pre-scrollable">
<pre x-text="shape.code"></pre>
</div>
</div>
</th>
<template x-for="layout in layouts">
<template x-for="look in looks">
<template x-for="theme in themes">
<td>
<pre
id="diagram6"
class="mermaid"
x-text="generateMermaidCode(layout, look, theme, shape)"
></pre>
</td>
</template>
</template>
</template>
</tr>
</template>
</table>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {};
mermaid.initialize({
handdrawn: false,
mergeEdges: true,
layout: 'dagre',
flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
fontFamily: 'Kalam',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
fontSize: 16,
logLevel: 0,
});
function callback() {
alert('It worked');
}
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
let coll = document.getElementsByClassName('collapsible');
for (const element of coll) {
element.addEventListener('click', function () {
this.classList.toggle('active');
let content = this.nextElementSibling;
if (content.style.maxHeight) {
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + 'px';
}
});
}
</script>
</body>
</html>

View File

@@ -0,0 +1,102 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&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=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
body {
font-family: 'Arial';
background-color: #333;
}
</style>
</head>
<body>
<div id="diagram"></div>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err);
};
mermaid.initialize({
startOnLoad: false,
//look: 'handdrawn',
// layout: 'fixed',
theme: 'dark',
//layout: 'elk',
fontFamily: 'Kalam',
logLevel: 1,
});
let shape = 'circle';
let simplified = true;
// let simplified = false;
let algorithm = 'elk';
// let algorithm = 'dagre';
let code = `---
config:
layout: ${algorithm}
---
flowchart TD
A["Abrakadabra"] --> C["C"] & D["I am a circle"] & n4["Untitled Node"]
D@{ shape: diamond}
B["Bombrakadombra"] --> D & C & D
C --> E["E"] & B
D --> E & A
n4 --> C
A@{ shape: ${shape}}
B@{ shape: ${shape}}
C@{ shape: ${shape}}
D@{ shape: ${shape}}
E@{ shape: ${shape}}
n4@{ shape: ${shape}}
`;
if (simplified) {
code = `---
config:
layout: ${algorithm}
---
flowchart LR
A["Abrakadabra"] --> C["I am the circle"] & C & C & C & C
%% A["Abrakadabra"] --> C
A@{ shape: ${shape}}
C@{ shape: ${shape}}
`;
}
console.log(code);
const { svg } = await mermaid.render('the-id-of-the-svg', code, undefined, undefined);
const elem = document.querySelector('#diagram');
elem.innerHTML = svg;
</script>
</body>
</html>

View File

@@ -0,0 +1,180 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&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=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
body {
font-family: 'Arial';
background-color: #333;
}
</style>
</head>
<body>
<div id="diagram"></div>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err);
};
mermaid.initialize({
startOnLoad: false,
//look: 'handdrawn',
layout: 'fixed',
theme: 'neo-dark',
//layout: 'elk',
fontFamily: 'Kalam',
logLevel: 1,
class: {
hideEmptyMembersBox: true,
},
});
let shape = 'circle';
let code = `
flowchart TB
n80["APA ksldj hfaskljdh aklsjdhf klasjdhf klasjhf klsajdh klasjdhf klasjdhf klasjdh klasjhf klasjdh klajsdhfklasjdhf kljadh fklasjdhf klajsdhf lkasdhf klajsdhf klasjdhfklasjdh klasjhf klasdfh klasdfh aklsjfh akjshkasldfh klasdfh klasjh fklsjhf klasdhf kljasdhf klasdhf klj"]
n80@{ shape: '${shape}'}
n81["APA ksldj hfaskljdh aklsjdhf klasjdhf klasjhf klsajdh klasjdhf klasjdhf klasjdh klasjhf klasjdh klajsdhfklasjdhf kljadh fklasjdhf klajsdhf lkasdhf klajsdhf klasjdhfklasjdh klasjhf klasdfh klasdfh aklsjfh akjshkasldfh klasdfh klasjh fklsjhf klasdhf kljasdhf klasdhf klj"]
n82["A single line of text"]
n81@{ shape: '${shape}'}
n82@{ shape: '${shape}'}
n83@{ label: "A single line of text", shape: '${shape}'}
n84@{ shape: '${shape}'}
`;
let code2 = `
classDiagram
class class1 {
int num
string test
string test
string test
string test
string test
method()
}
class class2 {
int num
string test
string test
string test
string test
string test
method()
method()
}
class class3 {
int test
}
<<interface>> class3
class class4 {
int[] id
method()
method()
method()
method()
}
<<interface>> class4
`;
let positions = {
edges: {},
nodes: {
n81: {
x: 0,
y: 10,
width: 300,
height: 200,
},
n80: {
x: -400,
y: 10,
width: 100,
height: 50,
},
n82: {
x: 400,
y: 10,
width: 300,
height: 200,
},
n83: {
x: 800,
y: 10,
},
n84: {
x: 1200,
y: 10,
width: 300,
height: 200,
},
},
};
let positions2 = {
edges: {},
nodes: {
class1: {
x: 0,
y: 10,
width: 100,
height: 400,
},
class2: {
x: -300,
y: 100,
width: 100,
height: 0,
},
class3: {
x: 400,
y: 10,
width: 0,
height: 0,
},
class4: {
x: 800,
y: 10,
width: 0,
height: 0,
},
},
};
const { svg } = await mermaid.render('the-id-of-the-svg', code2, undefined, positions2);
const elem = document.querySelector('#diagram');
elem.innerHTML = svg;
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -93,6 +93,7 @@
<th></th> <!-- Placeholder for the top left corner -->
<th>Dagre</th>
<th>Dagre with rough</th>
<th>Dagre with neo</th>
<th>ELK</th>
<th>ELK with rough</th>
</tr>
@@ -116,6 +117,14 @@ stateDiagram-v2
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
stateDiagram-v2
stateId
</pre>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
stateId
@@ -163,6 +172,13 @@ stateDiagram-v2
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
stateDiagram-v2
state "This is a state description" as s3
</pre>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
state "This is a state description" as s3
</pre>
@@ -207,6 +223,14 @@ stateDiagram-v2
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
stateDiagram-v2
s22 : This is a state description
</pre>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
s22 : This is a state description
@@ -267,10 +291,20 @@ stateDiagram-v2
</pre>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
s51 --> s52
</pre>
</td>
<td>
<pre id="diagram3" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
stateDiagram-v2
s51 --> s52
s61 --> s62
</pre>
@@ -279,7 +313,7 @@ stateDiagram-v2
<pre id="diagram4" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
stateDiagram-v2
s61 --> s62
s71 --> s72
</pre>
@@ -322,13 +356,23 @@ stateDiagram-v2
a3 --> a4: A transition
</pre>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
a5 --> a6: A transition
</pre>
</td>
<td>
<pre id="diagram3" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
stateDiagram-v2
a5 --> a6: A transition
a7 --> a8: A transition
</pre>
@@ -337,7 +381,7 @@ stateDiagram-v2
<pre id="diagram4" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
stateDiagram-v2
a7 --> a8: A transition
a9 --> a10: A transition
</pre>
@@ -383,6 +427,17 @@ stateDiagram-v2
test --> [*]
</pre>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
[*] --> test
test --> [*]
</pre>
</td>
<td>
@@ -455,6 +510,20 @@ stateDiagram-v2
}
</pre>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
[*] --> First
state First {
[*] --> second
second --> [*]
}
</pre>
</td>
<td>
@@ -568,6 +637,31 @@ stateDiagram-v2
</pre>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
[*] --> Level1
state Level1 {
[*] --> Level2
state Level2 {
[*] --> level2
level2 --> Level3
state Level3 {
[*] --> level3
level3 --> [*]
}
}
}
</pre>
</td>
<td>
@@ -698,6 +792,30 @@ stateDiagram-v2
</pre>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
[*] --> B1
B1 --> B2
B1 --> B3
state B1 {
[*] --> B11
B11 --> [*]
}
state B2 {
[*] --> B22
B22 --> [*]
}
state B3 {
[*] --> B33
B33 --> [*]
}
</pre>
</td>
<td>
<pre id="diagram3" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
stateDiagram-v2
@@ -794,7 +912,19 @@ stateDiagram-v2
if_state --> True : if n >= 0
</pre>
</td>
<td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
state if_state <<choice>>
[*] --> IsPositive
IsPositive --> if_state
if_state --> False: if n < 0
if_state --> True : if n >= 0
</pre>
</td>
<td>
<pre id="diagram3" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
stateDiagram-v2
@@ -866,6 +996,23 @@ stateDiagram-v2
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
stateDiagram-v2
state fork_state <<fork>>
[*] --> fork_state
fork_state --> State2
fork_state --> State3
state join_state <<join>>
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
</pre>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
state fork_state <<fork>>
[*] --> fork_state
@@ -956,6 +1103,19 @@ stateDiagram-v2
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
stateDiagram-v2
TN3: The state with a note
note right of TN3
Important information! You can write
notes.
end note
TN3 --> TN4
note left of TN4 : This is the note to the left.
</pre>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
TN3: The state with a note
note right of TN3
@@ -1056,6 +1216,27 @@ state Active {
stateDiagram-v2
[*] --> Active
state Active {
[*] --> NumLockOff
NumLockOff --> NumLockOn : EvNumLockPressed
NumLockOn --> NumLockOff : EvNumLockPressed
--
[*] --> CapsLockOff
CapsLockOff --> CapsLockOn : EvCapsLockPressed
CapsLockOn --> CapsLockOff : EvCapsLockPressed
--
[*] --> ScrollLockOff
ScrollLockOff --> ScrollLockOn : EvScrollLockPressed
ScrollLockOn --> ScrollLockOff : EvScrollLockPressed
}
</pre>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
[*] --> Active
state Active {
[*] --> NumLockOff
NumLockOff --> NumLockOn : EvNumLockPressed
@@ -1161,6 +1342,21 @@ direction LR
<pre id="diagram2" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
stateDiagram-v2
direction LR
[*] --> D1
D1 --> D2
D2 --> D3
state D3 {
direction TB
D11 --> D22
}
D2 --> D4
</pre>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "neo"} }%%
stateDiagram-v2
direction LR
[*] --> D1
D1 --> D2

172
cypress/platform/steph.html Normal file
View File

@@ -0,0 +1,172 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&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=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
body {
/* background: rgb(221, 208, 208); */
/* background: #333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 {
color: grey;
}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
/* background-color: #efefef;
background-image: radial-gradient(#fff 51%, transparent 91%),
radial-gradient(#fff 51%, transparent 91%);
background-size: 20px 20px;
background-position:
0 0,
10px 10px;
background-repeat: repeat; */
}
</style>
</head>
<body>
<pre id="diagram" class="mermaid2">
%%{init: {"look": "neo", "theme": "neo","fontFamily": "Arial"} }%%
flowchart
A[A really really really super long node] --> B & C
subgraph apa
D --> E
end
</pre
>
<pre id="diagram" class="mermaid2">
%%{init: {"look": "neo", "theme": "forest","fontFamily": "Arial", "themeVariables": {
"useGradient": true,
"gradientStart": '#fff',
"gradientStop": '#ccc'
}} }%%
stateDiagram-v2
stateId
</pre
>
<pre id="diagram2" class="mermaid2">
flowchart LR
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
</pre>
<pre id="diagram3" class="mermaid2">
flowchart LR
A:::foo & B:::bar --> C:::foobar
classDef foo stroke:#f00
classDef bar stroke:#0f0
classDef ash color:red
class C ash
style C stroke:#00f, fill:black
</pre>
<!-- Flowchart with subgraph-->
<pre id="diagram3" class="mermaid">
flowchart TB
c1-->a2
subgraph one
a1-->a2
end
subgraph two
b1-->b2
end
subgraph three
c1-->c2
end
</pre>
<pre id="diagram4" class="mermaid">
stateDiagram-v2
[*] --> First
state First {
[*] --> second
second --> [*]
}
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err);
};
window.callback = function () {
alert('A callback was triggered');
};
mermaid.initialize({
theme: 'neo',
// handdrawnSeed: 12,
look: 'neo',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre',
// layout: 'elk',
// layout: 'fixed',
// htmlLabels: false,
flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
// fontFamily: 'courier',
fontFamily: 'arial',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
fontSize: 12,
logLevel: 0,
securityLevel: 'loose',
});
function callback() {
alert('It worked');
}
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
</script>
</body>
</html>

View File

@@ -0,0 +1,285 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Architecture Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
<style>
div.mermaid {
/* font-family: 'trebuchet ms', verdana, arial; */
font-family: 'Courier New', Courier, monospace !important;
background-color: #333;
}
body {
color: white;
background-color: #333;
}
</style>
</head>
<body>
<h1>Architecture diagram demo</h1>
<h2>Simple diagram with groups</h2>
<pre class="mermaid">
architecture-beta
group api(cloud)[API]
service db(database)[Database] in api
service disk1(disk)[Storage] in api
service disk2(disk)[Storage] in api
service server(server)[Server] in api
service gateway(internet)[Gateway]
db:L -- R:server
disk1:T -- B:server
disk2:T -- B:db
server:T -- B:gateway
</pre>
<hr />
<h2>Groups within groups</h2>
<pre class="mermaid">
architecture-beta
group api[API]
group public[Public API] in api
group private[Private API] in api
service serv1(server)[Server] in public
service serv2(server)[Server] in private
service db(database)[Database] in private
service gateway(internet)[Gateway] in api
serv1:B -- T:serv2
serv2:L -- R:db
serv1:L -- R:gateway
</pre>
<hr />
<h2>Default icon (?) from unknown icon name</h2>
<pre class="mermaid">
architecture-beta
service unknown(iconnamedoesntexist)[Unknown Icon]
</pre>
<hr />
<h2>Split Direction</h2>
<pre class="mermaid">
architecture-beta
service db(database)[Database]
service s3(disk)[Storage]
service serv1(server)[Server 1]
service serv2(server)[Server 2]
service disk(disk)[Disk]
db:L -- R:s3
serv1:L -- T:s3
serv2:L -- B:s3
serv1:T -- B:disk
</pre>
<hr />
<h2>Arrow Tests</h2>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L <--> R:servL
servC:R <--> L:servR
servC:T <--> B:servT
servC:B <--> T:servB
servL:T <--> L:servT
servL:B <--> L:servB
servR:T <--> R:servT
servR:B <--> R:servB
</pre>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L <--> R:servL
servC:R <--> L:servR
servC:T <--> B:servT
servC:B <--> T:servB
servT:L <--> T:servL
servB:L <--> B:servL
servT:R <--> T:servR
servB:R <--> B:servR
</pre>
<hr />
<h2>Group Edges</h2>
<pre class="mermaid">
architecture-beta
group left_group(cloud)[Left]
group right_group(cloud)[Right]
group top_group(cloud)[Top]
group bottom_group(cloud)[Bottom]
group center_group(cloud)[Center]
service left_disk(disk)[Disk] in left_group
service right_disk(disk)[Disk] in right_group
service top_disk(disk)[Disk] in top_group
service bottom_disk(disk)[Disk] in bottom_group
service center_disk(disk)[Disk] in center_group
left_disk{group}:R <--> L:center_disk{group}
right_disk{group}:L <--> R:center_disk{group}
top_disk{group}:B <--> T:center_disk{group}
bottom_disk{group}:T <--> B:center_disk{group}
</pre
>
<hr />
<h2>Edge Label Test</h2>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L -[Label]- R:servL
servC:R -[Label]- L:servR
servC:T -[Label]- B:servT
servC:B -[Label]- T:servB
servL:T -[Label]- L:servT
servL:B -[Label]- L:servB
servR:T -[Label]- R:servT
servR:B -[Label]- R:servB
</pre>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L -[Label that is Long]- R:servL
servC:R -[Label that is Long]- L:servR
servC:T -[Label that is Long]- B:servT
servC:B -[Label that is Long]- T:servB
servL:T -[Label that is Long]- L:servT
servL:B -[Label that is Long]- L:servB
servR:T -[Label that is Long]- R:servT
servR:B -[Label that is Long]- R:servB
</pre>
<hr />
<h2>Junction Demo</h2>
<pre class="mermaid">
architecture-beta
service left_disk(disk)[Disk]
service top_disk(disk)[Disk]
service bottom_disk(disk)[Disk]
service top_gateway(internet)[Gateway]
service bottom_gateway(internet)[Gateway]
junction juncC
junction juncR
left_disk:R -- L:juncC
top_disk:B -- T:juncC
bottom_disk:T -- B:juncC
juncC:R -- L:juncR
top_gateway:B -- T:juncR
bottom_gateway:T -- B:juncR
</pre>
<hr />
<h2>Junction Demo Groups</h2>
<pre class="mermaid">
architecture-beta
group left
group right
service left_disk(disk)[Disk] in left
service top_disk(disk)[Disk] in left
service bottom_disk(disk)[Disk] in left
service top_gateway(internet)[Gateway] in right
service bottom_gateway(internet)[Gateway] in right
junction juncC in left
junction juncR in right
left_disk:R -- L:juncC
top_disk:B -- T:juncC
bottom_disk:T -- B:juncC
top_gateway:B <-- T:juncR
bottom_gateway:T <-- B:juncR
juncC{group}:R --> L:juncR{group}
</pre>
<hr />
<h2>External Icons Demo</h2>
<pre class="mermaid">
architecture-beta
service s3(logos:aws-s3)[Cloud Store]
service ec2(logos:aws-ec2)[Server]
service api(logos:aws-api-gateway)[Api Gateway]
service fa(fa:image)[Font Awesome Icon]
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({
theme: 'dark',
// handDrawnSeed: 12,
// look: 'handDrawn',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre',
// layout: 'elk',
// layout: 'fixed',
// htmlLabels: false,
//flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
// fontFamily: 'courier',
// fontFamily: 'arial',
// sequence: {
// actorFontFamily: 'courier',
// noteFontFamily: 'courier',
// messageFontFamily: 'courier',
// },
// fontSize: 12,
// logLevel: 3,
// securityLevel: 'loose',
});
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () =>
fetch('https://unpkg.com/@iconify-json/fa6-regular/icons.json').then((res) =>
res.json()
),
},
]);
</script>
</body>
</html>

View File

@@ -0,0 +1,280 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Architecture Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
<style>
div.mermaid {
/* font-family: 'trebuchet ms', verdana, arial; */
font-family: 'Courier New', Courier, monospace !important;
}
</style>
</head>
<body>
<h1>Architecture diagram demo</h1>
<h2>Simple diagram with groups</h2>
<pre class="mermaid">
architecture-beta
group api(cloud)[API]
service db(database)[Database] in api
service disk1(disk)[Storage] in api
service disk2(disk)[Storage] in api
service server(server)[Server] in api
service gateway(internet)[Gateway]
db:L -- R:server
disk1:T -- B:server
disk2:T -- B:db
server:T -- B:gateway
</pre>
<hr />
<h2>Groups within groups</h2>
<pre class="mermaid">
architecture-beta
group api[API]
group public[Public API] in api
group private[Private API] in api
service serv1(server)[Server] in public
service serv2(server)[Server] in private
service db(database)[Database] in private
service gateway(internet)[Gateway] in api
serv1:B -- T:serv2
serv2:L -- R:db
serv1:L -- R:gateway
</pre>
<hr />
<h2>Default icon (?) from unknown icon name</h2>
<pre class="mermaid">
architecture-beta
service unknown(iconnamedoesntexist)[Unknown Icon]
</pre>
<hr />
<h2>Split Direction</h2>
<pre class="mermaid">
architecture-beta
service db(database)[Database]
service s3(disk)[Storage]
service serv1(server)[Server 1]
service serv2(server)[Server 2]
service disk(disk)[Disk]
db:L -- R:s3
serv1:L -- T:s3
serv2:L -- B:s3
serv1:T -- B:disk
</pre>
<hr />
<h2>Arrow Tests</h2>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L <--> R:servL
servC:R <--> L:servR
servC:T <--> B:servT
servC:B <--> T:servB
servL:T <--> L:servT
servL:B <--> L:servB
servR:T <--> R:servT
servR:B <--> R:servB
</pre>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L <--> R:servL
servC:R <--> L:servR
servC:T <--> B:servT
servC:B <--> T:servB
servT:L <--> T:servL
servB:L <--> B:servL
servT:R <--> T:servR
servB:R <--> B:servR
</pre>
<hr />
<h2>Group Edges</h2>
<pre class="mermaid">
architecture-beta
group left_group(cloud)[Left]
group right_group(cloud)[Right]
group top_group(cloud)[Top]
group bottom_group(cloud)[Bottom]
group center_group(cloud)[Center]
service left_disk(disk)[Disk] in left_group
service right_disk(disk)[Disk] in right_group
service top_disk(disk)[Disk] in top_group
service bottom_disk(disk)[Disk] in bottom_group
service center_disk(disk)[Disk] in center_group
left_disk{group}:R <--> L:center_disk{group}
right_disk{group}:L <--> R:center_disk{group}
top_disk{group}:B <--> T:center_disk{group}
bottom_disk{group}:T <--> B:center_disk{group}
</pre
>
<hr />
<h2>Edge Label Test</h2>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L -[Label]- R:servL
servC:R -[Label]- L:servR
servC:T -[Label]- B:servT
servC:B -[Label]- T:servB
servL:T -[Label]- L:servT
servL:B -[Label]- L:servB
servR:T -[Label]- R:servT
servR:B -[Label]- R:servB
</pre>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L -[Label that is Long]- R:servL
servC:R -[Label that is Long]- L:servR
servC:T -[Label that is Long]- B:servT
servC:B -[Label that is Long]- T:servB
servL:T -[Label that is Long]- L:servT
servL:B -[Label that is Long]- L:servB
servR:T -[Label that is Long]- R:servT
servR:B -[Label that is Long]- R:servB
</pre>
<hr />
<h2>Junction Demo</h2>
<pre class="mermaid">
architecture-beta
service left_disk(disk)[Disk]
service top_disk(disk)[Disk]
service bottom_disk(disk)[Disk]
service top_gateway(internet)[Gateway]
service bottom_gateway(internet)[Gateway]
junction juncC
junction juncR
left_disk:R -- L:juncC
top_disk:B -- T:juncC
bottom_disk:T -- B:juncC
juncC:R -- L:juncR
top_gateway:B -- T:juncR
bottom_gateway:T -- B:juncR
</pre>
<hr />
<h2>Junction Demo Groups</h2>
<pre class="mermaid">
architecture-beta
group left
group right
service left_disk(disk)[Disk] in left
service top_disk(disk)[Disk] in left
service bottom_disk(disk)[Disk] in left
service top_gateway(internet)[Gateway] in right
service bottom_gateway(internet)[Gateway] in right
junction juncC in left
junction juncR in right
left_disk:R -- L:juncC
top_disk:B -- T:juncC
bottom_disk:T -- B:juncC
top_gateway:B <-- T:juncR
bottom_gateway:T <-- B:juncR
juncC{group}:R --> L:juncR{group}
</pre>
<hr />
<h2>External Icons Demo</h2>
<pre class="mermaid">
architecture-beta
service s3(logos:aws-s3)[Cloud Store]
service ec2(logos:aws-ec2)[Server]
service api(logos:aws-api-gateway)[Api Gateway]
service fa(fa:image)[Font Awesome Icon]
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({
theme: 'mc',
// handDrawnSeed: 12,
// look: 'handDrawn',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre',
// layout: 'elk',
// layout: 'fixed',
// htmlLabels: false,
//flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
// fontFamily: 'courier',
// fontFamily: 'arial',
// sequence: {
// actorFontFamily: 'courier',
// noteFontFamily: 'courier',
// messageFontFamily: 'courier',
// },
// fontSize: 12,
// logLevel: 3,
// securityLevel: 'loose',
});
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () =>
fetch('https://unpkg.com/@iconify-json/fa6-regular/icons.json').then((res) =>
res.json()
),
},
]);
</script>
</body>
</html>

View File

@@ -0,0 +1,284 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Architecture Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
<style>
div.mermaid {
/* font-family: 'trebuchet ms', verdana, arial; */
font-family: 'Courier New', Courier, monospace !important;
}
body {
color: white;
background-color: #333;
}
</style>
</head>
<body>
<h1>Architecture diagram demo</h1>
<h2>Simple diagram with groups</h2>
<pre class="mermaid">
architecture-beta
group api(cloud)[API]
service db(database)[Database] in api
service disk1(disk)[Storage] in api
service disk2(disk)[Storage] in api
service server(server)[Server] in api
service gateway(internet)[Gateway]
db:L -- R:server
disk1:T -- B:server
disk2:T -- B:db
server:T -- B:gateway
</pre>
<hr />
<h2>Groups within groups</h2>
<pre class="mermaid">
architecture-beta
group api[API]
group public[Public API] in api
group private[Private API] in api
service serv1(server)[Server] in public
service serv2(server)[Server] in private
service db(database)[Database] in private
service gateway(internet)[Gateway] in api
serv1:B -- T:serv2
serv2:L -- R:db
serv1:L -- R:gateway
</pre>
<hr />
<h2>Default icon (?) from unknown icon name</h2>
<pre class="mermaid">
architecture-beta
service unknown(iconnamedoesntexist)[Unknown Icon]
</pre>
<hr />
<h2>Split Direction</h2>
<pre class="mermaid">
architecture-beta
service db(database)[Database]
service s3(disk)[Storage]
service serv1(server)[Server 1]
service serv2(server)[Server 2]
service disk(disk)[Disk]
db:L -- R:s3
serv1:L -- T:s3
serv2:L -- B:s3
serv1:T -- B:disk
</pre>
<hr />
<h2>Arrow Tests</h2>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L <--> R:servL
servC:R <--> L:servR
servC:T <--> B:servT
servC:B <--> T:servB
servL:T <--> L:servT
servL:B <--> L:servB
servR:T <--> R:servT
servR:B <--> R:servB
</pre>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L <--> R:servL
servC:R <--> L:servR
servC:T <--> B:servT
servC:B <--> T:servB
servT:L <--> T:servL
servB:L <--> B:servL
servT:R <--> T:servR
servB:R <--> B:servR
</pre>
<hr />
<h2>Group Edges</h2>
<pre class="mermaid">
architecture-beta
group left_group(cloud)[Left]
group right_group(cloud)[Right]
group top_group(cloud)[Top]
group bottom_group(cloud)[Bottom]
group center_group(cloud)[Center]
service left_disk(disk)[Disk] in left_group
service right_disk(disk)[Disk] in right_group
service top_disk(disk)[Disk] in top_group
service bottom_disk(disk)[Disk] in bottom_group
service center_disk(disk)[Disk] in center_group
left_disk{group}:R <--> L:center_disk{group}
right_disk{group}:L <--> R:center_disk{group}
top_disk{group}:B <--> T:center_disk{group}
bottom_disk{group}:T <--> B:center_disk{group}
</pre
>
<hr />
<h2>Edge Label Test</h2>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L -[Label]- R:servL
servC:R -[Label]- L:servR
servC:T -[Label]- B:servT
servC:B -[Label]- T:servB
servL:T -[Label]- L:servT
servL:B -[Label]- L:servB
servR:T -[Label]- R:servT
servR:B -[Label]- R:servB
</pre>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L -[Label that is Long]- R:servL
servC:R -[Label that is Long]- L:servR
servC:T -[Label that is Long]- B:servT
servC:B -[Label that is Long]- T:servB
servL:T -[Label that is Long]- L:servT
servL:B -[Label that is Long]- L:servB
servR:T -[Label that is Long]- R:servT
servR:B -[Label that is Long]- R:servB
</pre>
<hr />
<h2>Junction Demo</h2>
<pre class="mermaid">
architecture-beta
service left_disk(disk)[Disk]
service top_disk(disk)[Disk]
service bottom_disk(disk)[Disk]
service top_gateway(internet)[Gateway]
service bottom_gateway(internet)[Gateway]
junction juncC
junction juncR
left_disk:R -- L:juncC
top_disk:B -- T:juncC
bottom_disk:T -- B:juncC
juncC:R -- L:juncR
top_gateway:B -- T:juncR
bottom_gateway:T -- B:juncR
</pre>
<hr />
<h2>Junction Demo Groups</h2>
<pre class="mermaid">
architecture-beta
group left
group right
service left_disk(disk)[Disk] in left
service top_disk(disk)[Disk] in left
service bottom_disk(disk)[Disk] in left
service top_gateway(internet)[Gateway] in right
service bottom_gateway(internet)[Gateway] in right
junction juncC in left
junction juncR in right
left_disk:R -- L:juncC
top_disk:B -- T:juncC
bottom_disk:T -- B:juncC
top_gateway:B <-- T:juncR
bottom_gateway:T <-- B:juncR
juncC{group}:R --> L:juncR{group}
</pre>
<hr />
<h2>External Icons Demo</h2>
<pre class="mermaid">
architecture-beta
service s3(logos:aws-s3)[Cloud Store]
service ec2(logos:aws-ec2)[Server]
service api(logos:aws-api-gateway)[Api Gateway]
service fa(fa:image)[Font Awesome Icon]
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({
theme: 'neo-dark',
// handDrawnSeed: 12,
// look: 'handDrawn',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre',
// layout: 'elk',
// layout: 'fixed',
// htmlLabels: false,
//flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
// fontFamily: 'courier',
// fontFamily: 'arial',
// sequence: {
// actorFontFamily: 'courier',
// noteFontFamily: 'courier',
// messageFontFamily: 'courier',
// },
// fontSize: 12,
// logLevel: 3,
// securityLevel: 'loose',
});
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () =>
fetch('https://unpkg.com/@iconify-json/fa6-regular/icons.json').then((res) =>
res.json()
),
},
]);
</script>
</body>
</html>

280
demos/architecture-neo.html Normal file
View File

@@ -0,0 +1,280 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Architecture Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
<style>
div.mermaid {
/* font-family: 'trebuchet ms', verdana, arial; */
font-family: 'Courier New', Courier, monospace !important;
}
</style>
</head>
<body>
<h1>Architecture diagram demo</h1>
<h2>Simple diagram with groups</h2>
<pre class="mermaid">
architecture-beta
group api(cloud)[API]
service db(database)[Database] in api
service disk1(disk)[Storage] in api
service disk2(disk)[Storage] in api
service server(server)[Server] in api
service gateway(internet)[Gateway]
db:L -- R:server
disk1:T -- B:server
disk2:T -- B:db
server:T -- B:gateway
</pre>
<hr />
<h2>Groups within groups</h2>
<pre class="mermaid">
architecture-beta
group api[API]
group public[Public API] in api
group private[Private API] in api
service serv1(server)[Server] in public
service serv2(server)[Server] in private
service db(database)[Database] in private
service gateway(internet)[Gateway] in api
serv1:B -- T:serv2
serv2:L -- R:db
serv1:L -- R:gateway
</pre>
<hr />
<h2>Default icon (?) from unknown icon name</h2>
<pre class="mermaid">
architecture-beta
service unknown(iconnamedoesntexist)[Unknown Icon]
</pre>
<hr />
<h2>Split Direction</h2>
<pre class="mermaid">
architecture-beta
service db(database)[Database]
service s3(disk)[Storage]
service serv1(server)[Server 1]
service serv2(server)[Server 2]
service disk(disk)[Disk]
db:L -- R:s3
serv1:L -- T:s3
serv2:L -- B:s3
serv1:T -- B:disk
</pre>
<hr />
<h2>Arrow Tests</h2>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L <--> R:servL
servC:R <--> L:servR
servC:T <--> B:servT
servC:B <--> T:servB
servL:T <--> L:servT
servL:B <--> L:servB
servR:T <--> R:servT
servR:B <--> R:servB
</pre>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L <--> R:servL
servC:R <--> L:servR
servC:T <--> B:servT
servC:B <--> T:servB
servT:L <--> T:servL
servB:L <--> B:servL
servT:R <--> T:servR
servB:R <--> B:servR
</pre>
<hr />
<h2>Group Edges</h2>
<pre class="mermaid">
architecture-beta
group left_group(cloud)[Left]
group right_group(cloud)[Right]
group top_group(cloud)[Top]
group bottom_group(cloud)[Bottom]
group center_group(cloud)[Center]
service left_disk(disk)[Disk] in left_group
service right_disk(disk)[Disk] in right_group
service top_disk(disk)[Disk] in top_group
service bottom_disk(disk)[Disk] in bottom_group
service center_disk(disk)[Disk] in center_group
left_disk{group}:R <--> L:center_disk{group}
right_disk{group}:L <--> R:center_disk{group}
top_disk{group}:B <--> T:center_disk{group}
bottom_disk{group}:T <--> B:center_disk{group}
</pre
>
<hr />
<h2>Edge Label Test</h2>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L -[Label]- R:servL
servC:R -[Label]- L:servR
servC:T -[Label]- B:servT
servC:B -[Label]- T:servB
servL:T -[Label]- L:servT
servL:B -[Label]- L:servB
servR:T -[Label]- R:servT
servR:B -[Label]- R:servB
</pre>
<pre class="mermaid">
architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC:L -[Label that is Long]- R:servL
servC:R -[Label that is Long]- L:servR
servC:T -[Label that is Long]- B:servT
servC:B -[Label that is Long]- T:servB
servL:T -[Label that is Long]- L:servT
servL:B -[Label that is Long]- L:servB
servR:T -[Label that is Long]- R:servT
servR:B -[Label that is Long]- R:servB
</pre>
<hr />
<h2>Junction Demo</h2>
<pre class="mermaid">
architecture-beta
service left_disk(disk)[Disk]
service top_disk(disk)[Disk]
service bottom_disk(disk)[Disk]
service top_gateway(internet)[Gateway]
service bottom_gateway(internet)[Gateway]
junction juncC
junction juncR
left_disk:R -- L:juncC
top_disk:B -- T:juncC
bottom_disk:T -- B:juncC
juncC:R -- L:juncR
top_gateway:B -- T:juncR
bottom_gateway:T -- B:juncR
</pre>
<hr />
<h2>Junction Demo Groups</h2>
<pre class="mermaid">
architecture-beta
group left
group right
service left_disk(disk)[Disk] in left
service top_disk(disk)[Disk] in left
service bottom_disk(disk)[Disk] in left
service top_gateway(internet)[Gateway] in right
service bottom_gateway(internet)[Gateway] in right
junction juncC in left
junction juncR in right
left_disk:R -- L:juncC
top_disk:B -- T:juncC
bottom_disk:T -- B:juncC
top_gateway:B <-- T:juncR
bottom_gateway:T <-- B:juncR
juncC{group}:R --> L:juncR{group}
</pre>
<hr />
<h2>External Icons Demo</h2>
<pre class="mermaid">
architecture-beta
service s3(logos:aws-s3)[Cloud Store]
service ec2(logos:aws-ec2)[Server]
service api(logos:aws-api-gateway)[Api Gateway]
service fa(fa:image)[Font Awesome Icon]
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({
theme: 'neo',
// handDrawnSeed: 12,
// look: 'handDrawn',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre',
// layout: 'elk',
// layout: 'fixed',
// htmlLabels: false,
//flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
// fontFamily: 'courier',
// fontFamily: 'arial',
// sequence: {
// actorFontFamily: 'courier',
// noteFontFamily: 'courier',
// messageFontFamily: 'courier',
// },
// fontSize: 12,
// logLevel: 3,
// securityLevel: 'loose',
});
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () =>
fetch('https://unpkg.com/@iconify-json/fa6-regular/icons.json').then((res) =>
res.json()
),
},
]);
</script>
</body>
</html>

View File

@@ -91,6 +91,18 @@
<li>
<h2><a href="./architecture.html">Architecture</a></h2>
</li>
<li>
<h2><a href="./architecture-neo.html">Architecture-neo</a></h2>
</li>
<li>
<h2><a href="./architecture-neo-dark.html">Architecture-neo-dark</a></h2>
</li>
<li>
<h2><a href="./architecture-mermaid-chart.html">Architecture-mermaid-chart</a></h2>
</li>
<li>
<h2><a href="./architecture-dark.html">Architecture-dark</a></h2>
</li>
</ul>
</body>
</html>

View File

@@ -4,7 +4,7 @@
>
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/README.md](../../../packages/mermaid/src/docs/config/setup/README.md).
# mermaid
# @mermaid-chart/mermaid
## Modules

View File

@@ -127,7 +127,7 @@ Error.prepareStackTrace
#### Defined in
node_modules/.pnpm/@types+node\@20.16.11/node_modules/@types/node/globals.d.ts:98
node_modules/.pnpm/@types+node\@20.16.5/node_modules/@types/node/globals.d.ts:98
---
@@ -141,7 +141,7 @@ Error.stackTraceLimit
#### Defined in
node_modules/.pnpm/@types+node\@20.16.11/node_modules/@types/node/globals.d.ts:100
node_modules/.pnpm/@types+node\@20.16.5/node_modules/@types/node/globals.d.ts:100
## Methods
@@ -168,4 +168,4 @@ Error.captureStackTrace
#### Defined in
node_modules/.pnpm/@types+node\@20.16.11/node_modules/@types/node/globals.d.ts:91
node_modules/.pnpm/@types+node\@20.16.5/node_modules/@types/node/globals.d.ts:91

View File

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

View File

@@ -16,7 +16,7 @@
#### 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)
[packages/mermaid/src/rendering-util/render.ts:25](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L25)
---
@@ -26,7 +26,7 @@
#### 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)
[packages/mermaid/src/rendering-util/render.ts:24](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L24)
---
@@ -36,4 +36,4 @@
#### 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)
[packages/mermaid/src/rendering-util/render.ts:23](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/render.ts#L23)

View File

@@ -122,7 +122,7 @@ This function should be called before the run function.
### mermaidAPI
**mermaidAPI**: `Readonly`<{ `defaultConfig`: [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.defaultConfig; `getConfig`: () => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.getConfig; `getDiagramFromText`: (`text`: `string`, `metadata`: `Pick`<`DiagramMetadata`, `"title"`>) => `Promise`<`Diagram`> ; `getSiteConfig`: () => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`userOptions`: [`MermaidConfig`](mermaid.MermaidConfig.md)) => `void` ; `parse`: (`text`: `string`, `parseOptions`: [`ParseOptions`](mermaid.ParseOptions.md) & { `suppressErrors`: `true` }) => `Promise`<[`ParseResult`](mermaid.ParseResult.md) | `false`>(`text`: `string`, `parseOptions?`: [`ParseOptions`](mermaid.ParseOptions.md)) => `Promise`<[`ParseResult`](mermaid.ParseResult.md)> ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`) => `Promise`<[`RenderResult`](mermaid.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: [`MermaidConfig`](mermaid.MermaidConfig.md)) => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.setConfig; `updateSiteConfig`: (`conf`: [`MermaidConfig`](mermaid.MermaidConfig.md)) => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.updateSiteConfig }>
**mermaidAPI**: `Readonly`<{ `defaultConfig`: [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.defaultConfig; `getConfig`: () => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.getConfig; `getDiagramFromText`: (`text`: `string`, `metadata`: `Pick`<`DiagramMetadata`, `"title"`>) => `Promise`<`Diagram`> ; `getSiteConfig`: () => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`userOptions`: [`MermaidConfig`](mermaid.MermaidConfig.md)) => `void` ; `parse`: (`text`: `string`, `parseOptions`: [`ParseOptions`](mermaid.ParseOptions.md) & { `suppressErrors`: `true` }) => `Promise`<[`ParseResult`](mermaid.ParseResult.md) & { `error?`: `unknown` }>(`text`: `string`, `parseOptions?`: [`ParseOptions`](mermaid.ParseOptions.md)) => `Promise`<[`ParseResult`](mermaid.ParseResult.md)> ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`, `positions?`: `Positions`) => `Promise`<[`RenderResult`](mermaid.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: [`MermaidConfig`](mermaid.MermaidConfig.md)) => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.setConfig; `updateSiteConfig`: (`conf`: [`MermaidConfig`](mermaid.MermaidConfig.md)) => [`MermaidConfig`](mermaid.MermaidConfig.md) = configApi.updateSiteConfig }>
**`Deprecated`**
@@ -136,11 +136,11 @@ Use [parse](mermaid.Mermaid.md#parse) and [render](mermaid.Mermaid.md#render) in
### parse
**parse**: (`text`: `string`, `parseOptions`: [`ParseOptions`](mermaid.ParseOptions.md) & { `suppressErrors`: `true` }) => `Promise`<[`ParseResult`](mermaid.ParseResult.md) | `false`>(`text`: `string`, `parseOptions?`: [`ParseOptions`](mermaid.ParseOptions.md)) => `Promise`<[`ParseResult`](mermaid.ParseResult.md)>
**parse**: (`text`: `string`, `parseOptions`: [`ParseOptions`](mermaid.ParseOptions.md) & { `suppressErrors`: `true` }) => `Promise`<[`ParseResult`](mermaid.ParseResult.md) & { `error?`: `unknown` }>(`text`: `string`, `parseOptions?`: [`ParseOptions`](mermaid.ParseOptions.md)) => `Promise`<[`ParseResult`](mermaid.ParseResult.md)>
#### Type declaration
▸ (`text`, `parseOptions`): `Promise`<[`ParseResult`](mermaid.ParseResult.md) | `false`>
▸ (`text`, `parseOptions`): `Promise`<[`ParseResult`](mermaid.ParseResult.md) & { `error?`: `unknown` }>
Parse the text and validate the syntax.
@@ -153,7 +153,7 @@ Parse the text and validate the syntax.
##### Returns
`Promise`<[`ParseResult`](mermaid.ParseResult.md) | `false`>
`Promise`<[`ParseResult`](mermaid.ParseResult.md) & { `error?`: `unknown` }>
An object with the `diagramType` set to type of the diagram if valid. Otherwise `false` if parseOptions.suppressErrors is `true`.
@@ -272,19 +272,20 @@ Used to register external diagram types.
### render
**render**: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`) => `Promise`<[`RenderResult`](mermaid.RenderResult.md)>
**render**: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`, `positions?`: `Positions`) => `Promise`<[`RenderResult`](mermaid.RenderResult.md)>
#### Type declaration
▸ (`id`, `text`, `svgContainingElement?`): `Promise`<[`RenderResult`](mermaid.RenderResult.md)>
▸ (`id`, `text`, `svgContainingElement?`, `positions?`): `Promise`<[`RenderResult`](mermaid.RenderResult.md)>
##### Parameters
| Name | Type |
| :---------------------- | :-------- |
| `id` | `string` |
| `text` | `string` |
| `svgContainingElement?` | `Element` |
| Name | Type |
| :---------------------- | :---------- |
| `id` | `string` |
| `text` | `string` |
| `svgContainingElement?` | `Element` |
| `positions?` | `Positions` |
##### Returns

View File

@@ -16,7 +16,7 @@
#### Defined in
[packages/mermaid/src/config.type.ts:122](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L122)
[packages/mermaid/src/config.type.ts:133](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L133)
---
@@ -26,7 +26,7 @@
#### Defined in
[packages/mermaid/src/config.type.ts:194](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L194)
[packages/mermaid/src/config.type.ts:205](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L205)
---
@@ -39,7 +39,7 @@ This matters if you are using base tag settings.
#### Defined in
[packages/mermaid/src/config.type.ts:141](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L141)
[packages/mermaid/src/config.type.ts:152](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L152)
---
@@ -49,7 +49,7 @@ This matters if you are using base tag settings.
#### Defined in
[packages/mermaid/src/config.type.ts:201](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L201)
[packages/mermaid/src/config.type.ts:212](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L212)
---
@@ -59,7 +59,7 @@ This matters if you are using base tag settings.
#### Defined in
[packages/mermaid/src/config.type.ts:198](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L198)
[packages/mermaid/src/config.type.ts:209](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L209)
---
@@ -69,7 +69,7 @@ This matters if you are using base tag settings.
#### Defined in
[packages/mermaid/src/config.type.ts:187](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L187)
[packages/mermaid/src/config.type.ts:198](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L198)
---
@@ -79,7 +79,7 @@ This matters if you are using base tag settings.
#### Defined in
[packages/mermaid/src/config.type.ts:113](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L113)
[packages/mermaid/src/config.type.ts:124](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L124)
---
@@ -93,7 +93,7 @@ You can set this attribute to base the seed on a static 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)
[packages/mermaid/src/config.type.ts:192](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L192)
---
@@ -111,7 +111,7 @@ should not change unless content is changed.
#### Defined in
[packages/mermaid/src/config.type.ts:174](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L174)
[packages/mermaid/src/config.type.ts:185](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L185)
---
@@ -121,7 +121,7 @@ should not change unless content is changed.
#### Defined in
[packages/mermaid/src/config.type.ts:202](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L202)
[packages/mermaid/src/config.type.ts:213](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L213)
---
@@ -139,7 +139,7 @@ should not change unless content is changed.
#### Defined in
[packages/mermaid/src/config.type.ts:91](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L91)
[packages/mermaid/src/config.type.ts:102](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L102)
---
@@ -149,7 +149,7 @@ should not change unless content is changed.
#### Defined in
[packages/mermaid/src/config.type.ts:189](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L189)
[packages/mermaid/src/config.type.ts:200](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L200)
---
@@ -159,7 +159,7 @@ should not change unless content is changed.
#### Defined in
[packages/mermaid/src/config.type.ts:182](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L182)
[packages/mermaid/src/config.type.ts:193](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L193)
---
@@ -173,7 +173,7 @@ See <https://developer.mozilla.org/en-US/docs/Web/CSS/font-family>
#### Defined in
[packages/mermaid/src/config.type.ts:121](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L121)
[packages/mermaid/src/config.type.ts:132](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L132)
---
@@ -183,7 +183,7 @@ See <https://developer.mozilla.org/en-US/docs/Web/CSS/font-family>
#### Defined in
[packages/mermaid/src/config.type.ts:204](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L204)
[packages/mermaid/src/config.type.ts:215](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L215)
---
@@ -197,7 +197,7 @@ If set to true, ignores legacyMathML.
#### Defined in
[packages/mermaid/src/config.type.ts:163](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L163)
[packages/mermaid/src/config.type.ts:174](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L174)
---
@@ -207,7 +207,7 @@ If set to true, ignores legacyMathML.
#### Defined in
[packages/mermaid/src/config.type.ts:184](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L184)
[packages/mermaid/src/config.type.ts:195](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L195)
---
@@ -217,7 +217,7 @@ If set to true, ignores legacyMathML.
#### Defined in
[packages/mermaid/src/config.type.ts:197](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L197)
[packages/mermaid/src/config.type.ts:208](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L208)
---
@@ -229,7 +229,7 @@ Defines the seed to be used when using handDrawn look. This is important for the
#### Defined in
[packages/mermaid/src/config.type.ts:76](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L76)
[packages/mermaid/src/config.type.ts:87](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L87)
---
@@ -239,7 +239,7 @@ Defines the seed to be used when using handDrawn look. This is important for the
#### Defined in
[packages/mermaid/src/config.type.ts:114](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L114)
[packages/mermaid/src/config.type.ts:125](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L125)
---
@@ -249,7 +249,7 @@ Defines the seed to be used when using handDrawn look. This is important for the
#### Defined in
[packages/mermaid/src/config.type.ts:185](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L185)
[packages/mermaid/src/config.type.ts:196](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L196)
---
@@ -259,7 +259,7 @@ Defines the seed to be used when using handDrawn look. This is important for the
#### Defined in
[packages/mermaid/src/config.type.ts:196](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L196)
[packages/mermaid/src/config.type.ts:207](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L207)
---
@@ -271,7 +271,7 @@ Defines which layout algorithm to use for rendering the diagram.
#### Defined in
[packages/mermaid/src/config.type.ts:81](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L81)
[packages/mermaid/src/config.type.ts:92](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L92)
---
@@ -286,7 +286,7 @@ fall back to legacy rendering for KaTeX.
#### Defined in
[packages/mermaid/src/config.type.ts:156](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L156)
[packages/mermaid/src/config.type.ts:167](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L167)
---
@@ -298,19 +298,19 @@ This option decides the amount of logging to be used by mermaid.
#### Defined in
[packages/mermaid/src/config.type.ts:127](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L127)
[packages/mermaid/src/config.type.ts:138](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L138)
---
### look
`Optional` **look**: `"classic"` | `"handDrawn"`
`Optional` **look**: `"neo"` | `"classic"` | `"handDrawn"`
Defines which main look to use for the diagram.
#### Defined in
[packages/mermaid/src/config.type.ts:71](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L71)
[packages/mermaid/src/config.type.ts:82](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L82)
---
@@ -320,7 +320,7 @@ Defines which main look to use for the diagram.
#### Defined in
[packages/mermaid/src/config.type.ts:205](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L205)
[packages/mermaid/src/config.type.ts:216](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L216)
---
@@ -332,7 +332,7 @@ Defines the maximum number of edges that can be drawn in a graph.
#### Defined in
[packages/mermaid/src/config.type.ts:90](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L90)
[packages/mermaid/src/config.type.ts:101](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L101)
---
@@ -344,7 +344,7 @@ The maximum allowed size of the users text diagram
#### Defined in
[packages/mermaid/src/config.type.ts:85](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L85)
[packages/mermaid/src/config.type.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L96)
---
@@ -354,7 +354,7 @@ The maximum allowed size of the users text diagram
#### Defined in
[packages/mermaid/src/config.type.ts:195](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L195)
[packages/mermaid/src/config.type.ts:206](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L206)
---
@@ -364,7 +364,7 @@ The maximum allowed size of the users text diagram
#### Defined in
[packages/mermaid/src/config.type.ts:200](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L200)
[packages/mermaid/src/config.type.ts:211](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L211)
---
@@ -374,7 +374,7 @@ The maximum allowed size of the users text diagram
#### Defined in
[packages/mermaid/src/config.type.ts:190](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L190)
[packages/mermaid/src/config.type.ts:201](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L201)
---
@@ -384,7 +384,7 @@ The maximum allowed size of the users text diagram
#### Defined in
[packages/mermaid/src/config.type.ts:191](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L191)
[packages/mermaid/src/config.type.ts:202](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L202)
---
@@ -394,7 +394,7 @@ The maximum allowed size of the users text diagram
#### Defined in
[packages/mermaid/src/config.type.ts:193](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L193)
[packages/mermaid/src/config.type.ts:204](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L204)
---
@@ -404,7 +404,7 @@ The maximum allowed size of the users text diagram
#### Defined in
[packages/mermaid/src/config.type.ts:199](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L199)
[packages/mermaid/src/config.type.ts:210](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L210)
---
@@ -418,7 +418,7 @@ This prevents malicious graph directives from overriding a site's default securi
#### Defined in
[packages/mermaid/src/config.type.ts:148](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L148)
[packages/mermaid/src/config.type.ts:159](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L159)
---
@@ -430,7 +430,7 @@ Level of trust for parsed diagram
#### Defined in
[packages/mermaid/src/config.type.ts:131](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L131)
[packages/mermaid/src/config.type.ts:142](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L142)
---
@@ -440,7 +440,7 @@ Level of trust for parsed diagram
#### Defined in
[packages/mermaid/src/config.type.ts:183](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L183)
[packages/mermaid/src/config.type.ts:194](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L194)
---
@@ -452,7 +452,7 @@ Dictates whether mermaid starts on Page load
#### Defined in
[packages/mermaid/src/config.type.ts:135](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L135)
[packages/mermaid/src/config.type.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L146)
---
@@ -462,7 +462,7 @@ Dictates whether mermaid starts on Page load
#### Defined in
[packages/mermaid/src/config.type.ts:188](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L188)
[packages/mermaid/src/config.type.ts:199](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L199)
---
@@ -475,13 +475,13 @@ This is useful when you want to control how to handle syntax errors in your appl
#### Defined in
[packages/mermaid/src/config.type.ts:211](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L211)
[packages/mermaid/src/config.type.ts:222](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L222)
---
### theme
`Optional` **theme**: `"default"` | `"base"` | `"dark"` | `"forest"` | `"neutral"` | `"null"`
`Optional` **theme**: `"default"` | `"base"` | `"dark"` | `"forest"` | `"neutral"` | `"neo"` | `"neo-dark"` | `"redux"` | `"redux-dark"` | `"mc"` | `"null"`
Theme, the CSS style sheet.
You may also use `themeCSS` to override this value.
@@ -498,7 +498,7 @@ You may also use `themeCSS` to override this value.
#### Defined in
[packages/mermaid/src/config.type.ts:66](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L66)
[packages/mermaid/src/config.type.ts:77](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L77)
---
@@ -508,7 +508,7 @@ You may also use `themeCSS` to override this value.
#### Defined in
[packages/mermaid/src/config.type.ts:65](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L65)
[packages/mermaid/src/config.type.ts:76](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L76)
---
@@ -518,7 +518,7 @@ You may also use `themeCSS` to override this value.
#### Defined in
[packages/mermaid/src/config.type.ts:186](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L186)
[packages/mermaid/src/config.type.ts:197](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L197)
---
@@ -528,7 +528,7 @@ You may also use `themeCSS` to override this value.
#### Defined in
[packages/mermaid/src/config.type.ts:203](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L203)
[packages/mermaid/src/config.type.ts:214](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L214)
---
@@ -538,4 +538,4 @@ You may also use `themeCSS` to override this value.
#### Defined in
[packages/mermaid/src/config.type.ts:192](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L192)
[packages/mermaid/src/config.type.ts:203](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts#L203)

View File

@@ -19,4 +19,4 @@ The `parseError` function will not be called.
#### Defined in
[packages/mermaid/src/types.ts:64](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L64)
[packages/mermaid/src/types.ts:66](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L66)

View File

@@ -10,6 +10,18 @@
## Properties
### code
**code**: `string`
The mermaid code after extracting the config.
#### Defined in
[packages/mermaid/src/types.ts:74](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L74)
---
### config
**config**: [`MermaidConfig`](mermaid.MermaidConfig.md)
@@ -18,16 +30,46 @@ The config passed as YAML frontmatter or directives
#### Defined in
[packages/mermaid/src/types.ts:75](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L75)
[packages/mermaid/src/types.ts:78](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L78)
---
### diagramType
### diagram
**diagramType**: `string`
The diagram type, e.g. 'flowchart', 'sequence', etc.
`Optional` **diagram**: `Diagram`
#### Defined in
[packages/mermaid/src/types.ts:71](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L71)
[packages/mermaid/src/types.ts:80](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L80)
---
### error
`Optional` **error**: `unknown`
The error that occurred during parsing, if any.
#### Defined in
[packages/mermaid/src/types.ts:84](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L84)
---
### success
**success**: `boolean`
#### Defined in
[packages/mermaid/src/types.ts:70](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L70)
---
### title
`Optional` **title**: `string`
#### Defined in
[packages/mermaid/src/types.ts:79](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L79)

View File

@@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
#### Defined in
[packages/mermaid/src/types.ts:103](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L103)
[packages/mermaid/src/types.ts:113](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L113)
---
@@ -51,7 +51,7 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
#### Defined in
[packages/mermaid/src/types.ts:93](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L93)
[packages/mermaid/src/types.ts:103](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L103)
---
@@ -63,4 +63,4 @@ The svg code for the rendered graph.
#### Defined in
[packages/mermaid/src/types.ts:89](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L89)
[packages/mermaid/src/types.ts:99](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L99)

View File

@@ -67,7 +67,7 @@
#### 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)
[packages/mermaid/src/diagram-api/types.ts:157](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L157)
---
@@ -77,7 +77,7 @@
#### Defined in
[packages/mermaid/src/diagram-api/types.ts:132](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L132)
[packages/mermaid/src/diagram-api/types.ts:159](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L159)
## Variables
@@ -88,3 +88,77 @@
#### Defined in
[packages/mermaid/src/mermaid.ts:442](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaid.ts#L442)
## Functions
### calcIntersect
**calcIntersect**(`nodeId`, `point`): `Point` | `Promise`<`Point`>
#### Parameters
| Name | Type |
| :------- | :------- |
| `nodeId` | `string` |
| `point` | `Point` |
#### Returns
`Point` | `Promise`<`Point`>
#### Defined in
[packages/mermaid/src/rendering-util/layout-algorithms/fixed/index.js:172](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/layout-algorithms/fixed/index.js#L172)
---
### calcIntersections
**calcIntersections**(`startNodeId`, `endNodeId`, `startNodeSize`, `endNodeSize`): `IntersectionPoint`\[]
#### Parameters
| Name | Type |
| :-------------------- | :---------------------- |
| `startNodeId` | `string` |
| `endNodeId` | `undefined` \| `string` |
| `startNodeSize` | `NodePosition` |
| `endNodeSize` | `Object` |
| `endNodeSize.height?` | `number` |
| `endNodeSize.width?` | `number` |
| `endNodeSize.x` | `number` |
| `endNodeSize.y` | `number` |
#### Returns
`IntersectionPoint`\[]
**`Throws`**
If the start node doesn't exist in the nodeDB (e.g. `render` hasn't been called yet)
#### Defined in
[packages/mermaid/src/rendering-util/layout-algorithms/fixed/index.js:115](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/layout-algorithms/fixed/index.js#L115)
---
### calcNodeIntersections
**calcNodeIntersections**(`targetNodeId`, `_node1`, `_node2`): `IntersectionPoint`\[] | `Promise`<`IntersectionPoint`\[]>
#### Parameters
| Name | Type |
| :------------- | :------------------------------------------------------------------------------------------------ |
| `targetNodeId` | `any` |
| `_node1` | `Pick`<`Node`, `"width"` \| `"height"` \| `"x"` \| `"y"` \| `"id"` \| `"shape"` \| `"intersect"`> |
| `_node2` | `Pick`<`Node`, `"width"` \| `"height"` \| `"x"` \| `"y"` \| `"id"` \| `"shape"` \| `"intersect"`> |
#### Returns
`IntersectionPoint`\[] | `Promise`<`IntersectionPoint`\[]>
#### Defined in
[packages/mermaid/src/rendering-util/layout-algorithms/fixed/index.js:78](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/layout-algorithms/fixed/index.js#L78)

View File

@@ -43,7 +43,7 @@
},
"devDependencies": {
"concurrently": "^8.2.2",
"mermaid": "workspace:*",
"@mermaid-chart/mermaid": "workspace:*",
"rimraf": "^5.0.5"
},
"files": [

View File

@@ -1,4 +1,4 @@
import type { ExternalDiagramDefinition } from 'mermaid';
import type { ExternalDiagramDefinition } from '@mermaid-chart/mermaid';
const id = 'example-diagram';

View File

@@ -1,6 +1,6 @@
{
"name": "@mermaid-js/layout-elk",
"version": "0.1.7",
"name": "@mermaid-chart/layout-elk",
"version": "0.1.7-b.1",
"description": "ELK layout engine for mermaid",
"module": "dist/mermaid-layout-elk.core.mjs",
"types": "dist/layouts.d.ts",
@@ -34,10 +34,10 @@
},
"devDependencies": {
"@types/d3": "^7.4.3",
"mermaid": "workspace:^"
"@mermaid-chart/mermaid": "workspace:^"
},
"peerDependencies": {
"mermaid": "^11.0.0"
"@mermaid-chart/mermaid": "^11.0.0"
},
"files": [
"dist"

View File

@@ -1,4 +1,4 @@
import type { LayoutLoaderDefinition } from 'mermaid';
import type { LayoutLoaderDefinition } from '@mermaid-chart/mermaid';
const loader = async () => await import(`./render.js`);
const algos = ['elk.stress', 'elk.force', 'elk.mrtree', 'elk.sporeOverlap'];

View File

@@ -1,10 +1,18 @@
import type {
InternalHelpers,
LayoutData,
RenderOptions,
SVG,
SVGGroup,
} from '@mermaid-chart/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';
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;
interface LabelData {
width: number;
height: number;
@@ -17,7 +25,16 @@ interface NodeWithVertex extends Omit<Node, 'domId'> {
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));
}
export const render = async (
data4Layout: LayoutData,
svg: SVG,
@@ -51,17 +68,17 @@ export const render = async (
// Add the element to the DOM
if (!node.isGroup) {
const child: NodeWithVertex = {
...node,
};
graph.children.push(child);
nodeDb[node.id] = child;
// const child: NodeWithVertex = {
// ...node,
// };
graph.children.push(node);
nodeDb[node.id] = node;
const childNodeEl = await insertNode(nodeEl, node, { config, dir: node.dir });
const boundingBox = childNodeEl.node()!.getBBox();
child.domId = childNodeEl;
child.width = boundingBox.width;
child.height = boundingBox.height;
node.domId = childNodeEl;
node.width = boundingBox.width;
node.height = boundingBox.height;
} else {
// A subgraph
const child: NodeWithVertex & { children: NodeWithVertex[] } = {
@@ -289,7 +306,7 @@ 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;
@@ -459,302 +476,6 @@ export const render = async (
}
}
function intersectLine(
p1: { y: number; x: number },
p2: { y: number; x: number },
q1: { x: any; y: any },
q2: { x: any; y: any }
) {
log.debug('UIO intersectLine', p1, p2, q1, q2);
// Algorithm from J. Avro, (ed.) Graphics Gems, No 2, Morgan Kaufmann, 1994,
// p7 and p473.
// let a1, a2, b1, b2, c1, c2;
// let r1, r2, r3, r4;
// let denom, offset, num;
// let x, y;
// Compute a1, b1, c1, where line joining points 1 and 2 is F(x,y) = a1 x +
// b1 y + c1 = 0.
const a1 = p2.y - p1.y;
const b1 = p1.x - p2.x;
const c1 = p2.x * p1.y - p1.x * p2.y;
// Compute r3 and r4.
const r3 = a1 * q1.x + b1 * q1.y + c1;
const r4 = a1 * q2.x + b1 * q2.y + c1;
const epsilon = 1e-6;
// Check signs of r3 and r4. If both point 3 and point 4 lie on
// same side of line 1, the line segments do not intersect.
if (r3 !== 0 && r4 !== 0 && sameSign(r3, r4)) {
return /*DON'T_INTERSECT*/;
}
// Compute a2, b2, c2 where line joining points 3 and 4 is G(x,y) = a2 x + b2 y + c2 = 0
const a2 = q2.y - q1.y;
const b2 = q1.x - q2.x;
const c2 = q2.x * q1.y - q1.x * q2.y;
// Compute r1 and r2
const r1 = a2 * p1.x + b2 * p1.y + c2;
const r2 = a2 * p2.x + b2 * p2.y + c2;
// Check signs of r1 and r2. If both point 1 and point 2 lie
// on same side of second line segment, the line segments do
// not intersect.
if (Math.abs(r1) < epsilon && Math.abs(r2) < epsilon && sameSign(r1, r2)) {
return /*DON'T_INTERSECT*/;
}
// Line segments intersect: compute intersection point.
const denom = a1 * b2 - a2 * b1;
if (denom === 0) {
return /*COLLINEAR*/;
}
const offset = Math.abs(denom / 2);
// The denom/2 is to get rounding instead of truncating. It
// is added or subtracted to the numerator, depending upon the
// sign of the numerator.
let num = b1 * c2 - b2 * c1;
const x = num < 0 ? (num - offset) / denom : (num + offset) / denom;
num = a2 * c1 - a1 * c2;
const y = num < 0 ? (num - offset) / denom : (num + offset) / denom;
return { x: x, y: y };
}
function sameSign(r1: number, r2: number) {
return r1 * r2 > 0;
}
const diamondIntersection = (
bounds: { x: any; y: any; width: any; height: any },
outsidePoint: { x: number; y: number },
insidePoint: any
) => {
const x1 = bounds.x;
const y1 = bounds.y;
const w = bounds.width; //+ bounds.padding;
const h = bounds.height; // + bounds.padding;
const polyPoints = [
{ x: x1, y: y1 - h / 2 },
{ x: x1 + w / 2, y: y1 },
{ x: x1, y: y1 + h / 2 },
{ x: x1 - w / 2, y: y1 },
];
log.debug(
`APA16 diamondIntersection calc abc89:
outsidePoint: ${JSON.stringify(outsidePoint)}
insidePoint : ${JSON.stringify(insidePoint)}
node-bounds : x:${bounds.x} y:${bounds.y} w:${bounds.width} h:${bounds.height}`,
JSON.stringify(polyPoints)
);
const intersections = [];
let minX = Number.POSITIVE_INFINITY;
let minY = Number.POSITIVE_INFINITY;
polyPoints.forEach(function (entry) {
minX = Math.min(minX, entry.x);
minY = Math.min(minY, entry.y);
});
const left = x1 - w / 2 - minX;
const top = y1 - h / 2 - minY;
for (let i = 0; i < polyPoints.length; i++) {
const p1 = polyPoints[i];
const p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0];
const intersect = intersectLine(
bounds,
outsidePoint,
{ x: left + p1.x, y: top + p1.y },
{ x: left + p2.x, y: top + p2.y }
);
if (intersect) {
intersections.push(intersect);
}
}
if (!intersections.length) {
return bounds;
}
log.debug('UIO intersections', intersections);
if (intersections.length > 1) {
// More intersections, find the one nearest to edge end point
intersections.sort(function (p, q) {
const pdx = p.x - outsidePoint.x;
const pdy = p.y - outsidePoint.y;
const distp = Math.sqrt(pdx * pdx + pdy * pdy);
const qdx = q.x - outsidePoint.x;
const qdy = q.y - outsidePoint.y;
const distq = Math.sqrt(qdx * qdx + qdy * qdy);
return distp < distq ? -1 : distp === distq ? 0 : 1;
});
}
return intersections[0];
};
const intersection = (
node: { x: any; y: any; width: number; height: number },
outsidePoint: { x: number; y: number },
insidePoint: { x: number; y: number }
) => {
log.debug(`intersection calc abc89:
outsidePoint: ${JSON.stringify(outsidePoint)}
insidePoint : ${JSON.stringify(insidePoint)}
node : x:${node.x} y:${node.y} w:${node.width} h:${node.height}`);
const x = node.x;
const y = node.y;
const dx = Math.abs(x - insidePoint.x);
// const dy = Math.abs(y - insidePoint.y);
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,
};
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;
}
log.debug(`abc89 topp/bott calc, Q ${Q}, q ${q}, R ${R}, r ${r}`, res); // cspell: disable-line
return res;
} else {
// Intersection onn sides of rect
if (insidePoint.x < outsidePoint.x) {
r = outsidePoint.x - w - x;
} else {
// r = outsidePoint.x - w - x;
r = x - w - outsidePoint.x;
}
const q = (Q * r) / R;
// OK let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x + dx - w;
// OK let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : outsidePoint.x + r;
let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x - R + r;
// let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : outsidePoint.x + r;
let _y = insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q;
log.debug(`sides calc abc89, Q ${Q}, q ${q}, R ${R}, r ${r}`, { _x, _y });
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 };
}
};
const outsideNode = (
node: { x: any; y: any; width: number; height: number },
point: { x: number; y: number }
) => {
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;
if (dx >= w || dy >= h) {
return true;
}
return false;
};
/**
* This function will page a path and node where the last point(s) in the path is inside the node
* and return an update path ending by the border of the node.
*/
const cutPathAtIntersect = (
_points: any[],
bounds: { x: any; y: any; width: any; height: any; padding: any },
isDiamond: boolean
) => {
log.debug('APA18 cutPathAtIntersect Points:', _points, 'node:', bounds, 'isDiamond', isDiamond);
const points: any[] = [];
let lastPointOutside = _points[0];
let isInside = false;
_points.forEach((point: any) => {
// check if point is inside the boundary rect
if (!outsideNode(bounds, point) && !isInside) {
// First point inside the rect found
// Calc the intersection coord between the point anf the last point outside the rect
let inter;
if (isDiamond) {
const inter2 = diamondIntersection(bounds, lastPointOutside, point);
const distance = Math.sqrt(
(lastPointOutside.x - inter2.x) ** 2 + (lastPointOutside.y - inter2.y) ** 2
);
if (distance > 1) {
inter = inter2;
}
}
if (!inter) {
inter = intersection(bounds, lastPointOutside, point);
}
// Check case where the intersection is the same as the last point
let pointPresent = false;
points.forEach((p) => {
pointPresent = pointPresent || (p.x === inter.x && p.y === inter.y);
});
// if (!pointPresent) {
if (!points.some((e) => e.x === inter.x && e.y === inter.y)) {
points.push(inter);
} else {
log.debug('abc88 no intersect', inter, points);
}
// points.push(inter);
isInside = true;
} else {
// Outside
log.debug('abc88 outside', point, lastPointOutside, points);
lastPointOutside = point;
// points.push(point);
if (!isInside) {
points.push(point);
}
}
});
return points;
};
// @ts-ignore - ELK is not typed
const elk = new ELK();
const element = svg.select('g');
@@ -766,20 +487,30 @@ export const render = async (
id: 'root',
layoutOptions: {
'elk.hierarchyHandling': 'INCLUDE_CHILDREN',
'elk.algorithm': algorithm,
'nodePlacement.strategy': data4Layout.config.elk?.nodePlacementStrategy,
'elk.layered.priority.direction': 10,
'elk.algorithm': 'elk.layered',
// 'elk.algorithm': 'elk.stress',
// 'partitioning.activate': true,
// 'nodePlacement.strategy': data4Layout.config.elk?.nodePlacementStrategy,
'elk.layered.nodePlacement.strategy': 'INTERACTIVE',
// 'nodePlacement.strategy': 'LINEAR_SEGMENTS',
'elk.layered.mergeEdges': data4Layout.config.elk?.mergeEdges,
'elk.direction': 'DOWN',
'spacing.baseValue': 35,
'elk.layered.unnecessaryBendpoints': true,
'elk.layered.cycleBreaking.strategy': data4Layout.config.elk?.cycleBreakingStrategy,
// 'spacing.nodeNode': 20,
// 'spacing.nodeNodeBetweenLayers': 25,
// 'spacing.edgeNode': 20,
// 'spacing.edgeNodeBetweenLayers': 10,
// 'spacing.edgeEdge': 10,
// 'spacing.edgeEdgeBetweenLayers': 20,
// 'spacing.nodeSelfLoop': 20,
// 'elk.layered.unnecessaryBendpoints': true,
// 'elk.layered.cycleBreaking.strategy': data4Layout.config.elk?.cycleBreakingStrategy,
// 'elk.layered.cycleBreaking.strategy': 'INTERACTIVE',
// 'elk.layered.layering.strategy': 'MIN_WIDTH',
// 'layering.strategy': 'SIMPLE',
// 'layering.nodePromotion.strategy': 'NODECOUNT_PERCENTAGE',
// 'elk.topdown.nodeType': 'PARALLEL_NODE',
'spacing.nodeNode': 20,
'spacing.nodeNodeBetweenLayers': 25,
'spacing.edgeNode': 20,
'spacing.edgeNodeBetweenLayers': 20,
'spacing.edgeEdge': 10,
'spacing.edgeEdgeBetweenLayers': 20,
'spacing.nodeSelfLoop': 20,
// Tweaking options
// 'elk.layered.nodePlacement.favorStraightEdges': true,
@@ -790,14 +521,21 @@ export const render = async (
// 'elk.layered.edgeRouting.selfLoopDistribution': 'EQUALLY',
// 'elk.layered.mergeHierarchyEdges': true,
// 'elk.layered.feedbackEdges': true,
// 'elk.layered.crossingMinimization.semiInteractive': true,
// 'elk.layered.crossingMinimization.semiInteractive': false,
// 'crossingMinimization.semiInteractive': false,
// '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.alg.layered.options.EdgeStraighteningStrategy': 'NONE',
// 'elk.layered.considerModelOrder.strategy': 'NODES_AND_EDGES', // NODES_AND_EDGES
// 'elk.layered.considerModelOrder.strategy': 'PREFER_NODES',
// 'elk.layered.wrapping.cutting.strategy': 'ARD', // NODES_AND_EDGES
// 'elk.layered.wrapping.cutting.strategy': 'NODES_AND_EDGES',
// 'elk.alignment': 'BOTTOM',
// 'elk.layered.nodePlacement.bk.fixedAlignment': 'RIGHTDOWN',
// 'elk.edgeRouting': 'UNDEFINED',
'elk.layered.crossingMinimization.forceNodeModelOrder': false,
},
children: [],
edges: [],
@@ -832,6 +570,7 @@ export const render = async (
// Iterate through all nodes and add the top level nodes to the graph
const nodes = data4Layout.nodes;
nodes.forEach((n: { id: string | number }) => {
const node = nodeDb[n.id];
@@ -850,6 +589,7 @@ export const render = async (
'spacing.baseValue': 30,
'nodeLabels.placement': '[H_CENTER V_TOP, INSIDE]',
};
if (node.dir) {
node.layoutOptions = {
...node.layoutOptions,
@@ -860,6 +600,7 @@ export const render = async (
'elk.hierarchyHandling': 'SEPARATE_CHILDREN',
};
}
delete node.x;
delete node.y;
delete node.width;
@@ -877,9 +618,7 @@ export const render = async (
setIncludeChildrenPolicy(target, ancestorId);
}
});
const g = await elk.layout(elkGraph);
// debugger;
await drawNodes(0, 0, g.children, svg, subGraphsEl, 0);
g.edges?.map(
@@ -966,42 +705,44 @@ export const render = async (
startNode.innerHTML
);
}
if (startNode.shape === 'diamond' || startNode.shape === 'diam') {
edge.points.unshift({
x: startNode.offset.posX + startNode.width / 2,
y: startNode.offset.posY + startNode.height / 2,
});
}
if (endNode.shape === 'diamond' || endNode.shape === 'diam') {
edge.points.push({
x: endNode.offset.posX + endNode.width / 2,
y: endNode.offset.posY + endNode.height / 2,
});
}
if (startNode.intersect) {
// Remove the first point of the edge points
// edge.points.shift();
const firstPoint = edge.points[0];
// Transpose points to adjust for elk standard
const adjustedFirstPoint = {
x: firstPoint.x - startNode.width / 2,
y: firstPoint.y - startNode.height / 2,
};
const intersectionRaw = startNode.intersect(adjustedFirstPoint);
const intersection = {
x: intersectionRaw.x + startNode.width / 2,
y: intersectionRaw.y + startNode.height / 2,
};
edge.points = cutPathAtIntersect(
edge.points.reverse(),
{
x: startNode.offset.posX + startNode.width / 2,
y: startNode.offset.posY + startNode.height / 2,
width: sw,
height: startNode.height,
padding: startNode.padding,
},
startNode.shape === 'diamond' || startNode.shape === 'diam'
).reverse();
if (distance(intersection, firstPoint) > epsilon) {
edge.points.unshift(intersection);
}
}
if (endNode.intersect) {
// Remove the last point of the edge points
// edge.points.pop();
edge.points = cutPathAtIntersect(
edge.points,
{
x: endNode.offset.posX + endNode.width / 2,
y: endNode.offset.posY + endNode.height / 2,
width: ew,
height: endNode.height,
padding: endNode.padding,
},
endNode.shape === 'diamond' || endNode.shape === 'diam'
);
const lastPoint = edge.points[edge.points.length - 1];
// Transpose points to adjust for elk standard
const adjustedLastPoint = {
x: lastPoint.x - endNode.width / 2,
y: lastPoint.y - endNode.height / 2,
};
const intersectionRaw = endNode.intersect(adjustedLastPoint);
const intersection = {
x: intersectionRaw.x + endNode.width / 2,
y: intersectionRaw.y + endNode.height / 2,
};
if (distance(intersection, lastPoint) > epsilon) {
edge.points.push(intersection);
}
}
const paths = insertEdge(
edgesEl,
@@ -1012,7 +753,6 @@ export const render = async (
endNode,
data4Layout.diagramId
);
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;

View File

@@ -36,7 +36,7 @@
"@zenuml/core": "^3.23.27"
},
"devDependencies": {
"mermaid": "workspace:^"
"@mermaid-chart/mermaid": "workspace:^"
},
"peerDependencies": {
"mermaid": "^10 || ^11"

View File

@@ -1,6 +1,6 @@
{
"name": "mermaid",
"version": "11.4.1",
"name": "@mermaid-chart/mermaid",
"version": "11.4.1-b.12",
"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",
@@ -52,7 +52,7 @@
},
"repository": {
"type": "git",
"url": "https://github.com/mermaid-js/mermaid"
"url": "https://github.com/Mermaid-Chart/mermaid"
},
"author": "Knut Sveidqvist",
"license": "MIT",
@@ -69,7 +69,7 @@
"dependencies": {
"@braintree/sanitize-url": "^7.0.1",
"@iconify/utils": "^2.1.32",
"@mermaid-js/parser": "workspace:^",
"@mermaid-js/parser": "^0.3.1-rc.1",
"@types/d3": "^7.4.3",
"cytoscape": "^3.29.2",
"cytoscape-cose-bilkent": "^4.1.0",
@@ -105,6 +105,8 @@
"@types/prettier": "^3.0.0",
"@types/stylis": "^4.2.5",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
"ajv": "^8.12.0",
"chokidar": "^3.6.0",
"concurrently": "^8.2.2",
@@ -134,8 +136,5 @@
"files": [
"dist/",
"README.md"
],
"publishConfig": {
"access": "public"
}
]
}

View File

@@ -53,12 +53,13 @@ import mm from 'micromatch';
// @ts-ignore No typescript declaration file
import flatmap from 'unist-util-flatmap';
import { visit } from 'unist-util-visit';
import { fileURLToPath } from 'url';
// short-circuit `.schema.yaml` imports, so that we can safely import `shapes.js`
register('./loadHook.mjs', import.meta.url);
const { shapesDefs } = await import('../src/rendering-util/rendering-elements/shapes.js');
export const MERMAID_RELEASE_VERSION = JSON.parse(readFileSync('../mermaid/package.json', 'utf8'))
const packageJsonPath = join(fileURLToPath(import.meta.url), '../../package.json');
export const MERMAID_RELEASE_VERSION = JSON.parse(readFileSync(packageJsonPath, 'utf8'))
.version as string;
const MERMAID_MAJOR_VERSION = MERMAID_RELEASE_VERSION.split('.')[0];
const CDN_URL = 'https://cdn.jsdelivr.net/npm'; // 'https://unpkg.com';

View File

@@ -53,8 +53,8 @@ export class Diagram {
public renderer: DiagramDefinition['renderer']
) {}
async render(id: string, version: string) {
await this.renderer.draw(this.text, id, version, this);
async render(id: string, version: string, positions?: any) {
await this.renderer.draw(this.text, id, version, this, positions);
}
getParser() {

View File

@@ -61,14 +61,25 @@ export interface MermaidConfig {
* You may also use `themeCSS` to override this value.
*
*/
theme?: 'default' | 'base' | 'dark' | 'forest' | 'neutral' | 'null';
theme?:
| 'default'
| 'base'
| 'dark'
| 'forest'
| 'neutral'
| 'neo'
| 'neo-dark'
| 'redux'
| 'redux-dark'
| 'mc'
| 'null';
themeVariables?: any;
themeCSS?: string;
/**
* Defines which main look to use for the diagram.
*
*/
look?: 'classic' | 'handDrawn';
look?: 'classic' | 'handDrawn' | 'neo';
/**
* Defines the seed to be used when using handDrawn look. This is important for the automated tests as they will always find differences without the seed. The default value is 0 which gives a random seed.
*
@@ -261,7 +272,12 @@ export interface FlowchartDiagramConfig extends BaseDiagramConfig {
* Defines how mermaid renders curves for flowcharts.
*
*/
curve?: 'basis' | 'linear' | 'cardinal';
curve?: 'basis' | 'linear' | 'cardinal' | 'rounded';
/**
* Highlights the points in an edge for debugging.
*
*/
edgeDebug?: boolean;
/**
* Represents the padding between the labels and the shape
*
@@ -754,6 +770,11 @@ export interface StateDiagramConfig extends BaseDiagramConfig {
edgeLengthFactor?: string;
compositTitleSize?: number;
radius?: number;
/**
* Defines how mermaid renders curves for flowcharts.
*
*/
curve?: 'basis' | 'linear' | 'cardinal' | 'rounded';
/**
* Decides which rendering engine that is to be used for the rendering.
*

View File

@@ -15,6 +15,8 @@ const rect = (parent, node) => {
const shapeSvg = parent
.insert('g')
.attr('class', 'cluster' + (node.class ? ' ' + node.class : ''))
.attr('data-et', 'cluster')
.attr('data-id', node.id)
.attr('id', node.id);
// add the rect

View File

@@ -29,6 +29,7 @@ const arrowTypesMap = {
arrow_cross: 'cross',
arrow_point: 'point',
arrow_barb: 'barb',
arrow_neo: 'barbNeo',
arrow_circle: 'circle',
aggregation: 'aggregation',
extension: 'extension',

View File

@@ -39,7 +39,7 @@ export const insertEdgeLabel = (elem, edge) => {
const edgeLabel = elem.insert('g').attr('class', 'edgeLabel');
// Create inner g, label, this will be positioned now for centering the text
const label = edgeLabel.insert('g').attr('class', 'label');
const label = edgeLabel.insert('g').attr('class', 'label').attr('data-id', edge.id);
label.node().appendChild(labelElement);
// Center the label
@@ -423,6 +423,8 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
.append('path')
.attr('d', lineFunction(lineData))
.attr('id', edge.id)
// MC
.attr('data-edge', 'true')
.attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : ''))
.attr('style', edge.style);

View File

@@ -1156,6 +1156,10 @@ export const insertNode = async (elem, node, renderOptions) => {
el.attr('class', 'node default ' + node.class);
}
// MC Special
newEl.attr('data-node', 'true');
newEl.attr('data-id', node.id);
nodeElems[node.id] = newEl;
if (node.haveCallback) {

View File

@@ -39,6 +39,7 @@ export const detectType = function (text: string, config?: MermaidConfig): strin
.replace(directiveRegex, '')
.replace(anyCommentRegex, '\n');
for (const [key, { detector }] of Object.entries(detectors)) {
console.log('APA20', key);
const diagram = detector(text, config);
if (diagram) {
return key;

View File

@@ -18,6 +18,7 @@ import journey from '../diagrams/user-journey/journeyDetector.js';
import errorDiagram from '../diagrams/error/errorDiagram.js';
import flowchartElk from '../diagrams/flowchart/elk/detector.js';
import timeline from '../diagrams/timeline/detector.js';
import swimlane from '../diagrams/swimlane/detector.js';
import mindmap from '../diagrams/mindmap/detector.js';
import kanban from '../diagrams/kanban/detector.js';
import sankey from '../diagrams/sankey/sankeyDetector.js';
@@ -94,6 +95,7 @@ export const addDiagrams = () => {
packet,
xychart,
block,
architecture
architecture,
swimlane
);
};

View File

@@ -1,16 +1,16 @@
import { addDetector } from './detectType.js';
import { log as _log, setLogLevel as _setLogLevel } from '../logger.js';
import {
defaultConfig as _defaultConfig,
getConfig as _getConfig,
setConfig as _setConfig,
defaultConfig as _defaultConfig,
setSiteConfig as _setSiteConfig,
} from '../config.js';
import { sanitizeText as _sanitizeText } from '../diagrams/common/common.js';
import * as _commonDb from '../diagrams/common/commonDb.js';
import { log as _log, setLogLevel as _setLogLevel } from '../logger.js';
import { setupGraphViewbox as _setupGraphViewbox } from '../setupGraphViewbox.js';
import { addStylesForDiagram } from '../styles.js';
import { addDetector } from './detectType.js';
import type { DiagramDefinition, DiagramDetector } from './types.js';
import * as _commonDb from '../diagrams/common/commonDb.js';
/*
Packaging and exposing resources for external diagrams so that they can import

View File

@@ -105,6 +105,30 @@ export interface ExternalDiagramDefinition {
export type DiagramDetector = (text: string, config?: MermaidConfig) => boolean;
export type DiagramLoader = () => Promise<{ id: string; diagram: DiagramDefinition }>;
/* Types for the positions used in the free layout engine */
interface Point {
x: number;
y: number;
}
export interface IntersectionPoint extends Point {
pos: 't' | 'b' | 'l' | 'r';
}
export interface NodePosition extends Point {
width?: number;
height?: number;
}
export interface EdgePoints {
points: Point[];
}
export interface Positions {
nodes: Record<string, NodePosition>;
edges: Record<string, EdgePoints>;
}
/**
* Type for function draws diagram in the tag with id: id based on the graph definition in text.
*
@@ -117,7 +141,10 @@ export type DrawDefinition = (
text: string,
id: string,
version: string,
diagramObject: Diagram
diagramObject: Diagram,
// Todo: types from positions when logic is done
// MC Special
positions?: any
) => void | Promise<void>;
export interface ParserDefinition {

View File

@@ -20,10 +20,10 @@ const getStyles: DiagramStylesProvider = (options: ArchitectureStyleOptions) =>
stroke-dasharray: 8;
}
.node-icon-text {
display: flex;
display: flex;
align-items: center;
}
.node-icon-text > div {
color: #fff;
margin: 1px;
@@ -33,6 +33,9 @@ const getStyles: DiagramStylesProvider = (options: ArchitectureStyleOptions) =>
display: -webkit-box;
-webkit-box-orient: vertical;
}
.architecture-services, .architecture-edges, .architecture-groups {
font-size: 16px;
}
`;
export default getStyles;

View File

@@ -105,7 +105,6 @@ const getStyles = (options: BlockChartStyleOptions) =>
}
.node .cluster {
// fill: ${fade(options.mainBkg, 0.5)};
fill: ${fade(options.clusterBkg, 0.5)};
stroke: ${fade(options.clusterBorder, 0.2)};
box-shadow: rgba(50, 50, 93, 0.25) 0px 13px 27px -5px, rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;

View File

@@ -38,7 +38,13 @@ export const getClasses = function (
return diagramObj.db.getClasses();
};
export const draw = async function (text: string, id: string, _version: string, diag: any) {
export const draw = async function (
text: string,
id: string,
_version: string,
diag: any,
positions: any
) {
log.info('REF0:');
log.info('Drawing class diagram (v3)', id);
const { securityLevel, state: conf, layout } = getConfig();
@@ -60,7 +66,7 @@ export const draw = async function (text: string, id: string, _version: string,
data4Layout.rankSpacing = conf?.rankSpacing || 50;
data4Layout.markers = ['aggregation', 'extension', 'composition', 'dependency', 'lollipop'];
data4Layout.diagramId = id;
await render(data4Layout, svg);
await render(data4Layout, svg, positions);
const padding = 8;
utils.insertTitle(
svg,

View File

@@ -960,6 +960,7 @@ You have to call mermaid.initialize.`
let arrowTypeStart = 'none';
let arrowTypeEnd = 'arrow_point';
switch (type) {
case 'arrow_open':
case 'arrow_point':
case 'arrow_circle':
case 'arrow_cross':
@@ -1096,6 +1097,7 @@ You have to call mermaid.initialize.`
if (rawEdge.style) {
styles.push(...rawEdge.style);
}
const edge: Edge = {
id: getEdgeId(rawEdge.start, rawEdge.end, { counter: index, prefix: 'L' }, rawEdge.id),
isUserDefinedId: rawEdge.isUserDefinedId,
@@ -1122,6 +1124,8 @@ You have to call mermaid.initialize.`
style: styles,
pattern: rawEdge.stroke,
look: config.look,
curve: config.flowchart?.curve,
showPoints: config.flowchart?.edgeDebug,
animate: rawEdge.animate,
animation: rawEdge.animation,
};

View File

@@ -15,7 +15,13 @@ export const getClasses = function (
return diagramObj.db.getClasses();
};
export const draw = async function (text: string, id: string, _version: string, diag: any) {
export const draw = async function (
text: string,
id: string,
_version: string,
diag: any,
positions: any
) {
log.info('REF0:');
log.info('Drawing state diagram (v2)', id);
const { securityLevel, flowchart: conf, layout } = getConfig();
@@ -40,6 +46,7 @@ export const draw = async function (text: string, id: string, _version: string,
data4Layout.type = diag.type;
data4Layout.layoutAlgorithm = getRegisteredLayoutAlgorithm(layout);
if (data4Layout.layoutAlgorithm === 'dagre' && layout === 'elk') {
log.warn(
'flowchart-elk was moved to an external package in Mermaid v11. Please refer [release notes](https://github.com/mermaid-js/mermaid/releases/tag/v11.0.0) for more details. This diagram will be rendered using `dagre` layout as a fallback.'
@@ -52,7 +59,7 @@ export const draw = async function (text: string, id: string, _version: string,
data4Layout.diagramId = id;
log.debug('REF1:', data4Layout);
await render(data4Layout, svg);
await render(data4Layout, svg, positions);
const padding = data4Layout.config.flowchart?.diagramPadding ?? 8;
utils.insertTitle(
svg,

View File

@@ -16,6 +16,7 @@ export interface FlowChartStyleOptions {
tertiaryColor: string;
textColor: string;
titleColor: string;
strokeWidth: string;
}
const fade = (color: string, opacity: number) => {
@@ -57,17 +58,11 @@ const getStyles = (options: FlowChartStyleOptions) =>
.node path {
fill: ${options.mainBkg};
stroke: ${options.nodeBorder};
stroke-width: 1px;
stroke-width: ${options.strokeWidth}px;
}
.rough-node .label text , .node .label text, .image-shape .label, .icon-shape .label {
text-anchor: middle;
}
// .flowchart-label .text-outer-tspan {
// text-anchor: middle;
// }
// .flowchart-label .text-inner-tspan {
// text-anchor: start;
// }
.node .katex path {
fill: #000;
@@ -95,7 +90,7 @@ const getStyles = (options: FlowChartStyleOptions) =>
.edgePath .path {
stroke: ${options.lineColor};
stroke-width: 2.0px;
stroke-width: ${options.strokeWidth}px;
}
.flowchart-link {
@@ -125,7 +120,7 @@ const getStyles = (options: FlowChartStyleOptions) =>
.cluster rect {
fill: ${options.clusterBkg};
stroke: ${options.clusterBorder};
stroke-width: 1px;
stroke-width: ${options.strokeWidth}px;
}
.cluster text {

View File

@@ -237,7 +237,7 @@ interface NoteModel {
* @param elem - The diagram to draw to.
* @param noteModel - Note model options.
*/
const drawNote = async function (elem: any, noteModel: NoteModel) {
const drawNote = async function (elem: any, noteModel: NoteModel, id: string) {
bounds.bumpVerticalPos(conf.boxMargin);
noteModel.height = conf.boxMargin;
noteModel.starty = bounds.getVerticalPos();
@@ -248,6 +248,8 @@ const drawNote = async function (elem: any, noteModel: NoteModel) {
rect.class = 'note';
const g = elem.append('g');
g.attr('data-et', 'note');
g.attr('data-id', 'i' + id);
const rectElem = svgDraw.drawRect(g, rect);
const textObj = svgDrawCommon.getTextObj();
textObj.x = noteModel.startx;
@@ -447,6 +449,11 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
line.attr('class', 'messageLine0');
}
line.attr('data-et', 'message');
line.attr('data-id', 'i' + msgModel.id);
line.attr('data-from', msgModel.from);
line.attr('data-to', msgModel.to);
let url = '';
if (conf.arrowMarkerAbsolute) {
url =
@@ -865,7 +872,7 @@ export const draw = async function (_text: string, id: string, _version: string,
case diagObj.db.LINETYPE.NOTE:
bounds.resetVerticalPos();
noteModel = msg.noteModel;
await drawNote(diagram, noteModel);
await drawNote(diagram, noteModel, msg.id);
break;
case diagObj.db.LINETYPE.ACTIVE_START:
bounds.newActivation(msg, diagram, actors);
@@ -884,7 +891,7 @@ export const draw = async function (_text: string, id: string, _version: string,
break;
case diagObj.db.LINETYPE.LOOP_END:
loopModel = bounds.endLoop();
await svgDraw.drawLoop(diagram, loopModel, 'loop', conf);
await svgDraw.drawLoop(diagram, loopModel, 'loop', conf, msg);
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
bounds.models.addLoop(loopModel);
break;
@@ -910,7 +917,7 @@ export const draw = async function (_text: string, id: string, _version: string,
break;
case diagObj.db.LINETYPE.OPT_END:
loopModel = bounds.endLoop();
await svgDraw.drawLoop(diagram, loopModel, 'opt', conf);
await svgDraw.drawLoop(diagram, loopModel, 'opt', conf, msg);
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
bounds.models.addLoop(loopModel);
break;
@@ -934,7 +941,7 @@ export const draw = async function (_text: string, id: string, _version: string,
break;
case diagObj.db.LINETYPE.ALT_END:
loopModel = bounds.endLoop();
await svgDraw.drawLoop(diagram, loopModel, 'alt', conf);
await svgDraw.drawLoop(diagram, loopModel, 'alt', conf, msg);
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
bounds.models.addLoop(loopModel);
break;
@@ -960,7 +967,7 @@ export const draw = async function (_text: string, id: string, _version: string,
break;
case diagObj.db.LINETYPE.PAR_END:
loopModel = bounds.endLoop();
await svgDraw.drawLoop(diagram, loopModel, 'par', conf);
await svgDraw.drawLoop(diagram, loopModel, 'par', conf, msg);
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
bounds.models.addLoop(loopModel);
break;
@@ -993,7 +1000,7 @@ export const draw = async function (_text: string, id: string, _version: string,
break;
case diagObj.db.LINETYPE.CRITICAL_END:
loopModel = bounds.endLoop();
await svgDraw.drawLoop(diagram, loopModel, 'critical', conf);
await svgDraw.drawLoop(diagram, loopModel, 'critical', conf, msg);
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
bounds.models.addLoop(loopModel);
break;
@@ -1008,7 +1015,7 @@ export const draw = async function (_text: string, id: string, _version: string,
break;
case diagObj.db.LINETYPE.BREAK_END:
loopModel = bounds.endLoop();
await svgDraw.drawLoop(diagram, loopModel, 'break', conf);
await svgDraw.drawLoop(diagram, loopModel, 'break', conf, msg);
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
bounds.models.addLoop(loopModel);
break;
@@ -1018,6 +1025,9 @@ export const draw = async function (_text: string, id: string, _version: string,
msgModel.starty = bounds.getVerticalPos();
msgModel.sequenceIndex = sequenceIndex;
msgModel.sequenceVisible = diagObj.db.showSequenceNumbers();
msgModel.id = msg.id;
msgModel.from = msg.from;
msgModel.to = msg.to;
const lineStartY = await boundMessage(diagram, msgModel);
adjustCreatedDestroyedData(
msg,
@@ -1087,6 +1097,18 @@ export const draw = async function (_text: string, id: string, _version: string,
const requiredBoxSize = drawActorsPopup(diagram, actors, actorKeys, doc);
const { bounds: box } = bounds.getBounds();
if (box.startx === undefined) {
box.startx = 0;
}
if (box.starty === undefined) {
box.starty = 0;
}
if (box.stopx === undefined) {
box.stopx = 0;
}
if (box.stopy === undefined) {
box.stopy = 0;
}
if (box.startx === undefined) {
box.startx = 0;

View File

@@ -348,7 +348,9 @@ const drawActorTypeParticipant = function (elem, actor, conf, isFooter) {
.attr('class', 'actor-line 200')
.attr('stroke-width', '0.5px')
.attr('stroke', '#999')
.attr('name', actor.name);
.attr('name', actor.name)
.attr('data-et', 'life-line')
.attr('data-id', actor.name);
g = boxplusLineGroup.append('g');
actor.actorCnt = actorCnt;
@@ -390,6 +392,11 @@ const drawActorTypeParticipant = function (elem, actor, conf, isFooter) {
}
}
if (!isFooter) {
g.attr('data-et', 'participant');
g.attr('data-id', actor.name);
}
_drawTextCandidateFunc(conf, hasKatex(actor.description))(
actor.description,
g,
@@ -430,7 +437,9 @@ const drawActorTypeActor = function (elem, actor, conf, isFooter) {
.attr('class', 'actor-line 200')
.attr('stroke-width', '0.5px')
.attr('stroke', '#999')
.attr('name', actor.name);
.attr('name', actor.name)
.attr('data-et', 'life-line')
.attr('data-id', actor.name);
actor.actorCnt = actorCnt;
}
@@ -444,6 +453,10 @@ const drawActorTypeActor = function (elem, actor, conf, isFooter) {
actElem.attr('class', cssClass);
actElem.attr('name', actor.name);
if (!isFooter) {
actElem.attr('data-et', 'participant').attr('data-id', actor.name);
}
const rect = svgDrawCommon.getNoteRect();
rect.x = actor.x;
rect.y = actorY;
@@ -567,7 +580,7 @@ export const drawActivation = function (elem, bounds, verticalPos, conf, actorAc
* @param {any} conf - Diagram configuration
* @returns {any}
*/
export const drawLoop = async function (elem, loopModel, labelText, conf) {
export const drawLoop = async function (elem, loopModel, labelText, conf, msg) {
const {
boxMargin,
boxTextMargin,
@@ -577,7 +590,10 @@ export const drawLoop = async function (elem, loopModel, labelText, conf) {
messageFontSize: fontSize,
messageFontWeight: fontWeight,
} = conf;
const g = elem.append('g');
const g = elem
.append('g')
.attr('data-et', 'control-structure')
.attr('data-id', 'i' + msg.id);
const drawLoopLine = function (startx, starty, stopx, stopy) {
return g
.append('line')

View File

@@ -54,16 +54,46 @@ export function stateDomId(itemId = '', counter = 0, type = '', typeSpacer = DOM
return `${DOMID_STATE}-${itemId}${typeStr}-${counter}`;
}
const setupDoc = (parentParsedItem, doc, diagramStates, nodes, edges, altFlag, look, classes) => {
const setupDoc = (
parentParsedItem,
doc,
diagramStates,
nodes,
edges,
altFlag,
look,
classes,
config
) => {
// graphItemCount = 0;
log.trace('items', doc);
doc.forEach((item) => {
switch (item.stmt) {
case STMT_STATE:
dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, look, classes);
dataFetcher(
parentParsedItem,
item,
diagramStates,
nodes,
edges,
altFlag,
look,
classes,
config
);
break;
case DEFAULT_STATE_TYPE:
dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, look, classes);
dataFetcher(
parentParsedItem,
item,
diagramStates,
nodes,
edges,
altFlag,
look,
classes,
config
);
break;
case STMT_RELATION:
{
@@ -75,7 +105,8 @@ const setupDoc = (parentParsedItem, doc, diagramStates, nodes, edges, altFlag, l
edges,
altFlag,
look,
classes
classes,
config
);
dataFetcher(
parentParsedItem,
@@ -85,7 +116,8 @@ const setupDoc = (parentParsedItem, doc, diagramStates, nodes, edges, altFlag, l
edges,
altFlag,
look,
classes
classes,
config
);
const edgeData = {
id: 'edge' + graphItemCount,
@@ -102,6 +134,7 @@ const setupDoc = (parentParsedItem, doc, diagramStates, nodes, edges, altFlag, l
thickness: G_EDGE_THICKNESS,
classes: CSS_EDGE,
look,
curve: config.state?.curve,
};
edges.push(edgeData);
graphItemCount++;
@@ -181,7 +214,8 @@ export const dataFetcher = (
edges,
altFlag,
look,
classes
classes,
config
) => {
const itemId = parsedItem.id;
const dbState = diagramStates.get(itemId);
@@ -362,6 +396,7 @@ export const dataFetcher = (
labelType: G_EDGE_LABELTYPE,
thickness: G_EDGE_THICKNESS,
look,
curve: config.state?.curve,
});
} else {
insertOrUpdateNode(nodes, nodeData, classes);
@@ -369,7 +404,17 @@ export const dataFetcher = (
}
if (parsedItem.doc) {
log.trace('Adding nodes children ');
setupDoc(parsedItem, parsedItem.doc, diagramStates, nodes, edges, !altFlag, look, classes);
setupDoc(
parsedItem,
parsedItem.doc,
diagramStates,
nodes,
edges,
!altFlag,
look,
classes,
config
);
}
};

View File

@@ -221,7 +221,7 @@ const extract = (_doc) => {
const config = getConfig();
const look = config.look;
resetDataFetching();
dataFetcher(undefined, getRootDocV2(), diagramStates, nodes, edges, true, look, classes);
dataFetcher(undefined, getRootDocV2(), diagramStates, nodes, edges, true, look, classes, config);
nodes.forEach((node) => {
if (Array.isArray(node.label)) {
// add the rest as description

View File

@@ -40,9 +40,16 @@ export const getClasses = function (
return diagramObj.db.getClasses();
};
export const draw = async function (text: string, id: string, _version: string, diag: any) {
log.info('REF0:');
export const draw = async function (
text: string,
id: string,
_version: string,
diag: any,
positions: any
) {
log.info('REF0:', positions);
log.info('Drawing state diagram (v2)', id);
log.info('Diagram Configuration:', getConfig());
const { securityLevel, state: conf, layout } = getConfig();
// Extracting the data from the parsed structure into a more usable form
// Not related to the refactoring, but this is the first step in the rendering process
@@ -64,10 +71,14 @@ export const draw = async function (text: string, id: string, _version: string,
data4Layout.nodeSpacing = conf?.nodeSpacing || 50;
data4Layout.rankSpacing = conf?.rankSpacing || 50;
data4Layout.markers = ['barb'];
const config = getConfig();
if (config.look === 'neo') {
data4Layout.markers = ['barbNeo'];
} else {
data4Layout.markers = ['barb'];
}
data4Layout.diagramId = id;
// console.log('REF1:', data4Layout);
await render(data4Layout, svg);
await render(data4Layout, svg, positions);
const padding = 8;
utils.insertTitle(
svg,

View File

@@ -104,14 +104,21 @@ g.stateGroup line {
}
.node circle.state-end {
fill: ${options.innerEndBackground};
fill: ${options.stateBkg || options.mainBkg};
stroke: ${options.background};
stroke-width: 1.5
stroke-width: 1.5;
}
[data-look="neo"].node circle.state-end {
filter: none;
stroke:${options.background};
fill: ${options.lineColor};
}
.end-state-inner {
fill: ${options.compositeBackground || options.background};
// stroke: ${options.background};
stroke-width: 1.5
stroke: ${options.background};
stroke-width: 1.5;
}
.node rect {
@@ -119,6 +126,13 @@ g.stateGroup line {
stroke: ${options.stateBorder || options.nodeBorder};
stroke-width: 1px;
}
.node-rect-neo {
fill: ${options.stateBkg || options.mainBkg};
stroke: none;
stroke-width: 1px;
}
.node polygon {
fill: ${options.mainBkg};
stroke: ${options.stateBorder || options.nodeBorder};;
@@ -136,26 +150,26 @@ g.stateGroup line {
.cluster-label, .nodeLabel {
color: ${options.stateLabelColor};
// line-height: 1;
line-height: 1.0;
}
.statediagram-cluster rect.outer {
rx: 5px;
ry: 5px;
rx: ${options.radius}px;
ry: ${options.radius}px;
}
.statediagram-state .divider {
stroke: ${options.stateBorder || options.nodeBorder};
}
.statediagram-state .title-state {
rx: 5px;
ry: 5px;
rx: ${options.radius}px;
ry: ${options.radius}px;
}
.statediagram-cluster.statediagram-cluster .inner {
fill: ${options.compositeBackground || options.background};
}
.statediagram-cluster.statediagram-cluster-alt .inner {
fill: ${options.altBackground ? options.altBackground : '#efefef'};
fill: ${options.altBackground ? options.altBackground : '#f0f0f0'};
}
.statediagram-cluster .inner {
@@ -164,9 +178,16 @@ g.stateGroup line {
}
.statediagram-state rect.basic {
rx: 5px;
ry: 5px;
rx: ${options.radius}px;
ry: ${options.radius}px;
}
.state-shadow-neo {
filter: ${options.dropShadow};
}
.statediagram-state rect.divider {
stroke-dasharray: 10,10;
fill: ${options.altBackground ? options.altBackground : '#efefef'};
@@ -198,6 +219,11 @@ g.stateGroup line {
.statediagram-note .nodeLabel {
color: ${options.noteTextColor};
}
.node.statediagram-note rect {
stroke: ${options.noteBorderColor} !important;
}
.statediagram .edgeLabel {
color: red; // ${options.noteTextColor};
}

View File

@@ -0,0 +1,24 @@
import type {
DiagramDetector,
DiagramLoader,
ExternalDiagramDefinition,
} from '../../diagram-api/types.js';
const id = 'swimlane';
const detector: DiagramDetector = (txt) => {
return /^\s*swimlane/.test(txt);
};
const loader: DiagramLoader = async () => {
const { diagram } = await import('./swimlaneDiagram.js');
return { id, diagram };
};
const plugin: ExternalDiagramDefinition = {
id,
detector,
loader,
};
export default plugin;

View File

@@ -0,0 +1,67 @@
import flowDb from './flowDb.js';
import type { FlowSubGraph } from './types.js';
describe('flow db subgraphs', () => {
let subgraphs: FlowSubGraph[];
beforeEach(() => {
subgraphs = [
{ nodes: ['a', 'b', 'c', 'e'] },
{ nodes: ['f', 'g', 'h'] },
{ nodes: ['i', 'j'] },
{ nodes: ['k'] },
] as FlowSubGraph[];
});
describe('exist', () => {
it('should return true when the is exists in a subgraph', () => {
expect(flowDb.exists(subgraphs, 'a')).toBe(true);
expect(flowDb.exists(subgraphs, 'h')).toBe(true);
expect(flowDb.exists(subgraphs, 'j')).toBe(true);
expect(flowDb.exists(subgraphs, 'k')).toBe(true);
});
it('should return false when the is exists in a subgraph', () => {
expect(flowDb.exists(subgraphs, 'a2')).toBe(false);
expect(flowDb.exists(subgraphs, 'l')).toBe(false);
});
});
describe('makeUniq', () => {
it('should remove ids from sungraph that already exists in another subgraph even if it gets empty', () => {
const subgraph = flowDb.makeUniq({ nodes: ['i', 'j'] } as FlowSubGraph, subgraphs);
expect(subgraph.nodes).toEqual([]);
});
it('should remove ids from sungraph that already exists in another subgraph', () => {
const subgraph = flowDb.makeUniq({ nodes: ['i', 'j', 'o'] } as FlowSubGraph, subgraphs);
expect(subgraph.nodes).toEqual(['o']);
});
it('should not remove ids from subgraph if they are unique', () => {
const subgraph = flowDb.makeUniq({ nodes: ['q', 'r', 's'] } as FlowSubGraph, subgraphs);
expect(subgraph.nodes).toEqual(['q', 'r', 's']);
});
});
});
describe('flow db addClass', () => {
beforeEach(() => {
flowDb.clear();
});
it('should detect many classes', () => {
flowDb.addClass('a,b', ['stroke-width: 8px']);
const classes = flowDb.getClasses();
expect(classes.has('a')).toBe(true);
expect(classes.has('b')).toBe(true);
expect(classes.get('a')?.styles).toEqual(['stroke-width: 8px']);
expect(classes.get('b')?.styles).toEqual(['stroke-width: 8px']);
});
it('should detect single class', () => {
flowDb.addClass('a', ['stroke-width: 8px']);
const classes = flowDb.getClasses();
expect(classes.has('a')).toBe(true);
expect(classes.get('a')?.styles).toEqual(['stroke-width: 8px']);
});
});

View File

@@ -0,0 +1,55 @@
import plugin from './detector.js';
import { describe, it } from 'vitest';
const { detector } = plugin;
describe('swimlane detector', () => {
it('should fail for dagre-d3', () => {
expect(
detector('swimlane', {
flowchart: {
defaultRenderer: 'dagre-d3',
},
})
).toBe(false);
});
it('should fail for dagre-wrapper', () => {
expect(
detector('flowchart', {
flowchart: {
defaultRenderer: 'dagre-wrapper',
},
})
).toBe(false);
});
it('should succeed for elk', () => {
expect(
detector('flowchart', {
flowchart: {
defaultRenderer: 'elk',
},
})
).toBe(true);
expect(
detector('graph', {
flowchart: {
defaultRenderer: 'elk',
},
})
).toBe(true);
});
it('should detect swimlane', () => {
expect(detector('swimlane')).toBe(true);
});
it('should not detect class with defaultRenderer set to elk', () => {
expect(
detector('class', {
flowchart: {
defaultRenderer: 'elk',
},
})
).toBe(false);
});
});

View File

@@ -0,0 +1,29 @@
import type {
ExternalDiagramDefinition,
DiagramDetector,
DiagramLoader,
} from '../../../diagram-api/types.js';
const id = 'swimlane';
const detector: DiagramDetector = (txt, config): boolean => {
if (txt.match(/^\s*swimlane/)) {
return true;
}
return false;
};
const loader: DiagramLoader = async () => {
const { diagram } = await import('./swimlane-definition.js');
return { id, diagram };
};
const plugin: ExternalDiagramDefinition = {
id,
detector,
loader,
};
export default plugin;

View File

@@ -0,0 +1,40 @@
import { findCommonAncestor, TreeData } from './render-utils.js';
describe('when rendering a flowchart using elk ', () => {
let lookupDb: TreeData;
beforeEach(() => {
lookupDb = {
parentById: {
B4: 'inner',
B5: 'inner',
C4: 'inner2',
C5: 'inner2',
B2: 'Ugge',
B3: 'Ugge',
inner: 'Ugge',
inner2: 'Ugge',
B6: 'outer',
},
childrenById: {
inner: ['B4', 'B5'],
inner2: ['C4', 'C5'],
Ugge: ['B2', 'B3', 'inner', 'inner2'],
outer: ['B6'],
},
};
});
it('to find parent of siblings in a subgraph', () => {
expect(findCommonAncestor('B4', 'B5', lookupDb)).toBe('inner');
});
it('to find an uncle', () => {
expect(findCommonAncestor('B4', 'B2', lookupDb)).toBe('Ugge');
});
it('to find a cousin', () => {
expect(findCommonAncestor('B4', 'C4', lookupDb)).toBe('Ugge');
});
it('to find a grandparent', () => {
expect(findCommonAncestor('B4', 'B6', lookupDb)).toBe('root');
});
it('to find ancestor of siblings in the root', () => {
expect(findCommonAncestor('B1', 'outer', lookupDb)).toBe('root');
});
});

View File

@@ -0,0 +1,25 @@
export interface TreeData {
parentById: Record<string, string>;
childrenById: Record<string, string[]>;
}
export const findCommonAncestor = (id1: string, id2: string, treeData: TreeData) => {
const { parentById } = treeData;
const visited = new Set();
let currentId = id1;
while (currentId) {
visited.add(currentId);
if (currentId === id2) {
return currentId;
}
currentId = parentById[currentId];
}
currentId = id2;
while (currentId) {
if (visited.has(currentId)) {
return currentId;
}
currentId = parentById[currentId];
}
return 'root';
};

View File

@@ -0,0 +1,395 @@
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { select, curveLinear, selectAll } from 'd3';
import { getConfig } from '../../../config.js';
import utils from '../../../utils.js';
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';
import { log } from '../../../logger.js';
import common, { evaluate } from '../../common/common.js';
import { interpolateToCurve, getStylesFromArray } from '../../../utils.js';
const conf = {};
export const setConf = function (cnf) {
const keys = Object.keys(cnf);
for (const key of keys) {
conf[key] = cnf[key];
}
};
/**
* Add edges to graph based on parsed graph definition
*
* @param {object} edges The edges to add to the graph
* @param {object} g The graph object
* @param diagObj
*/
export const addEdges = function (edges, g, diagObj,svg) {
log.info('abc78 edges = ', edges);
let cnt = 0;
let linkIdCnt = {};
let defaultStyle;
let defaultLabelStyle;
if (edges.defaultStyle !== undefined) {
const defaultStyles = getStylesFromArray(edges.defaultStyle);
defaultStyle = defaultStyles.style;
defaultLabelStyle = defaultStyles.labelStyle;
}
edges.forEach(function (edge) {
cnt++;
// Identify Link
var linkIdBase = 'L-' + edge.start + '-' + edge.end;
// count the links from+to the same node to give unique id
if (linkIdCnt[linkIdBase] === undefined) {
linkIdCnt[linkIdBase] = 0;
log.info('abc78 new entry', linkIdBase, linkIdCnt[linkIdBase]);
} else {
linkIdCnt[linkIdBase]++;
log.info('abc78 new entry', linkIdBase, linkIdCnt[linkIdBase]);
}
let linkId = linkIdBase + '-' + linkIdCnt[linkIdBase];
log.info('abc78 new link id to be used is', linkIdBase, linkId, linkIdCnt[linkIdBase]);
var linkNameStart = 'LS-' + edge.start;
var linkNameEnd = 'LE-' + edge.end;
const edgeData = { style: '', labelStyle: '' };
edgeData.minlen = edge.length || 1;
//edgeData.id = 'id' + cnt;
// 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 = '';
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;
case 'invisible':
edgeData.thickness = 'invisible';
edgeData.pattern = 'solid';
edgeData.style = 'stroke-width: 0;fill:none;';
break;
}
if (edge.style !== undefined) {
const styles = getStylesFromArray(edge.style);
style = styles.style;
labelStyle = styles.labelStyle;
}
edgeData.style = edgeData.style += style;
edgeData.labelStyle = edgeData.labelStyle += labelStyle;
if (edge.interpolate !== undefined) {
edgeData.curve = interpolateToCurve(edge.interpolate, curveLinear);
} else if (edges.defaultInterpolate !== undefined) {
edgeData.curve = interpolateToCurve(edges.defaultInterpolate, curveLinear);
} else {
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:');
edgeData.id = linkId;
edgeData.classes = 'flowchart-link ' + linkNameStart + ' ' + linkNameEnd;
// Add the edge to the graph
g.setEdge(edge.start, edge.end, edgeData, cnt);
});
};
/**
* Function that adds the vertices found during parsing to the graph to be rendered.
*
* @param vert Object containing the vertices.
* @param g The graph that is to be drawn.
* @param svgId
* @param root
* @param doc
* @param diagObj
*/
export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
const svg = root.select(`[id="${svgId}"]`);
const keys = Object.keys(vert);
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
keys.forEach(function (id) {
const vertex = vert[id];
/**
* Variable for storing the classes for the vertex
*
* @type {string}
*/
let classStr = 'default';
if (vertex.classes.length > 0) {
classStr = vertex.classes.join(' ');
}
classStr = classStr + ' flowchart-label';
const styles = getStylesFromArray(vertex.styles);
// Use vertex id as text in the box if no text is provided by the graph definition
let vertexText = vertex.text !== undefined ? vertex.text : vertex.id;
// We create a SVG label, either by delegating to addHtmlLabel or manually
let vertexNode;
log.info('vertex', vertex, vertex.labelType);
if (vertex.labelType === 'markdown') {
log.info('vertex', vertex, vertex.labelType);
} else {
if (evaluate(getConfig().flowchart.htmlLabels) && svg.html) {
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
const node = {
label: vertexText.replace(
/fa[blrs]?:fa-[\w-]+/g,
(s) => `<i class='${s.replace(':', ' ')}'></i>`
),
};
vertexNode = addHtmlLabel(svg, node).node();
vertexNode.parentNode.removeChild(vertexNode);
} else {
const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text');
svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:'));
const rows = vertexText.split(common.lineBreakRegex);
for (const row of rows) {
const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan');
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
tspan.setAttribute('dy', '1em');
tspan.setAttribute('x', '1');
tspan.textContent = row;
svgLabel.appendChild(tspan);
}
vertexNode = svgLabel;
}
}
let radious = 0;
let _shape = '';
// Set the shape based parameters
switch (vertex.type) {
case 'round':
radious = 5;
_shape = 'rect';
break;
case 'square':
_shape = 'rect';
break;
case 'diamond':
_shape = 'question';
break;
case 'hexagon':
_shape = 'hexagon';
break;
case 'odd':
_shape = 'rect_left_inv_arrow';
break;
case 'lean_right':
_shape = 'lean_right';
break;
case 'lean_left':
_shape = 'lean_left';
break;
case 'trapezoid':
_shape = 'trapezoid';
break;
case 'inv_trapezoid':
_shape = 'inv_trapezoid';
break;
case 'odd_right':
_shape = 'rect_left_inv_arrow';
break;
case 'circle':
_shape = 'circle';
break;
case 'ellipse':
_shape = 'ellipse';
break;
case 'stadium':
_shape = 'stadium';
break;
case 'subroutine':
_shape = 'subroutine';
break;
case 'cylinder':
_shape = 'cylinder';
break;
case 'group':
_shape = 'rect';
break;
case 'doublecircle':
_shape = 'doublecircle';
break;
default:
_shape = 'rect';
}
// Add the node
g.setNode(vertex.id, {
labelStyle: styles.labelStyle,
shape: _shape,
labelText: vertexText,
labelType: vertex.labelType,
rx: radious,
ry: radious,
class: classStr,
style: styles.style,
id: vertex.id,
link: vertex.link,
linkTarget: vertex.linkTarget,
tooltip: diagObj.db.getTooltip(vertex.id) || '',
domId: diagObj.db.lookUpDomId(vertex.id),
haveCallback: vertex.haveCallback,
width: vertex.type === 'group' ? 500 : undefined,
dir: vertex.dir,
type: vertex.type,
props: vertex.props,
padding: getConfig().flowchart.padding,
});
log.info('setNode', {
labelStyle: styles.labelStyle,
labelType: vertex.labelType,
shape: _shape,
labelText: vertexText,
rx: radious,
ry: radious,
class: classStr,
style: styles.style,
id: vertex.id,
domId: diagObj.db.lookUpDomId(vertex.id),
width: vertex.type === 'group' ? 500 : undefined,
type: vertex.type,
dir: vertex.dir,
props: vertex.props,
padding: getConfig().flowchart.padding,
});
});
};
/**
*
* @param diagObj
* @param id
* @param root
* @param doc
*/
function setupGraph(diagObj, id, root, doc) {
const { securityLevel, flowchart: conf } = getConfig();
const nodeSpacing = conf.nodeSpacing || 50;
const rankSpacing = conf.rankSpacing || 50;
// Fetch the default direction, use TD if none was found
let dir = diagObj.db.getDirection();
if (dir === undefined) {
dir = 'TD';
}
// Create the input mermaid.graph
const g = new graphlib.Graph({
multigraph: true,
compound: true,
})
.setGraph({
rankdir: dir,
nodesep: nodeSpacing,
ranksep: rankSpacing,
marginx: 0,
marginy: 0,
})
.setDefaultEdgeLabel(function () {
return {};
});
let subG;
const subGraphs = diagObj.db.getSubGraphs();
// Fetch the vertices/nodes and edges/links from the parsed graph definition
const vert = diagObj.db.getVertices();
const edges = diagObj.db.getEdges();
log.info('Edges', edges);
let i = 0;
// for (i = subGraphs.length - 1; i >= 0; i--) {
// // for (let i = 0; i < subGraphs.length; i++) {
// subG = subGraphs[i];
// selectAll('cluster').append('text');
// for (let j = 0; j < subG.nodes.length; j++) {
// log.info('Setting up subgraphs', subG.nodes[j], subG.id);
// g.setParent(subG.nodes[j], subG.id);
// }
// }
addVertices(vert, g, id, root, doc, diagObj);
addEdges(edges, g, diagObj);
return g;
}
export default setupGraph;

View File

@@ -0,0 +1,143 @@
/** Returns the styles given options */
export interface FlowChartStyleOptions {
arrowheadColor: string;
border2: string;
clusterBkg: string;
clusterBorder: string;
edgeLabelBackground: string;
fontFamily: string;
lineColor: string;
mainBkg: string;
nodeBorder: string;
nodeTextColor: string;
tertiaryColor: string;
textColor: string;
titleColor: string;
[key: string]: string;
}
const genSections = (options: FlowChartStyleOptions) => {
let sections = '';
for (let i = 0; i < 5; i++) {
sections += `
.subgraph-lvl-${i} {
fill: ${options[`surface${i}`]};
stroke: ${options[`surfacePeer${i}`]};
}
`;
}
return sections;
};
const getStyles = (options: FlowChartStyleOptions) =>
`.label {
font-family: ${options.fontFamily};
color: ${options.nodeTextColor || options.textColor};
}
.cluster-label text {
fill: ${options.titleColor};
}
.cluster-label span {
color: ${options.titleColor};
}
.label text,span {
fill: ${options.nodeTextColor || options.textColor};
color: ${options.nodeTextColor || options.textColor};
}
.node rect,
.node circle,
.node ellipse,
.node polygon,
.node path {
fill: ${options.mainBkg};
stroke: ${options.nodeBorder};
stroke-width: 1px;
}
.node .label {
text-align: center;
}
.node.clickable {
cursor: pointer;
}
.arrowheadPath {
fill: ${options.arrowheadColor};
}
.edgePath .path {
stroke: ${options.lineColor};
stroke-width: 2.0px;
}
.flowchart-link {
stroke: ${options.lineColor};
fill: none;
}
.edgeLabel {
background-color: ${options.edgeLabelBackground};
rect {
opacity: 0.85;
background-color: ${options.edgeLabelBackground};
fill: ${options.edgeLabelBackground};
}
text-align: center;
}
.cluster rect {
fill: ${options.clusterBkg};
stroke: ${options.clusterBorder};
stroke-width: 1px;
}
.cluster text {
fill: ${options.titleColor};
}
.cluster span {
color: ${options.titleColor};
}
/* .cluster div {
color: ${options.titleColor};
} */
div.mermaidTooltip {
position: absolute;
text-align: center;
max-width: 200px;
padding: 2px;
font-family: ${options.fontFamily};
font-size: 12px;
background: ${options.tertiaryColor};
border: 1px solid ${options.border2};
border-radius: 2px;
pointer-events: none;
z-index: 100;
}
.flowchartTitleText {
text-anchor: middle;
font-size: 18px;
fill: ${options.textColor};
}
.subgraph {
stroke-width:2;
rx:3;
}
// .subgraph-lvl-1 {
// fill:#ccc;
// // stroke:black;
// }
.flowchart-label text {
text-anchor: middle;
}
${genSections(options)}
`;
export default getStyles;

View File

@@ -0,0 +1,13 @@
// @ts-ignore: JISON typing missing
import parser from '../parser/flow.jison';
import * as db from '../flowDb.js';
import renderer from './swimlaneRenderer.js';
import styles from './styles.js';
export const diagram = {
db,
renderer,
parser,
styles,
};

View File

@@ -0,0 +1,220 @@
import { log } from '../../../logger.js';
import flowDb from '../flowDb.js';
export const getSubgraphLookupTable = function (diagObj) {
const subGraphs = diagObj.db.getSubGraphs();
const subgraphDb = {};
log.info('Subgraphs - ', subGraphs);
for (let i = subGraphs.length - 1; i >= 0; i--) {
const subG = subGraphs[i];
log.info('Subgraph - ', subG);
for (let j = 0; j < subG.nodes.length; j++) {
log.info('Setting up subgraphs', subG.nodes[j], subG.id);
subgraphDb[flowDb.lookUpId(subG.nodes[j])] = subG.id;
}
}
return subgraphDb;
};
/**
*
* @param graph
* @param subgraphLookupTable
*/
export function assignRanks(graph, subgraphLookupTable) {
let visited = new Set();
const lock = new Map();
const ranks = new Map();
let cnt = 0;
let changesDetected = true;
/**
*
* @param nodeId
* @param currentRank
*/
function dfs(nodeId, currentRank) {
if (visited.has(nodeId)) {
return;
}
visited.add(nodeId);
const existingRank = ranks.get(nodeId) || 0;
// console.log('APA444 DFS Base case for', nodeId, 'to', Math.max(existingRank, currentRank));
if (lock.get(nodeId) !== 1) {
ranks.set(nodeId, Math.max(existingRank, currentRank));
} else {
console.log(
'APA444 ',
nodeId,
'was locked to ',
existingRank,
'so not changing it',
ranks.get(nodeId)
);
}
const currentRankAdjusted = ranks.get(nodeId) || currentRank;
graph.successors(nodeId).forEach((targetId) => {
if (subgraphLookupTable[targetId] !== subgraphLookupTable[nodeId]) {
dfs(targetId, currentRankAdjusted);
} else {
// In same line, easy increase
dfs(targetId, currentRankAdjusted + 1);
}
});
}
/**
*
*/
function adjustSuccessors() {
console.log('APA444 Adjusting successors');
graph.nodes().forEach((nodeId) => {
console.log('APA444 Going through nodes', nodeId);
// if (graph.predecessors(nodeId).length === 0) {
console.log('APA444 has no predecessors', nodeId);
graph.successors(nodeId).forEach((successorNodeId) => {
console.log('APA444 has checking successor', successorNodeId);
if (subgraphLookupTable[successorNodeId] !== subgraphLookupTable[nodeId]) {
const newRank = ranks.get(successorNodeId);
ranks.set(nodeId, newRank);
console.log('APA444 POST-process case for', nodeId, 'to', newRank);
lock.set(nodeId, 1);
changesDetected = true;
// setRankFromTopNodes();
// Adjust ranks of successors in the same subgraph
graph.successors(nodeId).forEach((sameSubGraphSuccessorNodeId) => {
if (subgraphLookupTable[sameSubGraphSuccessorNodeId] === subgraphLookupTable[nodeId]) {
console.log(
'APA444 Adjusting rank of',
sameSubGraphSuccessorNodeId,
'to',
newRank + 1
);
ranks.set(sameSubGraphSuccessorNodeId, newRank + 1);
lock.set(sameSubGraphSuccessorNodeId, 1);
changesDetected = true;
// dfs(sameSubGraphSuccessorNodeId, newRank + 1);
// setRankFromTopNodes();
}
});
} else {
console.log('APA444 Node', nodeId, ' and ', successorNodeId, ' is in the same lane');
}
});
// }
});
}
/**
*
*/
function setRankFromTopNodes() {
visited = new Set();
graph.nodes().forEach((nodeId) => {
if (graph.predecessors(nodeId).length === 0) {
dfs(nodeId, 0);
}
});
adjustSuccessors();
}
while (changesDetected && cnt < 10) {
setRankFromTopNodes();
cnt++;
}
// Post-process the ranks
return ranks;
}
/**
*
* @param graph
* @param subgraphLÖookupTable
* @param ranks
* @param subgraphLookupTable
*/
export function assignAffinities(graph, ranks, subgraphLookupTable) {
const affinities = new Map();
const swimlaneRankAffinities = new Map();
const swimlaneMaxAffinity = new Map();
graph.nodes().forEach((nodeId) => {
const swimlane = subgraphLookupTable[nodeId];
const rank = ranks.get(nodeId);
const key = swimlane + ':' + rank;
let currentAffinity = swimlaneRankAffinities.get(key);
if (currentAffinity === undefined) {
currentAffinity = -1;
}
const newAffinity = currentAffinity + 1;
swimlaneRankAffinities.set(key, newAffinity);
affinities.set(nodeId, newAffinity);
let currentMaxAffinity = swimlaneMaxAffinity.get(swimlane);
if (currentMaxAffinity === undefined) {
swimlaneMaxAffinity.set(swimlane, 0);
currentMaxAffinity = 0;
}
if (newAffinity > currentMaxAffinity) {
swimlaneMaxAffinity.set(swimlane, newAffinity);
}
});
// console.log('APA444 affinities', swimlaneRankAffinities);
return { affinities, swimlaneMaxAffinity };
//return affinities;
}
/**
*
* @param graph
* @param diagObj
*/
export function swimlaneLayout(graph, diagObj) {
const subgraphLookupTable = getSubgraphLookupTable(diagObj);
const ranks = assignRanks(graph, subgraphLookupTable);
const { affinities, swimlaneMaxAffinity } = assignAffinities(graph, ranks, subgraphLookupTable);
// const affinities = assignAffinities(graph, ranks, subgraphLookupTable);
const subGraphs = diagObj.db.getSubGraphs();
const lanes = [];
const laneDb = {};
let xPos = 0;
for (const subG of subGraphs) {
const maxAffinity = swimlaneMaxAffinity.get(subG.id);
const lane = {
title: subG.title,
x: xPos,
width: 200 + maxAffinity * 150,
};
xPos += lane.width;
lanes.push(lane);
laneDb[subG.id] = lane;
}
const rankWidth = [];
// Basic layout, calculate the node positions based on rank
graph.nodes().forEach((nodeId) => {
const rank = ranks.get(nodeId);
if (!rankWidth[rank]) {
const laneId = subgraphLookupTable[nodeId];
const lane = laneDb[laneId];
const n = graph.node(nodeId);
console.log('Node', nodeId, n);
const affinity = affinities.get(nodeId);
console.log('APA444', nodeId, 'rank', rank, 'affinity', affinity);
graph.setNode(nodeId, { y: rank * 200 + 50, x: lane.x + 150 * affinity + 100 });
// lane.width = Math.max(lane.width, lane.x + 150*affinity + lane.width / 4);
}
});
return { graph, lanes };
}

View File

@@ -0,0 +1,129 @@
import flowDb from '../flowDb.js';
import { cleanupComments } from '../../../diagram-api/comments.js';
import setupGraph from './setup-graph.js';
import { swimlaneLayout, assignRanks, getSubgraphLookupTable } from './swimlane-layout.js';
import { getDiagramFromText } from '../../../Diagram.js';
import { addDiagrams } from '../../../diagram-api/diagram-orchestration.ts';
import jsdom from 'jsdom';
const { JSDOM } = jsdom;
addDiagrams();
describe('When doing a assigning ranks specific for swim lanes ', () => {
let root;
let doc;
beforeEach(function () {
const dom = new JSDOM(`<!DOCTYPE html><body><pre id="swimmer">My First JSDOM!</pre></body>`);
root = select(dom.window.document.getElementById('swimmer'));
root.html = () => {
' return <div>hello</div>';
};
doc = dom.window.document;
});
describe('Layout: ', () => {
// it('should rank the nodes:', async () => {
// const diagram = await getDiagramFromText(`swimlane LR
// subgraph "\`one\`"
// start --> cat --> rat
// end`);
// const g = setupGraph(diagram, 'swimmer', root, doc);
// const subgraphLookupTable = getSubgraphLookupTable(diagram);
// const ranks = assignRanks(g, subgraphLookupTable);
// expect(ranks.get('start')).toEqual(0);
// expect(ranks.get('cat')).toEqual(1);
// expect(ranks.get('rat')).toEqual(2);
// });
it('should rank the nodes:', async () => {
const diagram = await getDiagramFromText(`swimlane LR
subgraph "\`one\`"
start --> cat --> rat
end
subgraph "\`two\`"
monkey --> dog --> done
end
cat --> monkey`);
const g = setupGraph(diagram, 'swimmer', root, doc);
const subgraphLookupTable = getSubgraphLookupTable(diagram);
const ranks = assignRanks(g, subgraphLookupTable);
expect(ranks.get('start')).toEqual(0);
expect(ranks.get('cat')).toEqual(1);
expect(ranks.get('rat')).toEqual(2);
expect(ranks.get('monkey')).toEqual(1);
expect(ranks.get('dog')).toEqual(2);
expect(ranks.get('done')).toEqual(3);
});
});
describe('Layout: ', () => {
it('should rank the nodes:', async () => {
const diagram = await getDiagramFromText(`swimlane LR
subgraph "\`one\`"
start --> cat --> rat
end`);
const g = setupGraph(diagram, 'swimmer', root, doc);
const subgraphLookupTable = getSubgraphLookupTable(diagram);
const { graph, lanes } = swimlaneLayout(g, diagram);
expect(lanes.length).toBe(1);
const start = graph.node('start');
const cat = graph.node('cat');
const rat = graph.node('rat');
expect(start.y).toBe(50);
expect(cat.y).toBe(250);
expect(rat.y).toBe(450);
expect(rat.x).toBe(100);
});
it('should rank the nodes:', async () => {
const diagram = await getDiagramFromText(`swimlane LR
subgraph "\`one\`"
start --> cat --> rat
end
subgraph "\`two\`"
monkey --> dog --> done
end
cat --> monkey`);
const g = setupGraph(diagram, 'swimmer', root, doc);
const subgraphLookupTable = getSubgraphLookupTable(diagram);
const { graph, lanes } = swimlaneLayout(g, diagram);
expect(lanes.length).toBe(2);
const start = graph.node('start');
const cat = graph.node('cat');
const rat = graph.node('rat');
const monkey = graph.node('monkey');
const dog = graph.node('dog');
const done = graph.node('done');
expect(start.y).toBe(50);
expect(cat.y).toBe(250);
expect(rat.y).toBe(450);
expect(rat.x).toBe(100);
expect(monkey.y).toBe(250);
expect(dog.y).toBe(450);
expect(done.y).toBe(650);
expect(monkey.x).toBe(300);
});
it.only('should rank the nodes:', async () => {
const diagram = await getDiagramFromText(`swimlane LR
subgraph "\`one\`"
start --> cat --> rat & hat
end
`);
const g = setupGraph(diagram, 'swimmer', root, doc);
const subgraphLookupTable = getSubgraphLookupTable(diagram);
const { graph, lanes } = swimlaneLayout(g, diagram);
expect(lanes.length).toBe(1);
const start = graph.node('start');
const cat = graph.node('cat');
const rat = graph.node('rat');
const hat = graph.node('rat');
expect(start.y).toBe(50);
expect(cat.y).toBe(250);
expect(rat.y).toBe(450);
expect(rat.x).toBe(300);
expect(hat.y).toBe(450);
expect(hat.x).toBe(100);
});
});
});

View File

@@ -0,0 +1,596 @@
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { select, curveLinear, selectAll } from 'd3';
import { swimlaneLayout } from './swimlane-layout.js';
import insertMarkers from '../../../dagre-wrapper/markers.js';
import { insertNode } from '../../../dagre-wrapper/nodes.js';
import flowDb from '../flowDb.js';
import { getConfig } from '../../../config.js';
import {getStylesFromArray} from '../../../utils.js';
import setupGraph, { addEdges, addVertices } from './setup-graph.js';
import { render } from '../../../dagre-wrapper/index.js';
import { log } from '../../../logger.js';
import { setupGraphViewbox } from '../../../setupGraphViewbox.js';
import common, { evaluate } from '../../common/common.js';
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';
import { insertEdge,positionEdgeLabel } from '../../../dagre-wrapper/edges.js';
import {
clear as clearGraphlib,
clusterDb,
adjustClustersAndEdges,
findNonClusterChild,
sortNodesByHierarchy,
} from '../../../dagre-wrapper/mermaid-graphlib.js';
const conf = {};
export const setConf = function (cnf) {
const keys = Object.keys(cnf);
for (const key of keys) {
conf[key] = cnf[key];
}
};
/**
*
* @param element
* @param graph
* @param layout
* @param vert
* @param elem
* @param g
* @param id
* @param conf
*/
async function swimlaneRender(layout,vert, elem,g, id, conf) {
let renderedNodes = [];
// draw nodes from layout.graph to element
const nodes = layout.graph.nodes();
// lanes are the swimlanes
const lanes = layout.lanes;
const nodesElements = elem.insert('g').attr('class', 'nodes');
// for each node, draw a rect, with a child text inside as label
for (const node of nodes) {
const nodeFromLayout = layout.graph.node(node);
const vertex = vert[node];
//Initialise the node
/**
* Variable for storing the classes for the vertex
*
* @type {string}
*/
let classStr = 'default';
if (vertex.classes.length > 0) {
classStr = vertex.classes.join(' ');
}
classStr = classStr + ' swimlane-label';
const styles = getStylesFromArray(vertex.styles);
// Use vertex id as text in the box if no text is provided by the graph definition
let vertexText = vertex.text !== undefined ? vertex.text : vertex.id;
// We create a SVG label, either by delegating to addHtmlLabel or manually
let vertexNode;
log.info('vertex', vertex, vertex.labelType);
if (vertex.labelType === 'markdown') {
log.info('vertex', vertex, vertex.labelType);
} else {
if (evaluate(getConfig().flowchart.htmlLabels)) {
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
const node = {
label: vertexText.replace(
/fa[blrs]?:fa-[\w-]+/g,
(s) => `<i class='${s.replace(':', ' ')}'></i>`
),
};
vertexNode = addHtmlLabel(elem, node).node();
vertexNode.parentNode.removeChild(vertexNode);
} else {
const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text');
svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:'));
const rows = vertexText.split(common.lineBreakRegex);
for (const row of rows) {
const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan');
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
tspan.setAttribute('dy', '1em');
tspan.setAttribute('x', '1');
tspan.textContent = row;
svgLabel.appendChild(tspan);
}
vertexNode = svgLabel;
}
}
let radious = 0;
let _shape = '';
// Set the shape based parameters
switch (vertex.type) {
case 'round':
radious = 5;
_shape = 'rect';
break;
case 'square':
_shape = 'rect';
break;
case 'diamond':
_shape = 'question';
break;
case 'hexagon':
_shape = 'hexagon';
break;
case 'odd':
_shape = 'rect_left_inv_arrow';
break;
case 'lean_right':
_shape = 'lean_right';
break;
case 'lean_left':
_shape = 'lean_left';
break;
case 'trapezoid':
_shape = 'trapezoid';
break;
case 'inv_trapezoid':
_shape = 'inv_trapezoid';
break;
case 'odd_right':
_shape = 'rect_left_inv_arrow';
break;
case 'circle':
_shape = 'circle';
break;
case 'ellipse':
_shape = 'ellipse';
break;
case 'stadium':
_shape = 'stadium';
break;
case 'subroutine':
_shape = 'subroutine';
break;
case 'cylinder':
_shape = 'cylinder';
break;
case 'group':
_shape = 'rect';
break;
case 'doublecircle':
_shape = 'doublecircle';
break;
default:
_shape = 'rect';
}
// Add the node
let nodeObj ={
labelStyle: styles.labelStyle,
shape: _shape,
labelText: vertexText,
labelType: vertex.labelType,
rx: radious,
ry: radious,
class: classStr,
style: styles.style,
id: vertex.id,
link: vertex.link,
linkTarget: vertex.linkTarget,
// tooltip: diagObj.db.getTooltip(vertex.id) || '',
// domId: diagObj.db.lookUpDomId(vertex.id),
haveCallback: vertex.haveCallback,
width: vertex.type === 'group' ? 500 : undefined,
dir: vertex.dir,
type: vertex.type,
props: vertex.props,
padding: getConfig().flowchart.padding,
x: nodeFromLayout.x,
y: nodeFromLayout.y,
};
let boundingBox;
let nodeEl;
// Add the element to the DOM
nodeEl = await insertNode(nodesElements, nodeObj, vertex.dir);
boundingBox = nodeEl.node().getBBox();
nodeEl.attr('transform', `translate(${nodeObj.x}, ${nodeObj.y / 2})`);
// add to rendered nodes
renderedNodes.push({id: vertex.id, nodeObj: nodeObj, boundingBox: boundingBox});
}
return renderedNodes;
}
/**
* Returns the all the styles from classDef statements in the graph definition.
*
* @param text
* @param diagObj
* @returns {object} ClassDef styles
*/
// export const getClasses = function (text, diagObj) {
// log.info('Extracting classes');
// diagObj.db.clear();
// try {
// // Parse the graph definition
// diagObj.parse(text);
// return diagObj.db.getClasses();
// } catch (e) {
// return;
// }
// };
/**
* Returns the all the styles from classDef statements in the graph definition.
*
* @param text
* @param diagObj
* @returns {Record<string, import('../../../diagram-api/types.js').DiagramStyleClassDef>} ClassDef styles
*/
export const getClasses = function (text, diagObj) {
log.info('Extracting classes');
return diagObj.db.getClasses();
};
/**
* Draws a flowchart in the tag with id: id based on the graph definition in text.
*
* @param text
* @param id
*/
export const draw = async function (text, id, _version, diagObj) {
log.info('Drawing flowchart');
diagObj.db.clear();
flowDb.setGen('gen-2');
// Parse the graph definition
diagObj.parser.parse(text);
const { securityLevel, flowchart: conf } = getConfig();
// Handle root and document for when rendering in sandbox mode
let sandboxElement;
if (securityLevel === 'sandbox') {
sandboxElement = select('#i' + id);
}
const root =
securityLevel === 'sandbox'
? select(sandboxElement.nodes()[0].contentDocument.body)
: select('body');
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
// create g as a graphlib graph using setupGraph from setup-graph.js
const g = setupGraph(diagObj, id, root, doc);
let subG;
const subGraphs = diagObj.db.getSubGraphs();
log.info('Subgraphs - ', subGraphs);
for (let i = subGraphs.length - 1; i >= 0; i--) {
subG = subGraphs[i];
log.info('Subgraph - ', subG);
diagObj.db.addVertex(
subG.id,
{ text: subG.title, type: subG.labelType },
'group',
undefined,
subG.classes,
subG.dir
);
}
// Fetch the vertices/nodes and edges/links from the parsed graph definition
const vert = diagObj.db.getVertices();
const edges = diagObj.db.getEdges();
log.info('Edges', edges);
const svg = root.select('#' + id);
svg.append('g');
// Run the renderer. This is what draws the final graph.
// const element = root.select('#' + id + ' g');
console.log('diagObj',diagObj);
console.log('subGraphs', diagObj.db.getSubGraphs());
const layout = swimlaneLayout(g, diagObj);
console.log('custom layout',layout);
// insert markers
// Define the supported markers for the diagram
const markers = ['point', 'circle', 'cross'];
insertMarkers(svg, markers, 'flowchart', id);
// draw lanes as vertical lines
const lanesElements = svg.insert('g').attr('class', 'lanes');
let laneCount = 0;
for (const lane of layout.lanes) {
laneCount++;
//draw lane header as rectangle with lane title centered in it
const laneHeader = document.createElementNS("http://www.w3.org/2000/svg", "rect");
// Set attributes for the rectangle
laneHeader.setAttribute("x",lane.x); // x-coordinate of the top-left corner
laneHeader.setAttribute("y", -50); // y-coordinate of the top-left corner
laneHeader.setAttribute("width", lane.width); // width of the rectangle
laneHeader.setAttribute("height", "50"); // height of the rectangle
if(laneCount % 2 == 0){
//set light blue color for even lanes
laneHeader.setAttribute("fill", "blue"); // fill color of the rectangle
}else{
//set white color odd lanes
laneHeader.setAttribute("fill", "grey"); // fill color of the rectangle
}
laneHeader.setAttribute("stroke", "black"); // color of the stroke/border
laneHeader.setAttribute("stroke-width", "2"); // width of the stroke/border
// Append the rectangle to the SVG element
lanesElements.node().appendChild(laneHeader);
//draw lane title
const laneTitle = document.createElementNS("http://www.w3.org/2000/svg", "text");
// Set attributes for the rectangle
laneTitle.setAttribute("x",lane.x + lane.width/2); // x-coordinate of the top-left corner
laneTitle.setAttribute("y", -50 + 50/2); // y-coordinate of the top-left corner
laneTitle.setAttribute("width", lane.width); // width of the rectangle
laneTitle.setAttribute("height", "50"); // height of the rectangle
laneTitle.setAttribute("fill", "white"); // fill color of the rectangle
laneTitle.setAttribute("stroke-width", "1"); // width of the stroke/border
laneTitle.setAttribute("text-anchor", "middle"); // width of the stroke/border
laneTitle.setAttribute("alignment-baseline", "middle"); // width of the stroke/border
laneTitle.setAttribute("font-size", "20"); // width of the stroke/border
laneTitle.textContent = lane.title;
// Append the rectangle to the SVG element
lanesElements.node().appendChild(laneTitle);
//draw lane
// Create a <rect> element
const rectangle = document.createElementNS("http://www.w3.org/2000/svg", "rect");
// Set attributes for the rectangle
rectangle.setAttribute("x",lane.x); // x-coordinate of the top-left corner
rectangle.setAttribute("y", 0); // y-coordinate of the top-left corner
rectangle.setAttribute("width", lane.width); // width of the rectangle
rectangle.setAttribute("height", "500"); // height of the rectangle
if(laneCount % 2 == 0){
//set light blue color for even lanes
rectangle.setAttribute("fill", "lightblue"); // fill color of the rectangle
}else{
//set white color odd lanes
rectangle.setAttribute("fill", "#ffffff"); // fill color of the rectangle
}
rectangle.setAttribute("stroke", "black"); // color of the stroke/border
rectangle.setAttribute("stroke-width", "2"); // width of the stroke/border
// Append the rectangle to the SVG element
lanesElements.node().appendChild(rectangle);
}
// append lanesElements to elem
svg.node().appendChild(lanesElements.node());
// add lane headers
const laneHeaders = svg.insert('g').attr('class', 'laneHeaders');
let drawnEdges =[];
//get edge markers
let renderedNodes = await swimlaneRender(layout,vert, svg,g,id, conf);
let renderedEdgePaths= [];
addEdges(edges, g, diagObj,svg);
g.edges().forEach(function (e) {
const edge = g.edge(e);
log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge);
const edgePaths = svg.insert('g').attr('class', 'edgePaths');
//get start node x, y coordinates
let sourceNode = {x:layout.graph.node(e.v).x, y:layout.graph.node(e.v).y/2, id: e.v};
//get end node x, y coordinates=
const targetNode = {x:layout.graph.node(e.w).x, y:layout.graph.node(e.w).y/2, id: e.w};
//create edge points based on start and end node
edge.points = getEdgePoints(sourceNode, targetNode, drawnEdges, renderedNodes,renderedEdgePaths);
// add to drawn edges
drawnEdges.push(edge);
const paths = insertEdge(edgePaths, e, edge, clusterDb, 'flowchart', g);
//positionEdgeLabel(edge, paths);
});
// utils.insertTitle(svg, 'flowchartTitleText', conf.titleTopMargin, diagObj.db.getDiagramTitle());
setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth);
};
// function to find edge path points based on start and end node
/**
*
* @param startNode
* @param endNode
* @param drawnEdges
* @param renderedNodes
*/
function getEdgePoints(startNode, endNode, drawnEdges, renderedNodes) {
let potentialEdgePaths = [];
for(let i=1;i<=3;i++){
const points = [];
// add start point
points.push({ x: startNode.x, y: startNode.y })
// Point in the middle, if both nodes do not have same x or y
if (startNode.x !== endNode.x && startNode.y !== endNode.y && i!=1) {
if(i==2){
points.push({ x: startNode.x, y: endNode.y });
}else{
points.push({ x: endNode.x, y: startNode.y });
}
}
// add end point
points.push({ x: endNode.x, y: endNode.y });
//print points
console.log('points before intersection', points);
// get start and end node objects from array of rendered nodes
const startNodeObj = renderedNodes.find(node => node.id === startNode.id);
const endNodeObj = renderedNodes.find(node => node.id === endNode.id);
console.log(" intersection startNodeObj", startNodeObj);
console.log(" intersection endNodeObj", endNodeObj);
startNodeObj.nodeObj.x = startNode.x;
startNodeObj.nodeObj.y = startNode.y;
// the first point should be the intersection of the start node and the edge
let startInsection = startNodeObj.nodeObj.intersect(points[1]);
points[0] = startInsection;
//log intersection
console.log('start intersection', startInsection);
endNodeObj.nodeObj.x = endNode.x;
endNodeObj.nodeObj.y = endNode.y;
// the last point should be the intersection of the end node and the edge
let endInsection = endNodeObj.nodeObj.intersect(points[points.length - 2]);
points[points.length - 1] = endInsection;
//log intersection
console.log('end intersection', endInsection);
//push points to potential edge paths
potentialEdgePaths.push({points: points});
}
// Create a new list of renderedNodes without the start and end node
const filteredRenderedNodes = renderedNodes.filter(node => node.id !== startNode.id && node.id !== endNode.id);
//Rank the potential edge path
const rankedEdgePaths = rankEdgePaths(potentialEdgePaths, filteredRenderedNodes);
if(startNode.id==='sheep' && endNode.id === 'dog'){
console.log('sheep--> dog rankedEdgePaths', rankedEdgePaths);
}
return rankedEdgePaths[0].edgePath.points;
}
// Function to check if a point is inside a nodes bounding box
/**
*
* @param point
* @param nodes
*/
function isPointInsideNode(point, nodes) {
let isInside = false;
for (const node of nodes) {
if (
point.x >= node.nodeObj.x &&
point.x <= node.nodeObj.x + node.boundingBox.width &&
point.y >= node.nodeObj.y &&
point.y <= node.nodeObj.y + node.boundingBox.height
) {
isInside = true;
}
}
return isInside;
}
// Ranks edgePaths (points) based on the number of intersections with nodes
/**
*
* @param edgePaths
* @param nodes
*/
function rankEdgePaths(edgePaths, nodes) {
let rankedEdgePaths = [];
for (const edgePath of edgePaths) {
let rank = 10 + edgePath.points.length;
for (const point of edgePath.points) {
if (isPointInsideNode(point, nodes)) {
// remove edge path
}
}
rankedEdgePaths.push({ rank: rank, edgePath: edgePath });
}
//sort on the basis of rank, highest rank first
rankedEdgePaths.sort((a, b) => (a.rank < b.rank ? 1 : -1));
return rankedEdgePaths;
}
/**
* Function to find if edge path is intersecting with any other edge path
* @param edgePath
* @param renderedEdgePaths
* @returns {boolean}
*/
function isEdgePathIntersecting(edgePath, renderedEdgePaths) {
let isIntersecting = false;
for (const renderedEdgePath of renderedEdgePaths) {
// check if line drawn from start point of edge path to start point of rendered edge path is intersecting with any other edge path
if (
common.isLineIntersecting(
edgePath.points[0],
renderedEdgePath.points[0],
edgePath.points[1],
renderedEdgePath.points[1]
)
) {
isIntersecting = true;
}
}
return isIntersecting;
}
export default {
setConf,
addVertices,
addEdges,
getClasses,
draw,
};

View File

@@ -0,0 +1,269 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
describe('[Arrows] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});
it('should handle a nodes and edges', function () {
const res = flow.parser.parse('graph TD;\nA-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it("should handle angle bracket ' > ' as direction LR", function () {
const res = flow.parser.parse('graph >;A-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const direction = flow.parser.yy.getDirection();
expect(direction).toBe('LR');
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it("should handle angle bracket ' < ' as direction RL", function () {
const res = flow.parser.parse('graph <;A-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const direction = flow.parser.yy.getDirection();
expect(direction).toBe('RL');
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it("should handle caret ' ^ ' as direction BT", function () {
const res = flow.parser.parse('graph ^;A-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const direction = flow.parser.yy.getDirection();
expect(direction).toBe('BT');
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].length).toBe(1);
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it("should handle lower-case 'v' as direction TB", function () {
const res = flow.parser.parse('graph v;A-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const direction = flow.parser.yy.getDirection();
expect(direction).toBe('TB');
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle a nodes and edges and a space between link and node', function () {
const res = flow.parser.parse('graph TD;A --> B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle a nodes and edges, a space between link and node and each line ending without semicolon', function () {
const res = flow.parser.parse('graph TD\nA --> B\n style e red');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle statements ending without semicolon', function () {
const res = flow.parser.parse('graph TD\nA-->B\nB-->C');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(2);
expect(edges[1].start).toBe('B');
expect(edges[1].end).toBe('C');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
describe('it should handle multi directional arrows', function () {
describe('point', function () {
it('should handle double edged nodes and edges', function () {
const res = flow.parser.parse('graph TD;\nA<-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes with text', function () {
const res = flow.parser.parse('graph TD;\nA<-- text -->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('text');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes and edges on thick arrows', function () {
const res = flow.parser.parse('graph TD;\nA<==>B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes with text on thick arrows', function () {
const res = flow.parser.parse('graph TD;\nA<== text ==>B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('text');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes and edges on dotted arrows', function () {
const res = flow.parser.parse('graph TD;\nA<-.->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes with text on dotted arrows', function () {
const res = flow.parser.parse('graph TD;\nA<-. text .->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('text');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(1);
});
});
});
});

View File

@@ -0,0 +1,154 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
import { cleanupComments } from '../../../diagram-api/comments.js';
setConfig({
securityLevel: 'strict',
});
describe('[Comments] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});
it('should handle comments', function () {
const res = flow.parser.parse(cleanupComments('graph TD;\n%% Comment\n A-->B;'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
});
it('should handle comments at the start', function () {
const res = flow.parser.parse(cleanupComments('%% Comment\ngraph TD;\n A-->B;'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
});
it('should handle comments at the end', function () {
const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n %% Comment at the end\n'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
});
it('should handle comments at the end no trailing newline', function () {
const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n%% Comment'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
});
it('should handle comments at the end many trailing newlines', function () {
const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n%% Comment\n\n\n'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
});
it('should handle no trailing newlines', function () {
const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
});
it('should handle many trailing newlines', function () {
const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n\n'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
});
it('should handle a comment with blank rows in-between', function () {
const res = flow.parser.parse(cleanupComments('graph TD;\n\n\n %% Comment\n A-->B;'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
});
it('should handle a comment with mermaid flowchart code in them', function () {
const res = flow.parser.parse(
cleanupComments(
'graph TD;\n\n\n %% Test od>Odd shape]-->|Two line<br>edge comment|ro;\n A-->B;'
)
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
});
});

View File

@@ -0,0 +1,92 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
describe('when parsing directions', function () {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
flow.parser.yy.setGen('gen-2');
});
it('should use default direction from top level', function () {
const res = flow.parser.parse(`flowchart TB
subgraph A
a --> b
end`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(2);
expect(subgraph.nodes[0]).toBe('b');
expect(subgraph.nodes[1]).toBe('a');
expect(subgraph.id).toBe('A');
expect(subgraph.dir).toBe(undefined);
});
it('should handle a subgraph with a direction', function () {
const res = flow.parser.parse(`flowchart TB
subgraph A
direction BT
a --> b
end`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(2);
expect(subgraph.nodes[0]).toBe('b');
expect(subgraph.nodes[1]).toBe('a');
expect(subgraph.id).toBe('A');
expect(subgraph.dir).toBe('BT');
});
it('should use the last defined direction', function () {
const res = flow.parser.parse(`flowchart TB
subgraph A
direction BT
a --> b
direction RL
end`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(2);
expect(subgraph.nodes[0]).toBe('b');
expect(subgraph.nodes[1]).toBe('a');
expect(subgraph.id).toBe('A');
expect(subgraph.dir).toBe('RL');
});
it('should handle nested subgraphs 1', function () {
const res = flow.parser.parse(`flowchart TB
subgraph A
direction RL
b-->B
a
end
a-->c
subgraph B
direction LR
c
end`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(2);
const subgraphA = subgraphs.find((o) => o.id === 'A');
const subgraphB = subgraphs.find((o) => o.id === 'B');
expect(subgraphB.nodes[0]).toBe('c');
expect(subgraphB.dir).toBe('LR');
expect(subgraphA.nodes).toContain('B');
expect(subgraphA.nodes).toContain('b');
expect(subgraphA.nodes).toContain('a');
expect(subgraphA.nodes).not.toContain('c');
expect(subgraphA.dir).toBe('RL');
});
});

View File

@@ -0,0 +1,496 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
const keywords = [
'graph',
'flowchart',
'flowchart-elk',
'style',
'default',
'linkStyle',
'interpolate',
'classDef',
'class',
'href',
'call',
'click',
'_self',
'_blank',
'_parent',
'_top',
'end',
'subgraph',
'kitty',
];
const doubleEndedEdges = [
{ edgeStart: 'x--', edgeEnd: '--x', stroke: 'normal', type: 'double_arrow_cross' },
{ edgeStart: 'x==', edgeEnd: '==x', stroke: 'thick', type: 'double_arrow_cross' },
{ edgeStart: 'x-.', edgeEnd: '.-x', stroke: 'dotted', type: 'double_arrow_cross' },
{ edgeStart: 'o--', edgeEnd: '--o', stroke: 'normal', type: 'double_arrow_circle' },
{ edgeStart: 'o==', edgeEnd: '==o', stroke: 'thick', type: 'double_arrow_circle' },
{ edgeStart: 'o-.', edgeEnd: '.-o', stroke: 'dotted', type: 'double_arrow_circle' },
{ edgeStart: '<--', edgeEnd: '-->', stroke: 'normal', type: 'double_arrow_point' },
{ edgeStart: '<==', edgeEnd: '==>', stroke: 'thick', type: 'double_arrow_point' },
{ edgeStart: '<-.', edgeEnd: '.->', stroke: 'dotted', type: 'double_arrow_point' },
];
describe('[Edges] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});
it('should handle open ended edges', function () {
const res = flow.parser.parse('graph TD;A---B;');
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_open');
});
it('should handle cross ended edges', function () {
const res = flow.parser.parse('graph TD;A--xB;');
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
});
it('should handle open ended edges', function () {
const res = flow.parser.parse('graph TD;A--oB;');
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_circle');
});
describe('edges', function () {
doubleEndedEdges.forEach((edgeType) => {
it(`should handle ${edgeType.stroke} ${edgeType.type} with no text`, function () {
const res = flow.parser.parse(`graph TD;\nA ${edgeType.edgeStart}${edgeType.edgeEnd} B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe(`${edgeType.type}`);
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe(`${edgeType.stroke}`);
});
it(`should handle ${edgeType.stroke} ${edgeType.type} with text`, function () {
const res = flow.parser.parse(
`graph TD;\nA ${edgeType.edgeStart} text ${edgeType.edgeEnd} B;`
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe(`${edgeType.type}`);
expect(edges[0].text).toBe('text');
expect(edges[0].stroke).toBe(`${edgeType.stroke}`);
});
it.each(keywords)(
`should handle ${edgeType.stroke} ${edgeType.type} with %s text`,
function (keyword) {
const res = flow.parser.parse(
`graph TD;\nA ${edgeType.edgeStart} ${keyword} ${edgeType.edgeEnd} B;`
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe(`${edgeType.type}`);
expect(edges[0].text).toBe(`${keyword}`);
expect(edges[0].stroke).toBe(`${edgeType.stroke}`);
}
);
});
});
it('should handle multiple edges', function () {
const res = flow.parser.parse(
'graph TD;A---|This is the 123 s text|B;\nA---|This is the second edge|B;'
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(2);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('This is the 123 s text');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
expect(edges[1].start).toBe('A');
expect(edges[1].end).toBe('B');
expect(edges[1].type).toBe('arrow_open');
expect(edges[1].text).toBe('This is the second edge');
expect(edges[1].stroke).toBe('normal');
expect(edges[1].length).toBe(1);
});
describe('edge length', function () {
for (let length = 1; length <= 3; ++length) {
it(`should handle normal edges with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA -${'-'.repeat(length)}- B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle normal labelled edges with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA -- Label -${'-'.repeat(length)}- B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle normal edges with arrows with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA -${'-'.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle normal labelled edges with arrows with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA -- Label -${'-'.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle normal edges with double arrows with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA <-${'-'.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle normal labelled edges with double arrows with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA <-- Label -${'-'.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle thick edges with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA =${'='.repeat(length)}= B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle thick labelled edges with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA == Label =${'='.repeat(length)}= B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle thick edges with arrows with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA =${'='.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle thick labelled edges with arrows with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA == Label =${'='.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle thick edges with double arrows with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA <=${'='.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle thick labelled edges with double arrows with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA <== Label =${'='.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle dotted edges with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA -${'.'.repeat(length)}- B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle dotted labelled edges with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA -. Label ${'.'.repeat(length)}- B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle dotted edges with arrows with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA -${'.'.repeat(length)}-> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle dotted labelled edges with arrows with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA -. Label ${'.'.repeat(length)}-> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle dotted edges with double arrows with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA <-${'.'.repeat(length)}-> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle dotted edges with double arrows with length ${length}`, function () {
const res = flow.parser.parse(`graph TD;\nA <-. Label ${'.'.repeat(length)}-> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(length);
});
}
});
});

View File

@@ -0,0 +1,29 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
describe('[Text] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});
describe('it should handle huge files', function () {
// skipped because this test takes like 2 minutes or more!
it.skip('it should handlehuge diagrams', function () {
const nodes = ('A-->B;B-->A;'.repeat(415) + 'A-->B;').repeat(57) + 'A-->B;B-->A;'.repeat(275);
flow.parser.parse(`graph LR;${nodes}`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_point');
expect(edges.length).toBe(47917);
expect(vert.size).toBe(2);
});
});
});

View File

@@ -0,0 +1,158 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
import { vi } from 'vitest';
const spyOn = vi.spyOn;
setConfig({
securityLevel: 'strict',
});
describe('[Interactions] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});
it('should be possible to use click to a callback', function () {
spyOn(flowDb, 'setClickEvent');
const res = flow.parser.parse('graph TD\nA-->B\nclick A callback');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(flowDb.setClickEvent).toHaveBeenCalledWith('A', 'callback');
});
it('should be possible to use click to a click and call callback', function () {
spyOn(flowDb, 'setClickEvent');
const res = flow.parser.parse('graph TD\nA-->B\nclick A call callback()');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(flowDb.setClickEvent).toHaveBeenCalledWith('A', 'callback');
});
it('should be possible to use click to a callback with toolip', function () {
spyOn(flowDb, 'setClickEvent');
spyOn(flowDb, 'setTooltip');
const res = flow.parser.parse('graph TD\nA-->B\nclick A callback "tooltip"');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(flowDb.setClickEvent).toHaveBeenCalledWith('A', 'callback');
expect(flowDb.setTooltip).toHaveBeenCalledWith('A', 'tooltip');
});
it('should be possible to use click to a click and call callback with toolip', function () {
spyOn(flowDb, 'setClickEvent');
spyOn(flowDb, 'setTooltip');
const res = flow.parser.parse('graph TD\nA-->B\nclick A call callback() "tooltip"');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(flowDb.setClickEvent).toHaveBeenCalledWith('A', 'callback');
expect(flowDb.setTooltip).toHaveBeenCalledWith('A', 'tooltip');
});
it('should be possible to use click to a callback with an arbitrary number of args', function () {
spyOn(flowDb, 'setClickEvent');
const res = flow.parser.parse('graph TD\nA-->B\nclick A call callback("test0", test1, test2)');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(flowDb.setClickEvent).toHaveBeenCalledWith('A', 'callback', '"test0", test1, test2');
});
it('should handle interaction - click to a link', function () {
spyOn(flowDb, 'setLink');
const res = flow.parser.parse('graph TD\nA-->B\nclick A "click.html"');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(flowDb.setLink).toHaveBeenCalledWith('A', 'click.html');
});
it('should handle interaction - click to a click and href link', function () {
spyOn(flowDb, 'setLink');
const res = flow.parser.parse('graph TD\nA-->B\nclick A href "click.html"');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(flowDb.setLink).toHaveBeenCalledWith('A', 'click.html');
});
it('should handle interaction - click to a link with tooltip', function () {
spyOn(flowDb, 'setLink');
spyOn(flowDb, 'setTooltip');
const res = flow.parser.parse('graph TD\nA-->B\nclick A "click.html" "tooltip"');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(flowDb.setLink).toHaveBeenCalledWith('A', 'click.html');
expect(flowDb.setTooltip).toHaveBeenCalledWith('A', 'tooltip');
});
it('should handle interaction - click to a click and href link with tooltip', function () {
spyOn(flowDb, 'setLink');
spyOn(flowDb, 'setTooltip');
const res = flow.parser.parse('graph TD\nA-->B\nclick A href "click.html" "tooltip"');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(flowDb.setLink).toHaveBeenCalledWith('A', 'click.html');
expect(flowDb.setTooltip).toHaveBeenCalledWith('A', 'tooltip');
});
it('should handle interaction - click to a link with target', function () {
spyOn(flowDb, 'setLink');
const res = flow.parser.parse('graph TD\nA-->B\nclick A "click.html" _blank');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(flowDb.setLink).toHaveBeenCalledWith('A', 'click.html', '_blank');
});
it('should handle interaction - click to a click and href link with target', function () {
spyOn(flowDb, 'setLink');
const res = flow.parser.parse('graph TD\nA-->B\nclick A href "click.html" _blank');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(flowDb.setLink).toHaveBeenCalledWith('A', 'click.html', '_blank');
});
it('should handle interaction - click to a link with tooltip and target', function () {
spyOn(flowDb, 'setLink');
spyOn(flowDb, 'setTooltip');
const res = flow.parser.parse('graph TD\nA-->B\nclick A "click.html" "tooltip" _blank');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(flowDb.setLink).toHaveBeenCalledWith('A', 'click.html', '_blank');
expect(flowDb.setTooltip).toHaveBeenCalledWith('A', 'tooltip');
});
it('should handle interaction - click to a click and href link with tooltip and target', function () {
spyOn(flowDb, 'setLink');
spyOn(flowDb, 'setTooltip');
const res = flow.parser.parse('graph TD\nA-->B\nclick A href "click.html" "tooltip" _blank');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(flowDb.setLink).toHaveBeenCalledWith('A', 'click.html', '_blank');
expect(flowDb.setTooltip).toHaveBeenCalledWith('A', 'tooltip');
});
});

View File

@@ -0,0 +1,119 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
describe('[Lines] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});
it('should handle line interpolation default definitions', function () {
const res = flow.parser.parse('graph TD\n' + 'A-->B\n' + 'linkStyle default interpolate basis');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.defaultInterpolate).toBe('basis');
});
it('should handle line interpolation numbered definitions', function () {
const res = flow.parser.parse(
'graph TD\n' +
'A-->B\n' +
'A-->C\n' +
'linkStyle 0 interpolate basis\n' +
'linkStyle 1 interpolate cardinal'
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].interpolate).toBe('basis');
expect(edges[1].interpolate).toBe('cardinal');
});
it('should handle line interpolation multi-numbered definitions', function () {
const res = flow.parser.parse(
'graph TD\n' + 'A-->B\n' + 'A-->C\n' + 'linkStyle 0,1 interpolate basis'
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].interpolate).toBe('basis');
expect(edges[1].interpolate).toBe('basis');
});
it('should handle line interpolation default with style', function () {
const res = flow.parser.parse(
'graph TD\n' + 'A-->B\n' + 'linkStyle default interpolate basis stroke-width:1px;'
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.defaultInterpolate).toBe('basis');
});
it('should handle line interpolation numbered with style', function () {
const res = flow.parser.parse(
'graph TD\n' +
'A-->B\n' +
'A-->C\n' +
'linkStyle 0 interpolate basis stroke-width:1px;\n' +
'linkStyle 1 interpolate cardinal stroke-width:1px;'
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].interpolate).toBe('basis');
expect(edges[1].interpolate).toBe('cardinal');
});
it('should handle line interpolation multi-numbered with style', function () {
const res = flow.parser.parse(
'graph TD\n' + 'A-->B\n' + 'A-->C\n' + 'linkStyle 0,1 interpolate basis stroke-width:1px;'
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].interpolate).toBe('basis');
expect(edges[1].interpolate).toBe('basis');
});
describe('it should handle new line type notation', function () {
it('should handle regular lines', function () {
const res = flow.parser.parse('graph TD;A-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].stroke).toBe('normal');
});
it('should handle dotted lines', function () {
const res = flow.parser.parse('graph TD;A-.->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].stroke).toBe('dotted');
});
it('should handle dotted lines', function () {
const res = flow.parser.parse('graph TD;A==>B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].stroke).toBe('thick');
});
});
});

View File

@@ -0,0 +1,64 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
describe('parsing a flow chart with markdown strings', function () {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});
it('mardown formatting in nodes and labels', function () {
const res = flow.parser.parse(`flowchart
A["\`The cat in **the** hat\`"]-- "\`The *bat* in the chat\`" -->B["The dog in the hog"] -- "The rat in the mat" -->C;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('A').text).toBe('The cat in **the** hat');
expect(vert.get('A').labelType).toBe('markdown');
expect(vert.get('B').id).toBe('B');
expect(vert.get('B').text).toBe('The dog in the hog');
expect(vert.get('B').labelType).toBe('string');
expect(edges.length).toBe(2);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('The *bat* in the chat');
expect(edges[0].labelType).toBe('markdown');
expect(edges[1].start).toBe('B');
expect(edges[1].end).toBe('C');
expect(edges[1].type).toBe('arrow_point');
expect(edges[1].text).toBe('The rat in the mat');
expect(edges[1].labelType).toBe('string');
});
it('mardown formatting in subgraphs', function () {
const res = flow.parser.parse(`flowchart LR
subgraph "One"
a("\`The **cat**
in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}}
end
subgraph "\`**Two**\`"
c("\`The **cat**
in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog")
end`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(2);
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(2);
expect(subgraph.title).toBe('One');
expect(subgraph.labelType).toBe('text');
const subgraph2 = subgraphs[1];
expect(subgraph2.nodes.length).toBe(2);
expect(subgraph2.title).toBe('**Two**');
expect(subgraph2.labelType).toBe('markdown');
});
});

View File

@@ -0,0 +1,293 @@
import flowDb from '../swimlaneDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
describe('when parsing directions', function () {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
flow.parser.yy.setGen('gen-2');
});
it('should handle basic shape data statements', function () {
const res = flow.parser.parse(`flowchart TB
D@{ shape: rounded}`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('D');
});
it('should handle basic shape data statements', function () {
const res = flow.parser.parse(`flowchart TB
D@{ shape: rounded }`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('D');
});
it('should handle basic shape data statements with &', function () {
const res = flow.parser.parse(`flowchart TB
D@{ shape: rounded } & E`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(2);
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('D');
expect(data4Layout.nodes[1].label).toEqual('E');
});
it('should handle shape data statements with edges', function () {
const res = flow.parser.parse(`flowchart TB
D@{ shape: rounded } --> E`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(2);
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('D');
expect(data4Layout.nodes[1].label).toEqual('E');
});
it('should handle basic shape data statements with amp and edges 1', function () {
const res = flow.parser.parse(`flowchart TB
D@{ shape: rounded } & E --> F`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(3);
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('D');
expect(data4Layout.nodes[1].label).toEqual('E');
});
it('should handle basic shape data statements with amp and edges 2', function () {
const res = flow.parser.parse(`flowchart TB
D@{ shape: rounded } & E@{ shape: rounded } --> F`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(3);
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('D');
expect(data4Layout.nodes[1].label).toEqual('E');
});
it('should handle basic shape data statements with amp and edges 3', function () {
const res = flow.parser.parse(`flowchart TB
D@{ shape: rounded } & E@{ shape: rounded } --> F & G@{ shape: rounded }`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(4);
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('D');
expect(data4Layout.nodes[1].label).toEqual('E');
});
it('should handle basic shape data statements with amp and edges 4', function () {
const res = flow.parser.parse(`flowchart TB
D@{ shape: rounded } & E@{ shape: rounded } --> F@{ shape: rounded } & G@{ shape: rounded }`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(4);
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('D');
expect(data4Layout.nodes[1].label).toEqual('E');
});
it('should handle basic shape data statements with amp and edges 5, trailing space', function () {
const res = flow.parser.parse(`flowchart TB
D@{ shape: rounded } & E@{ shape: rounded } --> F{ shape: rounded } & G{ shape: rounded } `);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(4);
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('D');
expect(data4Layout.nodes[1].label).toEqual('E');
});
it('should no matter of there are no leading spaces', function () {
const res = flow.parser.parse(`flowchart TB
D@{shape: rounded}`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('D');
});
it('should no matter of there are many leading spaces', function () {
const res = flow.parser.parse(`flowchart TB
D@{ shape: rounded}`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('D');
});
it('should be forgiving with many spaces before teh end', function () {
const res = flow.parser.parse(`flowchart TB
D@{ shape: rounded }`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('D');
});
it('should be possible to add multiple properties on the same line', function () {
const res = flow.parser.parse(`flowchart TB
D@{ shape: rounded , label: "DD"}`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('rounded');
expect(data4Layout.nodes[0].label).toEqual('DD');
});
it('should be possible to link to a node with more data', function () {
const res = flow.parser.parse(`flowchart TB
A --> D@{
shape: circle
other: "clock"
}
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(2);
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
expect(data4Layout.nodes[0].label).toEqual('A');
expect(data4Layout.nodes[1].label).toEqual('D');
expect(data4Layout.nodes[1].shape).toEqual('circle');
expect(data4Layout.edges.length).toBe(1);
});
it('should not disturb adding multiple nodes after each other', function () {
const res = flow.parser.parse(`flowchart TB
A[hello]
B@{
shape: circle
other: "clock"
}
C[Hello]@{
shape: circle
other: "clock"
}
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(3);
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
expect(data4Layout.nodes[0].label).toEqual('hello');
expect(data4Layout.nodes[1].shape).toEqual('circle');
expect(data4Layout.nodes[1].label).toEqual('B');
expect(data4Layout.nodes[2].shape).toEqual('circle');
expect(data4Layout.nodes[2].label).toEqual('Hello');
});
it('should use handle bracket end (}) character inside the shape data', function () {
const res = flow.parser.parse(`flowchart TB
A@{
label: "This is }"
other: "clock"
}
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
expect(data4Layout.nodes[0].label).toEqual('This is }');
});
it('should error on non-existent shape', function () {
expect(() => {
flow.parser.parse(`flowchart TB
A@{ shape: this-shape-does-not-exist }
`);
}).toThrow('No such shape: this-shape-does-not-exist.');
});
it('should error on internal-only shape', function () {
expect(() => {
// this shape does exist, but it's only supposed to be for internal/backwards compatibility use
flow.parser.parse(`flowchart TB
A@{ shape: rect_left_inv_arrow }
`);
}).toThrow('No such shape: rect_left_inv_arrow. Shape names should be lowercase.');
});
it('Diamond shapes should work as usual', function () {
const res = flow.parser.parse(`flowchart TB
A{This is a label}
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('diamond');
expect(data4Layout.nodes[0].label).toEqual('This is a label');
});
it('Multi line strings should be supported', function () {
const res = flow.parser.parse(`flowchart TB
A@{
label: |
This is a
multiline string
other: "clock"
}
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
expect(data4Layout.nodes[0].label).toEqual('This is a\nmultiline string\n');
});
it('Multi line strings should be supported', function () {
const res = flow.parser.parse(`flowchart TB
A@{
label: "This is a
multiline string"
other: "clock"
}
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
expect(data4Layout.nodes[0].label).toEqual('This is a<br/>multiline string');
});
it(' should be possible to use } in strings', function () {
const res = flow.parser.parse(`flowchart TB
A@{
label: "This is a string with }"
other: "clock"
}
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
expect(data4Layout.nodes[0].label).toEqual('This is a string with }');
});
it(' should be possible to use @ in strings', function () {
const res = flow.parser.parse(`flowchart TB
A@{
label: "This is a string with @"
other: "clock"
}
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
expect(data4Layout.nodes[0].label).toEqual('This is a string with @');
});
it(' should be possible to use @ in strings', function () {
const res = flow.parser.parse(`flowchart TB
A@{
label: "This is a string with}"
other: "clock"
}
`);
const data4Layout = flow.parser.yy.getData();
expect(data4Layout.nodes.length).toBe(1);
expect(data4Layout.nodes[0].shape).toEqual('squareRect');
expect(data4Layout.nodes[0].label).toEqual('This is a string with}');
});
});

View File

@@ -0,0 +1,371 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
const keywords = [
'graph',
'flowchart',
'flowchart-elk',
'style',
'default',
'linkStyle',
'interpolate',
'classDef',
'class',
'href',
'call',
'click',
'_self',
'_blank',
'_parent',
'_top',
'end',
'subgraph',
];
const specialChars = ['#', ':', '0', '&', ',', '*', '.', '\\', 'v', '-', '/', '_'];
describe('[Singlenodes] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});
it('should handle a single node', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;A;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('A').styles.length).toBe(0);
});
it('should handle a single node with white space after it (SN1)', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;A ;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('A').styles.length).toBe(0);
});
it('should handle a single square node', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a[A];');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').styles.length).toBe(0);
expect(vert.get('a').type).toBe('square');
});
it('should handle a single round square node', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a[A];');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').styles.length).toBe(0);
expect(vert.get('a').type).toBe('square');
});
it('should handle a single circle node', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a((A));');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').type).toBe('circle');
});
it('should handle a single round node', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a(A);');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').type).toBe('round');
});
it('should handle a single odd node', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a>A];');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').type).toBe('odd');
});
it('should handle a single diamond node', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a{A};');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').type).toBe('diamond');
});
it('should handle a single diamond node with whitespace after it', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a{A} ;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').type).toBe('diamond');
});
it('should handle a single diamond node with html in it (SN3)', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a{A <br> end};');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').type).toBe('diamond');
expect(vert.get('a').text).toBe('A <br> end');
});
it('should handle a single hexagon node', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a{{A}};');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').type).toBe('hexagon');
});
it('should handle a single hexagon node with html in it', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a{{A <br> end}};');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').type).toBe('hexagon');
expect(vert.get('a').text).toBe('A <br> end');
});
it('should handle a single round node with html in it', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a(A <br> end);');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').type).toBe('round');
expect(vert.get('a').text).toBe('A <br> end');
});
it('should handle a single double circle node', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a(((A)));');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').type).toBe('doublecircle');
});
it('should handle a single double circle node with whitespace after it', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a(((A))) ;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').type).toBe('doublecircle');
});
it('should handle a single double circle node with html in it (SN3)', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a(((A <br> end)));');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('a').type).toBe('doublecircle');
expect(vert.get('a').text).toBe('A <br> end');
});
it('should handle a single node with alphanumerics starting on a char', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;id1;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('id1').styles.length).toBe(0);
});
it('should handle a single node with a single digit', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;1;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('1').text).toBe('1');
});
it('should handle a single node with a single digit in a subgraph', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;subgraph "hello";1;end;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('1').text).toBe('1');
});
it('should handle a single node with alphanumerics starting on a num', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;1id;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('1id').styles.length).toBe(0);
});
it('should handle a single node with alphanumerics containing a minus sign', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;i-d;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('i-d').styles.length).toBe(0);
});
it('should handle a single node with alphanumerics containing a underscore sign', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;i_d;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert.get('i_d').styles.length).toBe(0);
});
it.each(keywords)('should handle keywords between dashes "-"', function (keyword) {
const res = flow.parser.parse(`graph TD;a-${keyword}-node;`);
const vert = flow.parser.yy.getVertices();
expect(vert.get(`a-${keyword}-node`).text).toBe(`a-${keyword}-node`);
});
it.each(keywords)('should handle keywords between periods "."', function (keyword) {
const res = flow.parser.parse(`graph TD;a.${keyword}.node;`);
const vert = flow.parser.yy.getVertices();
expect(vert.get(`a.${keyword}.node`).text).toBe(`a.${keyword}.node`);
});
it.each(keywords)('should handle keywords between underscores "_"', function (keyword) {
const res = flow.parser.parse(`graph TD;a_${keyword}_node;`);
const vert = flow.parser.yy.getVertices();
expect(vert.get(`a_${keyword}_node`).text).toBe(`a_${keyword}_node`);
});
it.each(keywords)('should handle nodes ending in %s', function (keyword) {
const res = flow.parser.parse(`graph TD;node_${keyword};node.${keyword};node-${keyword};`);
const vert = flow.parser.yy.getVertices();
expect(vert.get(`node_${keyword}`).text).toBe(`node_${keyword}`);
expect(vert.get(`node.${keyword}`).text).toBe(`node.${keyword}`);
expect(vert.get(`node-${keyword}`).text).toBe(`node-${keyword}`);
});
const errorKeywords = [
'graph',
'flowchart',
'flowchart-elk',
'style',
'linkStyle',
'interpolate',
'classDef',
'class',
'_self',
'_blank',
'_parent',
'_top',
'end',
'subgraph',
];
it.each(errorKeywords)('should throw error at nodes beginning with %s', function (keyword) {
const str = `graph TD;${keyword}.node;${keyword}-node;${keyword}/node`;
const vert = flow.parser.yy.getVertices();
expect(() => flow.parser.parse(str)).toThrowError();
});
const workingKeywords = ['default', 'href', 'click', 'call'];
it.each(workingKeywords)('should parse node beginning with %s', function (keyword) {
flow.parser.parse(`graph TD; ${keyword}.node;${keyword}-node;${keyword}/node;`);
const vert = flow.parser.yy.getVertices();
expect(vert.get(`${keyword}.node`).text).toBe(`${keyword}.node`);
expect(vert.get(`${keyword}-node`).text).toBe(`${keyword}-node`);
expect(vert.get(`${keyword}/node`).text).toBe(`${keyword}/node`);
});
it.each(specialChars)(
'should allow node ids of single special characters',
function (specialChar) {
flow.parser.parse(`graph TD; ${specialChar} --> A`);
const vert = flow.parser.yy.getVertices();
expect(vert.get(`${specialChar}`).text).toBe(`${specialChar}`);
}
);
it.each(specialChars)(
'should allow node ids with special characters at start of id',
function (specialChar) {
flow.parser.parse(`graph TD; ${specialChar}node --> A`);
const vert = flow.parser.yy.getVertices();
expect(vert.get(`${specialChar}node`).text).toBe(`${specialChar}node`);
}
);
it.each(specialChars)(
'should allow node ids with special characters at end of id',
function (specialChar) {
flow.parser.parse(`graph TD; node${specialChar} --> A`);
const vert = flow.parser.yy.getVertices();
expect(vert.get(`node${specialChar}`).text).toBe(`node${specialChar}`);
}
);
});

View File

@@ -0,0 +1,370 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
describe('[Style] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
flow.parser.yy.setGen('gen-2');
});
// log.debug(flow.parser.parse('graph TD;style Q background:#fff;'));
it('should handle styles for vertices', function () {
const res = flow.parser.parse('graph TD;style Q background:#fff;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('Q').styles.length).toBe(1);
expect(vert.get('Q').styles[0]).toBe('background:#fff');
});
it('should handle multiple styles for a vortex', function () {
const res = flow.parser.parse('graph TD;style R background:#fff,border:1px solid red;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('R').styles.length).toBe(2);
expect(vert.get('R').styles[0]).toBe('background:#fff');
expect(vert.get('R').styles[1]).toBe('border:1px solid red');
});
it('should handle multiple styles in a graph', function () {
const res = flow.parser.parse(
'graph TD;style S background:#aaa;\nstyle T background:#bbb,border:1px solid red;'
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('S').styles.length).toBe(1);
expect(vert.get('T').styles.length).toBe(2);
expect(vert.get('S').styles[0]).toBe('background:#aaa');
expect(vert.get('T').styles[0]).toBe('background:#bbb');
expect(vert.get('T').styles[1]).toBe('border:1px solid red');
});
it('should handle styles and graph definitions in a graph', function () {
const res = flow.parser.parse(
'graph TD;S-->T;\nstyle S background:#aaa;\nstyle T background:#bbb,border:1px solid red;'
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('S').styles.length).toBe(1);
expect(vert.get('T').styles.length).toBe(2);
expect(vert.get('S').styles[0]).toBe('background:#aaa');
expect(vert.get('T').styles[0]).toBe('background:#bbb');
expect(vert.get('T').styles[1]).toBe('border:1px solid red');
});
it('should handle styles and graph definitions in a graph', function () {
const res = flow.parser.parse('graph TD;style T background:#bbb,border:1px solid red;');
// const res = flow.parser.parse('graph TD;style T background: #bbb;');
const vert = flow.parser.yy.getVertices();
expect(vert.get('T').styles.length).toBe(2);
expect(vert.get('T').styles[0]).toBe('background:#bbb');
expect(vert.get('T').styles[1]).toBe('border:1px solid red');
});
it('should keep node label text (if already defined) when a style is applied', function () {
const res = flow.parser.parse(
'graph TD;A(( ));B((Test));C;style A background:#fff;style D border:1px solid red;'
);
const vert = flow.parser.yy.getVertices();
expect(vert.get('A').text).toBe('');
expect(vert.get('B').text).toBe('Test');
expect(vert.get('C').text).toBe('C');
expect(vert.get('D').text).toBe('D');
});
it('should be possible to declare a class', function () {
const res = flow.parser.parse(
'graph TD;classDef exClass background:#bbb,border:1px solid red;'
);
// const res = flow.parser.parse('graph TD;style T background: #bbb;');
const classes = flow.parser.yy.getClasses();
expect(classes.get('exClass').styles.length).toBe(2);
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
});
it('should be possible to declare multiple classes', function () {
const res = flow.parser.parse(
'graph TD;classDef firstClass,secondClass background:#bbb,border:1px solid red;'
);
const classes = flow.parser.yy.getClasses();
expect(classes.get('firstClass').styles.length).toBe(2);
expect(classes.get('firstClass').styles[0]).toBe('background:#bbb');
expect(classes.get('firstClass').styles[1]).toBe('border:1px solid red');
expect(classes.get('secondClass').styles.length).toBe(2);
expect(classes.get('secondClass').styles[0]).toBe('background:#bbb');
expect(classes.get('secondClass').styles[1]).toBe('border:1px solid red');
});
it('should be possible to declare a class with a dot in the style', function () {
const res = flow.parser.parse(
'graph TD;classDef exClass background:#bbb,border:1.5px solid red;'
);
// const res = flow.parser.parse('graph TD;style T background: #bbb;');
const classes = flow.parser.yy.getClasses();
expect(classes.get('exClass').styles.length).toBe(2);
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
expect(classes.get('exClass').styles[1]).toBe('border:1.5px solid red');
});
it('should be possible to declare a class with a space in the style', function () {
const res = flow.parser.parse(
'graph TD;classDef exClass background: #bbb,border:1.5px solid red;'
);
// const res = flow.parser.parse('graph TD;style T background : #bbb;');
const classes = flow.parser.yy.getClasses();
expect(classes.get('exClass').styles.length).toBe(2);
expect(classes.get('exClass').styles[0]).toBe('background: #bbb');
expect(classes.get('exClass').styles[1]).toBe('border:1.5px solid red');
});
it('should be possible to apply a class to a vertex', function () {
let statement = '';
statement = statement + 'graph TD;' + '\n';
statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n';
statement = statement + 'a-->b;' + '\n';
statement = statement + 'class a exClass;';
const res = flow.parser.parse(statement);
const classes = flow.parser.yy.getClasses();
expect(classes.get('exClass').styles.length).toBe(2);
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
});
it('should be possible to apply a class to a vertex with an id containing _', function () {
let statement = '';
statement = statement + 'graph TD;' + '\n';
statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n';
statement = statement + 'a_a-->b_b;' + '\n';
statement = statement + 'class a_a exClass;';
const res = flow.parser.parse(statement);
const classes = flow.parser.yy.getClasses();
expect(classes.get('exClass').styles.length).toBe(2);
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
});
it('should be possible to apply a class to a vertex directly', function () {
let statement = '';
statement = statement + 'graph TD;' + '\n';
statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n';
statement = statement + 'a-->b[test]:::exClass;' + '\n';
const res = flow.parser.parse(statement);
const vertices = flow.parser.yy.getVertices();
const classes = flow.parser.yy.getClasses();
expect(classes.get('exClass').styles.length).toBe(2);
expect(vertices.get('b').classes[0]).toBe('exClass');
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
});
it('should be possible to apply a class to a vertex directly : usecase A[text].class ', function () {
let statement = '';
statement = statement + 'graph TD;' + '\n';
statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n';
statement = statement + 'b[test]:::exClass;' + '\n';
const res = flow.parser.parse(statement);
const vertices = flow.parser.yy.getVertices();
const classes = flow.parser.yy.getClasses();
expect(classes.get('exClass').styles.length).toBe(2);
expect(vertices.get('b').classes[0]).toBe('exClass');
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
});
it('should be possible to apply a class to a vertex directly : usecase A[text].class-->B[test2] ', function () {
let statement = '';
statement = statement + 'graph TD;' + '\n';
statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n';
statement = statement + 'A[test]:::exClass-->B[test2];' + '\n';
const res = flow.parser.parse(statement);
const vertices = flow.parser.yy.getVertices();
const classes = flow.parser.yy.getClasses();
expect(classes.get('exClass').styles.length).toBe(2);
expect(vertices.get('A').classes[0]).toBe('exClass');
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
});
it('should be possible to apply a class to a vertex directly 2', function () {
let statement = '';
statement = statement + 'graph TD;' + '\n';
statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n';
statement = statement + 'a-->b[1 a a text!.]:::exClass;' + '\n';
const res = flow.parser.parse(statement);
const vertices = flow.parser.yy.getVertices();
const classes = flow.parser.yy.getClasses();
expect(classes.get('exClass').styles.length).toBe(2);
expect(vertices.get('b').classes[0]).toBe('exClass');
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
});
it('should be possible to apply a class to a comma separated list of vertices', function () {
let statement = '';
statement = statement + 'graph TD;' + '\n';
statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n';
statement = statement + 'a-->b;' + '\n';
statement = statement + 'class a,b exClass;';
const res = flow.parser.parse(statement);
const classes = flow.parser.yy.getClasses();
const vertices = flow.parser.yy.getVertices();
expect(classes.get('exClass').styles.length).toBe(2);
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
expect(vertices.get('a').classes[0]).toBe('exClass');
expect(vertices.get('b').classes[0]).toBe('exClass');
});
it('should handle style definitions with more then 1 digit in a row', function () {
const res = flow.parser.parse(
'graph TD\n' +
'A-->B1\n' +
'A-->B2\n' +
'A-->B3\n' +
'A-->B4\n' +
'A-->B5\n' +
'A-->B6\n' +
'A-->B7\n' +
'A-->B8\n' +
'A-->B9\n' +
'A-->B10\n' +
'A-->B11\n' +
'linkStyle 10 stroke-width:1px;'
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_point');
});
it('should handle style definitions within number of edges', function () {
expect(() =>
flow.parser
.parse(
`graph TD
A-->B
linkStyle 1 stroke-width:1px;`
)
.toThrow(
'The index 1 for linkStyle is out of bounds. Valid indices for linkStyle are between 0 and 0. (Help: Ensure that the index is within the range of existing edges.)'
)
);
});
it('should handle style definitions within number of edges', function () {
const res = flow.parser.parse(`graph TD
A-->B
linkStyle 0 stroke-width:1px;`);
const edges = flow.parser.yy.getEdges();
expect(edges[0].style[0]).toBe('stroke-width:1px');
});
it('should handle multi-numbered style definitions with more then 1 digit in a row', function () {
const res = flow.parser.parse(
'graph TD\n' +
'A-->B1\n' +
'A-->B2\n' +
'A-->B3\n' +
'A-->B4\n' +
'A-->B5\n' +
'A-->B6\n' +
'A-->B7\n' +
'A-->B8\n' +
'A-->B9\n' +
'A-->B10\n' +
'A-->B11\n' +
'A-->B12\n' +
'linkStyle 10,11 stroke-width:1px;'
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_point');
});
it('should handle classDefs with style in classes', function () {
const res = flow.parser.parse('graph TD\nA-->B\nclassDef exClass font-style:bold;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_point');
});
it('should handle classDefs with % in classes', function () {
const res = flow.parser.parse(
'graph TD\nA-->B\nclassDef exClass fill:#f96,stroke:#333,stroke-width:4px,font-size:50%,font-style:bold;'
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_point');
});
it('should handle multiple vertices with style', function () {
const res = flow.parser.parse(`
graph TD
classDef C1 stroke-dasharray:4
classDef C2 stroke-dasharray:6
A & B:::C1 & D:::C1 --> E:::C2
`);
const vert = flow.parser.yy.getVertices();
expect(vert.get('A').classes.length).toBe(0);
expect(vert.get('B').classes[0]).toBe('C1');
expect(vert.get('D').classes[0]).toBe('C1');
expect(vert.get('E').classes[0]).toBe('C2');
});
});

View File

@@ -0,0 +1,609 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
describe('[Text] when parsing', () => {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});
describe('it should handle text on edges', function () {
it('should handle text without space', function () {
const res = flow.parser.parse('graph TD;A--x|textNoSpace|B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
});
it('should handle with space', function () {
const res = flow.parser.parse('graph TD;A--x|text including space|B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
});
it('should handle text with /', function () {
const res = flow.parser.parse('graph TD;A--x|text with / should work|B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].text).toBe('text with / should work');
});
it('should handle space and space between vertices and link', function () {
const res = flow.parser.parse('graph TD;A --x|textNoSpace| B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
});
it('should handle space and CAPS', function () {
const res = flow.parser.parse('graph TD;A--x|text including CAPS space|B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
});
it('should handle space and dir', function () {
const res = flow.parser.parse('graph TD;A--x|text including URL space|B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
expect(edges[0].text).toBe('text including URL space');
});
it('should handle space and send', function () {
const res = flow.parser.parse('graph TD;A--text including URL space and send-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('text including URL space and send');
});
it('should handle space and send', function () {
const res = flow.parser.parse('graph TD;A-- text including URL space and send -->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('text including URL space and send');
});
it('should handle space and dir (TD)', function () {
const res = flow.parser.parse('graph TD;A--x|text including R TD space|B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
expect(edges[0].text).toBe('text including R TD space');
});
it('should handle `', function () {
const res = flow.parser.parse('graph TD;A--x|text including `|B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
expect(edges[0].text).toBe('text including `');
});
it('should handle v in node ids only v', function () {
// only v
const res = flow.parser.parse('graph TD;A--xv(my text);');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
expect(vert.get('v').text).toBe('my text');
});
it('should handle v in node ids v at end', function () {
// v at end
const res = flow.parser.parse('graph TD;A--xcsv(my text);');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
expect(vert.get('csv').text).toBe('my text');
});
it('should handle v in node ids v in middle', function () {
// v in middle
const res = flow.parser.parse('graph TD;A--xava(my text);');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
expect(vert.get('ava').text).toBe('my text');
});
it('should handle v in node ids, v at start', function () {
// v at start
const res = flow.parser.parse('graph TD;A--xva(my text);');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
expect(vert.get('va').text).toBe('my text');
});
it('should handle keywords', function () {
const res = flow.parser.parse('graph TD;A--x|text including graph space|B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].text).toBe('text including graph space');
});
it('should handle keywords', function () {
const res = flow.parser.parse('graph TD;V-->a[v]');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('a').text).toBe('v');
});
it('should handle quoted text', function () {
const res = flow.parser.parse('graph TD;V-- "test string()" -->a[v]');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].text).toBe('test string()');
});
});
describe('it should handle text on lines', () => {
it('should handle normal text on lines', function () {
const res = flow.parser.parse('graph TD;A-- test text with == -->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].stroke).toBe('normal');
});
it('should handle dotted text on lines (TD3)', function () {
const res = flow.parser.parse('graph TD;A-. test text with == .->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].stroke).toBe('dotted');
});
it('should handle thick text on lines', function () {
const res = flow.parser.parse('graph TD;A== test text with - ==>B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].stroke).toBe('thick');
});
});
describe('it should handle text on edges using the new notation', function () {
it('should handle text without space', function () {
const res = flow.parser.parse('graph TD;A-- textNoSpace --xB;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
});
it('should handle text with multiple leading space', function () {
const res = flow.parser.parse('graph TD;A-- textNoSpace --xB;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
});
it('should handle with space', function () {
const res = flow.parser.parse('graph TD;A-- text including space --xB;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
});
it('should handle text with /', function () {
const res = flow.parser.parse('graph TD;A -- text with / should work --x B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].text).toBe('text with / should work');
});
it('should handle space and space between vertices and link', function () {
const res = flow.parser.parse('graph TD;A -- textNoSpace --x B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
});
it('should handle space and CAPS', function () {
const res = flow.parser.parse('graph TD;A-- text including CAPS space --xB;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
});
it('should handle space and dir', function () {
const res = flow.parser.parse('graph TD;A-- text including URL space --xB;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
expect(edges[0].text).toBe('text including URL space');
});
it('should handle space and dir (TD2)', function () {
const res = flow.parser.parse('graph TD;A-- text including R TD space --xB;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_cross');
expect(edges[0].text).toBe('text including R TD space');
});
it('should handle keywords', function () {
const res = flow.parser.parse('graph TD;A-- text including graph space and v --xB;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].text).toBe('text including graph space and v');
});
it('should handle keywords', function () {
const res = flow.parser.parse('graph TD;A-- text including graph space and v --xB[blav]');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].text).toBe('text including graph space and v');
});
// it.skip('should handle text on open links',function(){
// const res = flow.parser.parse('graph TD;A-- text including graph space --B');
//
// const vert = flow.parser.yy.getVertices();
// const edges = flow.parser.yy.getEdges();
//
// expect(edges[0].text).toBe('text including graph space');
//
// });
});
describe('it should handle text in vertices, ', function () {
it('should handle space', function () {
const res = flow.parser.parse('graph TD;A-->C(Chimpansen hoppar);');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('C').type).toBe('round');
expect(vert.get('C').text).toBe('Chimpansen hoppar');
});
const keywords = [
'graph',
'flowchart',
'flowchart-elk',
'style',
'default',
'linkStyle',
'interpolate',
'classDef',
'class',
'href',
'call',
'click',
'_self',
'_blank',
'_parent',
'_top',
'end',
'subgraph',
'kitty',
];
const shapes = [
{ start: '[', end: ']', name: 'square' },
{ start: '(', end: ')', name: 'round' },
{ start: '{', end: '}', name: 'diamond' },
{ start: '(-', end: '-)', name: 'ellipse' },
{ start: '([', end: '])', name: 'stadium' },
{ start: '>', end: ']', name: 'odd' },
{ start: '[(', end: ')]', name: 'cylinder' },
{ start: '(((', end: ')))', name: 'doublecircle' },
{ start: '[/', end: '\\]', name: 'trapezoid' },
{ start: '[\\', end: '/]', name: 'inv_trapezoid' },
{ start: '[/', end: '/]', name: 'lean_right' },
{ start: '[\\', end: '\\]', name: 'lean_left' },
{ start: '[[', end: ']]', name: 'subroutine' },
{ start: '{{', end: '}}', name: 'hexagon' },
];
shapes.forEach((shape) => {
it.each(keywords)(`should handle %s keyword in ${shape.name} vertex`, function (keyword) {
const rest = flow.parser.parse(
`graph TD;A_${keyword}_node-->B${shape.start}This node has a ${keyword} as text${shape.end};`
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('B').type).toBe(`${shape.name}`);
expect(vert.get('B').text).toBe(`This node has a ${keyword} as text`);
});
});
it.each(keywords)('should handle %s keyword in rect vertex', function (keyword) {
const rest = flow.parser.parse(
`graph TD;A_${keyword}_node-->B[|borders:lt|This node has a ${keyword} as text];`
);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('B').type).toBe('rect');
expect(vert.get('B').text).toBe(`This node has a ${keyword} as text`);
});
it('should handle edge case for odd vertex with node id ending with minus', function () {
const res = flow.parser.parse('graph TD;A_node-->odd->Vertex Text];');
const vert = flow.parser.yy.getVertices();
expect(vert.get('odd-').type).toBe('odd');
expect(vert.get('odd-').text).toBe('Vertex Text');
});
it('should allow forward slashes in lean_right vertices', function () {
const rest = flow.parser.parse(`graph TD;A_node-->B[/This node has a / as text/];`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('B').type).toBe('lean_right');
expect(vert.get('B').text).toBe(`This node has a / as text`);
});
it('should allow back slashes in lean_left vertices', function () {
const rest = flow.parser.parse(`graph TD;A_node-->B[\\This node has a \\ as text\\];`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('B').type).toBe('lean_left');
expect(vert.get('B').text).toBe(`This node has a \\ as text`);
});
it('should handle åäö and minus', function () {
const res = flow.parser.parse('graph TD;A-->C{Chimpansen hoppar åäö-ÅÄÖ};');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('C').type).toBe('diamond');
expect(vert.get('C').text).toBe('Chimpansen hoppar åäö-ÅÄÖ');
});
it('should handle with åäö, minus and space and br', function () {
const res = flow.parser.parse('graph TD;A-->C(Chimpansen hoppar åäö <br> - ÅÄÖ);');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('C').type).toBe('round');
expect(vert.get('C').text).toBe('Chimpansen hoppar åäö <br> - ÅÄÖ');
});
// it.skip('should handle åäö, minus and space and br',function(){
// const res = flow.parser.parse('graph TD; A[Object&#40;foo,bar&#41;]-->B(Thing);');
//
// const vert = flow.parser.yy.getVertices();
// const edges = flow.parser.yy.getEdges();
//
// expect(vert.get('C').type).toBe('round');
// expect(vert.get('C').text).toBe(' A[Object&#40;foo,bar&#41;]-->B(Thing);');
// });
it('should handle unicode chars', function () {
const res = flow.parser.parse('graph TD;A-->C(Начало);');
const vert = flow.parser.yy.getVertices();
expect(vert.get('C').text).toBe('Начало');
});
it('should handle backslask', function () {
const res = flow.parser.parse('graph TD;A-->C(c:\\windows);');
const vert = flow.parser.yy.getVertices();
expect(vert.get('C').text).toBe('c:\\windows');
});
it('should handle CAPS', function () {
const res = flow.parser.parse('graph TD;A-->C(some CAPS);');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('C').type).toBe('round');
expect(vert.get('C').text).toBe('some CAPS');
});
it('should handle directions', function () {
const res = flow.parser.parse('graph TD;A-->C(some URL);');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('C').type).toBe('round');
expect(vert.get('C').text).toBe('some URL');
});
});
it('should handle multi-line text', function () {
const res = flow.parser.parse('graph TD;A--o|text space|B;\n B-->|more text with space|C;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_circle');
expect(edges[1].type).toBe('arrow_point');
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(vert.get('C').id).toBe('C');
expect(edges.length).toBe(2);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
// expect(edges[0].text).toBe('text space');
expect(edges[1].start).toBe('B');
expect(edges[1].end).toBe('C');
expect(edges[1].text).toBe('more text with space');
});
it('should handle text in vertices with space', function () {
const res = flow.parser.parse('graph TD;A[chimpansen hoppar]-->C;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').type).toBe('square');
expect(vert.get('A').text).toBe('chimpansen hoppar');
});
it('should handle text in vertices with space with spaces between vertices and link', function () {
const res = flow.parser.parse('graph TD;A[chimpansen hoppar] --> C;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').type).toBe('square');
expect(vert.get('A').text).toBe('chimpansen hoppar');
});
it('should handle text including _ in vertices', function () {
const res = flow.parser.parse('graph TD;A[chimpansen_hoppar] --> C;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').type).toBe('square');
expect(vert.get('A').text).toBe('chimpansen_hoppar');
});
it('should handle quoted text in vertices ', function () {
const res = flow.parser.parse('graph TD;A["chimpansen hoppar ()[]"] --> C;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').type).toBe('square');
expect(vert.get('A').text).toBe('chimpansen hoppar ()[]');
});
it('should handle text in circle vertices with space', function () {
const res = flow.parser.parse('graph TD;A((chimpansen hoppar))-->C;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').type).toBe('circle');
expect(vert.get('A').text).toBe('chimpansen hoppar');
});
it('should handle text in ellipse vertices', function () {
const res = flow.parser.parse('graph TD\nA(-this is an ellipse-)-->B');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').type).toBe('ellipse');
expect(vert.get('A').text).toBe('this is an ellipse');
});
it('should not freeze when ellipse text has a `(`', function () {
expect(() => flow.parser.parse('graph\nX(- My Text (')).toThrowError();
});
it('should handle text in diamond vertices with space', function () {
const res = flow.parser.parse('graph TD;A(chimpansen hoppar)-->C;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').type).toBe('round');
expect(vert.get('A').text).toBe('chimpansen hoppar');
});
it('should handle text in with ?', function () {
const res = flow.parser.parse('graph TD;A(?)-->|?|C;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').text).toBe('?');
expect(edges[0].text).toBe('?');
});
it('should handle text in with éèêàçô', function () {
const res = flow.parser.parse('graph TD;A(éèêàçô)-->|éèêàçô|C;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').text).toBe('éèêàçô');
expect(edges[0].text).toBe('éèêàçô');
});
it('should handle text in with ,.?!+-*', function () {
const res = flow.parser.parse('graph TD;A(,.?!+-*)-->|,.?!+-*|C;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').text).toBe(',.?!+-*');
expect(edges[0].text).toBe(',.?!+-*');
});
it('should throw error at nested set of brackets', function () {
const str = 'graph TD; A[This is a () in text];';
expect(() => flow.parser.parse(str)).toThrowError("got 'PS'");
});
it('should throw error for strings and text at the same time', function () {
const str = 'graph TD;A(this node has "string" and text)-->|this link has "string" and text|C;';
expect(() => flow.parser.parse(str)).toThrowError("got 'STR'");
});
it('should throw error for escaping quotes in text state', function () {
//prettier-ignore
const str = 'graph TD; A[This is a \"()\" in text];'; //eslint-disable-line no-useless-escape
expect(() => flow.parser.parse(str)).toThrowError("got 'STR'");
});
it('should throw error for nested quoatation marks', function () {
const str = 'graph TD; A["This is a "()" in text"];';
expect(() => flow.parser.parse(str)).toThrowError("Expecting 'SQE'");
});
it('should throw error', function () {
const str = `graph TD; node[hello ) world] --> works`;
expect(() => flow.parser.parse(str)).toThrowError("got 'PE'");
});
});

View File

@@ -0,0 +1,222 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
describe('when parsing flowcharts', function () {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
flow.parser.yy.setGen('gen-2');
});
it('should handle chaining of vertices', function () {
const res = flow.parser.parse(`
graph TD
A-->B-->C;
`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(vert.get('C').id).toBe('C');
expect(edges.length).toBe(2);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[1].start).toBe('B');
expect(edges[1].end).toBe('C');
expect(edges[1].type).toBe('arrow_point');
expect(edges[1].text).toBe('');
});
it('should handle chaining of vertices', function () {
const res = flow.parser.parse(`
graph TD
A & B --> C;
`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(vert.get('C').id).toBe('C');
expect(edges.length).toBe(2);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('C');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[1].start).toBe('B');
expect(edges[1].end).toBe('C');
expect(edges[1].type).toBe('arrow_point');
expect(edges[1].text).toBe('');
});
it('should multiple vertices in link statement in the begining', function () {
const res = flow.parser.parse(`
graph TD
A-->B & C;
`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(vert.get('C').id).toBe('C');
expect(edges.length).toBe(2);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[1].start).toBe('A');
expect(edges[1].end).toBe('C');
expect(edges[1].type).toBe('arrow_point');
expect(edges[1].text).toBe('');
});
it('should multiple vertices in link statement at the end', function () {
const res = flow.parser.parse(`
graph TD
A & B--> C & D;
`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(vert.get('C').id).toBe('C');
expect(vert.get('D').id).toBe('D');
expect(edges.length).toBe(4);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('C');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[1].start).toBe('A');
expect(edges[1].end).toBe('D');
expect(edges[1].type).toBe('arrow_point');
expect(edges[1].text).toBe('');
expect(edges[2].start).toBe('B');
expect(edges[2].end).toBe('C');
expect(edges[2].type).toBe('arrow_point');
expect(edges[2].text).toBe('');
expect(edges[3].start).toBe('B');
expect(edges[3].end).toBe('D');
expect(edges[3].type).toBe('arrow_point');
expect(edges[3].text).toBe('');
});
it('should handle chaining of vertices at both ends at once', function () {
const res = flow.parser.parse(`
graph TD
A & B--> C & D;
`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(vert.get('C').id).toBe('C');
expect(vert.get('D').id).toBe('D');
expect(edges.length).toBe(4);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('C');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[1].start).toBe('A');
expect(edges[1].end).toBe('D');
expect(edges[1].type).toBe('arrow_point');
expect(edges[1].text).toBe('');
expect(edges[2].start).toBe('B');
expect(edges[2].end).toBe('C');
expect(edges[2].type).toBe('arrow_point');
expect(edges[2].text).toBe('');
expect(edges[3].start).toBe('B');
expect(edges[3].end).toBe('D');
expect(edges[3].type).toBe('arrow_point');
expect(edges[3].text).toBe('');
});
it('should handle chaining and multiple nodes in link statement FVC ', function () {
const res = flow.parser.parse(`
graph TD
A --> B & B2 & C --> D2;
`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(vert.get('B2').id).toBe('B2');
expect(vert.get('C').id).toBe('C');
expect(vert.get('D2').id).toBe('D2');
expect(edges.length).toBe(6);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[1].start).toBe('A');
expect(edges[1].end).toBe('B2');
expect(edges[1].type).toBe('arrow_point');
expect(edges[1].text).toBe('');
expect(edges[2].start).toBe('A');
expect(edges[2].end).toBe('C');
expect(edges[2].type).toBe('arrow_point');
expect(edges[2].text).toBe('');
expect(edges[3].start).toBe('B');
expect(edges[3].end).toBe('D2');
expect(edges[3].type).toBe('arrow_point');
expect(edges[3].text).toBe('');
expect(edges[4].start).toBe('B2');
expect(edges[4].end).toBe('D2');
expect(edges[4].type).toBe('arrow_point');
expect(edges[4].text).toBe('');
expect(edges[5].start).toBe('C');
expect(edges[5].end).toBe('D2');
expect(edges[5].type).toBe('arrow_point');
expect(edges[5].text).toBe('');
});
it('should handle chaining and multiple nodes in link statement with extra info in statements', function () {
const res = flow.parser.parse(`
graph TD
A[ h ] -- hello --> B[" test "]:::exClass & C --> D;
classDef exClass background:#bbb,border:1px solid red;
`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const classes = flow.parser.yy.getClasses();
expect(classes.get('exClass').styles.length).toBe(2);
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(vert.get('B').classes[0]).toBe('exClass');
expect(vert.get('C').id).toBe('C');
expect(vert.get('D').id).toBe('D');
expect(edges.length).toBe(4);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('hello');
expect(edges[1].start).toBe('A');
expect(edges[1].end).toBe('C');
expect(edges[1].type).toBe('arrow_point');
expect(edges[1].text).toBe('hello');
expect(edges[2].start).toBe('B');
expect(edges[2].end).toBe('D');
expect(edges[2].type).toBe('arrow_point');
expect(edges[2].text).toBe('');
expect(edges[3].start).toBe('C');
expect(edges[3].end).toBe('D');
expect(edges[3].type).toBe('arrow_point');
expect(edges[3].text).toBe('');
});
});

View File

@@ -0,0 +1,240 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { cleanupComments } from '../../../diagram-api/comments.js';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
describe('parsing a flow chart', function () {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
});
it('should handle a trailing whitespaces after statements', function () {
const res = flow.parser.parse(cleanupComments('graph TD;\n\n\n %% Comment\n A-->B; \n B-->C;'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
expect(edges.length).toBe(2);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
});
it('should handle node names with "end" substring', function () {
const res = flow.parser.parse('graph TD\nendpoint --> sender');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('endpoint').id).toBe('endpoint');
expect(vert.get('sender').id).toBe('sender');
expect(edges[0].start).toBe('endpoint');
expect(edges[0].end).toBe('sender');
});
it('should handle node names ending with keywords', function () {
const res = flow.parser.parse('graph TD\nblend --> monograph');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('blend').id).toBe('blend');
expect(vert.get('monograph').id).toBe('monograph');
expect(edges[0].start).toBe('blend');
expect(edges[0].end).toBe('monograph');
});
it('should allow default in the node name/id', function () {
const res = flow.parser.parse('graph TD\ndefault --> monograph');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('default').id).toBe('default');
expect(vert.get('monograph').id).toBe('monograph');
expect(edges[0].start).toBe('default');
expect(edges[0].end).toBe('monograph');
});
describe('special characters should be handled.', function () {
const charTest = function (char, result) {
const res = flow.parser.parse('graph TD;A(' + char + ')-->B;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert.get('A').id).toBe('A');
expect(vert.get('B').id).toBe('B');
if (result) {
expect(vert.get('A').text).toBe(result);
} else {
expect(vert.get('A').text).toBe(char);
}
flow.parser.yy.clear();
};
it("should be able to parse a '.'", function () {
charTest('.');
charTest('Start 103a.a1');
});
// it('should be able to parse text containing \'_\'', function () {
// charTest('_')
// })
it("should be able to parse a ':'", function () {
charTest(':');
});
it("should be able to parse a ','", function () {
charTest(',');
});
it("should be able to parse text containing '-'", function () {
charTest('a-b');
});
it("should be able to parse a '+'", function () {
charTest('+');
});
it("should be able to parse a '*'", function () {
charTest('*');
});
it("should be able to parse a '<'", function () {
charTest('<', '&lt;');
});
// it("should be able to parse a '>'", function() {
// charTest('>', '&gt;');
// });
// it("should be able to parse a '='", function() {
// charTest('=', '&equals;');
// });
it("should be able to parse a '&'", function () {
charTest('&');
});
});
it('should be possible to use direction in node ids', function () {
let statement = '';
statement = statement + 'graph TD;' + '\n';
statement = statement + ' node1TB\n';
const res = flow.parser.parse(statement);
const vertices = flow.parser.yy.getVertices();
const classes = flow.parser.yy.getClasses();
expect(vertices.get('node1TB').id).toBe('node1TB');
});
it('should be possible to use direction in node ids', function () {
let statement = '';
statement = statement + 'graph TD;A--x|text including URL space|B;';
const res = flow.parser.parse(statement);
const vertices = flow.parser.yy.getVertices();
const classes = flow.parser.yy.getClasses();
expect(vertices.get('A').id).toBe('A');
});
it('should be possible to use numbers as labels', function () {
let statement = '';
statement = statement + 'graph TB;subgraph "number as labels";1;end;';
const res = flow.parser.parse(statement);
const vertices = flow.parser.yy.getVertices();
expect(vertices.get('1').id).toBe('1');
});
it('should add accTitle and accDescr to flow chart', function () {
const flowChart = `graph LR
accTitle: Big decisions
accDescr: Flow chart of the decision making process
A[Hard] -->|Text| B(Round)
B --> C{Decision}
C -->|One| D[Result 1]
C -->|Two| E[Result 2]
`;
flow.parser.parse(flowChart);
expect(flow.parser.yy.getAccTitle()).toBe('Big decisions');
expect(flow.parser.yy.getAccDescription()).toBe('Flow chart of the decision making process');
});
it('should add accTitle and a multi line accDescr to flow chart', function () {
const flowChart = `graph LR
accTitle: Big decisions
accDescr {
Flow chart of the decision making process
with a second line
}
A[Hard] -->|Text| B(Round)
B --> C{Decision}
C -->|One| D[Result 1]
C -->|Two| E[Result 2]
`;
flow.parser.parse(flowChart);
expect(flow.parser.yy.getAccTitle()).toBe('Big decisions');
expect(flow.parser.yy.getAccDescription()).toBe(
`Flow chart of the decision making process
with a second line`
);
});
for (const unsafeProp of ['__proto__', 'constructor']) {
it(`should work with node id ${unsafeProp}`, function () {
const flowChart = `graph LR
${unsafeProp} --> A;`;
expect(() => {
flow.parser.parse(flowChart);
}).not.toThrow();
});
it(`should work with tooltip id ${unsafeProp}`, function () {
const flowChart = `graph LR
click ${unsafeProp} callback "${unsafeProp}";`;
expect(() => {
flow.parser.parse(flowChart);
}).not.toThrow();
});
it(`should work with class id ${unsafeProp}`, function () {
const flowChart = `graph LR
${unsafeProp} --> A;
classDef ${unsafeProp} color:#ffffff,fill:#000000;
class ${unsafeProp} ${unsafeProp};`;
expect(() => {
flow.parser.parse(flowChart);
}).not.toThrow();
});
it(`should work with subgraph id ${unsafeProp}`, function () {
const flowChart = `graph LR
${unsafeProp} --> A;
subgraph ${unsafeProp}
C --> D;
end;`;
expect(() => {
flow.parser.parse(flowChart);
}).not.toThrow();
});
}
});

View File

@@ -0,0 +1,312 @@
import flowDb from '../flowDb.js';
import flow from './flow.jison';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
describe('when parsing subgraphs', function () {
beforeEach(function () {
flow.parser.yy = flowDb;
flow.parser.yy.clear();
flow.parser.yy.setGen('gen-2');
});
it('should handle subgraph with tab indentation', function () {
const res = flow.parser.parse('graph TB\nsubgraph One\n\ta1-->a2\nend');
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(2);
expect(subgraph.nodes[0]).toBe('a2');
expect(subgraph.nodes[1]).toBe('a1');
expect(subgraph.title).toBe('One');
expect(subgraph.id).toBe('One');
});
it('should handle subgraph with chaining nodes indentation', function () {
const res = flow.parser.parse('graph TB\nsubgraph One\n\ta1-->a2-->a3\nend');
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(3);
expect(subgraph.nodes[0]).toBe('a3');
expect(subgraph.nodes[1]).toBe('a2');
expect(subgraph.nodes[2]).toBe('a1');
expect(subgraph.title).toBe('One');
expect(subgraph.id).toBe('One');
});
it('should handle subgraph with multiple words in title', function () {
const res = flow.parser.parse('graph TB\nsubgraph "Some Title"\n\ta1-->a2\nend');
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(2);
expect(subgraph.nodes[0]).toBe('a2');
expect(subgraph.nodes[1]).toBe('a1');
expect(subgraph.title).toBe('Some Title');
expect(subgraph.id).toBe('subGraph0');
});
it('should handle subgraph with id and title notation', function () {
const res = flow.parser.parse('graph TB\nsubgraph some-id[Some Title]\n\ta1-->a2\nend');
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(2);
expect(subgraph.nodes[0]).toBe('a2');
expect(subgraph.nodes[1]).toBe('a1');
expect(subgraph.title).toBe('Some Title');
expect(subgraph.id).toBe('some-id');
});
it.skip('should handle subgraph without id and space in title', function () {
const res = flow.parser.parse('graph TB\nsubgraph Some Title\n\ta1-->a2\nend');
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(2);
expect(subgraph.nodes[0]).toBe('a1');
expect(subgraph.nodes[1]).toBe('a2');
expect(subgraph.title).toBe('Some Title');
expect(subgraph.id).toBe('some-id');
});
it('should handle subgraph id starting with a number', function () {
const res = flow.parser.parse(`graph TD
A[Christmas] -->|Get money| B(Go shopping)
subgraph 1test
A
end`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.nodes.length).toBe(1);
expect(subgraph.nodes[0]).toBe('A');
expect(subgraph.id).toBe('1test');
});
it('should handle subgraphs1', function () {
const res = flow.parser.parse('graph TD;A-->B;subgraph myTitle;c-->d;end;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_point');
});
it('should handle subgraphs with title in quotes', function () {
const res = flow.parser.parse('graph TD;A-->B;subgraph "title in quotes";c-->d;end;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.title).toBe('title in quotes');
expect(edges[0].type).toBe('arrow_point');
});
it('should handle subgraphs in old style that was broken', function () {
const res = flow.parser.parse('graph TD;A-->B;subgraph old style that is broken;c-->d;end;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.title).toBe('old style that is broken');
expect(edges[0].type).toBe('arrow_point');
});
it('should handle subgraphs with dashes in the title', function () {
const res = flow.parser.parse('graph TD;A-->B;subgraph a-b-c;c-->d;end;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.title).toBe('a-b-c');
expect(edges[0].type).toBe('arrow_point');
});
it('should handle subgraphs with id and title in brackets', function () {
const res = flow.parser.parse('graph TD;A-->B;subgraph uid1[text of doom];c-->d;end;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.title).toBe('text of doom');
expect(subgraph.id).toBe('uid1');
expect(edges[0].type).toBe('arrow_point');
});
it('should handle subgraphs with id and title in brackets and quotes', function () {
const res = flow.parser.parse('graph TD;A-->B;subgraph uid2["text of doom"];c-->d;end;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.title).toBe('text of doom');
expect(subgraph.id).toBe('uid2');
expect(edges[0].type).toBe('arrow_point');
});
it('should handle subgraphs with id and title in brackets without spaces', function () {
const res = flow.parser.parse('graph TD;A-->B;subgraph uid2[textofdoom];c-->d;end;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.title).toBe('textofdoom');
expect(subgraph.id).toBe('uid2');
expect(edges[0].type).toBe('arrow_point');
});
it('should handle subgraphs2', function () {
const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\n\n c-->d \nend\n');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_point');
});
it('should handle subgraphs3', function () {
const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle \n\n c-->d \nend\n');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_point');
});
it('should handle nested subgraphs', function () {
const str =
'graph TD\n' +
'A-->B\n' +
'subgraph myTitle\n\n' +
' c-->d \n\n' +
' subgraph inner\n\n e-->f \n end \n\n' +
' subgraph inner\n\n h-->i \n end \n\n' +
'end\n';
const res = flow.parser.parse(str);
});
it('should handle subgraphs4', function () {
const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\nc-->d\nend;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_point');
});
it('should handle subgraphs5', function () {
const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\nc-- text -->d\nd-->e\n end;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_point');
});
it('should handle subgraphs with multi node statements in it', function () {
const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\na & b --> c & e\n end;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges[0].type).toBe('arrow_point');
});
it('should handle nested subgraphs 1', function () {
const res = flow.parser.parse(`flowchart TB
subgraph A
b-->B
a
end
a-->c
subgraph B
c
end`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(2);
const subgraphA = subgraphs.find((o) => o.id === 'A');
const subgraphB = subgraphs.find((o) => o.id === 'B');
expect(subgraphB.nodes[0]).toBe('c');
expect(subgraphA.nodes).toContain('B');
expect(subgraphA.nodes).toContain('b');
expect(subgraphA.nodes).toContain('a');
expect(subgraphA.nodes).not.toContain('c');
});
it('should handle nested subgraphs 2', function () {
const res = flow.parser.parse(`flowchart TB
b-->B
a-->c
subgraph B
c
end
subgraph A
a
b
B
end`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(2);
const subgraphA = subgraphs.find((o) => o.id === 'A');
const subgraphB = subgraphs.find((o) => o.id === 'B');
expect(subgraphB.nodes[0]).toBe('c');
expect(subgraphA.nodes).toContain('B');
expect(subgraphA.nodes).toContain('b');
expect(subgraphA.nodes).toContain('a');
expect(subgraphA.nodes).not.toContain('c');
});
it('should handle nested subgraphs 3', function () {
const res = flow.parser.parse(`flowchart TB
subgraph B
c
end
a-->c
subgraph A
b-->B
a
end`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(2);
const subgraphA = subgraphs.find((o) => o.id === 'A');
const subgraphB = subgraphs.find((o) => o.id === 'B');
expect(subgraphB.nodes[0]).toBe('c');
expect(subgraphA.nodes).toContain('B');
expect(subgraphA.nodes).toContain('b');
expect(subgraphA.nodes).toContain('a');
expect(subgraphA.nodes).not.toContain('c');
});
});

View File

@@ -0,0 +1,628 @@
/** mermaid
* https://mermaidjs.github.io/
* (c) 2015 Knut Sveidqvist
* MIT license.
*/
/* lexical grammar */
%lex
%x string
%x md_string
%x acc_title
%x acc_descr
%x acc_descr_multiline
%x dir
%x vertex
%x text
%x ellipseText
%x trapText
%x edgeText
%x thickEdgeText
%x dottedEdgeText
%x click
%x href
%x callbackname
%x callbackargs
%x shapeData
%x shapeDataStr
%x shapeDataEndBracket
%%
accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; }
<acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; }
accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; }
<acc_descr>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; }
accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
<acc_descr_multiline>[\}] { this.popState(); }
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
// <acc_descr_multiline>.*[^\n]* { return "acc_descr_line"}
\@\{ {
// console.log('=> shapeData', yytext);
this.pushState("shapeData"); yytext=""; return 'SHAPE_DATA' }
<shapeData>["] {
// console.log('=> shapeDataStr', yytext);
this.pushState("shapeDataStr");
return 'SHAPE_DATA';
}
<shapeDataStr>["] {
// console.log('shapeData <==', yytext);
this.popState(); return 'SHAPE_DATA'}
<shapeDataStr>[^\"]+ {
// console.log('shapeData', yytext);
const re = /\n\s*/g;
yytext = yytext.replace(re,"<br/>");
return 'SHAPE_DATA'}
<shapeData>[^}^"]+ {
// console.log('shapeData', yytext);
return 'SHAPE_DATA';
}
<shapeData>"}" {
// console.log('<== root', yytext)
this.popState();
}
/*
---interactivity command---
'call' adds a callback to the specified node. 'call' can only be specified when
the line was introduced with 'click'.
'call <callbackname>(<args>)' attaches the function 'callbackname' with the specified
arguments to the node that was specified by 'click'.
Function arguments are optional: 'call <callbackname>()' simply executes 'callbackname' without any arguments.
*/
"call"[\s]+ this.begin("callbackname");
<callbackname>\([\s]*\) this.popState();
<callbackname>\( this.popState(); this.begin("callbackargs");
<callbackname>[^(]* return 'CALLBACKNAME';
<callbackargs>\) this.popState();
<callbackargs>[^)]* return 'CALLBACKARGS';
<md_string>[^`"]+ { return "MD_STR";}
<md_string>[`]["] { this.popState();}
<*>["][`] { this.begin("md_string");}
<string>[^"]+ { return "STR"; }
<string>["] this.popState();
<*>["] this.pushState("string");
"style" return 'STYLE';
"default" return 'DEFAULT';
"linkStyle" return 'LINKSTYLE';
"interpolate" return 'INTERPOLATE';
"classDef" return 'CLASSDEF';
"class" return 'CLASS';
/*
---interactivity command---
'href' adds a link to the specified node. 'href' can only be specified when the
line was introduced with 'click'.
'href "<link>"' attaches the specified link to the node that was specified by 'click'.
*/
"href"[\s] return 'HREF';
/*
'click' is the keyword to introduce a line that contains interactivity commands.
'click' must be followed by an existing node-id. All commands are attached to
that id.
'click <id>' can be followed by href or call commands in any desired order
*/
"click"[\s]+ this.begin("click");
<click>[\s\n] this.popState();
<click>[^\s\n]* return 'CLICK';
"swimlane" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';}
"lane" return 'subgraph';
"end"\b\s* return 'end';
"_self" return 'LINK_TARGET';
"_blank" return 'LINK_TARGET';
"_parent" return 'LINK_TARGET';
"_top" return 'LINK_TARGET';
<dir>(\r?\n)*\s*\n { this.popState(); return 'NODIR'; }
<dir>\s*"LR" { this.popState(); return 'DIR'; }
<dir>\s*"RL" { this.popState(); return 'DIR'; }
<dir>\s*"TB" { this.popState(); return 'DIR'; }
<dir>\s*"BT" { this.popState(); return 'DIR'; }
<dir>\s*"TD" { this.popState(); return 'DIR'; }
<dir>\s*"BR" { this.popState(); return 'DIR'; }
<dir>\s*"<" { this.popState(); return 'DIR'; }
<dir>\s*">" { this.popState(); return 'DIR'; }
<dir>\s*"^" { this.popState(); return 'DIR'; }
<dir>\s*"v" { this.popState(); return 'DIR'; }
.*direction\s+TB[^\n]* return 'direction_tb';
.*direction\s+BT[^\n]* return 'direction_bt';
.*direction\s+RL[^\n]* return 'direction_rl';
.*direction\s+LR[^\n]* return 'direction_lr';
[0-9]+ return 'NUM';
\# return 'BRKT';
":::" return 'STYLE_SEPARATOR';
":" return 'COLON';
"&" return 'AMP';
";" return 'SEMI';
"," return 'COMMA';
"*" return 'MULT';
<INITIAL,edgeText>\s*[xo<]?\-\-+[-xo>]\s* { this.popState(); return 'LINK'; }
<INITIAL>\s*[xo<]?\-\-\s* { this.pushState("edgeText"); return 'START_LINK'; }
<edgeText>[^-]|\-(?!\-)+ return 'EDGE_TEXT';
<INITIAL,thickEdgeText>\s*[xo<]?\=\=+[=xo>]\s* { this.popState(); return 'LINK'; }
<INITIAL>\s*[xo<]?\=\=\s* { this.pushState("thickEdgeText"); return 'START_LINK'; }
<thickEdgeText>[^=]|\=(?!=) return 'EDGE_TEXT';
<INITIAL,dottedEdgeText>\s*[xo<]?\-?\.+\-[xo>]?\s* { this.popState(); return 'LINK'; }
<INITIAL>\s*[xo<]?\-\.\s* { this.pushState("dottedEdgeText"); return 'START_LINK'; }
<dottedEdgeText>[^\.]|\.(?!-) return 'EDGE_TEXT';
<*>\s*\~\~[\~]+\s* return 'LINK';
<ellipseText>[-/\)][\)] { this.popState(); return '-)'; }
<ellipseText>[^\(\)\[\]\{\}]|-\!\)+ return "TEXT"
<*>"(-" { this.pushState("ellipseText"); return '(-'; }
<text>"])" { this.popState(); return 'STADIUMEND'; }
<*>"([" { this.pushState("text"); return 'STADIUMSTART'; }
<text>"]]" { this.popState(); return 'SUBROUTINEEND'; }
<*>"[[" { this.pushState("text"); return 'SUBROUTINESTART'; }
"[|" { return 'VERTEX_WITH_PROPS_START'; }
\> { this.pushState("text"); return 'TAGEND'; }
<text>")]" { this.popState(); return 'CYLINDEREND'; }
<*>"[(" { this.pushState("text") ;return 'CYLINDERSTART'; }
<text>")))" { this.popState(); return 'DOUBLECIRCLEEND'; }
<*>"(((" { this.pushState("text"); return 'DOUBLECIRCLESTART'; }
<trapText>[\\(?=\])][\]] { this.popState(); return 'TRAPEND'; }
<trapText>\/(?=\])\] { this.popState(); return 'INVTRAPEND'; }
<trapText>\/(?!\])|\\(?!\])|[^\\\[\]\(\)\{\}\/]+ return 'TEXT';
<*>"[/" { this.pushState("trapText"); return 'TRAPSTART'; }
<*>"[\\" { this.pushState("trapText"); return 'INVTRAPSTART'; }
"<" return 'TAGSTART';
">" return 'TAGEND';
"^" return 'UP';
"\|" return 'SEP';
"v" return 'DOWN';
"*" return 'MULT';
"#" return 'BRKT';
"&" return 'AMP';
([A-Za-z0-9!"\#$%&'*+\.`?\\_\/]|\-(?=[^\>\-\.])|=(?!=))+ return 'NODE_STRING';
"-" return 'MINUS'
[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|
[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|
[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|
[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|
[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|
[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|
[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|
[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|
[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|
[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|
[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|
[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|
[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|
[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|
[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|
[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|
[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|
[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|
[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|
[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|
[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|
[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|
[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|
[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|
[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|
[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|
[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|
[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|
[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|
[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|
[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|
[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|
[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|
[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|
[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|
[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|
[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|
[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|
[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|
[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|
[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|
[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|
[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|
[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|
[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|
[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|
[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|
[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|
[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|
[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|
[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|
[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|
[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|
[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|
[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|
[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|
[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|
[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|
[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|
[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|
[\uFFD2-\uFFD7\uFFDA-\uFFDC]
return 'UNICODE_TEXT';
<text>"|" { this.popState(); return 'PIPE'; }
<*>"|" { this.pushState("text"); return 'PIPE'; }
<text>")" { this.popState(); return 'PE'; }
<*>"(" { this.pushState("text"); return 'PS'; }
<text>"]" { this.popState(); return 'SQE'; }
<*>"[" { this.pushState("text"); return 'SQS'; }
<text>(\}) { this.popState(); return 'DIAMOND_STOP' }
<*>"{" { this.pushState("text"); return 'DIAMOND_START' }
<text>[^\[\]\(\)\{\}\|\"]+ return "TEXT";
"\"" return 'QUOTE';
(\r?\n)+ return 'NEWLINE';
\s return 'SPACE';
<<EOF>> return 'EOF';
/lex
/* operator associations and precedence */
%left '^'
%start start
%% /* language grammar */
start
: graphConfig document
;
document
: /* empty */
{ $$ = [];}
| document line
{
if(!Array.isArray($line) || $line.length > 0){
$document.push($line);
}
$$=$document;}
;
line
: statement
{$$=$statement;}
| SEMI
| NEWLINE
| SPACE
| EOF
;
graphConfig
: SPACE graphConfig
| NEWLINE graphConfig
| GRAPH NODIR
{ yy.setDirection('TB');$$ = 'TB';}
| GRAPH DIR FirstStmtSeparator
{ yy.setDirection($DIR);$$ = $DIR;}
// | GRAPH SPACE TAGEND FirstStmtSeparator
// { yy.setDirection("LR");$$ = $TAGEND;}
// | GRAPH SPACE TAGSTART FirstStmtSeparator
// { yy.setDirection("RL");$$ = $TAGSTART;}
// | GRAPH SPACE UP FirstStmtSeparator
// { yy.setDirection("BT");$$ = $UP;}
// | GRAPH SPACE DOWN FirstStmtSeparator
// { yy.setDirection("TB");$$ = $DOWN;}
;
ending: endToken ending
| endToken
;
endToken: NEWLINE | SPACE | EOF;
FirstStmtSeparator
: SEMI | NEWLINE | spaceList NEWLINE ;
spaceListNewline
: SPACE spaceListNewline
| NEWLINE spaceListNewline
| NEWLINE
| SPACE
;
spaceList
: SPACE spaceList
| SPACE
;
statement
: vertexStatement separator
{ /* console.warn('finat vs', $vertexStatement.nodes); */ $$=$vertexStatement.nodes}
| styleStatement separator
{$$=[];}
| linkStyleStatement separator
{$$=[];}
| classDefStatement separator
{$$=[];}
| classStatement separator
{$$=[];}
| clickStatement separator
{$$=[];}
| subgraph SPACE textNoTags SQS text SQE separator document end
{$$=yy.addSubGraph($textNoTags,$document,$text);}
| subgraph SPACE textNoTags separator document end
{$$=yy.addSubGraph($textNoTags,$document,$textNoTags);}
| subgraph separator document end
{$$=yy.addSubGraph(undefined,$document,undefined);}
| lane SPACE textNoTags SQS text SQE separator document end
{$$=yy.addSubGraph($textNoTags,$document,$text, 'lane');}
| lane SPACE textNoTags separator document end
{$$=yy.addSubGraph($textNoTags,$document,$textNoTags, 'lane');}
| lane separator document end
{$$=yy.addSubGraph(undefined,$document,undefined, 'lane');}
| direction
| acc_title acc_title_value { $$=$acc_title_value.trim();yy.setAccTitle($$); }
| acc_descr acc_descr_value { $$=$acc_descr_value.trim();yy.setAccDescription($$); }
| acc_descr_multiline_value { $$=$acc_descr_multiline_value.trim();yy.setAccDescription($$); }
;
separator: NEWLINE | SEMI | EOF ;
shapeData:
shapeData SHAPE_DATA
{ $$ = $1 + $2; }
| SHAPE_DATA
{ $$ = $1; }
;
vertexStatement: vertexStatement link node shapeData
{ /* console.warn('vs shapeData',$vertexStatement.stmt,$node, $shapeData);*/ yy.addVertex($node[0],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData); yy.addLink($vertexStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($vertexStatement.nodes) } }
| vertexStatement link node
{ /*console.warn('vs',$vertexStatement.stmt,$node);*/ yy.addLink($vertexStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($vertexStatement.nodes) } }
| vertexStatement link node spaceList
{ /* console.warn('vs',$vertexStatement.stmt,$node); */ yy.addLink($vertexStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($vertexStatement.nodes) } }
|node spaceList { /*console.warn('vertexStatement: node spaceList', $node);*/ $$ = {stmt: $node, nodes:$node }}
|node shapeData {
/*console.warn('vertexStatement: node shapeData', $node[0], $shapeData);*/
yy.addVertex($node[0],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData);
$$ = {stmt: $node, nodes:$node, shapeData: $shapeData}
}
|node { /* console.warn('vertexStatement: single node', $node); */ $$ = {stmt: $node, nodes:$node }}
;
node: styledVertex
{ /*console.warn('nod', $styledVertex);*/ $$ = [$styledVertex];}
| node shapeData spaceList AMP spaceList styledVertex
{ yy.addVertex($node[0],undefined,undefined,undefined, undefined,undefined, undefined,$shapeData); $$ = $node.concat($styledVertex); /*console.warn('pip2', $node[0], $styledVertex, $$);*/ }
| node spaceList AMP spaceList styledVertex
{ $$ = $node.concat($styledVertex); /*console.warn('pip', $node[0], $styledVertex, $$);*/ }
;
styledVertex: vertex
{ /* console.warn('nodc', $vertex);*/ $$ = $vertex;}
| vertex STYLE_SEPARATOR idString
{$$ = $vertex;yy.setClass($vertex,$idString)}
;
vertex: idString SQS text SQE
{$$ = $idString;yy.addVertex($idString,$text,'square');}
| idString DOUBLECIRCLESTART text DOUBLECIRCLEEND
{$$ = $idString;yy.addVertex($idString,$text,'doublecircle');}
| idString PS PS text PE PE
{$$ = $idString;yy.addVertex($idString,$text,'circle');}
| idString '(-' text '-)'
{$$ = $idString;yy.addVertex($idString,$text,'ellipse');}
| idString STADIUMSTART text STADIUMEND
{$$ = $idString;yy.addVertex($idString,$text,'stadium');}
| idString SUBROUTINESTART text SUBROUTINEEND
{$$ = $idString;yy.addVertex($idString,$text,'subroutine');}
| idString VERTEX_WITH_PROPS_START NODE_STRING\[field] COLON NODE_STRING\[value] PIPE text SQE
{$$ = $idString;yy.addVertex($idString,$text,'rect',undefined,undefined,undefined, Object.fromEntries([[$field, $value]]));}
| idString CYLINDERSTART text CYLINDEREND
{$$ = $idString;yy.addVertex($idString,$text,'cylinder');}
| idString PS text PE
{$$ = $idString;yy.addVertex($idString,$text,'round');}
| idString DIAMOND_START text DIAMOND_STOP
{$$ = $idString;yy.addVertex($idString,$text,'diamond');}
| idString DIAMOND_START DIAMOND_START text DIAMOND_STOP DIAMOND_STOP
{$$ = $idString;yy.addVertex($idString,$text,'hexagon');}
| idString TAGEND text SQE
{$$ = $idString;yy.addVertex($idString,$text,'odd');}
| idString TRAPSTART text TRAPEND
{$$ = $idString;yy.addVertex($idString,$text,'trapezoid');}
| idString INVTRAPSTART text INVTRAPEND
{$$ = $idString;yy.addVertex($idString,$text,'inv_trapezoid');}
| idString TRAPSTART text INVTRAPEND
{$$ = $idString;yy.addVertex($idString,$text,'lean_right');}
| idString INVTRAPSTART text TRAPEND
{$$ = $idString;yy.addVertex($idString,$text,'lean_left');}
| idString
{ /*console.warn('h: ', $idString);*/$$ = $idString;yy.addVertex($idString);}
;
link: linkStatement arrowText
{$linkStatement.text = $arrowText;$$ = $linkStatement;}
| linkStatement TESTSTR SPACE
{$linkStatement.text = $TESTSTR;$$ = $linkStatement;}
| linkStatement arrowText SPACE
{$linkStatement.text = $arrowText;$$ = $linkStatement;}
| linkStatement
{$$ = $linkStatement;}
| START_LINK edgeText LINK
{var inf = yy.destructLink($LINK, $START_LINK); $$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length,"text":$edgeText};}
;
edgeText: edgeTextToken
{$$={text:$edgeTextToken, type:'text'};}
| edgeText edgeTextToken
{$$={text:$edgeText.text+''+$edgeTextToken, type:$edgeText.type};}
|STR
{$$={text: $STR, type: 'string'};}
| MD_STR
{$$={text:$MD_STR, type:'markdown'};}
;
linkStatement: LINK
{var inf = yy.destructLink($LINK);$$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length};}
;
arrowText:
PIPE text PIPE
{$$ = $text;}
;
text: textToken
{ $$={text:$textToken, type: 'text'};}
| text textToken
{ $$={text:$text.text+''+$textToken, type: $text.type};}
| STR
{ $$ = {text: $STR, type: 'string'};}
| MD_STR
{ $$={text: $MD_STR, type: 'markdown'};}
;
keywords
: STYLE | LINKSTYLE | CLASSDEF | CLASS | CLICK | GRAPH | DIR | subgraph | end | DOWN | UP;
textNoTags: textNoTagsToken
{$$={text:$textNoTagsToken, type: 'text'};}
| textNoTags textNoTagsToken
{$$={text:$textNoTags.text+''+$textNoTagsToken, type: $textNoTags.type};}
| STR
{ $$={text: $STR, type: 'text'};}
| MD_STR
{ $$={text: $MD_STR, type: 'markdown'};}
;
classDefStatement:CLASSDEF SPACE idString SPACE stylesOpt
{$$ = $CLASSDEF;yy.addClass($idString,$stylesOpt);}
;
classStatement:CLASS SPACE idString\[vertex] SPACE idString\[class]
{$$ = $CLASS;yy.setClass($vertex, $class);}
;
clickStatement
: CLICK CALLBACKNAME {$$ = $CLICK;yy.setClickEvent($CLICK, $CALLBACKNAME);}
| CLICK CALLBACKNAME SPACE STR {$$ = $CLICK;yy.setClickEvent($CLICK, $CALLBACKNAME);yy.setTooltip($CLICK, $STR);}
| CLICK CALLBACKNAME CALLBACKARGS {$$ = $CLICK;yy.setClickEvent($CLICK, $CALLBACKNAME, $CALLBACKARGS);}
| CLICK CALLBACKNAME CALLBACKARGS SPACE STR {$$ = $CLICK;yy.setClickEvent($CLICK, $CALLBACKNAME, $CALLBACKARGS);yy.setTooltip($CLICK, $STR);}
| CLICK HREF STR {$$ = $CLICK;yy.setLink($CLICK, $STR);}
| CLICK HREF STR SPACE STR {$$ = $CLICK;yy.setLink($CLICK, $STR1);yy.setTooltip($CLICK, $STR2);}
| CLICK HREF STR SPACE LINK_TARGET {$$ = $CLICK;yy.setLink($CLICK, $STR, $LINK_TARGET);}
| CLICK HREF STR\[link] SPACE STR\[tooltip] SPACE LINK_TARGET {$$ = $CLICK;yy.setLink($CLICK, $link, $LINK_TARGET);yy.setTooltip($CLICK, $tooltip);}
| CLICK alphaNum {$$ = $CLICK;yy.setClickEvent($CLICK, $alphaNum);}
| CLICK alphaNum SPACE STR {$$ = $CLICK;yy.setClickEvent($CLICK, $alphaNum);yy.setTooltip($CLICK, $STR);}
| CLICK STR {$$ = $CLICK;yy.setLink($CLICK, $STR);}
| CLICK STR\[link] SPACE STR\[tooltip] {$$ = $CLICK;yy.setLink($CLICK, $link);yy.setTooltip($CLICK, $tooltip);}
| CLICK STR SPACE LINK_TARGET {$$ = $CLICK;yy.setLink($CLICK, $STR, $LINK_TARGET);}
| CLICK STR\[link] SPACE STR\[tooltip] SPACE LINK_TARGET {$$ = $CLICK;yy.setLink($CLICK, $link, $LINK_TARGET);yy.setTooltip($CLICK, $tooltip);}
;
styleStatement:STYLE SPACE idString SPACE stylesOpt
{$$ = $STYLE;yy.addVertex($idString,undefined,undefined,$stylesOpt);}
;
linkStyleStatement
: LINKSTYLE SPACE DEFAULT SPACE stylesOpt
{$$ = $LINKSTYLE;yy.updateLink([$DEFAULT],$stylesOpt);}
| LINKSTYLE SPACE numList SPACE stylesOpt
{$$ = $LINKSTYLE;yy.updateLink($numList,$stylesOpt);}
| LINKSTYLE SPACE DEFAULT SPACE INTERPOLATE SPACE alphaNum SPACE stylesOpt
{$$ = $LINKSTYLE;yy.updateLinkInterpolate([$DEFAULT],$alphaNum);yy.updateLink([$DEFAULT],$stylesOpt);}
| LINKSTYLE SPACE numList SPACE INTERPOLATE SPACE alphaNum SPACE stylesOpt
{$$ = $LINKSTYLE;yy.updateLinkInterpolate($numList,$alphaNum);yy.updateLink($numList,$stylesOpt);}
| LINKSTYLE SPACE DEFAULT SPACE INTERPOLATE SPACE alphaNum
{$$ = $LINKSTYLE;yy.updateLinkInterpolate([$DEFAULT],$alphaNum);}
| LINKSTYLE SPACE numList SPACE INTERPOLATE SPACE alphaNum
{$$ = $LINKSTYLE;yy.updateLinkInterpolate($numList,$alphaNum);}
;
numList: NUM
{$$ = [$NUM]}
| numList COMMA NUM
{$numList.push($NUM);$$ = $numList;}
;
stylesOpt: style
{$$ = [$style]}
| stylesOpt COMMA style
{$stylesOpt.push($style);$$ = $stylesOpt;}
;
style: styleComponent
|style styleComponent
{$$ = $style + $styleComponent;}
;
styleComponent: NUM | NODE_STRING| COLON | UNIT | SPACE | BRKT | STYLE | PCT ;
/* Token lists */
idStringToken : NUM | NODE_STRING | DOWN | MINUS | DEFAULT | COMMA | COLON | AMP | BRKT | MULT | UNICODE_TEXT;
textToken : TEXT | TAGSTART | TAGEND | UNICODE_TEXT;
textNoTagsToken: NUM | NODE_STRING | SPACE | MINUS | AMP | UNICODE_TEXT | COLON | MULT | BRKT | keywords | START_LINK ;
edgeTextToken : EDGE_TEXT | UNICODE_TEXT ;
alphaNumToken : NUM | UNICODE_TEXT | NODE_STRING | DIR | DOWN | MINUS | COMMA | COLON | AMP | BRKT | MULT;
idString
:idStringToken
{$$=$idStringToken}
| idString idStringToken
{$$=$idString+''+$idStringToken}
;
alphaNum
: alphaNumToken
{$$=$alphaNumToken;}
| alphaNum alphaNumToken
{$$=$alphaNum+''+$alphaNumToken;}
;
direction
: direction_tb
{ $$={stmt:'dir', value:'TB'};}
| direction_bt
{ $$={stmt:'dir', value:'BT'};}
| direction_rl
{ $$={stmt:'dir', value:'RL'};}
| direction_lr
{ $$={stmt:'dir', value:'LR'};}
;
%%

View File

@@ -0,0 +1,38 @@
// import khroma from 'khroma';
import * as khroma from 'khroma';
import getStyleFlowchart from '../flowchart/styles.ts';
/** Returns the styles given options */
export interface FlowChartStyleOptions {
arrowheadColor: string;
border2: string;
clusterBkg: string;
clusterBorder: string;
edgeLabelBackground: string;
fontFamily: string;
lineColor: string;
mainBkg: string;
nodeBorder: string;
nodeTextColor: string;
tertiaryColor: string;
textColor: string;
titleColor: string;
}
const fade = (color: string, opacity: number) => {
// @ts-ignore TODO: incorrect types from khroma
const channel = khroma.channel;
const r = channel(color, 'r');
const g = channel(color, 'g');
const b = channel(color, 'b');
// @ts-ignore incorrect types from khroma
return khroma.rgba(r, g, b, opacity);
};
const getStyles = (options: FlowChartStyleOptions) =>
`${getStyleFlowchart(options)}
`;
export default getStyles;

Some files were not shown because too many files have changed in this diff Show More