reamkit 1.13.0 → 1.15.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 (80) hide show
  1. package/README.md +34 -8
  2. package/dist/esm/core/converter/facade.d.ts +8 -1
  3. package/dist/esm/core/converter/facade.js +34 -8
  4. package/dist/esm/core/converter/ream.d.ts +1 -0
  5. package/dist/esm/core/converter/ream.js +13 -8
  6. package/dist/esm/core/document-model/types.d.ts +2 -0
  7. package/dist/esm/core/ir/features.d.ts +1 -0
  8. package/dist/esm/core/ir/features.js +1 -0
  9. package/dist/esm/core/ir/sheet.d.ts +42 -3
  10. package/dist/esm/core/ole/cfb.d.ts +19 -0
  11. package/dist/esm/core/ole/cfb.js +158 -0
  12. package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
  13. package/dist/esm/core/spreadsheet-model/types.d.ts +81 -1
  14. package/dist/esm/excel/activex-parser.d.ts +9 -0
  15. package/dist/esm/excel/activex-parser.js +188 -0
  16. package/dist/esm/excel/comments-parser.d.ts +4 -0
  17. package/dist/esm/excel/comments-parser.js +104 -0
  18. package/dist/esm/excel/conditional-format.d.ts +5 -3
  19. package/dist/esm/excel/conditional-format.js +248 -12
  20. package/dist/esm/excel/form-control-parser.d.ts +6 -0
  21. package/dist/esm/excel/form-control-parser.js +29 -0
  22. package/dist/esm/excel/formula/context.d.ts +11 -0
  23. package/dist/esm/excel/formula/dates.d.ts +11 -0
  24. package/dist/esm/excel/formula/dates.js +46 -0
  25. package/dist/esm/excel/formula/eval.d.ts +11 -0
  26. package/dist/esm/excel/formula/eval.js +196 -0
  27. package/dist/esm/excel/formula/functions.d.ts +7 -0
  28. package/dist/esm/excel/formula/functions.js +1359 -0
  29. package/dist/esm/excel/formula/index.d.ts +14 -0
  30. package/dist/esm/excel/formula/index.js +17 -0
  31. package/dist/esm/excel/formula/lexer.d.ts +8 -0
  32. package/dist/esm/excel/formula/lexer.js +163 -0
  33. package/dist/esm/excel/formula/parser.d.ts +57 -0
  34. package/dist/esm/excel/formula/parser.js +274 -0
  35. package/dist/esm/excel/formula/value.d.ts +52 -0
  36. package/dist/esm/excel/formula/value.js +102 -0
  37. package/dist/esm/excel/header-footer.d.ts +2 -0
  38. package/dist/esm/excel/header-footer.js +127 -0
  39. package/dist/esm/excel/index.d.ts +1 -1
  40. package/dist/esm/excel/number-format.d.ts +2 -0
  41. package/dist/esm/excel/number-format.js +5 -1
  42. package/dist/esm/excel/print-model.d.ts +7 -2
  43. package/dist/esm/excel/print-model.js +123 -16
  44. package/dist/esm/excel/shared-strings-parser.d.ts +6 -1
  45. package/dist/esm/excel/shared-strings-parser.js +91 -12
  46. package/dist/esm/excel/sheet-drawing.d.ts +13 -1
  47. package/dist/esm/excel/sheet-drawing.js +47 -14
  48. package/dist/esm/excel/sheet-shape-parser.d.ts +4 -0
  49. package/dist/esm/excel/sheet-shape-parser.js +96 -0
  50. package/dist/esm/excel/sheet-to-flow.d.ts +4 -1
  51. package/dist/esm/excel/sheet-to-flow.js +170 -3
  52. package/dist/esm/excel/styles-parser.js +37 -0
  53. package/dist/esm/excel/worksheet-parser.js +191 -1
  54. package/dist/esm/excel/xls/biff-chart.d.ts +8 -0
  55. package/dist/esm/excel/xls/biff-chart.js +121 -0
  56. package/dist/esm/excel/xls/biff-reader.d.ts +4 -0
  57. package/dist/esm/excel/xls/biff-reader.js +1418 -0
  58. package/dist/esm/excel/xls/biff-styles.d.ts +8 -0
  59. package/dist/esm/excel/xls/biff-styles.js +299 -0
  60. package/dist/esm/excel/xls/escher.d.ts +24 -0
  61. package/dist/esm/excel/xls/escher.js +171 -0
  62. package/dist/esm/excel/xls/xls-reader.d.ts +3 -0
  63. package/dist/esm/excel/xls/xls-reader.js +30 -0
  64. package/dist/esm/excel/xlsx-reader.d.ts +2 -1
  65. package/dist/esm/excel/xlsx-reader.js +134 -16
  66. package/dist/esm/excel/xlsx-to-pdf.d.ts +1 -0
  67. package/dist/esm/excel/xlsx-to-pdf.js +2 -2
  68. package/dist/esm/excel/xlsx-writer.js +12 -2
  69. package/dist/esm/layout/styled-layout.js +29 -0
  70. package/dist/esm/pptx/ppt/ppt-reader.d.ts +4 -0
  71. package/dist/esm/pptx/ppt/ppt-reader.js +337 -0
  72. package/dist/esm/pptx/ppt/ppt-text.d.ts +69 -0
  73. package/dist/esm/pptx/ppt/ppt-text.js +756 -0
  74. package/dist/esm/pptx/slide-parser.d.ts +4 -2
  75. package/dist/esm/pptx/slide-parser.js +1 -1
  76. package/dist/esm/word/doc/doc-reader.d.ts +4 -0
  77. package/dist/esm/word/doc/doc-reader.js +421 -0
  78. package/dist/esm/word/doc/doc-text.d.ts +79 -0
  79. package/dist/esm/word/doc/doc-text.js +706 -0
  80. package/package.json +1 -1
@@ -0,0 +1,96 @@
1
+ import { emuToPt, pt } from "../core/ir/units.js";
2
+ import { poChildren, poFirstChild, poIntAttr, poIs, poText } from "../core/po-helpers.js";
3
+ import { parseFill, parseLine } from "../word/drawing-parser.js";
4
+ import { parseGeometry, parseTxBody } from "../pptx/slide-parser.js";
5
+ import { parseXml } from "../pptx/pptx-reader.js";
6
+ import { makeColWidthPt, makeRowHeightPt } from "./sheet-drawing.js";
7
+ //#region src/excel/sheet-shape-parser.ts
8
+ var ANCHOR_KINDS = [
9
+ "xdr:twoCellAnchor",
10
+ "xdr:oneCellAnchor",
11
+ "xdr:absoluteAnchor"
12
+ ];
13
+ function parseSheetShapes(drawingXml, worksheet, colors) {
14
+ const wsDr = parseXml(drawingXml).find((n) => poIs(n, "xdr:wsDr"));
15
+ if (!wsDr) return [];
16
+ const colWidthPt = makeColWidthPt(worksheet);
17
+ const rowHeightPt = makeRowHeightPt(worksheet);
18
+ const shapes = [];
19
+ for (const anchor of poChildren(wsDr)) {
20
+ if (!ANCHOR_KINDS.some((k) => poIs(anchor, k))) continue;
21
+ const sp = poChildren(anchor).find((c) => poIs(c, "xdr:sp"));
22
+ if (!sp) continue;
23
+ const box = anchorBox(anchor, colWidthPt, rowHeightPt);
24
+ if (!box) continue;
25
+ const spPr = poChildren(sp).find((c) => poIs(c, "xdr:spPr"));
26
+ const geometry = parseGeometry(spPr);
27
+ const fill = spPr ? parseFill(spPr, colors) : { kind: "none" };
28
+ const line = spPr ? parseLine(spPr, colors) : void 0;
29
+ const txBody = poChildren(sp).find((c) => poIs(c, "xdr:txBody"));
30
+ const text = txBody ? parseTxBody(txBody, void 0, void 0, colors, void 0) : void 0;
31
+ const visibleLine = line !== void 0 && line.fill !== "none";
32
+ if (!text && fill.kind === "none" && !visibleLine) continue;
33
+ shapes.push({
34
+ shape: {
35
+ width: pt(box.widthPt),
36
+ height: pt(box.heightPt),
37
+ geometry,
38
+ fill,
39
+ ...line ? { line } : {},
40
+ ...text ? { text } : {},
41
+ paragraphProperties: {}
42
+ },
43
+ anchorRow: box.anchorRow
44
+ });
45
+ }
46
+ shapes.sort((a, b) => a.anchorRow - b.anchorRow);
47
+ return shapes.map((s) => s.shape);
48
+ }
49
+ function anchorBox(anchor, colWidthPt, rowHeightPt) {
50
+ const from = marker(poChildren(anchor).find((c) => poIs(c, "xdr:from")));
51
+ if (poIs(anchor, "xdr:twoCellAnchor")) {
52
+ const to = marker(poChildren(anchor).find((c) => poIs(c, "xdr:to")));
53
+ if (!from || !to) return void 0;
54
+ const widthPt = span(from.col, from.colOffPt, to.col, to.colOffPt, colWidthPt);
55
+ const heightPt = span(from.row, from.rowOffPt, to.row, to.rowOffPt, rowHeightPt);
56
+ return widthPt > 0 && heightPt > 0 ? {
57
+ widthPt,
58
+ heightPt,
59
+ anchorRow: from.row
60
+ } : void 0;
61
+ }
62
+ const ext = poChildren(anchor).find((c) => poIs(c, "xdr:ext"));
63
+ if (!ext) return void 0;
64
+ const widthPt = emuToPt(poIntAttr(ext, "cx") ?? 0);
65
+ const heightPt = emuToPt(poIntAttr(ext, "cy") ?? 0);
66
+ return widthPt > 0 && heightPt > 0 ? {
67
+ widthPt,
68
+ heightPt,
69
+ anchorRow: from?.row ?? 0
70
+ } : void 0;
71
+ }
72
+ function marker(node) {
73
+ if (!node) return void 0;
74
+ const col = childInt(node, "xdr:col");
75
+ const row = childInt(node, "xdr:row");
76
+ if (col === void 0 || row === void 0) return void 0;
77
+ return {
78
+ col,
79
+ row,
80
+ colOffPt: emuToPt(childInt(node, "xdr:colOff") ?? 0),
81
+ rowOffPt: emuToPt(childInt(node, "xdr:rowOff") ?? 0)
82
+ };
83
+ }
84
+ function childInt(parent, tag) {
85
+ const child = poFirstChild(parent, tag);
86
+ if (!child) return void 0;
87
+ const n = Number(poText(child));
88
+ return Number.isFinite(n) ? n : void 0;
89
+ }
90
+ function span(from, fromOffPt, to, toOffPt, trackPt) {
91
+ let total = 0;
92
+ for (let i = from; i < to; i++) total += trackPt(i);
93
+ return total - fromOffPt + toOffPt;
94
+ }
95
+ //#endregion
96
+ export { parseSheetShapes };
@@ -1,3 +1,6 @@
1
1
  import { FlowDoc } from '../core/ir/flow.js';
2
2
  import { SheetDoc } from '../core/ir/sheet.js';
3
- export declare function projectSheetDoc(sheet: SheetDoc): FlowDoc;
3
+ export interface ProjectSheetOptions {
4
+ readonly now?: Date;
5
+ }
6
+ export declare function projectSheetDoc(sheet: SheetDoc, options?: ProjectSheetOptions): FlowDoc;
@@ -2,14 +2,18 @@ import { pt } from "../core/ir/units.js";
2
2
  import { EMPTY_STYLE_SHEET, resolveBodyStyles } from "../core/style-cascade/resolver.js";
3
3
  import "../core/style-cascade/index.js";
4
4
  import { resolvePrintArea, resolvePrintTitleRows, sectionFromWorksheet, slicerTable, worksheetToBody } from "./print-model.js";
5
+ import { buildHeaderFooterContent } from "./header-footer.js";
5
6
  //#region src/excel/sheet-to-flow.ts
6
- function projectSheetDoc(sheet) {
7
+ var HEADER_REL = "_xlsxHeaderDefault";
8
+ var FOOTER_REL = "_xlsxFooterDefault";
9
+ function projectSheetDoc(sheet, options = {}) {
7
10
  const body = [];
8
11
  let firstSheetSection;
12
+ const headersFooters = /* @__PURE__ */ new Map();
9
13
  const sheetGrids = new Map(sheet.sheets.map((s) => [s.name, s.grid]));
10
14
  for (let sheetIdx = 0; sheetIdx < sheet.sheets.length; sheetIdx++) {
11
15
  const ws = sheet.sheets[sheetIdx];
12
- if (sheetIdx === 0) firstSheetSection = sectionFromWorksheet(ws.grid);
16
+ if (sheetIdx === 0) firstSheetSection = withHeaderFooter(sectionFromWorksheet(ws.grid), ws, headersFooters);
13
17
  if (sheetIdx > 0) body.push({
14
18
  kind: "paragraph",
15
19
  paragraph: {
@@ -24,7 +28,12 @@ function projectSheetDoc(sheet) {
24
28
  ...printArea ? { printArea } : {},
25
29
  ...titleRows ? { titleRows } : {},
26
30
  gridLines,
27
- sheetGrids
31
+ sheetGrids,
32
+ sheetName: ws.name,
33
+ definedNames: sheet.definedNames,
34
+ ...ws.hyperlinks ? { hyperlinks: ws.hyperlinks } : {},
35
+ ...sheet.sharedStringRuns ? { sharedStringRuns: sheet.sharedStringRuns } : {},
36
+ ...options.now ? { now: options.now } : {}
28
37
  }));
29
38
  for (const ref of ws.charts ?? []) body.push({
30
39
  kind: "chart",
@@ -35,10 +44,26 @@ function projectSheetDoc(sheet) {
35
44
  paragraphProperties: {}
36
45
  }
37
46
  });
47
+ for (const img of ws.images ?? []) body.push({
48
+ kind: "image",
49
+ image: {
50
+ resource: img.resourceId,
51
+ width: pt(img.widthPt),
52
+ height: pt(img.heightPt),
53
+ paragraphProperties: {}
54
+ }
55
+ });
56
+ for (const shape of ws.shapes ?? []) body.push({
57
+ kind: "shape",
58
+ shape
59
+ });
38
60
  for (const slicer of ws.slicers ?? []) body.push({
39
61
  kind: "table",
40
62
  table: slicerTable(slicer)
41
63
  });
64
+ if (ws.comments && ws.comments.length > 0) body.push(...commentBlocks(ws.comments));
65
+ if (ws.formControls && ws.formControls.length > 0) body.push(...formControlBlocks(ws.formControls));
66
+ if (ws.activeXControls && ws.activeXControls.length > 0) body.push(...activeXBlocks(ws.activeXControls));
42
67
  }
43
68
  return {
44
69
  kind: "flow",
@@ -48,8 +73,150 @@ function projectSheetDoc(sheet) {
48
73
  styles: EMPTY_STYLE_SHEET,
49
74
  resources: sheet.resources,
50
75
  ...sheet.chartData && sheet.chartData.size > 0 ? { charts: sheet.chartData } : {},
76
+ ...headersFooters.size > 0 ? { headersFooters } : {},
51
77
  ...sheet.info ? { info: sheet.info } : {}
52
78
  };
53
79
  }
80
+ function commentBlocks(comments) {
81
+ const out = [{
82
+ kind: "paragraph",
83
+ paragraph: {
84
+ properties: {},
85
+ runs: [{
86
+ text: "Comments",
87
+ properties: { bold: true }
88
+ }]
89
+ }
90
+ }];
91
+ for (const c of comments) {
92
+ const body = c.text.replace(/\s+/g, " ").trim();
93
+ const label = c.author ? `${c.ref} — ${c.author}: ` : `${c.ref}: `;
94
+ out.push({
95
+ kind: "paragraph",
96
+ paragraph: {
97
+ properties: {},
98
+ runs: [{
99
+ text: label,
100
+ properties: { bold: true }
101
+ }, ...body.length > 0 ? [{
102
+ text: body,
103
+ properties: {}
104
+ }] : []]
105
+ }
106
+ });
107
+ }
108
+ return out;
109
+ }
110
+ function formControlBlocks(controls) {
111
+ const out = [{
112
+ kind: "paragraph",
113
+ paragraph: {
114
+ properties: {},
115
+ runs: [{
116
+ text: "Form controls",
117
+ properties: { bold: true }
118
+ }]
119
+ }
120
+ }];
121
+ for (const c of controls) out.push({
122
+ kind: "paragraph",
123
+ paragraph: {
124
+ properties: {},
125
+ runs: [{
126
+ text: formControlLabel(c),
127
+ properties: {}
128
+ }]
129
+ }
130
+ });
131
+ return out;
132
+ }
133
+ function formControlLabel(c) {
134
+ const name = c.name ?? c.objectType ?? "Control";
135
+ switch ((c.objectType ?? "").toLowerCase()) {
136
+ case "checkbox": return `${c.checked ? "[x]" : "[ ]"} ${name}`;
137
+ case "radio": return `${c.checked ? "(o)" : "( )"} ${name}`;
138
+ case "buttons": return `[ ${name} ]`;
139
+ case "spin":
140
+ case "scroll": return c.value !== void 0 ? `${name} (value ${c.value})` : name;
141
+ case "drop":
142
+ case "list": return `${name} (list)`;
143
+ default: return c.objectType ? `${name} (${c.objectType})` : name;
144
+ }
145
+ }
146
+ function activeXBlocks(controls) {
147
+ const out = [{
148
+ kind: "paragraph",
149
+ paragraph: {
150
+ properties: {},
151
+ runs: [{
152
+ text: "ActiveX controls",
153
+ properties: { bold: true }
154
+ }]
155
+ }
156
+ }];
157
+ for (const c of controls) out.push({
158
+ kind: "paragraph",
159
+ paragraph: {
160
+ properties: {},
161
+ runs: [{
162
+ text: activeXLabel(c),
163
+ properties: {}
164
+ }]
165
+ }
166
+ });
167
+ return out;
168
+ }
169
+ function activeXLabel(c) {
170
+ const label = c.caption && c.caption.length > 0 ? c.caption : c.type;
171
+ const on = c.value === "1" || c.value?.toLowerCase() === "true";
172
+ switch (c.type) {
173
+ case "checkbox": return `${on ? "[x]" : "[ ]"} ${label}`;
174
+ case "option": return `${on ? "(o)" : "( )"} ${label}`;
175
+ case "button":
176
+ case "toggle": return `[ ${label} ]`;
177
+ case "textbox": return `[ ${c.value ?? c.caption ?? ""} ]`;
178
+ case "combo":
179
+ case "list": return `${label} (list)`;
180
+ case "spin":
181
+ case "scroll": return c.value !== void 0 ? `${label} (value ${c.value})` : label;
182
+ case "label": return c.caption ?? "Label";
183
+ default: return label;
184
+ }
185
+ }
186
+ function withHeaderFooter(section, ws, headersFooters) {
187
+ const hf = ws.grid.headerFooter;
188
+ if (!hf || !hf.oddHeader && !hf.oddFooter) return section;
189
+ const headers = [];
190
+ const footers = [];
191
+ if (hf.oddHeader) {
192
+ const content = buildHeaderFooterContent(hf.oddHeader, ws.name);
193
+ if (content.length > 0) {
194
+ headersFooters.set(HEADER_REL, resolveBodyStyles(content, EMPTY_STYLE_SHEET));
195
+ headers.push({
196
+ type: "default",
197
+ relationshipId: HEADER_REL
198
+ });
199
+ }
200
+ }
201
+ if (hf.oddFooter) {
202
+ const content = buildHeaderFooterContent(hf.oddFooter, ws.name);
203
+ if (content.length > 0) {
204
+ headersFooters.set(FOOTER_REL, resolveBodyStyles(content, EMPTY_STYLE_SHEET));
205
+ footers.push({
206
+ type: "default",
207
+ relationshipId: FOOTER_REL
208
+ });
209
+ }
210
+ }
211
+ if (headers.length === 0 && footers.length === 0) return section;
212
+ return {
213
+ ...section ?? {
214
+ headers: [],
215
+ footers: []
216
+ },
217
+ headers,
218
+ footers
219
+ };
220
+ }
54
221
  //#endregion
55
222
  export { projectSheetDoc };
@@ -101,6 +101,12 @@ function parseBorders(root) {
101
101
  if (right) border.right = right;
102
102
  if (bottom) border.bottom = bottom;
103
103
  if (left) border.left = left;
104
+ const diagonal = parseBorderEdge(asObject(obj["diagonal"]));
105
+ if (diagonal) {
106
+ border.diagonal = diagonal;
107
+ if (boolAttr(obj, "diagonalUp")) border.diagonalUp = true;
108
+ if (boolAttr(obj, "diagonalDown")) border.diagonalDown = true;
109
+ }
104
110
  out.push(border);
105
111
  }
106
112
  return out;
@@ -169,6 +175,13 @@ function parseFills(root) {
169
175
  if (fg) fill.fgColorHex = fg;
170
176
  if (bg) fill.bgColorHex = bg;
171
177
  }
178
+ if (!fill.patternType) {
179
+ const avg = averageGradientColor(asObject(obj["gradientFill"]));
180
+ if (avg) {
181
+ fill.patternType = "solid";
182
+ fill.fgColorHex = avg;
183
+ }
184
+ }
172
185
  out.push(fill);
173
186
  }
174
187
  return out;
@@ -205,6 +218,11 @@ function parseCellXfs(root) {
205
218
  if (h) a.horizontal = h;
206
219
  if (v) a.vertical = v;
207
220
  if (wrap !== void 0) a.wrapText = wrap;
221
+ const indent = numAttr(align, "indent");
222
+ if (indent !== void 0 && indent > 0) a.indent = indent;
223
+ const rotation = numAttr(align, "textRotation");
224
+ if (rotation !== void 0 && rotation !== 0) a.textRotation = rotation;
225
+ if (boolAttr(align, "shrinkToFit")) a.shrinkToFit = true;
208
226
  if (Object.keys(a).length > 0) xf.alignment = a;
209
227
  }
210
228
  out.push(xf);
@@ -250,6 +268,25 @@ function childToggle(obj, childName) {
250
268
  if (val === void 0) return true;
251
269
  return !(val === "false" || val === "0");
252
270
  }
271
+ function averageGradientColor(gf) {
272
+ if (!gf) return void 0;
273
+ let r = 0;
274
+ let g = 0;
275
+ let b = 0;
276
+ let n = 0;
277
+ for (const s of asArray(gf["stop"])) {
278
+ const so = asObject(s);
279
+ const hex = so ? colorOf(asObject(so["color"])) : void 0;
280
+ if (!hex) continue;
281
+ r += parseInt(hex.slice(0, 2), 16);
282
+ g += parseInt(hex.slice(2, 4), 16);
283
+ b += parseInt(hex.slice(4, 6), 16);
284
+ n++;
285
+ }
286
+ if (n === 0) return void 0;
287
+ const h = (x) => Math.round(x / n).toString(16).padStart(2, "0").toUpperCase();
288
+ return `${h(r)}${h(g)}${h(b)}`;
289
+ }
253
290
  function colorOf(node) {
254
291
  if (!node) return void 0;
255
292
  const rgb = strAttr(node, "rgb");
@@ -38,6 +38,10 @@ function parseWorksheet(data) {
38
38
  const drawingRelId = drawingNode && typeof drawingNode === "object" ? strAttr(drawingNode, "id") : void 0;
39
39
  const conditionalFormats = parseConditionalFormatting(wsObj);
40
40
  const dataValidations = parseDataValidations(wsObj);
41
+ const hyperlinks = parseHyperlinks(wsObj);
42
+ const headerFooter = parseHeaderFooter(wsObj);
43
+ const formControls = parseFormControls(wsObj);
44
+ const oleObjects = parseOleObjects(wsObj);
41
45
  const sparklines = parseSparklines(wsObj);
42
46
  const tablePartRelIds = parseTableParts(wsObj);
43
47
  const printModel = {
@@ -51,6 +55,10 @@ function parseWorksheet(data) {
51
55
  ...drawingRelId !== void 0 ? { drawingRelId } : {},
52
56
  ...conditionalFormats.length > 0 ? { conditionalFormats } : {},
53
57
  ...dataValidations.length > 0 ? { dataValidations } : {},
58
+ ...hyperlinks.length > 0 ? { hyperlinks } : {},
59
+ ...headerFooter ? { headerFooter } : {},
60
+ ...formControls.length > 0 ? { formControls } : {},
61
+ ...oleObjects.length > 0 ? { oleObjects } : {},
54
62
  ...sparklines.length > 0 ? { sparklines } : {},
55
63
  ...tablePartRelIds.length > 0 ? { tablePartRelIds } : {}
56
64
  };
@@ -354,6 +362,41 @@ function boolAttr(obj, key) {
354
362
  const raw = strAttr(obj, key);
355
363
  return raw === "1" || raw === "true";
356
364
  }
365
+ function parseHeaderFooter(ws) {
366
+ const node = asObjectNode(ws["headerFooter"]);
367
+ if (!node) return void 0;
368
+ const oddHeader = formulaText(node["oddHeader"]);
369
+ const oddFooter = formulaText(node["oddFooter"]);
370
+ if (!oddHeader && !oddFooter) return void 0;
371
+ return {
372
+ ...oddHeader ? { oddHeader } : {},
373
+ ...oddFooter ? { oddFooter } : {}
374
+ };
375
+ }
376
+ function parseHyperlinks(ws) {
377
+ const node = asObjectNode(ws["hyperlinks"]);
378
+ if (!node) return [];
379
+ const out = [];
380
+ for (const h of toArray(node["hyperlink"])) {
381
+ const obj = asObjectNode(h);
382
+ if (!obj) continue;
383
+ const ref = strAttr(obj, "ref");
384
+ if (!ref) continue;
385
+ const relId = strAttr(obj, "id");
386
+ const location = strAttr(obj, "location");
387
+ if (relId === void 0 && location === void 0) continue;
388
+ const display = strAttr(obj, "display");
389
+ const tooltip = strAttr(obj, "tooltip");
390
+ out.push({
391
+ ref,
392
+ ...relId !== void 0 ? { relId } : {},
393
+ ...location !== void 0 ? { location } : {},
394
+ ...display !== void 0 ? { display } : {},
395
+ ...tooltip !== void 0 ? { tooltip } : {}
396
+ });
397
+ }
398
+ return out;
399
+ }
357
400
  function parseSqref(sqref) {
358
401
  const out = [];
359
402
  for (const token of sqref.split(/\s+/)) {
@@ -380,14 +423,113 @@ var CF_OPERATORS = new Set([
380
423
  ]);
381
424
  function parseCfRule(obj) {
382
425
  const priority = parseNumericAttr(obj, "priority") ?? 0;
383
- switch (strAttr(obj, "type")) {
426
+ const type = strAttr(obj, "type");
427
+ switch (type) {
384
428
  case "cellIs": return parseCellIsRule(obj, priority);
385
429
  case "colorScale": return parseColorScaleRule(obj, priority);
386
430
  case "dataBar": return parseDataBarRule(obj, priority);
387
431
  case "iconSet": return parseIconSetRule(obj, priority);
432
+ case "top10": return parseTop10Rule(obj, priority);
433
+ case "aboveAverage": return parseAboveAverageRule(obj, priority);
434
+ case "duplicateValues":
435
+ case "uniqueValues": return parseDupUniqueRule(type, obj, priority);
436
+ case "containsText":
437
+ case "notContainsText":
438
+ case "beginsWith":
439
+ case "endsWith": return parseTextRule(type, obj, priority);
440
+ case "expression": return parseExpressionRule(obj, priority);
441
+ case "timePeriod": return parseTimePeriodRule(obj, priority);
388
442
  default: return;
389
443
  }
390
444
  }
445
+ var TIME_PERIODS = new Set([
446
+ "today",
447
+ "yesterday",
448
+ "tomorrow",
449
+ "last7Days",
450
+ "thisWeek",
451
+ "lastWeek",
452
+ "nextWeek",
453
+ "thisMonth",
454
+ "lastMonth",
455
+ "nextMonth"
456
+ ]);
457
+ function parseExpressionRule(obj, priority) {
458
+ const dxfId = parseNumericAttr(obj, "dxfId");
459
+ if (dxfId === void 0) return void 0;
460
+ const formula = formulaText(obj["formula"]);
461
+ if (formula === void 0) return void 0;
462
+ return {
463
+ type: "expression",
464
+ priority,
465
+ formula,
466
+ dxfId
467
+ };
468
+ }
469
+ function parseTimePeriodRule(obj, priority) {
470
+ const dxfId = parseNumericAttr(obj, "dxfId");
471
+ if (dxfId === void 0) return void 0;
472
+ const period = strAttr(obj, "timePeriod");
473
+ if (period === void 0 || !TIME_PERIODS.has(period)) return void 0;
474
+ const formula = formulaText(obj["formula"]);
475
+ return {
476
+ type: "timePeriod",
477
+ priority,
478
+ timePeriod: period,
479
+ dxfId,
480
+ ...formula !== void 0 ? { formula } : {}
481
+ };
482
+ }
483
+ function parseTop10Rule(obj, priority) {
484
+ const dxfId = parseNumericAttr(obj, "dxfId");
485
+ if (dxfId === void 0) return void 0;
486
+ return {
487
+ type: "top10",
488
+ priority,
489
+ rank: parseNumericAttr(obj, "rank") ?? 10,
490
+ percent: boolAttr(obj, "percent"),
491
+ bottom: boolAttr(obj, "bottom"),
492
+ dxfId
493
+ };
494
+ }
495
+ function parseAboveAverageRule(obj, priority) {
496
+ const dxfId = parseNumericAttr(obj, "dxfId");
497
+ if (dxfId === void 0) return void 0;
498
+ const aboveRaw = strAttr(obj, "aboveAverage");
499
+ const aboveAverage = aboveRaw === void 0 ? true : aboveRaw === "1" || aboveRaw === "true";
500
+ const stdDev = parseNumericAttr(obj, "stdDev");
501
+ return {
502
+ type: "aboveAverage",
503
+ priority,
504
+ aboveAverage,
505
+ equalAverage: boolAttr(obj, "equalAverage"),
506
+ ...stdDev !== void 0 ? { stdDev } : {},
507
+ dxfId
508
+ };
509
+ }
510
+ function parseDupUniqueRule(type, obj, priority) {
511
+ const dxfId = parseNumericAttr(obj, "dxfId");
512
+ if (dxfId === void 0) return void 0;
513
+ return {
514
+ type,
515
+ priority,
516
+ dxfId
517
+ };
518
+ }
519
+ function parseTextRule(type, obj, priority) {
520
+ const dxfId = parseNumericAttr(obj, "dxfId");
521
+ if (dxfId === void 0) return void 0;
522
+ const text = strAttr(obj, "text");
523
+ if (text === void 0) return void 0;
524
+ const formula = formulaText(obj["formula"]);
525
+ return {
526
+ type,
527
+ priority,
528
+ text,
529
+ dxfId,
530
+ ...formula !== void 0 ? { formula } : {}
531
+ };
532
+ }
391
533
  function parseIconSetRule(obj, priority) {
392
534
  const is = obj["iconSet"];
393
535
  if (!is || typeof is !== "object") return void 0;
@@ -545,6 +687,54 @@ function parseSparklines(ws) {
545
687
  }
546
688
  return out;
547
689
  }
690
+ function parseFormControls(ws) {
691
+ const out = [];
692
+ const seen = /* @__PURE__ */ new Set();
693
+ collectControls(asObjectNode(ws["controls"]), out, seen);
694
+ for (const ext of toArray(asObjectNode(ws["extLst"])?.["ext"])) collectControls(asObjectNode(asObjectNode(ext)?.["controls"]), out, seen);
695
+ return out;
696
+ }
697
+ function collectControls(node, out, seen) {
698
+ if (!node) return;
699
+ const direct = toArray(node["control"]);
700
+ const fromChoice = toArray(asObjectNode(node["AlternateContent"])?.["Choice"]).flatMap((c) => toArray(asObjectNode(c)?.["control"]));
701
+ for (const c of [...direct, ...fromChoice]) {
702
+ const obj = asObjectNode(c);
703
+ if (!obj) continue;
704
+ const relId = strAttr(obj, "id");
705
+ if (!relId || seen.has(relId)) continue;
706
+ seen.add(relId);
707
+ const name = strAttr(obj, "name");
708
+ out.push({
709
+ relId,
710
+ ...name ? { name } : {}
711
+ });
712
+ }
713
+ }
714
+ function parseOleObjects(ws) {
715
+ const out = [];
716
+ const seen = /* @__PURE__ */ new Set();
717
+ collectOleObjects(asObjectNode(ws["oleObjects"]), out, seen);
718
+ for (const ext of toArray(asObjectNode(ws["extLst"])?.["ext"])) collectOleObjects(asObjectNode(asObjectNode(ext)?.["oleObjects"]), out, seen);
719
+ return out;
720
+ }
721
+ function collectOleObjects(node, out, seen) {
722
+ if (!node) return;
723
+ const direct = toArray(node["oleObject"]);
724
+ const fromChoice = toArray(asObjectNode(node["AlternateContent"])?.["Choice"]).flatMap((c) => toArray(asObjectNode(c)?.["oleObject"]));
725
+ for (const o of [...direct, ...fromChoice]) {
726
+ const obj = asObjectNode(o);
727
+ if (!obj) continue;
728
+ const relId = strAttr(obj, "id");
729
+ if (!relId || seen.has(relId)) continue;
730
+ seen.add(relId);
731
+ const progId = strAttr(obj, "progId");
732
+ out.push({
733
+ relId,
734
+ ...progId ? { progId } : {}
735
+ });
736
+ }
737
+ }
548
738
  function asObjectNode(v) {
549
739
  return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
550
740
  }
@@ -0,0 +1,8 @@
1
+ import { Chart } from '../../core/document-model/index.js';
2
+ import { WorksheetCell } from '../../core/spreadsheet-model/index.js';
3
+ interface Rec {
4
+ readonly type: number;
5
+ readonly data: Uint8Array;
6
+ }
7
+ export declare function parseBiffChart(records: ReadonlyArray<Rec>, cells: ReadonlyArray<WorksheetCell>, sharedStrings: ReadonlyArray<string>): Chart | undefined;
8
+ export {};