@templatical/quality 0.8.0 → 0.8.1

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/dist/index.js CHANGED
@@ -24,45 +24,53 @@ var u = Object.defineProperty, d = (e, t) => {
24
24
  //#endregion
25
25
  //#region src/contrast.ts
26
26
  function m(e, t) {
27
- let n = g(e), r = g(t);
27
+ let n = h(e), r = h(t);
28
28
  if (!n || !r) return NaN;
29
- let i = v(n), a = v(r), o = Math.max(i, a), s = Math.min(i, a);
29
+ let i = _(n), a = _(r), o = Math.max(i, a), s = Math.min(i, a);
30
30
  return (o + .05) / (s + .05);
31
31
  }
32
- var ne = /^#?([0-9a-f])([0-9a-f])([0-9a-f])$/i, h = /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i;
33
- function g(e) {
32
+ var ne = /^#?([0-9a-f])([0-9a-f])([0-9a-f])$/i, re = /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i, ie = /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i;
33
+ function h(e) {
34
34
  if (typeof e != "string") return null;
35
- let t = e.trim(), n = h.exec(t);
36
- if (n) return {
35
+ let t = e.trim(), n = ie.exec(t);
36
+ if (n) return n[4].toLowerCase() === "ff" ? {
37
37
  r: parseInt(n[1], 16),
38
38
  g: parseInt(n[2], 16),
39
39
  b: parseInt(n[3], 16)
40
+ } : null;
41
+ let r = re.exec(t);
42
+ if (r) return {
43
+ r: parseInt(r[1], 16),
44
+ g: parseInt(r[2], 16),
45
+ b: parseInt(r[3], 16)
40
46
  };
41
- let r = ne.exec(t);
42
- return r ? {
43
- r: parseInt(r[1] + r[1], 16),
44
- g: parseInt(r[2] + r[2], 16),
45
- b: parseInt(r[3] + r[3], 16)
47
+ let i = ne.exec(t);
48
+ return i ? {
49
+ r: parseInt(i[1] + i[1], 16),
50
+ g: parseInt(i[2] + i[2], 16),
51
+ b: parseInt(i[3] + i[3], 16)
46
52
  } : null;
47
53
  }
48
- function _(e) {
49
- return g(e ?? "") !== null;
54
+ function g(e) {
55
+ return h(e ?? "") !== null;
50
56
  }
51
- function v({ r: e, g: t, b: n }) {
52
- let r = y(e / 255), i = y(t / 255), a = y(n / 255);
57
+ function _({ r: e, g: t, b: n }) {
58
+ let r = v(e / 255), i = v(t / 255), a = v(n / 255);
53
59
  return .2126 * r + .7152 * i + .0722 * a;
54
60
  }
55
- function y(e) {
61
+ function v(e) {
56
62
  return e <= .03928 ? e / 12.92 : ((e + .055) / 1.055) ** 2.4;
57
63
  }
58
64
  //#endregion
59
65
  //#region src/walk.ts
60
- var re = "#ffffff";
61
- function b(e, t) {
62
- let n = _(e.settings.backgroundColor) ? e.settings.backgroundColor.toLowerCase() : re, r = (e, n) => {
63
- if (t(e, n), !o(e)) return;
64
- let i = e.styles?.backgroundColor, a = _(i) ? i.toLowerCase() : n.resolvedBackgroundColor;
65
- e.children.forEach((t, i) => {
66
+ var ae = "#ffffff";
67
+ function y(e, t) {
68
+ let n = g(e.settings.backgroundColor) ? e.settings.backgroundColor.toLowerCase() : ae, r = (e, n) => {
69
+ let i = e.styles?.backgroundColor, a = g(i) ? i.toLowerCase() : n.resolvedBackgroundColor;
70
+ t(e, a === n.resolvedBackgroundColor ? n : {
71
+ ...n,
72
+ resolvedBackgroundColor: a
73
+ }), o(e) && e.children.forEach((t, i) => {
66
74
  t.forEach((t) => r(t, {
67
75
  parent: e,
68
76
  section: e,
@@ -82,53 +90,79 @@ function b(e, t) {
82
90
  }
83
91
  //#endregion
84
92
  //#region src/run-rules.ts
85
- function x(e, t, n, r) {
86
- if (n.disabled === !0) return [];
87
- let i = ie(n, t), a = [];
88
- function o(e, t, n) {
93
+ function b(e, t, n, r) {
94
+ let i = [];
95
+ function a(e, t, i) {
89
96
  return {
90
- blockId: n.blockId,
97
+ blockId: i.blockId,
91
98
  ruleId: e,
92
99
  severity: t,
93
- message: r(i.locale, e, n.params),
94
- fix: n.fix
100
+ message: r(n.locale, e, i.params),
101
+ fix: i.fix
95
102
  };
96
103
  }
97
- b(e, (e, n) => {
98
- for (let r of t) {
99
- let t = i.severity(r.meta.id);
100
- if (t === "off" || !r.block) continue;
101
- let s = r.block(e, n, i);
102
- s !== null && a.push(o(r.meta.id, t, s));
104
+ y(e, (e, r) => {
105
+ for (let o of t) {
106
+ let t = n.severity(o.meta.id);
107
+ if (t === "off" || !o.block) continue;
108
+ let s = o.block(e, r, n);
109
+ s !== null && i.push(a(o.meta.id, t, s));
103
110
  }
104
111
  });
105
- for (let n of t) {
106
- let t = i.severity(n.meta.id);
107
- if (t === "off" || !n.template) continue;
108
- let r = n.template(e, i);
109
- for (let e of r) a.push(o(n.meta.id, t, e));
112
+ for (let r of t) {
113
+ let t = n.severity(r.meta.id);
114
+ if (t === "off" || !r.template) continue;
115
+ let o = r.template(e, n);
116
+ for (let e of o) i.push(a(r.meta.id, t, e));
110
117
  }
111
- return a;
118
+ return i;
112
119
  }
113
- function ie(e, t) {
114
- let n = e.rules ?? {}, r = {
120
+ function x(e) {
121
+ let t = e.overrides ?? {}, n = {
115
122
  ...f,
116
123
  ...e.thresholds ?? {}
117
- }, i = { nonProductionHosts: e.links?.nonProductionHosts ?? p };
124
+ }, r = { nonProductionHosts: e.nonProductionHosts ?? p }, i = e.locale ?? "en", a = e.rules;
118
125
  return {
119
- locale: e.locale ?? "en",
120
- rules: n,
121
- thresholds: r,
122
- links: i,
126
+ locale: i,
127
+ rules: t,
128
+ thresholds: n,
129
+ links: r,
123
130
  severity: (e) => {
124
- let r = n[e];
125
- return r === void 0 ? t.find((t) => t.meta.id === e)?.meta.severity ?? "warning" : r;
131
+ let n = t[e];
132
+ return n === void 0 ? a.find((t) => t.meta.id === e)?.meta.severity ?? "warning" : n;
126
133
  }
127
134
  };
128
135
  }
136
+ function oe(e, t, n) {
137
+ return x({
138
+ locale: e,
139
+ rules: n,
140
+ overrides: t.rules,
141
+ thresholds: t.thresholds,
142
+ nonProductionHosts: void 0
143
+ });
144
+ }
145
+ function se(e, t, n) {
146
+ return x({
147
+ locale: e,
148
+ rules: n,
149
+ overrides: t.rules,
150
+ thresholds: void 0,
151
+ nonProductionHosts: void 0
152
+ });
153
+ }
154
+ function ce(e, t, n) {
155
+ return x({
156
+ locale: e,
157
+ rules: n,
158
+ overrides: t.rules,
159
+ thresholds: void 0,
160
+ nonProductionHosts: t.nonProductionHosts
161
+ });
162
+ }
129
163
  //#endregion
130
164
  //#region src/accessibility/messages/de.ts
131
- var ae = /* @__PURE__ */ d({ default: () => oe }), oe = {
165
+ var le = /* @__PURE__ */ d({ default: () => ue }), ue = {
132
166
  "a11y.img-missing-alt": "Bild ohne Alt-Text. Füge eine kurze Beschreibung hinzu oder markiere das Bild als dekorativ.",
133
167
  "a11y.img-alt-is-filename": "Alt-Text sieht wie ein Dateiname aus (\"{alt}\"). Beschreibe stattdessen kurz, was das Bild zeigt.",
134
168
  "a11y.img-alt-too-long": "Alt-Text ist {length} Zeichen lang; bleibe unter {max}.",
@@ -148,7 +182,7 @@ var ae = /* @__PURE__ */ d({ default: () => oe }), oe = {
148
182
  "a11y.button-touch-target": "Button ist etwa {height}px hoch; mindestens {min}px verwenden, um Fehltipper auf Mobilgeräten zu vermeiden.",
149
183
  "a11y.button-low-contrast": "Buttontextkontrast beträgt {ratio}:1; WCAG AA verlangt mindestens {required}:1.",
150
184
  "a11y.missing-preheader": "Kein Preheader-Text gesetzt. Postfächer zeigen sonst Bruchstücke des ersten Blocks an."
151
- }, se = /* @__PURE__ */ d({ default: () => S }), S = {
185
+ }, de = /* @__PURE__ */ d({ default: () => S }), S = {
152
186
  "a11y.img-missing-alt": "Image is missing alt text. Add a short description, or mark the image as decorative.",
153
187
  "a11y.img-alt-is-filename": "Alt text looks like a filename (\"{alt}\"). Replace with a short description of what the image conveys.",
154
188
  "a11y.img-alt-too-long": "Alt text is {length} characters; aim for under {max}.",
@@ -169,8 +203,8 @@ var ae = /* @__PURE__ */ d({ default: () => oe }), oe = {
169
203
  "a11y.button-low-contrast": "Button text contrast is {ratio}:1; WCAG AA requires at least {required}:1.",
170
204
  "a11y.missing-preheader": "No preheader text set. Inboxes will fall back to fragments of the first block."
171
205
  }, C = /* @__PURE__ */ Object.assign({
172
- "./de.ts": ae,
173
- "./en.ts": se
206
+ "./de.ts": le,
207
+ "./en.ts": de
174
208
  }), w = {};
175
209
  for (let e in C) {
176
210
  let t = /\.\/([^/]+)\.ts$/.exec(e);
@@ -178,7 +212,7 @@ for (let e in C) {
178
212
  let n = t[1];
179
213
  n !== "index" && (w[n] = C[e].default);
180
214
  }
181
- var ce = Object.keys(w);
215
+ var fe = Object.keys(w);
182
216
  function T(e) {
183
217
  return w[e.split("-")[0]?.toLowerCase() ?? "en"] ?? w.en ?? S;
184
218
  }
@@ -189,7 +223,7 @@ function E(e, t, n) {
189
223
  return r === void 0 ? `{${t}}` : String(r);
190
224
  }) : r;
191
225
  }
192
- var le = {
226
+ var pe = {
193
227
  meta: {
194
228
  id: "a11y.img-missing-alt",
195
229
  severity: "error"
@@ -197,30 +231,26 @@ var le = {
197
231
  block(e) {
198
232
  return !r(e) || e.decorative === !0 || (e.alt?.trim() ?? "") !== "" || (e.src ?? "").trim() === "" ? null : { blockId: e.id };
199
233
  }
200
- }, ue = {
234
+ }, me = {
201
235
  id: "a11y.img-alt-is-filename",
202
236
  severity: "warning"
203
- }, de = [
237
+ }, he = [
204
238
  /\.(jpe?g|png|gif|webp|svg)$/i,
205
239
  /^IMG[_-]?\d+/i,
206
240
  /^Untitled/i,
207
241
  /^Screen[\s_-]?Shot/i,
208
242
  /^DSC[_-]?\d+/i
209
- ], fe = {
210
- meta: ue,
243
+ ], ge = {
244
+ meta: me,
211
245
  block(e) {
212
246
  if (!r(e) || e.decorative === !0) return null;
213
247
  let t = e.alt?.trim() ?? "";
214
- return t === "" || !de.some((e) => e.test(t)) ? null : {
248
+ return t === "" || !he.some((e) => e.test(t)) ? null : {
215
249
  blockId: e.id,
216
- params: { alt: t },
217
- fix: {
218
- description: "Clear alt text",
219
- apply: (t) => t.updateBlock(e.id, { alt: "" })
220
- }
250
+ params: { alt: t }
221
251
  };
222
252
  }
223
- }, pe = {
253
+ }, _e = {
224
254
  meta: {
225
255
  id: "a11y.img-alt-too-long",
226
256
  severity: "warning"
@@ -236,13 +266,13 @@ var le = {
236
266
  }
237
267
  };
238
268
  }
239
- }, me = {
269
+ }, ve = {
240
270
  meta: {
241
271
  id: "a11y.img-decorative-needs-empty-alt",
242
272
  severity: "info"
243
273
  },
244
274
  block(e) {
245
- return !r(e) || e.decorative !== !0 || (e.alt ?? "") === "" ? null : {
275
+ return !r(e) || e.decorative !== !0 || (e.alt ?? "").trim() === "" ? null : {
246
276
  blockId: e.id,
247
277
  fix: {
248
278
  description: "Clear alt text",
@@ -250,7 +280,7 @@ var le = {
250
280
  }
251
281
  };
252
282
  }
253
- }, he = /* @__PURE__ */ d({ default: () => ge }), ge = {
283
+ }, ye = /* @__PURE__ */ d({ default: () => be }), be = {
254
284
  vagueLinkText: [
255
285
  "hier klicken",
256
286
  "hier",
@@ -293,7 +323,7 @@ var le = {
293
323
  "anschauen",
294
324
  "jetzt"
295
325
  ]
296
- }, _e = /* @__PURE__ */ d({ default: () => ve }), ve = {
326
+ }, xe = /* @__PURE__ */ d({ default: () => Se }), Se = {
297
327
  vagueLinkText: [
298
328
  "click here",
299
329
  "here",
@@ -335,8 +365,8 @@ var le = {
335
365
  "watch"
336
366
  ]
337
367
  }, D = /* @__PURE__ */ Object.assign({
338
- "./de.ts": he,
339
- "./en.ts": _e
368
+ "./de.ts": ye,
369
+ "./en.ts": xe
340
370
  }), O = {};
341
371
  for (let e in D) {
342
372
  let t = /\.\/([^/]+)\.ts$/.exec(e);
@@ -345,22 +375,22 @@ for (let e in D) {
345
375
  n !== "index" && (O[n] = D[e].default);
346
376
  }
347
377
  function k(e) {
348
- return ye;
378
+ return Ce;
349
379
  }
350
380
  function A(e) {
351
381
  let t = /* @__PURE__ */ new Set();
352
382
  for (let n of Object.values(O)) for (let r of e(n)) t.add(r);
353
383
  return Array.from(t);
354
384
  }
355
- var ye = {
385
+ var Ce = {
356
386
  vagueLinkText: A((e) => e.vagueLinkText),
357
387
  vagueButtonLabels: A((e) => e.vagueButtonLabels),
358
388
  linkedImageActionHints: A((e) => e.linkedImageActionHints)
359
- }, be = Object.keys(O);
389
+ }, we = Object.keys(O);
360
390
  function j(e) {
361
391
  return e.toLowerCase().replace(/\s+/g, " ").replace(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu, "").trim();
362
392
  }
363
- var xe = {
393
+ var Te = {
364
394
  meta: {
365
395
  id: "a11y.img-linked-no-context",
366
396
  severity: "warning"
@@ -412,7 +442,7 @@ function N(e) {
412
442
  } });
413
443
  return n.write(e), n.end(), t.trim();
414
444
  }
415
- var Se = {
445
+ var Ee = {
416
446
  meta: {
417
447
  id: "a11y.heading-empty",
418
448
  severity: "error"
@@ -420,7 +450,7 @@ var Se = {
420
450
  block(e) {
421
451
  return !c(e) || N(e.content ?? "") !== "" ? null : { blockId: e.id };
422
452
  }
423
- }, Ce = {
453
+ }, De = {
424
454
  id: "a11y.heading-skip-level",
425
455
  severity: "error"
426
456
  };
@@ -433,8 +463,8 @@ function P(e, t) {
433
463
  if (o(n)) for (let e of n.children) P(e, t);
434
464
  }
435
465
  }
436
- var we = {
437
- meta: Ce,
466
+ var Oe = {
467
+ meta: De,
438
468
  template(e) {
439
469
  let t = [];
440
470
  P(e.blocks, t);
@@ -448,7 +478,7 @@ var we = {
448
478
  }), r = e.level;
449
479
  return n;
450
480
  }
451
- }, Te = {
481
+ }, ke = {
452
482
  id: "a11y.heading-multiple-h1",
453
483
  severity: "warning"
454
484
  };
@@ -461,38 +491,38 @@ function F(e, t) {
461
491
  if (o(n)) for (let e of n.children) F(e, t);
462
492
  }
463
493
  }
464
- var Ee = {
465
- meta: Te,
494
+ var Ae = {
495
+ meta: ke,
466
496
  template(e) {
467
497
  let t = [];
468
498
  F(e.blocks, t);
469
499
  let n = t.filter((e) => e.level === 1);
470
500
  return n.length <= 1 ? [] : n.slice(1).map((e) => ({ blockId: e.id }));
471
501
  }
472
- }, De = {
502
+ }, je = {
473
503
  id: "a11y.link-empty",
474
504
  severity: "error"
475
505
  };
476
- function Oe(e) {
506
+ function Me(e) {
477
507
  return a(e) || c(e) ? e.content : null;
478
508
  }
479
- var ke = {
480
- meta: De,
509
+ var Ne = {
510
+ meta: je,
481
511
  block(e) {
482
- let t = Oe(e);
512
+ let t = Me(e);
483
513
  return t === null || !M(t).find((e) => e.text === "" && !e.hasImageWithAlt) ? null : { blockId: e.id };
484
514
  }
485
- }, Ae = {
515
+ }, Pe = {
486
516
  id: "a11y.link-vague-text",
487
517
  severity: "warning"
488
518
  };
489
- function je(e) {
519
+ function Fe(e) {
490
520
  return a(e) || c(e) ? e.content : null;
491
521
  }
492
- var Me = {
493
- meta: Ae,
522
+ var Ie = {
523
+ meta: Pe,
494
524
  block(e, t, n) {
495
- let r = je(e);
525
+ let r = Fe(e);
496
526
  if (r === null) return null;
497
527
  let i = k(n.locale).vagueLinkText, a = M(r).find((e) => {
498
528
  let t = j(e.text);
@@ -503,52 +533,52 @@ var Me = {
503
533
  params: { text: a.text }
504
534
  } : null;
505
535
  }
506
- }, Ne = {
536
+ }, Le = {
507
537
  id: "a11y.link-href-empty",
508
538
  severity: "error"
509
539
  };
510
- function Pe(e) {
540
+ function Re(e) {
511
541
  return a(e) || c(e) ? e.content : null;
512
542
  }
513
- var Fe = {
514
- meta: Ne,
543
+ var ze = {
544
+ meta: Le,
515
545
  block(e) {
516
- let t = Pe(e);
546
+ let t = Re(e);
517
547
  return t === null || !M(t).find((e) => {
518
548
  let t = e.href.trim();
519
549
  return t === "" || t === "#";
520
550
  }) ? null : { blockId: e.id };
521
551
  }
522
- }, Ie = {
552
+ }, Be = {
523
553
  id: "a11y.link-target-blank-no-rel",
524
554
  severity: "warning"
525
555
  };
526
- function Le(e) {
556
+ function Ve(e) {
527
557
  return a(e) || c(e) ? e.content : null;
528
558
  }
529
- function Re(e) {
559
+ function He(e) {
530
560
  if (e === null) return !1;
531
561
  let t = e.toLowerCase().split(/\s+/);
532
562
  return t.includes("noopener") || t.includes("noreferrer");
533
563
  }
534
- var ze = {
535
- meta: Ie,
564
+ var Ue = {
565
+ meta: Be,
536
566
  block(e) {
537
- let t = Le(e);
538
- return t === null || !M(t).find((e) => e.target === "_blank" && !Re(e.rel)) ? null : {
567
+ let t = Ve(e);
568
+ return t === null || !M(t).find((e) => e.target === "_blank" && !He(e.rel)) ? null : {
539
569
  blockId: e.id,
540
570
  fix: {
541
571
  description: "Add rel=\"noopener\"",
542
572
  apply: (t) => {
543
573
  if (!a(e) && !c(e)) return;
544
- let n = He(e.content ?? "");
574
+ let n = Ke(e.content ?? "");
545
575
  t.updateBlock(e.id, { content: n });
546
576
  }
547
577
  }
548
578
  };
549
579
  }
550
580
  }, I = /([^\s"'>/=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
551
- function Be(e) {
581
+ function We(e) {
552
582
  let t = [], n = new RegExp(I.source, I.flags), r;
553
583
  for (; (r = n.exec(e)) !== null;) {
554
584
  let e = r[2] ?? r[3] ?? r[4] ?? null;
@@ -561,13 +591,13 @@ function Be(e) {
561
591
  }
562
592
  return t;
563
593
  }
564
- function Ve(e) {
594
+ function Ge(e) {
565
595
  return e.some((e) => e.name.toLowerCase() === "target" && e.value !== null && e.value.toLowerCase() === "_blank");
566
596
  }
567
- function He(e) {
597
+ function Ke(e) {
568
598
  return e.replace(/<a\b([^>]*)>/gi, (e, t) => {
569
- let n = Be(t);
570
- if (!Ve(n)) return e;
599
+ let n = We(t);
600
+ if (!Ge(n)) return e;
571
601
  let r = n.find((e) => e.name.toLowerCase() === "rel");
572
602
  if (r) {
573
603
  let n = (r.value ?? "").toLowerCase().split(/\s+/);
@@ -578,7 +608,7 @@ function He(e) {
578
608
  return `<a${t} rel="noopener">`;
579
609
  });
580
610
  }
581
- var Ue = {
611
+ var qe = {
582
612
  meta: {
583
613
  id: "a11y.text-all-caps",
584
614
  severity: "warning"
@@ -588,13 +618,13 @@ var Ue = {
588
618
  let r = N(e.content ?? "").replace(/[^\p{L}]/gu, "");
589
619
  return r.length < n.thresholds.allCapsMinLength || r !== r.toLocaleUpperCase() ? null : { blockId: e.id };
590
620
  }
591
- }, We = {
621
+ }, Je = {
592
622
  meta: {
593
623
  id: "a11y.text-low-contrast",
594
624
  severity: "error"
595
625
  },
596
626
  block(t, n) {
597
- if (!c(t) || !_(t.color) || !_(n.resolvedBackgroundColor)) return null;
627
+ if (!c(t) || !g(t.color) || !g(n.resolvedBackgroundColor)) return null;
598
628
  let r = e[t.level] >= 24 ? 3 : 4.5, i = m(t.color, n.resolvedBackgroundColor);
599
629
  return Number.isNaN(i) || i >= r ? null : {
600
630
  blockId: t.id,
@@ -604,34 +634,34 @@ var Ue = {
604
634
  }
605
635
  };
606
636
  }
607
- }, Ge = {
637
+ }, Ye = {
608
638
  id: "a11y.text-too-small",
609
639
  severity: "warning"
610
640
  };
611
- function Ke(e) {
641
+ function Xe(e) {
612
642
  return i(e) || ee(e) ? e.fontSize : null;
613
643
  }
614
644
  //#endregion
615
645
  //#region src/accessibility/index.ts
616
646
  var L = [
617
- le,
618
- fe,
619
647
  pe,
620
- me,
621
- xe,
622
- Se,
623
- we,
648
+ ge,
649
+ _e,
650
+ ve,
651
+ Te,
624
652
  Ee,
625
- ke,
626
- Me,
627
- Fe,
653
+ Oe,
654
+ Ae,
655
+ Ne,
656
+ Ie,
628
657
  ze,
629
658
  Ue,
630
- We,
659
+ qe,
660
+ Je,
631
661
  {
632
- meta: Ge,
662
+ meta: Ye,
633
663
  block(e, t, n) {
634
- let r = Ke(e);
664
+ let r = Xe(e);
635
665
  return r === null || r >= n.thresholds.minFontSize ? null : {
636
666
  blockId: e.id,
637
667
  params: {
@@ -703,26 +733,28 @@ var L = [
703
733
  }
704
734
  }
705
735
  ];
706
- function qe(e, t = {}) {
707
- return x(e, L, t, (e, t, n) => E(e, t, n));
736
+ function Ze(e, t = {}) {
737
+ if (t.disabled === !0 || t.accessibility === !1) return [];
738
+ let n = t.accessibility ?? {};
739
+ return b(e, L, oe(t.locale, n, L), (e, t, n) => E(e, t, n));
708
740
  }
709
741
  //#endregion
710
742
  //#region src/structure/messages/de.ts
711
- var Je = /* @__PURE__ */ d({ default: () => Ye }), Ye = {
743
+ var Qe = /* @__PURE__ */ d({ default: () => $e }), $e = {
712
744
  "structure.duplicate-block-id": "Block-ID erscheint {count}-mal im Baum. Jeder Block muss eine eindeutige ID haben.",
713
745
  "structure.section-column-mismatch": "Sektion verwendet Layout „{layout}\" (erwartet {expected} Spalten), hat aber {actual}. Deutet auf beschädigten Zustand hin.",
714
746
  "structure.nested-section": "Sektion ist in einer anderen Sektion verschachtelt. Sektionen können nicht verschachtelt werden – der Renderer wird sich falsch verhalten.",
715
747
  "structure.empty-section": "Sektion enthält keine Blöcke. Entferne sie oder füge Inhalt hinzu.",
716
748
  "structure.empty-column": "Spalte {columnIndex} dieser Sektion ist leer. Füge Inhalt hinzu oder reduziere die Spaltenanzahl."
717
- }, Xe = /* @__PURE__ */ d({ default: () => R }), R = {
749
+ }, et = /* @__PURE__ */ d({ default: () => R }), R = {
718
750
  "structure.duplicate-block-id": "Block id appears {count} times in the tree. Each block must have a unique id.",
719
751
  "structure.section-column-mismatch": "Section uses layout \"{layout}\" (expects {expected} columns) but has {actual}. Indicates corrupted state.",
720
752
  "structure.nested-section": "Section is nested inside another section. Sections cannot nest — the renderer will misbehave.",
721
753
  "structure.empty-section": "Section has no blocks. Remove it or add content.",
722
754
  "structure.empty-column": "Column {columnIndex} of this section is empty. Add content or reduce the column count."
723
755
  }, z = /* @__PURE__ */ Object.assign({
724
- "./de.ts": Je,
725
- "./en.ts": Xe
756
+ "./de.ts": Qe,
757
+ "./en.ts": et
726
758
  }), B = {};
727
759
  for (let e in z) {
728
760
  let t = /\.\/([^/]+)\.ts$/.exec(e);
@@ -730,7 +762,7 @@ for (let e in z) {
730
762
  let n = t[1];
731
763
  n !== "index" && (B[n] = z[e].default);
732
764
  }
733
- var Ze = Object.keys(B);
765
+ var tt = Object.keys(B);
734
766
  function V(e) {
735
767
  return B[e.split("-")[0]?.toLowerCase() ?? "en"] ?? B.en ?? R;
736
768
  }
@@ -743,15 +775,15 @@ function H(e, t, n) {
743
775
  }
744
776
  //#endregion
745
777
  //#region src/structure/rules/duplicate-block-id.ts
746
- var Qe = {
778
+ var nt = {
747
779
  id: "structure.duplicate-block-id",
748
780
  severity: "error"
749
781
  };
750
782
  function U(e, t) {
751
783
  for (let n of e) if (t.set(n.id, (t.get(n.id) ?? 0) + 1), o(n)) for (let e of n.children) U(e, t);
752
784
  }
753
- var $e = {
754
- meta: Qe,
785
+ var rt = {
786
+ meta: nt,
755
787
  template(e) {
756
788
  let t = /* @__PURE__ */ new Map();
757
789
  U(e.blocks, t);
@@ -762,7 +794,7 @@ var $e = {
762
794
  });
763
795
  return n;
764
796
  }
765
- }, et = {
797
+ }, it = {
766
798
  id: "structure.empty-column",
767
799
  severity: "warning"
768
800
  };
@@ -779,25 +811,25 @@ function W(e, t) {
779
811
  for (let n of e.children) W(n, t);
780
812
  }
781
813
  }
782
- var tt = {
783
- meta: et,
814
+ var at = {
815
+ meta: it,
784
816
  template(e) {
785
817
  let t = [];
786
818
  return W(e.blocks, t), t;
787
819
  }
788
- }, nt = {
820
+ }, ot = {
789
821
  id: "structure.empty-section",
790
822
  severity: "warning"
791
823
  };
792
- function rt(e) {
824
+ function st(e) {
793
825
  return e.children.length === 0 ? !0 : e.children.every((e) => e.length === 0);
794
826
  }
795
- var it = {
796
- meta: nt,
827
+ var ct = {
828
+ meta: ot,
797
829
  block(e) {
798
830
  if (!o(e)) return null;
799
831
  let t = e;
800
- return rt(t) ? {
832
+ return st(t) ? {
801
833
  blockId: t.id,
802
834
  fix: {
803
835
  description: "Remove the empty section",
@@ -807,7 +839,7 @@ var it = {
807
839
  }
808
840
  } : null;
809
841
  }
810
- }, at = {
842
+ }, lt = {
811
843
  meta: {
812
844
  id: "structure.nested-section",
813
845
  severity: "error"
@@ -820,25 +852,25 @@ var it = {
820
852
  params: { parentId: n.id }
821
853
  };
822
854
  }
823
- }, ot = {
855
+ }, ut = {
824
856
  id: "structure.section-column-mismatch",
825
857
  severity: "error"
826
858
  };
827
- function st(e) {
859
+ function dt(e) {
828
860
  return e === "1" ? 1 : e === "3" ? 3 : 2;
829
861
  }
830
862
  //#endregion
831
863
  //#region src/structure/index.ts
832
864
  var G = [
833
- $e,
834
- it,
835
- tt,
865
+ rt,
866
+ ct,
836
867
  at,
868
+ lt,
837
869
  {
838
- meta: ot,
870
+ meta: ut,
839
871
  block(e) {
840
872
  if (!o(e)) return null;
841
- let t = e, n = st(t.columns), r = t.children.length;
873
+ let t = e, n = dt(t.columns), r = t.children.length;
842
874
  return r === n ? null : {
843
875
  blockId: t.id,
844
876
  params: {
@@ -850,26 +882,28 @@ var G = [
850
882
  }
851
883
  }
852
884
  ];
853
- function ct(e, t = {}) {
854
- return x(e, G, t, (e, t, n) => H(e, t, n));
885
+ function ft(e, t = {}) {
886
+ if (t.disabled === !0 || t.structure === !1) return [];
887
+ let n = t.structure ?? {};
888
+ return b(e, G, se(t.locale, n, G), (e, t, n) => H(e, t, n));
855
889
  }
856
890
  //#endregion
857
891
  //#region src/links/messages/de.ts
858
- var lt = /* @__PURE__ */ d({ default: () => ut }), ut = {
892
+ var pt = /* @__PURE__ */ d({ default: () => mt }), mt = {
859
893
  "link.javascript-protocol": "Die URL verwendet das „javascript:\"-Protokoll, das aus Sicherheitsgründen beim Rendern entfernt wird. Ersetze sie durch eine echte URL oder entferne sie.",
860
894
  "link.unsupported-protocol": "Die URL verwendet das Protokoll „{protocol}\", das von den meisten E-Mail-Clients nicht unterstützt wird. Verwende http, https, mailto, tel oder sms.",
861
895
  "link.malformed-mailto": "Der mailto:-Link ist fehlerhaft. Erwartet wird eine einzelne Empfängeradresse vor einer eventuellen Querystring (z. B. mailto:hallo@example.com).",
862
896
  "link.malformed-tel": "Der tel:-Link enthält Zeichen, die keine Ziffern, +, Leerzeichen, Bindestriche, Klammern oder Punkte sind.",
863
897
  "link.localhost-or-staging": "Der URL-Host „{host}\" entspricht einem Nicht-Produktionsmuster. Ersetze ihn vor dem Versand durch die Produktions-URL."
864
- }, dt = /* @__PURE__ */ d({ default: () => K }), K = {
898
+ }, ht = /* @__PURE__ */ d({ default: () => K }), K = {
865
899
  "link.javascript-protocol": "URL uses the \"javascript:\" protocol, which is stripped at render time for safety. Replace it with a real link or remove the URL.",
866
900
  "link.unsupported-protocol": "URL uses the \"{protocol}\" protocol, which most email clients do not support. Use http, https, mailto, tel, or sms.",
867
901
  "link.malformed-mailto": "mailto: link is malformed. Expected a single recipient address before any query string (e.g. mailto:hello@example.com).",
868
902
  "link.malformed-tel": "tel: link contains characters that are not digits, +, spaces, dashes, parentheses, or dots.",
869
903
  "link.localhost-or-staging": "URL host \"{host}\" matches a non-production pattern. Replace with the production URL before sending."
870
904
  }, q = /* @__PURE__ */ Object.assign({
871
- "./de.ts": lt,
872
- "./en.ts": dt
905
+ "./de.ts": pt,
906
+ "./en.ts": ht
873
907
  }), J = {};
874
908
  for (let e in q) {
875
909
  let t = /\.\/([^/]+)\.ts$/.exec(e);
@@ -877,7 +911,7 @@ for (let e in q) {
877
911
  let n = t[1];
878
912
  n !== "index" && (J[n] = q[e].default);
879
913
  }
880
- var ft = Object.keys(J);
914
+ var gt = Object.keys(J);
881
915
  function Y(e) {
882
916
  return J[e.split("-")[0]?.toLowerCase() ?? "en"] ?? J.en ?? K;
883
917
  }
@@ -892,7 +926,7 @@ function X(e, t, n) {
892
926
  //#region src/url-walker.ts
893
927
  function Z(e) {
894
928
  let o = [];
895
- return b(e, (e) => {
929
+ return y(e, (e) => {
896
930
  if (c(e) || a(e) || n(e)) {
897
931
  for (let t of M(e.content)) o.push({
898
932
  url: t.href,
@@ -951,55 +985,55 @@ function Z(e) {
951
985
  }
952
986
  //#endregion
953
987
  //#region src/links/rules/javascript-protocol.ts
954
- var pt = {
988
+ var _t = {
955
989
  id: "link.javascript-protocol",
956
990
  severity: "error"
957
991
  };
958
- function mt(e) {
992
+ function vt(e) {
959
993
  if (!e) return !1;
960
994
  let t = e.replace(/\s+/g, "");
961
995
  return /^javascript:/i.test(t);
962
996
  }
963
- var ht = {
964
- meta: pt,
997
+ var yt = {
998
+ meta: _t,
965
999
  template(e) {
966
1000
  let t = [];
967
- for (let n of Z(e)) mt(n.url) && t.push({ blockId: n.blockId });
1001
+ for (let n of Z(e)) vt(n.url) && t.push({ blockId: n.blockId });
968
1002
  return t;
969
1003
  }
970
- }, gt = {
1004
+ }, bt = {
971
1005
  id: "link.unsupported-protocol",
972
1006
  severity: "warning"
973
- }, _t = new Set([
1007
+ }, xt = new Set([
974
1008
  "http",
975
1009
  "https",
976
1010
  "mailto",
977
1011
  "tel",
978
1012
  "sms"
979
1013
  ]);
980
- function vt(e) {
1014
+ function St(e) {
981
1015
  if (!e) return null;
982
1016
  let t = e.trim(), n = /^([a-z][a-z0-9+\-.]*):/i.exec(t);
983
1017
  return n ? n[1].toLowerCase() : null;
984
1018
  }
985
- var yt = {
986
- meta: gt,
1019
+ var Ct = {
1020
+ meta: bt,
987
1021
  template(e) {
988
1022
  let t = [];
989
1023
  for (let n of Z(e)) {
990
- let e = vt(n.url);
991
- e !== null && e !== "javascript" && (_t.has(e) || t.push({
1024
+ let e = St(n.url);
1025
+ e !== null && e !== "javascript" && (xt.has(e) || t.push({
992
1026
  blockId: n.blockId,
993
1027
  params: { protocol: e }
994
1028
  }));
995
1029
  }
996
1030
  return t;
997
1031
  }
998
- }, bt = {
1032
+ }, wt = {
999
1033
  id: "link.malformed-mailto",
1000
1034
  severity: "warning"
1001
1035
  };
1002
- function Q(e) {
1036
+ function Tt(e) {
1003
1037
  let t = e.trim();
1004
1038
  if (!/^mailto:/i.test(t)) return !1;
1005
1039
  let [n] = t.slice(7).split("?", 2);
@@ -1014,39 +1048,41 @@ function Q(e) {
1014
1048
  }
1015
1049
  return !1;
1016
1050
  }
1017
- var xt = {
1018
- meta: bt,
1051
+ var Et = {
1052
+ meta: wt,
1019
1053
  template(e) {
1020
1054
  let t = [];
1021
- for (let n of Z(e)) Q(n.url) && t.push({ blockId: n.blockId });
1055
+ for (let n of Z(e)) Tt(n.url) && t.push({ blockId: n.blockId });
1022
1056
  return t;
1023
1057
  }
1024
- }, St = {
1058
+ }, Dt = {
1025
1059
  id: "link.malformed-tel",
1026
1060
  severity: "warning"
1027
- }, Ct = /^[+0-9\s().\-]+$/;
1028
- function wt(e) {
1061
+ }, Q = /^[+0-9\s().\-]+$/, Ot = /^[A-Za-z0-9-]+(=[^;]+)?$/;
1062
+ function kt(e) {
1029
1063
  let t = e.trim();
1030
1064
  if (!/^tel:/i.test(t)) return !1;
1031
1065
  let n = t.slice(4).trim();
1032
- return n === "" ? !0 : !Ct.test(n);
1066
+ if (n === "") return !0;
1067
+ let [r, ...i] = n.split(";");
1068
+ return Q.test(r) ? i.some((e) => !Ot.test(e)) : !0;
1033
1069
  }
1034
- var Tt = {
1035
- meta: St,
1070
+ var At = {
1071
+ meta: Dt,
1036
1072
  template(e) {
1037
1073
  let t = [];
1038
- for (let n of Z(e)) wt(n.url) && t.push({ blockId: n.blockId });
1074
+ for (let n of Z(e)) kt(n.url) && t.push({ blockId: n.blockId });
1039
1075
  return t;
1040
1076
  }
1041
- }, Et = {
1077
+ }, jt = {
1042
1078
  id: "link.localhost-or-staging",
1043
1079
  severity: "warning"
1044
1080
  };
1045
- function Dt(e) {
1081
+ function Mt(e) {
1046
1082
  let t = e.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
1047
1083
  return RegExp(`^${t}$`, "i");
1048
1084
  }
1049
- function Ot(e) {
1085
+ function Nt(e) {
1050
1086
  if (!e) return null;
1051
1087
  let t = e.trim();
1052
1088
  if (!/^(https?|ftps?):\/\//i.test(t)) return null;
@@ -1059,18 +1095,18 @@ function Ot(e) {
1059
1095
  //#endregion
1060
1096
  //#region src/links/index.ts
1061
1097
  var $ = [
1062
- ht,
1063
1098
  yt,
1064
- xt,
1065
- Tt,
1099
+ Ct,
1100
+ Et,
1101
+ At,
1066
1102
  {
1067
- meta: Et,
1103
+ meta: jt,
1068
1104
  template(e, t) {
1069
1105
  let n = t.links.nonProductionHosts;
1070
1106
  if (n.length === 0) return [];
1071
- let r = n.map(Dt), i = [];
1107
+ let r = n.map(Mt), i = [];
1072
1108
  for (let t of Z(e)) {
1073
- let e = Ot(t.url);
1109
+ let e = Nt(t.url);
1074
1110
  e !== null && r.some((t) => t.test(e)) && i.push({
1075
1111
  blockId: t.blockId,
1076
1112
  params: { host: e }
@@ -1080,10 +1116,17 @@ var $ = [
1080
1116
  }
1081
1117
  }
1082
1118
  ];
1083
- function kt(e, t = {}) {
1084
- return x(e, $, t, (e, t, n) => X(e, t, n));
1119
+ function Pt(e, t = {}) {
1120
+ if (t.disabled === !0 || t.links === !1) return [];
1121
+ let n = t.links ?? {};
1122
+ return b(e, $, ce(t.locale, n, $), (e, t, n) => X(e, t, n));
1123
+ }
1124
+ //#endregion
1125
+ //#region src/util.ts
1126
+ function Ft(e) {
1127
+ return e ? e.disabled === !0 ? !0 : e.accessibility === !1 && e.structure === !1 && e.links === !1 : !1;
1085
1128
  }
1086
1129
  //#endregion
1087
- export { L as ACCESSIBILITY_RULES, f as DEFAULT_A11Y_THRESHOLDS, p as DEFAULT_NON_PRODUCTION_HOSTS, $ as LINK_RULES, G as STRUCTURE_RULES, be as SUPPORTED_DICTIONARY_LOCALES, ft as SUPPORTED_LINK_MESSAGE_LOCALES, ce as SUPPORTED_MESSAGE_LOCALES, Ze as SUPPORTED_STRUCTURE_MESSAGE_LOCALES, M as extractAnchors, N as extractText, X as formatLinkMessage, E as formatMessage, H as formatStructureMessage, m as getContrastRatio, k as getDictionary, Y as getLinkMessages, T as getMessages, V as getStructureMessages, _ as isOpaqueHex, qe as lintAccessibility, kt as lintLinks, ct as lintStructure, g as parseHex, b as walkBlocks, Z as walkUrls };
1130
+ export { L as ACCESSIBILITY_RULES, f as DEFAULT_A11Y_THRESHOLDS, p as DEFAULT_NON_PRODUCTION_HOSTS, $ as LINK_RULES, G as STRUCTURE_RULES, we as SUPPORTED_DICTIONARY_LOCALES, gt as SUPPORTED_LINK_MESSAGE_LOCALES, fe as SUPPORTED_MESSAGE_LOCALES, tt as SUPPORTED_STRUCTURE_MESSAGE_LOCALES, M as extractAnchors, N as extractText, X as formatLinkMessage, E as formatMessage, H as formatStructureMessage, m as getContrastRatio, k as getDictionary, Y as getLinkMessages, T as getMessages, V as getStructureMessages, Ft as isLintFullyDisabled, g as isOpaqueHex, Ze as lintAccessibility, Pt as lintLinks, ft as lintStructure, h as parseHex, y as walkBlocks, Z as walkUrls };
1088
1131
 
1089
1132
  //# sourceMappingURL=index.js.map