@formfeed/engine 0.3.11 → 0.3.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/index.cjs +2414 -241
  2. package/index.js +2414 -241
  3. package/package.json +3 -2
  4. package/types/frame/text-edit.d.cts +8 -1
  5. package/types/frame/text-edit.d.ts +8 -1
  6. package/types/index.d.cts +3 -1
  7. package/types/index.d.ts +3 -1
  8. package/types/lib/assemble.d.cts +8 -0
  9. package/types/lib/assemble.d.ts +8 -0
  10. package/types/lib/einvoice/check.d.cts +181 -0
  11. package/types/lib/einvoice/check.d.ts +181 -0
  12. package/types/lib/einvoice/cii.d.cts +18 -0
  13. package/types/lib/einvoice/cii.d.ts +18 -0
  14. package/types/lib/einvoice/codes.generated.d.cts +14 -0
  15. package/types/lib/einvoice/codes.generated.d.ts +14 -0
  16. package/types/lib/einvoice/decimal.d.cts +29 -0
  17. package/types/lib/einvoice/decimal.d.ts +29 -0
  18. package/types/lib/einvoice/display.d.cts +43 -0
  19. package/types/lib/einvoice/display.d.ts +43 -0
  20. package/types/lib/einvoice/html-text.d.cts +17 -0
  21. package/types/lib/einvoice/html-text.d.ts +17 -0
  22. package/types/lib/einvoice/index.d.cts +45 -0
  23. package/types/lib/einvoice/index.d.ts +45 -0
  24. package/types/lib/einvoice/locate.d.cts +21 -0
  25. package/types/lib/einvoice/locate.d.ts +21 -0
  26. package/types/lib/einvoice/report.d.cts +59 -0
  27. package/types/lib/einvoice/report.d.ts +59 -0
  28. package/types/lib/einvoice/schema.d.cts +293 -0
  29. package/types/lib/einvoice/schema.d.ts +293 -0
  30. package/types/lib/einvoice/skeleton.d.cts +10 -0
  31. package/types/lib/einvoice/skeleton.d.ts +10 -0
  32. package/types/lib/generated/frames.d.cts +2 -2
  33. package/types/lib/generated/frames.d.ts +2 -2
  34. package/types/lib/preview.d.cts +6 -0
  35. package/types/lib/preview.d.ts +6 -0
  36. package/types/lib/source-edit.d.cts +5 -0
  37. package/types/lib/source-edit.d.ts +5 -0
package/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  // packages/engine/src/lib/errors.ts
2
2
  var EngineSyntaxError = class extends Error {
3
- constructor(engine, message, line, column) {
3
+ constructor(engine, message, line2, column) {
4
4
  super(message);
5
5
  this.engine = engine;
6
- this.line = line;
6
+ this.line = line2;
7
7
  this.column = column;
8
8
  }
9
9
  name = "EngineSyntaxError";
@@ -19,10 +19,10 @@ var RenderLimitError = class extends Error {
19
19
  name = "RenderLimitError";
20
20
  };
21
21
  var RenderError = class extends Error {
22
- constructor(engine, message, line, column) {
22
+ constructor(engine, message, line2, column) {
23
23
  super(message);
24
24
  this.engine = engine;
25
- this.line = line;
25
+ this.line = line2;
26
26
  this.column = column;
27
27
  }
28
28
  name = "RenderError";
@@ -91,7 +91,7 @@ function toNumber(value) {
91
91
 
92
92
  // packages/engine/src/lib/codes/epc.ts
93
93
  function epcPayload(input) {
94
- const amount = input.amount === void 0 || input.amount === "" ? "" : `EUR${toNumber(input.amount).toFixed(2)}`;
94
+ const amount2 = input.amount === void 0 || input.amount === "" ? "" : `EUR${toNumber(input.amount).toFixed(2)}`;
95
95
  return [
96
96
  "BCD",
97
97
  "002",
@@ -100,7 +100,7 @@ function epcPayload(input) {
100
100
  (input.bic ?? "").replace(/\s/g, ""),
101
101
  String(input.name ?? "").slice(0, 70),
102
102
  String(input.iban ?? "").replace(/\s/g, ""),
103
- amount,
103
+ amount2,
104
104
  (input.purpose ?? "").slice(0, 4),
105
105
  (input.reference ?? "").slice(0, 35),
106
106
  input.reference ? "" : (input.text ?? "").slice(0, 140),
@@ -150,9 +150,9 @@ var IBAN_LENGTHS = {
150
150
  };
151
151
  var EPC_MAX_BYTES = 331;
152
152
  var byteLength = (value) => new TextEncoder().encode(value).length;
153
- var normaliseIban = (iban) => iban.replace(/\s/g, "").toUpperCase();
154
- function ibanChecksum(iban) {
155
- const rearranged = normaliseIban(iban).slice(4) + normaliseIban(iban).slice(0, 4);
153
+ var normaliseIban = (iban2) => iban2.replace(/\s/g, "").toUpperCase();
154
+ function ibanChecksum(iban2) {
155
+ const rearranged = normaliseIban(iban2).slice(4) + normaliseIban(iban2).slice(0, 4);
156
156
  const digits = [...rearranged].map((c) => c >= "A" && c <= "Z" ? String(c.charCodeAt(0) - 55) : c).join("");
157
157
  let remainder = 0;
158
158
  for (const digit of digits) remainder = (remainder * 10 + Number(digit)) % 97;
@@ -163,30 +163,30 @@ function validateEpc(input) {
163
163
  const name = String(input.name ?? "").trim();
164
164
  if (!name) problems.push({ field: "name", code: "required" });
165
165
  else if (name.length > 70) problems.push({ field: "name", code: "too_long", max: 70, actual: name.length });
166
- const iban = normaliseIban(String(input.iban ?? ""));
167
- if (!iban) problems.push({ field: "iban", code: "required" });
168
- else if (!/^[A-Z]{2}[0-9]{2}[A-Z0-9]{11,30}$/.test(iban)) problems.push({ field: "iban", code: "iban_characters" });
166
+ const iban2 = normaliseIban(String(input.iban ?? ""));
167
+ if (!iban2) problems.push({ field: "iban", code: "required" });
168
+ else if (!/^[A-Z]{2}[0-9]{2}[A-Z0-9]{11,30}$/.test(iban2)) problems.push({ field: "iban", code: "iban_characters" });
169
169
  else {
170
- const expected = IBAN_LENGTHS[iban.slice(0, 2)];
171
- if (expected !== void 0 && iban.length !== expected)
172
- problems.push({ field: "iban", code: "iban_country_length", max: expected, actual: iban.length });
173
- else if (!ibanChecksum(iban)) problems.push({ field: "iban", code: "iban_checksum" });
170
+ const expected = IBAN_LENGTHS[iban2.slice(0, 2)];
171
+ if (expected !== void 0 && iban2.length !== expected)
172
+ problems.push({ field: "iban", code: "iban_country_length", max: expected, actual: iban2.length });
173
+ else if (!ibanChecksum(iban2)) problems.push({ field: "iban", code: "iban_checksum" });
174
174
  }
175
175
  const bic = String(input.bic ?? "").replace(/\s/g, "").toUpperCase();
176
176
  if (bic && !/^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$/.test(bic)) problems.push({ field: "bic", code: "bic_format" });
177
177
  if (input.amount !== void 0 && input.amount !== "") {
178
- const amount = toNumber(input.amount);
179
- if (Number.isNaN(amount)) problems.push({ field: "amount", code: "not_a_number" });
180
- else if (amount < 0.01 || amount > 99999999999e-2) problems.push({ field: "amount", code: "out_of_range" });
178
+ const amount2 = toNumber(input.amount);
179
+ if (Number.isNaN(amount2)) problems.push({ field: "amount", code: "not_a_number" });
180
+ else if (amount2 < 0.01 || amount2 > 99999999999e-2) problems.push({ field: "amount", code: "out_of_range" });
181
181
  }
182
182
  const purpose = String(input.purpose ?? "");
183
183
  if (purpose.length > 4) problems.push({ field: "purpose", code: "too_long", max: 4, actual: purpose.length });
184
184
  const reference = String(input.reference ?? "").trim();
185
- const text2 = String(input.text ?? "").trim();
186
- if (reference && text2) problems.push({ field: "reference", code: "reference_or_text" });
185
+ const text3 = String(input.text ?? "").trim();
186
+ if (reference && text3) problems.push({ field: "reference", code: "reference_or_text" });
187
187
  if (reference.length > 35)
188
188
  problems.push({ field: "reference", code: "too_long", max: 35, actual: reference.length });
189
- if (text2.length > 140) problems.push({ field: "text", code: "too_long", max: 140, actual: text2.length });
189
+ if (text3.length > 140) problems.push({ field: "text", code: "too_long", max: 140, actual: text3.length });
190
190
  const bytes = byteLength(epcPayload(input));
191
191
  if (bytes > EPC_MAX_BYTES)
192
192
  problems.push({ field: "payload", code: "too_long", max: EPC_MAX_BYTES, actual: bytes });
@@ -224,9 +224,9 @@ var barcodeTypes = {
224
224
  };
225
225
  var ownTextLayout = /* @__PURE__ */ new Set(["ean13", "ean8", "upca"]);
226
226
  function codeText(helper, value) {
227
- const text2 = value === void 0 || value === null ? "" : String(value);
228
- if (text2 === "") throw new Error(`${helper}: nothing to encode, the value is empty or missing from the data`);
229
- return text2;
227
+ const text3 = value === void 0 || value === null ? "" : String(value);
228
+ if (text3 === "") throw new Error(`${helper}: nothing to encode, the value is empty or missing from the data`);
229
+ return text3;
230
230
  }
231
231
  var codeHelpers = [
232
232
  {
@@ -264,17 +264,17 @@ var codeHelpers = [
264
264
  fn: (ctx, value, options) => {
265
265
  const o = options ?? {};
266
266
  const bcid = barcodeTypes[String(o.type ?? "code128").toLowerCase()] ?? "code128";
267
- const text2 = codeText("barcode", value);
267
+ const text3 = codeText("barcode", value);
268
268
  const svg = toSVG({
269
269
  bcid,
270
- text: text2,
270
+ text: text3,
271
271
  height: o.height ?? 12,
272
272
  ...o.width === void 0 ? {} : { width: o.width },
273
273
  scale: o.scale ?? 2,
274
274
  includetext: o.text !== false,
275
275
  ...ownTextLayout.has(bcid) ? {} : { textxalign: "center" }
276
276
  });
277
- if (ctx.drawing) return ctx.drawing({ kind: "svg", svg, alt: `Barcode ${text2}` });
277
+ if (ctx.drawing) return ctx.drawing({ kind: "svg", svg, alt: `Barcode ${text3}` });
278
278
  return svgDataUri(svg);
279
279
  }
280
280
  },
@@ -300,12 +300,12 @@ var codeHelpers = [
300
300
  ...input && typeof input === "object" ? input : typeof input === "string" && input ? { iban: input } : {},
301
301
  ...options ?? {}
302
302
  };
303
- const payment = {};
303
+ const payment2 = {};
304
304
  const qr = {};
305
305
  for (const [key, value] of Object.entries(fields))
306
- (EPC_FIELDS.has(key) ? payment : qr)[key] = value;
306
+ (EPC_FIELDS.has(key) ? payment2 : qr)[key] = value;
307
307
  const o = { ecc: "M", ...qr };
308
- const svg = qrSvg(epcPayload(payment), o);
308
+ const svg = qrSvg(epcPayload(payment2), o);
309
309
  if (ctx.drawing) return ctx.drawing({ kind: "svg", svg, width: o.size, height: o.size, alt: "GiroCode" });
310
310
  return svgDataUri(svg);
311
311
  }
@@ -329,8 +329,8 @@ import { toCardinal as nlWords } from "n2words/nl";
329
329
  function resolveTranslation(dictionaries, locale, key) {
330
330
  const lang = locale.split("-")[0] ?? locale;
331
331
  for (const candidate of [locale, lang, "en"]) {
332
- const text2 = dictionaries?.[candidate]?.[key];
333
- if (typeof text2 === "string") return { text: text2, from: candidate };
332
+ const text3 = dictionaries?.[candidate]?.[key];
333
+ if (typeof text3 === "string") return { text: text3, from: candidate };
334
334
  }
335
335
  return { text: key, from: null };
336
336
  }
@@ -478,10 +478,10 @@ var formatHelpers = [
478
478
  },
479
479
  category: "format"
480
480
  },
481
- fn: (ctx, value, amount, unit) => {
481
+ fn: (ctx, value, amount2, unit) => {
482
482
  const d = toDate(value, ctx.timezone);
483
483
  if (!d) return str(value);
484
- const n = toNumber(amount);
484
+ const n = toNumber(amount2);
485
485
  const u = str(unit || "days").replace(/s?$/, "s");
486
486
  return add(d, { [u]: n }).toISOString();
487
487
  }
@@ -810,9 +810,9 @@ var formatHelpers = [
810
810
  category: "text"
811
811
  },
812
812
  fn: (ctx, key, params) => {
813
- const { text: text2 } = resolveTranslation(ctx.i18n, ctx.locale, str(key));
813
+ const { text: text3 } = resolveTranslation(ctx.i18n, ctx.locale, str(key));
814
814
  const p = params ?? {};
815
- return text2.replace(/\{(\w+)\}/g, (_, name) => str(p[name]));
815
+ return text3.replace(/\{(\w+)\}/g, (_, name) => str(p[name]));
816
816
  }
817
817
  },
818
818
  {
@@ -1343,22 +1343,22 @@ function unavailableHelper(name) {
1343
1343
  }
1344
1344
 
1345
1345
  // packages/engine/src/lib/analysis/tags.ts
1346
- function rangeAt(line, column, length) {
1346
+ function rangeAt(line2, column, length) {
1347
1347
  return {
1348
- start: { line, column },
1349
- end: { line, column: column + Math.max(1, length) }
1348
+ start: { line: line2, column },
1349
+ end: { line: line2, column: column + Math.max(1, length) }
1350
1350
  };
1351
1351
  }
1352
1352
  function positionOf(source, offset) {
1353
- let line = 1;
1353
+ let line2 = 1;
1354
1354
  let last = -1;
1355
1355
  for (let i = 0; i < offset && i < source.length; i++) {
1356
1356
  if (source.charCodeAt(i) === 10) {
1357
- line++;
1357
+ line2++;
1358
1358
  last = i;
1359
1359
  }
1360
1360
  }
1361
- return { line, column: offset - last };
1361
+ return { line: line2, column: offset - last };
1362
1362
  }
1363
1363
  function rangeOf(source, start, end) {
1364
1364
  return { start: positionOf(source, start), end: positionOf(source, end) };
@@ -1604,12 +1604,12 @@ function toSyntaxError(e) {
1604
1604
  const err2 = e;
1605
1605
  const message = String(err2.message ?? e);
1606
1606
  const m = /Parse error on line (\d+)/.exec(message);
1607
- const line = err2.lineNumber ?? (m ? Number(m[1]) : 1);
1607
+ const line2 = err2.lineNumber ?? (m ? Number(m[1]) : 1);
1608
1608
  const column = typeof err2.column === "number" ? err2.column + 1 : 1;
1609
1609
  return new EngineSyntaxError(
1610
1610
  "handlebars",
1611
1611
  message.split("\n")[0] ?? message,
1612
- line,
1612
+ line2,
1613
1613
  column
1614
1614
  );
1615
1615
  }
@@ -1919,48 +1919,48 @@ var SPEC = /^(?:([\s\S])?([<>=^]))?([+\- ])?(#)?(0)?(\d+)?([,_])?(?:\.(\d+))?([b
1919
1919
  function group(digits, separator) {
1920
1920
  return digits.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
1921
1921
  }
1922
- function pythonExponent(text2) {
1923
- return text2.replace(/e([+-])(\d)$/i, (m, sign, digit) => `${m[0]}${sign}0${digit}`);
1922
+ function pythonExponent(text3) {
1923
+ return text3.replace(/e([+-])(\d)$/i, (m, sign, digit) => `${m[0]}${sign}0${digit}`);
1924
1924
  }
1925
1925
  function formatNumber(value, type, precision, alternate) {
1926
1926
  if (!Number.isFinite(value)) return Number.isNaN(value) ? "nan" : "inf";
1927
- const abs = Math.abs(value);
1927
+ const abs2 = Math.abs(value);
1928
1928
  switch (type) {
1929
1929
  case "f":
1930
1930
  case "F":
1931
- return abs.toFixed(precision ?? 6);
1931
+ return abs2.toFixed(precision ?? 6);
1932
1932
  case "%":
1933
- return `${(abs * 100).toFixed(precision ?? 6)}%`;
1933
+ return `${(abs2 * 100).toFixed(precision ?? 6)}%`;
1934
1934
  case "e":
1935
1935
  case "E": {
1936
- const text2 = pythonExponent(abs.toExponential(precision ?? 6));
1937
- return type === "E" ? text2.toUpperCase() : text2;
1936
+ const text3 = pythonExponent(abs2.toExponential(precision ?? 6));
1937
+ return type === "E" ? text3.toUpperCase() : text3;
1938
1938
  }
1939
1939
  case "g":
1940
1940
  case "G": {
1941
1941
  const p = precision === 0 ? 1 : precision ?? 6;
1942
- const exp = abs === 0 ? 0 : Math.floor(Math.log10(abs));
1943
- let text2 = exp < -4 || exp >= p ? pythonExponent(abs.toExponential(p - 1)) : abs.toFixed(Math.max(0, p - 1 - exp));
1942
+ const exp = abs2 === 0 ? 0 : Math.floor(Math.log10(abs2));
1943
+ let text3 = exp < -4 || exp >= p ? pythonExponent(abs2.toExponential(p - 1)) : abs2.toFixed(Math.max(0, p - 1 - exp));
1944
1944
  if (!alternate) {
1945
- const [mantissa = "", exponent] = text2.split("e");
1945
+ const [mantissa = "", exponent] = text3.split("e");
1946
1946
  const trimmed = mantissa.includes(".") ? mantissa.replace(/0+$/, "").replace(/\.$/, "") : mantissa;
1947
- text2 = exponent === void 0 ? trimmed : `${trimmed}e${exponent}`;
1947
+ text3 = exponent === void 0 ? trimmed : `${trimmed}e${exponent}`;
1948
1948
  }
1949
- return type === "G" ? text2.toUpperCase() : text2;
1949
+ return type === "G" ? text3.toUpperCase() : text3;
1950
1950
  }
1951
1951
  case "d":
1952
1952
  case "n":
1953
- return String(Math.trunc(abs));
1953
+ return String(Math.trunc(abs2));
1954
1954
  case "b":
1955
- return (alternate ? "0b" : "") + Math.trunc(abs).toString(2);
1955
+ return (alternate ? "0b" : "") + Math.trunc(abs2).toString(2);
1956
1956
  case "o":
1957
- return (alternate ? "0o" : "") + Math.trunc(abs).toString(8);
1957
+ return (alternate ? "0o" : "") + Math.trunc(abs2).toString(8);
1958
1958
  case "x":
1959
- return (alternate ? "0x" : "") + Math.trunc(abs).toString(16);
1959
+ return (alternate ? "0x" : "") + Math.trunc(abs2).toString(16);
1960
1960
  case "X":
1961
- return (alternate ? "0X" : "") + Math.trunc(abs).toString(16).toUpperCase();
1961
+ return (alternate ? "0X" : "") + Math.trunc(abs2).toString(16).toUpperCase();
1962
1962
  default:
1963
- return precision === void 0 ? String(abs) : formatNumber(abs, "g", precision, alternate);
1963
+ return precision === void 0 ? String(abs2) : formatNumber(abs2, "g", precision, alternate);
1964
1964
  }
1965
1965
  }
1966
1966
  function formatValue(value, spec) {
@@ -2015,35 +2015,35 @@ function lookupField(name, positional, named, next) {
2015
2015
  function pythonFormat(template, positional, named = {}) {
2016
2016
  let auto = 0;
2017
2017
  const next = () => auto++;
2018
- const render = (text2) => {
2018
+ const render = (text3) => {
2019
2019
  let out = "";
2020
- for (let i = 0; i < text2.length; i++) {
2021
- const ch = text2[i];
2020
+ for (let i = 0; i < text3.length; i++) {
2021
+ const ch = text3[i];
2022
2022
  if (ch === "}") {
2023
2023
  out += "}";
2024
- if (text2[i + 1] === "}") i++;
2024
+ if (text3[i + 1] === "}") i++;
2025
2025
  continue;
2026
2026
  }
2027
2027
  if (ch !== "{") {
2028
2028
  out += ch;
2029
2029
  continue;
2030
2030
  }
2031
- if (text2[i + 1] === "{") {
2031
+ if (text3[i + 1] === "{") {
2032
2032
  out += "{";
2033
2033
  i++;
2034
2034
  continue;
2035
2035
  }
2036
2036
  let depth = 1;
2037
2037
  let j = i + 1;
2038
- for (; j < text2.length && depth > 0; j++) {
2039
- if (text2[j] === "{") depth++;
2040
- else if (text2[j] === "}") depth--;
2038
+ for (; j < text3.length && depth > 0; j++) {
2039
+ if (text3[j] === "{") depth++;
2040
+ else if (text3[j] === "}") depth--;
2041
2041
  }
2042
2042
  if (depth > 0) {
2043
- out += text2.slice(i);
2043
+ out += text3.slice(i);
2044
2044
  break;
2045
2045
  }
2046
- const field = text2.slice(i + 1, j - 1);
2046
+ const field = text3.slice(i + 1, j - 1);
2047
2047
  const colon = field.indexOf(":");
2048
2048
  const head = colon < 0 ? field : field.slice(0, colon);
2049
2049
  const name = head.replace(/![rsa]$/, "");
@@ -2147,7 +2147,7 @@ var stringMethods = {
2147
2147
  return out;
2148
2148
  },
2149
2149
  split: (s, sep, max2) => sep === void 0 || sep === null ? s.trim().split(/\s+/) : s.split(String(sep), max2 === void 0 ? void 0 : Number(max2) + 1),
2150
- join: (s, list2) => Array.isArray(list2) ? list2.join(s) : String(list2),
2150
+ join: (s, list3) => Array.isArray(list3) ? list3.join(s) : String(list3),
2151
2151
  format: (s, ...args) => {
2152
2152
  const named = keywordArgs(args);
2153
2153
  return pythonFormat(s, named ? args.slice(0, -1) : args, named ?? {});
@@ -2381,9 +2381,9 @@ function toSyntaxError2(e, fallbackLine = 1) {
2381
2381
  const fromMessage = /\[Line (\d+), Column (\d+)\]/.exec(
2382
2382
  String(err2.message ?? "")
2383
2383
  );
2384
- const line = typeof err2.lineno === "number" ? err2.lineno + 1 : fromMessage ? Number(fromMessage[1]) : fallbackLine;
2384
+ const line2 = typeof err2.lineno === "number" ? err2.lineno + 1 : fromMessage ? Number(fromMessage[1]) : fallbackLine;
2385
2385
  const column = typeof err2.colno === "number" ? err2.colno + 1 : fromMessage ? Number(fromMessage[2]) : 1;
2386
- return new EngineSyntaxError("jinja2", message, line, column);
2386
+ return new EngineSyntaxError("jinja2", message, line2, column);
2387
2387
  }
2388
2388
  function nodeRange(node, length = 1) {
2389
2389
  return rangeAt(node.lineno + 1, node.colno + 1, length);
@@ -2878,12 +2878,12 @@ var validationContext3 = {
2878
2878
  };
2879
2879
  function toSyntaxError3(e) {
2880
2880
  const err2 = e;
2881
- let line = err2.line ?? 1;
2881
+ let line2 = err2.line ?? 1;
2882
2882
  let column = err2.col ?? 1;
2883
2883
  const pos = err2.token?.getPosition?.();
2884
- if (pos) [line, column] = pos;
2884
+ if (pos) [line2, column] = pos;
2885
2885
  const message = String(err2.message ?? e).replace(/,\s*line:\d+,\s*col:\d+/, "").trim();
2886
- return new EngineSyntaxError("liquid", message, line, column);
2886
+ return new EngineSyntaxError("liquid", message, line2, column);
2887
2887
  }
2888
2888
  var identifier = /(?<![\w."'])([A-Za-z_][\w]*)((?:\.[A-Za-z_]\w*|\[\d+\])*)/g;
2889
2889
  function pathsIn(expression, base, source, out, scopes) {
@@ -3394,8 +3394,8 @@ function unionTypes(a, b) {
3394
3394
  ...Array.isArray(b) ? b : b ? [b] : []
3395
3395
  ]);
3396
3396
  if (set.has("number")) set.delete("integer");
3397
- const list2 = [...set];
3398
- return list2.length === 1 ? list2[0] : list2;
3397
+ const list3 = [...set];
3398
+ return list3.length === 1 ? list3[0] : list3;
3399
3399
  }
3400
3400
  function merge(a, b) {
3401
3401
  if (!a) return b;
@@ -3566,9 +3566,9 @@ function layeredPartials(own, shared2, onShared) {
3566
3566
  }
3567
3567
 
3568
3568
  // packages/engine/src/lib/dialect.ts
3569
- var loop = (engine, item, list2, body) => engine === "handlebars" ? `{{#each ${list2}}}
3569
+ var loop = (engine, item, list3, body) => engine === "handlebars" ? `{{#each ${list3}}}
3570
3570
  ${body.replace(new RegExp(`(?<![\\w.])${item}\\.`, "g"), "")}
3571
- {{/each}}` : `{% for ${item} in ${list2} %}
3571
+ {{/each}}` : `{% for ${item} in ${list3} %}
3572
3572
  ${body}
3573
3573
  {% endfor %}`;
3574
3574
  var val = (engine, expr, filter) => {
@@ -4137,12 +4137,12 @@ var stripComments = (css2) => css2.replace(/\/\*[\s\S]*?\*\//g, "");
4137
4137
  var selectorKey = (prelude) => (prelude.split(";").pop() ?? "").trim().replace(/\s*,\s*/g, ", ").replace(/\s+/g, " ");
4138
4138
  function mergeSnippetCss(css2, snippetCss) {
4139
4139
  if (!snippetCss?.trim()) return css2;
4140
- const defined = new Set(
4140
+ const defined2 = new Set(
4141
4141
  [...stripComments(css2).matchAll(/([^{}]+)\{/g)].map(
4142
4142
  (m) => selectorKey(m[1] ?? "")
4143
4143
  )
4144
4144
  );
4145
- const missing = [...stripComments(snippetCss).matchAll(/([^{}]+)\{[^{}]*\}/g)].filter((m) => !defined.has(selectorKey(m[1] ?? ""))).map((m) => m[0].trim());
4145
+ const missing = [...stripComments(snippetCss).matchAll(/([^{}]+)\{[^{}]*\}/g)].filter((m) => !defined2.has(selectorKey(m[1] ?? ""))).map((m) => m[0].trim());
4146
4146
  if (!missing.length) return css2;
4147
4147
  const base = css2.trimEnd();
4148
4148
  return `${base}${base ? "\n\n" : ""}${missing.join("\n")}
@@ -4188,9 +4188,9 @@ function pick(input, ...keys) {
4188
4188
  function toLength(value) {
4189
4189
  if (value === void 0 || value === null || value === "") return void 0;
4190
4190
  if (typeof value === "number") return `${value}mm`;
4191
- const text2 = String(value).trim();
4192
- if (/^-?\d+(\.\d+)?$/.test(text2)) return `${text2}mm`;
4193
- if (/^-?\d+(\.\d+)?(mm|cm|in|px|pt)$/i.test(text2)) return text2.toLowerCase();
4191
+ const text3 = String(value).trim();
4192
+ if (/^-?\d+(\.\d+)?$/.test(text3)) return `${text3}mm`;
4193
+ if (/^-?\d+(\.\d+)?(mm|cm|in|px|pt)$/i.test(text3)) return text3.toLowerCase();
4194
4194
  return void 0;
4195
4195
  }
4196
4196
  function toMarginLength(value) {
@@ -4210,7 +4210,7 @@ function convertHeaderFooter(html) {
4210
4210
  if (typeof html !== "string" || !html.trim()) return void 0;
4211
4211
  return chromePlaceholders.reduce((out, [pattern, span]) => out.replace(pattern, span), html);
4212
4212
  }
4213
- var escapeText = (text2) => text2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4213
+ var escapeText = (text3) => text3.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4214
4214
  var visibleMarkup = (html) => html.replace(/<style[\s\S]*?<\/style>/gi, "").trim();
4215
4215
  function apitemplateChrome(take, kind) {
4216
4216
  const custom = take(`custom_${kind}`);
@@ -4224,7 +4224,7 @@ function apitemplateChrome(take, kind) {
4224
4224
  if (!slots.some(Boolean)) return { fromSlots: false };
4225
4225
  const sizeText = size === void 0 ? "" : String(size).trim();
4226
4226
  const fontSize2 = /^\d+(\.\d+)?$/.test(sizeText) ? `${sizeText}px` : /^\d+(\.\d+)?(px|pt|mm)$/.test(sizeText) ? sizeText : "9px";
4227
- const cells = slots.map((text2, i) => `<span style="flex:1;text-align:${["left", "center", "right"][i]}">${escapeText(text2)}</span>`).join("");
4227
+ const cells = slots.map((text3, i) => `<span style="flex:1;text-align:${["left", "center", "right"][i]}">${escapeText(text3)}</span>`).join("");
4228
4228
  const styles = customHtml.match(/<style[\s\S]*?<\/style>/gi)?.join("") ?? "";
4229
4229
  return {
4230
4230
  html: convertHeaderFooter(`${styles}<div style="display:flex;gap:4mm;font-size:${fontSize2}">${cells}</div>`),
@@ -4344,15 +4344,15 @@ function parseSample(value) {
4344
4344
  }
4345
4345
  function positionOf2(source, index) {
4346
4346
  const before = source.slice(0, index);
4347
- const line = before.split("\n").length;
4347
+ const line2 = before.split("\n").length;
4348
4348
  const column = index - before.lastIndexOf("\n");
4349
- return { line, column };
4349
+ return { line: line2, column };
4350
4350
  }
4351
- function notesFor(source, pattern, note, { once = false } = {}) {
4351
+ function notesFor(source, pattern, note2, { once = false } = {}) {
4352
4352
  const global = new RegExp(pattern.source, pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`);
4353
4353
  const out = [];
4354
4354
  for (const m of source.matchAll(global)) {
4355
- out.push({ ...note, ...positionOf2(source, m.index ?? 0) });
4355
+ out.push({ ...note2, ...positionOf2(source, m.index ?? 0) });
4356
4356
  if (once) break;
4357
4357
  }
4358
4358
  return out;
@@ -4375,19 +4375,19 @@ function checkTemplate(engineId, html, sampleData, name, docs) {
4375
4375
  docs: d.code === "unknown-filter" ? docs.filters : d.code.startsWith("missing-") ? docs.sampleData : docs.syntax
4376
4376
  });
4377
4377
  for (const d of engine.analyze(html, { sampleData }).diagnostics) {
4378
- const note = fromDiagnostic(d);
4378
+ const note2 = fromDiagnostic(d);
4379
4379
  if (d.severity === "error") {
4380
- if (!errors.some((x) => x.code === note.code && x.line === note.line)) errors.push(note);
4381
- } else warnings.push(note);
4380
+ if (!errors.some((x) => x.code === note2.code && x.line === note2.line)) errors.push(note2);
4381
+ } else warnings.push(note2);
4382
4382
  }
4383
4383
  return { errors, warnings };
4384
4384
  }
4385
4385
  function lengthMm(value) {
4386
4386
  if (value === void 0 || value === null || value === "") return void 0;
4387
4387
  if (typeof value === "number" && Number.isFinite(value)) return `${value}mm`;
4388
- const text2 = String(value).trim();
4389
- if (/^-?\d+(\.\d+)?$/.test(text2)) return `${text2}mm`;
4390
- if (/^-?\d+(\.\d+)?(mm|cm|in|px|pt)$/i.test(text2)) return text2.toLowerCase();
4388
+ const text3 = String(value).trim();
4389
+ if (/^-?\d+(\.\d+)?$/.test(text3)) return `${text3}mm`;
4390
+ if (/^-?\d+(\.\d+)?(mm|cm|in|px|pt)$/i.test(text3)) return text3.toLowerCase();
4391
4391
  return void 0;
4392
4392
  }
4393
4393
  function toBase64(value) {
@@ -4474,17 +4474,17 @@ var STYLE_BLOCK = /<style\b[^>]*>([\s\S]*?)<\/style\s*>/gi;
4474
4474
  var HEAD_MARKUP = /<script\b[\s\S]*?<\/script\s*>|<!--[\s\S]*?-->|<(?:link|meta|base)\b[^>]*>/gi;
4475
4475
  var TEMPLATED = /\{\{|\{%/;
4476
4476
  function splitApitemplateCss(source) {
4477
- const styleElement = (rules) => `<style>
4478
- ${rules}
4477
+ const styleElement = (rules2) => `<style>
4478
+ ${rules2}
4479
4479
  </style>`;
4480
4480
  if (!/<\/?(style|link|script|meta|base)\b|<!--/i.test(source))
4481
4481
  return TEMPLATED.test(source) ? { css: "", head: "", body: styleElement(source.trim()) } : { css: source, head: "", body: "" };
4482
4482
  const styles = [];
4483
4483
  const head = [];
4484
4484
  const body = [];
4485
- let rest = source.replace(STYLE_BLOCK, (block, rules) => {
4486
- if (TEMPLATED.test(rules)) body.push(block.trim());
4487
- else styles.push(rules.replace(/^\n+|\s+$/g, ""));
4485
+ let rest = source.replace(STYLE_BLOCK, (block, rules2) => {
4486
+ if (TEMPLATED.test(rules2)) body.push(block.trim());
4487
+ else styles.push(rules2.replace(/^\n+|\s+$/g, ""));
4488
4488
  return "\n";
4489
4489
  });
4490
4490
  rest = rest.replace(HEAD_MARKUP, (tag) => {
@@ -4507,7 +4507,7 @@ function importApitemplate(input) {
4507
4507
  if (kind === "image") changes.push(`${format} template imported as an image template`);
4508
4508
  const mapped = mapApitemplateSettings(input.settings ?? void 0);
4509
4509
  const settings = mapped.settings;
4510
- for (const note of mapped.notes) changes.push(note);
4510
+ for (const note2 of mapped.notes) changes.push(note2);
4511
4511
  for (const key of mapped.ignored)
4512
4512
  warnings.push({ code: "setting-ignored", message: `Setting "${key}" has no Formfeed equivalent and was dropped.`, docs: "/migrate/apitemplate-io#settings" });
4513
4513
  if (settings.header?.html || settings.footer?.html) changes.push("header and footer templates moved to the Header and Footer tabs");
@@ -4904,11 +4904,11 @@ function inlineIncludes(source, blocks, errors, changes) {
4904
4904
  }
4905
4905
  var cssPaperFormats = { a3: "A3", a4: "A4", a5: "A5", letter: "Letter" };
4906
4906
  var isoSizes = { a0: [841, 1189], a1: [594, 841], a2: [420, 594], a6: [105, 148] };
4907
- var escapeHtml2 = (text2) => text2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4907
+ var escapeHtml2 = (text3) => text3.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
4908
4908
  function simpleHeaderFooter(part, margin) {
4909
4909
  const cells = ["left", "center", "right"].map((side) => part[side] ?? "");
4910
4910
  if (!cells.some((c) => c.trim())) return void 0;
4911
- const cell3 = (text2, align) => `<div style="flex: 1; text-align: ${align}">${escapeHtml2(text2).replace(/\[page\]/g, '<span class="pageNumber"></span>').replace(/\[topage\]/g, '<span class="totalPages"></span>')}</div>`;
4911
+ const cell3 = (text3, align) => `<div style="flex: 1; text-align: ${align}">${escapeHtml2(text3).replace(/\[page\]/g, '<span class="pageNumber"></span>').replace(/\[topage\]/g, '<span class="totalPages"></span>')}</div>`;
4912
4912
  return `<div style="display: flex; width: 100%; font-size: 10px; padding: 0 ${margin.right} 0 ${margin.left}">${cell3(cells[0] ?? "", "left")}${cell3(cells[1] ?? "", "center")}${cell3(cells[2] ?? "", "right")}</div>`;
4913
4913
  }
4914
4914
  function mapSettings(input, kind, warnings, changes) {
@@ -5077,11 +5077,11 @@ var DOCS3 = "/migrate/jsreport";
5077
5077
  var COLLECTIONS = ["templates", "data", "assets", "components", "scripts", "folders"];
5078
5078
  function readJsreportExport(files) {
5079
5079
  const bundle = { templates: [], data: [], assets: [], components: [], scripts: [], folders: [] };
5080
- for (const [path, text2] of Object.entries(files)) {
5080
+ for (const [path, text3] of Object.entries(files)) {
5081
5081
  const normalized = path.replace(/\\/g, "/").replace(/^\.?\//, "");
5082
5082
  if (normalized === "metadata.json") {
5083
5083
  try {
5084
- bundle.version = String(JSON.parse(text2).reporterVersion ?? "");
5084
+ bundle.version = String(JSON.parse(text3).reporterVersion ?? "");
5085
5085
  } catch {
5086
5086
  }
5087
5087
  continue;
@@ -5089,7 +5089,7 @@ function readJsreportExport(files) {
5089
5089
  const collection = normalized.split("/")[0];
5090
5090
  if (!COLLECTIONS.includes(collection) || !normalized.endsWith(".json")) continue;
5091
5091
  try {
5092
- bundle[collection].push(JSON.parse(text2));
5092
+ bundle[collection].push(JSON.parse(text3));
5093
5093
  } catch {
5094
5094
  }
5095
5095
  }
@@ -5114,9 +5114,9 @@ function pathOf2(bundle, entity) {
5114
5114
  function jsreportTemplates(bundle) {
5115
5115
  return bundle.templates.map((t) => ({ ref: t.shortid ?? t._id ?? t.name ?? "", name: t.name ?? "", path: pathOf2(bundle, t), engine: t.engine ?? "", recipe: t.recipe ?? "" })).sort((a, b) => a.path.localeCompare(b.path));
5116
5116
  }
5117
- function byPath(bundle, list2, ref) {
5117
+ function byPath(bundle, list3, ref) {
5118
5118
  const wanted = ref.replace(/^\.?\/+/, "");
5119
- return list2.find((e) => pathOf2(bundle, e) === wanted) ?? list2.find((e) => e.name === wanted.split("/").pop());
5119
+ return list3.find((e) => pathOf2(bundle, e) === wanted) ?? list3.find((e) => e.name === wanted.split("/").pop());
5120
5120
  }
5121
5121
  function decodeText(base64) {
5122
5122
  const binary = atob(base64);
@@ -5131,7 +5131,7 @@ function assetBase64(content) {
5131
5131
  }
5132
5132
  return toBase64(content);
5133
5133
  }
5134
- var escapeMustaches = (text2) => text2.replace(/\{\{/g, "\\{{");
5134
+ var escapeMustaches = (text3) => text3.replace(/\{\{/g, "\\{{");
5135
5135
  function resolveAssets(source, bundle, options, warnings, changes) {
5136
5136
  const v3 = /\{\{\{?\s*asset\s+(["'])([^"']+)\1(?:\s+(["'])([^"']+)\3)?\s*\}?\}\}/g;
5137
5137
  const v2 = /\{#asset\s+([^\s}]+)(?:\s+@encoding=(\w+))?\s*\}/g;
@@ -5369,9 +5369,9 @@ function importJsreport(bundle, ref, options = {}) {
5369
5369
  }
5370
5370
 
5371
5371
  // packages/engine/src/lib/generated/frames.ts
5372
- var textEditRuntime = '"use strict";(()=>{var H=`\nhtml.ff-edit-mode [data-ff-edit] { cursor: text; }\nhtml.ff-edit-mode [data-ff-edit]:hover { outline: 1px dashed rgba(37,99,235,.85); outline-offset: 2px; }\nhtml.ff-edit-mode [data-ff-edit="t"]:hover { outline-color: rgba(147,51,234,.9); }\n.ff-editing { outline: 2px solid #2563eb !important; outline-offset: 2px; cursor: text; }\n.ff-editing .ff-chip { background: rgba(37,99,235,.14) !important; box-shadow: inset 0 0 0 1px rgba(37,99,235,.45) !important; border-radius: 3px !important; padding: 0 1px !important; cursor: default; }\n.ff-edit-badge { position: absolute; z-index: 2147483647; font: 500 11px/1.4 system-ui, sans-serif !important; color: #fff !important; background: #2563eb !important; padding: 1px 6px !important; border-radius: 4px !important; pointer-events: none; white-space: nowrap; }\n`;function R(s,l={}){let g=l.clicks!==!1,p=l.live===!0,o=s.document,i=null,a=null,c=e=>{try{s.parent.postMessage(e,"*")}catch{}},b=o.createElement("style");b.setAttribute("data-formfeed","edit"),b.setAttribute("data-pagedjs-ignore",""),b.textContent=H,(o.head??o.documentElement).appendChild(b),g&&o.documentElement.classList.add("ff-edit-mode");let D=e=>(e&&typeof e.closest=="function"?e:null)?.closest("[data-ff-edit]")??null;o.addEventListener("click",e=>{if(!g)return;if(i&&!i.done&&i.element.contains(e.target)){e.stopImmediatePropagation();return}let t=D(e.target);if(!t)return;e.preventDefault(),e.stopImmediatePropagation(),i&&!i.done&&y();let n=t.getAttribute("data-ff-src")??"",r=t.getBoundingClientRect();a={src:n,element:t,x:e.clientX,y:e.clientY},c({type:"formfeed:edit-request",src:n,edit:t.getAttribute("data-ff-edit"),text:t.textContent??"",count:o.querySelectorAll(`[data-ff-src="${n.replace(/"/g,"")}"]`).length,split:t.hasAttribute("data-split-from")||t.hasAttribute("data-split-to"),rect:{left:r.left,top:r.top,width:r.width,height:r.height}})},!0),o.addEventListener("keydown",e=>{if(!g||i&&!i.done||!(e.ctrlKey||e.metaKey)||e.altKey)return;let t=e.key.toLowerCase();(t==="z"||t==="y")&&(e.preventDefault(),c({type:t==="y"||e.shiftKey?"formfeed:redo":"formfeed:undo"}))}),s.addEventListener("message",e=>{if(e.source!==s.parent)return;let t=e.data;!t||typeof t.type!="string"||(t.type==="formfeed:edit-begin"?F(t):(t.type==="formfeed:edit-refuse"||t.type==="formfeed:edit-end")&&(a=null,i&&!i.done&&h(!1)))});function F(e){i&&!i.done&&h(!1);let t=e.layer?o.querySelector(`[data-ff-layer="${String(e.layer).replace(/"/g,"")}"] > .ff-text`):a&&a.src===e.src?a.element:o.querySelector(`[data-ff-src="${String(e.src).replace(/"/g,"")}"]`),n=e.at,r=e.layer?n&&Number.isFinite(n.x)&&Number.isFinite(n.y)?{x:Number(n.x),y:Number(n.y)}:null:a&&a.src===e.src?a:null;if(a=null,!t||!Array.isArray(e.items)){c({type:"formfeed:edit-cancel",token:String(e.token)});return}let m=Array.from(t.childNodes),f=o.createDocumentFragment();for(let u of e.items)if(u.kind==="text")f.appendChild(o.createTextNode(String(u.text)));else if(u.kind==="break")f.appendChild(o.createElement("br"));else if(u.kind==="chip"){let d=o.createElement("span");d.className="ff-chip",d.setAttribute("data-ff-chip",String(u.index)),d.setAttribute("contenteditable","false"),u.title&&(d.title=String(u.title)),d.textContent=String(u.text),f.appendChild(d)}for(let u of m)t.removeChild(u);t.appendChild(f),t.contentEditable="true",t.classList.add("ff-editing"),t.setAttribute("role","textbox"),e.label&&t.setAttribute("aria-label",String(e.label)),t.spellcheck=!0,i={token:String(e.token),element:t,saved:m,allowBreaks:e.allowBreaks===!0,badge:e.note?B(t,String(e.note)):null,done:!1},t.addEventListener("keydown",E),t.addEventListener("beforeinput",v),t.addEventListener("paste",C),t.addEventListener("drop",L),t.addEventListener("focusout",A),p&&t.addEventListener("input",x),t.focus(),e.select==="all"?w(t):P(t,r),c({type:"formfeed:edit-started",token:i.token}),typeof e.insert=="string"&&e.insert&&k(e.insert.replace(/\\r\\n?|\\n/g," "))}function k(e){if(typeof o.execCommand=="function"&&o.execCommand("insertText",!1,e))return;let t=s.getSelection(),n=t&&t.rangeCount?t.getRangeAt(0):null;n&&(n.deleteContents(),n.insertNode(o.createTextNode(e)),n.collapse(!1),p&&x())}function x(){i&&!i.done&&c({type:"formfeed:edit-input",token:i.token,items:S(i.element)})}function B(e,t){let n=o.createElement("div");n.className="ff-edit-badge",n.textContent=t;let r=e.getBoundingClientRect();return n.style.left=`${r.left+s.scrollX}px`,n.style.top=`${Math.max(0,r.top+s.scrollY-22)}px`,o.body.appendChild(n),n}function w(e){let t=s.getSelection();if(!t)return;let n=o.createRange();n.selectNodeContents(e),t.removeAllRanges(),t.addRange(n)}function P(e,t){let n=s.getSelection();if(!n)return;let r=null,m=o;if(t){if(m.caretRangeFromPoint)r=m.caretRangeFromPoint(t.x,t.y);else if(m.caretPositionFromPoint){let f=m.caretPositionFromPoint(t.x,t.y);f&&(r=o.createRange(),r.setStart(f.offsetNode,f.offset))}}if(!r||!e.contains(r.startContainer))r=o.createRange(),r.selectNodeContents(e),r.collapse(!1);else if(t){let f=r.startContainer,d=(f.nodeType===1?f:f.parentElement)?.closest("[data-ff-chip]")??null;if(d&&d!==e&&e.contains(d)){let N=d.getBoundingClientRect();r=o.createRange(),t.x<N.left+N.width/2?r.setStartBefore(d):r.setStartAfter(d),r.collapse(!0)}}n.removeAllRanges(),n.addRange(r)}function E(e){let t=e.key;t==="Escape"?(e.preventDefault(),h(!0)):t==="Enter"&&!e.shiftKey?(e.preventDefault(),y()):t==="Enter"?(e.preventDefault(),i?.allowBreaks&&M()):t==="Tab"?(e.preventDefault(),y()):(e.ctrlKey||e.metaKey)&&["b","i","u"].includes(t.toLowerCase())&&(e.preventDefault(),p&&i&&!e.altKey&&c({type:"formfeed:edit-style",token:i.token,key:t.toLowerCase()}))}function v(e){let t=e.inputType??"";(t.startsWith("format")||t==="insertFromDrop"||t==="insertParagraph"||t==="insertLineBreak")&&e.preventDefault()}function C(e){e.preventDefault(),k((e.clipboardData?.getData("text/plain")??"").replace(/\\r\\n?|\\n/g," "))}function L(e){e.preventDefault()}function A(){s.setTimeout(()=>{i&&!i.done&&(!o.hasFocus()||!i.element.contains(o.activeElement))&&y()},0)}function M(){let e=s.getSelection();if(!e||!e.rangeCount)return;let t=e.getRangeAt(0);t.deleteContents();let n=o.createElement("br");t.insertNode(n),n.nextSibling||n.parentNode?.appendChild(o.createElement("br"));let r=o.createRange();r.setStartAfter(n),r.collapse(!0),e.removeAllRanges(),e.addRange(r)}function T(e){e.done=!0;let t=e.element;t.removeEventListener("keydown",E),t.removeEventListener("beforeinput",v),t.removeEventListener("paste",C),t.removeEventListener("drop",L),t.removeEventListener("focusout",A),t.removeEventListener("input",x),t.removeAttribute("contenteditable"),t.removeAttribute("role"),t.removeAttribute("aria-label"),t.classList.remove("ff-editing"),e.badge?.remove(),i===e&&(i=null)}function y(){let e=i;if(!e||e.done)return;let t=S(e.element);T(e),c({type:"formfeed:edit-commit",token:e.token,items:t})}function h(e){let t=i;if(!t||t.done)return;let n=t.element;for(;n.firstChild;)n.removeChild(n.firstChild);for(let r of t.saved)n.appendChild(r);T(t),e&&c({type:"formfeed:edit-cancel",token:t.token})}}function S(s){let l=[],g=o=>{let i=l[l.length-1];i?.kind==="text"?i.text+=o:o&&l.push({kind:"text",text:o})},p=o=>{for(let i of Array.from(o.childNodes))if(i.nodeType===3)g(i.data);else if(i.nodeType===1){let a=i,c=a.getAttribute("data-ff-chip");c!==null?l.push({kind:"chip",index:Number(c)}):a.tagName==="BR"?l.push({kind:"break"}):((a.tagName==="DIV"||a.tagName==="P")&&l.length&&l.push({kind:"break"}),p(a))}};for(p(s);l[l.length-1]?.kind==="break";)l.pop();return l}R(window);})();';
5372
+ var textEditRuntime = '"use strict";(()=>{var O=`\nhtml.ff-edit-mode [data-ff-edit] { cursor: text; }\nhtml.ff-edit-mode [data-ff-edit]:hover { outline: 1px dashed rgba(37,99,235,.85); outline-offset: 2px; }\nhtml.ff-edit-mode [data-ff-edit="t"]:hover { outline-color: rgba(147,51,234,.9); }\n.ff-editing { outline: 2px solid #2563eb !important; outline-offset: 2px; cursor: text; }\n.ff-editing .ff-chip { background: rgba(37,99,235,.14) !important; box-shadow: inset 0 0 0 1px rgba(37,99,235,.45) !important; border-radius: 3px !important; padding: 0 1px !important; cursor: default; }\n.ff-edit-badge { position: absolute; z-index: 2147483647; font: 500 11px/1.4 system-ui, sans-serif !important; color: #fff !important; background: #2563eb !important; padding: 1px 6px !important; border-radius: 4px !important; pointer-events: none; white-space: nowrap; }\n`;function F(l,d={}){let m=d.clicks!==!1,g=d.live===!0,o=l.document,i=null,s=null,f=e=>{try{l.parent.postMessage(e,"*")}catch{}},v=m?o.querySelector(\'meta[name="formfeed:document"]\')?.getAttribute("content")??null:null,h=!1;l.addEventListener("blur",()=>{h=!0}),l.addEventListener("focus",()=>{h=!1});let y=o.createElement("style");y.setAttribute("data-formfeed","edit"),y.setAttribute("data-pagedjs-ignore",""),y.textContent=O,(o.head??o.documentElement).appendChild(y),m&&o.documentElement.classList.add("ff-edit-mode");let M=e=>(e&&typeof e.closest=="function"?e:null)?.closest("[data-ff-edit]")??null;o.addEventListener("click",e=>{if(!m)return;if(i&&!i.done&&i.element.contains(e.target)){e.stopImmediatePropagation();return}let t=M(e.target);t&&(e.preventDefault(),e.stopImmediatePropagation(),C(t,{x:e.clientX,y:e.clientY}))},!0);function C(e,t){i&&!i.done&&x();let n=e.getAttribute("data-ff-src")??"",r=e.getBoundingClientRect(),u=Array.from(o.querySelectorAll(`[data-ff-src="${n.replace(/"/g,"")}"]`));s={src:n,element:e,point:t},f({type:"formfeed:edit-request",src:n,doc:v,edit:e.getAttribute("data-ff-edit"),text:e.textContent??"",elements:e.childElementCount,count:u.length,index:Math.max(0,u.indexOf(e)),split:e.hasAttribute("data-split-from")||e.hasAttribute("data-split-to"),rect:{left:r.left,top:r.top,width:r.width,height:r.height}})}o.addEventListener("keydown",e=>{if(!m||i&&!i.done||!(e.ctrlKey||e.metaKey)||e.altKey)return;let t=e.key.toLowerCase();(t==="z"||t==="y")&&(e.preventDefault(),f({type:t==="y"||e.shiftKey?"formfeed:redo":"formfeed:undo"}))}),l.addEventListener("message",e=>{if(e.source!==l.parent)return;let t=e.data;!t||typeof t.type!="string"||(t.type==="formfeed:edit-begin"?P(t):t.type==="formfeed:edit-refuse"||t.type==="formfeed:edit-end"?(s=null,i&&!i.done&&E(!1)):t.type==="formfeed:edit-open"&&B(t))});function B(e){if(!m||typeof e.src!="string"||i&&!i.done)return;let t=Array.from(o.querySelectorAll(`[data-ff-src="${e.src.replace(/"/g,"")}"][data-ff-edit]`)),n=Number.isInteger(e.index)?Number(e.index):0,r=t[n]??t[0];r&&C(r,null)}if(m){let e=()=>f({type:"formfeed:edit-ready",doc:v}),t=l;t.PagedConfig?t.formfeedEditReady=e:o.readyState==="loading"?o.addEventListener("DOMContentLoaded",e):e()}function P(e){i&&!i.done&&E(!1);let t=e.layer?o.querySelector(`[data-ff-layer="${String(e.layer).replace(/"/g,"")}"] > .ff-text`):s&&s.src===e.src?s.element:o.querySelector(`[data-ff-src="${String(e.src).replace(/"/g,"")}"]`),n=e.at,r=e.layer?n&&Number.isFinite(n.x)&&Number.isFinite(n.y)?{x:Number(n.x),y:Number(n.y)}:null:s&&s.src===e.src?s.point:null;s=null;let u=h&&!o.hasFocus();if(!t||!Array.isArray(e.items)||u){f({type:"formfeed:edit-cancel",token:String(e.token)});return}let c=Array.from(t.childNodes),b=o.createDocumentFragment();for(let a of e.items)if(a.kind==="text")b.appendChild(o.createTextNode(String(a.text)));else if(a.kind==="break")b.appendChild(o.createElement("br"));else if(a.kind==="chip"){let p=o.createElement("span");p.className="ff-chip",p.setAttribute("data-ff-chip",String(a.index)),p.setAttribute("contenteditable","false"),a.title&&(p.title=String(a.title)),p.textContent=String(a.text),b.appendChild(p)}for(let a of c)t.removeChild(a);t.appendChild(b),t.contentEditable="true",t.classList.add("ff-editing"),t.setAttribute("role","textbox"),e.label&&t.setAttribute("aria-label",String(e.label)),t.spellcheck=!0,i={token:String(e.token),element:t,saved:c,allowBreaks:e.allowBreaks===!0,badge:e.note?H(t,String(e.note)):null,done:!1},t.addEventListener("keydown",A),t.addEventListener("beforeinput",T),t.addEventListener("paste",S),t.addEventListener("drop",N),t.addEventListener("focusout",R),g&&t.addEventListener("input",k),t.focus(),e.select==="all"?I(t):K(t,r),f({type:"formfeed:edit-started",token:i.token}),typeof e.insert=="string"&&e.insert&&L(e.insert.replace(/\\r\\n?|\\n/g," "))}function L(e){if(typeof o.execCommand=="function"&&o.execCommand("insertText",!1,e))return;let t=l.getSelection(),n=t&&t.rangeCount?t.getRangeAt(0):null;n&&(n.deleteContents(),n.insertNode(o.createTextNode(e)),n.collapse(!1),g&&k())}function k(){i&&!i.done&&f({type:"formfeed:edit-input",token:i.token,items:D(i.element)})}function H(e,t){let n=o.createElement("div");n.className="ff-edit-badge",n.textContent=t;let r=e.getBoundingClientRect();return n.style.left=`${r.left+l.scrollX}px`,n.style.top=`${Math.max(0,r.top+l.scrollY-22)}px`,o.body.appendChild(n),n}function I(e){let t=l.getSelection();if(!t)return;let n=o.createRange();n.selectNodeContents(e),t.removeAllRanges(),t.addRange(n)}function K(e,t){let n=l.getSelection();if(!n)return;let r=null,u=o;if(t){if(u.caretRangeFromPoint)r=u.caretRangeFromPoint(t.x,t.y);else if(u.caretPositionFromPoint){let c=u.caretPositionFromPoint(t.x,t.y);c&&(r=o.createRange(),r.setStart(c.offsetNode,c.offset))}}if(!r||!e.contains(r.startContainer))r=o.createRange(),r.selectNodeContents(e),r.collapse(!1);else if(t){let c=r.startContainer,a=(c.nodeType===1?c:c.parentElement)?.closest("[data-ff-chip]")??null;if(a&&a!==e&&e.contains(a)){let p=a.getBoundingClientRect();r=o.createRange(),t.x<p.left+p.width/2?r.setStartBefore(a):r.setStartAfter(a),r.collapse(!0)}}n.removeAllRanges(),n.addRange(r)}function A(e){let t=e.key;t==="Escape"?(e.preventDefault(),E(!0)):t==="Enter"&&!e.shiftKey?(e.preventDefault(),x()):t==="Enter"?(e.preventDefault(),i?.allowBreaks&&q()):t==="Tab"?(e.preventDefault(),x()):(e.ctrlKey||e.metaKey)&&["b","i","u"].includes(t.toLowerCase())&&(e.preventDefault(),g&&i&&!e.altKey&&f({type:"formfeed:edit-style",token:i.token,key:t.toLowerCase()}))}function T(e){let t=e.inputType??"";(t.startsWith("format")||t==="insertFromDrop"||t==="insertParagraph"||t==="insertLineBreak")&&e.preventDefault()}function S(e){e.preventDefault(),L((e.clipboardData?.getData("text/plain")??"").replace(/\\r\\n?|\\n/g," "))}function N(e){e.preventDefault()}function R(){l.setTimeout(()=>{i&&!i.done&&(!o.hasFocus()||!i.element.contains(o.activeElement))&&x()},0)}function q(){let e=l.getSelection();if(!e||!e.rangeCount)return;let t=e.getRangeAt(0);t.deleteContents();let n=o.createElement("br");t.insertNode(n),n.nextSibling||n.parentNode?.appendChild(o.createElement("br"));let r=o.createRange();r.setStartAfter(n),r.collapse(!0),e.removeAllRanges(),e.addRange(r)}function w(e){e.done=!0;let t=e.element;t.removeEventListener("keydown",A),t.removeEventListener("beforeinput",T),t.removeEventListener("paste",S),t.removeEventListener("drop",N),t.removeEventListener("focusout",R),t.removeEventListener("input",k),t.removeAttribute("contenteditable"),t.removeAttribute("role"),t.removeAttribute("aria-label"),t.classList.remove("ff-editing"),e.badge?.remove(),i===e&&(i=null)}function x(){let e=i;if(!e||e.done)return;let t=D(e.element);w(e),f({type:"formfeed:edit-commit",token:e.token,items:t})}function E(e){let t=i;if(!t||t.done)return;let n=t.element;for(;n.firstChild;)n.removeChild(n.firstChild);for(let r of t.saved)n.appendChild(r);w(t),e&&f({type:"formfeed:edit-cancel",token:t.token})}}function D(l){let d=[],m=o=>{let i=d[d.length-1];i?.kind==="text"?i.text+=o:o&&d.push({kind:"text",text:o})},g=o=>{for(let i of Array.from(o.childNodes))if(i.nodeType===3)m(i.data);else if(i.nodeType===1){let s=i,f=s.getAttribute("data-ff-chip");f!==null?d.push({kind:"chip",index:Number(f)}):s.tagName==="BR"?d.push({kind:"break"}):((s.tagName==="DIV"||s.tagName==="P")&&d.length&&d.push({kind:"break"}),g(s))}};for(g(l);d[d.length-1]?.kind==="break";)d.pop();return d}F(window);})();';
5373
5373
  var fitRuntime = '"use strict";(()=>{function a(t,e,n){if(e===t)return t.scrollHeight<=t.clientHeight+.5&&t.scrollWidth<=t.clientWidth+.5;let o=n.getComputedStyle(t),i=t.clientHeight-(parseFloat(o.paddingTop)||0)-(parseFloat(o.paddingBottom)||0);return e.scrollHeight<=i+.5&&e.scrollWidth<=e.clientWidth+.5}function m(t,e){let n=t.firstElementChild??t;n.style.fontSize="";let o=parseFloat(e.getComputedStyle(n).fontSize)||16,i=Math.min(o,parseFloat(t.getAttribute("data-ff-fit-min")??"")||o/2);if(a(t,n,e))return o;let l=i,s=o;for(let d=0;d<14;d++){let r=(l+s)/2;n.style.fontSize=`${r}px`,a(t,n,e)?l=r:s=r}let f=Math.floor(l*100)/100;return n.style.fontSize=`${f}px`,f}function c(t){let e=()=>{for(let o of Array.from(t.document.querySelectorAll(\'[data-ff-fit="shrink"]\')))m(o,t);t.document.documentElement.setAttribute("data-ff-fit","done")};t.formfeedFit=e;let n=t.document.fonts;n?n.ready.then(e):t.addEventListener("load",e)}c(window);})();';
5374
- var stageRuntime = '"use strict";(()=>{var I=`\nhtml.ff-edit-mode [data-ff-edit] { cursor: text; }\nhtml.ff-edit-mode [data-ff-edit]:hover { outline: 1px dashed rgba(37,99,235,.85); outline-offset: 2px; }\nhtml.ff-edit-mode [data-ff-edit="t"]:hover { outline-color: rgba(147,51,234,.9); }\n.ff-editing { outline: 2px solid #2563eb !important; outline-offset: 2px; cursor: text; }\n.ff-editing .ff-chip { background: rgba(37,99,235,.14) !important; box-shadow: inset 0 0 0 1px rgba(37,99,235,.45) !important; border-radius: 3px !important; padding: 0 1px !important; cursor: default; }\n.ff-edit-badge { position: absolute; z-index: 2147483647; font: 500 11px/1.4 system-ui, sans-serif !important; color: #fff !important; background: #2563eb !important; padding: 1px 6px !important; border-radius: 4px !important; pointer-events: none; white-space: nowrap; }\n`;function D(a,l={}){let f=l.clicks!==!1,c=l.live===!0,o=a.document,n=null,s=null,u=e=>{try{a.parent.postMessage(e,"*")}catch{}},p=o.createElement("style");p.setAttribute("data-formfeed","edit"),p.setAttribute("data-pagedjs-ignore",""),p.textContent=I,(o.head??o.documentElement).appendChild(p),f&&o.documentElement.classList.add("ff-edit-mode");let d=e=>(e&&typeof e.closest=="function"?e:null)?.closest("[data-ff-edit]")??null;o.addEventListener("click",e=>{if(!f)return;if(n&&!n.done&&n.element.contains(e.target)){e.stopImmediatePropagation();return}let t=d(e.target);if(!t)return;e.preventDefault(),e.stopImmediatePropagation(),n&&!n.done&&v();let r=t.getAttribute("data-ff-src")??"",i=t.getBoundingClientRect();s={src:r,element:t,x:e.clientX,y:e.clientY},u({type:"formfeed:edit-request",src:r,edit:t.getAttribute("data-ff-edit"),text:t.textContent??"",count:o.querySelectorAll(`[data-ff-src="${r.replace(/"/g,"")}"]`).length,split:t.hasAttribute("data-split-from")||t.hasAttribute("data-split-to"),rect:{left:i.left,top:i.top,width:i.width,height:i.height}})},!0),o.addEventListener("keydown",e=>{if(!f||n&&!n.done||!(e.ctrlKey||e.metaKey)||e.altKey)return;let t=e.key.toLowerCase();(t==="z"||t==="y")&&(e.preventDefault(),u({type:t==="y"||e.shiftKey?"formfeed:redo":"formfeed:undo"}))}),a.addEventListener("message",e=>{if(e.source!==a.parent)return;let t=e.data;!t||typeof t.type!="string"||(t.type==="formfeed:edit-begin"?b(t):(t.type==="formfeed:edit-refuse"||t.type==="formfeed:edit-end")&&(s=null,n&&!n.done&&L(!1)))});function b(e){n&&!n.done&&L(!1);let t=e.layer?o.querySelector(`[data-ff-layer="${String(e.layer).replace(/"/g,"")}"] > .ff-text`):s&&s.src===e.src?s.element:o.querySelector(`[data-ff-src="${String(e.src).replace(/"/g,"")}"]`),r=e.at,i=e.layer?r&&Number.isFinite(r.x)&&Number.isFinite(r.y)?{x:Number(r.x),y:Number(r.y)}:null:s&&s.src===e.src?s:null;if(s=null,!t||!Array.isArray(e.items)){u({type:"formfeed:edit-cancel",token:String(e.token)});return}let x=Array.from(t.childNodes),g=o.createDocumentFragment();for(let y of e.items)if(y.kind==="text")g.appendChild(o.createTextNode(String(y.text)));else if(y.kind==="break")g.appendChild(o.createElement("br"));else if(y.kind==="chip"){let m=o.createElement("span");m.className="ff-chip",m.setAttribute("data-ff-chip",String(y.index)),m.setAttribute("contenteditable","false"),y.title&&(m.title=String(y.title)),m.textContent=String(y.text),g.appendChild(m)}for(let y of x)t.removeChild(y);t.appendChild(g),t.contentEditable="true",t.classList.add("ff-editing"),t.setAttribute("role","textbox"),e.label&&t.setAttribute("aria-label",String(e.label)),t.spellcheck=!0,n={token:String(e.token),element:t,saved:x,allowBreaks:e.allowBreaks===!0,badge:e.note?E(t,String(e.note)):null,done:!1},t.addEventListener("keydown",C),t.addEventListener("beforeinput",S),t.addEventListener("paste",A),t.addEventListener("drop",T),t.addEventListener("focusout",N),c&&t.addEventListener("input",k),t.focus(),e.select==="all"?H(t):M(t,i),u({type:"formfeed:edit-started",token:n.token}),typeof e.insert=="string"&&e.insert&&h(e.insert.replace(/\\r\\n?|\\n/g," "))}function h(e){if(typeof o.execCommand=="function"&&o.execCommand("insertText",!1,e))return;let t=a.getSelection(),r=t&&t.rangeCount?t.getRangeAt(0):null;r&&(r.deleteContents(),r.insertNode(o.createTextNode(e)),r.collapse(!1),c&&k())}function k(){n&&!n.done&&u({type:"formfeed:edit-input",token:n.token,items:w(n.element)})}function E(e,t){let r=o.createElement("div");r.className="ff-edit-badge",r.textContent=t;let i=e.getBoundingClientRect();return r.style.left=`${i.left+a.scrollX}px`,r.style.top=`${Math.max(0,i.top+a.scrollY-22)}px`,o.body.appendChild(r),r}function H(e){let t=a.getSelection();if(!t)return;let r=o.createRange();r.selectNodeContents(e),t.removeAllRanges(),t.addRange(r)}function M(e,t){let r=a.getSelection();if(!r)return;let i=null,x=o;if(t){if(x.caretRangeFromPoint)i=x.caretRangeFromPoint(t.x,t.y);else if(x.caretPositionFromPoint){let g=x.caretPositionFromPoint(t.x,t.y);g&&(i=o.createRange(),i.setStart(g.offsetNode,g.offset))}}if(!i||!e.contains(i.startContainer))i=o.createRange(),i.selectNodeContents(e),i.collapse(!1);else if(t){let g=i.startContainer,m=(g.nodeType===1?g:g.parentElement)?.closest("[data-ff-chip]")??null;if(m&&m!==e&&e.contains(m)){let F=m.getBoundingClientRect();i=o.createRange(),t.x<F.left+F.width/2?i.setStartBefore(m):i.setStartAfter(m),i.collapse(!0)}}r.removeAllRanges(),r.addRange(i)}function C(e){let t=e.key;t==="Escape"?(e.preventDefault(),L(!0)):t==="Enter"&&!e.shiftKey?(e.preventDefault(),v()):t==="Enter"?(e.preventDefault(),n?.allowBreaks&&P()):t==="Tab"?(e.preventDefault(),v()):(e.ctrlKey||e.metaKey)&&["b","i","u"].includes(t.toLowerCase())&&(e.preventDefault(),c&&n&&!e.altKey&&u({type:"formfeed:edit-style",token:n.token,key:t.toLowerCase()}))}function S(e){let t=e.inputType??"";(t.startsWith("format")||t==="insertFromDrop"||t==="insertParagraph"||t==="insertLineBreak")&&e.preventDefault()}function A(e){e.preventDefault(),h((e.clipboardData?.getData("text/plain")??"").replace(/\\r\\n?|\\n/g," "))}function T(e){e.preventDefault()}function N(){a.setTimeout(()=>{n&&!n.done&&(!o.hasFocus()||!n.element.contains(o.activeElement))&&v()},0)}function P(){let e=a.getSelection();if(!e||!e.rangeCount)return;let t=e.getRangeAt(0);t.deleteContents();let r=o.createElement("br");t.insertNode(r),r.nextSibling||r.parentNode?.appendChild(o.createElement("br"));let i=o.createRange();i.setStartAfter(r),i.collapse(!0),e.removeAllRanges(),e.addRange(i)}function R(e){e.done=!0;let t=e.element;t.removeEventListener("keydown",C),t.removeEventListener("beforeinput",S),t.removeEventListener("paste",A),t.removeEventListener("drop",T),t.removeEventListener("focusout",N),t.removeEventListener("input",k),t.removeAttribute("contenteditable"),t.removeAttribute("role"),t.removeAttribute("aria-label"),t.classList.remove("ff-editing"),e.badge?.remove(),n===e&&(n=null)}function v(){let e=n;if(!e||e.done)return;let t=w(e.element);R(e),u({type:"formfeed:edit-commit",token:e.token,items:t})}function L(e){let t=n;if(!t||t.done)return;let r=t.element;for(;r.firstChild;)r.removeChild(r.firstChild);for(let i of t.saved)r.appendChild(i);R(t),e&&u({type:"formfeed:edit-cancel",token:t.token})}}function w(a){let l=[],f=o=>{let n=l[l.length-1];n?.kind==="text"?n.text+=o:o&&l.push({kind:"text",text:o})},c=o=>{for(let n of Array.from(o.childNodes))if(n.nodeType===3)f(n.data);else if(n.nodeType===1){let s=n,u=s.getAttribute("data-ff-chip");u!==null?l.push({kind:"chip",index:Number(u)}):s.tagName==="BR"?l.push({kind:"break"}):((s.tagName==="DIV"||s.tagName==="P")&&l.length&&l.push({kind:"break"}),c(s))}};for(c(a);l[l.length-1]?.kind==="break";)l.pop();return l}function K(a,l){return Array.from(a.querySelectorAll("[data-ff-layer]")).map(f=>{let c=f.querySelector(":scope > .ff-text"),o=!1;if(c&&f.style.height!=="auto"){let n=l.getComputedStyle(f),s=f.clientHeight-(parseFloat(n.paddingTop)||0)-(parseFloat(n.paddingBottom)||0);o=n.overflow==="hidden"&&(c.scrollHeight>s+1||c.scrollWidth>c.clientWidth+1)}return{id:f.getAttribute("data-ff-layer")??"",width:f.offsetWidth,height:f.offsetHeight,overflow:o}})}function B(a){let l=a.document,f=p=>{try{a.parent.postMessage(p,"*")}catch{}},c=p=>typeof p=="string"?l.querySelector(`[data-ff-layer="${p.replace(/"/g,"")}"]`):null,o=()=>{for(let p of Array.from(l.querySelectorAll("[data-ff-layer]")))for(let d of["left","top","width","height","transform"])p.style.removeProperty(d)},n=()=>{a.formfeedFit?.(),f({type:"formfeed:ready",layers:K(l,a)})};a.addEventListener("message",p=>{if(p.source!==a.parent)return;let d=p.data;if(!(!d||typeof d.type!="string")){if(d.type==="formfeed:layer-style"){let b=c(d.id);if(!b)return;let h=(k,E)=>{typeof E=="number"&&Number.isFinite(E)&&b.style.setProperty(k,`${E}px`)};h("left",d.left),h("top",d.top),h("width",d.width),h("height",d.height),typeof d.rotation=="number"&&Number.isFinite(d.rotation)&&b.style.setProperty("transform",d.rotation?`rotate(${d.rotation}deg)`:"none")}else if(d.type==="formfeed:layer-style-clear")o();else if(d.type==="formfeed:css"&&typeof d.css=="string"){let b=l.querySelector(\'style[data-formfeed="template"]\');b&&(b.textContent=d.css),o(),n()}}}),D(a,{clicks:!1,live:!0});let s=l.fonts,u=()=>s?void s.ready.then(n):n();l.readyState==="complete"?u():a.addEventListener("load",u)}B(window);})();';
5374
+ var stageRuntime = '"use strict";(()=>{var W=`\nhtml.ff-edit-mode [data-ff-edit] { cursor: text; }\nhtml.ff-edit-mode [data-ff-edit]:hover { outline: 1px dashed rgba(37,99,235,.85); outline-offset: 2px; }\nhtml.ff-edit-mode [data-ff-edit="t"]:hover { outline-color: rgba(147,51,234,.9); }\n.ff-editing { outline: 2px solid #2563eb !important; outline-offset: 2px; cursor: text; }\n.ff-editing .ff-chip { background: rgba(37,99,235,.14) !important; box-shadow: inset 0 0 0 1px rgba(37,99,235,.45) !important; border-radius: 3px !important; padding: 0 1px !important; cursor: default; }\n.ff-edit-badge { position: absolute; z-index: 2147483647; font: 500 11px/1.4 system-ui, sans-serif !important; color: #fff !important; background: #2563eb !important; padding: 1px 6px !important; border-radius: 4px !important; pointer-events: none; white-space: nowrap; }\n`;function H(a,l={}){let f=l.clicks!==!1,p=l.live===!0,n=a.document,o=null,d=null,u=e=>{try{a.parent.postMessage(e,"*")}catch{}},m=f?n.querySelector(\'meta[name="formfeed:document"]\')?.getAttribute("content")??null:null,s=!1;a.addEventListener("blur",()=>{s=!0}),a.addEventListener("focus",()=>{s=!1});let g=n.createElement("style");g.setAttribute("data-formfeed","edit"),g.setAttribute("data-pagedjs-ignore",""),g.textContent=W,(n.head??n.documentElement).appendChild(g),f&&n.documentElement.classList.add("ff-edit-mode");let x=e=>(e&&typeof e.closest=="function"?e:null)?.closest("[data-ff-edit]")??null;n.addEventListener("click",e=>{if(!f)return;if(o&&!o.done&&o.element.contains(e.target)){e.stopImmediatePropagation();return}let t=x(e.target);t&&(e.preventDefault(),e.stopImmediatePropagation(),v(t,{x:e.clientX,y:e.clientY}))},!0);function v(e,t){o&&!o.done&&L();let r=e.getAttribute("data-ff-src")??"",i=e.getBoundingClientRect(),b=Array.from(n.querySelectorAll(`[data-ff-src="${r.replace(/"/g,"")}"]`));d={src:r,element:e,point:t},u({type:"formfeed:edit-request",src:r,doc:m,edit:e.getAttribute("data-ff-edit"),text:e.textContent??"",elements:e.childElementCount,count:b.length,index:Math.max(0,b.indexOf(e)),split:e.hasAttribute("data-split-from")||e.hasAttribute("data-split-to"),rect:{left:i.left,top:i.top,width:i.width,height:i.height}})}n.addEventListener("keydown",e=>{if(!f||o&&!o.done||!(e.ctrlKey||e.metaKey)||e.altKey)return;let t=e.key.toLowerCase();(t==="z"||t==="y")&&(e.preventDefault(),u({type:t==="y"||e.shiftKey?"formfeed:redo":"formfeed:undo"}))}),a.addEventListener("message",e=>{if(e.source!==a.parent)return;let t=e.data;!t||typeof t.type!="string"||(t.type==="formfeed:edit-begin"?B(t):t.type==="formfeed:edit-refuse"||t.type==="formfeed:edit-end"?(d=null,o&&!o.done&&S(!1)):t.type==="formfeed:edit-open"&&E(t))});function E(e){if(!f||typeof e.src!="string"||o&&!o.done)return;let t=Array.from(n.querySelectorAll(`[data-ff-src="${e.src.replace(/"/g,"")}"][data-ff-edit]`)),r=Number.isInteger(e.index)?Number(e.index):0,i=t[r]??t[0];i&&v(i,null)}if(f){let e=()=>u({type:"formfeed:edit-ready",doc:m}),t=a;t.PagedConfig?t.formfeedEditReady=e:n.readyState==="loading"?n.addEventListener("DOMContentLoaded",e):e()}function B(e){o&&!o.done&&S(!1);let t=e.layer?n.querySelector(`[data-ff-layer="${String(e.layer).replace(/"/g,"")}"] > .ff-text`):d&&d.src===e.src?d.element:n.querySelector(`[data-ff-src="${String(e.src).replace(/"/g,"")}"]`),r=e.at,i=e.layer?r&&Number.isFinite(r.x)&&Number.isFinite(r.y)?{x:Number(r.x),y:Number(r.y)}:null:d&&d.src===e.src?d.point:null;d=null;let b=s&&!n.hasFocus();if(!t||!Array.isArray(e.items)||b){u({type:"formfeed:edit-cancel",token:String(e.token)});return}let y=Array.from(t.childNodes),k=n.createDocumentFragment();for(let c of e.items)if(c.kind==="text")k.appendChild(n.createTextNode(String(c.text)));else if(c.kind==="break")k.appendChild(n.createElement("br"));else if(c.kind==="chip"){let h=n.createElement("span");h.className="ff-chip",h.setAttribute("data-ff-chip",String(c.index)),h.setAttribute("contenteditable","false"),c.title&&(h.title=String(c.title)),h.textContent=String(c.text),k.appendChild(h)}for(let c of y)t.removeChild(c);t.appendChild(k),t.contentEditable="true",t.classList.add("ff-editing"),t.setAttribute("role","textbox"),e.label&&t.setAttribute("aria-label",String(e.label)),t.spellcheck=!0,o={token:String(e.token),element:t,saved:y,allowBreaks:e.allowBreaks===!0,badge:e.note?I(t,String(e.note)):null,done:!1},t.addEventListener("keydown",T),t.addEventListener("beforeinput",N),t.addEventListener("paste",w),t.addEventListener("drop",R),t.addEventListener("focusout",F),p&&t.addEventListener("input",C),t.focus(),e.select==="all"?q(t):K(t,i),u({type:"formfeed:edit-started",token:o.token}),typeof e.insert=="string"&&e.insert&&A(e.insert.replace(/\\r\\n?|\\n/g," "))}function A(e){if(typeof n.execCommand=="function"&&n.execCommand("insertText",!1,e))return;let t=a.getSelection(),r=t&&t.rangeCount?t.getRangeAt(0):null;r&&(r.deleteContents(),r.insertNode(n.createTextNode(e)),r.collapse(!1),p&&C())}function C(){o&&!o.done&&u({type:"formfeed:edit-input",token:o.token,items:D(o.element)})}function I(e,t){let r=n.createElement("div");r.className="ff-edit-badge",r.textContent=t;let i=e.getBoundingClientRect();return r.style.left=`${i.left+a.scrollX}px`,r.style.top=`${Math.max(0,i.top+a.scrollY-22)}px`,n.body.appendChild(r),r}function q(e){let t=a.getSelection();if(!t)return;let r=n.createRange();r.selectNodeContents(e),t.removeAllRanges(),t.addRange(r)}function K(e,t){let r=a.getSelection();if(!r)return;let i=null,b=n;if(t){if(b.caretRangeFromPoint)i=b.caretRangeFromPoint(t.x,t.y);else if(b.caretPositionFromPoint){let y=b.caretPositionFromPoint(t.x,t.y);y&&(i=n.createRange(),i.setStart(y.offsetNode,y.offset))}}if(!i||!e.contains(i.startContainer))i=n.createRange(),i.selectNodeContents(e),i.collapse(!1);else if(t){let y=i.startContainer,c=(y.nodeType===1?y:y.parentElement)?.closest("[data-ff-chip]")??null;if(c&&c!==e&&e.contains(c)){let h=c.getBoundingClientRect();i=n.createRange(),t.x<h.left+h.width/2?i.setStartBefore(c):i.setStartAfter(c),i.collapse(!0)}}r.removeAllRanges(),r.addRange(i)}function T(e){let t=e.key;t==="Escape"?(e.preventDefault(),S(!0)):t==="Enter"&&!e.shiftKey?(e.preventDefault(),L()):t==="Enter"?(e.preventDefault(),o?.allowBreaks&&$()):t==="Tab"?(e.preventDefault(),L()):(e.ctrlKey||e.metaKey)&&["b","i","u"].includes(t.toLowerCase())&&(e.preventDefault(),p&&o&&!e.altKey&&u({type:"formfeed:edit-style",token:o.token,key:t.toLowerCase()}))}function N(e){let t=e.inputType??"";(t.startsWith("format")||t==="insertFromDrop"||t==="insertParagraph"||t==="insertLineBreak")&&e.preventDefault()}function w(e){e.preventDefault(),A((e.clipboardData?.getData("text/plain")??"").replace(/\\r\\n?|\\n/g," "))}function R(e){e.preventDefault()}function F(){a.setTimeout(()=>{o&&!o.done&&(!n.hasFocus()||!o.element.contains(n.activeElement))&&L()},0)}function $(){let e=a.getSelection();if(!e||!e.rangeCount)return;let t=e.getRangeAt(0);t.deleteContents();let r=n.createElement("br");t.insertNode(r),r.nextSibling||r.parentNode?.appendChild(n.createElement("br"));let i=n.createRange();i.setStartAfter(r),i.collapse(!0),e.removeAllRanges(),e.addRange(i)}function M(e){e.done=!0;let t=e.element;t.removeEventListener("keydown",T),t.removeEventListener("beforeinput",N),t.removeEventListener("paste",w),t.removeEventListener("drop",R),t.removeEventListener("focusout",F),t.removeEventListener("input",C),t.removeAttribute("contenteditable"),t.removeAttribute("role"),t.removeAttribute("aria-label"),t.classList.remove("ff-editing"),e.badge?.remove(),o===e&&(o=null)}function L(){let e=o;if(!e||e.done)return;let t=D(e.element);M(e),u({type:"formfeed:edit-commit",token:e.token,items:t})}function S(e){let t=o;if(!t||t.done)return;let r=t.element;for(;r.firstChild;)r.removeChild(r.firstChild);for(let i of t.saved)r.appendChild(i);M(t),e&&u({type:"formfeed:edit-cancel",token:t.token})}}function D(a){let l=[],f=n=>{let o=l[l.length-1];o?.kind==="text"?o.text+=n:n&&l.push({kind:"text",text:n})},p=n=>{for(let o of Array.from(n.childNodes))if(o.nodeType===3)f(o.data);else if(o.nodeType===1){let d=o,u=d.getAttribute("data-ff-chip");u!==null?l.push({kind:"chip",index:Number(u)}):d.tagName==="BR"?l.push({kind:"break"}):((d.tagName==="DIV"||d.tagName==="P")&&l.length&&l.push({kind:"break"}),p(d))}};for(p(a);l[l.length-1]?.kind==="break";)l.pop();return l}function O(a,l){return Array.from(a.querySelectorAll("[data-ff-layer]")).map(f=>{let p=f.querySelector(":scope > .ff-text"),n=!1;if(p&&f.style.height!=="auto"){let o=l.getComputedStyle(f),d=f.clientHeight-(parseFloat(o.paddingTop)||0)-(parseFloat(o.paddingBottom)||0);n=o.overflow==="hidden"&&(p.scrollHeight>d+1||p.scrollWidth>p.clientWidth+1)}return{id:f.getAttribute("data-ff-layer")??"",width:f.offsetWidth,height:f.offsetHeight,overflow:n}})}function P(a){let l=a.document,f=m=>{try{a.parent.postMessage(m,"*")}catch{}},p=m=>typeof m=="string"?l.querySelector(`[data-ff-layer="${m.replace(/"/g,"")}"]`):null,n=()=>{for(let m of Array.from(l.querySelectorAll("[data-ff-layer]")))for(let s of["left","top","width","height","transform"])m.style.removeProperty(s)},o=()=>{a.formfeedFit?.(),f({type:"formfeed:ready",layers:O(l,a)})};a.addEventListener("message",m=>{if(m.source!==a.parent)return;let s=m.data;if(!(!s||typeof s.type!="string")){if(s.type==="formfeed:layer-style"){let g=p(s.id);if(!g)return;let x=(v,E)=>{typeof E=="number"&&Number.isFinite(E)&&g.style.setProperty(v,`${E}px`)};x("left",s.left),x("top",s.top),x("width",s.width),x("height",s.height),typeof s.rotation=="number"&&Number.isFinite(s.rotation)&&g.style.setProperty("transform",s.rotation?`rotate(${s.rotation}deg)`:"none")}else if(s.type==="formfeed:layer-style-clear")n();else if(s.type==="formfeed:css"&&typeof s.css=="string"){let g=l.querySelector(\'style[data-formfeed="template"]\');g&&(g.textContent=s.css),n(),o()}}}),H(a,{clicks:!1,live:!0});let d=l.fonts,u=()=>d?void d.ready.then(o):o();l.readyState==="complete"?u():a.addEventListener("load",u)}P(window);})();';
5375
5375
 
5376
5376
  // packages/engine/src/lib/assemble.ts
5377
5377
  var DEFAULT_CHROME_PADDING = "0 10mm";
@@ -5606,6 +5606,13 @@ document.addEventListener('click', function (event) {
5606
5606
  if (!el || el.nodeType !== 1) return;
5607
5607
  try {
5608
5608
  var annotated = el.closest ? el.closest('[data-ff-src]') : null;
5609
+ // the paper around the template (the page's margins, the pane behind it) is no element of it:
5610
+ // a click there asks for nothing
5611
+ if (!annotated && (
5612
+ el === document.documentElement || el === document.body ||
5613
+ el.querySelector('[data-ff-src]') ||
5614
+ (el.closest && el.closest('[class*="pagedjs_"]') === el)
5615
+ )) return;
5609
5616
  parent.postMessage({
5610
5617
  type: 'formfeed:inspect',
5611
5618
  src: annotated ? annotated.getAttribute('data-ff-src') : null,
@@ -5619,6 +5626,10 @@ document.addEventListener('click', function (event) {
5619
5626
  }, true);
5620
5627
  </script>`;
5621
5628
  var textEditScript = `<script>${textEditRuntime.replace(/<\/script/gi, "<\\/script")}</script>`;
5629
+ function documentMeta(options) {
5630
+ const name = (options.document ?? "").replace(/[^A-Za-z0-9_-]/g, "");
5631
+ return name ? `<meta name="formfeed:document" content="${name}">` : "";
5632
+ }
5622
5633
  var pageNavScript = `<script>
5623
5634
  (function () {
5624
5635
  var pages = function () { return document.querySelectorAll('.pagedjs_page'); };
@@ -5753,7 +5764,7 @@ body.formfeed-preview { position: relative; box-sizing: border-box; width: ${pap
5753
5764
  const footer = footerHtml ? `<div class="formfeed-chrome" style="${pdf ? flowChromeStyle(settings, "footer") : `${chromeBoxStyle(settings, "footer")}margin-top:8px`}">${pageNumberSpans(footerHtml, "1", "1")}</div>` : "";
5754
5765
  return intoHead(
5755
5766
  draft.document,
5756
- `${chrome}${options.editing ? textEditScript : ""}${inspectScript}${zoomGestureScript}${pdf ? overflowScript("flow") : ""}`
5767
+ `${documentMeta(options)}${chrome}${options.editing ? textEditScript : ""}${inspectScript}${zoomGestureScript}${pdf ? overflowScript("flow") : ""}`
5757
5768
  ).replace(/(<body[^>]*>)/, `$1${header}`).replace("</body>", `${footer}</body>`);
5758
5769
  }
5759
5770
  function canvasDocument(draft) {
@@ -5781,13 +5792,13 @@ html { background: #e5e7eb; }
5781
5792
  `;
5782
5793
  const selectorGuard = `<script>(function(){var q=DocumentFragment.prototype.querySelectorAll;DocumentFragment.prototype.querySelectorAll=function(s){try{return q.call(this,s);}catch(e){console.warn('formfeed paged preview: skipped a selector Paged.js could not use:',s);return q.call(this,':not(*)');}};})();</script>`;
5783
5794
  const boxSizingGuard = `<script>(function(){var rule='.pagedjs_pagebox *';var o=new MutationObserver(function(ms){ms.forEach(function(m){m.addedNodes.forEach(function(n){if(n.nodeName==='STYLE'&&n.textContent&&n.textContent.indexOf(rule)>=0){n.textContent=n.textContent.split(rule).join('.pagedjs_pagebox [class*="pagedjs_"]');o.disconnect();}});});});o.observe(document.documentElement,{childList:true,subtree:true});})();</script>`;
5784
- const config = `<script>window.PagedConfig = { auto: true, after: function (flow) { try { if (window.formfeedDrawCharts) window.formfeedDrawCharts(); } catch (e) {} try { if (window.formfeedFit) window.formfeedFit(); } catch (e) {} try { parent.postMessage({ type: 'formfeed:pages', pages: flow.total }, '*'); } catch (e) {} if (window.formfeedCheckOverflow) window.formfeedCheckOverflow(); } };</script>`;
5795
+ const config = `<script>window.PagedConfig = { auto: true, after: function (flow) { try { if (window.formfeedDrawCharts) window.formfeedDrawCharts(); } catch (e) {} try { if (window.formfeedFit) window.formfeedFit(); } catch (e) {} try { parent.postMessage({ type: 'formfeed:pages', pages: flow.total }, '*'); } catch (e) {} if (window.formfeedCheckOverflow) window.formfeedCheckOverflow(); try { if (window.formfeedEditReady) window.formfeedEditReady(); } catch (e) {} } };</script>`;
5785
5796
  const script = `<script src="${options.pagedScriptUrl}"></script>`;
5786
5797
  const header = headerHtml ? `<div class="ff-running-header">${pageNumberSpans(headerHtml, '<span class="ff-page-no"></span>', '<span class="ff-page-total"></span>')}</div>` : "";
5787
5798
  const footer = footerHtml ? `<div class="ff-running-footer">${pageNumberSpans(footerHtml, '<span class="ff-page-no"></span>', '<span class="ff-page-total"></span>')}</div>` : "";
5788
5799
  return intoHead(
5789
5800
  draft.document,
5790
- `<style data-formfeed="paged">${runningCss}</style>${selectorGuard}${boxSizingGuard}${overflowScript("paged")}${config}${script}${options.editing ? textEditScript : ""}${inspectScript}${pageNavScript}${zoomGestureScript}`
5801
+ `${documentMeta(options)}<style data-formfeed="paged">${runningCss}</style>${selectorGuard}${boxSizingGuard}${overflowScript("paged")}${config}${script}${options.editing ? textEditScript : ""}${inspectScript}${pageNavScript}${zoomGestureScript}`
5791
5802
  ).replace(/(<body[^>]*>)/, `$1${header}${footer}`);
5792
5803
  }
5793
5804
 
@@ -6020,11 +6031,11 @@ function locate(starts, offset) {
6020
6031
  }
6021
6032
  return { line: low + 1, column: offset - (starts[low] ?? 0) + 1 };
6022
6033
  }
6023
- function offsetOf(starts, sourceLength, line, column) {
6024
- const start = starts[line - 1];
6034
+ function offsetOf(starts, sourceLength, line2, column) {
6035
+ const start = starts[line2 - 1];
6025
6036
  if (start === void 0 || column < 1) return null;
6026
6037
  const offset = start + column - 1;
6027
- const next = starts[line] ?? sourceLength + 1;
6038
+ const next = starts[line2] ?? sourceLength + 1;
6028
6039
  return offset < next ? offset : null;
6029
6040
  }
6030
6041
 
@@ -6180,7 +6191,10 @@ function editableRegionAt(source, engine, at) {
6180
6191
  const hasText = region.parts.some(
6181
6192
  (p) => p.kind === "text" && decodeText2(source.slice(p.start, p.end)).text.trim() !== ""
6182
6193
  );
6183
- return hasText ? region : { reason: "no-text" };
6194
+ const hasField = region.parts.some(
6195
+ (p) => p.kind === "chip" && p.chip === "expression"
6196
+ );
6197
+ return hasText || hasField ? region : { reason: "no-text" };
6184
6198
  }
6185
6199
  function findRegionAgain(source, engine, outer) {
6186
6200
  const first = source.indexOf(outer);
@@ -6188,6 +6202,9 @@ function findRegionAgain(source, engine, outer) {
6188
6202
  const found = editableRegionAt(source, engine, first);
6189
6203
  return "reason" in found ? null : found;
6190
6204
  }
6205
+ function regionPosition(source, region) {
6206
+ return locate(lineStarts(source), region.tagStart);
6207
+ }
6191
6208
  function regionChips(source, region) {
6192
6209
  const chips = [];
6193
6210
  for (const part of region.parts)
@@ -6272,18 +6289,18 @@ function applyRegionEdit(source, engine, region, items) {
6272
6289
  const rewritten = source.slice(0, region.start) + whole + source.slice(region.end);
6273
6290
  return readsBack(rewritten, engine, region.tagStart, expected) ? { source: rewritten } : { error: "invalid" };
6274
6291
  }
6275
- function translationItems(text2) {
6292
+ function translationItems(text3) {
6276
6293
  const items = [];
6277
6294
  const names = [];
6278
6295
  let last = 0;
6279
- for (const match of text2.matchAll(/\{(\w+)\}/g)) {
6296
+ for (const match of text3.matchAll(/\{(\w+)\}/g)) {
6280
6297
  if (match.index > last)
6281
- items.push({ kind: "text", text: text2.slice(last, match.index) });
6298
+ items.push({ kind: "text", text: text3.slice(last, match.index) });
6282
6299
  items.push({ kind: "chip", index: names.length });
6283
6300
  names.push(match[1] ?? "");
6284
6301
  last = match.index + match[0].length;
6285
6302
  }
6286
- if (last < text2.length) items.push({ kind: "text", text: text2.slice(last) });
6303
+ if (last < text3.length) items.push({ kind: "text", text: text3.slice(last) });
6287
6304
  return { items, names };
6288
6305
  }
6289
6306
  function translationText(items, names) {
@@ -6527,9 +6544,9 @@ function translationCall(engine, inner) {
6527
6544
  );
6528
6545
  return match ? { key: match[2] ?? "", params: parseParams(match[3] ?? "", "=", " ") } : null;
6529
6546
  }
6530
- function parseParams(text2, assign, separator) {
6547
+ function parseParams(text3, assign, separator) {
6531
6548
  const params = {};
6532
- for (const piece of splitTopLevel(text2, separator)) {
6549
+ for (const piece of splitTopLevel(text3, separator)) {
6533
6550
  const at = piece.indexOf(assign);
6534
6551
  if (at <= 0) continue;
6535
6552
  const name = piece.slice(0, at).trim().replace(/^['"]|['"]$/g, "");
@@ -6537,12 +6554,12 @@ function parseParams(text2, assign, separator) {
6537
6554
  }
6538
6555
  return params;
6539
6556
  }
6540
- function splitTopLevel(text2, separator) {
6557
+ function splitTopLevel(text3, separator) {
6541
6558
  const pieces = [];
6542
6559
  let depth = 0;
6543
6560
  let quote2 = null;
6544
6561
  let current = "";
6545
- for (const ch of text2) {
6562
+ for (const ch of text3) {
6546
6563
  if (quote2) {
6547
6564
  if (ch === quote2) quote2 = null;
6548
6565
  } else if (ch === '"' || ch === "'") quote2 = ch;
@@ -6567,7 +6584,7 @@ function entityChar(reference) {
6567
6584
  return code === void 0 ? null : String.fromCharCode(code);
6568
6585
  }
6569
6586
  function decodeText2(raw) {
6570
- let text2 = "";
6587
+ let text3 = "";
6571
6588
  const map = [];
6572
6589
  let i = 0;
6573
6590
  while (i < raw.length) {
@@ -6577,23 +6594,23 @@ function decodeText2(raw) {
6577
6594
  const decoded = match ? entityChar(match[1] ?? "") : null;
6578
6595
  if (match && decoded !== null) {
6579
6596
  for (let u = 0; u < decoded.length; u++) map.push(i);
6580
- text2 += decoded;
6597
+ text3 += decoded;
6581
6598
  i += match[0].length;
6582
6599
  continue;
6583
6600
  }
6584
6601
  }
6585
- text2 += raw[i];
6602
+ text3 += raw[i];
6586
6603
  map.push(i);
6587
6604
  i++;
6588
6605
  }
6589
6606
  map.push(raw.length);
6590
- return { text: text2, map };
6607
+ return { text: text3, map };
6591
6608
  }
6592
- function encodeText(text2, keepNbsp, allBraces = false) {
6609
+ function encodeText(text3, keepNbsp, allBraces = false) {
6593
6610
  let out = "";
6594
- for (let k = 0; k < text2.length; k++) {
6595
- const ch = text2[k] ?? "";
6596
- const next = text2[k + 1];
6611
+ for (let k = 0; k < text3.length; k++) {
6612
+ const ch = text3[k] ?? "";
6613
+ const next = text3[k + 1];
6597
6614
  if (ch === "&") out += "&amp;";
6598
6615
  else if (ch === "<") out += "&lt;";
6599
6616
  else if (ch === ">") out += "&gt;";
@@ -6605,8 +6622,8 @@ function encodeText(text2, keepNbsp, allBraces = false) {
6605
6622
  }
6606
6623
  return out;
6607
6624
  }
6608
- function encodeTemplateText(text2) {
6609
- return encodeText(text2, true);
6625
+ function encodeTemplateText(text3) {
6626
+ return encodeText(text3, true);
6610
6627
  }
6611
6628
  function spanOf(part) {
6612
6629
  return part ? [part.start, part.end] : [0, 0];
@@ -6640,7 +6657,7 @@ function rewriteSegment(source, segStart, segEnd, parts, next, breakSpelling) {
6640
6657
  const to = map[old.length - suffix] ?? segEnd;
6641
6658
  const middle = next.slice(prefix, next.length - suffix);
6642
6659
  const keepNbsp = old.slice(prefix, old.length - suffix).includes(NBSP);
6643
- const written = middle.split(BREAK).map((text2) => encodeText(text2, keepNbsp)).join(breakSpelling);
6660
+ const written = middle.split(BREAK).map((text3) => encodeText(text3, keepNbsp)).join(breakSpelling);
6644
6661
  return source.slice(segStart, from) + written + source.slice(to, segEnd);
6645
6662
  }
6646
6663
  var isHighSurrogate = (code) => code >= 55296 && code <= 56319;
@@ -6669,10 +6686,10 @@ var editAttribute = "data-ff-edit";
6669
6686
  function parseSourceAttribute(value) {
6670
6687
  const match = /^(body|header|footer):(\d+):(\d+)$/.exec(value ?? "");
6671
6688
  if (!match) return null;
6672
- const line = Number(match[2]);
6689
+ const line2 = Number(match[2]);
6673
6690
  const column = Number(match[3]);
6674
- if (line < 1 || column < 1) return null;
6675
- return { file: match[1], line, column };
6691
+ if (line2 < 1 || column < 1) return null;
6692
+ return { file: match[1], line: line2, column };
6676
6693
  }
6677
6694
  function annotateSourcePositions(source, engine, file, options = {}) {
6678
6695
  const scanner = new Scanner(source, engine);
@@ -6719,12 +6736,12 @@ function annotateSourcePositions(source, engine, file, options = {}) {
6719
6736
  const after = source[nameEnd];
6720
6737
  const plainName = after === void 0 || after === ">" || after === "/" || /\s/.test(after);
6721
6738
  if (plainName && !source.slice(nameEnd, end).toLowerCase().includes(sourceAttribute)) {
6722
- const { line, column } = locate(lines, i);
6739
+ const { line: line2, column } = locate(lines, i);
6723
6740
  const region = options.editable ? editableRegionAt(source, engine, i) : null;
6724
6741
  const edit = region && !("reason" in region) ? ` ${editAttribute}="${region.kind}"` : "";
6725
6742
  out.push(
6726
6743
  source.slice(copied, nameEnd),
6727
- ` ${sourceAttribute}="${file}:${line}:${column}"${edit}`
6744
+ ` ${sourceAttribute}="${file}:${line2}:${column}"${edit}`
6728
6745
  );
6729
6746
  copied = nameEnd;
6730
6747
  }
@@ -6844,8 +6861,8 @@ function parseDesign(value) {
6844
6861
  let guides;
6845
6862
  const g = v["guides"];
6846
6863
  if (g && typeof g === "object") {
6847
- const list2 = (x) => (Array.isArray(x) ? x : []).filter((n) => typeof n === "number" && Number.isFinite(n)).slice(0, 100);
6848
- guides = { x: list2(g["x"]), y: list2(g["y"]) };
6864
+ const list3 = (x) => (Array.isArray(x) ? x : []).filter((n) => typeof n === "number" && Number.isFinite(n)).slice(0, 100);
6865
+ guides = { x: list3(g["x"]), y: list3(g["y"]) };
6849
6866
  }
6850
6867
  if (problems.length) return { design: null, problems };
6851
6868
  return {
@@ -7395,11 +7412,11 @@ function googleFontsUrl(uses) {
7395
7412
 
7396
7413
  // packages/engine/src/lib/design/hash.ts
7397
7414
  function designOutputHash(html, css2) {
7398
- const text2 = `${html}\0${css2}`;
7415
+ const text3 = `${html}\0${css2}`;
7399
7416
  let a = 2166136261;
7400
7417
  let b = 16777619 ^ 2654435769;
7401
- for (let i = 0; i < text2.length; i++) {
7402
- const code = text2.charCodeAt(i);
7418
+ for (let i = 0; i < text3.length; i++) {
7419
+ const code = text3.charCodeAt(i);
7403
7420
  if (code === 13) continue;
7404
7421
  a = Math.imul(a ^ code, 16777619) >>> 0;
7405
7422
  b = Math.imul(b ^ code, 16777619) >>> 0;
@@ -7509,7 +7526,7 @@ var tokenPattern2 = /^[a-z][a-z0-9-]{0,31}$/;
7509
7526
  function emitDesign(design2, engine, size) {
7510
7527
  const lines = ['<div class="ff-design">'];
7511
7528
  const map = {};
7512
- const rules = [];
7529
+ const rules2 = [];
7513
7530
  for (const layer of design2.layers) {
7514
7531
  if (!layer.visible) continue;
7515
7532
  const markup = layerHtml(layer, engine);
@@ -7517,7 +7534,7 @@ function emitDesign(design2, engine, size) {
7517
7534
  ` ${layer.showWhen?.path ? ifBlock(engine, layer.showWhen.path, markup) : markup}`
7518
7535
  );
7519
7536
  map[layer.id] = { start: lines.length, end: lines.length };
7520
- rules.push(...layerCss(layer));
7537
+ rules2.push(...layerCss(layer));
7521
7538
  }
7522
7539
  lines.push("</div>");
7523
7540
  const html = `${lines.join("\n")}
@@ -7542,7 +7559,7 @@ function emitDesign(design2, engine, size) {
7542
7559
  })} }`,
7543
7560
  ".ff-layer { position: absolute; box-sizing: border-box; margin: 0; }"
7544
7561
  ];
7545
- const css2 = `${[...head, ...rules].join("\n")}
7562
+ const css2 = `${[...head, ...rules2].join("\n")}
7546
7563
  `;
7547
7564
  return { html, css: css2, map, output: designOutputHash(html, css2) };
7548
7565
  }
@@ -7626,32 +7643,32 @@ function imageSource(source, engine) {
7626
7643
  return `{{ brand.logo.${source.brandLogo} }}`;
7627
7644
  }
7628
7645
  function layerCss(layer) {
7629
- const text2 = layer.type === "text" ? layer : null;
7646
+ const text3 = layer.type === "text" ? layer : null;
7630
7647
  const box = {
7631
7648
  left: px(layer.x),
7632
7649
  top: px(layer.y),
7633
7650
  width: px(layer.width),
7634
- height: text2?.sizing === "grow" ? void 0 : px(layer.height),
7651
+ height: text3?.sizing === "grow" ? void 0 : px(layer.height),
7635
7652
  opacity: layer.opacity < 1 ? num(layer.opacity) : void 0,
7636
7653
  transform: layer.rotation ? `rotate(${num(layer.rotation)}deg)` : void 0,
7637
7654
  "border-radius": layer.type === "shape" && layer.shape === "ellipse" ? "50%" : layer.radius ? px(layer.radius) : void 0,
7638
7655
  border: layer.stroke && layer.stroke.width > 0 ? `${px(layer.stroke.width)} solid ${paint(layer.stroke.paint)}` : void 0,
7639
- "box-shadow": layer.shadow && !text2 ? shadow(layer.shadow) : void 0
7656
+ "box-shadow": layer.shadow && !text3 ? shadow(layer.shadow) : void 0
7640
7657
  };
7641
- if (text2) {
7658
+ if (text3) {
7642
7659
  Object.assign(box, {
7643
7660
  display: "flex",
7644
7661
  "flex-direction": "column",
7645
- "justify-content": text2.valign === "middle" ? "center" : text2.valign === "bottom" ? "flex-end" : "flex-start",
7646
- overflow: text2.sizing === "grow" ? void 0 : "hidden",
7647
- padding: text2.padding ? px(text2.padding) : void 0,
7648
- background: text2.fill ? paint(text2.fill) : void 0
7662
+ "justify-content": text3.valign === "middle" ? "center" : text3.valign === "bottom" ? "flex-end" : "flex-start",
7663
+ overflow: text3.sizing === "grow" ? void 0 : "hidden",
7664
+ padding: text3.padding ? px(text3.padding) : void 0,
7665
+ background: text3.fill ? paint(text3.fill) : void 0
7649
7666
  });
7650
- const s = text2.style;
7651
- const clamp = text2.maxLines ? {
7667
+ const s = text3.style;
7668
+ const clamp = text3.maxLines ? {
7652
7669
  display: "-webkit-box",
7653
7670
  "-webkit-box-orient": "vertical",
7654
- "-webkit-line-clamp": String(text2.maxLines),
7671
+ "-webkit-line-clamp": String(text3.maxLines),
7655
7672
  overflow: "hidden"
7656
7673
  } : {};
7657
7674
  const inner = decl({
@@ -7667,7 +7684,7 @@ function layerCss(layer) {
7667
7684
  "font-style": s.italic ? "italic" : void 0,
7668
7685
  "text-transform": s.uppercase ? "uppercase" : void 0,
7669
7686
  "text-decoration": [s.underline && "underline", s.strike && "line-through"].filter(Boolean).join(" ") || void 0,
7670
- "text-shadow": text2.shadow ? shadow(text2.shadow) : void 0,
7687
+ "text-shadow": text3.shadow ? shadow(text3.shadow) : void 0,
7671
7688
  "overflow-wrap": "break-word",
7672
7689
  ...clamp
7673
7690
  });
@@ -8006,6 +8023,2131 @@ var designStarters = [
8006
8023
  }
8007
8024
  ];
8008
8025
 
8026
+ // packages/engine/src/lib/einvoice/codes.generated.ts
8027
+ var list2 = (codes) => new Set(codes.split(" "));
8028
+ var CODE_LIST_RELEASE = "1.09.2";
8029
+ var documentTypeCodes = list2(
8030
+ "71 80 81 82 83 84 102 130 202 203 204 211 218 219 261 262 295 296 308 325 326 331 380 381 382 383 384 385 386 387 388 389 390 393 394 395 396 420 456 457 458 471 472 473 500 501 502 503 527 532 553 575 623 633 751 780 817 870 875 876 877 935"
8031
+ );
8032
+ var countryCodes = list2(
8033
+ "1A AD AE AF AG AI AL AM AO AQ AR AS AT AU AW AX AZ BA BB BD BE BF BG BH BI BJ BL BM BN BO BQ BR BS BT BV BW BY BZ CA CC CD CF CG CH CI CK CL CM CN CO CR CU CV CW CX CY CZ DE DJ DK DM DO DZ EC EE EG EH ER ES ET FI FJ FK FM FO FR GA GB GD GE GF GG GH GI GL GM GN GP GQ GR GS GT GU GW GY HK HM HN HR HT HU ID IE IL IM IN IO IQ IR IS IT JE JM JO JP KE KG KH KI KM KN KP KR KW KY KZ LA LB LC LI LK LR LS LT LU LV LY MA MC MD ME MF MG MH MK ML MM MN MO MP MQ MR MS MT MU MV MW MX MY MZ NA NC NE NF NG NI NL NO NP NR NU NZ OM PA PE PF PG PH PK PL PM PN PR PS PT PW PY QA RE RO RS RU RW SA SB SC SD SE SG SH SI SJ SK SL SM SN SO SR SS ST SV SX SY SZ TC TD TF TG TH TJ TK TL TM TN TO TR TT TV TW TZ UA UG UM US UY UZ VA VC VE VG VI VN VU WF WS XI YE YT ZA ZM ZW 1A XI"
8034
+ );
8035
+ var unitCodes = list2(
8036
+ "10 11 13 14 15 20 21 22 23 24 25 27 28 33 34 35 37 38 40 41 56 57 58 59 60 61 74 77 80 81 85 87 89 91 1I 2A 2B 2C 2G 2H 2I 2J 2K 2L 2M 2N 2P 2Q 2R 2U 2X 2Y 2Z 3B 3C 4C 4G 4H 4K 4L 4M 4N 4O 4P 4Q 4R 4T 4U 4W 4X 5A 5B 5E 5J A10 A11 A12 A13 A14 A15 A16 A17 A18 A19 A2 A20 A21 A22 A23 A24 A26 A27 A28 A29 A3 A30 A31 A32 A33 A34 A35 A36 A37 A38 A39 A4 A40 A41 A42 A43 A44 A45 A47 A48 A49 A5 A53 A54 A55 A56 A59 A6 A68 A69 A7 A70 A71 A73 A74 A75 A76 A8 A84 A85 A86 A87 A88 A89 A9 A90 A91 A93 A94 A95 A96 A97 A98 A99 AA AB ACR ACT AD AE AH AI AK AL AMH AMP ANN APZ AQ AS ASM ASU ATM AWG AY AZ B1 B10 B11 B12 B13 B14 B15 B16 B17 B18 B19 B20 B21 B22 B23 B24 B25 B26 B27 B28 B29 B3 B30 B31 B32 B33 B34 B35 B4 B41 B42 B43 B44 B45 B46 B47 B48 B49 B50 B52 B53 B54 B55 B56 B57 B58 B59 B60 B61 B62 B63 B64 B66 B67 B68 B69 B7 B70 B71 B72 B73 B74 B75 B76 B77 B78 B79 B8 B80 B81 B82 B83 B84 B85 B86 B87 B88 B89 B90 B91 B92 B93 B94 B95 B96 B97 B98 B99 BAR BB BFT BHP BIL BLD BLL BP BPM BQL BTU BUA BUI C0 C10 C11 C12 C13 C14 C15 C16 C17 C18 C19 C20 C21 C22 C23 C24 C25 C26 C27 C28 C29 C3 C30 C31 C32 C33 C34 C35 C36 C37 C38 C39 C40 C41 C42 C43 C44 C45 C46 C47 C48 C49 C50 C51 C52 C53 C54 C55 C56 C57 C58 C59 C60 C61 C62 C63 C64 C65 C66 C67 C68 C69 C7 C70 C71 C72 C73 C74 C75 C76 C78 C79 C8 C80 C81 C82 C83 C84 C85 C86 C87 C88 C89 C9 C90 C91 C92 C93 C94 C95 C96 C97 C99 CCT CDL CEL CEN CG CGM CKG CLF CLT CMK CMQ CMT CNP CNT COU CTG CTM CTN CUR CWA CWI D03 D04 D1 D10 D11 D12 D13 D15 D16 D17 D18 D19 D2 D20 D21 D22 D23 D24 D25 D26 D27 D29 D30 D31 D32 D33 D34 D36 D41 D42 D43 D44 D45 D46 D47 D48 D49 D5 D50 D51 D52 D53 D54 D55 D56 D57 D58 D59 D6 D60 D61 D62 D63 D65 D68 D69 D73 D74 D77 D78 D80 D81 D82 D83 D85 D86 D87 D88 D89 D91 D93 D94 D95 DAA DAD DAY DB DBM DBW DD DEC DG DJ DLT DMA DMK DMO DMQ DMT DN DPC DPR DPT DRA DRI DRL DT DTN DWT DZN DZP E01 E07 E08 E09 E10 E12 E14 E15 E16 E17 E18 E19 E20 E21 E22 E23 E25 E27 E28 E30 E31 E32 E33 E34 E35 E36 E37 E38 E39 E4 E40 E41 E42 E43 E44 E45 E46 E47 E48 E49 E50 E51 E52 E53 E54 E55 E56 E57 E58 E59 E60 E61 E62 E63 E64 E65 E66 E67 E68 E69 E70 E71 E72 E73 E74 E75 E76 E77 E78 E79 E80 E81 E82 E83 E84 E85 E86 E87 E88 E89 E90 E91 E92 E93 E94 E95 E96 E97 E98 E99 EA EB EQ F01 F02 F03 F04 F05 F06 F07 F08 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 F32 F33 F34 F35 F36 F37 F38 F39 F40 F41 F42 F43 F44 F45 F46 F47 F48 F49 F50 F51 F52 F53 F54 F55 F56 F57 F58 F59 F60 F61 F62 F63 F64 F65 F66 F67 F68 F69 F70 F71 F72 F73 F74 F75 F76 F77 F78 F79 F80 F81 F82 F83 F84 F85 F86 F87 F88 F89 F90 F91 F92 F93 F94 F95 F96 F97 F98 F99 FAH FAR FBM FC FF FH FIT FL FNU FOT FP FR FS FTK FTQ G01 G04 G05 G06 G08 G09 G10 G11 G12 G13 G14 G15 G16 G17 G18 G19 G2 G20 G21 G23 G24 G25 G26 G27 G28 G29 G3 G30 G31 G32 G33 G34 G35 G36 G37 G38 G39 G40 G41 G42 G43 G44 G45 G46 G47 G48 G49 G50 G51 G52 G53 G54 G55 G56 G57 G58 G59 G60 G61 G62 G63 G64 G65 G66 G67 G68 G69 G70 G71 G72 G73 G74 G75 G76 G77 G78 G79 G80 G81 G82 G83 G84 G85 G86 G87 G88 G89 G90 G91 G92 G93 G94 G95 G96 G97 G98 G99 GB GBQ GDW GE GF GFI GGR GIA GIC GII GIP GJ GL GLD GLI GLL GM GO GP GQ GRM GRN GRO GV GWH H03 H04 H05 H06 H07 H08 H09 H10 H11 H12 H13 H14 H15 H16 H18 H19 H20 H21 H22 H23 H24 H25 H26 H27 H28 H29 H30 H31 H32 H33 H34 H35 H36 H37 H38 H39 H40 H41 H42 H43 H44 H45 H46 H47 H48 H49 H50 H51 H52 H53 H54 H55 H56 H57 H58 H59 H60 H61 H62 H63 H64 H65 H66 H67 H68 H69 H70 H71 H72 H73 H74 H75 H76 H77 H79 H80 H81 H82 H83 H84 H85 H87 H88 H89 H90 H91 H92 H93 H94 H95 H96 H98 H99 HA HAD HBA HBX HC HDW HEA HGM HH HIU HKM HLT HM HMO HMQ HMT HPA HTZ HUR HWE IA IE INH INK INQ ISD IU IUG IV J10 J12 J13 J14 J15 J16 J17 J18 J19 J2 J20 J21 J22 J23 J24 J25 J26 J27 J28 J29 J30 J31 J32 J33 J34 J35 J36 J38 J39 J40 J41 J42 J43 J44 J45 J46 J47 J48 J49 J50 J51 J52 J53 J54 J55 J56 J57 J58 J59 J60 J61 J62 J63 J64 J65 J66 J67 J68 J69 J70 J71 J72 J73 J74 J75 J76 J78 J79 J81 J82 J83 J84 J85 J87 J90 J91 J92 J93 J95 J96 J97 J98 J99 JE JK JM JNT JOU JPS JWL K1 K10 K11 K12 K13 K14 K15 K16 K17 K18 K19 K2 K20 K21 K22 K23 K26 K27 K28 K3 K30 K31 K32 K33 K34 K35 K36 K37 K38 K39 K40 K41 K42 K43 K45 K46 K47 K48 K49 K50 K51 K52 K53 K54 K55 K58 K59 K6 K60 K61 K62 K63 K64 K65 K66 K67 K68 K69 K70 K71 K73 K74 K75 K76 K77 K78 K79 K80 K81 K82 K83 K84 K85 K86 K87 K88 K89 K90 K91 K92 K93 K94 K95 K96 K97 K98 K99 KA KAT KB KBA KCC KDW KEL KGM KGS KHY KHZ KI KIC KIP KJ KJO KL KLK KLX KMA KMH KMK KMQ KMT KNI KNM KNS KNT KO KPA KPH KPO KPP KR KSD KSH KT KTN KUR KVA KVR KVT KW KWH KWN KWO KWS KWT KWY KX L10 L11 L12 L13 L14 L15 L16 L17 L18 L19 L2 L20 L21 L23 L24 L25 L26 L27 L28 L29 L30 L31 L32 L33 L34 L35 L36 L37 L38 L39 L40 L41 L42 L43 L44 L45 L46 L47 L48 L49 L50 L51 L52 L53 L54 L55 L56 L57 L58 L59 L60 L63 L64 L65 L66 L67 L68 L69 L70 L71 L72 L73 L74 L75 L76 L77 L78 L79 L80 L81 L82 L83 L84 L85 L86 L87 L88 L89 L90 L91 L92 L93 L94 L95 L96 L98 L99 LA LAC LBR LBT LD LEF LF LH LK LM LN LO LP LPA LR LS LTN LTR LUB LUM LUX LY M1 M10 M11 M12 M13 M14 M15 M16 M17 M18 M19 M20 M21 M22 M23 M24 M25 M26 M27 M29 M30 M31 M32 M33 M34 M35 M36 M37 M38 M39 M4 M40 M41 M42 M43 M44 M45 M46 M47 M48 M49 M5 M50 M51 M52 M53 M55 M56 M57 M58 M59 M60 M61 M62 M63 M64 M65 M66 M67 M68 M69 M7 M70 M71 M72 M73 M74 M75 M76 M77 M78 M79 M80 M81 M82 M83 M84 M85 M86 M87 M88 M89 M9 M90 M91 M92 M93 M94 M95 M96 M97 M98 M99 MAH MAL MAM MAR MAW MBE MBF MBR MC MCU MD MGM MHZ MIK MIL MIN MIO MIU MKD MKM MKW MLD MLT MMK MMQ MMT MND MNJ MON MPA MQD MQH MQM MQS MQW MRD MRM MRW MSK MTK MTQ MTR MTS MTZ MVA MWH N1 N10 N11 N12 N13 N14 N15 N16 N17 N18 N19 N20 N21 N22 N23 N24 N25 N26 N27 N28 N29 N3 N30 N31 N32 N33 N34 N35 N36 N37 N38 N39 N40 N41 N42 N43 N44 N45 N46 N47 N48 N49 N50 N51 N52 N53 N54 N55 N56 N57 N58 N59 N60 N61 N62 N63 N64 N65 N66 N67 N68 N69 N70 N71 N72 N73 N74 N75 N76 N77 N78 N79 N80 N81 N82 N83 N84 N85 N86 N87 N88 N89 N90 N91 N92 N93 N94 N95 N96 N97 N98 N99 NA NAR NCL NEW NF NIL NIU NL NM3 NMI NMP NPT NT NTU NU NX OA ODE ODG ODK ODM OHM ON ONZ OPM OT OZA OZI P1 P10 P11 P12 P13 P14 P15 P16 P17 P18 P19 P2 P20 P21 P22 P23 P24 P25 P26 P27 P28 P29 P30 P31 P32 P33 P34 P35 P36 P37 P38 P39 P40 P41 P42 P43 P44 P45 P46 P47 P48 P49 P5 P50 P51 P52 P53 P54 P55 P56 P57 P58 P59 P60 P61 P62 P63 P64 P65 P66 P67 P68 P69 P70 P71 P72 P73 P74 P75 P76 P77 P78 P79 P80 P81 P82 P83 P84 P85 P86 P87 P88 P89 P90 P91 P92 P93 P94 P95 P96 P97 P98 P99 PAL PD PFL PGL PI PLA PO PQ PR PS PTD PTI PTL PTN Q10 Q11 Q12 Q13 Q14 Q15 Q16 Q17 Q18 Q19 Q20 Q21 Q22 Q23 Q24 Q25 Q26 Q27 Q28 Q29 Q3 Q30 Q31 Q32 Q33 Q34 Q35 Q36 Q37 Q38 Q39 Q40 Q41 Q42 QA QAN QB QR QTD QTI QTL QTR R1 R9 RH RM ROM RP RPM RPS RT S3 S4 SAN SCO SCR SEC SET SG SIE SM3 SMI SQ SQR SR STC STI STK STL STN STW SW SX SYR T0 T3 TAH TAN TI TIC TIP TKM TMS TNE TP TPI TPR TQD TRL TST TTS U1 U2 UB UC VA VLT VP W2 WA WB WCD WE WEB WEE WG WHR WM WSD WTT X1 X1A X1B X1D X1F X1G X1W X2C X3A X3H X43 X44 X4A X4B X4C X4D X4F X4G X4H X5H X5L X5M X6H X6P X7A X7B X8A X8B X8C XAA XAB XAC XAD XAE XAF XAG XAH XAI XAJ XAL XAM XAP XAT XAV XB4 XBA XBB XBC XBD XBE XBF XBG XBH XBI XBJ XBK XBL XBM XBN XBO XBP XBQ XBR XBS XBT XBU XBV XBW XBX XBY XBZ XCA XCB XCC XCD XCE XCF XCG XCH XCI XCJ XCK XCL XCM XCN XCO XCP XCQ XCR XCS XCT XCU XCV XCW XCX XCY XCZ XDA XDB XDC XDG XDH XDI XDJ XDK XDL XDM XDN XDP XDR XDS XDT XDU XDV XDW XDX XDY XEC XED XEE XEF XEG XEH XEI XEN XFB XFC XFD XFE XFI XFL XFO XFP XFR XFT XFW XFX XGB XGI XGL XGR XGU XGY XGZ XHA XHB XHC XHG XHN XHR XIA XIB XIC XID XIE XIF XIG XIH XIK XIL XIN XIZ XJB XJC XJG XJR XJT XJY XKG XKI XLE XLG XLT XLU XLV XLZ XMA XMB XMC XME XMR XMS XMT XMW XMX XNA XNE XNF XNG XNS XNT XNU XNV XO1 XO2 XO3 XO4 XO5 XO6 XO7 XO8 XO9 XOA XOB XOC XOD XOE XOF XOG XOH XOI XOJ XOK XOL XOM XON XOP XOQ XOR XOS XOT XOU XOV XOW XOX XOY XOZ XP1 XP2 XP3 XP4 XPA XPB XPC XPD XPE XPF XPG XPH XPI XPJ XPK XPL XPN XPO XPP XPR XPT XPU XPV XPX XPY XPZ XQA XQB XQC XQD XQF XQG XQH XQJ XQK XQL XQM XQN XQP XQQ XQR XQS XRD XRG XRJ XRK XRL XRO XRT XRZ XSA XSB XSC XSD XSE XSH XSI XSK XSL XSM XSO XSP XSS XST XSU XSV XSW XSX XSY XSZ XT1 XTB XTC XTD XTE XTG XTI XTK XTL XTN XTO XTR XTS XTT XTU XTV XTW XTY XTZ XUC XUN XVA XVG XVI XVK XVL XVN XVO XVP XVQ XVR XVS XVY XWA XWB XWC XWD XWF XWG XWH XWJ XWK XWL XWM XWN XWP XWQ XWR XWS XWT XWU XWV XWW XWX XWY XWZ XXA XXB XXC XXD XXF XXG XXH XXJ XXK XYA XYB XYC XYD XYF XYG XYH XYJ XYK XYL XYM XYN XYP XYQ XYR XYS XYT XYV XYW XYX XYY XYZ XZA XZB XZC XZD XZF XZG XZH XZJ XZK XZL XZM XZN XZP XZQ XZR XZS XZT XZU XZV XZW XZX XZY XZZ YDK YDQ YRD Z11 Z9 ZP ZZ"
8037
+ );
8038
+ var electronicAddressSchemes = list2(
8039
+ "0002 0007 0009 0037 0060 0088 0096 0097 0106 0130 0135 0142 0147 0151 0154 0158 0170 0177 0183 0184 0188 0190 0191 0192 0193 0194 0195 0196 0198 0199 0200 0201 0202 0203 0204 0205 0208 0209 0210 0211 0212 0213 0215 0216 0217 0218 0221 0225 0230 0235 0240 0242 0244 0245 0246 0248 9910 9913 9914 9915 9918 9919 9920 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9957 9959 AN AQ AS AU EM"
8040
+ );
8041
+ var currencyCodes = list2(
8042
+ "AED AFN ALL AMD AOA ARS AUD AWG AZN BAM BBD BDT BHD BIF BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CLF CLP CNH CNY COP COU CRC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRU MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SOS SRD SSP STN SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD USN UYI UYU UYW UZS VED VES VND VUV WST XAF XAG XAU XBA XBB XBC XBD XCD XCG XDR XOF XPD XPF XPT XSU XTS XUA XXX YER ZAR ZMW ZWG"
8043
+ );
8044
+ var paymentMeansCodes = list2(
8045
+ "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 74 75 76 77 78 91 92 93 94 95 96 97 98 ZZZ"
8046
+ );
8047
+
8048
+ // packages/engine/src/lib/einvoice/decimal.ts
8049
+ function decimalText(value) {
8050
+ if (typeof value === "string") {
8051
+ const text4 = value.trim();
8052
+ return /^-?\d+(\.\d+)?$/.test(text4) ? trimZeros(text4) : null;
8053
+ }
8054
+ if (typeof value !== "number" || !Number.isFinite(value)) return null;
8055
+ const text3 = value.toPrecision(15);
8056
+ return /^-?\d+(\.\d+)?$/.test(text3) ? trimZeros(text3) : null;
8057
+ }
8058
+ function trimZeros(text3) {
8059
+ const trimmed = text3.includes(".") ? text3.replace(/0+$/, "").replace(/\.$/, "") : text3;
8060
+ return trimmed === "-0" ? "0" : trimmed;
8061
+ }
8062
+ function decimalPlaces(text3) {
8063
+ const dot = text3.indexOf(".");
8064
+ return dot === -1 ? 0 : text3.length - dot - 1;
8065
+ }
8066
+ function toUnits(text3, scale) {
8067
+ const negative = text3.startsWith("-");
8068
+ const [whole = "0", fraction = ""] = (negative ? text3.slice(1) : text3).split(
8069
+ "."
8070
+ );
8071
+ const units = BigInt(whole + fraction.padEnd(scale, "0").slice(0, scale));
8072
+ return negative ? -units : units;
8073
+ }
8074
+ function fromUnits(units, scale, places = scale) {
8075
+ const negative = units < 0n;
8076
+ const digits = (negative ? -units : units).toString().padStart(scale + 1, "0");
8077
+ const whole = digits.slice(0, digits.length - scale);
8078
+ const fraction = digits.slice(digits.length - scale).padEnd(places, "0");
8079
+ const text3 = places > 0 ? `${whole}.${fraction.slice(0, places)}` : whole;
8080
+ return negative && /[1-9]/.test(text3) ? `-${text3}` : text3;
8081
+ }
8082
+ function withPlaces(text3, min) {
8083
+ const places = decimalPlaces(text3);
8084
+ if (places >= min) return text3;
8085
+ return places === 0 ? `${text3}.${"0".repeat(min)}` : text3 + "0".repeat(min - places);
8086
+ }
8087
+ function divideRounded(value, divisor) {
8088
+ const negative = value < 0n !== divisor < 0n;
8089
+ const a = value < 0n ? -value : value;
8090
+ const b = divisor < 0n ? -divisor : divisor;
8091
+ const quotient = (a * 2n + b) / (b * 2n);
8092
+ return negative ? -quotient : quotient;
8093
+ }
8094
+ var abs = (value) => value < 0n ? -value : value;
8095
+
8096
+ // packages/engine/src/lib/einvoice/schema.ts
8097
+ import { z } from "zod";
8098
+ var numeric = z.union([z.number(), z.string()]);
8099
+ var text2 = z.string().trim().min(1);
8100
+ var isoDate2 = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Expected a date as YYYY-MM-DD");
8101
+ var identifier2 = z.union([
8102
+ text2,
8103
+ z.object({ value: text2, scheme: text2.optional() })
8104
+ ]);
8105
+ var address = z.object({
8106
+ street: text2.optional(),
8107
+ street2: text2.optional(),
8108
+ street3: text2.optional(),
8109
+ postcode: text2.optional(),
8110
+ city: text2.optional(),
8111
+ /** ISO 3166-1 alpha-2 (BT-40, BT-55, BT-80). */
8112
+ country: text2,
8113
+ /** Region or province (BT-39, BT-54, BT-79). */
8114
+ subdivision: text2.optional()
8115
+ });
8116
+ var contact = z.object({
8117
+ name: text2.optional(),
8118
+ phone: text2.optional(),
8119
+ email: text2.optional()
8120
+ });
8121
+ var party = z.object({
8122
+ name: text2,
8123
+ /** The name the business trades under, where it differs (BT-28, BT-45). */
8124
+ trading_name: text2.optional(),
8125
+ /** An identifier of the party (BT-29, BT-46). */
8126
+ id: identifier2.optional(),
8127
+ /** The register entry (BT-30, BT-47): a SIREN, a company number. */
8128
+ legal_registration: identifier2.optional(),
8129
+ vat_id: text2.optional(),
8130
+ address,
8131
+ contact: contact.optional(),
8132
+ /** Where the party receives electronic invoices (BT-34, BT-49); a bare e-mail address is scheme EM. */
8133
+ electronic_address: identifier2.optional()
8134
+ });
8135
+ var period = z.object({ start: isoDate2.optional(), end: isoDate2.optional() });
8136
+ var VAT_CATEGORIES = ["S", "Z", "E", "AE", "K", "G", "O"];
8137
+ var vatCategory = z.enum(VAT_CATEGORIES);
8138
+ var lineTax = z.object({
8139
+ category: vatCategory,
8140
+ /** Percent, `19` for 19 %. Left out for category O only. */
8141
+ rate: numeric.optional()
8142
+ });
8143
+ var allowanceOrCharge = z.object({
8144
+ amount: numeric,
8145
+ reason: text2.optional(),
8146
+ /** UNTDID 5189 for an allowance, UNTDID 7161 for a charge. */
8147
+ reason_code: text2.optional(),
8148
+ base_amount: numeric.optional(),
8149
+ percent: numeric.optional()
8150
+ });
8151
+ var line = z.object({
8152
+ id: z.union([text2, z.number()]),
8153
+ name: text2,
8154
+ description: text2.optional(),
8155
+ quantity: numeric,
8156
+ /** UN/ECE Recommendation 20: C62 a piece, HUR an hour, DAY a day, KGM a kilogram. */
8157
+ unit_code: text2.default("C62"),
8158
+ net_price: numeric,
8159
+ /** The quantity the price is for, where it is not one unit (BT-149). */
8160
+ price_base_quantity: numeric.optional(),
8161
+ net_amount: numeric,
8162
+ tax: lineTax,
8163
+ period: period.optional(),
8164
+ allowances: z.array(allowanceOrCharge).optional(),
8165
+ charges: z.array(allowanceOrCharge).optional(),
8166
+ buyer_accounting_reference: text2.optional(),
8167
+ note: text2.optional(),
8168
+ /** The seller's and the buyer's article numbers (BT-155, BT-156), a GTIN and the like (BT-157). */
8169
+ seller_item_id: text2.optional(),
8170
+ buyer_item_id: text2.optional(),
8171
+ standard_item_id: identifier2.optional(),
8172
+ /** The line of the buyer's order this one answers (BT-132). */
8173
+ order_line_reference: text2.optional()
8174
+ });
8175
+ var breakdown = z.object({
8176
+ category: vatCategory,
8177
+ rate: numeric.optional(),
8178
+ basis: numeric,
8179
+ amount: numeric,
8180
+ exemption_reason: text2.optional(),
8181
+ /** A VATEX code (BT-121), for example VATEX-EU-AE for reverse charge. */
8182
+ exemption_reason_code: text2.optional()
8183
+ });
8184
+ var totals = z.object({
8185
+ line_net: numeric,
8186
+ allowances: numeric.optional(),
8187
+ charges: numeric.optional(),
8188
+ tax_basis: numeric,
8189
+ tax_total: numeric,
8190
+ /** The VAT total in the accounting currency (BT-111). */
8191
+ tax_total_accounting: numeric.optional(),
8192
+ grand: numeric,
8193
+ prepaid: numeric.optional(),
8194
+ rounding: numeric.optional(),
8195
+ due: numeric
8196
+ });
8197
+ var payment = z.object({
8198
+ /** UNTDID 4461: 58 SEPA credit transfer, 59 SEPA direct debit, 30 credit transfer, 48 card. */
8199
+ means_code: z.union([text2, z.number()]).optional(),
8200
+ iban: text2.optional(),
8201
+ bic: text2.optional(),
8202
+ account_name: text2.optional(),
8203
+ /** What the payer quotes with the payment (BT-83). */
8204
+ reference: text2.optional(),
8205
+ terms: text2.optional(),
8206
+ due_date: isoDate2.optional(),
8207
+ /** Direct debit: the mandate (BT-89), the creditor's identifier (BT-90), the account debited (BT-91). */
8208
+ mandate_id: text2.optional(),
8209
+ creditor_id: text2.optional(),
8210
+ debited_iban: text2.optional()
8211
+ });
8212
+ var note = z.object({
8213
+ text: text2,
8214
+ /** UNTDID 4451, which French invoices use for their statutory mentions (PMT, PMD, AAB). */
8215
+ subject_code: text2.optional()
8216
+ });
8217
+ var invoiceSchema = z.object({
8218
+ number: text2,
8219
+ issue_date: isoDate2,
8220
+ /** UNTDID 1001: 380 invoice, 381 credit note, 384 corrected invoice, 389 self-billed. */
8221
+ type_code: z.union([text2, z.number()]).default("380"),
8222
+ currency: text2,
8223
+ /** The currency the VAT is accounted in, where the invoice is in another (BT-6); goes with `totals.tax_total_accounting`. */
8224
+ accounting_currency: text2.optional(),
8225
+ /** The buyer's routing reference (BT-10); a German authority's Leitweg-ID goes here. */
8226
+ buyer_reference: text2.optional(),
8227
+ order_reference: text2.optional(),
8228
+ contract_reference: text2.optional(),
8229
+ note: text2.optional(),
8230
+ notes: z.array(note).optional(),
8231
+ period: period.optional(),
8232
+ /** The invoices a credit note or a correction refers to (BG-3). */
8233
+ preceding_invoices: z.array(z.object({ number: text2, issue_date: isoDate2.optional() })).optional(),
8234
+ /** France (spec 17 §4.4): what was sold, and the billing framework's code where the plain case does not fit. */
8235
+ operation: z.enum(["goods", "services", "mixed"]).optional(),
8236
+ operation_code: text2.optional(),
8237
+ seller: party.extend({
8238
+ tax_number: text2.optional(),
8239
+ /** Further legal information the invoice must state (BT-33): register court, capital. */
8240
+ legal_info: text2.optional(),
8241
+ /** France: VAT is owed when the invoice is issued, not when it is paid. */
8242
+ vat_on_debits: z.boolean().optional()
8243
+ }),
8244
+ buyer: party.extend({
8245
+ /** France: the buyer's SIREN, nine digits. */
8246
+ siren: text2.optional()
8247
+ }),
8248
+ delivery: z.object({
8249
+ name: text2.optional(),
8250
+ date: isoDate2.optional(),
8251
+ address: address.optional()
8252
+ }).optional(),
8253
+ lines: z.array(line).min(1),
8254
+ /** Allowances and charges on the whole document (BG-20, BG-21), each with the VAT it falls under. */
8255
+ allowances: z.array(allowanceOrCharge.extend({ tax: lineTax })).optional(),
8256
+ charges: z.array(allowanceOrCharge.extend({ tax: lineTax })).optional(),
8257
+ tax: z.object({ breakdown: z.array(breakdown).min(1) }),
8258
+ totals,
8259
+ payment: payment.optional()
8260
+ });
8261
+ var EINVOICE_PROFILES = ["basic", "en16931"];
8262
+ var EINVOICE_FLAVOURS = ["factur-x", "zugferd"];
8263
+ var einvoiceOptionsSchema = z.object({
8264
+ profile: z.string().optional(),
8265
+ flavour: z.string().optional(),
8266
+ xml: z.enum(["embedded", "both"]).optional(),
8267
+ display_check: z.enum(["warn", "strict"]).optional()
8268
+ }).strict();
8269
+ var defaultEinvoiceOptions = {
8270
+ profile: "en16931",
8271
+ flavour: "factur-x",
8272
+ xml: "embedded",
8273
+ display_check: "warn"
8274
+ };
8275
+ var knownUnsupported = {
8276
+ minimum: "MINIMUM carries no invoice lines and is not an invoice on its own; use basic or en16931",
8277
+ "basic-wl": "BASIC WL carries no invoice lines and is not an invoice on its own; use basic or en16931",
8278
+ basicwl: "BASIC WL carries no invoice lines and is not an invoice on its own; use basic or en16931",
8279
+ extended: "EXTENDED is not offered; use en16931, which carries the full European standard",
8280
+ xrechnung: "XRechnung is not offered yet; use en16931"
8281
+ };
8282
+ function resolveEinvoiceOptions(...layers) {
8283
+ let merged = null;
8284
+ for (const layer of layers) {
8285
+ if (layer === false) merged = null;
8286
+ else if (layer) merged = { ...merged ?? {}, ...definedOnly(layer) };
8287
+ }
8288
+ if (!merged) return { ok: true, options: null };
8289
+ const profile = (merged.profile ?? defaultEinvoiceOptions.profile).trim().toLowerCase();
8290
+ const flavour = (merged.flavour ?? defaultEinvoiceOptions.flavour).trim().toLowerCase();
8291
+ if (!EINVOICE_PROFILES.includes(profile))
8292
+ return {
8293
+ ok: false,
8294
+ field: "profile",
8295
+ value: profile,
8296
+ reason: knownUnsupported[profile] ?? `Unknown profile; use ${EINVOICE_PROFILES.join(" or ")}`
8297
+ };
8298
+ if (!EINVOICE_FLAVOURS.includes(flavour))
8299
+ return {
8300
+ ok: false,
8301
+ field: "flavour",
8302
+ value: flavour,
8303
+ reason: `Unknown flavour; use ${EINVOICE_FLAVOURS.join(" or ")}`
8304
+ };
8305
+ return {
8306
+ ok: true,
8307
+ options: {
8308
+ profile,
8309
+ flavour,
8310
+ xml: merged.xml ?? defaultEinvoiceOptions.xml,
8311
+ display_check: merged.display_check ?? defaultEinvoiceOptions.display_check
8312
+ }
8313
+ };
8314
+ }
8315
+ function definedOnly(layer) {
8316
+ return Object.fromEntries(
8317
+ Object.entries(layer).filter(([, value]) => value !== void 0)
8318
+ );
8319
+ }
8320
+
8321
+ // packages/engine/src/lib/einvoice/check.ts
8322
+ var REQUIRED = {
8323
+ number: ["BR-02", "BT-1"],
8324
+ issue_date: ["BR-03", "BT-2"],
8325
+ currency: ["BR-05", "BT-5"],
8326
+ seller: ["BR-06", "BG-4"],
8327
+ "seller.name": ["BR-06", "BT-27"],
8328
+ "seller.address": ["BR-08", "BG-5"],
8329
+ "seller.address.country": ["BR-09", "BT-40"],
8330
+ buyer: ["BR-07", "BG-7"],
8331
+ "buyer.name": ["BR-07", "BT-44"],
8332
+ "buyer.address": ["BR-10", "BG-8"],
8333
+ "buyer.address.country": ["BR-11", "BT-55"],
8334
+ lines: ["BR-16", "BG-25"],
8335
+ "lines[].id": ["BR-21", "BT-126"],
8336
+ "lines[].quantity": ["BR-22", "BT-129"],
8337
+ "lines[].net_amount": ["BR-24", "BT-131"],
8338
+ "lines[].name": ["BR-25", "BT-153"],
8339
+ "lines[].net_price": ["BR-26", "BT-146"],
8340
+ "lines[].tax": ["BR-CO-04", "BT-151"],
8341
+ "lines[].tax.category": ["BR-CO-04", "BT-151"],
8342
+ tax: ["BR-CO-18", "BG-23"],
8343
+ "tax.breakdown": ["BR-CO-18", "BG-23"],
8344
+ "tax.breakdown[].basis": ["BR-45", "BT-116"],
8345
+ "tax.breakdown[].amount": ["BR-46", "BT-117"],
8346
+ "tax.breakdown[].category": ["BR-47", "BT-118"],
8347
+ totals: ["BR-12", "BG-22"],
8348
+ "totals.line_net": ["BR-12", "BT-106"],
8349
+ "totals.tax_basis": ["BR-13", "BT-109"],
8350
+ "totals.tax_total": ["BR-CO-14", "BT-110"],
8351
+ "totals.grand": ["BR-14", "BT-112"],
8352
+ "totals.due": ["BR-15", "BT-115"],
8353
+ "allowances[].amount": ["BR-31", "BT-92"],
8354
+ "allowances[].tax": ["BR-32", "BT-95"],
8355
+ "allowances[].tax.category": ["BR-32", "BT-95"],
8356
+ "charges[].amount": ["BR-36", "BT-99"],
8357
+ "charges[].tax": ["BR-37", "BT-102"],
8358
+ "charges[].tax.category": ["BR-37", "BT-102"],
8359
+ "lines[].allowances[].amount": ["BR-41", "BT-136"],
8360
+ "lines[].charges[].amount": ["BR-43", "BT-141"],
8361
+ "delivery.address.country": ["BR-57", "BT-80"],
8362
+ "preceding_invoices[].number": ["BR-55", "BT-25"]
8363
+ };
8364
+ var RULE_PREFIX = {
8365
+ S: "BR-S",
8366
+ Z: "BR-Z",
8367
+ E: "BR-E",
8368
+ AE: "BR-AE",
8369
+ K: "BR-IC",
8370
+ G: "BR-G",
8371
+ O: "BR-O"
8372
+ };
8373
+ var UNIT_SUGGESTIONS = {
8374
+ piece: "C62",
8375
+ pieces: "C62",
8376
+ pcs: "C62",
8377
+ pc: "C62",
8378
+ stk: "C62",
8379
+ st\u00FCck: "C62",
8380
+ unit: "C62",
8381
+ units: "C62",
8382
+ each: "C62",
8383
+ hour: "HUR",
8384
+ hours: "HUR",
8385
+ h: "HUR",
8386
+ std: "HUR",
8387
+ stunde: "HUR",
8388
+ stunden: "HUR",
8389
+ day: "DAY",
8390
+ days: "DAY",
8391
+ tag: "DAY",
8392
+ tage: "DAY",
8393
+ month: "MON",
8394
+ months: "MON",
8395
+ monat: "MON",
8396
+ year: "ANN",
8397
+ min: "MIN",
8398
+ minute: "MIN",
8399
+ minutes: "MIN",
8400
+ kg: "KGM",
8401
+ g: "GRM",
8402
+ t: "TNE",
8403
+ l: "LTR",
8404
+ litre: "LTR",
8405
+ liter: "LTR",
8406
+ m: "MTR",
8407
+ km: "KMT",
8408
+ m2: "MTK",
8409
+ qm: "MTK",
8410
+ m3: "MTQ",
8411
+ kwh: "KWH",
8412
+ flat: "LS",
8413
+ pauschal: "LS"
8414
+ };
8415
+ var FRENCH_FRAMEWORKS = /* @__PURE__ */ new Set([
8416
+ "B1",
8417
+ "S1",
8418
+ "M1",
8419
+ "B2",
8420
+ "S2",
8421
+ "M2",
8422
+ "B4",
8423
+ "S4",
8424
+ "M4",
8425
+ "S5",
8426
+ "S6",
8427
+ "B7",
8428
+ "S7"
8429
+ ]);
8430
+ var FRENCH_OPERATION = { goods: "B1", services: "S1", mixed: "M1" };
8431
+ var CREDIT_TRANSFER = /* @__PURE__ */ new Set(["30", "58"]);
8432
+ function checkInvoice(data, options = {}) {
8433
+ const problems = [];
8434
+ const add2 = (code, path, message, extra = {}) => {
8435
+ problems.push({
8436
+ code,
8437
+ path,
8438
+ ...extra.rule ? { rule: extra.rule } : {},
8439
+ message: extra.rule ? `${message} (${extra.rule})` : message,
8440
+ args: {
8441
+ path,
8442
+ ...extra.rule ? { rule: extra.rule } : {},
8443
+ ...extra.args
8444
+ }
8445
+ });
8446
+ };
8447
+ const parsed = invoiceSchema.safeParse(data);
8448
+ if (!parsed.success) {
8449
+ for (const issue of parsed.error.issues) {
8450
+ const path = pathText(issue.path);
8451
+ const required = REQUIRED[path.replace(/\[\d+\]/g, "[]")];
8452
+ const absent = valueAt(data, issue.path) === void 0;
8453
+ if (absent && required)
8454
+ add2("missing", path, `_invoice.${path} is missing (${required[1]})`, {
8455
+ rule: required[0],
8456
+ args: { term: required[1] }
8457
+ });
8458
+ else if (absent) add2("missing", path, `_invoice.${path} is missing`);
8459
+ else if (issue.code === "too_small" && path === "lines")
8460
+ add2(
8461
+ "missing",
8462
+ path,
8463
+ "_invoice.lines is empty: an invoice has at least one line (BG-25)",
8464
+ {
8465
+ rule: "BR-16",
8466
+ args: { term: "BG-25" }
8467
+ }
8468
+ );
8469
+ else if (issue.code === "too_small" && path === "tax.breakdown")
8470
+ add2(
8471
+ "missing",
8472
+ path,
8473
+ "_invoice.tax.breakdown is empty: an invoice has at least one VAT breakdown (BG-23)",
8474
+ {
8475
+ rule: "BR-CO-18",
8476
+ args: { term: "BG-23" }
8477
+ }
8478
+ );
8479
+ else
8480
+ add2("invalid", path, `_invoice.${path}: ${issue.message}`, {
8481
+ args: { detail: issue.message }
8482
+ });
8483
+ }
8484
+ return { ok: false, invoice: null, problems };
8485
+ }
8486
+ const invoice = normalise(parsed.data, add2, options);
8487
+ if (problems.length > 0) return { ok: false, invoice: null, problems };
8488
+ rules(invoice, add2);
8489
+ return problems.length > 0 ? { ok: false, invoice: null, problems } : { ok: true, invoice, problems: [] };
8490
+ }
8491
+ function pathText(path) {
8492
+ let out = "";
8493
+ for (const key of path)
8494
+ out += typeof key === "number" ? `[${key}]` : out ? `.${String(key)}` : String(key);
8495
+ return out;
8496
+ }
8497
+ function valueAt(data, path) {
8498
+ let value = data;
8499
+ for (const key of path) {
8500
+ if (value === null || typeof value !== "object") return void 0;
8501
+ value = value[key];
8502
+ }
8503
+ return value === null ? void 0 : value;
8504
+ }
8505
+ function normalise(input, add2, options) {
8506
+ const amount2 = (value, path) => {
8507
+ const text3 = decimalText(value);
8508
+ if (text3 === null) {
8509
+ add2("not_a_number", path, `_invoice.${path} is not a number`);
8510
+ return "0";
8511
+ }
8512
+ if (decimalPlaces(text3) > 2) {
8513
+ add2(
8514
+ "decimals",
8515
+ path,
8516
+ `_invoice.${path} has more than 2 decimals; an amount of the invoice is exact to the cent`,
8517
+ {
8518
+ args: { max: 2, value: text3 }
8519
+ }
8520
+ );
8521
+ return "0";
8522
+ }
8523
+ return text3;
8524
+ };
8525
+ const number = (value, path, max2) => {
8526
+ const text3 = decimalText(value);
8527
+ if (text3 === null) {
8528
+ add2("not_a_number", path, `_invoice.${path} is not a number`);
8529
+ return "0";
8530
+ }
8531
+ if (decimalPlaces(text3) > max2) {
8532
+ add2("decimals", path, `_invoice.${path} has more than ${max2} decimals`, {
8533
+ args: { max: max2, value: text3 }
8534
+ });
8535
+ return "0";
8536
+ }
8537
+ return text3;
8538
+ };
8539
+ const optionalAmount = (value, path) => value === void 0 ? void 0 : amount2(value, path);
8540
+ const date2 = (value, path) => {
8541
+ if (value === void 0) return void 0;
8542
+ const [year = 0, month = 0, day = 0] = value.split("-").map(Number);
8543
+ const real = new Date(Date.UTC(year, month - 1, day));
8544
+ if (real.getUTCFullYear() !== year || real.getUTCMonth() !== month - 1 || real.getUTCDate() !== day) {
8545
+ add2("date", path, `_invoice.${path} is not a date of the calendar`, {
8546
+ args: { value }
8547
+ });
8548
+ }
8549
+ return value;
8550
+ };
8551
+ const code = (value, path, list3, name, rule2) => {
8552
+ const upper = value.trim().toUpperCase();
8553
+ if (!list3.has(upper))
8554
+ add2(
8555
+ "code_list",
8556
+ path,
8557
+ `_invoice.${path}: "${value}" is not a code of ${name}`,
8558
+ {
8559
+ rule: rule2,
8560
+ args: { value, list: name }
8561
+ }
8562
+ );
8563
+ return upper;
8564
+ };
8565
+ const period3 = (value, path, rule2) => {
8566
+ if (!value || value.start === void 0 && value.end === void 0)
8567
+ return void 0;
8568
+ const start = date2(value.start, `${path}.start`);
8569
+ const end = date2(value.end, `${path}.end`);
8570
+ if (start && end && end < start)
8571
+ add2("date_order", path, `_invoice.${path} ends before it starts`, {
8572
+ rule: rule2
8573
+ });
8574
+ return { ...start ? { start } : {}, ...end ? { end } : {} };
8575
+ };
8576
+ const identifier4 = (value) => {
8577
+ if (value === void 0) return void 0;
8578
+ if (typeof value === "string") return { value };
8579
+ return {
8580
+ value: value.value,
8581
+ ...value.scheme ? { scheme: value.scheme } : {}
8582
+ };
8583
+ };
8584
+ const address3 = (value, path) => ({
8585
+ ...defined({
8586
+ street: value.street,
8587
+ street2: value.street2,
8588
+ street3: value.street3,
8589
+ postcode: value.postcode,
8590
+ city: value.city,
8591
+ subdivision: value.subdivision
8592
+ }),
8593
+ country: code(
8594
+ value.country,
8595
+ `${path}.country`,
8596
+ countryCodes,
8597
+ "ISO 3166-1 (two letters, as in DE)",
8598
+ "BR-CL-14"
8599
+ )
8600
+ });
8601
+ const vatId = (value, path) => {
8602
+ if (value === void 0) return void 0;
8603
+ const id = value.replace(/\s/g, "").toUpperCase();
8604
+ const prefix = id.slice(0, 2);
8605
+ if (!(countryCodes.has(prefix) || prefix === "EL") || !/^[A-Z]{2}/.test(id))
8606
+ add2(
8607
+ "vat_id_prefix",
8608
+ path,
8609
+ `_invoice.${path} must start with the country code of the VAT ID, as in DE123456789`,
8610
+ {
8611
+ rule: "BR-CO-09",
8612
+ args: { value }
8613
+ }
8614
+ );
8615
+ return id;
8616
+ };
8617
+ const electronicAddress = (value, path, rule2) => {
8618
+ const id = identifier4(value);
8619
+ if (!id) return void 0;
8620
+ const scheme = id.scheme?.trim().toUpperCase() ?? (/^[^@\s]+@[^@\s]+$/.test(id.value) ? "EM" : void 0);
8621
+ if (!scheme) {
8622
+ add2(
8623
+ "scheme_required",
8624
+ path,
8625
+ `_invoice.${path} needs its scheme: write { "value": \u2026, "scheme": \u2026 } with a code of the EAS list, or an e-mail address`,
8626
+ { rule: rule2 }
8627
+ );
8628
+ return void 0;
8629
+ }
8630
+ if (!electronicAddressSchemes.has(scheme))
8631
+ add2(
8632
+ "code_list",
8633
+ `${path}.scheme`,
8634
+ `_invoice.${path}.scheme: "${scheme}" is not a code of the EAS list (EM is an e-mail address)`,
8635
+ {
8636
+ rule: "BR-CL-25",
8637
+ args: { value: scheme, list: "the EAS list" }
8638
+ }
8639
+ );
8640
+ return { value: id.value, scheme };
8641
+ };
8642
+ const party3 = (value, path, addressRule) => {
8643
+ const id = identifier4(value.id);
8644
+ const registration = identifier4(value.legal_registration);
8645
+ const electronic = electronicAddress(
8646
+ value.electronic_address,
8647
+ `${path}.electronic_address`,
8648
+ addressRule
8649
+ );
8650
+ const vat = vatId(value.vat_id, `${path}.vat_id`);
8651
+ return {
8652
+ name: value.name,
8653
+ ...defined({ trading_name: value.trading_name, vat_id: vat }),
8654
+ ...id ? { id } : {},
8655
+ ...registration ? { legal_registration: registration } : {},
8656
+ address: address3(value.address, `${path}.address`),
8657
+ ...value.contact && Object.values(value.contact).some((v) => v !== void 0) ? { contact: defined(value.contact) } : {},
8658
+ ...electronic ? { electronic_address: electronic } : {}
8659
+ };
8660
+ };
8661
+ const tax = (value, path) => ({
8662
+ category: value.category,
8663
+ ...value.rate === void 0 || value.rate === null ? {} : { rate: number(value.rate, `${path}.rate`, 4) }
8664
+ });
8665
+ const allowance = (value, path) => ({
8666
+ amount: amount2(value.amount, `${path}.amount`),
8667
+ ...defined({
8668
+ reason: value.reason,
8669
+ reason_code: value.reason_code?.trim().toUpperCase(),
8670
+ base_amount: optionalAmount(value.base_amount, `${path}.base_amount`),
8671
+ percent: value.percent === void 0 ? void 0 : number(value.percent, `${path}.percent`, 4)
8672
+ })
8673
+ });
8674
+ const seller = party3(input.seller, "seller", "BR-62");
8675
+ const buyer = party3(input.buyer, "buyer", "BR-63");
8676
+ if (input.buyer.siren !== void 0) {
8677
+ const siren = input.buyer.siren.replace(/\s/g, "");
8678
+ if (buyer.legal_registration && buyer.legal_registration.value.replace(/\s/g, "") !== siren)
8679
+ add2(
8680
+ "siren_mismatch",
8681
+ "buyer.siren",
8682
+ "_invoice.buyer.siren and _invoice.buyer.legal_registration name different registrations; state one of them"
8683
+ );
8684
+ else
8685
+ buyer.legal_registration = {
8686
+ value: siren,
8687
+ scheme: buyer.legal_registration?.scheme ?? "0002"
8688
+ };
8689
+ }
8690
+ const notes = [
8691
+ ...input.note ? [{ text: input.note }] : [],
8692
+ ...(input.notes ?? []).map((note2) => ({
8693
+ text: note2.text,
8694
+ ...note2.subject_code ? { subject_code: note2.subject_code.trim().toUpperCase() } : {}
8695
+ }))
8696
+ ];
8697
+ const delivery = input.delivery ? defined({
8698
+ name: input.delivery.name,
8699
+ date: date2(input.delivery.date, "delivery.date"),
8700
+ address: input.delivery.address ? address3(input.delivery.address, "delivery.address") : void 0
8701
+ }) : void 0;
8702
+ let businessProcess;
8703
+ if (input.operation_code !== void 0)
8704
+ businessProcess = input.operation_code.trim().toUpperCase();
8705
+ else if (input.operation !== void 0)
8706
+ businessProcess = FRENCH_OPERATION[input.operation];
8707
+ const payment2 = input.payment ? defined({
8708
+ means_code: input.payment.means_code === void 0 ? void 0 : code(
8709
+ String(input.payment.means_code),
8710
+ "payment.means_code",
8711
+ paymentMeansCodes,
8712
+ "UNTDID 4461 (58 is a SEPA credit transfer)",
8713
+ "BR-CL-16"
8714
+ ),
8715
+ iban: iban(input.payment.iban, "payment.iban", add2),
8716
+ bic: input.payment.bic?.replace(/\s/g, "").toUpperCase(),
8717
+ account_name: input.payment.account_name,
8718
+ reference: input.payment.reference,
8719
+ terms: input.payment.terms,
8720
+ due_date: date2(input.payment.due_date, "payment.due_date"),
8721
+ mandate_id: input.payment.mandate_id,
8722
+ creditor_id: input.payment.creditor_id,
8723
+ debited_iban: iban(
8724
+ input.payment.debited_iban,
8725
+ "payment.debited_iban",
8726
+ add2
8727
+ )
8728
+ }) : void 0;
8729
+ const rounding = optionalAmount(input.totals.rounding, "totals.rounding");
8730
+ if (options.profile === "basic" && rounding !== void 0 && toUnits(rounding, 2) !== 0n)
8731
+ add2(
8732
+ "profile",
8733
+ "totals.rounding",
8734
+ "_invoice.totals.rounding cannot be carried by the profile basic, which has no rounding amount (BT-114); use en16931",
8735
+ {
8736
+ args: { profile: "basic", term: "BT-114" }
8737
+ }
8738
+ );
8739
+ return {
8740
+ number: input.number,
8741
+ issue_date: date2(input.issue_date, "issue_date") ?? input.issue_date,
8742
+ type_code: code(
8743
+ String(input.type_code),
8744
+ "type_code",
8745
+ documentTypeCodes,
8746
+ "UNTDID 1001 (380 is an invoice, 381 a credit note)",
8747
+ "BR-CL-01"
8748
+ ),
8749
+ currency: code(
8750
+ input.currency,
8751
+ "currency",
8752
+ currencyCodes,
8753
+ "ISO 4217 (three letters, as in EUR)",
8754
+ "BR-CL-04"
8755
+ ),
8756
+ ...defined({
8757
+ accounting_currency: input.accounting_currency === void 0 ? void 0 : code(
8758
+ input.accounting_currency,
8759
+ "accounting_currency",
8760
+ currencyCodes,
8761
+ "ISO 4217 (three letters, as in EUR)",
8762
+ "BR-CL-05"
8763
+ ),
8764
+ buyer_reference: input.buyer_reference,
8765
+ order_reference: input.order_reference,
8766
+ contract_reference: input.contract_reference,
8767
+ period: period3(input.period, "period", "BR-29"),
8768
+ business_process: businessProcess
8769
+ }),
8770
+ notes,
8771
+ preceding_invoices: (input.preceding_invoices ?? []).map(
8772
+ (reference, i) => ({
8773
+ number: reference.number,
8774
+ ...defined({
8775
+ issue_date: date2(
8776
+ reference.issue_date,
8777
+ `preceding_invoices[${i}].issue_date`
8778
+ )
8779
+ })
8780
+ })
8781
+ ),
8782
+ seller: {
8783
+ ...seller,
8784
+ ...defined({
8785
+ tax_number: input.seller.tax_number,
8786
+ legal_info: input.seller.legal_info,
8787
+ vat_on_debits: input.seller.vat_on_debits
8788
+ })
8789
+ },
8790
+ buyer,
8791
+ ...delivery && Object.keys(delivery).length > 0 ? { delivery } : {},
8792
+ lines: input.lines.map((line2, i) => {
8793
+ const path = `lines[${i}]`;
8794
+ const unit = line2.unit_code.trim();
8795
+ const known = unitCodes.has(unit.toUpperCase()) || unitCodes.has(unit);
8796
+ if (!known) {
8797
+ const suggestion = UNIT_SUGGESTIONS[unit.toLowerCase()];
8798
+ add2(
8799
+ "code_list",
8800
+ `${path}.unit_code`,
8801
+ `_invoice.${path}.unit_code: "${unit}" is not a code of UN/ECE Recommendation 20${suggestion ? `; ${suggestion} is the code for it` : " (C62 is a piece, HUR an hour, DAY a day)"}`,
8802
+ {
8803
+ rule: "BR-CL-23",
8804
+ args: {
8805
+ value: unit,
8806
+ list: "UN/ECE Recommendation 20",
8807
+ ...suggestion ? { suggestion } : {}
8808
+ }
8809
+ }
8810
+ );
8811
+ }
8812
+ const price = number(line2.net_price, `${path}.net_price`, 6);
8813
+ if (price.startsWith("-"))
8814
+ add2(
8815
+ "negative",
8816
+ `${path}.net_price`,
8817
+ `_invoice.${path}.net_price must not be negative; a credit is a negative quantity`,
8818
+ { rule: "BR-27" }
8819
+ );
8820
+ const standard = identifier4(line2.standard_item_id);
8821
+ if (standard && !standard.scheme)
8822
+ add2(
8823
+ "scheme_required",
8824
+ `${path}.standard_item_id`,
8825
+ `_invoice.${path}.standard_item_id needs its scheme: write { "value": \u2026, "scheme": \u2026 }, 0160 for a GTIN`,
8826
+ { rule: "BR-64" }
8827
+ );
8828
+ return {
8829
+ id: String(line2.id),
8830
+ name: line2.name,
8831
+ quantity: number(line2.quantity, `${path}.quantity`, 6),
8832
+ unit_code: unitCodes.has(unit) ? unit : unit.toUpperCase(),
8833
+ net_price: price,
8834
+ net_amount: amount2(line2.net_amount, `${path}.net_amount`),
8835
+ tax: tax(line2.tax, `${path}.tax`),
8836
+ allowances: (line2.allowances ?? []).map(
8837
+ (a, j) => allowance(a, `${path}.allowances[${j}]`)
8838
+ ),
8839
+ charges: (line2.charges ?? []).map(
8840
+ (c, j) => allowance(c, `${path}.charges[${j}]`)
8841
+ ),
8842
+ ...defined({
8843
+ description: line2.description,
8844
+ price_base_quantity: line2.price_base_quantity === void 0 ? void 0 : number(
8845
+ line2.price_base_quantity,
8846
+ `${path}.price_base_quantity`,
8847
+ 6
8848
+ ),
8849
+ period: period3(line2.period, `${path}.period`, "BR-30"),
8850
+ buyer_accounting_reference: line2.buyer_accounting_reference,
8851
+ note: line2.note,
8852
+ seller_item_id: line2.seller_item_id,
8853
+ buyer_item_id: line2.buyer_item_id,
8854
+ standard_item_id: standard,
8855
+ order_line_reference: line2.order_line_reference
8856
+ })
8857
+ };
8858
+ }),
8859
+ allowances: (input.allowances ?? []).map((a, i) => ({
8860
+ ...allowance(a, `allowances[${i}]`),
8861
+ tax: tax(a.tax, `allowances[${i}].tax`)
8862
+ })),
8863
+ charges: (input.charges ?? []).map((c, i) => ({
8864
+ ...allowance(c, `charges[${i}]`),
8865
+ tax: tax(c.tax, `charges[${i}].tax`)
8866
+ })),
8867
+ breakdown: input.tax.breakdown.map((row2, i) => ({
8868
+ ...tax(row2, `tax.breakdown[${i}]`),
8869
+ basis: amount2(row2.basis, `tax.breakdown[${i}].basis`),
8870
+ amount: amount2(row2.amount, `tax.breakdown[${i}].amount`),
8871
+ ...defined({
8872
+ exemption_reason: row2.exemption_reason,
8873
+ exemption_reason_code: row2.exemption_reason_code?.trim()
8874
+ })
8875
+ })),
8876
+ totals: {
8877
+ line_net: amount2(input.totals.line_net, "totals.line_net"),
8878
+ tax_basis: amount2(input.totals.tax_basis, "totals.tax_basis"),
8879
+ tax_total: amount2(input.totals.tax_total, "totals.tax_total"),
8880
+ grand: amount2(input.totals.grand, "totals.grand"),
8881
+ due: amount2(input.totals.due, "totals.due"),
8882
+ ...defined({
8883
+ allowances: optionalAmount(
8884
+ input.totals.allowances,
8885
+ "totals.allowances"
8886
+ ),
8887
+ charges: optionalAmount(input.totals.charges, "totals.charges"),
8888
+ prepaid: optionalAmount(input.totals.prepaid, "totals.prepaid"),
8889
+ tax_total_accounting: optionalAmount(
8890
+ input.totals.tax_total_accounting,
8891
+ "totals.tax_total_accounting"
8892
+ ),
8893
+ rounding
8894
+ })
8895
+ },
8896
+ ...payment2 && Object.keys(payment2).length > 0 ? { payment: payment2 } : {}
8897
+ };
8898
+ }
8899
+ function iban(value, path, add2) {
8900
+ if (value === void 0) return void 0;
8901
+ const normalised = normaliseIban(value);
8902
+ if (!/^[A-Z]{2}[0-9]{2}[A-Z0-9]{11,30}$/.test(normalised) || !ibanChecksum(normalised))
8903
+ add2(
8904
+ "iban",
8905
+ path,
8906
+ `_invoice.${path} is not a valid IBAN: its check digits do not match`
8907
+ );
8908
+ return normalised;
8909
+ }
8910
+ function defined(value) {
8911
+ return Object.fromEntries(
8912
+ Object.entries(value).filter(([, v]) => v !== void 0)
8913
+ );
8914
+ }
8915
+ var cents = (text3) => text3 === void 0 ? 0n : toUnits(text3, 2);
8916
+ var money = (value) => fromUnits(value, 2);
8917
+ var rateKey = (tax) => `${tax.category}|${tax.rate ?? ""}`;
8918
+ function rules(invoice, add2) {
8919
+ const { totals: totals2 } = invoice;
8920
+ const sum = (path, stated, expected, rule2, formula) => {
8921
+ if (stated !== expected)
8922
+ add2(
8923
+ "sum",
8924
+ path,
8925
+ `_invoice.${path} is ${money(stated)}, but ${formula} ${money(expected)}`,
8926
+ {
8927
+ rule: rule2,
8928
+ args: { value: money(stated), expected: money(expected) }
8929
+ }
8930
+ );
8931
+ };
8932
+ const lineNet = invoice.lines.reduce(
8933
+ (total, line2) => total + cents(line2.net_amount),
8934
+ 0n
8935
+ );
8936
+ const allowanceSum = invoice.allowances.reduce(
8937
+ (total, a) => total + cents(a.amount),
8938
+ 0n
8939
+ );
8940
+ const chargeSum = invoice.charges.reduce(
8941
+ (total, c) => total + cents(c.amount),
8942
+ 0n
8943
+ );
8944
+ const taxSum = invoice.breakdown.reduce(
8945
+ (total, row2) => total + cents(row2.amount),
8946
+ 0n
8947
+ );
8948
+ sum(
8949
+ "totals.line_net",
8950
+ cents(totals2.line_net),
8951
+ lineNet,
8952
+ "BR-CO-10",
8953
+ "the net amounts of the lines add up to"
8954
+ );
8955
+ sum(
8956
+ "totals.allowances",
8957
+ cents(totals2.allowances),
8958
+ allowanceSum,
8959
+ "BR-CO-11",
8960
+ "the allowances of the document add up to"
8961
+ );
8962
+ sum(
8963
+ "totals.charges",
8964
+ cents(totals2.charges),
8965
+ chargeSum,
8966
+ "BR-CO-12",
8967
+ "the charges of the document add up to"
8968
+ );
8969
+ sum(
8970
+ "totals.tax_basis",
8971
+ cents(totals2.tax_basis),
8972
+ cents(totals2.line_net) - cents(totals2.allowances) + cents(totals2.charges),
8973
+ "BR-CO-13",
8974
+ "line_net less allowances plus charges is"
8975
+ );
8976
+ sum(
8977
+ "totals.tax_total",
8978
+ cents(totals2.tax_total),
8979
+ taxSum,
8980
+ "BR-CO-14",
8981
+ "the VAT amounts of the breakdown add up to"
8982
+ );
8983
+ sum(
8984
+ "totals.grand",
8985
+ cents(totals2.grand),
8986
+ cents(totals2.tax_basis) + cents(totals2.tax_total),
8987
+ "BR-CO-15",
8988
+ "tax_basis plus tax_total is"
8989
+ );
8990
+ sum(
8991
+ "totals.due",
8992
+ cents(totals2.due),
8993
+ cents(totals2.grand) - cents(totals2.prepaid) + cents(totals2.rounding),
8994
+ "BR-CO-16",
8995
+ "grand less prepaid plus rounding is"
8996
+ );
8997
+ if (invoice.accounting_currency !== void 0 && totals2.tax_total_accounting === void 0)
8998
+ add2(
8999
+ "missing",
9000
+ "totals.tax_total_accounting",
9001
+ `_invoice.totals.tax_total_accounting is missing: with accounting_currency ${invoice.accounting_currency} the invoice states its VAT total in that currency (BT-111)`,
9002
+ {
9003
+ rule: "BR-53",
9004
+ args: { term: "BT-111" }
9005
+ }
9006
+ );
9007
+ if (invoice.accounting_currency === void 0 && totals2.tax_total_accounting !== void 0)
9008
+ add2(
9009
+ "missing",
9010
+ "accounting_currency",
9011
+ "_invoice.accounting_currency is missing: totals.tax_total_accounting needs the currency it is stated in (BT-6)",
9012
+ {
9013
+ rule: "BR-53",
9014
+ args: { term: "BT-6" }
9015
+ }
9016
+ );
9017
+ const used = /* @__PURE__ */ new Map();
9018
+ const use = (tax, value, path) => {
9019
+ const entry = used.get(rateKey(tax)) ?? {
9020
+ tax,
9021
+ basis: 0n,
9022
+ items: 0,
9023
+ first: path
9024
+ };
9025
+ entry.basis += value;
9026
+ entry.items += 1;
9027
+ used.set(rateKey(tax), entry);
9028
+ };
9029
+ invoice.lines.forEach(
9030
+ (line2, i) => use(line2.tax, cents(line2.net_amount), `lines[${i}]`)
9031
+ );
9032
+ invoice.allowances.forEach(
9033
+ (a, i) => use(a.tax, -cents(a.amount), `allowances[${i}]`)
9034
+ );
9035
+ invoice.charges.forEach(
9036
+ (c, i) => use(c.tax, cents(c.amount), `charges[${i}]`)
9037
+ );
9038
+ const seen = /* @__PURE__ */ new Set();
9039
+ invoice.breakdown.forEach((row2, i) => {
9040
+ const path = `tax.breakdown[${i}]`;
9041
+ const prefix = RULE_PREFIX[row2.category];
9042
+ const shown = row2.rate === void 0 ? row2.category : `${row2.category} at ${row2.rate} %`;
9043
+ if (seen.has(rateKey(row2)))
9044
+ add2(
9045
+ "breakdown_duplicate",
9046
+ path,
9047
+ `_invoice.tax.breakdown lists category ${shown} twice; one entry per category and rate`,
9048
+ {
9049
+ args: { category: row2.category, rate: row2.rate ?? "" }
9050
+ }
9051
+ );
9052
+ seen.add(rateKey(row2));
9053
+ const entry = used.get(rateKey(row2));
9054
+ const expected = entry?.basis ?? 0n;
9055
+ if (cents(row2.basis) !== expected)
9056
+ add2(
9057
+ "sum",
9058
+ `${path}.basis`,
9059
+ `_invoice.${path}.basis is ${money(cents(row2.basis))}, but the lines, charges and allowances of category ${shown} come to ${money(expected)}`,
9060
+ {
9061
+ rule: `${prefix}-08`,
9062
+ args: {
9063
+ value: money(cents(row2.basis)),
9064
+ expected: money(expected),
9065
+ category: row2.category,
9066
+ rate: row2.rate ?? ""
9067
+ }
9068
+ }
9069
+ );
9070
+ if (row2.rate !== void 0) {
9071
+ const computed = divideRounded(
9072
+ cents(row2.basis) * toUnits(row2.rate, 4),
9073
+ 1000000n
9074
+ );
9075
+ const items = BigInt(Math.max(1, entry?.items ?? 1));
9076
+ const tolerance = (items + 1n) / 2n > 100n ? 100n : (items + 1n) / 2n;
9077
+ if (abs(cents(row2.amount) - computed) > tolerance)
9078
+ add2(
9079
+ "sum",
9080
+ `${path}.amount`,
9081
+ `_invoice.${path}.amount is ${money(cents(row2.amount))}, but ${row2.rate} % of ${money(cents(row2.basis))} is ${money(computed)}`,
9082
+ {
9083
+ rule: "BR-CO-17",
9084
+ args: {
9085
+ value: money(cents(row2.amount)),
9086
+ expected: money(computed),
9087
+ rate: row2.rate,
9088
+ basis: money(cents(row2.basis))
9089
+ }
9090
+ }
9091
+ );
9092
+ }
9093
+ });
9094
+ for (const [key, entry] of used) {
9095
+ if (seen.has(key)) continue;
9096
+ const shown = entry.tax.rate === void 0 ? entry.tax.category : `${entry.tax.category} at ${entry.tax.rate} %`;
9097
+ add2(
9098
+ "breakdown_missing",
9099
+ "tax.breakdown",
9100
+ `_invoice.tax.breakdown has no entry for category ${shown}, which _invoice.${entry.first} falls under`,
9101
+ {
9102
+ rule: `${RULE_PREFIX[entry.tax.category]}-01`,
9103
+ args: {
9104
+ category: entry.tax.category,
9105
+ rate: entry.tax.rate ?? "",
9106
+ used: entry.first
9107
+ }
9108
+ }
9109
+ );
9110
+ }
9111
+ const rate = (tax, path, at) => {
9112
+ const prefix = RULE_PREFIX[tax.category];
9113
+ const number = at === "line" || at === "breakdown" ? "05" : at === "allowance" ? "06" : "07";
9114
+ if (tax.category === "O") {
9115
+ if (tax.rate !== void 0)
9116
+ add2(
9117
+ "rate_forbidden",
9118
+ `${path}.rate`,
9119
+ `_invoice.${path}.rate must be left out: category O is not subject to VAT and has no rate`,
9120
+ { rule: `${prefix}-${number}` }
9121
+ );
9122
+ return;
9123
+ }
9124
+ if (tax.rate === void 0) {
9125
+ add2(
9126
+ "rate_required",
9127
+ `${path}.rate`,
9128
+ `_invoice.${path}.rate is missing: category ${tax.category} states its rate${tax.category === "S" ? "" : ", which is 0"}`,
9129
+ {
9130
+ rule: at === "breakdown" ? "BR-48" : `${prefix}-${number}`,
9131
+ args: { category: tax.category }
9132
+ }
9133
+ );
9134
+ return;
9135
+ }
9136
+ const value = toUnits(tax.rate, 4);
9137
+ if (tax.category === "S" && value <= 0n)
9138
+ add2(
9139
+ "rate_positive",
9140
+ `${path}.rate`,
9141
+ `_invoice.${path}.rate is ${tax.rate}: category S is standard rated and needs a rate above 0; a rate of 0 is category Z or E`,
9142
+ {
9143
+ rule: `${prefix}-${number}`,
9144
+ args: { rate: tax.rate }
9145
+ }
9146
+ );
9147
+ if (tax.category !== "S" && value !== 0n)
9148
+ add2(
9149
+ "rate_zero",
9150
+ `${path}.rate`,
9151
+ `_invoice.${path}.rate is ${tax.rate}: category ${tax.category} carries a rate of 0`,
9152
+ {
9153
+ rule: `${prefix}-${number}`,
9154
+ args: { rate: tax.rate, category: tax.category }
9155
+ }
9156
+ );
9157
+ };
9158
+ invoice.lines.forEach((line2, i) => rate(line2.tax, `lines[${i}].tax`, "line"));
9159
+ invoice.allowances.forEach(
9160
+ (a, i) => rate(a.tax, `allowances[${i}].tax`, "allowance")
9161
+ );
9162
+ invoice.charges.forEach((c, i) => rate(c.tax, `charges[${i}].tax`, "charge"));
9163
+ const categories = new Set(
9164
+ [...used.values()].map((entry) => entry.tax.category)
9165
+ );
9166
+ invoice.breakdown.forEach((row2, i) => {
9167
+ const path = `tax.breakdown[${i}]`;
9168
+ const prefix = RULE_PREFIX[row2.category];
9169
+ rate(row2, path, "breakdown");
9170
+ categories.add(row2.category);
9171
+ const reason = row2.exemption_reason !== void 0 || row2.exemption_reason_code !== void 0;
9172
+ if (row2.category === "S" || row2.category === "Z") {
9173
+ if (reason)
9174
+ add2(
9175
+ "exemption_reason_forbidden",
9176
+ `${path}.exemption_reason`,
9177
+ `_invoice.${path} must not state an exemption reason: category ${row2.category} is not an exemption`,
9178
+ {
9179
+ rule: `${prefix}-10`,
9180
+ args: { category: row2.category }
9181
+ }
9182
+ );
9183
+ } else if (!reason) {
9184
+ add2(
9185
+ "exemption_reason_required",
9186
+ `${path}.exemption_reason`,
9187
+ `_invoice.${path}.exemption_reason is missing: category ${row2.category} says why no VAT is charged, as text or as exemption_reason_code`,
9188
+ {
9189
+ rule: `${prefix}-10`,
9190
+ args: { category: row2.category }
9191
+ }
9192
+ );
9193
+ }
9194
+ if (row2.category !== "S" && cents(row2.amount) !== 0n)
9195
+ add2(
9196
+ "amount_zero",
9197
+ `${path}.amount`,
9198
+ `_invoice.${path}.amount is ${money(cents(row2.amount))}: category ${row2.category} carries no VAT, so the amount is 0`,
9199
+ {
9200
+ rule: `${prefix}-09`,
9201
+ args: { value: money(cents(row2.amount)), category: row2.category }
9202
+ }
9203
+ );
9204
+ });
9205
+ const sellerTaxId = invoice.seller.vat_id !== void 0 || invoice.seller.tax_number !== void 0;
9206
+ for (const category of categories) {
9207
+ const prefix = RULE_PREFIX[category];
9208
+ if (category === "O") {
9209
+ if (invoice.seller.vat_id !== void 0)
9210
+ add2(
9211
+ "vat_id_forbidden",
9212
+ "seller.vat_id",
9213
+ "_invoice.seller.vat_id must be left out: an invoice of category O is not subject to VAT; the seller is named by tax_number or legal_registration",
9214
+ { rule: "BR-O-02" }
9215
+ );
9216
+ if (invoice.buyer.vat_id !== void 0)
9217
+ add2(
9218
+ "vat_id_forbidden",
9219
+ "buyer.vat_id",
9220
+ "_invoice.buyer.vat_id must be left out: an invoice of category O is not subject to VAT",
9221
+ { rule: "BR-O-02" }
9222
+ );
9223
+ if (categories.size > 1)
9224
+ add2(
9225
+ "only_category",
9226
+ "tax.breakdown",
9227
+ "_invoice mixes category O with others: an invoice that is not subject to VAT has that one category only",
9228
+ { rule: "BR-O-11" }
9229
+ );
9230
+ continue;
9231
+ }
9232
+ if (category === "K" || category === "G") {
9233
+ if (invoice.seller.vat_id === void 0)
9234
+ add2(
9235
+ "seller_tax_id_required",
9236
+ "seller.vat_id",
9237
+ `_invoice.seller.vat_id is missing: category ${category} names the seller's VAT ID`,
9238
+ {
9239
+ rule: `${prefix}-02`,
9240
+ args: { category }
9241
+ }
9242
+ );
9243
+ } else if (!sellerTaxId) {
9244
+ add2(
9245
+ "seller_tax_id_required",
9246
+ "seller.vat_id",
9247
+ `_invoice.seller.vat_id is missing: category ${category} names the seller's VAT ID, or tax_number where there is none`,
9248
+ {
9249
+ rule: `${prefix}-02`,
9250
+ args: { category }
9251
+ }
9252
+ );
9253
+ }
9254
+ if (category === "AE" && invoice.buyer.vat_id === void 0 && invoice.buyer.legal_registration === void 0)
9255
+ add2(
9256
+ "buyer_tax_id_required",
9257
+ "buyer.vat_id",
9258
+ "_invoice.buyer.vat_id is missing: with reverse charge the buyer owes the VAT, so the invoice names the buyer's VAT ID or legal_registration",
9259
+ {
9260
+ rule: "BR-AE-02",
9261
+ args: { category }
9262
+ }
9263
+ );
9264
+ if (category === "K") {
9265
+ if (invoice.buyer.vat_id === void 0)
9266
+ add2(
9267
+ "buyer_tax_id_required",
9268
+ "buyer.vat_id",
9269
+ "_invoice.buyer.vat_id is missing: an intra-community supply names the buyer's VAT ID",
9270
+ {
9271
+ rule: "BR-IC-02",
9272
+ args: { category }
9273
+ }
9274
+ );
9275
+ if (invoice.delivery?.date === void 0 && invoice.period === void 0)
9276
+ add2(
9277
+ "delivery_required",
9278
+ "delivery.date",
9279
+ "_invoice.delivery.date is missing: an intra-community supply states when it was delivered, or the invoicing period",
9280
+ { rule: "BR-IC-11" }
9281
+ );
9282
+ if (invoice.delivery?.address === void 0)
9283
+ add2(
9284
+ "delivery_required",
9285
+ "delivery.address.country",
9286
+ "_invoice.delivery.address.country is missing: an intra-community supply states the country it was delivered to",
9287
+ { rule: "BR-IC-12" }
9288
+ );
9289
+ }
9290
+ }
9291
+ if (invoice.seller.id === void 0 && invoice.seller.legal_registration === void 0 && invoice.seller.vat_id === void 0)
9292
+ add2(
9293
+ "seller_identifier_required",
9294
+ "seller.vat_id",
9295
+ "_invoice.seller needs an identifier the buyer can match: vat_id, legal_registration or id",
9296
+ { rule: "BR-CO-26" }
9297
+ );
9298
+ const payment2 = invoice.payment;
9299
+ const account = payment2?.iban !== void 0 || payment2?.bic !== void 0 || payment2?.account_name !== void 0;
9300
+ if (payment2 && payment2.means_code === void 0 && (account || payment2.mandate_id !== void 0 || payment2.debited_iban !== void 0))
9301
+ add2(
9302
+ "means_code_required",
9303
+ "payment.means_code",
9304
+ "_invoice.payment.means_code is missing: payment details say how the invoice is paid, 58 for a SEPA credit transfer, 59 for a SEPA direct debit",
9305
+ { rule: "BR-49" }
9306
+ );
9307
+ if (payment2?.means_code !== void 0 && CREDIT_TRANSFER.has(payment2.means_code) && payment2.iban === void 0)
9308
+ add2(
9309
+ "account_required",
9310
+ "payment.iban",
9311
+ `_invoice.payment.iban is missing: a payment by credit transfer (code ${payment2.means_code}) names the account`,
9312
+ {
9313
+ rule: "BR-61",
9314
+ args: { means: payment2.means_code }
9315
+ }
9316
+ );
9317
+ if (cents(totals2.due) > 0n && payment2?.due_date === void 0 && payment2?.terms === void 0)
9318
+ add2(
9319
+ "due_or_terms_required",
9320
+ "payment.due_date",
9321
+ "_invoice.payment.due_date is missing: an invoice with an amount due states when it is due, or its payment terms",
9322
+ { rule: "BR-CO-25" }
9323
+ );
9324
+ if (invoice.seller.address.country === "FR" && invoice.buyer.address.country === "FR") {
9325
+ const digits = (id) => (id?.value ?? "").replace(/\s/g, "");
9326
+ if (!/^\d{9}$/.test(digits(invoice.seller.legal_registration)))
9327
+ add2(
9328
+ "fr_seller_siren",
9329
+ "seller.legal_registration",
9330
+ "_invoice.seller.legal_registration is missing or not nine digits: an invoice between French businesses names the seller's SIREN (BT-30)",
9331
+ { rule: "BR-FR-10" }
9332
+ );
9333
+ if (!/^\d{9}$/.test(digits(invoice.buyer.legal_registration)))
9334
+ add2(
9335
+ "fr_buyer_siren",
9336
+ "buyer.siren",
9337
+ "_invoice.buyer.siren is missing or not nine digits: an invoice between French businesses names the buyer's SIREN (BT-47)",
9338
+ { rule: "BR-FR-11" }
9339
+ );
9340
+ if (invoice.business_process === void 0)
9341
+ add2(
9342
+ "fr_operation",
9343
+ "operation",
9344
+ "_invoice.operation is missing: an invoice between French businesses says whether it is for goods, services or mixed (BT-23)",
9345
+ { rule: "BR-FR-08" }
9346
+ );
9347
+ else if (!FRENCH_FRAMEWORKS.has(invoice.business_process))
9348
+ add2(
9349
+ "code_list",
9350
+ "operation_code",
9351
+ `_invoice.operation_code: "${invoice.business_process}" is not a billing framework of the French specifications (B1, S1, M1 and their variants)`,
9352
+ {
9353
+ rule: "BR-FR-08",
9354
+ args: {
9355
+ value: invoice.business_process,
9356
+ list: "the French billing frameworks"
9357
+ }
9358
+ }
9359
+ );
9360
+ if (invoice.seller.vat_on_debits === void 0)
9361
+ add2(
9362
+ "fr_vat_on_debits",
9363
+ "seller.vat_on_debits",
9364
+ "_invoice.seller.vat_on_debits is missing: an invoice between French businesses says whether the seller pays VAT on invoicing (true) or on payment (false)"
9365
+ );
9366
+ }
9367
+ }
9368
+
9369
+ // packages/engine/src/lib/einvoice/cii.ts
9370
+ var CII_GUIDELINES = {
9371
+ basic: "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic",
9372
+ en16931: "urn:cen.eu:en16931:2017"
9373
+ };
9374
+ var EINVOICE_XML_NAME = "factur-x.xml";
9375
+ function leaf(name, text3, attributes) {
9376
+ if (text3 === void 0 || text3 === "") return void 0;
9377
+ const kept = Object.entries(attributes ?? {}).filter(
9378
+ (entry) => entry[1] !== void 0
9379
+ );
9380
+ return {
9381
+ name,
9382
+ text: text3,
9383
+ ...kept.length > 0 ? { attributes: Object.fromEntries(kept) } : {}
9384
+ };
9385
+ }
9386
+ function group2(name, children) {
9387
+ const kept = children.filter((child2) => !!child2);
9388
+ return kept.length > 0 ? { name, children: kept } : void 0;
9389
+ }
9390
+ var date = (name, value) => value === void 0 ? void 0 : group2(name, [
9391
+ leaf("udt:DateTimeString", value.replace(/-/g, ""), { format: "102" })
9392
+ ]);
9393
+ var amount = (name, value, attributes) => value === void 0 ? void 0 : leaf(name, withPlaces(value, 2), attributes);
9394
+ var identifier3 = (plain, withScheme, id) => id === void 0 ? void 0 : id.scheme ? leaf(withScheme, id.value, { schemeID: id.scheme }) : leaf(plain, id.value);
9395
+ function address2(value) {
9396
+ if (!value) return void 0;
9397
+ return group2("ram:PostalTradeAddress", [
9398
+ leaf("ram:PostcodeCode", value.postcode),
9399
+ leaf("ram:LineOne", value.street),
9400
+ leaf("ram:LineTwo", value.street2),
9401
+ leaf("ram:LineThree", value.street3),
9402
+ leaf("ram:CityName", value.city),
9403
+ leaf("ram:CountryID", value.country),
9404
+ leaf("ram:CountrySubDivisionName", value.subdivision)
9405
+ ]);
9406
+ }
9407
+ function party2(name, value, full) {
9408
+ return group2(name, [
9409
+ identifier3("ram:ID", "ram:GlobalID", value.id),
9410
+ leaf("ram:Name", value.name),
9411
+ full ? leaf("ram:Description", value.legal_info) : void 0,
9412
+ group2("ram:SpecifiedLegalOrganization", [
9413
+ value.legal_registration ? leaf("ram:ID", value.legal_registration.value, {
9414
+ schemeID: value.legal_registration.scheme
9415
+ }) : void 0,
9416
+ leaf("ram:TradingBusinessName", value.trading_name)
9417
+ ]),
9418
+ full && value.contact ? group2("ram:DefinedTradeContact", [
9419
+ leaf("ram:PersonName", value.contact.name),
9420
+ group2("ram:TelephoneUniversalCommunication", [
9421
+ leaf("ram:CompleteNumber", value.contact.phone)
9422
+ ]),
9423
+ group2("ram:EmailURIUniversalCommunication", [
9424
+ leaf("ram:URIID", value.contact.email)
9425
+ ])
9426
+ ]) : void 0,
9427
+ address2(value.address),
9428
+ value.electronic_address ? group2("ram:URIUniversalCommunication", [
9429
+ leaf("ram:URIID", value.electronic_address.value, {
9430
+ schemeID: value.electronic_address.scheme
9431
+ })
9432
+ ]) : void 0,
9433
+ group2("ram:SpecifiedTaxRegistration", [
9434
+ leaf("ram:ID", value.vat_id, { schemeID: "VA" })
9435
+ ]),
9436
+ group2("ram:SpecifiedTaxRegistration", [
9437
+ leaf("ram:ID", value.tax_number, { schemeID: "FC" })
9438
+ ])
9439
+ ]);
9440
+ }
9441
+ var taxOf = (tax) => [
9442
+ leaf("ram:TypeCode", "VAT"),
9443
+ leaf("ram:CategoryCode", tax.category),
9444
+ leaf("ram:RateApplicablePercent", tax.rate)
9445
+ ];
9446
+ function allowanceOrCharge2(value, charge) {
9447
+ return group2("ram:SpecifiedTradeAllowanceCharge", [
9448
+ group2("ram:ChargeIndicator", [
9449
+ leaf("udt:Indicator", charge ? "true" : "false")
9450
+ ]),
9451
+ leaf("ram:CalculationPercent", value.percent),
9452
+ amount("ram:BasisAmount", value.base_amount),
9453
+ amount("ram:ActualAmount", value.amount),
9454
+ leaf("ram:ReasonCode", value.reason_code),
9455
+ leaf("ram:Reason", value.reason),
9456
+ value.tax ? group2("ram:CategoryTradeTax", taxOf(value.tax)) : void 0
9457
+ ]);
9458
+ }
9459
+ var period2 = (value) => value === void 0 ? void 0 : group2("ram:BillingSpecifiedPeriod", [
9460
+ date("ram:StartDateTime", value.start),
9461
+ date("ram:EndDateTime", value.end)
9462
+ ]);
9463
+ function invoiceToCii(invoice, options) {
9464
+ const full = options.profile === "en16931";
9465
+ const { totals: totals2, payment: payment2 } = invoice;
9466
+ const lines = invoice.lines.map(
9467
+ (line2) => group2("ram:IncludedSupplyChainTradeLineItem", [
9468
+ group2("ram:AssociatedDocumentLineDocument", [
9469
+ leaf("ram:LineID", line2.id),
9470
+ group2("ram:IncludedNote", [leaf("ram:Content", line2.note)])
9471
+ ]),
9472
+ group2("ram:SpecifiedTradeProduct", [
9473
+ line2.standard_item_id ? leaf("ram:GlobalID", line2.standard_item_id.value, {
9474
+ schemeID: line2.standard_item_id.scheme
9475
+ }) : void 0,
9476
+ full ? leaf("ram:SellerAssignedID", line2.seller_item_id) : void 0,
9477
+ full ? leaf("ram:BuyerAssignedID", line2.buyer_item_id) : void 0,
9478
+ leaf("ram:Name", line2.name),
9479
+ full ? leaf("ram:Description", line2.description) : void 0
9480
+ ]),
9481
+ group2("ram:SpecifiedLineTradeAgreement", [
9482
+ full ? group2("ram:BuyerOrderReferencedDocument", [
9483
+ leaf("ram:LineID", line2.order_line_reference)
9484
+ ]) : void 0,
9485
+ group2("ram:NetPriceProductTradePrice", [
9486
+ leaf("ram:ChargeAmount", withPlaces(line2.net_price, 2)),
9487
+ leaf("ram:BasisQuantity", line2.price_base_quantity, {
9488
+ unitCode: line2.unit_code
9489
+ })
9490
+ ])
9491
+ ]),
9492
+ group2("ram:SpecifiedLineTradeDelivery", [
9493
+ leaf("ram:BilledQuantity", line2.quantity, { unitCode: line2.unit_code })
9494
+ ]),
9495
+ group2("ram:SpecifiedLineTradeSettlement", [
9496
+ group2("ram:ApplicableTradeTax", taxOf(line2.tax)),
9497
+ period2(line2.period),
9498
+ ...line2.allowances.map((a) => allowanceOrCharge2(a, false)),
9499
+ ...line2.charges.map((c) => allowanceOrCharge2(c, true)),
9500
+ group2("ram:SpecifiedTradeSettlementLineMonetarySummation", [
9501
+ amount("ram:LineTotalAmount", line2.net_amount)
9502
+ ]),
9503
+ full ? group2("ram:ReceivableSpecifiedTradeAccountingAccount", [
9504
+ leaf("ram:ID", line2.buyer_accounting_reference)
9505
+ ]) : void 0
9506
+ ])
9507
+ ])
9508
+ );
9509
+ const agreement = group2("ram:ApplicableHeaderTradeAgreement", [
9510
+ leaf("ram:BuyerReference", invoice.buyer_reference),
9511
+ party2("ram:SellerTradeParty", invoice.seller, full),
9512
+ party2("ram:BuyerTradeParty", invoice.buyer, full),
9513
+ group2("ram:BuyerOrderReferencedDocument", [
9514
+ leaf("ram:IssuerAssignedID", invoice.order_reference)
9515
+ ]),
9516
+ group2("ram:ContractReferencedDocument", [
9517
+ leaf("ram:IssuerAssignedID", invoice.contract_reference)
9518
+ ])
9519
+ ]);
9520
+ const shipTo = invoice.delivery;
9521
+ const delivery = group2("ram:ApplicableHeaderTradeDelivery", [
9522
+ group2("ram:ShipToTradeParty", [
9523
+ leaf("ram:Name", shipTo?.name),
9524
+ address2(shipTo?.address)
9525
+ ]),
9526
+ group2("ram:ActualDeliverySupplyChainEvent", [
9527
+ date("ram:OccurrenceDateTime", shipTo?.date)
9528
+ ])
9529
+ ]) ?? { name: "ram:ApplicableHeaderTradeDelivery" };
9530
+ const settlement = group2("ram:ApplicableHeaderTradeSettlement", [
9531
+ leaf("ram:CreditorReferenceID", payment2?.creditor_id),
9532
+ leaf("ram:PaymentReference", payment2?.reference),
9533
+ leaf("ram:TaxCurrencyCode", invoice.accounting_currency),
9534
+ leaf("ram:InvoiceCurrencyCode", invoice.currency),
9535
+ payment2?.means_code ? group2("ram:SpecifiedTradeSettlementPaymentMeans", [
9536
+ leaf("ram:TypeCode", payment2.means_code),
9537
+ group2("ram:PayerPartyDebtorFinancialAccount", [
9538
+ leaf("ram:IBANID", payment2.debited_iban)
9539
+ ]),
9540
+ group2("ram:PayeePartyCreditorFinancialAccount", [
9541
+ leaf("ram:IBANID", payment2.iban),
9542
+ full ? leaf("ram:AccountName", payment2.account_name) : void 0
9543
+ ]),
9544
+ full ? group2("ram:PayeeSpecifiedCreditorFinancialInstitution", [
9545
+ leaf("ram:BICID", payment2.bic)
9546
+ ]) : void 0
9547
+ ]) : void 0,
9548
+ ...invoice.breakdown.map(
9549
+ (row2) => group2("ram:ApplicableTradeTax", [
9550
+ amount("ram:CalculatedAmount", row2.amount),
9551
+ leaf("ram:TypeCode", "VAT"),
9552
+ leaf("ram:ExemptionReason", row2.exemption_reason),
9553
+ amount("ram:BasisAmount", row2.basis),
9554
+ leaf("ram:CategoryCode", row2.category),
9555
+ leaf("ram:ExemptionReasonCode", row2.exemption_reason_code),
9556
+ // France: VAT owed on invoicing rather than on payment is the code for "date of the
9557
+ // invoice" (BT-8). Nothing is written for the default, which the specifications leave unsaid.
9558
+ invoice.seller.vat_on_debits ? leaf("ram:DueDateTypeCode", "5") : void 0,
9559
+ leaf("ram:RateApplicablePercent", row2.rate)
9560
+ ])
9561
+ ),
9562
+ period2(invoice.period),
9563
+ ...invoice.allowances.map((a) => allowanceOrCharge2(a, false)),
9564
+ ...invoice.charges.map((c) => allowanceOrCharge2(c, true)),
9565
+ group2("ram:SpecifiedTradePaymentTerms", [
9566
+ leaf("ram:Description", payment2?.terms),
9567
+ date("ram:DueDateDateTime", payment2?.due_date),
9568
+ leaf("ram:DirectDebitMandateID", payment2?.mandate_id)
9569
+ ]),
9570
+ group2("ram:SpecifiedTradeSettlementHeaderMonetarySummation", [
9571
+ amount("ram:LineTotalAmount", totals2.line_net),
9572
+ amount("ram:ChargeTotalAmount", totals2.charges),
9573
+ amount("ram:AllowanceTotalAmount", totals2.allowances),
9574
+ amount("ram:TaxBasisTotalAmount", totals2.tax_basis),
9575
+ amount("ram:TaxTotalAmount", totals2.tax_total, {
9576
+ currencyID: invoice.currency
9577
+ }),
9578
+ invoice.accounting_currency ? amount("ram:TaxTotalAmount", totals2.tax_total_accounting, {
9579
+ currencyID: invoice.accounting_currency
9580
+ }) : void 0,
9581
+ full ? amount("ram:RoundingAmount", totals2.rounding) : void 0,
9582
+ amount("ram:GrandTotalAmount", totals2.grand),
9583
+ amount("ram:TotalPrepaidAmount", totals2.prepaid),
9584
+ amount("ram:DuePayableAmount", totals2.due)
9585
+ ]),
9586
+ ...invoice.preceding_invoices.map(
9587
+ (reference) => group2("ram:InvoiceReferencedDocument", [
9588
+ leaf("ram:IssuerAssignedID", reference.number),
9589
+ reference.issue_date ? group2("ram:FormattedIssueDateTime", [
9590
+ leaf(
9591
+ "qdt:DateTimeString",
9592
+ reference.issue_date.replace(/-/g, ""),
9593
+ { format: "102" }
9594
+ )
9595
+ ]) : void 0
9596
+ ])
9597
+ )
9598
+ ]);
9599
+ const root = {
9600
+ name: "rsm:CrossIndustryInvoice",
9601
+ attributes: {
9602
+ "xmlns:rsm": "urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100",
9603
+ "xmlns:qdt": "urn:un:unece:uncefact:data:standard:QualifiedDataType:100",
9604
+ "xmlns:ram": "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100",
9605
+ "xmlns:udt": "urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
9606
+ },
9607
+ children: [
9608
+ group2("rsm:ExchangedDocumentContext", [
9609
+ group2("ram:BusinessProcessSpecifiedDocumentContextParameter", [
9610
+ leaf("ram:ID", invoice.business_process)
9611
+ ]),
9612
+ group2("ram:GuidelineSpecifiedDocumentContextParameter", [
9613
+ leaf("ram:ID", CII_GUIDELINES[options.profile])
9614
+ ])
9615
+ ]),
9616
+ group2("rsm:ExchangedDocument", [
9617
+ leaf("ram:ID", invoice.number),
9618
+ leaf("ram:TypeCode", invoice.type_code),
9619
+ date("ram:IssueDateTime", invoice.issue_date),
9620
+ ...invoice.notes.map(
9621
+ (note2) => group2("ram:IncludedNote", [
9622
+ leaf("ram:Content", note2.text),
9623
+ leaf("ram:SubjectCode", note2.subject_code)
9624
+ ])
9625
+ )
9626
+ ]),
9627
+ group2("rsm:SupplyChainTradeTransaction", [
9628
+ ...lines,
9629
+ agreement,
9630
+ delivery,
9631
+ settlement
9632
+ ])
9633
+ ].filter((child2) => !!child2)
9634
+ };
9635
+ return `<?xml version="1.0" encoding="UTF-8"?>
9636
+ ${serialise(root, 0)}`;
9637
+ }
9638
+ var xmlCharacter = (code) => code === 9 || code === 10 || code === 13 || code >= 32 && !(code >= 55296 && code <= 57343) && code !== 65534 && code !== 65535;
9639
+ function carried(text3) {
9640
+ let out = "";
9641
+ for (const character of text3)
9642
+ if (xmlCharacter(character.codePointAt(0) ?? 0)) out += character;
9643
+ return out;
9644
+ }
9645
+ var escapeText2 = (text3) => carried(text3).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
9646
+ var escapeAttribute2 = (text3) => escapeText2(text3).replace(/"/g, "&quot;");
9647
+ function serialise(element, depth) {
9648
+ const indent = " ".repeat(depth);
9649
+ const attributes = Object.entries(element.attributes ?? {}).map(([name, value]) => ` ${name}="${escapeAttribute2(value)}"`).join("");
9650
+ if (element.children === void 0) {
9651
+ return element.text === void 0 ? `${indent}<${element.name}${attributes}/>
9652
+ ` : `${indent}<${element.name}${attributes}>${escapeText2(element.text)}</${element.name}>
9653
+ `;
9654
+ }
9655
+ const children = element.children.map((child2) => serialise(child2, depth + 1)).join("");
9656
+ return `${indent}<${element.name}${attributes}>
9657
+ ${children}${indent}</${element.name}>
9658
+ `;
9659
+ }
9660
+
9661
+ // packages/engine/src/lib/einvoice/display.ts
9662
+ var DISPLAY_TERMS = {
9663
+ "BT-1": "invoice number",
9664
+ "BT-109": "net total",
9665
+ "BT-110": "VAT total",
9666
+ "BT-112": "total",
9667
+ "BT-115": "amount due",
9668
+ "BT-117": "VAT amount"
9669
+ };
9670
+ var DIGIT_0 = 48;
9671
+ var DIGIT_9 = 57;
9672
+ var DOT = 46;
9673
+ var COMMA = 44;
9674
+ var SPACES = /* @__PURE__ */ new Set([32, 160, 8239, 8201]);
9675
+ var APOSTROPHES = /* @__PURE__ */ new Set([39, 8217]);
9676
+ var DASHES = /* @__PURE__ */ new Set([45, 8208, 8209, 8210, 8211, 8722]);
9677
+ var INVISIBLE = /* @__PURE__ */ new Set([173, 8203, 8204, 8205, 8288, 65279]);
9678
+ var isDigit = (code) => code >= DIGIT_0 && code <= DIGIT_9;
9679
+ var MAX_GROUPS = 6;
9680
+ function shownAmounts(text3) {
9681
+ const found = /* @__PURE__ */ new Set();
9682
+ let run2 = "";
9683
+ const flush = () => {
9684
+ const trimmed = run2.replace(/[^0-9]+$/, "");
9685
+ run2 = "";
9686
+ if (!trimmed) return;
9687
+ const parts = trimmed.split(" ").map((part) => part.replace(/[.,]+$/, "")).filter((part) => part !== "");
9688
+ for (let start = 0; start < parts.length; start += 1) {
9689
+ for (const cents2 of readings(parts[start] ?? "")) found.add(cents2);
9690
+ const first = parts[start] ?? "";
9691
+ if (!/^\d{1,3}$/.test(first)) continue;
9692
+ let whole = first;
9693
+ for (let end = start + 1; end < parts.length && end - start < MAX_GROUPS; end += 1) {
9694
+ const part = parts[end] ?? "";
9695
+ const last = /^(\d{3})(?:[.,](\d+))?$/.exec(part);
9696
+ if (!last) break;
9697
+ const cents2 = toCents(whole + last[1], last[2] ?? "");
9698
+ if (cents2 !== null) found.add(cents2);
9699
+ if (last[2] !== void 0) break;
9700
+ whole += last[1];
9701
+ }
9702
+ }
9703
+ };
9704
+ for (const character of text3) {
9705
+ const code = character.codePointAt(0) ?? 0;
9706
+ if (INVISIBLE.has(code)) continue;
9707
+ if (isDigit(code)) run2 += character;
9708
+ else if (run2 && (code === DOT || code === COMMA)) run2 += character;
9709
+ else if (run2 && SPACES.has(code)) run2 += " ";
9710
+ else if (run2 && APOSTROPHES.has(code)) continue;
9711
+ else flush();
9712
+ }
9713
+ flush();
9714
+ return found;
9715
+ }
9716
+ function readings(part) {
9717
+ if (/^\d+$/.test(part)) {
9718
+ const cents2 = toCents(part, "");
9719
+ return cents2 === null ? [] : [cents2];
9720
+ }
9721
+ const out = [];
9722
+ for (const [group3, decimal] of [
9723
+ [".", ","],
9724
+ [",", "."]
9725
+ ]) {
9726
+ const pieces = part.split(decimal);
9727
+ if (pieces.length > 2) continue;
9728
+ const [whole = "", fraction] = pieces;
9729
+ if (fraction !== void 0 && !/^\d+$/.test(fraction)) continue;
9730
+ const groups = whole.split(group3);
9731
+ const grouped = groups.every(
9732
+ (digits, index) => /^\d+$/.test(digits) && (index === 0 ? groups.length === 1 || digits.length <= 3 : digits.length === 3)
9733
+ );
9734
+ if (!grouped) continue;
9735
+ const cents2 = toCents(groups.join(""), fraction ?? "");
9736
+ if (cents2 !== null) out.push(cents2);
9737
+ }
9738
+ return out;
9739
+ }
9740
+ function toCents(whole, fraction) {
9741
+ if (whole.length > 18 || /[1-9]/.test(fraction.slice(2))) return null;
9742
+ return BigInt(whole) * 100n + BigInt((fraction + "00").slice(0, 2));
9743
+ }
9744
+ function squeeze(text3) {
9745
+ let out = "";
9746
+ for (const character of text3) {
9747
+ const code = character.codePointAt(0) ?? 0;
9748
+ if (INVISIBLE.has(code) || /\s/.test(character) || SPACES.has(code))
9749
+ continue;
9750
+ out += DASHES.has(code) ? "-" : character.toLowerCase();
9751
+ }
9752
+ return out;
9753
+ }
9754
+ function displayCheck(text3, invoice) {
9755
+ const whole = typeof text3 === "string" ? text3 : text3.join("\n");
9756
+ const amounts = shownAmounts(whole);
9757
+ const squeezed = squeeze(whole);
9758
+ const values = [];
9759
+ values.push({
9760
+ term: "BT-1",
9761
+ path: "number",
9762
+ value: invoice.number,
9763
+ shown: squeezed.includes(squeeze(invoice.number))
9764
+ });
9765
+ const amount2 = (term, path, value) => {
9766
+ const cents2 = abs(toUnits(value, 2));
9767
+ if (cents2 === 0n) return;
9768
+ values.push({
9769
+ term,
9770
+ path,
9771
+ // as the XML writes it and a reader expects it: `3760.40`, not `3760.4`
9772
+ value: withPlaces(value, 2),
9773
+ shown: amounts.has(cents2)
9774
+ });
9775
+ };
9776
+ const { totals: totals2 } = invoice;
9777
+ amount2("BT-109", "totals.tax_basis", totals2.tax_basis);
9778
+ amount2("BT-110", "totals.tax_total", totals2.tax_total);
9779
+ amount2("BT-112", "totals.grand", totals2.grand);
9780
+ if (toUnits(totals2.due, 2) !== toUnits(totals2.grand, 2))
9781
+ amount2("BT-115", "totals.due", totals2.due);
9782
+ if (invoice.breakdown.length > 1)
9783
+ invoice.breakdown.forEach(
9784
+ (row2, index) => amount2("BT-117", `tax.breakdown[${index}].amount`, row2.amount)
9785
+ );
9786
+ const unique = (terms) => [...new Set(terms)];
9787
+ return {
9788
+ checked: unique(values.map((value) => value.term)),
9789
+ missing: unique(
9790
+ values.filter((value) => !value.shown).map((value) => value.term)
9791
+ ),
9792
+ values
9793
+ };
9794
+ }
9795
+ function displayMissingText(check) {
9796
+ const missing = check.values.filter((value) => !value.shown);
9797
+ if (missing.length === 0) return null;
9798
+ const named = missing.map(
9799
+ (value) => `the ${DISPLAY_TERMS[value.term] ?? value.term} ${value.value} (${value.term})`
9800
+ );
9801
+ const list3 = named.length === 1 ? named[0] : `${named.slice(0, -1).join(", ")} and ${named[named.length - 1]}`;
9802
+ return `The PDF does not show ${list3} of the e-invoice`;
9803
+ }
9804
+
9805
+ // packages/engine/src/lib/einvoice/locate.ts
9806
+ function invoicePathSegments(path) {
9807
+ const segments = [];
9808
+ for (const part of path.split(".")) {
9809
+ if (!part) continue;
9810
+ const match = /^([^[\]]*)((?:\[\d+\])*)$/.exec(part);
9811
+ if (!match) {
9812
+ segments.push(part);
9813
+ continue;
9814
+ }
9815
+ if (match[1]) segments.push(match[1]);
9816
+ for (const index of match[2]?.matchAll(/\[(\d+)\]/g) ?? [])
9817
+ segments.push(Number(index[1]));
9818
+ }
9819
+ return segments;
9820
+ }
9821
+ function locateJsonPath(text3, path) {
9822
+ let offset = skipSpace(text3, 0);
9823
+ if (offset >= text3.length) return null;
9824
+ let best = { offset, depth: 0 };
9825
+ try {
9826
+ for (let depth = 0; depth < path.length; depth += 1) {
9827
+ const segment = path[depth];
9828
+ const found = typeof segment === "number" ? arrayItem(text3, offset, segment) : objectMember(text3, offset, String(segment));
9829
+ if (!found) break;
9830
+ best = { offset: found.at, depth: depth + 1 };
9831
+ offset = found.value;
9832
+ }
9833
+ } catch {
9834
+ }
9835
+ return { ...positionAt(text3, best.offset), depth: best.depth };
9836
+ }
9837
+ function positionAt(text3, offset) {
9838
+ let line2 = 1;
9839
+ let lineStart = 0;
9840
+ for (let i = 0; i < offset; i += 1)
9841
+ if (text3.charCodeAt(i) === 10) {
9842
+ line2 += 1;
9843
+ lineStart = i + 1;
9844
+ }
9845
+ return { line: line2, column: offset - lineStart + 1 };
9846
+ }
9847
+ function skipSpace(text3, from) {
9848
+ let i = from;
9849
+ while (i < text3.length && /\s/.test(text3[i] ?? "")) i += 1;
9850
+ return i;
9851
+ }
9852
+ function stringEnd(text3, from) {
9853
+ if (text3[from] !== '"') throw new Error("string");
9854
+ for (let i = from + 1; i < text3.length; i += 1) {
9855
+ if (text3[i] === "\\") i += 1;
9856
+ else if (text3[i] === '"') return i + 1;
9857
+ }
9858
+ throw new Error("string");
9859
+ }
9860
+ function valueEnd(text3, from) {
9861
+ const start = skipSpace(text3, from);
9862
+ const first = text3[start];
9863
+ if (first === '"') return stringEnd(text3, start);
9864
+ if (first === "{" || first === "[") {
9865
+ const close = first === "{" ? "}" : "]";
9866
+ let i2 = skipSpace(text3, start + 1);
9867
+ if (text3[i2] === close) return i2 + 1;
9868
+ for (; ; ) {
9869
+ if (first === "{") {
9870
+ i2 = skipSpace(text3, stringEnd(text3, skipSpace(text3, i2)));
9871
+ if (text3[i2] !== ":") throw new Error("colon");
9872
+ i2 += 1;
9873
+ }
9874
+ i2 = skipSpace(text3, valueEnd(text3, i2));
9875
+ if (text3[i2] === close) return i2 + 1;
9876
+ if (text3[i2] !== ",") throw new Error("comma");
9877
+ i2 += 1;
9878
+ }
9879
+ }
9880
+ let i = start;
9881
+ while (i < text3.length && !/[\s,\]}]/.test(text3[i] ?? "")) i += 1;
9882
+ if (i === start) throw new Error("value");
9883
+ return i;
9884
+ }
9885
+ function objectMember(text3, from, key) {
9886
+ const start = skipSpace(text3, from);
9887
+ if (text3[start] !== "{") return null;
9888
+ let i = skipSpace(text3, start + 1);
9889
+ while (text3[i] !== "}") {
9890
+ const at = skipSpace(text3, i);
9891
+ const end = stringEnd(text3, at);
9892
+ const colon = skipSpace(text3, end);
9893
+ if (text3[colon] !== ":") throw new Error("colon");
9894
+ const value = skipSpace(text3, colon + 1);
9895
+ if (JSON.parse(text3.slice(at, end)) === key) return { at, value };
9896
+ i = skipSpace(text3, valueEnd(text3, value));
9897
+ if (text3[i] === ",") i = skipSpace(text3, i + 1);
9898
+ else if (text3[i] !== "}") throw new Error("comma");
9899
+ }
9900
+ return null;
9901
+ }
9902
+ function arrayItem(text3, from, index) {
9903
+ const start = skipSpace(text3, from);
9904
+ if (text3[start] !== "[") return null;
9905
+ let i = skipSpace(text3, start + 1);
9906
+ for (let n = 0; text3[i] !== "]"; n += 1) {
9907
+ const at = skipSpace(text3, i);
9908
+ if (n === index) return { at, value: at };
9909
+ i = skipSpace(text3, valueEnd(text3, at));
9910
+ if (text3[i] === ",") i = skipSpace(text3, i + 1);
9911
+ else if (text3[i] !== "]") throw new Error("comma");
9912
+ }
9913
+ return null;
9914
+ }
9915
+
9916
+ // packages/engine/src/lib/einvoice/report.ts
9917
+ var EINVOICE_MAX_MESSAGES = 50;
9918
+ function capMessages(messages, max2 = EINVOICE_MAX_MESSAGES) {
9919
+ const sorted = [
9920
+ ...messages.filter((message) => message.severity === "error"),
9921
+ ...messages.filter((message) => message.severity !== "error")
9922
+ ];
9923
+ return sorted.length > max2 ? { messages: sorted.slice(0, max2), truncated: true } : { messages: sorted };
9924
+ }
9925
+ function einvoiceResult(options, specVersion, validation, display) {
9926
+ return {
9927
+ profile: options.profile,
9928
+ flavour: options.flavour,
9929
+ spec_version: specVersion,
9930
+ validation: validation ? {
9931
+ valid: validation.valid,
9932
+ schematron: validation.schematron,
9933
+ pdfa: validation.pdfa,
9934
+ ...capMessages(validation.messages)
9935
+ } : null,
9936
+ display: display ? { checked: display.checked, missing: display.missing } : null
9937
+ };
9938
+ }
9939
+ var EINVOICE_FLAVOUR_NAMES = {
9940
+ "factur-x": "Factur-X",
9941
+ zugferd: "ZUGFeRD"
9942
+ };
9943
+ var EINVOICE_PROFILE_NAMES = {
9944
+ basic: "Basic",
9945
+ en16931: "EN 16931"
9946
+ };
9947
+ function invoiceLineOf(location) {
9948
+ if (!location) return null;
9949
+ const match = /IncludedSupplyChainTradeLineItem\[(\d+)\]/.exec(location);
9950
+ return match ? Number(match[1]) : null;
9951
+ }
9952
+
9953
+ // packages/engine/src/lib/einvoice/html-text.ts
9954
+ var INLINE = /* @__PURE__ */ new Set([
9955
+ "a",
9956
+ "abbr",
9957
+ "b",
9958
+ "bdi",
9959
+ "bdo",
9960
+ "cite",
9961
+ "code",
9962
+ "data",
9963
+ "del",
9964
+ "dfn",
9965
+ "em",
9966
+ "font",
9967
+ "i",
9968
+ "ins",
9969
+ "kbd",
9970
+ "label",
9971
+ "mark",
9972
+ "nobr",
9973
+ "output",
9974
+ "q",
9975
+ "s",
9976
+ "samp",
9977
+ "small",
9978
+ "span",
9979
+ "strong",
9980
+ "sub",
9981
+ "sup",
9982
+ "time",
9983
+ "tt",
9984
+ "u",
9985
+ "var",
9986
+ "wbr"
9987
+ ]);
9988
+ var SKIPPED = ["script", "style", "template", "noscript", "head", "title"];
9989
+ var ENTITIES = {
9990
+ amp: 38,
9991
+ lt: 60,
9992
+ gt: 62,
9993
+ quot: 34,
9994
+ apos: 39,
9995
+ nbsp: 160,
9996
+ ensp: 8194,
9997
+ emsp: 8195,
9998
+ thinsp: 8201,
9999
+ shy: 173,
10000
+ minus: 8722,
10001
+ ndash: 8211,
10002
+ mdash: 8212,
10003
+ hyphen: 8208,
10004
+ euro: 8364,
10005
+ pound: 163,
10006
+ yen: 165,
10007
+ cent: 162,
10008
+ sect: 167,
10009
+ middot: 183,
10010
+ bull: 8226,
10011
+ times: 215,
10012
+ auml: 228,
10013
+ ouml: 246,
10014
+ uuml: 252,
10015
+ Auml: 196,
10016
+ Ouml: 214,
10017
+ Uuml: 220,
10018
+ szlig: 223,
10019
+ eacute: 233,
10020
+ egrave: 232,
10021
+ agrave: 224,
10022
+ ccedil: 231
10023
+ };
10024
+ function decodeEntities(text3) {
10025
+ return text3.replace(
10026
+ /&(#x[0-9a-f]+|#\d+|[a-z][a-z0-9]*);/gi,
10027
+ (whole, reference) => {
10028
+ const code = reference.startsWith("#") ? reference[1] === "x" || reference[1] === "X" ? Number.parseInt(reference.slice(2), 16) : Number.parseInt(reference.slice(1), 10) : ENTITIES[reference];
10029
+ return code !== void 0 && Number.isFinite(code) && code > 0 && code <= 1114111 ? String.fromCodePoint(code) : whole;
10030
+ }
10031
+ );
10032
+ }
10033
+ function htmlText(html) {
10034
+ let source = html.replace(/<!--[\s\S]*?-->/g, "");
10035
+ for (const tag2 of SKIPPED)
10036
+ source = source.replace(
10037
+ new RegExp(`<${tag2}\\b[^>]*>[\\s\\S]*?</${tag2}\\s*>`, "gi"),
10038
+ "\n"
10039
+ );
10040
+ let out = "";
10041
+ let position = 0;
10042
+ const tag = /<\/?([a-zA-Z][a-zA-Z0-9-]*)(?:"[^"]*"|'[^']*'|[^'">])*>/g;
10043
+ for (let match = tag.exec(source); match; match = tag.exec(source)) {
10044
+ out += source.slice(position, match.index);
10045
+ position = match.index + match[0].length;
10046
+ const name = (match[1] ?? "").toLowerCase();
10047
+ if (name === "br" || !INLINE.has(name)) out += "\n";
10048
+ }
10049
+ out += source.slice(position);
10050
+ return decodeEntities(out).split("\n").map((line2) => line2.replace(/[ \t\r\f]+/g, " ").trim()).filter((line2) => line2 !== "").join("\n");
10051
+ }
10052
+
10053
+ // packages/engine/src/lib/einvoice/skeleton.ts
10054
+ function invoiceSkeleton(issueDate = "2026-01-15") {
10055
+ const due = /* @__PURE__ */ new Date(`${issueDate}T00:00:00Z`);
10056
+ due.setUTCDate(due.getUTCDate() + 14);
10057
+ const number = `RE-${issueDate.slice(0, 4)}-0001`;
10058
+ return {
10059
+ number,
10060
+ issue_date: issueDate,
10061
+ type_code: "380",
10062
+ currency: "EUR",
10063
+ seller: {
10064
+ name: "Fennlor Studio GmbH",
10065
+ vat_id: "DE000000000",
10066
+ address: {
10067
+ street: "Musterstra\xDFe 1",
10068
+ postcode: "12345",
10069
+ city: "Musterstadt",
10070
+ country: "DE"
10071
+ },
10072
+ contact: {
10073
+ name: "Erika Mustermann",
10074
+ email: "rechnung@fennlor.example",
10075
+ phone: "+49 30 0000000"
10076
+ }
10077
+ },
10078
+ buyer: {
10079
+ name: "Olvarest GmbH",
10080
+ address: {
10081
+ street: "Beispielweg 2",
10082
+ postcode: "54321",
10083
+ city: "Beispielstadt",
10084
+ country: "DE"
10085
+ }
10086
+ },
10087
+ delivery: { date: issueDate },
10088
+ lines: [
10089
+ {
10090
+ id: "1",
10091
+ name: "Consulting",
10092
+ quantity: 8,
10093
+ unit_code: "HUR",
10094
+ net_price: 120,
10095
+ net_amount: 960,
10096
+ tax: { category: "S", rate: 19 }
10097
+ }
10098
+ ],
10099
+ tax: {
10100
+ breakdown: [{ category: "S", rate: 19, basis: 960, amount: 182.4 }]
10101
+ },
10102
+ totals: {
10103
+ line_net: 960,
10104
+ tax_basis: 960,
10105
+ tax_total: 182.4,
10106
+ grand: 1142.4,
10107
+ due: 1142.4
10108
+ },
10109
+ payment: {
10110
+ means_code: "58",
10111
+ iban: "DE36000000000000000000",
10112
+ reference: number,
10113
+ terms: "Zahlbar innerhalb von 14 Tagen ohne Abzug",
10114
+ due_date: due.toISOString().slice(0, 10)
10115
+ }
10116
+ };
10117
+ }
10118
+
10119
+ // packages/engine/src/lib/einvoice/index.ts
10120
+ var INVOICE_DATA_KEY = "_invoice";
10121
+ var EINVOICE_SPEC_VERSIONS = {
10122
+ "factur-x": "1.09",
10123
+ zugferd: "2.5"
10124
+ };
10125
+ function invoiceAmountText(amount2) {
10126
+ return withPlaces(amount2, 2);
10127
+ }
10128
+ function einvoiceXml(data, options) {
10129
+ const block = data !== null && typeof data === "object" ? data[INVOICE_DATA_KEY] : void 0;
10130
+ if (block === void 0 || block === null)
10131
+ return {
10132
+ ok: false,
10133
+ problems: [
10134
+ {
10135
+ code: "missing",
10136
+ path: "",
10137
+ message: "The data has no _invoice block: an e-invoice is built from it",
10138
+ args: { path: "" }
10139
+ }
10140
+ ]
10141
+ };
10142
+ const check = checkInvoice(block, options);
10143
+ if (!check.ok) return { ok: false, problems: check.problems };
10144
+ return {
10145
+ ok: true,
10146
+ xml: invoiceToCii(check.invoice, options),
10147
+ invoice: check.invoice
10148
+ };
10149
+ }
10150
+
8009
10151
  // packages/engine/src/lib/office/errors.ts
8010
10152
  var OfficeError = class extends Error {
8011
10153
  constructor(code, message, details = {}) {
@@ -9325,12 +11467,12 @@ function assertWellFormed(tokens, part) {
9325
11467
  }
9326
11468
  var FORBIDDEN = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
9327
11469
  var ENTITY = /&(?:#x[0-9A-Fa-f]+|#\d+|amp|lt|gt|quot|apos);/y;
9328
- function checkText(text2, part) {
9329
- if (FORBIDDEN.test(text2)) throw invalid2("a character XML does not allow", part);
9330
- if (text2.includes("<")) throw invalid2("unescaped < in text", part);
9331
- for (let i = text2.indexOf("&"); i !== -1; i = text2.indexOf("&", i + 1)) {
11470
+ function checkText(text3, part) {
11471
+ if (FORBIDDEN.test(text3)) throw invalid2("a character XML does not allow", part);
11472
+ if (text3.includes("<")) throw invalid2("unescaped < in text", part);
11473
+ for (let i = text3.indexOf("&"); i !== -1; i = text3.indexOf("&", i + 1)) {
9332
11474
  ENTITY.lastIndex = i;
9333
- if (!ENTITY.test(text2)) throw invalid2(`invalid entity reference near "${text2.slice(i, i + 12)}"`, part);
11475
+ if (!ENTITY.test(text3)) throw invalid2(`invalid entity reference near "${text3.slice(i, i + 12)}"`, part);
9334
11476
  }
9335
11477
  }
9336
11478
  function checkAttributes(raw, part) {
@@ -9365,13 +11507,13 @@ function decodeText3(raw) {
9365
11507
  }
9366
11508
  });
9367
11509
  }
9368
- function escapeText2(text2) {
9369
- return text2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
11510
+ function escapeText3(text3) {
11511
+ return text3.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
9370
11512
  }
9371
11513
  var FORBIDDEN_GLOBAL = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
9372
- function stripForbidden(text2) {
11514
+ function stripForbidden(text3) {
9373
11515
  let removed = 0;
9374
- const out = text2.replace(FORBIDDEN_GLOBAL, () => {
11516
+ const out = text3.replace(FORBIDDEN_GLOBAL, () => {
9375
11517
  removed++;
9376
11518
  return "";
9377
11519
  });
@@ -9584,7 +11726,7 @@ function textWidthEmu(xml2) {
9584
11726
  function inlinePicture(picture, rId, id) {
9585
11727
  const a = "http://schemas.openxmlformats.org/drawingml/2006/main";
9586
11728
  const name = `Formfeed picture ${id}`;
9587
- const alt = escapeText2(picture.alt).replace(/"/g, "&quot;");
11729
+ const alt = escapeText3(picture.alt).replace(/"/g, "&quot;");
9588
11730
  const { widthEmu: cx, heightEmu: cy } = picture;
9589
11731
  return `<w:drawing><wp:inline xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" distT="0" distB="0" distL="0" distR="0"><wp:extent cx="${cx}" cy="${cy}"/><wp:effectExtent l="0" t="0" r="0" b="0"/><wp:docPr id="${id}" name="${name}" descr="${alt}"/><wp:cNvGraphicFramePr><a:graphicFrameLocks xmlns:a="${a}" noChangeAspect="1"/></wp:cNvGraphicFramePr><a:graphic xmlns:a="${a}"><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:nvPicPr><pic:cNvPr id="${id}" name="${name}" descr="${alt}"/><pic:cNvPicPr/></pic:nvPicPr><pic:blipFill><a:blip r:embed="${rId}"/><a:stretch><a:fillRect/></a:stretch></pic:blipFill><pic:spPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="${cx}" cy="${cy}"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></pic:spPr></pic:pic></a:graphicData></a:graphic></wp:inline></w:drawing>`;
9590
11732
  }
@@ -9622,13 +11764,13 @@ function placeDrawings(xml2, pattern, markupFor) {
9622
11764
  pattern.lastIndex = 0;
9623
11765
  if (pattern.test(t.raw)) {
9624
11766
  const segments = t.raw.split(pattern);
9625
- let text2 = segments[0];
11767
+ let text3 = segments[0];
9626
11768
  for (let s = 1; s < segments.length; s += 2) {
9627
11769
  const index = Number(segments[s]);
9628
- text2 += `</w:t></w:r><w:r>${runProps}${markupFor(index)}</w:r>${runOpen}${runProps}<w:t xml:space="preserve">` + segments[s + 1];
11770
+ text3 += `</w:t></w:r><w:r>${runProps}${markupFor(index)}</w:r>${runOpen}${runProps}<w:t xml:space="preserve">` + segments[s + 1];
9629
11771
  }
9630
11772
  out[textOpen] = withPreserve(out[textOpen]);
9631
- out.push(text2);
11773
+ out.push(text3);
9632
11774
  continue;
9633
11775
  }
9634
11776
  }
@@ -9641,7 +11783,7 @@ function withPreserve(openTag) {
9641
11783
  }
9642
11784
  function withRelationships(rels2, relationships) {
9643
11785
  const type = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
9644
- const added = relationships.map((r) => `<Relationship Id="${r.id}" Type="${type}" Target="${escapeText2(r.target)}"/>`).join("");
11786
+ const added = relationships.map((r) => `<Relationship Id="${r.id}" Type="${type}" Target="${escapeText3(r.target)}"/>`).join("");
9645
11787
  if (!rels2)
9646
11788
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">${added}</Relationships>`;
9647
11789
  const end = rels2.lastIndexOf("</Relationships>");
@@ -9883,11 +12025,11 @@ function fromTemplateOutput(output, template, part) {
9883
12025
  let last = 0;
9884
12026
  let inText = false;
9885
12027
  const emit = (segment) => {
9886
- const { text: text2, removed } = stripForbidden(segment);
12028
+ const { text: text3, removed } = stripForbidden(segment);
9887
12029
  removedCharacters += removed;
9888
- if (!inText && text2.trim() !== "")
9889
- throw new OfficeError("office_document_invalid", `${part ?? "part"}: text outside a text element: "${text2.trim().slice(0, 40)}"`);
9890
- xml2 += escapeText2(text2);
12030
+ if (!inText && text3.trim() !== "")
12031
+ throw new OfficeError("office_document_invalid", `${part ?? "part"}: text outside a text element: "${text3.trim().slice(0, 40)}"`);
12032
+ xml2 += escapeText3(text3);
9891
12033
  };
9892
12034
  for (const m of output.matchAll(placeholder)) {
9893
12035
  emit(output.slice(last, m.index));
@@ -9929,15 +12071,15 @@ function layoutText(xml2, flavour, part) {
9929
12071
  out.push(token2.raw);
9930
12072
  continue;
9931
12073
  }
9932
- const text2 = token2.raw.replace(/\r\n?/g, "\n");
12074
+ const text3 = token2.raw.replace(/\r\n?/g, "\n");
9933
12075
  if (flavour === "wordprocessing") {
9934
- const pieces = text2.split(/(\n|\t)/);
9935
- if (pieces.length > 1 || /^\s|\s$/.test(text2)) out[textOpenIndex] = preserveSpace(out[textOpenIndex]);
12076
+ const pieces = text3.split(/(\n|\t)/);
12077
+ if (pieces.length > 1 || /^\s|\s$/.test(text3)) out[textOpenIndex] = preserveSpace(out[textOpenIndex]);
9936
12078
  out.push(
9937
12079
  pieces.map((p) => p === "\n" ? '</w:t><w:br/><w:t xml:space="preserve">' : p === " " ? '</w:t><w:tab/><w:t xml:space="preserve">' : p).join("")
9938
12080
  );
9939
12081
  } else {
9940
- out.push(text2.split("\n").join(`</a:t></a:r><a:br>${runProperties}</a:br><a:r>${runProperties}<a:t>`));
12082
+ out.push(text3.split("\n").join(`</a:t></a:r><a:br>${runProperties}</a:br><a:r>${runProperties}<a:t>`));
9941
12083
  }
9942
12084
  }
9943
12085
  return out.join("");
@@ -9970,17 +12112,17 @@ var AUTOCORRECTED = [
9970
12112
  [/\u200B|\u200C|\u200D|\uFEFF/g, ""]
9971
12113
  ];
9972
12114
  function normaliseTags(template, part) {
9973
- const { text: text2, origin, placeholders } = stripPlaceholders(template);
12115
+ const { text: text3, origin, placeholders } = stripPlaceholders(template);
9974
12116
  const sourceRange = (from, to) => [
9975
12117
  origin[from] ?? template.source.length,
9976
12118
  (origin[to - 1] ?? template.source.length - 1) + 1
9977
12119
  ];
9978
12120
  const diagnostics = [];
9979
12121
  const edits = [];
9980
- for (const tag of findTags(text2)) {
12122
+ for (const tag of findTags(text3)) {
9981
12123
  const inside = placeholders.filter((p) => p.at > tag.start && p.at < tag.end);
9982
12124
  const paragraph2 = paragraphOf(template, placeholders, tag.start);
9983
- const raw = text2.slice(tag.start, tag.end);
12125
+ const raw = text3.slice(tag.start, tag.end);
9984
12126
  const unsafe = inside.filter((p) => {
9985
12127
  const piece = template.markup[p.index];
9986
12128
  return !piece || piece.paragraphBoundary || piece.containerBoundary;
@@ -10016,7 +12158,7 @@ function normaliseTags(template, part) {
10016
12158
  for (const p of placeholders) {
10017
12159
  const raw = template.markup[p.index]?.raw ?? "";
10018
12160
  for (const m of raw.matchAll(/<w:instrText\b[^>]*>([^<]*)<\/w:instrText>/g)) {
10019
- const code = decodeEntities(m[1] ?? "");
12161
+ const code = decodeEntities2(m[1] ?? "");
10020
12162
  if (!/\{\{|\{%|\{#/.test(code)) continue;
10021
12163
  const paragraph2 = paragraphOf(template, placeholders, p.at);
10022
12164
  if (reported.has(paragraph2)) continue;
@@ -10033,38 +12175,38 @@ function normaliseTags(template, part) {
10033
12175
  }
10034
12176
  return { template: { ...template, source: applyEdits(template.source, edits) }, diagnostics };
10035
12177
  }
10036
- var ENTITIES = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'" };
10037
- function decodeEntities(text2) {
10038
- return text2.replace(/&(#x[0-9a-f]+|#\d+|amp|lt|gt|quot|apos);/gi, (whole, name) => {
10039
- if (name[0] !== "#") return ENTITIES[name.toLowerCase()] ?? whole;
12178
+ var ENTITIES2 = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'" };
12179
+ function decodeEntities2(text3) {
12180
+ return text3.replace(/&(#x[0-9a-f]+|#\d+|amp|lt|gt|quot|apos);/gi, (whole, name) => {
12181
+ if (name[0] !== "#") return ENTITIES2[name.toLowerCase()] ?? whole;
10040
12182
  const code = name[1] === "x" || name[1] === "X" ? parseInt(name.slice(2), 16) : parseInt(name.slice(1), 10);
10041
12183
  return Number.isFinite(code) ? String.fromCodePoint(code) : whole;
10042
12184
  });
10043
12185
  }
10044
12186
  function stripPlaceholders(template) {
10045
12187
  const pattern = placeholderPattern(template.nonce);
10046
- let text2 = "";
12188
+ let text3 = "";
10047
12189
  const origin = [];
10048
12190
  const placeholders = [];
10049
12191
  let last = 0;
10050
12192
  for (const m of template.source.matchAll(pattern)) {
10051
12193
  for (let i = last; i < (m.index ?? 0); i++) {
10052
- text2 += template.source[i];
12194
+ text3 += template.source[i];
10053
12195
  origin.push(i);
10054
12196
  }
10055
- placeholders.push({ index: Number(m[1]), at: text2.length, from: m.index ?? 0, to: (m.index ?? 0) + m[0].length });
12197
+ placeholders.push({ index: Number(m[1]), at: text3.length, from: m.index ?? 0, to: (m.index ?? 0) + m[0].length });
10056
12198
  last = (m.index ?? 0) + m[0].length;
10057
12199
  }
10058
12200
  for (let i = last; i < template.source.length; i++) {
10059
- text2 += template.source[i];
12201
+ text3 += template.source[i];
10060
12202
  origin.push(i);
10061
12203
  }
10062
- return { text: text2, origin, placeholders };
12204
+ return { text: text3, origin, placeholders };
10063
12205
  }
10064
12206
  function listTags(template, part) {
10065
- const { text: text2, placeholders } = stripPlaceholders(template);
10066
- return findTags(text2).map((tag) => {
10067
- const raw = text2.slice(tag.start, tag.end);
12207
+ const { text: text3, placeholders } = stripPlaceholders(template);
12208
+ return findTags(text3).map((tag) => {
12209
+ const raw = text3.slice(tag.start, tag.end);
10068
12210
  const kind = raw.startsWith("{#") ? "comment" : raw.startsWith("{%") || /^\{\{~?\s*[#/^]/.test(raw) || /^\{\{~?\s*else\b/.test(raw) ? "block" : "output";
10069
12211
  return { part, paragraph: paragraphOf(template, placeholders, tag.start), text: raw.replace(/\s+/g, " ").trim(), kind };
10070
12212
  });
@@ -10085,15 +12227,15 @@ function undoAutocorrect(tag) {
10085
12227
  for (const [pattern, replacement] of AUTOCORRECTED) out = out.replace(pattern, replacement);
10086
12228
  return out;
10087
12229
  }
10088
- function findTags(text2) {
12230
+ function findTags(text3) {
10089
12231
  const tags = [];
10090
- for (let i = 0; i < text2.length - 1; i++) {
10091
- const opener = OPENERS.find((o) => text2.startsWith(o, i));
12232
+ for (let i = 0; i < text3.length - 1; i++) {
12233
+ const opener = OPENERS.find((o) => text3.startsWith(o, i));
10092
12234
  if (!opener) continue;
10093
12235
  const closer = CLOSERS[opener];
10094
- const end = text2.indexOf(closer, i + opener.length);
12236
+ const end = text3.indexOf(closer, i + opener.length);
10095
12237
  if (end === -1) continue;
10096
- const stop = end + closer.length + (opener === "{{" && text2[end + closer.length] === "}" ? 1 : 0);
12238
+ const stop = end + closer.length + (opener === "{{" && text3[end + closer.length] === "}" ? 1 : 0);
10097
12239
  tags.push({ start: i, end: stop });
10098
12240
  i = stop - 1;
10099
12241
  }
@@ -10123,8 +12265,8 @@ var CONTENT = /* @__PURE__ */ new Set(["w:drawing", "w:pict", "w:object", "w:fld
10123
12265
  var JINJA_OPEN = /^(for|if|unless|case|capture|raw|with|macro|call|filter|block|tablerow|comment|autoescape)\b/;
10124
12266
  var JINJA_CLOSE = /^end(for|if|unless|case|capture|raw|with|macro|call|filter|block|tablerow|comment|autoescape)\b/;
10125
12267
  var JINJA_MIDDLE = /^(else|elif|elsif|when)\b/;
10126
- function blockRole(text2) {
10127
- const t = text2.trim();
12268
+ function blockRole(text3) {
12269
+ const t = text3.trim();
10128
12270
  let m = /^\{%-?\s*([\s\S]*?)\s*-?%\}$/.exec(t);
10129
12271
  if (m && !t.slice(2, -2).includes("%}")) {
10130
12272
  const body = m[1] ?? "";
@@ -10156,14 +12298,14 @@ function dropTaggedFallbacks(xml2, part) {
10156
12298
  if (t.kind === "open" && t.name === "mc:Fallback" && !t.selfClosing) {
10157
12299
  let depth = 1;
10158
12300
  let j = i + 1;
10159
- let text2 = "";
12301
+ let text3 = "";
10160
12302
  for (; j < tokens.length && depth > 0; j++) {
10161
12303
  const u = tokens[j];
10162
12304
  if (u.kind === "open" && u.name === "mc:Fallback" && !u.selfClosing) depth++;
10163
12305
  else if (u.kind === "close" && u.name === "mc:Fallback") depth--;
10164
- else if (u.kind === "text") text2 += decodeText3(u.raw);
12306
+ else if (u.kind === "text") text3 += decodeText3(u.raw);
10165
12307
  }
10166
- if (/\{\{|\{%|\{#/.test(text2)) {
12308
+ if (/\{\{|\{%|\{#/.test(text3)) {
10167
12309
  i = j - 1;
10168
12310
  continue;
10169
12311
  }
@@ -10230,15 +12372,15 @@ function applyStructure(xml2, part) {
10230
12372
  }
10231
12373
  }
10232
12374
  const replacements = [];
10233
- const element = (tag) => `<${STRUCTURAL_ELEMENT}>${escapeText2(tag)}</${STRUCTURAL_ELEMENT}>`;
12375
+ const element = (tag) => `<${STRUCTURAL_ELEMENT}>${escapeText3(tag)}</${STRUCTURAL_ELEMENT}>`;
10234
12376
  for (const [row2, tag] of replacedRows) replacements.push({ start: row2.start, end: row2.end, text: element(tag) });
10235
12377
  const cellsEmptied = /* @__PURE__ */ new Map();
10236
12378
  for (const [span, s] of structural) {
10237
12379
  if (rowOf.has(span)) continue;
10238
12380
  const keep = s.info.sectionProperties;
10239
- let text2 = element(s.tag);
10240
- if (keep) text2 = s.role === "open" ? `<w:p>${keep}</w:p>${text2}` : `${text2}<w:p>${keep}</w:p>`;
10241
- replacements.push({ start: span.start, end: span.end, text: text2 });
12381
+ let text3 = element(s.tag);
12382
+ if (keep) text3 = s.role === "open" ? `<w:p>${keep}</w:p>${text3}` : `${text3}<w:p>${keep}</w:p>`;
12383
+ replacements.push({ start: span.start, end: span.end, text: text3 });
10242
12384
  const holder = span.parent && BODIES.has(span.parent.name) ? span.parent : null;
10243
12385
  if (holder && !keep) cellsEmptied.set(holder, (cellsEmptied.get(holder) ?? 0) + 1);
10244
12386
  }
@@ -10292,7 +12434,7 @@ function collectParagraphs(tokens, root) {
10292
12434
  const out = [];
10293
12435
  const walk3 = (span) => {
10294
12436
  if (PARAGRAPH.has(span.name)) {
10295
- let text2 = "";
12437
+ let text3 = "";
10296
12438
  let hasContent = false;
10297
12439
  let sectionProperties = null;
10298
12440
  let inText = false;
@@ -10303,10 +12445,10 @@ function collectParagraphs(tokens, root) {
10303
12445
  else if (CONTENT.has(t.name)) hasContent = true;
10304
12446
  else if (t.name === "w:sectPr") sectionProperties = "";
10305
12447
  } else if (t.kind === "close" && TEXT.has(t.name)) inText = false;
10306
- else if (t.kind === "text" && inText) text2 += decodeText3(t.raw);
12448
+ else if (t.kind === "text" && inText) text3 += decodeText3(t.raw);
10307
12449
  }
10308
12450
  if (sectionProperties !== null) sectionProperties = propertiesOf(tokens, span);
10309
- out.push({ span, number: out.length + 1, text: text2, hasContent, sectionProperties });
12451
+ out.push({ span, number: out.length + 1, text: text3, hasContent, sectionProperties });
10310
12452
  }
10311
12453
  for (const child2 of span.children) walk3(child2);
10312
12454
  };
@@ -10328,9 +12470,9 @@ function isInside(span, container) {
10328
12470
  function rewrite(tokens, replacements) {
10329
12471
  const byStart = /* @__PURE__ */ new Map();
10330
12472
  for (const r of replacements) {
10331
- const list2 = byStart.get(r.start) ?? [];
10332
- list2.push({ end: r.end, text: r.text });
10333
- byStart.set(r.start, list2);
12473
+ const list3 = byStart.get(r.start) ?? [];
12474
+ list3.push({ end: r.end, text: r.text });
12475
+ byStart.set(r.start, list3);
10334
12476
  }
10335
12477
  let out = "";
10336
12478
  for (let i = 0; i < tokens.length; i++) {
@@ -10379,7 +12521,7 @@ function boxOf(container, tokens) {
10379
12521
  return x === null || y === null || cx === null || cy === null ? null : { x, y, cx, cy };
10380
12522
  }
10381
12523
  function slidePicture(picture, rId, id, box) {
10382
- const alt = escapeText2(picture.alt).replace(/"/g, "&quot;");
12524
+ const alt = escapeText3(picture.alt).replace(/"/g, "&quot;");
10383
12525
  return `<p:pic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><p:nvPicPr><p:cNvPr id="${id}" name="Formfeed picture ${id}" descr="${alt}"/><p:cNvPicPr><a:picLocks noChangeAspect="1"/></p:cNvPicPr><p:nvPr/></p:nvPicPr><p:blipFill><a:blip r:embed="${rId}"/><a:stretch><a:fillRect/></a:stretch></p:blipFill><p:spPr><a:xfrm><a:off x="${box.x}" y="${box.y}"/><a:ext cx="${box.cx}" cy="${box.cy}"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></p:spPr></p:pic>`;
10384
12526
  }
10385
12527
  function layoutPictures(pictures, box, growsWithText = false) {
@@ -10414,7 +12556,7 @@ function placeSlidePictures(xml2, pattern, drawingFor, pictureMarkup, slide) {
10414
12556
  for (const container of containers) {
10415
12557
  const indexes = [];
10416
12558
  const edits = [];
10417
- let text2 = "";
12559
+ let text3 = "";
10418
12560
  let inText = false;
10419
12561
  for (let i = container.start + 1; i < container.end; i++) {
10420
12562
  const t = tokens[i];
@@ -10423,7 +12565,7 @@ function placeSlidePictures(xml2, pattern, drawingFor, pictureMarkup, slide) {
10423
12565
  else if (t.kind === "text" && inText) {
10424
12566
  pattern.lastIndex = 0;
10425
12567
  if (!pattern.test(t.raw)) {
10426
- text2 += decodeText3(t.raw);
12568
+ text3 += decodeText3(t.raw);
10427
12569
  continue;
10428
12570
  }
10429
12571
  const segments = t.raw.split(pattern);
@@ -10432,7 +12574,7 @@ function placeSlidePictures(xml2, pattern, drawingFor, pictureMarkup, slide) {
10432
12574
  if (s % 2 === 1) indexes.push(Number(segments[s]));
10433
12575
  else kept += segments[s];
10434
12576
  }
10435
- text2 += decodeText3(kept);
12577
+ text3 += decodeText3(kept);
10436
12578
  edits.push({ at: i, raw: kept });
10437
12579
  }
10438
12580
  }
@@ -10451,7 +12593,7 @@ function placeSlidePictures(xml2, pattern, drawingFor, pictureMarkup, slide) {
10451
12593
  }
10452
12594
  const autoFit = tokens.slice(container.start, container.end).some((t) => t.kind === "open" && t.name === "a:spAutoFit");
10453
12595
  const placed = layoutPictures(pictures, box, autoFit).map((b, i) => pictureMarkup(pictures[i], b)).join("");
10454
- const onlyPictures = container.name === "p:sp" && text2.trim() === "";
12596
+ const onlyPictures = container.name === "p:sp" && text3.trim() === "";
10455
12597
  if (onlyPictures) replacements.push({ start: container.start, end: container.end, text: placed });
10456
12598
  else {
10457
12599
  for (const edit of edits) replacements.push({ start: edit.at, end: edit.at, text: edit.raw });
@@ -10724,8 +12866,8 @@ function starterTags(engine) {
10724
12866
  codeFit: engine === "liquid" ? "{{ offer.url | qrcode }}" : "{{ qrcode(offer.url) }}"
10725
12867
  };
10726
12868
  }
10727
- var paragraph = (text2, style2, bold = false) => `<w:p>${style2 ? `<w:pPr><w:pStyle w:val="${style2}"/></w:pPr>` : ""}<w:r>${bold ? "<w:rPr><w:b/></w:rPr>" : ""}<w:t xml:space="preserve">${escapeText2(text2)}</w:t></w:r></w:p>`;
10728
- var cell = (text2, width, bold = false) => `<w:tc><w:tcPr><w:tcW w:w="${width}" w:type="dxa"/></w:tcPr>${paragraph(text2, void 0, bold)}</w:tc>`;
12869
+ var paragraph = (text3, style2, bold = false) => `<w:p>${style2 ? `<w:pPr><w:pStyle w:val="${style2}"/></w:pPr>` : ""}<w:r>${bold ? "<w:rPr><w:b/></w:rPr>" : ""}<w:t xml:space="preserve">${escapeText3(text3)}</w:t></w:r></w:p>`;
12870
+ var cell = (text3, width, bold = false) => `<w:tc><w:tcPr><w:tcW w:w="${width}" w:type="dxa"/></w:tcPr>${paragraph(text3, void 0, bold)}</w:tc>`;
10729
12871
  var row = (cells) => `<w:tr>${cells}</w:tr>`;
10730
12872
  function starterDocument(engine) {
10731
12873
  const t = starterTags(engine);
@@ -10768,7 +12910,7 @@ function starterDocument(engine) {
10768
12910
  ["word/document.xml", `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:document xmlns:w="${W}"><w:body>${body}</w:body></w:document>`]
10769
12911
  ];
10770
12912
  return {
10771
- bytes: writeZip(files.map(([name, text2]) => ({ name, data: encoder2.encode(text2) }))),
12913
+ bytes: writeZip(files.map(([name, text3]) => ({ name, data: encoder2.encode(text3) }))),
10772
12914
  sampleData: starterSampleData()
10773
12915
  };
10774
12916
  }
@@ -10796,15 +12938,15 @@ var CM = 36e4;
10796
12938
  var FONT = "Carlito";
10797
12939
  var ACCENT = "0F766E";
10798
12940
  var emptyTree = '<p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr><p:grpSpPr/>';
10799
- var run = (text2, size, options = {}) => `<a:r><a:rPr lang="en-GB" sz="${size * 100}"${options.bold ? ' b="1"' : ""} dirty="0">${options.color ? `<a:solidFill><a:srgbClr val="${options.color}"/></a:solidFill>` : ""}<a:latin typeface="${FONT}"/></a:rPr><a:t>${escapeText2(text2)}</a:t></a:r>`;
10800
- var para = (text2, size, options = {}) => `<a:p>${run(text2, size, options)}</a:p>`;
12941
+ var run = (text3, size, options = {}) => `<a:r><a:rPr lang="en-GB" sz="${size * 100}"${options.bold ? ' b="1"' : ""} dirty="0">${options.color ? `<a:solidFill><a:srgbClr val="${options.color}"/></a:solidFill>` : ""}<a:latin typeface="${FONT}"/></a:rPr><a:t>${escapeText3(text3)}</a:t></a:r>`;
12942
+ var para = (text3, size, options = {}) => `<a:p>${run(text3, size, options)}</a:p>`;
10801
12943
  function textBox(id, name, x, y, cx, cy, paragraphs) {
10802
12944
  return `<p:sp><p:nvSpPr><p:cNvPr id="${id}" name="${name}"/><p:cNvSpPr txBox="1"/><p:nvPr/></p:nvSpPr><p:spPr><a:xfrm><a:off x="${x}" y="${y}"/><a:ext cx="${cx}" cy="${cy}"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom><a:noFill/></p:spPr><p:txBody><a:bodyPr wrap="square" rtlCol="0"><a:noAutofit/></a:bodyPr><a:lstStyle/>${paragraphs}</p:txBody></p:sp>`;
10803
12945
  }
10804
- function cell2(text2, header) {
12946
+ function cell2(text3, header) {
10805
12947
  const fill = header ? `<a:solidFill><a:srgbClr val="${ACCENT}"/></a:solidFill>` : "<a:noFill/>";
10806
- const line = `<a:lnB w="6350"><a:solidFill><a:srgbClr val="BFBFBF"/></a:solidFill></a:lnB>`;
10807
- return `<a:tc><a:txBody><a:bodyPr/><a:lstStyle/>${para(text2, 14, header ? { bold: true, color: "FFFFFF" } : {})}</a:txBody><a:tcPr marL="91440" marR="91440" marT="45720" marB="45720">${line}${fill}</a:tcPr></a:tc>`;
12948
+ const line2 = `<a:lnB w="6350"><a:solidFill><a:srgbClr val="BFBFBF"/></a:solidFill></a:lnB>`;
12949
+ return `<a:tc><a:txBody><a:bodyPr/><a:lstStyle/>${para(text3, 14, header ? { bold: true, color: "FFFFFF" } : {})}</a:txBody><a:tcPr marL="91440" marR="91440" marT="45720" marB="45720">${line2}${fill}</a:tcPr></a:tc>`;
10808
12950
  }
10809
12951
  var tableRow = (a, b, header = false) => `<a:tr h="${Math.round(0.9 * CM)}">${cell2(a, header)}${cell2(b, header)}</a:tr>`;
10810
12952
  function table2(id, x, y, rows) {
@@ -10814,8 +12956,8 @@ function table2(id, x, y, rows) {
10814
12956
  function theme() {
10815
12957
  const scheme = (name, color) => `<a:${name}><a:srgbClr val="${color}"/></a:${name}>`;
10816
12958
  const fill = `<a:solidFill><a:schemeClr val="phClr"/></a:solidFill>`;
10817
- const line = `<a:ln w="6350"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill></a:ln>`;
10818
- return `<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Formfeed"><a:themeElements><a:clrScheme name="Formfeed">${scheme("dk1", "000000")}${scheme("lt1", "FFFFFF")}${scheme("dk2", "1F2937")}${scheme("lt2", "F3F4F6")}${scheme("accent1", ACCENT)}${scheme("accent2", "F59E0B")}${scheme("accent3", "2563EB")}${scheme("accent4", "DC2626")}${scheme("accent5", "7C3AED")}${scheme("accent6", "059669")}${scheme("hlink", "2563EB")}${scheme("folHlink", "7C3AED")}</a:clrScheme><a:fontScheme name="Formfeed"><a:majorFont><a:latin typeface="${FONT}"/><a:ea typeface=""/><a:cs typeface=""/></a:majorFont><a:minorFont><a:latin typeface="${FONT}"/><a:ea typeface=""/><a:cs typeface=""/></a:minorFont></a:fontScheme><a:fmtScheme name="Formfeed"><a:fillStyleLst>${fill}${fill}${fill}</a:fillStyleLst><a:lnStyleLst>${line}${line}${line}</a:lnStyleLst><a:effectStyleLst><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst/></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst>${fill}${fill}${fill}</a:bgFillStyleLst></a:fmtScheme></a:themeElements></a:theme>`;
12959
+ const line2 = `<a:ln w="6350"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill></a:ln>`;
12960
+ return `<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Formfeed"><a:themeElements><a:clrScheme name="Formfeed">${scheme("dk1", "000000")}${scheme("lt1", "FFFFFF")}${scheme("dk2", "1F2937")}${scheme("lt2", "F3F4F6")}${scheme("accent1", ACCENT)}${scheme("accent2", "F59E0B")}${scheme("accent3", "2563EB")}${scheme("accent4", "DC2626")}${scheme("accent5", "7C3AED")}${scheme("accent6", "059669")}${scheme("hlink", "2563EB")}${scheme("folHlink", "7C3AED")}</a:clrScheme><a:fontScheme name="Formfeed"><a:majorFont><a:latin typeface="${FONT}"/><a:ea typeface=""/><a:cs typeface=""/></a:majorFont><a:minorFont><a:latin typeface="${FONT}"/><a:ea typeface=""/><a:cs typeface=""/></a:minorFont></a:fontScheme><a:fmtScheme name="Formfeed"><a:fillStyleLst>${fill}${fill}${fill}</a:fillStyleLst><a:lnStyleLst>${line2}${line2}${line2}</a:lnStyleLst><a:effectStyleLst><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst/></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst>${fill}${fill}${fill}</a:bgFillStyleLst></a:fmtScheme></a:themeElements></a:theme>`;
10819
12961
  }
10820
12962
  var xml = (body) => `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${body}`;
10821
12963
  var rels = (entries) => xml(
@@ -10894,21 +13036,33 @@ function starterPresentation(engine) {
10894
13036
  ];
10895
13037
  const encoder2 = new TextEncoder();
10896
13038
  return {
10897
- bytes: writeZip(files.map(([name, text2]) => ({ name, data: encoder2.encode(text2) }))),
13039
+ bytes: writeZip(files.map(([name, text3]) => ({ name, data: encoder2.encode(text3) }))),
10898
13040
  sampleData: starterSampleData()
10899
13041
  };
10900
13042
  }
10901
13043
  export {
13044
+ CII_GUIDELINES,
13045
+ CODE_LIST_RELEASE,
10902
13046
  DEFAULT_CHROME_PADDING,
10903
13047
  DESIGN_LIMITS,
10904
13048
  DESIGN_VERSION,
13049
+ DISPLAY_TERMS,
10905
13050
  DefaultHelperRegistry,
13051
+ EINVOICE_FLAVOURS,
13052
+ EINVOICE_FLAVOUR_NAMES,
13053
+ EINVOICE_MAX_MESSAGES,
13054
+ EINVOICE_PROFILES,
13055
+ EINVOICE_PROFILE_NAMES,
13056
+ EINVOICE_SPEC_VERSIONS,
13057
+ EINVOICE_XML_NAME,
10906
13058
  EPC_MAX_BYTES,
10907
13059
  EngineSyntaxError,
13060
+ INVOICE_DATA_KEY,
10908
13061
  OFFICE_FILLED_MAX_BYTES,
10909
13062
  OfficeTemplateError,
10910
13063
  RenderError,
10911
13064
  RenderLimitError,
13065
+ VAT_CATEGORIES,
10912
13066
  analyzeHandlebars,
10913
13067
  analyzeJinja2,
10914
13068
  analyzeLiquid,
@@ -10920,13 +13074,16 @@ export {
10920
13074
  brandCss,
10921
13075
  builtinHelpers,
10922
13076
  canvasDocument,
13077
+ capMessages,
10923
13078
  chartInitScript,
10924
13079
  chartMarkup,
10925
13080
  chartPayload,
13081
+ checkInvoice,
10926
13082
  chipValues,
10927
13083
  convertScss,
10928
13084
  createHelperRegistry,
10929
13085
  dataPathPattern,
13086
+ defaultEinvoiceOptions,
10930
13087
  defaultHelpers,
10931
13088
  defaultLayer,
10932
13089
  defaultLimits,
@@ -10937,9 +13094,14 @@ export {
10937
13094
  designOutputHash,
10938
13095
  designStarters,
10939
13096
  diffSchemas,
13097
+ displayCheck,
13098
+ displayMissingText,
10940
13099
  editAttribute,
10941
13100
  editableRegion,
10942
13101
  editableRegionAt,
13102
+ einvoiceOptionsSchema,
13103
+ einvoiceResult,
13104
+ einvoiceXml,
10943
13105
  emitDesign,
10944
13106
  emptyBrand,
10945
13107
  emptyDesign,
@@ -10959,6 +13121,7 @@ export {
10959
13121
  googleFontsUrl,
10960
13122
  handlebarsEngine,
10961
13123
  helperDocs,
13124
+ htmlText,
10962
13125
  ibanChecksum,
10963
13126
  imageIsEmpty,
10964
13127
  imageMarkup,
@@ -10969,6 +13132,12 @@ export {
10969
13132
  importPdfmonkey,
10970
13133
  inferSchema,
10971
13134
  inferSchemaFromDataSets,
13135
+ invoiceAmountText,
13136
+ invoiceLineOf,
13137
+ invoicePathSegments,
13138
+ invoiceSchema,
13139
+ invoiceSkeleton,
13140
+ invoiceToCii,
10972
13141
  isApitemplateHtmlTemplate,
10973
13142
  isApitemplateRegion,
10974
13143
  isOfficeKind,
@@ -10982,6 +13151,7 @@ export {
10982
13151
  liquidBuiltinFilters,
10983
13152
  liquidEngine,
10984
13153
  liquidTags,
13154
+ locateJsonPath,
10985
13155
  mergeSampleData,
10986
13156
  mergeSettings,
10987
13157
  mergeSnippetCss,
@@ -11008,12 +13178,15 @@ export {
11008
13178
  readJsreportExport,
11009
13179
  regionChips,
11010
13180
  regionItems,
13181
+ regionPosition,
11011
13182
  renderOffice,
11012
13183
  renderVersion,
13184
+ resolveEinvoiceOptions,
11013
13185
  resolvePath,
11014
13186
  resolveTranslation,
11015
13187
  scanBlocks,
11016
13188
  schemaPaths,
13189
+ shownAmounts,
11017
13190
  slugFromName,
11018
13191
  snippetText,
11019
13192
  snippets,