html-validate 9.4.2-rc.1 → 9.5.0

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 (41) hide show
  1. package/dist/cjs/core-browser.js.map +1 -1
  2. package/dist/cjs/core-nodejs.js +1 -0
  3. package/dist/cjs/core-nodejs.js.map +1 -1
  4. package/dist/cjs/core.js +41 -30
  5. package/dist/cjs/core.js.map +1 -1
  6. package/dist/cjs/elements.js.map +1 -1
  7. package/dist/cjs/html-validate.d.ts +1 -0
  8. package/dist/cjs/html-validate.js.map +1 -1
  9. package/dist/cjs/html5.d.ts +1 -0
  10. package/dist/cjs/jest-worker.d.ts +1 -0
  11. package/dist/cjs/jest-worker.js.map +1 -1
  12. package/dist/cjs/matchers.js.map +1 -1
  13. package/dist/cjs/meta-helper.js +1 -1
  14. package/dist/cjs/meta-helper.js.map +1 -1
  15. package/dist/cjs/package.json +2 -2
  16. package/dist/cjs/test-utils.js +45 -11
  17. package/dist/cjs/test-utils.js.map +7 -1
  18. package/dist/cjs/tsdoc-metadata.json +1 -1
  19. package/dist/cjs/vitest.d.ts +1 -0
  20. package/dist/es/core-browser.js.map +1 -1
  21. package/dist/es/core-nodejs.js +1 -0
  22. package/dist/es/core-nodejs.js.map +1 -1
  23. package/dist/es/core.js +41 -30
  24. package/dist/es/core.js.map +1 -1
  25. package/dist/es/elements.js.map +1 -1
  26. package/dist/es/html-validate.d.ts +1 -0
  27. package/dist/es/html-validate.js.map +1 -1
  28. package/dist/es/html5.d.ts +1 -0
  29. package/dist/es/jest-worker.d.ts +1 -0
  30. package/dist/es/jest-worker.js.map +1 -1
  31. package/dist/es/matchers.js.map +1 -1
  32. package/dist/es/meta-helper.js +1 -1
  33. package/dist/es/meta-helper.js.map +1 -1
  34. package/dist/es/package.json +2 -2
  35. package/dist/es/test-utils.js +7 -4
  36. package/dist/es/test-utils.js.map +7 -1
  37. package/dist/es/vitest.d.ts +1 -0
  38. package/dist/tsdoc-metadata.json +1 -1
  39. package/dist/types/browser.d.ts +6 -8
  40. package/dist/types/index.d.ts +6 -8
  41. package/package.json +2 -2
package/dist/cjs/core.js CHANGED
@@ -1071,6 +1071,7 @@ function migrateAttributes(src) {
1071
1071
  ...Object.keys(src.attributes ?? {}),
1072
1072
  ...src.requiredAttributes ?? [],
1073
1073
  ...src.deprecatedAttributes ?? []
1074
+ /* eslint-disable-next-line sonarjs/no-alphabetical-sort -- not really needed in this case, this is a-z anyway */
1074
1075
  ].sort();
1075
1076
  const entries = keys.map((key) => {
1076
1077
  return [key, migrateSingleAttribute(src, key)];
@@ -1347,7 +1348,7 @@ function expandRegexValue(value) {
1347
1348
  if (value instanceof RegExp) {
1348
1349
  return value;
1349
1350
  }
1350
- const match = value.match(/^\/(.*(?=\/))\/(i?)$/);
1351
+ const match = /^\/(.*(?=\/))\/(i?)$/.exec(value);
1351
1352
  if (match) {
1352
1353
  const [, expr, flags] = match;
1353
1354
  if (expr.startsWith("^") || expr.endsWith("$")) {
@@ -1592,6 +1593,7 @@ class DOMNode {
1592
1593
  * @internal
1593
1594
  */
1594
1595
  unique;
1596
+ /* eslint-disable-next-line sonarjs/use-type-alias -- technical debt */
1595
1597
  cache;
1596
1598
  /**
1597
1599
  * Set of disabled rules for this node.
@@ -1647,6 +1649,11 @@ class DOMNode {
1647
1649
  }
1648
1650
  return value;
1649
1651
  }
1652
+ /**
1653
+ * Remove a value by key from cache.
1654
+ *
1655
+ * @returns `true` if the entry existed and has been removed.
1656
+ */
1650
1657
  cacheRemove(key) {
1651
1658
  if (this.cache) {
1652
1659
  return this.cache.delete(key);
@@ -1654,6 +1661,9 @@ class DOMNode {
1654
1661
  return false;
1655
1662
  }
1656
1663
  }
1664
+ /**
1665
+ * Check if key exists in cache.
1666
+ */
1657
1667
  cacheExists(key) {
1658
1668
  return Boolean(this.cache?.has(key));
1659
1669
  }
@@ -1994,7 +2004,7 @@ class AttributeCondition extends Condition {
1994
2004
  value;
1995
2005
  constructor(attr) {
1996
2006
  super();
1997
- const [, key, op, value] = attr.match(/^(.+?)(?:([~^$*|]?=)"([^"]+?)")?$/);
2007
+ const [, key, op, value] = /^(.+?)(?:([~^$*|]?=)"([^"]+?)")?$/.exec(attr);
1998
2008
  this.key = key;
1999
2009
  this.op = op;
2000
2010
  this.value = value;
@@ -2003,6 +2013,7 @@ class AttributeCondition extends Condition {
2003
2013
  const attr = node.getAttribute(this.key, true);
2004
2014
  return attr.some((cur) => {
2005
2015
  switch (this.op) {
2016
+ /* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- technical debt, the type of op should reflect this case */
2006
2017
  case void 0:
2007
2018
  return true;
2008
2019
  /* attribute exists */
@@ -2019,7 +2030,7 @@ class PseudoClassCondition extends Condition {
2019
2030
  args;
2020
2031
  constructor(pseudoclass, context) {
2021
2032
  super();
2022
- const match = pseudoclass.match(/^([^(]+)(?:\((.*)\))?$/);
2033
+ const match = /^([^(]+)(?:\((.*)\))?$/.exec(pseudoclass);
2023
2034
  if (!match) {
2024
2035
  throw new Error(`Missing pseudo-class after colon in selector pattern "${context}"`);
2025
2036
  }
@@ -2089,7 +2100,7 @@ class Compound {
2089
2100
  selector;
2090
2101
  conditions;
2091
2102
  constructor(pattern) {
2092
- const match = pattern.match(/^([~+\->]?)((?:[*]|[^.#[:]+)?)([^]*)$/);
2103
+ const match = /^([~+\->]?)((?:[*]|[^.#[:]+)?)([^]*)$/.exec(pattern);
2093
2104
  if (!match) {
2094
2105
  throw new Error(`Failed to create selector pattern from "${pattern}"`);
2095
2106
  }
@@ -2157,14 +2168,12 @@ function candidatesFromCombinator(element, combinator) {
2157
2168
  return adjacentSibling(element);
2158
2169
  case Combinator.GENERAL_SIBLING:
2159
2170
  return generalSibling(element);
2171
+ /* istanbul ignore next -- cannot really happen, the selector would be malformed */
2160
2172
  case Combinator.SCOPE:
2161
2173
  return scope(element);
2162
2174
  }
2163
2175
  }
2164
2176
  function matchElement(element, compounds, context) {
2165
- if (compounds.length === 0) {
2166
- return true;
2167
- }
2168
2177
  const last = compounds[compounds.length - 1];
2169
2178
  if (!last.match(element, context)) {
2170
2179
  return false;
@@ -2258,7 +2267,7 @@ function escapeSelectorComponent(text) {
2258
2267
  }
2259
2268
  function generateIdSelector(id) {
2260
2269
  const escaped = escapeSelectorComponent(id);
2261
- return escaped.match(/^\d/) ? `[id="${escaped}"]` : `#${escaped}`;
2270
+ return /^\d/.exec(escaped) ? `[id="${escaped}"]` : `#${escaped}`;
2262
2271
  }
2263
2272
  class Selector {
2264
2273
  pattern;
@@ -3080,7 +3089,7 @@ class Validator {
3080
3089
  if (typeof rule !== "string") {
3081
3090
  return false;
3082
3091
  }
3083
- const [, category, quantifier] = rule.match(/^(@?.*?)([?*]?)$/);
3092
+ const [, category, quantifier] = /^(@?.*?)([?*]?)$/.exec(rule);
3084
3093
  const limit = category && quantifier && parseQuantifier(quantifier);
3085
3094
  if (limit) {
3086
3095
  const siblings = children.filter(
@@ -3248,7 +3257,7 @@ class Validator {
3248
3257
  */
3249
3258
  /* eslint-disable-next-line complexity -- rule does not like switch */
3250
3259
  static validatePermittedCategory(node, category, defaultMatch) {
3251
- const [, rawCategory] = category.match(/^(@?.*?)([?*]?)$/);
3260
+ const [, rawCategory] = /^(@?.*?)([?*]?)$/.exec(category);
3252
3261
  if (!rawCategory.startsWith("@")) {
3253
3262
  return node.tagName === rawCategory;
3254
3263
  }
@@ -3491,7 +3500,7 @@ function escape(value) {
3491
3500
  return JSON.stringify(value);
3492
3501
  }
3493
3502
  function format(value, quote = false) {
3494
- if (value === null) {
3503
+ if (value === null || value === void 0) {
3495
3504
  return "null";
3496
3505
  }
3497
3506
  if (typeof value === "number") {
@@ -3570,7 +3579,7 @@ function compilePattern(pattern) {
3570
3579
  if (cached) {
3571
3580
  return cached;
3572
3581
  }
3573
- const match = pattern.match(/^\/(.*)\/$/);
3582
+ const match = /^\/(.*)\/$/.exec(pattern);
3574
3583
  const regexp = match ? compileRegExpPattern(match[1]) : compileStringPattern(pattern);
3575
3584
  patternCache.set(pattern, regexp);
3576
3585
  return regexp;
@@ -3755,7 +3764,7 @@ function classifyNodeText(node, options = {}) {
3755
3764
  if (text.some((cur) => cur.isDynamic)) {
3756
3765
  return node.cacheSet(cacheKey, 1 /* DYNAMIC_TEXT */);
3757
3766
  }
3758
- if (text.some((cur) => cur.textContent.match(/\S/) !== null)) {
3767
+ if (text.some((cur) => /\S/.exec(cur.textContent) !== null)) {
3759
3768
  return node.cacheSet(cacheKey, 2 /* STATIC_TEXT */);
3760
3769
  }
3761
3770
  return node.cacheSet(cacheKey, 0 /* EMPTY_TEXT */);
@@ -5769,7 +5778,7 @@ class Deprecated extends Rule {
5769
5778
  }
5770
5779
  }
5771
5780
  function prettySource(source) {
5772
- const match = source.match(/html(\d)(\d)?/);
5781
+ const match = /html(\d)(\d)?/.exec(source);
5773
5782
  if (match) {
5774
5783
  const [, ...parts] = match;
5775
5784
  const version = parts.filter(Boolean).join(".");
@@ -6007,7 +6016,7 @@ class ElementName extends Rule {
6007
6016
  if (target.meta) {
6008
6017
  return;
6009
6018
  }
6010
- if (tagName.match(xmlns)) {
6019
+ if (xmlns.exec(tagName)) {
6011
6020
  return;
6012
6021
  }
6013
6022
  if (this.options.whitelist.includes(tagName)) {
@@ -6094,7 +6103,7 @@ class ElementPermittedContent extends Rule {
6094
6103
  }
6095
6104
  validatePermittedDescendant(node, parent) {
6096
6105
  for (let cur = parent; cur && !cur.isRootElement(); cur = /* istanbul ignore next */
6097
- cur?.parent ?? null) {
6106
+ cur.parent ?? null) {
6098
6107
  const meta = cur.meta;
6099
6108
  if (!meta) {
6100
6109
  continue;
@@ -6265,7 +6274,7 @@ class ElementPermittedParent extends Rule {
6265
6274
  }
6266
6275
 
6267
6276
  function isTagnameOnly(value) {
6268
- return Boolean(value.match(/^[a-zA-Z0-9-]+$/));
6277
+ return Boolean(/^[a-zA-Z0-9-]+$/.exec(value));
6269
6278
  }
6270
6279
  function getRuleDescription(context) {
6271
6280
  const escaped = context.ancestor.map((it) => `\`${it}\``);
@@ -6678,7 +6687,7 @@ function isRelevant$5(event) {
6678
6687
  return Boolean(node.meta?.heading);
6679
6688
  }
6680
6689
  function extractLevel(node) {
6681
- const match = node.tagName.match(/^[hH](\d)$/);
6690
+ const match = /^[hH](\d)$/.exec(node.tagName);
6682
6691
  if (match) {
6683
6692
  return parseInt(match[1], 10);
6684
6693
  } else {
@@ -6689,7 +6698,7 @@ function parseMaxInitial(value) {
6689
6698
  if (value === false || value === "any") {
6690
6699
  return 6;
6691
6700
  }
6692
- const match = value.match(/^h(\d)$/);
6701
+ const match = /^h(\d)$/.exec(value);
6693
6702
  if (!match) {
6694
6703
  return 1;
6695
6704
  }
@@ -7346,7 +7355,7 @@ class MetaRefresh extends Rule {
7346
7355
  }
7347
7356
  }
7348
7357
  function parseContent(text) {
7349
- const match = text.match(/^(\d+)(?:\s*;\s*url=(.*))?/i);
7358
+ const match = /^(\d+)(?:\s*;\s*url=(.*))?/i.exec(text);
7350
7359
  if (match) {
7351
7360
  return {
7352
7361
  delay: parseInt(match[1], 10),
@@ -8137,7 +8146,7 @@ class NoRawCharacters extends Rule {
8137
8146
  if (child.nodeType !== NodeType.TEXT_NODE) {
8138
8147
  continue;
8139
8148
  }
8140
- if (child.textContent.match(matchTemplate)) {
8149
+ if (matchTemplate.exec(child.textContent)) {
8141
8150
  continue;
8142
8151
  }
8143
8152
  this.findRawChars(node, child.textContent, child.location, textRegexp);
@@ -8330,7 +8339,7 @@ class NoSelfClosing extends Rule {
8330
8339
  }
8331
8340
  }
8332
8341
  function isRelevant(node, options) {
8333
- if (node.tagName.match(xmlns)) {
8342
+ if (xmlns.exec(node.tagName)) {
8334
8343
  return !options.ignoreXML;
8335
8344
  }
8336
8345
  if (!node.meta) {
@@ -8371,7 +8380,7 @@ class NoTrailingWhitespace extends Rule {
8371
8380
  }
8372
8381
  setup() {
8373
8382
  this.on("whitespace", (event) => {
8374
- if (event.text.match(/^[ \t]+\r?\n$/)) {
8383
+ if (/^[ \t]+\r?\n$/.exec(event.text)) {
8375
8384
  this.report(null, "Trailing whitespace", event.location);
8376
8385
  }
8377
8386
  });
@@ -8976,7 +8985,7 @@ function constructRegex(characters) {
8976
8985
  return new RegExp(pattern, "g");
8977
8986
  }
8978
8987
  function getText(node) {
8979
- const match = node.textContent.match(/^(\s*)(.*)$/);
8988
+ const match = /^(\s*)(.*)$/.exec(node.textContent);
8980
8989
  const [, leading, text] = match;
8981
8990
  return [leading.length, text.trimEnd()];
8982
8991
  }
@@ -9572,7 +9581,9 @@ const fieldNameGroup = {
9572
9581
  nickname: "text",
9573
9582
  username: "username",
9574
9583
  "new-password": "password",
9584
+ // eslint-disable-line sonarjs/no-hardcoded-passwords -- false positive, it is not used as a password
9575
9585
  "current-password": "password",
9586
+ // eslint-disable-line sonarjs/no-hardcoded-passwords -- false positive, it is not used as a password
9576
9587
  "one-time-code": "password",
9577
9588
  "organization-title": "text",
9578
9589
  organization: "text",
@@ -10061,7 +10072,7 @@ class ValidID extends Rule {
10061
10072
  this.report(event.target, this.messages[context.kind], event.location, context);
10062
10073
  return;
10063
10074
  }
10064
- if (value.match(/\s/)) {
10075
+ if (/\s/.exec(value)) {
10065
10076
  const context = { kind: 2 /* WHITESPACE */, id: value };
10066
10077
  this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10067
10078
  return;
@@ -10070,12 +10081,12 @@ class ValidID extends Rule {
10070
10081
  if (relaxed) {
10071
10082
  return;
10072
10083
  }
10073
- if (value.match(/^[^\p{L}]/u)) {
10084
+ if (/^[^\p{L}]/u.exec(value)) {
10074
10085
  const context = { kind: 3 /* LEADING_CHARACTER */, id: value };
10075
10086
  this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10076
10087
  return;
10077
10088
  }
10078
- if (value.match(/[^\p{L}\p{N}_-]/u)) {
10089
+ if (/[^\p{L}\p{N}_-]/u.exec(value)) {
10079
10090
  const context = { kind: 4 /* DISALLOWED_CHARACTER */, id: value };
10080
10091
  this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10081
10092
  }
@@ -11719,7 +11730,7 @@ class EventHandler {
11719
11730
  }
11720
11731
 
11721
11732
  const name = "html-validate";
11722
- const version = "9.4.2-rc.1";
11733
+ const version = "9.5.0";
11723
11734
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
11724
11735
 
11725
11736
  function freeze(src) {
@@ -12266,7 +12277,7 @@ class Parser {
12266
12277
  if (!postamble.startsWith("]")) {
12267
12278
  throw new ParserError(token.location, `Missing end bracket "]" on directive "${text}"`);
12268
12279
  }
12269
- const match = directive.match(/^(.*?)(?:(\s*(?:--|:)\s*)(.*))?$/);
12280
+ const match = /^(.*?)(?:(\s*(?:--|:)\s*)(.*))?$/.exec(directive);
12270
12281
  if (!match) {
12271
12282
  throw new Error(`Failed to parse directive "${text}"`);
12272
12283
  }
@@ -12851,7 +12862,7 @@ function validateTransformer(transformer) {
12851
12862
  }
12852
12863
  }
12853
12864
  function loadTransformerFunction(resolvers, name, plugins) {
12854
- const match = name.match(/(.*):(.*)/);
12865
+ const match = /(.*):(.*)/.exec(name);
12855
12866
  if (match) {
12856
12867
  const [, pluginName, key] = match;
12857
12868
  return getNamedTransformerFromPlugin(name, plugins, pluginName, key);