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/react.cjs
CHANGED
|
@@ -1193,6 +1193,342 @@ async function createThumbnailBlobUrlFromStore(store, thumbnailBlobId) {
|
|
|
1193
1193
|
return URL.createObjectURL(blob);
|
|
1194
1194
|
}
|
|
1195
1195
|
|
|
1196
|
+
// src/image/pdf-worker-renderer.ts
|
|
1197
|
+
var PDF_WORKER_SOURCE = `
|
|
1198
|
+
let pdfjsPromise = null;
|
|
1199
|
+
|
|
1200
|
+
const loadPdfJs = async (pdfjsModuleCandidates) => {
|
|
1201
|
+
if (!pdfjsPromise) {
|
|
1202
|
+
pdfjsPromise = (async () => {
|
|
1203
|
+
let lastError;
|
|
1204
|
+
for (const candidate of pdfjsModuleCandidates) {
|
|
1205
|
+
try {
|
|
1206
|
+
const pdfjs = await import(candidate.moduleUrl);
|
|
1207
|
+
if (pdfjs.GlobalWorkerOptions) {
|
|
1208
|
+
pdfjs.GlobalWorkerOptions.workerSrc = candidate.workerUrl;
|
|
1209
|
+
}
|
|
1210
|
+
return pdfjs;
|
|
1211
|
+
} catch (error) {
|
|
1212
|
+
lastError = error;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
throw lastError ?? new Error("Unable to load pdfjs-dist");
|
|
1216
|
+
})();
|
|
1217
|
+
}
|
|
1218
|
+
return await pdfjsPromise;
|
|
1219
|
+
};
|
|
1220
|
+
|
|
1221
|
+
const createErrorPayload = (error) => ({
|
|
1222
|
+
message: error instanceof Error ? error.message : String(error),
|
|
1223
|
+
name: error instanceof Error ? error.name : "Error",
|
|
1224
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
1225
|
+
});
|
|
1226
|
+
|
|
1227
|
+
const normalizePdfPageNumbers = (pageNumbers, pageCount) => {
|
|
1228
|
+
if (!Array.isArray(pageNumbers) || pageNumbers.length === 0) {
|
|
1229
|
+
return Array.from({ length: pageCount }, (_, index) => index + 1);
|
|
1230
|
+
}
|
|
1231
|
+
return [...new Set(pageNumbers)]
|
|
1232
|
+
.filter((pageNumber) => pageNumber >= 1 && pageNumber <= pageCount)
|
|
1233
|
+
.sort((left, right) => left - right);
|
|
1234
|
+
};
|
|
1235
|
+
|
|
1236
|
+
const runWithConcurrency = async (items, concurrency, execute) => {
|
|
1237
|
+
const results = new Array(items.length);
|
|
1238
|
+
let nextIndex = 0;
|
|
1239
|
+
const safeConcurrency = Number.isFinite(concurrency) && concurrency > 0
|
|
1240
|
+
? Math.round(concurrency)
|
|
1241
|
+
: 1;
|
|
1242
|
+
const workerCount = Math.max(1, Math.min(safeConcurrency, items.length));
|
|
1243
|
+
await Promise.all(
|
|
1244
|
+
Array.from({ length: workerCount }, async () => {
|
|
1245
|
+
while (nextIndex < items.length) {
|
|
1246
|
+
const currentIndex = nextIndex;
|
|
1247
|
+
nextIndex += 1;
|
|
1248
|
+
const item = items[currentIndex];
|
|
1249
|
+
if (item === undefined) {
|
|
1250
|
+
continue;
|
|
1251
|
+
}
|
|
1252
|
+
results[currentIndex] = await execute(item);
|
|
1253
|
+
}
|
|
1254
|
+
}),
|
|
1255
|
+
);
|
|
1256
|
+
return results;
|
|
1257
|
+
};
|
|
1258
|
+
|
|
1259
|
+
const renderPageToBlob = async (page, scale, storeThumbnails) => {
|
|
1260
|
+
const raw = page.getViewport({ scale: 1 });
|
|
1261
|
+
const adjustedScale = Math.round(raw.width * scale) / raw.width;
|
|
1262
|
+
const viewport = page.getViewport({ scale: adjustedScale });
|
|
1263
|
+
const width = Math.round(viewport.width);
|
|
1264
|
+
const height = Math.round(viewport.height);
|
|
1265
|
+
const canvas = new OffscreenCanvas(width, height);
|
|
1266
|
+
const canvasContext = canvas.getContext("2d");
|
|
1267
|
+
if (!canvasContext) {
|
|
1268
|
+
throw new Error("OffscreenCanvas 2D context unavailable");
|
|
1269
|
+
}
|
|
1270
|
+
canvasContext.imageSmoothingEnabled = true;
|
|
1271
|
+
canvasContext.imageSmoothingQuality = "high";
|
|
1272
|
+
await page.render({ canvasContext, viewport }).promise;
|
|
1273
|
+
const blob = await canvas.convertToBlob({ type: "image/png" });
|
|
1274
|
+
let thumbnailBlob;
|
|
1275
|
+
if (storeThumbnails) {
|
|
1276
|
+
const thumbScale = Math.min(1, 256 / Math.max(width, height));
|
|
1277
|
+
const thumbnailWidth = Math.max(1, Math.round(width * thumbScale));
|
|
1278
|
+
const thumbnailHeight = Math.max(1, Math.round(height * thumbScale));
|
|
1279
|
+
const thumbnailCanvas = new OffscreenCanvas(thumbnailWidth, thumbnailHeight);
|
|
1280
|
+
const thumbnailContext = thumbnailCanvas.getContext("2d");
|
|
1281
|
+
if (thumbnailContext) {
|
|
1282
|
+
thumbnailContext.imageSmoothingEnabled = true;
|
|
1283
|
+
thumbnailContext.imageSmoothingQuality = "high";
|
|
1284
|
+
thumbnailContext.drawImage(canvas, 0, 0, thumbnailWidth, thumbnailHeight);
|
|
1285
|
+
}
|
|
1286
|
+
thumbnailBlob = await thumbnailCanvas.convertToBlob({ type: "image/png" });
|
|
1287
|
+
}
|
|
1288
|
+
return { blob, height, thumbnailBlob, width };
|
|
1289
|
+
};
|
|
1290
|
+
|
|
1291
|
+
self.onmessage = async (event) => {
|
|
1292
|
+
const message = event.data;
|
|
1293
|
+
if (!message || message.type !== "render") {
|
|
1294
|
+
return;
|
|
1295
|
+
}
|
|
1296
|
+
try {
|
|
1297
|
+
const pdfjs = await loadPdfJs(message.pdfjsModuleCandidates);
|
|
1298
|
+
const pdf = await pdfjs.getDocument({
|
|
1299
|
+
data: new Uint8Array(message.pdfData),
|
|
1300
|
+
disableWorker: true,
|
|
1301
|
+
}).promise;
|
|
1302
|
+
try {
|
|
1303
|
+
const pageNumbers = normalizePdfPageNumbers(message.pageNumbers, pdf.numPages);
|
|
1304
|
+
const bufferedPages = new Map();
|
|
1305
|
+
let nextEmitIndex = 0;
|
|
1306
|
+
let emitChain = Promise.resolve();
|
|
1307
|
+
const emitPageInOrder = async (pageNumber, renderedPage) => {
|
|
1308
|
+
bufferedPages.set(pageNumber, renderedPage);
|
|
1309
|
+
const flush = () => {
|
|
1310
|
+
while (nextEmitIndex < pageNumbers.length) {
|
|
1311
|
+
const nextPageNumber = pageNumbers[nextEmitIndex];
|
|
1312
|
+
if (nextPageNumber == null) break;
|
|
1313
|
+
const nextPage = bufferedPages.get(nextPageNumber);
|
|
1314
|
+
if (!nextPage) break;
|
|
1315
|
+
bufferedPages.delete(nextPageNumber);
|
|
1316
|
+
nextEmitIndex += 1;
|
|
1317
|
+
self.postMessage({
|
|
1318
|
+
type: "page",
|
|
1319
|
+
page: {
|
|
1320
|
+
...nextPage,
|
|
1321
|
+
pageNumber: nextPageNumber,
|
|
1322
|
+
},
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1325
|
+
};
|
|
1326
|
+
const nextChain = emitChain.then(flush, flush);
|
|
1327
|
+
emitChain = nextChain.catch(() => {});
|
|
1328
|
+
await nextChain;
|
|
1329
|
+
};
|
|
1330
|
+
await runWithConcurrency(
|
|
1331
|
+
pageNumbers,
|
|
1332
|
+
message.pageConcurrency,
|
|
1333
|
+
async (pageNumber) => {
|
|
1334
|
+
const page = await pdf.getPage(pageNumber);
|
|
1335
|
+
try {
|
|
1336
|
+
const renderedPage = await renderPageToBlob(
|
|
1337
|
+
page,
|
|
1338
|
+
message.scale,
|
|
1339
|
+
message.storeThumbnails,
|
|
1340
|
+
);
|
|
1341
|
+
await emitPageInOrder(pageNumber, renderedPage);
|
|
1342
|
+
} finally {
|
|
1343
|
+
page.cleanup();
|
|
1344
|
+
}
|
|
1345
|
+
},
|
|
1346
|
+
);
|
|
1347
|
+
await emitChain;
|
|
1348
|
+
} finally {
|
|
1349
|
+
await pdf.destroy();
|
|
1350
|
+
}
|
|
1351
|
+
self.postMessage({ type: "done" });
|
|
1352
|
+
} catch (error) {
|
|
1353
|
+
self.postMessage({ type: "error", error: createErrorPayload(error) });
|
|
1354
|
+
}
|
|
1355
|
+
};
|
|
1356
|
+
`;
|
|
1357
|
+
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
1358
|
+
var hasObjectMembers = (value) => (typeof value === "object" || typeof value === "function") && value !== null;
|
|
1359
|
+
var isOffscreenCanvasCandidate = (value) => typeof value === "function";
|
|
1360
|
+
var getEnvironmentRecord = (environment) => isRecord(environment) ? environment : null;
|
|
1361
|
+
var canUsePdfWorkerRenderer = (environment = globalThis) => {
|
|
1362
|
+
const candidateEnvironment = getEnvironmentRecord(environment);
|
|
1363
|
+
if (!candidateEnvironment) return false;
|
|
1364
|
+
if (typeof candidateEnvironment.Worker !== "function") return false;
|
|
1365
|
+
if (typeof candidateEnvironment.Blob !== "function") return false;
|
|
1366
|
+
if (!isOffscreenCanvasCandidate(candidateEnvironment.OffscreenCanvas)) {
|
|
1367
|
+
return false;
|
|
1368
|
+
}
|
|
1369
|
+
const urlCandidate = candidateEnvironment.URL;
|
|
1370
|
+
if (!hasObjectMembers(urlCandidate)) return false;
|
|
1371
|
+
if (typeof urlCandidate.createObjectURL !== "function") return false;
|
|
1372
|
+
if (typeof urlCandidate.revokeObjectURL !== "function") return false;
|
|
1373
|
+
try {
|
|
1374
|
+
const canvas = new candidateEnvironment.OffscreenCanvas(1, 1);
|
|
1375
|
+
return typeof canvas.getContext === "function" && typeof canvas.convertToBlob === "function";
|
|
1376
|
+
} catch {
|
|
1377
|
+
return false;
|
|
1378
|
+
}
|
|
1379
|
+
};
|
|
1380
|
+
var createAbortError = () => new DOMException("Aborted", "AbortError");
|
|
1381
|
+
var throwIfAborted = (signal) => {
|
|
1382
|
+
if (signal?.aborted) {
|
|
1383
|
+
throw createAbortError();
|
|
1384
|
+
}
|
|
1385
|
+
};
|
|
1386
|
+
var createPdfWorker = () => {
|
|
1387
|
+
const workerBlob = new Blob([PDF_WORKER_SOURCE], {
|
|
1388
|
+
type: "text/javascript"
|
|
1389
|
+
});
|
|
1390
|
+
const workerUrl = URL.createObjectURL(workerBlob);
|
|
1391
|
+
try {
|
|
1392
|
+
const worker = new Worker(workerUrl, {
|
|
1393
|
+
name: "canvu-pdf-renderer",
|
|
1394
|
+
type: "module"
|
|
1395
|
+
});
|
|
1396
|
+
return {
|
|
1397
|
+
release: () => URL.revokeObjectURL(workerUrl),
|
|
1398
|
+
worker
|
|
1399
|
+
};
|
|
1400
|
+
} catch (error) {
|
|
1401
|
+
URL.revokeObjectURL(workerUrl);
|
|
1402
|
+
throw error;
|
|
1403
|
+
}
|
|
1404
|
+
};
|
|
1405
|
+
var createWorkerError = (message) => {
|
|
1406
|
+
const error = new Error(message.error.message);
|
|
1407
|
+
error.name = message.error.name;
|
|
1408
|
+
error.stack = message.error.stack;
|
|
1409
|
+
return error;
|
|
1410
|
+
};
|
|
1411
|
+
var PACKAGED_PDFJS_MODULE_FILE = "./pdf.mjs";
|
|
1412
|
+
var PACKAGED_PDFJS_WORKER_FILE = "./pdf.worker.mjs";
|
|
1413
|
+
var resolveRelativeAssetUrl = (path, baseUrl) => new URL(path, baseUrl).toString();
|
|
1414
|
+
var resolvePackagedPdfJsModuleCandidate = (baseUrl = (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('react.cjs', document.baseURI).href))) => ({
|
|
1415
|
+
moduleUrl: resolveRelativeAssetUrl(PACKAGED_PDFJS_MODULE_FILE, baseUrl),
|
|
1416
|
+
workerUrl: resolveRelativeAssetUrl(PACKAGED_PDFJS_WORKER_FILE, baseUrl)
|
|
1417
|
+
});
|
|
1418
|
+
var resolveBundledPdfJsModuleCandidate = () => ({
|
|
1419
|
+
moduleUrl: new URL("pdfjs-dist/build/pdf.min.mjs", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('react.cjs', document.baseURI).href))).toString(),
|
|
1420
|
+
workerUrl: new URL(
|
|
1421
|
+
"pdfjs-dist/build/pdf.worker.min.mjs",
|
|
1422
|
+
(typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('react.cjs', document.baseURI).href))
|
|
1423
|
+
).toString()
|
|
1424
|
+
});
|
|
1425
|
+
var resolvePdfJsModuleCandidates = () => [
|
|
1426
|
+
resolvePackagedPdfJsModuleCandidate(),
|
|
1427
|
+
resolveBundledPdfJsModuleCandidate()
|
|
1428
|
+
];
|
|
1429
|
+
var loadPdfToStoreWithWorker = async (file, store, options) => {
|
|
1430
|
+
throwIfAborted(options.signal);
|
|
1431
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
1432
|
+
throwIfAborted(options.signal);
|
|
1433
|
+
return await new Promise((resolve, reject) => {
|
|
1434
|
+
const { release, worker } = createPdfWorker();
|
|
1435
|
+
const pageResults = [];
|
|
1436
|
+
let storeChain = Promise.resolve();
|
|
1437
|
+
let cleanedUp = false;
|
|
1438
|
+
let settled = false;
|
|
1439
|
+
const cleanup = () => {
|
|
1440
|
+
if (cleanedUp) return;
|
|
1441
|
+
cleanedUp = true;
|
|
1442
|
+
options.signal?.removeEventListener("abort", abortWorker);
|
|
1443
|
+
worker.onmessage = null;
|
|
1444
|
+
worker.onerror = null;
|
|
1445
|
+
worker.terminate();
|
|
1446
|
+
release();
|
|
1447
|
+
};
|
|
1448
|
+
const rejectOnce = (error) => {
|
|
1449
|
+
if (settled) return;
|
|
1450
|
+
settled = true;
|
|
1451
|
+
cleanup();
|
|
1452
|
+
reject(error);
|
|
1453
|
+
};
|
|
1454
|
+
const rejectAfterQueuedStores = (error) => {
|
|
1455
|
+
if (settled) return;
|
|
1456
|
+
cleanup();
|
|
1457
|
+
storeChain.then(() => {
|
|
1458
|
+
if (settled) return;
|
|
1459
|
+
settled = true;
|
|
1460
|
+
reject(error);
|
|
1461
|
+
}).catch(rejectOnce);
|
|
1462
|
+
};
|
|
1463
|
+
function abortWorker() {
|
|
1464
|
+
rejectOnce(createAbortError());
|
|
1465
|
+
}
|
|
1466
|
+
const storePage = (message) => {
|
|
1467
|
+
try {
|
|
1468
|
+
options.onPageReceived?.({ pageNumber: message.page.pageNumber });
|
|
1469
|
+
} catch (error) {
|
|
1470
|
+
rejectOnce(error);
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
storeChain = storeChain.then(async () => {
|
|
1474
|
+
throwIfAborted(options.signal);
|
|
1475
|
+
const blobId = await store.storeOriginal(message.page.blob);
|
|
1476
|
+
throwIfAborted(options.signal);
|
|
1477
|
+
const thumbnailBlobId = options.storeThumbnails && message.page.thumbnailBlob ? await store.storeThumbnail(message.page.thumbnailBlob) : "";
|
|
1478
|
+
throwIfAborted(options.signal);
|
|
1479
|
+
const pageResult = {
|
|
1480
|
+
blobId,
|
|
1481
|
+
height: message.page.height,
|
|
1482
|
+
pageNumber: message.page.pageNumber,
|
|
1483
|
+
thumbnailBlobId,
|
|
1484
|
+
width: message.page.width
|
|
1485
|
+
};
|
|
1486
|
+
pageResults.push(pageResult);
|
|
1487
|
+
await options.onPageStored?.(pageResult);
|
|
1488
|
+
throwIfAborted(options.signal);
|
|
1489
|
+
});
|
|
1490
|
+
void storeChain.catch(rejectOnce);
|
|
1491
|
+
};
|
|
1492
|
+
worker.onmessage = (event) => {
|
|
1493
|
+
const message = event.data;
|
|
1494
|
+
if (message.type === "page") {
|
|
1495
|
+
storePage(message);
|
|
1496
|
+
return;
|
|
1497
|
+
}
|
|
1498
|
+
if (message.type === "error") {
|
|
1499
|
+
rejectAfterQueuedStores(createWorkerError(message));
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
storeChain.then(() => {
|
|
1503
|
+
if (settled) return;
|
|
1504
|
+
settled = true;
|
|
1505
|
+
cleanup();
|
|
1506
|
+
resolve(pageResults);
|
|
1507
|
+
}).catch(rejectOnce);
|
|
1508
|
+
};
|
|
1509
|
+
worker.onerror = (event) => {
|
|
1510
|
+
rejectAfterQueuedStores(event.error ?? new Error(event.message));
|
|
1511
|
+
};
|
|
1512
|
+
options.signal?.addEventListener("abort", abortWorker, { once: true });
|
|
1513
|
+
try {
|
|
1514
|
+
worker.postMessage(
|
|
1515
|
+
{
|
|
1516
|
+
pdfData: arrayBuffer,
|
|
1517
|
+
pdfjsModuleCandidates: resolvePdfJsModuleCandidates(),
|
|
1518
|
+
pageNumbers: options.pageNumbers ? [...options.pageNumbers] : void 0,
|
|
1519
|
+
pageConcurrency: options.pageConcurrency,
|
|
1520
|
+
scale: options.scale,
|
|
1521
|
+
storeThumbnails: options.storeThumbnails,
|
|
1522
|
+
type: "render"
|
|
1523
|
+
},
|
|
1524
|
+
[arrayBuffer]
|
|
1525
|
+
);
|
|
1526
|
+
} catch (error) {
|
|
1527
|
+
rejectOnce(error);
|
|
1528
|
+
}
|
|
1529
|
+
});
|
|
1530
|
+
};
|
|
1531
|
+
|
|
1196
1532
|
// src/image/pdf-loader.ts
|
|
1197
1533
|
var pdfjsPromise = null;
|
|
1198
1534
|
function getPdfJs() {
|
|
@@ -1209,7 +1545,7 @@ function getPdfJs() {
|
|
|
1209
1545
|
return pdfjsPromise;
|
|
1210
1546
|
}
|
|
1211
1547
|
async function renderPageToCanvas(page, scale, signal) {
|
|
1212
|
-
|
|
1548
|
+
throwIfAborted2(signal);
|
|
1213
1549
|
const raw = page.getViewport({ scale: 1 });
|
|
1214
1550
|
const adjustedScale = Math.round(raw.width * scale) / raw.width;
|
|
1215
1551
|
const viewport = page.getViewport({ scale: adjustedScale });
|
|
@@ -1231,7 +1567,7 @@ async function renderPageToCanvas(page, scale, signal) {
|
|
|
1231
1567
|
try {
|
|
1232
1568
|
await renderTask.promise;
|
|
1233
1569
|
} catch (error) {
|
|
1234
|
-
if (signal.aborted) throw
|
|
1570
|
+
if (signal.aborted) throw createAbortError2();
|
|
1235
1571
|
throw error;
|
|
1236
1572
|
} finally {
|
|
1237
1573
|
signal.removeEventListener("abort", abortRender);
|
|
@@ -1239,15 +1575,15 @@ async function renderPageToCanvas(page, scale, signal) {
|
|
|
1239
1575
|
} else {
|
|
1240
1576
|
await renderTask.promise;
|
|
1241
1577
|
}
|
|
1242
|
-
|
|
1578
|
+
throwIfAborted2(signal);
|
|
1243
1579
|
return { canvas, width: w, height: h };
|
|
1244
1580
|
}
|
|
1245
|
-
function
|
|
1581
|
+
function createAbortError2() {
|
|
1246
1582
|
return new DOMException("Aborted", "AbortError");
|
|
1247
1583
|
}
|
|
1248
|
-
function
|
|
1584
|
+
function throwIfAborted2(signal) {
|
|
1249
1585
|
if (signal?.aborted) {
|
|
1250
|
-
throw
|
|
1586
|
+
throw createAbortError2();
|
|
1251
1587
|
}
|
|
1252
1588
|
}
|
|
1253
1589
|
function normalizePdfPageNumbers(pageNumbers, pageCount) {
|
|
@@ -1263,7 +1599,7 @@ async function runWithConcurrency(items, concurrency, execute, signal) {
|
|
|
1263
1599
|
await Promise.all(
|
|
1264
1600
|
Array.from({ length: workerCount }, async () => {
|
|
1265
1601
|
while (nextIndex < items.length) {
|
|
1266
|
-
|
|
1602
|
+
throwIfAborted2(signal);
|
|
1267
1603
|
const currentIndex = nextIndex;
|
|
1268
1604
|
nextIndex += 1;
|
|
1269
1605
|
const item = items[currentIndex];
|
|
@@ -1271,7 +1607,7 @@ async function runWithConcurrency(items, concurrency, execute, signal) {
|
|
|
1271
1607
|
continue;
|
|
1272
1608
|
}
|
|
1273
1609
|
results[currentIndex] = await execute(item);
|
|
1274
|
-
|
|
1610
|
+
throwIfAborted2(signal);
|
|
1275
1611
|
}
|
|
1276
1612
|
})
|
|
1277
1613
|
);
|
|
@@ -1282,11 +1618,52 @@ async function loadPdfToStore(file, store, options) {
|
|
|
1282
1618
|
const pageConcurrency = options?.pageConcurrency ?? 2;
|
|
1283
1619
|
const storeThumbnails = options?.storeThumbnails ?? false;
|
|
1284
1620
|
const signal = options?.signal;
|
|
1285
|
-
|
|
1621
|
+
throwIfAborted2(signal);
|
|
1622
|
+
if (canUsePdfWorkerRenderer()) {
|
|
1623
|
+
let workerPageCount = 0;
|
|
1624
|
+
try {
|
|
1625
|
+
return await loadPdfToStoreWithWorker(file, store, {
|
|
1626
|
+
scale,
|
|
1627
|
+
pageNumbers: options?.pageNumbers,
|
|
1628
|
+
pageConcurrency,
|
|
1629
|
+
storeThumbnails,
|
|
1630
|
+
signal,
|
|
1631
|
+
onPageReceived: () => {
|
|
1632
|
+
workerPageCount += 1;
|
|
1633
|
+
},
|
|
1634
|
+
onPageStored: async (page) => {
|
|
1635
|
+
await options?.onPageStored?.(page);
|
|
1636
|
+
}
|
|
1637
|
+
});
|
|
1638
|
+
} catch (error) {
|
|
1639
|
+
if (signal?.aborted || workerPageCount > 0) {
|
|
1640
|
+
throw error;
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
return await loadPdfToStoreOnMainThread(file, store, {
|
|
1645
|
+
scale,
|
|
1646
|
+
pageNumbers: options?.pageNumbers,
|
|
1647
|
+
pageConcurrency,
|
|
1648
|
+
storeThumbnails,
|
|
1649
|
+
signal,
|
|
1650
|
+
onPageStored: options?.onPageStored
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
async function loadPdfToStoreOnMainThread(file, store, options) {
|
|
1654
|
+
const {
|
|
1655
|
+
pageConcurrency,
|
|
1656
|
+
scale,
|
|
1657
|
+
signal,
|
|
1658
|
+
storeThumbnails,
|
|
1659
|
+
onPageStored,
|
|
1660
|
+
pageNumbers
|
|
1661
|
+
} = options;
|
|
1662
|
+
throwIfAborted2(signal);
|
|
1286
1663
|
const pdfjs = await getPdfJs();
|
|
1287
|
-
|
|
1664
|
+
throwIfAborted2(signal);
|
|
1288
1665
|
const arrayBuffer = await file.arrayBuffer();
|
|
1289
|
-
|
|
1666
|
+
throwIfAborted2(signal);
|
|
1290
1667
|
const loadingTask = pdfjs.getDocument({ data: arrayBuffer });
|
|
1291
1668
|
if (signal) {
|
|
1292
1669
|
const abortLoading = () => {
|
|
@@ -1298,14 +1675,14 @@ async function loadPdfToStore(file, store, options) {
|
|
|
1298
1675
|
signal.removeEventListener("abort", abortLoading);
|
|
1299
1676
|
return await loadPdfDocumentToStore(pdf2, store, {
|
|
1300
1677
|
scale,
|
|
1301
|
-
pageNumbers
|
|
1678
|
+
pageNumbers,
|
|
1302
1679
|
pageConcurrency,
|
|
1303
1680
|
storeThumbnails,
|
|
1304
1681
|
signal,
|
|
1305
|
-
onPageStored
|
|
1682
|
+
onPageStored
|
|
1306
1683
|
});
|
|
1307
1684
|
} catch (error) {
|
|
1308
|
-
if (signal.aborted) throw
|
|
1685
|
+
if (signal.aborted) throw createAbortError2();
|
|
1309
1686
|
throw error;
|
|
1310
1687
|
} finally {
|
|
1311
1688
|
signal.removeEventListener("abort", abortLoading);
|
|
@@ -1314,16 +1691,16 @@ async function loadPdfToStore(file, store, options) {
|
|
|
1314
1691
|
const pdf = await loadingTask.promise;
|
|
1315
1692
|
return await loadPdfDocumentToStore(pdf, store, {
|
|
1316
1693
|
scale,
|
|
1317
|
-
pageNumbers
|
|
1694
|
+
pageNumbers,
|
|
1318
1695
|
pageConcurrency,
|
|
1319
1696
|
storeThumbnails,
|
|
1320
|
-
onPageStored
|
|
1697
|
+
onPageStored
|
|
1321
1698
|
});
|
|
1322
1699
|
}
|
|
1323
1700
|
async function loadPdfDocumentToStore(pdf, store, options) {
|
|
1324
1701
|
const { pageConcurrency, scale, signal } = options;
|
|
1325
1702
|
const storeThumbnails = options.storeThumbnails ?? false;
|
|
1326
|
-
|
|
1703
|
+
throwIfAborted2(signal);
|
|
1327
1704
|
const pageNumbers = normalizePdfPageNumbers(options?.pageNumbers, pdf.numPages);
|
|
1328
1705
|
const bufferedResults = /* @__PURE__ */ new Map();
|
|
1329
1706
|
let nextEmitIndex = 0;
|
|
@@ -1338,9 +1715,9 @@ async function loadPdfDocumentToStore(pdf, store, options) {
|
|
|
1338
1715
|
if (!bufferedResult) break;
|
|
1339
1716
|
bufferedResults.delete(nextPageNumber);
|
|
1340
1717
|
nextEmitIndex += 1;
|
|
1341
|
-
|
|
1718
|
+
throwIfAborted2(signal);
|
|
1342
1719
|
await options?.onPageStored?.(bufferedResult);
|
|
1343
|
-
|
|
1720
|
+
throwIfAborted2(signal);
|
|
1344
1721
|
}
|
|
1345
1722
|
};
|
|
1346
1723
|
const nextChain = emitChain.then(run, run);
|
|
@@ -1352,20 +1729,20 @@ async function loadPdfDocumentToStore(pdf, store, options) {
|
|
|
1352
1729
|
pageNumbers,
|
|
1353
1730
|
pageConcurrency,
|
|
1354
1731
|
async (pageNumber) => {
|
|
1355
|
-
|
|
1732
|
+
throwIfAborted2(signal);
|
|
1356
1733
|
const page = await pdf.getPage(pageNumber);
|
|
1357
|
-
|
|
1734
|
+
throwIfAborted2(signal);
|
|
1358
1735
|
const { canvas, width, height } = await renderPageToCanvas(
|
|
1359
1736
|
page,
|
|
1360
1737
|
scale,
|
|
1361
1738
|
signal
|
|
1362
1739
|
);
|
|
1363
|
-
|
|
1740
|
+
throwIfAborted2(signal);
|
|
1364
1741
|
const mime = "image/png";
|
|
1365
1742
|
const pageBlob = await encodeCanvasToBlob(canvas, { mimeType: mime });
|
|
1366
|
-
|
|
1743
|
+
throwIfAborted2(signal);
|
|
1367
1744
|
const blobId = await store.storeOriginal(pageBlob);
|
|
1368
|
-
|
|
1745
|
+
throwIfAborted2(signal);
|
|
1369
1746
|
const thumbnailBlobId = storeThumbnails ? await (async () => {
|
|
1370
1747
|
const thumbScale = Math.min(1, 256 / Math.max(width, height));
|
|
1371
1748
|
const tw = Math.max(1, Math.round(width * thumbScale));
|
|
@@ -1382,7 +1759,7 @@ async function loadPdfDocumentToStore(pdf, store, options) {
|
|
|
1382
1759
|
const thumbBlob = await encodeCanvasToBlob(thumbCanvas, {
|
|
1383
1760
|
mimeType: mime
|
|
1384
1761
|
});
|
|
1385
|
-
|
|
1762
|
+
throwIfAborted2(signal);
|
|
1386
1763
|
return await store.storeThumbnail(thumbBlob);
|
|
1387
1764
|
})() : "";
|
|
1388
1765
|
const pageResult = {
|
|
@@ -1736,22 +2113,22 @@ function finalizeIngestedItem(item, context, uploadResult, decorateItem) {
|
|
|
1736
2113
|
const itemWithAssetData = applyAssetUploadResultToItem(item, uploadResult);
|
|
1737
2114
|
return decorateItem ? decorateItem(itemWithAssetData, context) : itemWithAssetData;
|
|
1738
2115
|
}
|
|
1739
|
-
function
|
|
2116
|
+
function createAbortError3() {
|
|
1740
2117
|
return new DOMException("Aborted", "AbortError");
|
|
1741
2118
|
}
|
|
1742
|
-
function
|
|
2119
|
+
function throwIfAborted3(signal) {
|
|
1743
2120
|
if (signal?.aborted) {
|
|
1744
|
-
throw
|
|
2121
|
+
throw createAbortError3();
|
|
1745
2122
|
}
|
|
1746
2123
|
}
|
|
1747
2124
|
function isAbortError(error) {
|
|
1748
2125
|
return (error instanceof DOMException || error instanceof Error) && error.name === "AbortError";
|
|
1749
2126
|
}
|
|
1750
2127
|
async function uploadAssetIfNeeded(assetStore, file, kind, signal) {
|
|
1751
|
-
|
|
2128
|
+
throwIfAborted3(signal);
|
|
1752
2129
|
if (!assetStore) return null;
|
|
1753
2130
|
const result = await assetStore.upload({ file, kind, signal });
|
|
1754
|
-
|
|
2131
|
+
throwIfAborted3(signal);
|
|
1755
2132
|
return result ?? null;
|
|
1756
2133
|
}
|
|
1757
2134
|
async function ingestAssetFilesToSceneItems(options) {
|
|
@@ -1774,7 +2151,7 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1774
2151
|
const errors = [];
|
|
1775
2152
|
let occupiedBottomY = existingItems.length > 0 ? Math.max(...existingItems.map((item) => item.bounds.y + item.bounds.height)) : null;
|
|
1776
2153
|
for (const file of files) {
|
|
1777
|
-
|
|
2154
|
+
throwIfAborted3(signal);
|
|
1778
2155
|
const kind = getAssetKindForFile(file);
|
|
1779
2156
|
if (!kind) {
|
|
1780
2157
|
const error = {
|
|
@@ -1800,10 +2177,10 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1800
2177
|
storeThumbnails: false,
|
|
1801
2178
|
signal,
|
|
1802
2179
|
onPageStored: async (page) => {
|
|
1803
|
-
|
|
2180
|
+
throwIfAborted3(signal);
|
|
1804
2181
|
const uploadResult2 = await uploadResultPromise;
|
|
1805
2182
|
const fullUrl2 = await createBlobUrlFromStore(imageStore, page.blobId);
|
|
1806
|
-
|
|
2183
|
+
throwIfAborted3(signal);
|
|
1807
2184
|
const naturalTopY2 = worldCenter.y - page.height / 2;
|
|
1808
2185
|
const stackedTopY2 = occupiedBottomY == null ? naturalTopY2 : occupiedBottomY + gapWorld;
|
|
1809
2186
|
const bounds2 = {
|
|
@@ -1843,18 +2220,18 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1843
2220
|
);
|
|
1844
2221
|
items.push(item2);
|
|
1845
2222
|
occupiedBottomY = bounds2.y + page.height;
|
|
1846
|
-
|
|
2223
|
+
throwIfAborted3(signal);
|
|
1847
2224
|
onItemsReady?.([item2], { file, kind });
|
|
1848
2225
|
}
|
|
1849
2226
|
});
|
|
1850
2227
|
continue;
|
|
1851
2228
|
}
|
|
1852
|
-
|
|
2229
|
+
throwIfAborted3(signal);
|
|
1853
2230
|
const [uploadResult, storedImage] = await Promise.all([
|
|
1854
2231
|
uploadAssetIfNeeded(assetStore, file, kind, signal),
|
|
1855
2232
|
loadImageToStore(file, imageStore)
|
|
1856
2233
|
]);
|
|
1857
|
-
|
|
2234
|
+
throwIfAborted3(signal);
|
|
1858
2235
|
const { blobId, thumbnailBlobId, width, height } = storedImage;
|
|
1859
2236
|
const fullUrl = await createBlobUrlFromStore(imageStore, blobId);
|
|
1860
2237
|
const thumbBlob = await imageStore.getThumbnail(thumbnailBlobId);
|
|
@@ -1892,7 +2269,7 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1892
2269
|
decorateItem
|
|
1893
2270
|
);
|
|
1894
2271
|
items.push(item);
|
|
1895
|
-
|
|
2272
|
+
throwIfAborted3(signal);
|
|
1896
2273
|
onItemsReady?.([item], { file, kind });
|
|
1897
2274
|
occupiedBottomY = occupiedBottomY == null ? bounds.y + height : Math.max(occupiedBottomY, bounds.y + height);
|
|
1898
2275
|
} catch (error) {
|