@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/io/csv/write.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type CellValue } from '../../core/value.ts';
|
|
2
2
|
import type { Workbook } from '../../core/workbook.ts';
|
|
3
|
+
/**
|
|
4
|
+
* A byte encoding {@link writeCsv} can produce, spelled the way Node's `Buffer` spells it and
|
|
5
|
+
* meaning the same bytes.
|
|
6
|
+
*
|
|
7
|
+
* Named here rather than taken from Node's `BufferEncoding`, which is what this option used to be:
|
|
8
|
+
* that type is part of `@types/node`, so it made a browser consumer's public API surface depend on
|
|
9
|
+
* Node's types, and it offered `base64` and `hex` as if they were output encodings for a text
|
|
10
|
+
* format. The list is what a CSV consumer actually asks for.
|
|
11
|
+
*/
|
|
12
|
+
export type CsvEncoding = 'ascii' | 'latin1' | 'ucs-2' | 'ucs2' | 'utf-8' | 'utf-16le' | 'utf16le' | 'utf8';
|
|
3
13
|
export interface CsvWriteOptions {
|
|
4
14
|
/** Which worksheet to write; defaults to the first. A name matching no sheet throws rather than
|
|
5
15
|
* silently emitting an empty file. */
|
|
@@ -14,7 +24,7 @@ export interface CsvWriteOptions {
|
|
|
14
24
|
/** Render Date cells in UTC rather than the runner's local time. */
|
|
15
25
|
readonly dateUTC?: boolean;
|
|
16
26
|
/** Byte encoding for {@link writeCsv}; defaults to `"utf8"`. */
|
|
17
|
-
readonly encoding?:
|
|
27
|
+
readonly encoding?: CsvEncoding;
|
|
18
28
|
/** Prepend a UTF-8 byte-order mark (applies only to UTF-8); defaults to `true` for UTF-8. */
|
|
19
29
|
readonly bom?: boolean;
|
|
20
30
|
/** Per-field transform replacing the default value rendering; receives the cell's value (`null`
|
|
@@ -22,7 +32,12 @@ export interface CsvWriteOptions {
|
|
|
22
32
|
* still applied to the returned text. */
|
|
23
33
|
readonly map?: (value: CellValue, index: number) => string;
|
|
24
34
|
}
|
|
25
|
-
/** The logical CSV text of one worksheet
|
|
35
|
+
/** The logical CSV text of one worksheet: no BOM, no byte encoding. */
|
|
26
36
|
export declare function writeCsvText(workbook: Workbook, options?: CsvWriteOptions): string;
|
|
27
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* The CSV bytes of one worksheet in the requested encoding, with a UTF-8 BOM by default.
|
|
39
|
+
*
|
|
40
|
+
* @throws {AuthoringError} if a field holds an unpaired surrogate and the encoding is UTF-8, which
|
|
41
|
+
* cannot represent one. The alternative is a silent U+FFFD substitution.
|
|
42
|
+
*/
|
|
28
43
|
export declare function writeCsv(workbook: Workbook, options?: CsvWriteOptions): Uint8Array;
|
package/dist/io/csv/write.js
CHANGED
|
@@ -27,15 +27,45 @@ export function writeCsvText(workbook, options = {}) {
|
|
|
27
27
|
export function writeCsv(workbook, options = {}) {
|
|
28
28
|
const text = writeCsvText(workbook, options);
|
|
29
29
|
const encoding = options.encoding ?? 'utf8';
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
const utf8 = isUtf8(encoding);
|
|
31
|
+
if (utf8)
|
|
32
|
+
assertEncodable(text);
|
|
33
|
+
const body = encode(text, encoding);
|
|
34
|
+
const wantBom = options.bom ?? utf8;
|
|
35
|
+
if (!wantBom || !utf8)
|
|
36
|
+
return body;
|
|
34
37
|
const out = new Uint8Array(UTF8_BOM.length + body.length);
|
|
35
38
|
out.set(UTF8_BOM, 0);
|
|
36
39
|
out.set(body, UTF8_BOM.length);
|
|
37
40
|
return out;
|
|
38
41
|
}
|
|
42
|
+
function isUtf8(encoding) {
|
|
43
|
+
return encoding === 'utf8' || encoding === 'utf-8';
|
|
44
|
+
}
|
|
45
|
+
function encode(text, encoding) {
|
|
46
|
+
if (isUtf8(encoding))
|
|
47
|
+
return new TextEncoder().encode(text);
|
|
48
|
+
if (encoding === 'ascii' || encoding === 'latin1') {
|
|
49
|
+
const bytes = new Uint8Array(text.length);
|
|
50
|
+
for (let i = 0; i < text.length; i++)
|
|
51
|
+
bytes[i] = text.charCodeAt(i) & 0xff;
|
|
52
|
+
return bytes;
|
|
53
|
+
}
|
|
54
|
+
const bytes = new Uint8Array(text.length * 2);
|
|
55
|
+
const view = new DataView(bytes.buffer);
|
|
56
|
+
for (let i = 0; i < text.length; i++)
|
|
57
|
+
view.setUint16(i * 2, text.charCodeAt(i), true);
|
|
58
|
+
return bytes;
|
|
59
|
+
}
|
|
60
|
+
function assertEncodable(text) {
|
|
61
|
+
const found = LONE_SURROGATE.exec(text);
|
|
62
|
+
if (found === null)
|
|
63
|
+
return;
|
|
64
|
+
const codePoint = text.codePointAt(found.index).toString(16).toUpperCase();
|
|
65
|
+
throw new AuthoringError(`cannot write U+${codePoint} at offset ${found.index} of the CSV text: it is an unpaired ` +
|
|
66
|
+
'surrogate, which UTF-8 cannot encode and CSV has no escape for');
|
|
67
|
+
}
|
|
68
|
+
const LONE_SURROGATE = /[\u{D800}-\u{DFFF}]/u;
|
|
39
69
|
function selectSheet(workbook, name) {
|
|
40
70
|
if (name === undefined) {
|
|
41
71
|
const first = workbook.worksheets[0];
|
package/dist/io/opc/errors.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { XlsxError } from '../../errors.ts';
|
|
2
2
|
/**
|
|
3
3
|
* Which unsupported input the reader recognised:
|
|
4
|
-
* - `'xls'
|
|
5
|
-
* - `'xlsb'
|
|
4
|
+
* - `'xls'`: a legacy BIFF `.xls` (an OLE2/CFB compound file), detected by its magic bytes.
|
|
5
|
+
* - `'xlsb'`: a binary BIFF12 `.xlsb`, the same OPC/ZIP container as `.xlsx`, but its office document
|
|
6
6
|
* is `xl/workbook.bin` rather than `xl/workbook.xml`. `readXlsx`/`readXlsb` read one; the entry points
|
|
7
7
|
* that cannot yet (the row streamer) report it under this format with their own message.
|
|
8
|
-
* - `'unknown'
|
|
8
|
+
* - `'unknown'`: not a recognised spreadsheet at all, meaning not a ZIP, or a ZIP carrying no OOXML workbook
|
|
9
9
|
* part (nor a `.xlsb` binary one).
|
|
10
10
|
*/
|
|
11
11
|
export type UnsupportedFormat = 'xls' | 'xlsb' | 'unknown';
|
|
@@ -14,7 +14,7 @@ export type UnsupportedFormat = 'xls' | 'xlsb' | 'unknown';
|
|
|
14
14
|
* caller keys on (rather than a subclass per format), so a `catch` can distinguish a legacy `.xls`, a
|
|
15
15
|
* binary `.xlsb`, and an unrecognised blob without string-matching the message.
|
|
16
16
|
*
|
|
17
|
-
* The message never carries a filesystem path or the underlying zip library's internals
|
|
17
|
+
* The message never carries a filesystem path or the underlying zip library's internals. The whole
|
|
18
18
|
* point of the type is that the classification, not a leaked lower-layer string, is what the caller sees.
|
|
19
19
|
*
|
|
20
20
|
* {@link format} stays the branch for *which* unsupported input this was; the inherited
|
|
@@ -33,11 +33,11 @@ export declare class UnsupportedFormatError extends XlsxError {
|
|
|
33
33
|
*
|
|
34
34
|
* The neighbouring {@link UnsupportedFormatError} says the input is a different *kind* of thing; this
|
|
35
35
|
* one says it is the right kind and we will not (or cannot) unpack it. Keeping them apart is what
|
|
36
|
-
* lets a caller answer "should I try another reader, or reject this file?"
|
|
36
|
+
* lets a caller answer "should I try another reader, or reject this file?", and it is what replaced
|
|
37
37
|
* the message-prefix match the bomb refusal used to be recognised by.
|
|
38
38
|
*
|
|
39
39
|
* The zip library's own failure text never survives into either the message or `cause`: it can name
|
|
40
|
-
* internals
|
|
40
|
+
* internals, or an absolute filesystem path, from the layer below, and this type carries the
|
|
41
41
|
* classification precisely so no lower-layer string has to.
|
|
42
42
|
*/
|
|
43
43
|
export declare class PackageReadError extends XlsxError {
|
package/dist/io/opc/inflate.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @param cap Maximum total uncompressed output, in bytes, across all parts. Enforced
|
|
7
7
|
* against bytes actually produced, never against the archive's declared sizes.
|
|
8
8
|
* @returns A map of part path to inflated bytes.
|
|
9
|
-
* @throws {PackageReadError} if inflation would exceed `cap
|
|
9
|
+
* @throws {PackageReadError} if inflation would exceed `cap`, a probable zip bomb.
|
|
10
10
|
* @throws {Error} raised by the zip layer if the archive is malformed or a part uses an unsupported
|
|
11
11
|
* compression method. Callers reach this through {@link inflateSpreadsheetPackage}, which is where
|
|
12
12
|
* those are classified; the raw error is deliberately not re-typed here, because its text is the
|
package/dist/io/opc/inflate.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Unzip, UnzipInflate } from 'fflate';
|
|
2
|
+
import { concat } from '../../bytes.js';
|
|
2
3
|
import { PackageReadError } from './errors.js';
|
|
3
4
|
const INPUT_SLICE = 1 << 14;
|
|
4
5
|
export function inflatePackage(data, cap) {
|
|
@@ -23,7 +24,7 @@ export function inflatePackage(data, cap) {
|
|
|
23
24
|
chunks.push(chunk);
|
|
24
25
|
size += chunk.length;
|
|
25
26
|
if (final)
|
|
26
|
-
files[file.name] =
|
|
27
|
+
files[file.name] = concat(chunks, size);
|
|
27
28
|
};
|
|
28
29
|
try {
|
|
29
30
|
file.start();
|
|
@@ -43,14 +44,3 @@ export function inflatePackage(data, cap) {
|
|
|
43
44
|
throw failure;
|
|
44
45
|
return files;
|
|
45
46
|
}
|
|
46
|
-
function join(chunks, size) {
|
|
47
|
-
if (chunks.length === 1)
|
|
48
|
-
return chunks[0];
|
|
49
|
-
const out = new Uint8Array(size);
|
|
50
|
-
let at = 0;
|
|
51
|
-
for (const chunk of chunks) {
|
|
52
|
-
out.set(chunk, at);
|
|
53
|
-
at += chunk.length;
|
|
54
|
-
}
|
|
55
|
-
return out;
|
|
56
|
-
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The namespace URIs the Open Packaging Conventions layer itself owns
|
|
2
|
+
* The namespace URIs the Open Packaging Conventions layer itself owns: the ones that describe a
|
|
3
3
|
* *package* rather than the spreadsheet inside it. Every OOXML package carries these regardless of
|
|
4
4
|
* which serialisation its office document uses, so an `.xlsb` and an `.xlsx` agree on them exactly.
|
|
5
5
|
*
|
|
@@ -2,14 +2,13 @@ import type { PreservedPart } from '../../core/preserved.ts';
|
|
|
2
2
|
export interface PackageAccessors {
|
|
3
3
|
/** A part's decoded text, or undefined when the package holds no such part. Decodes lazily, so a
|
|
4
4
|
* part the reader never asks for is never stringified. */
|
|
5
|
-
partText(path: string)
|
|
5
|
+
partText: (path: string) => string | undefined;
|
|
6
6
|
/** A part's raw bytes, or undefined when the package holds no such part. */
|
|
7
|
-
partBytes(path: string)
|
|
7
|
+
partBytes: (path: string) => Uint8Array | undefined;
|
|
8
8
|
}
|
|
9
9
|
export declare function packageAccessors(files: Record<string, Uint8Array>): PackageAccessors;
|
|
10
10
|
export declare function relationshipTargetByType(xml: string, suffix: string): string | undefined;
|
|
11
11
|
export declare function relationshipTargetsByType(xml: string, suffix: string): string[];
|
|
12
|
-
export declare function sheetRelTarget(sheetPath: string, partText: (path: string) => string | undefined, type: string): string | undefined;
|
|
13
12
|
export declare function resolveRelativePart(basePart: string, target: string): string;
|
|
14
13
|
export declare function resolveWorkbookPart(target: string): string;
|
|
15
14
|
export declare function parseRelationships(xml: string): Map<string, string>;
|
|
@@ -20,5 +19,22 @@ export interface RelationshipRecord {
|
|
|
20
19
|
readonly external: boolean;
|
|
21
20
|
}
|
|
22
21
|
export declare function parseRelationshipRecords(xml: string): RelationshipRecord[];
|
|
22
|
+
export interface PartRelationships {
|
|
23
|
+
/** Every relationship the part declares, in declaration order. */
|
|
24
|
+
readonly records: readonly RelationshipRecord[];
|
|
25
|
+
/** The relationship with this id, or undefined. Its `target` is raw: an external one is a URL, not a
|
|
26
|
+
* package path, so a caller that may see `TargetMode="External"` must read it before resolving. */
|
|
27
|
+
byId(id: string): RelationshipRecord | undefined;
|
|
28
|
+
/** Resolve one of this part's targets against the part's own directory. */
|
|
29
|
+
pathOf(target: string): string;
|
|
30
|
+
/** The package part reached through the first relationship whose Type ends with `/<suffix>`, or
|
|
31
|
+
* undefined when the part declares none: the single-part lookup (notes, printer settings, drawing,
|
|
32
|
+
* background) in one call. */
|
|
33
|
+
targetPath(suffix: string): string | undefined;
|
|
34
|
+
/** Every package part reached through a relationship of this type, in declaration order. For a part
|
|
35
|
+
* class one sheet may reference more than once (tables, pivot tables). */
|
|
36
|
+
targetPaths(suffix: string): string[];
|
|
37
|
+
}
|
|
38
|
+
export declare function readPartRelationships(partPath: string, partText: (path: string) => string | undefined): PartRelationships;
|
|
23
39
|
export declare function contentTypeResolver(contentTypesXml: string): (path: string) => string;
|
|
24
40
|
export declare function capturePartClosure(entryPath: string, partText: (path: string) => string | undefined, partBytes: (path: string) => Uint8Array | undefined, contentTypeOf: (path: string) => string): readonly PreservedPart[] | undefined;
|
package/dist/io/opc/read-opc.js
CHANGED
|
@@ -3,7 +3,7 @@ import { openElements } from '../../xml/xml-read.js';
|
|
|
3
3
|
import { extensionOf, relsPathFor } from './part-paths.js';
|
|
4
4
|
export function packageAccessors(files) {
|
|
5
5
|
return {
|
|
6
|
-
partText(path) {
|
|
6
|
+
partText: (path) => {
|
|
7
7
|
const bytes = files[path];
|
|
8
8
|
return bytes === undefined ? undefined : strFromU8(bytes);
|
|
9
9
|
},
|
|
@@ -24,13 +24,6 @@ export function relationshipTargetsByType(xml, suffix) {
|
|
|
24
24
|
}
|
|
25
25
|
return targets;
|
|
26
26
|
}
|
|
27
|
-
export function sheetRelTarget(sheetPath, partText, type) {
|
|
28
|
-
const relsXml = partText(relsPathFor(sheetPath));
|
|
29
|
-
if (relsXml === undefined)
|
|
30
|
-
return undefined;
|
|
31
|
-
const target = relationshipTargetByType(relsXml, type);
|
|
32
|
-
return target === undefined ? undefined : resolveRelativePart(sheetPath, target);
|
|
33
|
-
}
|
|
34
27
|
export function resolveRelativePart(basePart, target) {
|
|
35
28
|
if (target.startsWith('/'))
|
|
36
29
|
return target.slice(1);
|
|
@@ -74,6 +67,19 @@ export function parseRelationshipRecords(xml) {
|
|
|
74
67
|
}
|
|
75
68
|
return records;
|
|
76
69
|
}
|
|
70
|
+
export function readPartRelationships(partPath, partText) {
|
|
71
|
+
const records = parseRelationshipRecords(partText(relsPathFor(partPath)) ?? '');
|
|
72
|
+
const byId = new Map(records.map((record) => [record.id, record]));
|
|
73
|
+
const pathOf = (target) => resolveRelativePart(partPath, target);
|
|
74
|
+
const targetsOf = (suffix) => records.filter((record) => record.type.endsWith(`/${suffix}`)).map((record) => record.target);
|
|
75
|
+
return {
|
|
76
|
+
records,
|
|
77
|
+
byId: (id) => byId.get(id),
|
|
78
|
+
pathOf,
|
|
79
|
+
targetPath: (suffix) => targetsOf(suffix).map(pathOf)[0],
|
|
80
|
+
targetPaths: (suffix) => targetsOf(suffix).map(pathOf),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
77
83
|
export function contentTypeResolver(contentTypesXml) {
|
|
78
84
|
const overrides = new Map();
|
|
79
85
|
const defaults = new Map();
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export interface ReadXlsxOptions {
|
|
2
2
|
/**
|
|
3
3
|
* Maximum total uncompressed output, in bytes, produced while inflating the package.
|
|
4
|
-
* The bound is enforced by a running counter as bytes are decompressed
|
|
5
|
-
* the archive's (untrusted, forgeable) size headers
|
|
4
|
+
* The bound is enforced by a running counter as bytes are decompressed, never read from
|
|
5
|
+
* the archive's (untrusted, forgeable) size headers, so a zip bomb that lies about its
|
|
6
6
|
* uncompressed size is rejected all the same. Defaults to 512 MiB.
|
|
7
7
|
*/
|
|
8
8
|
readonly maxUncompressedBytes?: number;
|
package/dist/io/opc/rels.d.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A single `<Relationship>`. An `external` target lives outside the package (a hyperlink URL), so the
|
|
3
|
+
* element carries `TargetMode="External"`; a package-internal target (the default) omits it.
|
|
4
|
+
*
|
|
5
|
+
* All three values are escaped here, unconditionally. The obligation used to sit in a comment saying
|
|
6
|
+
* the caller escaped a target it did not control, which made the safety of this function a property
|
|
7
|
+
* of its call sites rather than of itself, on the one boundary in the tree where `xml.ts` says that is
|
|
8
|
+
* explicitly not how it is done. Escaping a writer-controlled package path is the identity, so the
|
|
9
|
+
* generated chains emit the same bytes and the guarantee holds by construction instead of by
|
|
10
|
+
* inspecting every caller. `TargetMode` stays a fixed token, not a value.
|
|
11
|
+
*/
|
|
1
12
|
export declare function relationship(id: string, type: string, target: string, options?: {
|
|
2
13
|
external?: boolean;
|
|
3
14
|
}): string;
|
package/dist/io/opc/rels.js
CHANGED
|
@@ -2,13 +2,14 @@ import { escapeAttr, XML_DECLARATION } from '../../xml/xml.js';
|
|
|
2
2
|
import { PKG_RELS_NS } from './namespaces.js';
|
|
3
3
|
export function relationship(id, type, target, options) {
|
|
4
4
|
const mode = options?.external ? ' TargetMode="External"' : '';
|
|
5
|
-
return `<Relationship Id="${id}" Type="${type}"
|
|
5
|
+
return (`<Relationship Id="${escapeAttr(id)}" Type="${escapeAttr(type)}" ` +
|
|
6
|
+
`Target="${escapeAttr(target)}"${mode}/>`);
|
|
6
7
|
}
|
|
7
8
|
export function relationshipsPart(relationships) {
|
|
8
9
|
return `${XML_DECLARATION}<Relationships xmlns="${PKG_RELS_NS}">${relationships.join('')}</Relationships>`;
|
|
9
10
|
}
|
|
10
11
|
export function preservedRelsXml(rels) {
|
|
11
|
-
return relationshipsPart(rels.map((rel) => relationship(rel.id, rel.type,
|
|
12
|
+
return relationshipsPart(rels.map((rel) => relationship(rel.id, rel.type, rel.target, rel.external ? { external: true } : {})));
|
|
12
13
|
}
|
|
13
14
|
export function relsPartXml(rels) {
|
|
14
15
|
return relationshipsPart(rels.map((rel) => relationship(rel.id, rel.type, rel.target)));
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { UnsupportedFormatError } from './errors.ts';
|
|
2
2
|
/** The container kind a leading magic-byte sniff distinguishes, before any inflation. */
|
|
3
3
|
export type Container = 'cfb' | 'zip' | 'other';
|
|
4
|
-
/** Classify a blob's container by its leading magic bytes alone
|
|
4
|
+
/** Classify a blob's container by its leading magic bytes alone: no allocation, no inflation. */
|
|
5
5
|
export declare function sniffContainer(data: Uint8Array): Container;
|
|
6
6
|
/**
|
|
7
|
-
* Inflate a spreadsheet package (`.xlsx` or `.xlsb
|
|
7
|
+
* Inflate a spreadsheet package (`.xlsx` or `.xlsb`; the container is the same), translating input
|
|
8
8
|
* that is neither into a typed error before or instead of a raw zip failure:
|
|
9
9
|
* - a legacy `.xls` (CFB) blob → {@link UnsupportedFormatError} `'xls'`, caught by the magic sniff so
|
|
10
10
|
* fflate never runs on it;
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { type Cell } from '../../core/cell.ts';
|
|
2
|
-
import type
|
|
2
|
+
import { type Border, type CellStyle, type Fill, type Font, type NamedCellStyle } from '../../core/style.ts';
|
|
3
3
|
/**
|
|
4
4
|
* What an xf resolves to: the {@link CellStyle} facet tuple, plus the two flags an xf carries that
|
|
5
5
|
* are not facets. Absent facets stay undefined, matching the contract that an unset facet is simply
|
|
6
6
|
* not present on the reconstructed cell.
|
|
7
7
|
*
|
|
8
8
|
* It *derives* the facets rather than listing them, so a seventh facet added to `CellStyle` reaches
|
|
9
|
-
*
|
|
9
|
+
* every codec the moment it joins. Re-declaring them here, the shape this replaced, meant a new
|
|
10
10
|
* facet silently stopped at the model and never appeared in a file we read back.
|
|
11
|
+
*
|
|
12
|
+
* Read-only throughout: an xf is a resolved snapshot, assembled once and then only consulted. Both
|
|
13
|
+
* readers already build theirs through an explicitly-mutable draft (`{-readonly [K in keyof
|
|
14
|
+
* XfStyle]?: …}`), so the constraint costs nothing and stops a consumer editing a table entry that
|
|
15
|
+
* other cells share.
|
|
11
16
|
*/
|
|
12
|
-
export interface XfStyle extends CellStyle {
|
|
17
|
+
export interface XfStyle extends Readonly<CellStyle> {
|
|
13
18
|
readonly quotePrefix?: boolean;
|
|
14
19
|
/** The `xfId` link into the named-style layer (`cellStyleXfs`); absent for the Normal default (0). */
|
|
15
20
|
readonly xfId?: number;
|
|
@@ -21,7 +26,7 @@ export interface StyleTable {
|
|
|
21
26
|
readonly cellXfs: ReadonlyArray<XfStyle>;
|
|
22
27
|
readonly namedStyles: ReadonlyArray<NamedCellStyle>;
|
|
23
28
|
/**
|
|
24
|
-
* Font id 0
|
|
29
|
+
* Font id 0: the workbook's declared default font, the face every cell naming no font renders in.
|
|
25
30
|
* Surfaced separately from the fonts it was flattened onto because it is workbook-level state, not a
|
|
26
31
|
* cell format: a re-write must emit *this* face as font 0 rather than an assumed Calibri, or every
|
|
27
32
|
* empty cell changes face and every character-unit column width changes meaning. Absent when the
|
|
@@ -31,17 +36,49 @@ export interface StyleTable {
|
|
|
31
36
|
}
|
|
32
37
|
/**
|
|
33
38
|
* The format code a number-format id denotes: the file's own `<numFmt>`/`BrtFmt` declaration if it
|
|
34
|
-
* has one, else the built-in Excel defines for that id. Id 0 is General
|
|
39
|
+
* has one, else the built-in Excel defines for that id. Id 0 is General, the absence of a format,
|
|
35
40
|
* and resolves to nothing so an ordinary cell carries no `numFmt`.
|
|
36
41
|
*/
|
|
37
42
|
export declare function numFmtCodeFor(id: number, custom: ReadonlyMap<number, string>): string | undefined;
|
|
38
43
|
/**
|
|
39
|
-
* Apply a resolved xf's non-value facets to a cell
|
|
44
|
+
* Apply a resolved xf's non-value facets to a cell: the six {@link CellStyle} facets through the
|
|
40
45
|
* shared {@link applyCellStyle}, plus the two links that live on the xf itself rather than in the
|
|
41
46
|
* facet tuple (`quotePrefix`, and the `xfId` pointer into the named-style layer).
|
|
42
47
|
*
|
|
43
48
|
* Shared by every path that commits a cell: the XML reader's ordinary and shared-formula-clone paths,
|
|
44
|
-
* and the BIFF12 reader
|
|
49
|
+
* and the BIFF12 reader, so a styled cell keeps its look regardless of which serialisation it came
|
|
45
50
|
* from, and the two cannot drift on what "applying a style" means.
|
|
46
51
|
*/
|
|
47
52
|
export declare function applyXfToCell(cell: Cell, style: XfStyle | undefined): void;
|
|
53
|
+
/**
|
|
54
|
+
* A `<cellStyle>` / `BrtStyle` label: the name and builtinId that title one `cellStyleXfs` entry,
|
|
55
|
+
* keyed to that entry's index.
|
|
56
|
+
*/
|
|
57
|
+
export interface StyleLabel {
|
|
58
|
+
readonly xfId: number;
|
|
59
|
+
readonly name?: string;
|
|
60
|
+
readonly builtinId?: number;
|
|
61
|
+
}
|
|
62
|
+
/** The sub-tables an xf resolves its facet ids against, in whichever spelling the codec parsed them. */
|
|
63
|
+
export interface XfDeps {
|
|
64
|
+
readonly fonts: ReadonlyArray<Font | undefined>;
|
|
65
|
+
readonly fills: ReadonlyArray<Fill | undefined>;
|
|
66
|
+
readonly borders: ReadonlyArray<Border | undefined>;
|
|
67
|
+
readonly numFmtCodes: ReadonlyMap<number, string>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Turn the four tables a style-sheet parse yields into the {@link StyleTable} both codecs hand back:
|
|
71
|
+
* layer each direct xf over the named style it links to, title the named layer with its labels, and
|
|
72
|
+
* carry font 0 out as the workbook default.
|
|
73
|
+
*
|
|
74
|
+
* A facet the direct xf sets wins; one it leaves unset falls through to the named base; and the
|
|
75
|
+
* `xfId` link is carried through so a re-write keeps it. None of that depends on whether the tables
|
|
76
|
+
* were parsed out of `xl/styles.xml` or `xl/styles.bin`, which is the point of stating it once: the
|
|
77
|
+
* two readers used to hold a copy each, cross-referenced by a comment saying they agreed.
|
|
78
|
+
*/
|
|
79
|
+
export declare function resolveStyleTable(tables: {
|
|
80
|
+
readonly directXfs: ReadonlyArray<XfStyle>;
|
|
81
|
+
readonly namedXfs: ReadonlyArray<XfStyle>;
|
|
82
|
+
readonly labels: ReadonlyArray<StyleLabel>;
|
|
83
|
+
readonly fonts: ReadonlyArray<Font | undefined>;
|
|
84
|
+
}): StyleTable;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { applyCellStyle } from '../../core/cell.js';
|
|
2
2
|
import { NAMED_STYLE_ID } from '../../core/internal.js';
|
|
3
|
+
import { assignStyleFacets, } from '../../core/style.js';
|
|
3
4
|
const BUILTIN_NUMFMTS = new Map([
|
|
4
5
|
[1, '0'],
|
|
5
6
|
[2, '0.00'],
|
|
@@ -62,3 +63,29 @@ export function applyXfToCell(cell, style) {
|
|
|
62
63
|
if (style.xfId !== undefined)
|
|
63
64
|
cell[NAMED_STYLE_ID] = style.xfId;
|
|
64
65
|
}
|
|
66
|
+
export function resolveStyleTable(tables) {
|
|
67
|
+
const { directXfs, namedXfs, labels, fonts } = tables;
|
|
68
|
+
const cellXfs = directXfs.map((xf) => {
|
|
69
|
+
if (xf.xfId === undefined)
|
|
70
|
+
return xf;
|
|
71
|
+
const named = namedXfs[xf.xfId];
|
|
72
|
+
return named === undefined ? xf : { ...named, ...xf };
|
|
73
|
+
});
|
|
74
|
+
const labelsByXfId = new Map();
|
|
75
|
+
for (const label of labels) {
|
|
76
|
+
if (!labelsByXfId.has(label.xfId))
|
|
77
|
+
labelsByXfId.set(label.xfId, label);
|
|
78
|
+
}
|
|
79
|
+
const namedStyles = namedXfs.map((xf, index) => {
|
|
80
|
+
const label = labelsByXfId.get(index);
|
|
81
|
+
const style = {};
|
|
82
|
+
assignStyleFacets(style, xf);
|
|
83
|
+
if (label?.name !== undefined)
|
|
84
|
+
style.name = label.name;
|
|
85
|
+
if (label?.builtinId !== undefined)
|
|
86
|
+
style.builtinId = label.builtinId;
|
|
87
|
+
return style;
|
|
88
|
+
});
|
|
89
|
+
const defaultFont = fonts[0];
|
|
90
|
+
return defaultFont === undefined ? { cellXfs, namedStyles } : { cellXfs, namedStyles, defaultFont };
|
|
91
|
+
}
|
package/dist/io/xlsb/errors.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { XlsxError } from '../../errors.ts';
|
|
2
2
|
/**
|
|
3
|
-
* Thrown when an `.xlsb` package's binary BIFF12 content cannot be parsed
|
|
3
|
+
* Thrown when an `.xlsb` package's binary BIFF12 content cannot be parsed: a record whose declared
|
|
4
4
|
* size runs past the end of its part, a truncated record header, or a structure that does not conform
|
|
5
5
|
* to [MS-XLSB].
|
|
6
6
|
*
|
|
@@ -7,16 +7,16 @@ export interface ExternSheetRef {
|
|
|
7
7
|
}
|
|
8
8
|
/** The workbook-level tables a formula's references and names resolve through. */
|
|
9
9
|
export interface FormulaScope {
|
|
10
|
-
/** Sheet names in workbook (tab) order
|
|
10
|
+
/** Sheet names in workbook (tab) order: what an `Xti`'s sheet indices point into. */
|
|
11
11
|
readonly sheetNames: readonly string[];
|
|
12
12
|
/** The `BrtExternSheet` table, indexed by a 3-D token's `ixti`. */
|
|
13
13
|
readonly externSheets: readonly ExternSheetRef[];
|
|
14
14
|
/** The index of the supporting book that is this workbook, or `undefined` when the file declares a
|
|
15
15
|
* supporting book this reader does not recognise. A workbook with no external links declares
|
|
16
|
-
* exactly one
|
|
16
|
+
* exactly one, itself, so this is the ordinary case; anything else leaves the indices untrustworthy
|
|
17
17
|
* and no 3-D reference resolves, which drops those formulas rather than naming the wrong sheet. */
|
|
18
18
|
readonly selfSupBook: number | undefined;
|
|
19
|
-
/** Every `BrtName` in file order, function placeholders included
|
|
19
|
+
/** Every `BrtName` in file order, function placeholders included. A `PtgName` cites one by
|
|
20
20
|
* **1-based** index, so filtering this list would misaddress every name reference. */
|
|
21
21
|
readonly names: readonly string[];
|
|
22
22
|
}
|
|
@@ -28,7 +28,7 @@ export interface FormulaAnchor {
|
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
30
|
* Decode a `CellParsedFormula`'s token stream into formula text, in the same on-disk spelling the XML
|
|
31
|
-
* form writes into `<f
|
|
31
|
+
* form writes into `<f>`, `_xlfn.`-prefixed function names included, so the caller applies the same
|
|
32
32
|
* `unmangleFunctions` normalisation to either serialisation.
|
|
33
33
|
*
|
|
34
34
|
* @param rgce the token stream.
|
|
@@ -7,7 +7,7 @@ export interface CellHeader {
|
|
|
7
7
|
/** Zero-based index into the style sheet's cell-XF collection. */
|
|
8
8
|
readonly styleIndex: number;
|
|
9
9
|
}
|
|
10
|
-
/** An `UncheckedRfX` ([MS-XLSB] 2.5.155) cell range
|
|
10
|
+
/** An `UncheckedRfX` ([MS-XLSB] 2.5.155) cell range, all four bounds zero-based and inclusive. */
|
|
11
11
|
export interface RangeBounds {
|
|
12
12
|
readonly rowFirst: number;
|
|
13
13
|
readonly rowLast: number;
|
|
@@ -18,7 +18,7 @@ export interface RangeBounds {
|
|
|
18
18
|
* A bounds-checked cursor over one record's payload.
|
|
19
19
|
*
|
|
20
20
|
* Each accessor advances the cursor by exactly the bytes it consumed, so a record is decoded by
|
|
21
|
-
* naming its fields in order. Reading past the payload throws {@link XlsbParseError}
|
|
21
|
+
* naming its fields in order. Reading past the payload throws {@link XlsbParseError}: a record that
|
|
22
22
|
* is shorter than its own definition is a malformed file, not a case to guess through.
|
|
23
23
|
*/
|
|
24
24
|
export declare class RecordReader {
|
|
@@ -28,10 +28,10 @@ export declare class RecordReader {
|
|
|
28
28
|
get remaining(): number;
|
|
29
29
|
/** Whether the whole payload has been consumed. */
|
|
30
30
|
get done(): boolean;
|
|
31
|
-
/** Advance past `count` bytes without decoding them
|
|
31
|
+
/** Advance past `count` bytes without decoding them: a reserved or unmodelled field. */
|
|
32
32
|
skip(count: number): void;
|
|
33
33
|
/**
|
|
34
|
-
* The next `count` bytes as a **view**, for a field whose own decoding happens elsewhere
|
|
34
|
+
* The next `count` bytes as a **view**, for a field whose own decoding happens elsewhere: a formula
|
|
35
35
|
* token stream, whose meaning depends on workbook tables this record knows nothing about. A view
|
|
36
36
|
* rather than a copy for the same reason a record's payload is one: the declared length comes from
|
|
37
37
|
* the file, so it must bound a read, never an allocation.
|
|
@@ -46,7 +46,7 @@ export declare class RecordReader {
|
|
|
46
46
|
f64(): number;
|
|
47
47
|
/**
|
|
48
48
|
* An `RkNumber` ([MS-XLSB] 2.5.122): a number packed into 32 bits. Two flag bits steal the low end
|
|
49
|
-
* of the word
|
|
49
|
+
* of the word: `fInt` says the remaining 30 bits are a signed integer rather than the *high* 30
|
|
50
50
|
* bits of a double whose low 34 bits are zero, and `fX100` says the result was scaled up by 100 to
|
|
51
51
|
* keep two decimal places in the integer form. It exists because most real spreadsheet numbers are
|
|
52
52
|
* small integers or two-decimal currency, and this stores them in half the bytes of a double.
|
|
@@ -55,7 +55,7 @@ export declare class RecordReader {
|
|
|
55
55
|
/** An `XLWideString` ([MS-XLSB] 2.5.169): a 4-byte character count then that many UTF-16LE units. */
|
|
56
56
|
wideString(): string;
|
|
57
57
|
/**
|
|
58
|
-
* A UTF-16 string whose character count is 16-bit rather than 32-bit
|
|
58
|
+
* A UTF-16 string whose character count is 16-bit rather than 32-bit: the form used *inside* a
|
|
59
59
|
* formula token stream (`PtgStr`, and the string elements of an array constant), where a 4-byte
|
|
60
60
|
* count on every literal would be pure overhead.
|
|
61
61
|
*/
|
|
@@ -64,7 +64,7 @@ export declare class RecordReader {
|
|
|
64
64
|
nullableWideString(): string | undefined;
|
|
65
65
|
/**
|
|
66
66
|
* A `RichStr` ([MS-XLSB] 2.5.124): a string that may carry per-run formatting and phonetic guides.
|
|
67
|
-
* Only the text is returned
|
|
67
|
+
* Only the text is returned; the run and phonetic tails are left unread, which is safe because the
|
|
68
68
|
* record's framing (not this cursor) bounds where the payload ends.
|
|
69
69
|
*/
|
|
70
70
|
richString(): string;
|
|
@@ -77,7 +77,7 @@ export declare class RecordReader {
|
|
|
77
77
|
*
|
|
78
78
|
* The four encodings are mutually exclusive and the type tag picks which of the payload's fields
|
|
79
79
|
* carry meaning; the rest are explicitly undefined. An *automatic* colour (type 0) names nothing at
|
|
80
|
-
* all, and reads back as no colour
|
|
80
|
+
* all, and reads back as no colour: the same absence the XML reader produces for `<color auto="1"/>`,
|
|
81
81
|
* so a cell whose font colour was never set does not gain one on read.
|
|
82
82
|
*/
|
|
83
83
|
color(): Color | undefined;
|
|
@@ -5,7 +5,7 @@ export declare function functionNameFor(index: number): string | undefined;
|
|
|
5
5
|
/**
|
|
6
6
|
* How many arguments a fixed-arity function takes, or `undefined` for one whose argument count varies.
|
|
7
7
|
*
|
|
8
|
-
* A `PtgFunc` token states only *which* function is called, never with how many arguments
|
|
8
|
+
* A `PtgFunc` token states only *which* function is called, never with how many arguments: it is the
|
|
9
9
|
* token Excel emits precisely because the count is implied by the function. So decoding `ROUND(A1,2)`
|
|
10
10
|
* back from its two operands and one call token is impossible without this: the arity is the only
|
|
11
11
|
* thing that says which operands on the stack belong to the call. (`PtgFuncVar` carries its own count
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { numFmtCodeFor } from '../style/xf-style.js';
|
|
1
|
+
import { numFmtCodeFor, resolveStyleTable, } from '../style/xf-style.js';
|
|
3
2
|
import { RecordReader } from './primitives.js';
|
|
4
3
|
import { readRecords } from './record-stream.js';
|
|
5
4
|
import { BRT } from './record-types.js';
|
|
@@ -74,24 +73,7 @@ export function parseStyleTable(part) {
|
|
|
74
73
|
break;
|
|
75
74
|
}
|
|
76
75
|
}
|
|
77
|
-
|
|
78
|
-
if (xf.xfId === undefined)
|
|
79
|
-
return xf;
|
|
80
|
-
const named = namedXfs[xf.xfId];
|
|
81
|
-
return named === undefined ? xf : { ...named, ...xf };
|
|
82
|
-
});
|
|
83
|
-
const namedStyles = namedXfs.map((xf, index) => {
|
|
84
|
-
const label = labels.find((entry) => entry.xfId === index);
|
|
85
|
-
const style = {};
|
|
86
|
-
assignStyleFacets(style, xf);
|
|
87
|
-
if (label?.name !== undefined)
|
|
88
|
-
style.name = label.name;
|
|
89
|
-
if (label?.builtinId !== undefined)
|
|
90
|
-
style.builtinId = label.builtinId;
|
|
91
|
-
return style;
|
|
92
|
-
});
|
|
93
|
-
const defaultFont = fonts[0];
|
|
94
|
-
return defaultFont === undefined ? { cellXfs, namedStyles } : { cellXfs, namedStyles, defaultFont };
|
|
76
|
+
return resolveStyleTable({ directXfs, namedXfs, labels, fonts });
|
|
95
77
|
}
|
|
96
78
|
function readXf(reader, deps, isDirect) {
|
|
97
79
|
const parent = reader.u16();
|
package/dist/io/xlsb/read.d.ts
CHANGED
|
@@ -5,10 +5,10 @@ export declare const XLSB_WORKBOOK_PART = "xl/workbook.bin";
|
|
|
5
5
|
/**
|
|
6
6
|
* Read an `.xlsb` (binary BIFF12) package into a {@link Workbook}.
|
|
7
7
|
*
|
|
8
|
-
* @throws {UnsupportedFormatError} if the input is not an `.xlsb` package
|
|
8
|
+
* @throws {UnsupportedFormatError} if the input is not an `.xlsb` package: a legacy `.xls`
|
|
9
9
|
* (`.format === 'xls'`), an XML `.xlsx` or unrecognised blob (`'unknown'`).
|
|
10
10
|
* @throws {XlsbParseError} if a binary part is malformed.
|
|
11
|
-
* @throws {PackageReadError} if the input is a ZIP that cannot be unpacked
|
|
11
|
+
* @throws {PackageReadError} if the input is a ZIP that cannot be unpacked: a corrupt or
|
|
12
12
|
* truncated archive, or one exceeding the inflate bound (a probable zip bomb).
|
|
13
13
|
*/
|
|
14
14
|
export declare function readXlsb(data: Uint8Array, options?: ReadXlsxOptions): Workbook;
|