@build-qube/papyra 0.0.4 → 0.2.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 +129 -0
- package/dist/cache.d.ts +3 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js.map +1 -1
- package/dist/document.d.ts +251 -3
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +444 -16
- package/dist/document.js.map +1 -1
- package/dist/encode.d.ts +49 -0
- package/dist/encode.d.ts.map +1 -0
- package/dist/encode.js +71 -0
- package/dist/encode.js.map +1 -0
- package/dist/encoded.d.ts +91 -0
- package/dist/encoded.d.ts.map +1 -0
- package/dist/encoded.js +84 -0
- package/dist/encoded.js.map +1 -0
- package/dist/errors.d.ts +45 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +69 -0
- package/dist/errors.js.map +1 -0
- package/dist/fingerprint.d.ts +18 -0
- package/dist/fingerprint.d.ts.map +1 -0
- package/dist/fingerprint.js +48 -0
- package/dist/fingerprint.js.map +1 -0
- package/dist/index.d.ts +12 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/links.d.ts +53 -0
- package/dist/links.d.ts.map +1 -0
- package/dist/links.js +26 -0
- package/dist/links.js.map +1 -0
- package/dist/outline.d.ts +72 -0
- package/dist/outline.d.ts.map +1 -0
- package/dist/outline.js +73 -0
- package/dist/outline.js.map +1 -0
- package/dist/runtime.d.ts +8 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +2 -0
- package/dist/runtime.js.map +1 -1
- package/dist/scheduler.d.ts +20 -2
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +15 -0
- package/dist/scheduler.js.map +1 -1
- package/dist/search.d.ts +50 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +151 -0
- package/dist/search.js.map +1 -0
- package/dist/text.d.ts +113 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +84 -0
- package/dist/text.js.map +1 -0
- package/dist/types.d.ts +96 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -3
package/dist/encode.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { encodeBitmap, } from '@build-qube/papyra-native';
|
|
2
|
+
import { encodedImage, } from './encoded.js';
|
|
3
|
+
export { encodedImage, mimeType, svgPage } from './encoded.js';
|
|
4
|
+
/**
|
|
5
|
+
* Encode a page you already hold — a cache hit, or one you have just painted.
|
|
6
|
+
*
|
|
7
|
+
* This copies the pixels back into Rust, because a `Uint8Array` points at the JS heap
|
|
8
|
+
* and cannot be held across the worker-thread boundary. When you do not also need the
|
|
9
|
+
* raw pixels, `doc.renderImage()` skips the round trip entirely.
|
|
10
|
+
*/
|
|
11
|
+
export async function encode(page, options = {}) {
|
|
12
|
+
const format = options.format ?? 'webp';
|
|
13
|
+
const bytes = await encodeBitmap(page.data, page.width, page.height, page.stride, format, options.quality, options.signal);
|
|
14
|
+
return encodedImage(bytes, format);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A page held in Rust, encoded on demand.
|
|
18
|
+
*
|
|
19
|
+
* The pixels never cross into JS. A 42x30in drawing at 150 DPI is 6.5 MB raw and a
|
|
20
|
+
* fraction of that encoded, so for export the raw buffer is pure overhead. There is no
|
|
21
|
+
* accessor for it on purpose: use `renderPage` when you want pixels, this when you
|
|
22
|
+
* want a file.
|
|
23
|
+
*/
|
|
24
|
+
export class PageImage {
|
|
25
|
+
#inner;
|
|
26
|
+
constructor(inner) {
|
|
27
|
+
this.#inner = inner;
|
|
28
|
+
}
|
|
29
|
+
/** Output width in pixels. */
|
|
30
|
+
get width() {
|
|
31
|
+
return this.#inner.width;
|
|
32
|
+
}
|
|
33
|
+
/** Output height in pixels. */
|
|
34
|
+
get height() {
|
|
35
|
+
return this.#inner.height;
|
|
36
|
+
}
|
|
37
|
+
/** Size of the *raw* bitmap still held in Rust. Encoded output is much smaller. */
|
|
38
|
+
get byteLength() {
|
|
39
|
+
return this.#inner.byteLength;
|
|
40
|
+
}
|
|
41
|
+
/** Encode to {@link EncodeOptions.format}, defaulting to WebP. */
|
|
42
|
+
async encode(options = {}) {
|
|
43
|
+
const format = options.format ?? 'webp';
|
|
44
|
+
const bytes = await this.#inner.encode(format, options.quality, options.signal);
|
|
45
|
+
return encodedImage(bytes, format);
|
|
46
|
+
}
|
|
47
|
+
/** Lossless VP8L. The default, and ~3x smaller than PNG on page content. */
|
|
48
|
+
toWebp(options = {}) {
|
|
49
|
+
return this.encode({ ...options, format: 'webp' });
|
|
50
|
+
}
|
|
51
|
+
/** Lossless PNG. Reach for it when the consumer cannot be trusted to read WebP. */
|
|
52
|
+
toPng(options = {}) {
|
|
53
|
+
return this.encode({ ...options, format: 'png' });
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Lossy JPEG at `quality` (1-100, default 80).
|
|
57
|
+
*
|
|
58
|
+
* No alpha: transparent pixels composite onto white, matching how pages render.
|
|
59
|
+
*/
|
|
60
|
+
toJpeg(quality, options = {}) {
|
|
61
|
+
return this.encode({ ...options, format: 'jpeg', quality });
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Encode straight to a `data:` URL. Nothing but the finished string crosses the
|
|
65
|
+
* boundary — not the pixels, not the encoded bytes.
|
|
66
|
+
*/
|
|
67
|
+
toDataUrl(options = {}) {
|
|
68
|
+
return this.#inner.toDataUrl((options.format ?? 'webp'), options.quality, options.signal);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=encode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encode.js","sourceRoot":"","sources":["../src/encode.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,GAGb,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAGL,YAAY,GACb,MAAM,cAAc,CAAC;AAUtB,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE/D;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,IAAkB,EAClB,OAAO,GAAkB,EAAE;IAE3B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC;IACxC,MAAM,KAAK,GAAG,MAAM,YAAY,CAC9B,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,MAAM,EACX,MAAsB,EACtB,OAAO,CAAC,OAAO,EACf,OAAO,CAAC,MAAM,CACf,CAAC;IACF,OAAO,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,SAAS;IACX,MAAM,CAAkB;IAEjC,YAAY,KAAsB;QAChC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,8BAA8B;IAC9B,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;IAC3B,CAAC;IAED,+BAA+B;IAC/B,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,mFAAmF;IACnF,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;IAChC,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,MAAM,CAAC,OAAO,GAAkB,EAAE;QACtC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC;QACxC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CACpC,MAAsB,EACtB,OAAO,CAAC,OAAO,EACf,OAAO,CAAC,MAAM,CACf,CAAC;QACF,OAAO,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,4EAA4E;IAC5E,MAAM,CAAC,OAAO,GAA8C,EAAE;QAC5D,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,mFAAmF;IACnF,KAAK,CAAC,OAAO,GAA8C,EAAE;QAC3D,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,OAAgB,EAAE,OAAO,GAAkC,EAAE;QAClE,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED;;;OAGG;IACH,SAAS,CAAC,OAAO,GAAkB,EAAE;QACnC,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAC1B,CAAC,OAAO,CAAC,MAAM,IAAI,MAAM,CAAiB,EAC1C,OAAO,CAAC,OAAO,EACf,OAAO,CAAC,MAAM,CACf,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The parts of encoding that touch no native code.
|
|
3
|
+
*
|
|
4
|
+
* Split from `encode.ts` because CI's `unit-test` job runs with no Rust toolchain and
|
|
5
|
+
* no build: anything `test/unit` imports must not pull in the addon, and `encode.ts`
|
|
6
|
+
* imports `encodeBitmap` as a value. See CLAUDE.md.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Containers papyra can rasterise a page into. All three encoders are pure Rust — that
|
|
10
|
+
* is what keeps the browser build free of a C toolchain — so there is no lossy WebP and
|
|
11
|
+
* no AVIF.
|
|
12
|
+
*
|
|
13
|
+
* - `webp` is lossless VP8L, and the default: on page content (line art, text, flat
|
|
14
|
+
* fills) it is ~3x smaller than PNG for roughly the same encode time.
|
|
15
|
+
* - `png` is the universal fallback.
|
|
16
|
+
* - `jpeg` is the only lossy option and the only one with a `quality` knob. It has no
|
|
17
|
+
* alpha channel; transparent pixels are composited onto white, matching how pages
|
|
18
|
+
* are rendered.
|
|
19
|
+
*/
|
|
20
|
+
export type RasterFormat = 'webp' | 'png' | 'jpeg';
|
|
21
|
+
/**
|
|
22
|
+
* Every container papyra can write, {@link RasterFormat} plus `svg`.
|
|
23
|
+
*
|
|
24
|
+
* `svg` is separate from the others everywhere it matters: it comes off
|
|
25
|
+
* `Document.renderSvg`, not off pixels, so it takes no DPI and no quality — which is
|
|
26
|
+
* why {@link EncodeOptions.format} accepts only a {@link RasterFormat}.
|
|
27
|
+
*/
|
|
28
|
+
export type EncodedFormat = RasterFormat | 'svg';
|
|
29
|
+
/** MIME type for an encoded format, e.g. `'webp'` -> `'image/webp'`. */
|
|
30
|
+
export declare function mimeType(format: EncodedFormat): string;
|
|
31
|
+
/** Which container to write, and how hard to squeeze. */
|
|
32
|
+
export interface EncodeOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Defaults to `'webp'`. Rasters only — SVG is not an encoding of a bitmap, so it
|
|
35
|
+
* comes from `Document.renderSvg` instead.
|
|
36
|
+
*/
|
|
37
|
+
format?: RasterFormat;
|
|
38
|
+
/** JPEG only, 1-100. Defaults to 80. Ignored by the lossless formats. */
|
|
39
|
+
quality?: number;
|
|
40
|
+
/** Abort a request that has not started yet. */
|
|
41
|
+
signal?: AbortSignal;
|
|
42
|
+
}
|
|
43
|
+
/** Encoded bytes, plus the three ways you are likely to want to hand them to a browser. */
|
|
44
|
+
export interface EncodedImage {
|
|
45
|
+
/** The encoded file, ready to write to disk or upload. */
|
|
46
|
+
readonly bytes: Uint8Array;
|
|
47
|
+
/** The container {@link bytes} is written in. */
|
|
48
|
+
readonly format: EncodedFormat;
|
|
49
|
+
/** MIME type for {@link format}, so a caller never has to map it back. */
|
|
50
|
+
readonly mime: string;
|
|
51
|
+
/** Wrap as a `Blob`, ready for `URL.createObjectURL` or an upload. */
|
|
52
|
+
toBlob(): Blob;
|
|
53
|
+
/**
|
|
54
|
+
* An object URL for `<img src>`. Prefer this over {@link toDataUrl} in a browser:
|
|
55
|
+
* no base64 inflation, no multi-megabyte string on the heap, and the decoder reads
|
|
56
|
+
* straight from the blob.
|
|
57
|
+
*
|
|
58
|
+
* The caller owns the URL — `URL.revokeObjectURL` it when the image is gone.
|
|
59
|
+
*/
|
|
60
|
+
toBlobUrl(): string;
|
|
61
|
+
/**
|
|
62
|
+
* A `data:` URL. For an `<img src>` this is the worse option; reach for it when the
|
|
63
|
+
* bytes must be embedded — CSS, serialised output, server-rendered HTML.
|
|
64
|
+
*/
|
|
65
|
+
toDataUrl(): string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* One page as SVG. An {@link EncodedImage} whose markup is also readable as a string,
|
|
69
|
+
* because the usual thing to do with an SVG is inline it rather than hand a browser
|
|
70
|
+
* a URL.
|
|
71
|
+
*/
|
|
72
|
+
export interface SvgPage extends EncodedImage {
|
|
73
|
+
readonly format: 'svg';
|
|
74
|
+
/** The SVG document itself, a single `<svg>` element sized in PDF points. */
|
|
75
|
+
readonly markup: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Wrap SVG markup as an {@link SvgPage}.
|
|
79
|
+
*
|
|
80
|
+
* `bytes` is encoded on first access: inlining the markup is the common case, and a
|
|
81
|
+
* page of dense line art is megabytes of text that no one asked to have copied.
|
|
82
|
+
*/
|
|
83
|
+
export declare function svgPage(markup: string): SvgPage;
|
|
84
|
+
/**
|
|
85
|
+
* Wrap already-encoded bytes as an {@link EncodedImage}.
|
|
86
|
+
*
|
|
87
|
+
* Exported for callers holding bytes from somewhere else — a cache, a fetch — that
|
|
88
|
+
* want the same `toBlob`/`toBlobUrl`/`toDataUrl` conveniences.
|
|
89
|
+
*/
|
|
90
|
+
export declare function encodedImage(bytes: Uint8Array, format: EncodedFormat): EncodedImage;
|
|
91
|
+
//# sourceMappingURL=encoded.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encoded.d.ts","sourceRoot":"","sources":["../src/encoded.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,KAAK,CAAC;AASjD,wEAAwE;AACxE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAEtD;AAED,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,2FAA2F;AAC3F,MAAM,WAAW,YAAY;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,MAAM,IAAI,IAAI,CAAC;IACf;;;;;;OAMG;IACH,SAAS,IAAI,MAAM,CAAC;IACpB;;;OAGG;IACH,SAAS,IAAI,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,OAAQ,SAAQ,YAAY;IAC3C,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;IACvB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAqB/C;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,aAAa,GACpB,YAAY,CAYd"}
|
package/dist/encoded.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const MIME = {
|
|
2
|
+
webp: 'image/webp',
|
|
3
|
+
png: 'image/png',
|
|
4
|
+
jpeg: 'image/jpeg',
|
|
5
|
+
svg: 'image/svg+xml',
|
|
6
|
+
};
|
|
7
|
+
/** MIME type for an encoded format, e.g. `'webp'` -> `'image/webp'`. */
|
|
8
|
+
export function mimeType(format) {
|
|
9
|
+
return MIME[format];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Wrap SVG markup as an {@link SvgPage}.
|
|
13
|
+
*
|
|
14
|
+
* `bytes` is encoded on first access: inlining the markup is the common case, and a
|
|
15
|
+
* page of dense line art is megabytes of text that no one asked to have copied.
|
|
16
|
+
*/
|
|
17
|
+
export function svgPage(markup) {
|
|
18
|
+
const mime = MIME.svg;
|
|
19
|
+
let encoded;
|
|
20
|
+
const bytes = () => {
|
|
21
|
+
encoded ??= new TextEncoder().encode(markup);
|
|
22
|
+
return encoded;
|
|
23
|
+
};
|
|
24
|
+
return {
|
|
25
|
+
markup,
|
|
26
|
+
format: 'svg',
|
|
27
|
+
mime,
|
|
28
|
+
get bytes() {
|
|
29
|
+
return bytes();
|
|
30
|
+
},
|
|
31
|
+
toBlob: () => new Blob([markup], { type: mime }),
|
|
32
|
+
toBlobUrl() {
|
|
33
|
+
return URL.createObjectURL(this.toBlob());
|
|
34
|
+
},
|
|
35
|
+
toDataUrl: () => `data:${mime};base64,${base64(bytes())}`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Wrap already-encoded bytes as an {@link EncodedImage}.
|
|
40
|
+
*
|
|
41
|
+
* Exported for callers holding bytes from somewhere else — a cache, a fetch — that
|
|
42
|
+
* want the same `toBlob`/`toBlobUrl`/`toDataUrl` conveniences.
|
|
43
|
+
*/
|
|
44
|
+
export function encodedImage(bytes, format) {
|
|
45
|
+
const mime = MIME[format];
|
|
46
|
+
return {
|
|
47
|
+
bytes,
|
|
48
|
+
format,
|
|
49
|
+
mime,
|
|
50
|
+
toBlob: () => new Blob([detach(bytes)], { type: mime }),
|
|
51
|
+
toBlobUrl() {
|
|
52
|
+
return URL.createObjectURL(this.toBlob());
|
|
53
|
+
},
|
|
54
|
+
toDataUrl: () => `data:${mime};base64,${base64(bytes)}`,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Copy into a buffer `Blob` will accept.
|
|
59
|
+
*
|
|
60
|
+
* On the wasm build these bytes live in the module's shared linear memory, and
|
|
61
|
+
* `SharedArrayBuffer`-backed views are not valid `BlobPart`s. Copying unconditionally
|
|
62
|
+
* keeps both runtimes on one path; encoded output is small enough that it does not
|
|
63
|
+
* matter, which is exactly why `toImageData` cannot do the same trick cheaply.
|
|
64
|
+
*/
|
|
65
|
+
function detach(bytes) {
|
|
66
|
+
const out = new Uint8Array(bytes.byteLength);
|
|
67
|
+
out.set(bytes);
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
function base64(bytes) {
|
|
71
|
+
const buf = globalThis.Buffer;
|
|
72
|
+
// Node's native base64 beats anything expressible in JS by a wide margin.
|
|
73
|
+
if (buf)
|
|
74
|
+
return buf.from(bytes).toString('base64');
|
|
75
|
+
// btoa wants a binary string, and spreading into fromCharCode overflows the stack
|
|
76
|
+
// somewhere north of 100k arguments. Chunk it.
|
|
77
|
+
let binary = '';
|
|
78
|
+
const chunk = 0x8000;
|
|
79
|
+
for (let i = 0; i < bytes.length; i += chunk) {
|
|
80
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + chunk));
|
|
81
|
+
}
|
|
82
|
+
return btoa(binary);
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=encoded.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encoded.js","sourceRoot":"","sources":["../src/encoded.ts"],"names":[],"mappings":"AA8BA,MAAM,IAAI,GAAkC;IAC1C,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,eAAe;CACrB,CAAC;AAEF,wEAAwE;AACxE,MAAM,UAAU,QAAQ,CAAC,MAAqB;IAC5C,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAmDD;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,MAAc;IACpC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC;IACtB,IAAI,OAA+B,CAAC;IACpC,MAAM,KAAK,GAAG,GAAe,EAAE;QAC7B,OAAO,KAAK,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7C,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IAEF,OAAO;QACL,MAAM;QACN,MAAM,EAAE,KAAK;QACb,IAAI;QACJ,IAAI,KAAK;YACP,OAAO,KAAK,EAAE,CAAC;QACjB,CAAC;QACD,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAChD,SAAS;YACP,OAAO,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5C,CAAC;QACD,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,IAAI,WAAW,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE;KAC1D,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAiB,EACjB,MAAqB;IAErB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,OAAO;QACL,KAAK;QACL,MAAM;QACN,IAAI;QACJ,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACvD,SAAS;YACP,OAAO,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5C,CAAC;QACD,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,IAAI,WAAW,MAAM,CAAC,KAAK,CAAC,EAAE;KACxD,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,MAAM,CAAC,KAAiB;IAC/B,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC7C,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACf,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,MAAM,CAAC,KAAiB;IAC/B,MAAM,GAAG,GACP,UAGD,CAAC,MAAM,CAAC;IACT,0EAA0E;IAC1E,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEnD,kFAAkF;IAClF,+CAA+C;IAC/C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,MAAM,KAAK,GAAG,MAAM,CAAC;IACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;QAC7C,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A document that could not be opened because of its password.
|
|
3
|
+
*
|
|
4
|
+
* The base of both password failures, because a viewer handles them in one place: a
|
|
5
|
+
* dialog that either asks for the first time or says the last answer was wrong.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* try {
|
|
10
|
+
* doc = await open(file, { password });
|
|
11
|
+
* } catch (e) {
|
|
12
|
+
* if (e instanceof PasswordError) showPasswordDialog({ retry: e.retry });
|
|
13
|
+
* else throw e;
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare class PasswordError extends Error {
|
|
18
|
+
/**
|
|
19
|
+
* A password was already tried and rejected.
|
|
20
|
+
*
|
|
21
|
+
* `false` the first time, so a dialog can open without an error on it.
|
|
22
|
+
*/
|
|
23
|
+
readonly retry: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** The document is encrypted and {@link OpenOptions.password} was not supplied. */
|
|
26
|
+
export declare class PasswordRequiredError extends PasswordError {
|
|
27
|
+
/** Always `'PasswordRequiredError'`. */
|
|
28
|
+
readonly name = "PasswordRequiredError";
|
|
29
|
+
readonly retry = false;
|
|
30
|
+
constructor(message?: string);
|
|
31
|
+
}
|
|
32
|
+
/** A password was supplied and it did not open the document. */
|
|
33
|
+
export declare class IncorrectPasswordError extends PasswordError {
|
|
34
|
+
/** Always `'IncorrectPasswordError'`. */
|
|
35
|
+
readonly name = "IncorrectPasswordError";
|
|
36
|
+
readonly retry = true;
|
|
37
|
+
constructor(message?: string);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Rethrow a load failure as itself, or as the typed error it was tagged as.
|
|
41
|
+
*
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
export declare function rethrowLoadError(error: unknown): never;
|
|
45
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +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"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tags the bindings put in front of a load failure's message.
|
|
3
|
+
*
|
|
4
|
+
* napi-rs gives every error it throws the same `code`, so the message is the only
|
|
5
|
+
* channel a typed failure can travel through. These are stripped before the error
|
|
6
|
+
* reaches a caller — keep them in step with `TAG_PASSWORD_REQUIRED` and
|
|
7
|
+
* `TAG_INCORRECT_PASSWORD` in `packages/bindings/src/lib.rs`.
|
|
8
|
+
*/
|
|
9
|
+
const TAGS = {
|
|
10
|
+
'papyra/password-required': (message) => new PasswordRequiredError(message),
|
|
11
|
+
'papyra/incorrect-password': (message) => new IncorrectPasswordError(message),
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* A document that could not be opened because of its password.
|
|
15
|
+
*
|
|
16
|
+
* The base of both password failures, because a viewer handles them in one place: a
|
|
17
|
+
* dialog that either asks for the first time or says the last answer was wrong.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* try {
|
|
22
|
+
* doc = await open(file, { password });
|
|
23
|
+
* } catch (e) {
|
|
24
|
+
* if (e instanceof PasswordError) showPasswordDialog({ retry: e.retry });
|
|
25
|
+
* else throw e;
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export class PasswordError extends Error {
|
|
30
|
+
/**
|
|
31
|
+
* A password was already tried and rejected.
|
|
32
|
+
*
|
|
33
|
+
* `false` the first time, so a dialog can open without an error on it.
|
|
34
|
+
*/
|
|
35
|
+
retry = false;
|
|
36
|
+
}
|
|
37
|
+
/** The document is encrypted and {@link OpenOptions.password} was not supplied. */
|
|
38
|
+
export class PasswordRequiredError extends PasswordError {
|
|
39
|
+
/** Always `'PasswordRequiredError'`. */
|
|
40
|
+
name = 'PasswordRequiredError';
|
|
41
|
+
retry = false;
|
|
42
|
+
constructor(message = 'this PDF is password-protected') {
|
|
43
|
+
super(message);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** A password was supplied and it did not open the document. */
|
|
47
|
+
export class IncorrectPasswordError extends PasswordError {
|
|
48
|
+
/** Always `'IncorrectPasswordError'`. */
|
|
49
|
+
name = 'IncorrectPasswordError';
|
|
50
|
+
retry = true;
|
|
51
|
+
constructor(message = 'the supplied password is incorrect') {
|
|
52
|
+
super(message);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Rethrow a load failure as itself, or as the typed error it was tagged as.
|
|
57
|
+
*
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
export function rethrowLoadError(error) {
|
|
61
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
62
|
+
for (const [tag, build] of Object.entries(TAGS)) {
|
|
63
|
+
if (message.startsWith(tag)) {
|
|
64
|
+
throw build(message.slice(tag.length).trim());
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A stable identifier for a document's bytes.
|
|
3
|
+
*
|
|
4
|
+
* Sixteen hex characters, derived from the head, the tail and the length of the file.
|
|
5
|
+
* Meant as a key for whatever a viewer remembers per document — the page it was left
|
|
6
|
+
* on, the zoom, a set of highlights.
|
|
7
|
+
*
|
|
8
|
+
* **This is a content hash, not the PDF's `/ID`.** hayro exposes no trailer accessor,
|
|
9
|
+
* so the identifier the spec defines is out of reach; the practical difference is
|
|
10
|
+
* that a document saved with an incremental update keeps its `/ID` and gets a new
|
|
11
|
+
* fingerprint here. For "is this the same file I had open", which is what the value
|
|
12
|
+
* is for, hashing the bytes is the stronger answer anyway — it also distinguishes two
|
|
13
|
+
* documents that were copied from one another and kept the same `/ID`.
|
|
14
|
+
*
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export declare function fingerprint(bytes: Uint8Array): string;
|
|
18
|
+
//# sourceMappingURL=fingerprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAarD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How many bytes to read from each end of the file.
|
|
3
|
+
*
|
|
4
|
+
* The tail is the load-bearing half: it holds the cross-reference table and the
|
|
5
|
+
* trailer, and the trailer is where `/ID` lives. So although this never parses the
|
|
6
|
+
* document, a file that carries an `/ID` still contributes it to the hash.
|
|
7
|
+
*/
|
|
8
|
+
const SAMPLE = 4096;
|
|
9
|
+
/** FNV-1a, 32-bit. Two runs at different offsets give the 64 bits below. */
|
|
10
|
+
function fnv1a(bytes, seed) {
|
|
11
|
+
let hash = seed;
|
|
12
|
+
for (const byte of bytes) {
|
|
13
|
+
hash ^= byte;
|
|
14
|
+
// The FNV prime, 16777619, as shifts — `Math.imul` keeps this in 32 bits where
|
|
15
|
+
// `*` would silently go through a double and lose the low bits.
|
|
16
|
+
hash = Math.imul(hash, 0x01000193);
|
|
17
|
+
}
|
|
18
|
+
return hash >>> 0;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A stable identifier for a document's bytes.
|
|
22
|
+
*
|
|
23
|
+
* Sixteen hex characters, derived from the head, the tail and the length of the file.
|
|
24
|
+
* Meant as a key for whatever a viewer remembers per document — the page it was left
|
|
25
|
+
* on, the zoom, a set of highlights.
|
|
26
|
+
*
|
|
27
|
+
* **This is a content hash, not the PDF's `/ID`.** hayro exposes no trailer accessor,
|
|
28
|
+
* so the identifier the spec defines is out of reach; the practical difference is
|
|
29
|
+
* that a document saved with an incremental update keeps its `/ID` and gets a new
|
|
30
|
+
* fingerprint here. For "is this the same file I had open", which is what the value
|
|
31
|
+
* is for, hashing the bytes is the stronger answer anyway — it also distinguishes two
|
|
32
|
+
* documents that were copied from one another and kept the same `/ID`.
|
|
33
|
+
*
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
export function fingerprint(bytes) {
|
|
37
|
+
const head = bytes.subarray(0, SAMPLE);
|
|
38
|
+
// `subarray` clamps, so a file shorter than one sample simply hashes twice rather
|
|
39
|
+
// than needing a branch.
|
|
40
|
+
const tail = bytes.subarray(Math.max(0, bytes.length - SAMPLE));
|
|
41
|
+
const low = fnv1a(tail, fnv1a(head, 0x811c9dc5));
|
|
42
|
+
// A second pass from a different seed, so the two halves of the output are not the
|
|
43
|
+
// same 32 bits twice. Length goes in as well: it separates a file from its own
|
|
44
|
+
// prefix, which the samples alone would not.
|
|
45
|
+
const high = fnv1a(tail, fnv1a(head, bytes.length >>> 0));
|
|
46
|
+
return high.toString(16).padStart(8, '0') + low.toString(16).padStart(8, '0');
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,MAAM,GAAG,IAAI,CAAC;AAEpB,4EAA4E;AAC5E,SAAS,KAAK,CAAC,KAAiB,EAAE,IAAY;IAC5C,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,IAAI,CAAC;QACb,+EAA+E;QAC/E,gEAAgE;QAChE,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,WAAW,CAAC,KAAiB;IAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACvC,kFAAkF;IAClF,yBAAyB;IACzB,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;IAEhE,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;IACjD,mFAAmF;IACnF,+EAA+E;IAC/E,6CAA6C;IAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;IAE1D,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAChF,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -15,11 +15,21 @@
|
|
|
15
15
|
*/
|
|
16
16
|
export type { CacheStats } from './cache.js';
|
|
17
17
|
export { paintToCanvas, toImageData } from './canvas.js';
|
|
18
|
-
export type { RenderHandle } from './document.js';
|
|
18
|
+
export type { ImageHandle, RenderHandle, SvgHandle } from './document.js';
|
|
19
19
|
export { Document, open } from './document.js';
|
|
20
|
+
export type { EncodedFormat, EncodedImage, EncodeOptions, RasterFormat, SvgPage, } from './encode.js';
|
|
21
|
+
export { encode, encodedImage, mimeType, PageImage, svgPage, } from './encode.js';
|
|
22
|
+
export { IncorrectPasswordError, PasswordError, PasswordRequiredError, } from './errors.js';
|
|
23
|
+
export type { LinkTarget, PageLink } from './links.js';
|
|
24
|
+
export type { DestinationKind, OutlineDestination, OutlineNode, } from './outline.js';
|
|
25
|
+
export { buildOutlineTree, walkOutline } from './outline.js';
|
|
20
26
|
export type { Runtime } from './runtime.js';
|
|
21
27
|
export { backend, currentRuntime, hardwareConcurrency, init, } from './runtime.js';
|
|
22
28
|
export type { JobHandle, JobTiming } from './scheduler.js';
|
|
23
29
|
export { AbortError, DEFAULT_PRIORITY } from './scheduler.js';
|
|
24
|
-
export type {
|
|
30
|
+
export type { MatchOptions, SearchMatch } from './search.js';
|
|
31
|
+
export { findRanges, searchPageText } from './search.js';
|
|
32
|
+
export type { PageText, Quad, Rect, TextLine } from './text.js';
|
|
33
|
+
export { lineQuad, pageString, quadBounds, scaleQuad, scaleRect, } from './text.js';
|
|
34
|
+
export type { DocumentMetadata, OpenOptions, PageSize, PdfSource, RenderedPage, RenderOptions, SearchOptions, StreamedPage, StreamOptions, SvgOptions, } from './types.js';
|
|
25
35
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,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,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"}
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,11 @@
|
|
|
15
15
|
*/
|
|
16
16
|
export { paintToCanvas, toImageData } from './canvas.js';
|
|
17
17
|
export { Document, open } from './document.js';
|
|
18
|
+
export { encode, encodedImage, mimeType, PageImage, svgPage, } from './encode.js';
|
|
19
|
+
export { IncorrectPasswordError, PasswordError, PasswordRequiredError, } from './errors.js';
|
|
20
|
+
export { buildOutlineTree, walkOutline } from './outline.js';
|
|
18
21
|
export { backend, currentRuntime, hardwareConcurrency, init, } from './runtime.js';
|
|
19
22
|
export { AbortError, DEFAULT_PRIORITY } from './scheduler.js';
|
|
23
|
+
export { findRanges, searchPageText } from './search.js';
|
|
24
|
+
export { lineQuad, pageString, quadBounds, scaleQuad, scaleRect, } from './text.js';
|
|
20
25
|
//# 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,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,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;AAEzD,OAAO,EACL,QAAQ,EACR,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,GACV,MAAM,WAAW,CAAC"}
|
package/dist/links.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { PageLink as NativePageLink } from '@build-qube/papyra-native';
|
|
2
|
+
import { type OutlineDestination } from './outline.js';
|
|
3
|
+
import type { Rect } from './text.js';
|
|
4
|
+
/**
|
|
5
|
+
* Where a link goes.
|
|
6
|
+
*
|
|
7
|
+
* A discriminated union rather than two nullable fields, so narrowing on `kind` gives
|
|
8
|
+
* you the payload without a non-null assertion:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* if (link.target.kind === 'uri') window.open(link.target.uri);
|
|
12
|
+
* else void doc.render(link.target.dest.page, { fitWidth: 1600 });
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export type LinkTarget = {
|
|
16
|
+
/** The link points somewhere in this document. */
|
|
17
|
+
readonly kind: 'internal';
|
|
18
|
+
/** The page and the view, in the same shape an outline entry uses. */
|
|
19
|
+
readonly dest: OutlineDestination;
|
|
20
|
+
} | {
|
|
21
|
+
/**
|
|
22
|
+
* The link points out of this document.
|
|
23
|
+
*
|
|
24
|
+
* Not necessarily `http`: `mailto:` and `file:` are both common, and papyra
|
|
25
|
+
* does not validate the string. Decide for yourself what you are willing to
|
|
26
|
+
* follow before handing it to a browser.
|
|
27
|
+
*/
|
|
28
|
+
readonly kind: 'uri';
|
|
29
|
+
/** The URI, exactly as the document wrote it. */
|
|
30
|
+
readonly uri: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* One link on a page: a clickable region, and what it does.
|
|
34
|
+
*
|
|
35
|
+
* Only links that resolve to something actionable are reported — a `/Link` pointing
|
|
36
|
+
* at a page the document does not contain, or carrying an action papyra does not act
|
|
37
|
+
* on, is dropped rather than handed over as a region that would swallow clicks.
|
|
38
|
+
*/
|
|
39
|
+
export interface PageLink {
|
|
40
|
+
/**
|
|
41
|
+
* The clickable region, in the same 72-DPI top-left space as {@link PageText} and
|
|
42
|
+
* {@link PageSize}. Multiply by `rendered.width / pageSize.width` to place it over
|
|
43
|
+
* a render — {@link scaleRect} does exactly that.
|
|
44
|
+
*/
|
|
45
|
+
readonly rect: Rect;
|
|
46
|
+
/** Where activating the link goes. Narrow on `target.kind`. */
|
|
47
|
+
readonly target: LinkTarget;
|
|
48
|
+
/** The annotation's tooltip, when it has one. */
|
|
49
|
+
readonly alt: string | null;
|
|
50
|
+
}
|
|
51
|
+
/** @internal */
|
|
52
|
+
export declare function toPageLink(native: NativePageLink): PageLink | null;
|
|
53
|
+
//# sourceMappingURL=links.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EAAE,KAAK,kBAAkB,EAAiB,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC;;;;;;;;;;GAUG;AACH,MAAM,MAAM,UAAU,GAClB;IACE,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;CACnC,GACD;IACE;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,iDAAiD;IACjD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;AAEN;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,iDAAiD;IACjD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,gBAAgB;AAChB,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,QAAQ,GAAG,IAAI,CAelE"}
|
package/dist/links.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { toDestination } from './outline.js';
|
|
2
|
+
/** @internal */
|
|
3
|
+
export function toPageLink(native) {
|
|
4
|
+
const target = linkTarget(native);
|
|
5
|
+
// The bindings only emit a link with one target or the other, so this is
|
|
6
|
+
// unreachable in practice; dropping it beats widening the type with a null target.
|
|
7
|
+
if (!target)
|
|
8
|
+
return null;
|
|
9
|
+
return {
|
|
10
|
+
rect: {
|
|
11
|
+
x: native.x0,
|
|
12
|
+
y: native.y0,
|
|
13
|
+
width: native.x1 - native.x0,
|
|
14
|
+
height: native.y1 - native.y0,
|
|
15
|
+
},
|
|
16
|
+
target,
|
|
17
|
+
alt: native.alt ?? null,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function linkTarget(native) {
|
|
21
|
+
if (native.uri !== undefined)
|
|
22
|
+
return { kind: 'uri', uri: native.uri };
|
|
23
|
+
const dest = toDestination(native.dest);
|
|
24
|
+
return dest ? { kind: 'internal', dest } : null;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=links.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"links.js","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,aAAa,EAAE,MAAM,cAAc,CAAC;AAsDtE,gBAAgB;AAChB,MAAM,UAAU,UAAU,CAAC,MAAsB;IAC/C,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAClC,yEAAyE;IACzE,mFAAmF;IACnF,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,OAAO;QACL,IAAI,EAAE;YACJ,CAAC,EAAE,MAAM,CAAC,EAAE;YACZ,CAAC,EAAE,MAAM,CAAC,EAAE;YACZ,KAAK,EAAE,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE;YAC5B,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE;SAC9B;QACD,MAAM;QACN,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,IAAI;KACxB,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,MAAsB;IACxC,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC;IACtE,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC"}
|