Merge branch 'develop' into feature/1893_data_flow_diagrams

This commit is contained in:
Michael Maier 2021-11-28 12:26:39 +01:00 committed by GitHub
commit 9e8c03cb49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
115 changed files with 123148 additions and 147430 deletions

View File

@ -6,15 +6,20 @@
},
"parser": "@babel/eslint-parser",
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"jsx": true
},
"sourceType": "module"
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"jsx": true
},
"sourceType": "module"
},
"extends": ["prettier", "eslint:recommended"],
"plugins": ["prettier"],
"extends": ["eslint:recommended", "plugin:jsdoc/recommended", "plugin:prettier/recommended"],
"plugins": ["jsdoc", "prettier"],
"rules": {
"prettier/prettier": ["error"]
"jsdoc/check-indentation": 0,
"jsdoc/check-alignment": 0,
"jsdoc/check-line-alignment": 0,
"jsdoc/multiline-blocks": 0,
"jsdoc/newline-after-description": 0,
"jsdoc/tag-lines": 0
}
}
}

View File

@ -1,12 +1,17 @@
version: 2
updates:
- package-ecosystem: npm
open-pull-requests-limit: 10
directory: /
target-branch: develop
schedule:
interval: weekly
day: monday
time: "07:00"
- package-ecosystem: github-actions
directory: /
target-branch: develop
schedule:
interval: weekly
day: monday
time: "07:00"

View File

@ -8,7 +8,7 @@ jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: andymckay/labeler@1.0.3
- uses: andymckay/labeler@1.0.4
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
add-labels: "Status: Triage"

View File

@ -1,13 +0,0 @@
name: Lock closed issue
on:
issues:
types: [closed]
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: Dunning-Kruger/lock-issues@v1.1
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"

View File

@ -1,5 +1,6 @@
{
"endOfLine": "auto",
"plugins": ["prettier-plugin-jsdoc"],
"printWidth": 100,
"singleQuote": true,
"endOfLine": "auto"
"singleQuote": true
}

View File

@ -11,7 +11,7 @@ Here are a few things to know to get you started on the right path.
We make all changes via pull requests. As we have many pull requests from developers new to mermaid, the current approach is to have *knsv, Knut Sveidqvist* as a main reviewer of changes and merging pull requests. More precisely like this:
* Large changes reviewed by knsv or other developer asked to review by knsv
* Smaller low-risk changes like dependecies, documentation etc can be merged by active collaborators
* Smaller low-risk changes like dependencies, documentation etc can be merged by active collaborators
* documentation (updates to the docs folder is also allowed via direct commits)
To commit code, create a branch, let it start with the type like feature or bug followed by the issue number for reference and some describing text.
@ -35,13 +35,13 @@ The documentation is written in Markdown, for more information about Markdown [s
If you want to preview the documentation site on your machine, you need to install `docsify-cli`:
```
```sh
$ npm i docsify-cli -g
````
```
If you are more familiar with Yarn, you can use the following command:
```
```sh
$ yarn global add docsify-cli
```
@ -50,7 +50,7 @@ If the installation is successful, the command `docsify` will be available in yo
You can now run the following command to serve the documentation site:
```
```sh
$ docsify serve docs
```
@ -85,7 +85,7 @@ The rendering tests are very straightforward to create. There is a function imgS
When running in ci it will take a snapshot of the rendered diagram and compare it with the snapshot from last build and flag for review it if it differs.
This is what a rendering test looks like:
```
```javascript
it('should render forks and joins', () => {
imgSnapshotTest(
`

View File

@ -23,7 +23,7 @@ Mermaid 通过减少创建可修改的图表所需要的时间、精力和工具
你可以访问 [教程](./docs/Tutorials.md) 来查看 Live Editor 的视频教程。
U也可以查看 [Mermaid 的集成和使用](./docs/integrations.md) 这个清单来检查你的文档工具是否已经集成了 Mermaid 支持。
如果想要查看关于 Mermaid 更详细的介绍及基础使用方式,可以查看如果想要查看关于 Mermaid 更详细的介绍及基础使用方式,可以查看 [入门指引](./docs/n00b-overview.md) and [用法](./docs/usage.md).
如果想要查看关于 Mermaid 更详细的介绍及基础使用方式,可以查看 [入门指引](./docs/n00b-overview.md) and [用法](./docs/usage.md).
🌐 [CDN](https://unpkg.com/mermaid/) | 📖 [文档](https://mermaidjs.github.io) | 🙌 [贡献](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md) | 📜 [更新日志](./docs/CHANGELOG.md)
@ -31,7 +31,7 @@ U也可以查看 [Mermaid 的集成和使用](./docs/integrations.md) 这个清
## 示例
__下面是一些使用 Mermaid 和类 Markdown 语法创建的图表示例。点击[语法](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference) 查看详情__
__下面是一些使用 Mermaid 和类 Markdown 语法创建的图表示例。点击 [语法](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference) 查看详情__
<table>
<!-- <Flowchart> -->
<tr><td colspan=2 align="center">

View File

@ -78,5 +78,25 @@ describe('XSS', () => {
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
})
it('should not allow maniplulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => {
cy.visit('http://localhost:9000/xss10.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
})
it('should not allow maniplulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => {
cy.visit('http://localhost:9000/xss11.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
})
it('should not allow maniplulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => {
cy.visit('http://localhost:9000/xss12.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
})
it('should not allow maniplulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => {
cy.visit('http://localhost:9000/xss13.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
})
})

View File

@ -611,6 +611,16 @@ flowchart RL
);
});
it('76: handle unicode encoded character with HTML labels true', () => {
imgSnapshotTest(
`flowchart TB
a{{"Lorem 'ipsum' dolor 'sit' amet, 'consectetur' adipiscing 'elit'."}}
--> b{{"Lorem #quot;ipsum#quot; dolor #quot;sit#quot; amet,#quot;consectetur#quot; adipiscing #quot;elit#quot;."}}
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
);
});
it('2050: handling of different rendering direction in subgraphs', () => {
imgSnapshotTest(
`

View File

@ -563,7 +563,8 @@ context('Sequence diagram', () => {
});
});
context('links', () => {
it('should support actor links and properties', () => {
it('should support actor links and properties EXPERIMENTAL: USE WITH CAUTION', () => {
//Be aware that the syntax for "properties" is likely to be changed.
imgSnapshotTest(
`
%%{init: { "config": { "mirrorActors": true, "forceMenus": true }}}%%
@ -583,7 +584,8 @@ context('Sequence diagram', () => {
{ logLevel: 0, sequence: { mirrorActors: true, noteFontSize: 18, noteFontFamily: 'Arial' } }
);
});
it('should support actor links and properties when not mirrored', () => {
it('should support actor links and properties when not mirrored EXPERIMENTAL: USE WITH CAUTION', () => {
//Be aware that the syntax for "properties" is likely to be changed.
imgSnapshotTest(
`
%%{init: { "config": { "mirrorActors": false, "forceMenus": true, "wrap": true }}}%%

View File

@ -74,7 +74,7 @@ stateDiagram-v2
A --> D: asd123
</div>
</div>
<div class="mermaid" style="width: 50%; height: 40%;">
<div class="mermaid2" style="width: 50%; height: 40%;">
%% this does not produce the desired result
flowchart TB
subgraph container_Beta
@ -88,24 +88,13 @@ flowchart TB
</div>
<div class="mermaid" style="width: 50%; height: 40%;">
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ff0000'}}}%%
flowchart TB
b-->B
a-->c
subgraph O
A
end
subgraph B
c
end
subgraph A
a
b
B
end
flowchart TB
a{{"Lorem 'ipsum' dolor 'sit' amet, 'consectetur' adipiscing 'elit'."}}
--> b{{"Lorem #quot;ipsum#quot; dolor #quot;sit#quot; amet,#quot;consectetur#quot; adipiscing #quot;elit#quot;."}}
</div>
<div class="mermaid" style="width: 50%; height: 50%;">
<div class="mermaid2" style="width: 50%; height: 50%;">
flowchart TB
internet
nat
@ -130,7 +119,7 @@ flowchart TB
routeur --> subnet1 & subnet2
subnet1 & subnet2 --> nat --> internet
</div>
<div class="mermaid" style="width: 50%; height: 50%;">
<div class="mermaid2" style="width: 50%; height: 50%;">
flowchart TD
subgraph one[One]
@ -145,7 +134,7 @@ end
sub_one --> two
</div>
<div class="mermaid" style="width: 50%; height: 50%;">
<div class="mermaid2" style="width: 50%; height: 50%;">
flowchart TD
subgraph one[One]
@ -174,7 +163,7 @@ _one --> b
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'cardinal', "htmlLabels": false },
flowchart: { curve: 'cardinal', "htmlLabels": true },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated

View File

@ -28,113 +28,13 @@
<div>info below</div>
<div class="flex flex-wrap">
<div class="mermaid2" style="width: 100%; height: 20%;">
classDiagram
direction TB
class Student {
-idCard : IdCard
}
class IdCard{
-id : int
-name : string
}
class Bike{
-id : int
-name : string
}
Student "1" --o "1" IdCard : carries
Student "1" --o "1" Bike : rides
</div>
<div class="mermaid3" style="width: 100%; height: 20%;">
stateDiagram
state CompositeState {
YourState123456789012345123456789123456789012345123456789123456789012345123456789123456789012345123456789 --> MyState:a label
}
</div>
<div class="mermaid" style="width: 100%; height: 20%;">
sequenceDiagram
%%{init: {'config': {'wrap': true }}}%%
actor Alice as Extremely utterly long line of longness which had preivously overflown the actor box as it is much longer than what it should be
actor Bob
participant John as John2
participant Mandy
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice
Alice->>John: Hi John
John->>Mandy: Hi Mandy
Mandy ->>Joan: Hi Joan
</div>
<div class="mermaid" style="width: 100%; height: 20%;">
%%{int: { "apa":"b", "theme":"forest"}}%%
sequenceDiagram
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice
</div>
<div class="mermaid">
sequenceDiagram
autonumber
par Action 1
Alice->>John: Hello John, how are you?
and Action 2
Alice->>Bob: Hello Bob, how are you?
end
Alice->>+John: Hello John, how are you?
Alice->>+John: John, can you hear me?
John-->>-Alice: Hi Alice, I can hear you!
Note right of John: John is perceptive
John-->>-Alice: I feel great!
loop Every minute
John-->Alice: Great!
end
</div>
<div class="mermaid">
sequenceDiagram
%%{init: {'config': {'wrap': true }}}%%
actor Alice
actor Bob
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice
</div>
<div class="mermaid" style="width: 100%; height: 20%;">
%%{init: {'config': {'wrap': true }}}%%
sequenceDiagram
participant A as Extremely utterly long line of longness which had preivously overflown the actor box as it is much longer than what it should be
A->>Bob: Hola
Bob-->A: Pasten !
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
stateDiagram-v2
state CS {
state ACS {
YourState
}
}
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
stateDiagram-v2
[*] --> Active
[*] --> S1
state "Some long name" as S1
state Active {
[*] --> NumLockOff
NumLockOff --> NumLockOn : EvNumLockPressed
NumLockOn --> NumLockOff : EvNumLockPressed
--
[*] --> CapsLockOff
CapsLockOff --> CapsLockOn : EvCapsLockPressed
CapsLockOn --> CapsLockOff : EvCapsLockPressed
}
state SomethingElse {
A --> B
B --> A
}
</div>
Active --> SomethingElse
note right of SomethingElse : This is the note to the right.
SomethingElse --> [*] </div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {

105
cypress/platform/xss10.html Normal file
View File

@ -0,0 +1,105 @@
<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';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10, curve: 'cardinal', htmlLabels: true
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier',actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize']
// themeVariables: {relationLabelColor: 'red'}
});
function callback(){alert('It worked');}
function xssAttack(){
const div = document.createElement('div')
div.id = 'the-malware'
div.className = 'malware'
div.innerHTML = 'XSS Succeeded'
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = "classDiagram\n"
diagram += "class Square~<img/src";
diagram += "='1'/onerror=xssAttack()>~{\n";
diagram += "id A\n";
diagram += "}";
// var diagram = "stateDiagram-v2\n";
// diagram += "<img/src='1'/onerror"
// diagram += "=xssAttack()> --> B";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

103
cypress/platform/xss11.html Normal file
View File

@ -0,0 +1,103 @@
<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';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10, curve: 'cardinal', htmlLabels: true
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier',actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize']
// themeVariables: {relationLabelColor: 'red'}
});
function callback(){alert('It worked');}
function xssAttack(){
const div = document.createElement('div')
div.id = 'the-malware'
div.className = 'malware'
div.innerHTML = 'XSS Succeeded'
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = "stateDiagram-v2\n"
diagram += "s2 : This is a state description<img/src";
diagram += "='1'/onerror=xssAttack()>";
// var diagram = "stateDiagram-v2\n";
// diagram += "<img/src='1'/onerror"
// diagram += "=xssAttack()> --> B";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

103
cypress/platform/xss12.html Normal file
View File

@ -0,0 +1,103 @@
<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';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10, curve: 'cardinal', htmlLabels: true
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier',actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize']
// themeVariables: {relationLabelColor: 'red'}
});
function callback(){alert('It worked');}
function xssAttack(){
const div = document.createElement('div')
div.id = 'the-malware'
div.className = 'malware'
div.innerHTML = 'XSS Succeeded'
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = "stateDiagram-v2\n"
diagram += "s2 : A<img/src";
diagram += "='1'/onerror=xssAttack()>";
// var diagram = "stateDiagram-v2\n";
// diagram += "<img/src='1'/onerror"
// diagram += "=xssAttack()> --> B";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

103
cypress/platform/xss13.html Normal file
View File

@ -0,0 +1,103 @@
<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';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10, curve: 'cardinal', htmlLabels: true
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier',actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize']
// themeVariables: {relationLabelColor: 'red'}
});
function callback(){alert('It worked');}
function xssAttack(){
const div = document.createElement('div')
div.id = 'the-malware'
div.className = 'malware'
div.innerHTML = 'XSS Succeeded'
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = "stateDiagram-v2\n"
diagram += "if_state --> False: if n < 0<img/src";
diagram += "='1'/onerror=xssAttack()>";
// var diagram = "stateDiagram-v2\n";
// diagram += "<img/src='1'/onerror"
// diagram += "=xssAttack()> --> B";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

16
dist/index.html vendored
View File

@ -21,6 +21,22 @@
<hr />
<div class="mermaid">
gantt
title Airworks roadmap
dateFormat YYYY-MM-DD
axisFormat %m-%d %a
excludes weekends, 2021-10-01,2021-10-04,2021-10-05,2021-10-06,2021-10-07
includes 2021-10-09
section Airworks 3.4.1
开发 :b, 2021-10-07, 5d
测试 :after b, 4d
OK :milestore
section Airworks 3.4.2
开发 :a, 2021-10-09, 4d
测试 :after a, 4d
</div>
<div class="mermaid">
gantt
title Exclusive end dates (Manual date should end on 3d)

35386
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

3
dist/mermaid.esm.min.mjs vendored Normal file

File diff suppressed because one or more lines are too long

32
dist/mermaid.esm.min.mjs.LICENSE.txt vendored Normal file
View File

@ -0,0 +1,32 @@
/*!
* Wait for document loaded before starting the execution
*/
/*! @license DOMPurify 2.3.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.3/LICENSE */
/*! Check if previously processed */
/*! sequence config was passed as #1 */
/**
* @license
* Copyright (c) 2012-2013 Chris Pettitt
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

226550
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

35
dist/mermaid.min.js vendored

File diff suppressed because one or more lines are too long

32
dist/mermaid.min.js.LICENSE.txt vendored Normal file
View File

@ -0,0 +1,32 @@
/*!
* Wait for document loaded before starting the execution
*/
/*! @license DOMPurify 2.3.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.3/LICENSE */
/*! Check if previously processed */
/*! sequence config was passed as #1 */
/**
* @license
* Copyright (c) 2012-2013 Chris Pettitt
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

File diff suppressed because one or more lines are too long

View File

@ -73,7 +73,7 @@ When deployed within code, init is called before the graph/diagram description.
```
**for example**:
```
```mmd
%%{init: {"theme": "default", "logLevel": 1 }}%%
graph LR
a-->b

View File

@ -24,7 +24,7 @@ Site-wide themes are still declared via `initialize` by site owners.
Example of `Initalize` call setting `theme` to `base`:
```js
```javascript
mermaidAPI.initialize({
'securityLevel': 'loose', 'theme': 'base'
});
@ -39,7 +39,7 @@ It is also possible to override site-wide theme settings locally, for a specific
**Following is an example:**
```
```mmd
%%{init: {'theme':'base'}}%%
graph TD
a --> b
@ -56,7 +56,7 @@ The easiest way to make a custom theme is to start with the base theme, and just
Here is an example of overriding `primaryColor` and giving everything a different look, using `%%init%%`.
```
```mmd
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ff0000'}}}%%
graph TD
A[Christmas] -->|Get money| B(Go shopping)

View File

@ -2,10 +2,10 @@
Configuration is the second half of Mermaid, after deployment. Together Deployment and Configuration constitute the whole of Mermaid.
This section will introduce the different methods of configuring of the behaviors and apperances of Mermaid Diagrams.
This section will introduce the different methods of configuring of the behaviors and appearances of Mermaid Diagrams.
The Following are the most commonly used methods, and are all tied to Mermaid [Deployment](./n00b-gettingStarted.md) methods.
## Configuration Section in the [Live Editor](./Live-Editor.md).
## Configuration Section in the [Live Editor](https://mermaid-js.github.io/mermaid-live-editor).
## The `initialize()` call, for when Mermaid is called via an API, or through a <script> tag.
@ -13,7 +13,7 @@ The Following are the most commonly used methods, and are all tied to Mermaid [D
## [Directives](./directives.md),
allows the limited reconfiguration of a diagram just before it is rendered. It can alter the font style, color and other aesthetic aspects of the diagram. you can pass a directive alongside your defintion inside `%%{ }%%`, either above or below your diagram defintion.
allows the limited reconfiguration of a diagram just before it is rendered. It can alter the font style, color and other aesthetic aspects of the diagram. you can pass a directive alongside your definition inside `%%{ }%%`, either above or below your diagram definition.
## Theme Creation:
An application of using Directives to change [Themes](./theming.md). `Theme` is an value within mermaid's configuration that dictates the color scheme for diagrams.

View File

@ -48,7 +48,7 @@ For a more detailed introduction to Mermaid and some of it's basic uses, refer t
### [Flowchart](./flowchart.md?id=flowcharts-basic-syntax)
```
```mmd
graph TD;
A-->B;
A-->C;
@ -60,7 +60,7 @@ graph TD;
### [Sequence diagram](./sequenceDiagram.md)
```
```mmd
sequenceDiagram
participant Alice
participant Bob
@ -78,7 +78,7 @@ sequenceDiagram
### [Gantt diagram](./gantt.md)
```
```mmd
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram to mermaid
@ -95,7 +95,7 @@ Future task2 : des4, after des3, 5d
### [Class diagram](./classDiagram.md)
```
```mmd
classDiagram
Class01 <|-- AveryLongClass : Cool
Class03 *-- Class04
@ -116,7 +116,7 @@ Class08 <--> C2: Cool label
### Git graph - :exclamation: experimental
```
```mmd
gitGraph:
options
{
@ -139,7 +139,7 @@ merge newbranch
### [Entity Relationship Diagram - :exclamation: experimental](./entityRelationshipDiagram.md)
```
```mmd
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
@ -151,7 +151,7 @@ erDiagram
### [User Journey Diagram](./user-journey.md)
```markdown
```mmd
journey
title My working day
section Go to work
@ -199,7 +199,7 @@ To Deploy Mermaid:
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>mermaid.initialize({startOnLoad:true});</script>
```
**Doing so will command the mermaid parser to look for the `<div>` tags with `class="mermaid"`. From these tags mermaid will try to read the diagram/chart definitons and render them into svg charts.**
**Doing so will command the mermaid parser to look for the `<div>` tags with `class="mermaid"`. From these tags mermaid will try to read the diagram/chart definitions and render them into svg charts.**
**Examples can be found at** [Other examples](/examples)
@ -229,19 +229,19 @@ Don't hesitate to contact me if you want to get involved!
### Setup
```
```sh
yarn install
```
### Build
```
```sh
yarn build:watch
```
### Lint
```
```sh
yarn lint
```
@ -250,7 +250,7 @@ We recommend you to install [editor plugins](https://eslint.org/docs/user-guide/
### Test
```
```sh
yarn test
```
Manual test in browser: open `dist/index.html`
@ -261,7 +261,7 @@ For those who have the permission to do so:
Update version number in `package.json`.
```
```sh
npm publish
```

File diff suppressed because it is too large Load Diff

View File

@ -7,32 +7,7 @@ The class diagram is the main building block of object-oriented modeling. It is
Mermaid can render class diagrams.
```
classDiagram
Animal <|-- Duck
Animal <|-- Fish
Animal <|-- Zebra
Animal : +int age
Animal : +String gender
Animal: +isMammal()
Animal: +mate()
class Duck{
+String beakColor
+swim()
+quack()
}
class Fish{
-int sizeInFeet
-canEat()
}
class Zebra{
+bool is_wild
+run()
}
```
```mermaid
```mermaid-example
classDiagram
Animal <|-- Duck
Animal <|-- Fish
@ -68,7 +43,7 @@ A single instance of a class in the diagram contains three compartments:
- The middle compartment contains the attributes of the class. They are left-aligned and the first letter is lowercase.
The bottom compartment contains the operations the class can execute. They are also left-aligned and the first letter is lowercase.
```
```mermaid-example
classDiagram
class BankAccount
BankAccount : +String owner
@ -78,15 +53,6 @@ classDiagram
```
```mermaid
classDiagram
class BankAccount
BankAccount : +String owner
BankAccount : +BigDecimal balance
BankAccount : +deposit(amount)
BankAccount : +withdrawl(amount)
```
## Define a class
There are two ways to define a class:
@ -94,13 +60,7 @@ There are two ways to define a class:
- Explicitly defining a class using keyword **class** like `class Animal`. This defines the Animal class
- Define two classes via a **relationship** between them `Vehicle <|-- Car`. This defines two classes Vehicle and Car along with their relationship.
```
classDiagram
class Animal
Vehicle <|-- Car
```
```mermaid
```mermaid-example
classDiagram
class Animal
Vehicle <|-- Car
@ -118,7 +78,8 @@ There are two ways to define the members of a class, and regardless of whichever
- Associate a member of a class using **:** (colon) followed by member name, useful to define one member at a time. For example:
```
```mermaid-example
classDiagram
class BankAccount
BankAccount : +String owner
BankAccount : +BigDecimal balance
@ -126,18 +87,10 @@ There are two ways to define the members of a class, and regardless of whichever
BankAccount : +withdrawal(amount)
```
```mermaid
classDiagram
class BankAccount
BankAccount : +String owner
BankAccount : +BigDecimal balance
BankAccount : +deposit(amount)
BankAccount : +withdrawl(amount)
```
- Associate members of a class using **{}** brackets, where members are grouped within curly brackets. Suitable for defining multiple members at once. For example:
```
```mermaid-example
classDiagram
class BankAccount{
+String owner
+BigDecimal balance
@ -146,22 +99,13 @@ class BankAccount{
}
```
```mermaid
classDiagram
class BankAccount{
+String owner
+BigDecimal balance
+deposit(amount)
+withdrawl(amount)
}
```
#### Return Type
Optionally you can end the method/function definition with the data type that will be returned (note: there must be a space between the final `)` of the method definition and return type
example:
```
```mermaid-example
classDiagram
class BankAccount{
+String owner
+BigDecimal balance
@ -170,37 +114,13 @@ class BankAccount{
}
```
```mermaid
classDiagram
class BankAccount{
+String owner
+BigDecimal balance
+deposit(amount) bool
+withdrawl(amount) int
}
```
#### Generic Types
Members can be defined using generic types, such as `List<int>`, for fields, parameters and return types by enclosing the type within `~` (**tilde**). Note: **nested** type declarations (such as `List<List<int>>`) are not currently supported
This can be done as part of either class definition method:
```
classDiagram
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~
```
```mermaid
```mermaid-example
classDiagram
class Square~Shape~{
int id
@ -257,20 +177,7 @@ There are different types of relations defined for classes under UML which are c
| ..\|> | Realization |
| .. | Link (Dashed) |
```
classDiagram
classA <|-- classB
classC *-- classD
classE o-- classF
classG <-- classH
classI -- classJ
classK <.. classL
classM <|.. classN
classO .. classP
```
```mermaid
```mermaid-example
classDiagram
classA <|-- classB
classC *-- classD
@ -285,7 +192,7 @@ classO .. classP
We can use the labels to describe nature of relation between two classes. Also, arrowheads can be used in opposite directions as well :
```
```mermaid-example
classDiagram
classA --|> classB : Inheritance
classC --* classD : Composition
@ -298,18 +205,6 @@ classO .. classP : Link(Dashed)
```
```mermaid
classDiagram
classA --|> classB : Inheritance
classC --* classD : Composition
classE --o classF : Aggregation
classG --> classH : Association
classI -- classJ : Link(Solid)
classK ..> classL : Dependency
classM ..|> classN : Realization
classO .. classP : Link(Dashed)
```
### Labels on Relations
It is possible to add a label text to a relation:
@ -318,25 +213,18 @@ It is possible to add a label text to a relation:
[classA][Arrow][ClassB]:LabelText
```
```
```mermaid-example
classDiagram
classA <|-- classB : implements
classC *-- classD : composition
classE o-- classF : association
```
```mermaid
classDiagram
classA <|-- classB : implements
classE o-- classF : association
```
### Two-way relations
Relations can go in multiple ways:
```
```mmd
classDiagram
Animal <|--|> Zebra
```
@ -388,14 +276,7 @@ Cardinality can be easily defined by placing cardinality text within quotes `"`
[classA] "cardinality1" [Arrow] "cardinality2" [ClassB]:LabelText
```
```
classDiagram
Customer "1" --> "*" Ticket
Student "1" --> "1..*" Course
Galaxy --> "many" Star : Contains
```
```mermaid
```mermaid-example
classDiagram
Customer "1" --> "*" Ticket
Student "1" --> "1..*" Course
@ -415,13 +296,7 @@ Annotations are defined within the opening `<<` and closing `>>`. There are two
- In a **_separate line_** after a class is defined. For example:
```
classDiagram
class Shape
<<interface>> Shape
```
```mermaid
```mermaid-example
classDiagram
class Shape
<<interface>> Shape
@ -431,7 +306,7 @@ Shape : draw()
- In a **_nested structure_** along with class definition. For example:
```
```mermaid-example
classDiagram
class Shape{
<<interface>>
@ -449,28 +324,11 @@ class Color{
```
```mermaid
classDiagram
class Shape{
<<interface>>
noOfVertices
draw()
}
class Color{
<<enumeration>>
RED
BLUE
GREEN
WHITE
BLACK
}
```
## Comments
Comments can be entered within a class diagram, 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 class diagram syntax
```
```mmd
classDiagram
%% This whole line is a comment classDiagram class Shape <<interface>>
class Shape{
@ -485,25 +343,7 @@ class Shape{
With class diagrams you can use the direction statement to set the direction which the diagram will render like in this example.
```
classDiagram
direction RL
class Student {
-idCard : IdCard
}
class IdCard{
-id : int
-name : string
}
class Bike{
-id : int
-name : string
}
Student "1" --o "1" IdCard : carries
Student "1" --o "1" Bike : rides
```
This is how this renders
```mermaid
```mermaid-example
classDiagram
direction RL
class Student {
@ -542,7 +382,7 @@ click className href "url" "tooltip"
_URL Link:_
```
```mmd
classDiagram
class Shape
link Shape "http://www.github.com" "This is a tooltip for a link"
@ -552,7 +392,7 @@ click Shape2 href "http://www.github.com" "This is a tooltip for a link"
_Callback:_
```
```mmd
classDiagram
class Shape
callback Shape "callbackFunction" "This is a tooltip for a callback"
@ -560,7 +400,7 @@ class Shape2
click Shape2 call callbackFunction() "This is a tooltip for a callback"
```
```
```html
<script>
var callbackFunction = function(){
alert('A callback was triggered');
@ -584,7 +424,7 @@ classDiagram
Beginners tip, a full example using interactive links in an html context:
```
```html
<body>
<div class="mermaid">
classDiagram
@ -658,14 +498,14 @@ It is also possible to attach a class to a list of nodes in one statement:
A shorter form of adding a class is to attach the classname to the node using the `:::` operator as per below:
```
```mmd
classDiagram
class Animal:::cssClass
```
Or:
```
```mmd
classDiagram
class Animal:::cssClass {
-int sizeInFeet

View File

@ -25,7 +25,7 @@ This means that **you should branch off your pull request from develop** and dir
We make all changes via Pull Requests. As we have many Pull Requests from developers new to mermaid, we have put in place a process, wherein *knsv, Knut Sveidqvist* is the primary reviewer of changes and merging pull requests. The process is as follows:
* Large changes reviewed by knsv or other developer asked to review by knsv
* Smaller, low-risk changes like dependecies, documentation, etc. can be merged by active collaborators
* Smaller, low-risk changes like dependencies, documentation, etc. can be merged by active collaborators
* Documentation (we encourage updates to the docs folder; you can submit them via direct commits)
When you commit code, create a branch with the following naming convention:
@ -78,7 +78,7 @@ When running in CI it will take a snapshot of the rendered diagram and compare i
This is what a rendering test looks like:
```
```js
it('should render forks and joins', () => {
imgSnapshotTest(
`

View File

@ -11,22 +11,14 @@ This statement declares the direction of the Flowchart.
This declares the graph is oriented from top to bottom (`TD` or `TB`).
```
graph TD
Start --> Stop
```
```mermaid
```mermaid-example
graph TD
Start --> Stop
```
This declares the graph is oriented from left to right (`LR`).
```
graph LR
Start --> Stop
```
```mermaid
```mermaid-example
graph LR
Start --> Stop
```
@ -55,12 +47,7 @@ Apart from the graph type, the syntax is the same. This is currently experimenta
### A node (default)
```
graph LR
id
```
```mermaid
```mermaid-example
graph LR
id
```
@ -73,11 +60,7 @@ It is also possible to set text in the box that differs from the id. If this is
found for the node that will be used. Also if you define edges for the node later on, you can omit text definitions. The
one previously defined will be used when rendering the box.
```
graph LR
id1[This is the text in the box]
```
```mermaid
```mermaid-example
graph LR
id1[This is the text in the box]
```
@ -86,66 +69,42 @@ graph LR
### A node with round edges
```
graph LR
id1(This is the text in the box)
```
```mermaid
```mermaid-example
graph LR
id1(This is the text in the box)
```
### A stadium-shaped node
```
graph LR
id1([This is the text in the box])
```
```mermaid
```mermaid-example
graph LR
id1([This is the text in the box])
```
### A node in a subroutine shape
```
graph LR
id1[[This is the text in the box]]
```
```mermaid
```mermaid-example
graph LR
id1[[This is the text in the box]]
```
### A node in a cylindrical shape
```
graph LR
id1[(Database)]
```
```mermaid
```mermaid-example
graph LR
id1[(Database)]
```
### A node in the form of a circle
```
graph LR
id1((This is the text in the circle))
```
```mermaid
```mermaid-example
graph LR
id1((This is the text in the circle))
```
### A node in an asymmetric shape
```
graph LR
id1>This is the text in the box]
```
```mermaid
```mermaid-example
graph LR
id1>This is the text in the box]
```
@ -153,69 +112,40 @@ Currently only the shape above is possible and not its mirror. *This might chang
### A node (rhombus)
```
graph LR
id1{This is the text in the box}
```
```mermaid
```mermaid-example
graph LR
id1{This is the text in the box}
```
### A hexagon node
{% raw %}
```
graph LR
id1{{This is the text in the box}}
```
{% endraw %}
```mermaid
{% raw %}
```mermaid-example
graph LR
id1{{This is the text in the box}}
{% endraw %}
```
### Parallelogram
```
```mermaid-example
graph TD
id1[/This is the text in the box/]
```
```mermaid
graph TD
id1[/This is the text in the box/]
```
### Parallelogram alt
```
graph TD
id1[\This is the text in the box\]
```
```mermaid
```mermaid-example
graph TD
id1[\This is the text in the box\]
```
### Trapezoid
```
graph TD
A[/Christmas\]
```
```mermaid
```mermaid-example
graph TD
A[/Christmas\]
```
### Trapezoid alt
```
graph TD
B[\Go shopping/]
```
```mermaid
```mermaid-example
graph TD
B[\Go shopping/]
```
@ -226,142 +156,90 @@ Nodes can be connected with links/edges. It is possible to have different types
### A link with arrow head
```
graph LR
A-->B
```
```mermaid
```mermaid-example
graph LR
A-->B
```
### An open link
```
graph LR
A --- B
```
```mermaid
```mermaid-example
graph LR
A --- B
```
### Text on links
```
```mermaid-example
graph LR
A-- This is the text! ---B
```
```mermaid
graph LR
A-- This is the text ---B
```
or
```
graph LR
A---|This is the text|B
```
```mermaid
```mermaid-example
graph LR
A---|This is the text|B
```
### A link with arrow head and text
```
graph LR
A-->|text|B
```
```mermaid
```mermaid-example
graph LR
A-->|text|B
```
or
```
graph LR
A-- text -->B
```
```mermaid
```mermaid-example
graph LR
A-- text -->B
```
### Dotted link
```
graph LR;
A-.->B;
```
```mermaid
```mermaid-example
graph LR;
A-.->B;
```
### Dotted link with text
```
graph LR
A-. text .-> B
```
```mermaid
```mermaid-example
graph LR
A-. text .-> B
```
### Thick link
```
graph LR
A ==> B
```
```mermaid
```mermaid-example
graph LR
A ==> B
```
### Thick link with text
```
graph LR
A == text ==> B
```
```mermaid
```mermaid-example
graph LR
A == text ==> B
```
### Chaining of links
It is possible declare many links in the same line as per below:
```
graph LR
A -- text --> B -- text2 --> C
```
```mermaid
It is possible to declare many links in the same line as per below:
```mermaid-example
graph LR
A -- text --> B -- text2 --> C
```
It is also possible to declare multiple nodes links in the same line as per below:
```
graph LR
a --> b & c--> d
```
```mermaid
```mermaid-example
graph LR
a --> b & c--> d
```
You can then describe dependencies in a very expressive way. Like the one-liner below:
```
graph TB
A & B--> C & D
```
```mermaid
```mermaid-example
graph TB
A & B--> C & D
```
@ -369,7 +247,7 @@ If you describe the same diagram using the the basic syntax, it will take four l
word of warning, one could go overboard with this making the graph harder to read in
markdown form. The Swedish word `lagom` comes to mind. It means, not too much and not too little.
This goes for expressive syntaxes as well.
```
```mmd
graph TB
A --> C
A --> D
@ -381,13 +259,7 @@ graph TB
When using flowchart instead of graph there are new types of arrows supported as per below:
```
flowchart LR
A --o B
B --x C
```
```mermaid
```mermaid-example
flowchart LR
A --o B
B --x C
@ -398,14 +270,7 @@ flowchart LR
When using flowchart instead of graph there is the possibility to use multidirectional arrows.
```
flowchart LR
A o--o B
B <--> C
C x--x D
```
```mermaid
```mermaid-example
flowchart LR
A o--o B
B <--> C
@ -423,16 +288,7 @@ 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
```mermaid-example
graph TD
A[Start] --> B{Is it?};
B -->|Yes| C[OK];
@ -448,7 +304,7 @@ 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:
```
```mermaid-example
graph TD
A[Start] --> B{Is it?};
B -- Yes --> C[OK];
@ -457,15 +313,6 @@ graph TD
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:
@ -482,11 +329,7 @@ as summed up in the following table:
It is possible to put text within quotes in order to render more troublesome characters. As in the example below:
```
graph LR
id1["This is the (text) in the box"]
```
```mermaid
```mermaid-example
graph LR
id1["This is the (text) in the box"]
```
@ -495,11 +338,7 @@ graph LR
It is possible to escape characters using the syntax exemplified here.
```
graph LR
A["A double quote:#quot;"] -->B["A dec char:#9829;"]
```
```mermaid
```mermaid-example
graph LR
A["A double quote:#quot;"] -->B["A dec char:#9829;"]
```
@ -514,20 +353,7 @@ end
An example below:
```
graph TB
c1-->a2
subgraph one
a1-->a2
end
subgraph two
b1-->b2
end
subgraph three
c1-->c2
end
```
```mermaid
```mermaid-example
graph TB
c1-->a2
subgraph one
@ -543,43 +369,19 @@ graph TB
You can also set an explicit id for the subgraph.
```
```mermaid-example
graph TB
c1-->a2
subgraph ide1 [one]
a1-->a2
end
```
```mermaid
graph TB
c1-->a2
subgraph id1 [one]
a1-->a2
end
```
## Beta: flowcharts
With the graphtype flowcharts it is also possible to set edges to and from subgraphs as in the graph below.
```
flowchart TB
c1-->a2
subgraph one
a1-->a2
end
subgraph two
b1-->b2
end
subgraph three
c1-->c2
end
one --> two
three --> two
two --> c2
```
```mermaid
```mermaid-example
flowchart TB
c1-->a2
subgraph one
@ -618,7 +420,9 @@ Examples of tooltip usage below:
</script>
```
```
The tooltip text is surrounded in double quotes. The styles of the tooltip are set by the class .mermaidTooltip.
```mermaid-example
graph LR;
A-->B;
B-->C;
@ -628,37 +432,12 @@ graph LR;
click A call callback() "Tooltip for a callback"
click B href "http://www.github.com" "This is a tooltip for a link"
```
The tooltip text is surrounded in double quotes. The styles of the tooltip are set by the class .mermaidTooltip.
```mermaid
graph LR
A-->B;
B-->C;
C-->D;
click A callback "Tooltip"
click B "http://www.github.com" "This is a link"
click C call callback() "Tooltip"
click D href "http://www.github.com" "This is a link"
```
> **Success** The tooltip functionality and the ability to link to urls are available from version 0.5.2.
?> Due to limitations with how Docsify handles JavaScript callback functions, an alternate working demo for the above code can be viewed at [this jsfiddle](https://jsfiddle.net/s37cjoau/3/).
Links are opened in the same browser tab/window by default. It is possible to change this by adding a link target to the click definition (`_self`, `_blank`, `_parent` and `_top` are supported):
```
graph LR;
A-->B;
B-->C;
C-->D;
D-->E;
click A "http://www.github.com" _blank
click B "http://www.github.com" "Open this in a new tab" _blank
click C href "http://www.github.com" _blank
click D href "http://www.github.com" "Open this in a new tab" _blank
```
```mermaid
```mermaid-example
graph LR;
A-->B;
B-->C;
@ -707,7 +486,7 @@ Beginners tip, a full example using interactive links in a html context:
Comments can be entered within a flow diagram, 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 flow syntax
```
```mmd
graph LR
%% this is a comment A -- text --> B{node}
A -- text --> B -- text2 --> C
@ -751,13 +530,7 @@ linkStyle default interpolate cardinal stroke:#ff3,stroke-width:4px,color:red;
It is possible to apply specific styles such as a thicker border or a different background color to a node.
```
graph LR
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
```
```mermaid
```mermaid-example
graph LR
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
@ -791,12 +564,7 @@ It is also possible to attach a class to a list of nodes in one statement:
A shorter form of adding a class is to attach the classname to the node using the `:::`operator as per below:
```
graph LR
A:::someclass --> B
classDef someclass fill:#f96;
```
```mermaid
```mermaid-example
graph LR
A:::someclass --> B
classDef someclass fill:#f96;
@ -822,13 +590,7 @@ below:
**Example definition**
```
graph LR;
A-->B[AAA<span>BBB</span>];
B-->D;
class A cssClass;
```
```mermaid
```mermaid-example
graph LR;
A-->B[AAA<span>BBB</span>];
B-->D;
@ -851,14 +613,7 @@ It is possible to add icons from fontawesome.
The icons are accessed via the syntax fa:#icon class name#.
```
graph TD
B["fa:fa-twitter for peace"]
B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner);
B-->E(A fa:fa-camera-retro perhaps?);
```
```mermaid
```mermaid-example
graph TD
B["fa:fa-twitter for peace"]
B-->C[fa:fa-ban forbidden]
@ -875,15 +630,7 @@ graph TD
Below is the new declaration of the graph edges which is also valid along with the old declaration of the graph edges.
```
graph LR
A[Hard edge] -->|Link text| B(Round edge)
B --> C{Decision}
C -->|One| D[Result one]
C -->|Two| E[Result two]
```
```mermaid
```mermaid-example
graph LR
A[Hard edge] -->|Link text| B(Round edge)
B --> C{Decision}

View File

@ -21,7 +21,7 @@ The json object that is passed as {**argument** } must be valid key value pairs
Valid Key Value pairs can be found in config.
The init/initialize directive is parsed earlier in the flow, this allows the incorporation of `%%init%%` directives into the mermaid diagram that is being rendered. Example:
```
```mmd
%%{init: { 'logLevel': 'debug', 'theme': 'dark' } }%%
graph >
A-->B
@ -31,7 +31,7 @@ will set the `logLevel` to `debug` and the `theme` to `dark` for a flowchart dia
Note: 'init' or 'initialize' are both acceptable as init directives. Also note that `%%init%%` and `%%initialize%%` directives will be grouped together after they are parsed. This means:
```
```mmd
%%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%%
%%{initialize: { 'logLevel': 'fatal', "theme":'dark', 'startOnLoad': true } }%%
...
@ -39,7 +39,7 @@ Note: 'init' or 'initialize' are both acceptable as init directives. Also note t
parsing the above generates the `%%init%%` object below, combining the two directives and carrying over the last value given for `loglevel`:
```
```json5
{
logLevel: 'fatal',
theme: 'dark',
@ -54,7 +54,7 @@ This will then be sent to `mermaid.initialize(...)` for rendering.
In this category are any directives that come after the graph type declaration. Essentially, these directives will only be processed after the init directive. Each individual graph type will handle these directives. As an example:
```
```mmd
%%{init: { 'logLevel': 'debug', 'theme': 'dark' } }%%
sequenceDiagram
%%{config: { 'fontFamily': 'Menlo', 'fontSize': 18, 'fontWeight': 400} }%%

View File

@ -7,14 +7,7 @@ Note that practitioners of ER modelling almost always refer to *entity types* si
Mermaid can render ER diagrams
```markdown
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
```
```mermaid
```mermaid-example
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
@ -27,27 +20,7 @@ Relationships between entities are represented by lines with end markers represe
ER diagrams can be used for various purposes, ranging from abstract logical models devoid of any implementation details, through to physical models of relational database tables. It can be useful to include attribute definitions on ER diagrams to aid comprehension of the purpose and meaning of entities. These do not necessarily need to be exhaustive; often a small subset of attributes is enough. Mermaid allows to be defined in terms of their *type* and *name*.
```markdown
erDiagram
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
```
```mermaid
```mermaid-example
erDiagram
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
@ -75,7 +48,7 @@ When including attributes on ER diagrams, you must decide whether to include for
Mermaid syntax for ER diagrams is compatible with PlantUML, with an extension to label the relationship. Each statement consists of the following parts:
```markdown
```
<first-entity> [<relationship> <second-entity> : <relationship-label>]
```
@ -88,7 +61,7 @@ Where:
For example:
```markdown
```
PROPERTY ||--|{ ROOM : contains
```
@ -117,7 +90,8 @@ 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:
```
```mmd
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
PERSON ||--o{ NAMED-DRIVER : is
```
@ -126,22 +100,7 @@ Relationships may be classified as either *identifying* or *non-identifying* and
Attributes can be defined for entities by specifying the entity name followed by a block containing multiple `type name` pairs, where a block is delimited by an opening `{` and a closing `}`. For example:
```
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber
string make
string model
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string firstName
string lastName
int age
}
```
```mermaid
```mermaid-example
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
@ -158,22 +117,7 @@ erDiagram
```
The attributes are rendered inside the entity boxes:
```
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber
string make
string model
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string firstName
string lastName
int age
}
```
```mermaid
```mermaid-example
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
@ -195,7 +139,7 @@ The `type` and `name` values must begin with an alphabetic character and may con
Attributes may also have a `key` or comment defined. Keys can be "PK" or "FK", for Primary Key or Foreign Key. And a `comment` is defined by quotes at the end of an attribute. Comments themselves cannot have quote characters in them.
```mermaid
```mermaid-example
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {

View File

@ -8,23 +8,12 @@ This page contains a collection of examples of diagrams and charts that can be c
## Basic Pie Chart
```
```mermaid-example
pie title NETFLIX
"Time spent looking for movie" : 90
"Time spent watching it" : 10
```
```mermaid
pie title NETFLIX
"Time spent looking for movie" : 90
"Time spent watching it" : 10
```
```
pie title What Voldemort doesn't have?
"FRIENDS" : 2
"FAMILY" : 3
"NOSE" : 45
```
```mermaid
```mermaid-example
pie title What Voldemort doesn't have?
"FRIENDS" : 2
"FAMILY" : 3
@ -32,18 +21,7 @@ pie title What Voldemort doesn't have?
```
## Basic sequence diagram
```
sequenceDiagram
Alice ->> Bob: Hello Bob, how are you?
Bob-->>John: How about you John?
Bob--x Alice: I am good thanks!
Bob-x John: I am good thanks!
Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
Bob-->Alice: Checking with John...
Alice->John: Yes... John, how are you?
```
```mermaid
```mermaid-example
sequenceDiagram
Alice ->> Bob: Hello Bob, how are you?
Bob-->>John: How about you John?
@ -57,14 +35,7 @@ sequenceDiagram
## Basic flowchart
```
graph LR
A[Square Rect] -- Link text --> B((Circle))
A --> C(Round Rect)
B --> D{Rhombus}
C --> D
```
```mermaid
```mermaid-example
graph LR
A[Square Rect] -- Link text --> B((Circle))
A --> C(Round Rect)
@ -75,30 +46,7 @@ graph LR
## Larger flowchart with some styling
```
graph TB
sq[Square shape] --> ci((Circle shape))
subgraph A
od>Odd shape]-- Two line<br/>edge comment --> ro
di{Diamond with <br/> line break} -.-> ro(Rounded<br>square<br>shape)
di==>ro2(Rounded square shape)
end
%% Notice that no text in shape are added here instead that is appended further down
e --> od3>Really long text with linebreak<br>in an Odd shape]
%% Comments after double percent signs
e((Inner / circle<br>and some odd <br>special characters)) --> f(,.?!+-*ز)
cyr[Cyrillic]-->cyr2((Circle shape Начало));
classDef green fill:#9f6,stroke:#333,stroke-width:2px;
classDef orange fill:#f96,stroke:#333,stroke-width:4px;
class sq,e green
class di orange
```
```mermaid
```mermaid-example
graph TB
sq[Square shape] --> ci((Circle shape))
@ -125,22 +73,7 @@ graph TB
## SequenceDiagram: Loops, alt and opt
```
sequenceDiagram
loop Daily query
Alice->>Bob: Hello Bob, how are you?
alt is sick
Bob->>Alice: Not so good :(
else is well
Bob->>Alice: Feeling fresh like a daisy
end
opt Extra response
Bob->>Alice: Thanks for asking
end
end
```
```mermaid
```mermaid-example
sequenceDiagram
loop Daily query
Alice->>Bob: Hello Bob, how are you?
@ -159,20 +92,7 @@ sequenceDiagram
## SequenceDiagram: Message to self in loop
```
sequenceDiagram
participant Alice
participant Bob
Alice->>John: Hello John, how are you?
loop Healthcheck
John->>John: Fight against hypochondria
end
Note right of John: Rational thoughts<br/>prevail...
John-->>Alice: Great!
John->>Bob: How about you?
Bob-->>John: Jolly good!
```
```mermaid
```mermaid-example
sequenceDiagram
participant Alice
participant Bob

View File

@ -10,12 +10,7 @@ It can also accomodate different arrow types, multi directional arrows, and link
Node
### A node (default)
```
flowchart LR
id
```
```mermaid
```mermaid-example
flowchart LR
id
```
@ -28,11 +23,7 @@ It is also possible to set text in the box that differs from the id. If this is
found for the node that will be used. Also if you define edges for the node later on, you can omit text definitions. The
one previously defined will be used when rendering the box.
```
flowchart LR
id1[This is the text in the box]
```
```mermaid
```mermaid-example
flowchart LR
id1[This is the text in the box]
```
@ -43,22 +34,14 @@ This statement declares the direction of the Flowchart.
This declares the flowchart is oriented from top to bottom (`TD` or `TB`).
```
flowchart TD
Start --> Stop
```
```mermaid
```mermaid-example
flowchart TD
Start --> Stop
```
This declares the flowchart is oriented from left to right (`LR`).
```
flowchart LR
Start --> Stop
```
```mermaid
```mermaid-example
flowchart LR
Start --> Stop
```
@ -77,66 +60,42 @@ Possible FlowChart orientations are:
### A node with round edges
```
flowchart LR
id1(This is the text in the box)
```
```mermaid
```mermaid-example
flowchart LR
id1(This is the text in the box)
```
### A stadium-shaped node
```
flowchart LR
id1([This is the text in the box])
```
```mermaid
```mermaid-example
flowchart LR
id1([This is the text in the box])
```
### A node in a subroutine shape
```
flowchart LR
id1[[This is the text in the box]]
```
```mermaid
```mermaid-example
flowchart LR
id1[[This is the text in the box]]
```
### A node in a cylindrical shape
```
flowchart LR
id1[(Database)]
```
```mermaid
```mermaid-example
flowchart LR
id1[(Database)]
```
### A node in the form of a circle
```
flowchart LR
id1((This is the text in the circle))
```
```mermaid
```mermaid-example
flowchart LR
id1((This is the text in the circle))
```
### A node in an asymmetric shape
```
flowchart LR
id1>This is the text in the box]
```
```mermaid
```mermaid-example
flowchart LR
id1>This is the text in the box]
```
@ -144,65 +103,40 @@ Currently only the shape above is possible and not its mirror. *This might chang
### A node (rhombus)
```
flowchart LR
id1{This is the text in the box}
```
```mermaid
```mermaid-example
flowchart LR
id1{This is the text in the box}
```
### A hexagon node
```
flowchart LR
id1{{This is the text in the box}}
```
```mermaid
```mermaid-example
flowchart LR
id1{{This is the text in the box}}
```
### Parallelogram
```
flowchart TD
id1[/This is the text in the box/]
```
```mermaid
```mermaid-example
flowchart TD
id1[/This is the text in the box/]
```
### Parallelogram alt
```
flowchart TD
id1[\This is the text in the box\]
```
```mermaid
```mermaid-example
flowchart TD
id1[\This is the text in the box\]
```
### Trapezoid
```
flowchart TD
A[/Christmas\]
```
```mermaid
```mermaid-example
flowchart TD
A[/Christmas\]
```
### Trapezoid alt
```
flowchart TD
B[\Go shopping/]
```
```mermaid
```mermaid-example
flowchart TD
B[\Go shopping/]
```
@ -213,110 +147,70 @@ Nodes can be connected with links/edges. It is possible to have different types
### A link with arrow head
```
flowchart LR
A-->B
```
```mermaid
```mermaid-example
flowchart LR
A-->B
```
### An open link
```
flowchart LR
A --- B
```
```mermaid
```mermaid-example
flowchart LR
A --- B
```
### Text on links
```
```mermaid-example
flowchart LR
A-- This is the text! ---B
```
```mermaid
flowchart LR
A-- This is the text ---B
```
or
```
flowchart LR
A---|This is the text|B
```
```mermaid
```mermaid-example
flowchart LR
A---|This is the text|B
```
### A link with arrow head and text
```
flowchart LR
A-->|text|B
```
```mermaid
```mermaid-example
flowchart LR
A-->|text|B
```
or
```
flowchart LR
A-- text -->B
```
```mermaid
```mermaid-example
flowchart LR
A-- text -->B
```
### Dotted link
```
flowchart LR;
A-.->B;
```
```mermaid
```mermaid-example
flowchart LR;
A-.->B;
```
### Dotted link with text
```
flowchart LR
A-. text .-> B
```
```mermaid
```mermaid-example
flowchart LR
A-. text .-> B
```
### Thick link
```
flowchart LR
A ==> B
```
```mermaid
```mermaid-example
flowchart LR
A ==> B
```
### Thick link with text
```
flowchart LR
A == text ==> B
```
```mermaid
```mermaid-example
flowchart LR
A == text ==> B
```
@ -324,31 +218,19 @@ flowchart LR
### Chaining of links
It is possible declare many links in the same line as per below:
```
flowchart LR
A -- text --> B -- text2 --> C
```
```mermaid
```mermaid-example
flowchart LR
A -- text --> B -- text2 --> C
```
It is also possible to declare multiple nodes links in the same line as per below:
```
flowchart LR
a --> b & c--> d
```
```mermaid
```mermaid-example
flowchart LR
a --> b & c--> d
```
You can then describe dependencies in a very expressive way. Like the one-liner below:
```
flowchart TB
A & B--> C & D
```
```mermaid
```mermaid-example
flowchart TB
A & B--> C & D
```
@ -356,7 +238,7 @@ If you describe the same diagram using the the basic syntax, it will take four l
word of warning, one could go overboard with this making the flowchart harder to read in
markdown form. The Swedish word `lagom` comes to mind. It means, not too much and not too little.
This goes for expressive syntaxes as well.
```
```mmd
flowchart TB
A --> C
A --> D
@ -368,13 +250,7 @@ flowchart TB
There are new types of arrows supported as per below:
```
flowchart LR
A --o B
B --x C
```
```mermaid
```mermaid-example
flowchart LR
A --o B
B --x C
@ -385,14 +261,7 @@ flowchart LR
There is the possibility to use multidirectional arrows.
```
flowchart LR
A o--o B
B <--> C
C x--x D
```
```mermaid
```mermaid-example
flowchart LR
A o--o B
B <--> C
@ -410,16 +279,7 @@ 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:
```
flowchart TD
A[Start] --> B{Is it?};
B -->|Yes| C[OK];
C --> D[Rethink];
D --> B;
B ---->|No| E[End];
```
```mermaid
```mermaid-example
flowchart TD
A[Start] --> B{Is it?};
B -->|Yes| C[OK];
@ -435,7 +295,7 @@ 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:
```
```mermaid-example
flowchart TD
A[Start] --> B{Is it?};
B -- Yes --> C[OK];
@ -444,15 +304,6 @@ flowchart TD
B -- No ----> E[End];
```
```mermaid
flowchart 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:
@ -469,11 +320,7 @@ as summed up in the following table:
It is possible to put text within quotes in order to render more troublesome characters. As in the example below:
```
flowchart LR
id1["This is the (text) in the box"]
```
```mermaid
```mermaid-example
flowchart LR
id1["This is the (text) in the box"]
```
@ -482,11 +329,7 @@ flowchart LR
It is possible to escape characters using the syntax exemplified here.
```
flowchart LR
A["A double quote:#quot;"] -->B["A dec char:#9829;"]
```
```mermaid
```mermaid-example
flowchart LR
A["A double quote:#quot;"] -->B["A dec char:#9829;"]
```
@ -503,20 +346,7 @@ end
An example below:
```
flowchart TB
c1-->a2
subgraph one
a1-->a2
end
subgraph two
b1-->b2
end
subgraph three
c1-->c2
end
```
```mermaid
```mermaid-example
flowchart TB
c1-->a2
subgraph one
@ -532,43 +362,19 @@ flowchart TB
You can also set an explicit id for the subgraph.
```
```mermaid-example
flowchart TB
c1-->a2
subgraph ide1 [one]
a1-->a2
end
```
```mermaid
flowchart TB
c1-->a2
subgraph id1 [one]
a1-->a2
end
```
## Beta: flowcharts
With the graphtype flowcharts it is also possible to set edges to and from subgraphs as in the flowchart below.
```
flowchart TB
c1-->a2
subgraph one
a1-->a2
end
subgraph two
b1-->b2
end
subgraph three
c1-->c2
end
one --> two
three --> two
two --> c2
```
```mermaid
```mermaid-example
flowchart TB
c1-->a2
subgraph one
@ -589,7 +395,7 @@ flowchart TB
With the graphtype flowcharts you can use the direction statement to set the direction which the subgraph will render like in this example.
```
```mermaid-example
flowchart LR
subgraph TOP
direction TB
@ -606,24 +412,6 @@ flowchart LR
B1 --> B2
```
```mermaid
flowchart LR
subgraph TOP
direction TB
subgraph B1
direction RL
i1 -->f1
end
subgraph B2
direction BT
i2 -->f2
end
end
A --> TOP --> B
B1 --> B2
```
## Interaction
It is possible to bind a click event to a node, the click can lead to either a javascript callback or to a link which will be opened in a new browser tab. **Note**: This functionality is disabled when using `securityLevel='strict'` and enabled when using `securityLevel='loose'`.
@ -646,7 +434,9 @@ Examples of tooltip usage below:
</script>
```
```
The tooltip text is surrounded in double quotes. The styles of the tooltip are set by the class `.mermaidTooltip`.
```mermaid-example
flowchart LR;
A-->B;
B-->C;
@ -657,36 +447,12 @@ flowchart LR;
click B href "http://www.github.com" "This is a tooltip for a link"
```
The tooltip text is surrounded in double quotes. The styles of the tooltip are set by the class .mermaidTooltip.
```mermaid
flowchart LR
A-->B;
B-->C;
C-->D;
click A callback "Tooltip"
click B "http://www.github.com" "This is a link"
click C call callback() "Tooltip"
click D href "http://www.github.com" "This is a link"
```
> **Success** The tooltip functionality and the ability to link to urls are available from version 0.5.2.
?> Due to limitations with how Docsify handles JavaScript callback functions, an alternate working demo for the above code can be viewed at [this jsfiddle](https://jsfiddle.net/s37cjoau/3/).
Links are opened in the same browser tab/window by default. It is possible to change this by adding a link target to the click definition (`_self`, `_blank`, `_parent` and `_top` are supported):
```
flowchart LR;
A-->B;
B-->C;
C-->D;
D-->E;
click A "http://www.github.com" _blank
click B "http://www.github.com" "Open this in a new tab" _blank
click C href "http://www.github.com" _blank
click D href "http://www.github.com" "Open this in a new tab" _blank
```
```mermaid
```mermaid-example
flowchart LR;
A-->B;
B-->C;
@ -735,7 +501,7 @@ Beginners tip, a full example using interactive links in a html context:
Comments can be entered within a flow diagram, 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 flow syntax
```
```mmd
flowchart LR
%% this is a comment A -- text --> B{node}
A -- text --> B -- text2 --> C
@ -759,13 +525,7 @@ linkStyle 3 stroke:#ff3,stroke-width:4px,color:red;
It is possible to apply specific styles such as a thicker border or a different background color to a node.
```
flowchart LR
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
```
```mermaid
```mermaid-example
flowchart LR
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
@ -799,12 +559,7 @@ It is also possible to attach a class to a list of nodes in one statement:
A shorter form of adding a class is to attach the classname to the node using the `:::`operator as per below:
```
flowchart LR
A:::someclass --> B
classDef someclass fill:#f96;
```
```mermaid
```mermaid-example
flowchart LR
A:::someclass --> B
classDef someclass fill:#f96;
@ -830,13 +585,7 @@ below:
**Example definition**
```
flowchart LR;
A-->B[AAA<span>BBB</span>];
B-->D;
class A cssClass;
```
```mermaid
```mermaid-example
flowchart LR;
A-->B[AAA<span>BBB</span>];
B-->D;
@ -859,14 +608,7 @@ It is possible to add icons from fontawesome.
The icons are accessed via the syntax fa:#icon class name#.
```
flowchart TD
B["fa:fa-twitter for peace"]
B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner);
B-->E(A fa:fa-camera-retro perhaps?);
```
```mermaid
```mermaid-example
flowchart TD
B["fa:fa-twitter for peace"]
B-->C[fa:fa-ban forbidden]
@ -883,15 +625,7 @@ flowchart TD
Below is the new declaration of the graph edges which is also valid along with the old declaration of the graph edges.
```
flowchart LR
A[Hard edge] -->|Link text| B(Round edge)
B --> C{Decision}
C -->|One| D[Result one]
C -->|Two| E[Result two]
```
```mermaid
```mermaid-example
flowchart LR
A[Hard edge] -->|Link text| B(Round edge)
B --> C{Decision}

View File

@ -17,18 +17,7 @@
Mermaid can render Gantt diagrams as SVG, PNG or a MarkDown link that can be pasted into docs.
```
gantt
title A Gantt Diagram
dateFormat YYYY-MM-DD
section Section
A task :a1, 2014-01-01, 30d
Another task :after a1 , 20d
section Another
Task in sec :2014-01-12 , 12d
another task : 24d
```
```mermaid
```mermaid-example
gantt
title A Gantt Diagram
dateFormat YYYY-MM-DD
@ -41,39 +30,7 @@ gantt
```
## Syntax
```
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
excludes weekends
%% (`excludes` accepts specific dates in YYYY-MM-DD format, days of the week ("sunday") or "weekends", but not the word "weekdays".)
section A section
Completed task :done, des1, 2014-01-06,2014-01-08
Active task :active, des2, 2014-01-09, 3d
Future task : des3, after des2, 5d
Future task2 : des4, after des3, 5d
section Critical tasks
Completed task in the critical line :crit, done, 2014-01-06,24h
Implement parser and jison :crit, done, after des1, 2d
Create tests for parser :crit, active, 3d
Future task in critical line :crit, 5d
Create tests for renderer :2d
Add to mermaid :1d
functionality added :milestone
section Documentation
Describe gantt syntax :active, a1, after des1, 3d
Add gantt diagram to demo page :after a1 , 20h
Add another diagram to demo page :doc1, after a1 , 48h
section Last section
Describe gantt syntax :after doc1, 3d
Add gantt diagram to demo page :20h
Add another diagram to demo page :48h
```
```mermaid
```mermaid-example
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
@ -93,6 +50,7 @@ gantt
Future task in critical line :crit, 5d
Create tests for renderer :2d
Add to mermaid :1d
Functionality added :milestone, 2014-01-25, 0d
section Documentation
Describe gantt syntax :active, a1, after des1, 3d
@ -106,13 +64,7 @@ gantt
```
It is possible to set multiple dependencies separated by space:
```
gantt
apple :a, 2017-07-20, 1w
banana :crit, b, 2017-07-23, 1d
cherry :active, c, after b a, 1d
```
```
```mermaid-example
gantt
apple :a, 2017-07-20, 1w
banana :crit, b, 2017-07-23, 1d
@ -133,7 +85,17 @@ To do so, start a line with the `section` keyword and give it a name. (Note that
### Milestones
You can add milestones to the diagrams. Milestones differ from tasks as they represent a signle instant in time and are identifiedd by the keyword `milestone`
You can add milestones to the diagrams. Milestones differ from tasks as they represent a single instant in time and are identified by the keyword `milestone`. Below is an example on how to use milestones. As you may notice, the exact location of the milestone is determined by the initial date for the milestone and the "duration" of the task this way: *initial date*+*duration*/2.
```mermaid-example
gantt
dateFormat HH:mm
axisFormat %H:%M
Initial milestone : milestone, m1, 17:49,2min
taska2 : 10min
taska3 : 5min
Final milestone : milestone, m2, 18:14, 2min
```
## Setting dates
@ -219,7 +181,7 @@ More info in: https://github.com/mbostock/d3/wiki/Time-Formatting
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
title A Gantt Diagram
%% this is a comment

View File

@ -22,6 +22,12 @@
}
</script>
<script>var require = { paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs' } }</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs/loader.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs/editor/editor.main.nls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs/editor/editor.main.js"></script>
<script>exports = {};</script>
<script src="https://unpkg.com/monaco-mermaid/browser.js"></script>
<style>
.markdown-section {
@ -32,6 +38,27 @@
<body>
<div id="app"></div>
<script>
var initEditor = exports.default;
var parser = new DOMParser();
var currentCodeExample = 0;
var colorize = [];
function colorizeEverything(html) {
initEditor(monaco)
return new Promise((resolve, reject) => {
monaco.editor.setTheme('mermaid')
var parsed = parser.parseFromString(html, 'text/html').body
Promise.all([...parsed.querySelectorAll('pre[id*="code"]')].map(codeBlock => monaco.editor.colorize(codeBlock.innerText, 'mermaid'))).then(result => {
parsed.querySelectorAll('pre[id*="code"]').forEach((codeBlock, index) => codeBlock.innerHTML = result[index])
resolve(parsed.innerHTML)
})
})
}
function escapeHTML(html) {
return html.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll('\'', '&apos;')
}
window.$docsify = {
search: 'auto',
name: 'mermaid',
@ -43,10 +70,26 @@
markdown: {
renderer: {
code: function(code, lang) {
if (lang === "mermaid") {
return (
'<div class="mermaid">' + mermaid.render('mermaid-svg-' + num++, code) + "</div>"
);
if (lang.startsWith('mermaid') || lang === 'mmd') {
var resultingHTML = '';
if (lang === "mmd" || lang === 'mermaid-example') {
currentCodeExample++;
colorize.push(currentCodeExample);
resultingHTML += (
'<pre id="code' + currentCodeExample + '">' + escapeHTML(code) + '</pre>'
)
}
if (lang === 'mermaid' || lang === 'mermaid-example') {
resultingHTML += (
'<div class="mermaid">' + mermaid.render('mermaid-svg-' + num++, code) + "</div>"
);
}
if (resultingHTML !== '') {
return resultingHTML;
}
}
return this.origin.code.apply(this, arguments);
}
@ -59,6 +102,15 @@
var editHtml = '[:memo: Edit this Page](' + url + ')\n'
return editHtml + html
})
hook.afterEach(function (html, next) {
next(html);
(async() => {
while (!window.hasOwnProperty("monaco"))
await new Promise(resolve => setTimeout(resolve, 1000));
colorizeEverything(html).then(newHTML => document.querySelector('article.markdown-section').innerHTML = newHTML)
})();
})
}
]
}

View File

@ -12,7 +12,7 @@ They also serve as proof of concept, for the variety of things that can be built
- [Tuleap](https://docs.tuleap.org/user-guide/writing-in-tuleap.html#graphs) (**Native support**)
- [Joplin](https://joplinapp.org) (**Native support**)
- [GitHub](https://github.com)
- [Github action: Compile mermaid to image](https://github.com/neenjaw/compile-mermaid-markdown-action)
- [GitHub action: Compile mermaid to image](https://github.com/neenjaw/compile-mermaid-markdown-action)
- [svg-generator](https://github.com/SimonKenyonShepard/mermaidjs-github-svg-generator)
- [GitBook](http://gitbook.com)
- [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid)
@ -37,7 +37,7 @@ They also serve as proof of concept, for the variety of things that can be built
- [WordPress Markdown Editor](https://wordpress.org/plugins/wp-githuber-md)
- [WP-ReliableMD](https://wordpress.org/plugins/wp-reliablemd/)
- [Hexo](https://hexo.io)
- [hexo-filter-mermid-diagrams](https://github.com/webappdevelp/hexo-filter-mermaid-diagrams)
- [hexo-filter-mermaid-diagrams](https://github.com/webappdevelp/hexo-filter-mermaid-diagrams)
- [hexo-tag-mermaid](https://github.com/JameChou/hexo-tag-mermaid)
- [hexo-mermaid-diagrams](https://github.com/mslxl/hexo-mermaid-diagrams)
@ -107,6 +107,9 @@ They also serve as proof of concept, for the variety of things that can be built
- [Inkdrop](http://inkdrop.app) - [Plugin](https://github.com/inkdropapp/inkdrop-mermaid)
- [Vim](https://vim.org)
- [Vim Diagram Syntax](https://github.com/zhaozg/vim-diagram)
- [GNU Emacs](https://www.gnu.org/software/emacs/)
- [Major mode for .mmd files](https://github.com/abrochard/mermaid-mode)
- [Org-Mode integration](https://github.com/arnm/ob-mermaid)
- [Brackets](http://brackets.io/)
- [Mermaid Preview](https://s3.amazonaws.com/extend.brackets/alanhohn.mermaid-preview/alanhohn.mermaid-preview-1.0.2.zip)
- [Iodide](https://github.com/iodide-project/iodide)
@ -136,7 +139,6 @@ They also serve as proof of concept, for the variety of things that can be built
## Browser Extensions
## Browser Extensions
| Name | Chrome Web Store | Firefox Add-ons | Opera | Edge | Source/Repository |
| -- | -- | -- | -- | -- | -- |
| GitHub + Mermaid | [🎡🔗](https://chrome.google.com/webstore/detail/github-%20-mermaid/goiiopgdnkogdbjmncgedmgpoajilohe) | [🦊🔗](https://addons.mozilla.org/firefox/addon/github-mermaid/) | - | - | [🐙🔗](https://github.com/BackMarket/github-mermaid-extension)
@ -149,6 +151,7 @@ They also serve as proof of concept, for the variety of things that can be built
| Mermaid Diagrams | [🎡🔗](https://chrome.google.com/webstore/detail/mermaid-diagrams/phfcghedmopjadpojhmmaffjmfiakfil) | - | - | - | - |
|Mermaid Markdown | [🎡🔗](https://chrome.google.com/webstore/detail/mermaid-markdown/mboeoikjijmjcjgpccghbcoegikliijg) | - | - | - | - |
| Monkeys | [🎡🔗](https://chrome.google.com/webstore/detail/monkeys-mermaid-for-githu/cplfdpoajbclbgphaphphcldamfkjlgi) | - | - | - | - |
| Mermaid Previewer | [🎡🔗](https://chrome.google.com/webstore/detail/mermaid-previewer/oidjnlhbegipkcklbdfnbkikplpghfdl) | - | - | - | - |
## Other

View File

@ -53,7 +53,7 @@ It is a relatively straightforward solution to a significant hurdle with the sof
**Diagramming and charting is a large waste of developer's time, but not having diagrams ruins productivity.**
Mermaid solves this by reducing the timeand effort required to create diagrams and charts.
Mermaid solves this by reducing the time and effort required to create diagrams and charts.
Because, the text base for the diagrams allows it to be updated easily. Also, it can be made part of production scripts (and other pieces of code). So less time is spent on documenting, as a separate task.

View File

@ -10,18 +10,7 @@ One would notice that all **Diagrams definitions begin** with a declaration of t
**Example** : The code below is for an Entity Relationship Diagram, specified by the `erDiagram` declaration. What follows is the definition of the different `Entities` represented in it.
```
erDiagram
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
CUSTOMER ||--o{ ORDER : places
CUSTOMER ||--o{ INVOICE : "liable for"
DELIVERY-ADDRESS ||--o{ ORDER : receives
INVOICE ||--|{ ORDER : covers
ORDER ||--|{ ORDER-ITEM : includes
PRODUCT-CATEGORY ||--|{ PRODUCT : contains
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
```
```mermaid
```mermaid-example
erDiagram
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
CUSTOMER ||--o{ ORDER : places
@ -62,9 +51,10 @@ Configuration is the third part of Mermaid, after deployment and syntax. It deal
If you are interested in altering and customizing your Mermaid Diagrams, you will find the methods and values available for [Configuration](./Setup.md) here. It includes themes.
This section will introduce the different methods of configuring the behaviors and appearances of Mermaid Diagrams.
The following are the most commonly used methods, and they are all tied to Mermaid [Deployment](./n00b-gettingStarted.md) methods.
The following are the most commonly used methods, and they are all tied to Mermaid [Deployment](./n00b-gettingStarted.md) methods.
### Configuration Section in the [Live Editor](https://mermaid-js.github.io/mermaid-live-editor).
### Configuration Section in the [Live Editor](./Live-Editor.md).
Here you can edit certain values to change the behavior and appearance of the diagram.
### [The initialize() call](https://mermaid-js.github.io/mermaid/#/n00b-gettingStarted?id=_3-calling-the-javascript-api),
@ -72,7 +62,7 @@ Used when Mermaid is called via an API, or through a `<script>` tag.
### [Directives](./directives.md),
Allows for the limited reconfiguration of a diagram just before it is rendered. It can alter the font style, color and other aesthetic aspects of the diagram. You can pass a directive alongside your defintion inside `%%{ }%%`. It can be done either above or below your diagram definition.
Allows for the limited reconfiguration of a diagram just before it is rendered. It can alter the font style, color and other aesthetic aspects of the diagram. You can pass a directive alongside your definition inside `%%{ }%%`. It can be done either above or below your diagram definition.
### [Theme Manipulation](./theming.md):
An application of using Directives to change [Themes](./theming.md). `Theme` is a value within Mermaid's configuration that dictates the color scheme for diagrams.

View File

@ -17,7 +17,7 @@ For instance:
There are some jison specific sub steps here where the parser stores the data encountered when parsing the diagram, this data is later used by the renderer. You can during the parsing call a object provided to the parser by the user of the parser. This object can be called during parsing for storing data.
```
```jison
statement
: 'participant' actor { $$='actor'; }
| signal { $$='signal'; }

View File

@ -5,18 +5,12 @@
Mermaid can render Pie Chart diagrams.
```
```mermaid-example
pie title Pets adopted by volunteers
"Dogs" : 386
"Cats" : 85
"Rats" : 15
```
```mermaid
pie title Pets adopted by volunteers
"Dogs" : 386
"Cats" : 85
"Rats" : 35
```
## Syntax
@ -37,7 +31,7 @@ Drawing a pie chart is really simple in mermaid.
.
## Example
```
```mermaid-example
pie
title Key elements in Product X
"Calcium" : 42.96
@ -45,11 +39,3 @@ pie
"Magnesium" : 10.01
"Iron" : 5
```
```mermaid
pie
title Key elements in Product X
"Calcium" : 42.96
"Potassium" : 50.05
"Magnesium" : 25.01
"Iron" : 15
```

View File

@ -6,24 +6,7 @@
Rendering requirements is straightforward.
```
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
element test_entity {
type: simulation
}
test_entity - satisfies -> test_req
```
```mermaid
```mermaid-example
requirementDiagram
requirement test_req {
@ -44,7 +27,7 @@ Rendering requirements is straightforward.
There are three types of components to a requirement diagram: requirement, element, and relationship.
The grammar for defining each is defined below. Words denoted in angule brackets, such as ```<word>```, are enumerated keywords that have options elaborated in a table. ```user_defined_...``` is use in any place where user input is expected.
The grammar for defining each is defined below. Words denoted in angle brackets, such as ```<word>```, are enumerated keywords that have options elaborated in a table. ```user_defined_...``` is use in any place where user input is expected.
An important note on user text: all input can be surrounded in quotes or not. For example, both ```Id: "here is an example"``` and ```Id: here is an example``` are both valid. However, users must be careful with unquoted input. The parser will fail if another keyword is detected.
@ -66,7 +49,7 @@ Type, risk, and method are enumerations defined in SysML.
|---|---|
| Type | requirement, functionalRequirement, interfaceRequirement, performanceRequirement, physicalRequirement, designConstraint |
| Risk | Low, Medium, High |
| VerifcationMethod | Analysis, Inspection, Test, Demonstration |
| VerificationMethod | Analysis, Inspection, Test, Demonstration |
### Element
An element definition contains an element name, type, and document reference. These three are all user defined. The element feature is intended to be lightweight but allow requirements to be connected to portions of other documents.
@ -103,7 +86,7 @@ Each relationship is labeled in the diagram.
## Larger Example
This example uses all features of the diagram.
```mermaid
```mermaid-example
requirementDiagram
requirement test_req {

View File

@ -5,20 +5,13 @@
Mermaid can render sequence diagrams.
```
```mermaid-example
sequenceDiagram
Alice->>John: Hello John, how are you?
John-->>Alice: Great!
Alice-)John: See you later!
```
```mermaid
sequenceDiagram
Alice->>John: Hello John, how are you?
John-->>Alice: Great!
Alice--)John: See you later!
```
```note
A note on nodes, the word "end" could potentially break the diagram, due to the way that the mermaid language is scripted.
@ -34,7 +27,7 @@ rendered in order of appearance in the diagram source text. Sometimes you might
different order than how they appear in the first message. It is possible to specify the actor's order of
appearance by doing the following:
```
```mermaid-example
sequenceDiagram
participant Alice
participant Bob
@ -42,18 +35,10 @@ sequenceDiagram
Bob->>Alice: Hi Alice
```
```mermaid
sequenceDiagram
participant Alice
participant Bob
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice
```
### Actors
If you specifically want to use the actor symbol instead of a rectangle with text you can do so by using actor statements as per below.
```
```mermaid-example
sequenceDiagram
actor Alice
actor Bob
@ -61,15 +46,7 @@ sequenceDiagram
Bob->>Alice: Hi Alice
```
```mermaid
sequenceDiagram
actor Alice
actor Bob
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice
```
```
```mermaid-example
sequenceDiagram
actor Alice
actor Bob
@ -77,27 +54,11 @@ sequenceDiagram
Bob->>Alice: Hi Alice
```
```mermaid
sequenceDiagram
actor Alice
actor Bob
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice
```
### Aliases
The actor can have a convenient identifier and a descriptive label.
```
sequenceDiagram
participant A as Alice
participant J as John
A->>J: Hello John, how are you?
J->>A: Great!
```
```mermaid
```mermaid-example
sequenceDiagram
participant A as Alice
participant J as John
@ -130,15 +91,7 @@ There are six types of arrows currently supported:
It is possible to activate and deactivate an actor. (de)activation can be dedicated declarations:
```
sequenceDiagram
Alice->>John: Hello John, how are you?
activate John
John-->>Alice: Great!
deactivate John
```
```mermaid
```mermaid-example
sequenceDiagram
Alice->>John: Hello John, how are you?
activate John
@ -148,13 +101,7 @@ sequenceDiagram
There is also a shortcut notation by appending `+`/`-` suffix to the message arrow:
```
sequenceDiagram
Alice->>+John: Hello John, how are you?
John-->>-Alice: Great!
```
```mermaid
```mermaid-example
sequenceDiagram
Alice->>+John: Hello John, how are you?
John-->>-Alice: Great!
@ -162,15 +109,7 @@ sequenceDiagram
Activations can be stacked for same actor:
```
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!
```
```mermaid
```mermaid-example
sequenceDiagram
Alice->>+John: Hello John, how are you?
Alice->>+John: John, can you hear me?
@ -185,13 +124,7 @@ Note [ right of | left of | over ] [Actor]: Text in note content
See the example below:
```
sequenceDiagram
participant John
Note right of John: Text in note
```
```mermaid
```mermaid-example
sequenceDiagram
participant John
Note right of John: Text in note
@ -199,13 +132,7 @@ sequenceDiagram
It is also possible to create notes spanning two participants:
```
sequenceDiagram
Alice->John: Hello John, how are you?
Note over Alice,John: A typical interaction
```
```mermaid
```mermaid-example
sequenceDiagram
Alice->John: Hello John, how are you?
Note over Alice,John: A typical interaction
@ -223,15 +150,7 @@ end
See the example below:
```
sequenceDiagram
Alice->John: Hello John, how are you?
loop Every minute
John-->Alice: Great!
end
```
```mermaid
```mermaid-example
sequenceDiagram
Alice->John: Hello John, how are you?
loop Every minute
@ -261,20 +180,7 @@ end
See the example below:
```
sequenceDiagram
Alice->>Bob: Hello Bob, how are you?
alt is sick
Bob->>Alice: Not so good :(
else is well
Bob->>Alice: Feeling fresh like a daisy
end
opt Extra response
Bob->>Alice: Thanks for asking
end
```
```mermaid
```mermaid-example
sequenceDiagram
Alice->>Bob: Hello Bob, how are you?
alt is sick
@ -305,7 +211,7 @@ end
See the example below:
```mermaid
```mermaid-example
sequenceDiagram
par Alice to Bob
Alice->>Bob: Hello guys!
@ -318,7 +224,7 @@ sequenceDiagram
It is also possible to nest parallel blocks.
```mermaid
```mermaid-example
sequenceDiagram
par Alice to Bob
Alice->>Bob: Go help John
@ -352,7 +258,7 @@ end
See the examples below:
```mermaid
```mermaid-example
sequenceDiagram
participant Alice
participant John
@ -375,7 +281,7 @@ sequenceDiagram
Comments can be entered within a sequence diagram, 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
sequenceDiagram
Alice->>John: Hello John, how are you?
%% this is a comment
@ -386,12 +292,7 @@ sequenceDiagram
It is possible to escape characters using the syntax exemplified here.
```
sequenceDiagram
A->>B: I #9829; you!
B->>A: I #9829; you #infin; times more!
```
```mermaid
```mermaid-example
sequenceDiagram
A->>B: I #9829; you!
B->>A: I #9829; you #infin; times more!
@ -405,7 +306,7 @@ Because semicolons can be used instead of line breaks to define the markup, you
It is possible to get a sequence number attached to each arrow in a sequence diagram. This can be configured when adding mermaid to the website as shown below:
```
```html
<script>
mermaid.initialize({
sequence: { showSequenceNumbers: true },
@ -415,20 +316,7 @@ It is possible to get a sequence number attached to each arrow in a sequence dia
It can also be be turned on via the diagram code as in the diagram:
```
sequenceDiagram
autonumber
Alice->>John: Hello John, how are you?
loop Healthcheck
John->>John: Fight against hypochondria
end
Note right of John: Rational thoughts!
John-->>Alice: Great!
John->>Bob: How about you?
Bob-->>John: Jolly good!
```
```mermaid
```mermaid-example
sequenceDiagram
autonumber
Alice->>John: Hello John, how are you?
@ -446,10 +334,10 @@ sequenceDiagram
Actors can have popup-menus containing individualized links to external pages. For example, if an actor represented a web service, useful links might include a link to the service health dashboard, repo containing the code for the service, or a wiki page describing the service.
This can be configured by adding one or more link lines with the format:
link <actor>: <link-label> @ <link-url>
```
link <actor>: <link-label> @ <link-url>
```
```mmd
sequenceDiagram
participant Alice
participant John
@ -467,11 +355,13 @@ There is an advanced syntax that relies on JSON formatting. If you are comfortab
This can be configured by adding the links lines with the format:
links <actor>: <json-formatted link-name link-url pairs>
```
links <actor>: <json-formatted link-name link-url pairs>
```
An example is below:
```
```mmd
sequenceDiagram
participant Alice
participant John

View File

@ -4,7 +4,7 @@
Mermaid can render state diagrams. The syntax tries to be compliant with the syntax used in plantUml as this will make it easier for users to share diagrams between mermaid and plantUml.
```
```mermaid-example
stateDiagram-v2
[*] --> Still
Still --> [*]
@ -15,17 +15,9 @@ stateDiagram-v2
Crash --> [*]
```
```mermaid
stateDiagram-v2
[*] --> Still
Still --> [*]
Older renderer:
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
```
```mermaid
```mermaid-example
stateDiagram
[*] --> Still
Still --> [*]
@ -42,36 +34,21 @@ In state diagrams systems are described in terms of its states and how the syste
A state can be declared in multiple ways. The simplest way is to define a state id as a description.
```markdown
stateDiagram-v2
s1
```
```mermaid
```mermaid-example
stateDiagram-v2
s1
```
Another way is by using the state keyword with a description as per below:
```markdown
stateDiagram-v2
state "This is a state description" as s2
```
```mermaid
```mermaid-example
stateDiagram-v2
state "This is a state description" as s2
```
Another way to define a state with a description is to define the state id followed by a colon and the description:
```markdown
stateDiagram-v2
s2 : This is a state description
```
```mermaid
```mermaid-example
stateDiagram-v2
s2 : This is a state description
```
@ -82,24 +59,14 @@ Transitions are path/edges when one state passes into another. This is represent
When you define a transition between two states and the states are not already defined the undefined states are defined with the id from the transition. You can later add descriptions to states defined this way.
```
stateDiagram-v2
s1 --> s2
```
```mermaid
```mermaid-example
stateDiagram-v2
s1 --> s2
```
It is possible to add text to a transition. To describe what it represents.
```
stateDiagram-v2
s1 --> s2: A transition
```
```mermaid
```mermaid-example
stateDiagram-v2
s1 --> s2: A transition
```
@ -108,13 +75,7 @@ stateDiagram-v2
There are two special states indicating the start and stop of the diagram. These are written with the [\*] syntax and the direction of the transition to it defines it either as a start or a stop state.
```
stateDiagram-v2
[*] --> s1
s1 --> [*]
```
```mermaid
```mermaid-example
stateDiagram-v2
[*] --> s1
s1 --> [*]
@ -127,16 +88,7 @@ have several internal states. These are called composite states in this terminol
In order to define a composite state you need to use the state keyword followed by an id and the body of the composite state between \{\}. See the example below:
```
stateDiagram-v2
[*] --> First
state First {
[*] --> second
second --> [*]
}
```
```mermaid
```mermaid-example
stateDiagram-v2
[*] --> First
state First {
@ -147,7 +99,7 @@ stateDiagram-v2
You can do this in several layers:
```
```mermaid-example
stateDiagram-v2
[*] --> First
@ -166,47 +118,9 @@ stateDiagram-v2
}
```
```mermaid
stateDiagram-v2
[*] --> First
state First {
[*] --> Second
state Second {
[*] --> second2
second2 --> Third
state Third {
[*] --> third
third --> [*]
}
}
}
```
You can also define transitions also between composite states:
```
stateDiagram-v2
[*] --> First
First --> Second
First --> Third
state First {
[*] --> fir
fir --> [*]
}
state Second {
[*] --> sec
sec --> [*]
}
state Third {
[*] --> thi
thi --> [*]
}
```
```mermaid
```mermaid-example
stateDiagram-v2
[*] --> First
First --> Second
@ -232,16 +146,7 @@ stateDiagram-v2
Sometimes you need to model a choice between two or more paths, you can do so using &lt;&lt;choice&gt;&gt;.
```
stateDiagram-v2
state if_state <<choice>>
[*] --> IsPositive
IsPositive --> if_state
if_state --> False: if n < 0
if_state --> True : if n >= 0
```
```mermaid
```mermaid-example
stateDiagram-v2
state if_state <<choice>>
[*] --> IsPositive
@ -254,7 +159,7 @@ stateDiagram-v2
It is possible to specify a fork in the diagram using &lt;&lt;fork&gt;&gt; &lt;&lt;join&gt;&gt;.
```
```mermaid-example
stateDiagram-v2
state fork_state <<fork>>
[*] --> fork_state
@ -268,28 +173,13 @@ It is possible to specify a fork in the diagram using &lt;&lt;fork&gt;&gt; &lt;&
State4 --> [*]
```
```mermaid
stateDiagram-v2
state fork_state <<fork>>
[*] --> fork_state
fork_state --> State2
fork_state --> State3
state join_state <<join>>
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
```
## Notes
Sometimes nothing says it better then a Post-it note. That is also the case in state diagrams.
Here you can choose to put the note to the *right of* or to the *left of* a node.
```
```mermaid-example
stateDiagram-v2
State1: The state with a note
note right of State1
@ -300,42 +190,11 @@ Here you can choose to put the note to the *right of* or to the *left of* a node
note left of State2 : This is the note to the left.
```
```mermaid
stateDiagram-v2
State1: The state with a note
note right of State1
Important information! You can write
notes.
end note
State1 --> State2
note left of State2 : This is the note to the left.
```
## Concurrency
As in plantUml you can specify concurrency using the -- symbol.
```
stateDiagram-v2
[*] --> Active
state Active {
[*] --> NumLockOff
NumLockOff --> NumLockOn : EvNumLockPressed
NumLockOn --> NumLockOff : EvNumLockPressed
--
[*] --> CapsLockOff
CapsLockOff --> CapsLockOn : EvCapsLockPressed
CapsLockOn --> CapsLockOff : EvCapsLockPressed
--
[*] --> ScrollLockOff
ScrollLockOff --> ScrollLockOn : EvScrollLockPressed
ScrollLockOn --> ScrollLockOff : EvScrollLockPressed
}
```
```mermaid
```mermaid-example
stateDiagram-v2
[*] --> Active
@ -358,20 +217,7 @@ stateDiagram-v2
With state diagrams you can use the direction statement to set the direction which the diagram will render like in this example.
```
stateDiagram
direction LR
[*] --> A
A --> B
B --> C
state B {
direction LR
a --> b
}
B --> D
```
This is how this renders
```mermaid
```mermaid-example
stateDiagram
direction LR
[*] --> A
@ -389,7 +235,7 @@ stateDiagram
Comments can be entered within a state diagram 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
stateDiagram-v2
[*] --> Still
Still --> [*]

View File

@ -12,7 +12,7 @@ Themes follow and build upon the Levels of Configuration and employ `directives`
Site-wide themes are still declared via `initialize` by site owners.
Example of `Initalize` call setting `theme` to `base`:
```
```javascript
mermaidAPI.initialize({
'securityLevel': 'loose', 'theme': 'base'
});
@ -23,7 +23,7 @@ Example of `Initalize` call setting `theme` to `base`:
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.
```
```mmd
%%{init: {'theme':'base'}}%%
graph TD
a --> b
@ -32,7 +32,7 @@ When Generating a diagram using on a webpage that supports mermaid. It is also p
Here is an example of how `%%init%%` can set the theme to 'base', this assumes that `themeVariables` are set to default:
```mermaid
```mermaid-example
%%{init: {'theme':'base'}}%%
graph TD
A[Christmas] -->|Get money| B(Go shopping)
@ -61,7 +61,7 @@ The easiest way to make a custom theme is to start with the base theme, and just
## Here is an example of overriding `primaryColor` through `themeVariables` and giving everything a different look, using `%%init%%`.
```
```mermaid-example
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ff0000'}}}%%
graph TD
A[Christmas] -->|Get money| B(Go shopping)
@ -79,24 +79,6 @@ The easiest way to make a custom theme is to start with the base theme, and just
end
```
```mermaid
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#00ff00'}}}%%
graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
B --> G[/Another/]
C ==>|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
subgraph section
C
D
E
F
G
end
```
**Notes:**
Leaving it empty will set all variable values to default.
@ -204,26 +186,7 @@ Variables that are unique to some diagrams can be affected by changes in Theme V
# Here is an example of overriding `primaryColor` and giving everything a different look, using `%%init%%`.
```
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ff0000'}}}%%
graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
B --> G[/Another/]
C ==>|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
subgraph section
C
D
E
F
G
end
```
```mermaid
```mermaid-example
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ff0000'}}}%%
graph TD
A[Christmas] -->|Get money| B(Go shopping)
@ -248,25 +211,7 @@ Variables that are unique to some diagrams can be affected by changes in Theme V
* make the edge label background differ from the subgraph by setting the edgeLabelBackground
```
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ffcccc', 'edgeLabelBackground':'#ffffee', 'tertiaryColor': '#fff0f0'}}}%%
graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
B --> G[/Another/]
C ==>|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
subgraph section
C
D
E
F
G
end
```
```mermaid
```mermaid-example
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ffcccc', 'edgeLabelBackground':'#ffffee', 'tertiaryColor': '#fff0f0'}}}%%
graph TD
A[Christmas] -->|Get money| B(Go shopping)
@ -296,7 +241,7 @@ When adjusting a theme it might be helpful to look at how your preferred theme g
In the following examples, the directive `init` is used, with the `theme` being declared as `base`. For more information on using directives, read the documentation for [Version 8.6.0](/8.6.0_docs.md)
### Flowchart
```
```mmd
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
graph TD
A[Christmas] -->|Get money| B(Go shopping)
@ -332,24 +277,7 @@ In the following examples, the directive `init` is used, with the `theme` being
```
### Flowchart (beta)
```
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
flowchart TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
B --> G[Another]
C ==>|One| D[Laptop]
C x--x|Two| E[iPhone]
C o--o|Three| F[fa:fa-car Car]
subgraph section
C
D
E
F
G
end
```
```mermaid
```mermaid-example
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
flowchart TD
A[Christmas] -->|Get money| B(Go shopping)
@ -368,25 +296,7 @@ In the following examples, the directive `init` is used, with the `theme` being
```
### Sequence diagram
```
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
sequenceDiagram
autonumber
par Action 1
Alice->>John: Hello John, how are you?
and Action 2
Alice->>Bob: Hello Bob, how are you?
end
Alice->>+John: Hello John, how are you?
Alice->>+John: John, can you hear me?
John-->>-Alice: Hi Alice, I can hear you!
Note right of John: John is perceptive
John-->>-Alice: I feel great!
loop Every minute
John-->Alice: Great!
end
```
```mermaid
```mermaid-example
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
sequenceDiagram
autonumber
@ -406,7 +316,7 @@ In the following examples, the directive `init` is used, with the `theme` being
```
### Class diagram
```
```mermaid-example
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
classDiagram
@ -431,65 +341,9 @@ classDiagram
+run()
}
```
```mermaid
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
classDiagram
Animal "1" <|-- Duck
Animal <|-- Fish
Animal <--o Zebra
Animal : +int age
Animal : +String gender
Animal: +isMammal()
Animal: +mate()
class Duck{
+String beakColor
+swim()
+quack()
}
class Fish{
-int sizeInFeet
-canEat()
}
class Zebra{
+bool is_wild
+run()
}
```
### Gantt
```
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
excludes :excludes the named dates/days from being included in a charted task..
section A section
Completed task :done, des1, 2014-01-06,2014-01-08
Active task :active, des2, 2014-01-09, 3d
Future task : des3, after des2, 5d
Future task2 : des4, after des3, 5d
section Critical tasks
Completed task in the critical line :crit, done, 2014-01-06,24h
Implement parser and jison :crit, done, after des1, 2d
Create tests for parser :crit, active, 3d
Future task in critical line :crit, 5d
Create tests for renderer :2d
Add to mermaid :1d
section Documentation
Describe gantt syntax :active, a1, after des1, 3d
Add gantt diagram to demo page :after a1 , 20h
Add another diagram to demo page :doc1, after a1 , 48h
section Last section
Describe gantt syntax :after doc1, 3d
Add gantt diagram to demo page :20h
Add another diagram to demo page :48h
```
```mermaid
```mermaid-example
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
@ -520,36 +374,7 @@ gantt
```
### State diagram
```
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
stateDiagram
[*] --> Active
state Active {
[*] --> NumLockOff
NumLockOff --> NumLockOn : EvNumLockPressed
NumLockOn --> NumLockOff : EvNumLockPressed
--
[*] --> CapsLockOff
CapsLockOff --> CapsLockOn : EvCapsLockPressed
CapsLockOn --> CapsLockOff : EvCapsLockPressed
--
[*] --> ScrollLockOff
ScrollLockOff --> ScrollLockOn : EvCapsLockPressed
ScrollLockOn --> ScrollLockOff : EvCapsLockPressed
}
state SomethingElse {
A --> B
B --> A
}
Active --> SomethingElse
note right of SomethingElse : This is the note to the right.
SomethingElse --> [*]
```
```mermaid
```mermaid-example
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
stateDiagram
[*] --> Active
@ -581,35 +406,7 @@ gantt
### State diagram (beta)
```
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
stateDiagram-v2
[*] --> Active
state Active {
[*] --> NumLockOff
NumLockOff --> NumLockOn : EvNumLockPressed
NumLockOn --> NumLockOff : EvNumLockPressed
--
[*] --> CapsLockOff
CapsLockOff --> CapsLockOn : EvCapsLockPressed
CapsLockOn --> CapsLockOff : EvCapsLockPressed
--
[*] --> ScrollLockOff
ScrollLockOff --> ScrollLockOn : EvCapsLockPressed
ScrollLockOn --> ScrollLockOff : EvCapsLockPressed
}
state SomethingElse {
A --> B
B --> A
}
Active --> SomethingElse2
note right of SomethingElse2 : This is the note to the right.
SomethingElse2 --> [*]
```
```mermaid
```mermaid-example
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
stateDiagram-v2
[*] --> Active
@ -640,18 +437,7 @@ stateDiagram-v2
### Entity Relations diagram
```
erDiagram
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
CUSTOMER ||--o{ ORDER : places
CUSTOMER ||--o{ INVOICE : "liable for"
DELIVERY-ADDRESS ||--o{ ORDER : receives
INVOICE ||--|{ ORDER : covers
ORDER ||--|{ ORDER-ITEM : includes
PRODUCT-CATEGORY ||--|{ PRODUCT : contains
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
```
```mermaid
```mermaid-example
erDiagram
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
CUSTOMER ||--o{ ORDER : places
@ -664,19 +450,7 @@ stateDiagram-v2
```
### User journey diagram
```
journey
title My working day
section Go to work
Make tea: 5: Me
Go upstairs: 3: Me
Do work: 1: Me, Cat
section Go home
Go downstairs: 5: Me
Sit down: 5: Me
```
```mermaid
```mermaid-example
journey
title My working day
section Go to work

View File

@ -269,7 +269,7 @@ renderer.code = function (code, language) {
Another example in coffeescript that also includes the mermaid script tag in the generated markup.
```js
```coffee
marked = require 'marked'
module.exports = (options) ->
@ -320,7 +320,7 @@ var textFieldUpdated = function(){
bindEventHandler('change', 'code', textFieldUpdated);
```
**Alternative to mermaid.parse():**
One effective and more future-proof method of validating your graph deinitions, is to paste and render them via the [Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor/). This will ensure that your code is compliant with the syntax of Mermaid's most recent version.
One effective and more future-proof method of validating your graph definitions, is to paste and render them via the [Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor/). This will ensure that your code is compliant with the syntax of Mermaid's most recent version.
## Configuration
@ -370,7 +370,7 @@ approach are:
* mermaid.startOnLoad
* mermaid.htmlLabels
```js
```javascript
mermaid.startOnLoad = true;
```
@ -401,7 +401,7 @@ To set some configuration via the mermaid object. The two parameters that are su
* mermaid_config.startOnLoad
* mermaid_config.htmlLabels
```
```javascript
mermaid_config.startOnLoad = true;
```

View File

@ -4,18 +4,7 @@
Mermaid can render user journey diagrams:
```markdown
journey
title My working day
section Go to work
Make tea: 5: Me
Go upstairs: 3: Me
Do work: 1: Me, Cat
section Go home
Go downstairs: 5: Me
Sit down: 5: Me
```
```mermaid
```mermaid-example
journey
title My working day
section Go to work

View File

@ -1,10 +1,10 @@
const { Generator } = require('jison');
const { validate } = require('schema-utils');
const validate = require('schema-utils');
const schema = require('./parser-options-schema.json');
module.exports = function jisonLoader(source) {
const options = this.getOptions();
validate(schema, options, {
(validate.validate || validate)(schema, options, {
name: 'Jison Loader',
baseDataPath: 'options',
});

View File

@ -1,6 +1,6 @@
{
"name": "mermaid",
"version": "8.13.2",
"version": "8.13.4",
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"main": "dist/mermaid.core.js",
"module": "dist/mermaid.esm.min.mjs",
@ -28,6 +28,7 @@
"build:watch": "yarn build:development --watch",
"release": "yarn build",
"lint": "eslint src",
"lint:fix": "yarn lint --fix",
"e2e:depr": "yarn lint && jest e2e --config e2e/jest.config.js",
"cypress": "percy exec -- cypress run",
"e2e": "start-server-and-test dev http://localhost:9000/ cypress",
@ -78,10 +79,11 @@
"concurrently": "^6.2.2",
"coveralls": "^3.0.2",
"css-to-string-loader": "^0.1.3",
"cypress": "8.5.0",
"cypress": "9.0.0",
"documentation": "13.2.0",
"eslint": "^7.30.0",
"eslint": "^8.0.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-jsdoc": "^37.0.3",
"eslint-plugin-prettier": "^4.0.0",
"husky": "^7.0.1",
"identity-obj-proxy": "^3.0.0",
@ -91,6 +93,7 @@
"moment": "^2.23.0",
"path-browserify": "^1.0.1",
"prettier": "^2.3.2",
"prettier-plugin-jsdoc": "^0.3.30",
"start-server-and-test": "^1.12.6",
"terser-webpack-plugin": "^5.2.4",
"webpack": "^5.53.0",
@ -110,4 +113,4 @@
"pre-push": "yarn test"
}
}
}
}

164
src/Diagram.js Normal file
View File

@ -0,0 +1,164 @@
import classDb from './diagrams/class/classDb';
import classRenderer from './diagrams/class/classRenderer';
import classRendererV2 from './diagrams/class/classRenderer-v2';
import classParser from './diagrams/class/parser/classDiagram';
import erDb from './diagrams/er/erDb';
import erRenderer from './diagrams/er/erRenderer';
import erParser from './diagrams/er/parser/erDiagram';
import flowDb from './diagrams/flowchart/flowDb';
import flowRenderer from './diagrams/flowchart/flowRenderer';
import flowRendererV2 from './diagrams/flowchart/flowRenderer-v2';
import flowParser from './diagrams/flowchart/parser/flow';
import ganttDb from './diagrams/gantt/ganttDb';
import ganttRenderer from './diagrams/gantt/ganttRenderer';
import ganttParser from './diagrams/gantt/parser/gantt';
import gitGraphAst from './diagrams/git/gitGraphAst';
import gitGraphRenderer from './diagrams/git/gitGraphRenderer';
import gitGraphParser from './diagrams/git/parser/gitGraph';
import infoDb from './diagrams/info/infoDb';
import infoRenderer from './diagrams/info/infoRenderer';
import infoParser from './diagrams/info/parser/info';
import pieParser from './diagrams/pie/parser/pie';
import pieDb from './diagrams/pie/pieDb';
import pieRenderer from './diagrams/pie/pieRenderer';
import requirementParser from './diagrams/requirement/parser/requirementDiagram';
import requirementDb from './diagrams/requirement/requirementDb';
import requirementRenderer from './diagrams/requirement/requirementRenderer';
import sequenceParser from './diagrams/sequence/parser/sequenceDiagram';
import sequenceDb from './diagrams/sequence/sequenceDb';
import sequenceRenderer from './diagrams/sequence/sequenceRenderer';
import stateParser from './diagrams/state/parser/stateDiagram';
import stateDb from './diagrams/state/stateDb';
import stateRenderer from './diagrams/state/stateRenderer';
import stateRendererV2 from './diagrams/state/stateRenderer-v2';
import journeyDb from './diagrams/user-journey/journeyDb';
import journeyRenderer from './diagrams/user-journey/journeyRenderer';
import journeyParser from './diagrams/user-journey/parser/journey';
import utils from './utils';
import * as configApi from './config';
import { log } from './logger';
class Diagram {
type = 'graph';
parser;
renderer;
db;
constructor(txt) {
const cnf = configApi.getConfig();
this.txt = txt;
this.type = utils.detectType(txt, cnf);
log.debug('Type ' + this.type);
switch (this.type) {
case 'git':
this.parser = gitGraphParser;
this.parser.parser.yy = gitGraphAst;
this.db = gitGraphAst;
this.renderer = gitGraphRenderer;
break;
case 'flowchart':
flowDb.clear();
this.parser = flowParser;
this.parser.parser.yy = flowDb;
this.db = flowDb;
this.renderer = flowRenderer;
break;
case 'flowchart-v2':
flowDb.clear();
this.parser = flowParser;
this.parser.parser.yy = flowDb;
this.db = flowDb;
this.renderer = flowRendererV2;
break;
case 'sequenceDiagram':
case 'sequence':
this.parser = sequenceParser;
this.parser.parser.yy = sequenceDb;
this.db = sequenceDb;
this.renderer = sequenceRenderer;
break;
case 'gantt':
this.parser = ganttParser;
this.parser.parser.yy = ganttDb;
this.db = ganttDb;
this.renderer = ganttRenderer;
break;
case 'class':
this.parser = classParser;
this.parser.parser.yy = classDb;
this.db = classDb;
this.renderer = classRenderer;
break;
case 'classDiagram':
this.parser = classParser;
this.parser.parser.yy = classDb;
this.db = classDb;
this.renderer = classRendererV2;
break;
case 'state':
this.parser = stateParser;
this.parser.parser.yy = stateDb;
this.db = stateDb;
this.renderer = stateRenderer;
break;
case 'stateDiagram':
this.parser = stateParser;
this.parser.parser.yy = stateDb;
this.db = stateDb;
this.renderer = stateRendererV2;
break;
case 'info':
log.debug('info info info');
this.parser = infoParser;
this.parser.parser.yy = infoDb;
this.db = infoDb;
this.renderer = infoRenderer;
break;
case 'pie':
log.debug('pie');
this.parser = pieParser;
this.parser.parser.yy = pieDb;
this.db = pieDb;
this.renderer = pieRenderer;
break;
case 'er':
log.debug('er');
this.parser = erParser;
this.parser.parser.yy = erDb;
this.db = erDb;
this.renderer = erRenderer;
break;
case 'journey':
log.debug('Journey');
this.parser = journeyParser;
this.parser.parser.yy = journeyDb;
this.db = journeyDb;
this.renderer = journeyRenderer;
break;
case 'requirement':
case 'requirementDiagram':
log.debug('RequirementDiagram');
this.parser = requirementParser;
this.parser.parser.yy = requirementDb;
this.db = requirementDb;
this.renderer = requirementRenderer;
break;
default:
log.error('Unkown graphtype');
throw new Error('Unkown graphtype');
}
this.parser.parser.yy.graphType = this.type;
this.parser.parser.yy.parseError = (str, hash) => {
const error = { str, hash };
throw error;
};
this.parser.parse(txt);
}
getParser() {
return this.parser;
}
getType() {
return this.type;
}
}
export default Diagram;

View File

@ -41,19 +41,21 @@ export const updateCurrentConfig = (siteCfg, _directives) => {
currentConfig = cfg;
return cfg;
};
/**
*## setSiteConfig
*| Function | Description | Type | Values |
*| --------- | ------------------- | ------- | ------------------ |
*| setSiteConfig|Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array|
***Notes:**
*Sets the siteConfig. The siteConfig is a protected configuration for repeat use. Calls to reset() will reset
*the currentConfig to siteConfig. Calls to reset(configApi.defaultConfig) will reset siteConfig and currentConfig
*to the defaultConfig
*Note: currentConfig is set in this function
**Default value: At default, will mirror Global Config**
* @param conf - the base currentConfig to use as siteConfig
* @returns {*} - the siteConfig
* ## setSiteConfig
*
* | Function | Description | Type | Values |
* | ------------- | ------------------------------------- | ----------- | --------------------------------------- |
* | setSiteConfig | Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array |
*
* **Notes:** Sets the siteConfig. The siteConfig is a protected configuration for repeat use. Calls
* to reset() will reset the currentConfig to siteConfig. Calls to reset(configApi.defaultConfig)
* will reset siteConfig and currentConfig to the defaultConfig Note: currentConfig is set in this
* function *Default value: At default, will mirror Global Config**
*
* @param conf - The base currentConfig to use as siteConfig
* @returns {object} - The siteConfig
*/
export const setSiteConfig = (conf) => {
siteConfig = assignWithDepth({}, defaultConfig);
@ -78,28 +80,32 @@ export const updateSiteConfig = (conf) => {
return siteConfig;
};
/**
*## getSiteConfig
*| Function | Description | Type | Values |
*| --------- | ------------------- | ------- | ------------------ |
*| setSiteConfig|Returns the current siteConfig base configuration | Get Request | Returns Any Values in siteConfig|
***Notes**:
*Returns **any** values in siteConfig.
* @returns {*}
* ## getSiteConfig
*
* | Function | Description | Type | Values |
* | ------------- | ------------------------------------------------- | ----------- | -------------------------------- |
* | setSiteConfig | Returns the current siteConfig base configuration | Get Request | Returns Any Values in siteConfig |
*
* **Notes**: Returns **any** values in siteConfig.
*
* @returns {object} - The siteConfig
*/
export const getSiteConfig = () => {
return assignWithDepth({}, siteConfig);
};
/**
*## setConfig
*| Function | Description | Type | Values |
*| --------- | ------------------- | ------- | ------------------ |
*| setSiteConfig|Sets the siteConfig to desired values | Put Request| Any Values, except ones in secure array|
***Notes**:
*Sets the currentConfig. The parameter conf is sanitized based on the siteConfig.secure keys. Any
*values found in conf with key found in siteConfig.secure will be replaced with the corresponding
*siteConfig value.
* @param conf - the potential currentConfig
* @returns {*} - the currentConfig merged with the sanitized conf
* ## setConfig
*
* | Function | Description | Type | Values |
* | ------------- | ------------------------------------- | ----------- | --------------------------------------- |
* | setSiteConfig | Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array |
*
* **Notes**: Sets the currentConfig. The parameter conf is sanitized based on the siteConfig.secure
* keys. Any values found in conf with key found in siteConfig.secure will be replaced with the
* corresponding siteConfig value.
*
* @param {any} conf - The potential currentConfig
* @returns {any} - The currentConfig merged with the sanitized conf
*/
export const setConfig = (conf) => {
// sanitize(conf);
@ -114,25 +120,30 @@ export const setConfig = (conf) => {
};
/**
* ## getConfig
*| Function | Description | Type | Return Values |
*| --------- | ------------------- | ------- | ------------------ |
*| getConfig |Obtains the currentConfig | Get Request | Any Values from currentConfig|
***Notes**:
*Returns **any** the currentConfig
* @returns {*} - the currentConfig
* ## getConfig
*
* | Function | Description | Type | Return Values |
* | --------- | ------------------------- | ----------- | ------------------------------ |
* | getConfig | Obtains the currentConfig | Get Request | Any Values from current Config |
*
* **Notes**: Returns **any** the currentConfig
*
* @returns {any} - The currentConfig
*/
export const getConfig = () => {
return assignWithDepth({}, currentConfig);
};
/**
*## sanitize
*| Function | Description | Type | Values |
*| --------- | ------------------- | ------- | ------------------ |
*| sanitize |Sets the siteConfig to desired values. | Put Request |None|
*Ensures options parameter does not attempt to override siteConfig secure keys
*Note: modifies options in-place
* @param options - the potential setConfig parameter
* ## sanitize
*
* | Function | Description | Type | Values |
* | -------- | -------------------------------------- | ----------- | ------ |
* | sanitize | Sets the siteConfig to desired values. | Put Request | None |
*
* Ensures options parameter does not attempt to override siteConfig secure keys **Notes**: modifies
* options in-place
*
* @param {any} options - The potential setConfig parameter
*/
export const sanitize = (options) => {
// Checking that options are not in the list of excluded options
@ -172,6 +183,11 @@ export const sanitize = (options) => {
});
};
/**
* Pushes in a directive to the configuration
*
* @param {object} directive The directive to push in
*/
export const addDirective = (directive) => {
if (directive.fontFamily) {
if (!directive.themeVariables) {
@ -187,18 +203,19 @@ export const addDirective = (directive) => {
};
/**
*## reset
*| Function | Description | Type | Required | Values |
*| --------- | ------------------- | ------- | -------- | ------------------ |
*| reset|Resets currentConfig to conf| Put Request | Required | None|
* ## reset
*
*| Parameter | Description |Type | Required | Values|
*| --- | --- | --- | --- | --- |
*| conf| base set of values, which currentConfig coul be **reset** to.| Dictionary | Required | Any Values, with respect to the secure Array|
* | Function | Description | Type | Required | Values |
* | -------- | ---------------------------- | ----------- | -------- | ------ |
* | reset | Resets currentConfig to conf | Put Request | Required | None |
*
**Notes :
(default: current siteConfig ) (optional, default `getSiteConfig()`)
* @param conf the base currentConfig to reset to (default: current siteConfig ) (optional, default `getSiteConfig()`)
* ## conf
*
* | Parameter | Description | Type | Required | Values |
* | --------- | ------------------------------------------------------------- | ---------- | -------- | -------------------------------------------- |
* | conf | base set of values, which currentConfig coul be **reset** to. | Dictionary | Required | Any Values, with respect to the secure Array |
*
* **Notes**: (default: current siteConfig ) (optional, default `getSiteConfig()`)
*/
export const reset = () => {
// Replace current config with siteConfig

View File

@ -3,13 +3,6 @@ import { log } from './logger'; // eslint-disable-line
import theme from './themes';
import config from './defaultConfig';
// import { unflatten } from 'flat';
// import flatten from 'flat';
// import themeVariables from './theme-default';
// import themeForestVariables from './theme-forest';
// import themeNeutralVariables from './theme-neutral';
const handleThemeVariables = (value) => {
return theme[value] ? theme[value].getThemeVariables() : theme.default.getThemeVariables();
};
@ -27,18 +20,19 @@ const siteConfig = assignWithDepth({}, defaultConfig);
const currentConfig = assignWithDepth({}, defaultConfig);
/**
*## setSiteConfig
*| Function | Description | Type | Values |
*| --------- | ------------------- | ------- | ------------------ |
*| setSiteConfig|Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array|
***Notes:**
*Sets the siteConfig. The siteConfig is a protected configuration for repeat use. Calls to reset() will reset
*the currentConfig to siteConfig. Calls to reset(configApi.defaultConfig) will reset siteConfig and currentConfig
*to the defaultConfig
*Note: currentConfig is set in this function
**Default value: At default, will mirror Global Config**
* @param conf - the base currentConfig to use as siteConfig
* @returns {*} - the siteConfig
* ## setSiteConfig
*
* | Function | Description | Type | Values |
* | ------------- | ------------------------------------- | ----------- | --------------------------------------- |
* | setSiteConfig | Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array |
*
* **Notes:** Sets the siteConfig. The siteConfig is a protected configuration for repeat use. Calls
* to reset() will reset the currentConfig to siteConfig. Calls to reset(configApi.defaultConfig)
* will reset siteConfig and currentConfig to the defaultConfig Note: currentConfig is set in this
* function Default value: At default, will mirror Global Config
*
* @param {any} conf - The base currentConfig to use as siteConfig
* @returns {any} - The siteConfig
*/
export const setSiteConfig = (conf) => {
console.log('setSiteConfig');
@ -55,28 +49,32 @@ export const setSiteConfig = (conf) => {
return getSiteConfig();
};
/**
*## getSiteConfig
*| Function | Description | Type | Values |
*| --------- | ------------------- | ------- | ------------------ |
*| setSiteConfig|Returns the current siteConfig base configuration | Get Request | Returns Any Values in siteConfig|
***Notes**:
*Returns **any** values in siteConfig.
* @returns {*}
* ## getSiteConfig
*
* | Function | Description | Type | Values |
* | ------------- | ------------------------------------------------- | ----------- | -------------------------------- |
* | setSiteConfig | Returns the current siteConfig base configuration | Get Request | Returns Any Values in siteConfig |
*
* **Notes**: Returns **any** values in siteConfig.
*
* @returns {any}
*/
export const getSiteConfig = () => {
return assignWithDepth({}, siteConfig);
};
/**
*## setConfig
*| Function | Description | Type | Values |
*| --------- | ------------------- | ------- | ------------------ |
*| setSiteConfig|Sets the siteConfig to desired values | Put Request| Any Values, except ones in secure array|
***Notes**:
*Sets the currentConfig. The parameter conf is sanitized based on the siteConfig.secure keys. Any
*values found in conf with key found in siteConfig.secure will be replaced with the corresponding
*siteConfig value.
* @param conf - the potential currentConfig
* @returns {*} - the currentConfig merged with the sanitized conf
* ## setConfig
*
* | Function | Description | Type | Values |
* | ------------- | ------------------------------------- | ----------- | --------------------------------------- |
* | setSiteConfig | Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array |
*
* **Notes**: Sets the currentConfig. The parameter conf is sanitized based on the siteConfig.secure
* keys. Any values found in conf with key found in siteConfig.secure will be replaced with the
* corresponding siteConfig value.
*
* @param {any} conf - The potential currentConfig
* @returns {any} - The currentConfig merged with the sanitized conf
*/
export const setConfig = (conf) => {
console.log('setConfig');
@ -90,25 +88,30 @@ export const setConfig = (conf) => {
return getConfig();
};
/**
* ## getConfig
*| Function | Description | Type | Return Values |
*| --------- | ------------------- | ------- | ------------------ |
*| getConfig |Obtains the currentConfig | Get Request | Any Values from currentConfig|
***Notes**:
*Returns **any** the currentConfig
* @returns {*} - the currentConfig
* ## getConfig
*
* | Function | Description | Type | Return Values |
* | --------- | ------------------------- | ----------- | ----------------------------- |
* | getConfig | Obtains the currentConfig | Get Request | Any Values from currentConfig |
*
* **Notes**: Returns **any** the currentConfig
*
* @returns {any} - The currentConfig
*/
export const getConfig = () => {
return assignWithDepth({}, currentConfig);
};
/**
*## sanitize
*| Function | Description | Type | Values |
*| --------- | ------------------- | ------- | ------------------ |
*| sanitize |Sets the siteConfig to desired values. | Put Request |None|
*Ensures options parameter does not attempt to override siteConfig secure keys
*Note: modifies options in-place
* @param options - the potential setConfig parameter
* ## sanitize
*
* | Function | Description | Type | Values |
* | -------- | -------------------------------------- | ----------- | ------ |
* | sanitize | Sets the siteConfig to desired values. | Put Request | None |
*
* Ensures options parameter does not attempt to override siteConfig secure keys **Notes**: modifies
* options in-place
*
* @param {any} options - The potential setConfig parameter
*/
export const sanitize = (options) => {
Object.keys(siteConfig.secure).forEach((key) => {
@ -124,18 +127,20 @@ export const sanitize = (options) => {
});
};
/**
*## reset
*| Function | Description | Type | Required | Values |
*| --------- | ------------------- | ------- | -------- | ------------------ |
*| reset|Resets currentConfig to conf| Put Request | Required | None|
* ## reset
*
*| Parameter | Description |Type | Required | Values|
*| --- | --- | --- | --- | --- |
*| conf| base set of values, which currentConfig coul be **reset** to.| Dictionary | Required | Any Values, with respect to the secure Array|
* | Function | Description | Type | Required | Values |
* | -------- | ---------------------------- | ----------- | -------- | ------ |
* | reset | Resets currentConfig to conf | Put Request | Required | None |
*
**Notes :
(default: current siteConfig ) (optional, default `getSiteConfig()`)
* @param conf - the base currentConfig to reset to (default: current siteConfig )
* | Parameter | Description |Type | Required | Values|
*
* | --- | --- | --- | --- | --- |
* | conf| base set of values, which currentConfig coul be **reset** to.| Dictionary | Required | Any Values, with respect to the secure Array|
*
* **Notes**: (default: current siteConfig ) (optional, default `getSiteConfig()`)
*
* @param {any} conf - The base currentConfig to reset to (default: current siteConfig )
*/
export const reset = (conf = getSiteConfig()) => {
console.warn('reset');

View File

@ -79,6 +79,10 @@ const rect = (parent, node) => {
/**
* Non visiable cluster where the note is group with its
*
* @param {any} parent
* @param {any} node
* @returns {any} ShapeSvg
*/
const noteGroup = (parent, node) => {
// Add outer g element

View File

@ -1,66 +1,23 @@
import { select } from 'd3';
import { log } from '../logger'; // eslint-disable-line
import { evaluate } from '../diagrams/common/common';
// let vertexNode;
// if (evaluate(getConfig().flowchart.htmlLabels)) {
// // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
// const node = {
// label: vertexText.replace(/fa[lrsb]?:fa-[\w-]+/g, s => `<i class='${s.replace(':', ' ')}'></i>`)
// };
// vertexNode = addHtmlLabel(svg, node).node();
// vertexNode.parentNode.removeChild(vertexNode);
// } else {
// const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
// svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:'));
// const rows = vertexText.split(common.lineBreakRegex);
// for (let j = 0; j < rows.length; j++) {
// const tspan = document.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 = rows[j];
// svgLabel.appendChild(tspan);
// }
// vertexNode = svgLabel;
// }
import { getConfig } from '../config';
import { evaluate } from '../diagrams/common/common';
/**
* @param dom
* @param styleFn
*/
function applyStyle(dom, styleFn) {
if (styleFn) {
dom.attr('style', styleFn);
}
}
/**
* @param {any} node
* @returns {SVGForeignObjectElement} Node
*/
function addHtmlLabel(node) {
// var fo = root.append('foreignObject').attr('width', '100000');
// var div = fo.append('xhtml:div');
// div.attr('xmlns', 'http://www.w3.org/1999/xhtml');
// var label = node.label;
// switch (typeof label) {
// case 'function':
// div.insert(label);
// break;
// case 'object':
// // Currently we assume this is a DOM object.
// div.insert(function() {
// return label;
// });
// break;
// default:
// div.html(label);
// }
// applyStyle(div, node.labelStyle);
// div.style('display', 'inline-block');
// // Fix for firefox
// div.style('white-space', 'nowrap');
// var client = div.node().getBoundingClientRect();
// fo.attr('width', client.width).attr('height', client.height);
const fo = select(document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject'));
const div = fo.append('xhtml:div');

View File

@ -1,6 +1,5 @@
import { log } from '../logger'; // eslint-disable-line
import createLabel from './createLabel';
// import { line, curveBasis, curveLinear, select } from 'd3';
import { line, curveBasis, select } from 'd3';
import { getConfig } from '../config';
import utils from '../utils';
@ -110,6 +109,10 @@ export const insertEdgeLabel = (elem, edge) => {
}
};
/**
* @param {any} fo
* @param {any} value
*/
function setTerminalWidth(fo, value) {
if (getConfig().flowchart.htmlLabels && fo) {
fo.style.width = value.length * 9 + 'px';
@ -306,9 +309,10 @@ export const intersection = (node, outsidePoint, insidePoint) => {
/**
* This function will page a path and node where the last point(s) in the path is inside the node
* and return an update path ending by the border of the node.
* @param {*} points
* @param {*} boundryNode
* @returns
*
* @param {Array} _points
* @param {any} boundryNode
* @returns {Array} Points
*/
const cutPathAtIntersect = (_points, boundryNode) => {
log.warn('abc88 cutPathAtIntersect', _points, boundryNode);

View File

@ -1,5 +1,10 @@
import intersectEllipse from './intersect-ellipse';
/**
* @param node
* @param rx
* @param point
*/
function intersectCircle(node, rx, point) {
return intersectEllipse(node, rx, rx, point);
}

View File

@ -1,3 +1,9 @@
/**
* @param node
* @param rx
* @param ry
* @param point
*/
function intersectEllipse(node, rx, ry, point) {
// Formulae from: http://mathworld.wolfram.com/Ellipse-LineIntersection.html

View File

@ -1,6 +1,10 @@
/*
* Returns the point at which two lines, p and q, intersect or returns
* undefined if they do not intersect.
/**
* Returns the point at which two lines, p and q, intersect or returns undefined if they do not intersect.
*
* @param p1
* @param p2
* @param q1
* @param q2
*/
function intersectLine(p1, p2, q1, q2) {
// Algorithm from J. Avro, (ed.) Graphics Gems, No 2, Morgan Kaufmann, 1994,
@ -63,6 +67,10 @@ function intersectLine(p1, p2, q1, q2) {
return { x: x, y: y };
}
/**
* @param r1
* @param r2
*/
function sameSign(r1, r2) {
return r1 * r2 > 0;
}

View File

@ -1,5 +1,9 @@
module.exports = intersectNode;
/**
* @param node
* @param point
*/
function intersectNode(node, point) {
// console.info('Intersect Node');
return node.intersect(point);

View File

@ -4,9 +4,13 @@ import intersectLine from './intersect-line';
export default intersectPolygon;
/*
* Returns the point ({x, y}) at which the point argument intersects with the
* node argument assuming that it has the shape specified by polygon.
/**
* Returns the point ({x, y}) at which the point argument intersects with the node argument assuming
* that it has the shape specified by polygon.
*
* @param node
* @param polyPoints
* @param point
*/
function intersectPolygon(node, polyPoints, point) {
var x1 = node.x;

View File

@ -1,6 +1,4 @@
/**
* Setup arrow head and define the marker. The result is appended to the svg.
*/
/** Setup arrow head and define the marker. The result is appended to the svg. */
import { log } from '../logger';

View File

@ -1,6 +1,4 @@
/**
* Decorates with functions required by mermaids dagre-wrapper.
*/
/** Decorates with functions required by mermaids dagre-wrapper. */
import { log } from '../logger';
import graphlib from 'graphlib';
@ -145,7 +143,8 @@ export const extractDecendants = (id, graph) => {
/**
* Validates the graph, checking that all parent child relation points to existing nodes and that
* edges between nodes also ia correct. When not correct the function logs the discrepancies.
* @param {graphlib graph} g
*
* @param graph
*/
export const validate = (graph) => {
const edges = graph.edges();
@ -165,8 +164,9 @@ export const validate = (graph) => {
/**
* Finds a child that is not a cluster. When faking a edge between a node and a cluster.
* @param {Finds a } id
* @param {*} graph
*
* @param {Finds a} id
* @param {any} graph
*/
export const findNonClusterChild = (id, graph) => {
// const node = graph.node(id);

View File

@ -1,6 +1,4 @@
/**
* Setup arrow head and define the marker. The result is appended to the svg.
*/
/** Setup arrow head and define the marker. The result is appended to the svg. */
// import { log } from '../logger';

View File

@ -1,7 +1,8 @@
import createLabel from '../createLabel';
import { getConfig } from '../../config';
import { decodeEntities } from '../../mermaidAPI';
import { select } from 'd3';
import { evaluate } from '../../diagrams/common/common';
import { evaluate, sanitizeText } from '../../diagrams/common/common';
export const labelHelper = (parent, node, _classes, isNode) => {
let classes;
if (!_classes) {
@ -20,7 +21,14 @@ export const labelHelper = (parent, node, _classes, isNode) => {
const text = label
.node()
.appendChild(createLabel(node.labelText, node.labelStyle, false, isNode));
.appendChild(
createLabel(
sanitizeText(decodeEntities(node.labelText), getConfig()),
node.labelStyle,
false,
isNode
)
);
// Get the size of the label
let bbox = text.getBBox();
@ -47,6 +55,12 @@ export const updateNodeBounds = (node, element) => {
node.height = bbox.height;
};
/**
* @param parent
* @param w
* @param h
* @param points
*/
export function insertPolygonShape(parent, w, h, points) {
return parent
.insert('polygon', ':first-child')

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@ const splitClassNameAndType = function (id) {
let split = id.split('~');
className = split[0];
genericType = split[1];
genericType = common.sanitizeText(split[1], configApi.getConfig());
}
return { className: className, type: genericType };
@ -33,6 +33,7 @@ const splitClassNameAndType = function (id) {
/**
* Function called by parser when a node definition has been found.
*
* @param id
* @public
*/
@ -56,6 +57,7 @@ export const addClass = function (id) {
/**
* Function to lookup domId from id in the graph definition.
*
* @param id
* @public
*/
@ -98,8 +100,9 @@ export const addRelation = function (relation) {
};
/**
* Adds an annotation to the specified class
* Annotations mark special properties of the given type (like 'interface' or 'service')
* Adds an annotation to the specified class Annotations mark special properties of the given type
* (like 'interface' or 'service')
*
* @param className The class name
* @param annotation The name of the annotation without any brackets
* @public
@ -111,11 +114,11 @@ export const addAnnotation = function (className, annotation) {
/**
* Adds a member to the specified class
*
* @param className The class name
* @param member The full name of the member.
* If the member is enclosed in <<brackets>> it is treated as an annotation
* If the member is ending with a closing bracket ) it is treated as a method
* Otherwise the member will be treated as a normal property
* @param member The full name of the member. If the member is enclosed in <<brackets>> it is
* treated as an annotation If the member is ending with a closing bracket ) it is treated as a
* method Otherwise the member will be treated as a normal property
* @public
*/
export const addMember = function (className, member) {
@ -154,6 +157,7 @@ export const cleanupLabel = function (label) {
/**
* Called by parser when a special node is found, e.g. a clickable element.
*
* @param ids Comma separated list of ids
* @param className Class to add
*/
@ -169,6 +173,7 @@ export const setCssClass = function (ids, className) {
/**
* Called by parser when a tooltip is found, e.g. a clickable element.
*
* @param ids Comma separated list of ids
* @param tooltip Tooltip to add
*/
@ -183,6 +188,7 @@ const setTooltip = function (ids, tooltip) {
/**
* Called by parser when a link is found. Adds the URL to the vertex data.
*
* @param ids Comma separated list of ids
* @param linkStr URL to create a link for
* @param target Target of the link, _blank by default as originally defined in the svgDraw.js file
@ -206,6 +212,7 @@ export const setLink = function (ids, linkStr, target) {
/**
* Called by parser when a click definition is found. Registers an event handler.
*
* @param ids Comma separated list of ids
* @param functionName Function to be called on click
* @param functionArgs Function args the function should be called with

View File

@ -25,8 +25,13 @@ const conf = {
/**
* Function that adds the vertices found during parsing to the graph to be rendered.
* @param vert Object containing the vertices.
* @param g The graph that is to be drawn.
*
* @param {Object<
* string,
* { cssClasses: string[]; text: string; id: string; type: string; domId: string }
* >} classes
* Object containing the vertices.
* @param {SVGGElement} g The graph that is to be drawn.
*/
export const addClasses = function (classes, g) {
// const svg = select(`[id="${svgId}"]`);
@ -40,6 +45,7 @@ export const addClasses = function (classes, g) {
/**
* Variable for storing the classes for the vertex
*
* @type {string}
*/
let cssClassStr = '';
@ -130,8 +136,9 @@ export const addClasses = function (classes, g) {
/**
* Add edges to graph based on parsed graph defninition
* @param {Object} edges The edges to add to the graph
* @param {Object} g The graph object
*
* @param relations
* @param {object} g The graph object
*/
export const addRelations = function (relations, g) {
let cnt = 0;
@ -207,7 +214,8 @@ export const addRelations = function (relations, g) {
edgeData.arrowheadStyle = 'fill: #333';
edgeData.labelpos = 'c';
if (getConfig().flowchart.htmlLabels) { // eslint-disable-line
if (getConfig().flowchart.htmlLabels) {
// eslint-disable-line
edgeData.labelType = 'html';
edgeData.label = '<span class="edgeLabel">' + edge.text + '</span>';
} else {
@ -226,19 +234,25 @@ export const addRelations = function (relations, g) {
});
};
// Todo optimize
/**
* Gets the ID with the same label as in the cache
*
* @param {string} label The label to look for
* @returns {string} The resulting ID
*/
const getGraphId = function (label) {
const keys = Object.keys(idCache);
const foundEntry = Object.entries(idCache).find((entry) => entry[1].label === label);
for (let i = 0; i < keys.length; i++) {
if (idCache[keys[i]].label === label) {
return keys[i];
}
if (foundEntry) {
return foundEntry[0];
}
return undefined;
};
/**
* Merges the value of `conf` with the passed `cnf`
*
* @param {object} cnf Config to merge
*/
export const setConf = function (cnf) {
const keys = Object.keys(cnf);
@ -249,8 +263,9 @@ export const setConf = function (cnf) {
/**
* Draws a flowchart in the tag with id: id based on the graph definition in text.
* @param text
* @param id
*
* @param {string} text
* @param {string} id
*/
export const drawOld = function (text, id) {
idCache = {};
@ -498,10 +513,12 @@ export const draw = function (text, id) {
// });
};
export default {
setConf,
draw,
};
/**
* Gets the arrow marker for a type index
*
* @param {number} type The type to look for
* @returns {'aggregation' | 'extension' | 'composition' | 'dependency'} The arrow marker
*/
function getArrowMarker(type) {
let marker;
switch (type) {
@ -522,3 +539,8 @@ function getArrowMarker(type) {
}
return marker;
}
export default {
setConf,
draw,
};

View File

@ -18,21 +18,24 @@ const conf = {
textHeight: 10,
};
// Todo optimize
/**
* Gets the ID with the same label as in the cache
*
* @param {string} label The label to look for
* @returns {string} The resulting ID
*/
const getGraphId = function (label) {
const keys = Object.keys(idCache);
const foundEntry = Object.entries(idCache).find((entry) => entry[1].label === label);
for (let i = 0; i < keys.length; i++) {
if (idCache[keys[i]].label === label) {
return keys[i];
}
if (foundEntry) {
return foundEntry[0];
}
return undefined;
};
/**
* Setup arrow head and define the marker. The result is appended to the svg.
*
* @param {SVGSVGElement} elem The SVG element to append to
*/
const insertMarkers = function (elem) {
elem
@ -136,6 +139,11 @@ const insertMarkers = function (elem) {
.attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z');
};
/**
* Merges the value of `conf` with the passed `cnf`
*
* @param {object} cnf Config to merge
*/
export const setConf = function (cnf) {
const keys = Object.keys(cnf);
@ -146,8 +154,9 @@ export const setConf = function (cnf) {
/**
* Draws a flowchart in the tag with id: id based on the graph definition in text.
* @param text
* @param id
*
* @param {string} text
* @param {string} id
*/
export const draw = function (text, id) {
idCache = {};

View File

@ -144,6 +144,14 @@ export const drawEdge = function (elem, path, relation, conf) {
edgeCount++;
};
/**
* Renders a class diagram
*
* @param {SVGSVGElement} elem The element to draw it into
* @param classDef
* @param conf
* @todo Add more information in the JSDOC here
*/
export const drawClass = function (elem, classDef, conf) {
log.info('Rendering class ' + classDef);
@ -382,6 +390,14 @@ const buildLegacyDisplay = function (text) {
};
};
/**
* Adds a <tspan> for a member in a diagram
*
* @param {SVGElement} textEl The element to append to
* @param {string} txt The member
* @param {boolean} isFirst
* @param {{ padding: string; textHeight: string }} conf The configuration for the member
*/
const addTspan = function (textEl, txt, isFirst, conf) {
let member = parseMember(txt);
@ -396,6 +412,16 @@ const addTspan = function (textEl, txt, isFirst, conf) {
}
};
/**
* Makes generics in typescript syntax
*
* @example <caption>Array of array of strings in typescript syntax</caption>
* // returns "Array<Array<string>>"
* parseGenericTypes('Array~Array~string~~');
*
* @param {string} text The text to convert
* @returns {string} The converted string
*/
const parseGenericTypes = function (text) {
let cleanedText = text;
@ -409,6 +435,12 @@ const parseGenericTypes = function (text) {
}
};
/**
* Gives the styles for a classifier
*
* @param {'+' | '-' | '#' | '~' | '*' | '$'} classifier The classifier string
* @returns {string} Styling for the classifier
*/
const parseClassifier = function (classifier) {
switch (classifier) {
case '*':

View File

@ -1,5 +1,11 @@
import DOMPurify from 'dompurify';
/**
* Gets the number of lines in a string
*
* @param {string | undefined} s The string to check the lines for
* @returns {number} The number of lines in that string
*/
export const getRows = (s) => {
if (!s) return 1;
let str = breakToPlaceholder(s);
@ -7,6 +13,12 @@ export const getRows = (s) => {
return str.split('#br#');
};
/**
* Removes script tags from a text
*
* @param {string} txt The text to sanitize
* @returns {string} The safer text
*/
export const removeScript = (txt) => {
var rs = '';
var idx = 0;
@ -70,22 +82,61 @@ export const sanitizeText = (text, config) => {
return txt;
};
export const sanitizeTextOrArray = (a, config) => {
if (typeof a === 'string') return sanitizeText(a, config);
const f = (x) => sanitizeText(x, config);
return a.flat().map(f);
};
export const lineBreakRegex = /<br\s*\/?>/gi;
/**
* Whether or not a text has any linebreaks
*
* @param {string} text The text to test
* @returns {boolean} Whether or not the text has breaks
*/
export const hasBreaks = (text) => {
return /<br\s*[/]?>/gi.test(text);
return lineBreakRegex.test(text);
};
/**
* Splits on <br> tags
*
* @param {string} text Text to split
* @returns {string[]} List of lines as strings
*/
export const splitBreaks = (text) => {
return text.split(/<br\s*[/]?>/gi);
return text.split(lineBreakRegex);
};
/**
* Converts placeholders to linebreaks in HTML
*
* @param {string} s HTML with placeholders
* @returns {string} HTML with breaks instead of placeholders
*/
const placeholderToBreak = (s) => {
return s.replace(/#br#/g, '<br/>');
};
/**
* Opposite of `placeholderToBreak`, converts breaks to placeholders
*
* @param {string} s HTML string
* @returns {string} String with placeholders
*/
const breakToPlaceholder = (s) => {
return s.replace(lineBreakRegex, '#br#');
};
/**
* Gets the current URL
*
* @param {boolean} useAbsolute Whether to return the absolute URL or not
* @returns {string} The current URL
*/
const getUrl = (useAbsolute) => {
let url = '';
if (useAbsolute) {
@ -102,11 +153,18 @@ const getUrl = (useAbsolute) => {
return url;
};
/**
* Converts a string/boolean into a boolean
*
* @param {string | boolean} val String or boolean to convert
* @returns {boolean} The result from the input
*/
export const evaluate = (val) => (val === 'false' || val === false ? false : true);
export default {
getRows,
sanitizeText,
sanitizeTextOrArray,
hasBreaks,
splitBreaks,
lineBreakRegex,

View File

@ -1,6 +1,3 @@
/**
*
*/
import { log } from '../../logger';
import mermaidAPI from '../../mermaidAPI';
import * as configApi from '../../config';
@ -49,6 +46,7 @@ const addAttributes = function (entityName, attribs) {
/**
* Add a relationship
*
* @param entA The first entity in the relationship
* @param rolA The role played by the first entity in relation to the second
* @param entB The second entity in the relationship

View File

@ -11,6 +11,9 @@ const ERMarkers = {
/**
* Put the markers into the svg DOM for later use with edge paths
*
* @param elem
* @param conf
*/
const insertMarkers = function (elem, conf) {
let marker;

View File

@ -11,9 +11,11 @@ import { configureSvgSize } from '../../utils';
const conf = {};
/**
* Allows the top-level API module to inject config specific to this renderer,
* storing it in the local conf object. Note that generic config still needs to be
* retrieved using getConfig() imported from the config module
* Allows the top-level API module to inject config specific to this renderer, storing it in the
* local conf object. Note that generic config still needs to be retrieved using getConfig()
* imported from the config module
*
* @param cnf
*/
export const setConf = function (cnf) {
const keys = Object.keys(cnf);
@ -24,10 +26,11 @@ export const setConf = function (cnf) {
/**
* Draw attributes for an entity
* @param groupNode the svg group node for the entity
* @param entityTextNode the svg node for the entity label text
* @param attributes an array of attributes defined for the entity (each attribute has a type and a name)
* @return the bounding box of the entity, after attributes have been added
*
* @param groupNode The svg group node for the entity
* @param entityTextNode The svg node for the entity label text
* @param attributes An array of attributes defined for the entity (each attribute has a type and a name)
* @returns The bounding box of the entity, after attributes have been added
*/
const drawAttributes = (groupNode, entityTextNode, attributes) => {
const heightPadding = conf.entityPadding / 3; // Padding internal to attribute boxes
@ -269,10 +272,11 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
/**
* Use D3 to construct the svg elements for the entities
* @param svgNode the svg node that contains the diagram
*
* @param svgNode The svg node that contains the diagram
* @param entities The entities to be drawn
* @param graph The graph that contains the vertex and edge definitions post-layout
* @return The first entity that was inserted
* @returns The first entity that was inserted
*/
const drawEntities = function (svgNode, entities, graph) {
const keys = Object.keys(entities);
@ -356,9 +360,10 @@ const getEdgeName = function (rel) {
/**
* Add each relationship to the graph
* @param relationships the relationships to be added
* @param g the graph
* @return {Array} The array of relationships
*
* @param relationships The relationships to be added
* @param g The graph
* @returns {Array} The array of relationships
*/
const addRelationships = function (relationships, g) {
relationships.forEach(function (r) {
@ -370,10 +375,12 @@ const addRelationships = function (relationships, g) {
let relCnt = 0;
/**
* Draw a relationship using edge information from the graph
* @param svg the svg node
* @param rel the relationship to draw in the svg
* @param g the graph containing the edge information
* @param insert the insertion point in the svg DOM (because relationships have markers that need to sit 'behind' opaque entity boxes)
*
* @param svg The svg node
* @param rel The relationship to draw in the svg
* @param g The graph containing the edge information
* @param insert The insertion point in the svg DOM (because relationships have markers that need to
* sit 'behind' opaque entity boxes)
*/
const drawRelationshipFromLayout = function (svg, rel, g, insert) {
relCnt++;
@ -502,8 +509,9 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert) {
/**
* Draw en E-R diagram in the tag with id: id based on the text definition of the diagram
* @param text the text of the diagram
* @param id the unique id of the DOM node that contains the diagram
*
* @param text The text of the diagram
* @param id The unique id of the DOM node that contains the diagram
*/
export const draw = function (text, id) {
log.info('Drawing ER diagram');

View File

@ -1,5 +1,10 @@
import dagreD3 from 'dagre-d3';
/**
* @param parent
* @param bbox
* @param node
*/
function question(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
@ -17,6 +22,11 @@ function question(parent, bbox, node) {
return shapeSvg;
}
/**
* @param parent
* @param bbox
* @param node
*/
function hexagon(parent, bbox, node) {
const f = 4;
const h = bbox.height;
@ -37,6 +47,11 @@ function hexagon(parent, bbox, node) {
return shapeSvg;
}
/**
* @param parent
* @param bbox
* @param node
*/
function rect_left_inv_arrow(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
@ -54,6 +69,11 @@ function rect_left_inv_arrow(parent, bbox, node) {
return shapeSvg;
}
/**
* @param parent
* @param bbox
* @param node
*/
function lean_right(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
@ -70,6 +90,11 @@ function lean_right(parent, bbox, node) {
return shapeSvg;
}
/**
* @param parent
* @param bbox
* @param node
*/
function lean_left(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
@ -86,6 +111,11 @@ function lean_left(parent, bbox, node) {
return shapeSvg;
}
/**
* @param parent
* @param bbox
* @param node
*/
function trapezoid(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
@ -102,6 +132,11 @@ function trapezoid(parent, bbox, node) {
return shapeSvg;
}
/**
* @param parent
* @param bbox
* @param node
*/
function inv_trapezoid(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
@ -118,6 +153,11 @@ function inv_trapezoid(parent, bbox, node) {
return shapeSvg;
}
/**
* @param parent
* @param bbox
* @param node
*/
function rect_right_inv_arrow(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
@ -135,6 +175,11 @@ function rect_right_inv_arrow(parent, bbox, node) {
return shapeSvg;
}
/**
* @param parent
* @param bbox
* @param node
*/
function stadium(parent, bbox, node) {
const h = bbox.height;
const w = bbox.width + h / 4;
@ -154,6 +199,11 @@ function stadium(parent, bbox, node) {
return shapeSvg;
}
/**
* @param parent
* @param bbox
* @param node
*/
function subroutine(parent, bbox, node) {
const w = bbox.width;
const h = bbox.height;
@ -176,6 +226,11 @@ function subroutine(parent, bbox, node) {
return shapeSvg;
}
/**
* @param parent
* @param bbox
* @param node
*/
function cylinder(parent, bbox, node) {
const w = bbox.width;
const rx = w / 2;
@ -239,6 +294,7 @@ function cylinder(parent, bbox, node) {
return shapeSvg;
}
/** @param render */
export function addToRender(render) {
render.shapes().question = question;
render.shapes().hexagon = hexagon;
@ -265,6 +321,7 @@ export function addToRender(render) {
render.shapes().rect_right_inv_arrow = rect_right_inv_arrow;
}
/** @param addShape */
export function addToRenderV2(addShape) {
addShape({ question });
addShape({ hexagon });
@ -291,6 +348,12 @@ export function addToRenderV2(addShape) {
addShape({ rect_right_inv_arrow });
}
/**
* @param parent
* @param w
* @param h
* @param points
*/
function insertPolygonShape(parent, w, h, points) {
return parent
.insert('polygon', ':first-child')

View File

@ -29,6 +29,7 @@ export const parseDirective = function (statement, context, type) {
/**
* Function to lookup domId from id in the graph definition.
*
* @param id
* @public
*/
@ -44,11 +45,13 @@ export const lookUpDomId = function (id) {
/**
* Function called by parser when a node definition has been found
* @param id
*
* @param _id
* @param text
* @param type
* @param style
* @param classes
* @param dir
* @param props
*/
export const addVertex = function (_id, text, type, style, classes, dir, props = {}) {
@ -112,8 +115,9 @@ export const addVertex = function (_id, text, type, style, classes, dir, props =
/**
* Function called by parser when a link/edge definition has been found
* @param start
* @param end
*
* @param _start
* @param _end
* @param type
* @param linktext
*/
@ -154,8 +158,9 @@ export const addLink = function (_start, _end, type, linktext) {
/**
* Updates a link's line interpolation algorithm
* @param pos
* @param interpolate
*
* @param positions
* @param interp
*/
export const updateLinkInterpolate = function (positions, interp) {
positions.forEach(function (pos) {
@ -169,7 +174,8 @@ export const updateLinkInterpolate = function (positions, interp) {
/**
* Updates a link with a style
* @param pos
*
* @param positions
* @param style
*/
export const updateLink = function (positions, style) {
@ -206,6 +212,7 @@ export const addClass = function (id, style) {
/**
* Called by parser when a graph definition is found, stores the direction of the chart.
*
* @param dir
*/
export const setDirection = function (dir) {
@ -226,6 +233,7 @@ export const setDirection = function (dir) {
/**
* Called by parser when a special node is found, e.g. a clickable element.
*
* @param ids Comma separated list of ids
* @param className Class to add
*/
@ -300,8 +308,10 @@ const setClickFun = function (id, functionName, functionArgs) {
/**
* Called by parser when a link is found. Adds the URL to the vertex data.
*
* @param ids Comma separated list of ids
* @param linkStr URL to create a link for
* @param target
*/
export const setLink = function (ids, linkStr, target) {
ids.split(',').forEach(function (id) {
@ -318,9 +328,10 @@ export const getTooltip = function (id) {
/**
* Called by parser when a click definition is found. Registers an event handler.
*
* @param ids Comma separated list of ids
* @param functionName Function to be called on click
* @param tooltip Tooltip for the clickable element
* @param functionArgs
*/
export const setClickEvent = function (ids, functionName, functionArgs) {
ids.split(',').forEach(function (id) {
@ -339,7 +350,8 @@ export const getDirection = function () {
};
/**
* Retrieval function for fetching the found nodes after parsing has completed.
* @returns {{}|*|vertices}
*
* @returns {{} | any | vertices}
*/
export const getVertices = function () {
return vertices;
@ -347,7 +359,8 @@ export const getVertices = function () {
/**
* Retrieval function for fetching the found links after parsing has completed.
* @returns {{}|*|edges}
*
* @returns {{} | any | edges}
*/
export const getEdges = function () {
return edges;
@ -355,7 +368,8 @@ export const getEdges = function () {
/**
* Retrieval function for fetching the found class definitions after parsing has completed.
* @returns {{}|*|classes}
*
* @returns {{} | any | classes}
*/
export const getClasses = function () {
return classes;
@ -398,6 +412,8 @@ funs.push(setupToolTips);
/**
* Clears the internal graph db so that a new graph can be parsed.
*
* @param ver
*/
export const clear = function (ver) {
vertices = {};
@ -415,16 +431,17 @@ export const clear = function (ver) {
export const setGen = (ver) => {
version = ver || 'gen-1';
};
/**
*
* @returns {string}
*/
/** @returns {string} */
export const defaultStyle = function () {
return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;';
};
/**
* Clears the internal graph db so that a new graph can be parsed.
*
* @param _id
* @param list
* @param _title
*/
export const addSubGraph = function (_id, list, _title) {
// console.log('addSubGraph', _id, list, _title);
@ -433,6 +450,7 @@ export const addSubGraph = function (_id, list, _title) {
if (_id === _title && _title.match(/\s/)) {
id = undefined;
}
/** @param a */
function uniq(a) {
const prims = { boolean: {}, number: {}, string: {} };
const objs = [];
@ -476,9 +494,7 @@ export const addSubGraph = function (_id, list, _title) {
log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir);
/**
* Deletes an id from all subgraphs
*/
/** Deletes an id from all subgraphs */
// const del = _id => {
// subGraphs.forEach(sg => {
// const pos = sg.nodes.indexOf(_id);
@ -703,6 +719,9 @@ const exists = (allSgs, _id) => {
};
/**
* Deletes an id from all subgraphs
*
* @param sg
* @param allSubgraphs
*/
const makeUniq = (sg, allSubgraphs) => {
const res = [];

View File

@ -21,8 +21,10 @@ export const setConf = function (cnf) {
/**
* Function that adds the vertices found during parsing to the graph to be rendered.
*
* @param vert Object containing the vertices.
* @param g The graph that is to be drawn.
* @param svgId
*/
export const addVertices = function (vert, g, svgId) {
const svg = select(`[id="${svgId}"]`);
@ -34,6 +36,7 @@ export const addVertices = function (vert, g, svgId) {
/**
* Variable for storing the classes for the vertex
*
* @type {string}
*/
let classStr = 'default';
@ -174,8 +177,9 @@ export const addVertices = function (vert, g, svgId) {
/**
* Add edges to graph based on parsed graph defninition
* @param {Object} edges The edges to add to the graph
* @param {Object} g The graph object
*
* @param {object} edges The edges to add to the graph
* @param {object} g The graph object
*/
export const addEdges = function (edges, g) {
log.info('abc78 edges = ', edges);
@ -319,7 +323,9 @@ export const addEdges = function (edges, g) {
/**
* Returns the all the styles from classDef statements in the graph definition.
* @returns {object} classDef styles
*
* @param text
* @returns {object} ClassDef styles
*/
export const getClasses = function (text) {
log.info('Extracting classes');
@ -339,6 +345,7 @@ export const getClasses = function (text) {
/**
* Draws a flowchart in the tag with id: id based on the graph definition in text.
*
* @param text
* @param id
*/

View File

@ -22,8 +22,10 @@ export const setConf = function (cnf) {
/**
* Function that adds the vertices found in the graph definition to the graph to be rendered.
*
* @param vert Object containing the vertices.
* @param g The graph that is to be drawn.
* @param svgId
*/
export const addVertices = function (vert, g, svgId) {
const svg = select(`[id="${svgId}"]`);
@ -35,6 +37,7 @@ export const addVertices = function (vert, g, svgId) {
/**
* Variable for storing the classes for the vertex
*
* @type {string}
*/
let classStr = 'default';
@ -150,8 +153,9 @@ export const addVertices = function (vert, g, svgId) {
/**
* Add edges to graph based on parsed graph defninition
* @param {Object} edges The edges to add to the graph
* @param {Object} g The graph object
*
* @param {object} edges The edges to add to the graph
* @param {object} g The graph object
*/
export const addEdges = function (edges, g) {
let cnt = 0;
@ -257,7 +261,9 @@ export const addEdges = function (edges, g) {
/**
* Returns the all the styles from classDef statements in the graph definition.
* @returns {object} classDef styles
*
* @param text
* @returns {object} ClassDef styles
*/
export const getClasses = function (text) {
log.info('Extracting classes');
@ -276,6 +282,7 @@ export const getClasses = function (text) {
/**
* Draws a flowchart in the tag with id: id based on the graph definition in text.
*
* @param text
* @param id
*/

View File

@ -61,7 +61,7 @@ describe('[Style] when parsing', () => {
expect(vert['T'].styles[1]).toBe('border:1px solid red');
});
it('should handle styles and graph definitons in a graph', function() {
it('should handle styles and graph definitions in a graph', function() {
const res = flow.parser.parse(
'graph TD;S-->T;\nstyle S background:#aaa;\nstyle T background:#bbb,border:1px solid red;'
);
@ -76,7 +76,7 @@ describe('[Style] when parsing', () => {
expect(vert['T'].styles[1]).toBe('border:1px solid red');
});
it('should handle styles and graph definitons in a graph', function() {
it('should handle styles and graph definitions in a graph', function() {
const res = flow.parser.parse('graph TD;style T background:#bbb,border:1px solid red;');
// const res = flow.parser.parse('graph TD;style T background: #bbb;');
@ -277,7 +277,7 @@ describe('[Style] when parsing', () => {
expect(edges[0].type).toBe('arrow_point');
});
it('should handle multi-numbered style definitons with more then 1 digit in a row', function() {
it('should handle multi-numbered style definitions with more then 1 digit in a row', function() {
const res = flow.parser.parse(
'graph TD\n' +
'A-->B1\n' +

View File

@ -1,3 +1,24 @@
/**
* Returns the styles given options
*
* @param {{
* fontFamily: string;
* nodeTextColor: string;
* textColor: string;
* titleColor: string;
* mainBkg: string;
* nodeBorder: string;
* arrowheadColor: string;
* lineColor: string;
* edgeLabelBackground: string;
* clusterBkg: string;
* clusterBorder: string;
* tertiaryColor: string;
* border2: string;
* }} options
* The options for the styles
* @returns {string} The resulting styles
*/
const getStyles = (options) =>
`.label {
font-family: ${options.fontFamily};
@ -69,9 +90,9 @@ const getStyles = (options) =>
.cluster span {
color: ${options.titleColor};
}
// .cluster div {
// color: ${options.titleColor};
// }
/* .cluster div {
color: ${options.titleColor};
} */
div.mermaidTooltip {
position: absolute;

View File

@ -8,6 +8,7 @@ import mermaidAPI from '../../mermaidAPI';
let dateFormat = '';
let axisFormat = '';
let todayMarker = '';
let includes = [];
let excludes = [];
let title = '';
let sections = [];
@ -38,6 +39,7 @@ export const clear = function () {
dateFormat = '';
axisFormat = '';
todayMarker = '';
includes = [];
excludes = [];
inclusiveEndDates = false;
topAxis = false;
@ -84,6 +86,13 @@ export const getDateFormat = function () {
return dateFormat;
};
export const setIncludes = function (txt) {
includes = txt.toLowerCase().split(/[\s,]+/);
};
export const getIncludes = function () {
return includes;
};
export const setExcludes = function (txt) {
excludes = txt.toLowerCase().split(/[\s,]+/);
};
@ -123,7 +132,10 @@ export const getTasks = function () {
return tasks;
};
const isInvalidDate = function (date, dateFormat, excludes) {
export const isInvalidDate = function (date, dateFormat, excludes, includes) {
if (includes.indexOf(date.format(dateFormat.trim())) >= 0) {
return false;
}
if (date.isoWeekday() >= 6 && excludes.indexOf('weekends') >= 0) {
return true;
}
@ -133,24 +145,24 @@ const isInvalidDate = function (date, dateFormat, excludes) {
return excludes.indexOf(date.format(dateFormat.trim())) >= 0;
};
const checkTaskDates = function (task, dateFormat, excludes) {
const checkTaskDates = function (task, dateFormat, excludes, includes) {
if (!excludes.length || task.manualEndTime) return;
let startTime = moment(task.startTime, dateFormat, true);
startTime.add(1, 'd');
let endTime = moment(task.endTime, dateFormat, true);
let renderEndTime = fixTaskDates(startTime, endTime, dateFormat, excludes);
let renderEndTime = fixTaskDates(startTime, endTime, dateFormat, excludes, includes);
task.endTime = endTime.toDate();
task.renderEndTime = renderEndTime;
};
const fixTaskDates = function (startTime, endTime, dateFormat, excludes) {
const fixTaskDates = function (startTime, endTime, dateFormat, excludes, includes) {
let invalid = false;
let renderEndTime = null;
while (startTime <= endTime) {
if (!invalid) {
renderEndTime = endTime.toDate();
}
invalid = isInvalidDate(startTime, dateFormat, excludes);
invalid = isInvalidDate(startTime, dateFormat, excludes, includes);
if (invalid) {
endTime.add(1, 'd');
}
@ -306,7 +318,7 @@ const compileData = function (prevTask, dataStr) {
if (endTimeData) {
task.endTime = getEndDate(task.startTime, dateFormat, endTimeData, inclusiveEndDates);
task.manualEndTime = moment(endTimeData, 'YYYY-MM-DD', true).isValid();
checkTaskDates(task, dateFormat, excludes);
checkTaskDates(task, dateFormat, excludes, includes);
}
return task;
@ -460,7 +472,7 @@ const compileTasks = function () {
'YYYY-MM-DD',
true
).isValid();
checkTaskDates(rawTasks[pos], dateFormat, excludes);
checkTaskDates(rawTasks[pos], dateFormat, excludes, includes);
}
}
@ -478,8 +490,9 @@ const compileTasks = function () {
/**
* Called by parser when a link is found. Adds the URL to the vertex data.
*
* @param ids Comma separated list of ids
* @param linkStr URL to create a link for
* @param _linkStr URL to create a link for
*/
export const setLink = function (ids, _linkStr) {
let linkStr = _linkStr;
@ -499,6 +512,7 @@ export const setLink = function (ids, _linkStr) {
/**
* Called by parser when a special node is found, e.g. a clickable element.
*
* @param ids Comma separated list of ids
* @param className Class to add
*/
@ -548,7 +562,9 @@ const setClickFun = function (id, functionName, functionArgs) {
};
/**
* The callbackFunction is executed in a click event bound to the task with the specified id or the task's assigned text
* The callbackFunction is executed in a click event bound to the task with the specified id or the
* task's assigned text
*
* @param id The task's id
* @param callbackFunction A function to be executed when clicked on the task or the task's text
*/
@ -575,6 +591,7 @@ const pushFun = function (id, callbackFunction) {
/**
* Called by parser when a click definition is found. Registers an event handler.
*
* @param ids Comma separated list of ids
* @param functionName Function to be called on click
* @param functionArgs Function args the function should be called with
@ -588,6 +605,7 @@ export const setClickEvent = function (ids, functionName, functionArgs) {
/**
* Binds all functions previously added to fun (specified through click) to the element
*
* @param element
*/
export const bindFunctions = function (element) {
@ -618,14 +636,22 @@ export default {
addTask,
findTaskById,
addTaskOrg,
setIncludes,
getIncludes,
setExcludes,
getExcludes,
setClickEvent,
setLink,
bindFunctions,
durationToDate,
isInvalidDate,
};
/**
* @param data
* @param task
* @param tags
*/
function getTaskTags(data, task, tags) {
let matchFound = true;
while (matchFound) {

View File

@ -1,3 +1,4 @@
import moment from 'moment-mini';
import {
select,
scaleTime,
@ -70,6 +71,10 @@ export const draw = function (text, id) {
categories = checkUnique(categories);
/**
* @param a
* @param b
*/
function taskCompare(a, b) {
const taskA = a.startTime;
const taskB = b.startTime;
@ -97,6 +102,11 @@ export const draw = function (text, id) {
.attr('y', conf.titleTopMargin)
.attr('class', 'titleText');
/**
* @param tasks
* @param pageWidth
* @param pageHeight
*/
function makeGant(tasks, pageWidth, pageHeight) {
const barHeight = conf.barHeight;
const gap = barHeight + conf.barGap;
@ -108,12 +118,31 @@ export const draw = function (text, id) {
.range(['#00B9FA', '#F95002'])
.interpolate(interpolateHcl);
drawExcludeDays(
gap,
topPadding,
leftPadding,
pageWidth,
pageHeight,
tasks,
parser.yy.getExcludes(),
parser.yy.getIncludes()
);
makeGrid(leftPadding, topPadding, pageWidth, pageHeight);
drawRects(tasks, gap, topPadding, leftPadding, barHeight, colorScale, pageWidth, pageHeight);
vertLabels(gap, topPadding, leftPadding, barHeight, colorScale);
drawToday(leftPadding, topPadding, pageWidth, pageHeight);
}
/**
* @param theArray
* @param theGap
* @param theTopPad
* @param theSidePad
* @param theBarHeight
* @param theColorScale
* @param w
*/
function drawRects(theArray, theGap, theTopPad, theSidePad, theBarHeight, theColorScale, w) {
// Draw background rects covering the entire width of the graph, these form the section rows.
svg
@ -341,7 +370,84 @@ export const draw = function (text, id) {
}
});
}
/**
* @param theGap
* @param theTopPad
* @param theSidePad
* @param w
* @param h
* @param tasks
* @param excludes
* @param includes
*/
function drawExcludeDays(theGap, theTopPad, theSidePad, w, h, tasks, excludes, includes) {
const minTime = tasks.reduce(
(min, { startTime }) => (min ? Math.min(min, startTime) : startTime),
0
);
const maxTime = tasks.reduce((max, { endTime }) => (max ? Math.max(max, endTime) : endTime), 0);
const dateFormat = parser.yy.getDateFormat();
if (!minTime || !maxTime) return;
const excludeRanges = [];
let range = null;
let d = moment(minTime);
while (d.valueOf() <= maxTime) {
if (parser.yy.isInvalidDate(d, dateFormat, excludes, includes)) {
if (!range) {
range = {
start: d.clone(),
end: d.clone(),
};
} else {
range.end = d.clone();
}
} else {
if (range) {
excludeRanges.push(range);
range = null;
}
}
d.add(1, 'd');
}
const rectangles = svg.append('g').selectAll('rect').data(excludeRanges).enter();
rectangles
.append('rect')
.attr('id', function (d) {
return 'exclude-' + d.start.format('YYYY-MM-DD');
})
.attr('x', function (d) {
return timeScale(d.start) + theSidePad;
})
.attr('y', conf.gridLineStartPadding)
.attr('width', function (d) {
const renderEnd = d.end.clone().add(1, 'day');
return timeScale(renderEnd) - timeScale(d.start);
})
.attr('height', h - theTopPad - conf.gridLineStartPadding)
.attr('transform-origin', function (d, i) {
return (
(
timeScale(d.start) +
theSidePad +
0.5 * (timeScale(d.end) - timeScale(d.start))
).toString() +
'px ' +
(i * theGap + 0.5 * h).toString() +
'px'
);
})
.attr('class', 'exclude-range');
}
/**
* @param theSidePad
* @param theTopPad
* @param w
* @param h
*/
function makeGrid(theSidePad, theTopPad, w, h) {
let bottomXAxis = axisBottom(timeScale)
.tickSize(-h + theTopPad + conf.gridLineStartPadding)
@ -378,6 +484,10 @@ export const draw = function (text, id) {
}
}
/**
* @param theGap
* @param theTopPad
*/
function vertLabels(theGap, theTopPad) {
const numOccurances = [];
let prevGap = 0;
@ -431,6 +541,12 @@ export const draw = function (text, id) {
});
}
/**
* @param theSidePad
* @param theTopPad
* @param w
* @param h
*/
function drawToday(theSidePad, theTopPad, w, h) {
const todayMarker = ganttDb.getTodayMarker();
if (todayMarker === 'off') {
@ -453,12 +569,18 @@ export const draw = function (text, id) {
}
}
// from this stackexchange question: http://stackoverflow.com/questions/1890203/unique-for-arrays-in-javascript
/**
* From this stackexchange question:
* http://stackoverflow.com/questions/1890203/unique-for-arrays-in-javascript
*
* @param arr
*/
function checkUnique(arr) {
const hash = {};
const result = [];
for (let i = 0, l = arr.length; i < l; ++i) {
if (!hash.hasOwnProperty(arr[i])) { // eslint-disable-line
if (!Object.prototype.hasOwnProperty.call(hash, arr[i])) {
// eslint-disable-line
// it works with objects! in FF, at least
hash[arr[i]] = true;
result.push(arr[i]);
@ -467,7 +589,12 @@ export const draw = function (text, id) {
return result;
}
// from this stackexchange question: http://stackoverflow.com/questions/14227981/count-how-many-strings-in-an-array-have-duplicates-in-the-same-array
/**
* From this stackexchange 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
@ -477,7 +604,12 @@ export const draw = function (text, id) {
return obj;
}
// get specific from everything
/**
* Get specific from everything
*
* @param word
* @param arr
*/
function getCount(word, arr) {
return getCounts(arr)[word] || 0;
}

View File

@ -70,6 +70,7 @@ that id.
"inclusiveEndDates" return 'inclusiveEndDates';
"topAxis" return 'topAxis';
"axisFormat"\s[^#\n;]+ return 'axisFormat';
"includes"\s[^#\n;]+ return 'includes';
"excludes"\s[^#\n;]+ return 'excludes';
"todayMarker"\s[^\n;]+ return 'todayMarker';
\d\d\d\d"-"\d\d"-"\d\d return 'date';
@ -112,6 +113,7 @@ statement
| topAxis {yy.TopAxis();$$=$1.substr(8);}
| axisFormat {yy.setAxisFormat($1.substr(11));$$=$1.substr(11);}
| excludes {yy.setExcludes($1.substr(9));$$=$1.substr(9);}
| includes {yy.setIncludes($1.substr(9));$$=$1.substr(9);}
| todayMarker {yy.setTodayMarker($1.substr(12));$$=$1.substr(12);}
| title {yy.setTitle($1.substr(6));$$=$1.substr(6);}
| section {yy.addSection($1.substr(8));$$=$1.substr(8);}

View File

@ -4,6 +4,9 @@ const getStyles = (options) =>
font-family: "trebuchet ms", verdana, arial, sans-serif;
font-family: var(--mermaid-font-family);
}
.exclude-range {
fill: ${options.excludeBkgColor};
}
.section {
stroke: none;

View File

@ -11,6 +11,10 @@ function getId() {
return random({ length: 7 });
}
/**
* @param currentCommit
* @param otherCommit
*/
function isfastforwardable(currentCommit, otherCommit) {
log.debug('Entering isfastforwardable:', currentCommit.id, otherCommit.id);
while (currentCommit.seq <= otherCommit.seq && currentCommit !== otherCommit) {
@ -30,6 +34,10 @@ function isfastforwardable(currentCommit, otherCommit) {
return currentCommit.id === otherCommit.id;
}
/**
* @param currentCommit
* @param otherCommit
*/
function isReachableFrom(currentCommit, otherCommit) {
const currentSeq = currentCommit.seq;
const otherSeq = otherCommit.seq;
@ -37,6 +45,10 @@ function isReachableFrom(currentCommit, otherCommit) {
return false;
}
/**
* @param list
* @param fn
*/
function uniqBy(list, fn) {
const recordMap = Object.create(null);
return list.reduce((out, item) => {
@ -138,6 +150,11 @@ export const reset = function (commitRef) {
branches[curBranch] = commit.id;
};
/**
* @param arr
* @param key
* @param newval
*/
function upsert(arr, key, newval) {
const index = arr.indexOf(key);
if (index === -1) {
@ -147,6 +164,7 @@ function upsert(arr, key, newval) {
}
}
/** @param commitArr */
function prettyPrintCommitHistory(commitArr) {
const commit = commitArr.reduce((out, commit) => {
if (out.seq > commit.seq) return out;

View File

@ -21,7 +21,7 @@ describe('when parsing a gitGraph', function() {
afterEach(function() {
cryptoRandomString.mockReset();
});
it('should handle a gitGraph defintion', function() {
it('should handle a gitGraph definition', function() {
const str = 'gitGraph:\n' + 'commit\n';
parser.parse(str);
@ -33,7 +33,7 @@ describe('when parsing a gitGraph', function() {
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
});
it('should handle a gitGraph defintion with empty options', function() {
it('should handle a gitGraph definition with empty options', function() {
const str = 'gitGraph:\n' + 'options\n' + 'end\n' + 'commit\n';
parser.parse(str);
@ -46,7 +46,7 @@ describe('when parsing a gitGraph', function() {
expect(Object.keys(parser.yy.getBranches()).length).toBe(1);
});
it('should handle a gitGraph defintion with valid options', function() {
it('should handle a gitGraph definition with valid options', function() {
const str = 'gitGraph:\n' + 'options\n' + '{"key": "value"}\n' + 'end\n' + 'commit\n';
parser.parse(str);

View File

@ -30,6 +30,7 @@ export const setConf = function (c) {
apiConfig = c;
};
/** @param svg */
function svgCreateDefs(svg) {
svg
.append('defs')
@ -52,6 +53,12 @@ function svgCreateDefs(svg) {
.html('');
}
/**
* @param svg
* @param points
* @param colorIdx
* @param interpolate
*/
function svgDrawLine(svg, points, colorIdx, interpolate) {
const curve = interpolateToCurve(interpolate, curveBasis);
const color = config.branchColors[colorIdx % config.branchColors.length];
@ -72,7 +79,12 @@ function svgDrawLine(svg, points, colorIdx, interpolate) {
.style('fill', 'none');
}
// Pass in the element and its pre-transform coords
/**
* Pass in the element and its pre-transform coords
*
* @param element
* @param coords
*/
function getElementCoords(element, coords) {
coords = coords || element.node().getBBox();
const ctm = element.node().getCTM();
@ -86,6 +98,13 @@ function getElementCoords(element, coords) {
};
}
/**
* @param svg
* @param fromId
* @param toId
* @param direction
* @param color
*/
function svgDrawLineForCommits(svg, fromId, toId, direction, color) {
log.debug('svgDrawLineForCommits: ', fromId, toId);
const fromBbox = getElementCoords(svg.select('#node-' + fromId + ' circle'));
@ -190,10 +209,20 @@ function svgDrawLineForCommits(svg, fromId, toId, direction, color) {
}
}
/**
* @param svg
* @param selector
*/
function cloneNode(svg, selector) {
return svg.select(selector).node().cloneNode(true);
}
/**
* @param svg
* @param commitid
* @param branches
* @param direction
*/
function renderCommitHistory(svg, commitid, branches, direction) {
let commit;
const numCommits = Object.keys(allCommitsDict).length;
@ -276,6 +305,12 @@ function renderCommitHistory(svg, commitid, branches, direction) {
}
}
/**
* @param svg
* @param commit
* @param direction
* @param branchColor
*/
function renderLines(svg, commit, direction, branchColor) {
branchColor = branchColor || 0;
while (commit.seq > 0 && !commit.lineDrawn) {

View File

@ -1,6 +1,4 @@
/**
* Created by knut on 15-01-14.
*/
/** Created by knut on 15-01-14. */
import { log } from '../../logger';
var message = '';

View File

@ -1,6 +1,4 @@
/**
* Created by knut on 14-12-11.
*/
/** Created by knut on 14-12-11. */
import { select } from 'd3';
import db from './infoDb';
import infoParser from './parser/info';
@ -17,16 +15,18 @@ export const setConf = function (cnf) {
/**
* Draws a an info picture in the tag with id: id based on the graph definition in text.
* @param text
* @param id
*
* @param {any} text
* @param {any} id
* @param {any} version
*/
export const draw = (txt, id, ver) => {
export const draw = (text, id, version) => {
try {
const parser = infoParser.parser;
parser.yy = db;
log.debug('Renering info diagram\n' + txt);
log.debug('Renering info diagram\n' + text);
// Parse the graph definition
parser.parse(txt);
parser.parse(text);
log.debug('Parsed info diagram');
// Fetch the default direction, use TD if none was found
const svg = select('#' + id);
@ -39,7 +39,7 @@ export const draw = (txt, id, ver) => {
.attr('class', 'version')
.attr('font-size', '32px')
.style('text-anchor', 'middle')
.text('v ' + ver);
.text('v ' + version);
svg.attr('height', 100);
svg.attr('width', 400);

View File

@ -1,6 +1,3 @@
/**
*
*/
import { log } from '../../logger';
import mermaidAPI from '../../mermaidAPI';
import * as configApi from '../../config';

View File

@ -1,6 +1,4 @@
/**
* Created by AshishJ on 11-09-2019.
*/
/** Created by AshishJ on 11-09-2019. */
import { select, scaleOrdinal, pie as d3pie, arc } from 'd3';
import pieData from './pieDb';
import pieParser from './parser/pie';
@ -12,6 +10,7 @@ let conf = configApi.getConfig();
/**
* Draws a Pie Chart with the data given in text.
*
* @param text
* @param id
*/

View File

@ -1,6 +1,7 @@
import mermaidAPI from '../../mermaidAPI';
import * as configApi from '../../config';
import { log } from '../../logger';
import { sanitizeText } from '../common/common';
let prevActor = undefined;
let actors = {};
@ -219,7 +220,10 @@ export const addLinks = function (actorId, text) {
const actor = getActor(actorId);
// JSON.parse the text
try {
const links = JSON.parse(text.text);
let sanitizedText = sanitizeText(text.text, configApi.getConfig());
sanitizedText = sanitizedText.replace(/&amp;/g, '&');
sanitizedText = sanitizedText.replace(/&equals;/g, '=');
const links = JSON.parse(sanitizedText);
// add the deserialized text to the actor's links field.
insertLinks(actor, links);
} catch (e) {
@ -232,9 +236,12 @@ export const addALink = function (actorId, text) {
const actor = getActor(actorId);
try {
const links = {};
var sep = text.text.indexOf('@');
var label = text.text.slice(0, sep - 1).trim();
var link = text.text.slice(sep + 1).trim();
let sanitizedText = sanitizeText(text.text, configApi.getConfig());
var sep = sanitizedText.indexOf('@');
sanitizedText = sanitizedText.replace(/&amp;/g, '&');
sanitizedText = sanitizedText.replace(/&equals;/g, '=');
var label = sanitizedText.slice(0, sep - 1).trim();
var link = sanitizedText.slice(sep + 1).trim();
links[label] = link;
// add the deserialized text to the actor's links field.
@ -244,6 +251,10 @@ export const addALink = function (actorId, text) {
}
};
/**
* @param {any} actor
* @param {any} links
*/
function insertLinks(actor, links) {
if (actor.links == null) {
actor.links = links;
@ -259,7 +270,8 @@ export const addProperties = function (actorId, text) {
const actor = getActor(actorId);
// JSON.parse the text
try {
const properties = JSON.parse(text.text);
let sanitizedText = sanitizeText(text.text, configApi.getConfig());
const properties = JSON.parse(sanitizedText);
// add the deserialized text to the actor's property field.
insertProperties(actor, properties);
} catch (e) {
@ -267,6 +279,10 @@ export const addProperties = function (actorId, text) {
}
};
/**
* @param {any} actor
* @param {any} properties
*/
function insertProperties(actor, properties) {
if (actor.properties == null) {
actor.properties = properties;

View File

@ -976,7 +976,8 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com
expect(actors.a.links["Tests"]).toBe("https://tests.contoso.com/?svc=alice@contoso.com");
});
it('it should handle properties', function () {
it('it should handle properties EXPERIMENTAL: USE WITH CAUTION', function () {
//Be aware that the syntax for "properties" is likely to be changed.
const str = `
sequenceDiagram
participant a as Alice

View File

@ -97,6 +97,7 @@ export const bounds = {
updateBounds: function (startx, starty, stopx, stopy) {
const _self = this;
let cnt = 0;
/** @param {any} type */
function updateFn(type) {
return function updateItemBounds(item) {
cnt++;
@ -198,8 +199,11 @@ export const bounds = {
/**
* Draws an note in the diagram with the attached line
* @param elem - The diagram to draw to.
* @param noteModel:{x: number, y: number, message: string, width: number} - startx: x axis start position, verticalPos: y axis position, messsage: the message to be shown, width: Set this with a custom width to override the default configured width.
*
* @param {any} elem - The diagram to draw to.
* @param {{ x: number; y: number; message: string; width: number }} noteModel - Startx: x axis
* start position, verticalPos: y axis position, messsage: the message to be shown, width: Set
* this with a custom width to override the default configured width.
*/
const drawNote = function (elem, noteModel) {
bounds.bumpVerticalPos(conf.boxMargin);
@ -268,8 +272,9 @@ const actorFont = (cnf) => {
/**
* Draws a message
* @param g - the parent of the message element
* @param msgModel - the model containing fields describing a message
*
* @param {any} g - The parent of the message element
* @param {any} msgModel - The model containing fields describing a message
*/
const drawMessage = function (g, msgModel) {
bounds.bumpVerticalPos(10);
@ -499,6 +504,13 @@ const activationBounds = function (actor, actors) {
return [left, right];
};
/**
* @param {any} loopWidths
* @param {any} msg
* @param {any} preMargin
* @param {any} postMargin
* @param {any} addLoopFn
*/
function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoopFn) {
bounds.bumpVerticalPos(preMargin);
let heightAdjust = postMargin;
@ -521,8 +533,9 @@ function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoop
/**
* Draws a sequenceDiagram in the tag with id: id based on the graph definition in text.
* @param text
* @param id
*
* @param {any} text
* @param {any} id
*/
export const draw = function (text, id) {
conf = configApi.getConfig().sequence;
@ -556,6 +569,10 @@ export const draw = function (text, id) {
svgDraw.insertArrowFilledHead(diagram);
svgDraw.insertSequenceNumber(diagram);
/**
* @param {any} msg
* @param {any} verticalPos
*/
function activeEnd(msg, verticalPos) {
const activationData = bounds.endActivation(msg);
if (activationData.starty + 18 > verticalPos) {
@ -769,14 +786,14 @@ export const draw = function (text, id) {
};
/**
* Retrieves the max message width of each actor, supports signals (messages, loops)
* and notes.
* Retrieves the max message width of each actor, supports signals (messages, loops) and notes.
*
* It will enumerate each given message, and will determine its text width, in relation
* to the actor it originates from, and destined to.
* It will enumerate each given message, and will determine its text width, in relation to the actor
* it originates from, and destined to.
*
* @param actors - The actors map
* @param messages - A list of message objects to iterate
* @param {any} actors - The actors map
* @param {Array} messages - A list of message objects to iterate
* @returns {any}
*/
const getMaxMessageWidthPerActor = function (actors, messages) {
const maxMessageWidthPerActor = {};
@ -888,14 +905,13 @@ const getRequiredPopupWidth = function (actor) {
};
/**
* This will calculate the optimal margin for each given actor, for a given
* actor->messageWidth map.
* This will calculate the optimal margin for each given actor, for a given actor->messageWidth map.
*
* An actor's margin is determined by the width of the actor, the width of the
* largest message that originates from it, and the configured conf.actorMargin.
* An actor's margin is determined by the width of the actor, the width of the largest message that
* originates from it, and the configured conf.actorMargin.
*
* @param actors - The actors map to calculate margins for
* @param actorToMessageWidth - A map of actor key -> max message width it holds
* @param {any} actors - The actors map to calculate margins for
* @param {any} actorToMessageWidth - A map of actor key -> max message width it holds
*/
const calculateActorMargins = function (actors, actorToMessageWidth) {
let maxHeight = 0;

View File

@ -1,4 +1,5 @@
import common from '../common/common';
import { addFunction } from '../../interactionDb';
export const drawRect = function (elem, rectData) {
const rectElem = elem.append('rect');
@ -25,6 +26,17 @@ const sanitizeUrl = function (s) {
.replace(/javascript:/g, '');
};
const addPopupInteraction = (id, actorCnt) => {
addFunction(() => {
const arr = document.querySelectorAll(id);
arr[0].addEventListener('mouseover', function () {
popupMenuUpFunc('actor' + actorCnt + '_popup');
});
arr[0].addEventListener('mouseout', function () {
popupMenuDownFunc('actor' + actorCnt + '_popup');
});
});
};
export const drawPopup = function (elem, actor, minMenuWidth, textAttrs, forceMenus) {
if (actor.links === undefined || actor.links === null || Object.keys(actor.links).length === 0) {
return { height: 0, width: 0 };
@ -43,9 +55,7 @@ export const drawPopup = function (elem, actor, minMenuWidth, textAttrs, forceMe
g.attr('id', 'actor' + actorCnt + '_popup');
g.attr('class', 'actorPopupMenu');
g.attr('display', displayValue);
g.attr('onmouseover', popupMenu('actor' + actorCnt + '_popup'));
g.attr('onmouseout', popdownMenu('actor' + actorCnt + '_popup'));
addPopupInteraction('#actor' + actorCnt + '_popup', actorCnt);
var actorClass = '';
if (typeof rectData.class !== 'undefined') {
actorClass = ' ' + rectData.class;
@ -123,6 +133,19 @@ export const popdownMenu = function (popid) {
);
};
const popupMenuUpFunc = function (popupId) {
var pu = document.getElementById(popupId);
if (pu != null) {
pu.style.display = 'block';
}
};
const popupMenuDownFunc = function (popupId) {
var pu = document.getElementById(popupId);
if (pu != null) {
pu.style.display = 'none';
}
};
export const drawText = function (elem, textData) {
let prevTextHeight = 0,
textHeight = 0;
@ -252,6 +275,14 @@ export const drawText = function (elem, textData) {
};
export const drawLabel = function (elem, txtObject) {
/**
* @param {any} x
* @param {any} y
* @param {any} width
* @param {any} height
* @param {any} cut
* @returns {any}
*/
function genPoints(x, y, width, height, cut) {
return (
x +
@ -297,9 +328,10 @@ export const fixLifeLineHeights = (diagram, bounds) => {
/**
* Draws an actor in the diagram with the attached line
* @param elem - The diagram we'll draw to.
* @param actor - The actor to draw.
* @param conf - drawText implementation discriminator object
*
* @param {any} elem - The diagram we'll draw to.
* @param {any} actor - The actor to draw.
* @param {any} conf - DrawText implementation discriminator object
*/
const drawActorTypeParticipant = function (elem, actor, conf) {
const center = actor.x + actor.width / 2;
@ -321,9 +353,10 @@ const drawActorTypeParticipant = function (elem, actor, conf) {
g = boxpluslineGroup.append('g');
actor.actorCnt = actorCnt;
if (actor.links != null) {
g.attr('onmouseover', popupMenu('actor' + actorCnt + '_popup'));
g.attr('onmouseout', popdownMenu('actor' + actorCnt + '_popup'));
g.attr('id', 'root-' + actorCnt);
addPopupInteraction('#root-' + actorCnt, actorCnt);
}
}
@ -370,6 +403,7 @@ const drawActorTypeParticipant = function (elem, actor, conf) {
actor.height = bounds.height;
height = bounds.height;
}
return height;
};
@ -469,11 +503,12 @@ export const anchorElement = function (elem) {
};
/**
* Draws an activation in the diagram
* @param elem - element to append activation rect.
* @param bounds - activation box bounds.
* @param verticalPos - precise y cooridnate of bottom activation box edge.
* @param conf - sequence diagram config object.
* @param actorActivations - number of activations on the actor.
*
* @param {any} elem - Element to append activation rect.
* @param {any} bounds - Activation box bounds.
* @param {any} verticalPos - Precise y cooridnate of bottom activation box edge.
* @param {any} conf - Sequence diagram config object.
* @param {any} actorActivations - Number of activations on the actor.
*/
export const drawActivation = function (elem, bounds, verticalPos, conf, actorActivations) {
const rect = getNoteRect();
@ -488,10 +523,12 @@ export const drawActivation = function (elem, bounds, verticalPos, conf, actorAc
/**
* Draws a loop in the diagram
* @param elem - elemenet to append the loop to.
* @param loopModel - loopModel of the given loop.
* @param labelText - Text within the loop.
* @param conf - diagrom configuration
*
* @param {any} elem - Elemenet to append the loop to.
* @param {any} loopModel - LoopModel of the given loop.
* @param {any} labelText - Text within the loop.
* @param {any} conf - Diagrom configuration
* @returns {any}
*/
export const drawLoop = function (elem, loopModel, labelText, conf) {
const {
@ -588,8 +625,9 @@ export const drawLoop = function (elem, loopModel, labelText, conf) {
/**
* Draws a background rectangle
* @param elem diagram (reference for bounds)
* @param bounds shape of the rectangle
*
* @param {any} elem Diagram (reference for bounds)
* @param {any} bounds Shape of the rectangle
*/
export const drawBackgroundRect = function (elem, bounds) {
const rectElem = drawRect(elem, {
@ -650,6 +688,8 @@ export const insertClockIcon = function (elem) {
/**
* Setup arrow head and define the marker. The result is appended to the svg.
*
* @param elem
*/
export const insertArrowHead = function (elem) {
elem
@ -667,6 +707,8 @@ export const insertArrowHead = function (elem) {
};
/**
* Setup arrow head and define the marker. The result is appended to the svg.
*
* @param {any} elem
*/
export const insertArrowFilledHead = function (elem) {
elem
@ -683,6 +725,8 @@ export const insertArrowFilledHead = function (elem) {
};
/**
* Setup node number. The result is appended to the svg.
*
* @param {any} elem
*/
export const insertSequenceNumber = function (elem) {
elem
@ -702,6 +746,8 @@ export const insertSequenceNumber = function (elem) {
};
/**
* Setup arrow head and define the marker. The result is appended to the svg.
*
* @param {any} elem
*/
export const insertArrowCrossHead = function (elem) {
const defs = elem.append('defs');
@ -766,6 +812,15 @@ export const getNoteRect = function () {
};
const _drawTextCandidateFunc = (function () {
/**
* @param {any} content
* @param {any} g
* @param {any} x
* @param {any} y
* @param {any} width
* @param {any} height
* @param {any} textAttrs
*/
function byText(content, g, x, y, width, height, textAttrs) {
const text = g
.append('text')
@ -776,6 +831,16 @@ const _drawTextCandidateFunc = (function () {
_setTextAttrs(text, textAttrs);
}
/**
* @param {any} content
* @param {any} g
* @param {any} x
* @param {any} y
* @param {any} width
* @param {any} height
* @param {any} textAttrs
* @param {any} conf
*/
function byTspan(content, g, x, y, width, height, textAttrs, conf) {
const { actorFontSize, actorFontFamily, actorFontWeight } = conf;
@ -805,6 +870,16 @@ const _drawTextCandidateFunc = (function () {
}
}
/**
* @param {any} content
* @param {any} g
* @param {any} x
* @param {any} y
* @param {any} width
* @param {any} height
* @param {any} textAttrs
* @param {any} conf
*/
function byFo(content, g, x, y, width, height, textAttrs, conf) {
const s = g.append('switch');
const f = s
@ -831,6 +906,10 @@ const _drawTextCandidateFunc = (function () {
_setTextAttrs(text, textAttrs);
}
/**
* @param {any} toText
* @param {any} fromTextAttrsDict
*/
function _setTextAttrs(toText, fromTextAttrsDict) {
for (const key in fromTextAttrsDict) {
if (fromTextAttrsDict.hasOwnProperty(key)) { // eslint-disable-line
@ -845,6 +924,15 @@ const _drawTextCandidateFunc = (function () {
})();
const _drawMenuItemTextCandidateFunc = (function () {
/**
* @param {any} content
* @param {any} g
* @param {any} x
* @param {any} y
* @param {any} width
* @param {any} height
* @param {any} textAttrs
*/
function byText(content, g, x, y, width, height, textAttrs) {
const text = g
.append('text')
@ -855,6 +943,16 @@ const _drawMenuItemTextCandidateFunc = (function () {
_setTextAttrs(text, textAttrs);
}
/**
* @param {any} content
* @param {any} g
* @param {any} x
* @param {any} y
* @param {any} width
* @param {any} height
* @param {any} textAttrs
* @param {any} conf
*/
function byTspan(content, g, x, y, width, height, textAttrs, conf) {
const { actorFontSize, actorFontFamily, actorFontWeight } = conf;
@ -880,6 +978,16 @@ const _drawMenuItemTextCandidateFunc = (function () {
}
}
/**
* @param {any} content
* @param {any} g
* @param {any} x
* @param {any} y
* @param {any} width
* @param {any} height
* @param {any} textAttrs
* @param {any} conf
*/
function byFo(content, g, x, y, width, height, textAttrs, conf) {
const s = g.append('switch');
const f = s
@ -906,6 +1014,10 @@ const _drawMenuItemTextCandidateFunc = (function () {
_setTextAttrs(text, textAttrs);
}
/**
* @param {any} toText
* @param {any} fromTextAttrsDict
*/
function _setTextAttrs(toText, fromTextAttrsDict) {
for (const key in fromTextAttrsDict) {
if (fromTextAttrsDict.hasOwnProperty(key)) { // eslint-disable-line

View File

@ -6,10 +6,10 @@ import common from '../common/common';
import { getConfig } from '../../config';
import { log } from '../../logger';
// let conf;
/**
* Draws a start state as a black circle
*
* @param {any} g
*/
export const drawStartState = (g) =>
g
@ -23,6 +23,8 @@ export const drawStartState = (g) =>
/**
* Draws a start state as a black circle
*
* @param {any} g
*/
export const drawDivider = (g) =>
g
@ -37,6 +39,9 @@ export const drawDivider = (g) =>
/**
* Draws a an end state as a black circle
*
* @param {any} g
* @param {any} stateDef
*/
export const drawSimpleState = (g, stateDef) => {
const state = g
@ -60,8 +65,10 @@ export const drawSimpleState = (g, stateDef) => {
/**
* Draws a state with descriptions
* @param {*} g
* @param {*} stateDef
*
* @param {any} g
* @param {any} stateDef
* @returns
*/
export const drawDescrState = (g, stateDef) => {
const addTspan = function (textEl, txt, isFirst) {
@ -128,15 +135,14 @@ export const drawDescrState = (g, stateDef) => {
return g;
};
/**
* Adds the creates a box around the existing content and adds a
* panel for the id on top of the content.
*/
/** Adds the creates a box around the existing content and adds a panel for the id on top of the content. */
/**
* Function that creates an title row and a frame around a substate for a composit state diagram.
* The function returns a new d3 svg object with updated width and height properties;
* @param {*} g The d3 svg object for the substate to framed
* @param {*} stateDef The info about the
*
* @param {any} g The d3 svg object for the substate to framed
* @param {any} stateDef The info about the
* @param {any} altBkg
*/
export const addTitleAndBox = (g, stateDef, altBkg) => {
const pad = getConfig().state.padding;
@ -337,6 +343,7 @@ const _drawLongText = (_text, x, y, g) => {
/**
* Draws a note to the diagram
*
* @param text - The text of the given note.
* @param g - The element the note is attached to.
*/
@ -354,10 +361,11 @@ export const drawNote = (text, g) => {
};
/**
* Starting point for drawing a state. The function finds out the specifics
* about the state and renders with approprtiate function.
* @param {*} elem
* @param {*} stateDef
* Starting point for drawing a state. The function finds out the specifics about the state and
* renders with approprtiate function.
*
* @param {any} elem
* @param {any} stateDef
*/
export const drawState = function (elem, stateDef) {

View File

@ -117,10 +117,12 @@ let endCnt = 0; // eslint-disable-line
/**
* Function called by parser when a node definition has been found.
* @param id
* @param text
* @param type
* @param style
*
* @param {any} id
* @param {any} type
* @param {any} doc
* @param {any} descr
* @param {any} note
*/
export const addState = function (id, type, doc, descr, note) {
if (typeof currentDocument.states[id] === 'undefined') {

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