mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-23 09:20:03 +02:00
feat(arch): extended parser to control how edges pass through groups
This commit is contained in:
@@ -128,6 +128,8 @@ const addEdge = function ({
|
||||
rhsDir,
|
||||
lhsInto,
|
||||
rhsInto,
|
||||
lhsGroup,
|
||||
rhsGroup,
|
||||
title,
|
||||
}: ArchitectureEdge) {
|
||||
if (!isArchitectureDirection(lhsDir)) {
|
||||
@@ -152,14 +154,29 @@ const addEdge = function ({
|
||||
);
|
||||
}
|
||||
|
||||
const lhsGroupId = state.records.services[lhsId].in
|
||||
const rhsGroupId = state.records.services[rhsId].in
|
||||
if (lhsGroup && lhsGroupId && rhsGroupId && lhsGroupId == rhsGroupId) {
|
||||
throw new Error(
|
||||
`The left-hand id [${lhsId}] is modified to traverse the group boundary, but the edge does not pass through two groups.`
|
||||
)
|
||||
}
|
||||
if (rhsGroup && lhsGroupId && rhsGroupId && lhsGroupId == rhsGroupId) {
|
||||
throw new Error(
|
||||
`The right-hand id [${rhsId}] is modified to traverse the group boundary, but the edge does not pass through two groups.`
|
||||
)
|
||||
}
|
||||
|
||||
const edge = {
|
||||
lhsId,
|
||||
lhsDir,
|
||||
lhsInto,
|
||||
lhsGroup,
|
||||
rhsId,
|
||||
rhsDir,
|
||||
title,
|
||||
lhsInto,
|
||||
rhsInto,
|
||||
rhsGroup,
|
||||
title,
|
||||
};
|
||||
|
||||
state.records.edges.push(edge);
|
||||
|
@@ -84,7 +84,7 @@ function addGroups(groups: ArchitectureGroup[], cy: cytoscape.Core) {
|
||||
|
||||
function addEdges(edges: ArchitectureEdge[], cy: cytoscape.Core) {
|
||||
edges.forEach((parsedEdge) => {
|
||||
const { lhsId, rhsId, lhsInto, rhsInto, lhsDir, rhsDir, title } = parsedEdge;
|
||||
const { lhsId, rhsId, lhsInto, lhsGroup, rhsInto, lhsDir, rhsDir, rhsGroup, title } = parsedEdge;
|
||||
const edgeType = isArchitectureDirectionXY(parsedEdge.lhsDir, parsedEdge.rhsDir)
|
||||
? 'segments'
|
||||
: 'straight';
|
||||
@@ -94,6 +94,7 @@ function addEdges(edges: ArchitectureEdge[], cy: cytoscape.Core) {
|
||||
source: lhsId,
|
||||
sourceDir: lhsDir,
|
||||
sourceArrow: lhsInto,
|
||||
sourceGroup: lhsGroup,
|
||||
sourceEndpoint:
|
||||
lhsDir === 'L'
|
||||
? '0 50%'
|
||||
@@ -105,6 +106,7 @@ function addEdges(edges: ArchitectureEdge[], cy: cytoscape.Core) {
|
||||
target: rhsId,
|
||||
targetDir: rhsDir,
|
||||
targetArrow: rhsInto,
|
||||
targetGroup: rhsGroup,
|
||||
targetEndpoint:
|
||||
rhsDir === 'L'
|
||||
? '0 50%'
|
||||
|
@@ -199,11 +199,13 @@ export interface ArchitectureGroup {
|
||||
export interface ArchitectureEdge {
|
||||
lhsId: string;
|
||||
lhsDir: ArchitectureDirection;
|
||||
title?: string;
|
||||
lhsInto?: boolean;
|
||||
lhsGroup?: boolean;
|
||||
rhsId: string;
|
||||
rhsDir: ArchitectureDirection;
|
||||
lhsInto?: boolean;
|
||||
rhsInto?: boolean;
|
||||
rhsGroup?: boolean;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export interface ArchitectureDB extends DiagramDB {
|
||||
@@ -246,9 +248,11 @@ export type EdgeSingularData = {
|
||||
source: string;
|
||||
sourceDir: ArchitectureDirection;
|
||||
sourceArrow?: boolean;
|
||||
sourceGroup?: boolean;
|
||||
target: string;
|
||||
targetDir: ArchitectureDirection;
|
||||
targetArrow?: boolean;
|
||||
targetGroup?: boolean;
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
@@ -274,23 +278,23 @@ export interface EdgeSingular extends cytoscape.EdgeSingular {
|
||||
|
||||
export type NodeSingularData =
|
||||
| {
|
||||
type: 'service';
|
||||
id: string;
|
||||
icon?: string;
|
||||
label?: string;
|
||||
parent?: string;
|
||||
width: number;
|
||||
height: number;
|
||||
[key: string]: any;
|
||||
}
|
||||
type: 'service';
|
||||
id: string;
|
||||
icon?: string;
|
||||
label?: string;
|
||||
parent?: string;
|
||||
width: number;
|
||||
height: number;
|
||||
[key: string]: any;
|
||||
}
|
||||
| {
|
||||
type: 'group';
|
||||
id: string;
|
||||
icon?: string;
|
||||
label?: string;
|
||||
parent?: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
type: 'group';
|
||||
id: string;
|
||||
icon?: string;
|
||||
label?: string;
|
||||
parent?: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
export const nodeData = (node: cytoscape.NodeSingular) => {
|
||||
return node.data() as NodeSingularData;
|
||||
|
@@ -22,17 +22,37 @@ import { getConfigField } from './architectureDb.js';
|
||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||
|
||||
export const drawEdges = function (edgesEl: D3Element, cy: cytoscape.Core) {
|
||||
const padding = getConfigField('padding');
|
||||
const iconSize = getConfigField('iconSize');
|
||||
const arrowSize = iconSize / 6;
|
||||
const halfArrowSize = arrowSize / 2;
|
||||
|
||||
cy.edges().map((edge, id) => {
|
||||
const { sourceDir, sourceArrow, targetDir, targetArrow, label } = edgeData(edge);
|
||||
const { x: startX, y: startY } = edge[0].sourceEndpoint();
|
||||
const { sourceDir, sourceArrow, sourceGroup, targetDir, targetArrow, targetGroup, label } = edgeData(edge);
|
||||
let { x: startX, y: startY } = edge[0].sourceEndpoint();
|
||||
const { x: midX, y: midY } = edge[0].midpoint();
|
||||
const { x: endX, y: endY } = edge[0].targetEndpoint();
|
||||
let { x: endX, y: endY } = edge[0].targetEndpoint();
|
||||
|
||||
const groupEdgeShift = padding + 4;
|
||||
// +18 comes from the service label height that extends the padding on the bottom side of each group
|
||||
if (sourceGroup) {
|
||||
if (isArchitectureDirectionX(sourceDir)) {
|
||||
sourceDir === 'L' ? startX -= groupEdgeShift : startX += groupEdgeShift;
|
||||
} else {
|
||||
sourceDir === 'T' ? startY -= groupEdgeShift : startY += (groupEdgeShift + 18);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetGroup) {
|
||||
if (isArchitectureDirectionX(targetDir)) {
|
||||
targetDir === 'L' ? endX -= groupEdgeShift : endX += groupEdgeShift;
|
||||
} else {
|
||||
targetDir === 'T' ? endY -= groupEdgeShift : endY += (groupEdgeShift + 18);
|
||||
}
|
||||
}
|
||||
|
||||
if (edge[0]._private.rscratch) {
|
||||
const bounds = edge[0]._private.rscratch;
|
||||
// const bounds = edge[0]._private.rscratch;
|
||||
|
||||
const g = edgesEl.insert('g');
|
||||
|
||||
@@ -42,11 +62,11 @@ export const drawEdges = function (edgesEl: D3Element, cy: cytoscape.Core) {
|
||||
|
||||
if (sourceArrow) {
|
||||
const xShift = isArchitectureDirectionX(sourceDir)
|
||||
? ArchitectureDirectionArrowShift[sourceDir](bounds.startX, arrowSize)
|
||||
: bounds.startX - halfArrowSize;
|
||||
? ArchitectureDirectionArrowShift[sourceDir](startX, arrowSize)
|
||||
: startX - halfArrowSize;
|
||||
const yShift = isArchitectureDirectionY(sourceDir)
|
||||
? ArchitectureDirectionArrowShift[sourceDir](bounds.startY, arrowSize)
|
||||
: bounds.startY - halfArrowSize;
|
||||
? ArchitectureDirectionArrowShift[sourceDir](startY, arrowSize)
|
||||
: startY - halfArrowSize;
|
||||
|
||||
g.insert('polygon')
|
||||
.attr('points', ArchitectureDirectionArrow[sourceDir](arrowSize))
|
||||
@@ -55,11 +75,11 @@ export const drawEdges = function (edgesEl: D3Element, cy: cytoscape.Core) {
|
||||
}
|
||||
if (targetArrow) {
|
||||
const xShift = isArchitectureDirectionX(targetDir)
|
||||
? ArchitectureDirectionArrowShift[targetDir](bounds.endX, arrowSize)
|
||||
: bounds.endX - halfArrowSize;
|
||||
? ArchitectureDirectionArrowShift[targetDir](endX, arrowSize)
|
||||
: endX - halfArrowSize;
|
||||
const yShift = isArchitectureDirectionY(targetDir)
|
||||
? ArchitectureDirectionArrowShift[targetDir](bounds.endY, arrowSize)
|
||||
: bounds.endY - halfArrowSize;
|
||||
? ArchitectureDirectionArrowShift[targetDir](endY, arrowSize)
|
||||
: endY - halfArrowSize;
|
||||
|
||||
g.insert('polygon')
|
||||
.attr('points', ArchitectureDirectionArrow[targetDir](arrowSize))
|
||||
@@ -165,10 +185,10 @@ export const drawGroups = function (groupsEl: D3Element, cy: cytoscape.Core) {
|
||||
bkgElem.attr(
|
||||
'transform',
|
||||
'translate(' +
|
||||
(shiftedX1 + halfIconSize + 1) +
|
||||
', ' +
|
||||
(shiftedY1 + halfIconSize + 1) +
|
||||
')'
|
||||
(shiftedX1 + halfIconSize + 1) +
|
||||
', ' +
|
||||
(shiftedY1 + halfIconSize + 1) +
|
||||
')'
|
||||
);
|
||||
shiftedX1 += groupIconSize;
|
||||
// TODO: test with more values
|
||||
@@ -196,10 +216,10 @@ export const drawGroups = function (groupsEl: D3Element, cy: cytoscape.Core) {
|
||||
textElem.attr(
|
||||
'transform',
|
||||
'translate(' +
|
||||
(shiftedX1 + halfIconSize + 4) +
|
||||
', ' +
|
||||
(shiftedY1 + halfIconSize + 2) +
|
||||
')'
|
||||
(shiftedX1 + halfIconSize + 4) +
|
||||
', ' +
|
||||
(shiftedY1 + halfIconSize + 2) +
|
||||
')'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@ Service:
|
||||
;
|
||||
|
||||
Edge:
|
||||
lhsId=ARCH_ID Arrow rhsId=ARCH_ID EOL
|
||||
lhsId=ARCH_ID lhsGroup?=ARROW_GROUP? Arrow rhsId=ARCH_ID rhsGroup?=ARROW_GROUP? EOL
|
||||
;
|
||||
|
||||
terminal ARROW_DIRECTION: 'L' | 'R' | 'T' | 'B';
|
||||
@@ -38,4 +38,5 @@ terminal ARCH_ID: /[\w]+/;
|
||||
terminal ARCH_TEXT_ICON: /\("[^"]+"\)/;
|
||||
terminal ARCH_ICON: /\([\w]+\)/;
|
||||
terminal ARCH_TITLE: /\[[\w ]+\]/;
|
||||
terminal ARROW_GROUP: /\{group\}/;
|
||||
terminal ARROW_INTO: /\(|\)/;
|
Reference in New Issue
Block a user