reamkit 1.4.0 → 1.6.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 (62) hide show
  1. package/README.md +10 -8
  2. package/dist/esm/core/converter/facade.d.ts +12 -6
  3. package/dist/esm/core/converter/facade.js +34 -5
  4. package/dist/esm/core/converter/ream.d.ts +5 -3
  5. package/dist/esm/core/converter/ream.js +18 -4
  6. package/dist/esm/core/document-model/index.d.ts +1 -1
  7. package/dist/esm/core/document-model/types.d.ts +26 -0
  8. package/dist/esm/core/drawingml/sparkline-geometry.d.ts +8 -0
  9. package/dist/esm/core/drawingml/sparkline-geometry.js +111 -0
  10. package/dist/esm/core/ir/adapters.d.ts +5 -5
  11. package/dist/esm/core/ir/sheet.d.ts +31 -0
  12. package/dist/esm/core/opc/relationships.js +1 -0
  13. package/dist/esm/core/spreadsheet-model/index.d.ts +1 -0
  14. package/dist/esm/core/spreadsheet-model/types.d.ts +189 -0
  15. package/dist/esm/excel/column-bands.d.ts +7 -0
  16. package/dist/esm/excel/column-bands.js +87 -0
  17. package/dist/esm/excel/conditional-format.d.ts +16 -0
  18. package/dist/esm/excel/conditional-format.js +327 -0
  19. package/dist/esm/excel/index.d.ts +4 -3
  20. package/dist/esm/excel/print-model.d.ts +2 -1
  21. package/dist/esm/excel/print-model.js +144 -13
  22. package/dist/esm/excel/sheet-drawing.d.ts +1 -1
  23. package/dist/esm/excel/sheet-to-flow.d.ts +3 -0
  24. package/dist/esm/excel/sheet-to-flow.js +51 -0
  25. package/dist/esm/excel/styles-parser.d.ts +1 -50
  26. package/dist/esm/excel/styles-parser.js +38 -1
  27. package/dist/esm/excel/table-parser.d.ts +2 -0
  28. package/dist/esm/excel/table-parser.js +51 -0
  29. package/dist/esm/excel/workbook-parser.d.ts +1 -5
  30. package/dist/esm/excel/worksheet-parser.d.ts +1 -60
  31. package/dist/esm/excel/worksheet-parser.js +265 -1
  32. package/dist/esm/excel/xlsx-reader.d.ts +3 -1
  33. package/dist/esm/excel/xlsx-reader.js +86 -51
  34. package/dist/esm/excel/xlsx-writer.d.ts +4 -0
  35. package/dist/esm/excel/xlsx-writer.js +278 -0
  36. package/dist/esm/html/html-writer.js +126 -4
  37. package/dist/esm/layout/styled-layout.js +160 -1
  38. package/dist/esm/pdf-reader/cmap.d.ts +5 -0
  39. package/dist/esm/pdf-reader/cmap.js +72 -0
  40. package/dist/esm/pdf-reader/content.d.ts +14 -0
  41. package/dist/esm/pdf-reader/content.js +292 -0
  42. package/dist/esm/pdf-reader/document.d.ts +23 -0
  43. package/dist/esm/pdf-reader/document.js +230 -0
  44. package/dist/esm/pdf-reader/flow-build.d.ts +4 -0
  45. package/dist/esm/pdf-reader/flow-build.js +27 -0
  46. package/dist/esm/pdf-reader/font.d.ts +4 -0
  47. package/dist/esm/pdf-reader/font.js +69 -0
  48. package/dist/esm/pdf-reader/layout.d.ts +3 -0
  49. package/dist/esm/pdf-reader/layout.js +69 -0
  50. package/dist/esm/pdf-reader/lexer.d.ts +43 -0
  51. package/dist/esm/pdf-reader/lexer.js +250 -0
  52. package/dist/esm/pdf-reader/parser.d.ts +10 -0
  53. package/dist/esm/pdf-reader/parser.js +86 -0
  54. package/dist/esm/pdf-reader/reader.d.ts +4 -0
  55. package/dist/esm/pdf-reader/reader.js +43 -0
  56. package/dist/esm/pdf-reader/struct-tree.d.ts +14 -0
  57. package/dist/esm/pdf-reader/struct-tree.js +92 -0
  58. package/dist/esm/pdf-reader/tagged.d.ts +3 -0
  59. package/dist/esm/pdf-reader/tagged.js +88 -0
  60. package/dist/esm/pdf-reader/text.d.ts +3 -0
  61. package/dist/esm/pdf-reader/text.js +18 -0
  62. package/package.json +4 -3
@@ -0,0 +1,189 @@
1
+ export type CellType = 'n' | 's' | 'str' | 'b' | 'd' | 'e' | 'inlineStr';
2
+ export interface WorksheetCell {
3
+ readonly column: number;
4
+ readonly row: number;
5
+ readonly type: CellType;
6
+ readonly rawValue: string;
7
+ readonly inlineText?: string;
8
+ readonly styleIndex?: number;
9
+ }
10
+ export interface ColumnWidth {
11
+ readonly min: number;
12
+ readonly max: number;
13
+ readonly widthChars: number;
14
+ }
15
+ export interface MergedRange {
16
+ readonly startColumn: number;
17
+ readonly startRow: number;
18
+ readonly endColumn: number;
19
+ readonly endRow: number;
20
+ }
21
+ export interface RowHeight {
22
+ readonly row: number;
23
+ readonly heightPt: number;
24
+ readonly customHeight: boolean;
25
+ }
26
+ export interface XlsxPageMargins {
27
+ readonly leftInches: number;
28
+ readonly rightInches: number;
29
+ readonly topInches: number;
30
+ readonly bottomInches: number;
31
+ readonly headerInches?: number;
32
+ readonly footerInches?: number;
33
+ }
34
+ export interface XlsxPageSetup {
35
+ readonly paperSize?: number;
36
+ readonly orientation?: 'portrait' | 'landscape' | 'default';
37
+ readonly scale?: number;
38
+ readonly fitToWidth?: number;
39
+ readonly fitToHeight?: number;
40
+ }
41
+ export interface XlsxPrintOptions {
42
+ readonly gridLines?: boolean;
43
+ readonly horizontalCentered?: boolean;
44
+ readonly verticalCentered?: boolean;
45
+ }
46
+ export interface ParsedWorksheet {
47
+ readonly cells: ReadonlyArray<WorksheetCell>;
48
+ readonly maxRow: number;
49
+ readonly maxColumn: number;
50
+ readonly columns: ReadonlyArray<ColumnWidth>;
51
+ readonly merges: ReadonlyArray<MergedRange>;
52
+ readonly rowHeights: ReadonlyArray<RowHeight>;
53
+ readonly pageMargins?: XlsxPageMargins;
54
+ readonly pageSetup?: XlsxPageSetup;
55
+ readonly fitToPage?: boolean;
56
+ readonly printOptions?: XlsxPrintOptions;
57
+ readonly rowBreaks?: ReadonlyArray<number>;
58
+ readonly colBreaks?: ReadonlyArray<number>;
59
+ readonly drawingRelId?: string;
60
+ readonly conditionalFormats?: ReadonlyArray<ConditionalFormat>;
61
+ readonly sparklines?: ReadonlyArray<ParsedSparkline>;
62
+ readonly tablePartRelIds?: ReadonlyArray<string>;
63
+ readonly tables?: ReadonlyArray<ExcelTable>;
64
+ readonly pane?: SheetPane;
65
+ }
66
+ export interface SheetPane {
67
+ readonly frozenRows: number;
68
+ readonly frozenCols: number;
69
+ }
70
+ export interface ExcelTable {
71
+ readonly ref: MergedRange;
72
+ readonly name?: string;
73
+ readonly styleName?: string;
74
+ readonly headerRowCount: number;
75
+ readonly showRowStripes: boolean;
76
+ readonly showColumnStripes: boolean;
77
+ readonly showFirstColumn: boolean;
78
+ readonly showLastColumn: boolean;
79
+ readonly autoFilter: boolean;
80
+ readonly headerHex?: string;
81
+ readonly bandHex?: string;
82
+ readonly headerTextHex?: string;
83
+ }
84
+ export type SparklineKind = 'line' | 'column' | 'winLoss';
85
+ export interface ParsedSparkline {
86
+ readonly kind: SparklineKind;
87
+ readonly dataRange: string;
88
+ readonly sqref: string;
89
+ readonly colorHex?: string;
90
+ }
91
+ export interface XlsxFont {
92
+ readonly sizePt?: number;
93
+ readonly bold?: boolean;
94
+ readonly italic?: boolean;
95
+ readonly underline?: boolean;
96
+ readonly colorHex?: string;
97
+ readonly name?: string;
98
+ }
99
+ export interface XlsxFill {
100
+ readonly patternType?: string;
101
+ readonly fgColorHex?: string;
102
+ readonly bgColorHex?: string;
103
+ }
104
+ export type XlsxBorderStyleName = 'none' | 'thin' | 'medium' | 'thick' | 'hair' | 'dashed' | 'dotted' | 'double' | 'mediumDashed' | 'dashDot' | 'mediumDashDot' | 'dashDotDot' | 'mediumDashDotDot' | 'slantDashDot';
105
+ export interface XlsxBorderEdge {
106
+ readonly style?: XlsxBorderStyleName;
107
+ readonly colorHex?: string;
108
+ }
109
+ export interface XlsxBorder {
110
+ readonly top?: XlsxBorderEdge;
111
+ readonly right?: XlsxBorderEdge;
112
+ readonly bottom?: XlsxBorderEdge;
113
+ readonly left?: XlsxBorderEdge;
114
+ }
115
+ export type XlsxHorizontalAlign = 'left' | 'center' | 'right' | 'fill' | 'justify' | 'centerContinuous' | 'distributed';
116
+ export type XlsxVerticalAlign = 'top' | 'center' | 'bottom' | 'justify' | 'distributed';
117
+ export interface XlsxCellAlignment {
118
+ readonly horizontal?: XlsxHorizontalAlign;
119
+ readonly vertical?: XlsxVerticalAlign;
120
+ readonly wrapText?: boolean;
121
+ }
122
+ export interface XlsxCellXf {
123
+ readonly numFmtId: number;
124
+ readonly fontId: number;
125
+ readonly fillId: number;
126
+ readonly borderId: number;
127
+ readonly applyNumberFormat?: boolean;
128
+ readonly applyFont?: boolean;
129
+ readonly applyFill?: boolean;
130
+ readonly applyBorder?: boolean;
131
+ readonly applyAlignment?: boolean;
132
+ readonly alignment?: XlsxCellAlignment;
133
+ }
134
+ export interface XlsxStyles {
135
+ readonly numFmts: ReadonlyMap<number, string>;
136
+ readonly fonts: ReadonlyArray<XlsxFont>;
137
+ readonly fills: ReadonlyArray<XlsxFill>;
138
+ readonly borders: ReadonlyArray<XlsxBorder>;
139
+ readonly cellXfs: ReadonlyArray<XlsxCellXf>;
140
+ readonly dxfs?: ReadonlyArray<Dxf>;
141
+ }
142
+ export interface Dxf {
143
+ readonly font?: XlsxFont;
144
+ readonly fill?: XlsxFill;
145
+ }
146
+ export interface DefinedName {
147
+ readonly name: string;
148
+ readonly localSheetId?: number;
149
+ readonly value: string;
150
+ }
151
+ export type CfOperator = 'lessThan' | 'lessThanOrEqual' | 'equal' | 'notEqual' | 'greaterThanOrEqual' | 'greaterThan' | 'between' | 'notBetween';
152
+ export interface CfRuleCellIs {
153
+ readonly type: 'cellIs';
154
+ readonly priority: number;
155
+ readonly operator: CfOperator;
156
+ readonly formulas: ReadonlyArray<string>;
157
+ readonly dxfId: number;
158
+ }
159
+ export type CfvoType = 'num' | 'percent' | 'max' | 'min' | 'percentile' | 'formula' | 'autoMin' | 'autoMax';
160
+ export interface Cfvo {
161
+ readonly type: CfvoType;
162
+ readonly val?: string;
163
+ }
164
+ export interface CfRuleColorScale {
165
+ readonly type: 'colorScale';
166
+ readonly priority: number;
167
+ readonly cfvos: ReadonlyArray<Cfvo>;
168
+ readonly colorsHex: ReadonlyArray<string>;
169
+ }
170
+ export interface CfRuleDataBar {
171
+ readonly type: 'dataBar';
172
+ readonly priority: number;
173
+ readonly cfvos: ReadonlyArray<Cfvo>;
174
+ readonly colorHex: string;
175
+ readonly minLength?: number;
176
+ readonly maxLength?: number;
177
+ }
178
+ export interface CfRuleIconSet {
179
+ readonly type: 'iconSet';
180
+ readonly priority: number;
181
+ readonly iconSet: string;
182
+ readonly cfvos: ReadonlyArray<Cfvo>;
183
+ readonly reverse?: boolean;
184
+ }
185
+ export type CfRule = CfRuleCellIs | CfRuleColorScale | CfRuleDataBar | CfRuleIconSet;
186
+ export interface ConditionalFormat {
187
+ readonly ranges: ReadonlyArray<MergedRange>;
188
+ readonly rules: ReadonlyArray<CfRule>;
189
+ }
@@ -0,0 +1,7 @@
1
+ import { BodyElement, TableProperties, TableRow } from '../core/document-model/index.js';
2
+ export interface ColumnBand {
3
+ readonly start: number;
4
+ readonly end: number;
5
+ }
6
+ export declare function computeColumnBands(columnWidths: ReadonlyArray<number>, contentWidthTwips: number, colBreaks: ReadonlySet<number>): Array<ColumnBand>;
7
+ export declare function bandedTables(rows: ReadonlyArray<TableRow>, columnWidths: ReadonlyArray<number>, bands: ReadonlyArray<ColumnBand>, properties: TableProperties): Array<BodyElement>;
@@ -0,0 +1,87 @@
1
+ import { twipsToPt } from "../core/ir/units.js";
2
+ //#region src/excel/column-bands.ts
3
+ function computeColumnBands(columnWidths, contentWidthTwips, colBreaks) {
4
+ const n = columnWidths.length;
5
+ if (n === 0) return [];
6
+ const bands = [];
7
+ let start = 0;
8
+ let acc = 0;
9
+ for (let c = 0; c < n; c++) {
10
+ const w = columnWidths[c] ?? 0;
11
+ const atBreak = c > start && colBreaks.has(c);
12
+ const overflows = c > start && acc + w > contentWidthTwips;
13
+ if (atBreak || overflows) {
14
+ bands.push({
15
+ start,
16
+ end: c - 1
17
+ });
18
+ start = c;
19
+ acc = 0;
20
+ }
21
+ acc += w;
22
+ }
23
+ bands.push({
24
+ start,
25
+ end: n - 1
26
+ });
27
+ return bands;
28
+ }
29
+ function bandedTables(rows, columnWidths, bands, properties) {
30
+ return bands.map((band, bandIndex) => {
31
+ return {
32
+ kind: "table",
33
+ table: {
34
+ properties,
35
+ grid: columnWidths.slice(band.start, band.end + 1).map((w) => twipsToPt(w)),
36
+ rows: rows.map((row, rowIndex) => {
37
+ const cells = sliceRowCells(row.cells, band);
38
+ return {
39
+ properties: bandIndex > 0 && rowIndex === 0 ? {
40
+ ...row.properties,
41
+ pageBreakBefore: true
42
+ } : row.properties,
43
+ cells
44
+ };
45
+ })
46
+ }
47
+ };
48
+ });
49
+ }
50
+ function sliceRowCells(cells, band) {
51
+ const out = [];
52
+ let col = 0;
53
+ for (const cell of cells) {
54
+ const span = cell.properties.colSpan ?? 1;
55
+ const cellStart = col;
56
+ const cellEnd = col + span - 1;
57
+ col += span;
58
+ if (cellEnd < band.start || cellStart > band.end) continue;
59
+ const clampedSpan = Math.min(cellEnd, band.end) - Math.max(cellStart, band.start) + 1;
60
+ if (cellStart >= band.start) out.push(clampedSpan === span ? cell : withColSpan(cell, clampedSpan));
61
+ else out.push(blankCell(clampedSpan));
62
+ }
63
+ return out;
64
+ }
65
+ function withColSpan(cell, span) {
66
+ const props = { ...cell.properties };
67
+ if (span > 1) props.colSpan = span;
68
+ else delete props.colSpan;
69
+ return {
70
+ ...cell,
71
+ properties: props
72
+ };
73
+ }
74
+ function blankCell(span) {
75
+ return {
76
+ properties: span > 1 ? { colSpan: span } : {},
77
+ content: [{
78
+ kind: "paragraph",
79
+ paragraph: {
80
+ properties: {},
81
+ runs: []
82
+ }
83
+ }]
84
+ };
85
+ }
86
+ //#endregion
87
+ export { bandedTables, computeColumnBands };
@@ -0,0 +1,16 @@
1
+ import { CellIcon } from '../core/document-model/index.js';
2
+ import { ConditionalFormat, WorksheetCell, XlsxStyles } from '../core/spreadsheet-model/index.js';
3
+ export interface CfOverride {
4
+ readonly fillHex?: string;
5
+ readonly fontColorHex?: string;
6
+ readonly bold?: boolean;
7
+ readonly italic?: boolean;
8
+ readonly dataBar?: {
9
+ readonly fraction: number;
10
+ readonly colorHex: string;
11
+ readonly startFraction?: number;
12
+ };
13
+ readonly icon?: CellIcon;
14
+ }
15
+ export type CellConditionalFormatter = (row: number, col: number, numericValue: number | undefined) => CfOverride | undefined;
16
+ export declare function buildConditionalFormatter(conditionalFormats: ReadonlyArray<ConditionalFormat> | undefined, styles: XlsxStyles, cells: ReadonlyArray<WorksheetCell>): CellConditionalFormatter | undefined;
@@ -0,0 +1,327 @@
1
+ //#region src/excel/conditional-format.ts
2
+ function buildConditionalFormatter(conditionalFormats, styles, cells) {
3
+ if (!conditionalFormats || conditionalFormats.length === 0) return void 0;
4
+ const dxfs = styles.dxfs ?? [];
5
+ const flat = [];
6
+ for (const cf of conditionalFormats) for (const rule of cf.rules) if (rule.type === "colorScale") flat.push({
7
+ ranges: cf.ranges,
8
+ rule,
9
+ scale: resolveColorScale(rule, cf.ranges, cells)
10
+ });
11
+ else if (rule.type === "dataBar") flat.push({
12
+ ranges: cf.ranges,
13
+ rule,
14
+ bar: resolveDataBar(rule, cf.ranges, cells)
15
+ });
16
+ else if (rule.type === "iconSet") flat.push({
17
+ ranges: cf.ranges,
18
+ rule,
19
+ iconThresholds: resolveIconThresholds(rule, cf.ranges, cells)
20
+ });
21
+ else flat.push({
22
+ ranges: cf.ranges,
23
+ rule
24
+ });
25
+ flat.sort((a, b) => a.rule.priority - b.rule.priority);
26
+ return (row, col, value) => {
27
+ if (value === void 0) return void 0;
28
+ let textFmt;
29
+ let textClaimed = false;
30
+ let bar;
31
+ let icon;
32
+ for (const { ranges, rule, scale, bar: resolved, iconThresholds } of flat) {
33
+ if (!coversCell(ranges, row, col)) continue;
34
+ switch (rule.type) {
35
+ case "cellIs":
36
+ if (!textClaimed && cellIsMatches(rule.operator, value, rule.formulas)) {
37
+ textFmt = dxfToOverride(dxfs[rule.dxfId]);
38
+ textClaimed = true;
39
+ }
40
+ break;
41
+ case "colorScale":
42
+ if (!textClaimed && scale) {
43
+ textFmt = { fillHex: rgbHex(colorScaleColor(scale, value)) };
44
+ textClaimed = true;
45
+ }
46
+ break;
47
+ case "dataBar":
48
+ if (!bar && resolved) bar = dataBarBar(resolved, value);
49
+ break;
50
+ case "iconSet":
51
+ if (!icon && iconThresholds) {
52
+ const bucket = iconBucket(iconThresholds, value);
53
+ icon = iconToCell(rule.iconSet, iconThresholds.length, bucket, rule.reverse ?? false);
54
+ }
55
+ break;
56
+ }
57
+ }
58
+ if (!bar && !icon) return textFmt;
59
+ return {
60
+ ...textFmt ?? {},
61
+ ...bar ? { dataBar: bar } : {},
62
+ ...icon ? { icon } : {}
63
+ };
64
+ };
65
+ }
66
+ function coversCell(ranges, row, col) {
67
+ for (const r of ranges) if (row >= r.startRow && row <= r.endRow && col >= r.startColumn && col <= r.endColumn) return true;
68
+ return false;
69
+ }
70
+ function cellIsMatches(operator, value, formulas) {
71
+ const a = Number(formulas[0]);
72
+ if (!Number.isFinite(a)) return false;
73
+ switch (operator) {
74
+ case "lessThan": return value < a;
75
+ case "lessThanOrEqual": return value <= a;
76
+ case "equal": return value === a;
77
+ case "notEqual": return value !== a;
78
+ case "greaterThanOrEqual": return value >= a;
79
+ case "greaterThan": return value > a;
80
+ case "between":
81
+ case "notBetween": {
82
+ const b = Number(formulas[1]);
83
+ if (!Number.isFinite(b)) return false;
84
+ const inside = value >= Math.min(a, b) && value <= Math.max(a, b);
85
+ return operator === "between" ? inside : !inside;
86
+ }
87
+ }
88
+ }
89
+ function dxfToOverride(dxf) {
90
+ if (!dxf) return void 0;
91
+ const fillHex = dxf.fill?.bgColorHex ?? dxf.fill?.fgColorHex;
92
+ const out = {};
93
+ if (fillHex) out.fillHex = fillHex;
94
+ if (dxf.font?.colorHex) out.fontColorHex = dxf.font.colorHex;
95
+ if (dxf.font?.bold !== void 0) out.bold = dxf.font.bold;
96
+ if (dxf.font?.italic !== void 0) out.italic = dxf.font.italic;
97
+ return Object.keys(out).length > 0 ? out : void 0;
98
+ }
99
+ function collectRangeValues(cells, ranges) {
100
+ const out = [];
101
+ for (const cell of cells) {
102
+ if (cell.type !== "n") continue;
103
+ const n = Number(cell.rawValue);
104
+ if (!Number.isFinite(n)) continue;
105
+ if (coversCell(ranges, cell.row, cell.column)) out.push(n);
106
+ }
107
+ return out;
108
+ }
109
+ function resolveColorScale(rule, ranges, cells) {
110
+ const vals = collectRangeValues(cells, ranges);
111
+ if (vals.length === 0) return void 0;
112
+ const sorted = [...vals].sort((a, b) => a - b);
113
+ const vmin = sorted[0];
114
+ const vmax = sorted[sorted.length - 1];
115
+ const thresholds = [];
116
+ for (const cfvo of rule.cfvos) {
117
+ const t = resolveCfvo(cfvo, vmin, vmax, sorted);
118
+ if (t === void 0) return void 0;
119
+ thresholds.push(t);
120
+ }
121
+ const colors = [];
122
+ for (const hex of rule.colorsHex) {
123
+ const rgb = parseRgb(hex);
124
+ if (!rgb) return void 0;
125
+ colors.push(rgb);
126
+ }
127
+ if (thresholds.length < 2 || thresholds.length !== colors.length) return void 0;
128
+ for (let i = 1; i < thresholds.length; i++) if (thresholds[i] < thresholds[i - 1]) thresholds[i] = thresholds[i - 1];
129
+ return {
130
+ thresholds,
131
+ colors
132
+ };
133
+ }
134
+ function resolveCfvo(cfvo, vmin, vmax, sorted) {
135
+ switch (cfvo.type) {
136
+ case "min":
137
+ case "autoMin": return vmin;
138
+ case "max":
139
+ case "autoMax": return vmax;
140
+ case "num":
141
+ case "formula": {
142
+ const n = Number(cfvo.val);
143
+ return Number.isFinite(n) ? n : void 0;
144
+ }
145
+ case "percent": {
146
+ const p = Number(cfvo.val);
147
+ return Number.isFinite(p) ? vmin + (vmax - vmin) * (p / 100) : void 0;
148
+ }
149
+ case "percentile": {
150
+ const p = Number(cfvo.val);
151
+ return Number.isFinite(p) ? percentile(sorted, p) : void 0;
152
+ }
153
+ }
154
+ }
155
+ function percentile(sorted, p) {
156
+ const n = sorted.length;
157
+ if (n === 1) return sorted[0];
158
+ const rank = Math.min(100, Math.max(0, p)) / 100 * (n - 1);
159
+ const lo = Math.floor(rank);
160
+ const frac = rank - lo;
161
+ const a = sorted[lo];
162
+ return a + frac * (sorted[Math.min(lo + 1, n - 1)] - a);
163
+ }
164
+ function colorScaleColor(scale, value) {
165
+ const { thresholds: t, colors } = scale;
166
+ const last = t.length - 1;
167
+ if (value <= t[0]) return colors[0];
168
+ if (value >= t[last]) return colors[last];
169
+ let i = 0;
170
+ while (i < last && value > t[i + 1]) i++;
171
+ const a = t[i];
172
+ const b = t[i + 1];
173
+ const f = b > a ? (value - a) / (b - a) : 0;
174
+ return lerpRgb(colors[i], colors[i + 1], f);
175
+ }
176
+ function lerpRgb(c0, c1, f) {
177
+ return [
178
+ c0[0] + (c1[0] - c0[0]) * f,
179
+ c0[1] + (c1[1] - c0[1]) * f,
180
+ c0[2] + (c1[2] - c0[2]) * f
181
+ ];
182
+ }
183
+ function parseRgb(hex) {
184
+ const h = hex.length === 8 ? hex.slice(2) : hex;
185
+ if (!/^[0-9A-Fa-f]{6}$/.test(h)) return void 0;
186
+ return [
187
+ parseInt(h.slice(0, 2), 16),
188
+ parseInt(h.slice(2, 4), 16),
189
+ parseInt(h.slice(4, 6), 16)
190
+ ];
191
+ }
192
+ function rgbHex([r, g, b]) {
193
+ const h = (n) => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2, "0").toUpperCase();
194
+ return `${h(r)}${h(g)}${h(b)}`;
195
+ }
196
+ function resolveDataBar(rule, ranges, cells) {
197
+ const vals = collectRangeValues(cells, ranges);
198
+ if (vals.length === 0) return void 0;
199
+ const sorted = [...vals].sort((a, b) => a - b);
200
+ const vmin = sorted[0];
201
+ const vmax = sorted[sorted.length - 1];
202
+ const lower = resolveCfvo(rule.cfvos[0], vmin, vmax, sorted);
203
+ const upper = resolveCfvo(rule.cfvos[1], vmin, vmax, sorted);
204
+ if (lower === void 0 || upper === void 0) return void 0;
205
+ return {
206
+ lower,
207
+ upper,
208
+ colorHex: rule.colorHex,
209
+ negativeColorHex: "FF0000",
210
+ minLen: (rule.minLength ?? 0) / 100,
211
+ maxLen: (rule.maxLength ?? 100) / 100
212
+ };
213
+ }
214
+ function dataBarBar(bar, value) {
215
+ if (bar.lower < 0 && bar.upper > 0) {
216
+ const axis = -bar.lower / (bar.upper - bar.lower);
217
+ if (value >= 0) return {
218
+ fraction: value / bar.upper * (1 - axis),
219
+ colorHex: bar.colorHex,
220
+ startFraction: axis
221
+ };
222
+ const w = Math.abs(value) / Math.abs(bar.lower) * axis;
223
+ return {
224
+ fraction: w,
225
+ colorHex: bar.negativeColorHex,
226
+ startFraction: axis - w
227
+ };
228
+ }
229
+ return {
230
+ fraction: dataBarFraction(bar, value),
231
+ colorHex: bar.colorHex
232
+ };
233
+ }
234
+ function dataBarFraction(bar, value) {
235
+ const t = bar.upper > bar.lower ? Math.min(1, Math.max(0, (value - bar.lower) / (bar.upper - bar.lower))) : value >= bar.upper ? 1 : 0;
236
+ return bar.minLen + t * (bar.maxLen - bar.minLen);
237
+ }
238
+ function resolveIconThresholds(rule, ranges, cells) {
239
+ const vals = collectRangeValues(cells, ranges);
240
+ if (vals.length === 0) return void 0;
241
+ const sorted = [...vals].sort((a, b) => a - b);
242
+ const vmin = sorted[0];
243
+ const vmax = sorted[sorted.length - 1];
244
+ const out = [];
245
+ for (const cfvo of rule.cfvos) {
246
+ const t = resolveCfvo(cfvo, vmin, vmax, sorted);
247
+ if (t === void 0) return void 0;
248
+ out.push(t);
249
+ }
250
+ return out;
251
+ }
252
+ function iconBucket(thresholds, value) {
253
+ let idx = 0;
254
+ for (let i = 1; i < thresholds.length; i++) if (value >= thresholds[i]) idx++;
255
+ return idx;
256
+ }
257
+ function iconToCell(setName, count, index, reverse) {
258
+ const e = reverse ? count - 1 - index : index;
259
+ if (/Rating/i.test(setName)) return {
260
+ shape: "bars",
261
+ colorHex: METER_HEX,
262
+ fill: {
263
+ filled: e + 1,
264
+ levels: count
265
+ }
266
+ };
267
+ if (/Quarters/i.test(setName)) return {
268
+ shape: "pie",
269
+ colorHex: METER_HEX,
270
+ fill: {
271
+ filled: e,
272
+ levels: count - 1
273
+ }
274
+ };
275
+ const colorHex = /Gray/i.test(setName) ? GRAY_HEX : iconColor(count, e);
276
+ return {
277
+ shape: iconShape(setName, e, count),
278
+ colorHex
279
+ };
280
+ }
281
+ var GRAY_HEX = "808080";
282
+ var METER_HEX = "595959";
283
+ function iconShape(setName, e, count) {
284
+ if (setName.includes("Arrows")) {
285
+ if (e <= 0) return "triangleDown";
286
+ if (e >= count - 1) return "triangleUp";
287
+ return "triangleRight";
288
+ }
289
+ if (setName.includes("Symbols")) {
290
+ if (e <= 0) return "cross";
291
+ if (e >= count - 1) return "check";
292
+ return "exclamation";
293
+ }
294
+ if (setName.includes("Signs")) {
295
+ if (e <= 0) return "diamond";
296
+ if (e >= count - 1) return "circle";
297
+ return "triangleUp";
298
+ }
299
+ if (setName.includes("Flags")) return "square";
300
+ return "circle";
301
+ }
302
+ var ICON_RAMPS = {
303
+ 3: [
304
+ "FF0000",
305
+ "FFC000",
306
+ "00B050"
307
+ ],
308
+ 4: [
309
+ "FF0000",
310
+ "FF8C00",
311
+ "FFC000",
312
+ "00B050"
313
+ ],
314
+ 5: [
315
+ "FF0000",
316
+ "FF8C00",
317
+ "FFC000",
318
+ "92D050",
319
+ "00B050"
320
+ ]
321
+ };
322
+ function iconColor(count, e) {
323
+ const ramp = ICON_RAMPS[count] ?? ICON_RAMPS[3];
324
+ return ramp[Math.max(0, Math.min(ramp.length - 1, e))];
325
+ }
326
+ //#endregion
327
+ export { buildConditionalFormatter };
@@ -4,9 +4,10 @@ export { parseAreaRef, parseTitleRowRange } from './defined-name-ref.js';
4
4
  export type { CellRange } from './defined-name-ref.js';
5
5
  export { parseSharedStrings } from './shared-strings-parser.js';
6
6
  export { parseWorkbook } from './workbook-parser.js';
7
- export type { DefinedName, ParsedWorkbook, SheetReference } from './workbook-parser.js';
7
+ export type { ParsedWorkbook, SheetReference } from './workbook-parser.js';
8
+ export type { DefinedName } from '../core/spreadsheet-model/index.js';
8
9
  export { parseWorksheet } from './worksheet-parser.js';
9
- export type { CellType, ColumnWidth, MergedRange, ParsedWorksheet, RowHeight, WorksheetCell, XlsxPageMargins, XlsxPageSetup, XlsxPrintOptions, } from './worksheet-parser.js';
10
+ export type { CellType, ColumnWidth, ExcelTable, MergedRange, ParsedWorksheet, RowHeight, WorksheetCell, XlsxPageMargins, XlsxPageSetup, XlsxPrintOptions, } from '../core/spreadsheet-model/index.js';
10
11
  export { parseXlsxStyles, EMPTY_XLSX_STYLES } from './styles-parser.js';
11
- export type { XlsxBorder, XlsxBorderEdge, XlsxBorderStyleName, XlsxCellAlignment, XlsxCellXf, XlsxFill, XlsxFont, XlsxHorizontalAlign, XlsxStyles, XlsxVerticalAlign, } from './styles-parser.js';
12
+ export type { XlsxBorder, XlsxBorderEdge, XlsxBorderStyleName, XlsxCellAlignment, XlsxCellXf, XlsxFill, XlsxFont, XlsxHorizontalAlign, XlsxStyles, XlsxVerticalAlign, } from '../core/spreadsheet-model/index.js';
12
13
  export { applyNumberFormat } from './number-format.js';
@@ -16,6 +16,7 @@ interface PrintModelOptions {
16
16
  readonly startRow: number;
17
17
  readonly endRow: number;
18
18
  };
19
+ readonly sheetGrids?: ReadonlyMap<string, ParsedWorksheet>;
19
20
  }
20
- export declare function worksheetToBody(worksheet: ParsedWorksheet, sharedStrings: Array<string>, styles: XlsxStyles, date1904: boolean, print: PrintModelOptions): Array<BodyElement>;
21
+ export declare function worksheetToBody(worksheet: ParsedWorksheet, sharedStrings: ReadonlyArray<string>, styles: XlsxStyles, date1904: boolean, print: PrintModelOptions): Array<BodyElement>;
21
22
  export {};