pdf-lite 1.3.3 → 1.5.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.
Files changed (124) hide show
  1. package/dist/acroform/acroform.d.ts +7 -454
  2. package/dist/acroform/acroform.js +5 -1664
  3. package/dist/acroform/appearance/index.d.ts +4 -0
  4. package/dist/acroform/appearance/index.js +4 -0
  5. package/dist/acroform/appearance/pdf-appearance-stream.d.ts +21 -0
  6. package/dist/acroform/appearance/pdf-appearance-stream.js +41 -0
  7. package/dist/acroform/appearance/pdf-button-appearance-stream.d.ts +13 -0
  8. package/dist/acroform/appearance/pdf-button-appearance-stream.js +54 -0
  9. package/dist/acroform/appearance/pdf-choice-appearance-stream.d.ts +22 -0
  10. package/dist/acroform/appearance/pdf-choice-appearance-stream.js +75 -0
  11. package/dist/acroform/appearance/pdf-graphics.d.ts +51 -0
  12. package/dist/acroform/appearance/pdf-graphics.js +239 -0
  13. package/dist/acroform/appearance/pdf-text-appearance-stream.d.ts +22 -0
  14. package/dist/acroform/appearance/pdf-text-appearance-stream.js +104 -0
  15. package/dist/acroform/fields/index.d.ts +8 -0
  16. package/dist/acroform/fields/index.js +8 -0
  17. package/dist/acroform/fields/pdf-button-form-field.d.ts +23 -0
  18. package/dist/acroform/fields/pdf-button-form-field.js +102 -0
  19. package/dist/acroform/fields/pdf-choice-form-field.d.ts +18 -0
  20. package/dist/acroform/fields/pdf-choice-form-field.js +131 -0
  21. package/dist/acroform/fields/pdf-default-appearance.d.ts +23 -0
  22. package/dist/acroform/fields/pdf-default-appearance.js +68 -0
  23. package/dist/acroform/fields/pdf-form-field-flags.d.ts +45 -0
  24. package/dist/acroform/fields/pdf-form-field-flags.js +122 -0
  25. package/dist/acroform/fields/pdf-form-field.d.ts +123 -0
  26. package/dist/acroform/fields/pdf-form-field.js +433 -0
  27. package/dist/acroform/fields/pdf-signature-form-field.d.ts +7 -0
  28. package/dist/acroform/fields/pdf-signature-form-field.js +12 -0
  29. package/dist/acroform/fields/pdf-text-form-field.d.ts +10 -0
  30. package/dist/acroform/fields/pdf-text-form-field.js +77 -0
  31. package/dist/acroform/fields/types.d.ts +26 -0
  32. package/dist/acroform/fields/types.js +9 -0
  33. package/dist/acroform/index.d.ts +5 -1
  34. package/dist/acroform/index.js +5 -1
  35. package/dist/acroform/manager.d.ts +12 -1
  36. package/dist/acroform/manager.js +20 -2
  37. package/dist/acroform/pdf-acro-form.d.ts +69 -0
  38. package/dist/acroform/pdf-acro-form.js +293 -0
  39. package/dist/acroform/pdf-font-encoding-cache.d.ts +27 -0
  40. package/dist/acroform/pdf-font-encoding-cache.js +188 -0
  41. package/dist/acroform/xfa/index.d.ts +3 -0
  42. package/dist/acroform/xfa/index.js +2 -0
  43. package/dist/acroform/xfa/pdf-xfa-data.d.ts +20 -0
  44. package/dist/acroform/xfa/pdf-xfa-data.js +68 -0
  45. package/dist/acroform/xfa/pdf-xfa-form.d.ts +11 -0
  46. package/dist/acroform/xfa/pdf-xfa-form.js +56 -0
  47. package/dist/annotations/index.d.ts +4 -0
  48. package/dist/annotations/index.js +4 -0
  49. package/dist/annotations/pdf-annotation-flags.d.ts +24 -0
  50. package/dist/annotations/pdf-annotation-flags.js +93 -0
  51. package/dist/annotations/pdf-annotation-writer.d.ts +20 -0
  52. package/dist/annotations/pdf-annotation-writer.js +76 -0
  53. package/dist/annotations/pdf-annotation.d.ts +61 -0
  54. package/dist/annotations/pdf-annotation.js +106 -0
  55. package/dist/annotations/pdf-widget-annotation.d.ts +15 -0
  56. package/dist/annotations/pdf-widget-annotation.js +37 -0
  57. package/dist/core/objects/pdf-array.d.ts +1 -1
  58. package/dist/core/objects/pdf-array.js +3 -2
  59. package/dist/core/objects/pdf-boolean.d.ts +1 -1
  60. package/dist/core/objects/pdf-boolean.js +3 -2
  61. package/dist/core/objects/pdf-comment.d.ts +1 -1
  62. package/dist/core/objects/pdf-comment.js +1 -1
  63. package/dist/core/objects/pdf-dictionary.d.ts +1 -1
  64. package/dist/core/objects/pdf-dictionary.js +3 -2
  65. package/dist/core/objects/pdf-hexadecimal.d.ts +1 -1
  66. package/dist/core/objects/pdf-hexadecimal.js +3 -2
  67. package/dist/core/objects/pdf-indirect-object.d.ts +1 -1
  68. package/dist/core/objects/pdf-indirect-object.js +1 -1
  69. package/dist/core/objects/pdf-name.d.ts +1 -1
  70. package/dist/core/objects/pdf-name.js +3 -2
  71. package/dist/core/objects/pdf-null.d.ts +1 -1
  72. package/dist/core/objects/pdf-null.js +3 -2
  73. package/dist/core/objects/pdf-number.d.ts +1 -1
  74. package/dist/core/objects/pdf-number.js +3 -2
  75. package/dist/core/objects/pdf-object-reference.d.ts +1 -1
  76. package/dist/core/objects/pdf-object-reference.js +3 -2
  77. package/dist/core/objects/pdf-object.d.ts +3 -1
  78. package/dist/core/objects/pdf-object.js +6 -0
  79. package/dist/core/objects/pdf-start-xref.d.ts +1 -1
  80. package/dist/core/objects/pdf-start-xref.js +3 -2
  81. package/dist/core/objects/pdf-stream.d.ts +4 -3
  82. package/dist/core/objects/pdf-stream.js +45 -16
  83. package/dist/core/objects/pdf-string.d.ts +2 -1
  84. package/dist/core/objects/pdf-string.js +17 -2
  85. package/dist/core/objects/pdf-trailer.d.ts +1 -1
  86. package/dist/core/objects/pdf-trailer.js +3 -2
  87. package/dist/core/objects/pdf-xref-table.d.ts +3 -3
  88. package/dist/core/objects/pdf-xref-table.js +3 -3
  89. package/dist/core/parser/incremental-parser.d.ts +0 -13
  90. package/dist/core/parser/incremental-parser.js +1 -18
  91. package/dist/core/streams/object-stream.d.ts +1 -1
  92. package/dist/core/streams/object-stream.js +1 -1
  93. package/dist/errors.d.ts +22 -0
  94. package/dist/errors.js +24 -0
  95. package/dist/fonts/index.d.ts +1 -1
  96. package/dist/fonts/index.js +1 -1
  97. package/dist/fonts/pdf-font.d.ts +64 -7
  98. package/dist/fonts/pdf-font.js +188 -8
  99. package/dist/index.d.ts +2 -0
  100. package/dist/index.js +2 -0
  101. package/dist/pdf/index.d.ts +0 -1
  102. package/dist/pdf/index.js +0 -1
  103. package/dist/pdf/pdf-document.d.ts +16 -12
  104. package/dist/pdf/pdf-document.js +51 -37
  105. package/dist/pdf/pdf-revision.d.ts +1 -1
  106. package/dist/pdf/pdf-revision.js +1 -1
  107. package/dist/pdf/pdf-xref-lookup.d.ts +8 -0
  108. package/dist/pdf/pdf-xref-lookup.js +12 -0
  109. package/dist/security/handlers/base.js +3 -0
  110. package/dist/utils/encodePdfText.d.ts +17 -0
  111. package/dist/utils/encodePdfText.js +61 -0
  112. package/dist/utils/index.d.ts +1 -1
  113. package/dist/utils/index.js +1 -1
  114. package/package.json +1 -1
  115. package/dist/pdf/errors.d.ts +0 -6
  116. package/dist/pdf/errors.js +0 -6
  117. package/dist/xfa/index.d.ts +0 -1
  118. package/dist/xfa/index.js +0 -1
  119. package/dist/xfa/manager.d.ts +0 -44
  120. package/dist/xfa/manager.js +0 -136
  121. /package/dist/fonts/{font-manager.d.ts → manager.d.ts} +0 -0
  122. /package/dist/fonts/{font-manager.js → manager.js} +0 -0
  123. /package/dist/utils/{IterableReadableStream.d.ts → iterable-readable-stream.d.ts} +0 -0
  124. /package/dist/utils/{IterableReadableStream.js → iterable-readable-stream.js} +0 -0
@@ -27,11 +27,6 @@ export class PdfFont extends PdfDictionary {
27
27
  * Includes FontDescriptor, FontFile2, CIDFont, ToUnicode, etc.
28
28
  */
29
29
  auxiliaryObjects = [];
30
- /**
31
- * @internal
32
- * Reference to the font manager that created this font.
33
- */
34
- manager;
35
30
  /**
36
31
  * @internal
37
32
  * Font descriptor with metrics and properties.
@@ -42,15 +37,22 @@ export class PdfFont extends PdfDictionary {
42
37
  * Original font file bytes.
43
38
  */
44
39
  _fontData;
45
- constructor(options) {
40
+ constructor(optionsOrFontName) {
46
41
  super();
42
+ // Handle string parameter (simple fontName)
43
+ if (typeof optionsOrFontName === 'string') {
44
+ this.fontName = optionsOrFontName;
45
+ this.resourceName = optionsOrFontName;
46
+ return;
47
+ }
48
+ // Handle options object (existing behavior)
49
+ const options = optionsOrFontName;
47
50
  if (options.dict) {
48
51
  this.copyFrom(options.dict);
49
52
  }
50
53
  this.fontName = options.fontName;
51
54
  this.resourceName = options.resourceName ?? '';
52
55
  this.encoding = options.encoding;
53
- this.manager = options.manager;
54
56
  this.container = options.container;
55
57
  this._descriptor = options.descriptor;
56
58
  this._fontData = options.fontData;
@@ -169,6 +171,60 @@ export class PdfFont extends PdfDictionary {
169
171
  this.delete('Widths');
170
172
  }
171
173
  }
174
+ /**
175
+ * Gets the raw character width (in 1000-unit em square) for a character code.
176
+ * Returns null if the character is not in the font's width table.
177
+ *
178
+ * @param charCode - The character code to get the width for
179
+ * @returns The raw character width or null if not found
180
+ */
181
+ getRawCharacterWidth(charCode) {
182
+ if (this.widths === undefined || this.firstChar === undefined) {
183
+ return null;
184
+ }
185
+ const widthIndex = charCode - this.firstChar;
186
+ if (widthIndex >= 0 && widthIndex < this.widths.length) {
187
+ return this.widths[widthIndex];
188
+ }
189
+ return null;
190
+ }
191
+ /**
192
+ * Gets the character width scaled to the specified font size.
193
+ * Returns null if the character is not in the font's width table.
194
+ *
195
+ * @param charCode - The character code to get the width for
196
+ * @param fontSize - The font size to scale to
197
+ * @returns The scaled character width or null if not found
198
+ */
199
+ getCharacterWidth(charCode, fontSize) {
200
+ const rawWidth = this.getRawCharacterWidth(charCode);
201
+ return rawWidth !== null ? (rawWidth * fontSize) / 1000 : null;
202
+ }
203
+ /**
204
+ * Checks if the font has width data for a character code.
205
+ *
206
+ * @param charCode - The character code to check
207
+ * @returns True if width data is available, false otherwise
208
+ */
209
+ hasCharacterWidth(charCode) {
210
+ return this.getRawCharacterWidth(charCode) !== null;
211
+ }
212
+ /**
213
+ * Gets character widths for all characters in a string.
214
+ * Returns null for characters not in the font's width table.
215
+ *
216
+ * @param text - The text to get character widths for
217
+ * @param fontSize - The font size to scale to
218
+ * @returns Array of character widths (null for missing characters)
219
+ */
220
+ getCharacterWidthsForString(text, fontSize) {
221
+ const widths = [];
222
+ for (const char of text) {
223
+ const charCode = char.charCodeAt(0);
224
+ widths.push(this.getCharacterWidth(charCode, fontSize));
225
+ }
226
+ return widths;
227
+ }
172
228
  /**
173
229
  * Returns the resource name for string coercion.
174
230
  * This enables using PdfFont objects in template literals like:
@@ -235,16 +291,140 @@ export class PdfFont extends PdfDictionary {
235
291
  * These fonts don't require font data as they're built into PDF viewers.
236
292
  *
237
293
  * @param fontName - One of the 14 standard PDF fonts
294
+ * @param widths - Optional AFM widths array (1/1000 em units) for chars 32–126
238
295
  * @returns A PdfFont instance ready to be written to the PDF
239
296
  */
240
- static fromStandardFont(fontName) {
297
+ static fromStandardFont(fontName, widths) {
241
298
  const font = new PdfFont({ fontName });
242
299
  // Build Type1 font dictionary
243
300
  font.set('Type', new PdfName('Font'));
244
301
  font.set('Subtype', new PdfName('Type1'));
245
302
  font.set('BaseFont', new PdfName(fontName));
303
+ if (widths) {
304
+ font.firstChar = 32;
305
+ font.lastChar = 32 + widths.length - 1;
306
+ font.widths = widths;
307
+ }
246
308
  return font;
247
309
  }
310
+ // Helvetica AFM widths, chars 32–126 (95 values, 1/1000 em units)
311
+ static _HELVETICA_WIDTHS = [
312
+ 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333,
313
+ 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278,
314
+ 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278,
315
+ 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944,
316
+ 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556,
317
+ 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500,
318
+ 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584,
319
+ ];
320
+ // Helvetica-Bold AFM widths, chars 32–126
321
+ static _HELVETICA_BOLD_WIDTHS = [
322
+ 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333,
323
+ 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333,
324
+ 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278,
325
+ 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944,
326
+ 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556,
327
+ 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556,
328
+ 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584,
329
+ ];
330
+ // Times-Roman AFM widths, chars 32–126
331
+ static _TIMES_ROMAN_WIDTHS = [
332
+ 250, 333, 408, 500, 500, 833, 778, 180, 333, 333, 500, 564, 250, 333,
333
+ 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278,
334
+ 564, 564, 564, 444, 921, 722, 667, 667, 722, 611, 556, 722, 722, 333,
335
+ 389, 722, 611, 889, 722, 722, 556, 722, 667, 556, 611, 722, 722, 944,
336
+ 722, 722, 611, 333, 278, 333, 469, 500, 333, 444, 500, 444, 500, 444,
337
+ 333, 500, 500, 278, 278, 500, 278, 778, 500, 500, 500, 500, 333, 389,
338
+ 278, 500, 500, 722, 500, 500, 444, 480, 200, 480, 541,
339
+ ];
340
+ // Times-Bold AFM widths, chars 32–126
341
+ static _TIMES_BOLD_WIDTHS = [
342
+ 250, 333, 555, 500, 500, 1000, 833, 278, 333, 333, 500, 570, 250, 333,
343
+ 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333,
344
+ 570, 570, 570, 500, 930, 722, 667, 722, 722, 667, 611, 778, 778, 389,
345
+ 500, 778, 667, 944, 722, 778, 611, 778, 722, 556, 667, 722, 722, 1000,
346
+ 722, 722, 667, 333, 278, 333, 581, 500, 333, 500, 556, 444, 556, 444,
347
+ 333, 500, 556, 278, 333, 556, 278, 833, 556, 500, 556, 556, 444, 389,
348
+ 333, 556, 500, 722, 500, 500, 444, 394, 220, 394, 520,
349
+ ];
350
+ // Times-Italic AFM widths, chars 32–126
351
+ static _TIMES_ITALIC_WIDTHS = [
352
+ 250, 333, 420, 500, 500, 833, 778, 214, 333, 333, 500, 675, 250, 333,
353
+ 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333,
354
+ 675, 675, 675, 500, 920, 611, 611, 667, 722, 611, 611, 722, 722, 333,
355
+ 444, 667, 556, 833, 667, 722, 611, 722, 611, 500, 556, 722, 611, 833,
356
+ 611, 556, 556, 389, 278, 389, 422, 500, 333, 500, 500, 444, 500, 444,
357
+ 278, 500, 500, 278, 278, 444, 278, 722, 500, 500, 500, 500, 389, 389,
358
+ 278, 500, 444, 667, 444, 444, 389, 400, 275, 400, 541,
359
+ ];
360
+ // Times-BoldItalic AFM widths, chars 32–126
361
+ static _TIMES_BOLD_ITALIC_WIDTHS = [
362
+ 250, 389, 555, 500, 500, 833, 778, 278, 333, 333, 500, 570, 250, 333,
363
+ 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333,
364
+ 570, 570, 570, 500, 832, 667, 667, 667, 722, 667, 667, 722, 778, 389,
365
+ 500, 667, 611, 889, 722, 722, 611, 722, 667, 556, 611, 722, 667, 889,
366
+ 667, 611, 611, 333, 278, 333, 570, 500, 333, 500, 500, 444, 500, 444,
367
+ 333, 500, 556, 278, 278, 500, 278, 778, 556, 500, 500, 500, 389, 389,
368
+ 278, 556, 444, 667, 500, 444, 389, 348, 220, 348, 570,
369
+ ];
370
+ static HELVETICA = PdfFont.fromStandardFont('Helvetica', [
371
+ ...PdfFont._HELVETICA_WIDTHS,
372
+ ]);
373
+ static HELVETICA_BOLD = PdfFont.fromStandardFont('Helvetica-Bold', [...PdfFont._HELVETICA_BOLD_WIDTHS]);
374
+ static HELVETICA_OBLIQUE = PdfFont.fromStandardFont('Helvetica-Oblique', [...PdfFont._HELVETICA_WIDTHS]);
375
+ static HELVETICA_BOLD_OBLIQUE = PdfFont.fromStandardFont('Helvetica-BoldOblique', [...PdfFont._HELVETICA_BOLD_WIDTHS]);
376
+ static TIMES_ROMAN = PdfFont.fromStandardFont('Times-Roman', [
377
+ ...PdfFont._TIMES_ROMAN_WIDTHS,
378
+ ]);
379
+ static TIMES_BOLD = PdfFont.fromStandardFont('Times-Bold', [
380
+ ...PdfFont._TIMES_BOLD_WIDTHS,
381
+ ]);
382
+ static TIMES_ITALIC = PdfFont.fromStandardFont('Times-Italic', [
383
+ ...PdfFont._TIMES_ITALIC_WIDTHS,
384
+ ]);
385
+ static TIMES_BOLD_ITALIC = PdfFont.fromStandardFont('Times-BoldItalic', [...PdfFont._TIMES_BOLD_ITALIC_WIDTHS]);
386
+ static COURIER = PdfFont.fromStandardFont('Courier', Array(95).fill(600));
387
+ static COURIER_BOLD = PdfFont.fromStandardFont('Courier-Bold', Array(95).fill(600));
388
+ static COURIER_OBLIQUE = PdfFont.fromStandardFont('Courier-Oblique', Array(95).fill(600));
389
+ static COURIER_BOLD_OBLIQUE = PdfFont.fromStandardFont('Courier-BoldOblique', Array(95).fill(600));
390
+ static SYMBOL = PdfFont.fromStandardFont('Symbol');
391
+ static ZAPF_DINGBATS = PdfFont.fromStandardFont('ZapfDingbats');
392
+ static BY_BASE_FONT = new Map([
393
+ ['Helvetica', PdfFont.HELVETICA],
394
+ ['Helv', PdfFont.HELVETICA], // Alias for backward compatibility with old code using 'Helv'
395
+ ['Helvetica-Bold', PdfFont.HELVETICA_BOLD],
396
+ ['Helv-Bold', PdfFont.HELVETICA_BOLD], // Alias for backward compatibility with old code using 'Helv-Bold'
397
+ ['Helvetica-Oblique', PdfFont.HELVETICA_OBLIQUE],
398
+ ['Helv-Oblique', PdfFont.HELVETICA_OBLIQUE], // Alias for backward compatibility with old code using 'Helv-Oblique'
399
+ ['Helvetica-BoldOblique', PdfFont.HELVETICA_BOLD_OBLIQUE],
400
+ ['Helv-BoldOblique', PdfFont.HELVETICA_BOLD_OBLIQUE], // Alias for backward compatibility with old code using 'Helv-BoldOblique'
401
+ ['Times-Roman', PdfFont.TIMES_ROMAN],
402
+ ['TiRo', PdfFont.TIMES_ROMAN],
403
+ ['Times-Bold', PdfFont.TIMES_BOLD],
404
+ ['TiBo', PdfFont.TIMES_BOLD],
405
+ ['Times-Italic', PdfFont.TIMES_ITALIC],
406
+ ['TiIt', PdfFont.TIMES_ITALIC],
407
+ ['Times-BoldItalic', PdfFont.TIMES_BOLD_ITALIC],
408
+ ['TiBI', PdfFont.TIMES_BOLD_ITALIC],
409
+ ['Courier', PdfFont.COURIER],
410
+ ['Cour', PdfFont.COURIER], // Alias for backward compatibility with old code using 'Cour'
411
+ ['Courier-Bold', PdfFont.COURIER_BOLD],
412
+ ['Cour-Bold', PdfFont.COURIER_BOLD], // Alias for backward compatibility with old code using 'Cour-Bold'
413
+ ['Courier-Oblique', PdfFont.COURIER_OBLIQUE],
414
+ ['Cour-Oblique', PdfFont.COURIER_OBLIQUE], // Alias for backward compatibility with old code using 'Cour-Oblique'
415
+ ['Courier-BoldOblique', PdfFont.COURIER_BOLD_OBLIQUE],
416
+ ['Cour-BoldOblique', PdfFont.COURIER_BOLD_OBLIQUE], // Alias for backward compatibility with old code using 'Cour-BoldOblique'
417
+ ['Symbol', PdfFont.SYMBOL],
418
+ ['ZapfDingbats', PdfFont.ZAPF_DINGBATS],
419
+ ['ZaDb', PdfFont.ZAPF_DINGBATS],
420
+ ]);
421
+ /**
422
+ * Returns the static PdfFont instance for a standard font name, or null if not found.
423
+ */
424
+ static getStandardFont(fontName) {
425
+ const font = PdfFont.BY_BASE_FONT.get(fontName);
426
+ return font ?? null;
427
+ }
248
428
  /**
249
429
  * Creates a TrueType font from font file data.
250
430
  * Uses WinAnsiEncoding for standard 8-bit character support.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './types.js';
2
+ export * from './errors.js';
2
3
  export * from './core/index.js';
3
4
  export * from './crypto/index.js';
4
5
  export * from './filters/index.js';
@@ -7,3 +8,4 @@ export * from './pdf/index.js';
7
8
  export * from './security/index.js';
8
9
  export * from './signing/index.js';
9
10
  export * from './utils/index.js';
11
+ export * from './annotations/index.js';
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './types.js';
2
+ export * from './errors.js';
2
3
  export * from './core/index.js';
3
4
  export * from './crypto/index.js';
4
5
  export * from './filters/index.js';
@@ -7,3 +8,4 @@ export * from './pdf/index.js';
7
8
  export * from './security/index.js';
8
9
  export * from './signing/index.js';
9
10
  export * from './utils/index.js';
11
+ export * from './annotations/index.js';
@@ -1,4 +1,3 @@
1
- export * from './errors.js';
2
1
  export * from './pdf-document.js';
3
2
  export * from './pdf-reader.js';
4
3
  export * from './pdf-revision.js';
package/dist/pdf/index.js CHANGED
@@ -1,4 +1,3 @@
1
- export * from './errors.js';
2
1
  export * from './pdf-document.js';
3
2
  export * from './pdf-reader.js';
4
3
  export * from './pdf-revision.js';
@@ -12,9 +12,8 @@ import { PdfTrailerEntries } from '../core/objects/pdf-trailer.js';
12
12
  import { PdfDocumentSecurityStoreObject } from '../signing/document-security-store.js';
13
13
  import { ByteArray } from '../types.js';
14
14
  import { PdfDocumentVerificationResult, PdfSigner } from '../signing/signer.js';
15
- import { PdfXfaManager } from '../xfa/manager.js';
16
15
  import { PdfAcroFormManager } from '../acroform/manager.js';
17
- import { PdfFontManager } from '../fonts/font-manager.js';
16
+ import { PdfFontManager } from '../fonts/manager.js';
18
17
  /**
19
18
  * Represents a PDF document with support for reading, writing, and modifying PDF files.
20
19
  * Handles document structure, revisions, encryption, and digital signatures.
@@ -39,9 +38,9 @@ export declare class PdfDocument extends PdfObject {
39
38
  signer: PdfSigner;
40
39
  /** Security handler for encryption/decryption operations */
41
40
  securityHandler?: PdfSecurityHandler;
42
- private _xfa?;
43
- private _acroForm?;
44
- private _fonts?;
41
+ /** */
42
+ readonly acroForm: PdfAcroFormManager;
43
+ readonly fonts: PdfFontManager;
45
44
  private hasEncryptionDictionary?;
46
45
  private toBeCommitted;
47
46
  /**
@@ -65,12 +64,6 @@ export declare class PdfDocument extends PdfObject {
65
64
  });
66
65
  get header(): PdfComment | undefined;
67
66
  set header(comment: PdfComment | undefined);
68
- /** XFA manager for handling XFA forms */
69
- get xfa(): PdfXfaManager;
70
- /** AcroForm manager for handling form fields */
71
- get acroForm(): PdfAcroFormManager;
72
- /** Font manager for embedding and managing fonts */
73
- get fonts(): PdfFontManager;
74
67
  /**
75
68
  * Creates a PdfDocument from an array of PDF objects.
76
69
  * Parses objects into revisions based on EOF comments.
@@ -93,6 +86,16 @@ export declare class PdfDocument extends PdfObject {
93
86
  * @param objects - PDF objects to add to the document
94
87
  */
95
88
  add(...objects: PdfObject[]): void;
89
+ /**
90
+ * Packs non-stream indirect objects into compressed ObjStm containers.
91
+ * Objects that already have an object number are left unchanged.
92
+ * Appearance streams and other PdfStream objects must NOT be passed here —
93
+ * only non-stream indirect objects (dictionaries, arrays, etc.) are eligible.
94
+ *
95
+ * @param objects - Non-stream indirect objects to compress into ObjStm
96
+ * @param batchSize - Maximum objects per ObjStm container (default 100)
97
+ */
98
+ addObjectsAsStream(objects: PdfIndirectObject[], batchSize?: number): void;
96
99
  /**
97
100
  * Gets the latest (most recent) revision of the document.
98
101
  *
@@ -243,6 +246,7 @@ export declare class PdfDocument extends PdfObject {
243
246
  * @param newObjects - Additional objects to add before committing
244
247
  */
245
248
  commit(...newObjects: PdfObject[]): Promise<void>;
249
+ private ensureEncryptionDictionary;
246
250
  /**
247
251
  * Sets the Document Security Store (DSS) for the document.
248
252
  * Used for long-term validation of digital signatures.
@@ -284,7 +288,7 @@ export declare class PdfDocument extends PdfObject {
284
288
  *
285
289
  * @returns A cloned PdfDocument instance
286
290
  */
287
- clone(): this;
291
+ cloneImpl(): this;
288
292
  /**
289
293
  * Creates a PdfDocument from a byte stream.
290
294
  *
@@ -14,12 +14,11 @@ import { PdfByteOffsetToken } from '../core/tokens/byte-offset-token.js';
14
14
  import { PdfNumberToken } from '../core/tokens/number-token.js';
15
15
  import { PdfXRefTableEntryToken } from '../core/tokens/xref-table-entry-token.js';
16
16
  import { PdfStartXRef } from '../core/objects/pdf-start-xref.js';
17
- import { FoundCompressedObjectError } from './errors.js';
17
+ import { FoundCompressedObjectError } from '../errors.js';
18
18
  import { PdfReader } from './pdf-reader.js';
19
19
  import { PdfSigner } from '../signing/signer.js';
20
- import { PdfXfaManager } from '../xfa/manager.js';
21
20
  import { PdfAcroFormManager } from '../acroform/manager.js';
22
- import { PdfFontManager } from '../fonts/font-manager.js';
21
+ import { PdfFontManager } from '../fonts/manager.js';
23
22
  import { concatUint8Arrays } from '../utils/concatUint8Arrays.js';
24
23
  /**
25
24
  * Represents a PDF document with support for reading, writing, and modifying PDF files.
@@ -45,9 +44,9 @@ export class PdfDocument extends PdfObject {
45
44
  signer;
46
45
  /** Security handler for encryption/decryption operations */
47
46
  securityHandler;
48
- _xfa;
49
- _acroForm;
50
- _fonts;
47
+ /** */
48
+ acroForm;
49
+ fonts;
51
50
  hasEncryptionDictionary = false;
52
51
  toBeCommitted = [];
53
52
  /**
@@ -81,6 +80,8 @@ export class PdfDocument extends PdfObject {
81
80
  this.calculateOffsets();
82
81
  this.securityHandler =
83
82
  options?.securityHandler ?? this.getSecurityHandler();
83
+ this.acroForm = new PdfAcroFormManager(this);
84
+ this.fonts = new PdfFontManager(this);
84
85
  }
85
86
  get header() {
86
87
  return this.revisions[0].header;
@@ -89,27 +90,6 @@ export class PdfDocument extends PdfObject {
89
90
  if (comment)
90
91
  this.revisions[0].header = comment;
91
92
  }
92
- /** XFA manager for handling XFA forms */
93
- get xfa() {
94
- if (!this._xfa) {
95
- this._xfa = new PdfXfaManager(this);
96
- }
97
- return this._xfa;
98
- }
99
- /** AcroForm manager for handling form fields */
100
- get acroForm() {
101
- if (!this._acroForm) {
102
- this._acroForm = new PdfAcroFormManager(this);
103
- }
104
- return this._acroForm;
105
- }
106
- /** Font manager for embedding and managing fonts */
107
- get fonts() {
108
- if (!this._fonts) {
109
- this._fonts = new PdfFontManager(this);
110
- }
111
- return this._fonts;
112
- }
113
93
  /**
114
94
  * Creates a PdfDocument from an array of PDF objects.
115
95
  * Parses objects into revisions based on EOF comments.
@@ -170,6 +150,36 @@ export class PdfDocument extends PdfObject {
170
150
  this.latestRevision.addObject(obj);
171
151
  }
172
152
  }
153
+ /**
154
+ * Packs non-stream indirect objects into compressed ObjStm containers.
155
+ * Objects that already have an object number are left unchanged.
156
+ * Appearance streams and other PdfStream objects must NOT be passed here —
157
+ * only non-stream indirect objects (dictionaries, arrays, etc.) are eligible.
158
+ *
159
+ * @param objects - Non-stream indirect objects to compress into ObjStm
160
+ * @param batchSize - Maximum objects per ObjStm container (default 100)
161
+ */
162
+ addObjectsAsStream(objects, batchSize = 100) {
163
+ if (objects.length === 0)
164
+ return;
165
+ for (let start = 0; start < objects.length; start += batchSize) {
166
+ const batch = objects.slice(start, Math.min(start + batchSize, objects.length));
167
+ // Pre-assign a contiguous block of object numbers for the batch
168
+ const xref = this.latestRevision.xref;
169
+ const startNum = xref.reserveObjectNumbers(batch.length);
170
+ for (let i = 0; i < batch.length; i++) {
171
+ if (!batch[i].inPdf()) {
172
+ batch[i].objectNumber = startNum + i;
173
+ }
174
+ }
175
+ // Build the ObjStm and apply FlateDecode compression
176
+ const objStream = PdfObjStream.fromObjects(batch);
177
+ objStream.addFilter('FlateDecode');
178
+ // Add the container — xref.addObject() auto-registers children as type-2 entries
179
+ const container = new PdfIndirectObject({ content: objStream });
180
+ this.add(container);
181
+ }
182
+ }
173
183
  /**
174
184
  * Gets the latest (most recent) revision of the document.
175
185
  *
@@ -583,20 +593,24 @@ export class PdfDocument extends PdfObject {
583
593
  newObject instanceof PdfIndirectObject &&
584
594
  this.isObjectEncryptable(newObject)) {
585
595
  await this.securityHandler.write();
586
- if (!this.hasEncryptionDictionary) {
587
- const encryptionDictObject = new PdfIndirectObject({
588
- content: this.securityHandler.dict,
589
- encryptable: false,
590
- });
591
- this.latestRevision.addObject(encryptionDictObject);
592
- this.trailerDict.set('Encrypt', encryptionDictObject.reference);
593
- this.hasEncryptionDictionary = true;
594
- }
596
+ this.ensureEncryptionDictionary();
595
597
  await this.securityHandler.encryptObject(newObject);
596
598
  }
597
599
  }
598
600
  await this.update();
599
601
  }
602
+ ensureEncryptionDictionary() {
603
+ if (this.hasEncryptionDictionary) {
604
+ return;
605
+ }
606
+ const encryptionDictObject = new PdfIndirectObject({
607
+ content: this.securityHandler.dict,
608
+ encryptable: false,
609
+ });
610
+ this.latestRevision.addObject(encryptionDictObject);
611
+ this.trailerDict.set('Encrypt', encryptionDictObject.reference);
612
+ this.hasEncryptionDictionary = true;
613
+ }
600
614
  /**
601
615
  * Sets the Document Security Store (DSS) for the document.
602
616
  * Used for long-term validation of digital signatures.
@@ -729,7 +743,7 @@ export class PdfDocument extends PdfObject {
729
743
  *
730
744
  * @returns A cloned PdfDocument instance
731
745
  */
732
- clone() {
746
+ cloneImpl() {
733
747
  const clonedRevisions = this.revisions.map((rev) => rev.clone());
734
748
  return new PdfDocument({
735
749
  revisions: clonedRevisions,
@@ -124,7 +124,7 @@ export declare class PdfRevision extends PdfObject {
124
124
  *
125
125
  * @returns A cloned PdfRevision instance
126
126
  */
127
- clone(): this;
127
+ cloneImpl(): this;
128
128
  protected tokenize(): PdfToken[];
129
129
  toBytes(): ByteArray;
130
130
  }
@@ -250,7 +250,7 @@ export class PdfRevision extends PdfObject {
250
250
  *
251
251
  * @returns A cloned PdfRevision instance
252
252
  */
253
- clone() {
253
+ cloneImpl() {
254
254
  const clonedObjects = this.objects.map((obj) => obj.clone());
255
255
  return new PdfRevision({ objects: clonedObjects });
256
256
  }
@@ -110,6 +110,14 @@ export declare class PdfXrefLookup {
110
110
  * @returns The updated xref object
111
111
  */
112
112
  update(): PdfIndirectObject<PdfXRefStream> | PdfXRefTable;
113
+ /**
114
+ * Reserves a contiguous block of object numbers without registering objects.
115
+ * Use this to pre-assign numbers to objects that will live inside an ObjStm.
116
+ *
117
+ * @param count - Number of object numbers to reserve
118
+ * @returns The first reserved object number
119
+ */
120
+ reserveObjectNumbers(count: number): number;
113
121
  /**
114
122
  * Adds an indirect object to the xref lookup.
115
123
  * Assigns an object number if not already set.
@@ -305,6 +305,18 @@ export class PdfXrefLookup {
305
305
  this.object = newObject;
306
306
  return this.object;
307
307
  }
308
+ /**
309
+ * Reserves a contiguous block of object numbers without registering objects.
310
+ * Use this to pre-assign numbers to objects that will live inside an ObjStm.
311
+ *
312
+ * @param count - Number of object numbers to reserve
313
+ * @returns The first reserved object number
314
+ */
315
+ reserveObjectNumbers(count) {
316
+ const startNum = this.size;
317
+ this.size += count;
318
+ return startNum;
319
+ }
308
320
  /**
309
321
  * Adds an indirect object to the xref lookup.
310
322
  * Assigns an object number if not already set.
@@ -87,11 +87,14 @@ export class PdfSecurityHandler {
87
87
  else if (obj instanceof PdfString) {
88
88
  const decryptedData = await this.decrypt('string', obj.raw, objectNumber, generationNumber);
89
89
  obj.raw = decryptedData;
90
+ obj.setModified(false);
90
91
  }
91
92
  else if (obj instanceof PdfStream) {
92
93
  const decryptedData = await this.decrypt('stream', obj.raw, objectNumber, generationNumber);
93
94
  obj.raw = decryptedData;
94
95
  await decryptObject(obj.header);
96
+ obj.setModified(false);
97
+ obj.header.setModified(false);
95
98
  }
96
99
  else if (obj instanceof PdfDictionary) {
97
100
  const values = obj.values;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Encodes a text string for use in a PDF content stream text operator (`Tj`).
3
+ *
4
+ * PDF literal strings `(...)` in content streams are raw bytes interpreted by the
5
+ * font's encoding — NOT UTF-8. This function produces the correct PDF string token:
6
+ *
7
+ * - Type0/Identity-H fonts: hex string `<XXXX...>` with 2 bytes per character (CID = Unicode codepoint)
8
+ * - Single-byte fonts: PDF literal `(...)` with octal escapes `\ooo` for byte values ≥ 0x80,
9
+ * using the reverse encoding map when available for characters outside the Latin-1 range.
10
+ *
11
+ * @param text - The Unicode text to encode
12
+ * @param isUnicode - True if the font uses Type0/Identity-H encoding (2-byte CID per character)
13
+ * @param reverseEncodingMap - Optional map from Unicode character to byte code,
14
+ * derived by inverting the font's Differences-based encoding map
15
+ * @returns A PDF string token ready to use before `Tj`, e.g. `<0050> Tj` or `(text) Tj`
16
+ */
17
+ export declare function encodePdfText(text: string, isUnicode: boolean, reverseEncodingMap?: Map<string, number>): string;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Encodes a text string for use in a PDF content stream text operator (`Tj`).
3
+ *
4
+ * PDF literal strings `(...)` in content streams are raw bytes interpreted by the
5
+ * font's encoding — NOT UTF-8. This function produces the correct PDF string token:
6
+ *
7
+ * - Type0/Identity-H fonts: hex string `<XXXX...>` with 2 bytes per character (CID = Unicode codepoint)
8
+ * - Single-byte fonts: PDF literal `(...)` with octal escapes `\ooo` for byte values ≥ 0x80,
9
+ * using the reverse encoding map when available for characters outside the Latin-1 range.
10
+ *
11
+ * @param text - The Unicode text to encode
12
+ * @param isUnicode - True if the font uses Type0/Identity-H encoding (2-byte CID per character)
13
+ * @param reverseEncodingMap - Optional map from Unicode character to byte code,
14
+ * derived by inverting the font's Differences-based encoding map
15
+ * @returns A PDF string token ready to use before `Tj`, e.g. `<0050> Tj` or `(text) Tj`
16
+ */
17
+ export function encodePdfText(text, isUnicode, reverseEncodingMap) {
18
+ if (isUnicode) {
19
+ // Type0 / Identity-H: 2-byte big-endian CID per code point
20
+ let hex = '<';
21
+ for (const char of text) {
22
+ const code = char.codePointAt(0) ?? 0;
23
+ hex += code.toString(16).padStart(4, '0');
24
+ }
25
+ return hex + '>';
26
+ }
27
+ // Single-byte font: PDF literal string with octal escapes for non-ASCII bytes
28
+ let result = '(';
29
+ for (const char of text) {
30
+ const code = char.charCodeAt(0);
31
+ if (code === 0x28) {
32
+ result += '\\('; // (
33
+ }
34
+ else if (code === 0x29) {
35
+ result += '\\)'; // )
36
+ }
37
+ else if (code === 0x5c) {
38
+ result += '\\\\'; // \
39
+ }
40
+ else if (code === 0x0a) {
41
+ result += '\\n';
42
+ }
43
+ else if (code === 0x0d) {
44
+ result += '\\r';
45
+ }
46
+ else if (code < 0x80) {
47
+ result += char; // ASCII: safe to write directly
48
+ }
49
+ else if (reverseEncodingMap?.has(char)) {
50
+ // Custom font encoding (Differences): use the mapped byte code
51
+ const byteCode = reverseEncodingMap.get(char);
52
+ result += '\\' + byteCode.toString(8).padStart(3, '0');
53
+ }
54
+ else if (code <= 0xff) {
55
+ // Latin-1 range: encode as octal so UTF-8 serialisation doesn't mangle it
56
+ result += '\\' + code.toString(8).padStart(3, '0');
57
+ }
58
+ // Characters above 0xFF with no mapping are silently dropped
59
+ }
60
+ return result + ')';
61
+ }
@@ -1,4 +1,4 @@
1
- export * from './IterableReadableStream.js';
1
+ export * from './iterable-readable-stream.js';
2
2
  export * from './algos.js';
3
3
  export * from './assert.js';
4
4
  export * from './bytesToHex.js';
@@ -1,4 +1,4 @@
1
- export * from './IterableReadableStream.js';
1
+ export * from './iterable-readable-stream.js';
2
2
  export * from './algos.js';
3
3
  export * from './assert.js';
4
4
  export * from './bytesToHex.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdf-lite",
3
- "version": "1.3.3",
3
+ "version": "1.5.0",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "exports": {