@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.
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Base XML escape (gv_xml_escape with flags {0}): ids, titles, hrefs.
3
- * @see lib/util/xml.c gv_xml_escape / xml_core / xml_isentity
2
+ * Base XML escape (gv_xml_escape with flags {0}): ids, hrefs.
3
+ * @see lib/util/xml.c:gv_xml_escape
4
4
  */
5
5
  export declare function escapeXml(s: string): string;
6
6
  /**
@@ -12,10 +12,12 @@ export declare function escapeXml(s: string): string;
12
12
  */
13
13
  export declare function escapeXmlTitle(s: string): string;
14
14
  /**
15
- * Text/tooltip XML escape (gv_xml_escape with flags {raw, dash, nbsp}):
16
- * additionally escapes '-'→-, newline/CR→
/
, and 2nd+ consecutive
17
- * spaces→ . Used for textspans and tooltips.
18
- * @see plugin/core/gvrender_core_svg.c:546 (svg_textspan flags)
15
+ * Text/tooltip XML escape (gv_xml_escape with flags {raw, dash, nbsp}): raw
16
+ * escapes every '&' -- entity-looking or not -- and newline/CR to
17
+ * 
/
; also '-'→- and 2nd+ consecutive spaces→ . Used for
18
+ * textspans and xlink:title.
19
+ * @see plugin/core/gvrender_core_svg.c:svg_textspan, svg_begin_anchor
20
+ * @see lib/util/xml.c:xml_core (`flags.raw || !xml_isentity(s)`)
19
21
  */
20
22
  export declare function escapeXmlText(s: string): string;
21
23
  //# sourceMappingURL=xml-escape.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"xml-escape.d.ts","sourceRoot":"","sources":["../../src/render/xml-escape.ts"],"names":[],"mappings":"AAeA;;;GAGG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAO3C;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAKhD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAO/C"}
1
+ {"version":3,"file":"xml-escape.d.ts","sourceRoot":"","sources":["../../src/render/xml-escape.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE/C"}
package/dist/render.js CHANGED
@@ -8436,6 +8436,9 @@ function interpretCRNL(str) {
8436
8436
  }
8437
8437
  return out;
8438
8438
  }
8439
+ function preprocessTooltip(s) {
8440
+ return interpretCRNL(htmlEntityUTF8(s));
8441
+ }
8439
8442
 
8440
8443
  // src/model/graphInfo.ts
8441
8444
  function makeGraphInfo() {
@@ -15698,31 +15701,141 @@ function stripedBox(job, pts, clrs, rotate, renderer) {
15698
15701
  return error;
15699
15702
  }
15700
15703
 
15704
+ // src/util/xml.ts
15705
+ function gvXmlEscape(s, flags) {
15706
+ return XmlEscaper.escape(s, flags);
15707
+ }
15708
+ var XmlEscaper = class _XmlEscaper {
15709
+ static escape(s, flags) {
15710
+ let result = "";
15711
+ let previous = "";
15712
+ let pos = 0;
15713
+ while (pos < s.length) {
15714
+ const prev = s[pos];
15715
+ const [fragment, consumed] = _XmlEscaper.core(previous, s, pos, flags);
15716
+ result += fragment;
15717
+ previous = prev;
15718
+ pos += consumed;
15719
+ }
15720
+ return result;
15721
+ }
15722
+ /**
15723
+ * Escape one character/codepoint at s[pos].
15724
+ * Returns [escaped_fragment, characters_consumed].
15725
+ * Delegates to focused helpers to stay within CCN limit.
15726
+ * @see lib/util/xml.c:xml_core
15727
+ */
15728
+ static core(previous, s, pos, flags) {
15729
+ const special = _XmlEscaper.coreSpecial(previous, s, pos, flags);
15730
+ if (special !== null) return special;
15731
+ const code = s.charCodeAt(pos);
15732
+ if (code > 127 && flags.utf8) return _XmlEscaper.utf8Entity(s, pos);
15733
+ return [s[pos], 1];
15734
+ }
15735
+ /**
15736
+ * Handle all the fixed-escape cases (& < > - space " ' \n \r).
15737
+ * Returns null when none of those cases applies.
15738
+ * @see lib/util/xml.c:xml_core
15739
+ */
15740
+ static coreSpecial(previous, s, pos, flags) {
15741
+ const c = s[pos];
15742
+ if (c === "&" && (flags.raw || !_XmlEscaper.isEntity(s, pos))) {
15743
+ return ["&amp;", 1];
15744
+ }
15745
+ if (c === "<") return ["&lt;", 1];
15746
+ if (c === ">") return ["&gt;", 1];
15747
+ if (c === '"') return ["&quot;", 1];
15748
+ if (c === "'") return ["&#39;", 1];
15749
+ if (c === "-" && flags.dash) return ["&#45;", 1];
15750
+ if (c === " " && previous === " " && flags.nbsp) return ["&#160;", 1];
15751
+ if (c === "\n" && flags.raw) return ["&#10;", 1];
15752
+ if (c === "\r" && flags.raw) return ["&#13;", 1];
15753
+ return null;
15754
+ }
15755
+ /**
15756
+ * Return true if s[pos] (which is '&') starts a valid XML entity:
15757
+ * &[A-Za-z]+; e.g. &Ccedil;
15758
+ * &#[0-9]*; e.g. &#38;
15759
+ * &#x[0-9a-fA-F]*; e.g. &#x6C34;
15760
+ * @see lib/util/xml.c:xml_isentity
15761
+ */
15762
+ static isEntity(s, pos) {
15763
+ let i = pos + 1;
15764
+ if (i >= s.length || s[i] === ";") return false;
15765
+ i = s[i] === "#" ? _XmlEscaper.scanNumericRef(s, i) : _XmlEscaper.scanNamedRef(s, i);
15766
+ return i < s.length && s[i] === ";";
15767
+ }
15768
+ /** Scan a numeric entity body starting just after the '#'. */
15769
+ static scanNumericRef(s, hashPos) {
15770
+ let i = hashPos + 1;
15771
+ if (i < s.length && (s[i] === "x" || s[i] === "X")) {
15772
+ i++;
15773
+ while (i < s.length && _XmlEscaper.isXDigit(s[i])) i++;
15774
+ } else {
15775
+ while (i < s.length && _XmlEscaper.isDecDigit(s[i])) i++;
15776
+ }
15777
+ return i;
15778
+ }
15779
+ /** Scan a named entity body (alpha chars after the '&'). */
15780
+ static scanNamedRef(s, start) {
15781
+ let i = start;
15782
+ while (i < s.length && _XmlEscaper.isAlpha(s[i])) i++;
15783
+ return i;
15784
+ }
15785
+ /**
15786
+ * Emit &#xNNNN; for the Unicode code point at s[pos]. JS strings are
15787
+ * UTF-16, so the code point (what C decodes from UTF-8) comes from
15788
+ * codePointAt, and an astral character consumes two units.
15789
+ * @see lib/util/xml.c:xml_core (UTF-8 block)
15790
+ */
15791
+ static utf8Entity(s, pos) {
15792
+ const cp = _XmlEscaper.decodeUtf8(s, pos);
15793
+ const consumed = _XmlEscaper.utf8ByteLen(cp);
15794
+ return [`&#x${cp.toString(16)};`, consumed];
15795
+ }
15796
+ /**
15797
+ * Return the code point at s[pos]. A lone surrogate is the analogue of
15798
+ * malformed UTF-8, where C reports an error and exits (xml.c:135).
15799
+ * @see lib/util/xml.c:xml_core (fprintf + graphviz_exit at xml.c:135)
15800
+ */
15801
+ static decodeUtf8(s, pos) {
15802
+ const cp = s.codePointAt(pos);
15803
+ if (cp >= 55296 && cp <= 57343) {
15804
+ throw new RenderError(`gvXmlEscape: malformed UTF-8 at position ${pos}`, "RENDER_ERROR");
15805
+ }
15806
+ return cp;
15807
+ }
15808
+ /**
15809
+ * Return how many UTF-16 units encode the code point (C: the UTF-8 byte
15810
+ * length from the leading byte).
15811
+ * @see lib/util/xml.c:xml_core (length computation)
15812
+ */
15813
+ static utf8ByteLen(cp) {
15814
+ return cp > 65535 ? 2 : 1;
15815
+ }
15816
+ static isDecDigit(c) {
15817
+ return c >= "0" && c <= "9";
15818
+ }
15819
+ static isAlpha(c) {
15820
+ return c >= "a" && c <= "z" || c >= "A" && c <= "Z";
15821
+ }
15822
+ static isXDigit(c) {
15823
+ return _XmlEscaper.isDecDigit(c) || c >= "a" && c <= "f" || c >= "A" && c <= "F";
15824
+ }
15825
+ };
15826
+
15701
15827
  // src/render/xml-escape.ts
15702
- var RE_DQUOTE = new RegExp('"', "g");
15703
- var RE_SQUOTE = new RegExp("'", "g");
15704
- var RE_AMP_NONENTITY = /&(?![A-Za-z]+;|#[0-9]+;|#x[0-9A-Fa-f]+;)/g;
15828
+ var FLAGS_BASE = { raw: false, dash: false, nbsp: false, utf8: false };
15829
+ var FLAGS_TITLE = { raw: false, dash: true, nbsp: true, utf8: false };
15830
+ var FLAGS_TEXT = { raw: true, dash: true, nbsp: true, utf8: false };
15705
15831
  function escapeXml(s) {
15706
- let r = s.replace(RE_AMP_NONENTITY, "&amp;");
15707
- r = r.replace(/</g, "&lt;");
15708
- r = r.replace(/>/g, "&gt;");
15709
- r = r.replace(RE_DQUOTE, "&quot;");
15710
- r = r.replace(RE_SQUOTE, "&#39;");
15711
- return r;
15832
+ return gvXmlEscape(s, FLAGS_BASE);
15712
15833
  }
15713
15834
  function escapeXmlTitle(s) {
15714
- let r = escapeXml(s);
15715
- r = r.replace(/-/g, "&#45;");
15716
- r = r.replace(/ {2,}/g, (m) => " " + "&#160;".repeat(m.length - 1));
15717
- return r;
15835
+ return gvXmlEscape(s, FLAGS_TITLE);
15718
15836
  }
15719
15837
  function escapeXmlText(s) {
15720
- let r = escapeXml(s);
15721
- r = r.replace(/-/g, "&#45;");
15722
- r = r.replace(/\n/g, "&#10;");
15723
- r = r.replace(/\r/g, "&#13;");
15724
- r = r.replace(/ {2,}/g, (m) => " " + "&#160;".repeat(m.length - 1));
15725
- return r;
15838
+ return gvXmlEscape(s, FLAGS_TEXT);
15726
15839
  }
15727
15840
 
15728
15841
  // src/gvc/device-cluster.ts
@@ -15903,7 +16016,7 @@ function anchorAttr(n, key) {
15903
16016
  return v !== void 0 && v !== "" ? v : void 0;
15904
16017
  }
15905
16018
  function resolveTooltip(n, tooltip) {
15906
- if (tooltip !== void 0) return substObjAnchor(interpretCRNL(tooltip), n);
16019
+ if (tooltip !== void 0) return substObjAnchor(preprocessTooltip(tooltip), n);
15907
16020
  const label = n.info.label;
15908
16021
  return label?.text ?? "";
15909
16022
  }
@@ -20041,7 +20154,7 @@ function subst(s, obj) {
20041
20154
  return substObjAnchor(s, obj);
20042
20155
  }
20043
20156
  function tip(s, obj) {
20044
- return substObjAnchor(interpretCRNL(s), obj);
20157
+ return substObjAnchor(preprocessTooltip(s), obj);
20045
20158
  }
20046
20159
  function textOf(lp) {
20047
20160
  return lp?.text ?? null;