Compare commits

..

57 Commits

Author SHA1 Message Date
knsv
c777f9193d Update docs 2023-04-03 10:35:19 +00:00
Knut Sveidqvist
917a54f3cd Merge branch 'develop' into 4220-string-synax-and-features 2023-04-03 12:31:56 +02:00
Knut Sveidqvist
471c842a58 Adding rendering tests and unit tests 2023-04-03 12:12:51 +02:00
Knut Sveidqvist
99f65813a1 Syntax for markdown strings is a single backtick. 2023-04-03 10:43:15 +02:00
Sidharth Vinod
7e610d13dc Merge pull request #4207 from aloisklink/test/4198-fix-gantt-today-marker-tests
Fix broken Gantt  `todayMarker` tests
2023-03-31 18:23:06 +05:30
knsv
f9c0f1d46f Update docs 2023-03-31 06:46:34 +00:00
Knut Sveidqvist
3823ecafb1 Merge pull request #4238 from JeremyFunk/feature/1618_repeating_tasks
Implement repeating tasks
2023-03-31 08:43:13 +02:00
Knut Sveidqvist
057c9e4b81 Merge branch 'develop' into feature/1618_repeating_tasks 2023-03-31 08:42:10 +02:00
Knut Sveidqvist
c4e4efd4b8 Merge pull request #4258 from mermaid-js/sidv/fix/4256
fix(#4256): Keep error diagram on screen
2023-03-31 08:34:53 +02:00
Knut Sveidqvist
da066553bd Merge pull request #4257 from mermaid-js/sidv/fix/4137
fix(#4137): Cleanup comments before parsing
2023-03-31 08:32:55 +02:00
Sidharth Vinod
006da82470 fix: Remove comment line completely 2023-03-31 00:35:56 +05:30
Sidharth Vinod
1945a62990 fix: trimStart to text 2023-03-31 00:25:33 +05:30
Sidharth Vinod
d16894daf4 test: add space before init 2023-03-31 00:18:53 +05:30
Sidharth Vinod
4d933f6b72 Merge pull request #4253 from remcohaszing/export-mermaid-type
Define and export the Mermaid type
2023-03-30 23:56:48 +05:30
Sidharth Vinod
7739302ee8 fix uncaughexception in tests 2023-03-30 23:28:41 +05:30
Sidharth Vinod
46ab6f46f2 fix(#4256): Keep error diagram on screen 2023-03-30 23:09:46 +05:30
Sidharth Vinod
48d267c6dc fix(#4137): Cleanup comments before parsing 2023-03-30 22:08:50 +05:30
Jeremy Funk
15af3ea585 Update docs 2023-03-29 23:53:12 +02:00
Remco Haszing
2dd6329872 Define and export the Mermaid type
This represents the type of the default export. This is useful when it’s
being passed around or declared as a global.
2023-03-29 16:55:58 +02:00
Knut Sveidqvist
507a518a91 Bugfix for port selection when using diamonds in elk layout of flowcharts 2023-03-29 16:17:59 +02:00
Knut Sveidqvist
4caf7d7c7b Adding support for markdown string in flowchart-elk 2023-03-29 16:01:08 +02:00
Knut Sveidqvist
89193d7360 Simple markdown in lock file 2023-03-29 09:35:42 +02:00
Knut Sveidqvist
89eec225ce Merge branch 'develop' into 4220-string-synax-and-features 2023-03-29 09:34:49 +02:00
Knut Sveidqvist
cbc2df1ff6 Merge branch 'develop' into feature/1618_repeating_tasks 2023-03-29 09:23:18 +02:00
Knut Sveidqvist
e4a2c74b1b Merge pull request #4247 from kshitijsaksena/bug/4137_fix_comment_bug
Updated render to remove comments from text
2023-03-28 16:26:54 +02:00
Knut Sveidqvist
63160293c7 Updating support for the new type of strings for flowcharts-v2 2023-03-28 15:28:52 +02:00
Knut Sveidqvist
9c0cb3f320 Merge pull request #4249 from aloisklink/build/remove-use-inline-specifiers-lockfile-format-from-npmrc
Remove inline-specifiers pnpm option from `.npmrc` file to avoid merge conflicts
2023-03-27 16:27:30 +02:00
Knut Sveidqvist
fbeb016398 test commit 2023-03-27 14:43:59 +02:00
Alois Klink
093f1697e1 build: remove inline-specifiers pnpm option
Remove the `use-inline-specifiers-lockfile-format=true` pnpm option
from our `.npmrc` file.

This was added in
[PNPM version v7.7.0](https://github.com/pnpm/pnpm/releases/tag/v7.7.0)
and should make our `pnpm-lock.yaml` file much nicer,
but unfortunately, renovate doesn't seem to support it (unsure why?).

This means that whenever we do a `pnpm install` locally, the lock-file
gets changed, and whenever renovate makes a PR, it changes the
lock-file back. This causes a lot of unnecassary merge conflicts.
2023-03-25 21:16:45 +00:00
Alois Klink
f56e0bd530 Merge pull request #4246 from piradata/patch-1
Fix hexagon node flowchart code example in docs
2023-03-25 21:09:57 +00:00
PIRADATA
022e6670d0 docs: fix hexagon node flowchart code example
Use `mermaid-example` instead of `mmd` so that Mermaid formats
the code properly.
2023-03-25 20:13:04 +00:00
Kshitij
e3760d1709 Fixed regex bug 2023-03-25 20:13:30 +05:30
Kshitij
0475591fb6 Updated render to remove comments from text 2023-03-25 15:46:52 +05:30
Jeremy Funk
ba1c5dc6c7 Change to using display mode yaml 2023-03-25 01:56:50 +01:00
Jeremy Funk
2f8c571a5c Fix unit test 2023-03-24 00:37:25 +01:00
Jeremy Funk
a70b3a881d Add comment 2023-03-24 00:22:52 +01:00
Jeremy Funk
950f560d81 Refactor 2023-03-24 00:20:36 +01:00
Jeremy Funk
fd9680a050 Fix bug 2023-03-24 00:18:52 +01:00
Jeremy Funk
2d815e9626 Add documentation 2023-03-24 00:09:06 +01:00
Jeremy Funk
8c0550b2b7 Code refactoring, add e2e test 2023-03-23 23:45:59 +01:00
Jeremy Funk
f054609e02 Add test, fix typo 2023-03-23 22:58:46 +01:00
Jeremy Funk
45c0c5fee0 Bugfix 2023-03-23 22:54:58 +01:00
Jeremy Funk
a535fe1679 Bugfixes, refactor, add compact 2023-03-23 22:38:04 +01:00
Alois Klink
e4d2118d4b Merge pull request #4231 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update pnpm to v7.30.1
2023-03-23 20:04:30 +00:00
Alois Klink
1184fce148 Merge pull request #4237 from xuanxu/patch-1
Fix typos in timeline docs
2023-03-23 20:00:39 +00:00
Alois Klink
a79f118323 Merge pull request #4230 from vorburger/patch-1
docs: Remove repeated phrase
2023-03-23 19:58:11 +00:00
Juanjo Bazán
6cba2ea02d docs: fix typos in timeline.md 2023-03-23 19:46:17 +00:00
Michael Vorburger ⛑️
3add711c55 docs: Remove repeated phrase 2023-03-23 19:42:33 +00:00
renovate[bot]
1481a8ccb1 chore(deps): update pnpm to v7.30.1 2023-03-23 19:04:24 +00:00
Jeremy Funk
b3b7108d59 Implement basic repeating tasks 2023-03-22 23:15:54 +01:00
Knut Sveidqvist
fd9ad95346 #4220 Handling paragraphs and html labels with classes in mindmaps. 2023-03-22 18:41:31 +01:00
Knut Sveidqvist
a1c50b8079 #4220 Parsing the text as markdown and rendering accordingly 2023-03-20 14:15:26 +01:00
renovate[bot]
8b37ceffe1 chore(deps): update pnpm to v7.30.0 2023-03-20 04:21:23 +00:00
Alois Klink
7647ae317a Merge pull request #4228 from remcohaszing/update-types-lodash-es
Update @types/lodash-es
2023-03-17 18:52:30 +00:00
Remco Haszing
8c69ecd5ac Update @types/lodash-es
This adds support for the TypeScript `"moduleResolution": "node16"`.
2023-03-17 12:26:41 +01:00
Knut Sveidqvist
853d9b7f98 #4220 Create text utility functions handling new lines and applying them on mindmap 2023-03-14 13:52:20 +01:00
Alois Klink
58d4ba0d8f test(e2e): fix gantt todayMarker tests
The gantt diagram that were supposed to test whether
`todayMarker off` works wasn't working properly, because
`todayMarker on` wasn't working (i.e. the test never failed).

I've fixed this issue, and added a test that checks whether
`todayMarker on` works.

Fixes: https://github.com/mermaid-js/mermaid/issues/4198
2023-03-09 19:18:22 +00:00
69 changed files with 2085 additions and 720 deletions

1
.npmrc
View File

@@ -1,3 +1,2 @@
auto-install-peers=true
strict-peer-dependencies=false
use-inline-specifiers-lockfile-format=true

View File

@@ -47,7 +47,6 @@
"graphviz",
"grav",
"greywolf",
"huynh",
"inkdrop",
"jaoude",
"jison",
@@ -91,7 +90,6 @@
"sidharthv",
"sphinxcontrib",
"statediagram",
"steph",
"stylis",
"substate",
"sveidqvist",

View File

@@ -10,7 +10,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render an ER diagram with a recursive relationship', () => {
@@ -23,7 +22,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render an ER diagram with multiple relationships between the same two entities', () => {
@@ -35,7 +33,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render a cyclical ER diagram', () => {
@@ -48,7 +45,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render a not-so-simple ER diagram', () => {
@@ -66,7 +62,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render multiple ER diagrams', () => {
@@ -85,7 +80,6 @@ describe('Entity Relationship Diagram', () => {
],
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render an ER diagram with blank or empty labels', () => {
@@ -98,7 +92,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render an ER diagrams when useMaxWidth is true (default)', () => {
@@ -151,7 +144,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ er: { useMaxWidth: false } }
);
cy.get('svg');
});
it('should render entities with and without attributes', () => {
@@ -164,7 +156,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with generic and array attributes', () => {
@@ -179,7 +170,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with length in attributes type', () => {
@@ -193,7 +183,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities and attributes with big and small entity names', () => {
@@ -209,7 +198,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with keys', () => {
@@ -228,7 +216,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with comments', () => {
@@ -247,7 +234,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with keys and comments', () => {
@@ -267,7 +253,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with aliases', () => {
@@ -285,7 +270,6 @@ describe('Entity Relationship Diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('1433: should render a simple ER diagram with a title', () => {

View File

@@ -0,0 +1,45 @@
import { imgSnapshotTest } from '../../helpers/util';
describe('Error Diagrams', () => {
beforeEach(() => {
cy.on('uncaught:exception', (err) => {
expect(err.message).to.include('Parse error');
// return false to prevent the error from
// failing this test
return false;
});
});
it('should render a simple ER diagram', () => {
imgSnapshotTest(
`
error
`,
{ logLevel: 1 }
);
});
it('should render error diagram for actual errors', () => {
imgSnapshotTest(
`
flowchart TD
A[Christmas] --|Get money| B(Go shopping)
`,
{ logLevel: 1 }
);
});
it('should render error for wrong ER diagram', () => {
imgSnapshotTest(
`
erDiagram
ATLAS-ORGANIZATION ||--|{ ATLAS-PROJECTS : "has many"
ATLAS-PROJECTS ||--|{ MONGODB-CLUSTERS : "has many"
ATLAS-PROJECTS ||--|{ ATLAS-TEAMS : "has many"
MONGODB-CLUSTERS ||..|{
ATLAS-TEAMS ||..|{
`,
{ logLevel: 1 }
);
});
});

View File

@@ -684,4 +684,149 @@ A --> B
{ titleTopMargin: 0 }
);
});
describe('Markdown strings flowchart-elk (#4220)', () => {
describe('html labels', () => {
it('With styling and classes', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart-elk LR
A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
classDef someclass fill:#f96
`,
{ titleTopMargin: 0 }
);
});
it('With formatting in a node', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart-elk LR
a{"\`The **cat** in the hat\`"} -- 1o --> b
a -- 2o --> c
a -- 3o --> d
g --2i--> a
d --1i--> a
h --3i -->a
b --> d(The dog in the hog)
c --> d
`,
{ titleTopMargin: 0 }
);
});
it('New line in node and formatted edge label', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart-elk LR
b("\`The dog in **the** hog.(1)
NL\`") --"\`1o **bold**\`"--> c
`,
{ titleTopMargin: 0 }
);
});
it('Wrapping long text with a new line', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart-elk LR
b(\`The dog in **the** hog.(1).. a a a a *very long text* about it
Word!
Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`) --> c
`,
{ titleTopMargin: 0 }
);
});
it('Sub graphs and markdown strings', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart-elk LR
subgraph "One"
a("\`The **cat**
in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}}
end
subgraph "\`**Two**\`"
c("\`The **cat**
in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog")
end
`,
{ titleTopMargin: 0 }
);
});
});
describe('svg text labels', () => {
it('With styling and classes', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart-elk LR
A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
classDef someclass fill:#f96
`,
{ titleTopMargin: 0 }
);
});
it('With formatting in a node', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart-elk LR
a{"\`The **cat** in the hat\`"} -- 1o --> b
a -- 2o --> c
a -- 3o --> d
g --2i--> a
d --1i--> a
h --3i -->a
b --> d(The dog in the hog)
c --> d
`,
{ titleTopMargin: 0 }
);
});
it('New line in node and formatted edge label', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart-elk LR
b("\`The dog in **the** hog.(1)
NL\`") --"\`1o **bold**\`"--> c
`,
{ titleTopMargin: 0 }
);
});
it('Wrapping long text with a new line', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart-elk LR
b("\`The dog in **the** hog.(1).. a a a a *very long text* about it
Word!
Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c
`,
{ titleTopMargin: 0 }
);
});
it('Sub graphs and markdown strings', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart-elk LR
subgraph "One"
a("\`The **cat**
in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}}
end
subgraph "\`**Two**\`"
c("\`The **cat**
in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog")
end
`,
{ titleTopMargin: 0 }
);
});
});
});
});

View File

@@ -685,4 +685,149 @@ A ~~~ B
{ titleTopMargin: 0 }
);
});
describe('Markdown strings flowchart (#4220)', () => {
describe('html labels', () => {
it('With styling and classes', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart LR
A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
classDef someclass fill:#f96
`,
{ titleTopMargin: 0 }
);
});
it('With formatting in a node', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart LR
a{"\`The **cat** in the hat\`"} -- 1o --> b
a -- 2o --> c
a -- 3o --> d
g --2i--> a
d --1i--> a
h --3i -->a
b --> d(The dog in the hog)
c --> d
`,
{ titleTopMargin: 0 }
);
});
it('New line in node and formatted edge label', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart LR
b("\`The dog in **the** hog.(1)
NL\`") --"\`1o **bold**\`"--> c
`,
{ titleTopMargin: 0 }
);
});
it('Wrapping long text with a new line', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart LR
b("\`The dog in **the** hog.(1).. a a a a *very long text* about it
Word!
Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c
`,
{ titleTopMargin: 0 }
);
});
it('Sub graphs and markdown strings', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart LR
subgraph "One"
a("\`The **cat**
in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}}
end
subgraph "\`**Two**\`"
c("\`The **cat**
in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog")
end
`,
{ titleTopMargin: 0 }
);
});
});
describe('svg text labels', () => {
it('With styling and classes', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
classDef someclass fill:#f96
`,
{ titleTopMargin: 0 }
);
});
it('With formatting in a node', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
a{"\`The **cat** in the hat\`"} -- 1o --> b
a -- 2o --> c
a -- 3o --> d
g --2i--> a
d --1i--> a
h --3i -->a
b --> d(The dog in the hog)
c --> d
`,
{ titleTopMargin: 0 }
);
});
it('New line in node and formatted edge label', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
b("\`The dog in **the** hog.(1)
NL\`") --"\`1o **bold**\`"--> c
`,
{ titleTopMargin: 0 }
);
});
it('Wrapping long text with a new line', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
b("\`The dog in **the** hog.(1).. a a a a *very long text* about it
Word!
Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c
`,
{ titleTopMargin: 0 }
);
});
it('Sub graphs and markdown strings', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
subgraph "One"
a("\`The **cat**
in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}}
end
subgraph "\`**Two**\`"
c("\`The **cat**
in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog")
end
`,
{ titleTopMargin: 0 }
);
});
});
});
});

View File

@@ -133,6 +133,24 @@ describe('Gantt diagram', () => {
);
});
it('should default to showing today marker', () => {
// This test only works if the environment thinks today is 1010-10-10
imgSnapshotTest(
`
gantt
title Show today marker (vertical line should be visible)
dateFormat YYYY-MM-DD
axisFormat %d
%% Should default to being on
%% todayMarker on
section Section1
Yesterday: 1010-10-09, 1d
Today: 1010-10-10, 1d
`,
{}
);
});
it('should hide today marker', () => {
imgSnapshotTest(
`
@@ -142,7 +160,8 @@ describe('Gantt diagram', () => {
axisFormat %d
todayMarker off
section Section1
Today: 1, -1h
Yesterday: 1010-10-09, 1d
Today: 1010-10-10, 1d
`,
{}
);
@@ -157,7 +176,8 @@ describe('Gantt diagram', () => {
axisFormat %d
todayMarker stroke-width:5px,stroke:#00f,opacity:0.5
section Section1
Today: 1, -1h
Yesterday: 1010-10-09, 1d
Today: 1010-10-10, 1d
`,
{}
);
@@ -435,4 +455,39 @@ describe('Gantt diagram', () => {
{ gantt: { topAxis: true } }
);
});
it('should render when compact is true', () => {
imgSnapshotTest(
`
---
displayMode: compact
---
gantt
title GANTT compact
dateFormat HH:mm:ss
axisFormat %Hh%M
section DB Clean
Clean: 12:00:00, 10m
Clean: 12:30:00, 12m
Clean: 13:00:00, 8m
Clean: 13:30:00, 9m
Clean: 14:00:00, 13m
Clean: 14:30:00, 10m
Clean: 15:00:00, 11m
section Sessions
A: 12:00:00, 63m
B: 12:30:00, 12m
C: 13:05:00, 12m
D: 13:06:00, 33m
E: 13:15:00, 55m
F: 13:20:00, 12m
G: 13:32:00, 18m
H: 13:50:00, 20m
I: 14:10:00, 10m
`,
{}
);
});
});

View File

@@ -223,5 +223,18 @@ mindmap
shouldHaveRoot
);
});
describe('Markdown strings mindmaps (#4220)', () => {
it('Formatted label with linebreak and a wrapping label and emojis', () => {
imgSnapshotTest(
`mindmap
id1[\`**Start** with
a second line 😎\`]
id2[\`The dog in **the** hog... a *very long text* about it
Word!\`]
`,
{ titleTopMargin: 0 }
);
});
});
/* The end */
});

View File

@@ -51,27 +51,48 @@
font-family: monospace;
font-size: 72px;
}
/* tspan {
font-size: 6px !important;
} */
</style>
</head>
<body>
<pre id="diagram" class="mermaid">
%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
graph BT
a{The cat in the hat} -- 1o --> b
a -- 2o --> c
a -- 3o --> d
g --2i--> a
d --1i--> a
h --3i -->a
b --> d(The dog in the hog)
c --> d
</pre>
%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart-elk LR
b(`The dog in **the** hog(2)... a a a a *very long text* about it
Word!
Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. `)
</pre
>
<pre id="diagram" class="mermaid2">
flowchart-elk TB
a --> b
a --> c
b --> d
c --> d
flowchart-elk LR
b("The dog in the hog... a very<br/>long text about it<br/>Word!")
</pre>
<pre id="diagram" class="mermaid2">
flowchart-elk LR
b("The dog in the hog... a very<br/>long text about it<br/>Word!")
</pre>
>
<pre id="diagram" class="mermaid2">
mindmap
id1[`**Start2**
second line 😎 with long text that is wrapping to the next line`]
id2[`Child **with bold** text`]
id3[`Children of which some
is using *italic type of* text`]
id4[Child]
id5[`Child
Row
and another
`]
</pre>
<pre id="diagram" class="mermaid">
mindmap
id1["`**Start** with
a second line 😎`"]
id2["`The dog in **the** hog... a *very long text* about it
Word!`"]
</pre>
<pre id="diagram" class="mermaid2">
%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
@@ -272,12 +293,14 @@ mindmap
mermaid.initialize({
theme: 'forest',
startOnLoad: true,
logLevel: 5,
logLevel: 0,
flowchart: {
// defaultRenderer: 'elk',
useMaxWidth: false,
htmlLabels: true,
htmlLabels: false,
// htmlLabels: true,
},
// htmlLabels: true,
gantt: {
useMaxWidth: false,
},

View File

@@ -47,7 +47,6 @@ const contentLoaded = async function () {
await mermaid2.registerExternalDiagrams([externalExample]);
mermaid2.initialize(graphObj.mermaid);
await mermaid2.run();
markRendered();
}
};
@@ -123,7 +122,6 @@ const contentLoadedApi = async function () {
bindFunctions(div);
}
}
markRendered();
};
if (typeof document !== 'undefined') {
@@ -135,10 +133,10 @@ if (typeof document !== 'undefined') {
function () {
if (this.location.href.match('xss.html')) {
this.console.log('Using api');
void contentLoadedApi();
void contentLoadedApi().finally(markRendered);
} else {
this.console.log('Not using api');
void contentLoaded();
void contentLoaded().finally(markRendered);
}
},
false

38
demos/error.html Normal file
View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Error | Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
</head>
<body>
<pre class="mermaid">
erDiagram
ATLAS-ORGANIZATION ||--|{ ATLAS-PROJECTS : "has many"
ATLAS-PROJECTS ||--|{ MONGODB-CLUSTERS : "has many"
ATLAS-PROJECTS ||--|{ ATLAS-TEAMS : "has many"
</pre>
<pre class="mermaid">
erDiagram
ATLAS-ORGANIZATION ||--|{ ATLAS-PROJECTS : "has many"
ATLAS-PROJECTS ||--|{ MONGODB-CLUSTERS : "has many"
ATLAS-PROJECTS ||--|{ ATLAS-TEAMS : "has many"
MONGODB-CLUSTERS ||..|{
ATLAS-TEAMS ||..|{
</pre>
<hr />
<pre class="mermaid">
flowchart TD
A[Christmas] -->|Get money| B(Go shopping)
</pre>
<pre class="mermaid">
flowchart TD
A[Christmas] --|Get money| B(Go shopping)
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
</script>
</body>
</html>

View File

@@ -78,7 +78,7 @@
axisFormat %d/%m
todayMarker off
section Section1
Today: 1, -01:00, 5min
Today: 1, 08-08-09-01:00, 5min
</pre>
<hr />
@@ -89,7 +89,7 @@
axisFormat %d/%m
todayMarker stroke-width:5px,stroke:#00f,opacity:0.5
section Section1
Today: 1, -01:00, 5min
Today: 1, 08-08-09-01:00, 5min
</pre>
<hr />
@@ -166,6 +166,37 @@
</pre>
<hr />
<pre class="mermaid">
---
displayMode: compact
---
gantt
title GANTT compact
dateFormat HH:mm:ss
axisFormat %Hh%M
section DB Clean
Clean: 12:00:00, 10m
Clean: 12:30:00, 12m
Clean: 13:00:00, 8m
Clean: 13:30:00, 9m
Clean: 14:00:00, 13m
Clean: 14:30:00, 10m
Clean: 15:00:00, 11m
section Sessions
A: 12:00:00, 63m
B: 12:30:00, 12m
C: 13:05:00, 12m
D: 13:06:00, 33m
E: 13:15:00, 55m
F: 13:20:00, 12m
G: 13:32:00, 18m
H: 13:50:00, 20m
I: 14:10:00, 10m
</pre>
<hr />
<script>
function ganttTestClick(a, b, c) {
console.log('a:', a);

View File

@@ -16,4 +16,4 @@
#### Defined in
[mermaidAPI.ts:70](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L70)
[mermaidAPI.ts:77](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L77)

View File

@@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
#### Defined in
[mermaidAPI.ts:91](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L91)
[mermaidAPI.ts:98](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L98)
---
@@ -51,4 +51,4 @@ The svg code for the rendered graph.
#### Defined in
[mermaidAPI.ts:81](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L81)
[mermaidAPI.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L88)

View File

@@ -14,7 +14,7 @@
#### Defined in
[defaultConfig.ts:2093](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L2093)
[defaultConfig.ts:2115](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L2115)
---

View File

@@ -25,7 +25,7 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi)
#### Defined in
[mermaidAPI.ts:75](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L75)
[mermaidAPI.ts:82](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L82)
## Variables
@@ -88,6 +88,7 @@ const config = {
numberSectionStyles: 4,
axisFormat: '%Y-%m-%d',
topAxis: false,
displayMode: '',
},
};
mermaid.initialize(config);
@@ -95,7 +96,7 @@ mermaid.initialize(config);
#### Defined in
[mermaidAPI.ts:659](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L659)
[mermaidAPI.ts:667](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L667)
## Functions
@@ -126,7 +127,7 @@ Return the last node appended
#### Defined in
[mermaidAPI.ts:305](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L305)
[mermaidAPI.ts:312](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L312)
---
@@ -152,7 +153,7 @@ the cleaned up svgCode
#### Defined in
[mermaidAPI.ts:256](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L256)
[mermaidAPI.ts:263](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L263)
---
@@ -178,7 +179,7 @@ the string with all the user styles
#### Defined in
[mermaidAPI.ts:185](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L185)
[mermaidAPI.ts:192](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L192)
---
@@ -201,7 +202,7 @@ the string with all the user styles
#### Defined in
[mermaidAPI.ts:233](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L233)
[mermaidAPI.ts:240](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L240)
---
@@ -228,7 +229,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
#### Defined in
[mermaidAPI.ts:169](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L169)
[mermaidAPI.ts:176](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L176)
---
@@ -248,7 +249,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
#### Defined in
[mermaidAPI.ts:149](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L149)
[mermaidAPI.ts:156](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L156)
---
@@ -268,7 +269,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
#### Defined in
[mermaidAPI.ts:120](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L120)
[mermaidAPI.ts:127](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L127)
---
@@ -294,7 +295,7 @@ Put the svgCode into an iFrame. Return the iFrame code
#### Defined in
[mermaidAPI.ts:284](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L284)
[mermaidAPI.ts:291](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L291)
---
@@ -319,4 +320,4 @@ Remove any existing elements from the given document
#### Defined in
[mermaidAPI.ts:355](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L355)
[mermaidAPI.ts:362](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L362)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -183,8 +183,6 @@ flowchart LR
### A hexagon node
Code:
```mermaid-example
flowchart LR
id1{{This is the text in the box}}

View File

@@ -257,9 +257,41 @@ The pattern is:
More info in: <https://github.com/d3/d3-time#interval_every>
## Output in compact mode
The compact mode allows you to display multiple tasks in the same row. Compact mode can be enabled for a gantt chart by setting the display mode of the graph via preceeding YAML settings.
```mermaid-example
---
displayMode: compact
---
gantt
title A Gantt Diagram
dateFormat YYYY-MM-DD
section Section
A task :a1, 2014-01-01, 30d
Another task :a2, 2014-01-20, 25d
Another one :a3, 2014-02-10, 20d
```
```mermaid
---
displayMode: compact
---
gantt
title A Gantt Diagram
dateFormat YYYY-MM-DD
section Section
A task :a1, 2014-01-01, 30d
Another task :a2, 2014-01-20, 25d
Another one :a3, 2014-02-10, 20d
```
## Comments
Comments can be entered within a gantt chart, which will be ignored by the parser. Comments need to be on their own line and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any diagram syntax
Comments can be entered within a gantt chart, which will be ignored by the parser. Comments need to be on their own line and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any diagram syntax.
```mermaid-example
gantt

View File

@@ -8,7 +8,7 @@
> Timeline: This is an experimental diagram for now. The syntax and properties can change in future releases. The syntax is stable except for the icon integration which is the experimental part.
"A timeline is a type of diagram used to illustrate a chronology of events, dates, or periods of time. It is usually presented graphically to indicate the passing of time, and it is usually organized chronologically. A basic timeline presents a list of events in chronological order, usually using dates as markers. A timeline can also be used to show the relationship between events, such as the relationship between the events of a person's life. A timeline can also be used to show the relationship between events, such as the relationship between the events of a person's life." Wikipedia
"A timeline is a type of diagram used to illustrate a chronology of events, dates, or periods of time. It is usually presented graphically to indicate the passing of time, and it is usually organized chronologically. A basic timeline presents a list of events in chronological order, usually using dates as markers. A timeline can also be used to show the relationship between events, such as the relationship between the events of a person's life." Wikipedia
### An example of a timeline.
@@ -213,7 +213,7 @@ However, if there is no section defined, then we have two possibilities:
```
Note that this is no, section defined, and each time period and its corresponding events will have its own color scheme.
Note that there are no sections defined, and each time period and its corresponding events will have its own color scheme.
2. Disable the multiColor option using the `disableMultiColor` option. This will make all time periods and events follow the same color scheme.
@@ -257,7 +257,7 @@ let us look at same example, where we have disabled the multiColor option.
### Customizing Color scheme
You can customize the color scheme using the `cScale0` to `cScale11` theme variables. Mermaid allows you to set unique colors for up-to 12, where `cScale0` variable will drive the value of the first section or time-period, `cScale1` will drive the value of the second section and so on.
You can customize the color scheme using the `cScale0` to `cScale11` theme variables. Mermaid allows you to set unique colors for up-to 12 sections, where `cScale0` variable will drive the value of the first section or time-period, `cScale1` will drive the value of the second section and so on.
In case you have more than 12 sections, the color scheme will start to repeat.
NOTE: Default values for these theme variables are picked from the selected theme. If you want to override the default values, you can use the `initialize` call to add your custom theme variable values.

View File

@@ -4,7 +4,7 @@
"version": "10.0.2",
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"type": "module",
"packageManager": "pnpm@7.29.1",
"packageManager": "pnpm@7.30.1",
"keywords": [
"diagram",
"markdown",

View File

@@ -53,6 +53,7 @@
},
"dependencies": {
"@braintree/sanitize-url": "^6.0.0",
"@khanacademy/simple-markdown": "^0.8.6",
"cytoscape": "^3.23.0",
"cytoscape-cose-bilkent": "^4.1.0",
"cytoscape-fcose": "^2.1.0",
@@ -74,7 +75,7 @@
"@types/d3": "^7.4.0",
"@types/dompurify": "^2.4.0",
"@types/jsdom": "^21.0.0",
"@types/lodash-es": "^4.17.6",
"@types/lodash-es": "^4.17.7",
"@types/micromatch": "^4.0.2",
"@types/prettier": "^2.7.1",
"@types/stylis": "^4.0.2",

View File

@@ -5,6 +5,7 @@ import { detectType, getDiagramLoader } from './diagram-api/detectType';
import { extractFrontMatter } from './diagram-api/frontmatter';
import { UnknownDiagramError } from './errors';
import { DetailedError } from './utils';
import { cleanupComments } from './diagram-api/comments';
export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?: any) => void;
@@ -43,7 +44,10 @@ export class Diagram {
// Similarly, we can't do this in getDiagramFromText() because some code
// calls diagram.db.clear(), which would reset anything set by
// extractFrontMatter().
this.parser.parse = (text: string) => originalParse(extractFrontMatter(text, this.db));
this.parser.parse = (text: string) =>
originalParse(cleanupComments(extractFrontMatter(text, this.db)));
this.parser.parser.yy = this.db;
if (diagram.init) {
diagram.init(cnf);

View File

@@ -3,6 +3,7 @@ import { getConfig } from './config';
let title = '';
let diagramTitle = '';
let description = '';
const sanitizeText = (txt: string): string => _sanitizeText(txt, getConfig());
export const clear = function (): void {
@@ -36,10 +37,10 @@ export const getDiagramTitle = function (): string {
};
export default {
setAccTitle,
getAccTitle,
setAccTitle,
getDiagramTitle,
setDiagramTitle,
getDiagramTitle: getDiagramTitle,
getAccDescription,
setAccDescription,
clear,

View File

@@ -335,6 +335,7 @@ export interface GanttDiagramConfig extends BaseDiagramConfig {
axisFormat?: string;
tickInterval?: string;
topAxis?: boolean;
displayMode?: string;
}
export interface SequenceDiagramConfig extends BaseDiagramConfig {
@@ -385,6 +386,7 @@ export interface FlowchartDiagramConfig extends BaseDiagramConfig {
curve?: string;
padding?: number;
defaultRenderer?: string;
wrappingWidth?: number;
}
export interface FontConfig {

View File

@@ -1,12 +1,13 @@
import intersectRect from './intersect/intersect-rect';
import { log } from '../logger';
import createLabel from './createLabel';
import { createText } from '../rendering-util/createText';
import { select } from 'd3';
import { getConfig } from '../config';
import { evaluate } from '../diagrams/common/common';
const rect = (parent, node) => {
log.trace('Creating subgraph rect for ', node.id, node);
log.info('Creating subgraph rect for ', node.id, node);
// Add outer g element
const shapeSvg = parent
@@ -17,12 +18,18 @@ const rect = (parent, node) => {
// add the rect
const rect = shapeSvg.insert('rect', ':first-child');
const useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels);
// Create the label and insert it after the rect
const label = shapeSvg.insert('g').attr('class', 'cluster-label');
const text = label
.node()
.appendChild(createLabel(node.labelText, node.labelStyle, undefined, true));
// const text = label
// .node()
// .appendChild(createLabel(node.labelText, node.labelStyle, undefined, true));
const text =
node.labelType === 'markdown'
? createText(label, node.labelText, { style: node.labelStyle, useHtmlLabels })
: label.node().appendChild(createLabel(node.labelText, node.labelStyle, undefined, true));
// Get the size of the label
let bbox = text.getBBox();
@@ -61,7 +68,7 @@ const rect = (parent, node) => {
'transform',
// This puts the labal on top of the box instead of inside it
// 'translate(' + (node.x - bbox.width / 2) + ', ' + (node.y - node.height / 2 - bbox.height) + ')'
'translate(' + (node.x - bbox.width / 2) + ', ' + (node.y - node.height / 2) + ')'
'translate(' + node.x + ', ' + (node.y - node.height / 2) + ')'
);
const rectBox = rect.node().getBBox();

View File

@@ -41,7 +41,13 @@ function addHtmlLabel(node) {
div.attr('xmlns', 'http://www.w3.org/1999/xhtml');
return fo.node();
}
/**
* @param _vertexText
* @param style
* @param isTitle
* @param isNode
* @deprecated svg-util/createText instead
*/
const createLabel = (_vertexText, style, isTitle, isNode) => {
let vertexText = _vertexText || '';
if (typeof vertexText === 'object') {

View File

@@ -1,5 +1,6 @@
import { log } from '../logger';
import createLabel from './createLabel';
import { createText } from '../rendering-util/createText';
import { line, curveBasis, select } from 'd3';
import { getConfig } from '../config';
import utils from '../utils';
@@ -14,8 +15,17 @@ export const clear = () => {
};
export const insertEdgeLabel = (elem, edge) => {
const useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels);
// Create the actual text element
const labelElement = createLabel(edge.label, edge.labelStyle);
const labelElement =
edge.labelType === 'markdown'
? createText(elem, edge.label, {
style: edge.labelStyle,
useHtmlLabels,
addSvgBackground: true,
})
: createLabel(edge.label, edge.labelStyle);
log.info('abc82', edge, edge.labelType);
// Create outer g, edgeLabel, this will be positioned after graph layout
const edgeLabel = elem.insert('g').attr('class', 'edgeLabel');
@@ -26,7 +36,7 @@ export const insertEdgeLabel = (elem, edge) => {
// Center the label
let bbox = labelElement.getBBox();
if (evaluate(getConfig().flowchart.htmlLabels)) {
if (useHtmlLabels) {
const div = labelElement.children[0];
const dv = select(labelElement);
bbox = div.getBoundingClientRect();

View File

@@ -313,19 +313,18 @@ const cylinder = (parent, node) => {
const rect = (parent, node) => {
const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, 'node ' + node.classes, true);
log.trace('Classes = ', node.classes);
// add the rect
const rect = shapeSvg.insert('rect', ':first-child');
const totalWidth = bbox.width + node.padding;
const totalHeight = bbox.height + node.padding;
const totalWidth = bbox.width + node.padding * 2;
const totalHeight = bbox.height + node.padding * 2;
rect
.attr('class', 'basic label-container')
.attr('style', node.style)
.attr('rx', node.rx)
.attr('ry', node.ry)
.attr('x', -bbox.width / 2 - halfPadding)
.attr('y', -bbox.height / 2 - halfPadding)
.attr('x', -bbox.width / 2 - node.padding)
.attr('y', -bbox.height / 2 - node.padding)
.attr('width', totalWidth)
.attr('height', totalHeight);
@@ -352,7 +351,7 @@ const rect = (parent, node) => {
const labelRect = (parent, node) => {
const { shapeSvg } = labelHelper(parent, node, 'label', true);
log.trace('Classes = ', node.classes);
log.info('Classes = ', node.classes);
// add the rect
const rect = shapeSvg.insert('rect', ':first-child');

View File

@@ -1,4 +1,5 @@
import createLabel from '../createLabel';
import { createText } from '../../rendering-util/createText';
import { getConfig } from '../../config';
import { decodeEntities } from '../../mermaidAPI';
import { select } from 'd3';
@@ -27,9 +28,17 @@ export const labelHelper = (parent, node, _classes, isNode) => {
labelText = typeof node.labelText === 'string' ? node.labelText : node.labelText[0];
}
const text = label
.node()
.appendChild(
const textNode = label.node();
let text;
if (node.labelType === 'markdown') {
// text = textNode;
text = createText(label, sanitizeText(decodeEntities(labelText), getConfig()), {
useHtmlLabels: getConfig().flowchart.htmlLabels,
width: node.width || getConfig().flowchart.wrappingWidth,
classes: 'markdown-node-label',
});
} else {
text = textNode.appendChild(
createLabel(
sanitizeText(decodeEntities(labelText), getConfig()),
node.labelStyle,
@@ -37,6 +46,7 @@ export const labelHelper = (parent, node, _classes, isNode) => {
isNode
)
);
}
// Get the size of the label
let bbox = text.getBBox();
@@ -52,8 +62,12 @@ export const labelHelper = (parent, node, _classes, isNode) => {
const halfPadding = node.padding / 2;
// Center the label
label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')');
if (getConfig().flowchart.htmlLabels) {
label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')');
} else {
label.attr('transform', 'translate(' + 0 + ', ' + -bbox.height / 2 + ')');
}
label.insert('rect', ':first-child');
return { shapeSvg, bbox, halfPadding, label };
};

View File

@@ -258,6 +258,18 @@ const config: Partial<MermaidConfig> = {
* Default value: 'dagre-wrapper'
*/
defaultRenderer: 'dagre-wrapper',
/**
* | Parameter | Description | Type | Required | Values |
* | --------------- | ----------- | ------- | -------- | ----------------------- |
* | wrappingWidth | See notes | number | 4 | width of nodes where text is wrapped |
*
* **Notes:**
*
* When using markdown strings the text ius wrapped automatically, this
* value sets the max width of a text before it continues on a new line.
* Default value: 'dagre-wrapper'
*/
wrappingWidth: 200,
},
/** The object containing configurations specific for sequence diagrams */
@@ -659,6 +671,17 @@ const config: Partial<MermaidConfig> = {
*/
numberSectionStyles: 4,
/**
* | Parameter | Description | Type | Required | Values |
* | ----------- | ------------------------- | ------ | -------- | --------- |
* | displayMode | Controls the display mode | string | 4 | 'compact' |
*
* **Notes**:
*
* - **compact**: Enables displaying multiple tasks on the same row.
*/
displayMode: '',
/**
* | Parameter | Description | Type | Required | Values |
* | ---------- | ---------------------------- | ---- | -------- | ---------------- |
@@ -684,7 +707,6 @@ const config: Partial<MermaidConfig> = {
* Default value: undefined
*/
tickInterval: undefined,
/**
* | Parameter | Description | Type | Required | Values |
* | ----------- | ----------- | ------- | -------- | ----------- |

View File

@@ -0,0 +1,94 @@
// tests to check that comments are removed
import { cleanupComments } from './comments';
import { describe, it, expect } from 'vitest';
describe('comments', () => {
it('should remove comments', () => {
const text = `
%% This is a comment
%% This is another comment
graph TD
A-->B
%% This is a comment
`;
expect(cleanupComments(text)).toMatchInlineSnapshot(`
"graph TD
A-->B
"
`);
});
it('should keep init statements when removing comments', () => {
const text = `
%% This is a comment
%% This is another comment
%%{init: {'theme': 'forest'}}%%
%%{ init: {'theme': 'space before init'}}%%
%%{init: {'theme': 'space after ending'}}%%
graph TD
A-->B
B-->C
%% This is a comment
`;
expect(cleanupComments(text)).toMatchInlineSnapshot(`
"%%{init: {'theme': 'forest'}}%%
%%{ init: {'theme': 'space before init'}}%%
%%{init: {'theme': 'space after ending'}}%%
graph TD
A-->B
B-->C
"
`);
});
it('should remove indented comments', () => {
const text = `
%% This is a comment
graph TD
A-->B
%% This is a comment
C-->D
`;
expect(cleanupComments(text)).toMatchInlineSnapshot(`
"graph TD
A-->B
C-->D
"
`);
});
it('should remove empty newlines from start', () => {
const text = `
%% This is a comment
graph TD
A-->B
`;
expect(cleanupComments(text)).toMatchInlineSnapshot(`
"graph TD
A-->B
"
`);
});
it('should remove comments at end of text with no newline', () => {
const text = `
graph TD
A-->B
%% This is a comment`;
expect(cleanupComments(text)).toMatchInlineSnapshot(`
"graph TD
A-->B
"
`);
});
});

View File

@@ -0,0 +1,8 @@
/**
* Remove all lines starting with `%%` from the text that don't contain a `%%{`
* @param text - The text to remove comments from
* @returns cleaned text
*/
export const cleanupComments = (text: string): string => {
return text.trimStart().replace(/^\s*%%(?!{)[^\n]+\n?/gm, '');
};

View File

@@ -13,7 +13,7 @@ import classDiagramV2 from '../diagrams/class/classDetector-V2';
import state from '../diagrams/state/stateDetector';
import stateV2 from '../diagrams/state/stateDetector-V2';
import journey from '../diagrams/user-journey/journeyDetector';
import error from '../diagrams/error/errorDetector';
import errorDiagram from '../diagrams/error/errorDiagram';
import flowchartElk from '../diagrams/flowchart/elk/detector';
import timeline from '../diagrams/timeline/detector';
import mindmap from '../diagrams/mindmap/detector';
@@ -28,6 +28,9 @@ export const addDiagrams = () => {
// This is added here to avoid race-conditions.
// We could optimize the loading logic somehow.
hasLoadedDiagrams = true;
registerDiagram('error', errorDiagram, (text) => {
return text.toLowerCase().trim() === 'error';
});
registerDiagram(
'---',
// --- diagram type may appear if YAML front-matter is not parsed correctly
@@ -57,7 +60,6 @@ export const addDiagrams = () => {
);
// Ordering of detectors is important. The first one to return true will be used.
registerLazyLoadedDiagrams(
error,
c4,
classDiagramV2,
classDiagram,

View File

@@ -11,6 +11,8 @@ export const frontMatterRegex = /^-{3}\s*[\n\r](.*?)[\n\r]-{3}\s*[\n\r]+/s;
type FrontMatterMetadata = {
title?: string;
// Allows custom display modes. Currently used for compact mode in gantt charts.
displayMode?: string;
};
/**
@@ -33,6 +35,10 @@ export function extractFrontMatter(text: string, db: DiagramDb): string {
db.setDiagramTitle?.(parsed.title);
}
if (parsed?.displayMode) {
db.setDisplayMode?.(parsed.displayMode);
}
return text.slice(matches[0].length);
} else {
return text;

View File

@@ -16,6 +16,7 @@ export interface InjectUtils {
export interface DiagramDb {
clear?: () => void;
setDiagramTitle?: (title: string) => void;
setDisplayMode?: (title: string) => void;
getAccTitle?: () => string;
getAccDescription?: () => string;
bindFunctions?: (element: Element) => void;

View File

@@ -19,8 +19,6 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
\%%(?!\{)[^\n]* /* skip comments */
[^\}]\%\%[^\n]* /* skip comments */
[\n]+ return 'NEWLINE';
\s+ /* skip whitespace */
[\s]+ return 'SPACE';
@@ -35,8 +33,6 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
<block>[A-Za-z_][A-Za-z0-9\-_\[\]\(\)]* return 'ATTRIBUTE_WORD'
<block>\"[^"]*\" return 'COMMENT';
<block>[\n]+ /* nothing */
<block>\%%(?!\{)[^\n]* /* skip comments in attribute block */
<block>[^\}]\%\%[^\n]* /* skip comments in attribute block */
<block>"}" { this.popState(); return 'BLOCK_STOP'; }
<block>. return yytext[0];

View File

@@ -1,20 +0,0 @@
import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types';
const id = 'error';
const detector: DiagramDetector = (text) => {
return text.toLowerCase().trim() === 'error';
};
const loader = async () => {
const { diagram } = await import('./errorDiagram');
return { id, diagram };
};
const plugin: ExternalDiagramDefinition = {
id,
detector,
loader,
};
export default plugin;

View File

@@ -19,3 +19,5 @@ export const diagram: DiagramDefinition = {
// no op
},
};
export default diagram;

View File

@@ -4,15 +4,13 @@ import { select } from 'd3';
import { log } from '../../logger';
import { getErrorMessage } from '../../utils';
let conf = {};
/**
* Merges the value of `conf` with the passed `cnf`
*
* @param cnf - Config to merge
*/
export const setConf = function (cnf: any) {
conf = { ...conf, ...cnf };
export const setConf = function () {
// no-op
};
/**
@@ -78,7 +76,7 @@ export const draw = (_text: string, id: string, mermaidVersion: string) => {
.attr('y', 250)
.attr('font-size', '150px')
.style('text-anchor', 'middle')
.text('Syntax error in graph');
.text('Syntax error in text');
g.append('text') // text label for the x axis
.attr('class', 'error-text')
.attr('x', 1250)

View File

@@ -3,6 +3,7 @@ import { insertNode } from '../../../dagre-wrapper/nodes.js';
import insertMarkers from '../../../dagre-wrapper/markers.js';
import { insertEdgeLabel } from '../../../dagre-wrapper/edges.js';
import { findCommonAncestor } from './render-utils';
import { labelHelper } from '../../../dagre-wrapper/shapes/util';
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';
import { getConfig } from '../../../config';
import { log } from '../../../logger';
@@ -12,7 +13,7 @@ import { interpolateToCurve, getStylesFromArray } from '../../../utils';
import ELK from 'elkjs/lib/elk.bundled.js';
const elk = new ELK();
const portPos = {};
let portPos = {};
const conf = {};
export const setConf = function (cnf) {
@@ -52,7 +53,7 @@ export const addVertices = function (vert, svgId, root, doc, diagObj, parentLook
if (vertex.classes.length > 0) {
classStr = vertex.classes.join(' ');
}
classStr = classStr + ' flowchart-label';
const styles = getStylesFromArray(vertex.styles);
// Use vertex id as text in the box if no text is provided by the graph definition
@@ -61,40 +62,6 @@ export const addVertices = function (vert, svgId, root, doc, diagObj, parentLook
// We create a SVG label, either by delegating to addHtmlLabel or manually
let vertexNode;
const labelData = { width: 0, height: 0 };
if (evaluate(getConfig().flowchart.htmlLabels)) {
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
const node = {
label: vertexText.replace(
/fa[blrs]?:fa-[\w-]+/g,
(s) => `<i class='${s.replace(':', ' ')}'></i>`
),
};
vertexNode = addHtmlLabel(svg, node).node();
const bbox = vertexNode.getBBox();
labelData.width = bbox.width;
labelData.height = bbox.height;
labelData.labelNode = vertexNode;
vertexNode.parentNode.removeChild(vertexNode);
} else {
const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text');
svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:'));
const rows = vertexText.split(common.lineBreakRegex);
for (const row of rows) {
const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan');
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
tspan.setAttribute('dy', '1em');
tspan.setAttribute('x', '1');
tspan.textContent = row;
svgLabel.appendChild(tspan);
}
vertexNode = svgLabel;
const bbox = vertexNode.getBBox();
labelData.width = bbox.width;
labelData.height = bbox.height;
labelData.labelNode = vertexNode;
}
const ports = [
{
@@ -186,11 +153,13 @@ export const addVertices = function (vert, svgId, root, doc, diagObj, parentLook
default:
_shape = 'rect';
}
// Add the node
const node = {
labelStyle: styles.labelStyle,
shape: _shape,
labelText: vertexText,
labelType: vertex.labelType,
rx: radious,
ry: radious,
class: classStr,
@@ -209,10 +178,33 @@ export const addVertices = function (vert, svgId, root, doc, diagObj, parentLook
};
let boundingBox;
let nodeEl;
// Add the element to the DOM
if (node.type !== 'group') {
nodeEl = insertNode(nodes, node, vertex.dir);
boundingBox = nodeEl.node().getBBox();
} else {
const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text');
// svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:'));
// const rows = vertexText.split(common.lineBreakRegex);
// for (const row of rows) {
// const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan');
// tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
// tspan.setAttribute('dy', '1em');
// tspan.setAttribute('x', '1');
// tspan.textContent = row;
// svgLabel.appendChild(tspan);
// }
// vertexNode = svgLabel;
// const bbox = vertexNode.getBBox();
const { shapeSvg, bbox } = labelHelper(nodes, node, undefined, true);
labelData.width = bbox.width;
labelData.wrappingWidth = getConfig().flowchart.wrappingWidth;
labelData.height = bbox.height;
labelData.labelNode = shapeSvg.node();
node.labelData = labelData;
}
// const { shapeSvg, bbox } = labelHelper(svg, node, undefined, true);
const data = {
id: vertex.id,
@@ -520,7 +512,7 @@ export const addEdges = function (edges, diagObj, graph, svg) {
edgeData.labelpos = 'c';
}
edgeData.labelType = 'text';
edgeData.labelType = edge.labelType;
edgeData.label = edge.text.replace(common.lineBreakRegex, '\n');
if (edge.style === undefined) {
@@ -775,6 +767,7 @@ export const draw = async function (text, id, _version, diagObj) {
// Add temporary render element
diagObj.db.clear();
nodeDb = {};
portPos = {};
diagObj.db.setGen('gen-2');
// Parse the graph definition
diagObj.parser.parse(text);
@@ -845,9 +838,17 @@ export const draw = async function (text, id, _version, diagObj) {
log.info('Subgraphs - ', subGraphs);
for (let i = subGraphs.length - 1; i >= 0; i--) {
subG = subGraphs[i];
diagObj.db.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir);
diagObj.db.addVertex(
subG.id,
{ text: subG.title, type: subG.labelType },
'group',
undefined,
subG.classes,
subG.dir
);
}
// debugger;
// Add an element in the svg to be used to hold the subgraphs container
// elements
const subGraphsEl = svg.insert('g').attr('class', 'subgraphs');
@@ -860,7 +861,7 @@ export const draw = async function (text, id, _version, diagObj) {
// in order to get the size of the node. You can't get the size of a node
// that is not in the dom so we need to add it to the dom, get the size
// we will position the nodes when we get the layout from elkjs
graph = addVertices(vert, id, root, doc, diagObj, parentLookupDb, graph);
graph = addVertices(vert, id, root, doc, diagObj, parentLookupDb, graph, svg);
// Time for the edges, we start with adding an element in the node to hold the edges
const edgesEl = svg.insert('g').attr('class', 'edges edgePath');
@@ -887,6 +888,8 @@ export const draw = async function (text, id, _version, diagObj) {
},
width: node.labelData.width,
height: node.labelData.height,
// width: 100,
// height: 100,
},
];
delete node.x;
@@ -895,6 +898,7 @@ export const draw = async function (text, id, _version, diagObj) {
delete node.height;
}
});
insertChildren(graph.children, parentLookupDb);
log.info('after layout', JSON.stringify(graph, null, 2));
const g = await elk.layout(graph);

View File

@@ -81,7 +81,7 @@ const getStyles = (options: FlowChartStyleOptions) =>
.edgeLabel {
background-color: ${options.edgeLabelBackground};
rect {
opacity: 0.5;
opacity: 0.85;
background-color: ${options.edgeLabelBackground};
fill: ${options.edgeLabelBackground};
}
@@ -132,6 +132,11 @@ const getStyles = (options: FlowChartStyleOptions) =>
// fill:#ccc;
// // stroke:black;
// }
.flowchart-label text {
text-anchor: middle;
}
${genSections(options)}
`;

View File

@@ -59,13 +59,14 @@ export const lookUpDomId = function (id) {
*
* @param _id
* @param text
* @param textObj
* @param type
* @param style
* @param classes
* @param dir
* @param props
*/
export const addVertex = function (_id, text, type, style, classes, dir, props = {}) {
export const addVertex = function (_id, textObj, type, style, classes, dir, props = {}) {
let txt;
let id = _id;
if (id === undefined) {
@@ -80,16 +81,17 @@ export const addVertex = function (_id, text, type, style, classes, dir, props =
if (vertices[id] === undefined) {
vertices[id] = {
id: id,
labelType: 'text',
domId: MERMAID_DOM_ID_PREFIX + id + '-' + vertexCounter,
styles: [],
classes: [],
};
}
vertexCounter++;
if (text !== undefined) {
if (textObj !== undefined) {
config = configApi.getConfig();
txt = sanitizeText(text.trim());
txt = sanitizeText(textObj.text.trim());
vertices[id].labelType = textObj.type;
// strip quotes if string starts and ends with a quote
if (txt[0] === '"' && txt[txt.length - 1] === '"') {
txt = txt.substring(1, txt.length - 1);
@@ -131,24 +133,27 @@ export const addVertex = function (_id, text, type, style, classes, dir, props =
* @param _end
* @param type
* @param linkText
* @param linkTextObj
*/
export const addSingleLink = function (_start, _end, type, linkText) {
export const addSingleLink = function (_start, _end, type) {
let start = _start;
let end = _end;
// if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start;
// if (end[0].match(/\d/)) end = MERMAID_DOM_ID_PREFIX + end;
// log.info('Got edge...', start, end);
const edge = { start: start, end: end, type: undefined, text: '' };
linkText = type.text;
const edge = { start: start, end: end, type: undefined, text: '', labelType: 'text' };
log.info('abc78 Got edge...', edge);
const linkTextObj = type.text;
if (linkText !== undefined) {
edge.text = sanitizeText(linkText.trim());
if (linkTextObj !== undefined) {
edge.text = sanitizeText(linkTextObj.text.trim());
// strip quotes if string starts and ends with a quote
if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') {
edge.text = edge.text.substring(1, edge.text.length - 1);
}
edge.labelType = linkTextObj.type;
}
if (type !== undefined) {
@@ -158,11 +163,12 @@ export const addSingleLink = function (_start, _end, type, linkText) {
}
edges.push(edge);
};
export const addLink = function (_start, _end, type, linktext) {
export const addLink = function (_start, _end, type) {
log.info('addLink (abc78)', _start, _end, type);
let i, j;
for (i = 0; i < _start.length; i++) {
for (j = 0; j < _end.length; j++) {
addSingleLink(_start[i], _end[j], type, linktext);
addSingleLink(_start[i], _end[j], type);
}
}
};
@@ -457,10 +463,9 @@ export const defaultStyle = function () {
* @param _title
*/
export const addSubGraph = function (_id, list, _title) {
// console.log('addSubGraph', _id, list, _title);
let id = _id.trim();
let title = _title;
if (_id === _title && _title.match(/\s/)) {
let id = _id.text.trim();
let title = _title.text;
if (_id === _title && _title.text.match(/\s/)) {
id = undefined;
}
/** @param a */
@@ -502,7 +507,14 @@ export const addSubGraph = function (_id, list, _title) {
title = title || '';
title = sanitizeText(title);
subCount = subCount + 1;
const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [], dir };
const subGraph = {
id: id,
nodes: nodeList,
title: title.trim(),
classes: [],
dir,
labelType: _title.type,
};
log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir);

View File

@@ -47,7 +47,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
if (vertex.classes.length > 0) {
classStr = vertex.classes.join(' ');
}
classStr = classStr + ' flowchart-label';
const styles = getStylesFromArray(vertex.styles);
// Use vertex id as text in the box if no text is provided by the graph definition
@@ -55,31 +55,36 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
// We create a SVG label, either by delegating to addHtmlLabel or manually
let vertexNode;
if (evaluate(getConfig().flowchart.htmlLabels)) {
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
const node = {
label: vertexText.replace(
/fa[blrs]?:fa-[\w-]+/g,
(s) => `<i class='${s.replace(':', ' ')}'></i>`
),
};
vertexNode = addHtmlLabel(svg, node).node();
vertexNode.parentNode.removeChild(vertexNode);
log.info('vertex', vertex, vertex.labelType);
if (vertex.labelType === 'markdown') {
log.info('vertex', vertex, vertex.labelType);
} else {
const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text');
svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:'));
if (evaluate(getConfig().flowchart.htmlLabels)) {
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
const node = {
label: vertexText.replace(
/fa[blrs]?:fa-[\w-]+/g,
(s) => `<i class='${s.replace(':', ' ')}'></i>`
),
};
vertexNode = addHtmlLabel(svg, node).node();
vertexNode.parentNode.removeChild(vertexNode);
} else {
const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text');
svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:'));
const rows = vertexText.split(common.lineBreakRegex);
const rows = vertexText.split(common.lineBreakRegex);
for (const row of rows) {
const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan');
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
tspan.setAttribute('dy', '1em');
tspan.setAttribute('x', '1');
tspan.textContent = row;
svgLabel.appendChild(tspan);
for (const row of rows) {
const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan');
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
tspan.setAttribute('dy', '1em');
tspan.setAttribute('x', '1');
tspan.textContent = row;
svgLabel.appendChild(tspan);
}
vertexNode = svgLabel;
}
vertexNode = svgLabel;
}
let radious = 0;
@@ -146,6 +151,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
labelStyle: styles.labelStyle,
shape: _shape,
labelText: vertexText,
labelType: vertex.labelType,
rx: radious,
ry: radious,
class: classStr,
@@ -165,6 +171,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
log.info('setNode', {
labelStyle: styles.labelStyle,
labelType: vertex.labelType,
shape: _shape,
labelText: vertexText,
rx: radious,
@@ -312,7 +319,7 @@ export const addEdges = function (edges, g, diagObj) {
edgeData.labelpos = 'c';
}
edgeData.labelType = 'text';
edgeData.labelType = edge.labelType;
edgeData.label = edge.text.replace(common.lineBreakRegex, '\n');
if (edge.style === undefined) {
@@ -405,7 +412,14 @@ export const draw = function (text, id, _version, diagObj) {
for (let i = subGraphs.length - 1; i >= 0; i--) {
subG = subGraphs[i];
log.info('Subgraph - ', subG);
diagObj.db.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir);
diagObj.db.addVertex(
subG.id,
{ text: subG.title, type: subG.labelType },
'group',
undefined,
subG.classes,
subG.dir
);
}
// Fetch the vertices/nodes and edges/links from the parsed graph definition

View File

@@ -1,6 +1,7 @@
import flowDb from '../flowDb';
import flow from './flow';
import { setConfig } from '../../../config';
import { cleanupComments } from '../../../diagram-api/comments';
setConfig({
securityLevel: 'strict',
@@ -13,7 +14,7 @@ describe('[Comments] when parsing', () => {
});
it('should handle comments', function () {
const res = flow.parser.parse('graph TD;\n%% Comment\n A-->B;');
const res = flow.parser.parse(cleanupComments('graph TD;\n%% Comment\n A-->B;'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
@@ -28,7 +29,7 @@ describe('[Comments] when parsing', () => {
});
it('should handle comments at the start', function () {
const res = flow.parser.parse('%% Comment\ngraph TD;\n A-->B;');
const res = flow.parser.parse(cleanupComments('%% Comment\ngraph TD;\n A-->B;'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
@@ -43,7 +44,7 @@ describe('[Comments] when parsing', () => {
});
it('should handle comments at the end', function () {
const res = flow.parser.parse('graph TD;\n A-->B\n %% Comment at the end\n');
const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n %% Comment at the end\n'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
@@ -58,7 +59,7 @@ describe('[Comments] when parsing', () => {
});
it('should handle comments at the end no trailing newline', function () {
const res = flow.parser.parse('graph TD;\n A-->B\n%% Comment');
const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n%% Comment'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
@@ -73,7 +74,7 @@ describe('[Comments] when parsing', () => {
});
it('should handle comments at the end many trailing newlines', function () {
const res = flow.parser.parse('graph TD;\n A-->B\n%% Comment\n\n\n');
const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n%% Comment\n\n\n'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
@@ -88,7 +89,7 @@ describe('[Comments] when parsing', () => {
});
it('should handle no trailing newlines', function () {
const res = flow.parser.parse('graph TD;\n A-->B');
const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
@@ -103,7 +104,7 @@ describe('[Comments] when parsing', () => {
});
it('should handle many trailing newlines', function () {
const res = flow.parser.parse('graph TD;\n A-->B\n\n');
const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n\n'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
@@ -118,7 +119,7 @@ describe('[Comments] when parsing', () => {
});
it('should handle a comment with blank rows in-between', function () {
const res = flow.parser.parse('graph TD;\n\n\n %% Comment\n A-->B;');
const res = flow.parser.parse(cleanupComments('graph TD;\n\n\n %% Comment\n A-->B;'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
@@ -134,7 +135,9 @@ describe('[Comments] when parsing', () => {
it('should handle a comment with mermaid flowchart code in them', function () {
const res = flow.parser.parse(
'graph TD;\n\n\n %% Test od>Odd shape]-->|Two line<br>edge comment|ro;\n A-->B;'
cleanupComments(
'graph TD;\n\n\n %% Test od>Odd shape]-->|Two line<br>edge comment|ro;\n A-->B;'
)
);
const vert = flow.parser.yy.getVertices();

View File

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

View File

@@ -7,6 +7,7 @@
/* lexical grammar */
%lex
%x string
%x md_string
%x acc_title
%x acc_descr
%x acc_descr_multiline
@@ -27,8 +28,6 @@
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
\%\%(?!\{)[^\n]* /* skip comments */
[^\}]\%\%[^\n]* /* skip comments */
accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; }
<acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; }
accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; }
@@ -37,6 +36,9 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
<acc_descr_multiline>[\}] { this.popState(); }
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
// <acc_descr_multiline>.*[^\n]* { return "acc_descr_line"}
["][`] { this.begin("md_string");}
<md_string>[^`"]+ { return "MD_STR";}
<md_string>[`]["] { this.popState();}
["] this.begin("string");
<string>["] this.popState();
<string>[^"]* return "STR";
@@ -434,11 +436,13 @@ arrowText:
;
text: textToken
{$$=$1;}
{ $$={text:$1, type: 'text'};}
| text textToken
{$$=$1+''+$2;}
{ $$={text:$1.text+''+$2, type: $1.type};}
| STR
{$$=$1;}
{ $$={text: $1, type: 'text'};}
| MD_STR
{ $$={text: $1, type: 'markdown'};}
;

View File

@@ -1,6 +1,7 @@
import flowDb from '../flowDb';
import flow from './flow';
import { setConfig } from '../../../config';
import { cleanupComments } from '../../../diagram-api/comments';
setConfig({
securityLevel: 'strict',
@@ -13,7 +14,7 @@ describe('parsing a flow chart', function () {
});
it('should handle a trailing whitespaces after statements', function () {
const res = flow.parser.parse('graph TD;\n\n\n %% Comment\n A-->B; \n B-->C;');
const res = flow.parser.parse(cleanupComments('graph TD;\n\n\n %% Comment\n A-->B; \n B-->C;'));
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();

View File

@@ -41,6 +41,15 @@ const getStyles = (options: FlowChartStyleOptions) =>
stroke: ${options.nodeBorder};
stroke-width: 1px;
}
.flowchart-label text {
text-anchor: middle;
}
// .flowchart-label .text-outer-tspan {
// text-anchor: middle;
// }
// .flowchart-label .text-inner-tspan {
// text-anchor: start;
// }
.node .label {
text-align: center;

View File

@@ -32,6 +32,7 @@ let links = {};
let sections = [];
let tasks = [];
let currentSection = '';
let displayMode = '';
const tags = ['active', 'done', 'crit', 'milestone'];
let funs = [];
let inclusiveEndDates = false;
@@ -55,6 +56,7 @@ export const clear = function () {
rawTasks = [];
dateFormat = '';
axisFormat = '';
displayMode = '';
tickInterval = undefined;
todayMarker = '';
includes = [];
@@ -110,6 +112,14 @@ export const topAxisEnabled = function () {
return topAxis;
};
export const setDisplayMode = function (txt) {
displayMode = txt;
};
export const getDisplayMode = function () {
return displayMode;
};
export const getDateFormat = function () {
return dateFormat;
};
@@ -143,11 +153,11 @@ export const getSections = function () {
};
export const getTasks = function () {
let allItemsPricessed = compileTasks();
let allItemsProcessed = compileTasks();
const maxDepth = 10;
let iterationCount = 0;
while (!allItemsPricessed && iterationCount < maxDepth) {
allItemsPricessed = compileTasks();
while (!allItemsProcessed && iterationCount < maxDepth) {
allItemsProcessed = compileTasks();
iterationCount++;
}
@@ -719,6 +729,8 @@ export default {
getAccTitle,
setDiagramTitle,
getDiagramTitle,
setDisplayMode,
getDisplayMode,
setAccDescription,
getAccDescription,
addSection,

View File

@@ -34,6 +34,7 @@ describe('when using the ganttDb', function () {
beforeEach(function () {
ganttDb.setDateFormat('YYYY-MM-DD');
ganttDb.enableInclusiveEndDates();
ganttDb.setDisplayMode('compact');
ganttDb.setTodayMarker('off');
ganttDb.setExcludes('weekends 2019-02-06,friday');
ganttDb.addSection('weekends skip test');
@@ -53,6 +54,7 @@ describe('when using the ganttDb', function () {
${'getExcludes'} | ${[]}
${'getSections'} | ${[]}
${'endDatesAreInclusive'} | ${false}
${'getDisplayMode'} | ${''}
`)('should clear $fn', ({ fn, expected }) => {
expect(ganttDb[fn]()).toEqual(expected);
});

View File

@@ -24,12 +24,43 @@ export const setConf = function () {
log.debug('Something is calling, setConf, remove the call');
};
/**
* For this issue:
* https://github.com/mermaid-js/mermaid/issues/1618
*
* Finds the number of intersections between tasks that happen at any point in time.
* Used to figure out how many rows are needed to display the tasks when the display
* mode is set to 'compact'.
*
* @param tasks
* @param orderOffset
*/
const getMaxIntersections = (tasks, orderOffset) => {
let timeline = [...tasks].map(() => -Infinity);
let sorted = [...tasks].sort((a, b) => a.startTime - b.startTime || a.order - b.order);
let maxIntersections = 0;
for (const element of sorted) {
for (let j = 0; j < timeline.length; j++) {
if (element.startTime >= timeline[j]) {
timeline[j] = element.endTime;
element.order = j + orderOffset;
if (j > maxIntersections) {
maxIntersections = j;
}
break;
}
}
}
return maxIntersections;
};
let w;
export const draw = function (text, id, version, diagObj) {
const conf = getConfig().gantt;
// diagObj.db.clear();
// parser.parse(text);
const securityLevel = getConfig().securityLevel;
// Handle root and Document for when rendering in sandbox mode
let sandboxElement;
@@ -56,7 +87,40 @@ export const draw = function (text, id, version, diagObj) {
const taskArray = diagObj.db.getTasks();
// Set height based on number of tasks
const h = taskArray.length * (conf.barHeight + conf.barGap) + 2 * conf.topPadding;
let categories = [];
for (const element of taskArray) {
categories.push(element.type);
}
categories = checkUnique(categories);
const categoryHeights = {};
let h = 2 * conf.topPadding;
if (diagObj.db.getDisplayMode() === 'compact' || conf.displayMode === 'compact') {
const categoryElements = {};
for (const element of taskArray) {
if (categoryElements[element.section] === undefined) {
categoryElements[element.section] = [element];
} else {
categoryElements[element.section].push(element);
}
}
let intersections = 0;
for (const category of Object.keys(categoryElements)) {
const categoryHeight = getMaxIntersections(categoryElements[category], intersections) + 1;
intersections += categoryHeight;
h += categoryHeight * (conf.barHeight + conf.barGap);
categoryHeights[category] = categoryHeight;
}
} else {
h += taskArray.length * (conf.barHeight + conf.barGap);
for (const category of categories) {
categoryHeights[category] = taskArray.filter((task) => task.type === category).length;
}
}
// Set viewBox
elem.setAttribute('viewBox', '0 0 ' + w + ' ' + h);
@@ -74,16 +138,6 @@ export const draw = function (text, id, version, diagObj) {
])
.rangeRound([0, w - conf.leftPadding - conf.rightPadding]);
let categories = [];
for (const element of taskArray) {
categories.push(element.type);
}
const catsUnfiltered = categories; // for vert labels
categories = checkUnique(categories);
/**
* @param a
* @param b
@@ -157,11 +211,15 @@ export const draw = function (text, id, version, diagObj) {
* @param w
*/
function drawRects(theArray, theGap, theTopPad, theSidePad, theBarHeight, theColorScale, w) {
// Get unique task orders. Required to draw the background rects when display mode is compact.
const uniqueTaskOrderIds = [...new Set(theArray.map((item) => item.order))];
const uniqueTasks = uniqueTaskOrderIds.map((id) => theArray.find((item) => item.order === id));
// Draw background rects covering the entire width of the graph, these form the section rows.
svg
.append('g')
.selectAll('rect')
.data(theArray)
.data(uniqueTasks)
.enter()
.append('rect')
.attr('x', 0)
@@ -582,12 +640,9 @@ export const draw = function (text, id, version, diagObj) {
* @param theTopPad
*/
function vertLabels(theGap, theTopPad) {
const numOccurances = [];
let prevGap = 0;
for (const [i, category] of categories.entries()) {
numOccurances[i] = [category, getCount(category, catsUnfiltered)];
}
const numOccurances = Object.keys(categoryHeights).map((d) => [d, categoryHeights[d]]);
svg
.append('g') // without doing this, impossible to put grid lines behind text
@@ -625,7 +680,6 @@ export const draw = function (text, id, version, diagObj) {
}
})
.attr('font-size', conf.sectionFontSize)
.attr('font-size', conf.sectionFontSize)
.attr('class', function (d) {
for (const [i, category] of categories.entries()) {
if (d[0] === category) {
@@ -682,31 +736,6 @@ export const draw = function (text, id, version, diagObj) {
}
return result;
}
/**
* From this stack exchange question:
* http://stackoverflow.com/questions/14227981/count-how-many-strings-in-an-array-have-duplicates-in-the-same-array
*
* @param arr
*/
function getCounts(arr) {
let i = arr.length; // const to loop over
const obj = {}; // obj to store results
while (i) {
obj[arr[--i]] = (obj[arr[i]] || 0) + 1; // count occurrences
}
return obj;
}
/**
* Get specific from everything
*
* @param word
* @param arr
*/
function getCount(word, arr) {
return getCounts(arr)[word] || 0;
}
};
export default {

View File

@@ -131,9 +131,10 @@ statement
| includes {yy.setIncludes($1.substr(9));$$=$1.substr(9);}
| todayMarker {yy.setTodayMarker($1.substr(12));$$=$1.substr(12);}
| title {yy.setDiagramTitle($1.substr(6));$$=$1.substr(6);}
| acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); }
| acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); }
| acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); } | section {yy.addSection($1.substr(8));$$=$1.substr(8);}
| acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); }
| acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); }
| acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); }
| section { yy.addSection($1.substr(8));$$=$1.substr(8); }
| clickStatement
| taskTxt taskData {yy.addTask($1,$2);$$='task';}
| directive

View File

@@ -167,12 +167,15 @@ function positionNodes(cy) {
export const draw = async (text, id, version, diagObj) => {
const conf = getConfig();
// console.log('Config: ', conf);
conf.htmlLabels = false;
// This is done only for throwing the error if the text is not valid.
diagObj.db.clear();
// Parse the graph definition
diagObj.parser.parse(text);
log.debug('Renering info diagram\n' + text);
log.debug('Renering mindmap diagram\n' + text, diagObj);
const securityLevel = getConfig().securityLevel;
// Handle root and Document for when rendering in sandbox mode

View File

@@ -12,6 +12,7 @@
%}
%x NODE
%x NSTR
%x NSTR2
%x ICON
%x CLASS
@@ -41,6 +42,9 @@
// !(-\() return 'NODE_ID';
[^\(\[\n\-\)\{\}]+ return 'NODE_ID';
<<EOF>> return 'EOF';
<NODE>["][`] { this.begin("NSTR2");}
<NSTR2>[^`"]+ { return "NODE_DESCR";}
<NSTR2>[`]["] { this.popState();}
<NODE>["] { yy.getLogger().trace('Starting NSTR');this.begin("NSTR");}
<NSTR>[^"]+ { yy.getLogger().trace('description:', yytext); return "NODE_DESCR";}
<NSTR>["] {this.popState();}

View File

@@ -70,5 +70,12 @@ const getStyles = (options) =>
.edge {
fill: none;
}
.mindmap-node-label {
dy: 1em;
alignment-baseline: middle;
text-anchor: middle;
dominant-baseline: middle;
text-align: center;
}
`;
export default getStyles;

View File

@@ -1,5 +1,6 @@
import { select } from 'd3';
import * as db from './mindmapDb';
import { createText } from '../../rendering-util/createText';
const MAX_SECTIONS = 12;
/**
@@ -11,7 +12,7 @@ function wrap(text, width) {
var text = select(this),
words = text
.text()
.split(/(\s+|<br>)/)
.split(/(\s+|<br\/>)/)
.reverse(),
word,
line = [],
@@ -28,10 +29,10 @@ function wrap(text, width) {
word = words[words.length - 1 - j];
line.push(word);
tspan.text(line.join(' ').trim());
if (tspan.node().getComputedTextLength() > width || word === '<br>') {
if (tspan.node().getComputedTextLength() > width || word === '<br/>') {
line.pop();
tspan.text(line.join(' ').trim());
if (word === '<br>') {
if (word === '<br/>') {
line = [''];
} else {
line = [word];
@@ -203,6 +204,7 @@ const roundedRectBkg = function (elem, node) {
* @returns {number} The height nodes dom element
*/
export const drawNode = function (elem, node, fullSection, conf) {
const htmlLabels = conf.htmlLabels;
const section = fullSection % (MAX_SECTIONS - 1);
const nodeElem = elem.append('g');
node.section = section;
@@ -215,15 +217,21 @@ export const drawNode = function (elem, node, fullSection, conf) {
// Create the wrapped text element
const textElem = nodeElem.append('g');
const txt = textElem
.append('text')
.text(node.descr)
.attr('dy', '1em')
.attr('alignment-baseline', 'middle')
.attr('dominant-baseline', 'middle')
.attr('text-anchor', 'middle')
.call(wrap, node.width);
const bbox = txt.node().getBBox();
const newEl = createText(textElem, node.descr, {
useHtmlLabels: htmlLabels,
width: node.width,
classes: 'mindmap-node-label',
});
if (!htmlLabels) {
textElem
.attr('dy', '1em')
.attr('alignment-baseline', 'middle')
.attr('dominant-baseline', 'middle')
.attr('text-anchor', 'middle');
}
// .call(wrap, node.width);
const bbox = textElem.node().getBBox();
const fontSize = conf.fontSize.replace ? conf.fontSize.replace('px', '') : conf.fontSize;
node.height = bbox.height + fontSize * 1.1 * 0.5 + node.padding;
node.width = bbox.width + 2 * node.padding;
@@ -267,7 +275,16 @@ export const drawNode = function (elem, node, fullSection, conf) {
);
}
} else {
textElem.attr('transform', 'translate(' + node.width / 2 + ', ' + node.padding / 2 + ')');
if (!htmlLabels) {
const dx = node.width / 2;
const dy = node.padding / 2;
textElem.attr('transform', 'translate(' + dx + ', ' + dy + ')');
// textElem.attr('transform', 'translate(' + node.width / 2 + ', ' + node.padding / 2 + ')');
} else {
const dx = (node.width - bbox.width) / 2;
const dy = (node.height - bbox.height) / 2;
textElem.attr('transform', 'translate(' + dx + ', ' + dy + ')');
}
}
switch (node.type) {

View File

@@ -29,12 +29,6 @@ export default defineConfig({
socialLinks: [
{ icon: 'github', link: 'https://github.com/mermaid-js/mermaid' },
{ icon: 'slack', link: 'https://mermaid-talk.slack.com' },
{
icon: {
svg: '<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 490.16 490.16"><defs><mask id="Mask"><rect x="0" y="0" width="490.16" height="490.16" fill="white" /><path fill="black" d="M407.48,111.18A165.2,165.2,0,0,0,245.08,220,165.2,165.2,0,0,0,82.68,111.18a165.5,165.5,0,0,0,72.06,143.64,88.81,88.81,0,0,1,38.53,73.45v50.86H296.9V328.27a88.8,88.8,0,0,1,38.52-73.45,165.41,165.41,0,0,0,72.06-143.64Z"/><path fill="black" d="M160.63,328.27a56.09,56.09,0,0,0-24.27-46.49,198.74,198.74,0,0,1-28.54-23.66A196.87,196.87,0,0,1,82.53,227V379.13h78.1Z"/><path fill="black" d="M329.53,328.27a56.09,56.09,0,0,1,24.27-46.49,198.74,198.74,0,0,0,28.54-23.66A196.87,196.87,0,0,0,407.63,227V379.13h-78.1Z"/></mask><style>.cls-1{fill:#76767B;}.cls-1:hover{fill:#FF3570}</style></defs><rect class="cls-1" width="490.16" height="490.16" rx="84.61" mask="url(#Mask)" /></svg>',
},
link: 'https://www.mermaidchart.com/',
},
],
},
});

View File

@@ -23,15 +23,15 @@ features:
- title: Easy to use!
details: Easily create and render detailed diagrams and charts with the Mermaid Live Editor.
link: https://mermaid.live/
- title: 🎥 Video Tutorials!
details: Curated list of video tutorials and examples created by the community.
link: ../../config/Tutorials.html
- title: 🧩 Integrations available!
details: Use Mermaid with your favorite applications, check out the integrations list.
link: ../../ecosystem/integrations.md
- title: 🏆 Award winning!
details: 2019 JavaScript Open Source Award winner for "The Most Exciting Use of Technology".
link: https://osawards.com/javascript/2019
- title: 🥰 Mermaid + Mermaid Chart
details: Mermaid Chart is a major supporter of the Mermaid project.
link: https://www.mermaidchart.com/
---
<script setup>
@@ -149,12 +149,6 @@ const members = [
title: "Developer",
links: [{ icon: "github", link: "https://github.com/spopida" }],
},
{
avatar: "https://avatars.githubusercontent.com/u/35910788?v=4",
name: "Steph Huynh",
title: "Developer",
links: [{ icon: "github", link: "https://github.com/huynhicode" }],
},
];
</script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -122,9 +122,7 @@ flowchart LR
### A hexagon node
Code:
```mmd
```mermaid-example
flowchart LR
id1{{This is the text in the box}}
```

View File

@@ -189,9 +189,27 @@ The pattern is:
More info in: [https://github.com/d3/d3-time#interval_every](https://github.com/d3/d3-time#interval_every)
## Output in compact mode
The compact mode allows you to display multiple tasks in the same row. Compact mode can be enabled for a gantt chart by setting the display mode of the graph via preceeding YAML settings.
```mmd
---
displayMode: compact
---
gantt
title A Gantt Diagram
dateFormat YYYY-MM-DD
section Section
A task :a1, 2014-01-01, 30d
Another task :a2, 2014-01-20, 25d
Another one :a3, 2014-02-10, 20d
```
## Comments
Comments can be entered within a gantt chart, which will be ignored by the parser. Comments need to be on their own line and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any diagram syntax
Comments can be entered within a gantt chart, which will be ignored by the parser. Comments need to be on their own line and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any diagram syntax.
```mmd
gantt

View File

@@ -2,7 +2,7 @@
> Timeline: This is an experimental diagram for now. The syntax and properties can change in future releases. The syntax is stable except for the icon integration which is the experimental part.
"A timeline is a type of diagram used to illustrate a chronology of events, dates, or periods of time. It is usually presented graphically to indicate the passing of time, and it is usually organized chronologically. A basic timeline presents a list of events in chronological order, usually using dates as markers. A timeline can also be used to show the relationship between events, such as the relationship between the events of a person's life. A timeline can also be used to show the relationship between events, such as the relationship between the events of a person's life." Wikipedia
"A timeline is a type of diagram used to illustrate a chronology of events, dates, or periods of time. It is usually presented graphically to indicate the passing of time, and it is usually organized chronologically. A basic timeline presents a list of events in chronological order, usually using dates as markers. A timeline can also be used to show the relationship between events, such as the relationship between the events of a person's life." Wikipedia
### An example of a timeline.
@@ -139,7 +139,7 @@ However, if there is no section defined, then we have two possibilities:
```
Note that this is no, section defined, and each time period and its corresponding events will have its own color scheme.
Note that there are no sections defined, and each time period and its corresponding events will have its own color scheme.
2. Disable the multiColor option using the `disableMultiColor` option. This will make all time periods and events follow the same color scheme.
@@ -172,7 +172,7 @@ let us look at same example, where we have disabled the multiColor option.
### Customizing Color scheme
You can customize the color scheme using the `cScale0` to `cScale11` theme variables. Mermaid allows you to set unique colors for up-to 12, where `cScale0` variable will drive the value of the first section or time-period, `cScale1` will drive the value of the second section and so on.
You can customize the color scheme using the `cScale0` to `cScale11` theme variables. Mermaid allows you to set unique colors for up-to 12 sections, where `cScale0` variable will drive the value of the first section or time-period, `cScale1` will drive the value of the second section and so on.
In case you have more than 12 sections, the color scheme will start to repeat.
NOTE: Default values for these theme variables are picked from the selected theme. If you want to override the default values, you can use the `initialize` call to add your custom theme variable values.

View File

@@ -392,7 +392,7 @@ const render = (id: string, text: string, container?: Element): Promise<RenderRe
});
};
const mermaid: {
export interface Mermaid {
startOnLoad: boolean;
parseError?: ParseErrorFunction;
mermaidAPI: typeof mermaidAPI;
@@ -405,7 +405,9 @@ const mermaid: {
contentLoaded: typeof contentLoaded;
setParseErrorHandler: typeof setParseErrorHandler;
detectType: typeof detectType;
} = {
}
const mermaid: Mermaid = {
startOnLoad: true,
mermaidAPI,
parse,

View File

@@ -32,7 +32,14 @@ import { setA11yDiagramInfo, addSVGa11yTitleDescription } from './accessibility'
import { parseDirective } from './directiveUtils';
// diagram names that support classDef statements
const CLASSDEF_DIAGRAMS = ['graph', 'flowchart', 'flowchart-v2', 'stateDiagram', 'stateDiagram-v2'];
const CLASSDEF_DIAGRAMS = [
'graph',
'flowchart',
'flowchart-v2',
'flowchart-elk',
'stateDiagram',
'stateDiagram-v2',
];
const MAX_TEXTLENGTH = 50_000;
const MAX_TEXTLENGTH_EXCEEDED_MSG =
'graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa';
@@ -531,6 +538,10 @@ const render = async function (
attachFunctions();
if (parseEncounteredException) {
throw parseEncounteredException;
}
// -------------------------------------------------------------------------------
// Remove the temporary HTML element if appropriate
const tmpElementSelector = isSandboxed ? iFrameID_selector : enclosingDivID_selector;
@@ -539,10 +550,6 @@ const render = async function (
node.remove();
}
if (parseEncounteredException) {
throw parseEncounteredException;
}
return {
svg: svgCode,
bindFunctions: diag.db.bindFunctions,
@@ -650,6 +657,7 @@ function addA11yInfo(
* numberSectionStyles: 4,
* axisFormat: '%Y-%m-%d',
* topAxis: false,
* displayMode: '',
* },
* };
* mermaid.initialize(config);

View File

@@ -0,0 +1,232 @@
import { select } from 'd3';
import { log } from '../logger';
import { getConfig } from '../config';
import { evaluate } from '../diagrams/common/common';
import { decodeEntities } from '../mermaidAPI';
import { markdownToHTML, markdownToLines } from '../rendering-util/handle-markdown-text';
/**
* @param dom
* @param styleFn
*/
function applyStyle(dom, styleFn) {
if (styleFn) {
dom.attr('style', styleFn);
}
}
/**
* @param element
* @param {any} node
* @param width
* @param classes
* @returns {SVGForeignObjectElement} Node
*/
function addHtmlSpan(element, node, width, classes) {
const fo = element.append('foreignObject');
// const newEl = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
// const newEl = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
const div = fo.append('xhtml:div');
// const div = body.append('div');
// const div = fo.append('div');
const label = node.label;
const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel';
div.html(
`<span class="${labelClass} ${classes}" ` +
(node.labelStyle ? 'style="' + node.labelStyle + '"' : '') +
'>' +
label +
'</span>'
);
applyStyle(div, node.labelStyle);
div.style('display', 'table-cell');
div.style('white-space', 'nowrap');
div.style('max-width', width + 'px');
div.attr('xmlns', 'http://www.w3.org/1999/xhtml');
let bbox = div.node().getBoundingClientRect();
if (bbox.width === width) {
div.style('display', 'table');
div.style('white-space', 'break-spaces');
div.style('width', width + 'px');
bbox = div.node().getBoundingClientRect();
}
fo.style('width', bbox.width);
fo.style('height', bbox.height);
return fo.node();
}
/**
* Creates a tspan element with the specified attributes for text positioning.
*
* @param {object} textElement - The parent text element to append the tspan element.
* @param {number} lineIndex - The index of the current line in the structuredText array.
* @param {number} lineHeight - The line height value for the text.
* @returns {object} The created tspan element.
*/
function createTspan(textElement, lineIndex, lineHeight) {
return textElement
.append('tspan')
.attr('class', 'text-outer-tspan')
.attr('x', 0)
.attr('y', lineIndex * lineHeight - 0.1 + 'em')
.attr('dy', lineHeight + 'em');
}
/**
* Creates a formatted text element by breaking lines and applying styles based on
* the given structuredText.
*
* @param {number} width - The maximum allowed width of the text.
* @param {object} g - The parent group element to append the formatted text.
* @param {Array} structuredText - The structured text data to format.
* @param addBackground
*/
function createFormattedText(width, g, structuredText, addBackground = false) {
const lineHeight = 1.1;
const labelGroup = g.append('g');
let bkg = labelGroup.insert('rect').attr('class', 'background');
const textElement = labelGroup.append('text').attr('y', '-10.1');
// .attr('dominant-baseline', 'middle')
// .attr('text-anchor', 'middle');
// .attr('text-anchor', 'middle');
let lineIndex = -1;
structuredText.forEach((line) => {
lineIndex++;
let tspan = createTspan(textElement, lineIndex, lineHeight);
let words = [...line].reverse();
let currentWord;
let wrappedLine = [];
while (words.length) {
currentWord = words.pop();
wrappedLine.push(currentWord);
updateTextContentAndStyles(tspan, wrappedLine);
if (tspan.node().getComputedTextLength() > width) {
wrappedLine.pop();
words.push(currentWord);
updateTextContentAndStyles(tspan, wrappedLine);
wrappedLine = [];
lineIndex++;
tspan = createTspan(textElement, lineIndex, lineHeight);
}
}
});
if (addBackground) {
const bbox = textElement.node().getBBox();
const padding = 2;
bkg
.attr('x', -padding)
.attr('y', -padding)
.attr('width', bbox.width + 2 * padding)
.attr('height', bbox.height + 2 * padding);
// .style('fill', 'red');
return labelGroup.node();
} else {
return textElement.node();
}
}
/**
* Updates the text content and styles of the given tspan element based on the
* provided wrappedLine data.
*
* @param {object} tspan - The tspan element to update.
* @param {Array} wrappedLine - The line data to apply to the tspan element.
*/
function updateTextContentAndStyles(tspan, wrappedLine) {
tspan.text('');
wrappedLine.forEach((word, index) => {
const innerTspan = tspan
.append('tspan')
.attr('font-style', word.type === 'em' ? 'italic' : 'normal')
.attr('class', 'text-inner-tspan')
.attr('font-weight', word.type === 'strong' ? 'bold' : 'normal');
const special = [
'<',
'>',
'&',
'"',
"'",
'.',
',',
':',
';',
'!',
'?',
'(',
')',
'[',
']',
'{',
'}',
];
if (index !== 0 && special.includes(word.content)) {
innerTspan.text(word.content);
} else {
innerTspan.text(' ' + word.content);
}
});
}
/**
*
* @param el
* @param {*} text
* @param {*} param1
* @param root0
* @param root0.style
* @param root0.isTitle
* @param root0.classes
* @param root0.useHtmlLabels
* @param root0.isNode
* @returns
*/
// Note when using from flowcharts converting the API isNode means classes should be set accordingly. When using htmlLabels => to sett classes to'nodeLabel' when isNode=true otherwise 'edgeLabel'
// When not using htmlLabels => to set classes to 'title-row' when isTitle=true otherwise 'title-row'
export const createText = (
el,
text = '',
{
style = '',
isTitle = false,
classes = '',
useHtmlLabels = true,
isNode = true,
width,
addSvgBackground = false,
} = {}
) => {
log.info('createText', text, style, isTitle, classes, useHtmlLabels, isNode, addSvgBackground);
if (useHtmlLabels) {
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
// text = text.replace(/\\n|\n/g, '<br />');
const htmlText = markdownToHTML(text);
// log.info('markdo wnToHTML' + text, markdownToHTML(text));
const node = {
isNode,
label: decodeEntities(htmlText).replace(
/fa[blrs]?:fa-[\w-]+/g,
(s) => `<i class='${s.replace(':', ' ')}'></i>`
),
labelStyle: style.replace('fill:', 'color:'),
};
let vertexNode = addHtmlSpan(el, node, width, classes);
return vertexNode;
} else {
const structuredText = markdownToLines(text);
const svgLabel = createFormattedText(width, el, structuredText, addSvgBackground);
return svgLabel;
}
};

View File

@@ -0,0 +1,92 @@
import SimpleMarkdown from '@khanacademy/simple-markdown';
/**
*
* @param markdown
*/
function preprocessMarkdown(markdown) {
// Replace multiple newlines with a single newline
const withoutMultipleNewlines = markdown.replace(/\n{2,}/g, '\n');
// Remove extra spaces at the beginning of each line
const withoutExtraSpaces = withoutMultipleNewlines.replace(/^\s+/gm, '');
return withoutExtraSpaces;
}
/**
*
* @param markdown
*/
export function markdownToLines(markdown) {
const preprocessedMarkdown = preprocessMarkdown(markdown);
const mdParse = SimpleMarkdown.defaultBlockParse;
const syntaxTree = mdParse(preprocessedMarkdown);
let lines = [[]];
let currentLine = 0;
/**
*
* @param node
* @param parentType
*/
function processNode(node, parentType) {
if (node.type === 'text') {
const textLines = node.content.split('\n');
textLines.forEach((textLine, index) => {
if (index !== 0) {
currentLine++;
lines.push([]);
}
textLine.split(' ').forEach((word) => {
if (word) {
lines[currentLine].push({ content: word, type: parentType || 'normal' });
}
});
});
} else if (node.type === 'strong' || node.type === 'em') {
node.content.forEach((contentNode) => {
processNode(contentNode, node.type);
});
}
}
syntaxTree.forEach((treeNode) => {
if (treeNode.type === 'paragraph') {
treeNode.content.forEach((contentNode) => {
processNode(contentNode);
});
}
});
return lines;
}
/**
*
* @param markdown
*/
export function markdownToHTML(markdown) {
const mdParse = SimpleMarkdown.defaultBlockParse;
const syntaxTree = mdParse(markdown);
/**
*
* @param node
*/
function output(node) {
if (node.type === 'text') {
return node.content.replace(/\n/g, '<br/>');
} else if (node.type === 'strong') {
return `<strong>${node.content.map(output).join('')}</strong>`;
} else if (node.type === 'em') {
return `<em>${node.content.map(output).join('')}</em>`;
} else if (node.type === 'paragraph') {
return `<p>${node.content.map(output).join('')}</p>`;
} else {
return '';
}
}
return syntaxTree.map(output).join('');
}

View File

@@ -0,0 +1,253 @@
// import { test } from 'vitest';
import { markdownToLines, markdownToHTML } from './handle-markdown-text';
import { test } from 'vitest';
test('markdownToLines - Basic test', () => {
const input = `This is regular text
Here is a new line
There is some words **with a bold** section
Here is a line *with an italic* section`;
const expectedOutput = [
[
{ content: 'This', type: 'normal' },
{ content: 'is', type: 'normal' },
{ content: 'regular', type: 'normal' },
{ content: 'text', type: 'normal' },
],
[
{ content: 'Here', type: 'normal' },
{ content: 'is', type: 'normal' },
{ content: 'a', type: 'normal' },
{ content: 'new', type: 'normal' },
{ content: 'line', type: 'normal' },
],
[
{ content: 'There', type: 'normal' },
{ content: 'is', type: 'normal' },
{ content: 'some', type: 'normal' },
{ content: 'words', type: 'normal' },
{ content: 'with', type: 'strong' },
{ content: 'a', type: 'strong' },
{ content: 'bold', type: 'strong' },
{ content: 'section', type: 'normal' },
],
[
{ content: 'Here', type: 'normal' },
{ content: 'is', type: 'normal' },
{ content: 'a', type: 'normal' },
{ content: 'line', type: 'normal' },
{ content: 'with', type: 'em' },
{ content: 'an', type: 'em' },
{ content: 'italic', type: 'em' },
{ content: 'section', type: 'normal' },
],
];
const output = markdownToLines(input);
expect(output).toEqual(expectedOutput);
});
test('markdownToLines - Empty input', () => {
const input = '';
const expectedOutput = [[]];
const output = markdownToLines(input);
expect(output).toEqual(expectedOutput);
});
test('markdownToLines - No formatting', () => {
const input = `This is a simple test
with no formatting`;
const expectedOutput = [
[
{ content: 'This', type: 'normal' },
{ content: 'is', type: 'normal' },
{ content: 'a', type: 'normal' },
{ content: 'simple', type: 'normal' },
{ content: 'test', type: 'normal' },
],
[
{ content: 'with', type: 'normal' },
{ content: 'no', type: 'normal' },
{ content: 'formatting', type: 'normal' },
],
];
const output = markdownToLines(input);
expect(output).toEqual(expectedOutput);
});
test('markdownToLines - Only bold formatting', () => {
const input = `This is a **bold** test`;
const expectedOutput = [
[
{ content: 'This', type: 'normal' },
{ content: 'is', type: 'normal' },
{ content: 'a', type: 'normal' },
{ content: 'bold', type: 'strong' },
{ content: 'test', type: 'normal' },
],
];
const output = markdownToLines(input);
expect(output).toEqual(expectedOutput);
});
test('markdownToLines - paragraph 1', () => {
const input = `**Start** with
a second line`;
const expectedOutput = [
[
{ content: 'Start', type: 'strong' },
{ content: 'with', type: 'normal' },
],
[
{ content: 'a', type: 'normal' },
{ content: 'second', type: 'normal' },
{ content: 'line', type: 'normal' },
],
];
const output = markdownToLines(input);
expect(output).toEqual(expectedOutput);
});
test('markdownToLines - paragraph', () => {
const input = `**Start** with
a second line`;
const expectedOutput = [
[
{ content: 'Start', type: 'strong' },
{ content: 'with', type: 'normal' },
],
[
{ content: 'a', type: 'normal' },
{ content: 'second', type: 'normal' },
{ content: 'line', type: 'normal' },
],
];
const output = markdownToLines(input);
expect(output).toEqual(expectedOutput);
});
test('markdownToLines - Only italic formatting', () => {
const input = `This is an *italic* test`;
const expectedOutput = [
[
{ content: 'This', type: 'normal' },
{ content: 'is', type: 'normal' },
{ content: 'an', type: 'normal' },
{ content: 'italic', type: 'em' },
{ content: 'test', type: 'normal' },
],
];
const output = markdownToLines(input);
expect(output).toEqual(expectedOutput);
});
it('markdownToLines - Mixed formatting', () => {
const input = `*Italic* and **bold** formatting`;
const expectedOutput = [
[
{ content: 'Italic', type: 'em' },
{ content: 'and', type: 'normal' },
{ content: 'bold', type: 'strong' },
{ content: 'formatting', type: 'normal' },
],
];
const output = markdownToLines(input);
expect(output).toEqual(expectedOutput);
});
it('markdownToLines - Mixed formatting', () => {
const input = `The dog in **the** hog... a *very long text* about it
Word!`;
const expectedOutput = [
[
{ content: 'The', type: 'normal' },
{ content: 'dog', type: 'normal' },
{ content: 'in', type: 'normal' },
{ content: 'the', type: 'strong' },
{ content: 'hog', type: 'normal' },
{ content: '.', type: 'normal' },
{ content: '.', type: 'normal' },
{ content: '.', type: 'normal' },
{ content: 'a', type: 'normal' },
{ content: 'very', type: 'em' },
{ content: 'long', type: 'em' },
{ content: 'text', type: 'em' },
{ content: 'about', type: 'normal' },
{ content: 'it', type: 'normal' },
],
[
{ content: 'Word', type: 'normal' },
{ content: '!', type: 'normal' },
],
];
const output = markdownToLines(input);
expect(output).toEqual(expectedOutput);
});
test('markdownToHTML - Basic test', () => {
const input = `This is regular text
Here is a new line
There is some words **with a bold** section
Here is a line *with an italic* section`;
const expectedOutput = `<p>This is regular text<br/>Here is a new line<br/>There is some words <strong>with a bold</strong> section<br/>Here is a line <em>with an italic</em> section</p>`;
const output = markdownToHTML(input);
expect(output).toEqual(expectedOutput);
});
test('markdownToHTML - Empty input', () => {
const input = '';
const expectedOutput = '';
const output = markdownToHTML(input);
expect(output).toEqual(expectedOutput);
});
test('markdownToHTML - No formatting', () => {
const input = `This is a simple test
with no formatting`;
const expectedOutput = `<p>This is a simple test<br/>with no formatting</p>`;
const output = markdownToHTML(input);
expect(output).toEqual(expectedOutput);
});
test('markdownToHTML - Only bold formatting', () => {
const input = `This is a **bold** test`;
const expectedOutput = `<p>This is a <strong>bold</strong> test</p>`;
const output = markdownToHTML(input);
expect(output).toEqual(expectedOutput);
});
test('markdownToHTML - Only italic formatting', () => {
const input = `This is an *italic* test`;
const expectedOutput = `<p>This is an <em>italic</em> test</p>`;
const output = markdownToHTML(input);
expect(output).toEqual(expectedOutput);
});
test('markdownToHTML - Mixed formatting', () => {
const input = `*Italic* and **bold** formatting`;
const expectedOutput = `<p><em>Italic</em> and <strong>bold</strong> formatting</p>`;
const output = markdownToHTML(input);
expect(output).toEqual(expectedOutput);
});

747
pnpm-lock.yaml generated
View File

@@ -1,387 +1,271 @@
lockfileVersion: 5.4-inlineSpecifiers
lockfileVersion: 5.4
importers:
.:
specifiers:
'@applitools/eyes-cypress': ^3.27.6
'@commitlint/cli': ^17.2.0
'@commitlint/config-conventional': ^17.2.0
'@cspell/eslint-plugin': ^6.14.2
'@types/cors': ^2.8.13
'@types/eslint': ^8.4.10
'@types/express': ^4.17.17
'@types/js-yaml': ^4.0.5
'@types/jsdom': ^21.0.0
'@types/lodash': ^4.14.188
'@types/mdast': ^3.0.10
'@types/node': ^18.11.9
'@types/prettier': ^2.7.1
'@types/rollup-plugin-visualizer': ^4.2.1
'@typescript-eslint/eslint-plugin': ^5.48.2
'@typescript-eslint/parser': ^5.48.2
'@vitest/coverage-c8': ^0.29.0
'@vitest/spy': ^0.29.0
'@vitest/ui': ^0.29.0
concurrently: ^7.5.0
cors: ^2.8.5
coveralls: ^3.1.1
cypress: ^12.0.0
cypress-image-snapshot: ^4.0.1
esbuild: ^0.17.0
eslint: ^8.32.0
eslint-config-prettier: ^8.6.0
eslint-plugin-cypress: ^2.12.1
eslint-plugin-html: ^7.1.0
eslint-plugin-jest: ^27.1.5
eslint-plugin-jsdoc: ^39.6.2
eslint-plugin-json: ^3.1.0
eslint-plugin-lodash: ^7.4.0
eslint-plugin-markdown: ^3.0.0
eslint-plugin-no-only-tests: ^3.1.0
eslint-plugin-tsdoc: ^0.2.17
eslint-plugin-unicorn: ^45.0.0
express: ^4.18.2
globby: ^13.1.2
husky: ^8.0.2
jest: ^29.3.1
jison: ^0.4.18
js-yaml: ^4.1.0
jsdom: ^21.0.0
lint-staged: ^13.0.3
path-browserify: ^1.0.1
pnpm: ^7.15.0
prettier: ^2.7.1
prettier-plugin-jsdoc: ^0.4.2
rimraf: ^4.0.0
rollup-plugin-visualizer: ^5.8.3
start-server-and-test: ^1.15.4
ts-node: ^10.9.1
typescript: ^4.8.4
vite: ^4.1.1
vitest: ^0.29.0
devDependencies:
'@applitools/eyes-cypress':
specifier: ^3.27.6
version: 3.27.6
'@commitlint/cli':
specifier: ^17.2.0
version: 17.2.0
'@commitlint/config-conventional':
specifier: ^17.2.0
version: 17.2.0
'@cspell/eslint-plugin':
specifier: ^6.14.2
version: 6.14.2
'@types/cors':
specifier: ^2.8.13
version: 2.8.13
'@types/eslint':
specifier: ^8.4.10
version: 8.4.10
'@types/express':
specifier: ^4.17.17
version: 4.17.17
'@types/js-yaml':
specifier: ^4.0.5
version: 4.0.5
'@types/jsdom':
specifier: ^21.0.0
version: 21.1.0
'@types/lodash':
specifier: ^4.14.188
version: 4.14.188
'@types/mdast':
specifier: ^3.0.10
version: 3.0.10
'@types/node':
specifier: ^18.11.9
version: 18.11.9
'@types/prettier':
specifier: ^2.7.1
version: 2.7.1
'@types/rollup-plugin-visualizer':
specifier: ^4.2.1
version: 4.2.1
'@typescript-eslint/eslint-plugin':
specifier: ^5.48.2
version: 5.48.2_iljmjqxcygjq3saipl7gerxpvi
'@typescript-eslint/parser':
specifier: ^5.48.2
version: 5.48.2_yygwinqv3a2io74xmwofqb7uka
'@vitest/coverage-c8':
specifier: ^0.29.0
version: 0.29.2_vitest@0.29.2
'@vitest/spy':
specifier: ^0.29.0
version: 0.29.2
'@vitest/ui':
specifier: ^0.29.0
version: 0.29.2
concurrently:
specifier: ^7.5.0
version: 7.5.0
cors:
specifier: ^2.8.5
version: 2.8.5
coveralls:
specifier: ^3.1.1
version: 3.1.1
cypress:
specifier: ^12.0.0
version: 12.5.1
cypress-image-snapshot:
specifier: ^4.0.1
version: 4.0.1_cypress@12.5.1+jest@29.3.1
esbuild:
specifier: ^0.17.0
version: 0.17.0
eslint:
specifier: ^8.32.0
version: 8.32.0
eslint-config-prettier:
specifier: ^8.6.0
version: 8.6.0_eslint@8.32.0
eslint-plugin-cypress:
specifier: ^2.12.1
version: 2.12.1_eslint@8.32.0
eslint-plugin-html:
specifier: ^7.1.0
version: 7.1.0
eslint-plugin-jest:
specifier: ^27.1.5
version: 27.1.5_5rcd23qw3h5vuffwo2owxb3hw4
eslint-plugin-jsdoc:
specifier: ^39.6.2
version: 39.6.2_eslint@8.32.0
eslint-plugin-json:
specifier: ^3.1.0
version: 3.1.0
eslint-plugin-lodash:
specifier: ^7.4.0
version: 7.4.0_eslint@8.32.0
eslint-plugin-markdown:
specifier: ^3.0.0
version: 3.0.0_eslint@8.32.0
eslint-plugin-no-only-tests:
specifier: ^3.1.0
version: 3.1.0
eslint-plugin-tsdoc:
specifier: ^0.2.17
version: 0.2.17
eslint-plugin-unicorn:
specifier: ^45.0.0
version: 45.0.0_eslint@8.32.0
express:
specifier: ^4.18.2
version: 4.18.2
globby:
specifier: ^13.1.2
version: 13.1.2
husky:
specifier: ^8.0.2
version: 8.0.2
jest:
specifier: ^29.3.1
version: 29.3.1_odkjkoia5xunhxkdrka32ib6vi
jison:
specifier: ^0.4.18
version: 0.4.18
js-yaml:
specifier: ^4.1.0
version: 4.1.0
jsdom:
specifier: ^21.0.0
version: 21.1.0
lint-staged:
specifier: ^13.0.3
version: 13.0.3
path-browserify:
specifier: ^1.0.1
version: 1.0.1
pnpm:
specifier: ^7.15.0
version: 7.15.0
prettier:
specifier: ^2.7.1
version: 2.7.1
prettier-plugin-jsdoc:
specifier: ^0.4.2
version: 0.4.2_prettier@2.7.1
rimraf:
specifier: ^4.0.0
version: 4.1.2
rollup-plugin-visualizer:
specifier: ^5.8.3
version: 5.8.3
start-server-and-test:
specifier: ^1.15.4
version: 1.15.4
ts-node:
specifier: ^10.9.1
version: 10.9.1_cbe7ovvae6zqfnmtgctpgpys54
typescript:
specifier: ^4.8.4
version: 4.8.4
vite:
specifier: ^4.1.1
version: 4.1.1_@types+node@18.11.9
vitest:
specifier: ^0.29.0
version: 0.29.2_hjnfa4mohew6fc4mnpzgbfyvpa
'@applitools/eyes-cypress': 3.27.6
'@commitlint/cli': 17.2.0
'@commitlint/config-conventional': 17.2.0
'@cspell/eslint-plugin': 6.14.2
'@types/cors': 2.8.13
'@types/eslint': 8.4.10
'@types/express': 4.17.17
'@types/js-yaml': 4.0.5
'@types/jsdom': 21.1.0
'@types/lodash': 4.14.188
'@types/mdast': 3.0.10
'@types/node': 18.11.9
'@types/prettier': 2.7.1
'@types/rollup-plugin-visualizer': 4.2.1
'@typescript-eslint/eslint-plugin': 5.48.2_iljmjqxcygjq3saipl7gerxpvi
'@typescript-eslint/parser': 5.48.2_yygwinqv3a2io74xmwofqb7uka
'@vitest/coverage-c8': 0.29.2_vitest@0.29.2
'@vitest/spy': 0.29.2
'@vitest/ui': 0.29.2
concurrently: 7.5.0
cors: 2.8.5
coveralls: 3.1.1
cypress: 12.5.1
cypress-image-snapshot: 4.0.1_cypress@12.5.1+jest@29.3.1
esbuild: 0.17.0
eslint: 8.32.0
eslint-config-prettier: 8.6.0_eslint@8.32.0
eslint-plugin-cypress: 2.12.1_eslint@8.32.0
eslint-plugin-html: 7.1.0
eslint-plugin-jest: 27.1.5_5rcd23qw3h5vuffwo2owxb3hw4
eslint-plugin-jsdoc: 39.6.2_eslint@8.32.0
eslint-plugin-json: 3.1.0
eslint-plugin-lodash: 7.4.0_eslint@8.32.0
eslint-plugin-markdown: 3.0.0_eslint@8.32.0
eslint-plugin-no-only-tests: 3.1.0
eslint-plugin-tsdoc: 0.2.17
eslint-plugin-unicorn: 45.0.0_eslint@8.32.0
express: 4.18.2
globby: 13.1.2
husky: 8.0.2
jest: 29.3.1_odkjkoia5xunhxkdrka32ib6vi
jison: 0.4.18
js-yaml: 4.1.0
jsdom: 21.1.0
lint-staged: 13.0.3
path-browserify: 1.0.1
pnpm: 7.15.0
prettier: 2.7.1
prettier-plugin-jsdoc: 0.4.2_prettier@2.7.1
rimraf: 4.1.2
rollup-plugin-visualizer: 5.8.3
start-server-and-test: 1.15.4
ts-node: 10.9.1_cbe7ovvae6zqfnmtgctpgpys54
typescript: 4.8.4
vite: 4.1.1_@types+node@18.11.9
vitest: 0.29.2_hjnfa4mohew6fc4mnpzgbfyvpa
packages/mermaid:
specifiers:
'@braintree/sanitize-url': ^6.0.0
'@khanacademy/simple-markdown': ^0.8.6
'@types/cytoscape': ^3.19.9
'@types/d3': ^7.4.0
'@types/dompurify': ^2.4.0
'@types/jsdom': ^21.0.0
'@types/lodash-es': ^4.17.7
'@types/micromatch': ^4.0.2
'@types/prettier': ^2.7.1
'@types/stylis': ^4.0.2
'@types/uuid': ^9.0.0
'@typescript-eslint/eslint-plugin': ^5.42.1
'@typescript-eslint/parser': ^5.42.1
chokidar: ^3.5.3
concurrently: ^7.5.0
coveralls: ^3.1.1
cpy-cli: ^4.2.0
cspell: ^6.14.3
cytoscape: ^3.23.0
cytoscape-cose-bilkent: ^4.1.0
cytoscape-fcose: ^2.1.0
d3: ^7.4.0
dagre-d3-es: 7.0.10
dayjs: ^1.11.7
dompurify: 2.4.5
elkjs: ^0.8.2
globby: ^13.1.2
jison: ^0.4.18
js-base64: ^3.7.2
jsdom: ^21.0.0
khroma: ^2.0.0
lodash-es: ^4.17.21
micromatch: ^4.0.5
non-layered-tidy-tree-layout: ^2.0.2
path-browserify: ^1.0.1
prettier: ^2.7.1
remark: ^14.0.2
remark-frontmatter: ^4.0.1
remark-gfm: ^3.0.1
rimraf: ^4.0.0
start-server-and-test: ^1.14.0
stylis: ^4.1.2
ts-dedent: ^2.2.0
typedoc: ^0.23.18
typedoc-plugin-markdown: ^3.13.6
typescript: ^4.8.4
unist-util-flatmap: ^1.0.0
uuid: ^9.0.0
vitepress: ^1.0.0-alpha.46
vitepress-plugin-search: ^1.0.4-alpha.19
web-worker: ^1.2.0
dependencies:
'@braintree/sanitize-url':
specifier: ^6.0.0
version: 6.0.0
cytoscape:
specifier: ^3.23.0
version: 3.23.0
cytoscape-cose-bilkent:
specifier: ^4.1.0
version: 4.1.0_cytoscape@3.23.0
cytoscape-fcose:
specifier: ^2.1.0
version: 2.1.0_cytoscape@3.23.0
d3:
specifier: ^7.4.0
version: 7.8.2
dagre-d3-es:
specifier: 7.0.10
version: 7.0.10
dayjs:
specifier: ^1.11.7
version: 1.11.7
dompurify:
specifier: 2.4.5
version: 2.4.5
elkjs:
specifier: ^0.8.2
version: 0.8.2
khroma:
specifier: ^2.0.0
version: 2.0.0
lodash-es:
specifier: ^4.17.21
version: 4.17.21
non-layered-tidy-tree-layout:
specifier: ^2.0.2
version: 2.0.2
stylis:
specifier: ^4.1.2
version: 4.1.2
ts-dedent:
specifier: ^2.2.0
version: 2.2.0
uuid:
specifier: ^9.0.0
version: 9.0.0
web-worker:
specifier: ^1.2.0
version: 1.2.0
'@braintree/sanitize-url': 6.0.0
'@khanacademy/simple-markdown': 0.8.6_wcqkhtmu7mswc6yz4uyexck3ty
cytoscape: 3.23.0
cytoscape-cose-bilkent: 4.1.0_cytoscape@3.23.0
cytoscape-fcose: 2.1.0_cytoscape@3.23.0
d3: 7.8.2
dagre-d3-es: 7.0.10
dayjs: 1.11.7
dompurify: 2.4.5
elkjs: 0.8.2
khroma: 2.0.0
lodash-es: 4.17.21
non-layered-tidy-tree-layout: 2.0.2
stylis: 4.1.2
ts-dedent: 2.2.0
uuid: 9.0.0
web-worker: 1.2.0
devDependencies:
'@types/cytoscape':
specifier: ^3.19.9
version: 3.19.9
'@types/d3':
specifier: ^7.4.0
version: 7.4.0
'@types/dompurify':
specifier: ^2.4.0
version: 2.4.0
'@types/jsdom':
specifier: ^21.0.0
version: 21.1.0
'@types/lodash-es':
specifier: ^4.17.6
version: 4.17.6
'@types/micromatch':
specifier: ^4.0.2
version: 4.0.2
'@types/prettier':
specifier: ^2.7.1
version: 2.7.1
'@types/stylis':
specifier: ^4.0.2
version: 4.0.2
'@types/uuid':
specifier: ^9.0.0
version: 9.0.0
'@typescript-eslint/eslint-plugin':
specifier: ^5.42.1
version: 5.42.1_qxgr6oy2qtsmmpo3f6iejuryuq
'@typescript-eslint/parser':
specifier: ^5.42.1
version: 5.42.1_yygwinqv3a2io74xmwofqb7uka
chokidar:
specifier: ^3.5.3
version: 3.5.3
concurrently:
specifier: ^7.5.0
version: 7.5.0
coveralls:
specifier: ^3.1.1
version: 3.1.1
cpy-cli:
specifier: ^4.2.0
version: 4.2.0
cspell:
specifier: ^6.14.3
version: 6.14.3
globby:
specifier: ^13.1.2
version: 13.1.2
jison:
specifier: ^0.4.18
version: 0.4.18
js-base64:
specifier: ^3.7.2
version: 3.7.2
jsdom:
specifier: ^21.0.0
version: 21.1.0
micromatch:
specifier: ^4.0.5
version: 4.0.5
path-browserify:
specifier: ^1.0.1
version: 1.0.1
prettier:
specifier: ^2.7.1
version: 2.7.1
remark:
specifier: ^14.0.2
version: 14.0.2
remark-frontmatter:
specifier: ^4.0.1
version: 4.0.1
remark-gfm:
specifier: ^3.0.1
version: 3.0.1
rimraf:
specifier: ^4.0.0
version: 4.1.2
start-server-and-test:
specifier: ^1.14.0
version: 1.14.0
typedoc:
specifier: ^0.23.18
version: 0.23.18_typescript@4.8.4
typedoc-plugin-markdown:
specifier: ^3.13.6
version: 3.13.6_typedoc@0.23.18
typescript:
specifier: ^4.8.4
version: 4.8.4
unist-util-flatmap:
specifier: ^1.0.0
version: 1.0.0
vitepress:
specifier: ^1.0.0-alpha.46
version: 1.0.0-alpha.46_tbpndr44ulefs3hehwpi2mkf2y
vitepress-plugin-search:
specifier: ^1.0.4-alpha.19
version: 1.0.4-alpha.19_g67lr3vgasogkevpbew55lljzq
'@types/cytoscape': 3.19.9
'@types/d3': 7.4.0
'@types/dompurify': 2.4.0
'@types/jsdom': 21.1.0
'@types/lodash-es': 4.17.7
'@types/micromatch': 4.0.2
'@types/prettier': 2.7.1
'@types/stylis': 4.0.2
'@types/uuid': 9.0.0
'@typescript-eslint/eslint-plugin': 5.42.1_qxgr6oy2qtsmmpo3f6iejuryuq
'@typescript-eslint/parser': 5.42.1_yygwinqv3a2io74xmwofqb7uka
chokidar: 3.5.3
concurrently: 7.5.0
coveralls: 3.1.1
cpy-cli: 4.2.0
cspell: 6.14.3
globby: 13.1.2
jison: 0.4.18
js-base64: 3.7.2
jsdom: 21.1.0
micromatch: 4.0.5
path-browserify: 1.0.1
prettier: 2.7.1
remark: 14.0.2
remark-frontmatter: 4.0.1
remark-gfm: 3.0.1
rimraf: 4.1.2
start-server-and-test: 1.14.0
typedoc: 0.23.18_typescript@4.8.4
typedoc-plugin-markdown: 3.13.6_typedoc@0.23.18
typescript: 4.8.4
unist-util-flatmap: 1.0.0
vitepress: 1.0.0-alpha.46_hoyvfk3ab7nzsjkhptt6ai7rzq
vitepress-plugin-search: 1.0.4-alpha.19_g67lr3vgasogkevpbew55lljzq
packages/mermaid-example-diagram:
specifiers:
'@braintree/sanitize-url': ^6.0.0
'@types/cytoscape': ^3.19.9
concurrently: ^7.5.0
cytoscape: ^3.23.0
cytoscape-cose-bilkent: ^4.1.0
cytoscape-fcose: ^2.1.0
d3: ^7.0.0
khroma: ^2.0.0
mermaid: workspace:*
non-layered-tidy-tree-layout: ^2.0.2
rimraf: ^4.0.0
dependencies:
'@braintree/sanitize-url':
specifier: ^6.0.0
version: 6.0.0
cytoscape:
specifier: ^3.23.0
version: 3.23.0
cytoscape-cose-bilkent:
specifier: ^4.1.0
version: 4.1.0_cytoscape@3.23.0
cytoscape-fcose:
specifier: ^2.1.0
version: 2.1.0_cytoscape@3.23.0
d3:
specifier: ^7.0.0
version: 7.8.2
khroma:
specifier: ^2.0.0
version: 2.0.0
non-layered-tidy-tree-layout:
specifier: ^2.0.2
version: 2.0.2
'@braintree/sanitize-url': 6.0.0
cytoscape: 3.23.0
cytoscape-cose-bilkent: 4.1.0_cytoscape@3.23.0
cytoscape-fcose: 2.1.0_cytoscape@3.23.0
d3: 7.8.2
khroma: 2.0.0
non-layered-tidy-tree-layout: 2.0.2
devDependencies:
'@types/cytoscape':
specifier: ^3.19.9
version: 3.19.9
concurrently:
specifier: ^7.5.0
version: 7.5.0
mermaid:
specifier: workspace:*
version: link:../mermaid
rimraf:
specifier: ^4.0.0
version: 4.1.2
'@types/cytoscape': 3.19.9
concurrently: 7.5.0
mermaid: link:../mermaid
rimraf: 4.1.2
tests/webpack:
specifiers:
'@mermaid-js/mermaid-example-diagram': workspace:*
mermaid: workspace:*
webpack: ^5.74.0
webpack-cli: ^4.10.0
webpack-dev-server: ^4.11.1
dependencies:
'@mermaid-js/mermaid-example-diagram':
specifier: workspace:*
version: link:../../packages/mermaid-example-diagram
mermaid:
specifier: workspace:*
version: link:../../packages/mermaid
'@mermaid-js/mermaid-example-diagram': link:../../packages/mermaid-example-diagram
mermaid: link:../../packages/mermaid
devDependencies:
webpack:
specifier: ^5.74.0
version: 5.75.0_webpack-cli@4.10.0
webpack-cli:
specifier: ^4.10.0
version: 4.10.0_uaydpeuxkjjcxdbyfgk36cjdxi
webpack-dev-server:
specifier: ^4.11.1
version: 4.11.1_pda42hcaj7d62cr262fr632kue
webpack: 5.75.0_webpack-cli@4.10.0
webpack-cli: 4.10.0_uaydpeuxkjjcxdbyfgk36cjdxi
webpack-dev-server: 4.11.1_pda42hcaj7d62cr262fr632kue
packages:
@@ -1705,10 +1589,10 @@ packages:
resolution: {integrity: sha512-6SCwI7P8ao+se1TUsdZ7B4XzL+gqeQZnBc+2EONZlcVa0dVrk0NjETxozFKgMv0eEGH8QzP1fkN+A1rH61l4eg==}
dev: true
/@docsearch/js/3.3.3_tbpndr44ulefs3hehwpi2mkf2y:
/@docsearch/js/3.3.3_hoyvfk3ab7nzsjkhptt6ai7rzq:
resolution: {integrity: sha512-2xAv2GFuHzzmG0SSZgf8wHX0qZX8n9Y1ZirKUk5Wrdc+vH9CL837x2hZIUdwcPZI9caBA+/CzxsS68O4waYjUQ==}
dependencies:
'@docsearch/react': 3.3.3_tbpndr44ulefs3hehwpi2mkf2y
'@docsearch/react': 3.3.3_hoyvfk3ab7nzsjkhptt6ai7rzq
preact: 10.11.0
transitivePeerDependencies:
- '@algolia/client-search'
@@ -1717,7 +1601,7 @@ packages:
- react-dom
dev: true
/@docsearch/react/3.3.3_tbpndr44ulefs3hehwpi2mkf2y:
/@docsearch/react/3.3.3_hoyvfk3ab7nzsjkhptt6ai7rzq:
resolution: {integrity: sha512-pLa0cxnl+G0FuIDuYlW+EBK6Rw2jwLw9B1RHIeS4N4s2VhsfJ/wzeCi3CWcs5yVfxLd5ZK50t//TMA5e79YT7Q==}
peerDependencies:
'@types/react': '>= 16.8.0 < 19.0.0'
@@ -1735,6 +1619,8 @@ packages:
'@algolia/autocomplete-preset-algolia': 1.7.4_qs6lk5nhygj2o3hj4sf6xnr724
'@docsearch/css': 3.3.3
algoliasearch: 4.14.2
react: 16.14.0
react-dom: 16.14.0_react@16.14.0
transitivePeerDependencies:
- '@algolia/client-search'
dev: true
@@ -2464,6 +2350,17 @@ packages:
'@jridgewell/sourcemap-codec': 1.4.14
dev: true
/@khanacademy/simple-markdown/0.8.6_wcqkhtmu7mswc6yz4uyexck3ty:
resolution: {integrity: sha512-mAUlR9lchzfqunR89pFvNI51jQKsMpJeWYsYWw0DQcUXczn/T/V6510utgvm7X0N3zN87j1SvuKk8cMbl9IAFw==}
peerDependencies:
react: 16.14.0
react-dom: 16.14.0
dependencies:
'@types/react': 18.0.28
react: 16.14.0
react-dom: 16.14.0_react@16.14.0
dev: false
/@leichtgewicht/ip-codec/2.0.4:
resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==}
dev: true
@@ -2971,8 +2868,8 @@ packages:
resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==}
dev: true
/@types/lodash-es/4.17.6:
resolution: {integrity: sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==}
/@types/lodash-es/4.17.7:
resolution: {integrity: sha512-z0ptr6UI10VlU6l5MYhGwS4mC8DZyYer2mCoyysZtSF7p26zOX8UpbrV0YpNYLGS8K4PUFIyEr62IMFFjveSiQ==}
dependencies:
'@types/lodash': 4.14.188
dev: true
@@ -3047,6 +2944,10 @@ packages:
resolution: {integrity: sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==}
dev: true
/@types/prop-types/15.7.5:
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
dev: false
/@types/qs/6.9.7:
resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==}
dev: true
@@ -3055,6 +2956,14 @@ packages:
resolution: {integrity: sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==}
dev: true
/@types/react/18.0.28:
resolution: {integrity: sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==}
dependencies:
'@types/prop-types': 15.7.5
'@types/scheduler': 0.16.2
csstype: 3.1.1
dev: false
/@types/responselike/1.0.0:
resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==}
dependencies:
@@ -3072,6 +2981,10 @@ packages:
rollup: 2.79.1
dev: true
/@types/scheduler/0.16.2:
resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==}
dev: false
/@types/semver/7.3.12:
resolution: {integrity: sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==}
dev: true
@@ -3504,7 +3417,7 @@ packages:
'@vue/shared': 3.2.45
estree-walker: 2.0.2
magic-string: 0.25.9
postcss: 8.4.20
postcss: 8.4.21
source-map: 0.6.1
dev: true
@@ -4152,7 +4065,7 @@ packages:
/axios/0.21.4_debug@4.3.2:
resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==}
dependencies:
follow-redirects: 1.15.2_debug@4.3.2
follow-redirects: 1.15.2_debug@4.3.4
transitivePeerDependencies:
- debug
dev: true
@@ -5248,6 +5161,10 @@ packages:
resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==}
dev: true
/csstype/3.1.1:
resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==}
dev: false
/cypress-image-snapshot/4.0.1_cypress@12.5.1+jest@29.3.1:
resolution: {integrity: sha512-PBpnhX/XItlx3/DAk5ozsXQHUi72exybBNH5Mpqj1DVmjq+S5Jd9WE5CRa4q5q0zuMZb2V2VpXHth6MjFpgj9Q==}
engines: {node: '>=8'}
@@ -6724,28 +6641,6 @@ packages:
resolution: {integrity: sha512-XGozTsMPYkm+6b5QL3Z9wQcJjNYxp0CYn3U1gO7dwD6PAqU1SVWZxI9CCg3z+ml3YfqdPnrBehaBrnH2AGKbNA==}
dev: true
/follow-redirects/1.15.2:
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
dev: true
/follow-redirects/1.15.2_debug@4.3.2:
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
dependencies:
debug: 4.3.2
dev: true
/follow-redirects/1.15.2_debug@4.3.4:
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
engines: {node: '>=4.0'}
@@ -7295,7 +7190,7 @@ packages:
engines: {node: '>=8.0.0'}
dependencies:
eventemitter3: 4.0.7
follow-redirects: 1.15.2
follow-redirects: 1.15.2_debug@4.3.4
requires-port: 1.0.0
transitivePeerDependencies:
- debug
@@ -8213,7 +8108,6 @@ packages:
/js-tokens/4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
dev: true
/js-yaml/3.14.1:
resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
@@ -8621,6 +8515,12 @@ packages:
resolution: {integrity: sha512-cHlYSUpL2s7Fb3394mYxwTYj8niTaNHUCLr0qdiCXQfSjfuA7CKofpX2uSwEfFDQ0EB7JcnMnm+GjbqqoinYYg==}
dev: true
/loose-envify/1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
dependencies:
js-tokens: 4.0.0
/loupe/2.3.6:
resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==}
dependencies:
@@ -9432,7 +9332,6 @@ packages:
/object-assign/4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
dev: true
/object-inspect/1.12.2:
resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==}
@@ -9856,15 +9755,6 @@ packages:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
dev: true
/postcss/8.4.20:
resolution: {integrity: sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==}
engines: {node: ^10 || ^12 || >=14}
dependencies:
nanoid: 3.3.4
picocolors: 1.0.0
source-map-js: 1.0.2
dev: true
/postcss/8.4.21:
resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==}
engines: {node: ^10 || ^12 || >=14}
@@ -9943,6 +9833,13 @@ packages:
sisteransi: 1.0.5
dev: true
/prop-types/15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
dependencies:
loose-envify: 1.4.0
object-assign: 4.1.1
react-is: 16.13.1
/proxy-addr/2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
@@ -10055,6 +9952,20 @@ packages:
unpipe: 1.0.0
dev: true
/react-dom/16.14.0_react@16.14.0:
resolution: {integrity: sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==}
peerDependencies:
react: ^16.14.0
dependencies:
loose-envify: 1.4.0
object-assign: 4.1.1
prop-types: 15.8.1
react: 16.14.0
scheduler: 0.19.1
/react-is/16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
/react-is/17.0.2:
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
dev: true
@@ -10063,6 +9974,14 @@ packages:
resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
dev: true
/react/16.14.0:
resolution: {integrity: sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==}
engines: {node: '>=0.10.0'}
dependencies:
loose-envify: 1.4.0
object-assign: 4.1.1
prop-types: 15.8.1
/read-pkg-up/7.0.1:
resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==}
engines: {node: '>=8'}
@@ -10471,6 +10390,12 @@ packages:
xmlchars: 2.2.0
dev: true
/scheduler/0.19.1:
resolution: {integrity: sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==}
dependencies:
loose-envify: 1.4.0
object-assign: 4.1.1
/schema-utils/3.1.1:
resolution: {integrity: sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==}
engines: {node: '>= 10.13.0'}
@@ -11769,16 +11694,16 @@ packages:
'@types/markdown-it': 12.2.3
flexsearch: 0.7.31
markdown-it: 13.0.1
vitepress: 1.0.0-alpha.46_tbpndr44ulefs3hehwpi2mkf2y
vitepress: 1.0.0-alpha.46_hoyvfk3ab7nzsjkhptt6ai7rzq
vue: 3.2.45
dev: true
/vitepress/1.0.0-alpha.46_tbpndr44ulefs3hehwpi2mkf2y:
/vitepress/1.0.0-alpha.46_hoyvfk3ab7nzsjkhptt6ai7rzq:
resolution: {integrity: sha512-HiKiHzC0iTPsRsKs8XcsMeMzCpcCt5LWcX9mpDr288Ju+nQf1G8A2+Wm44ZkBsVv4EHxFK4ChmWyZrL1OJUXpg==}
hasBin: true
dependencies:
'@docsearch/css': 3.3.3
'@docsearch/js': 3.3.3_tbpndr44ulefs3hehwpi2mkf2y
'@docsearch/js': 3.3.3_hoyvfk3ab7nzsjkhptt6ai7rzq
'@vitejs/plugin-vue': 4.0.0_vite@4.1.1+vue@3.2.45
'@vue/devtools-api': 6.5.0
'@vueuse/core': 9.12.0_vue@3.2.45