mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-31 06:06:44 +02:00
Merge develop
into release/11.5.0
This commit is contained in:
5
.changeset/vast-nails-stay.md
Normal file
5
.changeset/vast-nails-stay.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'mermaid': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
The arrowhead color should match the color of the edge. Creates a unique clone of the arrow marker with the appropriate color.
|
@@ -917,4 +917,21 @@ graph TD
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it('#6369: edge color should affect arrow head', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
flowchart LR
|
||||||
|
A --> B
|
||||||
|
A --> C
|
||||||
|
C --> D
|
||||||
|
|
||||||
|
linkStyle 0 stroke:#D50000
|
||||||
|
linkStyle 2 stroke:#D50000
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
flowchart: { htmlLabels: true },
|
||||||
|
securityLevel: 'loose',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -15,32 +15,33 @@ export const addEdgeMarkers = (
|
|||||||
edge: Pick<EdgeData, 'arrowTypeStart' | 'arrowTypeEnd'>,
|
edge: Pick<EdgeData, 'arrowTypeStart' | 'arrowTypeEnd'>,
|
||||||
url: string,
|
url: string,
|
||||||
id: string,
|
id: string,
|
||||||
diagramType: string
|
diagramType: string,
|
||||||
|
strokeColor?: string
|
||||||
) => {
|
) => {
|
||||||
if (edge.arrowTypeStart) {
|
if (edge.arrowTypeStart) {
|
||||||
addEdgeMarker(svgPath, 'start', edge.arrowTypeStart, url, id, diagramType);
|
addEdgeMarker(svgPath, 'start', edge.arrowTypeStart, url, id, diagramType, strokeColor);
|
||||||
}
|
}
|
||||||
if (edge.arrowTypeEnd) {
|
if (edge.arrowTypeEnd) {
|
||||||
addEdgeMarker(svgPath, 'end', edge.arrowTypeEnd, url, id, diagramType);
|
addEdgeMarker(svgPath, 'end', edge.arrowTypeEnd, url, id, diagramType, strokeColor);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const arrowTypesMap = {
|
const arrowTypesMap = {
|
||||||
arrow_cross: 'cross',
|
arrow_cross: { type: 'cross', fill: false },
|
||||||
arrow_point: 'point',
|
arrow_point: { type: 'point', fill: true },
|
||||||
arrow_barb: 'barb',
|
arrow_barb: { type: 'barb', fill: true },
|
||||||
arrow_circle: 'circle',
|
arrow_circle: { type: 'circle', fill: false },
|
||||||
aggregation: 'aggregation',
|
aggregation: { type: 'aggregation', fill: false },
|
||||||
extension: 'extension',
|
extension: { type: 'extension', fill: false },
|
||||||
composition: 'composition',
|
composition: { type: 'composition', fill: true },
|
||||||
dependency: 'dependency',
|
dependency: { type: 'dependency', fill: true },
|
||||||
lollipop: 'lollipop',
|
lollipop: { type: 'lollipop', fill: false },
|
||||||
only_one: 'onlyOne',
|
only_one: { type: 'onlyOne', fill: false },
|
||||||
zero_or_one: 'zeroOrOne',
|
zero_or_one: { type: 'zeroOrOne', fill: false },
|
||||||
one_or_more: 'oneOrMore',
|
one_or_more: { type: 'oneOrMore', fill: false },
|
||||||
zero_or_more: 'zeroOrMore',
|
zero_or_more: { type: 'zeroOrMore', fill: false },
|
||||||
requirement_arrow: 'requirement_arrow',
|
requirement_arrow: { type: 'requirement_arrow', fill: false },
|
||||||
requirement_contains: 'requirement_contains',
|
requirement_contains: { type: 'requirement_contains', fill: false },
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const addEdgeMarker = (
|
const addEdgeMarker = (
|
||||||
@@ -49,15 +50,55 @@ const addEdgeMarker = (
|
|||||||
arrowType: string,
|
arrowType: string,
|
||||||
url: string,
|
url: string,
|
||||||
id: string,
|
id: string,
|
||||||
diagramType: string
|
diagramType: string,
|
||||||
|
strokeColor?: string
|
||||||
) => {
|
) => {
|
||||||
const endMarkerType = arrowTypesMap[arrowType as keyof typeof arrowTypesMap];
|
const arrowTypeInfo = arrowTypesMap[arrowType as keyof typeof arrowTypesMap];
|
||||||
|
|
||||||
if (!endMarkerType) {
|
if (!arrowTypeInfo) {
|
||||||
log.warn(`Unknown arrow type: ${arrowType}`);
|
log.warn(`Unknown arrow type: ${arrowType}`);
|
||||||
return; // unknown arrow type, ignore
|
return; // unknown arrow type, ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const endMarkerType = arrowTypeInfo.type;
|
||||||
const suffix = position === 'start' ? 'Start' : 'End';
|
const suffix = position === 'start' ? 'Start' : 'End';
|
||||||
svgPath.attr(`marker-${position}`, `url(${url}#${id}_${diagramType}-${endMarkerType}${suffix})`);
|
const originalMarkerId = `${id}_${diagramType}-${endMarkerType}${suffix}`;
|
||||||
|
|
||||||
|
// If stroke color is specified and non-empty, create or use a colored variant of the marker
|
||||||
|
if (strokeColor && strokeColor.trim() !== '') {
|
||||||
|
// Create a sanitized color value for use in IDs
|
||||||
|
const colorId = strokeColor.replace(/[^\dA-Za-z]/g, '_');
|
||||||
|
const coloredMarkerId = `${originalMarkerId}_${colorId}`;
|
||||||
|
|
||||||
|
// Check if the colored marker already exists
|
||||||
|
if (!document.getElementById(coloredMarkerId)) {
|
||||||
|
// Get the original marker
|
||||||
|
const originalMarker = document.getElementById(originalMarkerId);
|
||||||
|
if (originalMarker) {
|
||||||
|
// Clone the marker and create colored version
|
||||||
|
const coloredMarker = originalMarker.cloneNode(true) as Element;
|
||||||
|
coloredMarker.id = coloredMarkerId;
|
||||||
|
|
||||||
|
// Apply colors to the paths inside the marker
|
||||||
|
const paths = coloredMarker.querySelectorAll('path, circle, line');
|
||||||
|
paths.forEach((path) => {
|
||||||
|
path.setAttribute('stroke', strokeColor);
|
||||||
|
|
||||||
|
// Apply fill only to markers that should be filled
|
||||||
|
if (arrowTypeInfo.fill) {
|
||||||
|
path.setAttribute('fill', strokeColor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add the new colored marker to the defs section
|
||||||
|
originalMarker.parentNode?.appendChild(coloredMarker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the colored marker
|
||||||
|
svgPath.attr(`marker-${position}`, `url(${url}#${coloredMarkerId})`);
|
||||||
|
} else {
|
||||||
|
// Always use the original marker for unstyled edges
|
||||||
|
svgPath.attr(`marker-${position}`, `url(${url}#${originalMarkerId})`);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@@ -521,6 +521,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
|||||||
let svgPath;
|
let svgPath;
|
||||||
let linePath = lineFunction(lineData);
|
let linePath = lineFunction(lineData);
|
||||||
const edgeStyles = Array.isArray(edge.style) ? edge.style : [edge.style];
|
const edgeStyles = Array.isArray(edge.style) ? edge.style : [edge.style];
|
||||||
|
let strokeColor = edgeStyles.find((style) => style.startsWith('stroke:'));
|
||||||
|
|
||||||
if (edge.look === 'handDrawn') {
|
if (edge.look === 'handDrawn') {
|
||||||
const rc = rough.svg(elem);
|
const rc = rough.svg(elem);
|
||||||
@@ -551,18 +552,18 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
|||||||
if (edge.animation) {
|
if (edge.animation) {
|
||||||
animationClass = ' edge-animation-' + edge.animation;
|
animationClass = ' edge-animation-' + edge.animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const pathStyle = stylesFromClasses ? stylesFromClasses + ';' + styles + ';' : styles;
|
||||||
svgPath = elem
|
svgPath = elem
|
||||||
.append('path')
|
.append('path')
|
||||||
.attr('d', linePath)
|
.attr('d', linePath)
|
||||||
.attr('id', edge.id)
|
.attr('id', edge.id)
|
||||||
.attr(
|
.attr(
|
||||||
'class',
|
'class',
|
||||||
' ' +
|
' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : '') + (animationClass ?? '')
|
||||||
strokeClasses +
|
|
||||||
(edge.classes ? ' ' + edge.classes : '') +
|
|
||||||
(animationClass ? animationClass : '')
|
|
||||||
)
|
)
|
||||||
.attr('style', stylesFromClasses ? stylesFromClasses + ';' + styles + ';' : styles);
|
.attr('style', pathStyle);
|
||||||
|
strokeColor = pathStyle.match(/stroke:([^;]+)/)?.[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEBUG code, DO NOT REMOVE
|
// DEBUG code, DO NOT REMOVE
|
||||||
@@ -599,7 +600,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
|||||||
log.info('arrowTypeStart', edge.arrowTypeStart);
|
log.info('arrowTypeStart', edge.arrowTypeStart);
|
||||||
log.info('arrowTypeEnd', edge.arrowTypeEnd);
|
log.info('arrowTypeEnd', edge.arrowTypeEnd);
|
||||||
|
|
||||||
addEdgeMarkers(svgPath, edge, url, id, diagramType);
|
addEdgeMarkers(svgPath, edge, url, id, diagramType, strokeColor);
|
||||||
|
|
||||||
let paths = {};
|
let paths = {};
|
||||||
if (pointsHasChanged) {
|
if (pointsHasChanged) {
|
||||||
|
Reference in New Issue
Block a user