@shbernal/ts-xlsx 1.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/LICENSE +23 -0
- package/README.md +230 -0
- package/dist/core/address.d.ts +49 -0
- package/dist/core/address.js +125 -0
- package/dist/core/autofilter.d.ts +55 -0
- package/dist/core/autofilter.js +48 -0
- package/dist/core/cell.d.ts +132 -0
- package/dist/core/cell.js +249 -0
- package/dist/core/color-resolution.d.ts +58 -0
- package/dist/core/color-resolution.js +170 -0
- package/dist/core/column.d.ts +87 -0
- package/dist/core/column.js +167 -0
- package/dist/core/comment-thread.d.ts +116 -0
- package/dist/core/comment-thread.js +62 -0
- package/dist/core/conditional-formatting-overlay.d.ts +15 -0
- package/dist/core/conditional-formatting-overlay.js +24 -0
- package/dist/core/conditional-formatting.d.ts +70 -0
- package/dist/core/conditional-formatting.js +35 -0
- package/dist/core/containers.d.ts +2 -0
- package/dist/core/containers.js +25 -0
- package/dist/core/data-validation-overlay.d.ts +28 -0
- package/dist/core/data-validation-overlay.js +56 -0
- package/dist/core/data-validation.d.ts +38 -0
- package/dist/core/data-validation.js +13 -0
- package/dist/core/date.d.ts +25 -0
- package/dist/core/date.js +58 -0
- package/dist/core/formula.d.ts +49 -0
- package/dist/core/formula.js +319 -0
- package/dist/core/grid-edits.d.ts +22 -0
- package/dist/core/grid-edits.js +206 -0
- package/dist/core/image.d.ts +76 -0
- package/dist/core/image.js +65 -0
- package/dist/core/internal.d.ts +11 -0
- package/dist/core/internal.js +29 -0
- package/dist/core/merge.d.ts +13 -0
- package/dist/core/merge.js +26 -0
- package/dist/core/modern-functions.d.ts +1 -0
- package/dist/core/modern-functions.js +165 -0
- package/dist/core/page-setup.d.ts +94 -0
- package/dist/core/page-setup.js +6 -0
- package/dist/core/pivot-table.d.ts +113 -0
- package/dist/core/pivot-table.js +249 -0
- package/dist/core/preserved.d.ts +58 -0
- package/dist/core/preserved.js +5 -0
- package/dist/core/protection.d.ts +67 -0
- package/dist/core/protection.js +68 -0
- package/dist/core/range.d.ts +112 -0
- package/dist/core/range.js +283 -0
- package/dist/core/row.d.ts +73 -0
- package/dist/core/row.js +135 -0
- package/dist/core/style.d.ts +246 -0
- package/dist/core/style.js +125 -0
- package/dist/core/table-style.d.ts +67 -0
- package/dist/core/table-style.js +90 -0
- package/dist/core/table.d.ts +194 -0
- package/dist/core/table.js +291 -0
- package/dist/core/theme.d.ts +90 -0
- package/dist/core/theme.js +272 -0
- package/dist/core/value.d.ts +115 -0
- package/dist/core/value.js +144 -0
- package/dist/core/workbook-protection.d.ts +27 -0
- package/dist/core/workbook-protection.js +25 -0
- package/dist/core/workbook.d.ts +528 -0
- package/dist/core/workbook.js +732 -0
- package/dist/core/worksheet-model.d.ts +34 -0
- package/dist/core/worksheet-model.js +100 -0
- package/dist/core/worksheet.d.ts +647 -0
- package/dist/core/worksheet.js +1025 -0
- package/dist/customui/errors.d.ts +15 -0
- package/dist/customui/errors.js +15 -0
- package/dist/customui/index.d.ts +2 -0
- package/dist/customui/index.js +7 -0
- package/dist/customui/ribbon.d.ts +86 -0
- package/dist/customui/ribbon.js +180 -0
- package/dist/entries/core.d.ts +23 -0
- package/dist/entries/core.js +20 -0
- package/dist/entries/csv.d.ts +2 -0
- package/dist/entries/csv.js +6 -0
- package/dist/entries/customui.d.ts +1 -0
- package/dist/entries/customui.js +3 -0
- package/dist/entries/errors.d.ts +7 -0
- package/dist/entries/errors.js +20 -0
- package/dist/entries/vba.d.ts +2 -0
- package/dist/entries/vba.js +7 -0
- package/dist/entries/xlsb.d.ts +1 -0
- package/dist/entries/xlsb.js +7 -0
- package/dist/entries/xlsx.d.ts +5 -0
- package/dist/entries/xlsx.js +18 -0
- package/dist/errors.d.ts +65 -0
- package/dist/errors.js +66 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +19 -0
- package/dist/io/csv/read.d.ts +15 -0
- package/dist/io/csv/read.js +113 -0
- package/dist/io/csv/write.d.ts +28 -0
- package/dist/io/csv/write.js +124 -0
- package/dist/io/opc/errors.d.ts +46 -0
- package/dist/io/opc/errors.js +49 -0
- package/dist/io/opc/inflate.d.ts +15 -0
- package/dist/io/opc/inflate.js +91 -0
- package/dist/io/opc/namespaces.d.ts +18 -0
- package/dist/io/opc/namespaces.js +18 -0
- package/dist/io/opc/part-paths.d.ts +4 -0
- package/dist/io/opc/part-paths.js +35 -0
- package/dist/io/opc/read-opc.d.ts +24 -0
- package/dist/io/opc/read-opc.js +153 -0
- package/dist/io/opc/read-options.d.ts +10 -0
- package/dist/io/opc/read-options.js +7 -0
- package/dist/io/opc/rels.d.ts +15 -0
- package/dist/io/opc/rels.js +28 -0
- package/dist/io/opc/sniff-format.d.ts +27 -0
- package/dist/io/opc/sniff-format.js +92 -0
- package/dist/io/style/xf-style.d.ts +47 -0
- package/dist/io/style/xf-style.js +95 -0
- package/dist/io/xlsb/errors.d.ts +15 -0
- package/dist/io/xlsb/errors.js +15 -0
- package/dist/io/xlsb/formula.d.ts +48 -0
- package/dist/io/xlsb/formula.js +398 -0
- package/dist/io/xlsb/primitives.d.ts +86 -0
- package/dist/io/xlsb/primitives.js +230 -0
- package/dist/io/xlsb/ptg-functions.d.ts +16 -0
- package/dist/io/xlsb/ptg-functions.js +659 -0
- package/dist/io/xlsb/read-shared-strings.d.ts +2 -0
- package/dist/io/xlsb/read-shared-strings.js +22 -0
- package/dist/io/xlsb/read-styles.d.ts +4 -0
- package/dist/io/xlsb/read-styles.js +386 -0
- package/dist/io/xlsb/read-worksheet.d.ts +9 -0
- package/dist/io/xlsb/read-worksheet.js +301 -0
- package/dist/io/xlsb/read.d.ts +20 -0
- package/dist/io/xlsb/read.js +199 -0
- package/dist/io/xlsb/record-stream.d.ts +14 -0
- package/dist/io/xlsb/record-stream.js +56 -0
- package/dist/io/xlsb/record-types.d.ts +55 -0
- package/dist/io/xlsb/record-types.js +73 -0
- package/dist/io/xlsx/cell-accumulator.d.ts +25 -0
- package/dist/io/xlsx/cell-accumulator.js +172 -0
- package/dist/io/xlsx/cell-value.d.ts +32 -0
- package/dist/io/xlsx/cell-value.js +85 -0
- package/dist/io/xlsx/comments.d.ts +74 -0
- package/dist/io/xlsx/comments.js +243 -0
- package/dist/io/xlsx/conditional-formatting.d.ts +32 -0
- package/dist/io/xlsx/conditional-formatting.js +464 -0
- package/dist/io/xlsx/data-validation.d.ts +20 -0
- package/dist/io/xlsx/data-validation.js +258 -0
- package/dist/io/xlsx/edit-vba.d.ts +23 -0
- package/dist/io/xlsx/edit-vba.js +139 -0
- package/dist/io/xlsx/errors.d.ts +17 -0
- package/dist/io/xlsx/errors.js +17 -0
- package/dist/io/xlsx/hyperlinks.d.ts +42 -0
- package/dist/io/xlsx/hyperlinks.js +139 -0
- package/dist/io/xlsx/images.d.ts +34 -0
- package/dist/io/xlsx/images.js +218 -0
- package/dist/io/xlsx/namespaces.d.ts +55 -0
- package/dist/io/xlsx/namespaces.js +55 -0
- package/dist/io/xlsx/package-plan.d.ts +103 -0
- package/dist/io/xlsx/package-plan.js +168 -0
- package/dist/io/xlsx/pivot-read.d.ts +5 -0
- package/dist/io/xlsx/pivot-read.js +134 -0
- package/dist/io/xlsx/pivot.d.ts +12 -0
- package/dist/io/xlsx/pivot.js +141 -0
- package/dist/io/xlsx/read-rows.d.ts +85 -0
- package/dist/io/xlsx/read-rows.js +286 -0
- package/dist/io/xlsx/read-styles.d.ts +8 -0
- package/dist/io/xlsx/read-styles.js +551 -0
- package/dist/io/xlsx/read-worksheet.d.ts +4 -0
- package/dist/io/xlsx/read-worksheet.js +528 -0
- package/dist/io/xlsx/read.d.ts +32 -0
- package/dist/io/xlsx/read.js +680 -0
- package/dist/io/xlsx/relationships.d.ts +33 -0
- package/dist/io/xlsx/relationships.js +47 -0
- package/dist/io/xlsx/rich-runs.d.ts +13 -0
- package/dist/io/xlsx/rich-runs.js +59 -0
- package/dist/io/xlsx/rich-text.d.ts +7 -0
- package/dist/io/xlsx/rich-text.js +23 -0
- package/dist/io/xlsx/shared-formulas.d.ts +6 -0
- package/dist/io/xlsx/shared-formulas.js +52 -0
- package/dist/io/xlsx/shared-strings-read.d.ts +2 -0
- package/dist/io/xlsx/shared-strings-read.js +70 -0
- package/dist/io/xlsx/shared-strings.d.ts +17 -0
- package/dist/io/xlsx/shared-strings.js +50 -0
- package/dist/io/xlsx/sheet-properties.d.ts +13 -0
- package/dist/io/xlsx/sheet-properties.js +211 -0
- package/dist/io/xlsx/styles.d.ts +138 -0
- package/dist/io/xlsx/styles.js +821 -0
- package/dist/io/xlsx/tables.d.ts +9 -0
- package/dist/io/xlsx/tables.js +208 -0
- package/dist/io/xlsx/threaded-comments.d.ts +102 -0
- package/dist/io/xlsx/threaded-comments.js +308 -0
- package/dist/io/xlsx/workbook-xml.d.ts +12 -0
- package/dist/io/xlsx/workbook-xml.js +353 -0
- package/dist/io/xlsx/worksheet-xml.d.ts +86 -0
- package/dist/io/xlsx/worksheet-xml.js +643 -0
- package/dist/io/xlsx/write-stream.d.ts +171 -0
- package/dist/io/xlsx/write-stream.js +399 -0
- package/dist/io/xlsx/write.d.ts +81 -0
- package/dist/io/xlsx/write.js +396 -0
- package/dist/io/xlsx/x14-ext.d.ts +9 -0
- package/dist/io/xlsx/x14-ext.js +12 -0
- package/dist/vba/cfb-writer.d.ts +19 -0
- package/dist/vba/cfb-writer.js +277 -0
- package/dist/vba/cfb.d.ts +16 -0
- package/dist/vba/cfb.js +324 -0
- package/dist/vba/codepage.d.ts +18 -0
- package/dist/vba/codepage.js +87 -0
- package/dist/vba/errors.d.ts +24 -0
- package/dist/vba/errors.js +24 -0
- package/dist/vba/index.d.ts +5 -0
- package/dist/vba/index.js +15 -0
- package/dist/vba/ms-ovba.d.ts +12 -0
- package/dist/vba/ms-ovba.js +176 -0
- package/dist/vba/project-editor.d.ts +62 -0
- package/dist/vba/project-editor.js +377 -0
- package/dist/vba/project.d.ts +45 -0
- package/dist/vba/project.js +160 -0
- package/dist/vba/vba-encoding.d.ts +14 -0
- package/dist/vba/vba-encoding.js +39 -0
- package/dist/xml/errors.d.ts +15 -0
- package/dist/xml/errors.js +15 -0
- package/dist/xml/xml-read.d.ts +107 -0
- package/dist/xml/xml-read.js +283 -0
- package/dist/xml/xml.d.ts +41 -0
- package/dist/xml/xml.js +86 -0
- package/package.json +117 -0
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
// Workbook-level serialisation: the package's `[Content_Types].xml`, its root and workbook `.rels`
|
|
2
|
+
// parts, `xl/workbook.xml` (sheets, defined names, calc/protection settings, pivot-cache and slicer
|
|
3
|
+
// registrations), and the `docProps` core/app property parts.
|
|
4
|
+
import { mangleFormula, quoteSheetName } from "../../core/formula.js";
|
|
5
|
+
import { WORKBOOK_PROTECTION_CREDENTIAL_ATTRS } from "../../core/workbook-protection.js";
|
|
6
|
+
import { escapeAttr, escapeText, XML_DECLARATION } from "../../xml/xml.js";
|
|
7
|
+
import { extensionOf, relativePartPath, THEME_PART_PATH } from "../opc/part-paths.js";
|
|
8
|
+
import { relationship, relationshipsPart } from "../opc/rels.js";
|
|
9
|
+
import { imageContentType } from "./images.js";
|
|
10
|
+
import { SLICER_CACHES_EXT_URI } from "./namespaces.js";
|
|
11
|
+
import { NS, REL } from "./relationships.js";
|
|
12
|
+
import { x14Ext } from "./x14-ext.js";
|
|
13
|
+
const CT = {
|
|
14
|
+
workbook: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml',
|
|
15
|
+
macroEnabledWorkbook: 'application/vnd.ms-excel.sheet.macroEnabled.main+xml',
|
|
16
|
+
worksheet: 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml',
|
|
17
|
+
styles: 'application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml',
|
|
18
|
+
theme: 'application/vnd.openxmlformats-officedocument.theme+xml',
|
|
19
|
+
core: 'application/vnd.openxmlformats-package.core-properties+xml',
|
|
20
|
+
app: 'application/vnd.openxmlformats-officedocument.extended-properties+xml',
|
|
21
|
+
table: 'application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml',
|
|
22
|
+
comments: 'application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml',
|
|
23
|
+
vml: 'application/vnd.openxmlformats-officedocument.vmlDrawing',
|
|
24
|
+
drawing: 'application/vnd.openxmlformats-officedocument.drawing+xml',
|
|
25
|
+
printerSettings: 'application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings',
|
|
26
|
+
sharedStrings: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml',
|
|
27
|
+
pivotTable: 'application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml',
|
|
28
|
+
pivotCacheDefinition: 'application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml',
|
|
29
|
+
pivotCacheRecords: 'application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml',
|
|
30
|
+
// Both threaded-comment parts are Microsoft extensions, hence the `vnd.ms-excel` vendor prefix rather
|
|
31
|
+
// than the `openxmlformats-officedocument` one every standard part carries.
|
|
32
|
+
threadedComments: 'application/vnd.ms-excel.threadedcomments+xml',
|
|
33
|
+
person: 'application/vnd.ms-excel.person+xml',
|
|
34
|
+
};
|
|
35
|
+
export function contentTypesXml(sheetCount, tables, commentNumbers, drawingNumbers, printerSettingsNumbers, mediaExtensions, hasSharedStrings, preservedParts, pivots, preservedWorkbookRefs, threadedCommentNumbers, hasPersons) {
|
|
36
|
+
// One extension→default-content-type map both halves read: the defaults render it, the overrides
|
|
37
|
+
// correct any preserved part whose own type differs from its extension's default. Sharing it is what
|
|
38
|
+
// keeps a `<Default>` and its `<Override>`s from ever disagreeing.
|
|
39
|
+
const extensionDefaults = buildExtensionDefaults(commentNumbers, printerSettingsNumbers, mediaExtensions, preservedParts);
|
|
40
|
+
return (XML_DECLARATION +
|
|
41
|
+
`<Types xmlns="${NS.contentTypes}">` +
|
|
42
|
+
contentTypeDefaults(extensionDefaults) +
|
|
43
|
+
contentTypeOverrides(sheetCount, tables, drawingNumbers, commentNumbers, hasSharedStrings, preservedParts, pivots, preservedWorkbookRefs, extensionDefaults, threadedCommentNumbers, hasPersons) +
|
|
44
|
+
'</Types>');
|
|
45
|
+
}
|
|
46
|
+
// The content type declared at the `<Default>` level for each file extension the package carries, in
|
|
47
|
+
// emission order: the built-in rels/xml pair, the vml/bin/image kinds the writer itself generates,
|
|
48
|
+
// then one default per *new* extension a preserved binary part introduces (first part of an extension
|
|
49
|
+
// wins). Keys are lower-cased for case-insensitive extension matching; each value keeps the extension
|
|
50
|
+
// token as it will be emitted so rendering stays byte-stable. A preserved `.xml` part is deliberately
|
|
51
|
+
// left out — it always carries its own type as a per-part override, never a generic `xml` default.
|
|
52
|
+
function buildExtensionDefaults(commentNumbers, printerSettingsNumbers, mediaExtensions, preservedParts) {
|
|
53
|
+
const defaults = new Map();
|
|
54
|
+
const add = (extension, contentType) => {
|
|
55
|
+
const key = extension.toLowerCase();
|
|
56
|
+
if (!defaults.has(key))
|
|
57
|
+
defaults.set(key, { extension, contentType });
|
|
58
|
+
};
|
|
59
|
+
add('rels', 'application/vnd.openxmlformats-package.relationships+xml');
|
|
60
|
+
add('xml', 'application/xml');
|
|
61
|
+
if (commentNumbers.length > 0)
|
|
62
|
+
add('vml', CT.vml);
|
|
63
|
+
if (printerSettingsNumbers.length > 0)
|
|
64
|
+
add('bin', CT.printerSettings);
|
|
65
|
+
for (const ext of mediaExtensions)
|
|
66
|
+
add(ext, imageContentType(ext));
|
|
67
|
+
for (const part of preservedParts) {
|
|
68
|
+
const ext = extensionOf(part.path);
|
|
69
|
+
if (ext.toLowerCase() === 'xml')
|
|
70
|
+
continue;
|
|
71
|
+
add(ext, part.contentType);
|
|
72
|
+
}
|
|
73
|
+
return defaults;
|
|
74
|
+
}
|
|
75
|
+
// A macro-enabled workbook's own VBA project is round-tripped as a preserved workbook reference
|
|
76
|
+
// (see `isPreservedWorkbookRelType` in read.ts), so its presence is what distinguishes a re-emitted
|
|
77
|
+
// .xlsm from a plain .xlsx: `xl/workbook.xml` must declare the macro-enabled content type or Excel
|
|
78
|
+
// flags the package as needing repair on open.
|
|
79
|
+
function isMacroEnabled(preservedWorkbookRefs) {
|
|
80
|
+
return preservedWorkbookRefs.some((ref) => ref.relType.endsWith('/vbaProject'));
|
|
81
|
+
}
|
|
82
|
+
// The extension-level `<Default>` declarations, rendered from the shared extension-default map (see
|
|
83
|
+
// {@link buildExtensionDefaults}) in insertion order. The raw bytes of a VML, a printer-settings blob,
|
|
84
|
+
// or an image carry no XML content type of their own, so each is declared once per extension rather
|
|
85
|
+
// than per part; a preserved binary part whose type differs from its extension's default is corrected
|
|
86
|
+
// by a per-part `<Override>` in {@link contentTypeOverrides}.
|
|
87
|
+
function contentTypeDefaults(extensionDefaults) {
|
|
88
|
+
return [...extensionDefaults.values()]
|
|
89
|
+
.map(({ extension, contentType }) => defaultType(extension, contentType))
|
|
90
|
+
.join('');
|
|
91
|
+
}
|
|
92
|
+
// The per-part `<Override>` declarations, in canonical package order: workbook, worksheets, tables,
|
|
93
|
+
// drawings, comments, the threaded-comment parts, each pivot's three parts, theme, styles, the optional
|
|
94
|
+
// shared strings and threaded-comment person registry, the doc-props pair, then any preserved part whose
|
|
95
|
+
// content type its extension's `<Default>` does not already carry — every `.xml` part (the generic `xml`
|
|
96
|
+
// default never matches a real part type) and any binary part sharing an extension with a differently-typed
|
|
97
|
+
// sibling (a `vbaProjectSignature.bin` next to a `vbaProject.bin`), which a lone extension default would
|
|
98
|
+
// otherwise mis-type.
|
|
99
|
+
function contentTypeOverrides(sheetCount, tables, drawingNumbers, commentNumbers, hasSharedStrings, preservedParts, pivots, preservedWorkbookRefs, extensionDefaults, threadedCommentNumbers, hasPersons) {
|
|
100
|
+
const preservedOverrides = preservedParts
|
|
101
|
+
// A preserved theme lands at the fixed theme path, whose override is already in the list below —
|
|
102
|
+
// and OPC forbids declaring the same PartName twice. The fixed declaration is the right one to
|
|
103
|
+
// keep: the part reached the model through a `.../theme` relationship, so its type is the theme
|
|
104
|
+
// type whatever the source package happened to declare.
|
|
105
|
+
.filter((part) => part.path !== THEME_PART_PATH)
|
|
106
|
+
.filter((part) => extensionDefaults.get(extensionOf(part.path).toLowerCase())?.contentType !==
|
|
107
|
+
part.contentType)
|
|
108
|
+
.map((part) => override(`/${part.path}`, part.contentType));
|
|
109
|
+
return [
|
|
110
|
+
override('/xl/workbook.xml', isMacroEnabled(preservedWorkbookRefs) ? CT.macroEnabledWorkbook : CT.workbook),
|
|
111
|
+
...Array.from({ length: sheetCount }, (_, i) => override(`/xl/worksheets/sheet${i + 1}.xml`, CT.worksheet)),
|
|
112
|
+
...tables.map(({ number }) => override(`/xl/tables/table${number}.xml`, CT.table)),
|
|
113
|
+
...drawingNumbers.map((number) => override(`/xl/drawings/drawing${number}.xml`, CT.drawing)),
|
|
114
|
+
...commentNumbers.map((number) => override(`/xl/comments${number}.xml`, CT.comments)),
|
|
115
|
+
...threadedCommentNumbers.map((number) => override(`/xl/threadedComments/threadedComment${number}.xml`, CT.threadedComments)),
|
|
116
|
+
...pivots.map(({ number }) => override(`/xl/pivotTables/pivotTable${number}.xml`, CT.pivotTable)),
|
|
117
|
+
...pivots.map(({ number }) => override(`/xl/pivotCache/pivotCacheDefinition${number}.xml`, CT.pivotCacheDefinition)),
|
|
118
|
+
...pivots.map(({ number }) => override(`/xl/pivotCache/pivotCacheRecords${number}.xml`, CT.pivotCacheRecords)),
|
|
119
|
+
override(`/${THEME_PART_PATH}`, CT.theme),
|
|
120
|
+
override('/xl/styles.xml', CT.styles),
|
|
121
|
+
...(hasSharedStrings ? [override('/xl/sharedStrings.xml', CT.sharedStrings)] : []),
|
|
122
|
+
...(hasPersons ? [override('/xl/persons/person.xml', CT.person)] : []),
|
|
123
|
+
override('/docProps/core.xml', CT.core),
|
|
124
|
+
override('/docProps/app.xml', CT.app),
|
|
125
|
+
...preservedOverrides,
|
|
126
|
+
].join('');
|
|
127
|
+
}
|
|
128
|
+
function override(partName, contentType) {
|
|
129
|
+
return `<Override PartName="${partName}" ContentType="${contentType}"/>`;
|
|
130
|
+
}
|
|
131
|
+
// A `<Default>` content-type declaration binding a file extension to the type every part with that
|
|
132
|
+
// extension carries — the extension-level counterpart to {@link override}'s per-part declaration.
|
|
133
|
+
function defaultType(extension, contentType) {
|
|
134
|
+
return `<Default Extension="${extension}" ContentType="${contentType}"/>`;
|
|
135
|
+
}
|
|
136
|
+
// The package root relationships: the three the writer regenerates from the model (the office
|
|
137
|
+
// document and the core/app properties), followed by any preserved root references — customUI ribbon
|
|
138
|
+
// parts, custom properties, a thumbnail — re-declared with fresh ids past the fixed three so a
|
|
139
|
+
// round-trip keeps content wired from `_rels/.rels` that the model does not otherwise emit.
|
|
140
|
+
export function rootRelsXml(rootRefs) {
|
|
141
|
+
return relationshipsPart([
|
|
142
|
+
relationship('rId1', REL.officeDocument, 'xl/workbook.xml'),
|
|
143
|
+
relationship('rId2', REL.coreProps, 'docProps/core.xml'),
|
|
144
|
+
relationship('rId3', REL.extProps, 'docProps/app.xml'),
|
|
145
|
+
...rootRefs.map((ref, i) => relationship(`rId${4 + i}`, ref.relType, escapeAttr(ref.entryPath))),
|
|
146
|
+
]);
|
|
147
|
+
}
|
|
148
|
+
export function workbookXml(workbook, preservedRels, pivots) {
|
|
149
|
+
const sheets = workbook.worksheets;
|
|
150
|
+
const entries = sheets
|
|
151
|
+
.map((sheet, i) => {
|
|
152
|
+
const state = sheet.state === 'visible' ? '' : ` state="${sheet.state}"`;
|
|
153
|
+
return `<sheet name="${escapeAttr(sheet.name)}" sheetId="${sheet.id}"${state} r:id="rId${i + 1}"/>`;
|
|
154
|
+
})
|
|
155
|
+
.join('');
|
|
156
|
+
return (XML_DECLARATION +
|
|
157
|
+
`<workbook xmlns="${NS.main}" xmlns:r="${NS.docRels}">` +
|
|
158
|
+
workbookProtectionXml(workbook) +
|
|
159
|
+
bookViewsXml(workbook) +
|
|
160
|
+
`<sheets>${entries}</sheets>` +
|
|
161
|
+
externalReferencesXml(preservedRels) +
|
|
162
|
+
definedNamesXml(workbook) +
|
|
163
|
+
calcPrXml(workbook) +
|
|
164
|
+
pivotCachesXml(preservedRels, pivots) +
|
|
165
|
+
workbookExtLstXml(preservedRels) +
|
|
166
|
+
'</workbook>');
|
|
167
|
+
}
|
|
168
|
+
// `<bookViews>` follows `<workbookProtection>` and precedes `<sheets>` in CT_Workbook order. Unlike
|
|
169
|
+
// every other optional block here it is emitted unconditionally: a consumer restores the document
|
|
170
|
+
// window from this rect and lays the sheet's panes out inside it, so a package without one leaves a
|
|
171
|
+
// frozen split measured against an uninitialised window (see `DEFAULT_WORKBOOK_VIEW`). The
|
|
172
|
+
// visibility and minimised flags are written only when they differ from the schema default, and
|
|
173
|
+
// `activeTab` only for a non-first sheet — exactly the shape Excel writes for an ordinary window.
|
|
174
|
+
function bookViewsXml(workbook) {
|
|
175
|
+
const view = workbook.view;
|
|
176
|
+
const activeTab = workbook.activeTabIndex;
|
|
177
|
+
const attrs = (view.visibility !== undefined && view.visibility !== 'visible'
|
|
178
|
+
? ` visibility="${view.visibility}"`
|
|
179
|
+
: '') +
|
|
180
|
+
(view.minimized ? ' minimized="1"' : '') +
|
|
181
|
+
` xWindow="${view.x}" yWindow="${view.y}" windowWidth="${view.width}" windowHeight="${view.height}"` +
|
|
182
|
+
(activeTab === 0 ? '' : ` activeTab="${activeTab}"`);
|
|
183
|
+
return `<bookViews><workbookView${attrs}/></bookViews>`;
|
|
184
|
+
}
|
|
185
|
+
// The `<externalReferences>` element registers each preserved external link (a link to a source
|
|
186
|
+
// workbook), wired to the relationship reaching its `externalLink` part. It follows `<sheets>` in
|
|
187
|
+
// CT_Workbook order and precedes `<definedNames>`; its child order is the `[n]` index a formula or
|
|
188
|
+
// defined name resolves an external cell through, so entries are emitted by their captured
|
|
189
|
+
// `externalReferenceIndex` — keeping every `[1]`, `[2]`, … pointing at the same linked workbook it did
|
|
190
|
+
// before the round-trip. '' when no external link was preserved.
|
|
191
|
+
function externalReferencesXml(preservedRels) {
|
|
192
|
+
const links = preservedRels
|
|
193
|
+
.filter((ref) => ref.externalReferenceIndex !== undefined)
|
|
194
|
+
.sort((a, b) => a.externalReferenceIndex - b.externalReferenceIndex);
|
|
195
|
+
if (links.length === 0)
|
|
196
|
+
return '';
|
|
197
|
+
const entries = links.map((ref) => `<externalReference r:id="${ref.relId}"/>`).join('');
|
|
198
|
+
return `<externalReferences>${entries}</externalReferences>`;
|
|
199
|
+
}
|
|
200
|
+
// The workbook-body `<x14:slicerCaches>` extension that registers each preserved slicer cache, wired
|
|
201
|
+
// to the relationship reaching its cache part. Slicer caches (unlike pivot caches, which register in
|
|
202
|
+
// `<pivotCaches>`) live only in this extension block, so re-emitting it is what lets Excel rediscover
|
|
203
|
+
// the slicers. `<extLst>` is the final child of CT_Workbook. '' when no slicer cache was preserved.
|
|
204
|
+
function workbookExtLstXml(preservedRels) {
|
|
205
|
+
const caches = preservedRels.filter((ref) => ref.relType.endsWith('/slicerCache'));
|
|
206
|
+
if (caches.length === 0)
|
|
207
|
+
return '';
|
|
208
|
+
const entries = caches.map((ref) => `<x14:slicerCache r:id="${ref.relId}"/>`).join('');
|
|
209
|
+
return `<extLst>${x14Ext(SLICER_CACHES_EXT_URI, `<x14:slicerCaches>${entries}</x14:slicerCaches>`)}</extLst>`;
|
|
210
|
+
}
|
|
211
|
+
// The `<pivotCaches>` element registers each pivot cache under the `cacheId` a pivot table resolves
|
|
212
|
+
// its cache through, wired to the relationship that reaches the cache definition. It follows
|
|
213
|
+
// `<calcPr>` in CT_Workbook order and carries both preserved caches (passed through from a read file)
|
|
214
|
+
// and caches the writer generated for modeled pivot tables. A slicer cache (no `cacheId`) is
|
|
215
|
+
// registered in a workbook extension block, not here, so it is skipped.
|
|
216
|
+
function pivotCachesXml(preservedRels, pivots) {
|
|
217
|
+
const preserved = preservedRels
|
|
218
|
+
.filter((ref) => ref.pivotCacheId !== undefined)
|
|
219
|
+
.map((ref) => `<pivotCache cacheId="${escapeAttr(ref.pivotCacheId)}" r:id="${ref.relId}"/>`);
|
|
220
|
+
const generated = pivots.map((pivot) => `<pivotCache cacheId="${escapeAttr(pivot.cacheId)}" r:id="${pivot.workbookRelId}"/>`);
|
|
221
|
+
const entries = [...preserved, ...generated];
|
|
222
|
+
if (entries.length === 0)
|
|
223
|
+
return '';
|
|
224
|
+
return `<pivotCaches>${entries.join('')}</pivotCaches>`;
|
|
225
|
+
}
|
|
226
|
+
// `<workbookProtection>` precedes `<sheets>` in CT_Workbook order. It re-emits the workbook's
|
|
227
|
+
// structure/window lock flags (each written only when true, so an unlocked aspect stays absent) and
|
|
228
|
+
// the preserved password/agile-hash credential attributes verbatim. Emitted only when the workbook
|
|
229
|
+
// actually declares protection — the flags or a credential — so an unprotected workbook stays clean.
|
|
230
|
+
function workbookProtectionXml(workbook) {
|
|
231
|
+
const p = workbook.protection;
|
|
232
|
+
if (p === undefined)
|
|
233
|
+
return '';
|
|
234
|
+
const attrs = [];
|
|
235
|
+
if (p.lockStructure)
|
|
236
|
+
attrs.push('lockStructure="1"');
|
|
237
|
+
if (p.lockWindows)
|
|
238
|
+
attrs.push('lockWindows="1"');
|
|
239
|
+
if (p.lockRevision)
|
|
240
|
+
attrs.push('lockRevision="1"');
|
|
241
|
+
for (const key of WORKBOOK_PROTECTION_CREDENTIAL_ATTRS) {
|
|
242
|
+
const value = p.credentials?.[key];
|
|
243
|
+
if (value !== undefined)
|
|
244
|
+
attrs.push(`${key}="${escapeAttr(value)}"`);
|
|
245
|
+
}
|
|
246
|
+
if (attrs.length === 0)
|
|
247
|
+
return '';
|
|
248
|
+
return `<workbookProtection ${attrs.join(' ')}/>`;
|
|
249
|
+
}
|
|
250
|
+
// The `calcId` desktop Excel stamps into `<calcPr>` — the build number of the calc engine that last
|
|
251
|
+
// evaluated the workbook. Consumers only compare it to decide whether cached results are stale; we
|
|
252
|
+
// emit a fixed recent value alongside `fullCalcOnLoad`, which already forces a full recalculation.
|
|
253
|
+
const EXCEL_CALC_ID = '171027';
|
|
254
|
+
// `<calcPr>` follows `<definedNames>` in CT_Workbook order and carries the calculation settings.
|
|
255
|
+
// Today the model exposes a single one: `fullCalcOnLoad`, which tells the consumer to recalculate
|
|
256
|
+
// every formula on open instead of trusting the cached results. Emitted only when set, so an
|
|
257
|
+
// unmarked workbook keeps the element (and its `calcId`) out of the file entirely.
|
|
258
|
+
function calcPrXml(workbook) {
|
|
259
|
+
return workbook.fullCalcOnLoad ? `<calcPr calcId="${EXCEL_CALC_ID}" fullCalcOnLoad="1"/>` : '';
|
|
260
|
+
}
|
|
261
|
+
// The `<definedNames>` block follows `<sheets>` in the schema. A sheet-scoped name carries a
|
|
262
|
+
// `localSheetId` — the 0-based position of its sheet among the `<sheet>` entries, NOT the sheet's
|
|
263
|
+
// own id — so the index is resolved against the worksheet order here. The refersTo formula is the
|
|
264
|
+
// element's text content, run through the same `_xlfn.` function mangling the writer applies to a
|
|
265
|
+
// cell formula so a name defined as a modern function (a LAMBDA, an XLOOKUP-based name) is stored
|
|
266
|
+
// under the prefix Excel requires; a plain reference has no function call and passes through
|
|
267
|
+
// untouched. Only names that are actually set emit anything.
|
|
268
|
+
function definedNamesXml(workbook) {
|
|
269
|
+
const sheets = workbook.worksheets;
|
|
270
|
+
const userEntries = workbook.definedNames.map((name) => {
|
|
271
|
+
const scopeAttr = name.scope === undefined
|
|
272
|
+
? ''
|
|
273
|
+
: ` localSheetId="${sheets.findIndex((sheet) => sheet.name === name.scope)}"`;
|
|
274
|
+
const commentAttr = name.comment === undefined ? '' : ` comment="${escapeAttr(name.comment)}"`;
|
|
275
|
+
const hiddenAttr = name.hidden ? ' hidden="1"' : '';
|
|
276
|
+
return (`<definedName name="${escapeAttr(name.name)}"${scopeAttr}${commentAttr}${hiddenAttr}>` +
|
|
277
|
+
`${escapeText(mangleFormula(name.refersTo))}</definedName>`);
|
|
278
|
+
});
|
|
279
|
+
// Every sheet-level autofilter contributes the hidden, sheet-scoped `_FilterDatabase` built-in that
|
|
280
|
+
// Excel derives from its range. The reader drops these on load and rebuilds them from the sheet's
|
|
281
|
+
// `<autoFilter>`, so `Worksheet.autoFilter` stays the single source of truth and a round-trip never
|
|
282
|
+
// duplicates them.
|
|
283
|
+
const filterEntries = sheets.flatMap((sheet, index) => sheet.autoFilter === undefined
|
|
284
|
+
? []
|
|
285
|
+
: [
|
|
286
|
+
`<definedName name="_xlnm._FilterDatabase" localSheetId="${index}" hidden="1">` +
|
|
287
|
+
`${escapeText(filterDatabaseRefersTo(sheet.name, sheet.autoFilter.ref))}</definedName>`,
|
|
288
|
+
]);
|
|
289
|
+
const entries = [...userEntries, ...filterEntries];
|
|
290
|
+
if (entries.length === 0)
|
|
291
|
+
return '';
|
|
292
|
+
return `<definedNames>${entries.join('')}</definedNames>`;
|
|
293
|
+
}
|
|
294
|
+
// Build the sheet-qualified, fully-absolute reference a `_FilterDatabase` name carries
|
|
295
|
+
// (`'Sheet 1'!$A$1:$C$10`) from a sheet name and its already-canonical `A1:C10` autofilter range.
|
|
296
|
+
function filterDatabaseRefersTo(sheetName, range) {
|
|
297
|
+
const absolute = range.replace(/([A-Z]+)(\d+)/g, '$$$1$$$2');
|
|
298
|
+
return `${quoteSheetName(sheetName)}!${absolute}`;
|
|
299
|
+
}
|
|
300
|
+
// The relationships the workbook part always carries after its per-sheet rels: `styles.xml` and
|
|
301
|
+
// `theme/theme1.xml`. Their count anchors every downstream rel id — `sharedStrings.xml` and the
|
|
302
|
+
// threaded-comment person registry (when present), then the preserved/pivot caches — so `write.ts`
|
|
303
|
+
// derives its `workbookRelBase` from this same constant rather than repeating the literal and risking
|
|
304
|
+
// drift.
|
|
305
|
+
export const FIXED_WORKBOOK_REL_COUNT = 2;
|
|
306
|
+
export function workbookRelsXml(sheetCount, hasSharedStrings, personsRelId, preservedRels, pivots) {
|
|
307
|
+
return relationshipsPart([
|
|
308
|
+
...Array.from({ length: sheetCount }, (_, i) => relationship(`rId${i + 1}`, REL.worksheet, `worksheets/sheet${i + 1}.xml`)),
|
|
309
|
+
relationship(`rId${sheetCount + 1}`, REL.styles, 'styles.xml'),
|
|
310
|
+
relationship(`rId${sheetCount + FIXED_WORKBOOK_REL_COUNT}`, REL.theme, relativePartPath('xl/workbook.xml', THEME_PART_PATH)),
|
|
311
|
+
...(hasSharedStrings
|
|
312
|
+
? [
|
|
313
|
+
relationship(`rId${sheetCount + FIXED_WORKBOOK_REL_COUNT + 1}`, REL.sharedStrings, 'sharedStrings.xml'),
|
|
314
|
+
]
|
|
315
|
+
: []),
|
|
316
|
+
// The threaded-comment identity registry every conversation on every sheet resolves its authors and
|
|
317
|
+
// @mentions through. Workbook-level and singular, so this one relationship serves all the sheets.
|
|
318
|
+
...(personsRelId === null
|
|
319
|
+
? []
|
|
320
|
+
: [relationship(personsRelId, REL.person, 'persons/person.xml')]),
|
|
321
|
+
// A preserved cache's target is package-absolute; express it relative to the workbook part.
|
|
322
|
+
...preservedRels.map((ref) => relationship(ref.relId, ref.relType, escapeAttr(relativePartPath('xl/workbook.xml', ref.entryPath)))),
|
|
323
|
+
// A generated pivot cache's workbook relationship reaches its cache definition part.
|
|
324
|
+
...pivots.map((pivot) => relationship(pivot.workbookRelId, REL.pivotCacheDefinition, `pivotCache/pivotCacheDefinition${pivot.number}.xml`)),
|
|
325
|
+
]);
|
|
326
|
+
}
|
|
327
|
+
export function corePropsXml(properties) {
|
|
328
|
+
const parts = [];
|
|
329
|
+
if (properties.creator !== undefined) {
|
|
330
|
+
parts.push(`<dc:creator>${escapeText(properties.creator)}</dc:creator>`);
|
|
331
|
+
}
|
|
332
|
+
if (properties.lastModifiedBy !== undefined) {
|
|
333
|
+
parts.push(`<cp:lastModifiedBy>${escapeText(properties.lastModifiedBy)}</cp:lastModifiedBy>`);
|
|
334
|
+
}
|
|
335
|
+
if (properties.created) {
|
|
336
|
+
parts.push(w3cdtf('created', properties.created));
|
|
337
|
+
}
|
|
338
|
+
if (properties.modified) {
|
|
339
|
+
parts.push(w3cdtf('modified', properties.modified));
|
|
340
|
+
}
|
|
341
|
+
return (XML_DECLARATION +
|
|
342
|
+
`<cp:coreProperties xmlns:cp="${NS.coreProps}" xmlns:dc="${NS.dc}" xmlns:dcterms="${NS.dcterms}" ` +
|
|
343
|
+
`xmlns:dcmitype="${NS.dcmitype}" xmlns:xsi="${NS.xsi}">` +
|
|
344
|
+
parts.join('') +
|
|
345
|
+
'</cp:coreProperties>');
|
|
346
|
+
}
|
|
347
|
+
function w3cdtf(element, date) {
|
|
348
|
+
return `<dcterms:${element} xsi:type="dcterms:W3CDTF">${date.toISOString()}</dcterms:${element}>`;
|
|
349
|
+
}
|
|
350
|
+
export function appPropsXml() {
|
|
351
|
+
return (XML_DECLARATION +
|
|
352
|
+
`<Properties xmlns="${NS.extProps}"><Application>ts-xlsx</Application></Properties>`);
|
|
353
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { Cell } from '../../core/cell.ts';
|
|
2
|
+
import type { ColumnProperties, RowProperties, Worksheet } from '../../core/worksheet.ts';
|
|
3
|
+
import { type HyperlinkPlan } from './hyperlinks.ts';
|
|
4
|
+
import type { BackgroundPlan, CommentPlan, DrawingPlan, PivotPlan, PreservedReferencePlan, PrinterSettingsPlan, TablePlan, ThreadedCommentPlan } from './package-plan.ts';
|
|
5
|
+
import { type SharedFormulaRole } from './shared-formulas.ts';
|
|
6
|
+
import type { SharedStringTable } from './shared-strings.ts';
|
|
7
|
+
import type { StyleRegistry } from './styles.ts';
|
|
8
|
+
/**
|
|
9
|
+
* The used-cell extent of a sheet — the top-left/bottom-right grid bounds that fold into the
|
|
10
|
+
* `<dimension>`. Rows carrying only formatting (a row height, an outline level) do not extend the
|
|
11
|
+
* used range, matching how Excel records `<dimension>`, so {@link add} ignores them. A fresh extent
|
|
12
|
+
* holds the `Infinity`/`-Infinity` sentinels; {@link isEmpty} reports that no used cell has been seen.
|
|
13
|
+
*/
|
|
14
|
+
export declare class Extent {
|
|
15
|
+
top: number;
|
|
16
|
+
left: number;
|
|
17
|
+
bottom: number;
|
|
18
|
+
right: number;
|
|
19
|
+
constructor(seed?: Extent);
|
|
20
|
+
/** Whether no used cell has been folded in yet — the sheet's dimension is then the lone cell `A1`. */
|
|
21
|
+
get isEmpty(): boolean;
|
|
22
|
+
/** Fold a rendered row's used-column span into the extent. `minCol` is `Infinity` when the row
|
|
23
|
+
* carried no cells (only formatting), which extends nothing. */
|
|
24
|
+
add(row: number, minCol: number, maxCol: number): void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A worksheet's eagerly-serialised rows: each row's `<row>` XML tagged with its number (so it merges
|
|
28
|
+
* into ascending order with the sheet's remaining live rows, whatever order it was committed in), plus
|
|
29
|
+
* the used-cell {@link Extent} they span. The buffered pass folds that extent into the sheet's dimension.
|
|
30
|
+
*/
|
|
31
|
+
export interface FlushedSheet {
|
|
32
|
+
readonly rows: ReadonlyArray<{
|
|
33
|
+
readonly number: number;
|
|
34
|
+
readonly xml: string;
|
|
35
|
+
}>;
|
|
36
|
+
readonly extent: Extent;
|
|
37
|
+
/**
|
|
38
|
+
* The deepest row outline level among the flushed rows. Carried across the eviction because
|
|
39
|
+
* `<sheetFormatPr outlineLevelRow>` is derived from every row on the sheet, and a flushed row's
|
|
40
|
+
* properties are gone from the model by the time the header is serialised.
|
|
41
|
+
*/
|
|
42
|
+
readonly maxRowOutlineLevel: number;
|
|
43
|
+
}
|
|
44
|
+
export interface SheetReferences {
|
|
45
|
+
readonly drawingRelId: string | null;
|
|
46
|
+
readonly legacyDrawingRelId: string | null;
|
|
47
|
+
readonly printerSettingsRelId: string | null;
|
|
48
|
+
readonly backgroundRelId: string | null;
|
|
49
|
+
readonly legacyDrawingHFRelId: string | null;
|
|
50
|
+
readonly slicerRelIds: readonly string[];
|
|
51
|
+
}
|
|
52
|
+
export declare function worksheetXml(sheet: Worksheet, tables: readonly TablePlan[], styles: StyleRegistry, references: SheetReferences, hyperlinks: readonly HyperlinkPlan[], sharedStrings: SharedStringTable | null, active: boolean, flushed?: FlushedSheet): string;
|
|
53
|
+
/**
|
|
54
|
+
* A column's style facets are defaults its cells inherit unless they override them; the writer
|
|
55
|
+
* composes each cell's full style up front (cell over row over column, per facet) so a cell that
|
|
56
|
+
* overrides one facet still carries the column's others, rather than silently dropping them. Frozen
|
|
57
|
+
* once by the streaming writer at its first flush so every eagerly-rendered row sees the same defaults.
|
|
58
|
+
*/
|
|
59
|
+
export declare function buildColumnDefaults(sheet: Worksheet): Map<number, ColumnProperties>;
|
|
60
|
+
/** The whole-sheet context a single row needs to serialise: the column defaults it inherits, the
|
|
61
|
+
* style/string tables it interns into, the shared-formula roles its cells play, and the collapsed
|
|
62
|
+
* outline summaries whose toggle it must stamp. The streaming writer supplies empty shared-formula
|
|
63
|
+
* and collapsed-summary sets, since those are whole-sheet derivations a flushed row cannot join. */
|
|
64
|
+
export interface RowRenderContext {
|
|
65
|
+
readonly columnDefaults: ReadonlyMap<number, ColumnProperties>;
|
|
66
|
+
readonly styles: StyleRegistry;
|
|
67
|
+
readonly sharedStrings: SharedStringTable | null;
|
|
68
|
+
readonly sharedRoles: ReadonlyMap<string, SharedFormulaRole>;
|
|
69
|
+
readonly collapsedSummaries: ReadonlySet<number>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Serialise one row to its `<row>` element, or '' when the row has neither data nor its own
|
|
73
|
+
* formatting. Returns the used-column bounds (`Infinity`/`-Infinity` when nothing was rendered) so a
|
|
74
|
+
* caller can fold them into the sheet dimension. Shared by the buffered sheet pass and the streaming
|
|
75
|
+
* writer's eager flush, so both emit byte-identical rows.
|
|
76
|
+
*/
|
|
77
|
+
export declare function renderRow(entry: {
|
|
78
|
+
readonly number: number;
|
|
79
|
+
readonly cells: readonly Cell[];
|
|
80
|
+
readonly properties: RowProperties | undefined;
|
|
81
|
+
}, ctx: RowRenderContext): {
|
|
82
|
+
xml: string;
|
|
83
|
+
minCol: number;
|
|
84
|
+
maxCol: number;
|
|
85
|
+
};
|
|
86
|
+
export declare function worksheetRelsXml(tables: readonly TablePlan[], drawing: DrawingPlan | null, comments: CommentPlan | null, threadedComments: ThreadedCommentPlan | null, printerSettings: PrinterSettingsPlan | null, background: BackgroundPlan | null, hyperlinks: readonly HyperlinkPlan[], preservedReferences: readonly PreservedReferencePlan[], pivots: readonly PivotPlan[]): string;
|