@knowvah/dot-engine 2.6.8 → 2.6.9
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/subst.d.ts +8 -0
- package/dist/common/subst.d.ts.map +1 -1
- package/dist/gvc/anchor.d.ts.map +1 -1
- package/dist/index.js +134 -21
- package/dist/index.js.map +3 -3
- package/dist/render/xml-escape.d.ts +8 -6
- package/dist/render/xml-escape.d.ts.map +1 -1
- package/dist/render.js +134 -21
- package/dist/render.js.map +3 -3
- package/package.json +1 -1
- package/src/common/poly-gencode.ts +2 -2
- package/src/common/subst.ts +12 -0
- package/src/gvc/anchor.ts +6 -5
- package/src/render/xml-escape.ts +23 -33
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knowvah/dot-engine",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.9",
|
|
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",
|
|
@@ -22,7 +22,7 @@ import { FillType } from '../gvc/context.js';
|
|
|
22
22
|
import { emitHtmlLabel } from './htmltable-emit.js';
|
|
23
23
|
import { transformPoint } from '../gvc/device.js';
|
|
24
24
|
import { nodeAttr } from './poly-init.js';
|
|
25
|
-
import { substObjAnchor,
|
|
25
|
+
import { substObjAnchor, preprocessTooltip } from './subst.js';
|
|
26
26
|
import type { ResolvedFill, PolyStyleFlags } from './style-resolve.js';
|
|
27
27
|
import {
|
|
28
28
|
parseStyleFlags,
|
|
@@ -245,7 +245,7 @@ function anchorAttr(n: Node, key: string): string | undefined {
|
|
|
245
245
|
|
|
246
246
|
/** Resolve tooltip string: explicit attr, or fall back to label text. */
|
|
247
247
|
function resolveTooltip(n: Node, tooltip: string | undefined): string {
|
|
248
|
-
if (tooltip !== undefined) return substObjAnchor(
|
|
248
|
+
if (tooltip !== undefined) return substObjAnchor(preprocessTooltip(tooltip), n);
|
|
249
249
|
const label = n.info.label as TextlabelT | undefined;
|
|
250
250
|
return label?.text ?? '';
|
|
251
251
|
}
|
package/src/common/subst.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { Node } from '../model/node.js';
|
|
|
14
14
|
import { Edge } from '../model/edge.js';
|
|
15
15
|
import { Graph } from '../model/graph.js';
|
|
16
16
|
import type { TextlabelT } from './types.js';
|
|
17
|
+
import { htmlEntityUTF8 } from './html-entities.js';
|
|
17
18
|
|
|
18
19
|
export type GraphObj = Node | Edge | Graph;
|
|
19
20
|
|
|
@@ -124,3 +125,14 @@ export function interpretCRNL(str: string): string {
|
|
|
124
125
|
}
|
|
125
126
|
return out;
|
|
126
127
|
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Tooltip preprocessing: decode HTML entities to UTF-8, then interpret
|
|
131
|
+
* \n \l \r. C picks latin1ToUTF8 or htmlEntityUTF8 by GD_charset; both decode
|
|
132
|
+
* entities via htmlEntity, and the port's Latin-1 bytes are already decoded
|
|
133
|
+
* at input, so one branch serves both (as in make_label).
|
|
134
|
+
* @see lib/common/emit.c:preprocessTooltip
|
|
135
|
+
*/
|
|
136
|
+
export function preprocessTooltip(s: string): string {
|
|
137
|
+
return interpretCRNL(htmlEntityUTF8(s));
|
|
138
|
+
}
|
package/src/gvc/anchor.ts
CHANGED
|
@@ -17,7 +17,7 @@ import type { Node } from '../model/node.js';
|
|
|
17
17
|
import type { Point, Box, Spline, Bezier } from '../model/geom.js';
|
|
18
18
|
import type { TextlabelT, PolygonT } from '../common/types.js';
|
|
19
19
|
import type { GraphObj } from '../common/subst.js';
|
|
20
|
-
import { substObjAnchor,
|
|
20
|
+
import { substObjAnchor, preprocessTooltip } from '../common/subst.js';
|
|
21
21
|
import { parseStyleFlags } from '../common/style-resolve.js';
|
|
22
22
|
import { nodeAttr } from '../common/poly-init.js';
|
|
23
23
|
import { bezier } from '../common/bezier.js';
|
|
@@ -36,12 +36,13 @@ function subst(s: string, obj: GraphObj): string {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
* preprocessTooltip + strdup_and_subst_obj:
|
|
40
|
-
* object substitution — matching the node tooltip path
|
|
39
|
+
* preprocessTooltip + strdup_and_subst_obj: decode entities and interpret
|
|
40
|
+
* \n\l\r escapes, then object substitution — matching the node tooltip path
|
|
41
|
+
* (poly-gencode.ts).
|
|
41
42
|
* @see lib/common/emit.c:preprocessTooltip
|
|
42
43
|
*/
|
|
43
44
|
function tip(s: string, obj: GraphObj): string {
|
|
44
|
-
return substObjAnchor(
|
|
45
|
+
return substObjAnchor(preprocessTooltip(s), obj);
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
/** Label text of a textlabel, or null. @see device.ts:labelTextOf */
|
|
@@ -71,7 +72,7 @@ function pickEdge(e: Edge, keys: string[]): Picked {
|
|
|
71
72
|
return pickFirst(e.attrs, keys, (s) => subst(s, e));
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
/** pickFirst with tooltip preprocessing (
|
|
75
|
+
/** pickFirst with tooltip preprocessing (preprocessTooltip + subst). */
|
|
75
76
|
function pickEdgeTip(e: Edge, keys: string[]): Picked {
|
|
76
77
|
return pickFirst(e.attrs, keys, (s) => tip(s, e));
|
|
77
78
|
}
|
package/src/render/xml-escape.ts
CHANGED
|
@@ -1,29 +1,25 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EPL-2.0
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
3
|
+
// The SVG renderer's three gv_xml_escape flag sets (lib/util/xml.c), as presets
|
|
4
|
+
// over the faithful port in util/xml.ts. '<', '>', '"' and "'" are always
|
|
5
|
+
// escaped; '&' is escaped only when it does not begin an entity
|
|
6
|
+
// (xml_isentity), except under raw, which escapes every '&'.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
import { gvXmlEscape, type XmlFlags } from '../util/xml.js';
|
|
9
|
+
|
|
10
|
+
/** flags {0}. @see plugin/core/gvrender_core_svg.c:svg_begin_anchor (href) */
|
|
11
|
+
const FLAGS_BASE: XmlFlags = { raw: false, dash: false, nbsp: false, utf8: false };
|
|
12
|
+
/** gvputs_xml's flags. @see lib/gvc/gvdevice.c:gvputs_xml */
|
|
13
|
+
const FLAGS_TITLE: XmlFlags = { raw: false, dash: true, nbsp: true, utf8: false };
|
|
14
|
+
/** @see plugin/core/gvrender_core_svg.c:svg_textspan, svg_begin_anchor (tooltip) */
|
|
15
|
+
const FLAGS_TEXT: XmlFlags = { raw: true, dash: true, nbsp: true, utf8: false };
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
|
-
* Base XML escape (gv_xml_escape with flags {0}): ids,
|
|
18
|
-
* @see lib/util/xml.c
|
|
18
|
+
* Base XML escape (gv_xml_escape with flags {0}): ids, hrefs.
|
|
19
|
+
* @see lib/util/xml.c:gv_xml_escape
|
|
19
20
|
*/
|
|
20
21
|
export function escapeXml(s: string): string {
|
|
21
|
-
|
|
22
|
-
r = r.replace(/</g, '<');
|
|
23
|
-
r = r.replace(/>/g, '>');
|
|
24
|
-
r = r.replace(RE_DQUOTE, '"');
|
|
25
|
-
r = r.replace(RE_SQUOTE, ''');
|
|
26
|
-
return r;
|
|
22
|
+
return gvXmlEscape(s, FLAGS_BASE);
|
|
27
23
|
}
|
|
28
24
|
|
|
29
25
|
/**
|
|
@@ -34,23 +30,17 @@ export function escapeXml(s: string): string {
|
|
|
34
30
|
* @see lib/gvc/gvdevice.c:gvputs_xml, lib/util/xml.c:xml_core
|
|
35
31
|
*/
|
|
36
32
|
export function escapeXmlTitle(s: string): string {
|
|
37
|
-
|
|
38
|
-
r = r.replace(/-/g, '-');
|
|
39
|
-
r = r.replace(/ {2,}/g, (m) => ' ' + ' '.repeat(m.length - 1));
|
|
40
|
-
return r;
|
|
33
|
+
return gvXmlEscape(s, FLAGS_TITLE);
|
|
41
34
|
}
|
|
42
35
|
|
|
43
36
|
/**
|
|
44
|
-
* Text/tooltip XML escape (gv_xml_escape with flags {raw, dash, nbsp}):
|
|
45
|
-
*
|
|
46
|
-
* spaces→ . Used for
|
|
47
|
-
*
|
|
37
|
+
* Text/tooltip XML escape (gv_xml_escape with flags {raw, dash, nbsp}): raw
|
|
38
|
+
* escapes every '&' -- entity-looking or not -- and newline/CR to
|
|
39
|
+
* / ; also '-'→- and 2nd+ consecutive spaces→ . Used for
|
|
40
|
+
* textspans and xlink:title.
|
|
41
|
+
* @see plugin/core/gvrender_core_svg.c:svg_textspan, svg_begin_anchor
|
|
42
|
+
* @see lib/util/xml.c:xml_core (`flags.raw || !xml_isentity(s)`)
|
|
48
43
|
*/
|
|
49
44
|
export function escapeXmlText(s: string): string {
|
|
50
|
-
|
|
51
|
-
r = r.replace(/-/g, '-');
|
|
52
|
-
r = r.replace(/\n/g, ' ');
|
|
53
|
-
r = r.replace(/\r/g, ' ');
|
|
54
|
-
r = r.replace(/ {2,}/g, (m) => ' ' + ' '.repeat(m.length - 1));
|
|
55
|
-
return r;
|
|
45
|
+
return gvXmlEscape(s, FLAGS_TEXT);
|
|
56
46
|
}
|