Merge branch 'release/8.10.2'
This commit is contained in:
commit
5251dfaa97
|
@ -53,5 +53,10 @@ describe('XSS', () => {
|
|||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
})
|
||||
it('should not allow maniplulating htmlLabels into a false positive', () => {
|
||||
cy.visit('http://localhost:9000/xss4.html');
|
||||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
})
|
||||
|
||||
})
|
||||
|
|
|
@ -371,25 +371,25 @@ flowchart TD
|
|||
E[(red text)] -->|default style| F((blue text))
|
||||
G>red text] -->|default style| H{blue text}
|
||||
I{{red text}} -->|default style| J[/blue text/]
|
||||
K[\ red text\] -->|default style| L[/blue text\]
|
||||
M[\ red text/] -->|default style| N[blue text]
|
||||
K[\\ red text\\] -->|default style| L[/blue text\\]
|
||||
M[\\ red text/] -->|default style| N[blue text];
|
||||
linkStyle default color:Sienna;
|
||||
style A stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style B stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
style C stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style D stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
style E stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style F stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
style G stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style H stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
style I stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style J stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
style K stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style L stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
style M stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style N stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
style A stroke:#ff0000,fill:#ffcccc,color:#ff0000;
|
||||
style B stroke:#0000ff,fill:#ccccff,color:#0000ff;
|
||||
style C stroke:#ff0000,fill:#ffcccc,color:#ff0000;
|
||||
style D stroke:#0000ff,fill:#ccccff,color:#0000ff;
|
||||
style E stroke:#ff0000,fill:#ffcccc,color:#ff0000;
|
||||
style F stroke:#0000ff,fill:#ccccff,color:#0000ff;
|
||||
style G stroke:#ff0000,fill:#ffcccc,color:#ff0000;
|
||||
style H stroke:#0000ff,fill:#ccccff,color:#0000ff;
|
||||
style I stroke:#ff0000,fill:#ffcccc,color:#ff0000;
|
||||
style J stroke:#0000ff,fill:#ccccff,color:#0000ff;
|
||||
style K stroke:#ff0000,fill:#ffcccc,color:#ff0000;
|
||||
style L stroke:#0000ff,fill:#ccccff,color:#0000ff;
|
||||
style M stroke:#ff0000,fill:#ffcccc,color:#ff0000;
|
||||
style N stroke:#0000ff,fill:#ccccff,color:#0000ff;
|
||||
`,
|
||||
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
|
||||
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose', logLevel:2}
|
||||
);
|
||||
});
|
||||
it('61: fontawesome icons in edge labels', () => {
|
||||
|
@ -610,4 +610,27 @@ flowchart RL
|
|||
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
|
||||
);
|
||||
});
|
||||
|
||||
it('2050: handling of different rendering direction in subgraphs', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
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
|
||||
`,
|
||||
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -401,7 +401,7 @@ stateDiagram-v2
|
|||
it('v2 should handle different rendering directions in composite states', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
stateDiagram
|
||||
stateDiagram-v2
|
||||
direction LR
|
||||
state A {
|
||||
direction BT
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
const div = parent.document.createElement('div');
|
||||
div.id = 'the-malware';
|
||||
div.className = 'malware';
|
||||
div.innerHTML = 'XSS Succeeded';
|
||||
parent.document.getElementsByTagName('body')[0].appendChild(div);
|
||||
throw new Error('XSS Succeded');
|
|
@ -15,7 +15,7 @@
|
|||
/* font-size: 18px !important; */
|
||||
}
|
||||
h1 { color: grey;}
|
||||
.mermaid2 {
|
||||
.mermaid2,.mermaid3 {
|
||||
display: none;
|
||||
}
|
||||
.mermaid svg {
|
||||
|
@ -27,14 +27,27 @@
|
|||
<div>info below</div>
|
||||
<div class="flex">
|
||||
|
||||
<div class="mermaid" style="width: 100%; height: 20%;">
|
||||
<div class="mermaid3" style="width: 100%; height: 20%;">
|
||||
stateDiagram-v2
|
||||
state S1 {
|
||||
sub1 -->sub2
|
||||
}
|
||||
|
||||
state S2 {
|
||||
sub4
|
||||
}
|
||||
S1 --> S2
|
||||
sub1 --> sub4
|
||||
|
||||
</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%;">
|
||||
<div class="mermaid3" style="width: 100%; height: 20%;">
|
||||
flowchart
|
||||
subgraph CompositeState
|
||||
subgraph AnotherCompositeStateCompositeStateCompositeStateCompositeState
|
||||
|
@ -43,7 +56,7 @@ subgraph CompositeState
|
|||
|
||||
end
|
||||
</div>
|
||||
<div class="mermaid" style="width: 100%; height: 20%;">
|
||||
<div class="mermaid3" style="width: 100%; height: 20%;">
|
||||
stateDiagram-v2
|
||||
state CompositeState {
|
||||
state AnotherCompositeState1234567890 {
|
||||
|
@ -52,14 +65,18 @@ stateDiagram-v2
|
|||
}
|
||||
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%; height: 20%;">
|
||||
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!
|
||||
note right of John: Hello note reader
|
||||
</div>
|
||||
<div class="mermaid" style="width: 100%; height: 20%;">
|
||||
%%{init:{"theme":"forest", "themeVariables": {
|
||||
"specialStateColor":"red",
|
||||
"innerEndBackground":"lightgreen"
|
||||
}}}%%
|
||||
stateDiagram-v2
|
||||
state fork [[fork]]
|
||||
state join [[join]]
|
||||
[*] --> fork
|
||||
fork --> join
|
||||
join --> [*]
|
||||
</div>
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.parseError = function (err, hash) {
|
||||
|
|
|
@ -21,155 +21,28 @@
|
|||
.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>info below</div>
|
||||
<div>Security check</div>
|
||||
<div class="flex">
|
||||
<div class="mermaid2" style="width: 100%; height: 400px;">
|
||||
%%{init: { "logLevel": 1, "er": {"fontSize":18 }} }%%
|
||||
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"
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 50%; height: 400px;">
|
||||
flowchart TD
|
||||
A[Christmas] ==> D
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
A[Christmas] ==> C
|
||||
subgraph T ["Test"]
|
||||
A
|
||||
B
|
||||
C
|
||||
end
|
||||
|
||||
classDef Test fill:#F84E68,stroke:#333,color:white;
|
||||
class A,T Test
|
||||
classDef TestSub fill:green;
|
||||
class T TestSub
|
||||
linkStyle 0,1 color:orange, stroke: orange;
|
||||
</div>
|
||||
<div class="mermaid" style="width: 100%; height: 20%;">
|
||||
graph TD
|
||||
subgraph S1
|
||||
sub1 -->sub2
|
||||
end
|
||||
subgraph S2
|
||||
sub4
|
||||
end
|
||||
S1 --> S2
|
||||
sub1 --> sub4
|
||||
</div>
|
||||
<div class="mermaid" style="width: 100%; height: 20%;">
|
||||
graph TB
|
||||
A --> B
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%; height: 20%;">
|
||||
stateDiagram-v2
|
||||
state S1 {
|
||||
sub1 -->sub2
|
||||
}
|
||||
state S2 {
|
||||
sub4
|
||||
}
|
||||
S1 --> S2
|
||||
sub1 --> sub4
|
||||
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%; height: 20%;">
|
||||
requirementDiagram
|
||||
requirement test_req {
|
||||
id: 1
|
||||
text: the test text.
|
||||
risk: high
|
||||
verifymethod: test
|
||||
}
|
||||
|
||||
functionalRequirement test_req2 {
|
||||
id: 1.1
|
||||
text: the second test text.
|
||||
risk: low
|
||||
verifymethod: inspection
|
||||
}
|
||||
|
||||
performanceRequirement test_req3 {
|
||||
id: 1.2
|
||||
text: the third test text.
|
||||
risk: medium
|
||||
verifymethod: demonstration
|
||||
}
|
||||
|
||||
element test_entity {
|
||||
type: simulation
|
||||
}
|
||||
|
||||
element test_entity2 {
|
||||
type: word doc
|
||||
docRef: reqs/test_entity
|
||||
}
|
||||
|
||||
|
||||
test_entity - satisfies -> test_req2
|
||||
test_req - traces -> test_req2
|
||||
test_req - contains -> test_req3
|
||||
test_req <- copies - test_entity2
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 50%; height: 20%;">
|
||||
flowchart LR
|
||||
classDef dark fill:#000,stroke:#000,stroke-width:4px,color:#fff
|
||||
Lorem --> Ipsum --> Dolor
|
||||
class Lorem,Dolor dark
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 50%; height: 20%;">
|
||||
%%{init: {'theme': 'base' }}%%
|
||||
%%{init2: { 'logLevel': 0, 'theme': 'forest'} }%%
|
||||
flowchart TD
|
||||
L1 --- L2
|
||||
L2 --- C
|
||||
M1 ---> C
|
||||
R1 .-> R2
|
||||
R2 <.-> C
|
||||
C -->|Label 1| E1
|
||||
C <-- Label 2 ---> E2
|
||||
C ----> E3
|
||||
C <-...-> E4
|
||||
C ======> E5
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 50%; height: 21%;">
|
||||
flowchart LR
|
||||
A[red text] -->|default style| B(blue text)
|
||||
C([red text]) -->|default style| D[[blue text]]
|
||||
E[(red text)] -->|default style| F((blue text))
|
||||
G>red text] -->|default style| H{blue text}
|
||||
I{{red text}} -->|default style| J[/blue text/]
|
||||
K[
|
||||
ed text] -->|default style| L[/blue text]
|
||||
M[
|
||||
ed text/] -->|default style| N[blue text]
|
||||
linkStyle default color:Sienna;
|
||||
style A stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style B stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
style C stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style D stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
style E stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style F stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
style G stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style H stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
style I stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style J stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
style K stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style L stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
style M stroke:#ff0000,fill:#ffcccc,color:#ff0000
|
||||
style N stroke:#0000ff,fill:#ccccff,color:#0000ff
|
||||
</div>
|
||||
|
||||
|
||||
<div id="diagram" class="mermaid"></div>
|
||||
<div id="res" class=""></div>
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.parseError = function (err, hash) {
|
||||
|
@ -187,7 +60,7 @@ style N stroke:#0000ff,fill:#ccccff,color:#0000ff
|
|||
// defaultRenderer: 'dagre-wrapper',
|
||||
nodeSpacing: 10, curve: 'cardinal', htmlLabels: true
|
||||
},
|
||||
htmlLabels: true,
|
||||
htmlLabels: false,
|
||||
// gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorFontFamily: 'courier',actorMargin: 50, showSequenceNumbers: false },
|
||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||
|
@ -195,10 +68,26 @@ style N stroke:#0000ff,fill:#ccccff,color:#0000ff
|
|||
// fontFamily: 'courier',
|
||||
fontSize: 18,
|
||||
curve: 'basis',
|
||||
securityLevel: 'loose',
|
||||
securityLevel: 'strict',
|
||||
startOnLoad: false
|
||||
// themeVariables: {relationLabelColor: 'red'}
|
||||
});
|
||||
function callback(){alert('It worked');}
|
||||
|
||||
var diagram = "%%{init: {\"flowchart\": {\"htmlLabels\": \"false\"}} }%%\n";
|
||||
diagram += "flowchart\n";
|
||||
diagram += "A[\"<ifra";
|
||||
diagram += "me srcdoc='<scrip";
|
||||
diagram += "t src=http://localhost:9000/exploit.js>";
|
||||
diagram += "</scr"
|
||||
diagram += "ipt>'></iframe>\"]";
|
||||
|
||||
console.log(diagram);
|
||||
// document.querySelector('#diagram').innerHTML = diagram;
|
||||
mermaid.render('diagram', diagram, (res) => {
|
||||
document.querySelector('#res').innerHTML = res;
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
<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-wrapper',
|
||||
},
|
||||
flowchart: {
|
||||
// defaultRenderer: 'dagre-wrapper',
|
||||
nodeSpacing: 10, curve: 'cardinal', htmlLabels: true
|
||||
},
|
||||
htmlLabels: false,
|
||||
// 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: 'strict',
|
||||
startOnLoad: false,
|
||||
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize']
|
||||
// themeVariables: {relationLabelColor: 'red'}
|
||||
});
|
||||
function callback(){alert('It worked');}
|
||||
|
||||
var diagram = "%%{init: {\"flowchart\": {\"htmlLabels\": \"true\"}} }%%\n";
|
||||
diagram += "flowchart\n";
|
||||
diagram += "A[\"<ifra";
|
||||
diagram += "me srcdoc='<scrip";
|
||||
diagram += "t src=http://localhost:9000/exploit.js>";
|
||||
diagram += "</scr"
|
||||
diagram += "ipt>'></iframe>\"]";
|
||||
|
||||
console.log(diagram);
|
||||
// document.querySelector('#diagram').innerHTML = diagram;
|
||||
mermaid.render('diagram', diagram, (res) => {
|
||||
document.querySelector('#res').innerHTML = res;
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 134 KiB |
Binary file not shown.
After Width: | Height: | Size: 153 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -2,12 +2,12 @@
|
|||
|
||||
**Edit this Page** [![N|Solid](img/GitHub-Mark-32px.png)](https://github.com/mermaid-js/mermaid/blob/develop/docs/flowchart.md)
|
||||
|
||||
All Flowcharts are composed of **nodes**, the geometric shapes and **edges**, the arrows or lines. The mermaid code defines the way that these **nodes** and **edges** are made and interact.
|
||||
All Flowcharts are composed of **nodes**, the geometric shapes and **edges**, the arrows or lines. The mermaid code defines the way that these **nodes** and **edges** are made and interact.
|
||||
|
||||
It can also accomodate different arrow types, multi directional arrows, and linking to and from subgraphs.
|
||||
|
||||
> **Important note**: Do not type the word "end" as a Flowchart node. Capitalize all or any one the letters to keep the flowchart from breaking, i.e, "End" or "END". Or you can apply this [workaround](https://github.com/mermaid-js/mermaid/issues/1444#issuecomment-639528897).**
|
||||
Node
|
||||
Node
|
||||
### A node (default)
|
||||
|
||||
```
|
||||
|
@ -585,6 +585,45 @@ flowchart TB
|
|||
two --> c2
|
||||
```
|
||||
|
||||
## Direction in subgraphs
|
||||
|
||||
With the graphtype flowcharts you can use the direction state4ment to set the direction which the subgraph will render like in this example.
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
```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'`.
|
||||
|
|
|
@ -112,6 +112,8 @@ They also serve as proof of concept, for the variety of things that can be built
|
|||
- [iodide-mermaid-plugin](https://github.com/iodide-project/iodide-mermaid-plugin)
|
||||
- [Google docs](https://docs.google.com/)
|
||||
- [Mermaid plugin for google docs](https://workspace.google.com/marketplace/app/mermaid/636321283856)
|
||||
- [Podlite](https://github.com/zag/podlite-desktop)
|
||||
- [Named block =Diagram](https://github.com/zag/podlite/tree/main/packages/podlite-diagrams)
|
||||
|
||||
## Document Generation
|
||||
|
||||
|
|
|
@ -2,27 +2,27 @@
|
|||
|
||||
**Explaining with a Diagram**
|
||||
|
||||
A picture is worth a thousand words, a good diagram is certainly worth more.
|
||||
A picture is worth a thousand words, a good diagram is undoubtedly worth more. They make understanding easier.
|
||||
|
||||
## Creating and Maintaining Diagrams
|
||||
|
||||
Anyone who has used Visio, or (God Forbid) Excel to make a Gantt Chart, knows how hard it is to make, edit and maintain good visualizations.
|
||||
Anyone who has used Visio, or (God Forbid) Excel to make a Gantt Chart, knows how hard it is to create, edit and maintain good visualizations.
|
||||
|
||||
Diagrams/Charts are both very important but also become obsolete/inaccurate very fast. This catch-22 hobbles the productivity of teams.
|
||||
Diagrams/Charts are significant but also become obsolete/inaccurate very fast. This catch-22 hobbles the productivity of teams.
|
||||
|
||||
# Doc Rot in Diagrams
|
||||
|
||||
Doc-Rot kills diagrams as quickly as it does text, but it takes hours in a desktop application to produce a diagram.
|
||||
|
||||
mermaid seeks to change that. mermaid creates diagrams using markdown inspired syntax. The process is quicker, less complicated and more convenient way of going from concept to visualization
|
||||
Mermaid seeks to change using markdown-inspired syntax. The process is a quicker, less complicated, and more convenient way of going from concept to visualization.
|
||||
|
||||
This is a relatively straightforward solution to a major hurdle in software teams.
|
||||
It is a relatively straightforward solution to a significant hurdle with the software teams.
|
||||
|
||||
# Definition of Terms/ Dictionary
|
||||
|
||||
**Mermaid text definitions can be saved for later reuse and editing.**
|
||||
|
||||
>These are the Mermaid diagram deffinitions inside `<div>` tags, with the `class=mermaid`.
|
||||
>These are the Mermaid diagram definitions inside `<div>` tags, with the `class=mermaid`.
|
||||
|
||||
```html
|
||||
<div class="mermaid">
|
||||
|
@ -35,33 +35,33 @@ This is a relatively straightforward solution to a major hurdle in software team
|
|||
|
||||
**render**
|
||||
|
||||
>This is the core function of the Mermaid API, it reads all the `Mermaid Definitions` inside `div` tags and returns an SVG file, based on the definitions.
|
||||
>This is the core function of the Mermaid API. It reads all the `Mermaid Definitions` inside `div` tags and returns an SVG file, based on the definition.
|
||||
|
||||
|
||||
**Nodes**
|
||||
|
||||
>These are the boxes that contain text or otherwise discrete pieces of each diagram, separated generally by arrows, except for Gantt Charts and User Journey Diagrams. They will be referred to often in the instructions. Read for Diagram Specific [Syntax](./n00b-syntaxReference)
|
||||
>These are the boxes that contain text or otherwise discrete pieces of each diagram, separated generally by arrows, except for Gantt Charts and User Journey Diagrams. They will be referred often in the instructions. Read for Diagram Specific [Syntax](./n00b-syntaxReference)
|
||||
|
||||
## Advantages of Using Mermaid
|
||||
## Advantages of using Mermaid
|
||||
|
||||
- Ease of generate, modify and render diagrams, when you make
|
||||
- Ease to generate, modify and render diagrams when you make them.
|
||||
- The number of integrations and plugins it has.
|
||||
- It can be added to your or your company's website.
|
||||
- You can add it to your or companies website.
|
||||
- Diagrams can be created through comments like this in a script:
|
||||
|
||||
## The catch-22 of Diagrams and Charts:
|
||||
|
||||
**Diagramming and charting is a gigantic waste of developer time, but not having diagrams ruins productivity.**
|
||||
**Diagramming and charting is a large waste of developer's time, but not having diagrams ruins productivity.**
|
||||
|
||||
mermaid solves this by cutting the time, effort and tooling that is required to create diagrams and charts.
|
||||
Mermaid solves this by reducing the timeand effort required to create diagrams and charts.
|
||||
|
||||
Because, the text base for diagrams allows for it to be updated easily, it can also be made part of production scripts (and other pieces of code). So less time needs be spent on documenting, as a separate task.
|
||||
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.
|
||||
|
||||
|
||||
## Catching up with Development
|
||||
|
||||
Being based on markdown, mermaid can be used, not only by accomplished front-end developers, but by most computer savvy people to render diagrams, at much faster speeds.
|
||||
In fact one can pick up the syntax for it quite easily from the examples given and there are many tutorials in the internet.
|
||||
Being based on markdown, Mermaid can be used, not only by accomplished front-end developers, but by most computer savvy people to render diagrams, at much faster speeds.
|
||||
In fact one can pick up the syntax for it quite easily from the examples given and there are many tutorials available in the internet.
|
||||
|
||||
## Mermaid is for everyone.
|
||||
Video [Tutorials](https://mermaid-js.github.io/mermaid/#/./Tutorials) are also available for the mermaid [live editor](https://mermaid-js.github.io/mermaid-live-editor/).
|
||||
|
|
|
@ -228,6 +228,28 @@ stateDiagram-v2
|
|||
|
||||
*You can not define transitions between internal states belonging to different composite states*
|
||||
|
||||
## Choice
|
||||
|
||||
Sometimes you need to model a choice between two or more paths, you can do so using <<choice>>.
|
||||
|
||||
```
|
||||
stateDiagram-v2
|
||||
state if_state <<choice>>
|
||||
[*] --> IsPositive
|
||||
IsPositive --> if_state
|
||||
if_state --> False: if n < 0
|
||||
if_state --> True : if n >= 0
|
||||
```
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
state if_state <<choice>>
|
||||
[*] --> IsPositive
|
||||
IsPositive --> if_state
|
||||
if_state --> False: if n < 0
|
||||
if_state --> True : if n >= 0
|
||||
```
|
||||
|
||||
## Forks
|
||||
|
||||
It is possible to specify a fork in the diagram using <<fork>> <<join>>.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "mermaid",
|
||||
"version": "8.10.1",
|
||||
"version": "8.10.2",
|
||||
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
||||
"main": "dist/mermaid.core.js",
|
||||
"keywords": [
|
||||
|
|
|
@ -3,6 +3,7 @@ import { log } from '../logger';
|
|||
import createLabel from './createLabel';
|
||||
import { select } from 'd3';
|
||||
import { getConfig } from '../config';
|
||||
import { evaluate } from '../diagrams/common/common';
|
||||
|
||||
const rect = (parent, node) => {
|
||||
log.trace('Creating subgraph rect for ', node.id, node);
|
||||
|
@ -26,7 +27,7 @@ const rect = (parent, node) => {
|
|||
// Get the size of the label
|
||||
let bbox = text.getBBox();
|
||||
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
const div = text.children[0];
|
||||
const dv = select(text);
|
||||
bbox = div.getBoundingClientRect();
|
||||
|
@ -37,15 +38,22 @@ const rect = (parent, node) => {
|
|||
const padding = 0 * node.padding;
|
||||
const halfPadding = padding / 2;
|
||||
|
||||
const width = node.width <= bbox.width + padding ? bbox.width + padding : node.width;
|
||||
if (node.width <= bbox.width + padding) {
|
||||
node.diff = (bbox.width - node.width) / 2;
|
||||
} else {
|
||||
node.diff = -node.padding / 2;
|
||||
}
|
||||
|
||||
log.trace('Data ', node, JSON.stringify(node));
|
||||
// center the rect around its coordinate
|
||||
rect
|
||||
.attr('style', node.style)
|
||||
.attr('rx', node.rx)
|
||||
.attr('ry', node.ry)
|
||||
.attr('x', node.x - node.width / 2 - halfPadding)
|
||||
.attr('x', node.x - width / 2)
|
||||
.attr('y', node.y - node.height / 2 - halfPadding)
|
||||
.attr('width', node.width + padding)
|
||||
.attr('width', width)
|
||||
.attr('height', node.height + padding);
|
||||
|
||||
// Center the label
|
||||
|
@ -125,7 +133,7 @@ const roundedWithTitle = (parent, node) => {
|
|||
|
||||
// Get the size of the label
|
||||
let bbox = text.getBBox();
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
const div = text.children[0];
|
||||
const dv = select(text);
|
||||
bbox = div.getBoundingClientRect();
|
||||
|
@ -136,10 +144,11 @@ const roundedWithTitle = (parent, node) => {
|
|||
const padding = 0 * node.padding;
|
||||
const halfPadding = padding / 2;
|
||||
|
||||
const width =
|
||||
node.width > bbox.width + node.padding ? node.width + node.padding : bbox.width + node.padding;
|
||||
const width = node.width <= bbox.width + node.padding ? bbox.width + node.padding : node.width;
|
||||
if (node.width <= bbox.width + node.padding) {
|
||||
node.diff = (bbox.width - node.width) / 2;
|
||||
node.diff = (bbox.width + node.padding - node.width) / 2;
|
||||
} else {
|
||||
node.diff = -node.padding / 2;
|
||||
}
|
||||
|
||||
// center the rect around its coordinate
|
||||
|
@ -162,7 +171,10 @@ const roundedWithTitle = (parent, node) => {
|
|||
'translate(' +
|
||||
(node.x - bbox.width / 2) +
|
||||
', ' +
|
||||
(node.y - node.height / 2 - node.padding / 3 + (getConfig().flowchart.htmlLabels ? 5 : 3)) +
|
||||
(node.y -
|
||||
node.height / 2 -
|
||||
node.padding / 3 +
|
||||
(evaluate(getConfig().flowchart.htmlLabels) ? 5 : 3)) +
|
||||
')'
|
||||
);
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { select } from 'd3';
|
||||
import { log } from '../logger'; // eslint-disable-line
|
||||
import { evaluate } from '../diagrams/common/common';
|
||||
// let vertexNode;
|
||||
// if (getConfig().flowchart.htmlLabels) {
|
||||
// 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>`)
|
||||
|
@ -86,7 +87,7 @@ function addHtmlLabel(node) {
|
|||
const createLabel = (_vertexText, style, isTitle, isNode) => {
|
||||
let vertexText = _vertexText || '';
|
||||
if (typeof vertexText === 'object') vertexText = vertexText[0];
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
|
||||
vertexText = vertexText.replace(/\\n|\n/g, '<br />');
|
||||
log.info('vertexText' + vertexText);
|
||||
|
|
|
@ -4,7 +4,7 @@ import createLabel from './createLabel';
|
|||
import { line, curveBasis, select } from 'd3';
|
||||
import { getConfig } from '../config';
|
||||
import utils from '../utils';
|
||||
// import { calcLabelPosition } from '../utils';
|
||||
import { evaluate } from '../diagrams/common/common';
|
||||
|
||||
let edgeLabels = {};
|
||||
let terminalLabels = {};
|
||||
|
@ -27,7 +27,7 @@ export const insertEdgeLabel = (elem, edge) => {
|
|||
|
||||
// Center the label
|
||||
let bbox = labelElement.getBBox();
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
const div = labelElement.children[0];
|
||||
const dv = select(labelElement);
|
||||
bbox = div.getBoundingClientRect();
|
||||
|
|
|
@ -55,7 +55,7 @@ const recursiveRender = (_elem, graph, diagramtype, parentCluster) => {
|
|||
const newEl = o.elem;
|
||||
updateNodeBounds(node, newEl);
|
||||
node.diff = o.diff || 0;
|
||||
log.info('Node nounds ', v, node, node.width, node.x, node.y);
|
||||
log.info('Node bounds (abc123)', v, node, node.width, node.x, node.y);
|
||||
setNodeElem(newEl, node);
|
||||
|
||||
log.warn('Recursive render complete ', newEl, node);
|
||||
|
|
|
@ -6,6 +6,7 @@ import intersect from './intersect/index.js';
|
|||
import createLabel from './createLabel';
|
||||
import note from './shapes/note';
|
||||
import { parseMember } from '../diagrams/class/svgDraw';
|
||||
import { evaluate } from '../diagrams/common/common';
|
||||
|
||||
const question = (parent, node) => {
|
||||
const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true);
|
||||
|
@ -370,7 +371,7 @@ const rectWithTitle = (parent, node) => {
|
|||
|
||||
const text = label.node().appendChild(createLabel(title, node.labelStyle, true, true));
|
||||
let bbox;
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
const div = text.children[0];
|
||||
const dv = select(text);
|
||||
bbox = div.getBoundingClientRect();
|
||||
|
@ -386,7 +387,7 @@ const rectWithTitle = (parent, node) => {
|
|||
createLabel(textRows.join ? textRows.join('<br/>') : textRows, node.labelStyle, true, true)
|
||||
);
|
||||
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
const div = descr.children[0];
|
||||
const dv = select(descr);
|
||||
bbox = div.getBoundingClientRect();
|
||||
|
@ -567,8 +568,6 @@ const forkJoin = (parent, node, dir) => {
|
|||
|
||||
const shape = shapeSvg
|
||||
.append('rect')
|
||||
.style('stroke', 'black')
|
||||
.style('fill', 'black')
|
||||
.attr('x', (-1 * width) / 2)
|
||||
.attr('y', (-1 * height) / 2)
|
||||
.attr('width', width)
|
||||
|
@ -650,7 +649,7 @@ const class_box = (parent, node) => {
|
|||
.node()
|
||||
.appendChild(createLabel(interfaceLabelText, node.labelStyle, true, true));
|
||||
let interfaceBBox = interfaceLabel.getBBox();
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
const div = interfaceLabel.children[0];
|
||||
const dv = select(interfaceLabel);
|
||||
interfaceBBox = div.getBoundingClientRect();
|
||||
|
@ -672,7 +671,7 @@ const class_box = (parent, node) => {
|
|||
.appendChild(createLabel(classTitleString, node.labelStyle, true, true));
|
||||
select(classTitleLabel).attr('class', 'classTitle');
|
||||
let classTitleBBox = classTitleLabel.getBBox();
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
const div = classTitleLabel.children[0];
|
||||
const dv = select(classTitleLabel);
|
||||
classTitleBBox = div.getBoundingClientRect();
|
||||
|
@ -690,7 +689,7 @@ const class_box = (parent, node) => {
|
|||
.node()
|
||||
.appendChild(createLabel(parsedText, node.labelStyle, true, true));
|
||||
let bbox = lbl.getBBox();
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
const div = lbl.children[0];
|
||||
const dv = select(lbl);
|
||||
bbox = div.getBoundingClientRect();
|
||||
|
@ -713,7 +712,7 @@ const class_box = (parent, node) => {
|
|||
.node()
|
||||
.appendChild(createLabel(parsedText, node.labelStyle, true, true));
|
||||
let bbox = lbl.getBBox();
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
const div = lbl.children[0];
|
||||
const dv = select(lbl);
|
||||
bbox = div.getBoundingClientRect();
|
||||
|
@ -793,7 +792,7 @@ const class_box = (parent, node) => {
|
|||
});
|
||||
//
|
||||
// let bbox;
|
||||
// if (getConfig().flowchart.htmlLabels) {
|
||||
// if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
// const div = interfaceLabel.children[0];
|
||||
// const dv = select(interfaceLabel);
|
||||
// bbox = div.getBoundingClientRect();
|
||||
|
@ -809,7 +808,7 @@ const class_box = (parent, node) => {
|
|||
// .node()
|
||||
// .appendChild(createLabel(textRows.join('<br/>'), node.labelStyle, true, true));
|
||||
|
||||
// if (getConfig().flowchart.htmlLabels) {
|
||||
// if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
// const div = descr.children[0];
|
||||
// const dv = select(descr);
|
||||
// bbox = div.getBoundingClientRect();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import createLabel from '../createLabel';
|
||||
import { getConfig } from '../../config';
|
||||
import { select } from 'd3';
|
||||
import { evaluate } from '../../diagrams/common/common';
|
||||
export const labelHelper = (parent, node, _classes, isNode) => {
|
||||
let classes;
|
||||
if (!_classes) {
|
||||
|
@ -27,7 +28,7 @@ export const labelHelper = (parent, node, _classes, isNode) => {
|
|||
// Get the size of the label
|
||||
let bbox = text.getBBox();
|
||||
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
const div = text.children[0];
|
||||
const dv = select(text);
|
||||
bbox = div.getBoundingClientRect();
|
||||
|
|
|
@ -57,7 +57,7 @@ export const addClasses = function(classes, g) {
|
|||
|
||||
// We create a SVG label, either by delegating to addHtmlLabel or manually
|
||||
// let vertexNode;
|
||||
// if (getConfig().flowchart.htmlLabels) {
|
||||
// if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
// const node = {
|
||||
// label: vertexText.replace(
|
||||
// /fa[lrsb]?:fa-[\w-]+/g,
|
||||
|
|
|
@ -90,6 +90,8 @@ const getUrl = useAbsolute => {
|
|||
return url;
|
||||
};
|
||||
|
||||
export const evaluate = val => (val === 'false' || val === false ? false : true);
|
||||
|
||||
export default {
|
||||
getRows,
|
||||
sanitizeText,
|
||||
|
@ -97,5 +99,6 @@ export default {
|
|||
splitBreaks,
|
||||
lineBreakRegex,
|
||||
removeScript,
|
||||
getUrl
|
||||
getUrl,
|
||||
evaluate
|
||||
};
|
||||
|
|
|
@ -50,7 +50,7 @@ export const lookUpDomId = function(id) {
|
|||
* @param style
|
||||
* @param classes
|
||||
*/
|
||||
export const addVertex = function(_id, text, type, style, classes) {
|
||||
export const addVertex = function(_id, text, type, style, classes, dir) {
|
||||
let txt;
|
||||
let id = _id;
|
||||
if (typeof id === 'undefined') {
|
||||
|
@ -103,6 +103,9 @@ export const addVertex = function(_id, text, type, style, classes) {
|
|||
});
|
||||
}
|
||||
}
|
||||
if (typeof dir !== 'undefined') {
|
||||
vertices[id].dir = dir;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -431,6 +434,7 @@ export const defaultStyle = function() {
|
|||
* Clears the internal graph db so that a new graph can be parsed.
|
||||
*/
|
||||
export const addSubGraph = function(_id, list, _title) {
|
||||
// console.log('addSubGraph', _id, list, _title);
|
||||
let id = _id.trim();
|
||||
let title = _title;
|
||||
if (_id === _title && _title.match(/\s/)) {
|
||||
|
@ -440,8 +444,13 @@ export const addSubGraph = function(_id, list, _title) {
|
|||
const prims = { boolean: {}, number: {}, string: {} };
|
||||
const objs = [];
|
||||
|
||||
return a.filter(function(item) {
|
||||
let dir; // = unbdefined; direction.trim();
|
||||
const nodeList = a.filter(function(item) {
|
||||
const type = typeof item;
|
||||
if (item.stmt && item.stmt === 'dir') {
|
||||
dir = item.value;
|
||||
return false;
|
||||
}
|
||||
if (item.trim() === '') {
|
||||
return false;
|
||||
}
|
||||
|
@ -451,11 +460,13 @@ export const addSubGraph = function(_id, list, _title) {
|
|||
return objs.indexOf(item) >= 0 ? false : objs.push(item);
|
||||
}
|
||||
});
|
||||
return { nodeList, dir };
|
||||
}
|
||||
|
||||
let nodeList = [];
|
||||
|
||||
nodeList = uniq(nodeList.concat.apply(nodeList, list));
|
||||
const { nodeList: nl, dir } = uniq(nodeList.concat.apply(nodeList, list));
|
||||
nodeList = nl;
|
||||
if (version === 'gen-1') {
|
||||
log.warn('LOOKING UP');
|
||||
for (let i = 0; i < nodeList.length; i++) {
|
||||
|
@ -468,9 +479,9 @@ export const addSubGraph = function(_id, list, _title) {
|
|||
title = title || '';
|
||||
title = common.sanitizeText(title, config);
|
||||
subCount = subCount + 1;
|
||||
const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [] };
|
||||
const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [], dir };
|
||||
|
||||
log.info('Adding', subGraph.id, subGraph.nodes);
|
||||
log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir);
|
||||
|
||||
/**
|
||||
* Deletes an id from all subgraphs
|
||||
|
|
|
@ -8,7 +8,7 @@ import { getConfig } from '../../config';
|
|||
import { render } from '../../dagre-wrapper/index.js';
|
||||
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
|
||||
import { log } from '../../logger';
|
||||
import common from '../common/common';
|
||||
import common, { evaluate } from '../common/common';
|
||||
import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils';
|
||||
|
||||
const conf = {};
|
||||
|
@ -48,7 +48,7 @@ export const addVertices = function(vert, g, svgId) {
|
|||
|
||||
// We create a SVG label, either by delegating to addHtmlLabel or manually
|
||||
let vertexNode;
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
|
||||
const node = {
|
||||
label: vertexText.replace(
|
||||
|
@ -147,6 +147,7 @@ export const addVertices = function(vert, g, svgId) {
|
|||
domId: flowDb.lookUpDomId(vertex.id),
|
||||
haveCallback: vertex.haveCallback,
|
||||
width: vertex.type === 'group' ? 500 : undefined,
|
||||
dir: vertex.dir,
|
||||
type: vertex.type,
|
||||
padding: getConfig().flowchart.padding
|
||||
});
|
||||
|
@ -163,6 +164,7 @@ export const addVertices = function(vert, g, svgId) {
|
|||
domId: flowDb.lookUpDomId(vertex.id),
|
||||
width: vertex.type === 'group' ? 500 : undefined,
|
||||
type: vertex.type,
|
||||
dir: vertex.dir,
|
||||
padding: getConfig().flowchart.padding
|
||||
});
|
||||
});
|
||||
|
@ -290,7 +292,7 @@ export const addEdges = function(edges, g) {
|
|||
edgeData.arrowheadStyle = 'fill: #333';
|
||||
edgeData.labelpos = 'c';
|
||||
}
|
||||
// if (getConfig().flowchart.htmlLabels && false) {
|
||||
// if (evaluate(getConfig().flowchart.htmlLabels) && false) {
|
||||
// // eslint-disable-line
|
||||
// edgeData.labelType = 'html';
|
||||
// edgeData.label = `<span id="L-${linkId}" class="edgeLabel L-${linkNameStart}' L-${linkNameEnd}">${edge.text}</span>`;
|
||||
|
@ -385,7 +387,7 @@ export const draw = function(text, id) {
|
|||
for (let i = subGraphs.length - 1; i >= 0; i--) {
|
||||
subG = subGraphs[i];
|
||||
log.info('Subgraph - ', subG);
|
||||
flowDb.addVertex(subG.id, subG.title, 'group', undefined, subG.classes);
|
||||
flowDb.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir);
|
||||
}
|
||||
|
||||
// Fetch the verices/nodes and edges/links from the parsed graph definition
|
||||
|
|
|
@ -8,7 +8,7 @@ import { getConfig } from '../../config';
|
|||
import dagreD3 from 'dagre-d3';
|
||||
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
|
||||
import { log } from '../../logger';
|
||||
import common from '../common/common';
|
||||
import common, { evaluate } from '../common/common';
|
||||
import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils';
|
||||
import flowChartShapes from './flowChartShapes';
|
||||
|
||||
|
@ -49,7 +49,7 @@ export const addVertices = function(vert, g, svgId) {
|
|||
|
||||
// We create a SVG label, either by delegating to addHtmlLabel or manually
|
||||
let vertexNode;
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
|
||||
const node = {
|
||||
label: vertexText.replace(
|
||||
|
@ -228,7 +228,7 @@ export const addEdges = function(edges, g) {
|
|||
edgeData.arrowheadStyle = 'fill: #333';
|
||||
edgeData.labelpos = 'c';
|
||||
|
||||
if (getConfig().flowchart.htmlLabels) {
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
edgeData.labelType = 'html';
|
||||
edgeData.label = `<span id="L-${linkId}" class="edgeLabel L-${linkNameStart}' L-${linkNameEnd}">${edge.text.replace(
|
||||
/fa[lrsb]?:fa-[\w-]+/g,
|
||||
|
@ -451,7 +451,7 @@ export const draw = function(text, id) {
|
|||
}
|
||||
|
||||
// Add label rects for non html labels
|
||||
if (!conf.htmlLabels || true) { // eslint-disable-line
|
||||
if (!evaluate(conf.htmlLabels) || true) { // eslint-disable-line
|
||||
const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label');
|
||||
for (let k = 0; k < labels.length; k++) {
|
||||
const label = labels[k];
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
import flowDb from '../flowDb';
|
||||
import flow from './flow';
|
||||
import filter from 'lodash/filter';
|
||||
import { setConfig } from '../../../config';
|
||||
|
||||
setConfig({
|
||||
securityLevel: 'strict'
|
||||
});
|
||||
|
||||
describe('when parsing directions', function() {
|
||||
beforeEach(function() {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy.clear();
|
||||
flow.parser.yy.setGen('gen-2');
|
||||
});
|
||||
|
||||
|
||||
it('should use default direction from top level', function() {
|
||||
const res = flow.parser.parse(`flowchart TB
|
||||
subgraph A
|
||||
a --> b
|
||||
end`);
|
||||
|
||||
const subgraphs = flow.parser.yy.getSubGraphs();
|
||||
expect(subgraphs.length).toBe(1);
|
||||
const subgraph = subgraphs[0];
|
||||
expect(subgraph.nodes.length).toBe(2);
|
||||
expect(subgraph.nodes[0]).toBe('b');
|
||||
expect(subgraph.nodes[1]).toBe('a');
|
||||
expect(subgraph.id).toBe('A');
|
||||
expect(subgraph.dir).toBe(undefined);
|
||||
});
|
||||
it('should handle a subgraph with a direction', function() {
|
||||
const res = flow.parser.parse(`flowchart TB
|
||||
subgraph A
|
||||
direction BT
|
||||
a --> b
|
||||
end`);
|
||||
|
||||
const subgraphs = flow.parser.yy.getSubGraphs();
|
||||
expect(subgraphs.length).toBe(1);
|
||||
const subgraph = subgraphs[0];
|
||||
expect(subgraph.nodes.length).toBe(2);
|
||||
expect(subgraph.nodes[0]).toBe('b');
|
||||
expect(subgraph.nodes[1]).toBe('a');
|
||||
expect(subgraph.id).toBe('A');
|
||||
expect(subgraph.dir).toBe('BT');
|
||||
});
|
||||
it('should use the last defined direction', function() {
|
||||
const res = flow.parser.parse(`flowchart TB
|
||||
subgraph A
|
||||
direction BT
|
||||
a --> b
|
||||
direction RL
|
||||
end`);
|
||||
|
||||
const subgraphs = flow.parser.yy.getSubGraphs();
|
||||
expect(subgraphs.length).toBe(1);
|
||||
const subgraph = subgraphs[0];
|
||||
expect(subgraph.nodes.length).toBe(2);
|
||||
expect(subgraph.nodes[0]).toBe('b');
|
||||
expect(subgraph.nodes[1]).toBe('a');
|
||||
expect(subgraph.id).toBe('A');
|
||||
expect(subgraph.dir).toBe('RL');
|
||||
});
|
||||
|
||||
it('should handle nested subgraphs 1', function() {
|
||||
const res = flow.parser.parse(`flowchart TB
|
||||
subgraph A
|
||||
direction RL
|
||||
b-->B
|
||||
a
|
||||
end
|
||||
a-->c
|
||||
subgraph B
|
||||
direction LR
|
||||
c
|
||||
end`);
|
||||
|
||||
const subgraphs = flow.parser.yy.getSubGraphs();
|
||||
expect(subgraphs.length).toBe(2);
|
||||
|
||||
const subgraphA = filter(subgraphs,o => o.id === 'A')[0];
|
||||
const subgraphB = filter(subgraphs,o => o.id === 'B')[0];
|
||||
|
||||
expect(subgraphB.nodes[0]).toBe('c');
|
||||
expect(subgraphB.dir).toBe('LR');
|
||||
expect(subgraphA.nodes).toContain('B');
|
||||
expect(subgraphA.nodes).toContain('b');
|
||||
expect(subgraphA.nodes).toContain('a');
|
||||
expect(subgraphA.nodes).not.toContain('c');
|
||||
expect(subgraphA.dir).toBe('RL');
|
||||
});
|
||||
|
||||
});
|
|
@ -92,6 +92,12 @@ that id.
|
|||
<dir>\s*">" { this.popState(); return 'DIR'; }
|
||||
<dir>\s*"^" { this.popState(); return 'DIR'; }
|
||||
<dir>\s*"v" { this.popState(); return 'DIR'; }
|
||||
|
||||
.*direction\s+TB[^\n]* return 'direction_tb';
|
||||
.*direction\s+BT[^\n]* return 'direction_bt';
|
||||
.*direction\s+RL[^\n]* return 'direction_rl';
|
||||
.*direction\s+LR[^\n]* return 'direction_lr';
|
||||
|
||||
[0-9]+ { return 'NUM';}
|
||||
\# return 'BRKT';
|
||||
":::" return 'STYLE_SEPARATOR';
|
||||
|
@ -327,6 +333,7 @@ statement
|
|||
// {$$=yy.addSubGraph($3,$5,$3);}
|
||||
| subgraph separator document end
|
||||
{$$=yy.addSubGraph(undefined,$3,undefined);}
|
||||
| direction
|
||||
;
|
||||
|
||||
separator: NEWLINE | SEMI | EOF ;
|
||||
|
@ -537,6 +544,17 @@ alphaNumStatement
|
|||
{$$='-';}
|
||||
;
|
||||
|
||||
direction
|
||||
: direction_tb
|
||||
{ $$={stmt:'dir', value:'TB'};}
|
||||
| direction_bt
|
||||
{ $$={stmt:'dir', value:'BT'};}
|
||||
| direction_rl
|
||||
{ $$={stmt:'dir', value:'RL'};}
|
||||
| direction_lr
|
||||
{ $$={stmt:'dir', value:'LR'};}
|
||||
;
|
||||
|
||||
alphaNumToken : PUNCTUATION | AMP | UNICODE_TEXT | NUM| ALPHA | COLON | COMMA | PLUS | EQUALS | MULT | DOT | BRKT| UNDERSCORE ;
|
||||
|
||||
idStringToken : ALPHA|UNDERSCORE |UNICODE_TEXT | NUM| COLON | COMMA | PLUS | MINUS | DOWN |EQUALS | MULT | BRKT | DOT | PUNCTUATION | AMP;
|
||||
|
|
|
@ -3,7 +3,7 @@ import { select } from 'd3';
|
|||
import stateDb from './stateDb';
|
||||
import state from './parser/stateDiagram';
|
||||
import { getConfig } from '../../config';
|
||||
|
||||
// import { evaluate } from '../common/common';
|
||||
import { render } from '../../dagre-wrapper/index.js';
|
||||
import { log } from '../../logger';
|
||||
import { configureSvgSize } from '../../utils';
|
||||
|
@ -295,22 +295,22 @@ export const draw = function(text, id) {
|
|||
svg.attr('viewBox', vBox);
|
||||
|
||||
// Add label rects for non html labels
|
||||
if (!conf.htmlLabels) {
|
||||
const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label');
|
||||
for (let k = 0; k < labels.length; k++) {
|
||||
const label = labels[k];
|
||||
// if (!evaluate(conf.htmlLabels) || true) {
|
||||
const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label');
|
||||
for (let k = 0; k < labels.length; k++) {
|
||||
const label = labels[k];
|
||||
|
||||
// Get dimensions of label
|
||||
const dim = label.getBBox();
|
||||
// Get dimensions of label
|
||||
const dim = label.getBBox();
|
||||
|
||||
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||
rect.setAttribute('rx', 0);
|
||||
rect.setAttribute('ry', 0);
|
||||
rect.setAttribute('width', dim.width);
|
||||
rect.setAttribute('height', dim.height);
|
||||
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||
rect.setAttribute('rx', 0);
|
||||
rect.setAttribute('ry', 0);
|
||||
rect.setAttribute('width', dim.width);
|
||||
rect.setAttribute('height', dim.height);
|
||||
|
||||
label.insertBefore(rect, label.firstChild);
|
||||
}
|
||||
label.insertBefore(rect, label.firstChild);
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -82,11 +82,17 @@ g.stateGroup line {
|
|||
}
|
||||
|
||||
.node circle.state-start {
|
||||
fill: ${options.lineColor};
|
||||
stroke: black;
|
||||
fill: ${options.specialStateColor};
|
||||
stroke: ${options.specialStateColor};
|
||||
}
|
||||
|
||||
.node .fork-join {
|
||||
fill: ${options.specialStateColor};
|
||||
stroke: ${options.specialStateColor};
|
||||
}
|
||||
|
||||
.node circle.state-end {
|
||||
fill: ${options.primaryBorderColor};
|
||||
fill: ${options.innerEndBackground};
|
||||
stroke: ${options.background};
|
||||
stroke-width: 1.5
|
||||
}
|
||||
|
|
|
@ -137,7 +137,8 @@ const initialize = function(config) {
|
|||
mermaid.startOnLoad = config.mermaid.startOnLoad;
|
||||
}
|
||||
if (typeof config.mermaid.htmlLabels !== 'undefined') {
|
||||
mermaid.htmlLabels = config.mermaid.htmlLabels;
|
||||
mermaid.htmlLabels =
|
||||
config.mermaid.htmlLabels === 'false' || config.mermaid.htmlLabels === false ? false : true;
|
||||
}
|
||||
}
|
||||
mermaidAPI.initialize(config);
|
||||
|
|
|
@ -297,8 +297,9 @@ const render = function(id, _txt, cb, container) {
|
|||
// classDef
|
||||
if (graphType === 'flowchart' || graphType === 'flowchart-v2' || graphType === 'graph') {
|
||||
const classes = flowRenderer.getClasses(txt);
|
||||
const htmlLabels = cnf.htmlLabels || cnf.flowchart.htmlLabels;
|
||||
for (const className in classes) {
|
||||
if (cnf.htmlLabels || cnf.flowchart.htmlLabels) {
|
||||
if (htmlLabels) {
|
||||
userStyles += `\n.${className} > * { ${classes[className].styles.join(
|
||||
' !important; '
|
||||
)} !important; }`;
|
||||
|
@ -306,7 +307,6 @@ const render = function(id, _txt, cb, container) {
|
|||
' !important; '
|
||||
)} !important; }`;
|
||||
} else {
|
||||
// console.log('classes[className].styles', classes[className].styles, cnf.htmlLabels);
|
||||
userStyles += `\n.${className} path { ${classes[className].styles.join(
|
||||
' !important; '
|
||||
)} !important; }`;
|
||||
|
|
|
@ -121,10 +121,11 @@ class Theme {
|
|||
this.altBackground = this.altBackground || this.tertiaryColor;
|
||||
this.compositeTitleBackground = this.compositeTitleBackground || this.mainBkg;
|
||||
this.compositeBorder = this.compositeBorder || this.nodeBorder;
|
||||
|
||||
this.innerEndBackground = this.nodeBorder;
|
||||
this.errorBkgColor = this.errorBkgColor || this.tertiaryColor;
|
||||
this.errorTextColor = this.errorTextColor || this.tertiaryTextColor;
|
||||
this.transitionColor = this.transitionColor || this.lineColor;
|
||||
this.specialStateColor = this.lineColor;
|
||||
|
||||
/* class */
|
||||
this.classText = this.classText || this.textColor;
|
||||
|
|
|
@ -136,6 +136,8 @@ class Theme {
|
|||
this.altBackground = this.altBackground || '#555';
|
||||
this.compositeTitleBackground = this.compositeTitleBackground || this.mainBkg;
|
||||
this.compositeBorder = this.compositeBorder || this.nodeBorder;
|
||||
this.innerEndBackground = this.primaryBorderColor;
|
||||
this.specialStateColor = '#f4f4f4'; // this.lineColor;
|
||||
|
||||
this.errorBkgColor = this.errorBkgColor || this.tertiaryColor;
|
||||
this.errorTextColor = this.errorTextColor || this.tertiaryTextColor;
|
||||
|
|
|
@ -149,6 +149,8 @@ class Theme {
|
|||
this.altBackground = this.altBackground || '#f0f0f0';
|
||||
this.compositeTitleBackground = this.compositeTitleBackground || this.mainBkg;
|
||||
this.compositeBorder = this.compositeBorder || this.nodeBorder;
|
||||
this.innerEndBackground = this.nodeBorder;
|
||||
this.specialStateColor = this.lineColor;
|
||||
|
||||
this.errorBkgColor = this.errorBkgColor || this.tertiaryColor;
|
||||
this.errorTextColor = this.errorTextColor || this.tertiaryTextColor;
|
||||
|
|
|
@ -119,6 +119,8 @@ class Theme {
|
|||
this.altBackground = this.altBackground || '#f0f0f0';
|
||||
this.compositeTitleBackground = this.compositeTitleBackground || this.mainBkg;
|
||||
this.compositeBorder = this.compositeBorder || this.nodeBorder;
|
||||
this.innerEndBackground = this.primaryBorderColor;
|
||||
this.specialStateColor = this.lineColor;
|
||||
|
||||
this.errorBkgColor = this.errorBkgColor || this.tertiaryColor;
|
||||
this.errorTextColor = this.errorTextColor || this.tertiaryTextColor;
|
||||
|
|
|
@ -156,6 +156,8 @@ class Theme {
|
|||
this.altBackground = this.altBackground || '#f4f4f4';
|
||||
this.compositeTitleBackground = this.compositeTitleBackground || this.mainBkg;
|
||||
this.stateBorder = this.stateBorder || '#000';
|
||||
this.innerEndBackground = this.primaryBorderColor;
|
||||
this.specialStateColor = '#222';
|
||||
|
||||
this.errorBkgColor = this.errorBkgColor || this.tertiaryColor;
|
||||
this.errorTextColor = this.errorTextColor || this.tertiaryTextColor;
|
||||
|
|
Loading…
Reference in New Issue