modern-pdf-lib 0.25.0 → 0.26.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 (69) hide show
  1. package/README.md +1 -1
  2. package/dist/{batchOptimize-DtRwBOqR.mjs → batchOptimize-BCJEEN8J.mjs} +4 -4
  3. package/dist/{batchOptimize-Ba_pWw71.cjs → batchOptimize-C1W3O68Q.cjs} +3 -3
  4. package/dist/{bridge-DYCQzxF7.cjs → bridge-DMEuGtfn.cjs} +2 -2
  5. package/dist/{bridge-CcivG_Sm.mjs → bridge-DaS-gzEd.mjs} +3 -3
  6. package/dist/browser.cjs +31 -10
  7. package/dist/browser.d.cts +5 -5
  8. package/dist/browser.d.mts +5 -5
  9. package/dist/browser.mjs +12 -12
  10. package/dist/cli/index.cjs +2 -2
  11. package/dist/cli/index.mjs +3 -3
  12. package/dist/{compressionAnalysis-B84FPXaQ.cjs → compressionAnalysis-B-FPzgzw.cjs} +7 -7
  13. package/dist/{compressionAnalysis-DGs-MqTe.d.mts → compressionAnalysis-Ch7t-HXn.d.mts} +2 -2
  14. package/dist/{compressionAnalysis-DGs-MqTe.d.mts.map → compressionAnalysis-Ch7t-HXn.d.mts.map} +1 -1
  15. package/dist/{compressionAnalysis-odbHC7Uk.mjs → compressionAnalysis-CwknBtqx.mjs} +7 -7
  16. package/dist/{compressionAnalysis-VtYV9Zmq.d.cts → compressionAnalysis-Dgv1TtHJ.d.cts} +2 -2
  17. package/dist/{compressionAnalysis-VtYV9Zmq.d.cts.map → compressionAnalysis-Dgv1TtHJ.d.cts.map} +1 -1
  18. package/dist/create.cjs +3 -3
  19. package/dist/create.d.cts +2 -2
  20. package/dist/create.d.mts +2 -2
  21. package/dist/create.mjs +3 -3
  22. package/dist/{deduplicateImages-MfUDPxQz.mjs → deduplicateImages-DIon68zB.mjs} +2 -2
  23. package/dist/{fflateAdapter-PSiW_ML7.mjs → fflateAdapter-DuNiByKx.mjs} +2 -2
  24. package/dist/{fontEmbed-BN842wlb.d.cts → fontEmbed-3YhUPLFj.d.cts} +2 -2
  25. package/dist/{fontEmbed-BN842wlb.d.cts.map → fontEmbed-3YhUPLFj.d.cts.map} +1 -1
  26. package/dist/{fontEmbed-Dgq5K89o.d.mts → fontEmbed-DlVnVCZU.d.mts} +2 -2
  27. package/dist/{fontEmbed-Dgq5K89o.d.mts.map → fontEmbed-DlVnVCZU.d.mts.map} +1 -1
  28. package/dist/{fontSubset-D-vQQems.mjs → fontSubset-BGFDIMmT.mjs} +2 -2
  29. package/dist/forms.cjs +1 -1
  30. package/dist/forms.mjs +1 -1
  31. package/dist/{index-DCSbmXWh.d.mts → index-B4S61WjK.d.mts} +589 -21
  32. package/dist/index-B4S61WjK.d.mts.map +1 -0
  33. package/dist/{index-J1W3FdL8.d.cts → index-xfJP6Ycm.d.cts} +589 -21
  34. package/dist/index-xfJP6Ycm.d.cts.map +1 -0
  35. package/dist/index.cjs +31 -10
  36. package/dist/index.d.cts +5 -5
  37. package/dist/index.d.mts +5 -5
  38. package/dist/index.mjs +12 -12
  39. package/dist/{layout-D6EUKSP8.mjs → layout-CrqeJBMI.mjs} +3 -3
  40. package/dist/{layout-DH61a1iR.cjs → layout-DQh05VP-.cjs} +3 -3
  41. package/dist/{libdeflateWasm-8b91Vmia.mjs → libdeflateWasm-CcA1W04G.mjs} +3 -3
  42. package/dist/{libdeflateWasm-BdiDEJOj.cjs → libdeflateWasm-DLw-I1CY.cjs} +2 -2
  43. package/dist/{loader-C7B5dVCI.mjs → loader-CVB-c_3Z.mjs} +16 -6
  44. package/dist/{loader-I4zdkoWc.cjs → loader-DYCH3n7d.cjs} +15 -5
  45. package/dist/parse.cjs +2 -2
  46. package/dist/parse.d.cts +2 -2
  47. package/dist/parse.d.mts +2 -2
  48. package/dist/parse.mjs +2 -2
  49. package/dist/{pdfCatalog-CYy4NXEY.cjs → pdfCatalog-Bqq4FiLn.cjs} +2 -1
  50. package/dist/{pdfCatalog-3yMIhJtt.mjs → pdfCatalog-CnKMAtIo.mjs} +3 -2
  51. package/dist/{pdfDocument-CbU-2TjT.d.cts → pdfDocument-Bc_vAO74.d.cts} +257 -172
  52. package/dist/pdfDocument-Bc_vAO74.d.cts.map +1 -0
  53. package/dist/{pdfDocument-BgvEP5Po.d.mts → pdfDocument-Bi-NoyXv.d.mts} +257 -172
  54. package/dist/pdfDocument-Bi-NoyXv.d.mts.map +1 -0
  55. package/dist/{pdfDocument-B0_XwS4X.mjs → pdfDocument-D7aFSQEY.mjs} +219 -40
  56. package/dist/{pdfDocument-CEbbUP9i.cjs → pdfDocument-D9uYNSb-.cjs} +233 -36
  57. package/dist/{pdfForm-9gd40uz9.cjs → pdfForm-BpqDGp29.cjs} +7 -1
  58. package/dist/{pdfForm-Cn-cVicP.mjs → pdfForm-C3mC9FoQ.mjs} +2 -2
  59. package/dist/{pdfPage-B_d9HmkG.mjs → pdfPage-BJIE5hc6.mjs} +189 -24
  60. package/dist/{pdfPage-Cd8jOJp6.cjs → pdfPage-C_tjEjj1.cjs} +188 -23
  61. package/dist/{pngEmbed-BWAbEUKF.mjs → pngEmbed-CGi7cym7.mjs} +3 -3
  62. package/dist/{pngEmbed-D4X4ZN-3.cjs → pngEmbed-CTn9IeNB.cjs} +2 -2
  63. package/dist/{src-Db6Qknoz.mjs → src-QZWP21qF.mjs} +1738 -157
  64. package/dist/{src-B1iDGLCL.cjs → src-lFqJHb1C.cjs} +1874 -185
  65. package/package.json +2 -1
  66. package/dist/index-DCSbmXWh.d.mts.map +0 -1
  67. package/dist/index-J1W3FdL8.d.cts.map +0 -1
  68. package/dist/pdfDocument-BgvEP5Po.d.mts.map +0 -1
  69. package/dist/pdfDocument-CbU-2TjT.d.cts.map +0 -1
@@ -1,11 +1,11 @@
1
- import { m as applyRedactions, n as PdfPage, t as PageSizes, v as PdfLayerManager, x as drawSvgOnPage } from "./pdfPage-B_d9HmkG.mjs";
1
+ import { m as applyRedactions, n as PdfPage, t as PageSizes, v as PdfLayerManager, x as drawSvgOnPage } from "./pdfPage-BJIE5hc6.mjs";
2
2
  import { a as PdfNull, c as PdfRef, i as PdfName, l as PdfStream, n as PdfBool, o as PdfNumber, r as PdfDict, s as PdfObjectRegistry, t as PdfArray, u as PdfString } from "./pdfObjects-uEsWlfzU.mjs";
3
- import { a as formatPdfDate$1, n as buildDocumentStructure } from "./pdfCatalog-3yMIhJtt.mjs";
4
- import { n as isAvailable, t as deflateSync$1 } from "./libdeflateWasm-8b91Vmia.mjs";
5
- import { i as subsetFont, n as computeSubsetTag, t as buildSubsetCmap } from "./fontSubset-D-vQQems.mjs";
6
- import { t as embedPng } from "./pngEmbed-BWAbEUKF.mjs";
7
- import { t as decompressSync } from "./fflateAdapter-PSiW_ML7.mjs";
8
- import { t as PdfForm } from "./pdfForm-Cn-cVicP.mjs";
3
+ import { a as formatPdfDate$1, n as buildDocumentStructure } from "./pdfCatalog-CnKMAtIo.mjs";
4
+ import { n as isAvailable, t as deflateSync$1 } from "./libdeflateWasm-CcA1W04G.mjs";
5
+ import { i as subsetFont, n as computeSubsetTag, t as buildSubsetCmap } from "./fontSubset-BGFDIMmT.mjs";
6
+ import { t as embedPng } from "./pngEmbed-CGi7cym7.mjs";
7
+ import { t as decompressSync } from "./fflateAdapter-DuNiByKx.mjs";
8
+ import { t as PdfForm } from "./pdfForm-C3mC9FoQ.mjs";
9
9
  import { n as getStreamFilters, t as decodeStream$1 } from "./streamDecode-Bj568Nc9.mjs";
10
10
  import { deflateSync, inflateSync } from "fflate";
11
11
 
@@ -15,16 +15,17 @@ import { deflateSync, inflateSync } from "fflate";
15
15
  *
16
16
  * Binary serialization of a PDF document to a single `Uint8Array`.
17
17
  *
18
- * Produces a valid PDF 1.7 file:
18
+ * Produces a valid PDF 1.7 (or 2.0 when encryption V=5) file:
19
19
  *
20
- * 1. `%PDF-1.7` header + binary comment
21
- * 2. Indirect-object bodies
20
+ * 1. `%PDF-1.7` (or `%PDF-2.0`) header + binary comment
21
+ * 2. Indirect-object bodies (optionally encrypted)
22
22
  * 3. Cross-reference table
23
- * 4. Trailer dictionary (`/Size`, `/Root`, `/Info`)
23
+ * 4. Trailer dictionary (`/Size`, `/Root`, `/Info`, `/Encrypt`, `/ID`)
24
24
  * 5. `startxref` pointer
25
25
  * 6. `%%EOF`
26
26
  *
27
- * Supports optional FlateDecode compression for streams via `fflate`.
27
+ * Supports optional FlateDecode compression for streams via `fflate`
28
+ * and optional encryption via a {@link PdfEncryptionHandler}.
28
29
  */
29
30
  /**
30
31
  * Growable byte buffer used during serialization. All writes go
@@ -74,32 +75,48 @@ var PdfWriter = class {
74
75
  compressionLevel;
75
76
  useWasm;
76
77
  objectStreamThreshold;
77
- constructor(registry, structure, options) {
78
+ encryptionHandler;
79
+ /**
80
+ * When encryption is active, the /Encrypt dict is registered as an
81
+ * indirect object. Its reference is stored here for the trailer.
82
+ */
83
+ encryptDictRef;
84
+ constructor(registry, structure, options, encryptionHandler) {
78
85
  this.registry = registry;
79
86
  this.structure = structure;
80
87
  this.compress = options?.compress ?? true;
81
88
  this.compressionLevel = options?.compressionLevel ?? 6;
82
89
  this.useWasm = options?.useWasm ?? false;
83
90
  this.objectStreamThreshold = options?.objectStreamThreshold ?? Infinity;
91
+ this.encryptionHandler = encryptionHandler;
84
92
  }
85
93
  /**
86
94
  * Produce the complete PDF file as a `Uint8Array`.
95
+ *
96
+ * When an encryption handler is present, all string and stream
97
+ * objects are encrypted and the /Encrypt dictionary + /ID array
98
+ * are added to the trailer.
87
99
  */
88
- write() {
100
+ async write() {
101
+ if (this.encryptionHandler) {
102
+ const encDict = this.encryptionHandler.buildEncryptDict();
103
+ this.encryptDictRef = this.registry.register(encDict);
104
+ }
89
105
  this.writeHeader();
90
106
  if (this.objectStreamThreshold !== Infinity) {
91
- if (this.writeBodyWithObjectStreams(this.objectStreamThreshold)) return this.buf.toUint8Array();
107
+ if (await this.writeBodyWithObjectStreams(this.objectStreamThreshold)) return this.buf.toUint8Array();
92
108
  const xrefOffset = this.writeXref();
93
109
  this.writeTrailer(xrefOffset);
94
110
  } else {
95
- this.writeBody();
111
+ await this.writeBody();
96
112
  const xrefOffset = this.writeXref();
97
113
  this.writeTrailer(xrefOffset);
98
114
  }
99
115
  return this.buf.toUint8Array();
100
116
  }
101
117
  writeHeader() {
102
- this.buf.writeString("%PDF-1.7\n");
118
+ const version = this.encryptionHandler && this.encryptionHandler.getVersion() === 5 ? "2.0" : "1.7";
119
+ this.buf.writeString(`%PDF-${version}\n`);
103
120
  this.buf.write(new Uint8Array([
104
121
  37,
105
122
  226,
@@ -109,11 +126,13 @@ var PdfWriter = class {
109
126
  10
110
127
  ]));
111
128
  }
112
- writeBody() {
113
- for (const entry of this.registry) this.writeIndirectObject(entry);
129
+ async writeBody() {
130
+ for (const entry of this.registry) await this.writeIndirectObject(entry);
114
131
  }
115
- writeIndirectObject(entry) {
132
+ async writeIndirectObject(entry) {
116
133
  if (this.compress && entry.object.kind === "stream") this.compressStream(entry.object);
134
+ const isEncryptDict = this.encryptDictRef && entry.ref.objectNumber === this.encryptDictRef.objectNumber;
135
+ if (this.encryptionHandler && !isEncryptDict) await this.encryptEntry(entry);
117
136
  const objNum = entry.ref.objectNumber;
118
137
  while (this.xrefOffsets.length <= objNum) this.xrefOffsets.push(0);
119
138
  this.xrefOffsets[objNum] = this.buf.offset;
@@ -122,6 +141,50 @@ var PdfWriter = class {
122
141
  this.buf.writeString(`\n${entry.ref.toObjectFooter()}\n`);
123
142
  }
124
143
  /**
144
+ * Encrypt all encryptable data within an indirect object.
145
+ *
146
+ * Per the PDF spec:
147
+ * - Strings inside the object are encrypted with the per-object key.
148
+ * - Stream data is encrypted with the per-object key.
149
+ * - The /Encrypt dictionary itself is never encrypted.
150
+ * - String values in the trailer /ID array are never encrypted.
151
+ */
152
+ async encryptEntry(entry) {
153
+ const handler = this.encryptionHandler;
154
+ const objNum = entry.ref.objectNumber;
155
+ const genNum = entry.ref.generationNumber;
156
+ if (entry.object.kind === "stream") {
157
+ const stream = entry.object;
158
+ await this.encryptDictStrings(stream.dict, objNum, genNum);
159
+ stream.data = await handler.encryptObject(objNum, genNum, stream.data);
160
+ stream.syncLength();
161
+ } else if (entry.object.kind === "dict") await this.encryptDictStrings(entry.object, objNum, genNum);
162
+ }
163
+ /**
164
+ * Recursively encrypt all PdfString values inside a PdfDict.
165
+ */
166
+ async encryptDictStrings(dict, objNum, genNum) {
167
+ const handler = this.encryptionHandler;
168
+ for (const [key, value] of dict) if (value.kind === "string") {
169
+ const encrypted = await handler.encryptString(objNum, genNum, value);
170
+ dict.set(key, encrypted);
171
+ } else if (value.kind === "dict") await this.encryptDictStrings(value, objNum, genNum);
172
+ else if (value.kind === "array") await this.encryptArrayStrings(value, objNum, genNum);
173
+ }
174
+ /**
175
+ * Recursively encrypt all PdfString values inside a PdfArray.
176
+ */
177
+ async encryptArrayStrings(arr, objNum, genNum) {
178
+ const handler = this.encryptionHandler;
179
+ const items = arr.items;
180
+ for (let i = 0; i < items.length; i++) {
181
+ const item = items[i];
182
+ if (item.kind === "string") items[i] = await handler.encryptString(objNum, genNum, item);
183
+ else if (item.kind === "dict") await this.encryptDictStrings(item, objNum, genNum);
184
+ else if (item.kind === "array") await this.encryptArrayStrings(item, objNum, genNum);
185
+ }
186
+ }
187
+ /**
125
188
  * Apply FlateDecode compression to a stream's data if it is not
126
189
  * already compressed.
127
190
  */
@@ -159,7 +222,7 @@ var PdfWriter = class {
159
222
  * written in traditional format and the caller must still
160
223
  * emit the classic xref table and trailer.
161
224
  */
162
- writeBodyWithObjectStreams(threshold) {
225
+ async writeBodyWithObjectStreams(threshold) {
163
226
  const protectedNums = this.protectedObjectNumbers();
164
227
  const streamEntries = [];
165
228
  const protectedEntries = [];
@@ -168,11 +231,11 @@ var PdfWriter = class {
168
231
  else if (protectedNums.has(entry.ref.objectNumber)) protectedEntries.push(entry);
169
232
  else packableEntries.push(entry);
170
233
  if (packableEntries.length < threshold) {
171
- this.writeBody();
234
+ await this.writeBody();
172
235
  return false;
173
236
  }
174
- for (const entry of streamEntries) this.writeIndirectObject(entry);
175
- for (const entry of protectedEntries) this.writeIndirectObject(entry);
237
+ for (const entry of streamEntries) await this.writeIndirectObject(entry);
238
+ for (const entry of protectedEntries) await this.writeIndirectObject(entry);
176
239
  const OBJS_PER_STREAM = 200;
177
240
  const xrefEntries = /* @__PURE__ */ new Map();
178
241
  for (let i = 0; i < this.xrefOffsets.length; i++) {
@@ -361,6 +424,11 @@ var PdfWriter = class {
361
424
  this.buf.writeString(`/Size ${size}\n`);
362
425
  this.buf.writeString(`/Root ${this.structure.catalogRef.objectNumber} ${this.structure.catalogRef.generationNumber} R\n`);
363
426
  this.buf.writeString(`/Info ${this.structure.infoRef.objectNumber} ${this.structure.infoRef.generationNumber} R\n`);
427
+ if (this.encryptionHandler && this.encryptDictRef) {
428
+ this.buf.writeString(`/Encrypt ${this.encryptDictRef.objectNumber} ${this.encryptDictRef.generationNumber} R\n`);
429
+ const fileIdHex = this.encryptionHandler.getFileId().toHex();
430
+ this.buf.writeString(`/ID [<${fileIdHex}> <${fileIdHex}>]\n`);
431
+ }
364
432
  this.buf.writeString(">>\n");
365
433
  this.buf.writeString("startxref\n");
366
434
  this.buf.writeString(`${xrefOffset}\n`);
@@ -415,13 +483,16 @@ function writeIntBE(buf, offset, width, value) {
415
483
  /**
416
484
  * Serialize a complete PDF from a registry and structure refs.
417
485
  *
418
- * @param registry All registered indirect objects.
419
- * @param structure Catalog / Info / Pages references.
420
- * @param options Save options.
421
- * @returns The raw PDF bytes.
486
+ * @param registry All registered indirect objects.
487
+ * @param structure Catalog / Info / Pages references.
488
+ * @param options Save options.
489
+ * @param encryptionHandler Optional encryption handler for encrypting
490
+ * all objects and adding /Encrypt + /ID to
491
+ * the trailer.
492
+ * @returns The raw PDF bytes.
422
493
  */
423
- function serializePdf(registry, structure, options) {
424
- return new PdfWriter(registry, structure, options).write();
494
+ async function serializePdf(registry, structure, options, encryptionHandler) {
495
+ return new PdfWriter(registry, structure, options, encryptionHandler).write();
425
496
  }
426
497
 
427
498
  //#endregion
@@ -6282,10 +6353,10 @@ async function tryLoadLibdeflate() {
6282
6353
  if (libdeflateAttempted) return libdeflateEngine;
6283
6354
  libdeflateAttempted = true;
6284
6355
  try {
6285
- const { LibdeflateWasm: LibdeflateCtor, initDeflateWasm } = await import("./libdeflateWasm-8b91Vmia.mjs").then((n) => n.r);
6356
+ const { LibdeflateWasm: LibdeflateCtor, initDeflateWasm } = await import("./libdeflateWasm-CcA1W04G.mjs").then((n) => n.r);
6286
6357
  let customBytes;
6287
6358
  try {
6288
- const { getWasmLoaderConfig } = await import("./loader-C7B5dVCI.mjs").then((n) => n.l);
6359
+ const { getWasmLoaderConfig } = await import("./loader-CVB-c_3Z.mjs").then((n) => n.l);
6289
6360
  customBytes = getWasmLoaderConfig().moduleBytes?.["libdeflate"];
6290
6361
  } catch {}
6291
6362
  await initDeflateWasm(customBytes);
@@ -6303,7 +6374,7 @@ async function tryLoadLibdeflate() {
6303
6374
  */
6304
6375
  async function loadFflate() {
6305
6376
  if (fflateEngine) return fflateEngine;
6306
- const { FflateEngine: FflateCtor } = await import("./fflateAdapter-PSiW_ML7.mjs").then((n) => n.n);
6377
+ const { FflateEngine: FflateCtor } = await import("./fflateAdapter-DuNiByKx.mjs").then((n) => n.n);
6307
6378
  fflateEngine = new FflateCtor();
6308
6379
  return fflateEngine;
6309
6380
  }
@@ -9342,7 +9413,7 @@ var PdfDocumentParser = class {
9342
9413
  for (let i = 0; i + 1 < headerTokens.length && objEntries.length < n; i += 2) {
9343
9414
  const objNum = parseInt(headerTokens[i], 10);
9344
9415
  const offset = parseInt(headerTokens[i + 1], 10);
9345
- if (!isNaN(objNum) && !isNaN(offset)) objEntries.push({
9416
+ if (!Number.isNaN(objNum) && !Number.isNaN(offset)) objEntries.push({
9346
9417
  objNum,
9347
9418
  offset
9348
9419
  });
@@ -9624,7 +9695,7 @@ var PdfDocumentParser = class {
9624
9695
  const name = key.startsWith("/") ? key.slice(1) : key;
9625
9696
  if (name.startsWith(prefix)) {
9626
9697
  const num = parseInt(name.slice(prefix.length), 10);
9627
- return isNaN(num) ? 0 : num;
9698
+ return Number.isNaN(num) ? 0 : num;
9628
9699
  }
9629
9700
  return 0;
9630
9701
  }).reduce((max, n) => Math.max(max, n), 0);
@@ -10338,12 +10409,12 @@ function parseXmpMetadata(xmpString) {
10338
10409
  const createDate = extractSimpleValue(xmpString, "xmp:CreateDate");
10339
10410
  if (createDate !== void 0) {
10340
10411
  const parsed = new Date(createDate);
10341
- if (!isNaN(parsed.getTime())) result.creationDate = parsed;
10412
+ if (!Number.isNaN(parsed.getTime())) result.creationDate = parsed;
10342
10413
  }
10343
10414
  const modifyDate = extractSimpleValue(xmpString, "xmp:ModifyDate");
10344
10415
  if (modifyDate !== void 0) {
10345
10416
  const parsed = new Date(modifyDate);
10346
- if (!isNaN(parsed.getTime())) result.modDate = parsed;
10417
+ if (!Number.isNaN(parsed.getTime())) result.modDate = parsed;
10347
10418
  }
10348
10419
  return result;
10349
10420
  }
@@ -13593,6 +13664,99 @@ function parseJpegDimensions(data) {
13593
13664
  throw new Error("Invalid JPEG: SOF marker not found");
13594
13665
  }
13595
13666
 
13667
+ //#endregion
13668
+ //#region src/core/pageLabels.ts
13669
+ /** Map from user-facing style names to PDF /S name values. */
13670
+ const styleToPdfName = {
13671
+ decimal: "D",
13672
+ roman: "r",
13673
+ Roman: "R",
13674
+ alpha: "a",
13675
+ Alpha: "A"
13676
+ };
13677
+ /**
13678
+ * Symbol used to store page labels on the PdfDocument instance.
13679
+ * This avoids modifying the PdfDocument class while keeping state
13680
+ * associated with the document.
13681
+ */
13682
+ const PAGE_LABELS_KEY = Symbol.for("modern-pdf-lib:pageLabels");
13683
+ /**
13684
+ * Set the page label ranges for the document.
13685
+ *
13686
+ * Each entry in the `labels` array defines a contiguous range of pages
13687
+ * that share a numbering style. Ranges must be sorted by `startPage`
13688
+ * in ascending order.
13689
+ *
13690
+ * @param doc The document to set page labels on.
13691
+ * @param labels An array of label range definitions.
13692
+ * @throws If `labels` is empty or ranges are not sorted.
13693
+ */
13694
+ function setPageLabels(doc, labels) {
13695
+ if (labels.length === 0) throw new Error("Page labels array must not be empty");
13696
+ for (let i = 1; i < labels.length; i++) if (labels[i].startPage <= labels[i - 1].startPage) throw new Error(`Page label ranges must be sorted by startPage in ascending order. Got startPage ${labels[i].startPage} after ${labels[i - 1].startPage}.`);
13697
+ const store = doc;
13698
+ store[PAGE_LABELS_KEY] = labels.map((r) => ({ ...r }));
13699
+ }
13700
+ /**
13701
+ * Get the current page label ranges for the document.
13702
+ *
13703
+ * Returns `undefined` if no page labels have been set.
13704
+ *
13705
+ * @param doc The document to read page labels from.
13706
+ * @returns The page label ranges, or `undefined`.
13707
+ */
13708
+ function getPageLabels(doc) {
13709
+ const labels = doc[PAGE_LABELS_KEY];
13710
+ if (labels === void 0) return void 0;
13711
+ return labels.map((r) => ({ ...r }));
13712
+ }
13713
+ /**
13714
+ * Remove all page labels from the document.
13715
+ *
13716
+ * @param doc The document to clear page labels from.
13717
+ */
13718
+ function removePageLabels(doc) {
13719
+ const store = doc;
13720
+ store[PAGE_LABELS_KEY] = void 0;
13721
+ }
13722
+ /**
13723
+ * Build the `/PageLabels` number tree dictionary for inclusion in the
13724
+ * document catalog.
13725
+ *
13726
+ * This is called during document serialization (by the save pipeline)
13727
+ * to produce the PDF objects that represent the page label scheme.
13728
+ *
13729
+ * The number tree format (PDF 1.7 §7.9.7) uses a `/Nums` array of
13730
+ * alternating page-index / label-dict pairs:
13731
+ *
13732
+ * ```
13733
+ * /PageLabels << /Nums [
13734
+ * 0 << /S /r >>
13735
+ * 4 << /S /D /St 1 >>
13736
+ * ] >>
13737
+ * ```
13738
+ *
13739
+ * @param doc The document to read page label state from.
13740
+ * @returns The number tree entries as `[pageIndex, labelDict]` pairs,
13741
+ * or `undefined` if no labels are set.
13742
+ *
13743
+ * @internal
13744
+ */
13745
+ function getPageLabelEntries(doc) {
13746
+ return doc[PAGE_LABELS_KEY];
13747
+ }
13748
+ /**
13749
+ * Map a {@link PageLabelStyle} to its PDF `/S` name value.
13750
+ *
13751
+ * @param style The user-facing style name.
13752
+ * @returns The PDF name value (without the leading `/`).
13753
+ *
13754
+ * @internal
13755
+ */
13756
+ function styleToPdf(style) {
13757
+ return styleToPdfName[style];
13758
+ }
13759
+
13596
13760
  //#endregion
13597
13761
  //#region src/core/pdfDocument.ts
13598
13762
  /**
@@ -15189,7 +15353,7 @@ var PdfDocument = class PdfDocument {
15189
15353
  if ((options?.addDefaultPage ?? true) && this.getPageCount() === 0) this.addPage();
15190
15354
  if ((options?.updateFieldAppearances ?? true) && this.form) for (const field of this.form.getFields()) field.generateAppearance();
15191
15355
  const structure = this.buildStructure();
15192
- return serializePdf(this.registry, structure, options);
15356
+ return serializePdf(this.registry, structure, options, this.encryptionHandler);
15193
15357
  }
15194
15358
  /**
15195
15359
  * Serialize the document as a `ReadableStream<Uint8Array>`.
@@ -15365,6 +15529,21 @@ var PdfDocument = class PdfDocument {
15365
15529
  catalogObj.set("/AA", aaDict);
15366
15530
  }
15367
15531
  }
15532
+ const pageLabelRanges = getPageLabelEntries(this);
15533
+ if (pageLabelRanges !== void 0 && pageLabelRanges.length > 0) {
15534
+ const numsArray = new PdfArray();
15535
+ for (const range of pageLabelRanges) {
15536
+ numsArray.push(PdfNumber.of(range.startPage));
15537
+ const labelDict = new PdfDict();
15538
+ labelDict.set("/S", PdfName.of(styleToPdf(range.style)));
15539
+ if (range.prefix !== void 0) labelDict.set("/P", PdfString.literal(range.prefix));
15540
+ if (range.start !== void 0) labelDict.set("/St", PdfNumber.of(range.start));
15541
+ numsArray.push(labelDict);
15542
+ }
15543
+ const pageLabelsDict = new PdfDict();
15544
+ pageLabelsDict.set("/Nums", numsArray);
15545
+ catalogObj.set("/PageLabels", pageLabelsDict);
15546
+ }
15368
15547
  }
15369
15548
  if (this.originalBytes !== void 0) {
15370
15549
  const rootRefs = [structure.catalogRef, structure.infoRef];
@@ -15439,5 +15618,5 @@ function createPdf() {
15439
15618
  }
15440
15619
 
15441
15620
  //#endregion
15442
- export { PdfEncryptionHandler as $, parseDerTlv as A, EmbeddedFont as At, isAccessible as B, encodePrintableString as C, isWebP as Ct, encodeUtf8String as D, getSupportedFormats as Dt, encodeUTCTime as E, getImageFormatName as Et, prepareForSigning as F, buildViewerPreferencesDict as G, PdfStructureElement as H, copyPages as I, createXmpStream as J, parseViewerPreferences as K, mergePdfs as L, computeSignatureHash as M, PdfStreamWriter as Mt, embedSignature as N, PdfWriter as Nt, extractIssuerAndSerial as O, isOpenTypeCFF as Ot, findSignatures as P, serializePdf as Pt, loadPdf as Q, splitPdf as R, encodeOctetString as S, decodeWebP as St, encodeSet as T, detectImageFormat as Tt, PdfStructureTree as U, summarizeIssues as V, PdfViewerPreferences as W, PdfOutlineItem as X, parseXmpMetadata as Y, PdfOutlineTree as Z, detectNamedCurve as _, decodeTiffAll as _t, addWatermark as a, sha512 as at, encodeLength as b, isTiff as bt, buildEmbeddedFilesNameTree as c, aesDecryptCBC as ct, verifySignatures as d, md5 as dt, computeFileEncryptionKey as et, getSignatures as f, base64Decode as ft, detectKeyAlgorithm as g, decodeTiff as gt, decodeOidBytes as h, formatHexContext as ht, embedPageAsFormXObject as i, sha384 as it, toBuffer as j, extractMetrics as jt, getSubtle as k, isTrueType as kt, getAttachments as l, aesEncryptCBC as lt, buildPkcs7Signature as m, PdfParseError as mt, StandardFonts as n, verifyUserPassword as nt, addWatermarkToPage as o, decodePermissions as ot, signPdf as p, base64Encode as pt, buildXmpMetadata as q, createPdf as r, sha256 as rt, attachFile as s, encodePermissions as st, PdfDocument as t, verifyOwnerPassword as tt, verifySignature as u, rc4 as ut, encodeContextTag as v, decodeTiffPage as vt, encodeSequence as w, isWebPLossless as wt, encodeOID as x, parseTiffIfd as xt, encodeInteger as y, getTiffPageCount as yt, checkAccessibility as z };
15443
- //# sourceMappingURL=pdfDocument-B0_XwS4X.mjs.map
15621
+ export { PdfOutlineItem as $, encodeUtf8String as A, getSupportedFormats as At, mergePdfs as B, encodeLength as C, isTiff as Ct, encodeSequence as D, isWebPLossless as Dt, encodePrintableString as E, isWebP as Et, computeSignatureHash as F, PdfStreamWriter as Ft, PdfStructureElement as G, checkAccessibility as H, embedSignature as I, PdfWriter as It, buildViewerPreferencesDict as J, PdfStructureTree as K, findSignatures as L, serializePdf as Lt, getSubtle as M, isTrueType as Mt, parseDerTlv as N, EmbeddedFont as Nt, encodeSet as O, detectImageFormat as Ot, toBuffer as P, extractMetrics as Pt, parseXmpMetadata as Q, prepareForSigning as R, encodeInteger as S, getTiffPageCount as St, encodeOctetString as T, decodeWebP as Tt, isAccessible as U, splitPdf as V, summarizeIssues as W, buildXmpMetadata as X, parseViewerPreferences as Y, createXmpStream as Z, buildPkcs7Signature as _, PdfParseError as _t, removePageLabels as a, verifyUserPassword as at, detectNamedCurve as b, decodeTiffAll as bt, addWatermark as c, sha512 as ct, buildEmbeddedFilesNameTree as d, aesDecryptCBC as dt, PdfOutlineTree as et, getAttachments as f, aesEncryptCBC as ft, signPdf as g, base64Encode as gt, getSignatures as h, base64Decode as ht, getPageLabels as i, verifyOwnerPassword as it, extractIssuerAndSerial as j, isOpenTypeCFF as jt, encodeUTCTime as k, getImageFormatName as kt, addWatermarkToPage as l, decodePermissions as lt, verifySignatures as m, md5 as mt, StandardFonts as n, PdfEncryptionHandler as nt, setPageLabels as o, sha256 as ot, verifySignature as p, rc4 as pt, PdfViewerPreferences as q, createPdf as r, computeFileEncryptionKey as rt, embedPageAsFormXObject as s, sha384 as st, PdfDocument as t, loadPdf as tt, attachFile as u, encodePermissions as ut, decodeOidBytes as v, formatHexContext as vt, encodeOID as w, parseTiffIfd as wt, encodeContextTag as x, decodeTiffPage as xt, detectKeyAlgorithm as y, decodeTiff as yt, copyPages as z };
15622
+ //# sourceMappingURL=pdfDocument-D7aFSQEY.mjs.map