unpdf 1.6.2 → 1.7.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/dist/index.mjs CHANGED
@@ -55,7 +55,9 @@ async function getDocumentProxy(data, options = {}) {
55
55
  const base = import.meta.resolve("pdfjs-dist/package.json");
56
56
  nodeDefaults = {
57
57
  disableFontFace: true,
58
- standardFontDataUrl: new URL("./standard_fonts/", base).href
58
+ standardFontDataUrl: new URL("./standard_fonts/", base).href,
59
+ cMapUrl: new URL("./cmaps/", base).href,
60
+ cMapPacked: true
59
61
  };
60
62
  } catch {
61
63
  }
@@ -70,6 +72,15 @@ async function getDocumentProxy(data, options = {}) {
70
72
  }).promise;
71
73
  return pdf;
72
74
  }
75
+ async function withDocument(data, operation, options) {
76
+ const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data, options);
77
+ try {
78
+ return await operation(pdf);
79
+ } finally {
80
+ if (pdf !== data)
81
+ await pdf.destroy();
82
+ }
83
+ }
73
84
  async function getResolvedPDFJS() {
74
85
  if (!resolvedModule) {
75
86
  await resolvePDFJSImport();
@@ -175,6 +186,7 @@ class NodeCanvasFactory extends BaseCanvasFactory {
175
186
  }
176
187
  async function resolveCanvasModule(canvasImport) {
177
188
  resolvedCanvasModule ??= await interopDefault(canvasImport());
189
+ globalThis[Symbol.for("unpdf.canvasModule")] = resolvedCanvasModule;
178
190
  }
179
191
  function injectCanvasConstructors() {
180
192
  if (!resolvedCanvasModule)
@@ -187,69 +199,85 @@ function injectCanvasConstructors() {
187
199
  }
188
200
 
189
201
  async function extractImages$1(data, pageNumber) {
190
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
191
- if (pageNumber < 1 || pageNumber > pdf.numPages) {
192
- throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
193
- }
194
- const page = await pdf.getPage(pageNumber);
195
- const operatorList = await page.getOperatorList();
196
- const { OPS } = await getResolvedPDFJS();
197
- const images = [];
198
- for (let i = 0; i < operatorList.fnArray.length; i++) {
199
- const op = operatorList.fnArray[i];
200
- if (op !== OPS.paintImageXObject) {
201
- continue;
202
- }
203
- const imageKey = operatorList.argsArray[i][0];
204
- const image = await new Promise(
205
- (resolve) => (imageKey.startsWith("g_") ? page.commonObjs : page.objs).get(imageKey, resolve)
206
- );
207
- if (!image || !image.data || !image.width || !image.height) {
208
- continue;
202
+ return await withDocument(data, async (pdf) => {
203
+ if (pageNumber < 1 || pageNumber > pdf.numPages) {
204
+ throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
209
205
  }
210
- const { width, height, data: data2 } = image;
211
- const calculatedChannels = data2.length / (width * height);
212
- if (![1, 3, 4].includes(calculatedChannels)) {
213
- continue;
206
+ const page = await pdf.getPage(pageNumber);
207
+ const operatorList = await page.getOperatorList();
208
+ const { OPS } = await getResolvedPDFJS();
209
+ const images = [];
210
+ for (let i = 0; i < operatorList.fnArray.length; i++) {
211
+ const op = operatorList.fnArray[i];
212
+ if (op !== OPS.paintImageXObject) {
213
+ continue;
214
+ }
215
+ const imageKey = operatorList.argsArray[i][0];
216
+ const image = await new Promise(
217
+ (resolve) => (imageKey.startsWith("g_") ? page.commonObjs : page.objs).get(imageKey, resolve)
218
+ );
219
+ if (!image || !image.data || !image.width || !image.height) {
220
+ continue;
221
+ }
222
+ const { width, height, data: data2 } = image;
223
+ const calculatedChannels = data2.length / (width * height);
224
+ if (![1, 3, 4].includes(calculatedChannels)) {
225
+ continue;
226
+ }
227
+ const channels = calculatedChannels;
228
+ images.push({
229
+ data: data2,
230
+ width,
231
+ height,
232
+ channels,
233
+ key: imageKey
234
+ });
214
235
  }
215
- const channels = calculatedChannels;
216
- images.push({
217
- data: data2,
218
- width,
219
- height,
220
- channels,
221
- key: imageKey
222
- });
223
- }
224
- return images;
236
+ return images;
237
+ });
225
238
  }
226
239
  async function renderPageAsImage$1(data, pageNumber, options = {}) {
227
240
  const CanvasFactory = await createIsomorphicCanvasFactory(options.canvasImport);
228
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data, { CanvasFactory });
229
- const page = await pdf.getPage(pageNumber);
230
- if (pageNumber < 1 || pageNumber > pdf.numPages) {
231
- throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
232
- }
233
- const defaultViewport = page.getViewport({ scale: 1 });
234
- let scale = options.scale || 1;
235
- if (options.width) {
236
- scale = options.width / defaultViewport.width;
237
- } else if (options.height) {
238
- scale = options.height / defaultViewport.height;
239
- }
240
- const viewport = page.getViewport({ scale: Math.max(0, scale) });
241
- const drawingContext = new CanvasFactory().create(viewport.width, viewport.height);
242
- await page.render({
243
- canvas: drawingContext.canvas,
244
- canvasContext: drawingContext.context,
245
- viewport
246
- }).promise;
247
- const dataUrl = drawingContext.canvas.toDataURL();
248
- if (options.toDataURL) {
249
- return dataUrl;
250
- }
251
- const response = await fetch(dataUrl);
252
- return await response.arrayBuffer();
241
+ return await withDocument(data, async (pdf) => {
242
+ if (pageNumber < 1 || pageNumber > pdf.numPages) {
243
+ throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
244
+ }
245
+ const page = await pdf.getPage(pageNumber);
246
+ const defaultViewport = page.getViewport({ scale: 1 });
247
+ let scale = options.scale || 1;
248
+ if (options.width) {
249
+ scale = options.width / defaultViewport.width;
250
+ } else if (options.height) {
251
+ scale = options.height / defaultViewport.height;
252
+ }
253
+ const viewport = page.getViewport({ scale: Math.max(0, scale) });
254
+ const canvasFactory = new CanvasFactory();
255
+ const drawingContext = canvasFactory.create(viewport.width, viewport.height);
256
+ try {
257
+ await page.render({
258
+ canvas: drawingContext.canvas,
259
+ canvasContext: drawingContext.context,
260
+ viewport
261
+ }).promise;
262
+ const { canvas } = drawingContext;
263
+ if (options.toDataURL) {
264
+ return canvas.toDataURL();
265
+ }
266
+ if ("encode" in canvas) {
267
+ const buffer = await canvas.encode("png");
268
+ return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
269
+ }
270
+ const blob = await new Promise((resolve) => {
271
+ canvas.toBlob(resolve);
272
+ });
273
+ if (!blob) {
274
+ throw new Error("Failed to encode canvas to a PNG blob.");
275
+ }
276
+ return await blob.arrayBuffer();
277
+ } finally {
278
+ canvasFactory.destroy(drawingContext);
279
+ }
280
+ }, { CanvasFactory });
253
281
  }
254
282
  async function createIsomorphicCanvasFactory(canvasImport) {
255
283
  if (isBrowser)
@@ -266,14 +294,15 @@ async function createIsomorphicCanvasFactory(canvasImport) {
266
294
  }
267
295
 
268
296
  async function extractLinks$1(data) {
269
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
270
- const pageLinks = await Promise.all(
271
- Array.from({ length: pdf.numPages }, (_, i) => getPageLinks(pdf, i + 1))
272
- );
273
- return {
274
- totalPages: pdf.numPages,
275
- links: pageLinks.flat()
276
- };
297
+ return await withDocument(data, async (pdf) => {
298
+ const pageLinks = await Promise.all(
299
+ Array.from({ length: pdf.numPages }, (_, i) => getPageLinks(pdf, i + 1))
300
+ );
301
+ return {
302
+ totalPages: pdf.numPages,
303
+ links: pageLinks.flat()
304
+ };
305
+ });
277
306
  }
278
307
  async function getPageLinks(document, pageNumber) {
279
308
  const page = await document.getPage(pageNumber);
@@ -296,38 +325,39 @@ const XMP_DATE_PROPERTIES = [
296
325
  "xap:metadatadate"
297
326
  ];
298
327
  async function getMeta$1(data, options = {}) {
299
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
300
- const meta = await pdf.getMetadata();
301
- const info = meta?.info || {};
302
- if (options.parseDates) {
303
- const { PDFDateString } = await getResolvedPDFJS();
304
- if (info?.CreationDate) {
305
- info.CreationDate = PDFDateString.toDateObject(info?.CreationDate);
306
- }
307
- if (info?.ModDate) {
308
- info.ModDate = PDFDateString.toDateObject(info?.ModDate);
309
- }
310
- if (meta.metadata) {
311
- meta.metadata = new Proxy(meta.metadata, {
312
- get(target, prop) {
313
- if (prop === "get") {
314
- return (name) => {
315
- const value = target.get(name);
316
- if (XMP_DATE_PROPERTIES.includes(name) && value) {
317
- return parseISODateString(value);
318
- }
319
- return value;
320
- };
328
+ return await withDocument(data, async (pdf) => {
329
+ const meta = await pdf.getMetadata();
330
+ const info = meta?.info || {};
331
+ if (options.parseDates) {
332
+ const { PDFDateString } = await getResolvedPDFJS();
333
+ if (info?.CreationDate) {
334
+ info.CreationDate = PDFDateString.toDateObject(info?.CreationDate);
335
+ }
336
+ if (info?.ModDate) {
337
+ info.ModDate = PDFDateString.toDateObject(info?.ModDate);
338
+ }
339
+ if (meta.metadata) {
340
+ meta.metadata = new Proxy(meta.metadata, {
341
+ get(target, prop) {
342
+ if (prop === "get") {
343
+ return (name) => {
344
+ const value = target.get(name);
345
+ if (XMP_DATE_PROPERTIES.includes(name) && value) {
346
+ return parseISODateString(value);
347
+ }
348
+ return value;
349
+ };
350
+ }
351
+ return target[prop];
321
352
  }
322
- return target[prop];
323
- }
324
- });
353
+ });
354
+ }
325
355
  }
326
- }
327
- return {
328
- info,
329
- metadata: meta?.metadata || {}
330
- };
356
+ return {
357
+ info,
358
+ metadata: meta?.metadata || {}
359
+ };
360
+ });
331
361
  }
332
362
  function parseISODateString(isoDateString) {
333
363
  if (!isoDateString)
@@ -339,11 +369,12 @@ function parseISODateString(isoDateString) {
339
369
  }
340
370
 
341
371
  async function extractTextItems$1(data) {
342
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
343
- const items = await Promise.all(
344
- Array.from({ length: pdf.numPages }, (_, i) => getPageTextItems(pdf, i + 1))
345
- );
346
- return { totalPages: pdf.numPages, items };
372
+ return await withDocument(data, async (pdf) => {
373
+ const items = await Promise.all(
374
+ Array.from({ length: pdf.numPages }, (_, i) => getPageTextItems(pdf, i + 1))
375
+ );
376
+ return { totalPages: pdf.numPages, items };
377
+ });
347
378
  }
348
379
  async function getPageTextItems(document, pageNumber) {
349
380
  const page = await document.getPage(pageNumber);
@@ -366,20 +397,24 @@ async function getPageTextItems(document, pageNumber) {
366
397
  }
367
398
  async function extractText$1(data, options = {}) {
368
399
  const { mergePages = false } = options;
369
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
370
- const texts = await Promise.all(
371
- Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1))
372
- );
373
- return {
374
- totalPages: pdf.numPages,
375
- text: mergePages ? texts.join("\n").replace(/\s+/g, " ") : texts
376
- };
400
+ return await withDocument(data, async (pdf) => {
401
+ const texts = await Promise.all(
402
+ Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1))
403
+ );
404
+ return {
405
+ totalPages: pdf.numPages,
406
+ text: mergePages ? normalizeMergedText(texts) : texts
407
+ };
408
+ });
377
409
  }
378
410
  async function getPageText(document, pageNumber) {
379
411
  const page = await document.getPage(pageNumber);
380
412
  const content = await page.getTextContent();
381
413
  return content.items.filter((item) => item.str != null).map((item) => item.str + (item.hasEOL ? "\n" : "")).join("");
382
414
  }
415
+ function normalizeMergedText(texts) {
416
+ return texts.join("\n").replace(/[^\S\n]+/g, " ").replace(/ ?\n ?/g, "\n").replace(/\n{3,}/g, "\n\n");
417
+ }
383
418
 
384
419
  async function definePDFJSModule(pdfjs) {
385
420
  await resolvePDFJSImport(pdfjs, { reload: true });
package/dist/pdfjs.d.mts CHANGED
@@ -1 +1 @@
1
- export * from './types/src/pdf'
1
+ export * from './types/src/pdf.js'
package/dist/pdfjs.d.ts CHANGED
@@ -1 +1 @@
1
- export * from './types/src/pdf'
1
+ export * from './types/src/pdf.js'