@build-qube/papyra-tauri 0.0.0-stage → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,26 @@
1
- # Temporary Holding Version
1
+ # @build-qube/papyra-tauri
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Tauri engines for papyra's viewer and file preview: PDFs, TIFFs, spreadsheets, and
4
+ Word and PowerPoint are parsed and rendered by papyra in the app's host process,
5
+ through the `tauri-plugin-papyra` crate. `TauriEngine` is the PDF engine;
6
+ `openTiff` and `openWorkbook` mirror papyra's own and resolve to its classes; and
7
+ `TauriOfficeEngine` stands in for papyra's `officeEngine`.
8
+
9
+ A Tauri app's WebView is never cross-origin isolated on Android or iOS, so papyra's
10
+ wasm build cannot run there. This engine does not need it: the Rust side renders on
11
+ the device's real cores, and the WebView only paints.
12
+
13
+ Installing it, wiring `tauri-plugin-papyra` into the app, and keeping papyra's
14
+ wasm out of the bundle are in the [Tauri guide](https://buildqube.github.io/Papyra/docs/guides/tauri).
15
+
16
+ ## Pages and lifetimes
17
+
18
+ Pages travel over a `papyra://` protocol, as PNG by default. `new TauriEngine({
19
+ format: 'rgba' })` sends raw pixels instead: no encode or decode, four times the
20
+ bytes. Which is faster depends on the device.
21
+
22
+ Documents stay in the host until closed — TIFFs and workbooks too, through their
23
+ `close()`. The viewer's store and file preview close what they open; if you call the engine yourself, `await engine.close(doc)` — it
24
+ rejects if the host could not release the document. When a WebView loads a page —
25
+ a reload, HMR, the app restarting its UI — the host drops every document that
26
+ WebView had open, since nothing on the new page could close them.
@@ -0,0 +1,73 @@
1
+ import { type Attachment, type Availability, type BackendRenderOptions, type Capabilities, type DocumentMetadata, type OpenOptions, type OutlineNode, type PageBitmap, type PageLink, type PageSize, type PageText, type PdfBackend, PdfEngine, type PdfSource, type StructNode } from '@build-qube/papyra/core';
2
+ import { type TauriPageFormat } from './host.js';
3
+ type NativeInfo = {
4
+ [K in keyof DocumentMetadata]?: string | null;
5
+ };
6
+ export type { TauriPageFormat } from './host.js';
7
+ /** Options for {@link TauriEngine}. */
8
+ export interface TauriEngineOptions {
9
+ /**
10
+ * How pages come back from the host. `'png'` (the default) costs an encode in Rust
11
+ * and a decode in the WebView, off its main thread; `'rgba'` costs neither and is
12
+ * four times the bytes over an in-process channel, painted with `putImageData`.
13
+ * Which is faster depends on the device — measure on yours.
14
+ */
15
+ format?: TauriPageFormat;
16
+ }
17
+ /** The plugin's answer to `open`. */
18
+ interface Opened {
19
+ id: number;
20
+ sizes: [number, number][];
21
+ info: NativeInfo;
22
+ pdfVersion: string | null;
23
+ }
24
+ /**
25
+ * PDFs parsed and rendered by papyra in the Tauri app's host process, through
26
+ * `tauri-plugin-papyra`.
27
+ *
28
+ * For a Tauri app's WebView, which is never cross-origin isolated on Android or iOS
29
+ * and so cannot run papyra's wasm. Here the work runs on the host's real cores with
30
+ * no wasm at all, and the WebView only paints.
31
+ *
32
+ * The app registers the plugin (`.plugin(tauri_plugin_papyra::init())`) and allows
33
+ * `papyra:default` in its capabilities. Everything papyra's own engine reads, this one
34
+ * does: same parser, same text, same structure tree.
35
+ *
36
+ * Documents live in the host until closed, so close what you open — the viewer's
37
+ * store and file preview do.
38
+ */
39
+ export declare class TauriEngine extends PdfEngine<TauriBackend> {
40
+ #private;
41
+ readonly id = "tauri";
42
+ constructor(options?: TauriEngineOptions);
43
+ availability(): Availability;
44
+ protected load(source: PdfSource, options: OpenOptions): Promise<TauriBackend>;
45
+ }
46
+ /**
47
+ * One document held by the host, as a papyra backend.
48
+ *
49
+ * @internal Exported for tests.
50
+ */
51
+ export declare class TauriBackend implements PdfBackend {
52
+ #private;
53
+ readonly fingerprint: string;
54
+ readonly format: TauriPageFormat;
55
+ readonly capabilities: Capabilities;
56
+ readonly abortable = false;
57
+ readonly concurrency = 4;
58
+ constructor(opened: Opened, fingerprint: string, format: TauriPageFormat);
59
+ get pageCount(): number;
60
+ pageSize(index: number): PageSize;
61
+ renderPage(index: number, options: BackendRenderOptions, signal?: AbortSignal): Promise<PageBitmap>;
62
+ metadata(): DocumentMetadata;
63
+ pdfVersion(): string | null;
64
+ pageText(index: number): Promise<PageText>;
65
+ outline(): Promise<OutlineNode[]>;
66
+ links(index: number): Promise<readonly PageLink[]>;
67
+ pageLabels(): Promise<readonly string[]>;
68
+ attachments(): Promise<readonly Attachment[]>;
69
+ attachmentData(index: number): Promise<Uint8Array>;
70
+ structTree(): Promise<StructNode[]>;
71
+ close(): Promise<void>;
72
+ }
73
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,oBAAoB,EAGzB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EAErB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,SAAS,EACT,KAAK,SAAS,EAEd,KAAK,UAAU,EAKhB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,WAAW,CAAC;AAQnB,KAAK,UAAU,GAAG;KAAG,CAAC,IAAI,MAAM,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;CAAE,CAAC;AAEpE,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED,qCAAqC;AACrC,UAAU,MAAM;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAaD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,WAAY,SAAQ,SAAS,CAAC,YAAY,CAAC;;IACtD,QAAQ,CAAC,EAAE,WAAW;IAGtB,YAAY,OAAO,GAAE,kBAAuB,EAG3C;IAED,YAAY,IAAI,YAAY,CAE3B;IAED,UAAgB,IAAI,CAClB,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,YAAY,CAAC,CAevB;CACF;AAED;;;;GAIG;AACH,qBAAa,YAAa,YAAW,UAAU;;IAc3C,QAAQ,CAAC,WAAW,EAAE,MAAM;IAC5B,QAAQ,CAAC,MAAM,EAAE,eAAe;IAdlC,QAAQ,CAAC,YAAY,eAAc;IAGnC,QAAQ,CAAC,SAAS,SAAS;IAC3B,QAAQ,CAAC,WAAW,KAAK;IAOzB,YACE,MAAM,EAAE,MAAM,EACL,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,eAAe,EAiBjC;IAED,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAIhC;IAED,UAAU,CACR,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,oBAAoB,EAC7B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAOrB;IAED,QAAQ,IAAI,gBAAgB,CAE3B;IAED,UAAU,IAAI,MAAM,GAAG,IAAI,CAE1B;IAMK,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAU/C;IAEK,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAEtC;IAEK,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,QAAQ,EAAE,CAAC,CAKvD;IAED,UAAU,IAAI,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAEvC;IAEK,WAAW,IAAI,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAGlD;IAEK,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAIvD;IAEK,UAAU,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAIxC;IAED,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAErB;CACF"}
package/dist/engine.js ADDED
@@ -0,0 +1,152 @@
1
+ import { buildOutlineTree, buildStructTree, fingerprint, PdfEngine, rethrowLoadError, toAttachment, toBytes, toPageLink, toPageText, } from '@build-qube/papyra/core';
2
+ import { invoke } from '@tauri-apps/api/core';
3
+ import { closeDocument, command, fetchPage, pagesOf, tauriAvailability, } from './host.js';
4
+ /** papyra's engine reads everything, and so does the host running it. */
5
+ const EVERYTHING = {
6
+ text: true,
7
+ outline: true,
8
+ links: true,
9
+ attachments: true,
10
+ structure: true,
11
+ pageLabels: true,
12
+ annotationsToggle: true,
13
+ };
14
+ /**
15
+ * PDFs parsed and rendered by papyra in the Tauri app's host process, through
16
+ * `tauri-plugin-papyra`.
17
+ *
18
+ * For a Tauri app's WebView, which is never cross-origin isolated on Android or iOS
19
+ * and so cannot run papyra's wasm. Here the work runs on the host's real cores with
20
+ * no wasm at all, and the WebView only paints.
21
+ *
22
+ * The app registers the plugin (`.plugin(tauri_plugin_papyra::init())`) and allows
23
+ * `papyra:default` in its capabilities. Everything papyra's own engine reads, this one
24
+ * does: same parser, same text, same structure tree.
25
+ *
26
+ * Documents live in the host until closed, so close what you open — the viewer's
27
+ * store and file preview do.
28
+ */
29
+ export class TauriEngine extends PdfEngine {
30
+ id = 'tauri';
31
+ #format;
32
+ constructor(options = {}) {
33
+ super();
34
+ this.#format = options.format ?? 'png';
35
+ }
36
+ availability() {
37
+ return tauriAvailability('tauri-plugin-papyra');
38
+ }
39
+ async load(source, options) {
40
+ const bytes = await toBytes(source);
41
+ let opened;
42
+ try {
43
+ opened = await invoke(command('open'), bytes, {
44
+ headers: options.password === undefined
45
+ ? {}
46
+ : // Headers are ASCII; a password need not be.
47
+ { 'x-papyra-password': encodeURIComponent(options.password) },
48
+ });
49
+ }
50
+ catch (e) {
51
+ rethrowLoadError(e);
52
+ }
53
+ return new TauriBackend(opened, fingerprint(bytes), this.#format);
54
+ }
55
+ }
56
+ /**
57
+ * One document held by the host, as a papyra backend.
58
+ *
59
+ * @internal Exported for tests.
60
+ */
61
+ export class TauriBackend {
62
+ fingerprint;
63
+ format;
64
+ capabilities = EVERYTHING;
65
+ // A fetch can be aborted, but the render in Rust runs on regardless; abandoning it
66
+ // would only make a page scrolled back to render twice.
67
+ abortable = false;
68
+ concurrency = 4;
69
+ #id;
70
+ #sizes;
71
+ #info;
72
+ #version;
73
+ #pages;
74
+ constructor(opened, fingerprint, format) {
75
+ this.fingerprint = fingerprint;
76
+ this.format = format;
77
+ this.#id = opened.id;
78
+ this.#sizes = opened.sizes.map(([width, height]) => ({ width, height }));
79
+ const i = opened.info;
80
+ this.#info = {
81
+ title: i.title ?? null,
82
+ author: i.author ?? null,
83
+ subject: i.subject ?? null,
84
+ keywords: i.keywords ?? null,
85
+ creator: i.creator ?? null,
86
+ producer: i.producer ?? null,
87
+ created: i.created ?? null,
88
+ modified: i.modified ?? null,
89
+ };
90
+ this.#version = opened.pdfVersion ?? null;
91
+ this.#pages = pagesOf(this.#id);
92
+ }
93
+ get pageCount() {
94
+ return this.#sizes.length;
95
+ }
96
+ pageSize(index) {
97
+ const size = this.#sizes[index];
98
+ if (!size)
99
+ throw new RangeError(`page ${index} is out of range`);
100
+ return size;
101
+ }
102
+ renderPage(index, options, signal) {
103
+ const annots = options.annotations === false ? 0 : 1;
104
+ return fetchPage(`${this.#pages}${index}?dpi=${options.dpi}&annots=${annots}`, this.format, signal);
105
+ }
106
+ metadata() {
107
+ return this.#info;
108
+ }
109
+ pdfVersion() {
110
+ return this.#version;
111
+ }
112
+ #call(name, args = {}) {
113
+ return invoke(command(name), { id: this.#id, ...args });
114
+ }
115
+ async pageText(index) {
116
+ const text = await this.#call('page_text', { index });
117
+ // JSON carries offsets as numbers; papyra's lines hold a Float32Array.
118
+ return toPageText(index, {
119
+ ...text,
120
+ lines: text.lines.map((line) => ({
121
+ ...line,
122
+ offsets: Float32Array.from(line.offsets),
123
+ })),
124
+ });
125
+ }
126
+ async outline() {
127
+ return buildOutlineTree(await this.#call('outline'));
128
+ }
129
+ async links(index) {
130
+ const links = await this.#call('links', { index });
131
+ return links
132
+ .map(toPageLink)
133
+ .filter((link) => link !== null);
134
+ }
135
+ pageLabels() {
136
+ return this.#call('page_labels');
137
+ }
138
+ async attachments() {
139
+ const files = await this.#call('attachments');
140
+ return files.map(toAttachment);
141
+ }
142
+ async attachmentData(index) {
143
+ return new Uint8Array(await this.#call('attachment_data', { index }));
144
+ }
145
+ async structTree() {
146
+ return buildStructTree(await this.#call('struct_tree'));
147
+ }
148
+ close() {
149
+ return closeDocument(this.#id);
150
+ }
151
+ }
152
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
package/dist/host.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ import type { Availability, PageBitmap } from '@build-qube/papyra/core';
2
+ /** How pages travel from the host. */
3
+ export type TauriPageFormat = 'png' | 'rgba';
4
+ /** A plugin command, by the name Tauri routes it under. */
5
+ export declare const command: (name: string, plugin?: string) => string;
6
+ /** Ready inside a Tauri WebView; elsewhere, says which plugin it is waiting for. */
7
+ export declare function tauriAvailability(plugin: string): Availability;
8
+ /**
9
+ * Where one document's pages are served: `papyra://localhost/<id>/` on macOS, iOS
10
+ * and Linux, `http://papyra.localhost/<id>/` on Android and Windows — Tauri knows
11
+ * which, so ask it rather than sniff.
12
+ */
13
+ export declare function pagesOf(id: number): string;
14
+ /**
15
+ * One page from the `papyra://` protocol, whichever format the document is: PNG
16
+ * decoded off the main thread to an `ImageBitmap`, or raw RGBA as papyra's own pages
17
+ * are.
18
+ */
19
+ export declare function fetchPage(url: string, format: TauriPageFormat, signal?: AbortSignal): Promise<PageBitmap>;
20
+ /** Free a document of any format; closing one already gone is not an error. */
21
+ export declare function closeDocument(id: number): Promise<void>;
22
+ //# sourceMappingURL=host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGxE,sCAAsC;AACtC,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,MAAM,CAAC;AAE7C,2DAA2D;AAC3D,eAAO,MAAM,OAAO,SAAU,MAAM,4BACR,CAAC;AAE7B,oFAAoF;AACpF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAS9D;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,eAAe,EACvB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAarB;AAED,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvD"}
package/dist/host.js ADDED
@@ -0,0 +1,48 @@
1
+ import { convertFileSrc, invoke } from '@tauri-apps/api/core';
2
+ /** A plugin command, by the name Tauri routes it under. */
3
+ export const command = (name, plugin = 'papyra') => `plugin:${plugin}|${name}`;
4
+ /** Ready inside a Tauri WebView; elsewhere, says which plugin it is waiting for. */
5
+ export function tauriAvailability(plugin) {
6
+ if ('__TAURI_INTERNALS__' in globalThis)
7
+ return { ok: true };
8
+ return {
9
+ ok: false,
10
+ title: 'Not running inside a Tauri app',
11
+ reason: 'This engine renders in the app’s host process, through ' +
12
+ `${plugin}, and this page is not in a Tauri WebView.`,
13
+ };
14
+ }
15
+ /**
16
+ * Where one document's pages are served: `papyra://localhost/<id>/` on macOS, iOS
17
+ * and Linux, `http://papyra.localhost/<id>/` on Android and Windows — Tauri knows
18
+ * which, so ask it rather than sniff.
19
+ */
20
+ export function pagesOf(id) {
21
+ return `${convertFileSrc('', 'papyra')}${id}/`;
22
+ }
23
+ /**
24
+ * One page from the `papyra://` protocol, whichever format the document is: PNG
25
+ * decoded off the main thread to an `ImageBitmap`, or raw RGBA as papyra's own pages
26
+ * are.
27
+ */
28
+ export async function fetchPage(url, format, signal) {
29
+ const res = await fetch(`${url}&format=${format}`, { signal });
30
+ if (!res.ok)
31
+ throw new Error(await res.text());
32
+ if (format === 'png')
33
+ return createImageBitmap(await res.blob());
34
+ const width = Number(res.headers.get('x-width'));
35
+ const height = Number(res.headers.get('x-height'));
36
+ return {
37
+ width,
38
+ height,
39
+ stride: width * 4,
40
+ format: 'rgba8',
41
+ data: new Uint8Array(await res.arrayBuffer()),
42
+ };
43
+ }
44
+ /** Free a document of any format; closing one already gone is not an error. */
45
+ export function closeDocument(id) {
46
+ return invoke(command('close'), { id });
47
+ }
48
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAK9D,2DAA2D;AAC3D,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,MAAM,GAAG,QAAQ,EAAE,EAAE,CACzD,UAAU,MAAM,IAAI,IAAI,EAAE,CAAC;AAE7B,oFAAoF;AACpF,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,IAAI,qBAAqB,IAAI,UAAU;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IAC7D,OAAO;QACL,EAAE,EAAE,KAAK;QACT,KAAK,EAAE,gCAAgC;QACvC,MAAM,EACJ,yDAAyD;YACzD,GAAG,MAAM,4CAA4C;KACxD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,OAAO,GAAG,cAAc,CAAC,EAAE,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,GAAW,EACX,MAAuB,EACvB,MAAoB;IAEpB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,GAAG,WAAW,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/D,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/C,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,iBAAiB,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACjE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;IACnD,OAAO;QACL,KAAK;QACL,MAAM;QACN,MAAM,EAAE,KAAK,GAAG,CAAC;QACjB,MAAM,EAAE,OAAO;QACf,IAAI,EAAE,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;KAC9C,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,aAAa,CAAC,EAAU;IACtC,OAAO,MAAM,CAAO,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Tauri engines for papyra's viewer: PDFs, TIFFs, spreadsheets, and Word and
3
+ * PowerPoint parsed and rendered by papyra in the app's host process, through
4
+ * `tauri-plugin-papyra` (and `tauri-plugin-papyra-office` for office files).
5
+ *
6
+ * ```tsx
7
+ * import { TauriEngine, openTiff, openWorkbook } from '@build-qube/papyra-tauri';
8
+ * import { PdfEngineProvider } from '@/components/pdf-engine';
9
+ *
10
+ * <PdfEngineProvider engine={new TauriEngine()}>{app}</PdfEngineProvider>
11
+ * createFilePreview([tiffRenderer.with({ open: openTiff }), …]);
12
+ * ```
13
+ */
14
+ export { TauriEngine, type TauriEngineOptions, type TauriPageFormat, } from './engine.js';
15
+ export { TauriOfficeEngine } from './office.js';
16
+ export { openTiff } from './tiff.js';
17
+ export { openWorkbook } from './workbook.js';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EACL,WAAW,EACX,KAAK,kBAAkB,EACvB,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Tauri engines for papyra's viewer: PDFs, TIFFs, spreadsheets, and Word and
3
+ * PowerPoint parsed and rendered by papyra in the app's host process, through
4
+ * `tauri-plugin-papyra` (and `tauri-plugin-papyra-office` for office files).
5
+ *
6
+ * ```tsx
7
+ * import { TauriEngine, openTiff, openWorkbook } from '@build-qube/papyra-tauri';
8
+ * import { PdfEngineProvider } from '@/components/pdf-engine';
9
+ *
10
+ * <PdfEngineProvider engine={new TauriEngine()}>{app}</PdfEngineProvider>
11
+ * createFilePreview([tiffRenderer.with({ open: openTiff }), …]);
12
+ * ```
13
+ */
14
+ export { TauriEngine, } from './engine.js';
15
+ export { TauriOfficeEngine } from './office.js';
16
+ export { openTiff } from './tiff.js';
17
+ export { openWorkbook } from './workbook.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EACL,WAAW,GAGZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { type Availability, type BackendRenderOptions, type PageBitmap, type PagedBackend, PagedEngine, type PageSize, type PdfSource } from '@build-qube/papyra/core';
2
+ import type { OfficeDoc, OfficeKind } from '@build-qube/papyra/office';
3
+ import type { TauriEngineOptions } from './engine.js';
4
+ import { type TauriPageFormat } from './host.js';
5
+ /** The office plugin's answer to `open`. */
6
+ interface Opened {
7
+ id: number;
8
+ kind: OfficeKind;
9
+ sizes: [number, number][];
10
+ }
11
+ /** One office document held by the host, as a papyra backend. */
12
+ declare class TauriOfficeBackend implements PagedBackend {
13
+ #private;
14
+ readonly capabilities: import("@build-qube/papyra/core").Capabilities;
15
+ readonly abortable = false;
16
+ readonly concurrency = 4;
17
+ readonly kind: OfficeKind;
18
+ constructor(opened: Opened, format: TauriPageFormat);
19
+ get pageCount(): number;
20
+ pageSize(index: number): PageSize;
21
+ /** `annotations` does not apply: an office page has none to switch off. */
22
+ renderPage(index: number, { dpi }: BackendRenderOptions, signal?: AbortSignal): Promise<PageBitmap>;
23
+ close(): Promise<void>;
24
+ }
25
+ /**
26
+ * papyra's office engine — Word and PowerPoint, over WordCraft and DeckCraft — run
27
+ * in the Tauri app's host process through `tauri-plugin-papyra-office`, beside
28
+ * `tauri-plugin-papyra`. Allow `papyra:default` and `papyra-office:default`.
29
+ *
30
+ * Pass it where papyra's own `officeEngine` would go:
31
+ * `pptxRenderer.with({ engine })` and `docxPagedRenderer.with({ engine })`. Pages
32
+ * come over the `papyra://` protocol as a PDF's do, in the same `format`.
33
+ *
34
+ * The office crate is not on crates.io, because WordCraft and DeckCraft are not:
35
+ * an app takes it and `tauri-plugin-papyra` from the GitHub repository at one tag.
36
+ */
37
+ export declare class TauriOfficeEngine extends PagedEngine<OfficeDoc, TauriOfficeBackend> {
38
+ #private;
39
+ readonly id = "tauri-office";
40
+ constructor(options?: TauriEngineOptions);
41
+ /**
42
+ * Make a TrueType or OpenType font available to the host's Word and PowerPoint
43
+ * layout, for every document opened after this call. Resolves to how many faces
44
+ * were added. See papyra's `PapyraOfficeEngine.addFont` for why it matters.
45
+ */
46
+ addFont(source: PdfSource): Promise<number>;
47
+ availability(): Availability;
48
+ /** @internal */
49
+ protected load(source: PdfSource): Promise<TauriOfficeBackend>;
50
+ /** @internal */
51
+ protected handle(backend: TauriOfficeBackend): OfficeDoc;
52
+ }
53
+ export {};
54
+ //# sourceMappingURL=office.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"office.d.ts","sourceRoot":"","sources":["../src/office.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,WAAW,EACX,KAAK,QAAQ,EACb,KAAK,SAAS,EAGf,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAEvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,WAAW,CAAC;AAEnB,4CAA4C;AAC5C,UAAU,MAAM;IACd,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;CAC3B;AAED,iEAAiE;AACjE,cAAM,kBAAmB,YAAW,YAAY;;IAC9C,QAAQ,CAAC,YAAY,iDAAe;IAEpC,QAAQ,CAAC,SAAS,SAAS;IAC3B,QAAQ,CAAC,WAAW,KAAK;IACzB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAM1B,YAAY,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAMlD;IAED,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAIhC;IAED,2EAA2E;IAC3E,UAAU,CACR,KAAK,EAAE,MAAM,EACb,EAAE,GAAG,EAAE,EAAE,oBAAoB,EAC7B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAErB;IAED,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAErB;CACF;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAkB,SAAQ,WAAW,CAChD,SAAS,EACT,kBAAkB,CACnB;;IACC,QAAQ,CAAC,EAAE,kBAAkB;IAG7B,YAAY,OAAO,GAAE,kBAAuB,EAG3C;IAED;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAKhD;IAED,YAAY,IAAI,YAAY,CAE3B;IAED,gBAAgB;IAChB,UAAgB,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAMnE;IAED,gBAAgB;IAChB,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,kBAAkB,GAAG,SAAS,CAQvD;CACF"}
package/dist/office.js ADDED
@@ -0,0 +1,85 @@
1
+ import { PagedEngine, RENDER_ONLY, toBytes, } from '@build-qube/papyra/core';
2
+ import { invoke } from '@tauri-apps/api/core';
3
+ import { closeDocument, command, fetchPage, pagesOf, tauriAvailability, } from './host.js';
4
+ /** One office document held by the host, as a papyra backend. */
5
+ class TauriOfficeBackend {
6
+ capabilities = RENDER_ONLY;
7
+ // As TauriEngine: the render in Rust runs on whatever the fetch does.
8
+ abortable = false;
9
+ concurrency = 4;
10
+ kind;
11
+ #id;
12
+ #sizes;
13
+ #pages;
14
+ #format;
15
+ constructor(opened, format) {
16
+ this.#id = opened.id;
17
+ this.kind = opened.kind;
18
+ this.#sizes = opened.sizes.map(([width, height]) => ({ width, height }));
19
+ this.#pages = pagesOf(opened.id);
20
+ this.#format = format;
21
+ }
22
+ get pageCount() {
23
+ return this.#sizes.length;
24
+ }
25
+ pageSize(index) {
26
+ const size = this.#sizes[index];
27
+ if (!size)
28
+ throw new RangeError(`page ${index} is out of range`);
29
+ return size;
30
+ }
31
+ /** `annotations` does not apply: an office page has none to switch off. */
32
+ renderPage(index, { dpi }, signal) {
33
+ return fetchPage(`${this.#pages}${index}?dpi=${dpi}`, this.#format, signal);
34
+ }
35
+ close() {
36
+ return closeDocument(this.#id);
37
+ }
38
+ }
39
+ /**
40
+ * papyra's office engine — Word and PowerPoint, over WordCraft and DeckCraft — run
41
+ * in the Tauri app's host process through `tauri-plugin-papyra-office`, beside
42
+ * `tauri-plugin-papyra`. Allow `papyra:default` and `papyra-office:default`.
43
+ *
44
+ * Pass it where papyra's own `officeEngine` would go:
45
+ * `pptxRenderer.with({ engine })` and `docxPagedRenderer.with({ engine })`. Pages
46
+ * come over the `papyra://` protocol as a PDF's do, in the same `format`.
47
+ *
48
+ * The office crate is not on crates.io, because WordCraft and DeckCraft are not:
49
+ * an app takes it and `tauri-plugin-papyra` from the GitHub repository at one tag.
50
+ */
51
+ export class TauriOfficeEngine extends PagedEngine {
52
+ id = 'tauri-office';
53
+ #format;
54
+ constructor(options = {}) {
55
+ super();
56
+ this.#format = options.format ?? 'png';
57
+ }
58
+ /**
59
+ * Make a TrueType or OpenType font available to the host's Word and PowerPoint
60
+ * layout, for every document opened after this call. Resolves to how many faces
61
+ * were added. See papyra's `PapyraOfficeEngine.addFont` for why it matters.
62
+ */
63
+ async addFont(source) {
64
+ return invoke(command('add_font', 'papyra-office'), await toBytes(source));
65
+ }
66
+ availability() {
67
+ return tauriAvailability('tauri-plugin-papyra-office');
68
+ }
69
+ /** @internal */
70
+ async load(source) {
71
+ const opened = await invoke(command('open', 'papyra-office'), await toBytes(source));
72
+ return new TauriOfficeBackend(opened, this.#format);
73
+ }
74
+ /** @internal */
75
+ handle(backend) {
76
+ return {
77
+ engine: this.id,
78
+ kind: backend.kind,
79
+ pageCount: backend.pageCount,
80
+ pageSize: (index) => backend.pageSize(index),
81
+ capabilities: backend.capabilities,
82
+ };
83
+ }
84
+ }
85
+ //# sourceMappingURL=office.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"office.js","sourceRoot":"","sources":["../src/office.ts"],"names":[],"mappings":"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"}
package/dist/tiff.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { type PageBitmap, type PdfSource, TiffImage } from '@build-qube/papyra/core';
2
+ import type { TauriEngineOptions } from './engine.js';
3
+ /**
4
+ * papyra's `openTiff`, read and decoded in the Tauri app's host process through
5
+ * `tauri-plugin-papyra` with its `tiff` feature, and allowed by `papyra:tiff`.
6
+ *
7
+ * Resolves to papyra's own `TiffImage`, so `tiffRenderer.with({ open: openTiff })`
8
+ * shows it unchanged. Pages come over the `papyra://` protocol as a PDF's do, in
9
+ * the same `format` — PNG by default, which for a bilevel fax page is a fraction of
10
+ * its RGBA — so `renderPage` resolves to an `ImageBitmap` unless `format` is
11
+ * `'rgba'`. The file stays in the host until `close()`.
12
+ */
13
+ export declare function openTiff(source: PdfSource, options?: TauriEngineOptions): Promise<TiffImage<PageBitmap>>;
14
+ //# sourceMappingURL=tiff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tiff.d.ts","sourceRoot":"","sources":["../src/tiff.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,SAAS,EACd,SAAS,EAGV,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAkBtD;;;;;;;;;GASG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAkChC"}
package/dist/tiff.js ADDED
@@ -0,0 +1,43 @@
1
+ import { TiffImage, toBytes, } from '@build-qube/papyra/core';
2
+ import { invoke } from '@tauri-apps/api/core';
3
+ import { closeDocument, command, fetchPage, pagesOf, } from './host.js';
4
+ /** The widest page the protocol's `maxWidth` can name. */
5
+ const MAX_U32 = 0xffff_ffff;
6
+ /**
7
+ * papyra's `openTiff`, read and decoded in the Tauri app's host process through
8
+ * `tauri-plugin-papyra` with its `tiff` feature, and allowed by `papyra:tiff`.
9
+ *
10
+ * Resolves to papyra's own `TiffImage`, so `tiffRenderer.with({ open: openTiff })`
11
+ * shows it unchanged. Pages come over the `papyra://` protocol as a PDF's do, in
12
+ * the same `format` — PNG by default, which for a bilevel fax page is a fraction of
13
+ * its RGBA — so `renderPage` resolves to an `ImageBitmap` unless `format` is
14
+ * `'rgba'`. The file stays in the host until `close()`.
15
+ */
16
+ export async function openTiff(source, options = {}) {
17
+ const format = options.format ?? 'png';
18
+ const opened = await invoke(command('open_tiff'), await toBytes(source));
19
+ const pages = pagesOf(opened.id);
20
+ return new TiffImage({
21
+ pages: opened.pages,
22
+ renderPage(index, { maxPixels, maxWidth } = {}) {
23
+ // The host reads both as integers, so refuse here what it would answer with
24
+ // a bare 400: `1e+21` is not one, and a cap below one pixel is no page.
25
+ if (maxWidth !== undefined && !(maxWidth >= 1 && maxWidth <= MAX_U32)) {
26
+ return Promise.reject(new RangeError(`papyra: maxWidth ${maxWidth} is not a width in pixels`));
27
+ }
28
+ if (maxPixels !== undefined && !(maxPixels >= 1)) {
29
+ return Promise.reject(new RangeError(`papyra: maxPixels ${maxPixels} is under one pixel`));
30
+ }
31
+ const query = new URLSearchParams();
32
+ if (maxWidth !== undefined)
33
+ query.set('maxWidth', String(maxWidth));
34
+ if (maxPixels !== undefined) {
35
+ // Clamped as the host would, so a huge value is not written as `1e+21`.
36
+ query.set('maxPixels', String(Math.floor(Math.min(maxPixels, 1e8))));
37
+ }
38
+ return fetchPage(`${pages}${index}?${query}`, format);
39
+ },
40
+ close: () => closeDocument(opened.id),
41
+ });
42
+ }
43
+ //# sourceMappingURL=tiff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tiff.js","sourceRoot":"","sources":["../src/tiff.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,SAAS,EAET,OAAO,GACR,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,OAAO,EACL,aAAa,EACb,OAAO,EACP,SAAS,EACT,OAAO,GAER,MAAM,WAAW,CAAC;AAEnB,0DAA0D;AAC1D,MAAM,OAAO,GAAG,WAAW,CAAC;AAQ5B;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,MAAiB,EACjB,OAAO,GAAuB,EAAE;IAEhC,MAAM,MAAM,GAAoB,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC;IACxD,MAAM,MAAM,GAAG,MAAM,MAAM,CACzB,OAAO,CAAC,WAAW,CAAC,EACpB,MAAM,OAAO,CAAC,MAAM,CAAC,CACtB,CAAC;IACF,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACjC,OAAO,IAAI,SAAS,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE;YAC5C,4EAA4E;YAC5E,wEAAwE;YACxE,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAI,QAAQ,IAAI,OAAO,CAAC,EAAE,CAAC;gBACtE,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,UAAU,CACZ,oBAAoB,QAAQ,2BAA2B,CACxD,CACF,CAAC;YACJ,CAAC;YACD,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC;gBACjD,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,UAAU,CAAC,qBAAqB,SAAS,qBAAqB,CAAC,CACpE,CAAC;YACJ,CAAC;YACD,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;YACpC,IAAI,QAAQ,KAAK,SAAS;gBAAE,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YACpE,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,wEAAwE;gBACxE,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACvE,CAAC;YACD,OAAO,SAAS,CAAC,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,EAAE,EAAE,MAAM,CAAC,CAAC;QACxD,CAAC;QACD,KAAK,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;KACtC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type PdfSource, type Workbook, type WorkbookOptions } from '@build-qube/papyra/core';
2
+ /**
3
+ * papyra's `openWorkbook`, parsed in the Tauri app's host process through
4
+ * `tauri-plugin-papyra` with its `tables` feature, and allowed by `papyra:tables`.
5
+ *
6
+ * Resolves to papyra's own `Workbook`, so `spreadsheetRenderer.with({ open:
7
+ * openWorkbook })` and `csvRenderer`'s show it unchanged. A grid reads a sheet's
8
+ * cells synchronously, a window per frame, and IPC is not synchronous — so each
9
+ * sheet's cells come over **whole**, in one binary call when the sheet is first
10
+ * read, and windows are cut from that copy. That is about 19 bytes a cell plus its
11
+ * text, held in the host and here, over the sheet's whole rectangle — so the host
12
+ * cuts a sheet to its first rows, marked `truncated`, past a million cells (~19 MB)
13
+ * or past sixteen times the cells it really holds. A lower `maxCells` lowers the
14
+ * first.
15
+ *
16
+ * The workbook stays in the host until `close()`.
17
+ */
18
+ export declare function openWorkbook(source: PdfSource, options?: WorkbookOptions): Promise<Workbook>;
19
+ //# 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,SAAS,EAEd,KAAK,QAAQ,EACb,KAAK,eAAe,EAErB,MAAM,yBAAyB,CAAC;AAuHjC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,QAAQ,CAAC,CA4CnB"}
@@ -0,0 +1,139 @@
1
+ import { openWorkbookWith, } from '@build-qube/papyra/core';
2
+ import { invoke } from '@tauri-apps/api/core';
3
+ import { closeDocument, command } from './host.js';
4
+ /**
5
+ * A window as `pack` in the plugin's `tables.rs` lays it out: four u32s, then each
6
+ * array aligned for a view straight over the buffer, then the text as UTF-8.
7
+ */
8
+ function unpack(raw) {
9
+ // An ArrayBuffer from the binary IPC; a number[] if Tauri fell back to
10
+ // postMessage. A view over the first copies nothing, and starts at offset 0 — the
11
+ // typed views below are aligned to that.
12
+ const { buffer } = new Uint8Array(raw);
13
+ const [rowStart = 0, colStart = 0, rows = 0, cols = 0] = new Uint32Array(buffer, 0, 4);
14
+ const n = rows * cols;
15
+ let at = 16;
16
+ const take = (make, bytes) => {
17
+ const out = make(at);
18
+ at += bytes;
19
+ return out;
20
+ };
21
+ const kinds = take((a) => new Uint8Array(buffer, a, n), n);
22
+ at = Math.ceil(at / 8) * 8;
23
+ const numbers = take((a) => new Float64Array(buffer, a, n), n * 8);
24
+ const colors = take((a) => new Uint32Array(buffer, a, n), n * 4);
25
+ const offsets = take((a) => new Uint32Array(buffer, a, n + 1), (n + 1) * 4);
26
+ const styles = take((a) => new Uint16Array(buffer, a, n), n * 2);
27
+ const text = new TextDecoder().decode(new Uint8Array(buffer, at));
28
+ return {
29
+ rowStart,
30
+ colStart,
31
+ rows,
32
+ cols,
33
+ kinds,
34
+ numbers,
35
+ text,
36
+ offsets,
37
+ styles,
38
+ colors,
39
+ };
40
+ }
41
+ /**
42
+ * `[rowStart, rowEnd) x [colStart, colEnd)` of a window holding the whole sheet,
43
+ * clamped to it: what papyra's `Sheet.window` asks the addon for, answered here
44
+ * without a round trip.
45
+ */
46
+ function slice(all, rowStart, rowEnd, colStart, colEnd) {
47
+ const r1 = Math.min(rowEnd, all.rows);
48
+ const c1 = Math.min(colEnd, all.cols);
49
+ const r0 = Math.min(rowStart, r1);
50
+ const c0 = Math.min(colStart, c1);
51
+ const rows = r1 - r0;
52
+ const cols = c1 - c0;
53
+ const n = rows * cols;
54
+ const out = {
55
+ rowStart: r0,
56
+ colStart: c0,
57
+ rows,
58
+ cols,
59
+ kinds: new Uint8Array(n),
60
+ numbers: new Float64Array(n),
61
+ styles: new Uint16Array(n),
62
+ colors: new Uint32Array(n),
63
+ offsets: new Uint32Array(n + 1),
64
+ text: '',
65
+ };
66
+ const parts = [];
67
+ let length = 0;
68
+ for (let r = 0; r < rows; r++) {
69
+ const from = (r0 + r) * all.cols + c0;
70
+ const to = from + cols;
71
+ const into = r * cols;
72
+ out.kinds.set(all.kinds.subarray(from, to), into);
73
+ out.numbers.set(all.numbers.subarray(from, to), into);
74
+ out.styles.set(all.styles.subarray(from, to), into);
75
+ out.colors.set(all.colors.subarray(from, to), into);
76
+ const base = all.offsets[from] ?? 0;
77
+ for (let c = 0; c < cols; c++) {
78
+ out.offsets[into + c] = length + (all.offsets[from + c] ?? 0) - base;
79
+ }
80
+ const end = all.offsets[to] ?? base;
81
+ parts.push(all.text.slice(base, end));
82
+ length += end - base;
83
+ }
84
+ out.offsets[n] = length;
85
+ out.text = parts.join('');
86
+ return out;
87
+ }
88
+ /**
89
+ * papyra's `openWorkbook`, parsed in the Tauri app's host process through
90
+ * `tauri-plugin-papyra` with its `tables` feature, and allowed by `papyra:tables`.
91
+ *
92
+ * Resolves to papyra's own `Workbook`, so `spreadsheetRenderer.with({ open:
93
+ * openWorkbook })` and `csvRenderer`'s show it unchanged. A grid reads a sheet's
94
+ * cells synchronously, a window per frame, and IPC is not synchronous — so each
95
+ * sheet's cells come over **whole**, in one binary call when the sheet is first
96
+ * read, and windows are cut from that copy. That is about 19 bytes a cell plus its
97
+ * text, held in the host and here, over the sheet's whole rectangle — so the host
98
+ * cuts a sheet to its first rows, marked `truncated`, past a million cells (~19 MB)
99
+ * or past sixteen times the cells it really holds. A lower `maxCells` lowers the
100
+ * first.
101
+ *
102
+ * The workbook stays in the host until `close()`.
103
+ */
104
+ export function openWorkbook(source, options = {}) {
105
+ return openWorkbookWith(async (bytes, options) => {
106
+ const { id, ...book } = await invoke(command('open_workbook'), bytes, {
107
+ headers: {
108
+ // JSON in a header: ASCII, so percent-encoded like the password.
109
+ 'x-papyra-options': encodeURIComponent(JSON.stringify(options)),
110
+ },
111
+ });
112
+ return {
113
+ ...book,
114
+ async sheet(index) {
115
+ const meta = await invoke(command('sheet'), { id, index });
116
+ const all = unpack(await invoke(command('window'), {
117
+ id,
118
+ sheet: index,
119
+ rowStart: 0,
120
+ rowEnd: meta.rows,
121
+ colStart: 0,
122
+ colEnd: meta.cols,
123
+ }));
124
+ return {
125
+ ...meta,
126
+ merges: Uint32Array.from(meta.merges),
127
+ layout: meta.layout && {
128
+ ...meta.layout,
129
+ cols: Float64Array.from(meta.layout.cols),
130
+ rows: Float64Array.from(meta.layout.rows),
131
+ },
132
+ window: (r0, r1, c0, c1) => slice(all, r0, r1, c0, c1),
133
+ };
134
+ },
135
+ close: () => closeDocument(id),
136
+ };
137
+ }, source, options);
138
+ }
139
+ //# 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,49 @@
1
1
  {
2
2
  "name": "@build-qube/papyra-tauri",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.6.0",
4
+ "description": "A Tauri engine for papyra's viewer: PDFs parsed and rendered in the app's host process by tauri-plugin-papyra",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/BuildQube/papyra.git",
9
+ "directory": "packages/tauri"
10
+ },
11
+ "keywords": [
12
+ "pdf",
13
+ "tauri",
14
+ "papyra",
15
+ "viewer",
16
+ "mobile"
17
+ ],
18
+ "type": "module",
19
+ "main": "./dist/index.js",
20
+ "types": "./dist/index.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "default": "./dist/index.js"
25
+ }
26
+ },
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "publishConfig": {
31
+ "registry": "https://registry.npmjs.org/",
32
+ "access": "public"
33
+ },
34
+ "scripts": {
35
+ "build": "tsc -p tsconfig.json",
36
+ "typecheck": "tsc -p tsconfig.json --noEmit",
37
+ "clean": "rm -rf dist *.tsbuildinfo",
38
+ "test:integration": "bun test test/integration"
39
+ },
40
+ "peerDependencies": {
41
+ "@build-qube/papyra": "^0.6.0",
42
+ "@tauri-apps/api": "^2.0.0"
43
+ },
44
+ "devDependencies": {
45
+ "@build-qube/papyra": "0.6.0",
46
+ "@tauri-apps/api": "^2.9.0",
47
+ "typescript": "^7.0.2"
48
+ }
49
+ }