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.
- package/README.md +3 -3
- package/dist/browser.cjs +6 -1
- package/dist/browser.d.cts +2 -2
- package/dist/browser.d.mts +2 -2
- package/dist/browser.mjs +2 -2
- package/dist/{index-Ddc6zdqj.d.mts → index-BJtSRrMf.d.mts} +140 -3
- package/dist/index-BJtSRrMf.d.mts.map +1 -0
- package/dist/{index-JejepHCR.d.cts → index-BqYQ9lsY.d.cts} +140 -3
- package/dist/index-BqYQ9lsY.d.cts.map +1 -0
- package/dist/index.cjs +6 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{src-CeKIKI1W.cjs → src-BdVnpRoy.cjs} +548 -128
- package/dist/{src-DNe0XZhx.mjs → src-zeRl33xQ.mjs} +519 -129
- package/package.json +1 -1
- package/dist/index-Ddc6zdqj.d.mts.map +0 -1
- package/dist/index-JejepHCR.d.cts.map +0 -1
|
@@ -75,7 +75,7 @@ var ChangeTracker = class {
|
|
|
75
75
|
return this.newObjects.union(this.modifiedObjects).size;
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
|
-
const encoder$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
630
|
-
if (meta.keywords !== void 0) lines.push(` <pdf:Keywords>${escapeXml$
|
|
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(/</g, "<").replace(/>/g, ">").replace(/"/g, "\"").replace(/'/g, "'").replace(/&/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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
4205
|
+
return encoder$9.encode(appendix);
|
|
4206
4206
|
}
|
|
4207
4207
|
//#endregion
|
|
4208
4208
|
//#region src/signature/incrementalOptimizer.ts
|
|
4209
|
-
const encoder$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
4859
|
-
const footerBytes = encoder$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
5520
|
+
parts.push(encoder$6.encode(metaRef));
|
|
5521
5521
|
parts.push(data.subarray(catalogEnd));
|
|
5522
|
-
parts.push(encoder$
|
|
5523
|
-
parts.push(encoder$
|
|
5522
|
+
parts.push(encoder$6.encode("\n"));
|
|
5523
|
+
parts.push(encoder$6.encode(metaObj + "\n"));
|
|
5524
5524
|
parts.push(xmpBytes);
|
|
5525
|
-
parts.push(encoder$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
7020
|
+
const encoder$3 = new TextEncoder();
|
|
7021
7021
|
/** Escape XML special characters in a string. */
|
|
7022
|
-
function escapeXml$
|
|
7022
|
+
function escapeXml$5(str) {
|
|
7023
7023
|
return str.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
7084
|
-
if (options.keywords) xmp += ` <pdf:Keywords>${escapeXml$
|
|
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$
|
|
7102
|
+
return encoder$3.encode(generatePdfAXmp(options));
|
|
7103
7103
|
}
|
|
7104
7104
|
//#endregion
|
|
7105
7105
|
//#region src/compliance/enforcePdfAv2.ts
|
|
7106
|
-
const encoder$
|
|
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$
|
|
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$
|
|
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$
|
|
7160
|
+
const ref = encoder$2.encode(metaRef);
|
|
7161
7161
|
const after = data.subarray(catalogEnd);
|
|
7162
|
-
const stream = encoder$
|
|
7163
|
-
const end = encoder$
|
|
7164
|
-
return concatBytes(before, ref, after, encoder$
|
|
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$
|
|
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$
|
|
20878
|
+
function escapeXml$4(str) {
|
|
20879
20879
|
return str.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
21039
|
-
out.push(` <ram:TaxBasisTotalAmount currencyID="${escapeXml$
|
|
21040
|
-
out.push(` <ram:TaxTotalAmount currencyID="${escapeXml$
|
|
21041
|
-
out.push(` <ram:GrandTotalAmount currencyID="${escapeXml$
|
|
21042
|
-
out.push(` <ram:DuePayableAmount currencyID="${escapeXml$
|
|
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$
|
|
21264
|
+
function escapeXml$3(str) {
|
|
21265
21265
|
return str.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
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$
|
|
21283
|
-
out += ` <pdfaSchema:namespaceURI>${escapeXml$
|
|
21284
|
-
out += ` <pdfaSchema:prefix>${escapeXml$
|
|
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$
|
|
21290
|
-
out += ` <pdfaProperty:valueType>${escapeXml$
|
|
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$
|
|
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$
|
|
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$
|
|
21403
|
+
function escapeXml$2(str) {
|
|
21404
21404
|
return str.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
21520
|
-
out.push(` <ram:TaxBasisTotalAmount currencyID="${escapeXml$
|
|
21521
|
-
out.push(` <ram:TaxTotalAmount currencyID="${escapeXml$
|
|
21522
|
-
out.push(` <ram:GrandTotalAmount currencyID="${escapeXml$
|
|
21523
|
-
out.push(` <ram:DuePayableAmount currencyID="${escapeXml$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
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("<", "<").replaceAll(">", ">").replaceAll(""", "\"").replaceAll("'", "'").replaceAll("&", "&");
|
|
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-
|
|
33760
|
+
//# sourceMappingURL=src-BdVnpRoy.cjs.map
|