unpdf 1.6.1 → 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/README.md CHANGED
@@ -7,7 +7,7 @@ Ships with a serverless build of Mozilla's [PDF.js](https://github.com/mozilla/p
7
7
  ## Features
8
8
 
9
9
  - 🏗️ Works in Node.js, browser and serverless environments
10
- - 🪭 Includes serverless build of PDF.js ([`unpdf/pdfjs`](./package.json#L34))
10
+ - 🪭 Includes serverless build of PDF.js ([`unpdf/pdfjs`](./package.json))
11
11
  - 💬 Extract [text](#extract-text-from-pdf), [links](#extractlinks), and [images](#extractimages) from PDF files
12
12
  - 🧠 Perfect for AI applications and PDF summarization
13
13
  - 🧱 Opt-in to official or legacy PDF.js build
@@ -97,7 +97,7 @@ Heart and soul of this package is the [`pdfjs.rollup.config.ts`](./pdfjs.rollup.
97
97
 
98
98
  - **String replacements** strip browser-specific references from the PDF.js source.
99
99
  - **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 `FinalizationRegistry` (unavailable in Cloudflare Workers).
100
+ - **Global polyfills** provide missing APIs like `Promise.withResolvers` and `FinalizationRegistry` (unavailable in Node.js < 22 and Cloudflare Workers, respectively).
101
101
 
102
102
  ## API
103
103
 
@@ -121,6 +121,21 @@ Returns the resolved PDF.js module. If no other PDF.js build was defined, the se
121
121
  function getResolvedPDFJS(): Promise<PDFJS>
122
122
  ```
123
123
 
124
+ ### `getDocumentProxy`
125
+
126
+ 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
+
128
+ Applies sensible defaults: `isEvalSupported: false` and `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)).
129
+
130
+ **Type Declaration**
131
+
132
+ ```ts
133
+ function getDocumentProxy(
134
+ data: DocumentInitParameters['data'],
135
+ options?: DocumentInitParameters,
136
+ ): Promise<PDFDocumentProxy>
137
+ ```
138
+
124
139
  ### `getMeta`
125
140
 
126
141
  Extracts metadata from a PDF. If `parseDates` is set to `true`, the date properties will be parsed into `Date` objects.
@@ -141,7 +156,7 @@ function getMeta(
141
156
 
142
157
  ### `extractText`
143
158
 
144
- Extracts all text from a PDF. If `mergePages` is set to `true`, the text of all pages will be merged into a single string. Otherwise, an array of strings for each page will be returned.
159
+ Extracts all text from a PDF. If `mergePages` is set to `true`, the text of all pages will be merged into a single string with line breaks preserved and at most one blank line in a row. Otherwise, an array of strings for each page will be returned.
145
160
 
146
161
  **Type Declaration**
147
162
 
@@ -149,20 +164,42 @@ Extracts all text from a PDF. If `mergePages` is set to `true`, the text of all
149
164
  function extractText(
150
165
  data: DocumentInitParameters['data'] | PDFDocumentProxy,
151
166
  options?: {
152
- mergePages?: false
167
+ mergePages?: boolean
153
168
  }
154
169
  ): Promise<{
155
170
  totalPages: number
156
- text: string[]
171
+ text: string | string[]
157
172
  }>
158
- function extractText(
173
+ ```
174
+
175
+ ### `extractTextItems`
176
+
177
+ Extracts text with layout information – one array of positioned items per page. Useful when plain text is not enough and you need coordinates, font sizes, or reading direction, e.g. for table detection or positional parsing.
178
+
179
+ **Type Declaration**
180
+
181
+ ```ts
182
+ interface StructuredTextItem {
183
+ str: string
184
+ /** X position in PDF coordinate space (origin: bottom-left). */
185
+ x: number
186
+ /** Y position in PDF coordinate space (origin: bottom-left). */
187
+ y: number
188
+ width: number
189
+ height: number
190
+ fontSize: number
191
+ fontFamily: string
192
+ /** Text direction: `"ltr"`, `"rtl"`, or `"ttb"`. */
193
+ dir: string
194
+ /** Whether the text item is followed by a line break. */
195
+ hasEOL: boolean
196
+ }
197
+
198
+ function extractTextItems(
159
199
  data: DocumentInitParameters['data'] | PDFDocumentProxy,
160
- options: {
161
- mergePages: true
162
- }
163
200
  ): Promise<{
164
201
  totalPages: number
165
- text: string
202
+ items: StructuredTextItem[][]
166
203
  }>
167
204
  ```
168
205
 
@@ -294,26 +331,15 @@ function renderPageAsImage(
294
331
  scale?: number
295
332
  width?: number
296
333
  height?: number
297
- toDataURL?: false
334
+ toDataURL?: boolean
298
335
  },
299
- ): Promise<ArrayBuffer>
300
- function renderPageAsImage(
301
- data: DocumentInitParameters['data'] | PDFDocumentProxy,
302
- pageNumber: number,
303
- options: {
304
- canvasImport?: () => Promise<typeof import('@napi-rs/canvas')>
305
- /** @default 1.0 */
306
- scale?: number
307
- width?: number
308
- height?: number
309
- toDataURL: true
310
- },
311
- ): Promise<string>
336
+ ): Promise<ArrayBuffer | string>
312
337
  ```
313
338
 
314
339
  **Examples**
315
340
 
316
341
  ```ts
342
+ import { readFile, writeFile } from 'node:fs/promises'
317
343
  import { definePDFJSModule, renderPageAsImage } from 'unpdf'
318
344
 
319
345
  // Use the official PDF.js build
@@ -331,6 +357,7 @@ await writeFile('dummy-page-1.png', new Uint8Array(result))
331
357
  ```
332
358
 
333
359
  ```ts
360
+ import { readFile, writeFile } from 'node:fs/promises'
334
361
  import { definePDFJSModule, renderPageAsImage } from 'unpdf'
335
362
 
336
363
  await definePDFJSModule(() => import('pdfjs-dist'))
@@ -360,6 +387,15 @@ const html = `<!DOCTYPE html>
360
387
  await writeFile('dummy-page-1.html', html)
361
388
  ```
362
389
 
390
+ ## Processing Untrusted PDFs
391
+
392
+ The `getDocumentProxy` defaults are safe against script execution (`isEvalSupported: false`), but resource limits are your job:
393
+
394
+ - **Image decoding:** `maxImageSize` is unlimited by default – pass e.g. `maxImageSize: 16_777_216` (~16 MP) so a single declared image can't allocate gigabytes.
395
+ - **Page fan-out:** `extractText`, `extractTextItems`, and `extractLinks` process all pages in one call – check `pdf.numPages` against a limit first.
396
+ - **Timeouts:** with the serverless build, parsing runs on your event loop (no worker) – race extraction calls against a timeout.
397
+ - The raw `getDocument` from `unpdf/pdfjs` applies none of these defaults.
398
+
363
399
  ## License
364
400
 
365
401
  [MIT](./LICENSE) License © 2023-PRESENT [Johann Schopplich](https://github.com/johannschopplich)
package/dist/index.cjs CHANGED
@@ -57,7 +57,9 @@ async function getDocumentProxy(data, options = {}) {
57
57
  const base = undefined("pdfjs-dist/package.json");
58
58
  nodeDefaults = {
59
59
  disableFontFace: true,
60
- standardFontDataUrl: new URL("./standard_fonts/", base).href
60
+ standardFontDataUrl: new URL("./standard_fonts/", base).href,
61
+ cMapUrl: new URL("./cmaps/", base).href,
62
+ cMapPacked: true
61
63
  };
62
64
  } catch {
63
65
  }
@@ -72,6 +74,15 @@ async function getDocumentProxy(data, options = {}) {
72
74
  }).promise;
73
75
  return pdf;
74
76
  }
77
+ async function withDocument(data, operation, options) {
78
+ const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data, options);
79
+ try {
80
+ return await operation(pdf);
81
+ } finally {
82
+ if (pdf !== data)
83
+ await pdf.destroy();
84
+ }
85
+ }
75
86
  async function getResolvedPDFJS() {
76
87
  if (!resolvedModule) {
77
88
  await resolvePDFJSImport();
@@ -177,6 +188,7 @@ class NodeCanvasFactory extends BaseCanvasFactory {
177
188
  }
178
189
  async function resolveCanvasModule(canvasImport) {
179
190
  resolvedCanvasModule ??= await interopDefault(canvasImport());
191
+ globalThis[Symbol.for("unpdf.canvasModule")] = resolvedCanvasModule;
180
192
  }
181
193
  function injectCanvasConstructors() {
182
194
  if (!resolvedCanvasModule)
@@ -189,69 +201,85 @@ function injectCanvasConstructors() {
189
201
  }
190
202
 
191
203
  async function extractImages$1(data, pageNumber) {
192
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
193
- if (pageNumber < 1 || pageNumber > pdf.numPages) {
194
- throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
195
- }
196
- const page = await pdf.getPage(pageNumber);
197
- const operatorList = await page.getOperatorList();
198
- const { OPS } = await getResolvedPDFJS();
199
- const images = [];
200
- for (let i = 0; i < operatorList.fnArray.length; i++) {
201
- const op = operatorList.fnArray[i];
202
- if (op !== OPS.paintImageXObject) {
203
- continue;
204
- }
205
- const imageKey = operatorList.argsArray[i][0];
206
- const image = await new Promise(
207
- (resolve) => (imageKey.startsWith("g_") ? page.commonObjs : page.objs).get(imageKey, resolve)
208
- );
209
- if (!image || !image.data || !image.width || !image.height) {
210
- continue;
204
+ return await withDocument(data, async (pdf) => {
205
+ if (pageNumber < 1 || pageNumber > pdf.numPages) {
206
+ throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
211
207
  }
212
- const { width, height, data: data2 } = image;
213
- const calculatedChannels = data2.length / (width * height);
214
- if (![1, 3, 4].includes(calculatedChannels)) {
215
- continue;
208
+ const page = await pdf.getPage(pageNumber);
209
+ const operatorList = await page.getOperatorList();
210
+ const { OPS } = await getResolvedPDFJS();
211
+ const images = [];
212
+ for (let i = 0; i < operatorList.fnArray.length; i++) {
213
+ const op = operatorList.fnArray[i];
214
+ if (op !== OPS.paintImageXObject) {
215
+ continue;
216
+ }
217
+ const imageKey = operatorList.argsArray[i][0];
218
+ const image = await new Promise(
219
+ (resolve) => (imageKey.startsWith("g_") ? page.commonObjs : page.objs).get(imageKey, resolve)
220
+ );
221
+ if (!image || !image.data || !image.width || !image.height) {
222
+ continue;
223
+ }
224
+ const { width, height, data: data2 } = image;
225
+ const calculatedChannels = data2.length / (width * height);
226
+ if (![1, 3, 4].includes(calculatedChannels)) {
227
+ continue;
228
+ }
229
+ const channels = calculatedChannels;
230
+ images.push({
231
+ data: data2,
232
+ width,
233
+ height,
234
+ channels,
235
+ key: imageKey
236
+ });
216
237
  }
217
- const channels = calculatedChannels;
218
- images.push({
219
- data: data2,
220
- width,
221
- height,
222
- channels,
223
- key: imageKey
224
- });
225
- }
226
- return images;
238
+ return images;
239
+ });
227
240
  }
228
241
  async function renderPageAsImage$1(data, pageNumber, options = {}) {
229
242
  const CanvasFactory = await createIsomorphicCanvasFactory(options.canvasImport);
230
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data, { CanvasFactory });
231
- const page = await pdf.getPage(pageNumber);
232
- if (pageNumber < 1 || pageNumber > pdf.numPages) {
233
- throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
234
- }
235
- const defaultViewport = page.getViewport({ scale: 1 });
236
- let scale = options.scale || 1;
237
- if (options.width) {
238
- scale = options.width / defaultViewport.width;
239
- } else if (options.height) {
240
- scale = options.height / defaultViewport.height;
241
- }
242
- const viewport = page.getViewport({ scale: Math.max(0, scale) });
243
- const drawingContext = new CanvasFactory().create(viewport.width, viewport.height);
244
- await page.render({
245
- canvas: drawingContext.canvas,
246
- canvasContext: drawingContext.context,
247
- viewport
248
- }).promise;
249
- const dataUrl = drawingContext.canvas.toDataURL();
250
- if (options.toDataURL) {
251
- return dataUrl;
252
- }
253
- const response = await fetch(dataUrl);
254
- return await response.arrayBuffer();
243
+ return await withDocument(data, async (pdf) => {
244
+ if (pageNumber < 1 || pageNumber > pdf.numPages) {
245
+ throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
246
+ }
247
+ const page = await pdf.getPage(pageNumber);
248
+ const defaultViewport = page.getViewport({ scale: 1 });
249
+ let scale = options.scale || 1;
250
+ if (options.width) {
251
+ scale = options.width / defaultViewport.width;
252
+ } else if (options.height) {
253
+ scale = options.height / defaultViewport.height;
254
+ }
255
+ const viewport = page.getViewport({ scale: Math.max(0, scale) });
256
+ const canvasFactory = new CanvasFactory();
257
+ const drawingContext = canvasFactory.create(viewport.width, viewport.height);
258
+ try {
259
+ await page.render({
260
+ canvas: drawingContext.canvas,
261
+ canvasContext: drawingContext.context,
262
+ viewport
263
+ }).promise;
264
+ const { canvas } = drawingContext;
265
+ if (options.toDataURL) {
266
+ return canvas.toDataURL();
267
+ }
268
+ if ("encode" in canvas) {
269
+ const buffer = await canvas.encode("png");
270
+ return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
271
+ }
272
+ const blob = await new Promise((resolve) => {
273
+ canvas.toBlob(resolve);
274
+ });
275
+ if (!blob) {
276
+ throw new Error("Failed to encode canvas to a PNG blob.");
277
+ }
278
+ return await blob.arrayBuffer();
279
+ } finally {
280
+ canvasFactory.destroy(drawingContext);
281
+ }
282
+ }, { CanvasFactory });
255
283
  }
256
284
  async function createIsomorphicCanvasFactory(canvasImport) {
257
285
  if (isBrowser)
@@ -268,14 +296,15 @@ async function createIsomorphicCanvasFactory(canvasImport) {
268
296
  }
269
297
 
270
298
  async function extractLinks$1(data) {
271
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
272
- const pageLinks = await Promise.all(
273
- Array.from({ length: pdf.numPages }, (_, i) => getPageLinks(pdf, i + 1))
274
- );
275
- return {
276
- totalPages: pdf.numPages,
277
- links: pageLinks.flat()
278
- };
299
+ return await withDocument(data, async (pdf) => {
300
+ const pageLinks = await Promise.all(
301
+ Array.from({ length: pdf.numPages }, (_, i) => getPageLinks(pdf, i + 1))
302
+ );
303
+ return {
304
+ totalPages: pdf.numPages,
305
+ links: pageLinks.flat()
306
+ };
307
+ });
279
308
  }
280
309
  async function getPageLinks(document, pageNumber) {
281
310
  const page = await document.getPage(pageNumber);
@@ -298,38 +327,39 @@ const XMP_DATE_PROPERTIES = [
298
327
  "xap:metadatadate"
299
328
  ];
300
329
  async function getMeta$1(data, options = {}) {
301
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
302
- const meta = await pdf.getMetadata();
303
- const info = meta?.info || {};
304
- if (options.parseDates) {
305
- const { PDFDateString } = await getResolvedPDFJS();
306
- if (info?.CreationDate) {
307
- info.CreationDate = PDFDateString.toDateObject(info?.CreationDate);
308
- }
309
- if (info?.ModDate) {
310
- info.ModDate = PDFDateString.toDateObject(info?.ModDate);
311
- }
312
- if (meta.metadata) {
313
- meta.metadata = new Proxy(meta.metadata, {
314
- get(target, prop) {
315
- if (prop === "get") {
316
- return (name) => {
317
- const value = target.get(name);
318
- if (XMP_DATE_PROPERTIES.includes(name) && value) {
319
- return parseISODateString(value);
320
- }
321
- return value;
322
- };
330
+ return await withDocument(data, async (pdf) => {
331
+ const meta = await pdf.getMetadata();
332
+ const info = meta?.info || {};
333
+ if (options.parseDates) {
334
+ const { PDFDateString } = await getResolvedPDFJS();
335
+ if (info?.CreationDate) {
336
+ info.CreationDate = PDFDateString.toDateObject(info?.CreationDate);
337
+ }
338
+ if (info?.ModDate) {
339
+ info.ModDate = PDFDateString.toDateObject(info?.ModDate);
340
+ }
341
+ if (meta.metadata) {
342
+ meta.metadata = new Proxy(meta.metadata, {
343
+ get(target, prop) {
344
+ if (prop === "get") {
345
+ return (name) => {
346
+ const value = target.get(name);
347
+ if (XMP_DATE_PROPERTIES.includes(name) && value) {
348
+ return parseISODateString(value);
349
+ }
350
+ return value;
351
+ };
352
+ }
353
+ return target[prop];
323
354
  }
324
- return target[prop];
325
- }
326
- });
355
+ });
356
+ }
327
357
  }
328
- }
329
- return {
330
- info,
331
- metadata: meta?.metadata || {}
332
- };
358
+ return {
359
+ info,
360
+ metadata: meta?.metadata || {}
361
+ };
362
+ });
333
363
  }
334
364
  function parseISODateString(isoDateString) {
335
365
  if (!isoDateString)
@@ -341,11 +371,12 @@ function parseISODateString(isoDateString) {
341
371
  }
342
372
 
343
373
  async function extractTextItems$1(data) {
344
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
345
- const items = await Promise.all(
346
- Array.from({ length: pdf.numPages }, (_, i) => getPageTextItems(pdf, i + 1))
347
- );
348
- return { totalPages: pdf.numPages, items };
374
+ return await withDocument(data, async (pdf) => {
375
+ const items = await Promise.all(
376
+ Array.from({ length: pdf.numPages }, (_, i) => getPageTextItems(pdf, i + 1))
377
+ );
378
+ return { totalPages: pdf.numPages, items };
379
+ });
349
380
  }
350
381
  async function getPageTextItems(document, pageNumber) {
351
382
  const page = await document.getPage(pageNumber);
@@ -368,20 +399,24 @@ async function getPageTextItems(document, pageNumber) {
368
399
  }
369
400
  async function extractText$1(data, options = {}) {
370
401
  const { mergePages = false } = options;
371
- const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
372
- const texts = await Promise.all(
373
- Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1))
374
- );
375
- return {
376
- totalPages: pdf.numPages,
377
- text: mergePages ? texts.join("\n").replace(/\s+/g, " ") : texts
378
- };
402
+ return await withDocument(data, async (pdf) => {
403
+ const texts = await Promise.all(
404
+ Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1))
405
+ );
406
+ return {
407
+ totalPages: pdf.numPages,
408
+ text: mergePages ? normalizeMergedText(texts) : texts
409
+ };
410
+ });
379
411
  }
380
412
  async function getPageText(document, pageNumber) {
381
413
  const page = await document.getPage(pageNumber);
382
414
  const content = await page.getTextContent();
383
415
  return content.items.filter((item) => item.str != null).map((item) => item.str + (item.hasEOL ? "\n" : "")).join("");
384
416
  }
417
+ function normalizeMergedText(texts) {
418
+ return texts.join("\n").replace(/[^\S\n]+/g, " ").replace(/ ?\n ?/g, "\n").replace(/\n{3,}/g, "\n\n");
419
+ }
385
420
 
386
421
  async function definePDFJSModule(pdfjs) {
387
422
  await resolvePDFJSImport(pdfjs, { reload: true });
package/dist/index.d.cts CHANGED
@@ -1,12 +1,12 @@
1
1
  import * as _napi_rs_canvas from '@napi-rs/canvas';
2
- import { Canvas, CanvasRenderingContext2D } from '@napi-rs/canvas';
3
- import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
4
- import * as pdfjs_dist_types_src_display_metadata from './types/src/display/metadata';
5
- import * as PDFJS from './types/src/pdf';
2
+ import { Canvas, SKRSContext2D } from '@napi-rs/canvas';
3
+ import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api.js';
4
+ import * as pdfjs_dist_types_src_display_metadata from './types/src/display/metadata.js';
5
+ import * as PDFJS from './types/src/pdf.js';
6
6
 
7
7
  interface CanvasFactoryContext {
8
8
  canvas?: HTMLCanvasElement | Canvas;
9
- context?: CanvasRenderingContext2D | CanvasRenderingContext2D;
9
+ context?: CanvasRenderingContext2D | SKRSContext2D | null;
10
10
  }
11
11
  /**
12
12
  * Derived from the PDF.js project by the Mozilla Foundation.
@@ -20,7 +20,7 @@ declare class BaseCanvasFactory {
20
20
  });
21
21
  create(width: number, height: number): {
22
22
  canvas: Canvas | HTMLCanvasElement;
23
- context: _napi_rs_canvas.SKRSContext2D | globalThis.CanvasRenderingContext2D | null;
23
+ context: SKRSContext2D | CanvasRenderingContext2D | null;
24
24
  };
25
25
  reset({ canvas }: CanvasFactoryContext, width: number, height: number): void;
26
26
  destroy(context: CanvasFactoryContext): void;
@@ -136,6 +136,12 @@ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumen
136
136
  totalPages: number;
137
137
  text: string;
138
138
  }>;
139
+ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options?: {
140
+ mergePages?: boolean;
141
+ }): Promise<{
142
+ totalPages: number;
143
+ text: string | string[];
144
+ }>;
139
145
 
140
146
  /**
141
147
  * By default, unpdf will use the latest version of PDF.js compiled for
@@ -164,6 +170,7 @@ declare function configureUnPDF(options: {
164
170
  * In Node.js environments, additionally applies:
165
171
  * - `disableFontFace: true`
166
172
  * - `standardFontDataUrl` resolved from the local `pdfjs-dist` package
173
+ * - `cMapUrl` and `cMapPacked` resolved from the local `pdfjs-dist` package
167
174
  */
168
175
  declare function getDocumentProxy(data: DocumentInitParameters['data'], options?: DocumentInitParameters): Promise<PDFDocumentProxy>;
169
176
  declare function getResolvedPDFJS(): Promise<typeof PDFJS>;
package/dist/index.d.mts CHANGED
@@ -1,12 +1,12 @@
1
1
  import * as _napi_rs_canvas from '@napi-rs/canvas';
2
- import { Canvas, CanvasRenderingContext2D } from '@napi-rs/canvas';
3
- import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
4
- import * as pdfjs_dist_types_src_display_metadata from './types/src/display/metadata';
5
- import * as PDFJS from './types/src/pdf';
2
+ import { Canvas, SKRSContext2D } from '@napi-rs/canvas';
3
+ import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api.js';
4
+ import * as pdfjs_dist_types_src_display_metadata from './types/src/display/metadata.js';
5
+ import * as PDFJS from './types/src/pdf.js';
6
6
 
7
7
  interface CanvasFactoryContext {
8
8
  canvas?: HTMLCanvasElement | Canvas;
9
- context?: CanvasRenderingContext2D | CanvasRenderingContext2D;
9
+ context?: CanvasRenderingContext2D | SKRSContext2D | null;
10
10
  }
11
11
  /**
12
12
  * Derived from the PDF.js project by the Mozilla Foundation.
@@ -20,7 +20,7 @@ declare class BaseCanvasFactory {
20
20
  });
21
21
  create(width: number, height: number): {
22
22
  canvas: Canvas | HTMLCanvasElement;
23
- context: _napi_rs_canvas.SKRSContext2D | globalThis.CanvasRenderingContext2D | null;
23
+ context: SKRSContext2D | CanvasRenderingContext2D | null;
24
24
  };
25
25
  reset({ canvas }: CanvasFactoryContext, width: number, height: number): void;
26
26
  destroy(context: CanvasFactoryContext): void;
@@ -136,6 +136,12 @@ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumen
136
136
  totalPages: number;
137
137
  text: string;
138
138
  }>;
139
+ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options?: {
140
+ mergePages?: boolean;
141
+ }): Promise<{
142
+ totalPages: number;
143
+ text: string | string[];
144
+ }>;
139
145
 
140
146
  /**
141
147
  * By default, unpdf will use the latest version of PDF.js compiled for
@@ -164,6 +170,7 @@ declare function configureUnPDF(options: {
164
170
  * In Node.js environments, additionally applies:
165
171
  * - `disableFontFace: true`
166
172
  * - `standardFontDataUrl` resolved from the local `pdfjs-dist` package
173
+ * - `cMapUrl` and `cMapPacked` resolved from the local `pdfjs-dist` package
167
174
  */
168
175
  declare function getDocumentProxy(data: DocumentInitParameters['data'], options?: DocumentInitParameters): Promise<PDFDocumentProxy>;
169
176
  declare function getResolvedPDFJS(): Promise<typeof PDFJS>;
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import * as _napi_rs_canvas from '@napi-rs/canvas';
2
- import { Canvas, CanvasRenderingContext2D } from '@napi-rs/canvas';
3
- import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
4
- import * as pdfjs_dist_types_src_display_metadata from './types/src/display/metadata';
5
- import * as PDFJS from './types/src/pdf';
2
+ import { Canvas, SKRSContext2D } from '@napi-rs/canvas';
3
+ import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api.js';
4
+ import * as pdfjs_dist_types_src_display_metadata from './types/src/display/metadata.js';
5
+ import * as PDFJS from './types/src/pdf.js';
6
6
 
7
7
  interface CanvasFactoryContext {
8
8
  canvas?: HTMLCanvasElement | Canvas;
9
- context?: CanvasRenderingContext2D | CanvasRenderingContext2D;
9
+ context?: CanvasRenderingContext2D | SKRSContext2D | null;
10
10
  }
11
11
  /**
12
12
  * Derived from the PDF.js project by the Mozilla Foundation.
@@ -20,7 +20,7 @@ declare class BaseCanvasFactory {
20
20
  });
21
21
  create(width: number, height: number): {
22
22
  canvas: Canvas | HTMLCanvasElement;
23
- context: _napi_rs_canvas.SKRSContext2D | globalThis.CanvasRenderingContext2D | null;
23
+ context: SKRSContext2D | CanvasRenderingContext2D | null;
24
24
  };
25
25
  reset({ canvas }: CanvasFactoryContext, width: number, height: number): void;
26
26
  destroy(context: CanvasFactoryContext): void;
@@ -136,6 +136,12 @@ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumen
136
136
  totalPages: number;
137
137
  text: string;
138
138
  }>;
139
+ declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options?: {
140
+ mergePages?: boolean;
141
+ }): Promise<{
142
+ totalPages: number;
143
+ text: string | string[];
144
+ }>;
139
145
 
140
146
  /**
141
147
  * By default, unpdf will use the latest version of PDF.js compiled for
@@ -164,6 +170,7 @@ declare function configureUnPDF(options: {
164
170
  * In Node.js environments, additionally applies:
165
171
  * - `disableFontFace: true`
166
172
  * - `standardFontDataUrl` resolved from the local `pdfjs-dist` package
173
+ * - `cMapUrl` and `cMapPacked` resolved from the local `pdfjs-dist` package
167
174
  */
168
175
  declare function getDocumentProxy(data: DocumentInitParameters['data'], options?: DocumentInitParameters): Promise<PDFDocumentProxy>;
169
176
  declare function getResolvedPDFJS(): Promise<typeof PDFJS>;