@knowvah/dot-engine 1.2.7 → 1.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knowvah/dot-engine",
3
- "version": "1.2.7",
3
+ "version": "1.3.0",
4
4
  "description": "Faithful TypeScript port of Graphviz (dot, neato, fdp, sfdp, circo, twopi, osage, patchwork) — no C: no native binary, no WASM. Oracle-verified against the C implementation, runs in the browser.",
5
5
  "keywords": [
6
6
  "graphviz",
@@ -33,6 +33,7 @@
33
33
  import type { Graph } from '../model/graph.js';
34
34
  import type { Node } from '../model/node.js';
35
35
  import type { Edge } from '../model/edge.js';
36
+ import type { TextlabelT } from '../common/types.js';
36
37
  import { RenderError } from '../errors.js';
37
38
 
38
39
  // ---------------------------------------------------------------------------
@@ -98,7 +99,14 @@ export interface NodeGeometry {
98
99
  * in order. An edge with no routed spline produces an empty `points` array.
99
100
  * `label` is present only when the edge carries a centre label.
100
101
  *
101
- * @see lib/common/types.h:ED_spl, ED_label
102
+ * `tailLabel`/`headLabel` are the `taillabel`/`headlabel` port labels. They
103
+ * are present only once the layout has actually *placed* them (C `lp->set`),
104
+ * which is the same gate `render()` applies before emitting the `<text>`:
105
+ * a declared port label that place_portlabel skipped (no spline, IGNORED edge
106
+ * type) still holds calloc-zero coordinates, so it is reported as absent
107
+ * rather than as a label at the origin.
108
+ *
109
+ * @see lib/common/types.h:ED_spl, ED_label, ED_tail_label, ED_head_label
102
110
  */
103
111
  export interface EdgeGeometry {
104
112
  tail: string;
@@ -107,6 +115,16 @@ export interface EdgeGeometry {
107
115
  points: { x: number; y: number }[];
108
116
  /** Centre edge label position, if present. @see lib/common/types.h:ED_label */
109
117
  label?: { x: number; y: number };
118
+ /**
119
+ * `taillabel` position, if placed.
120
+ * @see lib/common/types.h:ED_tail_label
121
+ */
122
+ tailLabel?: { x: number; y: number };
123
+ /**
124
+ * `headlabel` position, if placed.
125
+ * @see lib/common/types.h:ED_head_label
126
+ */
127
+ headLabel?: { x: number; y: number };
110
128
  }
111
129
 
112
130
  /**
@@ -203,9 +221,26 @@ function collectEdgePoints(
203
221
  return pts;
204
222
  }
205
223
 
224
+ /**
225
+ * Position of a port label that layout actually placed, else undefined.
226
+ * `set` is C's own "this label has coordinates" flag, and the gate
227
+ * emit_edge_label uses before drawing; an unplaced label still holds the
228
+ * calloc-zero pos and must not be published as geometry.
229
+ * @see lib/common/splines.c:place_portlabel (l->set = TRUE)
230
+ * @see lib/common/emit.c:emit_edge_label (lbl == NULL || !lbl->set)
231
+ */
232
+ function placedLabelPos(
233
+ lbl: TextlabelT | undefined,
234
+ flipY: (y: number) => number,
235
+ ): { x: number; y: number } | undefined {
236
+ if (lbl === undefined || !lbl.set) return undefined;
237
+ return { x: lbl.pos.x, y: flipY(lbl.pos.y) };
238
+ }
239
+
206
240
  /**
207
241
  * Snapshot one edge's geometry.
208
- * @see lib/common/types.h:ED_spl, ED_label (textlabel_t.pos)
242
+ * @see lib/common/types.h:ED_spl, ED_label, ED_tail_label, ED_head_label
243
+ * (textlabel_t.pos)
209
244
  */
210
245
  function snapshotEdge(edge: Edge, flipY: (y: number) => number): EdgeGeometry {
211
246
  const geom: EdgeGeometry = {
@@ -217,6 +252,10 @@ function snapshotEdge(edge: Edge, flipY: (y: number) => number): EdgeGeometry {
217
252
  if (lbl !== undefined) {
218
253
  geom.label = { x: lbl.pos.x, y: flipY(lbl.pos.y) };
219
254
  }
255
+ const tailLabel = placedLabelPos(edge.info.tail_label, flipY);
256
+ if (tailLabel !== undefined) geom.tailLabel = tailLabel;
257
+ const headLabel = placedLabelPos(edge.info.head_label, flipY);
258
+ if (headLabel !== undefined) geom.headLabel = headLabel;
220
259
  return geom;
221
260
  }
222
261