html-validate 9.4.2 → 9.5.1
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-browser.js +2 -2
- package/dist/cjs/core-browser.js.map +1 -1
- package/dist/cjs/core-nodejs.js +3 -2
- package/dist/cjs/core-nodejs.js.map +1 -1
- package/dist/cjs/core.js +40 -27
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/elements.js.map +1 -1
- package/dist/cjs/html-validate.js.map +1 -1
- package/dist/cjs/jest-worker.js.map +1 -1
- package/dist/cjs/matchers.js +2 -2
- package/dist/cjs/matchers.js.map +1 -1
- package/dist/cjs/meta-helper.js +1 -1
- package/dist/cjs/meta-helper.js.map +1 -1
- package/dist/cjs/test-utils.js +45 -11
- package/dist/cjs/test-utils.js.map +7 -1
- package/dist/cjs/tsdoc-metadata.json +1 -1
- package/dist/es/core-browser.js +2 -2
- package/dist/es/core-browser.js.map +1 -1
- package/dist/es/core-nodejs.js +3 -2
- package/dist/es/core-nodejs.js.map +1 -1
- package/dist/es/core.js +40 -27
- package/dist/es/core.js.map +1 -1
- package/dist/es/elements.js.map +1 -1
- package/dist/es/html-validate.js.map +1 -1
- package/dist/es/jest-worker.js.map +1 -1
- package/dist/es/matchers.js +2 -2
- package/dist/es/matchers.js.map +1 -1
- package/dist/es/meta-helper.js +1 -1
- package/dist/es/meta-helper.js.map +1 -1
- package/dist/es/test-utils.js +7 -4
- package/dist/es/test-utils.js.map +7 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/types/browser.d.ts +6 -8
- package/dist/types/index.d.ts +6 -8
- 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 =
|
|
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] =
|
|
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 =
|
|
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 =
|
|
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
|
|
2270
|
+
return /^\d/.exec(escaped) ? `[id="${escaped}"]` : `#${escaped}`;
|
|
2260
2271
|
}
|
|
2261
2272
|
class Selector {
|
|
2262
2273
|
pattern;
|
|
@@ -2864,7 +2875,7 @@ class HtmlElement extends DOMNode {
|
|
|
2864
2875
|
if (!selectorList) {
|
|
2865
2876
|
return;
|
|
2866
2877
|
}
|
|
2867
|
-
for (const selector of selectorList.split(
|
|
2878
|
+
for (const selector of selectorList.split(/(?<!\\),\s*/)) {
|
|
2868
2879
|
const pattern = new Selector(selector);
|
|
2869
2880
|
yield* pattern.match(this);
|
|
2870
2881
|
}
|
|
@@ -3078,7 +3089,7 @@ class Validator {
|
|
|
3078
3089
|
if (typeof rule !== "string") {
|
|
3079
3090
|
return false;
|
|
3080
3091
|
}
|
|
3081
|
-
const [, category, quantifier] =
|
|
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] =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 (
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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 (
|
|
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 =
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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.
|
|
11733
|
+
const version = "9.5.1";
|
|
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 =
|
|
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 =
|
|
12865
|
+
const match = /(.*):(.*)/.exec(name);
|
|
12853
12866
|
if (match) {
|
|
12854
12867
|
const [, pluginName, key] = match;
|
|
12855
12868
|
return getNamedTransformerFromPlugin(name, plugins, pluginName, key);
|