@shbernal/ts-xlsx 2.1.0 → 3.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/dist/core/autofilter.d.ts +1 -1
- package/dist/core/autofilter.js +3 -5
- package/dist/core/axis-handle.d.ts +8 -0
- package/dist/core/axis-handle.js +14 -0
- package/dist/core/cell.d.ts +24 -0
- package/dist/core/cell.js +9 -1
- package/dist/core/column.d.ts +4 -1
- package/dist/core/column.js +31 -35
- package/dist/core/conditional-formatting.d.ts +5 -5
- package/dist/core/conditional-formatting.js +11 -25
- package/dist/core/data-validation.d.ts +3 -3
- package/dist/core/data-validation.js +7 -15
- package/dist/core/image.d.ts +1 -1
- package/dist/core/image.js +2 -4
- package/dist/core/merge-index.d.ts +31 -0
- package/dist/core/merge-index.js +60 -0
- package/dist/core/merge.d.ts +0 -10
- package/dist/core/merge.js +0 -8
- package/dist/core/page-setup.d.ts +72 -2
- package/dist/core/page-setup.js +34 -8
- package/dist/core/pivot-table.d.ts +1 -1
- package/dist/core/pivot-table.js +4 -8
- package/dist/core/row.d.ts +4 -1
- package/dist/core/row.js +19 -23
- package/dist/core/style.d.ts +51 -7
- package/dist/core/style.js +29 -34
- package/dist/core/table.d.ts +1 -1
- package/dist/core/table.js +3 -5
- package/dist/core/used-extent.d.ts +44 -0
- package/dist/core/used-extent.js +102 -0
- package/dist/core/worksheet.d.ts +17 -6
- package/dist/core/worksheet.js +48 -42
- package/dist/customui/ribbon.js +4 -6
- package/dist/io/opc/inflate.js +1 -1
- package/dist/io/opc/part-paths.d.ts +1 -0
- package/dist/io/opc/part-paths.js +15 -0
- package/dist/io/opc/read-opc.d.ts +22 -3
- package/dist/io/opc/read-opc.js +11 -39
- package/dist/io/opc/rels.d.ts +1 -6
- package/dist/io/opc/rels.js +1 -4
- package/dist/io/style/xf-style.d.ts +26 -2
- package/dist/io/style/xf-style.js +6 -0
- package/dist/io/xlsb/read-styles.js +6 -3
- package/dist/io/xlsb/read.d.ts +1 -1
- package/dist/io/xlsb/read.js +5 -8
- package/dist/io/xlsx/cell-accumulator.d.ts +1 -1
- package/dist/io/xlsx/cell-accumulator.js +1 -1
- package/dist/io/xlsx/cell-value.js +1 -1
- package/dist/io/xlsx/color-xml.js +1 -1
- package/dist/io/xlsx/comments.js +2 -1
- package/dist/io/xlsx/conditional-formatting.d.ts +3 -2
- package/dist/io/xlsx/conditional-formatting.js +22 -21
- package/dist/io/xlsx/data-validation.d.ts +9 -7
- package/dist/io/xlsx/data-validation.js +10 -9
- package/dist/io/xlsx/edit-vba.js +4 -11
- package/dist/io/xlsx/hyperlinks.d.ts +4 -2
- package/dist/io/xlsx/hyperlinks.js +20 -17
- package/dist/io/xlsx/images.js +15 -14
- package/dist/io/xlsx/package-plan.d.ts +9 -1
- package/dist/io/xlsx/package-plan.js +29 -16
- package/dist/io/xlsx/part-names.d.ts +41 -0
- package/dist/io/xlsx/part-names.js +46 -0
- package/dist/io/xlsx/read-pivot.js +2 -1
- package/dist/io/xlsx/read-rows.js +12 -13
- package/dist/io/xlsx/read-shared-strings.js +2 -1
- package/dist/io/xlsx/read-styles.d.ts +1 -1
- package/dist/io/xlsx/read-styles.js +63 -42
- package/dist/io/xlsx/read-worksheet.d.ts +10 -1
- package/dist/io/xlsx/read-worksheet.js +43 -56
- package/dist/io/xlsx/read.d.ts +2 -3
- package/dist/io/xlsx/read.js +81 -73
- package/dist/io/xlsx/rich-runs.d.ts +1 -1
- package/dist/io/xlsx/rich-runs.js +2 -1
- package/dist/io/xlsx/sheet-properties.js +21 -28
- package/dist/io/xlsx/styles.js +23 -20
- package/dist/io/xlsx/tables.js +2 -1
- package/dist/io/xlsx/theme-xml.js +1 -1
- package/dist/io/xlsx/threaded-comments.js +2 -1
- package/dist/io/xlsx/workbook-xml.js +29 -28
- package/dist/io/xlsx/worksheet-xml.d.ts +1 -1
- package/dist/io/xlsx/worksheet-xml.js +14 -16
- package/dist/io/xlsx/write-stream.d.ts +6 -0
- package/dist/io/xlsx/write-stream.js +30 -22
- package/dist/io/xlsx/write.d.ts +5 -0
- package/dist/io/xlsx/write.js +155 -131
- package/dist/token-set.d.ts +15 -0
- package/dist/token-set.js +4 -0
- package/dist/vba/cfb-format.d.ts +24 -0
- package/dist/vba/cfb-format.js +12 -0
- package/dist/vba/cfb-writer.js +17 -17
- package/dist/vba/cfb.js +1 -7
- package/dist/vba/ms-ovba.js +32 -11
- package/dist/vba/project.js +13 -13
- package/dist/vba/vba-encoding.js +1 -1
- package/dist/xml/xml-read.d.ts +59 -74
- package/dist/xml/xml-read.js +83 -176
- package/dist/xml/xml-scan.d.ts +100 -0
- package/dist/xml/xml-scan.js +208 -0
- package/dist/xml/xml.d.ts +1 -1
- package/package.json +2 -3
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AssertNever } from './internal.ts';
|
|
1
2
|
/**
|
|
2
3
|
* Paper orientation, as `<pageSetup orientation>` carries it.
|
|
3
4
|
*
|
|
@@ -7,11 +8,11 @@
|
|
|
7
8
|
*/
|
|
8
9
|
export type PageOrientation = 'portrait' | 'landscape';
|
|
9
10
|
/** Narrow a raw `<pageSetup orientation>` token to a known {@link PageOrientation}. */
|
|
10
|
-
export declare
|
|
11
|
+
export declare const isPageOrientation: (value: string) => value is PageOrientation;
|
|
11
12
|
/** The order pages are numbered and printed in across a sheet wider and taller than one page. */
|
|
12
13
|
export type PageOrder = 'downThenOver' | 'overThenDown';
|
|
13
14
|
/** Narrow a raw `<pageSetup pageOrder>` token to a known {@link PageOrder}. */
|
|
14
|
-
export declare
|
|
15
|
+
export declare const isPageOrder: (value: string) => value is PageOrder;
|
|
15
16
|
/**
|
|
16
17
|
* Print-scaling and orientation settings. These map onto two OOXML elements: `fitToPage` is the
|
|
17
18
|
* `<pageSetUpPr>` flag (a `<sheetPr>` child) that switches Excel from fixed-zoom to fit-to-page
|
|
@@ -47,6 +48,61 @@ export interface PageSetup {
|
|
|
47
48
|
*/
|
|
48
49
|
printerSettings?: Uint8Array;
|
|
49
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* How one `<pageSetup>` attribute encodes: which model key it is and what kind of value it carries.
|
|
53
|
+
*
|
|
54
|
+
* Format-blind on purpose, the same way {@link AlignmentFacet} is: `PageSetup` is a core type and
|
|
55
|
+
* the layering gate forbids core importing a serialisation, so the table states what an attribute
|
|
56
|
+
* *is* and each codec supplies the reading and the writing off the `kind`. The OOXML attribute name
|
|
57
|
+
* is the model key throughout, so it is not restated.
|
|
58
|
+
*/
|
|
59
|
+
export type PageSetupFacet = {
|
|
60
|
+
readonly key: 'paperSize' | 'scale' | 'fitToWidth' | 'fitToHeight';
|
|
61
|
+
/** A non-negative integer: a page count, a percentage, or a paper-size id. */
|
|
62
|
+
readonly kind: 'count';
|
|
63
|
+
} | {
|
|
64
|
+
readonly key: 'pageOrder' | 'orientation';
|
|
65
|
+
readonly kind: 'token';
|
|
66
|
+
/** The enumeration guard, and what to call it in the error when a value fails it. */
|
|
67
|
+
readonly isValid: (value: string) => boolean;
|
|
68
|
+
readonly label: string;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* The six `<pageSetup>` attributes, declared once, in CT_PageSetup order. Both directions key off
|
|
72
|
+
* this list, so an attribute written but not read (it survives a re-write and vanishes on load) or
|
|
73
|
+
* read but not written is a compile error rather than something a reviewer has to notice.
|
|
74
|
+
*/
|
|
75
|
+
export declare const PAGE_SETUP_FACETS: readonly [{
|
|
76
|
+
readonly key: 'paperSize';
|
|
77
|
+
readonly kind: 'count';
|
|
78
|
+
}, {
|
|
79
|
+
readonly key: 'scale';
|
|
80
|
+
readonly kind: 'count';
|
|
81
|
+
}, {
|
|
82
|
+
readonly key: 'fitToWidth';
|
|
83
|
+
readonly kind: 'count';
|
|
84
|
+
}, {
|
|
85
|
+
readonly key: 'fitToHeight';
|
|
86
|
+
readonly kind: 'count';
|
|
87
|
+
}, {
|
|
88
|
+
readonly key: 'pageOrder';
|
|
89
|
+
readonly kind: 'token';
|
|
90
|
+
readonly isValid: (value: string) => value is PageOrder;
|
|
91
|
+
readonly label: 'page order';
|
|
92
|
+
}, {
|
|
93
|
+
readonly key: 'orientation';
|
|
94
|
+
readonly kind: 'token';
|
|
95
|
+
readonly isValid: (value: string) => value is PageOrientation;
|
|
96
|
+
readonly label: 'page orientation';
|
|
97
|
+
}];
|
|
98
|
+
/**
|
|
99
|
+
* Compile-time proof that {@link PAGE_SETUP_FACETS} covers every `<pageSetup>` attribute.
|
|
100
|
+
*
|
|
101
|
+
* `fitToPage` and `printerSettings` are excluded because neither is one: `fitToPage` is a
|
|
102
|
+
* `<sheetPr>` child's flag and `printerSettings` is the blob behind an `r:id`, so both are written
|
|
103
|
+
* and read somewhere else entirely and a table entry for them would describe nothing.
|
|
104
|
+
*/
|
|
105
|
+
export type EveryPageSetupFacetIsDeclared = AssertNever<Exclude<keyof PageSetup, 'fitToPage' | 'printerSettings' | (typeof PAGE_SETUP_FACETS)[number]['key']>>;
|
|
50
106
|
/**
|
|
51
107
|
* Print-toggle flags from the `<printOptions>` element. Each maps to a boolean OOXML attribute that
|
|
52
108
|
* defaults false, except `gridLinesSet`, which defaults true and gates whether `gridLines` is
|
|
@@ -65,6 +121,11 @@ export interface PrintOptions {
|
|
|
65
121
|
/** Whether the `gridLines` flag is authoritative; when `false`, Excel ignores `gridLines`. */
|
|
66
122
|
gridLinesSet?: boolean;
|
|
67
123
|
}
|
|
124
|
+
/** The `<printOptions>` flags, in CT_PrintOptions attribute order. Each is a plain OOXML boolean, so
|
|
125
|
+
* the list is the whole of what either direction needs to know. */
|
|
126
|
+
export declare const PRINT_OPTION_FLAGS: readonly ["horizontalCentered", "verticalCentered", "headings", "gridLines", "gridLinesSet"];
|
|
127
|
+
/** Compile-time proof that {@link PRINT_OPTION_FLAGS} covers every {@link PrintOptions} flag. */
|
|
128
|
+
export type EveryPrintOptionFlagIsDeclared = AssertNever<Exclude<keyof PrintOptions, (typeof PRINT_OPTION_FLAGS)[number]>>;
|
|
68
129
|
/**
|
|
69
130
|
* A manual page break (`<brk>`). For a row break, `id` is the row the layout splits *before*; for a
|
|
70
131
|
* column break it is the column. `max` bounds the break's extent across the other axis (Excel writes
|
|
@@ -92,6 +153,10 @@ export interface PageMargins {
|
|
|
92
153
|
header?: number;
|
|
93
154
|
footer?: number;
|
|
94
155
|
}
|
|
156
|
+
/** The `<pageMargins>` sides, in the order CT_PageMargins declares them. */
|
|
157
|
+
export declare const MARGIN_SIDES: readonly ["left", "right", "top", "bottom", "header", "footer"];
|
|
158
|
+
/** Compile-time proof that {@link MARGIN_SIDES} covers every {@link PageMargins} side. */
|
|
159
|
+
export type EveryMarginSideIsDeclared = AssertNever<Exclude<keyof PageMargins, (typeof MARGIN_SIDES)[number]>>;
|
|
95
160
|
/**
|
|
96
161
|
* Page header/footer text, one string per page class. Excel only honours the even- and
|
|
97
162
|
* first-page variants when the writer also sets the gating flags (`differentOddEven`,
|
|
@@ -106,3 +171,8 @@ export interface HeaderFooter {
|
|
|
106
171
|
firstHeader?: string;
|
|
107
172
|
firstFooter?: string;
|
|
108
173
|
}
|
|
174
|
+
/** The `<headerFooter>` children, in CT_HeaderFooter child order. The element name is the model key
|
|
175
|
+
* throughout, so one list serves the reader's capture, the reader's commit, and the writer. */
|
|
176
|
+
export declare const HEADER_FOOTER_ELEMENTS: readonly ["oddHeader", "oddFooter", "evenHeader", "evenFooter", "firstHeader", "firstFooter"];
|
|
177
|
+
/** Compile-time proof that {@link HEADER_FOOTER_ELEMENTS} covers every {@link HeaderFooter} slot. */
|
|
178
|
+
export type EveryHeaderFooterElementIsDeclared = AssertNever<Exclude<keyof HeaderFooter, (typeof HEADER_FOOTER_ELEMENTS)[number]>>;
|
package/dist/core/page-setup.js
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
1
|
+
import { tokenSet } from '../token-set.js';
|
|
2
|
+
export const isPageOrientation = tokenSet({ portrait: true, landscape: true });
|
|
3
|
+
export const isPageOrder = tokenSet({ downThenOver: true, overThenDown: true });
|
|
4
|
+
export const PAGE_SETUP_FACETS = [
|
|
5
|
+
{ key: 'paperSize', kind: 'count' },
|
|
6
|
+
{ key: 'scale', kind: 'count' },
|
|
7
|
+
{ key: 'fitToWidth', kind: 'count' },
|
|
8
|
+
{ key: 'fitToHeight', kind: 'count' },
|
|
9
|
+
{ key: 'pageOrder', kind: 'token', isValid: isPageOrder, label: 'page order' },
|
|
10
|
+
{ key: 'orientation', kind: 'token', isValid: isPageOrientation, label: 'page orientation' },
|
|
11
|
+
];
|
|
12
|
+
export const PRINT_OPTION_FLAGS = [
|
|
13
|
+
'horizontalCentered',
|
|
14
|
+
'verticalCentered',
|
|
15
|
+
'headings',
|
|
16
|
+
'gridLines',
|
|
17
|
+
'gridLinesSet',
|
|
18
|
+
];
|
|
19
|
+
export const MARGIN_SIDES = [
|
|
20
|
+
'left',
|
|
21
|
+
'right',
|
|
22
|
+
'top',
|
|
23
|
+
'bottom',
|
|
24
|
+
'header',
|
|
25
|
+
'footer',
|
|
26
|
+
];
|
|
27
|
+
export const HEADER_FOOTER_ELEMENTS = [
|
|
28
|
+
'oddHeader',
|
|
29
|
+
'oddFooter',
|
|
30
|
+
'evenHeader',
|
|
31
|
+
'evenFooter',
|
|
32
|
+
'firstHeader',
|
|
33
|
+
'firstFooter',
|
|
34
|
+
];
|
|
@@ -18,7 +18,7 @@ export interface ParsedPivotField {
|
|
|
18
18
|
* `unknown` covers a `type` the file declares that is none of these. */
|
|
19
19
|
export type PivotSourceKind = 'worksheet' | 'external' | 'consolidation' | 'scenario' | 'unknown';
|
|
20
20
|
/** Narrow a raw `<cacheSource type>` token to a {@link PivotSourceKind} a file may declare. */
|
|
21
|
-
export declare
|
|
21
|
+
export declare const isDeclarablePivotSourceKind: (value: string) => value is "consolidation" | "external" | "scenario" | "worksheet";
|
|
22
22
|
/** Where a pivot cache draws its rows from. {@link kind} names the source type; {@link sheet} and
|
|
23
23
|
* {@link ref} locate the range only when it is `worksheet` and are empty strings otherwise, so a
|
|
24
24
|
* consumer can tell a genuinely non-worksheet source apart from a worksheet source that failed to
|
package/dist/core/pivot-table.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AuthoringError, InternalError } from '../errors.js';
|
|
2
|
+
import { tokenSet } from '../token-set.js';
|
|
2
3
|
import { encodeAddress } from './address.js';
|
|
3
4
|
import { isErrorValue, isFormulaValue, isHyperlinkValue, isRichTextValue, isSharedFormulaValue, richTextToPlain, } from './value.js';
|
|
4
5
|
const PIVOT_METRICS = {
|
|
@@ -14,23 +15,18 @@ const PIVOT_METRICS = {
|
|
|
14
15
|
var: true,
|
|
15
16
|
varp: true,
|
|
16
17
|
};
|
|
17
|
-
|
|
18
|
-
return Object.hasOwn(PIVOT_METRICS, value);
|
|
19
|
-
}
|
|
18
|
+
const isPivotMetric = tokenSet(PIVOT_METRICS);
|
|
20
19
|
export function pivotMetricFromSubtotal(subtotal) {
|
|
21
20
|
if (subtotal === undefined)
|
|
22
21
|
return 'sum';
|
|
23
22
|
return isPivotMetric(subtotal) ? subtotal : 'sum';
|
|
24
23
|
}
|
|
25
|
-
const
|
|
24
|
+
export const isDeclarablePivotSourceKind = tokenSet({
|
|
26
25
|
worksheet: true,
|
|
27
26
|
external: true,
|
|
28
27
|
consolidation: true,
|
|
29
28
|
scenario: true,
|
|
30
|
-
};
|
|
31
|
-
export function isDeclarablePivotSourceKind(value) {
|
|
32
|
-
return Object.hasOwn(DECLARABLE_PIVOT_SOURCE_KINDS, value);
|
|
33
|
-
}
|
|
29
|
+
});
|
|
34
30
|
const BLANK = { kind: 'blank' };
|
|
35
31
|
export class PivotTable {
|
|
36
32
|
metric;
|
package/dist/core/row.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { AxisHandle } from './axis-handle.ts';
|
|
1
2
|
import type { Cell } from './cell.ts';
|
|
2
3
|
import { type AssertNever } from './internal.ts';
|
|
3
4
|
import type { Fill } from './style.ts';
|
|
4
5
|
import type { CellValue } from './value.ts';
|
|
5
6
|
import type { RowProperties, Worksheet } from './worksheet.ts';
|
|
6
|
-
export declare class Row {
|
|
7
|
+
export declare class Row extends AxisHandle<RowProperties> {
|
|
7
8
|
#private;
|
|
8
9
|
/** 1-based row number. Fixed for this handle's lifetime. */
|
|
9
10
|
readonly number: number;
|
|
@@ -16,6 +17,8 @@ export declare class Row {
|
|
|
16
17
|
* formatted, and they create the record on first write.
|
|
17
18
|
*/
|
|
18
19
|
get properties(): Readonly<RowProperties> | undefined;
|
|
20
|
+
protected propertiesOf(): RowProperties | undefined;
|
|
21
|
+
protected ensureProperties(): RowProperties;
|
|
19
22
|
/**
|
|
20
23
|
* Row height in points; `undefined` leaves the sheet default in force.
|
|
21
24
|
*
|
package/dist/core/row.js
CHANGED
|
@@ -1,45 +1,53 @@
|
|
|
1
1
|
import { assertRowInBounds, columnToNumber, encodeAddress } from './address.js';
|
|
2
|
+
import { AxisHandle } from './axis-handle.js';
|
|
2
3
|
import { INTERNAL } from './internal.js';
|
|
3
|
-
export class Row {
|
|
4
|
+
export class Row extends AxisHandle {
|
|
4
5
|
#sheet;
|
|
5
6
|
number;
|
|
6
7
|
constructor(sheet, number) {
|
|
8
|
+
super();
|
|
7
9
|
assertRowInBounds(number);
|
|
8
10
|
this.#sheet = sheet;
|
|
9
11
|
this.number = number;
|
|
10
12
|
}
|
|
11
13
|
get properties() {
|
|
14
|
+
return this.propertiesOf();
|
|
15
|
+
}
|
|
16
|
+
propertiesOf() {
|
|
12
17
|
return this.#sheet[INTERNAL].rowPropertiesOf(this.number);
|
|
13
18
|
}
|
|
19
|
+
ensureProperties() {
|
|
20
|
+
return this.#sheet[INTERNAL].ensureRowProperties(this.number);
|
|
21
|
+
}
|
|
14
22
|
get height() {
|
|
15
|
-
return this
|
|
23
|
+
return this.read('height');
|
|
16
24
|
}
|
|
17
25
|
set height(height) {
|
|
18
|
-
this
|
|
26
|
+
this.write('height', height);
|
|
19
27
|
}
|
|
20
28
|
get hidden() {
|
|
21
|
-
return this
|
|
29
|
+
return this.read('hidden');
|
|
22
30
|
}
|
|
23
31
|
set hidden(hidden) {
|
|
24
|
-
this
|
|
32
|
+
this.write('hidden', hidden);
|
|
25
33
|
}
|
|
26
34
|
get outlineLevel() {
|
|
27
|
-
return this
|
|
35
|
+
return this.read('outlineLevel');
|
|
28
36
|
}
|
|
29
37
|
set outlineLevel(outlineLevel) {
|
|
30
|
-
this
|
|
38
|
+
this.write('outlineLevel', outlineLevel);
|
|
31
39
|
}
|
|
32
40
|
get collapsed() {
|
|
33
|
-
return this
|
|
41
|
+
return this.read('collapsed');
|
|
34
42
|
}
|
|
35
43
|
set collapsed(collapsed) {
|
|
36
|
-
this
|
|
44
|
+
this.write('collapsed', collapsed);
|
|
37
45
|
}
|
|
38
46
|
get fill() {
|
|
39
|
-
return this
|
|
47
|
+
return this.read('fill');
|
|
40
48
|
}
|
|
41
49
|
set fill(fill) {
|
|
42
|
-
this
|
|
50
|
+
this.write('fill', fill);
|
|
43
51
|
}
|
|
44
52
|
getCell(column) {
|
|
45
53
|
const index = typeof column === 'number' ? column : columnToNumber(column);
|
|
@@ -60,16 +68,4 @@ export class Row {
|
|
|
60
68
|
this.getCell(index + 1).value = value;
|
|
61
69
|
});
|
|
62
70
|
}
|
|
63
|
-
#read(key) {
|
|
64
|
-
return this.#sheet[INTERNAL].rowPropertiesOf(this.number)?.[key];
|
|
65
|
-
}
|
|
66
|
-
#write(key, value) {
|
|
67
|
-
if (value === undefined) {
|
|
68
|
-
const properties = this.#sheet[INTERNAL].rowPropertiesOf(this.number);
|
|
69
|
-
if (properties !== undefined)
|
|
70
|
-
delete properties[key];
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
this.#sheet[INTERNAL].ensureRowProperties(this.number)[key] = value;
|
|
74
|
-
}
|
|
75
71
|
}
|
package/dist/core/style.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { AssertNever } from './internal.ts';
|
|
1
2
|
/** Underline can be a plain flag or one of Excel's named underline styles. */
|
|
2
3
|
export type UnderlineStyle = boolean | 'none' | 'single' | 'double' | 'singleAccounting' | 'doubleAccounting';
|
|
3
4
|
/** Narrow a raw `<u val>` token to a named {@link UnderlineStyle} (the non-boolean members). */
|
|
4
|
-
export declare
|
|
5
|
+
export declare const isNamedUnderlineStyle: (value: string) => value is "double" | "doubleAccounting" | "none" | "single" | "singleAccounting";
|
|
5
6
|
/** A colour, expressed as an ARGB hex string (`"FF0000FF"`) or an indexed theme colour. */
|
|
6
7
|
export interface Color {
|
|
7
8
|
/** 8-digit ARGB hex, uppercase, no leading `#`. */
|
|
@@ -41,7 +42,7 @@ export declare function parseArgb(value: string): string | undefined;
|
|
|
41
42
|
*/
|
|
42
43
|
export type FillPatternType = 'none' | 'solid' | 'gray125' | 'darkGray' | 'mediumGray' | 'lightGray' | 'gray0625' | 'darkHorizontal' | 'darkVertical' | 'darkDown' | 'darkUp' | 'darkGrid' | 'darkTrellis' | 'lightHorizontal' | 'lightVertical' | 'lightDown' | 'lightUp' | 'lightGrid' | 'lightTrellis';
|
|
43
44
|
/** Narrow a raw `<patternFill patternType>` token to a known {@link FillPatternType}. */
|
|
44
|
-
export declare
|
|
45
|
+
export declare const isFillPatternType: (value: string) => value is FillPatternType;
|
|
45
46
|
/**
|
|
46
47
|
* A pattern fill. For a `solid` fill the visible colour is the pattern *foreground*
|
|
47
48
|
* (`fgColor`), OOXML's counter-intuitive rule, while `bgColor` is the automatic
|
|
@@ -84,7 +85,7 @@ export type Fill = PatternFill | GradientFill;
|
|
|
84
85
|
*/
|
|
85
86
|
export type BorderStyle = 'thin' | 'medium' | 'thick' | 'dashed' | 'dotted' | 'double' | 'hair' | 'mediumDashed' | 'dashDot' | 'mediumDashDot' | 'dashDotDot' | 'mediumDashDotDot' | 'slantDashDot';
|
|
86
87
|
/** Narrow a raw border-edge `style` attribute to a known {@link BorderStyle}. */
|
|
87
|
-
export declare
|
|
88
|
+
export declare const isBorderStyle: (value: string) => value is BorderStyle;
|
|
88
89
|
/** One edge of a cell border: its line style, and optionally the line colour. */
|
|
89
90
|
export interface BorderEdge {
|
|
90
91
|
readonly style: BorderStyle;
|
|
@@ -108,12 +109,12 @@ export interface Border {
|
|
|
108
109
|
/** Vertical alignment of a font relative to the baseline (super/subscript). */
|
|
109
110
|
export type FontVerticalAlignment = 'superscript' | 'subscript';
|
|
110
111
|
/** Narrow a raw `<vertAlign val>` token to a known {@link FontVerticalAlignment}. */
|
|
111
|
-
export declare
|
|
112
|
+
export declare const isFontVerticalAlignment: (value: string) => value is FontVerticalAlignment;
|
|
112
113
|
/** The theme-font role a `<scheme val>` names: `"minor"`/`"major"` bind the font to whichever
|
|
113
114
|
* face the workbook theme assigns that role, `"none"` leaves it a literal, unbound face. */
|
|
114
115
|
export type FontScheme = 'minor' | 'major' | 'none';
|
|
115
116
|
/** Narrow a raw `<scheme val>` token to a known {@link FontScheme}. */
|
|
116
|
-
export declare
|
|
117
|
+
export declare const isFontScheme: (value: string) => value is FontScheme;
|
|
117
118
|
/** A font, as it applies to a cell or a single rich-text run. Every facet is optional and
|
|
118
119
|
* independent, like {@link Border}/{@link Alignment}/{@link Protection}: a font sets only the
|
|
119
120
|
* facets it overrides (Excel's own default font backs the rest), so no consumer ever holds every
|
|
@@ -137,12 +138,12 @@ export interface Font {
|
|
|
137
138
|
* back as no explicit horizontal alignment. */
|
|
138
139
|
export type HorizontalAlignment = 'general' | 'left' | 'center' | 'right' | 'fill' | 'justify' | 'centerContinuous' | 'distributed';
|
|
139
140
|
/** Narrow a raw `<alignment horizontal>` token to a known {@link HorizontalAlignment}. */
|
|
140
|
-
export declare
|
|
141
|
+
export declare const isHorizontalAlignment: (value: string) => value is HorizontalAlignment;
|
|
141
142
|
/** How a cell's content sits vertically within its bounds, as OOXML's `ST_VerticalAlignment`
|
|
142
143
|
* enumerates it. */
|
|
143
144
|
export type VerticalAlignment = 'top' | 'center' | 'bottom' | 'justify' | 'distributed';
|
|
144
145
|
/** Narrow a raw `<alignment vertical>` token to a known {@link VerticalAlignment}. */
|
|
145
|
-
export declare
|
|
146
|
+
export declare const isVerticalAlignment: (value: string) => value is VerticalAlignment;
|
|
146
147
|
/**
|
|
147
148
|
* A cell's alignment. Every facet is optional and independent; an absent facet means the cell
|
|
148
149
|
* takes Excel's default for it. The boolean flags default to off, so a cell that never enabled
|
|
@@ -158,6 +159,49 @@ export interface Alignment {
|
|
|
158
159
|
readonly shrinkToFit?: boolean;
|
|
159
160
|
readonly readingOrder?: number;
|
|
160
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* How one `<alignment>` facet encodes: which model key it is, what kind of value it carries, and the
|
|
164
|
+
* value that means "default", which the writer omits and the reader drops.
|
|
165
|
+
*
|
|
166
|
+
* Format-blind on purpose. `Alignment` is a core type and the layering gate forbids core importing a
|
|
167
|
+
* serialisation, so the table states what a facet *is* and each codec supplies the reading and the
|
|
168
|
+
* writing off the `kind`. That is where {@link SHEET_PROTECTION_FLAGS} sits and how it is consumed,
|
|
169
|
+
* and it is the shape the BIFF12 codec would want if alignment ever reaches it.
|
|
170
|
+
*
|
|
171
|
+
* The OOXML attribute name is the model key for all seven facets, so it is not restated here: a
|
|
172
|
+
* second list that is always identical is a second list to keep in step. A future facet whose
|
|
173
|
+
* attribute differs from its key is the one that would have to add the field.
|
|
174
|
+
*/
|
|
175
|
+
export type AlignmentFacet = {
|
|
176
|
+
readonly key: 'horizontal' | 'vertical';
|
|
177
|
+
readonly kind: 'token';
|
|
178
|
+
/** The enumeration guard, and what to call it in the error when a value fails it. */
|
|
179
|
+
readonly isValid: (value: string) => boolean;
|
|
180
|
+
readonly label: string;
|
|
181
|
+
/** The token that means the OOXML default, expressed by omitting the attribute. */
|
|
182
|
+
readonly omit?: string;
|
|
183
|
+
} | {
|
|
184
|
+
readonly key: 'textRotation' | 'indent' | 'readingOrder';
|
|
185
|
+
readonly kind: 'number';
|
|
186
|
+
} | {
|
|
187
|
+
readonly key: 'wrapText' | 'shrinkToFit';
|
|
188
|
+
readonly kind: 'flag';
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* The seven `<alignment>` facets, declared once. Both directions key off this list, so a facet
|
|
192
|
+
* written but not read (it survives a re-write and vanishes on load) or read but not written (the
|
|
193
|
+
* reverse) is no longer something a reviewer has to notice: {@link EveryAlignmentFacetIsDeclared}
|
|
194
|
+
* makes a facet added to {@link Alignment} and forgotten here a compile error.
|
|
195
|
+
*
|
|
196
|
+
* In ECMA-376 CT_CellAlignment order, which is the order the writer emits.
|
|
197
|
+
*/
|
|
198
|
+
export declare const ALIGNMENT_FACETS: readonly AlignmentFacet[];
|
|
199
|
+
/**
|
|
200
|
+
* Compile-time proof that {@link ALIGNMENT_FACETS} covers every {@link Alignment} facet. A facet
|
|
201
|
+
* added to the type without a table entry resolves this to that facet's name, which does not satisfy
|
|
202
|
+
* `never`, so the error names what is missing.
|
|
203
|
+
*/
|
|
204
|
+
export type EveryAlignmentFacetIsDeclared = AssertNever<Exclude<keyof Alignment, (typeof ALIGNMENT_FACETS)[number]['key']>>;
|
|
161
205
|
/**
|
|
162
206
|
* A cell's protection state, enforced only when the worksheet itself is protected. The flags
|
|
163
207
|
* do nothing on an unprotected sheet. `locked` defaults to TRUE in OOXML (every cell is locked
|
package/dist/core/style.js
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import { tokenSet } from '../token-set.js';
|
|
2
|
+
export const isNamedUnderlineStyle = tokenSet({
|
|
2
3
|
none: true,
|
|
3
4
|
single: true,
|
|
4
5
|
double: true,
|
|
5
6
|
singleAccounting: true,
|
|
6
7
|
doubleAccounting: true,
|
|
7
|
-
};
|
|
8
|
-
export function isNamedUnderlineStyle(value) {
|
|
9
|
-
return Object.hasOwn(NAMED_UNDERLINE_STYLES, value);
|
|
10
|
-
}
|
|
8
|
+
});
|
|
11
9
|
export function parseArgb(value) {
|
|
12
10
|
const hex = value.startsWith('#') ? value.slice(1) : value;
|
|
13
11
|
const argb = hex.length === 6 ? `FF${hex}` : hex;
|
|
14
12
|
return /^[0-9a-fA-F]{8}$/.test(argb) ? argb : undefined;
|
|
15
13
|
}
|
|
16
|
-
const
|
|
14
|
+
export const isFillPatternType = tokenSet({
|
|
17
15
|
none: true,
|
|
18
16
|
solid: true,
|
|
19
17
|
gray125: true,
|
|
@@ -33,11 +31,8 @@ const FILL_PATTERN_TYPES = {
|
|
|
33
31
|
lightUp: true,
|
|
34
32
|
lightGrid: true,
|
|
35
33
|
lightTrellis: true,
|
|
36
|
-
};
|
|
37
|
-
export
|
|
38
|
-
return Object.hasOwn(FILL_PATTERN_TYPES, value);
|
|
39
|
-
}
|
|
40
|
-
const BORDER_STYLES = {
|
|
34
|
+
});
|
|
35
|
+
export const isBorderStyle = tokenSet({
|
|
41
36
|
thin: true,
|
|
42
37
|
medium: true,
|
|
43
38
|
thick: true,
|
|
@@ -51,22 +46,13 @@ const BORDER_STYLES = {
|
|
|
51
46
|
dashDotDot: true,
|
|
52
47
|
mediumDashDotDot: true,
|
|
53
48
|
slantDashDot: true,
|
|
54
|
-
};
|
|
55
|
-
export
|
|
56
|
-
return Object.hasOwn(BORDER_STYLES, value);
|
|
57
|
-
}
|
|
58
|
-
const FONT_VERTICAL_ALIGNMENTS = {
|
|
49
|
+
});
|
|
50
|
+
export const isFontVerticalAlignment = tokenSet({
|
|
59
51
|
superscript: true,
|
|
60
52
|
subscript: true,
|
|
61
|
-
};
|
|
62
|
-
export
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
const FONT_SCHEMES = { minor: true, major: true, none: true };
|
|
66
|
-
export function isFontScheme(value) {
|
|
67
|
-
return Object.hasOwn(FONT_SCHEMES, value);
|
|
68
|
-
}
|
|
69
|
-
const HORIZONTAL_ALIGNMENTS = {
|
|
53
|
+
});
|
|
54
|
+
export const isFontScheme = tokenSet({ minor: true, major: true, none: true });
|
|
55
|
+
export const isHorizontalAlignment = tokenSet({
|
|
70
56
|
general: true,
|
|
71
57
|
left: true,
|
|
72
58
|
center: true,
|
|
@@ -75,20 +61,29 @@ const HORIZONTAL_ALIGNMENTS = {
|
|
|
75
61
|
justify: true,
|
|
76
62
|
centerContinuous: true,
|
|
77
63
|
distributed: true,
|
|
78
|
-
};
|
|
79
|
-
export
|
|
80
|
-
return Object.hasOwn(HORIZONTAL_ALIGNMENTS, value);
|
|
81
|
-
}
|
|
82
|
-
const VERTICAL_ALIGNMENTS = {
|
|
64
|
+
});
|
|
65
|
+
export const isVerticalAlignment = tokenSet({
|
|
83
66
|
top: true,
|
|
84
67
|
center: true,
|
|
85
68
|
bottom: true,
|
|
86
69
|
justify: true,
|
|
87
70
|
distributed: true,
|
|
88
|
-
};
|
|
89
|
-
export
|
|
90
|
-
|
|
91
|
-
|
|
71
|
+
});
|
|
72
|
+
export const ALIGNMENT_FACETS = [
|
|
73
|
+
{
|
|
74
|
+
key: 'horizontal',
|
|
75
|
+
kind: 'token',
|
|
76
|
+
isValid: isHorizontalAlignment,
|
|
77
|
+
label: 'horizontal alignment',
|
|
78
|
+
omit: 'general',
|
|
79
|
+
},
|
|
80
|
+
{ key: 'vertical', kind: 'token', isValid: isVerticalAlignment, label: 'vertical alignment' },
|
|
81
|
+
{ key: 'textRotation', kind: 'number' },
|
|
82
|
+
{ key: 'wrapText', kind: 'flag' },
|
|
83
|
+
{ key: 'indent', kind: 'number' },
|
|
84
|
+
{ key: 'shrinkToFit', kind: 'flag' },
|
|
85
|
+
{ key: 'readingOrder', kind: 'number' },
|
|
86
|
+
];
|
|
92
87
|
const CELL_STYLE_FACET_KEYS = {
|
|
93
88
|
fill: true,
|
|
94
89
|
numFmt: true,
|
package/dist/core/table.d.ts
CHANGED
|
@@ -75,7 +75,7 @@ export declare const TOTALS_ROW_SUBTOTAL_CODE: Readonly<Partial<Record<TotalsRow
|
|
|
75
75
|
*/
|
|
76
76
|
export type TotalsRowFunction = 'average' | 'countNums' | 'count' | 'max' | 'min' | 'stdDev' | 'sum' | 'var' | 'custom' | 'none';
|
|
77
77
|
/** Narrow a raw `totalsRowFunction` attribute to a known {@link TotalsRowFunction}. */
|
|
78
|
-
export declare
|
|
78
|
+
export declare const isTotalsRowFunction: (value: string) => value is TotalsRowFunction;
|
|
79
79
|
/** One column of a table: a header name and its optional totals-row behaviour. */
|
|
80
80
|
export interface TableColumn {
|
|
81
81
|
/** The column's header/display name. Must be unique within the table (case-insensitively):
|
package/dist/core/table.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AuthoringError } from '../errors.js';
|
|
2
|
+
import { tokenSet } from '../token-set.js';
|
|
2
3
|
import { decodeCellRef, encodeAddress } from './address.js';
|
|
3
4
|
import { isDeletedSpan, shiftIndex } from './grid-shift.js';
|
|
4
5
|
function cloneStyleInfo(style) {
|
|
@@ -25,7 +26,7 @@ export const TOTALS_ROW_SUBTOTAL_CODE = {
|
|
|
25
26
|
sum: 109,
|
|
26
27
|
var: 110,
|
|
27
28
|
};
|
|
28
|
-
const
|
|
29
|
+
export const isTotalsRowFunction = tokenSet({
|
|
29
30
|
average: true,
|
|
30
31
|
countNums: true,
|
|
31
32
|
count: true,
|
|
@@ -36,10 +37,7 @@ const TOTALS_ROW_FUNCTIONS = {
|
|
|
36
37
|
var: true,
|
|
37
38
|
custom: true,
|
|
38
39
|
none: true,
|
|
39
|
-
};
|
|
40
|
-
export function isTotalsRowFunction(value) {
|
|
41
|
-
return Object.hasOwn(TOTALS_ROW_FUNCTIONS, value);
|
|
42
|
-
}
|
|
40
|
+
});
|
|
43
41
|
const IDENTIFIER = /^[\p{L}\\_][\p{L}\p{N}._]*$/u;
|
|
44
42
|
function disambiguateColumnNames(columns) {
|
|
45
43
|
const seen = new Set();
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type Cell } from './cell.ts';
|
|
2
|
+
import type { MergeRect } from './merge.ts';
|
|
3
|
+
/**
|
|
4
|
+
* The sheet storage an extent reads. Held by reference and never reassigned, so the extent always
|
|
5
|
+
* sees the live grid; the value types are irrelevant to it, only which keys are present.
|
|
6
|
+
*/
|
|
7
|
+
export interface ExtentStorage {
|
|
8
|
+
readonly rows: ReadonlyMap<number, ReadonlyMap<number, Cell>>;
|
|
9
|
+
readonly rowProperties: ReadonlyMap<number, unknown>;
|
|
10
|
+
readonly columns: ReadonlyMap<number, unknown>;
|
|
11
|
+
readonly mergeRects: readonly MergeRect[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The last used row and column of a sheet, tracked incrementally. The sheet reports every edit that
|
|
15
|
+
* can move the grid's outer keys; this turns those reports into the two accessors behind
|
|
16
|
+
* `Worksheet.rowCount` and `Worksheet.columnCount`.
|
|
17
|
+
*/
|
|
18
|
+
export declare class UsedExtent {
|
|
19
|
+
#private;
|
|
20
|
+
constructor(storage: ExtentStorage);
|
|
21
|
+
/** Note a cell materialised at `(row, col)`. Whether it goes on to carry anything is not this
|
|
22
|
+
* class's business: the bound is on where a used cell *could* be, and the read confirms it. */
|
|
23
|
+
noteCell(row: number, col: number): void;
|
|
24
|
+
/** Note a row that bounds the used range by declaration: one given properties of its own. */
|
|
25
|
+
noteDeclaredRow(row: number): void;
|
|
26
|
+
/** Note a column that bounds the used range by declaration: one given properties of its own. */
|
|
27
|
+
noteDeclaredColumn(col: number): void;
|
|
28
|
+
/** Note a merged region, which occupies its whole rectangle and so bounds both axes. */
|
|
29
|
+
noteMerge(rect: MergeRect): void;
|
|
30
|
+
/**
|
|
31
|
+
* Report an edit that can pull the grid's outer keys inward: an eviction, a splice, an unmerge, a
|
|
32
|
+
* row replaced wholesale. The bounds are recomputed once, on the next read, rather than adjusted
|
|
33
|
+
* here, because finding the *new* maximum after a deletion is the same scan as finding it from
|
|
34
|
+
* scratch. Appending never invalidates, which is the whole point.
|
|
35
|
+
*/
|
|
36
|
+
invalidate(): void;
|
|
37
|
+
/** Report that the grid has been emptied, which puts the bounds at a known zero rather than
|
|
38
|
+
* stale: nothing is left to scan. */
|
|
39
|
+
reset(): void;
|
|
40
|
+
/** The 1-based index of the last row carrying anything, or 0 when the sheet holds nothing. */
|
|
41
|
+
get lastRow(): number;
|
|
42
|
+
/** The 1-based index of the last column carrying anything, or 0 when the sheet holds nothing. */
|
|
43
|
+
get lastColumn(): number;
|
|
44
|
+
}
|