@jackgreen2018/pdf-engine 1.0.108 → 1.0.110
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 +7 -7
- package/dist/cli.js +0 -18
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/package.json +1 -1
- package/pkg/README.md +7 -6
- package/pkg/package.json +1 -1
- package/pkg/pdf_engine_bg.wasm +0 -0
- package/src/cli.ts +0 -18
- package/src/index.ts +5 -0
- package/src/lib.rs +3 -4
package/README.md
CHANGED
|
@@ -131,16 +131,16 @@ npm run benchmark
|
|
|
131
131
|
|
|
132
132
|
| Operation | pdf-engine (ms) | pdf-lib (ms) |
|
|
133
133
|
|-----------|-----------------|--------------|
|
|
134
|
-
| Page Count | 0.
|
|
135
|
-
| Text Extraction | 0.
|
|
136
|
-
| Merge (2 files) | 1.
|
|
137
|
-
| Split (pages [0,1]) | 0.
|
|
138
|
-
| Encrypt (V4 AES-128) |
|
|
139
|
-
| Decrypt | 0.
|
|
134
|
+
| Page Count | 0.75 | 1.64 |
|
|
135
|
+
| Text Extraction | 0.39 | — |
|
|
136
|
+
| Merge (2 files) | 1.03 | 4.15 |
|
|
137
|
+
| Split (pages [0,1]) | 0.25 | 1.77 |
|
|
138
|
+
| Encrypt (V4 AES-128) | 1.05 | — |
|
|
139
|
+
| Decrypt | 0.38 | — |
|
|
140
140
|
|
|
141
141
|
*extractText correctness: PASS — gated via `tests/fixtures/text-fixture.pdf` (FlateDecode-compressed, real-world content stream). v1.0.30 fixes extractText to return actual text instead of "No text extracted."*
|
|
142
142
|
|
|
143
|
-
*Run 2026-08-03 (v1.0.
|
|
143
|
+
*Run 2026-08-03 (v1.0.110); raw JSON at benchmark-results.json.*
|
|
144
144
|
|
|
145
145
|
## Commercial license & support
|
|
146
146
|
|
package/dist/cli.js
CHANGED
|
@@ -12,8 +12,6 @@ Commands:
|
|
|
12
12
|
extract-text <file> Extract text from a PDF
|
|
13
13
|
merge <file1> <file2> ... Merge PDFs into a single output
|
|
14
14
|
split <file> <page1> ... Split a PDF by 0-based page indices
|
|
15
|
-
encrypt <file> <password> Encrypt a PDF with a password
|
|
16
|
-
decrypt <file> <password> Decrypt a password-protected PDF
|
|
17
15
|
help Print this message
|
|
18
16
|
`;
|
|
19
17
|
async function main() {
|
|
@@ -51,22 +49,6 @@ async function main() {
|
|
|
51
49
|
process.stdout.write(`wrote ${out.length} part-*.pdf files\n`);
|
|
52
50
|
return 0;
|
|
53
51
|
}
|
|
54
|
-
case 'encrypt': {
|
|
55
|
-
const [file, password, ownerPassword = ""] = args;
|
|
56
|
-
const encrypted = await pdfEngine.encrypt(await read(file), password, ownerPassword);
|
|
57
|
-
const outFile = file.replace(/\.pdf$/, '') + '.enc.pdf';
|
|
58
|
-
await fs.writeFile(outFile, encrypted);
|
|
59
|
-
process.stdout.write(`wrote ${outFile} (${encrypted.byteLength} bytes)\n`);
|
|
60
|
-
return 0;
|
|
61
|
-
}
|
|
62
|
-
case 'decrypt': {
|
|
63
|
-
const [file, password] = args;
|
|
64
|
-
const decrypted = await pdfEngine.decrypt(await read(file), password);
|
|
65
|
-
const outFile = file.replace(/\.pdf$/, '') + '.dec.pdf';
|
|
66
|
-
await fs.writeFile(outFile, decrypted);
|
|
67
|
-
process.stdout.write(`wrote ${outFile} (${decrypted.byteLength} bytes)\n`);
|
|
68
|
-
return 0;
|
|
69
|
-
}
|
|
70
52
|
default:
|
|
71
53
|
process.stderr.write(`unknown command: ${cmd}\n${USAGE}`);
|
|
72
54
|
return 1;
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export declare class PdfEngineImpl {
|
|
|
14
14
|
extractText(buffer: Uint8Array): Promise<string>;
|
|
15
15
|
merge(pdfBuffers: Uint8Array[]): Promise<Uint8Array>;
|
|
16
16
|
split(buffer: Uint8Array, pages: number[]): Promise<Uint8Array[]>;
|
|
17
|
+
isEncrypted(buffer: Uint8Array): Promise<boolean>;
|
|
17
18
|
encrypt(buffer: Uint8Array, userPassword: string, ownerPassword: string, version?: number): Promise<Uint8Array>;
|
|
18
19
|
decrypt(buffer: Uint8Array, password: string): Promise<Uint8Array>;
|
|
19
20
|
}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAEhD;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAEtE;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAErE;AAED,wBAAsB,KAAK,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAGzE;AAED,wBAAsB,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAGtF;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAGtE;AAED,wBAAsB,OAAO,CACzB,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,OAAO,SAAI,GACZ,OAAO,CAAC,UAAU,CAAC,CAGrB;AAED,wBAAsB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAGvF;AAED,qBAAa,aAAa;IACtB,cAEC;IACD,OAAO,CAAC,WAAW,CAAS;IAEtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAK1B;IAEK,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAGtD;IAEK,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAGrD;IAEK,KAAK,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAGzD;IAEK,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAGtE;IAEK,OAAO,CACT,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,OAAO,SAAI,GACZ,OAAO,CAAC,UAAU,CAAC,CAGrB;IAEK,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAGvE;CACJ;AAED,QAAA,MAAM,SAAS,eAAsB,CAAC;eACvB,SAAS"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAEhD;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAEtE;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAErE;AAED,wBAAsB,KAAK,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAGzE;AAED,wBAAsB,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAGtF;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAGtE;AAED,wBAAsB,OAAO,CACzB,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,OAAO,SAAI,GACZ,OAAO,CAAC,UAAU,CAAC,CAGrB;AAED,wBAAsB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAGvF;AAED,qBAAa,aAAa;IACtB,cAEC;IACD,OAAO,CAAC,WAAW,CAAS;IAEtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAK1B;IAEK,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAGtD;IAEK,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAGrD;IAEK,KAAK,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAGzD;IAEK,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAGtE;IAEK,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAGtD;IAEK,OAAO,CACT,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,OAAO,SAAI,GACZ,OAAO,CAAC,UAAU,CAAC,CAGrB;IAEK,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAGvE;CACJ;AAED,QAAA,MAAM,SAAS,eAAsB,CAAC;eACvB,SAAS"}
|
package/dist/index.js
CHANGED
|
@@ -56,6 +56,10 @@ export class PdfEngineImpl {
|
|
|
56
56
|
await this.init();
|
|
57
57
|
return await split(buffer, pages);
|
|
58
58
|
}
|
|
59
|
+
async isEncrypted(buffer) {
|
|
60
|
+
await this.init();
|
|
61
|
+
return await isEncrypted(buffer);
|
|
62
|
+
}
|
|
59
63
|
async encrypt(buffer, userPassword, ownerPassword, version = 4) {
|
|
60
64
|
await this.init();
|
|
61
65
|
return await encrypt(buffer, userPassword, ownerPassword, version);
|
package/package.json
CHANGED
package/pkg/README.md
CHANGED
|
@@ -131,15 +131,16 @@ npm run benchmark
|
|
|
131
131
|
|
|
132
132
|
| Operation | pdf-engine (ms) | pdf-lib (ms) |
|
|
133
133
|
|-----------|-----------------|--------------|
|
|
134
|
-
| Page Count | 0.
|
|
135
|
-
| Text Extraction | 0.
|
|
136
|
-
| Merge (2 files) | 1.
|
|
137
|
-
| Split (pages [0,1]) | 0.
|
|
138
|
-
| Encrypt (V4 AES-128) |
|
|
134
|
+
| Page Count | 0.75 | 1.64 |
|
|
135
|
+
| Text Extraction | 0.39 | — |
|
|
136
|
+
| Merge (2 files) | 1.03 | 4.15 |
|
|
137
|
+
| Split (pages [0,1]) | 0.25 | 1.77 |
|
|
138
|
+
| Encrypt (V4 AES-128) | 1.05 | — |
|
|
139
|
+
| Decrypt | 0.38 | — |
|
|
139
140
|
|
|
140
141
|
*extractText correctness: PASS — gated via `tests/fixtures/text-fixture.pdf` (FlateDecode-compressed, real-world content stream). v1.0.30 fixes extractText to return actual text instead of "No text extracted."*
|
|
141
142
|
|
|
142
|
-
*Run 2026-08-03 (v1.0.
|
|
143
|
+
*Run 2026-08-03 (v1.0.110); raw JSON at benchmark-results.json.*
|
|
143
144
|
|
|
144
145
|
## Commercial license & support
|
|
145
146
|
|
package/pkg/package.json
CHANGED
package/pkg/pdf_engine_bg.wasm
CHANGED
|
Binary file
|
package/src/cli.ts
CHANGED
|
@@ -13,8 +13,6 @@ Commands:
|
|
|
13
13
|
extract-text <file> Extract text from a PDF
|
|
14
14
|
merge <file1> <file2> ... Merge PDFs into a single output
|
|
15
15
|
split <file> <page1> ... Split a PDF by 0-based page indices
|
|
16
|
-
encrypt <file> <password> Encrypt a PDF with a password
|
|
17
|
-
decrypt <file> <password> Decrypt a password-protected PDF
|
|
18
16
|
help Print this message
|
|
19
17
|
`;
|
|
20
18
|
|
|
@@ -56,22 +54,6 @@ async function main(): Promise<number> {
|
|
|
56
54
|
process.stdout.write(`wrote ${out.length} part-*.pdf files\n`);
|
|
57
55
|
return 0;
|
|
58
56
|
}
|
|
59
|
-
case 'encrypt': {
|
|
60
|
-
const [file, password, ownerPassword = ""] = args;
|
|
61
|
-
const encrypted = await pdfEngine.encrypt(await read(file), password, ownerPassword);
|
|
62
|
-
const outFile = file.replace(/\.pdf$/, '') + '.enc.pdf';
|
|
63
|
-
await fs.writeFile(outFile, encrypted);
|
|
64
|
-
process.stdout.write(`wrote ${outFile} (${encrypted.byteLength} bytes)\n`);
|
|
65
|
-
return 0;
|
|
66
|
-
}
|
|
67
|
-
case 'decrypt': {
|
|
68
|
-
const [file, password] = args;
|
|
69
|
-
const decrypted = await pdfEngine.decrypt(await read(file), password);
|
|
70
|
-
const outFile = file.replace(/\.pdf$/, '') + '.dec.pdf';
|
|
71
|
-
await fs.writeFile(outFile, decrypted);
|
|
72
|
-
process.stdout.write(`wrote ${outFile} (${decrypted.byteLength} bytes)\n`);
|
|
73
|
-
return 0;
|
|
74
|
-
}
|
|
75
57
|
default:
|
|
76
58
|
process.stderr.write(`unknown command: ${cmd}\n${USAGE}`);
|
|
77
59
|
return 1;
|
package/src/index.ts
CHANGED
|
@@ -77,6 +77,11 @@ export class PdfEngineImpl {
|
|
|
77
77
|
return await split(buffer, pages);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
async isEncrypted(buffer: Uint8Array): Promise<boolean> {
|
|
81
|
+
await this.init();
|
|
82
|
+
return await isEncrypted(buffer);
|
|
83
|
+
}
|
|
84
|
+
|
|
80
85
|
async encrypt(
|
|
81
86
|
buffer: Uint8Array,
|
|
82
87
|
userPassword: string,
|
package/src/lib.rs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
use wasm_bindgen::prelude::*;
|
|
2
2
|
use js_sys::{Array, Uint8Array};
|
|
3
|
-
use std::sync::Arc;
|
|
4
|
-
use std::collections::BTreeMap;
|
|
5
3
|
use lopdf::{Document, Object, ObjectId, encryption::{EncryptionState, EncryptionVersion, Permissions}};
|
|
6
4
|
use lopdf::encryption::crypt_filters::{CryptFilter, Aes128CryptFilter};
|
|
5
|
+
use std::collections::BTreeMap;
|
|
6
|
+
use std::sync::Arc;
|
|
7
7
|
|
|
8
8
|
#[wasm_bindgen]
|
|
9
9
|
pub fn init() -> Result<(), JsValue> {
|
|
@@ -301,7 +301,6 @@ pub fn encrypt(
|
|
|
301
301
|
.map_err(|e| JsValue::from_str(&format!("PDF load error: {}", e)))?;
|
|
302
302
|
|
|
303
303
|
// Ensure /ID trailer entry exists (required by PDF encryption spec)
|
|
304
|
-
// PDF spec requires /ID to be an array of two byte strings
|
|
305
304
|
let mut doc = doc;
|
|
306
305
|
if doc.trailer.get(b"ID").is_err() {
|
|
307
306
|
doc.trailer.set(b"ID", Object::Array(vec![
|
|
@@ -311,7 +310,7 @@ pub fn encrypt(
|
|
|
311
310
|
}
|
|
312
311
|
|
|
313
312
|
// ponytail: version arg maps 1→V1/RC4, 2→V2/RC4-40bit, 4→V4/AES-128
|
|
314
|
-
// V5 requires raw file_encryption_key from user;
|
|
313
|
+
// V5 requires raw file_encryption_key from user; omitted for now
|
|
315
314
|
let state = match version {
|
|
316
315
|
1 => {
|
|
317
316
|
EncryptionState::try_from(EncryptionVersion::V1 {
|