@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/render.js CHANGED
@@ -5653,9 +5653,11 @@ var StderrLines = class {
5653
5653
  writeLine;
5654
5654
  pending = "";
5655
5655
  write(text) {
5656
- const parts = (this.pending + text).split("\n");
5657
- this.pending = parts.pop() ?? "";
5658
- for (const line of parts) this.writeLine(line);
5656
+ this.pending += text;
5657
+ if (!this.pending.endsWith("\n")) return;
5658
+ const line = this.pending.slice(0, -1);
5659
+ this.pending = "";
5660
+ this.writeLine(line);
5659
5661
  }
5660
5662
  flush() {
5661
5663
  if (this.pending === "") return;
@@ -5663,6 +5665,16 @@ var StderrLines = class {
5663
5665
  this.pending = "";
5664
5666
  }
5665
5667
  };
5668
+ var consoleLine = (line) => {
5669
+ if (line.startsWith("Warning")) console.warn(line);
5670
+ else console.error(line);
5671
+ };
5672
+ var labelStderr = () => new StderrLines(consoleLine);
5673
+ var agerrLine = (out, msg) => {
5674
+ if (out === void 0) consoleLine(msg);
5675
+ else out.write(`${msg}
5676
+ `);
5677
+ };
5666
5678
 
5667
5679
  // src/common/htmltable-parse-state.ts
5668
5680
  var peek = (s) => s.tokens[s.pos];
@@ -5967,11 +5979,87 @@ function htmlEntityUTF8(s) {
5967
5979
  });
5968
5980
  }
5969
5981
 
5982
+ // src/common/htmltable-lex-attvalue.ts
5983
+ var XML_ERROR_UNDEFINED_ENTITY = "undefined entity";
5984
+ var XML_ERROR_BAD_CHAR_REF = "reference to invalid character number";
5985
+ var NAME_START = /[A-Za-z_:\u0080-￿]/;
5986
+ var NAME_CHAR = /[\w.:\u0080-￿-]/;
5987
+ var DEC_DIGIT = /[0-9]/;
5988
+ var HEX_DIGIT = /[0-9A-Fa-f]/;
5989
+ var NON_XML = /[\x00-\x08\x0b\x0c\x0e-\x1f]/;
5990
+ function scanDigits(text, i, digit) {
5991
+ if (i >= text.length) return { partial: true };
5992
+ if (!digit.test(text[i])) return { invalid: i };
5993
+ for (let k = i + 1; k < text.length; k++) {
5994
+ if (text[k] === ";") return k + 1;
5995
+ if (!digit.test(text[k])) return { invalid: k };
5996
+ }
5997
+ return { partial: true };
5998
+ }
5999
+ function scanRef(text, i) {
6000
+ const c = text[i];
6001
+ if (c === void 0) return { partial: true };
6002
+ if (c === "#") return text[i + 1] === "x" ? scanDigits(text, i + 2, HEX_DIGIT) : scanDigits(text, i + 1, DEC_DIGIT);
6003
+ if (!NAME_START.test(c)) return { invalid: i };
6004
+ for (let k = i + 1; k < text.length; k++) {
6005
+ if (text[k] === ";") return k + 1;
6006
+ if (!NAME_CHAR.test(text[k])) return { invalid: k };
6007
+ }
6008
+ return { partial: true };
6009
+ }
6010
+ function scanAttValue(text, j) {
6011
+ const q = text[j];
6012
+ let k = j + 1;
6013
+ for (; ; ) {
6014
+ const c = text[k];
6015
+ if (c === void 0) return { partial: true };
6016
+ if (c === q) return { close: k };
6017
+ if (c === "<" || NON_XML.test(c)) return { invalid: k };
6018
+ if (c !== "&") {
6019
+ k++;
6020
+ continue;
6021
+ }
6022
+ const r = scanRef(text, k + 1);
6023
+ if (typeof r !== "number") return r;
6024
+ k = r;
6025
+ }
6026
+ }
6027
+ function charRefNumber(ref) {
6028
+ const hex = ref.startsWith("&#x");
6029
+ const n = parseInt(ref.slice(hex ? 3 : 2, -1), hex ? 16 : 10);
6030
+ if (n >= 1114112) return -1;
6031
+ if (n >= 55296 && n <= 57343) return -1;
6032
+ if (n < 32 && NON_XML.test(String.fromCharCode(n))) return -1;
6033
+ return n === 65534 || n === 65535 ? -1 : n;
6034
+ }
6035
+ var PREDEFINED = { lt: "<", gt: ">", amp: "&", quot: '"', apos: "'" };
6036
+ var VALUE_PIECE = /&#x?[0-9A-Fa-f]+;|&[^;]+;|\r\n|[\t\n\r]/g;
6037
+ function attValueError(raw, base) {
6038
+ for (const m of raw.matchAll(VALUE_PIECE)) {
6039
+ const ref = m[0];
6040
+ if (!ref.startsWith("&")) continue;
6041
+ if (ref.startsWith("&#")) {
6042
+ if (charRefNumber(ref) < 0) return { message: XML_ERROR_BAD_CHAR_REF, offset: base + m.index };
6043
+ } else if (!Object.hasOwn(PREDEFINED, ref.slice(1, -1))) {
6044
+ return { message: XML_ERROR_UNDEFINED_ENTITY };
6045
+ }
6046
+ }
6047
+ return void 0;
6048
+ }
6049
+ function decodeAttValue(raw) {
6050
+ return raw.replace(VALUE_PIECE, (m) => {
6051
+ if (!m.startsWith("&")) return " ";
6052
+ if (m.startsWith("&#")) return String.fromCodePoint(charRefNumber(m));
6053
+ return PREDEFINED[m.slice(1, -1)];
6054
+ });
6055
+ }
6056
+
5970
6057
  // src/common/htmltable-lex-expat.ts
5971
6058
  var XML_ERROR_INVALID_TOKEN = "not well-formed (invalid token)";
5972
6059
  var XML_CONTEXT_BYTES = 1024;
5973
6060
  var INIT_BUFFER_SIZE = 1024;
5974
- var COMPLETE_END = (end, dup) => dup === void 0 ? { kind: "complete", end } : { kind: "complete", end, dup };
6061
+ var XML_ERROR_DUPLICATE_ATTRIBUTE = "duplicate attribute";
6062
+ var COMPLETE_END = (end, attError) => attError === void 0 ? { kind: "complete", end } : { kind: "complete", end, attError };
5975
6063
  var PARTIAL = { kind: "partial" };
5976
6064
  var INVALID = (offset) => ({ kind: "invalid", offset });
5977
6065
  var XML_NAME = /^[A-Za-z_:\u0080-\uFFFF][\w.:\u0080-\uFFFF-]*/;
@@ -5982,25 +6070,25 @@ function skipSpace(text, i) {
5982
6070
  return j;
5983
6071
  }
5984
6072
  var byteLength = (s) => new TextEncoder().encode(s).length;
5985
- function fedBytes(unit, isText) {
5986
- if (!isText) return byteLength(unit);
5987
- let text = unit.replace(/&([^;&<]*);/g, (m, name) => {
6073
+ function fedText(piece, endsUnit) {
6074
+ const text = piece.replace(/&([^;&<]*);/g, (m, name) => {
5988
6075
  return name.length >= 2 && Object.hasOwn(HTML_ENTITIES, name) ? `&#${HTML_ENTITIES[name]};` : m;
5989
6076
  });
5990
- if (text.endsWith("]")) text = `${text.slice(0, -1)}&#93;`;
5991
- return byteLength(text);
6077
+ return endsUnit && text.endsWith("]") ? `${text.slice(0, -1)}&#93;` : text;
6078
+ }
6079
+ function fedBytes(unit, isText) {
6080
+ return byteLength(isText ? fedText(unit, true) : unit);
5992
6081
  }
5993
6082
  function scanValue(text, j) {
5994
6083
  const q = text[j];
5995
6084
  if (q !== '"' && q !== "'") return INVALID(j);
5996
- const close = text.indexOf(q, j + 1);
5997
- if (close < 0) {
5998
- const lt = text.indexOf("<", j + 1);
5999
- return lt >= 0 ? INVALID(lt) : PARTIAL;
6000
- }
6085
+ const v = scanAttValue(text, j);
6086
+ if ("partial" in v) return PARTIAL;
6087
+ if ("invalid" in v) return INVALID(v.invalid);
6088
+ const close = v.close;
6001
6089
  const next = skipSpace(text, close + 1);
6002
6090
  if (next === close + 1 && !">/".includes(text[next] ?? ">")) return INVALID(next);
6003
- return next;
6091
+ return close;
6004
6092
  }
6005
6093
  function scanPair(text, i) {
6006
6094
  const name = XML_NAME.exec(text.slice(i))?.[0];
@@ -6010,8 +6098,9 @@ function scanPair(text, i) {
6010
6098
  if (text[eq] !== "=") return INVALID(eq);
6011
6099
  const j = skipSpace(text, eq + 1);
6012
6100
  if (j >= text.length) return PARTIAL;
6013
- const next = scanValue(text, j);
6014
- return typeof next === "number" ? { name, next } : next;
6101
+ const close = scanValue(text, j);
6102
+ if (typeof close !== "number") return close;
6103
+ return { name, next: skipSpace(text, close + 1), value: { start: j + 1, end: close } };
6015
6104
  }
6016
6105
  function tagEdge(text, i) {
6017
6106
  const c = text[i];
@@ -6021,18 +6110,23 @@ function tagEdge(text, i) {
6021
6110
  if (i + 1 >= text.length) return PARTIAL;
6022
6111
  return text[i + 1] === ">" ? COMPLETE_END(i + 2) : void 0;
6023
6112
  }
6024
- function scanAttributes(text, from) {
6113
+ function storeAttError(text, p, at, pair, seen) {
6114
+ if (seen.has(pair.name)) return { message: XML_ERROR_DUPLICATE_ATTRIBUTE, offset: at };
6115
+ seen.add(pair.name);
6116
+ const err = attValueError(text.slice(pair.value.start, pair.value.end), pair.value.start);
6117
+ return err === void 0 ? void 0 : { message: err.message, offset: err.offset ?? p };
6118
+ }
6119
+ function scanAttributes(text, p, from) {
6025
6120
  const seen = /* @__PURE__ */ new Set();
6026
- let dup;
6121
+ let attError;
6027
6122
  let i = skipSpace(text, from);
6028
6123
  for (; ; ) {
6029
6124
  const edge = tagEdge(text, i);
6030
- if (edge?.kind === "complete") return COMPLETE_END(edge.end, dup);
6125
+ if (edge?.kind === "complete") return COMPLETE_END(edge.end, attError);
6031
6126
  if (edge !== void 0) return edge;
6032
6127
  const pair = scanPair(text, i);
6033
6128
  if ("kind" in pair) return pair;
6034
- if (seen.has(pair.name)) dup ??= i;
6035
- seen.add(pair.name);
6129
+ attError ??= storeAttError(text, p, i, pair, seen);
6036
6130
  i = pair.next;
6037
6131
  }
6038
6132
  }
@@ -6047,7 +6141,7 @@ function scanStartTag(text, p) {
6047
6141
  const c = text[name.next];
6048
6142
  if (c === void 0) return PARTIAL;
6049
6143
  if (!isSpace(c) && c !== ">" && c !== "/") return INVALID(name.next);
6050
- return scanAttributes(text, name.next);
6144
+ return scanAttributes(text, p, name.next);
6051
6145
  }
6052
6146
  function scanEndTag(text, p) {
6053
6147
  const name = scanName(text, p + 2);
@@ -6090,26 +6184,45 @@ function scanMarkup(text, p) {
6090
6184
  if (c === "!") return { scan: scanDeclaration(text, p), kind: "tag" };
6091
6185
  return { scan: scanStartTag(text, p), kind: "tag" };
6092
6186
  }
6093
- function scanContent(text, base) {
6187
+ var CDATA_OPEN = "<![CDATA[";
6188
+ var CDATA_CLOSE = "]]>";
6189
+ function scanCdata(text, p, base, dataOf, tokens) {
6190
+ const close = text.indexOf(CDATA_CLOSE, p);
6191
+ const end = close < 0 ? text.length : close;
6192
+ if (end > p) tokens.push({ kind: "cdata", start: base + p, end: base + end, data: dataOf(base + p, base + end) });
6193
+ return close < 0 ? -1 : close + CDATA_CLOSE.length;
6194
+ }
6195
+ function scanText(text, p, base, tokens) {
6196
+ const e = text.indexOf("<", p);
6197
+ const end = e < 0 ? text.length : e;
6198
+ tokens.push({ kind: "text", start: base + p, end: base + end });
6199
+ return end;
6200
+ }
6201
+ function scanContent(text, base, inCdata, dataOf) {
6094
6202
  const tokens = [];
6095
6203
  let p = 0;
6204
+ let inSection = inCdata;
6096
6205
  while (p < text.length) {
6206
+ if (inSection || text.startsWith(CDATA_OPEN, p)) {
6207
+ const after2 = scanCdata(text, inSection ? p : p + CDATA_OPEN.length, base, dataOf, tokens);
6208
+ if (after2 < 0) return { tokens, consumed: text.length, inCdata: true };
6209
+ inSection = false;
6210
+ p = after2;
6211
+ continue;
6212
+ }
6097
6213
  if (text[p] !== "<") {
6098
- const e = text.indexOf("<", p);
6099
- const end = e < 0 ? text.length : e;
6100
- tokens.push({ kind: "text", start: base + p, end: base + end });
6101
- p = end;
6214
+ p = scanText(text, p, base, tokens);
6102
6215
  continue;
6103
6216
  }
6104
6217
  const { scan, kind } = scanMarkup(text, p);
6105
- if (scan.kind === "invalid") return { tokens, consumed: p, invalid: base + scan.offset };
6106
- if (scan.kind === "partial") return { tokens, consumed: p };
6218
+ if (scan.kind === "invalid") return { tokens, consumed: p, invalid: base + scan.offset, inCdata: false };
6219
+ if (scan.kind === "partial") return { tokens, consumed: p, inCdata: false };
6107
6220
  const tok = { kind, start: base + p, end: base + scan.end };
6108
- if (scan.dup !== void 0) tok.dup = base + scan.dup;
6221
+ if (scan.attError !== void 0) tok.attError = { ...scan.attError, offset: base + scan.attError.offset };
6109
6222
  tokens.push(tok);
6110
6223
  p = scan.end;
6111
6224
  }
6112
- return { tokens, consumed: p };
6225
+ return { tokens, consumed: p, inCdata: inSection };
6113
6226
  }
6114
6227
  var InputBuffer = class {
6115
6228
  size = 0;
@@ -6160,38 +6273,61 @@ var ExpatFeed = class {
6160
6273
  buffer = new InputBuffer();
6161
6274
  heldStart = 0;
6162
6275
  fedEnd = 0;
6276
+ inCdata = false;
6277
+ /** Source ranges of the text units fed so far: their bytes went through findNext's rewrite. */
6278
+ textUnits = [];
6163
6279
  /** Start of the token expat still holds, or undefined when it holds nothing. */
6164
6280
  get held() {
6165
6281
  return this.heldStart < this.fedEnd ? this.heldStart : void 0;
6166
6282
  }
6167
- /** One `XML_Parse(parser, src[start, end), nbytes, 0)`. */
6168
- feed(start, end, nbytes) {
6169
- this.buffer.append(nbytes);
6283
+ /** One `XML_Parse(parser, src[start, end), nbytes, 0)`; `isText` for a text unit. */
6284
+ feed(start, end, isText) {
6285
+ if (isText) this.textUnits.push([start, end]);
6286
+ this.buffer.append(fedBytes(this.src.slice(start, end), isText));
6170
6287
  this.fedEnd = end;
6171
6288
  if (!this.buffer.enough) return { tokens: [] };
6172
6289
  const text = this.src.slice(this.heldStart, end);
6173
- const scan = scanContent(text, this.heldStart);
6290
+ const scan = scanContent(text, this.heldStart, this.inCdata, (a, b) => this.fedBetween(a, b));
6174
6291
  if (scan.invalid !== void 0) {
6175
6292
  return { tokens: scan.tokens, invalid: { message: XML_ERROR_INVALID_TOKEN, offset: scan.invalid } };
6176
6293
  }
6294
+ this.inCdata = scan.inCdata;
6177
6295
  this.heldStart += scan.consumed;
6178
6296
  this.buffer.consumedTo(byteLength(this.src.slice(this.heldStart, end)), scan.consumed > 0);
6179
6297
  return { tokens: scan.tokens };
6180
6298
  }
6299
+ /** What expat read for source offsets [start, end): text-unit pieces as findNext rewrote them. */
6300
+ fedBetween(start, end) {
6301
+ let out = "";
6302
+ let p = start;
6303
+ for (const [us, ue] of this.textUnits) {
6304
+ if (ue <= p || us >= end) continue;
6305
+ if (us > p) out += this.src.slice(p, us);
6306
+ const e = Math.min(ue, end);
6307
+ out += fedText(this.src.slice(Math.max(us, p), e), e === ue);
6308
+ p = e;
6309
+ }
6310
+ return out + this.src.slice(p, end);
6311
+ }
6181
6312
  };
6182
6313
  var XML_PREDEFINED_ENTITIES = /* @__PURE__ */ new Set(["lt", "gt", "amp", "quot", "apos"]);
6183
6314
  var ENTITY_NAME = /^[A-Za-z_:][\w.:-]*$/;
6184
- function findUndefinedEntity(text) {
6315
+ var CHAR_REF = /^&#(?:x[0-9A-Fa-f]+|[0-9]+);/;
6316
+ function textRefError(text) {
6185
6317
  for (let t = text.indexOf("&"); t >= 0; t = text.indexOf("&", t + 1)) {
6186
- if (text[t + 1] === "#") continue;
6318
+ if (text[t + 1] === "#") {
6319
+ const ref = CHAR_REF.exec(text.slice(t))?.[0];
6320
+ if (ref !== void 0 && charRefNumber(ref) < 0) return { message: XML_ERROR_BAD_CHAR_REF, offset: t };
6321
+ continue;
6322
+ }
6187
6323
  const semi = text.indexOf(";", t + 1);
6188
6324
  if (semi < 0) continue;
6189
6325
  const key = text.slice(t + 1, semi);
6190
6326
  if (ENTITY_NAME.test(key) && !Object.hasOwn(HTML_ENTITIES, key) && !XML_PREDEFINED_ENTITIES.has(key)) {
6191
- return t;
6327
+ return { message: XML_ERROR_UNDEFINED_ENTITY, offset: t };
6192
6328
  }
6193
6329
  }
6194
- return -1;
6330
+ return void 0;
6195
6331
  }
6196
6332
  function parseTagChunk(chunk) {
6197
6333
  if (!chunk.endsWith(">")) return void 0;
@@ -6202,6 +6338,46 @@ function parseTagChunk(chunk) {
6202
6338
  return { close, selfClose: !close && body.endsWith("/"), name };
6203
6339
  }
6204
6340
 
6341
+ // src/common/htmltable-lex-chardata.ts
6342
+ var initialCharData = () => ({ inCell: true, xb: "" });
6343
+ function startInCell(name, inCell) {
6344
+ if (name === "TABLE" || name === "TR" || name === "TH") return false;
6345
+ return name === "TD" ? true : inCell;
6346
+ }
6347
+ function endInCell(name, inCell) {
6348
+ if (name === "TABLE") return true;
6349
+ return name === "TD" ? false : inCell;
6350
+ }
6351
+ function tagInCell(st, tag) {
6352
+ const name = tag.name.toUpperCase();
6353
+ if (tag.close) {
6354
+ st.inCell = endInCell(name, st.inCell);
6355
+ return;
6356
+ }
6357
+ st.inCell = startInCell(name, st.inCell);
6358
+ if (tag.selfClose) st.inCell = endInCell(name, st.inCell);
6359
+ }
6360
+ function keepLostText(st, lost) {
6361
+ for (const t of lost) if (t.type === "text") st.xb += t.value;
6362
+ }
6363
+ function releaseXb(st, first) {
6364
+ if (st.xb === "") return;
6365
+ if (first.type === "text") first.value = st.xb + first.value;
6366
+ else if (first.type === "open" && first.tag === "TABLE") first.heldText = st.xb;
6367
+ else return;
6368
+ st.xb = "";
6369
+ }
6370
+ function cleanText(decoded) {
6371
+ return decoded.replace(/[\x00-\x1f]/g, "");
6372
+ }
6373
+ function textTokens(raw) {
6374
+ return charDataTokens(htmlEntityUTF8(raw));
6375
+ }
6376
+ function charDataTokens(decoded) {
6377
+ const clean = cleanText(decoded);
6378
+ return clean.length > 0 ? [{ type: "text", value: clean }] : [];
6379
+ }
6380
+
6205
6381
  // src/common/htmltable-lex-units.ts
6206
6382
  var UNCLOSED_COMMENT = "Warning: Unclosed comment\n";
6207
6383
  var LABEL_CLOSED = "Warning: Label closed before end of HTML element\n";
@@ -6291,7 +6467,7 @@ function parseAttrPairs(raw) {
6291
6467
  if (q !== '"' && q !== "'") throw new HtmlParseError(name);
6292
6468
  const end = raw.indexOf(q, i + 1);
6293
6469
  if (end < 0) throw new HtmlParseError(name);
6294
- out.push([name, raw.slice(i + 1, end)]);
6470
+ out.push([name, decodeAttValue(raw.slice(i + 1, end))]);
6295
6471
  i = end + 1;
6296
6472
  }
6297
6473
  return out;
@@ -6306,20 +6482,17 @@ function parseCloseToken(inner) {
6306
6482
  checkTag(tag);
6307
6483
  return { type: "close", tag: normalizeTag(tag) };
6308
6484
  }
6309
- function cleanText(raw) {
6310
- const isKeep = (c) => c === " " || c === " " || c === "\n" || c === "\r";
6311
- return raw.replace(/[\x00-\x1f\x7f]/g, (c) => isKeep(c) ? c : "");
6312
- }
6313
- function textTokens(raw) {
6314
- const clean = htmlEntityUTF8(cleanText(raw));
6315
- return clean.length > 0 ? [{ type: "text", value: clean }] : [];
6316
- }
6485
+ var EMPTY_ELEMENTS = /* @__PURE__ */ new Set(["BR", "HR", "VR", "IMG"]);
6317
6486
  function tagTokens(text) {
6318
6487
  const inner = text.slice(1, -1).trim();
6319
6488
  if (inner.startsWith("/")) return [parseCloseToken(inner)];
6320
6489
  if (inner.endsWith("/")) {
6321
6490
  const open = parseOpenToken(inner.slice(0, -1).trim());
6322
- return [open, { type: "close", tag: open.tag }];
6491
+ if (EMPTY_ELEMENTS.has(open.tag)) return [open, { type: "close", tag: open.tag }];
6492
+ const close = { type: "close", tag: open.tag };
6493
+ if (open.warnings !== void 0) close.warnings = open.warnings;
6494
+ if (open.warn === true) close.warn = true;
6495
+ return [close];
6323
6496
  }
6324
6497
  return [parseOpenToken(inner)];
6325
6498
  }
@@ -6336,9 +6509,7 @@ function parseOpenToken(inner) {
6336
6509
  checkTag(tag);
6337
6510
  return openToken(normalizeTag(tag), sp === -1 ? "" : inner.slice(sp + 1));
6338
6511
  }
6339
- var XML_ERROR_UNDEFINED_ENTITY = "undefined entity";
6340
6512
  var XML_ERROR_TAG_MISMATCH = "mismatched tag";
6341
- var XML_ERROR_DUPLICATE_ATTRIBUTE = "duplicate attribute";
6342
6513
  var SYNTAX_ERROR = "syntax error";
6343
6514
  var HtmlLexError = class extends HtmlParseError {
6344
6515
  diagnostics;
@@ -6381,7 +6552,8 @@ function checkTagToken(site) {
6381
6552
  throw htmlErrorInLine(XML_ERROR_TAG_MISMATCH, lineAt(src, tok.start), context);
6382
6553
  }
6383
6554
  } else {
6384
- if (tok.dup !== void 0) throw htmlErrorInLine(XML_ERROR_DUPLICATE_ATTRIBUTE, lineAt(src, tok.dup), context);
6555
+ const err = tok.attError;
6556
+ if (err !== void 0) throw htmlErrorInLine(err.message, lineAt(src, err.offset), context);
6385
6557
  if (!tag.selfClose) st.stack.push(tag.name);
6386
6558
  }
6387
6559
  if (KNOWN_TAGS.has(tag.name.toUpperCase())) return;
@@ -6392,14 +6564,13 @@ function eventTokens(site) {
6392
6564
  const { src, tok, st } = site;
6393
6565
  const text = src.slice(tok.start, tok.end);
6394
6566
  if (tok.kind === "comment" || tok.kind === "pi") return [];
6567
+ if (tok.kind === "cdata") return charDataTokens(tok.data ?? "");
6395
6568
  if (tok.kind === "tag") {
6396
6569
  checkTagToken(site);
6397
6570
  return tagTokens(text);
6398
6571
  }
6399
- const off = findUndefinedEntity(text);
6400
- if (off >= 0) {
6401
- throw htmlErrorInLine(XML_ERROR_UNDEFINED_ENTITY, lineAt(src, tok.start + off), st.prev + st.curr);
6402
- }
6572
+ const err = textRefError(text);
6573
+ if (err !== void 0) throw htmlErrorInLine(err.message, lineAt(src, tok.start + err.offset), st.prev + st.curr);
6403
6574
  return textTokens(text);
6404
6575
  }
6405
6576
  function attachCarry(carry, first) {
@@ -6417,7 +6588,13 @@ function absorb(carry, lost) {
6417
6588
  function eventGroups(run, res) {
6418
6589
  const groups = [];
6419
6590
  for (const tok of res.tokens) {
6420
- const tokens = eventTokens({ src: run.src, tok, st: run.st });
6591
+ let tokens = eventTokens({ src: run.src, tok, st: run.st });
6592
+ if (tok.kind === "tag") {
6593
+ const tag = parseTagChunk(run.src.slice(tok.start, tok.end));
6594
+ if (tag !== void 0) tagInCell(run.cd, tag);
6595
+ } else if (!run.cd.inCell) {
6596
+ tokens = [];
6597
+ }
6421
6598
  if (tokens.length > 0) groups.push({ tokens, tok });
6422
6599
  }
6423
6600
  if (res.invalid !== void 0) {
@@ -6428,6 +6605,7 @@ function eventGroups(run, res) {
6428
6605
  }
6429
6606
  function deliver(run, last) {
6430
6607
  const first = last.tokens[0];
6608
+ releaseXb(run.cd, first);
6431
6609
  attachCarry(run.carry, first);
6432
6610
  const info = { src: run.src, pos: last.tok.start, end: last.tok.end, context: run.st.prev + run.st.curr };
6433
6611
  const prev = run.tokens.at(-1);
@@ -6442,7 +6620,10 @@ function deliver(run, last) {
6442
6620
  function runEvents(run, res) {
6443
6621
  const groups = eventGroups(run, res);
6444
6622
  const last = groups.pop();
6445
- for (const g of groups) absorb(run.carry, g.tokens);
6623
+ for (const g of groups) {
6624
+ absorb(run.carry, g.tokens);
6625
+ keepLostText(run.cd, g.tokens);
6626
+ }
6446
6627
  if (last !== void 0) deliver(run, last);
6447
6628
  }
6448
6629
  function appendString(into, more) {
@@ -6473,7 +6654,8 @@ function tokenizeDeferred(src, label = { start: 0, end: src.length }) {
6473
6654
  tokens: [],
6474
6655
  st: { stack: [], prev: "", curr: "" },
6475
6656
  expat: new ExpatFeed(src),
6476
- carry: { warnings: [], warn: false }
6657
+ carry: { warnings: [], warn: false },
6658
+ cd: initialCharData()
6477
6659
  };
6478
6660
  let error;
6479
6661
  try {
@@ -6482,8 +6664,7 @@ function tokenizeDeferred(src, label = { start: 0, end: src.length }) {
6482
6664
  run.st.curr = src.slice(u.start, u.end);
6483
6665
  run.carry.warnings.push(...u.warnings);
6484
6666
  if (u.warn) run.carry.warn = true;
6485
- const nbytes = fedBytes(run.st.curr, !run.st.curr.startsWith("<"));
6486
- runEvents(run, run.expat.feed(u.start, u.end, nbytes));
6667
+ runEvents(run, run.expat.feed(u.start, u.end, !run.st.curr.startsWith("<")));
6487
6668
  }
6488
6669
  const held = run.expat.held;
6489
6670
  if (held !== void 0) error = unfinishedError(run, held);
@@ -6499,9 +6680,6 @@ function tokenizeDeferred(src, label = { start: 0, end: src.length }) {
6499
6680
  }
6500
6681
 
6501
6682
  // src/common/htmltable-parse-attrs.ts
6502
- function anchorAttr(v) {
6503
- return v === void 0 ? void 0 : htmlEntityUTF8(v);
6504
- }
6505
6683
  var parseAlign = (v) => {
6506
6684
  const u = v.toUpperCase();
6507
6685
  if (u === "LEFT") return "left";
@@ -6509,6 +6687,7 @@ var parseAlign = (v) => {
6509
6687
  if (u === "CENTER") return "center";
6510
6688
  return void 0;
6511
6689
  };
6690
+ var parseCellAlign = (v) => v.toUpperCase() === "TEXT" ? "text" : parseAlign(v);
6512
6691
  var parseVAlign = (v) => {
6513
6692
  const u = v.toUpperCase();
6514
6693
  if (u === "TOP") return "top";
@@ -6542,7 +6721,7 @@ var buildCell = (content, a) => ({
6542
6721
  kind: "cell",
6543
6722
  content,
6544
6723
  port: a["port"],
6545
- align: parseAlign(a["align"] !== void 0 ? a["align"] : ""),
6724
+ align: parseCellAlign(a["align"] !== void 0 ? a["align"] : ""),
6546
6725
  valign: parseVAlign(a["valign"] !== void 0 ? a["valign"] : ""),
6547
6726
  balign: parseAlign(a["balign"] !== void 0 ? a["balign"] : ""),
6548
6727
  bgcolor: a["bgcolor"],
@@ -6558,9 +6737,9 @@ var buildCell = (content, a) => ({
6558
6737
  fixedsize: parseFixedSize(a),
6559
6738
  colspan: num(a["colspan"]),
6560
6739
  rowspan: num(a["rowspan"]),
6561
- href: anchorAttr(a["href"]),
6740
+ href: a["href"],
6562
6741
  title: parseTitle(a),
6563
- target: anchorAttr(a["target"]),
6742
+ target: a["target"],
6564
6743
  id: a["id"]
6565
6744
  });
6566
6745
  var buildTable = (rows, a) => ({
@@ -6578,9 +6757,9 @@ var buildTable = (rows, a) => ({
6578
6757
  fixedsize: parseFixedSize(a),
6579
6758
  width: num(a["width"]),
6580
6759
  height: num(a["height"]),
6581
- href: anchorAttr(a["href"]),
6760
+ href: a["href"],
6582
6761
  title: parseTitle(a),
6583
- target: anchorAttr(a["target"]),
6762
+ target: a["target"],
6584
6763
  id: a["id"],
6585
6764
  port: a["port"],
6586
6765
  sides: parseSides(a["sides"]),
@@ -6648,7 +6827,8 @@ var tableFont = (fontStack) => {
6648
6827
  var MSG_SYNTAX_ERROR = "syntax error";
6649
6828
  var MSG_TEXT_BEFORE_TABLE = "Syntax error: non-space string used before <TABLE>";
6650
6829
  var MSG_TEXT_AFTER_TABLE = "Syntax error: non-space string used after </TABLE>";
6651
- var nonSpace = (text) => /[^ \t\n\r]/.test(text);
6830
+ var nonSpace = (text) => /[^ ]/.test(text);
6831
+ var heldNonSpace = (tbl) => tbl?.type === "open" && nonSpace(tbl.heldText ?? "");
6652
6832
  var parseError = (s, tok, message) => {
6653
6833
  if (tok !== void 0) emitWarnings(s, tok);
6654
6834
  else emitEof(s);
@@ -6669,41 +6849,29 @@ var applyBrTag = (s, t, fontStack, items) => {
6669
6849
  items.push({ br: true, brAlign: parseAlign(t.attrs["align"] ?? ""), ...fontItemProps(font) });
6670
6850
  consumeClose(s, "BR");
6671
6851
  };
6672
- var applyFontTag = (s, t, fontStack, items) => {
6673
- consume(s);
6674
- const font = fontStack[fontStack.length - 1] ?? {};
6675
- fontStack.push(mergeFontState(font, {
6676
- fontColor: t.attrs["color"],
6677
- fontFace: t.attrs["face"],
6678
- fontSize: num(t.attrs["point-size"])
6679
- }));
6852
+ var parseStyledText = (s, tag, fontStack, items) => {
6680
6853
  const inner = parseText(s, fontStack);
6681
6854
  fontStack.pop();
6682
- items.push(...inner.items);
6683
6855
  const nxt = peek(s);
6684
- if (nxt?.type === "close" && nxt.tag === "FONT") consume(s);
6856
+ if (inner.items.length === 0 || nxt?.type !== "close" || nxt.tag !== tag) {
6857
+ throw parseError(s, nxt, MSG_SYNTAX_ERROR);
6858
+ }
6859
+ items.push(...inner.items);
6860
+ consume(s);
6685
6861
  };
6686
- var applyInlineTag = (s, t, fontStack, items) => {
6862
+ var applyStyleTag = (s, t, fontStack, items) => {
6687
6863
  consume(s);
6688
- const font = fontStack[fontStack.length - 1] ?? {};
6689
- fontStack.push(mergeFontState(font, inlineFontState(t.tag, t.attrs)));
6690
- const inner = parseText(s, fontStack);
6691
- fontStack.pop();
6692
- items.push(...inner.items);
6693
- const nxt = peek(s);
6694
- if (nxt?.type === "close" && nxt.tag === t.tag) consume(s);
6864
+ const own = t.tag === "FONT" ? { fontColor: t.attrs["color"], fontFace: t.attrs["face"], fontSize: num(t.attrs["point-size"]) } : inlineFontState(t.tag, t.attrs);
6865
+ fontStack.push(mergeFontState(fontStack[fontStack.length - 1] ?? {}, own));
6866
+ parseStyledText(s, t.tag, fontStack, items);
6695
6867
  };
6696
6868
  var applyOpenTag = (s, t, fontStack, items) => {
6697
6869
  if (t.tag === "BR") {
6698
6870
  applyBrTag(s, t, fontStack, items);
6699
6871
  return true;
6700
6872
  }
6701
- if (t.tag === "FONT") {
6702
- applyFontTag(s, t, fontStack, items);
6703
- return true;
6704
- }
6705
- if (isInlineTag(t.tag)) {
6706
- applyInlineTag(s, t, fontStack, items);
6873
+ if (t.tag === "FONT" || isInlineTag(t.tag)) {
6874
+ applyStyleTag(s, t, fontStack, items);
6707
6875
  return true;
6708
6876
  }
6709
6877
  return false;
@@ -6746,7 +6914,7 @@ var parseFontTable = (s, open, fontStack) => {
6746
6914
  fontStack.push(wrapperFont(open, fontStack));
6747
6915
  const textBefore = skipStrings(s);
6748
6916
  const tblTok = peek(s);
6749
- if (textBefore && tblTok !== void 0) throw parseError(s, tblTok, MSG_TEXT_BEFORE_TABLE);
6917
+ if ((textBefore || heldNonSpace(tblTok)) && tblTok !== void 0) throw parseError(s, tblTok, MSG_TEXT_BEFORE_TABLE);
6750
6918
  const table = parseTable(s, fontStack);
6751
6919
  const textAfter = skipStrings(s);
6752
6920
  const close = peek(s);
@@ -6763,11 +6931,11 @@ var rejectTableAfterTag = (s, start) => {
6763
6931
  throw parseError(s, nxt, MSG_SYNTAX_ERROR);
6764
6932
  }
6765
6933
  };
6766
- var parseImgContent = (s, t, cellAttrs) => {
6934
+ var parseImgContent = (s, t) => {
6767
6935
  consume(s);
6768
6936
  const img = {
6769
6937
  kind: "image",
6770
- src: cellAttrs["src"] ?? t.attrs["src"] ?? "",
6938
+ src: t.attrs["src"] ?? "",
6771
6939
  scale: t.attrs["scale"]
6772
6940
  };
6773
6941
  consumeClose(s, "IMG");
@@ -6775,7 +6943,7 @@ var parseImgContent = (s, t, cellAttrs) => {
6775
6943
  };
6776
6944
  var scanCellTable = (s, t, fontStack, st) => {
6777
6945
  if (st.kind === "image" || st.kind === "table") throw parseError(s, t, MSG_SYNTAX_ERROR);
6778
- if (st.textNonSpace) throw parseError(s, t, MSG_TEXT_BEFORE_TABLE);
6946
+ if (st.textNonSpace || heldNonSpace(t)) throw parseError(s, t, MSG_TEXT_BEFORE_TABLE);
6779
6947
  const tbl = parseTable(s, fontStack);
6780
6948
  st.kind = "table";
6781
6949
  return [tbl];
@@ -6795,12 +6963,12 @@ var scanAfterTable = (s, t, st) => {
6795
6963
  if (nonSpace(t.value)) st.afterNonSpace = true;
6796
6964
  return [];
6797
6965
  };
6798
- var scanCellImage = (s, t, cellAttrs, st) => {
6966
+ var scanCellImage = (s, t, st) => {
6799
6967
  if (st.kind !== "none") throw parseError(s, t, MSG_SYNTAX_ERROR);
6800
6968
  st.kind = "image";
6801
- return [parseImgContent(s, t, cellAttrs)];
6969
+ return [parseImgContent(s, t)];
6802
6970
  };
6803
- var scanCellItem = (s, t, cellAttrs, fontStack, st) => {
6971
+ var scanCellItem = (s, t, fontStack, st) => {
6804
6972
  if (st.kind === "fonttable") throw parseError(s, t, MSG_SYNTAX_ERROR);
6805
6973
  if (st.kind === "table") return scanAfterTable(s, t, st);
6806
6974
  const wrapper = st.kind === "none" ? fontTableWrapper(s) : void 0;
@@ -6809,7 +6977,7 @@ var scanCellItem = (s, t, cellAttrs, fontStack, st) => {
6809
6977
  return [parseFontTable(s, wrapper, fontStack)];
6810
6978
  }
6811
6979
  if (t.type === "open" && t.tag === "TABLE") return scanCellTable(s, t, fontStack, st);
6812
- if (t.type === "open" && t.tag === "IMG") return scanCellImage(s, t, cellAttrs, st);
6980
+ if (t.type === "open" && t.tag === "IMG") return scanCellImage(s, t, st);
6813
6981
  if (st.kind === "image") throw parseError(s, t, MSG_SYNTAX_ERROR);
6814
6982
  return scanCellText(s, t, fontStack, st);
6815
6983
  };
@@ -6819,12 +6987,12 @@ var endsCell = (s, t, st) => {
6819
6987
  if (t.tag === "TD" && !afterText) return true;
6820
6988
  throw parseError(s, t, afterText ? MSG_TEXT_AFTER_TABLE : MSG_SYNTAX_ERROR);
6821
6989
  };
6822
- var parseCellContent = (s, cellAttrs, fontStack) => {
6990
+ var parseCellContent = (s, fontStack) => {
6823
6991
  const content = [];
6824
6992
  const st = { kind: "none", textNonSpace: false, afterNonSpace: false };
6825
6993
  for (let t = peek(s); t !== void 0; t = peek(s)) {
6826
6994
  if (endsCell(s, t, st)) break;
6827
- content.push(...scanCellItem(s, t, cellAttrs, fontStack, st));
6995
+ content.push(...scanCellItem(s, t, fontStack, st));
6828
6996
  }
6829
6997
  const nxt = peek(s);
6830
6998
  if (nxt?.type === "close" && nxt.tag === "TD") consume(s);
@@ -6832,7 +7000,7 @@ var parseCellContent = (s, cellAttrs, fontStack) => {
6832
7000
  if (tbl !== void 0) return [tbl];
6833
7001
  return content;
6834
7002
  };
6835
- var parseCell = (s, attrs, fontStack) => buildCell(parseCellContent(s, attrs, fontStack), attrs);
7003
+ var parseCell = (s, attrs, fontStack) => buildCell(parseCellContent(s, fontStack), attrs);
6836
7004
  var parseRowVr = (s, t, cells) => {
6837
7005
  const prev = cells[cells.length - 1];
6838
7006
  if (prev === void 0) throw parseError(s, t, MSG_SYNTAX_ERROR);
@@ -6930,14 +7098,14 @@ var consumeRowHr = (s, rows) => {
6930
7098
  var findFirstRealToken = (tokens, start) => {
6931
7099
  for (let i = start; i < tokens.length; i++) {
6932
7100
  const tk = tokens[i];
6933
- if (tk.type !== "text" || tk.value.trim() !== "") return tk;
7101
+ if (tk.type !== "text" || nonSpace(tk.value)) return tk;
6934
7102
  }
6935
7103
  return void 0;
6936
7104
  };
6937
7105
  var skipLeadingWs = (s) => {
6938
7106
  while (true) {
6939
7107
  const nxt = peek(s);
6940
- if (!nxt || nxt.type !== "text" || nxt.value.trim() !== "") break;
7108
+ if (!nxt || nxt.type !== "text" || nonSpace(nxt.value)) break;
6941
7109
  consume(s);
6942
7110
  }
6943
7111
  };
@@ -6963,6 +7131,7 @@ var parseFontTableLabel = (s, open, fontStack) => {
6963
7131
  };
6964
7132
  var parseTableLabel = (s, fontStack) => {
6965
7133
  skipLeadingWs(s);
7134
+ if (heldNonSpace(peek(s))) throw parseError(s, peek(s), MSG_TEXT_BEFORE_TABLE);
6966
7135
  const table = parseTable(s, fontStack);
6967
7136
  finishTableLabel(s);
6968
7137
  return { kind: "table", table };
@@ -6992,17 +7161,9 @@ var parseTokens = (s) => {
6992
7161
  if (firstReal?.type === "open" && firstReal.tag === "TABLE") return parseTableLabel(s, fontStack);
6993
7162
  return parseTextLabel(s, fontStack);
6994
7163
  };
6995
- var parseHtmlLabelRv = (src, writeLine = (line) => console.warn(line)) => {
7164
+ var parseHtmlLabelRv = (src, stderr) => {
6996
7165
  const { tokens, error, eof } = tokenizeDeferred(`<HTML>${src}</HTML>`, { start: 6, end: 6 + src.length });
6997
- const s = {
6998
- tokens,
6999
- pos: 0,
7000
- pending: error,
7001
- stderr: new StderrLines(writeLine),
7002
- emitted: /* @__PURE__ */ new WeakSet(),
7003
- warn: false,
7004
- eof
7005
- };
7166
+ const s = { tokens, pos: 0, pending: error, stderr, emitted: /* @__PURE__ */ new WeakSet(), warn: false, eof };
7006
7167
  try {
7007
7168
  const label = parseTokens(s);
7008
7169
  if (error !== void 0) throw error;
@@ -7013,11 +7174,9 @@ var parseHtmlLabelRv = (src, writeLine = (line) => console.warn(line)) => {
7013
7174
  throw error;
7014
7175
  }
7015
7176
  throw e;
7016
- } finally {
7017
- s.stderr?.flush();
7018
7177
  }
7019
7178
  };
7020
- var parseHtmlLabel = (src) => parseHtmlLabelRv(src, () => void 0).label;
7179
+ var parseHtmlLabel = (src) => parseHtmlLabelRv(src, new StderrLines(() => void 0)).label;
7021
7180
 
7022
7181
  // src/gvc/usershape.ts
7023
7182
  var activeSizer = null;
@@ -7213,7 +7372,7 @@ var sizeTextContent = (texts, measurer, env = defaultSizeEnv()) => {
7213
7372
  return { w, h };
7214
7373
  };
7215
7374
  var missingImages = /* @__PURE__ */ new WeakSet();
7216
- var sizeHtmlImg = (img, imageSizer) => {
7375
+ var sizeHtmlImg = (img, { imageSizer, stderr }) => {
7217
7376
  if (img.width !== void 0 && img.height !== void 0) return missingImages.has(img) ? 1 : 0;
7218
7377
  const sz = imageSizer !== void 0 ? imageSizer(img.src) : findImageSize(img.src);
7219
7378
  if (sz !== null) {
@@ -7221,7 +7380,7 @@ var sizeHtmlImg = (img, imageSizer) => {
7221
7380
  img.height = sz.h;
7222
7381
  return 0;
7223
7382
  }
7224
- console.error(`Error: No or improper image file="${img.src}"`);
7383
+ agerrLine(stderr, `Error: No or improper image file="${img.src}"`);
7225
7384
  img.width = 0;
7226
7385
  img.height = 0;
7227
7386
  missingImages.add(img);
@@ -7234,7 +7393,7 @@ var sizeContentItem = (item, measurer, env) => {
7234
7393
  return { ...item.dimen !== void 0 ? item.dimen : { w: 0, h: 0 }, rv };
7235
7394
  }
7236
7395
  if (item.kind === "image") {
7237
- const rv = sizeHtmlImg(item, env.imageSizer);
7396
+ const rv = sizeHtmlImg(item, env);
7238
7397
  return { w: item.width ?? 0, h: item.height ?? 0, rv };
7239
7398
  }
7240
7399
  return { w: 0, h: 0, rv: 0 };
@@ -7264,14 +7423,14 @@ var WARN_CELL_UNSPECIFIED = "Warning: fixed cell size with unspecified width or
7264
7423
  var WARN_TABLE_TOO_SMALL = "Warning: table size too small for content";
7265
7424
  var WARN_TABLE_UNSPECIFIED = "Warning: fixed table size with unspecified width or height";
7266
7425
  var sizeWarned = /* @__PURE__ */ new WeakSet();
7267
- var fixedCellCheck = (cell2, sz, warn) => {
7426
+ var fixedCellCheck = (cell2, sz, warn, out) => {
7268
7427
  if (!cell2.fixedsize) return { rv: 0, zero: false };
7269
7428
  if (cell2.width && cell2.height) {
7270
7429
  const small = (cell2.width < sz.w || cell2.height < sz.h) && cell2.content[0]?.kind !== "image";
7271
- if (small && warn) console.warn(WARN_CELL_TOO_SMALL);
7430
+ if (small && warn) agerrLine(out, WARN_CELL_TOO_SMALL);
7272
7431
  return { rv: small ? 1 : 0, zero: true };
7273
7432
  }
7274
- if (warn) console.warn(WARN_CELL_UNSPECIFIED);
7433
+ if (warn) agerrLine(out, WARN_CELL_UNSPECIFIED);
7275
7434
  return { rv: 1, zero: false };
7276
7435
  };
7277
7436
  var getCellSize = (cell2, tbl, measurer, env) => {
@@ -7287,7 +7446,7 @@ var getCellSize = (cell2, tbl, measurer, env) => {
7287
7446
  let szy = ch + margin;
7288
7447
  const warn = !sizeWarned.has(cell2);
7289
7448
  sizeWarned.add(cell2);
7290
- const fixed = fixedCellCheck(cell2, { w: szx, h: szy }, warn);
7449
+ const fixed = fixedCellCheck(cell2, { w: szx, h: szy }, warn, env.stderr);
7291
7450
  rv |= fixed.rv;
7292
7451
  if (fixed.zero) {
7293
7452
  szx = 0;
@@ -7381,22 +7540,22 @@ var layoutHtmlTable = (tbl, measurer, env = defaultSizeEnv()) => {
7381
7540
  const heights = setRowHeights(entries, nrows, spacing);
7382
7541
  return { entries, widths, heights, spacing, border: border2, rv };
7383
7542
  };
7384
- var warnFixedTable = (tbl, dims) => {
7543
+ var warnFixedTable = (tbl, dims, out) => {
7385
7544
  const warn = !sizeWarned.has(tbl);
7386
7545
  sizeWarned.add(tbl);
7387
7546
  if (tbl.fixedsize !== true) return 0;
7388
7547
  if (tbl.width && tbl.height) {
7389
7548
  if (tbl.width >= dims.wd && tbl.height >= dims.ht) return 0;
7390
- if (warn) console.warn(WARN_TABLE_TOO_SMALL);
7549
+ if (warn) agerrLine(out, WARN_TABLE_TOO_SMALL);
7391
7550
  return 1;
7392
7551
  }
7393
- if (warn) console.warn(WARN_TABLE_UNSPECIFIED);
7552
+ if (warn) agerrLine(out, WARN_TABLE_UNSPECIFIED);
7394
7553
  return 1;
7395
7554
  };
7396
7555
  var sizeTableBody = (tbl, measurer, env) => {
7397
7556
  const { entries, widths, heights, spacing, border: border2, rv } = layoutHtmlTable(tbl, measurer, env);
7398
7557
  if (entries.length === 0) {
7399
- const fixed2 = warnFixedTable(tbl, sumTableDims({ widths, heights, ncols: 0, nrows: 0, spacing, border: border2 }));
7558
+ const fixed2 = warnFixedTable(tbl, sumTableDims({ widths, heights, ncols: 0, nrows: 0, spacing, border: border2 }), env.stderr);
7400
7559
  tbl.dimen = { w: 0, h: 0 };
7401
7560
  return rv | fixed2;
7402
7561
  }
@@ -7406,7 +7565,7 @@ var sizeTableBody = (tbl, measurer, env) => {
7406
7565
  const { wd, ht } = sumTableDims({ widths, heights, ncols, nrows, spacing, border: border2 });
7407
7566
  const baseWd = tbl.width !== void 0 ? tbl.width : 0;
7408
7567
  const baseHt = tbl.height !== void 0 ? tbl.height : 0;
7409
- const fixed = warnFixedTable(tbl, { wd, ht });
7568
+ const fixed = warnFixedTable(tbl, { wd, ht }, env.stderr);
7410
7569
  const zeroContent = isTblFixed(tbl) && baseWd !== 0 && baseHt !== 0;
7411
7570
  tbl.dimen = {
7412
7571
  w: Math.max(zeroContent ? 0 : wd, baseWd),
@@ -7611,7 +7770,7 @@ function placeComplexRuns(runs, box, finfo, measurer) {
7611
7770
  function alignContentBox(box, cell2, w, h) {
7612
7771
  const out = { ll: { ...box.ll }, ur: { ...box.ur } };
7613
7772
  const delx = out.ur.x - out.ll.x - w;
7614
- if (delx > 0) {
7773
+ if (delx > 0 && cell2.align !== "text") {
7615
7774
  if (cell2.align === "left") out.ur.x -= delx;
7616
7775
  else if (cell2.align === "right") out.ll.x += delx;
7617
7776
  else {
@@ -7866,21 +8025,25 @@ function posHtmlLabel(label, finfo, measurer) {
7866
8025
  if (label.kind === "table") return withTableFont(env, label.table.font, "emit", () => posHtmlTable(label.table, env, measurer));
7867
8026
  return posTextLabel(label, finfo, measurer);
7868
8027
  }
8028
+
8029
+ // src/common/htmltable-label.ts
7869
8030
  var HTML_PARSE_FATAL = 3;
7870
- function makeHtmlLabelRv(content, finfo, measurer) {
8031
+ function makeHtmlLabelTo(content, finfo, measurer, stderr) {
7871
8032
  const { fontname, fontsize, fontcolor, imageSizer, pencolor } = finfo;
7872
8033
  let lbl, lexWarn;
7873
8034
  try {
7874
- ({ label: lbl, warn: lexWarn } = parseHtmlLabelRv(content));
8035
+ ({ label: lbl, warn: lexWarn } = parseHtmlLabelRv(content, stderr));
7875
8036
  } catch (e) {
7876
- if (e instanceof HtmlLexError) for (const line of e.diagnostics) console.error(line);
8037
+ if (e instanceof HtmlLexError) for (const line of e.diagnostics) stderr.write(`${line}
8038
+ `);
7877
8039
  return { label: makeLabel("", fontname, fontsize, fontcolor, measurer), rv: HTML_PARSE_FATAL };
7878
8040
  }
7879
8041
  if (lbl.kind === "table") inheritTablePenColor(lbl.table, pencolor);
7880
8042
  const rv = Number(lexWarn) | sizeHtmlLabel(lbl, measurer, {
7881
8043
  fontsize,
7882
8044
  fontname,
7883
- imageSizer
8045
+ imageSizer,
8046
+ stderr
7884
8047
  });
7885
8048
  const placed = posHtmlLabel(lbl, { fontname, fontsize, fontcolor }, measurer);
7886
8049
  const dim = lbl.dimen ?? { w: 0, h: 0 };
@@ -8517,8 +8680,11 @@ function makeLabel(text, fontname, fontsize, fontcolor, measurer) {
8517
8680
  function makeAnyLabel(content, isHtml, font, measurer, obj) {
8518
8681
  if (isHtml && content !== "") {
8519
8682
  const imageSizer = obj !== void 0 ? rootOf(obj).info.gvc?.imageSizer : void 0;
8520
- const { label, rv } = makeHtmlLabelRv(content, { ...font, pencolor: getPenColor(obj), imageSizer }, measurer);
8521
- if (rv !== 0 && obj !== void 0) console.error(inLabelOf(obj));
8683
+ const stderr = labelStderr();
8684
+ const { label, rv } = makeHtmlLabelTo(content, { ...font, pencolor: getPenColor(obj), imageSizer }, measurer, stderr);
8685
+ if (rv !== 0 && obj !== void 0) stderr.write(`${inLabelOf(obj)}
8686
+ `);
8687
+ stderr.flush();
8522
8688
  return label;
8523
8689
  }
8524
8690
  const subst2 = obj !== void 0 ? substObj(content, obj, false) : content;
@@ -15732,7 +15898,7 @@ function renderNodeLabel(n, coord, renderer, job) {
15732
15898
  renderLabel(label, coord, renderer, job);
15733
15899
  }
15734
15900
  }
15735
- function anchorAttr2(n, key) {
15901
+ function anchorAttr(n, key) {
15736
15902
  const v = nodeAttr(n, n.root, key);
15737
15903
  return v !== void 0 && v !== "" ? v : void 0;
15738
15904
  }
@@ -15742,13 +15908,13 @@ function resolveTooltip(n, tooltip) {
15742
15908
  return label?.text ?? "";
15743
15909
  }
15744
15910
  function beginNodeAnchor(n, renderer, job) {
15745
- const url = anchorAttr2(n, "href") ?? anchorAttr2(n, "URL");
15746
- const tooltip = anchorAttr2(n, "tooltip");
15911
+ const url = anchorAttr(n, "href") ?? anchorAttr(n, "URL");
15912
+ const tooltip = anchorAttr(n, "tooltip");
15747
15913
  if (url === void 0 && tooltip === void 0) return false;
15748
15914
  renderer.beginAnchor?.(
15749
15915
  url !== void 0 ? substObjAnchor(url, n) : "",
15750
15916
  resolveTooltip(n, tooltip),
15751
- anchorAttr2(n, "target") ?? "",
15917
+ anchorAttr(n, "target") ?? "",
15752
15918
  svgNodeId(n, job),
15753
15919
  job
15754
15920
  );