UNPKG

mermaid

Version:

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

8 lines 50.4 kB
{
  "version": 3,
  "sources": ["../../../src/rendering-util/createGraph.ts", "../../../src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js", "../../../src/rendering-util/layout-algorithms/common/index.ts"],
  "sourcesContent": ["import type { Selection } from 'd3';\nimport * as graphlib from 'dagre-d3-es/src/graphlib/index.js';\nimport type { ClusterNode, LayoutData, NonClusterNode, ShapeRenderOptions } from './types.js';\nimport { getConfig } from '../diagram-api/diagramAPI.js';\nimport { hasEdgeLabel, insertEdgeLabel } from './rendering-elements/edges.js';\nimport { insertNode } from './rendering-elements/nodes.js';\nimport { labelHelper } from './rendering-elements/shapes/util.js';\n\n// Update type:\ntype D3Selection<T extends SVGElement = SVGElement> = Selection<\n  T,\n  unknown,\n  Element | null,\n  unknown\n>;\n\ninterface LayoutElementGroups {\n  clusters: D3Selection<SVGGElement>;\n  edgePaths: D3Selection<SVGGElement>;\n  edgeLabels: D3Selection<SVGGElement>;\n  nodes: D3Selection<SVGGElement>;\n  rootGroups: D3Selection<SVGGElement>;\n}\n\nexport interface CreateLayoutElementGroupsOptions {\n  edgePathsClass?: string;\n}\n\nexport function createLayoutElementGroups(\n  element: D3Selection,\n  { edgePathsClass = 'edges edgePath' }: CreateLayoutElementGroupsOptions = {}\n): LayoutElementGroups {\n  const rootGroups = element.insert('g').attr('class', 'root');\n  const clusters = rootGroups.insert('g').attr('class', 'clusters');\n  const edgePaths = rootGroups.insert('g').attr('class', edgePathsClass);\n  const edgeLabels = rootGroups.insert('g').attr('class', 'edgeLabels');\n  const nodes = rootGroups.insert('g').attr('class', 'nodes');\n\n  return { clusters, edgePaths, edgeLabels, nodes, rootGroups };\n}\n\nexport async function measureGroupLabel(\n  nodesGroup: D3Selection<SVGGElement>,\n  node: ClusterNode\n): Promise<void> {\n  if (node.label) {\n    const { shapeSvg, bbox } = await labelHelper(nodesGroup, node);\n    node.labelBBox = { width: bbox.width, height: bbox.height };\n    shapeSvg.remove();\n  } else {\n    node.labelBBox = { width: 0, height: 0 };\n  }\n}\n\nexport async function insertMeasuredNode(\n  nodesGroup: D3Selection<SVGGElement>,\n  node: NonClusterNode,\n  renderOptions: ShapeRenderOptions\n): Promise<D3Selection<SVGElement | SVGGElement>> {\n  const childNodeEl = await insertNode(nodesGroup, node, renderOptions);\n  const boundingBox = childNodeEl.node()?.getBBox() ?? { width: 0, height: 0 };\n  node.width = boundingBox.width;\n  node.height = boundingBox.height;\n  return childNodeEl as D3Selection<SVGElement | SVGGElement>;\n}\n\n/**\n * Creates a graph by merging the graph construction and DOM element insertion.\n *\n * This function creates the graph, inserts the SVG groups (clusters, edgePaths, edgeLabels, nodes)\n * into the provided element, and uses `insertNode` to add nodes to the diagram. Node dimensions\n * are computed using each node's bounding box.\n *\n * @param element - The D3 selection in which the SVG groups are inserted.\n * @param data4Layout - The layout data containing nodes and edges.\n * @returns A promise resolving to an object containing the graph and the inserted groups.\n */\nexport async function createGraphWithElements(\n  element: D3Selection,\n  data4Layout: LayoutData\n): Promise<{\n  graph: graphlib.Graph;\n  groups: {\n    clusters: D3Selection<SVGGElement>;\n    edgePaths: D3Selection<SVGGElement>;\n    edgeLabels: D3Selection<SVGGElement>;\n    nodes: D3Selection<SVGGElement>;\n    rootGroups: D3Selection<SVGGElement>;\n  };\n  nodeElements: Map<string, D3Selection<SVGElement | SVGGElement>>;\n}> {\n  // Create a directed, multi graph.\n  const graph = new graphlib.Graph({\n    multigraph: true,\n    compound: true,\n  });\n  const edgesToProcess = [...data4Layout.edges];\n  const config = getConfig();\n  const groups = createLayoutElementGroups(element);\n  const { edgeLabels, nodes: nodesGroup } = groups;\n\n  const nodeElements = new Map<string, D3Selection<SVGElement | SVGGElement>>();\n\n  // When the container element is detached (no real DOM \u2014 e.g. headless unit\n  // tests that exercise the layout engine without rendering), `insertNode`\n  // cannot measure labels and would dereference a null node. The browser\n  // always passes a live container, so render + measure only when one exists;\n  // otherwise still build the graph topology with unmeasured (0) sizes.\n  const hasDom = element.node() != null;\n\n  // Insert nodes into the DOM and add them to the graph.\n  await Promise.all(\n    data4Layout.nodes.map(async (node) => {\n      if (node.isGroup) {\n        if (hasDom) {\n          await measureGroupLabel(nodesGroup, node);\n        }\n        graph.setNode(node.id, { ...node });\n      } else {\n        if (hasDom) {\n          const childNodeEl = await insertMeasuredNode(nodesGroup, node, {\n            config,\n            dir: node.dir,\n          });\n          nodeElements.set(node.id, childNodeEl);\n        }\n        graph.setNode(node.id, { ...node });\n      }\n    })\n  );\n  // Add edges to the graph.\n\n  for (const edge of edgesToProcess) {\n    if (hasDom && hasEdgeLabel(edge)) {\n      await insertEdgeLabel(edgeLabels, edge);\n    }\n    graph.setEdge(edge.start!, edge.end!, { ...edge }, edge.id);\n    const edgeExists = data4Layout.edges.some((existingEdge) => existingEdge.id === edge.id);\n    if (!edgeExists) {\n      data4Layout.edges.push(edge);\n    }\n  }\n\n  // DDLT size capture (dev / test tooling only). The capture module is loaded\n  // via dynamic import so it is never bundled into the production render path:\n  // in published builds `window.mermaidCaptureSizes` is unset, so this guard is\n  // a single property read and the import resolves to a lazily-loaded chunk that\n  // is only fetched when a developer explicitly enables capture.\n  // See layout-algorithms/ddlt/sizeCapture.ts.\n  if ((globalThis as unknown as { mermaidCaptureSizes?: boolean }).mermaidCaptureSizes) {\n    const { captureNodeSizes } = await import('./layout-algorithms/ddlt/sizeCapture.js');\n    captureNodeSizes(element, data4Layout);\n  }\n\n  return {\n    graph,\n    groups,\n    nodeElements,\n  };\n}\n", "/** Decorates with functions required by mermaids dagre-wrapper. */\nimport { log } from '../../../logger.js';\nimport * as graphlib from 'dagre-d3-es/src/graphlib/index.js';\n\nexport let clusterDb = new Map();\nlet descendants = new Map();\nlet parents = new Map();\n\nexport const clear = () => {\n  descendants.clear();\n  parents.clear();\n  clusterDb.clear();\n};\n\nconst isDescendant = (id, ancestorId) => {\n  const ancestorDescendants = descendants.get(ancestorId) || [];\n  log.trace('In isDescendant', ancestorId, ' ', id, ' = ', ancestorDescendants.includes(id));\n  return ancestorDescendants.includes(id);\n};\n\nconst edgeInCluster = (edge, clusterId) => {\n  const clusterDescendants = descendants.get(clusterId) || [];\n  log.info('Descendants of ', clusterId, ' is ', clusterDescendants);\n  log.info('Edge is ', edge);\n  if (edge.v === clusterId || edge.w === clusterId) {\n    return false;\n  }\n\n  if (!clusterDescendants) {\n    log.debug('Tilt, ', clusterId, ',not in descendants');\n    return false;\n  }\n\n  return (\n    clusterDescendants.includes(edge.v) ||\n    isDescendant(edge.v, clusterId) ||\n    isDescendant(edge.w, clusterId) ||\n    clusterDescendants.includes(edge.w)\n  );\n};\n\nconst copy = (clusterId, graph, newGraph, rootId) => {\n  log.debug(\n    'Copying children of ',\n    clusterId,\n    'root',\n    rootId,\n    'data',\n    graph.node(clusterId),\n    rootId\n  );\n  const nodes = graph.children(clusterId) || [];\n\n  if (clusterId !== rootId) {\n    nodes.push(clusterId);\n  }\n\n  log.debug('Copying (nodes) clusterId', clusterId, 'nodes', nodes);\n\n  nodes.forEach((node) => {\n    if (graph.children(node).length > 0) {\n      copy(node, graph, newGraph, rootId);\n    } else {\n      const data = graph.node(node);\n      log.info('cp ', node, ' to ', rootId, ' with parent ', clusterId);\n      newGraph.setNode(node, data);\n      if (rootId !== graph.parent(node)) {\n        log.debug('Setting parent', node, graph.parent(node));\n        newGraph.setParent(node, graph.parent(node));\n      }\n\n      if (clusterId !== rootId && node !== clusterId) {\n        log.debug('Setting parent', node, clusterId);\n        newGraph.setParent(node, clusterId);\n      } else {\n        log.info('In copy ', clusterId, 'root', rootId, 'data', graph.node(clusterId), rootId);\n        log.debug(\n          'Not Setting parent for node=',\n          node,\n          'cluster!==rootId',\n          clusterId !== rootId,\n          'node!==clusterId',\n          node !== clusterId\n        );\n      }\n      const edges = graph.edges(node);\n      log.debug('Copying Edges', edges);\n      edges.forEach((edge) => {\n        log.info('Edge', edge);\n        const data = graph.edge(edge.v, edge.w, edge.name);\n        log.info('Edge data', data, rootId);\n        try {\n          if (edgeInCluster(edge, rootId)) {\n            log.info('Copying as ', edge.v, edge.w, data, edge.name);\n            newGraph.setEdge(edge.v, edge.w, data, edge.name);\n            log.info('newGraph edges ', newGraph.edges(), newGraph.edge(newGraph.edges()[0]));\n          } else {\n            log.info(\n              'Skipping copy of edge ',\n              edge.v,\n              '-->',\n              edge.w,\n              ' rootId: ',\n              rootId,\n              ' clusterId:',\n              clusterId\n            );\n          }\n        } catch (e) {\n          log.error(e);\n        }\n      });\n    }\n    log.debug('Removing node', node);\n    graph.removeNode(node);\n  });\n};\n\nexport const extractDescendants = (id, graph) => {\n  const children = graph.children(id);\n  let res = [...children];\n\n  for (const child of children) {\n    parents.set(child, id);\n    res = [...res, ...extractDescendants(child, graph)];\n  }\n\n  return res;\n};\n\nexport const validate = (graph) => {\n  const edges = graph.edges();\n  log.trace('Edges: ', edges);\n  for (const edge of edges) {\n    if (graph.children(edge.v).length > 0) {\n      log.trace('The node ', edge.v, ' is part of and edge even though it has children');\n      return false;\n    }\n    if (graph.children(edge.w).length > 0) {\n      log.trace('The node ', edge.w, ' is part of and edge even though it has children');\n      return false;\n    }\n  }\n  return true;\n};\n\nconst findCommonEdges = (graph, id1, id2) => {\n  const edges1 = graph.edges().filter((edge) => edge.v === id1 || edge.w === id1);\n  const edges2 = graph.edges().filter((edge) => edge.v === id2 || edge.w === id2);\n  const edges1Prim = edges1.map((edge) => {\n    return { v: edge.v === id1 ? id2 : edge.v, w: edge.w === id1 ? id1 : edge.w };\n  });\n  const edges2Prim = edges2.map((edge) => {\n    return { v: edge.v, w: edge.w };\n  });\n  const result = edges1Prim.filter((edgeIn1) => {\n    return edges2Prim.some((edge) => edgeIn1.v === edge.v && edgeIn1.w === edge.w);\n  });\n\n  return result;\n};\n\nexport const findNonClusterChild = (id, graph, clusterId) => {\n  const children = graph.children(id);\n  log.trace('Searching children of id ', id, children);\n  if (children.length < 1) {\n    return id;\n  }\n  let reserve;\n  for (const child of children) {\n    const _id = findNonClusterChild(child, graph, clusterId);\n\n    const commonEdges = findCommonEdges(graph, clusterId, _id);\n\n    if (_id) {\n      if (commonEdges.length > 0) {\n        reserve = _id;\n      } else {\n        return _id;\n      }\n    }\n  }\n  return reserve;\n};\n\nconst getAnchorId = (id) => {\n  if (!clusterDb.has(id)) {\n    return id;\n  }\n  if (!clusterDb.get(id).externalConnections) {\n    return id;\n  }\n\n  if (clusterDb.has(id)) {\n    return clusterDb.get(id).id;\n  }\n  return id;\n};\n\nexport const adjustClustersAndEdges = (graph, depth) => {\n  if (!graph || depth > 10) {\n    log.debug('Opting out, no graph ');\n    return;\n  } else {\n    log.debug('Opting in, graph ');\n  }\n\n  graph.nodes().forEach(function (id) {\n    const children = graph.children(id);\n    if (children.length > 0) {\n      log.debug(\n        'Cluster identified',\n        id,\n        ' Replacement id in edges: ',\n        findNonClusterChild(id, graph, id)\n      );\n      descendants.set(id, extractDescendants(id, graph));\n      clusterDb.set(id, { id: findNonClusterChild(id, graph, id), clusterData: graph.node(id) });\n    }\n  });\n\n  graph.nodes().forEach(function (id) {\n    const children = graph.children(id);\n    const edges = graph.edges();\n    if (children.length > 0) {\n      log.debug('Cluster identified', id, descendants);\n      edges.forEach((edge) => {\n        const d1 = isDescendant(edge.v, id);\n        const d2 = isDescendant(edge.w, id);\n\n        if (d1 ^ d2) {\n          log.debug('Edge: ', edge, ' leaves cluster ', id);\n          log.debug('Descendants of XXX ', id, ': ', descendants.get(id));\n          clusterDb.get(id).externalConnections = true;\n        }\n      });\n    } else {\n      log.debug('Not a cluster ', id, descendants);\n    }\n  });\n\n  for (let id of clusterDb.keys()) {\n    const nonClusterChild = clusterDb.get(id).id;\n    const parent = graph.parent(nonClusterChild);\n\n    if (parent !== id && clusterDb.has(parent) && !clusterDb.get(parent).externalConnections) {\n      clusterDb.get(id).id = parent;\n    }\n    // When this cluster has a direct outgoing edge AND its current anchor sits inside\n    // a sibling subgraph that will be extracted (collapsed into a clusterNode), the\n    // anchor will disappear by render time and the edge endpoint becomes undefined.\n    // Re-anchor onto a node that survives extraction.\n    const hasDirectOutgoingEdge = graph.edges().some((edge) => edge.v === id);\n    if (\n      nonClusterChild &&\n      clusterDb.get(id)?.externalConnections &&\n      hasDirectOutgoingEdge &&\n      isNodeInExtractableCluster(graph, nonClusterChild, id)\n    ) {\n      const safeAnchor = findSafeAnchorNode(graph, id, graph.parent(nonClusterChild));\n      if (safeAnchor) {\n        clusterDb.get(id).id = safeAnchor;\n      }\n    }\n  }\n\n  graph.edges().forEach(function (e) {\n    const edge = graph.edge(e);\n    log.debug('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e));\n    log.debug('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(graph.edge(e)));\n\n    let v = e.v;\n    let w = e.w;\n    log.debug(\n      'Fix XXX',\n      clusterDb,\n      'ids:',\n      e.v,\n      e.w,\n      'Translating: ',\n      clusterDb.get(e.v),\n      ' --- ',\n      clusterDb.get(e.w)\n    );\n    if (clusterDb.get(e.v) || clusterDb.get(e.w)) {\n      log.debug('Fixing and trying - removing XXX', e.v, e.w, e.name);\n      v = getAnchorId(e.v);\n      w = getAnchorId(e.w);\n      graph.removeEdge(e.v, e.w, e.name);\n      if (v !== e.v) {\n        const parent = graph.parent(v);\n        clusterDb.get(parent).externalConnections = true;\n        edge.fromCluster = e.v;\n      }\n      if (w !== e.w) {\n        const parent = graph.parent(w);\n        clusterDb.get(parent).externalConnections = true;\n        edge.toCluster = e.w;\n      }\n      log.debug('Fix Replacing with XXX', v, w, e.name);\n      graph.setEdge(v, w, edge, e.name);\n    }\n  });\n  // perf: skip eager graphlibJson.write() serialization (the arg runs every render even when the log is a no-op)\n  // log.debug('Adjusted Graph', graphlibJson.write(graph));\n  extractor(graph, 0);\n\n  log.trace(clusterDb);\n};\n\nexport const extractor = (graph, depth) => {\n  // perf: skip eager graphlibJson.write() serialization (the arg runs every render even when the log is a no-op)\n  // log.debug('extractor - ', depth, graphlibJson.write(graph), graph.children('D'));\n  if (depth > 10) {\n    log.error('Bailing out');\n    return;\n  }\n  let nodes = graph.nodes();\n  let hasChildren = false;\n  for (const node of nodes) {\n    const children = graph.children(node);\n    hasChildren = hasChildren || children.length > 0;\n  }\n\n  if (!hasChildren) {\n    log.debug('Done, no node has children', graph.nodes());\n    return;\n  }\n  log.debug('Nodes = ', nodes, depth);\n  for (const node of nodes) {\n    log.debug(\n      'Extracting node',\n      node,\n      clusterDb,\n      clusterDb.has(node) && !clusterDb.get(node).externalConnections,\n      !graph.parent(node),\n      graph.node(node),\n      graph.children('D'),\n      ' Depth ',\n      depth\n    );\n    if (!clusterDb.has(node)) {\n      log.debug('Not a cluster', node, depth);\n    } else if (\n      !clusterDb.get(node).externalConnections &&\n      graph.children(node) &&\n      graph.children(node).length > 0\n    ) {\n      // Original behaviour: cluster without external connections gets its own sub-graph.\n      log.debug(\n        'Cluster without external connections, without a parent and with children',\n        node,\n        depth\n      );\n\n      const graphSettings = graph.graph();\n      let dir = graphSettings.rankdir === 'TB' ? 'LR' : 'TB';\n      if (clusterDb.get(node)?.clusterData?.dir) {\n        dir = clusterDb.get(node).clusterData.dir;\n        log.debug('Fixing dir', clusterDb.get(node).clusterData.dir, dir);\n      }\n\n      const clusterGraph = new graphlib.Graph({\n        multigraph: true,\n        compound: true,\n      })\n        .setGraph({\n          rankdir: dir,\n          nodesep: 50,\n          ranksep: 50,\n          marginx: 8,\n          marginy: 8,\n        })\n        .setDefaultEdgeLabel(function () {\n          return {};\n        });\n\n      // perf: skip eager graphlibJson.write() serialization (the arg runs every render even when the log is a no-op)\n      // log.debug('Old graph before copy', graphlibJson.write(graph));\n      copy(node, graph, clusterGraph, node);\n      graph.setNode(node, {\n        clusterNode: true,\n        id: node,\n        clusterData: clusterDb.get(node).clusterData,\n        label: clusterDb.get(node).label,\n        graph: clusterGraph,\n      });\n      // perf: skip eager graphlibJson.write() serialization (the arg runs every render even when the log is a no-op)\n      // log.debug('Old graph after copy', graphlibJson.write(graph));\n    } else {\n      log.debug(\n        'Cluster ** ',\n        node,\n        ' **not meeting the criteria !externalConnections:',\n        !clusterDb.get(node).externalConnections,\n        ' no parent: ',\n        !graph.parent(node),\n        ' children ',\n        graph.children(node) && graph.children(node).length > 0,\n        graph.children('D'),\n        depth\n      );\n      log.debug(clusterDb);\n    }\n  }\n\n  nodes = graph.nodes();\n  log.debug('New list of nodes', nodes);\n  for (const node of nodes) {\n    const data = graph.node(node);\n    log.debug(' Now next level', node, data);\n    if (data?.clusterNode) {\n      extractor(data.graph, depth + 1);\n    }\n  }\n};\n\nconst sorter = (graph, nodes) => {\n  if (nodes.length === 0) {\n    return [];\n  }\n  let result = Object.assign([], nodes);\n  nodes.forEach((node) => {\n    const children = graph.children(node);\n    const sorted = sorter(graph, children);\n    result = [...result, ...sorted];\n  });\n\n  return result;\n};\n\nexport const sortNodesByHierarchy = (graph) => sorter(graph, graph.children());\n\n/** Checks if a node is inside a cluster that will be extracted (has no external connections). */\nconst isNodeInExtractableCluster = (graph, node, rootId) => {\n  let parent = graph.parent(node);\n\n  while (parent && parent !== rootId) {\n    const cluster = clusterDb.get(parent);\n    if (cluster && !cluster.externalConnections) {\n      return true;\n    }\n    parent = graph.parent(parent);\n  }\n\n  return false;\n};\n\n/** Finds an alternative anchor node for a cluster that is not inside an extractable cluster. */\nconst findSafeAnchorNode = (graph, clusterId, excludedCluster) => {\n  const children = graph.children(clusterId) ?? [];\n\n  for (const child of children) {\n    if (child === excludedCluster || isDescendant(child, excludedCluster)) {\n      continue;\n    }\n\n    // findNonClusterChild returns the leaf itself when child is a leaf, or drills\n    // into a subgraph to find a non-cluster descendant. A returned leaf sibling is\n    // a perfectly valid anchor \u2014 only skip when the lookup found nothing usable.\n    const candidate = findNonClusterChild(child, graph, clusterId);\n    if (!candidate) {\n      continue;\n    }\n\n    if (!isNodeInExtractableCluster(graph, candidate, clusterId)) {\n      return candidate;\n    }\n  }\n\n  return null;\n};\n", "import type { SVG } from '../../../diagram-api/types.js';\nimport type { InternalHelpers } from '../../../internals.js';\nimport type { D3Selection } from '../../../types.js';\nimport { log } from '../../../logger.js';\nimport { profiler } from '../../../profiler.js';\nimport { getConfig } from '../../../config.js';\nimport utils from '../../../utils.js';\nimport { getSubGraphTitleMargins } from '../../../utils/subGraphTitleMargins.js';\nimport { createGraphWithElements } from '../../createGraph.js';\nimport { clear as clearClusters, insertCluster } from '../../rendering-elements/clusters.js';\nimport {\n  clear as clearEdges,\n  edgeLabels,\n  hasEdgeLabel,\n  insertEdge,\n  insertEdgeLabel,\n  terminalLabels,\n} from '../../rendering-elements/edges.js';\nimport insertMarkers from '../../rendering-elements/markers.js';\nimport { clear as clearNodes, positionNode } from '../../rendering-elements/nodes.js';\nimport type { LayoutData, Edge, ClusterNode } from '../../types.js';\nimport type { RenderOptions } from '../../render.js';\nimport { clear as clearGraphlib } from '../dagre/mermaid-graphlib.js';\n\nexport type CommonLayoutMeasure = Awaited<ReturnType<typeof createGraphWithElements>>;\ntype RenderedEdge = Edge & {\n  x?: number;\n  y?: number;\n  startLabelLeft?: string;\n  endLabelRight?: string;\n};\ntype EdgeRenderPath = Parameters<typeof utils.calcLabelPosition>[0];\ntype ClusterDb = Map<string, { node?: LayoutData['nodes'][number] } & Record<string, unknown>>;\n\ninterface EdgeRenderPaths {\n  originalPath?: EdgeRenderPath;\n  updatedPath?: EdgeRenderPath;\n}\n\nexport interface CommonLayoutRenderContext<PreparedLayout = unknown> {\n  element: D3Selection<SVGElement>;\n  helpers?: InternalHelpers;\n  options?: RenderOptions;\n  preparedLayout?: PreparedLayout;\n}\n\nexport interface CommonLayoutPaintContext<\n  PreparedLayout = unknown,\n  MeasureResult = CommonLayoutMeasure,\n> extends CommonLayoutRenderContext<PreparedLayout> {\n  measure: MeasureResult;\n}\n\nexport interface CommonLayoutPaintOptions {\n  clusterDb?: ClusterDb;\n  getNodes?: (\n    data4Layout: LayoutData,\n    context: CommonLayoutPaintContext<unknown, CommonLayoutMeasure>\n  ) => Iterable<LayoutData['nodes'][number]>;\n  getEdgeNode?: (\n    id: string | undefined,\n    edge: Edge,\n    context: CommonLayoutPaintContext<unknown, CommonLayoutMeasure>\n  ) => LayoutData['nodes'][number] | object | undefined;\n  skipNode?: (\n    node: LayoutData['nodes'][number],\n    context: CommonLayoutPaintContext<unknown, CommonLayoutMeasure>\n  ) => boolean;\n  isCluster?: (\n    node: LayoutData['nodes'][number],\n    context: CommonLayoutPaintContext<unknown, CommonLayoutMeasure>\n  ) => boolean;\n  skipEdge?: (edge: Edge) => boolean;\n  skipIntersect?: boolean | ((edge: Edge) => boolean);\n}\n\nexport interface CommonLayoutRendererDefinition<\n  CoreResult = unknown,\n  PreparedLayout = void,\n  MeasureResult = CommonLayoutMeasure,\n> {\n  prepareLayout?: (\n    data4Layout: LayoutData,\n    context: CommonLayoutRenderContext<PreparedLayout>\n  ) => PreparedLayout | Promise<PreparedLayout>;\n  measureLayout?: (\n    data4Layout: LayoutData,\n    context: CommonLayoutRenderContext<PreparedLayout>\n  ) => Promise<MeasureResult>;\n  runLayoutCore: (\n    data4Layout: LayoutData,\n    context: CommonLayoutRenderContext<PreparedLayout>\n  ) => CoreResult | Promise<CoreResult>;\n  paintLayout?: (\n    data4Layout: LayoutData,\n    context: CommonLayoutPaintContext<PreparedLayout, MeasureResult>,\n    coreResult: CoreResult\n  ) => void | Promise<void>;\n  afterPaint?: (\n    data4Layout: LayoutData,\n    context: CommonLayoutPaintContext<PreparedLayout, MeasureResult>,\n    coreResult: CoreResult\n  ) => void | Promise<void>;\n  paintOptions?: CommonLayoutPaintOptions;\n}\n\nexport function createCommonLayoutRenderer<\n  CoreResult = unknown,\n  PreparedLayout = void,\n  MeasureResult = CommonLayoutMeasure,\n>({\n  prepareLayout,\n  measureLayout,\n  runLayoutCore,\n  paintLayout,\n  afterPaint,\n  paintOptions,\n}: CommonLayoutRendererDefinition<CoreResult, PreparedLayout, MeasureResult>) {\n  // Use the provided measureLayout or default to createGraphWithElements if not provided.\n  // This allows layout algorithms to skip the graph creation step if they don't need it,\n  // while still providing a default implementation for those that do.\n  const measureLayoutFn =\n    measureLayout ??\n    (defaultMeasureLayout as unknown as NonNullable<\n      CommonLayoutRendererDefinition<CoreResult, PreparedLayout, MeasureResult>['measureLayout']\n    >);\n\n  // This is the actual factory step where the render function is created.\n  return async function render(\n    data4Layout: LayoutData,\n    svg: SVG,\n    helpers?: InternalHelpers,\n    options?: RenderOptions\n  ): Promise<void> {\n    const element = svg.select('g') as unknown as D3Selection<SVGElement>;\n    insertMarkers(element, data4Layout.markers, data4Layout.type, data4Layout.diagramId);\n    clearLayoutRenderState();\n\n    // Convenience struct containing everything you need to render\n    // the root element and helper function from core mermaid\n    const renderContext: CommonLayoutRenderContext<PreparedLayout> = {\n      element, // root SVG <g>\n      helpers, // Mermaid helper functions\n      options, // { algorithm: \"elk.layered\" }\n    };\n\n    // Algorithm-specific transformations onto the original parsed layout data so the algorithm-specific\n    // layout core has the inputs and setup it needs\n    renderContext.preparedLayout = injected.profiling\n      ? await profiler.span('prepare', () => prepareLayout?.(data4Layout, renderContext))\n      : await prepareLayout?.(data4Layout, renderContext);\n\n    // Get the sizes of the labels and other elements by running the measureLayout function,\n    // which by default creates a graph with the elements and measures them.\n    // This is needed for layout algorithms that require size information to compute the layout.\n    const measure = injected.profiling\n      ? await profiler.span('measure', () => measureLayoutFn(data4Layout, renderContext))\n      : await measureLayoutFn(data4Layout, renderContext);\n\n    // Next, run the core layout algorithm to compute the positions of nodes and edges based on the algorithm,\n    // layoutData and the measurements. This is the core piece where functions are supposed to be different\n    // between different algorithms.\n    const coreResult = injected.profiling\n      ? await profiler.span('layout', () => runLayoutCore(data4Layout, renderContext))\n      : await runLayoutCore(data4Layout, renderContext);\n\n    const paintContext: CommonLayoutPaintContext<PreparedLayout, MeasureResult> = {\n      ...renderContext,\n      measure,\n    };\n\n    if (injected.profiling) {\n      profiler.begin('paint');\n    }\n    if (paintLayout) {\n      // Escape hatch: if a custom paintLayout is provided, we assume it handles everything including painting\n      // based on the layout data and measurements, so we just call it directly with the core result. Only to be used\n      // sparingly during transitions to the new system or for very custom layouts that don't fit the common pattern.\n      await paintLayout(data4Layout, paintContext, coreResult);\n    } else {\n      await paintLayoutData(\n        data4Layout,\n        paintContext as unknown as CommonLayoutPaintContext<unknown, CommonLayoutMeasure>,\n        paintOptions\n      );\n    }\n    // Some algorithms may need to do some post-processing after the initial paint, for example to position edge\n    // labels after the edges have been rendered and their paths are known.\n    await afterPaint?.(data4Layout, paintContext, coreResult);\n    if (injected.profiling) {\n      profiler.end(); // paint\n    }\n  };\n}\n\nexport function clearLayoutRenderState(): void {\n  clearNodes();\n  clearEdges();\n  clearClusters();\n  clearGraphlib();\n}\n\nexport async function defaultMeasureLayout(\n  data4Layout: LayoutData,\n  { element }: CommonLayoutRenderContext\n): Promise<CommonLayoutMeasure> {\n  return await createGraphWithElements(element, data4Layout);\n}\n\nexport async function paintLayoutData(\n  data4Layout: LayoutData,\n  context: CommonLayoutPaintContext<unknown, CommonLayoutMeasure>,\n  options: CommonLayoutPaintOptions = {}\n): Promise<void> {\n  const { measure } = context;\n  const { groups } = measure;\n\n  // Render clusters and position nodes; this also populates node.intersect on shapes.\n  for (const node of options.getNodes?.(data4Layout, context) ?? data4Layout.nodes) {\n    if (options.skipNode?.(node, context)) {\n      continue;\n    }\n    await paintLayoutNode(groups, node, context, options);\n  }\n\n  const nodeById = buildNodeLookup(data4Layout.nodes);\n\n  for (const edge of data4Layout.edges) {\n    if (shouldSkipPaintEdge(edge, options)) {\n      continue;\n    }\n\n    await paintLayoutEdge(groups, edge, nodeById, data4Layout, options, context);\n  }\n}\n\nasync function paintLayoutNode(\n  groups: CommonLayoutMeasure['groups'],\n  node: LayoutData['nodes'][number],\n  context: CommonLayoutPaintContext<unknown, CommonLayoutMeasure>,\n  options: CommonLayoutPaintOptions\n): Promise<void> {\n  if ((node as { clusterNode?: boolean }).clusterNode) {\n    positionNode(node);\n  } else if (shouldPaintAsCluster(node, context, options)) {\n    await insertCluster(groups.clusters, node);\n  } else {\n    positionNode(node);\n  }\n}\n\nfunction shouldPaintAsCluster(\n  node: LayoutData['nodes'][number],\n  context: CommonLayoutPaintContext<unknown, CommonLayoutMeasure>,\n  options: CommonLayoutPaintOptions\n): node is ClusterNode {\n  return node.isGroup === true && (options.isCluster?.(node, context) ?? true);\n}\n\nfunction buildNodeLookup(nodes: LayoutData['nodes']): Map<string, LayoutData['nodes'][number]> {\n  const nodeById = new Map<string, LayoutData['nodes'][number]>();\n  for (const node of nodes) {\n    if (node?.id) {\n      nodeById.set(node.id, node);\n    }\n  }\n  return nodeById;\n}\n\nfunction shouldSkipPaintEdge(edge: Edge, options: CommonLayoutPaintOptions): boolean {\n  return edge.isLayoutOnly || Boolean(options.skipEdge?.(edge));\n}\n\nasync function paintLayoutEdge(\n  groups: CommonLayoutMeasure['groups'],\n  edge: Edge,\n  nodeById: Map<string, LayoutData['nodes'][number]>,\n  data4Layout: LayoutData,\n  options: CommonLayoutPaintOptions,\n  context: CommonLayoutPaintContext<unknown, CommonLayoutMeasure>\n): Promise<void> {\n  const paths = insertEdge(\n    groups.edgePaths,\n    { ...edge },\n    options.clusterDb ?? new Map(),\n    data4Layout.type,\n    getRenderedNode(edge.start, edge, nodeById, context, options),\n    getRenderedNode(edge.end, edge, nodeById, context, options),\n    data4Layout.diagramId,\n    shouldSkipIntersect(edge, options)\n  ) as EdgeRenderPaths | undefined;\n\n  if (hasEdgeLabel(edge)) {\n    if (!edgeLabels.has(edge.id)) {\n      await insertEdgeLabel(groups.edgeLabels, edge);\n    }\n    positionRenderedEdgeLabel(edge, paths);\n  }\n}\n\nfunction getRenderedNode(\n  id: string | undefined,\n  edge: Edge,\n  nodeById: Map<string, LayoutData['nodes'][number]>,\n  context: CommonLayoutPaintContext<unknown, CommonLayoutMeasure>,\n  options: CommonLayoutPaintOptions\n): LayoutData['nodes'][number] | object {\n  return options.getEdgeNode?.(id, edge, context) ?? (id ? (nodeById.get(id) ?? {}) : {});\n}\n\nfunction shouldSkipIntersect(edge: Edge, options: CommonLayoutPaintOptions): boolean {\n  return typeof options.skipIntersect === 'function'\n    ? options.skipIntersect(edge)\n    : (options.skipIntersect ?? false);\n}\n\nfunction positionRenderedEdgeLabel(edge: RenderedEdge, paths?: EdgeRenderPaths): void {\n  const path = paths?.updatedPath ?? paths?.originalPath;\n  const siteConfig = getConfig();\n  const { subGraphTitleTotalMargin } = getSubGraphTitleMargins({\n    flowchart: siteConfig.flowchart ?? {},\n  });\n  if (edge.label) {\n    const el = edgeLabels.get(edge.id);\n    let x = edge.x;\n    let y = edge.y;\n    if (path) {\n      const pos = utils.calcLabelPosition(path);\n      log.debug(\n        'Moving label ' + edge.label + ' from (',\n        x,\n        ',',\n        y,\n        ') to (',\n        pos.x,\n        ',',\n        pos.y,\n        ') abc88'\n      );\n      if (paths?.updatedPath) {\n        x = pos.x;\n        y = pos.y;\n      }\n    }\n    el.attr('transform', `translate(${x}, ${y! + subGraphTitleTotalMargin / 2})`);\n  }\n\n  if (edge?.startLabelLeft) {\n    const el = terminalLabels.get(edge.id).startLeft;\n    let x = edge?.x;\n    let y = edge?.y;\n    if (path) {\n      const pos = utils.calcTerminalLabelPosition(edge.arrowTypeStart ? 10 : 0, 'start_left', path);\n      x = pos.x;\n      y = pos.y;\n    }\n    el.attr('transform', `translate(${x}, ${y})`);\n  }\n  if (edge.startLabelRight) {\n    const el = terminalLabels.get(edge.id).startRight;\n    let x = edge.x;\n    let y = edge.y;\n    if (path) {\n      const pos = utils.calcTerminalLabelPosition(\n        edge.arrowTypeStart ? 10 : 0,\n        'start_right',\n        path\n      );\n      x = pos.x;\n      y = pos.y;\n    }\n    el.attr('transform', `translate(${x}, ${y})`);\n  }\n  if (edge.endLabelLeft) {\n    const el = terminalLabels.get(edge.id).endLeft;\n    let x = edge.x;\n    let y = edge.y;\n    if (path) {\n      const pos = utils.calcTerminalLabelPosition(edge.arrowTypeEnd ? 10 : 0, 'end_left', path);\n      x = pos.x;\n      y = pos.y;\n    }\n    el.attr('transform', `translate(${x}, ${y})`);\n  }\n  if (edge.endLabelRight) {\n    const el = terminalLabels.get(edge.id).endRight;\n    let x = edge.x;\n    let y = edge.y;\n    if (path) {\n      const pos = utils.calcTerminalLabelPosition(edge.arrowTypeEnd ? 10 : 0, 'end_right', path);\n      x = pos.x;\n      y = pos.y;\n    }\n    el.attr('transform', `translate(${x}, ${y})`);\n  }\n}\n"],
  "mappings": "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",
  "names": ["edgeLabels", "getConfig", "graphlib", "clear", "data", "clear"]
}