html-validate 9.4.2 → 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.
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
  }
@@ -2256,7 +2267,7 @@ function escapeSelectorComponent(text) {
2256
2267
  }
2257
2268
  function generateIdSelector(id) {
2258
2269
  const escaped = escapeSelectorComponent(id);
2259
- return escaped.match(/^\d/) ? `[id="${escaped}"]` : `#${escaped}`;
2270
+ return /^\d/.exec(escaped) ? `[id="${escaped}"]` : `#${escaped}`;
2260
2271
  }
2261
2272
  class Selector {
2262
2273
  pattern;
@@ -3078,7 +3089,7 @@ class Validator {
3078
3089
  if (typeof rule !== "string") {
3079
3090
  return false;
3080
3091
  }
3081
- const [, category, quantifier] = rule.match(/^(@?.*?)([?*]?)$/);
3092
+ const [, category, quantifier] = /^(@?.*?)([?*]?)$/.exec(rule);
3082
3093
  const limit = category && quantifier && parseQuantifier(quantifier);
3083
3094
  if (limit) {
3084
3095
  const siblings = children.filter(
@@ -3246,7 +3257,7 @@ class Validator {
3246
3257
  */
3247
3258
  /* eslint-disable-next-line complexity -- rule does not like switch */
3248
3259
  static validatePermittedCategory(node, category, defaultMatch) {
3249
- const [, rawCategory] = category.match(/^(@?.*?)([?*]?)$/);
3260
+ const [, rawCategory] = /^(@?.*?)([?*]?)$/.exec(category);
3250
3261
  if (!rawCategory.startsWith("@")) {
3251
3262
  return node.tagName === rawCategory;
3252
3263
  }
@@ -3489,7 +3500,7 @@ function escape(value) {
3489
3500
  return JSON.stringify(value);
3490
3501
  }
3491
3502
  function format(value, quote = false) {
3492
- if (value === null) {
3503
+ if (value === null || value === void 0) {
3493
3504
  return "null";
3494
3505
  }
3495
3506
  if (typeof value === "number") {
@@ -3568,7 +3579,7 @@ function compilePattern(pattern) {
3568
3579
  if (cached) {
3569
3580
  return cached;
3570
3581
  }
3571
- const match = pattern.match(/^\/(.*)\/$/);
3582
+ const match = /^\/(.*)\/$/.exec(pattern);
3572
3583
  const regexp = match ? compileRegExpPattern(match[1]) : compileStringPattern(pattern);
3573
3584
  patternCache.set(pattern, regexp);
3574
3585
  return regexp;
@@ -3753,7 +3764,7 @@ function classifyNodeText(node, options = {}) {
3753
3764
  if (text.some((cur) => cur.isDynamic)) {
3754
3765
  return node.cacheSet(cacheKey, 1 /* DYNAMIC_TEXT */);
3755
3766
  }
3756
- if (text.some((cur) => cur.textContent.match(/\S/) !== null)) {
3767
+ if (text.some((cur) => /\S/.exec(cur.textContent) !== null)) {
3757
3768
  return node.cacheSet(cacheKey, 2 /* STATIC_TEXT */);
3758
3769
  }
3759
3770
  return node.cacheSet(cacheKey, 0 /* EMPTY_TEXT */);
@@ -5767,7 +5778,7 @@ class Deprecated extends Rule {
5767
5778
  }
5768
5779
  }
5769
5780
  function prettySource(source) {
5770
- const match = source.match(/html(\d)(\d)?/);
5781
+ const match = /html(\d)(\d)?/.exec(source);
5771
5782
  if (match) {
5772
5783
  const [, ...parts] = match;
5773
5784
  const version = parts.filter(Boolean).join(".");
@@ -6005,7 +6016,7 @@ class ElementName extends Rule {
6005
6016
  if (target.meta) {
6006
6017
  return;
6007
6018
  }
6008
- if (tagName.match(xmlns)) {
6019
+ if (xmlns.exec(tagName)) {
6009
6020
  return;
6010
6021
  }
6011
6022
  if (this.options.whitelist.includes(tagName)) {
@@ -6263,7 +6274,7 @@ class ElementPermittedParent extends Rule {
6263
6274
  }
6264
6275
 
6265
6276
  function isTagnameOnly(value) {
6266
- return Boolean(value.match(/^[a-zA-Z0-9-]+$/));
6277
+ return Boolean(/^[a-zA-Z0-9-]+$/.exec(value));
6267
6278
  }
6268
6279
  function getRuleDescription(context) {
6269
6280
  const escaped = context.ancestor.map((it) => `\`${it}\``);
@@ -6676,7 +6687,7 @@ function isRelevant$5(event) {
6676
6687
  return Boolean(node.meta?.heading);
6677
6688
  }
6678
6689
  function extractLevel(node) {
6679
- const match = node.tagName.match(/^[hH](\d)$/);
6690
+ const match = /^[hH](\d)$/.exec(node.tagName);
6680
6691
  if (match) {
6681
6692
  return parseInt(match[1], 10);
6682
6693
  } else {
@@ -6687,7 +6698,7 @@ function parseMaxInitial(value) {
6687
6698
  if (value === false || value === "any") {
6688
6699
  return 6;
6689
6700
  }
6690
- const match = value.match(/^h(\d)$/);
6701
+ const match = /^h(\d)$/.exec(value);
6691
6702
  if (!match) {
6692
6703
  return 1;
6693
6704
  }
@@ -7344,7 +7355,7 @@ class MetaRefresh extends Rule {
7344
7355
  }
7345
7356
  }
7346
7357
  function parseContent(text) {
7347
- const match = text.match(/^(\d+)(?:\s*;\s*url=(.*))?/i);
7358
+ const match = /^(\d+)(?:\s*;\s*url=(.*))?/i.exec(text);
7348
7359
  if (match) {
7349
7360
  return {
7350
7361
  delay: parseInt(match[1], 10),
@@ -8135,7 +8146,7 @@ class NoRawCharacters extends Rule {
8135
8146
  if (child.nodeType !== NodeType.TEXT_NODE) {
8136
8147
  continue;
8137
8148
  }
8138
- if (child.textContent.match(matchTemplate)) {
8149
+ if (matchTemplate.exec(child.textContent)) {
8139
8150
  continue;
8140
8151
  }
8141
8152
  this.findRawChars(node, child.textContent, child.location, textRegexp);
@@ -8328,7 +8339,7 @@ class NoSelfClosing extends Rule {
8328
8339
  }
8329
8340
  }
8330
8341
  function isRelevant(node, options) {
8331
- if (node.tagName.match(xmlns)) {
8342
+ if (xmlns.exec(node.tagName)) {
8332
8343
  return !options.ignoreXML;
8333
8344
  }
8334
8345
  if (!node.meta) {
@@ -8369,7 +8380,7 @@ class NoTrailingWhitespace extends Rule {
8369
8380
  }
8370
8381
  setup() {
8371
8382
  this.on("whitespace", (event) => {
8372
- if (event.text.match(/^[ \t]+\r?\n$/)) {
8383
+ if (/^[ \t]+\r?\n$/.exec(event.text)) {
8373
8384
  this.report(null, "Trailing whitespace", event.location);
8374
8385
  }
8375
8386
  });
@@ -8974,7 +8985,7 @@ function constructRegex(characters) {
8974
8985
  return new RegExp(pattern, "g");
8975
8986
  }
8976
8987
  function getText(node) {
8977
- const match = node.textContent.match(/^(\s*)(.*)$/);
8988
+ const match = /^(\s*)(.*)$/.exec(node.textContent);
8978
8989
  const [, leading, text] = match;
8979
8990
  return [leading.length, text.trimEnd()];
8980
8991
  }
@@ -9570,7 +9581,9 @@ const fieldNameGroup = {
9570
9581
  nickname: "text",
9571
9582
  username: "username",
9572
9583
  "new-password": "password",
9584
+ // eslint-disable-line sonarjs/no-hardcoded-passwords -- false positive, it is not used as a password
9573
9585
  "current-password": "password",
9586
+ // eslint-disable-line sonarjs/no-hardcoded-passwords -- false positive, it is not used as a password
9574
9587
  "one-time-code": "password",
9575
9588
  "organization-title": "text",
9576
9589
  organization: "text",
@@ -10059,7 +10072,7 @@ class ValidID extends Rule {
10059
10072
  this.report(event.target, this.messages[context.kind], event.location, context);
10060
10073
  return;
10061
10074
  }
10062
- if (value.match(/\s/)) {
10075
+ if (/\s/.exec(value)) {
10063
10076
  const context = { kind: 2 /* WHITESPACE */, id: value };
10064
10077
  this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10065
10078
  return;
@@ -10068,12 +10081,12 @@ class ValidID extends Rule {
10068
10081
  if (relaxed) {
10069
10082
  return;
10070
10083
  }
10071
- if (value.match(/^[^\p{L}]/u)) {
10084
+ if (/^[^\p{L}]/u.exec(value)) {
10072
10085
  const context = { kind: 3 /* LEADING_CHARACTER */, id: value };
10073
10086
  this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10074
10087
  return;
10075
10088
  }
10076
- if (value.match(/[^\p{L}\p{N}_-]/u)) {
10089
+ if (/[^\p{L}\p{N}_-]/u.exec(value)) {
10077
10090
  const context = { kind: 4 /* DISALLOWED_CHARACTER */, id: value };
10078
10091
  this.report(event.target, this.messages[context.kind], event.valueLocation, context);
10079
10092
  }
@@ -11717,7 +11730,7 @@ class EventHandler {
11717
11730
  }
11718
11731
 
11719
11732
  const name = "html-validate";
11720
- const version = "9.4.2";
11733
+ const version = "9.5.0";
11721
11734
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
11722
11735
 
11723
11736
  function freeze(src) {
@@ -12264,7 +12277,7 @@ class Parser {
12264
12277
  if (!postamble.startsWith("]")) {
12265
12278
  throw new ParserError(token.location, `Missing end bracket "]" on directive "${text}"`);
12266
12279
  }
12267
- const match = directive.match(/^(.*?)(?:(\s*(?:--|:)\s*)(.*))?$/);
12280
+ const match = /^(.*?)(?:(\s*(?:--|:)\s*)(.*))?$/.exec(directive);
12268
12281
  if (!match) {
12269
12282
  throw new Error(`Failed to parse directive "${text}"`);
12270
12283
  }
@@ -12849,7 +12862,7 @@ function validateTransformer(transformer) {
12849
12862
  }
12850
12863
  }
12851
12864
  function loadTransformerFunction(resolvers, name, plugins) {
12852
- const match = name.match(/(.*):(.*)/);
12865
+ const match = /(.*):(.*)/.exec(name);
12853
12866
  if (match) {
12854
12867
  const [, pluginName, key] = match;
12855
12868
  return getNamedTransformerFromPlugin(name, plugins, pluginName, key);