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