reamkit 1.11.0 → 1.13.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 (42) hide show
  1. package/dist/esm/core/converter/facade.js +1 -1
  2. package/dist/esm/core/converter/project.js +1 -0
  3. package/dist/esm/core/document-model/index.d.ts +1 -1
  4. package/dist/esm/core/document-model/types.d.ts +24 -0
  5. package/dist/esm/core/ir/features.d.ts +1 -0
  6. package/dist/esm/core/ir/features.js +1 -0
  7. package/dist/esm/core/ir/flow.d.ts +3 -1
  8. package/dist/esm/core/ir/sheet.d.ts +14 -0
  9. package/dist/esm/core/po-helpers.d.ts +2 -0
  10. package/dist/esm/core/po-helpers.js +14 -1
  11. package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
  12. package/dist/esm/core/spreadsheet-model/types.d.ts +34 -0
  13. package/dist/esm/excel/index.d.ts +1 -1
  14. package/dist/esm/excel/pivot-table-parser.d.ts +2 -0
  15. package/dist/esm/excel/pivot-table-parser.js +68 -0
  16. package/dist/esm/excel/print-model.d.ts +5 -2
  17. package/dist/esm/excel/print-model.js +123 -9
  18. package/dist/esm/excel/sheet-to-flow.js +5 -1
  19. package/dist/esm/excel/slicer-parser.d.ts +15 -0
  20. package/dist/esm/excel/slicer-parser.js +76 -0
  21. package/dist/esm/excel/table-parser.d.ts +10 -0
  22. package/dist/esm/excel/table-parser.js +36 -4
  23. package/dist/esm/excel/worksheet-parser.js +56 -0
  24. package/dist/esm/excel/xlsx-reader.js +129 -5
  25. package/dist/esm/excel/xlsx-writer.js +9 -1
  26. package/dist/esm/html/html-writer.js +56 -2
  27. package/dist/esm/layout/page-doc.d.ts +1 -0
  28. package/dist/esm/layout/styled-layout.d.ts +8 -1
  29. package/dist/esm/layout/styled-layout.js +154 -6
  30. package/dist/esm/pdf/styled-page-emitter.js +38 -0
  31. package/dist/esm/pptx/pptx-reader.d.ts +2 -0
  32. package/dist/esm/pptx/pptx-reader.js +30 -3
  33. package/dist/esm/pptx/slide-parser.d.ts +8 -2
  34. package/dist/esm/pptx/slide-parser.js +80 -12
  35. package/dist/esm/word/document-parser.d.ts +17 -2
  36. package/dist/esm/word/document-parser.js +178 -18
  37. package/dist/esm/word/docx-reader.js +54 -4
  38. package/dist/esm/word/docx-writer.js +84 -1
  39. package/dist/esm/word/drawing-parser.d.ts +7 -0
  40. package/dist/esm/word/drawing-parser.js +13 -0
  41. package/dist/esm/word/index.d.ts +2 -1
  42. package/package.json +1 -1
@@ -2,6 +2,7 @@ import { FontRegistry } from "../font/font-registry.js";
2
2
  import { FEATURES } from "../ir/features.js";
3
3
  import { ConversionLossError } from "../ir/loss.js";
4
4
  import { layoutStyledDocument } from "../../layout/styled-layout.js";
5
+ import { pptxReader } from "../../pptx/pptx-reader.js";
5
6
  import { docxReader } from "../../word/docx-reader.js";
6
7
  import { projectSheetDoc } from "../../excel/sheet-to-flow.js";
7
8
  import { xlsxReader } from "../../excel/xlsx-reader.js";
@@ -13,7 +14,6 @@ import { writeHtml } from "../../html/html-writer.js";
13
14
  import { writeSvg } from "../../svg/svg-writer.js";
14
15
  import { convertDocxToPdf } from "../../word/docx-to-pdf.js";
15
16
  import { convertXlsxToPdf } from "../../excel/xlsx-to-pdf.js";
16
- import { pptxReader } from "../../pptx/pptx-reader.js";
17
17
  import { pdfReader } from "../../pdf-reader/reader.js";
18
18
  //#region src/core/converter/facade.ts
19
19
  function toFlowDoc(doc) {
@@ -9,6 +9,7 @@ function flowRenderOptions(flow) {
9
9
  ...flow.headersFooters ? { headersFooters: flow.headersFooters } : {},
10
10
  ...flow.footnotes ? { footnotes: flow.footnotes } : {},
11
11
  ...flow.endnotes ? { endnotes: flow.endnotes } : {},
12
+ ...flow.comments ? { comments: flow.comments } : {},
12
13
  resources: flow.resources,
13
14
  ...flow.charts ? { charts: flow.charts } : {},
14
15
  ...flow.embeddedFonts ? { embeddedFonts: flow.embeddedFonts } : {},
@@ -1 +1 @@
1
- export type { AbstractNumbering, Alignment, Border, BorderStyle, BodyElement, CellBorders, CellMerge, DocumentInfo, CellMargins, CellProperties, CellShading, CellDataBar, CellIcon, CellIconShape, CellSparkline, Chart, ChartBlock, ChartDataPoint, ChartSeries, ChartType, CustomGeometry, CustomPathCmd, DocumentModel, FontFamilyMap, HeaderFooterReference, HeaderFooterType, ImageBlock, InlineImage, MathAccent, MathBar, MathDelimiter, MathEqArray, MathFraction, MathFunc, MathGroupChr, MathLimit, MathMatrix, MathNary, MathNode, MathRadical, MathRow, MathRun, MathScript, Numbering, NumberingFormat, NumberingInstance, NumberingLevel, NumberingReference, PageMargins, PageSize, Paragraph, ParagraphProperties, Run, RunProperties, RowProperties, Section, FloatAnchor, SectionColumns, SectionProperties, ShapeBlock, ShapeDash, ShapeFill, ShapeFillKind, ShapeGeometry, ShapeLine, ShapeTextBody, ShapeTransform, Style, StyleSheet, StyleType, Table, TableCell, TableLook, TableProperties, TableStyleCondition, TableStyleConditionType, TableStyleLayer, TableRow, UnderlineStyle, VerticalAlign, } from './types.js';
1
+ export type { AbstractNumbering, Alignment, Border, BorderStyle, BodyElement, Comment, CellBorders, CellMerge, DocumentInfo, CellMargins, CellProperties, CellShading, CellDataBar, CellIcon, CellIconShape, CellSparkline, Chart, ChartBlock, ChartDataPoint, ChartSeries, ChartType, CustomGeometry, CustomPathCmd, DocumentModel, FontFamilyMap, HeaderFooterReference, HeaderFooterType, ImageBlock, InlineImage, MathAccent, MathBar, MathDelimiter, MathEqArray, MathFraction, MathFunc, MathGroupChr, MathLimit, MathMatrix, MathNary, MathNode, MathRadical, MathRow, MathRun, MathScript, Numbering, NumberingFormat, NumberingInstance, NumberingLevel, NumberingReference, PageMargins, PageSize, Paragraph, ParagraphProperties, Run, RunProperties, RowProperties, Section, FloatAnchor, SectionColumns, SectionProperties, ShapeBlock, ShapeDash, ShapeFill, ShapeFillKind, ShapeGeometry, ShapeLine, ShapeTextBody, ShapeTransform, Style, StyleSheet, StyleType, Table, TableCell, TableLook, TableProperties, TableStyleCondition, TableStyleConditionType, TableStyleLayer, TableRow, UnderlineStyle, VerticalAlign, } from './types.js';
@@ -132,6 +132,8 @@ export interface Run {
132
132
  readonly anchor?: string;
133
133
  readonly footnoteRef?: string;
134
134
  readonly endnoteRef?: string;
135
+ readonly commentRef?: string;
136
+ readonly commentRangeRefs?: ReadonlyArray<string>;
135
137
  readonly noteNumber?: true;
136
138
  readonly listMarker?: true;
137
139
  readonly inlineImage?: InlineImage;
@@ -144,6 +146,27 @@ export interface Paragraph {
144
146
  readonly runs: ReadonlyArray<Run>;
145
147
  readonly bookmarks?: ReadonlyArray<string>;
146
148
  }
149
+ export interface Comment {
150
+ readonly content: ReadonlyArray<BodyElement>;
151
+ readonly author?: string;
152
+ readonly initials?: string;
153
+ /** Raw w:date timestamp (ISO 8601), as authored — not reformatted. */
154
+ readonly date?: string;
155
+ /**
156
+ * The author's resolved identity (usually an email) from word/people.xml
157
+ * (`w15:person` → `w15:presenceInfo/@w15:userId`), matched on the author name.
158
+ * Absent when the file ships no people part or the author is not listed.
159
+ */
160
+ readonly authorId?: string;
161
+ /**
162
+ * Microsoft commentsExtended (w15) — the id of the comment this one replies
163
+ * to, forming a thread. Set only when word/commentsExtended.xml links this
164
+ * comment's paragraph to a parent (w15:paraIdParent). Top-level comments omit it.
165
+ */
166
+ readonly parentId?: string;
167
+ /** w15:done — the comment thread was marked resolved. */
168
+ readonly done?: boolean;
169
+ }
147
170
  export type NumberingFormat = 'decimal' | 'lowerLetter' | 'upperLetter' | 'lowerRoman' | 'upperRoman' | 'bullet' | 'none';
148
171
  export interface NumberingReference {
149
172
  readonly numId: string;
@@ -252,6 +275,7 @@ export interface CellProperties {
252
275
  readonly dataBar?: CellDataBar;
253
276
  readonly icon?: CellIcon;
254
277
  readonly sparkline?: CellSparkline;
278
+ readonly dropdown?: boolean;
255
279
  }
256
280
  export interface RowProperties {
257
281
  readonly height?: Pt;
@@ -10,6 +10,7 @@ export declare const FEATURES: {
10
10
  readonly imagesJp2: "images.jp2";
11
11
  readonly hyperlinks: "hyperlinks";
12
12
  readonly shapes: "shapes";
13
+ readonly smartArt: "shapes.smartArt";
13
14
  readonly charts: "charts";
14
15
  readonly math: "math";
15
16
  readonly rtl: "rtl";
@@ -10,6 +10,7 @@ var FEATURES = {
10
10
  imagesJp2: "images.jp2",
11
11
  hyperlinks: "hyperlinks",
12
12
  shapes: "shapes",
13
+ smartArt: "shapes.smartArt",
13
14
  charts: "charts",
14
15
  math: "math",
15
16
  rtl: "rtl",
@@ -1,4 +1,4 @@
1
- import { BodyElement, Chart, DocumentInfo, Numbering, Section, SectionProperties, StyleSheet } from '../document-model/index.js';
1
+ import { BodyElement, Chart, Comment, DocumentInfo, Numbering, Section, SectionProperties, StyleSheet } from '../document-model/index.js';
2
2
  import { FontRegistry } from '../font/index.js';
3
3
  import { ResourceStore } from './resources.js';
4
4
  export interface FlowDoc {
@@ -14,6 +14,8 @@ export interface FlowDoc {
14
14
  /** §17.11 footnotes/endnotes content by id (separator stubs excluded). */
15
15
  readonly footnotes?: ReadonlyMap<string, ReadonlyArray<BodyElement>>;
16
16
  readonly endnotes?: ReadonlyMap<string, ReadonlyArray<BodyElement>>;
17
+ /** §17.13.4 review comments by id, anchored from a run's `commentRef`. */
18
+ readonly comments?: ReadonlyMap<string, Comment>;
17
19
  /** Parsed charts keyed by relationship id (ChartBlock.chartRelId). */
18
20
  readonly charts?: ReadonlyMap<string, Chart>;
19
21
  /** Content-addressed binary resources (images). */
@@ -6,10 +6,24 @@ export interface SheetChartRef {
6
6
  readonly widthPt: number;
7
7
  readonly heightPt: number;
8
8
  }
9
+ export interface SheetSlicerItem {
10
+ readonly label: string;
11
+ readonly selected: boolean;
12
+ }
13
+ export interface SheetSlicer {
14
+ readonly caption: string;
15
+ readonly columnCount: number;
16
+ readonly items: ReadonlyArray<SheetSlicerItem>;
17
+ readonly headerHex?: string;
18
+ readonly selectedHex?: string;
19
+ readonly headerTextHex?: string;
20
+ readonly selectedTextHex?: string;
21
+ }
9
22
  export interface Sheet {
10
23
  readonly name: string;
11
24
  readonly grid: ParsedWorksheet;
12
25
  readonly charts?: ReadonlyArray<SheetChartRef>;
26
+ readonly slicers?: ReadonlyArray<SheetSlicer>;
13
27
  }
14
28
  export interface SheetDoc {
15
29
  readonly kind: 'sheet';
@@ -6,6 +6,8 @@ export declare function poChildren(node: PoNode | undefined): ReadonlyArray<PoNo
6
6
  export declare function poChildrenWith(node: PoNode | undefined, tag: string): Array<PoNode>;
7
7
  export declare function poFirstChild(node: PoNode | undefined, tag: string): PoNode | undefined;
8
8
  export declare function poAttr(node: PoNode | undefined, name: string): string | undefined;
9
+ export declare function poAttrLocal(node: PoNode | undefined, name: string): string | undefined;
10
+ export declare function poIsLocal(node: PoNode | undefined, name: string): boolean;
9
11
  export declare function poIntAttr(node: PoNode | undefined, name: string): number | undefined;
10
12
  export declare function poVal(node: PoNode | undefined): string | undefined;
11
13
  export declare function poToggle(node: PoNode | undefined): boolean | undefined;
@@ -28,6 +28,19 @@ function poAttr(node, name) {
28
28
  const v = a[`@_w:${name}`] ?? a[`@_r:${name}`] ?? a[`@_m:${name}`] ?? a[`@_xml:${name}`] ?? a[`@_${name}`];
29
29
  return typeof v === "string" ? v : void 0;
30
30
  }
31
+ function poAttrLocal(node, name) {
32
+ if (!node || typeof node !== "object") return void 0;
33
+ const attrs = node[ATTRS_KEY];
34
+ if (!attrs || typeof attrs !== "object") return void 0;
35
+ for (const [k, v] of Object.entries(attrs)) {
36
+ if (!k.startsWith("@_")) continue;
37
+ if (k.slice(2).split(":").pop() === name && typeof v === "string") return v;
38
+ }
39
+ }
40
+ function poIsLocal(node, name) {
41
+ const tag = poTag(node);
42
+ return tag !== void 0 && (tag === name || tag.split(":").pop() === name);
43
+ }
31
44
  function poIntAttr(node, name) {
32
45
  const v = poAttr(node, name);
33
46
  if (v === void 0) return void 0;
@@ -73,4 +86,4 @@ function poFindDescendant(node, tag) {
73
86
  }
74
87
  }
75
88
  //#endregion
76
- export { poAttr, poChildren, poChildrenWith, poFindByPath, poFindDescendant, poFirstChild, poIntAttr, poIs, poTag, poText, poToggle, poVal };
89
+ export { poAttr, poAttrLocal, poChildren, poChildrenWith, poFindByPath, poFindDescendant, poFirstChild, poIntAttr, poIs, poIsLocal, poTag, poText, poToggle, poVal };
@@ -1 +1 @@
1
- export type { CellType, WorksheetCell, ColumnWidth, MergedRange, RowHeight, XlsxPageMargins, XlsxPageSetup, XlsxPrintOptions, ParsedWorksheet, XlsxFont, XlsxFill, XlsxBorderStyleName, XlsxBorderEdge, XlsxBorder, XlsxHorizontalAlign, XlsxVerticalAlign, XlsxCellAlignment, XlsxCellXf, XlsxStyles, DefinedName, Dxf, CfOperator, CfRuleCellIs, CfvoType, Cfvo, CfRuleColorScale, CfRuleDataBar, CfRuleIconSet, CfRule, ConditionalFormat, SparklineKind, ParsedSparkline, ExcelTable, SheetPane, } from './types.js';
1
+ export type { CellType, WorksheetCell, ColumnWidth, MergedRange, RowHeight, XlsxPageMargins, XlsxPageSetup, XlsxPrintOptions, ParsedWorksheet, XlsxFont, XlsxFill, XlsxBorderStyleName, XlsxBorderEdge, XlsxBorder, XlsxHorizontalAlign, XlsxVerticalAlign, XlsxCellAlignment, XlsxCellXf, XlsxStyles, DefinedName, Dxf, CfOperator, CfRuleCellIs, CfvoType, Cfvo, CfRuleColorScale, CfRuleDataBar, CfRuleIconSet, CfRule, ConditionalFormat, DataValidationType, DataValidation, SparklineKind, ParsedSparkline, ExcelTable, PivotTable, SheetPane, } from './types.js';
@@ -58,9 +58,11 @@ export interface ParsedWorksheet {
58
58
  readonly colBreaks?: ReadonlyArray<number>;
59
59
  readonly drawingRelId?: string;
60
60
  readonly conditionalFormats?: ReadonlyArray<ConditionalFormat>;
61
+ readonly dataValidations?: ReadonlyArray<DataValidation>;
61
62
  readonly sparklines?: ReadonlyArray<ParsedSparkline>;
62
63
  readonly tablePartRelIds?: ReadonlyArray<string>;
63
64
  readonly tables?: ReadonlyArray<ExcelTable>;
65
+ readonly pivotTables?: ReadonlyArray<PivotTable>;
64
66
  readonly pane?: SheetPane;
65
67
  }
66
68
  export interface SheetPane {
@@ -81,6 +83,21 @@ export interface ExcelTable {
81
83
  readonly bandHex?: string;
82
84
  readonly headerTextHex?: string;
83
85
  }
86
+ export interface PivotTable {
87
+ readonly ref: MergedRange;
88
+ readonly name?: string;
89
+ readonly styleName?: string;
90
+ readonly firstHeaderRow: number;
91
+ readonly firstDataRow: number;
92
+ readonly firstDataCol: number;
93
+ readonly showRowStripes: boolean;
94
+ readonly showColStripes: boolean;
95
+ readonly rowItemTypes?: ReadonlyArray<string | undefined>;
96
+ readonly colItemTypes?: ReadonlyArray<string | undefined>;
97
+ readonly headerHex?: string;
98
+ readonly bandHex?: string;
99
+ readonly headerTextHex?: string;
100
+ }
84
101
  export type SparklineKind = 'line' | 'column' | 'winLoss';
85
102
  export interface ParsedSparkline {
86
103
  readonly kind: SparklineKind;
@@ -187,3 +204,20 @@ export interface ConditionalFormat {
187
204
  readonly ranges: ReadonlyArray<MergedRange>;
188
205
  readonly rules: ReadonlyArray<CfRule>;
189
206
  }
207
+ export type DataValidationType = 'none' | 'whole' | 'decimal' | 'list' | 'date' | 'time' | 'textLength' | 'custom';
208
+ export interface DataValidation {
209
+ readonly type: DataValidationType;
210
+ readonly ranges: ReadonlyArray<MergedRange>;
211
+ readonly operator?: string;
212
+ readonly allowBlank?: boolean;
213
+ readonly showDropDown?: boolean;
214
+ readonly showInputMessage?: boolean;
215
+ readonly showErrorMessage?: boolean;
216
+ readonly errorStyle?: string;
217
+ readonly formula1?: string;
218
+ readonly formula2?: string;
219
+ readonly promptTitle?: string;
220
+ readonly prompt?: string;
221
+ readonly errorTitle?: string;
222
+ readonly error?: string;
223
+ }
@@ -7,7 +7,7 @@ export { parseWorkbook } from './workbook-parser.js';
7
7
  export type { ParsedWorkbook, SheetReference } from './workbook-parser.js';
8
8
  export type { DefinedName } from '../core/spreadsheet-model/index.js';
9
9
  export { parseWorksheet } from './worksheet-parser.js';
10
- export type { CellType, ColumnWidth, ExcelTable, MergedRange, ParsedWorksheet, RowHeight, WorksheetCell, XlsxPageMargins, XlsxPageSetup, XlsxPrintOptions, } from '../core/spreadsheet-model/index.js';
10
+ export type { CellType, ColumnWidth, DataValidation, DataValidationType, ExcelTable, MergedRange, ParsedWorksheet, RowHeight, WorksheetCell, XlsxPageMargins, XlsxPageSetup, XlsxPrintOptions, } from '../core/spreadsheet-model/index.js';
11
11
  export { parseXlsxStyles, EMPTY_XLSX_STYLES } from './styles-parser.js';
12
12
  export type { XlsxBorder, XlsxBorderEdge, XlsxBorderStyleName, XlsxCellAlignment, XlsxCellXf, XlsxFill, XlsxFont, XlsxHorizontalAlign, XlsxStyles, XlsxVerticalAlign, } from '../core/spreadsheet-model/index.js';
13
13
  export { applyNumberFormat } from './number-format.js';
@@ -0,0 +1,2 @@
1
+ import { PivotTable } from '../core/spreadsheet-model/index.js';
2
+ export declare function parsePivotTablePart(data: Uint8Array): PivotTable | undefined;
@@ -0,0 +1,68 @@
1
+ import { parseAreaRef } from "./defined-name-ref.js";
2
+ import { XMLParser } from "fast-xml-parser";
3
+ //#region src/excel/pivot-table-parser.ts
4
+ var decoder = new TextDecoder("utf-8");
5
+ var parser = new XMLParser({
6
+ ignoreAttributes: false,
7
+ attributeNamePrefix: "@_",
8
+ parseAttributeValue: false,
9
+ parseTagValue: false,
10
+ removeNSPrefix: true
11
+ });
12
+ function parsePivotTablePart(data) {
13
+ const def = asObj(parser.parse(decoder.decode(data))["pivotTableDefinition"]);
14
+ if (!def) return void 0;
15
+ const loc = asObj(def["location"]);
16
+ const refStr = loc ? strAttr(loc, "ref") : void 0;
17
+ const ref = refStr ? parseAreaRef(refStr) : void 0;
18
+ if (!ref) return void 0;
19
+ const si = asObj(def["pivotTableStyleInfo"]);
20
+ const name = strAttr(def, "name");
21
+ const styleName = si ? strAttr(si, "name") : void 0;
22
+ const rowItemTypes = itemTypes(asObj(def["rowItems"]));
23
+ const colItemTypes = itemTypes(asObj(def["colItems"]));
24
+ const hasRowTotals = rowItemTypes?.some((t) => t !== void 0) ?? false;
25
+ const hasColTotals = colItemTypes?.some((t) => t !== void 0) ?? false;
26
+ return {
27
+ ref,
28
+ ...name ? { name } : {},
29
+ ...styleName ? { styleName } : {},
30
+ firstHeaderRow: (loc ? numAttr(loc, "firstHeaderRow") : void 0) ?? 1,
31
+ firstDataRow: (loc ? numAttr(loc, "firstDataRow") : void 0) ?? 1,
32
+ firstDataCol: (loc ? numAttr(loc, "firstDataCol") : void 0) ?? 0,
33
+ showRowStripes: si ? boolAttr(si, "showRowStripes") : false,
34
+ showColStripes: si ? boolAttr(si, "showColStripes") : false,
35
+ ...hasRowTotals && rowItemTypes ? { rowItemTypes } : {},
36
+ ...hasColTotals && colItemTypes ? { colItemTypes } : {}
37
+ };
38
+ }
39
+ function itemTypes(node) {
40
+ if (!node) return void 0;
41
+ return toArray(node["i"]).map((i) => {
42
+ const o = asObj(i);
43
+ return o ? strAttr(o, "t") : void 0;
44
+ });
45
+ }
46
+ function toArray(v) {
47
+ if (v === void 0 || v === null) return [];
48
+ return Array.isArray(v) ? v : [v];
49
+ }
50
+ function asObj(v) {
51
+ return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
52
+ }
53
+ function strAttr(obj, name) {
54
+ const v = obj[`@_${name}`];
55
+ return typeof v === "string" ? v : void 0;
56
+ }
57
+ function numAttr(obj, name) {
58
+ const v = strAttr(obj, name);
59
+ if (v === void 0) return void 0;
60
+ const n = Number(v);
61
+ return Number.isFinite(n) ? n : void 0;
62
+ }
63
+ function boolAttr(obj, name) {
64
+ const v = strAttr(obj, name);
65
+ return v === "1" || v === "true";
66
+ }
67
+ //#endregion
68
+ export { parsePivotTablePart };
@@ -1,5 +1,6 @@
1
- import { BodyElement, SectionProperties } from '../core/document-model/index.js';
2
- import { CellRange, DefinedName, ParsedWorksheet, XlsxStyles } from './index.js';
1
+ import { BodyElement, SectionProperties, Table } from '../core/document-model/index.js';
2
+ import { CellRange, DefinedName, ParsedWorksheet, WorksheetCell, XlsxStyles } from './index.js';
3
+ import { SheetSlicer } from '../core/ir/sheet.js';
3
4
  export declare const TWIPS_PER_EXCEL_CHAR = 105;
4
5
  export declare const DEFAULT_COL_TWIPS = 960;
5
6
  export declare const DEFAULT_ROW_TWIPS = 300;
@@ -19,4 +20,6 @@ interface PrintModelOptions {
19
20
  readonly sheetGrids?: ReadonlyMap<string, ParsedWorksheet>;
20
21
  }
21
22
  export declare function worksheetToBody(worksheet: ParsedWorksheet, sharedStrings: ReadonlyArray<string>, styles: XlsxStyles, date1904: boolean, print: PrintModelOptions): Array<BodyElement>;
23
+ export declare function resolveCellText(cell: WorksheetCell, sharedStrings: ReadonlyArray<string>, styles: XlsxStyles, date1904: boolean): string;
24
+ export declare function slicerTable(slicer: SheetSlicer): Table;
22
25
  export {};
@@ -1,4 +1,4 @@
1
- import { eighthPtToPt, halfPtToPt, twipsToPt } from "../core/ir/units.js";
1
+ import { eighthPtToPt, halfPtToPt, pt, twipsToPt } from "../core/ir/units.js";
2
2
  import { parseAreaRef, parseTitleRowRange } from "./defined-name-ref.js";
3
3
  import { applyNumberFormat } from "./number-format.js";
4
4
  import "./index.js";
@@ -195,6 +195,7 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
195
195
  const cfFormatter = buildConditionalFormatter(worksheet.conditionalFormats, styles, worksheet.cells);
196
196
  const sparklineByCell = buildSparklineLookup(worksheet, print);
197
197
  const tableFormatByCell = buildTableFormatLookup(worksheet);
198
+ const dropdownRanges = listDropdownRanges(worksheet.dataValidations);
198
199
  const rows = [];
199
200
  for (let r = 0; r < rowCount; r++) {
200
201
  const absR = r + rowStart;
@@ -246,6 +247,7 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
246
247
  if (text.length > charsFit) text = text.slice(0, charsFit);
247
248
  }
248
249
  }
250
+ const dropdown = dropdownRanges.length > 0 && rangesCover(dropdownRanges, absR, absC);
249
251
  const visibleEndCol = merge ? Math.min(merge.endColumn, colWindowEnd) : 0;
250
252
  const properties = {
251
253
  ...merge && visibleEndCol > merge.startColumn ? { colSpan: visibleEndCol - merge.startColumn + 1 } : {},
@@ -254,7 +256,8 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
254
256
  ...dataBar ? { dataBar } : {},
255
257
  ...icon ? { icon } : {},
256
258
  ...sparkline ? { sparkline } : {},
257
- ...borders ? { borders } : {}
259
+ ...borders ? { borders } : {},
260
+ ...dropdown ? { dropdown: true } : {}
258
261
  };
259
262
  const paragraphProps = cellParaProps(alignment);
260
263
  cells.push({
@@ -474,6 +477,19 @@ function mapBorderStyle(style) {
474
477
  function key(row, col) {
475
478
  return `${row},${col}`;
476
479
  }
480
+ function listDropdownRanges(dvs) {
481
+ if (!dvs || dvs.length === 0) return [];
482
+ const out = [];
483
+ for (const dv of dvs) {
484
+ if (dv.type !== "list" || dv.showDropDown) continue;
485
+ out.push(...dv.ranges);
486
+ }
487
+ return out;
488
+ }
489
+ function rangesCover(ranges, row, col) {
490
+ for (const r of ranges) if (row >= r.startRow && row <= r.endRow && col >= r.startColumn && col <= r.endColumn) return true;
491
+ return false;
492
+ }
477
493
  function buildSparklineLookup(worksheet, print) {
478
494
  const out = /* @__PURE__ */ new Map();
479
495
  for (const sp of worksheet.sparklines ?? []) {
@@ -525,18 +541,23 @@ function collectSeriesValues(cells, area) {
525
541
  for (let r = area.startRow; r <= area.endRow; r++) for (let col = area.startColumn; col <= area.endColumn; col++) out.push(byKey.get(key(r, col)) ?? null);
526
542
  return out;
527
543
  }
544
+ function isPivotTotal(t) {
545
+ return t !== void 0 && t !== "data" && t !== "blank";
546
+ }
528
547
  function buildTableFormatLookup(worksheet) {
529
548
  const out = /* @__PURE__ */ new Map();
530
- for (const t of worksheet.tables ?? []) {
531
- const { ref } = t;
532
- const firstDataRow = ref.startRow + t.headerRowCount;
549
+ const band = (ref, headerRows, style, isTotalRow) => {
550
+ const firstDataRow = ref.startRow + headerRows;
533
551
  for (let r = ref.startRow; r <= ref.endRow; r++) {
534
552
  let colorHex;
535
553
  let fontColorHex;
536
554
  if (r < firstDataRow) {
537
- colorHex = t.headerHex;
538
- fontColorHex = t.headerTextHex;
539
- } else if (t.showRowStripes && t.bandHex) colorHex = (r - firstDataRow) % 2 === 1 ? t.bandHex : void 0;
555
+ colorHex = style.headerHex;
556
+ fontColorHex = style.headerTextHex;
557
+ } else if (isTotalRow?.(r - firstDataRow)) {
558
+ colorHex = style.headerHex;
559
+ fontColorHex = style.headerTextHex;
560
+ } else if (style.showRowStripes && style.bandHex) colorHex = (r - firstDataRow) % 2 === 1 ? style.bandHex : void 0;
540
561
  if (!colorHex && !fontColorHex) continue;
541
562
  const fmt = {
542
563
  ...colorHex ? { shading: { colorHex } } : {},
@@ -544,11 +565,104 @@ function buildTableFormatLookup(worksheet) {
544
565
  };
545
566
  for (let c = ref.startColumn; c <= ref.endColumn; c++) out.set(key(r, c), fmt);
546
567
  }
568
+ };
569
+ for (const t of worksheet.tables ?? []) band(t.ref, t.headerRowCount, t);
570
+ for (const p of worksheet.pivotTables ?? []) band(p.ref, p.firstDataRow, p, (off) => isPivotTotal(p.rowItemTypes?.[off]));
571
+ for (const p of worksheet.pivotTables ?? []) {
572
+ if (!p.colItemTypes || p.headerHex === void 0) continue;
573
+ const firstDataRow = p.ref.startRow + p.firstDataRow;
574
+ const firstDataCol = p.ref.startColumn + p.firstDataCol;
575
+ const totalFmt = {
576
+ shading: { colorHex: p.headerHex },
577
+ ...p.headerTextHex ? { fontColorHex: p.headerTextHex } : {}
578
+ };
579
+ for (let i = 0; i < p.colItemTypes.length; i++) {
580
+ if (!isPivotTotal(p.colItemTypes[i])) continue;
581
+ const c = firstDataCol + i;
582
+ if (c > p.ref.endColumn) continue;
583
+ for (let r = firstDataRow; r <= p.ref.endRow; r++) out.set(key(r, c), totalFmt);
584
+ }
547
585
  }
548
586
  return out;
549
587
  }
550
588
  function cellHasContent(cell) {
551
589
  return !!cell && (cell.rawValue !== "" || cell.inlineText !== void 0);
552
590
  }
591
+ var SLICER_WIDTH_PT = 108;
592
+ var SLICER_ROW_PT = 16;
593
+ var SLICER_UNSELECTED_HEX = "F2F2F2";
594
+ function slicerTable(slicer) {
595
+ const cols = Math.max(1, slicer.columnCount);
596
+ const colWidthPt = SLICER_WIDTH_PT / cols;
597
+ const thin = {
598
+ style: "single",
599
+ width: eighthPtToPt(4)
600
+ };
601
+ const rowProps = {
602
+ height: pt(SLICER_ROW_PT),
603
+ heightRule: "atLeast"
604
+ };
605
+ const rows = [];
606
+ rows.push({
607
+ properties: rowProps,
608
+ cells: [{
609
+ properties: {
610
+ ...cols > 1 ? { colSpan: cols } : {},
611
+ ...slicer.headerHex ? { shading: { colorHex: slicer.headerHex } } : {}
612
+ },
613
+ content: [slicerParagraph(slicer.caption, {
614
+ bold: true,
615
+ ...slicer.headerTextHex ? { colorHex: slicer.headerTextHex } : {}
616
+ })]
617
+ }]
618
+ });
619
+ for (let i = 0; i < slicer.items.length; i += cols) {
620
+ const cells = [];
621
+ for (let c = 0; c < cols; c++) {
622
+ const item = slicer.items[i + c];
623
+ if (!item) {
624
+ cells.push({
625
+ properties: {},
626
+ content: [slicerParagraph("", {})]
627
+ });
628
+ continue;
629
+ }
630
+ const fill = item.selected ? slicer.selectedHex : SLICER_UNSELECTED_HEX;
631
+ const textHex = item.selected ? slicer.selectedTextHex : void 0;
632
+ cells.push({
633
+ properties: fill ? { shading: { colorHex: fill } } : {},
634
+ content: [slicerParagraph(item.label, textHex ? { colorHex: textHex } : {})]
635
+ });
636
+ }
637
+ rows.push({
638
+ properties: rowProps,
639
+ cells
640
+ });
641
+ }
642
+ return {
643
+ properties: { borders: {
644
+ top: thin,
645
+ bottom: thin,
646
+ left: thin,
647
+ right: thin,
648
+ insideH: thin,
649
+ insideV: thin
650
+ } },
651
+ grid: Array.from({ length: cols }, () => pt(colWidthPt)),
652
+ rows
653
+ };
654
+ }
655
+ function slicerParagraph(text, runProps) {
656
+ return {
657
+ kind: "paragraph",
658
+ paragraph: {
659
+ properties: {},
660
+ runs: text.length > 0 ? [{
661
+ text,
662
+ properties: runProps
663
+ }] : []
664
+ }
665
+ };
666
+ }
553
667
  //#endregion
554
- export { resolvePrintArea, resolvePrintTitleRows, sectionFromWorksheet, worksheetToBody };
668
+ export { resolveCellText, resolvePrintArea, resolvePrintTitleRows, sectionFromWorksheet, slicerTable, worksheetToBody };
@@ -1,7 +1,7 @@
1
1
  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
- import { resolvePrintArea, resolvePrintTitleRows, sectionFromWorksheet, worksheetToBody } from "./print-model.js";
4
+ import { resolvePrintArea, resolvePrintTitleRows, sectionFromWorksheet, slicerTable, worksheetToBody } from "./print-model.js";
5
5
  //#region src/excel/sheet-to-flow.ts
6
6
  function projectSheetDoc(sheet) {
7
7
  const body = [];
@@ -35,6 +35,10 @@ function projectSheetDoc(sheet) {
35
35
  paragraphProperties: {}
36
36
  }
37
37
  });
38
+ for (const slicer of ws.slicers ?? []) body.push({
39
+ kind: "table",
40
+ table: slicerTable(slicer)
41
+ });
38
42
  }
39
43
  return {
40
44
  kind: "flow",
@@ -0,0 +1,15 @@
1
+ export interface SlicerDef {
2
+ readonly name: string;
3
+ readonly cacheName: string;
4
+ readonly caption: string;
5
+ readonly columnCount: number;
6
+ readonly styleName?: string;
7
+ }
8
+ export interface SlicerCacheDef {
9
+ readonly name: string;
10
+ readonly sourceName?: string;
11
+ readonly tableId?: number;
12
+ readonly columnId?: number;
13
+ }
14
+ export declare function parseSlicerPart(data: Uint8Array): Array<SlicerDef>;
15
+ export declare function parseSlicerCachePart(data: Uint8Array): SlicerCacheDef | undefined;
@@ -0,0 +1,76 @@
1
+ import { XMLParser } from "fast-xml-parser";
2
+ //#region src/excel/slicer-parser.ts
3
+ var decoder = new TextDecoder("utf-8");
4
+ var parser = new XMLParser({
5
+ ignoreAttributes: false,
6
+ attributeNamePrefix: "@_",
7
+ parseAttributeValue: false,
8
+ parseTagValue: false,
9
+ removeNSPrefix: true
10
+ });
11
+ function parseSlicerPart(data) {
12
+ const root = asObj(parser.parse(decoder.decode(data))["slicers"]);
13
+ if (!root) return [];
14
+ const out = [];
15
+ for (const s of asArray(root["slicer"])) {
16
+ const o = asObj(s);
17
+ if (!o) continue;
18
+ const name = strAttr(o, "name");
19
+ const cacheName = strAttr(o, "cache");
20
+ if (!name || !cacheName) continue;
21
+ const caption = strAttr(o, "caption") ?? name;
22
+ const styleName = strAttr(o, "style");
23
+ out.push({
24
+ name,
25
+ cacheName,
26
+ caption,
27
+ columnCount: Math.max(1, numAttr(o, "columnCount") ?? 1),
28
+ ...styleName ? { styleName } : {}
29
+ });
30
+ }
31
+ return out;
32
+ }
33
+ function parseSlicerCachePart(data) {
34
+ const root = asObj(parser.parse(decoder.decode(data))["slicerCacheDefinition"]);
35
+ if (!root) return void 0;
36
+ const name = strAttr(root, "name");
37
+ if (!name) return void 0;
38
+ const sourceName = strAttr(root, "sourceName");
39
+ let tableId;
40
+ let columnId;
41
+ const extLst = asObj(root["extLst"]);
42
+ if (extLst) for (const ext of asArray(extLst["ext"])) {
43
+ const e = asObj(ext);
44
+ const inner = e ? asObj(e["slicerCacheDefinition"]) : void 0;
45
+ const tsc = inner ? asObj(inner["tableSlicerCache"]) : void 0;
46
+ if (tsc) {
47
+ tableId = numAttr(tsc, "tableId");
48
+ columnId = numAttr(tsc, "column");
49
+ break;
50
+ }
51
+ }
52
+ return {
53
+ name,
54
+ ...sourceName ? { sourceName } : {},
55
+ ...tableId !== void 0 ? { tableId } : {},
56
+ ...columnId !== void 0 ? { columnId } : {}
57
+ };
58
+ }
59
+ function asObj(v) {
60
+ return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
61
+ }
62
+ function asArray(v) {
63
+ return Array.isArray(v) ? v : v === void 0 || v === null ? [] : [v];
64
+ }
65
+ function strAttr(obj, name) {
66
+ const v = obj[`@_${name}`];
67
+ return typeof v === "string" ? v : void 0;
68
+ }
69
+ function numAttr(obj, name) {
70
+ const v = strAttr(obj, name);
71
+ if (v === void 0) return void 0;
72
+ const n = Number(v);
73
+ return Number.isFinite(n) ? n : void 0;
74
+ }
75
+ //#endregion
76
+ export { parseSlicerCachePart, parseSlicerPart };
@@ -1,2 +1,12 @@
1
1
  import { ExcelTable } from '../core/spreadsheet-model/index.js';
2
+ export interface TableFilterColumn {
3
+ readonly colId: number;
4
+ readonly values: ReadonlyArray<string>;
5
+ }
6
+ export interface ParsedTablePart {
7
+ readonly table: ExcelTable;
8
+ readonly id?: number;
9
+ readonly filters: ReadonlyArray<TableFilterColumn>;
10
+ }
2
11
  export declare function parseTablePart(data: Uint8Array): ExcelTable | undefined;
12
+ export declare function parseTablePartFull(data: Uint8Array): ParsedTablePart | undefined;