@ktrysmt/beautiful-mermaid 1.5.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -481,8 +481,43 @@ function parseFlowchart(lines) {
481
481
  }
482
482
  parseEdgeLine(line, graph, subgraphStack);
483
483
  }
484
+ resolveSubgraphEdgeEndpoints(graph);
484
485
  return graph;
485
486
  }
487
+ function resolveSubgraphEdgeEndpoints(graph) {
488
+ const representatives = /* @__PURE__ */ new Map();
489
+ function pickRepresentative(sg) {
490
+ for (const id of sg.nodeIds) {
491
+ if (graph.nodes.has(id)) return id;
492
+ }
493
+ for (const child of sg.children) {
494
+ const childRep = representatives.get(child.id) ?? pickRepresentative(child);
495
+ if (childRep) return childRep;
496
+ }
497
+ return void 0;
498
+ }
499
+ function visit(sg) {
500
+ for (const child of sg.children) visit(child);
501
+ const rep = pickRepresentative(sg);
502
+ if (rep) representatives.set(sg.id, rep);
503
+ }
504
+ for (const sg of graph.subgraphs) visit(sg);
505
+ if (representatives.size === 0) return;
506
+ for (const edge of graph.edges) {
507
+ const newSource = representatives.get(edge.source);
508
+ if (newSource) edge.source = newSource;
509
+ const newTarget = representatives.get(edge.target);
510
+ if (newTarget) edge.target = newTarget;
511
+ }
512
+ for (const sgId of representatives.keys()) {
513
+ graph.nodes.delete(sgId);
514
+ }
515
+ function scrubMembership(sg) {
516
+ sg.nodeIds = sg.nodeIds.filter((id) => !representatives.has(id));
517
+ for (const child of sg.children) scrubMembership(child);
518
+ }
519
+ for (const sg of graph.subgraphs) scrubMembership(sg);
520
+ }
486
521
  function parseStateDiagram(lines) {
487
522
  const graph = {
488
523
  direction: "TD",
@@ -3912,6 +3947,7 @@ function createMapping(graph) {
3912
3947
  primaryRoots.push(root);
3913
3948
  }
3914
3949
  }
3950
+ const sourceStartLevel = computeSourceStartLevels(graph, primaryRoots);
3915
3951
  const rootsByTarget = /* @__PURE__ */ new Map();
3916
3952
  for (const root of primaryRoots) {
3917
3953
  const children = getChildren(graph, root);
@@ -3922,9 +3958,10 @@ function createMapping(graph) {
3922
3958
  }
3923
3959
  for (const [, roots] of rootsByTarget) {
3924
3960
  for (const node of roots) {
3925
- const requested = dir === "LR" ? { x: 0, y: highestPositionPerLevel[0] } : { x: highestPositionPerLevel[0], y: 0 };
3961
+ const startLevel = sourceStartLevel.get(node.name) ?? 0;
3962
+ const requested = dir === "LR" ? { x: startLevel, y: highestPositionPerLevel[startLevel] } : { x: highestPositionPerLevel[startLevel], y: startLevel };
3926
3963
  reserveSpotInGrid(graph, graph.nodes[node.index], requested);
3927
- highestPositionPerLevel[0] = highestPositionPerLevel[0] + 4;
3964
+ highestPositionPerLevel[startLevel] = highestPositionPerLevel[startLevel] + 4;
3928
3965
  }
3929
3966
  }
3930
3967
  if (shouldSeparate && subgraphRootNodes.length > 0) {
@@ -4073,6 +4110,62 @@ function createMapping(graph) {
4073
4110
  function getEdgesFromNode(graph, node) {
4074
4111
  return graph.edges.filter((e) => e.from.name === node.name);
4075
4112
  }
4113
+ function computeSourceStartLevels(graph, sources) {
4114
+ const childrenByName = /* @__PURE__ */ new Map();
4115
+ const parentsByName = /* @__PURE__ */ new Map();
4116
+ const inDegree = /* @__PURE__ */ new Map();
4117
+ for (const n of graph.nodes) {
4118
+ childrenByName.set(n.name, []);
4119
+ parentsByName.set(n.name, []);
4120
+ inDegree.set(n.name, 0);
4121
+ }
4122
+ for (const e of graph.edges) {
4123
+ if (e.from.name === e.to.name) continue;
4124
+ childrenByName.get(e.from.name).push(e.to);
4125
+ parentsByName.get(e.to.name).push(e.from);
4126
+ inDegree.set(e.to.name, (inDegree.get(e.to.name) ?? 0) + 1);
4127
+ }
4128
+ const queue = [];
4129
+ for (const n of graph.nodes) {
4130
+ if ((inDegree.get(n.name) ?? 0) === 0) queue.push(n);
4131
+ }
4132
+ const topoOrder = [];
4133
+ while (queue.length > 0) {
4134
+ const n = queue.shift();
4135
+ topoOrder.push(n);
4136
+ for (const c of childrenByName.get(n.name) ?? []) {
4137
+ const d = (inDegree.get(c.name) ?? 0) - 1;
4138
+ inDegree.set(c.name, d);
4139
+ if (d === 0) queue.push(c);
4140
+ }
4141
+ }
4142
+ const result = /* @__PURE__ */ new Map();
4143
+ if (topoOrder.length < graph.nodes.length) return result;
4144
+ const forwardLevel = /* @__PURE__ */ new Map();
4145
+ for (const n of topoOrder) {
4146
+ let best = 0;
4147
+ for (const p of parentsByName.get(n.name) ?? []) {
4148
+ const pl = (forwardLevel.get(p.name) ?? 0) + 1;
4149
+ if (pl > best) best = pl;
4150
+ }
4151
+ forwardLevel.set(n.name, best);
4152
+ }
4153
+ for (const src of sources) {
4154
+ const children = getChildren(graph, src).filter((c) => c.name !== src.name);
4155
+ if (children.length === 0) {
4156
+ result.set(src.name, 0);
4157
+ continue;
4158
+ }
4159
+ let minChild = Infinity;
4160
+ for (const c of children) {
4161
+ const cl = forwardLevel.get(c.name) ?? 0;
4162
+ if (cl < minChild) minChild = cl;
4163
+ }
4164
+ const logical = Number.isFinite(minChild) ? Math.max(0, minChild - 1) : 0;
4165
+ result.set(src.name, logical * 4);
4166
+ }
4167
+ return result;
4168
+ }
4076
4169
  function getChildren(graph, node) {
4077
4170
  return getEdgesFromNode(graph, node).map((e) => e.to);
4078
4171
  }