modern-pdf-lib 0.32.0 → 0.33.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.
@@ -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);
@@ -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.
@@ -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>");
@@ -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
@@ -31141,7 +31141,7 @@ const WTPDF_CONFORMS_TO_BASE = "http://pdfa.org/declarations/wtpdf#";
31141
31141
  */
31142
31142
  const PDFR_CONFORMS_TO = "http://pdfa.org/declarations/pdfr#1.0";
31143
31143
  /** Escape XML special characters in a string. */
31144
- function escapeXml(str) {
31144
+ function escapeXml$1(str) {
31145
31145
  return str.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
31146
31146
  }
31147
31147
  /**
@@ -31159,14 +31159,14 @@ function buildIdentificationXmp(identity) {
31159
31159
  const { profileName, conformsTo, part, conformance } = identity;
31160
31160
  let xmp = "<?xpacket begin=\"\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n";
31161
31161
  xmp += "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\">\n";
31162
- xmp += ` <!-- ${escapeXml(profileName)} identification marker (non-normative). -->\n`;
31162
+ xmp += ` <!-- ${escapeXml$1(profileName)} identification marker (non-normative). -->\n`;
31163
31163
  xmp += " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n";
31164
31164
  xmp += " <rdf:Description rdf:about=\"\"\n";
31165
31165
  xmp += ` xmlns:pdfd="${PDFD_NS}">\n`;
31166
31166
  xmp += " <pdfd:declarations>\n";
31167
31167
  xmp += " <rdf:Bag>\n";
31168
31168
  xmp += " <rdf:li rdf:parseType=\"Resource\">\n";
31169
- xmp += ` <pdfd:conformsTo>${escapeXml(conformsTo)}</pdfd:conformsTo>\n`;
31169
+ xmp += ` <pdfd:conformsTo>${escapeXml$1(conformsTo)}</pdfd:conformsTo>\n`;
31170
31170
  xmp += " </rdf:li>\n";
31171
31171
  xmp += " </rdf:Bag>\n";
31172
31172
  xmp += " </pdfd:declarations>\n";
@@ -31174,7 +31174,7 @@ function buildIdentificationXmp(identity) {
31174
31174
  xmp += " <rdf:Description rdf:about=\"\"\n";
31175
31175
  xmp += " xmlns:pid=\"http://modern-pdf-lib/ns/profile-id/\">\n";
31176
31176
  xmp += ` <pid:part>${part}</pid:part>\n`;
31177
- if (conformance !== void 0) xmp += ` <pid:conformance>${escapeXml(conformance)}</pid:conformance>\n`;
31177
+ if (conformance !== void 0) xmp += ` <pid:conformance>${escapeXml$1(conformance)}</pid:conformance>\n`;
31178
31178
  xmp += " </rdf:Description>\n";
31179
31179
  xmp += " </rdf:RDF>\n";
31180
31180
  xmp += "</x:xmpmeta>\n";
@@ -31233,6 +31233,396 @@ function buildPdfRIdentificationXmp(options) {
31233
31233
  });
31234
31234
  }
31235
31235
  //#endregion
31236
+ //#region src/compliance/facturXAssemble.ts
31237
+ /** Default profile when none is supplied. */
31238
+ const DEFAULT_PROFILE = "EN16931";
31239
+ /** Default embedded XML file name mandated by the Factur-X specification. */
31240
+ const DEFAULT_FILENAME = "factur-x.xml";
31241
+ /** Factur-X XMP extension-schema namespace URI (verified). */
31242
+ const FX_NAMESPACE_URI = "urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#";
31243
+ /** Factur-X XML schema version carried in `fx:Version` (verified: `1.0`). */
31244
+ const FX_VERSION = "1.0";
31245
+ /**
31246
+ * `fx:ConformanceLevel` strings keyed by profile.
31247
+ *
31248
+ * These are the human-readable profile names defined by the Factur-X
31249
+ * specification (note the embedded spaces in `BASIC WL` and `EN 16931`),
31250
+ * which differ from this library's internal {@link FacturXProfile} enum
31251
+ * tokens (`'BASIC-WL'`, `'EN16931'`). Verified against the Factur-X 1.0
31252
+ * specification.
31253
+ */
31254
+ const CONFORMANCE_LEVELS = {
31255
+ MINIMUM: "MINIMUM",
31256
+ "BASIC-WL": "BASIC WL",
31257
+ BASIC: "BASIC",
31258
+ EN16931: "EN 16931",
31259
+ EXTENDED: "EXTENDED"
31260
+ };
31261
+ const encoder = new TextEncoder();
31262
+ /** Escape XML special characters in a text value. */
31263
+ function escapeXml(str) {
31264
+ return str.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
31265
+ }
31266
+ /**
31267
+ * Build the Factur-X PDF/A-3 XMP extension metadata.
31268
+ *
31269
+ * Returns an XMP RDF fragment containing two `rdf:Description` blocks:
31270
+ *
31271
+ * 1. The **actual Factur-X values** in the `fx:` namespace —
31272
+ * `fx:DocumentType` (`INVOICE`), `fx:DocumentFileName`, `fx:Version`
31273
+ * (`1.0`) and `fx:ConformanceLevel` (derived from `profile`).
31274
+ * 2. The **PDF/A extension-schema description** (`pdfaExtension:schemas`),
31275
+ * which is required for PDF/A-3 conformance so that validators can resolve
31276
+ * the custom `fx:` properties.
31277
+ *
31278
+ * The fragment is rooted at `<rdf:RDF>` so it can be merged into a larger XMP
31279
+ * packet (e.g. alongside the `pdfaid`, `dc`, `xmp` and `pdf` descriptions
31280
+ * produced by the PDF/A XMP generator).
31281
+ *
31282
+ * @param profile The Factur-X / ZUGFeRD profile.
31283
+ * @param documentFileName The embedded XML file name. Must match the name under
31284
+ * which the XML is attached. Default: `'factur-x.xml'`.
31285
+ * @returns The XMP RDF string.
31286
+ */
31287
+ function buildFacturXXmp(profile, documentFileName = DEFAULT_FILENAME) {
31288
+ const conformanceLevel = CONFORMANCE_LEVELS[profile];
31289
+ const fileName = escapeXml(documentFileName);
31290
+ const out = [];
31291
+ out.push("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">");
31292
+ out.push(` <rdf:Description rdf:about="" xmlns:fx="${FX_NAMESPACE_URI}">`);
31293
+ out.push(` <fx:ConformanceLevel>${escapeXml(conformanceLevel)}</fx:ConformanceLevel>`);
31294
+ out.push(` <fx:DocumentFileName>${fileName}</fx:DocumentFileName>`);
31295
+ out.push(" <fx:DocumentType>INVOICE</fx:DocumentType>");
31296
+ out.push(` <fx:Version>${FX_VERSION}</fx:Version>`);
31297
+ out.push(" </rdf:Description>");
31298
+ out.push(" <rdf:Description rdf:about=\"\"");
31299
+ out.push(" xmlns:pdfaExtension=\"http://www.aiim.org/pdfa/ns/extension/\"");
31300
+ out.push(" xmlns:pdfaSchema=\"http://www.aiim.org/pdfa/ns/schema#\"");
31301
+ out.push(" xmlns:pdfaProperty=\"http://www.aiim.org/pdfa/ns/property#\">");
31302
+ out.push(" <pdfaExtension:schemas>");
31303
+ out.push(" <rdf:Bag>");
31304
+ out.push(" <rdf:li rdf:parseType=\"Resource\">");
31305
+ out.push(" <pdfaSchema:schema>Factur-X PDFA Extension Schema</pdfaSchema:schema>");
31306
+ out.push(` <pdfaSchema:namespaceURI>${FX_NAMESPACE_URI}</pdfaSchema:namespaceURI>`);
31307
+ out.push(" <pdfaSchema:prefix>fx</pdfaSchema:prefix>");
31308
+ out.push(" <pdfaSchema:property>");
31309
+ out.push(" <rdf:Seq>");
31310
+ for (const [name, description] of [
31311
+ ["DocumentFileName", "name of the embedded XML invoice file"],
31312
+ ["DocumentType", "INVOICE"],
31313
+ ["Version", "The actual version of the Factur-X XML schema"],
31314
+ ["ConformanceLevel", "The conformance level of the embedded Factur-X data"]
31315
+ ]) {
31316
+ out.push(" <rdf:li rdf:parseType=\"Resource\">");
31317
+ out.push(` <pdfaProperty:name>${name}</pdfaProperty:name>`);
31318
+ out.push(" <pdfaProperty:valueType>Text</pdfaProperty:valueType>");
31319
+ out.push(" <pdfaProperty:category>external</pdfaProperty:category>");
31320
+ out.push(` <pdfaProperty:description>${escapeXml(description)}</pdfaProperty:description>`);
31321
+ out.push(" </rdf:li>");
31322
+ }
31323
+ out.push(" </rdf:Seq>");
31324
+ out.push(" </pdfaSchema:property>");
31325
+ out.push(" </rdf:li>");
31326
+ out.push(" </rdf:Bag>");
31327
+ out.push(" </pdfaExtension:schemas>");
31328
+ out.push(" </rdf:Description>");
31329
+ out.push("</rdf:RDF>");
31330
+ return out.join("\n");
31331
+ }
31332
+ /**
31333
+ * Assemble a hybrid Factur-X PDF/A-3 invoice.
31334
+ *
31335
+ * Generates the CII XML for `invoice` under the requested profile, encodes it
31336
+ * as UTF-8 bytes and attaches it to `doc` as a PDF/A-3 associated file with the
31337
+ * `/Alternative` relationship (referenced from the catalog `/AF` array).
31338
+ *
31339
+ * The XMP from {@link buildFacturXXmp} can be merged into the document's
31340
+ * metadata by the caller to complete PDF/A-3 / Factur-X conformance.
31341
+ *
31342
+ * @param doc The target PDF document (should already be PDF/A-3 shaped).
31343
+ * @param invoice The invoice data.
31344
+ * @param options Optional profile and embedded file name.
31345
+ * @returns The generated CII XML string.
31346
+ */
31347
+ function assembleFacturX(doc, invoice, options) {
31348
+ const profile = options?.profile ?? DEFAULT_PROFILE;
31349
+ const filename = options?.filename ?? DEFAULT_FILENAME;
31350
+ const xml = generateCiiXml(invoice, profile);
31351
+ const bytes = encoder.encode(xml);
31352
+ doc.addAssociatedFile(filename, bytes, "text/xml", "Alternative", { description: "Factur-X invoice data" });
31353
+ return xml;
31354
+ }
31355
+ //#endregion
31356
+ //#region src/compliance/eInvoiceValidate.ts
31357
+ /**
31358
+ * Monetary comparison tolerance, in the invoice currency's major unit.
31359
+ * EN 16931 amounts are rounded to two decimals; half a cent of slack
31360
+ * absorbs accumulated floating-point and rounding noise.
31361
+ */
31362
+ const MONETARY_TOLERANCE = .005;
31363
+ /** True when `value` is a non-empty, non-whitespace string. */
31364
+ function isNonEmptyText(value) {
31365
+ return value.trim().length > 0;
31366
+ }
31367
+ /** True when two monetary amounts are equal within {@link MONETARY_TOLERANCE}. */
31368
+ function amountsEqual(a, b) {
31369
+ return Math.abs(a - b) <= MONETARY_TOLERANCE;
31370
+ }
31371
+ /** Sum the line net amounts (Σ quantity × unit price) of an invoice. */
31372
+ function sumLineNet(invoice) {
31373
+ let total = 0;
31374
+ for (const line of invoice.lines) total += line.quantity * line.unitPrice;
31375
+ return total;
31376
+ }
31377
+ /**
31378
+ * Validate an invoice against the core EN 16931 business rules that are
31379
+ * checkable from the typed {@link Invoice} model.
31380
+ *
31381
+ * Content-presence rules (BR-02, BR-03, BR-05, BR-06, BR-07, BR-16) are
31382
+ * always evaluated. The totals-calculation chain (BR-CO-10, BR-CO-13,
31383
+ * BR-CO-15, BR-CO-16) is only evaluated when the caller supplies
31384
+ * {@link ValidatableInvoice.declaredTotals}; otherwise those checks are
31385
+ * skipped because the model derives consistent totals from its lines.
31386
+ *
31387
+ * The function never throws; a structurally valid invoice returns `[]`.
31388
+ *
31389
+ * @param invoice - The invoice (optionally annotated with declared totals).
31390
+ * @returns A list of {@link EInvoiceIssue}s, empty when fully valid.
31391
+ */
31392
+ function validateEn16931(invoice) {
31393
+ const issues = [];
31394
+ if (!isNonEmptyText(invoice.invoiceNumber)) issues.push({
31395
+ rule: "BR-02",
31396
+ message: "An Invoice shall have an Invoice number (BT-1).",
31397
+ severity: "error"
31398
+ });
31399
+ if (!isNonEmptyText(invoice.issueDate)) issues.push({
31400
+ rule: "BR-03",
31401
+ message: "An Invoice shall have an Invoice issue date (BT-2).",
31402
+ severity: "error"
31403
+ });
31404
+ if (!isNonEmptyText(invoice.currency)) issues.push({
31405
+ rule: "BR-05",
31406
+ message: "An Invoice shall have an Invoice currency code (BT-5).",
31407
+ severity: "error"
31408
+ });
31409
+ if (!isNonEmptyText(invoice.seller.name)) issues.push({
31410
+ rule: "BR-06",
31411
+ message: "An Invoice shall contain the Seller name (BT-27).",
31412
+ severity: "error"
31413
+ });
31414
+ if (!isNonEmptyText(invoice.buyer.name)) issues.push({
31415
+ rule: "BR-07",
31416
+ message: "An Invoice shall contain the Buyer name (BT-44).",
31417
+ severity: "error"
31418
+ });
31419
+ if (invoice.lines.length === 0) issues.push({
31420
+ rule: "BR-16",
31421
+ message: "An Invoice shall have at least one Invoice line (BG-25).",
31422
+ severity: "error"
31423
+ });
31424
+ const declared = invoice.declaredTotals;
31425
+ if (declared !== void 0) {
31426
+ const computedLineNet = sumLineNet(invoice);
31427
+ const taxBasisTotal = declared.taxBasisTotal ?? declared.lineTotal;
31428
+ const duePayable = declared.duePayable ?? declared.grandTotal;
31429
+ if (!amountsEqual(declared.lineTotal, computedLineNet)) issues.push({
31430
+ rule: "BR-CO-10",
31431
+ 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)}.`,
31432
+ severity: "error"
31433
+ });
31434
+ if (!amountsEqual(taxBasisTotal, computedLineNet)) issues.push({
31435
+ rule: "BR-CO-13",
31436
+ 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)}.`,
31437
+ severity: "error"
31438
+ });
31439
+ const expectedGrand = taxBasisTotal + declared.taxTotal;
31440
+ if (!amountsEqual(declared.grandTotal, expectedGrand)) issues.push({
31441
+ rule: "BR-CO-15",
31442
+ 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)}.`,
31443
+ severity: "error"
31444
+ });
31445
+ if (!amountsEqual(duePayable, declared.grandTotal)) issues.push({
31446
+ rule: "BR-CO-16",
31447
+ 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)}.`,
31448
+ severity: "error"
31449
+ });
31450
+ }
31451
+ return issues;
31452
+ }
31453
+ //#endregion
31454
+ //#region src/compliance/ciiReader.ts
31455
+ /**
31456
+ * Guideline URNs keyed by profile.
31457
+ *
31458
+ * This mirrors the (non-exported) table in {@link module:compliance/facturX}
31459
+ * and is used to reverse-map a `GuidelineSpecifiedDocumentContextParameter/ID`
31460
+ * value back to a {@link FacturXProfile}.
31461
+ */
31462
+ const GUIDELINE_URNS = {
31463
+ MINIMUM: "urn:factur-x.eu:1p0:minimum",
31464
+ "BASIC-WL": "urn:factur-x.eu:1p0:basicwl",
31465
+ BASIC: "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic",
31466
+ EN16931: "urn:cen.eu:en16931:2017",
31467
+ EXTENDED: "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended"
31468
+ };
31469
+ /** Reverse of the generator's XML escaping. */
31470
+ function unescapeXml(str) {
31471
+ return str.replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&quot;", "\"").replaceAll("&apos;", "'").replaceAll("&amp;", "&");
31472
+ }
31473
+ /** Escape a string for safe inclusion in a RegExp. */
31474
+ function escapeRegExp(str) {
31475
+ return str.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
31476
+ }
31477
+ /**
31478
+ * Build a RegExp that matches `<[prefix:]name …>content</[prefix:]name>`
31479
+ * for the given local element name, ignoring any namespace prefix and
31480
+ * any attributes on the opening tag. The first capture group is the
31481
+ * (raw, still-escaped) inner content.
31482
+ */
31483
+ function elementRegExp(localName) {
31484
+ const n = escapeRegExp(localName);
31485
+ return new RegExp(`<(?:[\\w.-]+:)?${n}(?:\\s[^>]*)?>([\\s\\S]*?)</(?:[\\w.-]+:)?${n}>`);
31486
+ }
31487
+ /**
31488
+ * Extract the inner text of the first matching element (by local name)
31489
+ * within the given XML fragment, unescaped. Returns `undefined` if the
31490
+ * element is absent.
31491
+ */
31492
+ function firstText(xml, localName) {
31493
+ const match = elementRegExp(localName).exec(xml);
31494
+ if (match === null) return void 0;
31495
+ const inner = match[1];
31496
+ if (inner === void 0) return void 0;
31497
+ return unescapeXml(inner.trim());
31498
+ }
31499
+ /**
31500
+ * Extract the inner XML fragment (still containing child markup) of the
31501
+ * first matching element by local name. Returns `undefined` if absent.
31502
+ */
31503
+ function firstFragment(xml, localName) {
31504
+ const match = elementRegExp(localName).exec(xml);
31505
+ if (match === null) return void 0;
31506
+ return match[1] ?? void 0;
31507
+ }
31508
+ /**
31509
+ * Extract every non-overlapping block matching the given local element
31510
+ * name, returning each block's inner XML fragment.
31511
+ */
31512
+ function allFragments(xml, localName) {
31513
+ const n = escapeRegExp(localName);
31514
+ const re = new RegExp(`<(?:[\\w.-]+:)?${n}(?:\\s[^>]*)?>([\\s\\S]*?)</(?:[\\w.-]+:)?${n}>`, "g");
31515
+ const out = [];
31516
+ let match = re.exec(xml);
31517
+ while (match !== null) {
31518
+ const inner = match[1];
31519
+ if (inner !== void 0) out.push(inner);
31520
+ match = re.exec(xml);
31521
+ }
31522
+ return out;
31523
+ }
31524
+ /**
31525
+ * Parse a numeric text value, returning `0` when the value is missing or
31526
+ * not a finite number.
31527
+ */
31528
+ function parseNumber(text) {
31529
+ if (text === void 0) return 0;
31530
+ const value = Number.parseFloat(text);
31531
+ return Number.isFinite(value) ? value : 0;
31532
+ }
31533
+ /**
31534
+ * Convert a UN/CEFACT date-format-102 string (`YYYYMMDD`) to an ISO date
31535
+ * string (`YYYY-MM-DD`). Inputs that are not 8 digits are returned
31536
+ * unchanged (best effort).
31537
+ */
31538
+ function fromDateString102(value) {
31539
+ const digits = value.replaceAll(/[^0-9]/g, "");
31540
+ if (digits.length !== 8) return value;
31541
+ return `${digits.slice(0, 4)}-${digits.slice(4, 6)}-${digits.slice(6, 8)}`;
31542
+ }
31543
+ /** Parse a single trade-party fragment into an {@link InvoiceParty}. */
31544
+ function parseParty(fragment) {
31545
+ const name = firstText(fragment, "Name") ?? "";
31546
+ const countryCode = firstText(fragment, "CountryID") ?? "";
31547
+ const taxReg = firstFragment(fragment, "SpecifiedTaxRegistration");
31548
+ const vatId = taxReg !== void 0 ? firstText(taxReg, "ID") : void 0;
31549
+ return vatId !== void 0 && vatId !== "" ? {
31550
+ name,
31551
+ countryCode,
31552
+ vatId
31553
+ } : {
31554
+ name,
31555
+ countryCode
31556
+ };
31557
+ }
31558
+ /** Parse a single line-item fragment into an {@link InvoiceLine}. */
31559
+ function parseLine(fragment) {
31560
+ const productFragment = firstFragment(fragment, "SpecifiedTradeProduct");
31561
+ const description = (productFragment !== void 0 ? firstText(productFragment, "Name") : firstText(fragment, "Name")) ?? "";
31562
+ const priceFragment = firstFragment(fragment, "NetPriceProductTradePrice");
31563
+ const unitPrice = parseNumber(priceFragment !== void 0 ? firstText(priceFragment, "ChargeAmount") : firstText(fragment, "ChargeAmount"));
31564
+ return {
31565
+ description,
31566
+ quantity: parseNumber(firstText(fragment, "BilledQuantity")),
31567
+ unitPrice,
31568
+ taxPercent: parseNumber(firstText(fragment, "RateApplicablePercent"))
31569
+ };
31570
+ }
31571
+ /**
31572
+ * Parse a UN/CEFACT Cross Industry Invoice (CII) XML string into the
31573
+ * typed {@link Invoice} model.
31574
+ *
31575
+ * The parser is namespace-prefix tolerant (it matches on local element
31576
+ * names) and recovers the invoice number, issue date, currency, the
31577
+ * seller and buyer parties (name, country, VAT id) and every line item
31578
+ * (description, quantity, unit price, tax rate).
31579
+ *
31580
+ * @param xml - The CII XML document.
31581
+ * @returns The parsed {@link Invoice}.
31582
+ * @throws If the input does not contain a `CrossIndustryInvoice` root.
31583
+ */
31584
+ function parseCiiXml(xml) {
31585
+ const root = firstFragment(xml, "CrossIndustryInvoice");
31586
+ if (root === void 0) throw new Error("ciiReader: not a CrossIndustryInvoice document (no <CrossIndustryInvoice> root element found).");
31587
+ const docFragment = firstFragment(root, "ExchangedDocument") ?? root;
31588
+ const invoiceNumber = firstText(docFragment, "ID") ?? "";
31589
+ const issueRaw = firstText(docFragment, "DateTimeString") ?? "";
31590
+ const issueDate = issueRaw === "" ? "" : fromDateString102(issueRaw);
31591
+ const currency = firstText(root, "InvoiceCurrencyCode") ?? "";
31592
+ const sellerFragment = firstFragment(root, "SellerTradeParty");
31593
+ const buyerFragment = firstFragment(root, "BuyerTradeParty");
31594
+ return {
31595
+ invoiceNumber,
31596
+ issueDate,
31597
+ currency,
31598
+ seller: sellerFragment !== void 0 ? parseParty(sellerFragment) : {
31599
+ name: "",
31600
+ countryCode: ""
31601
+ },
31602
+ buyer: buyerFragment !== void 0 ? parseParty(buyerFragment) : {
31603
+ name: "",
31604
+ countryCode: ""
31605
+ },
31606
+ lines: allFragments(root, "IncludedSupplyChainTradeLineItem").map(parseLine)
31607
+ };
31608
+ }
31609
+ /**
31610
+ * Detect the Factur-X / ZUGFeRD profile of a CII XML document by reading
31611
+ * its `GuidelineSpecifiedDocumentContextParameter/ID` (the profile URN)
31612
+ * and mapping it back to a {@link FacturXProfile}.
31613
+ *
31614
+ * @param xml - The CII XML document.
31615
+ * @returns The matching {@link FacturXProfile}, or `undefined` if no
31616
+ * guideline URN is present or it does not match a known profile.
31617
+ */
31618
+ function detectFacturXProfile(xml) {
31619
+ const contextFragment = firstFragment(xml, "GuidelineSpecifiedDocumentContextParameter");
31620
+ if (contextFragment === void 0) return void 0;
31621
+ const urn = firstText(contextFragment, "ID");
31622
+ if (urn === void 0 || urn === "") return void 0;
31623
+ for (const profile of Object.keys(GUIDELINE_URNS)) if (GUIDELINE_URNS[profile] === urn) return profile;
31624
+ }
31625
+ //#endregion
31236
31626
  //#region src/index.ts
31237
31627
  /** Whether initWasm has already completed successfully. */
31238
31628
  let wasmInitialized = false;
@@ -31698,6 +32088,12 @@ Object.defineProperty(exports, "applyTablePreset", {
31698
32088
  return applyTablePreset;
31699
32089
  }
31700
32090
  });
32091
+ Object.defineProperty(exports, "assembleFacturX", {
32092
+ enumerable: true,
32093
+ get: function() {
32094
+ return assembleFacturX;
32095
+ }
32096
+ });
31701
32097
  Object.defineProperty(exports, "assembleTiles", {
31702
32098
  enumerable: true,
31703
32099
  get: function() {
@@ -31824,6 +32220,12 @@ Object.defineProperty(exports, "buildEncryptedPayload", {
31824
32220
  return buildEncryptedPayload;
31825
32221
  }
31826
32222
  });
32223
+ Object.defineProperty(exports, "buildFacturXXmp", {
32224
+ enumerable: true,
32225
+ get: function() {
32226
+ return buildFacturXXmp;
32227
+ }
32228
+ });
31827
32229
  Object.defineProperty(exports, "buildFieldLockDict", {
31828
32230
  enumerable: true,
31829
32231
  get: function() {
@@ -32160,6 +32562,12 @@ Object.defineProperty(exports, "delinearizePdf", {
32160
32562
  return delinearizePdf;
32161
32563
  }
32162
32564
  });
32565
+ Object.defineProperty(exports, "detectFacturXProfile", {
32566
+ enumerable: true,
32567
+ get: function() {
32568
+ return detectFacturXProfile;
32569
+ }
32570
+ });
32163
32571
  Object.defineProperty(exports, "detectModifications", {
32164
32572
  enumerable: true,
32165
32573
  get: function() {
@@ -32802,6 +33210,12 @@ Object.defineProperty(exports, "parseAcrobatDate", {
32802
33210
  return parseAcrobatDate;
32803
33211
  }
32804
33212
  });
33213
+ Object.defineProperty(exports, "parseCiiXml", {
33214
+ enumerable: true,
33215
+ get: function() {
33216
+ return parseCiiXml;
33217
+ }
33218
+ });
32805
33219
  Object.defineProperty(exports, "parseExistingTrailer", {
32806
33220
  enumerable: true,
32807
33221
  get: function() {
@@ -33246,6 +33660,12 @@ Object.defineProperty(exports, "validateCertificatePolicy", {
33246
33660
  return validateCertificatePolicy;
33247
33661
  }
33248
33662
  });
33663
+ Object.defineProperty(exports, "validateEn16931", {
33664
+ enumerable: true,
33665
+ get: function() {
33666
+ return validateEn16931;
33667
+ }
33668
+ });
33249
33669
  Object.defineProperty(exports, "validateExtendedKeyUsage", {
33250
33670
  enumerable: true,
33251
33671
  get: function() {
@@ -33337,4 +33757,4 @@ Object.defineProperty(exports, "wrapText", {
33337
33757
  }
33338
33758
  });
33339
33759
 
33340
- //# sourceMappingURL=src-CeKIKI1W.cjs.map
33760
+ //# sourceMappingURL=src-BdVnpRoy.cjs.map