unpdf 0.12.0 → 0.12.2
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 +47 -44
- package/dist/index.cjs +48 -45
- package/dist/index.d.cts +51 -24
- package/dist/index.d.mts +51 -24
- package/dist/index.d.ts +51 -24
- package/dist/index.mjs +48 -45
- package/package.json +10 -13
package/README.md
CHANGED
|
@@ -38,20 +38,23 @@ yarn add unpdf
|
|
|
38
38
|
### Extract Text From PDF
|
|
39
39
|
|
|
40
40
|
```ts
|
|
41
|
-
import { extractText, getDocumentProxy } from
|
|
41
|
+
import { extractText, getDocumentProxy } from 'unpdf'
|
|
42
42
|
|
|
43
43
|
// Fetch a PDF file from the web
|
|
44
44
|
const buffer = await fetch(
|
|
45
|
-
|
|
46
|
-
).then(
|
|
45
|
+
'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
|
|
46
|
+
).then(res => res.arrayBuffer())
|
|
47
47
|
|
|
48
48
|
// Or load it from the filesystem
|
|
49
|
-
const buffer = await readFile(
|
|
49
|
+
const buffer = await readFile('./dummy.pdf')
|
|
50
50
|
|
|
51
51
|
// Load PDF from buffer
|
|
52
|
-
const pdf = await getDocumentProxy(new Uint8Array(buffer))
|
|
52
|
+
const pdf = await getDocumentProxy(new Uint8Array(buffer))
|
|
53
53
|
// Extract text from PDF
|
|
54
|
-
const { totalPages, text } = await extractText(pdf, { mergePages: true })
|
|
54
|
+
const { totalPages, text } = await extractText(pdf, { mergePages: true })
|
|
55
|
+
|
|
56
|
+
console.log(`Total pages: ${totalPages}`)
|
|
57
|
+
console.log(text)
|
|
55
58
|
```
|
|
56
59
|
|
|
57
60
|
### Access the PDF.js API
|
|
@@ -65,19 +68,19 @@ This will return the resolved PDF.js module and gives full access to the PDF.js
|
|
|
65
68
|
Especially useful for platforms like 🦕 Deno or if you want to use the PDF.js API directly. If no custom build was defined beforehand, the serverless build bundled with `unpdf` will be initialized.
|
|
66
69
|
|
|
67
70
|
```ts
|
|
68
|
-
import { getResolvedPDFJS } from
|
|
71
|
+
import { getResolvedPDFJS } from 'unpdf'
|
|
69
72
|
|
|
70
|
-
const { getDocument } = await getResolvedPDFJS()
|
|
71
|
-
const data = Deno.readFileSync(
|
|
72
|
-
const doc = await getDocument(data).promise
|
|
73
|
+
const { getDocument } = await getResolvedPDFJS()
|
|
74
|
+
const data = Deno.readFileSync('dummy.pdf')
|
|
75
|
+
const doc = await getDocument(data).promise
|
|
73
76
|
|
|
74
|
-
console.log(await doc.getMetadata())
|
|
77
|
+
console.log(await doc.getMetadata())
|
|
75
78
|
|
|
76
79
|
for (let i = 1; i <= doc.numPages; i++) {
|
|
77
|
-
const page = await doc.getPage(i)
|
|
78
|
-
const textContent = await page.getTextContent()
|
|
79
|
-
const contents = textContent.items.map(
|
|
80
|
-
console.log(contents)
|
|
80
|
+
const page = await doc.getPage(i)
|
|
81
|
+
const textContent = await page.getTextContent()
|
|
82
|
+
const contents = textContent.items.map(item => item.str).join(' ')
|
|
83
|
+
console.log(contents)
|
|
81
84
|
}
|
|
82
85
|
```
|
|
83
86
|
|
|
@@ -91,12 +94,12 @@ Generally speaking, you don't need to worry about the PDF.js build. `unpdf` ship
|
|
|
91
94
|
```ts
|
|
92
95
|
// Before using any other method, define the PDF.js module
|
|
93
96
|
// if you need another PDF.js build
|
|
94
|
-
import { configureUnPDF } from
|
|
97
|
+
import { configureUnPDF } from 'unpdf'
|
|
95
98
|
|
|
96
99
|
await configureUnPDF({
|
|
97
100
|
// Use the official PDF.js build (make sure to install it first)
|
|
98
|
-
pdfjs: () => import(
|
|
99
|
-
})
|
|
101
|
+
pdfjs: () => import('pdfjs-dist'),
|
|
102
|
+
})
|
|
100
103
|
|
|
101
104
|
// Now, you can use the other methods
|
|
102
105
|
// …
|
|
@@ -115,7 +118,7 @@ interface UnPDFConfiguration {
|
|
|
115
118
|
* // Use the official PDF.js build (make sure to install it first)
|
|
116
119
|
* () => import('pdfjs-dist')
|
|
117
120
|
*/
|
|
118
|
-
pdfjs?: () => Promise<PDFJS
|
|
121
|
+
pdfjs?: () => Promise<PDFJS>
|
|
119
122
|
}
|
|
120
123
|
```
|
|
121
124
|
|
|
@@ -126,7 +129,7 @@ interface UnPDFConfiguration {
|
|
|
126
129
|
Define a custom PDF.js module, like the legacy build. Make sure to call this method before using any other methods.
|
|
127
130
|
|
|
128
131
|
```ts
|
|
129
|
-
function configureUnPDF(config: UnPDFConfiguration): Promise<void
|
|
132
|
+
function configureUnPDF(config: UnPDFConfiguration): Promise<void>
|
|
130
133
|
```
|
|
131
134
|
|
|
132
135
|
### `getResolvedPDFJS`
|
|
@@ -134,18 +137,18 @@ function configureUnPDF(config: UnPDFConfiguration): Promise<void>;
|
|
|
134
137
|
Returns the resolved PDF.js module. If no build is defined, the latest version will be initialized.
|
|
135
138
|
|
|
136
139
|
```ts
|
|
137
|
-
function getResolvedPDFJS(): Promise<PDFJS
|
|
140
|
+
function getResolvedPDFJS(): Promise<PDFJS>
|
|
138
141
|
```
|
|
139
142
|
|
|
140
143
|
### `getMeta`
|
|
141
144
|
|
|
142
145
|
```ts
|
|
143
146
|
function getMeta(
|
|
144
|
-
data: DocumentInitParameters[
|
|
147
|
+
data: DocumentInitParameters['data'] | PDFDocumentProxy,
|
|
145
148
|
): Promise<{
|
|
146
|
-
info: Record<string, any
|
|
147
|
-
metadata: Record<string, any
|
|
148
|
-
}
|
|
149
|
+
info: Record<string, any>
|
|
150
|
+
metadata: Record<string, any>
|
|
151
|
+
}>
|
|
149
152
|
```
|
|
150
153
|
|
|
151
154
|
### `extractText`
|
|
@@ -154,12 +157,12 @@ Extracts all text from a PDF. If `mergePages` is set to `true`, the text of all
|
|
|
154
157
|
|
|
155
158
|
```ts
|
|
156
159
|
function extractText(
|
|
157
|
-
data: DocumentInitParameters[
|
|
160
|
+
data: DocumentInitParameters['data'] | PDFDocumentProxy,
|
|
158
161
|
{ mergePages }?: { mergePages?: boolean },
|
|
159
162
|
): Promise<{
|
|
160
|
-
totalPages: number
|
|
161
|
-
text: string | string[]
|
|
162
|
-
}
|
|
163
|
+
totalPages: number
|
|
164
|
+
text: string | string[]
|
|
165
|
+
}>
|
|
163
166
|
```
|
|
164
167
|
|
|
165
168
|
### `renderPageAsImage`
|
|
@@ -177,37 +180,37 @@ In order to use this method, you have to meet the following requirements:
|
|
|
177
180
|
**Example**
|
|
178
181
|
|
|
179
182
|
```ts
|
|
180
|
-
import { configureUnPDF, renderPageAsImage } from
|
|
183
|
+
import { configureUnPDF, renderPageAsImage } from 'unpdf'
|
|
181
184
|
|
|
182
185
|
await configureUnPDF({
|
|
183
186
|
// Use the official PDF.js build
|
|
184
|
-
pdfjs: () => import(
|
|
185
|
-
})
|
|
187
|
+
pdfjs: () => import('pdfjs-dist'),
|
|
188
|
+
})
|
|
186
189
|
|
|
187
|
-
const pdf = await readFile(
|
|
188
|
-
const buffer = new Uint8Array(pdf)
|
|
189
|
-
const pageNumber = 1
|
|
190
|
+
const pdf = await readFile('./dummy.pdf')
|
|
191
|
+
const buffer = new Uint8Array(pdf)
|
|
192
|
+
const pageNumber = 1
|
|
190
193
|
|
|
191
194
|
const result = await renderPageAsImage(buffer, pageNumber, {
|
|
192
|
-
canvas: () => import(
|
|
193
|
-
})
|
|
194
|
-
await writeFile(
|
|
195
|
+
canvas: () => import('canvas'),
|
|
196
|
+
})
|
|
197
|
+
await writeFile('dummy-page-1.png', result)
|
|
195
198
|
```
|
|
196
199
|
|
|
197
200
|
**Type Declaration**
|
|
198
201
|
|
|
199
202
|
```ts
|
|
200
203
|
declare function renderPageAsImage(
|
|
201
|
-
data: DocumentInitParameters[
|
|
204
|
+
data: DocumentInitParameters['data'],
|
|
202
205
|
pageNumber: number,
|
|
203
206
|
options?: {
|
|
204
|
-
canvas?: () => Promise<typeof import(
|
|
207
|
+
canvas?: () => Promise<typeof import('canvas')>
|
|
205
208
|
/** @default 1 */
|
|
206
|
-
scale?: number
|
|
207
|
-
width?: number
|
|
208
|
-
height?: number
|
|
209
|
+
scale?: number
|
|
210
|
+
width?: number
|
|
211
|
+
height?: number
|
|
209
212
|
},
|
|
210
|
-
): Promise<ArrayBuffer
|
|
213
|
+
): Promise<ArrayBuffer>
|
|
211
214
|
```
|
|
212
215
|
|
|
213
216
|
## FAQ
|
package/dist/index.cjs
CHANGED
|
@@ -33,19 +33,15 @@ async function resolvePDFJSImports(pdfjsResolver, { force = false } = {}) {
|
|
|
33
33
|
return;
|
|
34
34
|
} catch (error) {
|
|
35
35
|
console.error(error);
|
|
36
|
-
throw new Error(
|
|
37
|
-
"Resolving failed. Please check the provided configuration."
|
|
38
|
-
);
|
|
36
|
+
throw new Error("Resolving failed. Please check the provided configuration.");
|
|
39
37
|
}
|
|
40
38
|
}
|
|
41
39
|
try {
|
|
42
|
-
const { resolvePDFJS } = await
|
|
40
|
+
const { resolvePDFJS } = await import('unpdf/pdfjs');
|
|
43
41
|
resolvedModule = await resolvePDFJS();
|
|
44
42
|
} catch (error) {
|
|
45
43
|
console.error(error);
|
|
46
|
-
throw new Error(
|
|
47
|
-
"PDF.js is not available. Please add the package as a dependency."
|
|
48
|
-
);
|
|
44
|
+
throw new Error("PDF.js is not available. Please add the package as a dependency.");
|
|
49
45
|
}
|
|
50
46
|
}
|
|
51
47
|
function isPDFDocumentProxy(data) {
|
|
@@ -56,40 +52,12 @@ async function interopDefault(m) {
|
|
|
56
52
|
return resolved.default || resolved;
|
|
57
53
|
}
|
|
58
54
|
|
|
59
|
-
async function getMeta$1(data) {
|
|
60
|
-
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
|
|
61
|
-
const meta = await pdf.getMetadata();
|
|
62
|
-
return {
|
|
63
|
-
info: meta?.info ?? {},
|
|
64
|
-
metadata: meta?.metadata?.getAll() ?? {}
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async function extractText$1(data, options = {}) {
|
|
69
|
-
const { mergePages = false } = { ...options };
|
|
70
|
-
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
|
|
71
|
-
const texts = await Promise.all(
|
|
72
|
-
Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1))
|
|
73
|
-
);
|
|
74
|
-
return {
|
|
75
|
-
totalPages: pdf.numPages,
|
|
76
|
-
text: mergePages ? texts.join("\n").replace(/\s+/g, " ") : texts
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
async function getPageText(document, pageNumber) {
|
|
80
|
-
const page = await document.getPage(pageNumber);
|
|
81
|
-
const content = await page.getTextContent();
|
|
82
|
-
return content.items.filter((item) => item.str != null).map((item) => item.str + (item.hasEOL ? "\n" : "")).join("");
|
|
83
|
-
}
|
|
84
|
-
|
|
85
55
|
async function extractImages$1(data, pageNumber) {
|
|
86
56
|
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
|
|
87
|
-
const page = await pdf.getPage(pageNumber);
|
|
88
57
|
if (pageNumber < 1 || pageNumber > pdf.numPages) {
|
|
89
|
-
throw new Error(
|
|
90
|
-
`Invalid page number. Must be between 1 and ${pdf.numPages}.`
|
|
91
|
-
);
|
|
58
|
+
throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
|
|
92
59
|
}
|
|
60
|
+
const page = await pdf.getPage(pageNumber);
|
|
93
61
|
const operatorList = await page.getOperatorList();
|
|
94
62
|
const { OPS } = await getResolvedPDFJS();
|
|
95
63
|
const images = [];
|
|
@@ -100,7 +68,22 @@ async function extractImages$1(data, pageNumber) {
|
|
|
100
68
|
}
|
|
101
69
|
const imageKey = operatorList.argsArray[i][0];
|
|
102
70
|
const image = await page.objs.get(imageKey);
|
|
103
|
-
|
|
71
|
+
if (!image || !image.data || !image.width || !image.height) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const { width, height, data: data2 } = image;
|
|
75
|
+
const calculatedChannels = data2.length / (width * height);
|
|
76
|
+
if (![1, 3, 4].includes(calculatedChannels)) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const channels = calculatedChannels;
|
|
80
|
+
images.push({
|
|
81
|
+
data: data2,
|
|
82
|
+
width,
|
|
83
|
+
height,
|
|
84
|
+
channels,
|
|
85
|
+
key: imageKey
|
|
86
|
+
});
|
|
104
87
|
}
|
|
105
88
|
return images;
|
|
106
89
|
}
|
|
@@ -109,9 +92,7 @@ async function renderPageAsImage$1(data, pageNumber, options = {}) {
|
|
|
109
92
|
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data, { canvasFactory });
|
|
110
93
|
const page = await pdf.getPage(pageNumber);
|
|
111
94
|
if (pageNumber < 1 || pageNumber > pdf.numPages) {
|
|
112
|
-
throw new Error(
|
|
113
|
-
`Invalid page number. Must be between 1 and ${pdf.numPages}.`
|
|
114
|
-
);
|
|
95
|
+
throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
|
|
115
96
|
}
|
|
116
97
|
let outputScale = options.scale || 1;
|
|
117
98
|
let viewport = page.getViewport({ scale: outputScale });
|
|
@@ -177,6 +158,32 @@ async function createIsomorphicCanvasFactory(canvas) {
|
|
|
177
158
|
};
|
|
178
159
|
}
|
|
179
160
|
|
|
161
|
+
async function getMeta$1(data) {
|
|
162
|
+
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
|
|
163
|
+
const meta = await pdf.getMetadata();
|
|
164
|
+
return {
|
|
165
|
+
info: meta?.info ?? {},
|
|
166
|
+
metadata: meta?.metadata?.getAll() ?? {}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async function extractText$1(data, options = {}) {
|
|
171
|
+
const { mergePages = false } = { ...options };
|
|
172
|
+
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
|
|
173
|
+
const texts = await Promise.all(
|
|
174
|
+
Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1))
|
|
175
|
+
);
|
|
176
|
+
return {
|
|
177
|
+
totalPages: pdf.numPages,
|
|
178
|
+
text: mergePages ? texts.join("\n").replace(/\s+/g, " ") : texts
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
async function getPageText(document, pageNumber) {
|
|
182
|
+
const page = await document.getPage(pageNumber);
|
|
183
|
+
const content = await page.getTextContent();
|
|
184
|
+
return content.items.filter((item) => item.str != null).map((item) => item.str + (item.hasEOL ? "\n" : "")).join("");
|
|
185
|
+
}
|
|
186
|
+
|
|
180
187
|
async function configureUnPDF(options) {
|
|
181
188
|
const { pdfjs } = { ...options };
|
|
182
189
|
if (pdfjs) {
|
|
@@ -201,10 +208,6 @@ const renderPageAsImage = async (...args) => {
|
|
|
201
208
|
return await renderPageAsImage$1(...args);
|
|
202
209
|
};
|
|
203
210
|
|
|
204
|
-
const pdfjs = {
|
|
205
|
-
__proto__: null
|
|
206
|
-
};
|
|
207
|
-
|
|
208
211
|
exports.configureUnPDF = configureUnPDF;
|
|
209
212
|
exports.createIsomorphicCanvasFactory = createIsomorphicCanvasFactory;
|
|
210
213
|
exports.extractImages = extractImages;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,28 +1,37 @@
|
|
|
1
|
-
import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
|
|
2
1
|
import * as canvas from 'canvas';
|
|
3
2
|
import { Canvas } from 'canvas';
|
|
3
|
+
import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
|
|
4
4
|
import * as _PDFJS from './types/src/pdf';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
6
|
+
interface ExtractedImageObject {
|
|
7
|
+
data: Uint8ClampedArray;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
channels: 1 | 3 | 4;
|
|
11
|
+
key: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Extracts images from a specific page of a PDF document, including necessary metadata,
|
|
15
|
+
* such as width, height, and calculated color channels.
|
|
16
|
+
*
|
|
17
|
+
* This version calculates channels based on image data length, width, and height,
|
|
18
|
+
* as the `kind` property provided by PDF.js might not reliably indicate the actual
|
|
19
|
+
* channel count of the raw pixel data (e.g., returning RGBA data even when kind is 3).
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const imagesData = await extractImages(pdf, pageNum)
|
|
23
|
+
*
|
|
24
|
+
* for (const imgData of imagesData) {
|
|
25
|
+
* const imageIndex = totalImagesProcessed + 1;
|
|
26
|
+
* await sharp(imgData.data, {
|
|
27
|
+
* raw: { width: imgData.width, height: imgData.height, channels: imgData.channels }
|
|
28
|
+
* })
|
|
29
|
+
* .png()
|
|
30
|
+
* .toFile(`${imageIndex}.png`);
|
|
31
|
+
* }
|
|
32
|
+
*/
|
|
33
|
+
declare function extractImages$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number): Promise<ExtractedImageObject[]>;
|
|
34
|
+
declare function renderPageAsImage$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number, options?: {
|
|
26
35
|
canvas?: () => Promise<typeof canvas>;
|
|
27
36
|
/** @default 1 */
|
|
28
37
|
scale?: number;
|
|
@@ -45,6 +54,24 @@ declare function createIsomorphicCanvasFactory(canvas?: () => Promise<typeof can
|
|
|
45
54
|
}): void;
|
|
46
55
|
}>;
|
|
47
56
|
|
|
57
|
+
declare function getMeta$1(data: DocumentInitParameters['data'] | PDFDocumentProxy): Promise<{
|
|
58
|
+
info: Record<string, any>;
|
|
59
|
+
metadata: Record<string, any>;
|
|
60
|
+
}>;
|
|
61
|
+
|
|
62
|
+
declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options?: {
|
|
63
|
+
mergePages?: false;
|
|
64
|
+
}): Promise<{
|
|
65
|
+
totalPages: number;
|
|
66
|
+
text: string[];
|
|
67
|
+
}>;
|
|
68
|
+
declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options: {
|
|
69
|
+
mergePages: true;
|
|
70
|
+
}): Promise<{
|
|
71
|
+
totalPages: number;
|
|
72
|
+
text: string;
|
|
73
|
+
}>;
|
|
74
|
+
|
|
48
75
|
type PDFJS = typeof _PDFJS;
|
|
49
76
|
interface UnPDFConfiguration {
|
|
50
77
|
/**
|
|
@@ -59,6 +86,8 @@ interface UnPDFConfiguration {
|
|
|
59
86
|
pdfjs?: () => Promise<any>;
|
|
60
87
|
}
|
|
61
88
|
|
|
89
|
+
declare function configureUnPDF(options: UnPDFConfiguration): Promise<void>;
|
|
90
|
+
|
|
62
91
|
/**
|
|
63
92
|
* Returns a PDFDocumentProxy instance from a given binary data.
|
|
64
93
|
*
|
|
@@ -66,14 +95,12 @@ interface UnPDFConfiguration {
|
|
|
66
95
|
* - `isEvalSupported: false`
|
|
67
96
|
* - `useSystemFonts: true`
|
|
68
97
|
*/
|
|
69
|
-
declare function getDocumentProxy(data: DocumentInitParameters[
|
|
98
|
+
declare function getDocumentProxy(data: DocumentInitParameters['data'], options?: DocumentInitParameters): Promise<PDFDocumentProxy>;
|
|
70
99
|
declare function getResolvedPDFJS(): Promise<PDFJS>;
|
|
71
100
|
declare function resolvePDFJSImports(pdfjsResolver?: () => Promise<any>, { force }?: {
|
|
72
101
|
force?: boolean | undefined;
|
|
73
102
|
}): Promise<void>;
|
|
74
103
|
|
|
75
|
-
declare function configureUnPDF(options: UnPDFConfiguration): Promise<void>;
|
|
76
|
-
|
|
77
104
|
declare const getMeta: typeof getMeta$1;
|
|
78
105
|
declare const extractText: typeof extractText$1;
|
|
79
106
|
declare const extractImages: typeof extractImages$1;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,28 +1,37 @@
|
|
|
1
|
-
import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
|
|
2
1
|
import * as canvas from 'canvas';
|
|
3
2
|
import { Canvas } from 'canvas';
|
|
3
|
+
import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
|
|
4
4
|
import * as _PDFJS from './types/src/pdf';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
6
|
+
interface ExtractedImageObject {
|
|
7
|
+
data: Uint8ClampedArray;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
channels: 1 | 3 | 4;
|
|
11
|
+
key: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Extracts images from a specific page of a PDF document, including necessary metadata,
|
|
15
|
+
* such as width, height, and calculated color channels.
|
|
16
|
+
*
|
|
17
|
+
* This version calculates channels based on image data length, width, and height,
|
|
18
|
+
* as the `kind` property provided by PDF.js might not reliably indicate the actual
|
|
19
|
+
* channel count of the raw pixel data (e.g., returning RGBA data even when kind is 3).
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const imagesData = await extractImages(pdf, pageNum)
|
|
23
|
+
*
|
|
24
|
+
* for (const imgData of imagesData) {
|
|
25
|
+
* const imageIndex = totalImagesProcessed + 1;
|
|
26
|
+
* await sharp(imgData.data, {
|
|
27
|
+
* raw: { width: imgData.width, height: imgData.height, channels: imgData.channels }
|
|
28
|
+
* })
|
|
29
|
+
* .png()
|
|
30
|
+
* .toFile(`${imageIndex}.png`);
|
|
31
|
+
* }
|
|
32
|
+
*/
|
|
33
|
+
declare function extractImages$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number): Promise<ExtractedImageObject[]>;
|
|
34
|
+
declare function renderPageAsImage$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number, options?: {
|
|
26
35
|
canvas?: () => Promise<typeof canvas>;
|
|
27
36
|
/** @default 1 */
|
|
28
37
|
scale?: number;
|
|
@@ -45,6 +54,24 @@ declare function createIsomorphicCanvasFactory(canvas?: () => Promise<typeof can
|
|
|
45
54
|
}): void;
|
|
46
55
|
}>;
|
|
47
56
|
|
|
57
|
+
declare function getMeta$1(data: DocumentInitParameters['data'] | PDFDocumentProxy): Promise<{
|
|
58
|
+
info: Record<string, any>;
|
|
59
|
+
metadata: Record<string, any>;
|
|
60
|
+
}>;
|
|
61
|
+
|
|
62
|
+
declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options?: {
|
|
63
|
+
mergePages?: false;
|
|
64
|
+
}): Promise<{
|
|
65
|
+
totalPages: number;
|
|
66
|
+
text: string[];
|
|
67
|
+
}>;
|
|
68
|
+
declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options: {
|
|
69
|
+
mergePages: true;
|
|
70
|
+
}): Promise<{
|
|
71
|
+
totalPages: number;
|
|
72
|
+
text: string;
|
|
73
|
+
}>;
|
|
74
|
+
|
|
48
75
|
type PDFJS = typeof _PDFJS;
|
|
49
76
|
interface UnPDFConfiguration {
|
|
50
77
|
/**
|
|
@@ -59,6 +86,8 @@ interface UnPDFConfiguration {
|
|
|
59
86
|
pdfjs?: () => Promise<any>;
|
|
60
87
|
}
|
|
61
88
|
|
|
89
|
+
declare function configureUnPDF(options: UnPDFConfiguration): Promise<void>;
|
|
90
|
+
|
|
62
91
|
/**
|
|
63
92
|
* Returns a PDFDocumentProxy instance from a given binary data.
|
|
64
93
|
*
|
|
@@ -66,14 +95,12 @@ interface UnPDFConfiguration {
|
|
|
66
95
|
* - `isEvalSupported: false`
|
|
67
96
|
* - `useSystemFonts: true`
|
|
68
97
|
*/
|
|
69
|
-
declare function getDocumentProxy(data: DocumentInitParameters[
|
|
98
|
+
declare function getDocumentProxy(data: DocumentInitParameters['data'], options?: DocumentInitParameters): Promise<PDFDocumentProxy>;
|
|
70
99
|
declare function getResolvedPDFJS(): Promise<PDFJS>;
|
|
71
100
|
declare function resolvePDFJSImports(pdfjsResolver?: () => Promise<any>, { force }?: {
|
|
72
101
|
force?: boolean | undefined;
|
|
73
102
|
}): Promise<void>;
|
|
74
103
|
|
|
75
|
-
declare function configureUnPDF(options: UnPDFConfiguration): Promise<void>;
|
|
76
|
-
|
|
77
104
|
declare const getMeta: typeof getMeta$1;
|
|
78
105
|
declare const extractText: typeof extractText$1;
|
|
79
106
|
declare const extractImages: typeof extractImages$1;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,28 +1,37 @@
|
|
|
1
|
-
import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
|
|
2
1
|
import * as canvas from 'canvas';
|
|
3
2
|
import { Canvas } from 'canvas';
|
|
3
|
+
import { DocumentInitParameters, PDFDocumentProxy } from './types/src/display/api';
|
|
4
4
|
import * as _PDFJS from './types/src/pdf';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
6
|
+
interface ExtractedImageObject {
|
|
7
|
+
data: Uint8ClampedArray;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
channels: 1 | 3 | 4;
|
|
11
|
+
key: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Extracts images from a specific page of a PDF document, including necessary metadata,
|
|
15
|
+
* such as width, height, and calculated color channels.
|
|
16
|
+
*
|
|
17
|
+
* This version calculates channels based on image data length, width, and height,
|
|
18
|
+
* as the `kind` property provided by PDF.js might not reliably indicate the actual
|
|
19
|
+
* channel count of the raw pixel data (e.g., returning RGBA data even when kind is 3).
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const imagesData = await extractImages(pdf, pageNum)
|
|
23
|
+
*
|
|
24
|
+
* for (const imgData of imagesData) {
|
|
25
|
+
* const imageIndex = totalImagesProcessed + 1;
|
|
26
|
+
* await sharp(imgData.data, {
|
|
27
|
+
* raw: { width: imgData.width, height: imgData.height, channels: imgData.channels }
|
|
28
|
+
* })
|
|
29
|
+
* .png()
|
|
30
|
+
* .toFile(`${imageIndex}.png`);
|
|
31
|
+
* }
|
|
32
|
+
*/
|
|
33
|
+
declare function extractImages$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number): Promise<ExtractedImageObject[]>;
|
|
34
|
+
declare function renderPageAsImage$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, pageNumber: number, options?: {
|
|
26
35
|
canvas?: () => Promise<typeof canvas>;
|
|
27
36
|
/** @default 1 */
|
|
28
37
|
scale?: number;
|
|
@@ -45,6 +54,24 @@ declare function createIsomorphicCanvasFactory(canvas?: () => Promise<typeof can
|
|
|
45
54
|
}): void;
|
|
46
55
|
}>;
|
|
47
56
|
|
|
57
|
+
declare function getMeta$1(data: DocumentInitParameters['data'] | PDFDocumentProxy): Promise<{
|
|
58
|
+
info: Record<string, any>;
|
|
59
|
+
metadata: Record<string, any>;
|
|
60
|
+
}>;
|
|
61
|
+
|
|
62
|
+
declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options?: {
|
|
63
|
+
mergePages?: false;
|
|
64
|
+
}): Promise<{
|
|
65
|
+
totalPages: number;
|
|
66
|
+
text: string[];
|
|
67
|
+
}>;
|
|
68
|
+
declare function extractText$1(data: DocumentInitParameters['data'] | PDFDocumentProxy, options: {
|
|
69
|
+
mergePages: true;
|
|
70
|
+
}): Promise<{
|
|
71
|
+
totalPages: number;
|
|
72
|
+
text: string;
|
|
73
|
+
}>;
|
|
74
|
+
|
|
48
75
|
type PDFJS = typeof _PDFJS;
|
|
49
76
|
interface UnPDFConfiguration {
|
|
50
77
|
/**
|
|
@@ -59,6 +86,8 @@ interface UnPDFConfiguration {
|
|
|
59
86
|
pdfjs?: () => Promise<any>;
|
|
60
87
|
}
|
|
61
88
|
|
|
89
|
+
declare function configureUnPDF(options: UnPDFConfiguration): Promise<void>;
|
|
90
|
+
|
|
62
91
|
/**
|
|
63
92
|
* Returns a PDFDocumentProxy instance from a given binary data.
|
|
64
93
|
*
|
|
@@ -66,14 +95,12 @@ interface UnPDFConfiguration {
|
|
|
66
95
|
* - `isEvalSupported: false`
|
|
67
96
|
* - `useSystemFonts: true`
|
|
68
97
|
*/
|
|
69
|
-
declare function getDocumentProxy(data: DocumentInitParameters[
|
|
98
|
+
declare function getDocumentProxy(data: DocumentInitParameters['data'], options?: DocumentInitParameters): Promise<PDFDocumentProxy>;
|
|
70
99
|
declare function getResolvedPDFJS(): Promise<PDFJS>;
|
|
71
100
|
declare function resolvePDFJSImports(pdfjsResolver?: () => Promise<any>, { force }?: {
|
|
72
101
|
force?: boolean | undefined;
|
|
73
102
|
}): Promise<void>;
|
|
74
103
|
|
|
75
|
-
declare function configureUnPDF(options: UnPDFConfiguration): Promise<void>;
|
|
76
|
-
|
|
77
104
|
declare const getMeta: typeof getMeta$1;
|
|
78
105
|
declare const extractText: typeof extractText$1;
|
|
79
106
|
declare const extractImages: typeof extractImages$1;
|
package/dist/index.mjs
CHANGED
|
@@ -31,19 +31,15 @@ async function resolvePDFJSImports(pdfjsResolver, { force = false } = {}) {
|
|
|
31
31
|
return;
|
|
32
32
|
} catch (error) {
|
|
33
33
|
console.error(error);
|
|
34
|
-
throw new Error(
|
|
35
|
-
"Resolving failed. Please check the provided configuration."
|
|
36
|
-
);
|
|
34
|
+
throw new Error("Resolving failed. Please check the provided configuration.");
|
|
37
35
|
}
|
|
38
36
|
}
|
|
39
37
|
try {
|
|
40
|
-
const { resolvePDFJS } = await
|
|
38
|
+
const { resolvePDFJS } = await import('unpdf/pdfjs');
|
|
41
39
|
resolvedModule = await resolvePDFJS();
|
|
42
40
|
} catch (error) {
|
|
43
41
|
console.error(error);
|
|
44
|
-
throw new Error(
|
|
45
|
-
"PDF.js is not available. Please add the package as a dependency."
|
|
46
|
-
);
|
|
42
|
+
throw new Error("PDF.js is not available. Please add the package as a dependency.");
|
|
47
43
|
}
|
|
48
44
|
}
|
|
49
45
|
function isPDFDocumentProxy(data) {
|
|
@@ -54,40 +50,12 @@ async function interopDefault(m) {
|
|
|
54
50
|
return resolved.default || resolved;
|
|
55
51
|
}
|
|
56
52
|
|
|
57
|
-
async function getMeta$1(data) {
|
|
58
|
-
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
|
|
59
|
-
const meta = await pdf.getMetadata();
|
|
60
|
-
return {
|
|
61
|
-
info: meta?.info ?? {},
|
|
62
|
-
metadata: meta?.metadata?.getAll() ?? {}
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
async function extractText$1(data, options = {}) {
|
|
67
|
-
const { mergePages = false } = { ...options };
|
|
68
|
-
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
|
|
69
|
-
const texts = await Promise.all(
|
|
70
|
-
Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1))
|
|
71
|
-
);
|
|
72
|
-
return {
|
|
73
|
-
totalPages: pdf.numPages,
|
|
74
|
-
text: mergePages ? texts.join("\n").replace(/\s+/g, " ") : texts
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
async function getPageText(document, pageNumber) {
|
|
78
|
-
const page = await document.getPage(pageNumber);
|
|
79
|
-
const content = await page.getTextContent();
|
|
80
|
-
return content.items.filter((item) => item.str != null).map((item) => item.str + (item.hasEOL ? "\n" : "")).join("");
|
|
81
|
-
}
|
|
82
|
-
|
|
83
53
|
async function extractImages$1(data, pageNumber) {
|
|
84
54
|
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
|
|
85
|
-
const page = await pdf.getPage(pageNumber);
|
|
86
55
|
if (pageNumber < 1 || pageNumber > pdf.numPages) {
|
|
87
|
-
throw new Error(
|
|
88
|
-
`Invalid page number. Must be between 1 and ${pdf.numPages}.`
|
|
89
|
-
);
|
|
56
|
+
throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
|
|
90
57
|
}
|
|
58
|
+
const page = await pdf.getPage(pageNumber);
|
|
91
59
|
const operatorList = await page.getOperatorList();
|
|
92
60
|
const { OPS } = await getResolvedPDFJS();
|
|
93
61
|
const images = [];
|
|
@@ -98,7 +66,22 @@ async function extractImages$1(data, pageNumber) {
|
|
|
98
66
|
}
|
|
99
67
|
const imageKey = operatorList.argsArray[i][0];
|
|
100
68
|
const image = await page.objs.get(imageKey);
|
|
101
|
-
|
|
69
|
+
if (!image || !image.data || !image.width || !image.height) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const { width, height, data: data2 } = image;
|
|
73
|
+
const calculatedChannels = data2.length / (width * height);
|
|
74
|
+
if (![1, 3, 4].includes(calculatedChannels)) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const channels = calculatedChannels;
|
|
78
|
+
images.push({
|
|
79
|
+
data: data2,
|
|
80
|
+
width,
|
|
81
|
+
height,
|
|
82
|
+
channels,
|
|
83
|
+
key: imageKey
|
|
84
|
+
});
|
|
102
85
|
}
|
|
103
86
|
return images;
|
|
104
87
|
}
|
|
@@ -107,9 +90,7 @@ async function renderPageAsImage$1(data, pageNumber, options = {}) {
|
|
|
107
90
|
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data, { canvasFactory });
|
|
108
91
|
const page = await pdf.getPage(pageNumber);
|
|
109
92
|
if (pageNumber < 1 || pageNumber > pdf.numPages) {
|
|
110
|
-
throw new Error(
|
|
111
|
-
`Invalid page number. Must be between 1 and ${pdf.numPages}.`
|
|
112
|
-
);
|
|
93
|
+
throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
|
|
113
94
|
}
|
|
114
95
|
let outputScale = options.scale || 1;
|
|
115
96
|
let viewport = page.getViewport({ scale: outputScale });
|
|
@@ -175,6 +156,32 @@ async function createIsomorphicCanvasFactory(canvas) {
|
|
|
175
156
|
};
|
|
176
157
|
}
|
|
177
158
|
|
|
159
|
+
async function getMeta$1(data) {
|
|
160
|
+
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
|
|
161
|
+
const meta = await pdf.getMetadata();
|
|
162
|
+
return {
|
|
163
|
+
info: meta?.info ?? {},
|
|
164
|
+
metadata: meta?.metadata?.getAll() ?? {}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function extractText$1(data, options = {}) {
|
|
169
|
+
const { mergePages = false } = { ...options };
|
|
170
|
+
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data);
|
|
171
|
+
const texts = await Promise.all(
|
|
172
|
+
Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1))
|
|
173
|
+
);
|
|
174
|
+
return {
|
|
175
|
+
totalPages: pdf.numPages,
|
|
176
|
+
text: mergePages ? texts.join("\n").replace(/\s+/g, " ") : texts
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
async function getPageText(document, pageNumber) {
|
|
180
|
+
const page = await document.getPage(pageNumber);
|
|
181
|
+
const content = await page.getTextContent();
|
|
182
|
+
return content.items.filter((item) => item.str != null).map((item) => item.str + (item.hasEOL ? "\n" : "")).join("");
|
|
183
|
+
}
|
|
184
|
+
|
|
178
185
|
async function configureUnPDF(options) {
|
|
179
186
|
const { pdfjs } = { ...options };
|
|
180
187
|
if (pdfjs) {
|
|
@@ -199,8 +206,4 @@ const renderPageAsImage = async (...args) => {
|
|
|
199
206
|
return await renderPageAsImage$1(...args);
|
|
200
207
|
};
|
|
201
208
|
|
|
202
|
-
const pdfjs = {
|
|
203
|
-
__proto__: null
|
|
204
|
-
};
|
|
205
|
-
|
|
206
209
|
export { configureUnPDF, createIsomorphicCanvasFactory, extractImages, extractText, getDocumentProxy, getMeta, getResolvedPDFJS, renderPageAsImage, resolvePDFJSImports };
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unpdf",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.12.
|
|
5
|
-
"packageManager": "pnpm@9.
|
|
4
|
+
"version": "0.12.2",
|
|
5
|
+
"packageManager": "pnpm@9.12.1",
|
|
6
6
|
"description": "Utilities to work with PDFs in Node.js, browser and workers",
|
|
7
7
|
"author": "Johann Schopplich <hello@johannschopplich.com>",
|
|
8
8
|
"license": "MIT",
|
|
@@ -56,9 +56,7 @@
|
|
|
56
56
|
"build:pdfjs": "rollup --config pdfjs.rollup.config.ts --configPlugin typescript && cp -R node_modules/pdfjs-dist/types dist",
|
|
57
57
|
"dev": "unbuild --stub",
|
|
58
58
|
"lint": "eslint .",
|
|
59
|
-
"lint:fix": "
|
|
60
|
-
"format": "prettier \"**/*.{json,md,cjs,mjs,ts,yml}\" --write",
|
|
61
|
-
"format:check": "prettier \"**/*.{json,md,cjs,mjs,ts,yml}\" --check",
|
|
59
|
+
"lint:fix": "eslint . --fix",
|
|
62
60
|
"release": "bumpp",
|
|
63
61
|
"test": "vitest",
|
|
64
62
|
"test:types": "tsc --noEmit"
|
|
@@ -67,6 +65,7 @@
|
|
|
67
65
|
"canvas": "^2.11.2"
|
|
68
66
|
},
|
|
69
67
|
"devDependencies": {
|
|
68
|
+
"@antfu/eslint-config": "^3.7.3",
|
|
70
69
|
"@rollup/plugin-alias": "^5.1.1",
|
|
71
70
|
"@rollup/plugin-commonjs": "^28.0.0",
|
|
72
71
|
"@rollup/plugin-inject": "^5.0.5",
|
|
@@ -74,19 +73,17 @@
|
|
|
74
73
|
"@rollup/plugin-replace": "^6.0.1",
|
|
75
74
|
"@rollup/plugin-terser": "^0.4.4",
|
|
76
75
|
"@rollup/plugin-typescript": "^12.1.0",
|
|
77
|
-
"@types/node": "^20.16.
|
|
76
|
+
"@types/node": "^20.16.11",
|
|
78
77
|
"bumpp": "^9.6.1",
|
|
79
|
-
"eslint": "^9.
|
|
80
|
-
"eslint-config-unjs": "^0.4.1",
|
|
78
|
+
"eslint": "^9.12.0",
|
|
81
79
|
"fast-glob": "^3.3.2",
|
|
82
|
-
"pdfjs-dist": "
|
|
83
|
-
"
|
|
84
|
-
"rollup": "^4.22.5",
|
|
80
|
+
"pdfjs-dist": "~4.6.82",
|
|
81
|
+
"rollup": "^4.24.0",
|
|
85
82
|
"tslib": "^2.7.0",
|
|
86
83
|
"typescript": "^5.5.4",
|
|
87
|
-
"unbuild": "^3.0.0-rc.
|
|
84
|
+
"unbuild": "^3.0.0-rc.11",
|
|
88
85
|
"unenv": "^1.10.0",
|
|
89
|
-
"vitest": "^2.1.
|
|
86
|
+
"vitest": "^2.1.2"
|
|
90
87
|
},
|
|
91
88
|
"pnpm": {
|
|
92
89
|
"patchedDependencies": {
|