@knowvah/dot-engine 0.1.0 → 1.1.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.
@@ -1 +1 @@
1
- {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../src/gvc/device.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAO,MAAM,kBAAkB,CAAC;AAInD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI/D,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhE,OAAO,EAAE,SAAS,EAAmF,MAAM,UAAU,CAAC;AAuBtH,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAE5F;AAcD,OAAO,QAAQ,UAAU,CAAC;IACxB,UAAU,SAAS;QACjB,0EAA0E;QAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB;CACF;AAMD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,GAAG,KAAK,CAe9D;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,KAAK,CAI7F;AAED,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,KAAK,CAI1F;AAED,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,CAGtD;AA+DD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAwBnG;AA2BD,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CA8BlF;AAsBD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,UAAU,GAAG,SAAS,EAC1B,QAAQ,EAAE,cAAc,EACxB,GAAG,EAAE,SAAS,GACb,IAAI,CAwBN;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAExF;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAIzF;AAkFD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAQvF;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,GAAG,MAAM,CAyBtF;AA8BD;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,UAAQ,GAAG,MAAM,CA2E9F"}
1
+ {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../src/gvc/device.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAO,MAAM,kBAAkB,CAAC;AAInD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI/D,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhE,OAAO,EAAE,SAAS,EAAmF,MAAM,UAAU,CAAC;AAuBtH,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAE5F;AAcD,OAAO,QAAQ,UAAU,CAAC;IACxB,UAAU,SAAS;QACjB,0EAA0E;QAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB;CACF;AAMD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,GAAG,KAAK,CAe9D;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,KAAK,CAI7F;AAED,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,KAAK,CAI1F;AAED,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,CAGtD;AA+DD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAwBnG;AA2BD,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CA8BlF;AAsBD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,UAAU,GAAG,SAAS,EAC1B,QAAQ,EAAE,cAAc,EACxB,GAAG,EAAE,SAAS,EACd,UAAU,UAAO,GAChB,IAAI,CA8BN;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAExF;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAIzF;AAkFD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAQvF;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,GAAG,MAAM,CAyBtF;AA8BD;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,UAAQ,GAAG,MAAM,CA2E9F"}
package/dist/index.js CHANGED
@@ -24961,7 +24961,7 @@ function orthoRoundedPolylines(pts, radius) {
24961
24961
  // src/render/svg-graph.ts
24962
24962
  var SVG_XML_DECL = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n';
24963
24963
  var SVG_DOCTYPE = '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"\n "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n';
24964
- var SVG_GENERATOR_COMMENT = "<!-- Generated by graphviz-ts -->\n";
24964
+ var SVG_GENERATOR_COMMENT = "<!-- Generated by @knowvah/dot-engine -->\n";
24965
24965
  var BGCOLOR_TRANSPARENT = "\0transparent";
24966
24966
  function formatG(n) {
24967
24967
  return String(parseFloat(n.toPrecision(6)));
@@ -25863,8 +25863,11 @@ function computeNodeUrlMap(n, obj, ctx) {
25863
25863
  obj.urlMapPts = m.pts.map((p) => mapTransform(p, ctx));
25864
25864
  }
25865
25865
  function computeGraphUrlMap(obj, ctx) {
25866
- const ll = { x: ctx.bb.ll.x - ctx.pad.x, y: ctx.bb.ll.y - ctx.pad.y };
25867
- const ur = { x: ctx.bb.ur.x + ctx.pad.x, y: ctx.bb.ur.y + ctx.pad.y };
25866
+ const ll = { x: -ctx.pad.x, y: -ctx.pad.y };
25867
+ const ur = {
25868
+ x: ctx.bb.ur.x - ctx.bb.ll.x + ctx.pad.x,
25869
+ y: ctx.bb.ur.y - ctx.bb.ll.y + ctx.pad.y
25870
+ };
25868
25871
  obj.urlMapShape = 0 /* Rectangle */;
25869
25872
  obj.urlMapPts = [mapTransform(ll, ctx), mapTransform(ur, ctx)];
25870
25873
  }
@@ -26101,7 +26104,7 @@ function walkNodesAndEdges(g, renderer, job, info) {
26101
26104
 
26102
26105
  // src/gvc/device.ts
26103
26106
  function renderClusterLabel(sg, renderer, job) {
26104
- renderOneLabel(sg.info.label, renderer, job);
26107
+ renderOneLabel(sg.info.label, renderer, job, false);
26105
26108
  }
26106
26109
  function transformPoint(p, job) {
26107
26110
  if ((job.flags & GVRENDER_DOES_TRANSFORM) !== 0) {
@@ -26208,8 +26211,9 @@ function labelSpanX(lp, just) {
26208
26211
  if (just === "r") return lp.pos.x + lp.space.x / 2;
26209
26212
  return lp.pos.x;
26210
26213
  }
26211
- function renderOneLabel(lp, renderer, job) {
26212
- if (!lp?.set) return;
26214
+ function renderOneLabel(lp, renderer, job, requireSet = true) {
26215
+ if (!lp) return;
26216
+ if (requireSet && !lp.set) return;
26213
26217
  if (lp.html) {
26214
26218
  if (lp.u.kind === "html") {
26215
26219
  const html = lp.u.html;
@@ -26232,7 +26236,7 @@ function renderNodeXLabel(n, renderer, job) {
26232
26236
  }
26233
26237
  function renderGraphLabel(g, renderer, job) {
26234
26238
  setHtmlAnchorObj(svgGraphId(g, job), labelTextOf2(g.info.label), job.obj ?? void 0);
26235
- renderOneLabel(g.info.label, renderer, job);
26239
+ renderOneLabel(g.info.label, renderer, job, false);
26236
26240
  }
26237
26241
  function renderClusterBox(sg, filled, renderer, job) {
26238
26242
  const { ll, ur } = sg.info.bb;
@@ -26357,7 +26361,7 @@ function adviseHostFaithful() {
26357
26361
  if (process.env?.GV_FONT_QUIET || !process.stderr?.isTTY) return;
26358
26362
  adviceShown = true;
26359
26363
  process.stderr.write(
26360
- "graphviz-ts: measuring text with built-in metrics (kerning/shaping not applied). For host-faithful sizing matching the rendering font, install `canvas` and call setTextMeasurer(new CanvasTextMeasurer(createCanvas(0,0).getContext('2d'))). Silence with GV_FONT_QUIET=1.\n"
26364
+ "@knowvah/dot-engine: measuring text with built-in metrics (kerning/shaping not applied). For host-faithful sizing matching the rendering font, install `canvas` and call setTextMeasurer(new CanvasTextMeasurer(createCanvas(0,0).getContext('2d'))). Silence with GV_FONT_QUIET=1.\n"
26361
26365
  );
26362
26366
  }
26363
26367
  function createMeasurer() {
@@ -39022,8 +39026,9 @@ function neatoInitNode(n, dim = DFLT_DIM) {
39022
39026
  n.info.pos = pos;
39023
39027
  }
39024
39028
  if (n.info.UF_size === void 0) n.info.UF_size = 1;
39025
- if (!n.info.width) n.info.width = 0.75;
39026
- if (!n.info.height) n.info.height = 0.5;
39029
+ const plainShaped = n.info.shape?.name === "plain";
39030
+ if (!n.info.width && !plainShaped) n.info.width = 0.75;
39031
+ if (!n.info.height && !plainShaped) n.info.height = 0.5;
39027
39032
  }
39028
39033
  function userPos(n) {
39029
39034
  const p = n.attrs.get("pos");
@@ -45623,8 +45628,9 @@ function makeRdata(INF) {
45623
45628
  }
45624
45629
  function twopiInitNode(n) {
45625
45630
  if (!n.info.pos || n.info.pos.length < 2) n.info.pos = [0, 0];
45626
- if (!n.info.width) n.info.width = 0.75;
45627
- if (!n.info.height) n.info.height = 0.5;
45631
+ const plainShaped = n.info.shape?.name === "plain";
45632
+ if (!n.info.width && !plainShaped) n.info.width = 0.75;
45633
+ if (!n.info.height && !plainShaped) n.info.height = 0.5;
45628
45634
  }
45629
45635
  function twopiInitEdge(e) {
45630
45636
  const wt = e.attrs.get("weight");
@@ -52097,73 +52103,253 @@ function createJsonRenderer() {
52097
52103
 
52098
52104
  // src/render/map.ts
52099
52105
  var DQ = '"';
52106
+ function exactDecimalDigits2(v) {
52107
+ const dv = new DataView(new ArrayBuffer(8));
52108
+ dv.setFloat64(0, Math.abs(v));
52109
+ const bits = dv.getBigUint64(0);
52110
+ const expBits = Number(bits >> 52n & 0x7ffn);
52111
+ const mant = bits & 0xfffffffffffffn;
52112
+ const m = expBits === 0 ? mant : mant | 1n << 52n;
52113
+ const e = (expBits === 0 ? 1 : expBits) - 1075;
52114
+ let intDigits;
52115
+ let fracLen = 0;
52116
+ if (e >= 0) {
52117
+ intDigits = (m << BigInt(e)).toString();
52118
+ } else {
52119
+ intDigits = (m * 5n ** BigInt(-e)).toString();
52120
+ fracLen = -e;
52121
+ }
52122
+ if (intDigits.length <= fracLen) {
52123
+ intDigits = "0".repeat(fracLen - intDigits.length + 1) + intDigits;
52124
+ }
52125
+ const pointPos = intDigits.length - fracLen;
52126
+ const firstSig = intDigits.search(/[1-9]/);
52127
+ return { digits: intDigits.slice(firstSig), exp10: pointPos - firstSig - 1 };
52128
+ }
52100
52129
  function printG5(v) {
52101
- const s = v.toPrecision(5);
52102
- if (s.includes(".") && !s.includes("e")) {
52103
- return s.replace(/\.?0+$/, "");
52130
+ if (v === 0 || !Number.isFinite(v)) return String(v);
52131
+ const P = 5;
52132
+ const { digits, exp10 } = exactDecimalDigits2(v);
52133
+ let sig = digits.slice(0, P);
52134
+ if (sig.length < P) sig += "0".repeat(P - sig.length);
52135
+ const rest = digits.slice(P);
52136
+ const restNonzeroAfterFirst = /[1-9]/.test(rest.slice(1));
52137
+ const roundUp = rest.length > 0 && (rest[0] > "5" || rest[0] === "5" && restNonzeroAfterFirst || rest[0] === "5" && !restNonzeroAfterFirst && (sig.charCodeAt(P - 1) - 48) % 2 === 1);
52138
+ let exp = exp10;
52139
+ if (roundUp) {
52140
+ const n = String(BigInt(sig) + 1n);
52141
+ sig = n.length > P ? (exp++, n.slice(0, P)) : n;
52104
52142
  }
52105
- return s;
52143
+ const sign2 = v < 0 ? "-" : "";
52144
+ if (exp < -4 || exp >= P) {
52145
+ const mant = (sig[0] + "." + sig.slice(1)).replace(/\.?0+$/, "");
52146
+ const as = Math.abs(exp);
52147
+ return sign2 + mant + "e" + (exp < 0 ? "-" : "+") + (as < 10 ? "0" : "") + String(as);
52148
+ }
52149
+ let s;
52150
+ if (exp >= sig.length - 1) {
52151
+ s = sig + "0".repeat(exp - sig.length + 1);
52152
+ } else if (exp >= 0) {
52153
+ s = sig.slice(0, exp + 1) + "." + sig.slice(exp + 1);
52154
+ } else {
52155
+ s = "0." + "0".repeat(-exp - 1) + sig;
52156
+ }
52157
+ if (s.includes(".")) s = s.replace(/\.?0+$/, "");
52158
+ return sign2 + s;
52106
52159
  }
52107
52160
  function plainCoord(v) {
52108
52161
  return printG5(v / 72);
52109
52162
  }
52110
- function plainNodeFill(n) {
52111
- const color = n.attrs.get("color") ?? "black";
52112
- return n.attrs.get("fillcolor") || color || "lightgrey";
52163
+ var CANON_KEYWORDS = ["node", "edge", "strict", "graph", "digraph", "subgraph"];
52164
+ var MAX_OUTPUTLINE = 128;
52165
+ function isDigitByte(b) {
52166
+ return b >= 48 && b <= 57;
52167
+ }
52168
+ function isAlnumByte(b) {
52169
+ return isDigitByte(b) || b >= 65 && b <= 90 || b >= 97 && b <= 122;
52170
+ }
52171
+ function isIdCharByte(b) {
52172
+ return isAlnumByte(b) || b === 46 || b === 45 || b >= 128;
52113
52173
  }
52114
- function plainNodeAttrs(n) {
52174
+ function isEscapeAt(bytes, i) {
52175
+ if (bytes[i] !== 92) return false;
52176
+ const c = bytes[i + 1];
52177
+ return c !== void 0 && 'EGHLNTlnr\\"'.includes(String.fromCharCode(c));
52178
+ }
52179
+ function agstrcanonText(arg) {
52180
+ if (arg.length === 0) return '""';
52181
+ const bytes = new TextEncoder().encode(arg);
52182
+ const out = [34];
52183
+ let needsQuotes = false;
52184
+ let partOfEscape = false;
52185
+ let backslashPending = false;
52186
+ let cnt = 0;
52187
+ let dotcnt = 0;
52188
+ let maybeNum = isDigitByte(bytes[0]) || bytes[0] === 46 || bytes[0] === 45;
52189
+ for (let i = 0; i < bytes.length; i++) {
52190
+ const uc = bytes[i];
52191
+ if (uc === 34 && !partOfEscape) {
52192
+ out.push(92);
52193
+ needsQuotes = true;
52194
+ } else if (!partOfEscape && isEscapeAt(bytes, i)) {
52195
+ needsQuotes = true;
52196
+ partOfEscape = true;
52197
+ } else if (maybeNum) {
52198
+ if (uc === 45) {
52199
+ if (cnt) {
52200
+ maybeNum = false;
52201
+ needsQuotes = true;
52202
+ }
52203
+ } else if (uc === 46) {
52204
+ if (dotcnt++) {
52205
+ maybeNum = false;
52206
+ needsQuotes = true;
52207
+ }
52208
+ } else if (!isDigitByte(uc)) {
52209
+ maybeNum = false;
52210
+ needsQuotes = true;
52211
+ }
52212
+ partOfEscape = false;
52213
+ } else if (!(isAlnumByte(uc) || uc === 95 || uc >= 128)) {
52214
+ needsQuotes = true;
52215
+ partOfEscape = false;
52216
+ } else {
52217
+ partOfEscape = false;
52218
+ }
52219
+ out.push(uc);
52220
+ cnt++;
52221
+ const next = bytes[i + 1];
52222
+ if (next !== void 0) {
52223
+ const last = out[out.length - 1];
52224
+ const canBreak = !(isIdCharByte(last) || last === 92) && isIdCharByte(next);
52225
+ if (backslashPending && canBreak) {
52226
+ out.push(92, 10);
52227
+ needsQuotes = true;
52228
+ backslashPending = false;
52229
+ cnt = 0;
52230
+ } else if (cnt >= MAX_OUTPUTLINE) {
52231
+ if (canBreak) {
52232
+ out.push(92, 10);
52233
+ needsQuotes = true;
52234
+ cnt = 0;
52235
+ } else {
52236
+ backslashPending = true;
52237
+ }
52238
+ }
52239
+ }
52240
+ }
52241
+ out.push(34);
52242
+ const first = bytes[0];
52243
+ if (needsQuotes || cnt === 1 && (first === 46 || first === 45)) {
52244
+ return new TextDecoder().decode(new Uint8Array(out));
52245
+ }
52246
+ const lower = arg.toLowerCase();
52247
+ for (const tok of CANON_KEYWORDS) {
52248
+ if (tok === lower) return new TextDecoder().decode(new Uint8Array(out));
52249
+ }
52250
+ return arg;
52251
+ }
52252
+ function lateNN(v, def) {
52253
+ return v !== void 0 && v !== "" ? v : def;
52254
+ }
52255
+ function plainNodeFill(n, g) {
52256
+ const fillcolor = lateNN(nodeAttr(n, g, "fillcolor"), "");
52257
+ if (fillcolor !== "") return fillcolor;
52258
+ return lateNN(nodeAttr(n, g, "color"), "lightgrey");
52259
+ }
52260
+ function plainNodeLabel(n, g) {
52261
+ const lbl = n.info.label;
52262
+ const attr2 = nodeAttr(n, g, "label");
52263
+ if (lbl !== void 0 && lbl.u.kind === "html") {
52264
+ const a = attr2 ?? "";
52265
+ return "<" + (isHtmlValue(a) ? htmlValueContent(a) : a) + ">";
52266
+ }
52267
+ if (attr2 !== void 0 && isHtmlValue(attr2) && lbl !== void 0 && lbl.u.kind === "txt") {
52268
+ return agstrcanonText(htmlValueContent(attr2));
52269
+ }
52270
+ const shape = n.info.shape;
52271
+ if (shape !== void 0 && shape.kind === 2 /* SH_RECORD */) {
52272
+ return agstrcanonText(nodeAttr(n, g, "label") ?? "\\N");
52273
+ }
52274
+ const text = lbl !== void 0 ? lbl.text : n.attrs.get("label") ?? n.name;
52275
+ return agstrcanonText(text);
52276
+ }
52277
+ function plainNodeAttrs(n, g) {
52278
+ const shapeAttr = lateNN(nodeAttr(n, g, "shape"), "ellipse");
52279
+ const shapefile = nodeAttr(n, g, "shapefile");
52280
+ const shapeName = shapefile !== void 0 && shapefile !== "" && shapeAttr !== "epsf" ? "custom" : shapeAttr;
52115
52281
  return {
52116
- label: n.attrs.get("label") ?? n.name,
52117
- style: n.attrs.get("style") ?? "solid",
52118
- shape: n.attrs.get("shape") ?? "ellipse",
52119
- color: n.attrs.get("color") ?? "black",
52120
- fill: plainNodeFill(n)
52282
+ label: plainNodeLabel(n, g),
52283
+ style: lateNN(nodeAttr(n, g, "style"), "solid"),
52284
+ shape: shapeName,
52285
+ color: lateNN(nodeAttr(n, g, "color"), "black"),
52286
+ fill: plainNodeFill(n, g)
52121
52287
  };
52122
52288
  }
52123
- function writePlainNode(n, out) {
52289
+ function writePlainNode(n, g, out) {
52124
52290
  const x = plainCoord(n.info.coord.x);
52125
52291
  const y = plainCoord(n.info.coord.y);
52126
52292
  const w = printG5(n.info.width);
52127
52293
  const h = printG5(n.info.height);
52128
- const a = plainNodeAttrs(n);
52129
- out.push("node " + n.name + " " + x + " " + y + " " + w + " " + h + " " + a.label + " " + a.style + " " + a.shape + " " + a.color + " " + a.fill + "\n");
52294
+ const a = plainNodeAttrs(n, g);
52295
+ out.push("node " + agstrcanonText(n.name) + " " + x + " " + y + " " + w + " " + h + " " + a.label + " " + a.style + " " + a.shape + " " + a.color + " " + a.fill + "\n");
52130
52296
  }
52131
52297
  function collectSplinePts(e) {
52132
52298
  if (!e.info.spl) return [];
52133
52299
  const pts = [];
52134
52300
  for (const bz of e.info.spl.list) {
52135
- for (const pt of bz.list) pts.push(pt);
52301
+ for (let i = 0; i < bz.size; i++) pts.push(bz.list[i]);
52136
52302
  }
52137
52303
  return pts;
52138
52304
  }
52139
- function portSuffix(name) {
52140
- return name ? ":" + name : "";
52305
+ function writeNodeAndPort(n, portname, out) {
52306
+ let name = n.name;
52307
+ if (n.info.clustnode) {
52308
+ const i = name.indexOf(":");
52309
+ if (i >= 0) name = name.slice(i + 1);
52310
+ }
52311
+ out.push(" " + agstrcanonText(name));
52312
+ if (portname !== "") out.push(":" + agstrcanonText(portname));
52141
52313
  }
52142
52314
  function writePlainEdgeHead(e, tport, hport, pts, out) {
52143
- out.push("edge " + e.tail.name + tport + " " + e.head.name + hport + " " + String(pts.length));
52315
+ out.push("edge");
52316
+ writeNodeAndPort(e.tail, tport, out);
52317
+ writeNodeAndPort(e.head, hport, out);
52318
+ out.push(" " + String(pts.length));
52144
52319
  for (const pt of pts) {
52145
52320
  out.push(" " + plainCoord(pt.x) + " " + plainCoord(pt.y));
52146
52321
  }
52147
52322
  }
52148
52323
  function writePlainEdge(e, extend, out) {
52149
- const tport = extend ? portSuffix(e.info.tail_port.name) : "";
52150
- const hport = extend ? portSuffix(e.info.head_port.name) : "";
52324
+ const tport = extend ? e.attrs.get("tailport") ?? "" : "";
52325
+ const hport = extend ? e.attrs.get("headport") ?? "" : "";
52151
52326
  const pts = collectSplinePts(e);
52152
52327
  if (pts.length > 0) writePlainEdgeHead(e, tport, hport, pts, out);
52153
- const style = e.attrs.get("style") ?? "solid";
52154
- const color = e.attrs.get("color") ?? "black";
52328
+ const lbl = e.info.label;
52329
+ if (lbl !== void 0) {
52330
+ out.push(" " + agstrcanonText(lbl.text) + " " + plainCoord(lbl.pos.x) + " " + plainCoord(lbl.pos.y));
52331
+ }
52332
+ const style = lateNN(e.attrs.get("style"), "solid");
52333
+ const color = lateNN(e.attrs.get("color"), "black");
52155
52334
  out.push(" " + style + " " + color + "\n");
52156
52335
  }
52157
52336
  function writePlain(g, job, extend) {
52158
52337
  const w = plainCoord(g.info.bb.ur.x);
52159
52338
  const h = plainCoord(g.info.bb.ur.y);
52160
- job.write("graph " + printG5(job.zoom) + " " + w + " " + h + "\n");
52161
- for (const [, n] of g.nodes) {
52339
+ const zoom = initJobViewportZoom(
52340
+ job.bb,
52341
+ parseDrawingSize(g.attrs.get("size")),
52342
+ { x: 0, y: 0 }
52343
+ );
52344
+ job.write("graph " + printG5(zoom) + " " + w + " " + h + "\n");
52345
+ const nodes = nodesInSeq(g);
52346
+ for (const n of nodes) {
52347
+ if (n.info.clustnode) continue;
52162
52348
  const buf = [];
52163
- writePlainNode(n, buf);
52349
+ writePlainNode(n, g, buf);
52164
52350
  job.write(buf.join(""));
52165
52351
  }
52166
- for (const [, n] of g.nodes) {
52352
+ for (const n of nodes) {
52167
52353
  for (const e of n.outEdges(g)) {
52168
52354
  const buf = [];
52169
52355
  writePlainEdge(e, extend, buf);