@2018kguo/recto 0.3.0 → 0.5.1
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/dist/assets.js +32 -52
- package/dist/document.d.ts +100 -4
- package/dist/document.js +72 -39
- package/dist/engine.d.ts +7 -0
- package/dist/engine.js +19 -13
- package/dist/index.d.ts +1 -1
- package/dist/pool-worker.d.ts +1 -0
- package/dist/pool-worker.js +2 -2
- package/dist/pool.d.ts +7 -1
- package/dist/pool.js +14 -6
- package/dist/ranged.d.ts +41 -11
- package/dist/ranged.js +579 -97
- package/dist/reading-order.d.ts +7 -0
- package/dist/reading-order.js +15 -6
- package/dist/text-items.js +1 -6
- package/package.json +1 -1
- package/wasm/pins.mjs +4 -4
- package/wasm/recto-more.wasm +0 -0
- package/wasm/recto-rare.wasm +0 -0
- package/wasm/recto-render.wasm +0 -0
- package/wasm/recto.gen.d.mts +1 -1
- package/wasm/recto.gen.mjs +100 -12
- package/wasm/recto.types.d.mts +39 -5
- package/wasm/recto.wasm +0 -0
package/dist/pool.js
CHANGED
|
@@ -39,6 +39,7 @@ class Pool {
|
|
|
39
39
|
#limit;
|
|
40
40
|
#ceiling;
|
|
41
41
|
#assetBase;
|
|
42
|
+
#maxDecodedBytes;
|
|
42
43
|
#threads = [];
|
|
43
44
|
/** Started and not yet ready. */
|
|
44
45
|
#startingThreads = new Set();
|
|
@@ -46,10 +47,11 @@ class Pool {
|
|
|
46
47
|
#nextFile = 0;
|
|
47
48
|
#nextId = 0;
|
|
48
49
|
#closed = false;
|
|
49
|
-
constructor(limit, assetBase) {
|
|
50
|
+
constructor(limit, assetBase, maxDecodedBytes) {
|
|
50
51
|
this.#limit = limit;
|
|
51
52
|
this.#ceiling = limit;
|
|
52
53
|
this.#assetBase = assetBase;
|
|
54
|
+
this.#maxDecodedBytes = maxDecodedBytes;
|
|
53
55
|
}
|
|
54
56
|
#spawn() {
|
|
55
57
|
const thread = { worker: null, running: null };
|
|
@@ -147,7 +149,7 @@ class Pool {
|
|
|
147
149
|
};
|
|
148
150
|
thread.worker = worker;
|
|
149
151
|
}
|
|
150
|
-
const start = { assetBase: this.#assetBase };
|
|
152
|
+
const start = { assetBase: this.#assetBase, maxDecodedBytes: this.#maxDecodedBytes };
|
|
151
153
|
thread.worker.postMessage(start);
|
|
152
154
|
}
|
|
153
155
|
catch (error) {
|
|
@@ -240,13 +242,15 @@ class Pool {
|
|
|
240
242
|
text: (index) => call("text", index),
|
|
241
243
|
objects: (index) => call("objects", index),
|
|
242
244
|
annotations: (index) => call("annotations", index),
|
|
245
|
+
links: (index) => call("links", index),
|
|
243
246
|
outline: () => call("outline"),
|
|
244
|
-
render: (index, renderOptions) => {
|
|
247
|
+
render: ((index, renderOptions) => {
|
|
245
248
|
if (renderOptions?.signal) {
|
|
246
249
|
return Promise.reject(new TypeError("a pool's render takes no signal: a call that's running can't be stopped. pool.close() ends all of them."));
|
|
247
250
|
}
|
|
248
|
-
|
|
249
|
-
|
|
251
|
+
const { width, maxHeight, region } = renderOptions ?? {};
|
|
252
|
+
return call("render", index, region === undefined ? { width, maxHeight } : { width, maxHeight, region });
|
|
253
|
+
}),
|
|
250
254
|
close,
|
|
251
255
|
[Symbol.asyncDispose]: close,
|
|
252
256
|
};
|
|
@@ -283,5 +287,9 @@ export function startPool(options) {
|
|
|
283
287
|
const assetBase = options.assetBase !== undefined && typeof location !== "undefined"
|
|
284
288
|
? new URL(options.assetBase, location.href).href
|
|
285
289
|
: options.assetBase;
|
|
286
|
-
|
|
290
|
+
const maxDecodedBytes = options.maxDecodedBytes;
|
|
291
|
+
if (maxDecodedBytes !== undefined && !(typeof maxDecodedBytes === "number" && maxDecodedBytes >= 0)) {
|
|
292
|
+
throw new RangeError("maxDecodedBytes must be a number of bytes, 0 or more");
|
|
293
|
+
}
|
|
294
|
+
return new Pool(threads, assetBase, maxDecodedBytes);
|
|
287
295
|
}
|
package/dist/ranged.d.ts
CHANGED
|
@@ -43,19 +43,37 @@ export type PdfRangedStats = {
|
|
|
43
43
|
export type PdfRangedDocument = PdfDocument & {
|
|
44
44
|
stats(): PdfRangedStats;
|
|
45
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* Bytes `start..end`. With `yieldTail`, read no further than that many bytes before the file's
|
|
48
|
+
* end, where a suffix asked for beside it starts, so no byte comes twice.
|
|
49
|
+
*/
|
|
46
50
|
type Range = {
|
|
47
51
|
start: number;
|
|
48
52
|
end: number;
|
|
53
|
+
yieldTail?: number;
|
|
54
|
+
};
|
|
55
|
+
/** The file's last `suffix` bytes (`bytes=-n`), asked for before its size is known. */
|
|
56
|
+
type Suffix = {
|
|
57
|
+
suffix: number;
|
|
49
58
|
};
|
|
59
|
+
type Request = Range | Suffix;
|
|
60
|
+
/** `received`: the bytes read off the response, `bytes` and any read past it. */
|
|
50
61
|
type Answer = {
|
|
51
62
|
start: number;
|
|
52
63
|
bytes: Uint8Array;
|
|
53
64
|
length: number;
|
|
54
65
|
etag: string | null;
|
|
55
66
|
status: number;
|
|
67
|
+
received: number;
|
|
56
68
|
};
|
|
57
|
-
/**
|
|
58
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Fetches `requests` in parallel; `limit` is how many bytes may still arrive. A range that
|
|
71
|
+
* fails throws. A suffix that isn't answered as one (a server that ignores or refuses it)
|
|
72
|
+
* gives null, and isn't counted: the caller asks for the tail by its offset instead.
|
|
73
|
+
*/
|
|
74
|
+
type Answers = (Answer | null)[];
|
|
75
|
+
type Fetch = (requests: Request[], timeoutMs: number, limit: number) => Answers;
|
|
76
|
+
type FetchAsync = (requests: Request[], timeoutMs: number, limit: number) => Promise<Answers>;
|
|
59
77
|
/** Fetched chunks of one file and the policy for fetching more. */
|
|
60
78
|
declare class RangeLoader {
|
|
61
79
|
#private;
|
|
@@ -71,25 +89,37 @@ declare class RangeLoader {
|
|
|
71
89
|
signal: AbortSignal | undefined;
|
|
72
90
|
});
|
|
73
91
|
stats(): PdfRangedStats;
|
|
74
|
-
/**
|
|
75
|
-
|
|
92
|
+
/**
|
|
93
|
+
* The first round: the head and, in parallel, the tail as a suffix, then the last
|
|
94
|
+
* cross-reference section if the tail didn't hold it. A file the head covers needs no more;
|
|
95
|
+
* a server that doesn't answer the suffix gets the tail by offset in a round of its own.
|
|
96
|
+
*/
|
|
97
|
+
begin(fetchAsync: FetchAsync | null): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* `failure`, or when what's held shows the file isn't a PDF (see `notPdfBytes`), that it isn't: an
|
|
100
|
+
* error or sign-in page fails to parse, or runs into `maxBytes`, and neither says why. Only when
|
|
101
|
+
* enough of the first KiB is held to tell.
|
|
102
|
+
*/
|
|
103
|
+
explain(failure: unknown): unknown;
|
|
76
104
|
/**
|
|
77
105
|
* The `startxref` offset in the fetched last chunk, if it names one. Null for a linearized
|
|
78
106
|
* file, whose trailer points at the first-page section near the head.
|
|
79
107
|
*/
|
|
80
108
|
startxref(): number | null;
|
|
81
109
|
/**
|
|
82
|
-
* Copies [offset, offset + out.length) into `out`, fetching what is missing first
|
|
83
|
-
*
|
|
84
|
-
*
|
|
110
|
+
* Copies [offset, offset + out.length) into `out`, fetching what is missing first, and if it
|
|
111
|
+
* fetches, `ahead` bytes past it too, as far as the budget allows: the engine's guess at what
|
|
112
|
+
* it reads next, which then costs no round trip of its own. On a failed fetch it records the
|
|
113
|
+
* failure and fails the read; the call that made it then throws the failure.
|
|
85
114
|
*/
|
|
86
|
-
read(offset: number, out: Uint8Array): boolean;
|
|
115
|
+
read(offset: number, out: Uint8Array, ahead?: number): boolean;
|
|
87
116
|
}
|
|
88
117
|
/**
|
|
89
|
-
* Starts a ranged read of `source`: the head, then
|
|
90
|
-
*
|
|
118
|
+
* Starts a ranged read of `source`: the head and tail, then the last cross-reference section
|
|
119
|
+
* if the tail didn't hold it. Blocks while it fetches, except in a browser, where these
|
|
120
|
+
* rounds are `fetch` calls.
|
|
91
121
|
*/
|
|
92
|
-
export declare function startRangeLoader(source: string | Uint8Array, options?: PdfRangedOpenOptions): RangeLoader
|
|
122
|
+
export declare function startRangeLoader(source: string | Uint8Array, options?: PdfRangedOpenOptions): Promise<RangeLoader>;
|
|
93
123
|
/**
|
|
94
124
|
* The caller's source in a form that stays valid across an await: bytes copied, a URL as an
|
|
95
125
|
* absolute http(s) string. Runs before anything asynchronous.
|