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/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);
@@ -2063,25 +2057,25 @@ function lastChild(node) {
2063
2057
  return node.nextSibling === null;
2064
2058
  }
2065
2059
 
2066
- const cache = {};
2060
+ const cache$1 = {};
2067
2061
  function getNthChild(node) {
2068
2062
  if (!node.parent) {
2069
2063
  return -1;
2070
2064
  }
2071
- if (!cache[node.unique]) {
2065
+ if (!cache$1[node.unique]) {
2072
2066
  const parent = node.parent;
2073
2067
  const index = parent.childElements.findIndex((cur) => {
2074
2068
  return cur.unique === node.unique;
2075
2069
  });
2076
- cache[node.unique] = index + 1;
2070
+ cache$1[node.unique] = index + 1;
2077
2071
  }
2078
- return cache[node.unique];
2072
+ return cache$1[node.unique];
2079
2073
  }
2080
2074
  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
 
@@ -2489,9 +2481,16 @@ function generateIdSelector(id) {
2489
2481
  return /^\d/.test(escaped) ? `[id="${escaped}"]` : `#${escaped}`;
2490
2482
  }
2491
2483
 
2484
+ const cache = /* @__PURE__ */ new Map();
2492
2485
  function parseSelector(selector) {
2486
+ const cached = cache.get(selector);
2487
+ if (cached) {
2488
+ return cached;
2489
+ }
2493
2490
  const compounds = getCompounds(selector);
2494
- return ComplexSelector.fromCompounds(compounds);
2491
+ const result = ComplexSelector.fromCompounds(compounds);
2492
+ cache.set(selector, result);
2493
+ return result;
2495
2494
  }
2496
2495
 
2497
2496
  const TEXT_NODE_NAME = "#text";
@@ -2636,10 +2635,10 @@ class HtmlElement extends DOMNode {
2636
2635
  */
2637
2636
  static fromTokens(startToken, endToken, parent, metaTable, namespace = "") {
2638
2637
  const name = startToken.data[2];
2639
- const tagName = namespace ? `${namespace}:${name}` : name;
2640
2638
  if (!name) {
2641
2639
  throw new Error("tagName cannot be empty");
2642
2640
  }
2641
+ const tagName = namespace ? `${namespace}:${name}` : name;
2643
2642
  const meta = metaTable ? metaTable.getMetaFor(tagName) : null;
2644
2643
  const open = startToken.data[1] !== "/";
2645
2644
  const closed = isClosed(endToken, meta);
@@ -2661,9 +2660,8 @@ class HtmlElement extends DOMNode {
2661
2660
  get annotatedName() {
2662
2661
  if (this.annotation) {
2663
2662
  return this.annotation;
2664
- } else {
2665
- return `<${this.tagName}>`;
2666
2663
  }
2664
+ return `<${this.tagName}>`;
2667
2665
  }
2668
2666
  /**
2669
2667
  * Get list of IDs referenced by `aria-labelledby`.
@@ -2882,13 +2880,13 @@ class HtmlElement extends DOMNode {
2882
2880
  if (!tabindex) {
2883
2881
  return this.cacheSet(TABINDEX, null);
2884
2882
  }
2885
- if (tabindex.value === null) {
2883
+ if (tabindex.value === null || tabindex.value === "") {
2886
2884
  return this.cacheSet(TABINDEX, null);
2887
2885
  }
2888
2886
  if (tabindex.value instanceof DynamicValue) {
2889
2887
  return this.cacheSet(TABINDEX, 0);
2890
2888
  }
2891
- const parsed = Number.parseInt(tabindex.value, 10);
2889
+ const parsed = Math.trunc(Number(tabindex.value));
2892
2890
  if (Number.isNaN(parsed)) {
2893
2891
  return this.cacheSet(TABINDEX, null);
2894
2892
  }
@@ -2904,11 +2902,11 @@ class HtmlElement extends DOMNode {
2904
2902
  const tagName = this.tagName.toLowerCase();
2905
2903
  if (tagName === "script") {
2906
2904
  return "script";
2907
- } else if (tagName === "style") {
2905
+ }
2906
+ if (tagName === "style") {
2908
2907
  return "css";
2909
- } else {
2910
- return "text";
2911
2908
  }
2909
+ return "text";
2912
2910
  }
2913
2911
  /**
2914
2912
  * Get a list of all attributes on this node.
@@ -2920,16 +2918,15 @@ class HtmlElement extends DOMNode {
2920
2918
  }
2921
2919
  hasAttribute(key) {
2922
2920
  key = key.toLowerCase();
2923
- return key in this.attr;
2921
+ return Object.hasOwn(this.attr, key);
2924
2922
  }
2925
2923
  getAttribute(key, all = false) {
2926
2924
  key = key.toLowerCase();
2927
- if (key in this.attr) {
2925
+ if (Object.hasOwn(this.attr, key)) {
2928
2926
  const matches = this.attr[key];
2929
2927
  return all ? matches : matches[0];
2930
- } else {
2931
- return all ? [] : null;
2932
2928
  }
2929
+ return all ? [] : null;
2933
2930
  }
2934
2931
  /**
2935
2932
  * Get attribute value.
@@ -2947,17 +2944,13 @@ class HtmlElement extends DOMNode {
2947
2944
  const attr = this.getAttribute(key);
2948
2945
  if (attr) {
2949
2946
  return attr.value !== null ? attr.value.toString() : null;
2950
- } else {
2951
- return null;
2952
2947
  }
2948
+ return null;
2953
2949
  }
2954
- /**
2955
- * Add text as a child node to this element.
2956
- *
2957
- * @param text - Text to add.
2958
- * @param location - Source code location of this text.
2959
- */
2960
2950
  appendText(text, location) {
2951
+ if (typeof text === "object" && "dynamic" in text) {
2952
+ text = new DynamicValue(text.dynamic);
2953
+ }
2961
2954
  this.childNodes.push(new TextNode(text, location));
2962
2955
  }
2963
2956
  /**
@@ -3010,23 +3003,30 @@ class HtmlElement extends DOMNode {
3010
3003
  return i <= this.siblings.length - 2 ? this.siblings[i + 1] : null;
3011
3004
  }
3012
3005
  getElementsByTagName(tagName) {
3013
- return this.childElements.reduce((matches, node) => {
3014
- return matches.concat(node.is(tagName) ? [node] : [], node.getElementsByTagName(tagName));
3015
- }, []);
3006
+ const matches = [];
3007
+ this.collectByTagName(tagName, matches);
3008
+ return matches;
3009
+ }
3010
+ collectByTagName(tagName, matches) {
3011
+ for (const node of this.childElements) {
3012
+ if (node.is(tagName)) {
3013
+ matches.push(node);
3014
+ }
3015
+ node.collectByTagName(tagName, matches);
3016
+ }
3016
3017
  }
3017
3018
  querySelector(selector) {
3018
3019
  const it = this.querySelectorImpl(selector);
3019
3020
  const next = it.next();
3020
3021
  if (next.done) {
3021
3022
  return null;
3022
- } else {
3023
- return next.value;
3024
3023
  }
3024
+ return next.value;
3025
3025
  }
3026
3026
  querySelectorAll(selector) {
3027
3027
  const it = this.querySelectorImpl(selector);
3028
3028
  const unique = new Set(it);
3029
- return Array.from(unique.values());
3029
+ return Array.from(unique);
3030
3030
  }
3031
3031
  *querySelectorImpl(selectorList) {
3032
3032
  if (!selectorList) {
@@ -3047,9 +3047,8 @@ class HtmlElement extends DOMNode {
3047
3047
  function visit(node) {
3048
3048
  if (callback(node)) {
3049
3049
  return true;
3050
- } else {
3051
- return node.childElements.some(visit);
3052
3050
  }
3051
+ return node.childElements.some(visit);
3053
3052
  }
3054
3053
  }
3055
3054
  /**
@@ -3224,7 +3223,7 @@ class Validator {
3224
3223
  return true;
3225
3224
  }
3226
3225
  return rules.some((rule) => {
3227
- return Validator.validatePermittedRule(node, rule);
3226
+ return this.validatePermittedRule(node, rule);
3228
3227
  });
3229
3228
  }
3230
3229
  /**
@@ -3251,9 +3250,7 @@ class Validator {
3251
3250
  const [, category, quantifier] = /^(@?.*?)([*?]?)$/.exec(rule);
3252
3251
  const limit = category && quantifier && parseQuantifier(quantifier);
3253
3252
  if (limit) {
3254
- const siblings = children.filter(
3255
- (cur) => Validator.validatePermittedCategory(cur, rule, true)
3256
- );
3253
+ const siblings = children.filter((cur) => this.validatePermittedCategory(cur, rule, true));
3257
3254
  if (siblings.length > limit) {
3258
3255
  for (const child of siblings.slice(limit)) {
3259
3256
  cb(child, category);
@@ -3284,12 +3281,12 @@ class Validator {
3284
3281
  let prev = null;
3285
3282
  for (const node of children) {
3286
3283
  const old = i;
3287
- while (rules[i] && !Validator.validatePermittedCategory(node, rules[i], true)) {
3284
+ while (rules[i] && !this.validatePermittedCategory(node, rules[i], true)) {
3288
3285
  i++;
3289
3286
  }
3290
3287
  if (i >= rules.length) {
3291
- const orderSpecified = rules.find(
3292
- (cur) => Validator.validatePermittedCategory(node, cur, true)
3288
+ const orderSpecified = rules.some(
3289
+ (cur) => this.validatePermittedCategory(node, cur, true)
3293
3290
  );
3294
3291
  if (orderSpecified) {
3295
3292
  cb(node, prev);
@@ -3328,7 +3325,7 @@ class Validator {
3328
3325
  }
3329
3326
  return rules.filter((tagName) => {
3330
3327
  const haveMatchingChild = node.childElements.some(
3331
- (child) => Validator.validatePermittedCategory(child, tagName, false)
3328
+ (child) => this.validatePermittedCategory(child, tagName, false)
3332
3329
  );
3333
3330
  return !haveMatchingChild;
3334
3331
  });
@@ -3375,36 +3372,35 @@ class Validator {
3375
3372
  return rule.enum.some((entry) => {
3376
3373
  if (typeof entry === "string") {
3377
3374
  return caseInsensitiveValue === entry;
3378
- } else if (entry instanceof RegExp) {
3375
+ }
3376
+ if (entry instanceof RegExp) {
3379
3377
  return entry.test(value);
3380
- } else if (entry.pattern instanceof RegExp) {
3378
+ }
3379
+ if (entry.pattern instanceof RegExp) {
3381
3380
  return entry.pattern.test(value);
3382
- } else {
3383
- throw new TypeError("RegExp was not precompiled when it should have been");
3384
3381
  }
3382
+ throw new TypeError("RegExp was not precompiled when it should have been");
3385
3383
  });
3386
3384
  }
3387
3385
  static validatePermittedRule(node, rule, isExclude = false) {
3388
3386
  if (typeof rule === "string") {
3389
- return Validator.validatePermittedCategory(node, rule, !isExclude);
3390
- } else if (Array.isArray(rule)) {
3387
+ return this.validatePermittedCategory(node, rule, !isExclude);
3388
+ }
3389
+ if (Array.isArray(rule)) {
3391
3390
  return rule.every((inner) => {
3392
- return Validator.validatePermittedRule(node, inner, isExclude);
3391
+ return this.validatePermittedRule(node, inner, isExclude);
3393
3392
  });
3394
- } else {
3395
- validateKeys(rule);
3396
- if (rule.exclude) {
3397
- if (Array.isArray(rule.exclude)) {
3398
- return !rule.exclude.some((inner) => {
3399
- return Validator.validatePermittedRule(node, inner, true);
3400
- });
3401
- } else {
3402
- return !Validator.validatePermittedRule(node, rule.exclude, true);
3403
- }
3404
- } else {
3405
- 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
+ });
3406
3400
  }
3401
+ return !this.validatePermittedRule(node, rule.exclude, true);
3407
3402
  }
3403
+ return true;
3408
3404
  }
3409
3405
  /**
3410
3406
  * Validate node against a content category.
@@ -3420,7 +3416,7 @@ class Validator {
3420
3416
  */
3421
3417
  /* eslint-disable-next-line complexity -- rule does not like switch */
3422
3418
  static validatePermittedCategory(node, category, defaultMatch) {
3423
- const [, rawCategory] = /^(@?.*?)([*?]?)$/.exec(category);
3419
+ const [, rawCategory] = /^(@?.*?)[*?]?$/.exec(category);
3424
3420
  if (!rawCategory.startsWith("@")) {
3425
3421
  return node.matches(rawCategory);
3426
3422
  }
@@ -3453,10 +3449,11 @@ class Validator {
3453
3449
  }
3454
3450
  function validateKeys(rule) {
3455
3451
  for (const key of Object.keys(rule)) {
3456
- if (!allowedKeys.has(key)) {
3457
- const str = JSON.stringify(rule);
3458
- throw new Error(`Permitted rule "${str}" contains unknown property "${key}"`);
3452
+ if (allowedKeys.has(key)) {
3453
+ continue;
3459
3454
  }
3455
+ const str = JSON.stringify(rule);
3456
+ throw new Error(`Permitted rule "${str}" contains unknown property "${key}"`);
3460
3457
  }
3461
3458
  }
3462
3459
  function parseQuantifier(quantifier) {
@@ -3523,9 +3520,8 @@ function ariaNaming(element) {
3523
3520
  if (role) {
3524
3521
  if (role instanceof DynamicValue) {
3525
3522
  return element.cacheSet(cacheKey, defaultValue);
3526
- } else {
3527
- return element.cacheSet(cacheKey, byRole(role));
3528
3523
  }
3524
+ return element.cacheSet(cacheKey, byRole(role));
3529
3525
  }
3530
3526
  const meta = element.meta;
3531
3527
  if (!meta) {
@@ -3710,9 +3706,8 @@ function isPresentation(node) {
3710
3706
  const role = node.getAttribute("role");
3711
3707
  if (role && (role.value === "presentation" || role.value === "none")) {
3712
3708
  return node.cacheSet(ROLE_PRESENTATION_CACHE, true);
3713
- } else {
3714
- return node.cacheSet(ROLE_PRESENTATION_CACHE, false);
3715
3709
  }
3710
+ return node.cacheSet(ROLE_PRESENTATION_CACHE, false);
3716
3711
  }
3717
3712
 
3718
3713
  const cachePrefix = classifyNodeText.name;
@@ -3730,13 +3725,14 @@ function getCachekey(options) {
3730
3725
  const { accessible = false, ignoreHiddenRoot = false } = options;
3731
3726
  if (accessible && ignoreHiddenRoot) {
3732
3727
  return IGNORE_HIDDEN_ROOT_A11Y_CACHE_KEY;
3733
- } else if (ignoreHiddenRoot) {
3728
+ }
3729
+ if (ignoreHiddenRoot) {
3734
3730
  return IGNORE_HIDDEN_ROOT_HTML_CACHE_KEY;
3735
- } else if (accessible) {
3731
+ }
3732
+ if (accessible) {
3736
3733
  return A11Y_CACHE_KEY;
3737
- } else {
3738
- return HTML_CACHE_KEY;
3739
3734
  }
3735
+ return HTML_CACHE_KEY;
3740
3736
  }
3741
3737
  function isSpecialEmpty(node) {
3742
3738
  return node.is("select") || node.is("textarea");
@@ -3768,7 +3764,7 @@ function classifyNodeText(node, options = {}) {
3768
3764
  }
3769
3765
  function findTextNodes(node, options) {
3770
3766
  const { accessible = false } = options;
3771
- let text = [];
3767
+ const text = [];
3772
3768
  for (const child of node.childNodes) {
3773
3769
  if (isTextNode(child)) {
3774
3770
  text.push(child);
@@ -3779,7 +3775,7 @@ function findTextNodes(node, options) {
3779
3775
  if (accessible && isAriaHidden(child, true).bySelf) {
3780
3776
  continue;
3781
3777
  }
3782
- text = text.concat(findTextNodes(child, options));
3778
+ text.push(...findTextNodes(child, options));
3783
3779
  }
3784
3780
  }
3785
3781
  return text;
@@ -3840,14 +3836,17 @@ function format(value, quote = false) {
3840
3836
  return String(value);
3841
3837
  }
3842
3838
  function interpolate(text, data) {
3843
- return text.replaceAll(/{{\s*([^\s{}]+)\s*}}/g, (match, key) => {
3839
+ return text.replaceAll(/\{\{\s*([^\s{}]+)\s*\}\}/g, (match, key) => {
3844
3840
  return data[key] !== void 0 ? format(data[key]) : match;
3845
3841
  });
3846
3842
  }
3847
3843
 
3848
- const ajv$1 = new Ajv__default.default({ strict: true, strictTuples: true, strictTypes: true });
3849
- ajv$1.addMetaSchema(ajvSchemaDraft);
3850
- 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
+ })();
3851
3850
  function getSchemaValidator(ruleId, properties) {
3852
3851
  const $id = `rule/${ruleId}`;
3853
3852
  const cached = ajv$1.getSchema($id);
@@ -3868,10 +3867,9 @@ function isErrorDescriptor(value) {
3868
3867
  function unpackErrorDescriptor(value) {
3869
3868
  if (isErrorDescriptor(value)) {
3870
3869
  return value[0];
3871
- } else {
3872
- const [node, message, location, context] = value;
3873
- return { node, message, location, context };
3874
3870
  }
3871
+ const [node, message, location, context] = value;
3872
+ return { node, message, location, context };
3875
3873
  }
3876
3874
  class Rule {
3877
3875
  reporter;
@@ -4077,17 +4075,18 @@ class Rule {
4077
4075
  const callback = args.pop();
4078
4076
  const filter = args.pop() ?? (() => true);
4079
4077
  return this.parser.on(event, (_event, data) => {
4080
- if (this.isEnabled() && filter(data)) {
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);
4090
- }
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);
4091
4090
  }
4092
4091
  });
4093
4092
  }
@@ -4157,7 +4156,7 @@ class Rule {
4157
4156
  * @public
4158
4157
  * @virtual
4159
4158
  * @param context - Error context given by a reported error.
4160
- * @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
4161
4160
  * additional documentation is available.
4162
4161
  */
4163
4162
  documentation(_context) {
@@ -4196,7 +4195,7 @@ function parseAllow(value) {
4196
4195
  };
4197
4196
  }
4198
4197
  function matchList(value, list) {
4199
- if (list.include && !list.include.some((it) => it.test(value))) {
4198
+ if (list.include?.every((it) => !it.test(value))) {
4200
4199
  return false;
4201
4200
  }
4202
4201
  if (list.exclude?.some((it) => it.test(value))) {
@@ -4281,10 +4280,10 @@ class AllowedLinks extends Rule {
4281
4280
  return Boolean(attr && attr === key);
4282
4281
  }
4283
4282
  getStyle(value) {
4284
- if (/^([a-z]+:)?\/\//g.test(value)) {
4283
+ if (/^(?:[a-z]+:)?\/\//.test(value)) {
4285
4284
  return "external" /* EXTERNAL */;
4286
4285
  }
4287
- switch (value[0]) {
4286
+ switch (value.at(0)) {
4288
4287
  /* /foo/bar */
4289
4288
  case "/":
4290
4289
  return "absolute" /* ABSOLUTE */;
@@ -4303,7 +4302,8 @@ class AllowedLinks extends Rule {
4303
4302
  const { allowAbsolute } = this;
4304
4303
  if (allowAbsolute === true) {
4305
4304
  return;
4306
- } else if (allowAbsolute === false) {
4305
+ }
4306
+ if (allowAbsolute === false) {
4307
4307
  this.report(
4308
4308
  event.target,
4309
4309
  "Link destination must not be absolute url",
@@ -4323,7 +4323,8 @@ class AllowedLinks extends Rule {
4323
4323
  const { allowExternal } = this;
4324
4324
  if (allowExternal === true) {
4325
4325
  return;
4326
- } else if (allowExternal === false) {
4326
+ }
4327
+ if (allowExternal === false) {
4327
4328
  this.report(
4328
4329
  event.target,
4329
4330
  "Link destination must not be external url",
@@ -4343,7 +4344,8 @@ class AllowedLinks extends Rule {
4343
4344
  const { allowRelative } = this;
4344
4345
  if (allowRelative === true) {
4345
4346
  return false;
4346
- } else if (allowRelative === false) {
4347
+ }
4348
+ if (allowRelative === false) {
4347
4349
  this.report(
4348
4350
  event.target,
4349
4351
  "Link destination must not be relative url",
@@ -4351,7 +4353,8 @@ class AllowedLinks extends Rule {
4351
4353
  style
4352
4354
  );
4353
4355
  return true;
4354
- } else if (!matchList(target, allowRelative)) {
4356
+ }
4357
+ if (!matchList(target, allowRelative)) {
4355
4358
  this.report(
4356
4359
  event.target,
4357
4360
  "Relative link to this destination is not allowed by current configuration",
@@ -4366,7 +4369,8 @@ class AllowedLinks extends Rule {
4366
4369
  const { allowBase } = this.options;
4367
4370
  if (this.handleRelativePath(target, event, style)) {
4368
4371
  return;
4369
- } else if (!allowBase) {
4372
+ }
4373
+ if (!allowBase) {
4370
4374
  this.report(
4371
4375
  event.target,
4372
4376
  "Relative links must be relative to current folder",
@@ -4584,12 +4588,11 @@ class AriaLabelMisuse extends Rule {
4584
4588
  ].join("\n"),
4585
4589
  url
4586
4590
  };
4587
- } else {
4588
- return {
4589
- description: [`\`${context.attr}\` can only be used on:`, "", ...lines].join("\n"),
4590
- url
4591
- };
4592
4591
  }
4592
+ return {
4593
+ description: [`\`${context.attr}\` can only be used on:`, "", ...lines].join("\n"),
4594
+ url
4595
+ };
4593
4596
  }
4594
4597
  setup() {
4595
4598
  this.on("dom:ready", (event) => {
@@ -4647,6 +4650,7 @@ class AriaLabelMisuse extends Rule {
4647
4650
  }
4648
4651
 
4649
4652
  class ConfigError extends UserError {
4653
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
4650
4654
  constructor(message, nested) {
4651
4655
  super(message, nested);
4652
4656
  this.name = "ConfigError";
@@ -4767,9 +4771,8 @@ class AttrCase extends Rule {
4767
4771
  isIgnored(node) {
4768
4772
  if (this.options.ignoreForeign) {
4769
4773
  return Boolean(node.meta?.foreign);
4770
- } else {
4771
- return false;
4772
4774
  }
4775
+ return false;
4773
4776
  }
4774
4777
  }
4775
4778
 
@@ -4816,14 +4819,21 @@ class Context {
4816
4819
  return JSON.stringify(this.string.length > n ? `${this.string.slice(0, 10)}...` : this.string);
4817
4820
  }
4818
4821
  consume(n, state) {
4819
- let consumed = this.string.slice(0, n);
4820
- let offset;
4821
- while ((offset = consumed.indexOf("\n")) >= 0) {
4822
- this.line++;
4823
- this.column = 1;
4824
- consumed = consumed.slice(offset + 1);
4825
- }
4826
- this.column += consumed.length;
4822
+ let lastNewline = -1;
4823
+ let newlines = 0;
4824
+ for (let i = 0; i < n; i++) {
4825
+ if (this.string[i] !== "\n") {
4826
+ continue;
4827
+ }
4828
+ newlines++;
4829
+ lastNewline = i;
4830
+ }
4831
+ if (newlines > 0) {
4832
+ this.line += newlines;
4833
+ this.column = n - lastNewline;
4834
+ } else {
4835
+ this.column += n;
4836
+ }
4827
4837
  this.offset += n;
4828
4838
  this.string = this.string.slice(n);
4829
4839
  this.state = state;
@@ -4878,28 +4888,29 @@ const MATCH_DOCTYPE_CLOSE = /^>/;
4878
4888
  const MATCH_XML_TAG = /^<\?xml.*?\?>\s+/;
4879
4889
  const MATCH_TAG_OPEN = /^<(\/?)([\w:\-]+)/;
4880
4890
  const MATCH_TAG_CLOSE = /^\/?>/;
4881
- const MATCH_TEXT = /^[^]*?(?=(?:[\t ]*(?:\r\n|\r|\n)|<[^ ]|$))/;
4891
+ const MATCH_TEXT = /^[\s\S]*?(?=[\t ]*(?:\r\n|\r|\n)|<[^ ]|$)/;
4882
4892
  const MATCH_TEMPLATING = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)/s;
4883
- const MATCH_TAG_LOOKAHEAD = /^[^]*?(?=<|$)/;
4893
+ const MATCH_TAG_LOOKAHEAD = /^[\s\S]*?(?=<|$)/;
4884
4894
  const MATCH_ATTR_START = /^([^\t\n\f\r "'/<=>]+)/;
4885
- const MATCH_ATTR_SINGLE = /^(\s*=\s*)'([^']*?)(')/;
4886
- const MATCH_ATTR_DOUBLE = /^(\s*=\s*)"([^"]*?)(")/;
4895
+ const MATCH_ATTR_SINGLE = /^(\s*=\s*)'([^']*)(')/;
4896
+ const MATCH_ATTR_DOUBLE = /^(\s*=\s*)"([^"]*)(")/;
4887
4897
  const MATCH_ATTR_UNQUOTED = /^(\s*=\s*)([^\t\n\f\r "'<>][^\t\n\f\r <>]*)/;
4888
4898
  const MATCH_CDATA_BEGIN = /^<!\[CDATA\[/;
4889
- const MATCH_CDATA_END = /^[^]*?]]>/;
4890
- const MATCH_SCRIPT_DATA = /^[^]*?(?=<\/script)/;
4899
+ const MATCH_CDATA_END = /^[\s\S]*?\]\]>/;
4900
+ const MATCH_SCRIPT_DATA = /^[\s\S]*?(?=<\/script)/;
4891
4901
  const MATCH_SCRIPT_END = /^<(\/)(script)/;
4892
- const MATCH_STYLE_DATA = /^[^]*?(?=<\/style)/;
4902
+ const MATCH_STYLE_DATA = /^[\s\S]*?(?=<\/style)/;
4893
4903
  const MATCH_STYLE_END = /^<(\/)(style)/;
4894
- const MATCH_TEXTAREA_DATA = /^[^]*?(?=<\/textarea)/;
4904
+ const MATCH_TEXTAREA_DATA = /^[\s\S]*?(?=<\/textarea)/;
4895
4905
  const MATCH_TEXTAREA_END = /^<(\/)(textarea)/;
4896
- const MATCH_TITLE_DATA = /^[^]*?(?=<\/title)/;
4906
+ const MATCH_TITLE_DATA = /^[\s\S]*?(?=<\/title)/;
4897
4907
  const MATCH_TITLE_END = /^<(\/)(title)/;
4898
- const MATCH_DIRECTIVE = /^(<!--\s*\[?)(html-validate-)([\da-z-]+)(\s*)(.*?)(]?\s*-->)/;
4899
- const MATCH_COMMENT = /^<!--([^]*?)-->/;
4900
- const MATCH_CONDITIONAL = /^<!\[([^\]]*?)]>/;
4908
+ const MATCH_DIRECTIVE = /^(<!--\s*\[?)(html-validate-)([\da-z-]+)(\s*)(.*?)(\]?\s*-->)/;
4909
+ const MATCH_COMMENT = /^<!--([\s\S]*?)-->/;
4910
+ const MATCH_CONDITIONAL = /^<!\[([^\]]*)\]>/;
4901
4911
  class InvalidTokenError extends Error {
4902
4912
  location;
4913
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
4903
4914
  constructor(location, message) {
4904
4915
  super(message);
4905
4916
  this.name = "InvalidTokenError";
@@ -4983,9 +4994,8 @@ class Lexer {
4983
4994
  evalNextState(nextState, token) {
4984
4995
  if (typeof nextState === "function") {
4985
4996
  return nextState(token);
4986
- } else {
4987
- return nextState;
4988
4997
  }
4998
+ return nextState;
4989
4999
  }
4990
5000
  *match(context, tests, error) {
4991
5001
  const n = tests.length;
@@ -5072,27 +5082,26 @@ class Lexer {
5072
5082
  case ContentModel.SCRIPT:
5073
5083
  if (selfClosed) {
5074
5084
  return State.SCRIPT;
5075
- } else {
5076
- return State.TEXT;
5077
5085
  }
5086
+ return State.TEXT;
5087
+ /* <script/> (not legal but handle it anyway so the lexer doesn't choke on it) */
5078
5088
  case ContentModel.STYLE:
5079
5089
  if (selfClosed) {
5080
5090
  return State.STYLE;
5081
- } else {
5082
- return State.TEXT;
5083
5091
  }
5092
+ return State.TEXT;
5093
+ /* <style/> */
5084
5094
  case ContentModel.TEXTAREA:
5085
5095
  if (selfClosed) {
5086
5096
  return State.TEXTAREA;
5087
- } else {
5088
- return State.TEXT;
5089
5097
  }
5098
+ return State.TEXT;
5099
+ /* <textarea/> */
5090
5100
  case ContentModel.TITLE:
5091
5101
  if (selfClosed) {
5092
5102
  return State.TITLE;
5093
- } else {
5094
- return State.TEXT;
5095
5103
  }
5104
+ return State.TEXT;
5096
5105
  }
5097
5106
  }
5098
5107
  yield* this.match(
@@ -5179,7 +5188,7 @@ class Lexer {
5179
5188
  }
5180
5189
  }
5181
5190
 
5182
- const whitespace = /(\s+)/;
5191
+ const whitespace = /\s+/;
5183
5192
  class AttrDelimiter extends Rule {
5184
5193
  documentation() {
5185
5194
  return {
@@ -5211,17 +5220,15 @@ const defaults$y = {
5211
5220
  function generateRegexp(pattern) {
5212
5221
  if (Array.isArray(pattern)) {
5213
5222
  return new RegExp(`^(${pattern.join("|")})$`, "i");
5214
- } else {
5215
- return new RegExp(`^${pattern}$`, "i");
5216
5223
  }
5224
+ return new RegExp(`^${pattern}$`, "i");
5217
5225
  }
5218
5226
  function generateMessage(name, pattern) {
5219
5227
  if (Array.isArray(pattern)) {
5220
5228
  const patterns = pattern.map((it) => `/${it}/`).join(", ");
5221
5229
  return `Attribute "${name}" should match one of [${patterns}]`;
5222
- } else {
5223
- return `Attribute "${name}" should match /${pattern}/`;
5224
5230
  }
5231
+ return `Attribute "${name}" should match /${pattern}/`;
5225
5232
  }
5226
5233
  function generateDescription(name, pattern) {
5227
5234
  if (Array.isArray(pattern)) {
@@ -5230,9 +5237,8 @@ function generateDescription(name, pattern) {
5230
5237
  "",
5231
5238
  ...pattern.map((it) => `- \`/${it}/\``)
5232
5239
  ].join("\n");
5233
- } else {
5234
- return `Attribute "${name}" should match the regular expression \`/${pattern}/\``;
5235
5240
  }
5241
+ return `Attribute "${name}" should match the regular expression \`/${pattern}/\``;
5236
5242
  }
5237
5243
  class AttrPattern extends Rule {
5238
5244
  pattern;
@@ -5278,9 +5284,8 @@ class AttrPattern extends Rule {
5278
5284
  isIgnored(node) {
5279
5285
  if (this.options.ignoreForeign) {
5280
5286
  return Boolean(node.meta?.foreign);
5281
- } else {
5282
- return false;
5283
5287
  }
5288
+ return false;
5284
5289
  }
5285
5290
  }
5286
5291
 
@@ -5391,9 +5396,8 @@ class AttrQuotes extends Rule {
5391
5396
  resolveQuotemark(value, style) {
5392
5397
  if (style === "auto" /* AUTO_QUOTE */) {
5393
5398
  return value.includes('"') ? "'" : '"';
5394
- } else {
5395
- return style;
5396
5399
  }
5400
+ return style;
5397
5401
  }
5398
5402
  }
5399
5403
  function parseStyle$3(style) {
@@ -5451,11 +5455,11 @@ class AttributeAllowedValues extends Rule {
5451
5455
  const allowedList = allowed.enum.map((value2) => {
5452
5456
  if (typeof value2 === "string") {
5453
5457
  return `- \`"${value2}"\``;
5454
- } else if (value2 instanceof RegExp) {
5458
+ }
5459
+ if (value2 instanceof RegExp) {
5455
5460
  return `- \`${value2.toString()}\``;
5456
- } else {
5457
- return `- ${value2.name}`;
5458
5461
  }
5462
+ return `- ${value2.name}`;
5459
5463
  });
5460
5464
  docs.description = [
5461
5465
  `The \`<${element}>\` element does not allow the attribute \`${attribute}\` to have the value \`"${value}"\`.`,
@@ -5499,9 +5503,8 @@ class AttributeAllowedValues extends Rule {
5499
5503
  const { key, value } = attr;
5500
5504
  if (value !== null) {
5501
5505
  return `Attribute "${key}" has invalid value "${value.toString()}"`;
5502
- } else {
5503
- return `Attribute "${key}" is missing value`;
5504
5506
  }
5507
+ return `Attribute "${key}" is missing value`;
5505
5508
  }
5506
5509
  getLocation(attr) {
5507
5510
  return attr.valueLocation ?? attr.keyLocation;
@@ -5788,10 +5791,10 @@ class AutocompletePassword extends Rule {
5788
5791
  const tokens = new DOMTokenList(raw, autocomplete.valueLocation);
5789
5792
  const index = tokens.findIndex((token) => !isGroupingToken(token));
5790
5793
  const value = tokens.item(index);
5791
- const location = tokens.location(index);
5792
5794
  if (!value) {
5793
5795
  return;
5794
5796
  }
5797
+ const location = tokens.location(index);
5795
5798
  if (value === "off") {
5796
5799
  const context = { kind: "off" };
5797
5800
  this.report({
@@ -5876,9 +5879,8 @@ function parsePattern(pattern) {
5876
5879
  function toArray$2(value) {
5877
5880
  if (Array.isArray(value)) {
5878
5881
  return value;
5879
- } else {
5880
- return [value];
5881
5882
  }
5883
+ return [value];
5882
5884
  }
5883
5885
  function validateAllowedPatterns(patterns, allowedPatterns, ruleId) {
5884
5886
  const extraneous = patterns.filter(isNamedPattern).filter((p) => !allowedPatterns.has(p));
@@ -5964,7 +5966,7 @@ class ClassPattern extends BasePatternRule {
5964
5966
  });
5965
5967
  }
5966
5968
  static schema() {
5967
- return BasePatternRule.schema();
5969
+ return super.schema();
5968
5970
  }
5969
5971
  documentation(context) {
5970
5972
  return {
@@ -6045,10 +6047,10 @@ class CloseOrder extends Rule {
6045
6047
  });
6046
6048
  this.on("tag:end", (event) => {
6047
6049
  const current = event.target;
6048
- const active = event.previous;
6049
6050
  if (current) {
6050
6051
  return;
6051
6052
  }
6053
+ const active = event.previous;
6052
6054
  for (const ancestor of ancestors(active)) {
6053
6055
  if (ancestor.isRootElement() || reported.has(ancestor.unique)) {
6054
6056
  continue;
@@ -6059,13 +6061,13 @@ class CloseOrder extends Rule {
6059
6061
  });
6060
6062
  this.on("tag:end", (event) => {
6061
6063
  const current = event.target;
6062
- const active = event.previous;
6063
6064
  if (!current) {
6064
6065
  return;
6065
6066
  }
6066
6067
  if (current.voidElement) {
6067
6068
  return;
6068
6069
  }
6070
+ const active = event.previous;
6069
6071
  if (active.closed === Node.CLOSED_IMPLICIT_CLOSED) {
6070
6072
  return;
6071
6073
  }
@@ -6160,7 +6162,7 @@ class Deprecated extends Rule {
6160
6162
  text.push(context.documentation);
6161
6163
  }
6162
6164
  const doc = {
6163
- 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"),
6164
6166
  url: "https://html-validate.org/rules/deprecated.html"
6165
6167
  };
6166
6168
  return doc;
@@ -6559,7 +6561,7 @@ class ElementName extends Rule {
6559
6561
  ];
6560
6562
  }
6561
6563
  setup() {
6562
- const xmlns = /^(.+):.+$/;
6564
+ const xmlns = /^[^:]+:.+$/;
6563
6565
  this.on("tag:start", (event) => {
6564
6566
  const target = event.target;
6565
6567
  const tagName = target.tagName;
@@ -6598,13 +6600,12 @@ function isNativeTemplate(node) {
6598
6600
  function getTransparentChildren(node, transparent) {
6599
6601
  if (typeof transparent === "boolean") {
6600
6602
  return node.childElements;
6601
- } else {
6602
- return node.childElements.filter((it) => {
6603
- return transparent.some((category) => {
6604
- return Validator.validatePermittedCategory(it, category, false);
6605
- });
6606
- });
6607
6603
  }
6604
+ return node.childElements.filter((it) => {
6605
+ return transparent.some((category) => {
6606
+ return Validator.validatePermittedCategory(it, category, false);
6607
+ });
6608
+ });
6608
6609
  }
6609
6610
  function getRuleDescription$2(context) {
6610
6611
  switch (context.kind) {
@@ -6636,6 +6637,7 @@ class ElementPermittedContent extends Rule {
6636
6637
  [
6637
6638
  () => this.validatePermittedContent(node, parent),
6638
6639
  () => this.validatePermittedDescendant(node, parent)
6640
+ /* eslint-disable-next-line unicorn/no-unused-array-method-return -- technical debt, should use iterator helpers */
6639
6641
  ].some((fn) => fn());
6640
6642
  });
6641
6643
  });
@@ -6781,14 +6783,12 @@ function getRuleDescription$1(context) {
6781
6783
  const allowed = rules.filter(isCategoryOrTag).map((it) => {
6782
6784
  if (isCategory$1(it)) {
6783
6785
  return `- any ${it.slice(1)} element`;
6784
- } else {
6785
- return `- \`<${it}>\``;
6786
6786
  }
6787
+ return `- \`<${it}>\``;
6787
6788
  });
6788
6789
  return [preamble, "", "Allowed parents one of:", "", ...allowed];
6789
- } else {
6790
- return [preamble];
6791
6790
  }
6791
+ return [preamble];
6792
6792
  }
6793
6793
  function formatMessage$1(node, parent, rules) {
6794
6794
  const nodeName = node.annotatedName;
@@ -6840,7 +6840,7 @@ class ElementPermittedParent extends Rule {
6840
6840
  }
6841
6841
 
6842
6842
  function isTagnameOnly(value) {
6843
- return /^[\dA-Za-z-]+$/.test(value);
6843
+ return /^[\dA-Z-]+$/i.test(value);
6844
6844
  }
6845
6845
  function getRuleDescription(context) {
6846
6846
  const escaped = context.ancestor.map((it) => `\`${it}\``);
@@ -6903,9 +6903,8 @@ function normalizeRequired(element, attr) {
6903
6903
  default:
6904
6904
  return result;
6905
6905
  }
6906
- } else {
6907
- return required ? defaultMessage : false;
6908
6906
  }
6907
+ return required ? defaultMessage : false;
6909
6908
  }
6910
6909
  class ElementRequiredAttributes extends Rule {
6911
6910
  documentation(context) {
@@ -6987,7 +6986,8 @@ const selector = ["h1", "h2", "h3", "h4", "h5", "h6"].join(",");
6987
6986
  function hasImgAltText$1(node) {
6988
6987
  if (node.is("img")) {
6989
6988
  return hasAltText(node);
6990
- } else if (node.is("svg")) {
6989
+ }
6990
+ if (node.is("svg")) {
6991
6991
  return node.textContent.trim() !== "";
6992
6992
  }
6993
6993
  return false;
@@ -7268,21 +7268,19 @@ class FormDupName extends Rule {
7268
7268
  const existing = group.cacheGet(UNIQUE_CACHE_KEY);
7269
7269
  if (existing) {
7270
7270
  return existing;
7271
- } else {
7272
- const elements = /* @__PURE__ */ new Map();
7273
- group.cacheSet(UNIQUE_CACHE_KEY, elements);
7274
- return elements;
7275
7271
  }
7272
+ const elements = /* @__PURE__ */ new Map();
7273
+ group.cacheSet(UNIQUE_CACHE_KEY, elements);
7274
+ return elements;
7276
7275
  }
7277
7276
  getSharedElements(group) {
7278
7277
  const existing = group.cacheGet(SHARED_CACHE_KEY);
7279
7278
  if (existing) {
7280
7279
  return existing;
7281
- } else {
7282
- const elements = /* @__PURE__ */ new Map();
7283
- group.cacheSet(SHARED_CACHE_KEY, elements);
7284
- return elements;
7285
7280
  }
7281
+ const elements = /* @__PURE__ */ new Map();
7282
+ group.cacheSet(SHARED_CACHE_KEY, elements);
7283
+ return elements;
7286
7284
  }
7287
7285
  }
7288
7286
 
@@ -7296,12 +7294,11 @@ function isRelevant$5(event) {
7296
7294
  return Boolean(node.meta?.heading);
7297
7295
  }
7298
7296
  function extractLevel(node) {
7299
- const match = /^[Hh](\d)$/.exec(node.tagName);
7297
+ const match = /^H(\d)$/i.exec(node.tagName);
7300
7298
  if (match) {
7301
- return Number.parseInt(match[1], 10);
7302
- } else {
7303
- return null;
7299
+ return Math.trunc(Number(match[1]));
7304
7300
  }
7301
+ return null;
7305
7302
  }
7306
7303
  function parseMaxInitial(value) {
7307
7304
  if (value === false || value === "any") {
@@ -7311,7 +7308,7 @@ function parseMaxInitial(value) {
7311
7308
  if (!match) {
7312
7309
  return 1;
7313
7310
  }
7314
- return Number.parseInt(match[1], 10);
7311
+ return Math.trunc(Number(match[1]));
7315
7312
  }
7316
7313
  class HeadingLevel extends Rule {
7317
7314
  minInitialRank;
@@ -7578,7 +7575,7 @@ class IdPattern extends BasePatternRule {
7578
7575
  });
7579
7576
  }
7580
7577
  static schema() {
7581
- return BasePatternRule.schema();
7578
+ return super.schema();
7582
7579
  }
7583
7580
  documentation(context) {
7584
7581
  return {
@@ -7800,24 +7797,23 @@ function isHidden(node, context) {
7800
7797
  const { reference } = context;
7801
7798
  if (reference?.isSameNode(node)) {
7802
7799
  return false;
7803
- } else {
7804
- return !inAccessibilityTree(node);
7805
7800
  }
7801
+ return !inAccessibilityTree(node);
7806
7802
  }
7807
7803
  function hasImgAltText(node, context) {
7808
7804
  if (node.is("img")) {
7809
7805
  return hasAltText(node);
7810
- } else if (node.is("svg")) {
7806
+ }
7807
+ if (node.is("svg")) {
7811
7808
  return node.textContent.trim() !== "";
7812
- } else {
7813
- for (const img of node.querySelectorAll("img, svg")) {
7814
- const hasName = hasAccessibleNameImpl(img, context);
7815
- if (hasName) {
7816
- return true;
7817
- }
7809
+ }
7810
+ for (const img of node.querySelectorAll("img, svg")) {
7811
+ const hasName = hasAccessibleNameImpl(img, context);
7812
+ if (hasName) {
7813
+ return true;
7818
7814
  }
7819
- return false;
7820
7815
  }
7816
+ return false;
7821
7817
  }
7822
7818
  function hasLabel(node) {
7823
7819
  const value = node.getAttributeValue("aria-label") ?? "";
@@ -7948,7 +7944,7 @@ class InputMissingLabel extends Rule {
7948
7944
  this.report(elem, `<${elem.tagName}> element has <label> but <label> element is hidden`);
7949
7945
  return;
7950
7946
  }
7951
- if (!labels.some((label) => hasAccessibleName(root, label))) {
7947
+ if (labels.every((label) => !hasAccessibleName(root, label))) {
7952
7948
  this.report(elem, `<${elem.tagName}> element has <label> but <label> has no text`);
7953
7949
  }
7954
7950
  }
@@ -8135,12 +8131,11 @@ function parseContent(text) {
8135
8131
  const match = /^(\d+)(?:\s*;\s*url=(.*))?/i.exec(text);
8136
8132
  if (match) {
8137
8133
  return {
8138
- delay: Number.parseInt(match[1], 10),
8134
+ delay: Math.trunc(Number(match[1])),
8139
8135
  url: match[2]
8140
8136
  };
8141
- } else {
8142
- return null;
8143
8137
  }
8138
+ return null;
8144
8139
  }
8145
8140
 
8146
8141
  class MissingDoctype extends Rule {
@@ -8217,7 +8212,7 @@ class NamePattern extends BasePatternRule {
8217
8212
  });
8218
8213
  }
8219
8214
  static schema() {
8220
- return BasePatternRule.schema();
8215
+ return super.schema();
8221
8216
  }
8222
8217
  documentation(context) {
8223
8218
  return {
@@ -8400,10 +8395,10 @@ class NoDeprecatedAttr extends Rule {
8400
8395
  this.on("attr", (event) => {
8401
8396
  const node = event.target;
8402
8397
  const meta = node.meta;
8403
- const attr = event.key.toLowerCase();
8404
8398
  if (meta === null) {
8405
8399
  return;
8406
8400
  }
8401
+ const attr = event.key.toLowerCase();
8407
8402
  const metaAttribute = meta.attributes[attr];
8408
8403
  if (!metaAttribute) {
8409
8404
  return;
@@ -8437,7 +8432,7 @@ class NoDupAttr extends Rule {
8437
8432
  return;
8438
8433
  }
8439
8434
  const name = event.key.toLowerCase();
8440
- if (name in attr) {
8435
+ if (Object.hasOwn(attr, name)) {
8441
8436
  this.report(event.target, `Attribute "${name}" duplicated`, event.keyLocation);
8442
8437
  }
8443
8438
  attr[event.key] = true;
@@ -8510,10 +8505,9 @@ function getExisting(element, root) {
8510
8505
  const existing = group.cacheGet(CACHE_KEY);
8511
8506
  if (existing) {
8512
8507
  return existing;
8513
- } else {
8514
- const existing2 = /* @__PURE__ */ new Set();
8515
- return group.cacheSet(CACHE_KEY, existing2);
8516
8508
  }
8509
+ const value = /* @__PURE__ */ new Set();
8510
+ return group.cacheSet(CACHE_KEY, value);
8517
8511
  }
8518
8512
 
8519
8513
  function isRelevant$2(event) {
@@ -8784,10 +8778,11 @@ class NoMissingReferences extends Rule {
8784
8778
  }
8785
8779
  }
8786
8780
  validateSingle(document, node, attr, id) {
8787
- if (idMissing(document, id)) {
8788
- const context = { key: attr.key, value: id };
8789
- this.report(node, `Element references missing id "${id}"`, attr.valueLocation, context);
8781
+ if (!idMissing(document, id)) {
8782
+ return;
8790
8783
  }
8784
+ const context = { key: attr.key, value: id };
8785
+ this.report(node, `Element references missing id "${id}"`, attr.valueLocation, context);
8791
8786
  }
8792
8787
  validateList(document, node, attr, values) {
8793
8788
  const parsed = new DOMTokenList(values, attr.valueLocation);
@@ -8827,9 +8822,9 @@ class NoMultipleMain extends Rule {
8827
8822
  const defaults$f = {
8828
8823
  relaxed: false
8829
8824
  };
8830
- const textRegexp = /(<|&(?![\d#A-Za-z]+;))/g;
8831
- const unquotedAttrRegexp = /(["'<=>`]|&(?![\d#A-Za-z]+;))/g;
8832
- const matchTemplate = /^(<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
8825
+ const textRegexp = /(<|&(?![\d#A-Z]+;))/gi;
8826
+ const unquotedAttrRegexp = /(["'<=>`]|&(?![\d#A-Z]+;))/gi;
8827
+ const matchTemplate = /^(?:<%.*?%>|<\?.*?\?>|<\$.*?\$>)$/s;
8833
8828
  const replacementTable = {
8834
8829
  '"': "&quot;",
8835
8830
  "&": "&amp;",
@@ -9061,7 +9056,7 @@ class NoRedundantRole extends Rule {
9061
9056
  }
9062
9057
  }
9063
9058
 
9064
- const xmlns = /^(.+):.+$/;
9059
+ const xmlns = /^[^:]+:.+$/;
9065
9060
  const defaults$d = {
9066
9061
  ignoreForeign: true,
9067
9062
  ignoreXML: true
@@ -9183,11 +9178,11 @@ class NoUnknownAttributes extends Rule {
9183
9178
  this.on("attr", (event) => {
9184
9179
  const node = event.target;
9185
9180
  const meta = node.meta;
9186
- const attr = event.key.toLowerCase();
9187
9181
  if (meta === null) {
9188
9182
  return;
9189
9183
  }
9190
- if (attr in meta.attributes) {
9184
+ const attr = event.key.toLowerCase();
9185
+ if (Object.hasOwn(meta.attributes, attr)) {
9191
9186
  return;
9192
9187
  }
9193
9188
  if (isPatternAttribute(attr, meta.patternAttributes)) {
@@ -9594,7 +9589,7 @@ const defaults$7 = {
9594
9589
  include: null,
9595
9590
  exclude: null
9596
9591
  };
9597
- const crossorigin = new RegExp("^(\\w+://|//)");
9592
+ const crossorigin = /^(?:\w+:\/\/|\/\/)/;
9598
9593
  const supportSri = {
9599
9594
  link: "href",
9600
9595
  script: "src"
@@ -9807,7 +9802,10 @@ function constructRegex(characters) {
9807
9802
  return new RegExp(pattern, "g");
9808
9803
  }
9809
9804
  function getText(node) {
9810
- const match = /^(\s*)(.*)$/.exec(node.textContent);
9805
+ const match = /^(\s*)(\S.*)$/.exec(node.textContent);
9806
+ if (!match) {
9807
+ return [0, ""];
9808
+ }
9811
9809
  const [, leading, text] = match;
9812
9810
  return [leading.length, text.trimEnd()];
9813
9811
  }
@@ -9960,9 +9958,8 @@ function hasDefaultText(node) {
9960
9958
  function isNonEmptyText(node) {
9961
9959
  if (isTextNode(node)) {
9962
9960
  return node.isDynamic || node.textContent.trim() !== "";
9963
- } else {
9964
- return false;
9965
9961
  }
9962
+ return false;
9966
9963
  }
9967
9964
  function haveAccessibleText(node) {
9968
9965
  if (!inAccessibilityTree(node)) {
@@ -10097,15 +10094,14 @@ function getTextFromReference(document, id) {
10097
10094
  const ref = document.querySelector(selector);
10098
10095
  if (ref) {
10099
10096
  return ref.textContent;
10100
- } else {
10101
- return selector;
10102
10097
  }
10098
+ return selector;
10103
10099
  }
10104
10100
  function groupBy(values, callback) {
10105
10101
  const result = {};
10106
10102
  for (const value of values) {
10107
10103
  const key = callback(value);
10108
- if (key in result) {
10104
+ if (Object.hasOwn(result, key)) {
10109
10105
  result[key].push(value);
10110
10106
  } else {
10111
10107
  result[key] = [value];
@@ -10205,7 +10201,7 @@ const defaults$5 = {
10205
10201
  ignoreCase: false,
10206
10202
  requireSemicolon: true
10207
10203
  };
10208
- const regexp$1 = /&(?:[\da-z]+|#x?[\da-f]+)(;|[^\da-z]|$)/gi;
10204
+ const regexp$1 = /&(?:[\da-z]+|#x?[\da-f]+)([^\da-z]|$)/gi;
10209
10205
  const lowercaseEntities = elements.entities.map((it) => it.toLowerCase());
10210
10206
  function isNumerical(entity) {
10211
10207
  return entity.startsWith("&#");
@@ -10284,9 +10280,8 @@ class UnknownCharReference extends Rule {
10284
10280
  get entities() {
10285
10281
  if (this.options.ignoreCase) {
10286
10282
  return lowercaseEntities;
10287
- } else {
10288
- return elements.entities;
10289
10283
  }
10284
+ return elements.entities;
10290
10285
  }
10291
10286
  findCharacterReferences(node, text, location, { isAttribute }) {
10292
10287
  const delimiter = text.search(/[#?]/);
@@ -10652,7 +10647,6 @@ class ValidAutocomplete extends Rule {
10652
10647
  }
10653
10648
  validateControlAutocomplete(node, tokens, keyLocation) {
10654
10649
  const type = node.getAttributeValue("type") ?? "text";
10655
- const mantle = type !== "hidden" ? "expectation" : "anchor";
10656
10650
  if (isDisallowedType(node, type)) {
10657
10651
  const context = {
10658
10652
  msg: 0 /* InvalidAttribute */,
@@ -10667,6 +10661,7 @@ class ValidAutocomplete extends Rule {
10667
10661
  return;
10668
10662
  }
10669
10663
  if (tokens.includes("on") || tokens.includes("off")) {
10664
+ const mantle = type !== "hidden" ? "expectation" : "anchor";
10670
10665
  this.validateOnOff(node, mantle, tokens);
10671
10666
  return;
10672
10667
  }
@@ -10790,44 +10785,46 @@ class ValidAutocomplete extends Rule {
10790
10785
  * Ensure contact token is only used with field names from the second list.
10791
10786
  */
10792
10787
  validateContact(node, tokens, order) {
10793
- if (order.includes("contact") && order.includes("field1")) {
10794
- const a = order.indexOf("field1");
10795
- 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
+ }
10796
10813
  const context = {
10797
- msg: 4 /* InvalidCombination */,
10814
+ msg: 2 /* InvalidOrder */,
10798
10815
  /* eslint-disable @typescript-eslint/no-non-null-assertion -- it must be present of it wouldn't be found */
10799
- first: tokens.item(a),
10800
- second: tokens.item(b)
10816
+ first: tokens.item(i),
10817
+ second: tokens.item(i + 1)
10801
10818
  /* eslint-enable @typescript-eslint/no-non-null-assertion */
10802
10819
  };
10803
10820
  this.report({
10804
10821
  node,
10805
10822
  message: getTerminalMessage(context),
10806
- location: tokens.location(b),
10823
+ location: tokens.location(i + 1),
10807
10824
  context
10808
10825
  });
10809
10826
  }
10810
10827
  }
10811
- validateOrder(node, tokens, order) {
10812
- const indicies = order.map((it) => expectedOrder.indexOf(it));
10813
- for (let i = 0; i < indicies.length - 1; i++) {
10814
- if (indicies[0] > indicies[i + 1]) {
10815
- const context = {
10816
- msg: 2 /* InvalidOrder */,
10817
- /* eslint-disable @typescript-eslint/no-non-null-assertion -- it must be present of it wouldn't be found */
10818
- first: tokens.item(i),
10819
- second: tokens.item(i + 1)
10820
- /* eslint-enable @typescript-eslint/no-non-null-assertion */
10821
- };
10822
- this.report({
10823
- node,
10824
- message: getTerminalMessage(context),
10825
- location: tokens.location(i + 1),
10826
- context
10827
- });
10828
- }
10829
- }
10830
- }
10831
10828
  validateControlGroup(node, tokens, fieldTokens) {
10832
10829
  const numFields = fieldTokens.filter(Boolean).length;
10833
10830
  if (numFields === 0) {
@@ -10919,7 +10916,7 @@ class ValidID extends Rule {
10919
10916
  documentation(context) {
10920
10917
  const { relaxed } = this.options;
10921
10918
  const { kind, id } = context;
10922
- 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());
10923
10920
  const relaxedDescription = relaxed ? [] : [
10924
10921
  " - ID must begin with a letter",
10925
10922
  " - ID must only contain letters, digits, `-` and `_`"
@@ -10957,7 +10954,7 @@ class ValidID extends Rule {
10957
10954
  if (relaxed) {
10958
10955
  return;
10959
10956
  }
10960
- if (/^[^\p{L}]/u.test(value)) {
10957
+ if (new RegExp("^\\P{L}", "u").test(value)) {
10961
10958
  const context = { kind: 3 /* LEADING_CHARACTER */, id: value };
10962
10959
  this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10963
10960
  return;
@@ -11318,7 +11315,7 @@ function isSimpleTable(table) {
11318
11315
  return false;
11319
11316
  }
11320
11317
  const numColumns = cells[0].length;
11321
- if (!cells.every((row) => row.length === numColumns)) {
11318
+ if (cells.some((row) => row.length !== numColumns)) {
11322
11319
  return false;
11323
11320
  }
11324
11321
  const shape = getShape(cells);
@@ -11972,7 +11969,7 @@ class ResolvedConfig {
11972
11969
  }
11973
11970
 
11974
11971
  function haveResolver(key, value) {
11975
- return key in value;
11972
+ return Object.hasOwn(value, key);
11976
11973
  }
11977
11974
  function haveConfigResolver(value) {
11978
11975
  return haveResolver("resolveConfig", value);
@@ -11987,7 +11984,10 @@ function haveTransformerResolver(value) {
11987
11984
  return haveResolver("resolveTransformer", value);
11988
11985
  }
11989
11986
  function resolveConfig(resolvers, id, options) {
11990
- for (const resolver of resolvers.filter(haveConfigResolver)) {
11987
+ for (const resolver of resolvers) {
11988
+ if (!haveConfigResolver(resolver)) {
11989
+ continue;
11990
+ }
11991
11991
  const config = resolver.resolveConfig(id, options);
11992
11992
  if (isThenable(config)) {
11993
11993
  return resolveConfigAsync(resolvers, id, options);
@@ -11999,7 +11999,10 @@ function resolveConfig(resolvers, id, options) {
11999
11999
  throw new UserError(`Failed to load configuration from "${id}"`);
12000
12000
  }
12001
12001
  async function resolveConfigAsync(resolvers, id, options) {
12002
- for (const resolver of resolvers.filter(haveConfigResolver)) {
12002
+ for (const resolver of resolvers) {
12003
+ if (!haveConfigResolver(resolver)) {
12004
+ continue;
12005
+ }
12003
12006
  const config = await resolver.resolveConfig(id, options);
12004
12007
  if (config) {
12005
12008
  return config;
@@ -12008,7 +12011,10 @@ async function resolveConfigAsync(resolvers, id, options) {
12008
12011
  throw new UserError(`Failed to load configuration from "${id}"`);
12009
12012
  }
12010
12013
  function resolveElements(resolvers, id, options) {
12011
- for (const resolver of resolvers.filter(haveElementsResolver)) {
12014
+ for (const resolver of resolvers) {
12015
+ if (!haveElementsResolver(resolver)) {
12016
+ continue;
12017
+ }
12012
12018
  const elements = resolver.resolveElements(id, options);
12013
12019
  if (isThenable(elements)) {
12014
12020
  return resolveElementsAsync(resolvers, id, options);
@@ -12020,7 +12026,10 @@ function resolveElements(resolvers, id, options) {
12020
12026
  throw new UserError(`Failed to load elements from "${id}"`);
12021
12027
  }
12022
12028
  async function resolveElementsAsync(resolvers, id, options) {
12023
- for (const resolver of resolvers.filter(haveElementsResolver)) {
12029
+ for (const resolver of resolvers) {
12030
+ if (!haveElementsResolver(resolver)) {
12031
+ continue;
12032
+ }
12024
12033
  const elements = await resolver.resolveElements(id, options);
12025
12034
  if (elements) {
12026
12035
  return elements;
@@ -12029,7 +12038,10 @@ async function resolveElementsAsync(resolvers, id, options) {
12029
12038
  throw new UserError(`Failed to load elements from "${id}"`);
12030
12039
  }
12031
12040
  function resolvePlugin(resolvers, id, options) {
12032
- for (const resolver of resolvers.filter(havePluginResolver)) {
12041
+ for (const resolver of resolvers) {
12042
+ if (!havePluginResolver(resolver)) {
12043
+ continue;
12044
+ }
12033
12045
  const plugin = resolver.resolvePlugin(id, options);
12034
12046
  if (isThenable(plugin)) {
12035
12047
  return resolvePluginAsync(resolvers, id, options);
@@ -12041,7 +12053,10 @@ function resolvePlugin(resolvers, id, options) {
12041
12053
  throw new UserError(`Failed to load plugin from "${id}"`);
12042
12054
  }
12043
12055
  async function resolvePluginAsync(resolvers, id, options) {
12044
- for (const resolver of resolvers.filter(havePluginResolver)) {
12056
+ for (const resolver of resolvers) {
12057
+ if (!havePluginResolver(resolver)) {
12058
+ continue;
12059
+ }
12045
12060
  const plugin = await resolver.resolvePlugin(id, options);
12046
12061
  if (plugin) {
12047
12062
  return plugin;
@@ -12050,7 +12065,10 @@ async function resolvePluginAsync(resolvers, id, options) {
12050
12065
  throw new UserError(`Failed to load plugin from "${id}"`);
12051
12066
  }
12052
12067
  function resolveTransformer(resolvers, id, options) {
12053
- for (const resolver of resolvers.filter(haveTransformerResolver)) {
12068
+ for (const resolver of resolvers) {
12069
+ if (!haveTransformerResolver(resolver)) {
12070
+ continue;
12071
+ }
12054
12072
  const transformer = resolver.resolveTransformer(id, options);
12055
12073
  if (isThenable(transformer)) {
12056
12074
  return resolveTransformerAsync(resolvers, id, options);
@@ -12062,7 +12080,10 @@ function resolveTransformer(resolvers, id, options) {
12062
12080
  throw new UserError(`Failed to load transformer from "${id}"`);
12063
12081
  }
12064
12082
  async function resolveTransformerAsync(resolvers, id, options) {
12065
- for (const resolver of resolvers.filter(haveTransformerResolver)) {
12083
+ for (const resolver of resolvers) {
12084
+ if (!haveTransformerResolver(resolver)) {
12085
+ continue;
12086
+ }
12066
12087
  const transformer = await resolver.resolveTransformer(id, options);
12067
12088
  if (transformer) {
12068
12089
  return transformer;
@@ -12102,9 +12123,12 @@ function staticResolver(map = {}) {
12102
12123
  };
12103
12124
  }
12104
12125
 
12105
- const ajv = new Ajv__default.default({ strict: true, strictTuples: true, strictTypes: true });
12106
- ajv.addMetaSchema(ajvSchemaDraft);
12107
- 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
+ })();
12108
12132
  const validator = ajv.compile(configurationSchema);
12109
12133
  function overwriteMerge(_a, b) {
12110
12134
  return b;
@@ -12123,18 +12147,16 @@ function mergeInternal(base, rhs) {
12123
12147
  function toArray$1(value) {
12124
12148
  if (Array.isArray(value)) {
12125
12149
  return value;
12126
- } else {
12127
- return [value];
12128
12150
  }
12151
+ return [value];
12129
12152
  }
12130
12153
  function transformerEntries(transform) {
12131
12154
  return Object.entries(transform).map(([pattern, value]) => {
12132
12155
  const regex = new RegExp(pattern);
12133
12156
  if (typeof value === "string") {
12134
12157
  return { kind: "import", pattern: regex, name: value };
12135
- } else {
12136
- return { kind: "function", pattern: regex, function: value };
12137
12158
  }
12159
+ return { kind: "function", pattern: regex, function: value };
12138
12160
  });
12139
12161
  }
12140
12162
  class Config {
@@ -12159,8 +12181,8 @@ class Config {
12159
12181
  * Create configuration from object.
12160
12182
  */
12161
12183
  static fromObject(resolvers, options, filename = null) {
12162
- Config.validate(options, filename);
12163
- return Config.create(resolvers, options);
12184
+ this.validate(options, filename);
12185
+ return this.create(resolvers, options);
12164
12186
  }
12165
12187
  /**
12166
12188
  * Read configuration from filename.
@@ -12174,10 +12196,9 @@ class Config {
12174
12196
  static fromFile(resolvers, filename) {
12175
12197
  const configData = resolveConfig(toArray$1(resolvers), filename, { cache: false });
12176
12198
  if (isThenable(configData)) {
12177
- return configData.then((configData2) => Config.fromObject(resolvers, configData2, filename));
12178
- } else {
12179
- return Config.fromObject(resolvers, configData, filename);
12199
+ return configData.then((configData2) => this.fromObject(resolvers, configData2, filename));
12180
12200
  }
12201
+ return this.fromObject(resolvers, configData, filename);
12181
12202
  }
12182
12203
  /**
12183
12204
  * Validate configuration data.
@@ -12199,8 +12220,8 @@ class Config {
12199
12220
  );
12200
12221
  }
12201
12222
  if (configData.rules) {
12202
- const normalizedRules = Config.getRulesObject(configData.rules);
12203
- for (const [ruleId, [, ruleOptions]] of normalizedRules.entries()) {
12223
+ const normalizedRules = this.getRulesObject(configData.rules);
12224
+ for (const [ruleId, [, ruleOptions]] of normalizedRules) {
12204
12225
  const cls = bundledRules[ruleId];
12205
12226
  const path = `/rules/${ruleId}/1`;
12206
12227
  Rule.validateOptions(cls, ruleId, path, ruleOptions, filename, configData);
@@ -12223,9 +12244,8 @@ class Config {
12223
12244
  return plugins.then((plugins2) => {
12224
12245
  return instance.init(options, plugins2);
12225
12246
  });
12226
- } else {
12227
- return instance.init(options, plugins);
12228
12247
  }
12248
+ return instance.init(options, plugins);
12229
12249
  }
12230
12250
  init(options, plugins) {
12231
12251
  this.plugins = plugins;
@@ -12242,9 +12262,8 @@ class Config {
12242
12262
  const extendedConfig = this.extendConfig(this.config.extends ?? []);
12243
12263
  if (isThenable(extendedConfig)) {
12244
12264
  return extendedConfig.then((extended) => update(extended));
12245
- } else {
12246
- return update(extendedConfig);
12247
12265
  }
12266
+ return update(extendedConfig);
12248
12267
  }
12249
12268
  /**
12250
12269
  * @internal
@@ -12286,12 +12305,11 @@ class Config {
12286
12305
  instance.extendMeta(instance.plugins);
12287
12306
  return instance;
12288
12307
  });
12289
- } else {
12290
- instance.plugins = plugins;
12291
- instance.configurations = instance.loadConfigurations(instance.plugins);
12292
- instance.extendMeta(instance.plugins);
12293
- return instance;
12294
12308
  }
12309
+ instance.plugins = plugins;
12310
+ instance.configurations = instance.loadConfigurations(instance.plugins);
12311
+ instance.extendMeta(instance.plugins);
12312
+ return instance;
12295
12313
  }
12296
12314
  extendConfig(entries) {
12297
12315
  if (entries.length === 0) {
@@ -12347,20 +12365,19 @@ class Config {
12347
12365
  const result = this.getElementsFromEntry(entry);
12348
12366
  if (isThenable(result)) {
12349
12367
  return result.then((result2) => {
12350
- const [obj, filename] = result2;
12351
- metaTable.loadFromObject(obj, filename);
12352
- const next2 = source.shift();
12353
- if (next2) {
12354
- 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);
12355
12373
  }
12356
12374
  });
12357
- } else {
12358
- const [obj, filename] = result;
12359
- metaTable.loadFromObject(obj, filename);
12360
- const next2 = source.shift();
12361
- if (next2) {
12362
- return loadEntry(next2);
12363
- }
12375
+ }
12376
+ const [obj, filename] = result;
12377
+ metaTable.loadFromObject(obj, filename);
12378
+ const next2 = source.shift();
12379
+ if (next2) {
12380
+ return loadEntry(next2);
12364
12381
  }
12365
12382
  };
12366
12383
  const next = source.shift();
@@ -12390,9 +12407,8 @@ class Config {
12390
12407
  return obj.then((obj2) => {
12391
12408
  return [obj2, entry];
12392
12409
  });
12393
- } else {
12394
- return [obj, entry];
12395
12410
  }
12411
+ return [obj, entry];
12396
12412
  } catch (err) {
12397
12413
  const message = err instanceof Error ? err.message : String(err);
12398
12414
  throw new ConfigError(
@@ -12454,7 +12470,7 @@ class Config {
12454
12470
  const loadPlugin = (entry, index) => {
12455
12471
  if (typeof entry !== "string") {
12456
12472
  const plugin = entry;
12457
- plugin.name = plugin.name || `:unnamedPlugin@${String(index + 1)}`;
12473
+ plugin.name ||= `:unnamedPlugin@${String(index + 1)}`;
12458
12474
  plugin.originalName = `:unnamedPlugin@${String(index + 1)}`;
12459
12475
  loaded.push(plugin);
12460
12476
  const next2 = loading.shift();
@@ -12466,22 +12482,21 @@ class Config {
12466
12482
  const plugin = resolvePlugin(this.resolvers, entry, { cache: true });
12467
12483
  if (isThenable(plugin)) {
12468
12484
  return plugin.then((plugin2) => {
12469
- plugin2.name = plugin2.name || entry;
12485
+ plugin2.name ||= entry;
12470
12486
  plugin2.originalName = entry;
12471
12487
  loaded.push(plugin2);
12472
- const next2 = loading.shift();
12473
- if (next2) {
12474
- return loadPlugin(next2, index + 1);
12488
+ const next3 = loading.shift();
12489
+ if (next3) {
12490
+ return loadPlugin(next3, index + 1);
12475
12491
  }
12476
12492
  });
12477
- } else {
12478
- plugin.name = plugin.name || entry;
12479
- plugin.originalName = entry;
12480
- loaded.push(plugin);
12481
- const next2 = loading.shift();
12482
- if (next2) {
12483
- return loadPlugin(next2, index + 1);
12484
- }
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);
12485
12500
  }
12486
12501
  } catch (err) {
12487
12502
  const message = err instanceof Error ? err.message : String(err);
@@ -12507,7 +12522,8 @@ class Config {
12507
12522
  configs.set(name, config);
12508
12523
  }
12509
12524
  for (const plugin of plugins) {
12510
- for (const [name, config] of Object.entries(plugin.configs ?? {})) {
12525
+ const entries = Object.entries(plugin.configs ?? {});
12526
+ for (const [name, config] of entries) {
12511
12527
  if (!config) {
12512
12528
  continue;
12513
12529
  }
@@ -12551,9 +12567,8 @@ class Config {
12551
12567
  return resolveData.then((resolveData2) => {
12552
12568
  return new ResolvedConfig(resolveData2, this.get());
12553
12569
  });
12554
- } else {
12555
- return new ResolvedConfig(resolveData, this.get());
12556
12570
  }
12571
+ return new ResolvedConfig(resolveData, this.get());
12557
12572
  }
12558
12573
  /**
12559
12574
  * Same as [[resolve]] but returns the raw configuration data instead of
@@ -12572,14 +12587,13 @@ class Config {
12572
12587
  transformers: this.transformers
12573
12588
  };
12574
12589
  });
12575
- } else {
12576
- return {
12577
- metaTable,
12578
- plugins: this.getPlugins(),
12579
- rules: this.getRules(),
12580
- transformers: this.transformers
12581
- };
12582
12590
  }
12591
+ return {
12592
+ metaTable,
12593
+ plugins: this.getPlugins(),
12594
+ rules: this.getRules(),
12595
+ transformers: this.transformers
12596
+ };
12583
12597
  }
12584
12598
  }
12585
12599
 
@@ -12623,10 +12637,9 @@ class ConfigLoader {
12623
12637
  this._globalConfig = config2;
12624
12638
  return this._globalConfig;
12625
12639
  });
12626
- } else {
12627
- this._globalConfig = config;
12628
- return this._globalConfig;
12629
12640
  }
12641
+ this._globalConfig = config;
12642
+ return this._globalConfig;
12630
12643
  }
12631
12644
  /**
12632
12645
  * Get the global configuration.
@@ -12708,9 +12721,8 @@ class StaticConfigLoader extends ConfigLoader {
12708
12721
  const override = this.loadFromObject(configOverride ?? {});
12709
12722
  if (isThenable(override)) {
12710
12723
  return override.then((override2) => this._resolveConfig(override2));
12711
- } else {
12712
- return this._resolveConfig(override);
12713
12724
  }
12725
+ return this._resolveConfig(override);
12714
12726
  }
12715
12727
  flushCache() {
12716
12728
  }
@@ -12727,25 +12739,22 @@ class StaticConfigLoader extends ConfigLoader {
12727
12739
  const globalConfig = this.getGlobalConfig();
12728
12740
  if (isThenable(globalConfig)) {
12729
12741
  return globalConfig.then((globalConfig2) => {
12730
- const merged = globalConfig2.merge(this.resolvers, override);
12731
- if (isThenable(merged)) {
12732
- return merged.then((merged2) => {
12733
- return merged2.resolve();
12742
+ const merged2 = globalConfig2.merge(this.resolvers, override);
12743
+ if (isThenable(merged2)) {
12744
+ return merged2.then((merged3) => {
12745
+ return merged3.resolve();
12734
12746
  });
12735
- } else {
12736
- return merged.resolve();
12737
12747
  }
12748
+ return merged2.resolve();
12738
12749
  });
12739
- } else {
12740
- const merged = globalConfig.merge(this.resolvers, override);
12741
- if (isThenable(merged)) {
12742
- return merged.then((merged2) => {
12743
- return merged2.resolve();
12744
- });
12745
- } else {
12746
- return merged.resolve();
12747
- }
12748
12750
  }
12751
+ const merged = globalConfig.merge(this.resolvers, override);
12752
+ if (isThenable(merged)) {
12753
+ return merged.then((merged2) => {
12754
+ return merged2.resolve();
12755
+ });
12756
+ }
12757
+ return merged.resolve();
12749
12758
  }
12750
12759
  }
12751
12760
 
@@ -12832,7 +12841,7 @@ class EventHandler {
12832
12841
  }
12833
12842
 
12834
12843
  const name = "html-validate";
12835
- const version = "11.5.2";
12844
+ const version = "11.5.4";
12836
12845
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
12837
12846
 
12838
12847
  function freeze(src) {
@@ -12870,7 +12879,7 @@ class Reporter {
12870
12879
  for (const report of reports) {
12871
12880
  for (const result of report.results) {
12872
12881
  const key = result.filePath;
12873
- if (key in merged) {
12882
+ if (Object.hasOwn(merged, key)) {
12874
12883
  merged[key].messages = [...merged[key].messages, ...result.messages];
12875
12884
  } else {
12876
12885
  merged[key] = { ...result };
@@ -12894,7 +12903,7 @@ class Reporter {
12894
12903
  */
12895
12904
  add(options) {
12896
12905
  const { rule, message, severity, node, location, context } = options;
12897
- if (!(location.filename in this.result)) {
12906
+ if (!Object.hasOwn(this.result, location.filename)) {
12898
12907
  this.result[location.filename] = [];
12899
12908
  }
12900
12909
  const ruleUrl = rule.documentation(context)?.url;
@@ -12922,7 +12931,7 @@ class Reporter {
12922
12931
  * @internal
12923
12932
  */
12924
12933
  addManual(filename, message) {
12925
- if (!(filename in this.result)) {
12934
+ if (!Object.hasOwn(this.result, filename)) {
12926
12935
  this.result[filename] = [];
12927
12936
  }
12928
12937
  this.result[filename].push(message);
@@ -12933,6 +12942,7 @@ class Reporter {
12933
12942
  save(sources) {
12934
12943
  const report = {
12935
12944
  valid: this.isValid(),
12945
+ /* eslint-disable-next-line unicorn/prefer-object-iterable-methods -- technical debt */
12936
12946
  results: Object.keys(this.result).map((filePath) => {
12937
12947
  const messages = Array.from(this.result[filePath], freeze).toSorted(messageSort);
12938
12948
  const source = (sources ?? []).find((source2) => filePath === source2.filename);
@@ -12997,7 +13007,7 @@ function definePlugin(plugin) {
12997
13007
  return plugin;
12998
13008
  }
12999
13009
 
13000
- const regexp = /<!(?:--)?\[(.*?)](?:--)?>/g;
13010
+ const regexp = /<!(?:--)?\[(.*?)\](?:--)?>/g;
13001
13011
  function* parseConditionalComment(comment, commentLocation) {
13002
13012
  let match;
13003
13013
  while ((match = regexp.exec(comment)) !== null) {
@@ -13014,6 +13024,7 @@ function* parseConditionalComment(comment, commentLocation) {
13014
13024
 
13015
13025
  class ParserError extends Error {
13016
13026
  location;
13027
+ /* eslint-disable-next-line unicorn/custom-error-definition -- technical debt */
13017
13028
  constructor(location, message) {
13018
13029
  super(message);
13019
13030
  this.name = "ParserError";
@@ -13177,9 +13188,8 @@ class Parser {
13177
13188
  const open = !token.data[1];
13178
13189
  if (open) {
13179
13190
  return this.wouldCloseElement(token, active);
13180
- } else {
13181
- return this.closeOptionalEndTag(token, active);
13182
13191
  }
13192
+ return this.closeOptionalEndTag(token, active);
13183
13193
  }
13184
13194
  /**
13185
13195
  * Returns `true` if the element’s end tag may be omitted, either because
@@ -13531,9 +13541,8 @@ class Parser {
13531
13541
  const quote = token.data[3];
13532
13542
  if (quote) {
13533
13543
  return sliceLocation(token.location, 2, -1);
13534
- } else {
13535
- return sliceLocation(token.location, 1);
13536
13544
  }
13545
+ return sliceLocation(token.location, 1);
13537
13546
  }
13538
13547
  /**
13539
13548
  * Take attribute key and value token an returns a new location referring to
@@ -13821,13 +13830,14 @@ class PerformanceTracker {
13821
13830
  */
13822
13831
  getResult() {
13823
13832
  const events = Array.from(
13824
- this.eventData.entries(),
13833
+ this.eventData,
13825
13834
  ([event, { count, time }]) => ({ event, count, time })
13826
13835
  ).toSorted((a, b) => b.time - a.time);
13827
- const rules = Array.from(
13828
- this.ruleData.entries(),
13829
- ([rule, { count, time }]) => ({ rule, count, time })
13830
- ).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);
13831
13841
  return {
13832
13842
  events,
13833
13843
  rules,
@@ -13874,9 +13884,11 @@ function dumpTree(root) {
13874
13884
  return lines;
13875
13885
  }
13876
13886
 
13877
- let blockerCounter = 1;
13887
+ const state = {
13888
+ blockerCounter: 1
13889
+ };
13878
13890
  function createBlocker() {
13879
- const id = blockerCounter++;
13891
+ const id = state.blockerCounter++;
13880
13892
  return id;
13881
13893
  }
13882
13894
 
@@ -14012,9 +14024,8 @@ class Engine {
14012
14024
  const [, options] = ruleData;
14013
14025
  const rule = this.instantiateRule(ruleId, options);
14014
14026
  return rule.documentation(context);
14015
- } else {
14016
- return null;
14017
14027
  }
14028
+ return null;
14018
14029
  }
14019
14030
  /**
14020
14031
  * Create a new parser instance with the current configuration.
@@ -14143,7 +14154,8 @@ class Engine {
14143
14154
  initRules(config) {
14144
14155
  const availableRules = {};
14145
14156
  for (const plugin of config.getPlugins()) {
14146
- for (const [name, rule] of Object.entries(plugin.rules ?? {})) {
14157
+ const entries = Object.entries(plugin.rules ?? {});
14158
+ for (const [name, rule] of entries) {
14147
14159
  if (!rule) {
14148
14160
  continue;
14149
14161
  }
@@ -14171,7 +14183,7 @@ class Engine {
14171
14183
  */
14172
14184
  setupRules(config, parser) {
14173
14185
  const rules = {};
14174
- for (const [ruleId, [severity, options]] of config.getRules().entries()) {
14186
+ for (const [ruleId, [severity, options]] of config.getRules()) {
14175
14187
  rules[ruleId] = this.loadRule(ruleId, config, severity, options, parser, this.report);
14176
14188
  }
14177
14189
  return rules;
@@ -14195,9 +14207,8 @@ class Engine {
14195
14207
  if (this.availableRules[name]) {
14196
14208
  const RuleConstructor = this.availableRules[name];
14197
14209
  return new RuleConstructor(options);
14198
- } else {
14199
- return this.missingRule(name);
14200
14210
  }
14211
+ return this.missingRule(name);
14201
14212
  }
14202
14213
  missingRule(name) {
14203
14214
  return new class MissingRule extends Rule {
@@ -14293,34 +14304,30 @@ function getTransformerFunction(resolvers, name, plugins) {
14293
14304
  validateTransformer(transformer2);
14294
14305
  return transformer2;
14295
14306
  });
14296
- } else {
14297
- validateTransformer(transformer);
14298
- return transformer;
14299
14307
  }
14308
+ validateTransformer(transformer);
14309
+ return transformer;
14300
14310
  } catch (err) {
14301
14311
  if (err instanceof ConfigError) {
14302
14312
  throw new ConfigError(`Failed to load transformer "${name}": ${err.message}`, err);
14303
- } else {
14304
- throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
14305
14313
  }
14314
+ throw new ConfigError(`Failed to load transformer "${name}"`, ensureError(err));
14306
14315
  }
14307
14316
  }
14308
14317
  function getCachedTransformerFunction(cache, resolvers, name, plugins) {
14309
14318
  const cached = cache.get(name);
14310
14319
  if (cached) {
14311
14320
  return cached;
14312
- } else {
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
- } else {
14320
- cache.set(name, transformer);
14321
- return transformer;
14322
- }
14323
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;
14324
14331
  }
14325
14332
 
14326
14333
  function isIterable(value) {
@@ -14336,6 +14343,9 @@ const asyncInSyncTransformError = "Cannot use async transformer from sync functi
14336
14343
  async function transformSource(resolvers, config, source, filename) {
14337
14344
  const { cache } = config;
14338
14345
  const transformer = config.findTransformer(filename ?? source.filename);
14346
+ if (!transformer) {
14347
+ return [source];
14348
+ }
14339
14349
  const context = {
14340
14350
  hasChain(filename2) {
14341
14351
  return config.canTransform(filename2);
@@ -14344,9 +14354,6 @@ async function transformSource(resolvers, config, source, filename) {
14344
14354
  return transformSource(resolvers, config, source2, filename2);
14345
14355
  }
14346
14356
  };
14347
- if (!transformer) {
14348
- return [source];
14349
- }
14350
14357
  const fn = transformer.kind === "import" ? await getCachedTransformerFunction(cache, resolvers, transformer.name, config.getPlugins()) : transformer.function;
14351
14358
  const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14352
14359
  try {
@@ -14365,6 +14372,9 @@ async function transformSource(resolvers, config, source, filename) {
14365
14372
  function transformSourceSync(resolvers, config, source, filename) {
14366
14373
  const { cache } = config;
14367
14374
  const transformer = config.findTransformer(filename ?? source.filename);
14375
+ if (!transformer) {
14376
+ return [source];
14377
+ }
14368
14378
  const context = {
14369
14379
  hasChain(filename2) {
14370
14380
  return config.canTransform(filename2);
@@ -14373,14 +14383,11 @@ function transformSourceSync(resolvers, config, source, filename) {
14373
14383
  return transformSourceSync(resolvers, config, source2, filename2);
14374
14384
  }
14375
14385
  };
14376
- if (!transformer) {
14377
- return [source];
14378
- }
14379
14386
  const fn = transformer.kind === "import" ? getCachedTransformerFunction(cache, resolvers, transformer.name, config.getPlugins()) : transformer.function;
14380
- const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14381
14387
  if (isThenable(fn)) {
14382
14388
  throw new UserError(asyncInSyncTransformError);
14383
14389
  }
14390
+ const name = transformer.kind === "import" ? transformer.name : transformer.function.name;
14384
14391
  try {
14385
14392
  const result = fn.call(context, source);
14386
14393
  if (isThenable(result)) {
@@ -14482,7 +14489,7 @@ function checkstyleFormatter(results) {
14482
14489
  `;
14483
14490
  for (const message of messages) {
14484
14491
  const ruleId = xmlescape(`htmlvalidate.rules.${message.ruleId}`);
14485
- output += " ";
14492
+ output += " ".repeat(4);
14486
14493
  output += [
14487
14494
  `<error line="${xmlescape(message.line)}"`,
14488
14495
  `column="${xmlescape(message.column)}"`,
@@ -14569,9 +14576,8 @@ function codeFrameColumns(rawLines, loc) {
14569
14576
  ].join("");
14570
14577
  }
14571
14578
  return [">", gutter, line.length > 0 ? ` ${line}` : "", markerLine].join("");
14572
- } else {
14573
- return [" ", gutter, line.length > 0 ? ` ${line}` : ""].join("");
14574
14579
  }
14580
+ return [" ", gutter, line.length > 0 ? ` ${line}` : ""].join("");
14575
14581
  }).join("\n");
14576
14582
  }
14577
14583