@shbernal/ts-xlsx 3.0.0 → 3.2.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 -24
- package/dist/bytes.d.ts +10 -2
- package/dist/bytes.js +22 -0
- package/dist/core/address.d.ts +96 -2
- package/dist/core/address.js +87 -33
- package/dist/core/array-formula-ranges.d.ts +33 -0
- package/dist/core/array-formula-ranges.js +62 -0
- package/dist/core/autofilter.d.ts +4 -3
- package/dist/core/autofilter.js +31 -30
- package/dist/core/axis-handle.d.ts +2 -0
- package/dist/core/axis-handle.js +5 -2
- package/dist/core/cell.d.ts +4 -3
- package/dist/core/cell.js +4 -6
- package/dist/core/clone.d.ts +29 -0
- package/dist/core/clone.js +24 -0
- package/dist/core/color-resolution.js +4 -6
- package/dist/core/column.d.ts +1 -0
- package/dist/core/column.js +6 -2
- package/dist/core/comment-thread.d.ts +7 -3
- package/dist/core/comment-thread.js +2 -1
- package/dist/core/conditional-formatting-overlay.d.ts +11 -1
- package/dist/core/conditional-formatting-overlay.js +30 -3
- package/dist/core/conditional-formatting.d.ts +107 -11
- package/dist/core/conditional-formatting.js +76 -19
- package/dist/core/containers.d.ts +12 -0
- package/dist/core/containers.js +5 -0
- package/dist/core/data-validation-overlay.d.ts +7 -1
- package/dist/core/data-validation-overlay.js +19 -4
- package/dist/core/data-validation.d.ts +22 -0
- package/dist/core/data-validation.js +30 -4
- package/dist/core/date-format.d.ts +20 -0
- package/dist/core/date-format.js +170 -0
- package/dist/core/date.d.ts +43 -8
- package/dist/core/date.js +19 -3
- package/dist/core/formula-references.d.ts +26 -0
- package/dist/core/formula-references.js +173 -0
- package/dist/core/formula-scan.d.ts +2 -0
- package/dist/core/formula-scan.js +58 -0
- package/dist/core/formula.d.ts +76 -17
- package/dist/core/formula.js +87 -80
- package/dist/core/function-values.d.ts +4 -0
- package/dist/core/function-values.js +58 -0
- package/dist/core/future-functions.d.ts +3 -0
- package/dist/core/{modern-functions.js → future-functions.js} +119 -88
- package/dist/core/grid-edits.d.ts +30 -3
- package/dist/core/grid-edits.js +248 -81
- package/dist/core/grid-shift.d.ts +58 -9
- package/dist/core/grid-shift.js +26 -4
- package/dist/core/hyperlink.d.ts +39 -0
- package/dist/core/hyperlink.js +88 -0
- package/dist/core/image.d.ts +49 -14
- package/dist/core/image.js +16 -5
- package/dist/core/internal.d.ts +10 -2
- package/dist/core/limits.d.ts +25 -0
- package/dist/core/limits.js +4 -0
- package/dist/core/merge.d.ts +18 -4
- package/dist/core/merge.js +33 -20
- package/dist/core/page-setup.d.ts +26 -11
- package/dist/core/pivot-table.d.ts +49 -10
- package/dist/core/pivot-table.js +112 -60
- package/dist/core/protection.d.ts +66 -4
- package/dist/core/protection.js +6 -11
- package/dist/core/range.js +34 -30
- package/dist/core/row-input.js +2 -2
- package/dist/core/row.d.ts +1 -0
- package/dist/core/row.js +6 -2
- package/dist/core/structured-reference.d.ts +7 -0
- package/dist/core/structured-reference.js +7 -0
- package/dist/core/style.d.ts +85 -70
- package/dist/core/style.js +92 -28
- package/dist/core/table-style.d.ts +1 -1
- package/dist/core/table-style.js +4 -4
- package/dist/core/table.d.ts +64 -16
- package/dist/core/table.js +87 -40
- package/dist/core/theme.d.ts +2 -0
- package/dist/core/theme.js +9 -5
- package/dist/core/value.d.ts +60 -28
- package/dist/core/value.js +48 -43
- package/dist/core/workbook-media.d.ts +34 -0
- package/dist/core/workbook-media.js +44 -0
- package/dist/core/workbook-styles.d.ts +83 -1
- package/dist/core/workbook-styles.js +4 -0
- package/dist/core/workbook-theme.js +5 -3
- package/dist/core/workbook-vba.js +3 -2
- package/dist/core/workbook.d.ts +41 -3
- package/dist/core/workbook.js +46 -41
- package/dist/core/worksheet-comments.d.ts +2 -1
- package/dist/core/worksheet-comments.js +20 -13
- package/dist/core/worksheet-merges.d.ts +49 -0
- package/dist/core/worksheet-merges.js +65 -0
- package/dist/core/worksheet-model.d.ts +10 -2
- package/dist/core/worksheet-model.js +28 -9
- package/dist/core/worksheet-pictures.d.ts +3 -3
- package/dist/core/worksheet-pictures.js +7 -6
- package/dist/core/worksheet.d.ts +165 -27
- package/dist/core/worksheet.js +206 -89
- package/dist/customui/ribbon.js +2 -1
- package/dist/entries/core.d.ts +21 -14
- package/dist/entries/core.js +14 -7
- package/dist/entries/errors.d.ts +1 -0
- package/dist/entries/errors.js +1 -0
- package/dist/entries/xlsx.d.ts +1 -1
- package/dist/errors.d.ts +64 -0
- package/dist/errors.js +22 -0
- package/dist/hex.d.ts +8 -0
- package/dist/hex.js +3 -0
- package/dist/io/cell-metadata/metadata.d.ts +42 -0
- package/dist/io/cell-metadata/metadata.js +35 -0
- package/dist/io/cell-metadata/rich-values.d.ts +11 -0
- package/dist/io/cell-metadata/rich-values.js +80 -0
- package/dist/io/csv/delimiter.d.ts +21 -0
- package/dist/io/csv/delimiter.js +18 -0
- package/dist/io/csv/errors.d.ts +14 -0
- package/dist/io/csv/errors.js +5 -0
- package/dist/io/csv/read.d.ts +6 -1
- package/dist/io/csv/read.js +51 -22
- package/dist/io/csv/write.d.ts +19 -5
- package/dist/io/csv/write.js +24 -44
- package/dist/io/opc/inflate.js +14 -0
- package/dist/io/opc/namespaces.d.ts +16 -0
- package/dist/io/opc/namespaces.js +4 -0
- package/dist/io/opc/part-paths.d.ts +9 -0
- package/dist/io/opc/part-paths.js +5 -5
- package/dist/io/opc/read-opc.d.ts +58 -14
- package/dist/io/opc/read-opc.js +49 -21
- package/dist/io/opc/read-options.d.ts +5 -1
- package/dist/io/opc/sniff-format.d.ts +3 -3
- package/dist/io/opc/sniff-format.js +2 -2
- package/dist/io/opc/strict-relationships.d.ts +2 -0
- package/dist/io/opc/strict-relationships.js +12 -0
- package/dist/io/read-policy/column-budget.d.ts +26 -0
- package/dist/io/read-policy/column-budget.js +18 -0
- package/dist/io/read-policy/read-repair.d.ts +74 -0
- package/dist/io/read-policy/read-repair.js +119 -0
- package/dist/io/style/cell-style-resolution.d.ts +25 -0
- package/dist/io/style/cell-style-resolution.js +30 -0
- package/dist/io/style/xf-style.d.ts +23 -1
- package/dist/io/style/xf-style.js +8 -0
- package/dist/io/xlsb/formula.d.ts +2 -2
- package/dist/io/xlsb/formula.js +52 -35
- package/dist/io/xlsb/primitives.js +8 -14
- package/dist/io/xlsb/ptg-functions.d.ts +19 -10
- package/dist/io/xlsb/ptg-functions.js +495 -596
- package/dist/io/xlsb/read-metadata.d.ts +7 -0
- package/dist/io/xlsb/read-metadata.js +69 -0
- package/dist/io/xlsb/read-styles.js +45 -81
- package/dist/io/xlsb/read-worksheet.d.ts +26 -1
- package/dist/io/xlsb/read-worksheet.js +148 -106
- package/dist/io/xlsb/read.d.ts +6 -3
- package/dist/io/xlsb/read.js +70 -31
- package/dist/io/xlsb/record-stream.d.ts +30 -0
- package/dist/io/xlsb/record-stream.js +20 -0
- package/dist/io/xlsb/record-types.d.ts +14 -5
- package/dist/io/xlsb/record-types.js +14 -5
- package/dist/io/xlsb/sheet-protection.d.ts +20 -0
- package/dist/io/xlsb/sheet-protection.js +60 -0
- package/dist/io/xlsx/cell-accumulator.d.ts +24 -9
- package/dist/io/xlsx/cell-accumulator.js +74 -21
- package/dist/io/xlsx/cell-metadata.d.ts +39 -0
- package/dist/io/xlsx/cell-metadata.js +162 -0
- package/dist/io/xlsx/cell-value.d.ts +19 -5
- package/dist/io/xlsx/cell-value.js +45 -30
- package/dist/io/xlsx/color-xml.js +3 -2
- package/dist/io/xlsx/column-span.d.ts +11 -0
- package/dist/io/xlsx/column-span.js +9 -0
- package/dist/io/xlsx/comments.d.ts +9 -30
- package/dist/io/xlsx/comments.js +25 -83
- package/dist/io/xlsx/conditional-formatting.d.ts +43 -23
- package/dist/io/xlsx/conditional-formatting.js +437 -138
- package/dist/io/xlsx/data-validation.d.ts +12 -7
- package/dist/io/xlsx/data-validation.js +67 -53
- package/dist/io/xlsx/edit-vba.d.ts +7 -2
- package/dist/io/xlsx/edit-vba.js +52 -52
- package/dist/io/xlsx/font-xml.d.ts +7 -0
- package/dist/io/xlsx/font-xml.js +104 -0
- package/dist/io/xlsx/hyperlinks.d.ts +19 -21
- package/dist/io/xlsx/hyperlinks.js +12 -32
- package/dist/io/xlsx/images.d.ts +49 -16
- package/dist/io/xlsx/images.js +149 -50
- package/dist/io/xlsx/namespaces.d.ts +24 -0
- package/dist/io/xlsx/namespaces.js +11 -0
- package/dist/io/xlsx/package-plan.d.ts +60 -15
- package/dist/io/xlsx/package-plan.js +83 -18
- package/dist/io/xlsx/part-names.d.ts +6 -8
- package/dist/io/xlsx/part-names.js +3 -7
- package/dist/io/xlsx/pivot.d.ts +5 -5
- package/dist/io/xlsx/pivot.js +26 -24
- package/dist/io/xlsx/preserved-splices.d.ts +6 -0
- package/dist/io/xlsx/preserved-splices.js +74 -0
- package/dist/io/xlsx/read-comments.d.ts +29 -0
- package/dist/io/xlsx/read-comments.js +75 -0
- package/dist/io/xlsx/read-parts.d.ts +59 -0
- package/dist/io/xlsx/read-parts.js +259 -0
- package/dist/io/xlsx/read-pivot.js +11 -4
- package/dist/io/xlsx/{rich-runs.d.ts → read-rich-runs.d.ts} +8 -5
- package/dist/io/xlsx/{rich-runs.js → read-rich-runs.js} +24 -4
- package/dist/io/xlsx/read-rows.d.ts +35 -11
- package/dist/io/xlsx/read-rows.js +73 -49
- package/dist/io/xlsx/read-shared-strings.js +3 -2
- package/dist/io/xlsx/read-styles.d.ts +0 -30
- package/dist/io/xlsx/read-styles.js +45 -105
- package/dist/io/xlsx/read-workbook-xml.d.ts +42 -0
- package/dist/io/xlsx/read-workbook-xml.js +175 -0
- package/dist/io/xlsx/read-worksheet.d.ts +9 -3
- package/dist/io/xlsx/read-worksheet.js +70 -177
- package/dist/io/xlsx/read.d.ts +3 -14
- package/dist/io/xlsx/read.js +74 -411
- package/dist/io/xlsx/relationships.d.ts +3 -0
- package/dist/io/xlsx/relationships.js +4 -0
- package/dist/io/xlsx/rich-text.js +1 -1
- package/dist/io/xlsx/row-position.d.ts +20 -0
- package/dist/io/xlsx/row-position.js +11 -0
- package/dist/io/xlsx/row-xml.d.ts +139 -0
- package/dist/io/xlsx/row-xml.js +222 -0
- package/dist/io/xlsx/shared-formulas.js +2 -2
- package/dist/io/xlsx/sheet-properties.d.ts +10 -1
- package/dist/io/xlsx/sheet-properties.js +182 -20
- package/dist/io/xlsx/strict-parts.d.ts +7 -0
- package/dist/io/xlsx/strict-parts.js +171 -0
- package/dist/io/xlsx/style-elements.d.ts +41 -0
- package/dist/io/xlsx/style-elements.js +136 -0
- package/dist/io/xlsx/styles.d.ts +17 -3
- package/dist/io/xlsx/styles.js +13 -209
- package/dist/io/xlsx/tables.d.ts +10 -2
- package/dist/io/xlsx/tables.js +55 -52
- package/dist/io/xlsx/theme-xml.d.ts +32 -4
- package/dist/io/xlsx/theme-xml.js +106 -71
- package/dist/io/xlsx/threaded-comments.d.ts +14 -11
- package/dist/io/xlsx/threaded-comments.js +16 -8
- package/dist/io/xlsx/workbook-xml.d.ts +45 -6
- package/dist/io/xlsx/workbook-xml.js +62 -54
- package/dist/io/xlsx/worksheet-xml.d.ts +26 -70
- package/dist/io/xlsx/worksheet-xml.js +69 -282
- package/dist/io/xlsx/write-stream.d.ts +90 -19
- package/dist/io/xlsx/write-stream.js +80 -25
- package/dist/io/xlsx/write.d.ts +12 -6
- package/dist/io/xlsx/write.js +226 -123
- package/dist/rel-type.d.ts +25 -0
- package/dist/rel-type.js +9 -0
- package/dist/token-set.d.ts +13 -0
- package/dist/token-set.js +4 -1
- package/dist/vba/bytes.d.ts +16 -5
- package/dist/vba/bytes.js +27 -6
- package/dist/vba/cfb-format.d.ts +55 -0
- package/dist/vba/cfb-format.js +35 -0
- package/dist/vba/cfb-writer.d.ts +8 -0
- package/dist/vba/cfb-writer.js +40 -40
- package/dist/vba/cfb.d.ts +21 -4
- package/dist/vba/cfb.js +124 -90
- package/dist/vba/codepage.js +2 -1
- package/dist/vba/dir-records.d.ts +6 -0
- package/dist/vba/dir-records.js +10 -2
- package/dist/vba/errors.d.ts +11 -4
- package/dist/vba/index.d.ts +0 -2
- package/dist/vba/index.js +0 -2
- package/dist/vba/ms-ovba.d.ts +6 -2
- package/dist/vba/ms-ovba.js +66 -22
- package/dist/vba/project-editor.js +129 -119
- package/dist/vba/project.d.ts +15 -1
- package/dist/vba/project.js +38 -13
- package/dist/vba/vba-encoding.d.ts +4 -10
- package/dist/vba/vba-encoding.js +3 -17
- package/dist/xml/xml-attrs.d.ts +37 -0
- package/dist/xml/xml-attrs.js +30 -0
- package/dist/xml/xml-chars.d.ts +40 -0
- package/dist/xml/xml-chars.js +12 -0
- package/dist/xml/xml-namespaces.d.ts +31 -0
- package/dist/xml/xml-namespaces.js +50 -0
- package/dist/xml/xml-read.d.ts +101 -11
- package/dist/xml/xml-read.js +150 -18
- package/dist/xml/xml-scan.d.ts +25 -34
- package/dist/xml/xml-scan.js +69 -46
- package/dist/xml/xml.d.ts +59 -26
- package/dist/xml/xml.js +45 -23
- package/package.json +15 -9
- package/skills/ts-xlsx-upstream/SKILL.md +21 -13
- package/dist/core/modern-functions.d.ts +0 -1
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { FormulaPlacement } from '../../core/array-formula-ranges.ts';
|
|
2
|
+
import { type Cell } from '../../core/cell.ts';
|
|
3
|
+
import { type DateEpoch } from '../../core/date.ts';
|
|
4
|
+
import type { ColumnProperties, RowProperties, Worksheet } from '../../core/worksheet.ts';
|
|
5
|
+
import type { WorkbookMetadataTable } from './cell-metadata.ts';
|
|
6
|
+
import type { CommentCell } from './comments.ts';
|
|
7
|
+
import type { SharedFormulaRole } from './shared-formulas.ts';
|
|
8
|
+
import type { SharedStringTable } from './shared-strings.ts';
|
|
9
|
+
import type { StyleRegistry } from './styles.ts';
|
|
10
|
+
/**
|
|
11
|
+
* The used-cell extent of a sheet: the top-left/bottom-right grid bounds that fold into the
|
|
12
|
+
* `<dimension>`. Rows carrying only formatting (a row height, an outline level) do not extend the
|
|
13
|
+
* used range, matching how Excel records `<dimension>`, so {@link add} ignores them. A fresh extent
|
|
14
|
+
* holds the `Infinity`/`-Infinity` sentinels; {@link isEmpty} reports that no used cell has been seen.
|
|
15
|
+
*/
|
|
16
|
+
export declare class Extent {
|
|
17
|
+
top: number;
|
|
18
|
+
left: number;
|
|
19
|
+
bottom: number;
|
|
20
|
+
right: number;
|
|
21
|
+
constructor(seed?: Extent);
|
|
22
|
+
/** Whether no used cell has been folded in yet, in which case the dimension is the lone cell `A1`. */
|
|
23
|
+
get isEmpty(): boolean;
|
|
24
|
+
/** Fold a rendered row's used-column span into the extent. `minCol` is `Infinity` when the row
|
|
25
|
+
* carried no cells (only formatting), which extends nothing. */
|
|
26
|
+
add(row: number, minCol: number, maxCol: number): void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A row the streaming writer already serialised, kept with the attribute string it was built from.
|
|
30
|
+
*
|
|
31
|
+
* The attributes are carried rather than re-read out of `xml`, and that is the whole point of the
|
|
32
|
+
* field. `collapsed="1"` is decided after the row is gone (see {@link FlushedSheet.rowOutline}), so
|
|
33
|
+
* the summary row has to be patched, and the patcher used to ask `xml.includes(' collapsed="1"')`
|
|
34
|
+
* whether the attribute was already there. The `<row>` tag's shape is known, but the *cell text*
|
|
35
|
+
* embedded in it is not: `escapeText` leaves a double quote verbatim, so a cell whose value was the
|
|
36
|
+
* literal string ` collapsed="1"` answered that question for the row and left the outline group
|
|
37
|
+
* rendering expanded. A file cannot forge a field.
|
|
38
|
+
*/
|
|
39
|
+
export interface FlushedRow {
|
|
40
|
+
readonly number: number;
|
|
41
|
+
readonly xml: string;
|
|
42
|
+
/** The `<row>` element's own attributes, exactly as {@link renderRow} emitted them. */
|
|
43
|
+
readonly attrs: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A worksheet's eagerly-serialised rows: each row's `<row>` XML tagged with its number (so it merges
|
|
47
|
+
* into ascending order with the sheet's remaining live rows, whatever order it was committed in), plus
|
|
48
|
+
* the used-cell {@link Extent} they span. The buffered pass folds that extent into the sheet's dimension.
|
|
49
|
+
*/
|
|
50
|
+
export interface FlushedSheet {
|
|
51
|
+
readonly rows: readonly FlushedRow[];
|
|
52
|
+
readonly extent: Extent;
|
|
53
|
+
/**
|
|
54
|
+
* Each flushed row's outline level and hidden flag. Carried across the eviction because both feed
|
|
55
|
+
* whole-sheet derivations made long after the row is gone from the model: `<sheetFormatPr
|
|
56
|
+
* outlineLevelRow>` is the deepest level on the sheet, and `collapsed="1"` rides a summary row only
|
|
57
|
+
* when its whole detail group is hidden, which is a question about *other* rows.
|
|
58
|
+
*
|
|
59
|
+
* Carried as the two inputs rather than the derived flag, because the derivation is a look-ahead a
|
|
60
|
+
* row being finalised cannot do, while its inputs are per-row and known exactly when the row flushes.
|
|
61
|
+
*/
|
|
62
|
+
readonly rowOutline: ReadonlyMap<number, {
|
|
63
|
+
readonly outlineLevel: number;
|
|
64
|
+
readonly hidden: boolean;
|
|
65
|
+
}>;
|
|
66
|
+
/**
|
|
67
|
+
* The notes the flushed rows carried, on the same terms and for the same reason. A note is
|
|
68
|
+
* serialised outside the `<row>`, into the comments and VML parts, and the buffered pass gathers
|
|
69
|
+
* notes by walking the sheet's rows at commit time, which finds nothing on a row whose cells have
|
|
70
|
+
* already been evicted. A hyperlink needs no such record: it lives beside the grid, on the sheet.
|
|
71
|
+
*/
|
|
72
|
+
readonly notes: readonly CommentCell[];
|
|
73
|
+
/**
|
|
74
|
+
* The formulas the flushed rows carried, on the same terms again: whether an array formula's range
|
|
75
|
+
* holds another formula, or shares a cell with another's, is a question about other rows, and the
|
|
76
|
+
* writer asks it of the whole sheet at commit.
|
|
77
|
+
*/
|
|
78
|
+
readonly formulas: readonly FormulaPlacement[];
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* A column's style facets are defaults its cells inherit unless they override them; the writer
|
|
82
|
+
* composes each cell's full style up front (cell over row over column, per facet) so a cell that
|
|
83
|
+
* overrides one facet still carries the column's others, rather than silently dropping them. Frozen
|
|
84
|
+
* once by the streaming writer at its first flush so every eagerly-rendered row sees the same defaults.
|
|
85
|
+
*/
|
|
86
|
+
export declare function buildColumnDefaults(sheet: Worksheet): Map<number, ColumnProperties>;
|
|
87
|
+
/** The whole-sheet context a single row needs to serialise: the column defaults it inherits, the
|
|
88
|
+
* style/string tables it interns into, the shared-formula roles its cells play, and the collapsed
|
|
89
|
+
* outline summaries whose toggle it must stamp. The streaming writer supplies empty shared-formula
|
|
90
|
+
* and collapsed-summary sets, since those are whole-sheet derivations a flushed row cannot join. */
|
|
91
|
+
export interface RowRenderContext {
|
|
92
|
+
readonly columnDefaults: ReadonlyMap<number, ColumnProperties>;
|
|
93
|
+
readonly styles: StyleRegistry;
|
|
94
|
+
readonly sharedStrings: SharedStringTable | null;
|
|
95
|
+
readonly sharedRoles: ReadonlyMap<string, SharedFormulaRole>;
|
|
96
|
+
readonly collapsedSummaries: ReadonlySet<number>;
|
|
97
|
+
/** The workbook's date system, which is what a `Date` cell's serial counts from. */
|
|
98
|
+
readonly dateEpoch: DateEpoch;
|
|
99
|
+
/** The defined names a bare name in this sheet's formulas resolves to, as `formulaNamesInScope`
|
|
100
|
+
* gives them: a function passed as a value is written bare where one of them captures its name. */
|
|
101
|
+
readonly formulaNames: ReadonlySet<string>;
|
|
102
|
+
/** The workbook's metadata, which a dynamic-array formula's cell and a rich-value error's cell point
|
|
103
|
+
* into. Shared by every row of every sheet, since the parts it becomes are the workbook's. */
|
|
104
|
+
readonly cellMetadata: WorkbookMetadataTable;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Serialise one row to its `<row>` element, or '' when the row has neither data nor its own
|
|
108
|
+
* formatting. Returns the used-column bounds (`Infinity`/`-Infinity` when nothing was rendered) so a
|
|
109
|
+
* caller can fold them into the sheet dimension, and the attribute string separately, so a later pass
|
|
110
|
+
* can ask what this row declared without reading it back out of markup that also holds cell text.
|
|
111
|
+
* Shared by the buffered sheet pass and the streaming writer's eager flush, so both emit
|
|
112
|
+
* byte-identical rows.
|
|
113
|
+
*/
|
|
114
|
+
export declare function renderRow(entry: {
|
|
115
|
+
readonly number: number;
|
|
116
|
+
readonly cells: readonly Cell[];
|
|
117
|
+
readonly properties: RowProperties | undefined;
|
|
118
|
+
}, ctx: RowRenderContext): {
|
|
119
|
+
xml: string;
|
|
120
|
+
attrs: string;
|
|
121
|
+
minCol: number;
|
|
122
|
+
maxCol: number;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* The `<row>` element's opening tag up to its first attribute: the one thing a later pass may rely on
|
|
126
|
+
* about a rendered row's shape, spelled here so it is the emitter's own string rather than a
|
|
127
|
+
* re-parse of the emitter's output.
|
|
128
|
+
*/
|
|
129
|
+
export declare function rowOpenTag(number: number): string;
|
|
130
|
+
/**
|
|
131
|
+
* Refuse an outline depth that is not a non-negative integer, naming what carried it.
|
|
132
|
+
*
|
|
133
|
+
* `xsd:unsignedInt` is the attribute's type, so this is what the schema already says. It is asserted
|
|
134
|
+
* rather than clamped because a negative level is also a hang: the writer finds a group's end by
|
|
135
|
+
* walking outwards while the neighbouring level exceeds the summary's, and every unmapped row
|
|
136
|
+
* answers `0`, which exceeds `-1` for as long as there are rows to walk.
|
|
137
|
+
*/
|
|
138
|
+
export declare function assertWritableLevel(name: string, level: number): void;
|
|
139
|
+
export declare function outlineAttr(name: string, level: number | undefined): string;
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { encodeRange, tryDecodeAnchoredRange } from '../../core/address.js';
|
|
2
|
+
import { cellHasOwnStyle } from '../../core/cell.js';
|
|
3
|
+
import { DEFAULT_DATE_NUMFMT, dateToSerial } from '../../core/date.js';
|
|
4
|
+
import { mangleFormula } from '../../core/formula.js';
|
|
5
|
+
import { NAMED_STYLE_ID } from '../../core/internal.js';
|
|
6
|
+
import { CELL_STYLE_FACETS } from '../../core/style.js';
|
|
7
|
+
import { detectValueType, isArrayFormulaValue, isDataTableFormulaValue, isErrorCode, isErrorValue, isFormulaValue, isRichTextValue, isSharedFormulaValue, } from '../../core/value.js';
|
|
8
|
+
import { AuthoringError, InternalError, quoted } from '../../errors.js';
|
|
9
|
+
import { boolAttr, checkedToken, escapeAttr, escapeSpreadsheetText, escapeText, numberText, nonDefaultNumAttr, textAttr, textElement, } from '../../xml/xml.js';
|
|
10
|
+
import { richTextRunsXml } from './rich-text.js';
|
|
11
|
+
export class Extent {
|
|
12
|
+
top = Infinity;
|
|
13
|
+
left = Infinity;
|
|
14
|
+
bottom = -Infinity;
|
|
15
|
+
right = -Infinity;
|
|
16
|
+
constructor(seed) {
|
|
17
|
+
if (seed) {
|
|
18
|
+
this.top = seed.top;
|
|
19
|
+
this.left = seed.left;
|
|
20
|
+
this.bottom = seed.bottom;
|
|
21
|
+
this.right = seed.right;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
get isEmpty() {
|
|
25
|
+
return this.bottom === -Infinity;
|
|
26
|
+
}
|
|
27
|
+
add(row, minCol, maxCol) {
|
|
28
|
+
if (minCol === Infinity)
|
|
29
|
+
return;
|
|
30
|
+
if (row < this.top)
|
|
31
|
+
this.top = row;
|
|
32
|
+
if (row > this.bottom)
|
|
33
|
+
this.bottom = row;
|
|
34
|
+
if (minCol < this.left)
|
|
35
|
+
this.left = minCol;
|
|
36
|
+
if (maxCol > this.right)
|
|
37
|
+
this.right = maxCol;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function buildColumnDefaults(sheet) {
|
|
41
|
+
const columnDefaults = new Map();
|
|
42
|
+
for (const { index, properties } of sheet.columns())
|
|
43
|
+
columnDefaults.set(index, properties ?? {});
|
|
44
|
+
return columnDefaults;
|
|
45
|
+
}
|
|
46
|
+
export function renderRow(entry, ctx) {
|
|
47
|
+
const { number, cells, properties } = entry;
|
|
48
|
+
const rendered = cells.filter((cell) => cell.value !== null || cellHasOwnStyle(cell));
|
|
49
|
+
const attrs = rowAttrs(properties, ctx.styles, ctx.collapsedSummaries.has(number));
|
|
50
|
+
if (rendered.length === 0 && attrs === '') {
|
|
51
|
+
return { xml: '', attrs: '', minCol: Infinity, maxCol: -Infinity };
|
|
52
|
+
}
|
|
53
|
+
const rowFill = properties?.fill;
|
|
54
|
+
const cellsXml = rendered
|
|
55
|
+
.map((cell) => {
|
|
56
|
+
const style = ctx.styles.styleId(composeCellStyle(cell, rowFill, ctx.columnDefaults.get(cell.col)));
|
|
57
|
+
return cellXml(cell, style, ctx.sharedRoles.get(cell.address), ctx);
|
|
58
|
+
})
|
|
59
|
+
.join('');
|
|
60
|
+
let minCol = Infinity;
|
|
61
|
+
let maxCol = -Infinity;
|
|
62
|
+
for (const cell of rendered) {
|
|
63
|
+
if (cell.col < minCol)
|
|
64
|
+
minCol = cell.col;
|
|
65
|
+
if (cell.col > maxCol)
|
|
66
|
+
maxCol = cell.col;
|
|
67
|
+
}
|
|
68
|
+
return { xml: `${rowOpenTag(number)}${attrs}>${cellsXml}</row>`, attrs, minCol, maxCol };
|
|
69
|
+
}
|
|
70
|
+
export function rowOpenTag(number) {
|
|
71
|
+
return `<row r="${number}"`;
|
|
72
|
+
}
|
|
73
|
+
function composeCellStyle(cell, rowFill, colDef) {
|
|
74
|
+
const style = {};
|
|
75
|
+
for (const facet of CELL_STYLE_FACETS)
|
|
76
|
+
inheritFacet(style, facet, cell, colDef);
|
|
77
|
+
style.fill = cell.fill ?? rowFill ?? colDef?.fill;
|
|
78
|
+
style.numFmt = cell.numFmt ?? colDef?.numFmt ?? dateDefaultNumFmt(cell.value);
|
|
79
|
+
if (cell.quotePrefix !== undefined)
|
|
80
|
+
style.quotePrefix = cell.quotePrefix;
|
|
81
|
+
const xfId = cell[NAMED_STYLE_ID];
|
|
82
|
+
if (xfId !== undefined)
|
|
83
|
+
style.xfId = xfId;
|
|
84
|
+
return style;
|
|
85
|
+
}
|
|
86
|
+
function inheritFacet(target, key, cell, colDef) {
|
|
87
|
+
target[key] = cell[key] ?? colDef?.[key];
|
|
88
|
+
}
|
|
89
|
+
function rowAttrs(properties, styles, collapsedSummary) {
|
|
90
|
+
if (properties === undefined)
|
|
91
|
+
return collapsedSummary ? ' collapsed="1"' : '';
|
|
92
|
+
let attrs = '';
|
|
93
|
+
if (properties.height !== undefined)
|
|
94
|
+
attrs += ` ht="${numberText(properties.height)}" customHeight="1"`;
|
|
95
|
+
if (properties.hidden)
|
|
96
|
+
attrs += ' hidden="1"';
|
|
97
|
+
attrs += outlineAttr('outlineLevel', properties.outlineLevel);
|
|
98
|
+
if (properties.collapsed || collapsedSummary)
|
|
99
|
+
attrs += ' collapsed="1"';
|
|
100
|
+
const style = styles.styleId({ fill: properties.fill });
|
|
101
|
+
if (style !== 0)
|
|
102
|
+
attrs += ` s="${style}" customFormat="1"`;
|
|
103
|
+
return attrs;
|
|
104
|
+
}
|
|
105
|
+
function dateDefaultNumFmt(value) {
|
|
106
|
+
const date = value instanceof Date
|
|
107
|
+
? value
|
|
108
|
+
: (isFormulaValue(value) || isSharedFormulaValue(value) || isArrayFormulaValue(value)) &&
|
|
109
|
+
value.result instanceof Date
|
|
110
|
+
? value.result
|
|
111
|
+
: undefined;
|
|
112
|
+
return date !== undefined && !Number.isNaN(date.getTime()) ? DEFAULT_DATE_NUMFMT : undefined;
|
|
113
|
+
}
|
|
114
|
+
function cellElement(ref, s, type, body, cm = '', vm = '') {
|
|
115
|
+
const attrs = `${s}${type === '' ? '' : ` t="${type}"`}${cm}${vm}`;
|
|
116
|
+
return body === '' ? `<c r="${ref}"${attrs}/>` : `<c r="${ref}"${attrs}>${body}</c>`;
|
|
117
|
+
}
|
|
118
|
+
const UNWRITABLE = { type: '', v: null };
|
|
119
|
+
const vElement = (v) => (v === null ? '' : `<v>${v}</v>`);
|
|
120
|
+
function valueBody(value, ctx) {
|
|
121
|
+
if (typeof value === 'number') {
|
|
122
|
+
return Number.isFinite(value) ? { type: '', v: numberText(value) } : UNWRITABLE;
|
|
123
|
+
}
|
|
124
|
+
if (typeof value === 'boolean')
|
|
125
|
+
return { type: 'b', v: value ? '1' : '0' };
|
|
126
|
+
if (value instanceof Date) {
|
|
127
|
+
return Number.isNaN(value.getTime())
|
|
128
|
+
? UNWRITABLE
|
|
129
|
+
: { type: '', v: numberText(dateToSerial(value, ctx.dateEpoch)) };
|
|
130
|
+
}
|
|
131
|
+
if (isErrorValue(value)) {
|
|
132
|
+
checkedToken(value.error, isErrorCode, 'cell error value');
|
|
133
|
+
const vm = ctx.cellMetadata.markRichValueError(value.error);
|
|
134
|
+
return vm === undefined
|
|
135
|
+
? { type: 'e', v: value.error }
|
|
136
|
+
: { type: 'e', v: '#VALUE!', vm: ` vm="${vm}"` };
|
|
137
|
+
}
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
function cellXml(cell, style, shared, ctx) {
|
|
141
|
+
const { sharedStrings } = ctx;
|
|
142
|
+
const ref = cell.address;
|
|
143
|
+
const value = cell.value;
|
|
144
|
+
const s = style !== 0 ? ` s="${style}"` : '';
|
|
145
|
+
const formula = cellFormulaXml(cell, s, shared, ctx);
|
|
146
|
+
if (formula !== undefined)
|
|
147
|
+
return formula;
|
|
148
|
+
const body = valueBody(value, ctx);
|
|
149
|
+
if (body !== undefined)
|
|
150
|
+
return cellElement(ref, s, body.type, vElement(body.v), '', body.vm);
|
|
151
|
+
if (typeof value === 'string' || isRichTextValue(value)) {
|
|
152
|
+
if (sharedStrings !== null) {
|
|
153
|
+
return cellElement(ref, s, 's', vElement(`${sharedStrings.intern(value)}`));
|
|
154
|
+
}
|
|
155
|
+
const inline = typeof value === 'string' ? textElement(value) : richTextRunsXml(value.richText);
|
|
156
|
+
return cellElement(ref, s, 'inlineStr', `<is>${inline}</is>`);
|
|
157
|
+
}
|
|
158
|
+
if (value === null)
|
|
159
|
+
return cellElement(ref, s, '', '');
|
|
160
|
+
throw new InternalError(`writing a ${detectValueType(value)} cell value has no arm: every CellValue kind is handled above`);
|
|
161
|
+
}
|
|
162
|
+
function cellFormulaXml(cell, s, shared, ctx) {
|
|
163
|
+
const { formulaNames } = ctx;
|
|
164
|
+
const { address: ref, value } = cell;
|
|
165
|
+
if (shared !== undefined) {
|
|
166
|
+
if (shared.ref !== undefined && isFormulaValue(value)) {
|
|
167
|
+
const f = `<f t="shared" ref="${shared.ref}" si="${shared.si}">${escapeText(mangleFormula(value.formula, formulaNames))}</f>`;
|
|
168
|
+
return formulaBodyXml(ref, s, f, value.result, ctx);
|
|
169
|
+
}
|
|
170
|
+
const result = isSharedFormulaValue(value) ? value.result : undefined;
|
|
171
|
+
return formulaBodyXml(ref, s, `<f t="shared" si="${shared.si}"/>`, result, ctx);
|
|
172
|
+
}
|
|
173
|
+
if (isDataTableFormulaValue(value)) {
|
|
174
|
+
const attrs = `ref="${escapeAttr(value.ref)}"` +
|
|
175
|
+
boolAttr('dt2D', value.dataTable2D) +
|
|
176
|
+
boolAttr('dtr', value.dataTableRow) +
|
|
177
|
+
(value.r1Deleted === true ? ' del1="1"' : '') +
|
|
178
|
+
(value.r2Deleted === true ? ' del2="1"' : '') +
|
|
179
|
+
textAttr('r1', value.r1) +
|
|
180
|
+
textAttr('r2', value.r2);
|
|
181
|
+
return formulaBodyXml(ref, s, `<f t="dataTable" ${attrs}/>`, value.result, ctx);
|
|
182
|
+
}
|
|
183
|
+
if (isArrayFormulaValue(value)) {
|
|
184
|
+
const cm = value.dynamic === true ? ` cm="${ctx.cellMetadata.markDynamicArray()}"` : '';
|
|
185
|
+
const f = `<f t="array" ref="${arrayFormulaRange(cell, value.ref)}">${escapeText(mangleFormula(value.formula, formulaNames))}</f>`;
|
|
186
|
+
return formulaBodyXml(ref, s, f, value.result, ctx, cm);
|
|
187
|
+
}
|
|
188
|
+
if (isFormulaValue(value)) {
|
|
189
|
+
return formulaBodyXml(ref, s, `<f>${escapeText(mangleFormula(value.formula, formulaNames))}</f>`, value.result, ctx);
|
|
190
|
+
}
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
function arrayFormulaRange(cell, ref) {
|
|
194
|
+
const range = tryDecodeAnchoredRange(ref, cell.col, cell.row);
|
|
195
|
+
if (range === undefined) {
|
|
196
|
+
throw new AuthoringError(`the array formula in ${cell.address} fills ${quoted(ref)}, which is not a range starting at ${cell.address}`);
|
|
197
|
+
}
|
|
198
|
+
return encodeRange(range);
|
|
199
|
+
}
|
|
200
|
+
function formulaBodyXml(ref, s, f, result, ctx, cm = '') {
|
|
201
|
+
if (result === undefined)
|
|
202
|
+
return cellElement(ref, s, '', f, cm);
|
|
203
|
+
const body = valueBody(result, ctx);
|
|
204
|
+
if (body !== undefined) {
|
|
205
|
+
return cellElement(ref, s, body.type, f + vElement(body.v), cm, body.vm);
|
|
206
|
+
}
|
|
207
|
+
if (typeof result === 'string') {
|
|
208
|
+
return cellElement(ref, s, 'str', f + vElement(escapeSpreadsheetText(result)), cm);
|
|
209
|
+
}
|
|
210
|
+
throw new InternalError('writing a non-primitive formula result has no arm: every FormulaResult kind is handled above');
|
|
211
|
+
}
|
|
212
|
+
export function assertWritableLevel(name, level) {
|
|
213
|
+
if (Number.isInteger(level) && level >= 0)
|
|
214
|
+
return;
|
|
215
|
+
throw new AuthoringError(`${name} must be a non-negative integer, not ${level}`);
|
|
216
|
+
}
|
|
217
|
+
export function outlineAttr(name, level) {
|
|
218
|
+
if (level === undefined)
|
|
219
|
+
return '';
|
|
220
|
+
assertWritableLevel(name, level);
|
|
221
|
+
return nonDefaultNumAttr(name, level, 0);
|
|
222
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { encodeRect } from '../../core/address.js';
|
|
2
2
|
import { isFormulaValue, isSharedFormulaValue } from '../../core/value.js';
|
|
3
3
|
import { AuthoringError } from '../../errors.js';
|
|
4
4
|
export function planSharedFormulas(sheet) {
|
|
@@ -35,7 +35,7 @@ export function planSharedFormulas(sheet) {
|
|
|
35
35
|
}
|
|
36
36
|
roles.set(masterAddress, {
|
|
37
37
|
si,
|
|
38
|
-
ref:
|
|
38
|
+
ref: encodeRect({ top: master.row, left: master.col, bottom: maxRow, right: maxCol }),
|
|
39
39
|
});
|
|
40
40
|
for (const clone of clones)
|
|
41
41
|
roles.set(clone.address, { si });
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AutoFilter } from '../../core/autofilter.ts';
|
|
2
2
|
import { type HeaderFooter, type PageBreak, type PageMargins, type PageSetup, type PrintOptions } from '../../core/page-setup.ts';
|
|
3
3
|
import { type SheetProtection } from '../../core/protection.ts';
|
|
4
4
|
import type { SheetView, Worksheet } from '../../core/worksheet.ts';
|
|
5
|
+
import { type XmlAttributes } from '../../xml/xml-scan.ts';
|
|
5
6
|
export declare function sheetViewsXml(view: SheetView, active: boolean): string;
|
|
6
7
|
export declare function sheetPrXml(sheet: Worksheet): string;
|
|
7
8
|
export declare function sheetProtectionXml(protection: SheetProtection | undefined): string;
|
|
@@ -11,3 +12,11 @@ export declare function printOptionsXml(printOptions: PrintOptions): string;
|
|
|
11
12
|
export declare function pageMarginsXml(margins: PageMargins): string;
|
|
12
13
|
export declare function pageSetupXml(pageSetup: PageSetup, printerSettingsRelId: string | null): string;
|
|
13
14
|
export declare function pageBreaksXml(breaks: readonly PageBreak[], element: 'rowBreaks' | 'colBreaks'): string;
|
|
15
|
+
export declare function parseSheetProtection(attrs: XmlAttributes): SheetProtection | undefined;
|
|
16
|
+
export declare class PageBreakAccumulator {
|
|
17
|
+
#private;
|
|
18
|
+
begin(target: PageBreak[]): void;
|
|
19
|
+
end(): void;
|
|
20
|
+
add(attrs: XmlAttributes): void;
|
|
21
|
+
}
|
|
22
|
+
export declare function applySheetProperties(local: string, attrs: XmlAttributes, sheet: Worksheet): void;
|
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
import { encodeAddress } from '../../core/address.js';
|
|
1
|
+
import { encodeAddress, MAX_COLUMN, MAX_ROW } from '../../core/address.js';
|
|
2
|
+
import { isCustomFilterOperator, } from '../../core/autofilter.js';
|
|
2
3
|
import { HEADER_FOOTER_ELEMENTS, MARGIN_SIDES, PAGE_SETUP_FACETS, PRINT_OPTION_FLAGS, } from '../../core/page-setup.js';
|
|
3
|
-
import { SHEET_PROTECTION_FLAGS } from '../../core/protection.js';
|
|
4
|
+
import { isLegacyPasswordHash, SHEET_PROTECTION_FLAGS, } from '../../core/protection.js';
|
|
5
|
+
import { assertWritableNumber, AuthoringError } from '../../errors.js';
|
|
6
|
+
import { numFinite, numInteger } from '../../xml/xml-attrs.js';
|
|
7
|
+
import { boolStrict, boolTristate } from '../../xml/xml-scan.js';
|
|
4
8
|
import { boolAttr, checkedToken, escapeAttr, escapeSpreadsheetText, numAttr, numberText, } from '../../xml/xml.js';
|
|
5
|
-
import { colorAttrs } from './color-xml.js';
|
|
9
|
+
import { colorAttrs, parseColor } from './color-xml.js';
|
|
6
10
|
export function sheetViewsXml(view, active) {
|
|
7
11
|
const selected = active ? ' tabSelected="1"' : '';
|
|
8
12
|
const gridLines = view.showGridLines === false ? ' showGridLines="0"' : '';
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
const normal = `<sheetViews><sheetView${gridLines}${selected} workbookViewId="0"/></sheetViews>`;
|
|
14
|
+
if (view.state !== 'frozen')
|
|
15
|
+
return normal;
|
|
16
|
+
const xSplit = frozenSplit('xSplit', view.xSplit, MAX_COLUMN);
|
|
17
|
+
const ySplit = frozenSplit('ySplit', view.ySplit, MAX_ROW);
|
|
18
|
+
if (xSplit === 0 && ySplit === 0)
|
|
19
|
+
return normal;
|
|
14
20
|
const topLeftCell = view.topLeftCell ?? encodeAddress(xSplit + 1, ySplit + 1);
|
|
15
21
|
const activePane = xSplit > 0 && ySplit > 0 ? 'bottomRight' : xSplit > 0 ? 'topRight' : 'bottomLeft';
|
|
16
22
|
const pane = '<pane' +
|
|
@@ -20,11 +26,23 @@ export function sheetViewsXml(view, active) {
|
|
|
20
26
|
const selection = `<selection pane="${activePane}" activeCell="${escapeAttr(topLeftCell)}" sqref="${escapeAttr(topLeftCell)}"/>`;
|
|
21
27
|
return `<sheetViews><sheetView${gridLines}${selected} workbookViewId="0">${pane}${selection}</sheetView></sheetViews>`;
|
|
22
28
|
}
|
|
29
|
+
function frozenSplit(name, value, lines) {
|
|
30
|
+
if (value === undefined)
|
|
31
|
+
return 0;
|
|
32
|
+
assertWritableNumber(value);
|
|
33
|
+
if (!Number.isInteger(value) || value < 0 || value >= lines) {
|
|
34
|
+
throw new AuthoringError(`cannot write ${name}="${value}": a frozen split is a whole count from 0 to ${lines - 1}`);
|
|
35
|
+
}
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
23
38
|
export function sheetPrXml(sheet) {
|
|
39
|
+
const attrs = sheet.codeName === undefined ? '' : ` codeName="${escapeAttr(sheet.codeName)}"`;
|
|
24
40
|
const children = (sheet.tabColor !== undefined ? `<tabColor ${colorAttrs(sheet.tabColor)}/>` : '') +
|
|
25
41
|
outlinePrXml(sheet.outline) +
|
|
26
42
|
pageSetUpPrXml(sheet.pageSetup);
|
|
27
|
-
|
|
43
|
+
if (attrs === '' && children === '')
|
|
44
|
+
return '';
|
|
45
|
+
return children === '' ? `<sheetPr${attrs}/>` : `<sheetPr${attrs}>${children}</sheetPr>`;
|
|
28
46
|
}
|
|
29
47
|
function pageSetUpPrXml(pageSetup) {
|
|
30
48
|
return pageSetup.fitToPage ? '<pageSetUpPr fitToPage="1"/>' : '';
|
|
@@ -36,14 +54,17 @@ function outlinePrXml(outline) {
|
|
|
36
54
|
export function sheetProtectionXml(protection) {
|
|
37
55
|
if (protection === undefined)
|
|
38
56
|
return '';
|
|
39
|
-
const { flags, credential } = protection;
|
|
57
|
+
const { flags, credential, legacyPasswordHash } = protection;
|
|
40
58
|
let attrs = '';
|
|
59
|
+
if (legacyPasswordHash !== undefined) {
|
|
60
|
+
attrs += ` password="${checkedToken(legacyPasswordHash, isLegacyPasswordHash, 'legacy sheet password hash')}"`;
|
|
61
|
+
}
|
|
41
62
|
if (credential !== undefined) {
|
|
42
63
|
attrs +=
|
|
43
|
-
` algorithmName="${credential.algorithmName}"` +
|
|
44
|
-
` hashValue="${credential.hashValue}"` +
|
|
45
|
-
` saltValue="${credential.saltValue}"` +
|
|
46
|
-
|
|
64
|
+
` algorithmName="${escapeAttr(credential.algorithmName)}"` +
|
|
65
|
+
` hashValue="${escapeAttr(credential.hashValue)}"` +
|
|
66
|
+
` saltValue="${escapeAttr(credential.saltValue)}"` +
|
|
67
|
+
numAttr('spinCount', credential.spinCount);
|
|
47
68
|
}
|
|
48
69
|
attrs += ' sheet="1"';
|
|
49
70
|
for (const { key, defaultForbidden } of SHEET_PROTECTION_FLAGS) {
|
|
@@ -66,7 +87,7 @@ export function autoFilterXml(filter) {
|
|
|
66
87
|
return `<autoFilter ref="${ref}">${filter.columns.map(filterColumnXml).join('')}</autoFilter>`;
|
|
67
88
|
}
|
|
68
89
|
function filterColumnXml(column) {
|
|
69
|
-
return `<filterColumn colId="${column.colId}">${filterCriteriaXml(column.criteria)}</filterColumn>`;
|
|
90
|
+
return `<filterColumn colId="${numberText(column.colId)}">${filterCriteriaXml(column.criteria)}</filterColumn>`;
|
|
70
91
|
}
|
|
71
92
|
function filterCriteriaXml(criteria) {
|
|
72
93
|
if (criteria.kind === 'values') {
|
|
@@ -76,7 +97,7 @@ function filterCriteriaXml(criteria) {
|
|
|
76
97
|
}
|
|
77
98
|
const andAttr = criteria.and ? ' and="1"' : '';
|
|
78
99
|
const predicates = criteria.predicates
|
|
79
|
-
.map((p) => `<customFilter operator="${p.operator}" val="${escapeAttr(p.val)}"/>`)
|
|
100
|
+
.map((p) => `<customFilter operator="${checkedToken(p.operator, isCustomFilterOperator, 'custom filter operator')}" val="${escapeAttr(p.val)}"/>`)
|
|
80
101
|
.join('');
|
|
81
102
|
return `<customFilters${andAttr}>${predicates}</customFilters>`;
|
|
82
103
|
}
|
|
@@ -137,10 +158,151 @@ export function pageSetupXml(pageSetup, printerSettingsRelId) {
|
|
|
137
158
|
export function pageBreaksXml(breaks, element) {
|
|
138
159
|
if (breaks.length === 0)
|
|
139
160
|
return '';
|
|
161
|
+
const manual = breaks.filter((brk) => brk.man !== false).length;
|
|
140
162
|
const brks = breaks
|
|
141
|
-
.map((brk) => {
|
|
142
|
-
|
|
143
|
-
})
|
|
163
|
+
.map((brk) => `<brk${numAttr('id', brk.id)}${numAttr('min', brk.min)}${numAttr('max', brk.max)}` +
|
|
164
|
+
`${brk.man === false ? '' : ' man="1"'}/>`)
|
|
144
165
|
.join('');
|
|
145
|
-
return `<${element} count="${breaks.length}" manualBreakCount="${
|
|
166
|
+
return `<${element} count="${breaks.length}" manualBreakCount="${manual}">${brks}</${element}>`;
|
|
167
|
+
}
|
|
168
|
+
export function parseSheetProtection(attrs) {
|
|
169
|
+
if (!boolStrict(attrs.sheet))
|
|
170
|
+
return undefined;
|
|
171
|
+
const flags = {};
|
|
172
|
+
for (const { key } of SHEET_PROTECTION_FLAGS) {
|
|
173
|
+
const raw = attrs[key];
|
|
174
|
+
if (raw !== undefined)
|
|
175
|
+
flags[key] = !boolStrict(raw);
|
|
176
|
+
}
|
|
177
|
+
const { algorithmName, hashValue, saltValue, spinCount } = attrs;
|
|
178
|
+
const spin = numInteger(spinCount, 0);
|
|
179
|
+
if (algorithmName !== undefined &&
|
|
180
|
+
hashValue !== undefined &&
|
|
181
|
+
saltValue !== undefined &&
|
|
182
|
+
spin !== undefined) {
|
|
183
|
+
const credential = {
|
|
184
|
+
algorithmName,
|
|
185
|
+
hashValue,
|
|
186
|
+
saltValue,
|
|
187
|
+
spinCount: spin,
|
|
188
|
+
};
|
|
189
|
+
return { flags, credential, ...legacyHash(attrs.password) };
|
|
190
|
+
}
|
|
191
|
+
return { flags, ...legacyHash(attrs.password) };
|
|
192
|
+
}
|
|
193
|
+
function legacyHash(password) {
|
|
194
|
+
return password !== undefined && isLegacyPasswordHash(password)
|
|
195
|
+
? { legacyPasswordHash: password }
|
|
196
|
+
: {};
|
|
197
|
+
}
|
|
198
|
+
export class PageBreakAccumulator {
|
|
199
|
+
#target = null;
|
|
200
|
+
begin(target) {
|
|
201
|
+
this.#target = target;
|
|
202
|
+
}
|
|
203
|
+
end() {
|
|
204
|
+
this.#target = null;
|
|
205
|
+
}
|
|
206
|
+
add(attrs) {
|
|
207
|
+
if (this.#target === null)
|
|
208
|
+
return;
|
|
209
|
+
const id = numInteger(attrs.id, 1);
|
|
210
|
+
if (id === undefined)
|
|
211
|
+
return;
|
|
212
|
+
const brk = {
|
|
213
|
+
id,
|
|
214
|
+
man: boolStrict(attrs.man),
|
|
215
|
+
};
|
|
216
|
+
const min = numInteger(attrs.min, 0);
|
|
217
|
+
if (min !== undefined)
|
|
218
|
+
brk.min = min;
|
|
219
|
+
const max = numInteger(attrs.max, 0);
|
|
220
|
+
if (max !== undefined)
|
|
221
|
+
brk.max = max;
|
|
222
|
+
this.#target.push(brk);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
export function applySheetProperties(local, attrs, sheet) {
|
|
226
|
+
switch (local) {
|
|
227
|
+
case 'sheetPr':
|
|
228
|
+
if (attrs.codeName !== undefined)
|
|
229
|
+
sheet.codeName = attrs.codeName;
|
|
230
|
+
break;
|
|
231
|
+
case 'tabColor':
|
|
232
|
+
sheet.tabColor = parseColor(attrs);
|
|
233
|
+
break;
|
|
234
|
+
case 'outlinePr':
|
|
235
|
+
for (const flag of ['summaryBelow', 'summaryRight']) {
|
|
236
|
+
const value = boolTristate(attrs[flag]);
|
|
237
|
+
if (value !== undefined)
|
|
238
|
+
sheet.outline[flag] = value;
|
|
239
|
+
}
|
|
240
|
+
break;
|
|
241
|
+
case 'sheetView':
|
|
242
|
+
if (boolTristate(attrs.showGridLines) === false) {
|
|
243
|
+
sheet.view.showGridLines = false;
|
|
244
|
+
}
|
|
245
|
+
break;
|
|
246
|
+
case 'pane':
|
|
247
|
+
if (attrs.state === 'frozen' || attrs.state === 'frozenSplit') {
|
|
248
|
+
sheet.view.state = 'frozen';
|
|
249
|
+
const xSplit = numInteger(attrs.xSplit, 0);
|
|
250
|
+
const ySplit = numInteger(attrs.ySplit, 0);
|
|
251
|
+
if (xSplit !== undefined && xSplit < MAX_COLUMN)
|
|
252
|
+
sheet.view.xSplit = xSplit;
|
|
253
|
+
if (ySplit !== undefined && ySplit < MAX_ROW)
|
|
254
|
+
sheet.view.ySplit = ySplit;
|
|
255
|
+
if (attrs.topLeftCell !== undefined)
|
|
256
|
+
sheet.view.topLeftCell = attrs.topLeftCell;
|
|
257
|
+
}
|
|
258
|
+
break;
|
|
259
|
+
case 'pageSetUpPr':
|
|
260
|
+
if (boolTristate(attrs.fitToPage) !== undefined) {
|
|
261
|
+
sheet.pageSetup.fitToPage = boolStrict(attrs.fitToPage);
|
|
262
|
+
}
|
|
263
|
+
break;
|
|
264
|
+
case 'printOptions':
|
|
265
|
+
applyPrintOptions(sheet.printOptions, attrs);
|
|
266
|
+
break;
|
|
267
|
+
case 'pageMargins':
|
|
268
|
+
applyMargins(sheet.pageMargins, attrs);
|
|
269
|
+
break;
|
|
270
|
+
case 'pageSetup':
|
|
271
|
+
applyPageSetup(sheet.pageSetup, attrs);
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function applyPrintOptions(printOptions, attrs) {
|
|
276
|
+
for (const flag of PRINT_OPTION_FLAGS) {
|
|
277
|
+
const value = boolTristate(attrs[flag]);
|
|
278
|
+
if (value !== undefined)
|
|
279
|
+
printOptions[flag] = value;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function applyMargins(margins, attrs) {
|
|
283
|
+
for (const side of MARGIN_SIDES) {
|
|
284
|
+
const value = numFinite(attrs[side]);
|
|
285
|
+
if (value !== undefined)
|
|
286
|
+
margins[side] = value;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function applyPageSetup(pageSetup, attrs) {
|
|
290
|
+
for (const facet of PAGE_SETUP_FACETS) {
|
|
291
|
+
const raw = attrs[facet.key];
|
|
292
|
+
if (facet.kind === 'count') {
|
|
293
|
+
const value = numInteger(raw, 0);
|
|
294
|
+
if (value !== undefined)
|
|
295
|
+
pageSetup[facet.key] = value;
|
|
296
|
+
}
|
|
297
|
+
else if (raw === undefined) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
else if (facet.key === 'pageOrder') {
|
|
301
|
+
if (facet.isValid(raw))
|
|
302
|
+
pageSetup.pageOrder = raw;
|
|
303
|
+
}
|
|
304
|
+
else if (facet.isValid(raw)) {
|
|
305
|
+
pageSetup.orientation = raw;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
146
308
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A package part's bytes in Transitional: an XML part declaring a Strict namespace has its
|
|
3
|
+
* declarations and its percentages translated, and any other part is handed back as the same bytes.
|
|
4
|
+
* Only the opening tags that change are re-rendered, so everything else in the part rides through byte
|
|
5
|
+
* for byte. A part the scanner cannot read is left as it came, as it would have been carried.
|
|
6
|
+
*/
|
|
7
|
+
export declare function transitionalPart(bytes: Uint8Array, contentType: string): Uint8Array;
|