html-validate 10.9.0 → 10.10.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 +179 -120
- 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 +179 -120
- 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/esm/core.js
CHANGED
|
@@ -395,6 +395,7 @@ function stringify(value) {
|
|
|
395
395
|
class WrappedError extends Error {
|
|
396
396
|
constructor(message) {
|
|
397
397
|
super(stringify(message));
|
|
398
|
+
this.name = "WrappedError";
|
|
398
399
|
}
|
|
399
400
|
}
|
|
400
401
|
|
|
@@ -409,8 +410,7 @@ function ensureError(value) {
|
|
|
409
410
|
class NestedError extends Error {
|
|
410
411
|
constructor(message, nested) {
|
|
411
412
|
super(message);
|
|
412
|
-
|
|
413
|
-
this.name = NestedError.name;
|
|
413
|
+
this.name = "NestedError";
|
|
414
414
|
if (nested?.stack) {
|
|
415
415
|
this.stack ??= "";
|
|
416
416
|
this.stack += `
|
|
@@ -422,8 +422,7 @@ Caused by: ${nested.stack}`;
|
|
|
422
422
|
class UserError extends NestedError {
|
|
423
423
|
constructor(message, nested) {
|
|
424
424
|
super(message, nested);
|
|
425
|
-
|
|
426
|
-
this.name = UserError.name;
|
|
425
|
+
this.name = "UserError";
|
|
427
426
|
Object.defineProperty(this, "isUserError", {
|
|
428
427
|
value: true,
|
|
429
428
|
enumerable: false,
|
|
@@ -446,8 +445,7 @@ class InheritError extends UserError {
|
|
|
446
445
|
constructor({ tagName, inherit }) {
|
|
447
446
|
const message = `Element <${tagName}> cannot inherit from <${inherit}>: no such element`;
|
|
448
447
|
super(message);
|
|
449
|
-
|
|
450
|
-
this.name = InheritError.name;
|
|
448
|
+
this.name = "InheritError";
|
|
451
449
|
this.tagName = tagName;
|
|
452
450
|
this.inherit = inherit;
|
|
453
451
|
this.filename = null;
|
|
@@ -489,6 +487,7 @@ class SchemaValidationError extends UserError {
|
|
|
489
487
|
constructor(filename, message, obj, schema, errors) {
|
|
490
488
|
const summary = getSummary(schema, obj, errors);
|
|
491
489
|
super(`${message}: ${summary}`);
|
|
490
|
+
this.name = "SchemaValidationError";
|
|
492
491
|
this.filename = filename;
|
|
493
492
|
this.obj = obj;
|
|
494
493
|
this.schema = schema;
|
|
@@ -636,6 +635,18 @@ const patternProperties = {
|
|
|
636
635
|
}
|
|
637
636
|
]
|
|
638
637
|
},
|
|
638
|
+
submitButton: {
|
|
639
|
+
title: "Mark this element as a submit button",
|
|
640
|
+
description: "This element can be used to submit forms.",
|
|
641
|
+
anyOf: [
|
|
642
|
+
{
|
|
643
|
+
type: "boolean"
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
"function": true
|
|
647
|
+
}
|
|
648
|
+
]
|
|
649
|
+
},
|
|
639
650
|
templateRoot: {
|
|
640
651
|
title: "Mark element as an element ignoring DOM ancestry, i.e. <template>.",
|
|
641
652
|
description: "The <template> element can contain any elements.",
|
|
@@ -1019,6 +1030,7 @@ const MetaCopyableProperty = [
|
|
|
1019
1030
|
"form",
|
|
1020
1031
|
"formAssociated",
|
|
1021
1032
|
"labelable",
|
|
1033
|
+
"submitButton",
|
|
1022
1034
|
"attributes",
|
|
1023
1035
|
"aria",
|
|
1024
1036
|
"permittedContent",
|
|
@@ -1033,7 +1045,7 @@ function setMetaProperty(dst, key, value) {
|
|
|
1033
1045
|
}
|
|
1034
1046
|
|
|
1035
1047
|
function isSet(value) {
|
|
1036
|
-
return
|
|
1048
|
+
return value !== void 0;
|
|
1037
1049
|
}
|
|
1038
1050
|
function flag(value) {
|
|
1039
1051
|
return value ? true : void 0;
|
|
@@ -1048,7 +1060,7 @@ function migrateSingleAttribute(src, key) {
|
|
|
1048
1060
|
result.required = flag(src.requiredAttributes?.includes(key));
|
|
1049
1061
|
result.omit = void 0;
|
|
1050
1062
|
const attr = src.attributes ? src.attributes[key] : void 0;
|
|
1051
|
-
if (
|
|
1063
|
+
if (attr === void 0) {
|
|
1052
1064
|
return stripUndefined(result);
|
|
1053
1065
|
}
|
|
1054
1066
|
if (attr === null) {
|
|
@@ -1075,7 +1087,7 @@ function migrateAttributes(src) {
|
|
|
1075
1087
|
...src.requiredAttributes ?? [],
|
|
1076
1088
|
...src.deprecatedAttributes ?? []
|
|
1077
1089
|
/* eslint-disable-next-line sonarjs/no-alphabetical-sort -- not really needed in this case, this is a-z anyway */
|
|
1078
|
-
].
|
|
1090
|
+
].toSorted();
|
|
1079
1091
|
const entries = keys.map((key) => {
|
|
1080
1092
|
return [key, migrateSingleAttribute(src, key)];
|
|
1081
1093
|
});
|
|
@@ -1103,9 +1115,7 @@ function migrateElement(src) {
|
|
|
1103
1115
|
const implicitRole = normalizeAriaImplicitRole(src.implicitRole ?? src.aria?.implicitRole);
|
|
1104
1116
|
const result = {
|
|
1105
1117
|
...src,
|
|
1106
|
-
|
|
1107
|
-
formAssociated: void 0
|
|
1108
|
-
},
|
|
1118
|
+
formAssociated: void 0,
|
|
1109
1119
|
attributes: migrateAttributes(src),
|
|
1110
1120
|
textContent: src.textContent,
|
|
1111
1121
|
focusable: src.focusable ?? false,
|
|
@@ -1140,7 +1150,8 @@ const dynamicKeys = [
|
|
|
1140
1150
|
"phrasing",
|
|
1141
1151
|
"embedded",
|
|
1142
1152
|
"interactive",
|
|
1143
|
-
"labelable"
|
|
1153
|
+
"labelable",
|
|
1154
|
+
"submitButton"
|
|
1144
1155
|
];
|
|
1145
1156
|
const schemaCache = /* @__PURE__ */ new Map();
|
|
1146
1157
|
function clone(src) {
|
|
@@ -1410,13 +1421,10 @@ class Attribute {
|
|
|
1410
1421
|
*/
|
|
1411
1422
|
constructor(key, value, keyLocation, valueLocation, originalAttribute) {
|
|
1412
1423
|
this.key = key;
|
|
1413
|
-
this.value = value;
|
|
1424
|
+
this.value = value ?? null;
|
|
1414
1425
|
this.keyLocation = keyLocation;
|
|
1415
1426
|
this.valueLocation = valueLocation;
|
|
1416
1427
|
this.originalAttribute = originalAttribute;
|
|
1417
|
-
if (typeof this.value === "undefined") {
|
|
1418
|
-
this.value = null;
|
|
1419
|
-
}
|
|
1420
1428
|
}
|
|
1421
1429
|
/**
|
|
1422
1430
|
* Flag set to true if the attribute value is static.
|
|
@@ -1560,11 +1568,11 @@ class Context {
|
|
|
1560
1568
|
while ((offset = consumed.indexOf("\n")) >= 0) {
|
|
1561
1569
|
this.line++;
|
|
1562
1570
|
this.column = 1;
|
|
1563
|
-
consumed = consumed.
|
|
1571
|
+
consumed = consumed.slice(offset + 1);
|
|
1564
1572
|
}
|
|
1565
1573
|
this.column += consumed.length;
|
|
1566
1574
|
this.offset += n;
|
|
1567
|
-
this.string = this.string.
|
|
1575
|
+
this.string = this.string.slice(n);
|
|
1568
1576
|
this.state = state;
|
|
1569
1577
|
}
|
|
1570
1578
|
getLocation(size) {
|
|
@@ -1742,7 +1750,7 @@ class DOMNode {
|
|
|
1742
1750
|
* node has no children.
|
|
1743
1751
|
*/
|
|
1744
1752
|
get lastChild() {
|
|
1745
|
-
return this.childNodes
|
|
1753
|
+
return this.childNodes.at(-1) ?? null;
|
|
1746
1754
|
}
|
|
1747
1755
|
/**
|
|
1748
1756
|
* @internal
|
|
@@ -1857,7 +1865,7 @@ function parse(text, baseLocation) {
|
|
|
1857
1865
|
begin++;
|
|
1858
1866
|
continue;
|
|
1859
1867
|
}
|
|
1860
|
-
const token = text.
|
|
1868
|
+
const token = text.slice(begin, end);
|
|
1861
1869
|
tokens.push(token);
|
|
1862
1870
|
if (locations && baseLocation) {
|
|
1863
1871
|
const location = sliceLocation(baseLocation, begin, end);
|
|
@@ -1872,7 +1880,7 @@ class DOMTokenList extends Array {
|
|
|
1872
1880
|
locations;
|
|
1873
1881
|
constructor(value, location) {
|
|
1874
1882
|
if (value && typeof value === "string") {
|
|
1875
|
-
const normalized = value.
|
|
1883
|
+
const normalized = value.replaceAll(/[\t\r\n]/g, " ");
|
|
1876
1884
|
const { tokens, locations } = parse(normalized, location);
|
|
1877
1885
|
super(...tokens);
|
|
1878
1886
|
this.locations = locations;
|
|
@@ -1962,7 +1970,7 @@ function nthChild(node, args) {
|
|
|
1962
1970
|
if (!args) {
|
|
1963
1971
|
throw new Error("Missing argument to nth-child");
|
|
1964
1972
|
}
|
|
1965
|
-
const n = parseInt(args.trim(), 10);
|
|
1973
|
+
const n = Number.parseInt(args.trim(), 10);
|
|
1966
1974
|
const cur = getNthChild(node);
|
|
1967
1975
|
return cur === n;
|
|
1968
1976
|
}
|
|
@@ -1987,7 +1995,7 @@ function factory(name, context) {
|
|
|
1987
1995
|
}
|
|
1988
1996
|
|
|
1989
1997
|
function stripslashes(value) {
|
|
1990
|
-
return value.
|
|
1998
|
+
return value.replaceAll(/\\(.)/g, "$1");
|
|
1991
1999
|
}
|
|
1992
2000
|
class Condition {
|
|
1993
2001
|
}
|
|
@@ -2186,7 +2194,7 @@ function candidatesFromCombinator(element, combinator) {
|
|
|
2186
2194
|
}
|
|
2187
2195
|
}
|
|
2188
2196
|
function matchElement(element, compounds, context) {
|
|
2189
|
-
const last = compounds
|
|
2197
|
+
const last = compounds.at(-1);
|
|
2190
2198
|
if (!last.match(element, context)) {
|
|
2191
2199
|
return false;
|
|
2192
2200
|
}
|
|
@@ -2203,7 +2211,7 @@ function matchElement(element, compounds, context) {
|
|
|
2203
2211
|
return false;
|
|
2204
2212
|
}
|
|
2205
2213
|
|
|
2206
|
-
const escapedCodepoints = ["9", "a", "d"];
|
|
2214
|
+
const escapedCodepoints = /* @__PURE__ */ new Set(["9", "a", "d"]);
|
|
2207
2215
|
function* splitSelectorElements(selector) {
|
|
2208
2216
|
let begin = 0;
|
|
2209
2217
|
let end = 0;
|
|
@@ -2218,7 +2226,7 @@ function* splitSelectorElements(selector) {
|
|
|
2218
2226
|
return 0 /* INITIAL */;
|
|
2219
2227
|
}
|
|
2220
2228
|
function escapedState(ch) {
|
|
2221
|
-
if (escapedCodepoints.
|
|
2229
|
+
if (escapedCodepoints.has(ch)) {
|
|
2222
2230
|
return 1 /* ESCAPED */;
|
|
2223
2231
|
}
|
|
2224
2232
|
return 0 /* INITIAL */;
|
|
@@ -2258,7 +2266,7 @@ function unescapeCodepoint(value) {
|
|
|
2258
2266
|
"\\a ": "\n",
|
|
2259
2267
|
"\\d ": "\r"
|
|
2260
2268
|
};
|
|
2261
|
-
return value.
|
|
2269
|
+
return value.replaceAll(
|
|
2262
2270
|
/(\\[\u0039\u0061\u0064] )/g,
|
|
2263
2271
|
(_, codepoint) => replacement[codepoint]
|
|
2264
2272
|
);
|
|
@@ -2269,7 +2277,7 @@ function escapeSelectorComponent(text) {
|
|
|
2269
2277
|
"\n": "\\a ",
|
|
2270
2278
|
"\r": "\\d "
|
|
2271
2279
|
};
|
|
2272
|
-
return text.toString().
|
|
2280
|
+
return text.toString().replaceAll(/([\t\n\r]|[^a-z0-9_-])/gi, (_, ch) => {
|
|
2273
2281
|
if (codepoints[ch]) {
|
|
2274
2282
|
return codepoints[ch];
|
|
2275
2283
|
} else {
|
|
@@ -2318,7 +2326,7 @@ class Selector {
|
|
|
2318
2326
|
}
|
|
2319
2327
|
}
|
|
2320
2328
|
static parse(selector) {
|
|
2321
|
-
selector = selector.
|
|
2329
|
+
selector = selector.replaceAll(/([+~>]) /g, "$1");
|
|
2322
2330
|
return Array.from(splitSelectorElements(selector), (element) => {
|
|
2323
2331
|
return new Compound(unescapeCodepoint(element));
|
|
2324
2332
|
});
|
|
@@ -2614,7 +2622,7 @@ class HtmlElement extends DOMNode {
|
|
|
2614
2622
|
}
|
|
2615
2623
|
parts.push(`${cur.tagName.toLowerCase()}:nth-child(${String(index + 1)})`);
|
|
2616
2624
|
}
|
|
2617
|
-
return parts.
|
|
2625
|
+
return parts.toReversed().join(" > ");
|
|
2618
2626
|
}
|
|
2619
2627
|
/**
|
|
2620
2628
|
* Tests if this element has given tagname.
|
|
@@ -2656,7 +2664,7 @@ class HtmlElement extends DOMNode {
|
|
|
2656
2664
|
this.metaElement ??= {};
|
|
2657
2665
|
for (const key of MetaCopyableProperty) {
|
|
2658
2666
|
const value = meta[key];
|
|
2659
|
-
if (
|
|
2667
|
+
if (value !== void 0) {
|
|
2660
2668
|
setMetaProperty(this.metaElement, key, value);
|
|
2661
2669
|
} else {
|
|
2662
2670
|
delete this.metaElement[key];
|
|
@@ -2760,8 +2768,8 @@ class HtmlElement extends DOMNode {
|
|
|
2760
2768
|
if (tabindex.value instanceof DynamicValue) {
|
|
2761
2769
|
return this.cacheSet(TABINDEX, 0);
|
|
2762
2770
|
}
|
|
2763
|
-
const parsed = parseInt(tabindex.value, 10);
|
|
2764
|
-
if (isNaN(parsed)) {
|
|
2771
|
+
const parsed = Number.parseInt(tabindex.value, 10);
|
|
2772
|
+
if (Number.isNaN(parsed)) {
|
|
2765
2773
|
return this.cacheSet(TABINDEX, null);
|
|
2766
2774
|
}
|
|
2767
2775
|
return this.cacheSet(TABINDEX, parsed);
|
|
@@ -2865,7 +2873,10 @@ class HtmlElement extends DOMNode {
|
|
|
2865
2873
|
*/
|
|
2866
2874
|
get lastElementChild() {
|
|
2867
2875
|
const children = this.childElements;
|
|
2868
|
-
return children.length > 0 ?
|
|
2876
|
+
return children.length > 0 ? (
|
|
2877
|
+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- it is checked right before this */
|
|
2878
|
+
children.at(-1)
|
|
2879
|
+
) : null;
|
|
2869
2880
|
}
|
|
2870
2881
|
get siblings() {
|
|
2871
2882
|
return this.parent ? this.parent.childElements : [this];
|
|
@@ -2988,7 +2999,9 @@ function depthFirst(root, callback) {
|
|
|
2988
2999
|
root = root.root;
|
|
2989
3000
|
}
|
|
2990
3001
|
function visit(node) {
|
|
2991
|
-
node.childElements
|
|
3002
|
+
for (const child of node.childElements) {
|
|
3003
|
+
visit(child);
|
|
3004
|
+
}
|
|
2992
3005
|
if (!node.isRootElement()) {
|
|
2993
3006
|
callback(node);
|
|
2994
3007
|
}
|
|
@@ -3077,7 +3090,7 @@ class DOMTree {
|
|
|
3077
3090
|
}
|
|
3078
3091
|
}
|
|
3079
3092
|
|
|
3080
|
-
const allowedKeys = ["exclude"];
|
|
3093
|
+
const allowedKeys = /* @__PURE__ */ new Set(["exclude"]);
|
|
3081
3094
|
class Validator {
|
|
3082
3095
|
/**
|
|
3083
3096
|
* Test if element is used in a proper context.
|
|
@@ -3316,7 +3329,7 @@ class Validator {
|
|
|
3316
3329
|
}
|
|
3317
3330
|
function validateKeys(rule) {
|
|
3318
3331
|
for (const key of Object.keys(rule)) {
|
|
3319
|
-
if (!allowedKeys.
|
|
3332
|
+
if (!allowedKeys.has(key)) {
|
|
3320
3333
|
const str = JSON.stringify(rule);
|
|
3321
3334
|
throw new Error(`Permitted rule "${str}" contains unknown property "${key}"`);
|
|
3322
3335
|
}
|
|
@@ -3358,7 +3371,7 @@ function parseSeverity(value) {
|
|
|
3358
3371
|
|
|
3359
3372
|
const cacheKey = /* @__PURE__ */ Symbol("aria-naming");
|
|
3360
3373
|
const defaultValue = "allowed";
|
|
3361
|
-
const prohibitedRoles = [
|
|
3374
|
+
const prohibitedRoles = /* @__PURE__ */ new Set([
|
|
3362
3375
|
"caption",
|
|
3363
3376
|
"code",
|
|
3364
3377
|
"deletion",
|
|
@@ -3370,9 +3383,9 @@ const prohibitedRoles = [
|
|
|
3370
3383
|
"strong",
|
|
3371
3384
|
"subscript",
|
|
3372
3385
|
"superscript"
|
|
3373
|
-
];
|
|
3386
|
+
]);
|
|
3374
3387
|
function byRole(role) {
|
|
3375
|
-
return prohibitedRoles.
|
|
3388
|
+
return prohibitedRoles.has(role) ? "prohibited" : "allowed";
|
|
3376
3389
|
}
|
|
3377
3390
|
function byMeta(element, meta) {
|
|
3378
3391
|
return meta.aria.naming(element._adapter);
|
|
@@ -3424,7 +3437,7 @@ function isInputDisabledImpl(node) {
|
|
|
3424
3437
|
|
|
3425
3438
|
const patternCache = /* @__PURE__ */ new Map();
|
|
3426
3439
|
function compileStringPattern(pattern) {
|
|
3427
|
-
const regexp = pattern.
|
|
3440
|
+
const regexp = pattern.replaceAll(/[*]+/g, ".+");
|
|
3428
3441
|
return new RegExp(`^${regexp}$`);
|
|
3429
3442
|
}
|
|
3430
3443
|
function compileRegExpPattern(pattern) {
|
|
@@ -3699,8 +3712,8 @@ function format(value, quote = false) {
|
|
|
3699
3712
|
return String(value);
|
|
3700
3713
|
}
|
|
3701
3714
|
function interpolate(text, data) {
|
|
3702
|
-
return text.
|
|
3703
|
-
return
|
|
3715
|
+
return text.replaceAll(/{{\s*([^\s{}]+)\s*}}/g, (match, key) => {
|
|
3716
|
+
return data[key] !== void 0 ? format(data[key]) : match;
|
|
3704
3717
|
});
|
|
3705
3718
|
}
|
|
3706
3719
|
|
|
@@ -3908,7 +3921,14 @@ class Rule {
|
|
|
3908
3921
|
});
|
|
3909
3922
|
if (enabled && !blocked) {
|
|
3910
3923
|
const interpolated = interpolate(message, context ?? {});
|
|
3911
|
-
this.reporter.add(
|
|
3924
|
+
this.reporter.add({
|
|
3925
|
+
rule: this,
|
|
3926
|
+
message: interpolated,
|
|
3927
|
+
severity: this.severity,
|
|
3928
|
+
node,
|
|
3929
|
+
location: where,
|
|
3930
|
+
context
|
|
3931
|
+
});
|
|
3912
3932
|
}
|
|
3913
3933
|
}
|
|
3914
3934
|
findLocation(src) {
|
|
@@ -4480,8 +4500,7 @@ class AriaLabelMisuse extends Rule {
|
|
|
4480
4500
|
class ConfigError extends UserError {
|
|
4481
4501
|
constructor(message, nested) {
|
|
4482
4502
|
super(message, nested);
|
|
4483
|
-
|
|
4484
|
-
this.name = ConfigError.name;
|
|
4503
|
+
this.name = "ConfigError";
|
|
4485
4504
|
}
|
|
4486
4505
|
}
|
|
4487
4506
|
|
|
@@ -4585,7 +4604,7 @@ class AttrCase extends Rule {
|
|
|
4585
4604
|
if (event.originalAttribute) {
|
|
4586
4605
|
return;
|
|
4587
4606
|
}
|
|
4588
|
-
const letters = event.key.
|
|
4607
|
+
const letters = event.key.replaceAll(/[^a-z]+/gi, "");
|
|
4589
4608
|
if (this.style.match(letters)) {
|
|
4590
4609
|
return;
|
|
4591
4610
|
}
|
|
@@ -4658,6 +4677,7 @@ class InvalidTokenError extends Error {
|
|
|
4658
4677
|
location;
|
|
4659
4678
|
constructor(location, message) {
|
|
4660
4679
|
super(message);
|
|
4680
|
+
this.name = "InvalidTokenError";
|
|
4661
4681
|
this.location = location;
|
|
4662
4682
|
}
|
|
4663
4683
|
}
|
|
@@ -4767,16 +4787,26 @@ class Lexer {
|
|
|
4767
4787
|
*/
|
|
4768
4788
|
enter(context, state, data) {
|
|
4769
4789
|
if (state === State.TAG && data?.[0].startsWith("<")) {
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4790
|
+
switch (data[0]) {
|
|
4791
|
+
case "<script": {
|
|
4792
|
+
context.contentModel = ContentModel.SCRIPT;
|
|
4793
|
+
break;
|
|
4794
|
+
}
|
|
4795
|
+
case "<style": {
|
|
4796
|
+
context.contentModel = ContentModel.STYLE;
|
|
4797
|
+
break;
|
|
4798
|
+
}
|
|
4799
|
+
case "<textarea": {
|
|
4800
|
+
context.contentModel = ContentModel.TEXTAREA;
|
|
4801
|
+
break;
|
|
4802
|
+
}
|
|
4803
|
+
case "<title": {
|
|
4804
|
+
context.contentModel = ContentModel.TITLE;
|
|
4805
|
+
break;
|
|
4806
|
+
}
|
|
4807
|
+
default: {
|
|
4808
|
+
context.contentModel = ContentModel.TEXT;
|
|
4809
|
+
}
|
|
4780
4810
|
}
|
|
4781
4811
|
}
|
|
4782
4812
|
}
|
|
@@ -5177,10 +5207,10 @@ class AttrSpacing extends Rule {
|
|
|
5177
5207
|
|
|
5178
5208
|
function pick(attr) {
|
|
5179
5209
|
const result = {};
|
|
5180
|
-
if (
|
|
5210
|
+
if (attr.enum !== void 0) {
|
|
5181
5211
|
result.enum = attr.enum;
|
|
5182
5212
|
}
|
|
5183
|
-
if (
|
|
5213
|
+
if (attr.boolean !== void 0) {
|
|
5184
5214
|
result.boolean = attr.boolean;
|
|
5185
5215
|
}
|
|
5186
5216
|
return result;
|
|
@@ -5907,7 +5937,7 @@ class Deprecated extends Rule {
|
|
|
5907
5937
|
text.push(context.documentation);
|
|
5908
5938
|
}
|
|
5909
5939
|
const doc = {
|
|
5910
|
-
description: text.map((cur) => cur.
|
|
5940
|
+
description: text.map((cur) => cur.replaceAll("$tagname", context.tagName)).join("\n\n"),
|
|
5911
5941
|
url: "https://html-validate.org/rules/deprecated.html"
|
|
5912
5942
|
};
|
|
5913
5943
|
return doc;
|
|
@@ -6226,7 +6256,7 @@ class ElementCase extends Rule {
|
|
|
6226
6256
|
});
|
|
6227
6257
|
}
|
|
6228
6258
|
validateCase(target, targetLocation) {
|
|
6229
|
-
const letters = target.tagName.
|
|
6259
|
+
const letters = target.tagName.replaceAll(/[^a-z]+/gi, "");
|
|
6230
6260
|
if (!this.style.match(letters)) {
|
|
6231
6261
|
const location = sliceLocation(targetLocation, 1);
|
|
6232
6262
|
this.report(target, `Element "${target.tagName}" should be ${this.style.name}`, location);
|
|
@@ -6830,8 +6860,8 @@ function haveName(name) {
|
|
|
6830
6860
|
return typeof name === "string" && name !== "";
|
|
6831
6861
|
}
|
|
6832
6862
|
function allowSharedName(node, shared) {
|
|
6833
|
-
const type = node
|
|
6834
|
-
return
|
|
6863
|
+
const type = getControlType(node);
|
|
6864
|
+
return shared.includes(type);
|
|
6835
6865
|
}
|
|
6836
6866
|
function isInputHidden(element) {
|
|
6837
6867
|
return element.is("input") && element.getAttributeValue("type") === "hidden";
|
|
@@ -6839,6 +6869,13 @@ function isInputHidden(element) {
|
|
|
6839
6869
|
function isInputCheckbox(element) {
|
|
6840
6870
|
return element.is("input") && element.getAttributeValue("type") === "checkbox";
|
|
6841
6871
|
}
|
|
6872
|
+
function getControlType(element) {
|
|
6873
|
+
const type = element.getAttributeValue("type") ?? "";
|
|
6874
|
+
if (element.is("button") && type === "") {
|
|
6875
|
+
return "submit";
|
|
6876
|
+
}
|
|
6877
|
+
return type;
|
|
6878
|
+
}
|
|
6842
6879
|
function isCheckboxWithDefault(control, previous, options) {
|
|
6843
6880
|
const { allowCheckboxDefault } = options;
|
|
6844
6881
|
if (!allowCheckboxDefault) {
|
|
@@ -6976,7 +7013,7 @@ class FormDupName extends Rule {
|
|
|
6976
7013
|
validateSharedName(control, group, attr, name) {
|
|
6977
7014
|
const uniqueElements = this.getUniqueElements(group);
|
|
6978
7015
|
const sharedElements = this.getSharedElements(group);
|
|
6979
|
-
const type = control
|
|
7016
|
+
const type = getControlType(control);
|
|
6980
7017
|
if (uniqueElements.has(name) || sharedElements.has(name) && sharedElements.get(name) !== type) {
|
|
6981
7018
|
const context = {
|
|
6982
7019
|
name,
|
|
@@ -7038,7 +7075,7 @@ function isRelevant$5(event) {
|
|
|
7038
7075
|
function extractLevel(node) {
|
|
7039
7076
|
const match = /^[hH](\d)$/.exec(node.tagName);
|
|
7040
7077
|
if (match) {
|
|
7041
|
-
return parseInt(match[1], 10);
|
|
7078
|
+
return Number.parseInt(match[1], 10);
|
|
7042
7079
|
} else {
|
|
7043
7080
|
return null;
|
|
7044
7081
|
}
|
|
@@ -7051,7 +7088,7 @@ function parseMaxInitial(value) {
|
|
|
7051
7088
|
if (!match) {
|
|
7052
7089
|
return 1;
|
|
7053
7090
|
}
|
|
7054
|
-
return parseInt(match[1], 10);
|
|
7091
|
+
return Number.parseInt(match[1], 10);
|
|
7055
7092
|
}
|
|
7056
7093
|
class HeadingLevel extends Rule {
|
|
7057
7094
|
minInitialRank;
|
|
@@ -7200,10 +7237,10 @@ class HeadingLevel extends Rule {
|
|
|
7200
7237
|
this.stack.pop();
|
|
7201
7238
|
}
|
|
7202
7239
|
getPrevRoot() {
|
|
7203
|
-
return this.stack
|
|
7240
|
+
return this.stack.at(-2);
|
|
7204
7241
|
}
|
|
7205
7242
|
getCurrentRoot() {
|
|
7206
|
-
return this.stack
|
|
7243
|
+
return this.stack.at(-1);
|
|
7207
7244
|
}
|
|
7208
7245
|
isSectioningRoot(node) {
|
|
7209
7246
|
const context = {
|
|
@@ -7800,7 +7837,7 @@ function parseContent(text) {
|
|
|
7800
7837
|
const match = /^(\d+)(?:\s*;\s*url=(.*))?/i.exec(text);
|
|
7801
7838
|
if (match) {
|
|
7802
7839
|
return {
|
|
7803
|
-
delay: parseInt(match[1], 10),
|
|
7840
|
+
delay: Number.parseInt(match[1], 10),
|
|
7804
7841
|
url: match[2]
|
|
7805
7842
|
};
|
|
7806
7843
|
} else {
|
|
@@ -8124,13 +8161,12 @@ class NoDupClass extends Rule {
|
|
|
8124
8161
|
}
|
|
8125
8162
|
const classes = new DOMTokenList(event.value, event.valueLocation);
|
|
8126
8163
|
const unique = /* @__PURE__ */ new Set();
|
|
8127
|
-
classes.
|
|
8128
|
-
if (unique.has(
|
|
8129
|
-
|
|
8130
|
-
this.report(event.target, `Class "${cur}" duplicated`, location);
|
|
8164
|
+
for (const { item, location } of classes.iterator()) {
|
|
8165
|
+
if (unique.has(item)) {
|
|
8166
|
+
this.report(event.target, `Class "${item}" duplicated`, location);
|
|
8131
8167
|
}
|
|
8132
|
-
unique.add(
|
|
8133
|
-
}
|
|
8168
|
+
unique.add(item);
|
|
8169
|
+
}
|
|
8134
8170
|
});
|
|
8135
8171
|
}
|
|
8136
8172
|
}
|
|
@@ -8862,7 +8898,7 @@ class NoUnusedDisable extends Rule {
|
|
|
8862
8898
|
setup() {
|
|
8863
8899
|
}
|
|
8864
8900
|
reportUnused(unused, options, location) {
|
|
8865
|
-
const tokens = new DOMTokenList(options.
|
|
8901
|
+
const tokens = new DOMTokenList(options.replaceAll(",", " "), location);
|
|
8866
8902
|
for (const ruleId of unused) {
|
|
8867
8903
|
const index = tokens.indexOf(ruleId);
|
|
8868
8904
|
const tokenLocation = index >= 0 ? tokens.location(index) : location;
|
|
@@ -9183,19 +9219,19 @@ const supportSri = {
|
|
|
9183
9219
|
link: "href",
|
|
9184
9220
|
script: "src"
|
|
9185
9221
|
};
|
|
9186
|
-
const supportedRel = ["stylesheet", "preload", "modulepreload"];
|
|
9187
|
-
const supportedPreload = ["style", "script"];
|
|
9222
|
+
const supportedRel = /* @__PURE__ */ new Set(["stylesheet", "preload", "modulepreload"]);
|
|
9223
|
+
const supportedPreload = /* @__PURE__ */ new Set(["style", "script"]);
|
|
9188
9224
|
function linkSupportsSri(node) {
|
|
9189
9225
|
const rel = node.getAttribute("rel");
|
|
9190
9226
|
if (typeof rel?.value !== "string") {
|
|
9191
9227
|
return false;
|
|
9192
9228
|
}
|
|
9193
|
-
if (!supportedRel.
|
|
9229
|
+
if (!supportedRel.has(rel.value)) {
|
|
9194
9230
|
return false;
|
|
9195
9231
|
}
|
|
9196
9232
|
if (rel.value === "preload") {
|
|
9197
9233
|
const as = node.getAttribute("as");
|
|
9198
|
-
return typeof as?.value === "string" && supportedPreload.
|
|
9234
|
+
return typeof as?.value === "string" && supportedPreload.has(as.value);
|
|
9199
9235
|
}
|
|
9200
9236
|
return true;
|
|
9201
9237
|
}
|
|
@@ -9312,13 +9348,13 @@ class ScriptElement extends Rule {
|
|
|
9312
9348
|
}
|
|
9313
9349
|
}
|
|
9314
9350
|
|
|
9315
|
-
const javascript = [
|
|
9351
|
+
const javascript = /* @__PURE__ */ new Set([
|
|
9316
9352
|
"",
|
|
9317
9353
|
"application/ecmascript",
|
|
9318
9354
|
"application/javascript",
|
|
9319
9355
|
"text/ecmascript",
|
|
9320
9356
|
"text/javascript"
|
|
9321
|
-
];
|
|
9357
|
+
]);
|
|
9322
9358
|
class ScriptType extends Rule {
|
|
9323
9359
|
documentation() {
|
|
9324
9360
|
return {
|
|
@@ -9349,7 +9385,7 @@ class ScriptType extends Rule {
|
|
|
9349
9385
|
}
|
|
9350
9386
|
isJavascript(mime) {
|
|
9351
9387
|
const type = mime.replace(/;.*/, "");
|
|
9352
|
-
return javascript.
|
|
9388
|
+
return javascript.has(type);
|
|
9353
9389
|
}
|
|
9354
9390
|
}
|
|
9355
9391
|
|
|
@@ -9925,7 +9961,7 @@ class UnknownCharReference extends Rule {
|
|
|
9925
9961
|
}
|
|
9926
9962
|
|
|
9927
9963
|
const expectedOrder = ["section", "hint", "contact", "field1", "field2", "webauthn"];
|
|
9928
|
-
const fieldNames1 = [
|
|
9964
|
+
const fieldNames1 = /* @__PURE__ */ new Set([
|
|
9929
9965
|
"name",
|
|
9930
9966
|
"honorific-prefix",
|
|
9931
9967
|
"given-name",
|
|
@@ -9970,8 +10006,8 @@ const fieldNames1 = [
|
|
|
9970
10006
|
"sex",
|
|
9971
10007
|
"url",
|
|
9972
10008
|
"photo"
|
|
9973
|
-
];
|
|
9974
|
-
const fieldNames2 = [
|
|
10009
|
+
]);
|
|
10010
|
+
const fieldNames2 = /* @__PURE__ */ new Set([
|
|
9975
10011
|
"tel",
|
|
9976
10012
|
"tel-country-code",
|
|
9977
10013
|
"tel-national",
|
|
@@ -9982,7 +10018,7 @@ const fieldNames2 = [
|
|
|
9982
10018
|
"tel-extension",
|
|
9983
10019
|
"email",
|
|
9984
10020
|
"impp"
|
|
9985
|
-
];
|
|
10021
|
+
]);
|
|
9986
10022
|
const fieldNameGroup = {
|
|
9987
10023
|
name: "text",
|
|
9988
10024
|
"honorific-prefix": "text",
|
|
@@ -10047,14 +10083,14 @@ function matchHint(token) {
|
|
|
10047
10083
|
return token === "shipping" || token === "billing";
|
|
10048
10084
|
}
|
|
10049
10085
|
function matchFieldNames1(token) {
|
|
10050
|
-
return fieldNames1.
|
|
10086
|
+
return fieldNames1.has(token);
|
|
10051
10087
|
}
|
|
10052
10088
|
function matchContact(token) {
|
|
10053
10089
|
const haystack = ["home", "work", "mobile", "fax", "pager"];
|
|
10054
10090
|
return haystack.includes(token);
|
|
10055
10091
|
}
|
|
10056
10092
|
function matchFieldNames2(token) {
|
|
10057
|
-
return fieldNames2.
|
|
10093
|
+
return fieldNames2.has(token);
|
|
10058
10094
|
}
|
|
10059
10095
|
function matchWebauthn(token) {
|
|
10060
10096
|
return token === "webauthn";
|
|
@@ -10725,11 +10761,13 @@ class H32 extends Rule {
|
|
|
10725
10761
|
setup() {
|
|
10726
10762
|
const formTags = this.getTagsWithProperty("form");
|
|
10727
10763
|
const formSelector = formTags.join(",");
|
|
10764
|
+
const submitButtonTags = this.getTagsWithProperty("submitButton");
|
|
10765
|
+
const submitButtonSelector = submitButtonTags.join(",");
|
|
10728
10766
|
this.on("dom:ready", (event) => {
|
|
10729
10767
|
const { document } = event;
|
|
10730
10768
|
const forms = document.querySelectorAll(formSelector);
|
|
10731
10769
|
for (const form of forms) {
|
|
10732
|
-
if (hasNestedSubmit(form)) {
|
|
10770
|
+
if (hasNestedSubmit(form, submitButtonSelector)) {
|
|
10733
10771
|
continue;
|
|
10734
10772
|
}
|
|
10735
10773
|
if (hasAssociatedSubmit(document, form)) {
|
|
@@ -10741,15 +10779,15 @@ class H32 extends Rule {
|
|
|
10741
10779
|
}
|
|
10742
10780
|
}
|
|
10743
10781
|
function isSubmit(node) {
|
|
10744
|
-
const
|
|
10745
|
-
return
|
|
10782
|
+
const meta = node.meta;
|
|
10783
|
+
return Boolean(meta?.submitButton);
|
|
10746
10784
|
}
|
|
10747
10785
|
function isAssociated(id, node) {
|
|
10748
10786
|
const form = node.getAttribute("form");
|
|
10749
10787
|
return Boolean(form?.valueMatches(id, true));
|
|
10750
10788
|
}
|
|
10751
|
-
function hasNestedSubmit(form) {
|
|
10752
|
-
const matches = form.querySelectorAll(
|
|
10789
|
+
function hasNestedSubmit(form, submitButtonSelector) {
|
|
10790
|
+
const matches = form.querySelectorAll(submitButtonSelector).filter(isSubmit).filter((node) => !node.hasAttribute("form"));
|
|
10753
10791
|
return matches.length > 0;
|
|
10754
10792
|
}
|
|
10755
10793
|
function hasAssociatedSubmit(document, form) {
|
|
@@ -11298,11 +11336,11 @@ function dumpTree(root) {
|
|
|
11298
11336
|
} else {
|
|
11299
11337
|
lines.push("(root)");
|
|
11300
11338
|
}
|
|
11301
|
-
node.childElements.
|
|
11339
|
+
for (const [index, child] of node.childElements.entries()) {
|
|
11302
11340
|
const s = lastSibling ? " " : "\u2502";
|
|
11303
11341
|
const i = level > 0 ? `${indent}${s} ` : "";
|
|
11304
11342
|
writeNode(child, level + 1, i, index);
|
|
11305
|
-
}
|
|
11343
|
+
}
|
|
11306
11344
|
}
|
|
11307
11345
|
writeNode(root, 0, "", 0);
|
|
11308
11346
|
return lines;
|
|
@@ -12417,7 +12455,7 @@ class EventHandler {
|
|
|
12417
12455
|
}
|
|
12418
12456
|
|
|
12419
12457
|
const name = "html-validate";
|
|
12420
|
-
const version = "10.
|
|
12458
|
+
const version = "10.10.0";
|
|
12421
12459
|
const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
|
|
12422
12460
|
|
|
12423
12461
|
function freeze(src) {
|
|
@@ -12433,7 +12471,13 @@ function isThenableArray(value) {
|
|
|
12433
12471
|
return isThenable(value[0]);
|
|
12434
12472
|
}
|
|
12435
12473
|
class Reporter {
|
|
12474
|
+
/**
|
|
12475
|
+
* @internal
|
|
12476
|
+
*/
|
|
12436
12477
|
result;
|
|
12478
|
+
/**
|
|
12479
|
+
* @internal
|
|
12480
|
+
*/
|
|
12437
12481
|
constructor() {
|
|
12438
12482
|
this.result = {};
|
|
12439
12483
|
}
|
|
@@ -12446,16 +12490,16 @@ class Reporter {
|
|
|
12446
12490
|
}
|
|
12447
12491
|
const valid = reports.every((report) => report.valid);
|
|
12448
12492
|
const merged = {};
|
|
12449
|
-
|
|
12450
|
-
report.results
|
|
12493
|
+
for (const report of reports) {
|
|
12494
|
+
for (const result of report.results) {
|
|
12451
12495
|
const key = result.filePath;
|
|
12452
12496
|
if (key in merged) {
|
|
12453
12497
|
merged[key].messages = [...merged[key].messages, ...result.messages];
|
|
12454
12498
|
} else {
|
|
12455
12499
|
merged[key] = { ...result };
|
|
12456
12500
|
}
|
|
12457
|
-
}
|
|
12458
|
-
}
|
|
12501
|
+
}
|
|
12502
|
+
}
|
|
12459
12503
|
const results = Object.values(merged).map((result) => {
|
|
12460
12504
|
result.errorCount = countErrors(result.messages);
|
|
12461
12505
|
result.warningCount = countWarnings(result.messages);
|
|
@@ -12468,8 +12512,11 @@ class Reporter {
|
|
|
12468
12512
|
warningCount: sumWarnings(results)
|
|
12469
12513
|
};
|
|
12470
12514
|
}
|
|
12471
|
-
|
|
12472
|
-
|
|
12515
|
+
/**
|
|
12516
|
+
* @internal
|
|
12517
|
+
*/
|
|
12518
|
+
add(options) {
|
|
12519
|
+
const { rule, message, severity, node, location, context } = options;
|
|
12473
12520
|
if (!(location.filename in this.result)) {
|
|
12474
12521
|
this.result[location.filename] = [];
|
|
12475
12522
|
}
|
|
@@ -12494,17 +12541,23 @@ class Reporter {
|
|
|
12494
12541
|
}
|
|
12495
12542
|
this.result[location.filename].push(entry);
|
|
12496
12543
|
}
|
|
12544
|
+
/**
|
|
12545
|
+
* @internal
|
|
12546
|
+
*/
|
|
12497
12547
|
addManual(filename, message) {
|
|
12498
12548
|
if (!(filename in this.result)) {
|
|
12499
12549
|
this.result[filename] = [];
|
|
12500
12550
|
}
|
|
12501
12551
|
this.result[filename].push(message);
|
|
12502
12552
|
}
|
|
12553
|
+
/**
|
|
12554
|
+
* @internal
|
|
12555
|
+
*/
|
|
12503
12556
|
save(sources) {
|
|
12504
12557
|
const report = {
|
|
12505
12558
|
valid: this.isValid(),
|
|
12506
12559
|
results: Object.keys(this.result).map((filePath) => {
|
|
12507
|
-
const messages = Array.from(this.result[filePath], freeze).
|
|
12560
|
+
const messages = Array.from(this.result[filePath], freeze).toSorted(messageSort);
|
|
12508
12561
|
const source = (sources ?? []).find((source2) => filePath === source2.filename);
|
|
12509
12562
|
return {
|
|
12510
12563
|
filePath,
|
|
@@ -12521,6 +12574,9 @@ class Reporter {
|
|
|
12521
12574
|
report.warningCount = sumWarnings(report.results);
|
|
12522
12575
|
return report;
|
|
12523
12576
|
}
|
|
12577
|
+
/**
|
|
12578
|
+
* @internal
|
|
12579
|
+
*/
|
|
12524
12580
|
isValid() {
|
|
12525
12581
|
const numErrors = Object.values(this.result).reduce((sum, messages) => {
|
|
12526
12582
|
return sum + countErrors(messages);
|
|
@@ -12583,6 +12639,7 @@ class ParserError extends Error {
|
|
|
12583
12639
|
location;
|
|
12584
12640
|
constructor(location, message) {
|
|
12585
12641
|
super(message);
|
|
12642
|
+
this.name = "ParserError";
|
|
12586
12643
|
this.location = location;
|
|
12587
12644
|
}
|
|
12588
12645
|
}
|
|
@@ -12739,7 +12796,7 @@ class Parser {
|
|
|
12739
12796
|
const tokens = Array.from(
|
|
12740
12797
|
this.consumeUntil(tokenStream, TokenType.TAG_CLOSE, startToken.location)
|
|
12741
12798
|
);
|
|
12742
|
-
const endToken = tokens.
|
|
12799
|
+
const endToken = tokens.at(-1);
|
|
12743
12800
|
const closeOptional = this.closeOptional(startToken);
|
|
12744
12801
|
const parent = closeOptional ? this.dom.getActive().parent : this.dom.getActive();
|
|
12745
12802
|
const node = HtmlElement.fromTokens(
|
|
@@ -12857,7 +12914,7 @@ class Parser {
|
|
|
12857
12914
|
const endTokens = Array.from(
|
|
12858
12915
|
this.consumeUntil(tokenStream, TokenType.TAG_CLOSE, last.location)
|
|
12859
12916
|
);
|
|
12860
|
-
endToken = endTokens.
|
|
12917
|
+
endToken = endTokens.at(-1);
|
|
12861
12918
|
const selfClosed = endToken.data[0] === "/>";
|
|
12862
12919
|
if (tagClosed) {
|
|
12863
12920
|
startToken = last;
|
|
@@ -13139,7 +13196,7 @@ class Parser {
|
|
|
13139
13196
|
this.event.once("*", cb);
|
|
13140
13197
|
}
|
|
13141
13198
|
trigger(event, data) {
|
|
13142
|
-
if (
|
|
13199
|
+
if (data.location === void 0) {
|
|
13143
13200
|
throw new Error("Triggered event must contain location");
|
|
13144
13201
|
}
|
|
13145
13202
|
this.event.trigger(event, data);
|
|
@@ -13267,7 +13324,9 @@ class Engine {
|
|
|
13267
13324
|
}
|
|
13268
13325
|
lines.push({ event, data });
|
|
13269
13326
|
});
|
|
13270
|
-
|
|
13327
|
+
for (const src of source) {
|
|
13328
|
+
parser.parseHtml(src);
|
|
13329
|
+
}
|
|
13271
13330
|
return lines;
|
|
13272
13331
|
}
|
|
13273
13332
|
dumpTokens(source) {
|
|
@@ -13732,7 +13791,7 @@ const entities = {
|
|
|
13732
13791
|
"&": "&"
|
|
13733
13792
|
};
|
|
13734
13793
|
function xmlescape(src) {
|
|
13735
|
-
return src.toString().
|
|
13794
|
+
return src.toString().replaceAll(/[><'"&]/g, (match) => {
|
|
13736
13795
|
return entities[match];
|
|
13737
13796
|
});
|
|
13738
13797
|
}
|
|
@@ -13752,11 +13811,11 @@ function checkstyleFormatter(results) {
|
|
|
13752
13811
|
`;
|
|
13753
13812
|
output += `<checkstyle version="4.3">
|
|
13754
13813
|
`;
|
|
13755
|
-
|
|
13814
|
+
for (const result of results) {
|
|
13756
13815
|
const messages = result.messages;
|
|
13757
13816
|
output += ` <file name="${xmlescape(result.filePath)}">
|
|
13758
13817
|
`;
|
|
13759
|
-
|
|
13818
|
+
for (const message of messages) {
|
|
13760
13819
|
const ruleId = xmlescape(`htmlvalidate.rules.${message.ruleId}`);
|
|
13761
13820
|
output += " ";
|
|
13762
13821
|
output += [
|
|
@@ -13767,9 +13826,9 @@ function checkstyleFormatter(results) {
|
|
|
13767
13826
|
`source="${ruleId}" />`
|
|
13768
13827
|
].join(" ");
|
|
13769
13828
|
output += "\n";
|
|
13770
|
-
}
|
|
13829
|
+
}
|
|
13771
13830
|
output += " </file>\n";
|
|
13772
|
-
}
|
|
13831
|
+
}
|
|
13773
13832
|
output += "</checkstyle>\n";
|
|
13774
13833
|
return output;
|
|
13775
13834
|
}
|
|
@@ -13839,11 +13898,11 @@ function codeFrameColumns(rawLines, loc) {
|
|
|
13839
13898
|
if (hasMarker) {
|
|
13840
13899
|
let markerLine = "";
|
|
13841
13900
|
if (Array.isArray(hasMarker)) {
|
|
13842
|
-
const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).
|
|
13901
|
+
const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replaceAll(/[^\t]/g, " ");
|
|
13843
13902
|
const numberOfMarkers = hasMarker[1] || 1;
|
|
13844
13903
|
markerLine = [
|
|
13845
13904
|
"\n ",
|
|
13846
|
-
gutter.
|
|
13905
|
+
gutter.replaceAll(/\d/g, " "),
|
|
13847
13906
|
" ",
|
|
13848
13907
|
markerSpacing,
|
|
13849
13908
|
"^".repeat(numberOfMarkers)
|
|
@@ -13981,10 +14040,10 @@ function stylish(results) {
|
|
|
13981
14040
|
function textFormatter(results) {
|
|
13982
14041
|
let output = "";
|
|
13983
14042
|
let total = 0;
|
|
13984
|
-
|
|
14043
|
+
for (const result of results) {
|
|
13985
14044
|
const messages = result.messages;
|
|
13986
14045
|
if (messages.length === 0) {
|
|
13987
|
-
|
|
14046
|
+
continue;
|
|
13988
14047
|
}
|
|
13989
14048
|
total += messages.length;
|
|
13990
14049
|
output += messages.map((message) => {
|
|
@@ -14000,7 +14059,7 @@ function textFormatter(results) {
|
|
|
14000
14059
|
return `${location}: ${messageType} [${message.ruleId}] ${message.message}
|
|
14001
14060
|
`;
|
|
14002
14061
|
}).join("");
|
|
14003
|
-
}
|
|
14062
|
+
}
|
|
14004
14063
|
return total > 0 ? output : "";
|
|
14005
14064
|
}
|
|
14006
14065
|
const formatter = textFormatter;
|
|
@@ -14832,7 +14891,7 @@ var ignoreExports = /*@__PURE__*/ requireIgnore();
|
|
|
14832
14891
|
var ignore = /*@__PURE__*/getDefaultExportFromCjs(ignoreExports);
|
|
14833
14892
|
|
|
14834
14893
|
const engines = {
|
|
14835
|
-
node: "^20.19.0 || >= 22.
|
|
14894
|
+
node: "^20.19.0 || >= 22.16.0"
|
|
14836
14895
|
};
|
|
14837
14896
|
|
|
14838
14897
|
var workerPath = "./jest-worker.js";
|