unpdf 1.6.2 → 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 +61 -25
- package/dist/index.cjs +386 -353
- package/dist/index.d.cts +101 -91
- package/dist/index.d.mts +101 -91
- package/dist/index.mjs +385 -351
- package/dist/pdfjs.d.mts +1 -1
- package/dist/pdfjs.d.ts +1 -1
- 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 +11 -9
- 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 +13 -13
- 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 +10 -3
- package/dist/types/src/display/xfa_text.d.ts +2 -2
- package/dist/types/src/pdf.d.ts +10 -9
- 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 +5 -5
- package/dist/types/web/annotation_layer_builder.d.ts +14 -11
- 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 +16 -5
- package/dist/types/web/pdf_history.d.ts +1 -1
- package/dist/types/web/pdf_link_service.d.ts +10 -2
- package/dist/types/web/pdf_page_view.d.ts +19 -12
- package/dist/types/web/pdf_rendering_queue.d.ts +3 -3
- package/dist/types/web/pdf_scripting_manager.d.ts +1 -1
- package/dist/types/web/pdf_thumbnail_view.d.ts +9 -9
- package/dist/types/web/pdf_thumbnail_viewer.d.ts +38 -19
- package/dist/types/web/pdf_viewer.d.ts +28 -14
- package/dist/types/web/renderable_view.d.ts +2 -2
- package/dist/types/web/struct_tree_layer_builder.d.ts +1 -1
- package/dist/types/web/text_accessibility.d.ts +1 -1
- package/dist/types/web/text_highlighter.d.ts +6 -6
- package/dist/types/web/text_layer_builder.d.ts +10 -10
- package/dist/types/web/xfa_layer_builder.d.ts +8 -8
- package/package.json +25 -24
- package/dist/index.d.ts +0 -182
- package/dist/types/src/display/webgpu_mesh.d.ts +0 -3
package/dist/index.cjs
CHANGED
|
@@ -1,420 +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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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;
|
|
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
|
+
*/
|
|
91
|
+
async function withDocument(data, operation, options) {
|
|
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
|
+
}
|
|
74
98
|
}
|
|
75
99
|
async function getResolvedPDFJS() {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
return resolvedModule;
|
|
100
|
+
if (!resolvedModule) await resolvePDFJSImport();
|
|
101
|
+
return resolvedModule;
|
|
80
102
|
}
|
|
81
103
|
async function resolvePDFJSImport(pdfjsResolver, { reload = false } = {}) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
resolvedModule = await import('unpdf/pdfjs');
|
|
96
|
-
} catch (error) {
|
|
97
|
-
throw new Error(`Serverless PDF.js bundle could not be resolved: ${error}`);
|
|
98
|
-
}
|
|
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
|
+
}
|
|
99
117
|
}
|
|
100
118
|
function isPDFDocumentProxy(data) {
|
|
101
|
-
|
|
119
|
+
return typeof data === "object" && data !== null && "_pdfInfo" in data;
|
|
102
120
|
}
|
|
103
121
|
async function interopDefault(m) {
|
|
104
|
-
|
|
105
|
-
|
|
122
|
+
const resolved = await m;
|
|
123
|
+
return resolved.default || resolved;
|
|
106
124
|
}
|
|
107
|
-
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/_internal/canvas.ts
|
|
108
127
|
let resolvedCanvasModule;
|
|
109
128
|
/**
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
context.context = void 0;
|
|
143
|
-
}
|
|
144
|
-
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
145
|
-
_createCanvas(width, height) {
|
|
146
|
-
throw new Error("Not implemented");
|
|
147
|
-
}
|
|
148
|
-
}
|
|
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
|
+
};
|
|
149
161
|
/**
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
return resolvedCanvasModule.createCanvas(width, height);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
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
|
+
};
|
|
178
187
|
async function resolveCanvasModule(canvasImport) {
|
|
179
|
-
|
|
188
|
+
resolvedCanvasModule ??= await interopDefault(canvasImport());
|
|
189
|
+
globalThis[Symbol.for("unpdf.canvasModule")] = resolvedCanvasModule;
|
|
180
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
|
+
*/
|
|
181
201
|
function injectCanvasConstructors() {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
globalThis.ImageData = resolvedCanvasModule.ImageData;
|
|
187
|
-
if (typeof globalThis.Path2D === "undefined")
|
|
188
|
-
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;
|
|
189
206
|
}
|
|
190
|
-
|
|
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
|
+
*/
|
|
191
225
|
async function extractImages$1(data, pageNumber) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
height,
|
|
222
|
-
channels,
|
|
223
|
-
key: imageKey
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
return images;
|
|
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
|
+
});
|
|
227
255
|
}
|
|
228
256
|
async function renderPageAsImage$1(data, pageNumber, options = {}) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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 });
|
|
255
289
|
}
|
|
256
290
|
async function createIsomorphicCanvasFactory(canvasImport) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
return NodeCanvasFactory;
|
|
266
|
-
}
|
|
267
|
-
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.");
|
|
268
299
|
}
|
|
269
|
-
|
|
300
|
+
//#endregion
|
|
301
|
+
//#region src/links.ts
|
|
270
302
|
async function extractLinks$1(data) {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
};
|
|
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
|
+
});
|
|
279
310
|
}
|
|
280
311
|
async function getPageLinks(document, pageNumber) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (annotation.subtype === "Link" && annotation.url) {
|
|
286
|
-
links.push(annotation.url);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
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;
|
|
290
316
|
}
|
|
291
|
-
|
|
317
|
+
//#endregion
|
|
318
|
+
//#region src/meta.ts
|
|
292
319
|
const XMP_DATE_PROPERTIES = [
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
320
|
+
"xmp:createdate",
|
|
321
|
+
"xmp:modifydate",
|
|
322
|
+
"xmp:metadatadate",
|
|
323
|
+
"xap:createdate",
|
|
324
|
+
"xap:modifydate",
|
|
325
|
+
"xap:metadatadate"
|
|
299
326
|
];
|
|
300
327
|
async function getMeta$1(data, options = {}) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
return target[prop];
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
return {
|
|
330
|
-
info,
|
|
331
|
-
metadata: meta?.metadata || {}
|
|
332
|
-
};
|
|
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
|
+
});
|
|
333
349
|
}
|
|
334
350
|
function parseISODateString(isoDateString) {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
if (!Number.isNaN(parsedDate)) {
|
|
339
|
-
return new Date(parsedDate);
|
|
340
|
-
}
|
|
351
|
+
if (!isoDateString) return;
|
|
352
|
+
const parsedDate = Date.parse(isoDateString);
|
|
353
|
+
if (!Number.isNaN(parsedDate)) return new Date(parsedDate);
|
|
341
354
|
}
|
|
342
|
-
|
|
355
|
+
//#endregion
|
|
356
|
+
//#region src/text.ts
|
|
343
357
|
async function extractTextItems$1(data) {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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
|
+
});
|
|
349
365
|
}
|
|
350
366
|
async function getPageTextItems(document, pageNumber) {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
});
|
|
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
|
+
});
|
|
368
383
|
}
|
|
369
384
|
async function extractText$1(data, options = {}) {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
};
|
|
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
|
+
});
|
|
379
393
|
}
|
|
380
394
|
async function getPageText(document, pageNumber) {
|
|
381
|
-
|
|
382
|
-
const content = await page.getTextContent();
|
|
383
|
-
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("");
|
|
384
396
|
}
|
|
385
|
-
|
|
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
|
+
*/
|
|
401
|
+
function normalizeMergedText(texts) {
|
|
402
|
+
return texts.join("\n").replace(/[^\S\n]+/g, " ").replace(/ ?\n ?/g, "\n").replace(/\n{3,}/g, "\n\n");
|
|
403
|
+
}
|
|
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
|
+
*/
|
|
386
417
|
async function definePDFJSModule(pdfjs) {
|
|
387
|
-
|
|
418
|
+
await resolvePDFJSImport(pdfjs, { reload: true });
|
|
388
419
|
}
|
|
420
|
+
/** @deprecated Use `definePDFJSModule` instead. Will be removed in v2. */
|
|
389
421
|
async function configureUnPDF(options) {
|
|
390
|
-
|
|
422
|
+
await resolvePDFJSImport(options.pdfjs, { reload: true });
|
|
391
423
|
}
|
|
392
|
-
|
|
424
|
+
//#endregion
|
|
425
|
+
//#region src/index.ts
|
|
393
426
|
const getMeta = async (...args) => {
|
|
394
|
-
|
|
395
|
-
|
|
427
|
+
await resolvePDFJSImport();
|
|
428
|
+
return await getMeta$1(...args);
|
|
396
429
|
};
|
|
397
430
|
const extractText = async (...args) => {
|
|
398
|
-
|
|
399
|
-
|
|
431
|
+
await resolvePDFJSImport();
|
|
432
|
+
return await extractText$1(...args);
|
|
400
433
|
};
|
|
401
434
|
const extractTextItems = async (...args) => {
|
|
402
|
-
|
|
403
|
-
|
|
435
|
+
await resolvePDFJSImport();
|
|
436
|
+
return await extractTextItems$1(...args);
|
|
404
437
|
};
|
|
405
438
|
const extractImages = async (...args) => {
|
|
406
|
-
|
|
407
|
-
|
|
439
|
+
await resolvePDFJSImport();
|
|
440
|
+
return await extractImages$1(...args);
|
|
408
441
|
};
|
|
409
442
|
const renderPageAsImage = async (...args) => {
|
|
410
|
-
|
|
411
|
-
|
|
443
|
+
await resolvePDFJSImport();
|
|
444
|
+
return await renderPageAsImage$1(...args);
|
|
412
445
|
};
|
|
413
446
|
const extractLinks = async (...args) => {
|
|
414
|
-
|
|
415
|
-
|
|
447
|
+
await resolvePDFJSImport();
|
|
448
|
+
return await extractLinks$1(...args);
|
|
416
449
|
};
|
|
417
|
-
|
|
450
|
+
//#endregion
|
|
418
451
|
exports.configureUnPDF = configureUnPDF;
|
|
419
452
|
exports.createIsomorphicCanvasFactory = createIsomorphicCanvasFactory;
|
|
420
453
|
exports.definePDFJSModule = definePDFJSModule;
|