@crazyhappyone/auto-graph 0.1.0 → 0.1.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.
@@ -3147,6 +3147,15 @@ function fitDslLabel(label, measurer) {
3147
3147
  function point(value) {
3148
3148
  return { x: value.x, y: value.y };
3149
3149
  }
3150
+
3151
+ // src/ir/diagnostics.ts
3152
+ var DELIVERABILITY_DIAGNOSTIC_CODES = /* @__PURE__ */ new Set([
3153
+ "constraints.locked-target-not-moved",
3154
+ "routing.evidence.crossing_forbidden",
3155
+ "routing.obstacle.unavoidable",
3156
+ "route_obstacle_fallback",
3157
+ "routing.text-clearance.unresolved"
3158
+ ]);
3150
3159
  var DEFAULT_OPTIONS = {
3151
3160
  nodesep: 80,
3152
3161
  ranksep: 100,
@@ -3345,6 +3354,51 @@ function routeEdge(input) {
3345
3354
  )
3346
3355
  );
3347
3356
  if (hardClearCandidate !== void 0) {
3357
+ let bestPoints2 = hardClearCandidate.points;
3358
+ if (input.kind === "obstacle-avoiding") {
3359
+ const allObstacles = [...softObstacles, ...hardObstacles];
3360
+ for (const candidate of candidateRoutes) {
3361
+ if (routeCrossesBoxes(candidate.points, hardObstacles) || routeIntersectsEndpointInteriors(
3362
+ candidate.points,
3363
+ candidate.endpointObstacles
3364
+ )) {
3365
+ continue;
3366
+ }
3367
+ const rerouted2 = greedyRerouteAroundObstacles(
3368
+ candidate.points,
3369
+ allObstacles,
3370
+ 3
3371
+ );
3372
+ if (!routeCrossesBoxes(rerouted2, allObstacles) && !routeIntersectsEndpointInteriors(
3373
+ rerouted2,
3374
+ candidate.endpointObstacles
3375
+ )) {
3376
+ return {
3377
+ points: finalizeRoute(
3378
+ rerouted2,
3379
+ softObstacles,
3380
+ hardObstacles,
3381
+ diagnostics
3382
+ ),
3383
+ diagnostics
3384
+ };
3385
+ }
3386
+ }
3387
+ const rerouted = greedyRerouteAroundObstacles(
3388
+ bestPoints2,
3389
+ allObstacles,
3390
+ 3
3391
+ );
3392
+ const reroutedAvoidsEndpointInteriors = !routeIntersectsEndpointInteriors(
3393
+ rerouted,
3394
+ hardClearCandidate.endpointObstacles
3395
+ );
3396
+ if (reroutedAvoidsEndpointInteriors) {
3397
+ if (routeCrossesBoxes(rerouted, hardObstacles) && !routeCrossesBoxes(bestPoints2, hardObstacles)) ; else {
3398
+ bestPoints2 = rerouted;
3399
+ }
3400
+ }
3401
+ }
3348
3402
  diagnostics.push({
3349
3403
  severity: "warning",
3350
3404
  code: "routing.obstacle.unavoidable",
@@ -3352,7 +3406,7 @@ function routeEdge(input) {
3352
3406
  });
3353
3407
  return {
3354
3408
  points: finalizeRoute(
3355
- hardClearCandidate.points,
3409
+ bestPoints2,
3356
3410
  softObstacles,
3357
3411
  hardObstacles,
3358
3412
  diagnostics
@@ -3361,6 +3415,33 @@ function routeEdge(input) {
3361
3415
  };
3362
3416
  }
3363
3417
  if (hardObstacles.length > 0) {
3418
+ let bestPoints2 = candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors);
3419
+ if (input.kind === "obstacle-avoiding") {
3420
+ const allObstacles = [...softObstacles, ...hardObstacles];
3421
+ for (const candidate of candidateRoutes) {
3422
+ const rerouted = greedyRerouteAroundObstacles(
3423
+ candidate.points,
3424
+ allObstacles,
3425
+ 5
3426
+ );
3427
+ if (!routeCrossesBoxes(rerouted, allObstacles)) {
3428
+ return {
3429
+ points: finalizeRoute(
3430
+ rerouted,
3431
+ softObstacles,
3432
+ hardObstacles,
3433
+ diagnostics
3434
+ ),
3435
+ diagnostics
3436
+ };
3437
+ }
3438
+ }
3439
+ bestPoints2 = greedyRerouteAroundObstacles(
3440
+ candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors),
3441
+ allObstacles,
3442
+ 5
3443
+ );
3444
+ }
3364
3445
  diagnostics.push({
3365
3446
  severity: "error",
3366
3447
  code: "routing.evidence.crossing_forbidden",
@@ -3368,7 +3449,7 @@ function routeEdge(input) {
3368
3449
  });
3369
3450
  return {
3370
3451
  points: finalizeRoute(
3371
- candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors),
3452
+ bestPoints2,
3372
3453
  softObstacles,
3373
3454
  hardObstacles,
3374
3455
  diagnostics
@@ -3376,6 +3457,33 @@ function routeEdge(input) {
3376
3457
  diagnostics
3377
3458
  };
3378
3459
  }
3460
+ let bestPoints = candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors);
3461
+ if (input.kind === "obstacle-avoiding") {
3462
+ const allObstacles = [...softObstacles, ...hardObstacles];
3463
+ for (const candidate of candidateRoutes) {
3464
+ const rerouted = greedyRerouteAroundObstacles(
3465
+ candidate.points,
3466
+ allObstacles,
3467
+ 5
3468
+ );
3469
+ if (!routeCrossesBoxes(rerouted, allObstacles)) {
3470
+ return {
3471
+ points: finalizeRoute(
3472
+ rerouted,
3473
+ softObstacles,
3474
+ hardObstacles,
3475
+ diagnostics
3476
+ ),
3477
+ diagnostics
3478
+ };
3479
+ }
3480
+ }
3481
+ bestPoints = greedyRerouteAroundObstacles(
3482
+ candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors),
3483
+ allObstacles,
3484
+ 5
3485
+ );
3486
+ }
3379
3487
  diagnostics.push({
3380
3488
  severity: "warning",
3381
3489
  code: "routing.obstacle.unavoidable",
@@ -3383,7 +3491,7 @@ function routeEdge(input) {
3383
3491
  });
3384
3492
  return {
3385
3493
  points: finalizeRoute(
3386
- candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors),
3494
+ bestPoints,
3387
3495
  softObstacles,
3388
3496
  hardObstacles,
3389
3497
  diagnostics
@@ -3393,21 +3501,29 @@ function routeEdge(input) {
3393
3501
  }
3394
3502
  function finalizeRoute(points, softObstacles, hardObstacles, diagnostics) {
3395
3503
  const simplified = simplifyRoute(points);
3504
+ if (simplified.length >= 3) {
3505
+ return simplified;
3506
+ }
3396
3507
  const crossesHardObstacles = routeCrossesBoxes(simplified, hardObstacles);
3397
3508
  const crossesSoftObstacles = routeCrossesBoxes(simplified, softObstacles);
3398
- if (simplified.length < 3 && (crossesHardObstacles || crossesSoftObstacles)) {
3509
+ if (!crossesHardObstacles && !crossesSoftObstacles) {
3510
+ return simplified;
3511
+ }
3512
+ const expanded = expandFallbackRoute(simplified, [
3513
+ ...softObstacles,
3514
+ ...hardObstacles
3515
+ ]);
3516
+ const expandedCrossesHard = routeCrossesBoxes(expanded, hardObstacles);
3517
+ const expandedCrossesSoft = routeCrossesBoxes(expanded, softObstacles);
3518
+ if (expandedCrossesHard || expandedCrossesSoft) {
3399
3519
  diagnostics.push({
3400
- severity: crossesHardObstacles ? "error" : "warning",
3520
+ severity: expandedCrossesHard ? "error" : "warning",
3401
3521
  code: "route_obstacle_fallback",
3402
3522
  message: "Obstacle-aware routing fell back to fewer than three route points.",
3403
3523
  detail: { pointCount: simplified.length }
3404
3524
  });
3405
- return expandFallbackRoute(simplified, [
3406
- ...softObstacles,
3407
- ...hardObstacles
3408
- ]);
3409
3525
  }
3410
- return simplified;
3526
+ return expanded;
3411
3527
  }
3412
3528
  function expandFallbackRoute(points, obstacles) {
3413
3529
  if (points.length !== 2) {
@@ -3438,12 +3554,12 @@ function expandFallbackRoute(points, obstacles) {
3438
3554
  const hv = diagonalDetourHV(source, target, obstacles);
3439
3555
  const vh = diagonalDetourVH(source, target, obstacles);
3440
3556
  const viable = [hv, vh].filter((c) => !routeCrossesBoxes(c, obstacles));
3441
- if (viable.length > 0) {
3557
+ const [firstViable, ...remainingViable] = viable;
3558
+ if (firstViable !== void 0) {
3442
3559
  const directLen = Math.hypot(target.x - source.x, target.y - source.y);
3443
- let best = viable[0];
3444
- for (let i = 1; i < viable.length; i += 1) {
3445
- const cand = viable[i];
3446
- if (cand !== void 0 && pathLength(cand) - directLen < pathLength(best) - directLen) {
3560
+ let best = firstViable;
3561
+ for (const cand of remainingViable) {
3562
+ if (pathLength(cand) - directLen < pathLength(best) - directLen) {
3447
3563
  best = cand;
3448
3564
  }
3449
3565
  }
@@ -3533,6 +3649,70 @@ function insetBox(box, margin) {
3533
3649
  height: box.height - margin * 2
3534
3650
  };
3535
3651
  }
3652
+ function greedyRerouteAroundObstacles(points, obstacles, maxIterations) {
3653
+ let current = [...points];
3654
+ for (let iter = 0; iter < maxIterations; iter++) {
3655
+ const improved = pushRouteAwayFromObstacles(current, obstacles);
3656
+ if (improved === null) {
3657
+ break;
3658
+ }
3659
+ current = improved;
3660
+ if (!routeCrossesBoxes(current, obstacles)) {
3661
+ break;
3662
+ }
3663
+ }
3664
+ return current;
3665
+ }
3666
+ function pushRouteAwayFromObstacles(points, obstacles) {
3667
+ const result = [];
3668
+ let improved = false;
3669
+ for (let i = 0; i < points.length - 1; i++) {
3670
+ const a = points[i];
3671
+ const b = points[i + 1];
3672
+ if (a === void 0 || b === void 0) {
3673
+ result.push(a ?? b ?? { x: 0, y: 0 });
3674
+ continue;
3675
+ }
3676
+ result.push(a);
3677
+ const intersectors = obstacles.filter(
3678
+ (obs) => segmentIntersectsBox(a, b, obs)
3679
+ );
3680
+ if (intersectors.length === 0) {
3681
+ continue;
3682
+ }
3683
+ const mx = (a.x + b.x) / 2;
3684
+ const my = (a.y + b.y) / 2;
3685
+ const isHorizontal = a.y === b.y;
3686
+ const margin = 12;
3687
+ let bestWaypoint = null;
3688
+ let bestDist = Infinity;
3689
+ for (const obs of intersectors) {
3690
+ const candidates = isHorizontal ? [
3691
+ { x: mx, y: obs.y - margin },
3692
+ { x: mx, y: obs.y + obs.height + margin }
3693
+ ] : [
3694
+ { x: obs.x - margin, y: my },
3695
+ { x: obs.x + obs.width + margin, y: my }
3696
+ ];
3697
+ for (const wp of candidates) {
3698
+ const dist = Math.hypot(wp.x - mx, wp.y - my);
3699
+ if (dist < bestDist) {
3700
+ bestDist = dist;
3701
+ bestWaypoint = wp;
3702
+ }
3703
+ }
3704
+ }
3705
+ if (bestWaypoint !== null) {
3706
+ result.push(bestWaypoint);
3707
+ improved = true;
3708
+ }
3709
+ }
3710
+ const last = points[points.length - 1];
3711
+ if (last !== void 0) {
3712
+ result.push(last);
3713
+ }
3714
+ return improved ? result : null;
3715
+ }
3536
3716
  function fallbackRoute(input, defaultAnchors) {
3537
3717
  return [
3538
3718
  getEdgePort(
@@ -4029,6 +4209,7 @@ function solveDiagram(diagram, options = {}) {
4029
4209
  ];
4030
4210
  const initialContentBounds = layoutBoxes.length === 0 ? { x: 0, y: 0, width: 0} : unionBoxes(layoutBoxes);
4031
4211
  placeEvidenceBlocks(
4212
+ options.obstacleMargin ?? 0,
4032
4213
  [
4033
4214
  ...coordinatedMatrices,
4034
4215
  ...coordinatedTables,
@@ -4095,17 +4276,35 @@ function solveDiagram(diagram, options = {}) {
4095
4276
  ...baseTextAnnotations.filter(isPreRouteTextObstacle),
4096
4277
  ...frameTextAnnotation.filter(isPreRouteTextObstacle)
4097
4278
  ];
4279
+ const margin = options.obstacleMargin ?? 0;
4280
+ const softObstacles = [
4281
+ ...coordinatedTables.map((table) => expandBox(table.box, margin)),
4282
+ ...coordinatedEvidencePanels.map((panel) => expandBox(panel.box, margin))
4283
+ ];
4284
+ const hardObstacles = coordinatedMatrices.map(
4285
+ (matrix) => expandBox(matrix.box, margin)
4286
+ );
4287
+ const titleBarObstacles = [];
4288
+ if (frame !== void 0) {
4289
+ titleBarObstacles.push(expandBox(frame.titleBox, margin));
4290
+ }
4291
+ for (const swimlane of coordinatedSwimlanes) {
4292
+ for (const lane of swimlane.lanes) {
4293
+ if (lane.headerBox !== void 0 && lane.headerBox.width > 0 && lane.headerBox.height > 0) {
4294
+ titleBarObstacles.push(expandBox(lane.headerBox, margin));
4295
+ }
4296
+ }
4297
+ }
4098
4298
  const coordinatedEdges = coordinateEdges(
4099
4299
  styledEdges,
4100
4300
  nodeGeometryById,
4101
4301
  coordinatedNodes,
4102
- [...nodeGeometryById.values()].map((geometry) => geometry.obstacleBox),
4103
- [
4104
- ...coordinatedTables.map((table) => table.box),
4105
- ...coordinatedEvidencePanels.map((panel) => panel.box)
4106
- ],
4302
+ [...nodeGeometryById.values()].map(
4303
+ (geometry) => options.routingGutter === void 0 ? geometry.obstacleBox : expandBox(geometry.obstacleBox, options.routingGutter)
4304
+ ),
4305
+ [...softObstacles, ...titleBarObstacles],
4107
4306
  routingTextObstacles,
4108
- coordinatedMatrices.map((matrix) => matrix.box),
4307
+ hardObstacles,
4109
4308
  diagram.direction,
4110
4309
  options,
4111
4310
  diagnostics
@@ -4140,6 +4339,16 @@ function solveDiagram(diagram, options = {}) {
4140
4339
  options.pageBounds
4141
4340
  )
4142
4341
  );
4342
+ let degraded = false;
4343
+ const resultDiagnostics = diagnostics.map((diagnostic) => {
4344
+ if (DELIVERABILITY_DIAGNOSTIC_CODES.has(diagnostic.code)) {
4345
+ degraded = true;
4346
+ if (options.strict) {
4347
+ return { ...diagnostic, severity: "error" };
4348
+ }
4349
+ }
4350
+ return diagnostic;
4351
+ });
4143
4352
  return {
4144
4353
  id: diagram.id,
4145
4354
  ...diagram.title === void 0 ? {} : { title: diagram.title },
@@ -4151,7 +4360,8 @@ function solveDiagram(diagram, options = {}) {
4151
4360
  ...coordinatedMatrices.length === 0 ? {} : { matrices: coordinatedMatrices },
4152
4361
  ...coordinatedTables.length === 0 ? {} : { tables: coordinatedTables },
4153
4362
  ...coordinatedEvidencePanels.length === 0 ? {} : { evidencePanels: coordinatedEvidencePanels },
4154
- diagnostics,
4363
+ diagnostics: resultDiagnostics,
4364
+ degraded,
4155
4365
  bounds: frame === void 0 ? unionBoxes(boundsBase) : unionBoxes([...boundsBase, frame.box, frame.titleBox]),
4156
4366
  ...frame === void 0 ? {} : { frame },
4157
4367
  ...textAnnotations.length === 0 ? {} : { textAnnotations },
@@ -5537,16 +5747,25 @@ function blockBox(block, defaultSize) {
5537
5747
  height: block.size?.height ?? defaultSize.height
5538
5748
  };
5539
5749
  }
5540
- function placeEvidenceBlocks(blocks, contentBounds) {
5750
+ function placeEvidenceBlocks(obstacleMargin, blocks, contentBounds) {
5751
+ const margin = normalizeInsets(obstacleMargin);
5752
+ const horizontalGap = Math.max(
5753
+ DEFAULT_EVIDENCE_BLOCK_GAP,
5754
+ margin.right + margin.left
5755
+ );
5756
+ const verticalGap = Math.max(
5757
+ DEFAULT_EVIDENCE_BLOCK_GAP,
5758
+ margin.bottom + margin.top
5759
+ );
5541
5760
  let nextY = contentBounds.y;
5542
- const x = contentBounds.x + contentBounds.width + DEFAULT_EVIDENCE_BLOCK_GAP;
5761
+ const x = contentBounds.x + contentBounds.width + horizontalGap;
5543
5762
  for (const block of blocks) {
5544
5763
  if (block.position !== void 0) {
5545
5764
  continue;
5546
5765
  }
5547
5766
  block.box.x = x;
5548
5767
  block.box.y = nextY;
5549
- nextY += block.box.height + DEFAULT_EVIDENCE_BLOCK_GAP;
5768
+ nextY += block.box.height + verticalGap;
5550
5769
  }
5551
5770
  }
5552
5771
  function columnXOffsets(table, box) {
@@ -6402,9 +6621,7 @@ function edgeLabelAnchorCandidates(points, placement, layout2) {
6402
6621
  { x: placement.x, y: placement.y + offset }
6403
6622
  );
6404
6623
  }
6405
- return candidates;
6406
- }
6407
- if (segment.start.x === segment.end.x) {
6624
+ } else if (segment.start.x === segment.end.x) {
6408
6625
  const needed = layout2.box.width / 2 + EDGE_LABEL_CLEARANCE;
6409
6626
  const maxSteps = Math.max(12, Math.ceil(needed / EDGE_LABEL_CLEARANCE));
6410
6627
  for (let step = 1; step <= maxSteps; step += 1) {
@@ -6414,7 +6631,83 @@ function edgeLabelAnchorCandidates(points, placement, layout2) {
6414
6631
  { x: placement.x - offset, y: placement.y }
6415
6632
  );
6416
6633
  }
6417
- return candidates;
6634
+ } else {
6635
+ const dx = segment.end.x - segment.start.x;
6636
+ const dy = segment.end.y - segment.start.y;
6637
+ const segLen = Math.hypot(dx, dy);
6638
+ if (segLen > 0) {
6639
+ const nx = -dy / segLen;
6640
+ const ny = dx / segLen;
6641
+ const needed = (Math.abs(nx) * layout2.box.width + Math.abs(ny) * layout2.box.height) / 2 + EDGE_LABEL_CLEARANCE;
6642
+ const maxSteps = Math.max(12, Math.ceil(needed / EDGE_LABEL_CLEARANCE));
6643
+ for (let step = 1; step <= maxSteps; step += 1) {
6644
+ const offset = EDGE_LABEL_CLEARANCE * step;
6645
+ candidates.push(
6646
+ { x: placement.x + nx * offset, y: placement.y + ny * offset },
6647
+ { x: placement.x - nx * offset, y: placement.y - ny * offset }
6648
+ );
6649
+ }
6650
+ }
6651
+ }
6652
+ const totalLen = points.reduce((sum, p, idx) => {
6653
+ if (idx === 0) return 0;
6654
+ const prev = points[idx - 1];
6655
+ return sum + Math.hypot((p?.x ?? 0) - (prev?.x ?? 0), (p?.y ?? 0) - (prev?.y ?? 0));
6656
+ }, 0);
6657
+ if (totalLen > 200) {
6658
+ for (const ratio of [0.25, 0.75]) {
6659
+ const qp = labelPlacementAtRatio(points, ratio, totalLen);
6660
+ if (qp !== void 0) {
6661
+ candidates.push(qp);
6662
+ const qTargetDist = totalLen * ratio;
6663
+ let qTravelled = 0;
6664
+ let seg;
6665
+ for (let si = 1; si < points.length; si++) {
6666
+ const sp = points[si - 1];
6667
+ const sc = points[si];
6668
+ if (sp === void 0 || sc === void 0) continue;
6669
+ const sl = Math.hypot(sc.x - sp.x, sc.y - sp.y);
6670
+ if (sl <= 0) continue;
6671
+ if (qTravelled + sl >= qTargetDist) {
6672
+ seg = { start: sp, end: sc, length: sl };
6673
+ break;
6674
+ }
6675
+ qTravelled += sl;
6676
+ }
6677
+ if (seg !== void 0) {
6678
+ const segLen = Math.hypot(
6679
+ seg.end.x - seg.start.x,
6680
+ seg.end.y - seg.start.y
6681
+ );
6682
+ const qpNeeded = seg.start.y === seg.end.y ? layout2.box.height / 2 + EDGE_LABEL_CLEARANCE : seg.start.x === seg.end.x ? layout2.box.width / 2 + EDGE_LABEL_CLEARANCE : (Math.abs(seg.start.y - seg.end.y) * layout2.box.width + Math.abs(seg.end.x - seg.start.x) * layout2.box.height) / (2 * segLen) + EDGE_LABEL_CLEARANCE;
6683
+ const qpMaxSteps = Math.max(
6684
+ 12,
6685
+ Math.ceil(qpNeeded / EDGE_LABEL_CLEARANCE)
6686
+ );
6687
+ for (let step = 1; step <= qpMaxSteps; step += 1) {
6688
+ const offset = EDGE_LABEL_CLEARANCE * step;
6689
+ if (seg.start.y === seg.end.y) {
6690
+ candidates.push(
6691
+ { x: qp.x, y: qp.y - offset },
6692
+ { x: qp.x, y: qp.y + offset }
6693
+ );
6694
+ } else if (seg.start.x === seg.end.x) {
6695
+ candidates.push(
6696
+ { x: qp.x - offset, y: qp.y },
6697
+ { x: qp.x + offset, y: qp.y }
6698
+ );
6699
+ } else {
6700
+ const nx = -(seg.end.y - seg.start.y) / segLen;
6701
+ const ny = (seg.end.x - seg.start.x) / segLen;
6702
+ candidates.push(
6703
+ { x: qp.x + nx * offset, y: qp.y + ny * offset },
6704
+ { x: qp.x - nx * offset, y: qp.y - ny * offset }
6705
+ );
6706
+ }
6707
+ }
6708
+ }
6709
+ }
6710
+ }
6418
6711
  }
6419
6712
  return candidates;
6420
6713
  }
@@ -6471,6 +6764,34 @@ function nonZeroSegments2(points) {
6471
6764
  }
6472
6765
  return segments;
6473
6766
  }
6767
+ function labelPlacementAtRatio(points, ratio, totalLength) {
6768
+ if (points.length < 2 || ratio < 0 || ratio > 1) {
6769
+ return void 0;
6770
+ }
6771
+ const targetDist = totalLength * ratio;
6772
+ let travelled = 0;
6773
+ for (let idx = 1; idx < points.length; idx++) {
6774
+ const prev = points[idx - 1];
6775
+ const curr = points[idx];
6776
+ if (prev === void 0 || curr === void 0) {
6777
+ continue;
6778
+ }
6779
+ const segLen = Math.hypot(curr.x - prev.x, curr.y - prev.y);
6780
+ if (segLen <= 0) {
6781
+ continue;
6782
+ }
6783
+ if (travelled + segLen >= targetDist) {
6784
+ const t = (targetDist - travelled) / segLen;
6785
+ const offset = labelOffset2({ start: prev, end: curr, length: segLen });
6786
+ return {
6787
+ x: prev.x + (curr.x - prev.x) * t + offset.x,
6788
+ y: prev.y + (curr.y - prev.y) * t + offset.y
6789
+ };
6790
+ }
6791
+ travelled += segLen;
6792
+ }
6793
+ return void 0;
6794
+ }
6474
6795
  function labelOffset2(segment) {
6475
6796
  const offset = 10;
6476
6797
  const dx = segment.end.x - segment.start.x;
@@ -6584,7 +6905,7 @@ function isValidEdgeId(value) {
6584
6905
  return value.length > 0 && EDGE_ID_PATTERN.test(value);
6585
6906
  }
6586
6907
  var directionSchema = zod.z.enum(["TB", "LR", "BT", "RL"]);
6587
- var routeKindSchema = zod.z.enum(["orthogonal", "straight"]);
6908
+ var routeKindSchema = zod.z.enum(["orthogonal", "straight", "obstacle-avoiding"]);
6588
6909
  var outputFormatSchema = zod.z.enum(["svg", "excalidraw"]);
6589
6910
  var edgeStrokeStyleSchema = zod.z.enum(["solid", "dashed"]);
6590
6911
  var edgeArrowheadSchema = zod.z.enum(["triangle", "hollowTriangle"]);
@@ -7183,7 +7504,7 @@ function renderDiagramDsl(source, options = {}) {
7183
7504
  return { diagnostics };
7184
7505
  }
7185
7506
  const solved = solveDiagram(normalized.diagram, {
7186
- routeKind: normalized.diagram.metadata?.routeKind === "straight" ? "straight" : "orthogonal",
7507
+ routeKind: normalized.diagram.metadata?.routeKind === "straight" ? "straight" : normalized.diagram.metadata?.routeKind === "obstacle-avoiding" ? "obstacle-avoiding" : "orthogonal",
7187
7508
  ...solvePortShiftingOption(normalized.diagram.metadata?.portShifting),
7188
7509
  ...options.textMeasurer === void 0 ? {} : { textMeasurer: options.textMeasurer }
7189
7510
  });