canvu-react 0.4.74 → 0.4.75
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/index.cjs +402 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +402 -25
- package/dist/index.js.map +1 -1
- package/dist/pdf.mjs +28 -0
- package/dist/pdf.worker.mjs +31 -0
- package/dist/react.cjs +414 -37
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +414 -37
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -203,6 +203,342 @@ var IndexedDbImageStore = class {
|
|
|
203
203
|
}
|
|
204
204
|
};
|
|
205
205
|
|
|
206
|
+
// src/image/pdf-worker-renderer.ts
|
|
207
|
+
var PDF_WORKER_SOURCE = `
|
|
208
|
+
let pdfjsPromise = null;
|
|
209
|
+
|
|
210
|
+
const loadPdfJs = async (pdfjsModuleCandidates) => {
|
|
211
|
+
if (!pdfjsPromise) {
|
|
212
|
+
pdfjsPromise = (async () => {
|
|
213
|
+
let lastError;
|
|
214
|
+
for (const candidate of pdfjsModuleCandidates) {
|
|
215
|
+
try {
|
|
216
|
+
const pdfjs = await import(candidate.moduleUrl);
|
|
217
|
+
if (pdfjs.GlobalWorkerOptions) {
|
|
218
|
+
pdfjs.GlobalWorkerOptions.workerSrc = candidate.workerUrl;
|
|
219
|
+
}
|
|
220
|
+
return pdfjs;
|
|
221
|
+
} catch (error) {
|
|
222
|
+
lastError = error;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
throw lastError ?? new Error("Unable to load pdfjs-dist");
|
|
226
|
+
})();
|
|
227
|
+
}
|
|
228
|
+
return await pdfjsPromise;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const createErrorPayload = (error) => ({
|
|
232
|
+
message: error instanceof Error ? error.message : String(error),
|
|
233
|
+
name: error instanceof Error ? error.name : "Error",
|
|
234
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const normalizePdfPageNumbers = (pageNumbers, pageCount) => {
|
|
238
|
+
if (!Array.isArray(pageNumbers) || pageNumbers.length === 0) {
|
|
239
|
+
return Array.from({ length: pageCount }, (_, index) => index + 1);
|
|
240
|
+
}
|
|
241
|
+
return [...new Set(pageNumbers)]
|
|
242
|
+
.filter((pageNumber) => pageNumber >= 1 && pageNumber <= pageCount)
|
|
243
|
+
.sort((left, right) => left - right);
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const runWithConcurrency = async (items, concurrency, execute) => {
|
|
247
|
+
const results = new Array(items.length);
|
|
248
|
+
let nextIndex = 0;
|
|
249
|
+
const safeConcurrency = Number.isFinite(concurrency) && concurrency > 0
|
|
250
|
+
? Math.round(concurrency)
|
|
251
|
+
: 1;
|
|
252
|
+
const workerCount = Math.max(1, Math.min(safeConcurrency, items.length));
|
|
253
|
+
await Promise.all(
|
|
254
|
+
Array.from({ length: workerCount }, async () => {
|
|
255
|
+
while (nextIndex < items.length) {
|
|
256
|
+
const currentIndex = nextIndex;
|
|
257
|
+
nextIndex += 1;
|
|
258
|
+
const item = items[currentIndex];
|
|
259
|
+
if (item === undefined) {
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
results[currentIndex] = await execute(item);
|
|
263
|
+
}
|
|
264
|
+
}),
|
|
265
|
+
);
|
|
266
|
+
return results;
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const renderPageToBlob = async (page, scale, storeThumbnails) => {
|
|
270
|
+
const raw = page.getViewport({ scale: 1 });
|
|
271
|
+
const adjustedScale = Math.round(raw.width * scale) / raw.width;
|
|
272
|
+
const viewport = page.getViewport({ scale: adjustedScale });
|
|
273
|
+
const width = Math.round(viewport.width);
|
|
274
|
+
const height = Math.round(viewport.height);
|
|
275
|
+
const canvas = new OffscreenCanvas(width, height);
|
|
276
|
+
const canvasContext = canvas.getContext("2d");
|
|
277
|
+
if (!canvasContext) {
|
|
278
|
+
throw new Error("OffscreenCanvas 2D context unavailable");
|
|
279
|
+
}
|
|
280
|
+
canvasContext.imageSmoothingEnabled = true;
|
|
281
|
+
canvasContext.imageSmoothingQuality = "high";
|
|
282
|
+
await page.render({ canvasContext, viewport }).promise;
|
|
283
|
+
const blob = await canvas.convertToBlob({ type: "image/png" });
|
|
284
|
+
let thumbnailBlob;
|
|
285
|
+
if (storeThumbnails) {
|
|
286
|
+
const thumbScale = Math.min(1, 256 / Math.max(width, height));
|
|
287
|
+
const thumbnailWidth = Math.max(1, Math.round(width * thumbScale));
|
|
288
|
+
const thumbnailHeight = Math.max(1, Math.round(height * thumbScale));
|
|
289
|
+
const thumbnailCanvas = new OffscreenCanvas(thumbnailWidth, thumbnailHeight);
|
|
290
|
+
const thumbnailContext = thumbnailCanvas.getContext("2d");
|
|
291
|
+
if (thumbnailContext) {
|
|
292
|
+
thumbnailContext.imageSmoothingEnabled = true;
|
|
293
|
+
thumbnailContext.imageSmoothingQuality = "high";
|
|
294
|
+
thumbnailContext.drawImage(canvas, 0, 0, thumbnailWidth, thumbnailHeight);
|
|
295
|
+
}
|
|
296
|
+
thumbnailBlob = await thumbnailCanvas.convertToBlob({ type: "image/png" });
|
|
297
|
+
}
|
|
298
|
+
return { blob, height, thumbnailBlob, width };
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
self.onmessage = async (event) => {
|
|
302
|
+
const message = event.data;
|
|
303
|
+
if (!message || message.type !== "render") {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
try {
|
|
307
|
+
const pdfjs = await loadPdfJs(message.pdfjsModuleCandidates);
|
|
308
|
+
const pdf = await pdfjs.getDocument({
|
|
309
|
+
data: new Uint8Array(message.pdfData),
|
|
310
|
+
disableWorker: true,
|
|
311
|
+
}).promise;
|
|
312
|
+
try {
|
|
313
|
+
const pageNumbers = normalizePdfPageNumbers(message.pageNumbers, pdf.numPages);
|
|
314
|
+
const bufferedPages = new Map();
|
|
315
|
+
let nextEmitIndex = 0;
|
|
316
|
+
let emitChain = Promise.resolve();
|
|
317
|
+
const emitPageInOrder = async (pageNumber, renderedPage) => {
|
|
318
|
+
bufferedPages.set(pageNumber, renderedPage);
|
|
319
|
+
const flush = () => {
|
|
320
|
+
while (nextEmitIndex < pageNumbers.length) {
|
|
321
|
+
const nextPageNumber = pageNumbers[nextEmitIndex];
|
|
322
|
+
if (nextPageNumber == null) break;
|
|
323
|
+
const nextPage = bufferedPages.get(nextPageNumber);
|
|
324
|
+
if (!nextPage) break;
|
|
325
|
+
bufferedPages.delete(nextPageNumber);
|
|
326
|
+
nextEmitIndex += 1;
|
|
327
|
+
self.postMessage({
|
|
328
|
+
type: "page",
|
|
329
|
+
page: {
|
|
330
|
+
...nextPage,
|
|
331
|
+
pageNumber: nextPageNumber,
|
|
332
|
+
},
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
const nextChain = emitChain.then(flush, flush);
|
|
337
|
+
emitChain = nextChain.catch(() => {});
|
|
338
|
+
await nextChain;
|
|
339
|
+
};
|
|
340
|
+
await runWithConcurrency(
|
|
341
|
+
pageNumbers,
|
|
342
|
+
message.pageConcurrency,
|
|
343
|
+
async (pageNumber) => {
|
|
344
|
+
const page = await pdf.getPage(pageNumber);
|
|
345
|
+
try {
|
|
346
|
+
const renderedPage = await renderPageToBlob(
|
|
347
|
+
page,
|
|
348
|
+
message.scale,
|
|
349
|
+
message.storeThumbnails,
|
|
350
|
+
);
|
|
351
|
+
await emitPageInOrder(pageNumber, renderedPage);
|
|
352
|
+
} finally {
|
|
353
|
+
page.cleanup();
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
);
|
|
357
|
+
await emitChain;
|
|
358
|
+
} finally {
|
|
359
|
+
await pdf.destroy();
|
|
360
|
+
}
|
|
361
|
+
self.postMessage({ type: "done" });
|
|
362
|
+
} catch (error) {
|
|
363
|
+
self.postMessage({ type: "error", error: createErrorPayload(error) });
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
`;
|
|
367
|
+
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
368
|
+
var hasObjectMembers = (value) => (typeof value === "object" || typeof value === "function") && value !== null;
|
|
369
|
+
var isOffscreenCanvasCandidate = (value) => typeof value === "function";
|
|
370
|
+
var getEnvironmentRecord = (environment) => isRecord(environment) ? environment : null;
|
|
371
|
+
var canUsePdfWorkerRenderer = (environment = globalThis) => {
|
|
372
|
+
const candidateEnvironment = getEnvironmentRecord(environment);
|
|
373
|
+
if (!candidateEnvironment) return false;
|
|
374
|
+
if (typeof candidateEnvironment.Worker !== "function") return false;
|
|
375
|
+
if (typeof candidateEnvironment.Blob !== "function") return false;
|
|
376
|
+
if (!isOffscreenCanvasCandidate(candidateEnvironment.OffscreenCanvas)) {
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
const urlCandidate = candidateEnvironment.URL;
|
|
380
|
+
if (!hasObjectMembers(urlCandidate)) return false;
|
|
381
|
+
if (typeof urlCandidate.createObjectURL !== "function") return false;
|
|
382
|
+
if (typeof urlCandidate.revokeObjectURL !== "function") return false;
|
|
383
|
+
try {
|
|
384
|
+
const canvas = new candidateEnvironment.OffscreenCanvas(1, 1);
|
|
385
|
+
return typeof canvas.getContext === "function" && typeof canvas.convertToBlob === "function";
|
|
386
|
+
} catch {
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
var createAbortError = () => new DOMException("Aborted", "AbortError");
|
|
391
|
+
var throwIfAborted = (signal) => {
|
|
392
|
+
if (signal?.aborted) {
|
|
393
|
+
throw createAbortError();
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
var createPdfWorker = () => {
|
|
397
|
+
const workerBlob = new Blob([PDF_WORKER_SOURCE], {
|
|
398
|
+
type: "text/javascript"
|
|
399
|
+
});
|
|
400
|
+
const workerUrl = URL.createObjectURL(workerBlob);
|
|
401
|
+
try {
|
|
402
|
+
const worker = new Worker(workerUrl, {
|
|
403
|
+
name: "canvu-pdf-renderer",
|
|
404
|
+
type: "module"
|
|
405
|
+
});
|
|
406
|
+
return {
|
|
407
|
+
release: () => URL.revokeObjectURL(workerUrl),
|
|
408
|
+
worker
|
|
409
|
+
};
|
|
410
|
+
} catch (error) {
|
|
411
|
+
URL.revokeObjectURL(workerUrl);
|
|
412
|
+
throw error;
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
var createWorkerError = (message) => {
|
|
416
|
+
const error = new Error(message.error.message);
|
|
417
|
+
error.name = message.error.name;
|
|
418
|
+
error.stack = message.error.stack;
|
|
419
|
+
return error;
|
|
420
|
+
};
|
|
421
|
+
var PACKAGED_PDFJS_MODULE_FILE = "./pdf.mjs";
|
|
422
|
+
var PACKAGED_PDFJS_WORKER_FILE = "./pdf.worker.mjs";
|
|
423
|
+
var resolveRelativeAssetUrl = (path, baseUrl) => new URL(path, baseUrl).toString();
|
|
424
|
+
var resolvePackagedPdfJsModuleCandidate = (baseUrl = import.meta.url) => ({
|
|
425
|
+
moduleUrl: resolveRelativeAssetUrl(PACKAGED_PDFJS_MODULE_FILE, baseUrl),
|
|
426
|
+
workerUrl: resolveRelativeAssetUrl(PACKAGED_PDFJS_WORKER_FILE, baseUrl)
|
|
427
|
+
});
|
|
428
|
+
var resolveBundledPdfJsModuleCandidate = () => ({
|
|
429
|
+
moduleUrl: new URL("pdfjs-dist/build/pdf.min.mjs", import.meta.url).toString(),
|
|
430
|
+
workerUrl: new URL(
|
|
431
|
+
"pdfjs-dist/build/pdf.worker.min.mjs",
|
|
432
|
+
import.meta.url
|
|
433
|
+
).toString()
|
|
434
|
+
});
|
|
435
|
+
var resolvePdfJsModuleCandidates = () => [
|
|
436
|
+
resolvePackagedPdfJsModuleCandidate(),
|
|
437
|
+
resolveBundledPdfJsModuleCandidate()
|
|
438
|
+
];
|
|
439
|
+
var loadPdfToStoreWithWorker = async (file, store, options) => {
|
|
440
|
+
throwIfAborted(options.signal);
|
|
441
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
442
|
+
throwIfAborted(options.signal);
|
|
443
|
+
return await new Promise((resolve, reject) => {
|
|
444
|
+
const { release, worker } = createPdfWorker();
|
|
445
|
+
const pageResults = [];
|
|
446
|
+
let storeChain = Promise.resolve();
|
|
447
|
+
let cleanedUp = false;
|
|
448
|
+
let settled = false;
|
|
449
|
+
const cleanup = () => {
|
|
450
|
+
if (cleanedUp) return;
|
|
451
|
+
cleanedUp = true;
|
|
452
|
+
options.signal?.removeEventListener("abort", abortWorker);
|
|
453
|
+
worker.onmessage = null;
|
|
454
|
+
worker.onerror = null;
|
|
455
|
+
worker.terminate();
|
|
456
|
+
release();
|
|
457
|
+
};
|
|
458
|
+
const rejectOnce = (error) => {
|
|
459
|
+
if (settled) return;
|
|
460
|
+
settled = true;
|
|
461
|
+
cleanup();
|
|
462
|
+
reject(error);
|
|
463
|
+
};
|
|
464
|
+
const rejectAfterQueuedStores = (error) => {
|
|
465
|
+
if (settled) return;
|
|
466
|
+
cleanup();
|
|
467
|
+
storeChain.then(() => {
|
|
468
|
+
if (settled) return;
|
|
469
|
+
settled = true;
|
|
470
|
+
reject(error);
|
|
471
|
+
}).catch(rejectOnce);
|
|
472
|
+
};
|
|
473
|
+
function abortWorker() {
|
|
474
|
+
rejectOnce(createAbortError());
|
|
475
|
+
}
|
|
476
|
+
const storePage = (message) => {
|
|
477
|
+
try {
|
|
478
|
+
options.onPageReceived?.({ pageNumber: message.page.pageNumber });
|
|
479
|
+
} catch (error) {
|
|
480
|
+
rejectOnce(error);
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
storeChain = storeChain.then(async () => {
|
|
484
|
+
throwIfAborted(options.signal);
|
|
485
|
+
const blobId = await store.storeOriginal(message.page.blob);
|
|
486
|
+
throwIfAborted(options.signal);
|
|
487
|
+
const thumbnailBlobId = options.storeThumbnails && message.page.thumbnailBlob ? await store.storeThumbnail(message.page.thumbnailBlob) : "";
|
|
488
|
+
throwIfAborted(options.signal);
|
|
489
|
+
const pageResult = {
|
|
490
|
+
blobId,
|
|
491
|
+
height: message.page.height,
|
|
492
|
+
pageNumber: message.page.pageNumber,
|
|
493
|
+
thumbnailBlobId,
|
|
494
|
+
width: message.page.width
|
|
495
|
+
};
|
|
496
|
+
pageResults.push(pageResult);
|
|
497
|
+
await options.onPageStored?.(pageResult);
|
|
498
|
+
throwIfAborted(options.signal);
|
|
499
|
+
});
|
|
500
|
+
void storeChain.catch(rejectOnce);
|
|
501
|
+
};
|
|
502
|
+
worker.onmessage = (event) => {
|
|
503
|
+
const message = event.data;
|
|
504
|
+
if (message.type === "page") {
|
|
505
|
+
storePage(message);
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
if (message.type === "error") {
|
|
509
|
+
rejectAfterQueuedStores(createWorkerError(message));
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
storeChain.then(() => {
|
|
513
|
+
if (settled) return;
|
|
514
|
+
settled = true;
|
|
515
|
+
cleanup();
|
|
516
|
+
resolve(pageResults);
|
|
517
|
+
}).catch(rejectOnce);
|
|
518
|
+
};
|
|
519
|
+
worker.onerror = (event) => {
|
|
520
|
+
rejectAfterQueuedStores(event.error ?? new Error(event.message));
|
|
521
|
+
};
|
|
522
|
+
options.signal?.addEventListener("abort", abortWorker, { once: true });
|
|
523
|
+
try {
|
|
524
|
+
worker.postMessage(
|
|
525
|
+
{
|
|
526
|
+
pdfData: arrayBuffer,
|
|
527
|
+
pdfjsModuleCandidates: resolvePdfJsModuleCandidates(),
|
|
528
|
+
pageNumbers: options.pageNumbers ? [...options.pageNumbers] : void 0,
|
|
529
|
+
pageConcurrency: options.pageConcurrency,
|
|
530
|
+
scale: options.scale,
|
|
531
|
+
storeThumbnails: options.storeThumbnails,
|
|
532
|
+
type: "render"
|
|
533
|
+
},
|
|
534
|
+
[arrayBuffer]
|
|
535
|
+
);
|
|
536
|
+
} catch (error) {
|
|
537
|
+
rejectOnce(error);
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
};
|
|
541
|
+
|
|
206
542
|
// src/image/pdf-loader.ts
|
|
207
543
|
var pdfjsPromise = null;
|
|
208
544
|
function getPdfJs() {
|
|
@@ -219,7 +555,7 @@ function getPdfJs() {
|
|
|
219
555
|
return pdfjsPromise;
|
|
220
556
|
}
|
|
221
557
|
async function renderPageToCanvas(page, scale, signal) {
|
|
222
|
-
|
|
558
|
+
throwIfAborted2(signal);
|
|
223
559
|
const raw = page.getViewport({ scale: 1 });
|
|
224
560
|
const adjustedScale = Math.round(raw.width * scale) / raw.width;
|
|
225
561
|
const viewport = page.getViewport({ scale: adjustedScale });
|
|
@@ -241,7 +577,7 @@ async function renderPageToCanvas(page, scale, signal) {
|
|
|
241
577
|
try {
|
|
242
578
|
await renderTask.promise;
|
|
243
579
|
} catch (error) {
|
|
244
|
-
if (signal.aborted) throw
|
|
580
|
+
if (signal.aborted) throw createAbortError2();
|
|
245
581
|
throw error;
|
|
246
582
|
} finally {
|
|
247
583
|
signal.removeEventListener("abort", abortRender);
|
|
@@ -249,15 +585,15 @@ async function renderPageToCanvas(page, scale, signal) {
|
|
|
249
585
|
} else {
|
|
250
586
|
await renderTask.promise;
|
|
251
587
|
}
|
|
252
|
-
|
|
588
|
+
throwIfAborted2(signal);
|
|
253
589
|
return { canvas, width: w, height: h };
|
|
254
590
|
}
|
|
255
|
-
function
|
|
591
|
+
function createAbortError2() {
|
|
256
592
|
return new DOMException("Aborted", "AbortError");
|
|
257
593
|
}
|
|
258
|
-
function
|
|
594
|
+
function throwIfAborted2(signal) {
|
|
259
595
|
if (signal?.aborted) {
|
|
260
|
-
throw
|
|
596
|
+
throw createAbortError2();
|
|
261
597
|
}
|
|
262
598
|
}
|
|
263
599
|
function normalizePdfPageNumbers(pageNumbers, pageCount) {
|
|
@@ -273,7 +609,7 @@ async function runWithConcurrency(items, concurrency, execute, signal) {
|
|
|
273
609
|
await Promise.all(
|
|
274
610
|
Array.from({ length: workerCount }, async () => {
|
|
275
611
|
while (nextIndex < items.length) {
|
|
276
|
-
|
|
612
|
+
throwIfAborted2(signal);
|
|
277
613
|
const currentIndex = nextIndex;
|
|
278
614
|
nextIndex += 1;
|
|
279
615
|
const item = items[currentIndex];
|
|
@@ -281,7 +617,7 @@ async function runWithConcurrency(items, concurrency, execute, signal) {
|
|
|
281
617
|
continue;
|
|
282
618
|
}
|
|
283
619
|
results[currentIndex] = await execute(item);
|
|
284
|
-
|
|
620
|
+
throwIfAborted2(signal);
|
|
285
621
|
}
|
|
286
622
|
})
|
|
287
623
|
);
|
|
@@ -292,11 +628,52 @@ async function loadPdfToStore(file, store, options) {
|
|
|
292
628
|
const pageConcurrency = options?.pageConcurrency ?? 2;
|
|
293
629
|
const storeThumbnails = options?.storeThumbnails ?? false;
|
|
294
630
|
const signal = options?.signal;
|
|
295
|
-
|
|
631
|
+
throwIfAborted2(signal);
|
|
632
|
+
if (canUsePdfWorkerRenderer()) {
|
|
633
|
+
let workerPageCount = 0;
|
|
634
|
+
try {
|
|
635
|
+
return await loadPdfToStoreWithWorker(file, store, {
|
|
636
|
+
scale,
|
|
637
|
+
pageNumbers: options?.pageNumbers,
|
|
638
|
+
pageConcurrency,
|
|
639
|
+
storeThumbnails,
|
|
640
|
+
signal,
|
|
641
|
+
onPageReceived: () => {
|
|
642
|
+
workerPageCount += 1;
|
|
643
|
+
},
|
|
644
|
+
onPageStored: async (page) => {
|
|
645
|
+
await options?.onPageStored?.(page);
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
} catch (error) {
|
|
649
|
+
if (signal?.aborted || workerPageCount > 0) {
|
|
650
|
+
throw error;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
return await loadPdfToStoreOnMainThread(file, store, {
|
|
655
|
+
scale,
|
|
656
|
+
pageNumbers: options?.pageNumbers,
|
|
657
|
+
pageConcurrency,
|
|
658
|
+
storeThumbnails,
|
|
659
|
+
signal,
|
|
660
|
+
onPageStored: options?.onPageStored
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
async function loadPdfToStoreOnMainThread(file, store, options) {
|
|
664
|
+
const {
|
|
665
|
+
pageConcurrency,
|
|
666
|
+
scale,
|
|
667
|
+
signal,
|
|
668
|
+
storeThumbnails,
|
|
669
|
+
onPageStored,
|
|
670
|
+
pageNumbers
|
|
671
|
+
} = options;
|
|
672
|
+
throwIfAborted2(signal);
|
|
296
673
|
const pdfjs = await getPdfJs();
|
|
297
|
-
|
|
674
|
+
throwIfAborted2(signal);
|
|
298
675
|
const arrayBuffer = await file.arrayBuffer();
|
|
299
|
-
|
|
676
|
+
throwIfAborted2(signal);
|
|
300
677
|
const loadingTask = pdfjs.getDocument({ data: arrayBuffer });
|
|
301
678
|
if (signal) {
|
|
302
679
|
const abortLoading = () => {
|
|
@@ -308,14 +685,14 @@ async function loadPdfToStore(file, store, options) {
|
|
|
308
685
|
signal.removeEventListener("abort", abortLoading);
|
|
309
686
|
return await loadPdfDocumentToStore(pdf2, store, {
|
|
310
687
|
scale,
|
|
311
|
-
pageNumbers
|
|
688
|
+
pageNumbers,
|
|
312
689
|
pageConcurrency,
|
|
313
690
|
storeThumbnails,
|
|
314
691
|
signal,
|
|
315
|
-
onPageStored
|
|
692
|
+
onPageStored
|
|
316
693
|
});
|
|
317
694
|
} catch (error) {
|
|
318
|
-
if (signal.aborted) throw
|
|
695
|
+
if (signal.aborted) throw createAbortError2();
|
|
319
696
|
throw error;
|
|
320
697
|
} finally {
|
|
321
698
|
signal.removeEventListener("abort", abortLoading);
|
|
@@ -324,16 +701,16 @@ async function loadPdfToStore(file, store, options) {
|
|
|
324
701
|
const pdf = await loadingTask.promise;
|
|
325
702
|
return await loadPdfDocumentToStore(pdf, store, {
|
|
326
703
|
scale,
|
|
327
|
-
pageNumbers
|
|
704
|
+
pageNumbers,
|
|
328
705
|
pageConcurrency,
|
|
329
706
|
storeThumbnails,
|
|
330
|
-
onPageStored
|
|
707
|
+
onPageStored
|
|
331
708
|
});
|
|
332
709
|
}
|
|
333
710
|
async function loadPdfDocumentToStore(pdf, store, options) {
|
|
334
711
|
const { pageConcurrency, scale, signal } = options;
|
|
335
712
|
const storeThumbnails = options.storeThumbnails ?? false;
|
|
336
|
-
|
|
713
|
+
throwIfAborted2(signal);
|
|
337
714
|
const pageNumbers = normalizePdfPageNumbers(options?.pageNumbers, pdf.numPages);
|
|
338
715
|
const bufferedResults = /* @__PURE__ */ new Map();
|
|
339
716
|
let nextEmitIndex = 0;
|
|
@@ -348,9 +725,9 @@ async function loadPdfDocumentToStore(pdf, store, options) {
|
|
|
348
725
|
if (!bufferedResult) break;
|
|
349
726
|
bufferedResults.delete(nextPageNumber);
|
|
350
727
|
nextEmitIndex += 1;
|
|
351
|
-
|
|
728
|
+
throwIfAborted2(signal);
|
|
352
729
|
await options?.onPageStored?.(bufferedResult);
|
|
353
|
-
|
|
730
|
+
throwIfAborted2(signal);
|
|
354
731
|
}
|
|
355
732
|
};
|
|
356
733
|
const nextChain = emitChain.then(run, run);
|
|
@@ -362,20 +739,20 @@ async function loadPdfDocumentToStore(pdf, store, options) {
|
|
|
362
739
|
pageNumbers,
|
|
363
740
|
pageConcurrency,
|
|
364
741
|
async (pageNumber) => {
|
|
365
|
-
|
|
742
|
+
throwIfAborted2(signal);
|
|
366
743
|
const page = await pdf.getPage(pageNumber);
|
|
367
|
-
|
|
744
|
+
throwIfAborted2(signal);
|
|
368
745
|
const { canvas, width, height } = await renderPageToCanvas(
|
|
369
746
|
page,
|
|
370
747
|
scale,
|
|
371
748
|
signal
|
|
372
749
|
);
|
|
373
|
-
|
|
750
|
+
throwIfAborted2(signal);
|
|
374
751
|
const mime = "image/png";
|
|
375
752
|
const pageBlob = await encodeCanvasToBlob(canvas, { mimeType: mime });
|
|
376
|
-
|
|
753
|
+
throwIfAborted2(signal);
|
|
377
754
|
const blobId = await store.storeOriginal(pageBlob);
|
|
378
|
-
|
|
755
|
+
throwIfAborted2(signal);
|
|
379
756
|
const thumbnailBlobId = storeThumbnails ? await (async () => {
|
|
380
757
|
const thumbScale = Math.min(1, 256 / Math.max(width, height));
|
|
381
758
|
const tw = Math.max(1, Math.round(width * thumbScale));
|
|
@@ -392,7 +769,7 @@ async function loadPdfDocumentToStore(pdf, store, options) {
|
|
|
392
769
|
const thumbBlob = await encodeCanvasToBlob(thumbCanvas, {
|
|
393
770
|
mimeType: mime
|
|
394
771
|
});
|
|
395
|
-
|
|
772
|
+
throwIfAborted2(signal);
|
|
396
773
|
return await store.storeThumbnail(thumbBlob);
|
|
397
774
|
})() : "";
|
|
398
775
|
const pageResult = {
|