@knowvah/dot-engine 2.3.0 → 2.4.0

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.
Files changed (118) hide show
  1. package/dist/common/arith.d.ts +12 -0
  2. package/dist/common/arith.d.ts.map +1 -1
  3. package/dist/common/edge-in-box.d.ts +31 -0
  4. package/dist/common/edge-in-box.d.ts.map +1 -0
  5. package/dist/common/htmltable-emit.d.ts +1 -1
  6. package/dist/common/htmltable-emit.d.ts.map +1 -1
  7. package/dist/common/make-label.d.ts +3 -1
  8. package/dist/common/make-label.d.ts.map +1 -1
  9. package/dist/common/poly-gencode.d.ts +12 -1
  10. package/dist/common/poly-gencode.d.ts.map +1 -1
  11. package/dist/gvc/device.d.ts.map +1 -1
  12. package/dist/gvc/emit-gates.d.ts +35 -0
  13. package/dist/gvc/emit-gates.d.ts.map +1 -0
  14. package/dist/gvc/job.d.ts +4 -0
  15. package/dist/gvc/job.d.ts.map +1 -1
  16. package/dist/gvc/viewport.d.ts +13 -0
  17. package/dist/gvc/viewport.d.ts.map +1 -1
  18. package/dist/index.js +1030 -742
  19. package/dist/index.js.map +4 -4
  20. package/dist/layout/circo/blockpath.d.ts +1 -38
  21. package/dist/layout/circo/blockpath.d.ts.map +1 -1
  22. package/dist/layout/circo/crossings.d.ts +59 -0
  23. package/dist/layout/circo/crossings.d.ts.map +1 -0
  24. package/dist/layout/dot/edge-route-chain.d.ts +5 -3
  25. package/dist/layout/dot/edge-route-chain.d.ts.map +1 -1
  26. package/dist/layout/dot/edge-route.d.ts.map +1 -1
  27. package/dist/layout/dot/index.d.ts +10 -2
  28. package/dist/layout/dot/index.d.ts.map +1 -1
  29. package/dist/layout/dot/ortho-adapter.d.ts +7 -3
  30. package/dist/layout/dot/ortho-adapter.d.ts.map +1 -1
  31. package/dist/layout/dot/pack-components.d.ts +4 -1
  32. package/dist/layout/dot/pack-components.d.ts.map +1 -1
  33. package/dist/layout/dot/splines-flat-multi.d.ts +7 -5
  34. package/dist/layout/dot/splines-flat-multi.d.ts.map +1 -1
  35. package/dist/layout/dot/splines-flat.d.ts +2 -13
  36. package/dist/layout/dot/splines-flat.d.ts.map +1 -1
  37. package/dist/layout/dot/splines-route.d.ts.map +1 -1
  38. package/dist/layout/neato/constraint-adjust.d.ts +32 -0
  39. package/dist/layout/neato/constraint-adjust.d.ts.map +1 -1
  40. package/dist/layout/neato/multispline.d.ts.map +1 -1
  41. package/dist/layout/neato/splines.d.ts.map +1 -1
  42. package/dist/layout/pack/poly-place.d.ts.map +1 -1
  43. package/dist/layout/sfdp/__fixtures__/pcp-rotate-native.d.ts +23 -0
  44. package/dist/layout/sfdp/__fixtures__/pcp-rotate-native.d.ts.map +1 -0
  45. package/dist/layout/sfdp/spring-driver.d.ts +6 -0
  46. package/dist/layout/sfdp/spring-driver.d.ts.map +1 -1
  47. package/dist/ortho/index.d.ts +4 -1
  48. package/dist/ortho/index.d.ts.map +1 -1
  49. package/dist/ortho/maze.d.ts +5 -2
  50. package/dist/ortho/maze.d.ts.map +1 -1
  51. package/dist/ortho/partition.d.ts +8 -1
  52. package/dist/ortho/partition.d.ts.map +1 -1
  53. package/dist/ortho/trap-segment.d.ts +2 -1
  54. package/dist/ortho/trap-segment.d.ts.map +1 -1
  55. package/dist/ortho/trapezoid.d.ts.map +1 -1
  56. package/dist/parser/index.d.ts +0 -7
  57. package/dist/parser/index.d.ts.map +1 -1
  58. package/dist/parser/number-scan.d.ts +31 -0
  59. package/dist/parser/number-scan.d.ts.map +1 -0
  60. package/dist/pathplan/route.d.ts.map +1 -1
  61. package/dist/pathplan/solvers.d.ts +15 -3
  62. package/dist/pathplan/solvers.d.ts.map +1 -1
  63. package/dist/render/dot/edge-draw.d.ts +12 -0
  64. package/dist/render/dot/edge-draw.d.ts.map +1 -1
  65. package/dist/render/svg-graph.d.ts +6 -5
  66. package/dist/render/svg-graph.d.ts.map +1 -1
  67. package/dist/render/svg.d.ts +2 -21
  68. package/dist/render/svg.d.ts.map +1 -1
  69. package/dist/render.js +1030 -742
  70. package/dist/render.js.map +4 -4
  71. package/dist/xdot/parse.d.ts.map +1 -1
  72. package/package.json +1 -1
  73. package/src/common/arith.ts +25 -0
  74. package/src/common/edge-in-box.ts +54 -0
  75. package/src/common/graph-init.ts +3 -3
  76. package/src/common/htmltable-emit.ts +4 -2
  77. package/src/common/make-label.ts +3 -1
  78. package/src/common/poly-gencode.ts +18 -4
  79. package/src/gvc/device.ts +8 -41
  80. package/src/gvc/edge-labels.ts +30 -13
  81. package/src/gvc/emit-gates.ts +89 -0
  82. package/src/gvc/job.ts +4 -0
  83. package/src/gvc/viewport.ts +29 -0
  84. package/src/layout/circo/blockpath.ts +6 -125
  85. package/src/layout/circo/crossings.ts +171 -0
  86. package/src/layout/dot/__fixtures__/2784.dot +1 -0
  87. package/src/layout/dot/__fixtures__/2784.native-16.1.svg +48 -0
  88. package/src/layout/dot/edge-route-chain.ts +11 -5
  89. package/src/layout/dot/edge-route.ts +19 -8
  90. package/src/layout/dot/index.ts +14 -4
  91. package/src/layout/dot/ortho-adapter.ts +11 -6
  92. package/src/layout/dot/pack-components.ts +11 -4
  93. package/src/layout/dot/splines-flat-multi.ts +21 -8
  94. package/src/layout/dot/splines-flat.ts +8 -35
  95. package/src/layout/dot/splines-route.ts +10 -2
  96. package/src/layout/dot/splines.ts +6 -6
  97. package/src/layout/neato/constraint-adjust.ts +10 -4
  98. package/src/layout/neato/multispline.ts +26 -9
  99. package/src/layout/neato/splines.ts +7 -7
  100. package/src/layout/pack/poly-place.ts +9 -2
  101. package/src/layout/sfdp/__fixtures__/pcp-rotate-native.ts +94 -0
  102. package/src/layout/sfdp/spring-driver.ts +45 -13
  103. package/src/ortho/index.ts +22 -13
  104. package/src/ortho/maze.ts +8 -2
  105. package/src/ortho/partition.ts +17 -2
  106. package/src/ortho/trap-segment.ts +47 -24
  107. package/src/ortho/trapezoid.ts +24 -15
  108. package/src/parser/dot.js +345 -380
  109. package/src/parser/dot.pegjs +25 -10
  110. package/src/parser/index.ts +15 -0
  111. package/src/parser/number-scan.ts +118 -0
  112. package/src/pathplan/route.ts +79 -34
  113. package/src/pathplan/solvers.ts +78 -50
  114. package/src/render/dot/edge-draw.ts +25 -0
  115. package/src/render/svg-graph.ts +77 -47
  116. package/src/render/svg-helpers.ts +2 -2
  117. package/src/render/svg.ts +4 -41
  118. package/src/xdot/parse.ts +19 -5
package/dist/render.js CHANGED
@@ -5086,8 +5086,8 @@ function normalizeFontName(name) {
5086
5086
  for (let i = 0; i < name.length; i++) {
5087
5087
  const ch = name[i];
5088
5088
  const code = ch.charCodeAt(0);
5089
- const isLetter = code >= 65 && code <= 90 || code >= 97 && code <= 122;
5090
- if (isLetter) result += ch.toLowerCase();
5089
+ const isLetter2 = code >= 65 && code <= 90 || code >= 97 && code <= 122;
5090
+ if (isLetter2) result += ch.toLowerCase();
5091
5091
  }
5092
5092
  return result;
5093
5093
  }
@@ -7338,7 +7338,7 @@ function interpretCRNL(str) {
7338
7338
 
7339
7339
  // src/common/make-label.ts
7340
7340
  var DEFAULT_FONTSIZE2 = 14;
7341
- var DEFAULT_FONTNAME = "Times,serif";
7341
+ var DEFAULT_FONTNAME = "Times-Roman";
7342
7342
  var DEFAULT_COLOR = "black";
7343
7343
  function getPenColor(obj) {
7344
7344
  if (obj === void 0) return void 0;
@@ -8765,6 +8765,10 @@ var RenderJob = class {
8765
8765
  format;
8766
8766
  bb = { ll: { x: 0, y: 0 }, ur: { x: 0, y: 0 } };
8767
8767
  pad = { x: 0, y: 0 };
8768
+ /** Current page clip in graph units, as setup_page computes it from the
8769
+ * viewport focus/view (see setupPageClip). Read by the SVG page translate and
8770
+ * background. @see lib/gvc/gvcjob.h:GVJ_s.clip; lib/common/emit.c:setup_page */
8771
+ clip = { ll: { x: 0, y: 0 }, ur: { x: 0, y: 0 } };
8768
8772
  /** Graph-level `margin=` (init_job_margin); page-pagination margin, distinct
8769
8773
  * from node/cluster label margin. @see lib/common/emit.c:3309-3331 */
8770
8774
  margin = { x: 0, y: 0 };
@@ -10317,11 +10321,11 @@ function emitHtmlLabel(placed, pos, renderer, job) {
10317
10321
  style: placed.style
10318
10322
  });
10319
10323
  }
10320
- for (const cell2 of placed.cells) emitHtmlCell(cell2, pos, renderer, job);
10321
10324
  emitTableRules(placed, pos, renderer, job);
10322
10325
  if (placed.border > 0) {
10323
10326
  emitBorder({ box: placed.box, pos, border: placed.border, color: placed.color, sides: placed.sides, style: placed.style }, renderer, job);
10324
10327
  }
10328
+ for (const cell2 of placed.cells) emitHtmlCell(cell2, pos, renderer, job);
10325
10329
  }
10326
10330
  if (inAnchor) endHtmlAnchor(renderer, job);
10327
10331
  if (clustersLast && initHtmlAnchor(anchorData, tblBox, renderer, job)) {
@@ -10509,6 +10513,18 @@ function fms(a, b, c) {
10509
10513
  function cround(v) {
10510
10514
  return v >= 0 ? Math.floor(v + 0.5) : Math.ceil(v - 0.5);
10511
10515
  }
10516
+ var INT64_MAX = 2n ** 63n - 1n;
10517
+ var INT64_MIN = -(2n ** 63n);
10518
+ var TWO_POW_63 = 2 ** 63;
10519
+ function croundNarrow32(v) {
10520
+ const r = cround(v);
10521
+ let i64;
10522
+ if (Number.isNaN(r)) i64 = 0n;
10523
+ else if (r >= TWO_POW_63) i64 = INT64_MAX;
10524
+ else if (r < -TWO_POW_63) i64 = INT64_MIN;
10525
+ else i64 = BigInt(r);
10526
+ return Number(BigInt.asIntN(32, i64));
10527
+ }
10512
10528
  function RADIANS(deg) {
10513
10529
  return deg / 180 * Math.PI;
10514
10530
  }
@@ -11346,6 +11362,8 @@ function parseSegs(colorlist) {
11346
11362
  }
11347
11363
 
11348
11364
  // src/util/math.ts
11365
+ var INT32_MAX = 2147483647;
11366
+ var INT32_MIN = -2147483648;
11349
11367
  function isExactlyEqual(a, b) {
11350
11368
  const buf = new ArrayBuffer(16);
11351
11369
  const dv = new DataView(buf);
@@ -11357,6 +11375,11 @@ function isExactlyEqual(a, b) {
11357
11375
  }
11358
11376
  return true;
11359
11377
  }
11378
+ function d2i(v) {
11379
+ if (v > INT32_MAX) return INT32_MAX;
11380
+ if (v < INT32_MIN) return INT32_MIN;
11381
+ return Math.trunc(v);
11382
+ }
11360
11383
 
11361
11384
  // src/common/colorData.ts
11362
11385
  var COLOR_LIB = [
@@ -14568,9 +14591,12 @@ function isMulticolor(fillcolor) {
14568
14591
  return fillcolor.includes(":");
14569
14592
  }
14570
14593
  function renderEllipse(ring, coord, renderer, job, filled) {
14571
- const rx = Math.abs((ring[1].x - ring[0].x) / 2);
14572
- const ry = Math.abs((ring[1].y - ring[0].y) / 2);
14573
- const center = transformPoint(coord, job);
14594
+ const af0 = { x: ring[0].x + coord.x, y: ring[0].y + coord.y };
14595
+ const af1 = { x: ring[1].x + coord.x, y: ring[1].y + coord.y };
14596
+ const mid = { x: (af0.x + af1.x) / 2, y: (af0.y + af1.y) / 2 };
14597
+ const rx = af1.x - mid.x;
14598
+ const ry = af1.y - mid.y;
14599
+ const center = transformPoint(mid, job);
14574
14600
  renderer.ellipse(center, rx, ry, filled, job);
14575
14601
  }
14576
14602
  function renderPolygon(ring, coord, renderer, job, filled) {
@@ -18173,7 +18199,7 @@ var BGCOLOR_TRANSPARENT = "\0transparent";
18173
18199
  function formatG(n) {
18174
18200
  return String(parseFloat(n.toPrecision(6)));
18175
18201
  }
18176
- function emitSvgTag(job) {
18202
+ function emitSvgTag(job, svgid = "") {
18177
18203
  const bb = job.bb;
18178
18204
  const szx = bb.ur.x - bb.ll.x + 2 * job.pad.x;
18179
18205
  const szy = bb.ur.y - bb.ll.y + 2 * job.pad.y;
@@ -18182,16 +18208,20 @@ function emitSvgTag(job) {
18182
18208
  const rotated = job.rotation !== 0;
18183
18209
  const pageX = rotated ? viewY : viewX;
18184
18210
  const pageY = rotated ? viewX : viewY;
18185
- const w = cround(pageX + 2 * job.margin.x);
18186
- const h = cround(pageY + 2 * job.margin.y);
18211
+ const w = croundNarrow32(pageX + 2 * job.margin.x);
18212
+ const h = croundNarrow32(pageY + 2 * job.margin.y);
18187
18213
  job.write('<svg width="' + String(w) + 'pt" height="' + String(h) + 'pt"\n');
18188
- const vbLLx = cround(job.margin.x);
18189
- const vbLLy = cround(job.margin.y);
18190
- const vbURx = cround(job.margin.x + pageX);
18191
- const vbURy = cround(job.margin.y + pageY);
18214
+ const vbLLx = croundNarrow32(job.margin.x);
18215
+ const vbLLy = croundNarrow32(job.margin.y);
18216
+ const vbURx = croundNarrow32(job.margin.x + pageX);
18217
+ const vbURy = croundNarrow32(job.margin.y + pageY);
18192
18218
  job.write(' viewBox="' + String(vbLLx) + ".00 " + String(vbLLy) + ".00 " + String(vbURx) + ".00 " + String(vbURy) + '.00"\n');
18193
18219
  job.write(' xmlns="http://www.w3.org/2000/svg"');
18194
- job.write(' xmlns:xlink="http://www.w3.org/1999/xlink">\n');
18220
+ job.write(' xmlns:xlink="http://www.w3.org/1999/xlink"');
18221
+ if (svgid !== void 0 && svgid.length > 0) {
18222
+ job.write(' id="' + escapeXmlTitle(svgid) + '"');
18223
+ }
18224
+ job.write(">\n");
18195
18225
  }
18196
18226
  function emitGraphGroupOpen(graphId, classStr, tx, ty, job) {
18197
18227
  const sx = formatG(job.scale.x);
@@ -18215,12 +18245,12 @@ function resolveGraphBgcolor(bgcolorAttr) {
18215
18245
  const solid = grad !== null ? grad[0] : bgcolorAttr;
18216
18246
  return colorPaint(resolveRenderColor(solid));
18217
18247
  }
18218
- function emitGraphBackground(bb, resolvedColor, job) {
18248
+ function emitGraphBackground(clip, resolvedColor, job) {
18219
18249
  if (resolvedColor === BGCOLOR_TRANSPARENT) return;
18220
- const left2 = bb.ll.x - job.pad.x;
18221
- const right2 = bb.ur.x + job.pad.x;
18222
- const top = -(bb.ur.y + job.pad.y);
18223
- const bottom = -(bb.ll.y - job.pad.y);
18250
+ const left2 = clip.ll.x;
18251
+ const right2 = clip.ur.x;
18252
+ const top = -clip.ur.y;
18253
+ const bottom = -clip.ll.y;
18224
18254
  const corners = [
18225
18255
  [left2, bottom],
18226
18256
  [left2, top],
@@ -18237,11 +18267,11 @@ function emitGraphBackground(bb, resolvedColor, job) {
18237
18267
  });
18238
18268
  job.write('"/>\n');
18239
18269
  }
18240
- function bgGradientPts(bb, pad) {
18241
- const left2 = bb.ll.x - pad.x;
18242
- const right2 = bb.ur.x + pad.x;
18243
- const bottom = bb.ll.y - pad.y;
18244
- const top = bb.ur.y + pad.y;
18270
+ function bgGradientPts(clip) {
18271
+ const left2 = clip.ll.x;
18272
+ const right2 = clip.ur.x;
18273
+ const bottom = clip.ll.y;
18274
+ const top = clip.ur.y;
18245
18275
  return [
18246
18276
  { x: left2, y: bottom },
18247
18277
  { x: left2, y: top },
@@ -18249,11 +18279,11 @@ function bgGradientPts(bb, pad) {
18249
18279
  { x: right2, y: bottom }
18250
18280
  ];
18251
18281
  }
18252
- function writeGradientPolygon(bb, id, job) {
18253
- const left2 = bb.ll.x - job.pad.x;
18254
- const right2 = bb.ur.x + job.pad.x;
18255
- const top = -(bb.ur.y + job.pad.y);
18256
- const bottom = -(bb.ll.y - job.pad.y);
18282
+ function writeGradientPolygon(clip, id, job) {
18283
+ const left2 = clip.ll.x;
18284
+ const right2 = clip.ur.x;
18285
+ const top = -clip.ur.y;
18286
+ const bottom = -clip.ll.y;
18257
18287
  const corners = [
18258
18288
  [left2, bottom],
18259
18289
  [left2, top],
@@ -18270,7 +18300,7 @@ function writeGradientPolygon(bb, id, job) {
18270
18300
  });
18271
18301
  job.write('"/>\n');
18272
18302
  }
18273
- function emitGradientBackground(bb, spec, job) {
18303
+ function emitGradientBackground(clip, spec, job) {
18274
18304
  const obj = createObjState(0 /* RootGraph */);
18275
18305
  obj.id = "graph0";
18276
18306
  obj.fillColor = resolveRenderColor(spec.fillColor);
@@ -18285,10 +18315,10 @@ function emitGradientBackground(bb, spec, job) {
18285
18315
  emitRadialGradient(job, gid);
18286
18316
  } else {
18287
18317
  gid = gradientId("graph0", "l", job.linearGradId++);
18288
- emitLinearGradient(job, bgGradientPts(bb, job.pad), gid);
18318
+ emitLinearGradient(job, bgGradientPts(clip), gid);
18289
18319
  }
18290
18320
  job.popObj();
18291
- writeGradientPolygon(bb, gid, job);
18321
+ writeGradientPolygon(clip, gid, job);
18292
18322
  }
18293
18323
  function resolveBgGradientSpec(g, bgcolorAttr) {
18294
18324
  const stop = findStopColor(bgcolorAttr);
@@ -18298,17 +18328,17 @@ function resolveBgGradientSpec(g, bgcolorAttr) {
18298
18328
  const angle = angleStr ? parseInt(angleStr, 10) || 0 : 0;
18299
18329
  return { fillColor: stop.fillColor, stopColor: stop.stopColor, frac: stop.frac, angle, radial: flags.radial };
18300
18330
  }
18301
- function emitBgcolorBackground(g, bb, bgcolorAttr, job) {
18331
+ function emitBgcolorBackground(g, clip, bgcolorAttr, job) {
18302
18332
  if (!bgcolorAttr || bgcolorAttr.length === 0 || bgcolorAttr === "transparent") {
18303
- emitGraphBackground(bb, resolveGraphBgcolor(bgcolorAttr), job);
18333
+ emitGraphBackground(clip, resolveGraphBgcolor(bgcolorAttr), job);
18304
18334
  return;
18305
18335
  }
18306
18336
  const spec = resolveBgGradientSpec(g, bgcolorAttr);
18307
18337
  if (spec !== null) {
18308
- emitGradientBackground(bb, spec, job);
18338
+ emitGradientBackground(clip, spec, job);
18309
18339
  return;
18310
18340
  }
18311
- emitGraphBackground(bb, resolveGraphBgcolor(bgcolorAttr), job);
18341
+ emitGraphBackground(clip, resolveGraphBgcolor(bgcolorAttr), job);
18312
18342
  }
18313
18343
  function svgBeginGraph(g, job) {
18314
18344
  job.devscale = { x: 1, y: -1 };
@@ -18322,13 +18352,23 @@ function svgBeginGraph(g, job) {
18322
18352
  }
18323
18353
  job.write(SVG_DOCTYPE);
18324
18354
  job.write(SVG_GENERATOR_COMMENT);
18325
- emitSvgTag(job);
18355
+ const comment = g.attrs.get("comment");
18356
+ if (comment !== void 0 && comment.length > 0) svgComment(comment, job);
18357
+ emitTitlePagesComment(g, job);
18358
+ emitSvgTag(job, g.attrs.get("svgid"));
18359
+ }
18360
+ function emitTitlePagesComment(g, job) {
18361
+ job.write("<!--");
18362
+ if (g.name.length > 0 && g.name[0] !== "%") {
18363
+ job.write(" Title: " + escapeXmlTitle(g.name));
18364
+ }
18365
+ job.write(" Pages: 1 -->\n");
18326
18366
  }
18327
18367
  function svgBeginPage(g, job) {
18328
- const bb = job.bb;
18368
+ const clip = job.clip;
18329
18369
  const z = job.scale.x;
18330
- const tx = job.rotation !== 0 ? -(bb.ur.x + job.pad.x) - job.margin.x / z : job.pad.x + job.margin.x / z;
18331
- const ty = bb.ur.y + job.pad.y + job.margin.y / z;
18370
+ const tx = job.rotation !== 0 ? -clip.ur.x - job.margin.x / z : -clip.ll.x + job.margin.x / z;
18371
+ const ty = clip.ur.y + job.margin.y / z;
18332
18372
  emitGraphGroupOpen(
18333
18373
  job.idLayerPrefix() + svgGraphId(g, job),
18334
18374
  svgGraphClass(g),
@@ -18339,7 +18379,7 @@ function svgBeginPage(g, job) {
18339
18379
  emitGraphTitle(g, job);
18340
18380
  }
18341
18381
  function svgPageBackground(g, job) {
18342
- emitBgcolorBackground(g, job.bb, g.attrs.get("bgcolor"), job);
18382
+ emitBgcolorBackground(g, job.clip, g.attrs.get("bgcolor"), job);
18343
18383
  }
18344
18384
  function svgEndPage(job) {
18345
18385
  job.write("</g>\n");
@@ -18675,7 +18715,7 @@ function svgPolyline(pts, job) {
18675
18715
  job.write('"/>\n');
18676
18716
  }
18677
18717
  function svgComment(text, job) {
18678
- job.write("<!-- " + escapeXml(text) + " -->\n");
18718
+ job.write("<!-- " + escapeXmlTitle(text) + " -->\n");
18679
18719
  }
18680
18720
  function svgEdgePath(e, job) {
18681
18721
  const spl = e.info.spl;
@@ -18862,6 +18902,22 @@ function initJobViewportZoom(bb, size, pad) {
18862
18902
  if (drawingNeedsFit(size, szx, szy)) return Math.min(size.x / szx, size.y / szy);
18863
18903
  return 1;
18864
18904
  }
18905
+ function setupPageClip(bb, size, pad, z) {
18906
+ const jbLL = { x: bb.ll.x - pad.x, y: bb.ll.y - pad.y };
18907
+ const jbUR = { x: bb.ur.x + pad.x, y: bb.ur.y + pad.y };
18908
+ const sz = { x: jbUR.x - jbLL.x, y: jbUR.y - jbLL.y };
18909
+ if (size !== null && size.x > 1e-3 && size.y > 1e-3) {
18910
+ if (sz.x <= 1e-3) sz.x = size.x;
18911
+ if (sz.y <= 1e-3) sz.y = size.y;
18912
+ }
18913
+ const focus = { x: 0.5 * (bb.ll.x + bb.ur.x), y: 0.5 * (bb.ll.y + bb.ur.y) };
18914
+ const pageSize = { x: z * sz.x / z, y: z * sz.y / z };
18915
+ const ll = {
18916
+ x: focus.x + pageSize.x * (0 - 1 / 2),
18917
+ y: focus.y + pageSize.y * (0 - 1 / 2)
18918
+ };
18919
+ return { ll, ur: { x: ll.x + pageSize.x, y: ll.y + pageSize.y } };
18920
+ }
18865
18921
 
18866
18922
  // src/gvc/anchor.ts
18867
18923
  function attr(attrs, key) {
@@ -19373,10 +19429,22 @@ function renderClusterLabel(sg, renderer, job) {
19373
19429
  renderOneLabel(sg.info.label, renderer, job, false);
19374
19430
  }
19375
19431
 
19376
- // src/gvc/device.ts
19377
- function labelTextOf2(lp) {
19378
- return lp?.text ?? null;
19432
+ // src/common/edge-in-box.ts
19433
+ function overlapLabel(lp, b) {
19434
+ const sx = lp.dimen.x / 2;
19435
+ const sy = lp.dimen.y / 2;
19436
+ const bb = {
19437
+ ll: { x: lp.pos.x - sx, y: lp.pos.y - sy },
19438
+ ur: { x: lp.pos.x + sx, y: lp.pos.y + sy }
19439
+ };
19440
+ return boxOverlap(b, bb);
19441
+ }
19442
+ function edgeHasDrawableContent(e, clip) {
19443
+ const i = e.info;
19444
+ return i.spl !== void 0 || i.label !== void 0 && i.label.set && overlapLabel(i.label, clip) || i.xlabel !== void 0 || i.head_label !== void 0 || i.tail_label !== void 0;
19379
19445
  }
19446
+
19447
+ // src/gvc/emit-gates.ts
19380
19448
  function nodeBBox(n) {
19381
19449
  const { coord, lw, rw, ht } = n.info;
19382
19450
  return {
@@ -19391,6 +19459,26 @@ function nodeInBox(n, job) {
19391
19459
  };
19392
19460
  return boxOverlap(nodeBBox(n), clip);
19393
19461
  }
19462
+ function gvrenderComment(renderer, job, str) {
19463
+ if (str === void 0 || str.length === 0) return;
19464
+ renderer.comment?.(str, job);
19465
+ }
19466
+ function emitNodeComments(n, renderer, job) {
19467
+ gvrenderComment(renderer, job, n.name);
19468
+ gvrenderComment(renderer, job, nodeAttr(n, n.root, "comment"));
19469
+ }
19470
+ function emitEdgeComments(e, renderer, job) {
19471
+ if (!edgeHasDrawableContent(e, job.bb)) return;
19472
+ const kind = e.head.root.kind;
19473
+ const op = kind === "directed" || kind === "strict-directed" ? "->" : "--";
19474
+ gvrenderComment(renderer, job, e.tail.name + op + e.head.name);
19475
+ gvrenderComment(renderer, job, e.attrs.get("comment"));
19476
+ }
19477
+
19478
+ // src/gvc/device.ts
19479
+ function labelTextOf2(lp) {
19480
+ return lp?.text ?? null;
19481
+ }
19394
19482
  function emitNodeBody(n, renderer, job) {
19395
19483
  setHtmlAnchorObj(svgNodeId(n, job), labelTextOf2(n.info.label), job.obj ?? void 0);
19396
19484
  setHtmlObjImgscale(nodeAttr(n, n.root, "imagescale"));
@@ -19406,6 +19494,7 @@ function renderNode(n, renderer, job, done) {
19406
19494
  if (done.has(n)) return;
19407
19495
  done.add(n);
19408
19496
  if (!nodeInBox(n, job)) return;
19497
+ emitNodeComments(n, renderer, job);
19409
19498
  const nodeStyle = nodeAttr(n, n.root, "style");
19410
19499
  if (parseStyleFlags(nodeStyle).invis) return;
19411
19500
  if (!isPointNode(n) && styleHasInvisibleAlias(nodeStyle)) return;
@@ -19431,6 +19520,7 @@ function setEdgePen(e, job) {
19431
19520
  obj.rawStyle = styleTokens(e.attrs.get("style"));
19432
19521
  }
19433
19522
  function renderEdge(e, renderer, job) {
19523
+ emitEdgeComments(e, renderer, job);
19434
19524
  const edgeStyle = e.attrs.get("style");
19435
19525
  if (parseStyleFlags(edgeStyle).invis || styleHasInvisibleAlias(edgeStyle)) return;
19436
19526
  const obj = createObjState(3 /* Edge */);
@@ -19544,7 +19634,9 @@ function render(ctx, g, format, inlineImages = false) {
19544
19634
  job.bb = g.info.bb;
19545
19635
  job.pad = parseGraphPad(g.attrs.get("pad"));
19546
19636
  job.margin = parseGraphMargin(g.attrs.get("margin"));
19547
- const z = initJobViewportZoom(job.bb, parseDrawingSize(g.attrs.get("size")), job.pad);
19637
+ const drawingSize = parseDrawingSize(g.attrs.get("size"));
19638
+ const z = initJobViewportZoom(job.bb, drawingSize, job.pad);
19639
+ job.clip = setupPageClip(job.bb, drawingSize, job.pad, z);
19548
19640
  const drawingDpi = lateDouble(
19549
19641
  g.attrs.get("dpi"),
19550
19642
  lateDouble(g.attrs.get("resolution"), 0, 0),
@@ -25162,56 +25254,63 @@ function setEndTheta(P, e, merge) {
25162
25254
 
25163
25255
  // src/pathplan/solvers.ts
25164
25256
  var EPS2 = 1e-7;
25165
- var Solver = class _Solver {
25166
- static aeq0(x) {
25167
- return x < EPS2 && x > -EPS2;
25168
- }
25169
- static solve1(c, r) {
25170
- if (_Solver.aeq0(c[1])) return _Solver.aeq0(c[0]) ? 4 : 0;
25171
- r[0] = -c[0] / c[1];
25172
- return 1;
25173
- }
25174
- static solve2(c, r) {
25175
- if (_Solver.aeq0(c[2])) return _Solver.solve1(c, r);
25176
- const b2a = c[1] / (2 * c[2]);
25177
- const disc = b2a * b2a - c[0] / c[2];
25178
- if (disc < 0) return 0;
25179
- if (disc > 0) {
25180
- r[0] = -b2a + Math.sqrt(disc);
25181
- r[1] = -2 * b2a - r[0];
25182
- return 2;
25183
- }
25184
- r[0] = -b2a;
25185
- return 1;
25186
- }
25187
- static solve3neg(disc, q, b3a, r) {
25188
- const rr = 0.5 * Math.sqrt(-disc + q * q);
25257
+ function aeq02(x) {
25258
+ return x < EPS2 && x > -EPS2;
25259
+ }
25260
+ function solve3(coeff, roots) {
25261
+ const a = coeff[3], b = coeff[2], c = coeff[1], d = coeff[0];
25262
+ if (aeq02(a)) return solve2(coeff, roots);
25263
+ const bOver3a = b / (3 * a), cOverA = c / a, dOverA = d / a;
25264
+ let p = bOver3a * bOver3a;
25265
+ const q = dOverA + fma(2 * bOver3a, p, -(bOver3a * cOverA));
25266
+ p = cOverA / 3 - p;
25267
+ const disc = fma(q, q, 4 * p * p * p);
25268
+ let rootn;
25269
+ if (disc < 0) {
25270
+ const r = 0.5 * Math.sqrt(fma(q, q, -disc));
25189
25271
  const theta = Math.atan2(Math.sqrt(-disc), -q);
25190
- const temp = 2 * Math.cbrt(rr);
25191
- r[0] = temp * Math.cos(theta / 3) - b3a;
25192
- r[1] = temp * Math.cos((theta + 2 * Math.PI) / 3) - b3a;
25193
- r[2] = temp * Math.cos((theta - 2 * Math.PI) / 3) - b3a;
25194
- return 3;
25272
+ const temp = 2 * Math.cbrt(r);
25273
+ roots[0] = temp * Math.cos(theta / 3);
25274
+ roots[1] = temp * Math.cos((theta + Math.PI + Math.PI) / 3);
25275
+ roots[2] = temp * Math.cos((theta - Math.PI - Math.PI) / 3);
25276
+ rootn = 3;
25277
+ } else {
25278
+ const alpha = 0.5 * (Math.sqrt(disc) - q);
25279
+ const beta = -q - alpha;
25280
+ roots[0] = Math.cbrt(alpha) + Math.cbrt(beta);
25281
+ if (disc > 0) rootn = 1;
25282
+ else {
25283
+ roots[1] = roots[2] = -0.5 * roots[0];
25284
+ rootn = 3;
25285
+ }
25195
25286
  }
25196
- static solve3pos(disc, q, b3a, r) {
25197
- const al = 0.5 * (Math.sqrt(disc) - q);
25198
- r[0] = Math.cbrt(al) + Math.cbrt(-q - al) - b3a;
25199
- if (disc > 0) return 1;
25200
- r[1] = r[2] = -0.5 * (r[0] + b3a) - b3a;
25201
- return 3;
25287
+ for (let i = 0; i < rootn; i++) roots[i] -= bOver3a;
25288
+ return rootn;
25289
+ }
25290
+ function solve2(coeff, roots) {
25291
+ const a = coeff[2], b = coeff[1], c = coeff[0];
25292
+ if (aeq02(a)) return solve1(coeff, roots);
25293
+ const bOver2a = b / (2 * a);
25294
+ const cOverA = c / a;
25295
+ const disc = fma(bOver2a, bOver2a, -cOverA);
25296
+ if (disc < 0) {
25297
+ return 0;
25298
+ } else if (disc > 0) {
25299
+ roots[0] = -bOver2a + Math.sqrt(disc);
25300
+ roots[1] = fma(-2, bOver2a, -roots[0]);
25301
+ return 2;
25202
25302
  }
25203
- static solve3(c, r) {
25204
- const a = c[3], b = c[2], cv = c[1], d = c[0];
25205
- if (_Solver.aeq0(a)) return _Solver.solve2(c, r);
25206
- const b3a = b / (3 * a), p0 = b3a * b3a;
25207
- const q = 2 * b3a * p0 - b3a * cv / a + d / a;
25208
- const p = cv / (3 * a) - p0;
25209
- const disc = q * q + 4 * p * p * p;
25210
- return disc < 0 ? _Solver.solve3neg(disc, q, b3a, r) : _Solver.solve3pos(disc, q, b3a, r);
25303
+ roots[0] = -bOver2a;
25304
+ return 1;
25305
+ }
25306
+ function solve1(coeff, roots) {
25307
+ const a = coeff[1], b = coeff[0];
25308
+ if (aeq02(a)) {
25309
+ if (aeq02(b)) return 4;
25310
+ return 0;
25211
25311
  }
25212
- };
25213
- function solve3(coeff, roots) {
25214
- return Solver.solve3(coeff, roots);
25312
+ roots[0] = -b / a;
25313
+ return 1;
25215
25314
  }
25216
25315
 
25217
25316
  // src/pathplan/route.ts
@@ -25233,16 +25332,19 @@ var RouteHelper = class _RouteHelper {
25233
25332
  static B3(t) {
25234
25333
  return t * t * t;
25235
25334
  }
25335
+ /** @see lib/pathplan/route.c:B01 */
25236
25336
  static B01(t) {
25237
25337
  const u = 1 - t;
25238
- return u * u * (u + 3 * t);
25338
+ return u * u * fma(3, t, u);
25239
25339
  }
25340
+ /** @see lib/pathplan/route.c:B23 */
25240
25341
  static B23(t) {
25241
25342
  const u = 1 - t;
25242
- return t * t * (3 * u + t);
25343
+ return t * t * fma(3, u, t);
25243
25344
  }
25345
+ /** @see lib/pathplan/route.c:normv */
25244
25346
  static normv(v) {
25245
- const d = v.x * v.x + v.y * v.y;
25347
+ const d = fma(v.x, v.x, v.y * v.y);
25246
25348
  if (d > 1e-6) {
25247
25349
  const s = Math.sqrt(d);
25248
25350
  return { x: v.x / s, y: v.y / s };
@@ -25258,20 +25360,28 @@ var RouteHelper = class _RouteHelper {
25258
25360
  static ptScale(p, c) {
25259
25361
  return { x: p.x * c, y: p.y * c };
25260
25362
  }
25363
+ /** @see lib/pathplan/route.c:dot */
25261
25364
  static ptDot(a, b) {
25262
- return a.x * b.x + a.y * b.y;
25365
+ return fma(a.x, b.x, a.y * b.y);
25263
25366
  }
25367
+ /** @see lib/pathplan/route.c:dist (libm hypot, no contraction) */
25264
25368
  static ptDist(a, b) {
25265
- return Math.hypot(a.x - b.x, a.y - b.y);
25369
+ return libmHypot(a.x - b.x, a.y - b.y);
25266
25370
  }
25267
25371
  static distN(pts) {
25268
25372
  let rv = 0;
25269
25373
  for (let i = 1; i < pts.length; i++) rv += _RouteHelper.ptDist(pts[i], pts[i - 1]);
25270
25374
  return rv;
25271
25375
  }
25376
+ /**
25377
+ * The cubic's coefficients come out of catastrophic cancellation when the
25378
+ * spline is tangent to a barrier (tests/2646.dot), so clang's contraction
25379
+ * here decides solve3's root count; mirror it exactly.
25380
+ * @see lib/pathplan/route.c:points2coeff
25381
+ */
25272
25382
  static points2coeff(v0, v1, v2, v3, c) {
25273
- c[3] = v3 + 3 * v1 - (v0 + 3 * v2);
25274
- c[2] = 3 * v0 + 3 * v2 - 6 * v1;
25383
+ c[3] = fma(3, v1, v3) - fma(3, v2, v0);
25384
+ c[2] = fma(-6, v1, fma(3, v0, 3 * v2));
25275
25385
  c[1] = 3 * (v1 - v0);
25276
25386
  c[0] = v0;
25277
25387
  }
@@ -25311,7 +25421,7 @@ var RouteHelper = class _RouteHelper {
25311
25421
  const tv = xr[i];
25312
25422
  if (tv >= 0 && tv <= 1) {
25313
25423
  _RouteHelper.points2coeff(sps[0].y, sps[1].y, sps[2].y, sps[3].y, sc);
25314
- const sv = (sc[0] + tv * (sc[1] + tv * (sc[2] + tv * sc[3])) - lc.yc0) / lc.yc1;
25424
+ const sv = (fma(tv, fma(tv, fma(tv, sc[3], sc[2]), sc[1]), sc[0]) - lc.yc0) / lc.yc1;
25315
25425
  if (sv >= 0 && sv <= 1) _RouteHelper.addRoot(tv, acc);
25316
25426
  }
25317
25427
  }
@@ -25321,25 +25431,26 @@ var RouteHelper = class _RouteHelper {
25321
25431
  const sc = [0, 0, 0, 0], xr = [0, 0, 0];
25322
25432
  const rat = lc.yc1 / lc.xc1;
25323
25433
  _RouteHelper.points2coeff(
25324
- sps[0].y - rat * sps[0].x,
25325
- sps[1].y - rat * sps[1].x,
25326
- sps[2].y - rat * sps[2].x,
25327
- sps[3].y - rat * sps[3].x,
25434
+ fms(rat, sps[0].x, sps[0].y),
25435
+ fms(rat, sps[1].x, sps[1].y),
25436
+ fms(rat, sps[2].x, sps[2].y),
25437
+ fms(rat, sps[3].x, sps[3].y),
25328
25438
  sc
25329
25439
  );
25330
- sc[0] += rat * lc.xc0 - lc.yc0;
25440
+ sc[0] += fma(rat, lc.xc0, -lc.yc0);
25331
25441
  const xn = solve3(sc, xr);
25332
25442
  if (xn === 4) return 4;
25333
25443
  for (let i = 0; i < xn; i++) {
25334
25444
  const tv = xr[i];
25335
25445
  if (tv >= 0 && tv <= 1) {
25336
25446
  _RouteHelper.points2coeff(sps[0].x, sps[1].x, sps[2].x, sps[3].x, sc);
25337
- const sv = (sc[0] + tv * (sc[1] + tv * (sc[2] + tv * sc[3])) - lc.xc0) / lc.xc1;
25447
+ const sv = (fma(tv, fma(tv, fma(tv, sc[3], sc[2]), sc[1]), sc[0]) - lc.xc0) / lc.xc1;
25338
25448
  if (sv >= 0 && sv <= 1) _RouteHelper.addRoot(tv, acc);
25339
25449
  }
25340
25450
  }
25341
25451
  return acc.n;
25342
25452
  }
25453
+ /** @see lib/pathplan/route.c:splineintersectsline */
25343
25454
  static splineIntersectsLine(sps, lps, roots) {
25344
25455
  const lc = {
25345
25456
  xc0: lps[0].x,
@@ -25390,8 +25501,9 @@ var RouteHelper = class _RouteHelper {
25390
25501
  x0 += _RouteHelper.ptDot(tnas[i].a[0], tmp);
25391
25502
  x1 += _RouteHelper.ptDot(tnas[i].a[1], tmp);
25392
25503
  }
25393
- const det01 = c00 * c11 - c01 * c01;
25394
- const detX1 = x0 * c11 - x1 * c01, det0X = c00 * x1 - c01 * x0;
25504
+ const det01 = fma(c00, c11, -(c01 * c01));
25505
+ const det0X = fma(c00, x1, -(c01 * x0));
25506
+ const detX1 = fma(x0, c11, -(x1 * c01));
25395
25507
  if (Math.abs(det01) >= 1e-6) {
25396
25508
  scale0 = detX1 / det01;
25397
25509
  scale3 = det0X / det01;
@@ -25415,6 +25527,27 @@ var RouteHelper = class _RouteHelper {
25415
25527
  }
25416
25528
  return tnas;
25417
25529
  }
25530
+ /**
25531
+ * The max-deviation split of `reallyroutespline` (route.c:130-143): the
25532
+ * interior polyline point farthest from the fitted bezier.
25533
+ *
25534
+ * Faithful contract. On a geometrically symmetric channel two interior
25535
+ * deviations tie to within an ulp, so the split point (and the whole
25536
+ * spline) is decided by C's exact arithmetic, which this mirrors bit for
25537
+ * bit against the native arm64 oracle:
25538
+ * - `dist` is libm `hypot` (route.c:448) -> `libmHypot` via `ptDist`;
25539
+ * - the test is C's strict `(d = dist(p, inps[i])) > maxd` (route.c:139),
25540
+ * so an exact tie keeps the first index;
25541
+ * - clang's default `-ffp-contract=on` fuses the bezier eval at
25542
+ * route.c:137-138 as `fma(B3,p2, fma(B2,cp2, fma(B0,p1, B1*cp1)))`; the
25543
+ * B0..B3 weights and cp1/cp2 (route.c:130-131) are not fused. Fusing the
25544
+ * other product first is NOT equivalent (flips pt-issue-23-w9 and 32).
25545
+ * C is therefore not translation-equivariant on such ties (the winner
25546
+ * depends on absolute-coordinate rounding), and neither is this port.
25547
+ * This supersedes the former tolerant tie-break (accepted divergence A3).
25548
+ * Contraction map: .agent-notes/pathplan-fma-contraction-map.md.
25549
+ * @see lib/pathplan/route.c:reallyroutespline
25550
+ */
25418
25551
  static findMaxDev(inps, tnas, ends) {
25419
25552
  const { p0, v0, p1, v1 } = ends;
25420
25553
  const cp1 = _RouteHelper.ptAdd(p0, _RouteHelper.ptScale(v0, 1 / 3));
@@ -25422,10 +25555,12 @@ var RouteHelper = class _RouteHelper {
25422
25555
  let maxi = -1, maxd = -1;
25423
25556
  for (let i = 1; i < inps.length - 1; i++) {
25424
25557
  const t = tnas[i].t;
25425
- const px = _RouteHelper.B0(t) * p0.x + _RouteHelper.B1(t) * cp1.x + _RouteHelper.B2(t) * cp2.x + _RouteHelper.B3(t) * p1.x;
25426
- const py = _RouteHelper.B0(t) * p0.y + _RouteHelper.B1(t) * cp1.y + _RouteHelper.B2(t) * cp2.y + _RouteHelper.B3(t) * p1.y;
25558
+ const b0 = _RouteHelper.B0(t), b1 = _RouteHelper.B1(t);
25559
+ const b2 = _RouteHelper.B2(t), b3 = _RouteHelper.B3(t);
25560
+ const px = fma(b3, p1.x, fma(b2, cp2.x, fma(b0, p0.x, b1 * cp1.x)));
25561
+ const py = fma(b3, p1.y, fma(b2, cp2.y, fma(b0, p0.y, b1 * cp1.y)));
25427
25562
  const d = _RouteHelper.ptDist({ x: px, y: py }, inps[i]);
25428
- if (d > maxd * (1 + 1e-10) + 1e-10) {
25563
+ if (d > maxd) {
25429
25564
  maxd = d;
25430
25565
  maxi = i;
25431
25566
  }
@@ -27156,7 +27291,7 @@ function routeMultiRankEdgeFaithful(g, e) {
27156
27291
  }
27157
27292
  const segs = chainSegments(e);
27158
27293
  if (segs.length === 0 || segs[segs.length - 1].head !== e.head) return null;
27159
- return routeChainSegmented(g, segs[0], segs[segs.length - 1], segs);
27294
+ return routeChainSegmented(g, segs[0], segs[segs.length - 1], segs) ?? "lost";
27160
27295
  }
27161
27296
  function entryRunSegments(e) {
27162
27297
  const segs = [e];
@@ -27228,7 +27363,10 @@ function routeBackEdge(e, _tailBox, _headBox, g) {
27228
27363
  if (segs.length < 2 || segs[segs.length - 1].head !== e.tail) return;
27229
27364
  const fwdEdge = makeFwdEdge(e);
27230
27365
  const fwd = routeChainSegmented(g, segs[0], segs[segs.length - 1], segs);
27231
- if (fwd === null) return;
27366
+ if (fwd === null) {
27367
+ e.info.lost = true;
27368
+ return;
27369
+ }
27232
27370
  clipAndInstall(fwdEdge, fwdEdge.head, fwd, fwd.length, buildDotSinfo());
27233
27371
  if (swapEndsP(e)) swapEdgeSpline(e);
27234
27372
  }
@@ -27380,7 +27518,7 @@ function baseSplineForGroup(g, e0) {
27380
27518
  const orig = resolveOrigEdge(e0);
27381
27519
  const fe = isBackEdgeMember(orig) ? makeFwdEdge(orig) : orig;
27382
27520
  const pts = routeRegularEdgeFaithful(g, fe);
27383
- if (pts === "lost") return null;
27521
+ if (pts === "lost") return "lost";
27384
27522
  return pts ?? routeMultiRankEdgeFaithful(g, fe);
27385
27523
  }
27386
27524
  function isBackEdgeMember(e) {
@@ -27409,6 +27547,10 @@ function routeParallelEdgeGroup(g, edges, multisep) {
27409
27547
  return o.info.head_port?.defined || o.info.tail_port?.defined;
27410
27548
  }) ?? edges[0];
27411
27549
  const base = baseSplineForGroup(g, baseEdge);
27550
+ if (base === "lost") {
27551
+ for (const e of edges) resolveOrigEdge(e).info.lost = true;
27552
+ return;
27553
+ }
27412
27554
  if (base === null) return;
27413
27555
  if (cnt === 1) {
27414
27556
  installShiftedEdge(edges[0], base);
@@ -29576,8 +29718,9 @@ function normalizeCopiedFlatSpline(orig, auxe) {
29576
29718
  if (orig.info.spl === void 0) return;
29577
29719
  if (swapEndsP(auxe) !== swapEndsP(orig)) swapEdgeSpline(orig);
29578
29720
  }
29579
- function makeFlatAdjEdges(g, edges, cnt, _et) {
29721
+ function makeFlatAdjEdges(g, edges, cnt, et) {
29580
29722
  const aux = buildFlatAux(g, edges, cnt);
29723
+ aux.auxg.info.flags = aux.auxg.info.flags & ~15 | et & 15;
29581
29724
  dotInitNodeEdge(aux.auxg);
29582
29725
  dotRank(aux.auxg);
29583
29726
  if (dotMincross(aux.auxg) !== 0) return 1;
@@ -29688,88 +29831,6 @@ function assembleFlatPath(P, tend, hend, mid) {
29688
29831
  for (let i = hend.boxn - 1; i >= 0; i--) addBox(P, hend.boxes[i]);
29689
29832
  }
29690
29833
 
29691
- // src/layout/dot/splines-flat-multi.ts
29692
- function portEq2(a, b) {
29693
- if (!a.defined && !b.defined) return true;
29694
- if (!a.defined || !b.defined) return false;
29695
- return a.p.x === b.p.x && a.p.y === b.p.y;
29696
- }
29697
- function flatPortKey(e, lo) {
29698
- return e.tail === lo ? { loP: e.info.tail_port, hiP: e.info.head_port } : { loP: e.info.head_port, hiP: e.info.tail_port };
29699
- }
29700
- function isNonAdjGroupable(x, g) {
29701
- return x.info.spl === void 0 && x.tail.info.rank !== void 0 && x.tail.info.rank === x.head.info.rank && !isFlatAdjacent(g, x);
29702
- }
29703
- function samePortsAs(x, lo, key) {
29704
- const k = flatPortKey(x, lo);
29705
- return portEq2(k.loP, key.loP) && portEq2(k.hiP, key.hiP);
29706
- }
29707
- function collectNonAdjacentFlatGroup(e, g) {
29708
- const u = e.tail, v = e.head;
29709
- const lo = (u.info.order ?? 0) <= (v.info.order ?? 0) ? u : v;
29710
- const key = flatPortKey(e, lo);
29711
- const sharesPair = (x) => x.tail === u && x.head === v || x.tail === v && x.head === u;
29712
- const group = g.edges.filter(
29713
- (x) => sharesPair(x) && isNonAdjGroupable(x, g) && samePortsAs(x, lo, key) && x.info.label === e.info.label
29714
- );
29715
- group.sort((a, b) => Number(b.tail === lo) - Number(a.tail === lo) || a.seq - b.seq);
29716
- return group;
29717
- }
29718
- function copyPathEnd(end) {
29719
- return {
29720
- ...end,
29721
- boxes: end.boxes.map((b) => ({ ll: { ...b.ll }, ur: { ...b.ur } }))
29722
- };
29723
- }
29724
- function routeGroupEdge(e, i, c) {
29725
- c.P.nbox = 0;
29726
- const endStepX = (i + 1) * c.stepx;
29727
- const endStepY = (i + 1) * c.stepy;
29728
- const mid = c.bottom ? bottomBoxes(c.tlast, c.hlast, endStepX, endStepY, c.stepy) : topBoxes(c.tlast, c.hlast, endStepX, endStepY, c.stepy);
29729
- assembleFlatPath(c.P, copyPathEnd(c.tend), copyPathEnd(c.hend), mid);
29730
- const pts = routeSplines(c.P);
29731
- if (pts === null || pts.length === 0) return false;
29732
- if (e.tail !== c.leftNode) pts.reverse();
29733
- clipAndInstall(e, e.head, pts, pts.length, { ...buildDotSinfo(), ignoreSwap: true });
29734
- return true;
29735
- }
29736
- function routeFlatEdgeGroupFaithful(g, edges, cnt) {
29737
- const lead = edges[0];
29738
- if (g.info.rank === void 0 || lead.tail.info.rank === void 0 || lead.head.info.rank !== lead.tail.info.rank) return false;
29739
- const tailIsLeft = (lead.tail.info.order ?? 0) <= (lead.head.info.order ?? 0);
29740
- const leftNode = tailIsLeft ? lead.tail : lead.head;
29741
- const rightNode = tailIsLeft ? lead.head : lead.tail;
29742
- const sample = tailIsLeft ? lead : {
29743
- ...lead,
29744
- tail: leftNode,
29745
- head: rightNode,
29746
- info: { ...lead.info, tail_port: lead.info.head_port, head_port: lead.info.tail_port }
29747
- };
29748
- const { bottom, side } = flatSide(sample);
29749
- const ctx = flatBboxCtx(g);
29750
- const ranksep = graphRanksep(g);
29751
- const P = freshFlatPath();
29752
- const tend = makeFlatEndBox({ ctx, P, e: sample, n: leftNode, side, ranksep, isBegin: true });
29753
- const hend = makeFlatEndBox({ ctx, P, e: sample, n: rightNode, side, ranksep, isBegin: false });
29754
- const stepx = (g.info.nodesep ?? 18) / (cnt + 1);
29755
- const stepy = flatVspace(g, leftNode, !bottom) / (cnt + 1);
29756
- const rc = {
29757
- P,
29758
- tend,
29759
- hend,
29760
- tlast: tend.boxes[tend.boxn - 1],
29761
- hlast: hend.boxes[hend.boxn - 1],
29762
- bottom,
29763
- stepx,
29764
- stepy,
29765
- leftNode
29766
- };
29767
- for (let i = 0; i < cnt; i++) {
29768
- if (!routeGroupEdge(edges[i], i, rc)) return false;
29769
- }
29770
- return true;
29771
- }
29772
-
29773
29834
  // src/layout/dot/splines-flat-labeled.ts
29774
29835
  var LBL_SPACE = 6;
29775
29836
  function findLabelNode(e) {
@@ -30024,6 +30085,93 @@ function makeAdjFlatNoPortEdge(g, e) {
30024
30085
  return true;
30025
30086
  }
30026
30087
 
30088
+ // src/layout/dot/splines-flat-multi.ts
30089
+ function portEq2(a, b) {
30090
+ if (!a.defined && !b.defined) return true;
30091
+ if (!a.defined || !b.defined) return false;
30092
+ return a.p.x === b.p.x && a.p.y === b.p.y;
30093
+ }
30094
+ function flatPortKey(e, lo) {
30095
+ return e.tail === lo ? { loP: e.info.tail_port, hiP: e.info.head_port } : { loP: e.info.head_port, hiP: e.info.tail_port };
30096
+ }
30097
+ function isNonAdjGroupable(x, g) {
30098
+ return x.info.spl === void 0 && x.tail.info.rank !== void 0 && x.tail.info.rank === x.head.info.rank && !isFlatAdjacent(g, x);
30099
+ }
30100
+ function samePortsAs(x, lo, key) {
30101
+ const k = flatPortKey(x, lo);
30102
+ return portEq2(k.loP, key.loP) && portEq2(k.hiP, key.hiP);
30103
+ }
30104
+ function collectNonAdjacentFlatGroup(e, g) {
30105
+ const u = e.tail, v = e.head;
30106
+ const lo = (u.info.order ?? 0) <= (v.info.order ?? 0) ? u : v;
30107
+ const key = flatPortKey(e, lo);
30108
+ const sharesPair = (x) => x.tail === u && x.head === v || x.tail === v && x.head === u;
30109
+ const group = g.edges.filter(
30110
+ (x) => sharesPair(x) && isNonAdjGroupable(x, g) && samePortsAs(x, lo, key) && x.info.label === e.info.label
30111
+ );
30112
+ group.sort((a, b) => Number(b.tail === lo) - Number(a.tail === lo) || a.seq - b.seq);
30113
+ return group;
30114
+ }
30115
+ function copyPathEnd(end) {
30116
+ return {
30117
+ ...end,
30118
+ boxes: end.boxes.map((b) => ({ ll: { ...b.ll }, ur: { ...b.ur } }))
30119
+ };
30120
+ }
30121
+ function routeGroupEdge(e, i, c) {
30122
+ c.P.nbox = 0;
30123
+ const endStepX = (i + 1) * c.stepx;
30124
+ const endStepY = (i + 1) * c.stepy;
30125
+ const mid = c.bottom ? bottomBoxes(c.tlast, c.hlast, endStepX, endStepY, c.stepy) : topBoxes(c.tlast, c.hlast, endStepX, endStepY, c.stepy);
30126
+ assembleFlatPath(c.P, copyPathEnd(c.tend), copyPathEnd(c.hend), mid);
30127
+ const pts = c.et === EDGETYPE_SPLINE ? routeSplines(c.P) : routePolylines(c.P);
30128
+ if (pts === null || pts.length === 0) return false;
30129
+ if (e.tail !== c.leftNode) pts.reverse();
30130
+ clipAndInstall(e, e.head, pts, pts.length, { ...buildDotSinfo(), ignoreSwap: true });
30131
+ return true;
30132
+ }
30133
+ function routeFlatEdgeGroupFaithful(g, edges, cnt, et) {
30134
+ const lead = edges[0];
30135
+ if (g.info.rank === void 0 || lead.tail.info.rank === void 0 || lead.head.info.rank !== lead.tail.info.rank) return false;
30136
+ if (et === EDGETYPE_LINE) {
30137
+ makeSimpleFlat(edges, et);
30138
+ return true;
30139
+ }
30140
+ const tailIsLeft = (lead.tail.info.order ?? 0) <= (lead.head.info.order ?? 0);
30141
+ const leftNode = tailIsLeft ? lead.tail : lead.head;
30142
+ const rightNode = tailIsLeft ? lead.head : lead.tail;
30143
+ const sample = tailIsLeft ? lead : {
30144
+ ...lead,
30145
+ tail: leftNode,
30146
+ head: rightNode,
30147
+ info: { ...lead.info, tail_port: lead.info.head_port, head_port: lead.info.tail_port }
30148
+ };
30149
+ const { bottom, side } = flatSide(sample);
30150
+ const ctx = flatBboxCtx(g);
30151
+ const ranksep = graphRanksep(g);
30152
+ const P = freshFlatPath();
30153
+ const tend = makeFlatEndBox({ ctx, P, e: sample, n: leftNode, side, ranksep, isBegin: true });
30154
+ const hend = makeFlatEndBox({ ctx, P, e: sample, n: rightNode, side, ranksep, isBegin: false });
30155
+ const stepx = (g.info.nodesep ?? 18) / (cnt + 1);
30156
+ const stepy = flatVspace(g, leftNode, !bottom) / (cnt + 1);
30157
+ const rc = {
30158
+ P,
30159
+ tend,
30160
+ hend,
30161
+ tlast: tend.boxes[tend.boxn - 1],
30162
+ hlast: hend.boxes[hend.boxn - 1],
30163
+ bottom,
30164
+ et,
30165
+ stepx,
30166
+ stepy,
30167
+ leftNode
30168
+ };
30169
+ for (let i = 0; i < cnt; i++) {
30170
+ if (!routeGroupEdge(edges[i], i, rc)) return false;
30171
+ }
30172
+ return true;
30173
+ }
30174
+
30027
30175
  // src/layout/dot/edge-route-boxes.ts
30028
30176
  var FUDGE2 = 2;
30029
30177
  function makeTailBox(nb, startPy) {
@@ -30308,6 +30456,10 @@ function routeOneEdge(e, g) {
30308
30456
  function routeFaithfulMultiRank(e, g) {
30309
30457
  const pts = routeMultiRankEdgeFaithful(g, e);
30310
30458
  if (pts === null) return false;
30459
+ if (pts === "lost") {
30460
+ e.info.lost = true;
30461
+ return true;
30462
+ }
30311
30463
  clipAndInstall(e, e.head, pts, pts.length, buildDotSinfo());
30312
30464
  return true;
30313
30465
  }
@@ -30323,7 +30475,10 @@ function isAdjacentPortFlat(e, g) {
30323
30475
  return e.tail.info.rank !== void 0 && e.tail.info.rank === e.head.info.rank && isFlatAdjacent(g, e) && hasDefinedPort(e);
30324
30476
  }
30325
30477
  function isGroupableFlat(x, g) {
30326
- return x.info.spl === void 0 && isAdjacentPortFlat(x, g);
30478
+ return x.info.spl === void 0 && x.tail.info.rank !== void 0 && x.tail.info.rank === x.head.info.rank && isFlatAdjacent(g, x);
30479
+ }
30480
+ function joinsPortedFlatGroup(e, g) {
30481
+ return isAdjFlatCandidate(e) && isGroupableFlat(e, g) && collectAdjacentFlatGroup(e, g).some(hasDefinedPort);
30327
30482
  }
30328
30483
  function collectAdjacentFlatGroup(e, g) {
30329
30484
  const u = e.tail, v = e.head;
@@ -30338,11 +30493,11 @@ function routeFaithfulSidePort(e, g) {
30338
30493
  const sameRank = e.tail.info.rank !== void 0 && e.tail.info.rank === e.head.info.rank;
30339
30494
  if (sameRank && isFlatAdjacent(g, e)) {
30340
30495
  const group = collectAdjacentFlatGroup(e, g);
30341
- return makeFlatAdjEdges(g, group, group.length, EDGETYPE_SPLINE) === 0 && e.info.spl !== void 0;
30496
+ return makeFlatAdjEdges(g, group, group.length, edgeType(g)) === 0 && e.info.spl !== void 0;
30342
30497
  }
30343
30498
  if (sameRank) {
30344
30499
  const group = collectNonAdjacentFlatGroup(e, g);
30345
- return routeFlatEdgeGroupFaithful(g, group, group.length) && e.info.spl !== void 0;
30500
+ return routeFlatEdgeGroupFaithful(g, group, group.length, edgeType(g)) && e.info.spl !== void 0;
30346
30501
  }
30347
30502
  const pts = routeRegularEdgeFaithful(g, e);
30348
30503
  if (pts === null) return false;
@@ -30363,11 +30518,12 @@ function isLostFlatAdjRecordEdge(g, e) {
30363
30518
  function routeFlatEdge(e, g) {
30364
30519
  if (isLostFlatAdjRecordEdge(g, e)) return true;
30365
30520
  if (makeFlatLabeledEdge(g, e)) return true;
30521
+ if (joinsPortedFlatGroup(e, g) && routeFaithfulSidePort(e, g)) return true;
30366
30522
  if (makeAdjFlatNoPortEdge(g, e)) return true;
30367
30523
  if ((hasSidePort(e) || isAdjacentPortFlat(e, g)) && routeFaithfulSidePort(e, g)) return true;
30368
30524
  if (e.tail.info.rank !== void 0 && e.tail.info.rank === e.head.info.rank && e.info.label === void 0 && !isFlatAdjacent(g, e)) {
30369
30525
  const group = collectNonAdjacentFlatGroup(e, g);
30370
- if (group.length > 0 && routeFlatEdgeGroupFaithful(g, group, group.length) && e.info.spl !== void 0) return true;
30526
+ if (group.length > 0 && routeFlatEdgeGroupFaithful(g, group, group.length, edgeType(g)) && e.info.spl !== void 0) return true;
30371
30527
  }
30372
30528
  return false;
30373
30529
  }
@@ -30812,24 +30968,28 @@ function addSegment(segnum, seg2, tr, qs) {
30812
30968
  swapSegEndpoints(s);
30813
30969
  isSwapped = true;
30814
30970
  }
30815
- let tfirst;
30816
- if (!inserted(segnum, seg2, isSwapped ? LASTPT : FIRSTPT)) {
30817
- tfirst = insertV0(s, seg2, tr, qs, segnum);
30818
- } else {
30819
- tfirst = locateEndpoint(s.v0, s.v1, s.root0, seg2, qs);
30971
+ const ctx = { s, seg: seg2, tr, qs, segnum, tribot: false, isSwapped };
30972
+ const tfirst = firstTrap(ctx);
30973
+ const tlast = lastTrap(ctx);
30974
+ if (threadSegment(ctx, tfirst, tlast) !== 0) return -1;
30975
+ seg2[segnum].isInserted = true;
30976
+ return 0;
30977
+ }
30978
+ function firstTrap(c) {
30979
+ if (!inserted(c.segnum, c.seg, c.isSwapped ? LASTPT : FIRSTPT)) {
30980
+ return insertV0(c.s, c.seg, c.tr, c.qs, c.segnum);
30820
30981
  }
30821
- let tlast;
30822
- let tribot = false;
30823
- if (!inserted(segnum, seg2, isSwapped ? FIRSTPT : LASTPT)) {
30824
- tlast = insertV1(s, seg2, tr, qs, segnum);
30825
- } else {
30826
- tlast = locateEndpoint(s.v1, s.v0, s.root1, seg2, qs);
30827
- tribot = true;
30982
+ return locateEndpoint(c.s.v0, c.s.v1, c.s.root0, c.seg, c.qs);
30983
+ }
30984
+ function lastTrap(c) {
30985
+ if (!inserted(c.segnum, c.seg, c.isSwapped ? FIRSTPT : LASTPT)) {
30986
+ return insertV1(c.s, c.seg, c.tr, c.qs, c.segnum);
30828
30987
  }
30829
- threadSegment(s, seg2, tr, qs, segnum, tfirst, tlast, tribot, isSwapped);
30830
- seg2[segnum].isInserted = true;
30988
+ c.tribot = true;
30989
+ return locateEndpoint(c.s.v1, c.s.v0, c.s.root1, c.seg, c.qs);
30831
30990
  }
30832
- function threadSegment(s, seg2, tr, qs, segnum, tfirst, tlast, tribot, isSwapped) {
30991
+ function threadSegment(c, tfirst, tlast) {
30992
+ const { s, seg: seg2, tr, qs, segnum, tribot, isSwapped } = c;
30833
30993
  let tfirstr = INVALID_TRAP;
30834
30994
  let tlastr = INVALID_TRAP;
30835
30995
  let t = tfirst;
@@ -30856,17 +31016,20 @@ function threadSegment(s, seg2, tr, qs, segnum, tfirst, tlast, tribot, isSwapped
30856
31016
  if (equalTo(tr[t].lo, tr[tlast].lo)) tlastr = tn;
30857
31017
  const tSav = t;
30858
31018
  const tnSav = tn;
31019
+ if (!isValidTrap(tr[t].d0) && !isValidTrap(tr[t].d1)) {
31020
+ console.error("trapezoid segment construction failed");
31021
+ return -1;
31022
+ }
30859
31023
  t = advanceT(s, seg2, tr, t, tn, tlast, segnum, isSwapped, tribot);
30860
31024
  tr[tSav].rseg = segnum;
30861
31025
  tr[tnSav].lseg = segnum;
30862
31026
  }
30863
31027
  mergeTrapezoids(segnum, tfirst, tlast, S_LEFT, tr, qs);
30864
31028
  mergeTrapezoids(segnum, tfirstr, tlastr, S_RIGHT, tr, qs);
31029
+ return 0;
30865
31030
  }
30866
31031
  function advanceT(s, seg2, tr, t, tn, tlast, segnum, isSwapped, tribot) {
30867
- if (!isValidTrap(tr[t].d0) && !isValidTrap(tr[t].d1)) {
30868
- return INVALID_TRAP;
30869
- } else if (isValidTrap(tr[t].d0) && !isValidTrap(tr[t].d1)) {
31032
+ if (isValidTrap(tr[t].d0) && !isValidTrap(tr[t].d1)) {
30870
31033
  handleD0Only(s, seg2, tr, t, tn, tlast, segnum, isSwapped, tribot);
30871
31034
  return tr[t].d0;
30872
31035
  } else if (!isValidTrap(tr[t].d0) && isValidTrap(tr[t].d1)) {
@@ -30886,33 +31049,16 @@ function findNewRoots(segnum, seg2, tr, qs) {
30886
31049
  // src/ortho/trapezoid.ts
30887
31050
  function constructTrapezoids(nseg, seg2, permute) {
30888
31051
  const qs = [];
30889
- const tr = [];
30890
- tr.push({
30891
- lseg: 0,
30892
- rseg: 0,
30893
- hi: { x: 0, y: 0 },
30894
- lo: { x: 0, y: 0 },
30895
- u0: 0,
30896
- u1: 0,
30897
- d0: 0,
30898
- d1: 0,
30899
- sink: 0,
30900
- usave: 0,
30901
- uside: 0,
30902
- isValid: false
30903
- });
31052
+ const tr = [sentinelTrap()];
30904
31053
  let segi = 0;
30905
31054
  const root = initQueryStructure(permute[segi++], seg2, tr, qs);
30906
- for (let i = 1; i <= nseg; i++) {
30907
- seg2[i].root0 = root;
30908
- seg2[i].root1 = root;
30909
- }
31055
+ seedRoots(nseg, seg2, root);
30910
31056
  const logstar = mathLogstarN(nseg);
30911
31057
  for (let h = 1; h <= logstar; h++) {
30912
31058
  const lo = mathN(nseg, h - 1) + 1;
30913
31059
  const hi = mathN(nseg, h);
30914
31060
  for (let i = lo; i <= hi; i++) {
30915
- addSegment(permute[segi++], seg2, tr, qs);
31061
+ if (addSegment(permute[segi++], seg2, tr, qs) !== 0) return [];
30916
31062
  }
30917
31063
  for (let i = 1; i <= nseg; i++) {
30918
31064
  findNewRoots(i, seg2, tr, qs);
@@ -30920,10 +31066,32 @@ function constructTrapezoids(nseg, seg2, permute) {
30920
31066
  }
30921
31067
  const remaining = mathN(nseg, logstar) + 1;
30922
31068
  for (let i = remaining; i <= nseg; i++) {
30923
- addSegment(permute[segi++], seg2, tr, qs);
31069
+ if (addSegment(permute[segi++], seg2, tr, qs) !== 0) return [];
30924
31070
  }
30925
31071
  return tr;
30926
31072
  }
31073
+ function sentinelTrap() {
31074
+ return {
31075
+ lseg: 0,
31076
+ rseg: 0,
31077
+ hi: { x: 0, y: 0 },
31078
+ lo: { x: 0, y: 0 },
31079
+ u0: 0,
31080
+ u1: 0,
31081
+ d0: 0,
31082
+ d1: 0,
31083
+ sink: 0,
31084
+ usave: 0,
31085
+ uside: 0,
31086
+ isValid: false
31087
+ };
31088
+ }
31089
+ function seedRoots(nseg, seg2, root) {
31090
+ for (let i = 1; i <= nseg; i++) {
31091
+ seg2[i].root0 = root;
31092
+ seg2[i].root1 = root;
31093
+ }
31094
+ }
30927
31095
  function initQueryStructure(segnum, seg2, tr, qs) {
30928
31096
  const s = seg2[segnum];
30929
31097
  const i1 = newQNode(qs);
@@ -31227,10 +31395,18 @@ function partition(cells, bb) {
31227
31395
  const hSeg = h.genSegments(cells, bb, false);
31228
31396
  const hPerm = h.generateRandomOrdering(nsegs);
31229
31397
  const hTr = constructTrapezoids(nsegs, hSeg, hPerm);
31398
+ if (hTr.length === 0) {
31399
+ console.error("horizontal trapezoid construction failed");
31400
+ return null;
31401
+ }
31230
31402
  const hDecomp = h.monotonateTrapezoids(hTr, hSeg, false);
31231
31403
  const vSeg = h.genSegments(cells, bb, true);
31232
31404
  const vPerm = h.generateRandomOrdering(nsegs);
31233
31405
  const vTr = constructTrapezoids(nsegs, vSeg, vPerm);
31406
+ if (vTr.length === 0) {
31407
+ console.error("vertical trapezoid construction failed");
31408
+ return null;
31409
+ }
31234
31410
  const vDecomp = h.monotonateTrapezoids(vTr, vSeg, true);
31235
31411
  const result = [];
31236
31412
  for (const v of vDecomp) {
@@ -31239,7 +31415,7 @@ function partition(cells, bb) {
31239
31415
  if (isect) result.push(isect);
31240
31416
  }
31241
31417
  }
31242
- return result;
31418
+ return result.length === 0 ? null : result;
31243
31419
  }
31244
31420
 
31245
31421
  // src/ortho/rawgraph.ts
@@ -32087,6 +32263,7 @@ function mkMaze(g) {
32087
32263
  UR: { x: BB.UR.x + MARGIN, y: BB.UR.y + MARGIN }
32088
32264
  };
32089
32265
  const rects = partition(gcells, BB);
32266
+ if (rects === null) return null;
32090
32267
  const cells = rects.map((bb) => ({
32091
32268
  flags: 0,
32092
32269
  nedges: 0,
@@ -32568,6 +32745,24 @@ function buildSpline(e, rte, mp) {
32568
32745
  pts.push({ ...p });
32569
32746
  return pts;
32570
32747
  }
32748
+ function ensureDummyNodes(sg, gstart) {
32749
+ while (sg.nodes.length < gstart + 2) {
32750
+ sg.nodes.push({
32751
+ nVal: 0,
32752
+ nIdx: 0,
32753
+ nDad: null,
32754
+ nEdge: null,
32755
+ nAdj: 0,
32756
+ saveNAdj: 0,
32757
+ cells: [null, null],
32758
+ adjEdgeList: [],
32759
+ index: sg.nodes.length,
32760
+ isVert: false,
32761
+ x: 0,
32762
+ y: 0
32763
+ });
32764
+ }
32765
+ }
32571
32766
  function orthoEdges(g, useLbls, clipAndInstall2) {
32572
32767
  if (useLbls) {
32573
32768
  console.warn(
@@ -32577,6 +32772,7 @@ function orthoEdges(g, useLbls, clipAndInstall2) {
32577
32772
  }
32578
32773
  void useLbls;
32579
32774
  const mp = mkMaze(g);
32775
+ if (mp === null) return -1;
32580
32776
  const sg = mp.sg;
32581
32777
  const es = g.edges.map((e) => ({ e, d: edgeLen(e) }));
32582
32778
  gvQsort(es, edgeCmp);
@@ -32586,22 +32782,7 @@ function orthoEdges(g, useLbls, clipAndInstall2) {
32586
32782
  const pq = pqGenForGraph(sg);
32587
32783
  const sn = sg.nodes[gstart];
32588
32784
  const dn = sg.nodes[gstart + 1];
32589
- while (sg.nodes.length < gstart + 2) {
32590
- sg.nodes.push({
32591
- nVal: 0,
32592
- nIdx: 0,
32593
- nDad: null,
32594
- nEdge: null,
32595
- nAdj: 0,
32596
- saveNAdj: 0,
32597
- cells: [null, null],
32598
- adjEdgeList: [],
32599
- index: sg.nodes.length,
32600
- isVert: false,
32601
- x: 0,
32602
- y: 0
32603
- });
32604
- }
32785
+ ensureDummyNodes(sg, gstart);
32605
32786
  for (let i = 0; i < nEdges; i++) {
32606
32787
  const e = es[i].e;
32607
32788
  const start = mp.gcells[g.nodes.indexOf(e.tail)];
@@ -32615,7 +32796,7 @@ function orthoEdges(g, useLbls, clipAndInstall2) {
32615
32796
  if (shortPath(pq, sg, dn, sn) !== 0) {
32616
32797
  pqFree(pq);
32617
32798
  freeMaze(mp);
32618
- return;
32799
+ return 0;
32619
32800
  }
32620
32801
  routeList[i] = convertSPtoRoute(sg, sn, dn);
32621
32802
  reset(sg);
@@ -32626,7 +32807,7 @@ function orthoEdges(g, useLbls, clipAndInstall2) {
32626
32807
  assignSegs(routeList, mp);
32627
32808
  if (assignTracks(mp) !== 0) {
32628
32809
  freeMaze(mp);
32629
- return;
32810
+ return 0;
32630
32811
  }
32631
32812
  if (clipAndInstall2) {
32632
32813
  for (let i = 0; i < nEdges; i++) {
@@ -32637,6 +32818,7 @@ function orthoEdges(g, useLbls, clipAndInstall2) {
32637
32818
  }
32638
32819
  }
32639
32820
  freeMaze(mp);
32821
+ return 0;
32640
32822
  }
32641
32823
 
32642
32824
  // src/layout/dot/ortho-adapter.ts
@@ -32664,7 +32846,6 @@ function buildEdges(g, nodeArr, orthoNodes) {
32664
32846
  const oes = outIndex.get(n);
32665
32847
  if (oes === void 0) continue;
32666
32848
  for (const e of oes) {
32667
- if (e.tail === e.head) continue;
32668
32849
  if (concentrate) {
32669
32850
  const ti = e.tail.id;
32670
32851
  const hi = e.head.id;
@@ -32708,7 +32889,7 @@ function installOrthoResult(oe, pts) {
32708
32889
  clipAndInstall(origEdge, origEdge.head, pts, pts.length, ORTHO_SINFO);
32709
32890
  }
32710
32891
  function dispatchOrthoEdges(g, useLbls) {
32711
- orthoEdges(
32892
+ return orthoEdges(
32712
32893
  buildOrthoGraph(g),
32713
32894
  useLbls,
32714
32895
  (_og, oe, pts) => installOrthoResult(oe, pts)
@@ -33245,12 +33426,12 @@ function resetRW(g) {
33245
33426
  }
33246
33427
  function orthoDispatch(g) {
33247
33428
  resetRW(g);
33429
+ let rc;
33248
33430
  if (((g.root.info.has_labels ?? 0) & EDGE_LABEL) !== 0) {
33249
33431
  setEdgeLabelPos(g);
33250
- dispatchOrthoEdges(g, true);
33251
- } else {
33252
- dispatchOrthoEdges(g, false);
33253
- }
33432
+ rc = dispatchOrthoEdges(g, true);
33433
+ } else rc = dispatchOrthoEdges(g, false);
33434
+ if (rc !== 0) return rc;
33254
33435
  placePortLabels(g);
33255
33436
  g.info.edgeLabelsDone = true;
33256
33437
  return 0;
@@ -33906,7 +34087,7 @@ function computeStep2(bbs, margin) {
33906
34087
  c -= W * H;
33907
34088
  }
33908
34089
  const r = Math.sqrt(b * b - 4 * a * c);
33909
- const root = Math.trunc((-b + r) / (2 * a));
34090
+ const root = d2i((-b + r) / (2 * a));
33910
34091
  return root === 0 ? 1 : root;
33911
34092
  }
33912
34093
  function lineXDominant(st, ps) {
@@ -34052,7 +34233,7 @@ function fits2(x, y, info, ctx) {
34052
34233
  }
34053
34234
  const bb = ctx.bbs[info.index];
34054
34235
  const LL = { x: cround(bb.ll.x), y: cround(bb.ll.y) };
34055
- ctx.places[info.index] = { x: ctx.step * x - LL.x, y: ctx.step * y - LL.y };
34236
+ ctx.places[info.index] = { x: Math.imul(ctx.step, x) - LL.x, y: Math.imul(ctx.step, y) - LL.y };
34056
34237
  for (const c of info.cells) ctx.ps.add(c.x + x, c.y + y);
34057
34238
  return true;
34058
34239
  }
@@ -34538,7 +34719,7 @@ function dotLayoutComponent(sg, root) {
34538
34719
  dotRank(sg);
34539
34720
  dotMincross(sg);
34540
34721
  dotPosition(sg);
34541
- dotPhasePostNoFinish(sg);
34722
+ return dotPhasePostNoFinish(sg);
34542
34723
  }
34543
34724
  function mapClust(clone, origOf) {
34544
34725
  const orig = origOf.get(clone);
@@ -34624,7 +34805,9 @@ function packComponentsClusterAware(root, comps, pinfo) {
34624
34805
  }
34625
34806
  function layoutAndPack(root, comps, pinfo, origOf) {
34626
34807
  dotGraphInit(root);
34627
- for (const sg of comps) dotLayoutComponent(sg, root);
34808
+ for (const sg of comps) {
34809
+ if (dotLayoutComponent(sg, root) !== 0) return;
34810
+ }
34628
34811
  packComponentsClusterAware(root, comps, pinfo);
34629
34812
  copyClusterInfo(comps, root, origOf);
34630
34813
  expandRootBbForClusters(root);
@@ -34656,11 +34839,13 @@ function dotPhaseInit(g) {
34656
34839
  function dotPhasePostNoFinish(g) {
34657
34840
  removeFill(g);
34658
34841
  dotSameports(g);
34659
- dotSplines(g);
34842
+ const r = dotSplines(g);
34843
+ if (r !== 0) return r;
34660
34844
  if (mapbool2(g.attrs.get("compound") ?? g.root.attrs.get("compound"))) dotCompoundEdges(g);
34845
+ return 0;
34661
34846
  }
34662
34847
  function dotPhasePost(g) {
34663
- dotPhasePostNoFinish(g);
34848
+ if (dotPhasePostNoFinish(g) !== 0) return;
34664
34849
  gvPostprocess(g);
34665
34850
  }
34666
34851
  function graphPhase(g) {
@@ -37546,10 +37731,10 @@ function raySegIntersect(v, w, a, b) {
37546
37731
  const mv = { x: w.x - v.x, y: w.y - v.y };
37547
37732
  const lv = { x: b.x - a.x, y: b.y - a.y };
37548
37733
  const ln = { x: -lv.y, y: lv.x };
37549
- const lc = -(ln.x * a.x + ln.y * a.y);
37550
- const dt = ln.x * mv.x + ln.y * mv.y;
37734
+ const lc = -fma(ln.x, a.x, ln.y * a.y);
37735
+ const dt = fma(ln.x, mv.x, ln.y * mv.y);
37551
37736
  if (Math.abs(dt) < SMALL3) return null;
37552
- const s = (ln.x * v.x + ln.y * v.y + lc) / dt;
37737
+ const s = (fma(ln.x, v.x, ln.y * v.y) + lc) / dt;
37553
37738
  return { x: v.x - s * mv.x, y: v.y - s * mv.y };
37554
37739
  }
37555
37740
  function triPoint(trip, vx, v, w) {
@@ -37567,36 +37752,44 @@ function ctrlPtIdx(v, ps) {
37567
37752
  return -1;
37568
37753
  }
37569
37754
  var SEP = 15;
37755
+ function bisectorTarget(v, cosTheta, sinTheta) {
37756
+ return { x: fma(cosTheta, 100, v.x), y: fma(sinTheta, 100, v.y) };
37757
+ }
37758
+ function distFused(p, q) {
37759
+ const dx = p.x - q.x;
37760
+ const dy = p.y - q.y;
37761
+ return Math.sqrt(fma(dx, dx, dy * dy));
37762
+ }
37570
37763
  function mkCtrlPts(s, mult, prev, v, nxt, trip) {
37571
37764
  const idx = ctrlPtIdx(v, trip.ps);
37572
37765
  if (idx < 0) return null;
37573
37766
  const theta = bisect(prev, v, nxt);
37574
37767
  let sinTheta = Math.sin(theta);
37575
37768
  let cosTheta = Math.cos(theta);
37576
- let w = { x: v.x + 100 * cosTheta, y: v.y + 100 * sinTheta };
37769
+ let w = bisectorTarget(v, cosTheta, sinTheta);
37577
37770
  if (idx > s) {
37578
37771
  if (wind(prev, v, w) !== 1) {
37579
37772
  sinTheta *= -1;
37580
37773
  cosTheta *= -1;
37581
- w = { x: v.x + 100 * cosTheta, y: v.y + 100 * sinTheta };
37774
+ w = bisectorTarget(v, cosTheta, sinTheta);
37582
37775
  }
37583
37776
  } else if (wind(prev, v, w) !== -1) {
37584
37777
  sinTheta *= -1;
37585
37778
  cosTheta *= -1;
37586
- w = { x: v.x + 100 * cosTheta, y: v.y + 100 * sinTheta };
37779
+ w = bisectorTarget(v, cosTheta, sinTheta);
37587
37780
  }
37588
37781
  const q = triPoint(trip, idx, v, w);
37589
37782
  if (q === null) return null;
37590
- const d = Math.hypot(q.x - v.x, q.y - v.y);
37783
+ const d = distFused(q, v);
37591
37784
  const sep = d >= mult * SEP ? SEP : d / mult;
37592
37785
  const ps = new Array(mult);
37593
37786
  if (idx < s) {
37594
37787
  for (let i = 0; i < mult; i++) {
37595
- ps[i] = { x: v.x + i * sep * cosTheta, y: v.y + i * sep * sinTheta };
37788
+ ps[i] = { x: fma(i * sep, cosTheta, v.x), y: fma(i * sep, sinTheta, v.y) };
37596
37789
  }
37597
37790
  } else {
37598
37791
  for (let i = 0; i < mult; i++) {
37599
- ps[mult - i - 1] = { x: v.x + i * sep * cosTheta, y: v.y + i * sep * sinTheta };
37792
+ ps[mult - i - 1] = { x: fma(i * sep, cosTheta, v.x), y: fma(i * sep, sinTheta, v.y) };
37600
37793
  }
37601
37794
  }
37602
37795
  return ps;
@@ -38030,7 +38223,7 @@ var ObstacleHelper = class {
38030
38223
  };
38031
38224
  function ellipseTangentSlope(a, b, p) {
38032
38225
  const signY = p.y >= 0 ? 1 : -1;
38033
- return -signY * (b * p.x) / (a * Math.sqrt(a * a - p.x * p.x));
38226
+ return -signY * (b * p.x) / (a * Math.sqrt(fma(a, a, -(p.x * p.x))));
38034
38227
  }
38035
38228
  function circumscribedCorner(a, b, i, nsides) {
38036
38229
  const angle0 = 2 * Math.PI * (i - 0.5) / nsides;
@@ -38039,8 +38232,8 @@ function circumscribedCorner(a, b, i, nsides) {
38039
38232
  const p1 = { x: a * Math.cos(angle1), y: b * Math.sin(angle1) };
38040
38233
  const m0 = ellipseTangentSlope(a, b, p0);
38041
38234
  const m1 = ellipseTangentSlope(a, b, p1);
38042
- const x = (m0 * p0.x - p0.y - m1 * p1.x + p1.y) / (m0 - m1);
38043
- const y = p0.y + m0 * (x - p0.x);
38235
+ const x = (fms(p1.x, m1, fma(m0, p0.x, -p0.y)) + p1.y) / (m0 - m1);
38236
+ const y = fma(m0, x - p0.x, p0.y);
38044
38237
  return { x, y };
38045
38238
  }
38046
38239
  function boxCornerMargin(j, m) {
@@ -42117,8 +42310,8 @@ function initItem(n, margin) {
42117
42310
  let w2;
42118
42311
  let h2;
42119
42312
  if (margin.doAdd) {
42120
- w2 = Math.trunc(SCALE * (cround(width / 2 * POINTS_PER_INCH6) + margin.x));
42121
- h2 = Math.trunc(SCALE * (cround(height / 2 * POINTS_PER_INCH6) + margin.y));
42313
+ w2 = d2i(SCALE * (cround(width / 2 * POINTS_PER_INCH6) + margin.x));
42314
+ h2 = d2i(SCALE * (cround(height / 2 * POINTS_PER_INCH6) + margin.y));
42122
42315
  } else {
42123
42316
  w2 = cround(margin.x * SCALE2 * width * POINTS_PER_INCH6);
42124
42317
  h2 = cround(margin.y * SCALE2 * height * POINTS_PER_INCH6);
@@ -44217,11 +44410,11 @@ function addClusters(g) {
44217
44410
  g.info.clust = clusters;
44218
44411
  g.info.n_cluster = clusters.length;
44219
44412
  }
44220
- function layoutComponents(g, comps, solve2, pinned) {
44413
+ function layoutComponents(g, comps, solve4, pinned) {
44221
44414
  for (const gc of comps) {
44222
44415
  setEdgeTypeFromAttr(gc, EDGETYPE_LINE);
44223
- solveModel2(gc, solve2.mode, solve2.model);
44224
- maybeRemoveOverlap(gc, solve2.am);
44416
+ solveModel2(gc, solve4.mode, solve4.model);
44417
+ maybeRemoveOverlap(gc, solve4.am);
44225
44418
  splineEdgesShifted(gc);
44226
44419
  }
44227
44420
  const pinfo = {
@@ -46126,6 +46319,20 @@ function powerLawGraph(A3) {
46126
46319
  }
46127
46320
  return mask[1] > 0.8 * max && mask[1] > 0.3 * m;
46128
46321
  }
46322
+ var PCP_COVARIANCE_LANES = 4;
46323
+ function pcpCovariance(n, dim, x, y) {
46324
+ const nUnfused = n - n % PCP_COVARIANCE_LANES;
46325
+ for (let i = 0; i < n; i++) {
46326
+ for (let k = 0; k < dim; k++) {
46327
+ for (let l = 0; l < dim; l++) {
46328
+ const a = x[i * dim + k];
46329
+ const b = x[i * dim + l];
46330
+ const acc = y[dim * k + l];
46331
+ y[dim * k + l] = i < nUnfused ? acc + a * b : fma(a, b, acc);
46332
+ }
46333
+ }
46334
+ }
46335
+ }
46129
46336
  function pcpRotate(n, dim, x) {
46130
46337
  const y = [0, 0, 0, 0];
46131
46338
  const center = [0, 0];
@@ -46136,24 +46343,23 @@ function pcpRotate(n, dim, x) {
46136
46343
  for (let i = 0; i < n; i++) {
46137
46344
  for (let k = 0; k < dim; k++) x[dim * i + k] -= center[k];
46138
46345
  }
46139
- for (let i = 0; i < n; i++) {
46140
- for (let k = 0; k < dim; k++) {
46141
- for (let l = 0; l < dim; l++) {
46142
- y[dim * k + l] = fma(x[i * dim + k], x[i * dim + l], y[dim * k + l]);
46143
- }
46144
- }
46145
- }
46346
+ pcpCovariance(n, dim, x, y);
46146
46347
  const axis = [0, 1];
46147
46348
  if (y[1] !== 0) {
46148
- axis[0] = -(-y[0] + y[3] - Math.sqrt(y[0] * y[0] + 4 * y[1] * y[1] - 2 * y[0] * y[3] + y[3] * y[3])) / (2 * y[1]);
46349
+ const radicand = fma(
46350
+ y[3],
46351
+ y[3],
46352
+ fma(-2 * y[0], y[3], fma(y[0], y[0], 4 * y[1] * y[1]))
46353
+ );
46354
+ axis[0] = -(-y[0] + y[3] - Math.sqrt(radicand)) / (2 * y[1]);
46149
46355
  axis[1] = 1;
46150
46356
  }
46151
- const dist4 = Math.sqrt(1 + axis[0] * axis[0]);
46357
+ const dist4 = Math.sqrt(fma(axis[0], axis[0], 1));
46152
46358
  axis[0] = axis[0] / dist4;
46153
46359
  axis[1] = axis[1] / dist4;
46154
46360
  for (let i = 0; i < n; i++) {
46155
- const x0 = x[dim * i] * axis[0] + x[dim * i + 1] * axis[1];
46156
- const x1 = -x[dim * i] * axis[1] + x[dim * i + 1] * axis[0];
46361
+ const x0 = fma(x[dim * i], axis[0], x[dim * i + 1] * axis[1]);
46362
+ const x1 = fma(-x[dim * i], axis[1], x[dim * i + 1] * axis[0]);
46157
46363
  x[dim * i] = x0;
46158
46364
  x[dim * i + 1] = x1;
46159
46365
  }
@@ -46416,16 +46622,7 @@ function makeCData(dn) {
46416
46622
  };
46417
46623
  }
46418
46624
 
46419
- // src/layout/circo/blockpath.ts
46420
- function blockGraph(allEdges3, sn) {
46421
- const ns = new Set(sn.subGraph.nodes);
46422
- for (const n of sn.subGraph.nodes) {
46423
- for (const e of allEdges3) {
46424
- if (e.tail === n && ns.has(e.head) && !sn.subGraph.edges.includes(e))
46425
- sn.subGraph.edges.push(e);
46426
- }
46427
- }
46428
- }
46625
+ // src/layout/circo/crossings.ts
46429
46626
  function derivedOf(n) {
46430
46627
  return n.info.alg?.derivedNode ?? null;
46431
46628
  }
@@ -46436,27 +46633,51 @@ function closeOpenEdge(e, d, opened) {
46436
46633
  }
46437
46634
  return cross2;
46438
46635
  }
46439
- function openEdgesAt(d, edges, opened, order) {
46636
+ function agfstedgeLists(edges) {
46637
+ const seq2 = /* @__PURE__ */ new Map();
46638
+ edges.forEach((e, i) => seq2.set(e, i));
46639
+ const by = (end) => (a, b) => end(a).orig.id - end(b).orig.id || seq2.get(a) - seq2.get(b);
46640
+ const out = /* @__PURE__ */ new Map();
46641
+ const inn = /* @__PURE__ */ new Map();
46440
46642
  for (const e of edges) {
46441
- if (e.order === 0 && (e.tail === d || e.head === d)) {
46442
- e.order = order;
46443
- opened.push(e);
46444
- }
46643
+ out.set(e.tail, [...out.get(e.tail) ?? [], e]);
46644
+ inn.set(e.head, [...inn.get(e.head) ?? [], e]);
46645
+ }
46646
+ const lists = /* @__PURE__ */ new Map();
46647
+ for (const d of /* @__PURE__ */ new Set([...out.keys(), ...inn.keys()])) {
46648
+ const o = (out.get(d) ?? []).sort(by((e) => e.head));
46649
+ const i = (inn.get(d) ?? []).sort(by((e) => e.tail));
46650
+ lists.set(d, [...o, ...i]);
46445
46651
  }
46652
+ return lists;
46446
46653
  }
46447
46654
  function countCrossings(list, edges) {
46448
46655
  for (const e of edges) e.order = 0;
46449
- const opened = [];
46656
+ const incident = agfstedgeLists(edges);
46657
+ const opened = /* @__PURE__ */ new Map();
46450
46658
  let crossings = 0;
46451
46659
  let order = 1;
46452
46660
  for (const n of list) {
46453
46661
  const d = derivedOf(n);
46454
46662
  if (!d) continue;
46455
- for (const e of edges) {
46456
- if (e.order > 0 && (e.tail === d || e.head === d))
46457
- crossings += closeOpenEdge(e, d, opened);
46663
+ const es = incident.get(d) ?? [];
46664
+ crossings += closeEdgesAt(d, es, opened);
46665
+ for (const e of es) {
46666
+ if (e.order === 0) {
46667
+ e.order = order;
46668
+ opened.set(e, d);
46669
+ }
46458
46670
  }
46459
- openEdgesAt(d, edges, opened, order++);
46671
+ order++;
46672
+ }
46673
+ return crossings;
46674
+ }
46675
+ function closeEdgesAt(d, es, opened) {
46676
+ let crossings = 0;
46677
+ for (const e of es) {
46678
+ if (e.order === 0) continue;
46679
+ crossings += closeOpenEdge(e, d, opened.keys());
46680
+ if (opened.get(e) === d) opened.delete(e);
46460
46681
  }
46461
46682
  return crossings;
46462
46683
  }
@@ -46509,6 +46730,17 @@ function spanIncident(dn, edges, ord, seq2) {
46509
46730
  const inn = edges.filter((e) => e.head === dn).sort((a, b) => (ord.get(a.tail) ?? 0) - (ord.get(b.tail) ?? 0) || (seq2.get(a) ?? 0) - (seq2.get(b) ?? 0));
46510
46731
  return [...out, ...inn];
46511
46732
  }
46733
+
46734
+ // src/layout/circo/blockpath.ts
46735
+ function blockGraph(allEdges3, sn) {
46736
+ const ns = new Set(sn.subGraph.nodes);
46737
+ for (const n of sn.subGraph.nodes) {
46738
+ for (const e of allEdges3) {
46739
+ if (e.tail === n && ns.has(e.head) && !sn.subGraph.edges.includes(e))
46740
+ sn.subGraph.edges.push(e);
46741
+ }
46742
+ }
46743
+ }
46512
46744
  function dfsSpan(sn, map, edges, ord, seq2) {
46513
46745
  sn.visited = true;
46514
46746
  for (const e of spanIncident(sn.dn, edges, ord, seq2)) {
@@ -47987,17 +48219,30 @@ function renderEdgeLabels(e, renderer, job) {
47987
48219
  }
47988
48220
  function emitEdgeLabel(lp, id, hs, renderer, job, spl, emitState) {
47989
48221
  if (!lp?.set) return;
47990
- const open = hs.url !== null || hs.explicit;
47991
- if (open) openAnchorWith(renderer, job, hs.url, hs.tooltip, hs.target, id);
47992
- const savedOverride = job.labelEmitOverride;
47993
- if (emitState !== void 0) job.labelEmitOverride = emitState;
47994
- try {
47995
- renderOneLabel(lp, renderer, job);
47996
- } finally {
47997
- job.labelEmitOverride = savedOverride;
48222
+ withObjEmitState(job, emitState ?? 11 /* ELabel */, () => {
48223
+ const open = hs.url !== null || hs.explicit;
48224
+ if (open) openAnchorWith(renderer, job, hs.url, hs.tooltip, hs.target, id);
48225
+ const savedOverride = job.labelEmitOverride;
48226
+ if (emitState !== void 0) job.labelEmitOverride = emitState;
48227
+ try {
48228
+ renderOneLabel(lp, renderer, job);
48229
+ } finally {
48230
+ job.labelEmitOverride = savedOverride;
48231
+ }
48232
+ if (spl) emitAttachment(lp, spl, renderer, job);
48233
+ if (open) renderer.endAnchor?.(job);
48234
+ });
48235
+ }
48236
+ function withObjEmitState(job, lkind, fn) {
48237
+ const obj = job.obj;
48238
+ if (obj === null) {
48239
+ fn();
48240
+ return;
47998
48241
  }
47999
- if (spl) emitAttachment(lp, spl, renderer, job);
48000
- if (open) renderer.endAnchor?.(job);
48242
+ const oldEmitState = obj.emitState;
48243
+ obj.emitState = lkind;
48244
+ fn();
48245
+ obj.emitState = oldEmitState;
48001
48246
  }
48002
48247
  function emitAttachment(lp, spl, renderer, job) {
48003
48248
  if (!lp?.set) return;
@@ -49583,6 +49828,7 @@ var DotWriterBase = class {
49583
49828
 
49584
49829
  // src/render/dot/edge-draw.ts
49585
49830
  var DEFAULT_COLOR5 = "black";
49831
+ var DEFAULT_LINE_STYLE = ["solid", "setlinewidth(1)"];
49586
49832
  function emitArrowOp(buf, op, pen) {
49587
49833
  switch (op.kind) {
49588
49834
  case "polygon":
@@ -49606,6 +49852,25 @@ function emitArrowOp(buf, op, pen) {
49606
49852
  var EdgeDrawBase = class extends DotWriterBase {
49607
49853
  /** setlinewidth state per emit_state. @see gvrender_core_dot.c penwidth[] */
49608
49854
  penwidth = new Array(12).fill(1);
49855
+ /**
49856
+ * emit_attachment's draw calls (decorate=true): gvrender_set_style with the
49857
+ * default line style sets the obj's rawstyle/pen/penwidth (setlinewidth 1),
49858
+ * gvrender_set_pencolor sets the pen to the label fontcolor (first entry of
49859
+ * a color list), then gvrender_polyline → xdot_polyline emits the style ops
49860
+ * (`S 5 -solid`; setlinewidth is filtered), the pen color and `L 3`.
49861
+ * @see lib/common/emit.c:emit_attachment (1886-1893)
49862
+ * @see lib/gvc/gvrender.c:gvrender_set_style / gvrender_set_pencolor
49863
+ */
49864
+ attachmentPolyline(pts, pencolor, job) {
49865
+ const obj = job.obj;
49866
+ if (obj !== null) {
49867
+ obj.rawStyle = [...DEFAULT_LINE_STYLE];
49868
+ obj.pen = 3 /* Solid */;
49869
+ obj.penWidth = 1;
49870
+ obj.penColor = resolveRenderColor(pencolor.split(":")[0]);
49871
+ }
49872
+ this.polyline(pts, job);
49873
+ }
49609
49874
  /**
49610
49875
  * The plain single-colour spline branch of beginEdge — lifted verbatim so the
49611
49876
  * four-way spline-kind chain above stays readable; no branch was reordered or
@@ -50139,19 +50404,6 @@ function emitMulticolorArrows(e, job, headColor, tailColor) {
50139
50404
  emitArrowOps(headOps, headColor, job, pw, colorOpacity(resolveRenderColor(headColor)));
50140
50405
  }
50141
50406
  }
50142
- function overlapLabel(lp, b) {
50143
- const sx = lp.dimen.x / 2;
50144
- const sy = lp.dimen.y / 2;
50145
- const bb = {
50146
- ll: { x: lp.pos.x - sx, y: lp.pos.y - sy },
50147
- ur: { x: lp.pos.x + sx, y: lp.pos.y + sy }
50148
- };
50149
- return boxOverlap(b, bb);
50150
- }
50151
- function edgeHasDrawableContent(e, clip) {
50152
- const i = e.info;
50153
- return i.spl !== void 0 || i.label !== void 0 && i.label.set && overlapLabel(i.label, clip) || i.xlabel !== void 0 || i.head_label !== void 0 || i.tail_label !== void 0;
50154
- }
50155
50407
  var SvgRenderer = class {
50156
50408
  type = "svg";
50157
50409
  /** @see plugin/core/gvplugin_core.c registration table */
@@ -50416,9 +50668,9 @@ function peg$parse(input, options) {
50416
50668
  const peg$c0 = "{";
50417
50669
  const peg$c1 = "}";
50418
50670
  const peg$c2 = ";";
50419
- const peg$c3 = "[";
50420
- const peg$c4 = "]";
50421
- const peg$c5 = "=";
50671
+ const peg$c3 = "=";
50672
+ const peg$c4 = "[";
50673
+ const peg$c5 = "]";
50422
50674
  const peg$c6 = ":";
50423
50675
  const peg$c7 = "->";
50424
50676
  const peg$c8 = "--";
@@ -50442,32 +50694,30 @@ function peg$parse(input, options) {
50442
50694
  const peg$r3 = /^[A-Za-z_\x80-\uFFFF]/;
50443
50695
  const peg$r4 = /^[A-Za-z_0-9\x80-\uFFFF]/;
50444
50696
  const peg$r5 = /^[0-9]/;
50445
- const peg$r6 = /^[eE]/;
50446
- const peg$r7 = /^[+\-]/;
50447
- const peg$r8 = /^[Ss]/;
50448
- const peg$r9 = /^[Tt]/;
50449
- const peg$r10 = /^[Rr]/;
50450
- const peg$r11 = /^[Ii]/;
50451
- const peg$r12 = /^[Cc]/;
50452
- const peg$r13 = /^[Gg]/;
50453
- const peg$r14 = /^[Aa]/;
50454
- const peg$r15 = /^[Pp]/;
50455
- const peg$r16 = /^[Hh]/;
50456
- const peg$r17 = /^[Dd]/;
50457
- const peg$r18 = /^[Nn]/;
50458
- const peg$r19 = /^[Oo]/;
50459
- const peg$r20 = /^[Ee]/;
50460
- const peg$r21 = /^[Uu]/;
50461
- const peg$r22 = /^[Bb]/;
50462
- const peg$r23 = /^[ \t\r\n]/;
50463
- const peg$r24 = /^[^\n]/;
50697
+ const peg$r6 = /^[Ss]/;
50698
+ const peg$r7 = /^[Tt]/;
50699
+ const peg$r8 = /^[Rr]/;
50700
+ const peg$r9 = /^[Ii]/;
50701
+ const peg$r10 = /^[Cc]/;
50702
+ const peg$r11 = /^[Gg]/;
50703
+ const peg$r12 = /^[Aa]/;
50704
+ const peg$r13 = /^[Pp]/;
50705
+ const peg$r14 = /^[Hh]/;
50706
+ const peg$r15 = /^[Dd]/;
50707
+ const peg$r16 = /^[Nn]/;
50708
+ const peg$r17 = /^[Oo]/;
50709
+ const peg$r18 = /^[Ee]/;
50710
+ const peg$r19 = /^[Uu]/;
50711
+ const peg$r20 = /^[Bb]/;
50712
+ const peg$r21 = /^[ \t\r\n]/;
50713
+ const peg$r22 = /^[^\n]/;
50464
50714
  const peg$e0 = peg$literalExpectation("{", false);
50465
50715
  const peg$e1 = peg$literalExpectation("}", false);
50466
50716
  const peg$e2 = peg$literalExpectation(";", false);
50467
- const peg$e3 = peg$literalExpectation("[", false);
50468
- const peg$e4 = peg$literalExpectation("]", false);
50469
- const peg$e5 = peg$classExpectation([";", ","], false, false, false);
50470
- const peg$e6 = peg$literalExpectation("=", false);
50717
+ const peg$e3 = peg$literalExpectation("=", false);
50718
+ const peg$e4 = peg$literalExpectation("[", false);
50719
+ const peg$e5 = peg$literalExpectation("]", false);
50720
+ const peg$e6 = peg$classExpectation([";", ","], false, false, false);
50471
50721
  const peg$e7 = peg$literalExpectation(":", false);
50472
50722
  const peg$e8 = peg$otherExpectation("edge operator");
50473
50723
  const peg$e9 = peg$literalExpectation("->", false);
@@ -50487,30 +50737,28 @@ function peg$parse(input, options) {
50487
50737
  const peg$e23 = peg$literalExpectation("-", false);
50488
50738
  const peg$e24 = peg$classExpectation([["0", "9"]], false, false, false);
50489
50739
  const peg$e25 = peg$literalExpectation(".", false);
50490
- const peg$e26 = peg$classExpectation(["e", "E"], false, false, false);
50491
- const peg$e27 = peg$classExpectation(["+", "-"], false, false, false);
50492
- const peg$e28 = peg$classExpectation(["S", "s"], false, false, false);
50493
- const peg$e29 = peg$classExpectation(["T", "t"], false, false, false);
50494
- const peg$e30 = peg$classExpectation(["R", "r"], false, false, false);
50495
- const peg$e31 = peg$classExpectation(["I", "i"], false, false, false);
50496
- const peg$e32 = peg$classExpectation(["C", "c"], false, false, false);
50497
- const peg$e33 = peg$classExpectation(["G", "g"], false, false, false);
50498
- const peg$e34 = peg$classExpectation(["A", "a"], false, false, false);
50499
- const peg$e35 = peg$classExpectation(["P", "p"], false, false, false);
50500
- const peg$e36 = peg$classExpectation(["H", "h"], false, false, false);
50501
- const peg$e37 = peg$classExpectation(["D", "d"], false, false, false);
50502
- const peg$e38 = peg$classExpectation(["N", "n"], false, false, false);
50503
- const peg$e39 = peg$classExpectation(["O", "o"], false, false, false);
50504
- const peg$e40 = peg$classExpectation(["E", "e"], false, false, false);
50505
- const peg$e41 = peg$classExpectation(["U", "u"], false, false, false);
50506
- const peg$e42 = peg$classExpectation(["B", "b"], false, false, false);
50507
- const peg$e43 = peg$classExpectation([" ", " ", "\r", "\n"], false, false, false);
50508
- const peg$e44 = peg$literalExpectation("/*", false);
50509
- const peg$e45 = peg$literalExpectation("*/", false);
50510
- const peg$e46 = peg$literalExpectation("//", false);
50511
- const peg$e47 = peg$classExpectation(["\n"], true, false, false);
50512
- const peg$e48 = peg$literalExpectation("\n", false);
50513
- const peg$e49 = peg$literalExpectation("#", false);
50740
+ const peg$e26 = peg$classExpectation(["S", "s"], false, false, false);
50741
+ const peg$e27 = peg$classExpectation(["T", "t"], false, false, false);
50742
+ const peg$e28 = peg$classExpectation(["R", "r"], false, false, false);
50743
+ const peg$e29 = peg$classExpectation(["I", "i"], false, false, false);
50744
+ const peg$e30 = peg$classExpectation(["C", "c"], false, false, false);
50745
+ const peg$e31 = peg$classExpectation(["G", "g"], false, false, false);
50746
+ const peg$e32 = peg$classExpectation(["A", "a"], false, false, false);
50747
+ const peg$e33 = peg$classExpectation(["P", "p"], false, false, false);
50748
+ const peg$e34 = peg$classExpectation(["H", "h"], false, false, false);
50749
+ const peg$e35 = peg$classExpectation(["D", "d"], false, false, false);
50750
+ const peg$e36 = peg$classExpectation(["N", "n"], false, false, false);
50751
+ const peg$e37 = peg$classExpectation(["O", "o"], false, false, false);
50752
+ const peg$e38 = peg$classExpectation(["E", "e"], false, false, false);
50753
+ const peg$e39 = peg$classExpectation(["U", "u"], false, false, false);
50754
+ const peg$e40 = peg$classExpectation(["B", "b"], false, false, false);
50755
+ const peg$e41 = peg$classExpectation([" ", " ", "\r", "\n"], false, false, false);
50756
+ const peg$e42 = peg$literalExpectation("/*", false);
50757
+ const peg$e43 = peg$literalExpectation("*/", false);
50758
+ const peg$e44 = peg$literalExpectation("//", false);
50759
+ const peg$e45 = peg$classExpectation(["\n"], true, false, false);
50760
+ const peg$e46 = peg$literalExpectation("\n", false);
50761
+ const peg$e47 = peg$literalExpectation("#", false);
50514
50762
  function peg$f0(s, t, id, stmts) {
50515
50763
  return {
50516
50764
  type: "graph",
@@ -50553,40 +50801,44 @@ function peg$parse(input, options) {
50553
50801
  function peg$f11(s) {
50554
50802
  return s;
50555
50803
  }
50556
- function peg$f12(t, attrs) {
50804
+ function peg$f12(t, m, attrs) {
50805
+ if (m) console.error("Warning: attribute macros not implemented");
50557
50806
  return { type: "attr", target: t, attrs };
50558
50807
  }
50559
50808
  function peg$f13(a) {
50560
50809
  return { type: "assign", key: a.key, value: a.value };
50561
50810
  }
50562
50811
  function peg$f14() {
50563
- return "graph";
50812
+ return true;
50564
50813
  }
50565
50814
  function peg$f15() {
50566
- return "node";
50815
+ return false;
50567
50816
  }
50568
50817
  function peg$f16() {
50818
+ return "graph";
50819
+ }
50820
+ function peg$f17() {
50821
+ return "node";
50822
+ }
50823
+ function peg$f18() {
50569
50824
  return "edge";
50570
50825
  }
50571
- function peg$f17(defs, rest) {
50826
+ function peg$f19(defs, rest) {
50572
50827
  return defs.concat(rest);
50573
50828
  }
50574
- function peg$f18(defs) {
50575
- return defs;
50576
- }
50577
- function peg$f19() {
50829
+ function peg$f20() {
50578
50830
  return [];
50579
50831
  }
50580
- function peg$f20(a) {
50832
+ function peg$f21(a) {
50581
50833
  return a;
50582
50834
  }
50583
- function peg$f21(pairs) {
50835
+ function peg$f22(pairs) {
50584
50836
  return pairs;
50585
50837
  }
50586
- function peg$f22(k, v) {
50838
+ function peg$f23(k, v) {
50587
50839
  return { key: k, value: v };
50588
50840
  }
50589
- function peg$f23(head, chain, attrs) {
50841
+ function peg$f24(head, chain, attrs) {
50590
50842
  if (chain.length > 0) {
50591
50843
  const nodes = [head].concat(chain);
50592
50844
  return { type: "edge", nodes, attrs };
@@ -50597,70 +50849,70 @@ function peg$parse(input, options) {
50597
50849
  return { type: "node", id: head, attrs };
50598
50850
  }
50599
50851
  }
50600
- function peg$f24(s) {
50852
+ function peg$f25(s) {
50601
50853
  return s;
50602
50854
  }
50603
- function peg$f25(n) {
50855
+ function peg$f26(n) {
50604
50856
  return n;
50605
50857
  }
50606
- function peg$f26(id, port, compass) {
50858
+ function peg$f27(id, port, compass) {
50607
50859
  return { id, port, compass };
50608
50860
  }
50609
- function peg$f27(id, port) {
50861
+ function peg$f28(id, port) {
50610
50862
  return { id, port, compass: null };
50611
50863
  }
50612
- function peg$f28(id) {
50864
+ function peg$f29(id) {
50613
50865
  return { id, port: null, compass: null };
50614
50866
  }
50615
- function peg$f29(s, rest) {
50867
+ function peg$f30(s, rest) {
50616
50868
  return [s].concat(rest);
50617
50869
  }
50618
- function peg$f30() {
50870
+ function peg$f31() {
50619
50871
  return [];
50620
50872
  }
50621
- function peg$f31(id, stmts) {
50873
+ function peg$f32(id, stmts) {
50622
50874
  return { type: "subgraph", id, stmts };
50623
50875
  }
50624
- function peg$f32(stmts) {
50876
+ function peg$f33(stmts) {
50625
50877
  return { type: "subgraph", id: null, stmts };
50626
50878
  }
50627
- function peg$f33(stmts) {
50879
+ function peg$f34(stmts) {
50628
50880
  return { type: "subgraph", id: null, stmts };
50629
50881
  }
50630
- function peg$f34(first, s) {
50882
+ function peg$f35(first, s) {
50631
50883
  return s;
50632
50884
  }
50633
- function peg$f35(first, rest) {
50885
+ function peg$f36(first, rest) {
50634
50886
  return rest.length > 0 ? first + rest.join("") : first;
50635
50887
  }
50636
- function peg$f36(chars) {
50888
+ function peg$f37(chars) {
50637
50889
  return chars.join("");
50638
50890
  }
50639
- function peg$f37() {
50891
+ function peg$f38() {
50640
50892
  return '"';
50641
50893
  }
50642
- function peg$f38() {
50894
+ function peg$f39() {
50643
50895
  return "";
50644
50896
  }
50645
- function peg$f39(c) {
50897
+ function peg$f40(c) {
50646
50898
  return "\\" + c;
50647
50899
  }
50648
- function peg$f40(content) {
50900
+ function peg$f41(content) {
50649
50901
  return "" + content;
50650
50902
  }
50651
- function peg$f41(chars) {
50903
+ function peg$f42(chars) {
50652
50904
  return chars.join("");
50653
50905
  }
50654
- function peg$f42(nested2, content) {
50906
+ function peg$f43(nested2, content) {
50655
50907
  return "<" + content + ">";
50656
50908
  }
50657
- function peg$f43(n) {
50909
+ function peg$f44(n) {
50658
50910
  return n;
50659
50911
  }
50660
- function peg$f44(first, rest) {
50912
+ function peg$f45(first, rest) {
50661
50913
  return first + rest.join("");
50662
50914
  }
50663
- function peg$f45(s) {
50915
+ function peg$f46(s) {
50664
50916
  return Array.isArray(s) ? s.flat(Infinity).filter((x) => x !== null && x !== void 0).join("") : String(s);
50665
50917
  }
50666
50918
  let peg$currPos = options.peg$currPos | 0;
@@ -51031,15 +51283,21 @@ function peg$parse(input, options) {
51031
51283
  return s0;
51032
51284
  }
51033
51285
  function peg$parseAttrStmt() {
51034
- let s0, s12, s2, s3;
51286
+ let s0, s12, s2, s3, s4;
51035
51287
  s0 = peg$currPos;
51036
51288
  s12 = peg$parseAttrType();
51037
51289
  if (s12 !== peg$FAILED) {
51038
51290
  s2 = peg$parse_();
51039
- s3 = peg$parseAttrList();
51291
+ s3 = peg$parseOptMacroName();
51040
51292
  if (s3 !== peg$FAILED) {
51041
- peg$savedPos = s0;
51042
- s0 = peg$f12(s12, s3);
51293
+ s4 = peg$parseAttrListReq();
51294
+ if (s4 !== peg$FAILED) {
51295
+ peg$savedPos = s0;
51296
+ s0 = peg$f12(s12, s3, s4);
51297
+ } else {
51298
+ peg$currPos = s0;
51299
+ s0 = peg$FAILED;
51300
+ }
51043
51301
  } else {
51044
51302
  peg$currPos = s0;
51045
51303
  s0 = peg$FAILED;
@@ -51059,13 +51317,49 @@ function peg$parse(input, options) {
51059
51317
  }
51060
51318
  return s0;
51061
51319
  }
51320
+ function peg$parseOptMacroName() {
51321
+ let s0, s12, s2, s3, s4;
51322
+ s0 = peg$currPos;
51323
+ s12 = peg$parseAtom();
51324
+ if (s12 !== peg$FAILED) {
51325
+ s2 = peg$parse_();
51326
+ if (input.charCodeAt(peg$currPos) === 61) {
51327
+ s3 = peg$c3;
51328
+ peg$currPos++;
51329
+ } else {
51330
+ s3 = peg$FAILED;
51331
+ if (peg$silentFails === 0) {
51332
+ peg$fail(peg$e3);
51333
+ }
51334
+ }
51335
+ if (s3 !== peg$FAILED) {
51336
+ s4 = peg$parse_();
51337
+ peg$savedPos = s0;
51338
+ s0 = peg$f14();
51339
+ } else {
51340
+ peg$currPos = s0;
51341
+ s0 = peg$FAILED;
51342
+ }
51343
+ } else {
51344
+ peg$currPos = s0;
51345
+ s0 = peg$FAILED;
51346
+ }
51347
+ if (s0 === peg$FAILED) {
51348
+ s0 = peg$currPos;
51349
+ s12 = "";
51350
+ peg$savedPos = s0;
51351
+ s12 = peg$f15();
51352
+ s0 = s12;
51353
+ }
51354
+ return s0;
51355
+ }
51062
51356
  function peg$parseAttrType() {
51063
51357
  let s0, s12;
51064
51358
  s0 = peg$currPos;
51065
51359
  s12 = peg$parseGraphKw();
51066
51360
  if (s12 !== peg$FAILED) {
51067
51361
  peg$savedPos = s0;
51068
- s12 = peg$f14();
51362
+ s12 = peg$f16();
51069
51363
  }
51070
51364
  s0 = s12;
51071
51365
  if (s0 === peg$FAILED) {
@@ -51073,7 +51367,7 @@ function peg$parse(input, options) {
51073
51367
  s12 = peg$parseNodeKw();
51074
51368
  if (s12 !== peg$FAILED) {
51075
51369
  peg$savedPos = s0;
51076
- s12 = peg$f15();
51370
+ s12 = peg$f17();
51077
51371
  }
51078
51372
  s0 = s12;
51079
51373
  if (s0 === peg$FAILED) {
@@ -51081,24 +51375,24 @@ function peg$parse(input, options) {
51081
51375
  s12 = peg$parseEdgeKw();
51082
51376
  if (s12 !== peg$FAILED) {
51083
51377
  peg$savedPos = s0;
51084
- s12 = peg$f16();
51378
+ s12 = peg$f18();
51085
51379
  }
51086
51380
  s0 = s12;
51087
51381
  }
51088
51382
  }
51089
51383
  return s0;
51090
51384
  }
51091
- function peg$parseAttrList() {
51385
+ function peg$parseAttrListReq() {
51092
51386
  let s0, s12, s2, s3, s4, s5, s6, s7;
51093
51387
  s0 = peg$currPos;
51094
51388
  s12 = peg$parse_();
51095
51389
  if (input.charCodeAt(peg$currPos) === 91) {
51096
- s2 = peg$c3;
51390
+ s2 = peg$c4;
51097
51391
  peg$currPos++;
51098
51392
  } else {
51099
51393
  s2 = peg$FAILED;
51100
51394
  if (peg$silentFails === 0) {
51101
- peg$fail(peg$e3);
51395
+ peg$fail(peg$e4);
51102
51396
  }
51103
51397
  }
51104
51398
  if (s2 !== peg$FAILED) {
@@ -51106,19 +51400,19 @@ function peg$parse(input, options) {
51106
51400
  s4 = peg$parseAttrDefs();
51107
51401
  s5 = peg$parse_();
51108
51402
  if (input.charCodeAt(peg$currPos) === 93) {
51109
- s6 = peg$c4;
51403
+ s6 = peg$c5;
51110
51404
  peg$currPos++;
51111
51405
  } else {
51112
51406
  s6 = peg$FAILED;
51113
51407
  if (peg$silentFails === 0) {
51114
- peg$fail(peg$e4);
51408
+ peg$fail(peg$e5);
51115
51409
  }
51116
51410
  }
51117
51411
  if (s6 !== peg$FAILED) {
51118
51412
  s7 = peg$parseAttrList();
51119
51413
  if (s7 !== peg$FAILED) {
51120
51414
  peg$savedPos = s0;
51121
- s0 = peg$f17(s4, s7);
51415
+ s0 = peg$f19(s4, s7);
51122
51416
  } else {
51123
51417
  peg$currPos = s0;
51124
51418
  s0 = peg$FAILED;
@@ -51131,49 +51425,17 @@ function peg$parse(input, options) {
51131
51425
  peg$currPos = s0;
51132
51426
  s0 = peg$FAILED;
51133
51427
  }
51428
+ return s0;
51429
+ }
51430
+ function peg$parseAttrList() {
51431
+ let s0, s12;
51432
+ s0 = peg$parseAttrListReq();
51134
51433
  if (s0 === peg$FAILED) {
51135
51434
  s0 = peg$currPos;
51136
- s12 = peg$parse_();
51137
- if (input.charCodeAt(peg$currPos) === 91) {
51138
- s2 = peg$c3;
51139
- peg$currPos++;
51140
- } else {
51141
- s2 = peg$FAILED;
51142
- if (peg$silentFails === 0) {
51143
- peg$fail(peg$e3);
51144
- }
51145
- }
51146
- if (s2 !== peg$FAILED) {
51147
- s3 = peg$parse_();
51148
- s4 = peg$parseAttrDefs();
51149
- s5 = peg$parse_();
51150
- if (input.charCodeAt(peg$currPos) === 93) {
51151
- s6 = peg$c4;
51152
- peg$currPos++;
51153
- } else {
51154
- s6 = peg$FAILED;
51155
- if (peg$silentFails === 0) {
51156
- peg$fail(peg$e4);
51157
- }
51158
- }
51159
- if (s6 !== peg$FAILED) {
51160
- peg$savedPos = s0;
51161
- s0 = peg$f18(s4);
51162
- } else {
51163
- peg$currPos = s0;
51164
- s0 = peg$FAILED;
51165
- }
51166
- } else {
51167
- peg$currPos = s0;
51168
- s0 = peg$FAILED;
51169
- }
51170
- if (s0 === peg$FAILED) {
51171
- s0 = peg$currPos;
51172
- s12 = "";
51173
- peg$savedPos = s0;
51174
- s12 = peg$f19();
51175
- s0 = s12;
51176
- }
51435
+ s12 = "";
51436
+ peg$savedPos = s0;
51437
+ s12 = peg$f20();
51438
+ s0 = s12;
51177
51439
  }
51178
51440
  return s0;
51179
51441
  }
@@ -51192,7 +51454,7 @@ function peg$parse(input, options) {
51192
51454
  } else {
51193
51455
  s6 = peg$FAILED;
51194
51456
  if (peg$silentFails === 0) {
51195
- peg$fail(peg$e5);
51457
+ peg$fail(peg$e6);
51196
51458
  }
51197
51459
  }
51198
51460
  if (s6 !== peg$FAILED) {
@@ -51207,7 +51469,7 @@ function peg$parse(input, options) {
51207
51469
  s5 = null;
51208
51470
  }
51209
51471
  peg$savedPos = s2;
51210
- s2 = peg$f20(s3);
51472
+ s2 = peg$f21(s3);
51211
51473
  } else {
51212
51474
  peg$currPos = s2;
51213
51475
  s2 = peg$FAILED;
@@ -51225,7 +51487,7 @@ function peg$parse(input, options) {
51225
51487
  } else {
51226
51488
  s6 = peg$FAILED;
51227
51489
  if (peg$silentFails === 0) {
51228
- peg$fail(peg$e5);
51490
+ peg$fail(peg$e6);
51229
51491
  }
51230
51492
  }
51231
51493
  if (s6 !== peg$FAILED) {
@@ -51240,14 +51502,14 @@ function peg$parse(input, options) {
51240
51502
  s5 = null;
51241
51503
  }
51242
51504
  peg$savedPos = s2;
51243
- s2 = peg$f20(s3);
51505
+ s2 = peg$f21(s3);
51244
51506
  } else {
51245
51507
  peg$currPos = s2;
51246
51508
  s2 = peg$FAILED;
51247
51509
  }
51248
51510
  }
51249
51511
  peg$savedPos = s0;
51250
- s12 = peg$f21(s12);
51512
+ s12 = peg$f22(s12);
51251
51513
  s0 = s12;
51252
51514
  return s0;
51253
51515
  }
@@ -51258,12 +51520,12 @@ function peg$parse(input, options) {
51258
51520
  if (s12 !== peg$FAILED) {
51259
51521
  s2 = peg$parse_();
51260
51522
  if (input.charCodeAt(peg$currPos) === 61) {
51261
- s3 = peg$c5;
51523
+ s3 = peg$c3;
51262
51524
  peg$currPos++;
51263
51525
  } else {
51264
51526
  s3 = peg$FAILED;
51265
51527
  if (peg$silentFails === 0) {
51266
- peg$fail(peg$e6);
51528
+ peg$fail(peg$e3);
51267
51529
  }
51268
51530
  }
51269
51531
  if (s3 !== peg$FAILED) {
@@ -51271,7 +51533,7 @@ function peg$parse(input, options) {
51271
51533
  s5 = peg$parseAtom();
51272
51534
  if (s5 !== peg$FAILED) {
51273
51535
  peg$savedPos = s0;
51274
- s0 = peg$f22(s12, s5);
51536
+ s0 = peg$f23(s12, s5);
51275
51537
  } else {
51276
51538
  peg$currPos = s0;
51277
51539
  s0 = peg$FAILED;
@@ -51298,7 +51560,7 @@ function peg$parse(input, options) {
51298
51560
  s5 = peg$parseAttrList();
51299
51561
  if (s5 !== peg$FAILED) {
51300
51562
  peg$savedPos = s0;
51301
- s0 = peg$f23(s12, s3, s5);
51563
+ s0 = peg$f24(s12, s3, s5);
51302
51564
  } else {
51303
51565
  peg$currPos = s0;
51304
51566
  s0 = peg$FAILED;
@@ -51319,7 +51581,7 @@ function peg$parse(input, options) {
51319
51581
  s12 = peg$parseSubgraph();
51320
51582
  if (s12 !== peg$FAILED) {
51321
51583
  peg$savedPos = s0;
51322
- s12 = peg$f24(s12);
51584
+ s12 = peg$f25(s12);
51323
51585
  }
51324
51586
  s0 = s12;
51325
51587
  if (s0 === peg$FAILED) {
@@ -51327,7 +51589,7 @@ function peg$parse(input, options) {
51327
51589
  s12 = peg$parseNode();
51328
51590
  if (s12 !== peg$FAILED) {
51329
51591
  peg$savedPos = s0;
51330
- s12 = peg$f25(s12);
51592
+ s12 = peg$f26(s12);
51331
51593
  }
51332
51594
  s0 = s12;
51333
51595
  }
@@ -51367,7 +51629,7 @@ function peg$parse(input, options) {
51367
51629
  s9 = peg$parseAtom();
51368
51630
  if (s9 !== peg$FAILED) {
51369
51631
  peg$savedPos = s0;
51370
- s0 = peg$f26(s12, s5, s9);
51632
+ s0 = peg$f27(s12, s5, s9);
51371
51633
  } else {
51372
51634
  peg$currPos = s0;
51373
51635
  s0 = peg$FAILED;
@@ -51407,7 +51669,7 @@ function peg$parse(input, options) {
51407
51669
  s5 = peg$parseAtom();
51408
51670
  if (s5 !== peg$FAILED) {
51409
51671
  peg$savedPos = s0;
51410
- s0 = peg$f27(s12, s5);
51672
+ s0 = peg$f28(s12, s5);
51411
51673
  } else {
51412
51674
  peg$currPos = s0;
51413
51675
  s0 = peg$FAILED;
@@ -51425,7 +51687,7 @@ function peg$parse(input, options) {
51425
51687
  s12 = peg$parseAtom();
51426
51688
  if (s12 !== peg$FAILED) {
51427
51689
  peg$savedPos = s0;
51428
- s12 = peg$f28(s12);
51690
+ s12 = peg$f29(s12);
51429
51691
  }
51430
51692
  s0 = s12;
51431
51693
  }
@@ -51444,7 +51706,7 @@ function peg$parse(input, options) {
51444
51706
  s5 = peg$parseEdgeChain();
51445
51707
  if (s5 !== peg$FAILED) {
51446
51708
  peg$savedPos = s0;
51447
- s0 = peg$f29(s3, s5);
51709
+ s0 = peg$f30(s3, s5);
51448
51710
  } else {
51449
51711
  peg$currPos = s0;
51450
51712
  s0 = peg$FAILED;
@@ -51461,7 +51723,7 @@ function peg$parse(input, options) {
51461
51723
  s0 = peg$currPos;
51462
51724
  s12 = "";
51463
51725
  peg$savedPos = s0;
51464
- s12 = peg$f30();
51726
+ s12 = peg$f31();
51465
51727
  s0 = s12;
51466
51728
  }
51467
51729
  return s0;
@@ -51532,7 +51794,7 @@ function peg$parse(input, options) {
51532
51794
  }
51533
51795
  if (s9 !== peg$FAILED) {
51534
51796
  peg$savedPos = s0;
51535
- s0 = peg$f31(s3, s7);
51797
+ s0 = peg$f32(s3, s7);
51536
51798
  } else {
51537
51799
  peg$currPos = s0;
51538
51800
  s0 = peg$FAILED;
@@ -51583,7 +51845,7 @@ function peg$parse(input, options) {
51583
51845
  }
51584
51846
  if (s7 !== peg$FAILED) {
51585
51847
  peg$savedPos = s0;
51586
- s0 = peg$f32(s5);
51848
+ s0 = peg$f33(s5);
51587
51849
  } else {
51588
51850
  peg$currPos = s0;
51589
51851
  s0 = peg$FAILED;
@@ -51627,7 +51889,7 @@ function peg$parse(input, options) {
51627
51889
  }
51628
51890
  if (s5 !== peg$FAILED) {
51629
51891
  peg$savedPos = s0;
51630
- s0 = peg$f33(s3);
51892
+ s0 = peg$f34(s3);
51631
51893
  } else {
51632
51894
  peg$currPos = s0;
51633
51895
  s0 = peg$FAILED;
@@ -51666,7 +51928,7 @@ function peg$parse(input, options) {
51666
51928
  s7 = peg$parseQAtom();
51667
51929
  if (s7 !== peg$FAILED) {
51668
51930
  peg$savedPos = s3;
51669
- s3 = peg$f34(s12, s7);
51931
+ s3 = peg$f35(s12, s7);
51670
51932
  } else {
51671
51933
  peg$currPos = s3;
51672
51934
  s3 = peg$FAILED;
@@ -51693,7 +51955,7 @@ function peg$parse(input, options) {
51693
51955
  s7 = peg$parseQAtom();
51694
51956
  if (s7 !== peg$FAILED) {
51695
51957
  peg$savedPos = s3;
51696
- s3 = peg$f34(s12, s7);
51958
+ s3 = peg$f35(s12, s7);
51697
51959
  } else {
51698
51960
  peg$currPos = s3;
51699
51961
  s3 = peg$FAILED;
@@ -51704,7 +51966,7 @@ function peg$parse(input, options) {
51704
51966
  }
51705
51967
  }
51706
51968
  peg$savedPos = s0;
51707
- s0 = peg$f35(s12, s2);
51969
+ s0 = peg$f36(s12, s2);
51708
51970
  } else {
51709
51971
  peg$currPos = s0;
51710
51972
  s0 = peg$FAILED;
@@ -51752,7 +52014,7 @@ function peg$parse(input, options) {
51752
52014
  }
51753
52015
  if (s3 !== peg$FAILED) {
51754
52016
  peg$savedPos = s0;
51755
- s0 = peg$f36(s2);
52017
+ s0 = peg$f37(s2);
51756
52018
  } else {
51757
52019
  peg$currPos = s0;
51758
52020
  s0 = peg$FAILED;
@@ -51777,7 +52039,7 @@ function peg$parse(input, options) {
51777
52039
  }
51778
52040
  if (s12 !== peg$FAILED) {
51779
52041
  peg$savedPos = s0;
51780
- s12 = peg$f37();
52042
+ s12 = peg$f38();
51781
52043
  }
51782
52044
  s0 = s12;
51783
52045
  if (s0 === peg$FAILED) {
@@ -51793,7 +52055,7 @@ function peg$parse(input, options) {
51793
52055
  }
51794
52056
  if (s12 !== peg$FAILED) {
51795
52057
  peg$savedPos = s0;
51796
- s12 = peg$f38();
52058
+ s12 = peg$f39();
51797
52059
  }
51798
52060
  s0 = s12;
51799
52061
  if (s0 === peg$FAILED) {
@@ -51819,7 +52081,7 @@ function peg$parse(input, options) {
51819
52081
  }
51820
52082
  if (s2 !== peg$FAILED) {
51821
52083
  peg$savedPos = s0;
51822
- s0 = peg$f39(s2);
52084
+ s0 = peg$f40(s2);
51823
52085
  } else {
51824
52086
  peg$currPos = s0;
51825
52087
  s0 = peg$FAILED;
@@ -51868,7 +52130,7 @@ function peg$parse(input, options) {
51868
52130
  }
51869
52131
  if (s3 !== peg$FAILED) {
51870
52132
  peg$savedPos = s0;
51871
- s0 = peg$f40(s2);
52133
+ s0 = peg$f41(s2);
51872
52134
  } else {
51873
52135
  peg$currPos = s0;
51874
52136
  s0 = peg$FAILED;
@@ -51889,7 +52151,7 @@ function peg$parse(input, options) {
51889
52151
  s2 = peg$parseHtmlChar();
51890
52152
  }
51891
52153
  peg$savedPos = s0;
51892
- s12 = peg$f41(s12);
52154
+ s12 = peg$f42(s12);
51893
52155
  s0 = s12;
51894
52156
  return s0;
51895
52157
  }
@@ -51919,7 +52181,7 @@ function peg$parse(input, options) {
51919
52181
  }
51920
52182
  if (s3 !== peg$FAILED) {
51921
52183
  peg$savedPos = s0;
51922
- s0 = peg$f42(s12, s2);
52184
+ s0 = peg$f43(s12, s2);
51923
52185
  } else {
51924
52186
  peg$currPos = s0;
51925
52187
  s0 = peg$FAILED;
@@ -51964,7 +52226,7 @@ function peg$parse(input, options) {
51964
52226
  s2 = peg$parseName();
51965
52227
  if (s2 !== peg$FAILED) {
51966
52228
  peg$savedPos = s0;
51967
- s0 = peg$f43(s2);
52229
+ s0 = peg$f44(s2);
51968
52230
  } else {
51969
52231
  peg$currPos = s0;
51970
52232
  s0 = peg$FAILED;
@@ -52012,7 +52274,7 @@ function peg$parse(input, options) {
52012
52274
  }
52013
52275
  }
52014
52276
  peg$savedPos = s0;
52015
- s0 = peg$f44(s12, s2);
52277
+ s0 = peg$f45(s12, s2);
52016
52278
  } else {
52017
52279
  peg$currPos = s0;
52018
52280
  s0 = peg$FAILED;
@@ -52162,70 +52424,7 @@ function peg$parse(input, options) {
52162
52424
  }
52163
52425
  }
52164
52426
  if (s3 !== peg$FAILED) {
52165
- s4 = peg$currPos;
52166
- s5 = input.charAt(peg$currPos);
52167
- if (peg$r6.test(s5)) {
52168
- peg$currPos++;
52169
- } else {
52170
- s5 = peg$FAILED;
52171
- if (peg$silentFails === 0) {
52172
- peg$fail(peg$e26);
52173
- }
52174
- }
52175
- if (s5 !== peg$FAILED) {
52176
- s6 = input.charAt(peg$currPos);
52177
- if (peg$r7.test(s6)) {
52178
- peg$currPos++;
52179
- } else {
52180
- s6 = peg$FAILED;
52181
- if (peg$silentFails === 0) {
52182
- peg$fail(peg$e27);
52183
- }
52184
- }
52185
- if (s6 === peg$FAILED) {
52186
- s6 = null;
52187
- }
52188
- s7 = [];
52189
- s8 = input.charAt(peg$currPos);
52190
- if (peg$r5.test(s8)) {
52191
- peg$currPos++;
52192
- } else {
52193
- s8 = peg$FAILED;
52194
- if (peg$silentFails === 0) {
52195
- peg$fail(peg$e24);
52196
- }
52197
- }
52198
- if (s8 !== peg$FAILED) {
52199
- while (s8 !== peg$FAILED) {
52200
- s7.push(s8);
52201
- s8 = input.charAt(peg$currPos);
52202
- if (peg$r5.test(s8)) {
52203
- peg$currPos++;
52204
- } else {
52205
- s8 = peg$FAILED;
52206
- if (peg$silentFails === 0) {
52207
- peg$fail(peg$e24);
52208
- }
52209
- }
52210
- }
52211
- } else {
52212
- s7 = peg$FAILED;
52213
- }
52214
- if (s7 !== peg$FAILED) {
52215
- s5 = [s5, s6, s7];
52216
- s4 = s5;
52217
- } else {
52218
- peg$currPos = s4;
52219
- s4 = peg$FAILED;
52220
- }
52221
- } else {
52222
- peg$currPos = s4;
52223
- s4 = peg$FAILED;
52224
- }
52225
- if (s4 === peg$FAILED) {
52226
- s4 = null;
52227
- }
52228
- s2 = [s2, s3, s4];
52427
+ s2 = [s2, s3];
52229
52428
  s12 = s2;
52230
52429
  } else {
52231
52430
  peg$currPos = s12;
@@ -52233,7 +52432,7 @@ function peg$parse(input, options) {
52233
52432
  }
52234
52433
  if (s12 !== peg$FAILED) {
52235
52434
  peg$savedPos = s0;
52236
- s12 = peg$f45(s12);
52435
+ s12 = peg$f46(s12);
52237
52436
  }
52238
52437
  s0 = s12;
52239
52438
  return s0;
@@ -52242,62 +52441,62 @@ function peg$parse(input, options) {
52242
52441
  let s0, s12, s2, s3, s4, s5, s6, s7, s8;
52243
52442
  s0 = peg$currPos;
52244
52443
  s12 = input.charAt(peg$currPos);
52245
- if (peg$r8.test(s12)) {
52444
+ if (peg$r6.test(s12)) {
52246
52445
  peg$currPos++;
52247
52446
  } else {
52248
52447
  s12 = peg$FAILED;
52249
52448
  if (peg$silentFails === 0) {
52250
- peg$fail(peg$e28);
52449
+ peg$fail(peg$e26);
52251
52450
  }
52252
52451
  }
52253
52452
  if (s12 !== peg$FAILED) {
52254
52453
  s2 = input.charAt(peg$currPos);
52255
- if (peg$r9.test(s2)) {
52454
+ if (peg$r7.test(s2)) {
52256
52455
  peg$currPos++;
52257
52456
  } else {
52258
52457
  s2 = peg$FAILED;
52259
52458
  if (peg$silentFails === 0) {
52260
- peg$fail(peg$e29);
52459
+ peg$fail(peg$e27);
52261
52460
  }
52262
52461
  }
52263
52462
  if (s2 !== peg$FAILED) {
52264
52463
  s3 = input.charAt(peg$currPos);
52265
- if (peg$r10.test(s3)) {
52464
+ if (peg$r8.test(s3)) {
52266
52465
  peg$currPos++;
52267
52466
  } else {
52268
52467
  s3 = peg$FAILED;
52269
52468
  if (peg$silentFails === 0) {
52270
- peg$fail(peg$e30);
52469
+ peg$fail(peg$e28);
52271
52470
  }
52272
52471
  }
52273
52472
  if (s3 !== peg$FAILED) {
52274
52473
  s4 = input.charAt(peg$currPos);
52275
- if (peg$r11.test(s4)) {
52474
+ if (peg$r9.test(s4)) {
52276
52475
  peg$currPos++;
52277
52476
  } else {
52278
52477
  s4 = peg$FAILED;
52279
52478
  if (peg$silentFails === 0) {
52280
- peg$fail(peg$e31);
52479
+ peg$fail(peg$e29);
52281
52480
  }
52282
52481
  }
52283
52482
  if (s4 !== peg$FAILED) {
52284
52483
  s5 = input.charAt(peg$currPos);
52285
- if (peg$r12.test(s5)) {
52484
+ if (peg$r10.test(s5)) {
52286
52485
  peg$currPos++;
52287
52486
  } else {
52288
52487
  s5 = peg$FAILED;
52289
52488
  if (peg$silentFails === 0) {
52290
- peg$fail(peg$e32);
52489
+ peg$fail(peg$e30);
52291
52490
  }
52292
52491
  }
52293
52492
  if (s5 !== peg$FAILED) {
52294
52493
  s6 = input.charAt(peg$currPos);
52295
- if (peg$r9.test(s6)) {
52494
+ if (peg$r7.test(s6)) {
52296
52495
  peg$currPos++;
52297
52496
  } else {
52298
52497
  s6 = peg$FAILED;
52299
52498
  if (peg$silentFails === 0) {
52300
- peg$fail(peg$e29);
52499
+ peg$fail(peg$e27);
52301
52500
  }
52302
52501
  }
52303
52502
  if (s6 !== peg$FAILED) {
@@ -52348,52 +52547,52 @@ function peg$parse(input, options) {
52348
52547
  let s0, s12, s2, s3, s4, s5, s6, s7;
52349
52548
  s0 = peg$currPos;
52350
52549
  s12 = input.charAt(peg$currPos);
52351
- if (peg$r13.test(s12)) {
52550
+ if (peg$r11.test(s12)) {
52352
52551
  peg$currPos++;
52353
52552
  } else {
52354
52553
  s12 = peg$FAILED;
52355
52554
  if (peg$silentFails === 0) {
52356
- peg$fail(peg$e33);
52555
+ peg$fail(peg$e31);
52357
52556
  }
52358
52557
  }
52359
52558
  if (s12 !== peg$FAILED) {
52360
52559
  s2 = input.charAt(peg$currPos);
52361
- if (peg$r10.test(s2)) {
52560
+ if (peg$r8.test(s2)) {
52362
52561
  peg$currPos++;
52363
52562
  } else {
52364
52563
  s2 = peg$FAILED;
52365
52564
  if (peg$silentFails === 0) {
52366
- peg$fail(peg$e30);
52565
+ peg$fail(peg$e28);
52367
52566
  }
52368
52567
  }
52369
52568
  if (s2 !== peg$FAILED) {
52370
52569
  s3 = input.charAt(peg$currPos);
52371
- if (peg$r14.test(s3)) {
52570
+ if (peg$r12.test(s3)) {
52372
52571
  peg$currPos++;
52373
52572
  } else {
52374
52573
  s3 = peg$FAILED;
52375
52574
  if (peg$silentFails === 0) {
52376
- peg$fail(peg$e34);
52575
+ peg$fail(peg$e32);
52377
52576
  }
52378
52577
  }
52379
52578
  if (s3 !== peg$FAILED) {
52380
52579
  s4 = input.charAt(peg$currPos);
52381
- if (peg$r15.test(s4)) {
52580
+ if (peg$r13.test(s4)) {
52382
52581
  peg$currPos++;
52383
52582
  } else {
52384
52583
  s4 = peg$FAILED;
52385
52584
  if (peg$silentFails === 0) {
52386
- peg$fail(peg$e35);
52585
+ peg$fail(peg$e33);
52387
52586
  }
52388
52587
  }
52389
52588
  if (s4 !== peg$FAILED) {
52390
52589
  s5 = input.charAt(peg$currPos);
52391
- if (peg$r16.test(s5)) {
52590
+ if (peg$r14.test(s5)) {
52392
52591
  peg$currPos++;
52393
52592
  } else {
52394
52593
  s5 = peg$FAILED;
52395
52594
  if (peg$silentFails === 0) {
52396
- peg$fail(peg$e36);
52595
+ peg$fail(peg$e34);
52397
52596
  }
52398
52597
  }
52399
52598
  if (s5 !== peg$FAILED) {
@@ -52440,72 +52639,72 @@ function peg$parse(input, options) {
52440
52639
  let s0, s12, s2, s3, s4, s5, s6, s7, s8, s9;
52441
52640
  s0 = peg$currPos;
52442
52641
  s12 = input.charAt(peg$currPos);
52443
- if (peg$r17.test(s12)) {
52642
+ if (peg$r15.test(s12)) {
52444
52643
  peg$currPos++;
52445
52644
  } else {
52446
52645
  s12 = peg$FAILED;
52447
52646
  if (peg$silentFails === 0) {
52448
- peg$fail(peg$e37);
52647
+ peg$fail(peg$e35);
52449
52648
  }
52450
52649
  }
52451
52650
  if (s12 !== peg$FAILED) {
52452
52651
  s2 = input.charAt(peg$currPos);
52453
- if (peg$r11.test(s2)) {
52652
+ if (peg$r9.test(s2)) {
52454
52653
  peg$currPos++;
52455
52654
  } else {
52456
52655
  s2 = peg$FAILED;
52457
52656
  if (peg$silentFails === 0) {
52458
- peg$fail(peg$e31);
52657
+ peg$fail(peg$e29);
52459
52658
  }
52460
52659
  }
52461
52660
  if (s2 !== peg$FAILED) {
52462
52661
  s3 = input.charAt(peg$currPos);
52463
- if (peg$r13.test(s3)) {
52662
+ if (peg$r11.test(s3)) {
52464
52663
  peg$currPos++;
52465
52664
  } else {
52466
52665
  s3 = peg$FAILED;
52467
52666
  if (peg$silentFails === 0) {
52468
- peg$fail(peg$e33);
52667
+ peg$fail(peg$e31);
52469
52668
  }
52470
52669
  }
52471
52670
  if (s3 !== peg$FAILED) {
52472
52671
  s4 = input.charAt(peg$currPos);
52473
- if (peg$r10.test(s4)) {
52672
+ if (peg$r8.test(s4)) {
52474
52673
  peg$currPos++;
52475
52674
  } else {
52476
52675
  s4 = peg$FAILED;
52477
52676
  if (peg$silentFails === 0) {
52478
- peg$fail(peg$e30);
52677
+ peg$fail(peg$e28);
52479
52678
  }
52480
52679
  }
52481
52680
  if (s4 !== peg$FAILED) {
52482
52681
  s5 = input.charAt(peg$currPos);
52483
- if (peg$r14.test(s5)) {
52682
+ if (peg$r12.test(s5)) {
52484
52683
  peg$currPos++;
52485
52684
  } else {
52486
52685
  s5 = peg$FAILED;
52487
52686
  if (peg$silentFails === 0) {
52488
- peg$fail(peg$e34);
52687
+ peg$fail(peg$e32);
52489
52688
  }
52490
52689
  }
52491
52690
  if (s5 !== peg$FAILED) {
52492
52691
  s6 = input.charAt(peg$currPos);
52493
- if (peg$r15.test(s6)) {
52692
+ if (peg$r13.test(s6)) {
52494
52693
  peg$currPos++;
52495
52694
  } else {
52496
52695
  s6 = peg$FAILED;
52497
52696
  if (peg$silentFails === 0) {
52498
- peg$fail(peg$e35);
52697
+ peg$fail(peg$e33);
52499
52698
  }
52500
52699
  }
52501
52700
  if (s6 !== peg$FAILED) {
52502
52701
  s7 = input.charAt(peg$currPos);
52503
- if (peg$r16.test(s7)) {
52702
+ if (peg$r14.test(s7)) {
52504
52703
  peg$currPos++;
52505
52704
  } else {
52506
52705
  s7 = peg$FAILED;
52507
52706
  if (peg$silentFails === 0) {
52508
- peg$fail(peg$e36);
52707
+ peg$fail(peg$e34);
52509
52708
  }
52510
52709
  }
52511
52710
  if (s7 !== peg$FAILED) {
@@ -52560,42 +52759,42 @@ function peg$parse(input, options) {
52560
52759
  let s0, s12, s2, s3, s4, s5, s6;
52561
52760
  s0 = peg$currPos;
52562
52761
  s12 = input.charAt(peg$currPos);
52563
- if (peg$r18.test(s12)) {
52762
+ if (peg$r16.test(s12)) {
52564
52763
  peg$currPos++;
52565
52764
  } else {
52566
52765
  s12 = peg$FAILED;
52567
52766
  if (peg$silentFails === 0) {
52568
- peg$fail(peg$e38);
52767
+ peg$fail(peg$e36);
52569
52768
  }
52570
52769
  }
52571
52770
  if (s12 !== peg$FAILED) {
52572
52771
  s2 = input.charAt(peg$currPos);
52573
- if (peg$r19.test(s2)) {
52772
+ if (peg$r17.test(s2)) {
52574
52773
  peg$currPos++;
52575
52774
  } else {
52576
52775
  s2 = peg$FAILED;
52577
52776
  if (peg$silentFails === 0) {
52578
- peg$fail(peg$e39);
52777
+ peg$fail(peg$e37);
52579
52778
  }
52580
52779
  }
52581
52780
  if (s2 !== peg$FAILED) {
52582
52781
  s3 = input.charAt(peg$currPos);
52583
- if (peg$r17.test(s3)) {
52782
+ if (peg$r15.test(s3)) {
52584
52783
  peg$currPos++;
52585
52784
  } else {
52586
52785
  s3 = peg$FAILED;
52587
52786
  if (peg$silentFails === 0) {
52588
- peg$fail(peg$e37);
52787
+ peg$fail(peg$e35);
52589
52788
  }
52590
52789
  }
52591
52790
  if (s3 !== peg$FAILED) {
52592
52791
  s4 = input.charAt(peg$currPos);
52593
- if (peg$r20.test(s4)) {
52792
+ if (peg$r18.test(s4)) {
52594
52793
  peg$currPos++;
52595
52794
  } else {
52596
52795
  s4 = peg$FAILED;
52597
52796
  if (peg$silentFails === 0) {
52598
- peg$fail(peg$e40);
52797
+ peg$fail(peg$e38);
52599
52798
  }
52600
52799
  }
52601
52800
  if (s4 !== peg$FAILED) {
@@ -52638,42 +52837,42 @@ function peg$parse(input, options) {
52638
52837
  let s0, s12, s2, s3, s4, s5, s6;
52639
52838
  s0 = peg$currPos;
52640
52839
  s12 = input.charAt(peg$currPos);
52641
- if (peg$r20.test(s12)) {
52840
+ if (peg$r18.test(s12)) {
52642
52841
  peg$currPos++;
52643
52842
  } else {
52644
52843
  s12 = peg$FAILED;
52645
52844
  if (peg$silentFails === 0) {
52646
- peg$fail(peg$e40);
52845
+ peg$fail(peg$e38);
52647
52846
  }
52648
52847
  }
52649
52848
  if (s12 !== peg$FAILED) {
52650
52849
  s2 = input.charAt(peg$currPos);
52651
- if (peg$r17.test(s2)) {
52850
+ if (peg$r15.test(s2)) {
52652
52851
  peg$currPos++;
52653
52852
  } else {
52654
52853
  s2 = peg$FAILED;
52655
52854
  if (peg$silentFails === 0) {
52656
- peg$fail(peg$e37);
52855
+ peg$fail(peg$e35);
52657
52856
  }
52658
52857
  }
52659
52858
  if (s2 !== peg$FAILED) {
52660
52859
  s3 = input.charAt(peg$currPos);
52661
- if (peg$r13.test(s3)) {
52860
+ if (peg$r11.test(s3)) {
52662
52861
  peg$currPos++;
52663
52862
  } else {
52664
52863
  s3 = peg$FAILED;
52665
52864
  if (peg$silentFails === 0) {
52666
- peg$fail(peg$e33);
52865
+ peg$fail(peg$e31);
52667
52866
  }
52668
52867
  }
52669
52868
  if (s3 !== peg$FAILED) {
52670
52869
  s4 = input.charAt(peg$currPos);
52671
- if (peg$r20.test(s4)) {
52870
+ if (peg$r18.test(s4)) {
52672
52871
  peg$currPos++;
52673
52872
  } else {
52674
52873
  s4 = peg$FAILED;
52675
52874
  if (peg$silentFails === 0) {
52676
- peg$fail(peg$e40);
52875
+ peg$fail(peg$e38);
52677
52876
  }
52678
52877
  }
52679
52878
  if (s4 !== peg$FAILED) {
@@ -52716,82 +52915,82 @@ function peg$parse(input, options) {
52716
52915
  let s0, s12, s2, s3, s4, s5, s6, s7, s8, s9, s10;
52717
52916
  s0 = peg$currPos;
52718
52917
  s12 = input.charAt(peg$currPos);
52719
- if (peg$r8.test(s12)) {
52918
+ if (peg$r6.test(s12)) {
52720
52919
  peg$currPos++;
52721
52920
  } else {
52722
52921
  s12 = peg$FAILED;
52723
52922
  if (peg$silentFails === 0) {
52724
- peg$fail(peg$e28);
52923
+ peg$fail(peg$e26);
52725
52924
  }
52726
52925
  }
52727
52926
  if (s12 !== peg$FAILED) {
52728
52927
  s2 = input.charAt(peg$currPos);
52729
- if (peg$r21.test(s2)) {
52928
+ if (peg$r19.test(s2)) {
52730
52929
  peg$currPos++;
52731
52930
  } else {
52732
52931
  s2 = peg$FAILED;
52733
52932
  if (peg$silentFails === 0) {
52734
- peg$fail(peg$e41);
52933
+ peg$fail(peg$e39);
52735
52934
  }
52736
52935
  }
52737
52936
  if (s2 !== peg$FAILED) {
52738
52937
  s3 = input.charAt(peg$currPos);
52739
- if (peg$r22.test(s3)) {
52938
+ if (peg$r20.test(s3)) {
52740
52939
  peg$currPos++;
52741
52940
  } else {
52742
52941
  s3 = peg$FAILED;
52743
52942
  if (peg$silentFails === 0) {
52744
- peg$fail(peg$e42);
52943
+ peg$fail(peg$e40);
52745
52944
  }
52746
52945
  }
52747
52946
  if (s3 !== peg$FAILED) {
52748
52947
  s4 = input.charAt(peg$currPos);
52749
- if (peg$r13.test(s4)) {
52948
+ if (peg$r11.test(s4)) {
52750
52949
  peg$currPos++;
52751
52950
  } else {
52752
52951
  s4 = peg$FAILED;
52753
52952
  if (peg$silentFails === 0) {
52754
- peg$fail(peg$e33);
52953
+ peg$fail(peg$e31);
52755
52954
  }
52756
52955
  }
52757
52956
  if (s4 !== peg$FAILED) {
52758
52957
  s5 = input.charAt(peg$currPos);
52759
- if (peg$r10.test(s5)) {
52958
+ if (peg$r8.test(s5)) {
52760
52959
  peg$currPos++;
52761
52960
  } else {
52762
52961
  s5 = peg$FAILED;
52763
52962
  if (peg$silentFails === 0) {
52764
- peg$fail(peg$e30);
52963
+ peg$fail(peg$e28);
52765
52964
  }
52766
52965
  }
52767
52966
  if (s5 !== peg$FAILED) {
52768
52967
  s6 = input.charAt(peg$currPos);
52769
- if (peg$r14.test(s6)) {
52968
+ if (peg$r12.test(s6)) {
52770
52969
  peg$currPos++;
52771
52970
  } else {
52772
52971
  s6 = peg$FAILED;
52773
52972
  if (peg$silentFails === 0) {
52774
- peg$fail(peg$e34);
52973
+ peg$fail(peg$e32);
52775
52974
  }
52776
52975
  }
52777
52976
  if (s6 !== peg$FAILED) {
52778
52977
  s7 = input.charAt(peg$currPos);
52779
- if (peg$r15.test(s7)) {
52978
+ if (peg$r13.test(s7)) {
52780
52979
  peg$currPos++;
52781
52980
  } else {
52782
52981
  s7 = peg$FAILED;
52783
52982
  if (peg$silentFails === 0) {
52784
- peg$fail(peg$e35);
52983
+ peg$fail(peg$e33);
52785
52984
  }
52786
52985
  }
52787
52986
  if (s7 !== peg$FAILED) {
52788
52987
  s8 = input.charAt(peg$currPos);
52789
- if (peg$r16.test(s8)) {
52988
+ if (peg$r14.test(s8)) {
52790
52989
  peg$currPos++;
52791
52990
  } else {
52792
52991
  s8 = peg$FAILED;
52793
52992
  if (peg$silentFails === 0) {
52794
- peg$fail(peg$e36);
52993
+ peg$fail(peg$e34);
52795
52994
  }
52796
52995
  }
52797
52996
  if (s8 !== peg$FAILED) {
@@ -52864,62 +53063,62 @@ function peg$parse(input, options) {
52864
53063
  s0 = peg$currPos;
52865
53064
  s12 = peg$currPos;
52866
53065
  s2 = input.charAt(peg$currPos);
52867
- if (peg$r8.test(s2)) {
53066
+ if (peg$r6.test(s2)) {
52868
53067
  peg$currPos++;
52869
53068
  } else {
52870
53069
  s2 = peg$FAILED;
52871
53070
  if (peg$silentFails === 0) {
52872
- peg$fail(peg$e28);
53071
+ peg$fail(peg$e26);
52873
53072
  }
52874
53073
  }
52875
53074
  if (s2 !== peg$FAILED) {
52876
53075
  s3 = input.charAt(peg$currPos);
52877
- if (peg$r9.test(s3)) {
53076
+ if (peg$r7.test(s3)) {
52878
53077
  peg$currPos++;
52879
53078
  } else {
52880
53079
  s3 = peg$FAILED;
52881
53080
  if (peg$silentFails === 0) {
52882
- peg$fail(peg$e29);
53081
+ peg$fail(peg$e27);
52883
53082
  }
52884
53083
  }
52885
53084
  if (s3 !== peg$FAILED) {
52886
53085
  s4 = input.charAt(peg$currPos);
52887
- if (peg$r10.test(s4)) {
53086
+ if (peg$r8.test(s4)) {
52888
53087
  peg$currPos++;
52889
53088
  } else {
52890
53089
  s4 = peg$FAILED;
52891
53090
  if (peg$silentFails === 0) {
52892
- peg$fail(peg$e30);
53091
+ peg$fail(peg$e28);
52893
53092
  }
52894
53093
  }
52895
53094
  if (s4 !== peg$FAILED) {
52896
53095
  s5 = input.charAt(peg$currPos);
52897
- if (peg$r11.test(s5)) {
53096
+ if (peg$r9.test(s5)) {
52898
53097
  peg$currPos++;
52899
53098
  } else {
52900
53099
  s5 = peg$FAILED;
52901
53100
  if (peg$silentFails === 0) {
52902
- peg$fail(peg$e31);
53101
+ peg$fail(peg$e29);
52903
53102
  }
52904
53103
  }
52905
53104
  if (s5 !== peg$FAILED) {
52906
53105
  s6 = input.charAt(peg$currPos);
52907
- if (peg$r12.test(s6)) {
53106
+ if (peg$r10.test(s6)) {
52908
53107
  peg$currPos++;
52909
53108
  } else {
52910
53109
  s6 = peg$FAILED;
52911
53110
  if (peg$silentFails === 0) {
52912
- peg$fail(peg$e32);
53111
+ peg$fail(peg$e30);
52913
53112
  }
52914
53113
  }
52915
53114
  if (s6 !== peg$FAILED) {
52916
53115
  s7 = input.charAt(peg$currPos);
52917
- if (peg$r9.test(s7)) {
53116
+ if (peg$r7.test(s7)) {
52918
53117
  peg$currPos++;
52919
53118
  } else {
52920
53119
  s7 = peg$FAILED;
52921
53120
  if (peg$silentFails === 0) {
52922
- peg$fail(peg$e29);
53121
+ peg$fail(peg$e27);
52923
53122
  }
52924
53123
  }
52925
53124
  if (s7 !== peg$FAILED) {
@@ -52952,72 +53151,72 @@ function peg$parse(input, options) {
52952
53151
  if (s12 === peg$FAILED) {
52953
53152
  s12 = peg$currPos;
52954
53153
  s2 = input.charAt(peg$currPos);
52955
- if (peg$r17.test(s2)) {
53154
+ if (peg$r15.test(s2)) {
52956
53155
  peg$currPos++;
52957
53156
  } else {
52958
53157
  s2 = peg$FAILED;
52959
53158
  if (peg$silentFails === 0) {
52960
- peg$fail(peg$e37);
53159
+ peg$fail(peg$e35);
52961
53160
  }
52962
53161
  }
52963
53162
  if (s2 !== peg$FAILED) {
52964
53163
  s3 = input.charAt(peg$currPos);
52965
- if (peg$r11.test(s3)) {
53164
+ if (peg$r9.test(s3)) {
52966
53165
  peg$currPos++;
52967
53166
  } else {
52968
53167
  s3 = peg$FAILED;
52969
53168
  if (peg$silentFails === 0) {
52970
- peg$fail(peg$e31);
53169
+ peg$fail(peg$e29);
52971
53170
  }
52972
53171
  }
52973
53172
  if (s3 !== peg$FAILED) {
52974
53173
  s4 = input.charAt(peg$currPos);
52975
- if (peg$r13.test(s4)) {
53174
+ if (peg$r11.test(s4)) {
52976
53175
  peg$currPos++;
52977
53176
  } else {
52978
53177
  s4 = peg$FAILED;
52979
53178
  if (peg$silentFails === 0) {
52980
- peg$fail(peg$e33);
53179
+ peg$fail(peg$e31);
52981
53180
  }
52982
53181
  }
52983
53182
  if (s4 !== peg$FAILED) {
52984
53183
  s5 = input.charAt(peg$currPos);
52985
- if (peg$r10.test(s5)) {
53184
+ if (peg$r8.test(s5)) {
52986
53185
  peg$currPos++;
52987
53186
  } else {
52988
53187
  s5 = peg$FAILED;
52989
53188
  if (peg$silentFails === 0) {
52990
- peg$fail(peg$e30);
53189
+ peg$fail(peg$e28);
52991
53190
  }
52992
53191
  }
52993
53192
  if (s5 !== peg$FAILED) {
52994
53193
  s6 = input.charAt(peg$currPos);
52995
- if (peg$r14.test(s6)) {
53194
+ if (peg$r12.test(s6)) {
52996
53195
  peg$currPos++;
52997
53196
  } else {
52998
53197
  s6 = peg$FAILED;
52999
53198
  if (peg$silentFails === 0) {
53000
- peg$fail(peg$e34);
53199
+ peg$fail(peg$e32);
53001
53200
  }
53002
53201
  }
53003
53202
  if (s6 !== peg$FAILED) {
53004
53203
  s7 = input.charAt(peg$currPos);
53005
- if (peg$r15.test(s7)) {
53204
+ if (peg$r13.test(s7)) {
53006
53205
  peg$currPos++;
53007
53206
  } else {
53008
53207
  s7 = peg$FAILED;
53009
53208
  if (peg$silentFails === 0) {
53010
- peg$fail(peg$e35);
53209
+ peg$fail(peg$e33);
53011
53210
  }
53012
53211
  }
53013
53212
  if (s7 !== peg$FAILED) {
53014
53213
  s8 = input.charAt(peg$currPos);
53015
- if (peg$r16.test(s8)) {
53214
+ if (peg$r14.test(s8)) {
53016
53215
  peg$currPos++;
53017
53216
  } else {
53018
53217
  s8 = peg$FAILED;
53019
53218
  if (peg$silentFails === 0) {
53020
- peg$fail(peg$e36);
53219
+ peg$fail(peg$e34);
53021
53220
  }
53022
53221
  }
53023
53222
  if (s8 !== peg$FAILED) {
@@ -53054,52 +53253,52 @@ function peg$parse(input, options) {
53054
53253
  if (s12 === peg$FAILED) {
53055
53254
  s12 = peg$currPos;
53056
53255
  s2 = input.charAt(peg$currPos);
53057
- if (peg$r13.test(s2)) {
53256
+ if (peg$r11.test(s2)) {
53058
53257
  peg$currPos++;
53059
53258
  } else {
53060
53259
  s2 = peg$FAILED;
53061
53260
  if (peg$silentFails === 0) {
53062
- peg$fail(peg$e33);
53261
+ peg$fail(peg$e31);
53063
53262
  }
53064
53263
  }
53065
53264
  if (s2 !== peg$FAILED) {
53066
53265
  s3 = input.charAt(peg$currPos);
53067
- if (peg$r10.test(s3)) {
53266
+ if (peg$r8.test(s3)) {
53068
53267
  peg$currPos++;
53069
53268
  } else {
53070
53269
  s3 = peg$FAILED;
53071
53270
  if (peg$silentFails === 0) {
53072
- peg$fail(peg$e30);
53271
+ peg$fail(peg$e28);
53073
53272
  }
53074
53273
  }
53075
53274
  if (s3 !== peg$FAILED) {
53076
53275
  s4 = input.charAt(peg$currPos);
53077
- if (peg$r14.test(s4)) {
53276
+ if (peg$r12.test(s4)) {
53078
53277
  peg$currPos++;
53079
53278
  } else {
53080
53279
  s4 = peg$FAILED;
53081
53280
  if (peg$silentFails === 0) {
53082
- peg$fail(peg$e34);
53281
+ peg$fail(peg$e32);
53083
53282
  }
53084
53283
  }
53085
53284
  if (s4 !== peg$FAILED) {
53086
53285
  s5 = input.charAt(peg$currPos);
53087
- if (peg$r15.test(s5)) {
53286
+ if (peg$r13.test(s5)) {
53088
53287
  peg$currPos++;
53089
53288
  } else {
53090
53289
  s5 = peg$FAILED;
53091
53290
  if (peg$silentFails === 0) {
53092
- peg$fail(peg$e35);
53291
+ peg$fail(peg$e33);
53093
53292
  }
53094
53293
  }
53095
53294
  if (s5 !== peg$FAILED) {
53096
53295
  s6 = input.charAt(peg$currPos);
53097
- if (peg$r16.test(s6)) {
53296
+ if (peg$r14.test(s6)) {
53098
53297
  peg$currPos++;
53099
53298
  } else {
53100
53299
  s6 = peg$FAILED;
53101
53300
  if (peg$silentFails === 0) {
53102
- peg$fail(peg$e36);
53301
+ peg$fail(peg$e34);
53103
53302
  }
53104
53303
  }
53105
53304
  if (s6 !== peg$FAILED) {
@@ -53128,42 +53327,42 @@ function peg$parse(input, options) {
53128
53327
  if (s12 === peg$FAILED) {
53129
53328
  s12 = peg$currPos;
53130
53329
  s2 = input.charAt(peg$currPos);
53131
- if (peg$r18.test(s2)) {
53330
+ if (peg$r16.test(s2)) {
53132
53331
  peg$currPos++;
53133
53332
  } else {
53134
53333
  s2 = peg$FAILED;
53135
53334
  if (peg$silentFails === 0) {
53136
- peg$fail(peg$e38);
53335
+ peg$fail(peg$e36);
53137
53336
  }
53138
53337
  }
53139
53338
  if (s2 !== peg$FAILED) {
53140
53339
  s3 = input.charAt(peg$currPos);
53141
- if (peg$r19.test(s3)) {
53340
+ if (peg$r17.test(s3)) {
53142
53341
  peg$currPos++;
53143
53342
  } else {
53144
53343
  s3 = peg$FAILED;
53145
53344
  if (peg$silentFails === 0) {
53146
- peg$fail(peg$e39);
53345
+ peg$fail(peg$e37);
53147
53346
  }
53148
53347
  }
53149
53348
  if (s3 !== peg$FAILED) {
53150
53349
  s4 = input.charAt(peg$currPos);
53151
- if (peg$r17.test(s4)) {
53350
+ if (peg$r15.test(s4)) {
53152
53351
  peg$currPos++;
53153
53352
  } else {
53154
53353
  s4 = peg$FAILED;
53155
53354
  if (peg$silentFails === 0) {
53156
- peg$fail(peg$e37);
53355
+ peg$fail(peg$e35);
53157
53356
  }
53158
53357
  }
53159
53358
  if (s4 !== peg$FAILED) {
53160
53359
  s5 = input.charAt(peg$currPos);
53161
- if (peg$r20.test(s5)) {
53360
+ if (peg$r18.test(s5)) {
53162
53361
  peg$currPos++;
53163
53362
  } else {
53164
53363
  s5 = peg$FAILED;
53165
53364
  if (peg$silentFails === 0) {
53166
- peg$fail(peg$e40);
53365
+ peg$fail(peg$e38);
53167
53366
  }
53168
53367
  }
53169
53368
  if (s5 !== peg$FAILED) {
@@ -53188,42 +53387,42 @@ function peg$parse(input, options) {
53188
53387
  if (s12 === peg$FAILED) {
53189
53388
  s12 = peg$currPos;
53190
53389
  s2 = input.charAt(peg$currPos);
53191
- if (peg$r20.test(s2)) {
53390
+ if (peg$r18.test(s2)) {
53192
53391
  peg$currPos++;
53193
53392
  } else {
53194
53393
  s2 = peg$FAILED;
53195
53394
  if (peg$silentFails === 0) {
53196
- peg$fail(peg$e40);
53395
+ peg$fail(peg$e38);
53197
53396
  }
53198
53397
  }
53199
53398
  if (s2 !== peg$FAILED) {
53200
53399
  s3 = input.charAt(peg$currPos);
53201
- if (peg$r17.test(s3)) {
53400
+ if (peg$r15.test(s3)) {
53202
53401
  peg$currPos++;
53203
53402
  } else {
53204
53403
  s3 = peg$FAILED;
53205
53404
  if (peg$silentFails === 0) {
53206
- peg$fail(peg$e37);
53405
+ peg$fail(peg$e35);
53207
53406
  }
53208
53407
  }
53209
53408
  if (s3 !== peg$FAILED) {
53210
53409
  s4 = input.charAt(peg$currPos);
53211
- if (peg$r13.test(s4)) {
53410
+ if (peg$r11.test(s4)) {
53212
53411
  peg$currPos++;
53213
53412
  } else {
53214
53413
  s4 = peg$FAILED;
53215
53414
  if (peg$silentFails === 0) {
53216
- peg$fail(peg$e33);
53415
+ peg$fail(peg$e31);
53217
53416
  }
53218
53417
  }
53219
53418
  if (s4 !== peg$FAILED) {
53220
53419
  s5 = input.charAt(peg$currPos);
53221
- if (peg$r20.test(s5)) {
53420
+ if (peg$r18.test(s5)) {
53222
53421
  peg$currPos++;
53223
53422
  } else {
53224
53423
  s5 = peg$FAILED;
53225
53424
  if (peg$silentFails === 0) {
53226
- peg$fail(peg$e40);
53425
+ peg$fail(peg$e38);
53227
53426
  }
53228
53427
  }
53229
53428
  if (s5 !== peg$FAILED) {
@@ -53248,82 +53447,82 @@ function peg$parse(input, options) {
53248
53447
  if (s12 === peg$FAILED) {
53249
53448
  s12 = peg$currPos;
53250
53449
  s2 = input.charAt(peg$currPos);
53251
- if (peg$r8.test(s2)) {
53450
+ if (peg$r6.test(s2)) {
53252
53451
  peg$currPos++;
53253
53452
  } else {
53254
53453
  s2 = peg$FAILED;
53255
53454
  if (peg$silentFails === 0) {
53256
- peg$fail(peg$e28);
53455
+ peg$fail(peg$e26);
53257
53456
  }
53258
53457
  }
53259
53458
  if (s2 !== peg$FAILED) {
53260
53459
  s3 = input.charAt(peg$currPos);
53261
- if (peg$r21.test(s3)) {
53460
+ if (peg$r19.test(s3)) {
53262
53461
  peg$currPos++;
53263
53462
  } else {
53264
53463
  s3 = peg$FAILED;
53265
53464
  if (peg$silentFails === 0) {
53266
- peg$fail(peg$e41);
53465
+ peg$fail(peg$e39);
53267
53466
  }
53268
53467
  }
53269
53468
  if (s3 !== peg$FAILED) {
53270
53469
  s4 = input.charAt(peg$currPos);
53271
- if (peg$r22.test(s4)) {
53470
+ if (peg$r20.test(s4)) {
53272
53471
  peg$currPos++;
53273
53472
  } else {
53274
53473
  s4 = peg$FAILED;
53275
53474
  if (peg$silentFails === 0) {
53276
- peg$fail(peg$e42);
53475
+ peg$fail(peg$e40);
53277
53476
  }
53278
53477
  }
53279
53478
  if (s4 !== peg$FAILED) {
53280
53479
  s5 = input.charAt(peg$currPos);
53281
- if (peg$r13.test(s5)) {
53480
+ if (peg$r11.test(s5)) {
53282
53481
  peg$currPos++;
53283
53482
  } else {
53284
53483
  s5 = peg$FAILED;
53285
53484
  if (peg$silentFails === 0) {
53286
- peg$fail(peg$e33);
53485
+ peg$fail(peg$e31);
53287
53486
  }
53288
53487
  }
53289
53488
  if (s5 !== peg$FAILED) {
53290
53489
  s6 = input.charAt(peg$currPos);
53291
- if (peg$r10.test(s6)) {
53490
+ if (peg$r8.test(s6)) {
53292
53491
  peg$currPos++;
53293
53492
  } else {
53294
53493
  s6 = peg$FAILED;
53295
53494
  if (peg$silentFails === 0) {
53296
- peg$fail(peg$e30);
53495
+ peg$fail(peg$e28);
53297
53496
  }
53298
53497
  }
53299
53498
  if (s6 !== peg$FAILED) {
53300
53499
  s7 = input.charAt(peg$currPos);
53301
- if (peg$r14.test(s7)) {
53500
+ if (peg$r12.test(s7)) {
53302
53501
  peg$currPos++;
53303
53502
  } else {
53304
53503
  s7 = peg$FAILED;
53305
53504
  if (peg$silentFails === 0) {
53306
- peg$fail(peg$e34);
53505
+ peg$fail(peg$e32);
53307
53506
  }
53308
53507
  }
53309
53508
  if (s7 !== peg$FAILED) {
53310
53509
  s8 = input.charAt(peg$currPos);
53311
- if (peg$r15.test(s8)) {
53510
+ if (peg$r13.test(s8)) {
53312
53511
  peg$currPos++;
53313
53512
  } else {
53314
53513
  s8 = peg$FAILED;
53315
53514
  if (peg$silentFails === 0) {
53316
- peg$fail(peg$e35);
53515
+ peg$fail(peg$e33);
53317
53516
  }
53318
53517
  }
53319
53518
  if (s8 !== peg$FAILED) {
53320
53519
  s9 = input.charAt(peg$currPos);
53321
- if (peg$r16.test(s9)) {
53520
+ if (peg$r14.test(s9)) {
53322
53521
  peg$currPos++;
53323
53522
  } else {
53324
53523
  s9 = peg$FAILED;
53325
53524
  if (peg$silentFails === 0) {
53326
- peg$fail(peg$e36);
53525
+ peg$fail(peg$e34);
53327
53526
  }
53328
53527
  }
53329
53528
  if (s9 !== peg$FAILED) {
@@ -53395,24 +53594,24 @@ function peg$parse(input, options) {
53395
53594
  s0 = [];
53396
53595
  s12 = [];
53397
53596
  s2 = input.charAt(peg$currPos);
53398
- if (peg$r23.test(s2)) {
53597
+ if (peg$r21.test(s2)) {
53399
53598
  peg$currPos++;
53400
53599
  } else {
53401
53600
  s2 = peg$FAILED;
53402
53601
  if (peg$silentFails === 0) {
53403
- peg$fail(peg$e43);
53602
+ peg$fail(peg$e41);
53404
53603
  }
53405
53604
  }
53406
53605
  if (s2 !== peg$FAILED) {
53407
53606
  while (s2 !== peg$FAILED) {
53408
53607
  s12.push(s2);
53409
53608
  s2 = input.charAt(peg$currPos);
53410
- if (peg$r23.test(s2)) {
53609
+ if (peg$r21.test(s2)) {
53411
53610
  peg$currPos++;
53412
53611
  } else {
53413
53612
  s2 = peg$FAILED;
53414
53613
  if (peg$silentFails === 0) {
53415
- peg$fail(peg$e43);
53614
+ peg$fail(peg$e41);
53416
53615
  }
53417
53616
  }
53418
53617
  }
@@ -53432,24 +53631,24 @@ function peg$parse(input, options) {
53432
53631
  s0.push(s12);
53433
53632
  s12 = [];
53434
53633
  s2 = input.charAt(peg$currPos);
53435
- if (peg$r23.test(s2)) {
53634
+ if (peg$r21.test(s2)) {
53436
53635
  peg$currPos++;
53437
53636
  } else {
53438
53637
  s2 = peg$FAILED;
53439
53638
  if (peg$silentFails === 0) {
53440
- peg$fail(peg$e43);
53639
+ peg$fail(peg$e41);
53441
53640
  }
53442
53641
  }
53443
53642
  if (s2 !== peg$FAILED) {
53444
53643
  while (s2 !== peg$FAILED) {
53445
53644
  s12.push(s2);
53446
53645
  s2 = input.charAt(peg$currPos);
53447
- if (peg$r23.test(s2)) {
53646
+ if (peg$r21.test(s2)) {
53448
53647
  peg$currPos++;
53449
53648
  } else {
53450
53649
  s2 = peg$FAILED;
53451
53650
  if (peg$silentFails === 0) {
53452
- peg$fail(peg$e43);
53651
+ peg$fail(peg$e41);
53453
53652
  }
53454
53653
  }
53455
53654
  }
@@ -53477,7 +53676,7 @@ function peg$parse(input, options) {
53477
53676
  } else {
53478
53677
  s12 = peg$FAILED;
53479
53678
  if (peg$silentFails === 0) {
53480
- peg$fail(peg$e44);
53679
+ peg$fail(peg$e42);
53481
53680
  }
53482
53681
  }
53483
53682
  if (s12 !== peg$FAILED) {
@@ -53491,7 +53690,7 @@ function peg$parse(input, options) {
53491
53690
  } else {
53492
53691
  s5 = peg$FAILED;
53493
53692
  if (peg$silentFails === 0) {
53494
- peg$fail(peg$e45);
53693
+ peg$fail(peg$e43);
53495
53694
  }
53496
53695
  }
53497
53696
  peg$silentFails--;
@@ -53533,7 +53732,7 @@ function peg$parse(input, options) {
53533
53732
  } else {
53534
53733
  s5 = peg$FAILED;
53535
53734
  if (peg$silentFails === 0) {
53536
- peg$fail(peg$e45);
53735
+ peg$fail(peg$e43);
53537
53736
  }
53538
53737
  }
53539
53738
  peg$silentFails--;
@@ -53571,7 +53770,7 @@ function peg$parse(input, options) {
53571
53770
  } else {
53572
53771
  s3 = peg$FAILED;
53573
53772
  if (peg$silentFails === 0) {
53574
- peg$fail(peg$e45);
53773
+ peg$fail(peg$e43);
53575
53774
  }
53576
53775
  }
53577
53776
  if (s3 !== peg$FAILED) {
@@ -53596,29 +53795,29 @@ function peg$parse(input, options) {
53596
53795
  } else {
53597
53796
  s12 = peg$FAILED;
53598
53797
  if (peg$silentFails === 0) {
53599
- peg$fail(peg$e46);
53798
+ peg$fail(peg$e44);
53600
53799
  }
53601
53800
  }
53602
53801
  if (s12 !== peg$FAILED) {
53603
53802
  s2 = [];
53604
53803
  s3 = input.charAt(peg$currPos);
53605
- if (peg$r24.test(s3)) {
53804
+ if (peg$r22.test(s3)) {
53606
53805
  peg$currPos++;
53607
53806
  } else {
53608
53807
  s3 = peg$FAILED;
53609
53808
  if (peg$silentFails === 0) {
53610
- peg$fail(peg$e47);
53809
+ peg$fail(peg$e45);
53611
53810
  }
53612
53811
  }
53613
53812
  while (s3 !== peg$FAILED) {
53614
53813
  s2.push(s3);
53615
53814
  s3 = input.charAt(peg$currPos);
53616
- if (peg$r24.test(s3)) {
53815
+ if (peg$r22.test(s3)) {
53617
53816
  peg$currPos++;
53618
53817
  } else {
53619
53818
  s3 = peg$FAILED;
53620
53819
  if (peg$silentFails === 0) {
53621
- peg$fail(peg$e47);
53820
+ peg$fail(peg$e45);
53622
53821
  }
53623
53822
  }
53624
53823
  }
@@ -53628,7 +53827,7 @@ function peg$parse(input, options) {
53628
53827
  } else {
53629
53828
  s3 = peg$FAILED;
53630
53829
  if (peg$silentFails === 0) {
53631
- peg$fail(peg$e48);
53830
+ peg$fail(peg$e46);
53632
53831
  }
53633
53832
  }
53634
53833
  if (s3 === peg$FAILED) {
@@ -53673,29 +53872,29 @@ function peg$parse(input, options) {
53673
53872
  } else {
53674
53873
  s12 = peg$FAILED;
53675
53874
  if (peg$silentFails === 0) {
53676
- peg$fail(peg$e49);
53875
+ peg$fail(peg$e47);
53677
53876
  }
53678
53877
  }
53679
53878
  if (s12 !== peg$FAILED) {
53680
53879
  s2 = [];
53681
53880
  s3 = input.charAt(peg$currPos);
53682
- if (peg$r24.test(s3)) {
53881
+ if (peg$r22.test(s3)) {
53683
53882
  peg$currPos++;
53684
53883
  } else {
53685
53884
  s3 = peg$FAILED;
53686
53885
  if (peg$silentFails === 0) {
53687
- peg$fail(peg$e47);
53886
+ peg$fail(peg$e45);
53688
53887
  }
53689
53888
  }
53690
53889
  while (s3 !== peg$FAILED) {
53691
53890
  s2.push(s3);
53692
53891
  s3 = input.charAt(peg$currPos);
53693
- if (peg$r24.test(s3)) {
53892
+ if (peg$r22.test(s3)) {
53694
53893
  peg$currPos++;
53695
53894
  } else {
53696
53895
  s3 = peg$FAILED;
53697
53896
  if (peg$silentFails === 0) {
53698
- peg$fail(peg$e47);
53897
+ peg$fail(peg$e45);
53699
53898
  }
53700
53899
  }
53701
53900
  }
@@ -53705,7 +53904,7 @@ function peg$parse(input, options) {
53705
53904
  } else {
53706
53905
  s3 = peg$FAILED;
53707
53906
  if (peg$silentFails === 0) {
53708
- peg$fail(peg$e48);
53907
+ peg$fail(peg$e46);
53709
53908
  }
53710
53909
  }
53711
53910
  if (s3 === peg$FAILED) {
@@ -54068,6 +54267,75 @@ function buildFromAst(ast) {
54068
54267
  return graph;
54069
54268
  }
54070
54269
 
54270
+ // src/parser/number-scan.ts
54271
+ var ASCII_DEL = 127;
54272
+ function isLetter(c) {
54273
+ if (c === void 0) return false;
54274
+ return c >= "A" && c <= "Z" || c >= "a" && c <= "z" || c === "_" || c.charCodeAt(0) > ASCII_DEL;
54275
+ }
54276
+ function isDigit(c) {
54277
+ return c !== void 0 && c >= "0" && c <= "9";
54278
+ }
54279
+ function startsNumber(s, i) {
54280
+ const c = s[i];
54281
+ if (isDigit(c)) return true;
54282
+ if (c === ".") return isDigit(s[i + 1]);
54283
+ if (c !== "-") return false;
54284
+ return isDigit(s[i + 1]) || s[i + 1] === "." && isDigit(s[i + 2]);
54285
+ }
54286
+ function matchNumber(s, i) {
54287
+ let j = s[i] === "-" ? i + 1 : i;
54288
+ if (s[j] === ".") {
54289
+ j++;
54290
+ while (isDigit(s[j])) j++;
54291
+ } else {
54292
+ while (isDigit(s[j])) j++;
54293
+ if (s[j] === ".") {
54294
+ j++;
54295
+ while (isDigit(s[j])) j++;
54296
+ }
54297
+ }
54298
+ if (s[j] === "." || isLetter(s[j])) j++;
54299
+ return j;
54300
+ }
54301
+ function twoDots(text) {
54302
+ const dot = text.indexOf(".");
54303
+ return dot !== -1 && dot !== text.length - 1;
54304
+ }
54305
+ function chkNum(text) {
54306
+ const c = text[text.length - 1];
54307
+ return !isDigit(c) && c !== "." || c === "." && twoDots(text);
54308
+ }
54309
+ function lexToken(s, i) {
54310
+ if (isLetter(s[i])) {
54311
+ let j2 = i + 1;
54312
+ while (isLetter(s[j2]) || isDigit(s[j2])) j2++;
54313
+ return { next: j2, bad: null };
54314
+ }
54315
+ if (s[i] === "-" && (s[i + 1] === "-" || s[i + 1] === ">")) return { next: i + 2, bad: null };
54316
+ if (!startsNumber(s, i)) return { next: i + 1, bad: null };
54317
+ const j = matchNumber(s, i);
54318
+ const text = s.slice(i, j);
54319
+ return chkNum(text) ? { next: j - 1, bad: text } : { next: j, bad: null };
54320
+ }
54321
+ function scanNumberAmbiguities(src, stripped) {
54322
+ const out = [];
54323
+ let line = 1;
54324
+ let lineAt = 0;
54325
+ for (let i = 0; i < stripped.length; ) {
54326
+ const { next, bad } = lexToken(stripped, i);
54327
+ if (bad !== null) {
54328
+ for (; lineAt < i; lineAt++) if (src[lineAt] === "\n") line++;
54329
+ out.push({ text: bad, line, offset: i });
54330
+ }
54331
+ i = next;
54332
+ }
54333
+ return out;
54334
+ }
54335
+ function numberAmbiguityMessage(a) {
54336
+ return `Warning: syntax ambiguity - badly delimited number '${a.text}' in line ${a.line} of input splits into two tokens`;
54337
+ }
54338
+
54071
54339
  // src/parser/index.ts
54072
54340
  var ParseError = class extends DotEngineError {
54073
54341
  type = "syntax";
@@ -54227,6 +54495,12 @@ function isPeggyError(err) {
54227
54495
  if (typeof e["location"] !== "object" || e["location"] === null) return false;
54228
54496
  return "start" in e["location"];
54229
54497
  }
54498
+ function warnNumberAmbiguities(src, upTo) {
54499
+ for (const a of scanNumberAmbiguities(src, Stripper.strip(src))) {
54500
+ if (a.offset > upTo) break;
54501
+ console.error(numberAmbiguityMessage(a));
54502
+ }
54503
+ }
54230
54504
  function parse(src) {
54231
54505
  if (typeof src !== "string") {
54232
54506
  throw invalidArgType("dotSource", "string", src);
@@ -54237,6 +54511,7 @@ function parse(src) {
54237
54511
  } catch (err) {
54238
54512
  if (isPeggyError(err)) {
54239
54513
  const start = err.location.start;
54514
+ warnNumberAmbiguities(src, start.offset);
54240
54515
  const code = err.found === null ? "SYNTAX_UNEXPECTED_EOF" : "SYNTAX_ERROR";
54241
54516
  throw new ParseError(
54242
54517
  err instanceof Error ? err.message : String(err),
@@ -54254,6 +54529,7 @@ function parse(src) {
54254
54529
  }
54255
54530
  throw err;
54256
54531
  }
54532
+ warnNumberAmbiguities(src, src.length);
54257
54533
  validateEdgeOperators(src, ast.directed);
54258
54534
  return buildFromAst(ast);
54259
54535
  }
@@ -54262,6 +54538,7 @@ function parse(src) {
54262
54538
  var XDOT_PARSE_ERROR = 1;
54263
54539
 
54264
54540
  // src/xdot/parse.ts
54541
+ var ULONG_MAX = 0xffffffffffffffffn;
54265
54542
  var XdotParser = class _XdotParser {
54266
54543
  static isWs(c) {
54267
54544
  return c === " " || c === " " || c === "\n" || c === "\r";
@@ -54305,12 +54582,23 @@ var XdotParser = class _XdotParser {
54305
54582
  if (i === digStart) return null;
54306
54583
  return { val: parseInt(s.slice(start, i), 10), pos: i };
54307
54584
  }
54585
+ /**
54586
+ * strtoul(s, &endp, 10) cast to unsigned int: optional sign, a leading "-"
54587
+ * negates modulo 2^64, magnitude overflow saturates to ULONG_MAX, and the
54588
+ * result keeps the low 32 bits.
54589
+ * @see lib/xdot/xdot.c:parseUInt
54590
+ */
54308
54591
  static parseUInt_(s, pos) {
54309
54592
  const i = _XdotParser.skipWs(s, pos);
54310
- const start = i;
54311
- const end = _XdotParser.consumeDigits(s, i);
54593
+ let start = i;
54594
+ const negative = i < s.length && s[i] === "-";
54595
+ if (i < s.length && (s[i] === "-" || s[i] === "+")) start++;
54596
+ const end = _XdotParser.consumeDigits(s, start);
54312
54597
  if (end === start) return null;
54313
- return { val: parseInt(s.slice(start, end), 10), pos: end };
54598
+ const mag = BigInt(s.slice(start, end));
54599
+ const clamped = mag > ULONG_MAX ? ULONG_MAX : mag;
54600
+ const wrapped = negative && mag <= ULONG_MAX ? BigInt.asUintN(64, -clamped) : clamped;
54601
+ return { val: Number(BigInt.asUintN(32, wrapped)), pos: end };
54314
54602
  }
54315
54603
  static parseRect(s, pos) {
54316
54604
  const rx = _XdotParser.parseReal(s, pos);
@@ -54407,7 +54695,7 @@ var XdotParser = class _XdotParser {
54407
54695
  if (!rx1) return null;
54408
54696
  const ry1 = _XdotParser.parseReal(s, rx1.pos);
54409
54697
  if (!ry1) return null;
54410
- const rn = _XdotParser.parseInt_(s, ry1.pos);
54698
+ const rn = _XdotParser.parseUInt_(s, ry1.pos);
54411
54699
  if (!rn) return null;
54412
54700
  const rs = _XdotParser.parseStops(s, rn.pos, rn.val);
54413
54701
  if (!rs) return null;
@@ -54426,7 +54714,7 @@ var XdotParser = class _XdotParser {
54426
54714
  if (!ry1) return null;
54427
54715
  const rr1 = _XdotParser.parseReal(s, ry1.pos);
54428
54716
  if (!rr1) return null;
54429
- const rn = _XdotParser.parseInt_(s, rr1.pos);
54717
+ const rn = _XdotParser.parseUInt_(s, rr1.pos);
54430
54718
  if (!rn) return null;
54431
54719
  const rs = _XdotParser.parseStops(s, rn.pos, rn.val);
54432
54720
  if (!rs) return null;