modern-pdf-lib 0.32.0 → 0.34.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 (42) hide show
  1. package/README.md +3 -3
  2. package/dist/browser.cjs +11 -3
  3. package/dist/browser.d.cts +5 -5
  4. package/dist/browser.d.mts +5 -5
  5. package/dist/browser.mjs +4 -4
  6. package/dist/{compressionAnalysis-0m5jJG1_.d.mts → compressionAnalysis-4EW8MJBa.d.mts} +2 -2
  7. package/dist/{compressionAnalysis-0m5jJG1_.d.mts.map → compressionAnalysis-4EW8MJBa.d.mts.map} +1 -1
  8. package/dist/{compressionAnalysis-CSBcmi0_.d.cts → compressionAnalysis-Cz3yWa-O.d.cts} +2 -2
  9. package/dist/{compressionAnalysis-CSBcmi0_.d.cts.map → compressionAnalysis-Cz3yWa-O.d.cts.map} +1 -1
  10. package/dist/create.cjs +2 -2
  11. package/dist/create.d.cts +2 -2
  12. package/dist/create.d.mts +2 -2
  13. package/dist/create.mjs +2 -2
  14. package/dist/{fontEmbed-Bzv89wgp.d.mts → fontEmbed-CTTeV1mZ.d.mts} +2 -2
  15. package/dist/{fontEmbed-Bzv89wgp.d.mts.map → fontEmbed-CTTeV1mZ.d.mts.map} +1 -1
  16. package/dist/{fontEmbed-Dwl1XeEA.d.cts → fontEmbed-DxvWoqOt.d.cts} +2 -2
  17. package/dist/{fontEmbed-Dwl1XeEA.d.cts.map → fontEmbed-DxvWoqOt.d.cts.map} +1 -1
  18. package/dist/{index-Ddc6zdqj.d.mts → index-C240uDcb.d.mts} +232 -45
  19. package/dist/index-C240uDcb.d.mts.map +1 -0
  20. package/dist/{index-JejepHCR.d.cts → index-Z4U1Jx0K.d.cts} +232 -45
  21. package/dist/index-Z4U1Jx0K.d.cts.map +1 -0
  22. package/dist/index.cjs +11 -3
  23. package/dist/index.d.cts +5 -5
  24. package/dist/index.d.mts +5 -5
  25. package/dist/index.mjs +4 -4
  26. package/dist/{layout-BYXpcYtC.cjs → layout-ClbkITM3.cjs} +2 -2
  27. package/dist/{layout-xOcesNCh.mjs → layout-XgQY_Uba.mjs} +2 -2
  28. package/dist/parse.cjs +1 -1
  29. package/dist/parse.d.cts +2 -2
  30. package/dist/parse.d.mts +2 -2
  31. package/dist/parse.mjs +1 -1
  32. package/dist/{pdfDocument-B8tQcZqj.d.cts → pdfDocument-BX5o5hI7.d.cts} +13 -1
  33. package/dist/{pdfDocument-B-8iPl_j.d.mts.map → pdfDocument-BX5o5hI7.d.cts.map} +1 -1
  34. package/dist/{pdfDocument-B-8iPl_j.d.mts → pdfDocument-C7TItmPQ.d.mts} +13 -1
  35. package/dist/{pdfDocument-B8tQcZqj.d.cts.map → pdfDocument-C7TItmPQ.d.mts.map} +1 -1
  36. package/dist/{pdfDocument-Bh4ebDqE.cjs → pdfDocument-Dyj4AmT1.cjs} +358 -21
  37. package/dist/{pdfDocument-Cgkkk8F8.mjs → pdfDocument-EcHxUnR6.mjs} +347 -22
  38. package/dist/{src-DNe0XZhx.mjs → src-CiUkSS81.mjs} +780 -150
  39. package/dist/{src-CeKIKI1W.cjs → src-PxZwqIKQ.cjs} +815 -149
  40. package/package.json +1 -1
  41. package/dist/index-Ddc6zdqj.d.mts.map +0 -1
  42. package/dist/index-JejepHCR.d.cts.map +0 -1
@@ -1,4 +1,4 @@
1
- const require_pdfDocument = require("./pdfDocument-Bh4ebDqE.cjs");
1
+ const require_pdfDocument = require("./pdfDocument-Dyj4AmT1.cjs");
2
2
  const require_pdfObjects = require("./pdfObjects-BcPlSI0a.cjs");
3
3
  const require_streamDecode = require("./streamDecode-kQ-REV7v.cjs");
4
4
  const require_pdfForm = require("./pdfForm-BVS_do95.cjs");
@@ -75,7 +75,7 @@ var ChangeTracker = class {
75
75
  return this.newObjects.union(this.modifiedObjects).size;
76
76
  }
77
77
  };
78
- const encoder$11 = new TextEncoder();
78
+ const encoder$12 = new TextEncoder();
79
79
  /**
80
80
  * Growable byte buffer for building the incremental appendix.
81
81
  */
@@ -90,7 +90,7 @@ var ByteBuffer$1 = class {
90
90
  this._offset += data.length;
91
91
  }
92
92
  writeString(str) {
93
- this.write(encoder$11.encode(str));
93
+ this.write(encoder$12.encode(str));
94
94
  }
95
95
  toUint8Array() {
96
96
  const result = new Uint8Array(this._offset);
@@ -277,7 +277,7 @@ function compressStream(stream, level) {
277
277
  * @returns The incremental save result.
278
278
  */
279
279
  async function saveDocumentIncremental(originalBytes, doc, options) {
280
- const { buildDocumentStructure } = await Promise.resolve().then(() => require("./pdfDocument-Bh4ebDqE.cjs")).then((n) => n.pdfCatalog_exports);
280
+ const { buildDocumentStructure } = await Promise.resolve().then(() => require("./pdfDocument-Dyj4AmT1.cjs")).then((n) => n.pdfCatalog_exports);
281
281
  const registry = doc.getRegistry();
282
282
  const structure = buildDocumentStructure(doc.getInternalPages().map((p) => p.finalize()), {
283
283
  producer: doc.getProducer(),
@@ -546,7 +546,7 @@ const NS_PDFAID = "http://www.aiim.org/pdfa/ns/id/";
546
546
  * Escape special characters for XML text content.
547
547
  * @internal
548
548
  */
549
- function escapeXml$5(str) {
549
+ function escapeXml$6(str) {
550
550
  const parts = [];
551
551
  for (let i = 0; i < str.length; i++) {
552
552
  const c = str.charCodeAt(i);
@@ -594,14 +594,14 @@ function buildXmpMetadata(meta) {
594
594
  if (meta.title !== void 0) {
595
595
  lines.push(" <dc:title>");
596
596
  lines.push(" <rdf:Alt>");
597
- lines.push(` <rdf:li xml:lang="x-default">${escapeXml$5(meta.title)}</rdf:li>`);
597
+ lines.push(` <rdf:li xml:lang="x-default">${escapeXml$6(meta.title)}</rdf:li>`);
598
598
  lines.push(" </rdf:Alt>");
599
599
  lines.push(" </dc:title>");
600
600
  }
601
601
  if (meta.author !== void 0) {
602
602
  lines.push(" <dc:creator>");
603
603
  lines.push(" <rdf:Seq>");
604
- lines.push(` <rdf:li>${escapeXml$5(meta.author)}</rdf:li>`);
604
+ lines.push(` <rdf:li>${escapeXml$6(meta.author)}</rdf:li>`);
605
605
  lines.push(" </rdf:Seq>");
606
606
  lines.push(" </dc:creator>");
607
607
  }
@@ -611,7 +611,7 @@ function buildXmpMetadata(meta) {
611
611
  lines.push(" <rdf:Bag>");
612
612
  for (const kw of keywords) {
613
613
  const trimmed = kw.trim();
614
- if (trimmed.length > 0) lines.push(` <rdf:li>${escapeXml$5(trimmed)}</rdf:li>`);
614
+ if (trimmed.length > 0) lines.push(` <rdf:li>${escapeXml$6(trimmed)}</rdf:li>`);
615
615
  }
616
616
  lines.push(" </rdf:Bag>");
617
617
  lines.push(" </dc:subject>");
@@ -619,15 +619,15 @@ function buildXmpMetadata(meta) {
619
619
  if (meta.subject !== void 0) {
620
620
  lines.push(" <dc:description>");
621
621
  lines.push(" <rdf:Alt>");
622
- lines.push(` <rdf:li xml:lang="x-default">${escapeXml$5(meta.subject)}</rdf:li>`);
622
+ lines.push(` <rdf:li xml:lang="x-default">${escapeXml$6(meta.subject)}</rdf:li>`);
623
623
  lines.push(" </rdf:Alt>");
624
624
  lines.push(" </dc:description>");
625
625
  }
626
- if (meta.creator !== void 0) lines.push(` <xmp:CreatorTool>${escapeXml$5(meta.creator)}</xmp:CreatorTool>`);
626
+ if (meta.creator !== void 0) lines.push(` <xmp:CreatorTool>${escapeXml$6(meta.creator)}</xmp:CreatorTool>`);
627
627
  if (meta.creationDate !== void 0) lines.push(` <xmp:CreateDate>${formatXmpDate(meta.creationDate)}</xmp:CreateDate>`);
628
628
  if (meta.modDate !== void 0) lines.push(` <xmp:ModifyDate>${formatXmpDate(meta.modDate)}</xmp:ModifyDate>`);
629
- if (meta.producer !== void 0) lines.push(` <pdf:Producer>${escapeXml$5(meta.producer)}</pdf:Producer>`);
630
- if (meta.keywords !== void 0) lines.push(` <pdf:Keywords>${escapeXml$5(meta.keywords)}</pdf:Keywords>`);
629
+ if (meta.producer !== void 0) lines.push(` <pdf:Producer>${escapeXml$6(meta.producer)}</pdf:Producer>`);
630
+ if (meta.keywords !== void 0) lines.push(` <pdf:Keywords>${escapeXml$6(meta.keywords)}</pdf:Keywords>`);
631
631
  lines.push("</rdf:Description>");
632
632
  lines.push("</rdf:RDF>");
633
633
  lines.push("</x:xmpmeta>");
@@ -702,7 +702,7 @@ function createXmpStream(meta, registry) {
702
702
  */
703
703
  function extractAltValue(xmp, tagName) {
704
704
  const match = new RegExp(`<${escapeRegex(tagName)}[^>]*>[\\s\\S]*?<rdf:Alt>[\\s\\S]*?<rdf:li[^>]*>([\\s\\S]*?)</rdf:li>`, "i").exec(xmp);
705
- if (match?.[1] !== void 0) return unescapeXml(match[1].trim());
705
+ if (match?.[1] !== void 0) return unescapeXml$1(match[1].trim());
706
706
  }
707
707
  /**
708
708
  * Extract the first value from an rdf:Seq container (used for dc:creator).
@@ -711,7 +711,7 @@ function extractAltValue(xmp, tagName) {
711
711
  */
712
712
  function extractSeqValue(xmp, tagName) {
713
713
  const match = new RegExp(`<${escapeRegex(tagName)}[^>]*>[\\s\\S]*?<rdf:Seq>[\\s\\S]*?<rdf:li[^>]*>([\\s\\S]*?)</rdf:li>`, "i").exec(xmp);
714
- if (match?.[1] !== void 0) return unescapeXml(match[1].trim());
714
+ if (match?.[1] !== void 0) return unescapeXml$1(match[1].trim());
715
715
  }
716
716
  /**
717
717
  * Extract a simple element value like `<pdf:Producer>VALUE</pdf:Producer>`.
@@ -720,15 +720,15 @@ function extractSeqValue(xmp, tagName) {
720
720
  */
721
721
  function extractSimpleValue(xmp, tagName) {
722
722
  const match = new RegExp(`<${escapeRegex(tagName)}[^>]*>([\\s\\S]*?)</${escapeRegex(tagName)}>`, "i").exec(xmp);
723
- if (match?.[1] !== void 0) return unescapeXml(match[1].trim());
723
+ if (match?.[1] !== void 0) return unescapeXml$1(match[1].trim());
724
724
  const attrMatch = new RegExp(`${escapeRegex(tagName)}="([^"]*)"`, "i").exec(xmp);
725
- if (attrMatch?.[1] !== void 0) return unescapeXml(attrMatch[1]);
725
+ if (attrMatch?.[1] !== void 0) return unescapeXml$1(attrMatch[1]);
726
726
  }
727
727
  /**
728
728
  * Unescape XML entities.
729
729
  * @internal
730
730
  */
731
- function unescapeXml(str) {
731
+ function unescapeXml$1(str) {
732
732
  return str.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, "\"").replace(/&apos;/g, "'").replace(/&amp;/g, "&");
733
733
  }
734
734
  /**
@@ -2224,7 +2224,7 @@ var PdfFileAttachmentAnnotation = class PdfFileAttachmentAnnotation extends requ
2224
2224
  };
2225
2225
  //#endregion
2226
2226
  //#region src/parser/textSearch.ts
2227
- function escapeRegExp(literal) {
2227
+ function escapeRegExp$1(literal) {
2228
2228
  return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2229
2229
  }
2230
2230
  function buildRegExp(query, options) {
@@ -2232,7 +2232,7 @@ function buildRegExp(query, options) {
2232
2232
  const flags = query.flags.includes("g") ? query.flags : `${query.flags}g`;
2233
2233
  return new RegExp(query.source, flags);
2234
2234
  }
2235
- const body = options?.wholeWord ? `\\b${escapeRegExp(query)}\\b` : escapeRegExp(query);
2235
+ const body = options?.wholeWord ? `\\b${escapeRegExp$1(query)}\\b` : escapeRegExp$1(query);
2236
2236
  return new RegExp(body, options?.caseSensitive ? "g" : "gi");
2237
2237
  }
2238
2238
  /** Build one hit-rect per contiguous run of same-item characters in `[start, end)`. */
@@ -2552,7 +2552,7 @@ async function requestTimestamp(dataHash, tsaUrl, hashAlgorithm = "SHA-256") {
2552
2552
  }
2553
2553
  //#endregion
2554
2554
  //#region src/signature/incrementalSave.ts
2555
- const encoder$10 = new TextEncoder();
2555
+ const encoder$11 = new TextEncoder();
2556
2556
  const decoder$16 = new TextDecoder("latin1");
2557
2557
  /**
2558
2558
  * Simple FNV-1a hash for change detection.
@@ -2579,7 +2579,7 @@ var ByteBuffer = class {
2579
2579
  this._offset += data.length;
2580
2580
  }
2581
2581
  writeString(str) {
2582
- this.write(encoder$10.encode(str));
2582
+ this.write(encoder$11.encode(str));
2583
2583
  }
2584
2584
  toUint8Array() {
2585
2585
  const result = new Uint8Array(this._offset);
@@ -3634,7 +3634,7 @@ const ECDSA_SIG_OID_MAP = {
3634
3634
  "SHA-384": "1.2.840.10045.4.3.3",
3635
3635
  "SHA-512": "1.2.840.10045.4.3.4"
3636
3636
  };
3637
- const encoder$9 = new TextEncoder();
3637
+ const encoder$10 = new TextEncoder();
3638
3638
  const decoder$10 = new TextDecoder("latin1");
3639
3639
  /**
3640
3640
  * Encode a small non-negative integer.
@@ -3823,7 +3823,7 @@ function buildCounterSignatureAppendix(pdf, targetIndex, counterSigAttr) {
3823
3823
  const newObjNum = currentSize;
3824
3824
  const hexContent = counterSigAttr.toHex();
3825
3825
  let appendix = "\n";
3826
- const objStart = pdf.length + encoder$9.encode(appendix).length;
3826
+ const objStart = pdf.length + encoder$10.encode(appendix).length;
3827
3827
  appendix += `${newObjNum} 0 obj\n`;
3828
3828
  appendix += `<< /Type /Annot /Subtype /Widget /FT /Sig`;
3829
3829
  appendix += ` /T (CounterSig_${targetIndex})`;
@@ -3833,7 +3833,7 @@ function buildCounterSignatureAppendix(pdf, targetIndex, counterSigAttr) {
3833
3833
  appendix += ` /Contents <${hexContent.padEnd(512, "0")}> >>`;
3834
3834
  appendix += ` /F 132 /Rect [0 0 0 0] >>\n`;
3835
3835
  appendix += "endobj\n";
3836
- const xrefOffset = pdf.length + encoder$9.encode(appendix).length;
3836
+ const xrefOffset = pdf.length + encoder$10.encode(appendix).length;
3837
3837
  appendix += "xref\n";
3838
3838
  appendix += `${newObjNum} 1\n`;
3839
3839
  appendix += `${objStart.toString().padStart(10, "0")} 00000 n \n`;
@@ -3846,7 +3846,7 @@ function buildCounterSignatureAppendix(pdf, targetIndex, counterSigAttr) {
3846
3846
  appendix += "startxref\n";
3847
3847
  appendix += `${xrefOffset}\n`;
3848
3848
  appendix += "%%EOF\n";
3849
- return encoder$9.encode(appendix);
3849
+ return encoder$10.encode(appendix);
3850
3850
  }
3851
3851
  /**
3852
3852
  * Extract counter-signatures from all signatures in a PDF.
@@ -3976,7 +3976,7 @@ function getCounterSignatures(pdf) {
3976
3976
  *
3977
3977
  * @packageDocumentation
3978
3978
  */
3979
- const encoder$8 = new TextEncoder();
3979
+ const encoder$9 = new TextEncoder();
3980
3980
  const decoder$9 = new TextDecoder("latin1");
3981
3981
  /**
3982
3982
  * Convert hex string to bytes, stripping trailing zero padding.
@@ -4140,7 +4140,7 @@ function buildDssIncrementalUpdate(pdf, data) {
4140
4140
  for (let i = 0; i < data.certs.length; i++) {
4141
4141
  const cert = data.certs[i];
4142
4142
  const objNum = certObjNums[i];
4143
- const offset = pdf.length + encoder$8.encode(appendix).length;
4143
+ const offset = pdf.length + encoder$9.encode(appendix).length;
4144
4144
  objOffsets.set(objNum, offset);
4145
4145
  const hexStr = cert.toHex();
4146
4146
  appendix += `${objNum} 0 obj\n`;
@@ -4153,7 +4153,7 @@ function buildDssIncrementalUpdate(pdf, data) {
4153
4153
  for (let i = 0; i < data.ocsps.length; i++) {
4154
4154
  const ocsp = data.ocsps[i];
4155
4155
  const objNum = ocspObjNums[i];
4156
- const offset = pdf.length + encoder$8.encode(appendix).length;
4156
+ const offset = pdf.length + encoder$9.encode(appendix).length;
4157
4157
  objOffsets.set(objNum, offset);
4158
4158
  const hexStr = ocsp.toHex();
4159
4159
  appendix += `${objNum} 0 obj\n`;
@@ -4166,7 +4166,7 @@ function buildDssIncrementalUpdate(pdf, data) {
4166
4166
  for (let i = 0; i < data.crls.length; i++) {
4167
4167
  const crl = data.crls[i];
4168
4168
  const objNum = crlObjNums[i];
4169
- const offset = pdf.length + encoder$8.encode(appendix).length;
4169
+ const offset = pdf.length + encoder$9.encode(appendix).length;
4170
4170
  objOffsets.set(objNum, offset);
4171
4171
  const hexStr = crl.toHex();
4172
4172
  appendix += `${objNum} 0 obj\n`;
@@ -4176,7 +4176,7 @@ function buildDssIncrementalUpdate(pdf, data) {
4176
4176
  appendix += `endstream\n`;
4177
4177
  appendix += `endobj\n`;
4178
4178
  }
4179
- const dssOffset = pdf.length + encoder$8.encode(appendix).length;
4179
+ const dssOffset = pdf.length + encoder$9.encode(appendix).length;
4180
4180
  objOffsets.set(dssObjNum, dssOffset);
4181
4181
  appendix += `${dssObjNum} 0 obj\n`;
4182
4182
  appendix += `<< /Type /DSS`;
@@ -4185,7 +4185,7 @@ function buildDssIncrementalUpdate(pdf, data) {
4185
4185
  if (crlObjNums.length > 0) appendix += ` /CRLs [${crlObjNums.map((n) => `${n} 0 R`).join(" ")}]`;
4186
4186
  appendix += ` >>\n`;
4187
4187
  appendix += `endobj\n`;
4188
- const xrefOffset = pdf.length + encoder$8.encode(appendix).length;
4188
+ const xrefOffset = pdf.length + encoder$9.encode(appendix).length;
4189
4189
  const totalNewObjs = newSize - currentSize;
4190
4190
  appendix += `xref\n`;
4191
4191
  appendix += `${currentSize} ${totalNewObjs}\n`;
@@ -4202,11 +4202,11 @@ function buildDssIncrementalUpdate(pdf, data) {
4202
4202
  appendix += `startxref\n`;
4203
4203
  appendix += `${xrefOffset}\n`;
4204
4204
  appendix += `%%EOF\n`;
4205
- return encoder$8.encode(appendix);
4205
+ return encoder$9.encode(appendix);
4206
4206
  }
4207
4207
  //#endregion
4208
4208
  //#region src/signature/incrementalOptimizer.ts
4209
- const encoder$7 = new TextEncoder();
4209
+ const encoder$8 = new TextEncoder();
4210
4210
  const decoder$8 = new TextDecoder("latin1");
4211
4211
  /**
4212
4212
  * FNV-1a 32-bit hash.
@@ -4280,7 +4280,7 @@ function findChangedObjects(original, modified) {
4280
4280
  continue;
4281
4281
  }
4282
4282
  if (computeObjectHash(origObj.content) !== computeObjectHash(modObj.content)) {
4283
- if (!bytesEqual(origObj.content, modObj.content)) changedObjNums.push(objNum);
4283
+ if (!bytesEqual$1(origObj.content, modObj.content)) changedObjNums.push(objNum);
4284
4284
  }
4285
4285
  }
4286
4286
  return changedObjNums.sort((a, b) => a - b);
@@ -4288,7 +4288,7 @@ function findChangedObjects(original, modified) {
4288
4288
  /**
4289
4289
  * Compare two Uint8Arrays for equality.
4290
4290
  */
4291
- function bytesEqual(a, b) {
4291
+ function bytesEqual$1(a, b) {
4292
4292
  if (a.length !== b.length) return false;
4293
4293
  for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
4294
4294
  return true;
@@ -4326,7 +4326,7 @@ function optimizeIncrementalSave(originalPdf, changes) {
4326
4326
  const changeHash = computeObjectHash(change.newContent);
4327
4327
  const origObj = originalObjs.get(change.objectNumber);
4328
4328
  if (origObj) {
4329
- if (computeObjectHash(origObj.content) === changeHash && bytesEqual(origObj.content, change.newContent)) continue;
4329
+ if (computeObjectHash(origObj.content) === changeHash && bytesEqual$1(origObj.content, change.newContent)) continue;
4330
4330
  }
4331
4331
  const dedupeKey = `${change.objectNumber}:${change.generationNumber}:${changeHash}`;
4332
4332
  if (seenHashes.has(dedupeKey)) continue;
@@ -4361,7 +4361,7 @@ function buildOptimizedAppendix(originalPdf, changes) {
4361
4361
  let appendix = "\n";
4362
4362
  const objOffsets = /* @__PURE__ */ new Map();
4363
4363
  for (const change of sortedChanges) {
4364
- const offset = originalPdf.length + encoder$7.encode(appendix).length;
4364
+ const offset = originalPdf.length + encoder$8.encode(appendix).length;
4365
4365
  objOffsets.set(change.objectNumber, offset);
4366
4366
  appendix += `${change.objectNumber} ${change.generationNumber} obj\n`;
4367
4367
  const contentStr = decoder$8.decode(change.newContent);
@@ -4369,7 +4369,7 @@ function buildOptimizedAppendix(originalPdf, changes) {
4369
4369
  if (!contentStr.endsWith("\n")) appendix += "\n";
4370
4370
  appendix += `endobj\n`;
4371
4371
  }
4372
- const xrefOffset = originalPdf.length + encoder$7.encode(appendix).length;
4372
+ const xrefOffset = originalPdf.length + encoder$8.encode(appendix).length;
4373
4373
  appendix += `xref\n`;
4374
4374
  const groups = groupConsecutive(sortedChanges.map((c) => c.objectNumber).sort((a, b) => a - b));
4375
4375
  for (const group of groups) {
@@ -4389,7 +4389,7 @@ function buildOptimizedAppendix(originalPdf, changes) {
4389
4389
  appendix += `startxref\n`;
4390
4390
  appendix += `${xrefOffset}\n`;
4391
4391
  appendix += `%%EOF\n`;
4392
- return encoder$7.encode(appendix);
4392
+ return encoder$8.encode(appendix);
4393
4393
  }
4394
4394
  /**
4395
4395
  * Group an array of sorted numbers into arrays of consecutive sequences.
@@ -4408,7 +4408,7 @@ function groupConsecutive(nums) {
4408
4408
  }
4409
4409
  //#endregion
4410
4410
  //#region src/core/linearization.ts
4411
- const encoder$6 = new TextEncoder();
4411
+ const encoder$7 = new TextEncoder();
4412
4412
  const decoder$7 = new TextDecoder();
4413
4413
  /**
4414
4414
  * Check if a PDF is linearized.
@@ -4450,7 +4450,7 @@ function getLinearizationInfo(pdfBytes) {
4450
4450
  }
4451
4451
  /** Find a string in the byte array, starting from `start`. */
4452
4452
  function findString(data, str, start = 0) {
4453
- const bytes = encoder$6.encode(str);
4453
+ const bytes = encoder$7.encode(str);
4454
4454
  outer: for (let i = start; i <= data.length - bytes.length; i++) {
4455
4455
  for (let j = 0; j < bytes.length; j++) if (data[i + j] !== bytes[j]) continue outer;
4456
4456
  return i;
@@ -4855,8 +4855,8 @@ function buildXrefStream(xrefObjNum, totalSize, entries, rootRef, infoRef, prevX
4855
4855
  dictStr += " >>";
4856
4856
  const objStr = `${xrefObjNum} 0 obj\n${dictStr}\nstream\n`;
4857
4857
  const objEnd = "\nendstream\nendobj\n";
4858
- const headerBytes = encoder$6.encode(objStr);
4859
- const footerBytes = encoder$6.encode(objEnd);
4858
+ const headerBytes = encoder$7.encode(objStr);
4859
+ const footerBytes = encoder$7.encode(objEnd);
4860
4860
  const result = new Uint8Array(headerBytes.length + streamData.length + footerBytes.length);
4861
4861
  result.set(headerBytes, 0);
4862
4862
  result.set(streamData, headerBytes.length);
@@ -4876,7 +4876,7 @@ function serializationPass(objects, firstPageObjNumsSorted, remainingObjNums, cl
4876
4876
  const serializedSizes = /* @__PURE__ */ new Map();
4877
4877
  let currentOffset = 0;
4878
4878
  function writeStr(s) {
4879
- const bytes = encoder$6.encode(s);
4879
+ const bytes = encoder$7.encode(s);
4880
4880
  chunks.push(bytes);
4881
4881
  currentOffset += bytes.length;
4882
4882
  }
@@ -5191,7 +5191,7 @@ function rebuildNormalPdf(objects, trailer) {
5191
5191
  const newOffsets = /* @__PURE__ */ new Map();
5192
5192
  let currentOffset = 0;
5193
5193
  function writeStr(s) {
5194
- const bytes = encoder$6.encode(s);
5194
+ const bytes = encoder$7.encode(s);
5195
5195
  chunks.push(bytes);
5196
5196
  currentOffset += bytes.length;
5197
5197
  }
@@ -5281,10 +5281,10 @@ function concatBytes(...arrays) {
5281
5281
  * Reference: ISO 19005-1:2005, ISO 19005-2:2011, ISO 19005-3:2012.
5282
5282
  */
5283
5283
  const decoder$6 = new TextDecoder();
5284
- const encoder$5 = new TextEncoder();
5284
+ const encoder$6 = new TextEncoder();
5285
5285
  /** Search for a pattern in the PDF bytes. */
5286
5286
  function findPattern$2(data, pattern, start = 0) {
5287
- const bytes = encoder$5.encode(pattern);
5287
+ const bytes = encoder$6.encode(pattern);
5288
5288
  outer: for (let i = start; i <= data.length - bytes.length; i++) {
5289
5289
  for (let j = 0; j < bytes.length; j++) if (data[i + j] !== bytes[j]) continue outer;
5290
5290
  return i;
@@ -5496,7 +5496,7 @@ function addPdfAXmpMetadata(data, part, conformance) {
5496
5496
  "</x:xmpmeta>",
5497
5497
  "<?xpacket end=\"w\"?>"
5498
5498
  ].join("\n");
5499
- const xmpBytes = encoder$5.encode(xmp);
5499
+ const xmpBytes = encoder$6.encode(xmp);
5500
5500
  const objMatches = decoder$6.decode(data).matchAll(/(\d+)\s+0\s+obj/g);
5501
5501
  let maxObj = 0;
5502
5502
  for (const m of objMatches) {
@@ -5517,12 +5517,12 @@ function addPdfAXmpMetadata(data, part, conformance) {
5517
5517
  const metaRef = `\n/Metadata ${metadataObjNum} 0 R\n`;
5518
5518
  const parts = [];
5519
5519
  parts.push(data.subarray(0, catalogEnd));
5520
- parts.push(encoder$5.encode(metaRef));
5520
+ parts.push(encoder$6.encode(metaRef));
5521
5521
  parts.push(data.subarray(catalogEnd));
5522
- parts.push(encoder$5.encode("\n"));
5523
- parts.push(encoder$5.encode(metaObj + "\n"));
5522
+ parts.push(encoder$6.encode("\n"));
5523
+ parts.push(encoder$6.encode(metaObj + "\n"));
5524
5524
  parts.push(xmpBytes);
5525
- parts.push(encoder$5.encode(metaObjEnd));
5525
+ parts.push(encoder$6.encode(metaObjEnd));
5526
5526
  return concatBytes(...parts);
5527
5527
  }
5528
5528
  /** Add a file identifier (/ID) to the trailer. */
@@ -5534,13 +5534,13 @@ function addTrailerId$1(data) {
5534
5534
  const idEntry = `\n/ID [<${crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(16)).toHex()}> <${crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(16)).toHex()}>]\n`;
5535
5535
  const parts = [];
5536
5536
  parts.push(data.subarray(0, trailerEnd));
5537
- parts.push(encoder$5.encode(idEntry));
5537
+ parts.push(encoder$6.encode(idEntry));
5538
5538
  parts.push(data.subarray(trailerEnd));
5539
5539
  return concatBytes(...parts);
5540
5540
  }
5541
5541
  //#endregion
5542
5542
  //#region src/compliance/transparencyFlattener.ts
5543
- const encoder$4 = new TextEncoder();
5543
+ const encoder$5 = new TextEncoder();
5544
5544
  const decoder$5 = new TextDecoder();
5545
5545
  /**
5546
5546
  * Analyze PDF bytes for transparency usage.
@@ -5628,7 +5628,7 @@ function flattenTransparency(pdfBytes) {
5628
5628
  });
5629
5629
  text = text.replace(/\/SMask\s+(?!\/None)\S+/g, "/SMask /None");
5630
5630
  text = text.replace(/\/BM\s+\/(?!Normal)\w+/g, "/BM /Normal");
5631
- return encoder$4.encode(text);
5631
+ return encoder$5.encode(text);
5632
5632
  }
5633
5633
  //#endregion
5634
5634
  //#region src/compliance/srgbIccProfile.ts
@@ -6911,7 +6911,7 @@ function buildAfArray(fileSpecRefs) {
6911
6911
  }
6912
6912
  //#endregion
6913
6913
  //#region src/compliance/stripProhibited.ts
6914
- const encoder$3 = new TextEncoder();
6914
+ const encoder$4 = new TextEncoder();
6915
6915
  const decoder$3 = new TextDecoder();
6916
6916
  /**
6917
6917
  * Count non-overlapping occurrences of `pattern` in `text`.
@@ -7003,7 +7003,7 @@ function stripProhibitedFeatures(pdfBytes, options = {}) {
7003
7003
  }
7004
7004
  }
7005
7005
  return {
7006
- bytes: modified ? encoder$3.encode(text) : pdfBytes,
7006
+ bytes: modified ? encoder$4.encode(text) : pdfBytes,
7007
7007
  stripped,
7008
7008
  modified
7009
7009
  };
@@ -7017,9 +7017,9 @@ function countMatches(text, regex) {
7017
7017
  }
7018
7018
  //#endregion
7019
7019
  //#region src/compliance/xmpGenerator.ts
7020
- const encoder$2 = new TextEncoder();
7020
+ const encoder$3 = new TextEncoder();
7021
7021
  /** Escape XML special characters in a string. */
7022
- function escapeXml$4(str) {
7022
+ function escapeXml$5(str) {
7023
7023
  return str.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
7024
7024
  }
7025
7025
  /**
@@ -7053,35 +7053,35 @@ function generatePdfAXmp(options) {
7053
7053
  if (options.title) {
7054
7054
  xmp += " <dc:title>\n";
7055
7055
  xmp += " <rdf:Alt>\n";
7056
- xmp += ` <rdf:li xml:lang="${lang}">${escapeXml$4(options.title)}</rdf:li>\n`;
7056
+ xmp += ` <rdf:li xml:lang="${lang}">${escapeXml$5(options.title)}</rdf:li>\n`;
7057
7057
  xmp += " </rdf:Alt>\n";
7058
7058
  xmp += " </dc:title>\n";
7059
7059
  }
7060
7060
  if (options.author) {
7061
7061
  xmp += " <dc:creator>\n";
7062
7062
  xmp += " <rdf:Seq>\n";
7063
- xmp += ` <rdf:li>${escapeXml$4(options.author)}</rdf:li>\n`;
7063
+ xmp += ` <rdf:li>${escapeXml$5(options.author)}</rdf:li>\n`;
7064
7064
  xmp += " </rdf:Seq>\n";
7065
7065
  xmp += " </dc:creator>\n";
7066
7066
  }
7067
7067
  if (options.subject) {
7068
7068
  xmp += " <dc:description>\n";
7069
7069
  xmp += " <rdf:Alt>\n";
7070
- xmp += ` <rdf:li xml:lang="${lang}">${escapeXml$4(options.subject)}</rdf:li>\n`;
7070
+ xmp += ` <rdf:li xml:lang="${lang}">${escapeXml$5(options.subject)}</rdf:li>\n`;
7071
7071
  xmp += " </rdf:Alt>\n";
7072
7072
  xmp += " </dc:description>\n";
7073
7073
  }
7074
7074
  xmp += " </rdf:Description>\n";
7075
7075
  xmp += " <rdf:Description rdf:about=\"\"\n";
7076
7076
  xmp += " xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\">\n";
7077
- xmp += ` <xmp:CreatorTool>${escapeXml$4(creatorTool)}</xmp:CreatorTool>\n`;
7077
+ xmp += ` <xmp:CreatorTool>${escapeXml$5(creatorTool)}</xmp:CreatorTool>\n`;
7078
7078
  xmp += ` <xmp:CreateDate>${createDate}</xmp:CreateDate>\n`;
7079
7079
  xmp += ` <xmp:ModifyDate>${modifyDate}</xmp:ModifyDate>\n`;
7080
7080
  xmp += " </rdf:Description>\n";
7081
7081
  xmp += " <rdf:Description rdf:about=\"\"\n";
7082
7082
  xmp += " xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n";
7083
- xmp += ` <pdf:Producer>${escapeXml$4(producer)}</pdf:Producer>\n`;
7084
- if (options.keywords) xmp += ` <pdf:Keywords>${escapeXml$4(options.keywords)}</pdf:Keywords>\n`;
7083
+ xmp += ` <pdf:Producer>${escapeXml$5(producer)}</pdf:Producer>\n`;
7084
+ if (options.keywords) xmp += ` <pdf:Keywords>${escapeXml$5(options.keywords)}</pdf:Keywords>\n`;
7085
7085
  xmp += " </rdf:Description>\n";
7086
7086
  xmp += " </rdf:RDF>\n";
7087
7087
  xmp += "</x:xmpmeta>\n";
@@ -7099,15 +7099,15 @@ function generatePdfAXmp(options) {
7099
7099
  * @returns XMP metadata as a `Uint8Array`.
7100
7100
  */
7101
7101
  function generatePdfAXmpBytes(options) {
7102
- return encoder$2.encode(generatePdfAXmp(options));
7102
+ return encoder$3.encode(generatePdfAXmp(options));
7103
7103
  }
7104
7104
  //#endregion
7105
7105
  //#region src/compliance/enforcePdfAv2.ts
7106
- const encoder$1 = new TextEncoder();
7106
+ const encoder$2 = new TextEncoder();
7107
7107
  const decoder$2 = new TextDecoder();
7108
7108
  /** Search for a byte pattern starting at `start`. */
7109
7109
  function findPattern$1(data, pattern, start = 0) {
7110
- const bytes = encoder$1.encode(pattern);
7110
+ const bytes = encoder$2.encode(pattern);
7111
7111
  outer: for (let i = start; i <= data.length - bytes.length; i++) {
7112
7112
  for (let j = 0; j < bytes.length; j++) if (data[i + j] !== bytes[j]) continue outer;
7113
7113
  return i;
@@ -7141,7 +7141,7 @@ function addXmpMetadata(data, part, conformance, options) {
7141
7141
  xmp.push("</x:xmpmeta>");
7142
7142
  xmp.push("<?xpacket end=\"w\"?>");
7143
7143
  const xmpStr = xmp.join("\n");
7144
- const xmpBytes = encoder$1.encode(xmpStr);
7144
+ const xmpBytes = encoder$2.encode(xmpStr);
7145
7145
  const str = decoder$2.decode(data);
7146
7146
  let maxObj = 0;
7147
7147
  for (const m of str.matchAll(/(\d+)\s+0\s+obj/g)) {
@@ -7157,11 +7157,11 @@ function addXmpMetadata(data, part, conformance, options) {
7157
7157
  if (catalogEnd < 0) return data;
7158
7158
  const metaRef = `\n/Metadata ${metadataObjNum} 0 R\n`;
7159
7159
  const before = data.subarray(0, catalogEnd);
7160
- const ref = encoder$1.encode(metaRef);
7160
+ const ref = encoder$2.encode(metaRef);
7161
7161
  const after = data.subarray(catalogEnd);
7162
- const stream = encoder$1.encode(metaObj);
7163
- const end = encoder$1.encode(metaObjEnd);
7164
- return concatBytes(before, ref, after, encoder$1.encode("\n"), stream, xmpBytes, end);
7162
+ const stream = encoder$2.encode(metaObj);
7163
+ const end = encoder$2.encode(metaObjEnd);
7164
+ return concatBytes(before, ref, after, encoder$2.encode("\n"), stream, xmpBytes, end);
7165
7165
  }
7166
7166
  /** Add a file identifier (/ID) to the trailer. */
7167
7167
  function addTrailerId(data) {
@@ -7170,7 +7170,7 @@ function addTrailerId(data) {
7170
7170
  const trailerEnd = findPattern$1(data, ">>", trailerIdx);
7171
7171
  if (trailerEnd < 0) return data;
7172
7172
  const idEntry = `\n/ID [<${crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(16)).toHex()}> <${crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(16)).toHex()}>]\n`;
7173
- return concatBytes(data.subarray(0, trailerEnd), encoder$1.encode(idEntry), data.subarray(trailerEnd));
7173
+ return concatBytes(data.subarray(0, trailerEnd), encoder$2.encode(idEntry), data.subarray(trailerEnd));
7174
7174
  }
7175
7175
  /**
7176
7176
  * Enforce PDF/A compliance with a full pipeline.
@@ -20861,7 +20861,7 @@ function rectToArray(rect) {
20861
20861
  //#endregion
20862
20862
  //#region src/compliance/facturX.ts
20863
20863
  /** Guideline URNs keyed by profile. */
20864
- const GUIDELINE_URNS = {
20864
+ const GUIDELINE_URNS$1 = {
20865
20865
  MINIMUM: "urn:factur-x.eu:1p0:minimum",
20866
20866
  "BASIC-WL": "urn:factur-x.eu:1p0:basicwl",
20867
20867
  BASIC: "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic",
@@ -20875,7 +20875,7 @@ const VAT_CATEGORY_STANDARD$1 = "S";
20875
20875
  /** Unit code C62 = "one" (unitless piece, UN/ECE Rec 20). */
20876
20876
  const UNIT_CODE_ONE$1 = "C62";
20877
20877
  /** Escape XML special characters in a text value. */
20878
- function escapeXml$3(str) {
20878
+ function escapeXml$4(str) {
20879
20879
  return str.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
20880
20880
  }
20881
20881
  /** Format a numeric monetary/quantity value with two decimal places. */
@@ -20933,13 +20933,13 @@ function computeTotals$1(lines) {
20933
20933
  /** Render a single trade party block (Seller or Buyer). */
20934
20934
  function renderParty$1(party, indent) {
20935
20935
  const lines = [];
20936
- lines.push(`${indent}<ram:Name>${escapeXml$3(party.name)}</ram:Name>`);
20936
+ lines.push(`${indent}<ram:Name>${escapeXml$4(party.name)}</ram:Name>`);
20937
20937
  lines.push(`${indent}<ram:PostalTradeAddress>`);
20938
- lines.push(`${indent} <ram:CountryID>${escapeXml$3(party.countryCode)}</ram:CountryID>`);
20938
+ lines.push(`${indent} <ram:CountryID>${escapeXml$4(party.countryCode)}</ram:CountryID>`);
20939
20939
  lines.push(`${indent}</ram:PostalTradeAddress>`);
20940
20940
  if (party.vatId !== void 0 && party.vatId !== "") {
20941
20941
  lines.push(`${indent}<ram:SpecifiedTaxRegistration>`);
20942
- lines.push(`${indent} <ram:ID schemeID="VA">${escapeXml$3(party.vatId)}</ram:ID>`);
20942
+ lines.push(`${indent} <ram:ID schemeID="VA">${escapeXml$4(party.vatId)}</ram:ID>`);
20943
20943
  lines.push(`${indent}</ram:SpecifiedTaxRegistration>`);
20944
20944
  }
20945
20945
  return lines.join("\n");
@@ -20953,7 +20953,7 @@ function renderLine$2(line, index, currency) {
20953
20953
  out.push(` <ram:LineID>${index}</ram:LineID>`);
20954
20954
  out.push(" </ram:AssociatedDocumentLineDocument>");
20955
20955
  out.push(" <ram:SpecifiedTradeProduct>");
20956
- out.push(` <ram:Name>${escapeXml$3(line.description)}</ram:Name>`);
20956
+ out.push(` <ram:Name>${escapeXml$4(line.description)}</ram:Name>`);
20957
20957
  out.push(" </ram:SpecifiedTradeProduct>");
20958
20958
  out.push(" <ram:SpecifiedLineTradeAgreement>");
20959
20959
  out.push(" <ram:NetPriceProductTradePrice>");
@@ -20970,7 +20970,7 @@ function renderLine$2(line, index, currency) {
20970
20970
  out.push(` <ram:RateApplicablePercent>${formatPercent$1(line.taxPercent)}</ram:RateApplicablePercent>`);
20971
20971
  out.push(" </ram:ApplicableTradeTax>");
20972
20972
  out.push(" <ram:SpecifiedTradeSettlementLineMonetarySummation>");
20973
- out.push(` <ram:LineTotalAmount currencyID="${escapeXml$3(currency)}">${formatAmount$1(net)}</ram:LineTotalAmount>`);
20973
+ out.push(` <ram:LineTotalAmount currencyID="${escapeXml$4(currency)}">${formatAmount$1(net)}</ram:LineTotalAmount>`);
20974
20974
  out.push(" </ram:SpecifiedTradeSettlementLineMonetarySummation>");
20975
20975
  out.push(" </ram:SpecifiedLineTradeSettlement>");
20976
20976
  out.push(" </ram:IncludedSupplyChainTradeLineItem>");
@@ -20980,9 +20980,9 @@ function renderLine$2(line, index, currency) {
20980
20980
  function renderTaxGroup$1(group, currency) {
20981
20981
  const out = [];
20982
20982
  out.push(" <ram:ApplicableTradeTax>");
20983
- out.push(` <ram:CalculatedAmount currencyID="${escapeXml$3(currency)}">${formatAmount$1(group.taxAmount)}</ram:CalculatedAmount>`);
20983
+ out.push(` <ram:CalculatedAmount currencyID="${escapeXml$4(currency)}">${formatAmount$1(group.taxAmount)}</ram:CalculatedAmount>`);
20984
20984
  out.push(" <ram:TypeCode>VAT</ram:TypeCode>");
20985
- out.push(` <ram:BasisAmount currencyID="${escapeXml$3(currency)}">${formatAmount$1(group.basisAmount)}</ram:BasisAmount>`);
20985
+ out.push(` <ram:BasisAmount currencyID="${escapeXml$4(currency)}">${formatAmount$1(group.basisAmount)}</ram:BasisAmount>`);
20986
20986
  out.push(` <ram:CategoryCode>${VAT_CATEGORY_STANDARD$1}</ram:CategoryCode>`);
20987
20987
  out.push(` <ram:RateApplicablePercent>${formatPercent$1(group.taxPercent)}</ram:RateApplicablePercent>`);
20988
20988
  out.push(" </ram:ApplicableTradeTax>");
@@ -21004,17 +21004,17 @@ function renderTaxGroup$1(group, currency) {
21004
21004
  function generateCiiXml(invoice, profile = "EN16931") {
21005
21005
  const totals = computeTotals$1(invoice.lines);
21006
21006
  const currency = invoice.currency;
21007
- const guidelineUrn = GUIDELINE_URNS[profile];
21007
+ const guidelineUrn = GUIDELINE_URNS$1[profile];
21008
21008
  const out = [];
21009
21009
  out.push("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
21010
21010
  out.push("<rsm:CrossIndustryInvoice xmlns:rsm=\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100\" xmlns:ram=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100\" xmlns:udt=\"urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100\">");
21011
21011
  out.push(" <rsm:ExchangedDocumentContext>");
21012
21012
  out.push(" <ram:GuidelineSpecifiedDocumentContextParameter>");
21013
- out.push(` <ram:ID>${escapeXml$3(guidelineUrn)}</ram:ID>`);
21013
+ out.push(` <ram:ID>${escapeXml$4(guidelineUrn)}</ram:ID>`);
21014
21014
  out.push(" </ram:GuidelineSpecifiedDocumentContextParameter>");
21015
21015
  out.push(" </rsm:ExchangedDocumentContext>");
21016
21016
  out.push(" <rsm:ExchangedDocument>");
21017
- out.push(` <ram:ID>${escapeXml$3(invoice.invoiceNumber)}</ram:ID>`);
21017
+ out.push(` <ram:ID>${escapeXml$4(invoice.invoiceNumber)}</ram:ID>`);
21018
21018
  out.push(` <ram:TypeCode>${COMMERCIAL_INVOICE_TYPE_CODE$1}</ram:TypeCode>`);
21019
21019
  out.push(" <ram:IssueDateTime>");
21020
21020
  out.push(` <udt:DateTimeString format="102">${toDateString102$1(invoice.issueDate)}</udt:DateTimeString>`);
@@ -21032,14 +21032,14 @@ function generateCiiXml(invoice, profile = "EN16931") {
21032
21032
  out.push(" </ram:ApplicableHeaderTradeAgreement>");
21033
21033
  out.push(" <ram:ApplicableHeaderTradeDelivery/>");
21034
21034
  out.push(" <ram:ApplicableHeaderTradeSettlement>");
21035
- out.push(` <ram:InvoiceCurrencyCode>${escapeXml$3(currency)}</ram:InvoiceCurrencyCode>`);
21035
+ out.push(` <ram:InvoiceCurrencyCode>${escapeXml$4(currency)}</ram:InvoiceCurrencyCode>`);
21036
21036
  for (const group of totals.taxGroups) out.push(renderTaxGroup$1(group, currency));
21037
21037
  out.push(" <ram:SpecifiedTradeSettlementHeaderMonetarySummation>");
21038
- out.push(` <ram:LineTotalAmount currencyID="${escapeXml$3(currency)}">${formatAmount$1(totals.lineTotal)}</ram:LineTotalAmount>`);
21039
- out.push(` <ram:TaxBasisTotalAmount currencyID="${escapeXml$3(currency)}">${formatAmount$1(totals.lineTotal)}</ram:TaxBasisTotalAmount>`);
21040
- out.push(` <ram:TaxTotalAmount currencyID="${escapeXml$3(currency)}">${formatAmount$1(totals.taxTotal)}</ram:TaxTotalAmount>`);
21041
- out.push(` <ram:GrandTotalAmount currencyID="${escapeXml$3(currency)}">${formatAmount$1(totals.grandTotal)}</ram:GrandTotalAmount>`);
21042
- out.push(` <ram:DuePayableAmount currencyID="${escapeXml$3(currency)}">${formatAmount$1(totals.duePayable)}</ram:DuePayableAmount>`);
21038
+ out.push(` <ram:LineTotalAmount currencyID="${escapeXml$4(currency)}">${formatAmount$1(totals.lineTotal)}</ram:LineTotalAmount>`);
21039
+ out.push(` <ram:TaxBasisTotalAmount currencyID="${escapeXml$4(currency)}">${formatAmount$1(totals.lineTotal)}</ram:TaxBasisTotalAmount>`);
21040
+ out.push(` <ram:TaxTotalAmount currencyID="${escapeXml$4(currency)}">${formatAmount$1(totals.taxTotal)}</ram:TaxTotalAmount>`);
21041
+ out.push(` <ram:GrandTotalAmount currencyID="${escapeXml$4(currency)}">${formatAmount$1(totals.grandTotal)}</ram:GrandTotalAmount>`);
21042
+ out.push(` <ram:DuePayableAmount currencyID="${escapeXml$4(currency)}">${formatAmount$1(totals.duePayable)}</ram:DuePayableAmount>`);
21043
21043
  out.push(" </ram:SpecifiedTradeSettlementHeaderMonetarySummation>");
21044
21044
  out.push(" </ram:ApplicableHeaderTradeSettlement>");
21045
21045
  out.push(" </rsm:SupplyChainTradeTransaction>");
@@ -21261,7 +21261,7 @@ const PDFA4_PART = 4;
21261
21261
  /** PDF/A-4 revision year (`pdfaid:rev`). */
21262
21262
  const PDFA4_REV = "2020";
21263
21263
  /** Escape XML special characters in a string. */
21264
- function escapeXml$2(str) {
21264
+ function escapeXml$3(str) {
21265
21265
  return str.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
21266
21266
  }
21267
21267
  /**
@@ -21279,17 +21279,17 @@ function conformanceFor(level) {
21279
21279
  function renderExtensionSchema(s) {
21280
21280
  let out = "";
21281
21281
  out += " <rdf:li rdf:parseType=\"Resource\">\n";
21282
- out += ` <pdfaSchema:schema>${escapeXml$2(s.schema)}</pdfaSchema:schema>\n`;
21283
- out += ` <pdfaSchema:namespaceURI>${escapeXml$2(s.namespaceUri)}</pdfaSchema:namespaceURI>\n`;
21284
- out += ` <pdfaSchema:prefix>${escapeXml$2(s.prefix)}</pdfaSchema:prefix>\n`;
21282
+ out += ` <pdfaSchema:schema>${escapeXml$3(s.schema)}</pdfaSchema:schema>\n`;
21283
+ out += ` <pdfaSchema:namespaceURI>${escapeXml$3(s.namespaceUri)}</pdfaSchema:namespaceURI>\n`;
21284
+ out += ` <pdfaSchema:prefix>${escapeXml$3(s.prefix)}</pdfaSchema:prefix>\n`;
21285
21285
  out += " <pdfaSchema:property>\n";
21286
21286
  out += " <rdf:Seq>\n";
21287
21287
  for (const p of s.properties) {
21288
21288
  out += " <rdf:li rdf:parseType=\"Resource\">\n";
21289
- out += ` <pdfaProperty:name>${escapeXml$2(p.name)}</pdfaProperty:name>\n`;
21290
- out += ` <pdfaProperty:valueType>${escapeXml$2(p.valueType)}</pdfaProperty:valueType>\n`;
21289
+ out += ` <pdfaProperty:name>${escapeXml$3(p.name)}</pdfaProperty:name>\n`;
21290
+ out += ` <pdfaProperty:valueType>${escapeXml$3(p.valueType)}</pdfaProperty:valueType>\n`;
21291
21291
  out += ` <pdfaProperty:category>${p.category}</pdfaProperty:category>\n`;
21292
- out += ` <pdfaProperty:description>${escapeXml$2(p.description)}</pdfaProperty:description>\n`;
21292
+ out += ` <pdfaProperty:description>${escapeXml$3(p.description)}</pdfaProperty:description>\n`;
21293
21293
  out += " </rdf:li>\n";
21294
21294
  }
21295
21295
  out += " </rdf:Seq>\n";
@@ -21326,7 +21326,7 @@ function buildPdfA4Xmp(options) {
21326
21326
  xmp += " xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n";
21327
21327
  xmp += " <dc:title>\n";
21328
21328
  xmp += " <rdf:Alt>\n";
21329
- xmp += ` <rdf:li xml:lang="x-default">${escapeXml$2(title)}</rdf:li>\n`;
21329
+ xmp += ` <rdf:li xml:lang="x-default">${escapeXml$3(title)}</rdf:li>\n`;
21330
21330
  xmp += " </rdf:Alt>\n";
21331
21331
  xmp += " </dc:title>\n";
21332
21332
  xmp += " </rdf:Description>\n";
@@ -21400,7 +21400,7 @@ const ORDER_X_TYPE_CODES = {
21400
21400
  OrderResponse: ORDER_RESPONSE_TYPE_CODE
21401
21401
  };
21402
21402
  /** Escape XML special characters in a text value. */
21403
- function escapeXml$1(str) {
21403
+ function escapeXml$2(str) {
21404
21404
  return str.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
21405
21405
  }
21406
21406
  /** Format a numeric monetary/quantity value with two decimal places. */
@@ -21457,13 +21457,13 @@ function computeTotals(lines) {
21457
21457
  /** Render a single trade party block (Seller or Buyer). */
21458
21458
  function renderParty(party, indent) {
21459
21459
  const out = [];
21460
- out.push(`${indent}<ram:Name>${escapeXml$1(party.name)}</ram:Name>`);
21460
+ out.push(`${indent}<ram:Name>${escapeXml$2(party.name)}</ram:Name>`);
21461
21461
  out.push(`${indent}<ram:PostalTradeAddress>`);
21462
- out.push(`${indent} <ram:CountryID>${escapeXml$1(party.countryCode)}</ram:CountryID>`);
21462
+ out.push(`${indent} <ram:CountryID>${escapeXml$2(party.countryCode)}</ram:CountryID>`);
21463
21463
  out.push(`${indent}</ram:PostalTradeAddress>`);
21464
21464
  if (party.vatId !== void 0 && party.vatId !== "") {
21465
21465
  out.push(`${indent}<ram:SpecifiedTaxRegistration>`);
21466
- out.push(`${indent} <ram:ID schemeID="VA">${escapeXml$1(party.vatId)}</ram:ID>`);
21466
+ out.push(`${indent} <ram:ID schemeID="VA">${escapeXml$2(party.vatId)}</ram:ID>`);
21467
21467
  out.push(`${indent}</ram:SpecifiedTaxRegistration>`);
21468
21468
  }
21469
21469
  return out.join("\n");
@@ -21477,7 +21477,7 @@ function renderLine$1(line, index, currency) {
21477
21477
  out.push(` <ram:LineID>${index}</ram:LineID>`);
21478
21478
  out.push(" </ram:AssociatedDocumentLineDocument>");
21479
21479
  out.push(" <ram:SpecifiedTradeProduct>");
21480
- out.push(` <ram:Name>${escapeXml$1(line.description)}</ram:Name>`);
21480
+ out.push(` <ram:Name>${escapeXml$2(line.description)}</ram:Name>`);
21481
21481
  out.push(" </ram:SpecifiedTradeProduct>");
21482
21482
  out.push(" <ram:SpecifiedLineTradeAgreement>");
21483
21483
  out.push(" <ram:NetPriceProductTradePrice>");
@@ -21494,7 +21494,7 @@ function renderLine$1(line, index, currency) {
21494
21494
  out.push(` <ram:RateApplicablePercent>${formatPercent(line.taxPercent)}</ram:RateApplicablePercent>`);
21495
21495
  out.push(" </ram:ApplicableTradeTax>");
21496
21496
  out.push(" <ram:SpecifiedTradeSettlementLineMonetarySummation>");
21497
- out.push(` <ram:LineTotalAmount currencyID="${escapeXml$1(currency)}">${formatAmount(net)}</ram:LineTotalAmount>`);
21497
+ out.push(` <ram:LineTotalAmount currencyID="${escapeXml$2(currency)}">${formatAmount(net)}</ram:LineTotalAmount>`);
21498
21498
  out.push(" </ram:SpecifiedTradeSettlementLineMonetarySummation>");
21499
21499
  out.push(" </ram:SpecifiedLineTradeSettlement>");
21500
21500
  out.push(" </ram:IncludedSupplyChainTradeLineItem>");
@@ -21504,9 +21504,9 @@ function renderLine$1(line, index, currency) {
21504
21504
  function renderTaxGroup(group, currency) {
21505
21505
  const out = [];
21506
21506
  out.push(" <ram:ApplicableTradeTax>");
21507
- out.push(` <ram:CalculatedAmount currencyID="${escapeXml$1(currency)}">${formatAmount(group.taxAmount)}</ram:CalculatedAmount>`);
21507
+ out.push(` <ram:CalculatedAmount currencyID="${escapeXml$2(currency)}">${formatAmount(group.taxAmount)}</ram:CalculatedAmount>`);
21508
21508
  out.push(" <ram:TypeCode>VAT</ram:TypeCode>");
21509
- out.push(` <ram:BasisAmount currencyID="${escapeXml$1(currency)}">${formatAmount(group.basisAmount)}</ram:BasisAmount>`);
21509
+ out.push(` <ram:BasisAmount currencyID="${escapeXml$2(currency)}">${formatAmount(group.basisAmount)}</ram:BasisAmount>`);
21510
21510
  out.push(` <ram:CategoryCode>${VAT_CATEGORY_STANDARD}</ram:CategoryCode>`);
21511
21511
  out.push(` <ram:RateApplicablePercent>${formatPercent(group.taxPercent)}</ram:RateApplicablePercent>`);
21512
21512
  out.push(" </ram:ApplicableTradeTax>");
@@ -21516,11 +21516,11 @@ function renderTaxGroup(group, currency) {
21516
21516
  function renderMonetarySummation(totals, currency) {
21517
21517
  const out = [];
21518
21518
  out.push(" <ram:SpecifiedTradeSettlementHeaderMonetarySummation>");
21519
- out.push(` <ram:LineTotalAmount currencyID="${escapeXml$1(currency)}">${formatAmount(totals.lineTotal)}</ram:LineTotalAmount>`);
21520
- out.push(` <ram:TaxBasisTotalAmount currencyID="${escapeXml$1(currency)}">${formatAmount(totals.lineTotal)}</ram:TaxBasisTotalAmount>`);
21521
- out.push(` <ram:TaxTotalAmount currencyID="${escapeXml$1(currency)}">${formatAmount(totals.taxTotal)}</ram:TaxTotalAmount>`);
21522
- out.push(` <ram:GrandTotalAmount currencyID="${escapeXml$1(currency)}">${formatAmount(totals.grandTotal)}</ram:GrandTotalAmount>`);
21523
- out.push(` <ram:DuePayableAmount currencyID="${escapeXml$1(currency)}">${formatAmount(totals.duePayable)}</ram:DuePayableAmount>`);
21519
+ out.push(` <ram:LineTotalAmount currencyID="${escapeXml$2(currency)}">${formatAmount(totals.lineTotal)}</ram:LineTotalAmount>`);
21520
+ out.push(` <ram:TaxBasisTotalAmount currencyID="${escapeXml$2(currency)}">${formatAmount(totals.lineTotal)}</ram:TaxBasisTotalAmount>`);
21521
+ out.push(` <ram:TaxTotalAmount currencyID="${escapeXml$2(currency)}">${formatAmount(totals.taxTotal)}</ram:TaxTotalAmount>`);
21522
+ out.push(` <ram:GrandTotalAmount currencyID="${escapeXml$2(currency)}">${formatAmount(totals.grandTotal)}</ram:GrandTotalAmount>`);
21523
+ out.push(` <ram:DuePayableAmount currencyID="${escapeXml$2(currency)}">${formatAmount(totals.duePayable)}</ram:DuePayableAmount>`);
21524
21524
  out.push(" </ram:SpecifiedTradeSettlementHeaderMonetarySummation>");
21525
21525
  return out.join("\n");
21526
21526
  }
@@ -21544,11 +21544,11 @@ function generateXRechnungCii(invoice, options = {}) {
21544
21544
  out.push("<rsm:CrossIndustryInvoice xmlns:rsm=\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100\" xmlns:ram=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100\" xmlns:udt=\"urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100\">");
21545
21545
  out.push(" <rsm:ExchangedDocumentContext>");
21546
21546
  out.push(" <ram:GuidelineSpecifiedDocumentContextParameter>");
21547
- out.push(` <ram:ID>${escapeXml$1(XRECHNUNG_GUIDELINE_URN)}</ram:ID>`);
21547
+ out.push(` <ram:ID>${escapeXml$2(XRECHNUNG_GUIDELINE_URN)}</ram:ID>`);
21548
21548
  out.push(" </ram:GuidelineSpecifiedDocumentContextParameter>");
21549
21549
  out.push(" </rsm:ExchangedDocumentContext>");
21550
21550
  out.push(" <rsm:ExchangedDocument>");
21551
- out.push(` <ram:ID>${escapeXml$1(invoice.invoiceNumber)}</ram:ID>`);
21551
+ out.push(` <ram:ID>${escapeXml$2(invoice.invoiceNumber)}</ram:ID>`);
21552
21552
  out.push(` <ram:TypeCode>${COMMERCIAL_INVOICE_TYPE_CODE}</ram:TypeCode>`);
21553
21553
  out.push(" <ram:IssueDateTime>");
21554
21554
  out.push(` <udt:DateTimeString format="102">${toDateString102(invoice.issueDate)}</udt:DateTimeString>`);
@@ -21557,7 +21557,7 @@ function generateXRechnungCii(invoice, options = {}) {
21557
21557
  out.push(" <rsm:SupplyChainTradeTransaction>");
21558
21558
  for (const [i, line] of invoice.lines.entries()) out.push(renderLine$1(line, i + 1, currency));
21559
21559
  out.push(" <ram:ApplicableHeaderTradeAgreement>");
21560
- if (buyerReference !== void 0 && buyerReference !== "") out.push(` <ram:BuyerReference>${escapeXml$1(buyerReference)}</ram:BuyerReference>`);
21560
+ if (buyerReference !== void 0 && buyerReference !== "") out.push(` <ram:BuyerReference>${escapeXml$2(buyerReference)}</ram:BuyerReference>`);
21561
21561
  out.push(" <ram:SellerTradeParty>");
21562
21562
  out.push(renderParty(invoice.seller, " "));
21563
21563
  out.push(" </ram:SellerTradeParty>");
@@ -21567,7 +21567,7 @@ function generateXRechnungCii(invoice, options = {}) {
21567
21567
  out.push(" </ram:ApplicableHeaderTradeAgreement>");
21568
21568
  out.push(" <ram:ApplicableHeaderTradeDelivery/>");
21569
21569
  out.push(" <ram:ApplicableHeaderTradeSettlement>");
21570
- out.push(` <ram:InvoiceCurrencyCode>${escapeXml$1(currency)}</ram:InvoiceCurrencyCode>`);
21570
+ out.push(` <ram:InvoiceCurrencyCode>${escapeXml$2(currency)}</ram:InvoiceCurrencyCode>`);
21571
21571
  for (const group of totals.taxGroups) out.push(renderTaxGroup(group, currency));
21572
21572
  out.push(renderMonetarySummation(totals, currency));
21573
21573
  out.push(" </ram:ApplicableHeaderTradeSettlement>");
@@ -21598,11 +21598,11 @@ function generateOrderX(invoice, orderType) {
21598
21598
  out.push("<rsm:SCRDMCCBDACIOMessageStructure xmlns:rsm=\"urn:un:unece:uncefact:data:standard:SCRDMCCBDACIOMessageStructure:100\" xmlns:ram=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:128\" xmlns:udt=\"urn:un:unece:uncefact:data:standard:UnqualifiedDataType:128\">");
21599
21599
  out.push(" <rsm:ExchangedDocumentContext>");
21600
21600
  out.push(" <ram:GuidelineSpecifiedDocumentContextParameter>");
21601
- out.push(` <ram:ID>${escapeXml$1(ORDER_X_GUIDELINE_URN)}</ram:ID>`);
21601
+ out.push(` <ram:ID>${escapeXml$2(ORDER_X_GUIDELINE_URN)}</ram:ID>`);
21602
21602
  out.push(" </ram:GuidelineSpecifiedDocumentContextParameter>");
21603
21603
  out.push(" </rsm:ExchangedDocumentContext>");
21604
21604
  out.push(" <rsm:ExchangedDocument>");
21605
- out.push(` <ram:ID>${escapeXml$1(invoice.invoiceNumber)}</ram:ID>`);
21605
+ out.push(` <ram:ID>${escapeXml$2(invoice.invoiceNumber)}</ram:ID>`);
21606
21606
  out.push(` <ram:TypeCode>${typeCode}</ram:TypeCode>`);
21607
21607
  out.push(" <ram:IssueDateTime>");
21608
21608
  out.push(` <udt:DateTimeString format="102">${toDateString102(invoice.issueDate)}</udt:DateTimeString>`);
@@ -21620,7 +21620,7 @@ function generateOrderX(invoice, orderType) {
21620
21620
  out.push(" </ram:ApplicableHeaderTradeAgreement>");
21621
21621
  out.push(" <ram:ApplicableHeaderTradeDelivery/>");
21622
21622
  out.push(" <ram:ApplicableHeaderTradeSettlement>");
21623
- out.push(` <ram:OrderCurrencyCode>${escapeXml$1(currency)}</ram:OrderCurrencyCode>`);
21623
+ out.push(` <ram:OrderCurrencyCode>${escapeXml$2(currency)}</ram:OrderCurrencyCode>`);
21624
21624
  for (const group of totals.taxGroups) out.push(renderTaxGroup(group, currency));
21625
21625
  out.push(renderMonetarySummation(totals, currency));
21626
21626
  out.push(" </ram:ApplicableHeaderTradeSettlement>");
@@ -24457,7 +24457,7 @@ function extractCrlUrls(cert) {
24457
24457
  /**
24458
24458
  * Extract the DER-encoded subject Name from a certificate.
24459
24459
  */
24460
- function extractSubjectDer$1(certDer) {
24460
+ function extractSubjectDer$2(certDer) {
24461
24461
  const tbsCert = require_pdfDocument.parseDerTlv(certDer, 0).children[0];
24462
24462
  let idx = 0;
24463
24463
  if (tbsCert.children[0].tag === 160) idx = 1;
@@ -24468,7 +24468,7 @@ function extractSubjectDer$1(certDer) {
24468
24468
  /**
24469
24469
  * Extract the DER-encoded issuer Name from a certificate.
24470
24470
  */
24471
- function extractIssuerDer$1(certDer) {
24471
+ function extractIssuerDer$2(certDer) {
24472
24472
  const tbsCert = require_pdfDocument.parseDerTlv(certDer, 0).children[0];
24473
24473
  let idx = 0;
24474
24474
  if (tbsCert.children[0].tag === 160) idx = 1;
@@ -24590,7 +24590,7 @@ var TrustStore = class {
24590
24590
  */
24591
24591
  async isTrusted(cert) {
24592
24592
  await this._ready;
24593
- const key = await computeSubjectKey(extractSubjectDer$1(cert));
24593
+ const key = await computeSubjectKey(extractSubjectDer$2(cert));
24594
24594
  const entries = this._certs.get(key);
24595
24595
  if (!entries) return false;
24596
24596
  return entries.some((e) => compareBytes$1(e.der, cert));
@@ -24607,7 +24607,7 @@ var TrustStore = class {
24607
24607
  */
24608
24608
  async findIssuer(cert) {
24609
24609
  await this._ready;
24610
- const key = await computeSubjectKey(extractIssuerDer$1(cert));
24610
+ const key = await computeSubjectKey(extractIssuerDer$2(cert));
24611
24611
  const entries = this._certs.get(key);
24612
24612
  if (!entries || entries.length === 0) return null;
24613
24613
  return entries[0].der;
@@ -24641,7 +24641,7 @@ var TrustStore = class {
24641
24641
  * Add a single certificate to the store.
24642
24642
  */
24643
24643
  async _addOne(cert) {
24644
- const key = await computeSubjectKey(extractSubjectDer$1(cert));
24644
+ const key = await computeSubjectKey(extractSubjectDer$2(cert));
24645
24645
  const entry = {
24646
24646
  der: cert,
24647
24647
  serialBytes: extractSerialBytes(cert),
@@ -25643,10 +25643,10 @@ function summarizeBitDepth(depths) {
25643
25643
  * Reference: ISO 15930-4:2003, ISO 15930-6:2005, ISO 15930-7:2010.
25644
25644
  */
25645
25645
  const decoder = new TextDecoder();
25646
- const encoder = new TextEncoder();
25646
+ const encoder$1 = new TextEncoder();
25647
25647
  /** Search for a pattern in the PDF bytes. */
25648
25648
  function findPattern(data, pattern, start = 0) {
25649
- const bytes = encoder.encode(pattern);
25649
+ const bytes = encoder$1.encode(pattern);
25650
25650
  outer: for (let i = start; i <= data.length - bytes.length; i++) {
25651
25651
  for (let j = 0; j < bytes.length; j++) if (data[i + j] !== bytes[j]) continue outer;
25652
25652
  return i;
@@ -25951,14 +25951,14 @@ function addOutputIntent(data, config) {
25951
25951
  const catalogEnd = findPattern(data, ">>", catalogIdx);
25952
25952
  if (catalogEnd < 0) return data;
25953
25953
  const intentRef = `\n/OutputIntents [${intentObjNum} 0 R]\n`;
25954
- return concatBytes(data.subarray(0, catalogEnd), encoder.encode(intentRef), data.subarray(catalogEnd), encoder.encode("\n" + intentObj + "\n"));
25954
+ return concatBytes(data.subarray(0, catalogEnd), encoder$1.encode(intentRef), data.subarray(catalogEnd), encoder$1.encode("\n" + intentObj + "\n"));
25955
25955
  }
25956
25956
  /** Set /Trapped in the Info dictionary (or add to trailer area). */
25957
25957
  function setTrapped(data, value) {
25958
25958
  const text = decoder.decode(data);
25959
25959
  if (text.includes("/Trapped")) {
25960
25960
  const updated = text.replace(/\/Trapped\s*\/\w+/, `/Trapped /${value}`);
25961
- return encoder.encode(updated);
25961
+ return encoder$1.encode(updated);
25962
25962
  }
25963
25963
  const infoMatch = /\/Info\s+(\d+)\s+\d+\s+R/.exec(text);
25964
25964
  if (infoMatch) {
@@ -25967,7 +25967,7 @@ function setTrapped(data, value) {
25967
25967
  const infoDictEnd = findPattern(data, ">>", infoIdx);
25968
25968
  if (infoDictEnd >= 0) {
25969
25969
  const trappedEntry = ` /Trapped /${value}`;
25970
- return concatBytes(data.subarray(0, infoDictEnd), encoder.encode(trappedEntry), data.subarray(infoDictEnd));
25970
+ return concatBytes(data.subarray(0, infoDictEnd), encoder$1.encode(trappedEntry), data.subarray(infoDictEnd));
25971
25971
  }
25972
25972
  }
25973
25973
  }
@@ -25978,7 +25978,7 @@ function setTrapped(data, value) {
25978
25978
  const trailerEnd = findPattern(data, ">>", trailerIdx);
25979
25979
  if (trailerEnd < 0) return data;
25980
25980
  const infoRef = `\n/Info ${infoObjNum} 0 R\n`;
25981
- return concatBytes(data.subarray(0, trailerEnd), encoder.encode(infoRef), data.subarray(trailerEnd), encoder.encode("\n" + infoObj));
25981
+ return concatBytes(data.subarray(0, trailerEnd), encoder$1.encode(infoRef), data.subarray(trailerEnd), encoder$1.encode("\n" + infoObj));
25982
25982
  }
25983
25983
  /** Find the highest object number in the PDF text. */
25984
25984
  function findMaxObjNumber(text) {
@@ -26004,7 +26004,7 @@ function addMissingTrimBoxes(data) {
26004
26004
  }
26005
26005
  return match;
26006
26006
  });
26007
- return encoder.encode(text);
26007
+ return encoder$1.encode(text);
26008
26008
  }
26009
26009
  /** Flatten transparency for PDF/X-1a and X-3 compliance. */
26010
26010
  function flattenTransparencyForPdfX(data) {
@@ -26017,7 +26017,7 @@ function flattenTransparencyForPdfX(data) {
26017
26017
  });
26018
26018
  text = text.replace(/\/SMask\s+(?!\/None)\S+/g, "/SMask /None");
26019
26019
  text = text.replace(/\/BM\s+\/(?!Normal)\w+/g, "/BM /Normal");
26020
- return encoder.encode(text);
26020
+ return encoder$1.encode(text);
26021
26021
  }
26022
26022
  //#endregion
26023
26023
  //#region src/layout/textLayout.ts
@@ -26729,7 +26729,7 @@ function parseAsn1Time(node) {
26729
26729
  /**
26730
26730
  * Extract the subject raw DER bytes from a certificate.
26731
26731
  */
26732
- function extractSubjectDer(certDer) {
26732
+ function extractSubjectDer$1(certDer) {
26733
26733
  const tbsCert = require_pdfDocument.parseDerTlv(certDer, 0).children[0];
26734
26734
  let idx = 0;
26735
26735
  if (tbsCert.children[0].tag === 160) idx = 1;
@@ -26740,7 +26740,7 @@ function extractSubjectDer(certDer) {
26740
26740
  /**
26741
26741
  * Extract the issuer raw DER bytes from a certificate.
26742
26742
  */
26743
- function extractIssuerDer(certDer) {
26743
+ function extractIssuerDer$1(certDer) {
26744
26744
  const tbsCert = require_pdfDocument.parseDerTlv(certDer, 0).children[0];
26745
26745
  let idx = 0;
26746
26746
  if (tbsCert.children[0].tag === 160) idx = 1;
@@ -26794,8 +26794,8 @@ function isCA(certDer) {
26794
26794
  * Check if a certificate is self-signed (subject === issuer).
26795
26795
  */
26796
26796
  function isSelfSigned(certDer) {
26797
- const subjectDer = extractSubjectDer(certDer);
26798
- const issuerDer = extractIssuerDer(certDer);
26797
+ const subjectDer = extractSubjectDer$1(certDer);
26798
+ const issuerDer = extractIssuerDer$1(certDer);
26799
26799
  if (subjectDer.length !== issuerDer.length) return false;
26800
26800
  for (let i = 0; i < subjectDer.length; i++) if (subjectDer[i] !== issuerDer[i]) return false;
26801
26801
  return true;
@@ -26993,9 +26993,9 @@ function buildCertificateChain(leaf, intermediates) {
26993
26993
  chain,
26994
26994
  complete: true
26995
26995
  };
26996
- const currentIssuerDer = extractIssuerDer(current);
26996
+ const currentIssuerDer = extractIssuerDer$1(current);
26997
26997
  let foundIdx = -1;
26998
- for (let i = 0; i < available.length; i++) if (namesEqual(currentIssuerDer, extractSubjectDer(available[i]))) {
26998
+ for (let i = 0; i < available.length; i++) if (namesEqual(currentIssuerDer, extractSubjectDer$1(available[i]))) {
26999
26999
  foundIdx = i;
27000
27000
  break;
27001
27001
  }
@@ -27083,8 +27083,8 @@ async function validateCertificateChain(chain, options) {
27083
27083
  if (!signatureValid) certErrors.push("Root certificate self-signature verification failed");
27084
27084
  } else {
27085
27085
  let foundTrusted = false;
27086
- const certIssuerDer = extractIssuerDer(certDer);
27087
- for (const trusted of trustedCerts) if (namesEqual(certIssuerDer, extractSubjectDer(trusted))) {
27086
+ const certIssuerDer = extractIssuerDer$1(certDer);
27087
+ for (const trusted of trustedCerts) if (namesEqual(certIssuerDer, extractSubjectDer$1(trusted))) {
27088
27088
  signatureValid = await verifyCertSignature(certDer, trusted);
27089
27089
  foundTrusted = true;
27090
27090
  break;
@@ -27841,6 +27841,246 @@ function extractNodeBytesFromParent(fullBuffer, parent, child) {
27841
27841
  return fullBuffer.subarray(start, start + child.totalLength);
27842
27842
  }
27843
27843
  //#endregion
27844
+ //#region src/signature/certPathBuilder.ts
27845
+ /**
27846
+ * @module signature/certPathBuilder
27847
+ *
27848
+ * Certification-path (trust-chain) construction per RFC 5280 §6.1.
27849
+ *
27850
+ * Given a leaf certificate, a pool of intermediate CA certificates, and a
27851
+ * set of trust anchors, {@link buildCertPath} assembles the ordered chain
27852
+ *
27853
+ * ```
27854
+ * leaf -> intermediate -> ... -> (issuer that is a trust anchor)
27855
+ * ```
27856
+ *
27857
+ * by matching, at each step, the *current* certificate's **issuer** Name to
27858
+ * a candidate certificate's **subject** Name (RFC 5280 §4.1.2.4 / §4.1.2.6).
27859
+ * When both certificates additionally carry the relevant key-identifier
27860
+ * extensions, the candidate's **Subject Key Identifier** (SKI, OID
27861
+ * `2.5.29.14`, RFC 5280 §4.2.1.2) must equal the current certificate's
27862
+ * **Authority Key Identifier** (AKI `keyIdentifier`, OID `2.5.29.35`,
27863
+ * RFC 5280 §4.2.1.1) for the link to be accepted. If only one side carries
27864
+ * the identifier, name matching alone is used (RFC 5280 §6.1.4 treats key
27865
+ * identifiers as a hint, not a hard requirement).
27866
+ *
27867
+ * Building stops when:
27868
+ * - the current certificate (or a matched issuer) is a member of `anchors`
27869
+ * → `complete: true`, `anchor` set, and `path` excludes the anchor; or
27870
+ * - no issuer can be found among `intermediates`/`anchors`
27871
+ * → `complete: false` (partial path returned).
27872
+ *
27873
+ * Loop protection: a certificate already present in the constructed path is
27874
+ * never revisited (RFC 5280 §6.1 prohibits a certificate appearing more than
27875
+ * once in a certification path).
27876
+ *
27877
+ * Name matching uses byte-for-byte equality of the DER-encoded `Name`. This
27878
+ * is the exact-match comparison permitted by RFC 5280 §7.1 when both names
27879
+ * are produced by conforming encoders (as is the case for fixtures generated
27880
+ * here and for the overwhelming majority of real-world CAs).
27881
+ *
27882
+ * References:
27883
+ * - RFC 5280 §4.1.2.4 (issuer), §4.1.2.6 (subject)
27884
+ * - RFC 5280 §4.2.1.1 (Authority Key Identifier, OID 2.5.29.35)
27885
+ * - RFC 5280 §4.2.1.2 (Subject Key Identifier, OID 2.5.29.14)
27886
+ * - RFC 5280 §6.1 (Certification Path Validation — path construction)
27887
+ *
27888
+ * @packageDocumentation
27889
+ */
27890
+ /** Subject Key Identifier — RFC 5280 §4.2.1.2. */
27891
+ const OID_SUBJECT_KEY_IDENTIFIER = "2.5.29.14";
27892
+ /** Authority Key Identifier — RFC 5280 §4.2.1.1. */
27893
+ const OID_AUTHORITY_KEY_IDENTIFIER = "2.5.29.35";
27894
+ /**
27895
+ * Reconstruct the absolute byte range of a child node within the original
27896
+ * certificate buffer, returning the full TLV (header + value) as a subarray
27897
+ * that shares the cert's underlying ArrayBuffer.
27898
+ *
27899
+ * `parentNode.data` is a subarray of `certDer`; `child.offset` is the child's
27900
+ * offset within that parent value; `child.totalLength` covers header + value.
27901
+ */
27902
+ function sliceChild(certDer, parentNode, child) {
27903
+ const start = child.offset + (parentNode.data.byteOffset - certDer.byteOffset);
27904
+ return certDer.subarray(start, start + child.totalLength);
27905
+ }
27906
+ /**
27907
+ * Resolve the TBSCertificate node and the index offset that accounts for the
27908
+ * optional `version [0] EXPLICIT` field.
27909
+ *
27910
+ * TBSCertificate ::= SEQUENCE {
27911
+ * version [0] EXPLICIT INTEGER DEFAULT v1, -- tag 0xA0 when present
27912
+ * serialNumber INTEGER,
27913
+ * signature AlgorithmIdentifier,
27914
+ * issuer Name,
27915
+ * validity Validity,
27916
+ * subject Name,
27917
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
27918
+ * ... extensions [3] EXPLICIT ...
27919
+ * }
27920
+ */
27921
+ function tbsContext(certDer) {
27922
+ const tbs = require_pdfDocument.parseDerTlv(certDer, 0).children[0];
27923
+ if (!tbs) throw new Error("Malformed certificate: missing TBSCertificate");
27924
+ const first = tbs.children[0];
27925
+ return {
27926
+ tbs,
27927
+ idx: first && first.tag === 160 ? 1 : 0
27928
+ };
27929
+ }
27930
+ /** Extract the raw DER bytes of the issuer Name (RFC 5280 §4.1.2.4). */
27931
+ function extractIssuerDer(certDer) {
27932
+ const { tbs, idx } = tbsContext(certDer);
27933
+ const issuerNode = tbs.children[idx + 2];
27934
+ if (!issuerNode) throw new Error("Malformed certificate: missing issuer");
27935
+ return sliceChild(certDer, tbs, issuerNode);
27936
+ }
27937
+ /** Extract the raw DER bytes of the subject Name (RFC 5280 §4.1.2.6). */
27938
+ function extractSubjectDer(certDer) {
27939
+ const { tbs, idx } = tbsContext(certDer);
27940
+ const subjectNode = tbs.children[idx + 4];
27941
+ if (!subjectNode) throw new Error("Malformed certificate: missing subject");
27942
+ return sliceChild(certDer, tbs, subjectNode);
27943
+ }
27944
+ /**
27945
+ * Extract the list of Extension nodes (each a SEQUENCE) from a certificate,
27946
+ * or an empty array when no extensions are present.
27947
+ *
27948
+ * extensions [3] EXPLICIT SEQUENCE OF Extension
27949
+ * Extension ::= SEQUENCE { extnID OID, critical BOOLEAN DEFAULT FALSE, extnValue OCTET STRING }
27950
+ */
27951
+ function extractExtensionNodes(certDer) {
27952
+ try {
27953
+ const { tbs } = tbsContext(certDer);
27954
+ for (const child of tbs.children) if (child.tag === 163 && child.children.length > 0) return child.children[0].children;
27955
+ } catch {}
27956
+ return [];
27957
+ }
27958
+ /**
27959
+ * Locate the `extnValue` OCTET STRING contents for a given extension OID.
27960
+ * Returns the raw bytes inside the OCTET STRING (the DER of the extension's
27961
+ * value), or `undefined` if the extension is absent.
27962
+ */
27963
+ function findExtensionValue(certDer, oid) {
27964
+ for (const ext of extractExtensionNodes(certDer)) {
27965
+ const oidNode = ext.children[0];
27966
+ if (!oidNode) continue;
27967
+ if (require_pdfDocument.decodeOidBytes(oidNode.data) !== oid) continue;
27968
+ const valueNode = ext.children[ext.children.length - 1];
27969
+ if (!valueNode) return void 0;
27970
+ return valueNode.data;
27971
+ }
27972
+ }
27973
+ /**
27974
+ * Extract the Subject Key Identifier (key bytes) — RFC 5280 §4.2.1.2.
27975
+ *
27976
+ * SubjectKeyIdentifier ::= KeyIdentifier
27977
+ * KeyIdentifier ::= OCTET STRING
27978
+ *
27979
+ * extnValue (an OCTET STRING) wraps the KeyIdentifier OCTET STRING, so we
27980
+ * parse one inner OCTET STRING to obtain the raw identifier bytes.
27981
+ */
27982
+ function extractSki(certDer) {
27983
+ const extnValue = findExtensionValue(certDer, OID_SUBJECT_KEY_IDENTIFIER);
27984
+ if (!extnValue) return void 0;
27985
+ try {
27986
+ const inner = require_pdfDocument.parseDerTlv(extnValue, 0);
27987
+ if (inner.tag !== 4) return void 0;
27988
+ return inner.data;
27989
+ } catch {
27990
+ return;
27991
+ }
27992
+ }
27993
+ /**
27994
+ * Extract the Authority Key Identifier `keyIdentifier` — RFC 5280 §4.2.1.1.
27995
+ *
27996
+ * AuthorityKeyIdentifier ::= SEQUENCE {
27997
+ * keyIdentifier [0] KeyIdentifier OPTIONAL, -- IMPLICIT OCTET STRING, tag 0x80
27998
+ * authorityCertIssuer [1] GeneralNames OPTIONAL,
27999
+ * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
28000
+ *
28001
+ * extnValue (an OCTET STRING) wraps the SEQUENCE. We return the bytes of the
28002
+ * `[0]` IMPLICIT field (context tag 0x80), or `undefined` if absent.
28003
+ */
28004
+ function extractAkiKeyId(certDer) {
28005
+ const extnValue = findExtensionValue(certDer, OID_AUTHORITY_KEY_IDENTIFIER);
28006
+ if (!extnValue) return void 0;
28007
+ try {
28008
+ const seq = require_pdfDocument.parseDerTlv(extnValue, 0);
28009
+ if (seq.tag !== 48) return void 0;
28010
+ for (const field of seq.children) if (field.tag === 128) return field.data;
28011
+ } catch {
28012
+ return;
28013
+ }
28014
+ }
28015
+ /** Byte-for-byte equality of two arrays. */
28016
+ function bytesEqual(a, b) {
28017
+ if (a.length !== b.length) return false;
28018
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
28019
+ return true;
28020
+ }
28021
+ /**
28022
+ * Determine whether `candidate` could be the issuer of `cert`:
28023
+ * the candidate's subject DN must equal the cert's issuer DN, and — only when
28024
+ * BOTH key identifiers are present — the candidate's SKI must equal the cert's
28025
+ * AKI keyIdentifier (RFC 5280 §6.1.4 / §4.2.1.1).
28026
+ */
28027
+ function isIssuerOf(cert, candidate) {
28028
+ if (!bytesEqual(extractIssuerDer(cert), extractSubjectDer(candidate))) return false;
28029
+ const aki = extractAkiKeyId(cert);
28030
+ const ski = extractSki(candidate);
28031
+ if (aki && ski) return bytesEqual(aki, ski);
28032
+ return true;
28033
+ }
28034
+ /**
28035
+ * Build an ordered certification path from a leaf certificate to a trust
28036
+ * anchor per RFC 5280 §6.1.
28037
+ *
28038
+ * @param leafCertDer DER-encoded end-entity (leaf) certificate.
28039
+ * @param intermediates DER-encoded intermediate CA certificates (any order).
28040
+ * @param anchors DER-encoded trust anchors (root or directly-trusted CAs).
28041
+ * @returns {@link CertPathResult} — `path` is leaf-first and
28042
+ * excludes the anchor; `anchor` is reported separately
28043
+ * when the path is `complete`.
28044
+ *
28045
+ * @example
28046
+ * ```ts
28047
+ * const { path, complete, anchor } = buildCertPath(leaf, [intermediate], [root]);
28048
+ * // path = [leaf, intermediate], complete = true, anchor = root
28049
+ * ```
28050
+ */
28051
+ function buildCertPath(leafCertDer, intermediates, anchors) {
28052
+ const leafAnchor = anchors.find((a) => bytesEqual(a, leafCertDer));
28053
+ if (leafAnchor) return {
28054
+ path: [leafCertDer],
28055
+ complete: true,
28056
+ anchor: leafAnchor
28057
+ };
28058
+ const path = [leafCertDer];
28059
+ let current = leafCertDer;
28060
+ const maxDepth = intermediates.length + anchors.length + 2;
28061
+ for (let depth = 0; depth < maxDepth; depth++) {
28062
+ const anchor = anchors.find((a) => isIssuerOf(current, a));
28063
+ if (anchor) return {
28064
+ path,
28065
+ complete: true,
28066
+ anchor
28067
+ };
28068
+ const next = intermediates.find((c) => isIssuerOf(current, c) && !path.some((p) => bytesEqual(p, c)));
28069
+ if (!next) return {
28070
+ path,
28071
+ complete: false,
28072
+ anchor: void 0
28073
+ };
28074
+ path.push(next);
28075
+ current = next;
28076
+ }
28077
+ return {
28078
+ path,
28079
+ complete: false,
28080
+ anchor: void 0
28081
+ };
28082
+ }
28083
+ //#endregion
27844
28084
  //#region src/render/matrix.ts
27845
28085
  /** The identity transform. */
27846
28086
  function identity() {
@@ -31141,7 +31381,7 @@ const WTPDF_CONFORMS_TO_BASE = "http://pdfa.org/declarations/wtpdf#";
31141
31381
  */
31142
31382
  const PDFR_CONFORMS_TO = "http://pdfa.org/declarations/pdfr#1.0";
31143
31383
  /** Escape XML special characters in a string. */
31144
- function escapeXml(str) {
31384
+ function escapeXml$1(str) {
31145
31385
  return str.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
31146
31386
  }
31147
31387
  /**
@@ -31159,14 +31399,14 @@ function buildIdentificationXmp(identity) {
31159
31399
  const { profileName, conformsTo, part, conformance } = identity;
31160
31400
  let xmp = "<?xpacket begin=\"\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n";
31161
31401
  xmp += "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\">\n";
31162
- xmp += ` <!-- ${escapeXml(profileName)} identification marker (non-normative). -->\n`;
31402
+ xmp += ` <!-- ${escapeXml$1(profileName)} identification marker (non-normative). -->\n`;
31163
31403
  xmp += " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n";
31164
31404
  xmp += " <rdf:Description rdf:about=\"\"\n";
31165
31405
  xmp += ` xmlns:pdfd="${PDFD_NS}">\n`;
31166
31406
  xmp += " <pdfd:declarations>\n";
31167
31407
  xmp += " <rdf:Bag>\n";
31168
31408
  xmp += " <rdf:li rdf:parseType=\"Resource\">\n";
31169
- xmp += ` <pdfd:conformsTo>${escapeXml(conformsTo)}</pdfd:conformsTo>\n`;
31409
+ xmp += ` <pdfd:conformsTo>${escapeXml$1(conformsTo)}</pdfd:conformsTo>\n`;
31170
31410
  xmp += " </rdf:li>\n";
31171
31411
  xmp += " </rdf:Bag>\n";
31172
31412
  xmp += " </pdfd:declarations>\n";
@@ -31174,7 +31414,7 @@ function buildIdentificationXmp(identity) {
31174
31414
  xmp += " <rdf:Description rdf:about=\"\"\n";
31175
31415
  xmp += " xmlns:pid=\"http://modern-pdf-lib/ns/profile-id/\">\n";
31176
31416
  xmp += ` <pid:part>${part}</pid:part>\n`;
31177
- if (conformance !== void 0) xmp += ` <pid:conformance>${escapeXml(conformance)}</pid:conformance>\n`;
31417
+ if (conformance !== void 0) xmp += ` <pid:conformance>${escapeXml$1(conformance)}</pid:conformance>\n`;
31178
31418
  xmp += " </rdf:Description>\n";
31179
31419
  xmp += " </rdf:RDF>\n";
31180
31420
  xmp += "</x:xmpmeta>\n";
@@ -31233,6 +31473,396 @@ function buildPdfRIdentificationXmp(options) {
31233
31473
  });
31234
31474
  }
31235
31475
  //#endregion
31476
+ //#region src/compliance/facturXAssemble.ts
31477
+ /** Default profile when none is supplied. */
31478
+ const DEFAULT_PROFILE = "EN16931";
31479
+ /** Default embedded XML file name mandated by the Factur-X specification. */
31480
+ const DEFAULT_FILENAME = "factur-x.xml";
31481
+ /** Factur-X XMP extension-schema namespace URI (verified). */
31482
+ const FX_NAMESPACE_URI = "urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#";
31483
+ /** Factur-X XML schema version carried in `fx:Version` (verified: `1.0`). */
31484
+ const FX_VERSION = "1.0";
31485
+ /**
31486
+ * `fx:ConformanceLevel` strings keyed by profile.
31487
+ *
31488
+ * These are the human-readable profile names defined by the Factur-X
31489
+ * specification (note the embedded spaces in `BASIC WL` and `EN 16931`),
31490
+ * which differ from this library's internal {@link FacturXProfile} enum
31491
+ * tokens (`'BASIC-WL'`, `'EN16931'`). Verified against the Factur-X 1.0
31492
+ * specification.
31493
+ */
31494
+ const CONFORMANCE_LEVELS = {
31495
+ MINIMUM: "MINIMUM",
31496
+ "BASIC-WL": "BASIC WL",
31497
+ BASIC: "BASIC",
31498
+ EN16931: "EN 16931",
31499
+ EXTENDED: "EXTENDED"
31500
+ };
31501
+ const encoder = new TextEncoder();
31502
+ /** Escape XML special characters in a text value. */
31503
+ function escapeXml(str) {
31504
+ return str.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
31505
+ }
31506
+ /**
31507
+ * Build the Factur-X PDF/A-3 XMP extension metadata.
31508
+ *
31509
+ * Returns an XMP RDF fragment containing two `rdf:Description` blocks:
31510
+ *
31511
+ * 1. The **actual Factur-X values** in the `fx:` namespace —
31512
+ * `fx:DocumentType` (`INVOICE`), `fx:DocumentFileName`, `fx:Version`
31513
+ * (`1.0`) and `fx:ConformanceLevel` (derived from `profile`).
31514
+ * 2. The **PDF/A extension-schema description** (`pdfaExtension:schemas`),
31515
+ * which is required for PDF/A-3 conformance so that validators can resolve
31516
+ * the custom `fx:` properties.
31517
+ *
31518
+ * The fragment is rooted at `<rdf:RDF>` so it can be merged into a larger XMP
31519
+ * packet (e.g. alongside the `pdfaid`, `dc`, `xmp` and `pdf` descriptions
31520
+ * produced by the PDF/A XMP generator).
31521
+ *
31522
+ * @param profile The Factur-X / ZUGFeRD profile.
31523
+ * @param documentFileName The embedded XML file name. Must match the name under
31524
+ * which the XML is attached. Default: `'factur-x.xml'`.
31525
+ * @returns The XMP RDF string.
31526
+ */
31527
+ function buildFacturXXmp(profile, documentFileName = DEFAULT_FILENAME) {
31528
+ const conformanceLevel = CONFORMANCE_LEVELS[profile];
31529
+ const fileName = escapeXml(documentFileName);
31530
+ const out = [];
31531
+ out.push("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">");
31532
+ out.push(` <rdf:Description rdf:about="" xmlns:fx="${FX_NAMESPACE_URI}">`);
31533
+ out.push(` <fx:ConformanceLevel>${escapeXml(conformanceLevel)}</fx:ConformanceLevel>`);
31534
+ out.push(` <fx:DocumentFileName>${fileName}</fx:DocumentFileName>`);
31535
+ out.push(" <fx:DocumentType>INVOICE</fx:DocumentType>");
31536
+ out.push(` <fx:Version>${FX_VERSION}</fx:Version>`);
31537
+ out.push(" </rdf:Description>");
31538
+ out.push(" <rdf:Description rdf:about=\"\"");
31539
+ out.push(" xmlns:pdfaExtension=\"http://www.aiim.org/pdfa/ns/extension/\"");
31540
+ out.push(" xmlns:pdfaSchema=\"http://www.aiim.org/pdfa/ns/schema#\"");
31541
+ out.push(" xmlns:pdfaProperty=\"http://www.aiim.org/pdfa/ns/property#\">");
31542
+ out.push(" <pdfaExtension:schemas>");
31543
+ out.push(" <rdf:Bag>");
31544
+ out.push(" <rdf:li rdf:parseType=\"Resource\">");
31545
+ out.push(" <pdfaSchema:schema>Factur-X PDFA Extension Schema</pdfaSchema:schema>");
31546
+ out.push(` <pdfaSchema:namespaceURI>${FX_NAMESPACE_URI}</pdfaSchema:namespaceURI>`);
31547
+ out.push(" <pdfaSchema:prefix>fx</pdfaSchema:prefix>");
31548
+ out.push(" <pdfaSchema:property>");
31549
+ out.push(" <rdf:Seq>");
31550
+ for (const [name, description] of [
31551
+ ["DocumentFileName", "name of the embedded XML invoice file"],
31552
+ ["DocumentType", "INVOICE"],
31553
+ ["Version", "The actual version of the Factur-X XML schema"],
31554
+ ["ConformanceLevel", "The conformance level of the embedded Factur-X data"]
31555
+ ]) {
31556
+ out.push(" <rdf:li rdf:parseType=\"Resource\">");
31557
+ out.push(` <pdfaProperty:name>${name}</pdfaProperty:name>`);
31558
+ out.push(" <pdfaProperty:valueType>Text</pdfaProperty:valueType>");
31559
+ out.push(" <pdfaProperty:category>external</pdfaProperty:category>");
31560
+ out.push(` <pdfaProperty:description>${escapeXml(description)}</pdfaProperty:description>`);
31561
+ out.push(" </rdf:li>");
31562
+ }
31563
+ out.push(" </rdf:Seq>");
31564
+ out.push(" </pdfaSchema:property>");
31565
+ out.push(" </rdf:li>");
31566
+ out.push(" </rdf:Bag>");
31567
+ out.push(" </pdfaExtension:schemas>");
31568
+ out.push(" </rdf:Description>");
31569
+ out.push("</rdf:RDF>");
31570
+ return out.join("\n");
31571
+ }
31572
+ /**
31573
+ * Assemble a hybrid Factur-X PDF/A-3 invoice.
31574
+ *
31575
+ * Generates the CII XML for `invoice` under the requested profile, encodes it
31576
+ * as UTF-8 bytes and attaches it to `doc` as a PDF/A-3 associated file with the
31577
+ * `/Alternative` relationship (referenced from the catalog `/AF` array).
31578
+ *
31579
+ * The XMP from {@link buildFacturXXmp} can be merged into the document's
31580
+ * metadata by the caller to complete PDF/A-3 / Factur-X conformance.
31581
+ *
31582
+ * @param doc The target PDF document (should already be PDF/A-3 shaped).
31583
+ * @param invoice The invoice data.
31584
+ * @param options Optional profile and embedded file name.
31585
+ * @returns The generated CII XML string.
31586
+ */
31587
+ function assembleFacturX(doc, invoice, options) {
31588
+ const profile = options?.profile ?? DEFAULT_PROFILE;
31589
+ const filename = options?.filename ?? DEFAULT_FILENAME;
31590
+ const xml = generateCiiXml(invoice, profile);
31591
+ const bytes = encoder.encode(xml);
31592
+ doc.addAssociatedFile(filename, bytes, "text/xml", "Alternative", { description: "Factur-X invoice data" });
31593
+ return xml;
31594
+ }
31595
+ //#endregion
31596
+ //#region src/compliance/eInvoiceValidate.ts
31597
+ /**
31598
+ * Monetary comparison tolerance, in the invoice currency's major unit.
31599
+ * EN 16931 amounts are rounded to two decimals; half a cent of slack
31600
+ * absorbs accumulated floating-point and rounding noise.
31601
+ */
31602
+ const MONETARY_TOLERANCE = .005;
31603
+ /** True when `value` is a non-empty, non-whitespace string. */
31604
+ function isNonEmptyText(value) {
31605
+ return value.trim().length > 0;
31606
+ }
31607
+ /** True when two monetary amounts are equal within {@link MONETARY_TOLERANCE}. */
31608
+ function amountsEqual(a, b) {
31609
+ return Math.abs(a - b) <= MONETARY_TOLERANCE;
31610
+ }
31611
+ /** Sum the line net amounts (Σ quantity × unit price) of an invoice. */
31612
+ function sumLineNet(invoice) {
31613
+ let total = 0;
31614
+ for (const line of invoice.lines) total += line.quantity * line.unitPrice;
31615
+ return total;
31616
+ }
31617
+ /**
31618
+ * Validate an invoice against the core EN 16931 business rules that are
31619
+ * checkable from the typed {@link Invoice} model.
31620
+ *
31621
+ * Content-presence rules (BR-02, BR-03, BR-05, BR-06, BR-07, BR-16) are
31622
+ * always evaluated. The totals-calculation chain (BR-CO-10, BR-CO-13,
31623
+ * BR-CO-15, BR-CO-16) is only evaluated when the caller supplies
31624
+ * {@link ValidatableInvoice.declaredTotals}; otherwise those checks are
31625
+ * skipped because the model derives consistent totals from its lines.
31626
+ *
31627
+ * The function never throws; a structurally valid invoice returns `[]`.
31628
+ *
31629
+ * @param invoice - The invoice (optionally annotated with declared totals).
31630
+ * @returns A list of {@link EInvoiceIssue}s, empty when fully valid.
31631
+ */
31632
+ function validateEn16931(invoice) {
31633
+ const issues = [];
31634
+ if (!isNonEmptyText(invoice.invoiceNumber)) issues.push({
31635
+ rule: "BR-02",
31636
+ message: "An Invoice shall have an Invoice number (BT-1).",
31637
+ severity: "error"
31638
+ });
31639
+ if (!isNonEmptyText(invoice.issueDate)) issues.push({
31640
+ rule: "BR-03",
31641
+ message: "An Invoice shall have an Invoice issue date (BT-2).",
31642
+ severity: "error"
31643
+ });
31644
+ if (!isNonEmptyText(invoice.currency)) issues.push({
31645
+ rule: "BR-05",
31646
+ message: "An Invoice shall have an Invoice currency code (BT-5).",
31647
+ severity: "error"
31648
+ });
31649
+ if (!isNonEmptyText(invoice.seller.name)) issues.push({
31650
+ rule: "BR-06",
31651
+ message: "An Invoice shall contain the Seller name (BT-27).",
31652
+ severity: "error"
31653
+ });
31654
+ if (!isNonEmptyText(invoice.buyer.name)) issues.push({
31655
+ rule: "BR-07",
31656
+ message: "An Invoice shall contain the Buyer name (BT-44).",
31657
+ severity: "error"
31658
+ });
31659
+ if (invoice.lines.length === 0) issues.push({
31660
+ rule: "BR-16",
31661
+ message: "An Invoice shall have at least one Invoice line (BG-25).",
31662
+ severity: "error"
31663
+ });
31664
+ const declared = invoice.declaredTotals;
31665
+ if (declared !== void 0) {
31666
+ const computedLineNet = sumLineNet(invoice);
31667
+ const taxBasisTotal = declared.taxBasisTotal ?? declared.lineTotal;
31668
+ const duePayable = declared.duePayable ?? declared.grandTotal;
31669
+ if (!amountsEqual(declared.lineTotal, computedLineNet)) issues.push({
31670
+ rule: "BR-CO-10",
31671
+ message: `Sum of Invoice line net amount (BT-106) must equal the sum of Invoice line net amounts (BT-131): declared ${declared.lineTotal.toFixed(2)} vs. computed ${computedLineNet.toFixed(2)}.`,
31672
+ severity: "error"
31673
+ });
31674
+ if (!amountsEqual(taxBasisTotal, computedLineNet)) issues.push({
31675
+ rule: "BR-CO-13",
31676
+ message: `Invoice total amount without VAT (BT-109) must equal the sum of Invoice line net amounts (BT-131) minus document allowances (BT-107) plus document charges (BT-108): declared ${taxBasisTotal.toFixed(2)} vs. expected ${computedLineNet.toFixed(2)}.`,
31677
+ severity: "error"
31678
+ });
31679
+ const expectedGrand = taxBasisTotal + declared.taxTotal;
31680
+ if (!amountsEqual(declared.grandTotal, expectedGrand)) issues.push({
31681
+ rule: "BR-CO-15",
31682
+ message: `Invoice total amount with VAT (BT-112) must equal Invoice total amount without VAT (BT-109) plus Invoice total VAT amount (BT-110): declared ${declared.grandTotal.toFixed(2)} vs. expected ${expectedGrand.toFixed(2)}.`,
31683
+ severity: "error"
31684
+ });
31685
+ if (!amountsEqual(duePayable, declared.grandTotal)) issues.push({
31686
+ rule: "BR-CO-16",
31687
+ message: `Amount due for payment (BT-115) must equal Invoice total amount with VAT (BT-112) minus paid amount (BT-113) plus rounding amount (BT-114): declared ${duePayable.toFixed(2)} vs. expected ${declared.grandTotal.toFixed(2)}.`,
31688
+ severity: "error"
31689
+ });
31690
+ }
31691
+ return issues;
31692
+ }
31693
+ //#endregion
31694
+ //#region src/compliance/ciiReader.ts
31695
+ /**
31696
+ * Guideline URNs keyed by profile.
31697
+ *
31698
+ * This mirrors the (non-exported) table in {@link module:compliance/facturX}
31699
+ * and is used to reverse-map a `GuidelineSpecifiedDocumentContextParameter/ID`
31700
+ * value back to a {@link FacturXProfile}.
31701
+ */
31702
+ const GUIDELINE_URNS = {
31703
+ MINIMUM: "urn:factur-x.eu:1p0:minimum",
31704
+ "BASIC-WL": "urn:factur-x.eu:1p0:basicwl",
31705
+ BASIC: "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic",
31706
+ EN16931: "urn:cen.eu:en16931:2017",
31707
+ EXTENDED: "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended"
31708
+ };
31709
+ /** Reverse of the generator's XML escaping. */
31710
+ function unescapeXml(str) {
31711
+ return str.replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&quot;", "\"").replaceAll("&apos;", "'").replaceAll("&amp;", "&");
31712
+ }
31713
+ /** Escape a string for safe inclusion in a RegExp. */
31714
+ function escapeRegExp(str) {
31715
+ return str.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
31716
+ }
31717
+ /**
31718
+ * Build a RegExp that matches `<[prefix:]name …>content</[prefix:]name>`
31719
+ * for the given local element name, ignoring any namespace prefix and
31720
+ * any attributes on the opening tag. The first capture group is the
31721
+ * (raw, still-escaped) inner content.
31722
+ */
31723
+ function elementRegExp(localName) {
31724
+ const n = escapeRegExp(localName);
31725
+ return new RegExp(`<(?:[\\w.-]+:)?${n}(?:\\s[^>]*)?>([\\s\\S]*?)</(?:[\\w.-]+:)?${n}>`);
31726
+ }
31727
+ /**
31728
+ * Extract the inner text of the first matching element (by local name)
31729
+ * within the given XML fragment, unescaped. Returns `undefined` if the
31730
+ * element is absent.
31731
+ */
31732
+ function firstText(xml, localName) {
31733
+ const match = elementRegExp(localName).exec(xml);
31734
+ if (match === null) return void 0;
31735
+ const inner = match[1];
31736
+ if (inner === void 0) return void 0;
31737
+ return unescapeXml(inner.trim());
31738
+ }
31739
+ /**
31740
+ * Extract the inner XML fragment (still containing child markup) of the
31741
+ * first matching element by local name. Returns `undefined` if absent.
31742
+ */
31743
+ function firstFragment(xml, localName) {
31744
+ const match = elementRegExp(localName).exec(xml);
31745
+ if (match === null) return void 0;
31746
+ return match[1] ?? void 0;
31747
+ }
31748
+ /**
31749
+ * Extract every non-overlapping block matching the given local element
31750
+ * name, returning each block's inner XML fragment.
31751
+ */
31752
+ function allFragments(xml, localName) {
31753
+ const n = escapeRegExp(localName);
31754
+ const re = new RegExp(`<(?:[\\w.-]+:)?${n}(?:\\s[^>]*)?>([\\s\\S]*?)</(?:[\\w.-]+:)?${n}>`, "g");
31755
+ const out = [];
31756
+ let match = re.exec(xml);
31757
+ while (match !== null) {
31758
+ const inner = match[1];
31759
+ if (inner !== void 0) out.push(inner);
31760
+ match = re.exec(xml);
31761
+ }
31762
+ return out;
31763
+ }
31764
+ /**
31765
+ * Parse a numeric text value, returning `0` when the value is missing or
31766
+ * not a finite number.
31767
+ */
31768
+ function parseNumber(text) {
31769
+ if (text === void 0) return 0;
31770
+ const value = Number.parseFloat(text);
31771
+ return Number.isFinite(value) ? value : 0;
31772
+ }
31773
+ /**
31774
+ * Convert a UN/CEFACT date-format-102 string (`YYYYMMDD`) to an ISO date
31775
+ * string (`YYYY-MM-DD`). Inputs that are not 8 digits are returned
31776
+ * unchanged (best effort).
31777
+ */
31778
+ function fromDateString102(value) {
31779
+ const digits = value.replaceAll(/[^0-9]/g, "");
31780
+ if (digits.length !== 8) return value;
31781
+ return `${digits.slice(0, 4)}-${digits.slice(4, 6)}-${digits.slice(6, 8)}`;
31782
+ }
31783
+ /** Parse a single trade-party fragment into an {@link InvoiceParty}. */
31784
+ function parseParty(fragment) {
31785
+ const name = firstText(fragment, "Name") ?? "";
31786
+ const countryCode = firstText(fragment, "CountryID") ?? "";
31787
+ const taxReg = firstFragment(fragment, "SpecifiedTaxRegistration");
31788
+ const vatId = taxReg !== void 0 ? firstText(taxReg, "ID") : void 0;
31789
+ return vatId !== void 0 && vatId !== "" ? {
31790
+ name,
31791
+ countryCode,
31792
+ vatId
31793
+ } : {
31794
+ name,
31795
+ countryCode
31796
+ };
31797
+ }
31798
+ /** Parse a single line-item fragment into an {@link InvoiceLine}. */
31799
+ function parseLine(fragment) {
31800
+ const productFragment = firstFragment(fragment, "SpecifiedTradeProduct");
31801
+ const description = (productFragment !== void 0 ? firstText(productFragment, "Name") : firstText(fragment, "Name")) ?? "";
31802
+ const priceFragment = firstFragment(fragment, "NetPriceProductTradePrice");
31803
+ const unitPrice = parseNumber(priceFragment !== void 0 ? firstText(priceFragment, "ChargeAmount") : firstText(fragment, "ChargeAmount"));
31804
+ return {
31805
+ description,
31806
+ quantity: parseNumber(firstText(fragment, "BilledQuantity")),
31807
+ unitPrice,
31808
+ taxPercent: parseNumber(firstText(fragment, "RateApplicablePercent"))
31809
+ };
31810
+ }
31811
+ /**
31812
+ * Parse a UN/CEFACT Cross Industry Invoice (CII) XML string into the
31813
+ * typed {@link Invoice} model.
31814
+ *
31815
+ * The parser is namespace-prefix tolerant (it matches on local element
31816
+ * names) and recovers the invoice number, issue date, currency, the
31817
+ * seller and buyer parties (name, country, VAT id) and every line item
31818
+ * (description, quantity, unit price, tax rate).
31819
+ *
31820
+ * @param xml - The CII XML document.
31821
+ * @returns The parsed {@link Invoice}.
31822
+ * @throws If the input does not contain a `CrossIndustryInvoice` root.
31823
+ */
31824
+ function parseCiiXml(xml) {
31825
+ const root = firstFragment(xml, "CrossIndustryInvoice");
31826
+ if (root === void 0) throw new Error("ciiReader: not a CrossIndustryInvoice document (no <CrossIndustryInvoice> root element found).");
31827
+ const docFragment = firstFragment(root, "ExchangedDocument") ?? root;
31828
+ const invoiceNumber = firstText(docFragment, "ID") ?? "";
31829
+ const issueRaw = firstText(docFragment, "DateTimeString") ?? "";
31830
+ const issueDate = issueRaw === "" ? "" : fromDateString102(issueRaw);
31831
+ const currency = firstText(root, "InvoiceCurrencyCode") ?? "";
31832
+ const sellerFragment = firstFragment(root, "SellerTradeParty");
31833
+ const buyerFragment = firstFragment(root, "BuyerTradeParty");
31834
+ return {
31835
+ invoiceNumber,
31836
+ issueDate,
31837
+ currency,
31838
+ seller: sellerFragment !== void 0 ? parseParty(sellerFragment) : {
31839
+ name: "",
31840
+ countryCode: ""
31841
+ },
31842
+ buyer: buyerFragment !== void 0 ? parseParty(buyerFragment) : {
31843
+ name: "",
31844
+ countryCode: ""
31845
+ },
31846
+ lines: allFragments(root, "IncludedSupplyChainTradeLineItem").map(parseLine)
31847
+ };
31848
+ }
31849
+ /**
31850
+ * Detect the Factur-X / ZUGFeRD profile of a CII XML document by reading
31851
+ * its `GuidelineSpecifiedDocumentContextParameter/ID` (the profile URN)
31852
+ * and mapping it back to a {@link FacturXProfile}.
31853
+ *
31854
+ * @param xml - The CII XML document.
31855
+ * @returns The matching {@link FacturXProfile}, or `undefined` if no
31856
+ * guideline URN is present or it does not match a known profile.
31857
+ */
31858
+ function detectFacturXProfile(xml) {
31859
+ const contextFragment = firstFragment(xml, "GuidelineSpecifiedDocumentContextParameter");
31860
+ if (contextFragment === void 0) return void 0;
31861
+ const urn = firstText(contextFragment, "ID");
31862
+ if (urn === void 0 || urn === "") return void 0;
31863
+ for (const profile of Object.keys(GUIDELINE_URNS)) if (GUIDELINE_URNS[profile] === urn) return profile;
31864
+ }
31865
+ //#endregion
31236
31866
  //#region src/index.ts
31237
31867
  /** Whether initWasm has already completed successfully. */
31238
31868
  let wasmInitialized = false;
@@ -31259,15 +31889,15 @@ async function initWasm(options) {
31259
31889
  if (wasmInitialized) return;
31260
31890
  const inits = [];
31261
31891
  if (options.deflate || options.deflateWasm) inits.push((async () => {
31262
- const { initDeflateWasm } = await Promise.resolve().then(() => require("./pdfDocument-Bh4ebDqE.cjs")).then((n) => n.libdeflateWasm_exports);
31892
+ const { initDeflateWasm } = await Promise.resolve().then(() => require("./pdfDocument-Dyj4AmT1.cjs")).then((n) => n.libdeflateWasm_exports);
31263
31893
  await initDeflateWasm(options.deflateWasm);
31264
31894
  })());
31265
31895
  if (options.png || options.pngWasm) inits.push((async () => {
31266
- const { initPngWasm } = await Promise.resolve().then(() => require("./pdfDocument-Bh4ebDqE.cjs")).then((n) => n.pngEmbed_exports);
31896
+ const { initPngWasm } = await Promise.resolve().then(() => require("./pdfDocument-Dyj4AmT1.cjs")).then((n) => n.pngEmbed_exports);
31267
31897
  await initPngWasm(options.pngWasm);
31268
31898
  })());
31269
31899
  if (options.fonts || options.fontWasm) inits.push((async () => {
31270
- const { initSubsetWasm } = await Promise.resolve().then(() => require("./pdfDocument-Bh4ebDqE.cjs")).then((n) => n.fontSubset_exports);
31900
+ const { initSubsetWasm } = await Promise.resolve().then(() => require("./pdfDocument-Dyj4AmT1.cjs")).then((n) => n.fontSubset_exports);
31271
31901
  await initSubsetWasm(options.fontWasm);
31272
31902
  })());
31273
31903
  if (options.jpeg || options.jpegWasm) inits.push((async () => {
@@ -31698,6 +32328,12 @@ Object.defineProperty(exports, "applyTablePreset", {
31698
32328
  return applyTablePreset;
31699
32329
  }
31700
32330
  });
32331
+ Object.defineProperty(exports, "assembleFacturX", {
32332
+ enumerable: true,
32333
+ get: function() {
32334
+ return assembleFacturX;
32335
+ }
32336
+ });
31701
32337
  Object.defineProperty(exports, "assembleTiles", {
31702
32338
  enumerable: true,
31703
32339
  get: function() {
@@ -31770,6 +32406,12 @@ Object.defineProperty(exports, "buildCalRGB", {
31770
32406
  return buildCalRGB;
31771
32407
  }
31772
32408
  });
32409
+ Object.defineProperty(exports, "buildCertPath", {
32410
+ enumerable: true,
32411
+ get: function() {
32412
+ return buildCertPath;
32413
+ }
32414
+ });
31773
32415
  Object.defineProperty(exports, "buildCertificateChain", {
31774
32416
  enumerable: true,
31775
32417
  get: function() {
@@ -31824,6 +32466,12 @@ Object.defineProperty(exports, "buildEncryptedPayload", {
31824
32466
  return buildEncryptedPayload;
31825
32467
  }
31826
32468
  });
32469
+ Object.defineProperty(exports, "buildFacturXXmp", {
32470
+ enumerable: true,
32471
+ get: function() {
32472
+ return buildFacturXXmp;
32473
+ }
32474
+ });
31827
32475
  Object.defineProperty(exports, "buildFieldLockDict", {
31828
32476
  enumerable: true,
31829
32477
  get: function() {
@@ -32160,6 +32808,12 @@ Object.defineProperty(exports, "delinearizePdf", {
32160
32808
  return delinearizePdf;
32161
32809
  }
32162
32810
  });
32811
+ Object.defineProperty(exports, "detectFacturXProfile", {
32812
+ enumerable: true,
32813
+ get: function() {
32814
+ return detectFacturXProfile;
32815
+ }
32816
+ });
32163
32817
  Object.defineProperty(exports, "detectModifications", {
32164
32818
  enumerable: true,
32165
32819
  get: function() {
@@ -32802,6 +33456,12 @@ Object.defineProperty(exports, "parseAcrobatDate", {
32802
33456
  return parseAcrobatDate;
32803
33457
  }
32804
33458
  });
33459
+ Object.defineProperty(exports, "parseCiiXml", {
33460
+ enumerable: true,
33461
+ get: function() {
33462
+ return parseCiiXml;
33463
+ }
33464
+ });
32805
33465
  Object.defineProperty(exports, "parseExistingTrailer", {
32806
33466
  enumerable: true,
32807
33467
  get: function() {
@@ -33246,6 +33906,12 @@ Object.defineProperty(exports, "validateCertificatePolicy", {
33246
33906
  return validateCertificatePolicy;
33247
33907
  }
33248
33908
  });
33909
+ Object.defineProperty(exports, "validateEn16931", {
33910
+ enumerable: true,
33911
+ get: function() {
33912
+ return validateEn16931;
33913
+ }
33914
+ });
33249
33915
  Object.defineProperty(exports, "validateExtendedKeyUsage", {
33250
33916
  enumerable: true,
33251
33917
  get: function() {
@@ -33337,4 +34003,4 @@ Object.defineProperty(exports, "wrapText", {
33337
34003
  }
33338
34004
  });
33339
34005
 
33340
- //# sourceMappingURL=src-CeKIKI1W.cjs.map
34006
+ //# sourceMappingURL=src-PxZwqIKQ.cjs.map