@build-qube/papyra 0.2.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.
Files changed (51) hide show
  1. package/README.md +18 -0
  2. package/dist/attachments.d.ts +76 -0
  3. package/dist/attachments.d.ts.map +1 -0
  4. package/dist/attachments.js +65 -0
  5. package/dist/attachments.js.map +1 -0
  6. package/dist/canvas.d.ts +27 -2
  7. package/dist/canvas.d.ts.map +1 -1
  8. package/dist/canvas.js +58 -5
  9. package/dist/canvas.js.map +1 -1
  10. package/dist/cells.d.ts +148 -0
  11. package/dist/cells.d.ts.map +1 -0
  12. package/dist/cells.js +144 -0
  13. package/dist/cells.js.map +1 -0
  14. package/dist/document.d.ts +61 -0
  15. package/dist/document.d.ts.map +1 -1
  16. package/dist/document.js +105 -7
  17. package/dist/document.js.map +1 -1
  18. package/dist/errors.d.ts +12 -0
  19. package/dist/errors.d.ts.map +1 -1
  20. package/dist/errors.js +17 -1
  21. package/dist/errors.js.map +1 -1
  22. package/dist/index.d.ts +18 -2
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +10 -2
  25. package/dist/index.js.map +1 -1
  26. package/dist/structure.d.ts +119 -0
  27. package/dist/structure.d.ts.map +1 -0
  28. package/dist/structure.js +115 -0
  29. package/dist/structure.js.map +1 -0
  30. package/dist/styles.d.ts +96 -0
  31. package/dist/styles.d.ts.map +1 -0
  32. package/dist/styles.js +69 -0
  33. package/dist/styles.js.map +1 -0
  34. package/dist/text.d.ts +18 -0
  35. package/dist/text.d.ts.map +1 -1
  36. package/dist/text.js.map +1 -1
  37. package/dist/tiff.d.ts +95 -0
  38. package/dist/tiff.d.ts.map +1 -0
  39. package/dist/tiff.js +78 -0
  40. package/dist/tiff.js.map +1 -0
  41. package/dist/types.d.ts +25 -0
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/viewport.d.ts +129 -0
  44. package/dist/viewport.d.ts.map +1 -0
  45. package/dist/viewport.js +163 -0
  46. package/dist/viewport.js.map +1 -0
  47. package/dist/workbook.d.ts +152 -0
  48. package/dist/workbook.d.ts.map +1 -0
  49. package/dist/workbook.js +158 -0
  50. package/dist/workbook.js.map +1 -0
  51. package/package.json +2 -2
package/README.md CHANGED
@@ -104,6 +104,24 @@ Encrypted files throw `PasswordRequiredError` or `IncorrectPasswordError`, both
104
104
  extending `PasswordError` with a `retry` flag, so one dialog handles the cold ask and
105
105
  the wrong answer.
106
106
 
107
+ ## Rotate the view
108
+
109
+ ```ts
110
+ const vp = viewport(doc.pageSize(index), { fitWidth: 1600, rotation: 90 });
111
+
112
+ paintToCanvas(await doc.renderPage(index, { dpi: vp.dpi }), canvas, {
113
+ rotation: vp.rotation,
114
+ });
115
+ const box = viewportRect(link.rect, vp); // the link layer, turned to match
116
+ ```
117
+
118
+ Pages render unrotated and the canvas does the turning, so a rotate button costs no
119
+ render. Size through the viewport rather than with `fitWidth` directly: turned, the
120
+ width on screen is the page's height, and `vp.dpi` carries the answer back.
121
+
122
+ Renders draw annotations by default. Pass `{ annotations: false }` when you are drawing
123
+ your own link or highlight layer, or they appear twice.
124
+
107
125
  ## Two things that will bite you
108
126
 
109
127
  **Size with `fitWidth`, not `dpi`.** Page areas vary by two orders of magnitude. At a
@@ -0,0 +1,76 @@
1
+ import type { Attachment as NativeAttachment } from '@build-qube/papyra-native';
2
+ /**
3
+ * A file embedded in the document.
4
+ *
5
+ * Metadata only. The bytes come from {@link Document.attachmentData}, because listing
6
+ * what a document carries is a different question from opening one of the things it
7
+ * carries, and an embedded file is as large as it is.
8
+ */
9
+ export interface Attachment {
10
+ /** Position in {@link Document.attachments}, and what identifies it for a fetch. */
11
+ readonly index: number;
12
+ /**
13
+ * The name to save the file under.
14
+ *
15
+ * `/UF` where the document provides it — the Unicode spelling, and the one the spec
16
+ * tells a reader to prefer — falling back to `/F`, then to the name the file was
17
+ * filed under. Never empty.
18
+ */
19
+ readonly name: string;
20
+ /** The document's own description of what the file is for. */
21
+ readonly description: string | null;
22
+ /**
23
+ * The declared media type, e.g. `'application/xml'`.
24
+ *
25
+ * Absent more often than not, so fall back to the extension on {@link name} rather
26
+ * than treating this as the answer. {@link attachmentMediaType} does exactly that.
27
+ */
28
+ readonly mediaType: string | null;
29
+ /**
30
+ * Length in bytes, uncompressed, **as the document claims it**.
31
+ *
32
+ * Not a measurement: reading the true length means decompressing the stream, which
33
+ * is the work this type exists to defer. Fine for a size column; not something to
34
+ * allocate against.
35
+ */
36
+ readonly size: number | null;
37
+ /** Creation date, ISO 8601. */
38
+ readonly created: string | null;
39
+ /** Modification date, ISO 8601. */
40
+ readonly modified: string | null;
41
+ /**
42
+ * What the file is to the document: `'Source'`, `'Data'`, `'Alternative'`,
43
+ * `'Supplement'`, `'EncryptedPayload'` or `'Unspecified'`.
44
+ *
45
+ * This is what identifies a hybrid invoice. A ZUGFeRD or Factur-X PDF carries its
46
+ * XML with a relationship of `Alternative` or `Data`, and that is the difference
47
+ * between a machine-readable invoice and a PDF with a file stapled to it — see
48
+ * {@link isInvoiceAttachment}.
49
+ */
50
+ readonly relationship: string | null;
51
+ }
52
+ /** @internal */
53
+ export declare function toAttachment(native: NativeAttachment, index: number): Attachment;
54
+ /**
55
+ * The attachment's media type, falling back to its extension.
56
+ *
57
+ * `'application/octet-stream'` when neither answers, which is the honest default for
58
+ * bytes nothing describes — and the one a download will not misrender.
59
+ */
60
+ export declare function attachmentMediaType(file: Attachment): string;
61
+ /**
62
+ * Whether this attachment is the machine-readable half of a hybrid invoice.
63
+ *
64
+ * ZUGFeRD, Factur-X, Order-X and XRechnung all work the same way: the PDF is what a
65
+ * person reads, and an embedded XML file is what an accounting system reads. Both
66
+ * halves are the same invoice, and a consumer that ignores the XML is retyping data
67
+ * the document already carries.
68
+ *
69
+ * Matched on the standardised filename rather than on
70
+ * {@link Attachment.relationship} alone. The relationship narrows it — the standards
71
+ * require `Alternative` or `Data` — but producers get it wrong often enough that
72
+ * requiring it would miss real invoices, while the filenames are fixed by the
73
+ * specifications and are what every other implementation keys on.
74
+ */
75
+ export declare function isInvoiceAttachment(file: Attachment): boolean;
76
+ //# sourceMappingURL=attachments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../src/attachments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAEhF;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,oFAAoF;IACpF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,+BAA+B;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;;;;;;OAQG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED,gBAAgB;AAChB,wBAAgB,YAAY,CAC1B,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,MAAM,GACZ,UAAU,CAWZ;AAiBD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAK5D;AAUD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAE7D"}
@@ -0,0 +1,65 @@
1
+ /** @internal */
2
+ export function toAttachment(native, index) {
3
+ return {
4
+ index,
5
+ name: native.name,
6
+ description: native.description ?? null,
7
+ mediaType: native.mediaType ?? null,
8
+ size: native.size ?? null,
9
+ created: native.created ?? null,
10
+ modified: native.modified ?? null,
11
+ relationship: native.relationship ?? null,
12
+ };
13
+ }
14
+ /** Extension to media type, for the majority of files that declare none. */
15
+ const BY_EXTENSION = {
16
+ csv: 'text/csv',
17
+ html: 'text/html',
18
+ json: 'application/json',
19
+ pdf: 'application/pdf',
20
+ png: 'image/png',
21
+ jpg: 'image/jpeg',
22
+ jpeg: 'image/jpeg',
23
+ svg: 'image/svg+xml',
24
+ txt: 'text/plain',
25
+ xml: 'application/xml',
26
+ zip: 'application/zip',
27
+ };
28
+ /**
29
+ * The attachment's media type, falling back to its extension.
30
+ *
31
+ * `'application/octet-stream'` when neither answers, which is the honest default for
32
+ * bytes nothing describes — and the one a download will not misrender.
33
+ */
34
+ export function attachmentMediaType(file) {
35
+ if (file.mediaType)
36
+ return file.mediaType;
37
+ const dot = file.name.lastIndexOf('.');
38
+ const extension = dot < 0 ? '' : file.name.slice(dot + 1).toLowerCase();
39
+ return BY_EXTENSION[extension] ?? 'application/octet-stream';
40
+ }
41
+ /** The filenames the hybrid-invoice standards define, lowercased. */
42
+ const INVOICE_NAMES = new Set([
43
+ 'factur-x.xml',
44
+ 'zugferd-invoice.xml',
45
+ 'xrechnung.xml',
46
+ 'order-x.xml',
47
+ ]);
48
+ /**
49
+ * Whether this attachment is the machine-readable half of a hybrid invoice.
50
+ *
51
+ * ZUGFeRD, Factur-X, Order-X and XRechnung all work the same way: the PDF is what a
52
+ * person reads, and an embedded XML file is what an accounting system reads. Both
53
+ * halves are the same invoice, and a consumer that ignores the XML is retyping data
54
+ * the document already carries.
55
+ *
56
+ * Matched on the standardised filename rather than on
57
+ * {@link Attachment.relationship} alone. The relationship narrows it — the standards
58
+ * require `Alternative` or `Data` — but producers get it wrong often enough that
59
+ * requiring it would miss real invoices, while the filenames are fixed by the
60
+ * specifications and are what every other implementation keys on.
61
+ */
62
+ export function isInvoiceAttachment(file) {
63
+ return INVOICE_NAMES.has(file.name.toLowerCase());
64
+ }
65
+ //# sourceMappingURL=attachments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../src/attachments.ts"],"names":[],"mappings":"AAqDA,gBAAgB;AAChB,MAAM,UAAU,YAAY,CAC1B,MAAwB,EACxB,KAAa;IAEb,OAAO;QACL,KAAK;QACL,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI;QACvC,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,IAAI;QACnC,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI;QACzB,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,IAAI;QAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,IAAI;QACjC,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,IAAI;KAC1C,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,MAAM,YAAY,GAA2B;IAC3C,GAAG,EAAE,UAAU;IACf,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,kBAAkB;IACxB,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,YAAY;IACjB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,eAAe;IACpB,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,iBAAiB;CACvB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAgB;IAClD,IAAI,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACxE,OAAO,YAAY,CAAC,SAAS,CAAC,IAAI,0BAA0B,CAAC;AAC/D,CAAC;AAED,qEAAqE;AACrE,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,cAAc;IACd,qBAAqB;IACrB,eAAe;IACf,aAAa;CACd,CAAC,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAgB;IAClD,OAAO,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;AACpD,CAAC"}
package/dist/canvas.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { RenderedPage } from './types.js';
2
+ import type { Rotation } from './viewport.js';
2
3
  /**
3
4
  * Wrap a rendered page as `ImageData`, ready for `putImageData`.
4
5
  *
@@ -7,6 +8,30 @@ import type { RenderedPage } from './types.js';
7
8
  * unconditionally keeps both runtimes on the same path.
8
9
  */
9
10
  export declare function toImageData(page: RenderedPage): ImageData;
10
- /** Paint a rendered page onto a canvas, resizing the canvas to match. */
11
- export declare function paintToCanvas(page: RenderedPage, canvas: HTMLCanvasElement | OffscreenCanvas): void;
11
+ /** How to paint. */
12
+ export interface PaintOptions {
13
+ /**
14
+ * Quarter turns clockwise to apply while drawing. Defaults to none.
15
+ *
16
+ * Free in the sense that matters: the pixels are not copied twice and no rotated
17
+ * bitmap is retained. Pair it with a {@link Viewport} of the same rotation so that
18
+ * link regions and text highlights land on the same page the pixels do.
19
+ */
20
+ rotation?: Rotation;
21
+ }
22
+ /**
23
+ * Paint a rendered page onto a canvas, resizing the canvas to match.
24
+ *
25
+ * With a `rotation` the canvas takes the turned dimensions — a 90° view of a portrait
26
+ * page is a landscape canvas.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * const vp = viewport(doc.pageSize(0), { fitWidth: 1600, rotation: 90 });
31
+ * paintToCanvas(await doc.renderPage(0, { dpi: vp.dpi }), canvas, {
32
+ * rotation: vp.rotation,
33
+ * });
34
+ * ```
35
+ */
36
+ export declare function paintToCanvas(page: RenderedPage, canvas: HTMLCanvasElement | OffscreenCanvas, options?: PaintOptions): void;
12
37
  //# sourceMappingURL=canvas.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../src/canvas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,CAMzD;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAC3B,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,iBAAiB,GAAG,eAAe,GAC1C,IAAI,CASN"}
1
+ {"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../src/canvas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAU9C;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,CAMzD;AAED,oBAAoB;AACpB,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,iBAAiB,GAAG,eAAe,EAC3C,OAAO,GAAE,YAAiB,GACzB,IAAI,CA+BN"}
package/dist/canvas.js CHANGED
@@ -8,13 +8,66 @@
8
8
  export function toImageData(page) {
9
9
  return new ImageData(Uint8ClampedArray.from(page.data), page.width, page.height);
10
10
  }
11
- /** Paint a rendered page onto a canvas, resizing the canvas to match. */
12
- export function paintToCanvas(page, canvas) {
13
- canvas.width = page.width;
14
- canvas.height = page.height;
11
+ /**
12
+ * Paint a rendered page onto a canvas, resizing the canvas to match.
13
+ *
14
+ * With a `rotation` the canvas takes the turned dimensions — a 90° view of a portrait
15
+ * page is a landscape canvas.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const vp = viewport(doc.pageSize(0), { fitWidth: 1600, rotation: 90 });
20
+ * paintToCanvas(await doc.renderPage(0, { dpi: vp.dpi }), canvas, {
21
+ * rotation: vp.rotation,
22
+ * });
23
+ * ```
24
+ */
25
+ export function paintToCanvas(page, canvas, options = {}) {
26
+ const rotation = options.rotation ?? 0;
27
+ const turned = rotation === 90 || rotation === 270;
28
+ canvas.width = turned ? page.height : page.width;
29
+ canvas.height = turned ? page.width : page.height;
15
30
  const ctx = canvas.getContext('2d');
16
31
  if (!ctx)
17
32
  throw new Error('papyra: could not get a 2d canvas context');
18
- ctx.putImageData(toImageData(page), 0, 0);
33
+ if (rotation === 0) {
34
+ ctx.putImageData(toImageData(page), 0, 0);
35
+ return;
36
+ }
37
+ // `putImageData` writes straight to the backing store and ignores the transform, so
38
+ // a rotation cannot go through it. The pixels land on a scratch surface first and
39
+ // are then blitted under a transform, which is one extra copy — against rotating
40
+ // the buffer ourselves, which is a copy plus a per-pixel loop in JS.
41
+ const scratch = scratchCanvas(page.width, page.height);
42
+ const scratchCtx = scratch.getContext('2d');
43
+ if (!scratchCtx)
44
+ throw new Error('papyra: could not get a 2d canvas context');
45
+ scratchCtx.putImageData(toImageData(page), 0, 0);
46
+ // Each pair puts the rotated page's origin back at the canvas corner: at 90° the
47
+ // page's top-left corner ends up top-right, so the axes move there first.
48
+ if (rotation === 90)
49
+ ctx.translate(canvas.width, 0);
50
+ else if (rotation === 180)
51
+ ctx.translate(canvas.width, canvas.height);
52
+ else
53
+ ctx.translate(0, canvas.height);
54
+ ctx.rotate((rotation * Math.PI) / 180);
55
+ ctx.drawImage(scratch, 0, 0);
56
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
57
+ }
58
+ /**
59
+ * A surface to hold the unrotated pixels.
60
+ *
61
+ * `OffscreenCanvas` when there is one — it is the only option inside a worker, where
62
+ * there is no `document` to create an element from.
63
+ */
64
+ function scratchCanvas(width, height) {
65
+ if (typeof OffscreenCanvas !== 'undefined') {
66
+ return new OffscreenCanvas(width, height);
67
+ }
68
+ const el = document.createElement('canvas');
69
+ el.width = width;
70
+ el.height = height;
71
+ return el;
19
72
  }
20
73
  //# sourceMappingURL=canvas.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"canvas.js","sourceRoot":"","sources":["../src/canvas.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,IAAkB;IAC5C,OAAO,IAAI,SAAS,CAClB,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EACjC,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,MAAM,CACZ,CAAC;AACJ,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,aAAa,CAC3B,IAAkB,EAClB,MAA2C;IAE3C,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IAC1B,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAG1B,CAAC;IACT,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IACvE,GAAG,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5C,CAAC"}
1
+ {"version":3,"file":"canvas.js","sourceRoot":"","sources":["../src/canvas.ts"],"names":[],"mappings":"AAWA;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,IAAkB;IAC5C,OAAO,IAAI,SAAS,CAClB,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EACjC,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,MAAM,CACZ,CAAC;AACJ,CAAC;AAcD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAkB,EAClB,MAA2C,EAC3C,OAAO,GAAiB,EAAE;IAE1B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,QAAQ,KAAK,EAAE,IAAI,QAAQ,KAAK,GAAG,CAAC;IACnD,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IACjD,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IAElD,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAsB,CAAC;IACzD,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAEvE,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QACnB,GAAG,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1C,OAAO;IACT,CAAC;IAED,oFAAoF;IACpF,kFAAkF;IAClF,iFAAiF;IACjF,qEAAqE;IACrE,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAsB,CAAC;IACjE,IAAI,CAAC,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC9E,UAAU,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAEjD,iFAAiF;IACjF,0EAA0E;IAC1E,IAAI,QAAQ,KAAK,EAAE;QAAE,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;SAC/C,IAAI,QAAQ,KAAK,GAAG;QAAE,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;;QACjE,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACrC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;IACvC,GAAG,CAAC,SAAS,CAAC,OAA4B,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAClD,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,SAAS,aAAa,CAAC,KAAa,EAAE,MAAc;IAClD,IAAI,OAAO,eAAe,KAAK,WAAW,EAAE,CAAC;QAC3C,OAAO,IAAI,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC5C,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC;IACjB,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC;IACnB,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -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":"AAAA,OAAO,KAAK,EAAE,UAAU,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAEhF,gFAAgF;AAChF,MAAM,MAAM,QAAQ,GAChB,OAAO,GACP,QAAQ,GACR,MAAM,GACN,MAAM,GACN,MAAM,GACN,UAAU,GACV,OAAO,CAAC;AAaZ,oEAAoE;AACpE,MAAM,WAAW,SAAS;IACxB,wBAAwB;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,mBAAmB;IACnB,IAAI,EAAE,EAAE,CAAC;CACV;AAED,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACzB,yBAAyB;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED,mEAAmE;AACnE,MAAM,WAAW,QAAQ;IACvB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,iBAAiB;AACjB,MAAM,WAAW,QAAQ;IACvB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,8EAA8E;IAC9E,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,+BAA+B;AAC/B,MAAM,WAAW,QAAQ;IACvB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAwB;AACxB,MAAM,WAAW,YAAY;IAC3B,2BAA2B;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;CACd;AAED,uCAAuC;AACvC,MAAM,WAAW,SAAS;IACxB,wBAAwB;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;GAMG;AACH,MAAM,MAAM,IAAI,GACZ,SAAS,GACT,UAAU,GACV,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,YAAY,GACZ,SAAS,CAAC;AAEd;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,qBAAa,UAAU;;IACrB,sBAAsB;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,yBAAyB;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oBAAoB;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAGtB,oCAAoC;IACpC,YAAY,MAAM,EAAE,gBAAgB,EAMnC;IAED,kCAAkC;IAClC,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,qCAAqC;IACrC,IAAI,MAAM,IAAI,MAAM,CAEnB;IASD,sEAAsE;IACtE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,CAGvC;IAED,iEAAiE;IACjE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAKrC;IAED;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGvC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGtC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIlD;IAED,+CAA+C;IAC/C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAqBnC;CACF;AAED,uDAAuD;AACvD,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,EAAE,CAWhE;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMhD"}
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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"}