html-validate 11.5.3 → 11.5.4

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 +420 -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 +420 -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 +21 -11
  56. package/dist/types/index.d.ts +23 -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,13 @@ 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 === "object" && "dynamic" in text) {
2943
+ text = new DynamicValue(text.dynamic);
2944
+ }
2959
2945
  this.childNodes.push(new TextNode(text, location));
2960
2946
  }
2961
2947
  /**
@@ -3025,14 +3011,13 @@ class HtmlElement extends DOMNode {
3025
3011
  const next = it.next();
3026
3012
  if (next.done) {
3027
3013
  return null;
3028
- } else {
3029
- return next.value;
3030
3014
  }
3015
+ return next.value;
3031
3016
  }
3032
3017
  querySelectorAll(selector) {
3033
3018
  const it = this.querySelectorImpl(selector);
3034
3019
  const unique = new Set(it);
3035
- return Array.from(unique.values());
3020
+ return Array.from(unique);
3036
3021
  }
3037
3022
  *querySelectorImpl(selectorList) {
3038
3023
  if (!selectorList) {
@@ -3053,9 +3038,8 @@ class HtmlElement extends DOMNode {
3053
3038
  function visit(node) {
3054
3039
  if (callback(node)) {
3055
3040
  return true;
3056
- } else {
3057
- return node.childElements.some(visit);
3058
3041
  }
3042
+ return node.childElements.some(visit);
3059
3043
  }
3060
3044
  }
3061
3045
  /**
@@ -3230,7 +3214,7 @@ class Validator {
3230
3214
  return true;
3231
3215
  }
3232
3216
  return rules.some((rule) => {
3233
- return Validator.validatePermittedRule(node, rule);
3217
+ return this.validatePermittedRule(node, rule);
3234
3218
  });
3235
3219
  }
3236
3220
  /**
@@ -3257,9 +3241,7 @@ class Validator {
3257
3241
  const [, category, quantifier] = /^(@?.*?)([*?]?)$/.exec(rule);
3258
3242
  const limit = category && quantifier && parseQuantifier(quantifier);
3259
3243
  if (limit) {
3260
- const siblings = children.filter(
3261
- (cur) => Validator.validatePermittedCategory(cur, rule, true)
3262
- );
3244
+ const siblings = children.filter((cur) => this.validatePermittedCategory(cur, rule, true));
3263
3245
  if (siblings.length > limit) {
3264
3246
  for (const child of siblings.slice(limit)) {
3265
3247
  cb(child, category);
@@ -3290,12 +3272,12 @@ class Validator {
3290
3272
  let prev = null;
3291
3273
  for (const node of children) {
3292
3274
  const old = i;
3293
- while (rules[i] && !Validator.validatePermittedCategory(node, rules[i], true)) {
3275
+ while (rules[i] && !this.validatePermittedCategory(node, rules[i], true)) {
3294
3276
  i++;
3295
3277
  }
3296
3278
  if (i >= rules.length) {
3297
- const orderSpecified = rules.find(
3298
- (cur) => Validator.validatePermittedCategory(node, cur, true)
3279
+ const orderSpecified = rules.some(
3280
+ (cur) => this.validatePermittedCategory(node, cur, true)
3299
3281
  );
3300
3282
  if (orderSpecified) {
3301
3283
  cb(node, prev);
@@ -3334,7 +3316,7 @@ class Validator {
3334
3316
  }
3335
3317
  return rules.filter((tagName) => {
3336
3318
  const haveMatchingChild = node.childElements.some(
3337
- (child) => Validator.validatePermittedCategory(child, tagName, false)
3319
+ (child) => this.validatePermittedCategory(child, tagName, false)
3338
3320
  );
3339
3321
  return !haveMatchingChild;
3340
3322
  });
@@ -3381,36 +3363,35 @@ class Validator {
3381
3363
  return rule.enum.some((entry) => {
3382
3364
  if (typeof entry === "string") {
3383
3365
  return caseInsensitiveValue === entry;
3384
- } else if (entry instanceof RegExp) {
3366
+ }
3367
+ if (entry instanceof RegExp) {
3385
3368
  return entry.test(value);
3386
- } else if (entry.pattern instanceof RegExp) {
3369
+ }
3370
+ if (entry.pattern instanceof RegExp) {
3387
3371
  return entry.pattern.test(value);
3388
- } else {
3389
- throw new TypeError("RegExp was not precompiled when it should have been");
3390
3372
  }
3373
+ throw new TypeError("RegExp was not precompiled when it should have been");
3391
3374
  });
3392
3375
  }
3393
3376
  static validatePermittedRule(node, rule, isExclude = false) {
3394
3377
  if (typeof rule === "string") {
3395
- return Validator.validatePermittedCategory(node, rule, !isExclude);
3396
- } else if (Array.isArray(rule)) {
3378
+ return this.validatePermittedCategory(node, rule, !isExclude);
3379
+ }
3380
+ if (Array.isArray(rule)) {
3397
3381
  return rule.every((inner) => {
3398
- return Validator.validatePermittedRule(node, inner, isExclude);
3382
+ return this.validatePermittedRule(node, inner, isExclude);
3399
3383
  });
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;
3384
+ }
3385
+ validateKeys(rule);
3386
+ if (rule.exclude) {
3387
+ if (Array.isArray(rule.exclude)) {
3388
+ return rule.exclude.every((inner) => {
3389
+ return !this.validatePermittedRule(node, inner, true);
3390
+ });
3412
3391
  }
3392
+ return !this.validatePermittedRule(node, rule.exclude, true);
3413
3393
  }
3394
+ return true;
3414
3395
  }
3415
3396
  /**
3416
3397
  * Validate node against a content category.
@@ -3426,7 +3407,7 @@ class Validator {
3426
3407
  */
3427
3408
  /* eslint-disable-next-line complexity -- rule does not like switch */
3428
3409
  static validatePermittedCategory(node, category, defaultMatch) {
3429
- const [, rawCategory] = /^(@?.*?)([*?]?)$/.exec(category);
3410
+ const [, rawCategory] = /^(@?.*?)[*?]?$/.exec(category);
3430
3411
  if (!rawCategory.startsWith("@")) {
3431
3412
  return node.matches(rawCategory);
3432
3413
  }
@@ -3459,10 +3440,11 @@ class Validator {
3459
3440
  }
3460
3441
  function validateKeys(rule) {
3461
3442
  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}"`);
3443
+ if (allowedKeys.has(key)) {
3444
+ continue;
3465
3445
  }
3446
+ const str = JSON.stringify(rule);
3447
+ throw new Error(`Permitted rule "${str}" contains unknown property "${key}"`);
3466
3448
  }
3467
3449
  }
3468
3450
  function parseQuantifier(quantifier) {
@@ -3529,9 +3511,8 @@ function ariaNaming(element) {
3529
3511
  if (role) {
3530
3512
  if (role instanceof DynamicValue) {
3531
3513
  return element.cacheSet(cacheKey, defaultValue);
3532
- } else {
3533
- return element.cacheSet(cacheKey, byRole(role));
3534
3514
  }
3515
+ return element.cacheSet(cacheKey, byRole(role));
3535
3516
  }
3536
3517
  const meta = element.meta;
3537
3518
  if (!meta) {
@@ -3716,9 +3697,8 @@ function isPresentation(node) {
3716
3697
  const role = node.getAttribute("role");
3717
3698
  if (role && (role.value === "presentation" || role.value === "none")) {
3718
3699
  return node.cacheSet(ROLE_PRESENTATION_CACHE, true);
3719
- } else {
3720
- return node.cacheSet(ROLE_PRESENTATION_CACHE, false);
3721
3700
  }
3701
+ return node.cacheSet(ROLE_PRESENTATION_CACHE, false);
3722
3702
  }
3723
3703
 
3724
3704
  const cachePrefix = classifyNodeText.name;
@@ -3736,13 +3716,14 @@ function getCachekey(options) {
3736
3716
  const { accessible = false, ignoreHiddenRoot = false } = options;
3737
3717
  if (accessible && ignoreHiddenRoot) {
3738
3718
  return IGNORE_HIDDEN_ROOT_A11Y_CACHE_KEY;
3739
- } else if (ignoreHiddenRoot) {
3719
+ }
3720
+ if (ignoreHiddenRoot) {
3740
3721
  return IGNORE_HIDDEN_ROOT_HTML_CACHE_KEY;
3741
- } else if (accessible) {
3722
+ }
3723
+ if (accessible) {
3742
3724
  return A11Y_CACHE_KEY;
3743
- } else {
3744
- return HTML_CACHE_KEY;
3745
3725
  }
3726
+ return HTML_CACHE_KEY;
3746
3727
  }
3747
3728
  function isSpecialEmpty(node) {
3748
3729
  return node.is("select") || node.is("textarea");
@@ -3774,7 +3755,7 @@ function classifyNodeText(node, options = {}) {
3774
3755
  }
3775
3756
  function findTextNodes(node, options) {
3776
3757
  const { accessible = false } = options;
3777
- let text = [];
3758
+ const text = [];
3778
3759
  for (const child of node.childNodes) {
3779
3760
  if (isTextNode(child)) {
3780
3761
  text.push(child);
@@ -3785,7 +3766,7 @@ function findTextNodes(node, options) {
3785
3766
  if (accessible && isAriaHidden(child, true).bySelf) {
3786
3767
  continue;
3787
3768
  }
3788
- text = text.concat(findTextNodes(child, options));
3769
+ text.push(...findTextNodes(child, options));
3789
3770
  }
3790
3771
  }
3791
3772
  return text;
@@ -3846,14 +3827,17 @@ function format(value, quote = false) {
3846
3827
  return String(value);
3847
3828
  }
3848
3829
  function interpolate(text, data) {
3849
- return text.replaceAll(/{{\s*([^\s{}]+)\s*}}/g, (match, key) => {
3830
+ return text.replaceAll(/\{\{\s*([^\s{}]+)\s*\}\}/g, (match, key) => {
3850
3831
  return data[key] !== void 0 ? format(data[key]) : match;
3851
3832
  });
3852
3833
  }
3853
3834
 
3854
- const ajv$1 = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
3855
- ajv$1.addMetaSchema(ajvSchemaDraft);
3856
- ajv$1.addKeyword(ajvRegexpKeyword);
3835
+ const ajv$1 = (() => {
3836
+ const ajv2 = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
3837
+ ajv2.addMetaSchema(ajvSchemaDraft);
3838
+ ajv2.addKeyword(ajvRegexpKeyword);
3839
+ return ajv2;
3840
+ })();
3857
3841
  function getSchemaValidator(ruleId, properties) {
3858
3842
  const $id = `rule/${ruleId}`;
3859
3843
  const cached = ajv$1.getSchema($id);
@@ -3874,10 +3858,9 @@ function isErrorDescriptor(value) {
3874
3858
  function unpackErrorDescriptor(value) {
3875
3859
  if (isErrorDescriptor(value)) {
3876
3860
  return value[0];
3877
- } else {
3878
- const [node, message, location, context] = value;
3879
- return { node, message, location, context };
3880
3861
  }
3862
+ const [node, message, location, context] = value;
3863
+ return { node, message, location, context };
3881
3864
  }
3882
3865
  class Rule {
3883
3866
  reporter;
@@ -4083,17 +4066,18 @@ class Rule {
4083
4066
  const callback = args.pop();
4084
4067
  const filter = args.pop() ?? (() => true);
4085
4068
  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
- }
4069
+ if (!this.isEnabled() || !filter(data)) {
4070
+ return;
4071
+ }
4072
+ this.event = data;
4073
+ const { tracker } = this;
4074
+ if (tracker) {
4075
+ const start = performance.now();
4076
+ callback(data);
4077
+ const end = performance.now();
4078
+ tracker.trackRule(this.name, end - start);
4079
+ } else {
4080
+ callback(data);
4097
4081
  }
4098
4082
  });
4099
4083
  }
@@ -4163,7 +4147,7 @@ class Rule {
4163
4147
  * @public
4164
4148
  * @virtual
4165
4149
  * @param context - Error context given by a reported error.
4166
- * @returns Rule documentation and url with additional details or `null` if no
4150
+ * @returns Rule documentation and URL with additional details or `null` if no
4167
4151
  * additional documentation is available.
4168
4152
  */
4169
4153
  documentation(_context) {
@@ -4202,7 +4186,7 @@ function parseAllow(value) {
4202
4186
  };
4203
4187
  }
4204
4188
  function matchList(value, list) {
4205
- if (list.include && !list.include.some((it) => it.test(value))) {
4189
+ if (list.include?.every((it) => !it.test(value))) {
4206
4190
  return false;
4207
4191
  }
4208
4192
  if (list.exclude?.some((it) => it.test(value))) {
@@ -4287,10 +4271,10 @@ class AllowedLinks extends Rule {
4287
4271
  return Boolean(attr && attr === key);
4288
4272
  }
4289
4273
  getStyle(value) {
4290
- if (/^([a-z]+:)?\/\//g.test(value)) {
4274
+ if (/^(?:[a-z]+:)?\/\//.test(value)) {
4291
4275
  return "external" /* EXTERNAL */;
4292
4276
  }
4293
- switch (value[0]) {
4277
+ switch (value.at(0)) {
4294
4278
  /* /foo/bar */
4295
4279
  case "/":
4296
4280
  return "absolute" /* ABSOLUTE */;
@@ -4309,7 +4293,8 @@ class AllowedLinks extends Rule {
4309
4293
  const { allowAbsolute } = this;
4310
4294
  if (allowAbsolute === true) {
4311
4295
  return;
4312
- } else if (allowAbsolute === false) {
4296
+ }
4297
+ if (allowAbsolute === false) {
4313
4298
  this.report(
4314
4299
  event.target,
4315
4300
  "Link destination must not be absolute url",
@@ -4329,7 +4314,8 @@ class AllowedLinks extends Rule {
4329
4314
  const { allowExternal } = this;
4330
4315
  if (allowExternal === true) {
4331
4316
  return;
4332
- } else if (allowExternal === false) {
4317
+ }
4318
+ if (allowExternal === false) {
4333
4319
  this.report(
4334
4320
  event.target,
4335
4321
  "Link destination must not be external url",
@@ -4349,7 +4335,8 @@ class AllowedLinks extends Rule {
4349
4335
  const { allowRelative } = this;
4350
4336
  if (allowRelative === true) {
4351
4337
  return false;
4352
- } else if (allowRelative === false) {
4338
+ }
4339
+ if (allowRelative === false) {
4353
4340
  this.report(
4354
4341
  event.target,
4355
4342
  "Link destination must not be relative url",
@@ -4357,7 +4344,8 @@ class AllowedLinks extends Rule {
4357
4344
  style
4358
4345
  );
4359
4346
  return true;
4360
- } else if (!matchList(target, allowRelative)) {
4347
+ }
4348
+ if (!matchList(target, allowRelative)) {
4361
4349
  this.report(
4362
4350
  event.target,
4363
4351
  "Relative link to this destination is not allowed by current configuration",
@@ -4372,7 +4360,8 @@ class AllowedLinks extends Rule {
4372
4360
  const { allowBase } = this.options;
4373
4361
  if (this.handleRelativePath(target, event, style)) {
4374
4362
  return;
4375
- } else if (!allowBase) {
4363
+ }
4364
+ if (!allowBase) {
4376
4365
  this.report(
4377
4366
  event.target,
4378
4367
  "Relative links must be relative to current folder",
@@ -4590,12 +4579,11 @@ class AriaLabelMisuse extends Rule {
4590
4579
  ].join("\n"),
4591
4580
  url
4592
4581
  };
4593
- } else {
4594
- return {
4595
- description: [`\`${context.attr}\` can only be used on:`, "", ...lines].join("\n"),
4596
- url
4597
- };
4598
4582
  }
4583
+ return {
4584
+ description: [`\`${context.attr}\` can only be used on:`, "", ...lines].join("\n"),
4585
+ url
4586
+ };
4599
4587
  }
4600
4588
  setup() {
4601
4589
  this.on("dom:ready", (event) => {
@@ -4653,6 +4641,7 @@ class AriaLabelMisuse extends Rule {
4653
4641
  }
4654
4642
 
4655
4643
  class ConfigError extends UserError {
4644
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
4656
4645
  constructor(message, nested) {
4657
4646
  super(message, nested);
4658
4647
  this.name = "ConfigError";
@@ -4773,9 +4762,8 @@ class AttrCase extends Rule {
4773
4762
  isIgnored(node) {
4774
4763
  if (this.options.ignoreForeign) {
4775
4764
  return Boolean(node.meta?.foreign);
4776
- } else {
4777
- return false;
4778
4765
  }
4766
+ return false;
4779
4767
  }
4780
4768
  }
4781
4769
 
@@ -4825,10 +4813,11 @@ class Context {
4825
4813
  let lastNewline = -1;
4826
4814
  let newlines = 0;
4827
4815
  for (let i = 0; i < n; i++) {
4828
- if (this.string[i] === "\n") {
4829
- newlines++;
4830
- lastNewline = i;
4816
+ if (this.string[i] !== "\n") {
4817
+ continue;
4831
4818
  }
4819
+ newlines++;
4820
+ lastNewline = i;
4832
4821
  }
4833
4822
  if (newlines > 0) {
4834
4823
  this.line += newlines;
@@ -4890,28 +4879,29 @@ const MATCH_DOCTYPE_CLOSE = /^>/;
4890
4879
  const MATCH_XML_TAG = /^<\?xml.*?\?>\s+/;
4891
4880
  const MATCH_TAG_OPEN = /^<(\/?)([\w:\-]+)/;
4892
4881
  const MATCH_TAG_CLOSE = /^\/?>/;
4893
- const MATCH_TEXT = /^[^]*?(?=(?:[\t ]*(?:\r\n|\r|\n)|<[^ ]|$))/;
4882
+ const MATCH_TEXT = /^[\s\S]*?(?=[\t ]*(?:\r\n|\r|\n)|<[^ ]|$)/;
4894
4883
  const MATCH_TEMPLATING = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)/s;
4895
- const MATCH_TAG_LOOKAHEAD = /^[^]*?(?=<|$)/;
4884
+ const MATCH_TAG_LOOKAHEAD = /^[\s\S]*?(?=<|$)/;
4896
4885
  const MATCH_ATTR_START = /^([^\t\n\f\r "'/<=>]+)/;
4897
- const MATCH_ATTR_SINGLE = /^(\s*=\s*)'([^']*?)(')/;
4898
- const MATCH_ATTR_DOUBLE = /^(\s*=\s*)"([^"]*?)(")/;
4886
+ const MATCH_ATTR_SINGLE = /^(\s*=\s*)'([^']*)(')/;
4887
+ const MATCH_ATTR_DOUBLE = /^(\s*=\s*)"([^"]*)(")/;
4899
4888
  const MATCH_ATTR_UNQUOTED = /^(\s*=\s*)([^\t\n\f\r "'<>][^\t\n\f\r <>]*)/;
4900
4889
  const MATCH_CDATA_BEGIN = /^<!\[CDATA\[/;
4901
- const MATCH_CDATA_END = /^[^]*?]]>/;
4902
- const MATCH_SCRIPT_DATA = /^[^]*?(?=<\/script)/;
4890
+ const MATCH_CDATA_END = /^[\s\S]*?\]\]>/;
4891
+ const MATCH_SCRIPT_DATA = /^[\s\S]*?(?=<\/script)/;
4903
4892
  const MATCH_SCRIPT_END = /^<(\/)(script)/;
4904
- const MATCH_STYLE_DATA = /^[^]*?(?=<\/style)/;
4893
+ const MATCH_STYLE_DATA = /^[\s\S]*?(?=<\/style)/;
4905
4894
  const MATCH_STYLE_END = /^<(\/)(style)/;
4906
- const MATCH_TEXTAREA_DATA = /^[^]*?(?=<\/textarea)/;
4895
+ const MATCH_TEXTAREA_DATA = /^[\s\S]*?(?=<\/textarea)/;
4907
4896
  const MATCH_TEXTAREA_END = /^<(\/)(textarea)/;
4908
- const MATCH_TITLE_DATA = /^[^]*?(?=<\/title)/;
4897
+ const MATCH_TITLE_DATA = /^[\s\S]*?(?=<\/title)/;
4909
4898
  const MATCH_TITLE_END = /^<(\/)(title)/;
4910
- const MATCH_DIRECTIVE = /^(<!--\s*\[?)(html-validate-)([\da-z-]+)(\s*)(.*?)(]?\s*-->)/;
4911
- const MATCH_COMMENT = /^<!--([^]*?)-->/;
4912
- const MATCH_CONDITIONAL = /^<!\[([^\]]*?)]>/;
4899
+ const MATCH_DIRECTIVE = /^(<!--\s*\[?)(html-validate-)([\da-z-]+)(\s*)(.*?)(\]?\s*-->)/;
4900
+ const MATCH_COMMENT = /^<!--([\s\S]*?)-->/;
4901
+ const MATCH_CONDITIONAL = /^<!\[([^\]]*)\]>/;
4913
4902
  class InvalidTokenError extends Error {
4914
4903
  location;
4904
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
4915
4905
  constructor(location, message) {
4916
4906
  super(message);
4917
4907
  this.name = "InvalidTokenError";
@@ -4995,9 +4985,8 @@ class Lexer {
4995
4985
  evalNextState(nextState, token) {
4996
4986
  if (typeof nextState === "function") {
4997
4987
  return nextState(token);
4998
- } else {
4999
- return nextState;
5000
4988
  }
4989
+ return nextState;
5001
4990
  }
5002
4991
  *match(context, tests, error) {
5003
4992
  const n = tests.length;
@@ -5084,27 +5073,26 @@ class Lexer {
5084
5073
  case ContentModel.SCRIPT:
5085
5074
  if (selfClosed) {
5086
5075
  return State.SCRIPT;
5087
- } else {
5088
- return State.TEXT;
5089
5076
  }
5077
+ return State.TEXT;
5078
+ /* <script/> (not legal but handle it anyway so the lexer doesn't choke on it) */
5090
5079
  case ContentModel.STYLE:
5091
5080
  if (selfClosed) {
5092
5081
  return State.STYLE;
5093
- } else {
5094
- return State.TEXT;
5095
5082
  }
5083
+ return State.TEXT;
5084
+ /* <style/> */
5096
5085
  case ContentModel.TEXTAREA:
5097
5086
  if (selfClosed) {
5098
5087
  return State.TEXTAREA;
5099
- } else {
5100
- return State.TEXT;
5101
5088
  }
5089
+ return State.TEXT;
5090
+ /* <textarea/> */
5102
5091
  case ContentModel.TITLE:
5103
5092
  if (selfClosed) {
5104
5093
  return State.TITLE;
5105
- } else {
5106
- return State.TEXT;
5107
5094
  }
5095
+ return State.TEXT;
5108
5096
  }
5109
5097
  }
5110
5098
  yield* this.match(
@@ -5191,7 +5179,7 @@ class Lexer {
5191
5179
  }
5192
5180
  }
5193
5181
 
5194
- const whitespace = /(\s+)/;
5182
+ const whitespace = /\s+/;
5195
5183
  class AttrDelimiter extends Rule {
5196
5184
  documentation() {
5197
5185
  return {
@@ -5223,17 +5211,15 @@ const defaults$y = {
5223
5211
  function generateRegexp(pattern) {
5224
5212
  if (Array.isArray(pattern)) {
5225
5213
  return new RegExp(`^(${pattern.join("|")})$`, "i");
5226
- } else {
5227
- return new RegExp(`^${pattern}$`, "i");
5228
5214
  }
5215
+ return new RegExp(`^${pattern}$`, "i");
5229
5216
  }
5230
5217
  function generateMessage(name, pattern) {
5231
5218
  if (Array.isArray(pattern)) {
5232
5219
  const patterns = pattern.map((it) => `/${it}/`).join(", ");
5233
5220
  return `Attribute "${name}" should match one of [${patterns}]`;
5234
- } else {
5235
- return `Attribute "${name}" should match /${pattern}/`;
5236
5221
  }
5222
+ return `Attribute "${name}" should match /${pattern}/`;
5237
5223
  }
5238
5224
  function generateDescription(name, pattern) {
5239
5225
  if (Array.isArray(pattern)) {
@@ -5242,9 +5228,8 @@ function generateDescription(name, pattern) {
5242
5228
  "",
5243
5229
  ...pattern.map((it) => `- \`/${it}/\``)
5244
5230
  ].join("\n");
5245
- } else {
5246
- return `Attribute "${name}" should match the regular expression \`/${pattern}/\``;
5247
5231
  }
5232
+ return `Attribute "${name}" should match the regular expression \`/${pattern}/\``;
5248
5233
  }
5249
5234
  class AttrPattern extends Rule {
5250
5235
  pattern;
@@ -5290,9 +5275,8 @@ class AttrPattern extends Rule {
5290
5275
  isIgnored(node) {
5291
5276
  if (this.options.ignoreForeign) {
5292
5277
  return Boolean(node.meta?.foreign);
5293
- } else {
5294
- return false;
5295
5278
  }
5279
+ return false;
5296
5280
  }
5297
5281
  }
5298
5282
 
@@ -5403,9 +5387,8 @@ class AttrQuotes extends Rule {
5403
5387
  resolveQuotemark(value, style) {
5404
5388
  if (style === "auto" /* AUTO_QUOTE */) {
5405
5389
  return value.includes('"') ? "'" : '"';
5406
- } else {
5407
- return style;
5408
5390
  }
5391
+ return style;
5409
5392
  }
5410
5393
  }
5411
5394
  function parseStyle$3(style) {
@@ -5463,11 +5446,11 @@ class AttributeAllowedValues extends Rule {
5463
5446
  const allowedList = allowed.enum.map((value2) => {
5464
5447
  if (typeof value2 === "string") {
5465
5448
  return `- \`"${value2}"\``;
5466
- } else if (value2 instanceof RegExp) {
5449
+ }
5450
+ if (value2 instanceof RegExp) {
5467
5451
  return `- \`${value2.toString()}\``;
5468
- } else {
5469
- return `- ${value2.name}`;
5470
5452
  }
5453
+ return `- ${value2.name}`;
5471
5454
  });
5472
5455
  docs.description = [
5473
5456
  `The \`<${element}>\` element does not allow the attribute \`${attribute}\` to have the value \`"${value}"\`.`,
@@ -5511,9 +5494,8 @@ class AttributeAllowedValues extends Rule {
5511
5494
  const { key, value } = attr;
5512
5495
  if (value !== null) {
5513
5496
  return `Attribute "${key}" has invalid value "${value.toString()}"`;
5514
- } else {
5515
- return `Attribute "${key}" is missing value`;
5516
5497
  }
5498
+ return `Attribute "${key}" is missing value`;
5517
5499
  }
5518
5500
  getLocation(attr) {
5519
5501
  return attr.valueLocation ?? attr.keyLocation;
@@ -5800,10 +5782,10 @@ class AutocompletePassword extends Rule {
5800
5782
  const tokens = new DOMTokenList(raw, autocomplete.valueLocation);
5801
5783
  const index = tokens.findIndex((token) => !isGroupingToken(token));
5802
5784
  const value = tokens.item(index);
5803
- const location = tokens.location(index);
5804
5785
  if (!value) {
5805
5786
  return;
5806
5787
  }
5788
+ const location = tokens.location(index);
5807
5789
  if (value === "off") {
5808
5790
  const context = { kind: "off" };
5809
5791
  this.report({
@@ -5888,9 +5870,8 @@ function parsePattern(pattern) {
5888
5870
  function toArray$2(value) {
5889
5871
  if (Array.isArray(value)) {
5890
5872
  return value;
5891
- } else {
5892
- return [value];
5893
5873
  }
5874
+ return [value];
5894
5875
  }
5895
5876
  function validateAllowedPatterns(patterns, allowedPatterns, ruleId) {
5896
5877
  const extraneous = patterns.filter(isNamedPattern).filter((p) => !allowedPatterns.has(p));
@@ -5976,7 +5957,7 @@ class ClassPattern extends BasePatternRule {
5976
5957
  });
5977
5958
  }
5978
5959
  static schema() {
5979
- return BasePatternRule.schema();
5960
+ return super.schema();
5980
5961
  }
5981
5962
  documentation(context) {
5982
5963
  return {
@@ -6057,10 +6038,10 @@ class CloseOrder extends Rule {
6057
6038
  });
6058
6039
  this.on("tag:end", (event) => {
6059
6040
  const current = event.target;
6060
- const active = event.previous;
6061
6041
  if (current) {
6062
6042
  return;
6063
6043
  }
6044
+ const active = event.previous;
6064
6045
  for (const ancestor of ancestors(active)) {
6065
6046
  if (ancestor.isRootElement() || reported.has(ancestor.unique)) {
6066
6047
  continue;
@@ -6071,13 +6052,13 @@ class CloseOrder extends Rule {
6071
6052
  });
6072
6053
  this.on("tag:end", (event) => {
6073
6054
  const current = event.target;
6074
- const active = event.previous;
6075
6055
  if (!current) {
6076
6056
  return;
6077
6057
  }
6078
6058
  if (current.voidElement) {
6079
6059
  return;
6080
6060
  }
6061
+ const active = event.previous;
6081
6062
  if (active.closed === Node.CLOSED_IMPLICIT_CLOSED) {
6082
6063
  return;
6083
6064
  }
@@ -6172,7 +6153,7 @@ class Deprecated extends Rule {
6172
6153
  text.push(context.documentation);
6173
6154
  }
6174
6155
  const doc = {
6175
- description: text.map((cur) => cur.replaceAll("$tagname", context.tagName)).join("\n\n"),
6156
+ description: text.map((cur) => cur.replaceAll("$tagname", () => context.tagName)).join("\n\n"),
6176
6157
  url: "https://html-validate.org/rules/deprecated.html"
6177
6158
  };
6178
6159
  return doc;
@@ -6571,7 +6552,7 @@ class ElementName extends Rule {
6571
6552
  ];
6572
6553
  }
6573
6554
  setup() {
6574
- const xmlns = /^(.+):.+$/;
6555
+ const xmlns = /^[^:]+:.+$/;
6575
6556
  this.on("tag:start", (event) => {
6576
6557
  const target = event.target;
6577
6558
  const tagName = target.tagName;
@@ -6610,13 +6591,12 @@ function isNativeTemplate(node) {
6610
6591
  function getTransparentChildren(node, transparent) {
6611
6592
  if (typeof transparent === "boolean") {
6612
6593
  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
6594
  }
6595
+ return node.childElements.filter((it) => {
6596
+ return transparent.some((category) => {
6597
+ return Validator.validatePermittedCategory(it, category, false);
6598
+ });
6599
+ });
6620
6600
  }
6621
6601
  function getRuleDescription$2(context) {
6622
6602
  switch (context.kind) {
@@ -6648,6 +6628,7 @@ class ElementPermittedContent extends Rule {
6648
6628
  [
6649
6629
  () => this.validatePermittedContent(node, parent),
6650
6630
  () => this.validatePermittedDescendant(node, parent)
6631
+ /* eslint-disable-next-line unicorn/no-unused-array-method-return -- technical debt, should use iterator helpers */
6651
6632
  ].some((fn) => fn());
6652
6633
  });
6653
6634
  });
@@ -6793,14 +6774,12 @@ function getRuleDescription$1(context) {
6793
6774
  const allowed = rules.filter(isCategoryOrTag).map((it) => {
6794
6775
  if (isCategory$1(it)) {
6795
6776
  return `- any ${it.slice(1)} element`;
6796
- } else {
6797
- return `- \`<${it}>\``;
6798
6777
  }
6778
+ return `- \`<${it}>\``;
6799
6779
  });
6800
6780
  return [preamble, "", "Allowed parents one of:", "", ...allowed];
6801
- } else {
6802
- return [preamble];
6803
6781
  }
6782
+ return [preamble];
6804
6783
  }
6805
6784
  function formatMessage$1(node, parent, rules) {
6806
6785
  const nodeName = node.annotatedName;
@@ -6852,7 +6831,7 @@ class ElementPermittedParent extends Rule {
6852
6831
  }
6853
6832
 
6854
6833
  function isTagnameOnly(value) {
6855
- return /^[\dA-Za-z-]+$/.test(value);
6834
+ return /^[\dA-Z-]+$/i.test(value);
6856
6835
  }
6857
6836
  function getRuleDescription(context) {
6858
6837
  const escaped = context.ancestor.map((it) => `\`${it}\``);
@@ -6915,9 +6894,8 @@ function normalizeRequired(element, attr) {
6915
6894
  default:
6916
6895
  return result;
6917
6896
  }
6918
- } else {
6919
- return required ? defaultMessage : false;
6920
6897
  }
6898
+ return required ? defaultMessage : false;
6921
6899
  }
6922
6900
  class ElementRequiredAttributes extends Rule {
6923
6901
  documentation(context) {
@@ -6999,7 +6977,8 @@ const selector = ["h1", "h2", "h3", "h4", "h5", "h6"].join(",");
6999
6977
  function hasImgAltText$1(node) {
7000
6978
  if (node.is("img")) {
7001
6979
  return hasAltText(node);
7002
- } else if (node.is("svg")) {
6980
+ }
6981
+ if (node.is("svg")) {
7003
6982
  return node.textContent.trim() !== "";
7004
6983
  }
7005
6984
  return false;
@@ -7280,21 +7259,19 @@ class FormDupName extends Rule {
7280
7259
  const existing = group.cacheGet(UNIQUE_CACHE_KEY);
7281
7260
  if (existing) {
7282
7261
  return existing;
7283
- } else {
7284
- const elements = /* @__PURE__ */ new Map();
7285
- group.cacheSet(UNIQUE_CACHE_KEY, elements);
7286
- return elements;
7287
7262
  }
7263
+ const elements = /* @__PURE__ */ new Map();
7264
+ group.cacheSet(UNIQUE_CACHE_KEY, elements);
7265
+ return elements;
7288
7266
  }
7289
7267
  getSharedElements(group) {
7290
7268
  const existing = group.cacheGet(SHARED_CACHE_KEY);
7291
7269
  if (existing) {
7292
7270
  return existing;
7293
- } else {
7294
- const elements = /* @__PURE__ */ new Map();
7295
- group.cacheSet(SHARED_CACHE_KEY, elements);
7296
- return elements;
7297
7271
  }
7272
+ const elements = /* @__PURE__ */ new Map();
7273
+ group.cacheSet(SHARED_CACHE_KEY, elements);
7274
+ return elements;
7298
7275
  }
7299
7276
  }
7300
7277
 
@@ -7308,12 +7285,11 @@ function isRelevant$5(event) {
7308
7285
  return Boolean(node.meta?.heading);
7309
7286
  }
7310
7287
  function extractLevel(node) {
7311
- const match = /^[Hh](\d)$/.exec(node.tagName);
7288
+ const match = /^H(\d)$/i.exec(node.tagName);
7312
7289
  if (match) {
7313
- return Number.parseInt(match[1], 10);
7314
- } else {
7315
- return null;
7290
+ return Math.trunc(Number(match[1]));
7316
7291
  }
7292
+ return null;
7317
7293
  }
7318
7294
  function parseMaxInitial(value) {
7319
7295
  if (value === false || value === "any") {
@@ -7323,7 +7299,7 @@ function parseMaxInitial(value) {
7323
7299
  if (!match) {
7324
7300
  return 1;
7325
7301
  }
7326
- return Number.parseInt(match[1], 10);
7302
+ return Math.trunc(Number(match[1]));
7327
7303
  }
7328
7304
  class HeadingLevel extends Rule {
7329
7305
  minInitialRank;
@@ -7590,7 +7566,7 @@ class IdPattern extends BasePatternRule {
7590
7566
  });
7591
7567
  }
7592
7568
  static schema() {
7593
- return BasePatternRule.schema();
7569
+ return super.schema();
7594
7570
  }
7595
7571
  documentation(context) {
7596
7572
  return {
@@ -7812,24 +7788,23 @@ function isHidden(node, context) {
7812
7788
  const { reference } = context;
7813
7789
  if (reference?.isSameNode(node)) {
7814
7790
  return false;
7815
- } else {
7816
- return !inAccessibilityTree(node);
7817
7791
  }
7792
+ return !inAccessibilityTree(node);
7818
7793
  }
7819
7794
  function hasImgAltText(node, context) {
7820
7795
  if (node.is("img")) {
7821
7796
  return hasAltText(node);
7822
- } else if (node.is("svg")) {
7797
+ }
7798
+ if (node.is("svg")) {
7823
7799
  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
- }
7800
+ }
7801
+ for (const img of node.querySelectorAll("img, svg")) {
7802
+ const hasName = hasAccessibleNameImpl(img, context);
7803
+ if (hasName) {
7804
+ return true;
7830
7805
  }
7831
- return false;
7832
7806
  }
7807
+ return false;
7833
7808
  }
7834
7809
  function hasLabel(node) {
7835
7810
  const value = node.getAttributeValue("aria-label") ?? "";
@@ -7960,7 +7935,7 @@ class InputMissingLabel extends Rule {
7960
7935
  this.report(elem, `<${elem.tagName}> element has <label> but <label> element is hidden`);
7961
7936
  return;
7962
7937
  }
7963
- if (!labels.some((label) => hasAccessibleName(root, label))) {
7938
+ if (labels.every((label) => !hasAccessibleName(root, label))) {
7964
7939
  this.report(elem, `<${elem.tagName}> element has <label> but <label> has no text`);
7965
7940
  }
7966
7941
  }
@@ -8147,12 +8122,11 @@ function parseContent(text) {
8147
8122
  const match = /^(\d+)(?:\s*;\s*url=(.*))?/i.exec(text);
8148
8123
  if (match) {
8149
8124
  return {
8150
- delay: Number.parseInt(match[1], 10),
8125
+ delay: Math.trunc(Number(match[1])),
8151
8126
  url: match[2]
8152
8127
  };
8153
- } else {
8154
- return null;
8155
8128
  }
8129
+ return null;
8156
8130
  }
8157
8131
 
8158
8132
  class MissingDoctype extends Rule {
@@ -8229,7 +8203,7 @@ class NamePattern extends BasePatternRule {
8229
8203
  });
8230
8204
  }
8231
8205
  static schema() {
8232
- return BasePatternRule.schema();
8206
+ return super.schema();
8233
8207
  }
8234
8208
  documentation(context) {
8235
8209
  return {
@@ -8412,10 +8386,10 @@ class NoDeprecatedAttr extends Rule {
8412
8386
  this.on("attr", (event) => {
8413
8387
  const node = event.target;
8414
8388
  const meta = node.meta;
8415
- const attr = event.key.toLowerCase();
8416
8389
  if (meta === null) {
8417
8390
  return;
8418
8391
  }
8392
+ const attr = event.key.toLowerCase();
8419
8393
  const metaAttribute = meta.attributes[attr];
8420
8394
  if (!metaAttribute) {
8421
8395
  return;
@@ -8449,7 +8423,7 @@ class NoDupAttr extends Rule {
8449
8423
  return;
8450
8424
  }
8451
8425
  const name = event.key.toLowerCase();
8452
- if (name in attr) {
8426
+ if (Object.hasOwn(attr, name)) {
8453
8427
  this.report(event.target, `Attribute "${name}" duplicated`, event.keyLocation);
8454
8428
  }
8455
8429
  attr[event.key] = true;
@@ -8522,10 +8496,9 @@ function getExisting(element, root) {
8522
8496
  const existing = group.cacheGet(CACHE_KEY);
8523
8497
  if (existing) {
8524
8498
  return existing;
8525
- } else {
8526
- const existing2 = /* @__PURE__ */ new Set();
8527
- return group.cacheSet(CACHE_KEY, existing2);
8528
8499
  }
8500
+ const value = /* @__PURE__ */ new Set();
8501
+ return group.cacheSet(CACHE_KEY, value);
8529
8502
  }
8530
8503
 
8531
8504
  function isRelevant$2(event) {
@@ -8796,10 +8769,11 @@ class NoMissingReferences extends Rule {
8796
8769
  }
8797
8770
  }
8798
8771
  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);
8772
+ if (!idMissing(document, id)) {
8773
+ return;
8802
8774
  }
8775
+ const context = { key: attr.key, value: id };
8776
+ this.report(node, `Element references missing id "${id}"`, attr.valueLocation, context);
8803
8777
  }
8804
8778
  validateList(document, node, attr, values) {
8805
8779
  const parsed = new DOMTokenList(values, attr.valueLocation);
@@ -8839,9 +8813,9 @@ class NoMultipleMain extends Rule {
8839
8813
  const defaults$f = {
8840
8814
  relaxed: false
8841
8815
  };
8842
- const textRegexp = /(<|&(?![\d#A-Za-z]+;))/g;
8843
- const unquotedAttrRegexp = /(["'<=>`]|&(?![\d#A-Za-z]+;))/g;
8844
- const matchTemplate = /^(<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
8816
+ const textRegexp = /(<|&(?![\d#A-Z]+;))/gi;
8817
+ const unquotedAttrRegexp = /(["'<=>`]|&(?![\d#A-Z]+;))/gi;
8818
+ const matchTemplate = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
8845
8819
  const replacementTable = {
8846
8820
  '"': "&quot;",
8847
8821
  "&": "&amp;",
@@ -9073,7 +9047,7 @@ class NoRedundantRole extends Rule {
9073
9047
  }
9074
9048
  }
9075
9049
 
9076
- const xmlns = /^(.+):.+$/;
9050
+ const xmlns = /^[^:]+:.+$/;
9077
9051
  const defaults$d = {
9078
9052
  ignoreForeign: true,
9079
9053
  ignoreXML: true
@@ -9195,11 +9169,11 @@ class NoUnknownAttributes extends Rule {
9195
9169
  this.on("attr", (event) => {
9196
9170
  const node = event.target;
9197
9171
  const meta = node.meta;
9198
- const attr = event.key.toLowerCase();
9199
9172
  if (meta === null) {
9200
9173
  return;
9201
9174
  }
9202
- if (attr in meta.attributes) {
9175
+ const attr = event.key.toLowerCase();
9176
+ if (Object.hasOwn(meta.attributes, attr)) {
9203
9177
  return;
9204
9178
  }
9205
9179
  if (isPatternAttribute(attr, meta.patternAttributes)) {
@@ -9606,7 +9580,7 @@ const defaults$7 = {
9606
9580
  include: null,
9607
9581
  exclude: null
9608
9582
  };
9609
- const crossorigin = new RegExp("^(\\w+://|//)");
9583
+ const crossorigin = /^(?:\w+:\/\/|\/\/)/;
9610
9584
  const supportSri = {
9611
9585
  link: "href",
9612
9586
  script: "src"
@@ -9819,7 +9793,10 @@ function constructRegex(characters) {
9819
9793
  return new RegExp(pattern, "g");
9820
9794
  }
9821
9795
  function getText(node) {
9822
- const match = /^(\s*)(.*)$/.exec(node.textContent);
9796
+ const match = /^(\s*)(\S.*)$/.exec(node.textContent);
9797
+ if (!match) {
9798
+ return [0, ""];
9799
+ }
9823
9800
  const [, leading, text] = match;
9824
9801
  return [leading.length, text.trimEnd()];
9825
9802
  }
@@ -9972,9 +9949,8 @@ function hasDefaultText(node) {
9972
9949
  function isNonEmptyText(node) {
9973
9950
  if (isTextNode(node)) {
9974
9951
  return node.isDynamic || node.textContent.trim() !== "";
9975
- } else {
9976
- return false;
9977
9952
  }
9953
+ return false;
9978
9954
  }
9979
9955
  function haveAccessibleText(node) {
9980
9956
  if (!inAccessibilityTree(node)) {
@@ -10109,15 +10085,14 @@ function getTextFromReference(document, id) {
10109
10085
  const ref = document.querySelector(selector);
10110
10086
  if (ref) {
10111
10087
  return ref.textContent;
10112
- } else {
10113
- return selector;
10114
10088
  }
10089
+ return selector;
10115
10090
  }
10116
10091
  function groupBy(values, callback) {
10117
10092
  const result = {};
10118
10093
  for (const value of values) {
10119
10094
  const key = callback(value);
10120
- if (key in result) {
10095
+ if (Object.hasOwn(result, key)) {
10121
10096
  result[key].push(value);
10122
10097
  } else {
10123
10098
  result[key] = [value];
@@ -10217,7 +10192,7 @@ const defaults$5 = {
10217
10192
  ignoreCase: false,
10218
10193
  requireSemicolon: true
10219
10194
  };
10220
- const regexp$1 = /&(?:[\da-z]+|#x?[\da-f]+)(;|[^\da-z]|$)/gi;
10195
+ const regexp$1 = /&(?:[\da-z]+|#x?[\da-f]+)([^\da-z]|$)/gi;
10221
10196
  const lowercaseEntities = entities$1.map((it) => it.toLowerCase());
10222
10197
  function isNumerical(entity) {
10223
10198
  return entity.startsWith("&#");
@@ -10296,9 +10271,8 @@ class UnknownCharReference extends Rule {
10296
10271
  get entities() {
10297
10272
  if (this.options.ignoreCase) {
10298
10273
  return lowercaseEntities;
10299
- } else {
10300
- return entities$1;
10301
10274
  }
10275
+ return entities$1;
10302
10276
  }
10303
10277
  findCharacterReferences(node, text, location, { isAttribute }) {
10304
10278
  const delimiter = text.search(/[#?]/);
@@ -10664,7 +10638,6 @@ class ValidAutocomplete extends Rule {
10664
10638
  }
10665
10639
  validateControlAutocomplete(node, tokens, keyLocation) {
10666
10640
  const type = node.getAttributeValue("type") ?? "text";
10667
- const mantle = type !== "hidden" ? "expectation" : "anchor";
10668
10641
  if (isDisallowedType(node, type)) {
10669
10642
  const context = {
10670
10643
  msg: 0 /* InvalidAttribute */,
@@ -10679,6 +10652,7 @@ class ValidAutocomplete extends Rule {
10679
10652
  return;
10680
10653
  }
10681
10654
  if (tokens.includes("on") || tokens.includes("off")) {
10655
+ const mantle = type !== "hidden" ? "expectation" : "anchor";
10682
10656
  this.validateOnOff(node, mantle, tokens);
10683
10657
  return;
10684
10658
  }
@@ -10802,44 +10776,46 @@ class ValidAutocomplete extends Rule {
10802
10776
  * Ensure contact token is only used with field names from the second list.
10803
10777
  */
10804
10778
  validateContact(node, tokens, order) {
10805
- if (order.includes("contact") && order.includes("field1")) {
10806
- const a = order.indexOf("field1");
10807
- const b = order.indexOf("contact");
10779
+ if (!order.includes("contact") || !order.includes("field1")) {
10780
+ return;
10781
+ }
10782
+ const a = order.indexOf("field1");
10783
+ const b = order.indexOf("contact");
10784
+ const context = {
10785
+ msg: 4 /* InvalidCombination */,
10786
+ /* eslint-disable @typescript-eslint/no-non-null-assertion -- it must be present of it wouldn't be found */
10787
+ first: tokens.item(a),
10788
+ second: tokens.item(b)
10789
+ /* eslint-enable @typescript-eslint/no-non-null-assertion */
10790
+ };
10791
+ this.report({
10792
+ node,
10793
+ message: getTerminalMessage(context),
10794
+ location: tokens.location(b),
10795
+ context
10796
+ });
10797
+ }
10798
+ validateOrder(node, tokens, order) {
10799
+ const indicies = order.map((it) => expectedOrder.indexOf(it));
10800
+ for (let i = 0; i < indicies.length - 1; i++) {
10801
+ if (indicies[0] <= indicies[i + 1]) {
10802
+ continue;
10803
+ }
10808
10804
  const context = {
10809
- msg: 4 /* InvalidCombination */,
10805
+ msg: 2 /* InvalidOrder */,
10810
10806
  /* 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)
10807
+ first: tokens.item(i),
10808
+ second: tokens.item(i + 1)
10813
10809
  /* eslint-enable @typescript-eslint/no-non-null-assertion */
10814
10810
  };
10815
10811
  this.report({
10816
10812
  node,
10817
10813
  message: getTerminalMessage(context),
10818
- location: tokens.location(b),
10814
+ location: tokens.location(i + 1),
10819
10815
  context
10820
10816
  });
10821
10817
  }
10822
10818
  }
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
10819
  validateControlGroup(node, tokens, fieldTokens) {
10844
10820
  const numFields = fieldTokens.filter(Boolean).length;
10845
10821
  if (numFields === 0) {
@@ -10931,7 +10907,7 @@ class ValidID extends Rule {
10931
10907
  documentation(context) {
10932
10908
  const { relaxed } = this.options;
10933
10909
  const { kind, id } = context;
10934
- const message = this.messages[kind].replace(`"{{ id }}"`, "`{{ id }}`").replace("id", "ID").replace(/^(.)/, (m) => m.toUpperCase());
10910
+ const message = this.messages[kind].replace(`"{{ id }}"`, "`{{ id }}`").replace("id", "ID").replace(/^./, (m) => m.toUpperCase());
10935
10911
  const relaxedDescription = relaxed ? [] : [
10936
10912
  " - ID must begin with a letter",
10937
10913
  " - ID must only contain letters, digits, `-` and `_`"
@@ -10969,7 +10945,7 @@ class ValidID extends Rule {
10969
10945
  if (relaxed) {
10970
10946
  return;
10971
10947
  }
10972
- if (/^[^\p{L}]/u.test(value)) {
10948
+ if (new RegExp("^\\P{L}", "u").test(value)) {
10973
10949
  const context = { kind: 3 /* LEADING_CHARACTER */, id: value };
10974
10950
  this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10975
10951
  return;
@@ -11330,7 +11306,7 @@ function isSimpleTable(table) {
11330
11306
  return false;
11331
11307
  }
11332
11308
  const numColumns = cells[0].length;
11333
- if (!cells.every((row) => row.length === numColumns)) {
11309
+ if (cells.some((row) => row.length !== numColumns)) {
11334
11310
  return false;
11335
11311
  }
11336
11312
  const shape = getShape(cells);
@@ -11984,7 +11960,7 @@ class ResolvedConfig {
11984
11960
  }
11985
11961
 
11986
11962
  function haveResolver(key, value) {
11987
- return key in value;
11963
+ return Object.hasOwn(value, key);
11988
11964
  }
11989
11965
  function haveConfigResolver(value) {
11990
11966
  return haveResolver("resolveConfig", value);
@@ -11999,7 +11975,10 @@ function haveTransformerResolver(value) {
11999
11975
  return haveResolver("resolveTransformer", value);
12000
11976
  }
12001
11977
  function resolveConfig(resolvers, id, options) {
12002
- for (const resolver of resolvers.filter(haveConfigResolver)) {
11978
+ for (const resolver of resolvers) {
11979
+ if (!haveConfigResolver(resolver)) {
11980
+ continue;
11981
+ }
12003
11982
  const config = resolver.resolveConfig(id, options);
12004
11983
  if (isThenable(config)) {
12005
11984
  return resolveConfigAsync(resolvers, id, options);
@@ -12011,7 +11990,10 @@ function resolveConfig(resolvers, id, options) {
12011
11990
  throw new UserError(`Failed to load configuration from "${id}"`);
12012
11991
  }
12013
11992
  async function resolveConfigAsync(resolvers, id, options) {
12014
- for (const resolver of resolvers.filter(haveConfigResolver)) {
11993
+ for (const resolver of resolvers) {
11994
+ if (!haveConfigResolver(resolver)) {
11995
+ continue;
11996
+ }
12015
11997
  const config = await resolver.resolveConfig(id, options);
12016
11998
  if (config) {
12017
11999
  return config;
@@ -12020,7 +12002,10 @@ async function resolveConfigAsync(resolvers, id, options) {
12020
12002
  throw new UserError(`Failed to load configuration from "${id}"`);
12021
12003
  }
12022
12004
  function resolveElements(resolvers, id, options) {
12023
- for (const resolver of resolvers.filter(haveElementsResolver)) {
12005
+ for (const resolver of resolvers) {
12006
+ if (!haveElementsResolver(resolver)) {
12007
+ continue;
12008
+ }
12024
12009
  const elements = resolver.resolveElements(id, options);
12025
12010
  if (isThenable(elements)) {
12026
12011
  return resolveElementsAsync(resolvers, id, options);
@@ -12032,7 +12017,10 @@ function resolveElements(resolvers, id, options) {
12032
12017
  throw new UserError(`Failed to load elements from "${id}"`);
12033
12018
  }
12034
12019
  async function resolveElementsAsync(resolvers, id, options) {
12035
- for (const resolver of resolvers.filter(haveElementsResolver)) {
12020
+ for (const resolver of resolvers) {
12021
+ if (!haveElementsResolver(resolver)) {
12022
+ continue;
12023
+ }
12036
12024
  const elements = await resolver.resolveElements(id, options);
12037
12025
  if (elements) {
12038
12026
  return elements;
@@ -12041,7 +12029,10 @@ async function resolveElementsAsync(resolvers, id, options) {
12041
12029
  throw new UserError(`Failed to load elements from "${id}"`);
12042
12030
  }
12043
12031
  function resolvePlugin(resolvers, id, options) {
12044
- for (const resolver of resolvers.filter(havePluginResolver)) {
12032
+ for (const resolver of resolvers) {
12033
+ if (!havePluginResolver(resolver)) {
12034
+ continue;
12035
+ }
12045
12036
  const plugin = resolver.resolvePlugin(id, options);
12046
12037
  if (isThenable(plugin)) {
12047
12038
  return resolvePluginAsync(resolvers, id, options);
@@ -12053,7 +12044,10 @@ function resolvePlugin(resolvers, id, options) {
12053
12044
  throw new UserError(`Failed to load plugin from "${id}"`);
12054
12045
  }
12055
12046
  async function resolvePluginAsync(resolvers, id, options) {
12056
- for (const resolver of resolvers.filter(havePluginResolver)) {
12047
+ for (const resolver of resolvers) {
12048
+ if (!havePluginResolver(resolver)) {
12049
+ continue;
12050
+ }
12057
12051
  const plugin = await resolver.resolvePlugin(id, options);
12058
12052
  if (plugin) {
12059
12053
  return plugin;
@@ -12062,7 +12056,10 @@ async function resolvePluginAsync(resolvers, id, options) {
12062
12056
  throw new UserError(`Failed to load plugin from "${id}"`);
12063
12057
  }
12064
12058
  function resolveTransformer(resolvers, id, options) {
12065
- for (const resolver of resolvers.filter(haveTransformerResolver)) {
12059
+ for (const resolver of resolvers) {
12060
+ if (!haveTransformerResolver(resolver)) {
12061
+ continue;
12062
+ }
12066
12063
  const transformer = resolver.resolveTransformer(id, options);
12067
12064
  if (isThenable(transformer)) {
12068
12065
  return resolveTransformerAsync(resolvers, id, options);
@@ -12074,7 +12071,10 @@ function resolveTransformer(resolvers, id, options) {
12074
12071
  throw new UserError(`Failed to load transformer from "${id}"`);
12075
12072
  }
12076
12073
  async function resolveTransformerAsync(resolvers, id, options) {
12077
- for (const resolver of resolvers.filter(haveTransformerResolver)) {
12074
+ for (const resolver of resolvers) {
12075
+ if (!haveTransformerResolver(resolver)) {
12076
+ continue;
12077
+ }
12078
12078
  const transformer = await resolver.resolveTransformer(id, options);
12079
12079
  if (transformer) {
12080
12080
  return transformer;
@@ -12114,9 +12114,12 @@ function staticResolver(map = {}) {
12114
12114
  };
12115
12115
  }
12116
12116
 
12117
- const ajv = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
12118
- ajv.addMetaSchema(ajvSchemaDraft);
12119
- ajv.addKeyword(ajvFunctionKeyword);
12117
+ const ajv = (() => {
12118
+ const ajv2 = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
12119
+ ajv2.addMetaSchema(ajvSchemaDraft);
12120
+ ajv2.addKeyword(ajvFunctionKeyword);
12121
+ return ajv2;
12122
+ })();
12120
12123
  const validator = ajv.compile(configurationSchema);
12121
12124
  function overwriteMerge(_a, b) {
12122
12125
  return b;
@@ -12135,18 +12138,16 @@ function mergeInternal(base, rhs) {
12135
12138
  function toArray$1(value) {
12136
12139
  if (Array.isArray(value)) {
12137
12140
  return value;
12138
- } else {
12139
- return [value];
12140
12141
  }
12142
+ return [value];
12141
12143
  }
12142
12144
  function transformerEntries(transform) {
12143
12145
  return Object.entries(transform).map(([pattern, value]) => {
12144
12146
  const regex = new RegExp(pattern);
12145
12147
  if (typeof value === "string") {
12146
12148
  return { kind: "import", pattern: regex, name: value };
12147
- } else {
12148
- return { kind: "function", pattern: regex, function: value };
12149
12149
  }
12150
+ return { kind: "function", pattern: regex, function: value };
12150
12151
  });
12151
12152
  }
12152
12153
  class Config {
@@ -12171,8 +12172,8 @@ class Config {
12171
12172
  * Create configuration from object.
12172
12173
  */
12173
12174
  static fromObject(resolvers, options, filename = null) {
12174
- Config.validate(options, filename);
12175
- return Config.create(resolvers, options);
12175
+ this.validate(options, filename);
12176
+ return this.create(resolvers, options);
12176
12177
  }
12177
12178
  /**
12178
12179
  * Read configuration from filename.
@@ -12186,10 +12187,9 @@ class Config {
12186
12187
  static fromFile(resolvers, filename) {
12187
12188
  const configData = resolveConfig(toArray$1(resolvers), filename, { cache: false });
12188
12189
  if (isThenable(configData)) {
12189
- return configData.then((configData2) => Config.fromObject(resolvers, configData2, filename));
12190
- } else {
12191
- return Config.fromObject(resolvers, configData, filename);
12190
+ return configData.then((configData2) => this.fromObject(resolvers, configData2, filename));
12192
12191
  }
12192
+ return this.fromObject(resolvers, configData, filename);
12193
12193
  }
12194
12194
  /**
12195
12195
  * Validate configuration data.
@@ -12211,8 +12211,8 @@ class Config {
12211
12211
  );
12212
12212
  }
12213
12213
  if (configData.rules) {
12214
- const normalizedRules = Config.getRulesObject(configData.rules);
12215
- for (const [ruleId, [, ruleOptions]] of normalizedRules.entries()) {
12214
+ const normalizedRules = this.getRulesObject(configData.rules);
12215
+ for (const [ruleId, [, ruleOptions]] of normalizedRules) {
12216
12216
  const cls = bundledRules[ruleId];
12217
12217
  const path = `/rules/${ruleId}/1`;
12218
12218
  Rule.validateOptions(cls, ruleId, path, ruleOptions, filename, configData);
@@ -12235,9 +12235,8 @@ class Config {
12235
12235
  return plugins.then((plugins2) => {
12236
12236
  return instance.init(options, plugins2);
12237
12237
  });
12238
- } else {
12239
- return instance.init(options, plugins);
12240
12238
  }
12239
+ return instance.init(options, plugins);
12241
12240
  }
12242
12241
  init(options, plugins) {
12243
12242
  this.plugins = plugins;
@@ -12254,9 +12253,8 @@ class Config {
12254
12253
  const extendedConfig = this.extendConfig(this.config.extends ?? []);
12255
12254
  if (isThenable(extendedConfig)) {
12256
12255
  return extendedConfig.then((extended) => update(extended));
12257
- } else {
12258
- return update(extendedConfig);
12259
12256
  }
12257
+ return update(extendedConfig);
12260
12258
  }
12261
12259
  /**
12262
12260
  * @internal
@@ -12298,12 +12296,11 @@ class Config {
12298
12296
  instance.extendMeta(instance.plugins);
12299
12297
  return instance;
12300
12298
  });
12301
- } else {
12302
- instance.plugins = plugins;
12303
- instance.configurations = instance.loadConfigurations(instance.plugins);
12304
- instance.extendMeta(instance.plugins);
12305
- return instance;
12306
12299
  }
12300
+ instance.plugins = plugins;
12301
+ instance.configurations = instance.loadConfigurations(instance.plugins);
12302
+ instance.extendMeta(instance.plugins);
12303
+ return instance;
12307
12304
  }
12308
12305
  extendConfig(entries) {
12309
12306
  if (entries.length === 0) {
@@ -12359,20 +12356,19 @@ class Config {
12359
12356
  const result = this.getElementsFromEntry(entry);
12360
12357
  if (isThenable(result)) {
12361
12358
  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);
12359
+ const [obj2, filename2] = result2;
12360
+ metaTable.loadFromObject(obj2, filename2);
12361
+ const next3 = source.shift();
12362
+ if (next3) {
12363
+ return loadEntry(next3);
12367
12364
  }
12368
12365
  });
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
- }
12366
+ }
12367
+ const [obj, filename] = result;
12368
+ metaTable.loadFromObject(obj, filename);
12369
+ const next2 = source.shift();
12370
+ if (next2) {
12371
+ return loadEntry(next2);
12376
12372
  }
12377
12373
  };
12378
12374
  const next = source.shift();
@@ -12402,9 +12398,8 @@ class Config {
12402
12398
  return obj.then((obj2) => {
12403
12399
  return [obj2, entry];
12404
12400
  });
12405
- } else {
12406
- return [obj, entry];
12407
12401
  }
12402
+ return [obj, entry];
12408
12403
  } catch (err) {
12409
12404
  const message = err instanceof Error ? err.message : String(err);
12410
12405
  throw new ConfigError(
@@ -12466,7 +12461,7 @@ class Config {
12466
12461
  const loadPlugin = (entry, index) => {
12467
12462
  if (typeof entry !== "string") {
12468
12463
  const plugin = entry;
12469
- plugin.name = plugin.name || `:unnamedPlugin@${String(index + 1)}`;
12464
+ plugin.name ||= `:unnamedPlugin@${String(index + 1)}`;
12470
12465
  plugin.originalName = `:unnamedPlugin@${String(index + 1)}`;
12471
12466
  loaded.push(plugin);
12472
12467
  const next2 = loading.shift();
@@ -12478,22 +12473,21 @@ class Config {
12478
12473
  const plugin = resolvePlugin(this.resolvers, entry, { cache: true });
12479
12474
  if (isThenable(plugin)) {
12480
12475
  return plugin.then((plugin2) => {
12481
- plugin2.name = plugin2.name || entry;
12476
+ plugin2.name ||= entry;
12482
12477
  plugin2.originalName = entry;
12483
12478
  loaded.push(plugin2);
12484
- const next2 = loading.shift();
12485
- if (next2) {
12486
- return loadPlugin(next2, index + 1);
12479
+ const next3 = loading.shift();
12480
+ if (next3) {
12481
+ return loadPlugin(next3, index + 1);
12487
12482
  }
12488
12483
  });
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
- }
12484
+ }
12485
+ plugin.name ||= entry;
12486
+ plugin.originalName = entry;
12487
+ loaded.push(plugin);
12488
+ const next2 = loading.shift();
12489
+ if (next2) {
12490
+ return loadPlugin(next2, index + 1);
12497
12491
  }
12498
12492
  } catch (err) {
12499
12493
  const message = err instanceof Error ? err.message : String(err);
@@ -12519,7 +12513,8 @@ class Config {
12519
12513
  configs.set(name, config);
12520
12514
  }
12521
12515
  for (const plugin of plugins) {
12522
- for (const [name, config] of Object.entries(plugin.configs ?? {})) {
12516
+ const entries = Object.entries(plugin.configs ?? {});
12517
+ for (const [name, config] of entries) {
12523
12518
  if (!config) {
12524
12519
  continue;
12525
12520
  }
@@ -12563,9 +12558,8 @@ class Config {
12563
12558
  return resolveData.then((resolveData2) => {
12564
12559
  return new ResolvedConfig(resolveData2, this.get());
12565
12560
  });
12566
- } else {
12567
- return new ResolvedConfig(resolveData, this.get());
12568
12561
  }
12562
+ return new ResolvedConfig(resolveData, this.get());
12569
12563
  }
12570
12564
  /**
12571
12565
  * Same as [[resolve]] but returns the raw configuration data instead of
@@ -12584,14 +12578,13 @@ class Config {
12584
12578
  transformers: this.transformers
12585
12579
  };
12586
12580
  });
12587
- } else {
12588
- return {
12589
- metaTable,
12590
- plugins: this.getPlugins(),
12591
- rules: this.getRules(),
12592
- transformers: this.transformers
12593
- };
12594
12581
  }
12582
+ return {
12583
+ metaTable,
12584
+ plugins: this.getPlugins(),
12585
+ rules: this.getRules(),
12586
+ transformers: this.transformers
12587
+ };
12595
12588
  }
12596
12589
  }
12597
12590
 
@@ -12635,10 +12628,9 @@ class ConfigLoader {
12635
12628
  this._globalConfig = config2;
12636
12629
  return this._globalConfig;
12637
12630
  });
12638
- } else {
12639
- this._globalConfig = config;
12640
- return this._globalConfig;
12641
12631
  }
12632
+ this._globalConfig = config;
12633
+ return this._globalConfig;
12642
12634
  }
12643
12635
  /**
12644
12636
  * Get the global configuration.
@@ -12720,9 +12712,8 @@ class StaticConfigLoader extends ConfigLoader {
12720
12712
  const override = this.loadFromObject(configOverride ?? {});
12721
12713
  if (isThenable(override)) {
12722
12714
  return override.then((override2) => this._resolveConfig(override2));
12723
- } else {
12724
- return this._resolveConfig(override);
12725
12715
  }
12716
+ return this._resolveConfig(override);
12726
12717
  }
12727
12718
  flushCache() {
12728
12719
  }
@@ -12739,25 +12730,22 @@ class StaticConfigLoader extends ConfigLoader {
12739
12730
  const globalConfig = this.getGlobalConfig();
12740
12731
  if (isThenable(globalConfig)) {
12741
12732
  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();
12733
+ const merged2 = globalConfig2.merge(this.resolvers, override);
12734
+ if (isThenable(merged2)) {
12735
+ return merged2.then((merged3) => {
12736
+ return merged3.resolve();
12746
12737
  });
12747
- } else {
12748
- return merged.resolve();
12749
12738
  }
12739
+ return merged2.resolve();
12740
+ });
12741
+ }
12742
+ const merged = globalConfig.merge(this.resolvers, override);
12743
+ if (isThenable(merged)) {
12744
+ return merged.then((merged2) => {
12745
+ return merged2.resolve();
12750
12746
  });
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
12747
  }
12748
+ return merged.resolve();
12761
12749
  }
12762
12750
  }
12763
12751
 
@@ -12844,7 +12832,7 @@ class EventHandler {
12844
12832
  }
12845
12833
 
12846
12834
  const name = "html-validate";
12847
- const version = "11.5.3";
12835
+ const version = "11.5.4";
12848
12836
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
12849
12837
 
12850
12838
  function freeze(src) {
@@ -12882,7 +12870,7 @@ class Reporter {
12882
12870
  for (const report of reports) {
12883
12871
  for (const result of report.results) {
12884
12872
  const key = result.filePath;
12885
- if (key in merged) {
12873
+ if (Object.hasOwn(merged, key)) {
12886
12874
  merged[key].messages = [...merged[key].messages, ...result.messages];
12887
12875
  } else {
12888
12876
  merged[key] = { ...result };
@@ -12906,7 +12894,7 @@ class Reporter {
12906
12894
  */
12907
12895
  add(options) {
12908
12896
  const { rule, message, severity, node, location, context } = options;
12909
- if (!(location.filename in this.result)) {
12897
+ if (!Object.hasOwn(this.result, location.filename)) {
12910
12898
  this.result[location.filename] = [];
12911
12899
  }
12912
12900
  const ruleUrl = rule.documentation(context)?.url;
@@ -12934,7 +12922,7 @@ class Reporter {
12934
12922
  * @internal
12935
12923
  */
12936
12924
  addManual(filename, message) {
12937
- if (!(filename in this.result)) {
12925
+ if (!Object.hasOwn(this.result, filename)) {
12938
12926
  this.result[filename] = [];
12939
12927
  }
12940
12928
  this.result[filename].push(message);
@@ -12945,6 +12933,7 @@ class Reporter {
12945
12933
  save(sources) {
12946
12934
  const report = {
12947
12935
  valid: this.isValid(),
12936
+ /* eslint-disable-next-line unicorn/prefer-object-iterable-methods -- technical debt */
12948
12937
  results: Object.keys(this.result).map((filePath) => {
12949
12938
  const messages = Array.from(this.result[filePath], freeze).toSorted(messageSort);
12950
12939
  const source = (sources ?? []).find((source2) => filePath === source2.filename);
@@ -13009,7 +12998,7 @@ function definePlugin(plugin) {
13009
12998
  return plugin;
13010
12999
  }
13011
13000
 
13012
- const regexp = /<!(?:--)?\[(.*?)](?:--)?>/g;
13001
+ const regexp = /<!(?:--)?\[(.*?)\](?:--)?>/g;
13013
13002
  function* parseConditionalComment(comment, commentLocation) {
13014
13003
  let match;
13015
13004
  while ((match = regexp.exec(comment)) !== null) {
@@ -13026,6 +13015,7 @@ function* parseConditionalComment(comment, commentLocation) {
13026
13015
 
13027
13016
  class ParserError extends Error {
13028
13017
  location;
13018
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
13029
13019
  constructor(location, message) {
13030
13020
  super(message);
13031
13021
  this.name = "ParserError";
@@ -13189,9 +13179,8 @@ class Parser {
13189
13179
  const open = !token.data[1];
13190
13180
  if (open) {
13191
13181
  return this.wouldCloseElement(token, active);
13192
- } else {
13193
- return this.closeOptionalEndTag(token, active);
13194
13182
  }
13183
+ return this.closeOptionalEndTag(token, active);
13195
13184
  }
13196
13185
  /**
13197
13186
  * Returns `true` if the element’s end tag may be omitted, either because
@@ -13543,9 +13532,8 @@ class Parser {
13543
13532
  const quote = token.data[3];
13544
13533
  if (quote) {
13545
13534
  return sliceLocation(token.location, 2, -1);
13546
- } else {
13547
- return sliceLocation(token.location, 1);
13548
13535
  }
13536
+ return sliceLocation(token.location, 1);
13549
13537
  }
13550
13538
  /**
13551
13539
  * Take attribute key and value token an returns a new location referring to
@@ -13833,13 +13821,14 @@ class PerformanceTracker {
13833
13821
  */
13834
13822
  getResult() {
13835
13823
  const events = Array.from(
13836
- this.eventData.entries(),
13824
+ this.eventData,
13837
13825
  ([event, { count, time }]) => ({ event, count, time })
13838
13826
  ).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);
13827
+ const rules = Array.from(this.ruleData, ([rule, { count, time }]) => ({
13828
+ rule,
13829
+ count,
13830
+ time
13831
+ })).toSorted((a, b) => b.time - a.time);
13843
13832
  return {
13844
13833
  events,
13845
13834
  rules,
@@ -13886,9 +13875,11 @@ function dumpTree(root) {
13886
13875
  return lines;
13887
13876
  }
13888
13877
 
13889
- let blockerCounter = 1;
13878
+ const state = {
13879
+ blockerCounter: 1
13880
+ };
13890
13881
  function createBlocker() {
13891
- const id = blockerCounter++;
13882
+ const id = state.blockerCounter++;
13892
13883
  return id;
13893
13884
  }
13894
13885
 
@@ -14024,9 +14015,8 @@ class Engine {
14024
14015
  const [, options] = ruleData;
14025
14016
  const rule = this.instantiateRule(ruleId, options);
14026
14017
  return rule.documentation(context);
14027
- } else {
14028
- return null;
14029
14018
  }
14019
+ return null;
14030
14020
  }
14031
14021
  /**
14032
14022
  * Create a new parser instance with the current configuration.
@@ -14155,7 +14145,8 @@ class Engine {
14155
14145
  initRules(config) {
14156
14146
  const availableRules = {};
14157
14147
  for (const plugin of config.getPlugins()) {
14158
- for (const [name, rule] of Object.entries(plugin.rules ?? {})) {
14148
+ const entries = Object.entries(plugin.rules ?? {});
14149
+ for (const [name, rule] of entries) {
14159
14150
  if (!rule) {
14160
14151
  continue;
14161
14152
  }
@@ -14183,7 +14174,7 @@ class Engine {
14183
14174
  */
14184
14175
  setupRules(config, parser) {
14185
14176
  const rules = {};
14186
- for (const [ruleId, [severity, options]] of config.getRules().entries()) {
14177
+ for (const [ruleId, [severity, options]] of config.getRules()) {
14187
14178
  rules[ruleId] = this.loadRule(ruleId, config, severity, options, parser, this.report);
14188
14179
  }
14189
14180
  return rules;
@@ -14207,9 +14198,8 @@ class Engine {
14207
14198
  if (this.availableRules[name]) {
14208
14199
  const RuleConstructor = this.availableRules[name];
14209
14200
  return new RuleConstructor(options);
14210
- } else {
14211
- return this.missingRule(name);
14212
14201
  }
14202
+ return this.missingRule(name);
14213
14203
  }
14214
14204
  missingRule(name) {
14215
14205
  return new class MissingRule extends Rule {
@@ -14305,34 +14295,30 @@ function getTransformerFunction(resolvers, name, plugins) {
14305
14295
  validateTransformer(transformer2);
14306
14296
  return transformer2;
14307
14297
  });
14308
- } else {
14309
- validateTransformer(transformer);
14310
- return transformer;
14311
14298
  }
14299
+ validateTransformer(transformer);
14300
+ return transformer;
14312
14301
  } catch (err) {
14313
14302
  if (err instanceof ConfigError) {
14314
14303
  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
14304
  }
14305
+ throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
14318
14306
  }
14319
14307
  }
14320
14308
  function getCachedTransformerFunction(cache, resolvers, name, plugins) {
14321
14309
  const cached = cache.get(name);
14322
14310
  if (cached) {
14323
14311
  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
14312
  }
14313
+ const transformer = getTransformerFunction(resolvers, name, plugins);
14314
+ if (isThenable(transformer)) {
14315
+ return transformer.then((transformer2) => {
14316
+ cache.set(name, transformer2);
14317
+ return transformer2;
14318
+ });
14319
+ }
14320
+ cache.set(name, transformer);
14321
+ return transformer;
14336
14322
  }
14337
14323
 
14338
14324
  function isIterable(value) {
@@ -14348,6 +14334,9 @@ const asyncInSyncTransformError = "Cannot use async transformer from sync functi
14348
14334
  async function transformSource(resolvers, config, source, filename) {
14349
14335
  const { cache } = config;
14350
14336
  const transformer = config.findTransformer(filename ?? source.filename);
14337
+ if (!transformer) {
14338
+ return [source];
14339
+ }
14351
14340
  const context = {
14352
14341
  hasChain(filename2) {
14353
14342
  return config.canTransform(filename2);
@@ -14356,9 +14345,6 @@ async function transformSource(resolvers, config, source, filename) {
14356
14345
  return transformSource(resolvers, config, source2, filename2);
14357
14346
  }
14358
14347
  };
14359
- if (!transformer) {
14360
- return [source];
14361
- }
14362
14348
  const fn = transformer.kind === "import" ? await getCachedTransformerFunction(cache, resolvers, transformer.name, config.getPlugins()) : transformer.function;
14363
14349
  const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14364
14350
  try {
@@ -14377,6 +14363,9 @@ async function transformSource(resolvers, config, source, filename) {
14377
14363
  function transformSourceSync(resolvers, config, source, filename) {
14378
14364
  const { cache } = config;
14379
14365
  const transformer = config.findTransformer(filename ?? source.filename);
14366
+ if (!transformer) {
14367
+ return [source];
14368
+ }
14380
14369
  const context = {
14381
14370
  hasChain(filename2) {
14382
14371
  return config.canTransform(filename2);
@@ -14385,14 +14374,11 @@ function transformSourceSync(resolvers, config, source, filename) {
14385
14374
  return transformSourceSync(resolvers, config, source2, filename2);
14386
14375
  }
14387
14376
  };
14388
- if (!transformer) {
14389
- return [source];
14390
- }
14391
14377
  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
14378
  if (isThenable(fn)) {
14394
14379
  throw new UserError(asyncInSyncTransformError);
14395
14380
  }
14381
+ const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14396
14382
  try {
14397
14383
  const result = fn.call(context, source);
14398
14384
  if (isThenable(result)) {
@@ -14494,7 +14480,7 @@ function checkstyleFormatter(results) {
14494
14480
  `;
14495
14481
  for (const message of messages) {
14496
14482
  const ruleId = xmlescape(`htmlvalidate.rules.${message.ruleId}`);
14497
- output += " ";
14483
+ output += " ".repeat(4);
14498
14484
  output += [
14499
14485
  `<error line="${xmlescape(message.line)}"`,
14500
14486
  `column="${xmlescape(message.column)}"`,
@@ -14581,9 +14567,8 @@ function codeFrameColumns(rawLines, loc) {
14581
14567
  ].join("");
14582
14568
  }
14583
14569
  return [">", gutter, line.length > 0 ? ` ${line}` : "", markerLine].join("");
14584
- } else {
14585
- return [" ", gutter, line.length > 0 ? ` ${line}` : ""].join("");
14586
14570
  }
14571
+ return [" ", gutter, line.length > 0 ? ` ${line}` : ""].join("");
14587
14572
  }).join("\n");
14588
14573
  }
14589
14574