unpdf 0.12.2 → 1.0.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 +147 -79
- package/dist/index.cjs +118 -73
- package/dist/index.d.cts +24 -41
- package/dist/index.d.mts +24 -41
- package/dist/index.d.ts +24 -41
- package/dist/index.mjs +117 -72
- package/dist/pdfjs.mjs +1 -1
- package/dist/types/src/display/annotation_layer.d.ts +25 -1
- package/dist/types/src/display/annotation_storage.d.ts +1 -8
- package/dist/types/src/display/api.d.ts +147 -57
- package/dist/types/src/display/canvas.d.ts +21 -28
- package/dist/types/src/display/canvas_factory.d.ts +27 -0
- package/dist/types/src/display/cmap_reader_factory.d.ts +25 -0
- package/dist/types/src/display/display_utils.d.ts +40 -60
- package/dist/types/src/display/draw_layer.d.ts +7 -19
- package/dist/types/src/display/editor/alt_text.d.ts +3 -2
- package/dist/types/src/display/editor/annotation_editor_layer.d.ts +16 -11
- package/dist/types/src/display/editor/color_picker.d.ts +1 -0
- package/dist/types/src/display/editor/draw.d.ts +121 -0
- package/dist/types/src/display/editor/drawers/contour.d.ts +3 -0
- package/dist/types/src/display/editor/drawers/freedraw.d.ts +31 -0
- package/dist/types/src/display/editor/drawers/highlight.d.ts +36 -0
- package/dist/types/src/display/editor/drawers/inkdraw.d.ts +129 -0
- package/dist/types/src/display/editor/drawers/outline.d.ts +19 -0
- package/dist/types/src/display/editor/drawers/signaturedraw.d.ts +79 -0
- package/dist/types/src/display/editor/editor.d.ts +55 -13
- package/dist/types/src/display/editor/freetext.d.ts +5 -16
- package/dist/types/src/display/editor/highlight.d.ts +8 -25
- package/dist/types/src/display/editor/ink.d.ts +21 -74
- package/dist/types/src/display/editor/signature.d.ts +80 -0
- package/dist/types/src/display/editor/stamp.d.ts +16 -22
- package/dist/types/src/display/editor/toolbar.d.ts +5 -2
- package/dist/types/src/display/editor/tools.d.ts +17 -9
- package/dist/types/src/display/fetch_stream.d.ts +6 -13
- package/dist/types/src/display/filter_factory.d.ts +29 -0
- package/dist/types/src/display/font_loader.d.ts +3 -6
- package/dist/types/src/display/metadata.d.ts +1 -2
- package/dist/types/src/display/network.d.ts +11 -7
- package/dist/types/src/display/network_utils.d.ts +7 -6
- package/dist/types/src/display/node_stream.d.ts +6 -22
- package/dist/types/src/display/node_utils.d.ts +15 -11
- package/dist/types/src/display/optional_content_config.d.ts +2 -2
- package/dist/types/src/display/pattern_helper.d.ts +4 -2
- package/dist/types/src/display/standard_fontdata_factory.d.ts +20 -0
- package/dist/types/src/display/svg_factory.d.ts +14 -0
- package/dist/types/src/display/text_layer.d.ts +12 -9
- package/dist/types/src/display/touch_manager.d.ts +18 -0
- package/dist/types/src/display/transport_stream.d.ts +1 -1
- package/dist/types/src/display/wasm_factory.d.ts +20 -0
- package/dist/types/src/display/worker_options.d.ts +2 -2
- package/dist/types/src/interfaces.d.ts +4 -0
- package/dist/types/src/pdf.d.ts +13 -5
- package/dist/types/src/shared/message_handler.d.ts +9 -4
- package/dist/types/src/shared/util.d.ts +137 -129
- package/dist/types/web/annotation_editor_layer_builder.d.ts +20 -5
- package/dist/types/web/annotation_layer_builder.d.ts +35 -4
- package/dist/types/web/app_options.d.ts +1 -1
- package/dist/types/web/autolinker.d.ts +28 -0
- package/dist/types/web/base_pdf_page_view.d.ts +27 -0
- package/dist/types/web/draw_layer_builder.d.ts +13 -2
- package/dist/types/web/event_utils.d.ts +2 -2
- package/dist/types/web/genericl10n.d.ts +5 -5
- package/dist/types/web/interfaces.d.ts +5 -5
- package/dist/types/web/l10n.d.ts +2 -2
- package/dist/types/web/pdf_find_controller.d.ts +2 -0
- package/dist/types/web/pdf_link_service.d.ts +1 -2
- package/dist/types/web/pdf_page_detail_view.d.ts +32 -0
- package/dist/types/web/pdf_page_view.d.ts +44 -23
- package/dist/types/web/pdf_rendering_queue.d.ts +2 -1
- package/dist/types/web/pdf_thumbnail_view.d.ts +23 -3
- package/dist/types/web/pdf_thumbnail_viewer.d.ts +21 -1
- package/dist/types/web/pdf_viewer.d.ts +44 -16
- package/dist/types/web/struct_tree_layer_builder.d.ts +20 -2
- package/dist/types/web/text_accessibility.d.ts +1 -1
- package/dist/types/web/text_layer_builder.d.ts +25 -17
- package/dist/types/web/ui_utils.d.ts +3 -19
- package/dist/types/web/xfa_layer_builder.d.ts +14 -3
- package/package.json +31 -28
- package/dist/types/src/display/base_factory.d.ts +0 -60
- package/dist/types/src/display/editor/outliner.d.ts +0 -70
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# unpdf
|
|
2
2
|
|
|
3
|
-
A collection of utilities
|
|
3
|
+
A collection of utilities for working with PDF files. Designed specifically for Bun, Deno, and serverless environments. However, it also works in Node.js and the browser.
|
|
4
4
|
|
|
5
5
|
`unpdf` ships with a serverless build/redistribution of Mozilla's [PDF.js](https://github.com/mozilla/pdf.js) for serverless environments. Apart from some string replacements and mocks, [`unenv`](https://github.com/unjs/unenv) does the heavy lifting by converting Node.js specific code to be platform-agnostic. See [`pdfjs.rollup.config.ts`](./pdfjs.rollup.config.ts) for all the details.
|
|
6
6
|
|
|
@@ -8,15 +8,18 @@ This library is also intended as a modern alternative to the unmaintained but st
|
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
- 🏗️
|
|
11
|
+
- 🏗️ Made for Node.js, browser and serverless environments
|
|
12
12
|
- 🪭 Includes serverless build of PDF.js ([`unpdf/pdfjs`](./package.json#L34))
|
|
13
|
-
- 💬 Extract text and images from
|
|
13
|
+
- 💬 Extract [text](#extract-text-from-pdf) and [images](#extractimages) from PDF files
|
|
14
14
|
- 🧱 Opt-in to legacy PDF.js build
|
|
15
15
|
- 💨 Zero dependencies
|
|
16
16
|
|
|
17
17
|
## PDF.js Compatibility
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
> [!Tip]
|
|
20
|
+
> The serverless PDF.js bundle provided by `unpdf` is built from PDF.js v5.2.133.
|
|
21
|
+
|
|
22
|
+
You can use an [official PDF.js build](#use-official-or-legacy-pdfjs-build) by using the [`definePDFJSModule`](#definepdfjsmodule) method. This is useful if you want to use a specific version or a custom build of PDF.js.
|
|
20
23
|
|
|
21
24
|
## Installation
|
|
22
25
|
|
|
@@ -24,13 +27,13 @@ Run the following command to add `unpdf` to your project.
|
|
|
24
27
|
|
|
25
28
|
```bash
|
|
26
29
|
# pnpm
|
|
27
|
-
pnpm add unpdf
|
|
30
|
+
pnpm add -D unpdf
|
|
28
31
|
|
|
29
32
|
# npm
|
|
30
|
-
npm install unpdf
|
|
33
|
+
npm install -D unpdf
|
|
31
34
|
|
|
32
35
|
# yarn
|
|
33
|
-
yarn add unpdf
|
|
36
|
+
yarn add -D unpdf
|
|
34
37
|
```
|
|
35
38
|
|
|
36
39
|
## Usage
|
|
@@ -40,32 +43,37 @@ yarn add unpdf
|
|
|
40
43
|
```ts
|
|
41
44
|
import { extractText, getDocumentProxy } from 'unpdf'
|
|
42
45
|
|
|
43
|
-
//
|
|
44
|
-
const buffer = await fetch(
|
|
45
|
-
|
|
46
|
-
).then(res => res.arrayBuffer())
|
|
47
|
-
|
|
48
|
-
// Or load it from the filesystem
|
|
46
|
+
// Either fetch a PDF file from the web or load it from the file system
|
|
47
|
+
const buffer = await fetch('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf')
|
|
48
|
+
.then(res => res.arrayBuffer())
|
|
49
49
|
const buffer = await readFile('./dummy.pdf')
|
|
50
50
|
|
|
51
|
-
//
|
|
51
|
+
// Then, load the PDF file into a PDF.js document
|
|
52
52
|
const pdf = await getDocumentProxy(new Uint8Array(buffer))
|
|
53
|
-
|
|
53
|
+
|
|
54
|
+
// Finally, extract the text from the PDF file
|
|
54
55
|
const { totalPages, text } = await extractText(pdf, { mergePages: true })
|
|
55
56
|
|
|
56
57
|
console.log(`Total pages: ${totalPages}`)
|
|
57
58
|
console.log(text)
|
|
58
59
|
```
|
|
59
60
|
|
|
60
|
-
###
|
|
61
|
+
### PDF.js API
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
`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.
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
- `version`
|
|
66
|
-
- … and all other methods
|
|
65
|
+
Access the PDF.js API directly by calling `getResolvedPDFJS`:
|
|
67
66
|
|
|
68
|
-
|
|
67
|
+
```ts
|
|
68
|
+
import { getResolvedPDFJS } from 'unpdf'
|
|
69
|
+
|
|
70
|
+
const { version } = await getResolvedPDFJS()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
> [!NOTE]
|
|
74
|
+
> If no other PDF.js build was defined, the serverless build will always be used.
|
|
75
|
+
|
|
76
|
+
For example, you can use the `getDocument` method to load a PDF file and then use the `getPage` method to get a specific page. You can also use the `getTextContent` method to extract the text from the page.
|
|
69
77
|
|
|
70
78
|
```ts
|
|
71
79
|
import { getResolvedPDFJS } from 'unpdf'
|
|
@@ -86,55 +94,40 @@ for (let i = 1; i <= doc.numPages; i++) {
|
|
|
86
94
|
|
|
87
95
|
### Use Official or Legacy PDF.js Build
|
|
88
96
|
|
|
89
|
-
|
|
97
|
+
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.
|
|
90
98
|
|
|
91
99
|
> [!WARNING]
|
|
92
|
-
>
|
|
100
|
+
> Later PDF.js v4.x versions uses `Promise.withResolvers`, which may not be supported in all environments, such as Node < 22. Consider to use the bundled serverless build, which includes a polyfill, or use an older version of PDF.js.
|
|
101
|
+
|
|
102
|
+
For example, if you want to use the official PDF.js build, you can do the following:
|
|
93
103
|
|
|
94
104
|
```ts
|
|
95
|
-
|
|
96
|
-
// if you need another PDF.js build
|
|
97
|
-
import { configureUnPDF } from 'unpdf'
|
|
105
|
+
import { definePDFJSModule } from 'unpdf'
|
|
98
106
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
pdfjs: () => import('pdfjs-dist'),
|
|
102
|
-
})
|
|
107
|
+
// Define the PDF.js build before using any other unpdf method
|
|
108
|
+
await definePDFJSModule(() => import('pdfjs-dist'))
|
|
103
109
|
|
|
104
|
-
// Now, you can use the
|
|
105
|
-
|
|
110
|
+
// Now, you can use all unpdf methods with the official PDF.js build
|
|
111
|
+
const { text } = await extractText(pdf)
|
|
106
112
|
```
|
|
107
113
|
|
|
108
|
-
##
|
|
109
|
-
|
|
110
|
-
```ts
|
|
111
|
-
interface UnPDFConfiguration {
|
|
112
|
-
/**
|
|
113
|
-
* By default, UnPDF will use the latest version of PDF.js compiled for
|
|
114
|
-
* serverless environments. If you want to use a different version, you can
|
|
115
|
-
* provide a custom resolver function.
|
|
116
|
-
*
|
|
117
|
-
* @example
|
|
118
|
-
* // Use the official PDF.js build (make sure to install it first)
|
|
119
|
-
* () => import('pdfjs-dist')
|
|
120
|
-
*/
|
|
121
|
-
pdfjs?: () => Promise<PDFJS>
|
|
122
|
-
}
|
|
123
|
-
```
|
|
114
|
+
## API
|
|
124
115
|
|
|
125
|
-
|
|
116
|
+
### `definePDFJSModule`
|
|
126
117
|
|
|
127
|
-
|
|
118
|
+
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.
|
|
128
119
|
|
|
129
|
-
|
|
120
|
+
**Type Declaration**
|
|
130
121
|
|
|
131
122
|
```ts
|
|
132
|
-
function
|
|
123
|
+
function definePDFJSModule(pdfjs: () => Promise<PDFJS>): Promise<void>
|
|
133
124
|
```
|
|
134
125
|
|
|
135
126
|
### `getResolvedPDFJS`
|
|
136
127
|
|
|
137
|
-
Returns the resolved PDF.js module. If no build
|
|
128
|
+
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.
|
|
129
|
+
|
|
130
|
+
**Type Declaration**
|
|
138
131
|
|
|
139
132
|
```ts
|
|
140
133
|
function getResolvedPDFJS(): Promise<PDFJS>
|
|
@@ -142,6 +135,8 @@ function getResolvedPDFJS(): Promise<PDFJS>
|
|
|
142
135
|
|
|
143
136
|
### `getMeta`
|
|
144
137
|
|
|
138
|
+
**Type Declaration**
|
|
139
|
+
|
|
145
140
|
```ts
|
|
146
141
|
function getMeta(
|
|
147
142
|
data: DocumentInitParameters['data'] | PDFDocumentProxy,
|
|
@@ -155,47 +150,109 @@ function getMeta(
|
|
|
155
150
|
|
|
156
151
|
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.
|
|
157
152
|
|
|
153
|
+
**Type Declaration**
|
|
154
|
+
|
|
158
155
|
```ts
|
|
159
156
|
function extractText(
|
|
160
157
|
data: DocumentInitParameters['data'] | PDFDocumentProxy,
|
|
161
|
-
|
|
158
|
+
options?: {
|
|
159
|
+
mergePages?: false
|
|
160
|
+
}
|
|
162
161
|
): Promise<{
|
|
163
162
|
totalPages: number
|
|
164
|
-
text: string
|
|
163
|
+
text: string[]
|
|
164
|
+
}>
|
|
165
|
+
function extractText(
|
|
166
|
+
data: DocumentInitParameters['data'] | PDFDocumentProxy,
|
|
167
|
+
options: {
|
|
168
|
+
mergePages: true
|
|
169
|
+
}
|
|
170
|
+
): Promise<{
|
|
171
|
+
totalPages: number
|
|
172
|
+
text: string
|
|
165
173
|
}>
|
|
166
174
|
```
|
|
167
175
|
|
|
168
|
-
### `
|
|
176
|
+
### `extractImages`
|
|
177
|
+
|
|
178
|
+
Extracts images from a specific page of a PDF document, including necessary metadata such as width, height, and calculated color channels.
|
|
169
179
|
|
|
170
180
|
> [!NOTE]
|
|
171
181
|
> This method will only work in Node.js and browser environments.
|
|
172
182
|
|
|
173
|
-
|
|
183
|
+
In order to use this method, make sure to meet the following requirements:
|
|
174
184
|
|
|
175
|
-
|
|
185
|
+
- Use the official PDF.js build (see below for details).
|
|
186
|
+
- 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.
|
|
176
187
|
|
|
177
|
-
|
|
178
|
-
|
|
188
|
+
**Type Declaration**
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
interface ExtractedImageObject {
|
|
192
|
+
data: Uint8ClampedArray
|
|
193
|
+
width: number
|
|
194
|
+
height: number
|
|
195
|
+
channels: 1 | 3 | 4
|
|
196
|
+
key: string
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function extractImages(
|
|
200
|
+
data: DocumentInitParameters['data'] | PDFDocumentProxy,
|
|
201
|
+
pageNumber: number,
|
|
202
|
+
): Promise<ExtractedImageObject[]>
|
|
203
|
+
```
|
|
179
204
|
|
|
180
205
|
**Example**
|
|
181
206
|
|
|
207
|
+
> [!NOTE]
|
|
208
|
+
> 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.
|
|
209
|
+
|
|
182
210
|
```ts
|
|
183
|
-
import {
|
|
211
|
+
import { readFile, writeFile } from 'node:fs/promises'
|
|
212
|
+
import sharp from 'sharp'
|
|
213
|
+
import { extractImages, getDocumentProxy } from 'unpdf'
|
|
214
|
+
|
|
215
|
+
async function extractPdfImages() {
|
|
216
|
+
const buffer = await readFile('./document.pdf')
|
|
217
|
+
const pdf = await getDocumentProxy(new Uint8Array(buffer))
|
|
218
|
+
|
|
219
|
+
// Extract images from page 1
|
|
220
|
+
const imagesData = await extractImages(pdf, 1)
|
|
221
|
+
console.log(`Found ${imagesData.length} images on page 1`)
|
|
222
|
+
|
|
223
|
+
// Process each image with sharp (optional)
|
|
224
|
+
let totalImagesProcessed = 0
|
|
225
|
+
for (const imgData of imagesData) {
|
|
226
|
+
const imageIndex = ++totalImagesProcessed
|
|
227
|
+
|
|
228
|
+
await sharp(imgData.data, {
|
|
229
|
+
raw: {
|
|
230
|
+
width: imgData.width,
|
|
231
|
+
height: imgData.height,
|
|
232
|
+
channels: imgData.channels
|
|
233
|
+
}
|
|
234
|
+
})
|
|
235
|
+
.png()
|
|
236
|
+
.toFile(`image-${imageIndex}.png`)
|
|
237
|
+
|
|
238
|
+
console.log(`Saved image ${imageIndex} (${imgData.width}x${imgData.height}, ${imgData.channels} channels)`)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
184
241
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
pdfjs: () => import('pdfjs-dist'),
|
|
188
|
-
})
|
|
242
|
+
extractPdfImages().catch(console.error)
|
|
243
|
+
```
|
|
189
244
|
|
|
190
|
-
|
|
191
|
-
const buffer = new Uint8Array(pdf)
|
|
192
|
-
const pageNumber = 1
|
|
245
|
+
### `renderPageAsImage`
|
|
193
246
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
247
|
+
To render a PDF page as an image, you can use the `renderPageAsImage` method. This method will return an `ArrayBuffer` of the rendered image.
|
|
248
|
+
|
|
249
|
+
> [!NOTE]
|
|
250
|
+
> This method will only work in Node.js and browser environments.
|
|
251
|
+
|
|
252
|
+
In order to use this method, make sure to meet the following requirements:
|
|
253
|
+
|
|
254
|
+
- Use the official PDF.js build (see below for details).
|
|
255
|
+
- 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.
|
|
199
256
|
|
|
200
257
|
**Type Declaration**
|
|
201
258
|
|
|
@@ -204,8 +261,8 @@ declare function renderPageAsImage(
|
|
|
204
261
|
data: DocumentInitParameters['data'],
|
|
205
262
|
pageNumber: number,
|
|
206
263
|
options?: {
|
|
207
|
-
|
|
208
|
-
/** @default 1 */
|
|
264
|
+
canvasImport?: () => Promise<typeof import('@napi-rs/canvas')>
|
|
265
|
+
/** @default 1.0 */
|
|
209
266
|
scale?: number
|
|
210
267
|
width?: number
|
|
211
268
|
height?: number
|
|
@@ -213,13 +270,24 @@ declare function renderPageAsImage(
|
|
|
213
270
|
): Promise<ArrayBuffer>
|
|
214
271
|
```
|
|
215
272
|
|
|
216
|
-
|
|
273
|
+
**Example**
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
import { definePDFJSModule, renderPageAsImage } from 'unpdf'
|
|
217
277
|
|
|
218
|
-
|
|
278
|
+
// Use the official PDF.js build
|
|
279
|
+
await definePDFJSModule(() => import('pdfjs-dist'))
|
|
219
280
|
|
|
220
|
-
|
|
281
|
+
const pdf = await readFile('./dummy.pdf')
|
|
282
|
+
const buffer = new Uint8Array(pdf)
|
|
283
|
+
const pageNumber = 1
|
|
221
284
|
|
|
222
|
-
|
|
285
|
+
const result = await renderPageAsImage(buffer, pageNumber, {
|
|
286
|
+
canvasImport: () => import('@napi-rs/canvas'),
|
|
287
|
+
scale: 2,
|
|
288
|
+
})
|
|
289
|
+
await writeFile('dummy-page-1.png', new Uint8Array(result))
|
|
290
|
+
```
|
|
223
291
|
|
|
224
292
|
## License
|
|
225
293
|
|
package/dist/index.cjs
CHANGED
|
@@ -16,24 +16,21 @@ async function getDocumentProxy(data, options = {}) {
|
|
|
16
16
|
}
|
|
17
17
|
async function getResolvedPDFJS() {
|
|
18
18
|
if (!resolvedModule) {
|
|
19
|
-
await
|
|
19
|
+
await resolvePDFJSImport();
|
|
20
20
|
}
|
|
21
21
|
return resolvedModule;
|
|
22
22
|
}
|
|
23
|
-
async function
|
|
24
|
-
if (resolvedModule && !
|
|
23
|
+
async function resolvePDFJSImport(pdfjsResolver, { reload = false } = {}) {
|
|
24
|
+
if (resolvedModule && !reload) {
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
if (pdfjsResolver) {
|
|
28
28
|
try {
|
|
29
29
|
resolvedModule = await interopDefault(pdfjsResolver());
|
|
30
|
-
if (resolvedModule && "resolvePDFJS" in resolvedModule) {
|
|
31
|
-
resolvedModule = await resolvedModule.resolvePDFJS();
|
|
32
|
-
}
|
|
33
30
|
return;
|
|
34
31
|
} catch (error) {
|
|
35
32
|
console.error(error);
|
|
36
|
-
throw new Error("
|
|
33
|
+
throw new Error("PDF.js could not be resolved. Please check the resolver function.");
|
|
37
34
|
}
|
|
38
35
|
}
|
|
39
36
|
try {
|
|
@@ -41,7 +38,7 @@ async function resolvePDFJSImports(pdfjsResolver, { force = false } = {}) {
|
|
|
41
38
|
resolvedModule = await resolvePDFJS();
|
|
42
39
|
} catch (error) {
|
|
43
40
|
console.error(error);
|
|
44
|
-
throw new Error("PDF.js
|
|
41
|
+
throw new Error("PDF.js package not available. Please install it first.");
|
|
45
42
|
}
|
|
46
43
|
}
|
|
47
44
|
function isPDFDocumentProxy(data) {
|
|
@@ -52,6 +49,87 @@ async function interopDefault(m) {
|
|
|
52
49
|
return resolved.default || resolved;
|
|
53
50
|
}
|
|
54
51
|
|
|
52
|
+
let canvasModule;
|
|
53
|
+
/**
|
|
54
|
+
* Derived from the PDF.js project by the Mozilla Foundation.
|
|
55
|
+
* @see https://github.com/mozilla/pdf.js/blob/b8de9a372f9bbf7e33adb362eeae5ef1919dba73/src/display/canvas_factory.js#L18
|
|
56
|
+
* @license Apache-2.0
|
|
57
|
+
*/
|
|
58
|
+
class BaseCanvasFactory {
|
|
59
|
+
#enableHWA = false;
|
|
60
|
+
constructor({ enableHWA = false } = {}) {
|
|
61
|
+
this.#enableHWA = enableHWA;
|
|
62
|
+
}
|
|
63
|
+
create(width, height) {
|
|
64
|
+
const canvas = this._createCanvas(width, height);
|
|
65
|
+
return {
|
|
66
|
+
canvas,
|
|
67
|
+
context: canvas.getContext("2d", {
|
|
68
|
+
willReadFrequently: !this.#enableHWA
|
|
69
|
+
})
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
reset({ canvas }, width, height) {
|
|
73
|
+
if (!canvas) {
|
|
74
|
+
throw new Error("Canvas is not specified");
|
|
75
|
+
}
|
|
76
|
+
canvas.width = width;
|
|
77
|
+
canvas.height = height;
|
|
78
|
+
}
|
|
79
|
+
destroy(context) {
|
|
80
|
+
if (!context.canvas) {
|
|
81
|
+
throw new Error("Canvas is not specified");
|
|
82
|
+
}
|
|
83
|
+
context.canvas.width = 0;
|
|
84
|
+
context.canvas.height = 0;
|
|
85
|
+
context.canvas = void 0;
|
|
86
|
+
context.context = void 0;
|
|
87
|
+
}
|
|
88
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
89
|
+
_createCanvas(width, height) {
|
|
90
|
+
throw new Error("Not implemented");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Derived from the PDF.js project by the Mozilla Foundation.
|
|
95
|
+
* @see https://github.com/mozilla/pdf.js/blob/b8de9a372f9bbf7e33adb362eeae5ef1919dba73/src/display/canvas_factory.js#L18
|
|
96
|
+
* @license Apache-2.0
|
|
97
|
+
*/
|
|
98
|
+
class DOMCanvasFactory extends BaseCanvasFactory {
|
|
99
|
+
_document;
|
|
100
|
+
constructor({ ownerDocument = globalThis.document, enableHWA = false } = {}) {
|
|
101
|
+
super({ enableHWA });
|
|
102
|
+
this._document = ownerDocument;
|
|
103
|
+
}
|
|
104
|
+
_createCanvas(width, height) {
|
|
105
|
+
const canvas = this._document.createElement("canvas");
|
|
106
|
+
canvas.width = width;
|
|
107
|
+
canvas.height = height;
|
|
108
|
+
return canvas;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
class NodeCanvasFactory extends BaseCanvasFactory {
|
|
112
|
+
constructor({ enableHWA = false } = {}) {
|
|
113
|
+
super({ enableHWA });
|
|
114
|
+
}
|
|
115
|
+
_createCanvas(width, height) {
|
|
116
|
+
if (!canvasModule) {
|
|
117
|
+
throw new Error("@napi-rs/canvas module is not resolved");
|
|
118
|
+
}
|
|
119
|
+
return canvasModule.createCanvas(width, height);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async function resolveCanvasModule(canvasImport) {
|
|
123
|
+
canvasModule ??= await interopDefault(canvasImport());
|
|
124
|
+
}
|
|
125
|
+
function injectCanvasConstructors() {
|
|
126
|
+
if (!canvasModule)
|
|
127
|
+
return;
|
|
128
|
+
globalThis.DOMMatrix ??= canvasModule.DOMMatrix;
|
|
129
|
+
globalThis.ImageData ??= canvasModule.ImageData;
|
|
130
|
+
globalThis.Path2D ??= canvasModule.Path2D;
|
|
131
|
+
}
|
|
132
|
+
|
|
55
133
|
async function extractImages$1(data, pageNumber) {
|
|
56
134
|
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
|
|
57
135
|
if (pageNumber < 1 || pageNumber > pdf.numPages) {
|
|
@@ -88,74 +166,41 @@ async function extractImages$1(data, pageNumber) {
|
|
|
88
166
|
return images;
|
|
89
167
|
}
|
|
90
168
|
async function renderPageAsImage$1(data, pageNumber, options = {}) {
|
|
91
|
-
const
|
|
92
|
-
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data, {
|
|
169
|
+
const CanvasFactory = await createIsomorphicCanvasFactory(options.canvasImport);
|
|
170
|
+
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data, { CanvasFactory });
|
|
93
171
|
const page = await pdf.getPage(pageNumber);
|
|
94
172
|
if (pageNumber < 1 || pageNumber > pdf.numPages) {
|
|
95
173
|
throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
|
|
96
174
|
}
|
|
97
|
-
|
|
98
|
-
let
|
|
175
|
+
const defaultViewport = page.getViewport({ scale: 1 });
|
|
176
|
+
let scale = options.scale || 1;
|
|
99
177
|
if (options.width) {
|
|
100
|
-
|
|
178
|
+
scale = options.width / defaultViewport.width;
|
|
101
179
|
} else if (options.height) {
|
|
102
|
-
|
|
180
|
+
scale = options.height / defaultViewport.height;
|
|
103
181
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
const ctx = canvasFactory.create(viewport.width, viewport.height);
|
|
182
|
+
const viewport = page.getViewport({ scale: Math.max(0, scale) });
|
|
183
|
+
const drawingContext = new CanvasFactory().create(viewport.width, viewport.height);
|
|
108
184
|
await page.render({
|
|
109
|
-
canvasContext:
|
|
185
|
+
canvasContext: drawingContext.context,
|
|
110
186
|
viewport
|
|
111
187
|
}).promise;
|
|
112
|
-
const dataUrl =
|
|
188
|
+
const dataUrl = drawingContext.canvas.toDataURL();
|
|
113
189
|
const response = await fetch(dataUrl);
|
|
114
190
|
return await response.arrayBuffer();
|
|
115
191
|
}
|
|
116
|
-
async function createIsomorphicCanvasFactory(
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
canvas2.width = width;
|
|
123
|
-
canvas2.height = height;
|
|
124
|
-
return canvas2;
|
|
125
|
-
}
|
|
126
|
-
if (isNode) {
|
|
127
|
-
if (!_canvas) {
|
|
128
|
-
throw new Error('Failed to resolve "canvas" package.');
|
|
129
|
-
}
|
|
130
|
-
return _canvas.createCanvas(width, height);
|
|
131
|
-
}
|
|
132
|
-
throw new Error("Unsupported environment for canvas creation.");
|
|
133
|
-
},
|
|
134
|
-
create(width, height) {
|
|
135
|
-
const _canvas2 = this._createCanvas(width, height);
|
|
136
|
-
const context = _canvas2.getContext(
|
|
137
|
-
"2d"
|
|
138
|
-
);
|
|
139
|
-
return {
|
|
140
|
-
canvas: _canvas2,
|
|
141
|
-
context
|
|
142
|
-
};
|
|
143
|
-
},
|
|
144
|
-
reset(ctx, width, height) {
|
|
145
|
-
if (ctx.canvas) {
|
|
146
|
-
ctx.canvas.width = width;
|
|
147
|
-
ctx.canvas.height = height;
|
|
148
|
-
}
|
|
149
|
-
},
|
|
150
|
-
destroy(ctx) {
|
|
151
|
-
if (ctx.canvas) {
|
|
152
|
-
ctx.canvas.width = 0;
|
|
153
|
-
ctx.canvas.height = 0;
|
|
154
|
-
}
|
|
155
|
-
ctx.canvas = void 0;
|
|
156
|
-
ctx.context = void 0;
|
|
192
|
+
async function createIsomorphicCanvasFactory(canvasImport) {
|
|
193
|
+
if (isBrowser)
|
|
194
|
+
return DOMCanvasFactory;
|
|
195
|
+
if (isNode) {
|
|
196
|
+
if (!canvasImport) {
|
|
197
|
+
throw new Error('Parameter "canvasImport" is required in Node.js environment.');
|
|
157
198
|
}
|
|
158
|
-
|
|
199
|
+
await resolveCanvasModule(canvasImport);
|
|
200
|
+
injectCanvasConstructors();
|
|
201
|
+
return NodeCanvasFactory;
|
|
202
|
+
}
|
|
203
|
+
throw new Error("Unsupported environment for canvas creation.");
|
|
159
204
|
}
|
|
160
205
|
|
|
161
206
|
async function getMeta$1(data) {
|
|
@@ -168,7 +213,7 @@ async function getMeta$1(data) {
|
|
|
168
213
|
}
|
|
169
214
|
|
|
170
215
|
async function extractText$1(data, options = {}) {
|
|
171
|
-
const { mergePages = false } =
|
|
216
|
+
const { mergePages = false } = options;
|
|
172
217
|
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
|
|
173
218
|
const texts = await Promise.all(
|
|
174
219
|
Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1))
|
|
@@ -184,36 +229,36 @@ async function getPageText(document, pageNumber) {
|
|
|
184
229
|
return content.items.filter((item) => item.str != null).map((item) => item.str + (item.hasEOL ? "\n" : "")).join("");
|
|
185
230
|
}
|
|
186
231
|
|
|
232
|
+
async function definePDFJSModule(pdfjs) {
|
|
233
|
+
await resolvePDFJSImport(pdfjs, { reload: true });
|
|
234
|
+
}
|
|
187
235
|
async function configureUnPDF(options) {
|
|
188
|
-
|
|
189
|
-
if (pdfjs) {
|
|
190
|
-
await resolvePDFJSImports(pdfjs, { force: true });
|
|
191
|
-
}
|
|
236
|
+
await resolvePDFJSImport(options.pdfjs, { reload: true });
|
|
192
237
|
}
|
|
193
238
|
|
|
194
239
|
const getMeta = async (...args) => {
|
|
195
|
-
await
|
|
240
|
+
await resolvePDFJSImport();
|
|
196
241
|
return await getMeta$1(...args);
|
|
197
242
|
};
|
|
198
243
|
const extractText = async (...args) => {
|
|
199
|
-
await
|
|
244
|
+
await resolvePDFJSImport();
|
|
200
245
|
return await extractText$1(...args);
|
|
201
246
|
};
|
|
202
247
|
const extractImages = async (...args) => {
|
|
203
|
-
await
|
|
248
|
+
await resolvePDFJSImport();
|
|
204
249
|
return await extractImages$1(...args);
|
|
205
250
|
};
|
|
206
251
|
const renderPageAsImage = async (...args) => {
|
|
207
|
-
await
|
|
252
|
+
await resolvePDFJSImport();
|
|
208
253
|
return await renderPageAsImage$1(...args);
|
|
209
254
|
};
|
|
210
255
|
|
|
211
256
|
exports.configureUnPDF = configureUnPDF;
|
|
212
|
-
exports.
|
|
257
|
+
exports.definePDFJSModule = definePDFJSModule;
|
|
213
258
|
exports.extractImages = extractImages;
|
|
214
259
|
exports.extractText = extractText;
|
|
215
260
|
exports.getDocumentProxy = getDocumentProxy;
|
|
216
261
|
exports.getMeta = getMeta;
|
|
217
262
|
exports.getResolvedPDFJS = getResolvedPDFJS;
|
|
218
263
|
exports.renderPageAsImage = renderPageAsImage;
|
|
219
|
-
exports.
|
|
264
|
+
exports.resolvePDFJSImport = resolvePDFJSImport;
|