html-validate 11.5.2 → 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 +454 -448
  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 +454 -448
  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 +22 -11
  56. package/dist/types/index.d.ts +24 -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);
@@ -2054,25 +2048,25 @@ function lastChild(node) {
2054
2048
  return node.nextSibling === null;
2055
2049
  }
2056
2050
 
2057
- const cache = {};
2051
+ const cache$1 = {};
2058
2052
  function getNthChild(node) {
2059
2053
  if (!node.parent) {
2060
2054
  return -1;
2061
2055
  }
2062
- if (!cache[node.unique]) {
2056
+ if (!cache$1[node.unique]) {
2063
2057
  const parent = node.parent;
2064
2058
  const index = parent.childElements.findIndex((cur) => {
2065
2059
  return cur.unique === node.unique;
2066
2060
  });
2067
- cache[node.unique] = index + 1;
2061
+ cache$1[node.unique] = index + 1;
2068
2062
  }
2069
- return cache[node.unique];
2063
+ return cache$1[node.unique];
2070
2064
  }
2071
2065
  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
 
@@ -2480,9 +2472,16 @@ function generateIdSelector(id) {
2480
2472
  return /^\d/.test(escaped) ? `[id="${escaped}"]` : `#${escaped}`;
2481
2473
  }
2482
2474
 
2475
+ const cache = /* @__PURE__ */ new Map();
2483
2476
  function parseSelector(selector) {
2477
+ const cached = cache.get(selector);
2478
+ if (cached) {
2479
+ return cached;
2480
+ }
2484
2481
  const compounds = getCompounds(selector);
2485
- return ComplexSelector.fromCompounds(compounds);
2482
+ const result = ComplexSelector.fromCompounds(compounds);
2483
+ cache.set(selector, result);
2484
+ return result;
2486
2485
  }
2487
2486
 
2488
2487
  const TEXT_NODE_NAME = "#text";
@@ -2627,10 +2626,10 @@ class HtmlElement extends DOMNode {
2627
2626
  */
2628
2627
  static fromTokens(startToken, endToken, parent, metaTable, namespace = "") {
2629
2628
  const name = startToken.data[2];
2630
- const tagName = namespace ? `${namespace}:${name}` : name;
2631
2629
  if (!name) {
2632
2630
  throw new Error("tagName cannot be empty");
2633
2631
  }
2632
+ const tagName = namespace ? `${namespace}:${name}` : name;
2634
2633
  const meta = metaTable ? metaTable.getMetaFor(tagName) : null;
2635
2634
  const open = startToken.data[1] !== "/";
2636
2635
  const closed = isClosed(endToken, meta);
@@ -2652,9 +2651,8 @@ class HtmlElement extends DOMNode {
2652
2651
  get annotatedName() {
2653
2652
  if (this.annotation) {
2654
2653
  return this.annotation;
2655
- } else {
2656
- return `<${this.tagName}>`;
2657
2654
  }
2655
+ return `<${this.tagName}>`;
2658
2656
  }
2659
2657
  /**
2660
2658
  * Get list of IDs referenced by `aria-labelledby`.
@@ -2873,13 +2871,13 @@ class HtmlElement extends DOMNode {
2873
2871
  if (!tabindex) {
2874
2872
  return this.cacheSet(TABINDEX, null);
2875
2873
  }
2876
- if (tabindex.value === null) {
2874
+ if (tabindex.value === null || tabindex.value === "") {
2877
2875
  return this.cacheSet(TABINDEX, null);
2878
2876
  }
2879
2877
  if (tabindex.value instanceof DynamicValue) {
2880
2878
  return this.cacheSet(TABINDEX, 0);
2881
2879
  }
2882
- const parsed = Number.parseInt(tabindex.value, 10);
2880
+ const parsed = Math.trunc(Number(tabindex.value));
2883
2881
  if (Number.isNaN(parsed)) {
2884
2882
  return this.cacheSet(TABINDEX, null);
2885
2883
  }
@@ -2895,11 +2893,11 @@ class HtmlElement extends DOMNode {
2895
2893
  const tagName = this.tagName.toLowerCase();
2896
2894
  if (tagName === "script") {
2897
2895
  return "script";
2898
- } else if (tagName === "style") {
2896
+ }
2897
+ if (tagName === "style") {
2899
2898
  return "css";
2900
- } else {
2901
- return "text";
2902
2899
  }
2900
+ return "text";
2903
2901
  }
2904
2902
  /**
2905
2903
  * Get a list of all attributes on this node.
@@ -2911,16 +2909,15 @@ class HtmlElement extends DOMNode {
2911
2909
  }
2912
2910
  hasAttribute(key) {
2913
2911
  key = key.toLowerCase();
2914
- return key in this.attr;
2912
+ return Object.hasOwn(this.attr, key);
2915
2913
  }
2916
2914
  getAttribute(key, all = false) {
2917
2915
  key = key.toLowerCase();
2918
- if (key in this.attr) {
2916
+ if (Object.hasOwn(this.attr, key)) {
2919
2917
  const matches = this.attr[key];
2920
2918
  return all ? matches : matches[0];
2921
- } else {
2922
- return all ? [] : null;
2923
2919
  }
2920
+ return all ? [] : null;
2924
2921
  }
2925
2922
  /**
2926
2923
  * Get attribute value.
@@ -2938,17 +2935,13 @@ class HtmlElement extends DOMNode {
2938
2935
  const attr = this.getAttribute(key);
2939
2936
  if (attr) {
2940
2937
  return attr.value !== null ? attr.value.toString() : null;
2941
- } else {
2942
- return null;
2943
2938
  }
2939
+ return null;
2944
2940
  }
2945
- /**
2946
- * Add text as a child node to this element.
2947
- *
2948
- * @param text - Text to add.
2949
- * @param location - Source code location of this text.
2950
- */
2951
2941
  appendText(text, location) {
2942
+ if (typeof text === "object" && "dynamic" in text) {
2943
+ text = new DynamicValue(text.dynamic);
2944
+ }
2952
2945
  this.childNodes.push(new TextNode(text, location));
2953
2946
  }
2954
2947
  /**
@@ -3001,23 +2994,30 @@ class HtmlElement extends DOMNode {
3001
2994
  return i <= this.siblings.length - 2 ? this.siblings[i + 1] : null;
3002
2995
  }
3003
2996
  getElementsByTagName(tagName) {
3004
- return this.childElements.reduce((matches, node) => {
3005
- return matches.concat(node.is(tagName) ? [node] : [], node.getElementsByTagName(tagName));
3006
- }, []);
2997
+ const matches = [];
2998
+ this.collectByTagName(tagName, matches);
2999
+ return matches;
3000
+ }
3001
+ collectByTagName(tagName, matches) {
3002
+ for (const node of this.childElements) {
3003
+ if (node.is(tagName)) {
3004
+ matches.push(node);
3005
+ }
3006
+ node.collectByTagName(tagName, matches);
3007
+ }
3007
3008
  }
3008
3009
  querySelector(selector) {
3009
3010
  const it = this.querySelectorImpl(selector);
3010
3011
  const next = it.next();
3011
3012
  if (next.done) {
3012
3013
  return null;
3013
- } else {
3014
- return next.value;
3015
3014
  }
3015
+ return next.value;
3016
3016
  }
3017
3017
  querySelectorAll(selector) {
3018
3018
  const it = this.querySelectorImpl(selector);
3019
3019
  const unique = new Set(it);
3020
- return Array.from(unique.values());
3020
+ return Array.from(unique);
3021
3021
  }
3022
3022
  *querySelectorImpl(selectorList) {
3023
3023
  if (!selectorList) {
@@ -3038,9 +3038,8 @@ class HtmlElement extends DOMNode {
3038
3038
  function visit(node) {
3039
3039
  if (callback(node)) {
3040
3040
  return true;
3041
- } else {
3042
- return node.childElements.some(visit);
3043
3041
  }
3042
+ return node.childElements.some(visit);
3044
3043
  }
3045
3044
  }
3046
3045
  /**
@@ -3215,7 +3214,7 @@ class Validator {
3215
3214
  return true;
3216
3215
  }
3217
3216
  return rules.some((rule) => {
3218
- return Validator.validatePermittedRule(node, rule);
3217
+ return this.validatePermittedRule(node, rule);
3219
3218
  });
3220
3219
  }
3221
3220
  /**
@@ -3242,9 +3241,7 @@ class Validator {
3242
3241
  const [, category, quantifier] = /^(@?.*?)([*?]?)$/.exec(rule);
3243
3242
  const limit = category && quantifier && parseQuantifier(quantifier);
3244
3243
  if (limit) {
3245
- const siblings = children.filter(
3246
- (cur) => Validator.validatePermittedCategory(cur, rule, true)
3247
- );
3244
+ const siblings = children.filter((cur) => this.validatePermittedCategory(cur, rule, true));
3248
3245
  if (siblings.length > limit) {
3249
3246
  for (const child of siblings.slice(limit)) {
3250
3247
  cb(child, category);
@@ -3275,12 +3272,12 @@ class Validator {
3275
3272
  let prev = null;
3276
3273
  for (const node of children) {
3277
3274
  const old = i;
3278
- while (rules[i] && !Validator.validatePermittedCategory(node, rules[i], true)) {
3275
+ while (rules[i] && !this.validatePermittedCategory(node, rules[i], true)) {
3279
3276
  i++;
3280
3277
  }
3281
3278
  if (i >= rules.length) {
3282
- const orderSpecified = rules.find(
3283
- (cur) => Validator.validatePermittedCategory(node, cur, true)
3279
+ const orderSpecified = rules.some(
3280
+ (cur) => this.validatePermittedCategory(node, cur, true)
3284
3281
  );
3285
3282
  if (orderSpecified) {
3286
3283
  cb(node, prev);
@@ -3319,7 +3316,7 @@ class Validator {
3319
3316
  }
3320
3317
  return rules.filter((tagName) => {
3321
3318
  const haveMatchingChild = node.childElements.some(
3322
- (child) => Validator.validatePermittedCategory(child, tagName, false)
3319
+ (child) => this.validatePermittedCategory(child, tagName, false)
3323
3320
  );
3324
3321
  return !haveMatchingChild;
3325
3322
  });
@@ -3366,36 +3363,35 @@ class Validator {
3366
3363
  return rule.enum.some((entry) => {
3367
3364
  if (typeof entry === "string") {
3368
3365
  return caseInsensitiveValue === entry;
3369
- } else if (entry instanceof RegExp) {
3366
+ }
3367
+ if (entry instanceof RegExp) {
3370
3368
  return entry.test(value);
3371
- } else if (entry.pattern instanceof RegExp) {
3369
+ }
3370
+ if (entry.pattern instanceof RegExp) {
3372
3371
  return entry.pattern.test(value);
3373
- } else {
3374
- throw new TypeError("RegExp was not precompiled when it should have been");
3375
3372
  }
3373
+ throw new TypeError("RegExp was not precompiled when it should have been");
3376
3374
  });
3377
3375
  }
3378
3376
  static validatePermittedRule(node, rule, isExclude = false) {
3379
3377
  if (typeof rule === "string") {
3380
- return Validator.validatePermittedCategory(node, rule, !isExclude);
3381
- } else if (Array.isArray(rule)) {
3378
+ return this.validatePermittedCategory(node, rule, !isExclude);
3379
+ }
3380
+ if (Array.isArray(rule)) {
3382
3381
  return rule.every((inner) => {
3383
- return Validator.validatePermittedRule(node, inner, isExclude);
3382
+ return this.validatePermittedRule(node, inner, isExclude);
3384
3383
  });
3385
- } else {
3386
- validateKeys(rule);
3387
- if (rule.exclude) {
3388
- if (Array.isArray(rule.exclude)) {
3389
- return !rule.exclude.some((inner) => {
3390
- return Validator.validatePermittedRule(node, inner, true);
3391
- });
3392
- } else {
3393
- return !Validator.validatePermittedRule(node, rule.exclude, true);
3394
- }
3395
- } else {
3396
- 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
+ });
3397
3391
  }
3392
+ return !this.validatePermittedRule(node, rule.exclude, true);
3398
3393
  }
3394
+ return true;
3399
3395
  }
3400
3396
  /**
3401
3397
  * Validate node against a content category.
@@ -3411,7 +3407,7 @@ class Validator {
3411
3407
  */
3412
3408
  /* eslint-disable-next-line complexity -- rule does not like switch */
3413
3409
  static validatePermittedCategory(node, category, defaultMatch) {
3414
- const [, rawCategory] = /^(@?.*?)([*?]?)$/.exec(category);
3410
+ const [, rawCategory] = /^(@?.*?)[*?]?$/.exec(category);
3415
3411
  if (!rawCategory.startsWith("@")) {
3416
3412
  return node.matches(rawCategory);
3417
3413
  }
@@ -3444,10 +3440,11 @@ class Validator {
3444
3440
  }
3445
3441
  function validateKeys(rule) {
3446
3442
  for (const key of Object.keys(rule)) {
3447
- if (!allowedKeys.has(key)) {
3448
- const str = JSON.stringify(rule);
3449
- throw new Error(`Permitted rule "${str}" contains unknown property "${key}"`);
3443
+ if (allowedKeys.has(key)) {
3444
+ continue;
3450
3445
  }
3446
+ const str = JSON.stringify(rule);
3447
+ throw new Error(`Permitted rule "${str}" contains unknown property "${key}"`);
3451
3448
  }
3452
3449
  }
3453
3450
  function parseQuantifier(quantifier) {
@@ -3514,9 +3511,8 @@ function ariaNaming(element) {
3514
3511
  if (role) {
3515
3512
  if (role instanceof DynamicValue) {
3516
3513
  return element.cacheSet(cacheKey, defaultValue);
3517
- } else {
3518
- return element.cacheSet(cacheKey, byRole(role));
3519
3514
  }
3515
+ return element.cacheSet(cacheKey, byRole(role));
3520
3516
  }
3521
3517
  const meta = element.meta;
3522
3518
  if (!meta) {
@@ -3701,9 +3697,8 @@ function isPresentation(node) {
3701
3697
  const role = node.getAttribute("role");
3702
3698
  if (role && (role.value === "presentation" || role.value === "none")) {
3703
3699
  return node.cacheSet(ROLE_PRESENTATION_CACHE, true);
3704
- } else {
3705
- return node.cacheSet(ROLE_PRESENTATION_CACHE, false);
3706
3700
  }
3701
+ return node.cacheSet(ROLE_PRESENTATION_CACHE, false);
3707
3702
  }
3708
3703
 
3709
3704
  const cachePrefix = classifyNodeText.name;
@@ -3721,13 +3716,14 @@ function getCachekey(options) {
3721
3716
  const { accessible = false, ignoreHiddenRoot = false } = options;
3722
3717
  if (accessible && ignoreHiddenRoot) {
3723
3718
  return IGNORE_HIDDEN_ROOT_A11Y_CACHE_KEY;
3724
- } else if (ignoreHiddenRoot) {
3719
+ }
3720
+ if (ignoreHiddenRoot) {
3725
3721
  return IGNORE_HIDDEN_ROOT_HTML_CACHE_KEY;
3726
- } else if (accessible) {
3722
+ }
3723
+ if (accessible) {
3727
3724
  return A11Y_CACHE_KEY;
3728
- } else {
3729
- return HTML_CACHE_KEY;
3730
3725
  }
3726
+ return HTML_CACHE_KEY;
3731
3727
  }
3732
3728
  function isSpecialEmpty(node) {
3733
3729
  return node.is("select") || node.is("textarea");
@@ -3759,7 +3755,7 @@ function classifyNodeText(node, options = {}) {
3759
3755
  }
3760
3756
  function findTextNodes(node, options) {
3761
3757
  const { accessible = false } = options;
3762
- let text = [];
3758
+ const text = [];
3763
3759
  for (const child of node.childNodes) {
3764
3760
  if (isTextNode(child)) {
3765
3761
  text.push(child);
@@ -3770,7 +3766,7 @@ function findTextNodes(node, options) {
3770
3766
  if (accessible && isAriaHidden(child, true).bySelf) {
3771
3767
  continue;
3772
3768
  }
3773
- text = text.concat(findTextNodes(child, options));
3769
+ text.push(...findTextNodes(child, options));
3774
3770
  }
3775
3771
  }
3776
3772
  return text;
@@ -3831,14 +3827,17 @@ function format(value, quote = false) {
3831
3827
  return String(value);
3832
3828
  }
3833
3829
  function interpolate(text, data) {
3834
- return text.replaceAll(/{{\s*([^\s{}]+)\s*}}/g, (match, key) => {
3830
+ return text.replaceAll(/\{\{\s*([^\s{}]+)\s*\}\}/g, (match, key) => {
3835
3831
  return data[key] !== void 0 ? format(data[key]) : match;
3836
3832
  });
3837
3833
  }
3838
3834
 
3839
- const ajv$1 = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
3840
- ajv$1.addMetaSchema(ajvSchemaDraft);
3841
- 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
+ })();
3842
3841
  function getSchemaValidator(ruleId, properties) {
3843
3842
  const $id = `rule/${ruleId}`;
3844
3843
  const cached = ajv$1.getSchema($id);
@@ -3859,10 +3858,9 @@ function isErrorDescriptor(value) {
3859
3858
  function unpackErrorDescriptor(value) {
3860
3859
  if (isErrorDescriptor(value)) {
3861
3860
  return value[0];
3862
- } else {
3863
- const [node, message, location, context] = value;
3864
- return { node, message, location, context };
3865
3861
  }
3862
+ const [node, message, location, context] = value;
3863
+ return { node, message, location, context };
3866
3864
  }
3867
3865
  class Rule {
3868
3866
  reporter;
@@ -4068,17 +4066,18 @@ class Rule {
4068
4066
  const callback = args.pop();
4069
4067
  const filter = args.pop() ?? (() => true);
4070
4068
  return this.parser.on(event, (_event, data) => {
4071
- if (this.isEnabled() && filter(data)) {
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);
4081
- }
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);
4082
4081
  }
4083
4082
  });
4084
4083
  }
@@ -4148,7 +4147,7 @@ class Rule {
4148
4147
  * @public
4149
4148
  * @virtual
4150
4149
  * @param context - Error context given by a reported error.
4151
- * @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
4152
4151
  * additional documentation is available.
4153
4152
  */
4154
4153
  documentation(_context) {
@@ -4187,7 +4186,7 @@ function parseAllow(value) {
4187
4186
  };
4188
4187
  }
4189
4188
  function matchList(value, list) {
4190
- if (list.include && !list.include.some((it) => it.test(value))) {
4189
+ if (list.include?.every((it) => !it.test(value))) {
4191
4190
  return false;
4192
4191
  }
4193
4192
  if (list.exclude?.some((it) => it.test(value))) {
@@ -4272,10 +4271,10 @@ class AllowedLinks extends Rule {
4272
4271
  return Boolean(attr && attr === key);
4273
4272
  }
4274
4273
  getStyle(value) {
4275
- if (/^([a-z]+:)?\/\//g.test(value)) {
4274
+ if (/^(?:[a-z]+:)?\/\//.test(value)) {
4276
4275
  return "external" /* EXTERNAL */;
4277
4276
  }
4278
- switch (value[0]) {
4277
+ switch (value.at(0)) {
4279
4278
  /* /foo/bar */
4280
4279
  case "/":
4281
4280
  return "absolute" /* ABSOLUTE */;
@@ -4294,7 +4293,8 @@ class AllowedLinks extends Rule {
4294
4293
  const { allowAbsolute } = this;
4295
4294
  if (allowAbsolute === true) {
4296
4295
  return;
4297
- } else if (allowAbsolute === false) {
4296
+ }
4297
+ if (allowAbsolute === false) {
4298
4298
  this.report(
4299
4299
  event.target,
4300
4300
  "Link destination must not be absolute url",
@@ -4314,7 +4314,8 @@ class AllowedLinks extends Rule {
4314
4314
  const { allowExternal } = this;
4315
4315
  if (allowExternal === true) {
4316
4316
  return;
4317
- } else if (allowExternal === false) {
4317
+ }
4318
+ if (allowExternal === false) {
4318
4319
  this.report(
4319
4320
  event.target,
4320
4321
  "Link destination must not be external url",
@@ -4334,7 +4335,8 @@ class AllowedLinks extends Rule {
4334
4335
  const { allowRelative } = this;
4335
4336
  if (allowRelative === true) {
4336
4337
  return false;
4337
- } else if (allowRelative === false) {
4338
+ }
4339
+ if (allowRelative === false) {
4338
4340
  this.report(
4339
4341
  event.target,
4340
4342
  "Link destination must not be relative url",
@@ -4342,7 +4344,8 @@ class AllowedLinks extends Rule {
4342
4344
  style
4343
4345
  );
4344
4346
  return true;
4345
- } else if (!matchList(target, allowRelative)) {
4347
+ }
4348
+ if (!matchList(target, allowRelative)) {
4346
4349
  this.report(
4347
4350
  event.target,
4348
4351
  "Relative link to this destination is not allowed by current configuration",
@@ -4357,7 +4360,8 @@ class AllowedLinks extends Rule {
4357
4360
  const { allowBase } = this.options;
4358
4361
  if (this.handleRelativePath(target, event, style)) {
4359
4362
  return;
4360
- } else if (!allowBase) {
4363
+ }
4364
+ if (!allowBase) {
4361
4365
  this.report(
4362
4366
  event.target,
4363
4367
  "Relative links must be relative to current folder",
@@ -4575,12 +4579,11 @@ class AriaLabelMisuse extends Rule {
4575
4579
  ].join("\n"),
4576
4580
  url
4577
4581
  };
4578
- } else {
4579
- return {
4580
- description: [`\`${context.attr}\` can only be used on:`, "", ...lines].join("\n"),
4581
- url
4582
- };
4583
4582
  }
4583
+ return {
4584
+ description: [`\`${context.attr}\` can only be used on:`, "", ...lines].join("\n"),
4585
+ url
4586
+ };
4584
4587
  }
4585
4588
  setup() {
4586
4589
  this.on("dom:ready", (event) => {
@@ -4638,6 +4641,7 @@ class AriaLabelMisuse extends Rule {
4638
4641
  }
4639
4642
 
4640
4643
  class ConfigError extends UserError {
4644
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
4641
4645
  constructor(message, nested) {
4642
4646
  super(message, nested);
4643
4647
  this.name = "ConfigError";
@@ -4758,9 +4762,8 @@ class AttrCase extends Rule {
4758
4762
  isIgnored(node) {
4759
4763
  if (this.options.ignoreForeign) {
4760
4764
  return Boolean(node.meta?.foreign);
4761
- } else {
4762
- return false;
4763
4765
  }
4766
+ return false;
4764
4767
  }
4765
4768
  }
4766
4769
 
@@ -4807,14 +4810,21 @@ class Context {
4807
4810
  return JSON.stringify(this.string.length > n ? `${this.string.slice(0, 10)}...` : this.string);
4808
4811
  }
4809
4812
  consume(n, state) {
4810
- let consumed = this.string.slice(0, n);
4811
- let offset;
4812
- while ((offset = consumed.indexOf("\n")) >= 0) {
4813
- this.line++;
4814
- this.column = 1;
4815
- consumed = consumed.slice(offset + 1);
4816
- }
4817
- this.column += consumed.length;
4813
+ let lastNewline = -1;
4814
+ let newlines = 0;
4815
+ for (let i = 0; i < n; i++) {
4816
+ if (this.string[i] !== "\n") {
4817
+ continue;
4818
+ }
4819
+ newlines++;
4820
+ lastNewline = i;
4821
+ }
4822
+ if (newlines > 0) {
4823
+ this.line += newlines;
4824
+ this.column = n - lastNewline;
4825
+ } else {
4826
+ this.column += n;
4827
+ }
4818
4828
  this.offset += n;
4819
4829
  this.string = this.string.slice(n);
4820
4830
  this.state = state;
@@ -4869,28 +4879,29 @@ const MATCH_DOCTYPE_CLOSE = /^>/;
4869
4879
  const MATCH_XML_TAG = /^<\?xml.*?\?>\s+/;
4870
4880
  const MATCH_TAG_OPEN = /^<(\/?)([\w:\-]+)/;
4871
4881
  const MATCH_TAG_CLOSE = /^\/?>/;
4872
- const MATCH_TEXT = /^[^]*?(?=(?:[\t ]*(?:\r\n|\r|\n)|<[^ ]|$))/;
4882
+ const MATCH_TEXT = /^[\s\S]*?(?=[\t ]*(?:\r\n|\r|\n)|<[^ ]|$)/;
4873
4883
  const MATCH_TEMPLATING = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)/s;
4874
- const MATCH_TAG_LOOKAHEAD = /^[^]*?(?=<|$)/;
4884
+ const MATCH_TAG_LOOKAHEAD = /^[\s\S]*?(?=<|$)/;
4875
4885
  const MATCH_ATTR_START = /^([^\t\n\f\r "'/<=>]+)/;
4876
- const MATCH_ATTR_SINGLE = /^(\s*=\s*)'([^']*?)(')/;
4877
- const MATCH_ATTR_DOUBLE = /^(\s*=\s*)"([^"]*?)(")/;
4886
+ const MATCH_ATTR_SINGLE = /^(\s*=\s*)'([^']*)(')/;
4887
+ const MATCH_ATTR_DOUBLE = /^(\s*=\s*)"([^"]*)(")/;
4878
4888
  const MATCH_ATTR_UNQUOTED = /^(\s*=\s*)([^\t\n\f\r "'<>][^\t\n\f\r <>]*)/;
4879
4889
  const MATCH_CDATA_BEGIN = /^<!\[CDATA\[/;
4880
- const MATCH_CDATA_END = /^[^]*?]]>/;
4881
- const MATCH_SCRIPT_DATA = /^[^]*?(?=<\/script)/;
4890
+ const MATCH_CDATA_END = /^[\s\S]*?\]\]>/;
4891
+ const MATCH_SCRIPT_DATA = /^[\s\S]*?(?=<\/script)/;
4882
4892
  const MATCH_SCRIPT_END = /^<(\/)(script)/;
4883
- const MATCH_STYLE_DATA = /^[^]*?(?=<\/style)/;
4893
+ const MATCH_STYLE_DATA = /^[\s\S]*?(?=<\/style)/;
4884
4894
  const MATCH_STYLE_END = /^<(\/)(style)/;
4885
- const MATCH_TEXTAREA_DATA = /^[^]*?(?=<\/textarea)/;
4895
+ const MATCH_TEXTAREA_DATA = /^[\s\S]*?(?=<\/textarea)/;
4886
4896
  const MATCH_TEXTAREA_END = /^<(\/)(textarea)/;
4887
- const MATCH_TITLE_DATA = /^[^]*?(?=<\/title)/;
4897
+ const MATCH_TITLE_DATA = /^[\s\S]*?(?=<\/title)/;
4888
4898
  const MATCH_TITLE_END = /^<(\/)(title)/;
4889
- const MATCH_DIRECTIVE = /^(<!--\s*\[?)(html-validate-)([\da-z-]+)(\s*)(.*?)(]?\s*-->)/;
4890
- const MATCH_COMMENT = /^<!--([^]*?)-->/;
4891
- const MATCH_CONDITIONAL = /^<!\[([^\]]*?)]>/;
4899
+ const MATCH_DIRECTIVE = /^(<!--\s*\[?)(html-validate-)([\da-z-]+)(\s*)(.*?)(\]?\s*-->)/;
4900
+ const MATCH_COMMENT = /^<!--([\s\S]*?)-->/;
4901
+ const MATCH_CONDITIONAL = /^<!\[([^\]]*)\]>/;
4892
4902
  class InvalidTokenError extends Error {
4893
4903
  location;
4904
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
4894
4905
  constructor(location, message) {
4895
4906
  super(message);
4896
4907
  this.name = "InvalidTokenError";
@@ -4974,9 +4985,8 @@ class Lexer {
4974
4985
  evalNextState(nextState, token) {
4975
4986
  if (typeof nextState === "function") {
4976
4987
  return nextState(token);
4977
- } else {
4978
- return nextState;
4979
4988
  }
4989
+ return nextState;
4980
4990
  }
4981
4991
  *match(context, tests, error) {
4982
4992
  const n = tests.length;
@@ -5063,27 +5073,26 @@ class Lexer {
5063
5073
  case ContentModel.SCRIPT:
5064
5074
  if (selfClosed) {
5065
5075
  return State.SCRIPT;
5066
- } else {
5067
- return State.TEXT;
5068
5076
  }
5077
+ return State.TEXT;
5078
+ /* <script/> (not legal but handle it anyway so the lexer doesn't choke on it) */
5069
5079
  case ContentModel.STYLE:
5070
5080
  if (selfClosed) {
5071
5081
  return State.STYLE;
5072
- } else {
5073
- return State.TEXT;
5074
5082
  }
5083
+ return State.TEXT;
5084
+ /* <style/> */
5075
5085
  case ContentModel.TEXTAREA:
5076
5086
  if (selfClosed) {
5077
5087
  return State.TEXTAREA;
5078
- } else {
5079
- return State.TEXT;
5080
5088
  }
5089
+ return State.TEXT;
5090
+ /* <textarea/> */
5081
5091
  case ContentModel.TITLE:
5082
5092
  if (selfClosed) {
5083
5093
  return State.TITLE;
5084
- } else {
5085
- return State.TEXT;
5086
5094
  }
5095
+ return State.TEXT;
5087
5096
  }
5088
5097
  }
5089
5098
  yield* this.match(
@@ -5170,7 +5179,7 @@ class Lexer {
5170
5179
  }
5171
5180
  }
5172
5181
 
5173
- const whitespace = /(\s+)/;
5182
+ const whitespace = /\s+/;
5174
5183
  class AttrDelimiter extends Rule {
5175
5184
  documentation() {
5176
5185
  return {
@@ -5202,17 +5211,15 @@ const defaults$y = {
5202
5211
  function generateRegexp(pattern) {
5203
5212
  if (Array.isArray(pattern)) {
5204
5213
  return new RegExp(`^(${pattern.join("|")})$`, "i");
5205
- } else {
5206
- return new RegExp(`^${pattern}$`, "i");
5207
5214
  }
5215
+ return new RegExp(`^${pattern}$`, "i");
5208
5216
  }
5209
5217
  function generateMessage(name, pattern) {
5210
5218
  if (Array.isArray(pattern)) {
5211
5219
  const patterns = pattern.map((it) => `/${it}/`).join(", ");
5212
5220
  return `Attribute "${name}" should match one of [${patterns}]`;
5213
- } else {
5214
- return `Attribute "${name}" should match /${pattern}/`;
5215
5221
  }
5222
+ return `Attribute "${name}" should match /${pattern}/`;
5216
5223
  }
5217
5224
  function generateDescription(name, pattern) {
5218
5225
  if (Array.isArray(pattern)) {
@@ -5221,9 +5228,8 @@ function generateDescription(name, pattern) {
5221
5228
  "",
5222
5229
  ...pattern.map((it) => `- \`/${it}/\``)
5223
5230
  ].join("\n");
5224
- } else {
5225
- return `Attribute "${name}" should match the regular expression \`/${pattern}/\``;
5226
5231
  }
5232
+ return `Attribute "${name}" should match the regular expression \`/${pattern}/\``;
5227
5233
  }
5228
5234
  class AttrPattern extends Rule {
5229
5235
  pattern;
@@ -5269,9 +5275,8 @@ class AttrPattern extends Rule {
5269
5275
  isIgnored(node) {
5270
5276
  if (this.options.ignoreForeign) {
5271
5277
  return Boolean(node.meta?.foreign);
5272
- } else {
5273
- return false;
5274
5278
  }
5279
+ return false;
5275
5280
  }
5276
5281
  }
5277
5282
 
@@ -5382,9 +5387,8 @@ class AttrQuotes extends Rule {
5382
5387
  resolveQuotemark(value, style) {
5383
5388
  if (style === "auto" /* AUTO_QUOTE */) {
5384
5389
  return value.includes('"') ? "'" : '"';
5385
- } else {
5386
- return style;
5387
5390
  }
5391
+ return style;
5388
5392
  }
5389
5393
  }
5390
5394
  function parseStyle$3(style) {
@@ -5442,11 +5446,11 @@ class AttributeAllowedValues extends Rule {
5442
5446
  const allowedList = allowed.enum.map((value2) => {
5443
5447
  if (typeof value2 === "string") {
5444
5448
  return `- \`"${value2}"\``;
5445
- } else if (value2 instanceof RegExp) {
5449
+ }
5450
+ if (value2 instanceof RegExp) {
5446
5451
  return `- \`${value2.toString()}\``;
5447
- } else {
5448
- return `- ${value2.name}`;
5449
5452
  }
5453
+ return `- ${value2.name}`;
5450
5454
  });
5451
5455
  docs.description = [
5452
5456
  `The \`<${element}>\` element does not allow the attribute \`${attribute}\` to have the value \`"${value}"\`.`,
@@ -5490,9 +5494,8 @@ class AttributeAllowedValues extends Rule {
5490
5494
  const { key, value } = attr;
5491
5495
  if (value !== null) {
5492
5496
  return `Attribute "${key}" has invalid value "${value.toString()}"`;
5493
- } else {
5494
- return `Attribute "${key}" is missing value`;
5495
5497
  }
5498
+ return `Attribute "${key}" is missing value`;
5496
5499
  }
5497
5500
  getLocation(attr) {
5498
5501
  return attr.valueLocation ?? attr.keyLocation;
@@ -5779,10 +5782,10 @@ class AutocompletePassword extends Rule {
5779
5782
  const tokens = new DOMTokenList(raw, autocomplete.valueLocation);
5780
5783
  const index = tokens.findIndex((token) => !isGroupingToken(token));
5781
5784
  const value = tokens.item(index);
5782
- const location = tokens.location(index);
5783
5785
  if (!value) {
5784
5786
  return;
5785
5787
  }
5788
+ const location = tokens.location(index);
5786
5789
  if (value === "off") {
5787
5790
  const context = { kind: "off" };
5788
5791
  this.report({
@@ -5867,9 +5870,8 @@ function parsePattern(pattern) {
5867
5870
  function toArray$2(value) {
5868
5871
  if (Array.isArray(value)) {
5869
5872
  return value;
5870
- } else {
5871
- return [value];
5872
5873
  }
5874
+ return [value];
5873
5875
  }
5874
5876
  function validateAllowedPatterns(patterns, allowedPatterns, ruleId) {
5875
5877
  const extraneous = patterns.filter(isNamedPattern).filter((p) => !allowedPatterns.has(p));
@@ -5955,7 +5957,7 @@ class ClassPattern extends BasePatternRule {
5955
5957
  });
5956
5958
  }
5957
5959
  static schema() {
5958
- return BasePatternRule.schema();
5960
+ return super.schema();
5959
5961
  }
5960
5962
  documentation(context) {
5961
5963
  return {
@@ -6036,10 +6038,10 @@ class CloseOrder extends Rule {
6036
6038
  });
6037
6039
  this.on("tag:end", (event) => {
6038
6040
  const current = event.target;
6039
- const active = event.previous;
6040
6041
  if (current) {
6041
6042
  return;
6042
6043
  }
6044
+ const active = event.previous;
6043
6045
  for (const ancestor of ancestors(active)) {
6044
6046
  if (ancestor.isRootElement() || reported.has(ancestor.unique)) {
6045
6047
  continue;
@@ -6050,13 +6052,13 @@ class CloseOrder extends Rule {
6050
6052
  });
6051
6053
  this.on("tag:end", (event) => {
6052
6054
  const current = event.target;
6053
- const active = event.previous;
6054
6055
  if (!current) {
6055
6056
  return;
6056
6057
  }
6057
6058
  if (current.voidElement) {
6058
6059
  return;
6059
6060
  }
6061
+ const active = event.previous;
6060
6062
  if (active.closed === Node.CLOSED_IMPLICIT_CLOSED) {
6061
6063
  return;
6062
6064
  }
@@ -6151,7 +6153,7 @@ class Deprecated extends Rule {
6151
6153
  text.push(context.documentation);
6152
6154
  }
6153
6155
  const doc = {
6154
- 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"),
6155
6157
  url: "https://html-validate.org/rules/deprecated.html"
6156
6158
  };
6157
6159
  return doc;
@@ -6550,7 +6552,7 @@ class ElementName extends Rule {
6550
6552
  ];
6551
6553
  }
6552
6554
  setup() {
6553
- const xmlns = /^(.+):.+$/;
6555
+ const xmlns = /^[^:]+:.+$/;
6554
6556
  this.on("tag:start", (event) => {
6555
6557
  const target = event.target;
6556
6558
  const tagName = target.tagName;
@@ -6589,13 +6591,12 @@ function isNativeTemplate(node) {
6589
6591
  function getTransparentChildren(node, transparent) {
6590
6592
  if (typeof transparent === "boolean") {
6591
6593
  return node.childElements;
6592
- } else {
6593
- return node.childElements.filter((it) => {
6594
- return transparent.some((category) => {
6595
- return Validator.validatePermittedCategory(it, category, false);
6596
- });
6597
- });
6598
6594
  }
6595
+ return node.childElements.filter((it) => {
6596
+ return transparent.some((category) => {
6597
+ return Validator.validatePermittedCategory(it, category, false);
6598
+ });
6599
+ });
6599
6600
  }
6600
6601
  function getRuleDescription$2(context) {
6601
6602
  switch (context.kind) {
@@ -6627,6 +6628,7 @@ class ElementPermittedContent extends Rule {
6627
6628
  [
6628
6629
  () => this.validatePermittedContent(node, parent),
6629
6630
  () => this.validatePermittedDescendant(node, parent)
6631
+ /* eslint-disable-next-line unicorn/no-unused-array-method-return -- technical debt, should use iterator helpers */
6630
6632
  ].some((fn) => fn());
6631
6633
  });
6632
6634
  });
@@ -6772,14 +6774,12 @@ function getRuleDescription$1(context) {
6772
6774
  const allowed = rules.filter(isCategoryOrTag).map((it) => {
6773
6775
  if (isCategory$1(it)) {
6774
6776
  return `- any ${it.slice(1)} element`;
6775
- } else {
6776
- return `- \`<${it}>\``;
6777
6777
  }
6778
+ return `- \`<${it}>\``;
6778
6779
  });
6779
6780
  return [preamble, "", "Allowed parents one of:", "", ...allowed];
6780
- } else {
6781
- return [preamble];
6782
6781
  }
6782
+ return [preamble];
6783
6783
  }
6784
6784
  function formatMessage$1(node, parent, rules) {
6785
6785
  const nodeName = node.annotatedName;
@@ -6831,7 +6831,7 @@ class ElementPermittedParent extends Rule {
6831
6831
  }
6832
6832
 
6833
6833
  function isTagnameOnly(value) {
6834
- return /^[\dA-Za-z-]+$/.test(value);
6834
+ return /^[\dA-Z-]+$/i.test(value);
6835
6835
  }
6836
6836
  function getRuleDescription(context) {
6837
6837
  const escaped = context.ancestor.map((it) => `\`${it}\``);
@@ -6894,9 +6894,8 @@ function normalizeRequired(element, attr) {
6894
6894
  default:
6895
6895
  return result;
6896
6896
  }
6897
- } else {
6898
- return required ? defaultMessage : false;
6899
6897
  }
6898
+ return required ? defaultMessage : false;
6900
6899
  }
6901
6900
  class ElementRequiredAttributes extends Rule {
6902
6901
  documentation(context) {
@@ -6978,7 +6977,8 @@ const selector = ["h1", "h2", "h3", "h4", "h5", "h6"].join(",");
6978
6977
  function hasImgAltText$1(node) {
6979
6978
  if (node.is("img")) {
6980
6979
  return hasAltText(node);
6981
- } else if (node.is("svg")) {
6980
+ }
6981
+ if (node.is("svg")) {
6982
6982
  return node.textContent.trim() !== "";
6983
6983
  }
6984
6984
  return false;
@@ -7259,21 +7259,19 @@ class FormDupName extends Rule {
7259
7259
  const existing = group.cacheGet(UNIQUE_CACHE_KEY);
7260
7260
  if (existing) {
7261
7261
  return existing;
7262
- } else {
7263
- const elements = /* @__PURE__ */ new Map();
7264
- group.cacheSet(UNIQUE_CACHE_KEY, elements);
7265
- return elements;
7266
7262
  }
7263
+ const elements = /* @__PURE__ */ new Map();
7264
+ group.cacheSet(UNIQUE_CACHE_KEY, elements);
7265
+ return elements;
7267
7266
  }
7268
7267
  getSharedElements(group) {
7269
7268
  const existing = group.cacheGet(SHARED_CACHE_KEY);
7270
7269
  if (existing) {
7271
7270
  return existing;
7272
- } else {
7273
- const elements = /* @__PURE__ */ new Map();
7274
- group.cacheSet(SHARED_CACHE_KEY, elements);
7275
- return elements;
7276
7271
  }
7272
+ const elements = /* @__PURE__ */ new Map();
7273
+ group.cacheSet(SHARED_CACHE_KEY, elements);
7274
+ return elements;
7277
7275
  }
7278
7276
  }
7279
7277
 
@@ -7287,12 +7285,11 @@ function isRelevant$5(event) {
7287
7285
  return Boolean(node.meta?.heading);
7288
7286
  }
7289
7287
  function extractLevel(node) {
7290
- const match = /^[Hh](\d)$/.exec(node.tagName);
7288
+ const match = /^H(\d)$/i.exec(node.tagName);
7291
7289
  if (match) {
7292
- return Number.parseInt(match[1], 10);
7293
- } else {
7294
- return null;
7290
+ return Math.trunc(Number(match[1]));
7295
7291
  }
7292
+ return null;
7296
7293
  }
7297
7294
  function parseMaxInitial(value) {
7298
7295
  if (value === false || value === "any") {
@@ -7302,7 +7299,7 @@ function parseMaxInitial(value) {
7302
7299
  if (!match) {
7303
7300
  return 1;
7304
7301
  }
7305
- return Number.parseInt(match[1], 10);
7302
+ return Math.trunc(Number(match[1]));
7306
7303
  }
7307
7304
  class HeadingLevel extends Rule {
7308
7305
  minInitialRank;
@@ -7569,7 +7566,7 @@ class IdPattern extends BasePatternRule {
7569
7566
  });
7570
7567
  }
7571
7568
  static schema() {
7572
- return BasePatternRule.schema();
7569
+ return super.schema();
7573
7570
  }
7574
7571
  documentation(context) {
7575
7572
  return {
@@ -7791,24 +7788,23 @@ function isHidden(node, context) {
7791
7788
  const { reference } = context;
7792
7789
  if (reference?.isSameNode(node)) {
7793
7790
  return false;
7794
- } else {
7795
- return !inAccessibilityTree(node);
7796
7791
  }
7792
+ return !inAccessibilityTree(node);
7797
7793
  }
7798
7794
  function hasImgAltText(node, context) {
7799
7795
  if (node.is("img")) {
7800
7796
  return hasAltText(node);
7801
- } else if (node.is("svg")) {
7797
+ }
7798
+ if (node.is("svg")) {
7802
7799
  return node.textContent.trim() !== "";
7803
- } else {
7804
- for (const img of node.querySelectorAll("img, svg")) {
7805
- const hasName = hasAccessibleNameImpl(img, context);
7806
- if (hasName) {
7807
- return true;
7808
- }
7800
+ }
7801
+ for (const img of node.querySelectorAll("img, svg")) {
7802
+ const hasName = hasAccessibleNameImpl(img, context);
7803
+ if (hasName) {
7804
+ return true;
7809
7805
  }
7810
- return false;
7811
7806
  }
7807
+ return false;
7812
7808
  }
7813
7809
  function hasLabel(node) {
7814
7810
  const value = node.getAttributeValue("aria-label") ?? "";
@@ -7939,7 +7935,7 @@ class InputMissingLabel extends Rule {
7939
7935
  this.report(elem, `<${elem.tagName}> element has <label> but <label> element is hidden`);
7940
7936
  return;
7941
7937
  }
7942
- if (!labels.some((label) => hasAccessibleName(root, label))) {
7938
+ if (labels.every((label) => !hasAccessibleName(root, label))) {
7943
7939
  this.report(elem, `<${elem.tagName}> element has <label> but <label> has no text`);
7944
7940
  }
7945
7941
  }
@@ -8126,12 +8122,11 @@ function parseContent(text) {
8126
8122
  const match = /^(\d+)(?:\s*;\s*url=(.*))?/i.exec(text);
8127
8123
  if (match) {
8128
8124
  return {
8129
- delay: Number.parseInt(match[1], 10),
8125
+ delay: Math.trunc(Number(match[1])),
8130
8126
  url: match[2]
8131
8127
  };
8132
- } else {
8133
- return null;
8134
8128
  }
8129
+ return null;
8135
8130
  }
8136
8131
 
8137
8132
  class MissingDoctype extends Rule {
@@ -8208,7 +8203,7 @@ class NamePattern extends BasePatternRule {
8208
8203
  });
8209
8204
  }
8210
8205
  static schema() {
8211
- return BasePatternRule.schema();
8206
+ return super.schema();
8212
8207
  }
8213
8208
  documentation(context) {
8214
8209
  return {
@@ -8391,10 +8386,10 @@ class NoDeprecatedAttr extends Rule {
8391
8386
  this.on("attr", (event) => {
8392
8387
  const node = event.target;
8393
8388
  const meta = node.meta;
8394
- const attr = event.key.toLowerCase();
8395
8389
  if (meta === null) {
8396
8390
  return;
8397
8391
  }
8392
+ const attr = event.key.toLowerCase();
8398
8393
  const metaAttribute = meta.attributes[attr];
8399
8394
  if (!metaAttribute) {
8400
8395
  return;
@@ -8428,7 +8423,7 @@ class NoDupAttr extends Rule {
8428
8423
  return;
8429
8424
  }
8430
8425
  const name = event.key.toLowerCase();
8431
- if (name in attr) {
8426
+ if (Object.hasOwn(attr, name)) {
8432
8427
  this.report(event.target, `Attribute "${name}" duplicated`, event.keyLocation);
8433
8428
  }
8434
8429
  attr[event.key] = true;
@@ -8501,10 +8496,9 @@ function getExisting(element, root) {
8501
8496
  const existing = group.cacheGet(CACHE_KEY);
8502
8497
  if (existing) {
8503
8498
  return existing;
8504
- } else {
8505
- const existing2 = /* @__PURE__ */ new Set();
8506
- return group.cacheSet(CACHE_KEY, existing2);
8507
8499
  }
8500
+ const value = /* @__PURE__ */ new Set();
8501
+ return group.cacheSet(CACHE_KEY, value);
8508
8502
  }
8509
8503
 
8510
8504
  function isRelevant$2(event) {
@@ -8775,10 +8769,11 @@ class NoMissingReferences extends Rule {
8775
8769
  }
8776
8770
  }
8777
8771
  validateSingle(document, node, attr, id) {
8778
- if (idMissing(document, id)) {
8779
- const context = { key: attr.key, value: id };
8780
- this.report(node, `Element references missing id "${id}"`, attr.valueLocation, context);
8772
+ if (!idMissing(document, id)) {
8773
+ return;
8781
8774
  }
8775
+ const context = { key: attr.key, value: id };
8776
+ this.report(node, `Element references missing id "${id}"`, attr.valueLocation, context);
8782
8777
  }
8783
8778
  validateList(document, node, attr, values) {
8784
8779
  const parsed = new DOMTokenList(values, attr.valueLocation);
@@ -8818,9 +8813,9 @@ class NoMultipleMain extends Rule {
8818
8813
  const defaults$f = {
8819
8814
  relaxed: false
8820
8815
  };
8821
- const textRegexp = /(<|&(?![\d#A-Za-z]+;))/g;
8822
- const unquotedAttrRegexp = /(["'<=>`]|&(?![\d#A-Za-z]+;))/g;
8823
- const matchTemplate = /^(<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
8816
+ const textRegexp = /(<|&(?![\d#A-Z]+;))/gi;
8817
+ const unquotedAttrRegexp = /(["'<=>`]|&(?![\d#A-Z]+;))/gi;
8818
+ const matchTemplate = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
8824
8819
  const replacementTable = {
8825
8820
  '"': "&quot;",
8826
8821
  "&": "&amp;",
@@ -9052,7 +9047,7 @@ class NoRedundantRole extends Rule {
9052
9047
  }
9053
9048
  }
9054
9049
 
9055
- const xmlns = /^(.+):.+$/;
9050
+ const xmlns = /^[^:]+:.+$/;
9056
9051
  const defaults$d = {
9057
9052
  ignoreForeign: true,
9058
9053
  ignoreXML: true
@@ -9174,11 +9169,11 @@ class NoUnknownAttributes extends Rule {
9174
9169
  this.on("attr", (event) => {
9175
9170
  const node = event.target;
9176
9171
  const meta = node.meta;
9177
- const attr = event.key.toLowerCase();
9178
9172
  if (meta === null) {
9179
9173
  return;
9180
9174
  }
9181
- if (attr in meta.attributes) {
9175
+ const attr = event.key.toLowerCase();
9176
+ if (Object.hasOwn(meta.attributes, attr)) {
9182
9177
  return;
9183
9178
  }
9184
9179
  if (isPatternAttribute(attr, meta.patternAttributes)) {
@@ -9585,7 +9580,7 @@ const defaults$7 = {
9585
9580
  include: null,
9586
9581
  exclude: null
9587
9582
  };
9588
- const crossorigin = new RegExp("^(\\w+://|//)");
9583
+ const crossorigin = /^(?:\w+:\/\/|\/\/)/;
9589
9584
  const supportSri = {
9590
9585
  link: "href",
9591
9586
  script: "src"
@@ -9798,7 +9793,10 @@ function constructRegex(characters) {
9798
9793
  return new RegExp(pattern, "g");
9799
9794
  }
9800
9795
  function getText(node) {
9801
- const match = /^(\s*)(.*)$/.exec(node.textContent);
9796
+ const match = /^(\s*)(\S.*)$/.exec(node.textContent);
9797
+ if (!match) {
9798
+ return [0, ""];
9799
+ }
9802
9800
  const [, leading, text] = match;
9803
9801
  return [leading.length, text.trimEnd()];
9804
9802
  }
@@ -9951,9 +9949,8 @@ function hasDefaultText(node) {
9951
9949
  function isNonEmptyText(node) {
9952
9950
  if (isTextNode(node)) {
9953
9951
  return node.isDynamic || node.textContent.trim() !== "";
9954
- } else {
9955
- return false;
9956
9952
  }
9953
+ return false;
9957
9954
  }
9958
9955
  function haveAccessibleText(node) {
9959
9956
  if (!inAccessibilityTree(node)) {
@@ -10088,15 +10085,14 @@ function getTextFromReference(document, id) {
10088
10085
  const ref = document.querySelector(selector);
10089
10086
  if (ref) {
10090
10087
  return ref.textContent;
10091
- } else {
10092
- return selector;
10093
10088
  }
10089
+ return selector;
10094
10090
  }
10095
10091
  function groupBy(values, callback) {
10096
10092
  const result = {};
10097
10093
  for (const value of values) {
10098
10094
  const key = callback(value);
10099
- if (key in result) {
10095
+ if (Object.hasOwn(result, key)) {
10100
10096
  result[key].push(value);
10101
10097
  } else {
10102
10098
  result[key] = [value];
@@ -10196,7 +10192,7 @@ const defaults$5 = {
10196
10192
  ignoreCase: false,
10197
10193
  requireSemicolon: true
10198
10194
  };
10199
- const regexp$1 = /&(?:[\da-z]+|#x?[\da-f]+)(;|[^\da-z]|$)/gi;
10195
+ const regexp$1 = /&(?:[\da-z]+|#x?[\da-f]+)([^\da-z]|$)/gi;
10200
10196
  const lowercaseEntities = entities$1.map((it) => it.toLowerCase());
10201
10197
  function isNumerical(entity) {
10202
10198
  return entity.startsWith("&#");
@@ -10275,9 +10271,8 @@ class UnknownCharReference extends Rule {
10275
10271
  get entities() {
10276
10272
  if (this.options.ignoreCase) {
10277
10273
  return lowercaseEntities;
10278
- } else {
10279
- return entities$1;
10280
10274
  }
10275
+ return entities$1;
10281
10276
  }
10282
10277
  findCharacterReferences(node, text, location, { isAttribute }) {
10283
10278
  const delimiter = text.search(/[#?]/);
@@ -10643,7 +10638,6 @@ class ValidAutocomplete extends Rule {
10643
10638
  }
10644
10639
  validateControlAutocomplete(node, tokens, keyLocation) {
10645
10640
  const type = node.getAttributeValue("type") ?? "text";
10646
- const mantle = type !== "hidden" ? "expectation" : "anchor";
10647
10641
  if (isDisallowedType(node, type)) {
10648
10642
  const context = {
10649
10643
  msg: 0 /* InvalidAttribute */,
@@ -10658,6 +10652,7 @@ class ValidAutocomplete extends Rule {
10658
10652
  return;
10659
10653
  }
10660
10654
  if (tokens.includes("on") || tokens.includes("off")) {
10655
+ const mantle = type !== "hidden" ? "expectation" : "anchor";
10661
10656
  this.validateOnOff(node, mantle, tokens);
10662
10657
  return;
10663
10658
  }
@@ -10781,44 +10776,46 @@ class ValidAutocomplete extends Rule {
10781
10776
  * Ensure contact token is only used with field names from the second list.
10782
10777
  */
10783
10778
  validateContact(node, tokens, order) {
10784
- if (order.includes("contact") && order.includes("field1")) {
10785
- const a = order.indexOf("field1");
10786
- 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
+ }
10787
10804
  const context = {
10788
- msg: 4 /* InvalidCombination */,
10805
+ msg: 2 /* InvalidOrder */,
10789
10806
  /* eslint-disable @typescript-eslint/no-non-null-assertion -- it must be present of it wouldn't be found */
10790
- first: tokens.item(a),
10791
- second: tokens.item(b)
10807
+ first: tokens.item(i),
10808
+ second: tokens.item(i + 1)
10792
10809
  /* eslint-enable @typescript-eslint/no-non-null-assertion */
10793
10810
  };
10794
10811
  this.report({
10795
10812
  node,
10796
10813
  message: getTerminalMessage(context),
10797
- location: tokens.location(b),
10814
+ location: tokens.location(i + 1),
10798
10815
  context
10799
10816
  });
10800
10817
  }
10801
10818
  }
10802
- validateOrder(node, tokens, order) {
10803
- const indicies = order.map((it) => expectedOrder.indexOf(it));
10804
- for (let i = 0; i < indicies.length - 1; i++) {
10805
- if (indicies[0] > indicies[i + 1]) {
10806
- const context = {
10807
- msg: 2 /* InvalidOrder */,
10808
- /* eslint-disable @typescript-eslint/no-non-null-assertion -- it must be present of it wouldn't be found */
10809
- first: tokens.item(i),
10810
- second: tokens.item(i + 1)
10811
- /* eslint-enable @typescript-eslint/no-non-null-assertion */
10812
- };
10813
- this.report({
10814
- node,
10815
- message: getTerminalMessage(context),
10816
- location: tokens.location(i + 1),
10817
- context
10818
- });
10819
- }
10820
- }
10821
- }
10822
10819
  validateControlGroup(node, tokens, fieldTokens) {
10823
10820
  const numFields = fieldTokens.filter(Boolean).length;
10824
10821
  if (numFields === 0) {
@@ -10910,7 +10907,7 @@ class ValidID extends Rule {
10910
10907
  documentation(context) {
10911
10908
  const { relaxed } = this.options;
10912
10909
  const { kind, id } = context;
10913
- 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());
10914
10911
  const relaxedDescription = relaxed ? [] : [
10915
10912
  " - ID must begin with a letter",
10916
10913
  " - ID must only contain letters, digits, `-` and `_`"
@@ -10948,7 +10945,7 @@ class ValidID extends Rule {
10948
10945
  if (relaxed) {
10949
10946
  return;
10950
10947
  }
10951
- if (/^[^\p{L}]/u.test(value)) {
10948
+ if (new RegExp("^\\P{L}", "u").test(value)) {
10952
10949
  const context = { kind: 3 /* LEADING_CHARACTER */, id: value };
10953
10950
  this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10954
10951
  return;
@@ -11309,7 +11306,7 @@ function isSimpleTable(table) {
11309
11306
  return false;
11310
11307
  }
11311
11308
  const numColumns = cells[0].length;
11312
- if (!cells.every((row) => row.length === numColumns)) {
11309
+ if (cells.some((row) => row.length !== numColumns)) {
11313
11310
  return false;
11314
11311
  }
11315
11312
  const shape = getShape(cells);
@@ -11963,7 +11960,7 @@ class ResolvedConfig {
11963
11960
  }
11964
11961
 
11965
11962
  function haveResolver(key, value) {
11966
- return key in value;
11963
+ return Object.hasOwn(value, key);
11967
11964
  }
11968
11965
  function haveConfigResolver(value) {
11969
11966
  return haveResolver("resolveConfig", value);
@@ -11978,7 +11975,10 @@ function haveTransformerResolver(value) {
11978
11975
  return haveResolver("resolveTransformer", value);
11979
11976
  }
11980
11977
  function resolveConfig(resolvers, id, options) {
11981
- for (const resolver of resolvers.filter(haveConfigResolver)) {
11978
+ for (const resolver of resolvers) {
11979
+ if (!haveConfigResolver(resolver)) {
11980
+ continue;
11981
+ }
11982
11982
  const config = resolver.resolveConfig(id, options);
11983
11983
  if (isThenable(config)) {
11984
11984
  return resolveConfigAsync(resolvers, id, options);
@@ -11990,7 +11990,10 @@ function resolveConfig(resolvers, id, options) {
11990
11990
  throw new UserError(`Failed to load configuration from "${id}"`);
11991
11991
  }
11992
11992
  async function resolveConfigAsync(resolvers, id, options) {
11993
- for (const resolver of resolvers.filter(haveConfigResolver)) {
11993
+ for (const resolver of resolvers) {
11994
+ if (!haveConfigResolver(resolver)) {
11995
+ continue;
11996
+ }
11994
11997
  const config = await resolver.resolveConfig(id, options);
11995
11998
  if (config) {
11996
11999
  return config;
@@ -11999,7 +12002,10 @@ async function resolveConfigAsync(resolvers, id, options) {
11999
12002
  throw new UserError(`Failed to load configuration from "${id}"`);
12000
12003
  }
12001
12004
  function resolveElements(resolvers, id, options) {
12002
- for (const resolver of resolvers.filter(haveElementsResolver)) {
12005
+ for (const resolver of resolvers) {
12006
+ if (!haveElementsResolver(resolver)) {
12007
+ continue;
12008
+ }
12003
12009
  const elements = resolver.resolveElements(id, options);
12004
12010
  if (isThenable(elements)) {
12005
12011
  return resolveElementsAsync(resolvers, id, options);
@@ -12011,7 +12017,10 @@ function resolveElements(resolvers, id, options) {
12011
12017
  throw new UserError(`Failed to load elements from "${id}"`);
12012
12018
  }
12013
12019
  async function resolveElementsAsync(resolvers, id, options) {
12014
- for (const resolver of resolvers.filter(haveElementsResolver)) {
12020
+ for (const resolver of resolvers) {
12021
+ if (!haveElementsResolver(resolver)) {
12022
+ continue;
12023
+ }
12015
12024
  const elements = await resolver.resolveElements(id, options);
12016
12025
  if (elements) {
12017
12026
  return elements;
@@ -12020,7 +12029,10 @@ async function resolveElementsAsync(resolvers, id, options) {
12020
12029
  throw new UserError(`Failed to load elements from "${id}"`);
12021
12030
  }
12022
12031
  function resolvePlugin(resolvers, id, options) {
12023
- for (const resolver of resolvers.filter(havePluginResolver)) {
12032
+ for (const resolver of resolvers) {
12033
+ if (!havePluginResolver(resolver)) {
12034
+ continue;
12035
+ }
12024
12036
  const plugin = resolver.resolvePlugin(id, options);
12025
12037
  if (isThenable(plugin)) {
12026
12038
  return resolvePluginAsync(resolvers, id, options);
@@ -12032,7 +12044,10 @@ function resolvePlugin(resolvers, id, options) {
12032
12044
  throw new UserError(`Failed to load plugin from "${id}"`);
12033
12045
  }
12034
12046
  async function resolvePluginAsync(resolvers, id, options) {
12035
- for (const resolver of resolvers.filter(havePluginResolver)) {
12047
+ for (const resolver of resolvers) {
12048
+ if (!havePluginResolver(resolver)) {
12049
+ continue;
12050
+ }
12036
12051
  const plugin = await resolver.resolvePlugin(id, options);
12037
12052
  if (plugin) {
12038
12053
  return plugin;
@@ -12041,7 +12056,10 @@ async function resolvePluginAsync(resolvers, id, options) {
12041
12056
  throw new UserError(`Failed to load plugin from "${id}"`);
12042
12057
  }
12043
12058
  function resolveTransformer(resolvers, id, options) {
12044
- for (const resolver of resolvers.filter(haveTransformerResolver)) {
12059
+ for (const resolver of resolvers) {
12060
+ if (!haveTransformerResolver(resolver)) {
12061
+ continue;
12062
+ }
12045
12063
  const transformer = resolver.resolveTransformer(id, options);
12046
12064
  if (isThenable(transformer)) {
12047
12065
  return resolveTransformerAsync(resolvers, id, options);
@@ -12053,7 +12071,10 @@ function resolveTransformer(resolvers, id, options) {
12053
12071
  throw new UserError(`Failed to load transformer from "${id}"`);
12054
12072
  }
12055
12073
  async function resolveTransformerAsync(resolvers, id, options) {
12056
- for (const resolver of resolvers.filter(haveTransformerResolver)) {
12074
+ for (const resolver of resolvers) {
12075
+ if (!haveTransformerResolver(resolver)) {
12076
+ continue;
12077
+ }
12057
12078
  const transformer = await resolver.resolveTransformer(id, options);
12058
12079
  if (transformer) {
12059
12080
  return transformer;
@@ -12093,9 +12114,12 @@ function staticResolver(map = {}) {
12093
12114
  };
12094
12115
  }
12095
12116
 
12096
- const ajv = new Ajv({ strict: true, strictTuples: true, strictTypes: true });
12097
- ajv.addMetaSchema(ajvSchemaDraft);
12098
- 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
+ })();
12099
12123
  const validator = ajv.compile(configurationSchema);
12100
12124
  function overwriteMerge(_a, b) {
12101
12125
  return b;
@@ -12114,18 +12138,16 @@ function mergeInternal(base, rhs) {
12114
12138
  function toArray$1(value) {
12115
12139
  if (Array.isArray(value)) {
12116
12140
  return value;
12117
- } else {
12118
- return [value];
12119
12141
  }
12142
+ return [value];
12120
12143
  }
12121
12144
  function transformerEntries(transform) {
12122
12145
  return Object.entries(transform).map(([pattern, value]) => {
12123
12146
  const regex = new RegExp(pattern);
12124
12147
  if (typeof value === "string") {
12125
12148
  return { kind: "import", pattern: regex, name: value };
12126
- } else {
12127
- return { kind: "function", pattern: regex, function: value };
12128
12149
  }
12150
+ return { kind: "function", pattern: regex, function: value };
12129
12151
  });
12130
12152
  }
12131
12153
  class Config {
@@ -12150,8 +12172,8 @@ class Config {
12150
12172
  * Create configuration from object.
12151
12173
  */
12152
12174
  static fromObject(resolvers, options, filename = null) {
12153
- Config.validate(options, filename);
12154
- return Config.create(resolvers, options);
12175
+ this.validate(options, filename);
12176
+ return this.create(resolvers, options);
12155
12177
  }
12156
12178
  /**
12157
12179
  * Read configuration from filename.
@@ -12165,10 +12187,9 @@ class Config {
12165
12187
  static fromFile(resolvers, filename) {
12166
12188
  const configData = resolveConfig(toArray$1(resolvers), filename, { cache: false });
12167
12189
  if (isThenable(configData)) {
12168
- return configData.then((configData2) => Config.fromObject(resolvers, configData2, filename));
12169
- } else {
12170
- return Config.fromObject(resolvers, configData, filename);
12190
+ return configData.then((configData2) => this.fromObject(resolvers, configData2, filename));
12171
12191
  }
12192
+ return this.fromObject(resolvers, configData, filename);
12172
12193
  }
12173
12194
  /**
12174
12195
  * Validate configuration data.
@@ -12190,8 +12211,8 @@ class Config {
12190
12211
  );
12191
12212
  }
12192
12213
  if (configData.rules) {
12193
- const normalizedRules = Config.getRulesObject(configData.rules);
12194
- for (const [ruleId, [, ruleOptions]] of normalizedRules.entries()) {
12214
+ const normalizedRules = this.getRulesObject(configData.rules);
12215
+ for (const [ruleId, [, ruleOptions]] of normalizedRules) {
12195
12216
  const cls = bundledRules[ruleId];
12196
12217
  const path = `/rules/${ruleId}/1`;
12197
12218
  Rule.validateOptions(cls, ruleId, path, ruleOptions, filename, configData);
@@ -12214,9 +12235,8 @@ class Config {
12214
12235
  return plugins.then((plugins2) => {
12215
12236
  return instance.init(options, plugins2);
12216
12237
  });
12217
- } else {
12218
- return instance.init(options, plugins);
12219
12238
  }
12239
+ return instance.init(options, plugins);
12220
12240
  }
12221
12241
  init(options, plugins) {
12222
12242
  this.plugins = plugins;
@@ -12233,9 +12253,8 @@ class Config {
12233
12253
  const extendedConfig = this.extendConfig(this.config.extends ?? []);
12234
12254
  if (isThenable(extendedConfig)) {
12235
12255
  return extendedConfig.then((extended) => update(extended));
12236
- } else {
12237
- return update(extendedConfig);
12238
12256
  }
12257
+ return update(extendedConfig);
12239
12258
  }
12240
12259
  /**
12241
12260
  * @internal
@@ -12277,12 +12296,11 @@ class Config {
12277
12296
  instance.extendMeta(instance.plugins);
12278
12297
  return instance;
12279
12298
  });
12280
- } else {
12281
- instance.plugins = plugins;
12282
- instance.configurations = instance.loadConfigurations(instance.plugins);
12283
- instance.extendMeta(instance.plugins);
12284
- return instance;
12285
12299
  }
12300
+ instance.plugins = plugins;
12301
+ instance.configurations = instance.loadConfigurations(instance.plugins);
12302
+ instance.extendMeta(instance.plugins);
12303
+ return instance;
12286
12304
  }
12287
12305
  extendConfig(entries) {
12288
12306
  if (entries.length === 0) {
@@ -12338,20 +12356,19 @@ class Config {
12338
12356
  const result = this.getElementsFromEntry(entry);
12339
12357
  if (isThenable(result)) {
12340
12358
  return result.then((result2) => {
12341
- const [obj, filename] = result2;
12342
- metaTable.loadFromObject(obj, filename);
12343
- const next2 = source.shift();
12344
- if (next2) {
12345
- 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);
12346
12364
  }
12347
12365
  });
12348
- } else {
12349
- const [obj, filename] = result;
12350
- metaTable.loadFromObject(obj, filename);
12351
- const next2 = source.shift();
12352
- if (next2) {
12353
- return loadEntry(next2);
12354
- }
12366
+ }
12367
+ const [obj, filename] = result;
12368
+ metaTable.loadFromObject(obj, filename);
12369
+ const next2 = source.shift();
12370
+ if (next2) {
12371
+ return loadEntry(next2);
12355
12372
  }
12356
12373
  };
12357
12374
  const next = source.shift();
@@ -12381,9 +12398,8 @@ class Config {
12381
12398
  return obj.then((obj2) => {
12382
12399
  return [obj2, entry];
12383
12400
  });
12384
- } else {
12385
- return [obj, entry];
12386
12401
  }
12402
+ return [obj, entry];
12387
12403
  } catch (err) {
12388
12404
  const message = err instanceof Error ? err.message : String(err);
12389
12405
  throw new ConfigError(
@@ -12445,7 +12461,7 @@ class Config {
12445
12461
  const loadPlugin = (entry, index) => {
12446
12462
  if (typeof entry !== "string") {
12447
12463
  const plugin = entry;
12448
- plugin.name = plugin.name || `:unnamedPlugin@${String(index + 1)}`;
12464
+ plugin.name ||= `:unnamedPlugin@${String(index + 1)}`;
12449
12465
  plugin.originalName = `:unnamedPlugin@${String(index + 1)}`;
12450
12466
  loaded.push(plugin);
12451
12467
  const next2 = loading.shift();
@@ -12457,22 +12473,21 @@ class Config {
12457
12473
  const plugin = resolvePlugin(this.resolvers, entry, { cache: true });
12458
12474
  if (isThenable(plugin)) {
12459
12475
  return plugin.then((plugin2) => {
12460
- plugin2.name = plugin2.name || entry;
12476
+ plugin2.name ||= entry;
12461
12477
  plugin2.originalName = entry;
12462
12478
  loaded.push(plugin2);
12463
- const next2 = loading.shift();
12464
- if (next2) {
12465
- return loadPlugin(next2, index + 1);
12479
+ const next3 = loading.shift();
12480
+ if (next3) {
12481
+ return loadPlugin(next3, index + 1);
12466
12482
  }
12467
12483
  });
12468
- } else {
12469
- plugin.name = plugin.name || entry;
12470
- plugin.originalName = entry;
12471
- loaded.push(plugin);
12472
- const next2 = loading.shift();
12473
- if (next2) {
12474
- return loadPlugin(next2, index + 1);
12475
- }
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);
12476
12491
  }
12477
12492
  } catch (err) {
12478
12493
  const message = err instanceof Error ? err.message : String(err);
@@ -12498,7 +12513,8 @@ class Config {
12498
12513
  configs.set(name, config);
12499
12514
  }
12500
12515
  for (const plugin of plugins) {
12501
- for (const [name, config] of Object.entries(plugin.configs ?? {})) {
12516
+ const entries = Object.entries(plugin.configs ?? {});
12517
+ for (const [name, config] of entries) {
12502
12518
  if (!config) {
12503
12519
  continue;
12504
12520
  }
@@ -12542,9 +12558,8 @@ class Config {
12542
12558
  return resolveData.then((resolveData2) => {
12543
12559
  return new ResolvedConfig(resolveData2, this.get());
12544
12560
  });
12545
- } else {
12546
- return new ResolvedConfig(resolveData, this.get());
12547
12561
  }
12562
+ return new ResolvedConfig(resolveData, this.get());
12548
12563
  }
12549
12564
  /**
12550
12565
  * Same as [[resolve]] but returns the raw configuration data instead of
@@ -12563,14 +12578,13 @@ class Config {
12563
12578
  transformers: this.transformers
12564
12579
  };
12565
12580
  });
12566
- } else {
12567
- return {
12568
- metaTable,
12569
- plugins: this.getPlugins(),
12570
- rules: this.getRules(),
12571
- transformers: this.transformers
12572
- };
12573
12581
  }
12582
+ return {
12583
+ metaTable,
12584
+ plugins: this.getPlugins(),
12585
+ rules: this.getRules(),
12586
+ transformers: this.transformers
12587
+ };
12574
12588
  }
12575
12589
  }
12576
12590
 
@@ -12614,10 +12628,9 @@ class ConfigLoader {
12614
12628
  this._globalConfig = config2;
12615
12629
  return this._globalConfig;
12616
12630
  });
12617
- } else {
12618
- this._globalConfig = config;
12619
- return this._globalConfig;
12620
12631
  }
12632
+ this._globalConfig = config;
12633
+ return this._globalConfig;
12621
12634
  }
12622
12635
  /**
12623
12636
  * Get the global configuration.
@@ -12699,9 +12712,8 @@ class StaticConfigLoader extends ConfigLoader {
12699
12712
  const override = this.loadFromObject(configOverride ?? {});
12700
12713
  if (isThenable(override)) {
12701
12714
  return override.then((override2) => this._resolveConfig(override2));
12702
- } else {
12703
- return this._resolveConfig(override);
12704
12715
  }
12716
+ return this._resolveConfig(override);
12705
12717
  }
12706
12718
  flushCache() {
12707
12719
  }
@@ -12718,25 +12730,22 @@ class StaticConfigLoader extends ConfigLoader {
12718
12730
  const globalConfig = this.getGlobalConfig();
12719
12731
  if (isThenable(globalConfig)) {
12720
12732
  return globalConfig.then((globalConfig2) => {
12721
- const merged = globalConfig2.merge(this.resolvers, override);
12722
- if (isThenable(merged)) {
12723
- return merged.then((merged2) => {
12724
- return merged2.resolve();
12733
+ const merged2 = globalConfig2.merge(this.resolvers, override);
12734
+ if (isThenable(merged2)) {
12735
+ return merged2.then((merged3) => {
12736
+ return merged3.resolve();
12725
12737
  });
12726
- } else {
12727
- return merged.resolve();
12728
12738
  }
12739
+ return merged2.resolve();
12729
12740
  });
12730
- } else {
12731
- const merged = globalConfig.merge(this.resolvers, override);
12732
- if (isThenable(merged)) {
12733
- return merged.then((merged2) => {
12734
- return merged2.resolve();
12735
- });
12736
- } else {
12737
- return merged.resolve();
12738
- }
12739
12741
  }
12742
+ const merged = globalConfig.merge(this.resolvers, override);
12743
+ if (isThenable(merged)) {
12744
+ return merged.then((merged2) => {
12745
+ return merged2.resolve();
12746
+ });
12747
+ }
12748
+ return merged.resolve();
12740
12749
  }
12741
12750
  }
12742
12751
 
@@ -12823,7 +12832,7 @@ class EventHandler {
12823
12832
  }
12824
12833
 
12825
12834
  const name = "html-validate";
12826
- const version = "11.5.2";
12835
+ const version = "11.5.4";
12827
12836
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
12828
12837
 
12829
12838
  function freeze(src) {
@@ -12861,7 +12870,7 @@ class Reporter {
12861
12870
  for (const report of reports) {
12862
12871
  for (const result of report.results) {
12863
12872
  const key = result.filePath;
12864
- if (key in merged) {
12873
+ if (Object.hasOwn(merged, key)) {
12865
12874
  merged[key].messages = [...merged[key].messages, ...result.messages];
12866
12875
  } else {
12867
12876
  merged[key] = { ...result };
@@ -12885,7 +12894,7 @@ class Reporter {
12885
12894
  */
12886
12895
  add(options) {
12887
12896
  const { rule, message, severity, node, location, context } = options;
12888
- if (!(location.filename in this.result)) {
12897
+ if (!Object.hasOwn(this.result, location.filename)) {
12889
12898
  this.result[location.filename] = [];
12890
12899
  }
12891
12900
  const ruleUrl = rule.documentation(context)?.url;
@@ -12913,7 +12922,7 @@ class Reporter {
12913
12922
  * @internal
12914
12923
  */
12915
12924
  addManual(filename, message) {
12916
- if (!(filename in this.result)) {
12925
+ if (!Object.hasOwn(this.result, filename)) {
12917
12926
  this.result[filename] = [];
12918
12927
  }
12919
12928
  this.result[filename].push(message);
@@ -12924,6 +12933,7 @@ class Reporter {
12924
12933
  save(sources) {
12925
12934
  const report = {
12926
12935
  valid: this.isValid(),
12936
+ /* eslint-disable-next-line unicorn/prefer-object-iterable-methods -- technical debt */
12927
12937
  results: Object.keys(this.result).map((filePath) => {
12928
12938
  const messages = Array.from(this.result[filePath], freeze).toSorted(messageSort);
12929
12939
  const source = (sources ?? []).find((source2) => filePath === source2.filename);
@@ -12988,7 +12998,7 @@ function definePlugin(plugin) {
12988
12998
  return plugin;
12989
12999
  }
12990
13000
 
12991
- const regexp = /<!(?:--)?\[(.*?)](?:--)?>/g;
13001
+ const regexp = /<!(?:--)?\[(.*?)\](?:--)?>/g;
12992
13002
  function* parseConditionalComment(comment, commentLocation) {
12993
13003
  let match;
12994
13004
  while ((match = regexp.exec(comment)) !== null) {
@@ -13005,6 +13015,7 @@ function* parseConditionalComment(comment, commentLocation) {
13005
13015
 
13006
13016
  class ParserError extends Error {
13007
13017
  location;
13018
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
13008
13019
  constructor(location, message) {
13009
13020
  super(message);
13010
13021
  this.name = "ParserError";
@@ -13168,9 +13179,8 @@ class Parser {
13168
13179
  const open = !token.data[1];
13169
13180
  if (open) {
13170
13181
  return this.wouldCloseElement(token, active);
13171
- } else {
13172
- return this.closeOptionalEndTag(token, active);
13173
13182
  }
13183
+ return this.closeOptionalEndTag(token, active);
13174
13184
  }
13175
13185
  /**
13176
13186
  * Returns `true` if the element’s end tag may be omitted, either because
@@ -13522,9 +13532,8 @@ class Parser {
13522
13532
  const quote = token.data[3];
13523
13533
  if (quote) {
13524
13534
  return sliceLocation(token.location, 2, -1);
13525
- } else {
13526
- return sliceLocation(token.location, 1);
13527
13535
  }
13536
+ return sliceLocation(token.location, 1);
13528
13537
  }
13529
13538
  /**
13530
13539
  * Take attribute key and value token an returns a new location referring to
@@ -13812,13 +13821,14 @@ class PerformanceTracker {
13812
13821
  */
13813
13822
  getResult() {
13814
13823
  const events = Array.from(
13815
- this.eventData.entries(),
13824
+ this.eventData,
13816
13825
  ([event, { count, time }]) => ({ event, count, time })
13817
13826
  ).toSorted((a, b) => b.time - a.time);
13818
- const rules = Array.from(
13819
- this.ruleData.entries(),
13820
- ([rule, { count, time }]) => ({ rule, count, time })
13821
- ).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);
13822
13832
  return {
13823
13833
  events,
13824
13834
  rules,
@@ -13865,9 +13875,11 @@ function dumpTree(root) {
13865
13875
  return lines;
13866
13876
  }
13867
13877
 
13868
- let blockerCounter = 1;
13878
+ const state = {
13879
+ blockerCounter: 1
13880
+ };
13869
13881
  function createBlocker() {
13870
- const id = blockerCounter++;
13882
+ const id = state.blockerCounter++;
13871
13883
  return id;
13872
13884
  }
13873
13885
 
@@ -14003,9 +14015,8 @@ class Engine {
14003
14015
  const [, options] = ruleData;
14004
14016
  const rule = this.instantiateRule(ruleId, options);
14005
14017
  return rule.documentation(context);
14006
- } else {
14007
- return null;
14008
14018
  }
14019
+ return null;
14009
14020
  }
14010
14021
  /**
14011
14022
  * Create a new parser instance with the current configuration.
@@ -14134,7 +14145,8 @@ class Engine {
14134
14145
  initRules(config) {
14135
14146
  const availableRules = {};
14136
14147
  for (const plugin of config.getPlugins()) {
14137
- for (const [name, rule] of Object.entries(plugin.rules ?? {})) {
14148
+ const entries = Object.entries(plugin.rules ?? {});
14149
+ for (const [name, rule] of entries) {
14138
14150
  if (!rule) {
14139
14151
  continue;
14140
14152
  }
@@ -14162,7 +14174,7 @@ class Engine {
14162
14174
  */
14163
14175
  setupRules(config, parser) {
14164
14176
  const rules = {};
14165
- for (const [ruleId, [severity, options]] of config.getRules().entries()) {
14177
+ for (const [ruleId, [severity, options]] of config.getRules()) {
14166
14178
  rules[ruleId] = this.loadRule(ruleId, config, severity, options, parser, this.report);
14167
14179
  }
14168
14180
  return rules;
@@ -14186,9 +14198,8 @@ class Engine {
14186
14198
  if (this.availableRules[name]) {
14187
14199
  const RuleConstructor = this.availableRules[name];
14188
14200
  return new RuleConstructor(options);
14189
- } else {
14190
- return this.missingRule(name);
14191
14201
  }
14202
+ return this.missingRule(name);
14192
14203
  }
14193
14204
  missingRule(name) {
14194
14205
  return new class MissingRule extends Rule {
@@ -14284,34 +14295,30 @@ function getTransformerFunction(resolvers, name, plugins) {
14284
14295
  validateTransformer(transformer2);
14285
14296
  return transformer2;
14286
14297
  });
14287
- } else {
14288
- validateTransformer(transformer);
14289
- return transformer;
14290
14298
  }
14299
+ validateTransformer(transformer);
14300
+ return transformer;
14291
14301
  } catch (err) {
14292
14302
  if (err instanceof ConfigError) {
14293
14303
  throw new ConfigError(`Failed to load transformer "${name}": ${err.message}`, err);
14294
- } else {
14295
- throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
14296
14304
  }
14305
+ throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
14297
14306
  }
14298
14307
  }
14299
14308
  function getCachedTransformerFunction(cache, resolvers, name, plugins) {
14300
14309
  const cached = cache.get(name);
14301
14310
  if (cached) {
14302
14311
  return cached;
14303
- } else {
14304
- const transformer = getTransformerFunction(resolvers, name, plugins);
14305
- if (isThenable(transformer)) {
14306
- return transformer.then((transformer2) => {
14307
- cache.set(name, transformer2);
14308
- return transformer2;
14309
- });
14310
- } else {
14311
- cache.set(name, transformer);
14312
- return transformer;
14313
- }
14314
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;
14315
14322
  }
14316
14323
 
14317
14324
  function isIterable(value) {
@@ -14327,6 +14334,9 @@ const asyncInSyncTransformError = "Cannot use async transformer from sync functi
14327
14334
  async function transformSource(resolvers, config, source, filename) {
14328
14335
  const { cache } = config;
14329
14336
  const transformer = config.findTransformer(filename ?? source.filename);
14337
+ if (!transformer) {
14338
+ return [source];
14339
+ }
14330
14340
  const context = {
14331
14341
  hasChain(filename2) {
14332
14342
  return config.canTransform(filename2);
@@ -14335,9 +14345,6 @@ async function transformSource(resolvers, config, source, filename) {
14335
14345
  return transformSource(resolvers, config, source2, filename2);
14336
14346
  }
14337
14347
  };
14338
- if (!transformer) {
14339
- return [source];
14340
- }
14341
14348
  const fn = transformer.kind === "import" ? await getCachedTransformerFunction(cache, resolvers, transformer.name, config.getPlugins()) : transformer.function;
14342
14349
  const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14343
14350
  try {
@@ -14356,6 +14363,9 @@ async function transformSource(resolvers, config, source, filename) {
14356
14363
  function transformSourceSync(resolvers, config, source, filename) {
14357
14364
  const { cache } = config;
14358
14365
  const transformer = config.findTransformer(filename ?? source.filename);
14366
+ if (!transformer) {
14367
+ return [source];
14368
+ }
14359
14369
  const context = {
14360
14370
  hasChain(filename2) {
14361
14371
  return config.canTransform(filename2);
@@ -14364,14 +14374,11 @@ function transformSourceSync(resolvers, config, source, filename) {
14364
14374
  return transformSourceSync(resolvers, config, source2, filename2);
14365
14375
  }
14366
14376
  };
14367
- if (!transformer) {
14368
- return [source];
14369
- }
14370
14377
  const fn = transformer.kind === "import" ? getCachedTransformerFunction(cache, resolvers, transformer.name, config.getPlugins()) : transformer.function;
14371
- const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14372
14378
  if (isThenable(fn)) {
14373
14379
  throw new UserError(asyncInSyncTransformError);
14374
14380
  }
14381
+ const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14375
14382
  try {
14376
14383
  const result = fn.call(context, source);
14377
14384
  if (isThenable(result)) {
@@ -14473,7 +14480,7 @@ function checkstyleFormatter(results) {
14473
14480
  `;
14474
14481
  for (const message of messages) {
14475
14482
  const ruleId = xmlescape(`htmlvalidate.rules.${message.ruleId}`);
14476
- output += " ";
14483
+ output += " ".repeat(4);
14477
14484
  output += [
14478
14485
  `<error line="${xmlescape(message.line)}"`,
14479
14486
  `column="${xmlescape(message.column)}"`,
@@ -14560,9 +14567,8 @@ function codeFrameColumns(rawLines, loc) {
14560
14567
  ].join("");
14561
14568
  }
14562
14569
  return [">", gutter, line.length > 0 ? ` ${line}` : "", markerLine].join("");
14563
- } else {
14564
- return [" ", gutter, line.length > 0 ? ` ${line}` : ""].join("");
14565
14570
  }
14571
+ return [" ", gutter, line.length > 0 ? ` ${line}` : ""].join("");
14566
14572
  }).join("\n");
14567
14573
  }
14568
14574