html-validate 10.9.0 → 10.11.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/cli.js +10 -10
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/core-browser.js +1 -1
- package/dist/cjs/core-browser.js.map +1 -1
- package/dist/cjs/core-nodejs.js +1 -1
- package/dist/cjs/core-nodejs.js.map +1 -1
- package/dist/cjs/core.js +286 -189
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/elements.js +24 -16
- package/dist/cjs/elements.js.map +1 -1
- package/dist/cjs/html-validate.js +23 -15
- package/dist/cjs/html-validate.js.map +1 -1
- package/dist/cjs/matchers-jestonly.js +2 -2
- package/dist/cjs/matchers-jestonly.js.map +1 -1
- package/dist/cjs/tsdoc-metadata.json +1 -1
- package/dist/cjs/utils/natural-join.js +1 -1
- package/dist/cjs/utils/natural-join.js.map +1 -1
- package/dist/esm/cli.js +10 -10
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/core-browser.js +1 -1
- package/dist/esm/core-browser.js.map +1 -1
- package/dist/esm/core-nodejs.js +1 -1
- package/dist/esm/core-nodejs.js.map +1 -1
- package/dist/esm/core.js +286 -189
- package/dist/esm/core.js.map +1 -1
- package/dist/esm/elements.js +24 -16
- package/dist/esm/elements.js.map +1 -1
- package/dist/esm/html-validate.js +24 -16
- package/dist/esm/html-validate.js.map +1 -1
- package/dist/esm/matchers-jestonly.js +2 -2
- package/dist/esm/matchers-jestonly.js.map +1 -1
- package/dist/esm/utils/natural-join.js +1 -1
- package/dist/esm/utils/natural-join.js.map +1 -1
- package/dist/schema/elements.json +6 -0
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/types/browser.d.ts +24 -9
- package/dist/types/index.d.ts +24 -9
- package/package.json +3 -3
package/dist/cjs/core.js
CHANGED
|
@@ -404,6 +404,7 @@ function stringify(value) {
|
|
|
404
404
|
class WrappedError extends Error {
|
|
405
405
|
constructor(message) {
|
|
406
406
|
super(stringify(message));
|
|
407
|
+
this.name = "WrappedError";
|
|
407
408
|
}
|
|
408
409
|
}
|
|
409
410
|
|
|
@@ -418,8 +419,7 @@ function ensureError(value) {
|
|
|
418
419
|
class NestedError extends Error {
|
|
419
420
|
constructor(message, nested) {
|
|
420
421
|
super(message);
|
|
421
|
-
|
|
422
|
-
this.name = NestedError.name;
|
|
422
|
+
this.name = "NestedError";
|
|
423
423
|
if (nested?.stack) {
|
|
424
424
|
this.stack ??= "";
|
|
425
425
|
this.stack += `
|
|
@@ -431,8 +431,7 @@ Caused by: ${nested.stack}`;
|
|
|
431
431
|
class UserError extends NestedError {
|
|
432
432
|
constructor(message, nested) {
|
|
433
433
|
super(message, nested);
|
|
434
|
-
|
|
435
|
-
this.name = UserError.name;
|
|
434
|
+
this.name = "UserError";
|
|
436
435
|
Object.defineProperty(this, "isUserError", {
|
|
437
436
|
value: true,
|
|
438
437
|
enumerable: false,
|
|
@@ -455,8 +454,7 @@ class InheritError extends UserError {
|
|
|
455
454
|
constructor({ tagName, inherit }) {
|
|
456
455
|
const message = `Element <${tagName}> cannot inherit from <${inherit}>: no such element`;
|
|
457
456
|
super(message);
|
|
458
|
-
|
|
459
|
-
this.name = InheritError.name;
|
|
457
|
+
this.name = "InheritError";
|
|
460
458
|
this.tagName = tagName;
|
|
461
459
|
this.inherit = inherit;
|
|
462
460
|
this.filename = null;
|
|
@@ -498,6 +496,7 @@ class SchemaValidationError extends UserError {
|
|
|
498
496
|
constructor(filename, message, obj, schema, errors) {
|
|
499
497
|
const summary = getSummary(schema, obj, errors);
|
|
500
498
|
super(`${message}: ${summary}`);
|
|
499
|
+
this.name = "SchemaValidationError";
|
|
501
500
|
this.filename = filename;
|
|
502
501
|
this.obj = obj;
|
|
503
502
|
this.schema = schema;
|
|
@@ -645,6 +644,18 @@ const patternProperties = {
|
|
|
645
644
|
}
|
|
646
645
|
]
|
|
647
646
|
},
|
|
647
|
+
submitButton: {
|
|
648
|
+
title: "Mark this element as a submit button",
|
|
649
|
+
description: "This element can be used to submit forms.",
|
|
650
|
+
anyOf: [
|
|
651
|
+
{
|
|
652
|
+
type: "boolean"
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
"function": true
|
|
656
|
+
}
|
|
657
|
+
]
|
|
658
|
+
},
|
|
648
659
|
templateRoot: {
|
|
649
660
|
title: "Mark element as an element ignoring DOM ancestry, i.e. <template>.",
|
|
650
661
|
description: "The <template> element can contain any elements.",
|
|
@@ -1028,6 +1039,7 @@ const MetaCopyableProperty = [
|
|
|
1028
1039
|
"form",
|
|
1029
1040
|
"formAssociated",
|
|
1030
1041
|
"labelable",
|
|
1042
|
+
"submitButton",
|
|
1031
1043
|
"attributes",
|
|
1032
1044
|
"aria",
|
|
1033
1045
|
"permittedContent",
|
|
@@ -1042,7 +1054,7 @@ function setMetaProperty(dst, key, value) {
|
|
|
1042
1054
|
}
|
|
1043
1055
|
|
|
1044
1056
|
function isSet(value) {
|
|
1045
|
-
return
|
|
1057
|
+
return value !== void 0;
|
|
1046
1058
|
}
|
|
1047
1059
|
function flag(value) {
|
|
1048
1060
|
return value ? true : void 0;
|
|
@@ -1057,7 +1069,7 @@ function migrateSingleAttribute(src, key) {
|
|
|
1057
1069
|
result.required = flag(src.requiredAttributes?.includes(key));
|
|
1058
1070
|
result.omit = void 0;
|
|
1059
1071
|
const attr = src.attributes ? src.attributes[key] : void 0;
|
|
1060
|
-
if (
|
|
1072
|
+
if (attr === void 0) {
|
|
1061
1073
|
return stripUndefined(result);
|
|
1062
1074
|
}
|
|
1063
1075
|
if (attr === null) {
|
|
@@ -1084,7 +1096,7 @@ function migrateAttributes(src) {
|
|
|
1084
1096
|
...src.requiredAttributes ?? [],
|
|
1085
1097
|
...src.deprecatedAttributes ?? []
|
|
1086
1098
|
/* eslint-disable-next-line sonarjs/no-alphabetical-sort -- not really needed in this case, this is a-z anyway */
|
|
1087
|
-
].
|
|
1099
|
+
].toSorted();
|
|
1088
1100
|
const entries = keys.map((key) => {
|
|
1089
1101
|
return [key, migrateSingleAttribute(src, key)];
|
|
1090
1102
|
});
|
|
@@ -1112,9 +1124,7 @@ function migrateElement(src) {
|
|
|
1112
1124
|
const implicitRole = normalizeAriaImplicitRole(src.implicitRole ?? src.aria?.implicitRole);
|
|
1113
1125
|
const result = {
|
|
1114
1126
|
...src,
|
|
1115
|
-
|
|
1116
|
-
formAssociated: void 0
|
|
1117
|
-
},
|
|
1127
|
+
formAssociated: void 0,
|
|
1118
1128
|
attributes: migrateAttributes(src),
|
|
1119
1129
|
textContent: src.textContent,
|
|
1120
1130
|
focusable: src.focusable ?? false,
|
|
@@ -1149,7 +1159,8 @@ const dynamicKeys = [
|
|
|
1149
1159
|
"phrasing",
|
|
1150
1160
|
"embedded",
|
|
1151
1161
|
"interactive",
|
|
1152
|
-
"labelable"
|
|
1162
|
+
"labelable",
|
|
1163
|
+
"submitButton"
|
|
1153
1164
|
];
|
|
1154
1165
|
const schemaCache = /* @__PURE__ */ new Map();
|
|
1155
1166
|
function clone(src) {
|
|
@@ -1419,13 +1430,10 @@ class Attribute {
|
|
|
1419
1430
|
*/
|
|
1420
1431
|
constructor(key, value, keyLocation, valueLocation, originalAttribute) {
|
|
1421
1432
|
this.key = key;
|
|
1422
|
-
this.value = value;
|
|
1433
|
+
this.value = value ?? null;
|
|
1423
1434
|
this.keyLocation = keyLocation;
|
|
1424
1435
|
this.valueLocation = valueLocation;
|
|
1425
1436
|
this.originalAttribute = originalAttribute;
|
|
1426
|
-
if (typeof this.value === "undefined") {
|
|
1427
|
-
this.value = null;
|
|
1428
|
-
}
|
|
1429
1437
|
}
|
|
1430
1438
|
/**
|
|
1431
1439
|
* Flag set to true if the attribute value is static.
|
|
@@ -1569,11 +1577,11 @@ class Context {
|
|
|
1569
1577
|
while ((offset = consumed.indexOf("\n")) >= 0) {
|
|
1570
1578
|
this.line++;
|
|
1571
1579
|
this.column = 1;
|
|
1572
|
-
consumed = consumed.
|
|
1580
|
+
consumed = consumed.slice(offset + 1);
|
|
1573
1581
|
}
|
|
1574
1582
|
this.column += consumed.length;
|
|
1575
1583
|
this.offset += n;
|
|
1576
|
-
this.string = this.string.
|
|
1584
|
+
this.string = this.string.slice(n);
|
|
1577
1585
|
this.state = state;
|
|
1578
1586
|
}
|
|
1579
1587
|
getLocation(size) {
|
|
@@ -1751,7 +1759,7 @@ class DOMNode {
|
|
|
1751
1759
|
* node has no children.
|
|
1752
1760
|
*/
|
|
1753
1761
|
get lastChild() {
|
|
1754
|
-
return this.childNodes
|
|
1762
|
+
return this.childNodes.at(-1) ?? null;
|
|
1755
1763
|
}
|
|
1756
1764
|
/**
|
|
1757
1765
|
* @internal
|
|
@@ -1845,7 +1853,7 @@ class DOMNode {
|
|
|
1845
1853
|
}
|
|
1846
1854
|
_removeChild(node) {
|
|
1847
1855
|
const index = this.childNodes.findIndex((it) => it.isSameNode(node));
|
|
1848
|
-
if (index
|
|
1856
|
+
if (index !== -1) {
|
|
1849
1857
|
this.childNodes.splice(index, 1);
|
|
1850
1858
|
} else {
|
|
1851
1859
|
throw new Error("DOMException: _removeChild(..) could not find child to remove");
|
|
@@ -1866,7 +1874,7 @@ function parse(text, baseLocation) {
|
|
|
1866
1874
|
begin++;
|
|
1867
1875
|
continue;
|
|
1868
1876
|
}
|
|
1869
|
-
const token = text.
|
|
1877
|
+
const token = text.slice(begin, end);
|
|
1870
1878
|
tokens.push(token);
|
|
1871
1879
|
if (locations && baseLocation) {
|
|
1872
1880
|
const location = sliceLocation(baseLocation, begin, end);
|
|
@@ -1881,7 +1889,7 @@ class DOMTokenList extends Array {
|
|
|
1881
1889
|
locations;
|
|
1882
1890
|
constructor(value, location) {
|
|
1883
1891
|
if (value && typeof value === "string") {
|
|
1884
|
-
const normalized = value.
|
|
1892
|
+
const normalized = value.replaceAll(/[\t\r\n]/g, " ");
|
|
1885
1893
|
const { tokens, locations } = parse(normalized, location);
|
|
1886
1894
|
super(...tokens);
|
|
1887
1895
|
this.locations = locations;
|
|
@@ -1971,7 +1979,7 @@ function nthChild(node, args) {
|
|
|
1971
1979
|
if (!args) {
|
|
1972
1980
|
throw new Error("Missing argument to nth-child");
|
|
1973
1981
|
}
|
|
1974
|
-
const n = parseInt(args.trim(), 10);
|
|
1982
|
+
const n = Number.parseInt(args.trim(), 10);
|
|
1975
1983
|
const cur = getNthChild(node);
|
|
1976
1984
|
return cur === n;
|
|
1977
1985
|
}
|
|
@@ -1996,7 +2004,7 @@ function factory(name, context) {
|
|
|
1996
2004
|
}
|
|
1997
2005
|
|
|
1998
2006
|
function stripslashes(value) {
|
|
1999
|
-
return value.
|
|
2007
|
+
return value.replaceAll(/\\(.)/g, "$1");
|
|
2000
2008
|
}
|
|
2001
2009
|
class Condition {
|
|
2002
2010
|
}
|
|
@@ -2195,7 +2203,7 @@ function candidatesFromCombinator(element, combinator) {
|
|
|
2195
2203
|
}
|
|
2196
2204
|
}
|
|
2197
2205
|
function matchElement(element, compounds, context) {
|
|
2198
|
-
const last = compounds
|
|
2206
|
+
const last = compounds.at(-1);
|
|
2199
2207
|
if (!last.match(element, context)) {
|
|
2200
2208
|
return false;
|
|
2201
2209
|
}
|
|
@@ -2212,7 +2220,7 @@ function matchElement(element, compounds, context) {
|
|
|
2212
2220
|
return false;
|
|
2213
2221
|
}
|
|
2214
2222
|
|
|
2215
|
-
const escapedCodepoints = ["9", "a", "d"];
|
|
2223
|
+
const escapedCodepoints = /* @__PURE__ */ new Set(["9", "a", "d"]);
|
|
2216
2224
|
function* splitSelectorElements(selector) {
|
|
2217
2225
|
let begin = 0;
|
|
2218
2226
|
let end = 0;
|
|
@@ -2227,7 +2235,7 @@ function* splitSelectorElements(selector) {
|
|
|
2227
2235
|
return 0 /* INITIAL */;
|
|
2228
2236
|
}
|
|
2229
2237
|
function escapedState(ch) {
|
|
2230
|
-
if (escapedCodepoints.
|
|
2238
|
+
if (escapedCodepoints.has(ch)) {
|
|
2231
2239
|
return 1 /* ESCAPED */;
|
|
2232
2240
|
}
|
|
2233
2241
|
return 0 /* INITIAL */;
|
|
@@ -2267,7 +2275,7 @@ function unescapeCodepoint(value) {
|
|
|
2267
2275
|
"\\a ": "\n",
|
|
2268
2276
|
"\\d ": "\r"
|
|
2269
2277
|
};
|
|
2270
|
-
return value.
|
|
2278
|
+
return value.replaceAll(
|
|
2271
2279
|
/(\\[\u0039\u0061\u0064] )/g,
|
|
2272
2280
|
(_, codepoint) => replacement[codepoint]
|
|
2273
2281
|
);
|
|
@@ -2278,7 +2286,7 @@ function escapeSelectorComponent(text) {
|
|
|
2278
2286
|
"\n": "\\a ",
|
|
2279
2287
|
"\r": "\\d "
|
|
2280
2288
|
};
|
|
2281
|
-
return text.toString().
|
|
2289
|
+
return text.toString().replaceAll(/([\t\n\r]|[^a-z0-9_-])/gi, (_, ch) => {
|
|
2282
2290
|
if (codepoints[ch]) {
|
|
2283
2291
|
return codepoints[ch];
|
|
2284
2292
|
} else {
|
|
@@ -2327,7 +2335,7 @@ class Selector {
|
|
|
2327
2335
|
}
|
|
2328
2336
|
}
|
|
2329
2337
|
static parse(selector) {
|
|
2330
|
-
selector = selector.
|
|
2338
|
+
selector = selector.replaceAll(/([+~>]) /g, "$1");
|
|
2331
2339
|
return Array.from(splitSelectorElements(selector), (element) => {
|
|
2332
2340
|
return new Compound(unescapeCodepoint(element));
|
|
2333
2341
|
});
|
|
@@ -2568,7 +2576,7 @@ class HtmlElement extends DOMNode {
|
|
|
2568
2576
|
return attr.value;
|
|
2569
2577
|
}
|
|
2570
2578
|
const list = new DOMTokenList(attr.value, attr.valueLocation);
|
|
2571
|
-
return list.length ? Array.from(list) : null;
|
|
2579
|
+
return list.length > 0 ? Array.from(list) : null;
|
|
2572
2580
|
}
|
|
2573
2581
|
/**
|
|
2574
2582
|
* Similar to childNodes but only elements.
|
|
@@ -2623,7 +2631,7 @@ class HtmlElement extends DOMNode {
|
|
|
2623
2631
|
}
|
|
2624
2632
|
parts.push(`${cur.tagName.toLowerCase()}:nth-child(${String(index + 1)})`);
|
|
2625
2633
|
}
|
|
2626
|
-
return parts.
|
|
2634
|
+
return parts.toReversed().join(" > ");
|
|
2627
2635
|
}
|
|
2628
2636
|
/**
|
|
2629
2637
|
* Tests if this element has given tagname.
|
|
@@ -2665,7 +2673,7 @@ class HtmlElement extends DOMNode {
|
|
|
2665
2673
|
this.metaElement ??= {};
|
|
2666
2674
|
for (const key of MetaCopyableProperty) {
|
|
2667
2675
|
const value = meta[key];
|
|
2668
|
-
if (
|
|
2676
|
+
if (value !== void 0) {
|
|
2669
2677
|
setMetaProperty(this.metaElement, key, value);
|
|
2670
2678
|
} else {
|
|
2671
2679
|
delete this.metaElement[key];
|
|
@@ -2769,8 +2777,8 @@ class HtmlElement extends DOMNode {
|
|
|
2769
2777
|
if (tabindex.value instanceof DynamicValue) {
|
|
2770
2778
|
return this.cacheSet(TABINDEX, 0);
|
|
2771
2779
|
}
|
|
2772
|
-
const parsed = parseInt(tabindex.value, 10);
|
|
2773
|
-
if (isNaN(parsed)) {
|
|
2780
|
+
const parsed = Number.parseInt(tabindex.value, 10);
|
|
2781
|
+
if (Number.isNaN(parsed)) {
|
|
2774
2782
|
return this.cacheSet(TABINDEX, null);
|
|
2775
2783
|
}
|
|
2776
2784
|
return this.cacheSet(TABINDEX, parsed);
|
|
@@ -2874,7 +2882,10 @@ class HtmlElement extends DOMNode {
|
|
|
2874
2882
|
*/
|
|
2875
2883
|
get lastElementChild() {
|
|
2876
2884
|
const children = this.childElements;
|
|
2877
|
-
return children.length > 0 ?
|
|
2885
|
+
return children.length > 0 ? (
|
|
2886
|
+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- it is checked right before this */
|
|
2887
|
+
children.at(-1)
|
|
2888
|
+
) : null;
|
|
2878
2889
|
}
|
|
2879
2890
|
get siblings() {
|
|
2880
2891
|
return this.parent ? this.parent.childElements : [this];
|
|
@@ -2997,7 +3008,9 @@ function depthFirst(root, callback) {
|
|
|
2997
3008
|
root = root.root;
|
|
2998
3009
|
}
|
|
2999
3010
|
function visit(node) {
|
|
3000
|
-
node.childElements
|
|
3011
|
+
for (const child of node.childElements) {
|
|
3012
|
+
visit(child);
|
|
3013
|
+
}
|
|
3001
3014
|
if (!node.isRootElement()) {
|
|
3002
3015
|
callback(node);
|
|
3003
3016
|
}
|
|
@@ -3086,7 +3099,7 @@ class DOMTree {
|
|
|
3086
3099
|
}
|
|
3087
3100
|
}
|
|
3088
3101
|
|
|
3089
|
-
const allowedKeys = ["exclude"];
|
|
3102
|
+
const allowedKeys = /* @__PURE__ */ new Set(["exclude"]);
|
|
3090
3103
|
class Validator {
|
|
3091
3104
|
/**
|
|
3092
3105
|
* Test if element is used in a proper context.
|
|
@@ -3325,7 +3338,7 @@ class Validator {
|
|
|
3325
3338
|
}
|
|
3326
3339
|
function validateKeys(rule) {
|
|
3327
3340
|
for (const key of Object.keys(rule)) {
|
|
3328
|
-
if (!allowedKeys.
|
|
3341
|
+
if (!allowedKeys.has(key)) {
|
|
3329
3342
|
const str = JSON.stringify(rule);
|
|
3330
3343
|
throw new Error(`Permitted rule "${str}" contains unknown property "${key}"`);
|
|
3331
3344
|
}
|
|
@@ -3367,7 +3380,7 @@ function parseSeverity(value) {
|
|
|
3367
3380
|
|
|
3368
3381
|
const cacheKey = /* @__PURE__ */ Symbol("aria-naming");
|
|
3369
3382
|
const defaultValue = "allowed";
|
|
3370
|
-
const prohibitedRoles = [
|
|
3383
|
+
const prohibitedRoles = /* @__PURE__ */ new Set([
|
|
3371
3384
|
"caption",
|
|
3372
3385
|
"code",
|
|
3373
3386
|
"deletion",
|
|
@@ -3379,9 +3392,9 @@ const prohibitedRoles = [
|
|
|
3379
3392
|
"strong",
|
|
3380
3393
|
"subscript",
|
|
3381
3394
|
"superscript"
|
|
3382
|
-
];
|
|
3395
|
+
]);
|
|
3383
3396
|
function byRole(role) {
|
|
3384
|
-
return prohibitedRoles.
|
|
3397
|
+
return prohibitedRoles.has(role) ? "prohibited" : "allowed";
|
|
3385
3398
|
}
|
|
3386
3399
|
function byMeta(element, meta) {
|
|
3387
3400
|
return meta.aria.naming(element._adapter);
|
|
@@ -3433,7 +3446,7 @@ function isInputDisabledImpl(node) {
|
|
|
3433
3446
|
|
|
3434
3447
|
const patternCache = /* @__PURE__ */ new Map();
|
|
3435
3448
|
function compileStringPattern(pattern) {
|
|
3436
|
-
const regexp = pattern.
|
|
3449
|
+
const regexp = pattern.replaceAll(/[*]+/g, ".+");
|
|
3437
3450
|
return new RegExp(`^${regexp}$`);
|
|
3438
3451
|
}
|
|
3439
3452
|
function compileRegExpPattern(pattern) {
|
|
@@ -3708,8 +3721,8 @@ function format(value, quote = false) {
|
|
|
3708
3721
|
return String(value);
|
|
3709
3722
|
}
|
|
3710
3723
|
function interpolate(text, data) {
|
|
3711
|
-
return text.
|
|
3712
|
-
return
|
|
3724
|
+
return text.replaceAll(/{{\s*([^\s{}]+)\s*}}/g, (match, key) => {
|
|
3725
|
+
return data[key] !== void 0 ? format(data[key]) : match;
|
|
3713
3726
|
});
|
|
3714
3727
|
}
|
|
3715
3728
|
|
|
@@ -3917,7 +3930,14 @@ class Rule {
|
|
|
3917
3930
|
});
|
|
3918
3931
|
if (enabled && !blocked) {
|
|
3919
3932
|
const interpolated = interpolate(message, context ?? {});
|
|
3920
|
-
this.reporter.add(
|
|
3933
|
+
this.reporter.add({
|
|
3934
|
+
rule: this,
|
|
3935
|
+
message: interpolated,
|
|
3936
|
+
severity: this.severity,
|
|
3937
|
+
node,
|
|
3938
|
+
location: where,
|
|
3939
|
+
context
|
|
3940
|
+
});
|
|
3921
3941
|
}
|
|
3922
3942
|
}
|
|
3923
3943
|
findLocation(src) {
|
|
@@ -4008,7 +4028,7 @@ class Rule {
|
|
|
4008
4028
|
}
|
|
4009
4029
|
}
|
|
4010
4030
|
|
|
4011
|
-
const defaults$
|
|
4031
|
+
const defaults$C = {
|
|
4012
4032
|
allowExternal: true,
|
|
4013
4033
|
allowRelative: true,
|
|
4014
4034
|
allowAbsolute: true,
|
|
@@ -4052,7 +4072,7 @@ class AllowedLinks extends Rule {
|
|
|
4052
4072
|
allowRelative;
|
|
4053
4073
|
allowAbsolute;
|
|
4054
4074
|
constructor(options) {
|
|
4055
|
-
super({ ...defaults$
|
|
4075
|
+
super({ ...defaults$C, ...options });
|
|
4056
4076
|
this.allowExternal = parseAllow(this.options.allowExternal);
|
|
4057
4077
|
this.allowRelative = parseAllow(this.options.allowRelative);
|
|
4058
4078
|
this.allowAbsolute = parseAllow(this.options.allowAbsolute);
|
|
@@ -4220,7 +4240,7 @@ class AllowedLinks extends Rule {
|
|
|
4220
4240
|
}
|
|
4221
4241
|
}
|
|
4222
4242
|
|
|
4223
|
-
const defaults$
|
|
4243
|
+
const defaults$B = {
|
|
4224
4244
|
accessible: true
|
|
4225
4245
|
};
|
|
4226
4246
|
function findByTarget(target, siblings) {
|
|
@@ -4250,7 +4270,7 @@ function getDescription$1(context) {
|
|
|
4250
4270
|
}
|
|
4251
4271
|
class AreaAlt extends Rule {
|
|
4252
4272
|
constructor(options) {
|
|
4253
|
-
super({ ...defaults$
|
|
4273
|
+
super({ ...defaults$B, ...options });
|
|
4254
4274
|
}
|
|
4255
4275
|
static schema() {
|
|
4256
4276
|
return {
|
|
@@ -4329,7 +4349,7 @@ class AriaHiddenBody extends Rule {
|
|
|
4329
4349
|
}
|
|
4330
4350
|
}
|
|
4331
4351
|
|
|
4332
|
-
const defaults$
|
|
4352
|
+
const defaults$A = {
|
|
4333
4353
|
allowAnyNamable: false,
|
|
4334
4354
|
elements: {
|
|
4335
4355
|
include: null,
|
|
@@ -4377,7 +4397,7 @@ function isValidUsage(target, meta) {
|
|
|
4377
4397
|
}
|
|
4378
4398
|
class AriaLabelMisuse extends Rule {
|
|
4379
4399
|
constructor(options) {
|
|
4380
|
-
super({ ...defaults$
|
|
4400
|
+
super({ ...defaults$A, ...options });
|
|
4381
4401
|
}
|
|
4382
4402
|
static schema() {
|
|
4383
4403
|
return {
|
|
@@ -4489,8 +4509,7 @@ class AriaLabelMisuse extends Rule {
|
|
|
4489
4509
|
class ConfigError extends UserError {
|
|
4490
4510
|
constructor(message, nested) {
|
|
4491
4511
|
super(message, nested);
|
|
4492
|
-
|
|
4493
|
-
this.name = ConfigError.name;
|
|
4512
|
+
this.name = "ConfigError";
|
|
4494
4513
|
}
|
|
4495
4514
|
}
|
|
4496
4515
|
|
|
@@ -4546,14 +4565,14 @@ class CaseStyle {
|
|
|
4546
4565
|
}
|
|
4547
4566
|
}
|
|
4548
4567
|
|
|
4549
|
-
const defaults$
|
|
4568
|
+
const defaults$z = {
|
|
4550
4569
|
style: "lowercase",
|
|
4551
4570
|
ignoreForeign: true
|
|
4552
4571
|
};
|
|
4553
4572
|
class AttrCase extends Rule {
|
|
4554
4573
|
style;
|
|
4555
4574
|
constructor(options) {
|
|
4556
|
-
super({ ...defaults$
|
|
4575
|
+
super({ ...defaults$z, ...options });
|
|
4557
4576
|
this.style = new CaseStyle(this.options.style, "attr-case");
|
|
4558
4577
|
}
|
|
4559
4578
|
static schema() {
|
|
@@ -4594,7 +4613,7 @@ class AttrCase extends Rule {
|
|
|
4594
4613
|
if (event.originalAttribute) {
|
|
4595
4614
|
return;
|
|
4596
4615
|
}
|
|
4597
|
-
const letters = event.key.
|
|
4616
|
+
const letters = event.key.replaceAll(/[^a-z]+/gi, "");
|
|
4598
4617
|
if (this.style.match(letters)) {
|
|
4599
4618
|
return;
|
|
4600
4619
|
}
|
|
@@ -4667,6 +4686,7 @@ class InvalidTokenError extends Error {
|
|
|
4667
4686
|
location;
|
|
4668
4687
|
constructor(location, message) {
|
|
4669
4688
|
super(message);
|
|
4689
|
+
this.name = "InvalidTokenError";
|
|
4670
4690
|
this.location = location;
|
|
4671
4691
|
}
|
|
4672
4692
|
}
|
|
@@ -4776,16 +4796,26 @@ class Lexer {
|
|
|
4776
4796
|
*/
|
|
4777
4797
|
enter(context, state, data) {
|
|
4778
4798
|
if (state === State.TAG && data?.[0].startsWith("<")) {
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4799
|
+
switch (data[0]) {
|
|
4800
|
+
case "<script": {
|
|
4801
|
+
context.contentModel = ContentModel.SCRIPT;
|
|
4802
|
+
break;
|
|
4803
|
+
}
|
|
4804
|
+
case "<style": {
|
|
4805
|
+
context.contentModel = ContentModel.STYLE;
|
|
4806
|
+
break;
|
|
4807
|
+
}
|
|
4808
|
+
case "<textarea": {
|
|
4809
|
+
context.contentModel = ContentModel.TEXTAREA;
|
|
4810
|
+
break;
|
|
4811
|
+
}
|
|
4812
|
+
case "<title": {
|
|
4813
|
+
context.contentModel = ContentModel.TITLE;
|
|
4814
|
+
break;
|
|
4815
|
+
}
|
|
4816
|
+
default: {
|
|
4817
|
+
context.contentModel = ContentModel.TEXT;
|
|
4818
|
+
}
|
|
4789
4819
|
}
|
|
4790
4820
|
}
|
|
4791
4821
|
}
|
|
@@ -4958,7 +4988,7 @@ class AttrDelimiter extends Rule {
|
|
|
4958
4988
|
}
|
|
4959
4989
|
|
|
4960
4990
|
const DEFAULT_PATTERN = "[a-z0-9-:]+";
|
|
4961
|
-
const defaults$
|
|
4991
|
+
const defaults$y = {
|
|
4962
4992
|
pattern: DEFAULT_PATTERN,
|
|
4963
4993
|
ignoreForeign: true
|
|
4964
4994
|
};
|
|
@@ -4991,7 +5021,7 @@ function generateDescription(name, pattern) {
|
|
|
4991
5021
|
class AttrPattern extends Rule {
|
|
4992
5022
|
pattern;
|
|
4993
5023
|
constructor(options) {
|
|
4994
|
-
super({ ...defaults$
|
|
5024
|
+
super({ ...defaults$y, ...options });
|
|
4995
5025
|
this.pattern = generateRegexp(this.options.pattern);
|
|
4996
5026
|
}
|
|
4997
5027
|
static schema() {
|
|
@@ -5038,7 +5068,7 @@ class AttrPattern extends Rule {
|
|
|
5038
5068
|
}
|
|
5039
5069
|
}
|
|
5040
5070
|
|
|
5041
|
-
const defaults$
|
|
5071
|
+
const defaults$x = {
|
|
5042
5072
|
style: "auto",
|
|
5043
5073
|
unquoted: false
|
|
5044
5074
|
};
|
|
@@ -5104,7 +5134,7 @@ class AttrQuotes extends Rule {
|
|
|
5104
5134
|
};
|
|
5105
5135
|
}
|
|
5106
5136
|
constructor(options) {
|
|
5107
|
-
super({ ...defaults$
|
|
5137
|
+
super({ ...defaults$x, ...options });
|
|
5108
5138
|
this.style = parseStyle$3(this.options.style);
|
|
5109
5139
|
}
|
|
5110
5140
|
setup() {
|
|
@@ -5186,10 +5216,10 @@ class AttrSpacing extends Rule {
|
|
|
5186
5216
|
|
|
5187
5217
|
function pick(attr) {
|
|
5188
5218
|
const result = {};
|
|
5189
|
-
if (
|
|
5219
|
+
if (attr.enum !== void 0) {
|
|
5190
5220
|
result.enum = attr.enum;
|
|
5191
5221
|
}
|
|
5192
|
-
if (
|
|
5222
|
+
if (attr.boolean !== void 0) {
|
|
5193
5223
|
result.boolean = attr.boolean;
|
|
5194
5224
|
}
|
|
5195
5225
|
return result;
|
|
@@ -5260,13 +5290,13 @@ class AttributeAllowedValues extends Rule {
|
|
|
5260
5290
|
}
|
|
5261
5291
|
}
|
|
5262
5292
|
|
|
5263
|
-
const defaults$
|
|
5293
|
+
const defaults$w = {
|
|
5264
5294
|
style: "omit"
|
|
5265
5295
|
};
|
|
5266
5296
|
class AttributeBooleanStyle extends Rule {
|
|
5267
5297
|
hasInvalidStyle;
|
|
5268
5298
|
constructor(options) {
|
|
5269
|
-
super({ ...defaults$
|
|
5299
|
+
super({ ...defaults$w, ...options });
|
|
5270
5300
|
this.hasInvalidStyle = parseStyle$2(this.options.style);
|
|
5271
5301
|
}
|
|
5272
5302
|
static schema() {
|
|
@@ -5336,13 +5366,13 @@ function reportMessage$1(attr, style) {
|
|
|
5336
5366
|
return "";
|
|
5337
5367
|
}
|
|
5338
5368
|
|
|
5339
|
-
const defaults$
|
|
5369
|
+
const defaults$v = {
|
|
5340
5370
|
style: "omit"
|
|
5341
5371
|
};
|
|
5342
5372
|
class AttributeEmptyStyle extends Rule {
|
|
5343
5373
|
hasInvalidStyle;
|
|
5344
5374
|
constructor(options) {
|
|
5345
|
-
super({ ...defaults$
|
|
5375
|
+
super({ ...defaults$v, ...options });
|
|
5346
5376
|
this.hasInvalidStyle = parseStyle$1(this.options.style);
|
|
5347
5377
|
}
|
|
5348
5378
|
static schema() {
|
|
@@ -5459,7 +5489,7 @@ class AttributeMisuse extends Rule {
|
|
|
5459
5489
|
}
|
|
5460
5490
|
}
|
|
5461
5491
|
|
|
5462
|
-
const defaults$
|
|
5492
|
+
const defaults$u = {
|
|
5463
5493
|
preferred: void 0
|
|
5464
5494
|
};
|
|
5465
5495
|
function isPasswordInput(event) {
|
|
@@ -5476,7 +5506,7 @@ function isGroupingToken(token) {
|
|
|
5476
5506
|
class AutocompletePassword extends Rule {
|
|
5477
5507
|
preferred;
|
|
5478
5508
|
constructor(options) {
|
|
5479
|
-
super({ ...defaults$
|
|
5509
|
+
super({ ...defaults$u, ...options });
|
|
5480
5510
|
this.preferred = options.preferred?.toLowerCase();
|
|
5481
5511
|
}
|
|
5482
5512
|
static schema() {
|
|
@@ -5555,21 +5585,19 @@ class AutocompletePassword extends Rule {
|
|
|
5555
5585
|
});
|
|
5556
5586
|
return;
|
|
5557
5587
|
}
|
|
5558
|
-
if (preferred) {
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
});
|
|
5572
|
-
}
|
|
5588
|
+
if (preferred && value !== preferred) {
|
|
5589
|
+
const context = {
|
|
5590
|
+
kind: "preferred-mismatch",
|
|
5591
|
+
value,
|
|
5592
|
+
preferred
|
|
5593
|
+
};
|
|
5594
|
+
this.report({
|
|
5595
|
+
node: target,
|
|
5596
|
+
message: `<input type="password"> should use autocomplete="${preferred}"`,
|
|
5597
|
+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- location must be present if value is */
|
|
5598
|
+
location,
|
|
5599
|
+
context
|
|
5600
|
+
});
|
|
5573
5601
|
}
|
|
5574
5602
|
});
|
|
5575
5603
|
}
|
|
@@ -5706,7 +5734,7 @@ class BasePatternRule extends Rule {
|
|
|
5706
5734
|
}
|
|
5707
5735
|
}
|
|
5708
5736
|
|
|
5709
|
-
const defaults$
|
|
5737
|
+
const defaults$t = {
|
|
5710
5738
|
pattern: "kebabcase"
|
|
5711
5739
|
};
|
|
5712
5740
|
class ClassPattern extends BasePatternRule {
|
|
@@ -5714,7 +5742,7 @@ class ClassPattern extends BasePatternRule {
|
|
|
5714
5742
|
super({
|
|
5715
5743
|
ruleId: "class-pattern",
|
|
5716
5744
|
attr: "class",
|
|
5717
|
-
options: { ...defaults$
|
|
5745
|
+
options: { ...defaults$t, ...options },
|
|
5718
5746
|
allowedPatterns: patternNames
|
|
5719
5747
|
// allow all patterns
|
|
5720
5748
|
});
|
|
@@ -5864,13 +5892,13 @@ class CloseOrder extends Rule {
|
|
|
5864
5892
|
}
|
|
5865
5893
|
}
|
|
5866
5894
|
|
|
5867
|
-
const defaults$
|
|
5895
|
+
const defaults$s = {
|
|
5868
5896
|
include: null,
|
|
5869
5897
|
exclude: null
|
|
5870
5898
|
};
|
|
5871
5899
|
class Deprecated extends Rule {
|
|
5872
5900
|
constructor(options) {
|
|
5873
|
-
super({ ...defaults$
|
|
5901
|
+
super({ ...defaults$s, ...options });
|
|
5874
5902
|
}
|
|
5875
5903
|
static schema() {
|
|
5876
5904
|
return {
|
|
@@ -5916,7 +5944,7 @@ class Deprecated extends Rule {
|
|
|
5916
5944
|
text.push(context.documentation);
|
|
5917
5945
|
}
|
|
5918
5946
|
const doc = {
|
|
5919
|
-
description: text.map((cur) => cur.
|
|
5947
|
+
description: text.map((cur) => cur.replaceAll("$tagname", context.tagName)).join("\n\n"),
|
|
5920
5948
|
url: "https://html-validate.org/rules/deprecated.html"
|
|
5921
5949
|
};
|
|
5922
5950
|
return doc;
|
|
@@ -5982,7 +6010,7 @@ function quote(value, char = '"') {
|
|
|
5982
6010
|
return `${char}${value}${char}`;
|
|
5983
6011
|
}
|
|
5984
6012
|
|
|
5985
|
-
const defaults$
|
|
6013
|
+
const defaults$r = {
|
|
5986
6014
|
classes: []
|
|
5987
6015
|
};
|
|
5988
6016
|
function isRelevant$6(event) {
|
|
@@ -6036,7 +6064,7 @@ ${listItems.join("\n")}`);
|
|
|
6036
6064
|
class DeprecatedClass extends Rule {
|
|
6037
6065
|
deprecatedMap;
|
|
6038
6066
|
constructor(options) {
|
|
6039
|
-
super({ ...defaults$
|
|
6067
|
+
super({ ...defaults$r, ...options });
|
|
6040
6068
|
const { classes } = this.options;
|
|
6041
6069
|
this.deprecatedMap = new Map(classes.map((entry) => [entry.class, normalizeEntry(entry)]));
|
|
6042
6070
|
}
|
|
@@ -6155,12 +6183,12 @@ let NoStyleTag$1 = class NoStyleTag extends Rule {
|
|
|
6155
6183
|
}
|
|
6156
6184
|
};
|
|
6157
6185
|
|
|
6158
|
-
const defaults$
|
|
6186
|
+
const defaults$q = {
|
|
6159
6187
|
style: "uppercase"
|
|
6160
6188
|
};
|
|
6161
6189
|
class DoctypeStyle extends Rule {
|
|
6162
6190
|
constructor(options) {
|
|
6163
|
-
super({ ...defaults$
|
|
6191
|
+
super({ ...defaults$q, ...options });
|
|
6164
6192
|
}
|
|
6165
6193
|
static schema() {
|
|
6166
6194
|
return {
|
|
@@ -6188,13 +6216,13 @@ class DoctypeStyle extends Rule {
|
|
|
6188
6216
|
}
|
|
6189
6217
|
}
|
|
6190
6218
|
|
|
6191
|
-
const defaults$
|
|
6219
|
+
const defaults$p = {
|
|
6192
6220
|
style: "lowercase"
|
|
6193
6221
|
};
|
|
6194
6222
|
class ElementCase extends Rule {
|
|
6195
6223
|
style;
|
|
6196
6224
|
constructor(options) {
|
|
6197
|
-
super({ ...defaults$
|
|
6225
|
+
super({ ...defaults$p, ...options });
|
|
6198
6226
|
this.style = new CaseStyle(this.options.style, "element-case");
|
|
6199
6227
|
}
|
|
6200
6228
|
static schema() {
|
|
@@ -6235,7 +6263,7 @@ class ElementCase extends Rule {
|
|
|
6235
6263
|
});
|
|
6236
6264
|
}
|
|
6237
6265
|
validateCase(target, targetLocation) {
|
|
6238
|
-
const letters = target.tagName.
|
|
6266
|
+
const letters = target.tagName.replaceAll(/[^a-z]+/gi, "");
|
|
6239
6267
|
if (!this.style.match(letters)) {
|
|
6240
6268
|
const location = sliceLocation(targetLocation, 1);
|
|
6241
6269
|
this.report(target, `Element "${target.tagName}" should be ${this.style.name}`, location);
|
|
@@ -6254,7 +6282,7 @@ class ElementCase extends Rule {
|
|
|
6254
6282
|
}
|
|
6255
6283
|
}
|
|
6256
6284
|
|
|
6257
|
-
const defaults$
|
|
6285
|
+
const defaults$o = {
|
|
6258
6286
|
pattern: "^[a-z][a-z0-9\\-._]*-[a-z0-9\\-._]*$",
|
|
6259
6287
|
whitelist: [],
|
|
6260
6288
|
blacklist: []
|
|
@@ -6262,7 +6290,7 @@ const defaults$n = {
|
|
|
6262
6290
|
class ElementName extends Rule {
|
|
6263
6291
|
pattern;
|
|
6264
6292
|
constructor(options) {
|
|
6265
|
-
super({ ...defaults$
|
|
6293
|
+
super({ ...defaults$o, ...options });
|
|
6266
6294
|
this.pattern = new RegExp(this.options.pattern);
|
|
6267
6295
|
}
|
|
6268
6296
|
static schema() {
|
|
@@ -6299,7 +6327,7 @@ class ElementName extends Rule {
|
|
|
6299
6327
|
...context.blacklist.map((cur) => `- ${cur}`)
|
|
6300
6328
|
];
|
|
6301
6329
|
}
|
|
6302
|
-
if (context.pattern !== defaults$
|
|
6330
|
+
if (context.pattern !== defaults$o.pattern) {
|
|
6303
6331
|
return [
|
|
6304
6332
|
`<${context.tagName}> is not a valid element name. This project is configured to only allow names matching the following regular expression:`,
|
|
6305
6333
|
"",
|
|
@@ -6816,7 +6844,7 @@ class EmptyTitle extends Rule {
|
|
|
6816
6844
|
}
|
|
6817
6845
|
}
|
|
6818
6846
|
|
|
6819
|
-
const defaults$
|
|
6847
|
+
const defaults$n = {
|
|
6820
6848
|
allowArrayBrackets: true,
|
|
6821
6849
|
allowCheckboxDefault: true,
|
|
6822
6850
|
shared: ["radio", "button", "reset", "submit"]
|
|
@@ -6839,8 +6867,8 @@ function haveName(name) {
|
|
|
6839
6867
|
return typeof name === "string" && name !== "";
|
|
6840
6868
|
}
|
|
6841
6869
|
function allowSharedName(node, shared) {
|
|
6842
|
-
const type = node
|
|
6843
|
-
return
|
|
6870
|
+
const type = getControlType(node);
|
|
6871
|
+
return shared.includes(type);
|
|
6844
6872
|
}
|
|
6845
6873
|
function isInputHidden(element) {
|
|
6846
6874
|
return element.is("input") && element.getAttributeValue("type") === "hidden";
|
|
@@ -6848,6 +6876,13 @@ function isInputHidden(element) {
|
|
|
6848
6876
|
function isInputCheckbox(element) {
|
|
6849
6877
|
return element.is("input") && element.getAttributeValue("type") === "checkbox";
|
|
6850
6878
|
}
|
|
6879
|
+
function getControlType(element) {
|
|
6880
|
+
const type = element.getAttributeValue("type") ?? "";
|
|
6881
|
+
if (element.is("button") && type === "") {
|
|
6882
|
+
return "submit";
|
|
6883
|
+
}
|
|
6884
|
+
return type;
|
|
6885
|
+
}
|
|
6851
6886
|
function isCheckboxWithDefault(control, previous, options) {
|
|
6852
6887
|
const { allowCheckboxDefault } = options;
|
|
6853
6888
|
if (!allowCheckboxDefault) {
|
|
@@ -6876,7 +6911,7 @@ function getDocumentation(context) {
|
|
|
6876
6911
|
}
|
|
6877
6912
|
class FormDupName extends Rule {
|
|
6878
6913
|
constructor(options) {
|
|
6879
|
-
super({ ...defaults$
|
|
6914
|
+
super({ ...defaults$n, ...options });
|
|
6880
6915
|
}
|
|
6881
6916
|
static schema() {
|
|
6882
6917
|
return {
|
|
@@ -6985,7 +7020,7 @@ class FormDupName extends Rule {
|
|
|
6985
7020
|
validateSharedName(control, group, attr, name) {
|
|
6986
7021
|
const uniqueElements = this.getUniqueElements(group);
|
|
6987
7022
|
const sharedElements = this.getSharedElements(group);
|
|
6988
|
-
const type = control
|
|
7023
|
+
const type = getControlType(control);
|
|
6989
7024
|
if (uniqueElements.has(name) || sharedElements.has(name) && sharedElements.get(name) !== type) {
|
|
6990
7025
|
const context = {
|
|
6991
7026
|
name,
|
|
@@ -7035,7 +7070,7 @@ class FormDupName extends Rule {
|
|
|
7035
7070
|
}
|
|
7036
7071
|
}
|
|
7037
7072
|
|
|
7038
|
-
const defaults$
|
|
7073
|
+
const defaults$m = {
|
|
7039
7074
|
allowMultipleH1: false,
|
|
7040
7075
|
minInitialRank: "h1",
|
|
7041
7076
|
sectioningRoots: ["dialog", '[role="dialog"]', '[role="alertdialog"]']
|
|
@@ -7047,7 +7082,7 @@ function isRelevant$5(event) {
|
|
|
7047
7082
|
function extractLevel(node) {
|
|
7048
7083
|
const match = /^[hH](\d)$/.exec(node.tagName);
|
|
7049
7084
|
if (match) {
|
|
7050
|
-
return parseInt(match[1], 10);
|
|
7085
|
+
return Number.parseInt(match[1], 10);
|
|
7051
7086
|
} else {
|
|
7052
7087
|
return null;
|
|
7053
7088
|
}
|
|
@@ -7060,14 +7095,14 @@ function parseMaxInitial(value) {
|
|
|
7060
7095
|
if (!match) {
|
|
7061
7096
|
return 1;
|
|
7062
7097
|
}
|
|
7063
|
-
return parseInt(match[1], 10);
|
|
7098
|
+
return Number.parseInt(match[1], 10);
|
|
7064
7099
|
}
|
|
7065
7100
|
class HeadingLevel extends Rule {
|
|
7066
7101
|
minInitialRank;
|
|
7067
7102
|
sectionRoots;
|
|
7068
7103
|
stack = [];
|
|
7069
7104
|
constructor(options) {
|
|
7070
|
-
super({ ...defaults$
|
|
7105
|
+
super({ ...defaults$m, ...options });
|
|
7071
7106
|
this.minInitialRank = parseMaxInitial(this.options.minInitialRank);
|
|
7072
7107
|
this.sectionRoots = this.options.sectioningRoots.map((it) => new Compound(it));
|
|
7073
7108
|
this.stack.push({
|
|
@@ -7209,10 +7244,10 @@ class HeadingLevel extends Rule {
|
|
|
7209
7244
|
this.stack.pop();
|
|
7210
7245
|
}
|
|
7211
7246
|
getPrevRoot() {
|
|
7212
|
-
return this.stack
|
|
7247
|
+
return this.stack.at(-2);
|
|
7213
7248
|
}
|
|
7214
7249
|
getCurrentRoot() {
|
|
7215
|
-
return this.stack
|
|
7250
|
+
return this.stack.at(-1);
|
|
7216
7251
|
}
|
|
7217
7252
|
isSectioningRoot(node) {
|
|
7218
7253
|
const context = {
|
|
@@ -7306,7 +7341,7 @@ class HiddenFocusable extends Rule {
|
|
|
7306
7341
|
}
|
|
7307
7342
|
}
|
|
7308
7343
|
|
|
7309
|
-
const defaults$
|
|
7344
|
+
const defaults$l = {
|
|
7310
7345
|
pattern: "kebabcase"
|
|
7311
7346
|
};
|
|
7312
7347
|
function exclude$1(set, ...values) {
|
|
@@ -7322,7 +7357,7 @@ class IdPattern extends BasePatternRule {
|
|
|
7322
7357
|
super({
|
|
7323
7358
|
ruleId: "id-pattern",
|
|
7324
7359
|
attr: "id",
|
|
7325
|
-
options: { ...defaults$
|
|
7360
|
+
options: { ...defaults$l, ...options },
|
|
7326
7361
|
allowedPatterns
|
|
7327
7362
|
});
|
|
7328
7363
|
}
|
|
@@ -7644,13 +7679,13 @@ function findLabelByParent(el) {
|
|
|
7644
7679
|
return [];
|
|
7645
7680
|
}
|
|
7646
7681
|
|
|
7647
|
-
const defaults$
|
|
7682
|
+
const defaults$k = {
|
|
7648
7683
|
maxlength: 70
|
|
7649
7684
|
};
|
|
7650
7685
|
class LongTitle extends Rule {
|
|
7651
7686
|
maxlength;
|
|
7652
7687
|
constructor(options) {
|
|
7653
|
-
super({ ...defaults$
|
|
7688
|
+
super({ ...defaults$k, ...options });
|
|
7654
7689
|
this.maxlength = this.options.maxlength;
|
|
7655
7690
|
}
|
|
7656
7691
|
static schema() {
|
|
@@ -7754,12 +7789,12 @@ class MapIdName extends Rule {
|
|
|
7754
7789
|
}
|
|
7755
7790
|
}
|
|
7756
7791
|
|
|
7757
|
-
const defaults$
|
|
7792
|
+
const defaults$j = {
|
|
7758
7793
|
allowLongDelay: false
|
|
7759
7794
|
};
|
|
7760
7795
|
class MetaRefresh extends Rule {
|
|
7761
7796
|
constructor(options) {
|
|
7762
|
-
super({ ...defaults$
|
|
7797
|
+
super({ ...defaults$j, ...options });
|
|
7763
7798
|
}
|
|
7764
7799
|
documentation() {
|
|
7765
7800
|
return {
|
|
@@ -7809,7 +7844,7 @@ function parseContent(text) {
|
|
|
7809
7844
|
const match = /^(\d+)(?:\s*;\s*url=(.*))?/i.exec(text);
|
|
7810
7845
|
if (match) {
|
|
7811
7846
|
return {
|
|
7812
|
-
delay: parseInt(match[1], 10),
|
|
7847
|
+
delay: Number.parseInt(match[1], 10),
|
|
7813
7848
|
url: match[2]
|
|
7814
7849
|
};
|
|
7815
7850
|
} else {
|
|
@@ -7870,7 +7905,7 @@ class MultipleLabeledControls extends Rule {
|
|
|
7870
7905
|
}
|
|
7871
7906
|
}
|
|
7872
7907
|
|
|
7873
|
-
const defaults$
|
|
7908
|
+
const defaults$i = {
|
|
7874
7909
|
pattern: "camelcase"
|
|
7875
7910
|
};
|
|
7876
7911
|
function exclude(set, ...values) {
|
|
@@ -7886,7 +7921,7 @@ class NamePattern extends BasePatternRule {
|
|
|
7886
7921
|
super({
|
|
7887
7922
|
ruleId: "name-pattern",
|
|
7888
7923
|
attr: "name",
|
|
7889
|
-
options: { ...defaults$
|
|
7924
|
+
options: { ...defaults$i, ...options },
|
|
7890
7925
|
allowedPatterns
|
|
7891
7926
|
});
|
|
7892
7927
|
}
|
|
@@ -7977,13 +8012,13 @@ class NoAbstractRole extends Rule {
|
|
|
7977
8012
|
}
|
|
7978
8013
|
}
|
|
7979
8014
|
|
|
7980
|
-
const defaults$
|
|
8015
|
+
const defaults$h = {
|
|
7981
8016
|
include: null,
|
|
7982
8017
|
exclude: null
|
|
7983
8018
|
};
|
|
7984
8019
|
class NoAutoplay extends Rule {
|
|
7985
8020
|
constructor(options) {
|
|
7986
|
-
super({ ...defaults$
|
|
8021
|
+
super({ ...defaults$h, ...options });
|
|
7987
8022
|
}
|
|
7988
8023
|
documentation(context) {
|
|
7989
8024
|
return {
|
|
@@ -8133,13 +8168,12 @@ class NoDupClass extends Rule {
|
|
|
8133
8168
|
}
|
|
8134
8169
|
const classes = new DOMTokenList(event.value, event.valueLocation);
|
|
8135
8170
|
const unique = /* @__PURE__ */ new Set();
|
|
8136
|
-
classes.
|
|
8137
|
-
if (unique.has(
|
|
8138
|
-
|
|
8139
|
-
this.report(event.target, `Class "${cur}" duplicated`, location);
|
|
8171
|
+
for (const { item, location } of classes.iterator()) {
|
|
8172
|
+
if (unique.has(item)) {
|
|
8173
|
+
this.report(event.target, `Class "${item}" duplicated`, location);
|
|
8140
8174
|
}
|
|
8141
|
-
unique.add(
|
|
8142
|
-
}
|
|
8175
|
+
unique.add(item);
|
|
8176
|
+
}
|
|
8143
8177
|
});
|
|
8144
8178
|
}
|
|
8145
8179
|
}
|
|
@@ -8305,14 +8339,14 @@ class NoImplicitInputType extends Rule {
|
|
|
8305
8339
|
}
|
|
8306
8340
|
}
|
|
8307
8341
|
|
|
8308
|
-
const defaults$
|
|
8342
|
+
const defaults$g = {
|
|
8309
8343
|
include: null,
|
|
8310
8344
|
exclude: null,
|
|
8311
8345
|
allowedProperties: ["display"]
|
|
8312
8346
|
};
|
|
8313
8347
|
class NoInlineStyle extends Rule {
|
|
8314
8348
|
constructor(options) {
|
|
8315
|
-
super({ ...defaults$
|
|
8349
|
+
super({ ...defaults$g, ...options });
|
|
8316
8350
|
}
|
|
8317
8351
|
static schema() {
|
|
8318
8352
|
return {
|
|
@@ -8498,7 +8532,7 @@ class NoMultipleMain extends Rule {
|
|
|
8498
8532
|
}
|
|
8499
8533
|
}
|
|
8500
8534
|
|
|
8501
|
-
const defaults$
|
|
8535
|
+
const defaults$f = {
|
|
8502
8536
|
relaxed: false
|
|
8503
8537
|
};
|
|
8504
8538
|
const textRegexp = /([<>]|&(?![a-zA-Z0-9#]+;))/g;
|
|
@@ -8516,7 +8550,7 @@ const replacementTable = {
|
|
|
8516
8550
|
class NoRawCharacters extends Rule {
|
|
8517
8551
|
relaxed;
|
|
8518
8552
|
constructor(options) {
|
|
8519
|
-
super({ ...defaults$
|
|
8553
|
+
super({ ...defaults$f, ...options });
|
|
8520
8554
|
this.relaxed = this.options.relaxed;
|
|
8521
8555
|
}
|
|
8522
8556
|
static schema() {
|
|
@@ -8655,7 +8689,14 @@ class NoRedundantFor extends Rule {
|
|
|
8655
8689
|
}
|
|
8656
8690
|
}
|
|
8657
8691
|
|
|
8692
|
+
const defaults$e = {
|
|
8693
|
+
include: null,
|
|
8694
|
+
exclude: null
|
|
8695
|
+
};
|
|
8658
8696
|
class NoRedundantRole extends Rule {
|
|
8697
|
+
constructor(options) {
|
|
8698
|
+
super({ ...defaults$e, ...options });
|
|
8699
|
+
}
|
|
8659
8700
|
documentation(context) {
|
|
8660
8701
|
const { role, tagName } = context;
|
|
8661
8702
|
return {
|
|
@@ -8663,6 +8704,36 @@ class NoRedundantRole extends Rule {
|
|
|
8663
8704
|
url: "https://html-validate.org/rules/no-redundant-role.html"
|
|
8664
8705
|
};
|
|
8665
8706
|
}
|
|
8707
|
+
static schema() {
|
|
8708
|
+
return {
|
|
8709
|
+
exclude: {
|
|
8710
|
+
anyOf: [
|
|
8711
|
+
{
|
|
8712
|
+
items: {
|
|
8713
|
+
type: "string"
|
|
8714
|
+
},
|
|
8715
|
+
type: "array"
|
|
8716
|
+
},
|
|
8717
|
+
{
|
|
8718
|
+
type: "null"
|
|
8719
|
+
}
|
|
8720
|
+
]
|
|
8721
|
+
},
|
|
8722
|
+
include: {
|
|
8723
|
+
anyOf: [
|
|
8724
|
+
{
|
|
8725
|
+
items: {
|
|
8726
|
+
type: "string"
|
|
8727
|
+
},
|
|
8728
|
+
type: "array"
|
|
8729
|
+
},
|
|
8730
|
+
{
|
|
8731
|
+
type: "null"
|
|
8732
|
+
}
|
|
8733
|
+
]
|
|
8734
|
+
}
|
|
8735
|
+
};
|
|
8736
|
+
}
|
|
8666
8737
|
setup() {
|
|
8667
8738
|
this.on("tag:ready", (event) => {
|
|
8668
8739
|
const { target } = event;
|
|
@@ -8681,6 +8752,9 @@ class NoRedundantRole extends Rule {
|
|
|
8681
8752
|
if (role.value !== implicitRole) {
|
|
8682
8753
|
return;
|
|
8683
8754
|
}
|
|
8755
|
+
if (this.isKeywordIgnored(role.value)) {
|
|
8756
|
+
return;
|
|
8757
|
+
}
|
|
8684
8758
|
const context = {
|
|
8685
8759
|
tagName: target.tagName,
|
|
8686
8760
|
role: role.value
|
|
@@ -8871,10 +8945,10 @@ class NoUnusedDisable extends Rule {
|
|
|
8871
8945
|
setup() {
|
|
8872
8946
|
}
|
|
8873
8947
|
reportUnused(unused, options, location) {
|
|
8874
|
-
const tokens = new DOMTokenList(options.
|
|
8948
|
+
const tokens = new DOMTokenList(options.replaceAll(",", " "), location);
|
|
8875
8949
|
for (const ruleId of unused) {
|
|
8876
8950
|
const index = tokens.indexOf(ruleId);
|
|
8877
|
-
const tokenLocation = index
|
|
8951
|
+
const tokenLocation = index !== -1 ? tokens.location(index) : location;
|
|
8878
8952
|
this.report({
|
|
8879
8953
|
node: null,
|
|
8880
8954
|
message: '"{{ ruleId }}" rule is disabled but no error was reported',
|
|
@@ -9122,7 +9196,7 @@ class PreferTbody extends Rule {
|
|
|
9122
9196
|
continue;
|
|
9123
9197
|
}
|
|
9124
9198
|
const tr = table.querySelectorAll("> tr");
|
|
9125
|
-
if (tr.length
|
|
9199
|
+
if (tr.length > 0) {
|
|
9126
9200
|
this.report(tr[0], "Prefer to wrap <tr> elements in <tbody>");
|
|
9127
9201
|
}
|
|
9128
9202
|
}
|
|
@@ -9192,19 +9266,19 @@ const supportSri = {
|
|
|
9192
9266
|
link: "href",
|
|
9193
9267
|
script: "src"
|
|
9194
9268
|
};
|
|
9195
|
-
const supportedRel = ["stylesheet", "preload", "modulepreload"];
|
|
9196
|
-
const supportedPreload = ["style", "script"];
|
|
9269
|
+
const supportedRel = /* @__PURE__ */ new Set(["stylesheet", "preload", "modulepreload"]);
|
|
9270
|
+
const supportedPreload = /* @__PURE__ */ new Set(["style", "script"]);
|
|
9197
9271
|
function linkSupportsSri(node) {
|
|
9198
9272
|
const rel = node.getAttribute("rel");
|
|
9199
9273
|
if (typeof rel?.value !== "string") {
|
|
9200
9274
|
return false;
|
|
9201
9275
|
}
|
|
9202
|
-
if (!supportedRel.
|
|
9276
|
+
if (!supportedRel.has(rel.value)) {
|
|
9203
9277
|
return false;
|
|
9204
9278
|
}
|
|
9205
9279
|
if (rel.value === "preload") {
|
|
9206
9280
|
const as = node.getAttribute("as");
|
|
9207
|
-
return typeof as?.value === "string" && supportedPreload.
|
|
9281
|
+
return typeof as?.value === "string" && supportedPreload.has(as.value);
|
|
9208
9282
|
}
|
|
9209
9283
|
return true;
|
|
9210
9284
|
}
|
|
@@ -9321,13 +9395,13 @@ class ScriptElement extends Rule {
|
|
|
9321
9395
|
}
|
|
9322
9396
|
}
|
|
9323
9397
|
|
|
9324
|
-
const javascript = [
|
|
9398
|
+
const javascript = /* @__PURE__ */ new Set([
|
|
9325
9399
|
"",
|
|
9326
9400
|
"application/ecmascript",
|
|
9327
9401
|
"application/javascript",
|
|
9328
9402
|
"text/ecmascript",
|
|
9329
9403
|
"text/javascript"
|
|
9330
|
-
];
|
|
9404
|
+
]);
|
|
9331
9405
|
class ScriptType extends Rule {
|
|
9332
9406
|
documentation() {
|
|
9333
9407
|
return {
|
|
@@ -9358,7 +9432,7 @@ class ScriptType extends Rule {
|
|
|
9358
9432
|
}
|
|
9359
9433
|
isJavascript(mime) {
|
|
9360
9434
|
const type = mime.replace(/;.*/, "");
|
|
9361
|
-
return javascript.
|
|
9435
|
+
return javascript.has(type);
|
|
9362
9436
|
}
|
|
9363
9437
|
}
|
|
9364
9438
|
|
|
@@ -9934,7 +10008,7 @@ class UnknownCharReference extends Rule {
|
|
|
9934
10008
|
}
|
|
9935
10009
|
|
|
9936
10010
|
const expectedOrder = ["section", "hint", "contact", "field1", "field2", "webauthn"];
|
|
9937
|
-
const fieldNames1 = [
|
|
10011
|
+
const fieldNames1 = /* @__PURE__ */ new Set([
|
|
9938
10012
|
"name",
|
|
9939
10013
|
"honorific-prefix",
|
|
9940
10014
|
"given-name",
|
|
@@ -9979,8 +10053,8 @@ const fieldNames1 = [
|
|
|
9979
10053
|
"sex",
|
|
9980
10054
|
"url",
|
|
9981
10055
|
"photo"
|
|
9982
|
-
];
|
|
9983
|
-
const fieldNames2 = [
|
|
10056
|
+
]);
|
|
10057
|
+
const fieldNames2 = /* @__PURE__ */ new Set([
|
|
9984
10058
|
"tel",
|
|
9985
10059
|
"tel-country-code",
|
|
9986
10060
|
"tel-national",
|
|
@@ -9991,7 +10065,7 @@ const fieldNames2 = [
|
|
|
9991
10065
|
"tel-extension",
|
|
9992
10066
|
"email",
|
|
9993
10067
|
"impp"
|
|
9994
|
-
];
|
|
10068
|
+
]);
|
|
9995
10069
|
const fieldNameGroup = {
|
|
9996
10070
|
name: "text",
|
|
9997
10071
|
"honorific-prefix": "text",
|
|
@@ -10056,14 +10130,14 @@ function matchHint(token) {
|
|
|
10056
10130
|
return token === "shipping" || token === "billing";
|
|
10057
10131
|
}
|
|
10058
10132
|
function matchFieldNames1(token) {
|
|
10059
|
-
return fieldNames1.
|
|
10133
|
+
return fieldNames1.has(token);
|
|
10060
10134
|
}
|
|
10061
10135
|
function matchContact(token) {
|
|
10062
10136
|
const haystack = ["home", "work", "mobile", "fax", "pager"];
|
|
10063
10137
|
return haystack.includes(token);
|
|
10064
10138
|
}
|
|
10065
10139
|
function matchFieldNames2(token) {
|
|
10066
|
-
return fieldNames2.
|
|
10140
|
+
return fieldNames2.has(token);
|
|
10067
10141
|
}
|
|
10068
10142
|
function matchWebauthn(token) {
|
|
10069
10143
|
return token === "webauthn";
|
|
@@ -10734,11 +10808,13 @@ class H32 extends Rule {
|
|
|
10734
10808
|
setup() {
|
|
10735
10809
|
const formTags = this.getTagsWithProperty("form");
|
|
10736
10810
|
const formSelector = formTags.join(",");
|
|
10811
|
+
const submitButtonTags = this.getTagsWithProperty("submitButton");
|
|
10812
|
+
const submitButtonSelector = submitButtonTags.join(",");
|
|
10737
10813
|
this.on("dom:ready", (event) => {
|
|
10738
10814
|
const { document } = event;
|
|
10739
10815
|
const forms = document.querySelectorAll(formSelector);
|
|
10740
10816
|
for (const form of forms) {
|
|
10741
|
-
if (hasNestedSubmit(form)) {
|
|
10817
|
+
if (hasNestedSubmit(form, submitButtonSelector)) {
|
|
10742
10818
|
continue;
|
|
10743
10819
|
}
|
|
10744
10820
|
if (hasAssociatedSubmit(document, form)) {
|
|
@@ -10750,15 +10826,15 @@ class H32 extends Rule {
|
|
|
10750
10826
|
}
|
|
10751
10827
|
}
|
|
10752
10828
|
function isSubmit(node) {
|
|
10753
|
-
const
|
|
10754
|
-
return
|
|
10829
|
+
const meta = node.meta;
|
|
10830
|
+
return Boolean(meta?.submitButton);
|
|
10755
10831
|
}
|
|
10756
10832
|
function isAssociated(id, node) {
|
|
10757
10833
|
const form = node.getAttribute("form");
|
|
10758
10834
|
return Boolean(form?.valueMatches(id, true));
|
|
10759
10835
|
}
|
|
10760
|
-
function hasNestedSubmit(form) {
|
|
10761
|
-
const matches = form.querySelectorAll(
|
|
10836
|
+
function hasNestedSubmit(form, submitButtonSelector) {
|
|
10837
|
+
const matches = form.querySelectorAll(submitButtonSelector).filter(isSubmit).filter((node) => !node.hasAttribute("form"));
|
|
10762
10838
|
return matches.length > 0;
|
|
10763
10839
|
}
|
|
10764
10840
|
function hasAssociatedSubmit(document, form) {
|
|
@@ -10904,7 +10980,7 @@ function isSimpleTable(table) {
|
|
|
10904
10980
|
}
|
|
10905
10981
|
const shape = getShape(cells);
|
|
10906
10982
|
const headersPerRow = cells.map((row) => row.reduce((sum, cell) => sum + cell, 0));
|
|
10907
|
-
const headersPerColumn = Array(shape.cols).fill(0).map((_, index) => {
|
|
10983
|
+
const headersPerColumn = new Array(shape.cols).fill(0).map((_, index) => {
|
|
10908
10984
|
return cells.reduce((sum, it) => sum + it[index], 0);
|
|
10909
10985
|
});
|
|
10910
10986
|
const [firstRow, ...otherRows] = headersPerRow;
|
|
@@ -11307,11 +11383,11 @@ function dumpTree(root) {
|
|
|
11307
11383
|
} else {
|
|
11308
11384
|
lines.push("(root)");
|
|
11309
11385
|
}
|
|
11310
|
-
node.childElements.
|
|
11386
|
+
for (const [index, child] of node.childElements.entries()) {
|
|
11311
11387
|
const s = lastSibling ? " " : "\u2502";
|
|
11312
11388
|
const i = level > 0 ? `${indent}${s} ` : "";
|
|
11313
11389
|
writeNode(child, level + 1, i, index);
|
|
11314
|
-
}
|
|
11390
|
+
}
|
|
11315
11391
|
}
|
|
11316
11392
|
writeNode(root, 0, "", 0);
|
|
11317
11393
|
return lines;
|
|
@@ -12426,7 +12502,7 @@ class EventHandler {
|
|
|
12426
12502
|
}
|
|
12427
12503
|
|
|
12428
12504
|
const name = "html-validate";
|
|
12429
|
-
const version = "10.
|
|
12505
|
+
const version = "10.11.0";
|
|
12430
12506
|
const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
|
|
12431
12507
|
|
|
12432
12508
|
function freeze(src) {
|
|
@@ -12442,7 +12518,13 @@ function isThenableArray(value) {
|
|
|
12442
12518
|
return isThenable(value[0]);
|
|
12443
12519
|
}
|
|
12444
12520
|
class Reporter {
|
|
12521
|
+
/**
|
|
12522
|
+
* @internal
|
|
12523
|
+
*/
|
|
12445
12524
|
result;
|
|
12525
|
+
/**
|
|
12526
|
+
* @internal
|
|
12527
|
+
*/
|
|
12446
12528
|
constructor() {
|
|
12447
12529
|
this.result = {};
|
|
12448
12530
|
}
|
|
@@ -12455,16 +12537,16 @@ class Reporter {
|
|
|
12455
12537
|
}
|
|
12456
12538
|
const valid = reports.every((report) => report.valid);
|
|
12457
12539
|
const merged = {};
|
|
12458
|
-
|
|
12459
|
-
report.results
|
|
12540
|
+
for (const report of reports) {
|
|
12541
|
+
for (const result of report.results) {
|
|
12460
12542
|
const key = result.filePath;
|
|
12461
12543
|
if (key in merged) {
|
|
12462
12544
|
merged[key].messages = [...merged[key].messages, ...result.messages];
|
|
12463
12545
|
} else {
|
|
12464
12546
|
merged[key] = { ...result };
|
|
12465
12547
|
}
|
|
12466
|
-
}
|
|
12467
|
-
}
|
|
12548
|
+
}
|
|
12549
|
+
}
|
|
12468
12550
|
const results = Object.values(merged).map((result) => {
|
|
12469
12551
|
result.errorCount = countErrors(result.messages);
|
|
12470
12552
|
result.warningCount = countWarnings(result.messages);
|
|
@@ -12477,8 +12559,11 @@ class Reporter {
|
|
|
12477
12559
|
warningCount: sumWarnings(results)
|
|
12478
12560
|
};
|
|
12479
12561
|
}
|
|
12480
|
-
|
|
12481
|
-
|
|
12562
|
+
/**
|
|
12563
|
+
* @internal
|
|
12564
|
+
*/
|
|
12565
|
+
add(options) {
|
|
12566
|
+
const { rule, message, severity, node, location, context } = options;
|
|
12482
12567
|
if (!(location.filename in this.result)) {
|
|
12483
12568
|
this.result[location.filename] = [];
|
|
12484
12569
|
}
|
|
@@ -12503,17 +12588,23 @@ class Reporter {
|
|
|
12503
12588
|
}
|
|
12504
12589
|
this.result[location.filename].push(entry);
|
|
12505
12590
|
}
|
|
12591
|
+
/**
|
|
12592
|
+
* @internal
|
|
12593
|
+
*/
|
|
12506
12594
|
addManual(filename, message) {
|
|
12507
12595
|
if (!(filename in this.result)) {
|
|
12508
12596
|
this.result[filename] = [];
|
|
12509
12597
|
}
|
|
12510
12598
|
this.result[filename].push(message);
|
|
12511
12599
|
}
|
|
12600
|
+
/**
|
|
12601
|
+
* @internal
|
|
12602
|
+
*/
|
|
12512
12603
|
save(sources) {
|
|
12513
12604
|
const report = {
|
|
12514
12605
|
valid: this.isValid(),
|
|
12515
12606
|
results: Object.keys(this.result).map((filePath) => {
|
|
12516
|
-
const messages = Array.from(this.result[filePath], freeze).
|
|
12607
|
+
const messages = Array.from(this.result[filePath], freeze).toSorted(messageSort);
|
|
12517
12608
|
const source = (sources ?? []).find((source2) => filePath === source2.filename);
|
|
12518
12609
|
return {
|
|
12519
12610
|
filePath,
|
|
@@ -12530,6 +12621,9 @@ class Reporter {
|
|
|
12530
12621
|
report.warningCount = sumWarnings(report.results);
|
|
12531
12622
|
return report;
|
|
12532
12623
|
}
|
|
12624
|
+
/**
|
|
12625
|
+
* @internal
|
|
12626
|
+
*/
|
|
12533
12627
|
isValid() {
|
|
12534
12628
|
const numErrors = Object.values(this.result).reduce((sum, messages) => {
|
|
12535
12629
|
return sum + countErrors(messages);
|
|
@@ -12592,6 +12686,7 @@ class ParserError extends Error {
|
|
|
12592
12686
|
location;
|
|
12593
12687
|
constructor(location, message) {
|
|
12594
12688
|
super(message);
|
|
12689
|
+
this.name = "ParserError";
|
|
12595
12690
|
this.location = location;
|
|
12596
12691
|
}
|
|
12597
12692
|
}
|
|
@@ -12748,7 +12843,7 @@ class Parser {
|
|
|
12748
12843
|
const tokens = Array.from(
|
|
12749
12844
|
this.consumeUntil(tokenStream, TokenType.TAG_CLOSE, startToken.location)
|
|
12750
12845
|
);
|
|
12751
|
-
const endToken = tokens.
|
|
12846
|
+
const endToken = tokens.at(-1);
|
|
12752
12847
|
const closeOptional = this.closeOptional(startToken);
|
|
12753
12848
|
const parent = closeOptional ? this.dom.getActive().parent : this.dom.getActive();
|
|
12754
12849
|
const node = HtmlElement.fromTokens(
|
|
@@ -12866,7 +12961,7 @@ class Parser {
|
|
|
12866
12961
|
const endTokens = Array.from(
|
|
12867
12962
|
this.consumeUntil(tokenStream, TokenType.TAG_CLOSE, last.location)
|
|
12868
12963
|
);
|
|
12869
|
-
endToken = endTokens.
|
|
12964
|
+
endToken = endTokens.at(-1);
|
|
12870
12965
|
const selfClosed = endToken.data[0] === "/>";
|
|
12871
12966
|
if (tagClosed) {
|
|
12872
12967
|
startToken = last;
|
|
@@ -13148,7 +13243,7 @@ class Parser {
|
|
|
13148
13243
|
this.event.once("*", cb);
|
|
13149
13244
|
}
|
|
13150
13245
|
trigger(event, data) {
|
|
13151
|
-
if (
|
|
13246
|
+
if (data.location === void 0) {
|
|
13152
13247
|
throw new Error("Triggered event must contain location");
|
|
13153
13248
|
}
|
|
13154
13249
|
this.event.trigger(event, data);
|
|
@@ -13276,7 +13371,9 @@ class Engine {
|
|
|
13276
13371
|
}
|
|
13277
13372
|
lines.push({ event, data });
|
|
13278
13373
|
});
|
|
13279
|
-
|
|
13374
|
+
for (const src of source) {
|
|
13375
|
+
parser.parseHtml(src);
|
|
13376
|
+
}
|
|
13280
13377
|
return lines;
|
|
13281
13378
|
}
|
|
13282
13379
|
dumpTokens(source) {
|
|
@@ -13741,7 +13838,7 @@ const entities = {
|
|
|
13741
13838
|
"&": "&"
|
|
13742
13839
|
};
|
|
13743
13840
|
function xmlescape(src) {
|
|
13744
|
-
return src.toString().
|
|
13841
|
+
return src.toString().replaceAll(/[><'"&]/g, (match) => {
|
|
13745
13842
|
return entities[match];
|
|
13746
13843
|
});
|
|
13747
13844
|
}
|
|
@@ -13761,11 +13858,11 @@ function checkstyleFormatter(results) {
|
|
|
13761
13858
|
`;
|
|
13762
13859
|
output += `<checkstyle version="4.3">
|
|
13763
13860
|
`;
|
|
13764
|
-
|
|
13861
|
+
for (const result of results) {
|
|
13765
13862
|
const messages = result.messages;
|
|
13766
13863
|
output += ` <file name="${xmlescape(result.filePath)}">
|
|
13767
13864
|
`;
|
|
13768
|
-
|
|
13865
|
+
for (const message of messages) {
|
|
13769
13866
|
const ruleId = xmlescape(`htmlvalidate.rules.${message.ruleId}`);
|
|
13770
13867
|
output += " ";
|
|
13771
13868
|
output += [
|
|
@@ -13776,9 +13873,9 @@ function checkstyleFormatter(results) {
|
|
|
13776
13873
|
`source="${ruleId}" />`
|
|
13777
13874
|
].join(" ");
|
|
13778
13875
|
output += "\n";
|
|
13779
|
-
}
|
|
13876
|
+
}
|
|
13780
13877
|
output += " </file>\n";
|
|
13781
|
-
}
|
|
13878
|
+
}
|
|
13782
13879
|
output += "</checkstyle>\n";
|
|
13783
13880
|
return output;
|
|
13784
13881
|
}
|
|
@@ -13848,11 +13945,11 @@ function codeFrameColumns(rawLines, loc) {
|
|
|
13848
13945
|
if (hasMarker) {
|
|
13849
13946
|
let markerLine = "";
|
|
13850
13947
|
if (Array.isArray(hasMarker)) {
|
|
13851
|
-
const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).
|
|
13948
|
+
const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replaceAll(/[^\t]/g, " ");
|
|
13852
13949
|
const numberOfMarkers = hasMarker[1] || 1;
|
|
13853
13950
|
markerLine = [
|
|
13854
13951
|
"\n ",
|
|
13855
|
-
gutter.
|
|
13952
|
+
gutter.replaceAll(/\d/g, " "),
|
|
13856
13953
|
" ",
|
|
13857
13954
|
markerSpacing,
|
|
13858
13955
|
"^".repeat(numberOfMarkers)
|
|
@@ -13990,10 +14087,10 @@ function stylish(results) {
|
|
|
13990
14087
|
function textFormatter(results) {
|
|
13991
14088
|
let output = "";
|
|
13992
14089
|
let total = 0;
|
|
13993
|
-
|
|
14090
|
+
for (const result of results) {
|
|
13994
14091
|
const messages = result.messages;
|
|
13995
14092
|
if (messages.length === 0) {
|
|
13996
|
-
|
|
14093
|
+
continue;
|
|
13997
14094
|
}
|
|
13998
14095
|
total += messages.length;
|
|
13999
14096
|
output += messages.map((message) => {
|
|
@@ -14009,7 +14106,7 @@ function textFormatter(results) {
|
|
|
14009
14106
|
return `${location}: ${messageType} [${message.ruleId}] ${message.message}
|
|
14010
14107
|
`;
|
|
14011
14108
|
}).join("");
|
|
14012
|
-
}
|
|
14109
|
+
}
|
|
14013
14110
|
return total > 0 ? output : "";
|
|
14014
14111
|
}
|
|
14015
14112
|
const formatter = textFormatter;
|
|
@@ -14841,7 +14938,7 @@ var ignoreExports = /*@__PURE__*/ requireIgnore();
|
|
|
14841
14938
|
var ignore = /*@__PURE__*/getDefaultExportFromCjs(ignoreExports);
|
|
14842
14939
|
|
|
14843
14940
|
const engines = {
|
|
14844
|
-
node: "^20.19.0 || >= 22.
|
|
14941
|
+
node: "^20.19.0 || >= 22.16.0"
|
|
14845
14942
|
};
|
|
14846
14943
|
|
|
14847
14944
|
var workerPath = "./jest-worker.js";
|