mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-28 07:03:17 +08:00
commit
280c89a78d
@ -214,7 +214,7 @@ pie
|
|||||||
|
|
||||||
## Related projects
|
## Related projects
|
||||||
|
|
||||||
- [Command Line Interface](https://github.com/mermaid-js/mermaid-cli)
|
- [Command Line Interface](https://github.com/mermaid-js/mermaid.cli)
|
||||||
- [Live Editor](https://github.com/mermaid-js/mermaid-live-editor)
|
- [Live Editor](https://github.com/mermaid-js/mermaid-live-editor)
|
||||||
- [HTTP Server](https://github.com/TomWright/mermaid-server)
|
- [HTTP Server](https://github.com/TomWright/mermaid-server)
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ describe('Configuration', () => {
|
|||||||
C -->|Three| F[fa:fa-car Car]
|
C -->|Three| F[fa:fa-car Car]
|
||||||
`,
|
`,
|
||||||
{
|
{
|
||||||
logLevel:0, arrowMarkerAbsolute: true,fontFamily: '"Noto Sans SC", sans-serif'
|
arrowMarkerAbsolute: true
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
/* eslint-env jest */
|
/* eslint-env jest */
|
||||||
describe('Rerendering', () => {
|
describe('Rerendering', () => {
|
||||||
|
it('should be able to render after an error has occured', () => {
|
||||||
|
const url = 'http://localhost:9000/render-after-error.html';
|
||||||
|
cy.viewport(1440, 1024);
|
||||||
|
cy.visit(url);
|
||||||
|
cy.get('#graphDiv').should('exist');
|
||||||
|
});
|
||||||
|
|
||||||
it('should be able to render and rerender a graph via API', () => {
|
it('should be able to render and rerender a graph via API', () => {
|
||||||
const url = 'http://localhost:9000/rerender.html';
|
const url = 'http://localhost:9000/rerender.html';
|
||||||
|
@ -4,15 +4,16 @@
|
|||||||
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
|
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
|
||||||
rel="stylesheet"
|
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 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">
|
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
/* background: rgb(221, 208, 208); */
|
/* background: rgb(221, 208, 208); */
|
||||||
background:#333;
|
/* background:#333; */
|
||||||
font-family: 'Arial';
|
font-family: 'Arial';
|
||||||
}
|
}
|
||||||
h1 { color: white;}
|
h1 { color: grey;}
|
||||||
.mermaid2 {
|
.mermaid2 {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -20,44 +21,58 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>info below</h1>
|
<h1>info below</h1>
|
||||||
|
<div class="flex">
|
||||||
|
<div class="mermaid2" style="width: 50%; height: 20%;">
|
||||||
|
flowchart BT
|
||||||
|
subgraph two
|
||||||
|
b1
|
||||||
|
end
|
||||||
|
subgraph three
|
||||||
|
c1-->c2
|
||||||
|
end
|
||||||
|
c1 --apa apa apa--> b1
|
||||||
|
two --> c2
|
||||||
|
</div>
|
||||||
<div class="mermaid" style="width: 50%; height: 20%;">
|
<div class="mermaid" style="width: 50%; height: 20%;">
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
Alice->>Bob:Extremely utterly long line of longness which had preivously overflown the actor box as it is much longer than what it should be
|
Alice->>Bob:Extremely utterly long line of longness which had preivously overflown the actor box as it is much longer than what it should be
|
||||||
Bob->>Alice: I'm short though
|
Bob->>Alice: I'm short though
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mermaid2" style="width: 50%; height: 20%;">
|
<div class="mermaid2" style="width: 50%; height: 20%;">
|
||||||
flowchart TB
|
flowchart TB
|
||||||
subgraph 1
|
subgraph two
|
||||||
A --> B;
|
b1
|
||||||
A -.-> C;
|
end
|
||||||
A ==> D;
|
subgraph three
|
||||||
A ==> E;
|
c1-->c2
|
||||||
B <--> F
|
end
|
||||||
C <--> F
|
c1 --apa apa apa--> b1
|
||||||
D <--> F
|
b1 --> c2
|
||||||
E <--> F
|
</div>
|
||||||
end
|
<div class="mermaid" style="width: 50%; height: 20%;">
|
||||||
subgraph 2
|
|
||||||
A2 --x B2;
|
flowchart BT
|
||||||
A2 -.-x C2;
|
subgraph a
|
||||||
A2 ==x D2;
|
b1 -- ok --> b2
|
||||||
A2 ==x E2;
|
end
|
||||||
B2 x--x F2
|
a -- sert --> c
|
||||||
C2 x--x F2
|
c --> d
|
||||||
D2 x--x F2
|
b1 --> d
|
||||||
E2 x--x F2
|
a --asd123 --> d
|
||||||
end
|
</div>
|
||||||
subgraph 3
|
<div class="mermaid2" style="width: 50%; height: 20%;">
|
||||||
A3 --o B3;
|
stateDiagram-v2
|
||||||
A3 -.-o C3;
|
state A {
|
||||||
A3 ==o D3;
|
B1 --> B2: ok
|
||||||
A3 ==o E3;
|
}
|
||||||
B3 o--o F3
|
A --> C: sert
|
||||||
C3 o--o F3
|
C --> D
|
||||||
D3 o--o F3
|
B1 --> D
|
||||||
E3 o--o F3
|
A --> D: asd123
|
||||||
end
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mermaid2" style="width: 50%; height: 20%;">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="./mermaid.js"></script>
|
<script src="./mermaid.js"></script>
|
||||||
@ -66,18 +81,17 @@ flowchart TB
|
|||||||
// console.error('Mermaid error: ', err);
|
// console.error('Mermaid error: ', err);
|
||||||
};
|
};
|
||||||
mermaid.initialize({
|
mermaid.initialize({
|
||||||
theme: 'dark',
|
// theme: 'dark',
|
||||||
// arrowMarkerAbsolute: true,
|
// arrowMarkerAbsolute: true,
|
||||||
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
||||||
logLevel: 0,
|
logLevel: 0,
|
||||||
flowchart: { curve: 'linear',htmlLabels: false },
|
flowchart: { curve: 'linear', "htmlLabels": false },
|
||||||
// gantt: { axisFormat: '%m/%d/%Y' },
|
// gantt: { axisFormat: '%m/%d/%Y' },
|
||||||
sequence: { actorMargin: 50, showSequenceNumbers: true },
|
sequence: { actorMargin: 50, showSequenceNumbers: true },
|
||||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||||
fontFamily: '"arial", sans-serif',
|
fontFamily: '"arial", sans-serif',
|
||||||
curve: 'linear',
|
curve: 'linear',
|
||||||
securityLevel: 'loose',
|
securityLevel: 'loose'
|
||||||
htmlLabels: false
|
|
||||||
});
|
});
|
||||||
function callback(){alert('It worked');}
|
function callback(){alert('It worked');}
|
||||||
</script>
|
</script>
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
/* font-family: 'Mansalva', cursive;*/
|
/* font-family: 'Mansalva', cursive;*/
|
||||||
font-family: '"Noto Sans SC", sans-serif';
|
font-family: 'Mansalva', cursive;
|
||||||
}
|
|
||||||
.mermaid-main-font {
|
|
||||||
font-family: '"Noto Sans SC", sans-serif';
|
|
||||||
/* font-family: var(--mermaid-font-family); */
|
|
||||||
}
|
}
|
||||||
|
/* .mermaid-main-font {
|
||||||
|
font-family: "trebuchet ms", verdana, arial;
|
||||||
|
font-family: var(--mermaid-font-family);
|
||||||
|
} */
|
||||||
/* :root {
|
/* :root {
|
||||||
--mermaid-font-family: '"trebuchet ms", verdana, arial';
|
--mermaid-font-family: '"trebuchet ms", verdana, arial';
|
||||||
--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive;
|
--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive;
|
||||||
@ -27,7 +27,7 @@
|
|||||||
<script>
|
<script>
|
||||||
// Notice startOnLoad=false
|
// Notice startOnLoad=false
|
||||||
// This prevents default handling in mermaid from render before the e2e logic is applied
|
// This prevents default handling in mermaid from render before the e2e logic is applied
|
||||||
window.mermaidDefault = {
|
mermaid.initialize({
|
||||||
startOnLoad: false,
|
startOnLoad: false,
|
||||||
useMaxWidth: true,
|
useMaxWidth: true,
|
||||||
// "themeCSS": ":root { --mermaid-font-family: \"trebuchet ms\", verdana, arial;}",
|
// "themeCSS": ":root { --mermaid-font-family: \"trebuchet ms\", verdana, arial;}",
|
||||||
@ -35,8 +35,7 @@
|
|||||||
// fontFamily: '"Comic Sans MS", "Comic Sans", cursive'
|
// fontFamily: '"Comic Sans MS", "Comic Sans", cursive'
|
||||||
// fontFamily: '"Mansalva", cursive',
|
// fontFamily: '"Mansalva", cursive',
|
||||||
fontFamily: '"Noto Sans SC", sans-serif'
|
fontFamily: '"Noto Sans SC", sans-serif'
|
||||||
};
|
});
|
||||||
mermaid.initialize(window.mermaidDefault);
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
32
cypress/platform/render-after-error.html
Normal file
32
cypress/platform/render-after-error.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<!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=">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="graph">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="./mermaid.js"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
mermaid.init({ startOnLoad: false });
|
||||||
|
mermaid.mermaidAPI.initialize();
|
||||||
|
|
||||||
|
try{
|
||||||
|
mermaid.mermaidAPI.render("graphDiv",
|
||||||
|
`>`);
|
||||||
|
} catch(e){}
|
||||||
|
|
||||||
|
mermaid.mermaidAPI.render("graphDiv",
|
||||||
|
`graph LR\n a --> b`, html => {
|
||||||
|
document.getElementById('graph').innerHTML=html;
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -30,11 +30,6 @@ const contentLoaded = function() {
|
|||||||
div.innerHTML = graphObj.code;
|
div.innerHTML = graphObj.code;
|
||||||
document.getElementsByTagName('body')[0].appendChild(div);
|
document.getElementsByTagName('body')[0].appendChild(div);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.mermaidDefault.fontFamily) {
|
|
||||||
graphObj.mermaid.fontFamily = window.mermaidDefault.fontFamily;
|
|
||||||
}
|
|
||||||
|
|
||||||
global.mermaid.initialize(graphObj.mermaid);
|
global.mermaid.initialize(graphObj.mermaid);
|
||||||
global.mermaid.init();
|
global.mermaid.init();
|
||||||
}
|
}
|
||||||
|
1609
dist/mermaid.core.js
vendored
1609
dist/mermaid.core.js
vendored
File diff suppressed because one or more lines are too long
2
dist/mermaid.core.js.map
vendored
2
dist/mermaid.core.js.map
vendored
File diff suppressed because one or more lines are too long
1609
dist/mermaid.js
vendored
1609
dist/mermaid.js
vendored
File diff suppressed because one or more lines are too long
2
dist/mermaid.js.map
vendored
2
dist/mermaid.js.map
vendored
File diff suppressed because one or more lines are too long
12
dist/mermaid.min.js
vendored
12
dist/mermaid.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/mermaid.min.js.map
vendored
2
dist/mermaid.min.js.map
vendored
File diff suppressed because one or more lines are too long
@ -34,7 +34,7 @@
|
|||||||
window.$docsify = {
|
window.$docsify = {
|
||||||
search: 'auto',
|
search: 'auto',
|
||||||
name: 'mermaid',
|
name: 'mermaid',
|
||||||
repo: 'https://github.com/mermaid-js/mermaid',
|
repo: 'https://github.com/knsv/mermaid',
|
||||||
loadSidebar: true,
|
loadSidebar: true,
|
||||||
mergeNavbar: true,
|
mergeNavbar: true,
|
||||||
maxLevel: 4,
|
maxLevel: 4,
|
||||||
|
@ -2,6 +2,8 @@ import { logger } from '../logger'; // eslint-disable-line
|
|||||||
import createLabel from './createLabel';
|
import createLabel from './createLabel';
|
||||||
import { line, curveBasis, select } from 'd3';
|
import { line, curveBasis, select } from 'd3';
|
||||||
import { getConfig } from '../config';
|
import { getConfig } from '../config';
|
||||||
|
import utils from '../utils';
|
||||||
|
// import { calcLabelPosition } from '../utils';
|
||||||
|
|
||||||
let edgeLabels = {};
|
let edgeLabels = {};
|
||||||
|
|
||||||
@ -39,11 +41,19 @@ export const insertEdgeLabel = (elem, edge) => {
|
|||||||
edge.height = bbox.height;
|
edge.height = bbox.height;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const positionEdgeLabel = edge => {
|
export const positionEdgeLabel = (edge, points) => {
|
||||||
logger.info('Moving label', edge.id, edge.label, edgeLabels[edge.id]);
|
logger.info('Moving label', edge.id, edge.label, edgeLabels[edge.id]);
|
||||||
if (edge.label) {
|
if (edge.label) {
|
||||||
const el = edgeLabels[edge.id];
|
const el = edgeLabels[edge.id];
|
||||||
el.attr('transform', 'translate(' + edge.x + ', ' + edge.y + ')');
|
let x = edge.x;
|
||||||
|
let y = edge.y;
|
||||||
|
if (points) {
|
||||||
|
// debugger;
|
||||||
|
const pos = utils.calcLabelPosition(points);
|
||||||
|
x = pos.x;
|
||||||
|
y = pos.y;
|
||||||
|
}
|
||||||
|
el.attr('transform', 'translate(' + x + ', ' + y + ')');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -61,47 +71,80 @@ export const positionEdgeLabel = edge => {
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
const outsideNode = (node, point) => {
|
const outsideNode = (node, point) => {
|
||||||
|
// logger.warn('Checking bounds ', node, point);
|
||||||
const x = node.x;
|
const x = node.x;
|
||||||
const y = node.y;
|
const y = node.y;
|
||||||
const dx = Math.abs(point.x - x);
|
const dx = Math.abs(point.x - x);
|
||||||
const dy = Math.abs(point.y - y);
|
const dy = Math.abs(point.y - y);
|
||||||
const w = node.width / 2;
|
const w = node.width / 2;
|
||||||
const h = node.height / 2;
|
const h = node.height / 2;
|
||||||
if (dx > w || dy > h) {
|
if (dx >= w || dy >= h) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const intersection = (node, outsidePoint, insidePoint) => {
|
export const intersection = (node, outsidePoint, insidePoint) => {
|
||||||
logger.trace('intersection o:', outsidePoint, ' i:', insidePoint, node);
|
logger.warn('intersection calc o:', outsidePoint, ' i:', insidePoint, node);
|
||||||
const x = node.x;
|
const x = node.x;
|
||||||
const y = node.y;
|
const y = node.y;
|
||||||
|
|
||||||
const dx = Math.abs(x - insidePoint.x);
|
const dx = Math.abs(x - insidePoint.x);
|
||||||
const w = node.width / 2;
|
const w = node.width / 2;
|
||||||
let r = insidePoint.x < outsidePoint.x ? w - dx : w + dx;
|
let r = insidePoint.x < outsidePoint.x ? w - dx : w + dx;
|
||||||
const dy = Math.abs(y - insidePoint.y);
|
|
||||||
const h = node.height / 2;
|
const h = node.height / 2;
|
||||||
let q = insidePoint.y < outsidePoint.y ? h - dy : h - dy;
|
|
||||||
|
const edges = {
|
||||||
|
x1: x - w,
|
||||||
|
x2: x + w,
|
||||||
|
y1: y - h,
|
||||||
|
y2: y + h
|
||||||
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
outsidePoint.x === edges.x1 ||
|
||||||
|
outsidePoint.x === edges.x2 ||
|
||||||
|
outsidePoint.y === edges.y1 ||
|
||||||
|
outsidePoint.y === edges.y2
|
||||||
|
) {
|
||||||
|
// logger.warn('calc equals on edge');
|
||||||
|
return outsidePoint;
|
||||||
|
}
|
||||||
|
|
||||||
const Q = Math.abs(outsidePoint.y - insidePoint.y);
|
const Q = Math.abs(outsidePoint.y - insidePoint.y);
|
||||||
const R = Math.abs(outsidePoint.x - insidePoint.x);
|
const R = Math.abs(outsidePoint.x - insidePoint.x);
|
||||||
if (Math.abs(y - outsidePoint.y) * w > Math.abs(x - outsidePoint.x) * h || false) { // eslint-disable-line
|
// log.warn();
|
||||||
|
if (Math.abs(y - outsidePoint.y) * w > Math.abs(x - outsidePoint.x) * h) { // eslint-disable-line
|
||||||
// Intersection is top or bottom of rect.
|
// Intersection is top or bottom of rect.
|
||||||
|
// let q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y;
|
||||||
|
let q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y;
|
||||||
r = (R * q) / Q;
|
r = (R * q) / Q;
|
||||||
|
const res = {
|
||||||
return {
|
x: insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x - r,
|
||||||
x: insidePoint.x < outsidePoint.x ? insidePoint.x + r : insidePoint.x - r,
|
y: outsidePoint.y + q
|
||||||
y: insidePoint.y + q
|
|
||||||
};
|
};
|
||||||
|
logger.warn(`topp/bott calc, Q ${Q}, q ${q}, R ${R}, r ${r}`, res);
|
||||||
|
|
||||||
|
return res;
|
||||||
} else {
|
} else {
|
||||||
q = (Q * r) / R;
|
// Intersection onn sides of rect
|
||||||
r = (R * q) / Q;
|
// q = (Q * r) / R;
|
||||||
|
// q = 2;
|
||||||
|
// r = (R * q) / Q;
|
||||||
|
if (insidePoint.x < outsidePoint.x) {
|
||||||
|
r = outsidePoint.x - w - x;
|
||||||
|
} else {
|
||||||
|
// r = outsidePoint.x - w - x;
|
||||||
|
r = x - w - outsidePoint.x;
|
||||||
|
}
|
||||||
|
let q = (q = (Q * r) / R);
|
||||||
|
logger.warn(`sides calc, Q ${Q}, q ${q}, R ${R}, r ${r}`, {
|
||||||
|
x: insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x + dx - w,
|
||||||
|
y: insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x: insidePoint.x < outsidePoint.x ? insidePoint.x + r : insidePoint.x + dx - w,
|
x: insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x + dx - w,
|
||||||
y: insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q
|
y: insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -110,7 +153,7 @@ const intersection = (node, outsidePoint, insidePoint) => {
|
|||||||
//(edgePaths, e, edge, clusterDb, diagramtype, graph)
|
//(edgePaths, e, edge, clusterDb, diagramtype, graph)
|
||||||
export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph) {
|
export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph) {
|
||||||
let points = edge.points;
|
let points = edge.points;
|
||||||
|
let pointsHasChanged = false;
|
||||||
const tail = graph.node(e.v);
|
const tail = graph.node(e.v);
|
||||||
var head = graph.node(e.w);
|
var head = graph.node(e.w);
|
||||||
|
|
||||||
@ -147,11 +190,12 @@ export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph)
|
|||||||
}
|
}
|
||||||
lastPointOutside = point;
|
lastPointOutside = point;
|
||||||
});
|
});
|
||||||
|
pointsHasChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edge.fromCluster) {
|
if (edge.fromCluster) {
|
||||||
logger.trace('edge', edge);
|
logger.trace('edge', edge);
|
||||||
logger.trace('from cluster', clusterDb[edge.toCluster]);
|
logger.warn('from cluster', clusterDb[edge.fromCluster]);
|
||||||
const updatedPoints = [];
|
const updatedPoints = [];
|
||||||
let lastPointOutside;
|
let lastPointOutside;
|
||||||
let isInside = false;
|
let isInside = false;
|
||||||
@ -160,7 +204,7 @@ export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph)
|
|||||||
const node = clusterDb[edge.fromCluster].node;
|
const node = clusterDb[edge.fromCluster].node;
|
||||||
|
|
||||||
if (!outsideNode(node, point) && !isInside) {
|
if (!outsideNode(node, point) && !isInside) {
|
||||||
logger.trace('inside', edge.toCluster, point);
|
logger.warn('inside', edge.fromCluster, point, node);
|
||||||
|
|
||||||
// First point inside the rect
|
// First point inside the rect
|
||||||
const insterection = intersection(node, lastPointOutside, point);
|
const insterection = intersection(node, lastPointOutside, point);
|
||||||
@ -176,6 +220,7 @@ export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph)
|
|||||||
lastPointOutside = point;
|
lastPointOutside = point;
|
||||||
}
|
}
|
||||||
points = updatedPoints;
|
points = updatedPoints;
|
||||||
|
pointsHasChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The data for our line
|
// The data for our line
|
||||||
@ -275,4 +320,8 @@ export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pointsHasChanged) {
|
||||||
|
return points;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
63
src/dagre-wrapper/edges.spec.js
Normal file
63
src/dagre-wrapper/edges.spec.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { intersection } from './edges';
|
||||||
|
import { setLogLevel, logger } from '../logger';
|
||||||
|
|
||||||
|
describe('Graphlib decorations', () => {
|
||||||
|
let node;
|
||||||
|
beforeEach(function () {
|
||||||
|
setLogLevel(1);
|
||||||
|
node = { x:171, y:100, width: 210, height: 184};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('intersection', function () {
|
||||||
|
it('case 1 - intersection on left edge of box', function () {
|
||||||
|
const o = {x: 31, y: 143.2257070163421};
|
||||||
|
const i = {x: 99.3359375, y: 100}
|
||||||
|
const int = intersection(node, o, i);
|
||||||
|
expect(int.x).toBe(66)
|
||||||
|
expect(int.y).toBeCloseTo(122.139)
|
||||||
|
});
|
||||||
|
|
||||||
|
it('case 2 - intersection on left edge of box', function () {
|
||||||
|
const o = {x: 310.2578125, y: 169.88002060631462};
|
||||||
|
const i = {x: 127.96875, y: 100};
|
||||||
|
const node2 = {
|
||||||
|
height: 337.5,
|
||||||
|
width: 184.4609375,
|
||||||
|
x: 100.23046875,
|
||||||
|
y: 176.75
|
||||||
|
}
|
||||||
|
const int = intersection(node2, o, i);
|
||||||
|
expect(int.x).toBeCloseTo(192.4609375)
|
||||||
|
expect(int.y).toBeCloseTo(145.15711441743503)
|
||||||
|
|
||||||
|
});
|
||||||
|
it('case 3 - intersection on otop of box outside point greater then inside point', function () {
|
||||||
|
const o = {x: 157.21875, y: 38.83361558001693};
|
||||||
|
const i = {x: 104.1328125, y: 105};
|
||||||
|
const node2 = {
|
||||||
|
width: 211.96875,
|
||||||
|
x: 113.984375,
|
||||||
|
y: 164.25,
|
||||||
|
height: 176.5
|
||||||
|
}
|
||||||
|
const int = intersection(node2, o, i);
|
||||||
|
expect(int.x).toBeCloseTo(127.39979619565217)
|
||||||
|
expect(int.y).toBeCloseTo(76)
|
||||||
|
|
||||||
|
});
|
||||||
|
it('case 4 - intersection on top of box inside point greater then inside point', function () {
|
||||||
|
const o = {x: 144.65625, y: 38.83361558001693};
|
||||||
|
const i = {x: 197.7421875, y: 105};
|
||||||
|
const node2 = {
|
||||||
|
width: 211.96875,
|
||||||
|
x: 113.984375,
|
||||||
|
y: 164.25,
|
||||||
|
height: 176.5
|
||||||
|
}
|
||||||
|
const int = intersection(node2, o, i);
|
||||||
|
expect(int.x).toBeCloseTo(167.9232336956522)
|
||||||
|
expect(int.y).toBeCloseTo(76)
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -124,8 +124,8 @@ const recursiveRender = (_elem, graph, diagramtype, parentCluster) => {
|
|||||||
const edge = graph.edge(e);
|
const edge = graph.edge(e);
|
||||||
log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge);
|
log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge);
|
||||||
|
|
||||||
insertEdge(edgePaths, e, edge, clusterDb, diagramtype, graph);
|
const updatedPath = insertEdge(edgePaths, e, edge, clusterDb, diagramtype, graph);
|
||||||
positionEdgeLabel(edge);
|
positionEdgeLabel(edge, updatedPath);
|
||||||
});
|
});
|
||||||
|
|
||||||
return elem;
|
return elem;
|
||||||
|
@ -171,7 +171,9 @@ export const validate = graph => {
|
|||||||
export const findNonClusterChild = (id, graph) => {
|
export const findNonClusterChild = (id, graph) => {
|
||||||
// const node = graph.node(id);
|
// const node = graph.node(id);
|
||||||
log.trace('Searching', id);
|
log.trace('Searching', id);
|
||||||
const children = graph.children(id);
|
// const children = graph.children(id).reverse();
|
||||||
|
const children = graph.children(id); //.reverse();
|
||||||
|
log.trace('Searching children of id ', id, children);
|
||||||
if (children.length < 1) {
|
if (children.length < 1) {
|
||||||
log.trace('This is a valid node', id);
|
log.trace('This is a valid node', id);
|
||||||
return id;
|
return id;
|
||||||
@ -213,7 +215,7 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
|||||||
graph.nodes().forEach(function(id) {
|
graph.nodes().forEach(function(id) {
|
||||||
const children = graph.children(id);
|
const children = graph.children(id);
|
||||||
if (children.length > 0) {
|
if (children.length > 0) {
|
||||||
log.trace(
|
log.warn(
|
||||||
'Cluster identified',
|
'Cluster identified',
|
||||||
id,
|
id,
|
||||||
' Replacement id in edges: ',
|
' Replacement id in edges: ',
|
||||||
@ -266,17 +268,17 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
|||||||
// Check if link is either from or to a cluster
|
// Check if link is either from or to a cluster
|
||||||
log.trace('Fix', clusterDb, 'ids:', e.v, e.w, 'Translateing: ', clusterDb[e.v], clusterDb[e.w]);
|
log.trace('Fix', clusterDb, 'ids:', e.v, e.w, 'Translateing: ', clusterDb[e.v], clusterDb[e.w]);
|
||||||
if (clusterDb[e.v] || clusterDb[e.w]) {
|
if (clusterDb[e.v] || clusterDb[e.w]) {
|
||||||
log.trace('Fixing and trixing - removing', e.v, e.w, e.name);
|
log.warn('Fixing and trixing - removing', e.v, e.w, e.name);
|
||||||
v = getAnchorId(e.v);
|
v = getAnchorId(e.v);
|
||||||
w = getAnchorId(e.w);
|
w = getAnchorId(e.w);
|
||||||
graph.removeEdge(e.v, e.w, e.name);
|
graph.removeEdge(e.v, e.w, e.name);
|
||||||
if (v !== e.v) edge.fromCluster = e.v;
|
if (v !== e.v) edge.fromCluster = e.v;
|
||||||
if (w !== e.w) edge.toCluster = e.w;
|
if (w !== e.w) edge.toCluster = e.w;
|
||||||
log.trace('Replacing with', v, w, e.name);
|
log.warn('Replacing with', v, w, e.name);
|
||||||
graph.setEdge(v, w, edge, e.name);
|
graph.setEdge(v, w, edge, e.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
log.debug('Adjusted Graph', graphlib.json.write(graph));
|
log.warn('Adjusted Graph', graphlib.json.write(graph));
|
||||||
|
|
||||||
log.trace(clusterDb);
|
log.trace(clusterDb);
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ function addConf(conf, key, value) {
|
|||||||
}
|
}
|
||||||
return conf;
|
return conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('when parsing a sequenceDiagram', function() {
|
describe('when parsing a sequenceDiagram', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
parser.yy = sequenceDb;
|
parser.yy = sequenceDb;
|
||||||
@ -1190,7 +1191,6 @@ sequenceDiagram
|
|||||||
Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
|
Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
|
||||||
Note left of Alice: Bob thinks
|
Note left of Alice: Bob thinks
|
||||||
Bob->>Alice: Fine!`;
|
Bob->>Alice: Fine!`;
|
||||||
|
|
||||||
parser.parse(str);
|
parser.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
@ -1214,7 +1214,6 @@ sequenceDiagram
|
|||||||
Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
|
Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
|
||||||
Note left of Alice: Bob thinks
|
Note left of Alice: Bob thinks
|
||||||
Bob->>Alice: Fine!`;
|
Bob->>Alice: Fine!`;
|
||||||
|
|
||||||
parser.parse(str);
|
parser.parse(str);
|
||||||
// renderer.setConf(mermaidAPI.getConfig().sequence);
|
// renderer.setConf(mermaidAPI.getConfig().sequence);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
@ -1242,7 +1241,6 @@ Alice->Bob: Hello Bob, how are you?
|
|||||||
loop Cheers
|
loop Cheers
|
||||||
Bob->Alice: Fine!
|
Bob->Alice: Fine!
|
||||||
end`;
|
end`;
|
||||||
|
|
||||||
parser.parse(str);
|
parser.parse(str);
|
||||||
renderer.draw(str, 'tst');
|
renderer.draw(str, 'tst');
|
||||||
|
|
||||||
@ -1274,6 +1272,7 @@ end`;
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('when rendering a sequenceDiagram with actor mirror activated', function() {
|
describe('when rendering a sequenceDiagram with actor mirror activated', function() {
|
||||||
let conf;
|
let conf;
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
|
@ -55,7 +55,29 @@ const conf = {
|
|||||||
// wrap text
|
// wrap text
|
||||||
wrapEnabled: false,
|
wrapEnabled: false,
|
||||||
// padding for wrapped text
|
// padding for wrapped text
|
||||||
wrapPadding: 15
|
wrapPadding: 15,
|
||||||
|
|
||||||
|
messageFont: () => {
|
||||||
|
return {
|
||||||
|
fontFamily: conf.messageFontFamily,
|
||||||
|
fontSize: conf.messageFontSize,
|
||||||
|
fontWeight: conf.messageFontWeight
|
||||||
|
};
|
||||||
|
},
|
||||||
|
noteFont: () => {
|
||||||
|
return {
|
||||||
|
fontFamily: conf.noteFontFamily,
|
||||||
|
fontSize: conf.noteFontSize,
|
||||||
|
fontWeight: conf.noteFontWeight
|
||||||
|
};
|
||||||
|
},
|
||||||
|
actorFont: () => {
|
||||||
|
return {
|
||||||
|
fontFamily: conf.actorFontFamily,
|
||||||
|
fontSize: conf.actorFontSize,
|
||||||
|
fontWeight: conf.actorFontWeight
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const bounds = {
|
export const bounds = {
|
||||||
@ -128,10 +150,10 @@ export const bounds = {
|
|||||||
|
|
||||||
this.updateBounds(_startx, _starty, _stopx, _stopy);
|
this.updateBounds(_startx, _starty, _stopx, _stopy);
|
||||||
},
|
},
|
||||||
newActivation: function(message, diagram) {
|
newActivation: function(message, diagram, actors) {
|
||||||
const actorRect = parser.yy.getActors()[message.from.actor];
|
const actorRect = actors[message.from.actor];
|
||||||
const stackedSize = actorActivations(message.from.actor).length;
|
const stackedSize = actorActivations(message.from.actor).length;
|
||||||
const x = actorRect.x + conf.width / 2 + ((stackedSize - 1) * conf.activationWidth) / 2;
|
const x = actorRect.x + actorRect.width / 2 + ((stackedSize - 1) * conf.activationWidth) / 2;
|
||||||
this.activations.push({
|
this.activations.push({
|
||||||
startx: x,
|
startx: x,
|
||||||
starty: this.verticalPos + 2,
|
starty: this.verticalPos + 2,
|
||||||
@ -436,9 +458,9 @@ export const drawActors = function(diagram, actors, actorKeys, verticalPos) {
|
|||||||
const actor = actors[actorKeys[i]];
|
const actor = actors[actorKeys[i]];
|
||||||
|
|
||||||
// Add some rendering data to the object
|
// Add some rendering data to the object
|
||||||
actor.width = typeof actor.width === 'undefined' ? calculateActorWidth(actor) : actor.width;
|
actor.width = actor.width ? actor.width : conf.width;
|
||||||
actor.height = conf.height;
|
actor.height = conf.height;
|
||||||
actor.margin = conf.actorMargin;
|
actor.margin = actor.margin || conf.actorMargin;
|
||||||
|
|
||||||
actor.x = prevWidth + prevMargin;
|
actor.x = prevWidth + prevMargin;
|
||||||
actor.y = verticalPos;
|
actor.y = verticalPos;
|
||||||
@ -489,52 +511,23 @@ const actorFlowVerticaBounds = function(actor) {
|
|||||||
return [left, right];
|
return [left, right];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* This calculates the actor's width, taking into account both the statically configured width,
|
|
||||||
* and the actor's description.
|
|
||||||
*
|
|
||||||
* If the description text has greater length, we extend the width of the actor, so it's description
|
|
||||||
* won't overflow.
|
|
||||||
*
|
|
||||||
* @param actor - An actor object
|
|
||||||
* @return - The width for the given actor
|
|
||||||
*/
|
|
||||||
const calculateActorWidth = function(actor) {
|
|
||||||
if (!actor.description) {
|
|
||||||
return conf.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
return actor.wrap
|
|
||||||
? conf.width
|
|
||||||
: Math.max(
|
|
||||||
conf.width,
|
|
||||||
utils.calculateTextWidth(actor.description, {
|
|
||||||
fontSize: conf.actorFontSize,
|
|
||||||
fontFamily: conf.actorFontFamily,
|
|
||||||
fontWeight: conf.actorFontWeight,
|
|
||||||
margin: conf.wrapPadding
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoopFn) {
|
function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoopFn) {
|
||||||
let heightAdjust = 0;
|
let heightAdjust = 0;
|
||||||
bounds.bumpVerticalPos(preMargin);
|
bounds.bumpVerticalPos(preMargin);
|
||||||
if (msg.message && msg.wrap && loopWidths[msg.message]) {
|
if (msg.message && loopWidths[msg.message]) {
|
||||||
let loopWidth = loopWidths[msg.message].width;
|
let loopWidth = loopWidths[msg.message].width;
|
||||||
let minSize =
|
let minSize =
|
||||||
Math.round((3 * conf.fontSize) / 4) < 10
|
Math.round((3 * conf.messageFontSize) / 4) < 10
|
||||||
? conf.fontSize
|
? conf.messageFontSize
|
||||||
: Math.round((3 * conf.fontSize) / 4);
|
: Math.round((3 * conf.messageFontSize) / 4);
|
||||||
let textConf = {
|
let textConf = conf.messageFont();
|
||||||
fontSize: minSize,
|
textConf.fontSize = minSize;
|
||||||
fontFamily: conf.messageFontFamily,
|
msg.message = utils.wrapLabel(
|
||||||
fontWeight: conf.messageFontWeight,
|
`[${msg.message}]`,
|
||||||
margin: conf.wrapPadding
|
loopWidth - 20 - 2 * conf.wrapPadding,
|
||||||
};
|
textConf
|
||||||
msg.message = msg.message
|
);
|
||||||
? utils.wrapLabel(`[${msg.message}]`, loopWidth, textConf)
|
|
||||||
: msg.message;
|
|
||||||
heightAdjust = Math.max(
|
heightAdjust = Math.max(
|
||||||
0,
|
0,
|
||||||
utils.calculateTextHeight(msg.message, textConf) - (preMargin + postMargin)
|
utils.calculateTextHeight(msg.message, textConf) - (preMargin + postMargin)
|
||||||
@ -559,7 +552,6 @@ export const draw = function(text, id) {
|
|||||||
|
|
||||||
let startx;
|
let startx;
|
||||||
let stopx;
|
let stopx;
|
||||||
let forceWidth;
|
|
||||||
|
|
||||||
// Fetch data from the parsing
|
// Fetch data from the parsing
|
||||||
const actors = parser.yy.getActors();
|
const actors = parser.yy.getActors();
|
||||||
@ -600,8 +592,9 @@ export const draw = function(text, id) {
|
|||||||
messages.forEach(function(msg) {
|
messages.forEach(function(msg) {
|
||||||
let loopData,
|
let loopData,
|
||||||
noteWidth,
|
noteWidth,
|
||||||
|
noteStart,
|
||||||
|
noteEnd,
|
||||||
textWidth,
|
textWidth,
|
||||||
textConf,
|
|
||||||
shouldWrap = msg.wrap && msg.message && !common.lineBreakRegex.test(msg.message);
|
shouldWrap = msg.wrap && msg.message && !common.lineBreakRegex.test(msg.message);
|
||||||
|
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
@ -610,18 +603,27 @@ export const draw = function(text, id) {
|
|||||||
|
|
||||||
startx = actors[msg.from].x;
|
startx = actors[msg.from].x;
|
||||||
stopx = actors[msg.to].x;
|
stopx = actors[msg.to].x;
|
||||||
textConf = {
|
noteStart = startx + actors[msg.from].width / 2;
|
||||||
fontSize: conf.noteFontSize,
|
noteEnd = stopx + actors[msg.to].width / 2;
|
||||||
fontFamily: conf.noteFontFamily,
|
textWidth = utils.calculateTextWidth(
|
||||||
fontWeight: conf.noteFontWeight,
|
shouldWrap ? utils.wrapLabel(msg.message, conf.width, conf.noteFont()) : msg.message,
|
||||||
margin: conf.wrapPadding
|
conf.noteFont()
|
||||||
};
|
);
|
||||||
textWidth = utils.calculateTextWidth(msg.message, textConf);
|
noteWidth = shouldWrap ? conf.width : Math.max(conf.width, textWidth + 2 * conf.noteMargin);
|
||||||
noteWidth = shouldWrap ? conf.width : Math.max(conf.width, textWidth);
|
|
||||||
|
|
||||||
if (msg.placement === parser.yy.PLACEMENT.RIGHTOF) {
|
if (msg.placement === parser.yy.PLACEMENT.RIGHTOF) {
|
||||||
|
noteWidth = shouldWrap
|
||||||
|
? conf.width
|
||||||
|
: Math.max(
|
||||||
|
actors[msg.from].width / 2 + actors[msg.to].width / 2,
|
||||||
|
textWidth + 2 * conf.noteMargin
|
||||||
|
);
|
||||||
if (shouldWrap) {
|
if (shouldWrap) {
|
||||||
msg.message = utils.wrapLabel(msg.message, noteWidth, textConf);
|
msg.message = utils.wrapLabel(
|
||||||
|
msg.message,
|
||||||
|
noteWidth - 2 * conf.wrapPadding,
|
||||||
|
conf.noteFont()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
drawNote(
|
drawNote(
|
||||||
diagram,
|
diagram,
|
||||||
@ -631,8 +633,18 @@ export const draw = function(text, id) {
|
|||||||
noteWidth
|
noteWidth
|
||||||
);
|
);
|
||||||
} else if (msg.placement === parser.yy.PLACEMENT.LEFTOF) {
|
} else if (msg.placement === parser.yy.PLACEMENT.LEFTOF) {
|
||||||
|
noteWidth = shouldWrap
|
||||||
|
? conf.width
|
||||||
|
: Math.max(
|
||||||
|
actors[msg.from].width / 2 + actors[msg.to].width / 2,
|
||||||
|
textWidth + 2 * conf.noteMargin
|
||||||
|
);
|
||||||
if (shouldWrap) {
|
if (shouldWrap) {
|
||||||
msg.message = utils.wrapLabel(msg.message, noteWidth, textConf);
|
msg.message = utils.wrapLabel(
|
||||||
|
msg.message,
|
||||||
|
noteWidth - 2 * conf.wrapPadding,
|
||||||
|
conf.noteFont()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
drawNote(
|
drawNote(
|
||||||
diagram,
|
diagram,
|
||||||
@ -643,8 +655,25 @@ export const draw = function(text, id) {
|
|||||||
);
|
);
|
||||||
} else if (msg.to === msg.from) {
|
} else if (msg.to === msg.from) {
|
||||||
// Single-actor over
|
// Single-actor over
|
||||||
|
textWidth = utils.calculateTextWidth(
|
||||||
|
shouldWrap
|
||||||
|
? utils.wrapLabel(
|
||||||
|
msg.message,
|
||||||
|
Math.max(conf.width, actors[msg.to].width),
|
||||||
|
conf.noteFont()
|
||||||
|
)
|
||||||
|
: msg.message,
|
||||||
|
conf.noteFont()
|
||||||
|
);
|
||||||
|
noteWidth = shouldWrap
|
||||||
|
? Math.max(conf.width, actors[msg.to].width)
|
||||||
|
: Math.max(actors[msg.to].width, conf.width, textWidth + 2 * conf.noteMargin);
|
||||||
if (shouldWrap) {
|
if (shouldWrap) {
|
||||||
msg.message = utils.wrapLabel(msg.message, noteWidth, textConf);
|
msg.message = utils.wrapLabel(
|
||||||
|
msg.message,
|
||||||
|
noteWidth - 2 * conf.wrapPadding,
|
||||||
|
conf.noteFont()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
drawNote(
|
drawNote(
|
||||||
diagram,
|
diagram,
|
||||||
@ -655,23 +684,19 @@ export const draw = function(text, id) {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Multi-actor over
|
// Multi-actor over
|
||||||
forceWidth = Math.abs(startx - stopx) + conf.actorMargin / 2;
|
noteWidth = Math.abs(noteStart - noteEnd) + conf.actorMargin;
|
||||||
if (shouldWrap) {
|
if (shouldWrap) {
|
||||||
noteWidth = forceWidth;
|
msg.message = utils.wrapLabel(msg.message, noteWidth, conf.noteFont());
|
||||||
msg.message = utils.wrapLabel(msg.message, noteWidth, textConf);
|
|
||||||
} else {
|
|
||||||
noteWidth = Math.max(forceWidth, textWidth - 2 * conf.noteMargin);
|
|
||||||
}
|
}
|
||||||
let x =
|
let x =
|
||||||
startx < stopx
|
startx < stopx
|
||||||
? startx + (actors[msg.from].width - conf.actorMargin / 2) / 2
|
? startx + actors[msg.from].width / 2 - conf.actorMargin / 2
|
||||||
: stopx + (actors[msg.to].width - conf.actorMargin / 2) / 2;
|
: stopx + actors[msg.to].width / 2 - conf.actorMargin / 2;
|
||||||
|
drawNote(diagram, x, bounds.getVerticalPos(), msg, noteWidth);
|
||||||
drawNote(diagram, x, bounds.getVerticalPos(), msg, forceWidth);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case parser.yy.LINETYPE.ACTIVE_START:
|
case parser.yy.LINETYPE.ACTIVE_START:
|
||||||
bounds.newActivation(msg, diagram);
|
bounds.newActivation(msg, diagram, actors);
|
||||||
break;
|
break;
|
||||||
case parser.yy.LINETYPE.ACTIVE_END:
|
case parser.yy.LINETYPE.ACTIVE_END:
|
||||||
activeEnd(msg, bounds.getVerticalPos());
|
activeEnd(msg, bounds.getVerticalPos());
|
||||||
@ -761,12 +786,6 @@ export const draw = function(text, id) {
|
|||||||
const toIdx = fromBounds[0] < toBounds[0] ? 0 : 1;
|
const toIdx = fromBounds[0] < toBounds[0] ? 0 : 1;
|
||||||
startx = fromBounds[fromIdx];
|
startx = fromBounds[fromIdx];
|
||||||
stopx = toBounds[toIdx];
|
stopx = toBounds[toIdx];
|
||||||
textConf = {
|
|
||||||
fontSize: conf.messageFontSize,
|
|
||||||
fontFamily: conf.messageFontFamily,
|
|
||||||
fontWeight: conf.messageFontWeight,
|
|
||||||
margin: conf.wrapPadding
|
|
||||||
};
|
|
||||||
if (shouldWrap) {
|
if (shouldWrap) {
|
||||||
msg.message = utils.wrapLabel(
|
msg.message = utils.wrapLabel(
|
||||||
msg.message,
|
msg.message,
|
||||||
@ -774,7 +793,7 @@ export const draw = function(text, id) {
|
|||||||
Math.abs(stopx - startx) + conf.messageMargin * 2,
|
Math.abs(stopx - startx) + conf.messageMargin * 2,
|
||||||
conf.width + conf.messageMargin * 2
|
conf.width + conf.messageMargin * 2
|
||||||
),
|
),
|
||||||
textConf
|
conf.messageFont()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -887,19 +906,11 @@ const getMaxMessageWidthPerActor = function(actors, messages) {
|
|||||||
const isNote = msg.placement !== undefined;
|
const isNote = msg.placement !== undefined;
|
||||||
const isMessage = !isNote;
|
const isMessage = !isNote;
|
||||||
|
|
||||||
const fontSize = isNote ? conf.noteFontSize : conf.messageFontSize;
|
const textFont = isNote ? conf.noteFont() : conf.messageFont();
|
||||||
const fontFamily = isNote ? conf.noteFontFamily : conf.messageFontFamily;
|
|
||||||
const fontWeight = isNote ? conf.noteFontWeight : conf.messageFontWeight;
|
|
||||||
const textConf = { fontFamily, fontSize, fontWeight, margin: conf.wrapPadding };
|
|
||||||
let wrappedMessage = msg.wrap
|
let wrappedMessage = msg.wrap
|
||||||
? utils.wrapLabel(msg.message, conf.width - conf.noteMargin, textConf)
|
? utils.wrapLabel(msg.message, conf.width - conf.noteMargin, textFont)
|
||||||
: msg.message;
|
: msg.message;
|
||||||
const messageDimensions = utils.calculateTextDimensions(wrappedMessage, {
|
const messageDimensions = utils.calculateTextDimensions(wrappedMessage, textFont);
|
||||||
fontSize,
|
|
||||||
fontFamily,
|
|
||||||
fontWeight,
|
|
||||||
margin: conf.wrapPadding
|
|
||||||
});
|
|
||||||
const messageWidth = messageDimensions.width;
|
const messageWidth = messageDimensions.width;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -954,6 +965,7 @@ const getMaxMessageWidthPerActor = function(actors, messages) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
logger.debug('MaxMessages:', maxMessageWidthPerActor);
|
||||||
return maxMessageWidthPerActor;
|
return maxMessageWidthPerActor;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -969,6 +981,24 @@ const getMaxMessageWidthPerActor = function(actors, messages) {
|
|||||||
*/
|
*/
|
||||||
const calculateActorMargins = function(actors, actorToMessageWidth) {
|
const calculateActorMargins = function(actors, actorToMessageWidth) {
|
||||||
let maxHeight = 0;
|
let maxHeight = 0;
|
||||||
|
Object.keys(actors).forEach(prop => {
|
||||||
|
const actor = actors[prop];
|
||||||
|
if (actor.wrap) {
|
||||||
|
actor.description = utils.wrapLabel(
|
||||||
|
actor.description,
|
||||||
|
conf.width - 2 * conf.wrapPadding,
|
||||||
|
conf.actorFont()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const actDims = utils.calculateTextDimensions(actor.description, conf.actorFont());
|
||||||
|
actor.width = actor.wrap
|
||||||
|
? conf.width
|
||||||
|
: Math.max(conf.width, actDims.width + 2 * conf.wrapPadding);
|
||||||
|
|
||||||
|
actor.height = actor.wrap ? Math.max(actDims.height, conf.height) : conf.height;
|
||||||
|
maxHeight = Math.max(maxHeight, actor.height);
|
||||||
|
});
|
||||||
|
|
||||||
for (let actorKey in actorToMessageWidth) {
|
for (let actorKey in actorToMessageWidth) {
|
||||||
const actor = actors[actorKey];
|
const actor = actors[actorKey];
|
||||||
|
|
||||||
@ -976,13 +1006,6 @@ const calculateActorMargins = function(actors, actorToMessageWidth) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const textConf = {
|
|
||||||
fontSize: conf.actorFontSize,
|
|
||||||
fontFamily: conf.actorFontFamily,
|
|
||||||
fontWeight: conf.actorFontWeight,
|
|
||||||
margin: conf.wrapPadding
|
|
||||||
};
|
|
||||||
|
|
||||||
const nextActor = actors[actor.nextActor];
|
const nextActor = actors[actor.nextActor];
|
||||||
|
|
||||||
// No need to space out an actor that doesn't have a next link
|
// No need to space out an actor that doesn't have a next link
|
||||||
@ -990,18 +1013,6 @@ const calculateActorMargins = function(actors, actorToMessageWidth) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
[actor, nextActor].forEach(function(act) {
|
|
||||||
if (act.wrap) {
|
|
||||||
act.description = utils.wrapLabel(act.description, conf.width, textConf);
|
|
||||||
}
|
|
||||||
const actDims = utils.calculateTextDimensions(act.description, textConf);
|
|
||||||
act.width = act.wrap ? conf.width : Math.max(conf.width, actDims.width);
|
|
||||||
|
|
||||||
act.height = act.wrap ? Math.max(actDims.height, conf.height) : conf.height;
|
|
||||||
logger.debug(`Actor h:${act.height} ${actDims.height} d:${act.description}`);
|
|
||||||
maxHeight = Math.max(maxHeight, act.height);
|
|
||||||
});
|
|
||||||
|
|
||||||
const messageWidth = actorToMessageWidth[actorKey];
|
const messageWidth = actorToMessageWidth[actorKey];
|
||||||
const actorWidth = messageWidth + conf.actorMargin - actor.width / 2 - nextActor.width / 2;
|
const actorWidth = messageWidth + conf.actorMargin - actor.width / 2 - nextActor.width / 2;
|
||||||
|
|
||||||
@ -1050,18 +1061,22 @@ const calculateLoopMargins = function(messages, actors) {
|
|||||||
current = stk;
|
current = stk;
|
||||||
let from = actors[msg.from];
|
let from = actors[msg.from];
|
||||||
let to = actors[msg.to];
|
let to = actors[msg.to];
|
||||||
if (from.x < to.x) {
|
if (from.x === to.x) {
|
||||||
current.from = Math.min(current.from, from.x);
|
current.from = current.to = from.x;
|
||||||
current.to = Math.max(current.to, to.x);
|
current.width = from.width;
|
||||||
} else {
|
} else {
|
||||||
current.from = Math.min(current.from, to.x);
|
if (from.x < to.x) {
|
||||||
current.to = Math.max(current.to, from.x);
|
current.from = Math.min(current.from, from.x);
|
||||||
|
current.to = Math.max(current.to, to.x);
|
||||||
|
} else {
|
||||||
|
current.from = Math.min(current.from, to.x);
|
||||||
|
current.to = Math.max(current.to, from.x);
|
||||||
|
}
|
||||||
|
current.width = Math.abs(current.from - current.to) - 20 + 2 * conf.wrapPadding;
|
||||||
}
|
}
|
||||||
current.width = Math.abs(current.from - current.to) - 20 + 2 * conf.wrapPadding;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
logger.debug('LoopWidths:', { loops, actors });
|
|
||||||
return loops;
|
return loops;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ let actorCnt = -1;
|
|||||||
* Draws an actor in the diagram with the attaced line
|
* Draws an actor in the diagram with the attaced line
|
||||||
* @param elem - The diagram we'll draw to.
|
* @param elem - The diagram we'll draw to.
|
||||||
* @param actor - The actor to draw.
|
* @param actor - The actor to draw.
|
||||||
* @param conf - utils.drawText implementation discriminator object
|
* @param conf - drawText implementation discriminator object
|
||||||
*/
|
*/
|
||||||
export const drawActor = function(elem, actor, conf) {
|
export const drawActor = function(elem, actor, conf) {
|
||||||
const center = actor.x + actor.width / 2;
|
const center = actor.x + actor.width / 2;
|
||||||
@ -241,16 +241,18 @@ export const drawLoop = function(elem, bounds, labelText, conf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let minSize =
|
let minSize =
|
||||||
Math.round((3 * conf.fontSize) / 4) < 10 ? conf.fontSize : Math.round((3 * conf.fontSize) / 4);
|
Math.round((3 * conf.messageFontSize) / 4) < 10
|
||||||
|
? conf.messageFontSize
|
||||||
|
: Math.round((3 * conf.messageFontSize) / 4);
|
||||||
|
|
||||||
let txt = getTextObj();
|
let txt = getTextObj();
|
||||||
txt.text = labelText;
|
txt.text = labelText;
|
||||||
txt.x = bounds.startx;
|
txt.x = bounds.startx;
|
||||||
txt.y = bounds.starty;
|
txt.y = bounds.starty;
|
||||||
txt.labelMargin = 1.5 * 10; // This is the small box that says "loop"
|
txt.labelMargin = 1.5 * 10; // This is the small box that says "loop"
|
||||||
txt.fontFamily = conf.fontFamily;
|
txt.fontFamily = conf.messageFontFamily;
|
||||||
txt.fontSize = minSize;
|
txt.fontSize = minSize;
|
||||||
txt.fontWeight = conf.fontWeight;
|
txt.fontWeight = conf.messageFontWeight;
|
||||||
txt.class = 'labelText'; // Its size & position are fixed.
|
txt.class = 'labelText'; // Its size & position are fixed.
|
||||||
|
|
||||||
let labelElem = drawLabel(g, txt);
|
let labelElem = drawLabel(g, txt);
|
||||||
@ -261,10 +263,10 @@ export const drawLoop = function(elem, bounds, labelText, conf) {
|
|||||||
txt.y = bounds.starty + conf.boxMargin + conf.boxTextMargin;
|
txt.y = bounds.starty + conf.boxMargin + conf.boxTextMargin;
|
||||||
txt.anchor = 'middle';
|
txt.anchor = 'middle';
|
||||||
txt.class = 'loopText';
|
txt.class = 'loopText';
|
||||||
txt.fontFamily = conf.fontFamily;
|
txt.fontFamily = conf.messageFontFamily;
|
||||||
txt.fontSize = minSize;
|
txt.fontSize = minSize;
|
||||||
txt.fontWeight = conf.fontWeight;
|
txt.fontWeight = conf.messageFontWeight;
|
||||||
txt.wrap = bounds.wrap;
|
txt.wrap = true;
|
||||||
|
|
||||||
drawText(g, txt);
|
drawText(g, txt);
|
||||||
|
|
||||||
@ -273,12 +275,12 @@ export const drawLoop = function(elem, bounds, labelText, conf) {
|
|||||||
if (item.message) {
|
if (item.message) {
|
||||||
txt.text = item.message;
|
txt.text = item.message;
|
||||||
txt.x = bounds.startx + (bounds.stopx - bounds.startx) / 2;
|
txt.x = bounds.startx + (bounds.stopx - bounds.startx) / 2;
|
||||||
txt.y = bounds.sections[idx] + 1.5 * conf.boxMargin;
|
txt.y = bounds.sections[idx] + conf.boxMargin + conf.boxTextMargin;
|
||||||
txt.class = 'loopText';
|
txt.class = 'loopText';
|
||||||
txt.anchor = 'middle';
|
txt.anchor = 'middle';
|
||||||
txt.fontFamily = conf.fontFamily;
|
txt.fontFamily = conf.messageFontFamily;
|
||||||
txt.fontSize = minSize;
|
txt.fontSize = minSize;
|
||||||
txt.fontWeight = conf.fontWeight;
|
txt.fontWeight = conf.messageFontWeight;
|
||||||
txt.wrap = bounds.wrap;
|
txt.wrap = bounds.wrap;
|
||||||
drawText(g, txt);
|
drawText(g, txt);
|
||||||
}
|
}
|
||||||
|
@ -130,8 +130,6 @@ const init = function() {
|
|||||||
|
|
||||||
const initialize = function(config) {
|
const initialize = function(config) {
|
||||||
mermaidAPI.reset();
|
mermaidAPI.reset();
|
||||||
|
|
||||||
// console.log('mermaid.initialize1', config);
|
|
||||||
if (typeof config.mermaid !== 'undefined') {
|
if (typeof config.mermaid !== 'undefined') {
|
||||||
if (typeof config.mermaid.startOnLoad !== 'undefined') {
|
if (typeof config.mermaid.startOnLoad !== 'undefined') {
|
||||||
mermaid.startOnLoad = config.mermaid.startOnLoad;
|
mermaid.startOnLoad = config.mermaid.startOnLoad;
|
||||||
@ -140,9 +138,7 @@ const initialize = function(config) {
|
|||||||
mermaid.htmlLabels = config.mermaid.htmlLabels;
|
mermaid.htmlLabels = config.mermaid.htmlLabels;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// console.log('Initializing mermaid 2', config);
|
|
||||||
mermaidAPI.initialize(config);
|
mermaidAPI.initialize(config);
|
||||||
// logger.debug('Initializing mermaid 3', config);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -735,7 +735,7 @@ const render = function(id, _txt, cb, container) {
|
|||||||
}
|
}
|
||||||
const element = document.querySelector('#' + 'd' + id);
|
const element = document.querySelector('#' + 'd' + id);
|
||||||
if (element) {
|
if (element) {
|
||||||
element.innerHTML = '';
|
element.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
select('body')
|
select('body')
|
||||||
@ -959,7 +959,6 @@ function initialize(options) {
|
|||||||
updateRendererConfigs(config);
|
updateRendererConfigs(config);
|
||||||
}
|
}
|
||||||
setConfig(config);
|
setConfig(config);
|
||||||
|
|
||||||
setLogLevel(config.logLevel);
|
setLogLevel(config.logLevel);
|
||||||
logger.debug('mermaidAPI.initialize: ', config);
|
logger.debug('mermaidAPI.initialize: ', config);
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
$mainBkg: #1f2020;
|
$mainBkg: #1f2020;
|
||||||
$secondBkg: lighten(#1f2020, 24);
|
$secondBkg: lighten(#1f2020, 16);
|
||||||
$mainContrastColor: rgba(226, 226, 226, .75);
|
$mainContrastColor: lightgrey;
|
||||||
$darkTextColor: #323D47;
|
$darkTextColor: #323D47;
|
||||||
$lineColor: lighten($mainContrastColor, 24);
|
$lineColor: $mainContrastColor;
|
||||||
$border1: #81b1db;
|
$border1: #81B1DB;
|
||||||
$border2: darken(#81b1db, 32);
|
$border2: rgba(255, 255, 255, 0.25);
|
||||||
$arrowheadColor: $mainContrastColor;
|
$arrowheadColor: $mainContrastColor;
|
||||||
|
|
||||||
/* Flowchart variables */
|
/* Flowchart variables */
|
||||||
|
|
||||||
$nodeBkg: $mainBkg;
|
$nodeBkg: $mainBkg;
|
||||||
$nodeBorder: purple;
|
$nodeBorder: $border1;
|
||||||
$clusterBkg: $secondBkg;
|
$clusterBkg: $secondBkg;
|
||||||
$clusterBorder: $border2;
|
$clusterBorder: $border2;
|
||||||
$defaultLinkColor: $lineColor;
|
$defaultLinkColor: $lineColor;
|
||||||
@ -31,10 +31,10 @@ $labelTextColor: $mainContrastColor;
|
|||||||
$loopTextColor: $mainContrastColor;
|
$loopTextColor: $mainContrastColor;
|
||||||
$noteBorderColor: $border2;
|
$noteBorderColor: $border2;
|
||||||
$noteBkgColor: #fff5ad;
|
$noteBkgColor: #fff5ad;
|
||||||
$noteTextColor: #1f2020;
|
$noteTextColor: $mainBkg;
|
||||||
$activationBorderColor: $border1;
|
$activationBorderColor: $border1;
|
||||||
$activationBkgColor: $secondBkg;
|
$activationBkgColor: $secondBkg;
|
||||||
$sequenceNumberColor: $mainContrastColor;
|
$sequenceNumberColor: white;
|
||||||
|
|
||||||
/* Gantt chart variables */
|
/* Gantt chart variables */
|
||||||
|
|
||||||
|
@ -18,9 +18,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Classes common for multiple diagrams */
|
/* Classes common for multiple diagrams */
|
||||||
body {
|
|
||||||
background-color: $mainBkg;
|
|
||||||
}
|
|
||||||
.error-icon {
|
.error-icon {
|
||||||
fill: $errorBkgColor;
|
fill: $errorBkgColor;
|
||||||
}
|
}
|
||||||
|
16
src/utils.js
16
src/utils.js
@ -36,7 +36,7 @@ const anyComment = /\s*%%.*\n/gm;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @function detectInit
|
* @function detectInit
|
||||||
* Detects the init config object from the text and (re)initializes mermaid
|
* Detects the init config object from the text
|
||||||
* ```mermaid
|
* ```mermaid
|
||||||
* %%{init: {"theme": "debug", "logLevel": 1 }}%%
|
* %%{init: {"theme": "debug", "logLevel": 1 }}%%
|
||||||
* graph LR
|
* graph LR
|
||||||
@ -494,8 +494,11 @@ export const drawSimpleText = function(elem, textData) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const wrapLabel = (label, maxWidth, config) => {
|
export const wrapLabel = (label, maxWidth, config) => {
|
||||||
|
if (!label) {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
config = Object.assign(
|
config = Object.assign(
|
||||||
{ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', margin: 15, joinWith: '<br/>' },
|
{ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', margin: 0, joinWith: '<br/>' },
|
||||||
config
|
config
|
||||||
);
|
);
|
||||||
if (common.lineBreakRegex.test(label)) {
|
if (common.lineBreakRegex.test(label)) {
|
||||||
@ -527,10 +530,7 @@ export const wrapLabel = (label, maxWidth, config) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const breakString = (word, maxWidth, hyphenCharacter = '-', config) => {
|
const breakString = (word, maxWidth, hyphenCharacter = '-', config) => {
|
||||||
config = Object.assign(
|
config = Object.assign({ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', margin: 0 }, config);
|
||||||
{ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', margin: 15 },
|
|
||||||
config
|
|
||||||
);
|
|
||||||
const characters = word.split('');
|
const characters = word.split('');
|
||||||
const lines = [];
|
const lines = [];
|
||||||
let currentLine = '';
|
let currentLine = '';
|
||||||
@ -596,7 +596,7 @@ export const calculateTextDimensions = function(text, config) {
|
|||||||
{ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', margin: 15 },
|
{ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', margin: 15 },
|
||||||
config
|
config
|
||||||
);
|
);
|
||||||
const { fontSize, fontFamily, fontWeight, margin } = config;
|
const { fontSize, fontFamily, fontWeight } = config;
|
||||||
if (!text) {
|
if (!text) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -638,7 +638,7 @@ export const calculateTextDimensions = function(text, config) {
|
|||||||
g.remove();
|
g.remove();
|
||||||
|
|
||||||
// Adds some padding, so the text won't sit exactly within the actor's borders
|
// Adds some padding, so the text won't sit exactly within the actor's borders
|
||||||
return { width: maxWidth + 2 * margin, height: height + 2 * margin };
|
return { width: Math.round(maxWidth), height: Math.round(height) };
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user