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.
- package/README.md +34 -8
- package/dist/esm/core/converter/facade.d.ts +8 -1
- package/dist/esm/core/converter/facade.js +34 -8
- package/dist/esm/core/converter/ream.d.ts +1 -0
- package/dist/esm/core/converter/ream.js +13 -8
- package/dist/esm/core/document-model/types.d.ts +2 -0
- package/dist/esm/core/ir/features.d.ts +1 -0
- package/dist/esm/core/ir/features.js +1 -0
- package/dist/esm/core/ir/sheet.d.ts +42 -3
- package/dist/esm/core/ole/cfb.d.ts +19 -0
- package/dist/esm/core/ole/cfb.js +158 -0
- package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
- package/dist/esm/core/spreadsheet-model/types.d.ts +81 -1
- package/dist/esm/excel/activex-parser.d.ts +9 -0
- package/dist/esm/excel/activex-parser.js +188 -0
- package/dist/esm/excel/comments-parser.d.ts +4 -0
- package/dist/esm/excel/comments-parser.js +104 -0
- package/dist/esm/excel/conditional-format.d.ts +5 -3
- package/dist/esm/excel/conditional-format.js +248 -12
- package/dist/esm/excel/form-control-parser.d.ts +6 -0
- package/dist/esm/excel/form-control-parser.js +29 -0
- package/dist/esm/excel/formula/context.d.ts +11 -0
- package/dist/esm/excel/formula/dates.d.ts +11 -0
- package/dist/esm/excel/formula/dates.js +46 -0
- package/dist/esm/excel/formula/eval.d.ts +11 -0
- package/dist/esm/excel/formula/eval.js +196 -0
- package/dist/esm/excel/formula/functions.d.ts +7 -0
- package/dist/esm/excel/formula/functions.js +1359 -0
- package/dist/esm/excel/formula/index.d.ts +14 -0
- package/dist/esm/excel/formula/index.js +17 -0
- package/dist/esm/excel/formula/lexer.d.ts +8 -0
- package/dist/esm/excel/formula/lexer.js +163 -0
- package/dist/esm/excel/formula/parser.d.ts +57 -0
- package/dist/esm/excel/formula/parser.js +274 -0
- package/dist/esm/excel/formula/value.d.ts +52 -0
- package/dist/esm/excel/formula/value.js +102 -0
- package/dist/esm/excel/header-footer.d.ts +2 -0
- package/dist/esm/excel/header-footer.js +127 -0
- package/dist/esm/excel/index.d.ts +1 -1
- package/dist/esm/excel/number-format.d.ts +2 -0
- package/dist/esm/excel/number-format.js +5 -1
- package/dist/esm/excel/print-model.d.ts +7 -2
- package/dist/esm/excel/print-model.js +123 -16
- package/dist/esm/excel/shared-strings-parser.d.ts +6 -1
- package/dist/esm/excel/shared-strings-parser.js +91 -12
- package/dist/esm/excel/sheet-drawing.d.ts +13 -1
- package/dist/esm/excel/sheet-drawing.js +47 -14
- package/dist/esm/excel/sheet-shape-parser.d.ts +4 -0
- package/dist/esm/excel/sheet-shape-parser.js +96 -0
- package/dist/esm/excel/sheet-to-flow.d.ts +4 -1
- package/dist/esm/excel/sheet-to-flow.js +170 -3
- package/dist/esm/excel/styles-parser.js +37 -0
- package/dist/esm/excel/worksheet-parser.js +191 -1
- package/dist/esm/excel/xls/biff-chart.d.ts +8 -0
- package/dist/esm/excel/xls/biff-chart.js +121 -0
- package/dist/esm/excel/xls/biff-reader.d.ts +4 -0
- package/dist/esm/excel/xls/biff-reader.js +1418 -0
- package/dist/esm/excel/xls/biff-styles.d.ts +8 -0
- package/dist/esm/excel/xls/biff-styles.js +299 -0
- package/dist/esm/excel/xls/escher.d.ts +24 -0
- package/dist/esm/excel/xls/escher.js +171 -0
- package/dist/esm/excel/xls/xls-reader.d.ts +3 -0
- package/dist/esm/excel/xls/xls-reader.js +30 -0
- package/dist/esm/excel/xlsx-reader.d.ts +2 -1
- package/dist/esm/excel/xlsx-reader.js +134 -16
- package/dist/esm/excel/xlsx-to-pdf.d.ts +1 -0
- package/dist/esm/excel/xlsx-to-pdf.js +2 -2
- package/dist/esm/excel/xlsx-writer.js +12 -2
- package/dist/esm/layout/styled-layout.js +29 -0
- package/dist/esm/pptx/ppt/ppt-reader.d.ts +4 -0
- package/dist/esm/pptx/ppt/ppt-reader.js +337 -0
- package/dist/esm/pptx/ppt/ppt-text.d.ts +69 -0
- package/dist/esm/pptx/ppt/ppt-text.js +756 -0
- package/dist/esm/pptx/slide-parser.d.ts +4 -2
- package/dist/esm/pptx/slide-parser.js +1 -1
- package/dist/esm/word/doc/doc-reader.d.ts +4 -0
- package/dist/esm/word/doc/doc-reader.js +421 -0
- package/dist/esm/word/doc/doc-text.d.ts +79 -0
- package/dist/esm/word/doc/doc-text.js +706 -0
- package/package.json +1 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
//#region src/excel/header-footer.ts
|
|
2
|
+
function buildHeaderFooterContent(formatString, sheetName) {
|
|
3
|
+
const regions = parseHeaderFooterString(formatString, sheetName);
|
|
4
|
+
const out = [];
|
|
5
|
+
const para = (runs, alignment) => {
|
|
6
|
+
if (runs.length > 0) out.push({
|
|
7
|
+
kind: "paragraph",
|
|
8
|
+
paragraph: {
|
|
9
|
+
properties: { alignment },
|
|
10
|
+
runs: [...runs]
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
para(regions.left, "left");
|
|
15
|
+
para(regions.center, "center");
|
|
16
|
+
para(regions.right, "right");
|
|
17
|
+
return out;
|
|
18
|
+
}
|
|
19
|
+
function parseHeaderFooterString(s, sheetName) {
|
|
20
|
+
const regions = {
|
|
21
|
+
left: [],
|
|
22
|
+
center: [],
|
|
23
|
+
right: []
|
|
24
|
+
};
|
|
25
|
+
let current = regions.center;
|
|
26
|
+
let bold = false;
|
|
27
|
+
let italic = false;
|
|
28
|
+
let buf = "";
|
|
29
|
+
const runProps = () => ({
|
|
30
|
+
...bold ? { bold: true } : {},
|
|
31
|
+
...italic ? { italic: true } : {}
|
|
32
|
+
});
|
|
33
|
+
const flush = () => {
|
|
34
|
+
if (buf.length > 0) {
|
|
35
|
+
current.push({
|
|
36
|
+
text: buf,
|
|
37
|
+
properties: runProps()
|
|
38
|
+
});
|
|
39
|
+
buf = "";
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const pushField = (field) => {
|
|
43
|
+
flush();
|
|
44
|
+
current.push({
|
|
45
|
+
text: "1",
|
|
46
|
+
properties: runProps(),
|
|
47
|
+
field
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
let i = 0;
|
|
51
|
+
while (i < s.length) {
|
|
52
|
+
const ch = s[i];
|
|
53
|
+
if (ch !== "&") {
|
|
54
|
+
buf += ch;
|
|
55
|
+
i++;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const next = s[i + 1];
|
|
59
|
+
if (next === void 0) {
|
|
60
|
+
buf += "&";
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
if (next === "&") {
|
|
64
|
+
buf += "&";
|
|
65
|
+
i += 2;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (next === "L" || next === "C" || next === "R") {
|
|
69
|
+
flush();
|
|
70
|
+
current = next === "L" ? regions.left : next === "R" ? regions.right : regions.center;
|
|
71
|
+
i += 2;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (next === "P") {
|
|
75
|
+
pushField("PAGE");
|
|
76
|
+
i += 2;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (next === "N") {
|
|
80
|
+
pushField("NUMPAGES");
|
|
81
|
+
i += 2;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (next === "A") {
|
|
85
|
+
buf += sheetName;
|
|
86
|
+
i += 2;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (next === "B") {
|
|
90
|
+
flush();
|
|
91
|
+
bold = !bold;
|
|
92
|
+
i += 2;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (next === "I") {
|
|
96
|
+
flush();
|
|
97
|
+
italic = !italic;
|
|
98
|
+
i += 2;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (next === "K") {
|
|
102
|
+
i += 2;
|
|
103
|
+
let n = 0;
|
|
104
|
+
while (n < 6 && i < s.length && /[0-9A-Fa-f]/.test(s[i])) {
|
|
105
|
+
i++;
|
|
106
|
+
n++;
|
|
107
|
+
}
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (next === "\"") {
|
|
111
|
+
i += 2;
|
|
112
|
+
while (i < s.length && s[i] !== "\"") i++;
|
|
113
|
+
if (i < s.length) i++;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (next >= "0" && next <= "9") {
|
|
117
|
+
i += 1;
|
|
118
|
+
while (i < s.length && s[i] >= "0" && s[i] <= "9") i++;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
i += 2;
|
|
122
|
+
}
|
|
123
|
+
flush();
|
|
124
|
+
return regions;
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
export { buildHeaderFooterContent };
|
|
@@ -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, DataValidation, DataValidationType, ExcelTable, MergedRange, ParsedWorksheet, RowHeight, WorksheetCell, XlsxPageMargins, XlsxPageSetup, XlsxPrintOptions, } from '../core/spreadsheet-model/index.js';
|
|
10
|
+
export type { CellType, ColumnWidth, DataValidation, DataValidationType, HeaderFooter, HyperlinkRef, ExcelTable, MergedRange, ParsedWorksheet, RowHeight, SheetRichRun, 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';
|
|
@@ -1 +1,3 @@
|
|
|
1
1
|
export declare function applyNumberFormat(rawValue: string, numFmtId: number, customFormats: ReadonlyMap<number, string>, date1904?: boolean): string;
|
|
2
|
+
export declare function excelSerialToDate(serial: number, date1904: boolean): Date;
|
|
3
|
+
export declare function excelSerialFromUtcParts(year: number, month0: number, day: number, date1904: boolean): number;
|
|
@@ -46,6 +46,10 @@ function excelSerialToDate(serial, date1904) {
|
|
|
46
46
|
if (date1904) return new Date(Date.UTC(1904, 0, 1) + ms);
|
|
47
47
|
return new Date(Date.UTC(1899, 11, 30) + ms);
|
|
48
48
|
}
|
|
49
|
+
function excelSerialFromUtcParts(year, month0, day, date1904) {
|
|
50
|
+
const epoch = date1904 ? Date.UTC(1904, 0, 1) : Date.UTC(1899, 11, 30);
|
|
51
|
+
return Math.round((Date.UTC(year, month0, day) - epoch) / 864e5);
|
|
52
|
+
}
|
|
49
53
|
var MONTH_ABBR = [
|
|
50
54
|
"Jan",
|
|
51
55
|
"Feb",
|
|
@@ -435,4 +439,4 @@ function unquoteLiteral(s) {
|
|
|
435
439
|
return out;
|
|
436
440
|
}
|
|
437
441
|
//#endregion
|
|
438
|
-
export { applyNumberFormat };
|
|
442
|
+
export { applyNumberFormat, excelSerialFromUtcParts, excelSerialToDate };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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';
|
|
2
|
+
import { CellRange, DefinedName, ParsedWorksheet, SheetRichRun, WorksheetCell, XlsxStyles } from './index.js';
|
|
3
|
+
import { SheetHyperlink, SheetSlicer } from '../core/ir/sheet.js';
|
|
4
4
|
export declare const TWIPS_PER_EXCEL_CHAR = 105;
|
|
5
5
|
export declare const DEFAULT_COL_TWIPS = 960;
|
|
6
6
|
export declare const DEFAULT_ROW_TWIPS = 300;
|
|
@@ -18,6 +18,11 @@ interface PrintModelOptions {
|
|
|
18
18
|
readonly endRow: number;
|
|
19
19
|
};
|
|
20
20
|
readonly sheetGrids?: ReadonlyMap<string, ParsedWorksheet>;
|
|
21
|
+
readonly sheetName?: string;
|
|
22
|
+
readonly definedNames?: ReadonlyArray<DefinedName>;
|
|
23
|
+
readonly hyperlinks?: ReadonlyArray<SheetHyperlink>;
|
|
24
|
+
readonly sharedStringRuns?: ReadonlyArray<ReadonlyArray<SheetRichRun> | undefined>;
|
|
25
|
+
readonly now?: Date;
|
|
21
26
|
}
|
|
22
27
|
export declare function worksheetToBody(worksheet: ParsedWorksheet, sharedStrings: ReadonlyArray<string>, styles: XlsxStyles, date1904: boolean, print: PrintModelOptions): Array<BodyElement>;
|
|
23
28
|
export declare function resolveCellText(cell: WorksheetCell, sharedStrings: ReadonlyArray<string>, styles: XlsxStyles, date1904: boolean): string;
|
|
@@ -192,7 +192,7 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
192
192
|
}
|
|
193
193
|
return props;
|
|
194
194
|
};
|
|
195
|
-
const cfFormatter = buildConditionalFormatter(worksheet.conditionalFormats, styles, worksheet.cells);
|
|
195
|
+
const cfFormatter = buildConditionalFormatter(worksheet.conditionalFormats, styles, worksheet.cells, (cell) => resolveCellText(cell, sharedStrings, styles, date1904), date1904, print.now, print.sheetGrids, print.sheetName, print.definedNames);
|
|
196
196
|
const sparklineByCell = buildSparklineLookup(worksheet, print);
|
|
197
197
|
const tableFormatByCell = buildTableFormatLookup(worksheet);
|
|
198
198
|
const dropdownRanges = listDropdownRanges(worksheet.dataValidations);
|
|
@@ -210,6 +210,7 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
210
210
|
}
|
|
211
211
|
const ws = cellMatrix[r]?.[c];
|
|
212
212
|
let text = ws ? resolveCellText(ws, sharedStrings, styles, date1904) : "";
|
|
213
|
+
const cfText = text.length > 0 ? text : void 0;
|
|
213
214
|
if (text.length > textBudget) text = text.slice(0, Math.max(0, textBudget));
|
|
214
215
|
textBudget -= text.length;
|
|
215
216
|
const xf = ws && ws.styleIndex !== void 0 ? styles.cellXfs[ws.styleIndex] : void 0;
|
|
@@ -227,7 +228,7 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
227
228
|
let icon;
|
|
228
229
|
const sparkline = sparklineByCell.get(key(absR, absC));
|
|
229
230
|
if (cfFormatter && ws) {
|
|
230
|
-
const over = cfFormatter(absR, absC, ws.type === "n" && Number.isFinite(Number(ws.rawValue)) ? Number(ws.rawValue) : void 0);
|
|
231
|
+
const over = cfFormatter(absR, absC, ws.type === "n" && Number.isFinite(Number(ws.rawValue)) ? Number(ws.rawValue) : void 0, cfText);
|
|
231
232
|
if (over) {
|
|
232
233
|
if (over.fillHex) shading = { colorHex: over.fillHex };
|
|
233
234
|
if (over.dataBar) dataBar = over.dataBar;
|
|
@@ -235,7 +236,11 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
235
236
|
runProps = applyCfOverride(runProps, over);
|
|
236
237
|
}
|
|
237
238
|
}
|
|
238
|
-
|
|
239
|
+
const wrapText = xf?.alignment?.wrapText === true;
|
|
240
|
+
const rotation = xf?.alignment?.textRotation;
|
|
241
|
+
const rotated = rotation !== void 0 && rotation !== 0 && text.length > 0;
|
|
242
|
+
const shrinkToFit = xf?.alignment?.shrinkToFit === true && !wrapText && !rotated;
|
|
243
|
+
if (text.length > 0 && !merge && !wrapText && !rotated && !shrinkToFit && ws && (ws.type === "s" || ws.type === "str" || ws.type === "inlineStr") && (alignment === void 0 || alignment === "left")) {
|
|
239
244
|
let availTwips = columnWidths[c];
|
|
240
245
|
let cc = c + 1;
|
|
241
246
|
while (cc < colCount && !cellHasContent(cellMatrix[r]?.[cc])) {
|
|
@@ -247,7 +252,19 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
247
252
|
if (text.length > charsFit) text = text.slice(0, charsFit);
|
|
248
253
|
}
|
|
249
254
|
}
|
|
255
|
+
if (shrinkToFit && ws && text.length > 0) {
|
|
256
|
+
const charsFit = Math.max(1, columnWidths[c] / 105);
|
|
257
|
+
if (text.length > charsFit) {
|
|
258
|
+
const baseHalfPt = (styles.fonts[xf.fontId]?.sizePt ?? 11) * 2;
|
|
259
|
+
const scaledHalfPt = Math.max(2, Math.round(baseHalfPt * charsFit / text.length));
|
|
260
|
+
runProps = {
|
|
261
|
+
...runProps,
|
|
262
|
+
fontSizePt: halfPtToPt(scaledHalfPt)
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
}
|
|
250
266
|
const dropdown = dropdownRanges.length > 0 && rangesCover(dropdownRanges, absR, absC);
|
|
267
|
+
const href = print.hyperlinks && print.hyperlinks.length > 0 ? hyperlinkUrlAt(print.hyperlinks, absR, absC) : void 0;
|
|
251
268
|
const visibleEndCol = merge ? Math.min(merge.endColumn, colWindowEnd) : 0;
|
|
252
269
|
const properties = {
|
|
253
270
|
...merge && visibleEndCol > merge.startColumn ? { colSpan: visibleEndCol - merge.startColumn + 1 } : {},
|
|
@@ -259,19 +276,32 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
259
276
|
...borders ? { borders } : {},
|
|
260
277
|
...dropdown ? { dropdown: true } : {}
|
|
261
278
|
};
|
|
262
|
-
const
|
|
279
|
+
const indentLevels = xf?.alignment?.indent ?? 0;
|
|
280
|
+
const baseParaProps = cellParaProps(alignment);
|
|
281
|
+
const paragraphProps = indentLevels > 0 ? {
|
|
282
|
+
...baseParaProps,
|
|
283
|
+
indentLeft: twipsToPt(indentLevels * 3 * 105)
|
|
284
|
+
} : baseParaProps;
|
|
285
|
+
const richRuns = ws && ws.type === "s" && print.sharedStringRuns ? print.sharedStringRuns[Number(ws.rawValue)] : void 0;
|
|
286
|
+
const cellRuns = richRuns && richRuns.length > 0 ? richRuns.map((rr) => ({
|
|
287
|
+
text: rr.text,
|
|
288
|
+
properties: richRunProps(runProps, rr),
|
|
289
|
+
...href ? { href } : {}
|
|
290
|
+
})) : text.length > 0 ? [{
|
|
291
|
+
text,
|
|
292
|
+
properties: runProps,
|
|
293
|
+
...href ? { href } : {}
|
|
294
|
+
}] : [];
|
|
295
|
+
const content = rotated ? stackedVerticalContent(text, runProps, href) : [{
|
|
296
|
+
kind: "paragraph",
|
|
297
|
+
paragraph: {
|
|
298
|
+
properties: paragraphProps,
|
|
299
|
+
runs: cellRuns
|
|
300
|
+
}
|
|
301
|
+
}];
|
|
263
302
|
cells.push({
|
|
264
303
|
properties,
|
|
265
|
-
content
|
|
266
|
-
kind: "paragraph",
|
|
267
|
-
paragraph: {
|
|
268
|
-
properties: paragraphProps,
|
|
269
|
-
runs: text.length > 0 ? [{
|
|
270
|
-
text,
|
|
271
|
-
properties: runProps
|
|
272
|
-
}] : []
|
|
273
|
-
}
|
|
274
|
-
}]
|
|
304
|
+
content
|
|
275
305
|
});
|
|
276
306
|
}
|
|
277
307
|
const baseRowProps = rowHeightMap.get(r);
|
|
@@ -377,6 +407,31 @@ function runPropsFromXf(xf, styles) {
|
|
|
377
407
|
if (font.colorHex) props.colorHex = font.colorHex;
|
|
378
408
|
return props;
|
|
379
409
|
}
|
|
410
|
+
function stackedVerticalContent(text, runProps, href) {
|
|
411
|
+
const out = [];
|
|
412
|
+
for (const ch of text) out.push({
|
|
413
|
+
kind: "paragraph",
|
|
414
|
+
paragraph: {
|
|
415
|
+
properties: { alignment: "center" },
|
|
416
|
+
runs: [{
|
|
417
|
+
text: ch,
|
|
418
|
+
properties: runProps,
|
|
419
|
+
...href ? { href } : {}
|
|
420
|
+
}]
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
return out;
|
|
424
|
+
}
|
|
425
|
+
function richRunProps(base, rr) {
|
|
426
|
+
const out = { ...base };
|
|
427
|
+
if (rr.bold) out.bold = true;
|
|
428
|
+
if (rr.italic) out.italic = true;
|
|
429
|
+
if (rr.underline) out.underline = "single";
|
|
430
|
+
if (rr.colorHex) out.colorHex = rr.colorHex;
|
|
431
|
+
if (rr.sizePt !== void 0) out.fontSizePt = halfPtToPt(Math.round(rr.sizePt * 2));
|
|
432
|
+
if (rr.vertAlign) out.verticalAlign = rr.vertAlign;
|
|
433
|
+
return out;
|
|
434
|
+
}
|
|
380
435
|
function applyCfOverride(base, o) {
|
|
381
436
|
return {
|
|
382
437
|
...base,
|
|
@@ -398,14 +453,55 @@ function mapAlignment(h) {
|
|
|
398
453
|
if (h === "justify") return "both";
|
|
399
454
|
if (h === "distributed") return "distribute";
|
|
400
455
|
}
|
|
456
|
+
var PATTERN_DENSITY = {
|
|
457
|
+
darkGray: .75,
|
|
458
|
+
mediumGray: .5,
|
|
459
|
+
lightGray: .25,
|
|
460
|
+
gray125: .125,
|
|
461
|
+
gray0625: .0625,
|
|
462
|
+
darkHorizontal: .5,
|
|
463
|
+
darkVertical: .5,
|
|
464
|
+
darkDown: .5,
|
|
465
|
+
darkUp: .5,
|
|
466
|
+
darkGrid: .62,
|
|
467
|
+
darkTrellis: .75,
|
|
468
|
+
lightHorizontal: .25,
|
|
469
|
+
lightVertical: .25,
|
|
470
|
+
lightDown: .25,
|
|
471
|
+
lightUp: .25,
|
|
472
|
+
lightGrid: .37,
|
|
473
|
+
lightTrellis: .5
|
|
474
|
+
};
|
|
401
475
|
function shadingFromXf(xf, styles) {
|
|
402
476
|
if (xf.applyFill === false) return void 0;
|
|
403
477
|
if (xf.fillId === 0 || xf.fillId === 1) {
|
|
404
478
|
if (!xf.applyFill) return void 0;
|
|
405
479
|
}
|
|
406
480
|
const fill = styles.fills[xf.fillId];
|
|
407
|
-
if (!fill
|
|
408
|
-
|
|
481
|
+
if (!fill) return void 0;
|
|
482
|
+
const pattern = fill.patternType;
|
|
483
|
+
if (!pattern || pattern === "none") return void 0;
|
|
484
|
+
if (pattern === "solid") return fill.fgColorHex ? { colorHex: fill.fgColorHex } : void 0;
|
|
485
|
+
const density = PATTERN_DENSITY[pattern];
|
|
486
|
+
if (density === void 0 || !fill.fgColorHex) return void 0;
|
|
487
|
+
const blended = blendHex(fill.fgColorHex, fill.bgColorHex ?? "FFFFFF", density);
|
|
488
|
+
return blended ? { colorHex: blended } : void 0;
|
|
489
|
+
}
|
|
490
|
+
function blendHex(fg, bg, fraction) {
|
|
491
|
+
const a = hexToRgb(fg);
|
|
492
|
+
const b = hexToRgb(bg);
|
|
493
|
+
if (!a || !b) return void 0;
|
|
494
|
+
const mix = (x, y) => Math.max(0, Math.min(255, Math.round(x * fraction + y * (1 - fraction)))).toString(16).padStart(2, "0").toUpperCase();
|
|
495
|
+
return `${mix(a[0], b[0])}${mix(a[1], b[1])}${mix(a[2], b[2])}`;
|
|
496
|
+
}
|
|
497
|
+
function hexToRgb(hex) {
|
|
498
|
+
const h = hex.length === 8 ? hex.slice(2) : hex;
|
|
499
|
+
if (!/^[0-9A-Fa-f]{6}$/.test(h)) return void 0;
|
|
500
|
+
return [
|
|
501
|
+
parseInt(h.slice(0, 2), 16),
|
|
502
|
+
parseInt(h.slice(2, 4), 16),
|
|
503
|
+
parseInt(h.slice(4, 6), 16)
|
|
504
|
+
];
|
|
409
505
|
}
|
|
410
506
|
function bordersFromXf(xf, styles) {
|
|
411
507
|
if (xf.applyBorder === false) return void 0;
|
|
@@ -421,6 +517,11 @@ function bordersFromXf(xf, styles) {
|
|
|
421
517
|
if (right) out.right = right;
|
|
422
518
|
if (bottom) out.bottom = bottom;
|
|
423
519
|
if (left) out.left = left;
|
|
520
|
+
const diagonal = border.diagonal ? mapBorderEdge(border.diagonal) : void 0;
|
|
521
|
+
if (diagonal) {
|
|
522
|
+
if (border.diagonalDown) out.diagonalDown = diagonal;
|
|
523
|
+
if (border.diagonalUp) out.diagonalUp = diagonal;
|
|
524
|
+
}
|
|
424
525
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
425
526
|
}
|
|
426
527
|
function mapBorderEdge(edge) {
|
|
@@ -490,6 +591,12 @@ function rangesCover(ranges, row, col) {
|
|
|
490
591
|
for (const r of ranges) if (row >= r.startRow && row <= r.endRow && col >= r.startColumn && col <= r.endColumn) return true;
|
|
491
592
|
return false;
|
|
492
593
|
}
|
|
594
|
+
function hyperlinkUrlAt(links, row, col) {
|
|
595
|
+
for (const l of links) {
|
|
596
|
+
const r = l.ref;
|
|
597
|
+
if (row >= r.startRow && row <= r.endRow && col >= r.startColumn && col <= r.endColumn) return l.url;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
493
600
|
function buildSparklineLookup(worksheet, print) {
|
|
494
601
|
const out = /* @__PURE__ */ new Map();
|
|
495
602
|
for (const sp of worksheet.sparklines ?? []) {
|
|
@@ -1 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { SheetRichRun } from '../core/spreadsheet-model/index.js';
|
|
2
|
+
export interface SharedStrings {
|
|
3
|
+
readonly texts: ReadonlyArray<string>;
|
|
4
|
+
readonly runs: ReadonlyArray<ReadonlyArray<SheetRichRun> | undefined>;
|
|
5
|
+
}
|
|
6
|
+
export declare function parseSharedStrings(data: Uint8Array): SharedStrings;
|
|
@@ -17,22 +17,101 @@ function capLen(s) {
|
|
|
17
17
|
function parseSharedStrings(data) {
|
|
18
18
|
const xml = decoder.decode(data);
|
|
19
19
|
const sst = parser.parse(xml)["sst"];
|
|
20
|
-
if (!sst || typeof sst !== "object") return
|
|
20
|
+
if (!sst || typeof sst !== "object") return {
|
|
21
|
+
texts: [],
|
|
22
|
+
runs: []
|
|
23
|
+
};
|
|
21
24
|
const siRaw = sst["si"];
|
|
22
|
-
|
|
25
|
+
const items = Array.isArray(siRaw) ? siRaw : siRaw !== void 0 ? [siRaw] : [];
|
|
26
|
+
const texts = [];
|
|
27
|
+
const runs = [];
|
|
28
|
+
for (const item of items) {
|
|
29
|
+
const parsed = extractSi(item);
|
|
30
|
+
texts.push(capLen(parsed.text));
|
|
31
|
+
runs.push(parsed.runs);
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
texts,
|
|
35
|
+
runs
|
|
36
|
+
};
|
|
23
37
|
}
|
|
24
|
-
function
|
|
25
|
-
if (typeof si === "string") return
|
|
26
|
-
|
|
27
|
-
|
|
38
|
+
function extractSi(si) {
|
|
39
|
+
if (typeof si === "string") return {
|
|
40
|
+
text: si,
|
|
41
|
+
runs: void 0
|
|
42
|
+
};
|
|
43
|
+
if (typeof si === "number") return {
|
|
44
|
+
text: String(si),
|
|
45
|
+
runs: void 0
|
|
46
|
+
};
|
|
47
|
+
if (!si || typeof si !== "object") return {
|
|
48
|
+
text: "",
|
|
49
|
+
runs: void 0
|
|
50
|
+
};
|
|
28
51
|
const obj = si;
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
52
|
+
const direct = textOf(obj["t"]);
|
|
53
|
+
if (direct) return {
|
|
54
|
+
text: direct,
|
|
55
|
+
runs: void 0
|
|
56
|
+
};
|
|
32
57
|
const r = obj["r"];
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
58
|
+
const rs = Array.isArray(r) ? r : r && typeof r === "object" ? [r] : [];
|
|
59
|
+
if (rs.length === 0) return {
|
|
60
|
+
text: "",
|
|
61
|
+
runs: void 0
|
|
62
|
+
};
|
|
63
|
+
const runs = [];
|
|
64
|
+
let anyFormatting = false;
|
|
65
|
+
for (const rr of rs) {
|
|
66
|
+
const ro = rr;
|
|
67
|
+
const text = textOf(ro?.["t"]);
|
|
68
|
+
if (text.length === 0) continue;
|
|
69
|
+
const run = richRun(text, ro?.["rPr"]);
|
|
70
|
+
if (Object.keys(run).length > 1) anyFormatting = true;
|
|
71
|
+
runs.push(run);
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
text: runs.map((x) => x.text).join(""),
|
|
75
|
+
runs: anyFormatting && runs.length > 0 ? runs : void 0
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function richRun(text, rPr) {
|
|
79
|
+
const p = rPr && typeof rPr === "object" ? rPr : void 0;
|
|
80
|
+
if (!p) return { text };
|
|
81
|
+
const out = { text };
|
|
82
|
+
if (has(p, "b")) out.bold = true;
|
|
83
|
+
if (has(p, "i")) out.italic = true;
|
|
84
|
+
if (has(p, "u")) out.underline = true;
|
|
85
|
+
const color = colorRgb(p["color"]);
|
|
86
|
+
if (color) out.colorHex = color;
|
|
87
|
+
const sz = attrNum(p["sz"], "val");
|
|
88
|
+
if (sz !== void 0) out.sizePt = sz;
|
|
89
|
+
const vert = attrStr(p["vertAlign"], "val");
|
|
90
|
+
if (vert === "superscript" || vert === "subscript") out.vertAlign = vert;
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
function has(p, key) {
|
|
94
|
+
if (!(key in p)) return false;
|
|
95
|
+
const node = p[key];
|
|
96
|
+
const val = attrStr(node, "val");
|
|
97
|
+
return val !== "0" && val !== "false";
|
|
98
|
+
}
|
|
99
|
+
function attrStr(node, key) {
|
|
100
|
+
if (!node || typeof node !== "object") return void 0;
|
|
101
|
+
const v = node[`@_${key}`];
|
|
102
|
+
return typeof v === "string" ? v : void 0;
|
|
103
|
+
}
|
|
104
|
+
function attrNum(node, key) {
|
|
105
|
+
const s = attrStr(node, key);
|
|
106
|
+
if (s === void 0) return void 0;
|
|
107
|
+
const n = Number(s);
|
|
108
|
+
return Number.isFinite(n) ? n : void 0;
|
|
109
|
+
}
|
|
110
|
+
function colorRgb(node) {
|
|
111
|
+
const rgb = attrStr(node, "rgb");
|
|
112
|
+
if (!rgb) return void 0;
|
|
113
|
+
const hex = rgb.length === 8 ? rgb.slice(2) : rgb;
|
|
114
|
+
return /^[0-9A-Fa-f]{6}$/.test(hex) ? hex.toUpperCase() : void 0;
|
|
36
115
|
}
|
|
37
116
|
function textOf(node) {
|
|
38
117
|
if (typeof node === "string") return node;
|
|
@@ -6,4 +6,16 @@ export interface SheetChartRef {
|
|
|
6
6
|
readonly heightPt: number;
|
|
7
7
|
readonly anchorRow: number;
|
|
8
8
|
}
|
|
9
|
-
export
|
|
9
|
+
export interface SheetPicture {
|
|
10
|
+
readonly imagePartPath: string;
|
|
11
|
+
readonly widthPt: number;
|
|
12
|
+
readonly heightPt: number;
|
|
13
|
+
readonly anchorRow: number;
|
|
14
|
+
}
|
|
15
|
+
export interface SheetDrawing {
|
|
16
|
+
readonly charts: Array<SheetChartRef>;
|
|
17
|
+
readonly pictures: Array<SheetPicture>;
|
|
18
|
+
}
|
|
19
|
+
export declare function parseSheetDrawing(drawingXml: Uint8Array, drawingPartPath: string, pkg: OpcPackage, worksheet: ParsedWorksheet): SheetDrawing;
|
|
20
|
+
export declare function makeColWidthPt(ws: ParsedWorksheet): (col: number) => number;
|
|
21
|
+
export declare function makeRowHeightPt(ws: ParsedWorksheet): (row: number) => number;
|
|
@@ -12,12 +12,20 @@ var parser = new XMLParser({
|
|
|
12
12
|
var TWIPS_PER_PT = 20;
|
|
13
13
|
function parseSheetDrawing(drawingXml, drawingPartPath, pkg, worksheet) {
|
|
14
14
|
const root = parser.parse(new TextDecoder().decode(drawingXml))["wsDr"];
|
|
15
|
-
if (!root || typeof root !== "object") return
|
|
15
|
+
if (!root || typeof root !== "object") return {
|
|
16
|
+
charts: [],
|
|
17
|
+
pictures: []
|
|
18
|
+
};
|
|
16
19
|
const rootObj = root;
|
|
17
20
|
const colWidthPt = makeColWidthPt(worksheet);
|
|
18
21
|
const rowHeightPt = makeRowHeightPt(worksheet);
|
|
19
22
|
const rels = pkg.getPartRelationships(drawingPartPath);
|
|
20
|
-
const
|
|
23
|
+
const partPathOf = (relId) => {
|
|
24
|
+
const rel = rels.find((r) => r.id === relId);
|
|
25
|
+
return rel ? pkg.resolveRelatedPart(drawingPartPath, rel)?.path : void 0;
|
|
26
|
+
};
|
|
27
|
+
const charts = [];
|
|
28
|
+
const pictures = [];
|
|
21
29
|
for (const kind of [
|
|
22
30
|
"twoCellAnchor",
|
|
23
31
|
"oneCellAnchor",
|
|
@@ -26,10 +34,8 @@ function parseSheetDrawing(drawingXml, drawingPartPath, pkg, worksheet) {
|
|
|
26
34
|
if (!anchor || typeof anchor !== "object") continue;
|
|
27
35
|
const a = anchor;
|
|
28
36
|
const chartRelId = chartRelIdOf(a);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const resolved = rel ? pkg.resolveRelatedPart(drawingPartPath, rel) : void 0;
|
|
32
|
-
if (!resolved) continue;
|
|
37
|
+
const picRelId = chartRelId ? void 0 : picRelIdOf(a);
|
|
38
|
+
if (!chartRelId && !picRelId) continue;
|
|
33
39
|
const from = cellMarker(a["from"]);
|
|
34
40
|
let widthPt = 0;
|
|
35
41
|
let heightPt = 0;
|
|
@@ -46,14 +52,41 @@ function parseSheetDrawing(drawingXml, drawingPartPath, pkg, worksheet) {
|
|
|
46
52
|
heightPt = emuToPt(num(e["@_cy"]) ?? 0);
|
|
47
53
|
}
|
|
48
54
|
if (widthPt <= 0 || heightPt <= 0) continue;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
const anchorRow = from?.row ?? 0;
|
|
56
|
+
if (chartRelId) {
|
|
57
|
+
const path = partPathOf(chartRelId);
|
|
58
|
+
if (path) charts.push({
|
|
59
|
+
chartPartPath: path,
|
|
60
|
+
widthPt,
|
|
61
|
+
heightPt,
|
|
62
|
+
anchorRow
|
|
63
|
+
});
|
|
64
|
+
} else if (picRelId) {
|
|
65
|
+
const path = partPathOf(picRelId);
|
|
66
|
+
if (path) pictures.push({
|
|
67
|
+
imagePartPath: path,
|
|
68
|
+
widthPt,
|
|
69
|
+
heightPt,
|
|
70
|
+
anchorRow
|
|
71
|
+
});
|
|
72
|
+
}
|
|
55
73
|
}
|
|
56
|
-
|
|
74
|
+
charts.sort((x, y) => x.anchorRow - y.anchorRow);
|
|
75
|
+
pictures.sort((x, y) => x.anchorRow - y.anchorRow);
|
|
76
|
+
return {
|
|
77
|
+
charts,
|
|
78
|
+
pictures
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function picRelIdOf(anchor) {
|
|
82
|
+
const pic = anchor["pic"];
|
|
83
|
+
if (!pic || typeof pic !== "object") return void 0;
|
|
84
|
+
const blipFill = pic["blipFill"];
|
|
85
|
+
if (!blipFill || typeof blipFill !== "object") return void 0;
|
|
86
|
+
const blip = blipFill["blip"];
|
|
87
|
+
if (!blip || typeof blip !== "object") return void 0;
|
|
88
|
+
const embed = blip["@_embed"];
|
|
89
|
+
return typeof embed === "string" && embed !== "" ? embed : void 0;
|
|
57
90
|
}
|
|
58
91
|
function chartRelIdOf(anchor) {
|
|
59
92
|
const frame = anchor["graphicFrame"];
|
|
@@ -110,4 +143,4 @@ function asArray(v) {
|
|
|
110
143
|
return Array.isArray(v) ? v : v !== void 0 ? [v] : [];
|
|
111
144
|
}
|
|
112
145
|
//#endregion
|
|
113
|
-
export { parseSheetDrawing };
|
|
146
|
+
export { makeColWidthPt, makeRowHeightPt, parseSheetDrawing };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ShapeBlock } from '../core/document-model/index.js';
|
|
2
|
+
import { ColorResolver } from '../core/drawingml/colors.js';
|
|
3
|
+
import { ParsedWorksheet } from '../core/spreadsheet-model/index.js';
|
|
4
|
+
export declare function parseSheetShapes(drawingXml: Uint8Array, worksheet: ParsedWorksheet, colors: ColorResolver): Array<ShapeBlock>;
|