unpdf 1.7.0 → 1.8.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 +3 -3
- package/dist/index.cjs +382 -384
- package/dist/index.d.cts +97 -94
- package/dist/index.d.mts +97 -94
- package/dist/index.mjs +381 -382
- package/dist/pdfjs.mjs +52 -59
- package/dist/types/external/brotli/decode.d.ts +5 -0
- package/dist/types/external/jbig2/jbig2.d.ts +2 -0
- package/dist/types/external/openjpeg/openjpeg.d.ts +2 -0
- package/dist/types/external/qcms/qcms.d.ts +92 -0
- package/dist/types/external/qcms/qcms_utils.d.ts +14 -0
- package/dist/types/src/core/ascii_85_stream.d.ts +7 -0
- package/dist/types/src/core/ascii_hex_stream.d.ts +7 -0
- package/dist/types/src/core/base_stream.d.ts +45 -0
- package/dist/types/src/core/brotli_stream.d.ts +9 -0
- package/dist/types/src/core/calculate_md5.d.ts +1 -0
- package/dist/types/src/core/calculate_sha256.d.ts +1 -0
- package/dist/types/src/core/calculate_sha_other.d.ts +2 -0
- package/dist/types/src/core/catalog.d.ts +169 -0
- package/dist/types/src/core/ccitt_stream.d.ts +18 -0
- package/dist/types/src/core/cleanup_helper.d.ts +1 -0
- package/dist/types/src/core/colorspace.d.ts +177 -0
- package/dist/types/src/core/colorspace_utils.d.ts +21 -0
- package/dist/types/src/core/core_utils.d.ts +132 -0
- package/dist/types/src/core/crypto.d.ts +136 -0
- package/dist/types/src/core/decode_stream.d.ts +32 -0
- package/dist/types/src/core/decrypt_stream.d.ts +9 -0
- package/dist/types/src/core/file_spec.d.ts +72 -0
- package/dist/types/src/core/flate_stream.d.ts +14 -0
- package/dist/types/src/core/icc_colorspace.d.ts +22 -0
- package/dist/types/src/core/image_utils.d.ts +52 -0
- package/dist/types/src/core/jbig2_ccittFax.d.ts +13 -0
- package/dist/types/src/core/jbig2_stream.d.ts +17 -0
- package/dist/types/src/core/jpeg_stream.d.ts +24 -0
- package/dist/types/src/core/jpg.d.ts +62 -0
- package/dist/types/src/core/jpx.d.ts +24 -0
- package/dist/types/src/core/jpx_stream.d.ts +15 -0
- package/dist/types/src/core/lzw_stream.d.ts +19 -0
- package/dist/types/src/core/metadata_parser.d.ts +13 -0
- package/dist/types/src/core/name_number_tree.d.ts +21 -0
- package/dist/types/src/core/parser.d.ts +121 -0
- package/dist/types/src/core/pattern.d.ts +63 -0
- package/dist/types/src/core/predictor_stream.d.ts +14 -0
- package/dist/types/src/core/primitives.d.ts +81 -0
- package/dist/types/src/core/run_length_stream.d.ts +6 -0
- package/dist/types/src/core/stream.d.ts +20 -0
- package/dist/types/src/core/string_utils.d.ts +5 -0
- package/dist/types/src/core/struct_tree.d.ts +93 -0
- package/dist/types/src/core/unicode.d.ts +5 -0
- package/dist/types/src/core/wasm_image.d.ts +21 -0
- package/dist/types/src/core/xml_parser.d.ts +79 -0
- package/dist/types/src/core/xref.d.ts +52 -0
- package/dist/types/src/display/annotation_layer.d.ts +10 -8
- package/dist/types/src/display/api.d.ts +92 -65
- package/dist/types/src/display/binary_data_factory.d.ts +0 -4
- package/dist/types/src/display/canvas.d.ts +58 -12
- package/dist/types/src/display/canvas_dependency_tracker.d.ts +2 -2
- package/dist/types/src/display/display_utils.d.ts +4 -156
- package/dist/types/src/display/draw_layer.d.ts +127 -2
- package/dist/types/src/display/editor/alt_text.d.ts +1 -1
- package/dist/types/src/display/editor/annotation_editor_layer.d.ts +3 -3
- package/dist/types/src/display/editor/color_picker.d.ts +3 -2
- package/dist/types/src/display/editor/draw.d.ts +10 -3
- package/dist/types/src/display/editor/drawers/freedraw.d.ts +3 -3
- package/dist/types/src/display/editor/drawers/highlight.d.ts +0 -1
- package/dist/types/src/display/editor/drawers/outline.d.ts +0 -1
- package/dist/types/src/display/editor/drawers/signaturedraw.d.ts +13 -13
- package/dist/types/src/display/editor/editor.d.ts +2 -1
- package/dist/types/src/display/editor/freetext.d.ts +2 -2
- package/dist/types/src/display/editor/highlight.d.ts +3 -3
- package/dist/types/src/display/editor/ink.d.ts +2 -0
- package/dist/types/src/display/editor/toolbar.d.ts +2 -2
- package/dist/types/src/display/editor/tools.d.ts +31 -14
- package/dist/types/src/display/filter_factory.d.ts +26 -0
- package/dist/types/src/display/node_utils.d.ts +2 -2
- package/dist/types/src/display/obj_bin_transform_display.d.ts +2 -6
- package/dist/types/src/display/optional_content_config.d.ts +13 -3
- package/dist/types/src/display/page_viewport.d.ts +137 -0
- package/dist/types/src/display/pattern_helper.d.ts +11 -4
- package/dist/types/src/display/text_layer.d.ts +10 -10
- package/dist/types/src/display/text_layer_images.d.ts +1 -1
- package/dist/types/src/display/webgpu.d.ts +11 -0
- package/dist/types/src/display/worker_options.d.ts +2 -2
- package/dist/types/src/display/xfa_layer.d.ts +8 -1
- package/dist/types/src/pdf.d.ts +5 -4
- package/dist/types/src/shared/image_utils.d.ts +11 -0
- package/dist/types/src/shared/internal_evt.d.ts +7 -0
- package/dist/types/src/shared/math_clamp.d.ts +1 -0
- package/dist/types/src/shared/util.d.ts +24 -13
- package/dist/types/web/annotation_editor_layer_builder.d.ts +1 -1
- package/dist/types/web/annotation_layer_builder.d.ts +6 -3
- package/dist/types/web/app_options.d.ts +1 -1
- package/dist/types/web/autolinker.d.ts +3 -3
- package/dist/types/web/base_pdf_page_view.d.ts +1 -0
- package/dist/types/web/comment_manager.d.ts +1 -1
- package/dist/types/web/draw_layer_builder.d.ts +44 -0
- package/dist/types/web/event_utils.d.ts +0 -8
- package/dist/types/web/generic_scripting.d.ts +1 -1
- package/dist/types/web/genericl10n.d.ts +5 -5
- package/dist/types/web/internal_evt.d.ts +7 -0
- package/dist/types/web/l10n.d.ts +2 -2
- package/dist/types/web/pdf_find_controller.d.ts +12 -1
- package/dist/types/web/pdf_link_service.d.ts +8 -0
- package/dist/types/web/pdf_page_view.d.ts +10 -3
- package/dist/types/web/pdf_thumbnail_view.d.ts +5 -5
- package/dist/types/web/pdf_thumbnail_viewer.d.ts +31 -12
- package/dist/types/web/pdf_viewer.d.ts +15 -1
- package/dist/types/web/text_accessibility.d.ts +1 -1
- package/dist/types/web/text_layer_builder.d.ts +5 -5
- package/dist/types/web/xfa_layer_builder.d.ts +3 -3
- package/package.json +23 -23
- package/dist/index.d.ts +0 -189
- package/dist/types/src/display/webgpu_mesh.d.ts +0 -3
package/dist/index.cjs
CHANGED
|
@@ -1,455 +1,453 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/_internal/dommatrix-polyfill.ts
|
|
3
3
|
function polyfillDOMMatrix() {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
this.a *= sx;
|
|
37
|
-
this.b *= sx;
|
|
38
|
-
this.c *= sy;
|
|
39
|
-
this.d *= sy;
|
|
40
|
-
return this;
|
|
41
|
-
}
|
|
42
|
-
};
|
|
4
|
+
if (typeof globalThis.DOMMatrix !== "undefined") return;
|
|
5
|
+
globalThis.DOMMatrix = class DOMMatrix {
|
|
6
|
+
constructor(init) {
|
|
7
|
+
if (Array.isArray(init) && init.length === 6) {
|
|
8
|
+
this.a = init[0];
|
|
9
|
+
this.b = init[1];
|
|
10
|
+
this.c = init[2];
|
|
11
|
+
this.d = init[3];
|
|
12
|
+
this.e = init[4];
|
|
13
|
+
this.f = init[5];
|
|
14
|
+
} else {
|
|
15
|
+
this.a = 1;
|
|
16
|
+
this.b = 0;
|
|
17
|
+
this.c = 0;
|
|
18
|
+
this.d = 1;
|
|
19
|
+
this.e = 0;
|
|
20
|
+
this.f = 0;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
translateSelf(tx, ty = 0) {
|
|
24
|
+
this.e = this.a * tx + this.c * ty + this.e;
|
|
25
|
+
this.f = this.b * tx + this.d * ty + this.f;
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
scaleSelf(sx, sy = sx) {
|
|
29
|
+
this.a *= sx;
|
|
30
|
+
this.b *= sx;
|
|
31
|
+
this.c *= sy;
|
|
32
|
+
this.d *= sy;
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
43
36
|
}
|
|
44
|
-
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/_internal/env.ts
|
|
39
|
+
/**
|
|
40
|
+
* Stubs browser globals that PDF.js expects at the module level
|
|
41
|
+
* in non-browser environments.
|
|
42
|
+
*
|
|
43
|
+
* @remarks
|
|
44
|
+
* Must be called before importing any PDF.js module, since PDF.js
|
|
45
|
+
* accesses these globals at parse time (top-level constants).
|
|
46
|
+
*/
|
|
45
47
|
function stubBrowserGlobals() {
|
|
46
|
-
|
|
48
|
+
polyfillDOMMatrix();
|
|
47
49
|
}
|
|
48
|
-
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region src/utils.ts
|
|
49
52
|
let resolvedModule;
|
|
50
53
|
const isNode = globalThis.process?.release?.name === "node";
|
|
51
54
|
const isBrowser = typeof window !== "undefined";
|
|
55
|
+
/**
|
|
56
|
+
* Returns a PDFDocumentProxy instance from a given binary data.
|
|
57
|
+
*
|
|
58
|
+
* Applies the following defaults:
|
|
59
|
+
* - `useSystemFonts: true`
|
|
60
|
+
*
|
|
61
|
+
* In Node.js environments, additionally applies:
|
|
62
|
+
* - `disableFontFace: true`
|
|
63
|
+
* - `standardFontDataUrl` resolved from the local `pdfjs-dist` package
|
|
64
|
+
* - `cMapUrl` and `cMapPacked` resolved from the local `pdfjs-dist` package
|
|
65
|
+
*/
|
|
52
66
|
async function getDocumentProxy(data, options = {}) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
// See: https://github.com/mozilla/pdf.js/issues/4244#issuecomment-1479534301
|
|
71
|
-
useSystemFonts: true,
|
|
72
|
-
...nodeDefaults,
|
|
73
|
-
...options
|
|
74
|
-
}).promise;
|
|
75
|
-
return pdf;
|
|
67
|
+
const { getDocument } = await getResolvedPDFJS();
|
|
68
|
+
let nodeDefaults = {};
|
|
69
|
+
if (isNode) try {
|
|
70
|
+
const base = {}.resolve("pdfjs-dist/package.json");
|
|
71
|
+
nodeDefaults = {
|
|
72
|
+
disableFontFace: true,
|
|
73
|
+
standardFontDataUrl: new URL("./standard_fonts/", base).href,
|
|
74
|
+
cMapUrl: new URL("./cmaps/", base).href,
|
|
75
|
+
cMapPacked: true
|
|
76
|
+
};
|
|
77
|
+
} catch {}
|
|
78
|
+
return await getDocument({
|
|
79
|
+
data,
|
|
80
|
+
useSystemFonts: true,
|
|
81
|
+
...nodeDefaults,
|
|
82
|
+
...options
|
|
83
|
+
}).promise;
|
|
76
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Runs an operation on a `PDFDocumentProxy` resolved from either binary data
|
|
87
|
+
* or an existing proxy. Documents created here are destroyed once the
|
|
88
|
+
* operation settles – caller-supplied proxies keep their lifecycle with the
|
|
89
|
+
* caller.
|
|
90
|
+
*/
|
|
77
91
|
async function withDocument(data, operation, options) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
92
|
+
const pdf = isPDFDocumentProxy(data) ? data : await getDocumentProxy(data, options);
|
|
93
|
+
try {
|
|
94
|
+
return await operation(pdf);
|
|
95
|
+
} finally {
|
|
96
|
+
if (pdf !== data) await pdf.loadingTask.destroy();
|
|
97
|
+
}
|
|
85
98
|
}
|
|
86
99
|
async function getResolvedPDFJS() {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
return resolvedModule;
|
|
100
|
+
if (!resolvedModule) await resolvePDFJSImport();
|
|
101
|
+
return resolvedModule;
|
|
91
102
|
}
|
|
92
103
|
async function resolvePDFJSImport(pdfjsResolver, { reload = false } = {}) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
resolvedModule = await import('unpdf/pdfjs');
|
|
107
|
-
} catch (error) {
|
|
108
|
-
throw new Error(`Serverless PDF.js bundle could not be resolved: ${error}`);
|
|
109
|
-
}
|
|
104
|
+
if (resolvedModule && !reload) return;
|
|
105
|
+
stubBrowserGlobals();
|
|
106
|
+
if (pdfjsResolver) try {
|
|
107
|
+
resolvedModule = await interopDefault(pdfjsResolver());
|
|
108
|
+
return;
|
|
109
|
+
} catch (error) {
|
|
110
|
+
throw new Error(`PDF.js could not be resolved: ${error}`);
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
resolvedModule = await import("unpdf/pdfjs");
|
|
114
|
+
} catch (error) {
|
|
115
|
+
throw new Error(`Serverless PDF.js bundle could not be resolved: ${error}`);
|
|
116
|
+
}
|
|
110
117
|
}
|
|
111
118
|
function isPDFDocumentProxy(data) {
|
|
112
|
-
|
|
119
|
+
return typeof data === "object" && data !== null && "_pdfInfo" in data;
|
|
113
120
|
}
|
|
114
121
|
async function interopDefault(m) {
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
const resolved = await m;
|
|
123
|
+
return resolved.default || resolved;
|
|
117
124
|
}
|
|
118
|
-
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/_internal/canvas.ts
|
|
119
127
|
let resolvedCanvasModule;
|
|
120
128
|
/**
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
context.context = void 0;
|
|
154
|
-
}
|
|
155
|
-
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
156
|
-
_createCanvas(width, height) {
|
|
157
|
-
throw new Error("Not implemented");
|
|
158
|
-
}
|
|
159
|
-
}
|
|
129
|
+
* Derived from the PDF.js project by the Mozilla Foundation.
|
|
130
|
+
* @see https://github.com/mozilla/pdf.js/blob/b8de9a372f9bbf7e33adb362eeae5ef1919dba73/src/display/canvas_factory.js#L18
|
|
131
|
+
* @license Apache-2.0
|
|
132
|
+
*/
|
|
133
|
+
var BaseCanvasFactory = class {
|
|
134
|
+
#enableHWA = false;
|
|
135
|
+
constructor({ enableHWA = false } = {}) {
|
|
136
|
+
this.#enableHWA = enableHWA;
|
|
137
|
+
}
|
|
138
|
+
create(width, height) {
|
|
139
|
+
const canvas = this._createCanvas(width, height);
|
|
140
|
+
return {
|
|
141
|
+
canvas,
|
|
142
|
+
context: canvas.getContext("2d", { willReadFrequently: !this.#enableHWA })
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
reset({ canvas }, width, height) {
|
|
146
|
+
if (!canvas) throw new Error("Canvas is not specified");
|
|
147
|
+
canvas.width = width;
|
|
148
|
+
canvas.height = height;
|
|
149
|
+
}
|
|
150
|
+
destroy(context) {
|
|
151
|
+
if (!context.canvas) throw new Error("Canvas is not specified");
|
|
152
|
+
context.canvas.width = 0;
|
|
153
|
+
context.canvas.height = 0;
|
|
154
|
+
context.canvas = void 0;
|
|
155
|
+
context.context = void 0;
|
|
156
|
+
}
|
|
157
|
+
_createCanvas(width, height) {
|
|
158
|
+
throw new Error("Not implemented");
|
|
159
|
+
}
|
|
160
|
+
};
|
|
160
161
|
/**
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
return resolvedCanvasModule.createCanvas(width, height);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
162
|
+
* Derived from the PDF.js project by the Mozilla Foundation.
|
|
163
|
+
* @see https://github.com/mozilla/pdf.js/blob/b8de9a372f9bbf7e33adb362eeae5ef1919dba73/src/display/canvas_factory.js#L18
|
|
164
|
+
* @license Apache-2.0
|
|
165
|
+
*/
|
|
166
|
+
var DOMCanvasFactory = class extends BaseCanvasFactory {
|
|
167
|
+
constructor({ ownerDocument = globalThis.document, enableHWA = false } = {}) {
|
|
168
|
+
super({ enableHWA });
|
|
169
|
+
this._document = ownerDocument;
|
|
170
|
+
}
|
|
171
|
+
_createCanvas(width, height) {
|
|
172
|
+
const canvas = this._document.createElement("canvas");
|
|
173
|
+
canvas.width = width;
|
|
174
|
+
canvas.height = height;
|
|
175
|
+
return canvas;
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
var NodeCanvasFactory = class extends BaseCanvasFactory {
|
|
179
|
+
constructor({ enableHWA = false } = {}) {
|
|
180
|
+
super({ enableHWA });
|
|
181
|
+
}
|
|
182
|
+
_createCanvas(width, height) {
|
|
183
|
+
if (!resolvedCanvasModule) throw new Error("@napi-rs/canvas module is not resolved");
|
|
184
|
+
return resolvedCanvasModule.createCanvas(width, height);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
189
187
|
async function resolveCanvasModule(canvasImport) {
|
|
190
|
-
|
|
191
|
-
|
|
188
|
+
resolvedCanvasModule ??= await interopDefault(canvasImport());
|
|
189
|
+
globalThis[Symbol.for("unpdf.canvasModule")] = resolvedCanvasModule;
|
|
192
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Injects `DOMMatrix`, `ImageData` and `Path2D` constructors from the
|
|
193
|
+
* `@napi-rs/canvas` package into the global scope. This is necessary for
|
|
194
|
+
* Node.js environments that do not support these constructors natively.
|
|
195
|
+
*
|
|
196
|
+
* @remarks
|
|
197
|
+
* `DOMMatrix` is always set because {@link stubBrowserGlobals} may have
|
|
198
|
+
* installed a minimal stub to allow PDF.js to import – the real
|
|
199
|
+
* `@napi-rs/canvas` implementation must take precedence for rendering.
|
|
200
|
+
*/
|
|
193
201
|
function injectCanvasConstructors() {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
globalThis.ImageData = resolvedCanvasModule.ImageData;
|
|
199
|
-
if (typeof globalThis.Path2D === "undefined")
|
|
200
|
-
globalThis.Path2D = resolvedCanvasModule.Path2D;
|
|
202
|
+
if (!resolvedCanvasModule) return;
|
|
203
|
+
globalThis.DOMMatrix = resolvedCanvasModule.DOMMatrix;
|
|
204
|
+
if (typeof globalThis.ImageData === "undefined") globalThis.ImageData = resolvedCanvasModule.ImageData;
|
|
205
|
+
if (typeof globalThis.Path2D === "undefined") globalThis.Path2D = resolvedCanvasModule.Path2D;
|
|
201
206
|
}
|
|
202
|
-
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region src/image.ts
|
|
209
|
+
/**
|
|
210
|
+
* Extracts images from a specific page of a PDF document, including necessary metadata,
|
|
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
|
+
*/
|
|
203
225
|
async function extractImages$1(data, pageNumber) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
height,
|
|
234
|
-
channels,
|
|
235
|
-
key: imageKey
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
return images;
|
|
239
|
-
});
|
|
226
|
+
return await withDocument(data, async (pdf) => {
|
|
227
|
+
if (pageNumber < 1 || pageNumber > pdf.numPages) throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
|
|
228
|
+
const page = await pdf.getPage(pageNumber);
|
|
229
|
+
const operatorList = await page.getOperatorList();
|
|
230
|
+
const { OPS } = await getResolvedPDFJS();
|
|
231
|
+
const images = [];
|
|
232
|
+
for (let i = 0; i < operatorList.fnArray.length; i++) {
|
|
233
|
+
if (operatorList.fnArray[i] !== OPS.paintImageXObject) continue;
|
|
234
|
+
const imageKey = operatorList.argsArray[i][0];
|
|
235
|
+
const image = await new Promise((resolve) => (imageKey.startsWith("g_") ? page.commonObjs : page.objs).get(imageKey, resolve));
|
|
236
|
+
if (!image || !image.data || !image.width || !image.height) continue;
|
|
237
|
+
const { width, height, data } = image;
|
|
238
|
+
const calculatedChannels = data.length / (width * height);
|
|
239
|
+
if (![
|
|
240
|
+
1,
|
|
241
|
+
3,
|
|
242
|
+
4
|
|
243
|
+
].includes(calculatedChannels)) continue;
|
|
244
|
+
const channels = calculatedChannels;
|
|
245
|
+
images.push({
|
|
246
|
+
data,
|
|
247
|
+
width,
|
|
248
|
+
height,
|
|
249
|
+
channels,
|
|
250
|
+
key: imageKey
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
return images;
|
|
254
|
+
});
|
|
240
255
|
}
|
|
241
256
|
async function renderPageAsImage$1(data, pageNumber, options = {}) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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 });
|
|
257
|
+
const CanvasFactory = await createIsomorphicCanvasFactory(options.canvasImport);
|
|
258
|
+
return await withDocument(data, async (pdf) => {
|
|
259
|
+
if (pageNumber < 1 || pageNumber > pdf.numPages) throw new Error(`Invalid page number. Must be between 1 and ${pdf.numPages}.`);
|
|
260
|
+
const page = await pdf.getPage(pageNumber);
|
|
261
|
+
const defaultViewport = page.getViewport({ scale: 1 });
|
|
262
|
+
let scale = options.scale || 1;
|
|
263
|
+
if (options.width) scale = options.width / defaultViewport.width;
|
|
264
|
+
else if (options.height) scale = options.height / defaultViewport.height;
|
|
265
|
+
const viewport = page.getViewport({ scale: Math.max(0, scale) });
|
|
266
|
+
const canvasFactory = new CanvasFactory();
|
|
267
|
+
const drawingContext = canvasFactory.create(viewport.width, viewport.height);
|
|
268
|
+
try {
|
|
269
|
+
await page.render({
|
|
270
|
+
canvas: drawingContext.canvas,
|
|
271
|
+
canvasContext: drawingContext.context,
|
|
272
|
+
viewport
|
|
273
|
+
}).promise;
|
|
274
|
+
const { canvas } = drawingContext;
|
|
275
|
+
if (options.toDataURL) return canvas.toDataURL();
|
|
276
|
+
if ("encode" in canvas) {
|
|
277
|
+
const buffer = await canvas.encode("png");
|
|
278
|
+
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
279
|
+
}
|
|
280
|
+
const blob = await new Promise((resolve) => {
|
|
281
|
+
canvas.toBlob(resolve);
|
|
282
|
+
});
|
|
283
|
+
if (!blob) throw new Error("Failed to encode canvas to a PNG blob.");
|
|
284
|
+
return await blob.arrayBuffer();
|
|
285
|
+
} finally {
|
|
286
|
+
canvasFactory.destroy(drawingContext);
|
|
287
|
+
}
|
|
288
|
+
}, { CanvasFactory });
|
|
283
289
|
}
|
|
284
290
|
async function createIsomorphicCanvasFactory(canvasImport) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
return NodeCanvasFactory;
|
|
294
|
-
}
|
|
295
|
-
throw new Error("Unsupported environment for canvas creation.");
|
|
291
|
+
if (isBrowser) return DOMCanvasFactory;
|
|
292
|
+
if (isNode) {
|
|
293
|
+
if (!canvasImport) throw new Error("Parameter \"canvasImport\" is required in Node.js environment.");
|
|
294
|
+
await resolveCanvasModule(canvasImport);
|
|
295
|
+
injectCanvasConstructors();
|
|
296
|
+
return NodeCanvasFactory;
|
|
297
|
+
}
|
|
298
|
+
throw new Error("Unsupported environment for canvas creation.");
|
|
296
299
|
}
|
|
297
|
-
|
|
300
|
+
//#endregion
|
|
301
|
+
//#region src/links.ts
|
|
298
302
|
async function extractLinks$1(data) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
};
|
|
307
|
-
});
|
|
303
|
+
return await withDocument(data, async (pdf) => {
|
|
304
|
+
const pageLinks = await Promise.all(Array.from({ length: pdf.numPages }, (_, i) => getPageLinks(pdf, i + 1)));
|
|
305
|
+
return {
|
|
306
|
+
totalPages: pdf.numPages,
|
|
307
|
+
links: pageLinks.flat()
|
|
308
|
+
};
|
|
309
|
+
});
|
|
308
310
|
}
|
|
309
311
|
async function getPageLinks(document, pageNumber) {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
if (annotation.subtype === "Link" && annotation.url) {
|
|
315
|
-
links.push(annotation.url);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
return links;
|
|
312
|
+
const annotations = await (await document.getPage(pageNumber)).getAnnotations();
|
|
313
|
+
const links = [];
|
|
314
|
+
for (const annotation of annotations) if (annotation.subtype === "Link" && annotation.url) links.push(annotation.url);
|
|
315
|
+
return links;
|
|
319
316
|
}
|
|
320
|
-
|
|
317
|
+
//#endregion
|
|
318
|
+
//#region src/meta.ts
|
|
321
319
|
const XMP_DATE_PROPERTIES = [
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
320
|
+
"xmp:createdate",
|
|
321
|
+
"xmp:modifydate",
|
|
322
|
+
"xmp:metadatadate",
|
|
323
|
+
"xap:createdate",
|
|
324
|
+
"xap:modifydate",
|
|
325
|
+
"xap:metadatadate"
|
|
328
326
|
];
|
|
329
327
|
async function getMeta$1(data, options = {}) {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
return target[prop];
|
|
354
|
-
}
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
return {
|
|
359
|
-
info,
|
|
360
|
-
metadata: meta?.metadata || {}
|
|
361
|
-
};
|
|
362
|
-
});
|
|
328
|
+
return await withDocument(data, async (pdf) => {
|
|
329
|
+
const meta = await pdf.getMetadata();
|
|
330
|
+
const info = meta?.info || {};
|
|
331
|
+
if (options.parseDates) {
|
|
332
|
+
const { PDFDateString } = await getResolvedPDFJS();
|
|
333
|
+
if (info?.CreationDate) 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
|
+
} });
|
|
343
|
+
}
|
|
344
|
+
return {
|
|
345
|
+
info,
|
|
346
|
+
metadata: meta?.metadata || {}
|
|
347
|
+
};
|
|
348
|
+
});
|
|
363
349
|
}
|
|
364
350
|
function parseISODateString(isoDateString) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
if (!Number.isNaN(parsedDate)) {
|
|
369
|
-
return new Date(parsedDate);
|
|
370
|
-
}
|
|
351
|
+
if (!isoDateString) return;
|
|
352
|
+
const parsedDate = Date.parse(isoDateString);
|
|
353
|
+
if (!Number.isNaN(parsedDate)) return new Date(parsedDate);
|
|
371
354
|
}
|
|
372
|
-
|
|
355
|
+
//#endregion
|
|
356
|
+
//#region src/text.ts
|
|
373
357
|
async function extractTextItems$1(data) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
358
|
+
return await withDocument(data, async (pdf) => {
|
|
359
|
+
const items = await Promise.all(Array.from({ length: pdf.numPages }, (_, i) => getPageTextItems(pdf, i + 1)));
|
|
360
|
+
return {
|
|
361
|
+
totalPages: pdf.numPages,
|
|
362
|
+
items
|
|
363
|
+
};
|
|
364
|
+
});
|
|
380
365
|
}
|
|
381
366
|
async function getPageTextItems(document, pageNumber) {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
});
|
|
367
|
+
const content = await (await document.getPage(pageNumber)).getTextContent();
|
|
368
|
+
const styles = content.styles;
|
|
369
|
+
return content.items.filter((item) => item.str != null).map((item) => {
|
|
370
|
+
const [_a, _b, c, d, e, f] = item.transform;
|
|
371
|
+
return {
|
|
372
|
+
str: item.str,
|
|
373
|
+
x: e,
|
|
374
|
+
y: f,
|
|
375
|
+
width: item.width,
|
|
376
|
+
height: item.height,
|
|
377
|
+
fontSize: Math.hypot(c, d),
|
|
378
|
+
fontFamily: styles[item.fontName]?.fontFamily ?? "",
|
|
379
|
+
dir: item.dir,
|
|
380
|
+
hasEOL: item.hasEOL
|
|
381
|
+
};
|
|
382
|
+
});
|
|
399
383
|
}
|
|
400
384
|
async function extractText$1(data, options = {}) {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
};
|
|
410
|
-
});
|
|
385
|
+
const { mergePages = false } = options;
|
|
386
|
+
return await withDocument(data, async (pdf) => {
|
|
387
|
+
const texts = await Promise.all(Array.from({ length: pdf.numPages }, (_, i) => getPageText(pdf, i + 1)));
|
|
388
|
+
return {
|
|
389
|
+
totalPages: pdf.numPages,
|
|
390
|
+
text: mergePages ? normalizeMergedText(texts) : texts
|
|
391
|
+
};
|
|
392
|
+
});
|
|
411
393
|
}
|
|
412
394
|
async function getPageText(document, pageNumber) {
|
|
413
|
-
|
|
414
|
-
const content = await page.getTextContent();
|
|
415
|
-
return content.items.filter((item) => item.str != null).map((item) => item.str + (item.hasEOL ? "\n" : "")).join("");
|
|
395
|
+
return (await (await document.getPage(pageNumber)).getTextContent()).items.filter((item) => item.str != null).map((item) => item.str + (item.hasEOL ? "\n" : "")).join("");
|
|
416
396
|
}
|
|
397
|
+
/**
|
|
398
|
+
* Collapses whitespace without destroying the line structure: `hasEOL` and
|
|
399
|
+
* page-join line breaks survive, but at most one blank line remains.
|
|
400
|
+
*/
|
|
417
401
|
function normalizeMergedText(texts) {
|
|
418
|
-
|
|
402
|
+
return texts.join("\n").replace(/[^\S\n]+/g, " ").replace(/ ?\n ?/g, "\n").replace(/\n{3,}/g, "\n\n");
|
|
419
403
|
}
|
|
420
|
-
|
|
404
|
+
//#endregion
|
|
405
|
+
//#region src/config.ts
|
|
406
|
+
/**
|
|
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.
|
|
410
|
+
*
|
|
411
|
+
* @example
|
|
412
|
+
* // Use the official PDF.js build (make sure to install it first)
|
|
413
|
+
* import { definePDFJSModule } from 'unpdf'
|
|
414
|
+
*
|
|
415
|
+
* await definePDFJSModule(() => import('pdfjs-dist'))
|
|
416
|
+
*/
|
|
421
417
|
async function definePDFJSModule(pdfjs) {
|
|
422
|
-
|
|
418
|
+
await resolvePDFJSImport(pdfjs, { reload: true });
|
|
423
419
|
}
|
|
420
|
+
/** @deprecated Use `definePDFJSModule` instead. Will be removed in v2. */
|
|
424
421
|
async function configureUnPDF(options) {
|
|
425
|
-
|
|
422
|
+
await resolvePDFJSImport(options.pdfjs, { reload: true });
|
|
426
423
|
}
|
|
427
|
-
|
|
424
|
+
//#endregion
|
|
425
|
+
//#region src/index.ts
|
|
428
426
|
const getMeta = async (...args) => {
|
|
429
|
-
|
|
430
|
-
|
|
427
|
+
await resolvePDFJSImport();
|
|
428
|
+
return await getMeta$1(...args);
|
|
431
429
|
};
|
|
432
430
|
const extractText = async (...args) => {
|
|
433
|
-
|
|
434
|
-
|
|
431
|
+
await resolvePDFJSImport();
|
|
432
|
+
return await extractText$1(...args);
|
|
435
433
|
};
|
|
436
434
|
const extractTextItems = async (...args) => {
|
|
437
|
-
|
|
438
|
-
|
|
435
|
+
await resolvePDFJSImport();
|
|
436
|
+
return await extractTextItems$1(...args);
|
|
439
437
|
};
|
|
440
438
|
const extractImages = async (...args) => {
|
|
441
|
-
|
|
442
|
-
|
|
439
|
+
await resolvePDFJSImport();
|
|
440
|
+
return await extractImages$1(...args);
|
|
443
441
|
};
|
|
444
442
|
const renderPageAsImage = async (...args) => {
|
|
445
|
-
|
|
446
|
-
|
|
443
|
+
await resolvePDFJSImport();
|
|
444
|
+
return await renderPageAsImage$1(...args);
|
|
447
445
|
};
|
|
448
446
|
const extractLinks = async (...args) => {
|
|
449
|
-
|
|
450
|
-
|
|
447
|
+
await resolvePDFJSImport();
|
|
448
|
+
return await extractLinks$1(...args);
|
|
451
449
|
};
|
|
452
|
-
|
|
450
|
+
//#endregion
|
|
453
451
|
exports.configureUnPDF = configureUnPDF;
|
|
454
452
|
exports.createIsomorphicCanvasFactory = createIsomorphicCanvasFactory;
|
|
455
453
|
exports.definePDFJSModule = definePDFJSModule;
|