UNPKG

mermaid

Version:

Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.

8 lines (7 loc) 34.9 kB
{ "version": 3, "sources": ["../../../src/rendering-util/layout-algorithms/dagre/index.js"], "sourcesContent": ["import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js';\nimport * as graphlibJson from 'dagre-d3-es/src/graphlib/json.js';\nimport * as graphlib from 'dagre-d3-es/src/graphlib/index.js';\nimport insertMarkers from '../../rendering-elements/markers.js';\nimport { updateNodeBounds } from '../../rendering-elements/shapes/util.js';\nimport {\n clear as clearGraphlib,\n clusterDb,\n adjustClustersAndEdges,\n findNonClusterChild,\n sortNodesByHierarchy,\n} from './mermaid-graphlib.js';\nimport {\n insertNode,\n positionNode,\n clear as clearNodes,\n setNodeElem,\n} from '../../rendering-elements/nodes.js';\nimport { insertCluster, clear as clearClusters } from '../../rendering-elements/clusters.js';\nimport {\n insertEdgeLabel,\n positionEdgeLabel,\n insertEdge,\n clear as clearEdges,\n} from '../../rendering-elements/edges.js';\nimport { log } from '../../../logger.js';\nimport { getSubGraphTitleMargins } from '../../../utils/subGraphTitleMargins.js';\nimport { getConfig } from '../../../diagram-api/diagramAPI.js';\n\nconst clamp = (value, min, max) => Math.max(min, Math.min(max, value));\n\nconst getDefaultSelfLoopSide = (rankdir = 'TB') => {\n switch (rankdir) {\n case 'BT':\n return 'bottom';\n case 'LR':\n return 'right';\n case 'RL':\n return 'left';\n case 'TB':\n default:\n return 'top';\n }\n};\n\n// Class diagrams also use dagre, but self-referential multiplicity labels rely on\n// the existing segmented self-loop rendering path for terminal label placement.\nconst shouldMergeSelfLoopSegments = (diagramType) =>\n diagramType === 'flowchart' || diagramType === 'flowchart-v2' || diagramType === 'stateDiagram';\n\n// Use dagre's dummy self-loop placement as a hint, so loops are not always forced above the node.\nconst getSelfLoopSide = (graph, node, segments, originalNodeId, rankdir) => {\n const layoutHints = [];\n const dummyNodeIds = new Set();\n\n segments.forEach(({ start, end }) => {\n if (start !== originalNodeId) {\n dummyNodeIds.add(start);\n }\n if (end !== originalNodeId) {\n dummyNodeIds.add(end);\n }\n });\n\n dummyNodeIds.forEach((id) => {\n const dummyNode = graph.node(id);\n if (typeof dummyNode?.x === 'number' && typeof dummyNode?.y === 'number') {\n layoutHints.push(dummyNode);\n }\n });\n\n if (layoutHints.length === 0) {\n segments.forEach(({ edge }) => {\n (edge.points ?? []).forEach((point) => {\n if (typeof point?.x === 'number' && typeof point?.y === 'number') {\n layoutHints.push(point);\n }\n });\n });\n }\n\n if (layoutHints.length === 0) {\n return getDefaultSelfLoopSide(rankdir);\n }\n\n const center = layoutHints.reduce(\n (acc, point) => ({\n x: acc.x + point.x / layoutHints.length,\n y: acc.y + point.y / layoutHints.length,\n }),\n { x: 0, y: 0 }\n );\n const dx = center.x - node.x;\n const dy = center.y - node.y;\n\n if (Math.abs(dx) > Math.abs(dy)) {\n return dx > 0 ? 'right' : 'left';\n }\n if (Math.abs(dy) > 0) {\n return dy > 0 ? 'bottom' : 'top';\n }\n return getDefaultSelfLoopSide(rankdir);\n};\n\n// Build a compact loop around the node instead of rendering dagre's long dummy-edge route.\nconst getSelfLoopPoints = (node, side = 'top', yOffset = 0, labelWidth = 0) => {\n const x = node.x;\n const y = node.y - yOffset;\n const halfWidth = node.width / 2;\n const halfHeight = node.height / 2;\n const maxSpan = Math.max(36, Math.min(100, node.width * 0.8));\n const span = clamp(Math.max(labelWidth, node.width * 0.35), 36, maxSpan);\n const depth = clamp(Math.min(node.width, node.height) * 0.45, 24, 48);\n\n switch (side) {\n case 'bottom': {\n const bottom = y + halfHeight;\n return [\n { x: x - span / 2, y: bottom },\n { x: x - span / 2, y: bottom + depth },\n { x: x + span / 2, y: bottom + depth },\n { x: x + span / 2, y: bottom },\n ];\n }\n case 'right': {\n const right = x + halfWidth;\n return [\n { x: right, y: y - span / 2 },\n { x: right + depth, y: y - span / 2 },\n { x: right + depth, y: y + span / 2 },\n { x: right, y: y + span / 2 },\n ];\n }\n case 'left': {\n const left = x - halfWidth;\n return [\n { x: left, y: y - span / 2 },\n { x: left - depth, y: y - span / 2 },\n { x: left - depth, y: y + span / 2 },\n { x: left, y: y + span / 2 },\n ];\n }\n case 'top':\n default: {\n const top = y - halfHeight;\n return [\n { x: x - span / 2, y: top },\n { x: x - span / 2, y: top - depth },\n { x: x + span / 2, y: top - depth },\n { x: x + span / 2, y: top },\n ];\n }\n }\n};\n\nconst getSelfLoopLabelPosition = (node, points, side = 'top', yOffset = 0, label = {}) => {\n const gap = 4;\n const x = node.x;\n const y = node.y - yOffset;\n const labelWidth = label.width ?? 0;\n const labelHeight = label.height ?? 0;\n\n switch (side) {\n case 'bottom':\n return { x, y: Math.max(...points.map((point) => point.y)) + labelHeight / 2 + gap };\n case 'right':\n return { x: Math.max(...points.map((point) => point.x)) + labelWidth / 2 + gap, y };\n case 'left':\n return { x: Math.min(...points.map((point) => point.x)) - labelWidth / 2 - gap, y };\n case 'top':\n default:\n return { x, y: Math.min(...points.map((point) => point.y)) - labelHeight / 2 - gap };\n }\n};\n\n// Convert internal dagre layout edges into the public SVG edges we actually render.\nexport const getEdgesToRender = (graph, yOffset = 0, { mergeSelfLoops = true } = {}) => {\n const selfLoopEdgeGroups = new Map();\n const edgesToRender = [];\n const rankdir = graph.graph()?.rankdir;\n\n graph.edges().forEach((e) => {\n const edge = graph.edge(e);\n if (mergeSelfLoops && edge.selfLoop) {\n const key = edge.selfLoop.id;\n if (!selfLoopEdgeGroups.has(key)) {\n selfLoopEdgeGroups.set(key, []);\n }\n selfLoopEdgeGroups.get(key).push({ edge, start: e.v, end: e.w });\n } else {\n edgesToRender.push({ edge, start: e.v, end: e.w });\n }\n });\n\n selfLoopEdgeGroups.forEach((segments) => {\n if (segments.length !== 3) {\n // Unexpected self-loop state: preserve the old rendering behavior rather than dropping edges.\n segments.forEach((segment) => edgesToRender.push(segment));\n return;\n }\n\n segments.sort((a, b) => a.edge.selfLoop.order - b.edge.selfLoop.order);\n const [firstSegment, middleSegment, lastSegment] = segments;\n const originalEdge =\n firstSegment.edge.originalEdge ??\n middleSegment.edge.originalEdge ??\n lastSegment.edge.originalEdge ??\n middleSegment.edge;\n const node = graph.node(originalEdge.start);\n if (!node) {\n segments.forEach((segment) => edgesToRender.push(segment));\n return;\n }\n const label = {\n width: middleSegment.edge.width,\n height: middleSegment.edge.height,\n };\n // Dagre uses the dummy route for layout; the SVG output should still be one logical edge.\n const side = getSelfLoopSide(graph, node, segments, originalEdge.start, rankdir);\n const points = getSelfLoopPoints(node, side, yOffset, label.width ?? 0);\n const labelPosition = getSelfLoopLabelPosition(node, points, side, yOffset, label);\n const mergedEdge = {\n ...middleSegment.edge,\n ...originalEdge,\n id: originalEdge.id,\n points,\n start: originalEdge.start,\n end: originalEdge.end,\n x: labelPosition.x,\n y: labelPosition.y,\n width: label.width,\n height: label.height,\n labelStyle: middleSegment.edge.labelStyle,\n fromCluster:\n firstSegment.edge.fromCluster ??\n middleSegment.edge.fromCluster ??\n lastSegment.edge.fromCluster,\n toCluster:\n firstSegment.edge.toCluster ?? middleSegment.edge.toCluster ?? lastSegment.edge.toCluster,\n };\n delete mergedEdge.selfLoop;\n delete mergedEdge.originalEdge;\n\n edgesToRender.push({ edge: mergedEdge, start: mergedEdge.start, end: mergedEdge.end });\n });\n\n return edgesToRender;\n};\n\nconst recursiveRender = async (_elem, graph, diagramType, id, parentCluster, siteConfig) => {\n log.warn('Graph in recursive render:XAX', graphlibJson.write(graph), parentCluster);\n const dir = graph.graph().rankdir;\n log.trace('Dir in recursive render - dir:', dir);\n\n const elem = _elem.insert('g').attr('class', 'root');\n if (!graph.nodes()) {\n log.info('No nodes found for', graph);\n } else {\n log.info('Recursive render XXX', graph.nodes());\n }\n if (graph.edges().length > 0) {\n log.info('Recursive edges', graph.edge(graph.edges()[0]));\n }\n const clusters = elem.insert('g').attr('class', 'clusters');\n const edgePaths = elem.insert('g').attr('class', 'edgePaths');\n const edgeLabels = elem.insert('g').attr('class', 'edgeLabels');\n const nodes = elem.insert('g').attr('class', 'nodes');\n const mergeSelfLoops = shouldMergeSelfLoopSegments(diagramType);\n\n // Insert nodes, this will insert them into the dom and each node will get a size. The size is updated\n // to the abstract node and is later used by dagre for the layout\n await Promise.all(\n graph.nodes().map(async function (v) {\n const node = graph.node(v);\n if (parentCluster !== undefined) {\n const data = JSON.parse(JSON.stringify(parentCluster.clusterData));\n // data.clusterPositioning = true;\n log.trace(\n 'Setting data for parent cluster XXX\\n Node.id = ',\n v,\n '\\n data=',\n data.height,\n '\\nParent cluster',\n parentCluster.height\n );\n graph.setNode(parentCluster.id, data);\n if (!graph.parent(v)) {\n log.trace('Setting parent', v, parentCluster.id);\n graph.setParent(v, parentCluster.id, data);\n }\n }\n log.info('(Insert) Node XXX' + v + ': ' + JSON.stringify(graph.node(v)));\n if (node?.clusterNode) {\n // const children = graph.children(v);\n log.info('Cluster identified XBX', v, node.width, graph.node(v));\n\n // `node.graph.setGraph` applies the graph configurations such as nodeSpacing to subgraphs as without this the default values would be used\n // We override only the `ranksep` and `nodesep` configurations to allow for setting subgraph spacing while avoiding overriding other properties\n const { ranksep, nodesep } = graph.graph();\n node.graph.setGraph({\n ...node.graph.graph(),\n ranksep: ranksep + 25,\n nodesep,\n });\n\n // \"o\" will contain the full cluster not just the children\n const o = await recursiveRender(\n nodes,\n node.graph,\n diagramType,\n id,\n graph.node(v),\n siteConfig\n );\n const newEl = o.elem;\n updateNodeBounds(node, newEl);\n // node.height = o.diff;\n node.diff = o.diff || 0;\n log.info(\n 'New compound node after recursive render XAX',\n v,\n 'width',\n // node,\n node.width,\n 'height',\n node.height\n // node.x,\n // node.y\n );\n setNodeElem(newEl, node);\n } else {\n if (graph.children(v).length > 0) {\n // This is a cluster but not to be rendered recursively\n // Render as before\n log.trace(\n 'Cluster - the non recursive path XBX',\n v,\n node.id,\n node,\n node.width,\n 'Graph:',\n graph\n );\n log.trace(findNonClusterChild(node.id, graph));\n clusterDb.set(node.id, { id: findNonClusterChild(node.id, graph), node });\n // insertCluster(clusters, graph.node(v));\n } else {\n log.trace('Node - the non recursive path XAX', v, nodes, graph.node(v), dir);\n await insertNode(nodes, graph.node(v), { config: siteConfig, dir });\n }\n }\n })\n );\n\n const processEdges = async () => {\n const edgePromises = graph.edges().map(async function (e) {\n const edge = graph.edge(e.v, e.w, e.name);\n log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e));\n log.info('Edge ' + e.v + ' -> ' + e.w + ': ', e, ' ', JSON.stringify(graph.edge(e)));\n\n // Check if link is either from or to a cluster\n log.info(\n 'Fix',\n clusterDb,\n 'ids:',\n e.v,\n e.w,\n 'Translating: ',\n clusterDb.get(e.v),\n clusterDb.get(e.w)\n );\n if (mergeSelfLoops && edge.selfLoop) {\n // Only the middle layout segment owns the label, using the original edge id for lookup.\n if (edge.selfLoop.order !== 1) {\n return;\n }\n const segmentId = edge.id;\n edge.id = edge.selfLoop.id;\n await insertEdgeLabel(edgeLabels, edge);\n edge.id = segmentId;\n return;\n }\n await insertEdgeLabel(edgeLabels, edge);\n });\n\n await Promise.all(edgePromises);\n };\n\n await processEdges();\n\n log.info('Graph before layout:', JSON.stringify(graphlibJson.write(graph)));\n\n log.info('############################################# XXX');\n log.info('### Layout ### XXX');\n log.info('############################################# XXX');\n\n dagreLayout(graph);\n\n log.info('Graph after layout:', JSON.stringify(graphlibJson.write(graph)));\n // Move the nodes to the correct place\n let diff = 0;\n let { subGraphTitleTotalMargin } = getSubGraphTitleMargins(siteConfig);\n await Promise.all(\n sortNodesByHierarchy(graph).map(async function (v) {\n const node = graph.node(v);\n log.info(\n 'Position XBX => ' + v + ': (' + node.x,\n ',' + node.y,\n ') width: ',\n node.width,\n ' height: ',\n node.height\n );\n if (node?.clusterNode) {\n // Adjust for padding when on root level\n node.y += subGraphTitleTotalMargin;\n\n log.info(\n 'A tainted cluster node XBX1',\n v,\n node.id,\n node.width,\n node.height,\n node.x,\n node.y,\n graph.parent(v)\n );\n clusterDb.get(node.id).node = node;\n positionNode(node);\n } else {\n // A tainted cluster node\n if (graph.children(v).length > 0) {\n log.info(\n 'A pure cluster node XBX1',\n v,\n node.id,\n node.x,\n node.y,\n node.width,\n node.height,\n graph.parent(v)\n );\n node.height += subGraphTitleTotalMargin;\n graph.node(node.parentId);\n const halfPadding = node?.padding / 2 || 0;\n const labelHeight = node?.labelBBox?.height || 0;\n const offsetY = labelHeight - halfPadding || 0;\n log.debug('OffsetY', offsetY, 'labelHeight', labelHeight, 'halfPadding', halfPadding);\n await insertCluster(clusters, node);\n\n // A cluster in the non-recursive way\n clusterDb.get(node.id).node = node;\n } else {\n // Regular node\n const parent = graph.node(node.parentId);\n node.y += subGraphTitleTotalMargin / 2;\n log.info(\n 'A regular node XBX1 - using the padding',\n node.id,\n 'parent',\n node.parentId,\n node.width,\n node.height,\n node.x,\n node.y,\n 'offsetY',\n node.offsetY,\n 'parent',\n parent,\n parent?.offsetY,\n node\n );\n\n positionNode(node);\n }\n }\n })\n );\n\n // Move the edge labels to the correct place after layout\n const edgeOffsetY = subGraphTitleTotalMargin / 2;\n const edgesToRender = getEdgesToRender(graph, edgeOffsetY, { mergeSelfLoops });\n\n edgesToRender.forEach(function ({ edge, start, end }) {\n log.info('Edge ' + start + ' -> ' + end + ': ' + JSON.stringify(edge), edge);\n\n edge.points.forEach((point) => (point.y += edgeOffsetY));\n const startNode = graph.node(start);\n const endNode = graph.node(end);\n const paths = insertEdge(edgePaths, edge, clusterDb, diagramType, startNode, endNode, id);\n positionEdgeLabel(edge, paths);\n });\n\n graph.nodes().forEach(function (v) {\n const n = graph.node(v);\n log.info(v, n.type, n.diff);\n if (n.isGroup) {\n diff = n.diff;\n }\n });\n log.warn('Returning from recursive render XAX', elem, diff);\n return { elem, diff };\n};\n\nexport const render = async (data4Layout, svg) => {\n const graph = new graphlib.Graph({\n multigraph: true,\n compound: true,\n })\n .setGraph({\n rankdir: data4Layout.direction,\n nodesep:\n data4Layout.config?.nodeSpacing ||\n data4Layout.config?.flowchart?.nodeSpacing ||\n data4Layout.nodeSpacing,\n ranksep:\n data4Layout.config?.rankSpacing ||\n data4Layout.config?.flowchart?.rankSpacing ||\n data4Layout.rankSpacing,\n marginx: 8,\n marginy: 8,\n })\n .setDefaultEdgeLabel(function () {\n return {};\n });\n const element = svg.select('g');\n insertMarkers(element, data4Layout.markers, data4Layout.type, data4Layout.diagramId);\n clearNodes();\n clearEdges();\n clearClusters();\n clearGraphlib();\n\n data4Layout.nodes.forEach((node) => {\n graph.setNode(node.id, { ...node });\n if (node.parentId) {\n graph.setParent(node.id, node.parentId);\n }\n });\n\n log.debug('Edges:', data4Layout.edges);\n data4Layout.edges.forEach((edge) => {\n if (edge.start === edge.end) {\n // Keep the dagre dummy-node workaround for layout, then merge these segments before rendering.\n const nodeId = edge.start;\n const specialId1 = nodeId + '---' + nodeId + '---1';\n const specialId2 = nodeId + '---' + nodeId + '---2';\n const node = graph.node(nodeId);\n graph.setNode(specialId1, {\n domId: specialId1,\n id: specialId1,\n parentId: node.parentId,\n labelStyle: '',\n label: '',\n padding: 0,\n shape: 'labelRect',\n // shape: 'rect',\n style: '',\n width: 10,\n height: 10,\n });\n graph.setParent(specialId1, node.parentId);\n graph.setNode(specialId2, {\n domId: specialId2,\n id: specialId2,\n parentId: node.parentId,\n labelStyle: '',\n padding: 0,\n // shape: 'rect',\n shape: 'labelRect',\n label: '',\n style: '',\n width: 10,\n height: 10,\n });\n graph.setParent(specialId2, node.parentId);\n\n const originalEdge = structuredClone(edge);\n const edge1 = structuredClone(edge);\n const edgeMid = structuredClone(edge);\n const edge2 = structuredClone(edge);\n // Preserve the original edge so the final SVG path uses the logical self-loop id and data.\n edge1.originalEdge = originalEdge;\n edge1.selfLoop = { id: originalEdge.id, order: 0 };\n edgeMid.originalEdge = originalEdge;\n edgeMid.selfLoop = { id: originalEdge.id, order: 1 };\n edge2.originalEdge = originalEdge;\n edge2.selfLoop = { id: originalEdge.id, order: 2 };\n edge1.label = '';\n edge1.arrowTypeEnd = 'none';\n edge1.endLabelLeft = '';\n edge1.endLabelRight = ''; // defensive\n edge1.startLabelLeft = ''; // defensive\n edge1.id = nodeId + '-cyclic-special-1';\n edgeMid.startLabelRight = '';\n edgeMid.startLabelLeft = ''; // defensive\n edgeMid.endLabelLeft = '';\n edgeMid.endLabelRight = ''; // defensive\n edgeMid.arrowTypeStart = 'none';\n edgeMid.arrowTypeEnd = 'none';\n edgeMid.id = nodeId + '-cyclic-special-mid';\n edge2.label = '';\n edge2.startLabelRight = '';\n edge2.startLabelLeft = ''; // defensive\n edge2.arrowTypeStart = 'none';\n if (node.isGroup) {\n edge1.fromCluster = nodeId;\n edge2.toCluster = nodeId;\n }\n edge2.id = nodeId + '-cyclic-special-2';\n edge2.arrowTypeStart = 'none';\n graph.setEdge(nodeId, specialId1, edge1, nodeId + '-cyclic-special-0');\n graph.setEdge(specialId1, specialId2, edgeMid, nodeId + '-cyclic-special-1');\n graph.setEdge(specialId2, nodeId, edge2, nodeId + '-cyclic-special-2');\n } else {\n graph.setEdge(edge.start, edge.end, { ...edge }, edge.id);\n }\n });\n\n log.warn('Graph at first:', JSON.stringify(graphlibJson.write(graph)));\n adjustClustersAndEdges(graph);\n log.warn('Graph after XAX:', JSON.stringify(graphlibJson.write(graph)));\n const siteConfig = getConfig();\n await recursiveRender(\n element,\n graph,\n data4Layout.type,\n data4Layout.diagramId,\n undefined,\n siteConfig\n );\n};\n"], "mappings": "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", "names": ["clamp", "__name", "value", "min", "max", "getDefaultSelfLoopSide", "rankdir", "shouldMergeSelfLoopSegments", "diagramType", "getSelfLoopSide", "graph", "node", "segments", "originalNodeId", "layoutHints", "dummyNodeIds", "start", "end", "id", "dummyNode", "edge", "point", "center", "acc", "dx", "dy", "getSelfLoopPoints", "side", "yOffset", "labelWidth", "x", "y", "halfWidth", "halfHeight", "maxSpan", "span", "depth", "bottom", "right", "left", "top", "getSelfLoopLabelPosition", "points", "label", "labelHeight", "getEdgesToRender", "mergeSelfLoops", "selfLoopEdgeGroups", "edgesToRender", "e", "key", "segment", "a", "b", "firstSegment", "middleSegment", "lastSegment", "originalEdge", "labelPosition", "mergedEdge", "recursiveRender", "_elem", "parentCluster", "siteConfig", "log", "write", "dir", "elem", "clusters", "edgePaths", "edgeLabels", "nodes", "v", "data", "ranksep", "nodesep", "o", "newEl", "updateNodeBounds", "setNodeElem", "findNonClusterChild", "clusterDb", "insertNode", "edgePromises", "segmentId", "insertEdgeLabel", "layout", "diff", "subGraphTitleTotalMargin", "getSubGraphTitleMargins", "sortNodesByHierarchy", "positionNode", "halfPadding", "offsetY", "insertCluster", "parent", "edgeOffsetY", "startNode", "endNode", "paths", "insertEdge", "positionEdgeLabel", "n", "render", "data4Layout", "svg", "Graph", "element", "markers_default", "clear", "nodeId", "specialId1", "specialId2", "edge1", "edgeMid", "edge2", "adjustClustersAndEdges", "getConfig"] }