mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-27 19:29:38 +02:00
Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
cbe3a9159d | ||
![]() |
b141f24068 | ||
![]() |
e13f97c8ee | ||
![]() |
882ba03fcb | ||
![]() |
46cdacfdc7 | ||
![]() |
384afc1a6d | ||
![]() |
fa55b7c824 | ||
![]() |
0185a74e95 | ||
![]() |
eeccf1c56b | ||
![]() |
e3e9c67f5b | ||
![]() |
a73b291c4f | ||
![]() |
1b5056ca38 | ||
![]() |
cbe2ce41c1 | ||
![]() |
06834eb383 | ||
![]() |
413816783d | ||
![]() |
4081d7f5f6 |
170
cypress/platform/click_security_sandbox.html
Normal file
170
cypress/platform/click_security_sandbox.html
Normal file
@@ -0,0 +1,170 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>Mermaid Quick Test Page</title>
|
||||
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
|
||||
<style>
|
||||
.mermaid2 {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="display: flex">
|
||||
<div id="FirstLine" class="mermaid">
|
||||
graph TB
|
||||
Function-->URL
|
||||
click Function clickByFlow "Add a div"
|
||||
click URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
|
||||
</div>
|
||||
<div id="FirstLine" class="mermaid">
|
||||
graph TB
|
||||
1Function--->2URL
|
||||
click 1Function clickByFlow "Add a div"
|
||||
click 2URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
|
||||
</div>
|
||||
<div id="FirstLine" class="mermaid">
|
||||
flowchart TB
|
||||
Function-->URL
|
||||
click Function clickByFlow "Add a div"
|
||||
click URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>" _self
|
||||
</div>
|
||||
<div id="FirstLine" class="mermaid">
|
||||
flowchart TB
|
||||
1Function--->2URL
|
||||
click 1Function clickByFlow "Add a div"
|
||||
click 2URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>" _self
|
||||
</div>
|
||||
|
||||
<div id="FirstLine" class="mermaid">
|
||||
classDiagram
|
||||
class ShapeLink
|
||||
link ShapeLink "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
|
||||
class ShapeCallback
|
||||
callback ShapeCallback "clickByClass" "This is a tooltip for a callback"
|
||||
</div>
|
||||
<div id="FirstLine" class="mermaid">
|
||||
classDiagram-v2
|
||||
class ShapeLink2
|
||||
link ShapeLink2 "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
|
||||
class ShapeCallback2
|
||||
callback ShapeCallback2 "clickByClass" "This is a tooltip for a callback"
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mermaid">
|
||||
gantt
|
||||
dateFormat YYYY-MM-DD
|
||||
axisFormat %d/%m
|
||||
title Adding GANTT diagram to mermaid
|
||||
excludes weekdays 2014-01-10
|
||||
|
||||
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 Clickable
|
||||
Visit mermaidjs :active, cl1, 2014-01-07,2014-01-10
|
||||
Calling a Callback (look at the console log) :cl2, after cl1, 3d
|
||||
Calling a Callback with args :cl3, after cl1, 3d
|
||||
|
||||
click cl1 href "http://localhost:9000/webpackUsage.html"
|
||||
click cl2 call clickByGantt()
|
||||
click cl3 call clickByGantt("test1", test2, test3)
|
||||
|
||||
section Last section
|
||||
Describe gantt syntax :after doc1, 3d
|
||||
Add gantt diagram to demo page : 20h
|
||||
Add another diagram to demo page : 48h
|
||||
</div>
|
||||
<div style="display: flex">
|
||||
<div id="FirstLine" class="mermaid">
|
||||
graph TB
|
||||
FunctionArg-->URL
|
||||
click FunctionArg call clickByFlowArg(ARGUMENT) "Add a div"
|
||||
click URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
|
||||
</div>
|
||||
<div id="FirstLine" class="mermaid">
|
||||
flowchart TB
|
||||
FunctionArg-->URL
|
||||
click FunctionArg call clickByFlowArg(ARGUMENT) "Add a div"
|
||||
click URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
|
||||
</div>
|
||||
|
||||
<div id="FirstLine" class="mermaid">
|
||||
classDiagram
|
||||
class ShapeLink
|
||||
link ShapeLink "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
|
||||
class ShapeCallback
|
||||
click ShapeCallback call clickByClass(123) "This is a tooltip for a callback"
|
||||
</div>
|
||||
|
||||
<div id="FirstLine" class="mermaid">
|
||||
classDiagram-v2
|
||||
class ShapeLink2
|
||||
link ShapeLink2 "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
|
||||
class ShapeCallback2
|
||||
click ShapeCallback2 call clickByClass(123) "This is a tooltip for a callback"
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
function clickByFlow(elemName) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'created-by-click';
|
||||
div.style = 'padding: 20px; background: green; color: white;';
|
||||
div.innerText = 'Clicked By Flow';
|
||||
|
||||
document.getElementsByTagName('body')[0].appendChild(div);
|
||||
}
|
||||
function clickByFlowArg(argument) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'created-by-click-2';
|
||||
div.style = 'padding: 20px; background: green; color: white;';
|
||||
div.innerText = 'Clicked By Flow: ' + argument;
|
||||
|
||||
document.getElementsByTagName('body')[0].appendChild(div);
|
||||
}
|
||||
function clickByGantt(arg1, arg2, arg3) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'created-by-gant-click';
|
||||
div.style = 'padding: 20px; background: green; color: white;';
|
||||
div.innerText = 'Clicked By Gant';
|
||||
if (arg1) div.innerText += ' ' + arg1;
|
||||
if (arg2) div.innerText += ' ' + arg2;
|
||||
if (arg3) div.innerText += ' ' + arg3;
|
||||
|
||||
document.getElementsByTagName('body')[0].appendChild(div);
|
||||
}
|
||||
function clickByClass(arg) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'created-by-class-click';
|
||||
div.style = 'padding: 20px; background: purple; color: white;';
|
||||
div.innerText = 'Clicked By Class' + (arg ? arg : '');
|
||||
|
||||
document.getElementsByTagName('body')[0].appendChild(div);
|
||||
}
|
||||
mermaid.initialize({ startOnLoad: true, securityLevel: 'sandbox', logLevel: 1 });
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@@ -14,6 +14,7 @@
|
||||
font-family: 'Arial';
|
||||
/* font-size: 18px !important; */
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
h1 { color: grey;}
|
||||
.mermaid2,.mermaid3 {
|
||||
@@ -25,15 +26,214 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>info below</div>
|
||||
<div class="flex flex-wrap">
|
||||
<div class="mermaid2" style="width: 50%;">
|
||||
pie title Pets adopted by volunteers
|
||||
"Dogs" : 386
|
||||
"Cats" : 85
|
||||
"Rats" : 15
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
gantt
|
||||
title Adding GANTT diagram functionality to mermaid
|
||||
excludes :excludes the named dates/days from being included in a charted task..
|
||||
section Screening
|
||||
Lexplore :active, des1, 2023-01-06,2023-01-08
|
||||
H4 :active, des2, 2024-01-09, 3d
|
||||
Future task : des3, after des2, 5d
|
||||
Future task2 : des4, after des3, 5d
|
||||
|
||||
<div class="mermaid" style="width: 100%; height: 20%;">
|
||||
stateDiagram-v2
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
info
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
gitGraph:
|
||||
options
|
||||
{
|
||||
"nodeSpacing": 150,
|
||||
"nodeRadius": 10
|
||||
}
|
||||
end
|
||||
commit
|
||||
branch newbranch
|
||||
checkout newbranch
|
||||
commit
|
||||
commit
|
||||
checkout master
|
||||
commit
|
||||
commit
|
||||
merge newbranch
|
||||
</div>
|
||||
<div class="mermaid" style="width: 50%;">
|
||||
sequenceDiagram
|
||||
participant a as Alice
|
||||
participant j as John
|
||||
note right of a: Hello world!
|
||||
properties a: {"class": "internal-service-actor", "type": "@clock"}
|
||||
properties j: {"class": "external-service-actor", "type": "@computer"}
|
||||
links a: {"Repo": "https://www.contoso.com/repo", "Swagger": "https://www.contoso.com/swagger"}
|
||||
links j: {"Repo": "https://www.contoso.com/repo"}
|
||||
links a: {"Dashboard": "https://www.contoso.com/dashboard", "On-Call": "https://www.contoso.com/oncall"}
|
||||
link a: Contacts @ https://contacts.contoso.com/?contact=alice@contoso.com
|
||||
a->>j: Hello John, how are you?
|
||||
j-->>a: Great! </div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
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
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
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: 100%;">
|
||||
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: 100%;">
|
||||
graph TB
|
||||
subgraph One
|
||||
a1-->a2-->a3
|
||||
end
|
||||
</div>
|
||||
<div class="mermaid" style="width: 50%;">
|
||||
flowchart LR
|
||||
Function-->URL-->A-->B-->C
|
||||
click Function clickByFlow "Add a div"
|
||||
click URL "https://mermaid-js.github.io/mermaid/#/" "Visit <strong>mermaid docs</strong>" _blank
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
gantt
|
||||
dateFormat YYYY-MM-DD
|
||||
axisFormat %d/%m
|
||||
title Adding GANTT diagram to mermaid
|
||||
excludes weekdays 2014-01-10
|
||||
|
||||
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 Clickable
|
||||
Visit mermaidjs :active, cl1, 2014-01-07,2014-01-10
|
||||
Calling a Callback (look at the console log) :cl2, after cl1, 3d
|
||||
Calling a Callback with args :cl3, after cl1, 3d
|
||||
|
||||
click cl1 href "https://mermaid-js.github.io/mermaid/#/"
|
||||
click cl2 call clickByGantt()
|
||||
click cl3 call clickByGantt("test1", test2, test3)
|
||||
|
||||
section Last section
|
||||
Describe gantt syntax :after doc1, 3d
|
||||
Add gantt diagram to demo page : 20h
|
||||
Add another diagram to demo page : 48h
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
classDiagram
|
||||
Class01 <|-- AveryLongClass : Cool
|
||||
Class09 --> C2 : Where am i?
|
||||
Class09 --* C3
|
||||
Class09 --|> Class07
|
||||
Class07 : equals()
|
||||
Class07 : Object[] elementData
|
||||
Class01 : size()
|
||||
Class01 : int chimp
|
||||
Class01 : int gorilla
|
||||
class Class10 {
|
||||
int id
|
||||
size()
|
||||
}
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
stateDiagram
|
||||
[*] --> S1
|
||||
state "Some long name" as S1
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="mermaid2" style="width: 100%;">
|
||||
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()
|
||||
}
|
||||
</div>
|
||||
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
@@ -42,29 +242,52 @@ stateDiagram-v2
|
||||
};
|
||||
mermaid.initialize({
|
||||
// theme: 'dark',
|
||||
theme: 'forest',
|
||||
arrowMarkerAbsolute: true,
|
||||
// theme: 'forest',
|
||||
// arrowMarkerAbsolute: true,
|
||||
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
||||
flowchart: { nodeSpacing: 10, curve: 'cardinal', htmlLabels: false },
|
||||
flowchart: {
|
||||
nodeSpacing: 10,
|
||||
curve: 'cardinal',
|
||||
htmlLabels: true,
|
||||
defaultRenderer: 'dagre-d3',
|
||||
},
|
||||
class: {
|
||||
defaultRenderer: 'dagre-d3',
|
||||
htmlLabels: true,
|
||||
},
|
||||
// gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
|
||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||
sequence: {
|
||||
actorFontFamily: 'courier',
|
||||
actorMargin: 50,
|
||||
showSequenceNumbers: false,
|
||||
// forceMenus: true,
|
||||
},
|
||||
// sequenceDiagram: { actorMargin: 300, forceMenus: false }, // deprecated
|
||||
// fontFamily: '"times", sans-serif',
|
||||
// fontFamily: 'courier',
|
||||
state: {
|
||||
nodeSpacing: 50,
|
||||
rankSpacing: 50,
|
||||
defaultRenderer: 'dagre-wrapper',
|
||||
defaultRenderer: 'dagre-d3',
|
||||
},
|
||||
logLevel: 0,
|
||||
fontSize: 18,
|
||||
curve: 'cardinal',
|
||||
securityLevel: 'strict',
|
||||
// securityLevel: 'sandbox',
|
||||
// themeVariables: {relationLabelColor: 'red'}
|
||||
});
|
||||
function callback() {
|
||||
alert('It worked');
|
||||
}
|
||||
|
||||
function clickByFlow(elemName) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'created-by-click';
|
||||
div.style = 'padding: 20px; background: green; color: white;';
|
||||
div.innerText = 'Clicked By Flow';
|
||||
|
||||
document.getElementsByTagName('body')[0].appendChild(div);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@@ -12,9 +12,11 @@
|
||||
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>mermaid.init({ startOnLoad: false });
|
||||
mermaid.mermaidAPI.initialize();
|
||||
|
||||
mermaid.mermaidAPI.initialize({ securityLevel: 'strict' });
|
||||
|
||||
try {
|
||||
console.log('rendering');
|
||||
mermaid.mermaidAPI.render('graphDiv', `>`);
|
||||
} catch (e) {}
|
||||
|
||||
|
@@ -70,7 +70,7 @@
|
||||
// fontFamily: 'courier',
|
||||
fontSize: 18,
|
||||
curve: 'basis',
|
||||
// securityLevel: 'loose',
|
||||
securityLevel: 'sandbox',
|
||||
startOnLoad: false,
|
||||
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
|
||||
// themeVariables: {relationLabelColor: 'red'}
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 166 KiB |
Binary file not shown.
After Width: | Height: | Size: 162 KiB |
@@ -1057,6 +1057,10 @@ Returns **any**
|
||||
|
||||
- `conf` **any**
|
||||
|
||||
## reinitialize
|
||||
|
||||
To be removed
|
||||
|
||||
## initialize
|
||||
|
||||
### Parameters
|
||||
@@ -1069,61 +1073,16 @@ Returns **any**
|
||||
|
||||
```html
|
||||
<script>
|
||||
var config = {
|
||||
theme: 'default',
|
||||
logLevel: 'fatal',
|
||||
securityLevel: 'strict',
|
||||
startOnLoad: true,
|
||||
arrowMarkerAbsolute: false,
|
||||
|
||||
er: {
|
||||
diagramPadding: 20,
|
||||
layoutDirection: 'TB',
|
||||
minEntityWidth: 100,
|
||||
minEntityHeight: 75,
|
||||
entityPadding: 15,
|
||||
stroke: 'gray',
|
||||
fill: 'honeydew',
|
||||
fontSize: 12,
|
||||
useMaxWidth: true,
|
||||
},
|
||||
flowchart: {
|
||||
diagramPadding: 8,
|
||||
htmlLabels: true,
|
||||
curve: 'basis',
|
||||
},
|
||||
sequence: {
|
||||
diagramMarginX: 50,
|
||||
diagramMarginY: 10,
|
||||
actorMargin: 50,
|
||||
width: 150,
|
||||
height: 65,
|
||||
boxMargin: 10,
|
||||
boxTextMargin: 5,
|
||||
noteMargin: 10,
|
||||
messageMargin: 35,
|
||||
messageAlign: 'center',
|
||||
mirrorActors: true,
|
||||
bottomMarginAdj: 1,
|
||||
useMaxWidth: true,
|
||||
rightAngles: false,
|
||||
showSequenceNumbers: false,
|
||||
},
|
||||
gantt: {
|
||||
titleTopMargin: 25,
|
||||
barHeight: 20,
|
||||
barGap: 4,
|
||||
topPadding: 50,
|
||||
leftPadding: 75,
|
||||
gridLineStartPadding: 35,
|
||||
fontSize: 11,
|
||||
fontFamily: '"Open-Sans", "sans-serif"',
|
||||
numberSectionStyles: 4,
|
||||
axisFormat: '%Y-%m-%d',
|
||||
topAxis: false,
|
||||
},
|
||||
};
|
||||
mermaid.initialize(config);
|
||||
var config = { theme: 'default', logLevel: 'fatal', securityLevel: 'strict', startOnLoad: true,
|
||||
arrowMarkerAbsolute: false, er: { diagramPadding: 20, layoutDirection: 'TB', minEntityWidth: 100,
|
||||
minEntityHeight: 75, entityPadding: 15, stroke: 'gray', fill: 'honeydew', fontSize: 12, useMaxWidth:
|
||||
true, }, flowchart: { diagramPadding: 8, htmlLabels: true, curve: 'basis', }, sequence: {
|
||||
diagramMarginX: 50, diagramMarginY: 10, actorMargin: 50, width: 150, height: 65, boxMargin: 10,
|
||||
boxTextMargin: 5, noteMargin: 10, messageMargin: 35, messageAlign: 'center', mirrorActors: true,
|
||||
bottomMarginAdj: 1, useMaxWidth: true, rightAngles: false, showSequenceNumbers: false, }, gantt: {
|
||||
titleTopMargin: 25, barHeight: 20, barGap: 4, topPadding: 50, leftPadding: 75, gridLineStartPadding:
|
||||
35, fontSize: 11, fontFamily: '"Open-Sans", "sans-serif"', numberSectionStyles: 4, axisFormat:
|
||||
'%Y-%m-%d', topAxis: false, }, }; mermaid.initialize(config);
|
||||
</script>
|
||||
```
|
||||
|
||||
|
@@ -50,7 +50,8 @@ The easiest way to integrate mermaid on a web page requires three elements:
|
||||
|
||||
2. The `mermaidAPI` call, in a separate `script` tag. Example:
|
||||
```html
|
||||
<script>mermaid.initialize({startOnLoad:true});</script>
|
||||
<script>mermaid.initialize({startOnLoad:true});
|
||||
</script>
|
||||
```
|
||||
|
||||
3. A graph definition, inside `<div>` tags labeled `class=mermaid`. Example:
|
||||
@@ -82,7 +83,8 @@ locate the graph definitions inside the `div` tags with `class="mermaid"` and re
|
||||
B-->D(fa:fa-spinner);
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
||||
<script>mermaid.initialize({startOnLoad:true});</script>
|
||||
<script>mermaid.initialize({startOnLoad:true});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@@ -105,17 +107,19 @@ Mermaid can load multiple diagrams, in the same page.
|
||||
|
||||
| Parameter | Description | Type | Required | Values |
|
||||
| ------------- | --------------------------------- | ------ | -------- | ------------------------- |
|
||||
| securityLevel | Level of trust for parsed diagram | String | Required | Strict, Loose, antiscript |
|
||||
| securityLevel | Level of trust for parsed diagram | String | Required | Strict, Loose, antiscript , sandbox|
|
||||
|
||||
Values:
|
||||
|
||||
- **strict**: (**default**) tags in text are encoded, click functionality is disabled
|
||||
- **loose**: tags in text are allowed, click functionality is enabled
|
||||
- **antiscript**: html tags in text are allowed, (only script element is removed), click functionality is enabled
|
||||
- **sandbox**: With this security level all rendering takes place in a sandboxed iframe. This prevent any javascript running in the context. This may hinder interactive functionality of the diagram like scripts, popups in sequence diagram or links to other tabs/targets etc.
|
||||
|
||||
|
||||
```note
|
||||
This changes the default behaviour of mermaid so that after upgrade to 8.2,unless the `securityLevel` is not changed, tags in flowcharts are encoded as tags and clicking is disabled.
|
||||
**sandbox** security level is still in the beta version.
|
||||
```
|
||||
|
||||
**If you are taking responsibility for the diagram source security you can set the `securityLevel` to a value of your choosing . This allows clicks and tags are allowed.**
|
||||
@@ -203,20 +207,10 @@ The example below show an outline of how this could be used. The example just lo
|
||||
<script src="mermaid.js"></script>
|
||||
|
||||
<script>
|
||||
mermaid.mermaidAPI.initialize({
|
||||
startOnLoad:false
|
||||
});
|
||||
$(function(){
|
||||
// Example of using the API
|
||||
var element = document.querySelector("#graphDiv");
|
||||
|
||||
var insertSvg = function(svgCode, bindFunctions){
|
||||
element.innerHTML = svgCode;
|
||||
};
|
||||
|
||||
var graphDefinition = 'graph TB\na-->b';
|
||||
var graph = mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg);
|
||||
});
|
||||
mermaid.mermaidAPI.initialize({ startOnLoad:false }); $(function(){ // Example of using the API var
|
||||
element = document.querySelector("#graphDiv"); var insertSvg = function(svgCode, bindFunctions){
|
||||
element.innerHTML = svgCode; }; var graphDefinition = 'graph TB\na-->b'; var graph =
|
||||
mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg); });
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -345,13 +339,7 @@ on what kind of integration you use.
|
||||
```html
|
||||
<script src="../dist/mermaid.js"></script>
|
||||
<script>
|
||||
var config = {
|
||||
startOnLoad:true,
|
||||
flowchart:{
|
||||
useMaxWidth:false,
|
||||
htmlLabels:true
|
||||
}
|
||||
};
|
||||
var config = { startOnLoad:true, flowchart:{ useMaxWidth:false, htmlLabels:true } };
|
||||
mermaid.initialize(config);
|
||||
</script>
|
||||
```
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mermaid",
|
||||
"version": "8.13.10",
|
||||
"version": "8.14.0",
|
||||
"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",
|
||||
|
@@ -6,7 +6,9 @@ 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';
|
||||
import { evaluate, sanitizeText as sanitize } from '../diagrams/common/common';
|
||||
|
||||
const sanitizeText = (txt) => sanitize(txt, getConfig());
|
||||
|
||||
const question = (parent, node) => {
|
||||
const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true);
|
||||
@@ -967,10 +969,13 @@ export const insertNode = (elem, node, dir) => {
|
||||
|
||||
// Add link when appropriate
|
||||
if (node.link) {
|
||||
newEl = elem
|
||||
.insert('svg:a')
|
||||
.attr('xlink:href', node.link)
|
||||
.attr('target', node.linkTarget || '_blank');
|
||||
let target;
|
||||
if (getConfig().securityLevel === 'sandbox') {
|
||||
target = '_top';
|
||||
} else if (node.linkTarget) {
|
||||
target = node.linkTarget || '_blank';
|
||||
}
|
||||
newEl = elem.insert('svg:a').attr('xlink:href', node.link).attr('target', target);
|
||||
el = shapes[node.shape](newEl, node, dir);
|
||||
} else {
|
||||
el = shapes[node.shape](elem, node, dir);
|
||||
|
@@ -143,6 +143,7 @@ export const addMember = function (className, member) {
|
||||
|
||||
if (memberString.startsWith('<<') && memberString.endsWith('>>')) {
|
||||
// Remove leading and trailing brackets
|
||||
// theClass.annotations.push(memberString.substring(2, memberString.length - 2));
|
||||
theClass.annotations.push(sanitizeText(memberString.substring(2, memberString.length - 2)));
|
||||
} else if (memberString.indexOf(')') > 0) {
|
||||
theClass.methods.push(sanitizeText(memberString));
|
||||
@@ -212,8 +213,10 @@ export const setLink = function (ids, linkStr, target) {
|
||||
if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
|
||||
if (typeof classes[id] !== 'undefined') {
|
||||
classes[id].link = utils.formatUrl(linkStr, config);
|
||||
if (typeof target === 'string') {
|
||||
classes[id].linkTarget = target;
|
||||
if (config.securityLevel === 'sandbox') {
|
||||
classes[id].linkTarget = '_top';
|
||||
} else if (typeof target === 'string') {
|
||||
classes[id].linkTarget = sanitizeText(target);
|
||||
} else {
|
||||
classes[id].linkTarget = '_blank';
|
||||
}
|
||||
|
@@ -269,101 +269,8 @@ export const setConf = function (cnf) {
|
||||
* @param {string} text
|
||||
* @param {string} id
|
||||
*/
|
||||
export const drawOld = function (text, id) {
|
||||
idCache = {};
|
||||
parser.yy.clear();
|
||||
parser.parse(text);
|
||||
|
||||
log.info('Rendering diagram ' + text);
|
||||
|
||||
// Fetch the default direction, use TD if none was found
|
||||
const diagram = select(`[id='${id}']`);
|
||||
// insertMarkers(diagram);
|
||||
|
||||
// Layout graph, Create a new directed graph
|
||||
const g = new graphlib.Graph({
|
||||
multigraph: true,
|
||||
});
|
||||
|
||||
// Set an object for the graph label
|
||||
g.setGraph({
|
||||
isMultiGraph: true,
|
||||
});
|
||||
|
||||
// Default to assigning a new object as a label for each new edge.
|
||||
g.setDefaultEdgeLabel(function () {
|
||||
return {};
|
||||
});
|
||||
|
||||
const classes = classDb.getClasses();
|
||||
log.info('classes:');
|
||||
log.info(classes);
|
||||
const keys = Object.keys(classes);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const classDef = classes[keys[i]];
|
||||
const node = svgDraw.drawClass(diagram, classDef, conf);
|
||||
idCache[node.id] = node;
|
||||
|
||||
// Add nodes to the graph. The first argument is the node id. The second is
|
||||
// metadata about the node. In this case we're going to add labels to each of
|
||||
// our nodes.
|
||||
g.setNode(node.id, node);
|
||||
|
||||
log.info('Org height: ' + node.height);
|
||||
}
|
||||
|
||||
const relations = classDb.getRelations();
|
||||
log.info('relations:', relations);
|
||||
relations.forEach(function (relation) {
|
||||
log.info(
|
||||
'tjoho' + getGraphId(relation.id1) + getGraphId(relation.id2) + JSON.stringify(relation)
|
||||
);
|
||||
g.setEdge(
|
||||
getGraphId(relation.id1),
|
||||
getGraphId(relation.id2),
|
||||
{
|
||||
relation: relation,
|
||||
},
|
||||
relation.title || 'DEFAULT'
|
||||
);
|
||||
});
|
||||
|
||||
dagre.layout(g);
|
||||
g.nodes().forEach(function (v) {
|
||||
if (typeof v !== 'undefined' && typeof g.node(v) !== 'undefined') {
|
||||
log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v)));
|
||||
select('#' + lookUpDomId(v)).attr(
|
||||
'transform',
|
||||
'translate(' +
|
||||
(g.node(v).x - g.node(v).width / 2) +
|
||||
',' +
|
||||
(g.node(v).y - g.node(v).height / 2) +
|
||||
' )'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
g.edges().forEach(function (e) {
|
||||
if (typeof e !== 'undefined' && typeof g.edge(e) !== 'undefined') {
|
||||
log.debug('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(g.edge(e)));
|
||||
svgDraw.drawEdge(diagram, g.edge(e), g.edge(e).relation, conf);
|
||||
}
|
||||
});
|
||||
|
||||
const svgBounds = diagram.node().getBBox();
|
||||
const width = svgBounds.width + padding * 2;
|
||||
const height = svgBounds.height + padding * 2;
|
||||
|
||||
configureSvgSize(diagram, height, width, conf.useMaxWidth);
|
||||
|
||||
// Ensure the viewBox includes the whole svgBounds area with extra space for padding
|
||||
const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`;
|
||||
log.debug(`viewBox ${vBox}`);
|
||||
diagram.attr('viewBox', vBox);
|
||||
};
|
||||
|
||||
export const draw = function (text, id) {
|
||||
log.info('Drawing class');
|
||||
log.info('Drawing class - ', id);
|
||||
classDb.clear();
|
||||
// const parser = classDb.parser;
|
||||
// parser.yy = classDb;
|
||||
@@ -379,6 +286,7 @@ export const draw = function (text, id) {
|
||||
//let dir = 'TD';
|
||||
|
||||
const conf = getConfig().flowchart;
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
log.info('config:', conf);
|
||||
const nodeSpacing = conf.nodeSpacing || 50;
|
||||
const rankSpacing = conf.rankSpacing || 50;
|
||||
@@ -430,11 +338,19 @@ export const draw = function (text, id) {
|
||||
// flowChartShapes.addToRenderV2(addShape);
|
||||
|
||||
// Set up an SVG group so that we can translate the final graph.
|
||||
const svg = select(`[id="${id}"]`);
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const svg = root.select(`[id="${id}"]`);
|
||||
svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
const element = select('#' + id + ' g');
|
||||
const element = root.select('#' + id + ' g');
|
||||
render(element, g, ['aggregation', 'extension', 'composition', 'dependency'], 'classDiagram', id);
|
||||
|
||||
// element.selectAll('g.node').attr('title', function() {
|
||||
@@ -462,14 +378,15 @@ export const draw = function (text, id) {
|
||||
|
||||
// Add label rects for non html labels
|
||||
if (!conf.htmlLabels) {
|
||||
const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
const labels = doc.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();
|
||||
|
||||
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||
const rect = doc.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||
rect.setAttribute('rx', 0);
|
||||
rect.setAttribute('ry', 0);
|
||||
rect.setAttribute('width', dim.width);
|
||||
|
@@ -6,6 +6,7 @@ import classDb, { lookUpDomId } from './classDb';
|
||||
import { parser } from './parser/classDiagram';
|
||||
import svgDraw from './svgDraw';
|
||||
import { configureSvgSize } from '../../utils';
|
||||
import { getConfig } from '../../config';
|
||||
|
||||
parser.yy = classDb;
|
||||
|
||||
@@ -165,8 +166,20 @@ export const draw = function (text, id) {
|
||||
|
||||
log.info('Rendering diagram ' + text);
|
||||
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and ocument for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
// Fetch the default direction, use TD if none was found
|
||||
const diagram = select(`[id='${id}']`);
|
||||
const diagram = root.select(`[id='${id}']`);
|
||||
diagram.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
insertMarkers(diagram);
|
||||
|
||||
@@ -220,14 +233,16 @@ export const draw = function (text, id) {
|
||||
g.nodes().forEach(function (v) {
|
||||
if (typeof v !== 'undefined' && typeof g.node(v) !== 'undefined') {
|
||||
log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v)));
|
||||
select('#' + lookUpDomId(v)).attr(
|
||||
'transform',
|
||||
'translate(' +
|
||||
(g.node(v).x - g.node(v).width / 2) +
|
||||
',' +
|
||||
(g.node(v).y - g.node(v).height / 2) +
|
||||
' )'
|
||||
);
|
||||
root
|
||||
.select('#' + lookUpDomId(v))
|
||||
.attr(
|
||||
'transform',
|
||||
'translate(' +
|
||||
(g.node(v).x - g.node(v).width / 2) +
|
||||
',' +
|
||||
(g.node(v).y - g.node(v).height / 2) +
|
||||
' )'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -545,6 +545,17 @@ export const draw = function (text, id) {
|
||||
erDb.clear();
|
||||
const parser = erParser.parser;
|
||||
parser.yy = erDb;
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and ocument for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
// Parse the text to populate erDb
|
||||
try {
|
||||
@@ -554,7 +565,7 @@ export const draw = function (text, id) {
|
||||
}
|
||||
|
||||
// Get a reference to the svg node that contains the text
|
||||
const svg = select(`[id='${id}']`);
|
||||
const svg = root.select(`[id='${id}']`);
|
||||
|
||||
// Add cardinality marker definitions to the svg
|
||||
erMarkers.insertMarkers(svg, conf);
|
||||
|
@@ -25,9 +25,11 @@ export const setConf = function (cnf) {
|
||||
* @param vert Object containing the vertices.
|
||||
* @param g The graph that is to be drawn.
|
||||
* @param svgId
|
||||
* @param root
|
||||
* @param doc
|
||||
*/
|
||||
export const addVertices = function (vert, g, svgId) {
|
||||
const svg = select(`[id="${svgId}"]`);
|
||||
export const addVertices = function (vert, g, svgId, root, doc) {
|
||||
const svg = root.select(`[id="${svgId}"]`);
|
||||
const keys = Object.keys(vert);
|
||||
|
||||
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
|
||||
@@ -62,13 +64,13 @@ export const addVertices = function (vert, g, svgId) {
|
||||
vertexNode = addHtmlLabel(svg, node).node();
|
||||
vertexNode.parentNode.removeChild(vertexNode);
|
||||
} else {
|
||||
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:'));
|
||||
|
||||
const rows = vertexText.split(common.lineBreakRegex);
|
||||
|
||||
for (let j = 0; j < rows.length; j++) {
|
||||
const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
||||
const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
||||
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
|
||||
tspan.setAttribute('dy', '1em');
|
||||
tspan.setAttribute('x', '1');
|
||||
@@ -374,6 +376,18 @@ export const draw = function (text, id) {
|
||||
const nodeSpacing = conf.nodeSpacing || 50;
|
||||
const rankSpacing = conf.rankSpacing || 50;
|
||||
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and ocument for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
// Create the input mermaid.graph
|
||||
const g = new graphlib.Graph({
|
||||
multigraph: true,
|
||||
@@ -417,18 +431,18 @@ export const draw = function (text, id) {
|
||||
g.setParent(subG.nodes[j], subG.id);
|
||||
}
|
||||
}
|
||||
addVertices(vert, g, id);
|
||||
addVertices(vert, g, id, root, doc);
|
||||
addEdges(edges, g);
|
||||
|
||||
// Add custom shapes
|
||||
// flowChartShapes.addToRenderV2(addShape);
|
||||
|
||||
// Set up an SVG group so that we can translate the final graph.
|
||||
const svg = select(`[id="${id}"]`);
|
||||
const svg = root.select(`[id="${id}"]`);
|
||||
svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
const element = select('#' + id + ' g');
|
||||
const element = root.select('#' + id + ' g');
|
||||
render(element, g, ['point', 'circle', 'cross'], 'flowchart', id);
|
||||
|
||||
const padding = conf.diagramPadding;
|
||||
@@ -452,14 +466,14 @@ export const draw = function (text, id) {
|
||||
|
||||
// Add label rects for non html labels
|
||||
if (!conf.htmlLabels) {
|
||||
const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label');
|
||||
const labels = doc.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();
|
||||
|
||||
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||
const rect = doc.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||
rect.setAttribute('rx', 0);
|
||||
rect.setAttribute('ry', 0);
|
||||
rect.setAttribute('width', dim.width);
|
||||
@@ -478,11 +492,13 @@ export const draw = function (text, id) {
|
||||
if (vertex.link) {
|
||||
const node = select('#' + id + ' [id="' + key + '"]');
|
||||
if (node) {
|
||||
const link = document.createElementNS('http://www.w3.org/2000/svg', 'a');
|
||||
const link = doc.createElementNS('http://www.w3.org/2000/svg', 'a');
|
||||
link.setAttributeNS('http://www.w3.org/2000/svg', 'class', vertex.classes.join(' '));
|
||||
link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertex.link);
|
||||
link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener');
|
||||
if (vertex.linkTarget) {
|
||||
if (securityLevel === 'sandbox') {
|
||||
link.setAttributeNS('http://www.w3.org/2000/svg', 'target', '_top');
|
||||
} else if (vertex.linkTarget) {
|
||||
link.setAttributeNS('http://www.w3.org/2000/svg', 'target', vertex.linkTarget);
|
||||
}
|
||||
|
||||
|
@@ -26,9 +26,15 @@ export const setConf = function (cnf) {
|
||||
* @param vert Object containing the vertices.
|
||||
* @param g The graph that is to be drawn.
|
||||
* @param svgId
|
||||
* @param root
|
||||
* @param doc
|
||||
* @param _doc
|
||||
*/
|
||||
export const addVertices = function (vert, g, svgId) {
|
||||
const svg = select(`[id="${svgId}"]`);
|
||||
export const addVertices = function (vert, g, svgId, root, _doc) {
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
|
||||
const svg = !root ? select(`[id="${svgId}"]`) : root.select(`[id="${svgId}"]`);
|
||||
const doc = !_doc ? document : _doc;
|
||||
const keys = Object.keys(vert);
|
||||
|
||||
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
|
||||
@@ -63,13 +69,13 @@ export const addVertices = function (vert, g, svgId) {
|
||||
vertexNode = addHtmlLabel(svg, node).node();
|
||||
vertexNode.parentNode.removeChild(vertexNode);
|
||||
} else {
|
||||
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:'));
|
||||
|
||||
const rows = vertexText.split(common.lineBreakRegex);
|
||||
|
||||
for (let j = 0; j < rows.length; j++) {
|
||||
const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
||||
const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
||||
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
|
||||
tspan.setAttribute('dy', '1em');
|
||||
tspan.setAttribute('x', '1');
|
||||
@@ -293,6 +299,17 @@ export const draw = function (text, id) {
|
||||
const parser = flow.parser;
|
||||
parser.yy = flowDb;
|
||||
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
// Parse the graph definition
|
||||
// try {
|
||||
parser.parse(text);
|
||||
@@ -355,7 +372,7 @@ export const draw = function (text, id) {
|
||||
g.setParent(flowDb.lookUpDomId(subG.nodes[j]), flowDb.lookUpDomId(subG.id));
|
||||
}
|
||||
}
|
||||
addVertices(vert, g, id);
|
||||
addVertices(vert, g, id, root, doc);
|
||||
addEdges(edges, g);
|
||||
|
||||
// Create the renderer
|
||||
@@ -404,13 +421,13 @@ export const draw = function (text, id) {
|
||||
};
|
||||
|
||||
// Set up an SVG group so that we can translate the final graph.
|
||||
const svg = select(`[id="${id}"]`);
|
||||
const svg = root.select(`[id="${id}"]`);
|
||||
svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
|
||||
log.warn(g);
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
const element = select('#' + id + ' g');
|
||||
const element = root.select('#' + id + ' g');
|
||||
render(element, g);
|
||||
|
||||
element.selectAll('g.node').attr('title', function () {
|
||||
@@ -436,10 +453,10 @@ export const draw = function (text, id) {
|
||||
for (i = 0; i < subGraphs.length; i++) {
|
||||
subG = subGraphs[i];
|
||||
if (subG.title !== 'undefined') {
|
||||
const clusterRects = document.querySelectorAll(
|
||||
const clusterRects = doc.querySelectorAll(
|
||||
'#' + id + ' [id="' + flowDb.lookUpDomId(subG.id) + '"] rect'
|
||||
);
|
||||
const clusterEl = document.querySelectorAll(
|
||||
const clusterEl = doc.querySelectorAll(
|
||||
'#' + id + ' [id="' + flowDb.lookUpDomId(subG.id) + '"]'
|
||||
);
|
||||
|
||||
@@ -459,14 +476,14 @@ export const draw = function (text, id) {
|
||||
|
||||
// Add label rects for non html labels
|
||||
if (!evaluate(conf.htmlLabels) || true) { // eslint-disable-line
|
||||
const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label');
|
||||
const labels = doc.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();
|
||||
|
||||
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||
const rect = doc.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||
rect.setAttribute('rx', 0);
|
||||
rect.setAttribute('ry', 0);
|
||||
rect.setAttribute('width', dim.width);
|
||||
@@ -483,13 +500,15 @@ export const draw = function (text, id) {
|
||||
const vertex = vert[key];
|
||||
|
||||
if (vertex.link) {
|
||||
const node = select('#' + id + ' [id="' + flowDb.lookUpDomId(key) + '"]');
|
||||
const node = root.select('#' + id + ' [id="' + flowDb.lookUpDomId(key) + '"]');
|
||||
if (node) {
|
||||
const link = document.createElementNS('http://www.w3.org/2000/svg', 'a');
|
||||
const link = doc.createElementNS('http://www.w3.org/2000/svg', 'a');
|
||||
link.setAttributeNS('http://www.w3.org/2000/svg', 'class', vertex.classes.join(' '));
|
||||
link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertex.link);
|
||||
link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener');
|
||||
if (vertex.linkTarget) {
|
||||
if (securityLevel === 'sandbox') {
|
||||
link.setAttributeNS('http://www.w3.org/2000/svg', 'target', '_top');
|
||||
} else if (vertex.linkTarget) {
|
||||
link.setAttributeNS('http://www.w3.org/2000/svg', 'target', vertex.linkTarget);
|
||||
}
|
||||
|
||||
|
@@ -10,6 +10,7 @@ let axisFormat = '';
|
||||
let todayMarker = '';
|
||||
let includes = [];
|
||||
let excludes = [];
|
||||
let links = {};
|
||||
let title = '';
|
||||
let sections = [];
|
||||
let tasks = [];
|
||||
@@ -44,6 +45,7 @@ export const clear = function () {
|
||||
inclusiveEndDates = false;
|
||||
topAxis = false;
|
||||
lastOrder = 0;
|
||||
links = {};
|
||||
};
|
||||
|
||||
export const setAxisFormat = function (txt) {
|
||||
@@ -101,6 +103,10 @@ export const getExcludes = function () {
|
||||
return excludes;
|
||||
};
|
||||
|
||||
export const getLinks = function () {
|
||||
return links;
|
||||
};
|
||||
|
||||
export const setTitle = function (txt) {
|
||||
title = txt;
|
||||
};
|
||||
@@ -505,6 +511,7 @@ export const setLink = function (ids, _linkStr) {
|
||||
pushFun(id, () => {
|
||||
window.open(linkStr, '_self');
|
||||
});
|
||||
links[id] = linkStr;
|
||||
}
|
||||
});
|
||||
setClass(ids, 'clickable');
|
||||
@@ -642,6 +649,7 @@ export default {
|
||||
getExcludes,
|
||||
setClickEvent,
|
||||
setLink,
|
||||
getLinks,
|
||||
bindFunctions,
|
||||
durationToDate,
|
||||
isInvalidDate,
|
||||
|
@@ -29,7 +29,19 @@ export const draw = function (text, id) {
|
||||
parser.yy.clear();
|
||||
parser.parse(text);
|
||||
|
||||
const elem = document.getElementById(id);
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and ocument for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
const elem = doc.getElementById(id);
|
||||
w = elem.parentElement.offsetWidth;
|
||||
|
||||
if (typeof w === 'undefined') {
|
||||
@@ -47,7 +59,7 @@ export const draw = function (text, id) {
|
||||
|
||||
// Set viewBox
|
||||
elem.setAttribute('viewBox', '0 0 ' + w + ' ' + h);
|
||||
const svg = select(`[id="${id}"]`);
|
||||
const svg = root.select(`[id="${id}"]`);
|
||||
|
||||
// Set timescale
|
||||
const timeScale = scaleTime()
|
||||
@@ -173,6 +185,10 @@ export const draw = function (text, id) {
|
||||
// Draw the rects representing the tasks
|
||||
const rectangles = svg.append('g').selectAll('rect').data(theArray).enter();
|
||||
|
||||
const links = ganttDb.getLinks();
|
||||
|
||||
// Render the tasks with links
|
||||
// Render the other tasks
|
||||
rectangles
|
||||
.append('rect')
|
||||
.attr('id', function (d) {
|
||||
@@ -369,6 +385,32 @@ export const draw = function (text, id) {
|
||||
return classStr + ' taskText taskText' + secNum + ' ' + taskType + ' width-' + textWidth;
|
||||
}
|
||||
});
|
||||
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
|
||||
// Wrap the tasks in an a tag for working links without javascript
|
||||
if (securityLevel === 'sandbox') {
|
||||
let sandboxElement;
|
||||
sandboxElement = select('#i' + id);
|
||||
const root = select(sandboxElement.nodes()[0].contentDocument.body);
|
||||
const doc = sandboxElement.nodes()[0].contentDocument;
|
||||
|
||||
rectangles
|
||||
.filter(function (d) {
|
||||
return typeof links[d.id] !== 'undefined';
|
||||
})
|
||||
.each(function (o) {
|
||||
var taskRect = doc.querySelector('#' + o.id);
|
||||
var taskText = doc.querySelector('#' + o.id + '-text');
|
||||
const oldParent = taskRect.parentNode;
|
||||
var Link = doc.createElement('a');
|
||||
Link.setAttribute('xlink:href', links[o.id]);
|
||||
Link.setAttribute('target', '_top');
|
||||
oldParent.appendChild(Link);
|
||||
Link.appendChild(taskRect);
|
||||
Link.appendChild(taskText);
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param theGap
|
||||
@@ -505,11 +547,11 @@ export const draw = function (text, id) {
|
||||
const rows = d[0].split(common.lineBreakRegex);
|
||||
const dy = -(rows.length - 1) / 2;
|
||||
|
||||
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
svgLabel.setAttribute('dy', dy + 'em');
|
||||
|
||||
for (let j = 0; j < rows.length; j++) {
|
||||
const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
||||
const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
||||
tspan.setAttribute('alignment-baseline', 'central');
|
||||
tspan.setAttribute('x', '10');
|
||||
if (j > 0) tspan.setAttribute('dy', '1em');
|
||||
|
@@ -4,6 +4,7 @@ import db from './gitGraphAst';
|
||||
import gitGraphParser from './parser/gitGraph';
|
||||
import { log } from '../../logger';
|
||||
import { interpolateToCurve } from '../../utils';
|
||||
import { getConfig } from '../../config';
|
||||
|
||||
let allCommitsDict = {};
|
||||
let branchNum;
|
||||
@@ -338,6 +339,18 @@ export const draw = function (txt, id, ver) {
|
||||
parser.yy = db;
|
||||
parser.yy.clear();
|
||||
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and ocument for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
log.debug('in gitgraph renderer', txt + '\n', 'id:', id, ver);
|
||||
// Parse the graph definition
|
||||
parser.parse(txt + '\n');
|
||||
@@ -352,7 +365,7 @@ export const draw = function (txt, id, ver) {
|
||||
config.nodeLabel.width = '100%';
|
||||
config.nodeLabel.y = -1 * 2 * config.nodeRadius;
|
||||
}
|
||||
const svg = select(`[id="${id}"]`);
|
||||
const svg = root.select(`[id="${id}"]`);
|
||||
svgCreateDefs(svg);
|
||||
branchNum = 1;
|
||||
for (let branch in branches) {
|
||||
|
@@ -3,6 +3,7 @@ import { select } from 'd3';
|
||||
import db from './infoDb';
|
||||
import infoParser from './parser/info';
|
||||
import { log } from '../../logger';
|
||||
import { getConfig } from '../../config';
|
||||
|
||||
const conf = {};
|
||||
export const setConf = function (cnf) {
|
||||
@@ -25,11 +26,24 @@ export const draw = (text, id, version) => {
|
||||
const parser = infoParser.parser;
|
||||
parser.yy = db;
|
||||
log.debug('Renering info diagram\n' + text);
|
||||
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and ocument for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
// Parse the graph definition
|
||||
parser.parse(text);
|
||||
log.debug('Parsed info diagram');
|
||||
// Fetch the default direction, use TD if none was found
|
||||
const svg = select('#' + id);
|
||||
const svg = root.select('#' + id);
|
||||
|
||||
const g = svg.append('g');
|
||||
|
||||
|
@@ -22,11 +22,24 @@ export const draw = (txt, id) => {
|
||||
const parser = pieParser.parser;
|
||||
parser.yy = pieData;
|
||||
log.debug('Rendering info diagram\n' + txt);
|
||||
|
||||
const securityLevel = configApi.getConfig().securityLevel;
|
||||
// Handle root and ocument for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
// Parse the Pie Chart definition
|
||||
parser.yy.clear();
|
||||
parser.parse(txt);
|
||||
log.debug('Parsed info diagram');
|
||||
const elem = document.getElementById(id);
|
||||
const elem = doc.getElementById(id);
|
||||
width = elem.parentElement.offsetWidth;
|
||||
|
||||
if (typeof width === 'undefined') {
|
||||
@@ -40,7 +53,7 @@ export const draw = (txt, id) => {
|
||||
width = conf.pie.useWidth;
|
||||
}
|
||||
|
||||
const diagram = select('#' + id);
|
||||
const diagram = root.select('#' + id);
|
||||
configureSvgSize(diagram, height, width, conf.pie.useMaxWidth);
|
||||
|
||||
// Set viewBox
|
||||
|
@@ -8,6 +8,7 @@ import common from '../common/common';
|
||||
import { parser } from './parser/requirementDiagram';
|
||||
import requirementDb from './requirementDb';
|
||||
import markers from './requirementMarkers';
|
||||
import { getConfig } from '../../config';
|
||||
|
||||
const conf = {};
|
||||
let relCnt = 0;
|
||||
@@ -321,7 +322,19 @@ export const draw = (text, id) => {
|
||||
parser.yy.clear();
|
||||
parser.parse(text);
|
||||
|
||||
const svg = select(`[id='${id}']`);
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and ocument for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
const svg = root.select(`[id='${id}']`);
|
||||
markers.insertLineEndings(svg, conf);
|
||||
|
||||
const g = new graphlib.Graph({
|
||||
|
@@ -452,13 +452,20 @@ export const drawActors = function (diagram, actors, actorKeys, verticalPos) {
|
||||
bounds.bumpVerticalPos(maxHeight);
|
||||
};
|
||||
|
||||
export const drawActorsPopup = function (diagram, actors, actorKeys) {
|
||||
export const drawActorsPopup = function (diagram, actors, actorKeys, doc) {
|
||||
var maxHeight = 0;
|
||||
var maxWidth = 0;
|
||||
for (let i = 0; i < actorKeys.length; i++) {
|
||||
const actor = actors[actorKeys[i]];
|
||||
const minMenuWidth = getRequiredPopupWidth(actor);
|
||||
var menuDimensions = svgDraw.drawPopup(diagram, actor, minMenuWidth, conf, conf.forceMenus);
|
||||
var menuDimensions = svgDraw.drawPopup(
|
||||
diagram,
|
||||
actor,
|
||||
minMenuWidth,
|
||||
conf,
|
||||
conf.forceMenus,
|
||||
doc
|
||||
);
|
||||
if (menuDimensions.height > maxHeight) {
|
||||
maxHeight = menuDimensions.height;
|
||||
}
|
||||
@@ -539,13 +546,26 @@ function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoop
|
||||
*/
|
||||
export const draw = function (text, id) {
|
||||
conf = configApi.getConfig().sequence;
|
||||
const securityLevel = configApi.getConfig().securityLevel;
|
||||
// Handle root and ocument for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
parser.yy.clear();
|
||||
parser.yy.setWrap(conf.wrap);
|
||||
parser.parse(text + '\n');
|
||||
bounds.init();
|
||||
log.debug(`C:${JSON.stringify(conf, null, 2)}`);
|
||||
|
||||
const diagram = select(`[id="${id}"]`);
|
||||
const diagram =
|
||||
securityLevel === 'sandbox' ? root.select(`[id="${id}"]`) : select(`[id="${id}"]`);
|
||||
|
||||
// Fetch data from the parsing
|
||||
const actors = parser.yy.getActors();
|
||||
@@ -733,7 +753,7 @@ export const draw = function (text, id) {
|
||||
}
|
||||
|
||||
// only draw popups for the top row of actors.
|
||||
var requiredBoxSize = drawActorsPopup(diagram, actors, actorKeys);
|
||||
var requiredBoxSize = drawActorsPopup(diagram, actors, actorKeys, doc);
|
||||
|
||||
const { bounds: box } = bounds.getBounds();
|
||||
|
||||
|
@@ -30,6 +30,8 @@ export const drawRect = function (elem, rectData) {
|
||||
const addPopupInteraction = (id, actorCnt) => {
|
||||
addFunction(() => {
|
||||
const arr = document.querySelectorAll(id);
|
||||
// This will be the case when running in sandboxed mode
|
||||
if (arr.length === 0) return;
|
||||
arr[0].addEventListener('mouseover', function () {
|
||||
popupMenuUpFunc('actor' + actorCnt + '_popup');
|
||||
});
|
||||
|
@@ -258,6 +258,8 @@ export const draw = function (text, id) {
|
||||
const nodeSpacing = conf.nodeSpacing || 50;
|
||||
const rankSpacing = conf.rankSpacing || 50;
|
||||
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
|
||||
log.info(stateDb.getRootDocV2());
|
||||
stateDb.extract(stateDb.getRootDocV2());
|
||||
log.info(stateDb.getRootDocV2());
|
||||
@@ -281,10 +283,20 @@ export const draw = function (text, id) {
|
||||
setupNode(g, undefined, stateDb.getRootDocV2(), true);
|
||||
|
||||
// Set up an SVG group so that we can translate the final graph.
|
||||
const svg = select(`[id="${id}"]`);
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
const svg = root.select(`[id="${id}"]`);
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
const element = select('#' + id + ' g');
|
||||
|
||||
const element = root.select('#' + id + ' g');
|
||||
render(element, g, ['barb'], 'statediagram', id);
|
||||
|
||||
const padding = 8;
|
||||
|
@@ -46,12 +46,24 @@ const insertMarkers = function (elem) {
|
||||
*/
|
||||
export const draw = function (text, id) {
|
||||
conf = getConfig().state;
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and ocument for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
parser.yy.clear();
|
||||
parser.parse(text);
|
||||
log.debug('Rendering diagram ' + text);
|
||||
|
||||
// Fetch the default direction, use TD if none was found
|
||||
const diagram = select(`[id='${id}']`);
|
||||
const diagram = root.select(`[id='${id}']`);
|
||||
insertMarkers(diagram);
|
||||
|
||||
// Layout graph, Create a new directed graph
|
||||
@@ -69,7 +81,7 @@ export const draw = function (text, id) {
|
||||
});
|
||||
|
||||
const rootDoc = stateDb.getRootDoc();
|
||||
renderDoc(rootDoc, diagram, undefined, false);
|
||||
renderDoc(rootDoc, diagram, undefined, false, root, doc);
|
||||
|
||||
const padding = conf.padding;
|
||||
const bounds = diagram.node().getBBox();
|
||||
@@ -90,7 +102,7 @@ const getLabelWidth = (text) => {
|
||||
return text ? text.length * conf.fontSizeFactor : 1;
|
||||
};
|
||||
|
||||
const renderDoc = (doc, diagram, parentId, altBkg) => {
|
||||
const renderDoc = (doc, diagram, parentId, altBkg, root, domDocument) => {
|
||||
// Layout graph, Create a new directed graph
|
||||
const graph = new graphlib.Graph({
|
||||
compound: true,
|
||||
@@ -159,7 +171,7 @@ const renderDoc = (doc, diagram, parentId, altBkg) => {
|
||||
let node;
|
||||
if (stateDef.doc) {
|
||||
let sub = diagram.append('g').attr('id', stateDef.id).attr('class', 'stateGroup');
|
||||
node = renderDoc(stateDef.doc, sub, stateDef.id, !altBkg);
|
||||
node = renderDoc(stateDef.doc, sub, stateDef.id, !altBkg, root, domDocument);
|
||||
|
||||
if (first) {
|
||||
// first = false;
|
||||
@@ -234,21 +246,22 @@ const renderDoc = (doc, diagram, parentId, altBkg) => {
|
||||
graph.nodes().forEach(function (v) {
|
||||
if (typeof v !== 'undefined' && typeof graph.node(v) !== 'undefined') {
|
||||
log.warn('Node ' + v + ': ' + JSON.stringify(graph.node(v)));
|
||||
select('#' + svgElem.id + ' #' + v).attr(
|
||||
'transform',
|
||||
'translate(' +
|
||||
(graph.node(v).x - graph.node(v).width / 2) +
|
||||
',' +
|
||||
(graph.node(v).y +
|
||||
(transformationLog[v] ? transformationLog[v].y : 0) -
|
||||
graph.node(v).height / 2) +
|
||||
' )'
|
||||
);
|
||||
select('#' + svgElem.id + ' #' + v).attr(
|
||||
'data-x-shift',
|
||||
graph.node(v).x - graph.node(v).width / 2
|
||||
);
|
||||
const dividers = document.querySelectorAll('#' + svgElem.id + ' #' + v + ' .divider');
|
||||
root
|
||||
.select('#' + svgElem.id + ' #' + v)
|
||||
.attr(
|
||||
'transform',
|
||||
'translate(' +
|
||||
(graph.node(v).x - graph.node(v).width / 2) +
|
||||
',' +
|
||||
(graph.node(v).y +
|
||||
(transformationLog[v] ? transformationLog[v].y : 0) -
|
||||
graph.node(v).height / 2) +
|
||||
' )'
|
||||
);
|
||||
root
|
||||
.select('#' + svgElem.id + ' #' + v)
|
||||
.attr('data-x-shift', graph.node(v).x - graph.node(v).width / 2);
|
||||
const dividers = domDocument.querySelectorAll('#' + svgElem.id + ' #' + v + ' .divider');
|
||||
dividers.forEach((divider) => {
|
||||
const parent = divider.parentElement;
|
||||
let pWidth = 0;
|
||||
|
@@ -54,8 +54,20 @@ export const draw = function (text, id) {
|
||||
parser.yy.clear();
|
||||
parser.parse(text + '\n');
|
||||
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and ocument for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
bounds.init();
|
||||
const diagram = select('#' + id);
|
||||
const diagram = root.select('#' + id);
|
||||
diagram.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
|
||||
svgDraw.initGraphics(diagram);
|
||||
|
@@ -83,6 +83,7 @@ const init = function () {
|
||||
let txt;
|
||||
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
// element is the current div with mermaid class
|
||||
const element = nodes[i];
|
||||
|
||||
/*! Check if previously processed */
|
||||
|
@@ -232,10 +232,43 @@ const render = function (id, _txt, cb, container) {
|
||||
txt = 'graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa';
|
||||
}
|
||||
|
||||
// let d3Iframe;
|
||||
let root = select('body');
|
||||
|
||||
// In regular execurtion the container will be the div with a mermaid class
|
||||
if (typeof container !== 'undefined') {
|
||||
if (cnf.securityLevel === 'sandbox') {
|
||||
// IF we are in sandboxed mode, we do everyting mermaid related
|
||||
// in a sandboxed div
|
||||
const iframe = select('body')
|
||||
.append('iframe')
|
||||
.attr('id', 'i' + id)
|
||||
.attr('style', 'width: 100%; height: 100%;')
|
||||
.attr('sandbox', '');
|
||||
// const iframeBody = ;
|
||||
root = select(iframe.nodes()[0].contentDocument.body);
|
||||
root.node().style.margin = 0;
|
||||
}
|
||||
|
||||
// A container was provided by the caller
|
||||
container.innerHTML = '';
|
||||
|
||||
select(container)
|
||||
if (cnf.securityLevel === 'sandbox') {
|
||||
// IF we are in sandboxed mode, we do everyting mermaid related
|
||||
// in a sandboxed div
|
||||
const iframe = select(container)
|
||||
.append('iframe')
|
||||
.attr('id', 'i' + id)
|
||||
.attr('style', 'width: 100%; height: 100%;')
|
||||
.attr('sandbox', '');
|
||||
// const iframeBody = ;
|
||||
root = select(iframe.nodes()[0].contentDocument.body);
|
||||
root.node().style.margin = 0;
|
||||
} else {
|
||||
root = select(container);
|
||||
}
|
||||
|
||||
root
|
||||
.append('div')
|
||||
.attr('id', 'd' + id)
|
||||
.attr('style', 'font-family: ' + cnf.fontFamily)
|
||||
@@ -245,18 +278,57 @@ const render = function (id, _txt, cb, container) {
|
||||
.attr('xmlns', 'http://www.w3.org/2000/svg')
|
||||
.append('g');
|
||||
} else {
|
||||
// No container was provided
|
||||
// If there is an existsing element with the id, we remove it
|
||||
// this likley a previously rendered diagram
|
||||
const existingSvg = document.getElementById(id);
|
||||
if (existingSvg) {
|
||||
existingSvg.remove();
|
||||
}
|
||||
const element = document.querySelector('#' + 'd' + id);
|
||||
|
||||
// Remove previous tpm element if it exists
|
||||
let element;
|
||||
if (cnf.securityLevel !== 'sandbox') {
|
||||
element = document.querySelector('#' + 'd' + id);
|
||||
} else {
|
||||
element = document.querySelector('#' + 'i' + id);
|
||||
}
|
||||
if (element) {
|
||||
element.remove();
|
||||
}
|
||||
|
||||
select('body')
|
||||
// if (cnf.securityLevel === 'sandbox') {
|
||||
// const iframe = select('body')
|
||||
// .append('iframe')
|
||||
// .attr('id', 'i' + id)
|
||||
// .attr('sandbox', '');
|
||||
// // const iframeBody = ;
|
||||
// root = select(iframe.nodes()[0].contentDocument.body);
|
||||
// }
|
||||
|
||||
// Add the tmp div used for rendering with the id `d${id}`
|
||||
// d+id it will contain a svg with the id "id"
|
||||
|
||||
if (cnf.securityLevel === 'sandbox') {
|
||||
// IF we are in sandboxed mode, we do everyting mermaid related
|
||||
// in a sandboxed div
|
||||
const iframe = select('body')
|
||||
.append('iframe')
|
||||
.attr('id', 'i' + id)
|
||||
.attr('style', 'width: 100%; height: 100%;')
|
||||
.attr('sandbox', '');
|
||||
// const iframeBody = ;
|
||||
root = select(iframe.nodes()[0].contentDocument.body);
|
||||
root.node().style.margin = 0;
|
||||
} else {
|
||||
root = select('body');
|
||||
}
|
||||
|
||||
// This is the temporary div
|
||||
root
|
||||
.append('div')
|
||||
.attr('id', 'd' + id)
|
||||
// this is the seed of the svg to be rendered
|
||||
.append('svg')
|
||||
.attr('id', id)
|
||||
.attr('width', '100%')
|
||||
@@ -264,10 +336,10 @@ const render = function (id, _txt, cb, container) {
|
||||
.append('g');
|
||||
}
|
||||
|
||||
window.txt = txt;
|
||||
txt = encodeEntities(txt);
|
||||
|
||||
const element = select('#d' + id).node();
|
||||
// Get the tmp element containing the the svg
|
||||
const element = root.select('#d' + id).node();
|
||||
const graphType = utils.detectType(txt, cnf);
|
||||
|
||||
// insert inline style into svg
|
||||
@@ -430,14 +502,19 @@ const render = function (id, _txt, cb, container) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
select(`[id="${id}"]`)
|
||||
root
|
||||
.select(`[id="${id}"]`)
|
||||
.selectAll('foreignobject > *')
|
||||
.attr('xmlns', 'http://www.w3.org/1999/xhtml');
|
||||
|
||||
// Fix for when the base tag is used
|
||||
let svgCode = select('#d' + id).node().innerHTML;
|
||||
let svgCode = root.select('#d' + id).node().innerHTML;
|
||||
|
||||
log.debug('cnf.arrowMarkerAbsolute', cnf.arrowMarkerAbsolute);
|
||||
if (!cnf.arrowMarkerAbsolute || cnf.arrowMarkerAbsolute === 'false') {
|
||||
if (
|
||||
(!cnf.arrowMarkerAbsolute || cnf.arrowMarkerAbsolute === 'false') &&
|
||||
cnf.arrowMarkerAbsolute !== 'sandbox'
|
||||
) {
|
||||
svgCode = svgCode.replace(/marker-end="url\(.*?#/g, 'marker-end="url(#', 'g');
|
||||
}
|
||||
|
||||
@@ -446,6 +523,21 @@ const render = function (id, _txt, cb, container) {
|
||||
// Fix for when the br tag is used
|
||||
svgCode = svgCode.replace(/<br>/g, '<br/>');
|
||||
|
||||
if (cnf.securityLevel === 'sandbox') {
|
||||
let svgEl = root.select('#d' + id + ' svg').node();
|
||||
let width = '100%';
|
||||
let height = '100%';
|
||||
if (svgEl) {
|
||||
// width = svgEl.viewBox.baseVal.width + 'px';
|
||||
height = svgEl.viewBox.baseVal.height + 'px';
|
||||
}
|
||||
svgCode = `<iframe style="width:${width};height:${height};border:0;margin:0;" src="data:text/html;base64,${btoa(
|
||||
'<body style="margin:0">' + svgCode + '</body>'
|
||||
)}" sandbox="allow-top-navigation-by-user-activation allow-popups">
|
||||
The “iframe” tag is not supported by your browser.
|
||||
</iframe>`;
|
||||
}
|
||||
|
||||
if (typeof cb !== 'undefined') {
|
||||
switch (graphType) {
|
||||
case 'flowchart':
|
||||
@@ -467,11 +559,10 @@ const render = function (id, _txt, cb, container) {
|
||||
}
|
||||
attachFunctions();
|
||||
|
||||
const node = select('#d' + id).node();
|
||||
const tmpElementSelector = cnf.securityLevel === 'sandbox' ? '#i' + id : '#d' + id;
|
||||
const node = select(tmpElementSelector).node();
|
||||
if (node !== null && typeof node.remove === 'function') {
|
||||
select('#d' + id)
|
||||
.node()
|
||||
.remove();
|
||||
select(tmpElementSelector).node().remove();
|
||||
}
|
||||
|
||||
return svgCode;
|
||||
@@ -570,6 +661,7 @@ function updateRendererConfigs(conf) {
|
||||
errorRenderer.setConf(conf.class);
|
||||
}
|
||||
|
||||
/** To be removed */
|
||||
function reinitialize() {
|
||||
// `mermaidAPI.reinitialize: v${pkg.version}`,
|
||||
// JSON.stringify(options),
|
||||
|
Reference in New Issue
Block a user