From 24257de8a631cd61604eb08015e32cf2fab4acc7 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 24 Jun 2025 14:50:20 +0530 Subject: [PATCH 1/5] fix state diagram edge label position --- .../rendering-util/rendering-elements/edges.js | 4 ++++ packages/mermaid/src/utils.ts | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index a97668d5f..154040d87 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -638,6 +638,10 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod addEdgeMarkers(svgPath, edge, url, id, diagramType, strokeColor); + if (!utils.isPointInDAttr(points, svgPath.attr('d'))) { + pointsHasChanged = true; + } + let paths = {}; if (pointsHasChanged) { paths.updatedPath = points; diff --git a/packages/mermaid/src/utils.ts b/packages/mermaid/src/utils.ts index 6ed935cf6..61157f827 100644 --- a/packages/mermaid/src/utils.ts +++ b/packages/mermaid/src/utils.ts @@ -884,6 +884,7 @@ export default { runFunc, entityDecode, insertTitle, + isPointInDAttr, parseFontSize, InitIDGenerator, }; @@ -960,3 +961,19 @@ export function handleUndefinedAttr( ) { return attrValue ?? null; } + +export function isPointInDAttr(points: Point[], dAttr: string) { + if (!points || points.length < 2 || !dAttr) { + return false; + } + + const point = points[1]; + const roundedX = Math.round(point.x); + const roundedY = Math.round(point.y); + + const sanitizedD = dAttr.replace(/(\d+\.\d+)/g, (match) => + Math.round(parseFloat(match)).toString() + ); + + return sanitizedD.includes(roundedX.toString()) || sanitizedD.includes(roundedY.toString()); +} From 33e08daf175125295a06b1b80279437004a4e865 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 24 Jun 2025 15:10:36 +0530 Subject: [PATCH 2/5] added changeset --- .changeset/cold-sites-accept.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/cold-sites-accept.md diff --git a/.changeset/cold-sites-accept.md b/.changeset/cold-sites-accept.md new file mode 100644 index 000000000..4166d40d4 --- /dev/null +++ b/.changeset/cold-sites-accept.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +edge label in the state diagram was not positioned correctly relative to the edge From 579c22cf5d94dc038206ad95d812f0f36c4b28b8 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Tue, 24 Jun 2025 17:08:42 +0530 Subject: [PATCH 3/5] refactor code --- .../rendering-util/rendering-elements/edges.js | 5 +++-- packages/mermaid/src/utils.ts | 18 +++++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index 154040d87..db48e313c 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -637,8 +637,9 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod log.info('arrowTypeEnd', edge.arrowTypeEnd); addEdgeMarkers(svgPath, edge, url, id, diagramType, strokeColor); - - if (!utils.isPointInDAttr(points, svgPath.attr('d'))) { + const midIndex = Math.floor(points.length / 2); + const point = points[midIndex]; + if (!utils.isLabelCoordinateInPath(point, svgPath.attr('d'))) { pointsHasChanged = true; } diff --git a/packages/mermaid/src/utils.ts b/packages/mermaid/src/utils.ts index 61157f827..0f1bfbecf 100644 --- a/packages/mermaid/src/utils.ts +++ b/packages/mermaid/src/utils.ts @@ -884,7 +884,7 @@ export default { runFunc, entityDecode, insertTitle, - isPointInDAttr, + isLabelCoordinateInPath, parseFontSize, InitIDGenerator, }; @@ -962,12 +962,16 @@ export function handleUndefinedAttr( return attrValue ?? null; } -export function isPointInDAttr(points: Point[], dAttr: string) { - if (!points || points.length < 2 || !dAttr) { - return false; - } - - const point = points[1]; +/** + * Checks if the x or y coordinate of the edge label + * appears in the given SVG path data string. + * + * @param point - The Point object with x and y properties to check. + * @param dAttr - SVG path data string (the 'd' attribute of an SVG path element). + * @returns - True if the rounded x or y coordinate of the edge label is found + * in the sanitized path data string; otherwise, false. + */ +export function isLabelCoordinateInPath(point: Point, dAttr: string) { const roundedX = Math.round(point.x); const roundedY = Math.round(point.y); From 4012cbf013a979bead300d29675b4ebfae07bdfd Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Mon, 30 Jun 2025 18:32:31 +0530 Subject: [PATCH 4/5] Update changeset Co-authored-by: Sidharth Vinod --- .changeset/cold-sites-accept.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/cold-sites-accept.md b/.changeset/cold-sites-accept.md index 4166d40d4..cba7ae414 100644 --- a/.changeset/cold-sites-accept.md +++ b/.changeset/cold-sites-accept.md @@ -2,4 +2,4 @@ 'mermaid': patch --- -edge label in the state diagram was not positioned correctly relative to the edge +fix: Position the edge label in state diagram correctly relative to the edge From 4254bdd4733a3b528c002f29fb583949c3f7be22 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Mon, 30 Jun 2025 20:15:32 +0530 Subject: [PATCH 5/5] added test cases for edge label positions --- .../rendering/stateDiagram-v2.spec.js | 225 ++++++++++++++++++ 1 file changed, 225 insertions(+) diff --git a/cypress/integration/rendering/stateDiagram-v2.spec.js b/cypress/integration/rendering/stateDiagram-v2.spec.js index 83190dbc7..e5a0cedd0 100644 --- a/cypress/integration/rendering/stateDiagram-v2.spec.js +++ b/cypress/integration/rendering/stateDiagram-v2.spec.js @@ -602,6 +602,231 @@ State1 --> [*] -- 55 } +`, + {} + ); + }); + it('should render edge labels correctly', () => { + imgSnapshotTest( + `--- +title: On The Way To Something Something DarkSide +config: + look: default + theme: default +--- + +stateDiagram-v2 + + state State1_____________ + { + c0 + } + + state State2_____________ + { + c1 + } + + state State3_____________ + { + c7 + } + + state State4_____________ + { + c2 + } + + state State5_____________ + { + c3 + } + + state State6_____________ + { + c4 + } + + state State7_____________ + { + c5 + } + + state State8_____________ + { + c6 + } + + +[*] --> State1_____________ +State1_____________ --> State2_____________ : Transition1_____ +State2_____________ --> State4_____________ : Transition2_____ +State2_____________ --> State3_____________ : Transition3_____ +State3_____________ --> State2_____________ +State4_____________ --> State2_____________ : Transition5_____ +State4_____________ --> State5_____________ : Transition6_____ +State5_____________ --> State6_____________ : Transition7_____ +State6_____________ --> State4_____________ : Transition8_____ +State2_____________ --> State7_____________ : Transition4_____ +State4_____________ --> State7_____________ : Transition4_____ +State5_____________ --> State7_____________ : Transition4_____ +State6_____________ --> State7_____________ : Transition4_____ +State7_____________ --> State1_____________ : Transition9_____ +State5_____________ --> State8_____________ : Transition10____ +State8_____________ --> State5_____________ : Transition11____ +`, + {} + ); + }); + it('should render edge labels correctly with multiple transitions', () => { + imgSnapshotTest( + `--- +title: Multiple Transitions +config: + look: default + theme: default +--- + +stateDiagram-v2 + + state State1_____________ + { + c0 + } + + state State2_____________ + { + c1 + } + + state State3_____________ + { + c7 + } + + state State4_____________ + { + c2 + } + + state State5_____________ + { + c3 + } + + state State6_____________ + { + c4 + } + + state State7_____________ + { + c5 + } + + state State8_____________ + { + c6 + } + + state State9_____________ + { + c9 + } + +[*] --> State1_____________ +State1_____________ --> State2_____________ : Transition1_____ +State2_____________ --> State4_____________ : Transition2_____ +State2_____________ --> State3_____________ : Transition3_____ +State3_____________ --> State2_____________ +State4_____________ --> State2_____________ : Transition5_____ +State4_____________ --> State5_____________ : Transition6_____ +State5_____________ --> State6_____________ : Transition7_____ +State6_____________ --> State4_____________ : Transition8_____ +State2_____________ --> State7_____________ : Transition4_____ +State4_____________ --> State7_____________ : Transition4_____ +State5_____________ --> State7_____________ : Transition4_____ +State6_____________ --> State7_____________ : Transition4_____ +State7_____________ --> State1_____________ : Transition9_____ +State5_____________ --> State8_____________ : Transition10____ +State8_____________ --> State5_____________ : Transition11____ +State9_____________ --> State8_____________ : Transition12____ +`, + {} + ); + }); + + it('should render edge labels correctly with multiple states', () => { + imgSnapshotTest( + `--- +title: Multiple States +config: + look: default + theme: default +--- + +stateDiagram-v2 + + state State1_____________ + { + c0 + } + + state State2_____________ + { + c1 + } + + state State3_____________ + { + c7 + } + + state State4_____________ + { + c2 + } + + state State5_____________ + { + c3 + } + + state State6_____________ + { + c4 + } + + state State7_____________ + { + c5 + } + + state State8_____________ + { + c6 + } + + state State9_____________ + { + c9 + } + + state State10_____________ + { + c10 + } + +[*] --> State1_____________ +State1_____________ --> State2_____________ : Transition1_____ +State2_____________ --> State3_____________ : Transition2_____ +State3_____________ --> State4_____________ : Transition3_____ +State4_____________ --> State5_____________ : Transition4_____ +State5_____________ --> State6_____________ : Transition5_____ +State6_____________ --> State7_____________ : Transition6_____ +State7_____________ --> State8_____________ : Transition7_____ +State8_____________ --> State9_____________ : Transition8_____ +State9_____________ --> State10_____________ : Transition9_____ `, {} );