@office-kit/xlsx 0.17.0 → 0.18.0

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 (61) hide show
  1. package/README.md +78 -4
  2. package/dist/{cell-style-DjKKPWDL.mjs → cell-style-CbB4nXTY.mjs} +11 -4
  3. package/dist/cell-style-CbB4nXTY.mjs.map +1 -0
  4. package/dist/{differential-7KGzbliB.mjs → differential-QLaKEiBk.mjs} +2 -2
  5. package/dist/{differential-7KGzbliB.mjs.map → differential-QLaKEiBk.mjs.map} +1 -1
  6. package/dist/io/load.d.ts +2 -0
  7. package/dist/io.mjs +2 -2
  8. package/dist/{iterparse-DZE0zy2M.mjs → iterparse-CZoRXvZW.mjs} +2 -2
  9. package/dist/{iterparse-DZE0zy2M.mjs.map → iterparse-CZoRXvZW.mjs.map} +1 -1
  10. package/dist/{load-DIdQ_zum.mjs → load-BpnCPv1S.mjs} +25 -13
  11. package/dist/load-BpnCPv1S.mjs.map +1 -0
  12. package/dist/{manifest-BHUYpjUG.mjs → manifest-9p0ccqmR.mjs} +10 -11
  13. package/dist/manifest-9p0ccqmR.mjs.map +1 -0
  14. package/dist/node.mjs +1 -1
  15. package/dist/packaging.mjs +1 -1
  16. package/dist/{parser-By6RWZVW.mjs → parser-B1tB9YaE.mjs} +15 -5
  17. package/dist/parser-B1tB9YaE.mjs.map +1 -0
  18. package/dist/{save-ax11Gsw0.mjs → save-1Z3344nz.mjs} +6 -6
  19. package/dist/{save-ax11Gsw0.mjs.map → save-1Z3344nz.mjs.map} +1 -1
  20. package/dist/schema.mjs +1 -1
  21. package/dist/{serialize-Dmb6Vtt9.mjs → serialize-BtxgssFK.mjs} +2 -2
  22. package/dist/{serialize-Dmb6Vtt9.mjs.map → serialize-BtxgssFK.mjs.map} +1 -1
  23. package/dist/{serializer-dhv07Z6F.mjs → serializer-N6XIwsgp.mjs} +2 -2
  24. package/dist/{serializer-dhv07Z6F.mjs.map → serializer-N6XIwsgp.mjs.map} +1 -1
  25. package/dist/streaming.mjs +34 -17
  26. package/dist/streaming.mjs.map +1 -1
  27. package/dist/styles/display-text.d.ts +95 -0
  28. package/dist/styles/format-code.d.ts +125 -0
  29. package/dist/styles/index.d.ts +1 -0
  30. package/dist/styles/numbers.d.ts +7 -0
  31. package/dist/styles.mjs +1161 -4
  32. package/dist/styles.mjs.map +1 -0
  33. package/dist/{stylesheet-writer-BBYjNSMA.mjs → stylesheet-writer-BEn-0P0x.mjs} +341 -105
  34. package/dist/stylesheet-writer-BEn-0P0x.mjs.map +1 -0
  35. package/dist/{table-BFi2WmgG.mjs → table-BxOLUZs3.mjs} +2 -2
  36. package/dist/{table-BFi2WmgG.mjs.map → table-BxOLUZs3.mjs.map} +1 -1
  37. package/dist/{tree-BX-sRRVp.mjs → tree-CspNjuYl.mjs} +12 -2
  38. package/dist/tree-CspNjuYl.mjs.map +1 -0
  39. package/dist/workbook/index.d.ts +1 -1
  40. package/dist/workbook/workbook.d.ts +9 -46
  41. package/dist/{workbook-CMel6UcI.mjs → workbook-tG9oYtzU.mjs} +46 -9
  42. package/dist/workbook-tG9oYtzU.mjs.map +1 -0
  43. package/dist/workbook.mjs +2 -2
  44. package/dist/worksheet/index.d.ts +1 -1
  45. package/dist/worksheet/worksheet.d.ts +55 -14
  46. package/dist/{worksheet-Cxn2c-jz.mjs → worksheet-DLMyDD7W.mjs} +85 -20
  47. package/dist/worksheet-DLMyDD7W.mjs.map +1 -0
  48. package/dist/worksheet.mjs +3 -3
  49. package/dist/xml/namespaces.d.ts +7 -0
  50. package/dist/xml/parser.d.ts +12 -0
  51. package/dist/xml/strict-package.d.ts +14 -0
  52. package/dist/xml.mjs +4 -4
  53. package/package.json +1 -1
  54. package/dist/cell-style-DjKKPWDL.mjs.map +0 -1
  55. package/dist/load-DIdQ_zum.mjs.map +0 -1
  56. package/dist/manifest-BHUYpjUG.mjs.map +0 -1
  57. package/dist/parser-By6RWZVW.mjs.map +0 -1
  58. package/dist/stylesheet-writer-BBYjNSMA.mjs.map +0 -1
  59. package/dist/tree-BX-sRRVp.mjs.map +0 -1
  60. package/dist/workbook-CMel6UcI.mjs.map +0 -1
  61. package/dist/worksheet-Cxn2c-jz.mjs.map +0 -1
@@ -7,17 +7,18 @@ import { t as makeChartsheet } from "./chartsheet-C3-tqkPy.mjs";
7
7
  import { o as makeDrawing } from "./drawing-Cv6UtInY.mjs";
8
8
  import { n as VALUED_COLOR_MOD_KINDS, r as VALUELESS_COLOR_MOD_KINDS, t as SCHEME_COLOR_NAMES } from "./colors-ovWAwnZI.mjs";
9
9
  import { i as escapeXmlTextVerbatim, n as escapeXmlAttr$1, r as escapeXmlText$1 } from "./escape-rA5UpibT.mjs";
10
- import { H as DRAWING_NS, I as CX_NS, T as CHART_NS, a as findChildren, bt as X14_NS, dt as SHEET_DRAWING_NS, ft as SHEET_MAIN_NS, i as findChild, jt as qname, lt as REL_NS, n as el, q as MARKUP_COMPAT_NS, w as CHART_DRAWING_NS } from "./tree-BX-sRRVp.mjs";
11
- import { t as parseXml } from "./parser-By6RWZVW.mjs";
12
- import { i as defineSchema, n as toTree, r as parseXsdBoolean, t as fromTree } from "./serialize-Dmb6Vtt9.mjs";
13
- import { t as serializeXml } from "./serializer-dhv07Z6F.mjs";
14
- import { Q as findById } from "./manifest-BHUYpjUG.mjs";
15
- import { Dn as makeColor, Zt as makeLegacyComment, cn as multiCellRangeToString, en as makeSheetView, ln as parseMultiCellRange, mn as rangeToString, nn as makeRowDimension, ot as makeWorksheet, tn as makeColumnDimension, un as parseRange, xt as setCell } from "./worksheet-Cxn2c-jz.mjs";
16
- import { Bt as PATTERN_TYPES, Ft as FONT_SCHEMES, It as UNDERLINE_STYLES, Kt as SIDE_STYLES, Lt as VERT_ALIGNS, Xt as HORIZONTAL_ALIGNMENTS, Zt as VERTICAL_ALIGNMENTS } from "./cell-style-DjKKPWDL.mjs";
17
- import { C as addSharedRichText, O as parseRichString, w as addSharedString } from "./workbook-CMel6UcI.mjs";
18
- import { a as makeCfRule, i as makeDataValidation, n as makeTableColumn, o as makeConditionalFormatting, r as makeTableDefinition } from "./table-BFi2WmgG.mjs";
10
+ import { H as DRAWING_NS, I as CX_NS, Nt as qname, T as CHART_NS, a as findChildren, dt as SHEET_DRAWING_NS, ft as SHEET_MAIN_NS, i as findChild, jt as localNameOf, lt as REL_NS, n as el, q as MARKUP_COMPAT_NS, w as CHART_DRAWING_NS, xt as X14_NS } from "./tree-CspNjuYl.mjs";
11
+ import { i as rejectDtdDeclarations, n as parseXml, t as isWhitespaceOnly } from "./parser-B1tB9YaE.mjs";
12
+ import { i as defineSchema, n as toTree, r as parseXsdBoolean, t as fromTree } from "./serialize-BtxgssFK.mjs";
13
+ import { t as serializeXml } from "./serializer-N6XIwsgp.mjs";
14
+ import { Q as findById } from "./manifest-9p0ccqmR.mjs";
15
+ import { F as assertNotStrictRoot, T as addSharedString, k as parseRichString, w as addSharedRichText } from "./workbook-tG9oYtzU.mjs";
16
+ import { $t as makeLegacyComment, Ct as setCell, ct as makeWorksheet, dn as parseMultiCellRange, fn as parseRange, gn as rangeToString, in as makeRowDimension, kn as makeColor, nn as makeSheetView, rn as makeColumnDimension, un as multiCellRangeToString } from "./worksheet-DLMyDD7W.mjs";
17
+ import { It as FONT_SCHEMES, Lt as UNDERLINE_STYLES, Qt as VERTICAL_ALIGNMENTS, Rt as VERT_ALIGNS, Vt as PATTERN_TYPES, Zt as HORIZONTAL_ALIGNMENTS, qt as SIDE_STYLES } from "./cell-style-CbB4nXTY.mjs";
18
+ import { a as makeCfRule, i as makeDataValidation, n as makeTableColumn, o as makeConditionalFormatting, r as makeTableDefinition } from "./table-BxOLUZs3.mjs";
19
19
  import { i as durationToExcel, r as dateToExcel } from "./datetime-B2ySVlXt.mjs";
20
- import { n as getDxfs } from "./differential-7KGzbliB.mjs";
20
+ import { n as getDxfs } from "./differential-QLaKEiBk.mjs";
21
+ import { SaxesParser } from "saxes";
21
22
  //#region src/drawing/dml/effect.ts
22
23
  const PRESET_SHADOW_NAMES = [
23
24
  "shdw1",
@@ -1937,9 +1938,9 @@ const NUM_REF_TAG = `{${CHART_NS}}numRef`;
1937
1938
  const STR_REF_TAG = `{${CHART_NS}}strRef`;
1938
1939
  const NUM_CACHE_TAG = `{${CHART_NS}}numCache`;
1939
1940
  const STR_CACHE_TAG = `{${CHART_NS}}strCache`;
1940
- const F_TAG$1 = `{${CHART_NS}}f`;
1941
+ const F_TAG = `{${CHART_NS}}f`;
1941
1942
  const PT_TAG = `{${CHART_NS}}pt`;
1942
- const V_TAG$1 = `{${CHART_NS}}v`;
1943
+ const V_TAG = `{${CHART_NS}}v`;
1943
1944
  const FORMAT_CODE_TAG = `{${CHART_NS}}formatCode`;
1944
1945
  const BAR_DIR_TAG = `{${CHART_NS}}barDir`;
1945
1946
  const GROUPING_TAG = `{${CHART_NS}}grouping`;
@@ -2222,7 +2223,7 @@ const parseDataLabel = (el) => {
2222
2223
  const strRef = findChild(txEl, STR_REF_TAG);
2223
2224
  if (strRef) out.tx = {
2224
2225
  kind: "strRef",
2225
- ref: findChild(strRef, F_TAG$1)?.text ?? ""
2226
+ ref: findChild(strRef, F_TAG)?.text ?? ""
2226
2227
  };
2227
2228
  }
2228
2229
  }
@@ -2467,7 +2468,7 @@ const parseNumCache = (cacheEl) => {
2467
2468
  const values = [];
2468
2469
  const fmt = findChild(cacheEl, FORMAT_CODE_TAG)?.text;
2469
2470
  for (const pt of findChildren(cacheEl, PT_TAG)) {
2470
- const v = findChild(pt, V_TAG$1)?.text;
2471
+ const v = findChild(pt, V_TAG)?.text;
2471
2472
  if (v !== void 0) values.push(Number.parseFloat(v));
2472
2473
  }
2473
2474
  return fmt !== void 0 ? {
@@ -2478,7 +2479,7 @@ const parseNumCache = (cacheEl) => {
2478
2479
  const parseStrCache = (cacheEl) => {
2479
2480
  const values = [];
2480
2481
  for (const pt of findChildren(cacheEl, PT_TAG)) {
2481
- const v = findChild(pt, V_TAG$1)?.text;
2482
+ const v = findChild(pt, V_TAG)?.text;
2482
2483
  if (v !== void 0) values.push(v);
2483
2484
  }
2484
2485
  return values;
@@ -2488,7 +2489,7 @@ const parseNumericRef = (parent, tag) => {
2488
2489
  if (!wrap) return void 0;
2489
2490
  const numRef = findChild(wrap, NUM_REF_TAG);
2490
2491
  if (!numRef) return void 0;
2491
- const ref = findChild(numRef, F_TAG$1)?.text ?? "";
2492
+ const ref = findChild(numRef, F_TAG)?.text ?? "";
2492
2493
  const cacheEl = findChild(numRef, NUM_CACHE_TAG);
2493
2494
  if (!cacheEl) return { ref };
2494
2495
  const { values, formatCode } = parseNumCache(cacheEl);
@@ -2503,7 +2504,7 @@ const parseCategoryRef = (parent) => {
2503
2504
  if (!cat) return void 0;
2504
2505
  const numRef = findChild(cat, NUM_REF_TAG);
2505
2506
  if (numRef) {
2506
- const ref = findChild(numRef, F_TAG$1)?.text ?? "";
2507
+ const ref = findChild(numRef, F_TAG)?.text ?? "";
2507
2508
  const cacheEl = findChild(numRef, NUM_CACHE_TAG);
2508
2509
  if (!cacheEl) return {
2509
2510
  ref,
@@ -2519,7 +2520,7 @@ const parseCategoryRef = (parent) => {
2519
2520
  }
2520
2521
  const strRef = findChild(cat, STR_REF_TAG);
2521
2522
  if (strRef) {
2522
- const ref = findChild(strRef, F_TAG$1)?.text ?? "";
2523
+ const ref = findChild(strRef, F_TAG)?.text ?? "";
2523
2524
  const cacheEl = findChild(strRef, STR_CACHE_TAG);
2524
2525
  if (!cacheEl) return {
2525
2526
  ref,
@@ -4991,11 +4992,6 @@ function parseCellNumber(raw, sheet, col, row) {
4991
4992
  //#region src/worksheet/reader.ts
4992
4993
  const WORKSHEET_TAG = `{${SHEET_MAIN_NS}}worksheet`;
4993
4994
  const SHEETDATA_TAG = `{${SHEET_MAIN_NS}}sheetData`;
4994
- const ROW_TAG$1 = `{${SHEET_MAIN_NS}}row`;
4995
- const C_TAG = `{${SHEET_MAIN_NS}}c`;
4996
- const V_TAG = `{${SHEET_MAIN_NS}}v`;
4997
- const F_TAG = `{${SHEET_MAIN_NS}}f`;
4998
- const IS_TAG = `{${SHEET_MAIN_NS}}is`;
4999
4995
  const MERGE_CELLS_TAG = `{${SHEET_MAIN_NS}}mergeCells`;
5000
4996
  const MERGE_CELL_TAG = `{${SHEET_MAIN_NS}}mergeCell`;
5001
4997
  const SHEET_VIEWS_TAG$1 = `{${SHEET_MAIN_NS}}sheetViews`;
@@ -5081,8 +5077,14 @@ const FIRST_FOOTER_TAG = `{${SHEET_MAIN_NS}}firstFooter`;
5081
5077
  * doesn't carry the sheet name (it lives in `workbook.xml`).
5082
5078
  */
5083
5079
  function parseWorksheetXml(bytes, title, ctx) {
5084
- const root = parseXml(bytes);
5085
- if (root.name !== WORKSHEET_TAG) throw new OpenXmlSchemaError(`parseWorksheetXml: root is "${root.name}", expected worksheet`);
5080
+ const text = typeof bytes === "string" ? bytes : XML_DECODER.decode(bytes);
5081
+ rejectDtdDeclarations(text);
5082
+ const sheetData = locateSheetData(text);
5083
+ const root = parseXml(sheetData === void 0 ? text : text.slice(0, sheetData.bodyStart) + text.slice(sheetData.bodyEnd));
5084
+ if (root.name !== WORKSHEET_TAG) {
5085
+ assertNotStrictRoot(root.name);
5086
+ throw new OpenXmlSchemaError(`parseWorksheetXml: root is "${root.name}", expected worksheet`);
5087
+ }
5086
5088
  const ws = makeWorksheet(title);
5087
5089
  const sheetPrEl = findChild(root, SHEET_PR_TAG$1);
5088
5090
  if (sheetPrEl) {
@@ -5115,22 +5117,7 @@ function parseWorksheetXml(bytes, title, ctx) {
5115
5117
  const dim = parseColumnDimension(c);
5116
5118
  ws.columnDimensions.set(dim.min, dim);
5117
5119
  }
5118
- const sheetData = findChild(root, SHEETDATA_TAG);
5119
- if (sheetData) {
5120
- const sharedFormulas = /* @__PURE__ */ new Map();
5121
- let nextRow = 1;
5122
- for (const rowNode of findChildren(sheetData, ROW_TAG$1)) {
5123
- const rowIdx = parseRowIndex(rowNode, nextRow);
5124
- nextRow = Math.max(nextRow, rowIdx + 1);
5125
- maybeRecordRowDimension(ws, rowNode, rowIdx);
5126
- let nextCol = 1;
5127
- for (const cNode of findChildren(rowNode, C_TAG)) {
5128
- const coord = parseCellCoord(cNode, rowIdx, nextCol);
5129
- readCell(ws, cNode, coord, ctx, sharedFormulas);
5130
- nextCol = coord.col + 1;
5131
- }
5132
- }
5133
- }
5120
+ if (sheetData !== void 0) readSheetData(ws, text, sheetData, ctx);
5134
5121
  const protectionEl = findChild(root, SHEET_PROTECTION_TAG$1);
5135
5122
  if (protectionEl) ws.sheetProtection = parseSheetProtection$1(protectionEl);
5136
5123
  const ssEl = findChild(root, SORT_STATE_TAG);
@@ -6068,60 +6055,309 @@ const parseSelection = (node) => {
6068
6055
  if (node.attrs["sqref"]) sel.sqref = node.attrs["sqref"];
6069
6056
  return sel;
6070
6057
  };
6071
- /** Row named by the first cell that carries an `@r`, if the row holds one. */
6072
- const firstLocatedCellRow = (rowNode) => {
6073
- for (const cNode of rowNode.children) {
6074
- if (cNode.name !== C_TAG) continue;
6075
- const ref = cNode.attrs["r"];
6076
- if (ref) return coordinateToTuple(ref).row;
6058
+ const saxAttributes = (attrs) => {
6059
+ const out = {};
6060
+ for (const attr of Object.values(attrs)) out[qname(attr.uri, attr.local)] = attr.value;
6061
+ return out;
6062
+ };
6063
+ const XML_DECODER = new TextDecoder("utf-8", { fatal: false });
6064
+ /**
6065
+ * Spans whose content is text rather than markup. `<` is not legal in element
6066
+ * content or in an attribute value, so a comment, a CDATA section and a
6067
+ * processing instruction are the only places a worksheet can carry the literal
6068
+ * text `<sheetData` or `</sheetData>` without meaning it, and so the only thing
6069
+ * the scans below have to step over.
6070
+ */
6071
+ const OPAQUE_SPAN = String.raw`<!--[\s\S]*?-->|<!\[CDATA\[[\s\S]*?\]\]>|<\?[\s\S]*?\?>`;
6072
+ /** One of the same three openers with no terminator after it. */
6073
+ const UNTERMINATED_SPAN = String.raw`(?<unterminated><!--|<!\[CDATA\[|<\?)`;
6074
+ const OPAQUE_SPAN_RE = new RegExp(String.raw`${OPAQUE_SPAN}|${UNTERMINATED_SPAN}`, "g");
6075
+ /** Lexical tag boundaries, including quoted `>` and opaque XML spans. */
6076
+ const HEADER_TAG_RE = new RegExp(String.raw`${OPAQUE_SPAN}|<(?:(?:"[^"]*"|'[^']*'|[^'">])*)>`, "g");
6077
+ /** `>` or XML whitespace: the characters that can end an element name. */
6078
+ const NAME_END_RE = /^[\s>]$/;
6079
+ /**
6080
+ * Locate the `<sheetData>` span in a worksheet part so its rows can be walked
6081
+ * without building a node per cell.
6082
+ *
6083
+ * Parse the header to resolve the direct child's namespace, then scan for its
6084
+ * closing tag without constructing cell nodes. The scan skips comments, CDATA
6085
+ * sections and processing instructions and refuses unterminated opaque spans.
6086
+ *
6087
+ * `undefined` means "this sheet has no rows", and must not come to mean anything
6088
+ * else: no node-tree path for `<sheetData>` is left, so a span this function
6089
+ * declined to identify would drop every cell in the sheet in silence.
6090
+ */
6091
+ const locateSheetData = (text) => {
6092
+ const parser = new SaxesParser({ xmlns: true });
6093
+ const scopes = [];
6094
+ let found;
6095
+ parser.on("error", (error) => {
6096
+ throw new OpenXmlSchemaError(`worksheet: malformed header: ${error.message}`, { cause: error });
6097
+ });
6098
+ parser.on("opentag", (node) => {
6099
+ const namespaces = {
6100
+ ...scopes[scopes.length - 1],
6101
+ ...node.ns
6102
+ };
6103
+ scopes.push(namespaces);
6104
+ if (scopes.length === 2 && node.uri === "http://schemas.openxmlformats.org/spreadsheetml/2006/main" && node.local === "sheetData") found = {
6105
+ tag: node.name,
6106
+ namespaces,
6107
+ empty: node.isSelfClosing
6108
+ };
6109
+ });
6110
+ parser.on("closetag", () => {
6111
+ scopes.pop();
6112
+ });
6113
+ HEADER_TAG_RE.lastIndex = 0;
6114
+ let cursor = 0;
6115
+ for (let tag = HEADER_TAG_RE.exec(text); tag !== null; tag = HEADER_TAG_RE.exec(text)) {
6116
+ const bodyStart = tag.index + tag[0].length;
6117
+ parser.write(text.slice(cursor, bodyStart));
6118
+ cursor = bodyStart;
6119
+ if (found !== void 0) {
6120
+ if (found.empty) return void 0;
6121
+ return {
6122
+ bodyStart,
6123
+ bodyEnd: findSheetDataClose(text, found.tag, bodyStart),
6124
+ namespaces: found.namespaces
6125
+ };
6126
+ }
6127
+ }
6128
+ };
6129
+ /** An unterminated opaque span means the part is not well-formed XML. */
6130
+ const refuseUnterminatedSpan = (match) => {
6131
+ const opener = match.groups?.["unterminated"];
6132
+ if (opener === void 0) return;
6133
+ throw new OpenXmlSchemaError(`worksheet: "${opener}" is never closed`);
6134
+ };
6135
+ /**
6136
+ * Index of the `<` opening `</tag>`, skipping any candidate that sits inside an
6137
+ * opaque span. The opaque scan only ever moves forward, so a part whose rows
6138
+ * hold no comment, CDATA section or processing instruction pays for one pass
6139
+ * over the body and then never looks again.
6140
+ */
6141
+ const findSheetDataClose = (text, tag, bodyStart) => {
6142
+ const close = `</${tag}`;
6143
+ let at = bodyStart;
6144
+ let opaque = nextOpaqueSpan(text, bodyStart);
6145
+ for (;;) {
6146
+ const candidate = indexOfCloseTag(text, close, at);
6147
+ if (candidate < 0) throw new OpenXmlSchemaError(`worksheet: <${tag}> is never closed`);
6148
+ while (opaque !== void 0 && opaque.end <= candidate) opaque = nextOpaqueSpan(text, opaque.end);
6149
+ if (opaque === void 0 || opaque.start > candidate) return candidate;
6150
+ at = opaque.end;
6151
+ }
6152
+ };
6153
+ /** First span at or after `from` whose content is text rather than markup. */
6154
+ const nextOpaqueSpan = (text, from) => {
6155
+ OPAQUE_SPAN_RE.lastIndex = from;
6156
+ const span = OPAQUE_SPAN_RE.exec(text);
6157
+ if (span === null) return void 0;
6158
+ refuseUnterminatedSpan(span);
6159
+ return {
6160
+ start: span.index,
6161
+ end: span.index + span[0].length
6162
+ };
6163
+ };
6164
+ /** Index of `</tag>` or `</tag >`, never of `</tagSomethingElse>`. */
6165
+ const indexOfCloseTag = (text, close, from) => {
6166
+ for (let at = text.indexOf(close, from); at >= 0; at = text.indexOf(close, at + close.length)) if (NAME_END_RE.test(text.charAt(at + close.length))) return at;
6167
+ return -1;
6168
+ };
6169
+ /**
6170
+ * Text handed to saxes per `write()`. The parser carries a partial token across
6171
+ * writes, so the size only decides how much of the part is copied at once. One
6172
+ * write of a 16 MB span would hold the cell text twice over for the length of
6173
+ * the walk, which is the footprint this reader exists to remove.
6174
+ */
6175
+ const WRITE_CHUNK = 256 * 1024;
6176
+ const isHighSurrogate = (code) => code >= 55296 && code <= 56319;
6177
+ /**
6178
+ * Walk `<sheetData>` and place every cell, resolving inherited namespaces
6179
+ * so foreign extension elements cannot become spreadsheet cells.
6180
+ *
6181
+ * `iterSheetRows` in `../streaming/read-only.ts` walks the same element shapes
6182
+ * to a different destination, and the two have to agree on where a row or cell
6183
+ * with no `@r` lands. That agreement is asserted rather than left to whoever
6184
+ * edits one of them: see "agrees with loadWorkbook on where every cell lands"
6185
+ * in `tests/worksheet/row-without-r-attribute.test.ts`.
6186
+ */
6187
+ const readSheetData = (ws, text, span, ctx) => {
6188
+ const sharedFormulas = /* @__PURE__ */ new Map();
6189
+ let nextRow = 1;
6190
+ let rowIdx = -1;
6191
+ let rowAttrs = {};
6192
+ let nextCol = 1;
6193
+ const held = [];
6194
+ let depth = 0;
6195
+ let cell;
6196
+ let valueTag;
6197
+ let valueText;
6198
+ const inlineStack = [];
6199
+ const settleRow = (row) => {
6200
+ rowIdx = row;
6201
+ nextRow = Math.max(nextRow, row + 1);
6202
+ maybeRecordRowDimension(ws, rowAttrs, row);
6203
+ for (const heldCell of held) {
6204
+ const coord = parseCellCoord(heldCell.ref, row, nextCol);
6205
+ readCell(ws, heldCell, coord, ctx, sharedFormulas);
6206
+ nextCol = coord.col + 1;
6207
+ }
6208
+ held.length = 0;
6209
+ };
6210
+ const parser = new SaxesParser({
6211
+ fragment: true,
6212
+ xmlns: true,
6213
+ additionalNamespaces: span.namespaces
6214
+ });
6215
+ parser.on("error", (err) => {
6216
+ throw new OpenXmlSchemaError(`worksheet: malformed <sheetData>: ${err.message}`, { cause: err });
6217
+ });
6218
+ parser.on("processinginstruction", (pi) => {
6219
+ throw new OpenXmlSchemaError(`worksheet: processing instructions are not supported (saw "<?${pi.target}")`);
6220
+ });
6221
+ parser.on("opentag", (node) => {
6222
+ depth++;
6223
+ if (inlineStack.length > 0) {
6224
+ const child = el(qname(node.uri, node.local), saxAttributes(node.attributes));
6225
+ inlineStack[inlineStack.length - 1]?.children.push(child);
6226
+ inlineStack.push(child);
6227
+ return;
6228
+ }
6229
+ const local = node.local;
6230
+ if (valueTag !== void 0) throw new OpenXmlSchemaError(`worksheet: mixed content not supported (<${local}> inside <${valueTag}>${cellLabel(cell)})`);
6231
+ if (node.uri !== "http://schemas.openxmlformats.org/spreadsheetml/2006/main") return;
6232
+ if (depth === 1) {
6233
+ if (local !== "row") return;
6234
+ rowAttrs = saxAttributes(node.attributes);
6235
+ nextCol = 1;
6236
+ held.length = 0;
6237
+ const rAttr = rowAttrs["r"];
6238
+ if (rAttr === void 0) rowIdx = 0;
6239
+ else settleRow(rowNumberFromAttr(rAttr, "worksheet"));
6240
+ return;
6241
+ }
6242
+ if (rowIdx < 0) return;
6243
+ if (depth === 2) {
6244
+ if (local !== "c") return;
6245
+ const attrs = saxAttributes(node.attributes);
6246
+ cell = {
6247
+ ref: attrs["r"],
6248
+ style: attrs["s"],
6249
+ t: attrs["t"] ?? "n",
6250
+ value: void 0,
6251
+ formulaAttrs: void 0,
6252
+ formula: void 0,
6253
+ inline: void 0
6254
+ };
6255
+ return;
6256
+ }
6257
+ if (depth === 3 && cell !== void 0) {
6258
+ if (local === "v" || local === "f") {
6259
+ if (local === "f") cell.formulaAttrs = saxAttributes(node.attributes);
6260
+ valueTag = local;
6261
+ valueText = "";
6262
+ } else if (local === "is") {
6263
+ const root = el(qname(SHEET_MAIN_NS, "is"));
6264
+ cell.inline = root;
6265
+ inlineStack.push(root);
6266
+ }
6267
+ }
6268
+ });
6269
+ const addText = (chunk) => {
6270
+ if (inlineStack.length > 0) {
6271
+ const top = inlineStack[inlineStack.length - 1];
6272
+ if (top !== void 0) top.text = (top.text ?? "") + chunk;
6273
+ return;
6274
+ }
6275
+ if (valueText !== void 0) valueText += chunk;
6276
+ else if ((depth === 0 || depth === 1 && rowIdx >= 0 || depth === 2 && cell !== void 0) && !isWhitespaceOnly(chunk)) throw new OpenXmlSchemaError("worksheet: mixed content not supported (text between cell elements)");
6277
+ };
6278
+ parser.on("text", addText);
6279
+ parser.on("cdata", addText);
6280
+ parser.on("closetag", (node) => {
6281
+ depth--;
6282
+ if (inlineStack.length > 0) {
6283
+ const closed = inlineStack.pop();
6284
+ if (closed !== void 0) refuseInlineMixedContent(closed);
6285
+ return;
6286
+ }
6287
+ if (node.uri !== "http://schemas.openxmlformats.org/spreadsheetml/2006/main") return;
6288
+ const local = node.local;
6289
+ if (depth === 2 && cell !== void 0) {
6290
+ if (local === "v") cell.value = valueText ?? "";
6291
+ else if (local === "f") cell.formula = valueText ?? "";
6292
+ valueTag = void 0;
6293
+ valueText = void 0;
6294
+ return;
6295
+ }
6296
+ if (depth === 1 && cell !== void 0 && local === "c") {
6297
+ if (rowIdx === 0) if (cell.ref !== void 0) settleRow(coordinateToTuple(cell.ref).row);
6298
+ else held.push(cell);
6299
+ if (rowIdx > 0) {
6300
+ const coord = parseCellCoord(cell.ref, rowIdx, nextCol);
6301
+ readCell(ws, cell, coord, ctx, sharedFormulas);
6302
+ nextCol = coord.col + 1;
6303
+ }
6304
+ cell = void 0;
6305
+ return;
6306
+ }
6307
+ if (depth === 0 && local === "row") {
6308
+ if (rowIdx === 0) settleRow(derivedRowNumber(nextRow, "worksheet"));
6309
+ rowIdx = -1;
6310
+ }
6311
+ });
6312
+ for (let at = span.bodyStart; at < span.bodyEnd;) {
6313
+ let end = Math.min(at + WRITE_CHUNK, span.bodyEnd);
6314
+ if (end < span.bodyEnd && isHighSurrogate(text.charCodeAt(end - 1))) end++;
6315
+ parser.write(text.slice(at, end));
6316
+ at = end;
6077
6317
  }
6318
+ parser.close();
6078
6319
  };
6320
+ /** The offending cell's `@r`, for an error message that can point at it. */
6321
+ const cellLabel = (cell) => cell?.ref === void 0 ? "" : ` of <c r="${cell.ref}">`;
6079
6322
  /**
6080
- * Row number for a `<row>`. `@r` is optional on CT_Row (ECMA-376 §18.3.1.73);
6081
- * without it the row is the one its first located cell names, which is the only
6082
- * record a generator that omits `@r` leaves of a gap, and is how openpyxl's
6083
- * reader places such a row too. With neither, the row takes `fallbackRow`.
6323
+ * Apply `parseXml`'s mixed-content rule to an `<is>` subtree this reader builds
6324
+ * itself: text alongside child elements is refused, whitespace between them is
6325
+ * dropped.
6084
6326
  */
6085
- const parseRowIndex = (rowNode, fallbackRow) => {
6086
- const rAttr = rowNode.attrs["r"];
6087
- if (rAttr !== void 0) return rowNumberFromAttr(rAttr, "worksheet");
6088
- return firstLocatedCellRow(rowNode) ?? derivedRowNumber(fallbackRow, "worksheet");
6089
- };
6090
- const parseCellCoord = (cNode, rowIdx, fallbackCol) => {
6091
- const rAttr = cNode.attrs["r"];
6092
- if (rAttr === void 0) return {
6327
+ const refuseInlineMixedContent = (node) => {
6328
+ if (node.children.length === 0 || node.text === void 0) return;
6329
+ if (!isWhitespaceOnly(node.text)) throw new OpenXmlSchemaError(`worksheet: mixed content not supported (text between elements under <${localNameOf(node.name)}>)`);
6330
+ delete node.text;
6331
+ };
6332
+ const parseCellCoord = (ref, rowIdx, fallbackCol) => {
6333
+ if (ref === void 0) return {
6093
6334
  row: rowIdx,
6094
6335
  col: fallbackCol
6095
6336
  };
6096
- const t = coordinateToTuple(rAttr);
6097
- if (t.row !== rowIdx) throw new OpenXmlSchemaError(`worksheet: <c r="${rAttr}"> row ${t.row} disagrees with row ${rowIdx}`);
6337
+ const t = coordinateToTuple(ref);
6338
+ if (t.row !== rowIdx) throw new OpenXmlSchemaError(`worksheet: <c r="${ref}"> row ${t.row} disagrees with row ${rowIdx}`);
6098
6339
  return {
6099
6340
  row: t.row,
6100
6341
  col: t.col
6101
6342
  };
6102
6343
  };
6103
- const readCell = (ws, cNode, coord, ctx, sharedFormulas) => {
6104
- const t = cNode.attrs["t"] ?? "n";
6105
- const styleAttr = cNode.attrs["s"];
6106
- const styleId = styleAttr === void 0 ? 0 : parseStyleId(styleAttr);
6107
- const fNode = findChild(cNode, F_TAG);
6108
- const vNode = findChild(cNode, V_TAG);
6109
- const isNode = findChild(cNode, IS_TAG);
6110
- if (fNode) {
6344
+ const readCell = (ws, raw, coord, ctx, sharedFormulas) => {
6345
+ const t = raw.t;
6346
+ const styleId = raw.style === void 0 ? 0 : parseStyleId(raw.style);
6347
+ if (raw.formulaAttrs !== void 0) {
6111
6348
  const cell = setCell(ws, coord.row, coord.col, null, styleId);
6112
- const cachedRaw = vNode === void 0 ? void 0 : vNode.text ?? "";
6113
- const cached = decodeCachedValue(cachedRaw, t, ctx, ws.title, coord);
6114
- handleFormula(cell, fNode, coord, cached, sharedFormulas, t);
6349
+ const cached = decodeCachedValue(raw.value, t, ctx, ws.title, coord);
6350
+ handleFormula(cell, raw.formulaAttrs, raw.formula, coord, cached, sharedFormulas, t);
6115
6351
  return;
6116
6352
  }
6117
6353
  let value = null;
6118
6354
  switch (t) {
6119
6355
  case "n":
6120
- value = parseCellNumber(vNode?.text, ws.title, coord.col, coord.row);
6356
+ value = parseCellNumber(raw.value, ws.title, coord.col, coord.row);
6121
6357
  break;
6122
6358
  case "s": {
6123
- if (vNode?.text === void 0) throw new OpenXmlSchemaError("worksheet: <c t=\"s\"> missing <v>");
6124
- const sst = resolveSharedString(vNode.text, ctx);
6359
+ if (raw.value === void 0 || raw.value === "") throw new OpenXmlSchemaError("worksheet: <c t=\"s\"> missing <v>");
6360
+ const sst = resolveSharedString(raw.value, ctx);
6125
6361
  value = typeof sst === "string" ? sst : {
6126
6362
  kind: "rich-text",
6127
6363
  runs: sst.runs
@@ -6129,18 +6365,18 @@ const readCell = (ws, cNode, coord, ctx, sharedFormulas) => {
6129
6365
  break;
6130
6366
  }
6131
6367
  case "b": {
6132
- const raw = vNode?.text?.trim();
6133
- if (raw === void 0 || raw === "") {
6368
+ const text = raw.value?.trim();
6369
+ if (text === void 0 || text === "") {
6134
6370
  value = null;
6135
6371
  break;
6136
6372
  }
6137
- const parsed = parseXsdBoolean(raw);
6138
- if (parsed === void 0) throw new OpenXmlSchemaError(`worksheet: <c r="${tupleToCoordinate(coord.col, coord.row)}" t="b"><v>${clipCellText(raw)}</v></c> is not a boolean`);
6373
+ const parsed = parseXsdBoolean(text);
6374
+ if (parsed === void 0) throw new OpenXmlSchemaError(`worksheet: <c r="${tupleToCoordinate(coord.col, coord.row)}" t="b"><v>${clipCellText(text)}</v></c> is not a boolean`);
6139
6375
  value = parsed;
6140
6376
  break;
6141
6377
  }
6142
6378
  case "e": {
6143
- const code = vNode?.text;
6379
+ const code = raw.value;
6144
6380
  if (code === void 0 || !ERROR_CODES$1.has(code)) throw new OpenXmlSchemaError(`worksheet: unknown error code "${code}" in <c t="e">`);
6145
6381
  value = {
6146
6382
  kind: "error",
@@ -6149,10 +6385,10 @@ const readCell = (ws, cNode, coord, ctx, sharedFormulas) => {
6149
6385
  break;
6150
6386
  }
6151
6387
  case "str":
6152
- value = vNode?.text ?? "";
6388
+ value = raw.value ?? "";
6153
6389
  break;
6154
6390
  case "inlineStr":
6155
- value = readInlineString(isNode);
6391
+ value = readInlineString(raw.inline);
6156
6392
  break;
6157
6393
  default: throw new OpenXmlSchemaError(`worksheet: unknown cell type t="${t}"`);
6158
6394
  }
@@ -6213,9 +6449,9 @@ const decodeCachedValue = (raw, t, ctx, sheet, coord) => {
6213
6449
  default: return raw;
6214
6450
  }
6215
6451
  };
6216
- const handleFormula = (cell, fNode, coord, cached, sharedFormulas, cachedType) => {
6217
- const tAttr = fNode.attrs["t"] ?? "normal";
6218
- const formula = normalizeFormulaText(fNode.text ?? "");
6452
+ const handleFormula = (cell, fAttrs, fText, coord, cached, sharedFormulas, cachedType) => {
6453
+ const tAttr = fAttrs["t"] ?? "normal";
6454
+ const formula = normalizeFormulaText(fText ?? "");
6219
6455
  const opts = cached !== void 0 ? {
6220
6456
  cachedValue: cached,
6221
6457
  ...cachedType === "e" ? { cachedValueType: "error" } : {}
@@ -6226,17 +6462,17 @@ const handleFormula = (cell, fNode, coord, cached, sharedFormulas, cachedType) =
6226
6462
  setFormula(cell, formula, opts);
6227
6463
  return;
6228
6464
  case "array": {
6229
- const ref = fNode.attrs["ref"];
6465
+ const ref = fAttrs["ref"];
6230
6466
  if (!ref) throw new OpenXmlSchemaError("worksheet: <f t=\"array\"> missing @ref");
6231
6467
  setArrayFormula(cell, ref, formula, opts);
6232
6468
  return;
6233
6469
  }
6234
6470
  case "shared": {
6235
- const siRaw = fNode.attrs["si"];
6471
+ const siRaw = fAttrs["si"];
6236
6472
  if (siRaw === void 0) throw new OpenXmlSchemaError("worksheet: <f t=\"shared\"> missing @si");
6237
6473
  const si = Number.parseInt(siRaw, 10);
6238
6474
  if (!Number.isInteger(si) || si < 0) throw new OpenXmlSchemaError(`worksheet: <f t="shared" si="${siRaw}"> is not a valid index`);
6239
- const ref = fNode.attrs["ref"];
6475
+ const ref = fAttrs["ref"];
6240
6476
  if (formula.length > 0) {
6241
6477
  sharedFormulas.set(si, {
6242
6478
  origin: tupleToCoordinate(coord.col, coord.row),
@@ -6252,19 +6488,19 @@ const handleFormula = (cell, fNode, coord, cached, sharedFormulas, cachedType) =
6252
6488
  return;
6253
6489
  }
6254
6490
  case "dataTable": {
6255
- const ref = fNode.attrs["ref"];
6491
+ const ref = fAttrs["ref"];
6256
6492
  if (!ref) throw new OpenXmlSchemaError("worksheet: <f t=\"dataTable\"> missing @ref");
6257
6493
  setDataTableFormula(cell, formula, {
6258
6494
  ref,
6259
6495
  ...opts,
6260
- ...fNode.attrs["r1"] !== void 0 ? { r1: fNode.attrs["r1"] } : {},
6261
- ...fNode.attrs["r2"] !== void 0 ? { r2: fNode.attrs["r2"] } : {},
6262
- ...parseXsdBoolean(fNode.attrs["dt2D"]) ? { dt2D: true } : {},
6263
- ...parseXsdBoolean(fNode.attrs["dtr"]) ? { dtr: true } : {},
6264
- ...parseXsdBoolean(fNode.attrs["del1"]) ? { del1: true } : {},
6265
- ...parseXsdBoolean(fNode.attrs["del2"]) ? { del2: true } : {},
6266
- ...parseXsdBoolean(fNode.attrs["aca"]) ? { aca: true } : {},
6267
- ...parseXsdBoolean(fNode.attrs["ca"]) ? { ca: true } : {}
6496
+ ...fAttrs["r1"] !== void 0 ? { r1: fAttrs["r1"] } : {},
6497
+ ...fAttrs["r2"] !== void 0 ? { r2: fAttrs["r2"] } : {},
6498
+ ...parseXsdBoolean(fAttrs["dt2D"]) ? { dt2D: true } : {},
6499
+ ...parseXsdBoolean(fAttrs["dtr"]) ? { dtr: true } : {},
6500
+ ...parseXsdBoolean(fAttrs["del1"]) ? { del1: true } : {},
6501
+ ...parseXsdBoolean(fAttrs["del2"]) ? { del2: true } : {},
6502
+ ...parseXsdBoolean(fAttrs["aca"]) ? { aca: true } : {},
6503
+ ...parseXsdBoolean(fAttrs["ca"]) ? { ca: true } : {}
6268
6504
  });
6269
6505
  return;
6270
6506
  }
@@ -6486,19 +6722,19 @@ const parseHyperlink = (node, rels) => {
6486
6722
  if (node.attrs["display"]) opts.display = node.attrs["display"];
6487
6723
  return opts;
6488
6724
  };
6489
- const maybeRecordRowDimension = (ws, node, rowIdx) => {
6725
+ const maybeRecordRowDimension = (ws, attrs, rowIdx) => {
6490
6726
  const opts = {};
6491
- const ht = parseFloatAttr(node.attrs["ht"]);
6727
+ const ht = parseFloatAttr(attrs["ht"]);
6492
6728
  if (ht !== void 0) opts.height = ht;
6493
- const customHeight = parseXsdBoolean(node.attrs["customHeight"]);
6729
+ const customHeight = parseXsdBoolean(attrs["customHeight"]);
6494
6730
  if (customHeight !== void 0) opts.customHeight = customHeight;
6495
- const hidden = parseXsdBoolean(node.attrs["hidden"]);
6731
+ const hidden = parseXsdBoolean(attrs["hidden"]);
6496
6732
  if (hidden !== void 0) opts.hidden = hidden;
6497
- const outlineLevel = parseIntegerAttr(node.attrs["outlineLevel"]);
6733
+ const outlineLevel = parseIntegerAttr(attrs["outlineLevel"]);
6498
6734
  if (outlineLevel !== void 0) opts.outlineLevel = outlineLevel;
6499
- const collapsed = parseXsdBoolean(node.attrs["collapsed"]);
6735
+ const collapsed = parseXsdBoolean(attrs["collapsed"]);
6500
6736
  if (collapsed !== void 0) opts.collapsed = collapsed;
6501
- const style = parseIntegerAttr(node.attrs["s"]);
6737
+ const style = parseIntegerAttr(attrs["s"]);
6502
6738
  if (style !== void 0) opts.style = style;
6503
6739
  if (Object.keys(opts).length === 0) return;
6504
6740
  ws.rowDimensions.set(rowIdx, makeRowDimension(opts));
@@ -8809,4 +9045,4 @@ const cellXfToTree = (xf) => {
8809
9045
  //#endregion
8810
9046
  export { userShapesToBytes as C, chartToBytes as D, parseChartExXml as E, findUserShapesRId as O, parseUserShapesXml as S, isChartExBytes as T, parseChartsheetXml as _, parseCommentsXml as a, parseWorksheetXml as b, NumberFormatSchema as c, BorderSchema as d, AlignmentSchema as f, chartsheetToBytes as g, parseDrawingXml as h, commentsToBytes as i, parseChartXml as k, FontSchema as l, drawingToBytes as m, parseTableXml as n, placeholderVmlDrawing as o, collectRawRelIds as p, tableToBytes as r, ProtectionSchema as s, stylesheetToBytes as t, fillFromTree as u, serializeCell as v, chartExToBytes as w, parseCellNumber as x, writeWorksheetXml as y };
8811
9047
 
8812
- //# sourceMappingURL=stylesheet-writer-BBYjNSMA.mjs.map
9048
+ //# sourceMappingURL=stylesheet-writer-BEn-0P0x.mjs.map