unpdf 1.9.0 → 1.9.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/README.md CHANGED
@@ -1,16 +1,17 @@
1
1
  # unpdf
2
2
 
3
- Utilities for PDF extraction and rendering across all JavaScript runtimes – Node.js, Deno, Bun, the browser, and serverless environments like Cloudflare Workers. Especially useful for AI applications that need to summarize or analyze PDF documents.
3
+ Utilities for PDF extraction and rendering across all JavaScript runtimes – Node.js, Bun, the browser, and serverless environments like Cloudflare Workers. Especially useful for AI applications that need to summarize or analyze PDF documents.
4
4
 
5
5
  Ships with a serverless build of Mozilla's [PDF.js](https://github.com/mozilla/pdf.js), optimized for edge environments. If you're coming from [`pdf-parse`](https://www.npmjs.com/package/pdf-parse), `unpdf` is a modern, actively maintained alternative with broader runtime support.
6
6
 
7
7
  ## Features
8
8
 
9
- - 🏗️ Works in Node.js, browser and serverless environments
10
- - 🪭 Includes serverless build of PDF.js ([`unpdf/pdfjs`](./package.json))
11
- - 💬 Extract [text](#extract-text-from-pdf), [links](#extractlinks), and [images](#extractimages) from PDF files
9
+ - 🏗️ Works in Node.js 22+, Bun, browsers, and serverless environments ([Cloudflare Workers example](./examples/cloudflare))
10
+ - 🪭 Includes serverless build of PDF.js ([`unpdf/pdfjs`](#how-it-works))
11
+ - 💬 Extract [text](#extracttext), [positioned text](#extracttextitems), [links](#extractlinks), [images](#extractimages), and [metadata](#getmeta) from PDF files
12
+ - 🖼️ [Render pages as images](#renderpageasimage)
12
13
  - 🧠 Perfect for AI applications and PDF summarization
13
- - 🧱 Opt-in to official or legacy PDF.js build
14
+ - 🧱 Opt-in to a [custom PDF.js build](#custom-pdfjs-build)
14
15
 
15
16
  ## Installation
16
17
 
@@ -24,8 +25,6 @@ npm install unpdf
24
25
 
25
26
  ## Usage
26
27
 
27
- ### Extract Text From PDF
28
-
29
28
  ```ts
30
29
  import { extractText, getDocumentProxy } from 'unpdf'
31
30
 
@@ -40,54 +39,6 @@ console.log(`Total pages: ${totalPages}`)
40
39
  console.log(text)
41
40
  ```
42
41
 
43
- ### Official or Legacy PDF.js Build
44
-
45
- Usually you don't need to worry about the PDF.js build. `unpdf` ships with a serverless build of the latest PDF.js version. However, if you want to use the official PDF.js version or the legacy build, you can define a custom PDF.js module.
46
-
47
- > [!WARNING]
48
- > PDF.js v5.x uses `Promise.withResolvers`, which may not be supported in all environments, such as Node < 22. Consider using the bundled serverless build, which includes a polyfill, or use an older version of PDF.js.
49
-
50
- For example, if you want to use the official PDF.js build:
51
-
52
- ```ts
53
- import { definePDFJSModule, extractText, getDocumentProxy } from 'unpdf'
54
-
55
- // Define the PDF.js build before using any other unpdf method
56
- await definePDFJSModule(() => import('pdfjs-dist'))
57
-
58
- // Now, you can use all unpdf methods with the official PDF.js build
59
- const pdf = await getDocumentProxy(/* … */)
60
- const { text } = await extractText(pdf)
61
- ```
62
-
63
- ### PDF.js API
64
-
65
- `unpdf` provides helpful [methods](#api) to work with PDF files, such as `extractText` and `extractImages`, which should cover most use cases. However, if you need more control over the PDF.js API, you can use the `getResolvedPDFJS` method to get the resolved PDF.js module.
66
-
67
- Access the PDF.js API directly by calling `getResolvedPDFJS`:
68
-
69
- ```ts
70
- import { getResolvedPDFJS } from 'unpdf'
71
-
72
- const { version } = await getResolvedPDFJS()
73
- ```
74
-
75
- > [!NOTE]
76
- > If no other PDF.js build was defined, the serverless build will always be used.
77
-
78
- For example, you can use the `getDocument` method to load a PDF file and then use the `getMetadata` method to get the metadata of the PDF file:
79
-
80
- ```ts
81
- import { readFile } from 'node:fs/promises'
82
- import { getResolvedPDFJS } from 'unpdf'
83
-
84
- const { getDocument } = await getResolvedPDFJS()
85
- const data = await readFile('./dummy.pdf')
86
- const document = await getDocument(new Uint8Array(data)).promise
87
-
88
- console.log(await document.getMetadata())
89
- ```
90
-
91
42
  ## How It Works
92
43
 
93
44
  > [!NOTE]
@@ -97,13 +48,13 @@ Heart and soul of this package is the [`pdfjs.rolldown.config.ts`](./pdfjs.rolld
97
48
 
98
49
  - **String replacements** strip browser-specific references from the PDF.js source.
99
50
  - **Worker inlining** embeds the PDF.js worker directly into the main bundle, since serverless runtimes can't load separate worker files.
100
- - **Global polyfills** provide missing APIs like `Promise.withResolvers` and `FinalizationRegistry` (unavailable in Node.js < 22 and Cloudflare Workers, respectively).
51
+ - **Global polyfills** fill in newer APIs like `Promise.try` and `Map.prototype.getOrInsert` for runtimes that lack them, plus `FinalizationRegistry` for Cloudflare Workers.
101
52
 
102
53
  ## API
103
54
 
104
55
  ### `definePDFJSModule`
105
56
 
106
- Allows to define a custom PDF.js build. This method should be called before using any other method. If no custom build is defined, the serverless build will be used.
57
+ Sets the PDF.js build every other method uses – call it before any of them. See [Custom PDF.js Build](#custom-pdfjs-build).
107
58
 
108
59
  **Type Declaration**
109
60
 
@@ -113,7 +64,7 @@ function definePDFJSModule(pdfjs: () => Promise<PDFJS>): Promise<void>
113
64
 
114
65
  ### `getResolvedPDFJS`
115
66
 
116
- Returns the resolved PDF.js module. If no other PDF.js build was defined, the serverless build will be used. This method is useful if you want to use the PDF.js API directly.
67
+ Returns the resolved PDF.js module – the serverless build, unless `definePDFJSModule` set another. Use it to call the PDF.js API directly.
117
68
 
118
69
  **Type Declaration**
119
70
 
@@ -121,11 +72,19 @@ Returns the resolved PDF.js module. If no other PDF.js build was defined, the se
121
72
  function getResolvedPDFJS(): Promise<PDFJS>
122
73
  ```
123
74
 
75
+ **Example**
76
+
77
+ ```ts
78
+ import { getResolvedPDFJS } from 'unpdf'
79
+
80
+ const { version } = await getResolvedPDFJS()
81
+ ```
82
+
124
83
  ### `getDocumentProxy`
125
84
 
126
85
  Creates a `PDFDocumentProxy` from binary PDF data. Every extraction method accepts either raw data or an existing proxy – use this when you want to reuse one document across multiple calls.
127
86
 
128
- Applies sensible defaults: `useSystemFonts: true`; in Node.js additionally `disableFontFace: true`, plus `standardFontDataUrl` and `cMapUrl`/`cMapPacked` resolved from the local `pdfjs-dist` package for standard font and CJK character map support (see the font rendering tip in [`renderPageAsImage`](#renderpageasimage)).
87
+ Applies sensible defaults: `useSystemFonts: true`; in Node.js additionally `disableFontFace: true`, plus `standardFontDataUrl` and `cMapUrl`/`cMapPacked` resolved from the local `pdfjs-dist` package for standard font and CJK character map support. Without `pdfjs-dist` installed, the Node.js defaults are skipped.
129
88
 
130
89
  **Type Declaration**
131
90
 
@@ -136,6 +95,17 @@ function getDocumentProxy(
136
95
  ): Promise<PDFDocumentProxy>
137
96
  ```
138
97
 
98
+ **Example**
99
+
100
+ Your options override the defaults:
101
+
102
+ ```ts
103
+ const pdf = await getDocumentProxy(buffer, {
104
+ disableFontFace: false,
105
+ standardFontDataUrl: 'https://unpkg.com/pdfjs-dist@latest/standard_fonts/',
106
+ })
107
+ ```
108
+
139
109
  ### `getMeta`
140
110
 
141
111
  Extracts metadata from a PDF. If `parseDates` is set to `true`, the date properties will be parsed into `Date` objects.
@@ -238,7 +208,7 @@ for (const link of links) console.log(link)
238
208
 
239
209
  ### `extractImages`
240
210
 
241
- Extracts images from a specific page of a PDF document, including necessary metadata such as width, height, and calculated color channels. Works with both the serverless and official PDF.js build.
211
+ Extracts images from a specific page of a PDF document, including necessary metadata such as width, height, and calculated color channels.
242
212
 
243
213
  **Type Declaration**
244
214
 
@@ -259,65 +229,31 @@ function extractImages(
259
229
 
260
230
  **Example**
261
231
 
262
- > [!NOTE]
263
- > The following example uses the [sharp](https://github.com/lovell/sharp) library to process and save the extracted images. You will need to install it with your preferred package manager.
232
+ Saves each image as PNG with [sharp](https://github.com/lovell/sharp), installed separately:
264
233
 
265
234
  ```ts
266
- import { readFile, writeFile } from 'node:fs/promises'
235
+ import { readFile } from 'node:fs/promises'
267
236
  import sharp from 'sharp'
268
237
  import { extractImages, getDocumentProxy } from 'unpdf'
269
238
 
270
- async function extractPdfImages() {
271
- const buffer = await readFile('./document.pdf')
272
- const pdf = await getDocumentProxy(new Uint8Array(buffer))
273
-
274
- // Extract images from page 1
275
- const imagesData = await extractImages(pdf, 1)
276
- console.log(`Found ${imagesData.length} images on page 1`)
277
-
278
- // Process each image with sharp (optional)
279
- let totalImagesProcessed = 0
280
- for (const imgData of imagesData) {
281
- const imageIndex = ++totalImagesProcessed
282
-
283
- await sharp(imgData.data, {
284
- raw: {
285
- width: imgData.width,
286
- height: imgData.height,
287
- channels: imgData.channels
288
- }
289
- })
290
- .png()
291
- .toFile(`image-${imageIndex}.png`)
292
-
293
- console.log(`Saved image ${imageIndex} (${imgData.width}x${imgData.height}, ${imgData.channels} channels)`)
294
- }
239
+ const buffer = await readFile('./document.pdf')
240
+ const pdf = await getDocumentProxy(new Uint8Array(buffer))
241
+ const images = await extractImages(pdf, 1)
242
+
243
+ for (const [index, image] of images.entries()) {
244
+ await sharp(image.data, {
245
+ raw: { width: image.width, height: image.height, channels: image.channels },
246
+ })
247
+ .png()
248
+ .toFile(`image-${index + 1}.png`)
295
249
  }
296
-
297
- extractPdfImages().catch(console.error)
298
250
  ```
299
251
 
300
252
  ### `renderPageAsImage`
301
253
 
302
- To render a PDF page as an image, you can use the `renderPageAsImage` method. This method will return an `ArrayBuffer` of the rendered image. It can also return a data URL (`string`) if `toDataURL` option is set to `true`.
254
+ Renders a PDF page as PNG and returns its bytes as an `ArrayBuffer`, or a data URL (`string`) with `toDataURL: true`.
303
255
 
304
- > [!NOTE]
305
- > This method will only work in Node.js and browser environments.
306
-
307
- In order to use this method, make sure to meet the following requirements:
308
-
309
- - Use the official PDF.js build (see [Official or Legacy PDF.js Build](#official-or-legacy-pdfjs-build)).
310
- - Install the [`@napi-rs/canvas`](https://github.com/Brooooooklyn/canvas) package if you are using Node.js. This package is required to render the PDF page as an image.
311
-
312
- > [!TIP]
313
- > In Node.js, `getDocumentProxy` automatically sets `disableFontFace: true` and resolves `standardFontDataUrl` from your local `pdfjs-dist` package for correct font rendering. To customize this behavior, pass your own options:
314
- >
315
- > ```ts
316
- > const pdf = await getDocumentProxy(buffer, {
317
- > disableFontFace: false,
318
- > standardFontDataUrl: 'https://unpkg.com/pdfjs-dist@latest/standard_fonts/',
319
- > })
320
- > ```
256
+ Rendering needs a canvas: browsers bring their own, while Node.js and Bun need the [`@napi-rs/canvas`](https://github.com/Brooooooklyn/canvas) package, passed as `canvasImport`. Serverless runtimes like Cloudflare Workers have neither.
321
257
 
322
258
  **Type Declaration**
323
259
 
@@ -336,57 +272,36 @@ function renderPageAsImage(
336
272
  ): Promise<ArrayBuffer | string>
337
273
  ```
338
274
 
339
- **Examples**
275
+ **Example**
340
276
 
341
277
  ```ts
342
278
  import { readFile, writeFile } from 'node:fs/promises'
343
- import { definePDFJSModule, renderPageAsImage } from 'unpdf'
279
+ import { renderPageAsImage } from 'unpdf'
344
280
 
345
- // Use the official PDF.js build
346
- await definePDFJSModule(() => import('pdfjs-dist'))
347
-
348
- const pdf = await readFile('./dummy.pdf')
349
- const buffer = new Uint8Array(pdf)
350
- const pageNumber = 1
351
-
352
- const result = await renderPageAsImage(buffer, pageNumber, {
281
+ const buffer = await readFile('./dummy.pdf')
282
+ const image = await renderPageAsImage(new Uint8Array(buffer), 1, {
353
283
  canvasImport: () => import('@napi-rs/canvas'),
354
284
  scale: 2,
355
285
  })
356
- await writeFile('dummy-page-1.png', new Uint8Array(result))
286
+
287
+ await writeFile('dummy-page-1.png', new Uint8Array(image))
357
288
  ```
358
289
 
359
- ```ts
360
- import { readFile, writeFile } from 'node:fs/promises'
361
- import { definePDFJSModule, renderPageAsImage } from 'unpdf'
290
+ ## Custom PDF.js Build
362
291
 
363
- await definePDFJSModule(() => import('pdfjs-dist'))
292
+ `unpdf` uses its serverless build unless you define another one, e.g. to pin a different PDF.js version. Install `pdfjs-dist` and call `definePDFJSModule` before any other method:
364
293
 
365
- const pdf = await readFile('./dummy.pdf')
366
- const buffer = new Uint8Array(pdf)
367
- const pageNumber = 1
294
+ ```ts
295
+ import { definePDFJSModule, extractText, getDocumentProxy } from 'unpdf'
368
296
 
369
- const result = await renderPageAsImage(buffer, pageNumber, {
370
- canvasImport: () => import('@napi-rs/canvas'),
371
- scale: 2,
372
- toDataURL: true,
373
- })
297
+ await definePDFJSModule(() => import('pdfjs-dist/legacy/build/pdf.mjs'))
374
298
 
375
- const html = `<!DOCTYPE html>
376
- <html lang="en">
377
- <head>
378
- <meta charset="UTF-8">
379
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
380
- <title>Dummy Page</title>
381
- </head>
382
- <body>
383
- <img alt="Example Page" src="${result}">
384
- </body>
385
- </html>`
386
-
387
- await writeFile('dummy-page-1.html', html)
299
+ const pdf = await getDocumentProxy(/* … */)
300
+ const { text } = await extractText(pdf)
388
301
  ```
389
302
 
303
+ In Node.js, import the legacy build as shown. The default `pdfjs-dist` entry targets current browsers – it fails on Node.js 24 and older and warns on newer versions.
304
+
390
305
  ## Processing Untrusted PDFs
391
306
 
392
307
  PDF.js does not execute scripts embedded in PDFs, but resource limits are your job:
package/dist/index.cjs CHANGED
@@ -53,7 +53,7 @@ let resolvedModule;
53
53
  const isNode = globalThis.process?.release?.name === "node";
54
54
  const isBrowser = typeof window !== "undefined";
55
55
  /**
56
- * Returns a `PDFDocumentProxy` instance from a given binary data.
56
+ * Creates a `PDFDocumentProxy` from binary PDF data.
57
57
  *
58
58
  * Applies the following defaults:
59
59
  * - `useSystemFonts: true`
@@ -209,18 +209,6 @@ function injectCanvasConstructors() {
209
209
  /**
210
210
  * Extracts images from a specific page of a PDF document, including necessary metadata,
211
211
  * such as width, height, and calculated color channels.
212
- *
213
- * @example
214
- * const imagesData = await extractImages(pdf, pageNum)
215
- *
216
- * for (const imgData of imagesData) {
217
- * const imageIndex = totalImagesProcessed + 1
218
- * await sharp(imgData.data, {
219
- * raw: { width: imgData.width, height: imgData.height, channels: imgData.channels }
220
- * })
221
- * .png()
222
- * .toFile(`${imageIndex}.png`)
223
- * }
224
212
  */
225
213
  async function extractImages$1(data, pageNumber) {
226
214
  return await withDocument(data, async (pdf) => {
@@ -327,23 +315,23 @@ const XMP_DATE_PROPERTIES = [
327
315
  async function getMeta$1(data, options = {}) {
328
316
  return await withDocument(data, async (pdf) => {
329
317
  const meta = await pdf.getMetadata();
330
- const info = meta?.info || {};
318
+ const info = { ...meta.info };
319
+ let metadata = meta.metadata;
331
320
  if (options.parseDates) {
332
321
  const { PDFDateString } = await getResolvedPDFJS();
333
- if (info?.CreationDate) info.CreationDate = PDFDateString.toDateObject(info?.CreationDate);
334
- if (info?.ModDate) info.ModDate = PDFDateString.toDateObject(info?.ModDate);
335
- if (meta.metadata) meta.metadata = new Proxy(meta.metadata, { get(target, prop) {
336
- if (prop === "get") return (name) => {
337
- const value = target.get(name);
338
- if (XMP_DATE_PROPERTIES.includes(name) && value) return parseISODateString(value);
339
- return value;
340
- };
341
- return target[prop];
342
- } });
322
+ if (info.CreationDate) info.CreationDate = PDFDateString.toDateObject(info.CreationDate);
323
+ if (info.ModDate) info.ModDate = PDFDateString.toDateObject(info.ModDate);
324
+ if (metadata) {
325
+ const Metadata = metadata.constructor;
326
+ metadata = new Metadata({
327
+ parsedData: new Map(Array.from(metadata, ([name, value]) => [name, XMP_DATE_PROPERTIES.includes(name) && value ? parseISODateString(value) : value])),
328
+ rawData: metadata.getRaw()
329
+ });
330
+ }
343
331
  }
344
332
  return {
345
333
  info,
346
- metadata: meta?.metadata || {}
334
+ metadata: metadata || {}
347
335
  };
348
336
  });
349
337
  }
@@ -404,15 +392,14 @@ function normalizeMergedText(texts) {
404
392
  //#endregion
405
393
  //#region src/config.ts
406
394
  /**
407
- * By default, unpdf will use the latest version of PDF.js compiled for
408
- * serverless environments. If you want to use a different version, you can
409
- * provide a custom resolver function.
395
+ * Sets the PDF.js build every other method uses – call it before any of them.
396
+ * Without it, the serverless build is used.
410
397
  *
411
398
  * @example
412
- * // Use the official PDF.js build (make sure to install it first)
399
+ * // In Node.js, the legacy build of `pdfjs-dist` (install it first)
413
400
  * import { definePDFJSModule } from 'unpdf'
414
401
  *
415
- * await definePDFJSModule(() => import('pdfjs-dist'))
402
+ * await definePDFJSModule(() => import('pdfjs-dist/legacy/build/pdf.mjs'))
416
403
  */
417
404
  async function definePDFJSModule(pdfjs) {
418
405
  await resolvePDFJSImport(pdfjs, { reload: true });
package/dist/index.d.cts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { DocumentInitParameters, PDFDocumentProxy } from "./types/src/display/api.js";
2
2
  import { Canvas, SKRSContext2D } from "@napi-rs/canvas";
3
+ import { Metadata } from "./types/src/display/metadata.js";
3
4
  import * as PDFJS from "./types/src/pdf.js";
4
5
  //#region src/_internal/canvas.d.ts
5
6
  interface CanvasFactoryContext {
@@ -55,18 +56,6 @@ interface ExtractedImageObject {
55
56
  /**
56
57
  * Extracts images from a specific page of a PDF document, including necessary metadata,
57
58
  * such as width, height, and calculated color channels.
58
- *
59
- * @example
60
- * const imagesData = await extractImages(pdf, pageNum)
61
- *
62
- * for (const imgData of imagesData) {
63
- * const imageIndex = totalImagesProcessed + 1
64
- * await sharp(imgData.data, {
65
- * raw: { width: imgData.width, height: imgData.height, channels: imgData.channels }
66
- * })
67
- * .png()
68
- * .toFile(`${imageIndex}.png`)
69
- * }
70
59
  */
71
60
  declare function extractImages$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number): Promise<ExtractedImageObject[]>;
72
61
  declare function renderPageAsImage$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number, options?: {
@@ -98,7 +87,7 @@ declare function getMeta$1(data: DocumentInitParameters['data'] | PDFDocumentPro
98
87
  parseDates?: boolean;
99
88
  }): Promise<{
100
89
  info: Record<string, any>;
101
- metadata: import("./types/src/display/metadata.js").Metadata;
90
+ metadata: Metadata;
102
91
  }>;
103
92
  //#endregion
104
93
  //#region src/text.d.ts
@@ -147,15 +136,14 @@ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumen
147
136
  //#endregion
148
137
  //#region src/config.d.ts
149
138
  /**
150
- * By default, unpdf will use the latest version of PDF.js compiled for
151
- * serverless environments. If you want to use a different version, you can
152
- * provide a custom resolver function.
139
+ * Sets the PDF.js build every other method uses – call it before any of them.
140
+ * Without it, the serverless build is used.
153
141
  *
154
142
  * @example
155
- * // Use the official PDF.js build (make sure to install it first)
143
+ * // In Node.js, the legacy build of `pdfjs-dist` (install it first)
156
144
  * import { definePDFJSModule } from 'unpdf'
157
145
  *
158
- * await definePDFJSModule(() => import('pdfjs-dist'))
146
+ * await definePDFJSModule(() => import('pdfjs-dist/legacy/build/pdf.mjs'))
159
147
  */
160
148
  export declare function definePDFJSModule(pdfjs: () => Promise<any>): Promise<void>;
161
149
  /** @deprecated Use `definePDFJSModule` instead. Will be removed in v2. */
@@ -165,7 +153,7 @@ export declare function configureUnPDF(options: {
165
153
  //#endregion
166
154
  //#region src/utils.d.ts
167
155
  /**
168
- * Returns a `PDFDocumentProxy` instance from a given binary data.
156
+ * Creates a `PDFDocumentProxy` from binary PDF data.
169
157
  *
170
158
  * Applies the following defaults:
171
159
  * - `useSystemFonts: true`
package/dist/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { DocumentInitParameters, PDFDocumentProxy } from "./types/src/display/api.js";
2
2
  import { Canvas, SKRSContext2D } from "@napi-rs/canvas";
3
+ import { Metadata } from "./types/src/display/metadata.js";
3
4
  import * as PDFJS from "./types/src/pdf.js";
4
5
  //#region src/_internal/canvas.d.ts
5
6
  interface CanvasFactoryContext {
@@ -55,18 +56,6 @@ interface ExtractedImageObject {
55
56
  /**
56
57
  * Extracts images from a specific page of a PDF document, including necessary metadata,
57
58
  * such as width, height, and calculated color channels.
58
- *
59
- * @example
60
- * const imagesData = await extractImages(pdf, pageNum)
61
- *
62
- * for (const imgData of imagesData) {
63
- * const imageIndex = totalImagesProcessed + 1
64
- * await sharp(imgData.data, {
65
- * raw: { width: imgData.width, height: imgData.height, channels: imgData.channels }
66
- * })
67
- * .png()
68
- * .toFile(`${imageIndex}.png`)
69
- * }
70
59
  */
71
60
  declare function extractImages$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number): Promise<ExtractedImageObject[]>;
72
61
  declare function renderPageAsImage$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number, options?: {
@@ -98,7 +87,7 @@ declare function getMeta$1(data: DocumentInitParameters['data'] | PDFDocumentPro
98
87
  parseDates?: boolean;
99
88
  }): Promise<{
100
89
  info: Record<string, any>;
101
- metadata: import("./types/src/display/metadata.js").Metadata;
90
+ metadata: Metadata;
102
91
  }>;
103
92
  //#endregion
104
93
  //#region src/text.d.ts
@@ -147,15 +136,14 @@ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumen
147
136
  //#endregion
148
137
  //#region src/config.d.ts
149
138
  /**
150
- * By default, unpdf will use the latest version of PDF.js compiled for
151
- * serverless environments. If you want to use a different version, you can
152
- * provide a custom resolver function.
139
+ * Sets the PDF.js build every other method uses – call it before any of them.
140
+ * Without it, the serverless build is used.
153
141
  *
154
142
  * @example
155
- * // Use the official PDF.js build (make sure to install it first)
143
+ * // In Node.js, the legacy build of `pdfjs-dist` (install it first)
156
144
  * import { definePDFJSModule } from 'unpdf'
157
145
  *
158
- * await definePDFJSModule(() => import('pdfjs-dist'))
146
+ * await definePDFJSModule(() => import('pdfjs-dist/legacy/build/pdf.mjs'))
159
147
  */
160
148
  export declare function definePDFJSModule(pdfjs: () => Promise<any>): Promise<void>;
161
149
  /** @deprecated Use `definePDFJSModule` instead. Will be removed in v2. */
@@ -165,7 +153,7 @@ export declare function configureUnPDF(options: {
165
153
  //#endregion
166
154
  //#region src/utils.d.ts
167
155
  /**
168
- * Returns a `PDFDocumentProxy` instance from a given binary data.
156
+ * Creates a `PDFDocumentProxy` from binary PDF data.
169
157
  *
170
158
  * Applies the following defaults:
171
159
  * - `useSystemFonts: true`
package/dist/index.mjs CHANGED
@@ -52,7 +52,7 @@ let resolvedModule;
52
52
  const isNode = globalThis.process?.release?.name === "node";
53
53
  const isBrowser = typeof window !== "undefined";
54
54
  /**
55
- * Returns a `PDFDocumentProxy` instance from a given binary data.
55
+ * Creates a `PDFDocumentProxy` from binary PDF data.
56
56
  *
57
57
  * Applies the following defaults:
58
58
  * - `useSystemFonts: true`
@@ -208,18 +208,6 @@ function injectCanvasConstructors() {
208
208
  /**
209
209
  * Extracts images from a specific page of a PDF document, including necessary metadata,
210
210
  * such as width, height, and calculated color channels.
211
- *
212
- * @example
213
- * const imagesData = await extractImages(pdf, pageNum)
214
- *
215
- * for (const imgData of imagesData) {
216
- * const imageIndex = totalImagesProcessed + 1
217
- * await sharp(imgData.data, {
218
- * raw: { width: imgData.width, height: imgData.height, channels: imgData.channels }
219
- * })
220
- * .png()
221
- * .toFile(`${imageIndex}.png`)
222
- * }
223
211
  */
224
212
  async function extractImages$1(data, pageNumber) {
225
213
  return await withDocument(data, async (pdf) => {
@@ -326,23 +314,23 @@ const XMP_DATE_PROPERTIES = [
326
314
  async function getMeta$1(data, options = {}) {
327
315
  return await withDocument(data, async (pdf) => {
328
316
  const meta = await pdf.getMetadata();
329
- const info = meta?.info || {};
317
+ const info = { ...meta.info };
318
+ let metadata = meta.metadata;
330
319
  if (options.parseDates) {
331
320
  const { PDFDateString } = await getResolvedPDFJS();
332
- if (info?.CreationDate) info.CreationDate = PDFDateString.toDateObject(info?.CreationDate);
333
- if (info?.ModDate) info.ModDate = PDFDateString.toDateObject(info?.ModDate);
334
- if (meta.metadata) meta.metadata = new Proxy(meta.metadata, { get(target, prop) {
335
- if (prop === "get") return (name) => {
336
- const value = target.get(name);
337
- if (XMP_DATE_PROPERTIES.includes(name) && value) return parseISODateString(value);
338
- return value;
339
- };
340
- return target[prop];
341
- } });
321
+ if (info.CreationDate) info.CreationDate = PDFDateString.toDateObject(info.CreationDate);
322
+ if (info.ModDate) info.ModDate = PDFDateString.toDateObject(info.ModDate);
323
+ if (metadata) {
324
+ const Metadata = metadata.constructor;
325
+ metadata = new Metadata({
326
+ parsedData: new Map(Array.from(metadata, ([name, value]) => [name, XMP_DATE_PROPERTIES.includes(name) && value ? parseISODateString(value) : value])),
327
+ rawData: metadata.getRaw()
328
+ });
329
+ }
342
330
  }
343
331
  return {
344
332
  info,
345
- metadata: meta?.metadata || {}
333
+ metadata: metadata || {}
346
334
  };
347
335
  });
348
336
  }
@@ -403,15 +391,14 @@ function normalizeMergedText(texts) {
403
391
  //#endregion
404
392
  //#region src/config.ts
405
393
  /**
406
- * By default, unpdf will use the latest version of PDF.js compiled for
407
- * serverless environments. If you want to use a different version, you can
408
- * provide a custom resolver function.
394
+ * Sets the PDF.js build every other method uses – call it before any of them.
395
+ * Without it, the serverless build is used.
409
396
  *
410
397
  * @example
411
- * // Use the official PDF.js build (make sure to install it first)
398
+ * // In Node.js, the legacy build of `pdfjs-dist` (install it first)
412
399
  * import { definePDFJSModule } from 'unpdf'
413
400
  *
414
- * await definePDFJSModule(() => import('pdfjs-dist'))
401
+ * await definePDFJSModule(() => import('pdfjs-dist/legacy/build/pdf.mjs'))
415
402
  */
416
403
  async function definePDFJSModule(pdfjs) {
417
404
  await resolvePDFJSImport(pdfjs, { reload: true });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "unpdf",
3
3
  "type": "module",
4
- "version": "1.9.0",
4
+ "version": "1.9.1",
5
5
  "packageManager": "pnpm@12.11.2",
6
6
  "description": "PDF extraction and rendering across all JavaScript runtimes",
7
7
  "author": "Johann Schopplich <hello@johannschopplich.com>",
@@ -84,6 +84,7 @@
84
84
  "devDependencies": {
85
85
  "@antfu/eslint-config": "^9.5.1",
86
86
  "@arethetypeswrong/cli": "^0.18.5",
87
+ "@cloudflare/vitest-plugin": "^1.4.3",
87
88
  "@napi-rs/canvas": "^1.0.11",
88
89
  "@types/node": "^26.6.5",
89
90
  "bumpp": "^12.3.0",