@shbernal/ts-xlsx 1.3.1 → 2.1.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 +20 -10
- package/dist/bytes.d.ts +24 -0
- package/dist/bytes.js +34 -0
- package/dist/core/address.d.ts +72 -3
- package/dist/core/address.js +50 -10
- package/dist/core/autofilter.d.ts +13 -2
- package/dist/core/autofilter.js +35 -10
- package/dist/core/cell.d.ts +17 -16
- package/dist/core/cell.js +3 -7
- package/dist/core/color-resolution.d.ts +8 -8
- package/dist/core/color-resolution.js +7 -8
- package/dist/core/column.d.ts +8 -9
- package/dist/core/column.js +2 -4
- package/dist/core/comment-thread.d.ts +32 -23
- package/dist/core/comment-thread.js +4 -4
- package/dist/core/conditional-formatting-overlay.d.ts +6 -1
- package/dist/core/conditional-formatting-overlay.js +11 -0
- package/dist/core/conditional-formatting.d.ts +48 -8
- package/dist/core/conditional-formatting.js +88 -0
- package/dist/core/data-validation-overlay.d.ts +12 -1
- package/dist/core/data-validation-overlay.js +21 -2
- package/dist/core/data-validation.d.ts +12 -5
- package/dist/core/data-validation.js +34 -0
- package/dist/core/date.d.ts +3 -3
- package/dist/core/formula.d.ts +6 -6
- package/dist/core/grid-edits.d.ts +16 -0
- package/dist/core/grid-edits.js +29 -11
- package/dist/core/grid-shift.d.ts +19 -0
- package/dist/core/grid-shift.js +8 -0
- package/dist/core/image.d.ts +39 -2
- package/dist/core/image.js +10 -0
- package/dist/core/internal.d.ts +9 -1
- package/dist/core/limits.d.ts +4 -4
- package/dist/core/merge.d.ts +17 -12
- package/dist/core/merge.js +36 -5
- package/dist/core/page-setup.d.ts +20 -6
- package/dist/core/page-setup.js +8 -1
- package/dist/core/pivot-table.d.ts +4 -4
- package/dist/core/pivot-table.js +29 -20
- package/dist/core/preserved.d.ts +3 -3
- package/dist/core/protection.d.ts +7 -4
- package/dist/core/protection.js +20 -14
- package/dist/core/range.d.ts +16 -14
- package/dist/core/range.js +5 -5
- package/dist/core/row-input.d.ts +9 -8
- package/dist/core/row-input.js +12 -10
- package/dist/core/row.d.ts +7 -8
- package/dist/core/row.js +2 -4
- package/dist/core/style.d.ts +41 -14
- package/dist/core/style.js +82 -67
- package/dist/core/table-style.d.ts +9 -9
- package/dist/core/table-style.js +1 -1
- package/dist/core/table.d.ts +53 -51
- package/dist/core/table.js +83 -41
- package/dist/core/theme.d.ts +16 -44
- package/dist/core/theme.js +6 -148
- package/dist/core/value.d.ts +7 -7
- package/dist/core/workbook-protection.d.ts +2 -2
- package/dist/core/workbook-styles.d.ts +26 -0
- package/dist/core/workbook-styles.js +48 -0
- package/dist/core/workbook-theme.d.ts +25 -0
- package/dist/core/workbook-theme.js +49 -0
- package/dist/core/workbook-vba.d.ts +17 -0
- package/dist/core/workbook-vba.js +79 -0
- package/dist/core/workbook.d.ts +133 -87
- package/dist/core/workbook.js +74 -133
- package/dist/core/worksheet-comments.d.ts +17 -0
- package/dist/core/worksheet-comments.js +70 -0
- package/dist/core/worksheet-model.d.ts +4 -4
- package/dist/core/worksheet-model.js +1 -0
- package/dist/core/worksheet-pictures.d.ts +29 -0
- package/dist/core/worksheet-pictures.js +42 -0
- package/dist/core/worksheet.d.ts +100 -79
- package/dist/core/worksheet.js +63 -142
- package/dist/customui/errors.d.ts +1 -1
- package/dist/customui/ribbon.d.ts +3 -3
- package/dist/customui/ribbon.js +24 -23
- package/dist/entries/core.d.ts +7 -7
- package/dist/entries/core.js +1 -1
- package/dist/entries/csv.d.ts +1 -1
- package/dist/entries/node-unavailable.d.ts +15 -0
- package/dist/entries/node-unavailable.js +20 -0
- package/dist/entries/node.d.ts +1 -0
- package/dist/entries/node.js +1 -0
- package/dist/entries/vba.d.ts +1 -1
- package/dist/entries/vba.js +1 -1
- package/dist/entries/xlsx.d.ts +1 -1
- package/dist/entries/xlsx.js +1 -1
- package/dist/errors.d.ts +12 -12
- package/dist/io/csv/read.js +2 -3
- package/dist/io/csv/write.d.ts +19 -4
- package/dist/io/csv/write.js +34 -4
- package/dist/io/opc/errors.d.ts +6 -6
- package/dist/io/opc/inflate.d.ts +1 -1
- package/dist/io/opc/inflate.js +2 -12
- package/dist/io/opc/namespaces.d.ts +1 -1
- package/dist/io/opc/read-opc.d.ts +19 -3
- package/dist/io/opc/read-opc.js +14 -8
- package/dist/io/opc/read-options.d.ts +2 -2
- package/dist/io/opc/rels.d.ts +11 -0
- package/dist/io/opc/rels.js +3 -2
- package/dist/io/opc/sniff-format.d.ts +2 -2
- package/dist/io/style/xf-style.d.ts +44 -7
- package/dist/io/style/xf-style.js +27 -0
- package/dist/io/xlsb/errors.d.ts +1 -1
- package/dist/io/xlsb/formula.d.ts +4 -4
- package/dist/io/xlsb/primitives.d.ts +8 -8
- package/dist/io/xlsb/ptg-functions.d.ts +1 -1
- package/dist/io/xlsb/read-styles.js +2 -20
- package/dist/io/xlsb/read.d.ts +2 -2
- package/dist/io/xlsx/cell-accumulator.d.ts +26 -9
- package/dist/io/xlsx/cell-accumulator.js +89 -46
- package/dist/io/xlsx/cell-value.d.ts +3 -3
- package/dist/io/xlsx/cell-value.js +9 -6
- package/dist/io/xlsx/color-xml.d.ts +1 -1
- package/dist/io/xlsx/color-xml.js +18 -23
- package/dist/io/xlsx/comments.d.ts +5 -5
- package/dist/io/xlsx/comments.js +17 -8
- package/dist/io/xlsx/conditional-formatting.d.ts +4 -4
- package/dist/io/xlsx/conditional-formatting.js +64 -58
- package/dist/io/xlsx/data-validation.d.ts +3 -3
- package/dist/io/xlsx/data-validation.js +35 -33
- package/dist/io/xlsx/errors.d.ts +3 -3
- package/dist/io/xlsx/hyperlinks.d.ts +4 -2
- package/dist/io/xlsx/hyperlinks.js +10 -18
- package/dist/io/xlsx/images.d.ts +1 -1
- package/dist/io/xlsx/images.js +25 -28
- package/dist/io/xlsx/namespaces.d.ts +2 -2
- package/dist/io/xlsx/package-plan.js +5 -2
- package/dist/io/xlsx/read-pivot.js +4 -13
- package/dist/io/xlsx/read-rows.d.ts +13 -13
- package/dist/io/xlsx/read-rows.js +19 -55
- package/dist/io/xlsx/read-shared-strings.js +7 -44
- package/dist/io/xlsx/read-styles.d.ts +3 -3
- package/dist/io/xlsx/read-styles.js +42 -66
- package/dist/io/xlsx/read-worksheet.js +73 -129
- package/dist/io/xlsx/read.d.ts +4 -6
- package/dist/io/xlsx/read.js +104 -142
- package/dist/io/xlsx/rich-runs.d.ts +41 -7
- package/dist/io/xlsx/rich-runs.js +94 -30
- package/dist/io/xlsx/rich-text.d.ts +1 -1
- package/dist/io/xlsx/shared-strings.d.ts +2 -2
- package/dist/io/xlsx/sheet-properties.d.ts +1 -1
- package/dist/io/xlsx/sheet-properties.js +14 -10
- package/dist/io/xlsx/styles.d.ts +9 -22
- package/dist/io/xlsx/styles.js +65 -89
- package/dist/io/xlsx/tables.d.ts +2 -2
- package/dist/io/xlsx/tables.js +20 -25
- package/dist/io/xlsx/theme-xml.d.ts +37 -0
- package/dist/io/xlsx/theme-xml.js +145 -0
- package/dist/io/xlsx/threaded-comments.d.ts +18 -27
- package/dist/io/xlsx/threaded-comments.js +26 -38
- package/dist/io/xlsx/workbook-xml.js +14 -8
- package/dist/io/xlsx/worksheet-xml.d.ts +2 -2
- package/dist/io/xlsx/worksheet-xml.js +40 -48
- package/dist/io/xlsx/write-stream.d.ts +23 -16
- package/dist/io/xlsx/write-stream.js +13 -14
- package/dist/io/xlsx/write.d.ts +8 -7
- package/dist/io/xlsx/write.js +6 -3
- package/dist/io/xlsx/x14-ext.d.ts +1 -1
- package/dist/sha512.d.ts +2 -0
- package/dist/sha512.js +146 -0
- package/dist/vba/bytes.d.ts +11 -0
- package/dist/vba/bytes.js +29 -0
- package/dist/vba/cfb-writer.d.ts +1 -1
- package/dist/vba/cfb.d.ts +1 -1
- package/dist/vba/cfb.js +15 -51
- package/dist/vba/codepage.d.ts +2 -2
- package/dist/vba/dir-records.d.ts +53 -0
- package/dist/vba/dir-records.js +28 -0
- package/dist/vba/errors.d.ts +2 -2
- package/dist/vba/index.d.ts +2 -2
- package/dist/vba/index.js +2 -2
- package/dist/vba/ms-ovba.d.ts +1 -1
- package/dist/vba/ms-ovba.js +1 -3
- package/dist/vba/project-editor.d.ts +9 -9
- package/dist/vba/project-editor.js +6 -44
- package/dist/vba/project.d.ts +5 -5
- package/dist/vba/project.js +3 -28
- package/dist/vba/vba-encoding.d.ts +1 -1
- package/dist/xml/errors.d.ts +1 -1
- package/dist/xml/xml-read.d.ts +98 -9
- package/dist/xml/xml-read.js +70 -0
- package/dist/xml/xml.d.ts +74 -10
- package/dist/xml/xml.js +39 -7
- package/package.json +59 -36
package/dist/core/preserved.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* One outbound relationship of a {@link PreservedPart}: the id it carries inside its own rels part,
|
|
3
3
|
* the relationship Type URI, and its target. An internal relationship's `targetPath` is the resolved
|
|
4
4
|
* package path of the part it points at (the writer re-numbers and rewires it); an `external`
|
|
5
|
-
* relationship's `targetPath` is the raw `Target` verbatim (a linked workbook's path or URL)
|
|
5
|
+
* relationship's `targetPath` is the raw `Target` verbatim (a linked workbook's path or URL). It is
|
|
6
6
|
* outside the package, so it is emitted unchanged with `TargetMode="External"` and never remapped.
|
|
7
7
|
* Preserving external relationships is what keeps an `externalLink` part's pointer to its source
|
|
8
8
|
* workbook alive, so a round-trip does not orphan the `[n]` external references formulas resolve through.
|
|
@@ -26,7 +26,7 @@ export interface PreservedPart {
|
|
|
26
26
|
readonly rels: readonly PreservedRelationship[];
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
-
* A worksheet-level reference to package content the model does not model
|
|
29
|
+
* A worksheet-level reference to package content the model does not model, preserved verbatim across
|
|
30
30
|
* a round-trip instead of being silently dropped. `element` is the worksheet child that wires the
|
|
31
31
|
* reference (`<drawing>` for a vector-shape drawing, `<legacyDrawingHF>` for a header/footer image),
|
|
32
32
|
* or `undefined` when the sheet wires it by relationship alone (a pivot table or slicer Excel
|
|
@@ -43,7 +43,7 @@ export interface PreservedWorksheetReference {
|
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
45
|
* A package-root reference to content the model does not model, wired from the package's own
|
|
46
|
-
* `_rels/.rels` rather than the workbook part's rels
|
|
46
|
+
* `_rels/.rels` rather than the workbook part's rels: the ribbon-customisation parts
|
|
47
47
|
* (`customUI/customUI14.xml`), custom document properties (`docProps/custom.xml`), a thumbnail, and
|
|
48
48
|
* anything else hung off the root. The writer regenerates the root rels for the parts it models
|
|
49
49
|
* (workbook, core/app properties), so these would be dropped unless captured here and re-declared.
|
|
@@ -33,7 +33,7 @@ export interface SheetProtectionOptions extends SheetProtectionFlags {
|
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
35
|
* A password-derived credential, in OOXML's agile form: the hash algorithm, the salted
|
|
36
|
-
* iterated hash of the password, the salt, and the iteration count
|
|
36
|
+
* iterated hash of the password, the salt, and the iteration count: everything a consumer
|
|
37
37
|
* needs to verify a supplied password without the password ever being stored.
|
|
38
38
|
*/
|
|
39
39
|
export interface SheetProtectionCredential {
|
|
@@ -50,8 +50,8 @@ export interface SheetProtection {
|
|
|
50
50
|
/**
|
|
51
51
|
* The OOXML encoding table for the protection flags: each `<sheetProtection>` attribute paired
|
|
52
52
|
* with whether that operation is *forbidden by default* once a sheet is protected. Both directions
|
|
53
|
-
* key off this one list
|
|
54
|
-
* equal to the default)
|
|
53
|
+
* key off this one list. The writer turns an author allow-flag into an attribute (omitting values
|
|
54
|
+
* equal to the default) and the reader turns an attribute back into an allow-flag, so serialization
|
|
55
55
|
* and deserialization can never fall out of step. Most editing operations default to forbidden
|
|
56
56
|
* under protection; selecting cells and the object/scenario operations default to permitted.
|
|
57
57
|
*/
|
|
@@ -61,7 +61,10 @@ export declare const SHEET_PROTECTION_FLAGS: readonly {
|
|
|
61
61
|
}[];
|
|
62
62
|
/**
|
|
63
63
|
* Derive a fresh {@link SheetProtectionCredential} for a password. Each call generates a new
|
|
64
|
-
* random salt, so protecting two sheets with the same password yields different credentials
|
|
64
|
+
* random salt, so protecting two sheets with the same password yields different credentials:
|
|
65
65
|
* the salt is real randomness, not a stub.
|
|
66
|
+
*
|
|
67
|
+
* The spin loop is the cost of the scheme rather than of this implementation: Excel's default
|
|
68
|
+
* 100000 iterations is 100000 chained SHA-512 digests, and no shortcut through them exists.
|
|
66
69
|
*/
|
|
67
70
|
export declare function deriveCredential(password: string, spinCount?: number): SheetProtectionCredential;
|
package/dist/core/protection.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { concat, toBase64 } from '../bytes.js';
|
|
2
|
+
import { sha512 } from '../sha512.js';
|
|
2
3
|
export const SHEET_PROTECTION_FLAGS = [
|
|
3
4
|
{ key: 'formatCells', defaultForbidden: true },
|
|
4
5
|
{ key: 'formatColumns', defaultForbidden: true },
|
|
@@ -17,26 +18,31 @@ export const SHEET_PROTECTION_FLAGS = [
|
|
|
17
18
|
{ key: 'selectUnlockedCells', defaultForbidden: false },
|
|
18
19
|
];
|
|
19
20
|
const ALGORITHM_NAME = 'SHA-512';
|
|
20
|
-
const HASH = 'sha512';
|
|
21
21
|
const DEFAULT_SPIN_COUNT = 100000;
|
|
22
22
|
const SALT_BYTES = 16;
|
|
23
23
|
export function deriveCredential(password, spinCount = DEFAULT_SPIN_COUNT) {
|
|
24
|
-
const salt =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
.digest();
|
|
29
|
-
const iteration = Buffer.alloc(4);
|
|
24
|
+
const salt = crypto.getRandomValues(new Uint8Array(SALT_BYTES));
|
|
25
|
+
let hash = sha512(concat([salt, utf16le(password)]));
|
|
26
|
+
const spun = new Uint8Array(hash.length + 4);
|
|
27
|
+
const counter = new DataView(spun.buffer, hash.length, 4);
|
|
30
28
|
for (let i = 0; i < spinCount; i++) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.digest();
|
|
29
|
+
spun.set(hash, 0);
|
|
30
|
+
counter.setUint32(0, i, true);
|
|
31
|
+
hash = sha512(spun);
|
|
35
32
|
}
|
|
36
33
|
return {
|
|
37
34
|
algorithmName: ALGORITHM_NAME,
|
|
38
|
-
hashValue: hash
|
|
39
|
-
saltValue: salt
|
|
35
|
+
hashValue: toBase64(hash),
|
|
36
|
+
saltValue: toBase64(salt),
|
|
40
37
|
spinCount,
|
|
41
38
|
};
|
|
42
39
|
}
|
|
40
|
+
function utf16le(text) {
|
|
41
|
+
const bytes = new Uint8Array(text.length * 2);
|
|
42
|
+
for (let i = 0; i < text.length; i++) {
|
|
43
|
+
const unit = text.charCodeAt(i);
|
|
44
|
+
bytes[i * 2] = unit & 0xff;
|
|
45
|
+
bytes[i * 2 + 1] = unit >>> 8;
|
|
46
|
+
}
|
|
47
|
+
return bytes;
|
|
48
|
+
}
|
package/dist/core/range.d.ts
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
+
import { type GridRect } from './address.ts';
|
|
1
2
|
import { type Cell } from './cell.ts';
|
|
2
3
|
import { type Alignment, type Border, type CellStyle, type Fill, type Font, type Protection } from './style.ts';
|
|
3
4
|
import type { Worksheet } from './worksheet.ts';
|
|
4
5
|
/**
|
|
5
6
|
* A rectangular block of a worksheet's cells: `sheet.getRange('B2:D5')`.
|
|
6
7
|
*
|
|
7
|
-
* Cheap and stateless
|
|
8
|
+
* Cheap and stateless: constructing one creates no cells and does not extend the used range.
|
|
8
9
|
* {@link addresses} walks the block without materialising anything; {@link cells} reports only what
|
|
9
10
|
* already exists.
|
|
10
11
|
*
|
|
11
12
|
* Bounds are **inclusive first/last**, never start-and-count. That is the convention every
|
|
12
13
|
* range-shaped accessor in this library follows, so the three axes cannot disagree about what a
|
|
13
|
-
* pair of numbers means
|
|
14
|
+
* pair of numbers means; the handle is declared to satisfy {@link GridRect}, which is that
|
|
15
|
+
* convention written down once.
|
|
14
16
|
*/
|
|
15
|
-
export declare class Range {
|
|
17
|
+
export declare class Range implements GridRect {
|
|
16
18
|
#private;
|
|
17
19
|
/** 1-based row of the block's top edge. Fixed for this handle's lifetime. */
|
|
18
20
|
readonly top: number;
|
|
@@ -23,7 +25,7 @@ export declare class Range {
|
|
|
23
25
|
/** 1-based column of the block's right edge, inclusive. */
|
|
24
26
|
readonly right: number;
|
|
25
27
|
/**
|
|
26
|
-
* Build a handle from inclusive corners, in any order
|
|
28
|
+
* Build a handle from inclusive corners, in any order: `(5, 4, 2, 2)` and `(2, 2, 5, 4)` name the
|
|
27
29
|
* same block, exactly as `D5:B2` and `B2:D5` do. Prefer {@link Worksheet.getRange}.
|
|
28
30
|
*
|
|
29
31
|
* @throws {RangeError} if a corner is not a positive integer or falls outside the sheet's bounds.
|
|
@@ -31,30 +33,30 @@ export declare class Range {
|
|
|
31
33
|
constructor(sheet: Worksheet, top: number, left: number, bottom: number, right: number);
|
|
32
34
|
/** The worksheet this block belongs to. */
|
|
33
35
|
get sheet(): Worksheet;
|
|
34
|
-
/** Canonical `tl:br` A1 form
|
|
36
|
+
/** Canonical `tl:br` A1 form, `"B2:D5"`. A one-cell block still reads as `"B2:B2"`. */
|
|
35
37
|
get address(): string;
|
|
36
38
|
/** Rows spanned, inclusive of both edges. */
|
|
37
39
|
get rowCount(): number;
|
|
38
40
|
/** Columns spanned, inclusive of both edges. */
|
|
39
41
|
get columnCount(): number;
|
|
40
|
-
/** Cells the block covers
|
|
42
|
+
/** Cells the block covers: `rowCount * columnCount`, whether or not they exist yet. */
|
|
41
43
|
get cellCount(): number;
|
|
42
44
|
/** Whether a 1-based position falls inside the block. */
|
|
43
45
|
contains(row: number, col: number): boolean;
|
|
44
46
|
/**
|
|
45
47
|
* Every address the block covers, row-major (`B2`, `C2`, `D2`, `B3`, …). Materialises nothing, so
|
|
46
|
-
* this is the cheap way to walk a large block
|
|
48
|
+
* this is the cheap way to walk a large block, and, being a generator, it can be abandoned
|
|
47
49
|
* part-way without having built the whole list.
|
|
48
50
|
*/
|
|
49
51
|
addresses(): IterableIterator<string>;
|
|
50
52
|
/**
|
|
51
53
|
* The block's **materialised** cells, row-major. Sparse: a position nothing has ever written to is
|
|
52
54
|
* simply absent, which is what distinguishes "never written" from a cell holding `null`. Reading
|
|
53
|
-
* this creates nothing
|
|
55
|
+
* this creates nothing, mirroring {@link Column.cells}.
|
|
54
56
|
*/
|
|
55
57
|
get cells(): readonly Cell[];
|
|
56
58
|
/**
|
|
57
|
-
* The block's style, facet by facet
|
|
59
|
+
* The block's style, facet by facet: the counterpart of {@link Cell.style} over a rectangle, with
|
|
58
60
|
* the same semantics in both directions.
|
|
59
61
|
*
|
|
60
62
|
* **Reading** reports a facet only when *every* position in the block carries a structurally
|
|
@@ -62,13 +64,13 @@ export declare class Range {
|
|
|
62
64
|
* through this handle therefore reads back what was written; a block whose cells disagree says so
|
|
63
65
|
* rather than picking a corner's answer and passing it off as the whole.
|
|
64
66
|
*
|
|
65
|
-
* **Writing** lays each facet the payload names onto every cell, leaving facets it omits
|
|
66
|
-
*
|
|
67
|
-
* it. Use {@link clearStyle} first for a wholesale replace.
|
|
67
|
+
* **Writing** lays each facet the payload names onto every cell, leaving facets it omits
|
|
68
|
+
* untouched, exactly what `cell.style = {...}` does, so this composes with prior styling instead
|
|
69
|
+
* of clearing it. Use {@link clearStyle} first for a wholesale replace.
|
|
68
70
|
*
|
|
69
71
|
* Writing **materialises** every position in the block, because a styled-but-valueless cell is the
|
|
70
72
|
* only way an empty cell renders with a fill: skipping the holes would leave gaps in a header band.
|
|
71
|
-
* The cost is bounded by construction
|
|
73
|
+
* The cost is bounded by construction: a range is always a bounded rectangle, and whole-axis
|
|
72
74
|
* styling belongs to {@link Worksheet.getColumn}/{@link Worksheet.getRow} instead. {@link cellCount}
|
|
73
75
|
* is the exact number of cells a write will create.
|
|
74
76
|
*/
|
|
@@ -77,7 +79,7 @@ export declare class Range {
|
|
|
77
79
|
/**
|
|
78
80
|
* Strip every style facet from every cell in the block, leaving values untouched. Assigning
|
|
79
81
|
* {@link style} composes, so this is how a wholesale replace is said: `clearStyle()` then assign.
|
|
80
|
-
* Materialises nothing
|
|
82
|
+
* Materialises nothing: a cell that does not exist carries no style to clear.
|
|
81
83
|
*/
|
|
82
84
|
clearStyle(): void;
|
|
83
85
|
/** Fill applied to every cell in the block; `undefined` when they do not all agree. */
|
package/dist/core/range.js
CHANGED
|
@@ -154,22 +154,22 @@ function facetKey(value) {
|
|
|
154
154
|
}
|
|
155
155
|
function checkBound(axis, value, max) {
|
|
156
156
|
if (!Number.isInteger(value) || value < 1) {
|
|
157
|
-
throw new RangeError(`${axis} ${value} is out of bounds
|
|
157
|
+
throw new RangeError(`${axis} ${value} is out of bounds: ${axis}s start at 1`);
|
|
158
158
|
}
|
|
159
159
|
if (value > max) {
|
|
160
|
-
throw new RangeError(`${axis} ${value} is out of bounds
|
|
160
|
+
throw new RangeError(`${axis} ${value} is out of bounds: the sheet ends at ${max}`);
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
export function rangeFrom(sheet, reference) {
|
|
164
164
|
const { top, left, bottom, right, sheetName, dimensions } = decodeRange(reference);
|
|
165
165
|
if (sheetName !== undefined && sheetName.toLowerCase() !== sheet.name.toLowerCase()) {
|
|
166
|
-
throw new SyntaxError(`"${reference}" names worksheet "${sheetName}", not "${sheet.name}"
|
|
166
|
+
throw new SyntaxError(`"${reference}" names worksheet "${sheetName}", not "${sheet.name}": a range belongs to the sheet it came from`);
|
|
167
167
|
}
|
|
168
168
|
if (top === undefined || bottom === undefined) {
|
|
169
|
-
throw new SyntaxError(`"${reference}" spans whole columns (${dimensions})
|
|
169
|
+
throw new SyntaxError(`"${reference}" spans whole columns (${dimensions}): style them through getColumn(n), which says the same thing in one attribute instead of ${MAX_ROW} cells`);
|
|
170
170
|
}
|
|
171
171
|
if (left === undefined || right === undefined) {
|
|
172
|
-
throw new SyntaxError(`"${reference}" spans whole rows (${dimensions})
|
|
172
|
+
throw new SyntaxError(`"${reference}" spans whole rows (${dimensions}): style them through getRow(n), which says the same thing in one attribute instead of ${MAX_COLUMN} cells`);
|
|
173
173
|
}
|
|
174
174
|
return new Range(sheet, top, left, bottom, right);
|
|
175
175
|
}
|
package/dist/core/row-input.d.ts
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { Cell } from './cell.ts';
|
|
2
2
|
import type { CellValue } from './value.ts';
|
|
3
3
|
import type { ColumnProperties, RowInput } from './worksheet.ts';
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a positional array of values to the (1-based index, value) placements it names: the first
|
|
6
|
+
* value lands at 1, and a hole or an explicit `undefined` places nothing, leaving that line
|
|
7
|
+
* untouched. The index is a column on the row axis and a row on the column axis; the reading is the
|
|
8
|
+
* same either way.
|
|
9
|
+
*/
|
|
10
|
+
export declare function positionalPlacements(values: readonly (CellValue | undefined)[]): Array<[number, CellValue]>;
|
|
4
11
|
/**
|
|
5
12
|
* Resolve a `RowInput` to the (1-based column, value) placements it names. A positional array maps
|
|
6
13
|
* each value to its column from A, skipping a hole or an explicit `undefined` so that column is left
|
|
7
14
|
* untouched; a keyed object maps each value under the column carrying the matching key.
|
|
8
15
|
*
|
|
9
16
|
* `Array.isArray`, not `instanceof Array`: a row built in another realm (a vm context, a browser
|
|
10
|
-
* iframe) is still an array but fails the identity check, and would then be walked as a keyed
|
|
11
|
-
* placing nothing.
|
|
17
|
+
* iframe) is still an array but fails the identity check, and would then be walked as a keyed
|
|
18
|
+
* object, placing nothing.
|
|
12
19
|
*/
|
|
13
20
|
export declare function rowPlacements(values: RowInput, columns: ReadonlyMap<number, ColumnProperties>): Array<[number, CellValue]>;
|
|
14
21
|
/**
|
|
@@ -16,9 +23,3 @@ export declare function rowPlacements(values: RowInput, columns: ReadonlyMap<num
|
|
|
16
23
|
* keyed by column. The grid-edit machinery then splices this map into place.
|
|
17
24
|
*/
|
|
18
25
|
export declare function buildRowCells(number: number, values: RowInput, columns: ReadonlyMap<number, ColumnProperties>): Map<number, Cell>;
|
|
19
|
-
/**
|
|
20
|
-
* The 1-based index of the column carrying `key` (see {@link ColumnProperties.key}).
|
|
21
|
-
*
|
|
22
|
-
* @throws {AuthoringError} if no column declares that key.
|
|
23
|
-
*/
|
|
24
|
-
export declare function columnIndexByKey(columns: ReadonlyMap<number, ColumnProperties>, key: string): number;
|
package/dist/core/row-input.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { AuthoringError } from '../errors.js';
|
|
2
2
|
import { Cell } from './cell.js';
|
|
3
|
+
export function positionalPlacements(values) {
|
|
4
|
+
const placements = [];
|
|
5
|
+
values.forEach((value, index) => {
|
|
6
|
+
if (value !== undefined)
|
|
7
|
+
placements.push([index + 1, value]);
|
|
8
|
+
});
|
|
9
|
+
return placements;
|
|
10
|
+
}
|
|
3
11
|
export function rowPlacements(values, columns) {
|
|
4
|
-
if (Array.isArray(values))
|
|
5
|
-
|
|
6
|
-
values.forEach((value, index) => {
|
|
7
|
-
if (value !== undefined)
|
|
8
|
-
placements.push([index + 1, value]);
|
|
9
|
-
});
|
|
10
|
-
return placements;
|
|
11
|
-
}
|
|
12
|
+
if (Array.isArray(values))
|
|
13
|
+
return positionalPlacements(values);
|
|
12
14
|
return Object.entries(values).map(([key, value]) => [columnIndexByKey(columns, key), value]);
|
|
13
15
|
}
|
|
14
16
|
export function buildRowCells(number, values, columns) {
|
|
@@ -20,10 +22,10 @@ export function buildRowCells(number, values, columns) {
|
|
|
20
22
|
}
|
|
21
23
|
return row;
|
|
22
24
|
}
|
|
23
|
-
|
|
25
|
+
function columnIndexByKey(columns, key) {
|
|
24
26
|
for (const [index, properties] of columns) {
|
|
25
27
|
if (properties.key === key)
|
|
26
28
|
return index;
|
|
27
29
|
}
|
|
28
|
-
throw new AuthoringError(`no column is keyed ${JSON.stringify(key)}
|
|
30
|
+
throw new AuthoringError(`no column is keyed ${JSON.stringify(key)}: set getColumn(n).key first`);
|
|
29
31
|
}
|
package/dist/core/row.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Cell } from './cell.ts';
|
|
2
|
+
import { type AssertNever } from './internal.ts';
|
|
2
3
|
import type { Fill } from './style.ts';
|
|
3
4
|
import type { CellValue } from './value.ts';
|
|
4
5
|
import type { RowProperties, Worksheet } from './worksheet.ts';
|
|
@@ -6,10 +7,10 @@ export declare class Row {
|
|
|
6
7
|
#private;
|
|
7
8
|
/** 1-based row number. Fixed for this handle's lifetime. */
|
|
8
9
|
readonly number: number;
|
|
9
|
-
/** @throws {RangeError}
|
|
10
|
+
/** @throws {RangeError} unless the number is an integer within Excel's row grid (1..1048576). */
|
|
10
11
|
constructor(sheet: Worksheet, number: number);
|
|
11
12
|
/**
|
|
12
|
-
* The row's format record if it has one, else `undefined
|
|
13
|
+
* The row's format record if it has one, else `undefined`: a read that never fabricates, so a
|
|
13
14
|
* serializer can ask every row it visits whether there are attributes to emit without giving each
|
|
14
15
|
* one an empty record. Read-only on purpose: {@link height} and its siblings are how a row is
|
|
15
16
|
* formatted, and they create the record on first write.
|
|
@@ -21,7 +22,7 @@ export declare class Row {
|
|
|
21
22
|
* Not bounded here, deliberately: {@link MAX_ROW_HEIGHT} is what Excel accepts *being set*, but
|
|
22
23
|
* the schema puts no ceiling on `ht` and this setter is also how the reader loads a foreign
|
|
23
24
|
* file, so refusing a taller row would mean refusing a file Excel opens clean. Check against the
|
|
24
|
-
* constant when authoring
|
|
25
|
+
* constant when authoring: Excel silently clamps a taller row on read, so a height above it is
|
|
25
26
|
* one you state and do not get.
|
|
26
27
|
*/
|
|
27
28
|
get height(): number | undefined;
|
|
@@ -51,7 +52,7 @@ export declare class Row {
|
|
|
51
52
|
getCell(column: number | string): Cell;
|
|
52
53
|
/**
|
|
53
54
|
* The row's materialised cells in ascending column order. Sparse: a column never written to has
|
|
54
|
-
* no cell here, and the array is a fresh snapshot of *which* cells exist
|
|
55
|
+
* no cell here, and the array is a fresh snapshot of *which* cells exist; the cells themselves
|
|
55
56
|
* are the live ones.
|
|
56
57
|
*/
|
|
57
58
|
get cells(): readonly Cell[];
|
|
@@ -60,16 +61,15 @@ export declare class Row {
|
|
|
60
61
|
* a column with no cell is a hole, which is what distinguishes "never written" from a cell
|
|
61
62
|
* holding `null`.
|
|
62
63
|
*
|
|
63
|
-
* Assigning places each value it names and leaves every other column untouched
|
|
64
|
+
* Assigning places each value it names and leaves every other column untouched: a hole or an
|
|
64
65
|
* explicit `undefined` skips that column, and a shorter array does not clear the tail. These are
|
|
65
66
|
* {@link Worksheet.addRow}'s rules, deliberately: `values` is that same row shape addressed by
|
|
66
|
-
* number rather than appended. To *replace* a row, including clearing what it held, splice it
|
|
67
|
+
* number rather than appended. To *replace* a row, including clearing what it held, splice it:
|
|
67
68
|
* `sheet.spliceRows(n, 1, values)`.
|
|
68
69
|
*/
|
|
69
70
|
get values(): (CellValue | undefined)[];
|
|
70
71
|
set values(values: (CellValue | undefined)[]);
|
|
71
72
|
}
|
|
72
|
-
type AssertNever<T extends never> = T;
|
|
73
73
|
/**
|
|
74
74
|
* Compile-time proof that {@link Row} mirrors every {@link RowProperties} field. A field added to
|
|
75
75
|
* the record without an accessor here resolves this to that field's name, which does not satisfy
|
|
@@ -78,4 +78,3 @@ type AssertNever<T extends never> = T;
|
|
|
78
78
|
* would simply never mention it.
|
|
79
79
|
*/
|
|
80
80
|
export type EveryRowPropertyIsMirrored = AssertNever<Exclude<keyof RowProperties, keyof Row & keyof RowProperties>>;
|
|
81
|
-
export {};
|
package/dist/core/row.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { columnToNumber, encodeAddress } from './address.js';
|
|
1
|
+
import { assertRowInBounds, columnToNumber, encodeAddress } from './address.js';
|
|
2
2
|
import { INTERNAL } from './internal.js';
|
|
3
3
|
export class Row {
|
|
4
4
|
#sheet;
|
|
5
5
|
number;
|
|
6
6
|
constructor(sheet, number) {
|
|
7
|
-
|
|
8
|
-
throw new RangeError(`row ${number} is out of bounds — rows start at 1`);
|
|
9
|
-
}
|
|
7
|
+
assertRowInBounds(number);
|
|
10
8
|
this.#sheet = sheet;
|
|
11
9
|
this.number = number;
|
|
12
10
|
}
|
package/dist/core/style.d.ts
CHANGED
|
@@ -14,6 +14,26 @@ export interface Color {
|
|
|
14
14
|
* automatic placeholder `indexed="64"`; the visible colour lives on `fgColor`. */
|
|
15
15
|
readonly indexed?: number;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Parse a colour written in any of the shapes the API accepts into the bare 8-hex ARGB OOXML wants,
|
|
19
|
+
* or `undefined` if it is not one of them.
|
|
20
|
+
*
|
|
21
|
+
* Two conveniences are accepted, and nothing else: a leading `#` is a CSS habit and is stripped
|
|
22
|
+
* (`'#FFBFBFBF'` → `'FFBFBFBF'`), and a 6-hex RGB is promoted with a fully-opaque alpha (`'00FF00'` →
|
|
23
|
+
* `'FF00FF00'`), the common case of a colour written without its alpha channel. Casing is preserved,
|
|
24
|
+
* so a foreign file's lowercase value round-trips as it arrived.
|
|
25
|
+
*
|
|
26
|
+
* This states the grammar once for both directions. What a malformed value *means* differs by
|
|
27
|
+
* direction and is decided by the caller: on read it is foreign data and resolves to nothing, on
|
|
28
|
+
* write it is a caller's bug and throws (see `normalizeArgb` in `io/xlsx/color-xml.ts`). Neither can
|
|
29
|
+
* be a silently half-parsed value, because Excel does not report a malformed `rgb` at all; it
|
|
30
|
+
* renders flat black.
|
|
31
|
+
*
|
|
32
|
+
* `normalizeThemeColor` in `core/theme.ts` asks a similar question and stays separate: a theme
|
|
33
|
+
* slot is `<a:srgbClr val>`, which DrawingML gives no alpha channel, so the two differ in exactly the
|
|
34
|
+
* thing this one exists to add.
|
|
35
|
+
*/
|
|
36
|
+
export declare function parseArgb(value: string): string | undefined;
|
|
17
37
|
/**
|
|
18
38
|
* Fill pattern kinds, as OOXML's `ST_PatternType` enumerates them. `none` is the
|
|
19
39
|
* absence of a fill; `solid` paints the whole cell with the foreground colour (the
|
|
@@ -24,7 +44,7 @@ export type FillPatternType = 'none' | 'solid' | 'gray125' | 'darkGray' | 'mediu
|
|
|
24
44
|
export declare function isFillPatternType(value: string): value is FillPatternType;
|
|
25
45
|
/**
|
|
26
46
|
* A pattern fill. For a `solid` fill the visible colour is the pattern *foreground*
|
|
27
|
-
* (`fgColor`)
|
|
47
|
+
* (`fgColor`), OOXML's counter-intuitive rule, while `bgColor` is the automatic
|
|
28
48
|
* indexed placeholder.
|
|
29
49
|
*/
|
|
30
50
|
export interface PatternFill {
|
|
@@ -89,13 +109,13 @@ export interface Border {
|
|
|
89
109
|
export type FontVerticalAlignment = 'superscript' | 'subscript';
|
|
90
110
|
/** Narrow a raw `<vertAlign val>` token to a known {@link FontVerticalAlignment}. */
|
|
91
111
|
export declare function isFontVerticalAlignment(value: string): value is FontVerticalAlignment;
|
|
92
|
-
/** The theme-font role a `<scheme val>` names
|
|
112
|
+
/** The theme-font role a `<scheme val>` names: `"minor"`/`"major"` bind the font to whichever
|
|
93
113
|
* face the workbook theme assigns that role, `"none"` leaves it a literal, unbound face. */
|
|
94
114
|
export type FontScheme = 'minor' | 'major' | 'none';
|
|
95
115
|
/** Narrow a raw `<scheme val>` token to a known {@link FontScheme}. */
|
|
96
116
|
export declare function isFontScheme(value: string): value is FontScheme;
|
|
97
117
|
/** A font, as it applies to a cell or a single rich-text run. Every facet is optional and
|
|
98
|
-
* independent, like {@link Border}/{@link Alignment}/{@link Protection}
|
|
118
|
+
* independent, like {@link Border}/{@link Alignment}/{@link Protection}: a font sets only the
|
|
99
119
|
* facets it overrides (Excel's own default font backs the rest), so no consumer ever holds every
|
|
100
120
|
* field populated at once. */
|
|
101
121
|
export interface Font {
|
|
@@ -125,7 +145,7 @@ export type VerticalAlignment = 'top' | 'center' | 'bottom' | 'justify' | 'distr
|
|
|
125
145
|
export declare function isVerticalAlignment(value: string): value is VerticalAlignment;
|
|
126
146
|
/**
|
|
127
147
|
* A cell's alignment. Every facet is optional and independent; an absent facet means the cell
|
|
128
|
-
* takes Excel's default for it. The boolean flags default to off
|
|
148
|
+
* takes Excel's default for it. The boolean flags default to off, so a cell that never enabled
|
|
129
149
|
* `wrapText`/`shrinkToFit` must never read back with them on. `textRotation` is in degrees
|
|
130
150
|
* (0–180, where 91–180 encodes -1° to -90°); `indent` is a non-negative indent level.
|
|
131
151
|
*/
|
|
@@ -139,7 +159,7 @@ export interface Alignment {
|
|
|
139
159
|
readonly readingOrder?: number;
|
|
140
160
|
}
|
|
141
161
|
/**
|
|
142
|
-
* A cell's protection state, enforced only when the worksheet itself is protected
|
|
162
|
+
* A cell's protection state, enforced only when the worksheet itself is protected. The flags
|
|
143
163
|
* do nothing on an unprotected sheet. `locked` defaults to TRUE in OOXML (every cell is locked
|
|
144
164
|
* unless told otherwise), so the meaningful, information-carrying state is an explicitly
|
|
145
165
|
* *unlocked* cell (`locked: false`); marking a cell locked merely restates the default and
|
|
@@ -151,14 +171,14 @@ export interface Protection {
|
|
|
151
171
|
readonly hidden?: boolean;
|
|
152
172
|
}
|
|
153
173
|
/**
|
|
154
|
-
* The six direct-format facets a cell can carry
|
|
174
|
+
* The six direct-format facets a cell can carry: its fill, number format, font, border, alignment,
|
|
155
175
|
* and protection. Every facet is optional and independent: a cell sets only the facets it overrides
|
|
156
176
|
* and inherits the rest. This one tuple is the unit of style throughout the library, so the
|
|
157
|
-
* interfaces that carry a cell's formatting compose it rather than re-listing the fields
|
|
177
|
+
* interfaces that carry a cell's formatting compose it rather than re-listing the fields: a column,
|
|
158
178
|
* table column, or named style whose facets *default* the cells that leave them unset (see
|
|
159
179
|
* {@link ColumnProperties}, {@link NamedCellStyle}), and a cell's own resolved format. Because they
|
|
160
180
|
* share this type, "add a facet" is a single edit here and the compiler enforces that no read/write
|
|
161
|
-
* path silently drops one
|
|
181
|
+
* path silently drops one, the round-trip symmetry the merge-loss contract depends on.
|
|
162
182
|
*/
|
|
163
183
|
export interface CellStyle {
|
|
164
184
|
fill?: Fill | undefined;
|
|
@@ -171,15 +191,22 @@ export interface CellStyle {
|
|
|
171
191
|
/** The names of the {@link CellStyle} facets, for helpers that copy the tuple facet-by-facet. */
|
|
172
192
|
export declare const CELL_STYLE_FACETS: (keyof CellStyle)[];
|
|
173
193
|
/**
|
|
174
|
-
* Copy each present facet of `source` onto `target`, leaving facets `source` omits untouched
|
|
194
|
+
* Copy each present facet of `source` onto `target`, leaving facets `source` omits untouched: the
|
|
175
195
|
* plain-record counterpart to a cell's `applyCellStyle`, for the {@link CellStyle}-shaped targets a
|
|
176
196
|
* `Cell`'s setters don't reach (a column's cell-defaults, a named style being assembled on read).
|
|
177
197
|
* Driven by {@link CELL_STYLE_FACETS}, so a facet added to the tuple reaches these paths the moment
|
|
178
|
-
* it joins
|
|
198
|
+
* it joins, the same single-point-of-change the cell path gets.
|
|
179
199
|
*/
|
|
180
200
|
export declare function assignStyleFacets(target: CellStyle, source: Readonly<CellStyle>): void;
|
|
181
201
|
/**
|
|
182
|
-
*
|
|
202
|
+
* The {@link CellStyle} facets of `source` as a plain tuple of their own, for a source that carries
|
|
203
|
+
* more than the facets (a column's properties also hold width, hidden and outline state). The
|
|
204
|
+
* projection counterpart to {@link assignStyleFacets}, driven by the same list, so a facet added to
|
|
205
|
+
* the tuple reaches a `<col>` style without anyone remembering to widen a literal.
|
|
206
|
+
*/
|
|
207
|
+
export declare function pickStyleFacets(source: Readonly<CellStyle>): CellStyle;
|
|
208
|
+
/**
|
|
209
|
+
* A named cell style: the OOXML `cellStyleXfs`/`cellStyles` layer. A spreadsheet applies a built-in
|
|
183
210
|
* or custom style (e.g. "Normal", "Accent1") whose visual facets live in this shared, named layer
|
|
184
211
|
* rather than on each cell's direct format; a cell links to it and inherits any facet the direct
|
|
185
212
|
* format leaves unset. The facets are a cell's own (see {@link CellStyle}); `name` is the style's
|
|
@@ -192,7 +219,7 @@ export type NamedCellStyle = Readonly<CellStyle> & {
|
|
|
192
219
|
/**
|
|
193
220
|
* A differential style (OOXML CT_Dxf): formatting laid *over* whatever a cell already carries. Only
|
|
194
221
|
* the facets present override; the rest of the cell's own style shows through. It carries the subset
|
|
195
|
-
* of the cell-style facets (see {@link CellStyle}) a `<dxf>` can express
|
|
222
|
+
* of the cell-style facets (see {@link CellStyle}) a `<dxf>` can express: font, number format, fill,
|
|
196
223
|
* and border.
|
|
197
224
|
*
|
|
198
225
|
* Differential styles live in one workbook-level table (`<dxfs>`) that several features index into:
|
|
@@ -214,7 +241,7 @@ export type DifferentialStyle = Pick<CellStyle, 'font' | 'numFmt' | 'fill' | 'bo
|
|
|
214
241
|
* Each entry of {@link styles} is one `<tableStyle>…</tableStyle>` fragment kept verbatim, for the
|
|
215
242
|
* same reason a `<dxf>` is: a `tableStyleElement`'s `dxfId` indexes the differential-style table,
|
|
216
243
|
* which the writer re-emits **at its original indices**, so the references stay valid without
|
|
217
|
-
* reparsing anything. That index-stability is load-bearing
|
|
244
|
+
* reparsing anything. That index-stability is load-bearing: renumbering the dxf table would
|
|
218
245
|
* silently re-point every preserved table style at a different format.
|
|
219
246
|
*
|
|
220
247
|
* The two default names are ordinary strings, not fragments: they are re-escaped on write, so they
|
|
@@ -230,7 +257,7 @@ export interface TableStyleTable {
|
|
|
230
257
|
*
|
|
231
258
|
* Carrying a fragment verbatim carries its *prefixes* too. Excel stamps a revision id
|
|
232
259
|
* (`xr9:uid="{…}"`) on every `<tableStyle>` it writes, so a fragment re-emitted under a
|
|
233
|
-
* `<styleSheet>` that declares only the default namespace is not namespace-well-formed
|
|
260
|
+
* `<styleSheet>` that declares only the default namespace is not namespace-well-formed, and no
|
|
234
261
|
* consumer can parse the part at all, which is a far louder failure than the dropped table style
|
|
235
262
|
* this preservation exists to prevent. The writer re-declares each prefix on `<styleSheet>` and
|
|
236
263
|
* re-states the ignorable ones, exactly as the source did.
|