html-validate 11.5.3 → 11.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/cjs/cli.js +11 -14
  2. package/dist/cjs/cli.js.map +1 -1
  3. package/dist/cjs/core-browser.js +4 -4
  4. package/dist/cjs/core-browser.js.map +1 -1
  5. package/dist/cjs/core-nodejs.js +17 -25
  6. package/dist/cjs/core-nodejs.js.map +1 -1
  7. package/dist/cjs/core.js +424 -435
  8. package/dist/cjs/core.js.map +1 -1
  9. package/dist/cjs/elements.js +11 -22
  10. package/dist/cjs/elements.js.map +1 -1
  11. package/dist/cjs/html-validate.js +1 -1
  12. package/dist/cjs/html-validate.js.map +1 -1
  13. package/dist/cjs/jest-matchers.js +49 -55
  14. package/dist/cjs/jest-matchers.js.map +1 -1
  15. package/dist/cjs/jest-utils.js +1 -2
  16. package/dist/cjs/jest-utils.js.map +1 -1
  17. package/dist/cjs/jest-worker.js.map +1 -1
  18. package/dist/cjs/test-utils.js +1 -2
  19. package/dist/cjs/test-utils.js.map +2 -2
  20. package/dist/cjs/tsdoc-metadata.json +1 -1
  21. package/dist/cjs/utils/parse-image-candidate-string.js +2 -2
  22. package/dist/cjs/utils/parse-image-candidate-string.js.map +1 -1
  23. package/dist/cjs/vitest-matchers.js +46 -50
  24. package/dist/cjs/vitest-matchers.js.map +1 -1
  25. package/dist/cjs/vitest-utils.js +1 -2
  26. package/dist/cjs/vitest-utils.js.map +1 -1
  27. package/dist/cjs/vitest-worker.js.map +1 -1
  28. package/dist/esm/cli.js +11 -14
  29. package/dist/esm/cli.js.map +1 -1
  30. package/dist/esm/core-browser.js +4 -4
  31. package/dist/esm/core-browser.js.map +1 -1
  32. package/dist/esm/core-nodejs.js +17 -25
  33. package/dist/esm/core-nodejs.js.map +1 -1
  34. package/dist/esm/core.js +424 -435
  35. package/dist/esm/core.js.map +1 -1
  36. package/dist/esm/elements.js +11 -22
  37. package/dist/esm/elements.js.map +1 -1
  38. package/dist/esm/html-validate.js +1 -1
  39. package/dist/esm/html-validate.js.map +1 -1
  40. package/dist/esm/jest-matchers.js +49 -55
  41. package/dist/esm/jest-matchers.js.map +1 -1
  42. package/dist/esm/jest-utils.js +1 -2
  43. package/dist/esm/jest-utils.js.map +1 -1
  44. package/dist/esm/jest-worker.js.map +1 -1
  45. package/dist/esm/test-utils.js +1 -2
  46. package/dist/esm/test-utils.js.map +2 -2
  47. package/dist/esm/utils/parse-image-candidate-string.js +2 -2
  48. package/dist/esm/utils/parse-image-candidate-string.js.map +1 -1
  49. package/dist/esm/vitest-matchers.js +46 -50
  50. package/dist/esm/vitest-matchers.js.map +1 -1
  51. package/dist/esm/vitest-utils.js +1 -2
  52. package/dist/esm/vitest-utils.js.map +1 -1
  53. package/dist/esm/vitest-worker.js.map +1 -1
  54. package/dist/tsdoc-metadata.json +1 -1
  55. package/dist/types/browser.d.ts +23 -11
  56. package/dist/types/index.d.ts +25 -13
  57. package/package.json +1 -1
package/dist/esm/core.js CHANGED
@@ -388,11 +388,11 @@ var deepmerge = /*@__PURE__*/getDefaultExportFromCjs(cjsExports);
388
388
  function stringify(value) {
389
389
  if (typeof value === "string") {
390
390
  return value;
391
- } else {
392
- return JSON.stringify(value);
393
391
  }
392
+ return JSON.stringify(value);
394
393
  }
395
394
  class WrappedError extends Error {
395
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
396
396
  constructor(message) {
397
397
  super(stringify(message));
398
398
  this.name = "WrappedError";
@@ -402,12 +402,12 @@ class WrappedError extends Error {
402
402
  function ensureError(value) {
403
403
  if (value instanceof Error) {
404
404
  return value;
405
- } else {
406
- return new WrappedError(value);
407
405
  }
406
+ return new WrappedError(value);
408
407
  }
409
408
 
410
409
  class NestedError extends Error {
410
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
411
411
  constructor(message, nested) {
412
412
  super(message);
413
413
  this.name = "NestedError";
@@ -420,6 +420,7 @@ Caused by: ${nested.stack}`;
420
420
  }
421
421
 
422
422
  class UserError extends NestedError {
423
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
423
424
  constructor(message, nested) {
424
425
  super(message, nested);
425
426
  this.name = "UserError";
@@ -1120,11 +1121,11 @@ const CONTROL_ESCAPES = /* @__PURE__ */ new Map([
1120
1121
  ["\r", "r"]
1121
1122
  ]);
1122
1123
  const OTHER_PUNCTUATORS = /^[!"#%&',:;<=>@`~-]$/;
1123
- const WHITE_SPACE = /^[\t\v\f\uFEFF\p{Zs}]$/u;
1124
+ const WHITE_SPACE = /^[\t\v\f\u{FEFF}\p{Zs}]$/u;
1124
1125
  const LINE_TERMINATOR = /^[\n\r\u2028\u2029]$/;
1125
1126
  const SURROGATE = /^[\uD800-\uDFFF]$/;
1126
1127
  function isDecimalDigitOrASCIILetter(ch) {
1127
- return /^[\dA-Za-z]$/.test(ch);
1128
+ return /^[\dA-Z]$/i.test(ch);
1128
1129
  }
1129
1130
  function needEscape(ch) {
1130
1131
  return OTHER_PUNCTUATORS.test(ch) || WHITE_SPACE.test(ch) || LINE_TERMINATOR.test(ch) || SURROGATE.test(ch);
@@ -1192,9 +1193,8 @@ function migrateSingleAttribute(src, key) {
1192
1193
  }
1193
1194
  }
1194
1195
  return stripUndefined(result);
1195
- } else {
1196
- return stripUndefined({ ...result, ...attr });
1197
1196
  }
1197
+ return stripUndefined({ ...result, ...attr });
1198
1198
  }
1199
1199
  function isPatternAttribute$1(key) {
1200
1200
  return key.includes("*");
@@ -1208,7 +1208,7 @@ function migrateAttributes(src) {
1208
1208
  ...Object.keys(src.attributes ?? {}),
1209
1209
  ...src.requiredAttributes ?? [],
1210
1210
  ...src.deprecatedAttributes ?? []
1211
- ].filter((key) => !isPatternAttribute$1(key)).toSorted();
1211
+ ].filter((key) => !isPatternAttribute$1(key)).toSorted((a, b) => a.localeCompare(b));
1212
1212
  const entries = keys.map((key) => {
1213
1213
  return [key, migrateSingleAttribute(src, key)];
1214
1214
  });
@@ -1288,11 +1288,10 @@ const dynamicKeys = [
1288
1288
  ];
1289
1289
  const schemaCache = /* @__PURE__ */ new Map();
1290
1290
  function clone(value) {
1291
- if (globalThis.structuredClone) {
1292
- return globalThis.structuredClone(value);
1293
- } else {
1294
- return JSON.parse(JSON.stringify(value));
1291
+ if (Object.hasOwn(globalThis, "structuredClone")) {
1292
+ return structuredClone(value);
1295
1293
  }
1294
+ return JSON.parse(JSON.stringify(value));
1296
1295
  }
1297
1296
  class MetaTable {
1298
1297
  elements;
@@ -1382,9 +1381,8 @@ class MetaTable {
1382
1381
  const meta = this.elements[tagName.toLowerCase()] ?? this.elements["*"];
1383
1382
  if (meta) {
1384
1383
  return { ...meta };
1385
- } else {
1386
- return null;
1387
1384
  }
1385
+ return null;
1388
1386
  }
1389
1387
  /**
1390
1388
  * Find all tags which has enabled given property.
@@ -1426,16 +1424,15 @@ class MetaTable {
1426
1424
  const cached = schemaCache.get(hash);
1427
1425
  if (cached) {
1428
1426
  return cached;
1429
- } else {
1430
- const ajv = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
1431
- ajv.addMetaSchema(ajvSchemaDraft);
1432
- ajv.addKeyword(ajvFunctionKeyword);
1433
- ajv.addKeyword(ajvRegexpKeyword);
1434
- ajv.addKeyword({ keyword: "copyable" });
1435
- const validate = ajv.compile(this.schema);
1436
- schemaCache.set(hash, validate);
1437
- return validate;
1438
1427
  }
1428
+ const ajv = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
1429
+ ajv.addMetaSchema(ajvSchemaDraft);
1430
+ ajv.addKeyword(ajvFunctionKeyword);
1431
+ ajv.addKeyword(ajvRegexpKeyword);
1432
+ ajv.addKeyword({ keyword: "copyable" });
1433
+ const validate = ajv.compile(this.schema);
1434
+ schemaCache.set(hash, validate);
1435
+ return validate;
1439
1436
  }
1440
1437
  /**
1441
1438
  * @public
@@ -1517,14 +1514,13 @@ function expandProperties(node, entry) {
1517
1514
  }
1518
1515
  }
1519
1516
  function compileRegexString(value) {
1520
- const match = /^\/(.*(?=\/))\/(i?)$/.exec(value);
1517
+ const match = /^\/(.*)\/(i?)$/.exec(value);
1521
1518
  if (match) {
1522
1519
  const [, expr, flags] = match;
1523
1520
  if (expr.startsWith("^") || expr.endsWith("$")) {
1524
1521
  return new RegExp(expr, flags);
1525
- } else {
1526
- return new RegExp(`^${expr}$`, flags);
1527
1522
  }
1523
+ return new RegExp(`^${expr}$`, flags);
1528
1524
  }
1529
1525
  return null;
1530
1526
  }
@@ -1585,7 +1581,7 @@ class Attribute {
1585
1581
  * @param keyLocation - Source location of attribute name.
1586
1582
  * @param valueLocation - Source location of attribute value.
1587
1583
  * @param originalAttribute - If this attribute was dynamically added via a
1588
- * transformation (e.g. vuejs `:id` generating the `id` attribute) this
1584
+ * transformation (e.g. Vue.js `:id` generating the `id` attribute) this
1589
1585
  * parameter should be set to the attribute name of the source attribute (`:id`).
1590
1586
  */
1591
1587
  constructor(key, value, keyLocation, valueLocation, originalAttribute) {
@@ -1629,9 +1625,8 @@ class Attribute {
1629
1625
  }
1630
1626
  if (pattern instanceof RegExp) {
1631
1627
  return this.value.match(pattern) !== null;
1632
- } else {
1633
- return this.value === pattern;
1634
1628
  }
1629
+ return this.value === pattern;
1635
1630
  }
1636
1631
  }
1637
1632
 
@@ -1707,7 +1702,9 @@ const Node = {
1707
1702
 
1708
1703
  const DOCUMENT_NODE_NAME = "#document";
1709
1704
  const TEXT_CONTENT = /* @__PURE__ */ Symbol("textContent");
1710
- let counter = 0;
1705
+ const state$1 = {
1706
+ counter: 0
1707
+ };
1711
1708
  class DOMNode {
1712
1709
  nodeName;
1713
1710
  nodeType;
@@ -1746,7 +1743,7 @@ class DOMNode {
1746
1743
  this.disabledRules = /* @__PURE__ */ new Set();
1747
1744
  this.blockedRules = /* @__PURE__ */ new Map();
1748
1745
  this.childNodes = [];
1749
- this.unique = counter++;
1746
+ this.unique = state$1.counter++;
1750
1747
  this.cache = null;
1751
1748
  }
1752
1749
  /**
@@ -1762,9 +1759,8 @@ class DOMNode {
1762
1759
  cacheGet(key) {
1763
1760
  if (this.cache) {
1764
1761
  return this.cache.get(key);
1765
- } else {
1766
- return void 0;
1767
1762
  }
1763
+ return void 0;
1768
1764
  }
1769
1765
  cacheSet(key, value) {
1770
1766
  if (this.cache) {
@@ -1780,9 +1776,8 @@ class DOMNode {
1780
1776
  cacheRemove(key) {
1781
1777
  if (this.cache) {
1782
1778
  return this.cache.delete(key);
1783
- } else {
1784
- return false;
1785
1779
  }
1780
+ return false;
1786
1781
  }
1787
1782
  /**
1788
1783
  * Check if key exists in cache.
@@ -2002,9 +1997,8 @@ class DOMTokenList extends Array {
2002
1997
  location(n) {
2003
1998
  if (this.locations) {
2004
1999
  return this.locations[n];
2005
- } else {
2006
- throw new Error("Trying to access DOMTokenList location when base location isn't set");
2007
2000
  }
2001
+ throw new Error("Trying to access DOMTokenList location when base location isn't set");
2008
2002
  }
2009
2003
  contains(token) {
2010
2004
  return this.includes(token);
@@ -2072,7 +2066,7 @@ function nthChild(node, args) {
2072
2066
  if (!args) {
2073
2067
  throw new Error("Missing argument to nth-child");
2074
2068
  }
2075
- const n = Number.parseInt(args.trim(), 10);
2069
+ const n = Math.trunc(Number(args.trim()));
2076
2070
  const cur = getNthChild(node);
2077
2071
  return cur === n;
2078
2072
  }
@@ -2091,9 +2085,8 @@ function factory(name, context) {
2091
2085
  const fn = table[name];
2092
2086
  if (fn) {
2093
2087
  return fn.bind(context);
2094
- } else {
2095
- throw new Error(`Pseudo-class "${name}" is not implemented`);
2096
2088
  }
2089
+ throw new Error(`Pseudo-class "${name}" is not implemented`);
2097
2090
  }
2098
2091
 
2099
2092
  function stripslashes(value) {
@@ -2119,7 +2112,7 @@ function createIdCondition(raw) {
2119
2112
  };
2120
2113
  }
2121
2114
  function createAttributeCondition(attr) {
2122
- const match = /^(.+?)(?:([$*^|~]?=)"([^"]+?)")?$/.exec(attr);
2115
+ const match = /^(.+?)(?:([$*^|~]?=)"([^"]+)")?$/.exec(attr);
2123
2116
  const key = match[1];
2124
2117
  const op = match[2];
2125
2118
  const rawValue = match[3];
@@ -2182,7 +2175,6 @@ function* splitCompound(pattern) {
2182
2175
  let quoted = false;
2183
2176
  while (cur < end) {
2184
2177
  const ch = pattern[cur];
2185
- const buffer = pattern.slice(begin, cur);
2186
2178
  if (ch === "\\") {
2187
2179
  cur += 2;
2188
2180
  continue;
@@ -2199,6 +2191,7 @@ function* splitCompound(pattern) {
2199
2191
  cur += 1;
2200
2192
  continue;
2201
2193
  }
2194
+ const buffer = pattern.slice(begin, cur);
2202
2195
  if (isPseudoElement(ch, buffer)) {
2203
2196
  cur += 1;
2204
2197
  continue;
@@ -2219,7 +2212,7 @@ class Compound {
2219
2212
  selector;
2220
2213
  conditions;
2221
2214
  constructor(pattern) {
2222
- const match = /^([+>~-]?)((?:\*|[^#.:[]+)?)([^]*)$/.exec(pattern);
2215
+ const match = /^([+>~-]?)((?:\*|[^#.:[]+)?)([\s\S]*)$/.exec(pattern);
2223
2216
  if (!match) {
2224
2217
  throw new Error(`Failed to create selector pattern from "${pattern}"`);
2225
2218
  }
@@ -2233,7 +2226,7 @@ class Compound {
2233
2226
  return node.is(this.tagName) && this.conditions.every((cur) => cur.match(node, context));
2234
2227
  }
2235
2228
  createCondition(pattern) {
2236
- switch (pattern[0]) {
2229
+ switch (pattern.at(0)) {
2237
2230
  case ".":
2238
2231
  return createClassCondition(pattern.slice(1));
2239
2232
  case "#":
@@ -2426,9 +2419,9 @@ class ComplexSelector {
2426
2419
  case Combinator.CHILD:
2427
2420
  return root.childElements.filter((node) => node.is(pattern.tagName));
2428
2421
  case Combinator.ADJACENT_SIBLING:
2429
- return ComplexSelector.findAdjacentSibling(root);
2422
+ return this.findAdjacentSibling(root);
2430
2423
  case Combinator.GENERAL_SIBLING:
2431
- return ComplexSelector.findGeneralSibling(root);
2424
+ return this.findGeneralSibling(root);
2432
2425
  case Combinator.SCOPE:
2433
2426
  return [root];
2434
2427
  }
@@ -2466,12 +2459,11 @@ const codepoints = {
2466
2459
  "\r": "\\d "
2467
2460
  };
2468
2461
  function escapeSelectorComponent(text) {
2469
- return text.toString().replaceAll(/([\t\n\r]|[^\w-])/gi, (_, ch) => {
2470
- if (codepoints[ch]) {
2462
+ return text.toString().replaceAll(/([^\w-])/g, (_, ch) => {
2463
+ if (Object.hasOwn(codepoints, ch)) {
2471
2464
  return codepoints[ch];
2472
- } else {
2473
- return `\\${ch}`;
2474
2465
  }
2466
+ return `\\${ch}`;
2475
2467
  });
2476
2468
  }
2477
2469
 
@@ -2634,10 +2626,10 @@ class HtmlElement extends DOMNode {
2634
2626
  */
2635
2627
  static fromTokens(startToken, endToken, parent, metaTable, namespace = "") {
2636
2628
  const name = startToken.data[2];
2637
- const tagName = namespace ? `${namespace}:${name}` : name;
2638
2629
  if (!name) {
2639
2630
  throw new Error("tagName cannot be empty");
2640
2631
  }
2632
+ const tagName = namespace ? `${namespace}:${name}` : name;
2641
2633
  const meta = metaTable ? metaTable.getMetaFor(tagName) : null;
2642
2634
  const open = startToken.data[1] !== "/";
2643
2635
  const closed = isClosed(endToken, meta);
@@ -2659,9 +2651,8 @@ class HtmlElement extends DOMNode {
2659
2651
  get annotatedName() {
2660
2652
  if (this.annotation) {
2661
2653
  return this.annotation;
2662
- } else {
2663
- return `<${this.tagName}>`;
2664
2654
  }
2655
+ return `<${this.tagName}>`;
2665
2656
  }
2666
2657
  /**
2667
2658
  * Get list of IDs referenced by `aria-labelledby`.
@@ -2880,13 +2871,13 @@ class HtmlElement extends DOMNode {
2880
2871
  if (!tabindex) {
2881
2872
  return this.cacheSet(TABINDEX, null);
2882
2873
  }
2883
- if (tabindex.value === null) {
2874
+ if (tabindex.value === null || tabindex.value === "") {
2884
2875
  return this.cacheSet(TABINDEX, null);
2885
2876
  }
2886
2877
  if (tabindex.value instanceof DynamicValue) {
2887
2878
  return this.cacheSet(TABINDEX, 0);
2888
2879
  }
2889
- const parsed = Number.parseInt(tabindex.value, 10);
2880
+ const parsed = Math.trunc(Number(tabindex.value));
2890
2881
  if (Number.isNaN(parsed)) {
2891
2882
  return this.cacheSet(TABINDEX, null);
2892
2883
  }
@@ -2902,11 +2893,11 @@ class HtmlElement extends DOMNode {
2902
2893
  const tagName = this.tagName.toLowerCase();
2903
2894
  if (tagName === "script") {
2904
2895
  return "script";
2905
- } else if (tagName === "style") {
2896
+ }
2897
+ if (tagName === "style") {
2906
2898
  return "css";
2907
- } else {
2908
- return "text";
2909
2899
  }
2900
+ return "text";
2910
2901
  }
2911
2902
  /**
2912
2903
  * Get a list of all attributes on this node.
@@ -2918,16 +2909,15 @@ class HtmlElement extends DOMNode {
2918
2909
  }
2919
2910
  hasAttribute(key) {
2920
2911
  key = key.toLowerCase();
2921
- return key in this.attr;
2912
+ return Object.hasOwn(this.attr, key);
2922
2913
  }
2923
2914
  getAttribute(key, all = false) {
2924
2915
  key = key.toLowerCase();
2925
- if (key in this.attr) {
2916
+ if (Object.hasOwn(this.attr, key)) {
2926
2917
  const matches = this.attr[key];
2927
2918
  return all ? matches : matches[0];
2928
- } else {
2929
- return all ? [] : null;
2930
2919
  }
2920
+ return all ? [] : null;
2931
2921
  }
2932
2922
  /**
2933
2923
  * Get attribute value.
@@ -2945,17 +2935,17 @@ class HtmlElement extends DOMNode {
2945
2935
  const attr = this.getAttribute(key);
2946
2936
  if (attr) {
2947
2937
  return attr.value !== null ? attr.value.toString() : null;
2948
- } else {
2949
- return null;
2950
2938
  }
2939
+ return null;
2951
2940
  }
2952
- /**
2953
- * Add text as a child node to this element.
2954
- *
2955
- * @param text - Text to add.
2956
- * @param location - Source code location of this text.
2957
- */
2958
2941
  appendText(text, location) {
2942
+ if (typeof text !== "string") {
2943
+ if ("dynamic" in text) {
2944
+ text = new DynamicValue(text.dynamic);
2945
+ } else {
2946
+ text = new DynamicValue(text.expr);
2947
+ }
2948
+ }
2959
2949
  this.childNodes.push(new TextNode(text, location));
2960
2950
  }
2961
2951
  /**
@@ -3025,14 +3015,13 @@ class HtmlElement extends DOMNode {
3025
3015
  const next = it.next();
3026
3016
  if (next.done) {
3027
3017
  return null;
3028
- } else {
3029
- return next.value;
3030
3018
  }
3019
+ return next.value;
3031
3020
  }
3032
3021
  querySelectorAll(selector) {
3033
3022
  const it = this.querySelectorImpl(selector);
3034
3023
  const unique = new Set(it);
3035
- return Array.from(unique.values());
3024
+ return Array.from(unique);
3036
3025
  }
3037
3026
  *querySelectorImpl(selectorList) {
3038
3027
  if (!selectorList) {
@@ -3053,9 +3042,8 @@ class HtmlElement extends DOMNode {
3053
3042
  function visit(node) {
3054
3043
  if (callback(node)) {
3055
3044
  return true;
3056
- } else {
3057
- return node.childElements.some(visit);
3058
3045
  }
3046
+ return node.childElements.some(visit);
3059
3047
  }
3060
3048
  }
3061
3049
  /**
@@ -3230,7 +3218,7 @@ class Validator {
3230
3218
  return true;
3231
3219
  }
3232
3220
  return rules.some((rule) => {
3233
- return Validator.validatePermittedRule(node, rule);
3221
+ return this.validatePermittedRule(node, rule);
3234
3222
  });
3235
3223
  }
3236
3224
  /**
@@ -3257,9 +3245,7 @@ class Validator {
3257
3245
  const [, category, quantifier] = /^(@?.*?)([*?]?)$/.exec(rule);
3258
3246
  const limit = category && quantifier && parseQuantifier(quantifier);
3259
3247
  if (limit) {
3260
- const siblings = children.filter(
3261
- (cur) => Validator.validatePermittedCategory(cur, rule, true)
3262
- );
3248
+ const siblings = children.filter((cur) => this.validatePermittedCategory(cur, rule, true));
3263
3249
  if (siblings.length > limit) {
3264
3250
  for (const child of siblings.slice(limit)) {
3265
3251
  cb(child, category);
@@ -3290,12 +3276,12 @@ class Validator {
3290
3276
  let prev = null;
3291
3277
  for (const node of children) {
3292
3278
  const old = i;
3293
- while (rules[i] && !Validator.validatePermittedCategory(node, rules[i], true)) {
3279
+ while (rules[i] && !this.validatePermittedCategory(node, rules[i], true)) {
3294
3280
  i++;
3295
3281
  }
3296
3282
  if (i >= rules.length) {
3297
- const orderSpecified = rules.find(
3298
- (cur) => Validator.validatePermittedCategory(node, cur, true)
3283
+ const orderSpecified = rules.some(
3284
+ (cur) => this.validatePermittedCategory(node, cur, true)
3299
3285
  );
3300
3286
  if (orderSpecified) {
3301
3287
  cb(node, prev);
@@ -3334,7 +3320,7 @@ class Validator {
3334
3320
  }
3335
3321
  return rules.filter((tagName) => {
3336
3322
  const haveMatchingChild = node.childElements.some(
3337
- (child) => Validator.validatePermittedCategory(child, tagName, false)
3323
+ (child) => this.validatePermittedCategory(child, tagName, false)
3338
3324
  );
3339
3325
  return !haveMatchingChild;
3340
3326
  });
@@ -3381,36 +3367,35 @@ class Validator {
3381
3367
  return rule.enum.some((entry) => {
3382
3368
  if (typeof entry === "string") {
3383
3369
  return caseInsensitiveValue === entry;
3384
- } else if (entry instanceof RegExp) {
3370
+ }
3371
+ if (entry instanceof RegExp) {
3385
3372
  return entry.test(value);
3386
- } else if (entry.pattern instanceof RegExp) {
3373
+ }
3374
+ if (entry.pattern instanceof RegExp) {
3387
3375
  return entry.pattern.test(value);
3388
- } else {
3389
- throw new TypeError("RegExp was not precompiled when it should have been");
3390
3376
  }
3377
+ throw new TypeError("RegExp was not precompiled when it should have been");
3391
3378
  });
3392
3379
  }
3393
3380
  static validatePermittedRule(node, rule, isExclude = false) {
3394
3381
  if (typeof rule === "string") {
3395
- return Validator.validatePermittedCategory(node, rule, !isExclude);
3396
- } else if (Array.isArray(rule)) {
3382
+ return this.validatePermittedCategory(node, rule, !isExclude);
3383
+ }
3384
+ if (Array.isArray(rule)) {
3397
3385
  return rule.every((inner) => {
3398
- return Validator.validatePermittedRule(node, inner, isExclude);
3386
+ return this.validatePermittedRule(node, inner, isExclude);
3399
3387
  });
3400
- } else {
3401
- validateKeys(rule);
3402
- if (rule.exclude) {
3403
- if (Array.isArray(rule.exclude)) {
3404
- return !rule.exclude.some((inner) => {
3405
- return Validator.validatePermittedRule(node, inner, true);
3406
- });
3407
- } else {
3408
- return !Validator.validatePermittedRule(node, rule.exclude, true);
3409
- }
3410
- } else {
3411
- return true;
3388
+ }
3389
+ validateKeys(rule);
3390
+ if (rule.exclude) {
3391
+ if (Array.isArray(rule.exclude)) {
3392
+ return rule.exclude.every((inner) => {
3393
+ return !this.validatePermittedRule(node, inner, true);
3394
+ });
3412
3395
  }
3396
+ return !this.validatePermittedRule(node, rule.exclude, true);
3413
3397
  }
3398
+ return true;
3414
3399
  }
3415
3400
  /**
3416
3401
  * Validate node against a content category.
@@ -3426,7 +3411,7 @@ class Validator {
3426
3411
  */
3427
3412
  /* eslint-disable-next-line complexity -- rule does not like switch */
3428
3413
  static validatePermittedCategory(node, category, defaultMatch) {
3429
- const [, rawCategory] = /^(@?.*?)([*?]?)$/.exec(category);
3414
+ const [, rawCategory] = /^(@?.*?)[*?]?$/.exec(category);
3430
3415
  if (!rawCategory.startsWith("@")) {
3431
3416
  return node.matches(rawCategory);
3432
3417
  }
@@ -3459,10 +3444,11 @@ class Validator {
3459
3444
  }
3460
3445
  function validateKeys(rule) {
3461
3446
  for (const key of Object.keys(rule)) {
3462
- if (!allowedKeys.has(key)) {
3463
- const str = JSON.stringify(rule);
3464
- throw new Error(`Permitted rule "${str}" contains unknown property "${key}"`);
3447
+ if (allowedKeys.has(key)) {
3448
+ continue;
3465
3449
  }
3450
+ const str = JSON.stringify(rule);
3451
+ throw new Error(`Permitted rule "${str}" contains unknown property "${key}"`);
3466
3452
  }
3467
3453
  }
3468
3454
  function parseQuantifier(quantifier) {
@@ -3529,9 +3515,8 @@ function ariaNaming(element) {
3529
3515
  if (role) {
3530
3516
  if (role instanceof DynamicValue) {
3531
3517
  return element.cacheSet(cacheKey, defaultValue);
3532
- } else {
3533
- return element.cacheSet(cacheKey, byRole(role));
3534
3518
  }
3519
+ return element.cacheSet(cacheKey, byRole(role));
3535
3520
  }
3536
3521
  const meta = element.meta;
3537
3522
  if (!meta) {
@@ -3716,9 +3701,8 @@ function isPresentation(node) {
3716
3701
  const role = node.getAttribute("role");
3717
3702
  if (role && (role.value === "presentation" || role.value === "none")) {
3718
3703
  return node.cacheSet(ROLE_PRESENTATION_CACHE, true);
3719
- } else {
3720
- return node.cacheSet(ROLE_PRESENTATION_CACHE, false);
3721
3704
  }
3705
+ return node.cacheSet(ROLE_PRESENTATION_CACHE, false);
3722
3706
  }
3723
3707
 
3724
3708
  const cachePrefix = classifyNodeText.name;
@@ -3736,13 +3720,14 @@ function getCachekey(options) {
3736
3720
  const { accessible = false, ignoreHiddenRoot = false } = options;
3737
3721
  if (accessible && ignoreHiddenRoot) {
3738
3722
  return IGNORE_HIDDEN_ROOT_A11Y_CACHE_KEY;
3739
- } else if (ignoreHiddenRoot) {
3723
+ }
3724
+ if (ignoreHiddenRoot) {
3740
3725
  return IGNORE_HIDDEN_ROOT_HTML_CACHE_KEY;
3741
- } else if (accessible) {
3726
+ }
3727
+ if (accessible) {
3742
3728
  return A11Y_CACHE_KEY;
3743
- } else {
3744
- return HTML_CACHE_KEY;
3745
3729
  }
3730
+ return HTML_CACHE_KEY;
3746
3731
  }
3747
3732
  function isSpecialEmpty(node) {
3748
3733
  return node.is("select") || node.is("textarea");
@@ -3774,7 +3759,7 @@ function classifyNodeText(node, options = {}) {
3774
3759
  }
3775
3760
  function findTextNodes(node, options) {
3776
3761
  const { accessible = false } = options;
3777
- let text = [];
3762
+ const text = [];
3778
3763
  for (const child of node.childNodes) {
3779
3764
  if (isTextNode(child)) {
3780
3765
  text.push(child);
@@ -3785,7 +3770,7 @@ function findTextNodes(node, options) {
3785
3770
  if (accessible && isAriaHidden(child, true).bySelf) {
3786
3771
  continue;
3787
3772
  }
3788
- text = text.concat(findTextNodes(child, options));
3773
+ text.push(...findTextNodes(child, options));
3789
3774
  }
3790
3775
  }
3791
3776
  return text;
@@ -3846,14 +3831,17 @@ function format(value, quote = false) {
3846
3831
  return String(value);
3847
3832
  }
3848
3833
  function interpolate(text, data) {
3849
- return text.replaceAll(/{{\s*([^\s{}]+)\s*}}/g, (match, key) => {
3834
+ return text.replaceAll(/\{\{\s*([^\s{}]+)\s*\}\}/g, (match, key) => {
3850
3835
  return data[key] !== void 0 ? format(data[key]) : match;
3851
3836
  });
3852
3837
  }
3853
3838
 
3854
- const ajv$1 = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
3855
- ajv$1.addMetaSchema(ajvSchemaDraft);
3856
- ajv$1.addKeyword(ajvRegexpKeyword);
3839
+ const ajv$1 = (() => {
3840
+ const ajv2 = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
3841
+ ajv2.addMetaSchema(ajvSchemaDraft);
3842
+ ajv2.addKeyword(ajvRegexpKeyword);
3843
+ return ajv2;
3844
+ })();
3857
3845
  function getSchemaValidator(ruleId, properties) {
3858
3846
  const $id = `rule/${ruleId}`;
3859
3847
  const cached = ajv$1.getSchema($id);
@@ -3874,10 +3862,9 @@ function isErrorDescriptor(value) {
3874
3862
  function unpackErrorDescriptor(value) {
3875
3863
  if (isErrorDescriptor(value)) {
3876
3864
  return value[0];
3877
- } else {
3878
- const [node, message, location, context] = value;
3879
- return { node, message, location, context };
3880
3865
  }
3866
+ const [node, message, location, context] = value;
3867
+ return { node, message, location, context };
3881
3868
  }
3882
3869
  class Rule {
3883
3870
  reporter;
@@ -4083,17 +4070,18 @@ class Rule {
4083
4070
  const callback = args.pop();
4084
4071
  const filter = args.pop() ?? (() => true);
4085
4072
  return this.parser.on(event, (_event, data) => {
4086
- if (this.isEnabled() && filter(data)) {
4087
- this.event = data;
4088
- const { tracker } = this;
4089
- if (tracker) {
4090
- const start = performance.now();
4091
- callback(data);
4092
- const end = performance.now();
4093
- tracker.trackRule(this.name, end - start);
4094
- } else {
4095
- callback(data);
4096
- }
4073
+ if (!this.isEnabled() || !filter(data)) {
4074
+ return;
4075
+ }
4076
+ this.event = data;
4077
+ const { tracker } = this;
4078
+ if (tracker) {
4079
+ const start = performance.now();
4080
+ callback(data);
4081
+ const end = performance.now();
4082
+ tracker.trackRule(this.name, end - start);
4083
+ } else {
4084
+ callback(data);
4097
4085
  }
4098
4086
  });
4099
4087
  }
@@ -4163,7 +4151,7 @@ class Rule {
4163
4151
  * @public
4164
4152
  * @virtual
4165
4153
  * @param context - Error context given by a reported error.
4166
- * @returns Rule documentation and url with additional details or `null` if no
4154
+ * @returns Rule documentation and URL with additional details or `null` if no
4167
4155
  * additional documentation is available.
4168
4156
  */
4169
4157
  documentation(_context) {
@@ -4202,7 +4190,7 @@ function parseAllow(value) {
4202
4190
  };
4203
4191
  }
4204
4192
  function matchList(value, list) {
4205
- if (list.include && !list.include.some((it) => it.test(value))) {
4193
+ if (list.include?.every((it) => !it.test(value))) {
4206
4194
  return false;
4207
4195
  }
4208
4196
  if (list.exclude?.some((it) => it.test(value))) {
@@ -4287,10 +4275,10 @@ class AllowedLinks extends Rule {
4287
4275
  return Boolean(attr && attr === key);
4288
4276
  }
4289
4277
  getStyle(value) {
4290
- if (/^([a-z]+:)?\/\//g.test(value)) {
4278
+ if (/^(?:[a-z]+:)?\/\//.test(value)) {
4291
4279
  return "external" /* EXTERNAL */;
4292
4280
  }
4293
- switch (value[0]) {
4281
+ switch (value.at(0)) {
4294
4282
  /* /foo/bar */
4295
4283
  case "/":
4296
4284
  return "absolute" /* ABSOLUTE */;
@@ -4309,7 +4297,8 @@ class AllowedLinks extends Rule {
4309
4297
  const { allowAbsolute } = this;
4310
4298
  if (allowAbsolute === true) {
4311
4299
  return;
4312
- } else if (allowAbsolute === false) {
4300
+ }
4301
+ if (allowAbsolute === false) {
4313
4302
  this.report(
4314
4303
  event.target,
4315
4304
  "Link destination must not be absolute url",
@@ -4329,7 +4318,8 @@ class AllowedLinks extends Rule {
4329
4318
  const { allowExternal } = this;
4330
4319
  if (allowExternal === true) {
4331
4320
  return;
4332
- } else if (allowExternal === false) {
4321
+ }
4322
+ if (allowExternal === false) {
4333
4323
  this.report(
4334
4324
  event.target,
4335
4325
  "Link destination must not be external url",
@@ -4349,7 +4339,8 @@ class AllowedLinks extends Rule {
4349
4339
  const { allowRelative } = this;
4350
4340
  if (allowRelative === true) {
4351
4341
  return false;
4352
- } else if (allowRelative === false) {
4342
+ }
4343
+ if (allowRelative === false) {
4353
4344
  this.report(
4354
4345
  event.target,
4355
4346
  "Link destination must not be relative url",
@@ -4357,7 +4348,8 @@ class AllowedLinks extends Rule {
4357
4348
  style
4358
4349
  );
4359
4350
  return true;
4360
- } else if (!matchList(target, allowRelative)) {
4351
+ }
4352
+ if (!matchList(target, allowRelative)) {
4361
4353
  this.report(
4362
4354
  event.target,
4363
4355
  "Relative link to this destination is not allowed by current configuration",
@@ -4372,7 +4364,8 @@ class AllowedLinks extends Rule {
4372
4364
  const { allowBase } = this.options;
4373
4365
  if (this.handleRelativePath(target, event, style)) {
4374
4366
  return;
4375
- } else if (!allowBase) {
4367
+ }
4368
+ if (!allowBase) {
4376
4369
  this.report(
4377
4370
  event.target,
4378
4371
  "Relative links must be relative to current folder",
@@ -4590,12 +4583,11 @@ class AriaLabelMisuse extends Rule {
4590
4583
  ].join("\n"),
4591
4584
  url
4592
4585
  };
4593
- } else {
4594
- return {
4595
- description: [`\`${context.attr}\` can only be used on:`, "", ...lines].join("\n"),
4596
- url
4597
- };
4598
4586
  }
4587
+ return {
4588
+ description: [`\`${context.attr}\` can only be used on:`, "", ...lines].join("\n"),
4589
+ url
4590
+ };
4599
4591
  }
4600
4592
  setup() {
4601
4593
  this.on("dom:ready", (event) => {
@@ -4653,6 +4645,7 @@ class AriaLabelMisuse extends Rule {
4653
4645
  }
4654
4646
 
4655
4647
  class ConfigError extends UserError {
4648
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
4656
4649
  constructor(message, nested) {
4657
4650
  super(message, nested);
4658
4651
  this.name = "ConfigError";
@@ -4773,9 +4766,8 @@ class AttrCase extends Rule {
4773
4766
  isIgnored(node) {
4774
4767
  if (this.options.ignoreForeign) {
4775
4768
  return Boolean(node.meta?.foreign);
4776
- } else {
4777
- return false;
4778
4769
  }
4770
+ return false;
4779
4771
  }
4780
4772
  }
4781
4773
 
@@ -4825,10 +4817,11 @@ class Context {
4825
4817
  let lastNewline = -1;
4826
4818
  let newlines = 0;
4827
4819
  for (let i = 0; i < n; i++) {
4828
- if (this.string[i] === "\n") {
4829
- newlines++;
4830
- lastNewline = i;
4820
+ if (this.string[i] !== "\n") {
4821
+ continue;
4831
4822
  }
4823
+ newlines++;
4824
+ lastNewline = i;
4832
4825
  }
4833
4826
  if (newlines > 0) {
4834
4827
  this.line += newlines;
@@ -4890,28 +4883,29 @@ const MATCH_DOCTYPE_CLOSE = /^>/;
4890
4883
  const MATCH_XML_TAG = /^<\?xml.*?\?>\s+/;
4891
4884
  const MATCH_TAG_OPEN = /^<(\/?)([\w:\-]+)/;
4892
4885
  const MATCH_TAG_CLOSE = /^\/?>/;
4893
- const MATCH_TEXT = /^[^]*?(?=(?:[\t ]*(?:\r\n|\r|\n)|<[^ ]|$))/;
4886
+ const MATCH_TEXT = /^[\s\S]*?(?=[\t ]*(?:\r\n|\r|\n)|<[^ ]|$)/;
4894
4887
  const MATCH_TEMPLATING = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)/s;
4895
- const MATCH_TAG_LOOKAHEAD = /^[^]*?(?=<|$)/;
4888
+ const MATCH_TAG_LOOKAHEAD = /^[\s\S]*?(?=<|$)/;
4896
4889
  const MATCH_ATTR_START = /^([^\t\n\f\r "'/<=>]+)/;
4897
- const MATCH_ATTR_SINGLE = /^(\s*=\s*)'([^']*?)(')/;
4898
- const MATCH_ATTR_DOUBLE = /^(\s*=\s*)"([^"]*?)(")/;
4890
+ const MATCH_ATTR_SINGLE = /^(\s*=\s*)'([^']*)(')/;
4891
+ const MATCH_ATTR_DOUBLE = /^(\s*=\s*)"([^"]*)(")/;
4899
4892
  const MATCH_ATTR_UNQUOTED = /^(\s*=\s*)([^\t\n\f\r "'<>][^\t\n\f\r <>]*)/;
4900
4893
  const MATCH_CDATA_BEGIN = /^<!\[CDATA\[/;
4901
- const MATCH_CDATA_END = /^[^]*?]]>/;
4902
- const MATCH_SCRIPT_DATA = /^[^]*?(?=<\/script)/;
4894
+ const MATCH_CDATA_END = /^[\s\S]*?\]\]>/;
4895
+ const MATCH_SCRIPT_DATA = /^[\s\S]*?(?=<\/script)/;
4903
4896
  const MATCH_SCRIPT_END = /^<(\/)(script)/;
4904
- const MATCH_STYLE_DATA = /^[^]*?(?=<\/style)/;
4897
+ const MATCH_STYLE_DATA = /^[\s\S]*?(?=<\/style)/;
4905
4898
  const MATCH_STYLE_END = /^<(\/)(style)/;
4906
- const MATCH_TEXTAREA_DATA = /^[^]*?(?=<\/textarea)/;
4899
+ const MATCH_TEXTAREA_DATA = /^[\s\S]*?(?=<\/textarea)/;
4907
4900
  const MATCH_TEXTAREA_END = /^<(\/)(textarea)/;
4908
- const MATCH_TITLE_DATA = /^[^]*?(?=<\/title)/;
4901
+ const MATCH_TITLE_DATA = /^[\s\S]*?(?=<\/title)/;
4909
4902
  const MATCH_TITLE_END = /^<(\/)(title)/;
4910
- const MATCH_DIRECTIVE = /^(<!--\s*\[?)(html-validate-)([\da-z-]+)(\s*)(.*?)(]?\s*-->)/;
4911
- const MATCH_COMMENT = /^<!--([^]*?)-->/;
4912
- const MATCH_CONDITIONAL = /^<!\[([^\]]*?)]>/;
4903
+ const MATCH_DIRECTIVE = /^(<!--\s*\[?)(html-validate-)([\da-z-]+)(\s*)(.*?)(\]?\s*-->)/;
4904
+ const MATCH_COMMENT = /^<!--([\s\S]*?)-->/;
4905
+ const MATCH_CONDITIONAL = /^<!\[([^\]]*)\]>/;
4913
4906
  class InvalidTokenError extends Error {
4914
4907
  location;
4908
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
4915
4909
  constructor(location, message) {
4916
4910
  super(message);
4917
4911
  this.name = "InvalidTokenError";
@@ -4995,9 +4989,8 @@ class Lexer {
4995
4989
  evalNextState(nextState, token) {
4996
4990
  if (typeof nextState === "function") {
4997
4991
  return nextState(token);
4998
- } else {
4999
- return nextState;
5000
4992
  }
4993
+ return nextState;
5001
4994
  }
5002
4995
  *match(context, tests, error) {
5003
4996
  const n = tests.length;
@@ -5084,27 +5077,26 @@ class Lexer {
5084
5077
  case ContentModel.SCRIPT:
5085
5078
  if (selfClosed) {
5086
5079
  return State.SCRIPT;
5087
- } else {
5088
- return State.TEXT;
5089
5080
  }
5081
+ return State.TEXT;
5082
+ /* <script/> (not legal but handle it anyway so the lexer doesn't choke on it) */
5090
5083
  case ContentModel.STYLE:
5091
5084
  if (selfClosed) {
5092
5085
  return State.STYLE;
5093
- } else {
5094
- return State.TEXT;
5095
5086
  }
5087
+ return State.TEXT;
5088
+ /* <style/> */
5096
5089
  case ContentModel.TEXTAREA:
5097
5090
  if (selfClosed) {
5098
5091
  return State.TEXTAREA;
5099
- } else {
5100
- return State.TEXT;
5101
5092
  }
5093
+ return State.TEXT;
5094
+ /* <textarea/> */
5102
5095
  case ContentModel.TITLE:
5103
5096
  if (selfClosed) {
5104
5097
  return State.TITLE;
5105
- } else {
5106
- return State.TEXT;
5107
5098
  }
5099
+ return State.TEXT;
5108
5100
  }
5109
5101
  }
5110
5102
  yield* this.match(
@@ -5191,7 +5183,7 @@ class Lexer {
5191
5183
  }
5192
5184
  }
5193
5185
 
5194
- const whitespace = /(\s+)/;
5186
+ const whitespace = /\s+/;
5195
5187
  class AttrDelimiter extends Rule {
5196
5188
  documentation() {
5197
5189
  return {
@@ -5223,17 +5215,15 @@ const defaults$y = {
5223
5215
  function generateRegexp(pattern) {
5224
5216
  if (Array.isArray(pattern)) {
5225
5217
  return new RegExp(`^(${pattern.join("|")})$`, "i");
5226
- } else {
5227
- return new RegExp(`^${pattern}$`, "i");
5228
5218
  }
5219
+ return new RegExp(`^${pattern}$`, "i");
5229
5220
  }
5230
5221
  function generateMessage(name, pattern) {
5231
5222
  if (Array.isArray(pattern)) {
5232
5223
  const patterns = pattern.map((it) => `/${it}/`).join(", ");
5233
5224
  return `Attribute "${name}" should match one of [${patterns}]`;
5234
- } else {
5235
- return `Attribute "${name}" should match /${pattern}/`;
5236
5225
  }
5226
+ return `Attribute "${name}" should match /${pattern}/`;
5237
5227
  }
5238
5228
  function generateDescription(name, pattern) {
5239
5229
  if (Array.isArray(pattern)) {
@@ -5242,9 +5232,8 @@ function generateDescription(name, pattern) {
5242
5232
  "",
5243
5233
  ...pattern.map((it) => `- \`/${it}/\``)
5244
5234
  ].join("\n");
5245
- } else {
5246
- return `Attribute "${name}" should match the regular expression \`/${pattern}/\``;
5247
5235
  }
5236
+ return `Attribute "${name}" should match the regular expression \`/${pattern}/\``;
5248
5237
  }
5249
5238
  class AttrPattern extends Rule {
5250
5239
  pattern;
@@ -5290,9 +5279,8 @@ class AttrPattern extends Rule {
5290
5279
  isIgnored(node) {
5291
5280
  if (this.options.ignoreForeign) {
5292
5281
  return Boolean(node.meta?.foreign);
5293
- } else {
5294
- return false;
5295
5282
  }
5283
+ return false;
5296
5284
  }
5297
5285
  }
5298
5286
 
@@ -5403,9 +5391,8 @@ class AttrQuotes extends Rule {
5403
5391
  resolveQuotemark(value, style) {
5404
5392
  if (style === "auto" /* AUTO_QUOTE */) {
5405
5393
  return value.includes('"') ? "'" : '"';
5406
- } else {
5407
- return style;
5408
5394
  }
5395
+ return style;
5409
5396
  }
5410
5397
  }
5411
5398
  function parseStyle$3(style) {
@@ -5463,11 +5450,11 @@ class AttributeAllowedValues extends Rule {
5463
5450
  const allowedList = allowed.enum.map((value2) => {
5464
5451
  if (typeof value2 === "string") {
5465
5452
  return `- \`"${value2}"\``;
5466
- } else if (value2 instanceof RegExp) {
5453
+ }
5454
+ if (value2 instanceof RegExp) {
5467
5455
  return `- \`${value2.toString()}\``;
5468
- } else {
5469
- return `- ${value2.name}`;
5470
5456
  }
5457
+ return `- ${value2.name}`;
5471
5458
  });
5472
5459
  docs.description = [
5473
5460
  `The \`<${element}>\` element does not allow the attribute \`${attribute}\` to have the value \`"${value}"\`.`,
@@ -5511,9 +5498,8 @@ class AttributeAllowedValues extends Rule {
5511
5498
  const { key, value } = attr;
5512
5499
  if (value !== null) {
5513
5500
  return `Attribute "${key}" has invalid value "${value.toString()}"`;
5514
- } else {
5515
- return `Attribute "${key}" is missing value`;
5516
5501
  }
5502
+ return `Attribute "${key}" is missing value`;
5517
5503
  }
5518
5504
  getLocation(attr) {
5519
5505
  return attr.valueLocation ?? attr.keyLocation;
@@ -5800,10 +5786,10 @@ class AutocompletePassword extends Rule {
5800
5786
  const tokens = new DOMTokenList(raw, autocomplete.valueLocation);
5801
5787
  const index = tokens.findIndex((token) => !isGroupingToken(token));
5802
5788
  const value = tokens.item(index);
5803
- const location = tokens.location(index);
5804
5789
  if (!value) {
5805
5790
  return;
5806
5791
  }
5792
+ const location = tokens.location(index);
5807
5793
  if (value === "off") {
5808
5794
  const context = { kind: "off" };
5809
5795
  this.report({
@@ -5888,9 +5874,8 @@ function parsePattern(pattern) {
5888
5874
  function toArray$2(value) {
5889
5875
  if (Array.isArray(value)) {
5890
5876
  return value;
5891
- } else {
5892
- return [value];
5893
5877
  }
5878
+ return [value];
5894
5879
  }
5895
5880
  function validateAllowedPatterns(patterns, allowedPatterns, ruleId) {
5896
5881
  const extraneous = patterns.filter(isNamedPattern).filter((p) => !allowedPatterns.has(p));
@@ -5976,7 +5961,7 @@ class ClassPattern extends BasePatternRule {
5976
5961
  });
5977
5962
  }
5978
5963
  static schema() {
5979
- return BasePatternRule.schema();
5964
+ return super.schema();
5980
5965
  }
5981
5966
  documentation(context) {
5982
5967
  return {
@@ -6057,10 +6042,10 @@ class CloseOrder extends Rule {
6057
6042
  });
6058
6043
  this.on("tag:end", (event) => {
6059
6044
  const current = event.target;
6060
- const active = event.previous;
6061
6045
  if (current) {
6062
6046
  return;
6063
6047
  }
6048
+ const active = event.previous;
6064
6049
  for (const ancestor of ancestors(active)) {
6065
6050
  if (ancestor.isRootElement() || reported.has(ancestor.unique)) {
6066
6051
  continue;
@@ -6071,13 +6056,13 @@ class CloseOrder extends Rule {
6071
6056
  });
6072
6057
  this.on("tag:end", (event) => {
6073
6058
  const current = event.target;
6074
- const active = event.previous;
6075
6059
  if (!current) {
6076
6060
  return;
6077
6061
  }
6078
6062
  if (current.voidElement) {
6079
6063
  return;
6080
6064
  }
6065
+ const active = event.previous;
6081
6066
  if (active.closed === Node.CLOSED_IMPLICIT_CLOSED) {
6082
6067
  return;
6083
6068
  }
@@ -6172,7 +6157,7 @@ class Deprecated extends Rule {
6172
6157
  text.push(context.documentation);
6173
6158
  }
6174
6159
  const doc = {
6175
- description: text.map((cur) => cur.replaceAll("$tagname", context.tagName)).join("\n\n"),
6160
+ description: text.map((cur) => cur.replaceAll("$tagname", () => context.tagName)).join("\n\n"),
6176
6161
  url: "https://html-validate.org/rules/deprecated.html"
6177
6162
  };
6178
6163
  return doc;
@@ -6571,7 +6556,7 @@ class ElementName extends Rule {
6571
6556
  ];
6572
6557
  }
6573
6558
  setup() {
6574
- const xmlns = /^(.+):.+$/;
6559
+ const xmlns = /^[^:]+:.+$/;
6575
6560
  this.on("tag:start", (event) => {
6576
6561
  const target = event.target;
6577
6562
  const tagName = target.tagName;
@@ -6610,13 +6595,12 @@ function isNativeTemplate(node) {
6610
6595
  function getTransparentChildren(node, transparent) {
6611
6596
  if (typeof transparent === "boolean") {
6612
6597
  return node.childElements;
6613
- } else {
6614
- return node.childElements.filter((it) => {
6615
- return transparent.some((category) => {
6616
- return Validator.validatePermittedCategory(it, category, false);
6617
- });
6618
- });
6619
6598
  }
6599
+ return node.childElements.filter((it) => {
6600
+ return transparent.some((category) => {
6601
+ return Validator.validatePermittedCategory(it, category, false);
6602
+ });
6603
+ });
6620
6604
  }
6621
6605
  function getRuleDescription$2(context) {
6622
6606
  switch (context.kind) {
@@ -6648,6 +6632,7 @@ class ElementPermittedContent extends Rule {
6648
6632
  [
6649
6633
  () => this.validatePermittedContent(node, parent),
6650
6634
  () => this.validatePermittedDescendant(node, parent)
6635
+ /* eslint-disable-next-line unicorn/no-unused-array-method-return -- technical debt, should use iterator helpers */
6651
6636
  ].some((fn) => fn());
6652
6637
  });
6653
6638
  });
@@ -6793,14 +6778,12 @@ function getRuleDescription$1(context) {
6793
6778
  const allowed = rules.filter(isCategoryOrTag).map((it) => {
6794
6779
  if (isCategory$1(it)) {
6795
6780
  return `- any ${it.slice(1)} element`;
6796
- } else {
6797
- return `- \`<${it}>\``;
6798
6781
  }
6782
+ return `- \`<${it}>\``;
6799
6783
  });
6800
6784
  return [preamble, "", "Allowed parents one of:", "", ...allowed];
6801
- } else {
6802
- return [preamble];
6803
6785
  }
6786
+ return [preamble];
6804
6787
  }
6805
6788
  function formatMessage$1(node, parent, rules) {
6806
6789
  const nodeName = node.annotatedName;
@@ -6852,7 +6835,7 @@ class ElementPermittedParent extends Rule {
6852
6835
  }
6853
6836
 
6854
6837
  function isTagnameOnly(value) {
6855
- return /^[\dA-Za-z-]+$/.test(value);
6838
+ return /^[\dA-Z-]+$/i.test(value);
6856
6839
  }
6857
6840
  function getRuleDescription(context) {
6858
6841
  const escaped = context.ancestor.map((it) => `\`${it}\``);
@@ -6915,9 +6898,8 @@ function normalizeRequired(element, attr) {
6915
6898
  default:
6916
6899
  return result;
6917
6900
  }
6918
- } else {
6919
- return required ? defaultMessage : false;
6920
6901
  }
6902
+ return required ? defaultMessage : false;
6921
6903
  }
6922
6904
  class ElementRequiredAttributes extends Rule {
6923
6905
  documentation(context) {
@@ -6999,7 +6981,8 @@ const selector = ["h1", "h2", "h3", "h4", "h5", "h6"].join(",");
6999
6981
  function hasImgAltText$1(node) {
7000
6982
  if (node.is("img")) {
7001
6983
  return hasAltText(node);
7002
- } else if (node.is("svg")) {
6984
+ }
6985
+ if (node.is("svg")) {
7003
6986
  return node.textContent.trim() !== "";
7004
6987
  }
7005
6988
  return false;
@@ -7280,21 +7263,19 @@ class FormDupName extends Rule {
7280
7263
  const existing = group.cacheGet(UNIQUE_CACHE_KEY);
7281
7264
  if (existing) {
7282
7265
  return existing;
7283
- } else {
7284
- const elements = /* @__PURE__ */ new Map();
7285
- group.cacheSet(UNIQUE_CACHE_KEY, elements);
7286
- return elements;
7287
7266
  }
7267
+ const elements = /* @__PURE__ */ new Map();
7268
+ group.cacheSet(UNIQUE_CACHE_KEY, elements);
7269
+ return elements;
7288
7270
  }
7289
7271
  getSharedElements(group) {
7290
7272
  const existing = group.cacheGet(SHARED_CACHE_KEY);
7291
7273
  if (existing) {
7292
7274
  return existing;
7293
- } else {
7294
- const elements = /* @__PURE__ */ new Map();
7295
- group.cacheSet(SHARED_CACHE_KEY, elements);
7296
- return elements;
7297
7275
  }
7276
+ const elements = /* @__PURE__ */ new Map();
7277
+ group.cacheSet(SHARED_CACHE_KEY, elements);
7278
+ return elements;
7298
7279
  }
7299
7280
  }
7300
7281
 
@@ -7308,12 +7289,11 @@ function isRelevant$5(event) {
7308
7289
  return Boolean(node.meta?.heading);
7309
7290
  }
7310
7291
  function extractLevel(node) {
7311
- const match = /^[Hh](\d)$/.exec(node.tagName);
7292
+ const match = /^H(\d)$/i.exec(node.tagName);
7312
7293
  if (match) {
7313
- return Number.parseInt(match[1], 10);
7314
- } else {
7315
- return null;
7294
+ return Math.trunc(Number(match[1]));
7316
7295
  }
7296
+ return null;
7317
7297
  }
7318
7298
  function parseMaxInitial(value) {
7319
7299
  if (value === false || value === "any") {
@@ -7323,7 +7303,7 @@ function parseMaxInitial(value) {
7323
7303
  if (!match) {
7324
7304
  return 1;
7325
7305
  }
7326
- return Number.parseInt(match[1], 10);
7306
+ return Math.trunc(Number(match[1]));
7327
7307
  }
7328
7308
  class HeadingLevel extends Rule {
7329
7309
  minInitialRank;
@@ -7590,7 +7570,7 @@ class IdPattern extends BasePatternRule {
7590
7570
  });
7591
7571
  }
7592
7572
  static schema() {
7593
- return BasePatternRule.schema();
7573
+ return super.schema();
7594
7574
  }
7595
7575
  documentation(context) {
7596
7576
  return {
@@ -7812,24 +7792,23 @@ function isHidden(node, context) {
7812
7792
  const { reference } = context;
7813
7793
  if (reference?.isSameNode(node)) {
7814
7794
  return false;
7815
- } else {
7816
- return !inAccessibilityTree(node);
7817
7795
  }
7796
+ return !inAccessibilityTree(node);
7818
7797
  }
7819
7798
  function hasImgAltText(node, context) {
7820
7799
  if (node.is("img")) {
7821
7800
  return hasAltText(node);
7822
- } else if (node.is("svg")) {
7801
+ }
7802
+ if (node.is("svg")) {
7823
7803
  return node.textContent.trim() !== "";
7824
- } else {
7825
- for (const img of node.querySelectorAll("img, svg")) {
7826
- const hasName = hasAccessibleNameImpl(img, context);
7827
- if (hasName) {
7828
- return true;
7829
- }
7804
+ }
7805
+ for (const img of node.querySelectorAll("img, svg")) {
7806
+ const hasName = hasAccessibleNameImpl(img, context);
7807
+ if (hasName) {
7808
+ return true;
7830
7809
  }
7831
- return false;
7832
7810
  }
7811
+ return false;
7833
7812
  }
7834
7813
  function hasLabel(node) {
7835
7814
  const value = node.getAttributeValue("aria-label") ?? "";
@@ -7960,7 +7939,7 @@ class InputMissingLabel extends Rule {
7960
7939
  this.report(elem, `<${elem.tagName}> element has <label> but <label> element is hidden`);
7961
7940
  return;
7962
7941
  }
7963
- if (!labels.some((label) => hasAccessibleName(root, label))) {
7942
+ if (labels.every((label) => !hasAccessibleName(root, label))) {
7964
7943
  this.report(elem, `<${elem.tagName}> element has <label> but <label> has no text`);
7965
7944
  }
7966
7945
  }
@@ -8147,12 +8126,11 @@ function parseContent(text) {
8147
8126
  const match = /^(\d+)(?:\s*;\s*url=(.*))?/i.exec(text);
8148
8127
  if (match) {
8149
8128
  return {
8150
- delay: Number.parseInt(match[1], 10),
8129
+ delay: Math.trunc(Number(match[1])),
8151
8130
  url: match[2]
8152
8131
  };
8153
- } else {
8154
- return null;
8155
8132
  }
8133
+ return null;
8156
8134
  }
8157
8135
 
8158
8136
  class MissingDoctype extends Rule {
@@ -8229,7 +8207,7 @@ class NamePattern extends BasePatternRule {
8229
8207
  });
8230
8208
  }
8231
8209
  static schema() {
8232
- return BasePatternRule.schema();
8210
+ return super.schema();
8233
8211
  }
8234
8212
  documentation(context) {
8235
8213
  return {
@@ -8412,10 +8390,10 @@ class NoDeprecatedAttr extends Rule {
8412
8390
  this.on("attr", (event) => {
8413
8391
  const node = event.target;
8414
8392
  const meta = node.meta;
8415
- const attr = event.key.toLowerCase();
8416
8393
  if (meta === null) {
8417
8394
  return;
8418
8395
  }
8396
+ const attr = event.key.toLowerCase();
8419
8397
  const metaAttribute = meta.attributes[attr];
8420
8398
  if (!metaAttribute) {
8421
8399
  return;
@@ -8449,7 +8427,7 @@ class NoDupAttr extends Rule {
8449
8427
  return;
8450
8428
  }
8451
8429
  const name = event.key.toLowerCase();
8452
- if (name in attr) {
8430
+ if (Object.hasOwn(attr, name)) {
8453
8431
  this.report(event.target, `Attribute "${name}" duplicated`, event.keyLocation);
8454
8432
  }
8455
8433
  attr[event.key] = true;
@@ -8522,10 +8500,9 @@ function getExisting(element, root) {
8522
8500
  const existing = group.cacheGet(CACHE_KEY);
8523
8501
  if (existing) {
8524
8502
  return existing;
8525
- } else {
8526
- const existing2 = /* @__PURE__ */ new Set();
8527
- return group.cacheSet(CACHE_KEY, existing2);
8528
8503
  }
8504
+ const value = /* @__PURE__ */ new Set();
8505
+ return group.cacheSet(CACHE_KEY, value);
8529
8506
  }
8530
8507
 
8531
8508
  function isRelevant$2(event) {
@@ -8796,10 +8773,11 @@ class NoMissingReferences extends Rule {
8796
8773
  }
8797
8774
  }
8798
8775
  validateSingle(document, node, attr, id) {
8799
- if (idMissing(document, id)) {
8800
- const context = { key: attr.key, value: id };
8801
- this.report(node, `Element references missing id "${id}"`, attr.valueLocation, context);
8776
+ if (!idMissing(document, id)) {
8777
+ return;
8802
8778
  }
8779
+ const context = { key: attr.key, value: id };
8780
+ this.report(node, `Element references missing id "${id}"`, attr.valueLocation, context);
8803
8781
  }
8804
8782
  validateList(document, node, attr, values) {
8805
8783
  const parsed = new DOMTokenList(values, attr.valueLocation);
@@ -8839,9 +8817,9 @@ class NoMultipleMain extends Rule {
8839
8817
  const defaults$f = {
8840
8818
  relaxed: false
8841
8819
  };
8842
- const textRegexp = /(<|&(?![\d#A-Za-z]+;))/g;
8843
- const unquotedAttrRegexp = /(["'<=>`]|&(?![\d#A-Za-z]+;))/g;
8844
- const matchTemplate = /^(<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
8820
+ const textRegexp = /(<|&(?![\d#A-Z]+;))/gi;
8821
+ const unquotedAttrRegexp = /(["'<=>`]|&(?![\d#A-Z]+;))/gi;
8822
+ const matchTemplate = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
8845
8823
  const replacementTable = {
8846
8824
  '"': "&quot;",
8847
8825
  "&": "&amp;",
@@ -9073,7 +9051,7 @@ class NoRedundantRole extends Rule {
9073
9051
  }
9074
9052
  }
9075
9053
 
9076
- const xmlns = /^(.+):.+$/;
9054
+ const xmlns = /^[^:]+:.+$/;
9077
9055
  const defaults$d = {
9078
9056
  ignoreForeign: true,
9079
9057
  ignoreXML: true
@@ -9195,11 +9173,11 @@ class NoUnknownAttributes extends Rule {
9195
9173
  this.on("attr", (event) => {
9196
9174
  const node = event.target;
9197
9175
  const meta = node.meta;
9198
- const attr = event.key.toLowerCase();
9199
9176
  if (meta === null) {
9200
9177
  return;
9201
9178
  }
9202
- if (attr in meta.attributes) {
9179
+ const attr = event.key.toLowerCase();
9180
+ if (Object.hasOwn(meta.attributes, attr)) {
9203
9181
  return;
9204
9182
  }
9205
9183
  if (isPatternAttribute(attr, meta.patternAttributes)) {
@@ -9606,7 +9584,7 @@ const defaults$7 = {
9606
9584
  include: null,
9607
9585
  exclude: null
9608
9586
  };
9609
- const crossorigin = new RegExp("^(\\w+://|//)");
9587
+ const crossorigin = /^(?:\w+:\/\/|\/\/)/;
9610
9588
  const supportSri = {
9611
9589
  link: "href",
9612
9590
  script: "src"
@@ -9819,7 +9797,10 @@ function constructRegex(characters) {
9819
9797
  return new RegExp(pattern, "g");
9820
9798
  }
9821
9799
  function getText(node) {
9822
- const match = /^(\s*)(.*)$/.exec(node.textContent);
9800
+ const match = /^(\s*)(\S.*)$/.exec(node.textContent);
9801
+ if (!match) {
9802
+ return [0, ""];
9803
+ }
9823
9804
  const [, leading, text] = match;
9824
9805
  return [leading.length, text.trimEnd()];
9825
9806
  }
@@ -9972,9 +9953,8 @@ function hasDefaultText(node) {
9972
9953
  function isNonEmptyText(node) {
9973
9954
  if (isTextNode(node)) {
9974
9955
  return node.isDynamic || node.textContent.trim() !== "";
9975
- } else {
9976
- return false;
9977
9956
  }
9957
+ return false;
9978
9958
  }
9979
9959
  function haveAccessibleText(node) {
9980
9960
  if (!inAccessibilityTree(node)) {
@@ -10109,15 +10089,14 @@ function getTextFromReference(document, id) {
10109
10089
  const ref = document.querySelector(selector);
10110
10090
  if (ref) {
10111
10091
  return ref.textContent;
10112
- } else {
10113
- return selector;
10114
10092
  }
10093
+ return selector;
10115
10094
  }
10116
10095
  function groupBy(values, callback) {
10117
10096
  const result = {};
10118
10097
  for (const value of values) {
10119
10098
  const key = callback(value);
10120
- if (key in result) {
10099
+ if (Object.hasOwn(result, key)) {
10121
10100
  result[key].push(value);
10122
10101
  } else {
10123
10102
  result[key] = [value];
@@ -10217,7 +10196,7 @@ const defaults$5 = {
10217
10196
  ignoreCase: false,
10218
10197
  requireSemicolon: true
10219
10198
  };
10220
- const regexp$1 = /&(?:[\da-z]+|#x?[\da-f]+)(;|[^\da-z]|$)/gi;
10199
+ const regexp$1 = /&(?:[\da-z]+|#x?[\da-f]+)([^\da-z]|$)/gi;
10221
10200
  const lowercaseEntities = entities$1.map((it) => it.toLowerCase());
10222
10201
  function isNumerical(entity) {
10223
10202
  return entity.startsWith("&#");
@@ -10296,9 +10275,8 @@ class UnknownCharReference extends Rule {
10296
10275
  get entities() {
10297
10276
  if (this.options.ignoreCase) {
10298
10277
  return lowercaseEntities;
10299
- } else {
10300
- return entities$1;
10301
10278
  }
10279
+ return entities$1;
10302
10280
  }
10303
10281
  findCharacterReferences(node, text, location, { isAttribute }) {
10304
10282
  const delimiter = text.search(/[#?]/);
@@ -10664,7 +10642,6 @@ class ValidAutocomplete extends Rule {
10664
10642
  }
10665
10643
  validateControlAutocomplete(node, tokens, keyLocation) {
10666
10644
  const type = node.getAttributeValue("type") ?? "text";
10667
- const mantle = type !== "hidden" ? "expectation" : "anchor";
10668
10645
  if (isDisallowedType(node, type)) {
10669
10646
  const context = {
10670
10647
  msg: 0 /* InvalidAttribute */,
@@ -10679,6 +10656,7 @@ class ValidAutocomplete extends Rule {
10679
10656
  return;
10680
10657
  }
10681
10658
  if (tokens.includes("on") || tokens.includes("off")) {
10659
+ const mantle = type !== "hidden" ? "expectation" : "anchor";
10682
10660
  this.validateOnOff(node, mantle, tokens);
10683
10661
  return;
10684
10662
  }
@@ -10802,44 +10780,46 @@ class ValidAutocomplete extends Rule {
10802
10780
  * Ensure contact token is only used with field names from the second list.
10803
10781
  */
10804
10782
  validateContact(node, tokens, order) {
10805
- if (order.includes("contact") && order.includes("field1")) {
10806
- const a = order.indexOf("field1");
10807
- const b = order.indexOf("contact");
10783
+ if (!order.includes("contact") || !order.includes("field1")) {
10784
+ return;
10785
+ }
10786
+ const a = order.indexOf("field1");
10787
+ const b = order.indexOf("contact");
10788
+ const context = {
10789
+ msg: 4 /* InvalidCombination */,
10790
+ /* eslint-disable @typescript-eslint/no-non-null-assertion -- it must be present of it wouldn't be found */
10791
+ first: tokens.item(a),
10792
+ second: tokens.item(b)
10793
+ /* eslint-enable @typescript-eslint/no-non-null-assertion */
10794
+ };
10795
+ this.report({
10796
+ node,
10797
+ message: getTerminalMessage(context),
10798
+ location: tokens.location(b),
10799
+ context
10800
+ });
10801
+ }
10802
+ validateOrder(node, tokens, order) {
10803
+ const indicies = order.map((it) => expectedOrder.indexOf(it));
10804
+ for (let i = 0; i < indicies.length - 1; i++) {
10805
+ if (indicies[0] <= indicies[i + 1]) {
10806
+ continue;
10807
+ }
10808
10808
  const context = {
10809
- msg: 4 /* InvalidCombination */,
10809
+ msg: 2 /* InvalidOrder */,
10810
10810
  /* eslint-disable @typescript-eslint/no-non-null-assertion -- it must be present of it wouldn't be found */
10811
- first: tokens.item(a),
10812
- second: tokens.item(b)
10811
+ first: tokens.item(i),
10812
+ second: tokens.item(i + 1)
10813
10813
  /* eslint-enable @typescript-eslint/no-non-null-assertion */
10814
10814
  };
10815
10815
  this.report({
10816
10816
  node,
10817
10817
  message: getTerminalMessage(context),
10818
- location: tokens.location(b),
10818
+ location: tokens.location(i + 1),
10819
10819
  context
10820
10820
  });
10821
10821
  }
10822
10822
  }
10823
- validateOrder(node, tokens, order) {
10824
- const indicies = order.map((it) => expectedOrder.indexOf(it));
10825
- for (let i = 0; i < indicies.length - 1; i++) {
10826
- if (indicies[0] > indicies[i + 1]) {
10827
- const context = {
10828
- msg: 2 /* InvalidOrder */,
10829
- /* eslint-disable @typescript-eslint/no-non-null-assertion -- it must be present of it wouldn't be found */
10830
- first: tokens.item(i),
10831
- second: tokens.item(i + 1)
10832
- /* eslint-enable @typescript-eslint/no-non-null-assertion */
10833
- };
10834
- this.report({
10835
- node,
10836
- message: getTerminalMessage(context),
10837
- location: tokens.location(i + 1),
10838
- context
10839
- });
10840
- }
10841
- }
10842
- }
10843
10823
  validateControlGroup(node, tokens, fieldTokens) {
10844
10824
  const numFields = fieldTokens.filter(Boolean).length;
10845
10825
  if (numFields === 0) {
@@ -10931,7 +10911,7 @@ class ValidID extends Rule {
10931
10911
  documentation(context) {
10932
10912
  const { relaxed } = this.options;
10933
10913
  const { kind, id } = context;
10934
- const message = this.messages[kind].replace(`"{{ id }}"`, "`{{ id }}`").replace("id", "ID").replace(/^(.)/, (m) => m.toUpperCase());
10914
+ const message = this.messages[kind].replace(`"{{ id }}"`, "`{{ id }}`").replace("id", "ID").replace(/^./, (m) => m.toUpperCase());
10935
10915
  const relaxedDescription = relaxed ? [] : [
10936
10916
  " - ID must begin with a letter",
10937
10917
  " - ID must only contain letters, digits, `-` and `_`"
@@ -10969,7 +10949,7 @@ class ValidID extends Rule {
10969
10949
  if (relaxed) {
10970
10950
  return;
10971
10951
  }
10972
- if (/^[^\p{L}]/u.test(value)) {
10952
+ if (new RegExp("^\\P{L}", "u").test(value)) {
10973
10953
  const context = { kind: 3 /* LEADING_CHARACTER */, id: value };
10974
10954
  this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10975
10955
  return;
@@ -11330,7 +11310,7 @@ function isSimpleTable(table) {
11330
11310
  return false;
11331
11311
  }
11332
11312
  const numColumns = cells[0].length;
11333
- if (!cells.every((row) => row.length === numColumns)) {
11313
+ if (cells.some((row) => row.length !== numColumns)) {
11334
11314
  return false;
11335
11315
  }
11336
11316
  const shape = getShape(cells);
@@ -11984,7 +11964,7 @@ class ResolvedConfig {
11984
11964
  }
11985
11965
 
11986
11966
  function haveResolver(key, value) {
11987
- return key in value;
11967
+ return Object.hasOwn(value, key);
11988
11968
  }
11989
11969
  function haveConfigResolver(value) {
11990
11970
  return haveResolver("resolveConfig", value);
@@ -11999,7 +11979,10 @@ function haveTransformerResolver(value) {
11999
11979
  return haveResolver("resolveTransformer", value);
12000
11980
  }
12001
11981
  function resolveConfig(resolvers, id, options) {
12002
- for (const resolver of resolvers.filter(haveConfigResolver)) {
11982
+ for (const resolver of resolvers) {
11983
+ if (!haveConfigResolver(resolver)) {
11984
+ continue;
11985
+ }
12003
11986
  const config = resolver.resolveConfig(id, options);
12004
11987
  if (isThenable(config)) {
12005
11988
  return resolveConfigAsync(resolvers, id, options);
@@ -12011,7 +11994,10 @@ function resolveConfig(resolvers, id, options) {
12011
11994
  throw new UserError(`Failed to load configuration from "${id}"`);
12012
11995
  }
12013
11996
  async function resolveConfigAsync(resolvers, id, options) {
12014
- for (const resolver of resolvers.filter(haveConfigResolver)) {
11997
+ for (const resolver of resolvers) {
11998
+ if (!haveConfigResolver(resolver)) {
11999
+ continue;
12000
+ }
12015
12001
  const config = await resolver.resolveConfig(id, options);
12016
12002
  if (config) {
12017
12003
  return config;
@@ -12020,7 +12006,10 @@ async function resolveConfigAsync(resolvers, id, options) {
12020
12006
  throw new UserError(`Failed to load configuration from "${id}"`);
12021
12007
  }
12022
12008
  function resolveElements(resolvers, id, options) {
12023
- for (const resolver of resolvers.filter(haveElementsResolver)) {
12009
+ for (const resolver of resolvers) {
12010
+ if (!haveElementsResolver(resolver)) {
12011
+ continue;
12012
+ }
12024
12013
  const elements = resolver.resolveElements(id, options);
12025
12014
  if (isThenable(elements)) {
12026
12015
  return resolveElementsAsync(resolvers, id, options);
@@ -12032,7 +12021,10 @@ function resolveElements(resolvers, id, options) {
12032
12021
  throw new UserError(`Failed to load elements from "${id}"`);
12033
12022
  }
12034
12023
  async function resolveElementsAsync(resolvers, id, options) {
12035
- for (const resolver of resolvers.filter(haveElementsResolver)) {
12024
+ for (const resolver of resolvers) {
12025
+ if (!haveElementsResolver(resolver)) {
12026
+ continue;
12027
+ }
12036
12028
  const elements = await resolver.resolveElements(id, options);
12037
12029
  if (elements) {
12038
12030
  return elements;
@@ -12041,7 +12033,10 @@ async function resolveElementsAsync(resolvers, id, options) {
12041
12033
  throw new UserError(`Failed to load elements from "${id}"`);
12042
12034
  }
12043
12035
  function resolvePlugin(resolvers, id, options) {
12044
- for (const resolver of resolvers.filter(havePluginResolver)) {
12036
+ for (const resolver of resolvers) {
12037
+ if (!havePluginResolver(resolver)) {
12038
+ continue;
12039
+ }
12045
12040
  const plugin = resolver.resolvePlugin(id, options);
12046
12041
  if (isThenable(plugin)) {
12047
12042
  return resolvePluginAsync(resolvers, id, options);
@@ -12053,7 +12048,10 @@ function resolvePlugin(resolvers, id, options) {
12053
12048
  throw new UserError(`Failed to load plugin from "${id}"`);
12054
12049
  }
12055
12050
  async function resolvePluginAsync(resolvers, id, options) {
12056
- for (const resolver of resolvers.filter(havePluginResolver)) {
12051
+ for (const resolver of resolvers) {
12052
+ if (!havePluginResolver(resolver)) {
12053
+ continue;
12054
+ }
12057
12055
  const plugin = await resolver.resolvePlugin(id, options);
12058
12056
  if (plugin) {
12059
12057
  return plugin;
@@ -12062,7 +12060,10 @@ async function resolvePluginAsync(resolvers, id, options) {
12062
12060
  throw new UserError(`Failed to load plugin from "${id}"`);
12063
12061
  }
12064
12062
  function resolveTransformer(resolvers, id, options) {
12065
- for (const resolver of resolvers.filter(haveTransformerResolver)) {
12063
+ for (const resolver of resolvers) {
12064
+ if (!haveTransformerResolver(resolver)) {
12065
+ continue;
12066
+ }
12066
12067
  const transformer = resolver.resolveTransformer(id, options);
12067
12068
  if (isThenable(transformer)) {
12068
12069
  return resolveTransformerAsync(resolvers, id, options);
@@ -12074,7 +12075,10 @@ function resolveTransformer(resolvers, id, options) {
12074
12075
  throw new UserError(`Failed to load transformer from "${id}"`);
12075
12076
  }
12076
12077
  async function resolveTransformerAsync(resolvers, id, options) {
12077
- for (const resolver of resolvers.filter(haveTransformerResolver)) {
12078
+ for (const resolver of resolvers) {
12079
+ if (!haveTransformerResolver(resolver)) {
12080
+ continue;
12081
+ }
12078
12082
  const transformer = await resolver.resolveTransformer(id, options);
12079
12083
  if (transformer) {
12080
12084
  return transformer;
@@ -12114,9 +12118,12 @@ function staticResolver(map = {}) {
12114
12118
  };
12115
12119
  }
12116
12120
 
12117
- const ajv = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
12118
- ajv.addMetaSchema(ajvSchemaDraft);
12119
- ajv.addKeyword(ajvFunctionKeyword);
12121
+ const ajv = (() => {
12122
+ const ajv2 = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
12123
+ ajv2.addMetaSchema(ajvSchemaDraft);
12124
+ ajv2.addKeyword(ajvFunctionKeyword);
12125
+ return ajv2;
12126
+ })();
12120
12127
  const validator = ajv.compile(configurationSchema);
12121
12128
  function overwriteMerge(_a, b) {
12122
12129
  return b;
@@ -12135,18 +12142,16 @@ function mergeInternal(base, rhs) {
12135
12142
  function toArray$1(value) {
12136
12143
  if (Array.isArray(value)) {
12137
12144
  return value;
12138
- } else {
12139
- return [value];
12140
12145
  }
12146
+ return [value];
12141
12147
  }
12142
12148
  function transformerEntries(transform) {
12143
12149
  return Object.entries(transform).map(([pattern, value]) => {
12144
12150
  const regex = new RegExp(pattern);
12145
12151
  if (typeof value === "string") {
12146
12152
  return { kind: "import", pattern: regex, name: value };
12147
- } else {
12148
- return { kind: "function", pattern: regex, function: value };
12149
12153
  }
12154
+ return { kind: "function", pattern: regex, function: value };
12150
12155
  });
12151
12156
  }
12152
12157
  class Config {
@@ -12171,8 +12176,8 @@ class Config {
12171
12176
  * Create configuration from object.
12172
12177
  */
12173
12178
  static fromObject(resolvers, options, filename = null) {
12174
- Config.validate(options, filename);
12175
- return Config.create(resolvers, options);
12179
+ this.validate(options, filename);
12180
+ return this.create(resolvers, options);
12176
12181
  }
12177
12182
  /**
12178
12183
  * Read configuration from filename.
@@ -12186,10 +12191,9 @@ class Config {
12186
12191
  static fromFile(resolvers, filename) {
12187
12192
  const configData = resolveConfig(toArray$1(resolvers), filename, { cache: false });
12188
12193
  if (isThenable(configData)) {
12189
- return configData.then((configData2) => Config.fromObject(resolvers, configData2, filename));
12190
- } else {
12191
- return Config.fromObject(resolvers, configData, filename);
12194
+ return configData.then((configData2) => this.fromObject(resolvers, configData2, filename));
12192
12195
  }
12196
+ return this.fromObject(resolvers, configData, filename);
12193
12197
  }
12194
12198
  /**
12195
12199
  * Validate configuration data.
@@ -12211,8 +12215,8 @@ class Config {
12211
12215
  );
12212
12216
  }
12213
12217
  if (configData.rules) {
12214
- const normalizedRules = Config.getRulesObject(configData.rules);
12215
- for (const [ruleId, [, ruleOptions]] of normalizedRules.entries()) {
12218
+ const normalizedRules = this.getRulesObject(configData.rules);
12219
+ for (const [ruleId, [, ruleOptions]] of normalizedRules) {
12216
12220
  const cls = bundledRules[ruleId];
12217
12221
  const path = `/rules/${ruleId}/1`;
12218
12222
  Rule.validateOptions(cls, ruleId, path, ruleOptions, filename, configData);
@@ -12235,9 +12239,8 @@ class Config {
12235
12239
  return plugins.then((plugins2) => {
12236
12240
  return instance.init(options, plugins2);
12237
12241
  });
12238
- } else {
12239
- return instance.init(options, plugins);
12240
12242
  }
12243
+ return instance.init(options, plugins);
12241
12244
  }
12242
12245
  init(options, plugins) {
12243
12246
  this.plugins = plugins;
@@ -12254,9 +12257,8 @@ class Config {
12254
12257
  const extendedConfig = this.extendConfig(this.config.extends ?? []);
12255
12258
  if (isThenable(extendedConfig)) {
12256
12259
  return extendedConfig.then((extended) => update(extended));
12257
- } else {
12258
- return update(extendedConfig);
12259
12260
  }
12261
+ return update(extendedConfig);
12260
12262
  }
12261
12263
  /**
12262
12264
  * @internal
@@ -12298,12 +12300,11 @@ class Config {
12298
12300
  instance.extendMeta(instance.plugins);
12299
12301
  return instance;
12300
12302
  });
12301
- } else {
12302
- instance.plugins = plugins;
12303
- instance.configurations = instance.loadConfigurations(instance.plugins);
12304
- instance.extendMeta(instance.plugins);
12305
- return instance;
12306
12303
  }
12304
+ instance.plugins = plugins;
12305
+ instance.configurations = instance.loadConfigurations(instance.plugins);
12306
+ instance.extendMeta(instance.plugins);
12307
+ return instance;
12307
12308
  }
12308
12309
  extendConfig(entries) {
12309
12310
  if (entries.length === 0) {
@@ -12359,20 +12360,19 @@ class Config {
12359
12360
  const result = this.getElementsFromEntry(entry);
12360
12361
  if (isThenable(result)) {
12361
12362
  return result.then((result2) => {
12362
- const [obj, filename] = result2;
12363
- metaTable.loadFromObject(obj, filename);
12364
- const next2 = source.shift();
12365
- if (next2) {
12366
- return loadEntry(next2);
12363
+ const [obj2, filename2] = result2;
12364
+ metaTable.loadFromObject(obj2, filename2);
12365
+ const next3 = source.shift();
12366
+ if (next3) {
12367
+ return loadEntry(next3);
12367
12368
  }
12368
12369
  });
12369
- } else {
12370
- const [obj, filename] = result;
12371
- metaTable.loadFromObject(obj, filename);
12372
- const next2 = source.shift();
12373
- if (next2) {
12374
- return loadEntry(next2);
12375
- }
12370
+ }
12371
+ const [obj, filename] = result;
12372
+ metaTable.loadFromObject(obj, filename);
12373
+ const next2 = source.shift();
12374
+ if (next2) {
12375
+ return loadEntry(next2);
12376
12376
  }
12377
12377
  };
12378
12378
  const next = source.shift();
@@ -12402,9 +12402,8 @@ class Config {
12402
12402
  return obj.then((obj2) => {
12403
12403
  return [obj2, entry];
12404
12404
  });
12405
- } else {
12406
- return [obj, entry];
12407
12405
  }
12406
+ return [obj, entry];
12408
12407
  } catch (err) {
12409
12408
  const message = err instanceof Error ? err.message : String(err);
12410
12409
  throw new ConfigError(
@@ -12466,7 +12465,7 @@ class Config {
12466
12465
  const loadPlugin = (entry, index) => {
12467
12466
  if (typeof entry !== "string") {
12468
12467
  const plugin = entry;
12469
- plugin.name = plugin.name || `:unnamedPlugin@${String(index + 1)}`;
12468
+ plugin.name ||= `:unnamedPlugin@${String(index + 1)}`;
12470
12469
  plugin.originalName = `:unnamedPlugin@${String(index + 1)}`;
12471
12470
  loaded.push(plugin);
12472
12471
  const next2 = loading.shift();
@@ -12478,22 +12477,21 @@ class Config {
12478
12477
  const plugin = resolvePlugin(this.resolvers, entry, { cache: true });
12479
12478
  if (isThenable(plugin)) {
12480
12479
  return plugin.then((plugin2) => {
12481
- plugin2.name = plugin2.name || entry;
12480
+ plugin2.name ||= entry;
12482
12481
  plugin2.originalName = entry;
12483
12482
  loaded.push(plugin2);
12484
- const next2 = loading.shift();
12485
- if (next2) {
12486
- return loadPlugin(next2, index + 1);
12483
+ const next3 = loading.shift();
12484
+ if (next3) {
12485
+ return loadPlugin(next3, index + 1);
12487
12486
  }
12488
12487
  });
12489
- } else {
12490
- plugin.name = plugin.name || entry;
12491
- plugin.originalName = entry;
12492
- loaded.push(plugin);
12493
- const next2 = loading.shift();
12494
- if (next2) {
12495
- return loadPlugin(next2, index + 1);
12496
- }
12488
+ }
12489
+ plugin.name ||= entry;
12490
+ plugin.originalName = entry;
12491
+ loaded.push(plugin);
12492
+ const next2 = loading.shift();
12493
+ if (next2) {
12494
+ return loadPlugin(next2, index + 1);
12497
12495
  }
12498
12496
  } catch (err) {
12499
12497
  const message = err instanceof Error ? err.message : String(err);
@@ -12519,7 +12517,8 @@ class Config {
12519
12517
  configs.set(name, config);
12520
12518
  }
12521
12519
  for (const plugin of plugins) {
12522
- for (const [name, config] of Object.entries(plugin.configs ?? {})) {
12520
+ const entries = Object.entries(plugin.configs ?? {});
12521
+ for (const [name, config] of entries) {
12523
12522
  if (!config) {
12524
12523
  continue;
12525
12524
  }
@@ -12563,9 +12562,8 @@ class Config {
12563
12562
  return resolveData.then((resolveData2) => {
12564
12563
  return new ResolvedConfig(resolveData2, this.get());
12565
12564
  });
12566
- } else {
12567
- return new ResolvedConfig(resolveData, this.get());
12568
12565
  }
12566
+ return new ResolvedConfig(resolveData, this.get());
12569
12567
  }
12570
12568
  /**
12571
12569
  * Same as [[resolve]] but returns the raw configuration data instead of
@@ -12584,14 +12582,13 @@ class Config {
12584
12582
  transformers: this.transformers
12585
12583
  };
12586
12584
  });
12587
- } else {
12588
- return {
12589
- metaTable,
12590
- plugins: this.getPlugins(),
12591
- rules: this.getRules(),
12592
- transformers: this.transformers
12593
- };
12594
12585
  }
12586
+ return {
12587
+ metaTable,
12588
+ plugins: this.getPlugins(),
12589
+ rules: this.getRules(),
12590
+ transformers: this.transformers
12591
+ };
12595
12592
  }
12596
12593
  }
12597
12594
 
@@ -12635,10 +12632,9 @@ class ConfigLoader {
12635
12632
  this._globalConfig = config2;
12636
12633
  return this._globalConfig;
12637
12634
  });
12638
- } else {
12639
- this._globalConfig = config;
12640
- return this._globalConfig;
12641
12635
  }
12636
+ this._globalConfig = config;
12637
+ return this._globalConfig;
12642
12638
  }
12643
12639
  /**
12644
12640
  * Get the global configuration.
@@ -12720,9 +12716,8 @@ class StaticConfigLoader extends ConfigLoader {
12720
12716
  const override = this.loadFromObject(configOverride ?? {});
12721
12717
  if (isThenable(override)) {
12722
12718
  return override.then((override2) => this._resolveConfig(override2));
12723
- } else {
12724
- return this._resolveConfig(override);
12725
12719
  }
12720
+ return this._resolveConfig(override);
12726
12721
  }
12727
12722
  flushCache() {
12728
12723
  }
@@ -12739,25 +12734,22 @@ class StaticConfigLoader extends ConfigLoader {
12739
12734
  const globalConfig = this.getGlobalConfig();
12740
12735
  if (isThenable(globalConfig)) {
12741
12736
  return globalConfig.then((globalConfig2) => {
12742
- const merged = globalConfig2.merge(this.resolvers, override);
12743
- if (isThenable(merged)) {
12744
- return merged.then((merged2) => {
12745
- return merged2.resolve();
12737
+ const merged2 = globalConfig2.merge(this.resolvers, override);
12738
+ if (isThenable(merged2)) {
12739
+ return merged2.then((merged3) => {
12740
+ return merged3.resolve();
12746
12741
  });
12747
- } else {
12748
- return merged.resolve();
12749
12742
  }
12743
+ return merged2.resolve();
12744
+ });
12745
+ }
12746
+ const merged = globalConfig.merge(this.resolvers, override);
12747
+ if (isThenable(merged)) {
12748
+ return merged.then((merged2) => {
12749
+ return merged2.resolve();
12750
12750
  });
12751
- } else {
12752
- const merged = globalConfig.merge(this.resolvers, override);
12753
- if (isThenable(merged)) {
12754
- return merged.then((merged2) => {
12755
- return merged2.resolve();
12756
- });
12757
- } else {
12758
- return merged.resolve();
12759
- }
12760
12751
  }
12752
+ return merged.resolve();
12761
12753
  }
12762
12754
  }
12763
12755
 
@@ -12844,7 +12836,7 @@ class EventHandler {
12844
12836
  }
12845
12837
 
12846
12838
  const name = "html-validate";
12847
- const version = "11.5.3";
12839
+ const version = "11.5.5";
12848
12840
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
12849
12841
 
12850
12842
  function freeze(src) {
@@ -12882,7 +12874,7 @@ class Reporter {
12882
12874
  for (const report of reports) {
12883
12875
  for (const result of report.results) {
12884
12876
  const key = result.filePath;
12885
- if (key in merged) {
12877
+ if (Object.hasOwn(merged, key)) {
12886
12878
  merged[key].messages = [...merged[key].messages, ...result.messages];
12887
12879
  } else {
12888
12880
  merged[key] = { ...result };
@@ -12906,7 +12898,7 @@ class Reporter {
12906
12898
  */
12907
12899
  add(options) {
12908
12900
  const { rule, message, severity, node, location, context } = options;
12909
- if (!(location.filename in this.result)) {
12901
+ if (!Object.hasOwn(this.result, location.filename)) {
12910
12902
  this.result[location.filename] = [];
12911
12903
  }
12912
12904
  const ruleUrl = rule.documentation(context)?.url;
@@ -12934,7 +12926,7 @@ class Reporter {
12934
12926
  * @internal
12935
12927
  */
12936
12928
  addManual(filename, message) {
12937
- if (!(filename in this.result)) {
12929
+ if (!Object.hasOwn(this.result, filename)) {
12938
12930
  this.result[filename] = [];
12939
12931
  }
12940
12932
  this.result[filename].push(message);
@@ -12945,6 +12937,7 @@ class Reporter {
12945
12937
  save(sources) {
12946
12938
  const report = {
12947
12939
  valid: this.isValid(),
12940
+ /* eslint-disable-next-line unicorn/prefer-object-iterable-methods -- technical debt */
12948
12941
  results: Object.keys(this.result).map((filePath) => {
12949
12942
  const messages = Array.from(this.result[filePath], freeze).toSorted(messageSort);
12950
12943
  const source = (sources ?? []).find((source2) => filePath === source2.filename);
@@ -13009,7 +13002,7 @@ function definePlugin(plugin) {
13009
13002
  return plugin;
13010
13003
  }
13011
13004
 
13012
- const regexp = /<!(?:--)?\[(.*?)](?:--)?>/g;
13005
+ const regexp = /<!(?:--)?\[(.*?)\](?:--)?>/g;
13013
13006
  function* parseConditionalComment(comment, commentLocation) {
13014
13007
  let match;
13015
13008
  while ((match = regexp.exec(comment)) !== null) {
@@ -13026,6 +13019,7 @@ function* parseConditionalComment(comment, commentLocation) {
13026
13019
 
13027
13020
  class ParserError extends Error {
13028
13021
  location;
13022
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
13029
13023
  constructor(location, message) {
13030
13024
  super(message);
13031
13025
  this.name = "ParserError";
@@ -13189,9 +13183,8 @@ class Parser {
13189
13183
  const open = !token.data[1];
13190
13184
  if (open) {
13191
13185
  return this.wouldCloseElement(token, active);
13192
- } else {
13193
- return this.closeOptionalEndTag(token, active);
13194
13186
  }
13187
+ return this.closeOptionalEndTag(token, active);
13195
13188
  }
13196
13189
  /**
13197
13190
  * Returns `true` if the element’s end tag may be omitted, either because
@@ -13543,9 +13536,8 @@ class Parser {
13543
13536
  const quote = token.data[3];
13544
13537
  if (quote) {
13545
13538
  return sliceLocation(token.location, 2, -1);
13546
- } else {
13547
- return sliceLocation(token.location, 1);
13548
13539
  }
13540
+ return sliceLocation(token.location, 1);
13549
13541
  }
13550
13542
  /**
13551
13543
  * Take attribute key and value token an returns a new location referring to
@@ -13833,13 +13825,14 @@ class PerformanceTracker {
13833
13825
  */
13834
13826
  getResult() {
13835
13827
  const events = Array.from(
13836
- this.eventData.entries(),
13828
+ this.eventData,
13837
13829
  ([event, { count, time }]) => ({ event, count, time })
13838
13830
  ).toSorted((a, b) => b.time - a.time);
13839
- const rules = Array.from(
13840
- this.ruleData.entries(),
13841
- ([rule, { count, time }]) => ({ rule, count, time })
13842
- ).toSorted((a, b) => b.time - a.time);
13831
+ const rules = Array.from(this.ruleData, ([rule, { count, time }]) => ({
13832
+ rule,
13833
+ count,
13834
+ time
13835
+ })).toSorted((a, b) => b.time - a.time);
13843
13836
  return {
13844
13837
  events,
13845
13838
  rules,
@@ -13886,9 +13879,11 @@ function dumpTree(root) {
13886
13879
  return lines;
13887
13880
  }
13888
13881
 
13889
- let blockerCounter = 1;
13882
+ const state = {
13883
+ blockerCounter: 1
13884
+ };
13890
13885
  function createBlocker() {
13891
- const id = blockerCounter++;
13886
+ const id = state.blockerCounter++;
13892
13887
  return id;
13893
13888
  }
13894
13889
 
@@ -14024,9 +14019,8 @@ class Engine {
14024
14019
  const [, options] = ruleData;
14025
14020
  const rule = this.instantiateRule(ruleId, options);
14026
14021
  return rule.documentation(context);
14027
- } else {
14028
- return null;
14029
14022
  }
14023
+ return null;
14030
14024
  }
14031
14025
  /**
14032
14026
  * Create a new parser instance with the current configuration.
@@ -14155,7 +14149,8 @@ class Engine {
14155
14149
  initRules(config) {
14156
14150
  const availableRules = {};
14157
14151
  for (const plugin of config.getPlugins()) {
14158
- for (const [name, rule] of Object.entries(plugin.rules ?? {})) {
14152
+ const entries = Object.entries(plugin.rules ?? {});
14153
+ for (const [name, rule] of entries) {
14159
14154
  if (!rule) {
14160
14155
  continue;
14161
14156
  }
@@ -14183,7 +14178,7 @@ class Engine {
14183
14178
  */
14184
14179
  setupRules(config, parser) {
14185
14180
  const rules = {};
14186
- for (const [ruleId, [severity, options]] of config.getRules().entries()) {
14181
+ for (const [ruleId, [severity, options]] of config.getRules()) {
14187
14182
  rules[ruleId] = this.loadRule(ruleId, config, severity, options, parser, this.report);
14188
14183
  }
14189
14184
  return rules;
@@ -14207,9 +14202,8 @@ class Engine {
14207
14202
  if (this.availableRules[name]) {
14208
14203
  const RuleConstructor = this.availableRules[name];
14209
14204
  return new RuleConstructor(options);
14210
- } else {
14211
- return this.missingRule(name);
14212
14205
  }
14206
+ return this.missingRule(name);
14213
14207
  }
14214
14208
  missingRule(name) {
14215
14209
  return new class MissingRule extends Rule {
@@ -14305,34 +14299,30 @@ function getTransformerFunction(resolvers, name, plugins) {
14305
14299
  validateTransformer(transformer2);
14306
14300
  return transformer2;
14307
14301
  });
14308
- } else {
14309
- validateTransformer(transformer);
14310
- return transformer;
14311
14302
  }
14303
+ validateTransformer(transformer);
14304
+ return transformer;
14312
14305
  } catch (err) {
14313
14306
  if (err instanceof ConfigError) {
14314
14307
  throw new ConfigError(`Failed to load transformer "${name}": ${err.message}`, err);
14315
- } else {
14316
- throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
14317
14308
  }
14309
+ throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
14318
14310
  }
14319
14311
  }
14320
14312
  function getCachedTransformerFunction(cache, resolvers, name, plugins) {
14321
14313
  const cached = cache.get(name);
14322
14314
  if (cached) {
14323
14315
  return cached;
14324
- } else {
14325
- const transformer = getTransformerFunction(resolvers, name, plugins);
14326
- if (isThenable(transformer)) {
14327
- return transformer.then((transformer2) => {
14328
- cache.set(name, transformer2);
14329
- return transformer2;
14330
- });
14331
- } else {
14332
- cache.set(name, transformer);
14333
- return transformer;
14334
- }
14335
14316
  }
14317
+ const transformer = getTransformerFunction(resolvers, name, plugins);
14318
+ if (isThenable(transformer)) {
14319
+ return transformer.then((transformer2) => {
14320
+ cache.set(name, transformer2);
14321
+ return transformer2;
14322
+ });
14323
+ }
14324
+ cache.set(name, transformer);
14325
+ return transformer;
14336
14326
  }
14337
14327
 
14338
14328
  function isIterable(value) {
@@ -14348,6 +14338,9 @@ const asyncInSyncTransformError = "Cannot use async transformer from sync functi
14348
14338
  async function transformSource(resolvers, config, source, filename) {
14349
14339
  const { cache } = config;
14350
14340
  const transformer = config.findTransformer(filename ?? source.filename);
14341
+ if (!transformer) {
14342
+ return [source];
14343
+ }
14351
14344
  const context = {
14352
14345
  hasChain(filename2) {
14353
14346
  return config.canTransform(filename2);
@@ -14356,9 +14349,6 @@ async function transformSource(resolvers, config, source, filename) {
14356
14349
  return transformSource(resolvers, config, source2, filename2);
14357
14350
  }
14358
14351
  };
14359
- if (!transformer) {
14360
- return [source];
14361
- }
14362
14352
  const fn = transformer.kind === "import" ? await getCachedTransformerFunction(cache, resolvers, transformer.name, config.getPlugins()) : transformer.function;
14363
14353
  const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14364
14354
  try {
@@ -14377,6 +14367,9 @@ async function transformSource(resolvers, config, source, filename) {
14377
14367
  function transformSourceSync(resolvers, config, source, filename) {
14378
14368
  const { cache } = config;
14379
14369
  const transformer = config.findTransformer(filename ?? source.filename);
14370
+ if (!transformer) {
14371
+ return [source];
14372
+ }
14380
14373
  const context = {
14381
14374
  hasChain(filename2) {
14382
14375
  return config.canTransform(filename2);
@@ -14385,14 +14378,11 @@ function transformSourceSync(resolvers, config, source, filename) {
14385
14378
  return transformSourceSync(resolvers, config, source2, filename2);
14386
14379
  }
14387
14380
  };
14388
- if (!transformer) {
14389
- return [source];
14390
- }
14391
14381
  const fn = transformer.kind === "import" ? getCachedTransformerFunction(cache, resolvers, transformer.name, config.getPlugins()) : transformer.function;
14392
- const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14393
14382
  if (isThenable(fn)) {
14394
14383
  throw new UserError(asyncInSyncTransformError);
14395
14384
  }
14385
+ const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14396
14386
  try {
14397
14387
  const result = fn.call(context, source);
14398
14388
  if (isThenable(result)) {
@@ -14494,7 +14484,7 @@ function checkstyleFormatter(results) {
14494
14484
  `;
14495
14485
  for (const message of messages) {
14496
14486
  const ruleId = xmlescape(`htmlvalidate.rules.${message.ruleId}`);
14497
- output += " ";
14487
+ output += " ".repeat(4);
14498
14488
  output += [
14499
14489
  `<error line="${xmlescape(message.line)}"`,
14500
14490
  `column="${xmlescape(message.column)}"`,
@@ -14581,9 +14571,8 @@ function codeFrameColumns(rawLines, loc) {
14581
14571
  ].join("");
14582
14572
  }
14583
14573
  return [">", gutter, line.length > 0 ? ` ${line}` : "", markerLine].join("");
14584
- } else {
14585
- return [" ", gutter, line.length > 0 ? ` ${line}` : ""].join("");
14586
14574
  }
14575
+ return [" ", gutter, line.length > 0 ? ` ${line}` : ""].join("");
14587
14576
  }).join("\n");
14588
14577
  }
14589
14578