@knowvah/dot-engine 2.6.10 → 2.6.12

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 (131) hide show
  1. package/dist/async/render-async.d.ts.map +1 -1
  2. package/dist/common/agerr.d.ts +37 -0
  3. package/dist/common/agerr.d.ts.map +1 -0
  4. package/dist/common/arrows-shapes-poly.d.ts.map +1 -1
  5. package/dist/common/color.d.ts.map +1 -1
  6. package/dist/common/crand.d.ts +0 -20
  7. package/dist/common/crand.d.ts.map +1 -1
  8. package/dist/common/emit-once.d.ts +6 -0
  9. package/dist/common/emit-once.d.ts.map +1 -0
  10. package/dist/common/graph-init.d.ts.map +1 -1
  11. package/dist/common/html-entities.d.ts +13 -5
  12. package/dist/common/html-entities.d.ts.map +1 -1
  13. package/dist/common/htmltable-attr-warn.d.ts.map +1 -1
  14. package/dist/common/htmltable-emit-fill.d.ts +9 -0
  15. package/dist/common/htmltable-emit-fill.d.ts.map +1 -1
  16. package/dist/common/htmltable-emit-rules.d.ts.map +1 -1
  17. package/dist/common/htmltable-lex-chardata.d.ts +9 -0
  18. package/dist/common/htmltable-lex-chardata.d.ts.map +1 -1
  19. package/dist/common/htmltable-lex-expat.d.ts +1 -6
  20. package/dist/common/htmltable-lex-expat.d.ts.map +1 -1
  21. package/dist/common/htmltable.d.ts +1 -7
  22. package/dist/common/htmltable.d.ts.map +1 -1
  23. package/dist/common/poly-gencode.d.ts.map +1 -1
  24. package/dist/common/poly-init.d.ts.map +1 -1
  25. package/dist/common/postproc.d.ts.map +1 -1
  26. package/dist/common/random.d.ts.map +1 -1
  27. package/dist/common/render-state.d.ts +8 -0
  28. package/dist/common/render-state.d.ts.map +1 -0
  29. package/dist/common/splines-geom.d.ts +8 -0
  30. package/dist/common/splines-geom.d.ts.map +1 -1
  31. package/dist/common/splines-routespl.d.ts.map +1 -1
  32. package/dist/common/textmeasure-lookup.d.ts.map +1 -1
  33. package/dist/common/textmeasure.d.ts.map +1 -1
  34. package/dist/gvc/anchor.d.ts.map +1 -1
  35. package/dist/gvc/device-cluster.d.ts.map +1 -1
  36. package/dist/gvc/device-labels.d.ts +14 -0
  37. package/dist/gvc/device-labels.d.ts.map +1 -1
  38. package/dist/gvc/device.d.ts.map +1 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +821 -471
  41. package/dist/index.js.map +4 -4
  42. package/dist/layout/dot/cluster.d.ts.map +1 -1
  43. package/dist/layout/dot/conc.d.ts.map +1 -1
  44. package/dist/layout/dot/decomp.d.ts.map +1 -1
  45. package/dist/layout/dot/edge-route-clip.d.ts +18 -10
  46. package/dist/layout/dot/edge-route-clip.d.ts.map +1 -1
  47. package/dist/layout/dot/mincross-build.d.ts.map +1 -1
  48. package/dist/layout/dot/mincross-cross.d.ts.map +1 -1
  49. package/dist/layout/dot/rank.d.ts.map +1 -1
  50. package/dist/layout/dot/splines.d.ts.map +1 -1
  51. package/dist/layout/fdp/index.d.ts.map +1 -1
  52. package/dist/layout/fdp/tlayout-parms.d.ts.map +1 -1
  53. package/dist/layout/fdp/xlayout.d.ts.map +1 -1
  54. package/dist/layout/neato/edge-len.d.ts.map +1 -1
  55. package/dist/layout/neato/fdp-adjust.d.ts.map +1 -1
  56. package/dist/layout/neato/init.d.ts +4 -10
  57. package/dist/layout/neato/init.d.ts.map +1 -1
  58. package/dist/layout/neato/kk.d.ts.map +1 -1
  59. package/dist/layout/neato/multispline-router.d.ts.map +1 -1
  60. package/dist/layout/neato/multispline.d.ts.map +1 -1
  61. package/dist/layout/neato/poly.d.ts.map +1 -1
  62. package/dist/layout/neato/sgd.d.ts.map +1 -1
  63. package/dist/layout/neato/start.d.ts.map +1 -1
  64. package/dist/ortho/index.d.ts.map +1 -1
  65. package/dist/parser/index.d.ts.map +1 -1
  66. package/dist/render/color-resolve.d.ts +49 -1
  67. package/dist/render/color-resolve.d.ts.map +1 -1
  68. package/dist/render/public.d.ts.map +1 -1
  69. package/dist/render/svg-edge-split.d.ts +2 -0
  70. package/dist/render/svg-edge-split.d.ts.map +1 -1
  71. package/dist/render/xdot-public.d.ts.map +1 -1
  72. package/dist/render.js +569 -220
  73. package/dist/render.js.map +4 -4
  74. package/package.json +1 -1
  75. package/src/async/render-async.ts +6 -0
  76. package/src/common/agerr.ts +96 -0
  77. package/src/common/arrows-shapes-poly.ts +19 -5
  78. package/src/common/color.ts +38 -10
  79. package/src/common/crand.ts +8 -2
  80. package/src/common/emit-once.ts +27 -0
  81. package/src/common/graph-init.ts +2 -1
  82. package/src/common/html-entities.ts +77 -25
  83. package/src/common/htmltable-attr-warn.ts +3 -4
  84. package/src/common/htmltable-emit-fill.ts +48 -0
  85. package/src/common/htmltable-emit-rules.ts +2 -0
  86. package/src/common/htmltable-lex-chardata.ts +42 -8
  87. package/src/common/htmltable-lex-expat.ts +78 -23
  88. package/src/common/htmltable.ts +15 -16
  89. package/src/common/poly-gencode.ts +14 -2
  90. package/src/common/poly-init.ts +2 -1
  91. package/src/common/postproc.ts +4 -1
  92. package/src/common/random.ts +11 -1
  93. package/src/common/render-state.ts +36 -0
  94. package/src/common/splines-geom.ts +8 -4
  95. package/src/common/splines-routespl.ts +2 -1
  96. package/src/common/textmeasure-lookup.ts +10 -3
  97. package/src/common/textmeasure.ts +45 -2
  98. package/src/gvc/anchor.ts +1 -12
  99. package/src/gvc/device-cluster.ts +37 -9
  100. package/src/gvc/device-labels.ts +27 -0
  101. package/src/gvc/device.ts +18 -6
  102. package/src/index.ts +3 -0
  103. package/src/layout/dot/cluster.ts +2 -1
  104. package/src/layout/dot/conc.ts +6 -5
  105. package/src/layout/dot/decomp.ts +3 -0
  106. package/src/layout/dot/edge-route-clip.ts +27 -21
  107. package/src/layout/dot/mincross-build.ts +2 -0
  108. package/src/layout/dot/mincross-cross.ts +2 -0
  109. package/src/layout/dot/rank.ts +2 -0
  110. package/src/layout/dot/splines.ts +2 -1
  111. package/src/layout/fdp/index.ts +2 -1
  112. package/src/layout/fdp/tlayout-parms.ts +9 -2
  113. package/src/layout/fdp/xlayout.ts +10 -2
  114. package/src/layout/neato/cdt-surface.ts +6 -6
  115. package/src/layout/neato/edge-len.ts +2 -1
  116. package/src/layout/neato/fdp-adjust.ts +3 -2
  117. package/src/layout/neato/init.ts +11 -11
  118. package/src/layout/neato/kk.ts +2 -1
  119. package/src/layout/neato/multispline-router.ts +3 -3
  120. package/src/layout/neato/multispline.ts +3 -2
  121. package/src/layout/neato/poly.ts +3 -2
  122. package/src/layout/neato/sgd.ts +5 -2
  123. package/src/layout/neato/start.ts +14 -10
  124. package/src/ortho/index.ts +3 -1
  125. package/src/parser/dot.js +4 -1
  126. package/src/parser/dot.pegjs +5 -1
  127. package/src/parser/index.ts +4 -3
  128. package/src/render/color-resolve.ts +193 -4
  129. package/src/render/public.ts +2 -0
  130. package/src/render/svg-edge-split.ts +4 -2
  131. package/src/render/xdot-public.ts +2 -0
package/dist/render.js CHANGED
@@ -5079,6 +5079,57 @@ var ALL_FONT_METRICS = [
5079
5079
  CALIBRI_FAMILY
5080
5080
  ];
5081
5081
 
5082
+ // src/common/render-state.ts
5083
+ var resets = [];
5084
+ function registerRenderState(reset2) {
5085
+ resets.push(reset2);
5086
+ }
5087
+ function resetRenderState() {
5088
+ for (const reset2 of resets) reset2();
5089
+ }
5090
+
5091
+ // src/common/agerr.ts
5092
+ var PREFIX_ERROR = "Error";
5093
+ var PREFIX_WARNING = "Warning";
5094
+ var PREFIX_SEP = ": ";
5095
+ var DEL = 127;
5096
+ var LAST_CNTRL = 31;
5097
+ var WHITESPACE = /* @__PURE__ */ new Set([9, 10, 11, 12, 13]);
5098
+ var OCTAL_WIDTH = 3;
5099
+ var OCTAL_RADIX = 8;
5100
+ var lastLevel = "warning";
5101
+ registerRenderState(() => {
5102
+ lastLevel = "warning";
5103
+ });
5104
+ function escapeControl(message) {
5105
+ let out = "";
5106
+ for (const ch of message) {
5107
+ const c = ch.codePointAt(0);
5108
+ if ((c <= LAST_CNTRL || c === DEL) && !WHITESPACE.has(c)) {
5109
+ out += `\\${c.toString(OCTAL_RADIX).padStart(OCTAL_WIDTH, "0")}`;
5110
+ } else out += ch;
5111
+ }
5112
+ return out;
5113
+ }
5114
+ function agerrLineOn(channel, line) {
5115
+ if (channel === "warn") console.warn(escapeControl(line));
5116
+ else console.error(escapeControl(line));
5117
+ }
5118
+ function agerr(level, msg, channel) {
5119
+ if (level === "prev") {
5120
+ agerrLineOn(channel ?? (lastLevel === "warning" ? "warn" : "error"), msg);
5121
+ return;
5122
+ }
5123
+ lastLevel = level;
5124
+ const prefix = level === "error" ? PREFIX_ERROR : PREFIX_WARNING;
5125
+ agerrLineOn(channel ?? (level === "warning" ? "warn" : "error"), `${prefix}${PREFIX_SEP}${msg}`);
5126
+ }
5127
+ var agerrorf = (msg, channel) => agerr("error", msg, channel);
5128
+ var agwarningf = (msg, channel) => agerr("warning", msg, channel);
5129
+ function agerrFinished(line, channel) {
5130
+ agerrLineOn(channel ?? (line.startsWith(PREFIX_WARNING) ? "warn" : "error"), line);
5131
+ }
5132
+
5082
5133
  // src/common/textmeasure-lookup.ts
5083
5134
  var TIMES_FALLBACK = ALL_FONT_METRICS[0];
5084
5135
  function normalizeFontName(name) {
@@ -5092,6 +5143,7 @@ function normalizeFontName(name) {
5092
5143
  return result;
5093
5144
  }
5094
5145
  var warnedFontNames = /* @__PURE__ */ new Set();
5146
+ registerRenderState(() => warnedFontNames.clear());
5095
5147
  function getFamilyMetrics(fontName) {
5096
5148
  const key = normalizeFontName(fontName);
5097
5149
  for (const family of ALL_FONT_METRICS) {
@@ -5099,8 +5151,8 @@ function getFamilyMetrics(fontName) {
5099
5151
  }
5100
5152
  if (!warnedFontNames.has(fontName)) {
5101
5153
  warnedFontNames.add(fontName);
5102
- console.warn(
5103
- `Warning: no hard-coded metrics for '${fontName}'. Falling back to 'Times' metrics`
5154
+ agwarningf(
5155
+ `no hard-coded metrics for '${fontName}'. Falling back to 'Times' metrics`
5104
5156
  );
5105
5157
  }
5106
5158
  return TIMES_FALLBACK;
@@ -5285,10 +5337,37 @@ function getVariantWidths(family, bold, italic) {
5285
5337
  return family.regular;
5286
5338
  }
5287
5339
  var SPACE_CHAR_CODE = 32;
5340
+ var FIRST_NON_ASCII = 128;
5341
+ var warned = /* @__PURE__ */ new Set();
5342
+ var NON_ASCII_FLAG = "non-ascii";
5343
+ var ASCII_FLAG = "ascii";
5344
+ registerRenderState(() => warned.clear());
5345
+ function warnNonAscii(character) {
5346
+ if (warned.has(NON_ASCII_FLAG)) return;
5347
+ warned.add(NON_ASCII_FLAG);
5348
+ agwarningf(
5349
+ `Warning: no value for width of non-ASCII character ${character}. Falling back to width of space character`
5350
+ );
5351
+ }
5352
+ function warnAscii(character) {
5353
+ if (warned.has(ASCII_FLAG)) return;
5354
+ warned.add(ASCII_FLAG);
5355
+ agwarningf(
5356
+ `Warning: no value for width of ASCII character ${character}. Falling back to 0`
5357
+ );
5358
+ }
5288
5359
  function charWidthUnits(widths, charCode) {
5289
- const code = charCode >= 128 ? SPACE_CHAR_CODE : charCode;
5360
+ let code = charCode;
5361
+ if (code >= FIRST_NON_ASCII) {
5362
+ warnNonAscii(code);
5363
+ code = SPACE_CHAR_CODE;
5364
+ }
5290
5365
  const w = widths[code] ?? -1;
5291
- return w < 0 ? 0 : w;
5366
+ if (w < 0) {
5367
+ warnAscii(code);
5368
+ return 0;
5369
+ }
5370
+ return w;
5292
5371
  }
5293
5372
  var utf8Encoder = new TextEncoder();
5294
5373
  function utf8Bytes(text) {
@@ -5665,10 +5744,7 @@ var StderrLines = class {
5665
5744
  this.pending = "";
5666
5745
  }
5667
5746
  };
5668
- var consoleLine = (line) => {
5669
- if (line.startsWith("Warning")) console.warn(line);
5670
- else console.error(line);
5671
- };
5747
+ var consoleLine = (line) => agerrFinished(line);
5672
5748
  var labelStderr = () => new StderrLines(consoleLine);
5673
5749
  var agerrLine = (out, msg) => {
5674
5750
  if (out === void 0) consoleLine(msg);
@@ -5955,28 +6031,46 @@ var HTML_ENTITIES = {
5955
6031
  "zwj": 8205,
5956
6032
  "zwnj": 8204
5957
6033
  };
5958
- var BASIC_ENTITIES = {
5959
- amp: 38,
5960
- lt: 60,
5961
- gt: 62,
5962
- quot: 34,
5963
- apos: 39
5964
- };
5965
- function numericEntityValue(body) {
5966
- const hex = body[1] === "x" || body[1] === "X";
5967
- const v = hex ? parseInt(body.slice(2), 16) : parseInt(body.slice(1), 10);
5968
- return Number.isFinite(v) && v > 0 && v <= 1114111 ? v : null;
6034
+ var ENTITY_NAME_LENGTH_MAX = 8;
6035
+ function numericEntity(s, at) {
6036
+ const hex = s[at + 1] === "x" || s[at + 1] === "X";
6037
+ const digit = hex ? /^[0-9A-Fa-f]$/ : /^[0-9]$/;
6038
+ let n = 0;
6039
+ let i = hex ? 2 : 1;
6040
+ for (; i < 8; i++) {
6041
+ const c = s[at + i] ?? "";
6042
+ if (!digit.test(c)) break;
6043
+ n = n * (hex ? 16 : 10) + parseInt(c, 16);
6044
+ }
6045
+ if (i < 8 && s[at + i] === ";") return { value: n, next: at + i + 1 };
6046
+ return { value: 0, next: at };
6047
+ }
6048
+ function namedEntity(s, at) {
6049
+ for (let i = 0; i < ENTITY_NAME_LENGTH_MAX; i++) {
6050
+ const c = s[at + i];
6051
+ if (c === void 0 || c === "\0") break;
6052
+ if (c === ";") {
6053
+ const key = s.slice(at, at + i);
6054
+ if (Object.hasOwn(HTML_ENTITIES, key)) return { value: HTML_ENTITIES[key], next: at + i + 1 };
6055
+ break;
6056
+ }
6057
+ }
6058
+ return { value: 0, next: at };
5969
6059
  }
5970
- function entityValue(body) {
5971
- if (body[0] === "#") return numericEntityValue(body);
5972
- return BASIC_ENTITIES[body] ?? HTML_ENTITIES[body] ?? null;
6060
+ function htmlEntity(s, at) {
6061
+ return s[at] === "#" ? numericEntity(s, at) : namedEntity(s, at);
5973
6062
  }
5974
6063
  function htmlEntityUTF8(s) {
5975
- if (s.indexOf("&") < 0) return s;
5976
- return s.replace(/&(#x[0-9a-fA-F]+|#[0-9]+|[A-Za-z]+);/g, (m, body) => {
5977
- const v = entityValue(body);
5978
- return v === null ? m : String.fromCodePoint(v);
5979
- });
6064
+ let amp = s.indexOf("&");
6065
+ if (amp < 0) return s;
6066
+ let out = "";
6067
+ let from = 0;
6068
+ for (; amp >= 0; amp = s.indexOf("&", from)) {
6069
+ const e = htmlEntity(s, amp + 1);
6070
+ out += s.slice(from, amp) + (e.value ? String.fromCodePoint(e.value) : "&");
6071
+ from = e.next;
6072
+ }
6073
+ return out + s.slice(from);
5980
6074
  }
5981
6075
 
5982
6076
  // src/common/htmltable-lex-attvalue.ts
@@ -6110,14 +6204,14 @@ function tagEdge(text, i) {
6110
6204
  if (i + 1 >= text.length) return PARTIAL;
6111
6205
  return text[i + 1] === ">" ? COMPLETE_END(i + 2) : void 0;
6112
6206
  }
6113
- function storeAttError(text, p, at, pair, seen) {
6114
- if (seen.has(pair.name)) return { message: XML_ERROR_DUPLICATE_ATTRIBUTE, offset: at };
6115
- seen.add(pair.name);
6207
+ function storeAttError(text, p, at, pair, seen2) {
6208
+ if (seen2.has(pair.name)) return { message: XML_ERROR_DUPLICATE_ATTRIBUTE, offset: at };
6209
+ seen2.add(pair.name);
6116
6210
  const err = attValueError(text.slice(pair.value.start, pair.value.end), pair.value.start);
6117
6211
  return err === void 0 ? void 0 : { message: err.message, offset: err.offset ?? p };
6118
6212
  }
6119
6213
  function scanAttributes(text, p, from) {
6120
- const seen = /* @__PURE__ */ new Set();
6214
+ const seen2 = /* @__PURE__ */ new Set();
6121
6215
  let attError;
6122
6216
  let i = skipSpace(text, from);
6123
6217
  for (; ; ) {
@@ -6126,7 +6220,7 @@ function scanAttributes(text, p, from) {
6126
6220
  if (edge !== void 0) return edge;
6127
6221
  const pair = scanPair(text, i);
6128
6222
  if ("kind" in pair) return pair;
6129
- attError ??= storeAttError(text, p, i, pair, seen);
6223
+ attError ??= storeAttError(text, p, i, pair, seen2);
6130
6224
  i = pair.next;
6131
6225
  }
6132
6226
  }
@@ -6194,9 +6288,11 @@ function scanCdata(text, p, base, dataOf, tokens) {
6194
6288
  }
6195
6289
  function scanText(text, p, base, tokens) {
6196
6290
  const e = text.indexOf("<", p);
6197
- const end = e < 0 ? text.length : e;
6198
- tokens.push({ kind: "text", start: base + p, end: base + end });
6199
- return end;
6291
+ const slice = text.slice(p, e < 0 ? text.length : e);
6292
+ const from = e < 0 ? heldRefStart(slice) : void 0;
6293
+ const end = from === void 0 ? p + slice.length : p + from;
6294
+ if (end > p) tokens.push({ kind: "text", start: base + p, end: base + end });
6295
+ return { at: end, held: from !== void 0 };
6200
6296
  }
6201
6297
  function scanContent(text, base, inCdata, dataOf) {
6202
6298
  const tokens = [];
@@ -6211,7 +6307,9 @@ function scanContent(text, base, inCdata, dataOf) {
6211
6307
  continue;
6212
6308
  }
6213
6309
  if (text[p] !== "<") {
6214
- p = scanText(text, p, base, tokens);
6310
+ const scanned = scanText(text, p, base, tokens);
6311
+ if (scanned.held) return { tokens, consumed: scanned.at, inCdata: false };
6312
+ p = scanned.at;
6215
6313
  continue;
6216
6314
  }
6217
6315
  const { scan, kind } = scanMarkup(text, p);
@@ -6311,24 +6409,44 @@ var ExpatFeed = class {
6311
6409
  }
6312
6410
  };
6313
6411
  var XML_PREDEFINED_ENTITIES = /* @__PURE__ */ new Set(["lt", "gt", "amp", "quot", "apos"]);
6314
- var ENTITY_NAME = /^[A-Za-z_:][\w.:-]*$/;
6315
- var CHAR_REF = /^&#(?:x[0-9A-Fa-f]+|[0-9]+);/;
6316
- function textRefError(text) {
6317
- for (let t = text.indexOf("&"); t >= 0; t = text.indexOf("&", t + 1)) {
6318
- if (text[t + 1] === "#") {
6319
- const ref = CHAR_REF.exec(text.slice(t))?.[0];
6320
- if (ref !== void 0 && charRefNumber(ref) < 0) return { message: XML_ERROR_BAD_CHAR_REF, offset: t };
6321
- continue;
6412
+ var SCANNED_ENTITY = /^&([^;&<]*);/;
6413
+ function contentRef(text, t) {
6414
+ const semi = text.indexOf(";", t);
6415
+ const ref = text.slice(t, semi < 0 ? text.length : semi + 1);
6416
+ const scan = scanAttValue(`"${ref}"`, 0);
6417
+ if ("close" in scan) return { end: t + scan.close - 1 };
6418
+ return { invalid: "invalid" in scan ? t + scan.invalid - 1 : text.length };
6419
+ }
6420
+ function firstRefProblem(text) {
6421
+ let t = text.indexOf("&");
6422
+ while (t >= 0) {
6423
+ if (text[t + 1] !== "#") {
6424
+ const name = SCANNED_ENTITY.exec(text.slice(t))?.[1];
6425
+ if (name !== void 0 && name.length >= 2 && Object.hasOwn(HTML_ENTITIES, name)) {
6426
+ t = text.indexOf("&", t + name.length + 2);
6427
+ continue;
6428
+ }
6322
6429
  }
6323
- const semi = text.indexOf(";", t + 1);
6324
- if (semi < 0) continue;
6325
- const key = text.slice(t + 1, semi);
6326
- if (ENTITY_NAME.test(key) && !Object.hasOwn(HTML_ENTITIES, key) && !XML_PREDEFINED_ENTITIES.has(key)) {
6327
- return { message: XML_ERROR_UNDEFINED_ENTITY, offset: t };
6430
+ const ref = contentRef(text, t);
6431
+ if ("invalid" in ref) return { message: XML_ERROR_INVALID_TOKEN, offset: ref.invalid, from: t };
6432
+ const key = text.slice(t + 1, ref.end - 1);
6433
+ if (text[t + 1] === "#") {
6434
+ if (charRefNumber(`&${key};`) < 0) return { message: XML_ERROR_BAD_CHAR_REF, offset: t, from: t };
6435
+ } else if (!XML_PREDEFINED_ENTITIES.has(key)) {
6436
+ return { message: XML_ERROR_UNDEFINED_ENTITY, offset: t, from: t };
6328
6437
  }
6438
+ t = text.indexOf("&", ref.end);
6329
6439
  }
6330
6440
  return void 0;
6331
6441
  }
6442
+ function textRefError(text) {
6443
+ const problem = firstRefProblem(text);
6444
+ return problem === void 0 ? void 0 : { message: problem.message, offset: problem.offset };
6445
+ }
6446
+ function heldRefStart(text) {
6447
+ const problem = firstRefProblem(text);
6448
+ return problem?.message === XML_ERROR_INVALID_TOKEN && problem.offset === text.length ? problem.from : void 0;
6449
+ }
6332
6450
  function parseTagChunk(chunk) {
6333
6451
  if (!chunk.endsWith(">")) return void 0;
6334
6452
  const body = chunk.slice(1, -1);
@@ -6370,8 +6488,26 @@ function releaseXb(st, first) {
6370
6488
  function cleanText(decoded) {
6371
6489
  return decoded.replace(/[\x00-\x1f]/g, "");
6372
6490
  }
6491
+ var XML_PREDEFINED = { lt: "<", gt: ">", amp: "&", quot: '"', apos: "'" };
6492
+ var SCAN_ENTITY_MIN = 2;
6493
+ var SCAN_ENTITY_MAX = 8;
6494
+ var TEXT_REF = /&(#x[0-9A-Fa-f]+|#[0-9]+|[^&;]+);/g;
6495
+ function textRefValue(ref, body) {
6496
+ if (body[0] === "#") {
6497
+ const v = charRefNumber(ref);
6498
+ return v < 0 ? ref : String.fromCodePoint(v);
6499
+ }
6500
+ const n = body.length;
6501
+ if (n >= SCAN_ENTITY_MIN && n <= SCAN_ENTITY_MAX && Object.hasOwn(HTML_ENTITIES, body)) {
6502
+ return String.fromCodePoint(HTML_ENTITIES[body]);
6503
+ }
6504
+ return Object.hasOwn(XML_PREDEFINED, body) ? XML_PREDEFINED[body] : ref;
6505
+ }
6506
+ function decodeTextRefs(raw) {
6507
+ return raw.indexOf("&") < 0 ? raw : raw.replace(TEXT_REF, textRefValue);
6508
+ }
6373
6509
  function textTokens(raw) {
6374
- return charDataTokens(htmlEntityUTF8(raw));
6510
+ return charDataTokens(decodeTextRefs(raw));
6375
6511
  }
6376
6512
  function charDataTokens(decoded) {
6377
6513
  const clean = cleanText(decoded);
@@ -7337,30 +7473,23 @@ var splitSizedLines = (texts, measurer, env) => {
7337
7473
  return lines;
7338
7474
  };
7339
7475
  var itemHasFlags = (i) => i.bold === true || i.italic === true || i.underline === true || i.strikethrough === true || i.overline === true || i.subscript === true || i.superscript === true;
7340
- var htmlTextIsSimple = (texts, env) => {
7476
+ var htmlTextIsSimple = (lines, env) => {
7341
7477
  let prevFs = -1;
7342
7478
  let prevFace = null;
7343
- let count = 0;
7344
- for (const txt of texts) {
7345
- for (const item of txt.items) {
7346
- if (item.br) {
7347
- count = 0;
7348
- continue;
7349
- }
7350
- if (item.text === void 0) continue;
7351
- if (++count > 1 || itemHasFlags(item)) return false;
7352
- const { fs, face } = itemFont(item, env);
7353
- if (prevFs < 0) prevFs = fs;
7354
- else if (fs !== prevFs) return false;
7355
- if (prevFace === null) prevFace = face;
7356
- else if (face !== prevFace) return false;
7357
- }
7479
+ for (const ln of lines) {
7480
+ const item = ln.items[0];
7481
+ if (ln.items.length > 1 || itemHasFlags(item)) return false;
7482
+ const { fs, face } = itemFont(item, env);
7483
+ if (prevFs < 0) prevFs = fs;
7484
+ else if (fs !== prevFs) return false;
7485
+ if (prevFace === null) prevFace = face;
7486
+ else if (face !== prevFace) return false;
7358
7487
  }
7359
7488
  return true;
7360
7489
  };
7361
7490
  var sizeTextContent = (texts, measurer, env = defaultSizeEnv()) => {
7362
7491
  const lines = splitSizedLines(texts, measurer, env);
7363
- const simple = htmlTextIsSimple(texts, env);
7492
+ const simple = htmlTextIsSimple(lines, env);
7364
7493
  let w = 0;
7365
7494
  let h = 0;
7366
7495
  for (const ln of lines) {
@@ -8940,10 +9069,10 @@ var SMALL = 1e-10;
8940
9069
  function ptToLine2(a, b, p) {
8941
9070
  const dx = b.x - a.x;
8942
9071
  const dy = b.y - a.y;
8943
- let a2 = (p.y - a.y) * dx - (p.x - a.x) * dy;
9072
+ let a2 = fma(p.y - a.y, dx, -(dy * (p.x - a.x)));
8944
9073
  a2 *= a2;
8945
9074
  if (a2 < SMALL) return 0;
8946
- return a2 / (dx * dx + dy * dy);
9075
+ return a2 / fma(dx, dx, dy * dy);
8947
9076
  }
8948
9077
  function checkControlPoints(cp) {
8949
9078
  const dis1 = ptToLine2(cp[0], cp[3], cp[1]);
@@ -9434,10 +9563,14 @@ function cubicHalf(c, rightHalf) {
9434
9563
  function curveControlPoints(p, v, w, flag) {
9435
9564
  const AF0 = { x: p.x + v.x + w.x, y: p.y + v.y + w.y };
9436
9565
  const AF3 = { x: p.x - v.x + w.x, y: p.y - v.y + w.y };
9437
- const s = flag & ARR_MOD_INV ? 1 : -1;
9438
- const AF1 = { x: p.x + 0.95 * v.x + w.x + s * w.x * (4 / 3), y: AF0.y + s * w.y * (4 / 3) };
9439
- const AF2 = { x: p.x - 0.95 * v.x + w.x + s * w.x * (4 / 3), y: AF3.y + s * w.y * (4 / 3) };
9440
- return [AF0, AF1, AF2, AF3];
9566
+ const bulgeX = w.x * 4 / 3;
9567
+ const bulgeY = w.y * 4 / 3;
9568
+ const x1 = fma(v.x, 0.95, p.x) + w.x;
9569
+ const x2 = fma(v.x, -0.95, p.x) + w.x;
9570
+ if (flag & ARR_MOD_INV) {
9571
+ return [AF0, { x: x1 + bulgeX, y: AF0.y + bulgeY }, { x: x2 + bulgeX, y: AF3.y + bulgeY }, AF3];
9572
+ }
9573
+ return [AF0, { x: x1 - bulgeX, y: AF0.y - bulgeY }, { x: x2 - bulgeX, y: AF3.y - bulgeY }, AF3];
9441
9574
  }
9442
9575
  function genCurve(p0, u, _arrowsize, penwidth, flag, rankdir = 0) {
9443
9576
  if (rankdir !== 0) {
@@ -9740,13 +9873,14 @@ function bezierClipNode(sp, cx, cy, insideFn, leftInside) {
9740
9873
  y: p.y + cy
9741
9874
  }));
9742
9875
  }
9876
+ function distFused(p, q) {
9877
+ const dx = p.x - q.x;
9878
+ const dy = p.y - q.y;
9879
+ return Math.sqrt(fma(dx, dx, dy * dy));
9880
+ }
9743
9881
  function arrowEndClip(path4, arrowTip, elen) {
9744
- if (elen <= 0) return path4;
9745
9882
  const sp = [arrowTip, path4[2], path4[1], path4[0]];
9746
- const insideSphere = (lx, ly) => Math.hypot(lx, ly) <= elen;
9747
- const spRel = sp.map((p) => ({ x: p.x - arrowTip.x, y: p.y - arrowTip.y }));
9748
- const clippedRel = bezierClipLocal(spRel, insideSphere, true);
9749
- const clipped = clippedRel.map((p) => ({ x: p.x + arrowTip.x, y: p.y + arrowTip.y }));
9883
+ const clipped = elen > 0 ? bezierClipNode(sp, 0, 0, (x, y) => distFused({ x, y }, arrowTip) <= elen, true) : sp;
9750
9884
  return [clipped[3], clipped[2], clipped[1], clipped[0]];
9751
9885
  }
9752
9886
  function arrowClipLength(arrowName, arrowsize, penwidth) {
@@ -11408,6 +11542,7 @@ function resetHtmlAnchorIds() {
11408
11542
  anchorEnv.objLabel = null;
11409
11543
  anchorEnv.imgscale = "false";
11410
11544
  }
11545
+ registerRenderState(resetHtmlAnchorIds);
11411
11546
  function initHtmlAnchor(data, box, renderer, job) {
11412
11547
  if (data.href === void 0 && data.title === void 0 && data.target === void 0) {
11413
11548
  return false;
@@ -12534,7 +12669,7 @@ function polyInit(n, g, measurer) {
12534
12669
  const shapefile = nodeAttr(n, g, "shapefile");
12535
12670
  n.info.shape = bindShape(shapeName2, shapefile);
12536
12671
  if (shapefile !== void 0 && shapefile !== "" && shapeName2 !== "epsf") {
12537
- console.error(`Warning: No or improper shapefile="${shapefile}" for node "${n.name}"`);
12672
+ agwarningf(`No or improper shapefile="${shapefile}" for node "${n.name}"`, "error");
12538
12673
  }
12539
12674
  if (n.info.shape.kind === 2 /* SH_RECORD */) {
12540
12675
  if (n.info.shape_info === void 0) recordNodeInit(n, g, measurer);
@@ -15160,6 +15295,9 @@ var COLOR_LIB = [
15160
15295
 
15161
15296
  // src/common/color.ts
15162
15297
  var colorScheme = "";
15298
+ registerRenderState(() => {
15299
+ colorScheme = "";
15300
+ });
15163
15301
  function setColorScheme(scheme) {
15164
15302
  colorScheme = scheme;
15165
15303
  }
@@ -15289,18 +15427,28 @@ function setBlackOpaque(color, targetType) {
15289
15427
  if (targetType === "rgba") setRgba(color, 0, 0, 0, 255);
15290
15428
  else if (targetType === "hsva") setHsvaDirect(color, 0, 0, 0, 1);
15291
15429
  }
15430
+ var SSCANF_SPACE = /* @__PURE__ */ new Set([" ", " ", "\n", "\v", "\f", "\r"]);
15431
+ function scanHexGroups(p, width2, max) {
15432
+ const out = [];
15433
+ if (p.charAt(0) !== "#") return out;
15434
+ let i = 1;
15435
+ while (out.length < max) {
15436
+ while (SSCANF_SPACE.has(p.charAt(i))) i++;
15437
+ let j = i;
15438
+ while (j < p.length && j - i < width2 && /[0-9a-fA-F]/.test(p.charAt(j))) j++;
15439
+ if (j === i) break;
15440
+ out.push(parseInt(p.slice(i, j), 16));
15441
+ i = j;
15442
+ }
15443
+ return out;
15444
+ }
15292
15445
  function parseHexColor(p) {
15293
- if (p.charAt(0) !== "#") return null;
15294
- const m8 = /^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/.exec(p);
15295
- if (m8) return { r: parseInt(m8[1], 16), g: parseInt(m8[2], 16), b: parseInt(m8[3], 16), a: parseInt(m8[4], 16) };
15296
- const m6 = /^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/.exec(p);
15297
- if (m6) return { r: parseInt(m6[1], 16), g: parseInt(m6[2], 16), b: parseInt(m6[3], 16), a: 255 };
15298
- const m3 = /^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])$/.exec(p);
15299
- if (!m3) return null;
15300
- const r = parseInt(m3[1], 16);
15301
- const g = parseInt(m3[2], 16);
15302
- const b = parseInt(m3[3], 16);
15303
- return { r: r | r << 4, g: g | g << 4, b: b | b << 4, a: 255 };
15446
+ const g = scanHexGroups(p, 2, 4);
15447
+ if (g.length >= 3) return { r: g[0], g: g[1], b: g[2], a: g[3] ?? 255 };
15448
+ const short = p.length === 4 ? scanHexGroups(p, 1, 3) : [];
15449
+ if (short.length !== 3) return null;
15450
+ const [r, gg, b] = short;
15451
+ return { r: r | r << 4, g: gg | gg << 4, b: b | b << 4, a: 255 };
15304
15452
  }
15305
15453
  function clamp01(x) {
15306
15454
  return Math.max(0, Math.min(1, x));
@@ -15346,6 +15494,17 @@ function colorxlate(str, color, targetType) {
15346
15494
  return 1 /* ColorUnknown */;
15347
15495
  }
15348
15496
 
15497
+ // src/common/emit-once.ts
15498
+ var seen = /* @__PURE__ */ new Set();
15499
+ registerRenderState(() => {
15500
+ seen.clear();
15501
+ });
15502
+ function emitOnce(str) {
15503
+ if (seen.has(str)) return false;
15504
+ seen.add(str);
15505
+ return true;
15506
+ }
15507
+
15349
15508
  // src/render/color-resolve.ts
15350
15509
  var SVG_KNOWN_COLORS = [
15351
15510
  "aliceblue",
@@ -15498,12 +15657,33 @@ var SVG_KNOWN_COLORS = [
15498
15657
  "yellowgreen"
15499
15658
  ];
15500
15659
  var KNOWN_COLORS = new Set(SVG_KNOWN_COLORS);
15501
- function resolveRenderColor(raw) {
15660
+ var rendererColors = { hasKnownList: true };
15661
+ registerRenderState(() => {
15662
+ rendererColors.hasKnownList = true;
15663
+ });
15664
+ function setRendererKnownColors(hasList) {
15665
+ rendererColors.hasKnownList = hasList;
15666
+ }
15667
+ function firstColor(name) {
15668
+ const i = name.indexOf(":");
15669
+ return i < 0 ? name : name.slice(0, i);
15670
+ }
15671
+ function resolveRenderColor(raw, report = true) {
15502
15672
  if (raw === "" || raw === "none") return { type: "none" };
15503
- if (KNOWN_COLORS.has(raw.toLowerCase())) return { type: "string", s: raw };
15673
+ const known = KNOWN_COLORS.has(raw.toLowerCase());
15674
+ if (known && (rendererColors.hasKnownList || !report)) return { type: "string", s: raw };
15504
15675
  const color = { type: "rgba", r: 0, g: 0, b: 0, a: 0 };
15505
- colorxlate(raw, color, "rgba");
15506
- return color;
15676
+ const rc = colorxlate(raw, color, "rgba");
15677
+ if (report) reportColorxlate(raw, rc);
15678
+ return known ? { type: "string", s: raw } : color;
15679
+ }
15680
+ function reportColorxlate(name, rc) {
15681
+ if (rc === 0 /* ColorOk */) return;
15682
+ if (rc === 1 /* ColorUnknown */) {
15683
+ if (emitOnce(`color ${name}`)) agwarningf(`${name} is not a known color.`);
15684
+ } else {
15685
+ agerrorf("error in colorxlate()");
15686
+ }
15507
15687
  }
15508
15688
  function withColorScheme(scheme, fn) {
15509
15689
  const prev = getColorScheme();
@@ -15550,6 +15730,72 @@ function textFillAttrs(fontColor) {
15550
15730
  if (byte < 255) out += ' fill-opacity="' + (byte / 255).toFixed(6) + '"';
15551
15731
  return out;
15552
15732
  }
15733
+ var DEFAULT_COLOR2 = "black";
15734
+ var SEG_EPS = 1e-5;
15735
+ function reportColorNames(names) {
15736
+ for (const name of names) resolveRenderColor(firstColor(name));
15737
+ }
15738
+ function countChar(s, ch) {
15739
+ return s.split(ch).length - 1;
15740
+ }
15741
+ function multicolorNames(color, arrows) {
15742
+ const { segs, error } = parseSegs(color);
15743
+ if (error === 1 || error === 2) return null;
15744
+ const out = [];
15745
+ const front = segs[0]?.color ?? null;
15746
+ for (const bz of arrows) {
15747
+ let endcolor = null;
15748
+ for (const seg2 of segs) {
15749
+ if (seg2.color === null) break;
15750
+ if (Math.abs(seg2.t) < SEG_EPS) continue;
15751
+ out.push(seg2.color);
15752
+ endcolor = seg2.color;
15753
+ }
15754
+ if (bz.sflag && front !== null) out.push(front);
15755
+ if (bz.eflag && endcolor !== null) out.push(endcolor);
15756
+ }
15757
+ return out;
15758
+ }
15759
+ function taperedNames(color, fillcolor, hasFill) {
15760
+ const pen = color === "" ? DEFAULT_COLOR2 : color;
15761
+ return hasFill ? [pen, fillcolor === "" ? DEFAULT_COLOR2 : fillcolor] : [pen];
15762
+ }
15763
+ function edgeGraphicsColors(spec) {
15764
+ const numc = countChar(spec.color, ":");
15765
+ let color = spec.color;
15766
+ if (countChar(color, ";") > 0 && numc > 0) {
15767
+ const multi = multicolorNames(color, spec.arrows);
15768
+ if (multi !== null) return multi;
15769
+ color = DEFAULT_COLOR2;
15770
+ }
15771
+ const hasFill = spec.fillcolor !== "";
15772
+ const early = hasFill ? [spec.fillcolor] : [];
15773
+ if (spec.tapered) return [...early, ...taperedNames(color, spec.fillcolor, hasFill)];
15774
+ if (numc > 0) return [...early, ...color.split(":").filter((c) => c !== "")];
15775
+ const fill = hasFill ? spec.fillcolor : color;
15776
+ if (color !== "") return [...early, color, fill];
15777
+ return [...early, DEFAULT_COLOR2, fill !== "" ? fill : DEFAULT_COLOR2];
15778
+ }
15779
+ function reportEdgeColors(e) {
15780
+ const spl = e.info.spl;
15781
+ if (!spl) return;
15782
+ const color = e.attrs.get("color") ?? "";
15783
+ reportColorNames(edgeGraphicsColors({
15784
+ color,
15785
+ fillcolor: e.attrs.get("fillcolor") ?? "",
15786
+ tapered: styleTokens2(e.attrs.get("style")).includes("tapered"),
15787
+ arrows: spl.list.map((bz) => ({ sflag: bz.sflag !== 0, eflag: bz.eflag !== 0 }))
15788
+ }));
15789
+ }
15790
+ function backgroundColors(bgcolor, truecolor) {
15791
+ let str = bgcolor !== void 0 && bgcolor !== "" ? bgcolor : "white";
15792
+ if (str === "transparent") {
15793
+ if (truecolor) return [];
15794
+ str = "white";
15795
+ }
15796
+ const stop = findStopColor(str);
15797
+ return stop === null ? [str, "transparent"] : [stop.fillColor, "transparent", stop.stopColor];
15798
+ }
15553
15799
 
15554
15800
  // src/render/svg-multicolor.ts
15555
15801
  var THIN_LINE = 0.5;
@@ -15910,20 +16156,36 @@ function applyClusterObjState(sg, job) {
15910
16156
  if (job.obj === null) return false;
15911
16157
  const obj = job.obj;
15912
16158
  return withColorScheme(clusterAttr(sg, "colorscheme"), () => {
16159
+ const filled = applyClusterFill(obj, fillRes);
15913
16160
  applyClusterPenState(obj, sg);
15914
- if (fillRes.kind === "none") {
15915
- obj.fill = 0 /* None */;
15916
- return false;
15917
- }
15918
- if (fillRes.kind === "solid") {
15919
- obj.fill = 1 /* Solid */;
15920
- obj.fillColor = resolveRenderColor(fillRes.color);
15921
- return true;
15922
- }
15923
- applyClusterGradient(obj, fillRes);
15924
- return true;
16161
+ reportColorNames(stripedClusterColors(sg));
16162
+ return filled;
15925
16163
  });
15926
16164
  }
16165
+ function stripedClusterColors(sg) {
16166
+ const flags = parseStyleFlags(clusterStyle(sg));
16167
+ if (!flags.striped || flags.rounded) return [];
16168
+ const color = clusterAttr(sg, "color") ?? "";
16169
+ let fill = clusterAttr(sg, "fillcolor") || color;
16170
+ const bg = clusterAttr(sg, "bgcolor") ?? "";
16171
+ if ((!flags.filled || fill === "") && bg !== "") fill = bg;
16172
+ const { segs, error } = parseSegs(fill === "" ? "lightgrey" : fill);
16173
+ if (error === 1 || error === 2) return [];
16174
+ return segs.flatMap((seg2) => seg2.color !== null && seg2.t > 0 ? [seg2.color] : []);
16175
+ }
16176
+ function applyClusterFill(obj, fillRes) {
16177
+ if (fillRes.kind === "none") {
16178
+ obj.fill = 0 /* None */;
16179
+ return false;
16180
+ }
16181
+ if (fillRes.kind === "solid") {
16182
+ obj.fill = 1 /* Solid */;
16183
+ obj.fillColor = resolveRenderColor(fillRes.color);
16184
+ return true;
16185
+ }
16186
+ applyClusterGradient(obj, fillRes);
16187
+ return true;
16188
+ }
15927
16189
 
15928
16190
  // src/render/svg-id.ts
15929
16191
  function svgClass(kind, classAttr) {
@@ -16011,6 +16273,7 @@ function renderPeripheries(poly, coord, filled, ctx) {
16011
16273
  }
16012
16274
  function renderLabel(label, coord, renderer, job) {
16013
16275
  if (label.u.kind !== "txt" || label.u.nspans < 1) return;
16276
+ reportColorNames([label.fontcolor]);
16014
16277
  label.pos = coord;
16015
16278
  label.set = true;
16016
16279
  const VALIGN_TOP2 = "t".charCodeAt(0);
@@ -16030,6 +16293,7 @@ function renderNodeLabel(n, coord, renderer, job) {
16030
16293
  label.pos = coord;
16031
16294
  label.set = true;
16032
16295
  const html = label.u.html;
16296
+ reportColorNames(htmlLabelColors(html));
16033
16297
  withLabelEmitState(job, () => emitHtmlLabel(html, coord, renderer, job));
16034
16298
  } else {
16035
16299
  renderLabel(label, coord, renderer, job);
@@ -16109,8 +16373,13 @@ function applyPenState(obj, styleAttr, colorAttr, penwidthAttr) {
16109
16373
  function applyNodeStyle(obj, n, job) {
16110
16374
  const styleAttr = nodeAttr(n, n.root, "style");
16111
16375
  const colorAttr = nodeAttr(n, n.root, "color");
16376
+ const penwidth = nodeAttr(n, n.root, "penwidth");
16377
+ if (n.info.shape?.kind === 2 /* SH_RECORD */) {
16378
+ applyPenState(obj, styleAttr, colorAttr, penwidth);
16379
+ return applyFillState(obj, n, job);
16380
+ }
16112
16381
  const filled = applyFillState(obj, n, job);
16113
- applyPenState(obj, styleAttr, colorAttr, nodeAttr(n, n.root, "penwidth"));
16382
+ applyPenState(obj, styleAttr, colorAttr, penwidth);
16114
16383
  return filled;
16115
16384
  }
16116
16385
  function prepareDrawPoly(poly, filled, obj) {
@@ -16390,6 +16659,9 @@ function decompSearch(g, start, cmark) {
16390
16659
  }
16391
16660
  }
16392
16661
  var _dc = { cmark: 0 };
16662
+ registerRenderState(() => {
16663
+ _dc.cmark = 0;
16664
+ });
16393
16665
  function resolveNode(n, pass) {
16394
16666
  if (pass > 0) {
16395
16667
  const subg = n.info.clust;
@@ -16622,6 +16894,9 @@ function makeInterclustChain(from, to, orig) {
16622
16894
 
16623
16895
  // src/layout/dot/mincross-cross.ts
16624
16896
  var reMincross = false;
16897
+ registerRenderState(() => {
16898
+ reMincross = false;
16899
+ });
16625
16900
  function setReMincross(b) {
16626
16901
  reMincross = b;
16627
16902
  }
@@ -17138,6 +17413,9 @@ function allocateRanks(g) {
17138
17413
  g.info.rank = rt;
17139
17414
  }
17140
17415
  var fillSeq = 0;
17416
+ registerRenderState(() => {
17417
+ fillSeq = 0;
17418
+ });
17141
17419
  function makeFillNode(sg, rank3, seq2) {
17142
17420
  const n = agnode(sg, `__fill_${rank3}_${seq2}`, true);
17143
17421
  agsubnode(sg, n, true);
@@ -17495,7 +17773,7 @@ function pruneForeignClusterNodes(par, clust) {
17495
17773
  }
17496
17774
  function markClusterNode(clust, n, g) {
17497
17775
  if ((n.info.ranktype ?? 0) !== 0) {
17498
- console.error(`Warning: ${n.name} was already in a rankset, deleted from cluster ${g.name}`);
17776
+ agwarningf(`${n.name} was already in a rankset, deleted from cluster ${g.name}`, "error");
17499
17777
  agDeleteFromCluster(clust, n);
17500
17778
  return;
17501
17779
  }
@@ -18074,7 +18352,7 @@ function findCharset(g) {
18074
18352
  }
18075
18353
  if (p === "big-5" || p === "big5") return CHAR_BIG5;
18076
18354
  if (p === "utf-8" || p === "utf8") return CHAR_UTF8;
18077
- console.error(`Warning: Unsupported charset "${raw}" - assuming utf-8`);
18355
+ agwarningf(`Unsupported charset "${raw}" - assuming utf-8`, "error");
18078
18356
  return CHAR_UTF8;
18079
18357
  }
18080
18358
  function maptoken(p, names, vals) {
@@ -19723,7 +20001,7 @@ function advanceTmpList(tmplist, offlist) {
19723
20001
  // src/render/svg-parallel-edge.ts
19724
20002
  var PENWIDTH_NORMAL2 = 1;
19725
20003
  var PENWIDTH_THRESHOLD2 = 5e-3;
19726
- var DEFAULT_COLOR2 = "black";
20004
+ var DEFAULT_COLOR3 = "black";
19727
20005
  function emitOffsetBezier(tmplist, job, color) {
19728
20006
  const obj = job.obj;
19729
20007
  const resolved = resolveRenderColor(color);
@@ -19765,11 +20043,11 @@ function emitParallelEdgePaths(e, job, colorList) {
19765
20043
  const spl = e.info.spl;
19766
20044
  const numc = (colorList.match(/:/g) ?? []).length;
19767
20045
  const segData = buildSegData(spl?.list ?? [], (2 + numc) / 2);
19768
- const colors = parseSegs(colorList).segs.map((s) => s.color ?? DEFAULT_COLOR2);
20046
+ const colors = parseSegs(colorList).segs.map((s) => s.color ?? DEFAULT_COLOR3);
19769
20047
  emitColorPasses(segData, colors, job);
19770
20048
  return {
19771
- headColor: colors[0] ?? DEFAULT_COLOR2,
19772
- tailColor: colors[1] ?? colors[0] ?? DEFAULT_COLOR2
20049
+ headColor: colors[0] ?? DEFAULT_COLOR3,
20050
+ tailColor: colors[1] ?? colors[0] ?? DEFAULT_COLOR3
19773
20051
  };
19774
20052
  }
19775
20053
 
@@ -20281,7 +20559,6 @@ function beginAnchorIf(renderer, job) {
20281
20559
  }
20282
20560
  var DFLT_SAMPLE = 20;
20283
20561
  var MAP_HW = 2;
20284
- var MAP_SMALL = 1e-10;
20285
20562
  function mapTransform(p, ctx) {
20286
20563
  return {
20287
20564
  x: (p.x + ctx.pad.x - ctx.bb.ll.x) * ctx.scale + ctx.marginOff.x,
@@ -20398,16 +20675,8 @@ function computeLabelRectMap(lab, obj, ctx) {
20398
20675
  mapTransform({ x: lab.pos.x + dx, y: lab.pos.y + dy }, ctx)
20399
20676
  ];
20400
20677
  }
20401
- function ptToLine22(a, b, p) {
20402
- const dx = b.x - a.x;
20403
- const dy = b.y - a.y;
20404
- let a2 = (p.y - a.y) * dx - (p.x - a.x) * dy;
20405
- a2 *= a2;
20406
- if (a2 < MAP_SMALL) return 0;
20407
- return a2 / (dx * dx + dy * dy);
20408
- }
20409
20678
  function checkControlPoints2(cp) {
20410
- return ptToLine22(cp[0], cp[3], cp[1]) < MAP_HW * MAP_HW && ptToLine22(cp[0], cp[3], cp[2]) < MAP_HW * MAP_HW;
20679
+ return ptToLine2(cp[0], cp[3], cp[1]) < MAP_HW * MAP_HW && ptToLine2(cp[0], cp[3], cp[2]) < MAP_HW * MAP_HW;
20411
20680
  }
20412
20681
  function bezierHalf(v) {
20413
20682
  const left2 = [];
@@ -20642,9 +20911,20 @@ function labelSpanX(lp, just) {
20642
20911
  if (just === "r") return lp.pos.x + lp.space.x / 2;
20643
20912
  return lp.pos.x;
20644
20913
  }
20914
+ function labelColorNames(lp) {
20915
+ if (lp.html) return lp.u.kind === "html" ? htmlLabelColors(lp.u.html) : [];
20916
+ return lp.u.kind === "txt" && lp.u.nspans >= 1 ? [lp.fontcolor] : [];
20917
+ }
20918
+ function reportEdgeLabelColors(e) {
20919
+ const labels = [e.info.label, e.info.xlabel, e.info.head_label, e.info.tail_label];
20920
+ for (const lp of labels) {
20921
+ if (lp?.set) reportColorNames(labelColorNames(lp));
20922
+ }
20923
+ }
20645
20924
  function renderOneLabel(lp, renderer, job, requireSet = true) {
20646
20925
  if (!lp) return;
20647
20926
  if (requireSet && !lp.set) return;
20927
+ reportColorNames(labelColorNames(lp));
20648
20928
  if (lp.html) {
20649
20929
  if (lp.u.kind === "html") {
20650
20930
  const html = lp.u.html;
@@ -20753,7 +21033,7 @@ function setEdgePen(e, job) {
20753
21033
  const flags = parseStyleFlags(e.attrs.get("style"));
20754
21034
  obj.penColor = withColorScheme(
20755
21035
  e.attrs.get("colorscheme"),
20756
- () => resolveRenderColor(resolvePenColor(e.attrs.get("color")))
21036
+ () => resolveRenderColor(resolvePenColor(e.attrs.get("color")), false)
20757
21037
  );
20758
21038
  obj.pen = resolvePenType(flags);
20759
21039
  obj.penWidth = resolvePenWidth(flags, e.attrs.get("penwidth"));
@@ -20772,6 +21052,8 @@ function renderEdge(e, renderer, job) {
20772
21052
  resolveEdgeAnchor(e, svgEdgeId(e, job), obj);
20773
21053
  withColorScheme(e.attrs.get("colorscheme"), () => {
20774
21054
  renderer.beginEdge(e, job);
21055
+ reportEdgeColors(e);
21056
+ reportEdgeLabelColors(e);
20775
21057
  renderer.endEdge(e, job);
20776
21058
  });
20777
21059
  } finally {
@@ -20855,8 +21137,11 @@ function renderPage(g, renderer, job, info) {
20855
21137
  resolveObjAnchor(g, labelTextOf2(g.info.label), svgGraphId(g, job), job.obj);
20856
21138
  }
20857
21139
  const anchored = beginAnchorIf(renderer, job);
20858
- renderer.pageBackground?.(g, job);
20859
- renderGraphLabel(g, renderer, job);
21140
+ withColorScheme(g.attrs.get("colorscheme"), () => {
21141
+ reportColorNames(backgroundColors(g.attrs.get("bgcolor"), renderer.type === "svg"));
21142
+ renderer.pageBackground?.(g, job);
21143
+ renderGraphLabel(g, renderer, job);
21144
+ });
20860
21145
  if (anchored) renderer.endAnchor?.(job);
20861
21146
  const clustersLast = (job.flags & EMIT_CLUSTERS_LAST) !== 0;
20862
21147
  if (!clustersLast) renderClusters(g, renderer, job);
@@ -20888,6 +21173,7 @@ function render(ctx, g, format, inlineImages = false) {
20888
21173
  job.scale = { x: z * dpiScale, y: z * dpiScale };
20889
21174
  job.rotation = parseLandscape(g) ? 90 : 0;
20890
21175
  job.renderer = renderer;
21176
+ setRendererKnownColors(renderer.type === "svg");
20891
21177
  resetHtmlAnchorIds();
20892
21178
  for (const n of g.nodes.values()) polyInit(n, g, job.measurer);
20893
21179
  return renderGraph(g, job, renderer);
@@ -20956,6 +21242,7 @@ function htmlFillPenWidth() {
20956
21242
  function resetHtmlFillPenWidth() {
20957
21243
  htmlFillPen = 1;
20958
21244
  }
21245
+ registerRenderState(resetHtmlFillPenWidth);
20959
21246
  function penTypeOf(style2) {
20960
21247
  const st = htmlStyle(style2);
20961
21248
  if (st.dashed) return 1 /* Dashed */;
@@ -21084,9 +21371,34 @@ function emitSidedPolylines(sides2, corners, renderer, job) {
21084
21371
  renderer.polyline(seq2.map((i) => corners[i]), job);
21085
21372
  }
21086
21373
  }
21374
+ var HTML_DEFAULT_COLOR = "black";
21375
+ function bgNames(bgcolor) {
21376
+ const spec = parseGradientSpec(bgcolor);
21377
+ return spec === null ? [bgcolor] : [spec[0], spec[1]];
21378
+ }
21379
+ function cellNames(cell2) {
21380
+ if (htmlStyle(cell2.style).invisible) return [];
21381
+ const out = cell2.bgcolor !== void 0 ? bgNames(cell2.bgcolor) : [];
21382
+ if (cell2.border > 0) out.push(cell2.color ?? HTML_DEFAULT_COLOR);
21383
+ if (cell2.nested !== void 0) out.push(...tableNames(cell2.nested));
21384
+ else for (const line of cell2.lines) if (line.fontColor !== null) out.push(line.fontColor);
21385
+ return out;
21386
+ }
21387
+ function tableNames(tbl) {
21388
+ if (htmlStyle(tbl.style).invisible) return [];
21389
+ const out = tbl.bgcolor !== void 0 ? bgNames(tbl.bgcolor) : [];
21390
+ const color = tbl.color ?? HTML_DEFAULT_COLOR;
21391
+ if (tbl.cells.some((c) => c.vruled === true || c.hruled === true)) out.push(color);
21392
+ if (tbl.border > 0) out.push(color);
21393
+ for (const cell2 of tbl.cells) out.push(...cellNames(cell2));
21394
+ return out;
21395
+ }
21396
+ function htmlLabelColors(label) {
21397
+ return [label.color ?? HTML_DEFAULT_COLOR, ...tableNames(label)];
21398
+ }
21087
21399
 
21088
21400
  // src/common/style-resolve.ts
21089
- var DEFAULT_COLOR3 = "black";
21401
+ var DEFAULT_COLOR4 = "black";
21090
21402
  var DEFAULT_FILL = "lightgrey";
21091
21403
  var PENWIDTH_BOLD2 = 2;
21092
21404
  var TOKEN_FLAG = {
@@ -21202,7 +21514,7 @@ function resolvePenWidth(flags, penwidthAttr) {
21202
21514
  return 1;
21203
21515
  }
21204
21516
  function resolvePenColor(colorAttr) {
21205
- if (!colorAttr || colorAttr.length === 0) return DEFAULT_COLOR3;
21517
+ if (!colorAttr || colorAttr.length === 0) return DEFAULT_COLOR4;
21206
21518
  return firstSolidColor(colorAttr);
21207
21519
  }
21208
21520
  function clusterColorAttrs(attrs) {
@@ -21228,7 +21540,7 @@ function findStopColor(colorlist) {
21228
21540
  const seg1 = segs[1];
21229
21541
  if (seg0.color === null) return null;
21230
21542
  const fillColor = seg0.color;
21231
- const stopColor = seg1.color ?? DEFAULT_COLOR3;
21543
+ const stopColor = seg1.color ?? DEFAULT_COLOR4;
21232
21544
  const frac = seg0.hasFraction ? seg0.t : seg1.hasFraction ? 1 - seg1.t : 0;
21233
21545
  return { fillColor, stopColor, frac };
21234
21546
  }
@@ -23896,6 +24208,9 @@ var clType = LOCAL;
23896
24208
  function setClType(t) {
23897
24209
  clType = t;
23898
24210
  }
24211
+ registerRenderState(() => {
24212
+ clType = LOCAL;
24213
+ });
23899
24214
  function mapbool2(s) {
23900
24215
  if (!s || s === "") return false;
23901
24216
  const l = s.toLowerCase();
@@ -25479,20 +25794,20 @@ function fillRankVlist(g, r, root) {
25479
25794
  const rankArr = g.info.rank;
25480
25795
  const lead = g.info.rankleader[r];
25481
25796
  if (lead === void 0 || lead === null) {
25482
- console.error(`Error: rebuild_vlists: lead is null for rank ${r}`);
25797
+ agerrorf(`rebuild_vlists: lead is null for rank ${r}`);
25483
25798
  return -1;
25484
25799
  }
25485
25800
  const rootRank = root.info.rank[r];
25486
25801
  if (rootRank.v[lead.info.order ?? 0] !== lead) {
25487
- console.error(
25488
- `Error: rebuild_vlists: rank lead ${lead.name} not in order ${lead.info.order ?? 0} of rank ${r}`
25802
+ agerrorf(
25803
+ `rebuild_vlists: rank lead ${lead.name} not in order ${lead.info.order ?? 0} of rank ${r}`
25489
25804
  );
25490
25805
  return -1;
25491
25806
  }
25492
25807
  rankArr[r].v = rootRank.v;
25493
25808
  rankArr[r].vStart = lead.info.order ?? 0;
25494
25809
  const maxi = computeMaxi(g, r);
25495
- if (maxi === -1) console.error(`Warning: degenerate concentrated rank ${g.name},${r}`);
25810
+ if (maxi === -1) agwarningf(`degenerate concentrated rank ${g.name},${r}`, "error");
25496
25811
  rankArr[r].n = maxi + 1;
25497
25812
  return 0;
25498
25813
  }
@@ -25581,7 +25896,7 @@ function dotConcentrate(g) {
25581
25896
  const clust = g.info.clust ?? [];
25582
25897
  for (let c = 0; c < nCluster; c++) {
25583
25898
  if (rebuildVlists(clust[c]) !== 0) {
25584
- console.error("concentrate=true may not work correctly.");
25899
+ agerr("prev", "concentrate=true may not work correctly.");
25585
25900
  return -1;
25586
25901
  }
25587
25902
  }
@@ -28311,7 +28626,7 @@ function routeSplinesInternal(pp, polyline) {
28311
28626
  ];
28312
28627
  const pl = shortestPath(poly, eps);
28313
28628
  if (pl === null) {
28314
- console.warn("in routesplines, Pshortestpath failed");
28629
+ agerrLineOn("warn", "in routesplines, Pshortestpath failed");
28315
28630
  return null;
28316
28631
  }
28317
28632
  emitDump("S3_POLY", dumpNames, () => ({
@@ -30630,6 +30945,10 @@ function addXLabels(gp) {
30630
30945
  var IGNORED_EDGE = 6;
30631
30946
  var Rankdir = 0;
30632
30947
  var Offset = { x: 0, y: 0 };
30948
+ registerRenderState(() => {
30949
+ Rankdir = 0;
30950
+ Offset = { x: 0, y: 0 };
30951
+ });
30633
30952
  function mapPoint(p) {
30634
30953
  const r = ccwrotatepf(p, Rankdir * 90);
30635
30954
  return { x: r.x - Offset.x, y: r.y - Offset.y };
@@ -30717,7 +31036,7 @@ function translateDrawing(g) {
30717
31036
  if (e.tail !== v) continue;
30718
31037
  if (e.info.spl === void 0) {
30719
31038
  if (!(g.info.concentrate ?? false) && (e.info.edge_type ?? 0) !== IGNORED_EDGE) {
30720
- console.warn(`lost ${e.tail.name} ${e.head.name} edge`);
31039
+ agerrLineOn("warn", `lost ${e.tail.name} ${e.head.name} edge`);
30721
31040
  }
30722
31041
  continue;
30723
31042
  }
@@ -31830,7 +32149,11 @@ var A = BigInt("0x5deece66d");
31830
32149
  var C = BigInt("0xb");
31831
32150
  var MASK48 = (1n << 48n) - 1n;
31832
32151
  var TWO48 = 2 ** 48;
31833
- var state = 0x330en;
32152
+ var UNSEEDED_STATE = 0x1234abcd330en;
32153
+ var state = UNSEEDED_STATE;
32154
+ registerRenderState(() => {
32155
+ state = UNSEEDED_STATE;
32156
+ });
31834
32157
  function srand48(seed) {
31835
32158
  const s = BigInt(Math.trunc(seed)) & 0xffffffffn;
31836
32159
  state = (s << 16n | 0x330en) & MASK48;
@@ -34017,7 +34340,8 @@ function ensureDummyNodes(sg, gstart) {
34017
34340
  }
34018
34341
  function orthoEdges(g, useLbls, clipAndInstall2) {
34019
34342
  if (useLbls) {
34020
- console.warn(
34343
+ agerrLineOn(
34344
+ "warn",
34021
34345
  "Orthogonal edges do not currently handle edge labels. Try using xlabels.\n"
34022
34346
  );
34023
34347
  useLbls = false;
@@ -34377,12 +34701,12 @@ function origSeq(e) {
34377
34701
  return resolveOrigEdge(e).seq;
34378
34702
  }
34379
34703
  function dedupByOrig(group) {
34380
- const seen = /* @__PURE__ */ new Set();
34704
+ const seen2 = /* @__PURE__ */ new Set();
34381
34705
  const out = [];
34382
34706
  for (const e of group) {
34383
34707
  const o = resolveOrigEdge(e);
34384
- if (seen.has(o)) continue;
34385
- seen.add(o);
34708
+ if (seen2.has(o)) continue;
34709
+ seen2.add(o);
34386
34710
  out.push(o);
34387
34711
  }
34388
34712
  return out;
@@ -34699,7 +35023,7 @@ function orthoDispatch(g) {
34699
35023
  function curvedTop(g) {
34700
35024
  resetRW(g);
34701
35025
  if (((g.root.info.has_labels ?? 0) & EDGE_LABEL) !== 0) {
34702
- console.warn("edge labels with splines=curved not supported in dot - use xlabels\n");
35026
+ agerrLineOn("warn", "edge labels with splines=curved not supported in dot - use xlabels\n");
34703
35027
  }
34704
35028
  }
34705
35029
  function finalizeSplines(g, et, normalize) {
@@ -36347,7 +36671,7 @@ function lenattr(ep, g) {
36347
36671
  const val2 = /^\s*[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/.exec(s);
36348
36672
  const len = val2 === null ? Number.NaN : parseFloat(val2[0]);
36349
36673
  if (Number.isNaN(len) || len < 0 || len === 0) {
36350
- console.warn(`bad edge len "${s}" in ${g.name} - setting to ${DEFAULT_EDGE_LEN.toFixed(2)}`);
36674
+ agerrLineOn("warn", `bad edge len "${s}" in ${g.name} - setting to ${DEFAULT_EDGE_LEN.toFixed(2)}`);
36351
36675
  return DEFAULT_EDGE_LEN;
36352
36676
  }
36353
36677
  return len;
@@ -36444,7 +36768,10 @@ var START_KEYWORDS = [
36444
36768
  ];
36445
36769
  var WARN_POS_IGNORED = "node positions are ignored unless start=random";
36446
36770
  var WARN_SELF_IGNORED = "start=0 not supported with mode=self - ignored";
36447
- var selfWarned = /* @__PURE__ */ new WeakSet();
36771
+ var selfOnce = { warned: false };
36772
+ registerRenderState(() => {
36773
+ selfOnce.warned = false;
36774
+ });
36448
36775
  var circuitWarned = /* @__PURE__ */ new WeakSet();
36449
36776
  function parseStart(p, dflt) {
36450
36777
  let init = dflt;
@@ -36475,7 +36802,7 @@ function initRegular(g, nG) {
36475
36802
  function checkStart(g, nG = g.nodes.size, dflt = INIT_RANDOM) {
36476
36803
  const { init, seed } = parseStart(g.root.attrs.get("start"), dflt);
36477
36804
  if (init !== INIT_RANDOM && [...g.nodes.values()].some((n) => n.attrs.has("pos"))) {
36478
- console.warn(WARN_POS_IGNORED);
36805
+ agerrLineOn("warn", WARN_POS_IGNORED);
36479
36806
  }
36480
36807
  if (init === INIT_REGULAR) initRegular(g, nG);
36481
36808
  srand48(seed);
@@ -36508,7 +36835,7 @@ function neatoMode(g) {
36508
36835
  if (str === void 0 || str === "") return MODE_MAJOR;
36509
36836
  const mode = modeByName().get(str);
36510
36837
  if (mode !== void 0) return mode;
36511
- console.warn(`Illegal value ${str} for attribute "mode" in graph ${g.root.name} - ignored`);
36838
+ agerrLineOn("warn", `Illegal value ${str} for attribute "mode" in graph ${g.root.name} - ignored`);
36512
36839
  return MODE_MAJOR;
36513
36840
  }
36514
36841
  function checkMode(g, mode) {
@@ -36522,9 +36849,9 @@ function checkStartAttr(g, mode) {
36522
36849
  const value = g.root.attrs.get("start");
36523
36850
  if (parseStart(value, INIT_RANDOM).init !== INIT_SELF) return;
36524
36851
  if (mode === MODE_MAJOR || mode === MODE_IPSEP) unsupported("start", value ?? "", "smart initialisation");
36525
- if ((mode === MODE_KK || mode === MODE_SGD) && !selfWarned.has(g.root)) {
36526
- selfWarned.add(g.root);
36527
- console.warn(WARN_SELF_IGNORED);
36852
+ if ((mode === MODE_KK || mode === MODE_SGD) && !selfOnce.warned) {
36853
+ selfOnce.warned = true;
36854
+ agerrLineOn("warn", WARN_SELF_IGNORED);
36528
36855
  }
36529
36856
  }
36530
36857
  function isConnected(g) {
@@ -36535,15 +36862,15 @@ function isConnected(g) {
36535
36862
  adj.get(e.tail)?.push(e.head);
36536
36863
  adj.get(e.head)?.push(e.tail);
36537
36864
  }
36538
- const seen = /* @__PURE__ */ new Set([nodes[0]]);
36865
+ const seen2 = /* @__PURE__ */ new Set([nodes[0]]);
36539
36866
  const stack = [nodes[0]];
36540
36867
  for (let n = stack.pop(); n !== void 0; n = stack.pop()) {
36541
- for (const m of adj.get(n) ?? []) if (!seen.has(m)) {
36542
- seen.add(m);
36868
+ for (const m of adj.get(n) ?? []) if (!seen2.has(m)) {
36869
+ seen2.add(m);
36543
36870
  stack.push(m);
36544
36871
  }
36545
36872
  }
36546
- return seen.size === nodes.length;
36873
+ return seen2.size === nodes.length;
36547
36874
  }
36548
36875
  function kkCircuitFallsBack(g) {
36549
36876
  const packed = getPack(g.root, -1, 0) >= 0 || (g.root.attrs.get("packmode") ?? "") !== "";
@@ -36552,7 +36879,8 @@ function kkCircuitFallsBack(g) {
36552
36879
  function warnCircuitDisconnected(g) {
36553
36880
  if (circuitWarned.has(g.root)) return;
36554
36881
  circuitWarned.add(g.root);
36555
- console.warn(
36882
+ agerrLineOn(
36883
+ "warn",
36556
36884
  `graph ${g.root.name} is disconnected. Hence, the circuit model
36557
36885
  is undefined. Reverting to the shortest path model.
36558
36886
  Alternatively, consider running neato using -Gpack=true or decomposing
@@ -36771,13 +37099,15 @@ function buildUnfixed(g, n) {
36771
37099
  }
36772
37100
  function resolveModel(model) {
36773
37101
  if (model === MODEL_CIRCUIT2) {
36774
- console.warn(
37102
+ agerrLineOn(
37103
+ "warn",
36775
37104
  "circuit model not yet supported in Gmode=sgd, reverting to shortpath model"
36776
37105
  );
36777
37106
  return MODEL_SHORTPATH;
36778
37107
  }
36779
37108
  if (model === MODEL_MDS) {
36780
- console.warn(
37109
+ agerrLineOn(
37110
+ "warn",
36781
37111
  "mds model not yet supported in Gmode=sgd, reverting to shortpath model"
36782
37112
  );
36783
37113
  return MODEL_SHORTPATH;
@@ -37162,7 +37492,7 @@ function moveNode(st, m) {
37162
37492
  function solveModel(g, st) {
37163
37493
  for (let m = chooseNode(st); m >= 0; m = chooseNode(st)) moveNode(st, m);
37164
37494
  if (st.move === st.maxIter) {
37165
- console.warn(`Max. iterations (${st.maxIter}) reached on graph ${g.name}`);
37495
+ agerrLineOn("warn", `Max. iterations (${st.maxIter}) reached on graph ${g.name}`);
37166
37496
  }
37167
37497
  }
37168
37498
  function mdsEdges(g, nodes, lens) {
@@ -37621,6 +37951,7 @@ var MODE_MAJOR = 1;
37621
37951
  var MODE_HIER = 2;
37622
37952
  var MODE_IPSEP = 3;
37623
37953
  var MODE_SGD = 4;
37954
+ var SGD_ITERATIONS = 30;
37624
37955
  var MODEL_SHORTPATH2 = 0;
37625
37956
  var MODEL_CIRCUIT = 1;
37626
37957
  var MODEL_SUBSET = 2;
@@ -37660,6 +37991,11 @@ function assignNodeIds2(g) {
37660
37991
  }
37661
37992
  return nodeList;
37662
37993
  }
37994
+ function neatoMaxIter(maxiter, mode, n) {
37995
+ if (maxiter !== void 0) return parseInt(maxiter, 10) || 0;
37996
+ if (mode === MODE_MAJOR) return DFLT_ITERATIONS;
37997
+ return mode === MODE_SGD ? SGD_ITERATIONS : 100 * n;
37998
+ }
37663
37999
  function runMajorization(g, mode, model) {
37664
38000
  void model;
37665
38001
  const nodeList = assignNodeIds2(g);
@@ -37667,7 +38003,7 @@ function runMajorization(g, mode, model) {
37667
38003
  const haveLen = graphHasLen(g);
37668
38004
  const vtx = makeGraphDataC(g, nodeList, haveLen, mode === MODE_HIER || mode === MODE_IPSEP);
37669
38005
  checkStart(g);
37670
- const maxi = lateDouble(g.attrs.get("maxiter"), DFLT_ITERATIONS, 0);
38006
+ const maxi = neatoMaxIter(g.attrs.get("maxiter"), mode, n);
37671
38007
  const epsilon = lateDouble(g.attrs.get("epsilon"), 1e-4, 0);
37672
38008
  const weighted = haveLen && mode !== MODE_IPSEP;
37673
38009
  const Dij = weighted ? computeWeightedApspPacked2(vtx, n) : computeApspPacked2(vtx, n);
@@ -37697,18 +38033,18 @@ function makeGraphDataC(g, nodeList, haveLen, haveDir) {
37697
38033
  for (const np of nodeList) {
37698
38034
  const i = np.info.id;
37699
38035
  const entry = vtx[i];
37700
- const seen = /* @__PURE__ */ new Map();
38036
+ const seen2 = /* @__PURE__ */ new Map();
37701
38037
  for (const ep of [...np.outEdges(g), ...np.inEdges(g)]) {
37702
38038
  if (ep.head === ep.tail) continue;
37703
38039
  const vp = ep.tail === np ? ep.head : ep.tail;
37704
38040
  const vid = vp.info.id;
37705
38041
  const dist4 = haveLen ? lateDouble(ep.attrs.get("len"), 1, 0) : 1;
37706
- const idx = seen.get(vid);
38042
+ const idx = seen2.get(vid);
37707
38043
  if (idx !== void 0) {
37708
38044
  if (haveLen) entry.ewgts[idx] = Math.max(entry.ewgts[idx], dist4);
37709
38045
  continue;
37710
38046
  }
37711
- seen.set(vid, entry.nedges);
38047
+ seen2.set(vid, entry.nedges);
37712
38048
  entry.edges.push(vid);
37713
38049
  if (haveLen || haveDir) entry.ewgts.push(dist4);
37714
38050
  entry.nedges++;
@@ -38055,15 +38391,15 @@ function delaunayTri(xv, yv, n) {
38055
38391
  for (let i = 1; i < n; i++) edges2.push(vs[i - 1], vs[i]);
38056
38392
  return edges2;
38057
38393
  }
38058
- const seen = /* @__PURE__ */ new Set();
38394
+ const seen2 = /* @__PURE__ */ new Set();
38059
38395
  const pairs = [];
38060
38396
  for (const t of tris) {
38061
38397
  for (const [u, v] of [[t.a, t.b], [t.b, t.c], [t.c, t.a]]) {
38062
38398
  const i = Math.min(u, v);
38063
38399
  const j = Math.max(u, v);
38064
38400
  const key = i * 1048576 + j;
38065
- if (!seen.has(key)) {
38066
- seen.add(key);
38401
+ if (!seen2.has(key)) {
38402
+ seen2.add(key);
38067
38403
  pairs.push([i, j]);
38068
38404
  }
38069
38405
  }
@@ -38348,8 +38684,8 @@ var Cdt = class {
38348
38684
  const en = this.edgeOrNew(v3, v4);
38349
38685
  this.removeFace(f1);
38350
38686
  this.removeFace(f2);
38351
- const f3 = this.addFace([v4, v2, v3], [e5, e2, en]);
38352
- const f4 = this.addFace([v1, v4, v3], [e4, en, e3]);
38687
+ const f3 = this.addFace([v3, v4, v2], [en, e5, e2]);
38688
+ const f4 = this.addFace([v4, v3, v1], [en, e3, e4]);
38353
38689
  this.swapIfInCircle(f3, v4, v2, v3, e5, e2, en);
38354
38690
  this.swapIfInCircle(f4, v1, v4, v3, e4, en, e3);
38355
38691
  }
@@ -38651,10 +38987,7 @@ function sharedEdge(faces, p3, q3) {
38651
38987
  return { i: p1, j: p2 };
38652
38988
  }
38653
38989
  function addTriEdge(g, t, h, seg2) {
38654
- const dist4 = Math.hypot(
38655
- g.nodes[t].ctr.x - g.nodes[h].ctr.x,
38656
- g.nodes[t].ctr.y - g.nodes[h].ctr.y
38657
- );
38990
+ const dist4 = Math.sqrt(dist2(g.nodes[t].ctr, g.nodes[h].ctr));
38658
38991
  const idx = g.edges.length;
38659
38992
  g.edges.push({ t, h, seg: seg2, dist: dist4 });
38660
38993
  g.nodes[t].edges.push(idx);
@@ -38981,7 +39314,7 @@ var SEP = 15;
38981
39314
  function bisectorTarget(v, cosTheta, sinTheta) {
38982
39315
  return { x: fma(cosTheta, 100, v.x), y: fma(sinTheta, 100, v.y) };
38983
39316
  }
38984
- function distFused(p, q) {
39317
+ function distFused2(p, q) {
38985
39318
  const dx = p.x - q.x;
38986
39319
  const dy = p.y - q.y;
38987
39320
  return Math.sqrt(fma(dx, dx, dy * dy));
@@ -39006,7 +39339,7 @@ function mkCtrlPts(s, mult, prev, v, nxt, trip) {
39006
39339
  }
39007
39340
  const q = triPoint(trip, idx, v, w);
39008
39341
  if (q === null) return null;
39009
- const d = distFused(q, v);
39342
+ const d = distFused2(q, v);
39010
39343
  const sep = d >= mult * SEP ? SEP : d / mult;
39011
39344
  const ps = new Array(mult);
39012
39345
  if (idx < s) {
@@ -39135,8 +39468,8 @@ function chainOf(e) {
39135
39468
  return list;
39136
39469
  }
39137
39470
  function warnNoControlPoints(e) {
39138
- console.warn(
39139
- `Warning: Could not create control points for multiple spline for edge (${e.tail.name},${e.head.name})`
39471
+ agwarningf(
39472
+ `Could not create control points for multiple spline for edge (${e.tail.name},${e.head.name})`
39140
39473
  );
39141
39474
  return 1;
39142
39475
  }
@@ -41799,7 +42132,11 @@ function armPow(x, y) {
41799
42132
 
41800
42133
  // src/common/crand.ts
41801
42134
  var C_RAND_MAX = 2147483647;
41802
- var state2 = 1;
42135
+ var UNSEEDED_STATE2 = 1;
42136
+ var state2 = UNSEEDED_STATE2;
42137
+ registerRenderState(() => {
42138
+ state2 = UNSEEDED_STATE2;
42139
+ });
41803
42140
  function csrand(seed) {
41804
42141
  state2 = seed;
41805
42142
  }
@@ -43739,7 +44076,7 @@ function makeAddPoly(n, xmargin, ymargin) {
43739
44076
  case 3 /* SH_POINT */:
43740
44077
  return finishPoly(genRound(n, xmargin, ymargin), POLY_CIRCLE);
43741
44078
  default:
43742
- console.error(`Error: makeAddPoly: unknown shape type ${shapeName(n)}
44079
+ agerrorf(`makeAddPoly: unknown shape type ${shapeName(n)}
43743
44080
  `);
43744
44081
  return null;
43745
44082
  }
@@ -43772,7 +44109,7 @@ function baseShape(n) {
43772
44109
  case 3 /* SH_POINT */:
43773
44110
  return { verts: genRound(n, 0, 0), kind: POLY_CIRCLE };
43774
44111
  default:
43775
- console.error(`Error: makePoly: unknown shape type ${shapeName(n)}
44112
+ agerrorf(`makePoly: unknown shape type ${shapeName(n)}
43776
44113
  `);
43777
44114
  return null;
43778
44115
  }
@@ -45154,7 +45491,7 @@ function warnUnrecognizedOverlap(flag) {
45154
45491
  const s = flag.toLowerCase();
45155
45492
  if (s.startsWith("prism") || NAMED_MODES.has(s)) return;
45156
45493
  if (mapBoolDflt(flag, false) === mapBoolDflt(flag, true)) return;
45157
- console.warn(`Unrecognized overlap value "${flag}" - using false`);
45494
+ agerrLineOn("warn", `Unrecognized overlap value "${flag}" - using false`);
45158
45495
  }
45159
45496
  function getAdjustMode(flag) {
45160
45497
  warnUnrecognizedOverlap(flag);
@@ -45187,7 +45524,7 @@ function adjustLate(g, am) {
45187
45524
  case AM_VPSC:
45188
45525
  return vpscAdjust(g);
45189
45526
  default:
45190
- console.warn(`Unhandled adjust option ${am.print}`);
45527
+ agerrLineOn("warn", `Unhandled adjust option ${am.print}`);
45191
45528
  return 0;
45192
45529
  }
45193
45530
  }
@@ -45406,20 +45743,20 @@ function setSubtreeSize(g) {
45406
45743
  walkAncestorChain(n);
45407
45744
  }
45408
45745
  }
45409
- function applySpanToChild(g, n, next, ratio, seen) {
45746
+ function applySpanToChild(g, n, next, ratio, seen2) {
45410
45747
  const nd2 = rdata(next);
45411
- if (nd2.parent !== n || nd2.span !== 0 || seen.has(next)) return;
45412
- seen.add(next);
45748
+ if (nd2.parent !== n || nd2.span !== 0 || seen2.has(next)) return;
45749
+ seen2.add(next);
45413
45750
  nd2.span = ratio * nd2.subtreeSize;
45414
45751
  if (nd2.nChildren > 0) setChildSubtreeSpans(g, next);
45415
45752
  }
45416
45753
  function setChildSubtreeSpans(g, n) {
45417
45754
  const nd = rdata(n);
45418
45755
  const ratio = nd.span / nd.subtreeSize;
45419
- const seen = /* @__PURE__ */ new Set();
45756
+ const seen2 = /* @__PURE__ */ new Set();
45420
45757
  for (const ep of incidentEdges2(g, n)) {
45421
45758
  const next = neighborOf(ep, n);
45422
- if (next !== null) applySpanToChild(g, n, next, ratio, seen);
45759
+ if (next !== null) applySpanToChild(g, n, next, ratio, seen2);
45423
45760
  }
45424
45761
  }
45425
45762
  function setSubtreeSpans(sg, center) {
@@ -45688,7 +46025,7 @@ var fdpParms = {
45688
46025
  * equivalent). @see lib/fdpgen/fdp.h:fdpParms_s.Mlimit */
45689
46026
  Mlimit: Infinity
45690
46027
  };
45691
- var parms = {
46028
+ var PARMS_INIT = {
45692
46029
  useGrid: 0,
45693
46030
  useNew: 0,
45694
46031
  seed: 0,
@@ -45706,6 +46043,10 @@ var parms = {
45706
46043
  pass1: 0,
45707
46044
  loopcnt: 0
45708
46045
  };
46046
+ var parms = { ...PARMS_INIT };
46047
+ registerRenderState(() => {
46048
+ Object.assign(parms, PARMS_INIT);
46049
+ });
45709
46050
  function cool(t) {
45710
46051
  return parms.T0 * (parms.maxIters - t) / parms.maxIters;
45711
46052
  }
@@ -46350,14 +46691,19 @@ function fdpTLayout(g, xpms) {
46350
46691
  // src/layout/fdp/xlayout.ts
46351
46692
  var DFLT_OVERLAP = "9:prism";
46352
46693
  var PS2INCH3 = (x) => x / 72;
46353
- var xParams = {
46694
+ var XPARAMS_INIT = {
46354
46695
  numIters: 60,
46355
46696
  T0: 0,
46356
46697
  K: 0.3,
46357
46698
  C: 1.5,
46358
46699
  loopcnt: 0
46359
46700
  };
46701
+ var xParams = { ...XPARAMS_INIT };
46360
46702
  var xMarg = { x: 0, y: 0, doAdd: false };
46703
+ registerRenderState(() => {
46704
+ Object.assign(xParams, XPARAMS_INIT);
46705
+ xMarg = { x: 0, y: 0, doAdd: false };
46706
+ });
46361
46707
  function wd2(n) {
46362
46708
  return xMarg.doAdd ? n.info.width / 2 + xMarg.x : n.info.width * xMarg.x / 2;
46363
46709
  }
@@ -47219,7 +47565,7 @@ function fdpSplines(g) {
47219
47565
  );
47220
47566
  }
47221
47567
  if (g.info.n_cluster_edges) {
47222
- console.warn(CLUSTER_EDGE_WARNING);
47568
+ agerrLineOn("warn", CLUSTER_EDGE_WARNING);
47223
47569
  et = EDGETYPE_LINE;
47224
47570
  } else {
47225
47571
  splineEdges1(g, et);
@@ -48641,7 +48987,7 @@ function buildDerivedGraph(g) {
48641
48987
  }
48642
48988
  function buildDerivedEdges(g, dg) {
48643
48989
  const edges = [];
48644
- const seen = /* @__PURE__ */ new Set();
48990
+ const seen2 = /* @__PURE__ */ new Set();
48645
48991
  for (const n of nodesInSeq(g)) {
48646
48992
  for (const e of n.outEdges(g)) {
48647
48993
  if (e.tail === e.head) continue;
@@ -48649,8 +48995,8 @@ function buildDerivedEdges(g, dg) {
48649
48995
  const head = dg.nodes.get(e.head.name);
48650
48996
  if (!tail || !head) continue;
48651
48997
  const key = [tail.name, head.name].sort().join("\0");
48652
- if (seen.has(key)) continue;
48653
- seen.add(key);
48998
+ if (seen2.has(key)) continue;
48999
+ seen2.add(key);
48654
49000
  edges.push({ tail, head, order: 0, origEdge: e });
48655
49001
  }
48656
49002
  }
@@ -49494,12 +49840,12 @@ function svgEndCluster(job) {
49494
49840
  }
49495
49841
 
49496
49842
  // src/render/svg-edge-split.ts
49497
- var DEFAULT_COLOR4 = "black";
49843
+ var DEFAULT_COLOR5 = "black";
49498
49844
  var PENWIDTH_NORMAL4 = 1;
49499
49845
  var PENWIDTH_THRESHOLD4 = 5e-3;
49500
49846
  var EPS3 = 1e-5;
49501
49847
  function dist3(a, b) {
49502
- return Math.hypot(a.x - b.x, a.y - b.y);
49848
+ return Math.sqrt(dist2(a, b));
49503
49849
  }
49504
49850
  function approxLen(list, off) {
49505
49851
  return dist3(list[off], list[off + 1]) + dist3(list[off + 1], list[off + 2]) + dist3(list[off + 2], list[off + 3]);
@@ -49548,7 +49894,7 @@ function emitCurve(list, color, job) {
49548
49894
  }
49549
49895
  function stepSegment(list, s, st, out) {
49550
49896
  if (Math.abs(s.t) < EPS3) return;
49551
- const color = s.color ?? DEFAULT_COLOR4;
49897
+ const color = s.color ?? DEFAULT_COLOR5;
49552
49898
  st.left -= s.t;
49553
49899
  st.endColor = color;
49554
49900
  if (st.first) {
@@ -49567,7 +49913,7 @@ function stepSegment(list, s, st, out) {
49567
49913
  }
49568
49914
  }
49569
49915
  function splitSplineByColor(list, segs) {
49570
- const st = { left: 1, first: true, bzR: list, done: false, endColor: DEFAULT_COLOR4 };
49916
+ const st = { left: 1, first: true, bzR: list, done: false, endColor: DEFAULT_COLOR5 };
49571
49917
  const curves = [];
49572
49918
  for (const s of segs) {
49573
49919
  stepSegment(list, s, st, curves);
@@ -49582,16 +49928,16 @@ function drawSplitSpline(list, segs, job) {
49582
49928
  }
49583
49929
  function emitSplitEdgePaths(e, job, colorList) {
49584
49930
  const segs = parseSegs(colorList).segs;
49585
- const firstColor = segs[0]?.color ?? DEFAULT_COLOR4;
49931
+ const firstColor2 = segs[0]?.color ?? DEFAULT_COLOR5;
49586
49932
  const spl = e.info.spl;
49587
- let endColor = firstColor;
49588
- if (spl === void 0) return { firstColor, endColor };
49933
+ let endColor = firstColor2;
49934
+ if (spl === void 0) return { firstColor: firstColor2, endColor };
49589
49935
  for (let si = 0; si < spl.size; si++) {
49590
49936
  const bz = spl.list[si];
49591
49937
  if (bz === void 0 || bz.size < 4) continue;
49592
49938
  endColor = drawSplitSpline(bz.list, segs, job);
49593
49939
  }
49594
- return { firstColor, endColor };
49940
+ return { firstColor: firstColor2, endColor };
49595
49941
  }
49596
49942
 
49597
49943
  // src/common/taper.ts
@@ -51036,7 +51382,7 @@ var DotWriterBase = class {
51036
51382
  };
51037
51383
 
51038
51384
  // src/render/dot/edge-draw.ts
51039
- var DEFAULT_COLOR5 = "black";
51385
+ var DEFAULT_COLOR6 = "black";
51040
51386
  var DEFAULT_LINE_STYLE = ["solid", "setlinewidth(1)"];
51041
51387
  function emitArrowOp(buf, op, pen) {
51042
51388
  switch (op.kind) {
@@ -51129,8 +51475,8 @@ var EdgeDrawBase = class extends DotWriterBase {
51129
51475
  */
51130
51476
  emitSplitSpline(bzList, colorAttr, edraw, job) {
51131
51477
  const segs = parseSegs(colorAttr).segs;
51132
- const firstColor = segs[0]?.color ?? DEFAULT_COLOR5;
51133
- let endColor = firstColor;
51478
+ const firstColor2 = segs[0]?.color ?? DEFAULT_COLOR6;
51479
+ let endColor = firstColor2;
51134
51480
  for (const bz of bzList) {
51135
51481
  if (bz === void 0 || bz.size < 4) continue;
51136
51482
  const split = splitSplineByColor(bz.list.slice(0, bz.size), segs);
@@ -51139,7 +51485,7 @@ var EdgeDrawBase = class extends DotWriterBase {
51139
51485
  edraw.push(this.styleOp(job), xdotPenColor(resolveRenderColor(c.color)), xdotPoints("B", c.points));
51140
51486
  }
51141
51487
  }
51142
- return { firstColor, endColor };
51488
+ return { firstColor: firstColor2, endColor };
51143
51489
  }
51144
51490
  /**
51145
51491
  * Emit the parallel-multicolor edge spline: one offset Bézier per color,
@@ -51151,7 +51497,7 @@ var EdgeDrawBase = class extends DotWriterBase {
51151
51497
  const segData = bzList.map(
51152
51498
  (bz) => bz !== void 0 && bz.size >= 4 ? buildOffsetLists(bz.list, (2 + numc) / 2) : { offlist: [], tmplist: [] }
51153
51499
  );
51154
- const colors = parseSegs(colorAttr).segs.map((s) => s.color ?? DEFAULT_COLOR5);
51500
+ const colors = parseSegs(colorAttr).segs.map((s) => s.color ?? DEFAULT_COLOR6);
51155
51501
  for (const color of colors) {
51156
51502
  const pen = xdotPenColor(resolveRenderColor(color));
51157
51503
  for (const sd of segData) {
@@ -51161,8 +51507,8 @@ var EdgeDrawBase = class extends DotWriterBase {
51161
51507
  }
51162
51508
  }
51163
51509
  return {
51164
- headColor: colors[0] ?? DEFAULT_COLOR5,
51165
- tailColor: colors[1] ?? colors[0] ?? DEFAULT_COLOR5
51510
+ headColor: colors[0] ?? DEFAULT_COLOR6,
51511
+ tailColor: colors[1] ?? colors[0] ?? DEFAULT_COLOR6
51166
51512
  };
51167
51513
  }
51168
51514
  /** Emit one arrow's primitive ops into `buf` (pen/fill from the edge color).
@@ -51673,8 +52019,8 @@ var SvgRenderer = class {
51673
52019
  const numc = (colorAttr.match(/:/g) ?? []).length;
51674
52020
  const numsemi = (colorAttr.match(/;/g) ?? []).length;
51675
52021
  if (numsemi > 0 && numc > 0) {
51676
- const { firstColor, endColor } = emitSplitEdgePaths(e, job, colorAttr);
51677
- emitMulticolorArrows(e, job, endColor, firstColor);
52022
+ const { firstColor: firstColor2, endColor } = emitSplitEdgePaths(e, job, colorAttr);
52023
+ emitMulticolorArrows(e, job, endColor, firstColor2);
51678
52024
  } else if (edgeIsTapered(e)) {
51679
52025
  svgTaperedEdge(e, job);
51680
52026
  } else if (numc > 0) {
@@ -52018,7 +52364,7 @@ function peg$parse(input, options) {
52018
52364
  return s;
52019
52365
  }
52020
52366
  function peg$f13(t, m, attrs) {
52021
- if (m) console.error("Warning: attribute macros not implemented");
52367
+ if (m) agwarningf("attribute macros not implemented", "error");
52022
52368
  return { type: "attr", target: t, attrs };
52023
52369
  }
52024
52370
  function peg$f14(a) {
@@ -55452,8 +55798,8 @@ var StmtProcessor = class _StmtProcessor {
55452
55798
  resolveEndpoint(item, root, scope, directed) {
55453
55799
  if ("type" in item && item.type === "subgraph") {
55454
55800
  this.processSubgraph(item, scope, root, directed);
55455
- const seen = /* @__PURE__ */ new Set();
55456
- const nodes = NameCollector.fromStmts(item.stmts).map((n) => this.registry.ensure(n, root, scope)).filter((nd) => seen.has(nd.id) ? false : (seen.add(nd.id), true));
55801
+ const seen2 = /* @__PURE__ */ new Set();
55802
+ const nodes = NameCollector.fromStmts(item.stmts).map((n) => this.registry.ensure(n, root, scope)).filter((nd) => seen2.has(nd.id) ? false : (seen2.add(nd.id), true));
55457
55803
  return nodes.sort((a, b) => a.id - b.id);
55458
55804
  }
55459
55805
  return [this.registry.ensure(item.id, root, scope)];
@@ -55697,22 +56043,22 @@ function countNewlines(s, from, to) {
55697
56043
  return n;
55698
56044
  }
55699
56045
  var HEADER_KEYWORDS = ["strict", "graph", "digraph"];
55700
- function isTruncatedHeaderKeyword(src, step, offset, seen) {
55701
- if (offset !== src.length || step.end !== offset || seen.length > 1) return false;
55702
- if (seen.length === 1 && seen[0].toLowerCase() !== "strict") return false;
56046
+ function isTruncatedHeaderKeyword(src, step, offset, seen2) {
56047
+ if (offset !== src.length || step.end !== offset || seen2.length > 1) return false;
56048
+ if (seen2.length === 1 && seen2[0].toLowerCase() !== "strict") return false;
55703
56049
  const word = step.text.toLowerCase();
55704
56050
  return HEADER_KEYWORDS.some((k) => k.length > word.length && k.startsWith(word));
55705
56051
  }
55706
- function reachesOffset(src, step, offset, seen) {
56052
+ function reachesOffset(src, step, offset, seen2) {
55707
56053
  if (step.end > offset) return true;
55708
- if (isTruncatedHeaderKeyword(src, step, offset, seen)) return true;
56054
+ if (isTruncatedHeaderKeyword(src, step, offset, seen2)) return true;
55709
56055
  if (step.text !== "-" && step.text !== ".") return false;
55710
56056
  return offset <= step.end + (step.text === "-" && src[step.end] === "." ? 1 : 0);
55711
56057
  }
55712
56058
  function scanAtError(src, offset) {
55713
56059
  let line = 1;
55714
56060
  let i = 0;
55715
- const seen = [];
56061
+ const seen2 = [];
55716
56062
  while (i < src.length) {
55717
56063
  const step = lexStep(src, i);
55718
56064
  if (step.kind === "open") {
@@ -55721,10 +56067,10 @@ function scanAtError(src, offset) {
55721
56067
  }
55722
56068
  if (step.kind === "skip" && step.line !== void 0) line = step.line;
55723
56069
  line += countNewlines(src, i, step.end);
55724
- if (step.kind === "token" && reachesOffset(src, step, offset, seen)) {
56070
+ if (step.kind === "token" && reachesOffset(src, step, offset, seen2)) {
55725
56071
  return { state: "INITIAL", text: step.text, line, buffer: "" };
55726
56072
  }
55727
- if (step.kind === "token") seen.push(step.text);
56073
+ if (step.kind === "token") seen2.push(step.text);
55728
56074
  i = step.end;
55729
56075
  }
55730
56076
  return { state: "INITIAL", text: "", line, buffer: "" };
@@ -55917,7 +56263,7 @@ function isPeggyError(err) {
55917
56263
  function warnNumberAmbiguities(src, upTo) {
55918
56264
  for (const a of scanNumberAmbiguities(src, Stripper.strip(src))) {
55919
56265
  if (a.offset > upTo) break;
55920
- console.error(numberAmbiguityMessage(a));
56266
+ agerrFinished(numberAmbiguityMessage(a), "error");
55921
56267
  }
55922
56268
  }
55923
56269
  function parse(src) {
@@ -55931,7 +56277,7 @@ function parse(src) {
55931
56277
  if (isPeggyError(err)) {
55932
56278
  const start = err.location.start;
55933
56279
  warnNumberAmbiguities(src, start.offset);
55934
- console.error(syntaxErrorMessage(src, start.offset));
56280
+ agerrFinished(syntaxErrorMessage(src, start.offset));
55935
56281
  const code = err.found === null ? "SYNTAX_UNEXPECTED_EOF" : "SYNTAX_ERROR";
55936
56282
  throw new ParseError(
55937
56283
  err instanceof Error ? err.message : String(err),
@@ -55956,7 +56302,7 @@ function parse(src) {
55956
56302
  const offset = err instanceof ParseError ? err.location.offset : void 0;
55957
56303
  if (offset !== void 0) {
55958
56304
  warnNumberAmbiguities(src, offset);
55959
- console.error(syntaxErrorMessage(src, offset));
56305
+ agerrFinished(syntaxErrorMessage(src, offset));
55960
56306
  }
55961
56307
  throw err;
55962
56308
  }
@@ -56799,6 +57145,7 @@ function checkRenderArgs(g, format, opts) {
56799
57145
  }
56800
57146
  function render2(g, format, opts) {
56801
57147
  checkRenderArgs(g, format, opts);
57148
+ resetRenderState();
56802
57149
  const engine = opts?.engine ?? "dot";
56803
57150
  const inlineImages = opts?.inlineImages ?? false;
56804
57151
  const ctx = createDefaultContext();
@@ -56995,6 +57342,7 @@ async function renderAsync(g, format, opts) {
56995
57342
  const engine = opts?.engine ?? "dot";
56996
57343
  try {
56997
57344
  const { fontIssues, sizes, bytes } = await prefetchAll(g, opts);
57345
+ resetRenderState();
56998
57346
  const ctx = createDefaultContext();
56999
57347
  if (opts?.imageSizer !== void 0) {
57000
57348
  const sizer = (src) => sizes.get(src) ?? null;
@@ -57059,6 +57407,7 @@ function layoutAndRenderXdot(g, engine) {
57059
57407
  }
57060
57408
  function getDrawOps(g, opts) {
57061
57409
  checkDrawOpsArgs(g, opts);
57410
+ resetRenderState();
57062
57411
  const engine = opts?.engine ?? DEFAULT_DRAW_ENGINE;
57063
57412
  return collectGraphOps(parse(layoutAndRenderXdot(g, engine)));
57064
57413
  }