Merge branch 'develop' of https://github.com/knsv/mermaid into 1542_take_two

This commit is contained in:
Ashish Jain 2020-08-19 18:45:24 +02:00
commit 455cd9c696
40 changed files with 1361 additions and 1125 deletions

View File

@ -1,81 +1,37 @@
# mermaid [![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/Mermaid/mermaid)
![banner](./img/header.png)
**Edit this Page** [![N|Solid](./docs/img/GitHub-Mark-32px.png)](https://github.com/mermaid-js/mermaid/blob/develop/docs/README.md)
:trophy: **Mermaid was nominated and won the [JS Open Source Awards (2019)](https://osawards.com/javascript/#nominees) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.**
:trophy: **Mermaid was nominated and won the [JS Open Source Awards (2019)](https://osawards.com/javascript/#nominees) in the category "The most exciting use of technology"!!!**
**Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project 🙏**
## About
<!-- <Main description> -->
__mermaid is a Javascript based diagramming and charting tool that uses markdown-inspired text definitions and a renderer to create and modify complex diagrams. The main purpose of mermaid is to help Documentation catch up with Development.__
Mermaid is a Javascript based diagramming and charting tool that uses Markdown-inspired text definitions and a renderer to create and modify complex diagrams. The main purpose of Mermaid is to help documentation catch up with development.
# Doc-Rot is a Catch-22 that Mermaid helps to solve.
> Doc-Rot is a Catch-22 that Mermaid helps to solve.
### Diagramming and Documentation costs precious developer time and gets outdated quickly.
### But not having diagrams or Docs ruins productivity and hurts organizational learning.
Diagramming and documentation costs precious developer time and gets outdated quickly.
But not having diagrams or docs ruins productivity and hurts organizational learning. <br/>
Mermaid addresses this problem by cutting the time, effort and tooling that is required to create modifiable diagrams and charts, for smarter and more reusable content.
The text definitions for Mermaid diagrams allows for it to be updated easily, it can also be made part of production scripts (and other pieces of code).
So less time needs be spent on documenting, as a separate and laborious task. <br/>
Even non-programmers can create diagrams through the [Mermaid Live Editor](https://github.com/mermaidjs/mermaid-live-editor). <br/>
[Mermaid Overview](./n00b-overview.md) has video tutorials.
Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./integrations.md).
## mermaid addresses this problem by cutting the time, effort and tooling that is required to create modifiable diagrams and charts, for smarter and more reusable content.**
For a more detailed introduction to Mermaid and some of it's more basic uses, look to the [Beginner's Guide](https://mermaid-js.github.io/mermaid/#/n00b-overview) and [Usage](./usage.md).
The text definitions for mermaid diagrams allows for it to be updated easily, it can also be made part of production scripts (and other pieces of code). So less time needs be spent on documenting, as a separate and laborious task.
## Even non-programmers can create diagrams through the [Mermaid Live Editor](https://github.com/mermaidjs/mermaid-live-editor).
## [mermaid Overview](./n00b-overview.md) has video tutorials.
## Use mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./integrations.md)**
## For a more detailed introduction to mermaid and some of it's more basic uses, look to the [Beginner's Guide](https://mermaid-js.github.io/mermaid/#/n00b-overview) and [Usage](./usage.md).
## [CDN](https://unpkg.com/mermaid/)
## [Documentation](https://mermaidjs.github.io)
## [Contribution](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md)
## Record of [Mermaid Version Changes](./versionUpdates.md).
# Version News: 8.7.0 Released with Updates to Theme Configuration
## [Version 8.7.0](./docs/theming.md) Mermaid comes out with a System for Dynamic and Integrated Diagram Theme Configuration.
## Mermaid comes out with [New Configuration Protocols in Version 8.6.0](./docs/8.6.0_docs.md)
## New diagrams in 8.4
With version 8.4 class diagrams have got some new features, bug fixes and documentation. Another new feature in 8.4 is the new diagram type, state diagrams.
![Image show the two new diagram types](./docs/img/new-diagrams.png)
## Special note regarding version 8.2
In version 8.2 a security improvement was introduced. A securityLevel configuration was introduced which sets the level of trust to be used on the parsed diagrams.
- **true**: (default) tags in text are encoded, click functionality is disabled
- false: tags in text are allowed, click functionality is enabled
Closed issues:
⚠️ **Note** : This changes the default behaviour of mermaid so that after upgrade to 8.2, if the securityLevel is not configured, tags in flowcharts are encoded as tags and clicking is prohibited.
If your application is taking resposibility for the diagram source security you can set the securityLevel accordingly. By doing this clicks and tags are again allowed.
```javascript
mermaidAPI.initialize({
securityLevel: 'loose'
});
```
🌐 [CDN](https://unpkg.com/mermaid/) | 📖 [Documentation](https://mermaidjs.github.io) | 🙌 [Contribution](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md) | 📜 [Changelog](./docs/versionUpdates.md)
<!-- </Main description> -->
__The following are some examples of the diagrams, charts and graphs that can be made using mermaid and the Markdown-inspired text specific to it. Click here jump into the [text syntax](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference).__
## Examples
__The following are some examples of the diagrams, charts and graphs that can be made using Mermaid and the Markdown-inspired text specific to it. Click here jump into the [text syntax](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference).__
<table>
<!-- <Flowchart> -->
<tr><td colspan=2 align="center">
@ -245,13 +201,13 @@ pie
- [Live Editor](https://github.com/mermaid-js/mermaid-live-editor)
- [HTTP Server](https://github.com/TomWright/mermaid-server)
# Contributors [![Help wanted](https://img.shields.io/github/labels/mermaid-js/mermaid/Help%20wanted!)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Help+wanted%21%22) [![Contributors](https://img.shields.io/github/contributors/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) [![Commits](https://img.shields.io/github/commit-activity/m/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors)
## Contributors [![Help wanted](https://img.shields.io/github/labels/mermaid-js/mermaid/Help%20wanted!)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Help+wanted%21%22) [![Contributors](https://img.shields.io/github/contributors/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) [![Commits](https://img.shields.io/github/commit-activity/m/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors)
Mermaid is a growing community and is always accepting new contributors. There's a lot of different ways to help out and we're always looking for extra hands! Look at [this issue](https://github.com/mermaid-js/mermaid/issues/866) if you want to know where to start helping out.
Detailed information about how to contribute can be found in the [contribution guide](CONTRIBUTING.md)
# Appreciation
## Appreciation
A quick note from Knut Sveidqvist:
>*Many thanks to the [d3](http://d3js.org/) and [dagre-d3](https://github.com/cpettitt/dagre-d3) projects for providing the graphical layout and drawing libraries!*
>*Thanks also to the [js-sequence-diagram](http://bramp.github.io/js-sequence-diagrams) project for usage of the grammar for the sequence diagrams. Thanks to Jessica Peter for inspiration and starting point for gantt rendering.*

27
Tutorials.md Normal file
View File

@ -0,0 +1,27 @@
# Tutorials
**Edit this Page** [![N|Solid](./img/GitHub-Mark-32px.png)](https://github.com/mermaid-js/mermaid/blob/develop/docs/Tutorials.md)
This is list of Tutorials in Mermaid.
For most purposes, the Live-Editor is capable of taking care of all diagramming needs.
The definitions that can be generated here are also backwards-compatible for integrations, plug-ins and the live-editor.
# Live-Editor Tutorials
https://www.youtube.com/watch?v=SQ9QmuTHuSI&t=438s
https://www.youtube.com/watch?v=5RQqht3NNSE
https://www.youtube.com/watch?v=7_2IroEs6Is&t=207s
https://www.youtube.com/watch?v=9HZzKkAqrX8
https://www.youtube.com/watch?v=7_2IroEs6Is&t=207s
https://www.youtube.com/watch?v=9HZzKkAqrX8
# Mermaid HTML tutorials and samples

View File

@ -19,7 +19,29 @@ export const mermaidUrl = (graphStr, options, api) => {
return url;
};
export const imgSnapshotTest = (graphStr, options, api) => {
export const imgSnapshotTest = (graphStr, _options, api) => {
const options = Object.assign(_options);
if (!options.fontFamily) {
options.fontFamily = 'courier';
}
if (!options.sequence) {
options.sequence = {};
}
if (!options.sequence || (options.sequence && !options.sequence.actorFontFamily)) {
options.sequence.actorFontFamily = 'courier';
}
if (options.sequence && !options.sequence.noteFontFamily) {
options.sequence.noteFontFamily = 'courier';
}
options.sequence.actorFontFamily = 'courier';
options.sequence.noteFontFamily = 'courier';
options.sequence.messageFontFamily = 'courier';
if (options.sequence && !options.sequence.actorFontFamily) {
options.sequence.actorFontFamily = 'courier';
}
if (!options.fontSize) {
options.fontSize = '16px';
}
const url = mermaidUrl(graphStr, options, api);
cy.visit(url);

View File

@ -0,0 +1,14 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util';
describe('Flowchart', () => {
it('34: testing the label width in percy', () => {
imgSnapshotTest(
`graph TD
A[Christmas]
`,
{ theme: 'forest' , fontFamily: '"Noto Sans SC", sans-serif' }
);
});
});

View File

@ -46,4 +46,22 @@ describe('Flowchart v2', () => {
{ flowchart: { diagramPadding: 0 } }
);
});
it('Length of edges', () => {
imgSnapshotTest(
`flowchart TD
L1 --- L2
L2 --- C
M1 ---> C
R1 .-> R2
R2 <.-> C
C -->|Label 1| E1
C <-- Label 2 ---> E2
C ----> E3
C <-...-> E4
C ======> E5
`,
{ flowchart: { diagramPadding: 0 } }
);
});
});

View File

@ -11,7 +11,7 @@ describe('Flowchart', () => {
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@ -24,7 +24,7 @@ describe('Flowchart', () => {
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { htmlLabels: true } }
{ flowchart: { htmlLabels: true }, fontFamily: 'courier' }
);
});
@ -38,7 +38,7 @@ describe('Flowchart', () => {
C -->|Two| E[iPhone]
C -->|Three| F[Car]
`,
{}
{fontFamily: 'courier'}
);
});
@ -53,7 +53,7 @@ describe('Flowchart', () => {
C -->|Two| E[\\iPhone\\]
C -->|Three| F[Car]
`,
{}
{ fontFamily: 'courier'}
);
});
@ -69,7 +69,7 @@ describe('Flowchart', () => {
classDef processHead fill:#888888,color:white,font-weight:bold,stroke-width:3px,stroke:#001f3f
class 1A,1B,D,E processHead
`,
{}
{fontFamily: 'courier'}
);
});
@ -98,7 +98,7 @@ describe('Flowchart', () => {
35(SAM.CommonFA.PopulationFME)-->39(SAM.CommonFA.ChargeDetails)
36(SAM.CommonFA.PremetricCost)-->39(SAM.CommonFA.ChargeDetails)
`,
{}
{ fontFamily: 'courier' }
);
});
@ -169,7 +169,7 @@ describe('Flowchart', () => {
9a072290_1ec3_e711_8c5a_005056ad0002-->d6072290_1ec3_e711_8c5a_005056ad0002
9a072290_1ec3_e711_8c5a_005056ad0002-->71082290_1ec3_e711_8c5a_005056ad0002
`,
{}
{ fontFamily: 'courier' }
);
});
@ -178,7 +178,7 @@ describe('Flowchart', () => {
`
graph TB;subgraph "number as labels";1;end;
`,
{}
{ fontFamily: 'courier' }
);
});
@ -190,7 +190,7 @@ describe('Flowchart', () => {
a1-->a2
end
`,
{}
{ fontFamily: 'courier' }
);
});
@ -202,7 +202,7 @@ describe('Flowchart', () => {
a1-->a2
end
`,
{}
{ fontFamily: 'courier' }
);
});
@ -237,7 +237,7 @@ describe('Flowchart', () => {
style foo fill:#F99,stroke-width:2px,stroke:#F0F
style bar fill:#999,stroke-width:10px,stroke:#0F0
`,
{}
{ fontFamily: 'courier' }
);
});
@ -339,7 +339,7 @@ describe('Flowchart', () => {
sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4DA958A0-26D9-4D47-93A7-70F39FD7D51A;
sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4FC27B48-A6F9-460A-A675-021F5854FE22;
`,
{}
{ fontFamily: 'courier' }
);
});
@ -356,6 +356,7 @@ describe('Flowchart', () => {
{
listUrl: false,
listId: 'color styling',
fontFamily: 'courier',
logLevel: 0
}
);
@ -378,7 +379,7 @@ describe('Flowchart', () => {
`,
{
listUrl: false,
listId: 'color styling',
listId: 'color styling', fontFamily: 'courier',
logLevel: 0
}
);
@ -394,7 +395,7 @@ describe('Flowchart', () => {
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
);
});
@ -413,7 +414,7 @@ describe('Flowchart', () => {
class A someclass;
class C someclass;
`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
);
});
@ -430,7 +431,7 @@ describe('Flowchart', () => {
linkStyle 1 stroke:DarkGray,stroke-width:2px
linkStyle 2 stroke:DarkGray,stroke-width:2px
`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
);
});
@ -439,7 +440,7 @@ describe('Flowchart', () => {
`graph LR
a --> b --> c
`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
);
});
@ -448,7 +449,7 @@ describe('Flowchart', () => {
`graph LR
a --> b & c--> d
`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
);
});
@ -458,7 +459,7 @@ describe('Flowchart', () => {
A[ h ] -- hello --> B[" test "]:::exClass & C --> D;
classDef exClass background:#bbb,border:1px solid red;
`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
);
});
@ -480,7 +481,7 @@ describe('Flowchart', () => {
click B testClick "click test"
classDef someclass fill:#f96;
class A someclass;`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
);
});
@ -494,7 +495,7 @@ describe('Flowchart', () => {
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { nodeSpacing: 50 } }
{ flowchart: { nodeSpacing: 50 }, fontFamily: 'courier' }
);
});
@ -508,7 +509,7 @@ describe('Flowchart', () => {
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { rankSpacing: '100' } }
{ flowchart: { rankSpacing: '100' }, fontFamily: 'courier' }
);
});
@ -521,7 +522,7 @@ describe('Flowchart', () => {
linkStyle 1 stroke:greenyellow,stroke-width:2px
style C fill:greenyellow,stroke:green,stroke-width:4px
`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
);
});
@ -543,7 +544,7 @@ describe('Flowchart', () => {
click E "notes://do-your-thing/id" "other protocol test"
click F "javascript:alert('test')" "script test"
`,
{ securityLevel: 'loose' }
{ securityLevel: 'loose', fontFamily: 'courier' }
);
});
@ -583,7 +584,7 @@ describe('Flowchart', () => {
click B "index.html#link-clicked" "link test"
click D testClick "click test"
`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
);
});
@ -615,7 +616,7 @@ describe('Flowchart', () => {
class A myClass1
class D myClass2
`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
);
});
@ -639,7 +640,7 @@ describe('Flowchart', () => {
classDef redBg fill:#622;
classDef whiteTxt color: white;
`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
);
});
@ -651,7 +652,7 @@ describe('Flowchart', () => {
eat --> sleep
work --> eat
`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
);
});
@ -670,7 +671,7 @@ describe('Flowchart', () => {
class A someclass;
class C someclass;
`,
{ flowchart: { htmlLabels: false } }
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
);
});
@ -696,4 +697,22 @@ describe('Flowchart', () => {
{ }
);
});
it('35: should honor minimum edge length as specified by the user', () => {
imgSnapshotTest(
`graph TD
L1 --- L2
L2 --- C
M1 ---> C
R1 .-> R2
R2 <.-> C
C -->|Label 1| E1
C -- Label 2 ---> E2
C ----> E3
C -----> E4
C ======> E5
`,
{ }
);
});
});

View File

@ -29,7 +29,7 @@ context('Sequence diagram', () => {
Alice -->> John: Parallel message 2
end
`,
{}
{sequence:{actorFontFamily:'courier'}}
);
});
it('should handle different line breaks', () => {
@ -92,7 +92,7 @@ context('Sequence diagram', () => {
Alice->>Bob: I'm short
Bob->>Alice: Short as well
`,
{ sequence: { actorFontSize: 18, actorFontFamily: 'Arial' } }
{ sequence: { actorFontSize: 18, actorFontFamily: 'times' } }
);
});
it('should render notes aligned to the left when configured', () => {

View File

@ -7,7 +7,7 @@ describe('State diagram', () => {
`
info
`,
{ logLevel: 1 }
{ logLevel: 1, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -19,7 +19,7 @@ describe('State diagram', () => {
[*] --> State1
State1 --> [*]
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -31,7 +31,7 @@ describe('State diagram', () => {
[*] --> S1
state "Some long name" as S1
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -43,7 +43,7 @@ describe('State diagram', () => {
[*] --> S1
state "Some long name" as S1: The description
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -54,7 +54,7 @@ describe('State diagram', () => {
state "A long long name" as long1
state "A" as longlonglongid
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -68,7 +68,7 @@ describe('State diagram', () => {
S1 --> S3: long line using <br>should work
S1 --> S4: long line using \\nshould work
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -82,7 +82,7 @@ describe('State diagram', () => {
notes.
end note
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -96,7 +96,7 @@ describe('State diagram', () => {
notes with . and in them.
end note
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -112,7 +112,7 @@ describe('State diagram', () => {
State1 --> State2 : With +,-
note left of State2 : This is the note +,-<br/>
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -128,7 +128,7 @@ describe('State diagram', () => {
And another line...
end note
`,
{}
{ logLevel: 0, fontFamily: 'courier' }
);
});
it('v2 should handle multiline notes with different line breaks', () => {
@ -140,7 +140,7 @@ describe('State diagram', () => {
Line1<br>Line2<br/>Line3<br />Line4<br />Line5
end note
`,
{}
{ logLevel: 0, fontFamily: 'courier' }
);
});
@ -155,7 +155,7 @@ describe('State diagram', () => {
State1 --> State2
State2 --> [*]
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -168,7 +168,7 @@ describe('State diagram', () => {
State1 --> State3
State1 --> [*]
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -184,7 +184,7 @@ describe('State diagram', () => {
State2 --> State3 : Transition 5
State1 --> [*]
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -197,7 +197,7 @@ describe('State diagram', () => {
XState2 : New line
XState1 --> XState2
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -216,7 +216,7 @@ describe('State diagram', () => {
Configuring --> Idle : EvConfig EvConfig EvConfig EvConfig EvConfig
}
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -246,7 +246,7 @@ describe('State diagram', () => {
}
}
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
});
it('v2 should render forks in composit states', () => {
@ -268,7 +268,7 @@ describe('State diagram', () => {
State4 --> [*]
}
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
});
it('v2 should render forks and joins', () => {
@ -286,7 +286,7 @@ describe('State diagram', () => {
join_state --> State4
State4 --> [*]
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -310,7 +310,7 @@ describe('State diagram', () => {
ScrollLockOn --> ScrollLockOff : EvCapsLockPressed
}
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -338,7 +338,7 @@ describe('State diagram', () => {
}
`,
{
logLevel: 0,
logLevel: 0, fontFamily: 'courier'
}
);
});
@ -350,7 +350,7 @@ describe('State diagram', () => {
a --> b: Stop
`,
{
logLevel: 0,
logLevel: 0, fontFamily: 'courier',
}
);
});

View File

@ -9,7 +9,7 @@ describe('State diagram', () => {
[*] --> State1
State1 --> [*]
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -21,7 +21,7 @@ describe('State diagram', () => {
[*] --> S1
state "Some long name" as S1
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -33,7 +33,7 @@ describe('State diagram', () => {
[*] --> S1
state "Some long name" as S1: The description
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -44,7 +44,7 @@ describe('State diagram', () => {
state "A long long name" as long1
state "A" as longlonglongid
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -58,7 +58,7 @@ describe('State diagram', () => {
S1 --> S3: long line using <br>should work
S1 --> S4: long line using \\nshould work
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -72,7 +72,7 @@ describe('State diagram', () => {
notes.
end note
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -86,7 +86,7 @@ describe('State diagram', () => {
notes with . and in them.
end note
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -102,7 +102,7 @@ describe('State diagram', () => {
State1 --> State2 : With +,-
note left of State2 : This is the note +,-<br/>
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -118,7 +118,7 @@ describe('State diagram', () => {
And another line...
end note
`,
{}
{ logLevel: 0, fontFamily: 'courier' }
);
});
it('should handle multiline notes with different line breaks', () => {
@ -130,7 +130,7 @@ describe('State diagram', () => {
Line1<br>Line2<br/>Line3<br />Line4<br />Line5
end note
`,
{}
{ logLevel: 0, fontFamily: 'courier' }
);
});
@ -145,7 +145,7 @@ describe('State diagram', () => {
State1 --> State2
State2 --> [*]
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -158,7 +158,7 @@ describe('State diagram', () => {
State1 --> State3
State1 --> [*]
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -174,7 +174,7 @@ describe('State diagram', () => {
State2 --> State3 : Transition 5
State1 --> [*]
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -187,7 +187,7 @@ describe('State diagram', () => {
XState2 : New line
XState1 --> XState2
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -206,7 +206,7 @@ describe('State diagram', () => {
Configuring --> Idle : EvConfig EvConfig EvConfig EvConfig EvConfig
}
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -236,7 +236,7 @@ describe('State diagram', () => {
}
}
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
});
it('should render forks in composit states', () => {
@ -258,7 +258,7 @@ describe('State diagram', () => {
State4 --> [*]
}
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
});
it('should render forks and joins', () => {
@ -276,7 +276,7 @@ describe('State diagram', () => {
join_state --> State4
State4 --> [*]
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -300,7 +300,7 @@ describe('State diagram', () => {
ScrollLockOn --> ScrollLockOff : EvCapsLockPressed
}
`,
{ logLevel: 0 }
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
@ -315,7 +315,7 @@ describe('State diagram', () => {
}
`,
{
logLevel: 0,
logLevel: 0, fontFamily: 'courier'
}
);
});
@ -328,7 +328,7 @@ describe('State diagram', () => {
}
`,
{
logLevel: 0,
logLevel: 0, fontFamily: 'courier'
}
);
});
@ -340,7 +340,7 @@ describe('State diagram', () => {
a --> b: Stop
`,
{
logLevel: 0,
logLevel: 0, fontFamily: 'courier'
}
);
});

View File

@ -23,7 +23,7 @@ describe('Pie Chart', () => {
it('should render a flowchart diagram', () => {
imgSnapshotTest(
`
%%{init: { 'logLevel': 0, 'theme': '${theme}'} }%%
%%{init: { 'logLevel': 0} }%%
graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}

View File

@ -20,16 +20,8 @@
</head>
<body>
<h1>info below</h1>
<div class="mermaid2" style="width: 100%; height: 20%;">
<div class="mermaid" style="width: 100%; height: 20%;">
%%{init: {'theme': 'base', 'fontFamily': 'arial', 'themeVariables': { 'primaryColor': '#ff0000'}}}%%
classDiagram-v2
classApa -- classB : Inheritance
classA -- classC : link
classC -- classD : link
classB -- classD
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
classDiagram-v2
class BankAccount{
+String owner
@ -59,30 +51,6 @@
classA -- classC : link
classC -- classD : link
classB -- classD
Customer "1" --> "*" Ticket
Student "1" --> "1..*" Course
Galaxy --> "many" Star : Contains
&lt;&lt;interface&gt;&gt; Customer
&lt;&lt;Service&gt;&gt; Galaxy
class BankAccount{
+String owner
+BigDecimal balance
+deposit(amount) bool
+withdrawl(amount) int
}
class Square~Shape~{
int id
List~int~ position
setPoints(List~int~ points)
getPoints() List~int~
}
Square : -List~string~ messages
Square : +setMessages(List~string~ messages)
Square : +getMessages() List~string~
</div>
<script src="./mermaid.js"></script>
<script>

View File

@ -4,14 +4,17 @@
<!-- <meta charset="iso-8859-15"/> -->
<script src="/e2e.js"></script>
<!-- <link href="https://fonts.googleapis.com/css?family=Mansalva&display=swap" rel="stylesheet" /> -->
<!-- <link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet"> -->
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* font-family: 'Mansalva', cursive;*/
/* font-family: 'Mansalva', cursive; */
/* font-family: '"Noto Sans SC", sans-serif'; */
/* font-family: 'arial'; */
/* font-family: "trebuchet ms", verdana, arial; */
}
/* div {
font-family: 'arial';
} */
/* .mermaid-main-font {
font-family: "trebuchet ms", verdana, arial;
font-family: var(--mermaid-font-family);
@ -31,16 +34,16 @@
<script>
// Notice startOnLoad=false
// This prevents default handling in mermaid from render before the e2e logic is applied
mermaid.initialize({
startOnLoad: false,
useMaxWidth: true,
// "themeCSS": ":root { --mermaid-font-family: \"trebuchet ms\", verdana, arial;}",
// fontFamily: '\"trebuchet ms\", verdana, arial;'
// fontFamily: '"Comic Sans MS", "Comic Sans", cursive'
// fontFamily: '"Mansalva", cursive',
// fontFamily: '"Noto Sans SC", sans-serif'
fontFamily: '"Noto Sans SC", sans-serif'
});
// mermaid.initialize({
// startOnLoad: false,
// useMaxWidth: true,
// // "themeCSS": ":root { --mermaid-font-family: \"trebuchet ms\", verdana, arial;}",
// // fontFamily: '\"trebuchet ms\", verdana, arial;'
// // fontFamily: '"Comic Sans MS", "Comic Sans", cursive'
// // fontFamily: '"Mansalva", cursive',
// // fontFamily: '"Noto Sans SC", sans-serif'
// fontFamily: '"Noto Sans SC", sans-serif'
// });
</script>
</body>
</html>

View File

@ -0,0 +1,98 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
</style>
</head>
<body>
<h1>info below</h1>
<div class="flex">
<div class="mermaid" style="width: 50%; height: 400px;">
sequenceDiagram
Alice->>+John: Hello John, how are you?
Alice->>+John: John, can you hear me?
John-->>-Alice: Hi Alice, I can hear you!
John-->>-Alice: I feel great!
</div>
<div class="mermaid" style="width: 50%; height: 20%;">
%%{init: { 'theme': 'base', 'themeVariables':{ 'primaryColor': '#ff0000'}}}%%
graph TD
A(Start) --> B[/Another/]
A[/Another/] --> C[End]
subgraph section
B
C
end
</div>
<div class="mermaid2" style="width: 50%; height: 20%;">
%%{init: {"fontFamily": "arial2"}}%%
graph TD
A[Christmas]
</div>
<div class="mermaid2" style="width: 50%; height: 20%;">
flowchart TD
L1 --- L2
L2 --- C
M1 ---> C
R1 .-> R2
R2 <.-> C
C -->|Label 1| E1
C <-- Label 2 ---> E2
C ----> E3
C <-...-> E4
C ======> E5
</div>
<div class="mermaid2" style="width: 50%; height: 20%;">
graph TD
L1 --- L2
L2 --- C
M1 ---> C
R1 .-> R2
R2 <.-> C
C -->|Label 1| E1
C -- Label 2 ---> E2
C ----> E3
C -----> E4
C ======> E5
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
// theme: 'forest',
// themeVariables:{primaryColor: '#ff0000'},
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'cardinal', "htmlLabels": true },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier',actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"arial", sans-serif',
fontFamily: 'courier',
curve: 'cardinal',
securityLevel: 'strict'
});
function callback(){alert('It worked');}
</script>
</body>
</html>

View File

@ -37,6 +37,27 @@ const contentLoaded = function() {
global.mermaid.init();
}
};
function merge(current, update) {
Object.keys(update).forEach(function(key) {
// if update[key] exist, and it's not a string or array,
// we go in one level deeper
if (
current.hasOwnProperty(key) && // eslint-disable-line
typeof current[key] === 'object' &&
!(current[key] instanceof Array)
) {
merge(current[key], update[key]);
// if update[key] doesn't exist in current, or it's a string
// or array, then assign/overwrite current[key] to update[key]
} else {
current[key] = update[key];
}
});
return current;
}
const contentLoadedApi = function() {
let pos = document.location.href.indexOf('?graph=');
if (pos > 0) {
@ -57,7 +78,11 @@ const contentLoadedApi = function() {
divs[i] = div;
}
mermaid2.initialize(graphObj.mermaid);
const defaultE2eCnf = { theme: 'forest' };
const cnf = merge(defaultE2eCnf, graphObj.mermaid);
mermaid2.initialize(cnf);
for (let i = 0; i < numCodes; i++) {
mermaid2.render(

540
dist/mermaid.core.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

540
dist/mermaid.js vendored

File diff suppressed because one or more lines are too long

2
dist/mermaid.js.map vendored

File diff suppressed because one or more lines are too long

4
dist/mermaid.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,53 +1,34 @@
# Mermaid
[![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid)
[![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master)
[![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# mermaid [![Build Status](https://travis-ci.org/mermaid-js/mermaid.svg?branch=master)](https://travis-ci.org/mermaid-js/mermaid) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/Mermaid/mermaid)
![banner](./img/header.png)
**Edit this Page** [![N|Solid](./img/GitHub-Mark-32px.png)](https://github.com/mermaid-js/mermaid/blob/develop/docs/README.md)
:trophy: **Mermaid was nominated and won the [JS Open Source Awards (2019)](https://osawards.com/javascript/#nominees) in the category "The most exciting use of technology"!!!**
**Mermaid was nominated and won the JS Open Source Awards (2019) in the category "The most exciting use of technology"!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.**
**Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project 🙏**
## About
# Doc-Rot is a Catch-22 that Mermaid helps to solve.
<!-- <Main description> -->
Mermaid is a Javascript based diagramming and charting tool that uses Markdown-inspired text definitions and a renderer to create and modify complex diagrams. The main purpose of Mermaid is to help documentation catch up with development.
### Diagramming and Documentation costs precious developer time and gets outdated quickly.
### But not having diagrams or Docs ruins productivity and hurts organizational learning.
> Doc-Rot is a Catch-22 that Mermaid helps to solve.
## mermaid addresses this problem by cutting the time, effort and tooling that is required to create modifiable diagrams and charts, for smarter and more reusable content.**
Diagramming and documentation costs precious developer time and gets outdated quickly.
But not having diagrams or docs ruins productivity and hurts organizational learning. <br/>
Mermaid addresses this problem by cutting the time, effort and tooling that is required to create modifiable diagrams and charts, for smarter and more reusable content.
The text definitions for Mermaid diagrams allows for it to be updated easily, it can also be made part of production scripts (and other pieces of code).
So less time needs be spent on documenting, as a separate and laborious task. <br/>
The text definitions that create mermaid diagrams allows for easy updates, it can also be made part of production scripts (and other pieces of code). So less time needs be spent on documenting, as a separate and laborious task.
Even non-programmers can create diagrams through the [Mermaid Live Editor](https://github.com/mermaidjs/mermaid-live-editor), visit [Mermaid Overview](./n00b-overview.md) for the video tutorials.
## Even non-programmers can create diagrams through the [Mermaid Live Editor](https://github.com/mermaidjs/mermaid-live-editor).
Want to see what can be built with mermaid, or what applications already support it? Read the [Integrations and Usages for Mermaid](./integrations.md).
## You can watch some popular mermaid Live Editor tutorials on [mermaid Overview](./n00b-overview.md) for a quick intro.
For a more detailed introduction to Mermaid and some of it's more basic uses, look to the [Beginner's Guide](./n00b-overview.md) and [Usage](./usage.md).
## To use mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./integrations.md)**
🌐 [CDN](https://unpkg.com/mermaid/) | 📖 [Documentation](https://mermaidjs.github.io) | 🙌 [Contribution](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md) | 📜 [Version Log](./docs/versionUpdates.md)
## For a more detailed introduction to mermaid and some of it's more basic uses, look to the [Beginner's Guide](https://mermaid-js.github.io/mermaid/#/n00b-overview) and [Usage](./usage.md).
## [CDN](https://unpkg.com/mermaid/)
## [Documentation](https://mermaidjs.github.io)
## [Contribution](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md)
## [Recent Mermaid Versions](./versionUpdates.md).
# Most Recent Version News: Version 8.7.0
## [New and Expanded Mermaid Theme and Styling Configurations](./theming.md)
## [New Mermaid Live-Editor Beta](https://mermaid-js.github.io/docs/mermaid-live-editor-beta/#/edit/eyJjb2RlIjoiJSV7aW5pdDoge1widGhlbWVcIjogXCJmb3Jlc3RcIiwgXCJsb2dMZXZlbFwiOiAxIH19JSVcbmdyYXBoIFREXG4gIEFbQ2hyaXN0bWFzXSAtLT58R2V0IG1vbmV5fCBCKEdvIHNob3BwaW5nKVxuICBCIC0tPiBDe0xldCBtZSB0aGlua31cbiAgQyAtLT58T25lfCBEW0xhcHRvcF1cbiAgQyAtLT58VHdvfCBFW2lQaG9uZV1cbiAgQyAtLT58VGhyZWV8IEZbZmE6ZmEtY2FyIENhcl1cblx0XHQiLCJtZXJtYWlkIjp7InRoZW1lIjoiZGFyayJ9fQ)
## [New Configuration Protocols in version 8.6.0](./8.6.0_docs.md)
## [Version Record](./versionUpdates.md)
**🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/knsv/mermaid/issues/866)**
> 🖖 Keep a steady pulse: mermaid needs more Collaborators, [Read More](https://github.com/knsv/mermaid/issues/866).
# Diagrams that mermaid can render:

View File

@ -25,7 +25,6 @@
- [Configurations](Setup.md)
- [Mermaid Versions](versionUpdates.md)
- [Changelog](CHANGELOG.md)
- [Mermaid Versions](versionUpdate.md)
- Beginner's Guide
- [overview](n00b-overview.md)

View File

@ -6,7 +6,7 @@ Note that practitioners of ER modelling almost always refer to *entity types* si
Mermaid can render ER diagrams
```mermaid
```markdown
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
@ -34,7 +34,7 @@ ER diagrams are a new feature in Mermaid and are **experimental**. There are li
Mermaid syntax for ER diagrams is compatible with PlantUML, with an extension to label the relationship. Each statement consists of the following parts, all of which are mandatory:
```mermaid
```markdown
<first-entity> <relationship> <second-entity> : <relationship-label>
```
@ -47,7 +47,7 @@ Where:
For example:
```mermaid
```markdown
PROPERTY ||--|{ ROOM : contains
```
@ -74,7 +74,7 @@ Cardinality is a property that describes how many elements of another entity can
Relationships may be classified as either *identifying* or *non-identifying* and these are rendered with either solid or dashed lines respectively. This is relevant when one of the entities in question can not have independent existence without the other. For example a firm that insures people to drive cars might need to store data on `NAMED-DRIVER`s. In modelling this we might start out by observing that a `CAR` can be driven by many `PERSON` instances, and a `PERSON` can drive many `CAR`s - both entities can exist without the other, so this is a non-identifying relationship that we might specify in Mermaid as: `PERSON }|..|{ CAR : "driver"`. Note the two dots in the middle of the relationship that will result in a dashed line being drawn between the two entities. But when this many-to-many relationship is resolved into two one-to-many relationships, we observe that a `NAMED-DRIVER` cannot exist without both a `PERSON` and a `CAR` - the relationships become identifying and would be specified using hyphens, which translate to a solid line:
```mermaid
```markdown
CAR ||--o{ NAMED-DRIVER : allows
PERSON ||--o{ NAMED-DRIVER : is
```

View File

@ -45,8 +45,7 @@ This renders a flowchart that allows for features such as: more arrow types, mul
Apart from the graph type, the syntax is the same. This is currently experimental but when the beta period is over, both the graph and flowchart keywords will render in the new way. This means it is ok to start beta testing flowcharts.
## An important note on Flowchart nodes, do not type the word "end" as a Flowchart node. Capitalize all or any one the letters to keep the flowchart from breaking, i.e, "End" or "END". Or you can apply this [workaround](https://github.com/mermaid-js/mermaid/issues/1444#issuecomment-639528897).
> **Important note** Do not type the word "end" as a Flowchart node. Capitalize all or any one the letters to keep the flowchart from breaking, i.e, "End" or "END". Or you can apply this [workaround](https://github.com/mermaid-js/mermaid/issues/1444#issuecomment-639528897).**
## Nodes & shapes
@ -61,7 +60,8 @@ graph LR
graph LR
id
```
# Note that the id is what is displayed in the box.
> **Note** The id is what is displayed in the box.
### A node with text
@ -369,7 +369,7 @@ graph TB
B --> D
```
## Beta: New arrow types
### Beta: New arrow types
When using flowchart instead of graph there is the are new types of arrows supported as per below:
@ -386,7 +386,7 @@ flowchart LR
```
## Beta: multi directional arrows
### Beta: Multi directional arrows
When using flowchart instead of graph there is the possibility to use multidirectional arrows.
@ -404,6 +404,72 @@ flowchart LR
C x--x D
```
### Minimum length of a link
Each node in the flowchart is ultimately assigned to a rank in the rendered
graph, i.e. to a vertical or horizontal level (depending on the flowchart
orientation), based on the nodes to which it is linked. By default, links
can span any number of ranks, but you can ask for any link to be longer
than the others by adding extra dashes in the link definition.
In the following example, two extra dashes are added in the link from node _B_
to node _E_, so that it spans two more ranks than regular links:
```
graph TD
A[Start] --> B{Is it?};
B -->|Yes| C[OK];
C --> D[Rethink];
D --> B;
B ---->|No| E[End];
```
```mermaid
graph TD
A[Start] --> B{Is it?};
B -->|Yes| C[OK];
C --> D[Rethink];
D --> B;
B ---->|No| E[End];
```
> **Note** Links may still be made longer than the requested number of ranks
> by the rendering engine to accommodate other requests.
When the link label is written in the middle of the link, the extra dashes must
be added on the right side of the link. The following example is equivalent to
the previous one:
```
graph TD
A[Start] --> B{Is it?};
B -- Yes --> C[OK];
C --> D[Rethink];
D --> B;
B -- No ----> E[End];
```
```mermaid
graph TD
A[Start] --> B{Is it?};
B -->|Yes| C[OK];
C --> D[Rethink];
D --> B;
B ---->|No| E[End];
```
For dotted or thick links, the characters to add are equals signs or dots,
as summed up in the following table:
| Length | 1 | 2 | 3 |
|-------------------|:------:|:-------:|:--------:|
| Normal | `---` | `----` | `-----` |
| Normal with arrow | `-->` | `--->` | `---->` |
| Thick | `===` | `====` | `=====` |
| Thick with arrow | `==>` | `===>` | `====>` |
| Dotted | `-.-` | `-..-` | `-...-` |
| Dotted with arrow | `-.->` | `-..->` | `-...->` |
## Special characters that break syntax
It is possible to put text within quotes in order to render more troublesome characters. As in the example below:

View File

@ -108,7 +108,7 @@ c. The `mermaid.initialize()` API call to start the rendering process.
</body>
```
### b. The embedded mermaid diagram definition needs to be contains inside a `<div>` tag that signifies that it is a mermaid diagram:
### b. The embedded mermaid diagram definition needs to be contained inside a `<div>` tag that signifies that it is a mermaid diagram:
```
<body>

View File

@ -169,7 +169,7 @@ stateDiagram-v2
```
```mermaid
stateDiagram-v2-v2
stateDiagram-v2
[*] --> First
state First {

View File

@ -5,11 +5,11 @@
## Here is the list of the newest versions in Descending Order, beginning from the latest version.
# [Version 8.7.0](./theming.md) brings with it a system for dynamic and integrated configuration of the diagram themes. The objective of this is to increase the customizability of mermaid and the ease of Styling, with the customization of themes through the `%%init%%` directive and `initialize` calls.
## [Version 8.7.0](./theming.md) brings with it a system for dynamic and integrated configuration of the diagram themes. The objective of this is to increase the customizability of mermaid and the ease of Styling, with the customization of themes through the `%%init%%` directive and `initialize` calls.
Themes follow and build upon the Levels of Configuration and employ `directives` to modify and create custom configurations, as they were introduced in Version [8.6.0](./8.6.0_docs.md).
**These Theming Configurations, similar to directives, will also be made applicable in the Live-Editor, for easier styling.
**These Theming Configurations, similar to directives, will also be made applicable in the Live-Editor, for easier styling.**
### Site-wide Themes
Site-wide themes are still declared via `initialize` by site owners.
@ -22,10 +22,10 @@ Example of `Initalize` call setting `theme` to `base`:
```
**Notes**: Only site owners can use the `mermaidAPI.initialize` call, to set values. Site-Users will have to use `%%init%%` to modify or create the theme for their diagrams.
## Themes at the Local or Current Level
### Themes at the Local or Current Level
When Generating a diagram using on a webpage that supports mermaid. It is also possible to override site-wide theme settings locally, for a specific diagram, using directives, as long as it is not prohibited by the `secure` array.
**Following is an example:
**Following is an example:**
```
%%{init: {'theme':'base'}}%%
@ -63,17 +63,17 @@ The easiest way to make a custom theme is to start with the base theme, and just
```
**Notes:
**Notes:**
Leaving it empty will set all variable values to default.
# [Version 8.6.0](./8.6.0_docs.md) introduces New Configuration Protocols and Directives and a Beta for the [New Mermaid Live-Editor](https://mermaid-js.github.io/docs/mermaid-live-editor-beta/#/edit/eyJjb2RlIjoiJSV7aW5pdDoge1widGhlbWVcIjogXCJmb3Jlc3RcIiwgXCJsb2dMZXZlbFwiOiAxIH19JSVcbmdyYXBoIFREXG4gIEFbQ2hyaXN0bWFzXSAtLT58R2V0IG1vbmV5fCBCKEdvIHNob3BwaW5nKVxuICBCIC0tPiBDe0xldCBtZSB0aGlua31cbiAgQyAtLT58T25lfCBEW0xhcHRvcF1cbiAgQyAtLT58VHdvfCBFW2lQaG9uZV1cbiAgQyAtLT58VGhyZWV8IEZbZmE6ZmEtY2FyIENhcl1cblx0XHQiLCJtZXJtYWlkIjp7InRoZW1lIjoiZGFyayJ9fQ)
## [Version 8.6.0](./8.6.0_docs.md) introduces New Configuration Protocols and Directives and a Beta for the [New Mermaid Live-Editor](https://mermaid-js.github.io/docs/mermaid-live-editor-beta/#/edit/eyJjb2RlIjoiJSV7aW5pdDoge1widGhlbWVcIjogXCJmb3Jlc3RcIiwgXCJsb2dMZXZlbFwiOiAxIH19JSVcbmdyYXBoIFREXG4gIEFbQ2hyaXN0bWFzXSAtLT58R2V0IG1vbmV5fCBCKEdvIHNob3BwaW5nKVxuICBCIC0tPiBDe0xldCBtZSB0aGlua31cbiAgQyAtLT58T25lfCBEW0xhcHRvcF1cbiAgQyAtLT58VHdvfCBFW2lQaG9uZV1cbiAgQyAtLT58VGhyZWV8IEZbZmE6ZmEtY2FyIENhcl1cblx0XHQiLCJtZXJtYWlkIjp7InRoZW1lIjoiZGFyayJ9fQ)
**With version 8.6.0 comes the release of directives for mermaid, a new system for modifying configurations, with the aim of establishing centralized, sane defaults and simple implementation.
**With version 8.6.0 comes the release of directives for mermaid, a new system for modifying configurations, with the aim of establishing centralized, sane defaults and simple implementation.**
directives allow for a diagram specific overriding of config, as it has been discussed in Configurations. This allows site users to input modifications to config alongside diagram definitions, when creating diagrams on a private webpage that supports mermaid.
# Version 8.5.0, introduces New diagrams
## Version 8.5.0, introduces New diagrams
**New diagrams in 8.5**
@ -81,18 +81,18 @@ With version 8.5 there are some bug fixes and enhancements, plus a new diagram t
![Image showing the new ER diagram type](./img/er.png)
# Version 8.2.0, introduces a security improvement
## Version 8.2.0, introduces a security improvement
A `securityLevel` configuration has to first be cleared, `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. This was introduce in version 8.2 as a security improvement, aimed at preventing malicious use.
## securityLevel
### securityLevel
| Parameter | Description | Type | Required | Values |
| ------------- | --------------------------------- | ------ | -------- | ------------------------- |
| securitylevel | Level of trust for parsed diagram | String | Required | Strict, Loose, antiscript |
\*\*Notes:
**Notes:**
- **strict**: (**default**) tags in text are encoded, click functionality is disabeled
- **loose**: tags in text are allowed, click functionality is enabled
@ -103,7 +103,7 @@ With version 8.5 there are some bug fixes and enhancements, plus a new diagram t
If you are taking resposibility for the diagram source security you can set the `securityLevel` to a value of your choosing . By doing this clicks and tags are again allowed.
## To chage `securityLevel` with `mermaidAPI.initialize`:
### To change `securityLevel` with `mermaidAPI.initialize`:
```javascript
mermaidAPI.initialize({

View File

@ -8,29 +8,42 @@ import config from './defaultConfig';
export const defaultConfig = Object.freeze(config);
let siteConfig = assignWithDepth({}, defaultConfig);
let siteConfigDelta;
let directives = [];
let currentConfig = assignWithDepth({}, defaultConfig);
export const updateCurrentConfig = (siteCfg, _directives) => {
// start with config beeing the siteConfig
let cfg = assignWithDepth({}, siteCfg);
// let sCfg = assignWithDepth(defaultConfig, siteConfigDelta);
// Apply directives
let themeVariables = {};
// Join directives
let sumOfDirectives = {};
for (let i = 0; i < _directives.length; i++) {
const d = _directives[i];
sanitize(d);
cfg = assignWithDepth(cfg, d);
if (d.theme) {
cfg.themeVariables = theme[cfg.theme].getThemeVariables(d.themeVariables);
}
// Apply the data from the directive where the the overrides the themeVaraibles
sumOfDirectives = assignWithDepth(sumOfDirectives, d);
}
if (cfg.theme && theme[cfg.theme]) {
let tVars = assignWithDepth({}, cfg.themeVariables);
tVars = assignWithDepth(tVars, themeVariables);
const variables = theme[cfg.theme].getThemeVariables(tVars);
cfg.themeVariables = variables;
cfg = assignWithDepth(cfg, sumOfDirectives);
if (sumOfDirectives.theme) {
const themeVariables = assignWithDepth(
siteConfigDelta.themeVariables || {},
sumOfDirectives.themeVariables
);
cfg.themeVariables = theme[cfg.theme].getThemeVariables(themeVariables);
}
// if (cfg.theme && theme[cfg.theme]) {
// let tVars = assignWithDepth({}, cfg.themeVariables);
// tVars = assignWithDepth(tVars, themeVariables);
// const variables = theme[cfg.theme].getThemeVariables(tVars);
// cfg.themeVariables = variables;
// }
currentConfig = cfg;
return cfg;
};
@ -59,6 +72,10 @@ export const setSiteConfig = conf => {
currentConfig = updateCurrentConfig(siteConfig, directives);
return siteConfig;
};
export const setSiteConfigDelta = conf => {
siteConfigDelta = assignWithDepth({}, conf);
};
export const updateSiteConfig = conf => {
siteConfig = assignWithDepth(siteConfig, conf);
updateCurrentConfig(siteConfig, directives);

View File

@ -414,6 +414,7 @@ export const draw = function(text, id) {
// Set up an SVG group so that we can translate the final graph.
const svg = select(`[id="${id}"]`);
svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
// Run the renderer. This is what draws the final graph.
const element = select('#' + id + ' g');

View File

@ -157,6 +157,7 @@ export const draw = function(text, id) {
// Fetch the default direction, use TD if none was found
const diagram = select(`[id='${id}']`);
diagram.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
insertMarkers(diagram);
// Layout graph, Create a new directed graph
@ -176,6 +177,7 @@ export const draw = function(text, id) {
const classes = classDb.getClasses();
const keys = Object.keys(classes);
for (let i = 0; i < keys.length; i++) {
const classDef = classes[keys[i]];
const node = svgDraw.drawClass(diagram, classDef, conf);

View File

@ -110,6 +110,7 @@ export const addSingleLink = function(_start, _end, type, linktext) {
if (typeof type !== 'undefined') {
edge.type = type.type;
edge.stroke = type.stroke;
edge.length = type.length;
}
edges.push(edge);
};
@ -498,97 +499,92 @@ export const firstGraph = () => {
};
const destructStartLink = _str => {
const str = _str.trim();
let str = _str.trim();
let type = 'arrow_open';
switch (str) {
case '<--':
return { type: 'arrow_point', stroke: 'normal' };
case 'x--':
return { type: 'arrow_cross', stroke: 'normal' };
case 'o--':
return { type: 'arrow_circle', stroke: 'normal' };
case '<-.':
return { type: 'arrow_point', stroke: 'dotted' };
case 'x-.':
return { type: 'arrow_cross', stroke: 'dotted' };
case 'o-.':
return { type: 'arrow_circle', stroke: 'dotted' };
case '<==':
return { type: 'arrow_point', stroke: 'thick' };
case 'x==':
return { type: 'arrow_cross', stroke: 'thick' };
case 'o==':
return { type: 'arrow_circle', stroke: 'thick' };
case '--':
return { type: 'arrow_open', stroke: 'normal' };
case '==':
return { type: 'arrow_open', stroke: 'thick' };
case '-.':
return { type: 'arrow_open', stroke: 'dotted' };
switch (str[0]) {
case '<':
type = 'arrow_point';
str = str.slice(1);
break;
case 'x':
type = 'arrow_cross';
str = str.slice(1);
break;
case 'o':
type = 'arrow_circle';
str = str.slice(1);
break;
}
let stroke = 'normal';
if (str.indexOf('=') !== -1) {
stroke = 'thick';
}
if (str.indexOf('.') !== -1) {
stroke = 'dotted';
}
return { type, stroke };
};
const countChar = (char, str) => {
const length = str.length;
let count = 0;
for (let i = 0; i < length; ++i) {
if (str[i] === char) {
++count;
}
}
return count;
};
const destructEndLink = _str => {
const str = _str.trim();
let line = str.slice(0, -1);
let type = 'arrow_open';
switch (str) {
case '--x':
return { type: 'arrow_cross', stroke: 'normal' };
case '-->':
return { type: 'arrow_point', stroke: 'normal' };
case '<-->':
return { type: 'double_arrow_point', stroke: 'normal' };
case 'x--x':
return { type: 'double_arrow_cross', stroke: 'normal' };
case 'o--o':
return { type: 'double_arrow_circle', stroke: 'normal' };
case 'o.-o':
return { type: 'double_arrow_circle', stroke: 'dotted' };
case '<==>':
return { type: 'double_arrow_point', stroke: 'thick' };
case 'o==o':
return { type: 'double_arrow_circle', stroke: 'thick' };
case 'x==x':
return { type: 'double_arrow_cross', stroke: 'thick' };
case 'x.-x':
return { type: 'double_arrow_cross', stroke: 'dotted' };
case 'x-.-x':
return { type: 'double_arrow_cross', stroke: 'dotted' };
case '<.->':
return { type: 'double_arrow_point', stroke: 'dotted' };
case '<-.->':
return { type: 'double_arrow_point', stroke: 'dotted' };
case 'o-.-o':
return { type: 'double_arrow_circle', stroke: 'dotted' };
case '--o':
return { type: 'arrow_circle', stroke: 'normal' };
case '---':
return { type: 'arrow_open', stroke: 'normal' };
case '-.-x':
return { type: 'arrow_cross', stroke: 'dotted' };
case '-.->':
return { type: 'arrow_point', stroke: 'dotted' };
case '-.-o':
return { type: 'arrow_circle', stroke: 'dotted' };
case '-.-':
return { type: 'arrow_open', stroke: 'dotted' };
case '.-x':
return { type: 'arrow_cross', stroke: 'dotted' };
case '.->':
return { type: 'arrow_point', stroke: 'dotted' };
case '.-o':
return { type: 'arrow_circle', stroke: 'dotted' };
case '.-':
return { type: 'arrow_open', stroke: 'dotted' };
case '==x':
return { type: 'arrow_cross', stroke: 'thick' };
case '==>':
return { type: 'arrow_point', stroke: 'thick' };
case '==o':
return { type: 'arrow_circle', stroke: 'thick' };
case '===':
return { type: 'arrow_open', stroke: 'thick' };
switch (str.slice(-1)) {
case 'x':
type = 'arrow_cross';
if (str[0] === 'x') {
type = 'double_' + type;
line = line.slice(1);
}
break;
case '>':
type = 'arrow_point';
if (str[0] === '<') {
type = 'double_' + type;
line = line.slice(1);
}
break;
case 'o':
type = 'arrow_circle';
if (str[0] === 'o') {
type = 'double_' + type;
line = line.slice(1);
}
break;
}
let stroke = 'normal';
let length = line.length - 1;
if (line[0] === '=') {
stroke = 'thick';
}
let dots = countChar('.', line);
if (dots) {
stroke = 'dotted';
length = dots;
}
return { type, stroke, length };
};
const destructLink = (_str, _startStr) => {
@ -602,7 +598,7 @@ const destructLink = (_str, _startStr) => {
}
if (startInfo.type === 'arrow_open') {
// -- xyz --> - take arrow type form ending
// -- xyz --> - take arrow type from ending
startInfo.type = info.type;
} else {
// x-- xyz --> - not supported
@ -615,6 +611,7 @@ const destructLink = (_str, _startStr) => {
startInfo.type = 'double_arrow_point';
}
startInfo.length = info.length;
return startInfo;
}

View File

@ -188,6 +188,7 @@ export const addEdges = function(edges, g) {
var linkNameEnd = 'LE-' + edge.end;
const edgeData = {};
edgeData.minlen = edge.length || 1;
//edgeData.id = 'id' + cnt;
// Set link type for rendering
@ -397,6 +398,7 @@ export const draw = function(text, id) {
// Set up an SVG group so that we can translate the final graph.
const svg = select(`[id="${id}"]`);
svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
// Run the renderer. This is what draws the final graph.
const element = select('#' + id + ' g');

View File

@ -244,6 +244,7 @@ export const addEdges = function(edges, g) {
edgeData.id = linkId;
edgeData.class = linkNameStart + ' ' + linkNameEnd;
edgeData.minlen = edge.length || 1;
// Add the edge to the graph
g.setEdge(edge.start, edge.end, edgeData, cnt);
@ -385,6 +386,7 @@ export const draw = function(text, id) {
// Set up an SVG group so that we can translate the final graph.
const svg = select(`[id="${id}"]`);
svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
// Run the renderer. This is what draws the final graph.
const element = select('#' + id + ' g');

View File

@ -25,6 +25,8 @@ describe('[Arrows] when parsing', () => {
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it("should handle angle bracket ' > ' as direction LR", function() {
@ -43,6 +45,8 @@ describe('[Arrows] when parsing', () => {
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it("should handle angle bracket ' < ' as direction RL", function() {
@ -61,6 +65,8 @@ describe('[Arrows] when parsing', () => {
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it("should handle caret ' ^ ' as direction BT", function() {
@ -77,8 +83,11 @@ describe('[Arrows] when parsing', () => {
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].length).toBe(1);
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it("should handle lower-case 'v' as direction TB", function() {
@ -97,6 +106,8 @@ describe('[Arrows] when parsing', () => {
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle a nodes and edges and a space between link and node', function() {
@ -112,6 +123,8 @@ describe('[Arrows] when parsing', () => {
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle a nodes and edges, a space between link and node and each line ending without semicolon', function() {
@ -127,6 +140,8 @@ describe('[Arrows] when parsing', () => {
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle statements ending without semicolon', function() {
@ -142,9 +157,11 @@ describe('[Arrows] when parsing', () => {
expect(edges[1].end).toBe('C');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
describe('it should multi directional arrows', function() {
describe('it should handle multi directional arrows', function() {
describe('point', function() {
it('should handle double edged nodes and edges', function() {
const res = flow.parser.parse('graph TD;\nA<-->B;');
@ -159,6 +176,8 @@ describe('[Arrows] when parsing', () => {
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes with text', function() {
@ -173,8 +192,9 @@ describe('[Arrows] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].text).toBe('text');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes and edges on thick arrows', function() {
@ -189,8 +209,9 @@ describe('[Arrows] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes with text on thick arrows', function() {
@ -205,8 +226,9 @@ describe('[Arrows] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].text).toBe('text');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes and edges on dotted arrows', function() {
@ -221,8 +243,9 @@ describe('[Arrows] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes with text on dotted arrows', function() {
@ -237,8 +260,9 @@ describe('[Arrows] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].text).toBe('text');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(1);
});
});
});

View File

@ -53,6 +53,8 @@ describe('[Edges] when parsing', () => {
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_cross');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes with text', function() {
@ -67,8 +69,9 @@ describe('[Edges] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_cross');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].text).toBe('text');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes and edges on thick arrows', function() {
@ -83,11 +86,12 @@ describe('[Edges] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_cross');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes with text on thick arrows XYZ1', function() {
it('should handle double edged nodes with text on thick arrows', function() {
const res = flow.parser.parse('graph TD;\nA x== text ==x B;');
const vert = flow.parser.yy.getVertices();
@ -99,8 +103,9 @@ describe('[Edges] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_cross');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].text).toBe('text');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes and edges on dotted arrows', function() {
@ -115,8 +120,9 @@ describe('[Edges] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_cross');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes with text on dotted arrows', function() {
@ -131,8 +137,9 @@ describe('[Edges] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_cross');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].text).toBe('text');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(1);
});
});
@ -150,6 +157,8 @@ describe('[Edges] when parsing', () => {
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_circle');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes with text', function() {
@ -164,8 +173,9 @@ describe('[Edges] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_circle');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].text).toBe('text');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes and edges on thick arrows', function() {
@ -180,8 +190,9 @@ describe('[Edges] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_circle');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes with text on thick arrows', function() {
@ -196,8 +207,9 @@ describe('[Edges] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_circle');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].text).toBe('text');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes and edges on dotted arrows', function() {
@ -212,8 +224,9 @@ describe('[Edges] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_circle');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(1);
});
it('should handle double edged nodes with text on dotted arrows', function() {
@ -228,8 +241,9 @@ describe('[Edges] when parsing', () => {
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_circle');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].text).toBe('text');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(1);
});
});
@ -245,9 +259,359 @@ describe('[Edges] when parsing', () => {
expect(edges.length).toBe(2);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('This is the 123 s text');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(1);
expect(edges[1].start).toBe('A');
expect(edges[1].end).toBe('B');
expect(edges[1].type).toBe('arrow_open');
expect(edges[1].text).toBe('This is the second edge');
expect(edges[1].stroke).toBe('normal');
expect(edges[1].length).toBe(1);
});
describe('edge length', function() {
for (let length = 1; length <= 3; ++length) {
it(`should handle normal edges with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA -${'-'.repeat(length)}- B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle normal labelled edges with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA -- Label -${'-'.repeat(length)}- B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle normal edges with arrows with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA -${'-'.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle normal labelled edges with arrows with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA -- Label -${'-'.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle normal edges with double arrows with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA <-${'-'.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle normal labelled edges with double arrows with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA <-- Label -${'-'.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('normal');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle thick edges with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA =${'='.repeat(length)}= B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle thick labelled edges with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA == Label =${'='.repeat(length)}= B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle thick edges with arrows with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA =${'='.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle thick labelled edges with arrows with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA == Label =${'='.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle thick edges with double arrows with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA <=${'='.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle thick labelled edges with double arrows with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA <== Label =${'='.repeat(length)}> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('thick');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle dotted edges with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA -${'.'.repeat(length)}- B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle dotted labelled edges with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA -. Label ${'.'.repeat(length)}- B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_open');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle dotted edges with arrows with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA -${'.'.repeat(length)}-> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle dotted labelled edges with arrows with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA -. Label ${'.'.repeat(length)}-> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('arrow_point');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle dotted edges with double arrows with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA <-${'.'.repeat(length)}-> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(length);
});
}
for (let length = 1; length <= 3; ++length) {
it(`should handle dotted edges with double arrows with length ${length}`, function() {
const res = flow.parser.parse(`graph TD;\nA <-. Label ${'.'.repeat(length)}-> B;`);
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(vert['A'].id).toBe('A');
expect(vert['B'].id).toBe('B');
expect(edges.length).toBe(1);
expect(edges[0].start).toBe('A');
expect(edges[0].end).toBe('B');
expect(edges[0].type).toBe('double_arrow_point');
expect(edges[0].text).toBe('Label');
expect(edges[0].stroke).toBe('dotted');
expect(edges[0].length).toBe(length);
});
}
});
});

View File

@ -61,46 +61,12 @@
";" return 'SEMI';
"," return 'COMMA';
"*" return 'MULT';
\s*\-\-[x]\s* return 'LINK';
\s*\-\-\>\s* return 'LINK';
\s*\<\-\-\>\s* return 'LINK';
\s*[x]\-\-[x]\s* return 'LINK';
\s*[o]\-\-[o]\s* return 'LINK';
\s*[o]\.\-[o]\s* return 'LINK';
\s*\<\=\=\>\s* return 'LINK';
\s*[o]\=\=[o]\s* return 'LINK';
\s*[x]\=\=[x]\s* return 'LINK';
\s*[x].\-[x]\s* return 'LINK';
\s*[x]\-\.\-[x]\s* return 'LINK';
\s*\<\.\-\>\s* return 'LINK';
\s*\<\-\.\-\>\s* return 'LINK';
\s*[o]\-\.\-[o]\s* return 'LINK';
\s*\-\-[o]\s* return 'LINK';
\s*\-\-\-\s* return 'LINK';
\s*\-\.\-[x]\s* return 'LINK';
\s*\-\.\-\>\s* return 'LINK';
\s*\-\.\-[o]\s* return 'LINK';
\s*\-\.\-\s* return 'LINK';
\s*.\-[x]\s* return 'LINK';
\s*\.\-\>\s* return 'LINK';
\s*\.\-[o]\s* return 'LINK';
\s*\.\-\s* return 'LINK';
\s*\=\=[x]\s* return 'LINK';
\s*\=\=\>\s* return 'LINK';
\s*\=\=[o]\s* return 'LINK';
\s*\=\=[\=]\s* return 'LINK';
\s*\<\-\-\s* return 'START_LINK';
\s*[x]\-\-\s* return 'START_LINK';
\s*[o]\-\-\s* return 'START_LINK';
\s*\<\-\.\s* return 'START_LINK';
\s*[x]\-\.\s* return 'START_LINK';
\s*[o]\-\.\s* return 'START_LINK';
\s*\<\=\=\s* return 'START_LINK';
\s*[x]\=\=\s* return 'START_LINK';
\s*[o]\=\=\s* return 'START_LINK';
\s*\-\-\s* return 'START_LINK';
\s*\-\.\s* return 'START_LINK';
\s*\=\=\s* return 'START_LINK';
\s*[xo<]?\-\-+[-xo>]\s* return 'LINK';
\s*[xo<]?\=\=+[=xo>]\s* return 'LINK';
\s*[xo<]?\-?\.+\-[xo>]?\s* return 'LINK';
\s*[xo<]?\-\-\s* return 'START_LINK';
\s*[xo<]?\=\=\s* return 'START_LINK';
\s*[xo<]?\-\.\s* return 'START_LINK';
"(-" return '(-';
"-)" return '-)';
"([" return 'STADIUMSTART';
@ -401,11 +367,11 @@ link: linkStatement arrowText
| linkStatement
{$$ = $1;}
| START_LINK text LINK
{var inf = yy.destructLink($3, $1); $$ = {"type":inf.type,"stroke":inf.stroke,"text":$2};}
{var inf = yy.destructLink($3, $1); $$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length,"text":$2};}
;
linkStatement: LINK
{var inf = yy.destructLink($1);$$ = {"type":inf.type,"stroke":inf.stroke};}
{var inf = yy.destructLink($1);$$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length};}
;
arrowText:

View File

@ -3,8 +3,6 @@ const getStyles = options =>
fill: ${options.nodeBorder};
stroke: none;
font-size: 10px;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family);
}
g.stateGroup text {
fill: ${options.textColor};
@ -76,8 +74,6 @@ g.stateGroup line {
fill: ${options.labelColor};
font-size: 10px;
font-weight: bold;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family);
}
.node circle.state-start {

View File

@ -220,7 +220,12 @@ const render = function(id, _txt, cb, container) {
// console.warn('Render fetching config');
const cnf = configApi.getConfig();
console.warn('Render with config after adding new directives', cnf.fontFamily);
console.warn('Render with config after adding new directives', cnf.sequence);
// console.warn(
// 'Render with config after adding new directives',
// cnf.fontFamily,
// cnf.themeVariables.fontFamily
// );
// Check the maximum allowed text size
if (_txt.length > cnf.maxTextSize) {
txt = 'graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa';
@ -552,10 +557,9 @@ function reinitialize() {
}
function initialize(options) {
console.warn(`mermaidAPI.initialize: v${pkg.version} `, options);
// console.warn(`mermaidAPI.initialize: v${pkg.version} `, options);
// Handle legacy location of font-family configuration
// console.warn('Conf - ', options.themeVariables.fontFamily);
if (options && options.fontFamily) {
if (!options.themeVariables) {
options.themeVariables = { fontFamily: options.fontFamily };
@ -566,12 +570,13 @@ function initialize(options) {
}
}
// Set default options
configApi.setSiteConfigDelta(options);
if (options && options.theme && theme[options.theme]) {
// Todo merge with user options
options.themeVariables = theme[options.theme].getThemeVariables(options.themeVariables);
} else {
if (options) options.themeVariables = theme.default.getThemeVariables();
if (options) options.themeVariables = theme.default.getThemeVariables(options.themeVariables);
}
const config =

View File

@ -29,7 +29,7 @@ const themes = {
export const calcThemeVariables = (theme, userOverRides) => theme.calcColors(userOverRides);
const getStyles = (type, userStyles, options) => {
console.warn('options in styles: ', options);
//console.warn('options in styles: ', options);
return ` {
font-family: ${options.fontFamily};
font-size: ${options.fontSize};

View File

@ -13,7 +13,7 @@ class Theme {
// this.secondaryColor = adjust(this.primaryColor, { h: 120 });
this.tertiaryColor = adjust(this.primaryColor, { h: -160 });
console.warn('primary color', this.primaryColor, 'tertiary - color', this.tertiaryColor);
// console.log('primary color', this.primaryColor, 'tertiary - color', this.tertiaryColor);
this.primaryBorderColor = mkBorder(this.primaryColor, this.darkMode);
this.secondaryBorderColor = mkBorder(this.secondaryColor, this.darkMode);
this.tertiaryBorderColor = mkBorder(this.tertiaryColor, this.darkMode);