@shbernal/ts-xlsx 1.3.1 → 2.0.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 (155) hide show
  1. package/dist/core/address.d.ts +49 -2
  2. package/dist/core/address.js +31 -3
  3. package/dist/core/autofilter.d.ts +2 -2
  4. package/dist/core/cell.d.ts +17 -16
  5. package/dist/core/cell.js +3 -7
  6. package/dist/core/color-resolution.d.ts +7 -7
  7. package/dist/core/column.d.ts +8 -9
  8. package/dist/core/column.js +2 -4
  9. package/dist/core/comment-thread.d.ts +32 -23
  10. package/dist/core/comment-thread.js +4 -4
  11. package/dist/core/conditional-formatting-overlay.d.ts +1 -1
  12. package/dist/core/conditional-formatting.d.ts +3 -3
  13. package/dist/core/data-validation-overlay.d.ts +1 -1
  14. package/dist/core/data-validation.d.ts +3 -3
  15. package/dist/core/date.d.ts +3 -3
  16. package/dist/core/formula.d.ts +6 -6
  17. package/dist/core/grid-edits.js +3 -3
  18. package/dist/core/image.d.ts +37 -2
  19. package/dist/core/image.js +6 -0
  20. package/dist/core/internal.d.ts +9 -1
  21. package/dist/core/limits.d.ts +4 -4
  22. package/dist/core/merge.d.ts +6 -12
  23. package/dist/core/merge.js +0 -3
  24. package/dist/core/page-setup.d.ts +4 -4
  25. package/dist/core/pivot-table.d.ts +2 -4
  26. package/dist/core/pivot-table.js +5 -5
  27. package/dist/core/preserved.d.ts +3 -3
  28. package/dist/core/protection.d.ts +4 -4
  29. package/dist/core/range.d.ts +16 -14
  30. package/dist/core/range.js +5 -5
  31. package/dist/core/row-input.d.ts +2 -8
  32. package/dist/core/row-input.js +2 -2
  33. package/dist/core/row.d.ts +7 -8
  34. package/dist/core/row.js +2 -4
  35. package/dist/core/style.d.ts +14 -14
  36. package/dist/core/table-style.d.ts +9 -9
  37. package/dist/core/table-style.js +1 -1
  38. package/dist/core/table.d.ts +30 -42
  39. package/dist/core/table.js +16 -10
  40. package/dist/core/theme.d.ts +13 -43
  41. package/dist/core/theme.js +2 -148
  42. package/dist/core/value.d.ts +7 -7
  43. package/dist/core/workbook-protection.d.ts +2 -2
  44. package/dist/core/workbook-styles.d.ts +26 -0
  45. package/dist/core/workbook-styles.js +48 -0
  46. package/dist/core/workbook-theme.d.ts +25 -0
  47. package/dist/core/workbook-theme.js +49 -0
  48. package/dist/core/workbook-vba.d.ts +17 -0
  49. package/dist/core/workbook-vba.js +79 -0
  50. package/dist/core/workbook.d.ts +131 -85
  51. package/dist/core/workbook.js +74 -133
  52. package/dist/core/worksheet-comments.d.ts +9 -0
  53. package/dist/core/worksheet-comments.js +52 -0
  54. package/dist/core/worksheet-model.d.ts +4 -4
  55. package/dist/core/worksheet-model.js +1 -0
  56. package/dist/core/worksheet-pictures.d.ts +29 -0
  57. package/dist/core/worksheet-pictures.js +42 -0
  58. package/dist/core/worksheet.d.ts +85 -77
  59. package/dist/core/worksheet.js +36 -95
  60. package/dist/customui/errors.d.ts +1 -1
  61. package/dist/customui/ribbon.d.ts +3 -3
  62. package/dist/entries/core.d.ts +4 -4
  63. package/dist/entries/core.js +1 -1
  64. package/dist/entries/vba.d.ts +1 -1
  65. package/dist/entries/vba.js +1 -1
  66. package/dist/entries/xlsx.d.ts +1 -0
  67. package/dist/entries/xlsx.js +1 -0
  68. package/dist/errors.d.ts +12 -12
  69. package/dist/io/csv/read.js +1 -2
  70. package/dist/io/csv/write.d.ts +8 -3
  71. package/dist/io/csv/write.js +17 -2
  72. package/dist/io/opc/errors.d.ts +6 -6
  73. package/dist/io/opc/inflate.d.ts +1 -1
  74. package/dist/io/opc/namespaces.d.ts +1 -1
  75. package/dist/io/opc/read-opc.d.ts +19 -3
  76. package/dist/io/opc/read-opc.js +14 -8
  77. package/dist/io/opc/read-options.d.ts +2 -2
  78. package/dist/io/opc/sniff-format.d.ts +2 -2
  79. package/dist/io/style/xf-style.d.ts +38 -6
  80. package/dist/io/style/xf-style.js +22 -0
  81. package/dist/io/xlsb/errors.d.ts +1 -1
  82. package/dist/io/xlsb/formula.d.ts +4 -4
  83. package/dist/io/xlsb/primitives.d.ts +8 -8
  84. package/dist/io/xlsb/ptg-functions.d.ts +1 -1
  85. package/dist/io/xlsb/read-styles.js +2 -20
  86. package/dist/io/xlsb/read.d.ts +2 -2
  87. package/dist/io/xlsx/cell-accumulator.d.ts +25 -6
  88. package/dist/io/xlsx/cell-accumulator.js +111 -30
  89. package/dist/io/xlsx/cell-value.d.ts +2 -2
  90. package/dist/io/xlsx/cell-value.js +3 -3
  91. package/dist/io/xlsx/color-xml.js +11 -17
  92. package/dist/io/xlsx/comments.d.ts +5 -5
  93. package/dist/io/xlsx/comments.js +13 -6
  94. package/dist/io/xlsx/conditional-formatting.d.ts +3 -3
  95. package/dist/io/xlsx/conditional-formatting.js +7 -16
  96. package/dist/io/xlsx/data-validation.d.ts +2 -2
  97. package/dist/io/xlsx/data-validation.js +1 -1
  98. package/dist/io/xlsx/errors.d.ts +3 -3
  99. package/dist/io/xlsx/hyperlinks.d.ts +4 -2
  100. package/dist/io/xlsx/hyperlinks.js +5 -5
  101. package/dist/io/xlsx/images.d.ts +1 -1
  102. package/dist/io/xlsx/images.js +8 -8
  103. package/dist/io/xlsx/namespaces.d.ts +2 -2
  104. package/dist/io/xlsx/package-plan.js +5 -2
  105. package/dist/io/xlsx/read-pivot.js +2 -5
  106. package/dist/io/xlsx/read-rows.d.ts +13 -13
  107. package/dist/io/xlsx/read-rows.js +19 -55
  108. package/dist/io/xlsx/read-shared-strings.js +7 -5
  109. package/dist/io/xlsx/read-styles.d.ts +3 -3
  110. package/dist/io/xlsx/read-styles.js +40 -65
  111. package/dist/io/xlsx/read-worksheet.js +61 -115
  112. package/dist/io/xlsx/read.d.ts +3 -5
  113. package/dist/io/xlsx/read.js +61 -69
  114. package/dist/io/xlsx/rich-runs.d.ts +1 -1
  115. package/dist/io/xlsx/rich-runs.js +1 -1
  116. package/dist/io/xlsx/rich-text.d.ts +1 -1
  117. package/dist/io/xlsx/shared-strings.d.ts +2 -2
  118. package/dist/io/xlsx/sheet-properties.js +2 -2
  119. package/dist/io/xlsx/styles.d.ts +8 -9
  120. package/dist/io/xlsx/styles.js +4 -3
  121. package/dist/io/xlsx/tables.d.ts +2 -2
  122. package/dist/io/xlsx/tables.js +8 -13
  123. package/dist/io/xlsx/theme-xml.d.ts +37 -0
  124. package/dist/io/xlsx/theme-xml.js +142 -0
  125. package/dist/io/xlsx/threaded-comments.d.ts +18 -27
  126. package/dist/io/xlsx/threaded-comments.js +9 -21
  127. package/dist/io/xlsx/worksheet-xml.d.ts +2 -2
  128. package/dist/io/xlsx/worksheet-xml.js +7 -12
  129. package/dist/io/xlsx/write-stream.d.ts +15 -15
  130. package/dist/io/xlsx/write-stream.js +3 -3
  131. package/dist/io/xlsx/write.d.ts +8 -7
  132. package/dist/io/xlsx/write.js +6 -3
  133. package/dist/io/xlsx/x14-ext.d.ts +1 -1
  134. package/dist/vba/bytes.d.ts +12 -0
  135. package/dist/vba/bytes.js +40 -0
  136. package/dist/vba/cfb-writer.d.ts +1 -1
  137. package/dist/vba/cfb.d.ts +1 -1
  138. package/dist/vba/cfb.js +15 -51
  139. package/dist/vba/codepage.d.ts +2 -2
  140. package/dist/vba/errors.d.ts +2 -2
  141. package/dist/vba/index.d.ts +2 -2
  142. package/dist/vba/index.js +2 -2
  143. package/dist/vba/ms-ovba.d.ts +1 -1
  144. package/dist/vba/ms-ovba.js +1 -3
  145. package/dist/vba/project-editor.d.ts +9 -9
  146. package/dist/vba/project-editor.js +2 -11
  147. package/dist/vba/project.d.ts +5 -5
  148. package/dist/vba/project.js +1 -10
  149. package/dist/vba/vba-encoding.d.ts +1 -1
  150. package/dist/xml/errors.d.ts +1 -1
  151. package/dist/xml/xml-read.d.ts +38 -9
  152. package/dist/xml/xml-read.js +23 -0
  153. package/dist/xml/xml.d.ts +31 -9
  154. package/dist/xml/xml.js +23 -3
  155. package/package.json +41 -35
@@ -1,6 +1,6 @@
1
- import { assignStyleFacets, isBorderStyle, isFillPatternType, isFontScheme, isFontVerticalAlignment, isHorizontalAlignment, isNamedUnderlineStyle, isVerticalAlignment, } from '../../core/style.js';
2
- import { boolPresent, boolStrict, closeEmptyElements, localName, openElements, xmlEvents, } from '../../xml/xml-read.js';
3
- import { numFmtCodeFor } from '../style/xf-style.js';
1
+ import { isBorderStyle, isFillPatternType, isFontScheme, isFontVerticalAlignment, isHorizontalAlignment, isNamedUnderlineStyle, isVerticalAlignment, } from '../../core/style.js';
2
+ import { boolPresent, boolStrict, closeEmptyElements, localName, numFinite, numInteger, openElements, xmlEvents, } from '../../xml/xml-read.js';
3
+ import { numFmtCodeFor, resolveStyleTable, } from '../style/xf-style.js';
4
4
  import { parseColor } from './color-xml.js';
5
5
  const BORDER_EDGE_NAMES = ['left', 'right', 'top', 'bottom', 'diagonal'];
6
6
  const BORDER_EDGES = new Set(BORDER_EDGE_NAMES);
@@ -53,24 +53,7 @@ export function parseStyleTable(xml) {
53
53
  }
54
54
  next = events.next();
55
55
  }
56
- const cellXfs = xfStyles.map((xf) => {
57
- if (xf.xfId === undefined)
58
- return xf;
59
- const named = namedXfs[xf.xfId];
60
- return named === undefined ? xf : { ...named, ...xf };
61
- });
62
- const namedStyles = namedXfs.map((xf, index) => {
63
- const label = cellStyleNames.find((entry) => entry.xfId === index);
64
- const style = {};
65
- assignStyleFacets(style, xf);
66
- if (label?.name !== undefined)
67
- style.name = label.name;
68
- if (label?.builtinId !== undefined)
69
- style.builtinId = label.builtinId;
70
- return style;
71
- });
72
- const defaultFont = fonts[0];
73
- return defaultFont === undefined ? { cellXfs, namedStyles } : { cellXfs, namedStyles, defaultFont };
56
+ return resolveStyleTable({ directXfs: xfStyles, namedXfs, labels: cellStyleNames, fonts });
74
57
  }
75
58
  function* until(events, container) {
76
59
  let next = events.next();
@@ -86,8 +69,8 @@ function parseNumFmts(events) {
86
69
  const codes = new Map();
87
70
  for (const event of until(events, 'numFmts')) {
88
71
  if (event.kind === 'open' && localName(event.name) === 'numFmt') {
89
- const id = Number(event.attrs.numFmtId);
90
- if (Number.isInteger(id) && id > 0 && event.attrs.formatCode !== undefined) {
72
+ const id = numInteger(event.attrs.numFmtId, 1);
73
+ if (id !== undefined && event.attrs.formatCode !== undefined) {
91
74
  codes.set(id, event.attrs.formatCode);
92
75
  }
93
76
  }
@@ -151,8 +134,7 @@ function parseFills(events) {
151
134
  break;
152
135
  case 'stop':
153
136
  if (gradientDraft !== null) {
154
- const position = Number(attrs.position);
155
- gradientDraft.stopPosition = Number.isFinite(position) ? position : 0;
137
+ gradientDraft.stopPosition = numFinite(attrs.position) ?? 0;
156
138
  gradientDraft.stopColor = undefined;
157
139
  }
158
140
  break;
@@ -271,12 +253,12 @@ function parseXfTable(events, container, deps) {
271
253
  return xfs;
272
254
  }
273
255
  function resolveXf(attrs, deps, captureXfId) {
274
- const fillId = Number(attrs.fillId);
275
- const fill = Number.isInteger(fillId) ? deps.fills[fillId] : undefined;
276
- const fontId = Number(attrs.fontId);
277
- const font = Number.isInteger(fontId) ? deps.fonts[fontId] : undefined;
278
- const borderId = Number(attrs.borderId);
279
- const border = Number.isInteger(borderId) && borderId > 0 ? deps.borders[borderId] : undefined;
256
+ const fillId = numInteger(attrs.fillId, 0);
257
+ const fill = fillId !== undefined ? deps.fills[fillId] : undefined;
258
+ const fontId = numInteger(attrs.fontId, 0);
259
+ const font = fontId !== undefined ? deps.fonts[fontId] : undefined;
260
+ const borderId = numInteger(attrs.borderId, 1);
261
+ const border = borderId !== undefined ? deps.borders[borderId] : undefined;
280
262
  const numFmt = resolveNumFmt(attrs.numFmtId, deps.numFmtCodes);
281
263
  const draft = {};
282
264
  if (fill)
@@ -289,9 +271,9 @@ function resolveXf(attrs, deps, captureXfId) {
289
271
  draft.border = border;
290
272
  if (boolStrict(attrs.quotePrefix))
291
273
  draft.quotePrefix = true;
292
- if (captureXfId && attrs.xfId !== undefined) {
293
- const xfId = Number(attrs.xfId);
294
- if (Number.isInteger(xfId) && xfId > 0)
274
+ if (captureXfId) {
275
+ const xfId = numInteger(attrs.xfId, 1);
276
+ if (xfId !== undefined)
295
277
  draft.xfId = xfId;
296
278
  }
297
279
  return draft;
@@ -301,16 +283,14 @@ function parseCellStyles(events) {
301
283
  for (const event of until(events, 'cellStyles')) {
302
284
  if (event.kind === 'open' && localName(event.name) === 'cellStyle') {
303
285
  const attrs = event.attrs;
304
- const xfId = Number(attrs.xfId);
305
- if (Number.isInteger(xfId)) {
286
+ const xfId = numInteger(attrs.xfId);
287
+ if (xfId !== undefined) {
306
288
  const entry = { xfId };
307
289
  if (attrs.name !== undefined)
308
290
  entry.name = attrs.name;
309
- if (attrs.builtinId !== undefined) {
310
- const builtinId = Number(attrs.builtinId);
311
- if (Number.isInteger(builtinId))
312
- entry.builtinId = builtinId;
313
- }
291
+ const builtinId = numInteger(attrs.builtinId);
292
+ if (builtinId !== undefined)
293
+ entry.builtinId = builtinId;
314
294
  names.push(entry);
315
295
  }
316
296
  }
@@ -346,8 +326,8 @@ export function applyFontChild(draft, local, attrs) {
346
326
  draft.vertAlign = attrs.val;
347
327
  break;
348
328
  case 'sz': {
349
- const size = Number(attrs.val);
350
- if (Number.isFinite(size))
329
+ const size = numFinite(attrs.val);
330
+ if (size !== undefined)
351
331
  draft.size = size;
352
332
  break;
353
333
  }
@@ -360,14 +340,14 @@ export function applyFontChild(draft, local, attrs) {
360
340
  draft.name = attrs.val;
361
341
  break;
362
342
  case 'family': {
363
- const family = Number(attrs.val);
364
- if (Number.isInteger(family))
343
+ const family = numInteger(attrs.val);
344
+ if (family !== undefined)
365
345
  draft.family = family;
366
346
  break;
367
347
  }
368
348
  case 'charset': {
369
- const charset = Number(attrs.val);
370
- if (Number.isInteger(charset))
349
+ const charset = numInteger(attrs.val);
350
+ if (charset !== undefined)
371
351
  draft.charset = charset;
372
352
  break;
373
353
  }
@@ -380,7 +360,8 @@ export function applyFontChild(draft, local, attrs) {
380
360
  }
381
361
  }
382
362
  function resolveNumFmt(raw, custom) {
383
- return raw === undefined ? undefined : numFmtCodeFor(Number(raw), custom);
363
+ const id = numInteger(raw, 1);
364
+ return id === undefined ? undefined : numFmtCodeFor(id, custom);
384
365
  }
385
366
  function toFill(pattern, fgColor, bgColor) {
386
367
  if (!isFillPatternType(pattern) || pattern === 'none')
@@ -394,8 +375,8 @@ function toFill(pattern, fgColor, bgColor) {
394
375
  }
395
376
  function assignGradientNumbers(fill, attrs) {
396
377
  for (const key of ['degree', 'left', 'right', 'top', 'bottom']) {
397
- const value = Number(attrs[key]);
398
- if (attrs[key] !== undefined && Number.isFinite(value))
378
+ const value = numFinite(attrs[key]);
379
+ if (value !== undefined)
399
380
  fill[key] = value;
400
381
  }
401
382
  }
@@ -414,25 +395,19 @@ function parseAlignment(attrs) {
414
395
  }
415
396
  if (attrs.vertical !== undefined && isVerticalAlignment(attrs.vertical))
416
397
  out.vertical = attrs.vertical;
417
- if (attrs.textRotation !== undefined) {
418
- const rotation = Number(attrs.textRotation);
419
- if (Number.isFinite(rotation) && rotation !== 0)
420
- out.textRotation = rotation;
421
- }
398
+ const rotation = numFinite(attrs.textRotation);
399
+ if (rotation !== undefined && rotation !== 0)
400
+ out.textRotation = rotation;
422
401
  if (boolStrict(attrs.wrapText))
423
402
  out.wrapText = true;
424
- if (attrs.indent !== undefined) {
425
- const indent = Number(attrs.indent);
426
- if (Number.isInteger(indent) && indent !== 0)
427
- out.indent = indent;
428
- }
403
+ const indent = numInteger(attrs.indent);
404
+ if (indent !== undefined && indent !== 0)
405
+ out.indent = indent;
429
406
  if (boolStrict(attrs.shrinkToFit))
430
407
  out.shrinkToFit = true;
431
- if (attrs.readingOrder !== undefined) {
432
- const order = Number(attrs.readingOrder);
433
- if (Number.isInteger(order) && order !== 0)
434
- out.readingOrder = order;
435
- }
408
+ const order = numInteger(attrs.readingOrder);
409
+ if (order !== undefined && order !== 0)
410
+ out.readingOrder = order;
436
411
  return Object.keys(out).length > 0 ? out : undefined;
437
412
  }
438
413
  function parseProtection(attrs) {
@@ -1,9 +1,9 @@
1
- import { decodeRange } from '../../core/address.js';
1
+ import { decodeRange, MAX_COLUMN, MAX_ROW } from '../../core/address.js';
2
2
  import { isCustomFilterOperator, } from '../../core/autofilter.js';
3
3
  import { INTERNAL } from '../../core/internal.js';
4
4
  import { SHEET_PROTECTION_FLAGS, } from '../../core/protection.js';
5
5
  import { assignStyleFacets } from '../../core/style.js';
6
- import { boolPresent, boolStrict, boolTristate, localName, parseXml, } from '../../xml/xml-read.js';
6
+ import { boolPresent, boolStrict, boolTristate, decodeSpreadsheetText, localName, numFinite, numInteger, parseXml, } from '../../xml/xml-read.js';
7
7
  import { CellAccumulator } from './cell-accumulator.js';
8
8
  import { parseColor } from './color-xml.js';
9
9
  const MARGIN_SIDES = ['left', 'right', 'top', 'bottom', 'header', 'footer'];
@@ -27,20 +27,18 @@ function parseSheetProtection(attrs) {
27
27
  flags[key] = !boolStrict(raw);
28
28
  }
29
29
  const { algorithmName, hashValue, saltValue, spinCount } = attrs;
30
+ const spin = numInteger(spinCount, 0);
30
31
  if (algorithmName !== undefined &&
31
32
  hashValue !== undefined &&
32
33
  saltValue !== undefined &&
33
- spinCount !== undefined) {
34
- const spin = Number(spinCount);
35
- if (Number.isFinite(spin)) {
36
- const credential = {
37
- algorithmName,
38
- hashValue,
39
- saltValue,
40
- spinCount: spin,
41
- };
42
- return { flags, credential };
43
- }
34
+ spin !== undefined) {
35
+ const credential = {
36
+ algorithmName,
37
+ hashValue,
38
+ saltValue,
39
+ spinCount: spin,
40
+ };
41
+ return { flags, credential };
44
42
  }
45
43
  return { flags };
46
44
  }
@@ -57,7 +55,7 @@ class AutoFilterAccumulator {
57
55
  this.#columns = [];
58
56
  }
59
57
  beginColumn(attrs) {
60
- this.#colId = attrs.colId !== undefined ? Number(attrs.colId) : -1;
58
+ this.#colId = numInteger(attrs.colId, 0) ?? -1;
61
59
  this.#values = null;
62
60
  this.#blank = false;
63
61
  this.#predicates = null;
@@ -114,12 +112,12 @@ class PageBreakAccumulator {
114
112
  add(attrs) {
115
113
  if (this.#target === null)
116
114
  return;
117
- const id = Number(attrs.id);
118
- if (!Number.isInteger(id) || id < 1)
115
+ const id = numInteger(attrs.id, 1);
116
+ if (id === undefined)
119
117
  return;
120
118
  const brk = { id };
121
- const max = Number(attrs.max);
122
- if (Number.isInteger(max) && max >= 0)
119
+ const max = numInteger(attrs.max, 0);
120
+ if (max !== undefined)
123
121
  brk.max = max;
124
122
  if (boolStrict(attrs.man))
125
123
  brk.man = true;
@@ -127,10 +125,7 @@ class PageBreakAccumulator {
127
125
  }
128
126
  }
129
127
  export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
130
- const cell = new CellAccumulator();
131
- let inInlineString = false;
132
- let capture = false;
133
- let text = '';
128
+ const cell = new CellAccumulator({ richRuns: true });
134
129
  let rowStyle = -1;
135
130
  let rowCustomFormat = false;
136
131
  const autoFilter = new AutoFilterAccumulator();
@@ -148,46 +143,24 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
148
143
  parseXml(xml, {
149
144
  onOpen(name, attrs, selfClosing) {
150
145
  const local = localName(name);
151
- text = '';
152
- capture = false;
146
+ if (cell.openElement(local, attrs, selfClosing))
147
+ return;
153
148
  switch (local) {
154
149
  case 'col':
155
150
  applyColumn(sheet, attrs, xfStyles, columnStyle);
156
151
  break;
157
152
  case 'row':
158
153
  applyRow(sheet, attrs);
159
- rowStyle = attrs.s !== undefined ? Number(attrs.s) : -1;
154
+ rowStyle = numInteger(attrs.s, 0) ?? -1;
160
155
  rowCustomFormat = boolStrict(attrs.customFormat);
161
156
  break;
162
- case 'c':
163
- cell.beginCell(attrs);
164
- break;
165
- case 'is':
166
- inInlineString = true;
167
- cell.beginInlineString();
168
- break;
169
- case 'r':
170
- if (inInlineString)
171
- cell.runs.beginRun();
172
- break;
173
- case 'rPr':
174
- cell.runs.beginProperties();
175
- break;
176
- case 'f':
177
- capture = true;
178
- cell.beginFormula(attrs, selfClosing);
179
- break;
180
- case 'v':
181
- case 't':
182
- capture = true;
183
- break;
184
157
  case 'oddHeader':
185
158
  case 'oddFooter':
186
159
  case 'evenHeader':
187
160
  case 'evenFooter':
188
161
  case 'firstHeader':
189
162
  case 'firstFooter':
190
- capture = true;
163
+ cell.capture();
191
164
  break;
192
165
  case 'mergeCell':
193
166
  if (attrs.ref !== undefined && attrs.ref !== '') {
@@ -245,41 +218,27 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
245
218
  cell.runs.applyProperty(local, attrs);
246
219
  break;
247
220
  }
248
- if (selfClosing && (local === 'f' || local === 'v'))
249
- capture = false;
250
221
  },
251
222
  onText(chunk) {
252
- if (capture)
253
- text += chunk;
223
+ cell.appendChunk(chunk);
254
224
  },
255
225
  onClose(name) {
256
226
  const local = localName(name);
227
+ const claimed = cell.closeElement(local);
228
+ if (claimed === 'cell') {
229
+ finalizeCellFromState();
230
+ return;
231
+ }
232
+ if (claimed === 'claimed')
233
+ return;
257
234
  switch (local) {
258
- case 'f':
259
- cell.setFormula(text);
260
- break;
261
- case 'v':
262
- cell.setValue(text);
263
- break;
264
- case 't':
265
- cell.appendText(text, inInlineString);
266
- break;
267
- case 'r':
268
- cell.runs.endRun();
269
- break;
270
- case 'is':
271
- inInlineString = false;
272
- break;
273
235
  case 'oddHeader':
274
236
  case 'oddFooter':
275
237
  case 'evenHeader':
276
238
  case 'evenFooter':
277
239
  case 'firstHeader':
278
240
  case 'firstFooter':
279
- sheet.headerFooter[local] = text;
280
- break;
281
- case 'c':
282
- finalizeCellFromState();
241
+ sheet.headerFooter[local] = decodeSpreadsheetText(cell.capturedText);
283
242
  break;
284
243
  case 'row':
285
244
  rowStyle = -1;
@@ -298,7 +257,6 @@ export function parseWorksheet(xml, sheet, sharedStrings, xfStyles) {
298
257
  default:
299
258
  break;
300
259
  }
301
- capture = false;
302
260
  },
303
261
  }, { closeEmptyElements: WORKSHEET_EMPTY_CLOSES });
304
262
  }
@@ -321,10 +279,12 @@ function applySheetProperties(local, attrs, sheet) {
321
279
  case 'pane':
322
280
  if (attrs.state === 'frozen' || attrs.state === 'frozenSplit') {
323
281
  sheet.view.state = 'frozen';
324
- if (attrs.xSplit !== undefined)
325
- sheet.view.xSplit = Number(attrs.xSplit);
326
- if (attrs.ySplit !== undefined)
327
- sheet.view.ySplit = Number(attrs.ySplit);
282
+ const xSplit = numInteger(attrs.xSplit, 0);
283
+ const ySplit = numInteger(attrs.ySplit, 0);
284
+ if (xSplit !== undefined)
285
+ sheet.view.xSplit = xSplit;
286
+ if (ySplit !== undefined)
287
+ sheet.view.ySplit = ySplit;
328
288
  if (attrs.topLeftCell !== undefined)
329
289
  sheet.view.topLeftCell = attrs.topLeftCell;
330
290
  }
@@ -345,25 +305,24 @@ function applySheetProperties(local, attrs, sheet) {
345
305
  }
346
306
  }
347
307
  function applyColumn(sheet, attrs, xfStyles, columnStyle) {
348
- const min = Number(attrs.min);
349
- const max = Number(attrs.max);
350
- if (!Number.isInteger(min) || !Number.isInteger(max) || min < 1)
308
+ const min = numInteger(attrs.min, 1);
309
+ const max = numInteger(attrs.max, 1);
310
+ if (min === undefined || max === undefined || min > MAX_COLUMN)
351
311
  return;
352
- const width = attrs.width !== undefined ? Number(attrs.width) : undefined;
312
+ const last = Math.min(max, MAX_COLUMN);
313
+ const width = numFinite(attrs.width);
353
314
  const hidden = boolStrict(attrs.hidden);
354
- const styleIndex = attrs.style !== undefined ? Number(attrs.style) : -1;
315
+ const styleIndex = numInteger(attrs.style, 0) ?? -1;
355
316
  const style = styleIndex >= 0 ? xfStyles[styleIndex] : undefined;
356
- for (let index = min; index <= max; index++) {
317
+ for (let index = min; index <= last; index++) {
357
318
  const column = sheet.getColumn(index);
358
- if (width !== undefined && Number.isFinite(width) && attrs.customWidth !== '0')
319
+ if (width !== undefined && boolPresent(attrs.customWidth))
359
320
  column.width = width;
360
321
  if (hidden)
361
322
  column.hidden = true;
362
- if (attrs.outlineLevel !== undefined) {
363
- const level = Number(attrs.outlineLevel);
364
- if (Number.isInteger(level) && level > 0)
365
- column.outlineLevel = level;
366
- }
323
+ const outlineLevel = numInteger(attrs.outlineLevel, 1);
324
+ if (outlineLevel !== undefined)
325
+ column.outlineLevel = outlineLevel;
367
326
  if (boolStrict(attrs.collapsed))
368
327
  column.collapsed = true;
369
328
  if (style !== undefined)
@@ -373,22 +332,18 @@ function applyColumn(sheet, attrs, xfStyles, columnStyle) {
373
332
  }
374
333
  }
375
334
  function applyRow(sheet, attrs) {
376
- const number = Number(attrs.r);
377
- if (!Number.isInteger(number) || number < 1)
335
+ const number = numInteger(attrs.r, 1);
336
+ if (number === undefined || number > MAX_ROW)
378
337
  return;
379
338
  const row = sheet.getRow(number);
380
- if (attrs.ht !== undefined && attrs.customHeight !== '0') {
381
- const height = Number(attrs.ht);
382
- if (Number.isFinite(height))
383
- row.height = height;
384
- }
339
+ const height = numFinite(attrs.ht);
340
+ if (height !== undefined && boolPresent(attrs.customHeight))
341
+ row.height = height;
385
342
  if (boolStrict(attrs.hidden))
386
343
  row.hidden = true;
387
- if (attrs.outlineLevel !== undefined) {
388
- const level = Number(attrs.outlineLevel);
389
- if (Number.isInteger(level) && level > 0)
390
- row.outlineLevel = level;
391
- }
344
+ const outlineLevel = numInteger(attrs.outlineLevel, 1);
345
+ if (outlineLevel !== undefined)
346
+ row.outlineLevel = outlineLevel;
392
347
  if (boolStrict(attrs.collapsed))
393
348
  row.collapsed = true;
394
349
  }
@@ -411,31 +366,22 @@ function applyPrintOptions(printOptions, attrs) {
411
366
  }
412
367
  function applyMargins(margins, attrs) {
413
368
  for (const side of MARGIN_SIDES) {
414
- const raw = attrs[side];
415
- if (raw === undefined)
416
- continue;
417
- const value = Number(raw);
418
- if (Number.isFinite(value))
369
+ const value = numFinite(attrs[side]);
370
+ if (value !== undefined)
419
371
  margins[side] = value;
420
372
  }
421
373
  }
422
374
  function applyPageSetup(pageSetup, attrs) {
423
- const num = (raw) => {
424
- if (raw === undefined)
425
- return undefined;
426
- const value = Number(raw);
427
- return Number.isFinite(value) ? value : undefined;
428
- };
429
- const paperSize = num(attrs.paperSize);
375
+ const paperSize = numInteger(attrs.paperSize, 0);
430
376
  if (paperSize !== undefined)
431
377
  pageSetup.paperSize = paperSize;
432
- const scale = num(attrs.scale);
378
+ const scale = numInteger(attrs.scale, 0);
433
379
  if (scale !== undefined)
434
380
  pageSetup.scale = scale;
435
- const fitToWidth = num(attrs.fitToWidth);
381
+ const fitToWidth = numInteger(attrs.fitToWidth, 0);
436
382
  if (fitToWidth !== undefined)
437
383
  pageSetup.fitToWidth = fitToWidth;
438
- const fitToHeight = num(attrs.fitToHeight);
384
+ const fitToHeight = numInteger(attrs.fitToHeight, 0);
439
385
  if (fitToHeight !== undefined)
440
386
  pageSetup.fitToHeight = fitToHeight;
441
387
  if (attrs.pageOrder === 'downThenOver' || attrs.pageOrder === 'overThenDown') {
@@ -1,5 +1,4 @@
1
1
  import { Workbook, type WorkbookView } from '../../core/workbook.ts';
2
- import { type WorkbookProtection } from '../../core/workbook-protection.ts';
3
2
  import type { WorksheetState } from '../../core/worksheet.ts';
4
3
  import { type ReadXlsxOptions } from '../opc/read-options.ts';
5
4
  export { parseRelationships, resolveWorkbookPart } from '../opc/read-opc.ts';
@@ -11,14 +10,14 @@ export { parseStyleTable } from './read-styles.ts';
11
10
  *
12
11
  * Both OOXML serialisations are accepted: an XML `.xlsx`, and a binary `.xlsb` (BIFF12), which is the
13
12
  * same OPC container with binary office-document parts. The two are auto-detected from the package
14
- * itself rather than from a file extension, so a caller never branches on which form it holds and
13
+ * itself rather than from a file extension, so a caller never branches on which form it holds, and
15
14
  * the model produced is the same either way. See `../xlsb/read.ts` for what the binary path does not
16
15
  * yet decode.
17
16
  *
18
- * @throws {UnsupportedFormatError} if the input is neither a legacy `.xls` (`.format === 'xls'`) or
17
+ * @throws {UnsupportedFormatError} if the input is neither: a legacy `.xls` (`.format === 'xls'`) or
19
18
  * an unrecognised/non-ZIP blob (`'unknown'`).
20
19
  * @throws {XlsbParseError} if a binary `.xlsb` part is malformed.
21
- * @throws {PackageReadError} if the input is a ZIP that cannot be unpacked a corrupt or
20
+ * @throws {PackageReadError} if the input is a ZIP that cannot be unpacked: a corrupt or
22
21
  * truncated archive, or one exceeding the inflate bound (a probable zip bomb).
23
22
  */
24
23
  export declare function readXlsx(data: Uint8Array, options?: ReadXlsxOptions): Workbook;
@@ -28,5 +27,4 @@ export interface SheetEntry {
28
27
  readonly state?: WorksheetState['state'];
29
28
  }
30
29
  export declare function parseWorkbookSheets(xml: string): SheetEntry[];
31
- export declare function parseWorkbookProtection(xml: string): WorkbookProtection | undefined;
32
30
  export declare function applyWorkbookView(view: WorkbookView, xml: string): void;