@knowvah/dot-engine 2.6.6 → 2.6.8

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.
Files changed (39) hide show
  1. package/dist/common/htmltable-attr-warn.d.ts +10 -4
  2. package/dist/common/htmltable-attr-warn.d.ts.map +1 -1
  3. package/dist/common/htmltable-label.d.ts +37 -0
  4. package/dist/common/htmltable-label.d.ts.map +1 -0
  5. package/dist/common/htmltable-lex-attvalue.d.ts +59 -0
  6. package/dist/common/htmltable-lex-attvalue.d.ts.map +1 -0
  7. package/dist/common/htmltable-lex-chardata.d.ts +37 -0
  8. package/dist/common/htmltable-lex-chardata.d.ts.map +1 -0
  9. package/dist/common/htmltable-lex-expat.d.ts +26 -13
  10. package/dist/common/htmltable-lex-expat.d.ts.map +1 -1
  11. package/dist/common/htmltable-lex.d.ts.map +1 -1
  12. package/dist/common/htmltable-parse-attrs.d.ts +3 -1
  13. package/dist/common/htmltable-parse-attrs.d.ts.map +1 -1
  14. package/dist/common/htmltable-parse.d.ts +6 -5
  15. package/dist/common/htmltable-parse.d.ts.map +1 -1
  16. package/dist/common/htmltable-pos.d.ts +3 -26
  17. package/dist/common/htmltable-pos.d.ts.map +1 -1
  18. package/dist/common/htmltable-types.d.ts +5 -1
  19. package/dist/common/htmltable-types.d.ts.map +1 -1
  20. package/dist/common/htmltable.d.ts +3 -2
  21. package/dist/common/htmltable.d.ts.map +1 -1
  22. package/dist/common/make-label.d.ts.map +1 -1
  23. package/dist/index.js +310 -144
  24. package/dist/index.js.map +4 -4
  25. package/dist/render.js +310 -144
  26. package/dist/render.js.map +4 -4
  27. package/package.json +1 -1
  28. package/src/common/htmltable-attr-warn.ts +24 -7
  29. package/src/common/htmltable-label.ts +109 -0
  30. package/src/common/htmltable-lex-attvalue.ts +141 -0
  31. package/src/common/htmltable-lex-chardata.ts +95 -0
  32. package/src/common/htmltable-lex-expat.ts +143 -48
  33. package/src/common/htmltable-lex.ts +41 -36
  34. package/src/common/htmltable-parse-attrs.ts +10 -13
  35. package/src/common/htmltable-parse.ts +46 -61
  36. package/src/common/htmltable-pos.ts +5 -88
  37. package/src/common/htmltable-types.ts +6 -1
  38. package/src/common/htmltable.ts +16 -16
  39. package/src/common/make-label.ts +8 -3
package/dist/index.js CHANGED
@@ -10358,9 +10358,11 @@ var StderrLines = class {
10358
10358
  writeLine;
10359
10359
  pending = "";
10360
10360
  write(text) {
10361
- const parts = (this.pending + text).split("\n");
10362
- this.pending = parts.pop() ?? "";
10363
- for (const line of parts) this.writeLine(line);
10361
+ this.pending += text;
10362
+ if (!this.pending.endsWith("\n")) return;
10363
+ const line = this.pending.slice(0, -1);
10364
+ this.pending = "";
10365
+ this.writeLine(line);
10364
10366
  }
10365
10367
  flush() {
10366
10368
  if (this.pending === "") return;
@@ -10368,6 +10370,16 @@ var StderrLines = class {
10368
10370
  this.pending = "";
10369
10371
  }
10370
10372
  };
10373
+ var consoleLine = (line) => {
10374
+ if (line.startsWith("Warning")) console.warn(line);
10375
+ else console.error(line);
10376
+ };
10377
+ var labelStderr = () => new StderrLines(consoleLine);
10378
+ var agerrLine = (out, msg) => {
10379
+ if (out === void 0) consoleLine(msg);
10380
+ else out.write(`${msg}
10381
+ `);
10382
+ };
10371
10383
 
10372
10384
  // src/common/htmltable-parse-state.ts
10373
10385
  var peek = (s) => s.tokens[s.pos];
@@ -10672,11 +10684,87 @@ function htmlEntityUTF8(s) {
10672
10684
  });
10673
10685
  }
10674
10686
 
10687
+ // src/common/htmltable-lex-attvalue.ts
10688
+ var XML_ERROR_UNDEFINED_ENTITY = "undefined entity";
10689
+ var XML_ERROR_BAD_CHAR_REF = "reference to invalid character number";
10690
+ var NAME_START = /[A-Za-z_:\u0080-￿]/;
10691
+ var NAME_CHAR = /[\w.:\u0080-￿-]/;
10692
+ var DEC_DIGIT = /[0-9]/;
10693
+ var HEX_DIGIT = /[0-9A-Fa-f]/;
10694
+ var NON_XML = /[\x00-\x08\x0b\x0c\x0e-\x1f]/;
10695
+ function scanDigits(text, i, digit) {
10696
+ if (i >= text.length) return { partial: true };
10697
+ if (!digit.test(text[i])) return { invalid: i };
10698
+ for (let k = i + 1; k < text.length; k++) {
10699
+ if (text[k] === ";") return k + 1;
10700
+ if (!digit.test(text[k])) return { invalid: k };
10701
+ }
10702
+ return { partial: true };
10703
+ }
10704
+ function scanRef(text, i) {
10705
+ const c = text[i];
10706
+ if (c === void 0) return { partial: true };
10707
+ if (c === "#") return text[i + 1] === "x" ? scanDigits(text, i + 2, HEX_DIGIT) : scanDigits(text, i + 1, DEC_DIGIT);
10708
+ if (!NAME_START.test(c)) return { invalid: i };
10709
+ for (let k = i + 1; k < text.length; k++) {
10710
+ if (text[k] === ";") return k + 1;
10711
+ if (!NAME_CHAR.test(text[k])) return { invalid: k };
10712
+ }
10713
+ return { partial: true };
10714
+ }
10715
+ function scanAttValue(text, j) {
10716
+ const q = text[j];
10717
+ let k = j + 1;
10718
+ for (; ; ) {
10719
+ const c = text[k];
10720
+ if (c === void 0) return { partial: true };
10721
+ if (c === q) return { close: k };
10722
+ if (c === "<" || NON_XML.test(c)) return { invalid: k };
10723
+ if (c !== "&") {
10724
+ k++;
10725
+ continue;
10726
+ }
10727
+ const r = scanRef(text, k + 1);
10728
+ if (typeof r !== "number") return r;
10729
+ k = r;
10730
+ }
10731
+ }
10732
+ function charRefNumber(ref) {
10733
+ const hex = ref.startsWith("&#x");
10734
+ const n = parseInt(ref.slice(hex ? 3 : 2, -1), hex ? 16 : 10);
10735
+ if (n >= 1114112) return -1;
10736
+ if (n >= 55296 && n <= 57343) return -1;
10737
+ if (n < 32 && NON_XML.test(String.fromCharCode(n))) return -1;
10738
+ return n === 65534 || n === 65535 ? -1 : n;
10739
+ }
10740
+ var PREDEFINED = { lt: "<", gt: ">", amp: "&", quot: '"', apos: "'" };
10741
+ var VALUE_PIECE = /&#x?[0-9A-Fa-f]+;|&[^;]+;|\r\n|[\t\n\r]/g;
10742
+ function attValueError(raw, base) {
10743
+ for (const m of raw.matchAll(VALUE_PIECE)) {
10744
+ const ref = m[0];
10745
+ if (!ref.startsWith("&")) continue;
10746
+ if (ref.startsWith("&#")) {
10747
+ if (charRefNumber(ref) < 0) return { message: XML_ERROR_BAD_CHAR_REF, offset: base + m.index };
10748
+ } else if (!Object.hasOwn(PREDEFINED, ref.slice(1, -1))) {
10749
+ return { message: XML_ERROR_UNDEFINED_ENTITY };
10750
+ }
10751
+ }
10752
+ return void 0;
10753
+ }
10754
+ function decodeAttValue(raw) {
10755
+ return raw.replace(VALUE_PIECE, (m) => {
10756
+ if (!m.startsWith("&")) return " ";
10757
+ if (m.startsWith("&#")) return String.fromCodePoint(charRefNumber(m));
10758
+ return PREDEFINED[m.slice(1, -1)];
10759
+ });
10760
+ }
10761
+
10675
10762
  // src/common/htmltable-lex-expat.ts
10676
10763
  var XML_ERROR_INVALID_TOKEN = "not well-formed (invalid token)";
10677
10764
  var XML_CONTEXT_BYTES = 1024;
10678
10765
  var INIT_BUFFER_SIZE = 1024;
10679
- var COMPLETE_END = (end, dup) => dup === void 0 ? { kind: "complete", end } : { kind: "complete", end, dup };
10766
+ var XML_ERROR_DUPLICATE_ATTRIBUTE = "duplicate attribute";
10767
+ var COMPLETE_END = (end, attError) => attError === void 0 ? { kind: "complete", end } : { kind: "complete", end, attError };
10680
10768
  var PARTIAL = { kind: "partial" };
10681
10769
  var INVALID = (offset) => ({ kind: "invalid", offset });
10682
10770
  var XML_NAME = /^[A-Za-z_:\u0080-\uFFFF][\w.:\u0080-\uFFFF-]*/;
@@ -10687,25 +10775,25 @@ function skipSpace(text, i) {
10687
10775
  return j;
10688
10776
  }
10689
10777
  var byteLength = (s) => new TextEncoder().encode(s).length;
10690
- function fedBytes(unit, isText) {
10691
- if (!isText) return byteLength(unit);
10692
- let text = unit.replace(/&([^;&<]*);/g, (m, name) => {
10778
+ function fedText(piece, endsUnit) {
10779
+ const text = piece.replace(/&([^;&<]*);/g, (m, name) => {
10693
10780
  return name.length >= 2 && Object.hasOwn(HTML_ENTITIES, name) ? `&#${HTML_ENTITIES[name]};` : m;
10694
10781
  });
10695
- if (text.endsWith("]")) text = `${text.slice(0, -1)}&#93;`;
10696
- return byteLength(text);
10782
+ return endsUnit && text.endsWith("]") ? `${text.slice(0, -1)}&#93;` : text;
10783
+ }
10784
+ function fedBytes(unit, isText) {
10785
+ return byteLength(isText ? fedText(unit, true) : unit);
10697
10786
  }
10698
10787
  function scanValue(text, j) {
10699
10788
  const q = text[j];
10700
10789
  if (q !== '"' && q !== "'") return INVALID(j);
10701
- const close = text.indexOf(q, j + 1);
10702
- if (close < 0) {
10703
- const lt = text.indexOf("<", j + 1);
10704
- return lt >= 0 ? INVALID(lt) : PARTIAL;
10705
- }
10790
+ const v = scanAttValue(text, j);
10791
+ if ("partial" in v) return PARTIAL;
10792
+ if ("invalid" in v) return INVALID(v.invalid);
10793
+ const close = v.close;
10706
10794
  const next = skipSpace(text, close + 1);
10707
10795
  if (next === close + 1 && !">/".includes(text[next] ?? ">")) return INVALID(next);
10708
- return next;
10796
+ return close;
10709
10797
  }
10710
10798
  function scanPair(text, i) {
10711
10799
  const name = XML_NAME.exec(text.slice(i))?.[0];
@@ -10715,8 +10803,9 @@ function scanPair(text, i) {
10715
10803
  if (text[eq] !== "=") return INVALID(eq);
10716
10804
  const j = skipSpace(text, eq + 1);
10717
10805
  if (j >= text.length) return PARTIAL;
10718
- const next = scanValue(text, j);
10719
- return typeof next === "number" ? { name, next } : next;
10806
+ const close = scanValue(text, j);
10807
+ if (typeof close !== "number") return close;
10808
+ return { name, next: skipSpace(text, close + 1), value: { start: j + 1, end: close } };
10720
10809
  }
10721
10810
  function tagEdge(text, i) {
10722
10811
  const c = text[i];
@@ -10726,18 +10815,23 @@ function tagEdge(text, i) {
10726
10815
  if (i + 1 >= text.length) return PARTIAL;
10727
10816
  return text[i + 1] === ">" ? COMPLETE_END(i + 2) : void 0;
10728
10817
  }
10729
- function scanAttributes(text, from) {
10818
+ function storeAttError(text, p, at, pair, seen) {
10819
+ if (seen.has(pair.name)) return { message: XML_ERROR_DUPLICATE_ATTRIBUTE, offset: at };
10820
+ seen.add(pair.name);
10821
+ const err = attValueError(text.slice(pair.value.start, pair.value.end), pair.value.start);
10822
+ return err === void 0 ? void 0 : { message: err.message, offset: err.offset ?? p };
10823
+ }
10824
+ function scanAttributes(text, p, from) {
10730
10825
  const seen = /* @__PURE__ */ new Set();
10731
- let dup;
10826
+ let attError;
10732
10827
  let i = skipSpace(text, from);
10733
10828
  for (; ; ) {
10734
10829
  const edge = tagEdge(text, i);
10735
- if (edge?.kind === "complete") return COMPLETE_END(edge.end, dup);
10830
+ if (edge?.kind === "complete") return COMPLETE_END(edge.end, attError);
10736
10831
  if (edge !== void 0) return edge;
10737
10832
  const pair = scanPair(text, i);
10738
10833
  if ("kind" in pair) return pair;
10739
- if (seen.has(pair.name)) dup ??= i;
10740
- seen.add(pair.name);
10834
+ attError ??= storeAttError(text, p, i, pair, seen);
10741
10835
  i = pair.next;
10742
10836
  }
10743
10837
  }
@@ -10752,7 +10846,7 @@ function scanStartTag(text, p) {
10752
10846
  const c = text[name.next];
10753
10847
  if (c === void 0) return PARTIAL;
10754
10848
  if (!isSpace(c) && c !== ">" && c !== "/") return INVALID(name.next);
10755
- return scanAttributes(text, name.next);
10849
+ return scanAttributes(text, p, name.next);
10756
10850
  }
10757
10851
  function scanEndTag(text, p) {
10758
10852
  const name = scanName(text, p + 2);
@@ -10795,26 +10889,45 @@ function scanMarkup(text, p) {
10795
10889
  if (c === "!") return { scan: scanDeclaration(text, p), kind: "tag" };
10796
10890
  return { scan: scanStartTag(text, p), kind: "tag" };
10797
10891
  }
10798
- function scanContent(text, base) {
10892
+ var CDATA_OPEN = "<![CDATA[";
10893
+ var CDATA_CLOSE = "]]>";
10894
+ function scanCdata(text, p, base, dataOf, tokens) {
10895
+ const close = text.indexOf(CDATA_CLOSE, p);
10896
+ const end = close < 0 ? text.length : close;
10897
+ if (end > p) tokens.push({ kind: "cdata", start: base + p, end: base + end, data: dataOf(base + p, base + end) });
10898
+ return close < 0 ? -1 : close + CDATA_CLOSE.length;
10899
+ }
10900
+ function scanText(text, p, base, tokens) {
10901
+ const e = text.indexOf("<", p);
10902
+ const end = e < 0 ? text.length : e;
10903
+ tokens.push({ kind: "text", start: base + p, end: base + end });
10904
+ return end;
10905
+ }
10906
+ function scanContent(text, base, inCdata, dataOf) {
10799
10907
  const tokens = [];
10800
10908
  let p = 0;
10909
+ let inSection = inCdata;
10801
10910
  while (p < text.length) {
10911
+ if (inSection || text.startsWith(CDATA_OPEN, p)) {
10912
+ const after2 = scanCdata(text, inSection ? p : p + CDATA_OPEN.length, base, dataOf, tokens);
10913
+ if (after2 < 0) return { tokens, consumed: text.length, inCdata: true };
10914
+ inSection = false;
10915
+ p = after2;
10916
+ continue;
10917
+ }
10802
10918
  if (text[p] !== "<") {
10803
- const e = text.indexOf("<", p);
10804
- const end = e < 0 ? text.length : e;
10805
- tokens.push({ kind: "text", start: base + p, end: base + end });
10806
- p = end;
10919
+ p = scanText(text, p, base, tokens);
10807
10920
  continue;
10808
10921
  }
10809
10922
  const { scan, kind } = scanMarkup(text, p);
10810
- if (scan.kind === "invalid") return { tokens, consumed: p, invalid: base + scan.offset };
10811
- if (scan.kind === "partial") return { tokens, consumed: p };
10923
+ if (scan.kind === "invalid") return { tokens, consumed: p, invalid: base + scan.offset, inCdata: false };
10924
+ if (scan.kind === "partial") return { tokens, consumed: p, inCdata: false };
10812
10925
  const tok = { kind, start: base + p, end: base + scan.end };
10813
- if (scan.dup !== void 0) tok.dup = base + scan.dup;
10926
+ if (scan.attError !== void 0) tok.attError = { ...scan.attError, offset: base + scan.attError.offset };
10814
10927
  tokens.push(tok);
10815
10928
  p = scan.end;
10816
10929
  }
10817
- return { tokens, consumed: p };
10930
+ return { tokens, consumed: p, inCdata: inSection };
10818
10931
  }
10819
10932
  var InputBuffer = class {
10820
10933
  size = 0;
@@ -10865,38 +10978,61 @@ var ExpatFeed = class {
10865
10978
  buffer = new InputBuffer();
10866
10979
  heldStart = 0;
10867
10980
  fedEnd = 0;
10981
+ inCdata = false;
10982
+ /** Source ranges of the text units fed so far: their bytes went through findNext's rewrite. */
10983
+ textUnits = [];
10868
10984
  /** Start of the token expat still holds, or undefined when it holds nothing. */
10869
10985
  get held() {
10870
10986
  return this.heldStart < this.fedEnd ? this.heldStart : void 0;
10871
10987
  }
10872
- /** One `XML_Parse(parser, src[start, end), nbytes, 0)`. */
10873
- feed(start, end, nbytes) {
10874
- this.buffer.append(nbytes);
10988
+ /** One `XML_Parse(parser, src[start, end), nbytes, 0)`; `isText` for a text unit. */
10989
+ feed(start, end, isText) {
10990
+ if (isText) this.textUnits.push([start, end]);
10991
+ this.buffer.append(fedBytes(this.src.slice(start, end), isText));
10875
10992
  this.fedEnd = end;
10876
10993
  if (!this.buffer.enough) return { tokens: [] };
10877
10994
  const text = this.src.slice(this.heldStart, end);
10878
- const scan = scanContent(text, this.heldStart);
10995
+ const scan = scanContent(text, this.heldStart, this.inCdata, (a, b) => this.fedBetween(a, b));
10879
10996
  if (scan.invalid !== void 0) {
10880
10997
  return { tokens: scan.tokens, invalid: { message: XML_ERROR_INVALID_TOKEN, offset: scan.invalid } };
10881
10998
  }
10999
+ this.inCdata = scan.inCdata;
10882
11000
  this.heldStart += scan.consumed;
10883
11001
  this.buffer.consumedTo(byteLength(this.src.slice(this.heldStart, end)), scan.consumed > 0);
10884
11002
  return { tokens: scan.tokens };
10885
11003
  }
11004
+ /** What expat read for source offsets [start, end): text-unit pieces as findNext rewrote them. */
11005
+ fedBetween(start, end) {
11006
+ let out = "";
11007
+ let p = start;
11008
+ for (const [us, ue] of this.textUnits) {
11009
+ if (ue <= p || us >= end) continue;
11010
+ if (us > p) out += this.src.slice(p, us);
11011
+ const e = Math.min(ue, end);
11012
+ out += fedText(this.src.slice(Math.max(us, p), e), e === ue);
11013
+ p = e;
11014
+ }
11015
+ return out + this.src.slice(p, end);
11016
+ }
10886
11017
  };
10887
11018
  var XML_PREDEFINED_ENTITIES = /* @__PURE__ */ new Set(["lt", "gt", "amp", "quot", "apos"]);
10888
11019
  var ENTITY_NAME = /^[A-Za-z_:][\w.:-]*$/;
10889
- function findUndefinedEntity(text) {
11020
+ var CHAR_REF = /^&#(?:x[0-9A-Fa-f]+|[0-9]+);/;
11021
+ function textRefError(text) {
10890
11022
  for (let t = text.indexOf("&"); t >= 0; t = text.indexOf("&", t + 1)) {
10891
- if (text[t + 1] === "#") continue;
11023
+ if (text[t + 1] === "#") {
11024
+ const ref = CHAR_REF.exec(text.slice(t))?.[0];
11025
+ if (ref !== void 0 && charRefNumber(ref) < 0) return { message: XML_ERROR_BAD_CHAR_REF, offset: t };
11026
+ continue;
11027
+ }
10892
11028
  const semi = text.indexOf(";", t + 1);
10893
11029
  if (semi < 0) continue;
10894
11030
  const key = text.slice(t + 1, semi);
10895
11031
  if (ENTITY_NAME.test(key) && !Object.hasOwn(HTML_ENTITIES, key) && !XML_PREDEFINED_ENTITIES.has(key)) {
10896
- return t;
11032
+ return { message: XML_ERROR_UNDEFINED_ENTITY, offset: t };
10897
11033
  }
10898
11034
  }
10899
- return -1;
11035
+ return void 0;
10900
11036
  }
10901
11037
  function parseTagChunk(chunk) {
10902
11038
  if (!chunk.endsWith(">")) return void 0;
@@ -10907,6 +11043,46 @@ function parseTagChunk(chunk) {
10907
11043
  return { close, selfClose: !close && body.endsWith("/"), name };
10908
11044
  }
10909
11045
 
11046
+ // src/common/htmltable-lex-chardata.ts
11047
+ var initialCharData = () => ({ inCell: true, xb: "" });
11048
+ function startInCell(name, inCell) {
11049
+ if (name === "TABLE" || name === "TR" || name === "TH") return false;
11050
+ return name === "TD" ? true : inCell;
11051
+ }
11052
+ function endInCell(name, inCell) {
11053
+ if (name === "TABLE") return true;
11054
+ return name === "TD" ? false : inCell;
11055
+ }
11056
+ function tagInCell(st, tag) {
11057
+ const name = tag.name.toUpperCase();
11058
+ if (tag.close) {
11059
+ st.inCell = endInCell(name, st.inCell);
11060
+ return;
11061
+ }
11062
+ st.inCell = startInCell(name, st.inCell);
11063
+ if (tag.selfClose) st.inCell = endInCell(name, st.inCell);
11064
+ }
11065
+ function keepLostText(st, lost) {
11066
+ for (const t of lost) if (t.type === "text") st.xb += t.value;
11067
+ }
11068
+ function releaseXb(st, first) {
11069
+ if (st.xb === "") return;
11070
+ if (first.type === "text") first.value = st.xb + first.value;
11071
+ else if (first.type === "open" && first.tag === "TABLE") first.heldText = st.xb;
11072
+ else return;
11073
+ st.xb = "";
11074
+ }
11075
+ function cleanText(decoded) {
11076
+ return decoded.replace(/[\x00-\x1f]/g, "");
11077
+ }
11078
+ function textTokens(raw) {
11079
+ return charDataTokens(htmlEntityUTF8(raw));
11080
+ }
11081
+ function charDataTokens(decoded) {
11082
+ const clean = cleanText(decoded);
11083
+ return clean.length > 0 ? [{ type: "text", value: clean }] : [];
11084
+ }
11085
+
10910
11086
  // src/common/htmltable-lex-units.ts
10911
11087
  var UNCLOSED_COMMENT = "Warning: Unclosed comment\n";
10912
11088
  var LABEL_CLOSED = "Warning: Label closed before end of HTML element\n";
@@ -10996,7 +11172,7 @@ function parseAttrPairs(raw) {
10996
11172
  if (q !== '"' && q !== "'") throw new HtmlParseError(name);
10997
11173
  const end = raw.indexOf(q, i + 1);
10998
11174
  if (end < 0) throw new HtmlParseError(name);
10999
- out.push([name, raw.slice(i + 1, end)]);
11175
+ out.push([name, decodeAttValue(raw.slice(i + 1, end))]);
11000
11176
  i = end + 1;
11001
11177
  }
11002
11178
  return out;
@@ -11011,20 +11187,17 @@ function parseCloseToken(inner) {
11011
11187
  checkTag(tag);
11012
11188
  return { type: "close", tag: normalizeTag(tag) };
11013
11189
  }
11014
- function cleanText(raw) {
11015
- const isKeep = (c) => c === " " || c === " " || c === "\n" || c === "\r";
11016
- return raw.replace(/[\x00-\x1f\x7f]/g, (c) => isKeep(c) ? c : "");
11017
- }
11018
- function textTokens(raw) {
11019
- const clean = htmlEntityUTF8(cleanText(raw));
11020
- return clean.length > 0 ? [{ type: "text", value: clean }] : [];
11021
- }
11190
+ var EMPTY_ELEMENTS = /* @__PURE__ */ new Set(["BR", "HR", "VR", "IMG"]);
11022
11191
  function tagTokens(text) {
11023
11192
  const inner = text.slice(1, -1).trim();
11024
11193
  if (inner.startsWith("/")) return [parseCloseToken(inner)];
11025
11194
  if (inner.endsWith("/")) {
11026
11195
  const open = parseOpenToken(inner.slice(0, -1).trim());
11027
- return [open, { type: "close", tag: open.tag }];
11196
+ if (EMPTY_ELEMENTS.has(open.tag)) return [open, { type: "close", tag: open.tag }];
11197
+ const close = { type: "close", tag: open.tag };
11198
+ if (open.warnings !== void 0) close.warnings = open.warnings;
11199
+ if (open.warn === true) close.warn = true;
11200
+ return [close];
11028
11201
  }
11029
11202
  return [parseOpenToken(inner)];
11030
11203
  }
@@ -11041,9 +11214,7 @@ function parseOpenToken(inner) {
11041
11214
  checkTag(tag);
11042
11215
  return openToken(normalizeTag(tag), sp === -1 ? "" : inner.slice(sp + 1));
11043
11216
  }
11044
- var XML_ERROR_UNDEFINED_ENTITY = "undefined entity";
11045
11217
  var XML_ERROR_TAG_MISMATCH = "mismatched tag";
11046
- var XML_ERROR_DUPLICATE_ATTRIBUTE = "duplicate attribute";
11047
11218
  var SYNTAX_ERROR = "syntax error";
11048
11219
  var HtmlLexError = class extends HtmlParseError {
11049
11220
  diagnostics;
@@ -11086,7 +11257,8 @@ function checkTagToken(site) {
11086
11257
  throw htmlErrorInLine(XML_ERROR_TAG_MISMATCH, lineAt(src, tok.start), context);
11087
11258
  }
11088
11259
  } else {
11089
- if (tok.dup !== void 0) throw htmlErrorInLine(XML_ERROR_DUPLICATE_ATTRIBUTE, lineAt(src, tok.dup), context);
11260
+ const err = tok.attError;
11261
+ if (err !== void 0) throw htmlErrorInLine(err.message, lineAt(src, err.offset), context);
11090
11262
  if (!tag.selfClose) st.stack.push(tag.name);
11091
11263
  }
11092
11264
  if (KNOWN_TAGS.has(tag.name.toUpperCase())) return;
@@ -11097,14 +11269,13 @@ function eventTokens(site) {
11097
11269
  const { src, tok, st } = site;
11098
11270
  const text = src.slice(tok.start, tok.end);
11099
11271
  if (tok.kind === "comment" || tok.kind === "pi") return [];
11272
+ if (tok.kind === "cdata") return charDataTokens(tok.data ?? "");
11100
11273
  if (tok.kind === "tag") {
11101
11274
  checkTagToken(site);
11102
11275
  return tagTokens(text);
11103
11276
  }
11104
- const off = findUndefinedEntity(text);
11105
- if (off >= 0) {
11106
- throw htmlErrorInLine(XML_ERROR_UNDEFINED_ENTITY, lineAt(src, tok.start + off), st.prev + st.curr);
11107
- }
11277
+ const err = textRefError(text);
11278
+ if (err !== void 0) throw htmlErrorInLine(err.message, lineAt(src, tok.start + err.offset), st.prev + st.curr);
11108
11279
  return textTokens(text);
11109
11280
  }
11110
11281
  function attachCarry(carry, first) {
@@ -11122,7 +11293,13 @@ function absorb(carry, lost) {
11122
11293
  function eventGroups(run, res) {
11123
11294
  const groups = [];
11124
11295
  for (const tok of res.tokens) {
11125
- const tokens = eventTokens({ src: run.src, tok, st: run.st });
11296
+ let tokens = eventTokens({ src: run.src, tok, st: run.st });
11297
+ if (tok.kind === "tag") {
11298
+ const tag = parseTagChunk(run.src.slice(tok.start, tok.end));
11299
+ if (tag !== void 0) tagInCell(run.cd, tag);
11300
+ } else if (!run.cd.inCell) {
11301
+ tokens = [];
11302
+ }
11126
11303
  if (tokens.length > 0) groups.push({ tokens, tok });
11127
11304
  }
11128
11305
  if (res.invalid !== void 0) {
@@ -11133,6 +11310,7 @@ function eventGroups(run, res) {
11133
11310
  }
11134
11311
  function deliver(run, last) {
11135
11312
  const first = last.tokens[0];
11313
+ releaseXb(run.cd, first);
11136
11314
  attachCarry(run.carry, first);
11137
11315
  const info = { src: run.src, pos: last.tok.start, end: last.tok.end, context: run.st.prev + run.st.curr };
11138
11316
  const prev = run.tokens.at(-1);
@@ -11147,7 +11325,10 @@ function deliver(run, last) {
11147
11325
  function runEvents(run, res) {
11148
11326
  const groups = eventGroups(run, res);
11149
11327
  const last = groups.pop();
11150
- for (const g of groups) absorb(run.carry, g.tokens);
11328
+ for (const g of groups) {
11329
+ absorb(run.carry, g.tokens);
11330
+ keepLostText(run.cd, g.tokens);
11331
+ }
11151
11332
  if (last !== void 0) deliver(run, last);
11152
11333
  }
11153
11334
  function appendString(into, more) {
@@ -11178,7 +11359,8 @@ function tokenizeDeferred(src, label = { start: 0, end: src.length }) {
11178
11359
  tokens: [],
11179
11360
  st: { stack: [], prev: "", curr: "" },
11180
11361
  expat: new ExpatFeed(src),
11181
- carry: { warnings: [], warn: false }
11362
+ carry: { warnings: [], warn: false },
11363
+ cd: initialCharData()
11182
11364
  };
11183
11365
  let error;
11184
11366
  try {
@@ -11187,8 +11369,7 @@ function tokenizeDeferred(src, label = { start: 0, end: src.length }) {
11187
11369
  run.st.curr = src.slice(u.start, u.end);
11188
11370
  run.carry.warnings.push(...u.warnings);
11189
11371
  if (u.warn) run.carry.warn = true;
11190
- const nbytes = fedBytes(run.st.curr, !run.st.curr.startsWith("<"));
11191
- runEvents(run, run.expat.feed(u.start, u.end, nbytes));
11372
+ runEvents(run, run.expat.feed(u.start, u.end, !run.st.curr.startsWith("<")));
11192
11373
  }
11193
11374
  const held = run.expat.held;
11194
11375
  if (held !== void 0) error = unfinishedError(run, held);
@@ -11204,9 +11385,6 @@ function tokenizeDeferred(src, label = { start: 0, end: src.length }) {
11204
11385
  }
11205
11386
 
11206
11387
  // src/common/htmltable-parse-attrs.ts
11207
- function anchorAttr(v) {
11208
- return v === void 0 ? void 0 : htmlEntityUTF8(v);
11209
- }
11210
11388
  var parseAlign = (v) => {
11211
11389
  const u = v.toUpperCase();
11212
11390
  if (u === "LEFT") return "left";
@@ -11214,6 +11392,7 @@ var parseAlign = (v) => {
11214
11392
  if (u === "CENTER") return "center";
11215
11393
  return void 0;
11216
11394
  };
11395
+ var parseCellAlign = (v) => v.toUpperCase() === "TEXT" ? "text" : parseAlign(v);
11217
11396
  var parseVAlign = (v) => {
11218
11397
  const u = v.toUpperCase();
11219
11398
  if (u === "TOP") return "top";
@@ -11247,7 +11426,7 @@ var buildCell = (content, a) => ({
11247
11426
  kind: "cell",
11248
11427
  content,
11249
11428
  port: a["port"],
11250
- align: parseAlign(a["align"] !== void 0 ? a["align"] : ""),
11429
+ align: parseCellAlign(a["align"] !== void 0 ? a["align"] : ""),
11251
11430
  valign: parseVAlign(a["valign"] !== void 0 ? a["valign"] : ""),
11252
11431
  balign: parseAlign(a["balign"] !== void 0 ? a["balign"] : ""),
11253
11432
  bgcolor: a["bgcolor"],
@@ -11263,9 +11442,9 @@ var buildCell = (content, a) => ({
11263
11442
  fixedsize: parseFixedSize(a),
11264
11443
  colspan: num(a["colspan"]),
11265
11444
  rowspan: num(a["rowspan"]),
11266
- href: anchorAttr(a["href"]),
11445
+ href: a["href"],
11267
11446
  title: parseTitle(a),
11268
- target: anchorAttr(a["target"]),
11447
+ target: a["target"],
11269
11448
  id: a["id"]
11270
11449
  });
11271
11450
  var buildTable = (rows, a) => ({
@@ -11283,9 +11462,9 @@ var buildTable = (rows, a) => ({
11283
11462
  fixedsize: parseFixedSize(a),
11284
11463
  width: num(a["width"]),
11285
11464
  height: num(a["height"]),
11286
- href: anchorAttr(a["href"]),
11465
+ href: a["href"],
11287
11466
  title: parseTitle(a),
11288
- target: anchorAttr(a["target"]),
11467
+ target: a["target"],
11289
11468
  id: a["id"],
11290
11469
  port: a["port"],
11291
11470
  sides: parseSides(a["sides"]),
@@ -11353,7 +11532,8 @@ var tableFont = (fontStack) => {
11353
11532
  var MSG_SYNTAX_ERROR = "syntax error";
11354
11533
  var MSG_TEXT_BEFORE_TABLE = "Syntax error: non-space string used before <TABLE>";
11355
11534
  var MSG_TEXT_AFTER_TABLE = "Syntax error: non-space string used after </TABLE>";
11356
- var nonSpace = (text) => /[^ \t\n\r]/.test(text);
11535
+ var nonSpace = (text) => /[^ ]/.test(text);
11536
+ var heldNonSpace = (tbl) => tbl?.type === "open" && nonSpace(tbl.heldText ?? "");
11357
11537
  var parseError = (s, tok, message) => {
11358
11538
  if (tok !== void 0) emitWarnings(s, tok);
11359
11539
  else emitEof(s);
@@ -11374,41 +11554,29 @@ var applyBrTag = (s, t, fontStack, items) => {
11374
11554
  items.push({ br: true, brAlign: parseAlign(t.attrs["align"] ?? ""), ...fontItemProps(font) });
11375
11555
  consumeClose(s, "BR");
11376
11556
  };
11377
- var applyFontTag = (s, t, fontStack, items) => {
11378
- consume(s);
11379
- const font = fontStack[fontStack.length - 1] ?? {};
11380
- fontStack.push(mergeFontState(font, {
11381
- fontColor: t.attrs["color"],
11382
- fontFace: t.attrs["face"],
11383
- fontSize: num(t.attrs["point-size"])
11384
- }));
11557
+ var parseStyledText = (s, tag, fontStack, items) => {
11385
11558
  const inner = parseText(s, fontStack);
11386
11559
  fontStack.pop();
11387
- items.push(...inner.items);
11388
11560
  const nxt = peek(s);
11389
- if (nxt?.type === "close" && nxt.tag === "FONT") consume(s);
11561
+ if (inner.items.length === 0 || nxt?.type !== "close" || nxt.tag !== tag) {
11562
+ throw parseError(s, nxt, MSG_SYNTAX_ERROR);
11563
+ }
11564
+ items.push(...inner.items);
11565
+ consume(s);
11390
11566
  };
11391
- var applyInlineTag = (s, t, fontStack, items) => {
11567
+ var applyStyleTag = (s, t, fontStack, items) => {
11392
11568
  consume(s);
11393
- const font = fontStack[fontStack.length - 1] ?? {};
11394
- fontStack.push(mergeFontState(font, inlineFontState(t.tag, t.attrs)));
11395
- const inner = parseText(s, fontStack);
11396
- fontStack.pop();
11397
- items.push(...inner.items);
11398
- const nxt = peek(s);
11399
- if (nxt?.type === "close" && nxt.tag === t.tag) consume(s);
11569
+ const own = t.tag === "FONT" ? { fontColor: t.attrs["color"], fontFace: t.attrs["face"], fontSize: num(t.attrs["point-size"]) } : inlineFontState(t.tag, t.attrs);
11570
+ fontStack.push(mergeFontState(fontStack[fontStack.length - 1] ?? {}, own));
11571
+ parseStyledText(s, t.tag, fontStack, items);
11400
11572
  };
11401
11573
  var applyOpenTag = (s, t, fontStack, items) => {
11402
11574
  if (t.tag === "BR") {
11403
11575
  applyBrTag(s, t, fontStack, items);
11404
11576
  return true;
11405
11577
  }
11406
- if (t.tag === "FONT") {
11407
- applyFontTag(s, t, fontStack, items);
11408
- return true;
11409
- }
11410
- if (isInlineTag(t.tag)) {
11411
- applyInlineTag(s, t, fontStack, items);
11578
+ if (t.tag === "FONT" || isInlineTag(t.tag)) {
11579
+ applyStyleTag(s, t, fontStack, items);
11412
11580
  return true;
11413
11581
  }
11414
11582
  return false;
@@ -11451,7 +11619,7 @@ var parseFontTable = (s, open, fontStack) => {
11451
11619
  fontStack.push(wrapperFont(open, fontStack));
11452
11620
  const textBefore = skipStrings(s);
11453
11621
  const tblTok = peek(s);
11454
- if (textBefore && tblTok !== void 0) throw parseError(s, tblTok, MSG_TEXT_BEFORE_TABLE);
11622
+ if ((textBefore || heldNonSpace(tblTok)) && tblTok !== void 0) throw parseError(s, tblTok, MSG_TEXT_BEFORE_TABLE);
11455
11623
  const table = parseTable(s, fontStack);
11456
11624
  const textAfter = skipStrings(s);
11457
11625
  const close = peek(s);
@@ -11468,11 +11636,11 @@ var rejectTableAfterTag = (s, start) => {
11468
11636
  throw parseError(s, nxt, MSG_SYNTAX_ERROR);
11469
11637
  }
11470
11638
  };
11471
- var parseImgContent = (s, t, cellAttrs) => {
11639
+ var parseImgContent = (s, t) => {
11472
11640
  consume(s);
11473
11641
  const img = {
11474
11642
  kind: "image",
11475
- src: cellAttrs["src"] ?? t.attrs["src"] ?? "",
11643
+ src: t.attrs["src"] ?? "",
11476
11644
  scale: t.attrs["scale"]
11477
11645
  };
11478
11646
  consumeClose(s, "IMG");
@@ -11480,7 +11648,7 @@ var parseImgContent = (s, t, cellAttrs) => {
11480
11648
  };
11481
11649
  var scanCellTable = (s, t, fontStack, st) => {
11482
11650
  if (st.kind === "image" || st.kind === "table") throw parseError(s, t, MSG_SYNTAX_ERROR);
11483
- if (st.textNonSpace) throw parseError(s, t, MSG_TEXT_BEFORE_TABLE);
11651
+ if (st.textNonSpace || heldNonSpace(t)) throw parseError(s, t, MSG_TEXT_BEFORE_TABLE);
11484
11652
  const tbl = parseTable(s, fontStack);
11485
11653
  st.kind = "table";
11486
11654
  return [tbl];
@@ -11500,12 +11668,12 @@ var scanAfterTable = (s, t, st) => {
11500
11668
  if (nonSpace(t.value)) st.afterNonSpace = true;
11501
11669
  return [];
11502
11670
  };
11503
- var scanCellImage = (s, t, cellAttrs, st) => {
11671
+ var scanCellImage = (s, t, st) => {
11504
11672
  if (st.kind !== "none") throw parseError(s, t, MSG_SYNTAX_ERROR);
11505
11673
  st.kind = "image";
11506
- return [parseImgContent(s, t, cellAttrs)];
11674
+ return [parseImgContent(s, t)];
11507
11675
  };
11508
- var scanCellItem = (s, t, cellAttrs, fontStack, st) => {
11676
+ var scanCellItem = (s, t, fontStack, st) => {
11509
11677
  if (st.kind === "fonttable") throw parseError(s, t, MSG_SYNTAX_ERROR);
11510
11678
  if (st.kind === "table") return scanAfterTable(s, t, st);
11511
11679
  const wrapper = st.kind === "none" ? fontTableWrapper(s) : void 0;
@@ -11514,7 +11682,7 @@ var scanCellItem = (s, t, cellAttrs, fontStack, st) => {
11514
11682
  return [parseFontTable(s, wrapper, fontStack)];
11515
11683
  }
11516
11684
  if (t.type === "open" && t.tag === "TABLE") return scanCellTable(s, t, fontStack, st);
11517
- if (t.type === "open" && t.tag === "IMG") return scanCellImage(s, t, cellAttrs, st);
11685
+ if (t.type === "open" && t.tag === "IMG") return scanCellImage(s, t, st);
11518
11686
  if (st.kind === "image") throw parseError(s, t, MSG_SYNTAX_ERROR);
11519
11687
  return scanCellText(s, t, fontStack, st);
11520
11688
  };
@@ -11524,12 +11692,12 @@ var endsCell = (s, t, st) => {
11524
11692
  if (t.tag === "TD" && !afterText) return true;
11525
11693
  throw parseError(s, t, afterText ? MSG_TEXT_AFTER_TABLE : MSG_SYNTAX_ERROR);
11526
11694
  };
11527
- var parseCellContent = (s, cellAttrs, fontStack) => {
11695
+ var parseCellContent = (s, fontStack) => {
11528
11696
  const content = [];
11529
11697
  const st = { kind: "none", textNonSpace: false, afterNonSpace: false };
11530
11698
  for (let t = peek(s); t !== void 0; t = peek(s)) {
11531
11699
  if (endsCell(s, t, st)) break;
11532
- content.push(...scanCellItem(s, t, cellAttrs, fontStack, st));
11700
+ content.push(...scanCellItem(s, t, fontStack, st));
11533
11701
  }
11534
11702
  const nxt = peek(s);
11535
11703
  if (nxt?.type === "close" && nxt.tag === "TD") consume(s);
@@ -11537,7 +11705,7 @@ var parseCellContent = (s, cellAttrs, fontStack) => {
11537
11705
  if (tbl !== void 0) return [tbl];
11538
11706
  return content;
11539
11707
  };
11540
- var parseCell = (s, attrs, fontStack) => buildCell(parseCellContent(s, attrs, fontStack), attrs);
11708
+ var parseCell = (s, attrs, fontStack) => buildCell(parseCellContent(s, fontStack), attrs);
11541
11709
  var parseRowVr = (s, t, cells) => {
11542
11710
  const prev = cells[cells.length - 1];
11543
11711
  if (prev === void 0) throw parseError(s, t, MSG_SYNTAX_ERROR);
@@ -11635,14 +11803,14 @@ var consumeRowHr = (s, rows) => {
11635
11803
  var findFirstRealToken = (tokens, start) => {
11636
11804
  for (let i = start; i < tokens.length; i++) {
11637
11805
  const tk = tokens[i];
11638
- if (tk.type !== "text" || tk.value.trim() !== "") return tk;
11806
+ if (tk.type !== "text" || nonSpace(tk.value)) return tk;
11639
11807
  }
11640
11808
  return void 0;
11641
11809
  };
11642
11810
  var skipLeadingWs = (s) => {
11643
11811
  while (true) {
11644
11812
  const nxt = peek(s);
11645
- if (!nxt || nxt.type !== "text" || nxt.value.trim() !== "") break;
11813
+ if (!nxt || nxt.type !== "text" || nonSpace(nxt.value)) break;
11646
11814
  consume(s);
11647
11815
  }
11648
11816
  };
@@ -11668,6 +11836,7 @@ var parseFontTableLabel = (s, open, fontStack) => {
11668
11836
  };
11669
11837
  var parseTableLabel = (s, fontStack) => {
11670
11838
  skipLeadingWs(s);
11839
+ if (heldNonSpace(peek(s))) throw parseError(s, peek(s), MSG_TEXT_BEFORE_TABLE);
11671
11840
  const table = parseTable(s, fontStack);
11672
11841
  finishTableLabel(s);
11673
11842
  return { kind: "table", table };
@@ -11697,17 +11866,9 @@ var parseTokens = (s) => {
11697
11866
  if (firstReal?.type === "open" && firstReal.tag === "TABLE") return parseTableLabel(s, fontStack);
11698
11867
  return parseTextLabel(s, fontStack);
11699
11868
  };
11700
- var parseHtmlLabelRv = (src, writeLine = (line) => console.warn(line)) => {
11869
+ var parseHtmlLabelRv = (src, stderr) => {
11701
11870
  const { tokens, error, eof } = tokenizeDeferred(`<HTML>${src}</HTML>`, { start: 6, end: 6 + src.length });
11702
- const s = {
11703
- tokens,
11704
- pos: 0,
11705
- pending: error,
11706
- stderr: new StderrLines(writeLine),
11707
- emitted: /* @__PURE__ */ new WeakSet(),
11708
- warn: false,
11709
- eof
11710
- };
11871
+ const s = { tokens, pos: 0, pending: error, stderr, emitted: /* @__PURE__ */ new WeakSet(), warn: false, eof };
11711
11872
  try {
11712
11873
  const label = parseTokens(s);
11713
11874
  if (error !== void 0) throw error;
@@ -11718,11 +11879,9 @@ var parseHtmlLabelRv = (src, writeLine = (line) => console.warn(line)) => {
11718
11879
  throw error;
11719
11880
  }
11720
11881
  throw e;
11721
- } finally {
11722
- s.stderr?.flush();
11723
11882
  }
11724
11883
  };
11725
- var parseHtmlLabel = (src) => parseHtmlLabelRv(src, () => void 0).label;
11884
+ var parseHtmlLabel = (src) => parseHtmlLabelRv(src, new StderrLines(() => void 0)).label;
11726
11885
 
11727
11886
  // src/gvc/usershape.ts
11728
11887
  var activeSizer = null;
@@ -11924,7 +12083,7 @@ var sizeTextContent = (texts, measurer, env = defaultSizeEnv()) => {
11924
12083
  return { w, h };
11925
12084
  };
11926
12085
  var missingImages = /* @__PURE__ */ new WeakSet();
11927
- var sizeHtmlImg = (img, imageSizer) => {
12086
+ var sizeHtmlImg = (img, { imageSizer, stderr }) => {
11928
12087
  if (img.width !== void 0 && img.height !== void 0) return missingImages.has(img) ? 1 : 0;
11929
12088
  const sz = imageSizer !== void 0 ? imageSizer(img.src) : findImageSize(img.src);
11930
12089
  if (sz !== null) {
@@ -11932,7 +12091,7 @@ var sizeHtmlImg = (img, imageSizer) => {
11932
12091
  img.height = sz.h;
11933
12092
  return 0;
11934
12093
  }
11935
- console.error(`Error: No or improper image file="${img.src}"`);
12094
+ agerrLine(stderr, `Error: No or improper image file="${img.src}"`);
11936
12095
  img.width = 0;
11937
12096
  img.height = 0;
11938
12097
  missingImages.add(img);
@@ -11945,7 +12104,7 @@ var sizeContentItem = (item, measurer, env) => {
11945
12104
  return { ...item.dimen !== void 0 ? item.dimen : { w: 0, h: 0 }, rv };
11946
12105
  }
11947
12106
  if (item.kind === "image") {
11948
- const rv = sizeHtmlImg(item, env.imageSizer);
12107
+ const rv = sizeHtmlImg(item, env);
11949
12108
  return { w: item.width ?? 0, h: item.height ?? 0, rv };
11950
12109
  }
11951
12110
  return { w: 0, h: 0, rv: 0 };
@@ -11975,14 +12134,14 @@ var WARN_CELL_UNSPECIFIED = "Warning: fixed cell size with unspecified width or
11975
12134
  var WARN_TABLE_TOO_SMALL = "Warning: table size too small for content";
11976
12135
  var WARN_TABLE_UNSPECIFIED = "Warning: fixed table size with unspecified width or height";
11977
12136
  var sizeWarned = /* @__PURE__ */ new WeakSet();
11978
- var fixedCellCheck = (cell2, sz, warn) => {
12137
+ var fixedCellCheck = (cell2, sz, warn, out) => {
11979
12138
  if (!cell2.fixedsize) return { rv: 0, zero: false };
11980
12139
  if (cell2.width && cell2.height) {
11981
12140
  const small = (cell2.width < sz.w || cell2.height < sz.h) && cell2.content[0]?.kind !== "image";
11982
- if (small && warn) console.warn(WARN_CELL_TOO_SMALL);
12141
+ if (small && warn) agerrLine(out, WARN_CELL_TOO_SMALL);
11983
12142
  return { rv: small ? 1 : 0, zero: true };
11984
12143
  }
11985
- if (warn) console.warn(WARN_CELL_UNSPECIFIED);
12144
+ if (warn) agerrLine(out, WARN_CELL_UNSPECIFIED);
11986
12145
  return { rv: 1, zero: false };
11987
12146
  };
11988
12147
  var getCellSize = (cell2, tbl, measurer, env) => {
@@ -11998,7 +12157,7 @@ var getCellSize = (cell2, tbl, measurer, env) => {
11998
12157
  let szy = ch + margin;
11999
12158
  const warn = !sizeWarned.has(cell2);
12000
12159
  sizeWarned.add(cell2);
12001
- const fixed = fixedCellCheck(cell2, { w: szx, h: szy }, warn);
12160
+ const fixed = fixedCellCheck(cell2, { w: szx, h: szy }, warn, env.stderr);
12002
12161
  rv |= fixed.rv;
12003
12162
  if (fixed.zero) {
12004
12163
  szx = 0;
@@ -12092,22 +12251,22 @@ var layoutHtmlTable = (tbl, measurer, env = defaultSizeEnv()) => {
12092
12251
  const heights = setRowHeights(entries, nrows, spacing);
12093
12252
  return { entries, widths, heights, spacing, border: border2, rv };
12094
12253
  };
12095
- var warnFixedTable = (tbl, dims) => {
12254
+ var warnFixedTable = (tbl, dims, out) => {
12096
12255
  const warn = !sizeWarned.has(tbl);
12097
12256
  sizeWarned.add(tbl);
12098
12257
  if (tbl.fixedsize !== true) return 0;
12099
12258
  if (tbl.width && tbl.height) {
12100
12259
  if (tbl.width >= dims.wd && tbl.height >= dims.ht) return 0;
12101
- if (warn) console.warn(WARN_TABLE_TOO_SMALL);
12260
+ if (warn) agerrLine(out, WARN_TABLE_TOO_SMALL);
12102
12261
  return 1;
12103
12262
  }
12104
- if (warn) console.warn(WARN_TABLE_UNSPECIFIED);
12263
+ if (warn) agerrLine(out, WARN_TABLE_UNSPECIFIED);
12105
12264
  return 1;
12106
12265
  };
12107
12266
  var sizeTableBody = (tbl, measurer, env) => {
12108
12267
  const { entries, widths, heights, spacing, border: border2, rv } = layoutHtmlTable(tbl, measurer, env);
12109
12268
  if (entries.length === 0) {
12110
- const fixed2 = warnFixedTable(tbl, sumTableDims({ widths, heights, ncols: 0, nrows: 0, spacing, border: border2 }));
12269
+ const fixed2 = warnFixedTable(tbl, sumTableDims({ widths, heights, ncols: 0, nrows: 0, spacing, border: border2 }), env.stderr);
12111
12270
  tbl.dimen = { w: 0, h: 0 };
12112
12271
  return rv | fixed2;
12113
12272
  }
@@ -12117,7 +12276,7 @@ var sizeTableBody = (tbl, measurer, env) => {
12117
12276
  const { wd, ht } = sumTableDims({ widths, heights, ncols, nrows, spacing, border: border2 });
12118
12277
  const baseWd = tbl.width !== void 0 ? tbl.width : 0;
12119
12278
  const baseHt = tbl.height !== void 0 ? tbl.height : 0;
12120
- const fixed = warnFixedTable(tbl, { wd, ht });
12279
+ const fixed = warnFixedTable(tbl, { wd, ht }, env.stderr);
12121
12280
  const zeroContent = isTblFixed(tbl) && baseWd !== 0 && baseHt !== 0;
12122
12281
  tbl.dimen = {
12123
12282
  w: Math.max(zeroContent ? 0 : wd, baseWd),
@@ -17449,7 +17608,7 @@ function placeComplexRuns(runs, box, finfo, measurer) {
17449
17608
  function alignContentBox(box, cell2, w, h) {
17450
17609
  const out = { ll: { ...box.ll }, ur: { ...box.ur } };
17451
17610
  const delx = out.ur.x - out.ll.x - w;
17452
- if (delx > 0) {
17611
+ if (delx > 0 && cell2.align !== "text") {
17453
17612
  if (cell2.align === "left") out.ur.x -= delx;
17454
17613
  else if (cell2.align === "right") out.ll.x += delx;
17455
17614
  else {
@@ -17704,21 +17863,25 @@ function posHtmlLabel(label, finfo, measurer) {
17704
17863
  if (label.kind === "table") return withTableFont(env, label.table.font, "emit", () => posHtmlTable(label.table, env, measurer));
17705
17864
  return posTextLabel(label, finfo, measurer);
17706
17865
  }
17866
+
17867
+ // src/common/htmltable-label.ts
17707
17868
  var HTML_PARSE_FATAL = 3;
17708
- function makeHtmlLabelRv(content, finfo, measurer) {
17869
+ function makeHtmlLabelTo(content, finfo, measurer, stderr) {
17709
17870
  const { fontname, fontsize, fontcolor, imageSizer, pencolor } = finfo;
17710
17871
  let lbl, lexWarn;
17711
17872
  try {
17712
- ({ label: lbl, warn: lexWarn } = parseHtmlLabelRv(content));
17873
+ ({ label: lbl, warn: lexWarn } = parseHtmlLabelRv(content, stderr));
17713
17874
  } catch (e) {
17714
- if (e instanceof HtmlLexError) for (const line of e.diagnostics) console.error(line);
17875
+ if (e instanceof HtmlLexError) for (const line of e.diagnostics) stderr.write(`${line}
17876
+ `);
17715
17877
  return { label: makeLabel("", fontname, fontsize, fontcolor, measurer), rv: HTML_PARSE_FATAL };
17716
17878
  }
17717
17879
  if (lbl.kind === "table") inheritTablePenColor(lbl.table, pencolor);
17718
17880
  const rv = Number(lexWarn) | sizeHtmlLabel(lbl, measurer, {
17719
17881
  fontsize,
17720
17882
  fontname,
17721
- imageSizer
17883
+ imageSizer,
17884
+ stderr
17722
17885
  });
17723
17886
  const placed = posHtmlLabel(lbl, { fontname, fontsize, fontcolor }, measurer);
17724
17887
  const dim = lbl.dimen ?? { w: 0, h: 0 };
@@ -17917,8 +18080,11 @@ function makeLabel(text, fontname, fontsize, fontcolor, measurer) {
17917
18080
  function makeAnyLabel(content, isHtml, font, measurer, obj) {
17918
18081
  if (isHtml && content !== "") {
17919
18082
  const imageSizer = obj !== void 0 ? rootOf(obj).info.gvc?.imageSizer : void 0;
17920
- const { label, rv } = makeHtmlLabelRv(content, { ...font, pencolor: getPenColor(obj), imageSizer }, measurer);
17921
- if (rv !== 0 && obj !== void 0) console.error(inLabelOf(obj));
18083
+ const stderr = labelStderr();
18084
+ const { label, rv } = makeHtmlLabelTo(content, { ...font, pencolor: getPenColor(obj), imageSizer }, measurer, stderr);
18085
+ if (rv !== 0 && obj !== void 0) stderr.write(`${inLabelOf(obj)}
18086
+ `);
18087
+ stderr.flush();
17922
18088
  return label;
17923
18089
  }
17924
18090
  const subst2 = obj !== void 0 ? substObj(content, obj, false) : content;
@@ -24886,7 +25052,7 @@ function renderNodeLabel(n, coord, renderer, job) {
24886
25052
  renderLabel(label, coord, renderer, job);
24887
25053
  }
24888
25054
  }
24889
- function anchorAttr2(n, key) {
25055
+ function anchorAttr(n, key) {
24890
25056
  const v = nodeAttr(n, n.root, key);
24891
25057
  return v !== void 0 && v !== "" ? v : void 0;
24892
25058
  }
@@ -24896,13 +25062,13 @@ function resolveTooltip(n, tooltip) {
24896
25062
  return label?.text ?? "";
24897
25063
  }
24898
25064
  function beginNodeAnchor(n, renderer, job) {
24899
- const url = anchorAttr2(n, "href") ?? anchorAttr2(n, "URL");
24900
- const tooltip = anchorAttr2(n, "tooltip");
25065
+ const url = anchorAttr(n, "href") ?? anchorAttr(n, "URL");
25066
+ const tooltip = anchorAttr(n, "tooltip");
24901
25067
  if (url === void 0 && tooltip === void 0) return false;
24902
25068
  renderer.beginAnchor?.(
24903
25069
  url !== void 0 ? substObjAnchor(url, n) : "",
24904
25070
  resolveTooltip(n, tooltip),
24905
- anchorAttr2(n, "target") ?? "",
25071
+ anchorAttr(n, "target") ?? "",
24906
25072
  svgNodeId(n, job),
24907
25073
  job
24908
25074
  );