mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-25 11:16:53 +02:00
Compare commits
28 Commits
mermaid@11
...
5824-diff-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4693aa2749 | ||
![]() |
468b6a55b6 | ||
![]() |
df636c6d0a | ||
![]() |
64554a6c60 | ||
![]() |
becadf0a7d | ||
![]() |
54d485f173 | ||
![]() |
b4f5b8ddaf | ||
![]() |
cb5c1ae367 | ||
![]() |
b29081d4e8 | ||
![]() |
654097c438 | ||
![]() |
1e672868c4 | ||
![]() |
c7880d7281 | ||
![]() |
bff32827b5 | ||
![]() |
f27ca07371 | ||
![]() |
65f9b29b86 | ||
![]() |
b4879d13b8 | ||
![]() |
95964b5487 | ||
![]() |
4e17da0a30 | ||
![]() |
2a91849a38 | ||
![]() |
082de76eef | ||
![]() |
570ae78b15 | ||
![]() |
885ac6f947 | ||
![]() |
193fdb225e | ||
![]() |
7cbd80af33 | ||
![]() |
16c448b89b | ||
![]() |
cb0a4703bd | ||
![]() |
8cb1c68166 | ||
![]() |
d752240efc |
5
.changeset/angry-bags-brake.md
Normal file
5
.changeset/angry-bags-brake.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: architecture diagrams no longer grow to extreme heights due to conflicting alignments
|
5
.changeset/gold-ducks-sort.md
Normal file
5
.changeset/gold-ducks-sort.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: Proper separation between strings and markdown strings
|
@@ -171,6 +171,58 @@ describe.skip('architecture diagram', () => {
|
|||||||
`
|
`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should render an architecture diagram with a resonable height', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`architecture-beta
|
||||||
|
group federated(cloud)[Federated Environment]
|
||||||
|
service server1(server)[System] in federated
|
||||||
|
service edge(server)[Edge Device] in federated
|
||||||
|
server1:R -- L:edge
|
||||||
|
|
||||||
|
group on_prem(cloud)[Hub]
|
||||||
|
service firewall(server)[Firewall Device] in on_prem
|
||||||
|
service server(server)[Server] in on_prem
|
||||||
|
firewall:R -- L:server
|
||||||
|
|
||||||
|
service db1(database)[db1] in on_prem
|
||||||
|
service db2(database)[db2] in on_prem
|
||||||
|
service db3(database)[db3] in on_prem
|
||||||
|
service db4(database)[db4] in on_prem
|
||||||
|
service db5(database)[db5] in on_prem
|
||||||
|
service db6(database)[db6] in on_prem
|
||||||
|
|
||||||
|
junction mid in on_prem
|
||||||
|
server:B -- T:mid
|
||||||
|
|
||||||
|
junction 1Leftofmid in on_prem
|
||||||
|
1Leftofmid:R -- L:mid
|
||||||
|
1Leftofmid:B -- T:db1
|
||||||
|
|
||||||
|
junction 2Leftofmid in on_prem
|
||||||
|
2Leftofmid:R -- L:1Leftofmid
|
||||||
|
2Leftofmid:B -- T:db2
|
||||||
|
|
||||||
|
junction 3Leftofmid in on_prem
|
||||||
|
3Leftofmid:R -- L:2Leftofmid
|
||||||
|
3Leftofmid:B -- T:db3
|
||||||
|
|
||||||
|
junction 1RightOfMid in on_prem
|
||||||
|
mid:R -- L:1RightOfMid
|
||||||
|
1RightOfMid:B -- T:db4
|
||||||
|
|
||||||
|
junction 2RightOfMid in on_prem
|
||||||
|
1RightOfMid:R -- L:2RightOfMid
|
||||||
|
2RightOfMid:B -- T:db5
|
||||||
|
|
||||||
|
junction 3RightOfMid in on_prem
|
||||||
|
2RightOfMid:R -- L:3RightOfMid
|
||||||
|
3RightOfMid:B -- T:db6
|
||||||
|
|
||||||
|
edge:R -- L:firewall
|
||||||
|
`
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Skipped as the layout is not deterministic, and causes issues in E2E tests.
|
// Skipped as the layout is not deterministic, and causes issues in E2E tests.
|
||||||
|
@@ -900,6 +900,153 @@ flowchart LR
|
|||||||
n7@{ shape: rect}
|
n7@{ shape: rect}
|
||||||
n8@{ shape: rect}
|
n8@{ shape: rect}
|
||||||
|
|
||||||
|
`,
|
||||||
|
{ flowchart: { titleTopMargin: 0 } }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('6088-1: should handle diamond shape intersections', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`---
|
||||||
|
config:
|
||||||
|
layout: elk
|
||||||
|
---
|
||||||
|
flowchart LR
|
||||||
|
subgraph S2
|
||||||
|
subgraph s1["APA"]
|
||||||
|
D{"Use the editor"}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
D -- Mermaid js --> I{"fa:fa-code Text"}
|
||||||
|
D --> I
|
||||||
|
D --> I
|
||||||
|
|
||||||
|
end
|
||||||
|
`,
|
||||||
|
{ flowchart: { titleTopMargin: 0 } }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('6088-2: should handle diamond shape intersections', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`---
|
||||||
|
config:
|
||||||
|
layout: elk
|
||||||
|
---
|
||||||
|
flowchart LR
|
||||||
|
a
|
||||||
|
subgraph s0["APA"]
|
||||||
|
subgraph s8["APA"]
|
||||||
|
subgraph s1["APA"]
|
||||||
|
D{"X"}
|
||||||
|
E[Q]
|
||||||
|
end
|
||||||
|
subgraph s3["BAPA"]
|
||||||
|
F[Q]
|
||||||
|
I
|
||||||
|
end
|
||||||
|
D --> I
|
||||||
|
D --> I
|
||||||
|
D --> I
|
||||||
|
|
||||||
|
I{"X"}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
`,
|
||||||
|
{ flowchart: { titleTopMargin: 0 } }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('6088-3: should handle diamond shape intersections', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`---
|
||||||
|
config:
|
||||||
|
layout: elk
|
||||||
|
---
|
||||||
|
flowchart LR
|
||||||
|
a
|
||||||
|
D{"Use the editor"}
|
||||||
|
|
||||||
|
D -- Mermaid js --> I{"fa:fa-code Text"}
|
||||||
|
D-->I
|
||||||
|
D-->I
|
||||||
|
|
||||||
|
`,
|
||||||
|
{ flowchart: { titleTopMargin: 0 } }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('6088-4: should handle diamond shape intersections', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`---
|
||||||
|
config:
|
||||||
|
layout: elk
|
||||||
|
---
|
||||||
|
flowchart LR
|
||||||
|
subgraph s1["Untitled subgraph"]
|
||||||
|
n1["Evaluate"]
|
||||||
|
n2["Option 1"]
|
||||||
|
n3["Option 2"]
|
||||||
|
n4["fa:fa-car Option 3"]
|
||||||
|
end
|
||||||
|
subgraph s2["Untitled subgraph"]
|
||||||
|
n5["Evaluate"]
|
||||||
|
n6["Option 1"]
|
||||||
|
n7["Option 2"]
|
||||||
|
n8["fa:fa-car Option 3"]
|
||||||
|
end
|
||||||
|
A["Start"] -- Some text --> B("Continue")
|
||||||
|
B --> C{"Evaluate"}
|
||||||
|
C -- One --> D["Option 1"]
|
||||||
|
C -- Two --> E["Option 2"]
|
||||||
|
C -- Three --> F["fa:fa-car Option 3"]
|
||||||
|
n1 -- One --> n2
|
||||||
|
n1 -- Two --> n3
|
||||||
|
n1 -- Three --> n4
|
||||||
|
n5 -- One --> n6
|
||||||
|
n5 -- Two --> n7
|
||||||
|
n5 -- Three --> n8
|
||||||
|
n1@{ shape: diam}
|
||||||
|
n2@{ shape: rect}
|
||||||
|
n3@{ shape: rect}
|
||||||
|
n4@{ shape: rect}
|
||||||
|
n5@{ shape: diam}
|
||||||
|
n6@{ shape: rect}
|
||||||
|
n7@{ shape: rect}
|
||||||
|
n8@{ shape: rect}
|
||||||
|
|
||||||
|
`,
|
||||||
|
{ flowchart: { titleTopMargin: 0 } }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('6088-5: should handle diamond shape intersections', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`---
|
||||||
|
config:
|
||||||
|
layout: elk
|
||||||
|
---
|
||||||
|
flowchart LR
|
||||||
|
A{A} --> B & C
|
||||||
|
|
||||||
|
`,
|
||||||
|
{ flowchart: { titleTopMargin: 0 } }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('6088-6: should handle diamond shape intersections', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`---
|
||||||
|
config:
|
||||||
|
layout: elk
|
||||||
|
---
|
||||||
|
flowchart LR
|
||||||
|
A{A} --> B & C
|
||||||
|
subgraph "subbe"
|
||||||
|
A
|
||||||
|
end
|
||||||
|
|
||||||
`,
|
`,
|
||||||
{ flowchart: { titleTopMargin: 0 } }
|
{ flowchart: { titleTopMargin: 0 } }
|
||||||
);
|
);
|
||||||
|
@@ -917,4 +917,24 @@ graph TD
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it('68: should be able to render string and markdown labels (#5824)', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
flowchart TB
|
||||||
|
mermaid{"What is\nyourmermaid version?"} --> v10["<11"] --"\`<**1**1\`"--> fine["No bug"]
|
||||||
|
mermaid --> v11[">= v11"] -- ">= v11" --> broken["Affected by https://github.com/mermaid-js/mermaid/issues/5824"]
|
||||||
|
subgraph subgraph1["\`How to fix **fix**\`"]
|
||||||
|
broken --> B["B"]
|
||||||
|
end
|
||||||
|
githost["Github, Gitlab, BitBucket, etc."]
|
||||||
|
githost2["\`Github, Gitlab, BitBucket, etc.\`"]
|
||||||
|
a["1."]
|
||||||
|
b["- x"]
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
flowchart: { htmlLabels: true },
|
||||||
|
securityLevel: 'loose',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -88,36 +88,64 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<pre id="diagram4" class="mermaid2">
|
<pre id="diagram4" class="mermaid">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
---
|
---
|
||||||
flowchart LR
|
flowchart LR
|
||||||
subgraph s1["Untitled subgraph"]
|
subgraph S2
|
||||||
n1["Evaluate"]
|
subgraph s1["APA"]
|
||||||
n2["Option 1"]
|
D{"Use the editor"}
|
||||||
n3["Option 2"]
|
|
||||||
n4["fa:fa-car Option 3"]
|
|
||||||
end
|
end
|
||||||
n1 -- One --> n2
|
|
||||||
n1 -- Two --> n3
|
|
||||||
n1 -- Three --> n4
|
|
||||||
n5
|
|
||||||
n1@{ shape: diam}
|
|
||||||
n2@{ shape: rect}
|
|
||||||
n3@{ shape: rect}
|
|
||||||
n4@{ shape: rect}
|
|
||||||
A["Start"] -- Some text --> B("Continue")
|
|
||||||
B --> C{"Evaluate"}
|
|
||||||
C -- One --> D["Option 1"]
|
|
||||||
C -- Two --> E["Option 2"]
|
|
||||||
C -- Three --> F["fa:fa-car Option 3"]
|
|
||||||
|
|
||||||
|
|
||||||
|
D -- Mermaid js --> I{"fa:fa-code Text"}
|
||||||
|
D --> I
|
||||||
|
D --> I
|
||||||
|
|
||||||
|
end
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid">
|
||||||
---
|
---
|
||||||
|
config:
|
||||||
|
layout: elk
|
||||||
|
---
|
||||||
|
flowchart LR
|
||||||
|
a
|
||||||
|
subgraph s0["APA"]
|
||||||
|
subgraph s8["APA"]
|
||||||
|
subgraph s1["APA"]
|
||||||
|
D{"X"}
|
||||||
|
E[Q]
|
||||||
|
end
|
||||||
|
subgraph s3["BAPA"]
|
||||||
|
F[Q]
|
||||||
|
I
|
||||||
|
end
|
||||||
|
D --> I
|
||||||
|
D --> I
|
||||||
|
D --> I
|
||||||
|
|
||||||
|
I{"X"}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
<pre id="diagram4" class="mermaid">
|
||||||
|
---
|
||||||
|
config:
|
||||||
|
layout: elk
|
||||||
|
---
|
||||||
|
flowchart LR
|
||||||
|
a
|
||||||
|
D{"Use the editor"}
|
||||||
|
|
||||||
|
D -- Mermaid js --> I{"fa:fa-code Text"}
|
||||||
|
D-->I
|
||||||
|
D-->I
|
||||||
|
</pre>
|
||||||
|
<pre id="diagram4" class="mermaid2">
|
||||||
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
---
|
---
|
||||||
@@ -155,23 +183,23 @@ flowchart LR
|
|||||||
n8@{ shape: rect}
|
n8@{ shape: rect}
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid2">
|
<pre id="diagram4" class="mermaid">
|
||||||
---
|
---
|
||||||
config:
|
title: https://github.com/mermaid-js/mermaid/issues/5824
|
||||||
layout: elk
|
|
||||||
---
|
---
|
||||||
flowchart LR
|
%% 6048, 5824
|
||||||
subgraph s1["Untitled subgraph"]
|
flowchart TB
|
||||||
n1["Evaluate"]
|
mermaid{"What is\nyourmermaid version?"} --> v10["<11"] --"`<**1**1`"--> fine["No bug"]
|
||||||
n2["Option 1"]
|
mermaid --> v11[">= v11"] -- ">= v11" --> broken["Affected by https://github.com/mermaid-js/mermaid/issues/5824"]
|
||||||
|
subgraph subgraph1["`How to fix **fix**`"]
|
||||||
|
broken --> B["B"]
|
||||||
end
|
end
|
||||||
n1 -- One --> n2
|
githost["Github, Gitlab, BitBucket, etc."]
|
||||||
|
githost2["`Github, Gitlab, BitBucket, etc.`"]
|
||||||
|
a["1."]
|
||||||
|
b["- x"]
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid2">
|
<pre id="diagram4" class="mermaid">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
@@ -180,7 +208,19 @@ flowchart LR
|
|||||||
A{A} --> B & C
|
A{A} --> B & C
|
||||||
</pre
|
</pre
|
||||||
>
|
>
|
||||||
<pre id="diagram4" class="mermaid2">
|
<pre id="diagram4" class="mermaid">
|
||||||
|
---
|
||||||
|
config:
|
||||||
|
layout: elk
|
||||||
|
---
|
||||||
|
flowchart LR
|
||||||
|
A{A} --> B & C
|
||||||
|
subgraph "subbe"
|
||||||
|
A
|
||||||
|
end
|
||||||
|
</pre
|
||||||
|
>
|
||||||
|
<pre id="diagram4" class="mermaid">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
|
@@ -39,8 +39,8 @@ graph TB
|
|||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import mermaid from '/mermaid.esm.mjs';
|
import mermaid from '/mermaid.esm.mjs';
|
||||||
import flowchartELK from '/mermaid-flowchart-elk.esm.mjs';
|
import layouts from '/mermaid-layout-elk.esm.mjs';
|
||||||
await mermaid.registerExternalDiagrams([flowchartELK]);
|
mermaid.registerLayoutLoaders(layouts);
|
||||||
async function render(str) {
|
async function render(str) {
|
||||||
const { svg } = await mermaid.render('dynamic', str);
|
const { svg } = await mermaid.render('dynamic', str);
|
||||||
document.getElementById('dynamicDiagram').innerHTML = svg;
|
document.getElementById('dynamicDiagram').innerHTML = svg;
|
||||||
|
@@ -500,7 +500,7 @@ mermaid.ganttConfig = {
|
|||||||
sectionFontSize: 24, // Font size for sections
|
sectionFontSize: 24, // Font size for sections
|
||||||
numberSectionStyles: 1, // The number of alternating section styles
|
numberSectionStyles: 1, // The number of alternating section styles
|
||||||
axisFormat: '%d/%m', // Date/time format of the axis
|
axisFormat: '%d/%m', // Date/time format of the axis
|
||||||
tickInterval: '1 week', // Axis ticks
|
tickInterval: '1week', // Axis ticks
|
||||||
topAxis: true, // When this flag is set, date labels will be added to the top of the chart
|
topAxis: true, // When this flag is set, date labels will be added to the top of the chart
|
||||||
displayMode: 'compact', // Turns compact mode on
|
displayMode: 'compact', // Turns compact mode on
|
||||||
weekday: 'sunday', // On which day a week-based interval should start
|
weekday: 'sunday', // On which day a week-based interval should start
|
||||||
|
@@ -86,7 +86,7 @@ todo[Todo]
|
|||||||
|
|
||||||
## Configuration Options
|
## Configuration Options
|
||||||
|
|
||||||
You can customize the Kanban diagram using a configuration block at the beginning of your markdown file. This is useful for setting global settings like a base URL for tickets. Currently there is one configuration option for kanban diagrams tacketBaseUrl. This can be set as in the the following example:
|
You can customize the Kanban diagram using a configuration block at the beginning of your markdown file. This is useful for setting global settings like a base URL for tickets. Currently there is one configuration option for kanban diagrams `ticketBaseUrl`. This can be set as in the the following example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
---
|
---
|
||||||
|
@@ -1,5 +1,11 @@
|
|||||||
# @mermaid-js/layout-elk
|
# @mermaid-js/layout-elk
|
||||||
|
|
||||||
|
## 0.1.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#6090](https://github.com/mermaid-js/mermaid/pull/6090) [`654097c`](https://github.com/mermaid-js/mermaid/commit/654097c43801b2d606bc3d2bef8c6fbc3301e9e4) Thanks [@knsv](https://github.com/knsv)! - fix: Updated offset calculations for diamond shape when handling intersections
|
||||||
|
|
||||||
## 0.1.6
|
## 0.1.6
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@mermaid-js/layout-elk",
|
"name": "@mermaid-js/layout-elk",
|
||||||
"version": "0.1.6",
|
"version": "0.1.7",
|
||||||
"description": "ELK layout engine for mermaid",
|
"description": "ELK layout engine for mermaid",
|
||||||
"module": "dist/mermaid-layout-elk.core.mjs",
|
"module": "dist/mermaid-layout-elk.core.mjs",
|
||||||
"types": "dist/layouts.d.ts",
|
"types": "dist/layouts.d.ts",
|
||||||
|
@@ -705,14 +705,11 @@ export const render = async (
|
|||||||
bounds: { x: any; y: any; width: any; height: any; padding: any },
|
bounds: { x: any; y: any; width: any; height: any; padding: any },
|
||||||
isDiamond: boolean
|
isDiamond: boolean
|
||||||
) => {
|
) => {
|
||||||
log.debug('UIO cutPathAtIntersect Points:', _points, 'node:', bounds, 'isDiamond', isDiamond);
|
log.debug('APA18 cutPathAtIntersect Points:', _points, 'node:', bounds, 'isDiamond', isDiamond);
|
||||||
const points: any[] = [];
|
const points: any[] = [];
|
||||||
let lastPointOutside = _points[0];
|
let lastPointOutside = _points[0];
|
||||||
let isInside = false;
|
let isInside = false;
|
||||||
_points.forEach((point: any) => {
|
_points.forEach((point: any) => {
|
||||||
// const node = clusterDb[edge.toCluster].node;
|
|
||||||
log.debug(' checking point', point, bounds);
|
|
||||||
|
|
||||||
// check if point is inside the boundary rect
|
// check if point is inside the boundary rect
|
||||||
if (!outsideNode(bounds, point) && !isInside) {
|
if (!outsideNode(bounds, point) && !isInside) {
|
||||||
// First point inside the rect found
|
// First point inside the rect found
|
||||||
@@ -906,7 +903,7 @@ export const render = async (
|
|||||||
|
|
||||||
const offset = calcOffset(sourceId, targetId, parentLookupDb);
|
const offset = calcOffset(sourceId, targetId, parentLookupDb);
|
||||||
log.debug(
|
log.debug(
|
||||||
'offset',
|
'APA18 offset',
|
||||||
offset,
|
offset,
|
||||||
sourceId,
|
sourceId,
|
||||||
' ==> ',
|
' ==> ',
|
||||||
@@ -971,29 +968,22 @@ export const render = async (
|
|||||||
}
|
}
|
||||||
if (startNode.shape === 'diamond' || startNode.shape === 'diam') {
|
if (startNode.shape === 'diamond' || startNode.shape === 'diam') {
|
||||||
edge.points.unshift({
|
edge.points.unshift({
|
||||||
x: startNode.x + startNode.width / 2 + offset.x,
|
x: startNode.offset.posX + startNode.width / 2,
|
||||||
y: startNode.y + startNode.height / 2 + offset.y,
|
y: startNode.offset.posY + startNode.height / 2,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (endNode.shape === 'diamond' || endNode.shape === 'diam') {
|
if (endNode.shape === 'diamond' || endNode.shape === 'diam') {
|
||||||
const x = endNode.x + endNode.width / 2 + offset.x;
|
|
||||||
// Add a point at the center of the diamond
|
|
||||||
if (
|
|
||||||
Math.abs(edge.points[edge.points.length - 1].y - endNode.y - offset.y) > 0.01 ||
|
|
||||||
Math.abs(edge.points[edge.points.length - 1].x - x) > 0.001
|
|
||||||
) {
|
|
||||||
edge.points.push({
|
edge.points.push({
|
||||||
x: endNode.x + endNode.width / 2 + offset.x,
|
x: endNode.offset.posX + endNode.width / 2,
|
||||||
y: endNode.y + endNode.height / 2 + offset.y,
|
y: endNode.offset.posY + endNode.height / 2,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
edge.points = cutPathAtIntersect(
|
edge.points = cutPathAtIntersect(
|
||||||
edge.points.reverse(),
|
edge.points.reverse(),
|
||||||
{
|
{
|
||||||
x: startNode.x + startNode.width / 2 + offset.x,
|
x: startNode.offset.posX + startNode.width / 2,
|
||||||
y: startNode.y + startNode.height / 2 + offset.y,
|
y: startNode.offset.posY + startNode.height / 2,
|
||||||
width: sw,
|
width: sw,
|
||||||
height: startNode.height,
|
height: startNode.height,
|
||||||
padding: startNode.padding,
|
padding: startNode.padding,
|
||||||
@@ -1004,8 +994,8 @@ export const render = async (
|
|||||||
edge.points = cutPathAtIntersect(
|
edge.points = cutPathAtIntersect(
|
||||||
edge.points,
|
edge.points,
|
||||||
{
|
{
|
||||||
x: endNode.x + ew / 2 + endNode.offset.x,
|
x: endNode.offset.posX + endNode.width / 2,
|
||||||
y: endNode.y + endNode.height / 2 + endNode.offset.y,
|
y: endNode.offset.posY + endNode.height / 2,
|
||||||
width: ew,
|
width: ew,
|
||||||
height: endNode.height,
|
height: endNode.height,
|
||||||
padding: endNode.padding,
|
padding: endNode.padding,
|
||||||
|
@@ -13,6 +13,7 @@ import {
|
|||||||
setDiagramTitle,
|
setDiagramTitle,
|
||||||
} from '../common/commonDb.js';
|
} from '../common/commonDb.js';
|
||||||
import type {
|
import type {
|
||||||
|
ArchitectureAlignment,
|
||||||
ArchitectureDB,
|
ArchitectureDB,
|
||||||
ArchitectureDirectionPair,
|
ArchitectureDirectionPair,
|
||||||
ArchitectureDirectionPairMap,
|
ArchitectureDirectionPairMap,
|
||||||
@@ -25,6 +26,7 @@ import type {
|
|||||||
ArchitectureState,
|
ArchitectureState,
|
||||||
} from './architectureTypes.js';
|
} from './architectureTypes.js';
|
||||||
import {
|
import {
|
||||||
|
getArchitectureDirectionAlignment,
|
||||||
getArchitectureDirectionPair,
|
getArchitectureDirectionPair,
|
||||||
isArchitectureDirection,
|
isArchitectureDirection,
|
||||||
isArchitectureJunction,
|
isArchitectureJunction,
|
||||||
@@ -211,12 +213,18 @@ const addEdge = function ({
|
|||||||
const getEdges = (): ArchitectureEdge[] => state.records.edges;
|
const getEdges = (): ArchitectureEdge[] => state.records.edges;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current diagram's adjacency list & spatial map.
|
* Returns the current diagram's adjacency list, spatial map, & group alignments.
|
||||||
* If they have not been created, run the algorithms to generate them.
|
* If they have not been created, run the algorithms to generate them.
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const getDataStructures = () => {
|
const getDataStructures = () => {
|
||||||
if (state.records.dataStructures === undefined) {
|
if (state.records.dataStructures === undefined) {
|
||||||
|
// Tracks how groups are aligned with one another. Generated while creating the adj list
|
||||||
|
const groupAlignments: Record<
|
||||||
|
string,
|
||||||
|
Record<string, Exclude<ArchitectureAlignment, 'bend'>>
|
||||||
|
> = {};
|
||||||
|
|
||||||
// Create an adjacency list of the diagram to perform BFS on
|
// Create an adjacency list of the diagram to perform BFS on
|
||||||
// Outer reduce applied on all services
|
// Outer reduce applied on all services
|
||||||
// Inner reduce applied on the edges for a service
|
// Inner reduce applied on the edges for a service
|
||||||
@@ -224,6 +232,19 @@ const getDataStructures = () => {
|
|||||||
Record<string, ArchitectureDirectionPairMap>
|
Record<string, ArchitectureDirectionPairMap>
|
||||||
>((prevOuter, [id, service]) => {
|
>((prevOuter, [id, service]) => {
|
||||||
prevOuter[id] = service.edges.reduce<ArchitectureDirectionPairMap>((prevInner, edge) => {
|
prevOuter[id] = service.edges.reduce<ArchitectureDirectionPairMap>((prevInner, edge) => {
|
||||||
|
// track the direction groups connect to one another
|
||||||
|
const lhsGroupId = getNode(edge.lhsId)?.in;
|
||||||
|
const rhsGroupId = getNode(edge.rhsId)?.in;
|
||||||
|
if (lhsGroupId && rhsGroupId && lhsGroupId !== rhsGroupId) {
|
||||||
|
const alignment = getArchitectureDirectionAlignment(edge.lhsDir, edge.rhsDir);
|
||||||
|
if (alignment !== 'bend') {
|
||||||
|
groupAlignments[lhsGroupId] ??= {};
|
||||||
|
groupAlignments[lhsGroupId][rhsGroupId] = alignment;
|
||||||
|
groupAlignments[rhsGroupId] ??= {};
|
||||||
|
groupAlignments[rhsGroupId][lhsGroupId] = alignment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (edge.lhsId === id) {
|
if (edge.lhsId === id) {
|
||||||
// source is LHS
|
// source is LHS
|
||||||
const pair = getArchitectureDirectionPair(edge.lhsDir, edge.rhsDir);
|
const pair = getArchitectureDirectionPair(edge.lhsDir, edge.rhsDir);
|
||||||
@@ -245,6 +266,7 @@ const getDataStructures = () => {
|
|||||||
// Configuration for the initial pass of BFS
|
// Configuration for the initial pass of BFS
|
||||||
const firstId = Object.keys(adjList)[0];
|
const firstId = Object.keys(adjList)[0];
|
||||||
const visited = { [firstId]: 1 };
|
const visited = { [firstId]: 1 };
|
||||||
|
// If a key is present in this object, it has not been visited
|
||||||
const notVisited = Object.keys(adjList).reduce(
|
const notVisited = Object.keys(adjList).reduce(
|
||||||
(prev, id) => (id === firstId ? prev : { ...prev, [id]: 1 }),
|
(prev, id) => (id === firstId ? prev : { ...prev, [id]: 1 }),
|
||||||
{} as Record<string, number>
|
{} as Record<string, number>
|
||||||
@@ -283,6 +305,7 @@ const getDataStructures = () => {
|
|||||||
state.records.dataStructures = {
|
state.records.dataStructures = {
|
||||||
adjList,
|
adjList,
|
||||||
spatialMaps,
|
spatialMaps,
|
||||||
|
groupAlignments,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return state.records.dataStructures;
|
return state.records.dataStructures;
|
||||||
|
@@ -12,7 +12,9 @@ import { setupGraphViewbox } from '../../setupGraphViewbox.js';
|
|||||||
import { getConfigField } from './architectureDb.js';
|
import { getConfigField } from './architectureDb.js';
|
||||||
import { architectureIcons } from './architectureIcons.js';
|
import { architectureIcons } from './architectureIcons.js';
|
||||||
import type {
|
import type {
|
||||||
|
ArchitectureAlignment,
|
||||||
ArchitectureDataStructures,
|
ArchitectureDataStructures,
|
||||||
|
ArchitectureGroupAlignments,
|
||||||
ArchitectureJunction,
|
ArchitectureJunction,
|
||||||
ArchitectureSpatialMap,
|
ArchitectureSpatialMap,
|
||||||
EdgeSingular,
|
EdgeSingular,
|
||||||
@@ -149,25 +151,91 @@ function addEdges(edges: ArchitectureEdge[], cy: cytoscape.Core) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAlignments(spatialMaps: ArchitectureSpatialMap[]): fcose.FcoseAlignmentConstraint {
|
function getAlignments(
|
||||||
|
db: ArchitectureDB,
|
||||||
|
spatialMaps: ArchitectureSpatialMap[],
|
||||||
|
groupAlignments: ArchitectureGroupAlignments
|
||||||
|
): fcose.FcoseAlignmentConstraint {
|
||||||
|
/**
|
||||||
|
* Flattens the alignment object so nodes in different groups will be in the same alignment array IFF their groups don't connect in a conflicting alignment
|
||||||
|
*
|
||||||
|
* i.e., two groups which connect horizontally should not have nodes with vertical alignments to one another
|
||||||
|
*
|
||||||
|
* See: #5952
|
||||||
|
*
|
||||||
|
* @param alignmentObj - alignment object with the outer key being the row/col # and the inner key being the group name mapped to the nodes on that axis in the group
|
||||||
|
* @param alignmentDir - alignment direction
|
||||||
|
* @returns flattened alignment object with an arbitrary key mapping to nodes in the same row/col
|
||||||
|
*/
|
||||||
|
const flattenAlignments = (
|
||||||
|
alignmentObj: Record<number, Record<string, string[]>>,
|
||||||
|
alignmentDir: ArchitectureAlignment
|
||||||
|
): Record<string, string[]> => {
|
||||||
|
return Object.entries(alignmentObj).reduce(
|
||||||
|
(prev, [dir, alignments]) => {
|
||||||
|
// prev is the mapping of x/y coordinate to an array of the nodes in that row/column
|
||||||
|
let cnt = 0;
|
||||||
|
const arr = Object.entries(alignments); // [group name, array of nodes within the group on axis dir]
|
||||||
|
if (arr.length === 1) {
|
||||||
|
// If only one group exists in the row/column, we don't need to do anything else
|
||||||
|
prev[dir] = arr[0][1];
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < arr.length - 1; i++) {
|
||||||
|
for (let j = i + 1; j < arr.length; j++) {
|
||||||
|
const [aGroupId, aNodeIds] = arr[i];
|
||||||
|
const [bGroupId, bNodeIds] = arr[j];
|
||||||
|
const alignment = groupAlignments[aGroupId]?.[bGroupId]; // Get how the two groups are intended to align (undefined if they aren't)
|
||||||
|
|
||||||
|
if (alignment === alignmentDir) {
|
||||||
|
// If the intended alignment between the two groups is the same as the alignment we are parsing
|
||||||
|
prev[dir] ??= [];
|
||||||
|
prev[dir] = [...prev[dir], ...aNodeIds, ...bNodeIds]; // add the node ids of both groups to the axis array in prev
|
||||||
|
} else if (aGroupId === 'default' || bGroupId === 'default') {
|
||||||
|
// If either of the groups are in the default space (not in a group), use the same behavior as above
|
||||||
|
prev[dir] ??= [];
|
||||||
|
prev[dir] = [...prev[dir], ...aNodeIds, ...bNodeIds];
|
||||||
|
} else {
|
||||||
|
// Otherwise, the nodes in the two groups are not intended to align
|
||||||
|
const keyA = `${dir}-${cnt++}`;
|
||||||
|
prev[keyA] = aNodeIds;
|
||||||
|
const keyB = `${dir}-${cnt++}`;
|
||||||
|
prev[keyB] = bNodeIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return prev;
|
||||||
|
},
|
||||||
|
{} as Record<string, string[]>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const alignments = spatialMaps.map((spatialMap) => {
|
const alignments = spatialMaps.map((spatialMap) => {
|
||||||
const horizontalAlignments: Record<number, string[]> = {};
|
const horizontalAlignments: Record<number, Record<string, string[]>> = {};
|
||||||
const verticalAlignments: Record<number, string[]> = {};
|
const verticalAlignments: Record<number, Record<string, string[]>> = {};
|
||||||
|
|
||||||
// Group service ids in an object with their x and y coordinate as the key
|
// Group service ids in an object with their x and y coordinate as the key
|
||||||
Object.entries(spatialMap).forEach(([id, [x, y]]) => {
|
Object.entries(spatialMap).forEach(([id, [x, y]]) => {
|
||||||
if (!horizontalAlignments[y]) {
|
const nodeGroup = db.getNode(id)?.in ?? 'default';
|
||||||
horizontalAlignments[y] = [];
|
|
||||||
}
|
horizontalAlignments[y] ??= {};
|
||||||
if (!verticalAlignments[x]) {
|
horizontalAlignments[y][nodeGroup] ??= [];
|
||||||
verticalAlignments[x] = [];
|
horizontalAlignments[y][nodeGroup].push(id);
|
||||||
}
|
|
||||||
horizontalAlignments[y].push(id);
|
verticalAlignments[x] ??= {};
|
||||||
verticalAlignments[x].push(id);
|
verticalAlignments[x][nodeGroup] ??= [];
|
||||||
|
verticalAlignments[x][nodeGroup].push(id);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Merge the values of each object into a list if the inner list has at least 2 elements
|
// Merge the values of each object into a list if the inner list has at least 2 elements
|
||||||
return {
|
return {
|
||||||
horiz: Object.values(horizontalAlignments).filter((arr) => arr.length > 1),
|
horiz: Object.values(flattenAlignments(horizontalAlignments, 'horizontal')).filter(
|
||||||
vert: Object.values(verticalAlignments).filter((arr) => arr.length > 1),
|
(arr) => arr.length > 1
|
||||||
|
),
|
||||||
|
vert: Object.values(flattenAlignments(verticalAlignments, 'vertical')).filter(
|
||||||
|
(arr) => arr.length > 1
|
||||||
|
),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -244,7 +312,8 @@ function layoutArchitecture(
|
|||||||
junctions: ArchitectureJunction[],
|
junctions: ArchitectureJunction[],
|
||||||
groups: ArchitectureGroup[],
|
groups: ArchitectureGroup[],
|
||||||
edges: ArchitectureEdge[],
|
edges: ArchitectureEdge[],
|
||||||
{ spatialMaps }: ArchitectureDataStructures
|
db: ArchitectureDB,
|
||||||
|
{ spatialMaps, groupAlignments }: ArchitectureDataStructures
|
||||||
): Promise<cytoscape.Core> {
|
): Promise<cytoscape.Core> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const renderEl = select('body').append('div').attr('id', 'cy').attr('style', 'display:none');
|
const renderEl = select('body').append('div').attr('id', 'cy').attr('style', 'display:none');
|
||||||
@@ -318,9 +387,8 @@ function layoutArchitecture(
|
|||||||
addServices(services, cy);
|
addServices(services, cy);
|
||||||
addJunctions(junctions, cy);
|
addJunctions(junctions, cy);
|
||||||
addEdges(edges, cy);
|
addEdges(edges, cy);
|
||||||
|
|
||||||
// Use the spatial map to create alignment arrays for fcose
|
// Use the spatial map to create alignment arrays for fcose
|
||||||
const alignmentConstraint = getAlignments(spatialMaps);
|
const alignmentConstraint = getAlignments(db, spatialMaps, groupAlignments);
|
||||||
|
|
||||||
// Create the relative constraints for fcose by using an inverse of the spatial map and performing BFS on it
|
// Create the relative constraints for fcose by using an inverse of the spatial map and performing BFS on it
|
||||||
const relativePlacementConstraint = getRelativeConstraints(spatialMaps);
|
const relativePlacementConstraint = getRelativeConstraints(spatialMaps);
|
||||||
@@ -454,7 +522,7 @@ export const draw: DrawDefinition = async (text, id, _version, diagObj: Diagram)
|
|||||||
await drawServices(db, servicesElem, services);
|
await drawServices(db, servicesElem, services);
|
||||||
drawJunctions(db, servicesElem, junctions);
|
drawJunctions(db, servicesElem, junctions);
|
||||||
|
|
||||||
const cy = await layoutArchitecture(services, junctions, groups, edges, ds);
|
const cy = await layoutArchitecture(services, junctions, groups, edges, db, ds);
|
||||||
|
|
||||||
await drawEdges(edgesElem, cy);
|
await drawEdges(edgesElem, cy);
|
||||||
await drawGroups(groupElem, cy);
|
await drawGroups(groupElem, cy);
|
||||||
|
@@ -7,6 +7,8 @@ import type cytoscape from 'cytoscape';
|
|||||||
| Architecture Diagram Types |
|
| Architecture Diagram Types |
|
||||||
\*=======================================*/
|
\*=======================================*/
|
||||||
|
|
||||||
|
export type ArchitectureAlignment = 'vertical' | 'horizontal' | 'bend';
|
||||||
|
|
||||||
export type ArchitectureDirection = 'L' | 'R' | 'T' | 'B';
|
export type ArchitectureDirection = 'L' | 'R' | 'T' | 'B';
|
||||||
export type ArchitectureDirectionX = Extract<ArchitectureDirection, 'L' | 'R'>;
|
export type ArchitectureDirectionX = Extract<ArchitectureDirection, 'L' | 'R'>;
|
||||||
export type ArchitectureDirectionY = Extract<ArchitectureDirection, 'T' | 'B'>;
|
export type ArchitectureDirectionY = Extract<ArchitectureDirection, 'T' | 'B'>;
|
||||||
@@ -170,6 +172,18 @@ export const getArchitectureDirectionXYFactors = function (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getArchitectureDirectionAlignment = function (
|
||||||
|
a: ArchitectureDirection,
|
||||||
|
b: ArchitectureDirection
|
||||||
|
): ArchitectureAlignment {
|
||||||
|
if (isArchitectureDirectionXY(a, b)) {
|
||||||
|
return 'bend';
|
||||||
|
} else if (isArchitectureDirectionX(a)) {
|
||||||
|
return 'horizontal';
|
||||||
|
}
|
||||||
|
return 'vertical';
|
||||||
|
};
|
||||||
|
|
||||||
export interface ArchitectureStyleOptions {
|
export interface ArchitectureStyleOptions {
|
||||||
archEdgeColor: string;
|
archEdgeColor: string;
|
||||||
archEdgeArrowColor: string;
|
archEdgeArrowColor: string;
|
||||||
@@ -249,9 +263,27 @@ export interface ArchitectureDB extends DiagramDB {
|
|||||||
|
|
||||||
export type ArchitectureAdjacencyList = Record<string, ArchitectureDirectionPairMap>;
|
export type ArchitectureAdjacencyList = Record<string, ArchitectureDirectionPairMap>;
|
||||||
export type ArchitectureSpatialMap = Record<string, number[]>;
|
export type ArchitectureSpatialMap = Record<string, number[]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps the direction that groups connect from.
|
||||||
|
*
|
||||||
|
* **Outer key**: ID of group A
|
||||||
|
*
|
||||||
|
* **Inner key**: ID of group B
|
||||||
|
*
|
||||||
|
* **Value**: 'vertical' or 'horizontal'
|
||||||
|
*
|
||||||
|
* Note: tmp[groupA][groupB] == tmp[groupB][groupA]
|
||||||
|
*/
|
||||||
|
export type ArchitectureGroupAlignments = Record<
|
||||||
|
string,
|
||||||
|
Record<string, Exclude<ArchitectureAlignment, 'bend'>>
|
||||||
|
>;
|
||||||
|
|
||||||
export interface ArchitectureDataStructures {
|
export interface ArchitectureDataStructures {
|
||||||
adjList: ArchitectureAdjacencyList;
|
adjList: ArchitectureAdjacencyList;
|
||||||
spatialMaps: ArchitectureSpatialMap[];
|
spatialMaps: ArchitectureSpatialMap[];
|
||||||
|
groupAlignments: ArchitectureGroupAlignments;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ArchitectureState extends Record<string, unknown> {
|
export interface ArchitectureState extends Record<string, unknown> {
|
||||||
|
@@ -896,6 +896,7 @@ const addNodeFromVertex = (
|
|||||||
const baseNode = {
|
const baseNode = {
|
||||||
id: vertex.id,
|
id: vertex.id,
|
||||||
label: vertex.text,
|
label: vertex.text,
|
||||||
|
labelType: vertex.labelType,
|
||||||
labelStyle: '',
|
labelStyle: '',
|
||||||
parentId,
|
parentId,
|
||||||
padding: config.flowchart?.padding || 8,
|
padding: config.flowchart?.padding || 8,
|
||||||
@@ -1002,6 +1003,7 @@ export const getData = () => {
|
|||||||
end: rawEdge.end,
|
end: rawEdge.end,
|
||||||
type: rawEdge.type ?? 'normal',
|
type: rawEdge.type ?? 'normal',
|
||||||
label: rawEdge.text,
|
label: rawEdge.text,
|
||||||
|
labelType: rawEdge.labelType,
|
||||||
labelpos: 'c',
|
labelpos: 'c',
|
||||||
thickness: rawEdge.stroke,
|
thickness: rawEdge.stroke,
|
||||||
minlen: rawEdge.length,
|
minlen: rawEdge.length,
|
||||||
|
@@ -390,7 +390,7 @@ mermaid.ganttConfig = {
|
|||||||
sectionFontSize: 24, // Font size for sections
|
sectionFontSize: 24, // Font size for sections
|
||||||
numberSectionStyles: 1, // The number of alternating section styles
|
numberSectionStyles: 1, // The number of alternating section styles
|
||||||
axisFormat: '%d/%m', // Date/time format of the axis
|
axisFormat: '%d/%m', // Date/time format of the axis
|
||||||
tickInterval: '1 week', // Axis ticks
|
tickInterval: '1week', // Axis ticks
|
||||||
topAxis: true, // When this flag is set, date labels will be added to the top of the chart
|
topAxis: true, // When this flag is set, date labels will be added to the top of the chart
|
||||||
displayMode: 'compact', // Turns compact mode on
|
displayMode: 'compact', // Turns compact mode on
|
||||||
weekday: 'sunday', // On which day a week-based interval should start
|
weekday: 'sunday', // On which day a week-based interval should start
|
||||||
|
@@ -64,7 +64,7 @@ todo[Todo]
|
|||||||
|
|
||||||
## Configuration Options
|
## Configuration Options
|
||||||
|
|
||||||
You can customize the Kanban diagram using a configuration block at the beginning of your markdown file. This is useful for setting global settings like a base URL for tickets. Currently there is one configuration option for kanban diagrams tacketBaseUrl. This can be set as in the the following example:
|
You can customize the Kanban diagram using a configuration block at the beginning of your markdown file. This is useful for setting global settings like a base URL for tickets. Currently there is one configuration option for kanban diagrams `ticketBaseUrl`. This can be set as in the the following example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
---
|
---
|
||||||
|
@@ -26,12 +26,16 @@ export const getLabelStyles = (styleArray) => {
|
|||||||
export const insertEdgeLabel = async (elem, edge) => {
|
export const insertEdgeLabel = async (elem, edge) => {
|
||||||
let useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels);
|
let useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels);
|
||||||
|
|
||||||
const labelElement = await createText(elem, edge.label, {
|
const labelElement =
|
||||||
|
edge.labelType === 'markdown'
|
||||||
|
? await createText(elem, edge.label, {
|
||||||
style: getLabelStyles(edge.labelStyle),
|
style: getLabelStyles(edge.labelStyle),
|
||||||
useHtmlLabels,
|
useHtmlLabels,
|
||||||
addSvgBackground: true,
|
addSvgBackground: true,
|
||||||
isNode: false,
|
isNode: false,
|
||||||
});
|
})
|
||||||
|
: await createLabel(edge.label, getLabelStyles(edge.labelStyle), undefined, false);
|
||||||
|
|
||||||
log.info('abc82', edge, edge.labelType);
|
log.info('abc82', edge, edge.labelType);
|
||||||
|
|
||||||
// Create outer g, edgeLabel, this will be positioned after graph layout
|
// Create outer g, edgeLabel, this will be positioned after graph layout
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import createLabel from '../createLabel.js';
|
||||||
import { createText } from '../../createText.js';
|
import { createText } from '../../createText.js';
|
||||||
import type { Node } from '../../types.js';
|
import type { Node } from '../../types.js';
|
||||||
import { getConfig } from '../../../diagram-api/diagramAPI.js';
|
import { getConfig } from '../../../diagram-api/diagramAPI.js';
|
||||||
@@ -40,7 +41,9 @@ export const labelHelper = async <T extends SVGGraphicsElement>(
|
|||||||
label = typeof node.label === 'string' ? node.label : node.label[0];
|
label = typeof node.label === 'string' ? node.label : node.label[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), {
|
let text;
|
||||||
|
if (node.labelType !== 'string') {
|
||||||
|
text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), {
|
||||||
useHtmlLabels,
|
useHtmlLabels,
|
||||||
width: node.width || getConfig().flowchart?.wrappingWidth,
|
width: node.width || getConfig().flowchart?.wrappingWidth,
|
||||||
// @ts-expect-error -- This is currently not used. Should this be `classes` instead?
|
// @ts-expect-error -- This is currently not used. Should this be `classes` instead?
|
||||||
@@ -48,6 +51,16 @@ export const labelHelper = async <T extends SVGGraphicsElement>(
|
|||||||
style: node.labelStyle,
|
style: node.labelStyle,
|
||||||
addSvgBackground: !!node.icon || !!node.img,
|
addSvgBackground: !!node.icon || !!node.img,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
const labelElement = await createLabel(
|
||||||
|
sanitizeText(decodeEntities(label), getConfig()),
|
||||||
|
node.labelStyle,
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
text = labelEl.node()?.appendChild(labelElement);
|
||||||
|
}
|
||||||
|
|
||||||
// Get the size of the label
|
// Get the size of the label
|
||||||
let bbox = text.getBBox();
|
let bbox = text.getBBox();
|
||||||
const halfPadding = (node?.padding ?? 0) / 2;
|
const halfPadding = (node?.padding ?? 0) / 2;
|
||||||
|
Reference in New Issue
Block a user