From 2ee7ef09c43d0b543b80842adcdaf9dd4162dd08 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Fri, 10 Oct 2025 18:41:21 +0530 Subject: [PATCH] fix: note position in state diagram on-behalf-of: @Mermaid-Chart --- .../layout-algorithms/dagre/index.js | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js index e9f0266e2..e5bf77b56 100644 --- a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js +++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js @@ -27,6 +27,53 @@ import { log } from '../../../logger.js'; import { getSubGraphTitleMargins } from '../../../utils/subGraphTitleMargins.js'; import { getConfig } from '../../../diagram-api/diagramAPI.js'; +/** + * Apply absolute note positioning after dagre layout + * This fixes the issue where TB and LR directions position notes differently + * by making note positioning truly absolute + */ +const positionNotes = (graph) => { + const noteStatePairs = []; + + graph.nodes().forEach((nodeId) => { + const node = graph.node(nodeId); + if (node.position && node.shape === 'note') { + const edges = graph.nodeEdges(nodeId); + + for (const edge of edges) { + const otherNodeId = edge.v === nodeId ? edge.w : edge.v; + const otherNode = graph.node(otherNodeId); + + if (otherNode && otherNode.shape !== 'note' && otherNode.shape !== 'noteGroup') { + noteStatePairs.push({ + noteId: nodeId, + noteNode: node, + stateId: otherNodeId, + stateNode: otherNode, + position: node.position, + }); + } + } + } + }); + + noteStatePairs.forEach(({ noteNode, stateNode, position }) => { + const spacing = 60; + + let noteX = noteNode.x; + let noteY = stateNode.y; + + if (position === 'right of') { + noteX = stateNode.x + stateNode.width / 2 + spacing + noteNode.width / 2; + } else if (position === 'left of') { + noteX = stateNode.x - stateNode.width / 2 - spacing - noteNode.width / 2; + } + + noteNode.x = noteX; + noteNode.y = noteY; + }); +}; + const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, siteConfig) => { log.warn('Graph in recursive render:XAX', graphlibJson.write(graph), parentCluster); const dir = graph.graph().rankdir; @@ -164,6 +211,9 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit dagreLayout(graph); + // Apply absolute note positioning after dagre layout + positionNotes(graph); + log.info('Graph after layout:', JSON.stringify(graphlibJson.write(graph))); // Move the nodes to the correct place let diff = 0;