modern-pdf-lib 0.9.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 modern-pdf contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,455 @@
1
+ <div align="center">
2
+
3
+ <br />
4
+
5
+ <picture>
6
+ <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/badge/modern--pdf--lib-fff?style=for-the-badge&labelColor=000&color=000&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTQgMkg2YTIgMiAwIDAgMC0yIDJ2MTZhMiAyIDAgMCAwIDIgMmgxMmEyIDIgMCAwIDAgMi0yVjhsLTYtNloiLz48cG9seWxpbmUgcG9pbnRzPSIxNCAyIDE0IDggMjAgOCIvPjxsaW5lIHgxPSIxNiIgeTE9IjEzIiB4Mj0iOCIgeTI9IjEzIi8+PGxpbmUgeDE9IjE2IiB5MT0iMTciIHgyPSI4IiB5Mj0iMTciLz48bGluZSB4MT0iMTAiIHkxPSI5IiB4Mj0iOCIgeTI9IjkiLz48L3N2Zz4" />
7
+ <img src="https://img.shields.io/badge/modern--pdf--lib-000?style=for-the-badge&labelColor=fff&color=fff&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTQgMkg2YTIgMiAwIDAgMC0yIDJ2MTZhMiAyIDAgMCAwIDIgMmgxMmEyIDIgMCAwIDAgMi0yVjhsLTYtNloiLz48cG9seWxpbmUgcG9pbnRzPSIxNCAyIDE0IDggMjAgOCIvPjxsaW5lIHgxPSIxNiIgeTE9IjEzIiB4Mj0iOCIgeTI9IjEzIi8+PGxpbmUgeDE9IjE2IiB5MT0iMTciIHgyPSI4IiB5Mj0iMTciLz48bGluZSB4MT0iMTAiIHkxPSI5IiB4Mj0iOCIgeTI9IjkiLz48L3N2Zz4" alt="modern-pdf-lib" />
8
+ </picture>
9
+
10
+ ### The PDF engine for modern JavaScript
11
+
12
+ Create, parse, fill, merge, sign, and manipulate PDF documents<br />in Node, Deno, Bun, Cloudflare Workers, and every browser.
13
+
14
+ <br />
15
+
16
+ [![npm version](https://img.shields.io/npm/v/modern-pdf-lib?style=flat-square&color=cb3837)](https://www.npmjs.com/package/modern-pdf-lib)
17
+ [![bundle size](https://img.shields.io/badge/gzip-36kb_core-blue?style=flat-square)](https://bundlephobia.com/package/modern-pdf-lib)
18
+ [![tests](https://img.shields.io/badge/tests-1%2C952_passing-brightgreen?style=flat-square)](#)
19
+ [![TypeScript](https://img.shields.io/badge/TypeScript-6.0-3178c6?style=flat-square&logo=typescript&logoColor=white)](#)
20
+ [![License: MIT](https://img.shields.io/badge/license-MIT-yellow?style=flat-square)](LICENSE)
21
+
22
+ <br />
23
+
24
+ [Get Started](#quick-start) · [Features](#features) · [API](#api-surface) · [Why This?](#why-modern-pdf-lib)
25
+
26
+ <br />
27
+
28
+ </div>
29
+
30
+ ---
31
+
32
+ <br />
33
+
34
+ ## Quick Start
35
+
36
+ ```sh
37
+ npm install modern-pdf-lib
38
+ ```
39
+
40
+ ```ts
41
+ import { createPdf, PageSizes, rgb } from 'modern-pdf-lib';
42
+
43
+ const doc = createPdf();
44
+ const page = doc.addPage(PageSizes.A4);
45
+
46
+ page.drawText('Hello from modern-pdf-lib', {
47
+ x: 50,
48
+ y: 750,
49
+ size: 28,
50
+ color: rgb(0.13, 0.13, 0.13),
51
+ });
52
+
53
+ const bytes = await doc.save(); // Uint8Array
54
+ const stream = doc.saveAsStream(); // ReadableStream
55
+ const blob = await doc.saveAsBlob(); // Blob (browsers)
56
+ ```
57
+
58
+ <br />
59
+
60
+ ## Features
61
+
62
+ <table>
63
+ <tr>
64
+ <td width="50%" valign="top">
65
+
66
+ **Create & Draw**
67
+ - Pages, text, images, shapes, SVG paths
68
+ - TrueType & OpenType font embedding
69
+ - Automatic font subsetting
70
+ - JPEG / PNG image embedding
71
+ - RGB, CMYK, grayscale colors
72
+ - Text layout (multiline, combed, auto-size)
73
+
74
+ </td>
75
+ <td width="50%" valign="top">
76
+
77
+ **Parse & Modify**
78
+ - Load existing PDFs (encrypted too)
79
+ - Extract text with positions
80
+ - Fill & flatten AcroForm fields
81
+ - Merge, split, copy pages
82
+ - Add / remove / reorder pages
83
+ - Incremental saves
84
+
85
+ </td>
86
+ </tr>
87
+ <tr>
88
+ <td width="50%" valign="top">
89
+
90
+ **Secure & Compliant**
91
+ - AES-256 / RC4 encryption & decryption
92
+ - Digital signatures (PKCS#7, timestamps)
93
+ - PDF/A-1b through PDF/A-3u validation
94
+ - Tagged PDF / PDF/UA accessibility
95
+ - Structure tree & marked content
96
+ - Redaction with content removal
97
+
98
+ </td>
99
+ <td width="50%" valign="top">
100
+
101
+ **Advanced**
102
+ - Outlines / bookmarks
103
+ - Optional content layers (OCGs)
104
+ - File attachments
105
+ - Watermarks
106
+ - Linearization (fast web view)
107
+ - 60+ low-level PDF operators
108
+ - Custom appearance providers
109
+
110
+ </td>
111
+ </tr>
112
+ </table>
113
+
114
+ <br />
115
+
116
+ ## Why modern-pdf-lib?
117
+
118
+ <table>
119
+ <tr>
120
+ <th></th>
121
+ <th align="center"><strong>modern-pdf-lib</strong></th>
122
+ <th align="center">pdf-lib</th>
123
+ </tr>
124
+
125
+ <tr><td><strong>Runtime</strong></td>
126
+ <td align="center">Node, Deno, Bun, CF Workers, browsers</td>
127
+ <td align="center">Node, browsers</td></tr>
128
+
129
+ <tr><td><strong>Module format</strong></td>
130
+ <td align="center">ESM + CJS</td>
131
+ <td align="center">CJS (with ESM wrapper)</td></tr>
132
+
133
+ <tr><td><strong>TypeScript</strong></td>
134
+ <td align="center">6.0 strict</td>
135
+ <td align="center">3.x</td></tr>
136
+
137
+ <tr><td><strong>Parse existing PDFs</strong></td>
138
+ <td align="center">Yes (with decryption)</td>
139
+ <td align="center">Yes</td></tr>
140
+
141
+ <tr><td><strong>Text extraction</strong></td>
142
+ <td align="center">Yes (with positions)</td>
143
+ <td align="center">No</td></tr>
144
+
145
+ <tr><td><strong>Encryption</strong></td>
146
+ <td align="center">AES-256 + RC4</td>
147
+ <td align="center">No</td></tr>
148
+
149
+ <tr><td><strong>Digital signatures</strong></td>
150
+ <td align="center">PKCS#7, timestamps</td>
151
+ <td align="center">No</td></tr>
152
+
153
+ <tr><td><strong>Forms</strong></td>
154
+ <td align="center">Full (7 field types)</td>
155
+ <td align="center">Full</td></tr>
156
+
157
+ <tr><td><strong>PDF/A compliance</strong></td>
158
+ <td align="center">1a/1b through 3a/3b/3u</td>
159
+ <td align="center">No</td></tr>
160
+
161
+ <tr><td><strong>Accessibility (PDF/UA)</strong></td>
162
+ <td align="center">Structure tree, checker</td>
163
+ <td align="center">No</td></tr>
164
+
165
+ <tr><td><strong>Merge & split</strong></td>
166
+ <td align="center">Built-in</td>
167
+ <td align="center">Copy pages only</td></tr>
168
+
169
+ <tr><td><strong>Annotations</strong></td>
170
+ <td align="center">16 types + appearances</td>
171
+ <td align="center">No</td></tr>
172
+
173
+ <tr><td><strong>Streaming output</strong></td>
174
+ <td align="center">ReadableStream</td>
175
+ <td align="center">No</td></tr>
176
+
177
+ <tr><td><strong>Layers (OCG)</strong></td>
178
+ <td align="center">Yes</td>
179
+ <td align="center">No</td></tr>
180
+
181
+ <tr><td><strong>Outlines</strong></td>
182
+ <td align="center">Yes</td>
183
+ <td align="center">No</td></tr>
184
+
185
+ <tr><td><strong>Watermarks</strong></td>
186
+ <td align="center">Yes</td>
187
+ <td align="center">No</td></tr>
188
+
189
+ <tr><td><strong>Redaction</strong></td>
190
+ <td align="center">Yes</td>
191
+ <td align="center">No</td></tr>
192
+
193
+ <tr><td><strong>Linearization</strong></td>
194
+ <td align="center">Yes</td>
195
+ <td align="center">No</td></tr>
196
+
197
+ <tr><td><strong>WASM acceleration</strong></td>
198
+ <td align="center">Optional (compression, PNG, fonts)</td>
199
+ <td align="center">No</td></tr>
200
+
201
+ <tr><td><strong>Dependencies</strong></td>
202
+ <td align="center">1 (fflate)</td>
203
+ <td align="center">0</td></tr>
204
+
205
+ <tr><td><strong>Maintained</strong></td>
206
+ <td align="center">Active</td>
207
+ <td align="center">Inactive since 2021</td></tr>
208
+
209
+ </table>
210
+
211
+ <br />
212
+
213
+ ## Runtimes
214
+
215
+ | Runtime | Version | Status |
216
+ |:---|:---|:---:|
217
+ | **Node.js** | 22+ | Fully supported |
218
+ | **Deno** | 1.40+ | Fully supported |
219
+ | **Bun** | 1.0+ | Fully supported |
220
+ | **Cloudflare Workers** | &mdash; | Fully supported |
221
+ | **Chrome / Edge** | 109+ | Fully supported |
222
+ | **Firefox** | 115+ | Fully supported |
223
+ | **Safari** | 16.4+ | Fully supported |
224
+
225
+ <br />
226
+
227
+ ## API Surface
228
+
229
+ <details>
230
+ <summary><strong>Document</strong> &mdash; create, load, save, metadata</summary>
231
+
232
+ ```ts
233
+ import { createPdf, loadPdf, PageSizes } from 'modern-pdf-lib';
234
+
235
+ // Create from scratch
236
+ const doc = createPdf();
237
+ doc.setTitle('Invoice #1042');
238
+ doc.setLanguage('en');
239
+
240
+ // Load existing
241
+ const existing = await loadPdf(pdfBytes, { password: 'secret' });
242
+
243
+ // Save
244
+ const bytes = await doc.save();
245
+ const stream = doc.saveAsStream();
246
+ ```
247
+ </details>
248
+
249
+ <details>
250
+ <summary><strong>Pages</strong> &mdash; draw text, images, shapes, SVG</summary>
251
+
252
+ ```ts
253
+ const page = doc.addPage(PageSizes.LETTER);
254
+
255
+ page.drawText('Hello', { x: 50, y: 700, size: 24 });
256
+ page.drawImage(imageRef, { x: 50, y: 400, width: 200, height: 200 });
257
+ page.drawRectangle({ x: 50, y: 300, width: 100, height: 50, color: rgb(0, 0.5, 1) });
258
+ page.drawCircle({ x: 200, y: 325, radius: 25 });
259
+ page.drawSvgPath('M 0 0 L 100 0 L 50 80 Z', { x: 300, y: 300 });
260
+ ```
261
+ </details>
262
+
263
+ <details>
264
+ <summary><strong>Fonts</strong> &mdash; embed, subset, standard 14</summary>
265
+
266
+ ```ts
267
+ // Standard fonts (no embedding needed)
268
+ const helvetica = doc.embedStandardFont('Helvetica');
269
+
270
+ // Custom TrueType / OpenType
271
+ const fontBytes = await readFile('Inter.ttf');
272
+ const inter = await doc.embedFont(fontBytes, { subset: true });
273
+
274
+ page.drawText('Custom font', { x: 50, y: 500, font: inter, size: 18 });
275
+ ```
276
+ </details>
277
+
278
+ <details>
279
+ <summary><strong>Forms</strong> &mdash; fill, create, flatten</summary>
280
+
281
+ ```ts
282
+ const form = doc.getForm();
283
+
284
+ form.getTextField('name').setText('Jane Doe');
285
+ form.getCheckbox('agree').check();
286
+ form.getDropdown('country').select('Canada');
287
+
288
+ form.flatten(); // Burn values into page content
289
+ ```
290
+ </details>
291
+
292
+ <details>
293
+ <summary><strong>Merge & Split</strong></summary>
294
+
295
+ ```ts
296
+ import { mergePdfs, splitPdf, copyPages } from 'modern-pdf-lib';
297
+
298
+ const merged = await mergePdfs([pdf1Bytes, pdf2Bytes]);
299
+ const pages = await splitPdf(pdfBytes, [
300
+ { start: 0, end: 4 }, // Pages 1-5
301
+ { start: 5, end: 9 }, // Pages 6-10
302
+ ]);
303
+ ```
304
+ </details>
305
+
306
+ <details>
307
+ <summary><strong>Encryption</strong> &mdash; AES-256, RC4, permissions</summary>
308
+
309
+ ```ts
310
+ const bytes = await doc.save({
311
+ userPassword: 'reader',
312
+ ownerPassword: 'admin',
313
+ permissions: { printing: true, copying: false },
314
+ });
315
+ ```
316
+ </details>
317
+
318
+ <details>
319
+ <summary><strong>Digital Signatures</strong></summary>
320
+
321
+ ```ts
322
+ import { signPdf, verifySignatures } from 'modern-pdf-lib';
323
+
324
+ const signed = await signPdf(pdfBytes, {
325
+ certificate: certPem,
326
+ privateKey: keyPem,
327
+ reason: 'Approved',
328
+ });
329
+
330
+ const results = await verifySignatures(signed);
331
+ ```
332
+ </details>
333
+
334
+ <details>
335
+ <summary><strong>Text Extraction</strong></summary>
336
+
337
+ ```ts
338
+ import { loadPdf, extractTextWithPositions } from 'modern-pdf-lib';
339
+
340
+ const doc = await loadPdf(pdfBytes);
341
+ const page = doc.getPage(0);
342
+ const items = extractTextWithPositions(page.getOperators(), page.getResources());
343
+
344
+ for (const item of items) {
345
+ console.log(`"${item.text}" at (${item.x}, ${item.y})`);
346
+ }
347
+ ```
348
+ </details>
349
+
350
+ <details>
351
+ <summary><strong>PDF/A & Accessibility</strong></summary>
352
+
353
+ ```ts
354
+ import { enforcePdfA, checkAccessibility } from 'modern-pdf-lib';
355
+
356
+ // Enforce PDF/A-2b compliance
357
+ const archival = enforcePdfA(pdfBytes, '2b');
358
+
359
+ // Check accessibility
360
+ const issues = checkAccessibility(doc);
361
+ for (const issue of issues) {
362
+ console.log(`[${issue.severity}] ${issue.code}: ${issue.message}`);
363
+ }
364
+ ```
365
+ </details>
366
+
367
+ <br />
368
+
369
+ ## Install
370
+
371
+ ```sh
372
+ # npm
373
+ npm install modern-pdf-lib
374
+
375
+ # pnpm
376
+ pnpm add modern-pdf-lib
377
+
378
+ # yarn
379
+ yarn add modern-pdf-lib
380
+
381
+ # bun
382
+ bun add modern-pdf-lib
383
+
384
+ # deno
385
+ import { createPdf } from 'npm:modern-pdf-lib';
386
+ ```
387
+
388
+ <br />
389
+
390
+ ## WASM Acceleration
391
+
392
+ All WASM modules are **optional**. Without them, identical output is produced using pure-JS fallbacks.
393
+
394
+ ```ts
395
+ import { initWasm } from 'modern-pdf-lib';
396
+
397
+ await initWasm({
398
+ deflate: true, // Faster compression
399
+ png: true, // Faster PNG decoding
400
+ fonts: true, // Faster font subsetting
401
+ });
402
+ ```
403
+
404
+ | Module | Purpose | Speedup |
405
+ |:---|:---|:---:|
406
+ | libdeflate | Stream compression | ~2x |
407
+ | png | PNG image decoding | ~5x |
408
+ | ttf | Font parsing & subsetting | ~3x |
409
+ | shaping | Complex script layout | ~10x |
410
+
411
+ <br />
412
+
413
+ ## Project Structure
414
+
415
+ ```
416
+ modern-pdf-lib/
417
+ src/
418
+ core/ PDF document model, objects, writer, pages
419
+ parser/ PDF loading, text extraction, content streams
420
+ form/ AcroForm fields (7 types) + appearances
421
+ annotation/ 16 annotation types + appearance generators
422
+ accessibility/ Structure tree, marked content, PDF/UA checker
423
+ compliance/ PDF/A validation & enforcement
424
+ signature/ PKCS#7 signatures, timestamps, verification
425
+ crypto/ AES-256, RC4, MD5, SHA-256/384/512
426
+ compression/ Deflate (fflate + optional WASM)
427
+ assets/ Font metrics/embed/subset, image embed, SVG
428
+ layers/ Optional content groups (OCG)
429
+ outline/ Bookmarks / document outline
430
+ metadata/ XMP metadata, viewer preferences
431
+ wasm/ Rust crate sources (4 modules)
432
+ tests/ 1,952 tests across 90 suites
433
+ docs/ VitePress documentation
434
+ ```
435
+
436
+ <br />
437
+
438
+ ## Contributing
439
+
440
+ ```sh
441
+ git clone https://github.com/ABCrimson/modern-pdf-lib.git
442
+ cd modern-pdf-lib
443
+ npm install
444
+ npm test # 1,952 tests
445
+ npm run typecheck # TypeScript 6.0 strict
446
+ npm run build # ESM + CJS + declarations
447
+ ```
448
+
449
+ <br />
450
+
451
+ ## License
452
+
453
+ [MIT](LICENSE) &copy; 2026
454
+
455
+ </div>