@formfeed/engine 0.3.12 → 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs +694 -275
- package/index.js +694 -275
- package/package.json +1 -1
- package/types/frame/audit.d.cts +15 -0
- package/types/frame/audit.d.ts +15 -0
- package/types/frame/audit.entry.d.cts +1 -0
- package/types/frame/audit.entry.d.ts +1 -0
- package/types/index.d.cts +5 -0
- package/types/index.d.ts +5 -0
- package/types/lib/accessibility/index.d.cts +201 -0
- package/types/lib/accessibility/index.d.ts +201 -0
- package/types/lib/accessibility/static.d.cts +40 -0
- package/types/lib/accessibility/static.d.ts +40 -0
- package/types/lib/assemble.d.cts +8 -0
- package/types/lib/assemble.d.ts +8 -0
- package/types/lib/generated/frames.d.cts +2 -0
- package/types/lib/generated/frames.d.ts +2 -0
- package/types/lib/helpers/document.d.cts +5 -0
- package/types/lib/helpers/document.d.ts +5 -0
- package/types/lib/preview.d.cts +5 -0
- package/types/lib/preview.d.ts +5 -0
package/index.cjs
CHANGED
|
@@ -30,6 +30,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// packages/engine/src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
ACCESSIBILITY_HEADER_LENGTH: () => ACCESSIBILITY_HEADER_LENGTH,
|
|
34
|
+
ACCESSIBILITY_MAX_ELEMENTS: () => ACCESSIBILITY_MAX_ELEMENTS,
|
|
35
|
+
ACCESSIBILITY_MAX_FAILURES: () => ACCESSIBILITY_MAX_FAILURES,
|
|
36
|
+
AUDIT_CODES: () => AUDIT_CODES,
|
|
37
|
+
AUDIT_RULES: () => AUDIT_RULES,
|
|
38
|
+
AUDIT_SEVERITY: () => AUDIT_SEVERITY,
|
|
39
|
+
AUDIT_SNIPPET_LENGTH: () => AUDIT_SNIPPET_LENGTH,
|
|
40
|
+
AUDIT_TITLES: () => AUDIT_TITLES,
|
|
33
41
|
CII_GUIDELINES: () => CII_GUIDELINES,
|
|
34
42
|
CODE_LIST_RELEASE: () => CODE_LIST_RELEASE,
|
|
35
43
|
DEFAULT_CHROME_PADDING: () => DEFAULT_CHROME_PADDING,
|
|
@@ -49,9 +57,15 @@ __export(index_exports, {
|
|
|
49
57
|
INVOICE_DATA_KEY: () => INVOICE_DATA_KEY,
|
|
50
58
|
OFFICE_FILLED_MAX_BYTES: () => OFFICE_FILLED_MAX_BYTES,
|
|
51
59
|
OfficeTemplateError: () => OfficeTemplateError,
|
|
60
|
+
PDFUA_STANDARD: () => PDFUA_STANDARD,
|
|
52
61
|
RenderError: () => RenderError,
|
|
53
62
|
RenderLimitError: () => RenderLimitError,
|
|
63
|
+
UA_CHECKS: () => UA_CHECKS,
|
|
64
|
+
UA_REFUSALS: () => UA_REFUSALS,
|
|
54
65
|
VAT_CATEGORIES: () => VAT_CATEGORIES,
|
|
66
|
+
accessibilityHeader: () => accessibilityHeader,
|
|
67
|
+
accessibilityHeaderValue: () => accessibilityHeaderValue,
|
|
68
|
+
accessibilityResult: () => accessibilityResult,
|
|
55
69
|
analyzeHandlebars: () => analyzeHandlebars,
|
|
56
70
|
analyzeJinja2: () => analyzeJinja2,
|
|
57
71
|
analyzeLiquid: () => analyzeLiquid,
|
|
@@ -60,6 +74,8 @@ __export(index_exports, {
|
|
|
60
74
|
apitemplateRegions: () => apitemplateRegions,
|
|
61
75
|
applyRegionEdit: () => applyRegionEdit,
|
|
62
76
|
assembleDocument: () => assembleDocument,
|
|
77
|
+
auditMessage: () => auditMessage,
|
|
78
|
+
auditRuntime: () => auditRuntime,
|
|
63
79
|
brandCss: () => brandCss,
|
|
64
80
|
builtinHelpers: () => builtinHelpers,
|
|
65
81
|
canvasDocument: () => canvasDocument,
|
|
@@ -132,6 +148,7 @@ __export(index_exports, {
|
|
|
132
148
|
isOfficeKind: () => isOfficeKind,
|
|
133
149
|
isOutputFormat: () => isOutputFormat,
|
|
134
150
|
isScss: () => isScss,
|
|
151
|
+
isUaSetting: () => isUaSetting,
|
|
135
152
|
jinja2Engine: () => jinja2Engine,
|
|
136
153
|
jinjaTags: () => jinjaTags,
|
|
137
154
|
jsreportTemplates: () => jsreportTemplates,
|
|
@@ -173,6 +190,7 @@ __export(index_exports, {
|
|
|
173
190
|
resolveEinvoiceOptions: () => resolveEinvoiceOptions,
|
|
174
191
|
resolvePath: () => resolvePath,
|
|
175
192
|
resolveTranslation: () => resolveTranslation,
|
|
193
|
+
resolveUa: () => resolveUa,
|
|
176
194
|
scanBlocks: () => scanBlocks,
|
|
177
195
|
schemaPaths: () => schemaPaths,
|
|
178
196
|
shownAmounts: () => shownAmounts,
|
|
@@ -184,6 +202,8 @@ __export(index_exports, {
|
|
|
184
202
|
splitApitemplateCss: () => splitApitemplateCss,
|
|
185
203
|
starterDocument: () => starterDocument,
|
|
186
204
|
starterPresentation: () => starterPresentation,
|
|
205
|
+
staticAudit: () => staticAudit,
|
|
206
|
+
staticAuditDiagnostics: () => staticAuditDiagnostics,
|
|
187
207
|
strftimeToDateFns: () => strftimeToDateFns,
|
|
188
208
|
svgDataUri: () => svgDataUri,
|
|
189
209
|
toDate: () => toDate,
|
|
@@ -380,11 +400,11 @@ function validateEpc(input) {
|
|
|
380
400
|
const purpose = String(input.purpose ?? "");
|
|
381
401
|
if (purpose.length > 4) problems.push({ field: "purpose", code: "too_long", max: 4, actual: purpose.length });
|
|
382
402
|
const reference = String(input.reference ?? "").trim();
|
|
383
|
-
const
|
|
384
|
-
if (reference &&
|
|
403
|
+
const text4 = String(input.text ?? "").trim();
|
|
404
|
+
if (reference && text4) problems.push({ field: "reference", code: "reference_or_text" });
|
|
385
405
|
if (reference.length > 35)
|
|
386
406
|
problems.push({ field: "reference", code: "too_long", max: 35, actual: reference.length });
|
|
387
|
-
if (
|
|
407
|
+
if (text4.length > 140) problems.push({ field: "text", code: "too_long", max: 140, actual: text4.length });
|
|
388
408
|
const bytes = byteLength(epcPayload(input));
|
|
389
409
|
if (bytes > EPC_MAX_BYTES)
|
|
390
410
|
problems.push({ field: "payload", code: "too_long", max: EPC_MAX_BYTES, actual: bytes });
|
|
@@ -422,9 +442,12 @@ var barcodeTypes = {
|
|
|
422
442
|
};
|
|
423
443
|
var ownTextLayout = /* @__PURE__ */ new Set(["ean13", "ean8", "upca"]);
|
|
424
444
|
function codeText(helper, value) {
|
|
425
|
-
const
|
|
426
|
-
if (
|
|
427
|
-
|
|
445
|
+
const text4 = value === void 0 || value === null ? "" : String(value);
|
|
446
|
+
if (text4 === "")
|
|
447
|
+
throw new Error(
|
|
448
|
+
`${helper}: nothing to encode, the value is empty or missing from the data`
|
|
449
|
+
);
|
|
450
|
+
return text4;
|
|
428
451
|
}
|
|
429
452
|
var codeHelpers = [
|
|
430
453
|
{
|
|
@@ -432,18 +455,25 @@ var codeHelpers = [
|
|
|
432
455
|
aliases: ["qr"],
|
|
433
456
|
doc: {
|
|
434
457
|
signature: "qrcode(value, { size = 160, ecc = 'M', margin = 1, color, background })",
|
|
435
|
-
description: "QR code as an SVG data URI for an <img> src.",
|
|
458
|
+
description: "QR code as an SVG data URI for an <img> src. Give the image an `alt` that says where the code leads: a screen reader cannot scan it.",
|
|
436
459
|
examples: {
|
|
437
|
-
jinja2: '<img src="{{ qrcode(order.url, { size: 120 }) }}">',
|
|
438
|
-
liquid: '<img src="{{ order.url | qrcode: size: 120 }}">',
|
|
439
|
-
handlebars: '<img src="{{qrcode order.url size=120}}">'
|
|
460
|
+
jinja2: '<img src="{{ qrcode(order.url, { size: 120 }) }}" alt="QR code: {{ order.url }}">',
|
|
461
|
+
liquid: '<img src="{{ order.url | qrcode: size: 120 }}" alt="QR code: {{ order.url }}">',
|
|
462
|
+
handlebars: '<img src="{{qrcode order.url size=120}}" alt="QR code: {{order.url}}">'
|
|
440
463
|
},
|
|
441
464
|
category: "code"
|
|
442
465
|
},
|
|
443
466
|
fn: (ctx, value, options) => {
|
|
444
467
|
const o = options ?? {};
|
|
445
468
|
const svg = qrSvg(codeText("qrcode", value), o);
|
|
446
|
-
if (ctx.drawing)
|
|
469
|
+
if (ctx.drawing)
|
|
470
|
+
return ctx.drawing({
|
|
471
|
+
kind: "svg",
|
|
472
|
+
svg,
|
|
473
|
+
width: o.size,
|
|
474
|
+
height: o.size,
|
|
475
|
+
alt: "QR code"
|
|
476
|
+
});
|
|
447
477
|
return svgDataUri(svg);
|
|
448
478
|
}
|
|
449
479
|
},
|
|
@@ -451,28 +481,29 @@ var codeHelpers = [
|
|
|
451
481
|
name: "barcode",
|
|
452
482
|
doc: {
|
|
453
483
|
signature: "barcode(value, { type = 'code128', height = 12, width, text = true, scale = 2 })",
|
|
454
|
-
description: "Barcode (code128, ean13, ean8, upc, itf14, code39, datamatrix, pdf417) as an SVG data URI.",
|
|
484
|
+
description: "Barcode (code128, ean13, ean8, upc, itf14, code39, datamatrix, pdf417) as an SVG data URI. Give the image an `alt` with the value it encodes.",
|
|
455
485
|
examples: {
|
|
456
|
-
jinja2: `<img src="{{ barcode(item.sku, { type: 'code128' }) }}">`,
|
|
457
|
-
liquid: `<img src="{{ item.sku | barcode: type: 'code128' }}">`,
|
|
458
|
-
handlebars: `<img src="{{barcode item.sku type='code128'}}">`
|
|
486
|
+
jinja2: `<img src="{{ barcode(item.sku, { type: 'code128' }) }}" alt="Barcode {{ item.sku }}">`,
|
|
487
|
+
liquid: `<img src="{{ item.sku | barcode: type: 'code128' }}" alt="Barcode {{ item.sku }}">`,
|
|
488
|
+
handlebars: `<img src="{{barcode item.sku type='code128'}}" alt="Barcode {{item.sku}}">`
|
|
459
489
|
},
|
|
460
490
|
category: "code"
|
|
461
491
|
},
|
|
462
492
|
fn: (ctx, value, options) => {
|
|
463
493
|
const o = options ?? {};
|
|
464
494
|
const bcid = barcodeTypes[String(o.type ?? "code128").toLowerCase()] ?? "code128";
|
|
465
|
-
const
|
|
495
|
+
const text4 = codeText("barcode", value);
|
|
466
496
|
const svg = (0, import_bwip_js.toSVG)({
|
|
467
497
|
bcid,
|
|
468
|
-
text:
|
|
498
|
+
text: text4,
|
|
469
499
|
height: o.height ?? 12,
|
|
470
500
|
...o.width === void 0 ? {} : { width: o.width },
|
|
471
501
|
scale: o.scale ?? 2,
|
|
472
502
|
includetext: o.text !== false,
|
|
473
503
|
...ownTextLayout.has(bcid) ? {} : { textxalign: "center" }
|
|
474
504
|
});
|
|
475
|
-
if (ctx.drawing)
|
|
505
|
+
if (ctx.drawing)
|
|
506
|
+
return ctx.drawing({ kind: "svg", svg, alt: `Barcode ${text4}` });
|
|
476
507
|
return svgDataUri(svg);
|
|
477
508
|
}
|
|
478
509
|
},
|
|
@@ -481,11 +512,11 @@ var codeHelpers = [
|
|
|
481
512
|
aliases: ["epc_qr", "girocode"],
|
|
482
513
|
doc: {
|
|
483
514
|
signature: "epcQr({ name, iban, bic?, amount?, reference?, text? }, { size })",
|
|
484
|
-
description: "SEPA credit transfer QR code (EPC069-12 / GiroCode) that banking apps scan to prefill a payment.",
|
|
515
|
+
description: "SEPA credit transfer QR code (EPC069-12 / GiroCode) that banking apps scan to prefill a payment. Give the image an `alt`, and print the bank details as text as well: the code is a picture.",
|
|
485
516
|
examples: {
|
|
486
|
-
jinja2: '<img src="{{ epcQr({ name: company.name, iban: company.iban, amount: invoice.total, reference: invoice.number }) }}">',
|
|
487
|
-
liquid: '<img src="{{ company.iban | epcQr: name: company.name, amount: invoice.total, reference: invoice.number }}">',
|
|
488
|
-
handlebars: '<img src="{{epcQr name=company.name iban=company.iban amount=invoice.total reference=invoice.number}}">'
|
|
517
|
+
jinja2: '<img src="{{ epcQr({ name: company.name, iban: company.iban, amount: invoice.total, reference: invoice.number }) }}" alt="QR code to pay invoice {{ invoice.number }}">',
|
|
518
|
+
liquid: '<img src="{{ company.iban | epcQr: name: company.name, amount: invoice.total, reference: invoice.number }}" alt="QR code to pay invoice {{ invoice.number }}">',
|
|
519
|
+
handlebars: '<img src="{{epcQr name=company.name iban=company.iban amount=invoice.total reference=invoice.number}}" alt="QR code to pay invoice {{invoice.number}}">'
|
|
489
520
|
},
|
|
490
521
|
category: "code"
|
|
491
522
|
},
|
|
@@ -504,12 +535,27 @@ var codeHelpers = [
|
|
|
504
535
|
(EPC_FIELDS.has(key) ? payment2 : qr)[key] = value;
|
|
505
536
|
const o = { ecc: "M", ...qr };
|
|
506
537
|
const svg = qrSvg(epcPayload(payment2), o);
|
|
507
|
-
if (ctx.drawing)
|
|
538
|
+
if (ctx.drawing)
|
|
539
|
+
return ctx.drawing({
|
|
540
|
+
kind: "svg",
|
|
541
|
+
svg,
|
|
542
|
+
width: o.size,
|
|
543
|
+
height: o.size,
|
|
544
|
+
alt: "GiroCode"
|
|
545
|
+
});
|
|
508
546
|
return svgDataUri(svg);
|
|
509
547
|
}
|
|
510
548
|
}
|
|
511
549
|
];
|
|
512
|
-
var EPC_FIELDS = /* @__PURE__ */ new Set([
|
|
550
|
+
var EPC_FIELDS = /* @__PURE__ */ new Set([
|
|
551
|
+
"name",
|
|
552
|
+
"iban",
|
|
553
|
+
"bic",
|
|
554
|
+
"amount",
|
|
555
|
+
"reference",
|
|
556
|
+
"text",
|
|
557
|
+
"purpose"
|
|
558
|
+
]);
|
|
513
559
|
|
|
514
560
|
// packages/engine/src/lib/helpers/format.ts
|
|
515
561
|
var import_tz = require("@date-fns/tz");
|
|
@@ -527,8 +573,8 @@ var import_nl = require("n2words/nl");
|
|
|
527
573
|
function resolveTranslation(dictionaries, locale, key) {
|
|
528
574
|
const lang = locale.split("-")[0] ?? locale;
|
|
529
575
|
for (const candidate of [locale, lang, "en"]) {
|
|
530
|
-
const
|
|
531
|
-
if (typeof
|
|
576
|
+
const text4 = dictionaries?.[candidate]?.[key];
|
|
577
|
+
if (typeof text4 === "string") return { text: text4, from: candidate };
|
|
532
578
|
}
|
|
533
579
|
return { text: key, from: null };
|
|
534
580
|
}
|
|
@@ -1008,9 +1054,9 @@ var formatHelpers = [
|
|
|
1008
1054
|
category: "text"
|
|
1009
1055
|
},
|
|
1010
1056
|
fn: (ctx, key, params) => {
|
|
1011
|
-
const { text:
|
|
1057
|
+
const { text: text4 } = resolveTranslation(ctx.i18n, ctx.locale, str(key));
|
|
1012
1058
|
const p = params ?? {};
|
|
1013
|
-
return
|
|
1059
|
+
return text4.replace(/\{(\w+)\}/g, (_, name) => str(p[name]));
|
|
1014
1060
|
}
|
|
1015
1061
|
},
|
|
1016
1062
|
{
|
|
@@ -1281,7 +1327,16 @@ var collectionHelpers = [
|
|
|
1281
1327
|
];
|
|
1282
1328
|
|
|
1283
1329
|
// packages/engine/src/lib/helpers/document.ts
|
|
1284
|
-
var CHART_PALETTE = [
|
|
1330
|
+
var CHART_PALETTE = [
|
|
1331
|
+
"#3E63DD",
|
|
1332
|
+
"#12A594",
|
|
1333
|
+
"#E5484D",
|
|
1334
|
+
"#F76B15",
|
|
1335
|
+
"#8E4EC6",
|
|
1336
|
+
"#FFC53D",
|
|
1337
|
+
"#0090FF",
|
|
1338
|
+
"#978365"
|
|
1339
|
+
];
|
|
1285
1340
|
var SLICED = /* @__PURE__ */ new Set(["pie", "doughnut", "polarArea"]);
|
|
1286
1341
|
var colour = (value) => typeof value === "string" && value ? value : Array.isArray(value) && value.length ? value.map(String) : void 0;
|
|
1287
1342
|
function chartDataFromPlain(spec) {
|
|
@@ -1295,8 +1350,13 @@ function chartDataFromPlain(spec) {
|
|
|
1295
1350
|
});
|
|
1296
1351
|
const own = colour(s.color);
|
|
1297
1352
|
const fill = SLICED.has(type) ? own ?? labels.map((_, i) => CHART_PALETTE[i % CHART_PALETTE.length]) : own ?? CHART_PALETTE[index % CHART_PALETTE.length];
|
|
1298
|
-
const dataset = {
|
|
1299
|
-
|
|
1353
|
+
const dataset = {
|
|
1354
|
+
data,
|
|
1355
|
+
backgroundColor: fill,
|
|
1356
|
+
borderColor: fill
|
|
1357
|
+
};
|
|
1358
|
+
if (s.label !== void 0 && s.label !== null && s.label !== "")
|
|
1359
|
+
dataset["label"] = String(s.label);
|
|
1300
1360
|
if (type === "line") dataset["fill"] = false;
|
|
1301
1361
|
return dataset;
|
|
1302
1362
|
});
|
|
@@ -1313,7 +1373,8 @@ function chartPayload(spec) {
|
|
|
1313
1373
|
const options = { ...spec.options ?? {} };
|
|
1314
1374
|
options["animation"] = false;
|
|
1315
1375
|
options["responsive"] = false;
|
|
1316
|
-
if (!isPlain(spec))
|
|
1376
|
+
if (!isPlain(spec))
|
|
1377
|
+
return { type: spec.type ?? "bar", data: spec.data ?? {}, options };
|
|
1317
1378
|
const data = chartDataFromPlain(spec);
|
|
1318
1379
|
const unnamed = data.datasets.length === 1 && data.datasets[0]?.["label"] === void 0;
|
|
1319
1380
|
const plugins = asObject(options["plugins"]);
|
|
@@ -1326,7 +1387,8 @@ function chartMarkup(spec, id) {
|
|
|
1326
1387
|
const height = toNumber(spec.height ?? 240) || 240;
|
|
1327
1388
|
const payload = escapeHtml(JSON.stringify(chartPayload(spec)));
|
|
1328
1389
|
const idAttr = id ? ` id="${escapeHtml(id)}"` : "";
|
|
1329
|
-
|
|
1390
|
+
const alt = typeof spec.alt === "string" && spec.alt.trim() ? ` role="img" aria-label="${escapeHtml(spec.alt.trim())}"` : "";
|
|
1391
|
+
return `<canvas class="ff-chart"${idAttr}${alt} width="${width}" height="${height}" style="width:${width}px;height:${height}px" data-ff-chart="${payload}"></canvas>`;
|
|
1330
1392
|
}
|
|
1331
1393
|
function imageMarkup(url, options = {}) {
|
|
1332
1394
|
const styles = [
|
|
@@ -1347,18 +1409,21 @@ var documentHelpers = [
|
|
|
1347
1409
|
name: "chart",
|
|
1348
1410
|
html: true,
|
|
1349
1411
|
doc: {
|
|
1350
|
-
signature: "chart({ type, labels, values, label, color } | { type, labels, series } | { type, data, options }, { width, height })",
|
|
1351
|
-
description: "Draws a Chart.js chart (bar, line, pie, doughnut, radar, \u2026) from plain data, `labels` with `values` or several `series` of `{ label, values, color }`, or from a full Chart.js `data` and `options`; animations are disabled so PDF and preview match.",
|
|
1412
|
+
signature: "chart({ type, labels, values, label, color } | { type, labels, series } | { type, data, options }, { width, height, alt })",
|
|
1413
|
+
description: "Draws a Chart.js chart (bar, line, pie, doughnut, radar, \u2026) from plain data, `labels` with `values` or several `series` of `{ label, values, color }`, or from a full Chart.js `data` and `options`; animations are disabled so PDF and preview match. `alt` says in words what the chart shows: a screen reader reads it in place of the picture, and a tagged PDF needs it.",
|
|
1352
1414
|
examples: {
|
|
1353
|
-
jinja2: "{{ chart({ type: 'line', labels: sales.labels, values: sales.quarters, width: 480 }) }}",
|
|
1354
|
-
liquid: "{{ '' | chart: type: 'line', labels: sales.labels, values: sales.quarters, width: 480 }}",
|
|
1355
|
-
handlebars: "{{chart type='line' labels=sales.labels values=sales.quarters width=480}}"
|
|
1415
|
+
jinja2: "{{ chart({ type: 'line', labels: sales.labels, values: sales.quarters, width: 480, alt: 'Sales by quarter' }) }}",
|
|
1416
|
+
liquid: "{{ '' | chart: type: 'line', labels: sales.labels, values: sales.quarters, width: 480, alt: 'Sales by quarter' }}",
|
|
1417
|
+
handlebars: "{{chart type='line' labels=sales.labels values=sales.quarters width=480 alt='Sales by quarter'}}"
|
|
1356
1418
|
},
|
|
1357
1419
|
category: "document"
|
|
1358
1420
|
},
|
|
1359
1421
|
fn: (ctx, spec, extra) => {
|
|
1360
1422
|
if (ctx.mode === "office") throw new Error(officeUnsupported("chart"));
|
|
1361
|
-
return chartMarkup({
|
|
1423
|
+
return chartMarkup({
|
|
1424
|
+
...asObject(spec),
|
|
1425
|
+
...asObject(extra)
|
|
1426
|
+
});
|
|
1362
1427
|
}
|
|
1363
1428
|
},
|
|
1364
1429
|
{
|
|
@@ -1366,18 +1431,24 @@ var documentHelpers = [
|
|
|
1366
1431
|
html: true,
|
|
1367
1432
|
doc: {
|
|
1368
1433
|
signature: "image(url, { width, height, fit, alt })",
|
|
1369
|
-
description: "Places an image with fixed size and crop mode (`cover`, `contain`, `fill`); the render-worker fetches it through its cache and blocks private hosts.",
|
|
1434
|
+
description: "Places an image with fixed size and crop mode (`cover`, `contain`, `fill`); the render-worker fetches it through its cache and blocks private hosts. `alt` says what it shows; without one the image counts as decoration and a screen reader passes over it.",
|
|
1370
1435
|
examples: {
|
|
1371
|
-
jinja2: "{{ image(product.photo, { width: 120, height: 80, fit: 'cover' }) }}",
|
|
1372
|
-
liquid: "{{ product.photo | image: width: 120, height: 80, fit: 'cover' }}",
|
|
1373
|
-
handlebars: "{{image product.photo width=120 height=80 fit='cover'}}"
|
|
1436
|
+
jinja2: "{{ image(product.photo, { width: 120, height: 80, fit: 'cover', alt: product.name }) }}",
|
|
1437
|
+
liquid: "{{ product.photo | image: width: 120, height: 80, fit: 'cover', alt: product.name }}",
|
|
1438
|
+
handlebars: "{{image product.photo width=120 height=80 fit='cover' alt=product.name}}"
|
|
1374
1439
|
},
|
|
1375
1440
|
category: "document"
|
|
1376
1441
|
},
|
|
1377
1442
|
fn: (ctx, url, options) => {
|
|
1378
1443
|
const o = asObject(options);
|
|
1379
1444
|
if (ctx.drawing)
|
|
1380
|
-
return ctx.drawing({
|
|
1445
|
+
return ctx.drawing({
|
|
1446
|
+
kind: "url",
|
|
1447
|
+
url: resolveAsset(ctx.assetBaseUrl, String(url ?? "")),
|
|
1448
|
+
width: o.width,
|
|
1449
|
+
height: o.height,
|
|
1450
|
+
alt: o.alt
|
|
1451
|
+
});
|
|
1381
1452
|
return imageMarkup(String(url ?? ""), o);
|
|
1382
1453
|
}
|
|
1383
1454
|
}
|
|
@@ -2117,8 +2188,8 @@ var SPEC = /^(?:([\s\S])?([<>=^]))?([+\- ])?(#)?(0)?(\d+)?([,_])?(?:\.(\d+))?([b
|
|
|
2117
2188
|
function group(digits, separator) {
|
|
2118
2189
|
return digits.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
|
|
2119
2190
|
}
|
|
2120
|
-
function pythonExponent(
|
|
2121
|
-
return
|
|
2191
|
+
function pythonExponent(text4) {
|
|
2192
|
+
return text4.replace(/e([+-])(\d)$/i, (m, sign, digit) => `${m[0]}${sign}0${digit}`);
|
|
2122
2193
|
}
|
|
2123
2194
|
function formatNumber(value, type, precision, alternate) {
|
|
2124
2195
|
if (!Number.isFinite(value)) return Number.isNaN(value) ? "nan" : "inf";
|
|
@@ -2131,20 +2202,20 @@ function formatNumber(value, type, precision, alternate) {
|
|
|
2131
2202
|
return `${(abs2 * 100).toFixed(precision ?? 6)}%`;
|
|
2132
2203
|
case "e":
|
|
2133
2204
|
case "E": {
|
|
2134
|
-
const
|
|
2135
|
-
return type === "E" ?
|
|
2205
|
+
const text4 = pythonExponent(abs2.toExponential(precision ?? 6));
|
|
2206
|
+
return type === "E" ? text4.toUpperCase() : text4;
|
|
2136
2207
|
}
|
|
2137
2208
|
case "g":
|
|
2138
2209
|
case "G": {
|
|
2139
2210
|
const p = precision === 0 ? 1 : precision ?? 6;
|
|
2140
2211
|
const exp = abs2 === 0 ? 0 : Math.floor(Math.log10(abs2));
|
|
2141
|
-
let
|
|
2212
|
+
let text4 = exp < -4 || exp >= p ? pythonExponent(abs2.toExponential(p - 1)) : abs2.toFixed(Math.max(0, p - 1 - exp));
|
|
2142
2213
|
if (!alternate) {
|
|
2143
|
-
const [mantissa = "", exponent] =
|
|
2214
|
+
const [mantissa = "", exponent] = text4.split("e");
|
|
2144
2215
|
const trimmed = mantissa.includes(".") ? mantissa.replace(/0+$/, "").replace(/\.$/, "") : mantissa;
|
|
2145
|
-
|
|
2216
|
+
text4 = exponent === void 0 ? trimmed : `${trimmed}e${exponent}`;
|
|
2146
2217
|
}
|
|
2147
|
-
return type === "G" ?
|
|
2218
|
+
return type === "G" ? text4.toUpperCase() : text4;
|
|
2148
2219
|
}
|
|
2149
2220
|
case "d":
|
|
2150
2221
|
case "n":
|
|
@@ -2213,35 +2284,35 @@ function lookupField(name, positional, named, next) {
|
|
|
2213
2284
|
function pythonFormat(template, positional, named = {}) {
|
|
2214
2285
|
let auto = 0;
|
|
2215
2286
|
const next = () => auto++;
|
|
2216
|
-
const render = (
|
|
2287
|
+
const render = (text4) => {
|
|
2217
2288
|
let out = "";
|
|
2218
|
-
for (let i = 0; i <
|
|
2219
|
-
const ch =
|
|
2289
|
+
for (let i = 0; i < text4.length; i++) {
|
|
2290
|
+
const ch = text4[i];
|
|
2220
2291
|
if (ch === "}") {
|
|
2221
2292
|
out += "}";
|
|
2222
|
-
if (
|
|
2293
|
+
if (text4[i + 1] === "}") i++;
|
|
2223
2294
|
continue;
|
|
2224
2295
|
}
|
|
2225
2296
|
if (ch !== "{") {
|
|
2226
2297
|
out += ch;
|
|
2227
2298
|
continue;
|
|
2228
2299
|
}
|
|
2229
|
-
if (
|
|
2300
|
+
if (text4[i + 1] === "{") {
|
|
2230
2301
|
out += "{";
|
|
2231
2302
|
i++;
|
|
2232
2303
|
continue;
|
|
2233
2304
|
}
|
|
2234
2305
|
let depth = 1;
|
|
2235
2306
|
let j = i + 1;
|
|
2236
|
-
for (; j <
|
|
2237
|
-
if (
|
|
2238
|
-
else if (
|
|
2307
|
+
for (; j < text4.length && depth > 0; j++) {
|
|
2308
|
+
if (text4[j] === "{") depth++;
|
|
2309
|
+
else if (text4[j] === "}") depth--;
|
|
2239
2310
|
}
|
|
2240
2311
|
if (depth > 0) {
|
|
2241
|
-
out +=
|
|
2312
|
+
out += text4.slice(i);
|
|
2242
2313
|
break;
|
|
2243
2314
|
}
|
|
2244
|
-
const field =
|
|
2315
|
+
const field = text4.slice(i + 1, j - 1);
|
|
2245
2316
|
const colon = field.indexOf(":");
|
|
2246
2317
|
const head = colon < 0 ? field : field.slice(0, colon);
|
|
2247
2318
|
const name = head.replace(/![rsa]$/, "");
|
|
@@ -4386,9 +4457,9 @@ function pick(input, ...keys) {
|
|
|
4386
4457
|
function toLength(value) {
|
|
4387
4458
|
if (value === void 0 || value === null || value === "") return void 0;
|
|
4388
4459
|
if (typeof value === "number") return `${value}mm`;
|
|
4389
|
-
const
|
|
4390
|
-
if (/^-?\d+(\.\d+)?$/.test(
|
|
4391
|
-
if (/^-?\d+(\.\d+)?(mm|cm|in|px|pt)$/i.test(
|
|
4460
|
+
const text4 = String(value).trim();
|
|
4461
|
+
if (/^-?\d+(\.\d+)?$/.test(text4)) return `${text4}mm`;
|
|
4462
|
+
if (/^-?\d+(\.\d+)?(mm|cm|in|px|pt)$/i.test(text4)) return text4.toLowerCase();
|
|
4392
4463
|
return void 0;
|
|
4393
4464
|
}
|
|
4394
4465
|
function toMarginLength(value) {
|
|
@@ -4408,7 +4479,7 @@ function convertHeaderFooter(html) {
|
|
|
4408
4479
|
if (typeof html !== "string" || !html.trim()) return void 0;
|
|
4409
4480
|
return chromePlaceholders.reduce((out, [pattern, span]) => out.replace(pattern, span), html);
|
|
4410
4481
|
}
|
|
4411
|
-
var escapeText = (
|
|
4482
|
+
var escapeText = (text4) => text4.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
4412
4483
|
var visibleMarkup = (html) => html.replace(/<style[\s\S]*?<\/style>/gi, "").trim();
|
|
4413
4484
|
function apitemplateChrome(take, kind) {
|
|
4414
4485
|
const custom = take(`custom_${kind}`);
|
|
@@ -4422,7 +4493,7 @@ function apitemplateChrome(take, kind) {
|
|
|
4422
4493
|
if (!slots.some(Boolean)) return { fromSlots: false };
|
|
4423
4494
|
const sizeText = size === void 0 ? "" : String(size).trim();
|
|
4424
4495
|
const fontSize2 = /^\d+(\.\d+)?$/.test(sizeText) ? `${sizeText}px` : /^\d+(\.\d+)?(px|pt|mm)$/.test(sizeText) ? sizeText : "9px";
|
|
4425
|
-
const cells = slots.map((
|
|
4496
|
+
const cells = slots.map((text4, i) => `<span style="flex:1;text-align:${["left", "center", "right"][i]}">${escapeText(text4)}</span>`).join("");
|
|
4426
4497
|
const styles = customHtml.match(/<style[\s\S]*?<\/style>/gi)?.join("") ?? "";
|
|
4427
4498
|
return {
|
|
4428
4499
|
html: convertHeaderFooter(`${styles}<div style="display:flex;gap:4mm;font-size:${fontSize2}">${cells}</div>`),
|
|
@@ -4583,9 +4654,9 @@ function checkTemplate(engineId, html, sampleData, name, docs) {
|
|
|
4583
4654
|
function lengthMm(value) {
|
|
4584
4655
|
if (value === void 0 || value === null || value === "") return void 0;
|
|
4585
4656
|
if (typeof value === "number" && Number.isFinite(value)) return `${value}mm`;
|
|
4586
|
-
const
|
|
4587
|
-
if (/^-?\d+(\.\d+)?$/.test(
|
|
4588
|
-
if (/^-?\d+(\.\d+)?(mm|cm|in|px|pt)$/i.test(
|
|
4657
|
+
const text4 = String(value).trim();
|
|
4658
|
+
if (/^-?\d+(\.\d+)?$/.test(text4)) return `${text4}mm`;
|
|
4659
|
+
if (/^-?\d+(\.\d+)?(mm|cm|in|px|pt)$/i.test(text4)) return text4.toLowerCase();
|
|
4589
4660
|
return void 0;
|
|
4590
4661
|
}
|
|
4591
4662
|
function toBase64(value) {
|
|
@@ -5102,11 +5173,11 @@ function inlineIncludes(source, blocks, errors, changes) {
|
|
|
5102
5173
|
}
|
|
5103
5174
|
var cssPaperFormats = { a3: "A3", a4: "A4", a5: "A5", letter: "Letter" };
|
|
5104
5175
|
var isoSizes = { a0: [841, 1189], a1: [594, 841], a2: [420, 594], a6: [105, 148] };
|
|
5105
|
-
var escapeHtml2 = (
|
|
5176
|
+
var escapeHtml2 = (text4) => text4.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
5106
5177
|
function simpleHeaderFooter(part, margin) {
|
|
5107
5178
|
const cells = ["left", "center", "right"].map((side) => part[side] ?? "");
|
|
5108
5179
|
if (!cells.some((c) => c.trim())) return void 0;
|
|
5109
|
-
const cell3 = (
|
|
5180
|
+
const cell3 = (text4, align) => `<div style="flex: 1; text-align: ${align}">${escapeHtml2(text4).replace(/\[page\]/g, '<span class="pageNumber"></span>').replace(/\[topage\]/g, '<span class="totalPages"></span>')}</div>`;
|
|
5110
5181
|
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>`;
|
|
5111
5182
|
}
|
|
5112
5183
|
function mapSettings(input, kind, warnings, changes) {
|
|
@@ -5275,11 +5346,11 @@ var DOCS3 = "/migrate/jsreport";
|
|
|
5275
5346
|
var COLLECTIONS = ["templates", "data", "assets", "components", "scripts", "folders"];
|
|
5276
5347
|
function readJsreportExport(files) {
|
|
5277
5348
|
const bundle = { templates: [], data: [], assets: [], components: [], scripts: [], folders: [] };
|
|
5278
|
-
for (const [path,
|
|
5349
|
+
for (const [path, text4] of Object.entries(files)) {
|
|
5279
5350
|
const normalized = path.replace(/\\/g, "/").replace(/^\.?\//, "");
|
|
5280
5351
|
if (normalized === "metadata.json") {
|
|
5281
5352
|
try {
|
|
5282
|
-
bundle.version = String(JSON.parse(
|
|
5353
|
+
bundle.version = String(JSON.parse(text4).reporterVersion ?? "");
|
|
5283
5354
|
} catch {
|
|
5284
5355
|
}
|
|
5285
5356
|
continue;
|
|
@@ -5287,7 +5358,7 @@ function readJsreportExport(files) {
|
|
|
5287
5358
|
const collection = normalized.split("/")[0];
|
|
5288
5359
|
if (!COLLECTIONS.includes(collection) || !normalized.endsWith(".json")) continue;
|
|
5289
5360
|
try {
|
|
5290
|
-
bundle[collection].push(JSON.parse(
|
|
5361
|
+
bundle[collection].push(JSON.parse(text4));
|
|
5291
5362
|
} catch {
|
|
5292
5363
|
}
|
|
5293
5364
|
}
|
|
@@ -5329,7 +5400,7 @@ function assetBase64(content) {
|
|
|
5329
5400
|
}
|
|
5330
5401
|
return toBase64(content);
|
|
5331
5402
|
}
|
|
5332
|
-
var escapeMustaches = (
|
|
5403
|
+
var escapeMustaches = (text4) => text4.replace(/\{\{/g, "\\{{");
|
|
5333
5404
|
function resolveAssets(source, bundle, options, warnings, changes) {
|
|
5334
5405
|
const v3 = /\{\{\{?\s*asset\s+(["'])([^"']+)\1(?:\s+(["'])([^"']+)\3)?\s*\}?\}\}/g;
|
|
5335
5406
|
const v2 = /\{#asset\s+([^\s}]+)(?:\s+@encoding=(\w+))?\s*\}/g;
|
|
@@ -5570,6 +5641,7 @@ function importJsreport(bundle, ref, options = {}) {
|
|
|
5570
5641
|
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);})();';
|
|
5571
5642
|
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);})();';
|
|
5572
5643
|
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);})();';
|
|
5644
|
+
var auditRuntime = '"use strict";(()=>{var I={"document-title":"error","image-alt":"error","figure-name":"error","heading-order":"error","table-rows":"error","table-cell-empty":"error","masked-text":"error","filtered-text":"warning","document-language":"warning","table-headers":"warning","link-name":"warning","generated-text":"warning","fixed-text":"warning","running-text":"warning"};var S=120;var O=".formfeed-chrome, .ff-running-header, .ff-running-footer",_=".pageNumber, .totalPages, .date, .title, .url, .ff-page-no, .ff-page-total",k=new Set(["script","style","template","noscript","head"]),j=2e4,q=10,B=new Set(["page","pages","of","seite","seiten","von","p","s"]),u=t=>(t??"").replace(/\\s+/g," ").trim(),D=t=>t.replace(/\\s+/g,"").toLowerCase(),$=t=>/[\\p{L}\\p{N}]/u.test(t),Y=/^data-(ref|id|split-(from|to|original)|(previous-|next-)?break-(before|after|inside)|(align-)?last-split-element|nth-of-type|counter-.+|page(-number)?|undisplayed|after-page|following|has-notes|children|item-num)$/;function X(t){let n=t.cloneNode(!1);n.removeAttribute("data-ff-src"),n.removeAttribute("data-ff-edit");let i=t.closest(".pagedjs_page")!==null;for(let s of Array.from(n.attributes))i&&Y.test(s.name)?n.removeAttribute(s.name):s.value.length>48&&n.setAttribute(s.name,`${s.value.slice(0,40)}\\u2026`);let o=n.outerHTML.replace(new RegExp(`</${t.tagName}>$`,"i"),"");return o.length>S?`${o.slice(0,S-1)}\\u2026`:o}function F(t,n={}){let i=t.document,o=i.body,s=[],d=new Set,a=n.findings!==!1,c=(e,r,l={})=>{if(!a)return;let m=r?.closest("[data-ff-src]")?.getAttribute("data-ff-src")??null,h=r?X(r):"",g=`${e}|${m??h}|${JSON.stringify(l)}`;d.has(g)||(d.add(g),s.push({code:e,severity:I[e],src:m,snippet:h,args:l}))},f=new WeakMap,A=e=>{let r=f.get(e);if(r!==void 0)return r;let l=t.getComputedStyle(e),m=l.display==="none"||l.visibility==="hidden"||l.visibility==="collapse"||e.parentElement!==null&&e.parentElement!==i.documentElement&&A(e.parentElement);return f.set(e,m),m},p=e=>e.closest(\'[aria-hidden="true"]\')!==null,E=e=>/^(presentation|none)$/.test(e.getAttribute("role")??""),H=e=>e.closest(O)!==null,y=e=>$(e.textContent??""),x=e=>{let r=u(e.getAttribute("aria-label"));return r||u((e.getAttribute("aria-labelledby")??"").split(/\\s+/).filter(Boolean).map(l=>e.ownerDocument.getElementById(l)?.textContent??"").join(" "))},P=e=>x(e)||u(e.textContent)||u(Array.from(e.querySelectorAll("img[alt]")).map(r=>r.getAttribute("alt")).join(" "))||u(e.getAttribute("title")),T=e=>{let r=e.getAttribute("href")??"";return{href:r.startsWith("#")?r:e.href??r,name:P(e)}};u(i.title)||c("document-title",null),!u(i.documentElement.getAttribute("lang"))&&!n.locale&&c("document-language",null);let M=n.pages??(n.pageHeight&&n.pageHeight>0?Math.ceil(i.documentElement.scrollHeight/n.pageHeight):1),C=[],v=[],R={"masked-text":[],"filtered-text":[],"fixed-text":[]},w=(e,r)=>{R[e].some(l=>l.contains(r))||(R[e].push(r),c(e,r))},V=a&&ne(i),G=o?Array.from(o.querySelectorAll("*")).slice(0,j):[];for(let e of G){let r=e.tagName.toLowerCase();if(k.has(r)||H(e)||A(e))continue;if(r==="a"&&e.hasAttribute("href")){let g=T(e);C.push(g),!g.name&&!p(e)&&c("link-name",e)}if(!a)continue;let l=t.getComputedStyle(e),m=l.getPropertyValue("mask-image")||l.getPropertyValue("-webkit-mask-image");if(m&&m!=="none"&&y(e)&&w("masked-text",e),l.filter&&l.filter!=="none"&&y(e)&&w("filtered-text",e),l.position==="fixed"&&M>1&&y(e)&&w("fixed-text",e),V)for(let g of["::before","::after"]){let U=re(t.getComputedStyle(e,g).content);U&&c("generated-text",e,{text:U})}if(p(e))continue;r==="img"&&!E(e)?e.hasAttribute("alt")||x(e)||u(e.getAttribute("title"))||c("image-alt",e):(r==="canvas"||e.getAttribute("role")==="img"&&r!=="img")&&(x(e)||u(e.getAttribute("title"))||u(e.querySelector(":scope > title")?.textContent)||c("figure-name",e,{tag:r}));let h=/^h[1-6]$/.test(r)?Number(r[1]):e.getAttribute("role")==="heading"?Number(e.getAttribute("aria-level"))||2:0;h&&v.push({element:e,level:h}),r==="table"&&!E(e)&&Q(e,c)}let b=0;for(let{element:e,level:r}of v)(b===0?r!==1:r>b+1)&&c("heading-order",e,{level:r,previous:b}),b=r;let N=[],W=a&&o?D(J(o)):"",L=0;for(let e of["header","footer"])for(let r of z(i,e,n[e])){for(let l of Array.from(r.querySelectorAll("a[href]")))N.push(T(l));if(a)for(let{text:l,element:m}of K(r)){if(L>=q||W.includes(D(l)))continue;let h=s.length;c("running-text",m,{text:l.slice(0,80),part:e}),s.length>h&&L++}}return{findings:s,links:C,templateLinks:N}}function z(t,n,i){if(i!==void 0){if(!i.trim())return[];let o=new DOMParser().parseFromString(`<!doctype html><body>${i}</body>`,"text/html");return o.body?[o.body]:[]}return Array.from(t.querySelectorAll(`.ff-running-${n}, .formfeed-chrome[data-ff-chrome="${n}"]`))}function J(t){let n=[],i=o=>{if(o.nodeType===3){n.push(o.nodeValue??"");return}if(o.nodeType!==1)return;let s=o;if(!(k.has(s.tagName.toLowerCase())||s.matches(O)))for(let d of Array.from(o.childNodes))i(d)};return i(t),n.join(" ")}function K(t){let n=[],i=o=>{let s=o.tagName.toLowerCase();if(k.has(s)||o.matches(_))return;let d=Array.from(o.children).some(a=>a.matches(_));for(let a of Array.from(o.childNodes))if(a.nodeType===1)i(a);else if(a.nodeType===3&&!d)for(let c of(a.nodeValue??"").split(/\\s*[\xB7\u2022|]\\s*|\\s{2,}|\\n/)){let f=u(c);(f.toLowerCase().match(/[\\p{L}\\p{N}]+/gu)??[]).some(p=>!B.has(p))&&n.push({text:f,element:o})}};return i(t),n}function Q(t,n){let i=Array.from(t.rows);if(!(t.querySelector(\'th, [role="columnheader"], [role="rowheader"]\')!==null)){i.length>=2&&n("table-headers",t);return}let s=te(i),d=s.find(c=>c!==s[0]);d!==void 0&&n("table-rows",t,{first:s[0]??0,other:d});let a=i.flatMap(c=>Array.from(c.cells).filter(f=>f.tagName==="TD"&&ee(f)));a[0]&&n("table-cell-empty",a[0],{count:a.length})}var Z=\'img[alt]:not([alt=""]), svg, canvas, input, select, textarea, button, meter, progress\';function ee(t){return!/[^ \\t\\n\\r\\f]/.test(t.textContent??"")&&t.querySelector(Z)===null}function te(t){let n=[];return t.map(i=>{let o=[],s=0,d=()=>{for(;(n[s]??0)>0;)o[s]=n[s]-1,s++};for(let a of Array.from(i.cells)){d();let c=Math.max(1,a.rowSpan||1)-1;for(let f=Math.max(1,a.colSpan||1);f>0;f--)o[s++]=c}d();for(let a=s;a<n.length;a++)(n[a]??0)>0&&(o[a]=n[a]-1,s=a+1);return n=o,s})}function ne(t){let n=i=>{for(let o of Array.from(i??[])){let s=o;if(s.selectorText&&/::?(before|after)/.test(s.selectorText)&&s.style?.content||o.cssRules&&n(o.cssRules))return!0}return!1};for(let i of Array.from(t.styleSheets))try{if(n(i.cssRules))return!0}catch{return!0}return!1}function re(t){if(!t||t==="none"||t==="normal")return"";let n=(t.match(/"(?:[^"\\\\]|\\\\.)*"/g)??[]).map(o=>o.slice(1,-1).replace(/\\\\(.)/g,"$1"));if(/\\bcounters?\\(/.test(t))return u(t).slice(0,80);let i=u(n.join(""));return $(i)?i.slice(0,80):""}window.formfeedAudit=t=>F(window,t);})();';
|
|
5573
5645
|
|
|
5574
5646
|
// packages/engine/src/lib/assemble.ts
|
|
5575
5647
|
var DEFAULT_CHROME_PADDING = "0 10mm";
|
|
@@ -5824,6 +5896,23 @@ document.addEventListener('click', function (event) {
|
|
|
5824
5896
|
}, true);
|
|
5825
5897
|
</script>`;
|
|
5826
5898
|
var textEditScript = `<script>${textEditRuntime.replace(/<\/script/gi, "<\\/script")}</script>`;
|
|
5899
|
+
function auditScript(mode) {
|
|
5900
|
+
return `<script>${auditRuntime.replace(/<\/script/gi, "<\\/script")}</script><script>
|
|
5901
|
+
(function () {
|
|
5902
|
+
window.formfeedRunAudit = function (pages) {
|
|
5903
|
+
try {
|
|
5904
|
+
var report = window.formfeedAudit({
|
|
5905
|
+
locale: true,
|
|
5906
|
+
pages: pages,
|
|
5907
|
+
pageHeight: parseFloat(getComputedStyle(document.body).minHeight) || 0,
|
|
5908
|
+
});
|
|
5909
|
+
parent.postMessage({ type: 'formfeed:audit', findings: report.findings }, '*');
|
|
5910
|
+
} catch (e) {}
|
|
5911
|
+
};
|
|
5912
|
+
${mode === "flow" ? "window.addEventListener('load', function () { (document.fonts ? document.fonts.ready : Promise.resolve()).then(function () { window.formfeedRunAudit(); }); });" : ""}
|
|
5913
|
+
})();
|
|
5914
|
+
</script>`;
|
|
5915
|
+
}
|
|
5827
5916
|
function documentMeta(options) {
|
|
5828
5917
|
const name = (options.document ?? "").replace(/[^A-Za-z0-9_-]/g, "");
|
|
5829
5918
|
return name ? `<meta name="formfeed:document" content="${name}">` : "";
|
|
@@ -5935,6 +6024,15 @@ function intoHead(document, markup) {
|
|
|
5935
6024
|
${markup}`
|
|
5936
6025
|
);
|
|
5937
6026
|
}
|
|
6027
|
+
function intoBody(document, atStart, atEnd = "") {
|
|
6028
|
+
const own = document.indexOf('<body class="formfeed-body');
|
|
6029
|
+
const open2 = own >= 0 ? own : document.search(/<body[^>]*>/);
|
|
6030
|
+
if (open2 < 0) return document;
|
|
6031
|
+
const content = document.indexOf(">", open2) + 1;
|
|
6032
|
+
const close = document.lastIndexOf("</body>");
|
|
6033
|
+
const end = close >= content ? close : document.length;
|
|
6034
|
+
return `${document.slice(0, content)}${atStart}${document.slice(content, end)}${atEnd}${document.slice(end)}`;
|
|
6035
|
+
}
|
|
5938
6036
|
function chromeBoxStyle(settings, which) {
|
|
5939
6037
|
const margin = settings.margin ?? {};
|
|
5940
6038
|
const left = margin.left ?? "0px";
|
|
@@ -5958,12 +6056,16 @@ html { background: #e5e7eb; }
|
|
|
5958
6056
|
body.formfeed-preview { position: relative; box-sizing: border-box; width: ${paper.width}; min-height: ${paper.height}; margin: 24px auto; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.2), 0 8px 24px rgba(0,0,0,.08); padding: ${margin.top ?? "0"} ${margin.right ?? "0"} ${margin.bottom ?? "0"} ${margin.left ?? "0"}; }
|
|
5959
6057
|
.formfeed-chrome { color: #6b7280; font: 10px/1.3 system-ui, sans-serif; }
|
|
5960
6058
|
</style>` : `<style data-formfeed="preview">html { background: #e5e7eb; } body.formfeed-preview { margin: 24px auto; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.2); }</style>`;
|
|
5961
|
-
const header = headerHtml ? `<div class="formfeed-chrome" style="${pdf ? flowChromeStyle(settings, "header") : `${chromeBoxStyle(settings, "header")}margin-bottom:8px`}">${headerHtml}</div>` : "";
|
|
5962
|
-
const footer = footerHtml ? `<div class="formfeed-chrome" style="${pdf ? flowChromeStyle(settings, "footer") : `${chromeBoxStyle(settings, "footer")}margin-top:8px`}">${pageNumberSpans(footerHtml, "1", "1")}</div>` : "";
|
|
5963
|
-
return
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
6059
|
+
const header = headerHtml ? `<div class="formfeed-chrome" data-ff-chrome="header" style="${pdf ? flowChromeStyle(settings, "header") : `${chromeBoxStyle(settings, "header")}margin-bottom:8px`}">${headerHtml}</div>` : "";
|
|
6060
|
+
const footer = footerHtml ? `<div class="formfeed-chrome" data-ff-chrome="footer" style="${pdf ? flowChromeStyle(settings, "footer") : `${chromeBoxStyle(settings, "footer")}margin-top:8px`}">${pageNumberSpans(footerHtml, "1", "1")}</div>` : "";
|
|
6061
|
+
return intoBody(
|
|
6062
|
+
intoHead(
|
|
6063
|
+
draft.document,
|
|
6064
|
+
`${documentMeta(options)}${chrome}${options.editing ? textEditScript : ""}${inspectScript}${zoomGestureScript}${pdf ? overflowScript("flow") : ""}${pdf && options.audit ? auditScript("flow") : ""}`
|
|
6065
|
+
),
|
|
6066
|
+
header,
|
|
6067
|
+
footer
|
|
6068
|
+
);
|
|
5967
6069
|
}
|
|
5968
6070
|
function canvasDocument(draft) {
|
|
5969
6071
|
const chrome = `<style data-formfeed="stage">html, body { background: transparent !important; margin: 0 !important; }</style>`;
|
|
@@ -5990,14 +6092,17 @@ html { background: #e5e7eb; }
|
|
|
5990
6092
|
`;
|
|
5991
6093
|
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>`;
|
|
5992
6094
|
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>`;
|
|
5993
|
-
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>`;
|
|
6095
|
+
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(); if (window.formfeedRunAudit) window.formfeedRunAudit(flow.total); try { if (window.formfeedEditReady) window.formfeedEditReady(); } catch (e) {} } };</script>`;
|
|
5994
6096
|
const script = `<script src="${options.pagedScriptUrl}"></script>`;
|
|
5995
6097
|
const header = headerHtml ? `<div class="ff-running-header">${pageNumberSpans(headerHtml, '<span class="ff-page-no"></span>', '<span class="ff-page-total"></span>')}</div>` : "";
|
|
5996
6098
|
const footer = footerHtml ? `<div class="ff-running-footer">${pageNumberSpans(footerHtml, '<span class="ff-page-no"></span>', '<span class="ff-page-total"></span>')}</div>` : "";
|
|
5997
|
-
return
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6099
|
+
return intoBody(
|
|
6100
|
+
intoHead(
|
|
6101
|
+
draft.document,
|
|
6102
|
+
`${documentMeta(options)}<style data-formfeed="paged">${runningCss}</style>${selectorGuard}${boxSizingGuard}${overflowScript("paged")}${options.audit ? auditScript("paged") : ""}${config}${script}${options.editing ? textEditScript : ""}${inspectScript}${pageNavScript}${zoomGestureScript}`
|
|
6103
|
+
),
|
|
6104
|
+
`${header}${footer}`
|
|
6105
|
+
);
|
|
6001
6106
|
}
|
|
6002
6107
|
|
|
6003
6108
|
// packages/engine/src/lib/source-scan.ts
|
|
@@ -6487,18 +6592,18 @@ function applyRegionEdit(source, engine, region, items) {
|
|
|
6487
6592
|
const rewritten = source.slice(0, region.start) + whole + source.slice(region.end);
|
|
6488
6593
|
return readsBack(rewritten, engine, region.tagStart, expected) ? { source: rewritten } : { error: "invalid" };
|
|
6489
6594
|
}
|
|
6490
|
-
function translationItems(
|
|
6595
|
+
function translationItems(text4) {
|
|
6491
6596
|
const items = [];
|
|
6492
6597
|
const names = [];
|
|
6493
6598
|
let last = 0;
|
|
6494
|
-
for (const match of
|
|
6599
|
+
for (const match of text4.matchAll(/\{(\w+)\}/g)) {
|
|
6495
6600
|
if (match.index > last)
|
|
6496
|
-
items.push({ kind: "text", text:
|
|
6601
|
+
items.push({ kind: "text", text: text4.slice(last, match.index) });
|
|
6497
6602
|
items.push({ kind: "chip", index: names.length });
|
|
6498
6603
|
names.push(match[1] ?? "");
|
|
6499
6604
|
last = match.index + match[0].length;
|
|
6500
6605
|
}
|
|
6501
|
-
if (last <
|
|
6606
|
+
if (last < text4.length) items.push({ kind: "text", text: text4.slice(last) });
|
|
6502
6607
|
return { items, names };
|
|
6503
6608
|
}
|
|
6504
6609
|
function translationText(items, names) {
|
|
@@ -6742,9 +6847,9 @@ function translationCall(engine, inner) {
|
|
|
6742
6847
|
);
|
|
6743
6848
|
return match ? { key: match[2] ?? "", params: parseParams(match[3] ?? "", "=", " ") } : null;
|
|
6744
6849
|
}
|
|
6745
|
-
function parseParams(
|
|
6850
|
+
function parseParams(text4, assign, separator) {
|
|
6746
6851
|
const params = {};
|
|
6747
|
-
for (const piece of splitTopLevel(
|
|
6852
|
+
for (const piece of splitTopLevel(text4, separator)) {
|
|
6748
6853
|
const at = piece.indexOf(assign);
|
|
6749
6854
|
if (at <= 0) continue;
|
|
6750
6855
|
const name = piece.slice(0, at).trim().replace(/^['"]|['"]$/g, "");
|
|
@@ -6752,12 +6857,12 @@ function parseParams(text3, assign, separator) {
|
|
|
6752
6857
|
}
|
|
6753
6858
|
return params;
|
|
6754
6859
|
}
|
|
6755
|
-
function splitTopLevel(
|
|
6860
|
+
function splitTopLevel(text4, separator) {
|
|
6756
6861
|
const pieces = [];
|
|
6757
6862
|
let depth = 0;
|
|
6758
6863
|
let quote2 = null;
|
|
6759
6864
|
let current = "";
|
|
6760
|
-
for (const ch of
|
|
6865
|
+
for (const ch of text4) {
|
|
6761
6866
|
if (quote2) {
|
|
6762
6867
|
if (ch === quote2) quote2 = null;
|
|
6763
6868
|
} else if (ch === '"' || ch === "'") quote2 = ch;
|
|
@@ -6782,7 +6887,7 @@ function entityChar(reference) {
|
|
|
6782
6887
|
return code === void 0 ? null : String.fromCharCode(code);
|
|
6783
6888
|
}
|
|
6784
6889
|
function decodeText2(raw) {
|
|
6785
|
-
let
|
|
6890
|
+
let text4 = "";
|
|
6786
6891
|
const map = [];
|
|
6787
6892
|
let i = 0;
|
|
6788
6893
|
while (i < raw.length) {
|
|
@@ -6792,23 +6897,23 @@ function decodeText2(raw) {
|
|
|
6792
6897
|
const decoded = match ? entityChar(match[1] ?? "") : null;
|
|
6793
6898
|
if (match && decoded !== null) {
|
|
6794
6899
|
for (let u = 0; u < decoded.length; u++) map.push(i);
|
|
6795
|
-
|
|
6900
|
+
text4 += decoded;
|
|
6796
6901
|
i += match[0].length;
|
|
6797
6902
|
continue;
|
|
6798
6903
|
}
|
|
6799
6904
|
}
|
|
6800
|
-
|
|
6905
|
+
text4 += raw[i];
|
|
6801
6906
|
map.push(i);
|
|
6802
6907
|
i++;
|
|
6803
6908
|
}
|
|
6804
6909
|
map.push(raw.length);
|
|
6805
|
-
return { text:
|
|
6910
|
+
return { text: text4, map };
|
|
6806
6911
|
}
|
|
6807
|
-
function encodeText(
|
|
6912
|
+
function encodeText(text4, keepNbsp, allBraces = false) {
|
|
6808
6913
|
let out = "";
|
|
6809
|
-
for (let k = 0; k <
|
|
6810
|
-
const ch =
|
|
6811
|
-
const next =
|
|
6914
|
+
for (let k = 0; k < text4.length; k++) {
|
|
6915
|
+
const ch = text4[k] ?? "";
|
|
6916
|
+
const next = text4[k + 1];
|
|
6812
6917
|
if (ch === "&") out += "&";
|
|
6813
6918
|
else if (ch === "<") out += "<";
|
|
6814
6919
|
else if (ch === ">") out += ">";
|
|
@@ -6820,8 +6925,8 @@ function encodeText(text3, keepNbsp, allBraces = false) {
|
|
|
6820
6925
|
}
|
|
6821
6926
|
return out;
|
|
6822
6927
|
}
|
|
6823
|
-
function encodeTemplateText(
|
|
6824
|
-
return encodeText(
|
|
6928
|
+
function encodeTemplateText(text4) {
|
|
6929
|
+
return encodeText(text4, true);
|
|
6825
6930
|
}
|
|
6826
6931
|
function spanOf(part) {
|
|
6827
6932
|
return part ? [part.start, part.end] : [0, 0];
|
|
@@ -6855,7 +6960,7 @@ function rewriteSegment(source, segStart, segEnd, parts, next, breakSpelling) {
|
|
|
6855
6960
|
const to = map[old.length - suffix] ?? segEnd;
|
|
6856
6961
|
const middle = next.slice(prefix, next.length - suffix);
|
|
6857
6962
|
const keepNbsp = old.slice(prefix, old.length - suffix).includes(NBSP);
|
|
6858
|
-
const written = middle.split(BREAK).map((
|
|
6963
|
+
const written = middle.split(BREAK).map((text4) => encodeText(text4, keepNbsp)).join(breakSpelling);
|
|
6859
6964
|
return source.slice(segStart, from) + written + source.slice(to, segEnd);
|
|
6860
6965
|
}
|
|
6861
6966
|
var isHighSurrogate = (code) => code >= 55296 && code <= 56319;
|
|
@@ -7610,11 +7715,11 @@ function googleFontsUrl(uses) {
|
|
|
7610
7715
|
|
|
7611
7716
|
// packages/engine/src/lib/design/hash.ts
|
|
7612
7717
|
function designOutputHash(html, css2) {
|
|
7613
|
-
const
|
|
7718
|
+
const text4 = `${html}\0${css2}`;
|
|
7614
7719
|
let a = 2166136261;
|
|
7615
7720
|
let b = 16777619 ^ 2654435769;
|
|
7616
|
-
for (let i = 0; i <
|
|
7617
|
-
const code =
|
|
7721
|
+
for (let i = 0; i < text4.length; i++) {
|
|
7722
|
+
const code = text4.charCodeAt(i);
|
|
7618
7723
|
if (code === 13) continue;
|
|
7619
7724
|
a = Math.imul(a ^ code, 16777619) >>> 0;
|
|
7620
7725
|
b = Math.imul(b ^ code, 16777619) >>> 0;
|
|
@@ -7841,32 +7946,32 @@ function imageSource(source, engine) {
|
|
|
7841
7946
|
return `{{ brand.logo.${source.brandLogo} }}`;
|
|
7842
7947
|
}
|
|
7843
7948
|
function layerCss(layer) {
|
|
7844
|
-
const
|
|
7949
|
+
const text4 = layer.type === "text" ? layer : null;
|
|
7845
7950
|
const box = {
|
|
7846
7951
|
left: px(layer.x),
|
|
7847
7952
|
top: px(layer.y),
|
|
7848
7953
|
width: px(layer.width),
|
|
7849
|
-
height:
|
|
7954
|
+
height: text4?.sizing === "grow" ? void 0 : px(layer.height),
|
|
7850
7955
|
opacity: layer.opacity < 1 ? num(layer.opacity) : void 0,
|
|
7851
7956
|
transform: layer.rotation ? `rotate(${num(layer.rotation)}deg)` : void 0,
|
|
7852
7957
|
"border-radius": layer.type === "shape" && layer.shape === "ellipse" ? "50%" : layer.radius ? px(layer.radius) : void 0,
|
|
7853
7958
|
border: layer.stroke && layer.stroke.width > 0 ? `${px(layer.stroke.width)} solid ${paint(layer.stroke.paint)}` : void 0,
|
|
7854
|
-
"box-shadow": layer.shadow && !
|
|
7959
|
+
"box-shadow": layer.shadow && !text4 ? shadow(layer.shadow) : void 0
|
|
7855
7960
|
};
|
|
7856
|
-
if (
|
|
7961
|
+
if (text4) {
|
|
7857
7962
|
Object.assign(box, {
|
|
7858
7963
|
display: "flex",
|
|
7859
7964
|
"flex-direction": "column",
|
|
7860
|
-
"justify-content":
|
|
7861
|
-
overflow:
|
|
7862
|
-
padding:
|
|
7863
|
-
background:
|
|
7965
|
+
"justify-content": text4.valign === "middle" ? "center" : text4.valign === "bottom" ? "flex-end" : "flex-start",
|
|
7966
|
+
overflow: text4.sizing === "grow" ? void 0 : "hidden",
|
|
7967
|
+
padding: text4.padding ? px(text4.padding) : void 0,
|
|
7968
|
+
background: text4.fill ? paint(text4.fill) : void 0
|
|
7864
7969
|
});
|
|
7865
|
-
const s =
|
|
7866
|
-
const clamp =
|
|
7970
|
+
const s = text4.style;
|
|
7971
|
+
const clamp = text4.maxLines ? {
|
|
7867
7972
|
display: "-webkit-box",
|
|
7868
7973
|
"-webkit-box-orient": "vertical",
|
|
7869
|
-
"-webkit-line-clamp": String(
|
|
7974
|
+
"-webkit-line-clamp": String(text4.maxLines),
|
|
7870
7975
|
overflow: "hidden"
|
|
7871
7976
|
} : {};
|
|
7872
7977
|
const inner = decl({
|
|
@@ -7882,7 +7987,7 @@ function layerCss(layer) {
|
|
|
7882
7987
|
"font-style": s.italic ? "italic" : void 0,
|
|
7883
7988
|
"text-transform": s.uppercase ? "uppercase" : void 0,
|
|
7884
7989
|
"text-decoration": [s.underline && "underline", s.strike && "line-through"].filter(Boolean).join(" ") || void 0,
|
|
7885
|
-
"text-shadow":
|
|
7990
|
+
"text-shadow": text4.shadow ? shadow(text4.shadow) : void 0,
|
|
7886
7991
|
"overflow-wrap": "break-word",
|
|
7887
7992
|
...clamp
|
|
7888
7993
|
});
|
|
@@ -8246,24 +8351,24 @@ var paymentMeansCodes = list2(
|
|
|
8246
8351
|
// packages/engine/src/lib/einvoice/decimal.ts
|
|
8247
8352
|
function decimalText(value) {
|
|
8248
8353
|
if (typeof value === "string") {
|
|
8249
|
-
const
|
|
8250
|
-
return /^-?\d+(\.\d+)?$/.test(
|
|
8354
|
+
const text5 = value.trim();
|
|
8355
|
+
return /^-?\d+(\.\d+)?$/.test(text5) ? trimZeros(text5) : null;
|
|
8251
8356
|
}
|
|
8252
8357
|
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
|
8253
|
-
const
|
|
8254
|
-
return /^-?\d+(\.\d+)?$/.test(
|
|
8358
|
+
const text4 = value.toPrecision(15);
|
|
8359
|
+
return /^-?\d+(\.\d+)?$/.test(text4) ? trimZeros(text4) : null;
|
|
8255
8360
|
}
|
|
8256
|
-
function trimZeros(
|
|
8257
|
-
const trimmed =
|
|
8361
|
+
function trimZeros(text4) {
|
|
8362
|
+
const trimmed = text4.includes(".") ? text4.replace(/0+$/, "").replace(/\.$/, "") : text4;
|
|
8258
8363
|
return trimmed === "-0" ? "0" : trimmed;
|
|
8259
8364
|
}
|
|
8260
|
-
function decimalPlaces(
|
|
8261
|
-
const dot =
|
|
8262
|
-
return dot === -1 ? 0 :
|
|
8365
|
+
function decimalPlaces(text4) {
|
|
8366
|
+
const dot = text4.indexOf(".");
|
|
8367
|
+
return dot === -1 ? 0 : text4.length - dot - 1;
|
|
8263
8368
|
}
|
|
8264
|
-
function toUnits(
|
|
8265
|
-
const negative =
|
|
8266
|
-
const [whole = "0", fraction = ""] = (negative ?
|
|
8369
|
+
function toUnits(text4, scale) {
|
|
8370
|
+
const negative = text4.startsWith("-");
|
|
8371
|
+
const [whole = "0", fraction = ""] = (negative ? text4.slice(1) : text4).split(
|
|
8267
8372
|
"."
|
|
8268
8373
|
);
|
|
8269
8374
|
const units = BigInt(whole + fraction.padEnd(scale, "0").slice(0, scale));
|
|
@@ -8274,13 +8379,13 @@ function fromUnits(units, scale, places = scale) {
|
|
|
8274
8379
|
const digits = (negative ? -units : units).toString().padStart(scale + 1, "0");
|
|
8275
8380
|
const whole = digits.slice(0, digits.length - scale);
|
|
8276
8381
|
const fraction = digits.slice(digits.length - scale).padEnd(places, "0");
|
|
8277
|
-
const
|
|
8278
|
-
return negative && /[1-9]/.test(
|
|
8382
|
+
const text4 = places > 0 ? `${whole}.${fraction.slice(0, places)}` : whole;
|
|
8383
|
+
return negative && /[1-9]/.test(text4) ? `-${text4}` : text4;
|
|
8279
8384
|
}
|
|
8280
|
-
function withPlaces(
|
|
8281
|
-
const places = decimalPlaces(
|
|
8282
|
-
if (places >= min) return
|
|
8283
|
-
return places === 0 ? `${
|
|
8385
|
+
function withPlaces(text4, min) {
|
|
8386
|
+
const places = decimalPlaces(text4);
|
|
8387
|
+
if (places >= min) return text4;
|
|
8388
|
+
return places === 0 ? `${text4}.${"0".repeat(min)}` : text4 + "0".repeat(min - places);
|
|
8284
8389
|
}
|
|
8285
8390
|
function divideRounded(value, divisor) {
|
|
8286
8391
|
const negative = value < 0n !== divisor < 0n;
|
|
@@ -8702,37 +8807,37 @@ function valueAt(data, path) {
|
|
|
8702
8807
|
}
|
|
8703
8808
|
function normalise(input, add2, options) {
|
|
8704
8809
|
const amount2 = (value, path) => {
|
|
8705
|
-
const
|
|
8706
|
-
if (
|
|
8810
|
+
const text4 = decimalText(value);
|
|
8811
|
+
if (text4 === null) {
|
|
8707
8812
|
add2("not_a_number", path, `_invoice.${path} is not a number`);
|
|
8708
8813
|
return "0";
|
|
8709
8814
|
}
|
|
8710
|
-
if (decimalPlaces(
|
|
8815
|
+
if (decimalPlaces(text4) > 2) {
|
|
8711
8816
|
add2(
|
|
8712
8817
|
"decimals",
|
|
8713
8818
|
path,
|
|
8714
8819
|
`_invoice.${path} has more than 2 decimals; an amount of the invoice is exact to the cent`,
|
|
8715
8820
|
{
|
|
8716
|
-
args: { max: 2, value:
|
|
8821
|
+
args: { max: 2, value: text4 }
|
|
8717
8822
|
}
|
|
8718
8823
|
);
|
|
8719
8824
|
return "0";
|
|
8720
8825
|
}
|
|
8721
|
-
return
|
|
8826
|
+
return text4;
|
|
8722
8827
|
};
|
|
8723
8828
|
const number = (value, path, max2) => {
|
|
8724
|
-
const
|
|
8725
|
-
if (
|
|
8829
|
+
const text4 = decimalText(value);
|
|
8830
|
+
if (text4 === null) {
|
|
8726
8831
|
add2("not_a_number", path, `_invoice.${path} is not a number`);
|
|
8727
8832
|
return "0";
|
|
8728
8833
|
}
|
|
8729
|
-
if (decimalPlaces(
|
|
8834
|
+
if (decimalPlaces(text4) > max2) {
|
|
8730
8835
|
add2("decimals", path, `_invoice.${path} has more than ${max2} decimals`, {
|
|
8731
|
-
args: { max: max2, value:
|
|
8836
|
+
args: { max: max2, value: text4 }
|
|
8732
8837
|
});
|
|
8733
8838
|
return "0";
|
|
8734
8839
|
}
|
|
8735
|
-
return
|
|
8840
|
+
return text4;
|
|
8736
8841
|
};
|
|
8737
8842
|
const optionalAmount = (value, path) => value === void 0 ? void 0 : amount2(value, path);
|
|
8738
8843
|
const date2 = (value, path) => {
|
|
@@ -9110,7 +9215,7 @@ function defined(value) {
|
|
|
9110
9215
|
Object.entries(value).filter(([, v]) => v !== void 0)
|
|
9111
9216
|
);
|
|
9112
9217
|
}
|
|
9113
|
-
var cents = (
|
|
9218
|
+
var cents = (text4) => text4 === void 0 ? 0n : toUnits(text4, 2);
|
|
9114
9219
|
var money = (value) => fromUnits(value, 2);
|
|
9115
9220
|
var rateKey = (tax) => `${tax.category}|${tax.rate ?? ""}`;
|
|
9116
9221
|
function rules(invoice, add2) {
|
|
@@ -9570,14 +9675,14 @@ var CII_GUIDELINES = {
|
|
|
9570
9675
|
en16931: "urn:cen.eu:en16931:2017"
|
|
9571
9676
|
};
|
|
9572
9677
|
var EINVOICE_XML_NAME = "factur-x.xml";
|
|
9573
|
-
function leaf(name,
|
|
9574
|
-
if (
|
|
9678
|
+
function leaf(name, text4, attributes) {
|
|
9679
|
+
if (text4 === void 0 || text4 === "") return void 0;
|
|
9575
9680
|
const kept = Object.entries(attributes ?? {}).filter(
|
|
9576
9681
|
(entry) => entry[1] !== void 0
|
|
9577
9682
|
);
|
|
9578
9683
|
return {
|
|
9579
9684
|
name,
|
|
9580
|
-
text:
|
|
9685
|
+
text: text4,
|
|
9581
9686
|
...kept.length > 0 ? { attributes: Object.fromEntries(kept) } : {}
|
|
9582
9687
|
};
|
|
9583
9688
|
}
|
|
@@ -9834,14 +9939,14 @@ function invoiceToCii(invoice, options) {
|
|
|
9834
9939
|
${serialise(root, 0)}`;
|
|
9835
9940
|
}
|
|
9836
9941
|
var xmlCharacter = (code) => code === 9 || code === 10 || code === 13 || code >= 32 && !(code >= 55296 && code <= 57343) && code !== 65534 && code !== 65535;
|
|
9837
|
-
function carried(
|
|
9942
|
+
function carried(text4) {
|
|
9838
9943
|
let out = "";
|
|
9839
|
-
for (const character of
|
|
9944
|
+
for (const character of text4)
|
|
9840
9945
|
if (xmlCharacter(character.codePointAt(0) ?? 0)) out += character;
|
|
9841
9946
|
return out;
|
|
9842
9947
|
}
|
|
9843
|
-
var escapeText2 = (
|
|
9844
|
-
var escapeAttribute2 = (
|
|
9948
|
+
var escapeText2 = (text4) => carried(text4).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
9949
|
+
var escapeAttribute2 = (text4) => escapeText2(text4).replace(/"/g, """);
|
|
9845
9950
|
function serialise(element, depth) {
|
|
9846
9951
|
const indent = " ".repeat(depth);
|
|
9847
9952
|
const attributes = Object.entries(element.attributes ?? {}).map(([name, value]) => ` ${name}="${escapeAttribute2(value)}"`).join("");
|
|
@@ -9875,7 +9980,7 @@ var DASHES = /* @__PURE__ */ new Set([45, 8208, 8209, 8210, 8211, 8722]);
|
|
|
9875
9980
|
var INVISIBLE = /* @__PURE__ */ new Set([173, 8203, 8204, 8205, 8288, 65279]);
|
|
9876
9981
|
var isDigit = (code) => code >= DIGIT_0 && code <= DIGIT_9;
|
|
9877
9982
|
var MAX_GROUPS = 6;
|
|
9878
|
-
function shownAmounts(
|
|
9983
|
+
function shownAmounts(text4) {
|
|
9879
9984
|
const found = /* @__PURE__ */ new Set();
|
|
9880
9985
|
let run2 = "";
|
|
9881
9986
|
const flush = () => {
|
|
@@ -9899,7 +10004,7 @@ function shownAmounts(text3) {
|
|
|
9899
10004
|
}
|
|
9900
10005
|
}
|
|
9901
10006
|
};
|
|
9902
|
-
for (const character of
|
|
10007
|
+
for (const character of text4) {
|
|
9903
10008
|
const code = character.codePointAt(0) ?? 0;
|
|
9904
10009
|
if (INVISIBLE.has(code)) continue;
|
|
9905
10010
|
if (isDigit(code)) run2 += character;
|
|
@@ -9939,9 +10044,9 @@ function toCents(whole, fraction) {
|
|
|
9939
10044
|
if (whole.length > 18 || /[1-9]/.test(fraction.slice(2))) return null;
|
|
9940
10045
|
return BigInt(whole) * 100n + BigInt((fraction + "00").slice(0, 2));
|
|
9941
10046
|
}
|
|
9942
|
-
function squeeze(
|
|
10047
|
+
function squeeze(text4) {
|
|
9943
10048
|
let out = "";
|
|
9944
|
-
for (const character of
|
|
10049
|
+
for (const character of text4) {
|
|
9945
10050
|
const code = character.codePointAt(0) ?? 0;
|
|
9946
10051
|
if (INVISIBLE.has(code) || /\s/.test(character) || SPACES.has(code))
|
|
9947
10052
|
continue;
|
|
@@ -9949,8 +10054,8 @@ function squeeze(text3) {
|
|
|
9949
10054
|
}
|
|
9950
10055
|
return out;
|
|
9951
10056
|
}
|
|
9952
|
-
function displayCheck(
|
|
9953
|
-
const whole = typeof
|
|
10057
|
+
function displayCheck(text4, invoice) {
|
|
10058
|
+
const whole = typeof text4 === "string" ? text4 : text4.join("\n");
|
|
9954
10059
|
const amounts = shownAmounts(whole);
|
|
9955
10060
|
const squeezed = squeeze(whole);
|
|
9956
10061
|
const values = [];
|
|
@@ -10016,97 +10121,97 @@ function invoicePathSegments(path) {
|
|
|
10016
10121
|
}
|
|
10017
10122
|
return segments;
|
|
10018
10123
|
}
|
|
10019
|
-
function locateJsonPath(
|
|
10020
|
-
let offset = skipSpace(
|
|
10021
|
-
if (offset >=
|
|
10124
|
+
function locateJsonPath(text4, path) {
|
|
10125
|
+
let offset = skipSpace(text4, 0);
|
|
10126
|
+
if (offset >= text4.length) return null;
|
|
10022
10127
|
let best = { offset, depth: 0 };
|
|
10023
10128
|
try {
|
|
10024
10129
|
for (let depth = 0; depth < path.length; depth += 1) {
|
|
10025
10130
|
const segment = path[depth];
|
|
10026
|
-
const found = typeof segment === "number" ? arrayItem(
|
|
10131
|
+
const found = typeof segment === "number" ? arrayItem(text4, offset, segment) : objectMember(text4, offset, String(segment));
|
|
10027
10132
|
if (!found) break;
|
|
10028
10133
|
best = { offset: found.at, depth: depth + 1 };
|
|
10029
10134
|
offset = found.value;
|
|
10030
10135
|
}
|
|
10031
10136
|
} catch {
|
|
10032
10137
|
}
|
|
10033
|
-
return { ...positionAt(
|
|
10138
|
+
return { ...positionAt(text4, best.offset), depth: best.depth };
|
|
10034
10139
|
}
|
|
10035
|
-
function positionAt(
|
|
10140
|
+
function positionAt(text4, offset) {
|
|
10036
10141
|
let line2 = 1;
|
|
10037
10142
|
let lineStart = 0;
|
|
10038
10143
|
for (let i = 0; i < offset; i += 1)
|
|
10039
|
-
if (
|
|
10144
|
+
if (text4.charCodeAt(i) === 10) {
|
|
10040
10145
|
line2 += 1;
|
|
10041
10146
|
lineStart = i + 1;
|
|
10042
10147
|
}
|
|
10043
10148
|
return { line: line2, column: offset - lineStart + 1 };
|
|
10044
10149
|
}
|
|
10045
|
-
function skipSpace(
|
|
10150
|
+
function skipSpace(text4, from) {
|
|
10046
10151
|
let i = from;
|
|
10047
|
-
while (i <
|
|
10152
|
+
while (i < text4.length && /\s/.test(text4[i] ?? "")) i += 1;
|
|
10048
10153
|
return i;
|
|
10049
10154
|
}
|
|
10050
|
-
function stringEnd(
|
|
10051
|
-
if (
|
|
10052
|
-
for (let i = from + 1; i <
|
|
10053
|
-
if (
|
|
10054
|
-
else if (
|
|
10155
|
+
function stringEnd(text4, from) {
|
|
10156
|
+
if (text4[from] !== '"') throw new Error("string");
|
|
10157
|
+
for (let i = from + 1; i < text4.length; i += 1) {
|
|
10158
|
+
if (text4[i] === "\\") i += 1;
|
|
10159
|
+
else if (text4[i] === '"') return i + 1;
|
|
10055
10160
|
}
|
|
10056
10161
|
throw new Error("string");
|
|
10057
10162
|
}
|
|
10058
|
-
function valueEnd(
|
|
10059
|
-
const start = skipSpace(
|
|
10060
|
-
const first =
|
|
10061
|
-
if (first === '"') return stringEnd(
|
|
10163
|
+
function valueEnd(text4, from) {
|
|
10164
|
+
const start = skipSpace(text4, from);
|
|
10165
|
+
const first = text4[start];
|
|
10166
|
+
if (first === '"') return stringEnd(text4, start);
|
|
10062
10167
|
if (first === "{" || first === "[") {
|
|
10063
10168
|
const close = first === "{" ? "}" : "]";
|
|
10064
|
-
let i2 = skipSpace(
|
|
10065
|
-
if (
|
|
10169
|
+
let i2 = skipSpace(text4, start + 1);
|
|
10170
|
+
if (text4[i2] === close) return i2 + 1;
|
|
10066
10171
|
for (; ; ) {
|
|
10067
10172
|
if (first === "{") {
|
|
10068
|
-
i2 = skipSpace(
|
|
10069
|
-
if (
|
|
10173
|
+
i2 = skipSpace(text4, stringEnd(text4, skipSpace(text4, i2)));
|
|
10174
|
+
if (text4[i2] !== ":") throw new Error("colon");
|
|
10070
10175
|
i2 += 1;
|
|
10071
10176
|
}
|
|
10072
|
-
i2 = skipSpace(
|
|
10073
|
-
if (
|
|
10074
|
-
if (
|
|
10177
|
+
i2 = skipSpace(text4, valueEnd(text4, i2));
|
|
10178
|
+
if (text4[i2] === close) return i2 + 1;
|
|
10179
|
+
if (text4[i2] !== ",") throw new Error("comma");
|
|
10075
10180
|
i2 += 1;
|
|
10076
10181
|
}
|
|
10077
10182
|
}
|
|
10078
10183
|
let i = start;
|
|
10079
|
-
while (i <
|
|
10184
|
+
while (i < text4.length && !/[\s,\]}]/.test(text4[i] ?? "")) i += 1;
|
|
10080
10185
|
if (i === start) throw new Error("value");
|
|
10081
10186
|
return i;
|
|
10082
10187
|
}
|
|
10083
|
-
function objectMember(
|
|
10084
|
-
const start = skipSpace(
|
|
10085
|
-
if (
|
|
10086
|
-
let i = skipSpace(
|
|
10087
|
-
while (
|
|
10088
|
-
const at = skipSpace(
|
|
10089
|
-
const end = stringEnd(
|
|
10090
|
-
const colon = skipSpace(
|
|
10091
|
-
if (
|
|
10092
|
-
const value = skipSpace(
|
|
10093
|
-
if (JSON.parse(
|
|
10094
|
-
i = skipSpace(
|
|
10095
|
-
if (
|
|
10096
|
-
else if (
|
|
10188
|
+
function objectMember(text4, from, key) {
|
|
10189
|
+
const start = skipSpace(text4, from);
|
|
10190
|
+
if (text4[start] !== "{") return null;
|
|
10191
|
+
let i = skipSpace(text4, start + 1);
|
|
10192
|
+
while (text4[i] !== "}") {
|
|
10193
|
+
const at = skipSpace(text4, i);
|
|
10194
|
+
const end = stringEnd(text4, at);
|
|
10195
|
+
const colon = skipSpace(text4, end);
|
|
10196
|
+
if (text4[colon] !== ":") throw new Error("colon");
|
|
10197
|
+
const value = skipSpace(text4, colon + 1);
|
|
10198
|
+
if (JSON.parse(text4.slice(at, end)) === key) return { at, value };
|
|
10199
|
+
i = skipSpace(text4, valueEnd(text4, value));
|
|
10200
|
+
if (text4[i] === ",") i = skipSpace(text4, i + 1);
|
|
10201
|
+
else if (text4[i] !== "}") throw new Error("comma");
|
|
10097
10202
|
}
|
|
10098
10203
|
return null;
|
|
10099
10204
|
}
|
|
10100
|
-
function arrayItem(
|
|
10101
|
-
const start = skipSpace(
|
|
10102
|
-
if (
|
|
10103
|
-
let i = skipSpace(
|
|
10104
|
-
for (let n = 0;
|
|
10105
|
-
const at = skipSpace(
|
|
10205
|
+
function arrayItem(text4, from, index) {
|
|
10206
|
+
const start = skipSpace(text4, from);
|
|
10207
|
+
if (text4[start] !== "[") return null;
|
|
10208
|
+
let i = skipSpace(text4, start + 1);
|
|
10209
|
+
for (let n = 0; text4[i] !== "]"; n += 1) {
|
|
10210
|
+
const at = skipSpace(text4, i);
|
|
10106
10211
|
if (n === index) return { at, value: at };
|
|
10107
|
-
i = skipSpace(
|
|
10108
|
-
if (
|
|
10109
|
-
else if (
|
|
10212
|
+
i = skipSpace(text4, valueEnd(text4, at));
|
|
10213
|
+
if (text4[i] === ",") i = skipSpace(text4, i + 1);
|
|
10214
|
+
else if (text4[i] !== "]") throw new Error("comma");
|
|
10110
10215
|
}
|
|
10111
10216
|
return null;
|
|
10112
10217
|
}
|
|
@@ -10219,8 +10324,8 @@ var ENTITIES = {
|
|
|
10219
10324
|
agrave: 224,
|
|
10220
10325
|
ccedil: 231
|
|
10221
10326
|
};
|
|
10222
|
-
function decodeEntities(
|
|
10223
|
-
return
|
|
10327
|
+
function decodeEntities(text4) {
|
|
10328
|
+
return text4.replace(
|
|
10224
10329
|
/&(#x[0-9a-f]+|#\d+|[a-z][a-z0-9]*);/gi,
|
|
10225
10330
|
(whole, reference) => {
|
|
10226
10331
|
const code = reference.startsWith("#") ? reference[1] === "x" || reference[1] === "X" ? Number.parseInt(reference.slice(2), 16) : Number.parseInt(reference.slice(1), 10) : ENTITIES[reference];
|
|
@@ -10346,6 +10451,320 @@ function einvoiceXml(data, options) {
|
|
|
10346
10451
|
};
|
|
10347
10452
|
}
|
|
10348
10453
|
|
|
10454
|
+
// packages/engine/src/lib/accessibility/index.ts
|
|
10455
|
+
var PDFUA_STANDARD = "PDF/UA-1";
|
|
10456
|
+
var UA_CHECKS = ["strict", "report"];
|
|
10457
|
+
function resolveUa(setting) {
|
|
10458
|
+
if (setting === true) return { check: "strict" };
|
|
10459
|
+
if (!setting || typeof setting !== "object" || Array.isArray(setting))
|
|
10460
|
+
return null;
|
|
10461
|
+
const check = setting.check;
|
|
10462
|
+
return { check: check === "report" ? "report" : "strict" };
|
|
10463
|
+
}
|
|
10464
|
+
var UA_REFUSALS = {
|
|
10465
|
+
office: "pdf.ua is not available for Word and PowerPoint templates yet",
|
|
10466
|
+
merge: "pdf.ua cannot be combined with post.merge_after: the tags of merged documents do not survive the merge"
|
|
10467
|
+
};
|
|
10468
|
+
function isUaSetting(value) {
|
|
10469
|
+
if (value === null || typeof value === "boolean") return true;
|
|
10470
|
+
if (typeof value !== "object" || Array.isArray(value)) return false;
|
|
10471
|
+
const entries = Object.entries(value);
|
|
10472
|
+
return entries.every(
|
|
10473
|
+
([key, entry]) => key === "check" && UA_CHECKS.includes(entry)
|
|
10474
|
+
);
|
|
10475
|
+
}
|
|
10476
|
+
var AUDIT_CODES = [
|
|
10477
|
+
"document-title",
|
|
10478
|
+
"image-alt",
|
|
10479
|
+
"figure-name",
|
|
10480
|
+
"heading-order",
|
|
10481
|
+
"table-rows",
|
|
10482
|
+
"table-cell-empty",
|
|
10483
|
+
"masked-text",
|
|
10484
|
+
"filtered-text",
|
|
10485
|
+
"document-language",
|
|
10486
|
+
"table-headers",
|
|
10487
|
+
"link-name",
|
|
10488
|
+
"generated-text",
|
|
10489
|
+
"fixed-text",
|
|
10490
|
+
"running-text"
|
|
10491
|
+
];
|
|
10492
|
+
var AUDIT_SEVERITY = {
|
|
10493
|
+
"document-title": "error",
|
|
10494
|
+
"image-alt": "error",
|
|
10495
|
+
"figure-name": "error",
|
|
10496
|
+
"heading-order": "error",
|
|
10497
|
+
"table-rows": "error",
|
|
10498
|
+
"table-cell-empty": "error",
|
|
10499
|
+
"masked-text": "error",
|
|
10500
|
+
"filtered-text": "warning",
|
|
10501
|
+
"document-language": "warning",
|
|
10502
|
+
"table-headers": "warning",
|
|
10503
|
+
"link-name": "warning",
|
|
10504
|
+
"generated-text": "warning",
|
|
10505
|
+
"fixed-text": "warning",
|
|
10506
|
+
"running-text": "warning"
|
|
10507
|
+
};
|
|
10508
|
+
var AUDIT_RULES = {
|
|
10509
|
+
"document-title": ["7.1-9", "7.1-10"],
|
|
10510
|
+
"image-alt": ["7.3-1"],
|
|
10511
|
+
"figure-name": ["7.3-1"],
|
|
10512
|
+
"heading-order": ["7.4.2-1"],
|
|
10513
|
+
"table-rows": ["7.2-43"],
|
|
10514
|
+
"table-cell-empty": ["7.2-43"],
|
|
10515
|
+
"masked-text": ["7.20-2"],
|
|
10516
|
+
"filtered-text": [],
|
|
10517
|
+
"document-language": [],
|
|
10518
|
+
"table-headers": [],
|
|
10519
|
+
"link-name": [],
|
|
10520
|
+
"generated-text": [],
|
|
10521
|
+
"fixed-text": [],
|
|
10522
|
+
"running-text": []
|
|
10523
|
+
};
|
|
10524
|
+
var AUDIT_TITLES = {
|
|
10525
|
+
"document-title": "No document title",
|
|
10526
|
+
"image-alt": "Image without an alt attribute",
|
|
10527
|
+
"figure-name": "Figure without a name",
|
|
10528
|
+
"heading-order": "Heading level skipped",
|
|
10529
|
+
"table-rows": "Table rows of different lengths",
|
|
10530
|
+
"table-cell-empty": "Empty table cell",
|
|
10531
|
+
"masked-text": "Text under a CSS mask",
|
|
10532
|
+
"filtered-text": "Text under a CSS filter",
|
|
10533
|
+
"document-language": "No language stated",
|
|
10534
|
+
"table-headers": "Table without header cells",
|
|
10535
|
+
"link-name": "Link without a name",
|
|
10536
|
+
"generated-text": "Text generated by CSS",
|
|
10537
|
+
"fixed-text": "Fixed text on every page",
|
|
10538
|
+
"running-text": "Only in the header or footer"
|
|
10539
|
+
};
|
|
10540
|
+
var AUDIT_SNIPPET_LENGTH = 120;
|
|
10541
|
+
var text3 = (value) => String(value ?? "");
|
|
10542
|
+
function auditMessage(finding2) {
|
|
10543
|
+
const args = finding2.args;
|
|
10544
|
+
switch (finding2.code) {
|
|
10545
|
+
case "document-title":
|
|
10546
|
+
return "The document has no title. A PDF viewer shows the title in its title bar and a screen reader says it first: set pdf.metadata.title, or give the page a <title>.";
|
|
10547
|
+
case "image-alt":
|
|
10548
|
+
return 'The image has no alt attribute. Say what it shows, or write alt="" if it is decoration.';
|
|
10549
|
+
case "figure-name":
|
|
10550
|
+
return `The ${text3(args["tag"])} has no text alternative. Give it an aria-label that says what it shows; the chart helper takes alt.`;
|
|
10551
|
+
case "heading-order":
|
|
10552
|
+
return args["previous"] === 0 ? `The first heading is an h${text3(args["level"])}. Start with an h1 and size it with CSS.` : `This h${text3(args["level"])} follows an h${text3(args["previous"])}, so a heading level is skipped. Make it an h${Number(args["previous"]) + 1} and size it with CSS.`;
|
|
10553
|
+
case "table-rows":
|
|
10554
|
+
return `The rows of this table span different numbers of columns (${text3(args["first"])} and ${text3(args["other"])}). Even them out with colspan.`;
|
|
10555
|
+
case "table-cell-empty":
|
|
10556
|
+
return Number(args["count"]) > 1 ? `${text3(args["count"])} cells of this table are empty. Chromium writes no cell for an empty td, so their rows come out shorter than the others: put a non-breaking space ( ) or a dash into each.` : "This table cell is empty. Chromium writes no cell for an empty td, so its row comes out shorter than the others: put a non-breaking space ( ) or a dash into it.";
|
|
10557
|
+
case "masked-text":
|
|
10558
|
+
return "This element has a CSS mask and holds text. Chromium then writes the text in a way PDF/UA-1 does not allow, and no repair reaches it: mask an element without text instead.";
|
|
10559
|
+
case "filtered-text":
|
|
10560
|
+
return "This element has a CSS filter and holds text. The filter turns the text into a picture, which nobody can have read out or select.";
|
|
10561
|
+
case "document-language":
|
|
10562
|
+
return "The document names no language. Set lang on the html element, or the locale in the settings.";
|
|
10563
|
+
case "table-headers":
|
|
10564
|
+
return "The table has no header cells. Use th for the titles of its columns or rows, or a screen reader says the cells without them.";
|
|
10565
|
+
case "link-name":
|
|
10566
|
+
return "The link has no text. A screen reader says its address instead: give it text, an aria-label, or an image with alt.";
|
|
10567
|
+
case "generated-text":
|
|
10568
|
+
return `\u201C${text3(args["text"])}\u201D comes from CSS (::before or ::after). Generated text is not read out: write it into the template.`;
|
|
10569
|
+
case "fixed-text":
|
|
10570
|
+
return "This element is position: fixed, so it is printed on every page and read once per page, one after the other.";
|
|
10571
|
+
case "running-text":
|
|
10572
|
+
return `\u201C${text3(args["text"])}\u201D stands only in the ${text3(args["part"])}. A screen reader skips page headers and footers, so say it in the body too.`;
|
|
10573
|
+
}
|
|
10574
|
+
}
|
|
10575
|
+
var ACCESSIBILITY_MAX_FAILURES = 20;
|
|
10576
|
+
var ACCESSIBILITY_MAX_ELEMENTS = 5;
|
|
10577
|
+
var elementOf = (finding2) => finding2.code === "running-text" || finding2.code === "generated-text" ? text3(finding2.args["text"]) : finding2.snippet;
|
|
10578
|
+
function accessibilityResult(options, verdict, findings) {
|
|
10579
|
+
const failures = verdict.failures.map((failure) => {
|
|
10580
|
+
const about = findings.filter(
|
|
10581
|
+
(finding2) => AUDIT_RULES[finding2.code].includes(failure.rule)
|
|
10582
|
+
);
|
|
10583
|
+
const first = about[0];
|
|
10584
|
+
return {
|
|
10585
|
+
rule: failure.rule,
|
|
10586
|
+
...first ? { code: first.code } : {},
|
|
10587
|
+
count: failure.checks,
|
|
10588
|
+
message: first ? auditMessage(first) : failure.description.replace(/\s+/g, " ").trim(),
|
|
10589
|
+
elements: [...new Set(about.map(elementOf).filter(Boolean))].slice(
|
|
10590
|
+
0,
|
|
10591
|
+
ACCESSIBILITY_MAX_ELEMENTS
|
|
10592
|
+
)
|
|
10593
|
+
};
|
|
10594
|
+
});
|
|
10595
|
+
const warnings = [];
|
|
10596
|
+
for (const finding2 of findings) {
|
|
10597
|
+
if (finding2.severity !== "warning") continue;
|
|
10598
|
+
let warning = warnings.find((entry) => entry.code === finding2.code);
|
|
10599
|
+
if (!warning)
|
|
10600
|
+
warnings.push(warning = { code: finding2.code, count: 0, elements: [] });
|
|
10601
|
+
warning.count++;
|
|
10602
|
+
const element = elementOf(finding2);
|
|
10603
|
+
if (element && warning.elements.length < ACCESSIBILITY_MAX_ELEMENTS && !warning.elements.includes(element))
|
|
10604
|
+
warning.elements.push(element);
|
|
10605
|
+
}
|
|
10606
|
+
return {
|
|
10607
|
+
standard: PDFUA_STANDARD,
|
|
10608
|
+
check: options.check,
|
|
10609
|
+
conformant: verdict.compliant,
|
|
10610
|
+
validator: verdict.validator,
|
|
10611
|
+
rules: verdict.rules,
|
|
10612
|
+
failures: failures.slice(0, ACCESSIBILITY_MAX_FAILURES),
|
|
10613
|
+
warnings,
|
|
10614
|
+
...failures.length > ACCESSIBILITY_MAX_FAILURES ? { truncated: true } : {}
|
|
10615
|
+
};
|
|
10616
|
+
}
|
|
10617
|
+
function accessibilityHeader(result) {
|
|
10618
|
+
return result.conformant ? "conformant" : "not-conformant";
|
|
10619
|
+
}
|
|
10620
|
+
var ACCESSIBILITY_HEADER_LENGTH = 8e3;
|
|
10621
|
+
function accessibilityHeaderValue(result, limit = ACCESSIBILITY_HEADER_LENGTH) {
|
|
10622
|
+
const encode = (report2) => encodeURIComponent(JSON.stringify(report2));
|
|
10623
|
+
const keep = (report2, elements) => ({
|
|
10624
|
+
...report2,
|
|
10625
|
+
truncated: true,
|
|
10626
|
+
failures: report2.failures.map((failure) => ({
|
|
10627
|
+
...failure,
|
|
10628
|
+
elements: failure.elements.slice(0, elements)
|
|
10629
|
+
})),
|
|
10630
|
+
warnings: report2.warnings.map((warning) => ({
|
|
10631
|
+
...warning,
|
|
10632
|
+
elements: warning.elements.slice(0, elements)
|
|
10633
|
+
}))
|
|
10634
|
+
});
|
|
10635
|
+
let value = encode(result);
|
|
10636
|
+
if (value.length <= limit) return value;
|
|
10637
|
+
for (const elements of [1, 0]) {
|
|
10638
|
+
value = encode(keep(result, elements));
|
|
10639
|
+
if (value.length <= limit) return value;
|
|
10640
|
+
}
|
|
10641
|
+
let report = keep(result, 0);
|
|
10642
|
+
while (report.failures.length + report.warnings.length > 0) {
|
|
10643
|
+
report = report.warnings.length ? { ...report, warnings: report.warnings.slice(0, -1) } : { ...report, failures: report.failures.slice(0, -1) };
|
|
10644
|
+
value = encode(report);
|
|
10645
|
+
if (value.length <= limit) return value;
|
|
10646
|
+
}
|
|
10647
|
+
return value;
|
|
10648
|
+
}
|
|
10649
|
+
|
|
10650
|
+
// packages/engine/src/lib/accessibility/static.ts
|
|
10651
|
+
var finding = (code, src, snippet) => ({
|
|
10652
|
+
code,
|
|
10653
|
+
severity: AUDIT_SEVERITY[code],
|
|
10654
|
+
src,
|
|
10655
|
+
snippet,
|
|
10656
|
+
args: {}
|
|
10657
|
+
});
|
|
10658
|
+
var NAMING = /* @__PURE__ */ new Set(["alt", "aria-label", "aria-labelledby", "title"]);
|
|
10659
|
+
function imageIsNamed(attributes, scanner, base) {
|
|
10660
|
+
const n = attributes.length;
|
|
10661
|
+
let i = 0;
|
|
10662
|
+
let named = false;
|
|
10663
|
+
while (i < n) {
|
|
10664
|
+
const ch = attributes[i];
|
|
10665
|
+
if (/[\s/>]/.test(ch)) {
|
|
10666
|
+
i++;
|
|
10667
|
+
continue;
|
|
10668
|
+
}
|
|
10669
|
+
if (ch === "{" && scanner.skipTemplate(base + i) !== null) return null;
|
|
10670
|
+
const start = i;
|
|
10671
|
+
while (i < n && !/[\s=/>]/.test(attributes[i])) i++;
|
|
10672
|
+
const name = attributes.slice(start, i).toLowerCase();
|
|
10673
|
+
while (i < n && /\s/.test(attributes[i])) i++;
|
|
10674
|
+
let value = "";
|
|
10675
|
+
if (attributes[i] === "=") {
|
|
10676
|
+
i++;
|
|
10677
|
+
while (i < n && /\s/.test(attributes[i])) i++;
|
|
10678
|
+
const quote2 = attributes[i];
|
|
10679
|
+
if (quote2 === '"' || quote2 === "'") {
|
|
10680
|
+
const end = scanner.skipTo(base + i + 1, quote2) - base;
|
|
10681
|
+
value = attributes.slice(i + 1, Math.max(i + 1, end - 1));
|
|
10682
|
+
i = end;
|
|
10683
|
+
} else {
|
|
10684
|
+
const from = i;
|
|
10685
|
+
while (i < n && !/[\s>]/.test(attributes[i])) i++;
|
|
10686
|
+
value = attributes.slice(from, i);
|
|
10687
|
+
}
|
|
10688
|
+
}
|
|
10689
|
+
if (NAMING.has(name)) named = true;
|
|
10690
|
+
else if (name === "aria-hidden" && value.trim() !== "false") named = true;
|
|
10691
|
+
else if (name === "role" && /^(presentation|none)$/.test(value.trim()))
|
|
10692
|
+
named = true;
|
|
10693
|
+
}
|
|
10694
|
+
return named;
|
|
10695
|
+
}
|
|
10696
|
+
function staticAuditDiagnostics(input, ua) {
|
|
10697
|
+
return staticAudit(input).map((found) => {
|
|
10698
|
+
const at = /^body:(\d+):(\d+)$/.exec(found.src ?? "");
|
|
10699
|
+
return {
|
|
10700
|
+
severity: found.severity === "error" && ua.check === "strict" ? "error" : "warning",
|
|
10701
|
+
code: `accessibility-${found.code}`,
|
|
10702
|
+
message: auditMessage(found),
|
|
10703
|
+
...at ? { location: { line: Number(at[1]), column: Number(at[2]) } } : {}
|
|
10704
|
+
};
|
|
10705
|
+
});
|
|
10706
|
+
}
|
|
10707
|
+
function staticAudit(input) {
|
|
10708
|
+
const findings = [];
|
|
10709
|
+
if (!input.title?.trim() && !/<title[\s>]/i.test(input.head ?? ""))
|
|
10710
|
+
findings.push(finding("document-title", null, ""));
|
|
10711
|
+
const source = input.html;
|
|
10712
|
+
const scanner = new Scanner(source, input.engine);
|
|
10713
|
+
const lines = lineStarts(source);
|
|
10714
|
+
const n = source.length;
|
|
10715
|
+
let i = 0;
|
|
10716
|
+
while (i < n) {
|
|
10717
|
+
const ch = source[i];
|
|
10718
|
+
if (ch === "{") {
|
|
10719
|
+
i = scanner.skipTemplate(i) ?? i + 1;
|
|
10720
|
+
continue;
|
|
10721
|
+
}
|
|
10722
|
+
if (ch !== "<") {
|
|
10723
|
+
i++;
|
|
10724
|
+
continue;
|
|
10725
|
+
}
|
|
10726
|
+
if (source.startsWith("<!--", i)) {
|
|
10727
|
+
i = scanner.skipTo(i + 4, "-->");
|
|
10728
|
+
continue;
|
|
10729
|
+
}
|
|
10730
|
+
const next = source[i + 1];
|
|
10731
|
+
if (next === "!" || next === "?") {
|
|
10732
|
+
i = scanner.tagEnd(i + 2);
|
|
10733
|
+
continue;
|
|
10734
|
+
}
|
|
10735
|
+
if (next === "/") {
|
|
10736
|
+
i += 2;
|
|
10737
|
+
continue;
|
|
10738
|
+
}
|
|
10739
|
+
tagName.lastIndex = i + 1;
|
|
10740
|
+
const name = tagName.exec(source)?.[0];
|
|
10741
|
+
if (!name) {
|
|
10742
|
+
i++;
|
|
10743
|
+
continue;
|
|
10744
|
+
}
|
|
10745
|
+
const nameEnd = i + 1 + name.length;
|
|
10746
|
+
const end = scanner.tagEnd(nameEnd);
|
|
10747
|
+
if (name.toLowerCase() === "img") {
|
|
10748
|
+
const named = imageIsNamed(source.slice(nameEnd, end), scanner, nameEnd);
|
|
10749
|
+
if (named === false) {
|
|
10750
|
+
const { line: line2, column } = locate(lines, i);
|
|
10751
|
+
const tag = source.slice(i, end).replace(/\s+/g, " ");
|
|
10752
|
+
findings.push(
|
|
10753
|
+
finding(
|
|
10754
|
+
"image-alt",
|
|
10755
|
+
`body:${line2}:${column}`,
|
|
10756
|
+
tag.length > AUDIT_SNIPPET_LENGTH ? `${tag.slice(0, AUDIT_SNIPPET_LENGTH - 1)}\u2026` : tag
|
|
10757
|
+
)
|
|
10758
|
+
);
|
|
10759
|
+
}
|
|
10760
|
+
}
|
|
10761
|
+
i = end;
|
|
10762
|
+
if (rawTextElements.has(name.toLowerCase()) && source[end - 1] === ">")
|
|
10763
|
+
i = scanner.skipToClosingTag(end, name);
|
|
10764
|
+
}
|
|
10765
|
+
return findings;
|
|
10766
|
+
}
|
|
10767
|
+
|
|
10349
10768
|
// packages/engine/src/lib/office/errors.ts
|
|
10350
10769
|
var OfficeError = class extends Error {
|
|
10351
10770
|
constructor(code, message, details = {}) {
|
|
@@ -11665,12 +12084,12 @@ function assertWellFormed(tokens, part) {
|
|
|
11665
12084
|
}
|
|
11666
12085
|
var FORBIDDEN = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
|
|
11667
12086
|
var ENTITY = /&(?:#x[0-9A-Fa-f]+|#\d+|amp|lt|gt|quot|apos);/y;
|
|
11668
|
-
function checkText(
|
|
11669
|
-
if (FORBIDDEN.test(
|
|
11670
|
-
if (
|
|
11671
|
-
for (let i =
|
|
12087
|
+
function checkText(text4, part) {
|
|
12088
|
+
if (FORBIDDEN.test(text4)) throw invalid2("a character XML does not allow", part);
|
|
12089
|
+
if (text4.includes("<")) throw invalid2("unescaped < in text", part);
|
|
12090
|
+
for (let i = text4.indexOf("&"); i !== -1; i = text4.indexOf("&", i + 1)) {
|
|
11672
12091
|
ENTITY.lastIndex = i;
|
|
11673
|
-
if (!ENTITY.test(
|
|
12092
|
+
if (!ENTITY.test(text4)) throw invalid2(`invalid entity reference near "${text4.slice(i, i + 12)}"`, part);
|
|
11674
12093
|
}
|
|
11675
12094
|
}
|
|
11676
12095
|
function checkAttributes(raw, part) {
|
|
@@ -11705,13 +12124,13 @@ function decodeText3(raw) {
|
|
|
11705
12124
|
}
|
|
11706
12125
|
});
|
|
11707
12126
|
}
|
|
11708
|
-
function escapeText3(
|
|
11709
|
-
return
|
|
12127
|
+
function escapeText3(text4) {
|
|
12128
|
+
return text4.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
11710
12129
|
}
|
|
11711
12130
|
var FORBIDDEN_GLOBAL = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
|
|
11712
|
-
function stripForbidden(
|
|
12131
|
+
function stripForbidden(text4) {
|
|
11713
12132
|
let removed = 0;
|
|
11714
|
-
const out =
|
|
12133
|
+
const out = text4.replace(FORBIDDEN_GLOBAL, () => {
|
|
11715
12134
|
removed++;
|
|
11716
12135
|
return "";
|
|
11717
12136
|
});
|
|
@@ -11962,13 +12381,13 @@ function placeDrawings(xml2, pattern, markupFor) {
|
|
|
11962
12381
|
pattern.lastIndex = 0;
|
|
11963
12382
|
if (pattern.test(t.raw)) {
|
|
11964
12383
|
const segments = t.raw.split(pattern);
|
|
11965
|
-
let
|
|
12384
|
+
let text4 = segments[0];
|
|
11966
12385
|
for (let s = 1; s < segments.length; s += 2) {
|
|
11967
12386
|
const index = Number(segments[s]);
|
|
11968
|
-
|
|
12387
|
+
text4 += `</w:t></w:r><w:r>${runProps}${markupFor(index)}</w:r>${runOpen}${runProps}<w:t xml:space="preserve">` + segments[s + 1];
|
|
11969
12388
|
}
|
|
11970
12389
|
out[textOpen] = withPreserve(out[textOpen]);
|
|
11971
|
-
out.push(
|
|
12390
|
+
out.push(text4);
|
|
11972
12391
|
continue;
|
|
11973
12392
|
}
|
|
11974
12393
|
}
|
|
@@ -12223,11 +12642,11 @@ function fromTemplateOutput(output, template, part) {
|
|
|
12223
12642
|
let last = 0;
|
|
12224
12643
|
let inText = false;
|
|
12225
12644
|
const emit = (segment) => {
|
|
12226
|
-
const { text:
|
|
12645
|
+
const { text: text4, removed } = stripForbidden(segment);
|
|
12227
12646
|
removedCharacters += removed;
|
|
12228
|
-
if (!inText &&
|
|
12229
|
-
throw new OfficeError("office_document_invalid", `${part ?? "part"}: text outside a text element: "${
|
|
12230
|
-
xml2 += escapeText3(
|
|
12647
|
+
if (!inText && text4.trim() !== "")
|
|
12648
|
+
throw new OfficeError("office_document_invalid", `${part ?? "part"}: text outside a text element: "${text4.trim().slice(0, 40)}"`);
|
|
12649
|
+
xml2 += escapeText3(text4);
|
|
12231
12650
|
};
|
|
12232
12651
|
for (const m of output.matchAll(placeholder)) {
|
|
12233
12652
|
emit(output.slice(last, m.index));
|
|
@@ -12269,15 +12688,15 @@ function layoutText(xml2, flavour, part) {
|
|
|
12269
12688
|
out.push(token2.raw);
|
|
12270
12689
|
continue;
|
|
12271
12690
|
}
|
|
12272
|
-
const
|
|
12691
|
+
const text4 = token2.raw.replace(/\r\n?/g, "\n");
|
|
12273
12692
|
if (flavour === "wordprocessing") {
|
|
12274
|
-
const pieces =
|
|
12275
|
-
if (pieces.length > 1 || /^\s|\s$/.test(
|
|
12693
|
+
const pieces = text4.split(/(\n|\t)/);
|
|
12694
|
+
if (pieces.length > 1 || /^\s|\s$/.test(text4)) out[textOpenIndex] = preserveSpace(out[textOpenIndex]);
|
|
12276
12695
|
out.push(
|
|
12277
12696
|
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("")
|
|
12278
12697
|
);
|
|
12279
12698
|
} else {
|
|
12280
|
-
out.push(
|
|
12699
|
+
out.push(text4.split("\n").join(`</a:t></a:r><a:br>${runProperties}</a:br><a:r>${runProperties}<a:t>`));
|
|
12281
12700
|
}
|
|
12282
12701
|
}
|
|
12283
12702
|
return out.join("");
|
|
@@ -12310,17 +12729,17 @@ var AUTOCORRECTED = [
|
|
|
12310
12729
|
[/\u200B|\u200C|\u200D|\uFEFF/g, ""]
|
|
12311
12730
|
];
|
|
12312
12731
|
function normaliseTags(template, part) {
|
|
12313
|
-
const { text:
|
|
12732
|
+
const { text: text4, origin, placeholders } = stripPlaceholders(template);
|
|
12314
12733
|
const sourceRange = (from, to) => [
|
|
12315
12734
|
origin[from] ?? template.source.length,
|
|
12316
12735
|
(origin[to - 1] ?? template.source.length - 1) + 1
|
|
12317
12736
|
];
|
|
12318
12737
|
const diagnostics = [];
|
|
12319
12738
|
const edits = [];
|
|
12320
|
-
for (const tag of findTags(
|
|
12739
|
+
for (const tag of findTags(text4)) {
|
|
12321
12740
|
const inside = placeholders.filter((p) => p.at > tag.start && p.at < tag.end);
|
|
12322
12741
|
const paragraph2 = paragraphOf(template, placeholders, tag.start);
|
|
12323
|
-
const raw =
|
|
12742
|
+
const raw = text4.slice(tag.start, tag.end);
|
|
12324
12743
|
const unsafe = inside.filter((p) => {
|
|
12325
12744
|
const piece = template.markup[p.index];
|
|
12326
12745
|
return !piece || piece.paragraphBoundary || piece.containerBoundary;
|
|
@@ -12374,8 +12793,8 @@ function normaliseTags(template, part) {
|
|
|
12374
12793
|
return { template: { ...template, source: applyEdits(template.source, edits) }, diagnostics };
|
|
12375
12794
|
}
|
|
12376
12795
|
var ENTITIES2 = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'" };
|
|
12377
|
-
function decodeEntities2(
|
|
12378
|
-
return
|
|
12796
|
+
function decodeEntities2(text4) {
|
|
12797
|
+
return text4.replace(/&(#x[0-9a-f]+|#\d+|amp|lt|gt|quot|apos);/gi, (whole, name) => {
|
|
12379
12798
|
if (name[0] !== "#") return ENTITIES2[name.toLowerCase()] ?? whole;
|
|
12380
12799
|
const code = name[1] === "x" || name[1] === "X" ? parseInt(name.slice(2), 16) : parseInt(name.slice(1), 10);
|
|
12381
12800
|
return Number.isFinite(code) ? String.fromCodePoint(code) : whole;
|
|
@@ -12383,28 +12802,28 @@ function decodeEntities2(text3) {
|
|
|
12383
12802
|
}
|
|
12384
12803
|
function stripPlaceholders(template) {
|
|
12385
12804
|
const pattern = placeholderPattern(template.nonce);
|
|
12386
|
-
let
|
|
12805
|
+
let text4 = "";
|
|
12387
12806
|
const origin = [];
|
|
12388
12807
|
const placeholders = [];
|
|
12389
12808
|
let last = 0;
|
|
12390
12809
|
for (const m of template.source.matchAll(pattern)) {
|
|
12391
12810
|
for (let i = last; i < (m.index ?? 0); i++) {
|
|
12392
|
-
|
|
12811
|
+
text4 += template.source[i];
|
|
12393
12812
|
origin.push(i);
|
|
12394
12813
|
}
|
|
12395
|
-
placeholders.push({ index: Number(m[1]), at:
|
|
12814
|
+
placeholders.push({ index: Number(m[1]), at: text4.length, from: m.index ?? 0, to: (m.index ?? 0) + m[0].length });
|
|
12396
12815
|
last = (m.index ?? 0) + m[0].length;
|
|
12397
12816
|
}
|
|
12398
12817
|
for (let i = last; i < template.source.length; i++) {
|
|
12399
|
-
|
|
12818
|
+
text4 += template.source[i];
|
|
12400
12819
|
origin.push(i);
|
|
12401
12820
|
}
|
|
12402
|
-
return { text:
|
|
12821
|
+
return { text: text4, origin, placeholders };
|
|
12403
12822
|
}
|
|
12404
12823
|
function listTags(template, part) {
|
|
12405
|
-
const { text:
|
|
12406
|
-
return findTags(
|
|
12407
|
-
const raw =
|
|
12824
|
+
const { text: text4, placeholders } = stripPlaceholders(template);
|
|
12825
|
+
return findTags(text4).map((tag) => {
|
|
12826
|
+
const raw = text4.slice(tag.start, tag.end);
|
|
12408
12827
|
const kind = raw.startsWith("{#") ? "comment" : raw.startsWith("{%") || /^\{\{~?\s*[#/^]/.test(raw) || /^\{\{~?\s*else\b/.test(raw) ? "block" : "output";
|
|
12409
12828
|
return { part, paragraph: paragraphOf(template, placeholders, tag.start), text: raw.replace(/\s+/g, " ").trim(), kind };
|
|
12410
12829
|
});
|
|
@@ -12425,15 +12844,15 @@ function undoAutocorrect(tag) {
|
|
|
12425
12844
|
for (const [pattern, replacement] of AUTOCORRECTED) out = out.replace(pattern, replacement);
|
|
12426
12845
|
return out;
|
|
12427
12846
|
}
|
|
12428
|
-
function findTags(
|
|
12847
|
+
function findTags(text4) {
|
|
12429
12848
|
const tags = [];
|
|
12430
|
-
for (let i = 0; i <
|
|
12431
|
-
const opener = OPENERS.find((o) =>
|
|
12849
|
+
for (let i = 0; i < text4.length - 1; i++) {
|
|
12850
|
+
const opener = OPENERS.find((o) => text4.startsWith(o, i));
|
|
12432
12851
|
if (!opener) continue;
|
|
12433
12852
|
const closer = CLOSERS[opener];
|
|
12434
|
-
const end =
|
|
12853
|
+
const end = text4.indexOf(closer, i + opener.length);
|
|
12435
12854
|
if (end === -1) continue;
|
|
12436
|
-
const stop = end + closer.length + (opener === "{{" &&
|
|
12855
|
+
const stop = end + closer.length + (opener === "{{" && text4[end + closer.length] === "}" ? 1 : 0);
|
|
12437
12856
|
tags.push({ start: i, end: stop });
|
|
12438
12857
|
i = stop - 1;
|
|
12439
12858
|
}
|
|
@@ -12463,8 +12882,8 @@ var CONTENT = /* @__PURE__ */ new Set(["w:drawing", "w:pict", "w:object", "w:fld
|
|
|
12463
12882
|
var JINJA_OPEN = /^(for|if|unless|case|capture|raw|with|macro|call|filter|block|tablerow|comment|autoescape)\b/;
|
|
12464
12883
|
var JINJA_CLOSE = /^end(for|if|unless|case|capture|raw|with|macro|call|filter|block|tablerow|comment|autoescape)\b/;
|
|
12465
12884
|
var JINJA_MIDDLE = /^(else|elif|elsif|when)\b/;
|
|
12466
|
-
function blockRole(
|
|
12467
|
-
const t =
|
|
12885
|
+
function blockRole(text4) {
|
|
12886
|
+
const t = text4.trim();
|
|
12468
12887
|
let m = /^\{%-?\s*([\s\S]*?)\s*-?%\}$/.exec(t);
|
|
12469
12888
|
if (m && !t.slice(2, -2).includes("%}")) {
|
|
12470
12889
|
const body = m[1] ?? "";
|
|
@@ -12496,14 +12915,14 @@ function dropTaggedFallbacks(xml2, part) {
|
|
|
12496
12915
|
if (t.kind === "open" && t.name === "mc:Fallback" && !t.selfClosing) {
|
|
12497
12916
|
let depth = 1;
|
|
12498
12917
|
let j = i + 1;
|
|
12499
|
-
let
|
|
12918
|
+
let text4 = "";
|
|
12500
12919
|
for (; j < tokens.length && depth > 0; j++) {
|
|
12501
12920
|
const u = tokens[j];
|
|
12502
12921
|
if (u.kind === "open" && u.name === "mc:Fallback" && !u.selfClosing) depth++;
|
|
12503
12922
|
else if (u.kind === "close" && u.name === "mc:Fallback") depth--;
|
|
12504
|
-
else if (u.kind === "text")
|
|
12923
|
+
else if (u.kind === "text") text4 += decodeText3(u.raw);
|
|
12505
12924
|
}
|
|
12506
|
-
if (/\{\{|\{%|\{#/.test(
|
|
12925
|
+
if (/\{\{|\{%|\{#/.test(text4)) {
|
|
12507
12926
|
i = j - 1;
|
|
12508
12927
|
continue;
|
|
12509
12928
|
}
|
|
@@ -12576,9 +12995,9 @@ function applyStructure(xml2, part) {
|
|
|
12576
12995
|
for (const [span, s] of structural) {
|
|
12577
12996
|
if (rowOf.has(span)) continue;
|
|
12578
12997
|
const keep = s.info.sectionProperties;
|
|
12579
|
-
let
|
|
12580
|
-
if (keep)
|
|
12581
|
-
replacements.push({ start: span.start, end: span.end, text:
|
|
12998
|
+
let text4 = element(s.tag);
|
|
12999
|
+
if (keep) text4 = s.role === "open" ? `<w:p>${keep}</w:p>${text4}` : `${text4}<w:p>${keep}</w:p>`;
|
|
13000
|
+
replacements.push({ start: span.start, end: span.end, text: text4 });
|
|
12582
13001
|
const holder = span.parent && BODIES.has(span.parent.name) ? span.parent : null;
|
|
12583
13002
|
if (holder && !keep) cellsEmptied.set(holder, (cellsEmptied.get(holder) ?? 0) + 1);
|
|
12584
13003
|
}
|
|
@@ -12632,7 +13051,7 @@ function collectParagraphs(tokens, root) {
|
|
|
12632
13051
|
const out = [];
|
|
12633
13052
|
const walk3 = (span) => {
|
|
12634
13053
|
if (PARAGRAPH.has(span.name)) {
|
|
12635
|
-
let
|
|
13054
|
+
let text4 = "";
|
|
12636
13055
|
let hasContent = false;
|
|
12637
13056
|
let sectionProperties = null;
|
|
12638
13057
|
let inText = false;
|
|
@@ -12643,10 +13062,10 @@ function collectParagraphs(tokens, root) {
|
|
|
12643
13062
|
else if (CONTENT.has(t.name)) hasContent = true;
|
|
12644
13063
|
else if (t.name === "w:sectPr") sectionProperties = "";
|
|
12645
13064
|
} else if (t.kind === "close" && TEXT.has(t.name)) inText = false;
|
|
12646
|
-
else if (t.kind === "text" && inText)
|
|
13065
|
+
else if (t.kind === "text" && inText) text4 += decodeText3(t.raw);
|
|
12647
13066
|
}
|
|
12648
13067
|
if (sectionProperties !== null) sectionProperties = propertiesOf(tokens, span);
|
|
12649
|
-
out.push({ span, number: out.length + 1, text:
|
|
13068
|
+
out.push({ span, number: out.length + 1, text: text4, hasContent, sectionProperties });
|
|
12650
13069
|
}
|
|
12651
13070
|
for (const child2 of span.children) walk3(child2);
|
|
12652
13071
|
};
|
|
@@ -12754,7 +13173,7 @@ function placeSlidePictures(xml2, pattern, drawingFor, pictureMarkup, slide) {
|
|
|
12754
13173
|
for (const container of containers) {
|
|
12755
13174
|
const indexes = [];
|
|
12756
13175
|
const edits = [];
|
|
12757
|
-
let
|
|
13176
|
+
let text4 = "";
|
|
12758
13177
|
let inText = false;
|
|
12759
13178
|
for (let i = container.start + 1; i < container.end; i++) {
|
|
12760
13179
|
const t = tokens[i];
|
|
@@ -12763,7 +13182,7 @@ function placeSlidePictures(xml2, pattern, drawingFor, pictureMarkup, slide) {
|
|
|
12763
13182
|
else if (t.kind === "text" && inText) {
|
|
12764
13183
|
pattern.lastIndex = 0;
|
|
12765
13184
|
if (!pattern.test(t.raw)) {
|
|
12766
|
-
|
|
13185
|
+
text4 += decodeText3(t.raw);
|
|
12767
13186
|
continue;
|
|
12768
13187
|
}
|
|
12769
13188
|
const segments = t.raw.split(pattern);
|
|
@@ -12772,7 +13191,7 @@ function placeSlidePictures(xml2, pattern, drawingFor, pictureMarkup, slide) {
|
|
|
12772
13191
|
if (s % 2 === 1) indexes.push(Number(segments[s]));
|
|
12773
13192
|
else kept += segments[s];
|
|
12774
13193
|
}
|
|
12775
|
-
|
|
13194
|
+
text4 += decodeText3(kept);
|
|
12776
13195
|
edits.push({ at: i, raw: kept });
|
|
12777
13196
|
}
|
|
12778
13197
|
}
|
|
@@ -12791,7 +13210,7 @@ function placeSlidePictures(xml2, pattern, drawingFor, pictureMarkup, slide) {
|
|
|
12791
13210
|
}
|
|
12792
13211
|
const autoFit = tokens.slice(container.start, container.end).some((t) => t.kind === "open" && t.name === "a:spAutoFit");
|
|
12793
13212
|
const placed = layoutPictures(pictures, box, autoFit).map((b, i) => pictureMarkup(pictures[i], b)).join("");
|
|
12794
|
-
const onlyPictures = container.name === "p:sp" &&
|
|
13213
|
+
const onlyPictures = container.name === "p:sp" && text4.trim() === "";
|
|
12795
13214
|
if (onlyPictures) replacements.push({ start: container.start, end: container.end, text: placed });
|
|
12796
13215
|
else {
|
|
12797
13216
|
for (const edit of edits) replacements.push({ start: edit.at, end: edit.at, text: edit.raw });
|
|
@@ -13064,8 +13483,8 @@ function starterTags(engine) {
|
|
|
13064
13483
|
codeFit: engine === "liquid" ? "{{ offer.url | qrcode }}" : "{{ qrcode(offer.url) }}"
|
|
13065
13484
|
};
|
|
13066
13485
|
}
|
|
13067
|
-
var paragraph = (
|
|
13068
|
-
var cell = (
|
|
13486
|
+
var paragraph = (text4, 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(text4)}</w:t></w:r></w:p>`;
|
|
13487
|
+
var cell = (text4, width, bold = false) => `<w:tc><w:tcPr><w:tcW w:w="${width}" w:type="dxa"/></w:tcPr>${paragraph(text4, void 0, bold)}</w:tc>`;
|
|
13069
13488
|
var row = (cells) => `<w:tr>${cells}</w:tr>`;
|
|
13070
13489
|
function starterDocument(engine) {
|
|
13071
13490
|
const t = starterTags(engine);
|
|
@@ -13108,7 +13527,7 @@ function starterDocument(engine) {
|
|
|
13108
13527
|
["word/document.xml", `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:document xmlns:w="${W}"><w:body>${body}</w:body></w:document>`]
|
|
13109
13528
|
];
|
|
13110
13529
|
return {
|
|
13111
|
-
bytes: writeZip(files.map(([name,
|
|
13530
|
+
bytes: writeZip(files.map(([name, text4]) => ({ name, data: encoder2.encode(text4) }))),
|
|
13112
13531
|
sampleData: starterSampleData()
|
|
13113
13532
|
};
|
|
13114
13533
|
}
|
|
@@ -13136,15 +13555,15 @@ var CM = 36e4;
|
|
|
13136
13555
|
var FONT = "Carlito";
|
|
13137
13556
|
var ACCENT = "0F766E";
|
|
13138
13557
|
var emptyTree = '<p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr><p:grpSpPr/>';
|
|
13139
|
-
var run = (
|
|
13140
|
-
var para = (
|
|
13558
|
+
var run = (text4, 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(text4)}</a:t></a:r>`;
|
|
13559
|
+
var para = (text4, size, options = {}) => `<a:p>${run(text4, size, options)}</a:p>`;
|
|
13141
13560
|
function textBox(id, name, x, y, cx, cy, paragraphs) {
|
|
13142
13561
|
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>`;
|
|
13143
13562
|
}
|
|
13144
|
-
function cell2(
|
|
13563
|
+
function cell2(text4, header) {
|
|
13145
13564
|
const fill = header ? `<a:solidFill><a:srgbClr val="${ACCENT}"/></a:solidFill>` : "<a:noFill/>";
|
|
13146
13565
|
const line2 = `<a:lnB w="6350"><a:solidFill><a:srgbClr val="BFBFBF"/></a:solidFill></a:lnB>`;
|
|
13147
|
-
return `<a:tc><a:txBody><a:bodyPr/><a:lstStyle/>${para(
|
|
13566
|
+
return `<a:tc><a:txBody><a:bodyPr/><a:lstStyle/>${para(text4, 14, header ? { bold: true, color: "FFFFFF" } : {})}</a:txBody><a:tcPr marL="91440" marR="91440" marT="45720" marB="45720">${line2}${fill}</a:tcPr></a:tc>`;
|
|
13148
13567
|
}
|
|
13149
13568
|
var tableRow = (a, b, header = false) => `<a:tr h="${Math.round(0.9 * CM)}">${cell2(a, header)}${cell2(b, header)}</a:tr>`;
|
|
13150
13569
|
function table2(id, x, y, rows) {
|
|
@@ -13234,7 +13653,7 @@ function starterPresentation(engine) {
|
|
|
13234
13653
|
];
|
|
13235
13654
|
const encoder2 = new TextEncoder();
|
|
13236
13655
|
return {
|
|
13237
|
-
bytes: writeZip(files.map(([name,
|
|
13656
|
+
bytes: writeZip(files.map(([name, text4]) => ({ name, data: encoder2.encode(text4) }))),
|
|
13238
13657
|
sampleData: starterSampleData()
|
|
13239
13658
|
};
|
|
13240
13659
|
}
|