@build-qube/papyra 0.3.0 → 0.4.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.
@@ -0,0 +1,148 @@
1
+ import type { CellWindow as NativeCellWindow } from '@build-qube/papyra-native';
2
+ /** What a cell holds. A formula cell reports the result Excel last computed. */
3
+ export type CellKind = 'empty' | 'number' | 'text' | 'bool' | 'date' | 'duration' | 'error';
4
+ /** A cell with nothing in it, or outside the sheet's used range. */
5
+ export interface EmptyCell {
6
+ /** Always `'empty'`. */
7
+ kind: 'empty';
8
+ /** Always `''`. */
9
+ text: '';
10
+ }
11
+ /** A number, or in CSV a field that is unambiguously one. */
12
+ export interface NumberCell {
13
+ /** Always `'number'`. */
14
+ kind: 'number';
15
+ /** The value. */
16
+ value: number;
17
+ /**
18
+ * Excel's General rendering for a workbook. For CSV, the field exactly as
19
+ * written: `2.50` stays `2.50`.
20
+ */
21
+ text: string;
22
+ }
23
+ /** A string. Every CSV field that is not a plain number is one. */
24
+ export interface TextCell {
25
+ /** Always `'text'`. */
26
+ kind: 'text';
27
+ /** The string. */
28
+ text: string;
29
+ }
30
+ /** A boolean. */
31
+ export interface BoolCell {
32
+ /** Always `'bool'`. */
33
+ kind: 'bool';
34
+ /** The value. */
35
+ value: boolean;
36
+ /** Excel's spelling, which is also what a CSV export of the cell contains. */
37
+ text: 'TRUE' | 'FALSE';
38
+ }
39
+ /** A date, a time, or both. */
40
+ export interface DateCell {
41
+ /** Always `'date'`. */
42
+ kind: 'date';
43
+ /**
44
+ * The Excel date serial: days since 1899-12-30, time as the fraction. NaN for
45
+ * OpenDocument, which stores only the ISO form.
46
+ */
47
+ serial: number;
48
+ /** `2024-03-15`, `2024-03-15T13:30:00`, or `13:30:00` for a time alone. */
49
+ text: string;
50
+ }
51
+ /** A length of time. */
52
+ export interface DurationCell {
53
+ /** Always `'duration'`. */
54
+ kind: 'duration';
55
+ /** Length in days. NaN for OpenDocument, which stores only the text form. */
56
+ days: number;
57
+ /** `[h]:mm:ss` — hours do not wrap at 24. */
58
+ text: string;
59
+ }
60
+ /** An error a formula evaluated to. */
61
+ export interface ErrorCell {
62
+ /** Always `'error'`. */
63
+ kind: 'error';
64
+ /** Excel's code for it, e.g. `#DIV/0!`. */
65
+ text: string;
66
+ }
67
+ /**
68
+ * One cell's value, discriminated on `kind`.
69
+ *
70
+ * `text` is always what to display. Number formats are not applied yet, so a
71
+ * currency cell reads `1234.5` rather than `$1,234.50` and a date reads as ISO 8601
72
+ * — the raw value is beside it for anything that needs to compute.
73
+ */
74
+ export type Cell = EmptyCell | NumberCell | TextCell | BoolCell | DateCell | DurationCell | ErrorCell;
75
+ /**
76
+ * Cells merged into one, as a sheet reports them. Inclusive at both ends, like the
77
+ * `A4:B4` Excel would write — hence `lastRow` rather than an exclusive `rowEnd`.
78
+ */
79
+ export interface MergedRange {
80
+ /** 0-based row of the top-left cell, which holds the value. */
81
+ row: number;
82
+ /** 0-based column of the top-left cell. */
83
+ col: number;
84
+ /** Last row covered, inclusive. */
85
+ lastRow: number;
86
+ /** Last column covered, inclusive. */
87
+ lastCol: number;
88
+ }
89
+ /**
90
+ * A rectangle of a sheet, read in one call and decoded on access.
91
+ *
92
+ * Cells cross from Rust as four flat buffers rather than an object each, because
93
+ * building thousands of objects costs more than parsing them did. Nothing is
94
+ * decoded until asked for, so a grid that only draws text never builds a {@link Cell}.
95
+ *
96
+ * Coordinates are the sheet's, not the window's: `text(10, 2)` is row 10 of the
97
+ * sheet whichever row the window starts on. Anything outside the window is empty.
98
+ */
99
+ export declare class CellWindow {
100
+ #private;
101
+ /** First row held. */
102
+ readonly rowStart: number;
103
+ /** First column held. */
104
+ readonly colStart: number;
105
+ /** Rows held, which may be fewer than asked for at the sheet's edge. */
106
+ readonly rows: number;
107
+ /** Columns held. */
108
+ readonly cols: number;
109
+ /** @internal Use `Sheet.window`. */
110
+ constructor(native: NativeCellWindow);
111
+ /** One past the last row held. */
112
+ get rowEnd(): number;
113
+ /** One past the last column held. */
114
+ get colEnd(): number;
115
+ /** What the cell at `(row, col)` holds. Cheaper than {@link cell}. */
116
+ kind(row: number, col: number): CellKind;
117
+ /** The display text at `(row, col)` — all a plain grid needs. */
118
+ text(row: number, col: number): string;
119
+ /**
120
+ * The numeric value at `(row, col)`: a number, a bool as 0 or 1, a date's serial,
121
+ * a duration in days. NaN for anything else.
122
+ */
123
+ number(row: number, col: number): number;
124
+ /**
125
+ * The index of the cell's style in `Sheet.styles`. 0, the default, for a cell
126
+ * with none — and for every cell of a format that carries no styles.
127
+ */
128
+ style(row: number, col: number): number;
129
+ /**
130
+ * The colour the cell's number format chose, as `0xRRGGBB` — the `[Red]` in
131
+ * `#,##0;[Red](#,##0)`. It overrides the style's text colour, as in Excel.
132
+ */
133
+ color(row: number, col: number): number | undefined;
134
+ /** The cell at `(row, col)`, fully decoded. */
135
+ cell(row: number, col: number): Cell;
136
+ }
137
+ /** Unpack the bindings' flat merge quads. @internal */
138
+ export declare function toMergedRanges(quads: Uint32Array): MergedRange[];
139
+ /**
140
+ * The letters Excel heads a column with: 0 is `A`, 25 is `Z`, 26 is `AA`.
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * columnName(27); // 'AB'
145
+ * ```
146
+ */
147
+ export declare function columnName(index: number): string;
148
+ //# sourceMappingURL=cells.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cells.d.ts","sourceRoot":"","sources":["../src/cells.ts"],"names":[],"mappings":"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"}
package/dist/cells.js ADDED
@@ -0,0 +1,144 @@
1
+ /** Indexed by the tag byte the bindings write. Keep in step with `CellKind` in Rust. */
2
+ const KINDS = [
3
+ 'empty',
4
+ 'number',
5
+ 'text',
6
+ 'bool',
7
+ 'date',
8
+ 'duration',
9
+ 'error',
10
+ ];
11
+ /**
12
+ * A rectangle of a sheet, read in one call and decoded on access.
13
+ *
14
+ * Cells cross from Rust as four flat buffers rather than an object each, because
15
+ * building thousands of objects costs more than parsing them did. Nothing is
16
+ * decoded until asked for, so a grid that only draws text never builds a {@link Cell}.
17
+ *
18
+ * Coordinates are the sheet's, not the window's: `text(10, 2)` is row 10 of the
19
+ * sheet whichever row the window starts on. Anything outside the window is empty.
20
+ */
21
+ export class CellWindow {
22
+ /** First row held. */
23
+ rowStart;
24
+ /** First column held. */
25
+ colStart;
26
+ /** Rows held, which may be fewer than asked for at the sheet's edge. */
27
+ rows;
28
+ /** Columns held. */
29
+ cols;
30
+ #native;
31
+ /** @internal Use `Sheet.window`. */
32
+ constructor(native) {
33
+ this.#native = native;
34
+ this.rowStart = native.rowStart;
35
+ this.colStart = native.colStart;
36
+ this.rows = native.rows;
37
+ this.cols = native.cols;
38
+ }
39
+ /** One past the last row held. */
40
+ get rowEnd() {
41
+ return this.rowStart + this.rows;
42
+ }
43
+ /** One past the last column held. */
44
+ get colEnd() {
45
+ return this.colStart + this.cols;
46
+ }
47
+ #index(row, col) {
48
+ const r = row - this.rowStart;
49
+ const c = col - this.colStart;
50
+ if (r < 0 || c < 0 || r >= this.rows || c >= this.cols)
51
+ return -1;
52
+ return r * this.cols + c;
53
+ }
54
+ /** What the cell at `(row, col)` holds. Cheaper than {@link cell}. */
55
+ kind(row, col) {
56
+ const i = this.#index(row, col);
57
+ return i < 0 ? 'empty' : (KINDS[this.#native.kinds[i] ?? 0] ?? 'empty');
58
+ }
59
+ /** The display text at `(row, col)` — all a plain grid needs. */
60
+ text(row, col) {
61
+ const i = this.#index(row, col);
62
+ if (i < 0)
63
+ return '';
64
+ const { offsets, text } = this.#native;
65
+ return text.slice(offsets[i], offsets[i + 1]);
66
+ }
67
+ /**
68
+ * The numeric value at `(row, col)`: a number, a bool as 0 or 1, a date's serial,
69
+ * a duration in days. NaN for anything else.
70
+ */
71
+ number(row, col) {
72
+ const i = this.#index(row, col);
73
+ return i < 0 ? Number.NaN : (this.#native.numbers[i] ?? Number.NaN);
74
+ }
75
+ /**
76
+ * The index of the cell's style in `Sheet.styles`. 0, the default, for a cell
77
+ * with none — and for every cell of a format that carries no styles.
78
+ */
79
+ style(row, col) {
80
+ const i = this.#index(row, col);
81
+ return i < 0 ? 0 : (this.#native.styles[i] ?? 0);
82
+ }
83
+ /**
84
+ * The colour the cell's number format chose, as `0xRRGGBB` — the `[Red]` in
85
+ * `#,##0;[Red](#,##0)`. It overrides the style's text colour, as in Excel.
86
+ */
87
+ color(row, col) {
88
+ const i = this.#index(row, col);
89
+ const c = i < 0 ? 0 : (this.#native.colors[i] ?? 0);
90
+ return c === 0 ? undefined : c & 0xffffff;
91
+ }
92
+ /** The cell at `(row, col)`, fully decoded. */
93
+ cell(row, col) {
94
+ const kind = this.kind(row, col);
95
+ const text = this.text(row, col);
96
+ const n = this.number(row, col);
97
+ switch (kind) {
98
+ case 'empty':
99
+ return { kind, text: '' };
100
+ case 'number':
101
+ return { kind, value: n, text };
102
+ case 'bool':
103
+ return n === 1
104
+ ? { kind, value: true, text: 'TRUE' }
105
+ : { kind, value: false, text: 'FALSE' };
106
+ case 'date':
107
+ return { kind, serial: n, text };
108
+ case 'duration':
109
+ return { kind, days: n, text };
110
+ case 'text':
111
+ case 'error':
112
+ return { kind, text };
113
+ }
114
+ }
115
+ }
116
+ /** Unpack the bindings' flat merge quads. @internal */
117
+ export function toMergedRanges(quads) {
118
+ const out = [];
119
+ for (let i = 0; i + 3 < quads.length; i += 4) {
120
+ out.push({
121
+ row: quads[i] ?? 0,
122
+ col: quads[i + 1] ?? 0,
123
+ lastRow: quads[i + 2] ?? 0,
124
+ lastCol: quads[i + 3] ?? 0,
125
+ });
126
+ }
127
+ return out;
128
+ }
129
+ /**
130
+ * The letters Excel heads a column with: 0 is `A`, 25 is `Z`, 26 is `AA`.
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * columnName(27); // 'AB'
135
+ * ```
136
+ */
137
+ export function columnName(index) {
138
+ let name = '';
139
+ for (let n = Math.floor(index) + 1; n > 0; n = Math.floor((n - 1) / 26)) {
140
+ name = String.fromCharCode(65 + ((n - 1) % 26)) + name;
141
+ }
142
+ return name;
143
+ }
144
+ //# sourceMappingURL=cells.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cells.js","sourceRoot":"","sources":["../src/cells.ts"],"names":[],"mappings":"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"}
package/dist/errors.d.ts CHANGED
@@ -36,6 +36,18 @@ export declare class IncorrectPasswordError extends PasswordError {
36
36
  readonly retry = true;
37
37
  constructor(message?: string);
38
38
  }
39
+ /**
40
+ * A spreadsheet that is password-protected.
41
+ *
42
+ * Deliberately not a {@link PasswordError}: Excel encrypts the whole package, and
43
+ * there is no decryption here to hand a password to, so a dialog asking for one
44
+ * would only fail again. Show that the file is protected, and stop.
45
+ */
46
+ export declare class EncryptedWorkbookError extends Error {
47
+ /** Always `'EncryptedWorkbookError'`. */
48
+ readonly name = "EncryptedWorkbookError";
49
+ constructor(message?: string);
50
+ }
39
51
  /**
40
52
  * Rethrow a load failure as itself, or as the typed error it was tagged as.
41
53
  *
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAeA;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAS;CACjC;AAED,mFAAmF;AACnF,qBAAa,qBAAsB,SAAQ,aAAa;IACtD,wCAAwC;IACxC,SAAkB,IAAI,2BAA2B;IACjD,SAAkB,KAAK,SAAS;IAChC,YAAY,OAAO,SAAmC,EAErD;CACF;AAED,gEAAgE;AAChE,qBAAa,sBAAuB,SAAQ,aAAa;IACvD,yCAAyC;IACzC,SAAkB,IAAI,4BAA4B;IAClD,SAAkB,KAAK,QAAQ;IAC/B,YAAY,OAAO,SAAuC,EAEzD;CACF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAQtD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAS;CACjC;AAED,mFAAmF;AACnF,qBAAa,qBAAsB,SAAQ,aAAa;IACtD,wCAAwC;IACxC,SAAkB,IAAI,2BAA2B;IACjD,SAAkB,KAAK,SAAS;IAChC,YAAY,OAAO,SAAmC,EAErD;CACF;AAED,gEAAgE;AAChE,qBAAa,sBAAuB,SAAQ,aAAa;IACvD,yCAAyC;IACzC,SAAkB,IAAI,4BAA4B;IAClD,SAAkB,KAAK,QAAQ;IAC/B,YAAY,OAAO,SAAuC,EAEzD;CACF;AAED;;;;;;GAMG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,yCAAyC;IACzC,SAAkB,IAAI,4BAA4B;IAClD,YAAY,OAAO,SAAwC,EAE1D;CACF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAQtD"}
package/dist/errors.js CHANGED
@@ -4,11 +4,13 @@
4
4
  * napi-rs gives every error it throws the same `code`, so the message is the only
5
5
  * channel a typed failure can travel through. These are stripped before the error
6
6
  * reaches a caller — keep them in step with `TAG_PASSWORD_REQUIRED` and
7
- * `TAG_INCORRECT_PASSWORD` in `packages/bindings/src/lib.rs`.
7
+ * `TAG_INCORRECT_PASSWORD` in `packages/bindings/src/lib.rs`, and `TAG_ENCRYPTED` in
8
+ * `packages/bindings/src/tables.rs`.
8
9
  */
9
10
  const TAGS = {
10
11
  'papyra/password-required': (message) => new PasswordRequiredError(message),
11
12
  'papyra/incorrect-password': (message) => new IncorrectPasswordError(message),
13
+ 'papyra/encrypted-workbook': (message) => new EncryptedWorkbookError(message),
12
14
  };
13
15
  /**
14
16
  * A document that could not be opened because of its password.
@@ -52,6 +54,20 @@ export class IncorrectPasswordError extends PasswordError {
52
54
  super(message);
53
55
  }
54
56
  }
57
+ /**
58
+ * A spreadsheet that is password-protected.
59
+ *
60
+ * Deliberately not a {@link PasswordError}: Excel encrypts the whole package, and
61
+ * there is no decryption here to hand a password to, so a dialog asking for one
62
+ * would only fail again. Show that the file is protected, and stop.
63
+ */
64
+ export class EncryptedWorkbookError extends Error {
65
+ /** Always `'EncryptedWorkbookError'`. */
66
+ name = 'EncryptedWorkbookError';
67
+ constructor(message = 'this workbook is password-protected') {
68
+ super(message);
69
+ }
70
+ }
55
71
  /**
56
72
  * Rethrow a load failure as itself, or as the typed error it was tagged as.
57
73
  *
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,IAAI,GAAG;IACX,0BAA0B,EAAE,CAAC,OAAe,EAAE,EAAE,CAC9C,IAAI,qBAAqB,CAAC,OAAO,CAAC;IACpC,2BAA2B,EAAE,CAAC,OAAe,EAAE,EAAE,CAC/C,IAAI,sBAAsB,CAAC,OAAO,CAAC;CAC7B,CAAC;AAEX;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC;;;;OAIG;IACM,KAAK,GAAY,KAAK,CAAC;CACjC;AAED,mFAAmF;AACnF,MAAM,OAAO,qBAAsB,SAAQ,aAAa;IACtD,wCAAwC;IACtB,IAAI,GAAG,uBAAuB,CAAC;IAC/B,KAAK,GAAG,KAAK,CAAC;IAChC,YAAY,OAAO,GAAG,gCAAgC;QACpD,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED,gEAAgE;AAChE,MAAM,OAAO,sBAAuB,SAAQ,aAAa;IACvD,yCAAyC;IACvB,IAAI,GAAG,wBAAwB,CAAC;IAChC,KAAK,GAAG,IAAI,CAAC;IAC/B,YAAY,OAAO,GAAG,oCAAoC;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,MAAM,KAAK,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,IAAI,GAAG;IACX,0BAA0B,EAAE,CAAC,OAAe,EAAE,EAAE,CAC9C,IAAI,qBAAqB,CAAC,OAAO,CAAC;IACpC,2BAA2B,EAAE,CAAC,OAAe,EAAE,EAAE,CAC/C,IAAI,sBAAsB,CAAC,OAAO,CAAC;IACrC,2BAA2B,EAAE,CAAC,OAAe,EAAE,EAAE,CAC/C,IAAI,sBAAsB,CAAC,OAAO,CAAC;CAC7B,CAAC;AAEX;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC;;;;OAIG;IACM,KAAK,GAAY,KAAK,CAAC;CACjC;AAED,mFAAmF;AACnF,MAAM,OAAO,qBAAsB,SAAQ,aAAa;IACtD,wCAAwC;IACtB,IAAI,GAAG,uBAAuB,CAAC;IAC/B,KAAK,GAAG,KAAK,CAAC;IAChC,YAAY,OAAO,GAAG,gCAAgC;QACpD,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED,gEAAgE;AAChE,MAAM,OAAO,sBAAuB,SAAQ,aAAa;IACvD,yCAAyC;IACvB,IAAI,GAAG,wBAAwB,CAAC;IAChC,KAAK,GAAG,IAAI,CAAC;IAC/B,YAAY,OAAO,GAAG,oCAAoC;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C,yCAAyC;IACvB,IAAI,GAAG,wBAAwB,CAAC;IAClD,YAAY,OAAO,GAAG,qCAAqC;QACzD,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,MAAM,KAAK,CAAC;AACd,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
- * papyra — fast PDF rendering for Node and the browser.
2
+ * papyra — fast PDF rendering for Node and the browser, and spreadsheets and TIFF
3
+ * scans beside it.
3
4
  *
4
5
  * ```ts
5
6
  * import { open, paintToCanvas } from '@build-qube/papyra';
@@ -18,11 +19,13 @@ export { attachmentMediaType, isInvoiceAttachment, } from './attachments.js';
18
19
  export type { CacheStats } from './cache.js';
19
20
  export type { PaintOptions } from './canvas.js';
20
21
  export { paintToCanvas, toImageData } from './canvas.js';
22
+ export type { BoolCell, Cell, CellKind, DateCell, DurationCell, EmptyCell, ErrorCell, MergedRange, NumberCell, TextCell, } from './cells.js';
23
+ export { CellWindow, columnName } from './cells.js';
21
24
  export type { ImageHandle, RenderHandle, SvgHandle } from './document.js';
22
25
  export { Document, open } from './document.js';
23
26
  export type { EncodedFormat, EncodedImage, EncodeOptions, RasterFormat, SvgPage, } from './encode.js';
24
27
  export { encode, encodedImage, mimeType, PageImage, svgPage, } from './encode.js';
25
- export { IncorrectPasswordError, PasswordError, PasswordRequiredError, } from './errors.js';
28
+ export { EncryptedWorkbookError, IncorrectPasswordError, PasswordError, PasswordRequiredError, } from './errors.js';
26
29
  export type { LinkTarget, PageLink } from './links.js';
27
30
  export type { DestinationKind, OutlineDestination, OutlineNode, } from './outline.js';
28
31
  export { buildOutlineTree, walkOutline } from './outline.js';
@@ -34,9 +37,15 @@ export type { MatchOptions, SearchMatch } from './search.js';
34
37
  export { findRanges, searchPageText } from './search.js';
35
38
  export type { MarkedContent, OrderedLine, StructNode, } from './structure.js';
36
39
  export { buildStructTree, readingOrder, structuredPageString, walkStructTree, } from './structure.js';
40
+ export type { BorderEdge, BorderStyle, CellStyle, ColumnSpan, HorizontalAlign, RowSize, SheetLayout, VerticalAlign, } from './styles.js';
41
+ export { cssColor } from './styles.js';
37
42
  export type { PageText, Quad, Rect, TextLine } from './text.js';
38
43
  export { lineQuad, pageString, quadBounds, scaleQuad, scaleRect, } from './text.js';
44
+ export type { TiffCompression, TiffPage, TiffRenderOptions, } from './tiff.js';
45
+ export { openTiff, TIFF_MAX_PIXELS, TiffImage } from './tiff.js';
39
46
  export type { DocumentMetadata, OpenOptions, PageSize, PdfSource, RenderedPage, RenderOptions, SearchOptions, StreamedPage, StreamOptions, SvgOptions, } from './types.js';
40
47
  export type { Rotation, Viewport, ViewportOptions } from './viewport.js';
41
48
  export { rotatePage, rotateSize, viewport, viewportQuad, viewportRect, } from './viewport.js';
49
+ export type { SheetInfo, SheetKind, SheetVisibility, WindowRange, WorkbookFormat, WorkbookOptions, } from './workbook.js';
50
+ export { openWorkbook, Sheet, Workbook } from './workbook.js';
42
51
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EACL,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EACV,aAAa,EACb,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,OAAO,GACR,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,OAAO,GACR,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACvD,YAAY,EACV,eAAe,EACf,kBAAkB,EAClB,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EACL,OAAO,EACP,cAAc,EACd,mBAAmB,EACnB,IAAI,GACL,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC9D,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EACV,aAAa,EACb,WAAW,EACX,UAAU,GACX,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EACL,QAAQ,EACR,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,GACV,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EACL,UAAU,EACV,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,YAAY,GACb,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
- * papyra — fast PDF rendering for Node and the browser.
2
+ * papyra — fast PDF rendering for Node and the browser, and spreadsheets and TIFF
3
+ * scans beside it.
3
4
  *
4
5
  * ```ts
5
6
  * import { open, paintToCanvas } from '@build-qube/papyra';
@@ -15,14 +16,18 @@
15
16
  */
16
17
  export { attachmentMediaType, isInvoiceAttachment, } from './attachments.js';
17
18
  export { paintToCanvas, toImageData } from './canvas.js';
19
+ export { CellWindow, columnName } from './cells.js';
18
20
  export { Document, open } from './document.js';
19
21
  export { encode, encodedImage, mimeType, PageImage, svgPage, } from './encode.js';
20
- export { IncorrectPasswordError, PasswordError, PasswordRequiredError, } from './errors.js';
22
+ export { EncryptedWorkbookError, IncorrectPasswordError, PasswordError, PasswordRequiredError, } from './errors.js';
21
23
  export { buildOutlineTree, walkOutline } from './outline.js';
22
24
  export { backend, currentRuntime, hardwareConcurrency, init, } from './runtime.js';
23
25
  export { AbortError, DEFAULT_PRIORITY } from './scheduler.js';
24
26
  export { findRanges, searchPageText } from './search.js';
25
27
  export { buildStructTree, readingOrder, structuredPageString, walkStructTree, } from './structure.js';
28
+ export { cssColor } from './styles.js';
26
29
  export { lineQuad, pageString, quadBounds, scaleQuad, scaleRect, } from './text.js';
30
+ export { openTiff, TIFF_MAX_PIXELS, TiffImage } from './tiff.js';
27
31
  export { rotatePage, rotateSize, viewport, viewportQuad, viewportRect, } from './viewport.js';
32
+ export { openWorkbook, Sheet, Workbook } from './workbook.js';
28
33
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EACL,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAQ/C,OAAO,EACL,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,OAAO,GACR,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAOrB,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE7D,OAAO,EACL,OAAO,EACP,cAAc,EACd,mBAAmB,EACnB,IAAI,GACL,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAMzD,OAAO,EACL,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,cAAc,GACf,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,QAAQ,EACR,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,GACV,MAAM,WAAW,CAAC;AAcnB,OAAO,EACL,UAAU,EACV,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,YAAY,GACb,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EACL,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAazD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAQ/C,OAAO,EACL,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,OAAO,GACR,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,aAAa,EACb,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAOrB,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE7D,OAAO,EACL,OAAO,EACP,cAAc,EACd,mBAAmB,EACnB,IAAI,GACL,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAMzD,OAAO,EACL,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,cAAc,GACf,MAAM,gBAAgB,CAAC;AAWxB,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EACL,QAAQ,EACR,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,GACV,MAAM,WAAW,CAAC;AAMnB,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAcjE,OAAO,EACL,UAAU,EACV,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,YAAY,GACb,MAAM,eAAe,CAAC;AASvB,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,96 @@
1
+ import type { CellStyle as NativeCellStyle, SheetLayout as NativeSheetLayout } from '@build-qube/papyra-native';
2
+ /** How one edge of a border is drawn. Dash-dot variants arrive as `'dashed'`. */
3
+ export type BorderStyle = 'thin' | 'medium' | 'thick' | 'dashed' | 'dotted' | 'double' | 'hair';
4
+ /** One edge of a cell's border. */
5
+ export interface BorderEdge {
6
+ /** The line. */
7
+ style: BorderStyle;
8
+ /** `0xRRGGBB`. Absent means automatic, which Excel draws black. */
9
+ color?: number;
10
+ }
11
+ /** Horizontal alignment. Absent means Excel's default: text left, numbers right. */
12
+ export type HorizontalAlign = 'left' | 'center' | 'right' | 'justify' | 'centerContinuous' | 'fill' | 'distributed';
13
+ /** Vertical alignment. Absent means bottom. */
14
+ export type VerticalAlign = 'top' | 'center' | 'bottom' | 'justify' | 'distributed';
15
+ /**
16
+ * How a cell looks, apart from its number format — which is already applied to the
17
+ * text. Sheets share styles by index: see {@link CellWindow.style}.
18
+ *
19
+ * Colours are `0xRRGGBB` numbers; {@link cssColor} turns one into CSS. An absent
20
+ * colour means "automatic", which is the reader's to choose — black on white in
21
+ * Excel, but whatever the page's own text colour is in a dark theme.
22
+ */
23
+ export interface CellStyle {
24
+ /** Bold text. */
25
+ bold: boolean;
26
+ /** Italic text. */
27
+ italic: boolean;
28
+ /** Underlined text. */
29
+ underline: boolean;
30
+ /** Struck-through text. */
31
+ strike: boolean;
32
+ /** Font size relative to the workbook's default font: 2 is twice the size. */
33
+ fontScale: number;
34
+ /** Text colour. Absent means automatic. */
35
+ color?: number;
36
+ /** Background. Absent means none. */
37
+ fill?: number;
38
+ /** Top border. */
39
+ borderTop?: BorderEdge;
40
+ /** Right border. */
41
+ borderRight?: BorderEdge;
42
+ /** Bottom border. */
43
+ borderBottom?: BorderEdge;
44
+ /** Left border. */
45
+ borderLeft?: BorderEdge;
46
+ /** Horizontal alignment. */
47
+ horizontal?: HorizontalAlign;
48
+ /** Vertical alignment. */
49
+ vertical?: VerticalAlign;
50
+ /** Wrap text onto further lines within the row's height. */
51
+ wrap: boolean;
52
+ /** Indent level. Excel draws each as roughly three characters. */
53
+ indent: number;
54
+ }
55
+ /** Columns sharing a width, inclusive at both ends. */
56
+ export interface ColumnSpan {
57
+ /** First column, 0-based. */
58
+ first: number;
59
+ /** Last column, inclusive. Often 16383 — "to the end of the sheet". */
60
+ last: number;
61
+ /** Pixels at 96 DPI. 0 means hidden. */
62
+ width: number;
63
+ }
64
+ /** A row with a height of its own. */
65
+ export interface RowSize {
66
+ /** The row, 0-based. */
67
+ row: number;
68
+ /** Pixels at 96 DPI. 0 means hidden. */
69
+ height: number;
70
+ }
71
+ /**
72
+ * Column widths and row heights as the author left them, in pixels at 96 DPI —
73
+ * Excel's own geometry, so a 64px default column is 64px here.
74
+ */
75
+ export interface SheetLayout {
76
+ /** Width of a column with no span of its own. */
77
+ defaultColWidth: number;
78
+ /** Height of a row with no size of its own. */
79
+ defaultRowHeight: number;
80
+ /** Columns with their own width, in the file's order. */
81
+ columns: readonly ColumnSpan[];
82
+ /** Rows with their own height, in row order. */
83
+ rows: readonly RowSize[];
84
+ /**
85
+ * `false` when the author turned gridlines off — usually a report or a
86
+ * dashboard, drawn with borders where lines are meant to be.
87
+ */
88
+ showGridLines: boolean;
89
+ }
90
+ /** `0x1F4E79` → `'#1f4e79'`. */
91
+ export declare function cssColor(rgb: number): string;
92
+ /** @internal */
93
+ export declare function toCellStyle(s: NativeCellStyle): CellStyle;
94
+ /** @internal */
95
+ export declare function toSheetLayout(l: NativeSheetLayout): SheetLayout;
96
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,IAAI,eAAe,EAC5B,WAAW,IAAI,iBAAiB,EACjC,MAAM,2BAA2B,CAAC;AAEnC,iFAAiF;AACjF,MAAM,MAAM,WAAW,GACnB,MAAM,GACN,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,MAAM,CAAC;AAEX,mCAAmC;AACnC,MAAM,WAAW,UAAU;IACzB,gBAAgB;IAChB,KAAK,EAAE,WAAW,CAAC;IACnB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,oFAAoF;AACpF,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,QAAQ,GACR,OAAO,GACP,SAAS,GACT,kBAAkB,GAClB,MAAM,GACN,aAAa,CAAC;AAElB,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GACrB,KAAK,GACL,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,aAAa,CAAC;AAElB;;;;;;;GAOG;AACH,MAAM,WAAW,SAAS;IACxB,iBAAiB;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,mBAAmB;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,uBAAuB;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,2BAA2B;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,oBAAoB;IACpB,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,qBAAqB;IACrB,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,mBAAmB;IACnB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,4DAA4D;IAC5D,IAAI,EAAE,OAAO,CAAC;IACd,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,uDAAuD;AACvD,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,sCAAsC;AACtC,MAAM,WAAW,OAAO;IACtB,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,iDAAiD;IACjD,eAAe,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,gBAAgB,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,OAAO,EAAE,SAAS,UAAU,EAAE,CAAC;IAC/B,gDAAgD;IAChD,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;IACzB;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,gCAAgC;AAChC,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5C;AASD,gBAAgB;AAChB,wBAAgB,WAAW,CAAC,CAAC,EAAE,eAAe,GAAG,SAAS,CAyBzD;AAED,gBAAgB;AAChB,wBAAgB,aAAa,CAAC,CAAC,EAAE,iBAAiB,GAAG,WAAW,CAoB/D"}
package/dist/styles.js ADDED
@@ -0,0 +1,69 @@
1
+ /** `0x1F4E79` → `'#1f4e79'`. */
2
+ export function cssColor(rgb) {
3
+ return `#${(rgb & 0xffffff).toString(16).padStart(6, '0')}`;
4
+ }
5
+ function edge(e) {
6
+ if (!e)
7
+ return undefined;
8
+ return e.color === undefined || e.color === null
9
+ ? { style: e.style }
10
+ : { style: e.style, color: e.color };
11
+ }
12
+ /** @internal */
13
+ export function toCellStyle(s) {
14
+ const out = {
15
+ bold: s.bold,
16
+ italic: s.italic,
17
+ underline: s.underline,
18
+ strike: s.strike,
19
+ fontScale: s.fontScale,
20
+ wrap: s.wrap,
21
+ indent: s.indent,
22
+ };
23
+ // Assigned only when present, so a style compares and spreads as the file meant
24
+ // it — `{ color: undefined }` and `{}` are different objects to a test.
25
+ if (s.color != null)
26
+ out.color = s.color;
27
+ if (s.fill != null)
28
+ out.fill = s.fill;
29
+ const top = edge(s.borderTop);
30
+ const right = edge(s.borderRight);
31
+ const bottom = edge(s.borderBottom);
32
+ const left = edge(s.borderLeft);
33
+ if (top)
34
+ out.borderTop = top;
35
+ if (right)
36
+ out.borderRight = right;
37
+ if (bottom)
38
+ out.borderBottom = bottom;
39
+ if (left)
40
+ out.borderLeft = left;
41
+ if (s.horizontal)
42
+ out.horizontal = s.horizontal;
43
+ if (s.vertical)
44
+ out.vertical = s.vertical;
45
+ return out;
46
+ }
47
+ /** @internal */
48
+ export function toSheetLayout(l) {
49
+ const columns = [];
50
+ for (let i = 0; i + 2 < l.cols.length; i += 3) {
51
+ columns.push({
52
+ first: l.cols[i] ?? 0,
53
+ last: l.cols[i + 1] ?? 0,
54
+ width: l.cols[i + 2] ?? 0,
55
+ });
56
+ }
57
+ const rows = [];
58
+ for (let i = 0; i + 1 < l.rows.length; i += 2) {
59
+ rows.push({ row: l.rows[i] ?? 0, height: l.rows[i + 1] ?? 0 });
60
+ }
61
+ return {
62
+ defaultColWidth: l.defaultColWidth,
63
+ defaultRowHeight: l.defaultRowHeight,
64
+ columns,
65
+ rows,
66
+ showGridLines: l.showGridLines,
67
+ };
68
+ }
69
+ //# sourceMappingURL=styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"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"}
package/dist/tiff.d.ts ADDED
@@ -0,0 +1,95 @@
1
+ import { type TiffImage as NativeTiffImage } from '@build-qube/papyra-native';
2
+ import type { PdfSource, RenderedPage } from './types.js';
3
+ /**
4
+ * How a TIFF page's pixels are stored.
5
+ *
6
+ * The three `ccitt-*` values are fax coding — `ccitt-g4` is what nearly every scanned
7
+ * drawing uses. `old-jpeg` is listed so a page can say what it is, but cannot be
8
+ * rendered.
9
+ */
10
+ export type TiffCompression = 'none' | 'ccitt-rle' | 'ccitt-g3' | 'ccitt-g4' | 'lzw' | 'old-jpeg' | 'jpeg' | 'deflate' | 'packbits' | 'other';
11
+ /** One page of a TIFF, as it is shown: the file's `Orientation` is already applied. */
12
+ export interface TiffPage {
13
+ /** Width in pixels, at full resolution. */
14
+ readonly width: number;
15
+ /** Height in pixels, at full resolution. */
16
+ readonly height: number;
17
+ /**
18
+ * Resolution in dots per inch, when the file states one. Fax pages are typically
19
+ * 204 by 196, so the two can differ.
20
+ */
21
+ readonly dpi: {
22
+ /** Horizontal dots per inch. */
23
+ readonly x: number;
24
+ /** Vertical dots per inch. */
25
+ readonly y: number;
26
+ } | undefined;
27
+ /** How the pixels are stored. */
28
+ readonly compression: TiffCompression;
29
+ /** Bits per sample: 1 for a bilevel scan, 8 for most others. */
30
+ readonly bitsPerSample: number;
31
+ /** Samples per pixel: 1 for grey, 3 for RGB, 4 with alpha or for CMYK. */
32
+ readonly samplesPerPixel: number;
33
+ /** TIFF `Orientation`, 1–8. 1 is upright; 6 and 8 are a quarter turn. */
34
+ readonly orientation: number;
35
+ }
36
+ /**
37
+ * Size limits for {@link TiffImage.renderPage}. The page keeps its aspect ratio and
38
+ * is never enlarged.
39
+ */
40
+ export interface TiffRenderOptions {
41
+ /** The most pixels the result may have. Defaults to {@link TIFF_MAX_PIXELS}. */
42
+ maxPixels?: number;
43
+ /** The widest the result may be, in pixels. */
44
+ maxWidth?: number;
45
+ }
46
+ /**
47
+ * The default {@link TiffRenderOptions.maxPixels}: 4096 × 4096.
48
+ *
49
+ * It is iOS Safari's canvas limit, and 64 MB of RGBA. A 300-dpi E-size sheet comes out
50
+ * at about 100 dpi under it — readable, with hairlines in grey.
51
+ */
52
+ export declare const TIFF_MAX_PIXELS: number;
53
+ /**
54
+ * Open a TIFF: single or multi-page, classic or BigTIFF.
55
+ *
56
+ * Reads fax-coded pages (CCITT Group 3 and Group 4, the usual case for a scanned
57
+ * drawing), and uncompressed, LZW, Deflate, PackBits and JPEG pages in grey, RGB or
58
+ * CMYK at 1 to 16 bits, in strips or tiles. Palette-colour and old-style JPEG pages
59
+ * are listed but fail to render.
60
+ *
61
+ * Only the directory is read here. Each page is decoded by
62
+ * {@link TiffImage.renderPage}, in Rust and off the JS thread, and straight to a
63
+ * reduced size — a page is never held at full resolution, so a 600-dpi colour scan of
64
+ * a sheet larger than the tab could allocate still opens.
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * const tiff = await openTiff(file);
69
+ * const page = await tiff.renderPage(0, { maxWidth: 1600 });
70
+ * paintToCanvas(page, canvas);
71
+ * ```
72
+ */
73
+ export declare function openTiff(source: PdfSource): Promise<TiffImage>;
74
+ /** An opened TIFF. Get one from {@link openTiff}. */
75
+ export declare class TiffImage {
76
+ #private;
77
+ /**
78
+ * Every page, in file order. A reduced-resolution copy of a page — a thumbnail, a
79
+ * pyramid level — is not a page and is left out.
80
+ */
81
+ readonly pages: readonly TiffPage[];
82
+ /** @internal — construct via {@link openTiff}. */
83
+ constructor(native: NativeTiffImage);
84
+ /** How many pages there are. */
85
+ get pageCount(): number;
86
+ /**
87
+ * Decode one page to RGBA, upright, at no more than `options` allows.
88
+ *
89
+ * Paint the result with `paintToCanvas`, or encode it with `encode`, exactly as a
90
+ * rendered PDF page. Each call decodes the page again; keep the result if it will
91
+ * be shown again.
92
+ */
93
+ renderPage(index: number, options?: TiffRenderOptions): Promise<RenderedPage>;
94
+ }
95
+ //# sourceMappingURL=tiff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tiff.d.ts","sourceRoot":"","sources":["../src/tiff.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,IAAI,eAAe,EAClC,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1D;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,WAAW,GACX,UAAU,GACV,UAAU,GACV,KAAK,GACL,UAAU,GACV,MAAM,GACN,SAAS,GACT,UAAU,GACV,OAAO,CAAC;AAEZ,uFAAuF;AACvF,MAAM,WAAW,QAAQ;IACvB,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,GAAG,EACR;QACE,gCAAgC;QAChC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QACnB,8BAA8B;QAC9B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;KACpB,GACD,SAAS,CAAC;IACd,iCAAiC;IACjC,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;IACtC,gEAAgE;IAChE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,0EAA0E;IAC1E,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,yEAAyE;IACzE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,QAAc,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAGpE;AAED,qDAAqD;AACrD,qBAAa,SAAS;;IACpB;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IAGpC,kDAAkD;IAClD,YAAY,MAAM,EAAE,eAAe,EAWlC;IAED,gCAAgC;IAChC,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;;;;;OAMG;IACH,UAAU,CACR,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,YAAY,CAAC,CAavB;CACF"}
package/dist/tiff.js ADDED
@@ -0,0 +1,78 @@
1
+ import { loadTiff, } from '@build-qube/papyra-native';
2
+ import { toBytes } from './source.js';
3
+ /**
4
+ * The default {@link TiffRenderOptions.maxPixels}: 4096 × 4096.
5
+ *
6
+ * It is iOS Safari's canvas limit, and 64 MB of RGBA. A 300-dpi E-size sheet comes out
7
+ * at about 100 dpi under it — readable, with hairlines in grey.
8
+ */
9
+ export const TIFF_MAX_PIXELS = 4096 * 4096;
10
+ /**
11
+ * Open a TIFF: single or multi-page, classic or BigTIFF.
12
+ *
13
+ * Reads fax-coded pages (CCITT Group 3 and Group 4, the usual case for a scanned
14
+ * drawing), and uncompressed, LZW, Deflate, PackBits and JPEG pages in grey, RGB or
15
+ * CMYK at 1 to 16 bits, in strips or tiles. Palette-colour and old-style JPEG pages
16
+ * are listed but fail to render.
17
+ *
18
+ * Only the directory is read here. Each page is decoded by
19
+ * {@link TiffImage.renderPage}, in Rust and off the JS thread, and straight to a
20
+ * reduced size — a page is never held at full resolution, so a 600-dpi colour scan of
21
+ * a sheet larger than the tab could allocate still opens.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * const tiff = await openTiff(file);
26
+ * const page = await tiff.renderPage(0, { maxWidth: 1600 });
27
+ * paintToCanvas(page, canvas);
28
+ * ```
29
+ */
30
+ export async function openTiff(source) {
31
+ const bytes = await toBytes(source);
32
+ return new TiffImage(await loadTiff(bytes));
33
+ }
34
+ /** An opened TIFF. Get one from {@link openTiff}. */
35
+ export class TiffImage {
36
+ /**
37
+ * Every page, in file order. A reduced-resolution copy of a page — a thumbnail, a
38
+ * pyramid level — is not a page and is left out.
39
+ */
40
+ pages;
41
+ #native;
42
+ /** @internal — construct via {@link openTiff}. */
43
+ constructor(native) {
44
+ this.#native = native;
45
+ this.pages = native.pages.map((p) => ({
46
+ width: p.width,
47
+ height: p.height,
48
+ dpi: p.xDpi != null ? { x: p.xDpi, y: p.yDpi ?? p.xDpi } : undefined,
49
+ compression: p.compression,
50
+ bitsPerSample: p.bitsPerSample,
51
+ samplesPerPixel: p.samplesPerPixel,
52
+ orientation: p.orientation,
53
+ }));
54
+ }
55
+ /** How many pages there are. */
56
+ get pageCount() {
57
+ return this.pages.length;
58
+ }
59
+ /**
60
+ * Decode one page to RGBA, upright, at no more than `options` allows.
61
+ *
62
+ * Paint the result with `paintToCanvas`, or encode it with `encode`, exactly as a
63
+ * rendered PDF page. Each call decodes the page again; keep the result if it will
64
+ * be shown again.
65
+ */
66
+ renderPage(index, options = {}) {
67
+ if (!Number.isInteger(index) || index < 0 || index >= this.pages.length) {
68
+ return Promise.reject(new RangeError(`papyra: no TIFF page ${JSON.stringify(index)}`));
69
+ }
70
+ return this.#native.renderPage(index, {
71
+ maxPixels: options.maxPixels,
72
+ maxWidth: options.maxWidth === undefined
73
+ ? undefined
74
+ : Math.max(1, Math.floor(options.maxWidth)),
75
+ });
76
+ }
77
+ }
78
+ //# sourceMappingURL=tiff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tiff.js","sourceRoot":"","sources":["../src/tiff.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,GAET,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AA6DtC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAiB;IAC9C,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,IAAI,SAAS,CAAC,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,qDAAqD;AACrD,MAAM,OAAO,SAAS;IACpB;;;OAGG;IACM,KAAK,CAAsB;IAC3B,OAAO,CAAkB;IAElC,kDAAkD;IAClD,YAAY,MAAuB;QACjC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACpC,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,GAAG,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;YACpE,WAAW,EAAE,CAAC,CAAC,WAA8B;YAC7C,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,eAAe,EAAE,CAAC,CAAC,eAAe;YAClC,WAAW,EAAE,CAAC,CAAC,WAAW;SAC3B,CAAC,CAAC,CAAC;IACN,CAAC;IAED,gCAAgC;IAChC,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED;;;;;;OAMG;IACH,UAAU,CACR,KAAa,EACb,OAAO,GAAsB,EAAE;QAE/B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACxE,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,UAAU,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAChE,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,EAAE;YACpC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,QAAQ,EACN,OAAO,CAAC,QAAQ,KAAK,SAAS;gBAC5B,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;SAChD,CAA0B,CAAC;IAC9B,CAAC;CACF"}
@@ -0,0 +1,152 @@
1
+ import { type Sheet as NativeSheet, type Workbook as NativeWorkbook } from '@build-qube/papyra-native';
2
+ import { CellWindow, type MergedRange } from './cells.js';
3
+ import { type CellStyle, type SheetLayout } from './styles.js';
4
+ import type { PdfSource } from './types.js';
5
+ /**
6
+ * The container a workbook was read from.
7
+ *
8
+ * Macro-enabled and template variants read as their base format: an `.xlsm` is
9
+ * `'xlsx'` here, because to a reader that is what it is.
10
+ */
11
+ export type WorkbookFormat = 'xlsx' | 'xlsb' | 'xls' | 'ods' | 'csv' | 'tsv';
12
+ /** How to read a workbook. Everything is sniffed when left out. */
13
+ export interface WorkbookOptions {
14
+ /**
15
+ * Skip sniffing. Only needed to read a file as TSV that was not named `.tsv` —
16
+ * the binary formats identify themselves, and text is sniffed for its delimiter.
17
+ * `'xlsm'` is accepted and reads as `'xlsx'`.
18
+ */
19
+ format?: WorkbookFormat | 'xlsm';
20
+ /** CSV and TSV only: the delimiter, a single ASCII character such as `';'`. */
21
+ delimiter?: string;
22
+ /**
23
+ * CSV and TSV only: a WHATWG encoding label, e.g. `'windows-1252'` or
24
+ * `'shift_jis'`. Without one, a byte-order mark decides, then valid UTF-8, then a
25
+ * statistical guess.
26
+ */
27
+ encoding?: string;
28
+ /**
29
+ * Cells to hold per sheet before truncating it to its first whole rows. Defaults
30
+ * to 8 million — about 400 MB, which a browser tab survives. A sheet that hits it
31
+ * reports {@link Sheet.truncated}.
32
+ */
33
+ maxCells?: number;
34
+ }
35
+ /** Whether a sheet shows in the application's tab bar. */
36
+ export type SheetVisibility = 'visible' | 'hidden' | 'veryHidden';
37
+ /** What a sheet holds. Only worksheets have cells worth showing. */
38
+ export type SheetKind = 'worksheet' | 'chartsheet' | 'dialog' | 'macro' | 'vba';
39
+ /** A sheet's entry in the workbook, known without reading its cells. */
40
+ export interface SheetInfo {
41
+ /** The name on the sheet's tab. CSV and TSV have one sheet, named `Sheet1`. */
42
+ name: string;
43
+ /** What the sheet holds. */
44
+ kind: SheetKind;
45
+ /**
46
+ * `'hidden'` sheets can be unhidden by the user; `'veryHidden'` ones only by a
47
+ * macro. A viewer usually lists the first and omits the second.
48
+ */
49
+ visibility: SheetVisibility;
50
+ }
51
+ /** Rows and columns to read, half-open like `Array.prototype.slice`. */
52
+ export interface WindowRange {
53
+ /** First row, 0-based. */
54
+ rowStart: number;
55
+ /** One past the last row. Clamped to the sheet. */
56
+ rowEnd: number;
57
+ /** First column. Defaults to 0. */
58
+ colStart?: number;
59
+ /** One past the last column. Defaults to every column. */
60
+ colEnd?: number;
61
+ }
62
+ /**
63
+ * Open a spreadsheet: Excel (`.xlsx`, `.xlsm`, `.xlsb`, `.xls`), OpenDocument
64
+ * (`.ods`), or delimited text (`.csv`, `.tsv`).
65
+ *
66
+ * Parsing happens in Rust and off the JS thread, and only sheet names are read up
67
+ * front: a sheet's cells are read the first time {@link Workbook.sheet} asks for it.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * const book = await openWorkbook(file);
72
+ * const sheet = await book.sheet(0);
73
+ * const cells = sheet.window({ rowStart: 0, rowEnd: 50 });
74
+ * cells.text(0, 0); // 'Item'
75
+ * ```
76
+ *
77
+ * @throws {@link EncryptedWorkbookError} when the workbook is password-protected.
78
+ */
79
+ export declare function openWorkbook(source: PdfSource, options?: WorkbookOptions): Promise<Workbook>;
80
+ /** An opened spreadsheet. Get one from {@link openWorkbook}. */
81
+ export declare class Workbook {
82
+ #private;
83
+ /** The container actually read. */
84
+ readonly format: WorkbookFormat;
85
+ /** Every sheet in tab order, hidden ones included. */
86
+ readonly sheets: readonly SheetInfo[];
87
+ /**
88
+ * CSV and TSV only: the encoding the text was decoded from, e.g.
89
+ * `'windows-1252'`. Worth showing when it was guessed — a wrong guess reads as
90
+ * mojibake, and {@link WorkbookOptions.encoding} is the fix.
91
+ */
92
+ readonly encoding: string | undefined;
93
+ /** CSV and TSV only: the delimiter, given or sniffed. */
94
+ readonly delimiter: string | undefined;
95
+ /** @internal — construct via {@link openWorkbook}. */
96
+ constructor(native: NativeWorkbook);
97
+ /**
98
+ * Read one sheet, by index or by name.
99
+ *
100
+ * The first call parses the sheet, off the JS thread; later calls for the same
101
+ * sheet share that result.
102
+ */
103
+ sheet(which: number | string): Promise<Sheet>;
104
+ }
105
+ /**
106
+ * One sheet, parsed and held in Rust. Read it a window at a time.
107
+ *
108
+ * Coordinates are the sheet's own and 0-based: row 0 is the row Excel labels 1, and
109
+ * a sheet whose data starts at F10 still reports ten rows and six columns, so a grid
110
+ * draws the data where its author put it.
111
+ */
112
+ export declare class Sheet {
113
+ #private;
114
+ /** The name on the sheet's tab. */
115
+ readonly name: string;
116
+ /** One past the last row holding a value or covered by a merge. */
117
+ readonly rows: number;
118
+ /**
119
+ * The sheet held more cells than {@link WorkbookOptions.maxCells}, and this is
120
+ * its first whole rows. Worth saying on screen: the rest of the file is not here.
121
+ */
122
+ readonly truncated: boolean;
123
+ /** One past the last column holding a value or covered by a merge. */
124
+ readonly cols: number;
125
+ /**
126
+ * Merged regions. The value lives in each one's top-left cell; the others are
127
+ * empty. Always empty for `.xlsb` and `.ods`, which calamine does not read
128
+ * merges from.
129
+ */
130
+ readonly merges: readonly MergedRange[];
131
+ /**
132
+ * The styles {@link CellWindow.style} indexes into, with the default at 0.
133
+ * xlsx only: empty for every other format, whose cells all read as style 0.
134
+ */
135
+ readonly styles: readonly CellStyle[];
136
+ /**
137
+ * Column widths and row heights as the author set them. xlsx only; for anything
138
+ * else a grid sizes columns itself.
139
+ */
140
+ readonly layout: SheetLayout | undefined;
141
+ /** @internal — construct via {@link Workbook.sheet}. */
142
+ constructor(native: NativeSheet);
143
+ /**
144
+ * Read a rectangle of cells, clamped to the sheet.
145
+ *
146
+ * Synchronous, because the sheet is already parsed and the cost is the size of
147
+ * the window. Ask for what is on screen plus some overscan, not the whole sheet:
148
+ * a screenful is a few thousand cells and well under a millisecond.
149
+ */
150
+ window(range: WindowRange): CellWindow;
151
+ }
152
+ //# sourceMappingURL=workbook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workbook.d.ts","sourceRoot":"","sources":["../src/workbook.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,KAAK,IAAI,WAAW,EACzB,KAAK,QAAQ,IAAI,cAAc,EAChC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAkB,MAAM,YAAY,CAAC;AAG1E,OAAO,EACL,KAAK,SAAS,EACd,KAAK,WAAW,EAGjB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAE7E,mEAAmE;AACnE,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC;IACjC,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,0DAA0D;AAC1D,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAC;AAElE,oEAAoE;AACpE,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAC;AAEhF,wEAAwE;AACxE,MAAM,WAAW,SAAS;IACxB,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB;;;OAGG;IACH,UAAU,EAAE,eAAe,CAAC;CAC7B;AAED,wEAAwE;AACxE,MAAM,WAAW,WAAW;IAC1B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,QAAQ,CAAC,CASnB;AAgBD,gEAAgE;AAChE,qBAAa,QAAQ;;IACnB,mCAAmC;IACnC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAIvC,sDAAsD;IACtD,YAAY,MAAM,EAAE,cAAc,EAUjC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAkB5C;CACF;AAED;;;;;;GAMG;AACH,qBAAa,KAAK;;IAChB,mCAAmC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;IAGzC,wDAAwD;IACxD,YAAY,MAAM,EAAE,WAAW,EAS9B;IAED;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,CAWrC;CACF"}
@@ -0,0 +1,158 @@
1
+ import { loadWorkbook, } from '@build-qube/papyra-native';
2
+ import { CellWindow, toMergedRanges } from './cells.js';
3
+ import { rethrowLoadError } from './errors.js';
4
+ import { toBytes } from './source.js';
5
+ import { toCellStyle, toSheetLayout, } from './styles.js';
6
+ /**
7
+ * Open a spreadsheet: Excel (`.xlsx`, `.xlsm`, `.xlsb`, `.xls`), OpenDocument
8
+ * (`.ods`), or delimited text (`.csv`, `.tsv`).
9
+ *
10
+ * Parsing happens in Rust and off the JS thread, and only sheet names are read up
11
+ * front: a sheet's cells are read the first time {@link Workbook.sheet} asks for it.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const book = await openWorkbook(file);
16
+ * const sheet = await book.sheet(0);
17
+ * const cells = sheet.window({ rowStart: 0, rowEnd: 50 });
18
+ * cells.text(0, 0); // 'Item'
19
+ * ```
20
+ *
21
+ * @throws {@link EncryptedWorkbookError} when the workbook is password-protected.
22
+ */
23
+ export async function openWorkbook(source, options = {}) {
24
+ const bytes = await toBytes(source);
25
+ const format = options.format ?? formatFromName(source);
26
+ try {
27
+ const native = await loadWorkbook(bytes, { ...options, format });
28
+ return new Workbook(native);
29
+ }
30
+ catch (error) {
31
+ rethrowLoadError(error);
32
+ }
33
+ }
34
+ /**
35
+ * A `File` named `.tsv` is TSV whatever its contents sniff as.
36
+ *
37
+ * Only that one extension is trusted. The binary formats announce themselves in
38
+ * their first bytes, and a `.xls` downloaded from a web app is as often an HTML
39
+ * table or a CSV as it is BIFF — believing the name would refuse a readable file.
40
+ */
41
+ function formatFromName(source) {
42
+ const name = source.name;
43
+ return typeof name === 'string' && /\.(tsv|tab)$/i.test(name)
44
+ ? 'tsv'
45
+ : undefined;
46
+ }
47
+ /** An opened spreadsheet. Get one from {@link openWorkbook}. */
48
+ export class Workbook {
49
+ /** The container actually read. */
50
+ format;
51
+ /** Every sheet in tab order, hidden ones included. */
52
+ sheets;
53
+ /**
54
+ * CSV and TSV only: the encoding the text was decoded from, e.g.
55
+ * `'windows-1252'`. Worth showing when it was guessed — a wrong guess reads as
56
+ * mojibake, and {@link WorkbookOptions.encoding} is the fix.
57
+ */
58
+ encoding;
59
+ /** CSV and TSV only: the delimiter, given or sniffed. */
60
+ delimiter;
61
+ #native;
62
+ #sheets = new Map();
63
+ /** @internal — construct via {@link openWorkbook}. */
64
+ constructor(native) {
65
+ this.#native = native;
66
+ this.format = native.format;
67
+ this.sheets = native.sheets.map((s) => ({
68
+ name: s.name,
69
+ kind: s.kind,
70
+ visibility: s.visibility,
71
+ }));
72
+ this.encoding = native.encoding ?? undefined;
73
+ this.delimiter = native.delimiter ?? undefined;
74
+ }
75
+ /**
76
+ * Read one sheet, by index or by name.
77
+ *
78
+ * The first call parses the sheet, off the JS thread; later calls for the same
79
+ * sheet share that result.
80
+ */
81
+ sheet(which) {
82
+ const index = typeof which === 'number'
83
+ ? which
84
+ : this.sheets.findIndex((s) => s.name === which);
85
+ if (!Number.isInteger(index) || index < 0 || index >= this.sheets.length) {
86
+ return Promise.reject(new RangeError(`papyra: no sheet ${JSON.stringify(which)}`));
87
+ }
88
+ let sheet = this.#sheets.get(index);
89
+ if (!sheet) {
90
+ sheet = this.#native.sheet(index).then((native) => new Sheet(native));
91
+ // A failed read is not cached, so a retry gets a fresh attempt.
92
+ sheet.catch(() => this.#sheets.delete(index));
93
+ this.#sheets.set(index, sheet);
94
+ }
95
+ return sheet;
96
+ }
97
+ }
98
+ /**
99
+ * One sheet, parsed and held in Rust. Read it a window at a time.
100
+ *
101
+ * Coordinates are the sheet's own and 0-based: row 0 is the row Excel labels 1, and
102
+ * a sheet whose data starts at F10 still reports ten rows and six columns, so a grid
103
+ * draws the data where its author put it.
104
+ */
105
+ export class Sheet {
106
+ /** The name on the sheet's tab. */
107
+ name;
108
+ /** One past the last row holding a value or covered by a merge. */
109
+ rows;
110
+ /**
111
+ * The sheet held more cells than {@link WorkbookOptions.maxCells}, and this is
112
+ * its first whole rows. Worth saying on screen: the rest of the file is not here.
113
+ */
114
+ truncated;
115
+ /** One past the last column holding a value or covered by a merge. */
116
+ cols;
117
+ /**
118
+ * Merged regions. The value lives in each one's top-left cell; the others are
119
+ * empty. Always empty for `.xlsb` and `.ods`, which calamine does not read
120
+ * merges from.
121
+ */
122
+ merges;
123
+ /**
124
+ * The styles {@link CellWindow.style} indexes into, with the default at 0.
125
+ * xlsx only: empty for every other format, whose cells all read as style 0.
126
+ */
127
+ styles;
128
+ /**
129
+ * Column widths and row heights as the author set them. xlsx only; for anything
130
+ * else a grid sizes columns itself.
131
+ */
132
+ layout;
133
+ #native;
134
+ /** @internal — construct via {@link Workbook.sheet}. */
135
+ constructor(native) {
136
+ this.#native = native;
137
+ this.name = native.name;
138
+ this.rows = native.rows;
139
+ this.truncated = native.truncated;
140
+ this.cols = native.cols;
141
+ this.merges = toMergedRanges(native.merges);
142
+ this.styles = native.styles.map(toCellStyle);
143
+ this.layout = native.layout ? toSheetLayout(native.layout) : undefined;
144
+ }
145
+ /**
146
+ * Read a rectangle of cells, clamped to the sheet.
147
+ *
148
+ * Synchronous, because the sheet is already parsed and the cost is the size of
149
+ * the window. Ask for what is on screen plus some overscan, not the whole sheet:
150
+ * a screenful is a few thousand cells and well under a millisecond.
151
+ */
152
+ window(range) {
153
+ // The bindings take u32s, which a negative overscan would wrap rather than clamp.
154
+ const at = (n) => Math.max(0, Math.floor(n));
155
+ return new CellWindow(this.#native.window(at(range.rowStart), at(range.rowEnd), at(range.colStart ?? 0), at(range.colEnd ?? this.cols)));
156
+ }
157
+ }
158
+ //# sourceMappingURL=workbook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workbook.js","sourceRoot":"","sources":["../src/workbook.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@build-qube/papyra",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Fast PDF rendering for Node and the browser, powered by Rust",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -40,7 +40,7 @@
40
40
  "test:integration": "bun test test/integration"
41
41
  },
42
42
  "dependencies": {
43
- "@build-qube/papyra-native": "0.3.0"
43
+ "@build-qube/papyra-native": "0.4.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "typescript": "^7.0.2"