pdf-lite 1.4.0 → 1.6.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 (144) hide show
  1. package/EXAMPLES.md +51 -70
  2. package/README.md +1 -1
  3. package/dist/acroform/appearance/index.d.ts +4 -4
  4. package/dist/acroform/appearance/index.js +4 -4
  5. package/dist/acroform/appearance/{PdfAppearanceStream.d.ts → pdf-appearance-stream.d.ts} +9 -3
  6. package/dist/acroform/appearance/{PdfAppearanceStream.js → pdf-appearance-stream.js} +14 -5
  7. package/dist/acroform/appearance/{PdfButtonAppearanceStream.d.ts → pdf-button-appearance-stream.d.ts} +3 -2
  8. package/dist/acroform/appearance/pdf-button-appearance-stream.js +58 -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/{PdfTextAppearanceStream.d.ts → pdf-text-appearance-stream.d.ts} +7 -2
  14. package/dist/acroform/appearance/pdf-text-appearance-stream.js +104 -0
  15. package/dist/acroform/fields/index.d.ts +7 -7
  16. package/dist/acroform/fields/index.js +7 -7
  17. package/dist/acroform/fields/pdf-button-form-field.d.ts +14 -0
  18. package/dist/acroform/fields/pdf-button-form-field.js +70 -0
  19. package/dist/acroform/fields/pdf-choice-form-field.d.ts +19 -0
  20. package/dist/acroform/fields/pdf-choice-form-field.js +112 -0
  21. package/dist/acroform/fields/{PdfFormFieldFlags.d.ts → pdf-form-field-flags.d.ts} +5 -6
  22. package/dist/acroform/fields/{PdfFormFieldFlags.js → pdf-form-field-flags.js} +12 -18
  23. package/dist/acroform/fields/{PdfFormField.d.ts → pdf-form-field.d.ts} +37 -38
  24. package/dist/acroform/fields/pdf-form-field.js +519 -0
  25. package/dist/acroform/fields/{PdfSignatureFormField.d.ts → pdf-signature-form-field.d.ts} +1 -1
  26. package/dist/acroform/fields/{PdfSignatureFormField.js → pdf-signature-form-field.js} +1 -1
  27. package/dist/acroform/fields/{PdfTextFormField.d.ts → pdf-text-form-field.d.ts} +1 -1
  28. package/dist/acroform/fields/{PdfTextFormField.js → pdf-text-form-field.js} +11 -13
  29. package/dist/acroform/fields/types.d.ts +6 -1
  30. package/dist/acroform/index.d.ts +1 -3
  31. package/dist/acroform/index.js +1 -3
  32. package/dist/acroform/pdf-acro-form.d.ts +45 -0
  33. package/dist/acroform/pdf-acro-form.js +203 -0
  34. package/dist/acroform/xfa/index.d.ts +3 -3
  35. package/dist/acroform/xfa/index.js +2 -2
  36. package/dist/acroform/xfa/{PdfXfaData.d.ts → pdf-xfa-data.d.ts} +4 -3
  37. package/dist/acroform/xfa/{PdfXfaData.js → pdf-xfa-data.js} +16 -12
  38. package/dist/acroform/xfa/pdf-xfa-form.d.ts +16 -0
  39. package/dist/acroform/xfa/pdf-xfa-form.js +34 -0
  40. package/dist/annotations/index.d.ts +3 -4
  41. package/dist/annotations/index.js +3 -4
  42. package/dist/annotations/{PdfAnnotationFlags.d.ts → pdf-annotation-flags.d.ts} +3 -4
  43. package/dist/annotations/{PdfAnnotationFlags.js → pdf-annotation-flags.js} +5 -6
  44. package/dist/annotations/{PdfAnnotation.d.ts → pdf-annotation.d.ts} +31 -5
  45. package/dist/annotations/{PdfAnnotation.js → pdf-annotation.js} +31 -19
  46. package/dist/annotations/pdf-default-resources.d.ts +11 -0
  47. package/dist/annotations/pdf-default-resources.js +3 -0
  48. package/dist/annotations/{PdfWidgetAnnotation.d.ts → pdf-widget-annotation.d.ts} +1 -1
  49. package/dist/annotations/{PdfWidgetAnnotation.js → pdf-widget-annotation.js} +1 -1
  50. package/dist/core/decoder.js +1 -1
  51. package/dist/core/objects/pdf-array.d.ts +8 -1
  52. package/dist/core/objects/pdf-array.js +31 -0
  53. package/dist/core/objects/pdf-dictionary.d.ts +2 -0
  54. package/dist/core/objects/pdf-dictionary.js +14 -7
  55. package/dist/core/objects/pdf-hexadecimal.d.ts +1 -0
  56. package/dist/core/objects/pdf-hexadecimal.js +3 -3
  57. package/dist/core/objects/pdf-indirect-object.d.ts +18 -9
  58. package/dist/core/objects/pdf-indirect-object.js +75 -16
  59. package/dist/core/objects/pdf-number.d.ts +1 -0
  60. package/dist/core/objects/pdf-number.js +5 -4
  61. package/dist/core/objects/pdf-object-reference.d.ts +8 -1
  62. package/dist/core/objects/pdf-object-reference.js +14 -0
  63. package/dist/core/objects/pdf-object.d.ts +14 -0
  64. package/dist/core/objects/pdf-object.js +36 -0
  65. package/dist/core/objects/pdf-start-xref.d.ts +1 -0
  66. package/dist/core/objects/pdf-start-xref.js +4 -0
  67. package/dist/core/objects/pdf-stream.d.ts +44 -7
  68. package/dist/core/objects/pdf-stream.js +284 -26
  69. package/dist/core/objects/pdf-string.d.ts +1 -0
  70. package/dist/core/objects/pdf-string.js +3 -6
  71. package/dist/core/objects/pdf-trailer.d.ts +1 -0
  72. package/dist/core/objects/pdf-trailer.js +6 -3
  73. package/dist/core/objects/pdf-xref-table.js +1 -1
  74. package/dist/core/parser/incremental-parser.d.ts +0 -13
  75. package/dist/core/parser/incremental-parser.js +1 -18
  76. package/dist/core/ref.d.ts +3 -1
  77. package/dist/core/ref.js +8 -5
  78. package/dist/core/streams/object-stream.d.ts +1 -1
  79. package/dist/core/streams/object-stream.js +1 -1
  80. package/dist/core/tokens/token.d.ts +2 -1
  81. package/dist/core/tokens/token.js +3 -0
  82. package/dist/errors.d.ts +22 -0
  83. package/dist/errors.js +24 -0
  84. package/dist/fonts/index.d.ts +0 -1
  85. package/dist/fonts/index.js +0 -1
  86. package/dist/fonts/pdf-font.d.ts +94 -32
  87. package/dist/fonts/pdf-font.js +301 -83
  88. package/dist/index.d.ts +1 -0
  89. package/dist/index.js +1 -0
  90. package/dist/pdf/index.d.ts +2 -1
  91. package/dist/pdf/index.js +2 -1
  92. package/dist/pdf/pdf-document.d.ts +61 -36
  93. package/dist/pdf/pdf-document.js +315 -117
  94. package/dist/pdf/pdf-page.d.ts +50 -0
  95. package/dist/pdf/pdf-page.js +144 -0
  96. package/dist/pdf/pdf-pages.d.ts +28 -0
  97. package/dist/pdf/pdf-pages.js +94 -0
  98. package/dist/pdf/pdf-reader.d.ts +5 -1
  99. package/dist/pdf/pdf-reader.js +36 -2
  100. package/dist/pdf/pdf-revision.d.ts +3 -3
  101. package/dist/pdf/pdf-revision.js +7 -7
  102. package/dist/pdf/pdf-xref-lookup.js +34 -14
  103. package/dist/signing/document-security-store.d.ts +14 -17
  104. package/dist/signing/document-security-store.js +19 -34
  105. package/dist/signing/signer.d.ts +23 -8
  106. package/dist/signing/signer.js +51 -17
  107. package/dist/utils/encodePdfText.d.ts +17 -0
  108. package/dist/utils/encodePdfText.js +61 -0
  109. package/dist/utils/index.d.ts +1 -2
  110. package/dist/utils/index.js +1 -2
  111. package/dist/utils/needsCentralWhitespace.d.ts +10 -0
  112. package/dist/utils/needsCentralWhitespace.js +34 -0
  113. package/package.json +3 -3
  114. package/dist/acroform/PdfAcroForm.d.ts +0 -63
  115. package/dist/acroform/PdfAcroForm.js +0 -279
  116. package/dist/acroform/PdfFontEncodingCache.d.ts +0 -16
  117. package/dist/acroform/PdfFontEncodingCache.js +0 -75
  118. package/dist/acroform/acroform.d.ts +0 -9
  119. package/dist/acroform/acroform.js +0 -7
  120. package/dist/acroform/appearance/PdfButtonAppearanceStream.js +0 -54
  121. package/dist/acroform/appearance/PdfChoiceAppearanceStream.d.ts +0 -15
  122. package/dist/acroform/appearance/PdfChoiceAppearanceStream.js +0 -48
  123. package/dist/acroform/appearance/PdfTextAppearanceStream.js +0 -75
  124. package/dist/acroform/fields/PdfButtonFormField.d.ts +0 -9
  125. package/dist/acroform/fields/PdfButtonFormField.js +0 -35
  126. package/dist/acroform/fields/PdfChoiceFormField.d.ts +0 -9
  127. package/dist/acroform/fields/PdfChoiceFormField.js +0 -46
  128. package/dist/acroform/fields/PdfFormField.js +0 -499
  129. package/dist/acroform/manager.d.ts +0 -33
  130. package/dist/acroform/manager.js +0 -51
  131. package/dist/acroform/xfa/PdfXfaForm.d.ts +0 -12
  132. package/dist/acroform/xfa/PdfXfaForm.js +0 -64
  133. package/dist/annotations/PdfAnnotationWriter.d.ts +0 -20
  134. package/dist/annotations/PdfAnnotationWriter.js +0 -76
  135. package/dist/fonts/font-manager.d.ts +0 -127
  136. package/dist/fonts/font-manager.js +0 -378
  137. package/dist/pdf/errors.d.ts +0 -6
  138. package/dist/pdf/errors.js +0 -6
  139. package/dist/utils/predictors.d.ts +0 -113
  140. package/dist/utils/predictors.js +0 -279
  141. /package/dist/acroform/fields/{PdfDefaultAppearance.d.ts → pdf-default-appearance.d.ts} +0 -0
  142. /package/dist/acroform/fields/{PdfDefaultAppearance.js → pdf-default-appearance.js} +0 -0
  143. /package/dist/utils/{IterableReadableStream.d.ts → iterable-readable-stream.d.ts} +0 -0
  144. /package/dist/utils/{IterableReadableStream.js → iterable-readable-stream.js} +0 -0
@@ -30,23 +30,20 @@ export class PdfDocumentSecurityStoreDictionary extends PdfDictionary {
30
30
  * @example
31
31
  * ```typescript
32
32
  * const dss = new PdfDocumentSecurityStoreObject(document)
33
- * await dss.addCert(certificateBytes)
34
- * await dss.addCrl(crlBytes)
35
- * await dss.addOcsp(ocspBytes)
33
+ * dss.addCert(certificateBytes)
34
+ * dss.addCrl(crlBytes)
35
+ * dss.addOcsp(ocspBytes)
36
36
  * ```
37
37
  */
38
38
  export class PdfDocumentSecurityStoreObject extends PdfIndirectObject {
39
- /** Reference to the parent document. */
40
- document;
41
39
  /**
42
40
  * Creates a new DSS object.
43
41
  *
44
42
  * @param document - The parent PDF document.
45
43
  * @param content - Optional pre-existing DSS dictionary.
46
44
  */
47
- constructor(document, content) {
45
+ constructor(content) {
48
46
  super(content ?? new PdfDocumentSecurityStoreDictionary());
49
- this.document = document;
50
47
  }
51
48
  /**
52
49
  * Adds an OCSP response to the DSS, avoiding duplicates.
@@ -54,25 +51,21 @@ export class PdfDocumentSecurityStoreObject extends PdfIndirectObject {
54
51
  * @param ocsp - The DER-encoded OCSP response.
55
52
  * @returns The created or existing OCSP object.
56
53
  */
57
- async addOcsp(ocsp) {
54
+ addOcsp(ocsp) {
58
55
  const newOcsp = new PdfStream(ocsp);
59
56
  let ocspArray = this.content.get('OCSPs');
60
- const currentOcsps = (await Promise.all((ocspArray?.items ?? []).map(async (ref) => {
61
- const obj = await this.document.readObject(ref);
62
- return obj;
63
- })));
57
+ const currentOcsps = (ocspArray?.items ?? []).map((ref) => ref.resolve());
64
58
  for (const existingOcsp of currentOcsps) {
65
59
  if (existingOcsp.content.equals(newOcsp)) {
66
- return existingOcsp;
60
+ return existingOcsp.becomes(PdfOcspObject);
67
61
  }
68
62
  }
69
63
  const ocspObject = new PdfOcspObject(newOcsp);
70
- this.document.add(ocspObject);
71
64
  if (!ocspArray) {
72
65
  ocspArray = new PdfArray([]);
73
66
  this.content.set('OCSPs', ocspArray);
74
67
  }
75
- ocspArray.items.push(ocspObject.reference);
68
+ ocspArray.push(ocspObject.reference);
76
69
  return ocspObject;
77
70
  }
78
71
  /**
@@ -81,24 +74,20 @@ export class PdfDocumentSecurityStoreObject extends PdfIndirectObject {
81
74
  * @param crl - The DER-encoded CRL.
82
75
  * @returns The created or existing CRL object.
83
76
  */
84
- async addCrl(crl) {
77
+ addCrl(crl) {
85
78
  let crlArray = this.content.get('CRLs');
86
- const currentCrls = (await Promise.all((crlArray?.items ?? []).map(async (ref) => {
87
- const obj = await this.document.readObject(ref);
88
- return obj;
89
- })));
79
+ const currentCrls = (crlArray?.items ?? []).map((ref) => ref.resolve());
90
80
  for (const existingCrl of currentCrls) {
91
81
  if (existingCrl.content.equals(new PdfStream(crl))) {
92
- return existingCrl;
82
+ return existingCrl.becomes(PdfCrlObject);
93
83
  }
94
84
  }
95
85
  const crlObject = new PdfCrlObject(new PdfStream(crl));
96
- this.document.add(crlObject);
97
86
  if (!crlArray) {
98
87
  crlArray = new PdfArray([]);
99
88
  this.content.set('CRLs', crlArray);
100
89
  }
101
- crlArray.items.push(crlObject.reference);
90
+ crlArray.push(crlObject.reference);
102
91
  return crlObject;
103
92
  }
104
93
  /**
@@ -107,24 +96,20 @@ export class PdfDocumentSecurityStoreObject extends PdfIndirectObject {
107
96
  * @param cert - The DER-encoded certificate.
108
97
  * @returns The created or existing certificate object.
109
98
  */
110
- async addCert(cert) {
99
+ addCert(cert) {
111
100
  let certArray = this.content.get('Certs');
112
- const currentCerts = (await Promise.all((certArray?.items ?? []).map(async (ref) => {
113
- const obj = await this.document.readObject(ref);
114
- return obj;
115
- })));
101
+ const currentCerts = (certArray?.items ?? []).map((ref) => ref.resolve());
116
102
  for (const existingCert of currentCerts) {
117
103
  if (existingCert.content.equals(new PdfStream(cert))) {
118
- return existingCert;
104
+ return existingCert.becomes(PdfCertObject);
119
105
  }
120
106
  }
121
107
  const certObject = new PdfCertObject(new PdfStream(cert));
122
- this.document.add(certObject);
123
108
  if (!certArray) {
124
109
  certArray = new PdfArray([]);
125
110
  this.content.set('Certs', certArray);
126
111
  }
127
- certArray.items.push(certObject.reference);
112
+ certArray.push(certObject.reference);
128
113
  return certObject;
129
114
  }
130
115
  /**
@@ -132,12 +117,12 @@ export class PdfDocumentSecurityStoreObject extends PdfIndirectObject {
132
117
  *
133
118
  * @param revocationInfo - The revocation information to add.
134
119
  */
135
- async addRevocationInfo(revocationInfo) {
120
+ addRevocationInfo(revocationInfo) {
136
121
  for (const ocsp of revocationInfo.ocsps ?? []) {
137
- await this.addOcsp(ocsp);
122
+ this.addOcsp(ocsp);
138
123
  }
139
124
  for (const crl of revocationInfo.crls ?? []) {
140
- await this.addCrl(crl);
125
+ this.addCrl(crl);
141
126
  }
142
127
  }
143
128
  /**
@@ -1,8 +1,9 @@
1
- import { PdfDocument } from '../pdf/pdf-document.js';
1
+ import { PdfDocumentSecurityStoreObject } from './document-security-store.js';
2
2
  import { PdfSignatureObject } from './signatures/index.js';
3
3
  import { PdfSignatureVerificationResult, CertificateValidationOptions, PdfSignatureSubType } from './types.js';
4
+ import { PdfDocument } from '../pdf/pdf-document.js';
4
5
  /**
5
- * Result of verifying all signatures in a document.
6
+ * Result of verifying all signatures in a this.document.
6
7
  */
7
8
  export type PdfDocumentVerificationResult = {
8
9
  /** Whether all signatures in the document are valid. */
@@ -11,7 +12,7 @@ export type PdfDocumentVerificationResult = {
11
12
  signatures: {
12
13
  /** The signature subfilter type. */
13
14
  type: PdfSignatureSubType;
14
- /** Index of the signature in the document. */
15
+ /** Index of the signature in the this.document. */
15
16
  index: number;
16
17
  /** The signature object. */
17
18
  signature: PdfSignatureObject;
@@ -30,16 +31,22 @@ export type PdfDocumentVerificationResult = {
30
31
  * ```
31
32
  */
32
33
  export declare class PdfSigner {
34
+ /** The PDF document to be signed. */
35
+ document: PdfDocument;
33
36
  /** Whether to use the Document Security Store for revocation information. */
34
37
  useDocumentSecurityStore: boolean;
38
+ constructor(options: {
39
+ useDocumentSecurityStore?: boolean;
40
+ document: PdfDocument;
41
+ });
35
42
  /**
36
- * Signs all signature objects in the document.
43
+ * Signs all signature objects in the this.document.
37
44
  * Computes byte ranges, generates signatures, and optionally adds revocation info to DSS.
38
45
  *
39
46
  * @param document - The PDF document to sign.
40
- * @returns The signed document.
47
+ * @returns The signed this.document.
41
48
  */
42
- sign(document: PdfDocument): Promise<PdfDocument>;
49
+ sign(): Promise<void>;
43
50
  /**
44
51
  * Instantiates the appropriate signature object based on SubFilter type.
45
52
  *
@@ -48,7 +55,7 @@ export declare class PdfSigner {
48
55
  */
49
56
  private instantiateSignatureObject;
50
57
  /**
51
- * Verifies all signatures in the document.
58
+ * Verifies all signatures in the this.document.
52
59
  * First serializes the document to bytes and reloads it to ensure signatures
53
60
  * are properly deserialized into the correct classes before verification.
54
61
  * Then searches for signature objects, computes their byte ranges, and verifies each one.
@@ -72,7 +79,15 @@ export declare class PdfSigner {
72
79
  * }
73
80
  * ```
74
81
  */
75
- verify(document: PdfDocument, options?: {
82
+ verify(options?: {
76
83
  certificateValidation?: CertificateValidationOptions | boolean;
77
84
  }): Promise<PdfDocumentVerificationResult>;
85
+ /**
86
+ * Sets the Document Security Store (DSS) for the this.document.
87
+ * Used for long-term validation of digital signatures.
88
+ *
89
+ * @param dss - The Document Security Store object to set
90
+ * @throws Error if the document has no root dictionary
91
+ */
92
+ setDocumentSecurityStore(dss: PdfDocumentSecurityStoreObject): void;
78
93
  }
@@ -1,6 +1,3 @@
1
- import { PdfCommentToken } from '../core/tokens/comment-token.js';
2
- import { PdfHexadecimalToken } from '../core/tokens/hexadecimal-token.js';
3
- import { PdfNameToken } from '../core/tokens/name-token.js';
4
1
  import { concatUint8Arrays } from '../utils/concatUint8Arrays.js';
5
2
  import { PdfDocumentSecurityStoreObject } from './document-security-store.js';
6
3
  import { PdfSignatureObject, PdfAdbePkcs7DetachedSignatureObject, PdfAdbePkcs7Sha1SignatureObject, PdfAdbePkcsX509RsaSha1SignatureObject, PdfEtsiCadesDetachedSignatureObject, PdfEtsiRfc3161SignatureObject, PdfSignatureDictionary, } from './signatures/index.js';
@@ -8,6 +5,9 @@ import { PdfNumber } from '../core/objects/pdf-number.js';
8
5
  import { PdfIndirectObject } from '../core/objects/pdf-indirect-object.js';
9
6
  import { PdfDictionary } from '../core/objects/pdf-dictionary.js';
10
7
  import { PdfArray } from '../core/objects/pdf-array.js';
8
+ import { PdfNameToken } from '../core/tokens/name-token.js';
9
+ import { PdfCommentToken } from '../core/tokens/comment-token.js';
10
+ import { PdfHexadecimalToken } from '../core/tokens/hexadecimal-token.js';
11
11
  /**
12
12
  * Handles digital signing operations for PDF documents.
13
13
  * Processes signature objects and optionally stores revocation information in the DSS.
@@ -19,25 +19,39 @@ import { PdfArray } from '../core/objects/pdf-array.js';
19
19
  * ```
20
20
  */
21
21
  export class PdfSigner {
22
+ /** The PDF document to be signed. */
23
+ document;
22
24
  /** Whether to use the Document Security Store for revocation information. */
23
25
  useDocumentSecurityStore = true;
26
+ constructor(options) {
27
+ this.document = options.document;
28
+ if (options?.useDocumentSecurityStore !== undefined) {
29
+ this.useDocumentSecurityStore = options.useDocumentSecurityStore;
30
+ }
31
+ }
24
32
  /**
25
- * Signs all signature objects in the document.
33
+ * Signs all signature objects in the this.document.
26
34
  * Computes byte ranges, generates signatures, and optionally adds revocation info to DSS.
27
35
  *
28
36
  * @param document - The PDF document to sign.
29
- * @returns The signed document.
37
+ * @returns The signed this.document.
30
38
  */
31
- async sign(document) {
39
+ async sign() {
32
40
  const signatures = [
33
- ...document.objects.filter((x) => x instanceof PdfSignatureObject),
41
+ ...this.document.objects.filter((x) => x instanceof PdfSignatureObject),
34
42
  ];
43
+ // Move all signature objects to the end of the document in a new revision to ensure their byte positions are after all other content.
44
+ signatures.forEach((sig) => {
45
+ this.document.deleteObject(sig);
46
+ this.document.startNewRevision();
47
+ this.document.add(sig);
48
+ });
35
49
  const dss = this.useDocumentSecurityStore
36
- ? (document.objects.find((x) => x instanceof PdfDocumentSecurityStoreObject) ?? new PdfDocumentSecurityStoreObject(document))
50
+ ? (this.document.objects.find((x) => x instanceof PdfDocumentSecurityStoreObject) ?? new PdfDocumentSecurityStoreObject())
37
51
  : undefined;
38
52
  for (let i = 0; i < signatures.length; i++) {
39
53
  const signature = signatures[i];
40
- const tokens = document.tokensWithObjects();
54
+ const tokens = this.document.tokensWithObjects();
41
55
  const signableTokens = [];
42
56
  let contentsOffset = 0;
43
57
  let contentsLength = 0;
@@ -77,7 +91,7 @@ export class PdfSigner {
77
91
  byteCount - (contentsOffset + contentsLength),
78
92
  ];
79
93
  signature.setByteRange(byteRange);
80
- const allBytes = document.toBytes();
94
+ const allBytes = this.document.toBytes();
81
95
  const toSign = concatUint8Arrays(allBytes.slice(byteRange[0], byteRange[1]), allBytes.slice(byteRange[2], byteRange[3] + byteRange[2]));
82
96
  const { signedBytes, revocationInfo } = await signature.sign({
83
97
  bytes: toSign,
@@ -85,13 +99,12 @@ export class PdfSigner {
85
99
  });
86
100
  signature.setSignedBytes(signedBytes);
87
101
  if (dss && revocationInfo) {
88
- await dss.addRevocationInfo(revocationInfo);
102
+ dss.addRevocationInfo(revocationInfo);
89
103
  }
90
104
  }
91
105
  if (dss && !dss.isEmpty()) {
92
- await document.setDocumentSecurityStore(dss);
106
+ this.setDocumentSecurityStore(dss);
93
107
  }
94
- return document;
95
108
  }
96
109
  /**
97
110
  * Instantiates the appropriate signature object based on SubFilter type.
@@ -161,7 +174,7 @@ export class PdfSigner {
161
174
  return signatureObj;
162
175
  }
163
176
  /**
164
- * Verifies all signatures in the document.
177
+ * Verifies all signatures in the this.document.
165
178
  * First serializes the document to bytes and reloads it to ensure signatures
166
179
  * are properly deserialized into the correct classes before verification.
167
180
  * Then searches for signature objects, computes their byte ranges, and verifies each one.
@@ -185,11 +198,11 @@ export class PdfSigner {
185
198
  * }
186
199
  * ```
187
200
  */
188
- async verify(document, options) {
189
- const documentBytes = document.toBytes();
201
+ async verify(options) {
202
+ const documentBytes = this.document.toBytes();
190
203
  const results = [];
191
204
  let allValid = true;
192
- const documentObjects = document.objects;
205
+ const documentObjects = this.document.objects;
193
206
  for (let i = 0; i < documentObjects.length; i++) {
194
207
  const obj = documentObjects[i];
195
208
  if (!(obj instanceof PdfIndirectObject)) {
@@ -284,4 +297,25 @@ export class PdfSigner {
284
297
  signatures: results,
285
298
  };
286
299
  }
300
+ /**
301
+ * Sets the Document Security Store (DSS) for the this.document.
302
+ * Used for long-term validation of digital signatures.
303
+ *
304
+ * @param dss - The Document Security Store object to set
305
+ * @throws Error if the document has no root dictionary
306
+ */
307
+ setDocumentSecurityStore(dss) {
308
+ const root = this.document.root;
309
+ if (!root?.content) {
310
+ throw new Error('Cannot set DSS - document has no root dictionary');
311
+ }
312
+ // Add DSS in a new incremental revision so it doesn't change
313
+ // byte positions in earlier revisions (which have signed ByteRanges).
314
+ this.document.startNewRevision();
315
+ // Clone the root catalog into the new revision with the DSS reference
316
+ const updatedRoot = root.clone();
317
+ updatedRoot.content.set('DSS', dss.reference);
318
+ this.document.add(updatedRoot);
319
+ this.document.add(dss);
320
+ }
287
321
  }
@@ -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';
@@ -13,7 +13,6 @@ export * from './hexBytesToString.js';
13
13
  export * from './hexToBytes.js';
14
14
  export * from './needsUnicodeEncoding.js';
15
15
  export * from './padBytes.js';
16
- export * from './predictors.js';
17
16
  export * from './replaceInBuffer.js';
18
17
  export * from './stringToBytes.js';
19
18
  export * from './stringToHexBytes.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';
@@ -13,7 +13,6 @@ export * from './hexBytesToString.js';
13
13
  export * from './hexToBytes.js';
14
14
  export * from './needsUnicodeEncoding.js';
15
15
  export * from './padBytes.js';
16
- export * from './predictors.js';
17
16
  export * from './replaceInBuffer.js';
18
17
  export * from './stringToBytes.js';
19
18
  export * from './stringToHexBytes.js';
@@ -0,0 +1,10 @@
1
+ import { PdfObject } from '../core/objects/pdf-object.js';
2
+ /**
3
+ * Returns true if the given PDF object's serialized form starts with a
4
+ * non-delimiter character, meaning it requires whitespace separation from
5
+ * a preceding token to avoid ambiguous parsing.
6
+ *
7
+ * Self-delimiting types (PdfString, PdfHexadecimal, PdfArray, PdfDictionary)
8
+ * start with `(`, `<`, `[`, or `<<` and do not need a leading space.
9
+ */
10
+ export declare function needsCentralWhitespace(obj1?: PdfObject, obj2?: PdfObject): boolean;
@@ -0,0 +1,34 @@
1
+ import { PdfBoolean } from '../core/objects/pdf-boolean.js';
2
+ import { PdfNull } from '../core/objects/pdf-null.js';
3
+ import { PdfNumber } from '../core/objects/pdf-number.js';
4
+ import { PdfObjectReference } from '../core/objects/pdf-object-reference.js';
5
+ /**
6
+ * Returns true if the given PDF object's serialized form starts with a
7
+ * non-delimiter character, meaning it requires whitespace separation from
8
+ * a preceding token to avoid ambiguous parsing.
9
+ *
10
+ * Self-delimiting types (PdfString, PdfHexadecimal, PdfArray, PdfDictionary)
11
+ * start with `(`, `<`, `[`, or `<<` and do not need a leading space.
12
+ */
13
+ export function needsCentralWhitespace(obj1, obj2) {
14
+ if (!obj1 || !obj2) {
15
+ return false;
16
+ }
17
+ if (obj1.postTokens === undefined && obj2.preTokens === undefined) {
18
+ // Undefined means tokens will be generated
19
+ return false;
20
+ }
21
+ if (obj1.isTrailingDelimited) {
22
+ // Self-delimiting types (string, hex, array, dict) end with a delimiter
23
+ // character and never require trailing whitespace before the next token
24
+ return false;
25
+ }
26
+ const tokens = [...(obj1.postTokens ?? []), ...(obj2?.preTokens ?? [])];
27
+ if (tokens.length > 0) {
28
+ return false;
29
+ }
30
+ return (obj2 instanceof PdfObjectReference ||
31
+ obj2 instanceof PdfNumber ||
32
+ obj2 instanceof PdfNull ||
33
+ obj2 instanceof PdfBoolean);
34
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdf-lite",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -54,8 +54,8 @@
54
54
  ],
55
55
  "dependencies": {
56
56
  "pako": "2.1.0",
57
- "pki-lite": "^1.0.13",
58
- "pki-lite-crypto-extended": "^1.0.13"
57
+ "pki-lite": "^1.0.14",
58
+ "pki-lite-crypto-extended": "^1.0.14"
59
59
  },
60
60
  "scripts": {
61
61
  "test:acceptance": "vitest run test/acceptance",
@@ -1,63 +0,0 @@
1
- import { PdfDocument } from '../pdf/pdf-document.js';
2
- import { PdfDictionary } from '../core/objects/pdf-dictionary.js';
3
- import { PdfArray } from '../core/objects/pdf-array.js';
4
- import { PdfString } from '../core/objects/pdf-string.js';
5
- import { PdfObjectReference } from '../core/objects/pdf-object-reference.js';
6
- import { PdfIndirectObject } from '../core/objects/pdf-indirect-object.js';
7
- import { PdfBoolean } from '../core/objects/pdf-boolean.js';
8
- import { PdfNumber } from '../core/objects/pdf-number.js';
9
- import { PdfFormField } from './fields/PdfFormField.js';
10
- import './fields/PdfTextFormField.js';
11
- import './fields/PdfButtonFormField.js';
12
- import './fields/PdfChoiceFormField.js';
13
- import './fields/PdfSignatureFormField.js';
14
- import type { FormContext } from './fields/types.js';
15
- export type PdfDefaultResourcesDictionary = PdfDictionary<{
16
- Font?: PdfDictionary;
17
- ProcSet?: PdfArray;
18
- ExtGState?: PdfDictionary;
19
- ColorSpace?: PdfDictionary;
20
- Pattern?: PdfDictionary;
21
- Shading?: PdfDictionary;
22
- XObject?: PdfDictionary;
23
- }>;
24
- export declare class PdfAcroForm<T extends Record<string, string> = Record<string, string>> extends PdfIndirectObject<PdfDictionary<{
25
- Fields: PdfArray<PdfObjectReference>;
26
- NeedAppearances?: PdfBoolean;
27
- SigFlags?: PdfNumber;
28
- CO?: PdfArray<PdfObjectReference>;
29
- DR?: PdfDefaultResourcesDictionary;
30
- DA?: PdfString;
31
- Q?: PdfNumber;
32
- XFA?: PdfDictionary;
33
- }>> implements FormContext<PdfFormField> {
34
- fields: PdfFormField[];
35
- private _fontEncodingCache?;
36
- private document?;
37
- constructor(options?: {
38
- other?: PdfIndirectObject;
39
- fields?: PdfFormField[];
40
- document?: PdfDocument;
41
- });
42
- private get fontEncodingCache();
43
- get fontEncodingMaps(): Map<string, Map<number, string>>;
44
- isModified(): boolean;
45
- get needAppearances(): boolean;
46
- set needAppearances(value: boolean);
47
- get signatureFlags(): number;
48
- set signatureFlags(flags: number);
49
- get defaultAppearance(): string | null;
50
- set defaultAppearance(da: string);
51
- get defaultQuadding(): number;
52
- set defaultQuadding(q: number);
53
- get defaultResources(): PdfDefaultResourcesDictionary | null;
54
- set defaultResources(resources: PdfDefaultResourcesDictionary | null);
55
- setValues(values: Partial<T>): void;
56
- importData(fields: T): void;
57
- exportData(): Partial<T>;
58
- getFontEncodingMap(fontName: string): Promise<Map<number, string> | null>;
59
- static fromDocument(document: PdfDocument): Promise<PdfAcroForm | null>;
60
- private cacheAllFontEncodings;
61
- private updatePageAnnotations;
62
- write(document: PdfDocument): Promise<void>;
63
- }