This commit is contained in:
Knut Sveidqvist
2022-06-08 20:17:31 +02:00
parent 7a4acb5c36
commit 4dd3d3bc76
7 changed files with 242 additions and 228 deletions

View File

@@ -230,6 +230,7 @@ class Class10 {
nodeSpacing: 10, nodeSpacing: 10,
curve: 'cardinal', curve: 'cardinal',
htmlLabels: true, htmlLabels: true,
useMaxWidth: false,
// defaultRenderer: 'dagre-d3', // defaultRenderer: 'dagre-d3',
}, },
class: { class: {

View File

@@ -11,196 +11,224 @@
body { body {
/* background: rgb(221, 208, 208); */ /* background: rgb(221, 208, 208); */
/* background:#333; */ /* background:#333; */
font-family: 'Arial'; font-family: 'Courier New', Courier, monospace;
/* font-size: 18px !important; */ /* font-size: 18px !important; */
} }
h1 { color: grey;} h1 { color: grey;}
.mermaid2 { .mermaid2 {
display: none; display: none;
} }
.mermaid svg { .mermaid {
border: 1px solid red;
font-family: 'Courier New', Courier, monospace;
/* font-size: 18px !important; */ /* font-size: 18px !important; */
} }
</style> </style>
</head> </head>
<body> <body>
<div>info below</div> <div>info below</div>
<div class="flex"> <div class="">
<div class="mermaid2" style="width: 100%; height: 400px;"> <div class="mermaid" style="width: 100%; height: 400px;">
%%{init: { "logLevel": 1, "er": {"fontSize":18 }} }%% flowchart TB;subgraph "number as labels";1;end;
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>
<div class="mermaid2" style="width: 50%; height: 400px;"> <div class="mermaid" style="width: 100%; height: 400px;">
flowchart TD flowchart TB;a[APA];
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
subgraph T ["Test"]
A
B
C
end
classDef Test fill:#F84E68,stroke:#333,color:white;
class A,T Test
classDef TestSub fill:green;
class T TestSub
linkStyle 0,1 color:orange, stroke: orange;
</div>
<div class="mermaid" style="width: 100%; height: 20%;">
flowchart TB
subgraph S1
sub1 -->sub2
end
subgraph S2
sub4
end
S1 --> S2
sub1 --> sub4
</div> </div>
<div class="mermaid2" style="width: 100%; height: 20%;"> <div class="mermaid" style="margin-left:100px;">
flowchart TB graph TD
c1-->a2 work --> sleep
subgraph one sleep --> work
a1-->a2 eat --> sleep
end work --> eat
subgraph two
b1-->b2
end
subgraph three
c1-->c2
end
one --> two
three --> two
two --> c2
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
stateDiagram-v2
state S1 {
sub1 -->sub2
}
state S2 {
sub4
}
S1 --> S2
sub1 --> sub4
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}
performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}
element test_entity {
type: simulation
}
element test_entity2 {
type: word doc
docRef: reqs/test_entity
}
test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req <- copies - test_entity2
</div> </div>
<div class="mermaid2" style="width: 50%; height: 20%;"> <div class="mermaid" style="margin-left:100px;">
flowchart LR
classDef dark fill:#000,stroke:#000,stroke-width:4px,color:#fff
Lorem --> Ipsum --> Dolor
class Lorem,Dolor dark
</div>
<div class="mermaid2" style="width: 50%; height: 20%;">
%%{init: {'theme': 'base' }}%%
%%{init2: { 'logLevel': 0, 'theme': 'forest'} }%%
flowchart TD flowchart TD
L1 --- L2 work --> sleep
L2 --- C sleep --> work
M1 ---> C eat --> sleep
R1 .-> R2 work --> eat
R2 <.-> C </div>
C -->|Label 1| E1 <div class="mermaid" style="">
C <-- Label 2 ---> E2 graph TB
C ----> E3 A
C <-...-> E4 B
C ======> E5 subgraph foo[Foo SubGraph]
</div> C
<div class="mermaid2" style="width: 50%; height: 21%;"> D
end
subgraph bar[Bar SubGraph]
E
F
end
G
A-->B
B-->C
C-->D
B-->D
D-->E
E-->A
E-->F
F-->D
F-->G
B-->G
G-->D
style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred
style bar fill:#999,stroke-width:2px,stroke:#0F0,color:blue
</div>
<div class="mermaid" style="">
graph TB
%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
A
B
subgraph foo[Foo SubGraph]
C
D
end
subgraph bar[Bar SubGraph]
E
F
end
G
A-->B
B-->C
C-->D
B-->D
D-->E
E-->A
E-->F
F-->D
F-->G
B-->G
G-->D
style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred
style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue
</div>
<div class="mermaid" style="">
graph TD
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
</div>
<div class="mermaid" style="">
graph TD
%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
</div>
<div class="mermaid" style="">
flowchart TD
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
</div>
<div class="mermaid" style="">
flowchart TD
%%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
</div>
<div class="mermaid" style="">
flowchart LR flowchart LR
A[red text] -->|default style| B(blue text) a["<strong>Haiya</strong>"]---->b
C([red text]) -->|default style| D[[blue text]] </div>
E[(red text)] -->|default style| F((blue text)) <div class="mermaid" style="">
G>red text] -->|default style| H{blue text} flowchart LR
I{{red text}} -->|default style| J[/blue text/] %%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
K[ a["<strong>Haiya</strong>"]---->b
ed text] -->|default style| L[/blue text] </div>
M[ <div class="mermaid" style="">
ed text/] -->|default style| N[blue text] flowchart TD
linkStyle default color:Sienna; A[Christmas] ==> D
style A stroke:#ff0000,fill:#ffcccc,color:#ff0000 A[Christmas] -->|Get money| B(Go shopping)
style B stroke:#0000ff,fill:#ccccff,color:#0000ff A[Christmas] ==> C
style C stroke:#ff0000,fill:#ffcccc,color:#ff0000 </div>
style D stroke:#0000ff,fill:#ccccff,color:#0000ff <div class="mermaid" style="">
style E stroke:#ff0000,fill:#ffcccc,color:#ff0000 flowchart TD
style F stroke:#0000ff,fill:#ccccff,color:#0000ff %%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
style G stroke:#ff0000,fill:#ffcccc,color:#ff0000 A[Christmas] ==> D
style H stroke:#0000ff,fill:#ccccff,color:#0000ff A[Christmas] -->|Get money| B(Go shopping)
style I stroke:#ff0000,fill:#ffcccc,color:#ff0000 A[Christmas] ==> C
style J stroke:#0000ff,fill:#ccccff,color:#0000ff </div>
style K stroke:#ff0000,fill:#ffcccc,color:#ff0000 <div class="mermaid" style="">
style L stroke:#0000ff,fill:#ccccff,color:#0000ff %%{init: { "logLevel": 1, "flowchart": {"htmlLabels":true }} }%%
style M stroke:#ff0000,fill:#ffcccc,color:#ff0000 classDiagram-v2
style N stroke:#0000ff,fill:#ccccff,color:#0000ff Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
Class12 <|.. Class08
Class11 ..>Class12
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class01 : -int privateChimp
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
</div>
<div class="mermaid" style="">
classDiagram-v2
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
Class12 <|.. Class08
Class11 ..>Class12
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class01 : -int privateChimp
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
</div> </div>
<script src="./mermaid.js"></script> <script src="./mermaid.js"></script>
<script> <script>
mermaid.parseError = function (err, hash) { mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err); // console.error('Mermaid error: ', err);
}; };
mermaid.initialize({ mermaid.initialize({
theme: 'neutral', // theme: 'neutral',
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: { nodeSpacing: 10, curve: 'cardinal', htmlLabels: true }, flowchart: { curve: 'cardinal', htmlLabels: false },
htmlLabels: true, // htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' }, // gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false }, // sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated // sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif', // fontFamily: '"times", sans-serif',
// fontFamily: 'courier', fontFamily: 'courier',
fontSize: 18, // fontSize: 18,
curve: 'cardinal', // curve: 'cardinal',
securityLevel: 'loose', securityLevel: 'loose',
// themeVariables: {relationLabelColor: 'red'} // themeVariables: {relationLabelColor: 'red'}
}); });

View File

@@ -40,7 +40,7 @@ const rect = (parent, node) => {
const width = node.width <= bbox.width + padding ? bbox.width + padding : node.width; const width = node.width <= bbox.width + padding ? bbox.width + padding : node.width;
if (node.width <= bbox.width + padding) { if (node.width <= bbox.width + padding) {
node.diff = (bbox.width - node.width) / 2; node.diff = (bbox.width - node.width) / 2 - node.padding / 2;
} else { } else {
node.diff = -node.padding / 2; node.diff = -node.padding / 2;
} }

View File

@@ -9,7 +9,7 @@ import { getConfig } from '../../config';
import { render } from '../../dagre-wrapper/index.js'; import { render } from '../../dagre-wrapper/index.js';
// import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js'; // import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
import { curveLinear } from 'd3'; import { curveLinear } from 'd3';
import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils'; import { interpolateToCurve, getStylesFromArray, setupGraphViewbox } from '../../utils';
import common from '../common/common'; import common from '../common/common';
import addSVGAccessibilityFields from '../../accessibility'; import addSVGAccessibilityFields from '../../accessibility';
@@ -322,16 +322,6 @@ export const draw = function (text, id) {
const relations = classDb.getRelations(); const relations = classDb.getRelations();
log.info(relations); log.info(relations);
// let i = 0;
// for (i = subGraphs.length - 1; i >= 0; i--) {
// subG = subGraphs[i];
// selectAll('cluster').append('text');
// for (let j = 0; j < subG.nodes.length; j++) {
// g.setParent(subG.nodes[j], subG.id);
// }
// }
addClasses(classes, g, id); addClasses(classes, g, id);
addRelations(relations, g); addRelations(relations, g);
@@ -354,28 +344,7 @@ export const draw = function (text, id) {
const element = root.select('#' + id + ' g'); const element = root.select('#' + id + ' g');
render(element, g, ['aggregation', 'extension', 'composition', 'dependency'], 'classDiagram', id); render(element, g, ['aggregation', 'extension', 'composition', 'dependency'], 'classDiagram', id);
// element.selectAll('g.node').attr('title', function() { setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth);
// return flowDb.getTooltip(this.id);
// });
const padding = 8;
const svgBounds = svg.node().getBBox();
const width = svgBounds.width + padding * 2;
const height = svgBounds.height + padding * 2;
log.debug(
`new ViewBox 0 0 ${width} ${height}`,
`translate(${padding - g._label.marginx}, ${padding - g._label.marginy})`
);
configureSvgSize(svg, height, width, conf.useMaxWidth);
svg.attr('viewBox', `0 0 ${width} ${height}`);
svg
.select('g')
.attr('transform', `translate(${padding - g._label.marginx}, ${padding - svgBounds.y})`);
// Index nodes
// flowDb.indexNodes('subGraph' + i);
// Add label rects for non html labels // Add label rects for non html labels
if (!conf.htmlLabels) { if (!conf.htmlLabels) {

View File

@@ -9,7 +9,7 @@ import { render } from '../../dagre-wrapper/index.js';
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js'; import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
import { log } from '../../logger'; import { log } from '../../logger';
import common, { evaluate } from '../common/common'; import common, { evaluate } from '../common/common';
import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils'; import { interpolateToCurve, getStylesFromArray, setupGraphViewbox } from '../../utils';
import addSVGAccessibilityFields from '../../accessibility'; import addSVGAccessibilityFields from '../../accessibility';
const conf = {}; const conf = {};
@@ -452,21 +452,7 @@ export const draw = function (text, id) {
const element = root.select('#' + id + ' g'); const element = root.select('#' + id + ' g');
render(element, g, ['point', 'circle', 'cross'], 'flowchart', id); render(element, g, ['point', 'circle', 'cross'], 'flowchart', id);
const padding = conf.diagramPadding; setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth);
const svgBounds = svg.node().getBBox();
const width = svgBounds.width + padding * 2;
const height = svgBounds.height + padding * 2;
log.debug(
`new ViewBox 0 0 ${width} ${height}`,
`translate(${padding - g._label.marginx}, ${padding - g._label.marginy})`
);
configureSvgSize(svg, height, width, conf.useMaxWidth);
svg.attr('viewBox', `0 0 ${width} ${height}`);
svg
.select('g')
.attr('transform', `translate(${padding - g._label.marginx}, ${padding - svgBounds.y})`);
// Index nodes // Index nodes
flowDb.indexNodes('subGraph' + i); flowDb.indexNodes('subGraph' + i);

View File

@@ -9,7 +9,7 @@ import dagreD3 from 'dagre-d3';
import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js'; import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js';
import { log } from '../../logger'; import { log } from '../../logger';
import common, { evaluate } from '../common/common'; import common, { evaluate } from '../common/common';
import { interpolateToCurve, getStylesFromArray, configureSvgSize } from '../../utils'; import { interpolateToCurve, getStylesFromArray, setupGraphViewbox } from '../../utils';
import flowChartShapes from './flowChartShapes'; import flowChartShapes from './flowChartShapes';
import addSVGAccessibilityFields from '../../accessibility'; import addSVGAccessibilityFields from '../../accessibility';
@@ -427,8 +427,6 @@ export const draw = function (text, id) {
const svg = root.select(`[id="${id}"]`); const svg = root.select(`[id="${id}"]`);
svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink'); svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink');
log.warn(g);
// Adds title and description to the flow chart // Adds title and description to the flow chart
addSVGAccessibilityFields(parser.yy, svg, id); addSVGAccessibilityFields(parser.yy, svg, id);
@@ -440,18 +438,6 @@ export const draw = function (text, id) {
return flowDb.getTooltip(this.id); return flowDb.getTooltip(this.id);
}); });
const padding = conf.diagramPadding;
const svgBounds = svg.node().getBBox();
const width = svgBounds.width + padding * 2;
const height = svgBounds.height + padding * 2;
configureSvgSize(svg, 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}`);
svg.attr('viewBox', vBox);
// Index nodes // Index nodes
flowDb.indexNodes('subGraph' + i); flowDb.indexNodes('subGraph' + i);
@@ -468,10 +454,10 @@ export const draw = function (text, id) {
const xPos = clusterRects[0].x.baseVal.value; const xPos = clusterRects[0].x.baseVal.value;
const yPos = clusterRects[0].y.baseVal.value; const yPos = clusterRects[0].y.baseVal.value;
const width = clusterRects[0].width.baseVal.value; const _width = clusterRects[0].width.baseVal.value;
const cluster = select(clusterEl[0]); const cluster = select(clusterEl[0]);
const te = cluster.select('.label'); const te = cluster.select('.label');
te.attr('transform', `translate(${xPos + width / 2}, ${yPos + 14})`); te.attr('transform', `translate(${xPos + _width / 2}, ${yPos + 14})`);
te.attr('id', id + 'Text'); te.attr('id', id + 'Text');
for (let j = 0; j < subG.classes.length; j++) { for (let j = 0; j < subG.classes.length; j++) {
@@ -499,6 +485,7 @@ export const draw = function (text, id) {
label.insertBefore(rect, label.firstChild); label.insertBefore(rect, label.firstChild);
} }
} }
setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth);
// If node has a link, wrap it in an anchor SVG object. // If node has a link, wrap it in an anchor SVG object.
const keys = Object.keys(vert); const keys = Object.keys(vert);

View File

@@ -919,6 +919,48 @@ export const configureSvgSize = function (svgElem, height, width, useMaxWidth) {
const attrs = calculateSvgSizeAttrs(height, width, useMaxWidth); const attrs = calculateSvgSizeAttrs(height, width, useMaxWidth);
d3Attrs(svgElem, attrs); d3Attrs(svgElem, attrs);
}; };
export const setupGraphViewbox = function (graph, svgElem, padding, useMaxWidth) {
const svgBounds = svgElem.node().getBBox();
const sWidth = svgBounds.width;
const sHeight = svgBounds.height;
let width = graph._label.width;
let height = graph._label.height;
let tx = 0;
let ty = 0;
if (sWidth > width) {
tx = (sWidth - width) / 2 + padding;
width = sWidth + padding * 2;
}
if (sHeight > height) {
ty = (sHeight - height) / 2 + padding;
height = sHeight + padding * 2;
}
configureSvgSize(svgElem, height, width, useMaxWidth);
// Ensure the viewBox includes the whole svgBounds area with extra space for padding
const vBox = `0 0 ${width} ${height}`;
log.debug(
'Grpah.label',
graph._label,
'swidth',
sWidth,
'sheight',
sHeight,
'width',
width,
'height',
height,
'tx',
tx,
'ty',
ty,
'vBox',
vBox
);
svgElem.attr('viewBox', vBox);
svgElem.select('g').attr('transform', `translate(${tx}, ${ty})`);
};
export const initIdGeneratior = class iterator { export const initIdGeneratior = class iterator {
constructor(deterministic, seed) { constructor(deterministic, seed) {
@@ -1018,6 +1060,7 @@ export default {
calculateTextDimensions, calculateTextDimensions,
calculateSvgSizeAttrs, calculateSvgSizeAttrs,
configureSvgSize, configureSvgSize,
setupGraphViewbox,
detectInit, detectInit,
detectDirective, detectDirective,
detectType, detectType,