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/cjs/core.js CHANGED
@@ -397,11 +397,11 @@ var deepmerge = /*@__PURE__*/getDefaultExportFromCjs(cjsExports);
397
397
  function stringify(value) {
398
398
  if (typeof value === "string") {
399
399
  return value;
400
- } else {
401
- return JSON.stringify(value);
402
400
  }
401
+ return JSON.stringify(value);
403
402
  }
404
403
  class WrappedError extends Error {
404
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
405
405
  constructor(message) {
406
406
  super(stringify(message));
407
407
  this.name = "WrappedError";
@@ -411,12 +411,12 @@ class WrappedError extends Error {
411
411
  function ensureError(value) {
412
412
  if (value instanceof Error) {
413
413
  return value;
414
- } else {
415
- return new WrappedError(value);
416
414
  }
415
+ return new WrappedError(value);
417
416
  }
418
417
 
419
418
  class NestedError extends Error {
419
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
420
420
  constructor(message, nested) {
421
421
  super(message);
422
422
  this.name = "NestedError";
@@ -429,6 +429,7 @@ Caused by: ${nested.stack}`;
429
429
  }
430
430
 
431
431
  class UserError extends NestedError {
432
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
432
433
  constructor(message, nested) {
433
434
  super(message, nested);
434
435
  this.name = "UserError";
@@ -1129,11 +1130,11 @@ const CONTROL_ESCAPES = /* @__PURE__ */ new Map([
1129
1130
  ["\r", "r"]
1130
1131
  ]);
1131
1132
  const OTHER_PUNCTUATORS = /^[!"#%&',:;<=>@`~-]$/;
1132
- const WHITE_SPACE = /^[\t\v\f\uFEFF\p{Zs}]$/u;
1133
+ const WHITE_SPACE = /^[\t\v\f\u{FEFF}\p{Zs}]$/u;
1133
1134
  const LINE_TERMINATOR = /^[\n\r\u2028\u2029]$/;
1134
1135
  const SURROGATE = /^[\uD800-\uDFFF]$/;
1135
1136
  function isDecimalDigitOrASCIILetter(ch) {
1136
- return /^[\dA-Za-z]$/.test(ch);
1137
+ return /^[\dA-Z]$/i.test(ch);
1137
1138
  }
1138
1139
  function needEscape(ch) {
1139
1140
  return OTHER_PUNCTUATORS.test(ch) || WHITE_SPACE.test(ch) || LINE_TERMINATOR.test(ch) || SURROGATE.test(ch);
@@ -1201,9 +1202,8 @@ function migrateSingleAttribute(src, key) {
1201
1202
  }
1202
1203
  }
1203
1204
  return stripUndefined(result);
1204
- } else {
1205
- return stripUndefined({ ...result, ...attr });
1206
1205
  }
1206
+ return stripUndefined({ ...result, ...attr });
1207
1207
  }
1208
1208
  function isPatternAttribute$1(key) {
1209
1209
  return key.includes("*");
@@ -1217,7 +1217,7 @@ function migrateAttributes(src) {
1217
1217
  ...Object.keys(src.attributes ?? {}),
1218
1218
  ...src.requiredAttributes ?? [],
1219
1219
  ...src.deprecatedAttributes ?? []
1220
- ].filter((key) => !isPatternAttribute$1(key)).toSorted();
1220
+ ].filter((key) => !isPatternAttribute$1(key)).toSorted((a, b) => a.localeCompare(b));
1221
1221
  const entries = keys.map((key) => {
1222
1222
  return [key, migrateSingleAttribute(src, key)];
1223
1223
  });
@@ -1297,11 +1297,10 @@ const dynamicKeys = [
1297
1297
  ];
1298
1298
  const schemaCache = /* @__PURE__ */ new Map();
1299
1299
  function clone(value) {
1300
- if (globalThis.structuredClone) {
1301
- return globalThis.structuredClone(value);
1302
- } else {
1303
- return JSON.parse(JSON.stringify(value));
1300
+ if (Object.hasOwn(globalThis, "structuredClone")) {
1301
+ return structuredClone(value);
1304
1302
  }
1303
+ return JSON.parse(JSON.stringify(value));
1305
1304
  }
1306
1305
  class MetaTable {
1307
1306
  elements;
@@ -1391,9 +1390,8 @@ class MetaTable {
1391
1390
  const meta = this.elements[tagName.toLowerCase()] ?? this.elements["*"];
1392
1391
  if (meta) {
1393
1392
  return { ...meta };
1394
- } else {
1395
- return null;
1396
1393
  }
1394
+ return null;
1397
1395
  }
1398
1396
  /**
1399
1397
  * Find all tags which has enabled given property.
@@ -1435,16 +1433,15 @@ class MetaTable {
1435
1433
  const cached = schemaCache.get(hash);
1436
1434
  if (cached) {
1437
1435
  return cached;
1438
- } else {
1439
- const ajv = new Ajv__default.default({ strict: true, strictTuples: true, strictTypes: true });
1440
- ajv.addMetaSchema(ajvSchemaDraft);
1441
- ajv.addKeyword(ajvFunctionKeyword);
1442
- ajv.addKeyword(ajvRegexpKeyword);
1443
- ajv.addKeyword({ keyword: "copyable" });
1444
- const validate = ajv.compile(this.schema);
1445
- schemaCache.set(hash, validate);
1446
- return validate;
1447
1436
  }
1437
+ const ajv = new Ajv__default.default({ strict: true, strictTuples: true, strictTypes: true });
1438
+ ajv.addMetaSchema(ajvSchemaDraft);
1439
+ ajv.addKeyword(ajvFunctionKeyword);
1440
+ ajv.addKeyword(ajvRegexpKeyword);
1441
+ ajv.addKeyword({ keyword: "copyable" });
1442
+ const validate = ajv.compile(this.schema);
1443
+ schemaCache.set(hash, validate);
1444
+ return validate;
1448
1445
  }
1449
1446
  /**
1450
1447
  * @public
@@ -1526,14 +1523,13 @@ function expandProperties(node, entry) {
1526
1523
  }
1527
1524
  }
1528
1525
  function compileRegexString(value) {
1529
- const match = /^\/(.*(?=\/))\/(i?)$/.exec(value);
1526
+ const match = /^\/(.*)\/(i?)$/.exec(value);
1530
1527
  if (match) {
1531
1528
  const [, expr, flags] = match;
1532
1529
  if (expr.startsWith("^") || expr.endsWith("$")) {
1533
1530
  return new RegExp(expr, flags);
1534
- } else {
1535
- return new RegExp(`^${expr}$`, flags);
1536
1531
  }
1532
+ return new RegExp(`^${expr}$`, flags);
1537
1533
  }
1538
1534
  return null;
1539
1535
  }
@@ -1594,7 +1590,7 @@ class Attribute {
1594
1590
  * @param keyLocation - Source location of attribute name.
1595
1591
  * @param valueLocation - Source location of attribute value.
1596
1592
  * @param originalAttribute - If this attribute was dynamically added via a
1597
- * transformation (e.g. vuejs `:id` generating the `id` attribute) this
1593
+ * transformation (e.g. Vue.js `:id` generating the `id` attribute) this
1598
1594
  * parameter should be set to the attribute name of the source attribute (`:id`).
1599
1595
  */
1600
1596
  constructor(key, value, keyLocation, valueLocation, originalAttribute) {
@@ -1638,9 +1634,8 @@ class Attribute {
1638
1634
  }
1639
1635
  if (pattern instanceof RegExp) {
1640
1636
  return this.value.match(pattern) !== null;
1641
- } else {
1642
- return this.value === pattern;
1643
1637
  }
1638
+ return this.value === pattern;
1644
1639
  }
1645
1640
  }
1646
1641
 
@@ -1716,7 +1711,9 @@ const Node = {
1716
1711
 
1717
1712
  const DOCUMENT_NODE_NAME = "#document";
1718
1713
  const TEXT_CONTENT = /* @__PURE__ */ Symbol("textContent");
1719
- let counter = 0;
1714
+ const state$1 = {
1715
+ counter: 0
1716
+ };
1720
1717
  class DOMNode {
1721
1718
  nodeName;
1722
1719
  nodeType;
@@ -1755,7 +1752,7 @@ class DOMNode {
1755
1752
  this.disabledRules = /* @__PURE__ */ new Set();
1756
1753
  this.blockedRules = /* @__PURE__ */ new Map();
1757
1754
  this.childNodes = [];
1758
- this.unique = counter++;
1755
+ this.unique = state$1.counter++;
1759
1756
  this.cache = null;
1760
1757
  }
1761
1758
  /**
@@ -1771,9 +1768,8 @@ class DOMNode {
1771
1768
  cacheGet(key) {
1772
1769
  if (this.cache) {
1773
1770
  return this.cache.get(key);
1774
- } else {
1775
- return void 0;
1776
1771
  }
1772
+ return void 0;
1777
1773
  }
1778
1774
  cacheSet(key, value) {
1779
1775
  if (this.cache) {
@@ -1789,9 +1785,8 @@ class DOMNode {
1789
1785
  cacheRemove(key) {
1790
1786
  if (this.cache) {
1791
1787
  return this.cache.delete(key);
1792
- } else {
1793
- return false;
1794
1788
  }
1789
+ return false;
1795
1790
  }
1796
1791
  /**
1797
1792
  * Check if key exists in cache.
@@ -2011,9 +2006,8 @@ class DOMTokenList extends Array {
2011
2006
  location(n) {
2012
2007
  if (this.locations) {
2013
2008
  return this.locations[n];
2014
- } else {
2015
- throw new Error("Trying to access DOMTokenList location when base location isn't set");
2016
2009
  }
2010
+ throw new Error("Trying to access DOMTokenList location when base location isn't set");
2017
2011
  }
2018
2012
  contains(token) {
2019
2013
  return this.includes(token);
@@ -2081,7 +2075,7 @@ function nthChild(node, args) {
2081
2075
  if (!args) {
2082
2076
  throw new Error("Missing argument to nth-child");
2083
2077
  }
2084
- const n = Number.parseInt(args.trim(), 10);
2078
+ const n = Math.trunc(Number(args.trim()));
2085
2079
  const cur = getNthChild(node);
2086
2080
  return cur === n;
2087
2081
  }
@@ -2100,9 +2094,8 @@ function factory(name, context) {
2100
2094
  const fn = table[name];
2101
2095
  if (fn) {
2102
2096
  return fn.bind(context);
2103
- } else {
2104
- throw new Error(`Pseudo-class "${name}" is not implemented`);
2105
2097
  }
2098
+ throw new Error(`Pseudo-class "${name}" is not implemented`);
2106
2099
  }
2107
2100
 
2108
2101
  function stripslashes(value) {
@@ -2128,7 +2121,7 @@ function createIdCondition(raw) {
2128
2121
  };
2129
2122
  }
2130
2123
  function createAttributeCondition(attr) {
2131
- const match = /^(.+?)(?:([$*^|~]?=)"([^"]+?)")?$/.exec(attr);
2124
+ const match = /^(.+?)(?:([$*^|~]?=)"([^"]+)")?$/.exec(attr);
2132
2125
  const key = match[1];
2133
2126
  const op = match[2];
2134
2127
  const rawValue = match[3];
@@ -2191,7 +2184,6 @@ function* splitCompound(pattern) {
2191
2184
  let quoted = false;
2192
2185
  while (cur < end) {
2193
2186
  const ch = pattern[cur];
2194
- const buffer = pattern.slice(begin, cur);
2195
2187
  if (ch === "\\") {
2196
2188
  cur += 2;
2197
2189
  continue;
@@ -2208,6 +2200,7 @@ function* splitCompound(pattern) {
2208
2200
  cur += 1;
2209
2201
  continue;
2210
2202
  }
2203
+ const buffer = pattern.slice(begin, cur);
2211
2204
  if (isPseudoElement(ch, buffer)) {
2212
2205
  cur += 1;
2213
2206
  continue;
@@ -2228,7 +2221,7 @@ class Compound {
2228
2221
  selector;
2229
2222
  conditions;
2230
2223
  constructor(pattern) {
2231
- const match = /^([+>~-]?)((?:\*|[^#.:[]+)?)([^]*)$/.exec(pattern);
2224
+ const match = /^([+>~-]?)((?:\*|[^#.:[]+)?)([\s\S]*)$/.exec(pattern);
2232
2225
  if (!match) {
2233
2226
  throw new Error(`Failed to create selector pattern from "${pattern}"`);
2234
2227
  }
@@ -2242,7 +2235,7 @@ class Compound {
2242
2235
  return node.is(this.tagName) && this.conditions.every((cur) => cur.match(node, context));
2243
2236
  }
2244
2237
  createCondition(pattern) {
2245
- switch (pattern[0]) {
2238
+ switch (pattern.at(0)) {
2246
2239
  case ".":
2247
2240
  return createClassCondition(pattern.slice(1));
2248
2241
  case "#":
@@ -2435,9 +2428,9 @@ class ComplexSelector {
2435
2428
  case Combinator.CHILD:
2436
2429
  return root.childElements.filter((node) => node.is(pattern.tagName));
2437
2430
  case Combinator.ADJACENT_SIBLING:
2438
- return ComplexSelector.findAdjacentSibling(root);
2431
+ return this.findAdjacentSibling(root);
2439
2432
  case Combinator.GENERAL_SIBLING:
2440
- return ComplexSelector.findGeneralSibling(root);
2433
+ return this.findGeneralSibling(root);
2441
2434
  case Combinator.SCOPE:
2442
2435
  return [root];
2443
2436
  }
@@ -2475,12 +2468,11 @@ const codepoints = {
2475
2468
  "\r": "\\d "
2476
2469
  };
2477
2470
  function escapeSelectorComponent(text) {
2478
- return text.toString().replaceAll(/([\t\n\r]|[^\w-])/gi, (_, ch) => {
2479
- if (codepoints[ch]) {
2471
+ return text.toString().replaceAll(/([^\w-])/g, (_, ch) => {
2472
+ if (Object.hasOwn(codepoints, ch)) {
2480
2473
  return codepoints[ch];
2481
- } else {
2482
- return `\\${ch}`;
2483
2474
  }
2475
+ return `\\${ch}`;
2484
2476
  });
2485
2477
  }
2486
2478
 
@@ -2643,10 +2635,10 @@ class HtmlElement extends DOMNode {
2643
2635
  */
2644
2636
  static fromTokens(startToken, endToken, parent, metaTable, namespace = "") {
2645
2637
  const name = startToken.data[2];
2646
- const tagName = namespace ? `${namespace}:${name}` : name;
2647
2638
  if (!name) {
2648
2639
  throw new Error("tagName cannot be empty");
2649
2640
  }
2641
+ const tagName = namespace ? `${namespace}:${name}` : name;
2650
2642
  const meta = metaTable ? metaTable.getMetaFor(tagName) : null;
2651
2643
  const open = startToken.data[1] !== "/";
2652
2644
  const closed = isClosed(endToken, meta);
@@ -2668,9 +2660,8 @@ class HtmlElement extends DOMNode {
2668
2660
  get annotatedName() {
2669
2661
  if (this.annotation) {
2670
2662
  return this.annotation;
2671
- } else {
2672
- return `<${this.tagName}>`;
2673
2663
  }
2664
+ return `<${this.tagName}>`;
2674
2665
  }
2675
2666
  /**
2676
2667
  * Get list of IDs referenced by `aria-labelledby`.
@@ -2889,13 +2880,13 @@ class HtmlElement extends DOMNode {
2889
2880
  if (!tabindex) {
2890
2881
  return this.cacheSet(TABINDEX, null);
2891
2882
  }
2892
- if (tabindex.value === null) {
2883
+ if (tabindex.value === null || tabindex.value === "") {
2893
2884
  return this.cacheSet(TABINDEX, null);
2894
2885
  }
2895
2886
  if (tabindex.value instanceof DynamicValue) {
2896
2887
  return this.cacheSet(TABINDEX, 0);
2897
2888
  }
2898
- const parsed = Number.parseInt(tabindex.value, 10);
2889
+ const parsed = Math.trunc(Number(tabindex.value));
2899
2890
  if (Number.isNaN(parsed)) {
2900
2891
  return this.cacheSet(TABINDEX, null);
2901
2892
  }
@@ -2911,11 +2902,11 @@ class HtmlElement extends DOMNode {
2911
2902
  const tagName = this.tagName.toLowerCase();
2912
2903
  if (tagName === "script") {
2913
2904
  return "script";
2914
- } else if (tagName === "style") {
2905
+ }
2906
+ if (tagName === "style") {
2915
2907
  return "css";
2916
- } else {
2917
- return "text";
2918
2908
  }
2909
+ return "text";
2919
2910
  }
2920
2911
  /**
2921
2912
  * Get a list of all attributes on this node.
@@ -2927,16 +2918,15 @@ class HtmlElement extends DOMNode {
2927
2918
  }
2928
2919
  hasAttribute(key) {
2929
2920
  key = key.toLowerCase();
2930
- return key in this.attr;
2921
+ return Object.hasOwn(this.attr, key);
2931
2922
  }
2932
2923
  getAttribute(key, all = false) {
2933
2924
  key = key.toLowerCase();
2934
- if (key in this.attr) {
2925
+ if (Object.hasOwn(this.attr, key)) {
2935
2926
  const matches = this.attr[key];
2936
2927
  return all ? matches : matches[0];
2937
- } else {
2938
- return all ? [] : null;
2939
2928
  }
2929
+ return all ? [] : null;
2940
2930
  }
2941
2931
  /**
2942
2932
  * Get attribute value.
@@ -2954,17 +2944,13 @@ class HtmlElement extends DOMNode {
2954
2944
  const attr = this.getAttribute(key);
2955
2945
  if (attr) {
2956
2946
  return attr.value !== null ? attr.value.toString() : null;
2957
- } else {
2958
- return null;
2959
2947
  }
2948
+ return null;
2960
2949
  }
2961
- /**
2962
- * Add text as a child node to this element.
2963
- *
2964
- * @param text - Text to add.
2965
- * @param location - Source code location of this text.
2966
- */
2967
2950
  appendText(text, location) {
2951
+ if (typeof text === "object" && "dynamic" in text) {
2952
+ text = new DynamicValue(text.dynamic);
2953
+ }
2968
2954
  this.childNodes.push(new TextNode(text, location));
2969
2955
  }
2970
2956
  /**
@@ -3034,14 +3020,13 @@ class HtmlElement extends DOMNode {
3034
3020
  const next = it.next();
3035
3021
  if (next.done) {
3036
3022
  return null;
3037
- } else {
3038
- return next.value;
3039
3023
  }
3024
+ return next.value;
3040
3025
  }
3041
3026
  querySelectorAll(selector) {
3042
3027
  const it = this.querySelectorImpl(selector);
3043
3028
  const unique = new Set(it);
3044
- return Array.from(unique.values());
3029
+ return Array.from(unique);
3045
3030
  }
3046
3031
  *querySelectorImpl(selectorList) {
3047
3032
  if (!selectorList) {
@@ -3062,9 +3047,8 @@ class HtmlElement extends DOMNode {
3062
3047
  function visit(node) {
3063
3048
  if (callback(node)) {
3064
3049
  return true;
3065
- } else {
3066
- return node.childElements.some(visit);
3067
3050
  }
3051
+ return node.childElements.some(visit);
3068
3052
  }
3069
3053
  }
3070
3054
  /**
@@ -3239,7 +3223,7 @@ class Validator {
3239
3223
  return true;
3240
3224
  }
3241
3225
  return rules.some((rule) => {
3242
- return Validator.validatePermittedRule(node, rule);
3226
+ return this.validatePermittedRule(node, rule);
3243
3227
  });
3244
3228
  }
3245
3229
  /**
@@ -3266,9 +3250,7 @@ class Validator {
3266
3250
  const [, category, quantifier] = /^(@?.*?)([*?]?)$/.exec(rule);
3267
3251
  const limit = category && quantifier && parseQuantifier(quantifier);
3268
3252
  if (limit) {
3269
- const siblings = children.filter(
3270
- (cur) => Validator.validatePermittedCategory(cur, rule, true)
3271
- );
3253
+ const siblings = children.filter((cur) => this.validatePermittedCategory(cur, rule, true));
3272
3254
  if (siblings.length > limit) {
3273
3255
  for (const child of siblings.slice(limit)) {
3274
3256
  cb(child, category);
@@ -3299,12 +3281,12 @@ class Validator {
3299
3281
  let prev = null;
3300
3282
  for (const node of children) {
3301
3283
  const old = i;
3302
- while (rules[i] && !Validator.validatePermittedCategory(node, rules[i], true)) {
3284
+ while (rules[i] && !this.validatePermittedCategory(node, rules[i], true)) {
3303
3285
  i++;
3304
3286
  }
3305
3287
  if (i >= rules.length) {
3306
- const orderSpecified = rules.find(
3307
- (cur) => Validator.validatePermittedCategory(node, cur, true)
3288
+ const orderSpecified = rules.some(
3289
+ (cur) => this.validatePermittedCategory(node, cur, true)
3308
3290
  );
3309
3291
  if (orderSpecified) {
3310
3292
  cb(node, prev);
@@ -3343,7 +3325,7 @@ class Validator {
3343
3325
  }
3344
3326
  return rules.filter((tagName) => {
3345
3327
  const haveMatchingChild = node.childElements.some(
3346
- (child) => Validator.validatePermittedCategory(child, tagName, false)
3328
+ (child) => this.validatePermittedCategory(child, tagName, false)
3347
3329
  );
3348
3330
  return !haveMatchingChild;
3349
3331
  });
@@ -3390,36 +3372,35 @@ class Validator {
3390
3372
  return rule.enum.some((entry) => {
3391
3373
  if (typeof entry === "string") {
3392
3374
  return caseInsensitiveValue === entry;
3393
- } else if (entry instanceof RegExp) {
3375
+ }
3376
+ if (entry instanceof RegExp) {
3394
3377
  return entry.test(value);
3395
- } else if (entry.pattern instanceof RegExp) {
3378
+ }
3379
+ if (entry.pattern instanceof RegExp) {
3396
3380
  return entry.pattern.test(value);
3397
- } else {
3398
- throw new TypeError("RegExp was not precompiled when it should have been");
3399
3381
  }
3382
+ throw new TypeError("RegExp was not precompiled when it should have been");
3400
3383
  });
3401
3384
  }
3402
3385
  static validatePermittedRule(node, rule, isExclude = false) {
3403
3386
  if (typeof rule === "string") {
3404
- return Validator.validatePermittedCategory(node, rule, !isExclude);
3405
- } else if (Array.isArray(rule)) {
3387
+ return this.validatePermittedCategory(node, rule, !isExclude);
3388
+ }
3389
+ if (Array.isArray(rule)) {
3406
3390
  return rule.every((inner) => {
3407
- return Validator.validatePermittedRule(node, inner, isExclude);
3391
+ return this.validatePermittedRule(node, inner, isExclude);
3408
3392
  });
3409
- } else {
3410
- validateKeys(rule);
3411
- if (rule.exclude) {
3412
- if (Array.isArray(rule.exclude)) {
3413
- return !rule.exclude.some((inner) => {
3414
- return Validator.validatePermittedRule(node, inner, true);
3415
- });
3416
- } else {
3417
- return !Validator.validatePermittedRule(node, rule.exclude, true);
3418
- }
3419
- } else {
3420
- return true;
3393
+ }
3394
+ validateKeys(rule);
3395
+ if (rule.exclude) {
3396
+ if (Array.isArray(rule.exclude)) {
3397
+ return rule.exclude.every((inner) => {
3398
+ return !this.validatePermittedRule(node, inner, true);
3399
+ });
3421
3400
  }
3401
+ return !this.validatePermittedRule(node, rule.exclude, true);
3422
3402
  }
3403
+ return true;
3423
3404
  }
3424
3405
  /**
3425
3406
  * Validate node against a content category.
@@ -3435,7 +3416,7 @@ class Validator {
3435
3416
  */
3436
3417
  /* eslint-disable-next-line complexity -- rule does not like switch */
3437
3418
  static validatePermittedCategory(node, category, defaultMatch) {
3438
- const [, rawCategory] = /^(@?.*?)([*?]?)$/.exec(category);
3419
+ const [, rawCategory] = /^(@?.*?)[*?]?$/.exec(category);
3439
3420
  if (!rawCategory.startsWith("@")) {
3440
3421
  return node.matches(rawCategory);
3441
3422
  }
@@ -3468,10 +3449,11 @@ class Validator {
3468
3449
  }
3469
3450
  function validateKeys(rule) {
3470
3451
  for (const key of Object.keys(rule)) {
3471
- if (!allowedKeys.has(key)) {
3472
- const str = JSON.stringify(rule);
3473
- throw new Error(`Permitted rule "${str}" contains unknown property "${key}"`);
3452
+ if (allowedKeys.has(key)) {
3453
+ continue;
3474
3454
  }
3455
+ const str = JSON.stringify(rule);
3456
+ throw new Error(`Permitted rule "${str}" contains unknown property "${key}"`);
3475
3457
  }
3476
3458
  }
3477
3459
  function parseQuantifier(quantifier) {
@@ -3538,9 +3520,8 @@ function ariaNaming(element) {
3538
3520
  if (role) {
3539
3521
  if (role instanceof DynamicValue) {
3540
3522
  return element.cacheSet(cacheKey, defaultValue);
3541
- } else {
3542
- return element.cacheSet(cacheKey, byRole(role));
3543
3523
  }
3524
+ return element.cacheSet(cacheKey, byRole(role));
3544
3525
  }
3545
3526
  const meta = element.meta;
3546
3527
  if (!meta) {
@@ -3725,9 +3706,8 @@ function isPresentation(node) {
3725
3706
  const role = node.getAttribute("role");
3726
3707
  if (role && (role.value === "presentation" || role.value === "none")) {
3727
3708
  return node.cacheSet(ROLE_PRESENTATION_CACHE, true);
3728
- } else {
3729
- return node.cacheSet(ROLE_PRESENTATION_CACHE, false);
3730
3709
  }
3710
+ return node.cacheSet(ROLE_PRESENTATION_CACHE, false);
3731
3711
  }
3732
3712
 
3733
3713
  const cachePrefix = classifyNodeText.name;
@@ -3745,13 +3725,14 @@ function getCachekey(options) {
3745
3725
  const { accessible = false, ignoreHiddenRoot = false } = options;
3746
3726
  if (accessible && ignoreHiddenRoot) {
3747
3727
  return IGNORE_HIDDEN_ROOT_A11Y_CACHE_KEY;
3748
- } else if (ignoreHiddenRoot) {
3728
+ }
3729
+ if (ignoreHiddenRoot) {
3749
3730
  return IGNORE_HIDDEN_ROOT_HTML_CACHE_KEY;
3750
- } else if (accessible) {
3731
+ }
3732
+ if (accessible) {
3751
3733
  return A11Y_CACHE_KEY;
3752
- } else {
3753
- return HTML_CACHE_KEY;
3754
3734
  }
3735
+ return HTML_CACHE_KEY;
3755
3736
  }
3756
3737
  function isSpecialEmpty(node) {
3757
3738
  return node.is("select") || node.is("textarea");
@@ -3783,7 +3764,7 @@ function classifyNodeText(node, options = {}) {
3783
3764
  }
3784
3765
  function findTextNodes(node, options) {
3785
3766
  const { accessible = false } = options;
3786
- let text = [];
3767
+ const text = [];
3787
3768
  for (const child of node.childNodes) {
3788
3769
  if (isTextNode(child)) {
3789
3770
  text.push(child);
@@ -3794,7 +3775,7 @@ function findTextNodes(node, options) {
3794
3775
  if (accessible && isAriaHidden(child, true).bySelf) {
3795
3776
  continue;
3796
3777
  }
3797
- text = text.concat(findTextNodes(child, options));
3778
+ text.push(...findTextNodes(child, options));
3798
3779
  }
3799
3780
  }
3800
3781
  return text;
@@ -3855,14 +3836,17 @@ function format(value, quote = false) {
3855
3836
  return String(value);
3856
3837
  }
3857
3838
  function interpolate(text, data) {
3858
- return text.replaceAll(/{{\s*([^\s{}]+)\s*}}/g, (match, key) => {
3839
+ return text.replaceAll(/\{\{\s*([^\s{}]+)\s*\}\}/g, (match, key) => {
3859
3840
  return data[key] !== void 0 ? format(data[key]) : match;
3860
3841
  });
3861
3842
  }
3862
3843
 
3863
- const ajv$1 = new Ajv__default.default({ strict: true, strictTuples: true, strictTypes: true });
3864
- ajv$1.addMetaSchema(ajvSchemaDraft);
3865
- ajv$1.addKeyword(ajvRegexpKeyword);
3844
+ const ajv$1 = (() => {
3845
+ const ajv2 = new Ajv__default.default({ strict: true, strictTuples: true, strictTypes: true });
3846
+ ajv2.addMetaSchema(ajvSchemaDraft);
3847
+ ajv2.addKeyword(ajvRegexpKeyword);
3848
+ return ajv2;
3849
+ })();
3866
3850
  function getSchemaValidator(ruleId, properties) {
3867
3851
  const $id = `rule/${ruleId}`;
3868
3852
  const cached = ajv$1.getSchema($id);
@@ -3883,10 +3867,9 @@ function isErrorDescriptor(value) {
3883
3867
  function unpackErrorDescriptor(value) {
3884
3868
  if (isErrorDescriptor(value)) {
3885
3869
  return value[0];
3886
- } else {
3887
- const [node, message, location, context] = value;
3888
- return { node, message, location, context };
3889
3870
  }
3871
+ const [node, message, location, context] = value;
3872
+ return { node, message, location, context };
3890
3873
  }
3891
3874
  class Rule {
3892
3875
  reporter;
@@ -4092,17 +4075,18 @@ class Rule {
4092
4075
  const callback = args.pop();
4093
4076
  const filter = args.pop() ?? (() => true);
4094
4077
  return this.parser.on(event, (_event, data) => {
4095
- if (this.isEnabled() && filter(data)) {
4096
- this.event = data;
4097
- const { tracker } = this;
4098
- if (tracker) {
4099
- const start = performance.now();
4100
- callback(data);
4101
- const end = performance.now();
4102
- tracker.trackRule(this.name, end - start);
4103
- } else {
4104
- callback(data);
4105
- }
4078
+ if (!this.isEnabled() || !filter(data)) {
4079
+ return;
4080
+ }
4081
+ this.event = data;
4082
+ const { tracker } = this;
4083
+ if (tracker) {
4084
+ const start = performance.now();
4085
+ callback(data);
4086
+ const end = performance.now();
4087
+ tracker.trackRule(this.name, end - start);
4088
+ } else {
4089
+ callback(data);
4106
4090
  }
4107
4091
  });
4108
4092
  }
@@ -4172,7 +4156,7 @@ class Rule {
4172
4156
  * @public
4173
4157
  * @virtual
4174
4158
  * @param context - Error context given by a reported error.
4175
- * @returns Rule documentation and url with additional details or `null` if no
4159
+ * @returns Rule documentation and URL with additional details or `null` if no
4176
4160
  * additional documentation is available.
4177
4161
  */
4178
4162
  documentation(_context) {
@@ -4211,7 +4195,7 @@ function parseAllow(value) {
4211
4195
  };
4212
4196
  }
4213
4197
  function matchList(value, list) {
4214
- if (list.include && !list.include.some((it) => it.test(value))) {
4198
+ if (list.include?.every((it) => !it.test(value))) {
4215
4199
  return false;
4216
4200
  }
4217
4201
  if (list.exclude?.some((it) => it.test(value))) {
@@ -4296,10 +4280,10 @@ class AllowedLinks extends Rule {
4296
4280
  return Boolean(attr && attr === key);
4297
4281
  }
4298
4282
  getStyle(value) {
4299
- if (/^([a-z]+:)?\/\//g.test(value)) {
4283
+ if (/^(?:[a-z]+:)?\/\//.test(value)) {
4300
4284
  return "external" /* EXTERNAL */;
4301
4285
  }
4302
- switch (value[0]) {
4286
+ switch (value.at(0)) {
4303
4287
  /* /foo/bar */
4304
4288
  case "/":
4305
4289
  return "absolute" /* ABSOLUTE */;
@@ -4318,7 +4302,8 @@ class AllowedLinks extends Rule {
4318
4302
  const { allowAbsolute } = this;
4319
4303
  if (allowAbsolute === true) {
4320
4304
  return;
4321
- } else if (allowAbsolute === false) {
4305
+ }
4306
+ if (allowAbsolute === false) {
4322
4307
  this.report(
4323
4308
  event.target,
4324
4309
  "Link destination must not be absolute url",
@@ -4338,7 +4323,8 @@ class AllowedLinks extends Rule {
4338
4323
  const { allowExternal } = this;
4339
4324
  if (allowExternal === true) {
4340
4325
  return;
4341
- } else if (allowExternal === false) {
4326
+ }
4327
+ if (allowExternal === false) {
4342
4328
  this.report(
4343
4329
  event.target,
4344
4330
  "Link destination must not be external url",
@@ -4358,7 +4344,8 @@ class AllowedLinks extends Rule {
4358
4344
  const { allowRelative } = this;
4359
4345
  if (allowRelative === true) {
4360
4346
  return false;
4361
- } else if (allowRelative === false) {
4347
+ }
4348
+ if (allowRelative === false) {
4362
4349
  this.report(
4363
4350
  event.target,
4364
4351
  "Link destination must not be relative url",
@@ -4366,7 +4353,8 @@ class AllowedLinks extends Rule {
4366
4353
  style
4367
4354
  );
4368
4355
  return true;
4369
- } else if (!matchList(target, allowRelative)) {
4356
+ }
4357
+ if (!matchList(target, allowRelative)) {
4370
4358
  this.report(
4371
4359
  event.target,
4372
4360
  "Relative link to this destination is not allowed by current configuration",
@@ -4381,7 +4369,8 @@ class AllowedLinks extends Rule {
4381
4369
  const { allowBase } = this.options;
4382
4370
  if (this.handleRelativePath(target, event, style)) {
4383
4371
  return;
4384
- } else if (!allowBase) {
4372
+ }
4373
+ if (!allowBase) {
4385
4374
  this.report(
4386
4375
  event.target,
4387
4376
  "Relative links must be relative to current folder",
@@ -4599,12 +4588,11 @@ class AriaLabelMisuse extends Rule {
4599
4588
  ].join("\n"),
4600
4589
  url
4601
4590
  };
4602
- } else {
4603
- return {
4604
- description: [`\`${context.attr}\` can only be used on:`, "", ...lines].join("\n"),
4605
- url
4606
- };
4607
4591
  }
4592
+ return {
4593
+ description: [`\`${context.attr}\` can only be used on:`, "", ...lines].join("\n"),
4594
+ url
4595
+ };
4608
4596
  }
4609
4597
  setup() {
4610
4598
  this.on("dom:ready", (event) => {
@@ -4662,6 +4650,7 @@ class AriaLabelMisuse extends Rule {
4662
4650
  }
4663
4651
 
4664
4652
  class ConfigError extends UserError {
4653
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
4665
4654
  constructor(message, nested) {
4666
4655
  super(message, nested);
4667
4656
  this.name = "ConfigError";
@@ -4782,9 +4771,8 @@ class AttrCase extends Rule {
4782
4771
  isIgnored(node) {
4783
4772
  if (this.options.ignoreForeign) {
4784
4773
  return Boolean(node.meta?.foreign);
4785
- } else {
4786
- return false;
4787
4774
  }
4775
+ return false;
4788
4776
  }
4789
4777
  }
4790
4778
 
@@ -4834,10 +4822,11 @@ class Context {
4834
4822
  let lastNewline = -1;
4835
4823
  let newlines = 0;
4836
4824
  for (let i = 0; i < n; i++) {
4837
- if (this.string[i] === "\n") {
4838
- newlines++;
4839
- lastNewline = i;
4825
+ if (this.string[i] !== "\n") {
4826
+ continue;
4840
4827
  }
4828
+ newlines++;
4829
+ lastNewline = i;
4841
4830
  }
4842
4831
  if (newlines > 0) {
4843
4832
  this.line += newlines;
@@ -4899,28 +4888,29 @@ const MATCH_DOCTYPE_CLOSE = /^>/;
4899
4888
  const MATCH_XML_TAG = /^<\?xml.*?\?>\s+/;
4900
4889
  const MATCH_TAG_OPEN = /^<(\/?)([\w:\-]+)/;
4901
4890
  const MATCH_TAG_CLOSE = /^\/?>/;
4902
- const MATCH_TEXT = /^[^]*?(?=(?:[\t ]*(?:\r\n|\r|\n)|<[^ ]|$))/;
4891
+ const MATCH_TEXT = /^[\s\S]*?(?=[\t ]*(?:\r\n|\r|\n)|<[^ ]|$)/;
4903
4892
  const MATCH_TEMPLATING = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)/s;
4904
- const MATCH_TAG_LOOKAHEAD = /^[^]*?(?=<|$)/;
4893
+ const MATCH_TAG_LOOKAHEAD = /^[\s\S]*?(?=<|$)/;
4905
4894
  const MATCH_ATTR_START = /^([^\t\n\f\r "'/<=>]+)/;
4906
- const MATCH_ATTR_SINGLE = /^(\s*=\s*)'([^']*?)(')/;
4907
- const MATCH_ATTR_DOUBLE = /^(\s*=\s*)"([^"]*?)(")/;
4895
+ const MATCH_ATTR_SINGLE = /^(\s*=\s*)'([^']*)(')/;
4896
+ const MATCH_ATTR_DOUBLE = /^(\s*=\s*)"([^"]*)(")/;
4908
4897
  const MATCH_ATTR_UNQUOTED = /^(\s*=\s*)([^\t\n\f\r "'<>][^\t\n\f\r <>]*)/;
4909
4898
  const MATCH_CDATA_BEGIN = /^<!\[CDATA\[/;
4910
- const MATCH_CDATA_END = /^[^]*?]]>/;
4911
- const MATCH_SCRIPT_DATA = /^[^]*?(?=<\/script)/;
4899
+ const MATCH_CDATA_END = /^[\s\S]*?\]\]>/;
4900
+ const MATCH_SCRIPT_DATA = /^[\s\S]*?(?=<\/script)/;
4912
4901
  const MATCH_SCRIPT_END = /^<(\/)(script)/;
4913
- const MATCH_STYLE_DATA = /^[^]*?(?=<\/style)/;
4902
+ const MATCH_STYLE_DATA = /^[\s\S]*?(?=<\/style)/;
4914
4903
  const MATCH_STYLE_END = /^<(\/)(style)/;
4915
- const MATCH_TEXTAREA_DATA = /^[^]*?(?=<\/textarea)/;
4904
+ const MATCH_TEXTAREA_DATA = /^[\s\S]*?(?=<\/textarea)/;
4916
4905
  const MATCH_TEXTAREA_END = /^<(\/)(textarea)/;
4917
- const MATCH_TITLE_DATA = /^[^]*?(?=<\/title)/;
4906
+ const MATCH_TITLE_DATA = /^[\s\S]*?(?=<\/title)/;
4918
4907
  const MATCH_TITLE_END = /^<(\/)(title)/;
4919
- const MATCH_DIRECTIVE = /^(<!--\s*\[?)(html-validate-)([\da-z-]+)(\s*)(.*?)(]?\s*-->)/;
4920
- const MATCH_COMMENT = /^<!--([^]*?)-->/;
4921
- const MATCH_CONDITIONAL = /^<!\[([^\]]*?)]>/;
4908
+ const MATCH_DIRECTIVE = /^(<!--\s*\[?)(html-validate-)([\da-z-]+)(\s*)(.*?)(\]?\s*-->)/;
4909
+ const MATCH_COMMENT = /^<!--([\s\S]*?)-->/;
4910
+ const MATCH_CONDITIONAL = /^<!\[([^\]]*)\]>/;
4922
4911
  class InvalidTokenError extends Error {
4923
4912
  location;
4913
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
4924
4914
  constructor(location, message) {
4925
4915
  super(message);
4926
4916
  this.name = "InvalidTokenError";
@@ -5004,9 +4994,8 @@ class Lexer {
5004
4994
  evalNextState(nextState, token) {
5005
4995
  if (typeof nextState === "function") {
5006
4996
  return nextState(token);
5007
- } else {
5008
- return nextState;
5009
4997
  }
4998
+ return nextState;
5010
4999
  }
5011
5000
  *match(context, tests, error) {
5012
5001
  const n = tests.length;
@@ -5093,27 +5082,26 @@ class Lexer {
5093
5082
  case ContentModel.SCRIPT:
5094
5083
  if (selfClosed) {
5095
5084
  return State.SCRIPT;
5096
- } else {
5097
- return State.TEXT;
5098
5085
  }
5086
+ return State.TEXT;
5087
+ /* <script/> (not legal but handle it anyway so the lexer doesn't choke on it) */
5099
5088
  case ContentModel.STYLE:
5100
5089
  if (selfClosed) {
5101
5090
  return State.STYLE;
5102
- } else {
5103
- return State.TEXT;
5104
5091
  }
5092
+ return State.TEXT;
5093
+ /* <style/> */
5105
5094
  case ContentModel.TEXTAREA:
5106
5095
  if (selfClosed) {
5107
5096
  return State.TEXTAREA;
5108
- } else {
5109
- return State.TEXT;
5110
5097
  }
5098
+ return State.TEXT;
5099
+ /* <textarea/> */
5111
5100
  case ContentModel.TITLE:
5112
5101
  if (selfClosed) {
5113
5102
  return State.TITLE;
5114
- } else {
5115
- return State.TEXT;
5116
5103
  }
5104
+ return State.TEXT;
5117
5105
  }
5118
5106
  }
5119
5107
  yield* this.match(
@@ -5200,7 +5188,7 @@ class Lexer {
5200
5188
  }
5201
5189
  }
5202
5190
 
5203
- const whitespace = /(\s+)/;
5191
+ const whitespace = /\s+/;
5204
5192
  class AttrDelimiter extends Rule {
5205
5193
  documentation() {
5206
5194
  return {
@@ -5232,17 +5220,15 @@ const defaults$y = {
5232
5220
  function generateRegexp(pattern) {
5233
5221
  if (Array.isArray(pattern)) {
5234
5222
  return new RegExp(`^(${pattern.join("|")})$`, "i");
5235
- } else {
5236
- return new RegExp(`^${pattern}$`, "i");
5237
5223
  }
5224
+ return new RegExp(`^${pattern}$`, "i");
5238
5225
  }
5239
5226
  function generateMessage(name, pattern) {
5240
5227
  if (Array.isArray(pattern)) {
5241
5228
  const patterns = pattern.map((it) => `/${it}/`).join(", ");
5242
5229
  return `Attribute "${name}" should match one of [${patterns}]`;
5243
- } else {
5244
- return `Attribute "${name}" should match /${pattern}/`;
5245
5230
  }
5231
+ return `Attribute "${name}" should match /${pattern}/`;
5246
5232
  }
5247
5233
  function generateDescription(name, pattern) {
5248
5234
  if (Array.isArray(pattern)) {
@@ -5251,9 +5237,8 @@ function generateDescription(name, pattern) {
5251
5237
  "",
5252
5238
  ...pattern.map((it) => `- \`/${it}/\``)
5253
5239
  ].join("\n");
5254
- } else {
5255
- return `Attribute "${name}" should match the regular expression \`/${pattern}/\``;
5256
5240
  }
5241
+ return `Attribute "${name}" should match the regular expression \`/${pattern}/\``;
5257
5242
  }
5258
5243
  class AttrPattern extends Rule {
5259
5244
  pattern;
@@ -5299,9 +5284,8 @@ class AttrPattern extends Rule {
5299
5284
  isIgnored(node) {
5300
5285
  if (this.options.ignoreForeign) {
5301
5286
  return Boolean(node.meta?.foreign);
5302
- } else {
5303
- return false;
5304
5287
  }
5288
+ return false;
5305
5289
  }
5306
5290
  }
5307
5291
 
@@ -5412,9 +5396,8 @@ class AttrQuotes extends Rule {
5412
5396
  resolveQuotemark(value, style) {
5413
5397
  if (style === "auto" /* AUTO_QUOTE */) {
5414
5398
  return value.includes('"') ? "'" : '"';
5415
- } else {
5416
- return style;
5417
5399
  }
5400
+ return style;
5418
5401
  }
5419
5402
  }
5420
5403
  function parseStyle$3(style) {
@@ -5472,11 +5455,11 @@ class AttributeAllowedValues extends Rule {
5472
5455
  const allowedList = allowed.enum.map((value2) => {
5473
5456
  if (typeof value2 === "string") {
5474
5457
  return `- \`"${value2}"\``;
5475
- } else if (value2 instanceof RegExp) {
5458
+ }
5459
+ if (value2 instanceof RegExp) {
5476
5460
  return `- \`${value2.toString()}\``;
5477
- } else {
5478
- return `- ${value2.name}`;
5479
5461
  }
5462
+ return `- ${value2.name}`;
5480
5463
  });
5481
5464
  docs.description = [
5482
5465
  `The \`<${element}>\` element does not allow the attribute \`${attribute}\` to have the value \`"${value}"\`.`,
@@ -5520,9 +5503,8 @@ class AttributeAllowedValues extends Rule {
5520
5503
  const { key, value } = attr;
5521
5504
  if (value !== null) {
5522
5505
  return `Attribute "${key}" has invalid value "${value.toString()}"`;
5523
- } else {
5524
- return `Attribute "${key}" is missing value`;
5525
5506
  }
5507
+ return `Attribute "${key}" is missing value`;
5526
5508
  }
5527
5509
  getLocation(attr) {
5528
5510
  return attr.valueLocation ?? attr.keyLocation;
@@ -5809,10 +5791,10 @@ class AutocompletePassword extends Rule {
5809
5791
  const tokens = new DOMTokenList(raw, autocomplete.valueLocation);
5810
5792
  const index = tokens.findIndex((token) => !isGroupingToken(token));
5811
5793
  const value = tokens.item(index);
5812
- const location = tokens.location(index);
5813
5794
  if (!value) {
5814
5795
  return;
5815
5796
  }
5797
+ const location = tokens.location(index);
5816
5798
  if (value === "off") {
5817
5799
  const context = { kind: "off" };
5818
5800
  this.report({
@@ -5897,9 +5879,8 @@ function parsePattern(pattern) {
5897
5879
  function toArray$2(value) {
5898
5880
  if (Array.isArray(value)) {
5899
5881
  return value;
5900
- } else {
5901
- return [value];
5902
5882
  }
5883
+ return [value];
5903
5884
  }
5904
5885
  function validateAllowedPatterns(patterns, allowedPatterns, ruleId) {
5905
5886
  const extraneous = patterns.filter(isNamedPattern).filter((p) => !allowedPatterns.has(p));
@@ -5985,7 +5966,7 @@ class ClassPattern extends BasePatternRule {
5985
5966
  });
5986
5967
  }
5987
5968
  static schema() {
5988
- return BasePatternRule.schema();
5969
+ return super.schema();
5989
5970
  }
5990
5971
  documentation(context) {
5991
5972
  return {
@@ -6066,10 +6047,10 @@ class CloseOrder extends Rule {
6066
6047
  });
6067
6048
  this.on("tag:end", (event) => {
6068
6049
  const current = event.target;
6069
- const active = event.previous;
6070
6050
  if (current) {
6071
6051
  return;
6072
6052
  }
6053
+ const active = event.previous;
6073
6054
  for (const ancestor of ancestors(active)) {
6074
6055
  if (ancestor.isRootElement() || reported.has(ancestor.unique)) {
6075
6056
  continue;
@@ -6080,13 +6061,13 @@ class CloseOrder extends Rule {
6080
6061
  });
6081
6062
  this.on("tag:end", (event) => {
6082
6063
  const current = event.target;
6083
- const active = event.previous;
6084
6064
  if (!current) {
6085
6065
  return;
6086
6066
  }
6087
6067
  if (current.voidElement) {
6088
6068
  return;
6089
6069
  }
6070
+ const active = event.previous;
6090
6071
  if (active.closed === Node.CLOSED_IMPLICIT_CLOSED) {
6091
6072
  return;
6092
6073
  }
@@ -6181,7 +6162,7 @@ class Deprecated extends Rule {
6181
6162
  text.push(context.documentation);
6182
6163
  }
6183
6164
  const doc = {
6184
- description: text.map((cur) => cur.replaceAll("$tagname", context.tagName)).join("\n\n"),
6165
+ description: text.map((cur) => cur.replaceAll("$tagname", () => context.tagName)).join("\n\n"),
6185
6166
  url: "https://html-validate.org/rules/deprecated.html"
6186
6167
  };
6187
6168
  return doc;
@@ -6580,7 +6561,7 @@ class ElementName extends Rule {
6580
6561
  ];
6581
6562
  }
6582
6563
  setup() {
6583
- const xmlns = /^(.+):.+$/;
6564
+ const xmlns = /^[^:]+:.+$/;
6584
6565
  this.on("tag:start", (event) => {
6585
6566
  const target = event.target;
6586
6567
  const tagName = target.tagName;
@@ -6619,13 +6600,12 @@ function isNativeTemplate(node) {
6619
6600
  function getTransparentChildren(node, transparent) {
6620
6601
  if (typeof transparent === "boolean") {
6621
6602
  return node.childElements;
6622
- } else {
6623
- return node.childElements.filter((it) => {
6624
- return transparent.some((category) => {
6625
- return Validator.validatePermittedCategory(it, category, false);
6626
- });
6627
- });
6628
6603
  }
6604
+ return node.childElements.filter((it) => {
6605
+ return transparent.some((category) => {
6606
+ return Validator.validatePermittedCategory(it, category, false);
6607
+ });
6608
+ });
6629
6609
  }
6630
6610
  function getRuleDescription$2(context) {
6631
6611
  switch (context.kind) {
@@ -6657,6 +6637,7 @@ class ElementPermittedContent extends Rule {
6657
6637
  [
6658
6638
  () => this.validatePermittedContent(node, parent),
6659
6639
  () => this.validatePermittedDescendant(node, parent)
6640
+ /* eslint-disable-next-line unicorn/no-unused-array-method-return -- technical debt, should use iterator helpers */
6660
6641
  ].some((fn) => fn());
6661
6642
  });
6662
6643
  });
@@ -6802,14 +6783,12 @@ function getRuleDescription$1(context) {
6802
6783
  const allowed = rules.filter(isCategoryOrTag).map((it) => {
6803
6784
  if (isCategory$1(it)) {
6804
6785
  return `- any ${it.slice(1)} element`;
6805
- } else {
6806
- return `- \`<${it}>\``;
6807
6786
  }
6787
+ return `- \`<${it}>\``;
6808
6788
  });
6809
6789
  return [preamble, "", "Allowed parents one of:", "", ...allowed];
6810
- } else {
6811
- return [preamble];
6812
6790
  }
6791
+ return [preamble];
6813
6792
  }
6814
6793
  function formatMessage$1(node, parent, rules) {
6815
6794
  const nodeName = node.annotatedName;
@@ -6861,7 +6840,7 @@ class ElementPermittedParent extends Rule {
6861
6840
  }
6862
6841
 
6863
6842
  function isTagnameOnly(value) {
6864
- return /^[\dA-Za-z-]+$/.test(value);
6843
+ return /^[\dA-Z-]+$/i.test(value);
6865
6844
  }
6866
6845
  function getRuleDescription(context) {
6867
6846
  const escaped = context.ancestor.map((it) => `\`${it}\``);
@@ -6924,9 +6903,8 @@ function normalizeRequired(element, attr) {
6924
6903
  default:
6925
6904
  return result;
6926
6905
  }
6927
- } else {
6928
- return required ? defaultMessage : false;
6929
6906
  }
6907
+ return required ? defaultMessage : false;
6930
6908
  }
6931
6909
  class ElementRequiredAttributes extends Rule {
6932
6910
  documentation(context) {
@@ -7008,7 +6986,8 @@ const selector = ["h1", "h2", "h3", "h4", "h5", "h6"].join(",");
7008
6986
  function hasImgAltText$1(node) {
7009
6987
  if (node.is("img")) {
7010
6988
  return hasAltText(node);
7011
- } else if (node.is("svg")) {
6989
+ }
6990
+ if (node.is("svg")) {
7012
6991
  return node.textContent.trim() !== "";
7013
6992
  }
7014
6993
  return false;
@@ -7289,21 +7268,19 @@ class FormDupName extends Rule {
7289
7268
  const existing = group.cacheGet(UNIQUE_CACHE_KEY);
7290
7269
  if (existing) {
7291
7270
  return existing;
7292
- } else {
7293
- const elements = /* @__PURE__ */ new Map();
7294
- group.cacheSet(UNIQUE_CACHE_KEY, elements);
7295
- return elements;
7296
7271
  }
7272
+ const elements = /* @__PURE__ */ new Map();
7273
+ group.cacheSet(UNIQUE_CACHE_KEY, elements);
7274
+ return elements;
7297
7275
  }
7298
7276
  getSharedElements(group) {
7299
7277
  const existing = group.cacheGet(SHARED_CACHE_KEY);
7300
7278
  if (existing) {
7301
7279
  return existing;
7302
- } else {
7303
- const elements = /* @__PURE__ */ new Map();
7304
- group.cacheSet(SHARED_CACHE_KEY, elements);
7305
- return elements;
7306
7280
  }
7281
+ const elements = /* @__PURE__ */ new Map();
7282
+ group.cacheSet(SHARED_CACHE_KEY, elements);
7283
+ return elements;
7307
7284
  }
7308
7285
  }
7309
7286
 
@@ -7317,12 +7294,11 @@ function isRelevant$5(event) {
7317
7294
  return Boolean(node.meta?.heading);
7318
7295
  }
7319
7296
  function extractLevel(node) {
7320
- const match = /^[Hh](\d)$/.exec(node.tagName);
7297
+ const match = /^H(\d)$/i.exec(node.tagName);
7321
7298
  if (match) {
7322
- return Number.parseInt(match[1], 10);
7323
- } else {
7324
- return null;
7299
+ return Math.trunc(Number(match[1]));
7325
7300
  }
7301
+ return null;
7326
7302
  }
7327
7303
  function parseMaxInitial(value) {
7328
7304
  if (value === false || value === "any") {
@@ -7332,7 +7308,7 @@ function parseMaxInitial(value) {
7332
7308
  if (!match) {
7333
7309
  return 1;
7334
7310
  }
7335
- return Number.parseInt(match[1], 10);
7311
+ return Math.trunc(Number(match[1]));
7336
7312
  }
7337
7313
  class HeadingLevel extends Rule {
7338
7314
  minInitialRank;
@@ -7599,7 +7575,7 @@ class IdPattern extends BasePatternRule {
7599
7575
  });
7600
7576
  }
7601
7577
  static schema() {
7602
- return BasePatternRule.schema();
7578
+ return super.schema();
7603
7579
  }
7604
7580
  documentation(context) {
7605
7581
  return {
@@ -7821,24 +7797,23 @@ function isHidden(node, context) {
7821
7797
  const { reference } = context;
7822
7798
  if (reference?.isSameNode(node)) {
7823
7799
  return false;
7824
- } else {
7825
- return !inAccessibilityTree(node);
7826
7800
  }
7801
+ return !inAccessibilityTree(node);
7827
7802
  }
7828
7803
  function hasImgAltText(node, context) {
7829
7804
  if (node.is("img")) {
7830
7805
  return hasAltText(node);
7831
- } else if (node.is("svg")) {
7806
+ }
7807
+ if (node.is("svg")) {
7832
7808
  return node.textContent.trim() !== "";
7833
- } else {
7834
- for (const img of node.querySelectorAll("img, svg")) {
7835
- const hasName = hasAccessibleNameImpl(img, context);
7836
- if (hasName) {
7837
- return true;
7838
- }
7809
+ }
7810
+ for (const img of node.querySelectorAll("img, svg")) {
7811
+ const hasName = hasAccessibleNameImpl(img, context);
7812
+ if (hasName) {
7813
+ return true;
7839
7814
  }
7840
- return false;
7841
7815
  }
7816
+ return false;
7842
7817
  }
7843
7818
  function hasLabel(node) {
7844
7819
  const value = node.getAttributeValue("aria-label") ?? "";
@@ -7969,7 +7944,7 @@ class InputMissingLabel extends Rule {
7969
7944
  this.report(elem, `<${elem.tagName}> element has <label> but <label> element is hidden`);
7970
7945
  return;
7971
7946
  }
7972
- if (!labels.some((label) => hasAccessibleName(root, label))) {
7947
+ if (labels.every((label) => !hasAccessibleName(root, label))) {
7973
7948
  this.report(elem, `<${elem.tagName}> element has <label> but <label> has no text`);
7974
7949
  }
7975
7950
  }
@@ -8156,12 +8131,11 @@ function parseContent(text) {
8156
8131
  const match = /^(\d+)(?:\s*;\s*url=(.*))?/i.exec(text);
8157
8132
  if (match) {
8158
8133
  return {
8159
- delay: Number.parseInt(match[1], 10),
8134
+ delay: Math.trunc(Number(match[1])),
8160
8135
  url: match[2]
8161
8136
  };
8162
- } else {
8163
- return null;
8164
8137
  }
8138
+ return null;
8165
8139
  }
8166
8140
 
8167
8141
  class MissingDoctype extends Rule {
@@ -8238,7 +8212,7 @@ class NamePattern extends BasePatternRule {
8238
8212
  });
8239
8213
  }
8240
8214
  static schema() {
8241
- return BasePatternRule.schema();
8215
+ return super.schema();
8242
8216
  }
8243
8217
  documentation(context) {
8244
8218
  return {
@@ -8421,10 +8395,10 @@ class NoDeprecatedAttr extends Rule {
8421
8395
  this.on("attr", (event) => {
8422
8396
  const node = event.target;
8423
8397
  const meta = node.meta;
8424
- const attr = event.key.toLowerCase();
8425
8398
  if (meta === null) {
8426
8399
  return;
8427
8400
  }
8401
+ const attr = event.key.toLowerCase();
8428
8402
  const metaAttribute = meta.attributes[attr];
8429
8403
  if (!metaAttribute) {
8430
8404
  return;
@@ -8458,7 +8432,7 @@ class NoDupAttr extends Rule {
8458
8432
  return;
8459
8433
  }
8460
8434
  const name = event.key.toLowerCase();
8461
- if (name in attr) {
8435
+ if (Object.hasOwn(attr, name)) {
8462
8436
  this.report(event.target, `Attribute "${name}" duplicated`, event.keyLocation);
8463
8437
  }
8464
8438
  attr[event.key] = true;
@@ -8531,10 +8505,9 @@ function getExisting(element, root) {
8531
8505
  const existing = group.cacheGet(CACHE_KEY);
8532
8506
  if (existing) {
8533
8507
  return existing;
8534
- } else {
8535
- const existing2 = /* @__PURE__ */ new Set();
8536
- return group.cacheSet(CACHE_KEY, existing2);
8537
8508
  }
8509
+ const value = /* @__PURE__ */ new Set();
8510
+ return group.cacheSet(CACHE_KEY, value);
8538
8511
  }
8539
8512
 
8540
8513
  function isRelevant$2(event) {
@@ -8805,10 +8778,11 @@ class NoMissingReferences extends Rule {
8805
8778
  }
8806
8779
  }
8807
8780
  validateSingle(document, node, attr, id) {
8808
- if (idMissing(document, id)) {
8809
- const context = { key: attr.key, value: id };
8810
- this.report(node, `Element references missing id "${id}"`, attr.valueLocation, context);
8781
+ if (!idMissing(document, id)) {
8782
+ return;
8811
8783
  }
8784
+ const context = { key: attr.key, value: id };
8785
+ this.report(node, `Element references missing id "${id}"`, attr.valueLocation, context);
8812
8786
  }
8813
8787
  validateList(document, node, attr, values) {
8814
8788
  const parsed = new DOMTokenList(values, attr.valueLocation);
@@ -8848,9 +8822,9 @@ class NoMultipleMain extends Rule {
8848
8822
  const defaults$f = {
8849
8823
  relaxed: false
8850
8824
  };
8851
- const textRegexp = /(<|&(?![\d#A-Za-z]+;))/g;
8852
- const unquotedAttrRegexp = /(["'<=>`]|&(?![\d#A-Za-z]+;))/g;
8853
- const matchTemplate = /^(<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
8825
+ const textRegexp = /(<|&(?![\d#A-Z]+;))/gi;
8826
+ const unquotedAttrRegexp = /(["'<=>`]|&(?![\d#A-Z]+;))/gi;
8827
+ const matchTemplate = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
8854
8828
  const replacementTable = {
8855
8829
  '"': "&quot;",
8856
8830
  "&": "&amp;",
@@ -9082,7 +9056,7 @@ class NoRedundantRole extends Rule {
9082
9056
  }
9083
9057
  }
9084
9058
 
9085
- const xmlns = /^(.+):.+$/;
9059
+ const xmlns = /^[^:]+:.+$/;
9086
9060
  const defaults$d = {
9087
9061
  ignoreForeign: true,
9088
9062
  ignoreXML: true
@@ -9204,11 +9178,11 @@ class NoUnknownAttributes extends Rule {
9204
9178
  this.on("attr", (event) => {
9205
9179
  const node = event.target;
9206
9180
  const meta = node.meta;
9207
- const attr = event.key.toLowerCase();
9208
9181
  if (meta === null) {
9209
9182
  return;
9210
9183
  }
9211
- if (attr in meta.attributes) {
9184
+ const attr = event.key.toLowerCase();
9185
+ if (Object.hasOwn(meta.attributes, attr)) {
9212
9186
  return;
9213
9187
  }
9214
9188
  if (isPatternAttribute(attr, meta.patternAttributes)) {
@@ -9615,7 +9589,7 @@ const defaults$7 = {
9615
9589
  include: null,
9616
9590
  exclude: null
9617
9591
  };
9618
- const crossorigin = new RegExp("^(\\w+://|//)");
9592
+ const crossorigin = /^(?:\w+:\/\/|\/\/)/;
9619
9593
  const supportSri = {
9620
9594
  link: "href",
9621
9595
  script: "src"
@@ -9828,7 +9802,10 @@ function constructRegex(characters) {
9828
9802
  return new RegExp(pattern, "g");
9829
9803
  }
9830
9804
  function getText(node) {
9831
- const match = /^(\s*)(.*)$/.exec(node.textContent);
9805
+ const match = /^(\s*)(\S.*)$/.exec(node.textContent);
9806
+ if (!match) {
9807
+ return [0, ""];
9808
+ }
9832
9809
  const [, leading, text] = match;
9833
9810
  return [leading.length, text.trimEnd()];
9834
9811
  }
@@ -9981,9 +9958,8 @@ function hasDefaultText(node) {
9981
9958
  function isNonEmptyText(node) {
9982
9959
  if (isTextNode(node)) {
9983
9960
  return node.isDynamic || node.textContent.trim() !== "";
9984
- } else {
9985
- return false;
9986
9961
  }
9962
+ return false;
9987
9963
  }
9988
9964
  function haveAccessibleText(node) {
9989
9965
  if (!inAccessibilityTree(node)) {
@@ -10118,15 +10094,14 @@ function getTextFromReference(document, id) {
10118
10094
  const ref = document.querySelector(selector);
10119
10095
  if (ref) {
10120
10096
  return ref.textContent;
10121
- } else {
10122
- return selector;
10123
10097
  }
10098
+ return selector;
10124
10099
  }
10125
10100
  function groupBy(values, callback) {
10126
10101
  const result = {};
10127
10102
  for (const value of values) {
10128
10103
  const key = callback(value);
10129
- if (key in result) {
10104
+ if (Object.hasOwn(result, key)) {
10130
10105
  result[key].push(value);
10131
10106
  } else {
10132
10107
  result[key] = [value];
@@ -10226,7 +10201,7 @@ const defaults$5 = {
10226
10201
  ignoreCase: false,
10227
10202
  requireSemicolon: true
10228
10203
  };
10229
- const regexp$1 = /&(?:[\da-z]+|#x?[\da-f]+)(;|[^\da-z]|$)/gi;
10204
+ const regexp$1 = /&(?:[\da-z]+|#x?[\da-f]+)([^\da-z]|$)/gi;
10230
10205
  const lowercaseEntities = elements.entities.map((it) => it.toLowerCase());
10231
10206
  function isNumerical(entity) {
10232
10207
  return entity.startsWith("&#");
@@ -10305,9 +10280,8 @@ class UnknownCharReference extends Rule {
10305
10280
  get entities() {
10306
10281
  if (this.options.ignoreCase) {
10307
10282
  return lowercaseEntities;
10308
- } else {
10309
- return elements.entities;
10310
10283
  }
10284
+ return elements.entities;
10311
10285
  }
10312
10286
  findCharacterReferences(node, text, location, { isAttribute }) {
10313
10287
  const delimiter = text.search(/[#?]/);
@@ -10673,7 +10647,6 @@ class ValidAutocomplete extends Rule {
10673
10647
  }
10674
10648
  validateControlAutocomplete(node, tokens, keyLocation) {
10675
10649
  const type = node.getAttributeValue("type") ?? "text";
10676
- const mantle = type !== "hidden" ? "expectation" : "anchor";
10677
10650
  if (isDisallowedType(node, type)) {
10678
10651
  const context = {
10679
10652
  msg: 0 /* InvalidAttribute */,
@@ -10688,6 +10661,7 @@ class ValidAutocomplete extends Rule {
10688
10661
  return;
10689
10662
  }
10690
10663
  if (tokens.includes("on") || tokens.includes("off")) {
10664
+ const mantle = type !== "hidden" ? "expectation" : "anchor";
10691
10665
  this.validateOnOff(node, mantle, tokens);
10692
10666
  return;
10693
10667
  }
@@ -10811,44 +10785,46 @@ class ValidAutocomplete extends Rule {
10811
10785
  * Ensure contact token is only used with field names from the second list.
10812
10786
  */
10813
10787
  validateContact(node, tokens, order) {
10814
- if (order.includes("contact") && order.includes("field1")) {
10815
- const a = order.indexOf("field1");
10816
- const b = order.indexOf("contact");
10788
+ if (!order.includes("contact") || !order.includes("field1")) {
10789
+ return;
10790
+ }
10791
+ const a = order.indexOf("field1");
10792
+ const b = order.indexOf("contact");
10793
+ const context = {
10794
+ msg: 4 /* InvalidCombination */,
10795
+ /* eslint-disable @typescript-eslint/no-non-null-assertion -- it must be present of it wouldn't be found */
10796
+ first: tokens.item(a),
10797
+ second: tokens.item(b)
10798
+ /* eslint-enable @typescript-eslint/no-non-null-assertion */
10799
+ };
10800
+ this.report({
10801
+ node,
10802
+ message: getTerminalMessage(context),
10803
+ location: tokens.location(b),
10804
+ context
10805
+ });
10806
+ }
10807
+ validateOrder(node, tokens, order) {
10808
+ const indicies = order.map((it) => expectedOrder.indexOf(it));
10809
+ for (let i = 0; i < indicies.length - 1; i++) {
10810
+ if (indicies[0] <= indicies[i + 1]) {
10811
+ continue;
10812
+ }
10817
10813
  const context = {
10818
- msg: 4 /* InvalidCombination */,
10814
+ msg: 2 /* InvalidOrder */,
10819
10815
  /* eslint-disable @typescript-eslint/no-non-null-assertion -- it must be present of it wouldn't be found */
10820
- first: tokens.item(a),
10821
- second: tokens.item(b)
10816
+ first: tokens.item(i),
10817
+ second: tokens.item(i + 1)
10822
10818
  /* eslint-enable @typescript-eslint/no-non-null-assertion */
10823
10819
  };
10824
10820
  this.report({
10825
10821
  node,
10826
10822
  message: getTerminalMessage(context),
10827
- location: tokens.location(b),
10823
+ location: tokens.location(i + 1),
10828
10824
  context
10829
10825
  });
10830
10826
  }
10831
10827
  }
10832
- validateOrder(node, tokens, order) {
10833
- const indicies = order.map((it) => expectedOrder.indexOf(it));
10834
- for (let i = 0; i < indicies.length - 1; i++) {
10835
- if (indicies[0] > indicies[i + 1]) {
10836
- const context = {
10837
- msg: 2 /* InvalidOrder */,
10838
- /* eslint-disable @typescript-eslint/no-non-null-assertion -- it must be present of it wouldn't be found */
10839
- first: tokens.item(i),
10840
- second: tokens.item(i + 1)
10841
- /* eslint-enable @typescript-eslint/no-non-null-assertion */
10842
- };
10843
- this.report({
10844
- node,
10845
- message: getTerminalMessage(context),
10846
- location: tokens.location(i + 1),
10847
- context
10848
- });
10849
- }
10850
- }
10851
- }
10852
10828
  validateControlGroup(node, tokens, fieldTokens) {
10853
10829
  const numFields = fieldTokens.filter(Boolean).length;
10854
10830
  if (numFields === 0) {
@@ -10940,7 +10916,7 @@ class ValidID extends Rule {
10940
10916
  documentation(context) {
10941
10917
  const { relaxed } = this.options;
10942
10918
  const { kind, id } = context;
10943
- const message = this.messages[kind].replace(`"{{ id }}"`, "`{{ id }}`").replace("id", "ID").replace(/^(.)/, (m) => m.toUpperCase());
10919
+ const message = this.messages[kind].replace(`"{{ id }}"`, "`{{ id }}`").replace("id", "ID").replace(/^./, (m) => m.toUpperCase());
10944
10920
  const relaxedDescription = relaxed ? [] : [
10945
10921
  " - ID must begin with a letter",
10946
10922
  " - ID must only contain letters, digits, `-` and `_`"
@@ -10978,7 +10954,7 @@ class ValidID extends Rule {
10978
10954
  if (relaxed) {
10979
10955
  return;
10980
10956
  }
10981
- if (/^[^\p{L}]/u.test(value)) {
10957
+ if (new RegExp("^\\P{L}", "u").test(value)) {
10982
10958
  const context = { kind: 3 /* LEADING_CHARACTER */, id: value };
10983
10959
  this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10984
10960
  return;
@@ -11339,7 +11315,7 @@ function isSimpleTable(table) {
11339
11315
  return false;
11340
11316
  }
11341
11317
  const numColumns = cells[0].length;
11342
- if (!cells.every((row) => row.length === numColumns)) {
11318
+ if (cells.some((row) => row.length !== numColumns)) {
11343
11319
  return false;
11344
11320
  }
11345
11321
  const shape = getShape(cells);
@@ -11993,7 +11969,7 @@ class ResolvedConfig {
11993
11969
  }
11994
11970
 
11995
11971
  function haveResolver(key, value) {
11996
- return key in value;
11972
+ return Object.hasOwn(value, key);
11997
11973
  }
11998
11974
  function haveConfigResolver(value) {
11999
11975
  return haveResolver("resolveConfig", value);
@@ -12008,7 +11984,10 @@ function haveTransformerResolver(value) {
12008
11984
  return haveResolver("resolveTransformer", value);
12009
11985
  }
12010
11986
  function resolveConfig(resolvers, id, options) {
12011
- for (const resolver of resolvers.filter(haveConfigResolver)) {
11987
+ for (const resolver of resolvers) {
11988
+ if (!haveConfigResolver(resolver)) {
11989
+ continue;
11990
+ }
12012
11991
  const config = resolver.resolveConfig(id, options);
12013
11992
  if (isThenable(config)) {
12014
11993
  return resolveConfigAsync(resolvers, id, options);
@@ -12020,7 +11999,10 @@ function resolveConfig(resolvers, id, options) {
12020
11999
  throw new UserError(`Failed to load configuration from "${id}"`);
12021
12000
  }
12022
12001
  async function resolveConfigAsync(resolvers, id, options) {
12023
- for (const resolver of resolvers.filter(haveConfigResolver)) {
12002
+ for (const resolver of resolvers) {
12003
+ if (!haveConfigResolver(resolver)) {
12004
+ continue;
12005
+ }
12024
12006
  const config = await resolver.resolveConfig(id, options);
12025
12007
  if (config) {
12026
12008
  return config;
@@ -12029,7 +12011,10 @@ async function resolveConfigAsync(resolvers, id, options) {
12029
12011
  throw new UserError(`Failed to load configuration from "${id}"`);
12030
12012
  }
12031
12013
  function resolveElements(resolvers, id, options) {
12032
- for (const resolver of resolvers.filter(haveElementsResolver)) {
12014
+ for (const resolver of resolvers) {
12015
+ if (!haveElementsResolver(resolver)) {
12016
+ continue;
12017
+ }
12033
12018
  const elements = resolver.resolveElements(id, options);
12034
12019
  if (isThenable(elements)) {
12035
12020
  return resolveElementsAsync(resolvers, id, options);
@@ -12041,7 +12026,10 @@ function resolveElements(resolvers, id, options) {
12041
12026
  throw new UserError(`Failed to load elements from "${id}"`);
12042
12027
  }
12043
12028
  async function resolveElementsAsync(resolvers, id, options) {
12044
- for (const resolver of resolvers.filter(haveElementsResolver)) {
12029
+ for (const resolver of resolvers) {
12030
+ if (!haveElementsResolver(resolver)) {
12031
+ continue;
12032
+ }
12045
12033
  const elements = await resolver.resolveElements(id, options);
12046
12034
  if (elements) {
12047
12035
  return elements;
@@ -12050,7 +12038,10 @@ async function resolveElementsAsync(resolvers, id, options) {
12050
12038
  throw new UserError(`Failed to load elements from "${id}"`);
12051
12039
  }
12052
12040
  function resolvePlugin(resolvers, id, options) {
12053
- for (const resolver of resolvers.filter(havePluginResolver)) {
12041
+ for (const resolver of resolvers) {
12042
+ if (!havePluginResolver(resolver)) {
12043
+ continue;
12044
+ }
12054
12045
  const plugin = resolver.resolvePlugin(id, options);
12055
12046
  if (isThenable(plugin)) {
12056
12047
  return resolvePluginAsync(resolvers, id, options);
@@ -12062,7 +12053,10 @@ function resolvePlugin(resolvers, id, options) {
12062
12053
  throw new UserError(`Failed to load plugin from "${id}"`);
12063
12054
  }
12064
12055
  async function resolvePluginAsync(resolvers, id, options) {
12065
- for (const resolver of resolvers.filter(havePluginResolver)) {
12056
+ for (const resolver of resolvers) {
12057
+ if (!havePluginResolver(resolver)) {
12058
+ continue;
12059
+ }
12066
12060
  const plugin = await resolver.resolvePlugin(id, options);
12067
12061
  if (plugin) {
12068
12062
  return plugin;
@@ -12071,7 +12065,10 @@ async function resolvePluginAsync(resolvers, id, options) {
12071
12065
  throw new UserError(`Failed to load plugin from "${id}"`);
12072
12066
  }
12073
12067
  function resolveTransformer(resolvers, id, options) {
12074
- for (const resolver of resolvers.filter(haveTransformerResolver)) {
12068
+ for (const resolver of resolvers) {
12069
+ if (!haveTransformerResolver(resolver)) {
12070
+ continue;
12071
+ }
12075
12072
  const transformer = resolver.resolveTransformer(id, options);
12076
12073
  if (isThenable(transformer)) {
12077
12074
  return resolveTransformerAsync(resolvers, id, options);
@@ -12083,7 +12080,10 @@ function resolveTransformer(resolvers, id, options) {
12083
12080
  throw new UserError(`Failed to load transformer from "${id}"`);
12084
12081
  }
12085
12082
  async function resolveTransformerAsync(resolvers, id, options) {
12086
- for (const resolver of resolvers.filter(haveTransformerResolver)) {
12083
+ for (const resolver of resolvers) {
12084
+ if (!haveTransformerResolver(resolver)) {
12085
+ continue;
12086
+ }
12087
12087
  const transformer = await resolver.resolveTransformer(id, options);
12088
12088
  if (transformer) {
12089
12089
  return transformer;
@@ -12123,9 +12123,12 @@ function staticResolver(map = {}) {
12123
12123
  };
12124
12124
  }
12125
12125
 
12126
- const ajv = new Ajv__default.default({ strict: true, strictTuples: true, strictTypes: true });
12127
- ajv.addMetaSchema(ajvSchemaDraft);
12128
- ajv.addKeyword(ajvFunctionKeyword);
12126
+ const ajv = (() => {
12127
+ const ajv2 = new Ajv__default.default({ strict: true, strictTuples: true, strictTypes: true });
12128
+ ajv2.addMetaSchema(ajvSchemaDraft);
12129
+ ajv2.addKeyword(ajvFunctionKeyword);
12130
+ return ajv2;
12131
+ })();
12129
12132
  const validator = ajv.compile(configurationSchema);
12130
12133
  function overwriteMerge(_a, b) {
12131
12134
  return b;
@@ -12144,18 +12147,16 @@ function mergeInternal(base, rhs) {
12144
12147
  function toArray$1(value) {
12145
12148
  if (Array.isArray(value)) {
12146
12149
  return value;
12147
- } else {
12148
- return [value];
12149
12150
  }
12151
+ return [value];
12150
12152
  }
12151
12153
  function transformerEntries(transform) {
12152
12154
  return Object.entries(transform).map(([pattern, value]) => {
12153
12155
  const regex = new RegExp(pattern);
12154
12156
  if (typeof value === "string") {
12155
12157
  return { kind: "import", pattern: regex, name: value };
12156
- } else {
12157
- return { kind: "function", pattern: regex, function: value };
12158
12158
  }
12159
+ return { kind: "function", pattern: regex, function: value };
12159
12160
  });
12160
12161
  }
12161
12162
  class Config {
@@ -12180,8 +12181,8 @@ class Config {
12180
12181
  * Create configuration from object.
12181
12182
  */
12182
12183
  static fromObject(resolvers, options, filename = null) {
12183
- Config.validate(options, filename);
12184
- return Config.create(resolvers, options);
12184
+ this.validate(options, filename);
12185
+ return this.create(resolvers, options);
12185
12186
  }
12186
12187
  /**
12187
12188
  * Read configuration from filename.
@@ -12195,10 +12196,9 @@ class Config {
12195
12196
  static fromFile(resolvers, filename) {
12196
12197
  const configData = resolveConfig(toArray$1(resolvers), filename, { cache: false });
12197
12198
  if (isThenable(configData)) {
12198
- return configData.then((configData2) => Config.fromObject(resolvers, configData2, filename));
12199
- } else {
12200
- return Config.fromObject(resolvers, configData, filename);
12199
+ return configData.then((configData2) => this.fromObject(resolvers, configData2, filename));
12201
12200
  }
12201
+ return this.fromObject(resolvers, configData, filename);
12202
12202
  }
12203
12203
  /**
12204
12204
  * Validate configuration data.
@@ -12220,8 +12220,8 @@ class Config {
12220
12220
  );
12221
12221
  }
12222
12222
  if (configData.rules) {
12223
- const normalizedRules = Config.getRulesObject(configData.rules);
12224
- for (const [ruleId, [, ruleOptions]] of normalizedRules.entries()) {
12223
+ const normalizedRules = this.getRulesObject(configData.rules);
12224
+ for (const [ruleId, [, ruleOptions]] of normalizedRules) {
12225
12225
  const cls = bundledRules[ruleId];
12226
12226
  const path = `/rules/${ruleId}/1`;
12227
12227
  Rule.validateOptions(cls, ruleId, path, ruleOptions, filename, configData);
@@ -12244,9 +12244,8 @@ class Config {
12244
12244
  return plugins.then((plugins2) => {
12245
12245
  return instance.init(options, plugins2);
12246
12246
  });
12247
- } else {
12248
- return instance.init(options, plugins);
12249
12247
  }
12248
+ return instance.init(options, plugins);
12250
12249
  }
12251
12250
  init(options, plugins) {
12252
12251
  this.plugins = plugins;
@@ -12263,9 +12262,8 @@ class Config {
12263
12262
  const extendedConfig = this.extendConfig(this.config.extends ?? []);
12264
12263
  if (isThenable(extendedConfig)) {
12265
12264
  return extendedConfig.then((extended) => update(extended));
12266
- } else {
12267
- return update(extendedConfig);
12268
12265
  }
12266
+ return update(extendedConfig);
12269
12267
  }
12270
12268
  /**
12271
12269
  * @internal
@@ -12307,12 +12305,11 @@ class Config {
12307
12305
  instance.extendMeta(instance.plugins);
12308
12306
  return instance;
12309
12307
  });
12310
- } else {
12311
- instance.plugins = plugins;
12312
- instance.configurations = instance.loadConfigurations(instance.plugins);
12313
- instance.extendMeta(instance.plugins);
12314
- return instance;
12315
12308
  }
12309
+ instance.plugins = plugins;
12310
+ instance.configurations = instance.loadConfigurations(instance.plugins);
12311
+ instance.extendMeta(instance.plugins);
12312
+ return instance;
12316
12313
  }
12317
12314
  extendConfig(entries) {
12318
12315
  if (entries.length === 0) {
@@ -12368,20 +12365,19 @@ class Config {
12368
12365
  const result = this.getElementsFromEntry(entry);
12369
12366
  if (isThenable(result)) {
12370
12367
  return result.then((result2) => {
12371
- const [obj, filename] = result2;
12372
- metaTable.loadFromObject(obj, filename);
12373
- const next2 = source.shift();
12374
- if (next2) {
12375
- return loadEntry(next2);
12368
+ const [obj2, filename2] = result2;
12369
+ metaTable.loadFromObject(obj2, filename2);
12370
+ const next3 = source.shift();
12371
+ if (next3) {
12372
+ return loadEntry(next3);
12376
12373
  }
12377
12374
  });
12378
- } else {
12379
- const [obj, filename] = result;
12380
- metaTable.loadFromObject(obj, filename);
12381
- const next2 = source.shift();
12382
- if (next2) {
12383
- return loadEntry(next2);
12384
- }
12375
+ }
12376
+ const [obj, filename] = result;
12377
+ metaTable.loadFromObject(obj, filename);
12378
+ const next2 = source.shift();
12379
+ if (next2) {
12380
+ return loadEntry(next2);
12385
12381
  }
12386
12382
  };
12387
12383
  const next = source.shift();
@@ -12411,9 +12407,8 @@ class Config {
12411
12407
  return obj.then((obj2) => {
12412
12408
  return [obj2, entry];
12413
12409
  });
12414
- } else {
12415
- return [obj, entry];
12416
12410
  }
12411
+ return [obj, entry];
12417
12412
  } catch (err) {
12418
12413
  const message = err instanceof Error ? err.message : String(err);
12419
12414
  throw new ConfigError(
@@ -12475,7 +12470,7 @@ class Config {
12475
12470
  const loadPlugin = (entry, index) => {
12476
12471
  if (typeof entry !== "string") {
12477
12472
  const plugin = entry;
12478
- plugin.name = plugin.name || `:unnamedPlugin@${String(index + 1)}`;
12473
+ plugin.name ||= `:unnamedPlugin@${String(index + 1)}`;
12479
12474
  plugin.originalName = `:unnamedPlugin@${String(index + 1)}`;
12480
12475
  loaded.push(plugin);
12481
12476
  const next2 = loading.shift();
@@ -12487,22 +12482,21 @@ class Config {
12487
12482
  const plugin = resolvePlugin(this.resolvers, entry, { cache: true });
12488
12483
  if (isThenable(plugin)) {
12489
12484
  return plugin.then((plugin2) => {
12490
- plugin2.name = plugin2.name || entry;
12485
+ plugin2.name ||= entry;
12491
12486
  plugin2.originalName = entry;
12492
12487
  loaded.push(plugin2);
12493
- const next2 = loading.shift();
12494
- if (next2) {
12495
- return loadPlugin(next2, index + 1);
12488
+ const next3 = loading.shift();
12489
+ if (next3) {
12490
+ return loadPlugin(next3, index + 1);
12496
12491
  }
12497
12492
  });
12498
- } else {
12499
- plugin.name = plugin.name || entry;
12500
- plugin.originalName = entry;
12501
- loaded.push(plugin);
12502
- const next2 = loading.shift();
12503
- if (next2) {
12504
- return loadPlugin(next2, index + 1);
12505
- }
12493
+ }
12494
+ plugin.name ||= entry;
12495
+ plugin.originalName = entry;
12496
+ loaded.push(plugin);
12497
+ const next2 = loading.shift();
12498
+ if (next2) {
12499
+ return loadPlugin(next2, index + 1);
12506
12500
  }
12507
12501
  } catch (err) {
12508
12502
  const message = err instanceof Error ? err.message : String(err);
@@ -12528,7 +12522,8 @@ class Config {
12528
12522
  configs.set(name, config);
12529
12523
  }
12530
12524
  for (const plugin of plugins) {
12531
- for (const [name, config] of Object.entries(plugin.configs ?? {})) {
12525
+ const entries = Object.entries(plugin.configs ?? {});
12526
+ for (const [name, config] of entries) {
12532
12527
  if (!config) {
12533
12528
  continue;
12534
12529
  }
@@ -12572,9 +12567,8 @@ class Config {
12572
12567
  return resolveData.then((resolveData2) => {
12573
12568
  return new ResolvedConfig(resolveData2, this.get());
12574
12569
  });
12575
- } else {
12576
- return new ResolvedConfig(resolveData, this.get());
12577
12570
  }
12571
+ return new ResolvedConfig(resolveData, this.get());
12578
12572
  }
12579
12573
  /**
12580
12574
  * Same as [[resolve]] but returns the raw configuration data instead of
@@ -12593,14 +12587,13 @@ class Config {
12593
12587
  transformers: this.transformers
12594
12588
  };
12595
12589
  });
12596
- } else {
12597
- return {
12598
- metaTable,
12599
- plugins: this.getPlugins(),
12600
- rules: this.getRules(),
12601
- transformers: this.transformers
12602
- };
12603
12590
  }
12591
+ return {
12592
+ metaTable,
12593
+ plugins: this.getPlugins(),
12594
+ rules: this.getRules(),
12595
+ transformers: this.transformers
12596
+ };
12604
12597
  }
12605
12598
  }
12606
12599
 
@@ -12644,10 +12637,9 @@ class ConfigLoader {
12644
12637
  this._globalConfig = config2;
12645
12638
  return this._globalConfig;
12646
12639
  });
12647
- } else {
12648
- this._globalConfig = config;
12649
- return this._globalConfig;
12650
12640
  }
12641
+ this._globalConfig = config;
12642
+ return this._globalConfig;
12651
12643
  }
12652
12644
  /**
12653
12645
  * Get the global configuration.
@@ -12729,9 +12721,8 @@ class StaticConfigLoader extends ConfigLoader {
12729
12721
  const override = this.loadFromObject(configOverride ?? {});
12730
12722
  if (isThenable(override)) {
12731
12723
  return override.then((override2) => this._resolveConfig(override2));
12732
- } else {
12733
- return this._resolveConfig(override);
12734
12724
  }
12725
+ return this._resolveConfig(override);
12735
12726
  }
12736
12727
  flushCache() {
12737
12728
  }
@@ -12748,25 +12739,22 @@ class StaticConfigLoader extends ConfigLoader {
12748
12739
  const globalConfig = this.getGlobalConfig();
12749
12740
  if (isThenable(globalConfig)) {
12750
12741
  return globalConfig.then((globalConfig2) => {
12751
- const merged = globalConfig2.merge(this.resolvers, override);
12752
- if (isThenable(merged)) {
12753
- return merged.then((merged2) => {
12754
- return merged2.resolve();
12742
+ const merged2 = globalConfig2.merge(this.resolvers, override);
12743
+ if (isThenable(merged2)) {
12744
+ return merged2.then((merged3) => {
12745
+ return merged3.resolve();
12755
12746
  });
12756
- } else {
12757
- return merged.resolve();
12758
12747
  }
12748
+ return merged2.resolve();
12749
+ });
12750
+ }
12751
+ const merged = globalConfig.merge(this.resolvers, override);
12752
+ if (isThenable(merged)) {
12753
+ return merged.then((merged2) => {
12754
+ return merged2.resolve();
12759
12755
  });
12760
- } else {
12761
- const merged = globalConfig.merge(this.resolvers, override);
12762
- if (isThenable(merged)) {
12763
- return merged.then((merged2) => {
12764
- return merged2.resolve();
12765
- });
12766
- } else {
12767
- return merged.resolve();
12768
- }
12769
12756
  }
12757
+ return merged.resolve();
12770
12758
  }
12771
12759
  }
12772
12760
 
@@ -12853,7 +12841,7 @@ class EventHandler {
12853
12841
  }
12854
12842
 
12855
12843
  const name = "html-validate";
12856
- const version = "11.5.3";
12844
+ const version = "11.5.4";
12857
12845
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
12858
12846
 
12859
12847
  function freeze(src) {
@@ -12891,7 +12879,7 @@ class Reporter {
12891
12879
  for (const report of reports) {
12892
12880
  for (const result of report.results) {
12893
12881
  const key = result.filePath;
12894
- if (key in merged) {
12882
+ if (Object.hasOwn(merged, key)) {
12895
12883
  merged[key].messages = [...merged[key].messages, ...result.messages];
12896
12884
  } else {
12897
12885
  merged[key] = { ...result };
@@ -12915,7 +12903,7 @@ class Reporter {
12915
12903
  */
12916
12904
  add(options) {
12917
12905
  const { rule, message, severity, node, location, context } = options;
12918
- if (!(location.filename in this.result)) {
12906
+ if (!Object.hasOwn(this.result, location.filename)) {
12919
12907
  this.result[location.filename] = [];
12920
12908
  }
12921
12909
  const ruleUrl = rule.documentation(context)?.url;
@@ -12943,7 +12931,7 @@ class Reporter {
12943
12931
  * @internal
12944
12932
  */
12945
12933
  addManual(filename, message) {
12946
- if (!(filename in this.result)) {
12934
+ if (!Object.hasOwn(this.result, filename)) {
12947
12935
  this.result[filename] = [];
12948
12936
  }
12949
12937
  this.result[filename].push(message);
@@ -12954,6 +12942,7 @@ class Reporter {
12954
12942
  save(sources) {
12955
12943
  const report = {
12956
12944
  valid: this.isValid(),
12945
+ /* eslint-disable-next-line unicorn/prefer-object-iterable-methods -- technical debt */
12957
12946
  results: Object.keys(this.result).map((filePath) => {
12958
12947
  const messages = Array.from(this.result[filePath], freeze).toSorted(messageSort);
12959
12948
  const source = (sources ?? []).find((source2) => filePath === source2.filename);
@@ -13018,7 +13007,7 @@ function definePlugin(plugin) {
13018
13007
  return plugin;
13019
13008
  }
13020
13009
 
13021
- const regexp = /<!(?:--)?\[(.*?)](?:--)?>/g;
13010
+ const regexp = /<!(?:--)?\[(.*?)\](?:--)?>/g;
13022
13011
  function* parseConditionalComment(comment, commentLocation) {
13023
13012
  let match;
13024
13013
  while ((match = regexp.exec(comment)) !== null) {
@@ -13035,6 +13024,7 @@ function* parseConditionalComment(comment, commentLocation) {
13035
13024
 
13036
13025
  class ParserError extends Error {
13037
13026
  location;
13027
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
13038
13028
  constructor(location, message) {
13039
13029
  super(message);
13040
13030
  this.name = "ParserError";
@@ -13198,9 +13188,8 @@ class Parser {
13198
13188
  const open = !token.data[1];
13199
13189
  if (open) {
13200
13190
  return this.wouldCloseElement(token, active);
13201
- } else {
13202
- return this.closeOptionalEndTag(token, active);
13203
13191
  }
13192
+ return this.closeOptionalEndTag(token, active);
13204
13193
  }
13205
13194
  /**
13206
13195
  * Returns `true` if the element’s end tag may be omitted, either because
@@ -13552,9 +13541,8 @@ class Parser {
13552
13541
  const quote = token.data[3];
13553
13542
  if (quote) {
13554
13543
  return sliceLocation(token.location, 2, -1);
13555
- } else {
13556
- return sliceLocation(token.location, 1);
13557
13544
  }
13545
+ return sliceLocation(token.location, 1);
13558
13546
  }
13559
13547
  /**
13560
13548
  * Take attribute key and value token an returns a new location referring to
@@ -13842,13 +13830,14 @@ class PerformanceTracker {
13842
13830
  */
13843
13831
  getResult() {
13844
13832
  const events = Array.from(
13845
- this.eventData.entries(),
13833
+ this.eventData,
13846
13834
  ([event, { count, time }]) => ({ event, count, time })
13847
13835
  ).toSorted((a, b) => b.time - a.time);
13848
- const rules = Array.from(
13849
- this.ruleData.entries(),
13850
- ([rule, { count, time }]) => ({ rule, count, time })
13851
- ).toSorted((a, b) => b.time - a.time);
13836
+ const rules = Array.from(this.ruleData, ([rule, { count, time }]) => ({
13837
+ rule,
13838
+ count,
13839
+ time
13840
+ })).toSorted((a, b) => b.time - a.time);
13852
13841
  return {
13853
13842
  events,
13854
13843
  rules,
@@ -13895,9 +13884,11 @@ function dumpTree(root) {
13895
13884
  return lines;
13896
13885
  }
13897
13886
 
13898
- let blockerCounter = 1;
13887
+ const state = {
13888
+ blockerCounter: 1
13889
+ };
13899
13890
  function createBlocker() {
13900
- const id = blockerCounter++;
13891
+ const id = state.blockerCounter++;
13901
13892
  return id;
13902
13893
  }
13903
13894
 
@@ -14033,9 +14024,8 @@ class Engine {
14033
14024
  const [, options] = ruleData;
14034
14025
  const rule = this.instantiateRule(ruleId, options);
14035
14026
  return rule.documentation(context);
14036
- } else {
14037
- return null;
14038
14027
  }
14028
+ return null;
14039
14029
  }
14040
14030
  /**
14041
14031
  * Create a new parser instance with the current configuration.
@@ -14164,7 +14154,8 @@ class Engine {
14164
14154
  initRules(config) {
14165
14155
  const availableRules = {};
14166
14156
  for (const plugin of config.getPlugins()) {
14167
- for (const [name, rule] of Object.entries(plugin.rules ?? {})) {
14157
+ const entries = Object.entries(plugin.rules ?? {});
14158
+ for (const [name, rule] of entries) {
14168
14159
  if (!rule) {
14169
14160
  continue;
14170
14161
  }
@@ -14192,7 +14183,7 @@ class Engine {
14192
14183
  */
14193
14184
  setupRules(config, parser) {
14194
14185
  const rules = {};
14195
- for (const [ruleId, [severity, options]] of config.getRules().entries()) {
14186
+ for (const [ruleId, [severity, options]] of config.getRules()) {
14196
14187
  rules[ruleId] = this.loadRule(ruleId, config, severity, options, parser, this.report);
14197
14188
  }
14198
14189
  return rules;
@@ -14216,9 +14207,8 @@ class Engine {
14216
14207
  if (this.availableRules[name]) {
14217
14208
  const RuleConstructor = this.availableRules[name];
14218
14209
  return new RuleConstructor(options);
14219
- } else {
14220
- return this.missingRule(name);
14221
14210
  }
14211
+ return this.missingRule(name);
14222
14212
  }
14223
14213
  missingRule(name) {
14224
14214
  return new class MissingRule extends Rule {
@@ -14314,34 +14304,30 @@ function getTransformerFunction(resolvers, name, plugins) {
14314
14304
  validateTransformer(transformer2);
14315
14305
  return transformer2;
14316
14306
  });
14317
- } else {
14318
- validateTransformer(transformer);
14319
- return transformer;
14320
14307
  }
14308
+ validateTransformer(transformer);
14309
+ return transformer;
14321
14310
  } catch (err) {
14322
14311
  if (err instanceof ConfigError) {
14323
14312
  throw new ConfigError(`Failed to load transformer "${name}": ${err.message}`, err);
14324
- } else {
14325
- throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
14326
14313
  }
14314
+ throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
14327
14315
  }
14328
14316
  }
14329
14317
  function getCachedTransformerFunction(cache, resolvers, name, plugins) {
14330
14318
  const cached = cache.get(name);
14331
14319
  if (cached) {
14332
14320
  return cached;
14333
- } else {
14334
- const transformer = getTransformerFunction(resolvers, name, plugins);
14335
- if (isThenable(transformer)) {
14336
- return transformer.then((transformer2) => {
14337
- cache.set(name, transformer2);
14338
- return transformer2;
14339
- });
14340
- } else {
14341
- cache.set(name, transformer);
14342
- return transformer;
14343
- }
14344
14321
  }
14322
+ const transformer = getTransformerFunction(resolvers, name, plugins);
14323
+ if (isThenable(transformer)) {
14324
+ return transformer.then((transformer2) => {
14325
+ cache.set(name, transformer2);
14326
+ return transformer2;
14327
+ });
14328
+ }
14329
+ cache.set(name, transformer);
14330
+ return transformer;
14345
14331
  }
14346
14332
 
14347
14333
  function isIterable(value) {
@@ -14357,6 +14343,9 @@ const asyncInSyncTransformError = "Cannot use async transformer from sync functi
14357
14343
  async function transformSource(resolvers, config, source, filename) {
14358
14344
  const { cache } = config;
14359
14345
  const transformer = config.findTransformer(filename ?? source.filename);
14346
+ if (!transformer) {
14347
+ return [source];
14348
+ }
14360
14349
  const context = {
14361
14350
  hasChain(filename2) {
14362
14351
  return config.canTransform(filename2);
@@ -14365,9 +14354,6 @@ async function transformSource(resolvers, config, source, filename) {
14365
14354
  return transformSource(resolvers, config, source2, filename2);
14366
14355
  }
14367
14356
  };
14368
- if (!transformer) {
14369
- return [source];
14370
- }
14371
14357
  const fn = transformer.kind === "import" ? await getCachedTransformerFunction(cache, resolvers, transformer.name, config.getPlugins()) : transformer.function;
14372
14358
  const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14373
14359
  try {
@@ -14386,6 +14372,9 @@ async function transformSource(resolvers, config, source, filename) {
14386
14372
  function transformSourceSync(resolvers, config, source, filename) {
14387
14373
  const { cache } = config;
14388
14374
  const transformer = config.findTransformer(filename ?? source.filename);
14375
+ if (!transformer) {
14376
+ return [source];
14377
+ }
14389
14378
  const context = {
14390
14379
  hasChain(filename2) {
14391
14380
  return config.canTransform(filename2);
@@ -14394,14 +14383,11 @@ function transformSourceSync(resolvers, config, source, filename) {
14394
14383
  return transformSourceSync(resolvers, config, source2, filename2);
14395
14384
  }
14396
14385
  };
14397
- if (!transformer) {
14398
- return [source];
14399
- }
14400
14386
  const fn = transformer.kind === "import" ? getCachedTransformerFunction(cache, resolvers, transformer.name, config.getPlugins()) : transformer.function;
14401
- const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14402
14387
  if (isThenable(fn)) {
14403
14388
  throw new UserError(asyncInSyncTransformError);
14404
14389
  }
14390
+ const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14405
14391
  try {
14406
14392
  const result = fn.call(context, source);
14407
14393
  if (isThenable(result)) {
@@ -14503,7 +14489,7 @@ function checkstyleFormatter(results) {
14503
14489
  `;
14504
14490
  for (const message of messages) {
14505
14491
  const ruleId = xmlescape(`htmlvalidate.rules.${message.ruleId}`);
14506
- output += " ";
14492
+ output += " ".repeat(4);
14507
14493
  output += [
14508
14494
  `<error line="${xmlescape(message.line)}"`,
14509
14495
  `column="${xmlescape(message.column)}"`,
@@ -14590,9 +14576,8 @@ function codeFrameColumns(rawLines, loc) {
14590
14576
  ].join("");
14591
14577
  }
14592
14578
  return [">", gutter, line.length > 0 ? ` ${line}` : "", markerLine].join("");
14593
- } else {
14594
- return [" ", gutter, line.length > 0 ? ` ${line}` : ""].join("");
14595
14579
  }
14580
+ return [" ", gutter, line.length > 0 ? ` ${line}` : ""].join("");
14596
14581
  }).join("\n");
14597
14582
  }
14598
14583