xlvane 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -73,13 +73,15 @@ const WARNING_CODES = [
73
73
  "XLV_W_DUPLICATE_CELL",
74
74
  "XLV_W_INVALID_VALUE",
75
75
  "XLV_W_SHEET_PART_MISSING",
76
+ "XLV_W_SHEET_PART_SHARED",
76
77
  "XLV_W_PART_MISSING",
77
78
  "XLV_W_FORMULAS_NOT_RECALCULATED",
78
79
  "XLV_W_INVALID_CELL_REF",
79
80
  "XLV_W_UNUSUAL_HYPERLINK",
80
81
  "XLV_W_THREADED_COMMENTS",
81
82
  "XLV_W_DRAWING_CONTENT_NOT_READ",
82
- "XLV_W_MERGED_CELL_WRITE"
83
+ "XLV_W_MERGED_CELL_WRITE",
84
+ "XLV_W_LIMIT_REACHED"
83
85
  ];
84
86
  /**
85
87
  * The only error type thrown by xlvane for problems with input files or options. It says what
@@ -332,6 +334,8 @@ function createXmlStreamParser(handler, options) {
332
334
  }
333
335
  };
334
336
  }
337
+ const COMMENT_TOO_LONG = "Comment is longer than the limit.";
338
+ const PI_TOO_LONG = "Processing instruction is longer than the limit.";
335
339
  /** Consumed input is dropped once at least this many characters can go (amortises copying). */
336
340
  const COMPACT_THRESHOLD = 65536;
337
341
  var Parser = class {
@@ -363,13 +367,23 @@ var Parser = class {
363
367
  tokenAt = -1;
364
368
  tokenFrom = 0;
365
369
  tokenQuote = 0;
370
+ /** Offset of the quote that opened the attribute value being searched. */
371
+ tokenQuoteAt = 0;
372
+ /**
373
+ * Pieces held back while the unconsumed input is long (a long token or text run), joined to `s`
374
+ * once they are at least as long as it. Appending every piece to `s` and searching it again
375
+ * made a long token cost time quadratic in its length; joining at doubling sizes keeps the
376
+ * total work linear (D-H01).
377
+ */
378
+ held = [];
379
+ heldLength = 0;
366
380
  constructor(handler, options, whole) {
367
381
  this.handler = handler;
368
382
  this.options = options;
369
383
  this.whole = whole;
370
384
  }
371
385
  get buffered() {
372
- return this.s.length - this.pos + this.textBuffer.length;
386
+ return this.s.length - this.pos + this.heldLength + this.textBuffer.length;
373
387
  }
374
388
  write(chunk) {
375
389
  if (this.ended) throw new Error("XML stream parser: write() after end().");
@@ -389,24 +403,36 @@ var Parser = class {
389
403
  }
390
404
  }
391
405
  if (text.length === 0) return;
406
+ if (this.whole) {
407
+ this.append(text);
408
+ return;
409
+ }
410
+ this.held.push(text);
411
+ this.heldLength += text.length;
412
+ if (this.heldLength < this.s.length - this.pos) return;
413
+ this.appendHeld();
414
+ this.pump(false);
415
+ this.compact();
416
+ }
417
+ append(text) {
392
418
  const from = this.s.length;
393
419
  this.s += text;
394
420
  this.checkCharacters(from);
395
- if (!this.whole) {
396
- this.pump(false);
397
- this.compact();
398
- }
421
+ }
422
+ appendHeld() {
423
+ if (this.held.length === 0) return;
424
+ const text = this.held.length === 1 ? this.held[0] ?? "" : this.held.join("");
425
+ this.held = [];
426
+ this.heldLength = 0;
427
+ this.append(text);
399
428
  }
400
429
  end() {
401
430
  if (this.ended) return;
402
431
  const tail = this.pendingHigh + (this.pendingCR ? "\n" : "");
403
432
  this.pendingCR = false;
404
433
  this.pendingHigh = "";
405
- if (tail.length > 0) {
406
- const from = this.s.length;
407
- this.s += tail;
408
- this.checkCharacters(from);
409
- }
434
+ this.appendHeld();
435
+ if (tail.length > 0) this.append(tail);
410
436
  this.ended = true;
411
437
  this.pump(true);
412
438
  }
@@ -428,6 +454,7 @@ var Parser = class {
428
454
  if (this.tokenAt !== -1) {
429
455
  this.tokenAt -= drop;
430
456
  this.tokenFrom -= drop;
457
+ this.tokenQuoteAt -= drop;
431
458
  }
432
459
  }
433
460
  /**
@@ -440,7 +467,10 @@ var Parser = class {
440
467
  if (!this.declarationChecked) {
441
468
  if (s.length - this.pos < 6 && !final) return;
442
469
  if (s.startsWith("<?xml", this.pos) && (s.length === 5 || isWhitespace(s.charCodeAt(5)) || s.charCodeAt(5) === QUESTION)) {
443
- if (!final && s.indexOf("?>", this.pos + 2) === -1) return;
470
+ if (!final && s.indexOf("?>", this.pos + 2) === -1) {
471
+ if (s.length - this.pos - 2 > this.options.limits.maxXmlTextLength + 1) this.limit("maxXmlTextLength", PI_TOO_LONG, this.pos);
472
+ return;
473
+ }
444
474
  this.declarationChecked = true;
445
475
  this.skipProcessingInstruction(true);
446
476
  }
@@ -490,15 +520,24 @@ var Parser = class {
490
520
  if (length - at >= 4 && s.startsWith("<!--", at)) {
491
521
  const dashes = s.indexOf("--", Math.max(at + 4, this.tokenFrom));
492
522
  done = dashes !== -1 && dashes + 2 < length;
493
- if (!done) this.tokenFrom = Math.max(at + 4, length - 1);
523
+ if (!done) {
524
+ this.tokenFrom = Math.max(at + 4, length - 1);
525
+ if (length - (at + 4) > this.options.limits.maxXmlTextLength + 2) this.limit("maxXmlTextLength", COMMENT_TOO_LONG, at);
526
+ }
494
527
  } else if (length - at < 9) done = false;
495
528
  else if (s.startsWith("<![CDATA[", at)) {
496
529
  done = s.indexOf("]]>", Math.max(at + 9, this.tokenFrom)) !== -1;
497
- if (!done) this.tokenFrom = Math.max(at + 9, length - 2);
530
+ if (!done) {
531
+ this.tokenFrom = Math.max(at + 9, length - 2);
532
+ if (this.textBuffer.length + length - (at + 9) > this.options.limits.maxXmlTextLength + 2) this.limit("maxXmlTextLength", "Text node is longer than the limit.", at);
533
+ }
498
534
  } else done = true;
499
535
  } else if (next === QUESTION) {
500
536
  done = s.indexOf("?>", Math.max(at + 2, this.tokenFrom)) !== -1;
501
- if (!done) this.tokenFrom = Math.max(at + 2, length - 1);
537
+ if (!done) {
538
+ this.tokenFrom = Math.max(at + 2, length - 1);
539
+ if (length - (at + 2) > this.options.limits.maxXmlTextLength + 1) this.limit("maxXmlTextLength", PI_TOO_LONG, at);
540
+ }
502
541
  } else if (next === SLASH$1) {
503
542
  done = s.indexOf(">", Math.max(at + 2, this.tokenFrom)) !== -1;
504
543
  if (!done) this.tokenFrom = length;
@@ -510,14 +549,17 @@ var Parser = class {
510
549
  const c = s.charCodeAt(i);
511
550
  if (quote !== 0) {
512
551
  if (c === quote) quote = 0;
513
- } else if (c === QUOTE || c === APOS) quote = c;
514
- else if (c === GT) {
552
+ } else if (c === QUOTE || c === APOS) {
553
+ quote = c;
554
+ this.tokenQuoteAt = i;
555
+ } else if (c === GT) {
515
556
  done = true;
516
557
  break;
517
558
  }
518
559
  }
519
560
  this.tokenFrom = i;
520
561
  this.tokenQuote = quote;
562
+ if (!done && quote !== 0 && i - (this.tokenQuoteAt + 1) > this.options.limits.maxXmlTextLength) this.limit("maxXmlTextLength", `Value of attribute "${this.attributeNameBefore(this.tokenQuoteAt)}" is longer than the limit.`, this.tokenQuoteAt + 1);
521
563
  }
522
564
  if (done) this.tokenAt = -1;
523
565
  return done;
@@ -532,7 +574,13 @@ var Parser = class {
532
574
  if (s.length - this.pos <= this.options.limits.maxXmlTextLength) return;
533
575
  let cut = s.length;
534
576
  const amp = s.indexOf("&", Math.max(this.pos, s.lastIndexOf(";") + 1));
535
- if (amp !== -1) cut = amp;
577
+ if (amp !== -1) {
578
+ cut = amp;
579
+ if (s.length - amp > this.options.limits.maxXmlNameLength + 12) {
580
+ if (s.charCodeAt(amp + 1) !== HASH) this.limit("maxXmlNameLength", "Entity name is longer than the limit.", amp);
581
+ this.fail("\"&\" must start an entity or character reference ending with \";\".", amp);
582
+ }
583
+ }
536
584
  while (cut > this.pos && s.charCodeAt(cut - 1) === 93 && cut > s.length - 2) cut--;
537
585
  if (cut <= this.pos) return;
538
586
  if (this.segmentStart === -1) {
@@ -865,6 +913,7 @@ var Parser = class {
865
913
  skipComment() {
866
914
  const start = this.pos;
867
915
  const end = this.s.indexOf("--", start + 4);
916
+ if ((end === -1 ? this.s.length : end) - (start + 4) > this.options.limits.maxXmlTextLength) this.limit("maxXmlTextLength", COMMENT_TOO_LONG, start);
868
917
  if (end === -1) this.fail("Comment is not terminated.", start);
869
918
  if (this.s.charCodeAt(end + 2) !== GT) this.fail("\"--\" is not allowed inside a comment.", end);
870
919
  this.pos = end + 3;
@@ -875,6 +924,7 @@ var Parser = class {
875
924
  const target = this.readName();
876
925
  if (!declaration && target.toLowerCase() === "xml") this.fail("The XML declaration is allowed only at the very start of the document.", start);
877
926
  const end = this.s.indexOf("?>", this.pos);
927
+ if ((end === -1 ? this.s.length : end) - (start + 2) > this.options.limits.maxXmlTextLength) this.limit("maxXmlTextLength", PI_TOO_LONG, start);
878
928
  if (end === -1) this.fail("Processing instruction is not terminated.", start);
879
929
  const c = this.s.charCodeAt(this.pos);
880
930
  if (this.pos !== end && !isWhitespace(c)) this.fail("Invalid processing instruction target.", start);
@@ -911,6 +961,17 @@ var Parser = class {
911
961
  hint: "The part is not well-formed XML. Re-save the file in a spreadsheet application; if it was generated by a program, report the problem to its authors."
912
962
  });
913
963
  }
964
+ /** The attribute name before `name = "` whose quote is at `quote` (for a message). */
965
+ attributeNameBefore(quote) {
966
+ const s = this.s;
967
+ let i = quote - 1;
968
+ while (i >= 0 && isWhitespace(s.charCodeAt(i))) i--;
969
+ if (s.charCodeAt(i) === EQ) i--;
970
+ while (i >= 0 && isWhitespace(s.charCodeAt(i))) i--;
971
+ const end = i + 1;
972
+ while (i >= 0 && end - i <= this.options.limits.maxXmlNameLength && !isWhitespace(s.charCodeAt(i)) && s.charCodeAt(i) !== 60) i--;
973
+ return s.slice(i + 1, end);
974
+ }
914
975
  limit(limit, message, offset) {
915
976
  const details = {
916
977
  limit,
@@ -984,8 +1045,16 @@ function createXmlByteStreamParser(handler, options) {
984
1045
  let decoder = null;
985
1046
  /** Bytes held until the encoding is known (at most the first two). */
986
1047
  let head = /* @__PURE__ */ new Uint8Array(0);
987
- /** Decoded text held until the XML declaration can be checked. */
988
- let pending = "";
1048
+ /**
1049
+ * Decoded pieces held until the XML declaration can be checked (null once it has been), with
1050
+ * their length, their first five characters and whether "?>" has been seen. Each piece is
1051
+ * searched once, so a long declaration costs linear time (D-H01).
1052
+ */
1053
+ let pending = [];
1054
+ let pendingLength = 0;
1055
+ let pendingHead = "";
1056
+ let pendingLast = "";
1057
+ let declarationEnd = false;
989
1058
  const encodingError = (cause) => new XlvError("XLV_E_XML_ENCODING", `The part is not valid ${(encoding ?? "utf-8").toUpperCase()}.`, {
990
1059
  location: { part },
991
1060
  hint: "Office Open XML parts must be encoded in UTF-8 or UTF-16. Re-save the file in a spreadsheet application.",
@@ -1004,9 +1073,30 @@ function createXmlByteStreamParser(handler, options) {
1004
1073
  if (chunk.length > 0) text.write(chunk);
1005
1074
  return;
1006
1075
  }
1007
- pending += chunk;
1008
- if (!(pending.length >= 5 && (!pending.startsWith("<?xml") || pending.indexOf("?>") !== -1)) && !final) return;
1009
- const declared = declaredEncoding(pending);
1076
+ if (chunk.length > 0) {
1077
+ pending.push(chunk);
1078
+ pendingLength += chunk.length;
1079
+ if (pendingHead.length < 5) pendingHead += chunk.slice(0, 5 - pendingHead.length);
1080
+ declarationEnd ||= (pendingLast + chunk).includes("?>");
1081
+ pendingLast = chunk.slice(-1);
1082
+ }
1083
+ const known = pendingLength >= 5 && (!pendingHead.startsWith("<?xml") || declarationEnd);
1084
+ if (!known && pendingLength - 2 > options.limits.maxXmlTextLength + 1) throw new XlvError("XLV_E_LIMIT_EXCEEDED", PI_TOO_LONG, {
1085
+ location: {
1086
+ part,
1087
+ line: 1,
1088
+ column: 1
1089
+ },
1090
+ hint: `If you trust this file, raise the limit, for example { limits: { maxXmlTextLength: ${String(options.limits.maxXmlTextLength * 4)} } }.`,
1091
+ details: {
1092
+ limit: "maxXmlTextLength",
1093
+ value: options.limits.maxXmlTextLength
1094
+ }
1095
+ });
1096
+ if (!known && !final) return;
1097
+ const all = pending.join("");
1098
+ pending = null;
1099
+ const declared = declaredEncoding(all);
1010
1100
  if (declared !== null) {
1011
1101
  const normalized = declared.toLowerCase();
1012
1102
  if (!(encoding === "utf-8" ? normalized === "utf-8" : normalized === "utf-16" || normalized === encoding)) throw new XlvError("XLV_E_XML_ENCODING", `The part declares encoding "${declared}", which is not supported.`, {
@@ -1015,8 +1105,6 @@ function createXmlByteStreamParser(handler, options) {
1015
1105
  details: { encoding: declared }
1016
1106
  });
1017
1107
  }
1018
- const all = pending;
1019
- pending = null;
1020
1108
  if (all.length > 0) text.write(all);
1021
1109
  };
1022
1110
  const start = (bytes) => {
@@ -3412,6 +3500,22 @@ function describe$1(value) {
3412
3500
  if (typeof value === "object" || typeof value === "function") return `a value of type ${typeof value}`;
3413
3501
  return String(value);
3414
3502
  }
3503
+ /**
3504
+ * Checks the number of positions an output built from a sheet would have against
3505
+ * max(`maxCells`, OUTPUT_PER_CELL × cells read). Throws `XLV_E_LIMIT_EXCEEDED` above it.
3506
+ */
3507
+ function checkOutputPositions(positions, cells, maxCells, what, sheet) {
3508
+ const budget = Math.max(maxCells, 16 * cells);
3509
+ if (positions <= budget) return;
3510
+ throw new XlvError("XLV_E_LIMIT_EXCEEDED", `${what} of sheet "${sheet}" would have ${String(positions)} positions (rows × columns) for ${String(cells)} cells, more than the limit of ${String(budget)}.`, {
3511
+ location: { sheet },
3512
+ hint: `The cells are spread over a far larger area than they fill. Pass a smaller range (for example { range: "A1:H1000" } or --range), or raise limits.maxCells if the file is trusted.`,
3513
+ details: {
3514
+ limit: "maxCells",
3515
+ value: budget
3516
+ }
3517
+ });
3518
+ }
3415
3519
  // src/sml/numfmt.ts
3416
3520
  /** A `Map` whose contents cannot change after construction. */
3417
3521
  var FrozenMap = class extends Map {
@@ -8430,6 +8534,10 @@ function createRuleCollector(ctx) {
8430
8534
  };
8431
8535
  }
8432
8536
  // src/sml/formula-shift.ts
8537
+ /** Number of decimal digits of a positive whole number. */
8538
+ const digits = (n) => n < 10 ? 1 : n < 100 ? 2 : n < 1e3 ? 3 : n < 1e4 ? 4 : n < 1e5 ? 5 : n < 1e6 ? 6 : 7;
8539
+ /** Number of letters of a column number from 1 to 16384 (A to XFD). */
8540
+ const letters = (c) => c <= 26 ? 1 : c <= 702 ? 2 : 3;
8433
8541
  /** Error constants (§18.17.3, fact E-33). */
8434
8542
  const ERROR_CONSTANTS = [
8435
8543
  "#NULL!",
@@ -8773,8 +8881,17 @@ var Compiled = class {
8773
8881
  maxRow = -Infinity;
8774
8882
  minCol = Infinity;
8775
8883
  maxCol = -Infinity;
8884
+ /** Length of the literal text and sheet prefixes, which do not change when moved. */
8885
+ literalLength = 0;
8886
+ /** The references, for {@link renderedLength}. */
8887
+ refs;
8776
8888
  constructor(parts) {
8777
8889
  this.parts = parts;
8890
+ const refs = [];
8891
+ for (const p of parts) if (typeof p === "string") this.literalLength += p.length;
8892
+ else if (p.kind === "prefix") this.literalLength += p.text.length;
8893
+ else refs.push(p);
8894
+ this.refs = refs;
8778
8895
  const row = (r, abs) => {
8779
8896
  if (abs) return;
8780
8897
  if (r < this.minRow) this.minRow = r;
@@ -8805,6 +8922,15 @@ var Compiled = class {
8805
8922
  if (this.minCol !== Infinity && (this.minCol + dCol < 1 || this.maxCol + dCol > 16384)) return false;
8806
8923
  return true;
8807
8924
  }
8925
+ renderedLength(dRow, dCol) {
8926
+ let length = this.literalLength;
8927
+ const col = (c, abs) => abs ? 1 + letters(c) : letters(c + dCol);
8928
+ const row = (r, abs) => abs ? 1 + digits(r) : digits(r + dRow);
8929
+ for (const p of this.refs) if (p.kind === "cell") length += col(p.col, p.colAbs) + row(p.row, p.rowAbs);
8930
+ else if (p.kind === "cols") length += col(p.c1, p.c1Abs) + 1 + col(p.c2, p.c2Abs);
8931
+ else length += row(p.r1, p.r1Abs) + 1 + row(p.r2, p.r2Abs);
8932
+ return length;
8933
+ }
8808
8934
  render(dRow, dCol) {
8809
8935
  let out = "";
8810
8936
  const col = (c, abs) => (abs ? "$" : "") + columnLetters(abs ? c : c + dCol);
@@ -8943,7 +9069,7 @@ function parseWorksheet(xml, ctx) {
8943
9069
  /** The cells of one row's style-only list (`[col, styleIndex, …]`), in column order. */
8944
9070
  function styledCellsOf(row, list, make) {
8945
9071
  const pairs = [];
8946
- for (let i = 0; i + 1 < list.length; i += 2) pairs.push([list[i], list[i + 1]]);
9072
+ for (let i = 0; i + 1 < list.length; i += 2) if (list[i + 1] !== -1) pairs.push([list[i], list[i + 1]]);
8947
9073
  pairs.sort((a, b) => a[0] - b[0]);
8948
9074
  return pairs.map(([col, styleIndex]) => make(row, col, styleIndex));
8949
9075
  }
@@ -8951,6 +9077,7 @@ function createWorksheetParser(ctx, onRow) {
8951
9077
  const rows = /* @__PURE__ */ new Map();
8952
9078
  const styleOnly = /* @__PURE__ */ new Map();
8953
9079
  const styleOnlyMax = /* @__PURE__ */ new Map();
9080
+ const styleOnlyIndex = /* @__PURE__ */ new Map();
8954
9081
  const merges = [];
8955
9082
  const formats = ctx.formatCache;
8956
9083
  const path = [];
@@ -8959,6 +9086,7 @@ function createWorksheetParser(ctx, onRow) {
8959
9086
  let cellCount = 0;
8960
9087
  const masters = /* @__PURE__ */ new Map();
8961
9088
  const dependents = [];
9089
+ const compiled = /* @__PURE__ */ new Map();
8962
9090
  const columns = [];
8963
9091
  const rowInfo = /* @__PURE__ */ new Map();
8964
9092
  let freeze = null;
@@ -9041,8 +9169,14 @@ function createWorksheetParser(ctx, onRow) {
9041
9169
  if (max === void 0 || col > max) return -1;
9042
9170
  const list = styleOnly.get(row);
9043
9171
  if (list === void 0) return -1;
9044
- for (let i = list.length - 2; i >= 0; i -= 2) if (list[i] === col) return i;
9045
- return -1;
9172
+ if (list[list.length - 2] === col && list[list.length - 1] !== -1) return list.length - 2;
9173
+ let index = styleOnlyIndex.get(row);
9174
+ if (index === void 0) {
9175
+ index = /* @__PURE__ */ new Map();
9176
+ for (let i = 0; i + 1 < list.length; i += 2) if (list[i + 1] !== -1) index.set(list[i], i);
9177
+ styleOnlyIndex.set(row, index);
9178
+ }
9179
+ return index.get(col) ?? -1;
9046
9180
  };
9047
9181
  const styledCell = (row, col, styleIndex) => {
9048
9182
  const code = numberFormat(styleIndex).code;
@@ -9223,13 +9357,16 @@ function createWorksheetParser(ctx, onRow) {
9223
9357
  value: ctx.limits.maxCells
9224
9358
  }
9225
9359
  });
9360
+ styleOnlyIndex.get(p.row)?.set(p.col, styled.length);
9226
9361
  styled.push(p.col, p.styleIndex);
9227
9362
  if (p.col > (styleOnlyMax.get(p.row) ?? 0)) styleOnlyMax.set(p.row, p.col);
9228
9363
  return;
9229
9364
  }
9230
9365
  const at = styledIndex(p.row, p.col);
9231
9366
  if (at >= 0) {
9232
- styleOnly.get(p.row)?.splice(at, 2);
9367
+ const list = styleOnly.get(p.row);
9368
+ if (list !== void 0) list[at + 1] = -1;
9369
+ styleOnlyIndex.get(p.row)?.delete(p.col);
9233
9370
  ctx.budget.remaining++;
9234
9371
  ctx.warnings.add("XLV_W_DUPLICATE_CELL", "The sheet defines the same cell more than once; the last definition is used.", loc(p.ref));
9235
9372
  }
@@ -9263,6 +9400,18 @@ function createWorksheetParser(ctx, onRow) {
9263
9400
  ...richText === void 0 ? {} : { richText }
9264
9401
  });
9265
9402
  };
9403
+ const spendFormulaText = (chars, ref) => {
9404
+ ctx.budget.formulaText -= chars;
9405
+ if (ctx.budget.formulaText >= 0) return;
9406
+ throw new XlvError("XLV_E_LIMIT_EXCEEDED", "The cells that share formulas would hold more formula text than the limit allows.", {
9407
+ location: loc(ref),
9408
+ hint: `Small files can share one huge formula with many cells; the limit counts the formula of each cell that shares it. If you trust this file, raise the limit, for example { limits: { maxSharedStringChars: ${String(ctx.limits.maxSharedStringChars * 4)} } }.`,
9409
+ details: {
9410
+ limit: "maxSharedStringChars",
9411
+ value: ctx.limits.maxSharedStringChars
9412
+ }
9413
+ });
9414
+ };
9266
9415
  const warnNotExpanded = (ref) => ctx.warnings.add("XLV_W_SHARED_FORMULA_NOT_EXPANDED", "Some cells reuse a shared formula that could not be moved to them (missing master, cell outside the master range, or formula text xlvane cannot translate safely); their formula.text is null and their cached values are available.", loc(ref));
9267
9416
  /** Streaming: expands the pending shared formulas and hands the buffered cells on. */
9268
9417
  const flushRows = () => {
@@ -9270,7 +9419,7 @@ function createWorksheetParser(ctx, onRow) {
9270
9419
  const info = rowInfo.get(currentRow);
9271
9420
  rowInfo.delete(currentRow);
9272
9421
  if (rows.size === 0 && styleOnly.size === 0) return;
9273
- expandSharedFormulas(rows, masters, dependents, warnNotExpanded);
9422
+ expandSharedFormulas(rows, masters, compiled, dependents, warnNotExpanded, spendFormulaText);
9274
9423
  dependents.length = 0;
9275
9424
  const out = [];
9276
9425
  for (const r of [...rows.keys()].sort((a, b) => a - b)) {
@@ -9282,6 +9431,7 @@ function createWorksheetParser(ctx, onRow) {
9282
9431
  for (const r of [...styleOnly.keys()].sort((a, b) => a - b)) styled.push(...styledCellsOf(r, styleOnly.get(r) ?? [], styledCell));
9283
9432
  styleOnly.clear();
9284
9433
  styleOnlyMax.clear();
9434
+ styleOnlyIndex.clear();
9285
9435
  if (out.length > 0 || styled.length > 0) onRow(currentRow, out, info, styled);
9286
9436
  };
9287
9437
  const handler = {
@@ -9530,7 +9680,7 @@ function createWorksheetParser(ctx, onRow) {
9530
9680
  };
9531
9681
  const finish = () => {
9532
9682
  if (onRow) flushRows();
9533
- else expandSharedFormulas(rows, masters, dependents, warnNotExpanded);
9683
+ else expandSharedFormulas(rows, masters, compiled, dependents, warnNotExpanded, spendFormulaText);
9534
9684
  const activeCell = selections.get(activePane);
9535
9685
  if (activeCell !== void 0) view = Object.freeze({
9536
9686
  ...view,
@@ -9569,8 +9719,7 @@ function createWorksheetParser(ctx, onRow) {
9569
9719
  * many cells costs memory only for the texts actually read. Dependents that cannot be expanded
9570
9720
  * keep `text: null` and are reported through `warn`.
9571
9721
  */
9572
- function expandSharedFormulas(rows, masters, dependents, warn) {
9573
- const compiled = /* @__PURE__ */ new Map();
9722
+ function expandSharedFormulas(rows, masters, compiled, dependents, warn, spend) {
9574
9723
  for (const d of dependents) {
9575
9724
  const rowCells = rows.get(d.row);
9576
9725
  const cell = rowCells?.get(d.col);
@@ -9592,6 +9741,7 @@ function expandSharedFormulas(rows, masters, dependents, warn) {
9592
9741
  warn(d.ref);
9593
9742
  continue;
9594
9743
  }
9744
+ spend(formula.renderedLength(dRow, dCol), d.ref);
9595
9745
  rowCells.set(d.col, {
9596
9746
  ...cell,
9597
9747
  formula: lazySharedFormula(formula, dRow, dCol, d.si)
@@ -9910,6 +10060,7 @@ var NotLoaded = class extends Error {
9910
10060
  this.end = end;
9911
10061
  }
9912
10062
  };
10063
+ const segmentEnd = (segment) => segment.start + segment.data.length;
9913
10064
  /**
9914
10065
  * Little-endian access to a file of `size` bytes, of which only some segments may be in memory
9915
10066
  * (all of it for `openZip`; the tail, the central directory and local headers for streaming
@@ -9917,7 +10068,14 @@ var NotLoaded = class extends Error {
9917
10068
  */
9918
10069
  var Bytes = class Bytes {
9919
10070
  size;
10071
+ /** Loaded segments in order of `start` (equal starts in order of addition). */
9920
10072
  segments = [];
10073
+ /**
10074
+ * For each index i, the segment with the largest end among segments[0..i]. A range is loaded
10075
+ * exactly when that segment, for the last i whose start is at or before the range's start,
10076
+ * reaches its end; so a lookup is one binary search (D-H01).
10077
+ */
10078
+ reach = [];
9921
10079
  last;
9922
10080
  constructor(size, segments) {
9923
10081
  this.size = size;
@@ -9934,35 +10092,40 @@ var Bytes = class Bytes {
9934
10092
  start,
9935
10093
  data
9936
10094
  };
9937
- this.segments.push(segment);
9938
- this.segments.sort((a, b) => a.start - b.start);
10095
+ const at = this.upperBound(start);
10096
+ this.segments.splice(at, 0, segment);
10097
+ this.reach.splice(at, 0, segment);
10098
+ for (let i = at; i < this.segments.length; i++) {
10099
+ const own = this.segments[i];
10100
+ const before = i === 0 ? void 0 : this.reach[i - 1];
10101
+ this.reach[i] = before !== void 0 && segmentEnd(before) >= segmentEnd(own) ? before : own;
10102
+ }
9939
10103
  this.last = segment;
9940
10104
  }
9941
10105
  /** Whether `[start, end)` is fully inside one loaded segment. */
9942
10106
  has(start, end) {
9943
10107
  return this.find(start, end) !== void 0;
9944
10108
  }
9945
- find(start, end) {
9946
- const last = this.last;
9947
- if (last && start >= last.start && end <= last.start + last.data.length) return last;
10109
+ /** The number of segments whose start is at or before `start`. */
10110
+ upperBound(start) {
9948
10111
  let lo = 0;
9949
- let hi = this.segments.length - 1;
9950
- let found;
9951
- while (lo <= hi) {
10112
+ let hi = this.segments.length;
10113
+ while (lo < hi) {
9952
10114
  const mid = lo + hi >> 1;
9953
- const seg = this.segments[mid];
9954
- if (seg.start <= start) {
9955
- found = seg;
9956
- lo = mid + 1;
9957
- } else hi = mid - 1;
9958
- }
9959
- for (let i = found === void 0 ? -1 : this.segments.indexOf(found); i >= 0; i--) {
9960
- const seg = this.segments[i];
9961
- if (end <= seg.start + seg.data.length && start >= seg.start) {
9962
- this.last = seg;
9963
- return seg;
9964
- }
10115
+ if (this.segments[mid].start <= start) lo = mid + 1;
10116
+ else hi = mid;
9965
10117
  }
10118
+ return lo;
10119
+ }
10120
+ find(start, stop) {
10121
+ const last = this.last;
10122
+ if (last && start >= last.start && stop <= segmentEnd(last)) return last;
10123
+ const i = this.upperBound(start) - 1;
10124
+ if (i < 0) return void 0;
10125
+ const seg = this.reach[i];
10126
+ if (stop > segmentEnd(seg)) return void 0;
10127
+ this.last = seg;
10128
+ return seg;
9966
10129
  }
9967
10130
  /** The bytes `[start, end)`; throws {@link NotLoaded} if they are not in memory. */
9968
10131
  slice(start, end) {
@@ -10501,7 +10664,8 @@ function readWorkbook(data, options) {
10501
10664
  const book = analyzeWorkbook(pkg, limits, warnings);
10502
10665
  const budget = {
10503
10666
  remaining: limits.maxCells,
10504
- sharedText: limits.maxSharedStringChars
10667
+ sharedText: limits.maxSharedStringChars,
10668
+ formulaText: limits.maxSharedStringChars
10505
10669
  };
10506
10670
  const formatCache = /* @__PURE__ */ new Map();
10507
10671
  const media = /* @__PURE__ */ new Map();
@@ -10521,10 +10685,10 @@ function readWorkbook(data, options) {
10521
10685
  formatCache
10522
10686
  });
10523
10687
  const links = data === null || entry.part === null ? [] : resolveHyperlinks(pkg, entry.part, entry.name, data, warnings);
10524
- const notes = data === null || entry.part === null ? [] : readNotes(pkg, entry.part, entry.name, limits, warnings);
10688
+ const notes = data === null || entry.part === null ? [] : readNotes(pkg, entry.part, entry.name, limits, warnings, entry.foreignParts);
10525
10689
  if (data !== null) attachNotes(data.rows, notes);
10526
10690
  const sheet = new ReadSheet(entry.name, entry.index, entry.kind, entry.state, entry.part, data, entry.sheetId, links, notes, book.definedNames);
10527
- if (data !== null && entry.part !== null) sheet.tables = readTables(pkg, entry.part, entry.name, limits, warnings);
10691
+ if (data !== null && entry.part !== null) sheet.tables = readTables(pkg, entry.part, entry.name, limits, warnings, entry.foreignParts);
10528
10692
  if (data !== null && entry.part !== null) {
10529
10693
  const drawing = readSheetDrawing(pkg, entry.part, entry.name, {
10530
10694
  drawing: data.drawingRelId ?? null,
@@ -10578,29 +10742,55 @@ function resolveHyperlinks(pkg, part, sheet, data, warnings) {
10578
10742
  part,
10579
10743
  sheet
10580
10744
  });
10745
+ let total = 0;
10746
+ for (const cells of data.rows.values()) total += cells.size;
10747
+ let linked = 0;
10748
+ let visits = 0;
10749
+ const maxVisits = 16 * total + 1e6;
10581
10750
  for (const link of links) {
10751
+ if (linked === total) break;
10752
+ if (visits > maxVisits) {
10753
+ warnings.add("XLV_W_LIMIT_REACHED", `The sheet's hyperlinks cover far more positions than it has cells; cell.hyperlink is not set for the cells of some links. sheet.hyperlinks lists every link.`, {
10754
+ part,
10755
+ sheet
10756
+ });
10757
+ break;
10758
+ }
10582
10759
  const range = parseRange(link.ref);
10583
10760
  if (range === null) continue;
10584
10761
  const rowSpan = range.end.row - range.start.row + 1;
10585
10762
  const colSpan = range.end.col - range.start.col + 1;
10586
10763
  const visit = (cells) => {
10587
10764
  const mark = (c, cell) => {
10588
- if (cell.hyperlink === void 0) cells.set(c, {
10589
- ...cell,
10590
- hyperlink: link
10591
- });
10765
+ if (cell.hyperlink === void 0) {
10766
+ cells.set(c, {
10767
+ ...cell,
10768
+ hyperlink: link
10769
+ });
10770
+ linked++;
10771
+ }
10592
10772
  };
10593
- if (colSpan <= cells.size) for (let c = range.start.col; c <= range.end.col; c++) {
10594
- const cell = cells.get(c);
10595
- if (cell) mark(c, cell);
10773
+ if (colSpan <= cells.size) {
10774
+ visits += colSpan;
10775
+ for (let c = range.start.col; c <= range.end.col; c++) {
10776
+ const cell = cells.get(c);
10777
+ if (cell) mark(c, cell);
10778
+ }
10779
+ } else {
10780
+ visits += cells.size;
10781
+ for (const [c, cell] of cells) if (c >= range.start.col && c <= range.end.col) mark(c, cell);
10596
10782
  }
10597
- else for (const [c, cell] of cells) if (c >= range.start.col && c <= range.end.col) mark(c, cell);
10598
10783
  };
10599
- if (rowSpan <= data.rows.size) for (let r = range.start.row; r <= range.end.row; r++) {
10600
- const cells = data.rows.get(r);
10601
- if (cells) visit(cells);
10784
+ if (rowSpan <= data.rows.size) {
10785
+ visits += rowSpan;
10786
+ for (let r = range.start.row; r <= range.end.row; r++) {
10787
+ const cells = data.rows.get(r);
10788
+ if (cells) visit(cells);
10789
+ }
10790
+ } else {
10791
+ visits += data.rows.size;
10792
+ for (const [r, cells] of data.rows) if (r >= range.start.row && r <= range.end.row) visit(cells);
10602
10793
  }
10603
- else for (const [r, cells] of data.rows) if (r >= range.start.row && r <= range.end.row) visit(cells);
10604
10794
  }
10605
10795
  return links;
10606
10796
  }
@@ -10610,8 +10800,8 @@ function resolveHyperlinks(pkg, part, sheet, data, warnings) {
10610
10800
  * ([MS-XLSX] §2.3.7) are reported with `XLV_W_THREADED_COMMENTS`; their legacy placeholders are
10611
10801
  * ordinary notes.
10612
10802
  */
10613
- function readNotes(pkg, part, sheet, limits, warnings) {
10614
- const rels = pkg.relationships(part);
10803
+ function readNotes(pkg, part, sheet, limits, warnings, foreign = NO_PARTS) {
10804
+ const rels = pkg.relationships(part).filter((r) => r.external || !foreign.has(partKey(r.target)));
10615
10805
  if (rels.some((r) => r.type === "http://schemas.microsoft.com/office/2017/10/relationships/threadedComment")) warnings.add("XLV_W_THREADED_COMMENTS", "The sheet has threaded comments (conversations); xlvane reads only the notes stored with them, whose author is \"tc={id}\" and whose text may not include the replies.", {
10616
10806
  part,
10617
10807
  sheet
@@ -10633,8 +10823,12 @@ function readNotes(pkg, part, sheet, limits, warnings) {
10633
10823
  warnings
10634
10824
  });
10635
10825
  if (notes.length === 0) return notes;
10826
+ const seen = /* @__PURE__ */ new Set();
10636
10827
  for (const vml of rels) {
10637
10828
  if (vml.external || classifyRelationship(vml.type)?.name !== "vmlDrawing") continue;
10829
+ const key = partKey(vml.target);
10830
+ if (seen.has(key)) continue;
10831
+ seen.add(key);
10638
10832
  const text = pkg.readXml(vml.target);
10639
10833
  if (text === void 0) continue;
10640
10834
  const boxes = parseNoteBoxes(text, {
@@ -10659,10 +10853,14 @@ function readNotes(pkg, part, sheet, limits, warnings) {
10659
10853
  * relationships (Part 1 §12.3.21, §18.3.1.94; TD-01), in relationship order. A missing or
10660
10854
  * invalid part gives a warning, never an error.
10661
10855
  */
10662
- function readTables(pkg, part, sheet, limits, warnings) {
10856
+ function readTables(pkg, part, sheet, limits, warnings, foreign = NO_PARTS) {
10663
10857
  const tables = [];
10858
+ const seen = /* @__PURE__ */ new Set();
10664
10859
  for (const rel of pkg.relationships(part)) {
10665
10860
  if (rel.external || classifyRelationship(rel.type)?.name !== "table") continue;
10861
+ const key = partKey(rel.target);
10862
+ if (seen.has(key) || foreign.has(key)) continue;
10863
+ seen.add(key);
10666
10864
  if (tables.length >= 4096) {
10667
10865
  warnings.add("XLV_W_INVALID_VALUE", `The sheet has more than ${String(MAX_TABLES_PER_SHEET)} tables; the rest are not read.`, {
10668
10866
  part,
@@ -10701,6 +10899,13 @@ function attachNotes(rows, notes) {
10701
10899
  });
10702
10900
  }
10703
10901
  }
10902
+ const NO_PARTS = /* @__PURE__ */ new Set();
10903
+ /** Relationship types whose parts are read per sheet, besides the worksheet itself. */
10904
+ const SHEET_RELATED = /* @__PURE__ */ new Set([
10905
+ "comments",
10906
+ "vmlDrawing",
10907
+ "table"
10908
+ ]);
10704
10909
  /** The Core Properties relationship of the package, if any (D-A02). */
10705
10910
  function corePropertiesRel(pkg) {
10706
10911
  return pkg.relationships(null).find((r) => !r.external && isCorePropertiesRel(r.type));
@@ -10774,6 +10979,7 @@ function analyzeWorkbook(pkg, limits, warnings) {
10774
10979
  const externalLinkCount = rels.filter((r) => classifyRelationship(r.type)?.name === "externalLink").length;
10775
10980
  if (externalLinkCount > 0) warnings.add("XLV_W_EXTERNAL_LINKS", `The workbook links to ${externalLinkCount} external workbook(s). xlvane never follows the links; linked values are the cached copies.`, { part: workbookPart });
10776
10981
  const dateSystem = info.date1904 ? "1904" : "1900";
10982
+ const owners = /* @__PURE__ */ new Map();
10777
10983
  const sheets = info.sheets.map((entry, index) => {
10778
10984
  if (entry.state === "veryHidden") warnings.add("XLV_W_VERY_HIDDEN_SHEET", `Sheet "${entry.name}" is very hidden: spreadsheet applications do not offer a way to unhide it.`, { sheet: entry.name });
10779
10985
  const rel = entry.relId === null ? void 0 : relsById.get(entry.relId);
@@ -10790,16 +10996,49 @@ function analyzeWorkbook(pkg, limits, warnings) {
10790
10996
  sheetId: entry.sheetId,
10791
10997
  kind,
10792
10998
  state: entry.state,
10793
- part: null
10999
+ part: null,
11000
+ foreignParts: NO_PARTS
11001
+ };
11002
+ }
11003
+ const owner = owners.get(partKey(rel.target));
11004
+ if (owner !== void 0) {
11005
+ warnings.add("XLV_W_SHEET_PART_SHARED", `Sheet "${entry.name}" has the same part as sheet "${owner}"; the part is read for "${owner}" only, and "${entry.name}" is returned without cells.`, {
11006
+ sheet: entry.name,
11007
+ part: rel.target
11008
+ });
11009
+ return {
11010
+ name: entry.name,
11011
+ index,
11012
+ sheetId: entry.sheetId,
11013
+ kind,
11014
+ state: entry.state,
11015
+ part: null,
11016
+ foreignParts: NO_PARTS
10794
11017
  };
10795
11018
  }
11019
+ owners.set(partKey(rel.target), entry.name);
11020
+ const foreign = /* @__PURE__ */ new Set();
11021
+ for (const r of pkg.relationships(rel.target)) {
11022
+ if (r.external || !SHEET_RELATED.has(classifyRelationship(r.type)?.name ?? "")) continue;
11023
+ const key = partKey(r.target);
11024
+ const first = owners.get(key);
11025
+ if (first === void 0) owners.set(key, entry.name);
11026
+ else if (first !== entry.name && !foreign.has(key)) {
11027
+ foreign.add(key);
11028
+ warnings.add("XLV_W_SHEET_PART_SHARED", `Sheet "${entry.name}" relates to the part ${r.target}, which belongs to sheet "${first}"; it is read for "${first}" only.`, {
11029
+ sheet: entry.name,
11030
+ part: r.target
11031
+ });
11032
+ }
11033
+ }
10796
11034
  return {
10797
11035
  name: entry.name,
10798
11036
  index,
10799
11037
  sheetId: entry.sheetId,
10800
11038
  kind,
10801
11039
  state: entry.state,
10802
- part: rel.target
11040
+ part: rel.target,
11041
+ foreignParts: foreign
10803
11042
  };
10804
11043
  });
10805
11044
  const definedNames = info.definedNames.map((n) => {
@@ -13076,4 +13315,4 @@ function openInput(input, limits, onWarning) {
13076
13315
  if (onWarning !== void 0) for (const warning of workbook.warnings) onWarning(warning);
13077
13316
  return workbook;
13078
13317
  }
13079
- export { fillXml as $, resolveImage as $t, limitExceeded as A, EMPTY_STYLES as At, tokenize as B, suggest as Bt, Bytes as C, escapeText as Cn, relationshipsPartName as Ct, TAIL_BYTES as D, isXlvError as Dn, normalizeTable as Dt, NotLoaded as E, XlvError as En, TABLE_CONTENT_TYPE as Et, validateLocalHeaders as F, normalizeStyle as Ft, DEFAULT_FONT as G, legacyPasswordHash as Gt, X14_DV_URI as H, printXml as Ht, WarningCollector as I, stableKey as It, borderXml as J, IMAGE_CONTENT_TYPES as Jt, SheetRels as K, verifyPassword as Kt, sheetNotFound as L, isDateFormat as Lt, openZip as M, READING_ORDERS as Mt, readCentralDirectory as N, checkStyleCount as Nt, checkSource as O, checkDefinedName as Ot, unsupported as P, mergeStyles as Pt, createSharedStrings as Q, metricsOf as Qt, createWorksheetParser as R, DEFAULT_READ_LIMITS as Rt, workbookPartsToLoad as S, escapeAttr as Sn, openPackage as St, HEAD_BYTES as T, WARNING_CODES as Tn, zipNameToPartName as Tt, X14_NS as U, sheetProtectionXml as Ut, X14_CF_URI as V, printNames as Vt, XM_NS as W, hashPassword as Wt, cellXml as X, drawingParts as Xt, buildStyles as Y, MediaParts as Yt, contentTypesXml as Z, imageFormat as Zt, isoDate as _, createXmlByteStreamParser as _n, FormulaGroups as _t, DATE_FORMAT as a, columnLetters as an, reusableBuiltinNumFmt as at, readWorkbook as b, parseXml as bn, parseIsoDateTime as bt, NewSheet as c, parseCellRef as cn, sheetHead as ct, convertCellInput as d, CORE_PROPERTIES_PART as dn, sheetTail as dt, SML_NS as en, fontXml as et, createWorkbook as f, appPropertiesXml as fn, stringItemXml as ft, inspect as g, parseXmlTree as gn, workbookXml as gt, detectHeader as h, childrenNamed as hn, workbookRelsXml as ht, readOptions as i, MAX_ROWS as in, noteParts as it, locateCentralDirectory as j, parseStyles as jt, corrupt as k, checkUniqueName as kt, NewWorkbook as l, parseRange as ln, sheetRelsPartName as lt, writeWorkbook as m, childNamed as mn, textElement as mt, oneOfOption as n, relationshipTypes as nn, hyperlinksXml as nt, DATE_TIME_FORMAT as o, formatCellRef as on, rootRelsXml as ot, sortedNotes as p, corePropertiesXml as pn, tableParts as pt, attr as q, DRAWING_CONTENT_TYPE as qt, openInput as r, MAX_COLUMNS as rn, nameTitles as rt, ERROR_VALUES as s, formatRange as sn, rowStart as st, booleanOption as t, classifyRelationship as tn, formatNumber as tt, checkBookViews as u, APP_PROPERTIES_PART as un, sheetRulesXml as ut, analyzeWorkbook as v, decodeXml as vn, writeZip as vt, CORRUPT_HINT as w, ERROR_CODES as wn, partKey as wt, toBytes as x, encodeXstring as xn, parseSharedStrings as xt, readNotes as y, normalizeLineEnds as yn, crc32 as yt, shiftFormula as z, resolveLimits as zt };
13318
+ export { fillXml as $, metricsOf as $t, limitExceeded as A, EMPTY_STYLES as At, tokenize as B, resolveLimits as Bt, Bytes as C, encodeXstring as Cn, relationshipsPartName as Ct, TAIL_BYTES as D, WARNING_CODES as Dn, normalizeTable as Dt, NotLoaded as E, ERROR_CODES as En, TABLE_CONTENT_TYPE as Et, validateLocalHeaders as F, normalizeStyle as Ft, DEFAULT_FONT as G, hashPassword as Gt, X14_DV_URI as H, printNames as Ht, WarningCollector as I, stableKey as It, borderXml as J, DRAWING_CONTENT_TYPE as Jt, SheetRels as K, legacyPasswordHash as Kt, sheetNotFound as L, isDateFormat as Lt, openZip as M, READING_ORDERS as Mt, readCentralDirectory as N, checkStyleCount as Nt, checkSource as O, XlvError as On, checkDefinedName as Ot, unsupported as P, mergeStyles as Pt, createSharedStrings as Q, imageFormat as Qt, createWorksheetParser as R, DEFAULT_READ_LIMITS as Rt, workbookPartsToLoad as S, parseXml as Sn, openPackage as St, HEAD_BYTES as T, escapeText as Tn, zipNameToPartName as Tt, X14_NS as U, printXml as Ut, X14_CF_URI as V, suggest as Vt, XM_NS as W, sheetProtectionXml as Wt, cellXml as X, MediaParts as Xt, buildStyles as Y, IMAGE_CONTENT_TYPES as Yt, contentTypesXml as Z, drawingParts as Zt, isoDate as _, childrenNamed as _n, FormulaGroups as _t, DATE_FORMAT as a, MAX_COLUMNS as an, reusableBuiltinNumFmt as at, readWorkbook as b, decodeXml as bn, parseIsoDateTime as bt, NewSheet as c, formatCellRef as cn, sheetHead as ct, convertCellInput as d, parseRange as dn, sheetTail as dt, resolveImage as en, fontXml as et, createWorkbook as f, APP_PROPERTIES_PART as fn, stringItemXml as ft, inspect as g, childNamed as gn, workbookXml as gt, detectHeader as h, corePropertiesXml as hn, workbookRelsXml as ht, readOptions as i, relationshipTypes as in, noteParts as it, locateCentralDirectory as j, parseStyles as jt, corrupt as k, isXlvError as kn, checkUniqueName as kt, NewWorkbook as l, formatRange as ln, sheetRelsPartName as lt, writeWorkbook as m, appPropertiesXml as mn, textElement as mt, oneOfOption as n, SML_NS as nn, hyperlinksXml as nt, DATE_TIME_FORMAT as o, MAX_ROWS as on, rootRelsXml as ot, sortedNotes as p, CORE_PROPERTIES_PART as pn, tableParts as pt, attr as q, verifyPassword as qt, openInput as r, classifyRelationship as rn, nameTitles as rt, ERROR_VALUES as s, columnLetters as sn, rowStart as st, booleanOption as t, REL_NS as tn, formatNumber as tt, checkBookViews as u, parseCellRef as un, sheetRulesXml as ut, analyzeWorkbook as v, parseXmlTree as vn, writeZip as vt, CORRUPT_HINT as w, escapeAttr as wn, partKey as wt, toBytes as x, normalizeLineEnds as xn, parseSharedStrings as xt, readNotes as y, createXmlByteStreamParser as yn, crc32 as yt, shiftFormula as z, checkOutputPositions as zt };