mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-20 07:49:43 +02:00
refactor: Unify the edgeMarker adding logic
This commit is contained in:
67
packages/mermaid/src/dagre-wrapper/edgeMarker.spec.ts
Normal file
67
packages/mermaid/src/dagre-wrapper/edgeMarker.spec.ts
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import type { SVG } from '../diagram-api/types.js';
|
||||||
|
import { addEdgeMarkers } from './edgeMarker.js';
|
||||||
|
|
||||||
|
describe('addEdgeMarker', () => {
|
||||||
|
const svgPath = {
|
||||||
|
attr: vitest.fn(),
|
||||||
|
} as unknown as SVG;
|
||||||
|
const url = 'http://example.com';
|
||||||
|
const id = 'test';
|
||||||
|
const diagramType = 'test';
|
||||||
|
|
||||||
|
it('should add markers for arrow_cross:arrow_point', () => {
|
||||||
|
const arrowTypeStart = 'arrow_cross';
|
||||||
|
const arrowTypeEnd = 'arrow_point';
|
||||||
|
addEdgeMarkers(svgPath, { arrowTypeStart, arrowTypeEnd }, url, id, diagramType);
|
||||||
|
expect(svgPath.attr).toHaveBeenCalledWith(
|
||||||
|
'marker-start',
|
||||||
|
`url(${url}#${id}_${diagramType}-crossStart)`
|
||||||
|
);
|
||||||
|
expect(svgPath.attr).toHaveBeenCalledWith(
|
||||||
|
'marker-end',
|
||||||
|
`url(${url}#${id}_${diagramType}-pointEnd)`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add markers for aggregation:arrow_point', () => {
|
||||||
|
const arrowTypeStart = 'aggregation';
|
||||||
|
const arrowTypeEnd = 'arrow_point';
|
||||||
|
addEdgeMarkers(svgPath, { arrowTypeStart, arrowTypeEnd }, url, id, diagramType);
|
||||||
|
expect(svgPath.attr).toHaveBeenCalledWith(
|
||||||
|
'marker-start',
|
||||||
|
`url(${url}#${id}_${diagramType}-aggregationStart)`
|
||||||
|
);
|
||||||
|
expect(svgPath.attr).toHaveBeenCalledWith(
|
||||||
|
'marker-end',
|
||||||
|
`url(${url}#${id}_${diagramType}-pointEnd)`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add markers for arrow_point:aggregation', () => {
|
||||||
|
const arrowTypeStart = 'arrow_point';
|
||||||
|
const arrowTypeEnd = 'aggregation';
|
||||||
|
addEdgeMarkers(svgPath, { arrowTypeStart, arrowTypeEnd }, url, id, diagramType);
|
||||||
|
expect(svgPath.attr).toHaveBeenCalledWith(
|
||||||
|
'marker-start',
|
||||||
|
`url(${url}#${id}_${diagramType}-pointStart)`
|
||||||
|
);
|
||||||
|
expect(svgPath.attr).toHaveBeenCalledWith(
|
||||||
|
'marker-end',
|
||||||
|
`url(${url}#${id}_${diagramType}-aggregationEnd)`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add markers for aggregation:composition', () => {
|
||||||
|
const arrowTypeStart = 'aggregation';
|
||||||
|
const arrowTypeEnd = 'composition';
|
||||||
|
addEdgeMarkers(svgPath, { arrowTypeStart, arrowTypeEnd }, url, id, diagramType);
|
||||||
|
expect(svgPath.attr).toHaveBeenCalledWith(
|
||||||
|
'marker-start',
|
||||||
|
`url(${url}#${id}_${diagramType}-aggregationStart)`
|
||||||
|
);
|
||||||
|
expect(svgPath.attr).toHaveBeenCalledWith(
|
||||||
|
'marker-end',
|
||||||
|
`url(${url}#${id}_${diagramType}-compositionEnd)`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
41
packages/mermaid/src/dagre-wrapper/edgeMarker.ts
Normal file
41
packages/mermaid/src/dagre-wrapper/edgeMarker.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import type { SVG } from '../diagram-api/types.js';
|
||||||
|
import type { EdgeData } from '../types.js';
|
||||||
|
/**
|
||||||
|
* Adds SVG markers to a path element based on the arrow types specified in the edge.
|
||||||
|
*
|
||||||
|
* @param svgPath - The SVG path element to add markers to.
|
||||||
|
* @param edge - The edge data object containing the arrow types.
|
||||||
|
* @param url - The URL of the SVG marker definitions.
|
||||||
|
* @param id - The ID prefix for the SVG marker definitions.
|
||||||
|
* @param diagramType - The type of diagram being rendered.
|
||||||
|
*/
|
||||||
|
export const addEdgeMarkers = (
|
||||||
|
svgPath: SVG,
|
||||||
|
edge: Pick<EdgeData, 'arrowTypeStart' | 'arrowTypeEnd'>,
|
||||||
|
url: string,
|
||||||
|
id: string,
|
||||||
|
diagramType: string
|
||||||
|
) => {
|
||||||
|
if (edge.arrowTypeStart) {
|
||||||
|
addEdgeMarker(svgPath, 'start', edge.arrowTypeStart, url, id, diagramType);
|
||||||
|
}
|
||||||
|
if (edge.arrowTypeEnd) {
|
||||||
|
addEdgeMarker(svgPath, 'end', edge.arrowTypeEnd, url, id, diagramType);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addEdgeMarker = (
|
||||||
|
svgPath: SVG,
|
||||||
|
position: 'start' | 'end',
|
||||||
|
arrowType: string,
|
||||||
|
url: string,
|
||||||
|
id: string,
|
||||||
|
diagramType: string
|
||||||
|
) => {
|
||||||
|
if (arrowType.startsWith('arrow_')) {
|
||||||
|
arrowType = arrowType.replace('arrow_', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
const suffix = position === 'start' ? 'Start' : 'End';
|
||||||
|
svgPath.attr(`marker-${position}`, `url(${url}#${id}_${diagramType}-${arrowType}${suffix})`);
|
||||||
|
};
|
@@ -6,6 +6,7 @@ import { getConfig } from '../config.js';
|
|||||||
import utils from '../utils.js';
|
import utils from '../utils.js';
|
||||||
import { evaluate } from '../diagrams/common/common.js';
|
import { evaluate } from '../diagrams/common/common.js';
|
||||||
import { getLineFunctionsWithOffset } from '../utils/lineWithOffset.js';
|
import { getLineFunctionsWithOffset } from '../utils/lineWithOffset.js';
|
||||||
|
import { addEdgeMarker } from './edgeMarker.js';
|
||||||
|
|
||||||
let edgeLabels = {};
|
let edgeLabels = {};
|
||||||
let terminalLabels = {};
|
let terminalLabels = {};
|
||||||
@@ -506,108 +507,9 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
|
|||||||
log.info('arrowTypeStart', edge.arrowTypeStart);
|
log.info('arrowTypeStart', edge.arrowTypeStart);
|
||||||
log.info('arrowTypeEnd', edge.arrowTypeEnd);
|
log.info('arrowTypeEnd', edge.arrowTypeEnd);
|
||||||
|
|
||||||
switch (edge.arrowTypeStart) {
|
addEdgeMarker(svgPath, 'start', edge.arrowTypeStart, url, id, diagramType);
|
||||||
case 'arrow_cross':
|
addEdgeMarker(svgPath, 'end', edge.arrowTypeEnd, url, id, diagramType);
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-crossStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'arrow_point':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-pointStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'arrow_barb':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-barbStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'arrow_circle':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-circleStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'aggregation':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-aggregationStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'extension':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-extensionStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'composition':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-compositionStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'dependency':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-dependencyStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'lollipop':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-lollipopStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
switch (edge.arrowTypeEnd) {
|
|
||||||
case 'arrow_cross':
|
|
||||||
svgPath.attr('marker-end', 'url(' + url + '#' + id + '_' + diagramType + '-crossEnd' + ')');
|
|
||||||
break;
|
|
||||||
case 'arrow_point':
|
|
||||||
svgPath.attr('marker-end', 'url(' + url + '#' + id + '_' + diagramType + '-pointEnd' + ')');
|
|
||||||
break;
|
|
||||||
case 'arrow_barb':
|
|
||||||
svgPath.attr('marker-end', 'url(' + url + '#' + id + '_' + diagramType + '-barbEnd' + ')');
|
|
||||||
break;
|
|
||||||
case 'arrow_circle':
|
|
||||||
svgPath.attr('marker-end', 'url(' + url + '#' + id + '_' + diagramType + '-circleEnd' + ')');
|
|
||||||
break;
|
|
||||||
case 'aggregation':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-end',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-aggregationEnd' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'extension':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-end',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-extensionEnd' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'composition':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-end',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-compositionEnd' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'dependency':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-end',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-dependencyEnd' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'lollipop':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-end',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-lollipopEnd' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
let paths = {};
|
let paths = {};
|
||||||
if (pointsHasChanged) {
|
if (pointsHasChanged) {
|
||||||
paths.updatedPath = points;
|
paths.updatedPath = points;
|
||||||
|
@@ -11,6 +11,7 @@ import common from '../../common/common.js';
|
|||||||
import { interpolateToCurve, getStylesFromArray } from '../../../utils.js';
|
import { interpolateToCurve, getStylesFromArray } from '../../../utils.js';
|
||||||
import ELK from 'elkjs/lib/elk.bundled.js';
|
import ELK from 'elkjs/lib/elk.bundled.js';
|
||||||
import { getLineFunctionsWithOffset } from '../../../utils/lineWithOffset.js';
|
import { getLineFunctionsWithOffset } from '../../../utils/lineWithOffset.js';
|
||||||
|
import { addEdgeMarker } from '../../../dagre-wrapper/edgeMarker.js';
|
||||||
|
|
||||||
const elk = new ELK();
|
const elk = new ELK();
|
||||||
|
|
||||||
@@ -586,108 +587,8 @@ const addMarkersToEdge = function (svgPath, edgeData, diagramType, arrowMarkerAb
|
|||||||
}
|
}
|
||||||
|
|
||||||
// look in edge data and decide which marker to use
|
// look in edge data and decide which marker to use
|
||||||
switch (edgeData.arrowTypeStart) {
|
addEdgeMarker(svgPath, 'start', edgeData.arrowTypeStart, url, id, diagramType);
|
||||||
case 'arrow_cross':
|
addEdgeMarker(svgPath, 'end', edgeData.arrowTypeEnd, url, id, diagramType);
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-crossStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'arrow_point':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-pointStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'arrow_barb':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-barbStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'arrow_circle':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-circleStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'aggregation':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-aggregationStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'extension':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-extensionStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'composition':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-compositionStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'dependency':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-dependencyStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'lollipop':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-start',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-lollipopStart' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
switch (edgeData.arrowTypeEnd) {
|
|
||||||
case 'arrow_cross':
|
|
||||||
svgPath.attr('marker-end', 'url(' + url + '#' + id + '_' + diagramType + '-crossEnd' + ')');
|
|
||||||
break;
|
|
||||||
case 'arrow_point':
|
|
||||||
svgPath.attr('marker-end', 'url(' + url + '#' + id + '_' + diagramType + '-pointEnd' + ')');
|
|
||||||
break;
|
|
||||||
case 'arrow_barb':
|
|
||||||
svgPath.attr('marker-end', 'url(' + url + '#' + id + '_' + diagramType + '-barbEnd' + ')');
|
|
||||||
break;
|
|
||||||
case 'arrow_circle':
|
|
||||||
svgPath.attr('marker-end', 'url(' + url + '#' + id + '_' + diagramType + '-circleEnd' + ')');
|
|
||||||
break;
|
|
||||||
case 'aggregation':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-end',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-aggregationEnd' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'extension':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-end',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-extensionEnd' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'composition':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-end',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-compositionEnd' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'dependency':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-end',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-dependencyEnd' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'lollipop':
|
|
||||||
svgPath.attr(
|
|
||||||
'marker-end',
|
|
||||||
'url(' + url + '#' + id + '_' + diagramType + '-lollipopEnd' + ')'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user