@knowvah/dot-engine 2.7.0 → 2.7.1
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/dist/common/attr-get.d.ts +30 -0
- package/dist/common/attr-get.d.ts.map +1 -0
- package/dist/common/make-label.d.ts.map +1 -1
- package/dist/common/poly-init.d.ts +2 -12
- package/dist/common/poly-init.d.ts.map +1 -1
- package/dist/index.js +18 -11
- package/dist/index.js.map +3 -3
- package/dist/layout/dot/graph-label.d.ts.map +1 -1
- package/dist/render.js +18 -11
- package/dist/render.js.map +3 -3
- package/package.json +1 -1
- package/src/common/attr-get.ts +46 -0
- package/src/common/make-label.ts +14 -2
- package/src/common/poly-init.ts +4 -18
- package/src/layout/dot/graph-label.ts +1 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knowvah/dot-engine",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.1",
|
|
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",
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EPL-2.0
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Attribute reads with cgraph's `agxget` semantics: an object's own value,
|
|
5
|
+
* else the declared default it was created under. A leaf module (model types
|
|
6
|
+
* only) so label and shape code can share it without an import cycle.
|
|
7
|
+
*
|
|
8
|
+
* @see lib/cgraph/attr.c:agxget
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { Node } from '../model/node.js';
|
|
12
|
+
import type { Graph } from '../model/graph.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Read a node attribute: the node's own value, else the node-attribute defaults
|
|
16
|
+
* (`node [...]`) captured from the node's declaring scope up to root *at the
|
|
17
|
+
* time the node was created*. The snapshot makes a `node [...]` declared after
|
|
18
|
+
* the node — at any scope — correctly not apply, and lets a cluster-scoped
|
|
19
|
+
* default reach nodes declared in that cluster, as the oracle does.
|
|
20
|
+
*
|
|
21
|
+
* Programmatically created nodes have no snapshot; they fall back to the live
|
|
22
|
+
* defaults of the passed graph `g` and root.
|
|
23
|
+
* @see lib/cgraph/attr.c:agxget; src/parser/builder.ts:effectiveNodeDefaults
|
|
24
|
+
*/
|
|
25
|
+
export function nodeAttr(n: Node, g: Graph, key: string): string | undefined {
|
|
26
|
+
const own = n.attrs.get(key);
|
|
27
|
+
if (own !== undefined) return own;
|
|
28
|
+
if (n.nodeDefaultsSnapshot !== undefined) return n.nodeDefaultsSnapshot.get(key);
|
|
29
|
+
return g.nodeDefaults.get(key)
|
|
30
|
+
?? (g !== g.root ? g.root.nodeDefaults.get(key) : undefined);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Read a graph attribute with subgraph→root inheritance, mirroring C's
|
|
35
|
+
* agxget (late_nnstring(sg, agfindgraphattr(sg, key), ...) in do_graph_label):
|
|
36
|
+
* a cluster inherits `fontname`/`fontsize`/`fontcolor` set on an ancestor
|
|
37
|
+
* (e.g. root `graph[fontname=Arial]`) when it sets none of its own.
|
|
38
|
+
* @see lib/common/input.c:do_graph_label
|
|
39
|
+
*/
|
|
40
|
+
export function graphAttrInherited(sg: Graph, key: string): string | undefined {
|
|
41
|
+
// Own value wins; otherwise the ancestor defaults SNAPSHOTTED when this
|
|
42
|
+
// subgraph opened (not a live parent walk) — so an ancestor attribute set
|
|
43
|
+
// later in statement order does not retroactively apply (2184).
|
|
44
|
+
// @see lib/cgraph/graph.c:agsubg (parse-time defval copy)
|
|
45
|
+
return sg.attrs.get(key) ?? sg.graphDefaultsSnapshot?.get(key);
|
|
46
|
+
}
|
package/src/common/make-label.ts
CHANGED
|
@@ -16,6 +16,8 @@ import { makeHtmlLabelTo } from './htmltable-label.js';
|
|
|
16
16
|
import { labelStderr } from './htmltable-attr-warn.js';
|
|
17
17
|
import { substObj, type GraphObj } from './subst.js';
|
|
18
18
|
import { Edge } from '../model/edge.js';
|
|
19
|
+
import { Node } from '../model/node.js';
|
|
20
|
+
import { nodeAttr, graphAttrInherited } from './attr-get.js';
|
|
19
21
|
import { Graph } from '../model/graph.js';
|
|
20
22
|
import { htmlEntityUTF8 } from './html-entities.js';
|
|
21
23
|
|
|
@@ -33,17 +35,27 @@ export { htmlEntityUTF8 };
|
|
|
33
35
|
/**
|
|
34
36
|
* The object's pen color: `pencolor` attr, else `color` attr, else undefined
|
|
35
37
|
* (no default). An HTML table/cell border with no explicit COLOR inherits it.
|
|
38
|
+
* Read as C's agget does, so declared defaults count: a node's `node [...]`
|
|
39
|
+
* snapshot and a subgraph's inherited graph attributes (894589). Edge
|
|
40
|
+
* defaults are already materialized into `attrs` by the builder.
|
|
36
41
|
* @see lib/common/htmltable.c:getPenColor
|
|
37
42
|
*/
|
|
38
43
|
function getPenColor(obj?: GraphObj): string | undefined {
|
|
39
44
|
if (obj === undefined) return undefined;
|
|
40
|
-
const pc = obj
|
|
45
|
+
const pc = aggetObj(obj, 'pencolor');
|
|
41
46
|
if (pc !== undefined && pc !== '') return pc;
|
|
42
|
-
const c = obj
|
|
47
|
+
const c = aggetObj(obj, 'color');
|
|
43
48
|
if (c !== undefined && c !== '') return c;
|
|
44
49
|
return undefined;
|
|
45
50
|
}
|
|
46
51
|
|
|
52
|
+
/** `agget(obj, key)` for any object kind. @see lib/cgraph/attr.c:agxget */
|
|
53
|
+
function aggetObj(obj: GraphObj, key: string): string | undefined {
|
|
54
|
+
if (obj instanceof Node) return nodeAttr(obj, obj.root, key);
|
|
55
|
+
if (obj instanceof Graph) return graphAttrInherited(obj, key);
|
|
56
|
+
return obj.attrs.get(key);
|
|
57
|
+
}
|
|
58
|
+
|
|
47
59
|
/** The root graph owning `obj` (edges resolve through their tail node). */
|
|
48
60
|
function rootOf(obj: GraphObj): Graph {
|
|
49
61
|
return obj instanceof Edge ? obj.tail.root : obj.root;
|
package/src/common/poly-init.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import type { Node } from '../model/node.js';
|
|
11
11
|
import type { Graph } from '../model/graph.js';
|
|
12
12
|
import type { TextMeasurer } from './textmeasure.js';
|
|
13
|
+
import { nodeAttr } from './attr-get.js';
|
|
13
14
|
import type { PolygonT, ShapeDesc } from './types.js';
|
|
14
15
|
import { ShapeKind } from './types.js';
|
|
15
16
|
import type { TextlabelT } from './types.js';
|
|
@@ -32,24 +33,9 @@ const DEFAULT_LW = 27;
|
|
|
32
33
|
const DEFAULT_RW = 27;
|
|
33
34
|
const DEFAULT_HT = 36;
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
* time the node was created*. The snapshot makes a `node [...]` declared after
|
|
39
|
-
* the node — at any scope — correctly not apply, and lets a cluster-scoped
|
|
40
|
-
* default reach nodes declared in that cluster, as the oracle does.
|
|
41
|
-
*
|
|
42
|
-
* Programmatically created nodes have no snapshot; they fall back to the live
|
|
43
|
-
* defaults of the passed graph `g` and root.
|
|
44
|
-
* @see lib/cgraph/attr.c:agxget; src/parser/builder.ts:effectiveNodeDefaults
|
|
45
|
-
*/
|
|
46
|
-
export function nodeAttr(n: Node, g: Graph, key: string): string | undefined {
|
|
47
|
-
const own = n.attrs.get(key);
|
|
48
|
-
if (own !== undefined) return own;
|
|
49
|
-
if (n.nodeDefaultsSnapshot !== undefined) return n.nodeDefaultsSnapshot.get(key);
|
|
50
|
-
return g.nodeDefaults.get(key)
|
|
51
|
-
?? (g !== g.root ? g.root.nodeDefaults.get(key) : undefined);
|
|
52
|
-
}
|
|
36
|
+
// nodeAttr moved to attr-get.ts (leaf module, shared with make-label.ts);
|
|
37
|
+
// re-exported so existing importers are unchanged.
|
|
38
|
+
export { nodeAttr };
|
|
53
39
|
|
|
54
40
|
/** Read label-font attributes from node, falling back to defaults. */
|
|
55
41
|
export function readFontAttrs(n: Node, g: Graph): {
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import type { Graph } from '../../model/graph.js';
|
|
10
10
|
import type { Point } from '../../model/geom.js';
|
|
11
11
|
import type { TextMeasurer } from '../../common/textmeasure.js';
|
|
12
|
+
import { graphAttrInherited } from '../../common/attr-get.js';
|
|
12
13
|
import { makeAnyLabel, DEFAULT_FONTSIZE, DEFAULT_FONTNAME, DEFAULT_COLOR } from '../../common/make-label.js';
|
|
13
14
|
import { isHtmlValue, htmlValueContent } from '../../common/html-string.js';
|
|
14
15
|
import { BOTTOM_IX, TOP_IX, RIGHT_IX, LEFT_IX } from './position-aux.js';
|
|
@@ -45,21 +46,6 @@ function readLabelPos(sg: Graph): number {
|
|
|
45
46
|
return pos;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
/**
|
|
49
|
-
* Read a graph attribute with subgraph→root inheritance, mirroring C's
|
|
50
|
-
* agxget (late_nnstring(sg, agfindgraphattr(sg, key), ...) in do_graph_label):
|
|
51
|
-
* a cluster inherits `fontname`/`fontsize`/`fontcolor` set on an ancestor
|
|
52
|
-
* (e.g. root `graph[fontname=Arial]`) when it sets none of its own.
|
|
53
|
-
* @see lib/common/input.c:do_graph_label
|
|
54
|
-
*/
|
|
55
|
-
function graphAttrInherited(sg: Graph, key: string): string | undefined {
|
|
56
|
-
// Own value wins; otherwise the ancestor defaults SNAPSHOTTED when this
|
|
57
|
-
// subgraph opened (not a live parent walk) — so an ancestor attribute set
|
|
58
|
-
// later in statement order does not retroactively apply (2184).
|
|
59
|
-
// @see lib/cgraph/graph.c:agsubg (parse-time defval copy)
|
|
60
|
-
return sg.attrs.get(key) ?? sg.graphDefaultsSnapshot?.get(key);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
49
|
/**
|
|
64
50
|
* Graph/cluster label font, read through graphAttrInherited.
|
|
65
51
|
* @internal also used by src/async/collect.ts to request the same face.
|