html-validate 8.1.0 → 8.3.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 +36 -10
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/core-nodejs.js +3 -2
- package/dist/cjs/core-nodejs.js.map +1 -1
- package/dist/cjs/core.js +198 -114
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/elements.js +29 -5
- package/dist/cjs/elements.js.map +1 -1
- package/dist/cjs/html-validate.js +2 -2
- package/dist/cjs/html-validate.js.map +1 -1
- package/dist/cjs/jest-lib.js +3 -3
- package/dist/cjs/jest-lib.js.map +1 -1
- package/dist/cjs/meta-helper.js +16 -2
- package/dist/cjs/meta-helper.js.map +1 -1
- package/dist/cjs/test-utils.js +1 -1
- package/dist/cjs/test-utils.js.map +1 -1
- package/dist/cjs/tsdoc-metadata.json +1 -1
- package/dist/es/browser.js +1 -1
- package/dist/es/cli.js +36 -10
- package/dist/es/cli.js.map +1 -1
- package/dist/es/core-nodejs.js +3 -2
- package/dist/es/core-nodejs.js.map +1 -1
- package/dist/es/core.js +199 -115
- package/dist/es/core.js.map +1 -1
- package/dist/es/elements.js +29 -5
- package/dist/es/elements.js.map +1 -1
- package/dist/es/html-validate.js +3 -3
- package/dist/es/html-validate.js.map +1 -1
- package/dist/es/index.js +1 -1
- package/dist/es/jest-lib.js +3 -3
- package/dist/es/jest-lib.js.map +1 -1
- package/dist/es/meta-helper.js +16 -2
- package/dist/es/meta-helper.js.map +1 -1
- package/dist/es/test-utils.js +1 -1
- package/dist/es/test-utils.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/types/browser.d.ts +33 -56
- package/dist/types/index.d.ts +33 -56
- package/dist/types/jest.d.ts +4 -8
- package/package.json +19 -19
package/dist/cjs/core.js
CHANGED
|
@@ -295,7 +295,7 @@ class NestedError extends Error {
|
|
|
295
295
|
super(message);
|
|
296
296
|
Error.captureStackTrace(this, NestedError);
|
|
297
297
|
this.name = NestedError.name;
|
|
298
|
-
if (nested
|
|
298
|
+
if (nested === null || nested === void 0 ? void 0 : nested.stack) {
|
|
299
299
|
this.stack += `\nCaused by: ${nested.stack}`;
|
|
300
300
|
}
|
|
301
301
|
}
|
|
@@ -1030,7 +1030,8 @@ function hasAttribute(node, attr) {
|
|
|
1030
1030
|
* Matches attribute against value.
|
|
1031
1031
|
*/
|
|
1032
1032
|
function matchAttribute(node, key, op, value) {
|
|
1033
|
-
|
|
1033
|
+
var _a;
|
|
1034
|
+
const nodeValue = ((_a = node.getAttributeValue(key)) !== null && _a !== void 0 ? _a : "").toLowerCase();
|
|
1034
1035
|
switch (op) {
|
|
1035
1036
|
case "!=":
|
|
1036
1037
|
return nodeValue !== value;
|
|
@@ -1392,6 +1393,16 @@ class Attribute {
|
|
|
1392
1393
|
get isDynamic() {
|
|
1393
1394
|
return this.value instanceof DynamicValue;
|
|
1394
1395
|
}
|
|
1396
|
+
/**
|
|
1397
|
+
* Test attribute value.
|
|
1398
|
+
*
|
|
1399
|
+
* @param pattern - Pattern to match value against. Can be a RegExp, literal
|
|
1400
|
+
* string or an array of strings (returns true if any value matches the
|
|
1401
|
+
* array).
|
|
1402
|
+
* @param dynamicMatches - If true `DynamicValue` will always match, if false
|
|
1403
|
+
* it never matches.
|
|
1404
|
+
* @returns `true` if attribute value matches pattern.
|
|
1405
|
+
*/
|
|
1395
1406
|
valueMatches(pattern, dynamicMatches = true) {
|
|
1396
1407
|
if (this.value === null) {
|
|
1397
1408
|
return false;
|
|
@@ -1777,7 +1788,7 @@ class DOMTokenList extends Array {
|
|
|
1777
1788
|
this.value = value.expr;
|
|
1778
1789
|
}
|
|
1779
1790
|
else {
|
|
1780
|
-
this.value = value
|
|
1791
|
+
this.value = value !== null && value !== void 0 ? value : "";
|
|
1781
1792
|
}
|
|
1782
1793
|
}
|
|
1783
1794
|
item(n) {
|
|
@@ -2002,7 +2013,7 @@ class IdMatcher extends Matcher {
|
|
|
2002
2013
|
class AttrMatcher extends Matcher {
|
|
2003
2014
|
constructor(attr) {
|
|
2004
2015
|
super();
|
|
2005
|
-
const [, key, op, value] = attr.match(/^(.+?)(?:([~^$*|]?=)"([^"]+?)")?$/);
|
|
2016
|
+
const [, key, op, value] = attr.match(/^(.+?)(?:([~^$*|]?=)"([^"]+?)")?$/); // eslint-disable-line @typescript-eslint/no-non-null-assertion -- will always match
|
|
2006
2017
|
this.key = key;
|
|
2007
2018
|
this.op = op;
|
|
2008
2019
|
this.value = value;
|
|
@@ -2039,11 +2050,11 @@ class PseudoClassMatcher extends Matcher {
|
|
|
2039
2050
|
}
|
|
2040
2051
|
class Pattern {
|
|
2041
2052
|
constructor(pattern) {
|
|
2042
|
-
const match = pattern.match(/^([~+\->]?)((?:[*]|[^.#[:]+)?)(.*)$/);
|
|
2053
|
+
const match = pattern.match(/^([~+\->]?)((?:[*]|[^.#[:]+)?)(.*)$/); // eslint-disable-line @typescript-eslint/no-non-null-assertion -- will always match
|
|
2043
2054
|
match.shift(); /* remove full matched string */
|
|
2044
2055
|
this.selector = pattern;
|
|
2045
2056
|
this.combinator = parseCombinator(match.shift(), pattern);
|
|
2046
|
-
this.tagName = match.shift() || "*";
|
|
2057
|
+
this.tagName = match.shift() || "*"; // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing -- empty string */
|
|
2047
2058
|
this.pattern = Array.from(splitPattern(match[0]), (it) => this.createMatcher(it));
|
|
2048
2059
|
}
|
|
2049
2060
|
match(node, context) {
|
|
@@ -2217,6 +2228,21 @@ function isElementNode(node) {
|
|
|
2217
2228
|
function isValidTagName(tagName) {
|
|
2218
2229
|
return Boolean(tagName !== "" && tagName !== "*");
|
|
2219
2230
|
}
|
|
2231
|
+
function createAdapter(node) {
|
|
2232
|
+
return {
|
|
2233
|
+
closest(selectors) {
|
|
2234
|
+
var _a;
|
|
2235
|
+
return (_a = node.closest(selectors)) === null || _a === void 0 ? void 0 : _a._adapter;
|
|
2236
|
+
},
|
|
2237
|
+
getAttribute(name) {
|
|
2238
|
+
var _a;
|
|
2239
|
+
return (_a = node.getAttribute(name)) === null || _a === void 0 ? void 0 : _a.value;
|
|
2240
|
+
},
|
|
2241
|
+
hasAttribute(name) {
|
|
2242
|
+
return node.hasAttribute(name);
|
|
2243
|
+
},
|
|
2244
|
+
};
|
|
2245
|
+
}
|
|
2220
2246
|
/**
|
|
2221
2247
|
* @public
|
|
2222
2248
|
*/
|
|
@@ -2225,9 +2251,9 @@ class HtmlElement extends DOMNode {
|
|
|
2225
2251
|
const nodeType = tagName ? exports.NodeType.ELEMENT_NODE : exports.NodeType.DOCUMENT_NODE;
|
|
2226
2252
|
super(nodeType, tagName, location);
|
|
2227
2253
|
if (!isValidTagName(tagName)) {
|
|
2228
|
-
throw new Error(`The tag name provided ('${tagName
|
|
2254
|
+
throw new Error(`The tag name provided ('${tagName !== null && tagName !== void 0 ? tagName : ""}') is not a valid name`);
|
|
2229
2255
|
}
|
|
2230
|
-
this.tagName = tagName
|
|
2256
|
+
this.tagName = tagName !== null && tagName !== void 0 ? tagName : "#document";
|
|
2231
2257
|
this.parent = parent !== null && parent !== void 0 ? parent : null;
|
|
2232
2258
|
this.attr = {};
|
|
2233
2259
|
this.metaElement = meta !== null && meta !== void 0 ? meta : null;
|
|
@@ -2235,6 +2261,7 @@ class HtmlElement extends DOMNode {
|
|
|
2235
2261
|
this.voidElement = meta ? Boolean(meta.void) : false;
|
|
2236
2262
|
this.depth = 0;
|
|
2237
2263
|
this.annotation = null;
|
|
2264
|
+
this._adapter = createAdapter(this);
|
|
2238
2265
|
if (parent) {
|
|
2239
2266
|
parent.childNodes.push(this);
|
|
2240
2267
|
/* calculate depth in domtree */
|
|
@@ -2294,7 +2321,7 @@ class HtmlElement extends DOMNode {
|
|
|
2294
2321
|
*/
|
|
2295
2322
|
get ariaLabelledby() {
|
|
2296
2323
|
const attr = this.getAttribute("aria-labelledby");
|
|
2297
|
-
if (!attr ||
|
|
2324
|
+
if (!(attr === null || attr === void 0 ? void 0 : attr.value)) {
|
|
2298
2325
|
return null;
|
|
2299
2326
|
}
|
|
2300
2327
|
if (attr.value instanceof DynamicValue) {
|
|
@@ -2412,6 +2439,7 @@ class HtmlElement extends DOMNode {
|
|
|
2412
2439
|
setMetaProperty(this.metaElement, key, value);
|
|
2413
2440
|
}
|
|
2414
2441
|
else {
|
|
2442
|
+
/* eslint-disable-next-line @typescript-eslint/no-dynamic-delete -- technical debt */
|
|
2415
2443
|
delete this.metaElement[key];
|
|
2416
2444
|
}
|
|
2417
2445
|
}
|
|
@@ -2687,11 +2715,12 @@ class DOMTree {
|
|
|
2687
2715
|
this.active = node;
|
|
2688
2716
|
}
|
|
2689
2717
|
popActive() {
|
|
2718
|
+
var _a;
|
|
2690
2719
|
if (this.active.isRootElement()) {
|
|
2691
2720
|
/* root element should never be popped, continue as if nothing happened */
|
|
2692
2721
|
return;
|
|
2693
2722
|
}
|
|
2694
|
-
this.active = this.active.parent
|
|
2723
|
+
this.active = (_a = this.active.parent) !== null && _a !== void 0 ? _a : this.root;
|
|
2695
2724
|
}
|
|
2696
2725
|
getActive() {
|
|
2697
2726
|
return this.active;
|
|
@@ -2727,6 +2756,7 @@ const allowedKeys = ["exclude"];
|
|
|
2727
2756
|
*
|
|
2728
2757
|
* @public
|
|
2729
2758
|
*/
|
|
2759
|
+
/* eslint-disable-next-line @typescript-eslint/no-extraneous-class -- technical debt, should probably be plain functions maybe in an object */
|
|
2730
2760
|
class Validator {
|
|
2731
2761
|
/**
|
|
2732
2762
|
* Test if element is used in a proper context.
|
|
@@ -2768,7 +2798,7 @@ class Validator {
|
|
|
2768
2798
|
return false;
|
|
2769
2799
|
}
|
|
2770
2800
|
// Check if the rule has a quantifier
|
|
2771
|
-
const [, category, quantifier] = rule.match(/^(@?.*?)([?*]?)$/);
|
|
2801
|
+
const [, category, quantifier] = rule.match(/^(@?.*?)([?*]?)$/); // eslint-disable-line @typescript-eslint/no-non-null-assertion -- will always match
|
|
2772
2802
|
const limit = category && quantifier && parseQuantifier(quantifier);
|
|
2773
2803
|
if (limit) {
|
|
2774
2804
|
const siblings = children.filter((cur) => Validator.validatePermittedCategory(cur, rule, true));
|
|
@@ -2814,6 +2844,7 @@ class Validator {
|
|
|
2814
2844
|
* In both of these cases no error should be reported. */
|
|
2815
2845
|
const orderSpecified = rules.find((cur) => Validator.validatePermittedCategory(node, cur, true));
|
|
2816
2846
|
if (orderSpecified) {
|
|
2847
|
+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- technical debt, should never happen */
|
|
2817
2848
|
cb(node, prev);
|
|
2818
2849
|
return false;
|
|
2819
2850
|
}
|
|
@@ -2954,7 +2985,7 @@ class Validator {
|
|
|
2954
2985
|
*/
|
|
2955
2986
|
/* eslint-disable-next-line complexity -- rule does not like switch */
|
|
2956
2987
|
static validatePermittedCategory(node, category, defaultMatch) {
|
|
2957
|
-
const [, rawCategory] = category.match(/^(@?.*?)([?*]?)$/);
|
|
2988
|
+
const [, rawCategory] = category.match(/^(@?.*?)([?*]?)$/); // eslint-disable-line @typescript-eslint/no-non-null-assertion -- will always match
|
|
2958
2989
|
/* match tagName when an explicit name is given */
|
|
2959
2990
|
if (!rawCategory.startsWith("@")) {
|
|
2960
2991
|
return node.tagName === rawCategory;
|
|
@@ -2979,9 +3010,9 @@ class Validator {
|
|
|
2979
3010
|
case "@interactive":
|
|
2980
3011
|
return node.meta.interactive;
|
|
2981
3012
|
case "@script":
|
|
2982
|
-
return node.meta.scriptSupporting;
|
|
3013
|
+
return Boolean(node.meta.scriptSupporting);
|
|
2983
3014
|
case "@form":
|
|
2984
|
-
return node.meta.form;
|
|
3015
|
+
return Boolean(node.meta.form);
|
|
2985
3016
|
default:
|
|
2986
3017
|
throw new Error(`Invalid content category "${category}"`);
|
|
2987
3018
|
}
|
|
@@ -3166,10 +3197,12 @@ var configurationSchema = {
|
|
|
3166
3197
|
properties: properties
|
|
3167
3198
|
};
|
|
3168
3199
|
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3200
|
+
/**
|
|
3201
|
+
* @internal
|
|
3202
|
+
*/
|
|
3203
|
+
const TRANSFORMER_API = {
|
|
3204
|
+
VERSION: 1,
|
|
3205
|
+
};
|
|
3173
3206
|
|
|
3174
3207
|
/**
|
|
3175
3208
|
* @public
|
|
@@ -3416,7 +3449,7 @@ function classifyNodeText(node, options = {}) {
|
|
|
3416
3449
|
const { accessible = false, ignoreHiddenRoot = false } = options;
|
|
3417
3450
|
const cacheKey = getCachekey(options);
|
|
3418
3451
|
if (node.cacheExists(cacheKey)) {
|
|
3419
|
-
return node.cacheGet(cacheKey);
|
|
3452
|
+
return node.cacheGet(cacheKey); // eslint-disable-line @typescript-eslint/no-non-null-assertion -- has/get combo
|
|
3420
3453
|
}
|
|
3421
3454
|
if (!ignoreHiddenRoot && isHTMLHidden(node)) {
|
|
3422
3455
|
return node.cacheSet(cacheKey, exports.TextClassification.EMPTY_TEXT);
|
|
@@ -3464,8 +3497,12 @@ function findTextNodes(node, options) {
|
|
|
3464
3497
|
|
|
3465
3498
|
function hasAltText(image) {
|
|
3466
3499
|
const alt = image.getAttribute("alt");
|
|
3467
|
-
/* missing
|
|
3468
|
-
if (alt
|
|
3500
|
+
/* missing attribute */
|
|
3501
|
+
if (!alt) {
|
|
3502
|
+
return false;
|
|
3503
|
+
}
|
|
3504
|
+
/* (incorrectly) set as boolean value */
|
|
3505
|
+
if (alt.value === null) {
|
|
3469
3506
|
return false;
|
|
3470
3507
|
}
|
|
3471
3508
|
return alt.isDynamic || alt.value.toString() !== "";
|
|
@@ -3473,8 +3510,12 @@ function hasAltText(image) {
|
|
|
3473
3510
|
|
|
3474
3511
|
function hasAriaLabel(node) {
|
|
3475
3512
|
const label = node.getAttribute("aria-label");
|
|
3476
|
-
/* missing
|
|
3477
|
-
if (label
|
|
3513
|
+
/* missing attribute */
|
|
3514
|
+
if (!label) {
|
|
3515
|
+
return false;
|
|
3516
|
+
}
|
|
3517
|
+
/* (incorrectly) set as boolean value */
|
|
3518
|
+
if (label.value === null) {
|
|
3478
3519
|
return false;
|
|
3479
3520
|
}
|
|
3480
3521
|
return label.isDynamic || label.value.toString() !== "";
|
|
@@ -3555,7 +3596,7 @@ class Rule {
|
|
|
3555
3596
|
this.options = options;
|
|
3556
3597
|
this.enabled = true;
|
|
3557
3598
|
this.blockers = [];
|
|
3558
|
-
this.severity =
|
|
3599
|
+
this.severity = exports.Severity.DISABLED;
|
|
3559
3600
|
this.name = "";
|
|
3560
3601
|
}
|
|
3561
3602
|
getSeverity() {
|
|
@@ -3708,13 +3749,14 @@ class Rule {
|
|
|
3708
3749
|
}
|
|
3709
3750
|
}
|
|
3710
3751
|
findLocation(src) {
|
|
3752
|
+
var _a, _b;
|
|
3711
3753
|
if (src.location) {
|
|
3712
3754
|
return src.location;
|
|
3713
3755
|
}
|
|
3714
|
-
if (src.event
|
|
3756
|
+
if ((_a = src.event) === null || _a === void 0 ? void 0 : _a.location) {
|
|
3715
3757
|
return src.event.location;
|
|
3716
3758
|
}
|
|
3717
|
-
if (src.node
|
|
3759
|
+
if ((_b = src.node) === null || _b === void 0 ? void 0 : _b.location) {
|
|
3718
3760
|
return src.node.location;
|
|
3719
3761
|
}
|
|
3720
3762
|
return {};
|
|
@@ -3887,7 +3929,8 @@ class AllowedLinks extends Rule {
|
|
|
3887
3929
|
};
|
|
3888
3930
|
}
|
|
3889
3931
|
documentation(context) {
|
|
3890
|
-
|
|
3932
|
+
var _a;
|
|
3933
|
+
const message = (_a = description[context]) !== null && _a !== void 0 ? _a : "This link type is not allowed by current configuration";
|
|
3891
3934
|
return {
|
|
3892
3935
|
description: message,
|
|
3893
3936
|
url: "https://html-validate.org/rules/allowed-links.html",
|
|
@@ -4151,7 +4194,7 @@ function isValidUsage(target, meta) {
|
|
|
4151
4194
|
return true;
|
|
4152
4195
|
}
|
|
4153
4196
|
/* interactive and labelable elements are valid */
|
|
4154
|
-
if (meta.interactive || meta.labelable) {
|
|
4197
|
+
if (Boolean(meta.interactive) || Boolean(meta.labelable)) {
|
|
4155
4198
|
return true;
|
|
4156
4199
|
}
|
|
4157
4200
|
return false;
|
|
@@ -4186,7 +4229,7 @@ class AriaLabelMisuse extends Rule {
|
|
|
4186
4229
|
}
|
|
4187
4230
|
validateElement(target) {
|
|
4188
4231
|
const attr = target.getAttribute("aria-label");
|
|
4189
|
-
if (!attr ||
|
|
4232
|
+
if (!(attr === null || attr === void 0 ? void 0 : attr.value) || attr.valueMatches("", false)) {
|
|
4190
4233
|
return;
|
|
4191
4234
|
}
|
|
4192
4235
|
/* ignore elements without meta */
|
|
@@ -4917,7 +4960,7 @@ class AttributeAllowedValues extends Rule {
|
|
|
4917
4960
|
const meta = node.meta;
|
|
4918
4961
|
/* ignore rule if element has no meta or meta does not specify attribute
|
|
4919
4962
|
* allowed values */
|
|
4920
|
-
if (!meta ||
|
|
4963
|
+
if (!(meta === null || meta === void 0 ? void 0 : meta.attributes))
|
|
4921
4964
|
return;
|
|
4922
4965
|
for (const attr of node.attributes) {
|
|
4923
4966
|
if (Validator.validateAttribute(attr, meta.attributes)) {
|
|
@@ -4985,7 +5028,7 @@ class AttributeBooleanStyle extends Rule {
|
|
|
4985
5028
|
const meta = node.meta;
|
|
4986
5029
|
/* ignore rule if element has no meta or meta does not specify attribute
|
|
4987
5030
|
* allowed values */
|
|
4988
|
-
if (!meta ||
|
|
5031
|
+
if (!(meta === null || meta === void 0 ? void 0 : meta.attributes))
|
|
4989
5032
|
return;
|
|
4990
5033
|
/* check all boolean attributes */
|
|
4991
5034
|
for (const attr of node.attributes) {
|
|
@@ -5066,7 +5109,7 @@ class AttributeEmptyStyle extends Rule {
|
|
|
5066
5109
|
const meta = node.meta;
|
|
5067
5110
|
/* ignore rule if element has no meta or meta does not specify attribute
|
|
5068
5111
|
* allowed values */
|
|
5069
|
-
if (!meta ||
|
|
5112
|
+
if (!(meta === null || meta === void 0 ? void 0 : meta.attributes))
|
|
5070
5113
|
return;
|
|
5071
5114
|
/* check all boolean attributes */
|
|
5072
5115
|
for (const attr of node.attributes) {
|
|
@@ -5154,10 +5197,10 @@ class AttributeMisuse extends Rule {
|
|
|
5154
5197
|
});
|
|
5155
5198
|
}
|
|
5156
5199
|
validateAttr(node, attr, meta) {
|
|
5157
|
-
if (!meta ||
|
|
5200
|
+
if (!(meta === null || meta === void 0 ? void 0 : meta.allowed)) {
|
|
5158
5201
|
return;
|
|
5159
5202
|
}
|
|
5160
|
-
const details = meta.allowed(node, attr);
|
|
5203
|
+
const details = meta.allowed(node._adapter, attr.value);
|
|
5161
5204
|
if (details) {
|
|
5162
5205
|
this.report({
|
|
5163
5206
|
node,
|
|
@@ -5828,7 +5871,7 @@ class ElementPermittedOccurrences extends Rule {
|
|
|
5828
5871
|
this.on("dom:ready", (event) => {
|
|
5829
5872
|
const doc = event.document;
|
|
5830
5873
|
doc.visitDepthFirst((node) => {
|
|
5831
|
-
if (!node ||
|
|
5874
|
+
if (!(node === null || node === void 0 ? void 0 : node.meta)) {
|
|
5832
5875
|
return;
|
|
5833
5876
|
}
|
|
5834
5877
|
const rules = node.meta.permittedContent;
|
|
@@ -6033,7 +6076,7 @@ class ElementRequiredAttributes extends Rule {
|
|
|
6033
6076
|
const node = event.previous;
|
|
6034
6077
|
const meta = node.meta;
|
|
6035
6078
|
/* handle missing metadata and missing attributes */
|
|
6036
|
-
if (!meta ||
|
|
6079
|
+
if (!(meta === null || meta === void 0 ? void 0 : meta.attributes)) {
|
|
6037
6080
|
return;
|
|
6038
6081
|
}
|
|
6039
6082
|
for (const [key, attr] of Object.entries(meta.attributes)) {
|
|
@@ -6345,7 +6388,7 @@ class FormDupName extends Rule {
|
|
|
6345
6388
|
const meta = this.getMetaFor(tagName);
|
|
6346
6389
|
/* istanbul ignore if: the earlier check for getTagsWithProperty ensures
|
|
6347
6390
|
* these will actually be set so this is just an untestable fallback */
|
|
6348
|
-
if (!meta ||
|
|
6391
|
+
if (!(meta === null || meta === void 0 ? void 0 : meta.formAssociated)) {
|
|
6349
6392
|
return false;
|
|
6350
6393
|
}
|
|
6351
6394
|
return meta.formAssociated.listed;
|
|
@@ -6379,7 +6422,7 @@ const defaults$h = {
|
|
|
6379
6422
|
minInitialRank: "h1",
|
|
6380
6423
|
sectioningRoots: ["dialog", '[role="dialog"]', '[role="alertdialog"]'],
|
|
6381
6424
|
};
|
|
6382
|
-
function isRelevant$
|
|
6425
|
+
function isRelevant$4(event) {
|
|
6383
6426
|
const node = event.target;
|
|
6384
6427
|
return Boolean(node.meta && node.meta.heading);
|
|
6385
6428
|
}
|
|
@@ -6447,7 +6490,7 @@ class HeadingLevel extends Rule {
|
|
|
6447
6490
|
};
|
|
6448
6491
|
}
|
|
6449
6492
|
setup() {
|
|
6450
|
-
this.on("tag:start", isRelevant$
|
|
6493
|
+
this.on("tag:start", isRelevant$4, (event) => {
|
|
6451
6494
|
this.onTagStart(event);
|
|
6452
6495
|
});
|
|
6453
6496
|
this.on("tag:ready", (event) => {
|
|
@@ -6593,7 +6636,7 @@ class IdPattern extends Rule {
|
|
|
6593
6636
|
}
|
|
6594
6637
|
setup() {
|
|
6595
6638
|
this.on("attr", (event) => {
|
|
6596
|
-
var _a;
|
|
6639
|
+
var _a, _b;
|
|
6597
6640
|
if (event.key.toLowerCase() !== "id") {
|
|
6598
6641
|
return;
|
|
6599
6642
|
}
|
|
@@ -6601,8 +6644,8 @@ class IdPattern extends Rule {
|
|
|
6601
6644
|
if (event.value instanceof DynamicValue) {
|
|
6602
6645
|
return;
|
|
6603
6646
|
}
|
|
6604
|
-
if (!event.value ||
|
|
6605
|
-
const value = (
|
|
6647
|
+
if (!((_a = event.value) === null || _a === void 0 ? void 0 : _a.match(this.pattern))) {
|
|
6648
|
+
const value = (_b = event.value) !== null && _b !== void 0 ? _b : "";
|
|
6606
6649
|
const pattern = this.pattern.toString();
|
|
6607
6650
|
const message = `ID "${value}" does not match required pattern "${pattern}"`;
|
|
6608
6651
|
this.report(event.target, message, event.valueLocation);
|
|
@@ -7030,7 +7073,7 @@ class MetaRefresh extends Rule {
|
|
|
7030
7073
|
}
|
|
7031
7074
|
/* ensure content attribute is set */
|
|
7032
7075
|
const content = target.getAttribute("content");
|
|
7033
|
-
if (!content ||
|
|
7076
|
+
if (!(content === null || content === void 0 ? void 0 : content.value) || content.isDynamic) {
|
|
7034
7077
|
return;
|
|
7035
7078
|
}
|
|
7036
7079
|
/* ensure content attribute is valid */
|
|
@@ -7107,7 +7150,7 @@ class MapDupName extends Rule {
|
|
|
7107
7150
|
}
|
|
7108
7151
|
}
|
|
7109
7152
|
|
|
7110
|
-
function isRelevant$
|
|
7153
|
+
function isRelevant$3(event) {
|
|
7111
7154
|
return event.target.is("map");
|
|
7112
7155
|
}
|
|
7113
7156
|
function hasStaticValue(attr) {
|
|
@@ -7121,7 +7164,7 @@ class MapIdName extends Rule {
|
|
|
7121
7164
|
};
|
|
7122
7165
|
}
|
|
7123
7166
|
setup() {
|
|
7124
|
-
this.on("tag:ready", isRelevant$
|
|
7167
|
+
this.on("tag:ready", isRelevant$3, (event) => {
|
|
7125
7168
|
var _a;
|
|
7126
7169
|
const { target } = event;
|
|
7127
7170
|
const id = target.getAttribute("id");
|
|
@@ -7309,7 +7352,7 @@ class NoDeprecatedAttr extends Rule {
|
|
|
7309
7352
|
if (meta === null) {
|
|
7310
7353
|
return;
|
|
7311
7354
|
}
|
|
7312
|
-
const metaAttribute = meta.attributes
|
|
7355
|
+
const metaAttribute = meta.attributes[attr];
|
|
7313
7356
|
if (!metaAttribute) {
|
|
7314
7357
|
return;
|
|
7315
7358
|
}
|
|
@@ -7385,11 +7428,11 @@ class NoDupID extends Rule {
|
|
|
7385
7428
|
const { document } = event;
|
|
7386
7429
|
const existing = new Set();
|
|
7387
7430
|
const elements = document.querySelectorAll("[id]");
|
|
7388
|
-
const relevant = elements.filter(isRelevant$
|
|
7431
|
+
const relevant = elements.filter(isRelevant$2);
|
|
7389
7432
|
for (const el of relevant) {
|
|
7390
7433
|
const attr = el.getAttribute("id");
|
|
7391
7434
|
/* istanbul ignore next: this has already been tested in isRelevant once but for type-safety it is checked again */
|
|
7392
|
-
if (!attr ||
|
|
7435
|
+
if (!(attr === null || attr === void 0 ? void 0 : attr.value)) {
|
|
7393
7436
|
continue;
|
|
7394
7437
|
}
|
|
7395
7438
|
const id = attr.value.toString();
|
|
@@ -7401,7 +7444,7 @@ class NoDupID extends Rule {
|
|
|
7401
7444
|
});
|
|
7402
7445
|
}
|
|
7403
7446
|
}
|
|
7404
|
-
function isRelevant$
|
|
7447
|
+
function isRelevant$2(element) {
|
|
7405
7448
|
const attr = element.getAttribute("id");
|
|
7406
7449
|
/* istanbul ignore next: can not really happen as querySelector will only return elements with id present */
|
|
7407
7450
|
if (!attr) {
|
|
@@ -7418,6 +7461,41 @@ function isRelevant$1(element) {
|
|
|
7418
7461
|
return true;
|
|
7419
7462
|
}
|
|
7420
7463
|
|
|
7464
|
+
function isRelevant$1(event) {
|
|
7465
|
+
return event.target.is("button");
|
|
7466
|
+
}
|
|
7467
|
+
class NoImplicitButtonType extends Rule {
|
|
7468
|
+
documentation() {
|
|
7469
|
+
return {
|
|
7470
|
+
description: [
|
|
7471
|
+
"`<button>` is missing required `type` attribute",
|
|
7472
|
+
"",
|
|
7473
|
+
"When the `type` attribute is omitted it defaults to `submit`.",
|
|
7474
|
+
"Submit buttons are triggered when a keyboard user presses <kbd>Enter</kbd>.",
|
|
7475
|
+
"",
|
|
7476
|
+
"As this may or may not be inteded this rule enforces that the `type` attribute be explicitly set to one of the valid types:",
|
|
7477
|
+
"",
|
|
7478
|
+
"- `button` - a generic button.",
|
|
7479
|
+
"- `submit` - a submit button.",
|
|
7480
|
+
"- `reset`- a button to reset form fields.",
|
|
7481
|
+
].join("\n"),
|
|
7482
|
+
url: "https://html-validate.org/rules/no-implicit-button-type.html",
|
|
7483
|
+
};
|
|
7484
|
+
}
|
|
7485
|
+
setup() {
|
|
7486
|
+
this.on("element:ready", isRelevant$1, (event) => {
|
|
7487
|
+
const { target } = event;
|
|
7488
|
+
const attr = target.getAttribute("type");
|
|
7489
|
+
if (!attr) {
|
|
7490
|
+
this.report({
|
|
7491
|
+
node: event.target,
|
|
7492
|
+
message: `<button> is missing required "type" attribute`,
|
|
7493
|
+
});
|
|
7494
|
+
}
|
|
7495
|
+
});
|
|
7496
|
+
}
|
|
7497
|
+
}
|
|
7498
|
+
|
|
7421
7499
|
class NoImplicitClose extends Rule {
|
|
7422
7500
|
documentation() {
|
|
7423
7501
|
return {
|
|
@@ -7523,11 +7601,12 @@ class NoInlineStyle extends Rule {
|
|
|
7523
7601
|
});
|
|
7524
7602
|
}
|
|
7525
7603
|
isRelevant(event) {
|
|
7604
|
+
var _a;
|
|
7526
7605
|
if (event.key !== "style") {
|
|
7527
7606
|
return false;
|
|
7528
7607
|
}
|
|
7529
7608
|
const { include, exclude } = this.options;
|
|
7530
|
-
const key = event.originalAttribute
|
|
7609
|
+
const key = (_a = event.originalAttribute) !== null && _a !== void 0 ? _a : event.key;
|
|
7531
7610
|
/* ignore attributes not present in "include" */
|
|
7532
7611
|
if (include && !include.includes(key)) {
|
|
7533
7612
|
return false;
|
|
@@ -7721,7 +7800,8 @@ class NoRawCharacters extends Rule {
|
|
|
7721
7800
|
if (event.quote) {
|
|
7722
7801
|
return;
|
|
7723
7802
|
}
|
|
7724
|
-
this.findRawChars(event.target, event.value.toString(), event.valueLocation,
|
|
7803
|
+
this.findRawChars(event.target, event.value.toString(), event.valueLocation, // eslint-disable-line @typescript-eslint/no-non-null-assertion -- technical debt, valueLocation is always set if a value is provided
|
|
7804
|
+
unquotedAttrRegexp);
|
|
7725
7805
|
});
|
|
7726
7806
|
}
|
|
7727
7807
|
/**
|
|
@@ -7935,7 +8015,7 @@ class NoSelfClosing extends Rule {
|
|
|
7935
8015
|
function isRelevant(node, options) {
|
|
7936
8016
|
/* tags in XML namespaces are relevant only if ignoreXml is false, in which
|
|
7937
8017
|
* case assume all xml elements must not be self-closed */
|
|
7938
|
-
if (node.tagName
|
|
8018
|
+
if (node.tagName.match(xmlns)) {
|
|
7939
8019
|
return !options.ignoreXML;
|
|
7940
8020
|
}
|
|
7941
8021
|
/* nodes with missing metadata is assumed relevant */
|
|
@@ -8141,16 +8221,12 @@ class PreferButton extends Rule {
|
|
|
8141
8221
|
};
|
|
8142
8222
|
}
|
|
8143
8223
|
documentation(context) {
|
|
8144
|
-
const
|
|
8145
|
-
|
|
8224
|
+
const src = `<input type="${context.type}">`;
|
|
8225
|
+
const dst = replacement[context.type] || `<button>`;
|
|
8226
|
+
return {
|
|
8227
|
+
description: `Prefer to use \`${dst}\` instead of \`"${src}\`.`,
|
|
8146
8228
|
url: "https://html-validate.org/rules/prefer-button.html",
|
|
8147
8229
|
};
|
|
8148
|
-
if (context) {
|
|
8149
|
-
const src = `<input type="${context.type}">`;
|
|
8150
|
-
const dst = replacement[context.type] || `<button>`;
|
|
8151
|
-
doc.description = `Prefer to use \`${dst}\` instead of \`"${src}\`.`;
|
|
8152
|
-
}
|
|
8153
|
-
return doc;
|
|
8154
8230
|
}
|
|
8155
8231
|
setup() {
|
|
8156
8232
|
this.on("attr", (event) => {
|
|
@@ -8249,14 +8325,10 @@ class PreferNativeElement extends Rule {
|
|
|
8249
8325
|
};
|
|
8250
8326
|
}
|
|
8251
8327
|
documentation(context) {
|
|
8252
|
-
|
|
8253
|
-
description: `Instead of using WAI-ARIA
|
|
8328
|
+
return {
|
|
8329
|
+
description: `Instead of using the WAI-ARIA role "${context.role}" prefer to use the native <${context.replacement}> element.`,
|
|
8254
8330
|
url: "https://html-validate.org/rules/prefer-native-element.html",
|
|
8255
8331
|
};
|
|
8256
|
-
if (context) {
|
|
8257
|
-
doc.description = `Instead of using the WAI-ARIA role "${context.role}" prefer to use the native <${context.replacement}> element.`;
|
|
8258
|
-
}
|
|
8259
|
-
return doc;
|
|
8260
8332
|
}
|
|
8261
8333
|
setup() {
|
|
8262
8334
|
const { mapping } = this.options;
|
|
@@ -8297,7 +8369,7 @@ class PreferNativeElement extends Rule {
|
|
|
8297
8369
|
}
|
|
8298
8370
|
getLocation(event) {
|
|
8299
8371
|
const begin = event.location;
|
|
8300
|
-
const end = event.valueLocation;
|
|
8372
|
+
const end = event.valueLocation; // eslint-disable-line @typescript-eslint/no-non-null-assertion -- technical debt, valueLocation will always be set when a value is provided
|
|
8301
8373
|
const quote = event.quote ? 1 : 0;
|
|
8302
8374
|
const size = end.offset + end.size - begin.offset + quote;
|
|
8303
8375
|
return {
|
|
@@ -8371,7 +8443,7 @@ class RequireCSPNonce extends Rule {
|
|
|
8371
8443
|
const { tags } = this.options;
|
|
8372
8444
|
const node = event.previous;
|
|
8373
8445
|
/* ignore other tags */
|
|
8374
|
-
if (!
|
|
8446
|
+
if (!tags.includes(node.tagName)) {
|
|
8375
8447
|
return;
|
|
8376
8448
|
}
|
|
8377
8449
|
/* ignore if nonce is set to non-empty value (or dynamic) */
|
|
@@ -8463,7 +8535,10 @@ class RequireSri extends Rule {
|
|
|
8463
8535
|
}
|
|
8464
8536
|
needSri(node) {
|
|
8465
8537
|
const attr = this.elementSourceAttr(node);
|
|
8466
|
-
if (!attr
|
|
8538
|
+
if (!attr) {
|
|
8539
|
+
return false;
|
|
8540
|
+
}
|
|
8541
|
+
if (attr.value === null || attr.value === "" || attr.isDynamic) {
|
|
8467
8542
|
return false;
|
|
8468
8543
|
}
|
|
8469
8544
|
const url = attr.value.toString();
|
|
@@ -8520,7 +8595,7 @@ class ScriptType extends Rule {
|
|
|
8520
8595
|
setup() {
|
|
8521
8596
|
this.on("tag:end", (event) => {
|
|
8522
8597
|
const node = event.previous;
|
|
8523
|
-
if (
|
|
8598
|
+
if (node.tagName !== "script") {
|
|
8524
8599
|
return;
|
|
8525
8600
|
}
|
|
8526
8601
|
const attr = node.getAttribute("type");
|
|
@@ -8801,18 +8876,16 @@ class TextContent extends Rule {
|
|
|
8801
8876
|
description: `The textual content for this element is not valid.`,
|
|
8802
8877
|
url: "https://html-validate.org/rules/text-content.html",
|
|
8803
8878
|
};
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
|
|
8810
|
-
|
|
8811
|
-
|
|
8812
|
-
|
|
8813
|
-
|
|
8814
|
-
break;
|
|
8815
|
-
}
|
|
8879
|
+
switch (context.textContent) {
|
|
8880
|
+
case exports.TextContent.NONE:
|
|
8881
|
+
doc.description = `The \`<${context.tagName}>\` element must not have textual content.`;
|
|
8882
|
+
break;
|
|
8883
|
+
case exports.TextContent.REQUIRED:
|
|
8884
|
+
doc.description = `The \`<${context.tagName}>\` element must have textual content.`;
|
|
8885
|
+
break;
|
|
8886
|
+
case exports.TextContent.ACCESSIBLE:
|
|
8887
|
+
doc.description = `The \`<${context.tagName}>\` element must have accessible text.`;
|
|
8888
|
+
break;
|
|
8816
8889
|
}
|
|
8817
8890
|
return doc;
|
|
8818
8891
|
}
|
|
@@ -9173,20 +9246,16 @@ class VoidStyle extends Rule {
|
|
|
9173
9246
|
};
|
|
9174
9247
|
}
|
|
9175
9248
|
documentation(context) {
|
|
9176
|
-
const
|
|
9177
|
-
|
|
9249
|
+
const [desc, end] = styleDescription(context.style);
|
|
9250
|
+
return {
|
|
9251
|
+
description: `The current configuration requires void elements to ${desc}, use <${context.tagName}${end}> instead.`,
|
|
9178
9252
|
url: "https://html-validate.org/rules/void-style.html",
|
|
9179
9253
|
};
|
|
9180
|
-
if (context) {
|
|
9181
|
-
const [desc, end] = styleDescription(context.style);
|
|
9182
|
-
doc.description = `The current configuration requires void elements to ${desc}, use <${context.tagName}${end}> instead.`;
|
|
9183
|
-
}
|
|
9184
|
-
return doc;
|
|
9185
9254
|
}
|
|
9186
9255
|
setup() {
|
|
9187
9256
|
this.on("tag:end", (event) => {
|
|
9188
9257
|
const active = event.previous; // The current active element (that is, the current element on the stack)
|
|
9189
|
-
if (active
|
|
9258
|
+
if (active.meta) {
|
|
9190
9259
|
this.validateActive(active);
|
|
9191
9260
|
}
|
|
9192
9261
|
});
|
|
@@ -9423,7 +9492,8 @@ class H37 extends Rule {
|
|
|
9423
9492
|
return;
|
|
9424
9493
|
}
|
|
9425
9494
|
/* validate plain alt-attribute */
|
|
9426
|
-
if (node.getAttributeValue("alt") ||
|
|
9495
|
+
if (Boolean(node.getAttributeValue("alt")) ||
|
|
9496
|
+
Boolean(node.hasAttribute("alt") && this.options.allowEmpty)) {
|
|
9427
9497
|
return;
|
|
9428
9498
|
}
|
|
9429
9499
|
/* validate if any non-empty alias is present */
|
|
@@ -9600,6 +9670,7 @@ const bundledRules = {
|
|
|
9600
9670
|
"no-dup-attr": NoDupAttr,
|
|
9601
9671
|
"no-dup-class": NoDupClass,
|
|
9602
9672
|
"no-dup-id": NoDupID,
|
|
9673
|
+
"no-implicit-button-type": NoImplicitButtonType,
|
|
9603
9674
|
"no-implicit-close": NoImplicitClose,
|
|
9604
9675
|
"no-inline-style": NoInlineStyle,
|
|
9605
9676
|
"no-missing-references": NoMissingReferences,
|
|
@@ -9646,6 +9717,7 @@ const config$4 = {
|
|
|
9646
9717
|
"multiple-labeled-controls": "error",
|
|
9647
9718
|
"no-autoplay": ["error", { include: ["audio", "video"] }],
|
|
9648
9719
|
"no-dup-id": "error",
|
|
9720
|
+
"no-implicit-button-type": "error",
|
|
9649
9721
|
"no-redundant-aria-label": "error",
|
|
9650
9722
|
"no-redundant-for": "error",
|
|
9651
9723
|
"no-redundant-role": "error",
|
|
@@ -9725,6 +9797,7 @@ const config$1 = {
|
|
|
9725
9797
|
"no-dup-attr": "error",
|
|
9726
9798
|
"no-dup-class": "error",
|
|
9727
9799
|
"no-dup-id": "error",
|
|
9800
|
+
"no-implicit-button-type": "error",
|
|
9728
9801
|
"no-implicit-close": "error",
|
|
9729
9802
|
"no-inline-style": "error",
|
|
9730
9803
|
"no-multiple-main": "error",
|
|
@@ -9856,7 +9929,7 @@ class ResolvedConfig {
|
|
|
9856
9929
|
* @returns A list of transformed sources ready for validation.
|
|
9857
9930
|
*/
|
|
9858
9931
|
transformSource(source, filename) {
|
|
9859
|
-
const transformer = this.findTransformer(filename
|
|
9932
|
+
const transformer = this.findTransformer(filename !== null && filename !== void 0 ? filename : source.filename);
|
|
9860
9933
|
const context = {
|
|
9861
9934
|
hasChain: (filename) => {
|
|
9862
9935
|
return !!this.findTransformer(filename);
|
|
@@ -9868,9 +9941,10 @@ class ResolvedConfig {
|
|
|
9868
9941
|
if (transformer) {
|
|
9869
9942
|
try {
|
|
9870
9943
|
return Array.from(transformer.fn.call(context, source), (cur) => {
|
|
9944
|
+
var _a;
|
|
9871
9945
|
/* keep track of which transformers that has been run on this source
|
|
9872
9946
|
* by appending this entry to the transformedBy array */
|
|
9873
|
-
cur.transformedBy
|
|
9947
|
+
(_a = cur.transformedBy) !== null && _a !== void 0 ? _a : (cur.transformedBy = []);
|
|
9874
9948
|
cur.transformedBy.push(transformer.name);
|
|
9875
9949
|
return cur;
|
|
9876
9950
|
});
|
|
@@ -10042,7 +10116,7 @@ function mergeInternal(base, rhs) {
|
|
|
10042
10116
|
}
|
|
10043
10117
|
/* root property is merged with boolean "or" since it should always be truthy
|
|
10044
10118
|
* if any config has it set. */
|
|
10045
|
-
const root = base.root || rhs.root;
|
|
10119
|
+
const root = Boolean(base.root) || Boolean(rhs.root);
|
|
10046
10120
|
if (root) {
|
|
10047
10121
|
dst.root = root;
|
|
10048
10122
|
}
|
|
@@ -10129,7 +10203,7 @@ class Config {
|
|
|
10129
10203
|
* @internal
|
|
10130
10204
|
*/
|
|
10131
10205
|
constructor(resolvers, options) {
|
|
10132
|
-
var _a;
|
|
10206
|
+
var _a, _b;
|
|
10133
10207
|
this.transformers = [];
|
|
10134
10208
|
const initial = {
|
|
10135
10209
|
extends: [],
|
|
@@ -10142,18 +10216,18 @@ class Config {
|
|
|
10142
10216
|
this.initialized = false;
|
|
10143
10217
|
this.resolvers = toArray(resolvers);
|
|
10144
10218
|
/* load plugins */
|
|
10145
|
-
this.plugins = this.loadPlugins(this.config.plugins
|
|
10219
|
+
this.plugins = this.loadPlugins((_a = this.config.plugins) !== null && _a !== void 0 ? _a : []);
|
|
10146
10220
|
this.configurations = this.loadConfigurations(this.plugins);
|
|
10147
10221
|
this.extendMeta(this.plugins);
|
|
10148
10222
|
/* process extended configs */
|
|
10149
|
-
this.config = this.extendConfig((
|
|
10223
|
+
this.config = this.extendConfig((_b = this.config.extends) !== null && _b !== void 0 ? _b : []);
|
|
10150
10224
|
/* reset extends as we already processed them, this prevents the next config
|
|
10151
10225
|
* from reapplying config from extended config as well as duplicate entries
|
|
10152
10226
|
* when merging arrays */
|
|
10153
10227
|
this.config.extends = [];
|
|
10154
10228
|
/* rules explicitly set by passed options should have precedence over any
|
|
10155
10229
|
* extended rules, not the other way around. */
|
|
10156
|
-
if (options
|
|
10230
|
+
if (options === null || options === void 0 ? void 0 : options.rules) {
|
|
10157
10231
|
this.config = mergeInternal(this.config, { rules: options.rules });
|
|
10158
10232
|
}
|
|
10159
10233
|
}
|
|
@@ -10166,11 +10240,12 @@ class Config {
|
|
|
10166
10240
|
* @public
|
|
10167
10241
|
*/
|
|
10168
10242
|
init() {
|
|
10243
|
+
var _a;
|
|
10169
10244
|
if (this.initialized) {
|
|
10170
10245
|
return;
|
|
10171
10246
|
}
|
|
10172
10247
|
/* precompile transform patterns */
|
|
10173
|
-
this.transformers = this.precompileTransformers(this.config.transform
|
|
10248
|
+
this.transformers = this.precompileTransformers((_a = this.config.transform) !== null && _a !== void 0 ? _a : {});
|
|
10174
10249
|
this.initialized = true;
|
|
10175
10250
|
}
|
|
10176
10251
|
/**
|
|
@@ -10197,7 +10272,7 @@ class Config {
|
|
|
10197
10272
|
for (const entry of entries) {
|
|
10198
10273
|
let extended;
|
|
10199
10274
|
if (this.configurations.has(entry)) {
|
|
10200
|
-
extended = this.configurations.get(entry);
|
|
10275
|
+
extended = this.configurations.get(entry); // eslint-disable-line @typescript-eslint/no-non-null-assertion -- map has/get combo
|
|
10201
10276
|
}
|
|
10202
10277
|
else {
|
|
10203
10278
|
extended = Config.fromFile(this.resolvers, entry).config;
|
|
@@ -10212,12 +10287,13 @@ class Config {
|
|
|
10212
10287
|
* @internal
|
|
10213
10288
|
*/
|
|
10214
10289
|
getMetaTable() {
|
|
10290
|
+
var _a;
|
|
10215
10291
|
/* use cached table if it exists */
|
|
10216
10292
|
if (this.metaTable) {
|
|
10217
10293
|
return this.metaTable;
|
|
10218
10294
|
}
|
|
10219
10295
|
const metaTable = new MetaTable();
|
|
10220
|
-
const source = this.config.elements
|
|
10296
|
+
const source = (_a = this.config.elements) !== null && _a !== void 0 ? _a : ["html5"];
|
|
10221
10297
|
/* extend validation schema from plugins */
|
|
10222
10298
|
for (const plugin of this.getPlugins()) {
|
|
10223
10299
|
if (plugin.elementSchema) {
|
|
@@ -10315,6 +10391,7 @@ class Config {
|
|
|
10315
10391
|
});
|
|
10316
10392
|
}
|
|
10317
10393
|
loadConfigurations(plugins) {
|
|
10394
|
+
var _a;
|
|
10318
10395
|
const configs = new Map();
|
|
10319
10396
|
/* builtin presets */
|
|
10320
10397
|
for (const [name, config] of Object.entries(Presets)) {
|
|
@@ -10323,7 +10400,7 @@ class Config {
|
|
|
10323
10400
|
}
|
|
10324
10401
|
/* presets from plugins */
|
|
10325
10402
|
for (const plugin of plugins) {
|
|
10326
|
-
for (const [name, config] of Object.entries(plugin.configs
|
|
10403
|
+
for (const [name, config] of Object.entries((_a = plugin.configs) !== null && _a !== void 0 ? _a : {})) {
|
|
10327
10404
|
if (!config)
|
|
10328
10405
|
continue;
|
|
10329
10406
|
Config.validate(config, name);
|
|
@@ -10688,10 +10765,11 @@ class Parser {
|
|
|
10688
10765
|
* stack when is allowed to omit.
|
|
10689
10766
|
*/
|
|
10690
10767
|
closeOptional(token) {
|
|
10768
|
+
var _a;
|
|
10691
10769
|
/* if the element doesn't have metadata it cannot have optional end
|
|
10692
10770
|
* tags. Period. */
|
|
10693
10771
|
const active = this.dom.getActive();
|
|
10694
|
-
if (!(active.meta
|
|
10772
|
+
if (!((_a = active.meta) === null || _a === void 0 ? void 0 : _a.implicitClosed)) {
|
|
10695
10773
|
return false;
|
|
10696
10774
|
}
|
|
10697
10775
|
const tagName = token.data[2];
|
|
@@ -10843,9 +10921,10 @@ class Parser {
|
|
|
10843
10921
|
}
|
|
10844
10922
|
}
|
|
10845
10923
|
processElement(node, source) {
|
|
10924
|
+
var _a;
|
|
10846
10925
|
/* enable cache on node now that it is fully constructed */
|
|
10847
10926
|
node.cacheEnable();
|
|
10848
|
-
if (source.hooks
|
|
10927
|
+
if ((_a = source.hooks) === null || _a === void 0 ? void 0 : _a.processElement) {
|
|
10849
10928
|
const processElement = source.hooks.processElement;
|
|
10850
10929
|
const metaTable = this.metaTable;
|
|
10851
10930
|
const context = {
|
|
@@ -10912,6 +10991,7 @@ class Parser {
|
|
|
10912
10991
|
* @internal
|
|
10913
10992
|
*/
|
|
10914
10993
|
consumeAttribute(source, node, token, next) {
|
|
10994
|
+
var _a;
|
|
10915
10995
|
const keyLocation = this.getAttributeKeyLocation(token);
|
|
10916
10996
|
const valueLocation = this.getAttributeValueLocation(next);
|
|
10917
10997
|
const location = this.getAttributeLocation(token, next);
|
|
@@ -10930,7 +11010,7 @@ class Parser {
|
|
|
10930
11010
|
* data right away but a transformer may override it to allow aliasing
|
|
10931
11011
|
* attributes, e.g ng-attr-foo or v-bind:foo */
|
|
10932
11012
|
let processAttribute = (attr) => [attr];
|
|
10933
|
-
if (source.hooks
|
|
11013
|
+
if ((_a = source.hooks) === null || _a === void 0 ? void 0 : _a.processAttribute) {
|
|
10934
11014
|
processAttribute = source.hooks.processAttribute;
|
|
10935
11015
|
}
|
|
10936
11016
|
/* handle deprecated callbacks */
|
|
@@ -11280,14 +11360,15 @@ class Reporter {
|
|
|
11280
11360
|
const report = {
|
|
11281
11361
|
valid: this.isValid(),
|
|
11282
11362
|
results: Object.keys(this.result).map((filePath) => {
|
|
11363
|
+
var _a;
|
|
11283
11364
|
const messages = Array.from(this.result[filePath], freeze).sort(messageSort);
|
|
11284
|
-
const source = (sources
|
|
11365
|
+
const source = (sources !== null && sources !== void 0 ? sources : []).find((source) => { var _a; return filePath === ((_a = source.filename) !== null && _a !== void 0 ? _a : ""); });
|
|
11285
11366
|
return {
|
|
11286
11367
|
filePath,
|
|
11287
11368
|
messages,
|
|
11288
11369
|
errorCount: countErrors(messages),
|
|
11289
11370
|
warningCount: countWarnings(messages),
|
|
11290
|
-
source: source ? source.originalData
|
|
11371
|
+
source: source ? (_a = source.originalData) !== null && _a !== void 0 ? _a : source.data : null,
|
|
11291
11372
|
};
|
|
11292
11373
|
}),
|
|
11293
11374
|
errorCount: 0,
|
|
@@ -11305,10 +11386,10 @@ class Reporter {
|
|
|
11305
11386
|
}
|
|
11306
11387
|
}
|
|
11307
11388
|
function countErrors(messages) {
|
|
11308
|
-
return messages.filter((m) => m.severity === exports.Severity.ERROR).length;
|
|
11389
|
+
return messages.filter((m) => m.severity === Number(exports.Severity.ERROR)).length;
|
|
11309
11390
|
}
|
|
11310
11391
|
function countWarnings(messages) {
|
|
11311
|
-
return messages.filter((m) => m.severity === exports.Severity.WARN).length;
|
|
11392
|
+
return messages.filter((m) => m.severity === Number(exports.Severity.WARN)).length;
|
|
11312
11393
|
}
|
|
11313
11394
|
function sumErrors(results) {
|
|
11314
11395
|
return results.reduce((sum, result) => {
|
|
@@ -11653,9 +11734,10 @@ class Engine {
|
|
|
11653
11734
|
* between rule name and its constructor.
|
|
11654
11735
|
*/
|
|
11655
11736
|
initRules(config) {
|
|
11737
|
+
var _a;
|
|
11656
11738
|
const availableRules = {};
|
|
11657
11739
|
for (const plugin of config.getPlugins()) {
|
|
11658
|
-
for (const [name, rule] of Object.entries(plugin.rules
|
|
11740
|
+
for (const [name, rule] of Object.entries((_a = plugin.rules) !== null && _a !== void 0 ? _a : {})) {
|
|
11659
11741
|
if (!rule)
|
|
11660
11742
|
continue;
|
|
11661
11743
|
availableRules[name] = rule;
|
|
@@ -11758,7 +11840,7 @@ class StaticConfigLoader extends ConfigLoader {
|
|
|
11758
11840
|
}
|
|
11759
11841
|
}
|
|
11760
11842
|
getConfigFor(_handle, configOverride) {
|
|
11761
|
-
const override = this.loadFromObject(configOverride
|
|
11843
|
+
const override = this.loadFromObject(configOverride !== null && configOverride !== void 0 ? configOverride : {});
|
|
11762
11844
|
if (override.isRootFound()) {
|
|
11763
11845
|
override.init();
|
|
11764
11846
|
return override.resolve();
|
|
@@ -11802,6 +11884,7 @@ class HtmlValidate {
|
|
|
11802
11884
|
const [loader, config] = arg instanceof ConfigLoader ? [arg, undefined] : [undefined, arg];
|
|
11803
11885
|
this.configLoader = loader !== null && loader !== void 0 ? loader : new StaticConfigLoader(config);
|
|
11804
11886
|
}
|
|
11887
|
+
/* eslint-enable @typescript-eslint/unified-signatures */
|
|
11805
11888
|
validateString(str, arg1, arg2, arg3) {
|
|
11806
11889
|
const filename = typeof arg1 === "string" ? arg1 : "inline";
|
|
11807
11890
|
const options = isConfigData(arg1) ? arg1 : isConfigData(arg2) ? arg2 : undefined;
|
|
@@ -11816,6 +11899,7 @@ class HtmlValidate {
|
|
|
11816
11899
|
};
|
|
11817
11900
|
return this.validateSource(source, options);
|
|
11818
11901
|
}
|
|
11902
|
+
/* eslint-enable @typescript-eslint/unified-signatures */
|
|
11819
11903
|
validateStringSync(str, arg1, arg2, arg3) {
|
|
11820
11904
|
const filename = typeof arg1 === "string" ? arg1 : "inline";
|
|
11821
11905
|
const options = isConfigData(arg1) ? arg1 : isConfigData(arg2) ? arg2 : undefined;
|
|
@@ -12087,7 +12171,7 @@ class HtmlValidate {
|
|
|
12087
12171
|
* contextual details and suggestions.
|
|
12088
12172
|
*/
|
|
12089
12173
|
async getRuleDocumentation(ruleId, config = null, context = null) {
|
|
12090
|
-
const c = config
|
|
12174
|
+
const c = config !== null && config !== void 0 ? config : this.getConfigFor("inline");
|
|
12091
12175
|
const engine = new Engine(await c, Parser);
|
|
12092
12176
|
return engine.getRuleDocumentation({ ruleId, context });
|
|
12093
12177
|
}
|
|
@@ -12116,7 +12200,7 @@ class HtmlValidate {
|
|
|
12116
12200
|
* contextual details and suggestions.
|
|
12117
12201
|
*/
|
|
12118
12202
|
getRuleDocumentationSync(ruleId, config = null, context = null) {
|
|
12119
|
-
const c = config
|
|
12203
|
+
const c = config !== null && config !== void 0 ? config : this.getConfigForSync("inline");
|
|
12120
12204
|
const engine = new Engine(c, Parser);
|
|
12121
12205
|
return engine.getRuleDocumentation({ ruleId, context });
|
|
12122
12206
|
}
|
|
@@ -12172,7 +12256,7 @@ class HtmlValidate {
|
|
|
12172
12256
|
/** @public */
|
|
12173
12257
|
const name = "html-validate";
|
|
12174
12258
|
/** @public */
|
|
12175
|
-
const version = "8.
|
|
12259
|
+
const version = "8.3.0";
|
|
12176
12260
|
/** @public */
|
|
12177
12261
|
const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
|
|
12178
12262
|
|