@shbernal/ts-xlsx 1.2.0 → 2.0.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 +5 -0
- package/dist/core/address.d.ts +49 -2
- package/dist/core/address.js +31 -3
- package/dist/core/autofilter.d.ts +2 -2
- package/dist/core/cell.d.ts +17 -16
- package/dist/core/cell.js +3 -7
- package/dist/core/color-resolution.d.ts +7 -7
- package/dist/core/column.d.ts +8 -9
- package/dist/core/column.js +2 -4
- package/dist/core/comment-thread.d.ts +32 -23
- package/dist/core/comment-thread.js +4 -4
- package/dist/core/conditional-formatting-overlay.d.ts +1 -1
- package/dist/core/conditional-formatting.d.ts +3 -3
- package/dist/core/data-validation-overlay.d.ts +1 -1
- package/dist/core/data-validation.d.ts +3 -3
- package/dist/core/date.d.ts +3 -3
- package/dist/core/formula.d.ts +6 -6
- package/dist/core/grid-edits.js +3 -3
- package/dist/core/image.d.ts +37 -2
- package/dist/core/image.js +6 -0
- package/dist/core/internal.d.ts +9 -1
- package/dist/core/limits.d.ts +4 -4
- package/dist/core/merge.d.ts +6 -12
- package/dist/core/merge.js +0 -3
- package/dist/core/page-setup.d.ts +4 -4
- package/dist/core/pivot-table.d.ts +2 -4
- package/dist/core/pivot-table.js +5 -5
- package/dist/core/preserved.d.ts +3 -3
- package/dist/core/protection.d.ts +4 -4
- package/dist/core/range.d.ts +16 -14
- package/dist/core/range.js +5 -5
- package/dist/core/row-input.d.ts +2 -8
- package/dist/core/row-input.js +2 -2
- package/dist/core/row.d.ts +7 -8
- package/dist/core/row.js +2 -4
- package/dist/core/style.d.ts +14 -14
- package/dist/core/table-style.d.ts +9 -9
- package/dist/core/table-style.js +1 -1
- package/dist/core/table.d.ts +30 -42
- package/dist/core/table.js +16 -10
- package/dist/core/theme.d.ts +13 -43
- package/dist/core/theme.js +2 -148
- package/dist/core/value.d.ts +7 -7
- package/dist/core/workbook-protection.d.ts +2 -2
- package/dist/core/workbook-styles.d.ts +26 -0
- package/dist/core/workbook-styles.js +48 -0
- package/dist/core/workbook-theme.d.ts +25 -0
- package/dist/core/workbook-theme.js +49 -0
- package/dist/core/workbook-vba.d.ts +17 -0
- package/dist/core/workbook-vba.js +79 -0
- package/dist/core/workbook.d.ts +141 -83
- package/dist/core/workbook.js +74 -133
- package/dist/core/worksheet-comments.d.ts +9 -0
- package/dist/core/worksheet-comments.js +52 -0
- package/dist/core/worksheet-model.d.ts +4 -4
- package/dist/core/worksheet-model.js +1 -0
- package/dist/core/worksheet-pictures.d.ts +29 -0
- package/dist/core/worksheet-pictures.js +42 -0
- package/dist/core/worksheet.d.ts +94 -77
- package/dist/core/worksheet.js +36 -95
- package/dist/customui/errors.d.ts +1 -1
- package/dist/customui/ribbon.d.ts +3 -3
- package/dist/entries/core.d.ts +4 -4
- package/dist/entries/core.js +1 -1
- package/dist/entries/vba.d.ts +1 -1
- package/dist/entries/vba.js +1 -1
- package/dist/entries/xlsx.d.ts +1 -0
- package/dist/entries/xlsx.js +1 -0
- package/dist/errors.d.ts +12 -12
- package/dist/io/csv/read.js +1 -2
- package/dist/io/csv/write.d.ts +8 -3
- package/dist/io/csv/write.js +17 -2
- package/dist/io/opc/errors.d.ts +6 -6
- package/dist/io/opc/inflate.d.ts +1 -1
- package/dist/io/opc/namespaces.d.ts +1 -1
- package/dist/io/opc/read-opc.d.ts +19 -3
- package/dist/io/opc/read-opc.js +14 -8
- package/dist/io/opc/read-options.d.ts +2 -2
- package/dist/io/opc/sniff-format.d.ts +2 -2
- package/dist/io/opc/zip-mtime.d.ts +5 -0
- package/dist/io/opc/zip-mtime.js +1 -0
- package/dist/io/style/xf-style.d.ts +38 -6
- package/dist/io/style/xf-style.js +22 -0
- package/dist/io/xlsb/errors.d.ts +1 -1
- package/dist/io/xlsb/formula.d.ts +4 -4
- package/dist/io/xlsb/primitives.d.ts +8 -8
- package/dist/io/xlsb/ptg-functions.d.ts +1 -1
- package/dist/io/xlsb/read-styles.js +2 -20
- package/dist/io/xlsb/read.d.ts +2 -2
- package/dist/io/xlsx/cell-accumulator.d.ts +25 -6
- package/dist/io/xlsx/cell-accumulator.js +111 -30
- package/dist/io/xlsx/cell-value.d.ts +2 -2
- package/dist/io/xlsx/cell-value.js +3 -3
- package/dist/io/xlsx/color-xml.js +11 -17
- package/dist/io/xlsx/comments.d.ts +5 -5
- package/dist/io/xlsx/comments.js +13 -6
- package/dist/io/xlsx/conditional-formatting.d.ts +3 -3
- package/dist/io/xlsx/conditional-formatting.js +7 -16
- package/dist/io/xlsx/data-validation.d.ts +2 -2
- package/dist/io/xlsx/data-validation.js +1 -1
- package/dist/io/xlsx/edit-vba.js +2 -1
- package/dist/io/xlsx/errors.d.ts +3 -3
- package/dist/io/xlsx/hyperlinks.d.ts +4 -2
- package/dist/io/xlsx/hyperlinks.js +5 -5
- package/dist/io/xlsx/images.d.ts +1 -1
- package/dist/io/xlsx/images.js +8 -8
- package/dist/io/xlsx/namespaces.d.ts +2 -2
- package/dist/io/xlsx/package-plan.js +5 -2
- package/dist/io/xlsx/read-pivot.js +2 -5
- package/dist/io/xlsx/read-rows.d.ts +13 -13
- package/dist/io/xlsx/read-rows.js +19 -55
- package/dist/io/xlsx/read-shared-strings.js +7 -5
- package/dist/io/xlsx/read-styles.d.ts +3 -3
- package/dist/io/xlsx/read-styles.js +40 -65
- package/dist/io/xlsx/read-worksheet.js +67 -115
- package/dist/io/xlsx/read.d.ts +3 -5
- package/dist/io/xlsx/read.js +94 -71
- package/dist/io/xlsx/rich-runs.d.ts +1 -1
- package/dist/io/xlsx/rich-runs.js +1 -1
- package/dist/io/xlsx/rich-text.d.ts +1 -1
- package/dist/io/xlsx/shared-strings.d.ts +2 -2
- package/dist/io/xlsx/sheet-properties.js +5 -4
- package/dist/io/xlsx/styles.d.ts +8 -9
- package/dist/io/xlsx/styles.js +4 -3
- package/dist/io/xlsx/tables.d.ts +2 -2
- package/dist/io/xlsx/tables.js +8 -13
- package/dist/io/xlsx/theme-xml.d.ts +37 -0
- package/dist/io/xlsx/theme-xml.js +142 -0
- package/dist/io/xlsx/threaded-comments.d.ts +18 -27
- package/dist/io/xlsx/threaded-comments.js +9 -21
- package/dist/io/xlsx/workbook-xml.d.ts +1 -1
- package/dist/io/xlsx/workbook-xml.js +6 -2
- package/dist/io/xlsx/worksheet-xml.d.ts +2 -2
- package/dist/io/xlsx/worksheet-xml.js +7 -12
- package/dist/io/xlsx/write-stream.d.ts +15 -15
- package/dist/io/xlsx/write-stream.js +5 -3
- package/dist/io/xlsx/write.d.ts +12 -7
- package/dist/io/xlsx/write.js +10 -6
- package/dist/io/xlsx/x14-ext.d.ts +1 -1
- package/dist/vba/bytes.d.ts +12 -0
- package/dist/vba/bytes.js +40 -0
- package/dist/vba/cfb-writer.d.ts +1 -1
- package/dist/vba/cfb.d.ts +1 -1
- package/dist/vba/cfb.js +15 -51
- package/dist/vba/codepage.d.ts +2 -2
- package/dist/vba/errors.d.ts +2 -2
- package/dist/vba/index.d.ts +2 -2
- package/dist/vba/index.js +2 -2
- package/dist/vba/ms-ovba.d.ts +1 -1
- package/dist/vba/ms-ovba.js +1 -3
- package/dist/vba/project-editor.d.ts +9 -9
- package/dist/vba/project-editor.js +2 -11
- package/dist/vba/project.d.ts +5 -5
- package/dist/vba/project.js +1 -10
- package/dist/vba/vba-encoding.d.ts +1 -1
- package/dist/xml/errors.d.ts +1 -1
- package/dist/xml/xml-read.d.ts +38 -9
- package/dist/xml/xml-read.js +23 -0
- package/dist/xml/xml.d.ts +31 -9
- package/dist/xml/xml.js +23 -3
- package/package.json +41 -35
package/dist/io/xlsx/read.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { decodeRange } from '../../core/address.js';
|
|
2
2
|
import { unmangleFunctions } from '../../core/formula.js';
|
|
3
3
|
import { INTERNAL } from '../../core/internal.js';
|
|
4
|
-
import { Workbook } from '../../core/workbook.js';
|
|
5
4
|
import { WORKBOOK_PROTECTION_CREDENTIAL_ATTRS, } from '../../core/workbook-protection.js';
|
|
6
|
-
import {
|
|
5
|
+
import { Workbook } from '../../core/workbook.js';
|
|
6
|
+
import { boolStrict, localName, numInteger, openElements, parseXml } from '../../xml/xml-read.js';
|
|
7
7
|
import { UnsupportedFormatError } from '../opc/errors.js';
|
|
8
|
-
import { extensionOf
|
|
9
|
-
import { capturePartClosure, contentTypeResolver, packageAccessors, parseRelationshipRecords, parseRelationships,
|
|
8
|
+
import { extensionOf } from '../opc/part-paths.js';
|
|
9
|
+
import { capturePartClosure, contentTypeResolver, packageAccessors, parseRelationshipRecords, parseRelationships, readPartRelationships, relationshipTargetByType, resolveRelativePart, resolveWorkbookPart, } from '../opc/read-opc.js';
|
|
10
10
|
import { DEFAULT_MAX_UNCOMPRESSED } from '../opc/read-options.js';
|
|
11
11
|
import { inflateSpreadsheetPackage } from '../opc/sniff-format.js';
|
|
12
12
|
import { readXlsbPackage, XLSB_WORKBOOK_PART } from '../xlsb/read.js';
|
|
@@ -20,6 +20,7 @@ import { parseSharedStrings } from './read-shared-strings.js';
|
|
|
20
20
|
import { parseIndexedColors, parseMruColors, parseStyleTable, parseTableStyles, } from './read-styles.js';
|
|
21
21
|
import { parseWorksheet } from './read-worksheet.js';
|
|
22
22
|
import { parseTable } from './tables.js';
|
|
23
|
+
import { parseThemeColorScheme, parseThemeFontScheme } from './theme-xml.js';
|
|
23
24
|
import { buildCommentThreads, parsePersons, parseThreadedComments } from './threaded-comments.js';
|
|
24
25
|
export { parseRelationships, resolveWorkbookPart } from '../opc/read-opc.js';
|
|
25
26
|
export { DEFAULT_MAX_UNCOMPRESSED } from '../opc/read-options.js';
|
|
@@ -53,6 +54,9 @@ export function readXlsx(data, options = {}) {
|
|
|
53
54
|
const core = partText('docProps/core.xml');
|
|
54
55
|
if (core !== undefined)
|
|
55
56
|
applyCoreProperties(workbook, core);
|
|
57
|
+
const app = partText('docProps/app.xml');
|
|
58
|
+
if (app !== undefined)
|
|
59
|
+
applyAppProperties(workbook, app);
|
|
56
60
|
workbook.protection = parseWorkbookProtection(workbookXml);
|
|
57
61
|
applyWorkbookView(workbook.view, workbookXml);
|
|
58
62
|
readWorkbookPersons(workbookRelsXml, pkg, workbook);
|
|
@@ -67,9 +71,9 @@ export function readXlsx(data, options = {}) {
|
|
|
67
71
|
if (sheetXml !== undefined)
|
|
68
72
|
parseWorksheet(sheetXml, sheet, sharedStrings, xfStyles);
|
|
69
73
|
if (path !== undefined) {
|
|
74
|
+
const sheetRels = readPartRelationships(path, partText);
|
|
70
75
|
if (sheetXml !== undefined) {
|
|
71
|
-
|
|
72
|
-
applyHyperlinks(sheet, parseSheetHyperlinks(sheetXml), sheetRels);
|
|
76
|
+
applyHyperlinks(sheet, parseSheetHyperlinks(sheetXml), (id) => sheetRels.byId(id)?.target);
|
|
73
77
|
applyDataValidations(sheet, [
|
|
74
78
|
...parseDataValidations(sheetXml),
|
|
75
79
|
...parseExtendedDataValidations(sheetXml),
|
|
@@ -77,20 +81,20 @@ export function readXlsx(data, options = {}) {
|
|
|
77
81
|
for (const cf of parseConditionalFormattings(sheetXml))
|
|
78
82
|
sheet.addConditionalFormatting(cf);
|
|
79
83
|
}
|
|
80
|
-
const threads = readSheetCommentThreads(
|
|
84
|
+
const threads = readSheetCommentThreads(sheetRels, pkg, workbook);
|
|
81
85
|
if (threads.length > 0)
|
|
82
86
|
sheet[INTERNAL].restoreCommentThreads(threads);
|
|
83
|
-
const comments = readSheetComments(
|
|
87
|
+
const comments = readSheetComments(sheetRels, pkg);
|
|
84
88
|
if (comments !== undefined)
|
|
85
89
|
applyNotes(sheet, comments);
|
|
86
|
-
readSheetImages(
|
|
87
|
-
readSheetBackground(
|
|
90
|
+
readSheetImages(sheetRels, pkg, workbook, sheet, imageIdByMediaPath);
|
|
91
|
+
readSheetBackground(sheetRels, pkg, workbook, sheet, imageIdByMediaPath);
|
|
88
92
|
if (sheetXml !== undefined) {
|
|
89
|
-
readSheetPreservedReferences(
|
|
93
|
+
readSheetPreservedReferences(sheetRels, sheetXml, pkg, contentTypeOf, sheet);
|
|
90
94
|
}
|
|
91
|
-
readSheetTables(
|
|
92
|
-
readSheetPivotTables(
|
|
93
|
-
const printerSettings = readSheetPrinterSettings(
|
|
95
|
+
readSheetTables(sheetRels, pkg, sheet);
|
|
96
|
+
readSheetPivotTables(sheetRels, pkg, sheet);
|
|
97
|
+
const printerSettings = readSheetPrinterSettings(sheetRels, pkg);
|
|
94
98
|
if (printerSettings !== undefined)
|
|
95
99
|
sheet.pageSetup.printerSettings = printerSettings;
|
|
96
100
|
}
|
|
@@ -102,8 +106,8 @@ export function readXlsx(data, options = {}) {
|
|
|
102
106
|
}
|
|
103
107
|
return workbook;
|
|
104
108
|
}
|
|
105
|
-
function readSheetComments(
|
|
106
|
-
const commentsPath =
|
|
109
|
+
function readSheetComments(sheetRels, pkg) {
|
|
110
|
+
const commentsPath = sheetRels.targetPath('comments');
|
|
107
111
|
if (commentsPath === undefined)
|
|
108
112
|
return undefined;
|
|
109
113
|
const commentsXml = pkg.partText(commentsPath);
|
|
@@ -123,23 +127,25 @@ function readWorkbookTheme(workbookRelsXml, pkg, contentTypeOf, workbook) {
|
|
|
123
127
|
return;
|
|
124
128
|
const entryPath = resolveWorkbookPart(target);
|
|
125
129
|
const parts = capturePartClosure(entryPath, pkg.partText, pkg.partBytes, contentTypeOf);
|
|
126
|
-
if (parts
|
|
127
|
-
|
|
130
|
+
if (parts === undefined)
|
|
131
|
+
return;
|
|
132
|
+
const xml = pkg.partText(entryPath) ?? '';
|
|
133
|
+
workbook[INTERNAL].restoreThemePart({ entryPath, parts }, { colors: parseThemeColorScheme(xml), fonts: parseThemeFontScheme(xml) });
|
|
128
134
|
}
|
|
129
|
-
function readSheetCommentThreads(
|
|
130
|
-
const path =
|
|
135
|
+
function readSheetCommentThreads(sheetRels, pkg, workbook) {
|
|
136
|
+
const path = sheetRels.targetPath('threadedComment');
|
|
131
137
|
const xml = path === undefined ? undefined : pkg.partText(path);
|
|
132
138
|
if (xml === undefined)
|
|
133
139
|
return [];
|
|
134
140
|
return buildCommentThreads(parseThreadedComments(xml), (id) => workbook.getPerson(id));
|
|
135
141
|
}
|
|
136
|
-
function readSheetPrinterSettings(
|
|
137
|
-
const path =
|
|
142
|
+
function readSheetPrinterSettings(sheetRels, pkg) {
|
|
143
|
+
const path = sheetRels.targetPath('printerSettings');
|
|
138
144
|
return path === undefined ? undefined : pkg.partBytes(path);
|
|
139
145
|
}
|
|
140
|
-
function readSheetImages(
|
|
146
|
+
function readSheetImages(sheetRels, pkg, workbook, sheet, imageIdByMediaPath) {
|
|
141
147
|
const { partText, partBytes } = pkg;
|
|
142
|
-
const drawingPath =
|
|
148
|
+
const drawingPath = sheetRels.targetPath('drawing');
|
|
143
149
|
if (drawingPath === undefined)
|
|
144
150
|
return;
|
|
145
151
|
const drawingXml = partText(drawingPath);
|
|
@@ -147,12 +153,12 @@ function readSheetImages(sheetPath, pkg, workbook, sheet, imageIdByMediaPath) {
|
|
|
147
153
|
return;
|
|
148
154
|
if (drawingHasUnmodeledContent(drawingXml))
|
|
149
155
|
return;
|
|
150
|
-
const drawingRels =
|
|
156
|
+
const drawingRels = readPartRelationships(drawingPath, partText);
|
|
151
157
|
for (const anchor of parseDrawing(drawingXml)) {
|
|
152
|
-
const
|
|
153
|
-
if (
|
|
158
|
+
const embedded = drawingRels.byId(anchor.embed);
|
|
159
|
+
if (embedded === undefined)
|
|
154
160
|
continue;
|
|
155
|
-
const mediaPath =
|
|
161
|
+
const mediaPath = drawingRels.pathOf(embedded.target);
|
|
156
162
|
let id = imageIdByMediaPath.get(mediaPath);
|
|
157
163
|
if (id === undefined) {
|
|
158
164
|
const bytes = partBytes(mediaPath);
|
|
@@ -171,8 +177,8 @@ function readSheetImages(sheetPath, pkg, workbook, sheet, imageIdByMediaPath) {
|
|
|
171
177
|
}
|
|
172
178
|
}
|
|
173
179
|
}
|
|
174
|
-
function readSheetBackground(
|
|
175
|
-
const mediaPath =
|
|
180
|
+
function readSheetBackground(sheetRels, pkg, workbook, sheet, imageIdByMediaPath) {
|
|
181
|
+
const mediaPath = sheetRels.targetPath('image');
|
|
176
182
|
if (mediaPath === undefined)
|
|
177
183
|
return;
|
|
178
184
|
let id = imageIdByMediaPath.get(mediaPath);
|
|
@@ -185,15 +191,10 @@ function readSheetBackground(sheetPath, pkg, workbook, sheet, imageIdByMediaPath
|
|
|
185
191
|
}
|
|
186
192
|
sheet.addBackgroundImage(id);
|
|
187
193
|
}
|
|
188
|
-
function readSheetPreservedReferences(
|
|
194
|
+
function readSheetPreservedReferences(sheetRels, sheetXml, pkg, contentTypeOf, sheet) {
|
|
189
195
|
const { partText, partBytes } = pkg;
|
|
190
|
-
const relsXml = partText(relsPathFor(sheetPath));
|
|
191
|
-
if (relsXml === undefined)
|
|
192
|
-
return;
|
|
193
|
-
const records = parseRelationshipRecords(relsXml);
|
|
194
|
-
const recordById = new Map(records.map((record) => [record.id, record]));
|
|
195
196
|
const capture = (element, relType, target) => {
|
|
196
|
-
const entryPath =
|
|
197
|
+
const entryPath = sheetRels.pathOf(target);
|
|
197
198
|
const parts = capturePartClosure(entryPath, partText, partBytes, contentTypeOf);
|
|
198
199
|
if (parts !== undefined)
|
|
199
200
|
sheet[INTERNAL].addPreservedReference({ element, relType, entryPath, parts });
|
|
@@ -201,11 +202,11 @@ function readSheetPreservedReferences(sheetPath, sheetXml, pkg, contentTypeOf, s
|
|
|
201
202
|
const referenceElements = sheet.images.length === 0 ? ['drawing', 'legacyDrawingHF'] : ['legacyDrawingHF'];
|
|
202
203
|
for (const element of referenceElements) {
|
|
203
204
|
const relId = worksheetReferenceRelId(sheetXml, element);
|
|
204
|
-
const record = relId === undefined ? undefined :
|
|
205
|
+
const record = relId === undefined ? undefined : sheetRels.byId(relId);
|
|
205
206
|
if (record !== undefined && !record.external)
|
|
206
207
|
capture(element, record.type, record.target);
|
|
207
208
|
}
|
|
208
|
-
for (const record of records) {
|
|
209
|
+
for (const record of sheetRels.records) {
|
|
209
210
|
if (record.external)
|
|
210
211
|
continue;
|
|
211
212
|
if (isPreservedSheetRelType(record.type))
|
|
@@ -291,12 +292,9 @@ function worksheetReferenceRelId(sheetXml, element) {
|
|
|
291
292
|
}
|
|
292
293
|
return undefined;
|
|
293
294
|
}
|
|
294
|
-
function readSheetTables(
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
return;
|
|
298
|
-
for (const target of relationshipTargetsByType(relsXml, 'table')) {
|
|
299
|
-
const tableXml = pkg.partText(resolveRelativePart(sheetPath, target));
|
|
295
|
+
function readSheetTables(sheetRels, pkg, sheet) {
|
|
296
|
+
for (const tablePath of sheetRels.targetPaths('table')) {
|
|
297
|
+
const tableXml = pkg.partText(tablePath);
|
|
300
298
|
if (tableXml === undefined)
|
|
301
299
|
continue;
|
|
302
300
|
const options = parseTable(tableXml);
|
|
@@ -305,20 +303,14 @@ function readSheetTables(sheetPath, pkg, sheet) {
|
|
|
305
303
|
}
|
|
306
304
|
dropMergesInsideTables(sheet);
|
|
307
305
|
}
|
|
308
|
-
function readSheetPivotTables(
|
|
306
|
+
function readSheetPivotTables(sheetRels, pkg, sheet) {
|
|
309
307
|
const { partText } = pkg;
|
|
310
|
-
const
|
|
311
|
-
if (relsXml === undefined)
|
|
312
|
-
return;
|
|
313
|
-
for (const target of relationshipTargetsByType(relsXml, 'pivotTable')) {
|
|
314
|
-
const tablePath = resolveRelativePart(sheetPath, target);
|
|
308
|
+
for (const tablePath of sheetRels.targetPaths('pivotTable')) {
|
|
315
309
|
const tableXml = partText(tablePath);
|
|
316
310
|
if (tableXml === undefined)
|
|
317
311
|
continue;
|
|
318
|
-
const
|
|
319
|
-
const cacheXml =
|
|
320
|
-
? ''
|
|
321
|
-
: (partText(resolveRelativePart(tablePath, cacheTarget)) ?? '');
|
|
312
|
+
const cachePath = readPartRelationships(tablePath, partText).targetPath('pivotCacheDefinition');
|
|
313
|
+
const cacheXml = cachePath === undefined ? '' : (partText(cachePath) ?? '');
|
|
322
314
|
sheet[INTERNAL].addLoadedPivotTable(parsePivotTable(tableXml, cacheXml));
|
|
323
315
|
}
|
|
324
316
|
}
|
|
@@ -351,7 +343,7 @@ export function parseWorkbookSheets(xml) {
|
|
|
351
343
|
}
|
|
352
344
|
return sheets;
|
|
353
345
|
}
|
|
354
|
-
|
|
346
|
+
function parseWorkbookProtection(xml) {
|
|
355
347
|
let result;
|
|
356
348
|
parseXml(xml, {
|
|
357
349
|
onOpen(name, attrs) {
|
|
@@ -379,11 +371,21 @@ export function parseWorkbookProtection(xml) {
|
|
|
379
371
|
}
|
|
380
372
|
export function applyWorkbookView(view, xml) {
|
|
381
373
|
for (const { attrs } of openElements(xml, 'workbookView')) {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
374
|
+
const x = numInteger(attrs.xWindow);
|
|
375
|
+
if (x !== undefined)
|
|
376
|
+
view.x = x;
|
|
377
|
+
const y = numInteger(attrs.yWindow);
|
|
378
|
+
if (y !== undefined)
|
|
379
|
+
view.y = y;
|
|
380
|
+
const width = numInteger(attrs.windowWidth, 0);
|
|
381
|
+
if (width !== undefined)
|
|
382
|
+
view.width = width;
|
|
383
|
+
const height = numInteger(attrs.windowHeight, 0);
|
|
384
|
+
if (height !== undefined)
|
|
385
|
+
view.height = height;
|
|
386
|
+
const activeTab = numInteger(attrs.activeTab, 0);
|
|
387
|
+
if (activeTab !== undefined)
|
|
388
|
+
view.activeTab = activeTab;
|
|
387
389
|
if (attrs.visibility === 'hidden' || attrs.visibility === 'veryHidden') {
|
|
388
390
|
view.visibility = attrs.visibility;
|
|
389
391
|
}
|
|
@@ -392,13 +394,6 @@ export function applyWorkbookView(view, xml) {
|
|
|
392
394
|
return;
|
|
393
395
|
}
|
|
394
396
|
}
|
|
395
|
-
function applyViewNumber(raw, assign) {
|
|
396
|
-
if (raw === undefined)
|
|
397
|
-
return;
|
|
398
|
-
const value = Number(raw);
|
|
399
|
-
if (Number.isFinite(value))
|
|
400
|
-
assign(Math.trunc(value));
|
|
401
|
-
}
|
|
402
397
|
function parseWorkbookDefinedNames(xml, sheetOrder) {
|
|
403
398
|
const names = [];
|
|
404
399
|
let capture = false;
|
|
@@ -412,7 +407,7 @@ function parseWorkbookDefinedNames(xml, sheetOrder) {
|
|
|
412
407
|
return;
|
|
413
408
|
capture = true;
|
|
414
409
|
refersTo = '';
|
|
415
|
-
const scopeIndex = attrs.localSheetId
|
|
410
|
+
const scopeIndex = numInteger(attrs.localSheetId, 0) ?? -1;
|
|
416
411
|
const scope = sheetOrder[scopeIndex];
|
|
417
412
|
pending = { name: attrs.name };
|
|
418
413
|
if (scope !== undefined)
|
|
@@ -436,7 +431,13 @@ function parseWorkbookDefinedNames(xml, sheetOrder) {
|
|
|
436
431
|
});
|
|
437
432
|
return names;
|
|
438
433
|
}
|
|
439
|
-
const CORE_PROPERTY_LOCAL_NAMES = new Set([
|
|
434
|
+
const CORE_PROPERTY_LOCAL_NAMES = new Set([
|
|
435
|
+
'title',
|
|
436
|
+
'creator',
|
|
437
|
+
'lastModifiedBy',
|
|
438
|
+
'created',
|
|
439
|
+
'modified',
|
|
440
|
+
]);
|
|
440
441
|
function applyCoreProperties(workbook, xml) {
|
|
441
442
|
let capture = '';
|
|
442
443
|
let text = '';
|
|
@@ -453,7 +454,9 @@ function applyCoreProperties(workbook, xml) {
|
|
|
453
454
|
onClose(name) {
|
|
454
455
|
if (capture === '' || localName(name) !== capture)
|
|
455
456
|
return;
|
|
456
|
-
if (capture === '
|
|
457
|
+
if (capture === 'title')
|
|
458
|
+
workbook.properties.title = text;
|
|
459
|
+
else if (capture === 'creator')
|
|
457
460
|
workbook.properties.creator = text;
|
|
458
461
|
else if (capture === 'lastModifiedBy')
|
|
459
462
|
workbook.properties.lastModifiedBy = text;
|
|
@@ -470,3 +473,23 @@ function applyCoreProperties(workbook, xml) {
|
|
|
470
473
|
},
|
|
471
474
|
});
|
|
472
475
|
}
|
|
476
|
+
function applyAppProperties(workbook, xml) {
|
|
477
|
+
let capture = false;
|
|
478
|
+
let text = '';
|
|
479
|
+
parseXml(xml, {
|
|
480
|
+
onOpen(name) {
|
|
481
|
+
capture = localName(name) === 'Company';
|
|
482
|
+
text = '';
|
|
483
|
+
},
|
|
484
|
+
onText(chunk) {
|
|
485
|
+
if (capture)
|
|
486
|
+
text += chunk;
|
|
487
|
+
},
|
|
488
|
+
onClose(name) {
|
|
489
|
+
if (!capture || localName(name) !== 'Company')
|
|
490
|
+
return;
|
|
491
|
+
workbook.properties.company = text;
|
|
492
|
+
capture = false;
|
|
493
|
+
},
|
|
494
|
+
});
|
|
495
|
+
}
|
|
@@ -2,7 +2,7 @@ import type { RichTextRun } from '../../core/value.ts';
|
|
|
2
2
|
import type { XmlAttributes } from '../../xml/xml-read.ts';
|
|
3
3
|
export declare class RunAccumulator {
|
|
4
4
|
#private;
|
|
5
|
-
|
|
5
|
+
beginContainer(): void;
|
|
6
6
|
/** The runs gathered so far. */
|
|
7
7
|
get runs(): RichTextRun[];
|
|
8
8
|
beginRun(): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RichTextRun } from '../../core/value.ts';
|
|
2
2
|
/**
|
|
3
3
|
* Serialise a rich-text value's runs as the inner content of an `<is>` element. A zero-length run
|
|
4
|
-
* is dropped: an empty `<t/>` is schema-invalid
|
|
4
|
+
* is dropped: an empty `<t/>` is schema-invalid (Excel flags the file as corrupt) and an empty
|
|
5
5
|
* run contributes nothing to the rendered text, so omitting it is loss-free.
|
|
6
6
|
*/
|
|
7
7
|
export declare function richTextRunsXml(runs: readonly RichTextRun[]): string;
|
|
@@ -3,14 +3,14 @@ import type { RichTextValue } from '../../core/value.ts';
|
|
|
3
3
|
* Interns cell string values into the shared-strings pool. {@link intern} returns the index a
|
|
4
4
|
* `t="s"` cell writes as its `<v>`; identical entries collapse to one, so `count` (total references)
|
|
5
5
|
* and `uniqueCount` (distinct entries) diverge exactly as Excel records them. Each entry is stored as
|
|
6
|
-
* its rendered `<si>` inner XML, which is also its dedup key
|
|
6
|
+
* its rendered `<si>` inner XML, which is also its dedup key: a plain string (`<t>…`) and rich runs
|
|
7
7
|
* (`<r>…`) render to distinct markup, so the two kinds never collide in the pool.
|
|
8
8
|
*/
|
|
9
9
|
export declare class SharedStringTable {
|
|
10
10
|
#private;
|
|
11
11
|
/** Intern a plain or rich string and return its `<si>` index, reusing the entry when it repeats. */
|
|
12
12
|
intern(value: string | RichTextValue): number;
|
|
13
|
-
/** Whether no string has been interned
|
|
13
|
+
/** Whether no string has been interned; the writer omits the part entirely when so. */
|
|
14
14
|
get isEmpty(): boolean;
|
|
15
15
|
/** Serialise the pool as the `xl/sharedStrings.xml` part. */
|
|
16
16
|
toXml(): string;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { encodeAddress } from '../../core/address.js';
|
|
2
2
|
import { SHEET_PROTECTION_FLAGS } from '../../core/protection.js';
|
|
3
|
-
import { attr, boolAttr, escapeAttr,
|
|
3
|
+
import { attr, boolAttr, escapeAttr, escapeSpreadsheetText, numberText } from '../../xml/xml.js';
|
|
4
4
|
import { colorAttrs } from './color-xml.js';
|
|
5
5
|
export function sheetViewsXml(view, active) {
|
|
6
6
|
const selected = active ? ' tabSelected="1"' : '';
|
|
7
|
+
const gridLines = view.showGridLines === false ? ' showGridLines="0"' : '';
|
|
7
8
|
const xSplit = view.xSplit ?? 0;
|
|
8
9
|
const ySplit = view.ySplit ?? 0;
|
|
9
10
|
if (view.state !== 'frozen' || (xSplit === 0 && ySplit === 0)) {
|
|
10
|
-
return `<sheetViews><sheetView${selected} workbookViewId="0"/></sheetViews>`;
|
|
11
|
+
return `<sheetViews><sheetView${gridLines}${selected} workbookViewId="0"/></sheetViews>`;
|
|
11
12
|
}
|
|
12
13
|
const topLeftCell = view.topLeftCell ?? encodeAddress(xSplit + 1, ySplit + 1);
|
|
13
14
|
const activePane = xSplit > 0 && ySplit > 0 ? 'bottomRight' : xSplit > 0 ? 'topRight' : 'bottomLeft';
|
|
@@ -16,7 +17,7 @@ export function sheetViewsXml(view, active) {
|
|
|
16
17
|
(ySplit > 0 ? ` ySplit="${ySplit}"` : '') +
|
|
17
18
|
` topLeftCell="${escapeAttr(topLeftCell)}" activePane="${activePane}" state="frozen"/>`;
|
|
18
19
|
const selection = `<selection pane="${activePane}" activeCell="${escapeAttr(topLeftCell)}" sqref="${escapeAttr(topLeftCell)}"/>`;
|
|
19
|
-
return `<sheetViews><sheetView${selected} workbookViewId="0">${pane}${selection}</sheetView></sheetViews>`;
|
|
20
|
+
return `<sheetViews><sheetView${gridLines}${selected} workbookViewId="0">${pane}${selection}</sheetView></sheetViews>`;
|
|
20
21
|
}
|
|
21
22
|
export function sheetPrXml(sheet) {
|
|
22
23
|
const children = (sheet.tabColor !== undefined ? `<tabColor ${colorAttrs(sheet.tabColor)}/>` : '') +
|
|
@@ -98,7 +99,7 @@ export function headerFooterXml(hf) {
|
|
|
98
99
|
if (differentFirst)
|
|
99
100
|
attrs += ' differentFirst="1"';
|
|
100
101
|
const body = children
|
|
101
|
-
.map(({ tag, key }) => `<${tag}>${
|
|
102
|
+
.map(({ tag, key }) => `<${tag}>${escapeSpreadsheetText(hf[key])}</${tag}>`)
|
|
102
103
|
.join('');
|
|
103
104
|
return `<headerFooter${attrs}>${body}</headerFooter>`;
|
|
104
105
|
}
|
package/dist/io/xlsx/styles.d.ts
CHANGED
|
@@ -8,15 +8,15 @@ export interface CellStyle {
|
|
|
8
8
|
readonly border?: Border | undefined;
|
|
9
9
|
readonly alignment?: Alignment | undefined;
|
|
10
10
|
readonly protection?: Protection | undefined;
|
|
11
|
-
/** The quote-prefix flag
|
|
11
|
+
/** The quote-prefix flag: an attribute on the xf, not a shared sub-table entry. */
|
|
12
12
|
readonly quotePrefix?: boolean | undefined;
|
|
13
|
-
/** The `xfId` link into `cellStyleXfs
|
|
13
|
+
/** The `xfId` link into `cellStyleXfs`: the named cell style this format inherits from (0 = Normal). */
|
|
14
14
|
readonly xfId?: number | undefined;
|
|
15
15
|
}
|
|
16
16
|
/** What a {@link StyleRegistry} needs from its workbook before any style is interned. */
|
|
17
17
|
export interface StyleRegistryOptions {
|
|
18
18
|
/**
|
|
19
|
-
* The font every cell naming none of its own renders in
|
|
19
|
+
* The font every cell naming none of its own renders in, emitted as id 0. Take it from
|
|
20
20
|
* {@link Workbook.defaultFont}, which resolves the authored/declared/theme chain and guarantees a
|
|
21
21
|
* complete entry. Omitted, the registry falls back to the Office default.
|
|
22
22
|
*/
|
|
@@ -28,7 +28,7 @@ export interface StyleRegistryOptions {
|
|
|
28
28
|
*
|
|
29
29
|
* The reader flattens font 0 onto every xf that names it, so a cell that merely inherited the
|
|
30
30
|
* file's default arrives carrying it as a concrete face. That face is an artefact of reading, not
|
|
31
|
-
* an authored intent
|
|
31
|
+
* an authored intent (in the source file the cell said nothing about its font) so it must
|
|
32
32
|
* collapse back to id 0 and follow the new default rather than pin itself to the old one through a
|
|
33
33
|
* custom entry.
|
|
34
34
|
*/
|
|
@@ -59,7 +59,7 @@ export declare class StyleRegistry {
|
|
|
59
59
|
* rule's `dxfId`, and every `<tableStyleElement dxfId="…">` inside a preserved `<tableStyle>` (see
|
|
60
60
|
* {@link seedTableStyles}). Those constructs are carried as opaque XML precisely *because* the
|
|
61
61
|
* indices they name do not move. Renumbering, reordering, or de-duplicating the seeded entries
|
|
62
|
-
* would silently re-point every one of them at a different format
|
|
62
|
+
* would silently re-point every one of them at a different format: a change no schema check and no
|
|
63
63
|
* round-trip of our own can catch, because the file stays perfectly valid and merely renders wrong.
|
|
64
64
|
*/
|
|
65
65
|
seedDifferentialStyles(fragments: readonly string[]): void;
|
|
@@ -88,13 +88,13 @@ export declare class StyleRegistry {
|
|
|
88
88
|
* {@link seedTableStyles}, whose preserved definitions these append after.
|
|
89
89
|
*
|
|
90
90
|
* A definition here **replaces** a preserved one of the same name. Two `<tableStyle>` elements
|
|
91
|
-
* sharing a name is ambiguous
|
|
92
|
-
* happened to index first
|
|
91
|
+
* sharing a name is ambiguous, since a table's `tableStyleInfo/@name` would reach whichever a
|
|
92
|
+
* consumer happened to index first, so authoring a name the source already used is read as overriding it,
|
|
93
93
|
* which is what asking for it means.
|
|
94
94
|
*/
|
|
95
95
|
addTableStyle(style: TableStyle): void;
|
|
96
96
|
/**
|
|
97
|
-
* Intern an authored differential style, returning the `<dxfs>` index that references it
|
|
97
|
+
* Intern an authored differential style, returning the `<dxfs>` index that references it: a
|
|
98
98
|
* conditional-formatting rule's `dxfId`, or a table style element's. Identical styles collapse to
|
|
99
99
|
* one entry, whichever feature asked for them, so a highlight rule and a table style's header row
|
|
100
100
|
* painted the same way share a single `<dxf>`.
|
|
@@ -107,4 +107,3 @@ export declare class StyleRegistry {
|
|
|
107
107
|
toXml(): string;
|
|
108
108
|
}
|
|
109
109
|
export declare function fontXml(font: Font, nameTag?: 'name' | 'rFont'): string;
|
|
110
|
-
export declare function dxfXml(style: DifferentialStyle): string;
|
package/dist/io/xlsx/styles.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isBorderStyle, isFillPatternType, isFontScheme, isFontVerticalAlignment, isHorizontalAlignment, isNamedUnderlineStyle, isVerticalAlignment, } from '../../core/style.js';
|
|
2
2
|
import { TABLE_STYLE_ELEMENT_TYPES } from '../../core/table-style.js';
|
|
3
3
|
import { AuthoringError } from '../../errors.js';
|
|
4
|
-
import { escapeAttr, XML_DECLARATION } from '../../xml/xml.js';
|
|
5
4
|
import { decodeEntities } from '../../xml/xml-read.js';
|
|
5
|
+
import { assertRepresentable, escapeAttr, XML_DECLARATION } from '../../xml/xml.js';
|
|
6
6
|
import { colorAttrs } from './color-xml.js';
|
|
7
7
|
import { MARKUP_COMPATIBILITY_NS, SPREADSHEETML_NS } from './namespaces.js';
|
|
8
8
|
const RESERVED_FILL_COUNT = 2;
|
|
@@ -188,7 +188,7 @@ export class StyleRegistry {
|
|
|
188
188
|
const cellStyleXfs = this.#cellStyleXfs.map((format) => xfXml(format, null)).join('');
|
|
189
189
|
const cellStyles = this.#cellStyleNames.map(cellStyleTag).join('');
|
|
190
190
|
const fontCount = RESERVED_FONT_COUNT + this.#fontXml.length;
|
|
191
|
-
const fonts = `<font>${this.#defaultFontBody}</font
|
|
191
|
+
const fonts = `<font>${this.#defaultFontBody}</font>${this.#fontXml.join('')}`;
|
|
192
192
|
const borderCount = RESERVED_BORDER_COUNT + this.#borderXml.length;
|
|
193
193
|
const borders = DEFAULT_BORDER + this.#borderXml.join('');
|
|
194
194
|
return (XML_DECLARATION +
|
|
@@ -362,7 +362,7 @@ export function fontXml(font, nameTag = 'name') {
|
|
|
362
362
|
parts.push(`<scheme val="${checkedToken(font.scheme, isFontScheme, 'font scheme')}"/>`);
|
|
363
363
|
return parts.join('');
|
|
364
364
|
}
|
|
365
|
-
|
|
365
|
+
function dxfXml(style) {
|
|
366
366
|
const parts = [];
|
|
367
367
|
if (style.font !== undefined) {
|
|
368
368
|
const font = fontXml(style.font);
|
|
@@ -425,6 +425,7 @@ function edgeXml(tag, edge) {
|
|
|
425
425
|
return `<${tag} style="${style}"><color ${colorAttrs(edge.color)}/></${tag}>`;
|
|
426
426
|
}
|
|
427
427
|
function escapeFormatCode(code) {
|
|
428
|
+
assertRepresentable(code);
|
|
428
429
|
return code
|
|
429
430
|
.replace(/&/g, '&')
|
|
430
431
|
.replace(/</g, '<')
|
package/dist/io/xlsx/tables.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { type Table, type TableOptions } from '../../core/table.ts';
|
|
|
2
2
|
export declare function tableXml(table: Table, id: number): string;
|
|
3
3
|
/**
|
|
4
4
|
* Parse a `<table>` part into the options that reconstruct it, or `undefined` when the XML is not a
|
|
5
|
-
* usable table (no name, no ref, or no columns
|
|
6
|
-
* rather than fabricate a degenerate table). Duplicate column names are not resolved here
|
|
5
|
+
* usable table (no name, no ref, or no columns: Excel treats such a part as corrupt, so we drop it
|
|
6
|
+
* rather than fabricate a degenerate table). Duplicate column names are not resolved here, since the
|
|
7
7
|
* {@link Table} constructor disambiguates them, so authoring and loading share one implementation.
|
|
8
8
|
*/
|
|
9
9
|
export declare function parseTable(xml: string): TableOptions | undefined;
|
package/dist/io/xlsx/tables.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { decodeRange, encodeAddress } from '../../core/address.js';
|
|
2
2
|
import { isTotalsRowFunction, } from '../../core/table.js';
|
|
3
|
+
import { boolPresent, localName, numInteger, parseXml } from '../../xml/xml-read.js';
|
|
3
4
|
import { boolAttr, escapeAttr, escapeText, XML_DECLARATION } from '../../xml/xml.js';
|
|
4
|
-
import { localName, parseXml } from '../../xml/xml-read.js';
|
|
5
5
|
import { NS } from './relationships.js';
|
|
6
6
|
export function tableXml(table, id) {
|
|
7
7
|
const name = escapeAttr(table.name);
|
|
@@ -55,9 +55,6 @@ function tableColumnXml(column, id) {
|
|
|
55
55
|
}
|
|
56
56
|
return `<tableColumn ${attrs}/>`;
|
|
57
57
|
}
|
|
58
|
-
function parseOoxmlBool(value) {
|
|
59
|
-
return value !== '0' && value !== 'false';
|
|
60
|
-
}
|
|
61
58
|
export function parseTable(xml) {
|
|
62
59
|
let name;
|
|
63
60
|
let displayName;
|
|
@@ -77,12 +74,10 @@ export function parseTable(xml) {
|
|
|
77
74
|
name = attrs.name ?? attrs.displayName;
|
|
78
75
|
displayName = attrs.displayName ?? attrs.name;
|
|
79
76
|
ref = attrs.ref;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (attrs.totalsRowCount !== undefined)
|
|
83
|
-
totalsRowCount = Number(attrs.totalsRowCount);
|
|
77
|
+
headerRowCount = numInteger(attrs.headerRowCount, 0) ?? headerRowCount;
|
|
78
|
+
totalsRowCount = numInteger(attrs.totalsRowCount, 0) ?? totalsRowCount;
|
|
84
79
|
if (attrs.totalsRowShown !== undefined)
|
|
85
|
-
totalsRowShown =
|
|
80
|
+
totalsRowShown = boolPresent(attrs.totalsRowShown);
|
|
86
81
|
break;
|
|
87
82
|
case 'autoFilter':
|
|
88
83
|
hasAutoFilter = true;
|
|
@@ -92,13 +87,13 @@ export function parseTable(xml) {
|
|
|
92
87
|
if (attrs.name !== undefined)
|
|
93
88
|
captured.name = attrs.name;
|
|
94
89
|
if (attrs.showFirstColumn !== undefined)
|
|
95
|
-
captured.showFirstColumn =
|
|
90
|
+
captured.showFirstColumn = boolPresent(attrs.showFirstColumn);
|
|
96
91
|
if (attrs.showLastColumn !== undefined)
|
|
97
|
-
captured.showLastColumn =
|
|
92
|
+
captured.showLastColumn = boolPresent(attrs.showLastColumn);
|
|
98
93
|
if (attrs.showRowStripes !== undefined)
|
|
99
|
-
captured.showRowStripes =
|
|
94
|
+
captured.showRowStripes = boolPresent(attrs.showRowStripes);
|
|
100
95
|
if (attrs.showColumnStripes !== undefined) {
|
|
101
|
-
captured.showColumnStripes =
|
|
96
|
+
captured.showColumnStripes = boolPresent(attrs.showColumnStripes);
|
|
102
97
|
}
|
|
103
98
|
style = captured;
|
|
104
99
|
break;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ThemeColorScheme, type ThemeFontScheme, type ThemeOverrides } from '../../core/theme.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Extract the colour scheme from a theme part. Returns only the slots the part actually declares in a
|
|
4
|
+
* colour model this reader understands; an unrecognised one is dropped rather than guessed at, so a
|
|
5
|
+
* caller can tell "the theme says nothing here" from "the theme says black".
|
|
6
|
+
*
|
|
7
|
+
* Reads the `<a:clrScheme>` block alone. A theme carries a font scheme and a format scheme too, but
|
|
8
|
+
* neither participates in resolving a colour, and scanning the whole part would let a `<a:srgbClr>`
|
|
9
|
+
* buried in a gradient stop masquerade as a scheme slot.
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseThemeColorScheme(themeXml: string): ThemeColorScheme;
|
|
12
|
+
/** Extract the major/minor latin typefaces from a theme part's `<a:fontScheme>`. */
|
|
13
|
+
export declare function parseThemeFontScheme(themeXml: string): ThemeFontScheme;
|
|
14
|
+
/**
|
|
15
|
+
* Apply authored colour/font overrides to a theme part, returning the new part text.
|
|
16
|
+
*
|
|
17
|
+
* Surgical by design: the base part rides through untouched except for the `<a:clrScheme>` and
|
|
18
|
+
* `<a:fontScheme>` blocks, and within those, only what the caller actually named. The format scheme,
|
|
19
|
+
* the gradients, line styles and effect styles that make a theme look like a theme, is left exactly
|
|
20
|
+
* as it was, because nobody hand-authors `fillStyleLst` gradient stops from a spreadsheet API and
|
|
21
|
+
* regenerating it would replace a designer's work with the Office default.
|
|
22
|
+
*
|
|
23
|
+
* A slot the caller did not override keeps its **verbatim source element**, not a re-serialisation of
|
|
24
|
+
* its value. That matters for `dk1`/`lt1`, which Excel writes as `<a:sysClr val="windowText"
|
|
25
|
+
* lastClr="000000"/>`: rewriting those as `<a:srgbClr>` would pin them to one machine's resolved
|
|
26
|
+
* window colours and break dark-mode following.
|
|
27
|
+
*/
|
|
28
|
+
export declare function applyThemeOverrides(baseXml: string, overrides: ThemeOverrides): string;
|
|
29
|
+
/**
|
|
30
|
+
* The theme part a workbook with no theme of its own ships: the standard Office theme.
|
|
31
|
+
*
|
|
32
|
+
* A spreadsheet must carry one even when nobody configured it: the stylesheet's own default font
|
|
33
|
+
* references `theme="1"`, which a consumer can only resolve against this part, so the two travel
|
|
34
|
+
* together. It is also the base {@link applyThemeOverrides} authors on top of when a workbook was
|
|
35
|
+
* built from scratch rather than read from a file.
|
|
36
|
+
*/
|
|
37
|
+
export declare const DEFAULT_THEME_XML: string;
|