Compare commits

..

214 Commits

Author SHA1 Message Date
omkarht
f2982cbcc3 Merge branch 'develop' into fix/sequence-diagram-autonumber-arrow-positioning 2025-11-11 12:35:06 +05:30
omkarht
0d1f6af383 fix: adjust line start position for bidirectional arrows
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-11-11 12:29:10 +05:30
Shubham P
6b9f26dac8 Merge pull request #7080 from mermaid-js/7079-c4context-componentqueue-ext-lexical-error
7079: add missing support for ComponentQueue_Ext in C4Context diagrams
2025-11-11 04:07:06 +00:00
Shubham P
ea590cdafe Merge pull request #7075 from mermaid-js/6889-fix-escaped-p-tags-in-sandbox-mode
6889: Fix escaped <p> tags in labels when securityLevel is set to "sandbox"
2025-11-11 04:05:37 +00:00
Shubham P
f3769c70bc Merge branch 'develop' into 7079-c4context-componentqueue-ext-lexical-error 2025-11-11 09:24:14 +05:30
Shubham P
4cf4d15197 Merge branch 'develop' into 6889-fix-escaped-p-tags-in-sandbox-mode 2025-11-11 09:23:23 +05:30
omkarht
e7c78dec87 fix : autonumber positioning for all types of arrows and central connections 2025-11-10 16:14:23 +05:30
Shubham P
c02cf92656 Merge pull request #7149 from mermaid-js/renovate/patch-dompurify
fix(deps): update dependency dompurify to ^3.3.0
2025-11-10 10:15:31 +00:00
Shubham P
3a1266892d Merge pull request #7148 from mermaid-js/renovate/patch-all-patch
fix(deps): update all patch dependencies (patch)
2025-11-10 10:15:16 +00:00
renovate[bot]
67e81de557 fix(deps): update dependency dompurify to ^3.3.0 2025-11-10 02:54:45 +00:00
renovate[bot]
847b3aa24e fix(deps): update all patch dependencies 2025-11-10 02:54:19 +00:00
Sidharth Vinod
85a13da40f Merge pull request #7138 from mermaid-js/update-timings
Update E2E Timings
2025-11-07 21:42:11 +09:00
darshanr0107
9ec0e8f932 Merge branch 'develop' of https://github.com/mermaid-js/mermaid into 6889-fix-escaped-p-tags-in-sandbox-mode 2025-11-07 11:58:38 +05:30
darshanr0107
9585ee7533 chore:add e2e test
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-11-07 11:46:41 +05:30
github-actions[bot]
1269486124 chore: update E2E timings 2025-11-07 04:15:01 +00:00
Shubham P
f45ea0c60e Merge pull request #7096 from mermaid-js/renovate/npm-vite-vulnerability
chore(deps): update dependency vite to v7.1.11 [security]
2025-11-06 14:52:25 +00:00
renovate[bot]
d20955a56a chore(deps): update dependency vite to v7.1.11 [security] 2025-11-06 12:46:25 +00:00
Shubham P
fb66b3fbe3 Merge pull request #7049 from mermaid-js/renovate/major-eslint
chore(deps): update eslint (major)
2025-11-06 12:31:47 +00:00
Shubham P
82ea5d63bb Merge pull request #7017 from mermaid-js/renovate/peter-evans-create-pull-request-digest
chore(deps): update peter-evans/create-pull-request digest to 0edc001
2025-11-06 12:30:09 +00:00
renovate[bot]
881e74087a chore(deps): update eslint 2025-11-06 12:06:45 +00:00
renovate[bot]
09920c0497 chore(deps): update peter-evans/create-pull-request digest to 0edc001 2025-11-06 12:05:55 +00:00
Shubham P
8065d65cd7 Merge pull request #6973 from mermaid-js/renovate/patch-dompurify
fix(deps): update dependency dompurify to ^3.2.7
2025-11-06 11:52:40 +00:00
renovate[bot]
09b841f781 fix(deps): update dependency dompurify to ^3.2.7 2025-11-06 10:46:44 +00:00
Shubham P
d0f9dc0c9b Merge pull request #7018 from mermaid-js/renovate/patch-all-patch
fix(deps): update all patch dependencies (patch)
2025-11-06 10:28:10 +00:00
renovate[bot]
15e2824d53 fix(deps): update all patch dependencies 2025-11-06 10:04:11 +00:00
Shubham P
7eb582e860 Merge pull request #7135 from mermaid-js/fix/er-numeric-entity-test-conflict
refactor: update test description for standalone numeric entities in ER diagram
2025-11-06 09:51:04 +00:00
omkarht
6ca928f31f refactor: update test description for standalone numeric entities in ER diagram 2025-11-06 15:05:58 +05:30
darshanr0107
983120d945 fix: add test case for C4Context diagram with ComponentQueue_Ext
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-11-05 17:18:34 +05:30
Sidharth Vinod
dfd59470dc Merge pull request #7129 from mermaid-js/sidv/injectVersion
feat: Optimize bundling to remove shipping package.json inside mermaid's JS bundle.
2025-11-04 18:42:32 +00:00
Sidharth Vinod
4aac6fa448 Merge pull request #7128 from CNOCTAVE/develop
add doc to use marmaid.js in GNU Octave
2025-11-04 17:42:28 +00:00
CNOCTAVE
5f96f80efb Merge branch 'develop' of https://github.com/CNOCTAVE/mermaid into develop 2025-11-05 01:16:47 +08:00
CNOCTAVE
545801e144 Update integrations-community.md 2025-11-05 01:16:17 +08:00
CNOCTAVE
0bd74759cc Merge branch 'develop' into develop 2025-11-05 01:13:00 +08:00
CNOCTAVE
e4cf266c1d remove changeset
remove changeset
2025-11-05 01:12:15 +08:00
CNOCTAVE
c0e1662e50 Update packages/mermaid/src/docs/ecosystem/integrations-community.md
Co-authored-by: Sidharth Vinod <github@sidharth.dev>
2025-11-05 01:08:04 +08:00
Sidharth Vinod
6546aed482 chore: forbid use of viewbox in code 2025-11-05 00:07:30 +07:00
Sidharth Vinod
b76ccae065 feat: Optimize bundling to remove shipping package.json inside mermaid's JS bundle.
Move all build time injected variables to `injected.` namespace to avoid conflicts.
2025-11-04 23:49:54 +07:00
Sidharth Vinod
287a9a3fcb chore: Add missing clean scripts
Co-authored-by: Alois Klink <alois@aloisklink.com>
2025-11-04 21:21:58 +07:00
Sidharth Vinod
7f5160fa4d chore: Remove NPM_TOKEN from release workflow 2025-11-04 21:12:10 +07:00
autofix-ci[bot]
7b0763f262 [autofix.ci] apply automated fixes 2025-11-04 12:43:03 +00:00
CNOCTAVE
38c289818c feat: add doc to use marmaid.js in GNU Octave
feat: add doc to use marmaid.js in GNU Octave. Resolve #7073
2025-11-04 20:34:13 +08:00
CNOCTAVE
57530076aa add doc to use marmaid.js in GNU Octave
add doc to use marmaid.js in GNU Octave. Resolve #7073
2025-11-04 20:29:53 +08:00
CNOCTAVE
f2d7877c7a Merge branch 'develop' of https://github.com/CNOCTAVE/mermaid into develop 2025-11-04 20:20:28 +08:00
Sidharth Vinod
62d2c6505e Merge pull request #7109 from arnaudrenaud/add-speccharts
docs: Add speccharts to `integrations-community.md`
2025-11-04 11:57:01 +00:00
autofix-ci[bot]
974236bbb8 [autofix.ci] apply automated fixes 2025-11-04 11:48:23 +00:00
Sidharth Vinod
cf0d1248a4 chore: Add speccharts to cspell 2025-11-04 18:42:42 +07:00
Alois Klink
ebefbd87a8 Merge pull request #7127 from mermaid-js/sidharthv96-patch-2
Refactor GitHub Actions workflow for lockfile validation
2025-11-04 07:43:17 +00:00
Sidharth Vinod
1e7b71a085 Refactor GitHub Actions workflow for lockfile validation
Removed Node.js setup step and pnpm action version.

Co-authored-by: Alois Klink <alois@mermaidchart.com>
2025-11-03 23:30:27 -08:00
Sidharth Vinod
f28f3c25aa Merge pull request #7116 from mermaid-js/sidv/lockfileValidation
fix: Lockfile validation
2025-10-30 02:29:50 +09:00
Sidharth Vinod
58137aa631 feat: Allow validation workflow to run on forks 2025-10-30 01:56:18 +09:00
Sidharth Vinod
e7719f14c5 fix: Prevent duplicate comments by validation workflow 2025-10-30 01:55:58 +09:00
Sidharth Vinod
35d9cead8a chore: Cleanup lockfile 2025-10-30 01:22:17 +09:00
Ashish Jain
13baf51b35 Merge 11.12.1 back to develop 2025-10-28 11:23:19 +01:00
Justin Greywolf
9af985ba9b Merge pull request #5814 from kairi003/feature/4706_allow_notes_in_namespace
feat: allow to put notes in namespaces on classDiagram
2025-10-27 19:21:00 +00:00
Arnaud Renaud
c7f8a11ded Add speccharts to integrations-community.md 2025-10-27 14:16:35 +01:00
Sidharth Vinod
762b44cf33 Merge pull request #7108 from mermaid-js/changeset-release/master
Version Packages
2025-10-27 18:35:34 +05:30
github-actions[bot]
02c0091106 Version Packages 2025-10-27 12:08:22 +00:00
Sidharth Vinod
16359adc33 Merge pull request #7107 from mermaid-js/patch/dagre-d3-es-7.0.13
fix: update dagre-d3-es to version 7.0.13
2025-10-27 17:35:36 +05:30
Shubham P
061632c580 Update .changeset/slick-wasps-bathe.md
Co-authored-by: Alois Klink <alois@mermaidchart.com>
2025-10-27 16:20:24 +05:30
shubhamparikh2704
cbf89462ac fix: update dagre-d3-es to version 7.0.13 2025-10-27 15:06:24 +05:30
kairi003
700aa100f2 fix: style broken caused by a mistake in merge 3f46c94a 2025-10-26 04:18:19 +09:00
kairi003
49103ea654 fix: update ClassDB and ClassTypes for improved type safety and consistency 2025-10-26 03:01:00 +09:00
kairi003
3f46c94ab2 Merge branch 'develop' into tmp/feature/4706_allow_notes_in_namespace 2025-10-26 02:39:38 +09:00
Knut Sveidqvist
fed8a523a4 Merge pull request #7076 from mermaid-js/6919-fix-incorrect-viewBox-casing
6919: correct viewBox casing in Radar & Packet
2025-10-21 12:20:04 +00:00
Knut Sveidqvist
33b4946e21 Merge branch 'develop' into 6919-fix-incorrect-viewBox-casing 2025-10-21 10:33:21 +02:00
Justin Greywolf
3d768f3adf Merge pull request #6975 from ilovelinux/fix/6974-ilovelinux-fix-classdiagram-example
Fix classDiagram example
2025-10-17 02:56:34 +00:00
darshanr0107
76e17ffd20 fix: add validation to ensure correct casing of 'viewBox' in all rendering tests
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-15 18:56:49 +05:30
darshanr0107
835de0012d fix:ComponentQueue_Ext throws lexical error
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-14 19:00:17 +05:30
darshanr0107
60f633101c chore: added changeset
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-13 19:14:22 +05:30
Shubham P
18f51eb14e Merge pull request #6843 from saurabhg772244/saurabh/fix-edge-animation-for-hand-dranw-shapes
Fixed edge animation for hand drawn shapes
2025-10-13 13:14:24 +00:00
Shubham P
2bb57bf7d2 Merge pull request #6989 from mermaid-js/subgraph-td-direction
6338: allow direction TD inside subgraphs
2025-10-13 13:13:46 +00:00
Shubham P
a6276daffd Merge pull request #7055 from mermaid-js/sequence-diagram-participant-name-parsing
6853:  prevent browser freeze caused by invalid participant name in sequenceDiagram
2025-10-13 13:12:08 +00:00
darshanr0107
7def6eecbf fix: correct viewBox casing in radar and packet diagram
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-13 18:15:38 +05:30
darshanr0107
96a766dcdb chore: added changeset
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-13 13:42:41 +05:30
darshanr0107
39d7ebd32e fix: escaped p tags in sandbox mode
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-13 13:16:58 +05:30
CNOCTAVE
34f40f0794 add doc to use marmaid.js in GNU Octave 2025-10-13 15:11:44 +08:00
CNOCTAVE
32ac2c689d add doc to use marmaid.js in GNU Octave 2025-10-13 15:02:46 +08:00
CNOCTAVE
dbcadc1d0b add doc to use marmaid.js in GNU Octave 2025-10-13 13:56:04 +08:00
Antonio Spadaro
ac411a7d7e Fix class diagram example 2025-10-11 22:56:37 +02:00
Justin Greywolf
d80a638e55 Merge pull request #6023 from yari-dewalt/fix_lollipop_stroke
Fix: Delete 'stroke: black' from lollipop marker so it matches themes and edge paths
2025-10-11 20:43:08 +00:00
Justin Greywolf
7a869c08a2 Merge pull request #6026 from yari-dewalt/bug/5669_class-diagram-fix-namespace-themes
Fix: Class diagram namespaces black lines, not responding to theme variables
2025-10-11 20:42:53 +00:00
Justin Greywolf
44e8cbb1de Merge branch 'develop' into bug/5669_class-diagram-fix-namespace-themes 2025-10-11 13:27:47 -07:00
Justin Greywolf
efe38b8425 Merge branch 'develop' into fix_lollipop_stroke 2025-10-11 13:26:59 -07:00
darshanr0107
6fecb985e8 fix: failing argos
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-09 11:50:44 +05:30
darshanr0107
69b338d8af fix: formatting issues
Co-authored-by: omkarht <omkar@mermaidchart.com>
2025-10-09 11:37:05 +05:30
darshanr0107
fa15ce8502 chore: added changeset
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-08 13:23:28 +05:30
darshanr0107
6d0650918f fix: handle participant names with spaces correctly in sequenceDiagram
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-08 13:09:30 +05:30
Shubham P
c728d864c8 Merge pull request #7054 from mermaid-js/fix/update-argos-ci-version
fix: update @argos-ci/cypress to version 6.1.3
2025-10-07 08:34:58 +00:00
shubhamparikh2704
99f17bea3a fix: update @argos-ci/cypress to version 6.1.3 2025-10-07 13:39:28 +05:30
Sidharth Vinod
ad82448084 Merge pull request #7053 from mermaid-js/changeset-release/master
Version Packages
2025-10-07 13:23:31 +05:30
github-actions[bot]
9498619d3c Version Packages 2025-10-07 07:36:05 +00:00
Sidharth Vinod
7a8557a1a2 Merge pull request #7036 from mermaid-js/knsv-patch-1
Update free plan diagram limit from 3 to 6
2025-10-07 13:03:39 +05:30
Sidharth Vinod
74863c94fb Merge pull request #7051 from mermaid-js/patch-parser-release
Pre Release
2025-10-07 12:34:22 +05:30
shubhamparikh2704
63df702146 chore: added changeset file 2025-10-07 10:47:16 +05:30
autofix-ci[bot]
421f8d4633 [autofix.ci] apply automated fixes 2025-10-03 07:41:08 +00:00
Knut Sveidqvist
bf6e1a594c Update free plan diagram limit from 3 to 6 2025-10-03 09:35:21 +02:00
Ashish Jain
c1c14e401a Merge pull request #7019 from mermaid-js/tmp-mindmap-elk
mindmap breaking issue in ELK layout
2025-09-30 09:02:40 +00:00
darshanr0107
8b3057f27c fix: guard nodeDb[node.id] against undefined
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-30 12:27:53 +05:30
Shubham P
717d3b3bb2 Merge pull request #6984 from mermaid-js/fix/er-diagram-syntax-error-special-chars
fix(er-diagram): handle syntax errors for special characters in node names
2025-09-29 08:37:03 +00:00
Shubham P
2f8d9ba958 Merge pull request #6789 from mermaid-js/6638-sequence-diagram-additional-messages
6638:sequence diagram additional messages
2025-09-29 08:08:33 +00:00
darshanr0107
ace0367afd chore: add changeset
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-29 13:37:10 +05:30
Knut Sveidqvist
b983626587 Fix for reference issue affecting mindmaps 2025-09-26 15:24:20 +02:00
Shubham P
7effdc147b Merge pull request #6997 from mermaid-js/ci/enable-codeql-for-github-actions
ci(codeql): enable CodeQL for GitHub Actions
2025-09-25 08:47:48 +00:00
Alois Klink
6e67515f41 ci(codeql): enable CodeQL for GitHub Actions
Support for scanning GitHub Actions was added in 2024-12-17, see
https://github.blog/changelog/2024-12-17-find-and-fix-actions-workflows-vulnerabilities-with-codeql-public-preview/
2025-09-25 17:17:12 +09:00
darshanr0107
1a9d45abf0 fix: allow direction TD inside subgraphs
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-24 12:22:31 +05:30
omkarht
09b74f1c29 chore: added changeset
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-23 13:39:45 +05:30
omkarht
880da21908 test: add tests for handling special characters and numeric entity names
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-23 13:29:19 +05:30
omkarht
38191243be Merge branch 'develop' into fix/er-diagram-syntax-error-special-chars 2025-09-23 12:41:42 +05:30
omkarht
b75dcb8a82 Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-09-23 12:40:39 +05:30
omkarht
4c1e170f4a fix(er-diagram): handle syntax errors for special characters in node names 2025-09-23 12:39:29 +05:30
Shubham P
d5c4eff251 Merge pull request #6972 from mermaid-js/renovate/patch-all-patch
fix(deps): update all patch dependencies (patch)
2025-09-22 13:49:30 +00:00
renovate[bot]
5324fd8dfd fix(deps): update all patch dependencies 2025-09-22 13:35:45 +00:00
omkarht
bd25b88a01 Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-09-22 13:36:01 +05:30
Sidharth Vinod
0116b272b4 Merge pull request #6961 from mermaid-js/changeset-release/master
Version Packages
2025-09-18 10:50:42 +05:30
github-actions[bot]
634f3367da Version Packages 2025-09-17 17:48:06 +00:00
Sidharth Vinod
37e3a6951b Merge pull request #6956 from mermaid-js/develop
Pre Release
2025-09-17 23:15:32 +05:30
Sidharth Vinod
0de0b063e4 Merge pull request #6958 from dijitali/fix/arch-icon-docs
fix(docs) correct phrasing for architecture icon installation
2025-09-17 23:06:48 +05:30
Shubham P
619515e5a9 Merge pull request #6925 from mermaid-js/renovate/patch-all-patch
fix(deps): update all patch dependencies (patch)
2025-09-17 14:16:47 +00:00
shubhamparikh2704
59c8b07509 Merge branch 'develop' of https://github.com/mermaid-js/mermaid into renovate/patch-all-patch 2025-09-17 19:34:56 +05:30
Sidharth Vinod
9e72bbf62d Merge pull request #6955 from mermaid-js/sidv/updateArgos
chore: Update argos to 6.1.0
2025-09-17 18:48:40 +05:30
Sidharth Vinod
2a2c46f1e2 chore: Update argos to 6.1.1 2025-09-17 18:14:03 +05:30
Shubham P
f25df353d4 Merge pull request #6959 from mermaid-js/remove-changeset
chore: remove duplicate changeset file
2025-09-17 10:50:09 +00:00
shubhamparikh2704
398345a8bc chore: remove duplicate changeset file 2025-09-17 16:07:45 +05:30
autofix-ci[bot]
7fd2d94ef7 [autofix.ci] apply automated fixes 2025-09-17 08:47:15 +00:00
Ieuan Jenkins
bcc1472b9d fix(docs) correct phrasing for architecture icon installation
docs gave the incorrect impression that iconify.design icons came preinstalled
2025-09-17 09:21:42 +01:00
shubhamparikh2704
ddc1cfe6c8 Revert "fix: downgrade @argos-ci/cypress to version 5.0.2"
This reverts commit 18e9c1174d.
2025-09-17 13:07:43 +05:30
omkarht
d3de3ecbbb Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-09-17 12:41:51 +05:30
shubhamparikh2704
18e9c1174d fix: downgrade @argos-ci/cypress to version 5.0.2 2025-09-17 12:14:29 +05:30
Sidharth Vinod
789018abf6 chore: Update argos to 6.1.0 2025-09-17 11:38:57 +05:30
Shubham P
16569b295b Merge pull request #6942 from mermaid-js/renovate/peter-evans-create-pull-request-digest
chore(deps): update peter-evans/create-pull-request digest to 915d841
2025-09-16 17:28:34 +00:00
renovate[bot]
11a35c11ee chore(deps): update peter-evans/create-pull-request digest to 915d841 2025-09-16 16:02:14 +00:00
Shubham P
216be22801 Merge pull request #6945 from mermaid-js/fix/gantt-crash-obsidian-browser
6920: Fix Gantt chart crashes in Obsidian and browser
2025-09-16 15:49:49 +00:00
Ashish Jain
e87f77a865 Merge pull request #6950 from mermaid-js/patch/mindmap-fix
Pre Release
2025-09-16 12:48:55 +02:00
shubhamparikh2704
a9579083bf chore: add changeset for fixing mindmap rendering and applying tidytree layout 2025-09-16 13:33:31 +05:30
Knut Sveidqvist
6fd78d0856 Merge pull request #6944 from mermaid-js/docs/fix-mindmap-rendering
6932:Fix mindmap rendering in docs and apply tidytree layout
2025-09-16 13:27:23 +05:30
Sidharth Vinod
531f5e9380 Merge pull request #6948 from mermaid-js/add-newest-blog-posts
DOCS: add newest blog posts
2025-09-16 11:45:06 +05:30
Steph
ad4c227477 add newest blog posts 2025-09-15 13:24:39 -07:00
omkarht
3964ce0a0f Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-09-15 18:15:59 +05:30
shubhamparikh2704
a44e3e992c refactor: remove unused dependencies from pnpm-lock.yaml 2025-09-15 14:37:50 +05:30
shubhamparikh2704
ca5b370ffb Merge branch 'develop' of https://github.com/mermaid-js/mermaid into renovate/patch-all-patch 2025-09-15 14:32:02 +05:30
omkarht
4dbabba8e8 Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-09-15 12:50:11 +05:30
darshanr0107
d318f1a13c chore: add changeset
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-15 12:42:25 +05:30
darshanr0107
525a7de8ae fix:gant chart crashing in browser
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-15 12:42:24 +05:30
Saurabh Gore
bbb93b263d Merge branch 'develop' into saurabh/fix-edge-animation-for-hand-dranw-shapes 2025-09-13 11:37:21 +05:30
Sidharth Vinod
450754221e Merge pull request #6930 from mermaid-js/rajat-ht/chore-editor-selection-update
Chore: Simplify editor selection to single version
2025-09-11 19:57:08 +05:30
rajat-ht
7a4f5b62c9 chore: update variable name 2025-09-11 19:54:14 +05:30
omkarht
e3ef5e4208 fix: fixed central connection for bidirectional dotted arrow
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-11 13:03:06 +05:30
omkarht
daeb85bac2 Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-09-11 12:40:55 +05:30
saurabhg772244
4240340a18 Merge branch 'develop' of github.com:mermaid-js/mermaid into saurabh/fix-edge-animation-for-hand-dranw-shapes 2025-09-11 11:36:26 +05:30
Shubham P
cf08ba0ef8 Merge branch 'develop' into renovate/patch-all-patch 2025-09-10 21:03:45 +05:30
rajat-ht
4829dfa8c5 Chore: Simplify editor selection to single version 2025-09-09 22:16:52 +05:30
autofix-ci[bot]
e7811886c3 [autofix.ci] apply automated fixes 2025-09-08 01:00:25 +00:00
renovate[bot]
32eda8565c fix(deps): update all patch dependencies 2025-09-08 00:54:41 +00:00
omkarht
ca10a259fa Merge branch 'develop' into saurabh/fix-edge-animation-for-hand-dranw-shapes 2025-09-05 16:28:39 +05:30
Saurabh Gore
0ed9c65572 Merge branch 'develop' into saurabh/fix-edge-animation-for-hand-dranw-shapes 2025-09-05 12:56:27 +05:30
saurabhg772244
56cc12690f Added option to skip screenshot for cypress tests 2025-09-05 12:47:07 +05:30
omkarht
2cdaf03ada Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-09-05 12:12:01 +05:30
Sidharth Vinod
9c85521e16 Merge pull request #6914 from mermaid-js/changeset-release/master
Version Packages
2025-09-04 20:36:52 +05:30
github-actions[bot]
8a565bce92 Version Packages 2025-09-04 14:12:57 +00:00
Sidharth Vinod
baf510b935 Merge pull request #6912 from mermaid-js/develop
Pre Release
2025-09-04 19:39:17 +05:30
omkarht
f6fa0260e7 Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-09-04 12:56:49 +05:30
omkarht
29aad6d23c Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-09-04 12:12:03 +05:30
omkarht
82ef7b5fdb docs: add version placeholders for new features 2025-09-02 19:02:02 +05:30
omkarht
11cd3f1262 feat: add central connection rendering and parsing tests 2025-09-02 18:52:18 +05:30
omkarht
ac4aa94e78 Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-09-02 15:13:07 +05:30
omkarht
c40faac80d Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-08-29 13:26:48 +05:30
omkarht
c530baed3f Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-08-28 13:07:57 +05:30
omkarht
045699de10 Merge branch 'develop' of https://github.com/mermaid-js/mermaid into 6638-sequence-diagram-additional-messages 2025-08-25 15:14:50 +05:30
omkarht
1988d24227 fix: fixed reverse arrows placing for autonumber
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-08-22 16:46:49 +05:30
omkarht
39f90debe7 Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-08-22 13:03:01 +05:30
omkarht
73e9849f99 chore: added changeset
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-08-21 16:12:25 +05:30
omkarht
5a05540a5f Merge branch 'develop' of https://github.com/mermaid-js/mermaid into 6638-sequence-diagram-additional-messages 2025-08-21 16:09:18 +05:30
omkarht
2b58df9665 fix: refactored documentation
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-08-19 14:53:08 +05:30
saurabhg772244
e6fb4a84da code refactor 2025-08-11 16:32:03 +05:30
saurabhg772244
32723b2de1 Added change set 2025-08-11 15:59:07 +05:30
saurabhg772244
18703782ee Fixed edge animation for hand drawn shapes 2025-08-11 15:52:49 +05:30
omkarht
0b42bdba07 Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-08-11 15:28:48 +05:30
omkarht
74c96db3e2 docs: document new syntax for half-arrow message and central connection
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-08-07 12:47:31 +05:30
omkarht
bd47c57eaf chore: refactored code
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-08-06 18:56:58 +05:30
omkarht
3e5d2db514 Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-08-06 18:56:18 +05:30
omkarht
40990bb096 Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-07-29 18:17:34 +05:30
omkarht
7ca0665764 fix: fixed failing test case
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-07-28 19:13:51 +05:30
omkarht
81a6a361ab Merge branch 'develop' into 6638-sequence-diagram-additional-messages 2025-07-28 16:51:38 +05:30
omkarht
62faacdeeb fix: fixed failing test cases
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-07-28 16:01:43 +05:30
omkarht
0e40d8e8a8 fix: fixed failing test cases
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-07-28 15:55:07 +05:30
omkarht
e8d6daf4f6 add support for central connection circle after arrow in lifeline direction
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-07-28 15:37:33 +05:30
omkarht
cb4ed605b2 chore: added rendering test cases for arrow head type
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-07-23 16:59:04 +05:30
omkarht
ba9db26bfa Lexing : Added Support for new arrow types through lexing
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-07-22 19:25:27 +05:30
omkarht
252b1837f7 added arrowhead types for dotted line type
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-07-22 19:20:06 +05:30
omkarht
6b9c15d7f0 added reverse arrow head types
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-07-22 16:30:21 +05:30
omkarht
fda640c90c fix: adjusted arrowhead design
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-07-21 19:03:29 +05:30
omkarht
584a789183 6638: add support for additional message types for sequence diagram
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-07-21 13:33:52 +05:30
autofix-ci[bot]
47297f7c26 [autofix.ci] apply automated fixes 2025-02-26 17:49:51 +00:00
Yari DeWalt
967aa0629e Merge branch 'develop' into bug/5669_class-diagram-fix-namespace-themes 2025-02-26 09:45:14 -08:00
Yari DeWalt
04b20a79b9 Merge branch 'develop' into fix_lollipop_stroke 2025-02-26 09:20:16 -08:00
kairi
d60b09cafc Merge branch 'develop' into feature/4706_allow_notes_in_namespace 2024-12-01 09:20:39 +09:00
kairi003
875827f59b Merge branch 'develop' into feature/4706_allow_notes_in_namespace 2024-11-21 07:16:47 +09:00
kairi003
c4e08261b5 Merge branch 'develop' into feature/4706_allow_notes_in_namespace 2024-11-10 23:56:48 +09:00
kairi003
70f679d2fa add: e2e test for classDiagram-v3 2024-11-10 20:27:35 +09:00
kairi003
25c43fa439 add: horizontal rules to demos/classchart.html 2024-11-10 02:34:31 +09:00
kairi003
ec1c6325d4 refactor: Add type annotations and optimize redundant set loop 2024-11-10 02:34:31 +09:00
kairi003
309ff6be38 fix: Reimplement notes in namespaces for classRenderer-v3 (#5880) 2024-11-10 02:32:20 +09:00
kairi003
02d368df05 chore: relax git version constraint in Dockerfile to allow patch updates 2024-11-10 01:58:29 +09:00
kairi003
4ee1fe2ca4 Merge branch 'master' into feature/4706_allow_notes_in_namespace 2024-11-10 01:52:46 +09:00
yari-dewalt
4ff2ae9f4e Add styles for clusters and remove hard-coded styling for namespace nodes 2024-11-06 09:00:21 -08:00
Yari DeWalt
7a729e8f16 Merge branch 'develop' into fix_lollipop_stroke 2024-11-04 10:21:00 -08:00
yari-dewalt
3c7fd95617 Remove black stroke from lollipops so it matches edge paths 2024-11-04 10:15:51 -08:00
kairi003
2dd29bee25 add changelogs 2024-09-08 02:13:33 +09:00
kairi003
259a508d8a add e2e test 2024-09-08 01:31:26 +09:00
kairi
1963064369 Merge branch 'develop' into feature/4706_allow_notes_in_namespace 2024-09-08 00:27:14 +09:00
kairi
a101ce803c Merge branch 'develop' into feature/4706_allow_notes_in_namespace 2024-09-04 14:14:19 +09:00
kairi003
fc0c7936d1 feat: Add support for adding notes to namespaces in class diagrams 2024-09-03 15:27:31 +09:00
kairi003
2d2add5b44 Change: use Map for notes 2024-09-03 15:22:59 +09:00
kairi003
58fd5ddbaf Add: demo for notes in namespace on classDialog 2024-09-03 15:22:41 +09:00
129 changed files with 8412 additions and 7087 deletions

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Prevent HTML tags from being escaped in sandbox label rendering

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Support edge animation in hand drawn look

View File

@@ -1,5 +0,0 @@
---
'mermaid': minor
---
feat: Add custom images and icons support for sequence diagram actors

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Resolved parsing error where direction TD was not recognized within subgraphs

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Correct viewBox casing and make SVGs responsive

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
fix: Render newlines as spaces in class diagrams

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
fix: Handle arrows correctly when auto number is enabled

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Improve participant parsing and prevent recursive loops on invalid syntax

View File

@@ -1,5 +0,0 @@
---
'mermaid': minor
---
Add IDs in architecture diagrams

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
fix: Ensure edge label color is applied when using classDef with edge IDs

View File

@@ -1,5 +0,0 @@
---
'mermaid': minor
---
feat: Added support for new participant types (`actor`, `boundary`, `control`, `entity`, `database`, `collections`, `queue`) in `sequenceDiagram`.

View File

@@ -1,7 +0,0 @@
---
'mermaid': minor
'@mermaid-js/layout-tidy-tree': minor
'@mermaid-js/layout-elk': minor
---
feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes

View File

@@ -0,0 +1,5 @@
---
'mermaid': minor
---
feat: Add half-arrowheads (solid & stick) and central connection support

View File

@@ -1,5 +0,0 @@
---
'mermaid': minor
---
feat: Add IDs in architecture diagrams

View File

@@ -1,9 +0,0 @@
---
'mermaid': patch
---
chore: revert marked dependency from ^15.0.7 to ^16.0.0
- Reverted marked package version to ^16.0.0 for better compatibility
- This is a dependency update that maintains API compatibility
- All tests pass with the updated version

View File

@@ -0,0 +1,5 @@
---
'mermaid': minor
---
feat: allow to put notes in namespaces on classDiagram

View File

@@ -0,0 +1,5 @@
---
'@mermaid': patch
---
fix: Mindmap breaking in ELK layout

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix(er-diagram): prevent syntax error when using 'u', numbers, and decimals in node names

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Support ComponentQueue_Ext to prevent parsing error

View File

@@ -1,3 +1,5 @@
!viewbox
# It should be viewBox
# This file contains coding related terms # This file contains coding related terms
ALPHANUM ALPHANUM
antiscript antiscript

View File

@@ -64,6 +64,7 @@ rscratch
shiki shiki
Slidev Slidev
sparkline sparkline
speccharts
sphinxcontrib sphinxcontrib
ssim ssim
stylis stylis

View File

@@ -71,6 +71,9 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
const external: string[] = ['require', 'fs', 'path']; const external: string[] = ['require', 'fs', 'path'];
const outFileName = getFileName(name, options); const outFileName = getFileName(name, options);
const { dependencies, version } = JSON.parse(
readFileSync(resolve(__dirname, `../packages/${packageName}/package.json`), 'utf-8')
);
const output: BuildOptions = buildOptions({ const output: BuildOptions = buildOptions({
...rest, ...rest,
absWorkingDir: resolve(__dirname, `../packages/${packageName}`), absWorkingDir: resolve(__dirname, `../packages/${packageName}`),
@@ -82,15 +85,13 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
chunkNames: `chunks/${outFileName}/[name]-[hash]`, chunkNames: `chunks/${outFileName}/[name]-[hash]`,
define: { define: {
// This needs to be stringified for esbuild // This needs to be stringified for esbuild
includeLargeFeatures: `${includeLargeFeatures}`, 'injected.includeLargeFeatures': `${includeLargeFeatures}`,
'injected.version': `'${version}'`,
'import.meta.vitest': 'undefined', 'import.meta.vitest': 'undefined',
}, },
}); });
if (core) { if (core) {
const { dependencies } = JSON.parse(
readFileSync(resolve(__dirname, `../packages/${packageName}/package.json`), 'utf-8')
);
// Core build is used to generate file without bundled dependencies. // Core build is used to generate file without bundled dependencies.
// This is used by downstream projects to bundle dependencies themselves. // This is used by downstream projects to bundle dependencies themselves.
// Ignore dependencies and any dependencies of dependencies // Ignore dependencies and any dependencies of dependencies

View File

@@ -26,8 +26,8 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
language: ['javascript'] language: ['javascript', 'actions']
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # CodeQL supports [ 'actions', 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps: steps:
@@ -36,7 +36,7 @@ jobs:
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 uses: github/codeql-action/init@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21
with: with:
config-file: ./.github/codeql/codeql-config.yml config-file: ./.github/codeql/codeql-config.yml
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
@@ -48,7 +48,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 uses: github/codeql-action/autobuild@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -62,4 +62,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 uses: github/codeql-action/analyze@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21

View File

@@ -53,7 +53,7 @@ jobs:
args: -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH" args: -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH"
- name: Cypress run - name: Cypress run
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
id: cypress id: cypress
with: with:
start: pnpm run dev start: pnpm run dev

View File

@@ -27,12 +27,12 @@ jobs:
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
- name: Install dependencies - name: Install dependencies
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
with: with:
runTests: false runTests: false
- name: Cypress run - name: Cypress run
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
id: cypress id: cypress
with: with:
install: false install: false
@@ -58,7 +58,7 @@ jobs:
echo "EOF" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT
- name: Commit and create pull request - name: Commit and create pull request
uses: peter-evans/create-pull-request@18e469570b1cf0dfc11d60ec121099f8ff3e617a uses: peter-evans/create-pull-request@0edc001d28a2959cd7a6b505629f1d82f0a6e67d
with: with:
add-paths: | add-paths: |
cypress/timings.json cypress/timings.json

View File

@@ -45,7 +45,7 @@ jobs:
node-version-file: '.node-version' node-version-file: '.node-version'
- name: Cache snapshots - name: Cache snapshots
id: cache-snapshot id: cache-snapshot
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with: with:
path: ./cypress/snapshots path: ./cypress/snapshots
key: ${{ runner.os }}-snapshots-${{ env.targetHash }} key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
@@ -59,7 +59,7 @@ jobs:
- name: Install dependencies - name: Install dependencies
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
with: with:
# just perform install # just perform install
runTests: false runTests: false
@@ -95,13 +95,13 @@ jobs:
# These cached snapshots are downloaded, providing the reference snapshots. # These cached snapshots are downloaded, providing the reference snapshots.
- name: Cache snapshots - name: Cache snapshots
id: cache-snapshot id: cache-snapshot
uses: actions/cache/restore@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with: with:
path: ./cypress/snapshots path: ./cypress/snapshots
key: ${{ runner.os }}-snapshots-${{ env.targetHash }} key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
- name: Install dependencies - name: Install dependencies
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
with: with:
runTests: false runTests: false
@@ -117,7 +117,7 @@ jobs:
# Install NPM dependencies, cache them correctly # Install NPM dependencies, cache them correctly
# and run all Cypress tests # and run all Cypress tests
- name: Cypress run - name: Cypress run
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 uses: cypress-io/github-action@108b8684ae52e735ff7891524cbffbcd4be5b19f # v6.7.16
id: cypress id: cypress
with: with:
install: false install: false

View File

@@ -32,7 +32,7 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Restore lychee cache - name: Restore lychee cache
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with: with:
path: .lycheecache path: .lycheecache
key: cache-lychee-${{ github.sha }} key: cache-lychee-${{ github.sha }}

View File

@@ -36,11 +36,10 @@ jobs:
- name: Create Release Pull Request or Publish to npm - name: Create Release Pull Request or Publish to npm
id: changesets id: changesets
uses: changesets/action@c8bada60c408975afd1a20b3db81d6eee6789308 # v1.4.9 uses: changesets/action@06245a4e0a36c064a573d4150030f5ec548e4fcc # v1.4.10
with: with:
version: pnpm changeset:version version: pnpm changeset:version
publish: pnpm changeset:publish publish: pnpm changeset:publish
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true NPM_CONFIG_PROVENANCE: true

View File

@@ -20,18 +20,18 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Run analysis - name: Run analysis
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with: with:
results_file: results.sarif results_file: results.sarif
results_format: sarif results_format: sarif
publish_results: true publish_results: true
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: SARIF file name: SARIF file
path: results.sarif path: results.sarif
retention-days: 5 retention-days: 5
- name: Upload to code-scanning - name: Upload to code-scanning
uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 uses: github/codeql-action/upload-sarif@5378192d256ef1302a6980fffe5ca04426d43091 # v3.28.21
with: with:
sarif_file: results.sarif sarif_file: results.sarif

View File

@@ -19,7 +19,7 @@ jobs:
message: 'chore: update browsers list' message: 'chore: update browsers list'
push: false push: false
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
with: with:
branch: update-browserslist branch: update-browserslist
title: Update Browserslist title: Update Browserslist

View File

@@ -1,7 +1,7 @@
name: Validate pnpm-lock.yaml name: Validate pnpm-lock.yaml
on: on:
pull_request: pull_request_target:
paths: paths:
- 'pnpm-lock.yaml' - 'pnpm-lock.yaml'
- '**/package.json' - '**/package.json'
@@ -15,13 +15,8 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up Node.js repository: ${{ github.event.pull_request.head.repo.full_name }}
uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Validate pnpm-lock.yaml entries - name: Validate pnpm-lock.yaml entries
id: validate # give this step an ID so we can reference its outputs id: validate # give this step an ID so we can reference its outputs
@@ -55,16 +50,41 @@ jobs:
exit 1 exit 1
fi fi
- name: Find existing lockfile validation comment
if: always()
uses: peter-evans/find-comment@v3
id: find-comment
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]'
body-includes: 'Lockfile Validation Failed'
- name: Comment on PR if validation failed - name: Comment on PR if validation failed
if: failure() if: failure()
uses: peter-evans/create-or-update-comment@v4 uses: peter-evans/create-or-update-comment@v5
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.pull_request.number }} issue-number: ${{ github.event.pull_request.number }}
comment-id: ${{ steps.find-comment.outputs.comment-id }}
edit-mode: replace
body: | body: |
❌ **Lockfile Validation Failed**
The following issue(s) were detected: The following issue(s) were detected:
${{ steps.validate.outputs.errors }} ${{ steps.validate.outputs.errors }}
Please address these and push an update. Please address these and push an update.
_Posted automatically by GitHub Actions_ _Posted automatically by GitHub Actions_
- name: Delete comment if validation passed
if: success() && steps.find-comment.outputs.comment-id != ''
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
await github.rest.issues.deleteComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: ${{ steps.find-comment.outputs.comment-id }},
});

View File

@@ -78,6 +78,8 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
}, },
define: { define: {
'import.meta.vitest': 'undefined', 'import.meta.vitest': 'undefined',
'injected.includeLargeFeatures': 'true',
'injected.version': `'0.0.0'`,
}, },
resolve: { resolve: {
extensions: [], extensions: [],
@@ -94,10 +96,6 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
}), }),
...visualizerOptions(packageName, core), ...visualizerOptions(packageName, core),
], ],
define: {
// Needs to be string
includeLargeFeatures: 'true',
},
}; };
if (watch && config.build) { if (watch && config.build) {

View File

@@ -5,7 +5,7 @@ USER 0:0
RUN corepack enable \ RUN corepack enable \
&& corepack enable pnpm && corepack enable pnpm
RUN apk add --no-cache git~=2.43.4 \ RUN apk add --no-cache git~=2.43 \
&& git config --add --system safe.directory /mermaid && git config --add --system safe.directory /mermaid
ENV NODE_OPTIONS="--max_old_space_size=8192" ENV NODE_OPTIONS="--max_old_space_size=8192"

View File

@@ -6,6 +6,7 @@ interface CypressConfig {
listUrl?: boolean; listUrl?: boolean;
listId?: string; listId?: string;
name?: string; name?: string;
screenshot?: boolean;
} }
type CypressMermaidConfig = MermaidConfig & CypressConfig; type CypressMermaidConfig = MermaidConfig & CypressConfig;
@@ -90,20 +91,33 @@ export const renderGraph = (
export const openURLAndVerifyRendering = ( export const openURLAndVerifyRendering = (
url: string, url: string,
options: CypressMermaidConfig, { screenshot = true, ...options }: CypressMermaidConfig,
validation?: any validation?: any
): void => { ): void => {
const name: string = (options.name ?? cy.state('runnable').fullTitle()).replace(/\s+/g, '-'); const name: string = (options.name ?? cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
cy.visit(url); cy.visit(url);
cy.window().should('have.property', 'rendered', true); cy.window().should('have.property', 'rendered', true);
cy.get('svg').should('be.visible');
if (validation) { // Handle sandbox mode where SVG is inside an iframe
cy.get('svg').should(validation); if (options.securityLevel === 'sandbox') {
cy.get('iframe').should('be.visible');
if (validation) {
cy.get('iframe').should(validation);
}
} else {
cy.get('svg').should('be.visible');
// cspell:ignore viewbox
cy.get('svg').should('not.have.attr', 'viewbox');
if (validation) {
cy.get('svg').should(validation);
}
} }
verifyScreenshot(name); if (screenshot) {
verifyScreenshot(name);
}
}; };
export const verifyScreenshot = (name: string): void => { export const verifyScreenshot = (name: string): void => {

View File

@@ -114,4 +114,28 @@ describe('C4 diagram', () => {
{} {}
); );
}); });
it('C4.6 should render C4Context diagram with ComponentQueue_Ext', () => {
imgSnapshotTest(
`
C4Context
title System Context diagram with ComponentQueue_Ext
Enterprise_Boundary(b0, "BankBoundary0") {
Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")
System(SystemAA, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")
Enterprise_Boundary(b1, "BankBoundary") {
ComponentQueue_Ext(msgQueue, "Message Queue", "RabbitMQ", "External message queue system for processing banking transactions")
System_Ext(SystemC, "E-mail system", "The internal Microsoft Exchange e-mail system.")
}
}
BiRel(customerA, SystemAA, "Uses")
Rel(SystemAA, msgQueue, "Sends messages to")
Rel(SystemAA, SystemC, "Sends e-mails", "SMTP")
`,
{}
);
});
}); });

View File

@@ -562,6 +562,20 @@ class C13["With Città foreign language"]
` `
); );
}); });
it('should add notes in namespaces', function () {
imgSnapshotTest(
`
classDiagram
note "This is a outer note"
note for C1 "This is a outer note for C1"
namespace Namespace1 {
note "This is a inner note"
note for C1 "This is a inner note for C1"
class C1
}
`
);
});
it('should render a simple class diagram with no members', () => { it('should render a simple class diagram with no members', () => {
imgSnapshotTest( imgSnapshotTest(
` `

View File

@@ -709,6 +709,20 @@ class C13["With Città foreign language"]
` `
); );
}); });
it('should add notes in namespaces', function () {
imgSnapshotTest(
`
classDiagram
note "This is a outer note"
note for C1 "This is a outer note for C1"
namespace Namespace1 {
note "This is a inner note"
note for C1 "This is a inner note for C1"
class C1
}
`
);
});
it('should render a simple class diagram with no members', () => { it('should render a simple class diagram with no members', () => {
imgSnapshotTest( imgSnapshotTest(
` `

View File

@@ -369,4 +369,92 @@ ORDER ||--|{ LINE-ITEM : contains
); );
}); });
}); });
describe('Special characters and numbers syntax', () => {
it('should render ER diagram with numeric entity names', () => {
imgSnapshotTest(
`
erDiagram
1 ||--|| ORDER : places
ORDER ||--|{ 2 : contains
2 ||--o{ 3.5 : references
`,
{ logLevel: 1 }
);
});
it('should render ER diagram with "u" character in entity names and cardinality', () => {
imgSnapshotTest(
`
erDiagram
CUSTOMER ||--|| u : has
u ||--|| ORDER : places
PROJECT u--o{ TEAM_MEMBER : "parent"
`,
{ logLevel: 1 }
);
});
it('should render ER diagram with decimal numbers in relationships', () => {
imgSnapshotTest(
`
erDiagram
2.5 ||--|| 1.5 : has
CUSTOMER ||--o{ 3.14 : references
1.0 ||--|{ ORDER : contains
`,
{ logLevel: 1 }
);
});
it('should render ER diagram with numeric entity names and attributes', () => {
imgSnapshotTest(
`
erDiagram
1 {
string name
int value
}
1 ||--|| ORDER : places
ORDER {
float price
string description
}
`,
{ logLevel: 1 }
);
});
it('should render complex ER diagram with mixed special entity names', () => {
imgSnapshotTest(
`
erDiagram
CUSTOMER ||--o{ 1 : places
1 ||--|{ u : contains
1.5
u ||--|| 2.5 : processes
2.5 {
string id
float value
}
u {
varchar(50) name
int count
}
`,
{ logLevel: 1 }
);
});
it('should render ER diagram with standalone numeric entities', () => {
imgSnapshotTest(
`erDiagram
PRODUCT ||--o{ ORDER-ITEM : has
1.5
u
1
`,
{ logLevel: 1 }
);
});
});
}); });

View File

@@ -1029,4 +1029,19 @@ graph TD
} }
); );
}); });
it('FDH49: should add edge animation', () => {
renderGraph(
`
flowchart TD
A(["Start"]) L_A_B_0@--> B{"Decision"}
B --> C["Option A"] & D["Option B"]
style C stroke-width:4px,stroke-dasharray: 5
L_A_B_0@{ animation: slow }
L_B_D_0@{ animation: fast }`,
{ look: 'handDrawn', screenshot: false }
);
cy.get('path#L_A_B_0').should('have.class', 'edge-animation-slow');
cy.get('path#L_B_D_0').should('have.class', 'edge-animation-fast');
});
}); });

View File

@@ -79,6 +79,18 @@ describe('Flowchart v2', () => {
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
); );
}); });
it('6a: should render complex HTML in labels with sandbox security', () => {
imgSnapshotTest(
`flowchart TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ securityLevel: 'sandbox', flowchart: { htmlLabels: true } }
);
});
it('7: should render a flowchart when useMaxWidth is true (default)', () => { it('7: should render a flowchart when useMaxWidth is true (default)', () => {
renderGraph( renderGraph(
`flowchart TD `flowchart TD

View File

@@ -774,6 +774,21 @@ describe('Graph', () => {
expect(svg).to.not.have.attr('style'); expect(svg).to.not.have.attr('style');
}); });
}); });
it('40: should add edge animation', () => {
renderGraph(
`
flowchart TD
A(["Start"]) L_A_B_0@--> B{"Decision"}
B --> C["Option A"] & D["Option B"]
style C stroke-width:4px,stroke-dasharray: 5
L_A_B_0@{ animation: slow }
L_B_D_0@{ animation: fast }`,
{ screenshot: false }
);
// Verify animation classes are applied to both edges
cy.get('path#L_A_B_0').should('have.class', 'edge-animation-slow');
cy.get('path#L_B_D_0').should('have.class', 'edge-animation-fast');
});
it('58: handle styling with style expressions', () => { it('58: handle styling with style expressions', () => {
imgSnapshotTest( imgSnapshotTest(
` `
@@ -973,4 +988,19 @@ graph TD
} }
); );
}); });
it('70: should render a subgraph with direction TD', () => {
imgSnapshotTest(
`
flowchart LR
subgraph A
direction TD
a --> b
end
`,
{
fontFamily: 'courier',
}
);
});
}); });

View File

@@ -803,4 +803,34 @@ describe('Gantt diagram', () => {
{} {}
); );
}); });
it('should handle numeric timestamps with dateFormat x', () => {
imgSnapshotTest(
`
gantt
title Process time profile (ms)
dateFormat x
axisFormat %L
tickInterval 250millisecond
section Pipeline
Parse JSON p1: 000, 120
`,
{}
);
});
it('should handle numeric timestamps with dateFormat X', () => {
imgSnapshotTest(
`
gantt
title Process time profile (ms)
dateFormat X
axisFormat %L
tickInterval 250millisecond
section Pipeline
Parse JSON p1: 000, 120
`,
{}
);
});
}); });

View File

@@ -1,118 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util';
const looks = ['classic'] as const;
looks.forEach((look) => {
describe(`SequenceDiagram icon participants in ${look} look`, () => {
it(`single participant with icon`, () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "icon", icon: "fa:bell" }
Note over Bob: Icon participant`;
imgSnapshotTest(diagram, { look });
});
it(`two participants, one icon and one normal`, () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "icon", icon: "fa:bell" }
participant Alice
Bob->>Alice: Hello`;
imgSnapshotTest(diagram, { look });
});
it(`two icon participants`, () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "icon", icon: "fa:bell" }
participant Alice@{ type: "icon", icon: "fa:user" }
Bob->>Alice: Hello
Alice-->>Bob: Hi`;
imgSnapshotTest(diagram, { look });
});
it(`with markdown htmlLabels:true content`, () => {
// html/markdown in messages/notes (participants themselves don't support label/form/w/h)
const diagram = `
sequenceDiagram
participant Bob@{ type: "icon", icon: "fa:bell" }
participant Alice
Bob->>Alice: This is **bold** </br>and <strong>strong</strong>
Note over Bob,Alice: Mixed <em>HTML</em> and **markdown**`;
imgSnapshotTest(diagram, { look });
});
it(`with markdown htmlLabels:false content`, () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "icon", icon: "fa:bell" }
participant Alice
Bob->>Alice: This is **bold** </br>and <strong>strong</strong>`;
imgSnapshotTest(diagram, {
look,
htmlLabels: false,
flowchart: { htmlLabels: false },
});
});
it(`with styles applied to participant`, () => {
// style by participant id
const diagram = `
sequenceDiagram
participant Bob@{ type: "icon", icon: "fa:bell" }
participant Alice
Bob->>Alice: Styled participant
`;
imgSnapshotTest(diagram, { look });
});
it(`with classDef and class application`, () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "icon", icon: "fa:bell" }
participant Alice
Bob->>Alice: Classed participant
`;
imgSnapshotTest(diagram, { look });
});
});
});
// Colored emoji icon tests (analogous to the flowchart colored icon tests), no direction line.
describe('SequenceDiagram colored icon participant', () => {
it('colored emoji icon without styles', () => {
const icon = 'fluent-emoji:tropical-fish';
const diagram = `
sequenceDiagram
participant Bob@{ type: "icon", icon: "${icon}" }
Note over Bob: colored emoji icon
`;
imgSnapshotTest(diagram);
});
it('colored emoji icon with styles', () => {
const icon = 'fluent-emoji:tropical-fish';
const diagram = `
sequenceDiagram
participant Bob@{ type: "icon", icon: "${icon}" }
`;
imgSnapshotTest(diagram);
});
});
// Mixed scenario: multiple interactions, still no direction line.
describe('SequenceDiagram icon participant with multiple interactions', () => {
const icon = 'fa:bell-slash';
it('icon participant interacts with two normal participants', () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "icon", icon: "${icon}" }
participant Alice
participant Carol
Bob->>Alice: Ping
Alice-->>Bob: Pong
Bob->>Carol: Notify
Note right of Bob: Icon side note`;
imgSnapshotTest(diagram);
});
});

View File

@@ -1,94 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util';
const looks = ['classic'] as const;
looks.forEach((look) => {
describe(`SequenceDiagram image participants in ${look} look`, () => {
it(`single participant with image`, () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
Note over Bob: Image participant`;
imgSnapshotTest(diagram, { look });
});
it(`two participants, one image and one normal`, () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
participant Alice
Bob->>Alice: Hello`;
imgSnapshotTest(diagram, { look });
});
it(`two image participants`, () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
participant Alice@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
Bob->>Alice: Hello
Alice-->>Bob: Hi`;
imgSnapshotTest(diagram, { look });
});
it(`with markdown htmlLabels:true content`, () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
participant Alice
Bob->>Alice: This is **bold** </br>and <strong>strong</strong>
Note over Bob,Alice: Mixed <em>HTML</em> and **markdown**`;
imgSnapshotTest(diagram, { look });
});
it(`with markdown htmlLabels:false content`, () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
participant Alice
Bob->>Alice: This is **bold** </br>and <strong>strong</strong>`;
imgSnapshotTest(diagram, {
look,
htmlLabels: false,
flowchart: { htmlLabels: false },
});
});
it(`with styles applied to participant`, () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
participant Alice
Bob->>Alice: Styled participant
`;
imgSnapshotTest(diagram, { look });
});
it(`with classDef and class application`, () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
participant Alice
Bob->>Alice: Classed participant
`;
imgSnapshotTest(diagram, { look });
});
});
});
// Mixed scenario: multiple interactions, still no direction line.
describe('SequenceDiagram image participant with multiple interactions', () => {
const imageUrl = 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg';
it('image participant interacts with two normal participants', () => {
const diagram = `
sequenceDiagram
participant Bob@{ type: "image", "image": "${imageUrl}" }
participant Alice
participant Carol
Bob->>Alice: Ping
Alice-->>Bob: Pong
Bob->>Carol: Notify
Note right of Bob: Image side note`;
imgSnapshotTest(diagram);
});
});

View File

@@ -655,5 +655,955 @@ describe('Sequence Diagram Special Cases', () => {
expect(svg).to.not.have.attr('style'); expect(svg).to.not.have.attr('style');
}); });
}); });
describe('Central Connection Rendering Tests', () => {
it('should render central connection circles on actor vertical lines', () => {
imgSnapshotTest(
`sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice ()->>() Bob: Central connection
Bob ()-->> Charlie: Reverse central connection
Charlie ()<<-->>() Alice: Dual central connection`,
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render central connections with different arrow types', () => {
imgSnapshotTest(
`sequenceDiagram
participant Alice
participant Bob
Alice ()->>() Bob: Solid open arrow
Alice ()-->>() Bob: Dotted open arrow
Alice ()-x() Bob: Solid cross
Alice ()--x() Bob: Dotted cross
Alice ()->() Bob: Solid arrow`,
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render central connections with bidirectional arrows', () => {
imgSnapshotTest(
`sequenceDiagram
participant Alice
participant Bob
Alice ()<<->>() Bob: Bidirectional solid
Alice ()<<-->>() Bob: Bidirectional dotted`,
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render central connections with activations', () => {
imgSnapshotTest(
`sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice ()->>() Bob: Activate Bob
activate Bob
Bob ()-->> Charlie: Message to Charlie
Bob ()->>() Alice: Response to Alice
deactivate Bob`,
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render central connections mixed with normal messages', () => {
imgSnapshotTest(
`sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice ->> Bob: Normal message
Bob ()->>() Charlie: Central connection
Charlie -->> Alice: Normal dotted message
Alice ()<<-->>() Bob: Dual central connection
Bob -x Charlie: Normal cross message`,
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render central connections with notes', () => {
imgSnapshotTest(
`sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice ()->>() Bob: Central connection
Note over Alice,Bob: Central connection note
Bob ()-->> Charlie: Reverse central connection
Note right of Charlie: Response note
Charlie ()<<-->>() Alice: Dual central connection`,
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render central connections with loops and alternatives', () => {
imgSnapshotTest(
`sequenceDiagram
participant Alice
participant Bob
participant Charlie
loop Every minute
Alice ()->>() Bob: Central heartbeat
Bob ()-->> Charlie: Forward heartbeat
end
alt Success
Charlie ()<<-->>() Alice: Success response
else Failure
Charlie ()-x() Alice: Failure response
end`,
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render central connections with different participant types', () => {
imgSnapshotTest(
`sequenceDiagram
participant Alice
actor Bob
participant Charlie@{"type":"boundary"}
participant David@{"type":"control"}
participant Eve@{"type":"entity"}
Alice ()->>() Bob: To actor
Bob ()-->> Charlie: To boundary
Charlie ()->>() David: To control
David ()<<-->>() Eve: To entity
Eve ()-x() Alice: Back to participant`,
{ look: 'classic', sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
});
describe('Sequence Diagram Rendering with Autonumber and All Arrow Types', () => {
describe('Autonumber with All Arrow Types', () => {
it('should render all arrow types with autonumbering', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
Alice->>Bob: Solid arrow (->>)
Bob-->>Alice: Dotted arrow (-->>)
Alice->Charlie: Solid open arrow (->)
Charlie-->Dave: Dotted open arrow (-->)
Alice-xBob: Solid cross (-x)
Bob--xAlice: Dotted cross (--x)
Alice-)Charlie: Solid point async (-)
Charlie--)Dave: Dotted point async (--)
Alice<<->>Bob: Bidirectional solid (<<->>)
Charlie<<-->>Dave: Bidirectional dotted (<<-->>)
Alice-|\\Bob: Solid top half (-|\\)
Bob-|/Alice: Solid bottom half (-|/)
Alice-\\\\Charlie: Stick top half (-\\\\)
Charlie-//Dave: Stick bottom half (-//)
Dave/|-Charlie: Solid top reverse (/|-)
Charlie\\|-Bob: Solid bottom reverse (\\|-)
Bob//-Alice: Stick top reverse (//-)
Alice\\\\-Bob: Stick bottom reverse (\\\\-)
Alice--|\\Bob: Dotted solid top (--|\\)
Bob--|/Alice: Dotted solid bottom (--|/)
Alice--\\\\Charlie: Dotted stick top (--\\\\)
Charlie--//Dave: Dotted stick bottom (--//)
Dave/|--Charlie: Dotted solid top reverse (/|--)
Charlie\\|--Bob: Dotted solid bottom reverse (\\|--)
Bob//--Alice: Dotted stick top reverse (//--)
Alice\\\\--Bob: Dotted stick bottom reverse (\\\\--)
Alice->>()Bob: Solid with central connection
Bob()-->>Alice: Dotted with reverse central
Alice()->>()Charlie: Dual central connections`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render all arrow types with autonumbering - left to right only', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
Alice->>Bob: Solid arrow (->>)
Alice-->>Bob: Dotted arrow (-->>)
Alice->Bob: Solid open arrow (->)
Alice-->Bob: Dotted open arrow (-->)
Alice-xBob: Solid cross (-x)
Alice--xBob: Dotted cross (--x)
Alice-)Bob: Solid point async (-)
Alice--)Bob: Dotted point async (--)
Alice<<->>Bob: Bidirectional solid (<<->>)
Alice<<-->>Bob: Bidirectional dotted (<<-->>)
Alice-|\\Bob: Solid top half (-|\\)
Alice-|/Bob: Solid bottom half (-|/)
Alice-\\\\Bob: Stick top half (-\\\\)
Alice-//Bob: Stick bottom half (-//)
Bob/|-Alice: Solid top reverse (/|-)
Bob\\|-Alice: Solid bottom reverse (\\|-)
Bob//-Alice: Stick top reverse (//-)
Bob\\\\-Alice: Stick bottom reverse (\\\\-)
Alice--|\\Bob: Dotted solid top (--|\\)
Alice--|/Bob: Dotted solid bottom (--|/)
Alice--\\\\Bob: Dotted stick top (--\\\\)
Alice--//Bob: Dotted stick bottom (--//)
Bob/|--Alice: Dotted solid top reverse (/|--)
Bob\\|--Alice: Dotted solid bottom reverse (\\|--)
Bob//--Alice: Dotted stick top reverse (//--)
Bob\\\\--Alice: Dotted stick bottom reverse (\\\\--)
Alice->>()Bob: Solid with central connection
Alice()-->>Bob: Dotted with reverse central
Alice()->>()Bob: Dual central connections`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render central connections with autonumbering', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice->>()Bob: Central connection at destination
Bob()->>Alice: Reverse central at source
Alice()->>()Bob: Dual central connections
Bob->>()Charlie: Another central connection
Charlie()-->>Alice: Reverse central dotted
Alice()<<-->>()Bob: Dual central bidirectional`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render bidirectional arrows with autonumbering', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice<<->>Bob: Bidirectional solid left to right
Bob<<->>Alice: Bidirectional solid right to left
Alice<<-->>Charlie: Bidirectional dotted left to right
Charlie<<-->>Alice: Bidirectional dotted right to left
Bob<<->>Charlie: Bidirectional solid
Charlie<<-->>Bob: Bidirectional dotted`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render reverse arrows with autonumbering', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Bob/|-Alice: Solid top reverse left to right
Alice/|-Bob: Solid top reverse right to left
Bob\\|-Alice: Solid bottom reverse left to right
Alice\\|-Bob: Solid bottom reverse right to left
Bob//-Alice: Stick top reverse left to right
Alice//-Bob: Stick top reverse right to left
Bob\\\\-Alice: Stick bottom reverse left to right
Alice\\\\-Bob: Stick bottom reverse right to left
Bob/|--Alice: Dotted solid top reverse
Alice\\|--Bob: Dotted solid bottom reverse
Bob//--Alice: Dotted stick top reverse
Alice\\\\--Bob: Dotted stick bottom reverse`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
});
describe('Central Connections with Autonumber - Comprehensive Coverage', () => {
it('should render CENTRAL_CONNECTION with normal arrows - left to right', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice->>()Bob: Solid arrow with circle at destination
Alice-->>()Bob: Dotted arrow with circle at destination
Alice->()Bob: Open arrow with circle at destination
Alice--x()Bob: Cross arrow with circle at destination
Alice--)()Bob: Close arrow with circle at destination`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render CENTRAL_CONNECTION with normal arrows - right to left', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Bob->>()Alice: Solid arrow with circle at destination (RTL)
Charlie-->>()Bob: Dotted arrow with circle at destination (RTL)
Bob->()Alice: Open arrow with circle at destination (RTL)
Charlie--x()Alice: Cross arrow with circle at destination (RTL)
Bob--)()Alice: Close arrow with circle at destination (RTL)`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render CENTRAL_CONNECTION with reverse arrows - left to right', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Bob/|-()Alice: Solid top reverse with circle (LTR)
Bob\\|-()Alice: Solid bottom reverse with circle (LTR)
Bob//-()Alice: Stick top reverse with circle (LTR)
Bob\\\\-()Alice: Stick bottom reverse with circle (LTR)
Bob/|--()Alice: Dotted solid top reverse with circle (LTR)
Bob\\|--()Alice: Dotted solid bottom reverse with circle (LTR)
Bob//--()Alice: Dotted stick top reverse with circle (LTR)
Bob\\\\--()Alice: Dotted stick bottom reverse with circle (LTR)`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render CENTRAL_CONNECTION with reverse arrows - right to left', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice/|-()Bob: Solid top reverse with circle (RTL)
Alice\\|-()Bob: Solid bottom reverse with circle (RTL)
Alice//-()Bob: Stick top reverse with circle (RTL)
Alice\\\\-()Bob: Stick bottom reverse with circle (RTL)
Alice/|--()Bob: Dotted solid top reverse with circle (RTL)
Alice\\|--()Bob: Dotted solid bottom reverse with circle (RTL)
Alice//--()Bob: Dotted stick top reverse with circle (RTL)
Alice\\\\--()Bob: Dotted stick bottom reverse with circle (RTL)`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render Central_Connection_REVERSE ()->> normal LTR', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice()->>Bob: Circle at source with solid arrow
Alice()-->>Bob: Circle at source with dotted arrow
Alice()->Bob: Circle at source with open arrow
Alice()--xBob: Circle at source with cross arrow
Alice()--)Bob: Circle at source with close arrow`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render Central_Connection_REVERSE ()->> normal RTL', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Bob()->>Alice: Circle at source with solid arrow (RTL)
Charlie()-->>Bob: Circle at source with dotted arrow (RTL)
Bob()->Alice: Circle at source with open arrow (RTL)
Charlie()--xAlice: Circle at source with cross arrow (RTL)
Bob()--)Alice: Circle at source with close arrow (RTL)`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render Central_Connection_REVERSE ()->> reverse LTR', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Bob()/|-Alice: Circle at source with solid top reverse (LTR)
Bob()\\|-Alice: Circle at source with solid bottom reverse (LTR)
Bob()//-Alice: Circle at source with stick top reverse (LTR)
Bob()\\\\-Alice: Circle at source with stick bottom reverse (LTR)
Bob()/|--Alice: Circle at source with dotted solid top reverse (LTR)
Bob()\\|--Alice: Circle at source with dotted solid bottom reverse (LTR)
Bob()//--Alice: Circle at source with dotted stick top reverse (LTR)
Bob()\\\\--Alice: Circle at source with dotted stick bottom reverse (LTR)`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render Central_Connection_REVERSE ()->> reverse RTL', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice()/|-Bob: Circle at source with solid top reverse (RTL)
Alice()\\|-Bob: Circle at source with solid bottom reverse (RTL)
Alice()//-Bob: Circle at source with stick top reverse (RTL)
Alice()\\\\-Bob: Circle at source with stick bottom reverse (RTL)
Alice()/|--Bob: Circle at source with dotted solid top reverse (RTL)
Alice()\\|--Bob: Circle at source with dotted solid bottom reverse (RTL)
Alice()//--Bob: Circle at source with dotted stick top reverse (RTL)
Alice()\\\\--Bob: Circle at source with dotted stick bottom reverse (RTL)`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render Central_Connection_DUAL ()->>() normal LTR', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice()->>()Bob: Circles at both ends with solid arrow
Alice()-->>()Bob: Circles at both ends with dotted arrow
Alice()->()Bob: Circles at both ends with open arrow
Alice()--x()Bob: Circles at both ends with cross arrow
Alice()--)()Bob: Circles at both ends with close arrow`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render Central_Connection_DUAL ()->>() normal RTL', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Bob()->>()Alice: Circles at both ends with solid arrow (RTL)
Charlie()-->>()Bob: Circles at both ends with dotted arrow (RTL)
Bob()->()Alice: Circles at both ends with open arrow (RTL)
Charlie()--x()Alice: Circles at both ends with cross arrow (RTL)
Bob()--)()Alice: Circles at both ends with close arrow (RTL)`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render Central_Connection_DUAL ()->>() reverse LTR', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Bob()/|-()Alice: Circles at both ends with solid top reverse (LTR)
Bob()\\|-()Alice: Circles at both ends with solid bottom reverse (LTR)
Bob()//-()Alice: Circles at both ends with stick top reverse (LTR)
Bob()\\\\-()Alice: Circles at both ends with stick bottom reverse (LTR)
Bob()/|--()Alice: Circles at both ends with dotted solid top reverse (LTR)
Bob()\\|--()Alice: Circles at both ends with dotted solid bottom reverse (LTR)
Bob()//--()Alice: Circles at both ends with dotted stick top reverse (LTR)
Bob()\\\\--()Alice: Circles at both ends with dotted stick bottom reverse (LTR)`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render Central_Connection_DUAL ()->>() reverse RTL', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice()/|-()Bob: Circles at both ends with solid top reverse (RTL)
Alice()\\|-()Bob: Circles at both ends with solid bottom reverse (RTL)
Alice()//-()Bob: Circles at both ends with stick top reverse (RTL)
Alice()\\\\-()Bob: Circles at both ends with stick bottom reverse (RTL)
Alice()/|--()Bob: Circles at both ends with dotted solid top reverse (RTL)
Alice()\\|--()Bob: Circles at both ends with dotted solid bottom reverse (RTL)
Alice()//--()Bob: Circles at both ends with dotted stick top reverse (RTL)
Alice()\\\\--()Bob: Circles at both ends with dotted stick bottom reverse (RTL)`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render mixed central connections with autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
participant David
Note over Alice,David: Normal arrows with central connections
Alice->>()Bob: CENTRAL_CONNECTION LTR
Bob->>()Alice: CENTRAL_CONNECTION RTL
Alice()->>Bob: CENTRAL_CONNECTION_REVERSE LTR
Bob()->>Alice: CENTRAL_CONNECTION_REVERSE RTL
Alice()->>()Bob: CENTRAL_CONNECTION_DUAL LTR
Bob()->>()Alice: CENTRAL_CONNECTION_DUAL RTL
Note over Alice,David: Reverse arrows with central connections
Bob/|-()Alice: Reverse with CENTRAL_CONNECTION LTR
Alice/|-()Bob: Reverse with CENTRAL_CONNECTION RTL
Bob()/|-Alice: Reverse with CENTRAL_CONNECTION_REVERSE LTR
Alice()/|-Bob: Reverse with CENTRAL_CONNECTION_REVERSE RTL
Bob()/|-()Alice: Reverse with CENTRAL_CONNECTION_DUAL LTR
Alice()/|-()Bob: Reverse with CENTRAL_CONNECTION_DUAL RTL
Note over Alice,David: Mixed with different participants
Alice->>()Charlie: Skip participant
Charlie()->>Alice: Back skip
Bob()->>()David: Another skip
David()->>()Bob: Return skip`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render central connections with bidirectional arrows and autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice()<<->>()Bob: Dual central with bidirectional solid LTR
Bob()<<->>()Alice: Dual central with bidirectional solid RTL
Alice()<<-->>()Bob: Dual central with bidirectional dotted LTR
Bob()<<-->>()Alice: Dual central with bidirectional dotted RTL
Alice<<->>()Bob: Central at end with bidirectional LTR
Bob()<<->>Alice: Central at start with bidirectional RTL`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
});
describe('Self-Reference Arrows - Comprehensive Coverage', () => {
it('should render self-reference with normal arrows - without autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice->>Alice: Solid arrow self-reference
Bob-->>Bob: Dotted arrow self-reference
Charlie->Charlie: Open arrow self-reference
Alice-->Alice: Dotted open arrow self-reference
Bob-xBob: Cross arrow self-reference
Charlie--xCharlie: Dotted cross self-reference`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with normal arrows - with autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice->>Alice: Solid arrow self-reference
Bob-->>Bob: Dotted arrow self-reference
Charlie->Charlie: Open arrow self-reference
Alice-->Alice: Dotted open arrow self-reference
Bob-xBob: Cross arrow self-reference
Charlie--xCharlie: Dotted cross self-reference`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with reverse arrows - without autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice/|-Alice: Solid top reverse self-reference
Bob\\|-Bob: Solid bottom reverse self-reference
Charlie//-Charlie: Stick top reverse self-reference
Alice\\\\-Alice: Stick bottom reverse self-reference
Bob/|--Bob: Dotted solid top reverse self-reference
Charlie\\|--Charlie: Dotted solid bottom reverse self-reference
Alice//--Alice: Dotted stick top reverse self-reference
Bob\\\\--Bob: Dotted stick bottom reverse self-reference`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with reverse arrows - with autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice/|-Alice: Solid top reverse self-reference
Bob\\|-Bob: Solid bottom reverse self-reference
Charlie//-Charlie: Stick top reverse self-reference
Alice\\\\-Alice: Stick bottom reverse self-reference
Bob/|--Bob: Dotted solid top reverse self-reference
Charlie\\|--Charlie: Dotted solid bottom reverse self-reference
Alice//--Alice: Dotted stick top reverse self-reference
Bob\\\\--Bob: Dotted stick bottom reverse self-reference`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with bidirectional arrows - without autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice<<->>Alice: Bidirectional solid self-reference
Bob<<-->>Bob: Bidirectional dotted self-reference
Charlie<<->>Charlie: Another bidirectional solid
Alice<<-->>Alice: Another bidirectional dotted`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with bidirectional arrows - with autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice<<->>Alice: Bidirectional solid self-reference
Bob<<-->>Bob: Bidirectional dotted self-reference
Charlie<<->>Charlie: Another bidirectional solid
Alice<<-->>Alice: Another bidirectional dotted`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with CENTRAL_CONNECTION - without autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice->>()Alice: Solid arrow with circle at destination
Bob-->>()Bob: Dotted arrow with circle at destination
Charlie->()Charlie: Open arrow with circle at destination
Alice--x()Alice: Cross arrow with circle at destination
Bob--)()Bob: Close arrow with circle at destination`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with CENTRAL_CONNECTION - with autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice->>()Alice: Solid arrow with circle at destination
Bob-->>()Bob: Dotted arrow with circle at destination
Charlie->()Charlie: Open arrow with circle at destination
Alice--x()Alice: Cross arrow with circle at destination
Bob--)()Bob: Close arrow with circle at destination`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with CENTRAL_CONNECTION_REVERSE - without autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice()->>Alice: Circle at source with solid arrow
Bob()-->>Bob: Circle at source with dotted arrow
Charlie()->Charlie: Circle at source with open arrow
Alice()--xAlice: Circle at source with cross arrow
Bob()--)Bob: Circle at source with close arrow`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with CENTRAL_CONNECTION_REVERSE - with autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice()->>Alice: Circle at source with solid arrow
Bob()-->>Bob: Circle at source with dotted arrow
Charlie()->Charlie: Circle at source with open arrow
Alice()--xAlice: Circle at source with cross arrow
Bob()--)Bob: Circle at source with close arrow`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with CENTRAL_CONNECTION_DUAL - without autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice()->>()Alice: Circles at both ends with solid arrow
Bob()-->>()Bob: Circles at both ends with dotted arrow
Charlie()->()Charlie: Circles at both ends with open arrow
Alice()--x()Alice: Circles at both ends with cross arrow
Bob()--)()Bob: Circles at both ends with close arrow`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with CENTRAL_CONNECTION_DUAL - with autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice()->>()Alice: Circles at both ends with solid arrow
Bob()-->>()Bob: Circles at both ends with dotted arrow
Charlie()->()Charlie: Circles at both ends with open arrow
Alice()--x()Alice: Circles at both ends with cross arrow
Bob()--)()Bob: Circles at both ends with close arrow`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with reverse arrows and CENTRAL_CONNECTION', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice/|-()Alice: Solid top reverse with circle at destination
Bob\\|-()Bob: Solid bottom reverse with circle at destination
Charlie//-()Charlie: Stick top reverse with circle at destination
Alice\\\\-()Alice: Stick bottom reverse with circle at destination
Bob/|--()Bob: Dotted solid top reverse with circle at destination
Charlie\\|--()Charlie: Dotted solid bottom reverse with circle at destination
Alice//--()Alice: Dotted stick top reverse with circle at destination
Bob\\\\--()Bob: Dotted stick bottom reverse with circle at destination`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with reverse arrows and CENTRAL_CONNECTION - with autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice/|-()Alice: Solid top reverse with circle at destination
Bob\\|-()Bob: Solid bottom reverse with circle at destination
Charlie//-()Charlie: Stick top reverse with circle at destination
Alice\\\\-()Alice: Stick bottom reverse with circle at destination
Bob/|--()Bob: Dotted solid top reverse with circle at destination
Charlie\\|--()Charlie: Dotted solid bottom reverse with circle at destination
Alice//--()Alice: Dotted stick top reverse with circle at destination
Bob\\\\--()Bob: Dotted stick bottom reverse with circle at destination`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-ref reverse Central_Connection_REVERSE no-autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice()/|-Alice: Circle at source with solid top reverse
Bob()\\|-Bob: Circle at source with solid bottom reverse
Charlie()//-Charlie: Circle at source with stick top reverse
Alice()\\\\-Alice: Circle at source with stick bottom reverse
Bob()/|--Bob: Circle at source with dotted solid top reverse
Charlie()\\|--Charlie: Circle at source with dotted solid bottom reverse
Alice()//--Alice: Circle at source with dotted stick top reverse
Bob()\\\\--Bob: Circle at source with dotted stick bottom reverse`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-ref reverse Central_Connection_REVERSE autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice()/|-Alice: Circle at source with solid top reverse
Bob()\\|-Bob: Circle at source with solid bottom reverse
Charlie()//-Charlie: Circle at source with stick top reverse
Alice()\\\\-Alice: Circle at source with stick bottom reverse
Bob()/|--Bob: Circle at source with dotted solid top reverse
Charlie()\\|--Charlie: Circle at source with dotted solid bottom reverse
Alice()//--Alice: Circle at source with dotted stick top reverse
Bob()\\\\--Bob: Circle at source with dotted stick bottom reverse`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-ref reverse Central_Connection_DUAL no-autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice()/|-()Alice: Circles at both ends with solid top reverse
Bob()\\|-()Bob: Circles at both ends with solid bottom reverse
Charlie()//-()Charlie: Circles at both ends with stick top reverse
Alice()\\\\-()Alice: Circles at both ends with stick bottom reverse
Bob()/|--()Bob: Circles at both ends with dotted solid top reverse
Charlie()\\|--()Charlie: Circles at both ends with dotted solid bottom reverse
Alice()//--()Alice: Circles at both ends with dotted stick top reverse
Bob()\\\\--()Bob: Circles at both ends with dotted stick bottom reverse`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-references, reverse arrows & dual central connection (autonumber).', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice()/|-()Alice: Circles at both ends with solid top reverse
Bob()\\|-()Bob: Circles at both ends with solid bottom reverse
Charlie()//-()Charlie: Circles at both ends with stick top reverse
Alice()\\\\-()Alice: Circles at both ends with stick bottom reverse
Bob()/|--()Bob: Circles at both ends with dotted solid top reverse
Charlie()\\|--()Charlie: Circles at both ends with dotted solid bottom reverse
Alice()//--()Alice: Circles at both ends with dotted stick top reverse
Bob()\\\\--()Bob: Circles at both ends with dotted stick bottom reverse`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('Render self-references with bidirectional central connections (no autonumber).', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice()<<->>()Alice: Dual central with bidirectional solid
Bob()<<-->>()Bob: Dual central with bidirectional dotted
Charlie<<->>()Alice: Central at end with bidirectional
Bob()<<->>Bob: Central at start with bidirectional`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference with bidirectional and central connections - with autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice()<<->>()Alice: Dual central with bidirectional solid
Bob()<<-->>()Bob: Dual central with bidirectional dotted
Charlie<<->>()Charlie: Central at end with bidirectional
Bob()<<->>Bob: Central at start with bidirectional`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render comprehensive self-reference scenario - all arrow types mixed', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Note over Alice,Charlie: Normal arrows
Alice->>Alice: Normal solid
Bob-->>Bob: Normal dotted
Charlie->Charlie: Normal open
Note over Alice,Charlie: Reverse arrows
Alice/|-Alice: Reverse solid top
Bob\\|-Bob: Reverse solid bottom
Note over Alice,Charlie: Bidirectional arrows
Charlie<<->>Charlie: Bidirectional solid
Alice<<-->>Alice: Bidirectional dotted
Note over Alice,Charlie: Central connections
Bob->>()Bob: Central at destination
Charlie()->>Charlie: Central at source
Alice()->>()Alice: Dual central
Note over Alice,Charlie: Reverse with central
Bob()/|-()Bob: Reverse with dual central
Charlie/|-()Charlie: Reverse with central at destination
Note over Alice,Charlie: Bidirectional with central
Alice()<<->>()Alice: Bidirectional with dual central`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
it('should render self-reference mixed with regular messages and autonumber', () => {
imgSnapshotTest(
`%%{init: {'theme':'base'}}%%
sequenceDiagram
autonumber
participant Alice
participant Bob
participant Charlie
Alice->>Bob: Regular message
Bob->>Bob: Self-reference solid
Bob-->>Charlie: Regular dotted
Charlie()->>()Charlie: Self-ref dual central
Charlie->>Alice: Regular back
Alice<<->>Alice: Self-ref bidirectional
Alice()->>Bob: Regular with central
Bob()/|-()Bob: Self-ref reverse dual central
Bob-->>Alice: Regular dotted back`,
{ sequence: { diagramMarginX: 50, diagramMarginY: 10 } }
);
});
});
});
}); });
}); });

View File

@@ -1053,4 +1053,167 @@ describe('Sequence diagram', () => {
]); ]);
}); });
}); });
describe('render new arrow type', () => {
it('should render Solid half arrow top', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice -|\\ John: Hello John, how are you?
Alice-|\\ John: Hi Alice, I can hear you!
Alice -|\\ John: Test
`
);
});
it('should render Solid half arrow bottom', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice-|/John: Hello John, how are you?
Alice-|/John: Hi Alice, I can hear you!
Alice-|/John: Test
`
);
});
it('should render Stick half arrow top ', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice-\\\\John: Hello John, how are you?
Alice-\\\\John: Hi Alice, I can hear you!
Alice-\\\\John: Test
`
);
});
it('should render Stick half arrow bottom ', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice-//John: Hello John, how are you?
Alice-//John: Hi Alice, I can hear you!
Alice-//John: Test
`
);
});
it('should render Solid half arrow top reverse ', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice/|-John: Hello Alice, how are you?
Alice/|-John: Hi Alice, I can hear you!
Alice/|-John: Test
`
);
});
it('should render Solid half arrow bottom reverse ', () => {
imgSnapshotTest(
`sequenceDiagram
Alice \\|- John: Hello Alice, how are you?
Alice \\|- John: Hi Alice, I can hear you!
Alice \\|- John: Test`
);
});
it('should render Stick half arrow top reverse ', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice //-John: Hello Alice, how are you?
Alice //-John: Hi Alice, I can hear you!
Alice //-John: Test`
);
});
it('should render Stick half arrow bottom reverse ', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice \\\\-John: Hello Alice, how are you?
Alice \\\\-John: Hi Alice, I can hear you!
Alice \\\\-John: Test`
);
});
it('should render Solid half arrow top dotted', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice --|\\John: Hello John, how are you?
Alice --|\\John: Hi Alice, I can hear you!
Alice --|\\John: Test`
);
});
it('should render Solid half arrow bottom dotted', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice --|/John: Hello John, how are you?
Alice --|/John: Hi Alice, I can hear you!
Alice --|/John: Test`
);
});
it('should render Stick half arrow top dotted', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice--\\\\John: Hello John, how are you?
Alice--\\\\John: Hi Alice, I can hear you!
Alice--\\\\John: Test`
);
});
it('should render Stick half arrow bottom dotted', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice--//John: Hello John, how are you?
Alice--//John: Hi Alice, I can hear you!
Alice--//John: Test`
);
});
it('should render Solid half arrow top reverse dotted', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice/|--John: Hello Alice, how are you?
Alice/|--John: Hi Alice, I can hear you!
Alice/|--John: Test`
);
});
it('should render Solid half arrow bottom reverse dotted', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice\\|--John: Hello Alice, how are you?
Alice\\|--John: Hi Alice, I can hear you!
Alice\\|--John: Test`
);
});
it('should render Stick half arrow top reverse dotted ', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice//--John: Hello Alice, how are you?
Alice//--John: Hi Alice, I can hear you!
Alice//--John: Test`
);
});
it('should render Stick half arrow bottom reverse dotted ', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice\\\\--John: Hello Alice, how are you?
Alice\\\\--John: Hi Alice, I can hear you!
Alice\\\\--John: Test`
);
});
});
}); });

View File

@@ -110,6 +110,48 @@
config: config:
layout: elk layout: elk
--- ---
mindmap
root((mindmap))
Origins
Long history
::icon(fa fa-book)
Popularisation
British popular psychology author Tony Buzan
Research
On effectiveness&lt;br/>and features
On Automatic creation
Uses
Creative techniques
Strategic planning
Argument mapping
Tools
id)I am a cloud(
id))I am a bang((
Tools
</pre>
<pre id="diagram4" class="mermaid">
---
config:
layout: elk
---
flowchart
aid0
</pre
>
<pre id="diagram4" class="mermaid">
---
config:
layout: elk
---
mindmap
aid0
</pre>
<pre id="diagram4" class="mermaid">
---
config:
layout: ogdc
---
flowchart-elk TB flowchart-elk TB
c1-->a2 c1-->a2
subgraph one subgraph one

View File

@@ -603,6 +603,10 @@
</div> </div>
<div class="test"> <div class="test">
<pre class="mermaid"> <pre class="mermaid">
---
config:
theme: dark
---
classDiagram classDiagram
test ()--() test2 test ()--() test2
</pre> </pre>

View File

@@ -2,227 +2,227 @@
"durations": [ "durations": [
{ {
"spec": "cypress/integration/other/configuration.spec.js", "spec": "cypress/integration/other/configuration.spec.js",
"duration": 5841 "duration": 6099
}, },
{ {
"spec": "cypress/integration/other/external-diagrams.spec.js", "spec": "cypress/integration/other/external-diagrams.spec.js",
"duration": 2138 "duration": 2236
}, },
{ {
"spec": "cypress/integration/other/ghsa.spec.js", "spec": "cypress/integration/other/ghsa.spec.js",
"duration": 3370 "duration": 3405
}, },
{ {
"spec": "cypress/integration/other/iife.spec.js", "spec": "cypress/integration/other/iife.spec.js",
"duration": 2052 "duration": 2176
}, },
{ {
"spec": "cypress/integration/other/interaction.spec.js", "spec": "cypress/integration/other/interaction.spec.js",
"duration": 12243 "duration": 12300
}, },
{ {
"spec": "cypress/integration/other/rerender.spec.js", "spec": "cypress/integration/other/rerender.spec.js",
"duration": 2065 "duration": 2089
}, },
{ {
"spec": "cypress/integration/other/xss.spec.js", "spec": "cypress/integration/other/xss.spec.js",
"duration": 31288 "duration": 32033
}, },
{ {
"spec": "cypress/integration/rendering/appli.spec.js", "spec": "cypress/integration/rendering/appli.spec.js",
"duration": 3421 "duration": 3672
}, },
{ {
"spec": "cypress/integration/rendering/architecture.spec.ts", "spec": "cypress/integration/rendering/architecture.spec.ts",
"duration": 97 "duration": 103
}, },
{ {
"spec": "cypress/integration/rendering/block.spec.js", "spec": "cypress/integration/rendering/block.spec.js",
"duration": 18500 "duration": 18135
}, },
{ {
"spec": "cypress/integration/rendering/c4.spec.js", "spec": "cypress/integration/rendering/c4.spec.js",
"duration": 5793 "duration": 5661
}, },
{ {
"spec": "cypress/integration/rendering/classDiagram-elk-v3.spec.js", "spec": "cypress/integration/rendering/classDiagram-elk-v3.spec.js",
"duration": 40966 "duration": 41456
}, },
{ {
"spec": "cypress/integration/rendering/classDiagram-handDrawn-v3.spec.js", "spec": "cypress/integration/rendering/classDiagram-handDrawn-v3.spec.js",
"duration": 39176 "duration": 38910
}, },
{ {
"spec": "cypress/integration/rendering/classDiagram-v2.spec.js", "spec": "cypress/integration/rendering/classDiagram-v2.spec.js",
"duration": 23468 "duration": 24120
}, },
{ {
"spec": "cypress/integration/rendering/classDiagram-v3.spec.js", "spec": "cypress/integration/rendering/classDiagram-v3.spec.js",
"duration": 38291 "duration": 38454
}, },
{ {
"spec": "cypress/integration/rendering/classDiagram.spec.js", "spec": "cypress/integration/rendering/classDiagram.spec.js",
"duration": 16949 "duration": 17099
}, },
{ {
"spec": "cypress/integration/rendering/conf-and-directives.spec.js", "spec": "cypress/integration/rendering/conf-and-directives.spec.js",
"duration": 9480 "duration": 9844
}, },
{ {
"spec": "cypress/integration/rendering/current.spec.js", "spec": "cypress/integration/rendering/current.spec.js",
"duration": 2753 "duration": 2951
}, },
{ {
"spec": "cypress/integration/rendering/erDiagram-unified.spec.js", "spec": "cypress/integration/rendering/erDiagram-unified.spec.js",
"duration": 88028 "duration": 90081
}, },
{ {
"spec": "cypress/integration/rendering/erDiagram.spec.js", "spec": "cypress/integration/rendering/erDiagram.spec.js",
"duration": 15615 "duration": 19496
}, },
{ {
"spec": "cypress/integration/rendering/errorDiagram.spec.js", "spec": "cypress/integration/rendering/errorDiagram.spec.js",
"duration": 3706 "duration": 3829
}, },
{ {
"spec": "cypress/integration/rendering/flowchart-elk.spec.js", "spec": "cypress/integration/rendering/flowchart-elk.spec.js",
"duration": 43905 "duration": 42517
}, },
{ {
"spec": "cypress/integration/rendering/flowchart-handDrawn.spec.js", "spec": "cypress/integration/rendering/flowchart-handDrawn.spec.js",
"duration": 31217 "duration": 31541
}, },
{ {
"spec": "cypress/integration/rendering/flowchart-icon.spec.js", "spec": "cypress/integration/rendering/flowchart-icon.spec.js",
"duration": 7531 "duration": 7749
}, },
{ {
"spec": "cypress/integration/rendering/flowchart-shape-alias.spec.ts", "spec": "cypress/integration/rendering/flowchart-shape-alias.spec.ts",
"duration": 25423 "duration": 25230
}, },
{ {
"spec": "cypress/integration/rendering/flowchart-v2.spec.js", "spec": "cypress/integration/rendering/flowchart-v2.spec.js",
"duration": 49664 "duration": 49359
}, },
{ {
"spec": "cypress/integration/rendering/flowchart.spec.js", "spec": "cypress/integration/rendering/flowchart.spec.js",
"duration": 32525 "duration": 33028
}, },
{ {
"spec": "cypress/integration/rendering/gantt.spec.js", "spec": "cypress/integration/rendering/gantt.spec.js",
"duration": 20915 "duration": 22271
}, },
{ {
"spec": "cypress/integration/rendering/gitGraph.spec.js", "spec": "cypress/integration/rendering/gitGraph.spec.js",
"duration": 53556 "duration": 51837
}, },
{ {
"spec": "cypress/integration/rendering/iconShape.spec.ts", "spec": "cypress/integration/rendering/iconShape.spec.ts",
"duration": 283038 "duration": 285060
}, },
{ {
"spec": "cypress/integration/rendering/imageShape.spec.ts", "spec": "cypress/integration/rendering/imageShape.spec.ts",
"duration": 59434 "duration": 59517
}, },
{ {
"spec": "cypress/integration/rendering/info.spec.ts", "spec": "cypress/integration/rendering/info.spec.ts",
"duration": 3101 "duration": 3501
}, },
{ {
"spec": "cypress/integration/rendering/journey.spec.js", "spec": "cypress/integration/rendering/journey.spec.js",
"duration": 7099 "duration": 7405
}, },
{ {
"spec": "cypress/integration/rendering/kanban.spec.ts", "spec": "cypress/integration/rendering/kanban.spec.ts",
"duration": 7567 "duration": 7975
}, },
{ {
"spec": "cypress/integration/rendering/katex.spec.js", "spec": "cypress/integration/rendering/katex.spec.js",
"duration": 3817 "duration": 4312
}, },
{ {
"spec": "cypress/integration/rendering/marker_unique_id.spec.js", "spec": "cypress/integration/rendering/marker_unique_id.spec.js",
"duration": 2624 "duration": 2630
}, },
{ {
"spec": "cypress/integration/rendering/mindmap-tidy-tree.spec.js", "spec": "cypress/integration/rendering/mindmap-tidy-tree.spec.js",
"duration": 4246 "duration": 4541
}, },
{ {
"spec": "cypress/integration/rendering/mindmap.spec.ts", "spec": "cypress/integration/rendering/mindmap.spec.ts",
"duration": 11967 "duration": 12134
}, },
{ {
"spec": "cypress/integration/rendering/newShapes.spec.ts", "spec": "cypress/integration/rendering/newShapes.spec.ts",
"duration": 151914 "duration": 151160
}, },
{ {
"spec": "cypress/integration/rendering/oldShapes.spec.ts", "spec": "cypress/integration/rendering/oldShapes.spec.ts",
"duration": 116698 "duration": 118044
}, },
{ {
"spec": "cypress/integration/rendering/packet.spec.ts", "spec": "cypress/integration/rendering/packet.spec.ts",
"duration": 4967 "duration": 5166
}, },
{ {
"spec": "cypress/integration/rendering/pie.spec.ts", "spec": "cypress/integration/rendering/pie.spec.ts",
"duration": 6700 "duration": 7074
}, },
{ {
"spec": "cypress/integration/rendering/quadrantChart.spec.js", "spec": "cypress/integration/rendering/quadrantChart.spec.js",
"duration": 8963 "duration": 9518
}, },
{ {
"spec": "cypress/integration/rendering/radar.spec.js", "spec": "cypress/integration/rendering/radar.spec.js",
"duration": 5540 "duration": 5846
}, },
{ {
"spec": "cypress/integration/rendering/requirement.spec.js", "spec": "cypress/integration/rendering/requirement.spec.js",
"duration": 2782 "duration": 3089
}, },
{ {
"spec": "cypress/integration/rendering/requirementDiagram-unified.spec.js", "spec": "cypress/integration/rendering/requirementDiagram-unified.spec.js",
"duration": 54797 "duration": 55361
}, },
{ {
"spec": "cypress/integration/rendering/sankey.spec.ts", "spec": "cypress/integration/rendering/sankey.spec.ts",
"duration": 6914 "duration": 7236
}, },
{ {
"spec": "cypress/integration/rendering/sequencediagram-v2.spec.js", "spec": "cypress/integration/rendering/sequencediagram-v2.spec.js",
"duration": 20481 "duration": 26057
}, },
{ {
"spec": "cypress/integration/rendering/sequencediagram.spec.js", "spec": "cypress/integration/rendering/sequencediagram.spec.js",
"duration": 38490 "duration": 48401
}, },
{ {
"spec": "cypress/integration/rendering/stateDiagram-v2.spec.js", "spec": "cypress/integration/rendering/stateDiagram-v2.spec.js",
"duration": 30766 "duration": 30364
}, },
{ {
"spec": "cypress/integration/rendering/stateDiagram.spec.js", "spec": "cypress/integration/rendering/stateDiagram.spec.js",
"duration": 16705 "duration": 16862
}, },
{ {
"spec": "cypress/integration/rendering/theme.spec.js", "spec": "cypress/integration/rendering/theme.spec.js",
"duration": 30928 "duration": 30553
}, },
{ {
"spec": "cypress/integration/rendering/timeline.spec.ts", "spec": "cypress/integration/rendering/timeline.spec.ts",
"duration": 8424 "duration": 8962
}, },
{ {
"spec": "cypress/integration/rendering/treemap.spec.ts", "spec": "cypress/integration/rendering/treemap.spec.ts",
"duration": 12533 "duration": 12486
}, },
{ {
"spec": "cypress/integration/rendering/xyChart.spec.js", "spec": "cypress/integration/rendering/xyChart.spec.js",
"duration": 21197 "duration": 21718
}, },
{ {
"spec": "cypress/integration/rendering/zenuml.spec.js", "spec": "cypress/integration/rendering/zenuml.spec.js",
"duration": 3455 "duration": 3882
} }
] ]
} }

View File

@@ -2,7 +2,7 @@
"compilerOptions": { "compilerOptions": {
"target": "es2020", "target": "es2020",
"lib": ["es2020", "dom"], "lib": ["es2020", "dom"],
"types": ["cypress", "node", "@argos-ci/cypress/dist/support.d.ts"], "types": ["cypress", "node", "@argos-ci/cypress/support"],
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
"noEmit": true "noEmit": true
}, },

View File

@@ -184,6 +184,7 @@
} }
Admin --> Report : generates Admin --> Report : generates
</pre> </pre>
<hr />
<pre class="mermaid"> <pre class="mermaid">
classDiagram classDiagram
namespace Company.Project.Module { namespace Company.Project.Module {
@@ -240,6 +241,20 @@
Bike --> Square : "Logo Shape" Bike --> Square : "Logo Shape"
</pre> </pre>
<hr />
<pre class="mermaid">
classDiagram
note "This is a outer note"
note for Class1 "This is a outer note for Class1"
namespace ns {
note "This is a inner note"
note for Class1 "This is a inner note for Class1"
class Class1
class Class2
}
</pre>
<hr />
<script type="module"> <script type="module">
import mermaid from './mermaid.esm.mjs'; import mermaid from './mermaid.esm.mjs';
mermaid.initialize({ mermaid.initialize({

View File

@@ -11,7 +11,7 @@
rel="stylesheet" rel="stylesheet"
/> />
<link <link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
rel="stylesheet" rel="stylesheet"
/> />
<link <link

View File

@@ -29,7 +29,8 @@ In GitHub, you first [**fork a mermaid repository**](https://github.com/mermaid-
Then you **clone** a copy to your local development machine (e.g. where you code) to make a copy with all the files to work with. Then you **clone** a copy to your local development machine (e.g. where you code) to make a copy with all the files to work with.
> **💡 Tip** > [Here is a GitHub document that gives an overview of the process](https://docs.github.com/en/get-started/quickstart/fork-a-repo). > **💡 Tip**
> [Here is a GitHub document that gives an overview of the process](https://docs.github.com/en/get-started/quickstart/fork-a-repo).
```bash ```bash
git clone git@github.com/your-fork/mermaid git clone git@github.com/your-fork/mermaid

View File

@@ -33,7 +33,8 @@ mindmap
## Join the Development ## Join the Development
> **💡 Tip** > **Check out our** [**detailed contribution guide**](./contributing.md). > **💡 Tip**
> **Check out our** [**detailed contribution guide**](./contributing.md).
Where to start: Where to start:
@@ -47,7 +48,8 @@ Where to start:
## A Question Or a Suggestion? ## A Question Or a Suggestion?
> **💡 Tip** > **Have a look at** [**how to open an issue**](./questions-and-suggestions.md). > **💡 Tip**
> **Have a look at** [**how to open an issue**](./questions-and-suggestions.md).
If you have faced a vulnerability [report it to us](./security.md). If you have faced a vulnerability [report it to us](./security.md).

View File

@@ -22,7 +22,6 @@ While directives allow you to change most of the default configuration settings,
Mermaid basically supports two types of configuration options to be overridden by directives. Mermaid basically supports two types of configuration options to be overridden by directives.
1. _General/Top Level configurations_ : These are the configurations that are available and applied to all the diagram. **Some of the most important top-level** configurations are: 1. _General/Top Level configurations_ : These are the configurations that are available and applied to all the diagram. **Some of the most important top-level** configurations are:
- theme - theme
- fontFamily - fontFamily
- logLevel - logLevel

View File

@@ -10,7 +10,7 @@
# Interface: ParseOptions # Interface: ParseOptions
Defined in: [packages/mermaid/src/types.ts:76](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L76) Defined in: [packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L88)
## Properties ## Properties
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:76](https://github.com/mermaid-js/mer
> `optional` **suppressErrors**: `boolean` > `optional` **suppressErrors**: `boolean`
Defined in: [packages/mermaid/src/types.ts:81](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L81) Defined in: [packages/mermaid/src/types.ts:93](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L93)
If `true`, parse will return `false` instead of throwing error when the diagram is invalid. If `true`, parse will return `false` instead of throwing error when the diagram is invalid.
The `parseError` function will not be called. The `parseError` function will not be called.

View File

@@ -10,7 +10,7 @@
# Interface: ParseResult # Interface: ParseResult
Defined in: [packages/mermaid/src/types.ts:84](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L84) Defined in: [packages/mermaid/src/types.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L96)
## Properties ## Properties
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:84](https://github.com/mermaid-js/mer
> **config**: [`MermaidConfig`](MermaidConfig.md) > **config**: [`MermaidConfig`](MermaidConfig.md)
Defined in: [packages/mermaid/src/types.ts:92](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L92) Defined in: [packages/mermaid/src/types.ts:104](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L104)
The config passed as YAML frontmatter or directives The config passed as YAML frontmatter or directives
@@ -28,6 +28,6 @@ The config passed as YAML frontmatter or directives
> **diagramType**: `string` > **diagramType**: `string`
Defined in: [packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L88) Defined in: [packages/mermaid/src/types.ts:100](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L100)
The diagram type, e.g. 'flowchart', 'sequence', etc. The diagram type, e.g. 'flowchart', 'sequence', etc.

View File

@@ -10,7 +10,7 @@
# Interface: RenderResult # Interface: RenderResult
Defined in: [packages/mermaid/src/types.ts:102](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L102) Defined in: [packages/mermaid/src/types.ts:114](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L114)
## Properties ## Properties
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:102](https://github.com/mermaid-js/me
> `optional` **bindFunctions**: (`element`) => `void` > `optional` **bindFunctions**: (`element`) => `void`
Defined in: [packages/mermaid/src/types.ts:120](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L120) Defined in: [packages/mermaid/src/types.ts:132](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L132)
Bind function to be called after the svg has been inserted into the DOM. Bind function to be called after the svg has been inserted into the DOM.
This is necessary for adding event listeners to the elements in the svg. This is necessary for adding event listeners to the elements in the svg.
@@ -45,7 +45,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
> **diagramType**: `string` > **diagramType**: `string`
Defined in: [packages/mermaid/src/types.ts:110](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L110) Defined in: [packages/mermaid/src/types.ts:122](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L122)
The diagram type, e.g. 'flowchart', 'sequence', etc. The diagram type, e.g. 'flowchart', 'sequence', etc.
@@ -55,6 +55,6 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
> **svg**: `string` > **svg**: `string`
Defined in: [packages/mermaid/src/types.ts:106](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L106) Defined in: [packages/mermaid/src/types.ts:118](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L118)
The svg code for the rendered graph. The svg code for the rendered graph.

View File

@@ -57,6 +57,8 @@ To add an integration to this list, see the [Integrations - create page](./integ
- [GitHub Writer](https://github.com/ckeditor/github-writer) - [GitHub Writer](https://github.com/ckeditor/github-writer)
- [SVG diagram generator](https://github.com/SimonKenyonShepard/mermaidjs-github-svg-generator) - [SVG diagram generator](https://github.com/SimonKenyonShepard/mermaidjs-github-svg-generator)
- [GitLab](https://docs.gitlab.com/ee/user/markdown.html#diagrams-and-flowcharts) ✅ - [GitLab](https://docs.gitlab.com/ee/user/markdown.html#diagrams-and-flowcharts) ✅
- [GNU Octave](https://octave.org/) ✅
- [octave_mermaid_js](https://github.com/CNOCTAVE/octave_mermaid_js) ✅
- [Mermaid Plugin for JetBrains IDEs](https://plugins.jetbrains.com/plugin/20146-mermaid) - [Mermaid Plugin for JetBrains IDEs](https://plugins.jetbrains.com/plugin/20146-mermaid)
- [MonsterWriter](https://www.monsterwriter.com/) ✅ - [MonsterWriter](https://www.monsterwriter.com/) ✅
- [Joplin](https://joplinapp.org) ✅ - [Joplin](https://joplinapp.org) ✅
@@ -272,6 +274,7 @@ Communication tools and platforms
- [reveal.js-mermaid-plugin](https://github.com/ludwick/reveal.js-mermaid-plugin) - [reveal.js-mermaid-plugin](https://github.com/ludwick/reveal.js-mermaid-plugin)
- [Reveal CK](https://github.com/jedcn/reveal-ck) - [Reveal CK](https://github.com/jedcn/reveal-ck)
- [reveal-ck-mermaid-plugin](https://github.com/tmtm/reveal-ck-mermaid-plugin) - [reveal-ck-mermaid-plugin](https://github.com/tmtm/reveal-ck-mermaid-plugin)
- [speccharts: Turn your test suites into specification diagrams](https://github.com/arnaudrenaud/speccharts)
- [Vitepress Plugin](https://github.com/sametcn99/vitepress-mermaid-renderer) - [Vitepress Plugin](https://github.com/sametcn99/vitepress-mermaid-renderer)
<!--- cspell:ignore Blazorade HueHive ---> <!--- cspell:ignore Blazorade HueHive --->

View File

@@ -29,7 +29,6 @@ Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an accoun
- **Plugins** - A plugin system for extending the functionality of Mermaid. - **Plugins** - A plugin system for extending the functionality of Mermaid.
Official Mermaid Chart plugins: Official Mermaid Chart plugins:
- [Mermaid Chart GPT](https://chatgpt.com/g/g-684cc36f30208191b21383b88650a45d-mermaid-chart-diagrams-and-charts) - [Mermaid Chart GPT](https://chatgpt.com/g/g-684cc36f30208191b21383b88650a45d-mermaid-chart-diagrams-and-charts)
- [Confluence](https://marketplace.atlassian.com/apps/1234056/mermaid-chart-for-confluence?hosting=cloud&tab=overview) - [Confluence](https://marketplace.atlassian.com/apps/1234056/mermaid-chart-for-confluence?hosting=cloud&tab=overview)
- [Jira](https://marketplace.atlassian.com/apps/1234810/mermaid-chart-for-jira?tab=overview&hosting=cloud) - [Jira](https://marketplace.atlassian.com/apps/1234810/mermaid-chart-for-jira?tab=overview&hosting=cloud)
@@ -48,7 +47,7 @@ Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an accoun
## Plans ## Plans
- **Free** - A free plan that includes three diagrams. - **Free** - A free plan that includes six diagrams.
- **Pro** - A paid plan that includes unlimited diagrams, access to the collaboration feature, and more. - **Pro** - A paid plan that includes unlimited diagrams, access to the collaboration feature, and more.

View File

@@ -35,13 +35,11 @@ The Mermaid Chart team is excited to introduce a new Visual Editor for Flowchart
Learn more: Learn more:
- Visual Editor For Flowcharts - Visual Editor For Flowcharts
- [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-releases-new-visual-editor-for-flowcharts) - [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-releases-new-visual-editor-for-flowcharts)
- [Demo video](https://www.youtube.com/watch?v=5aja0gijoO0) - [Demo video](https://www.youtube.com/watch?v=5aja0gijoO0)
- Visual Editor For Sequence diagrams - Visual Editor For Sequence diagrams
- [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-unveils-visual-editor-for-sequence-diagrams) - [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-unveils-visual-editor-for-sequence-diagrams)
- [Demo video](https://youtu.be/imc2u5_N6Dc) - [Demo video](https://youtu.be/imc2u5_N6Dc)

View File

@@ -6,6 +6,18 @@
# Blog # Blog
## [The Essential Guide to Mermaid Chart Plugin for VS Code \[08/2025\]](https://docs.mermaidchart.com/blog/posts/the-essential-guide-to-mermaid-chart-plugin-for-vs-code-08-2025)
9/9/2025 • 5 mins
Creating diagrams in VS Code has never been easier—the Mermaid VS Code plugin transforms text-based syntax into clear, professional visuals right inside your editor. With live previews, smart editing, and AI-powered diagram generation, it removes the friction from visualization so you can focus on coding.
## [How to Create Perfect Flowcharts Using AI in 2025 Step-by-Step Guide](https://docs.mermaidchart.com/blog/posts/how-to-create-perfect-flowcharts-using-ai-in-2025-step-by-step-guide)
7/22/2025 • 8 mins
In 2025, AI tools make creating flowcharts faster and easier than ever. With Mermaids AI flowchart generator, you can turn plain text into clear, accurate diagrams in seconds. This guide walks through how it works and how to get the most out of it for technical and business workflows alike.
## [Mermaid introduces the Visual Editor for Entity Relationship diagrams](https://docs.mermaidchart.com/blog/posts/mermaid-introduces-the-visual-editor-for-entity-relationship-diagrams) ## [Mermaid introduces the Visual Editor for Entity Relationship diagrams](https://docs.mermaidchart.com/blog/posts/mermaid-introduces-the-visual-editor-for-entity-relationship-diagrams)
7/15/2025 • 7 mins 7/15/2025 • 7 mins

View File

@@ -194,7 +194,7 @@ architecture-beta
## Icons ## Icons
By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`. By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`.
Users can use any of the 200,000+ icons available in iconify.design, or [add custom icons](../config/icons.md). Users can use any of the 200,000+ icons available in iconify.design, or add other custom icons, by [registering an icon pack](../config/icons.md).
After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack. After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack.

View File

@@ -139,7 +139,6 @@ The following unfinished features are not supported in the short term.
- [ ] Legend - [ ] Legend
- [x] System Context - [x] System Context
- [x] Person(alias, label, ?descr, ?sprite, ?tags, $link) - [x] Person(alias, label, ?descr, ?sprite, ?tags, $link)
- [x] Person_Ext - [x] Person_Ext
- [x] System(alias, label, ?descr, ?sprite, ?tags, $link) - [x] System(alias, label, ?descr, ?sprite, ?tags, $link)
@@ -153,7 +152,6 @@ The following unfinished features are not supported in the short term.
- [x] System_Boundary - [x] System_Boundary
- [x] Container diagram - [x] Container diagram
- [x] Container(alias, label, ?techn, ?descr, ?sprite, ?tags, $link) - [x] Container(alias, label, ?techn, ?descr, ?sprite, ?tags, $link)
- [x] ContainerDb - [x] ContainerDb
- [x] ContainerQueue - [x] ContainerQueue
@@ -163,7 +161,6 @@ The following unfinished features are not supported in the short term.
- [x] Container_Boundary(alias, label, ?tags, $link) - [x] Container_Boundary(alias, label, ?tags, $link)
- [x] Component diagram - [x] Component diagram
- [x] Component(alias, label, ?techn, ?descr, ?sprite, ?tags, $link) - [x] Component(alias, label, ?techn, ?descr, ?sprite, ?tags, $link)
- [x] ComponentDb - [x] ComponentDb
- [x] ComponentQueue - [x] ComponentQueue
@@ -172,18 +169,15 @@ The following unfinished features are not supported in the short term.
- [x] ComponentQueue_Ext - [x] ComponentQueue_Ext
- [x] Dynamic diagram - [x] Dynamic diagram
- [x] RelIndex(index, from, to, label, ?tags, $link) - [x] RelIndex(index, from, to, label, ?tags, $link)
- [x] Deployment diagram - [x] Deployment diagram
- [x] Deployment_Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link) - [x] Deployment_Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link)
- [x] Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link): short name of Deployment_Node() - [x] Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link): short name of Deployment_Node()
- [x] Node_L(alias, label, ?type, ?descr, ?sprite, ?tags, $link): left aligned Node() - [x] Node_L(alias, label, ?type, ?descr, ?sprite, ?tags, $link): left aligned Node()
- [x] Node_R(alias, label, ?type, ?descr, ?sprite, ?tags, $link): right aligned Node() - [x] Node_R(alias, label, ?type, ?descr, ?sprite, ?tags, $link): right aligned Node()
- [x] Relationship Types - [x] Relationship Types
- [x] Rel(from, to, label, ?techn, ?descr, ?sprite, ?tags, $link) - [x] Rel(from, to, label, ?techn, ?descr, ?sprite, ?tags, $link)
- [x] BiRel (bidirectional relationship) - [x] BiRel (bidirectional relationship)
- [x] Rel_U, Rel_Up - [x] Rel_U, Rel_Up

View File

@@ -21,7 +21,7 @@ title: Animal example
classDiagram classDiagram
note "From Duck till Zebra" note "From Duck till Zebra"
Animal <|-- Duck Animal <|-- Duck
note for Duck "can fly\ncan swim\ncan dive\ncan help in debugging" note for Duck "can fly<br>can swim<br>can dive<br>can help in debugging"
Animal <|-- Fish Animal <|-- Fish
Animal <|-- Zebra Animal <|-- Zebra
Animal : +int age Animal : +int age
@@ -50,7 +50,7 @@ title: Animal example
classDiagram classDiagram
note "From Duck till Zebra" note "From Duck till Zebra"
Animal <|-- Duck Animal <|-- Duck
note for Duck "can fly\ncan swim\ncan dive\ncan help in debugging" note for Duck "can fly<br>can swim<br>can dive<br>can help in debugging"
Animal <|-- Fish Animal <|-- Fish
Animal <|-- Zebra Animal <|-- Zebra
Animal : +int age Animal : +int age

View File

@@ -360,7 +360,8 @@ gantt
weekday monday weekday monday
``` ```
> **Warning** > `millisecond` and `second` support was added in v10.3.0 > **Warning**
> `millisecond` and `second` support was added in v10.3.0
## Output in compact mode ## Output in compact mode

View File

@@ -194,46 +194,6 @@ sequenceDiagram
Bob->>Alice: Queue response Bob->>Alice: Queue response
``` ```
### Icon
If you want to use a custom icon for a participant, use the JSON configuration syntax as shown below. The `icon` value can be a FontAwesome icon name, emoji, or other supported icon identifier.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "icon", "icon": "fa:bell" }
participant Bob
Alice->>Bob: Icon participant
Bob->>Alice: Response to icon
```
```mermaid
sequenceDiagram
participant Alice@{ "type" : "icon", "icon": "fa:bell" }
participant Bob
Alice->>Bob: Icon participant
Bob->>Alice: Response to icon
```
### Image
If you want to use a custom image for a participant, use the JSON configuration syntax as shown below. The `image` value should be a valid image URL.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
participant Bob
Alice->>Bob: Image participant
Bob->>Alice: Response to image
```
```mermaid
sequenceDiagram
participant Alice@{ "type" : "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
participant Bob
Alice->>Bob: Image participant
Bob->>Alice: Response to image
```
### Aliases ### Aliases
The actor can have a convenient identifier and a descriptive label. The actor can have a convenient identifier and a descriptive label.
@@ -369,7 +329,11 @@ Messages can be of two displayed either solid or with a dotted line.
[Actor][Arrow][Actor]:Message text [Actor][Arrow][Actor]:Message text
``` ```
There are ten types of arrows currently supported: Lines can be solid or dotted, and can end with various types of arrowheads, crosses, or open arrows.
#### Supported Arrow Types
**Standard Arrow Types**
| Type | Description | | Type | Description |
| -------- | ---------------------------------------------------- | | -------- | ---------------------------------------------------- |
@@ -384,6 +348,58 @@ There are ten types of arrows currently supported:
| `-)` | Solid line with an open arrow at the end (async) | | `-)` | Solid line with an open arrow at the end (async) |
| `--)` | Dotted line with a open arrow at the end (async) | | `--)` | Dotted line with a open arrow at the end (async) |
**Half-Arrows (v\<MERMAID_RELEASE_VERSION>+)**
The following half-arrow types are supported for more expressive sequence diagrams. Both solid and dotted variants are available by increasing the number of dashes (`-` → `--`).
---
| Type | Description |
| ------- | ---------------------------------------------------- |
| `-\|\` | Solid line with top half arrowhead |
| `--\|\` | Dotted line with top half arrowhead |
| `-\|/` | Solid line with bottom half arrowhead |
| `--\|/` | Dotted line with bottom half arrowhead |
| `/\|-` | Solid line with reverse top half arrowhead |
| `/\|--` | Dotted line with reverse top half arrowhead |
| `\\-` | Solid line with reverse bottom half arrowhead |
| `\\--` | Dotted line with reverse bottom half arrowhead |
| `-\\` | Solid line with top stick half arrowhead |
| `--\\` | Dotted line with top stick half arrowhead |
| `-//` | Solid line with bottom stick half arrowhead |
| `--//` | Dotted line with bottom stick half arrowhead |
| `//-` | Solid line with reverse top stick half arrowhead |
| `//--` | Dotted line with reverse top stick half arrowhead |
| `\\-` | Solid line with reverse bottom stick half arrowhead |
| `\\--` | Dotted line with reverse bottom stick half arrowhead |
## Central Connections (v\<MERMAID_RELEASE_VERSION>+)
Mermaid sequence diagrams support **central lifeline connections** using a `()`.
This is useful to represent messages or signals that connect to a central point, rather than from one actor directly to another.
To indicate a central connection, append `()` to the arrow syntax.
#### Basic Syntax
```mermaid-example
sequenceDiagram
participant Alice
participant John
Alice->>()John: Hello John
Alice()->>John: How are you?
John()->>()Alice: Great!
```
```mermaid
sequenceDiagram
participant Alice
participant John
Alice->>()John: Hello John
Alice()->>John: How are you?
John()->>()Alice: Great!
```
## Activations ## Activations
It is possible to activate and deactivate an actor. (de)activation can be dedicated declarations: It is possible to activate and deactivate an actor. (de)activation can be dedicated declarations:

View File

@@ -63,73 +63,73 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"@applitools/eyes-cypress": "^3.44.9", "@applitools/eyes-cypress": "^3.56.3",
"@argos-ci/cypress": "^5.0.2", "@argos-ci/cypress": "^6.2.1",
"@changesets/changelog-github": "^0.5.1", "@changesets/changelog-github": "^0.5.1",
"@changesets/cli": "^2.27.12", "@changesets/cli": "^2.29.7",
"@cspell/eslint-plugin": "^8.19.4", "@cspell/eslint-plugin": "^9.3.0",
"@cypress/code-coverage": "^3.12.49", "@cypress/code-coverage": "^3.14.7",
"@eslint/js": "^9.26.0", "@eslint/js": "^9.26.0",
"@rollup/plugin-typescript": "^12.1.2", "@rollup/plugin-typescript": "^12.1.4",
"@types/cors": "^2.8.17", "@types/cors": "^2.8.19",
"@types/express": "^5.0.0", "@types/express": "^5.0.5",
"@types/js-yaml": "^4.0.9", "@types/js-yaml": "^4.0.9",
"@types/jsdom": "^21.1.7", "@types/jsdom": "^21.1.7",
"@types/lodash": "^4.17.15", "@types/lodash": "^4.17.20",
"@types/mdast": "^4.0.4", "@types/mdast": "^4.0.4",
"@types/node": "^22.13.5", "@types/node": "^22.19.0",
"@types/rollup-plugin-visualizer": "^5.0.3", "@types/rollup-plugin-visualizer": "^5.0.3",
"@vitest/coverage-v8": "^3.0.6", "@vitest/coverage-v8": "^3.2.4",
"@vitest/spy": "^3.0.6", "@vitest/spy": "^3.2.4",
"@vitest/ui": "^3.0.6", "@vitest/ui": "^3.2.4",
"ajv": "^8.17.1", "ajv": "^8.17.1",
"chokidar": "3.6.0", "chokidar": "3.6.0",
"concurrently": "^9.1.2", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"cpy-cli": "^5.0.0", "cpy-cli": "^5.0.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"cspell": "^9.1.3", "cspell": "^9.3.0",
"cypress": "^14.5.1", "cypress": "^14.5.4",
"cypress-image-snapshot": "^4.0.1", "cypress-image-snapshot": "^4.0.1",
"cypress-split": "^1.24.14", "cypress-split": "^1.24.25",
"esbuild": "^0.25.0", "esbuild": "^0.25.12",
"eslint": "^9.26.0", "eslint": "^9.26.0",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"eslint-plugin-cypress": "^4.3.0", "eslint-plugin-cypress": "^5.2.0",
"eslint-plugin-html": "^8.1.3", "eslint-plugin-html": "^8.1.3",
"eslint-plugin-jest": "^28.14.0", "eslint-plugin-jest": "^29.0.1",
"eslint-plugin-jsdoc": "^50.8.0", "eslint-plugin-jsdoc": "^61.1.12",
"eslint-plugin-json": "^4.0.1", "eslint-plugin-json": "^4.0.1",
"eslint-plugin-lodash": "^8.0.0", "eslint-plugin-lodash": "^8.0.0",
"eslint-plugin-markdown": "^5.1.0", "eslint-plugin-markdown": "^5.1.0",
"eslint-plugin-no-only-tests": "^3.3.0", "eslint-plugin-no-only-tests": "^3.3.0",
"eslint-plugin-tsdoc": "^0.4.0", "eslint-plugin-tsdoc": "^0.4.0",
"eslint-plugin-unicorn": "^59.0.1", "eslint-plugin-unicorn": "^62.0.0",
"express": "^5.1.0", "express": "^5.1.0",
"globals": "^16.0.0", "globals": "^16.4.0",
"globby": "^14.0.2", "globby": "^14.1.0",
"husky": "^9.1.7", "husky": "^9.1.7",
"jest": "^30.0.4", "jest": "^30.1.3",
"jison": "^0.4.18", "jison": "^0.4.18",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"jsdom": "^26.1.0", "jsdom": "^26.1.0",
"langium-cli": "3.3.0", "langium-cli": "3.3.0",
"lint-staged": "^16.1.2", "lint-staged": "^16.1.6",
"markdown-table": "^3.0.4", "markdown-table": "^3.0.4",
"nyc": "^17.1.0", "nyc": "^17.1.0",
"path-browserify": "^1.0.1", "path-browserify": "^1.0.1",
"prettier": "^3.5.2", "prettier": "^3.6.2",
"prettier-plugin-jsdoc": "^1.3.2", "prettier-plugin-jsdoc": "^1.3.3",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"rollup-plugin-visualizer": "^6.0.3", "rollup-plugin-visualizer": "^6.0.5",
"start-server-and-test": "^2.0.10", "start-server-and-test": "^2.1.2",
"tslib": "^2.8.1", "tslib": "^2.8.1",
"tsx": "^4.7.3", "tsx": "^4.20.6",
"typescript": "~5.7.3", "typescript": "~5.7.3",
"typescript-eslint": "^8.38.0", "typescript-eslint": "^8.38.0",
"vite": "^7.0.3", "vite": "^7.0.8",
"vite-plugin-istanbul": "^7.0.0", "vite-plugin-istanbul": "^7.0.0",
"vitest": "^3.0.6" "vitest": "^3.2.4"
}, },
"nyc": { "nyc": {
"report-dir": "coverage/cypress" "report-dir": "coverage/cypress"

View File

@@ -37,12 +37,12 @@
] ]
}, },
"dependencies": { "dependencies": {
"@braintree/sanitize-url": "^7.0.4", "@braintree/sanitize-url": "^7.1.1",
"d3": "^7.9.0", "d3": "^7.9.0",
"khroma": "^2.1.0" "khroma": "^2.1.0"
}, },
"devDependencies": { "devDependencies": {
"concurrently": "^9.1.2", "concurrently": "^9.2.1",
"mermaid": "workspace:*", "mermaid": "workspace:*",
"rimraf": "^6.0.1" "rimraf": "^6.0.1"
}, },

View File

@@ -1,5 +1,16 @@
# @mermaid-js/layout-elk # @mermaid-js/layout-elk
## 0.2.0
### Minor Changes
- [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes
### Patch Changes
- Updated dependencies [[`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800), [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20), [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05), [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8)]:
- mermaid@11.11.0
## 0.1.9 ## 0.1.9
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@mermaid-js/layout-elk", "name": "@mermaid-js/layout-elk",
"version": "0.1.9", "version": "0.2.0",
"description": "ELK layout engine for mermaid", "description": "ELK layout engine for mermaid",
"module": "dist/mermaid-layout-elk.core.mjs", "module": "dist/mermaid-layout-elk.core.mjs",
"types": "dist/layouts.d.ts", "types": "dist/layouts.d.ts",
@@ -18,7 +18,9 @@
"elk", "elk",
"mermaid" "mermaid"
], ],
"scripts": {}, "scripts": {
"clean": "rimraf dist"
},
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/mermaid-js/mermaid" "url": "https://github.com/mermaid-js/mermaid"

View File

@@ -67,7 +67,22 @@ export const render = async (
// Add the element to the DOM // Add the element to the DOM
if (!node.isGroup) { if (!node.isGroup) {
const child = node as NodeWithVertex; // const child = node as NodeWithVertex;
const child: NodeWithVertex = {
id: node.id,
width: node.width,
height: node.height,
// Store the original node data for later use
label: node.label,
isGroup: node.isGroup,
shape: node.shape,
padding: node.padding,
cssClasses: node.cssClasses,
cssStyles: node.cssStyles,
look: node.look,
// Include parentId for subgraph processing
parentId: node.parentId,
};
graph.children.push(child); graph.children.push(child);
nodeDb[node.id] = node; nodeDb[node.id] = node;
@@ -150,7 +165,7 @@ export const render = async (
domId: { node: () => any; attr: (arg0: string, arg1: string) => void }; domId: { node: () => any; attr: (arg0: string, arg1: string) => void };
}) { }) {
if (node) { if (node) {
nodeDb[node.id] = node; nodeDb[node.id] ??= {};
nodeDb[node.id].offset = { nodeDb[node.id].offset = {
posX: node.x + relX, posX: node.x + relX,
posY: node.y + relY, posY: node.y + relY,
@@ -860,11 +875,13 @@ export const render = async (
log.info('APA01 layout result:', JSON.stringify(g, null, 2)); log.info('APA01 layout result:', JSON.stringify(g, null, 2));
} catch (error) { } catch (error) {
log.error('APA01 ELK layout error:', error); log.error('APA01 ELK layout error:', error);
log.error('APA01 elkGraph that caused error:', JSON.stringify(elkGraph, null, 2));
throw error; throw error;
} }
// debugger; // debugger;
await drawNodes(0, 0, g.children, svg, subGraphsEl, 0); await drawNodes(0, 0, g.children, svg, subGraphsEl, 0);
g.edges?.map( g.edges?.map(
(edge: { (edge: {
sources: (string | number)[]; sources: (string | number)[];

View File

@@ -0,0 +1,12 @@
# @mermaid-js/layout-tidy-tree
## 0.2.0
### Minor Changes
- [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes
### Patch Changes
- Updated dependencies [[`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800), [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20), [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05), [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8)]:
- mermaid@11.11.0

View File

@@ -1,6 +1,6 @@
{ {
"name": "@mermaid-js/layout-tidy-tree", "name": "@mermaid-js/layout-tidy-tree",
"version": "0.1.0", "version": "0.2.0",
"description": "Tidy-tree layout engine for mermaid", "description": "Tidy-tree layout engine for mermaid",
"module": "dist/mermaid-layout-tidy-tree.core.mjs", "module": "dist/mermaid-layout-tidy-tree.core.mjs",
"types": "dist/layouts.d.ts", "types": "dist/layouts.d.ts",
@@ -19,7 +19,9 @@
"mermaid", "mermaid",
"layout" "layout"
], ],
"scripts": {}, "scripts": {
"clean": "rimraf dist"
},
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/mermaid-js/mermaid" "url": "https://github.com/mermaid-js/mermaid"

View File

@@ -33,7 +33,7 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@zenuml/core": "^3.35.2" "@zenuml/core": "^3.41.6"
}, },
"devDependencies": { "devDependencies": {
"mermaid": "workspace:^" "mermaid": "workspace:^"

View File

@@ -1,5 +1,44 @@
# mermaid # mermaid
## 11.12.1
### Patch Changes
- [#7107](https://github.com/mermaid-js/mermaid/pull/7107) [`cbf8946`](https://github.com/mermaid-js/mermaid/commit/cbf89462acecac7a06f19843e8d48cb137df0753) Thanks [@shubhamparikh2704](https://github.com/shubhamparikh2704)! - fix: Updated the dependency dagre-d3-es to 7.0.13 to fix GHSA-cc8p-78qf-8p7q
## 11.12.0
### Minor Changes
- [#6921](https://github.com/mermaid-js/mermaid/pull/6921) [`764b315`](https://github.com/mermaid-js/mermaid/commit/764b315dc16d0359add7c6b8e3ef7592e9bdc09c) Thanks [@quilicicf](https://github.com/quilicicf)! - feat: Add IDs in architecture diagrams
### Patch Changes
- [#6950](https://github.com/mermaid-js/mermaid/pull/6950) [`a957908`](https://github.com/mermaid-js/mermaid/commit/a9579083bfba367a4f4678547ec37ed7b61b9f5b) Thanks [@shubhamparikh2704](https://github.com/shubhamparikh2704)! - chore: Fix mindmap rendering in docs and apply tidytree layout
- [#6826](https://github.com/mermaid-js/mermaid/pull/6826) [`1d36810`](https://github.com/mermaid-js/mermaid/commit/1d3681053b9168354e48e5763023b6305cd1ca72) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Ensure edge label color is applied when using classDef with edge IDs
- [#6945](https://github.com/mermaid-js/mermaid/pull/6945) [`d318f1a`](https://github.com/mermaid-js/mermaid/commit/d318f1a13cd7429334a29c70e449074ec1cb9f68) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Resolve gantt chart crash due to invalid array length
- [#6918](https://github.com/mermaid-js/mermaid/pull/6918) [`cfe9238`](https://github.com/mermaid-js/mermaid/commit/cfe9238882cbe95416db1feea3112456a71b6aaf) Thanks [@shubhamparikh2704](https://github.com/shubhamparikh2704)! - chore: revert marked dependency from ^15.0.7 to ^16.0.0
- Reverted marked package version to ^16.0.0 for better compatibility
- This is a dependency update that maintains API compatibility
- All tests pass with the updated version
## 11.11.0
### Minor Changes
- [#6704](https://github.com/mermaid-js/mermaid/pull/6704) [`012530e`](https://github.com/mermaid-js/mermaid/commit/012530e98e9b8b80962ab270b6bb3b6d9f6ada05) Thanks [@omkarht](https://github.com/omkarht)! - feat: Added support for new participant types (`actor`, `boundary`, `control`, `entity`, `database`, `collections`, `queue`) in `sequenceDiagram`.
- [#6802](https://github.com/mermaid-js/mermaid/pull/6802) [`c8e5027`](https://github.com/mermaid-js/mermaid/commit/c8e50276e877c4de7593a09ec458c99353e65af8) Thanks [@darshanr0107](https://github.com/darshanr0107)! - feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes
### Patch Changes
- [#6905](https://github.com/mermaid-js/mermaid/pull/6905) [`33bc4a0`](https://github.com/mermaid-js/mermaid/commit/33bc4a0b4e2ca6d937bb0a8c4e2081b1362b2800) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Render newlines as spaces in class diagrams
- [#6886](https://github.com/mermaid-js/mermaid/pull/6886) [`e0b45c2`](https://github.com/mermaid-js/mermaid/commit/e0b45c2d2b41c2a9038bf87646fa3ccd7560eb20) Thanks [@darshanr0107](https://github.com/darshanr0107)! - fix: Handle arrows correctly when auto number is enabled
## 11.10.0 ## 11.10.0
### Minor Changes ### Minor Changes
@@ -154,7 +193,6 @@
### Minor Changes ### Minor Changes
- [#6408](https://github.com/mermaid-js/mermaid/pull/6408) [`ad65313`](https://github.com/mermaid-js/mermaid/commit/ad653138e16765d095613a6e5de86dc5e52ac8f0) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - fix: restore curve type configuration functionality for flowcharts. This fixes the issue where curve type settings were not being applied when configured through any of the following methods: - [#6408](https://github.com/mermaid-js/mermaid/pull/6408) [`ad65313`](https://github.com/mermaid-js/mermaid/commit/ad653138e16765d095613a6e5de86dc5e52ac8f0) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - fix: restore curve type configuration functionality for flowcharts. This fixes the issue where curve type settings were not being applied when configured through any of the following methods:
- Config - Config
- Init directive (%%{ init: { 'flowchart': { 'curve': '...' } } }%%) - Init directive (%%{ init: { 'flowchart': { 'curve': '...' } } }%%)
- LinkStyle command (linkStyle default interpolate ...) - LinkStyle command (linkStyle default interpolate ...)
@@ -173,14 +211,12 @@
### Minor Changes ### Minor Changes
- [#6187](https://github.com/mermaid-js/mermaid/pull/6187) [`7809b5a`](https://github.com/mermaid-js/mermaid/commit/7809b5a93fae127f45727071f5ff14325222c518) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Flowchart new syntax for node metadata bugs - [#6187](https://github.com/mermaid-js/mermaid/pull/6187) [`7809b5a`](https://github.com/mermaid-js/mermaid/commit/7809b5a93fae127f45727071f5ff14325222c518) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Flowchart new syntax for node metadata bugs
- Incorrect label mapping for nodes when using `&` - Incorrect label mapping for nodes when using `&`
- Syntax error when `}` with trailing spaces before new line - Syntax error when `}` with trailing spaces before new line
- [#6136](https://github.com/mermaid-js/mermaid/pull/6136) [`ec0d9c3`](https://github.com/mermaid-js/mermaid/commit/ec0d9c389aa6018043187654044c1e0b5aa4f600) Thanks [@knsv](https://github.com/knsv)! - Adding support for animation of flowchart edges - [#6136](https://github.com/mermaid-js/mermaid/pull/6136) [`ec0d9c3`](https://github.com/mermaid-js/mermaid/commit/ec0d9c389aa6018043187654044c1e0b5aa4f600) Thanks [@knsv](https://github.com/knsv)! - Adding support for animation of flowchart edges
- [#6373](https://github.com/mermaid-js/mermaid/pull/6373) [`05bdf0e`](https://github.com/mermaid-js/mermaid/commit/05bdf0e20e2629fe77513218fbd4e28e65f75882) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Upgrade Requirement and ER diagram to use the common renderer flow - [#6373](https://github.com/mermaid-js/mermaid/pull/6373) [`05bdf0e`](https://github.com/mermaid-js/mermaid/commit/05bdf0e20e2629fe77513218fbd4e28e65f75882) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Upgrade Requirement and ER diagram to use the common renderer flow
- Added support for directions - Added support for directions
- Added support for hand drawn look - Added support for hand drawn look

View File

@@ -1,6 +1,6 @@
{ {
"name": "mermaid", "name": "mermaid",
"version": "11.10.0", "version": "11.12.1",
"description": "Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.", "description": "Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.",
"type": "module", "type": "module",
"module": "./dist/mermaid.core.mjs", "module": "./dist/mermaid.core.mjs",
@@ -67,32 +67,32 @@
] ]
}, },
"dependencies": { "dependencies": {
"@braintree/sanitize-url": "^7.0.4", "@braintree/sanitize-url": "^7.1.1",
"@iconify/utils": "^3.0.1", "@iconify/utils": "^3.0.2",
"@mermaid-js/parser": "workspace:^", "@mermaid-js/parser": "workspace:^",
"@types/d3": "^7.4.3", "@types/d3": "^7.4.3",
"cytoscape": "^3.29.3", "cytoscape": "^3.33.1",
"cytoscape-cose-bilkent": "^4.1.0", "cytoscape-cose-bilkent": "^4.1.0",
"cytoscape-fcose": "^2.2.0", "cytoscape-fcose": "^2.2.0",
"d3": "^7.9.0", "d3": "^7.9.0",
"d3-sankey": "^0.12.3", "d3-sankey": "^0.12.3",
"dagre-d3-es": "7.0.11", "dagre-d3-es": "7.0.13",
"dayjs": "^1.11.13", "dayjs": "^1.11.19",
"dompurify": "^3.2.5", "dompurify": "^3.3.0",
"katex": "^0.16.22", "katex": "^0.16.25",
"khroma": "^2.1.0", "khroma": "^2.1.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"marked": "^16.0.0", "marked": "^16.3.0",
"roughjs": "^4.6.6", "roughjs": "^4.6.6",
"stylis": "^4.3.6", "stylis": "^4.3.6",
"ts-dedent": "^2.2.0", "ts-dedent": "^2.2.0",
"uuid": "^11.1.0" "uuid": "^11.1.0"
}, },
"devDependencies": { "devDependencies": {
"@adobe/jsonschema2md": "^8.0.2", "@adobe/jsonschema2md": "^8.0.7",
"@iconify/types": "^2.0.0", "@iconify/types": "^2.0.0",
"@types/cytoscape": "^3.21.9", "@types/cytoscape": "^3.21.9",
"@types/cytoscape-fcose": "^2.2.4", "@types/cytoscape-fcose": "^2.2.5",
"@types/d3-sankey": "^0.12.4", "@types/d3-sankey": "^0.12.4",
"@types/d3-scale": "^4.0.9", "@types/d3-scale": "^4.0.9",
"@types/d3-scale-chromatic": "^3.1.0", "@types/d3-scale-chromatic": "^3.1.0",
@@ -101,34 +101,34 @@
"@types/jsdom": "^21.1.7", "@types/jsdom": "^21.1.7",
"@types/katex": "^0.16.7", "@types/katex": "^0.16.7",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/micromatch": "^4.0.9", "@types/micromatch": "^4.0.10",
"@types/stylis": "^4.2.7", "@types/stylis": "^4.2.7",
"@types/uuid": "^10.0.0", "@types/uuid": "^10.0.0",
"ajv": "^8.17.1", "ajv": "^8.17.1",
"canvas": "^3.1.0", "canvas": "^3.2.0",
"chokidar": "3.6.0", "chokidar": "3.6.0",
"concurrently": "^9.1.2", "concurrently": "^9.2.1",
"csstree-validator": "^4.0.1", "csstree-validator": "^4.0.1",
"globby": "^14.0.2", "globby": "^14.1.0",
"jison": "^0.4.18", "jison": "^0.4.18",
"js-base64": "^3.7.7", "js-base64": "^3.7.8",
"jsdom": "^26.1.0", "jsdom": "^26.1.0",
"json-schema-to-typescript": "^15.0.4", "json-schema-to-typescript": "^15.0.4",
"micromatch": "^4.0.8", "micromatch": "^4.0.8",
"path-browserify": "^1.0.1", "path-browserify": "^1.0.1",
"prettier": "^3.5.2", "prettier": "^3.6.2",
"remark": "^15.0.1", "remark": "^15.0.1",
"remark-frontmatter": "^5.0.0", "remark-frontmatter": "^5.0.0",
"remark-gfm": "^4.0.1", "remark-gfm": "^4.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"start-server-and-test": "^2.0.10", "start-server-and-test": "^2.1.2",
"type-fest": "^4.35.0", "type-fest": "^4.41.0",
"typedoc": "^0.28.9", "typedoc": "^0.28.14",
"typedoc-plugin-markdown": "^4.8.0", "typedoc-plugin-markdown": "^4.8.1",
"typescript": "~5.7.3", "typescript": "~5.7.3",
"unist-util-flatmap": "^1.0.0", "unist-util-flatmap": "^1.0.0",
"unist-util-visit": "^5.0.0", "unist-util-visit": "^5.0.0",
"vitepress": "^1.0.2", "vitepress": "^1.6.4",
"vitepress-plugin-search": "1.0.4-alpha.22" "vitepress-plugin-search": "1.0.4-alpha.22"
}, },
"files": [ "files": [

View File

@@ -72,7 +72,7 @@ export const addDiagrams = () => {
} }
); );
if (includeLargeFeatures) { if (injected.includeLargeFeatures) {
registerLazyLoadedDiagrams(flowchartElk, mindmap, architecture); registerLazyLoadedDiagrams(flowchartElk, mindmap, architecture);
} }

View File

@@ -0,0 +1,58 @@
import c4Db from '../c4Db.js';
import c4 from './c4Diagram.jison';
import { setConfig } from '../../../config.js';
setConfig({
securityLevel: 'strict',
});
describe.each([
['Component', 'component'],
['ComponentDb', 'component_db'],
['ComponentQueue', 'component_queue'],
['Component_Ext', 'external_component'],
['ComponentDb_Ext', 'external_component_db'],
['ComponentQueue_Ext', 'external_component_queue'],
])('parsing a C4 %s', function (macroName, elementName) {
beforeEach(function () {
c4.parser.yy = c4Db;
c4.parser.yy.clear();
});
it('should parse a C4 diagram with one Component correctly', function () {
c4.parser.parse(`C4Component
title Component diagram for Internet Banking Component
${macroName}(ComponentAA, "Internet Banking Component", "Technology", "Allows customers to view information about their bank accounts, and make payments.")`);
const yy = c4.parser.yy;
const shapes = yy.getC4ShapeArray();
expect(shapes.length).toBe(1);
const onlyShape = shapes[0];
expect(onlyShape).toMatchObject({
alias: 'ComponentAA',
descr: {
text: 'Allows customers to view information about their bank accounts, and make payments.',
},
label: {
text: 'Internet Banking Component',
},
techn: {
text: 'Technology',
},
typeC4Shape: {
text: elementName,
},
});
});
it('should handle a trailing whitespaces after Component', function () {
const whitespace = ' ';
const rendered = c4.parser.parse(`C4Component${whitespace}
title Component diagram for Internet Banking Component${whitespace}
${macroName}(ComponentAA, "Internet Banking Component", "Technology", "Allows customers to view information about their bank accounts, and make payments.")${whitespace}`);
expect(rendered).toBe(true);
});
});

View File

@@ -158,10 +158,10 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
"UpdateRelStyle" { this.begin("update_rel_style"); return 'UPDATE_REL_STYLE';} "UpdateRelStyle" { this.begin("update_rel_style"); return 'UPDATE_REL_STYLE';}
"UpdateLayoutConfig" { this.begin("update_layout_config"); return 'UPDATE_LAYOUT_CONFIG';} "UpdateLayoutConfig" { this.begin("update_layout_config"); return 'UPDATE_LAYOUT_CONFIG';}
<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext_queue,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config><<EOF>> return "EOF_IN_STRUCT"; <person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext_queue,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext_queue,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config><<EOF>> return "EOF_IN_STRUCT";
<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext_queue,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config>[(][ ]*[,] { this.begin("attribute"); return "ATTRIBUTE_EMPTY";} <person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext_queue,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext_queue,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config>[(][ ]*[,] { this.begin("attribute"); return "ATTRIBUTE_EMPTY";}
<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext_queue,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config>[(] { this.begin("attribute"); } <person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext_queue,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext_queue,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config>[(] { this.begin("attribute"); }
<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext_queue,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config,attribute>[)] { this.popState();this.popState();} <person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext_queue,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext_queue,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,update_el_style,update_rel_style,update_layout_config,attribute>[)] { this.popState();this.popState();}
<attribute>",," { return 'ATTRIBUTE_EMPTY';} <attribute>",," { return 'ATTRIBUTE_EMPTY';}
<attribute>"," { } <attribute>"," { }

View File

@@ -17,6 +17,7 @@ import type {
ClassRelation, ClassRelation,
ClassNode, ClassNode,
ClassNote, ClassNote,
ClassNoteMap,
ClassMap, ClassMap,
NamespaceMap, NamespaceMap,
NamespaceNode, NamespaceNode,
@@ -33,15 +34,16 @@ const sanitizeText = (txt: string) => common.sanitizeText(txt, getConfig());
export class ClassDB implements DiagramDB { export class ClassDB implements DiagramDB {
private relations: ClassRelation[] = []; private relations: ClassRelation[] = [];
private classes = new Map<string, ClassNode>(); private classes: ClassMap = new Map<string, ClassNode>();
private readonly styleClasses = new Map<string, StyleClass>(); private readonly styleClasses = new Map<string, StyleClass>();
private notes: ClassNote[] = []; private notes: ClassNoteMap = new Map<string, ClassNote>();
private interfaces: Interface[] = []; private interfaces: Interface[] = [];
// private static classCounter = 0; // private static classCounter = 0;
private namespaces = new Map<string, NamespaceNode>(); private namespaces = new Map<string, NamespaceNode>();
private namespaceCounter = 0; private namespaceCounter = 0;
private functions: any[] = []; // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
private functions: Function[] = [];
constructor() { constructor() {
this.functions.push(this.setupToolTips.bind(this)); this.functions.push(this.setupToolTips.bind(this));
@@ -124,7 +126,7 @@ export class ClassDB implements DiagramDB {
annotations: [], annotations: [],
styles: [], styles: [],
domId: MERMAID_DOM_ID_PREFIX + name + '-' + classCounter, domId: MERMAID_DOM_ID_PREFIX + name + '-' + classCounter,
} as ClassNode); });
classCounter++; classCounter++;
} }
@@ -155,12 +157,12 @@ export class ClassDB implements DiagramDB {
public clear() { public clear() {
this.relations = []; this.relations = [];
this.classes = new Map(); this.classes = new Map<string, ClassNode>();
this.notes = []; this.notes = new Map<string, ClassNote>();
this.interfaces = []; this.interfaces = [];
this.functions = []; this.functions = [];
this.functions.push(this.setupToolTips.bind(this)); this.functions.push(this.setupToolTips.bind(this));
this.namespaces = new Map(); this.namespaces = new Map<string, NamespaceNode>();
this.namespaceCounter = 0; this.namespaceCounter = 0;
this.direction = 'TB'; this.direction = 'TB';
commonClear(); commonClear();
@@ -178,7 +180,12 @@ export class ClassDB implements DiagramDB {
return this.relations; return this.relations;
} }
public getNotes() { public getNote(id: string | number): ClassNote {
const key = typeof id === 'number' ? `note${id}` : id;
return this.notes.get(key)!;
}
public getNotes(): ClassNoteMap {
return this.notes; return this.notes;
} }
@@ -279,16 +286,19 @@ export class ClassDB implements DiagramDB {
} }
} }
public addNote(text: string, className: string) { public addNote(text: string, className: string): string {
const index = this.notes.size;
const note = { const note = {
id: `note${this.notes.length}`, id: `note${index}`,
class: className, class: className,
text: text, text: text,
index: index,
}; };
this.notes.push(note); this.notes.set(note.id, note);
return note.id;
} }
public cleanupLabel(label: string) { public cleanupLabel(label: string): string {
if (label.startsWith(':')) { if (label.startsWith(':')) {
label = label.substring(1); label = label.substring(1);
} }
@@ -354,7 +364,7 @@ export class ClassDB implements DiagramDB {
}); });
} }
public getTooltip(id: string, namespace?: string) { public getTooltip(id: string, namespace?: string): string | undefined {
if (namespace && this.namespaces.has(namespace)) { if (namespace && this.namespaces.has(namespace)) {
return this.namespaces.get(namespace)!.classes.get(id)!.tooltip; return this.namespaces.get(namespace)!.classes.get(id)!.tooltip;
} }
@@ -534,10 +544,11 @@ export class ClassDB implements DiagramDB {
this.namespaces.set(id, { this.namespaces.set(id, {
id: id, id: id,
classes: new Map(), classes: new Map<string, ClassNode>(),
children: {}, notes: new Map<string, ClassNote>(),
children: new Map<string, NamespaceNode>(),
domId: MERMAID_DOM_ID_PREFIX + id + '-' + this.namespaceCounter, domId: MERMAID_DOM_ID_PREFIX + id + '-' + this.namespaceCounter,
} as NamespaceNode); });
this.namespaceCounter++; this.namespaceCounter++;
} }
@@ -555,16 +566,23 @@ export class ClassDB implements DiagramDB {
* *
* @param id - ID of the namespace to add * @param id - ID of the namespace to add
* @param classNames - IDs of the class to add * @param classNames - IDs of the class to add
* @param noteNames - IDs of the notes to add
* @public * @public
*/ */
public addClassesToNamespace(id: string, classNames: string[]) { public addClassesToNamespace(id: string, classNames: string[], noteNames: string[]) {
if (!this.namespaces.has(id)) { if (!this.namespaces.has(id)) {
return; return;
} }
for (const name of classNames) { for (const name of classNames) {
const { className } = this.splitClassNameAndType(name); const { className } = this.splitClassNameAndType(name);
this.classes.get(className)!.parent = id; const classNode = this.getClass(className);
this.namespaces.get(id)!.classes.set(className, this.classes.get(className)!); classNode.parent = id;
this.namespaces.get(id)!.classes.set(className, classNode);
}
for (const noteName of noteNames) {
const noteNode = this.getNote(noteName);
noteNode.parent = id;
this.namespaces.get(id)!.notes.set(noteName, noteNode);
} }
} }
@@ -617,36 +635,32 @@ export class ClassDB implements DiagramDB {
const edges: Edge[] = []; const edges: Edge[] = [];
const config = getConfig(); const config = getConfig();
for (const namespaceKey of this.namespaces.keys()) { for (const namespace of this.namespaces.values()) {
const namespace = this.namespaces.get(namespaceKey); const node: Node = {
if (namespace) { id: namespace.id,
const node: Node = { label: namespace.id,
id: namespace.id, isGroup: true,
label: namespace.id, padding: config.class!.padding ?? 16,
isGroup: true, // parent node must be one of [rect, roundedWithTitle, noteGroup, divider]
padding: config.class!.padding ?? 16, shape: 'rect',
// parent node must be one of [rect, roundedWithTitle, noteGroup, divider] cssStyles: [],
shape: 'rect', look: config.look,
cssStyles: ['fill: none', 'stroke: black'], };
look: config.look, nodes.push(node);
};
nodes.push(node);
}
} }
for (const classKey of this.classes.keys()) { for (const classNode of this.classes.values()) {
const classNode = this.classes.get(classKey); const node: Node = {
if (classNode) { ...classNode,
const node = classNode as unknown as Node; type: undefined,
node.parentId = classNode.parent; isGroup: false,
node.look = config.look; parentId: classNode.parent,
nodes.push(node); look: config.look,
} };
nodes.push(node);
} }
let cnt = 0; for (const note of this.notes.values()) {
for (const note of this.notes) {
cnt++;
const noteNode: Node = { const noteNode: Node = {
id: note.id, id: note.id,
label: note.text, label: note.text,
@@ -660,14 +674,15 @@ export class ClassDB implements DiagramDB {
`stroke: ${config.themeVariables.noteBorderColor}`, `stroke: ${config.themeVariables.noteBorderColor}`,
], ],
look: config.look, look: config.look,
parentId: note.parent,
}; };
nodes.push(noteNode); nodes.push(noteNode);
const noteClassId = this.classes.get(note.class)?.id ?? ''; const noteClassId = this.classes.get(note.class)?.id;
if (noteClassId) { if (noteClassId) {
const edge: Edge = { const edge: Edge = {
id: `edgeNote${cnt}`, id: `edgeNote${note.index}`,
start: note.id, start: note.id,
end: noteClassId, end: noteClassId,
type: 'normal', type: 'normal',
@@ -697,7 +712,7 @@ export class ClassDB implements DiagramDB {
nodes.push(interfaceNode); nodes.push(interfaceNode);
} }
cnt = 0; let cnt = 0;
for (const classRelation of this.relations) { for (const classRelation of this.relations) {
cnt++; cnt++;
const edge: Edge = { const edge: Edge = {

View File

@@ -417,7 +417,7 @@ class C13["With Città foreign language"]
note "This is a keyword: ${keyword}. It truly is." note "This is a keyword: ${keyword}. It truly is."
`; `;
parser.parse(str); parser.parse(str);
expect(classDb.getNotes()[0].text).toEqual(`This is a keyword: ${keyword}. It truly is.`); expect(classDb.getNote(0).text).toEqual(`This is a keyword: ${keyword}. It truly is.`);
}); });
it.each(keywords)( it.each(keywords)(
@@ -427,7 +427,7 @@ class C13["With Città foreign language"]
note "${keyword}"`; note "${keyword}"`;
parser.parse(str); parser.parse(str);
expect(classDb.getNotes()[0].text).toEqual(`${keyword}`); expect(classDb.getNote(0).text).toEqual(`${keyword}`);
} }
); );
@@ -441,7 +441,7 @@ class C13["With Città foreign language"]
`; `;
parser.parse(str); parser.parse(str);
expect(classDb.getNotes()[0].text).toEqual(`This is a keyword: ${keyword}. It truly is.`); expect(classDb.getNote(0).text).toEqual(`This is a keyword: ${keyword}. It truly is.`);
}); });
it.each(keywords)( it.each(keywords)(
@@ -456,7 +456,7 @@ class C13["With Città foreign language"]
`; `;
parser.parse(str); parser.parse(str);
expect(classDb.getNotes()[0].text).toEqual(`${keyword}`); expect(classDb.getNote(0).text).toEqual(`${keyword}`);
} }
); );

View File

@@ -8,7 +8,7 @@ import utils, { getEdgeId } from '../../utils.js';
import { interpolateToCurve, getStylesFromArray } from '../../utils.js'; import { interpolateToCurve, getStylesFromArray } from '../../utils.js';
import { setupGraphViewbox } from '../../setupGraphViewbox.js'; import { setupGraphViewbox } from '../../setupGraphViewbox.js';
import common from '../common/common.js'; import common from '../common/common.js';
import type { ClassRelation, ClassNote, ClassMap, NamespaceMap } from './classTypes.js'; import type { ClassRelation, ClassMap, ClassNoteMap, NamespaceMap } from './classTypes.js';
import type { EdgeData } from '../../types.js'; import type { EdgeData } from '../../types.js';
const sanitizeText = (txt: string) => common.sanitizeText(txt, getConfig()); const sanitizeText = (txt: string) => common.sanitizeText(txt, getConfig());
@@ -65,6 +65,9 @@ export const addNamespaces = function (
g.setNode(vertex.id, node); g.setNode(vertex.id, node);
addClasses(vertex.classes, g, _id, diagObj, vertex.id); addClasses(vertex.classes, g, _id, diagObj, vertex.id);
const classes: ClassMap = diagObj.db.getClasses();
const relations: ClassRelation[] = diagObj.db.getRelations();
addNotes(vertex.notes, g, relations.length + 1, classes, vertex.id);
log.info('setNode', node); log.info('setNode', node);
}); });
@@ -144,69 +147,74 @@ export const addClasses = function (
* @param classes - Classes * @param classes - Classes
*/ */
export const addNotes = function ( export const addNotes = function (
notes: ClassNote[], notes: ClassNoteMap,
g: graphlib.Graph, g: graphlib.Graph,
startEdgeId: number, startEdgeId: number,
classes: ClassMap classes: ClassMap,
parent?: string
) { ) {
log.info(notes); log.info(notes);
notes.forEach(function (note, i) { [...notes.values()]
const vertex = note; .filter((note) => note.parent === parent)
.forEach(function (vertex) {
const cssNoteStr = '';
const cssNoteStr = ''; const styles = { labelStyle: '', style: '' };
const styles = { labelStyle: '', style: '' }; const vertexText = vertex.text;
const vertexText = vertex.text; const radius = 0;
const shape = 'note';
const node = {
labelStyle: styles.labelStyle,
shape: shape,
labelText: sanitizeText(vertexText),
noteData: vertex,
rx: radius,
ry: radius,
class: cssNoteStr,
style: styles.style,
id: vertex.id,
domId: vertex.id,
tooltip: '',
type: 'note',
// TODO V10: Flowchart ? Keeping flowchart for backwards compatibility. Remove in next major release
padding: getConfig().flowchart?.padding ?? getConfig().class?.padding,
};
g.setNode(vertex.id, node);
log.info('setNode', node);
const radius = 0; if (parent) {
const shape = 'note'; g.setParent(vertex.id, parent);
const node = { }
labelStyle: styles.labelStyle,
shape: shape,
labelText: sanitizeText(vertexText),
noteData: vertex,
rx: radius,
ry: radius,
class: cssNoteStr,
style: styles.style,
id: vertex.id,
domId: vertex.id,
tooltip: '',
type: 'note',
// TODO V10: Flowchart ? Keeping flowchart for backwards compatibility. Remove in next major release
padding: getConfig().flowchart?.padding ?? getConfig().class?.padding,
};
g.setNode(vertex.id, node);
log.info('setNode', node);
if (!vertex.class || !classes.has(vertex.class)) { if (!vertex.class || !classes.has(vertex.class)) {
return; return;
} }
const edgeId = startEdgeId + i; const edgeId = startEdgeId + vertex.index;
const edgeData: EdgeData = { const edgeData: EdgeData = {
id: `edgeNote${edgeId}`, id: `edgeNote${edgeId}`,
//Set relationship style and line type //Set relationship style and line type
classes: 'relation', classes: 'relation',
pattern: 'dotted', pattern: 'dotted',
// Set link type for rendering // Set link type for rendering
arrowhead: 'none', arrowhead: 'none',
//Set edge extra labels //Set edge extra labels
startLabelRight: '', startLabelRight: '',
endLabelLeft: '', endLabelLeft: '',
//Set relation arrow types //Set relation arrow types
arrowTypeStart: 'none', arrowTypeStart: 'none',
arrowTypeEnd: 'none', arrowTypeEnd: 'none',
style: 'fill:none', style: 'fill:none',
labelStyle: '', labelStyle: '',
curve: interpolateToCurve(conf.curve, curveLinear), curve: interpolateToCurve(conf.curve, curveLinear),
}; };
// Add the edge to the graph // Add the edge to the graph
g.setEdge(vertex.id, vertex.class, edgeData, edgeId); g.setEdge(vertex.id, vertex.class, edgeData, edgeId);
}); });
}; };
/** /**
@@ -329,7 +337,7 @@ export const draw = async function (text: string, id: string, _version: string,
const namespaces: NamespaceMap = diagObj.db.getNamespaces(); const namespaces: NamespaceMap = diagObj.db.getNamespaces();
const classes: ClassMap = diagObj.db.getClasses(); const classes: ClassMap = diagObj.db.getClasses();
const relations: ClassRelation[] = diagObj.db.getRelations(); const relations: ClassRelation[] = diagObj.db.getRelations();
const notes: ClassNote[] = diagObj.db.getNotes(); const notes: ClassNoteMap = diagObj.db.getNotes();
log.info(relations); log.info(relations);
addNamespaces(namespaces, g, id, diagObj); addNamespaces(namespaces, g, id, diagObj);
addClasses(classes, g, id, diagObj); addClasses(classes, g, id, diagObj);

View File

@@ -206,7 +206,7 @@ export const draw = function (text, id, _version, diagObj) {
); );
}); });
const notes = diagObj.db.getNotes(); const notes = diagObj.db.getNotes().values();
notes.forEach(function (note) { notes.forEach(function (note) {
log.debug(`Adding note: ${JSON.stringify(note)}`); log.debug(`Adding note: ${JSON.stringify(note)}`);
const node = svgDraw.drawNote(diagram, note, conf, diagObj); const node = svgDraw.drawNote(diagram, note, conf, diagObj);

View File

@@ -5,7 +5,7 @@ export interface ClassNode {
id: string; id: string;
type: string; type: string;
label: string; label: string;
shape: string; shape: 'classBox';
text: string; text: string;
cssClasses: string; cssClasses: string;
methods: ClassMember[]; methods: ClassMember[];
@@ -149,6 +149,8 @@ export interface ClassNote {
id: string; id: string;
class: string; class: string;
text: string; text: string;
index: number;
parent?: string;
} }
export interface ClassRelation { export interface ClassRelation {
@@ -177,6 +179,7 @@ export interface NamespaceNode {
id: string; id: string;
domId: string; domId: string;
classes: ClassMap; classes: ClassMap;
notes: ClassNoteMap;
children: NamespaceMap; children: NamespaceMap;
} }
@@ -187,4 +190,5 @@ export interface StyleClass {
} }
export type ClassMap = Map<string, ClassNode>; export type ClassMap = Map<string, ClassNode>;
export type ClassNoteMap = Map<string, ClassNote>;
export type NamespaceMap = Map<string, NamespaceNode>; export type NamespaceMap = Map<string, NamespaceNode>;

View File

@@ -275,8 +275,8 @@ statement
; ;
namespaceStatement namespaceStatement
: namespaceIdentifier STRUCT_START classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $3); } : namespaceIdentifier STRUCT_START classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $3[0], $3[1]); }
| namespaceIdentifier STRUCT_START NEWLINE classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $4); } | namespaceIdentifier STRUCT_START NEWLINE classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $4[0], $4[1]); }
; ;
namespaceIdentifier namespaceIdentifier
@@ -284,9 +284,12 @@ namespaceIdentifier
; ;
classStatements classStatements
: classStatement {$$=[$1]} : classStatement {$$=[[$1], []]}
| classStatement NEWLINE {$$=[$1]} | classStatement NEWLINE {$$=[[$1], []]}
| classStatement NEWLINE classStatements {$3.unshift($1); $$=$3} | classStatement NEWLINE classStatements {$3[0].unshift($1); $$=$3}
| noteStatement {$$=[[], [$1]]}
| noteStatement NEWLINE {$$=[[], [$1]]}
| noteStatement NEWLINE classStatements {$3[1].unshift($1); $$=$3}
; ;
classStatement classStatement
@@ -333,8 +336,8 @@ relationStatement
; ;
noteStatement noteStatement
: NOTE_FOR className noteText { yy.addNote($3, $2); } : NOTE_FOR className noteText { $$ = yy.addNote($3, $2); }
| NOTE noteText { yy.addNote($2); } | NOTE noteText { $$ = yy.addNote($2); }
; ;
classDefStatement classDefStatement

View File

@@ -13,6 +13,30 @@ const getStyles = (options) =>
} }
.cluster-label text {
fill: ${options.titleColor};
}
.cluster-label span {
color: ${options.titleColor};
}
.cluster-label span p {
background-color: transparent;
}
.cluster rect {
fill: ${options.clusterBkg};
stroke: ${options.clusterBorder};
stroke-width: 1px;
}
.cluster text {
fill: ${options.titleColor};
}
.cluster span {
color: ${options.titleColor};
}
.nodeLabel, .edgeLabel { .nodeLabel, .edgeLabel {
color: ${options.classText}; color: ${options.classText};
} }

View File

@@ -70,6 +70,31 @@ describe('Sanitize text', () => {
}); });
expect(result).not.toContain('javascript:alert(1)'); expect(result).not.toContain('javascript:alert(1)');
}); });
it('should allow HTML tags in sandbox mode', () => {
const htmlStr = '<p>This is a <strong>bold</strong> text</p>';
const result = sanitizeText(htmlStr, {
securityLevel: 'sandbox',
flowchart: { htmlLabels: true },
});
expect(result).toContain('<p>');
expect(result).toContain('<strong>');
expect(result).toContain('</strong>');
expect(result).toContain('</p>');
});
it('should remove script tags in sandbox mode', () => {
const maliciousStr = '<p>Hello <script>alert(1)</script> world</p>';
const result = sanitizeText(maliciousStr, {
securityLevel: 'sandbox',
flowchart: { htmlLabels: true },
});
expect(result).not.toContain('<script>');
expect(result).not.toContain('alert(1)');
expect(result).toContain('<p>');
expect(result).toContain('Hello');
expect(result).toContain('world');
});
}); });
describe('generic parser', () => { describe('generic parser', () => {

View File

@@ -66,7 +66,7 @@ export const removeScript = (txt: string): string => {
const sanitizeMore = (text: string, config: MermaidConfig) => { const sanitizeMore = (text: string, config: MermaidConfig) => {
if (config.flowchart?.htmlLabels !== false) { if (config.flowchart?.htmlLabels !== false) {
const level = config.securityLevel; const level = config.securityLevel;
if (level === 'antiscript' || level === 'strict') { if (level === 'antiscript' || level === 'strict' || level === 'sandbox') {
text = removeScript(text); text = removeScript(text);
} else if (level !== 'loose') { } else if (level !== 'loose') {
text = breakToPlaceholder(text); text = breakToPlaceholder(text);
@@ -333,7 +333,7 @@ const renderKatexUnsanitized = async (text: string, config: MermaidConfig): Prom
return text.replace(katexRegex, 'MathML is unsupported in this environment.'); return text.replace(katexRegex, 'MathML is unsupported in this environment.');
} }
if (includeLargeFeatures) { if (injected.includeLargeFeatures) {
const { default: katex } = await import('katex'); const { default: katex } = await import('katex');
const outputMode = const outputMode =
config.forceLegacyMathML || (!isMathMLSupported() && config.legacyMathML) config.forceLegacyMathML || (!isMathMLSupported() && config.legacyMathML)

View File

@@ -66,12 +66,15 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
\}\| return 'ONE_OR_MORE'; \}\| return 'ONE_OR_MORE';
"one" return 'ONLY_ONE'; "one" return 'ONLY_ONE';
"only one" return 'ONLY_ONE'; "only one" return 'ONLY_ONE';
"1" return 'ONLY_ONE'; [0-9]+\.[0-9]+ return 'DECIMAL_NUM';
"1"(?=\s+[A-Za-z_"']) return 'ONLY_ONE';
"1" return 'ENTITY_ONE';
[0-9]+ return 'NUM';
\|\| return 'ONLY_ONE'; \|\| return 'ONLY_ONE';
o\| return 'ZERO_OR_ONE'; o\| return 'ZERO_OR_ONE';
o\{ return 'ZERO_OR_MORE'; o\{ return 'ZERO_OR_MORE';
\|\{ return 'ONE_OR_MORE'; \|\{ return 'ONE_OR_MORE';
\s*u return 'MD_PARENT'; u(?=[\.\-\|]) return 'MD_PARENT';
\.\. return 'NON_IDENTIFYING'; \.\. return 'NON_IDENTIFYING';
\-\- return 'IDENTIFYING'; \-\- return 'IDENTIFYING';
"to" return 'IDENTIFYING'; "to" return 'IDENTIFYING';
@@ -80,13 +83,15 @@ o\{ return 'ZERO_OR_MORE';
\-\. return 'NON_IDENTIFYING'; \-\. return 'NON_IDENTIFYING';
<style>([^\x00-\x7F]|\w|\-|\*)+ return 'STYLE_TEXT'; <style>([^\x00-\x7F]|\w|\-|\*)+ return 'STYLE_TEXT';
<style>';' return 'SEMI'; <style>';' return 'SEMI';
([^\x00-\x7F]|\w|\-|\*)+ return 'UNICODE_TEXT'; ([^\x00-\x7F]|\w|\-|\*|\.)+ return 'UNICODE_TEXT';
[0-9] return 'NUM';
. return yytext[0]; . return yytext[0];
<<EOF>> return 'EOF'; <<EOF>> return 'EOF';
/lex /lex
%left 'ONLY_ONE'
%left 'ZERO_OR_ONE' 'ZERO_OR_MORE' 'ONE_OR_MORE' 'MD_PARENT'
%start start %start start
%% /* language grammar */ %% /* language grammar */
@@ -228,6 +233,9 @@ styleComponent: STYLE_TEXT | NUM | COLON | BRKT;
entityName entityName
: 'ENTITY_NAME' { $$ = $1.replace(/"/g, ''); } : 'ENTITY_NAME' { $$ = $1.replace(/"/g, ''); }
| 'UNICODE_TEXT' { $$ = $1; } | 'UNICODE_TEXT' { $$ = $1; }
| 'NUM' { $$ = $1; }
| 'DECIMAL_NUM' { $$ = $1; }
| 'ENTITY_ONE' { $$ = $1; }
; ;
attributes attributes

View File

@@ -1001,4 +1001,90 @@ describe('when parsing ER diagram it...', function () {
} }
); );
}); });
describe('syntax fixes for special characters and numbers', function () {
describe('standalone entity names', function () {
it('should allow number "1" as standalone entity', function () {
erDiagram.parser.parse(`erDiagram\nCUSTOMER }|..|{ DELIVERY-ADDRESS : has\n1`);
});
it('should allow character "u" as standalone entity', function () {
erDiagram.parser.parse(`erDiagram\nCUSTOMER }|..|{ DELIVERY-ADDRESS : has\nu`);
});
it('should allow decimal numbers as standalone entities', function () {
erDiagram.parser.parse(`erDiagram\nCUSTOMER }|..|{ DELIVERY-ADDRESS : has\n2.5`);
erDiagram.parser.parse(`erDiagram\nCUSTOMER }|..|{ DELIVERY-ADDRESS : has\n1.5`);
erDiagram.parser.parse(`erDiagram\nCUSTOMER }|..|{ DELIVERY-ADDRESS : has\n0.1`);
erDiagram.parser.parse(`erDiagram\nCUSTOMER }|..|{ DELIVERY-ADDRESS : has\n99.99`);
});
});
describe('entity names with attributes', function () {
it('should allow "u" as entity name with attributes', function () {
erDiagram.parser.parse(`erDiagram\nu {\nstring name\nint id\n}`);
});
it('should allow number "1" as entity name with attributes', function () {
erDiagram.parser.parse(`erDiagram\n1 {\nstring name\nint id\n}`);
});
it('should allow decimal numbers as entity names with attributes', function () {
erDiagram.parser.parse(`erDiagram\n2.5 {\nstring name\nint id\n}`);
erDiagram.parser.parse(`erDiagram\n1.5 {\nstring value\n}`);
});
});
describe('entity names in relationships', function () {
it('should allow "u" in relationships', function () {
erDiagram.parser.parse(`erDiagram\nCUSTOMER ||--|| u : has`);
erDiagram.parser.parse(`erDiagram\nu ||--|| ORDER : places`);
erDiagram.parser.parse(`erDiagram\nu ||--|| v : connects`);
});
it('should allow numbers in relationships', function () {
erDiagram.parser.parse(`erDiagram\nCUSTOMER ||--|| 1 : has`);
erDiagram.parser.parse(`erDiagram\n1 ||--|| ORDER : places`);
erDiagram.parser.parse(`erDiagram\n1 ||--|| 2 : connects`);
});
it('should allow decimal numbers in relationships', function () {
erDiagram.parser.parse(`erDiagram\nCUSTOMER ||--|| 2.5 : has`);
erDiagram.parser.parse(`erDiagram\n1.5 ||--|| ORDER : places`);
erDiagram.parser.parse(`erDiagram\n2.5 ||--|| 5.5 : connects`);
});
});
describe('mixed scenarios', function () {
it('should handle complex diagram with special entity names', function () {
erDiagram.parser.parse(
`erDiagram
CUSTOMER ||--o{ 1 : places
1 ||--|{ u : contains
u {
string name
int quantity
}
"2.5" ||--|| ORDER : processes
ORDER {
int id
date created
}
`
);
});
it('should handle attributes with numbers in names (but not starting)', function () {
erDiagram.parser.parse(
`erDiagram
ENTITY {
string name1
int value2
float point3_5
}
`
);
});
});
});
}); });

View File

@@ -140,6 +140,7 @@ that id.
.*direction\s+BT[^\n]* return 'direction_bt'; .*direction\s+BT[^\n]* return 'direction_bt';
.*direction\s+RL[^\n]* return 'direction_rl'; .*direction\s+RL[^\n]* return 'direction_rl';
.*direction\s+LR[^\n]* return 'direction_lr'; .*direction\s+LR[^\n]* return 'direction_lr';
.*direction\s+TD[^\n]* return 'direction_td';
[^\s\"]+\@(?=[^\{\"]) { return 'LINK_ID'; } [^\s\"]+\@(?=[^\{\"]) { return 'LINK_ID'; }
[0-9]+ return 'NUM'; [0-9]+ return 'NUM';
@@ -626,6 +627,8 @@ direction
{ $$={stmt:'dir', value:'RL'};} { $$={stmt:'dir', value:'RL'};}
| direction_lr | direction_lr
{ $$={stmt:'dir', value:'LR'};} { $$={stmt:'dir', value:'LR'};}
| direction_td
{ $$={stmt:'dir', value:'TD'};}
; ;
%% %%

View File

@@ -309,4 +309,21 @@ describe('when parsing subgraphs', function () {
expect(subgraphA.nodes).toContain('a'); expect(subgraphA.nodes).toContain('a');
expect(subgraphA.nodes).not.toContain('c'); expect(subgraphA.nodes).not.toContain('c');
}); });
it('should correctly parse direction TD inside a subgraph', function () {
const res = flow.parser.parse(`
graph LR
subgraph WithTD
direction TD
A1 --> A2
end
`);
const subgraphs = flow.parser.yy.getSubGraphs();
expect(subgraphs.length).toBe(1);
const subgraph = subgraphs[0];
expect(subgraph.dir).toBe('TD');
expect(subgraph.nodes).toContain('A1');
expect(subgraph.nodes).toContain('A2');
});
}); });

View File

@@ -268,7 +268,9 @@ const fixTaskDates = function (startTime, endTime, dateFormat, excludes, include
const getStartDate = function (prevTime, dateFormat, str) { const getStartDate = function (prevTime, dateFormat, str) {
str = str.trim(); str = str.trim();
if ((dateFormat.trim() === 'x' || dateFormat.trim() === 'X') && /^\d+$/.test(str)) {
return new Date(Number(str));
}
// Test for after // Test for after
const afterRePattern = /^after\s+(?<ids>[\d\w- ]+)/; const afterRePattern = /^after\s+(?<ids>[\d\w- ]+)/;
const afterStatement = afterRePattern.exec(str); const afterStatement = afterRePattern.exec(str);

View File

@@ -1,8 +1,7 @@
import type { InfoFields, InfoDB } from './infoTypes.js'; import type { InfoFields, InfoDB } from './infoTypes.js';
import packageJson from '../../../package.json' assert { type: 'json' };
export const DEFAULT_INFO_DB: InfoFields = { export const DEFAULT_INFO_DB: InfoFields = {
version: packageJson.version + (includeLargeFeatures ? '' : '-tiny'), version: injected.version + (injected.includeLargeFeatures ? '' : '-tiny'),
} as const; } as const;
export const getVersion = (): string => DEFAULT_INFO_DB.version; export const getVersion = (): string => DEFAULT_INFO_DB.version;

View File

@@ -16,7 +16,7 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
const svgWidth = bitWidth * bitsPerRow + 2; const svgWidth = bitWidth * bitsPerRow + 2;
const svg: SVG = selectSvgElement(id); const svg: SVG = selectSvgElement(id);
svg.attr('viewbox', `0 0 ${svgWidth} ${svgHeight}`); svg.attr('viewBox', `0 0 ${svgWidth} ${svgHeight}`);
configureSvgSize(svg, svgHeight, svgWidth, config.useMaxWidth); configureSvgSize(svg, svgHeight, svgWidth, config.useMaxWidth);
for (const [word, packet] of words.entries()) { for (const [word, packet] of words.entries()) {

View File

@@ -2,6 +2,7 @@ import type { Diagram } from '../../Diagram.js';
import type { RadarDiagramConfig } from '../../config.type.js'; import type { RadarDiagramConfig } from '../../config.type.js';
import type { DiagramRenderer, DrawDefinition, SVG, SVGGroup } from '../../diagram-api/types.js'; import type { DiagramRenderer, DrawDefinition, SVG, SVGGroup } from '../../diagram-api/types.js';
import { selectSvgElement } from '../../rendering-util/selectSvgElement.js'; import { selectSvgElement } from '../../rendering-util/selectSvgElement.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
import type { RadarDB, RadarAxis, RadarCurve } from './types.js'; import type { RadarDB, RadarAxis, RadarCurve } from './types.js';
const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => { const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
@@ -53,11 +54,9 @@ const drawFrame = (svg: SVG, config: Required<RadarDiagramConfig>): SVGGroup =>
x: config.marginLeft + config.width / 2, x: config.marginLeft + config.width / 2,
y: config.marginTop + config.height / 2, y: config.marginTop + config.height / 2,
}; };
// Initialize the SVG configureSvgSize(svg, totalHeight, totalWidth, config.useMaxWidth ?? true);
svg
.attr('viewbox', `0 0 ${totalWidth} ${totalHeight}`) svg.attr('viewBox', `0 0 ${totalWidth} ${totalHeight}`);
.attr('width', totalWidth)
.attr('height', totalHeight);
// g element to center the radar chart // g element to center the radar chart
return svg.append('g').attr('transform', `translate(${center.x}, ${center.y})`); return svg.append('g').attr('transform', `translate(${center.x}, ${center.y})`);
}; };

View File

@@ -32,13 +32,14 @@
<CONFIG>[^\}]+ { return 'CONFIG_CONTENT'; } <CONFIG>[^\}]+ { return 'CONFIG_CONTENT'; }
<CONFIG>\} { this.popState(); this.popState(); return 'CONFIG_END'; } <CONFIG>\} { this.popState(); this.popState(); return 'CONFIG_END'; }
<ID>[^\<->\->:\n,;@\s]+(?=\@\{) { yytext = yytext.trim(); return 'ACTOR'; } <ID>[^\<->\->:\n,;@\s]+(?=\@\{) { yytext = yytext.trim(); return 'ACTOR'; }
<ID>[^\<->\->:\n,;@]+?([\-]*[^\<->\->:\n,;@]+?)*?(?=((?!\n)\s)+"as"(?!\n)\s|[#\n;]|$) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; } <ID>[^<>:\n,;@\s]+(?=\s+as\s) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; }
<ID>[^<>:\n,;@]+(?=\s*[\n;#]|$) { yytext = yytext.trim(); this.popState(); return 'ACTOR'; }
<ID>[^<>:\n,;@]*\<[^\n]* { this.popState(); return 'INVALID'; }
"box" { this.begin('LINE'); return 'box'; } "box" { this.begin('LINE'); return 'box'; }
"participant" { this.begin('ID'); return 'participant'; } "participant" { this.begin('ID'); return 'participant'; }
"actor" { this.begin('ID'); return 'participant_actor'; } "actor" { this.begin('ID'); return 'participant_actor'; }
"create" return 'create'; "create" return 'create';
"destroy" { this.begin('ID'); return 'destroy'; } "destroy" { this.begin('ID'); return 'destroy'; }
<ID>[^<\->\->:\n,;]+?([\-]*[^<\->\->:\n,;]+?)*?(?=((?!\n)\s)+"as"(?!\n)\s|[#\n;]|$) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; }
<ALIAS>"as" { this.popState(); this.popState(); this.begin('LINE'); return 'AS'; } <ALIAS>"as" { this.popState(); this.popState(); this.begin('LINE'); return 'AS'; }
<ALIAS>(?:) { this.popState(); this.popState(); return 'NEWLINE'; } <ALIAS>(?:) { this.popState(); this.popState(); return 'NEWLINE'; }
"loop" { this.begin('LINE'); return 'loop'; } "loop" { this.begin('LINE'); return 'loop'; }
@@ -78,7 +79,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
"off" return 'off'; "off" return 'off';
"," return ','; "," return ',';
";" return 'NEWLINE'; ";" return 'NEWLINE';
[^+<\->\->:\n,;]+((?!(\-x|\-\-x|\-\)|\-\-\)))[\-]*[^\+<\->\->:\n,;]+)* { yytext = yytext.trim(); return 'ACTOR'; } [^\/\\\+\()\+<\->\->:\n,;]+((?!(\-x|\-\-x|\-\)|\-\-\)|\-\|\\|\-\\|\-\/|\-\/\/|\-\|\/|\/\|\-|\\\|\-|\/\/\-|\\\\\-|\/\|\-|\-\-\|\\|\-\-|\(\)))[\-]*[^\+<\->\->:\n,;]+)* { yytext = yytext.trim(); return 'ACTOR'; } //final_4.11
"->>" return 'SOLID_ARROW'; "->>" return 'SOLID_ARROW';
"<<->>" return 'BIDIRECTIONAL_SOLID_ARROW'; "<<->>" return 'BIDIRECTIONAL_SOLID_ARROW';
"-->>" return 'DOTTED_ARROW'; "-->>" return 'DOTTED_ARROW';
@@ -89,10 +90,36 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
\-\-[x] return 'DOTTED_CROSS'; \-\-[x] return 'DOTTED_CROSS';
\-[\)] return 'SOLID_POINT'; \-[\)] return 'SOLID_POINT';
\-\-[\)] return 'DOTTED_POINT'; \-\-[\)] return 'DOTTED_POINT';
//normal-dotted
\-\-\|\\ return 'SOLID_ARROW_TOP_DOTTED';
\-\-\|\/ return 'SOLID_ARROW_BOTTOM_DOTTED';
\-\-\\\\ return 'STICK_ARROW_TOP_DOTTED';
\-\-\/\/ return 'STICK_ARROW_BOTTOM_DOTTED';
//reverse-dotted
\/\|\-\- return 'SOLID_ARROW_TOP_REVERSE_DOTTED';
\\\|\-\- return 'SOLID_ARROW_BOTTOM_REVERSE_DOTTED';
\/\/\-\- return 'STICK_ARROW_TOP_REVERSE_DOTTED';
\\\\\-\- return 'STICK_ARROW_BOTTOM_REVERSE_DOTTED';
//normal
\-\|\\ return 'SOLID_ARROW_TOP';
\-\|\/ return 'SOLID_ARROW_BOTTOM';
\-\\\\ return 'STICK_ARROW_TOP';
\-\/\/ return 'STICK_ARROW_BOTTOM';
//reverse
\/\|\- return 'SOLID_ARROW_TOP_REVERSE';
\\\|\- return 'SOLID_ARROW_BOTTOM_REVERSE';
\/\/\- return 'STICK_ARROW_TOP_REVERSE';
\\\\\- return 'STICK_ARROW_BOTTOM_REVERSE';
":"(?:(?:no)?wrap:)?[^#\n;]* return 'TXT'; ":"(?:(?:no)?wrap:)?[^#\n;]* return 'TXT';
":" return 'TXT'; ":" return 'TXT';
"+" return '+'; "+" return '+';
"-" return '-'; "-" return '-';
"()" return '()';
<<EOF>> return 'NEWLINE'; <<EOF>> return 'NEWLINE';
. return 'INVALID'; . return 'INVALID';
@@ -119,6 +146,7 @@ line
: SPACE statement { $$ = $2 } : SPACE statement { $$ = $2 }
| statement { $$ = $1 } | statement { $$ = $1 }
| NEWLINE { $$=[]; } | NEWLINE { $$=[]; }
| INVALID { $$=[]; }
; ;
box_section box_section
@@ -304,6 +332,20 @@ signal
{ $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$2, msg:$5}, { $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$2, msg:$5},
{type: 'activeEnd', signalType: yy.LINETYPE.ACTIVE_END, actor: $1.actor} {type: 'activeEnd', signalType: yy.LINETYPE.ACTIVE_END, actor: $1.actor}
]} ]}
| actor signaltype '()' actor text2
{ $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$2, msg:$5, activate: true, centralConnection: yy.LINETYPE.CENTRAL_CONNECTION},
{type: 'centralConnection', signalType: yy.LINETYPE.CENTRAL_CONNECTION, actor: $4.actor, }
]}
| actor '()' signaltype actor text2
{ $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$3, msg:$5, activate: false, centralConnection: yy.LINETYPE.CENTRAL_CONNECTION_REVERSE},
{type: 'centralConnectionReverse', signalType: yy.LINETYPE.CENTRAL_CONNECTION_REVERSE, actor: $1.actor}
]}
| actor '()' signaltype '()' actor text2
{ $$ = [$1,$5,{type: 'addMessage', from:$1.actor, to:$5.actor, signalType:$3, msg:$6, activate: true, centralConnection: yy.LINETYPE.CENTRAL_CONNECTION_DUAL},
{type: 'centralConnection', signalType: yy.LINETYPE.CENTRAL_CONNECTION, actor: $5.actor, },
{type: 'centralConnectionReverse', signalType: yy.LINETYPE.CENTRAL_CONNECTION_REVERSE, actor: $1.actor}
]}
| actor signaltype actor text2 | actor signaltype actor text2
{ $$ = [$1,$3,{type: 'addMessage', from:$1.actor, to:$3.actor, signalType:$2, msg:$4}]} { $$ = [$1,$3,{type: 'addMessage', from:$1.actor, to:$3.actor, signalType:$2, msg:$4}]}
; ;
@@ -337,7 +379,28 @@ signaltype
: SOLID_OPEN_ARROW { $$ = yy.LINETYPE.SOLID_OPEN; } : SOLID_OPEN_ARROW { $$ = yy.LINETYPE.SOLID_OPEN; }
| DOTTED_OPEN_ARROW { $$ = yy.LINETYPE.DOTTED_OPEN; } | DOTTED_OPEN_ARROW { $$ = yy.LINETYPE.DOTTED_OPEN; }
| SOLID_ARROW { $$ = yy.LINETYPE.SOLID; } | SOLID_ARROW { $$ = yy.LINETYPE.SOLID; }
| BIDIRECTIONAL_SOLID_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_SOLID; }
| SOLID_ARROW_TOP { $$ = yy.LINETYPE.SOLID_TOP; }
| SOLID_ARROW_BOTTOM { $$ = yy.LINETYPE.SOLID_BOTTOM; }
| STICK_ARROW_TOP { $$ = yy.LINETYPE.STICK_TOP; }
| STICK_ARROW_BOTTOM { $$ = yy.LINETYPE.STICK_BOTTOM; }
| SOLID_ARROW_TOP_DOTTED { $$ = yy.LINETYPE.SOLID_TOP_DOTTED; }
| SOLID_ARROW_BOTTOM_DOTTED { $$ = yy.LINETYPE.SOLID_BOTTOM_DOTTED; }
| STICK_ARROW_TOP_DOTTED { $$ = yy.LINETYPE.STICK_TOP_DOTTED; }
| STICK_ARROW_BOTTOM_DOTTED { $$ = yy.LINETYPE.STICK_BOTTOM_DOTTED; }
| SOLID_ARROW_TOP_REVERSE { $$ = yy.LINETYPE.SOLID_ARROW_TOP_REVERSE; }
| SOLID_ARROW_BOTTOM_REVERSE { $$ = yy.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE; }
| STICK_ARROW_TOP_REVERSE { $$ = yy.LINETYPE.STICK_ARROW_TOP_REVERSE; }
| STICK_ARROW_BOTTOM_REVERSE { $$ = yy.LINETYPE.STICK_ARROW_BOTTOM_REVERSE; }
| SOLID_ARROW_TOP_REVERSE_DOTTED { $$ = yy.LINETYPE.SOLID_ARROW_TOP_REVERSE_DOTTED; }
| SOLID_ARROW_BOTTOM_REVERSE_DOTTED { $$ = yy.LINETYPE.SOLID_ARROW_BOTTOM_REVERSE_DOTTED; }
| STICK_ARROW_TOP_REVERSE_DOTTED { $$ = yy.LINETYPE.STICK_ARROW_TOP_REVERSE_DOTTED; }
| STICK_ARROW_BOTTOM_REVERSE_DOTTED { $$ = yy.LINETYPE.STICK_ARROW_BOTTOM_REVERSE_DOTTED; }
| BIDIRECTIONAL_SOLID_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_SOLID; }
| DOTTED_ARROW { $$ = yy.LINETYPE.DOTTED; } | DOTTED_ARROW { $$ = yy.LINETYPE.DOTTED; }
| BIDIRECTIONAL_DOTTED_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_DOTTED; } | BIDIRECTIONAL_DOTTED_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_DOTTED; }
| SOLID_CROSS { $$ = yy.LINETYPE.SOLID_CROSS; } | SOLID_CROSS { $$ = yy.LINETYPE.SOLID_CROSS; }
@@ -350,4 +413,4 @@ text2
: TXT {$$ = yy.parseMessage($1.trim().substring(1)) } : TXT {$$ = yy.parseMessage($1.trim().substring(1)) }
; ;
%% %%

View File

@@ -13,7 +13,8 @@ import {
setAccTitle, setAccTitle,
setDiagramTitle, setDiagramTitle,
} from '../common/commonDb.js'; } from '../common/commonDb.js';
import type { Actor, AddMessageParams, Box, Message, Note, ParticipantMetaData } from './types.js'; import type { Actor, AddMessageParams, Box, Message, Note } from './types.js';
import type { ParticipantMetaData } from '../../types.js';
interface SequenceState { interface SequenceState {
prevActor?: string; prevActor?: string;
@@ -63,6 +64,30 @@ const LINETYPE = {
PAR_OVER_START: 32, PAR_OVER_START: 32,
BIDIRECTIONAL_SOLID: 33, BIDIRECTIONAL_SOLID: 33,
BIDIRECTIONAL_DOTTED: 34, BIDIRECTIONAL_DOTTED: 34,
SOLID_TOP: 41,
SOLID_BOTTOM: 42,
STICK_TOP: 43,
STICK_BOTTOM: 44,
SOLID_ARROW_TOP_REVERSE: 45,
SOLID_ARROW_BOTTOM_REVERSE: 46,
STICK_ARROW_TOP_REVERSE: 47,
STICK_ARROW_BOTTOM_REVERSE: 48,
SOLID_TOP_DOTTED: 51,
SOLID_BOTTOM_DOTTED: 52,
STICK_TOP_DOTTED: 53,
STICK_BOTTOM_DOTTED: 54,
SOLID_ARROW_TOP_REVERSE_DOTTED: 55,
SOLID_ARROW_BOTTOM_REVERSE_DOTTED: 56,
STICK_ARROW_TOP_REVERSE_DOTTED: 57,
STICK_ARROW_BOTTOM_REVERSE_DOTTED: 58,
CENTRAL_CONNECTION: 59,
CENTRAL_CONNECTION_REVERSE: 60,
CENTRAL_CONNECTION_DUAL: 61,
} as const; } as const;
const ARROWTYPE = { const ARROWTYPE = {
@@ -85,8 +110,6 @@ export const PARTICIPANT_TYPE = {
ENTITY: 'entity', ENTITY: 'entity',
PARTICIPANT: 'participant', PARTICIPANT: 'participant',
QUEUE: 'queue', QUEUE: 'queue',
ICON: 'icon',
IMAGE: 'image',
} as const; } as const;
export class SequenceDB implements DiagramDB { export class SequenceDB implements DiagramDB {
@@ -187,7 +210,6 @@ export class SequenceDB implements DiagramDB {
actorCnt: null, actorCnt: null,
rectData: null, rectData: null,
type: type ?? 'participant', type: type ?? 'participant',
doc: doc,
}); });
if (this.state.records.prevActor) { if (this.state.records.prevActor) {
const prevActorInRecords = this.state.records.actors.get(this.state.records.prevActor); const prevActorInRecords = this.state.records.actors.get(this.state.records.prevActor);
@@ -246,7 +268,8 @@ export class SequenceDB implements DiagramDB {
idTo?: Message['to'], idTo?: Message['to'],
message?: { text: string; wrap: boolean }, message?: { text: string; wrap: boolean },
messageType?: number, messageType?: number,
activate = false activate = false,
centralConnection?: number
) { ) {
if (messageType === this.LINETYPE.ACTIVE_END) { if (messageType === this.LINETYPE.ACTIVE_END) {
const cnt = this.activationCount(idFrom ?? ''); const cnt = this.activationCount(idFrom ?? '');
@@ -273,6 +296,7 @@ export class SequenceDB implements DiagramDB {
wrap: message?.wrap ?? this.autoWrap(), wrap: message?.wrap ?? this.autoWrap(),
type: messageType, type: messageType,
activate, activate,
centralConnection: centralConnection ?? 0,
}); });
return true; return true;
} }
@@ -565,6 +589,12 @@ export class SequenceDB implements DiagramDB {
case 'activeStart': case 'activeStart':
this.addSignal(param.actor, undefined, undefined, param.signalType); this.addSignal(param.actor, undefined, undefined, param.signalType);
break; break;
case 'centralConnection':
this.addSignal(param.actor, undefined, undefined, param.signalType);
break;
case 'centralConnectionReverse':
this.addSignal(param.actor, undefined, undefined, param.signalType);
break;
case 'activeEnd': case 'activeEnd':
this.addSignal(param.actor, undefined, undefined, param.signalType); this.addSignal(param.actor, undefined, undefined, param.signalType);
break; break;
@@ -608,7 +638,14 @@ export class SequenceDB implements DiagramDB {
this.state.records.lastDestroyed = undefined; this.state.records.lastDestroyed = undefined;
} }
} }
this.addSignal(param.from, param.to, param.msg, param.signalType, param.activate); this.addSignal(
param.from,
param.to,
param.msg,
param.signalType,
param.activate,
param.centralConnection
);
break; break;
case 'boxStart': case 'boxStart':
this.addBox(param.boxData); this.addBox(param.boxData);

View File

@@ -104,6 +104,7 @@ describe('more than one sequence diagram', () => {
[ [
{ {
"activate": false, "activate": false,
"centralConnection": 0,
"from": "Alice", "from": "Alice",
"id": "0", "id": "0",
"message": "Hello Bob, how are you?", "message": "Hello Bob, how are you?",
@@ -113,6 +114,7 @@ describe('more than one sequence diagram', () => {
}, },
{ {
"activate": false, "activate": false,
"centralConnection": 0,
"from": "Bob", "from": "Bob",
"id": "1", "id": "1",
"message": "I am good thanks!", "message": "I am good thanks!",
@@ -131,6 +133,7 @@ describe('more than one sequence diagram', () => {
[ [
{ {
"activate": false, "activate": false,
"centralConnection": 0,
"from": "Alice", "from": "Alice",
"id": "0", "id": "0",
"message": "Hello Bob, how are you?", "message": "Hello Bob, how are you?",
@@ -140,6 +143,7 @@ describe('more than one sequence diagram', () => {
}, },
{ {
"activate": false, "activate": false,
"centralConnection": 0,
"from": "Bob", "from": "Bob",
"id": "1", "id": "1",
"message": "I am good thanks!", "message": "I am good thanks!",
@@ -160,6 +164,7 @@ describe('more than one sequence diagram', () => {
[ [
{ {
"activate": false, "activate": false,
"centralConnection": 0,
"from": "Alice", "from": "Alice",
"id": "0", "id": "0",
"message": "Hello John, how are you?", "message": "Hello John, how are you?",
@@ -169,6 +174,7 @@ describe('more than one sequence diagram', () => {
}, },
{ {
"activate": false, "activate": false,
"centralConnection": 0,
"from": "John", "from": "John",
"id": "1", "id": "1",
"message": "I am good thanks!", "message": "I am good thanks!",
@@ -181,6 +187,254 @@ describe('more than one sequence diagram', () => {
}); });
}); });
describe('Central Connection Parsing', () => {
describe('when parsing central connection syntax', () => {
it('should parse actor ()->>() actor syntax as CENTRAL_CONNECTION_DUAL', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Alice
participant Bob
Alice ()->>() Bob: Hello Bob, how are you?
`);
const messages = diagram.db.getMessages();
expect(messages).toHaveLength(3); // addMessage + centralConnection + centralConnectionReverse
// Find the actual message (type: 'addMessage')
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
expect(actualMessage).toMatchObject({
from: 'Alice',
to: 'Bob',
message: 'Hello Bob, how are you?',
centralConnection: 61, // CENTRAL_CONNECTION_DUAL
activate: true,
type: 0, // SOLID (based on test output)
});
});
it('should parse actor ()-->>() actor syntax as CENTRAL_CONNECTION_DUAL', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Alice
participant Bob
Alice ()-->>() Bob: Hello Bob, how are you?
`);
const messages = diagram.db.getMessages();
expect(messages).toHaveLength(3); // addMessage + centralConnection + centralConnectionReverse
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
expect(actualMessage).toMatchObject({
from: 'Alice',
to: 'Bob',
message: 'Hello Bob, how are you?',
centralConnection: 61, // CENTRAL_CONNECTION_DUAL
activate: true,
type: 1, // DOTTED (based on test output)
});
});
it('should parse actor ->>() actor syntax as CENTRAL_CONNECTION', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Alice
participant Bob
Alice ->>() Bob: Hello Bob, how are you?
`);
const messages = diagram.db.getMessages();
expect(messages).toHaveLength(2); // addMessage + centralConnection (no activation for this pattern)
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
expect(actualMessage).toMatchObject({
from: 'Alice',
to: 'Bob',
message: 'Hello Bob, how are you?',
centralConnection: 59, // CENTRAL_CONNECTION
activate: true,
type: 0, // SOLID (based on actual parsing)
});
});
it('should parse actor ()-->> actor syntax as CENTRAL_CONNECTION_REVERSE', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Alice
participant Bob
Alice ()-->> Bob: Hello Bob, how are you?
`);
const messages = diagram.db.getMessages();
expect(messages).toHaveLength(2); // addMessage + centralConnectionReverse
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
expect(actualMessage).toMatchObject({
from: 'Alice',
to: 'Bob',
message: 'Hello Bob, how are you?',
centralConnection: 60, // CENTRAL_CONNECTION_REVERSE
activate: false,
type: 1, // DOTTED (based on test output)
});
});
it('should parse actor ()->> actor syntax as CENTRAL_CONNECTION_REVERSE', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Alice
participant Bob
Alice ()->> Bob: Hello Bob, how are you?
`);
const messages = diagram.db.getMessages();
expect(messages).toHaveLength(2); // addMessage + centralConnectionReverse
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
expect(actualMessage).toMatchObject({
from: 'Alice',
to: 'Bob',
message: 'Hello Bob, how are you?',
centralConnection: 60, // CENTRAL_CONNECTION_REVERSE
activate: false,
type: 0, // SOLID (based on test output)
});
});
it('should parse actor ()<<-->>() actor syntax as CENTRAL_CONNECTION_DUAL', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Alice
participant Bob
Alice ()<<-->>() Bob: Hello Bob, how are you?
`);
const messages = diagram.db.getMessages();
expect(messages).toHaveLength(3); // addMessage + centralConnection + centralConnectionReverse
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
expect(actualMessage).toMatchObject({
from: 'Alice',
to: 'Bob',
message: 'Hello Bob, how are you?',
centralConnection: 61, // CENTRAL_CONNECTION_DUAL
activate: true,
type: 34, // BIDIRECTIONAL_DOTTED
});
});
it('should parse actor ()<<->>() actor syntax as CENTRAL_CONNECTION_DUAL', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Alice
participant Bob
Alice ()<<->>() Bob: Hello Bob, how are you?
`);
const messages = diagram.db.getMessages();
expect(messages).toHaveLength(3); // addMessage + centralConnection + centralConnectionReverse
const actualMessage = messages.find((msg) => msg.type !== undefined && msg.from && msg.to);
expect(actualMessage).toMatchObject({
from: 'Alice',
to: 'Bob',
message: 'Hello Bob, how are you?',
centralConnection: 61, // CENTRAL_CONNECTION_DUAL
activate: true,
type: 33, // BIDIRECTIONAL_SOLID
});
});
it('should handle multiple central connection types in one diagram', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Alice
participant Bob
participant Charlie
Alice ()->>() Bob: Message 1
Bob ()-->> Charlie: Message 2
Charlie ()<<-->>() Alice: Message 3
`);
const messages = diagram.db.getMessages();
expect(messages).toHaveLength(8); // 3 addMessages + 5 central connection markers
// Filter to get only the actual messages
const actualMessages = messages.filter((msg) => msg.type !== undefined && msg.from && msg.to);
expect(actualMessages).toHaveLength(3);
expect(actualMessages[0]).toMatchObject({
from: 'Alice',
to: 'Bob',
centralConnection: 61, // CENTRAL_CONNECTION_DUAL (()->>())
});
expect(actualMessages[1]).toMatchObject({
from: 'Bob',
to: 'Charlie',
centralConnection: 60, // CENTRAL_CONNECTION_REVERSE (()-->>)
});
expect(actualMessages[2]).toMatchObject({
from: 'Charlie',
to: 'Alice',
centralConnection: 61, // CENTRAL_CONNECTION_DUAL (()<<-->>())
});
});
it('should handle central connections with different arrow types', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Alice
participant Bob
Alice ()-x() Bob: Cross message
Alice ()--x() Bob: Dotted cross message
`);
const messages = diagram.db.getMessages();
expect(messages).toHaveLength(6); // 2 addMessages + 4 central connection markers
const actualMessages = messages.filter((msg) => msg.type !== undefined && msg.from && msg.to);
expect(actualMessages).toHaveLength(2);
expect(actualMessages[0]).toMatchObject({
from: 'Alice',
to: 'Bob',
centralConnection: 61, // CENTRAL_CONNECTION_DUAL (()-x())
type: 3, // SOLID_CROSS
});
expect(actualMessages[1]).toMatchObject({
from: 'Alice',
to: 'Bob',
centralConnection: 61, // CENTRAL_CONNECTION_DUAL (()--x())
type: 4, // DOTTED_CROSS
});
});
it('should not break existing parsing without central connections', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Alice
participant Bob
Alice ->> Bob: Normal message
Bob -->> Alice: Normal dotted message
Alice -x Bob: Normal cross message
`);
const messages = diagram.db.getMessages();
expect(messages).toHaveLength(3);
messages.forEach((msg) => {
expect(msg.centralConnection).toBe(0); // No central connection
});
expect(messages[0].type).toBe(0); // SOLID (based on actual parsing)
expect(messages[1].type).toBe(1); // DOTTED (based on actual parsing)
expect(messages[2].type).toBe(3); // SOLID_CROSS
});
});
});
describe('when parsing a sequenceDiagram', function () { describe('when parsing a sequenceDiagram', function () {
let diagram; let diagram;
beforeEach(async function () { beforeEach(async function () {
@@ -2058,6 +2312,36 @@ Bob->>Alice:Got it!
expect(messages[0].from).toBe('Alice'); expect(messages[0].from).toBe('Alice');
expect(messages[0].to).toBe('Bob'); expect(messages[0].to).toBe('Bob');
}); });
it('1 should parse ', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
actor Bob
actor Alice
Bob -|\\ Alice: Hello Alice, how are you?
Bob -|/ Alice: Hello Alice, how are you?
Bob -// Alice: Hello Alice, how are you?
Bob -\\\\ Alice: Hello Alice, how are you?
Bob \\|- Alice: Hello Alice, how are you?
Bob /|- Alice: Hello Alice, how are you?
Bob //- Alice: Hello Alice, how are you?
Bob \\\\- Alice: Hello Alice, how are you?
`);
const messages = diagram.db.getMessages();
});
it('2 should parse ', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
actor Bob
actor Alice
Alice ()<<->>() Bob: hey?
`);
const messages = diagram.db.getMessages();
});
describe('when parsing extended participant syntax', () => { describe('when parsing extended participant syntax', () => {
it('should parse participants with different quote styles and whitespace', async () => { it('should parse participants with different quote styles and whitespace', async () => {
const diagram = await Diagram.fromText(` const diagram = await Diagram.fromText(`
@@ -2325,74 +2609,17 @@ Bob->>Alice:Got it!
expect(actors.get('E').type).toBe('entity'); expect(actors.get('E').type).toBe('entity');
expect(actors.get('E').description).toBe('E'); expect(actors.get('E').description).toBe('E');
}); });
}); it('should handle fail parsing when alias token causes conflicts in participant definition', async () => {
let error = false;
describe('image and icon participant parsing', () => { try {
it('should parse image participant with image URL', async () => { await Diagram.fromText(`
const diagram = await Diagram.fromText(`
sequenceDiagram sequenceDiagram
participant Bob@{ "type": "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" } participant SAS MyServiceWithMoreThan20Chars <br> service decription
Bob->>Bob: test `);
`); } catch (e) {
const actors = diagram.db.getActors(); error = true;
expect(actors.get('Bob').type).toBe('image'); }
expect(actors.get('Bob').doc.image).toBe( expect(error).toBe(true);
'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg'
);
});
it('should parse icon participant with icon name', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Alice@{ "type": "icon", "icon": "fa:bell" }
Alice->>Alice: test
`);
const actors = diagram.db.getActors();
expect(actors.get('Alice').type).toBe('icon');
expect(actors.get('Alice').doc.icon).toBe('fa:bell');
});
it('should parse two image participants', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Bob@{ "type": "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
participant Alice@{ "type": "image", "image": "https://cdn.pixabay.com/photo/2016/11/29/09/32/animal-1867121_1280.jpg" }
Bob->>Alice: Hello
Alice-->>Bob: Hi
`);
const actors = diagram.db.getActors();
expect(actors.get('Bob').type).toBe('image');
expect(actors.get('Bob').doc.image).toBe(
'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg'
);
expect(actors.get('Alice').type).toBe('image');
expect(actors.get('Alice').doc.image).toBe(
'https://cdn.pixabay.com/photo/2016/11/29/09/32/animal-1867121_1280.jpg'
);
});
it('should parse image participant with normal participant', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Bob@{ "type": "image", "image": "https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg" }
participant Alice
Bob->>Alice: Hello
`);
const actors = diagram.db.getActors();
expect(actors.get('Bob').type).toBe('image');
expect(actors.get('Alice').type).toBe('participant');
});
it('should parse icon participant with normal participant', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Bob@{ "type": "icon", "icon": "fa:bell" }
participant Alice
Bob->>Alice: Hello
`);
const actors = diagram.db.getActors();
expect(actors.get('Bob').type).toBe('icon');
expect(actors.get('Alice').type).toBe('participant');
}); });
}); });
}); });

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