reamkit 1.15.3 → 1.16.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 (95) hide show
  1. package/dist/esm/core/converter/facade.d.ts +5 -0
  2. package/dist/esm/core/converter/ream.d.ts +6 -0
  3. package/dist/esm/core/converter/ream.js +34 -8
  4. package/dist/esm/core/document-model/index.d.ts +1 -1
  5. package/dist/esm/core/document-model/types.d.ts +187 -1
  6. package/dist/esm/core/drawingml/chart-geometry.d.ts +28 -0
  7. package/dist/esm/core/drawingml/chart-geometry.js +371 -88
  8. package/dist/esm/core/drawingml/chart-parser.js +262 -11
  9. package/dist/esm/core/drawingml/colors.d.ts +6 -6
  10. package/dist/esm/core/drawingml/colors.js +58 -18
  11. package/dist/esm/core/drawingml/preset-geometry.js +7 -6
  12. package/dist/esm/core/drawingml/sparkline-geometry.js +6 -4
  13. package/dist/esm/core/drawingml/theme-parser.d.ts +41 -0
  14. package/dist/esm/core/drawingml/theme-parser.js +74 -1
  15. package/dist/esm/core/font/ttf-subset.js +26 -1
  16. package/dist/esm/core/images.js +172 -43
  17. package/dist/esm/core/indexed-colors.d.ts +11 -0
  18. package/dist/esm/core/indexed-colors.js +81 -0
  19. package/dist/esm/core/ir/sheet.d.ts +67 -3
  20. package/dist/esm/{excel → core}/number-format.d.ts +37 -0
  21. package/dist/esm/core/number-format.js +800 -0
  22. package/dist/esm/core/opc/alternate-content.d.ts +13 -0
  23. package/dist/esm/core/opc/alternate-content.js +72 -0
  24. package/dist/esm/core/opc/core-properties.js +1 -0
  25. package/dist/esm/core/opc/package.d.ts +14 -1
  26. package/dist/esm/core/opc/package.js +43 -4
  27. package/dist/esm/core/opc/relationships.js +1 -0
  28. package/dist/esm/core/opc/xml-entities.d.ts +12 -0
  29. package/dist/esm/core/opc/xml-entities.js +91 -0
  30. package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
  31. package/dist/esm/core/spreadsheet-model/types.d.ts +137 -0
  32. package/dist/esm/core/vector.d.ts +13 -0
  33. package/dist/esm/excel/activex-parser.d.ts +9 -0
  34. package/dist/esm/excel/activex-parser.js +16 -1
  35. package/dist/esm/excel/column-bands.d.ts +26 -1
  36. package/dist/esm/excel/column-bands.js +156 -20
  37. package/dist/esm/excel/comments-parser.js +5 -3
  38. package/dist/esm/excel/conditional-format.d.ts +25 -2
  39. package/dist/esm/excel/conditional-format.js +63 -19
  40. package/dist/esm/excel/escaped-text.d.ts +9 -0
  41. package/dist/esm/excel/escaped-text.js +20 -0
  42. package/dist/esm/excel/form-control-parser.js +1 -0
  43. package/dist/esm/excel/formula/dates.js +1 -1
  44. package/dist/esm/excel/header-footer.d.ts +9 -1
  45. package/dist/esm/excel/header-footer.js +162 -14
  46. package/dist/esm/excel/index.d.ts +1 -1
  47. package/dist/esm/excel/index.js +2 -2
  48. package/dist/esm/excel/pivot-table-parser.js +1 -0
  49. package/dist/esm/excel/print-model.d.ts +75 -0
  50. package/dist/esm/excel/print-model.js +902 -77
  51. package/dist/esm/excel/printer-settings.d.ts +16 -0
  52. package/dist/esm/excel/printer-settings.js +36 -0
  53. package/dist/esm/excel/rich-value.d.ts +13 -0
  54. package/dist/esm/excel/rich-value.js +120 -0
  55. package/dist/esm/excel/shared-strings-parser.js +11 -7
  56. package/dist/esm/excel/sheet-drawing.d.ts +11 -0
  57. package/dist/esm/excel/sheet-drawing.js +26 -3
  58. package/dist/esm/excel/sheet-shape-parser.d.ts +53 -1
  59. package/dist/esm/excel/sheet-shape-parser.js +461 -32
  60. package/dist/esm/excel/sheet-to-flow.d.ts +23 -2
  61. package/dist/esm/excel/sheet-to-flow.js +551 -36
  62. package/dist/esm/excel/slicer-parser.js +1 -0
  63. package/dist/esm/excel/styles-parser.d.ts +30 -2
  64. package/dist/esm/excel/styles-parser.js +177 -40
  65. package/dist/esm/excel/table-parser.js +1 -0
  66. package/dist/esm/excel/vml-drawing.d.ts +68 -0
  67. package/dist/esm/excel/vml-drawing.js +158 -0
  68. package/dist/esm/excel/workbook-parser.d.ts +5 -0
  69. package/dist/esm/excel/workbook-parser.js +5 -1
  70. package/dist/esm/excel/worksheet-parser.d.ts +2 -1
  71. package/dist/esm/excel/worksheet-parser.js +149 -28
  72. package/dist/esm/excel/xlsx-reader.js +271 -33
  73. package/dist/esm/excel/xlsx-to-pdf.js +12 -1
  74. package/dist/esm/html/html-writer.js +11 -2
  75. package/dist/esm/layout/page-doc.d.ts +26 -0
  76. package/dist/esm/layout/styled-layout.d.ts +2 -0
  77. package/dist/esm/layout/styled-layout.js +493 -64
  78. package/dist/esm/pdf/cid-font.js +20 -9
  79. package/dist/esm/pdf/objects.d.ts +13 -0
  80. package/dist/esm/pdf/objects.js +18 -1
  81. package/dist/esm/pdf/styled-page-emitter.js +164 -32
  82. package/dist/esm/pdf/text-page-renderer.js +1 -0
  83. package/dist/esm/pdf/vector-graphics.d.ts +3 -1
  84. package/dist/esm/pdf/vector-graphics.js +19 -2
  85. package/dist/esm/pptx/pptx-reader.js +1 -0
  86. package/dist/esm/pptx/slide-parser.js +12 -1
  87. package/dist/esm/svg/svg-writer.js +23 -4
  88. package/dist/esm/word/document-parser.js +1 -0
  89. package/dist/esm/word/drawing-parser.d.ts +34 -1
  90. package/dist/esm/word/drawing-parser.js +52 -2
  91. package/dist/esm/word/numbering-parser.js +1 -0
  92. package/dist/esm/word/settings-parser.js +1 -0
  93. package/dist/esm/word/styles-parser.js +1 -0
  94. package/package.json +7 -3
  95. package/dist/esm/excel/number-format.js +0 -476
@@ -1,4 +1,5 @@
1
1
  import { ParsedWorksheet } from '../core/spreadsheet-model/index.js';
2
+ import { ThemePalette } from './styles-parser.js';
2
3
  /**
3
4
  * Parse `worksheet.xml` (§18.3.1.99) into a {@link ParsedWorksheet}: a flat list
4
5
  * of cells with absolute row/column addresses and their raw stored values, plus
@@ -8,4 +9,4 @@ import { ParsedWorksheet } from '../core/spreadsheet-model/index.js';
8
9
  * and table parts). `r=` is optional on `<row>`/`<c>`; absent indices are inferred
9
10
  * from document order. A malformed root or missing `sheetData` yields an empty grid.
10
11
  */
11
- export declare function parseWorksheet(data: Uint8Array): ParsedWorksheet;
12
+ export declare function parseWorksheet(data: Uint8Array, theme?: ThemePalette): ParsedWorksheet;
@@ -1,9 +1,14 @@
1
+ import { INDEXED_COLORS } from "../core/indexed-colors.js";
1
2
  import { parseCellRef } from "./cell-reference.js";
2
3
  import { parseAreaRef } from "./defined-name-ref.js";
4
+ import { resolveInternalEntities } from "../core/opc/xml-entities.js";
5
+ import { decodeXstring } from "./escaped-text.js";
6
+ import { parseDxf } from "./styles-parser.js";
3
7
  import { XMLParser } from "fast-xml-parser";
4
8
  //#region src/excel/worksheet-parser.ts
5
9
  var decoder = new TextDecoder("utf-8");
6
10
  var parser = new XMLParser({
11
+ htmlEntities: true,
7
12
  ignoreAttributes: false,
8
13
  attributeNamePrefix: "@_",
9
14
  textNodeName: "#text",
@@ -21,9 +26,10 @@ var parser = new XMLParser({
21
26
  * and table parts). `r=` is optional on `<row>`/`<c>`; absent indices are inferred
22
27
  * from document order. A malformed root or missing `sheetData` yields an empty grid.
23
28
  */
24
- function parseWorksheet(data) {
25
- const xml = decoder.decode(data);
26
- const worksheet = parser.parse(xml)["worksheet"];
29
+ function parseWorksheet(data, theme) {
30
+ const xml = resolveInternalEntities(decoder.decode(data));
31
+ const tree = parser.parse(xml);
32
+ const worksheet = tree["worksheet"] ?? tree["chartsheet"];
27
33
  const emptyExtras = () => ({
28
34
  columns: [],
29
35
  merges: [],
@@ -45,7 +51,12 @@ function parseWorksheet(data) {
45
51
  const pane = parsePane(wsObj);
46
52
  const drawingNode = wsObj["drawing"];
47
53
  const drawingRelId = drawingNode && typeof drawingNode === "object" ? strAttr(drawingNode, "id") : void 0;
48
- const conditionalFormats = parseConditionalFormatting(wsObj);
54
+ const legacyNode = wsObj["legacyDrawing"];
55
+ const legacyDrawingRelId = legacyNode && typeof legacyNode === "object" ? strAttr(legacyNode, "id") : void 0;
56
+ const conditionalFormats = [...parseConditionalFormatting(wsObj), ...parseX14ConditionalFormatting(wsObj, {
57
+ ...theme ? { theme } : {},
58
+ indexed: INDEXED_COLORS
59
+ })];
49
60
  const dataValidations = parseDataValidations(wsObj);
50
61
  const hyperlinks = parseHyperlinks(wsObj);
51
62
  const headerFooter = parseHeaderFooter(wsObj);
@@ -63,6 +74,7 @@ function parseWorksheet(data) {
63
74
  ...colBreaks.length > 0 ? { colBreaks } : {},
64
75
  ...pane ? { pane } : {},
65
76
  ...drawingRelId !== void 0 ? { drawingRelId } : {},
77
+ ...legacyDrawingRelId !== void 0 ? { legacyDrawingRelId } : {},
66
78
  ...conditionalFormats.length > 0 ? { conditionalFormats } : {},
67
79
  ...dataValidations.length > 0 ? { dataValidations } : {},
68
80
  ...hyperlinks.length > 0 ? { hyperlinks } : {},
@@ -86,6 +98,7 @@ function parseWorksheet(data) {
86
98
  const rows = Array.isArray(rowRaw) ? rowRaw : rowRaw !== void 0 ? [rowRaw] : [];
87
99
  const cells = [];
88
100
  const rowHeights = [];
101
+ const rowStyles = [];
89
102
  let maxRow = -1;
90
103
  let maxColumn = -1;
91
104
  let currentRow = -1;
@@ -96,6 +109,11 @@ function parseWorksheet(data) {
96
109
  currentRow = explicitRow !== void 0 ? explicitRow : currentRow + 1;
97
110
  const height = parseRowHeight(obj, currentRow);
98
111
  if (height) rowHeights.push(height);
112
+ const rowStyle = Number(strAttr(obj, "s"));
113
+ if (boolAttr(obj, "customFormat") && Number.isFinite(rowStyle) && rowStyle > 0) rowStyles.push({
114
+ row: currentRow,
115
+ styleIndex: rowStyle
116
+ });
99
117
  const cellRaw = obj["c"];
100
118
  const rowCells = Array.isArray(cellRaw) ? cellRaw : cellRaw !== void 0 ? [cellRaw] : [];
101
119
  let prevCol = -1;
@@ -108,6 +126,7 @@ function parseWorksheet(data) {
108
126
  if (parsed.column > maxColumn) maxColumn = parsed.column;
109
127
  }
110
128
  }
129
+ const colStyles = parseColumnStyles(wsObj);
111
130
  return {
112
131
  cells,
113
132
  maxRow,
@@ -115,6 +134,8 @@ function parseWorksheet(data) {
115
134
  columns: parseColumns(wsObj),
116
135
  merges: parseMerges(wsObj),
117
136
  rowHeights,
137
+ ...colStyles.length > 0 ? { columnStyles: colStyles } : {},
138
+ ...rowStyles.length > 0 ? { rowStyles } : {},
118
139
  ...printModel
119
140
  };
120
141
  }
@@ -126,15 +147,17 @@ function parseRowIndex(obj) {
126
147
  }
127
148
  function parseRowHeight(obj, rowIndex) {
128
149
  if (rowIndex === void 0) return void 0;
150
+ const hidden = boolAttr(obj, "hidden");
129
151
  const htRaw = strAttr(obj, "ht");
130
- if (htRaw === void 0) return void 0;
131
- const heightPt = Number(htRaw);
132
- if (!Number.isFinite(heightPt)) return void 0;
152
+ const heightPt = htRaw !== void 0 ? Number(htRaw) : NaN;
153
+ if (!Number.isFinite(heightPt) && !hidden) return void 0;
133
154
  const customRaw = strAttr(obj, "customHeight");
155
+ const customHeight = customRaw === "1" || customRaw === "true";
134
156
  return {
135
157
  row: rowIndex,
136
- heightPt,
137
- customHeight: customRaw === "1" || customRaw === "true"
158
+ heightPt: Number.isFinite(heightPt) ? heightPt : 0,
159
+ customHeight,
160
+ ...hidden ? { hidden } : {}
138
161
  };
139
162
  }
140
163
  function parsePageMargins(ws) {
@@ -167,13 +190,18 @@ function parsePageSetup(ws) {
167
190
  const scale = parseNumericAttr(obj, "scale");
168
191
  const fitToWidth = parseNumericAttr(obj, "fitToWidth");
169
192
  const fitToHeight = parseNumericAttr(obj, "fitToHeight");
170
- if (paperSize === void 0 && orientation === void 0 && scale === void 0 && fitToWidth === void 0 && fitToHeight === void 0) return;
193
+ const printerSettingsRelId = strAttr(obj, "id");
194
+ const commentsRaw = strAttr(obj, "cellComments");
195
+ const cellComments = commentsRaw === "none" || commentsRaw === "asDisplayed" || commentsRaw === "atEnd" ? commentsRaw : void 0;
196
+ if (paperSize === void 0 && orientation === void 0 && scale === void 0 && fitToWidth === void 0 && fitToHeight === void 0 && printerSettingsRelId === void 0 && cellComments === void 0) return;
171
197
  return {
172
198
  ...paperSize !== void 0 ? { paperSize: Math.round(paperSize) } : {},
173
199
  ...orientation !== void 0 ? { orientation } : {},
174
200
  ...scale !== void 0 ? { scale } : {},
175
201
  ...fitToWidth !== void 0 ? { fitToWidth: Math.round(fitToWidth) } : {},
176
- ...fitToHeight !== void 0 ? { fitToHeight: Math.round(fitToHeight) } : {}
202
+ ...fitToHeight !== void 0 ? { fitToHeight: Math.round(fitToHeight) } : {},
203
+ ...printerSettingsRelId !== void 0 ? { printerSettingsRelId } : {},
204
+ ...cellComments !== void 0 ? { cellComments } : {}
177
205
  };
178
206
  }
179
207
  function parseFitToPage(ws) {
@@ -194,11 +222,13 @@ function parsePrintOptions(ws) {
194
222
  return raw === "1" || raw === "true";
195
223
  };
196
224
  const gridLines = flag("gridLines");
225
+ const headings = flag("headings");
197
226
  const horizontalCentered = flag("horizontalCentered");
198
227
  const verticalCentered = flag("verticalCentered");
199
- if (gridLines === void 0 && horizontalCentered === void 0 && verticalCentered === void 0) return;
228
+ if (gridLines === void 0 && headings === void 0 && horizontalCentered === void 0 && verticalCentered === void 0) return;
200
229
  return {
201
230
  ...gridLines !== void 0 ? { gridLines } : {},
231
+ ...headings !== void 0 ? { headings } : {},
202
232
  ...horizontalCentered !== void 0 ? { horizontalCentered } : {},
203
233
  ...verticalCentered !== void 0 ? { verticalCentered } : {}
204
234
  };
@@ -267,7 +297,7 @@ function parseSheetFormatPr(ws) {
267
297
  ...base !== void 0 && base > 0 ? { baseColWidthChars: base } : {}
268
298
  };
269
299
  }
270
- function parseColumns(ws) {
300
+ function parseColumnStyles(ws) {
271
301
  const colsNode = ws["cols"];
272
302
  if (!colsNode || typeof colsNode !== "object") return [];
273
303
  const colRaw = colsNode["col"];
@@ -278,15 +308,41 @@ function parseColumns(ws) {
278
308
  const obj = c;
279
309
  const min = Number(strAttr(obj, "min"));
280
310
  const max = Number(strAttr(obj, "max"));
281
- const width = Number(strAttr(obj, "width"));
282
- if (Number.isFinite(min) && Number.isFinite(max) && Number.isFinite(width)) out.push({
311
+ const styleIndex = Number(strAttr(obj, "style"));
312
+ if (!Number.isFinite(min) || !Number.isFinite(max)) continue;
313
+ if (!Number.isFinite(styleIndex) || styleIndex <= 0) continue;
314
+ out.push({
283
315
  min,
284
316
  max,
285
- widthChars: width
317
+ styleIndex
286
318
  });
287
319
  }
288
320
  return out;
289
321
  }
322
+ function parseColumns(ws) {
323
+ const colsNode = ws["cols"];
324
+ if (!colsNode || typeof colsNode !== "object") return [];
325
+ const colRaw = colsNode["col"];
326
+ const items = Array.isArray(colRaw) ? colRaw : colRaw !== void 0 ? [colRaw] : [];
327
+ const out = [];
328
+ for (const c of items) {
329
+ if (!c || typeof c !== "object") continue;
330
+ const obj = c;
331
+ const min = Number(strAttr(obj, "min"));
332
+ const max = Number(strAttr(obj, "max"));
333
+ const width = Number(strAttr(obj, "width"));
334
+ if (Number.isFinite(min) && Number.isFinite(max) && Number.isFinite(width)) {
335
+ const hidden = boolAttr(obj, "hidden");
336
+ out.push({
337
+ min,
338
+ max,
339
+ widthChars: width,
340
+ ...hidden ? { hidden } : {}
341
+ });
342
+ }
343
+ }
344
+ return out;
345
+ }
290
346
  function parseMerges(ws) {
291
347
  const mergeNode = ws["mergeCells"];
292
348
  if (!mergeNode || typeof mergeNode !== "object") return [];
@@ -339,6 +395,62 @@ function parseConditionalFormatting(ws) {
339
395
  }
340
396
  return out;
341
397
  }
398
+ /** The rule types the extension states as a formula rather than a literal. */
399
+ var TEXT_RULES = new Set([
400
+ "containsText",
401
+ "notContainsText",
402
+ "beginsWith",
403
+ "endsWith"
404
+ ]);
405
+ function parseX14ConditionalFormatting(ws, colors) {
406
+ const out = [];
407
+ for (const ext of toArray(asObjectNode(ws["extLst"])?.["ext"])) {
408
+ const group = asObjectNode(asObjectNode(ext)?.["conditionalFormattings"]);
409
+ if (!group) continue;
410
+ for (const cf of toArray(group["conditionalFormatting"])) {
411
+ const obj = asObjectNode(cf);
412
+ if (!obj) continue;
413
+ const sqref = typeof obj["sqref"] === "string" ? obj["sqref"] : void 0;
414
+ if (!sqref) continue;
415
+ const ranges = parseSqref(sqref);
416
+ if (ranges.length === 0) continue;
417
+ const rules = [];
418
+ for (const rn of toArray(obj["cfRule"])) {
419
+ const node = asObjectNode(rn);
420
+ if (!node) continue;
421
+ const rule = parseCfRule(asBaseCfRule(node));
422
+ if (!rule) continue;
423
+ const dxf = parseDxf(node["dxf"], colors);
424
+ rules.push("dxfId" in rule && Object.keys(dxf).length > 0 ? {
425
+ ...rule,
426
+ dxf
427
+ } : rule);
428
+ }
429
+ if (rules.length > 0) out.push({
430
+ ranges,
431
+ rules
432
+ });
433
+ }
434
+ }
435
+ return out;
436
+ }
437
+ /**
438
+ * Rewrite a `<x14:cfRule>` into the shape {@link parseCfRule} reads, so one
439
+ * reader serves both spellings of the same rule.
440
+ */
441
+ function asBaseCfRule(node) {
442
+ const formulas = toArray(node["f"]).filter((f) => typeof f === "string" || typeof f === "number");
443
+ const out = {
444
+ ...node,
445
+ formula: formulas.length === 1 ? formulas[0] : formulas
446
+ };
447
+ if (out["@_dxfId"] === void 0 && node["dxf"] !== void 0) out["@_dxfId"] = "0";
448
+ if (TEXT_RULES.has(String(out["@_type"])) && formulas.length > 0) {
449
+ out["@_type"] = "expression";
450
+ out["formula"] = formulas[0];
451
+ }
452
+ return out;
453
+ }
342
454
  var DV_TYPES = new Set([
343
455
  "none",
344
456
  "whole",
@@ -588,13 +700,16 @@ function parseDataBarRule(obj, priority) {
588
700
  if (!colorHex) return void 0;
589
701
  const minLength = parseNumericAttr(dbObj, "minLength");
590
702
  const maxLength = parseNumericAttr(dbObj, "maxLength");
703
+ const showValueRaw = strAttr(dbObj, "showValue");
704
+ const showValue = showValueRaw === "0" || showValueRaw === "false" ? false : void 0;
591
705
  return {
592
706
  type: "dataBar",
593
707
  priority,
594
708
  cfvos,
595
709
  colorHex,
596
710
  ...minLength !== void 0 ? { minLength } : {},
597
- ...maxLength !== void 0 ? { maxLength } : {}
711
+ ...maxLength !== void 0 ? { maxLength } : {},
712
+ ...showValue === false ? { showValue } : {}
598
713
  };
599
714
  }
600
715
  function parseCellIsRule(obj, priority) {
@@ -736,9 +851,15 @@ function collectControls(node, out, seen) {
736
851
  if (!relId || seen.has(relId)) continue;
737
852
  seen.add(relId);
738
853
  const name = strAttr(obj, "name");
854
+ const shapeId = strAttr(obj, "shapeId");
855
+ const controlPr = asObjectNode(obj["controlPr"]);
856
+ const printAttr = controlPr ? strAttr(controlPr, "print") : void 0;
857
+ const print = printAttr === "0" || printAttr === "false" ? false : void 0;
739
858
  out.push({
740
859
  relId,
741
- ...name ? { name } : {}
860
+ ...name ? { name } : {},
861
+ ...shapeId ? { shapeId } : {},
862
+ ...print === false ? { print } : {}
742
863
  });
743
864
  }
744
865
  }
@@ -752,7 +873,7 @@ function parseOleObjects(ws) {
752
873
  function collectOleObjects(node, out, seen) {
753
874
  if (!node) return;
754
875
  const direct = toArray(node["oleObject"]);
755
- const fromChoice = toArray(asObjectNode(node["AlternateContent"])?.["Choice"]).flatMap((c) => toArray(asObjectNode(c)?.["oleObject"]));
876
+ const fromChoice = toArray(node["AlternateContent"]).flatMap((ac) => toArray(asObjectNode(ac)?.["Choice"])).flatMap((c) => toArray(asObjectNode(c)?.["oleObject"]));
756
877
  for (const o of [...direct, ...fromChoice]) {
757
878
  const obj = asObjectNode(o);
758
879
  if (!obj) continue;
@@ -800,10 +921,13 @@ function parseCell(c, fallbackRow, fallbackCol) {
800
921
  const styleIndex = styleStr !== void 0 ? Number(styleStr) : void 0;
801
922
  const v = obj["v"];
802
923
  const rawValue = textOf(v);
924
+ const vmStr = type === "e" ? strAttr(obj, "vm") : void 0;
925
+ const vm = vmStr !== void 0 ? Number(vmStr) : void 0;
803
926
  const base = {
804
927
  column: address.column,
805
928
  row: address.row,
806
- type
929
+ type,
930
+ ...vm !== void 0 && Number.isInteger(vm) && vm > 0 ? { valueMetadataIndex: vm } : {}
807
931
  };
808
932
  if (type === "inlineStr") {
809
933
  const is = obj["is"];
@@ -831,11 +955,11 @@ function strAttr(obj, key) {
831
955
  return typeof v === "string" ? v : void 0;
832
956
  }
833
957
  function textOf(node) {
834
- if (typeof node === "string") return node;
958
+ if (typeof node === "string") return decodeXstring(node);
835
959
  if (typeof node === "number") return String(node);
836
960
  if (!node || typeof node !== "object") return "";
837
961
  const inner = node["#text"];
838
- if (typeof inner === "string") return inner;
962
+ if (typeof inner === "string") return decodeXstring(inner);
839
963
  if (typeof inner === "number") return String(inner);
840
964
  return "";
841
965
  }
@@ -846,12 +970,9 @@ function inlineStringText(is) {
846
970
  const t = obj["t"];
847
971
  const direct = textOf(t);
848
972
  if (direct) return direct.length > MAX_CELL_CHARS ? direct.slice(0, MAX_CELL_CHARS) : direct;
849
- const r = obj["r"];
850
- if (Array.isArray(r)) {
851
- const joined = r.map((rr) => textOf(rr?.["t"])).join("");
852
- return joined.length > MAX_CELL_CHARS ? joined.slice(0, MAX_CELL_CHARS) : joined;
853
- }
854
- return "";
973
+ const raw = obj["r"];
974
+ const joined = (Array.isArray(raw) ? raw : raw !== void 0 ? [raw] : []).map((rr) => textOf(rr?.["t"])).join("");
975
+ return joined.length > MAX_CELL_CHARS ? joined.slice(0, MAX_CELL_CHARS) : joined;
855
976
  }
856
977
  //#endregion
857
978
  export { parseWorksheet };