pdf-lite 1.5.0 → 1.6.1

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 (93) hide show
  1. package/EXAMPLES.md +51 -70
  2. package/README.md +1 -1
  3. package/dist/acroform/appearance/pdf-button-appearance-stream.d.ts +1 -1
  4. package/dist/acroform/appearance/pdf-button-appearance-stream.js +6 -2
  5. package/dist/acroform/fields/pdf-button-form-field.d.ts +0 -9
  6. package/dist/acroform/fields/pdf-button-form-field.js +7 -39
  7. package/dist/acroform/fields/pdf-choice-form-field.d.ts +2 -1
  8. package/dist/acroform/fields/pdf-choice-form-field.js +19 -38
  9. package/dist/acroform/fields/pdf-default-appearance.js +1 -1
  10. package/dist/acroform/fields/pdf-form-field.d.ts +27 -32
  11. package/dist/acroform/fields/pdf-form-field.js +180 -94
  12. package/dist/acroform/fields/pdf-text-form-field.js +6 -33
  13. package/dist/acroform/fields/types.d.ts +1 -1
  14. package/dist/acroform/index.d.ts +0 -2
  15. package/dist/acroform/index.js +0 -2
  16. package/dist/acroform/pdf-acro-form.d.ts +12 -36
  17. package/dist/acroform/pdf-acro-form.js +111 -201
  18. package/dist/acroform/xfa/pdf-xfa-data.d.ts +4 -3
  19. package/dist/acroform/xfa/pdf-xfa-data.js +16 -12
  20. package/dist/acroform/xfa/pdf-xfa-form.d.ts +9 -4
  21. package/dist/acroform/xfa/pdf-xfa-form.js +17 -39
  22. package/dist/annotations/index.d.ts +0 -1
  23. package/dist/annotations/index.js +0 -1
  24. package/dist/annotations/pdf-annotation.d.ts +7 -2
  25. package/dist/annotations/pdf-annotation.js +30 -19
  26. package/dist/annotations/pdf-default-resources.d.ts +11 -0
  27. package/dist/annotations/pdf-default-resources.js +3 -0
  28. package/dist/core/decoder.js +1 -1
  29. package/dist/core/objects/pdf-array.d.ts +8 -1
  30. package/dist/core/objects/pdf-array.js +31 -0
  31. package/dist/core/objects/pdf-dictionary.d.ts +2 -0
  32. package/dist/core/objects/pdf-dictionary.js +14 -7
  33. package/dist/core/objects/pdf-hexadecimal.d.ts +1 -0
  34. package/dist/core/objects/pdf-hexadecimal.js +3 -3
  35. package/dist/core/objects/pdf-indirect-object.d.ts +18 -9
  36. package/dist/core/objects/pdf-indirect-object.js +75 -16
  37. package/dist/core/objects/pdf-number.d.ts +1 -0
  38. package/dist/core/objects/pdf-number.js +5 -4
  39. package/dist/core/objects/pdf-object-reference.d.ts +8 -1
  40. package/dist/core/objects/pdf-object-reference.js +14 -0
  41. package/dist/core/objects/pdf-object.d.ts +14 -0
  42. package/dist/core/objects/pdf-object.js +36 -0
  43. package/dist/core/objects/pdf-start-xref.d.ts +1 -0
  44. package/dist/core/objects/pdf-start-xref.js +4 -0
  45. package/dist/core/objects/pdf-stream.d.ts +47 -7
  46. package/dist/core/objects/pdf-stream.js +301 -32
  47. package/dist/core/objects/pdf-string.d.ts +1 -0
  48. package/dist/core/objects/pdf-string.js +3 -6
  49. package/dist/core/objects/pdf-trailer.d.ts +1 -0
  50. package/dist/core/objects/pdf-trailer.js +6 -3
  51. package/dist/core/objects/pdf-xref-table.js +1 -1
  52. package/dist/core/ref.d.ts +3 -1
  53. package/dist/core/ref.js +8 -5
  54. package/dist/core/tokens/token.d.ts +2 -1
  55. package/dist/core/tokens/token.js +3 -0
  56. package/dist/fonts/index.d.ts +0 -1
  57. package/dist/fonts/index.js +0 -1
  58. package/dist/fonts/pdf-font.d.ts +32 -27
  59. package/dist/fonts/pdf-font.js +115 -77
  60. package/dist/pdf/index.d.ts +2 -0
  61. package/dist/pdf/index.js +2 -0
  62. package/dist/pdf/pdf-document.d.ts +63 -37
  63. package/dist/pdf/pdf-document.js +351 -135
  64. package/dist/pdf/pdf-page.d.ts +50 -0
  65. package/dist/pdf/pdf-page.js +144 -0
  66. package/dist/pdf/pdf-pages.d.ts +28 -0
  67. package/dist/pdf/pdf-pages.js +94 -0
  68. package/dist/pdf/pdf-reader.d.ts +5 -1
  69. package/dist/pdf/pdf-reader.js +36 -2
  70. package/dist/pdf/pdf-revision.d.ts +3 -3
  71. package/dist/pdf/pdf-revision.js +7 -7
  72. package/dist/pdf/pdf-xref-lookup.js +34 -14
  73. package/dist/signing/document-security-store.d.ts +14 -17
  74. package/dist/signing/document-security-store.js +19 -34
  75. package/dist/signing/signer.d.ts +23 -8
  76. package/dist/signing/signer.js +51 -17
  77. package/dist/utils/index.d.ts +0 -1
  78. package/dist/utils/index.js +0 -1
  79. package/dist/utils/needsCentralWhitespace.d.ts +10 -0
  80. package/dist/utils/needsCentralWhitespace.js +34 -0
  81. package/package.json +3 -3
  82. package/dist/acroform/acroform.d.ts +0 -9
  83. package/dist/acroform/acroform.js +0 -7
  84. package/dist/acroform/manager.d.ts +0 -37
  85. package/dist/acroform/manager.js +0 -57
  86. package/dist/acroform/pdf-font-encoding-cache.d.ts +0 -27
  87. package/dist/acroform/pdf-font-encoding-cache.js +0 -188
  88. package/dist/annotations/pdf-annotation-writer.d.ts +0 -20
  89. package/dist/annotations/pdf-annotation-writer.js +0 -76
  90. package/dist/fonts/manager.d.ts +0 -127
  91. package/dist/fonts/manager.js +0 -378
  92. package/dist/utils/predictors.d.ts +0 -113
  93. package/dist/utils/predictors.js +0 -279
@@ -4,17 +4,25 @@ import { PdfObjectReference } from '../core/objects/pdf-object-reference.js';
4
4
  import { PdfArray } from '../core/objects/pdf-array.js';
5
5
  import { PdfNumber } from '../core/objects/pdf-number.js';
6
6
  import { PdfAnnotationFlags } from './pdf-annotation-flags.js';
7
+ import { PdfPage } from '../pdf/pdf-page.js';
7
8
  /**
8
9
  * Base class for all PDF annotations.
9
10
  */
10
11
  export class PdfAnnotation extends PdfIndirectObject {
11
12
  _annotationFlags;
13
+ get flags_() {
14
+ if (!this._annotationFlags) {
15
+ const flagValue = this.content.get('F')?.as(PdfNumber)?.value ?? 0;
16
+ this._annotationFlags = new PdfAnnotationFlags(flagValue);
17
+ this.content.set('F', this._annotationFlags);
18
+ }
19
+ return this._annotationFlags;
20
+ }
12
21
  constructor(options) {
13
22
  super(options?.other ??
14
23
  new PdfIndirectObject({ content: new PdfDictionary() }));
15
- const flagValue = this.content.get('F')?.as(PdfNumber)?.value ?? 0;
16
- this._annotationFlags = new PdfAnnotationFlags(flagValue);
17
- this.content.set('F', this._annotationFlags);
24
+ // Eagerly initialize when constructed normally
25
+ this.flags_;
18
26
  }
19
27
  get rect() {
20
28
  const rectArray = this.content.get('Rect')?.as((PdfArray));
@@ -31,52 +39,52 @@ export class PdfAnnotation extends PdfIndirectObject {
31
39
  this.content.set('Rect', rectArray);
32
40
  }
33
41
  get annotationFlags() {
34
- return this._annotationFlags.annotationFlags;
42
+ return this.flags_.annotationFlags;
35
43
  }
36
44
  set annotationFlags(flags) {
37
- this._annotationFlags.annotationFlags = flags;
45
+ this.flags_.annotationFlags = flags;
38
46
  }
39
47
  get invisible() {
40
- return this._annotationFlags.invisible;
48
+ return this.flags_.invisible;
41
49
  }
42
50
  set invisible(value) {
43
- this._annotationFlags.invisible = value;
51
+ this.flags_.invisible = value;
44
52
  }
45
53
  get hidden() {
46
- return this._annotationFlags.hidden;
54
+ return this.flags_.hidden;
47
55
  }
48
56
  set hidden(value) {
49
- this._annotationFlags.hidden = value;
57
+ this.flags_.hidden = value;
50
58
  }
51
59
  get print() {
52
- return this._annotationFlags.print;
60
+ return this.flags_.print;
53
61
  }
54
62
  set print(value) {
55
- this._annotationFlags.print = value;
63
+ this.flags_.print = value;
56
64
  }
57
65
  get noZoom() {
58
- return this._annotationFlags.noZoom;
66
+ return this.flags_.noZoom;
59
67
  }
60
68
  set noZoom(value) {
61
- this._annotationFlags.noZoom = value;
69
+ this.flags_.noZoom = value;
62
70
  }
63
71
  get noRotate() {
64
- return this._annotationFlags.noRotate;
72
+ return this.flags_.noRotate;
65
73
  }
66
74
  set noRotate(value) {
67
- this._annotationFlags.noRotate = value;
75
+ this.flags_.noRotate = value;
68
76
  }
69
77
  get noView() {
70
- return this._annotationFlags.noView;
78
+ return this.flags_.noView;
71
79
  }
72
80
  set noView(value) {
73
- this._annotationFlags.noView = value;
81
+ this.flags_.noView = value;
74
82
  }
75
83
  get locked() {
76
- return this._annotationFlags.locked;
84
+ return this.flags_.locked;
77
85
  }
78
86
  set locked(value) {
79
- this._annotationFlags.locked = value;
87
+ this.flags_.locked = value;
80
88
  }
81
89
  get appearanceStreamDict() {
82
90
  const apDict = this.content.get('AP')?.as(PdfDictionary);
@@ -103,4 +111,7 @@ export class PdfAnnotation extends PdfIndirectObject {
103
111
  this.content.set('P', ref);
104
112
  }
105
113
  }
114
+ get page() {
115
+ return this.parentRef?.resolve(PdfPage) ?? null;
116
+ }
106
117
  }
@@ -0,0 +1,11 @@
1
+ import { PdfArray, PdfDictionary } from '../core';
2
+ export declare class PdfDefaultResourcesDictionary extends PdfDictionary<{
3
+ Font?: PdfDictionary;
4
+ ProcSet?: PdfArray;
5
+ ExtGState?: PdfDictionary;
6
+ ColorSpace?: PdfDictionary;
7
+ Pattern?: PdfDictionary;
8
+ Shading?: PdfDictionary;
9
+ XObject?: PdfDictionary;
10
+ }> {
11
+ }
@@ -0,0 +1,3 @@
1
+ import { PdfDictionary } from '../core';
2
+ export class PdfDefaultResourcesDictionary extends PdfDictionary {
3
+ }
@@ -286,7 +286,7 @@ export class PdfDecoder extends IncrementalParser {
286
286
  throw new Error('Trailer token missing byte offset');
287
287
  }
288
288
  trailer.offset.update(trailerToken.byteOffset);
289
- trailer.offset.isModified = false;
289
+ trailer.offset.modified = false;
290
290
  trailer.preTokens = preTokens;
291
291
  trailer.postTokens = postTokens;
292
292
  return trailer;
@@ -1,13 +1,20 @@
1
+ import { PdfObjectReference } from '../index.js';
1
2
  import { PdfWhitespaceToken } from '../tokens/whitespace-token.js';
3
+ import { PdfIndirectObject } from './pdf-indirect-object.js';
2
4
  import { PdfObject } from './pdf-object.js';
3
- export declare class PdfArray<T extends PdfObject = PdfObject> extends PdfObject {
5
+ export declare class PdfArray<T extends PdfObject = PdfObject> extends PdfObject implements Iterable<T> {
4
6
  items: T[];
5
7
  innerTokens: PdfWhitespaceToken[];
6
8
  constructor(items?: T[]);
9
+ static refs(items: PdfIndirectObject[]): PdfArray<PdfObjectReference>;
7
10
  get length(): number;
8
11
  push(item: T): void;
12
+ get isTrailingDelimited(): boolean;
9
13
  protected tokenize(): import("../index.js").PdfToken[];
10
14
  cloneImpl(): this;
15
+ setModified(modified?: boolean): void;
11
16
  isModified(): boolean;
12
17
  setImmutable(immutable?: boolean): void;
18
+ refs(): PdfArray<PdfObjectReference>;
19
+ [Symbol.iterator](): Iterator<T>;
13
20
  }
@@ -1,6 +1,8 @@
1
+ import { needsCentralWhitespace } from '../../utils/needsCentralWhitespace.js';
1
2
  import { PdfEndArrayToken } from '../tokens/end-array-token.js';
2
3
  import { PdfStartArrayToken } from '../tokens/start-array-token.js';
3
4
  import { PdfWhitespaceToken } from '../tokens/whitespace-token.js';
5
+ import { PdfIndirectObject } from './pdf-indirect-object.js';
4
6
  import { PdfObject } from './pdf-object.js';
5
7
  export class PdfArray extends PdfObject {
6
8
  items;
@@ -9,12 +11,18 @@ export class PdfArray extends PdfObject {
9
11
  super();
10
12
  this.items = items;
11
13
  }
14
+ static refs(items) {
15
+ return new PdfArray(items.map((item) => item.reference));
16
+ }
12
17
  get length() {
13
18
  return this.items.length;
14
19
  }
15
20
  push(item) {
16
21
  this.items.push(item);
17
22
  }
23
+ get isTrailingDelimited() {
24
+ return true;
25
+ }
18
26
  tokenize() {
19
27
  const items = this.items.flatMap((item, index) => {
20
28
  const tokens = item.toTokens();
@@ -24,6 +32,11 @@ export class PdfArray extends PdfObject {
24
32
  ? [PdfWhitespaceToken.SPACE]
25
33
  : [];
26
34
  const postTokens = item.postTokens ? [] : [PdfWhitespaceToken.SPACE];
35
+ if (index !== this.items.length - 1 &&
36
+ postTokens.length === 0 &&
37
+ needsCentralWhitespace(item, this.items[index + 1])) {
38
+ postTokens.push(PdfWhitespaceToken.SPACE);
39
+ }
27
40
  return [...preTokens, ...tokens, ...postTokens];
28
41
  });
29
42
  return [
@@ -37,6 +50,10 @@ export class PdfArray extends PdfObject {
37
50
  const cloned = new PdfArray(this.items.map((x) => x.clone()));
38
51
  return cloned;
39
52
  }
53
+ setModified(modified) {
54
+ super.setModified(modified);
55
+ this.items.forEach((item) => item.setModified(modified));
56
+ }
40
57
  isModified() {
41
58
  return (super.isModified() || this.items.some((item) => item.isModified()));
42
59
  }
@@ -44,4 +61,18 @@ export class PdfArray extends PdfObject {
44
61
  super.setImmutable(immutable);
45
62
  this.items.forEach((item) => item.setImmutable(immutable));
46
63
  }
64
+ refs() {
65
+ const refs = this.items.map((item) => {
66
+ if (item instanceof PdfIndirectObject) {
67
+ return item.reference;
68
+ }
69
+ else {
70
+ throw new Error('Cannot get reference of non-indirect object in array');
71
+ }
72
+ });
73
+ return new PdfArray(refs);
74
+ }
75
+ [Symbol.iterator]() {
76
+ return this.items[Symbol.iterator]();
77
+ }
47
78
  }
@@ -20,9 +20,11 @@ export declare class PdfDictionary<T extends PdfDictionaryEntries = PdfDictionar
20
20
  * Each entry is a tuple of [key string, value].
21
21
  */
22
22
  entries(): IterableIterator<[string, PdfObject | undefined]>;
23
+ get isTrailingDelimited(): boolean;
23
24
  protected tokenize(): PdfToken[];
24
25
  copyFrom(other: PdfDictionary<any>): void;
25
26
  cloneImpl(): this;
27
+ setModified(modified?: boolean): void;
26
28
  isModified(): boolean;
27
29
  setImmutable(immutable?: boolean): void;
28
30
  }
@@ -1,3 +1,4 @@
1
+ import { needsCentralWhitespace } from '../../utils/needsCentralWhitespace.js';
1
2
  import { PdfEndDictionaryToken } from '../tokens/end-dictionary-token.js';
2
3
  import { PdfStartDictionaryToken } from '../tokens/start-dictionary-token.js';
3
4
  import { PdfWhitespaceToken } from '../tokens/whitespace-token.js';
@@ -11,7 +12,7 @@ export class PdfDictionary extends PdfObject {
11
12
  this.#entries = entries instanceof Map ? entries : new Map();
12
13
  if (entries) {
13
14
  for (const [key, value] of Object.entries(entries)) {
14
- this.#entries.set(new PdfName(key), value);
15
+ this.set(key, value);
15
16
  }
16
17
  }
17
18
  }
@@ -28,9 +29,6 @@ export class PdfDictionary extends PdfObject {
28
29
  }
29
30
  }
30
31
  set(key, value) {
31
- if (this.isImmutable()) {
32
- throw new Error('Cannot modify an immutable PdfDictionary');
33
- }
34
32
  const currentValue = this.get(key);
35
33
  if (currentValue !== value && !currentValue?.equals(value)) {
36
34
  this.modified = true;
@@ -50,9 +48,6 @@ export class PdfDictionary extends PdfObject {
50
48
  this.#entries.set(new PdfName(key), value);
51
49
  }
52
50
  delete(key) {
53
- if (this.isImmutable()) {
54
- throw new Error('Cannot modify an immutable PdfDictionary');
55
- }
56
51
  if (this.has(key)) {
57
52
  this.modified = true;
58
53
  }
@@ -97,6 +92,9 @@ export class PdfDictionary extends PdfObject {
97
92
  const entries = Array.from(this.#entries.entries()).map(([key, value]) => [key.value, value]);
98
93
  return entries[Symbol.iterator]();
99
94
  }
95
+ get isTrailingDelimited() {
96
+ return true;
97
+ }
100
98
  tokenize() {
101
99
  let index = 0;
102
100
  const entries = Array.from(this.#entries.entries()).flatMap(([key, value]) => {
@@ -114,6 +112,9 @@ export class PdfDictionary extends PdfObject {
114
112
  const postTokens = value.postTokens
115
113
  ? []
116
114
  : [PdfWhitespaceToken.SPACE];
115
+ if (needsCentralWhitespace(key, value)) {
116
+ centralTokens.push(PdfWhitespaceToken.SPACE);
117
+ }
117
118
  index++;
118
119
  return [
119
120
  ...preTokens,
@@ -144,6 +145,12 @@ export class PdfDictionary extends PdfObject {
144
145
  const cloned = new PdfDictionary(clonedEntries);
145
146
  return cloned;
146
147
  }
148
+ setModified(modified) {
149
+ super.setModified(modified);
150
+ for (const value of this.#entries.values()) {
151
+ value?.setModified(modified);
152
+ }
153
+ }
147
154
  isModified() {
148
155
  return (super.isModified() ||
149
156
  Array.from(this.#entries.values()).some((v) => v?.isModified()));
@@ -19,6 +19,7 @@ export declare class PdfHexadecimal extends PdfObject {
19
19
  get bytes(): ByteArray;
20
20
  toHexBytes(): ByteArray;
21
21
  toHexString(): string;
22
+ get isTrailingDelimited(): boolean;
22
23
  protected tokenize(): PdfHexadecimalToken[];
23
24
  cloneImpl(): this;
24
25
  }
@@ -31,9 +31,6 @@ export class PdfHexadecimal extends PdfObject {
31
31
  return this._raw;
32
32
  }
33
33
  set raw(raw) {
34
- if (this.isImmutable()) {
35
- throw new Error('Cannot modify an immutable PdfHexadecimal');
36
- }
37
34
  this.setModified();
38
35
  this._raw = raw;
39
36
  // Clear original bytes when modified
@@ -51,6 +48,9 @@ export class PdfHexadecimal extends PdfObject {
51
48
  toHexString() {
52
49
  return bytesToString(this.toHexBytes());
53
50
  }
51
+ get isTrailingDelimited() {
52
+ return true;
53
+ }
54
54
  tokenize() {
55
55
  return [new PdfHexadecimalToken(this.raw, this._originalBytes)];
56
56
  }
@@ -2,20 +2,25 @@ import { PdfNull } from './pdf-null.js';
2
2
  import { PdfObject } from './pdf-object.js';
3
3
  import { PdfObjectReference } from './pdf-object-reference.js';
4
4
  import { Ref } from '../ref.js';
5
- export declare class PdfIndirectObject<T extends PdfObject = PdfObject> extends PdfObjectReference {
5
+ export type PdfIndirectObjectOptions<T extends PdfObject = PdfObject> = {
6
+ objectNumber?: number;
7
+ generationNumber?: number;
8
+ content?: T;
9
+ offset?: number | Ref<number>;
10
+ encryptable?: boolean;
11
+ compressed?: boolean;
12
+ } | T | PdfIndirectObject | undefined;
13
+ export declare class PdfIndirectObject<T extends PdfObject = PdfObject> extends PdfObject {
6
14
  static readonly MAX_ORDER_INDEX = 2147483647;
15
+ objectNumber: number;
16
+ generationNumber: number;
7
17
  content: T;
8
18
  offset: Ref<number>;
9
19
  encryptable?: boolean;
20
+ compressed?: boolean;
10
21
  orderIndex?: number;
11
- constructor(options?: {
12
- objectNumber?: number;
13
- generationNumber?: number;
14
- content?: T;
15
- offset?: number | Ref<number>;
16
- encryptable?: boolean;
17
- } | T | PdfIndirectObject);
18
- get reference(): PdfObjectReference;
22
+ constructor(options?: PdfIndirectObjectOptions<T>);
23
+ get reference(): PdfObjectReference<this>;
19
24
  isEncryptable(): boolean;
20
25
  static createPlaceholder<T extends PdfObject>(objectNumber?: number, generationNumber?: number, content?: T): PdfIndirectObject<T extends unknown ? PdfNull : T>;
21
26
  inPdf(): boolean;
@@ -24,6 +29,10 @@ export declare class PdfIndirectObject<T extends PdfObject = PdfObject> extends
24
29
  copyFrom(other: PdfIndirectObject): void;
25
30
  cloneImpl(): this;
26
31
  order(): number;
32
+ setModified(modified?: boolean): void;
27
33
  isModified(): boolean;
28
34
  setImmutable(immutable?: boolean): void;
35
+ becomes<T extends PdfIndirectObject>(cls: new (options: PdfIndirectObject) => T): T;
36
+ resolve<T extends PdfIndirectObject>(cls?: new (options: PdfIndirectObject) => T): T;
37
+ get key(): string;
29
38
  }
@@ -7,46 +7,68 @@ import { PdfObjectReference } from './pdf-object-reference.js';
7
7
  import { PdfStream } from './pdf-stream.js';
8
8
  import { Ref } from '../ref.js';
9
9
  import { PdfByteOffsetToken } from '../tokens/byte-offset-token.js';
10
- export class PdfIndirectObject extends PdfObjectReference {
10
+ export class PdfIndirectObject extends PdfObject {
11
11
  static MAX_ORDER_INDEX = 2147483647;
12
+ objectNumber;
13
+ generationNumber;
12
14
  content;
13
15
  offset;
14
16
  encryptable;
17
+ compressed;
15
18
  orderIndex;
16
19
  constructor(options) {
17
20
  if (options instanceof PdfIndirectObject) {
18
- super(options.objectNumber, options.generationNumber);
19
- this.content = options.content.clone();
20
- this.offset = options.offset.clone();
21
+ super();
22
+ this.objectNumber = options.objectNumber;
23
+ this.generationNumber = options.generationNumber;
24
+ this.content = options.content;
25
+ this.offset = options.offset;
26
+ this.compressed = options.compressed;
21
27
  return;
22
28
  }
23
29
  if (options instanceof PdfObject) {
24
- super(-1, 0);
30
+ super();
31
+ this.objectNumber = -1;
32
+ this.generationNumber = 0;
25
33
  this.content = options;
26
34
  this.offset = new Ref(0);
27
35
  return;
28
36
  }
29
- super(options?.objectNumber ?? -1, options?.generationNumber ?? 0);
37
+ super();
38
+ this.objectNumber = options?.objectNumber ?? -1;
39
+ this.generationNumber = options?.generationNumber ?? 0;
30
40
  this.content = options?.content ?? new PdfNull();
31
41
  this.offset =
32
42
  options?.offset instanceof Ref
33
43
  ? options.offset
34
44
  : new Ref(options?.offset ?? 0);
35
45
  this.encryptable = options?.encryptable;
46
+ this.compressed = options?.compressed;
36
47
  }
37
48
  get reference() {
38
- return new Proxy(this, {
39
- get: (target, prop) => {
40
- const value = new PdfObjectReference(target.objectNumber, target.generationNumber);
41
- if (prop === 'objectNumber') {
42
- return target.objectNumber;
49
+ const original = this;
50
+ return new Proxy(new PdfObjectReference(this.objectNumber, this.generationNumber), {
51
+ get: (_target, prop) => {
52
+ // Always read from the live indirect object so objectNumber
53
+ // stays current even after the object is added to a document.
54
+ if (prop === 'resolve') {
55
+ return original.resolve.bind(original);
43
56
  }
44
- else if (prop === 'generationNumber') {
45
- return target.generationNumber;
57
+ else if (prop === 'resolver') {
58
+ // Signal that this proxy reference is resolvable
59
+ // so collectMissingReferences can discover it
60
+ return {
61
+ resolve: () => original,
62
+ };
63
+ }
64
+ else if (prop === 'objectNumber') {
65
+ return original.objectNumber;
46
66
  }
47
- else {
48
- return value[prop];
67
+ else if (prop === 'generationNumber') {
68
+ return original.generationNumber;
49
69
  }
70
+ const value = new PdfObjectReference(original.objectNumber, original.generationNumber);
71
+ return value[prop];
50
72
  },
51
73
  });
52
74
  }
@@ -100,19 +122,56 @@ export class PdfIndirectObject extends PdfObjectReference {
100
122
  generationNumber: this.generationNumber,
101
123
  content: this.content.clone(),
102
124
  offset: this.offset.resolve(),
125
+ encryptable: this.encryptable,
126
+ compressed: this.compressed,
103
127
  });
104
128
  }
105
129
  order() {
106
130
  return this.orderIndex ?? 0;
107
131
  }
132
+ setModified(modified = true) {
133
+ super.setModified(modified);
134
+ this.content.setModified(modified);
135
+ this.offset.setModified(modified);
136
+ }
108
137
  isModified() {
109
138
  return (super.isModified() ||
110
139
  this.content.isModified() ||
111
- this.offset.isModified);
140
+ this.offset.isModified());
112
141
  }
113
142
  setImmutable(immutable) {
114
143
  super.setImmutable(immutable);
115
144
  this.content.setImmutable(immutable);
116
145
  this.offset.setImmutable(immutable);
117
146
  }
147
+ becomes(cls) {
148
+ if (this instanceof cls) {
149
+ return this;
150
+ }
151
+ // Preserve identity-critical properties that subclass constructors
152
+ // may inadvertently reset (e.g. PdfFont's super() creates a fresh
153
+ // PdfIndirectObject with objectNumber = -1, and PdfFormField's
154
+ // super() chain creates a fresh empty PdfDictionary as content).
155
+ const savedObjectNumber = this.objectNumber;
156
+ const savedGenerationNumber = this.generationNumber;
157
+ const savedOffset = this.offset;
158
+ const savedContent = this.content;
159
+ const newObject = new cls(this);
160
+ Object.setPrototypeOf(this, cls.prototype);
161
+ Object.assign(this, newObject);
162
+ this.objectNumber = savedObjectNumber;
163
+ this.generationNumber = savedGenerationNumber;
164
+ this.offset = savedOffset;
165
+ this.content = savedContent;
166
+ return this;
167
+ }
168
+ resolve(cls) {
169
+ if (cls) {
170
+ return this.becomes(cls);
171
+ }
172
+ return this;
173
+ }
174
+ get key() {
175
+ return `${this.objectNumber}/${this.generationNumber}`;
176
+ }
118
177
  }
@@ -18,6 +18,7 @@ export declare class PdfNumber extends PdfObject {
18
18
  toToken(): PdfNumberToken;
19
19
  protected tokenize(): PdfNumberToken[];
20
20
  cloneImpl(): this;
21
+ setModified(modified?: boolean): void;
21
22
  isModified(): boolean;
22
23
  }
23
24
  export declare class PdfByteOffsetNumber extends PdfNumber {
@@ -45,9 +45,6 @@ export class PdfNumber extends PdfObject {
45
45
  return this.#value.resolve();
46
46
  }
47
47
  set value(value) {
48
- if (this.isImmutable()) {
49
- throw new Error('Cannot modify an immutable PdfNumber');
50
- }
51
48
  this.#value.update(value);
52
49
  }
53
50
  onChange(callback) {
@@ -72,8 +69,12 @@ export class PdfNumber extends PdfObject {
72
69
  });
73
70
  return cloned;
74
71
  }
72
+ setModified(modified) {
73
+ super.setModified(modified);
74
+ this.#value.setModified(modified);
75
+ }
75
76
  isModified() {
76
- return super.isModified() || this.#value.isModified;
77
+ return super.isModified() || this.#value.isModified();
77
78
  }
78
79
  }
79
80
  export class PdfByteOffsetNumber extends PdfNumber {
@@ -1,9 +1,16 @@
1
1
  import { PdfToken } from '../tokens/token.js';
2
2
  import { PdfObject } from './pdf-object.js';
3
- export declare class PdfObjectReference extends PdfObject {
3
+ import { PdfIndirectObject } from './pdf-indirect-object.js';
4
+ export interface IPdfObjectResolver {
5
+ resolve(objectNumber: number, generationNumber: number): PdfIndirectObject;
6
+ }
7
+ export declare class PdfObjectReference<T extends PdfIndirectObject = PdfIndirectObject> extends PdfObject {
4
8
  objectNumber: number;
5
9
  generationNumber: number;
10
+ resolver?: IPdfObjectResolver;
6
11
  constructor(objectNumber: number, generationNumber: number);
7
12
  protected tokenize(): PdfToken[];
8
13
  cloneImpl(): this;
14
+ resolve<U extends PdfIndirectObject = T>(cls?: new (options: PdfIndirectObject) => U): U;
15
+ get key(): string;
9
16
  }
@@ -3,6 +3,7 @@ import { PdfObject } from './pdf-object.js';
3
3
  export class PdfObjectReference extends PdfObject {
4
4
  objectNumber;
5
5
  generationNumber;
6
+ resolver;
6
7
  constructor(objectNumber, generationNumber) {
7
8
  super();
8
9
  this.objectNumber = objectNumber;
@@ -17,4 +18,17 @@ export class PdfObjectReference extends PdfObject {
17
18
  const cloned = new PdfObjectReference(this.objectNumber, this.generationNumber);
18
19
  return cloned;
19
20
  }
21
+ resolve(cls) {
22
+ if (!this.resolver) {
23
+ throw new Error(`No resolver set for PdfObjectReference '${this.objectNumber} ${this.generationNumber}'`);
24
+ }
25
+ const object = this.resolver.resolve(this.objectNumber, this.generationNumber);
26
+ if (cls) {
27
+ return object.becomes(cls);
28
+ }
29
+ return object;
30
+ }
31
+ get key() {
32
+ return `${this.objectNumber}/${this.generationNumber}`;
33
+ }
20
34
  }
@@ -11,8 +11,16 @@ export declare abstract class PdfObject {
11
11
  protected immutable: boolean;
12
12
  /** Tokenizes the object into an array of PdfTokens */
13
13
  protected abstract tokenize(): PdfToken[];
14
+ /** Cached byte representation of the object, if available */
15
+ protected cachedTokens?: PdfToken[];
14
16
  /** The type of this PDF object */
15
17
  get objectType(): string;
18
+ /**
19
+ * Returns true if this object's serialized form ends with a self-delimiting
20
+ * character (e.g., `)`, `>`, `]`, `>>`). Such objects do not require trailing
21
+ * whitespace before the next token.
22
+ */
23
+ get isTrailingDelimited(): boolean;
16
24
  /** Indicates whether the object has been modified. Override this method if the modified state is determined differently */
17
25
  isModified(): boolean;
18
26
  /** Sets the modified state of the object. Override this method if the modified state is determined differently */
@@ -35,4 +43,10 @@ export declare abstract class PdfObject {
35
43
  clone(): this;
36
44
  /** Compares this object to another for equality based on their token representations */
37
45
  equals(other?: PdfObject): boolean;
46
+ /**
47
+ * Serializes the document to a Base64-encoded string.
48
+ *
49
+ * @returns A promise that resolves to the PDF document as a Base64 string
50
+ */
51
+ toBase64(): string;
38
52
  }