html-validate 8.10.0 → 8.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/browser.js +1 -0
- package/dist/cjs/browser.js.map +1 -1
- package/dist/cjs/core.js +205 -19
- package/dist/cjs/core.js.map +1 -1
- package/dist/cjs/elements.js +496 -235
- package/dist/cjs/elements.js.map +1 -1
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/tsdoc-metadata.json +1 -1
- package/dist/es/browser.js +1 -1
- package/dist/es/cli.js +1 -1
- package/dist/es/core-browser.js +1 -1
- package/dist/es/core-nodejs.js +1 -1
- package/dist/es/core.js +205 -20
- package/dist/es/core.js.map +1 -1
- package/dist/es/elements.js +496 -235
- package/dist/es/elements.js.map +1 -1
- package/dist/es/html-validate.js +1 -1
- package/dist/es/index.js +1 -1
- package/dist/es/matchers-jestonly.js +1 -1
- package/dist/schema/elements.json +22 -0
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/types/browser.d.ts +78 -1
- package/dist/types/index.d.ts +78 -1
- package/package.json +8 -6
package/dist/cjs/browser.js
CHANGED
|
@@ -45,6 +45,7 @@ exports.TextNode = core.TextNode;
|
|
|
45
45
|
exports.UserError = core.UserError;
|
|
46
46
|
exports.Validator = core.Validator;
|
|
47
47
|
exports.WrappedError = core.WrappedError;
|
|
48
|
+
exports.ariaNaming = core.ariaNaming;
|
|
48
49
|
exports.classifyNodeText = core.classifyNodeText;
|
|
49
50
|
exports.configPresets = core.Presets;
|
|
50
51
|
exports.defineConfig = core.defineConfig;
|
package/dist/cjs/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"browser.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/cjs/core.js
CHANGED
|
@@ -594,8 +594,13 @@ const patternProperties = {
|
|
|
594
594
|
implicitRole: {
|
|
595
595
|
title: "Implicit ARIA role for this element",
|
|
596
596
|
description: "Some elements have implicit ARIA roles.",
|
|
597
|
+
deprecated: true,
|
|
597
598
|
"function": true
|
|
598
599
|
},
|
|
600
|
+
aria: {
|
|
601
|
+
title: "WAI-ARIA properties for this element",
|
|
602
|
+
$ref: "#/definitions/Aria"
|
|
603
|
+
},
|
|
599
604
|
scriptSupporting: {
|
|
600
605
|
title: "Mark element as script-supporting",
|
|
601
606
|
description: "Script-supporting elements are elements which can be inserted where othersise not permitted to assist in templating",
|
|
@@ -692,6 +697,39 @@ const patternProperties = {
|
|
|
692
697
|
}
|
|
693
698
|
};
|
|
694
699
|
const definitions = {
|
|
700
|
+
Aria: {
|
|
701
|
+
type: "object",
|
|
702
|
+
additionalProperties: false,
|
|
703
|
+
properties: {
|
|
704
|
+
implicitRole: {
|
|
705
|
+
title: "Implicit ARIA role for this element",
|
|
706
|
+
description: "Some elements have implicit ARIA roles.",
|
|
707
|
+
anyOf: [
|
|
708
|
+
{
|
|
709
|
+
type: "string"
|
|
710
|
+
},
|
|
711
|
+
{
|
|
712
|
+
"function": true
|
|
713
|
+
}
|
|
714
|
+
]
|
|
715
|
+
},
|
|
716
|
+
naming: {
|
|
717
|
+
title: "Prohibit or allow this element to be named by aria-label or aria-labelledby",
|
|
718
|
+
anyOf: [
|
|
719
|
+
{
|
|
720
|
+
type: "string",
|
|
721
|
+
"enum": [
|
|
722
|
+
"prohibited",
|
|
723
|
+
"allowed"
|
|
724
|
+
]
|
|
725
|
+
},
|
|
726
|
+
{
|
|
727
|
+
"function": true
|
|
728
|
+
}
|
|
729
|
+
]
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
},
|
|
695
733
|
contentCategory: {
|
|
696
734
|
anyOf: [
|
|
697
735
|
{
|
|
@@ -992,6 +1030,7 @@ const MetaCopyableProperty = [
|
|
|
992
1030
|
"formAssociated",
|
|
993
1031
|
"labelable",
|
|
994
1032
|
"attributes",
|
|
1033
|
+
"aria",
|
|
995
1034
|
"permittedContent",
|
|
996
1035
|
"permittedDescendants",
|
|
997
1036
|
"permittedOrder",
|
|
@@ -1052,7 +1091,27 @@ function migrateAttributes(src) {
|
|
|
1052
1091
|
});
|
|
1053
1092
|
return Object.fromEntries(entries);
|
|
1054
1093
|
}
|
|
1094
|
+
function normalizeAriaImplicitRole(value) {
|
|
1095
|
+
if (!value) {
|
|
1096
|
+
return () => null;
|
|
1097
|
+
}
|
|
1098
|
+
if (typeof value === "string") {
|
|
1099
|
+
return () => value;
|
|
1100
|
+
}
|
|
1101
|
+
return value;
|
|
1102
|
+
}
|
|
1103
|
+
function normalizeAriaNaming(value) {
|
|
1104
|
+
if (!value) {
|
|
1105
|
+
return () => "allowed";
|
|
1106
|
+
}
|
|
1107
|
+
if (typeof value === "string") {
|
|
1108
|
+
return () => value;
|
|
1109
|
+
}
|
|
1110
|
+
return value;
|
|
1111
|
+
}
|
|
1055
1112
|
function migrateElement(src) {
|
|
1113
|
+
var _a, _b;
|
|
1114
|
+
const implicitRole = normalizeAriaImplicitRole(src.implicitRole ?? ((_a = src.aria) == null ? void 0 : _a.implicitRole));
|
|
1056
1115
|
const result = {
|
|
1057
1116
|
...src,
|
|
1058
1117
|
...{
|
|
@@ -1061,7 +1120,11 @@ function migrateElement(src) {
|
|
|
1061
1120
|
attributes: migrateAttributes(src),
|
|
1062
1121
|
textContent: src.textContent,
|
|
1063
1122
|
focusable: src.focusable ?? false,
|
|
1064
|
-
implicitRole
|
|
1123
|
+
implicitRole,
|
|
1124
|
+
aria: {
|
|
1125
|
+
implicitRole,
|
|
1126
|
+
naming: normalizeAriaNaming((_b = src.aria) == null ? void 0 : _b.naming)
|
|
1127
|
+
}
|
|
1065
1128
|
};
|
|
1066
1129
|
delete result.deprecatedAttributes;
|
|
1067
1130
|
delete result.requiredAttributes;
|
|
@@ -1900,11 +1963,82 @@ function factory$1(name, context) {
|
|
|
1900
1963
|
}
|
|
1901
1964
|
}
|
|
1902
1965
|
|
|
1966
|
+
const escapedCodepoints = ["9", "a", "d"];
|
|
1967
|
+
function* splitSelectorElements(selector) {
|
|
1968
|
+
let begin = 0;
|
|
1969
|
+
let end = 0;
|
|
1970
|
+
function initialState(ch, p) {
|
|
1971
|
+
if (ch === "\\") {
|
|
1972
|
+
return 1 /* ESCAPED */;
|
|
1973
|
+
}
|
|
1974
|
+
if (ch === " ") {
|
|
1975
|
+
end = p;
|
|
1976
|
+
return 2 /* WHITESPACE */;
|
|
1977
|
+
}
|
|
1978
|
+
return 0 /* INITIAL */;
|
|
1979
|
+
}
|
|
1980
|
+
function escapedState(ch) {
|
|
1981
|
+
if (escapedCodepoints.includes(ch)) {
|
|
1982
|
+
return 1 /* ESCAPED */;
|
|
1983
|
+
}
|
|
1984
|
+
return 0 /* INITIAL */;
|
|
1985
|
+
}
|
|
1986
|
+
function* whitespaceState(ch, p) {
|
|
1987
|
+
if (ch === " ") {
|
|
1988
|
+
return 2 /* WHITESPACE */;
|
|
1989
|
+
}
|
|
1990
|
+
yield selector.slice(begin, end);
|
|
1991
|
+
begin = p;
|
|
1992
|
+
end = p;
|
|
1993
|
+
return 0 /* INITIAL */;
|
|
1994
|
+
}
|
|
1995
|
+
let state = 0 /* INITIAL */;
|
|
1996
|
+
for (let p = 0; p < selector.length; p++) {
|
|
1997
|
+
const ch = selector[p];
|
|
1998
|
+
switch (state) {
|
|
1999
|
+
case 0 /* INITIAL */:
|
|
2000
|
+
state = initialState(ch, p);
|
|
2001
|
+
break;
|
|
2002
|
+
case 1 /* ESCAPED */:
|
|
2003
|
+
state = escapedState(ch);
|
|
2004
|
+
break;
|
|
2005
|
+
case 2 /* WHITESPACE */:
|
|
2006
|
+
state = yield* whitespaceState(ch, p);
|
|
2007
|
+
break;
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
if (begin !== selector.length) {
|
|
2011
|
+
yield selector.slice(begin);
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
|
|
1903
2015
|
function stripslashes(value) {
|
|
1904
2016
|
return value.replace(/\\(.)/g, "$1");
|
|
1905
2017
|
}
|
|
2018
|
+
function unescapeCodepoint(value) {
|
|
2019
|
+
const replacement = {
|
|
2020
|
+
"\\9 ": " ",
|
|
2021
|
+
"\\a ": "\n",
|
|
2022
|
+
"\\d ": "\r"
|
|
2023
|
+
};
|
|
2024
|
+
return value.replace(
|
|
2025
|
+
/(\\[\u0039\u0061\u0064] )/g,
|
|
2026
|
+
(_, codepoint) => replacement[codepoint]
|
|
2027
|
+
);
|
|
2028
|
+
}
|
|
1906
2029
|
function escapeSelectorComponent(text) {
|
|
1907
|
-
|
|
2030
|
+
const codepoints = {
|
|
2031
|
+
" ": "\\9 ",
|
|
2032
|
+
"\n": "\\a ",
|
|
2033
|
+
"\r": "\\d "
|
|
2034
|
+
};
|
|
2035
|
+
return text.toString().replace(/([\t\n\r]|[^a-z0-9_-])/gi, (_, ch) => {
|
|
2036
|
+
if (codepoints[ch]) {
|
|
2037
|
+
return codepoints[ch];
|
|
2038
|
+
} else {
|
|
2039
|
+
return `\\${ch}`;
|
|
2040
|
+
}
|
|
2041
|
+
});
|
|
1908
2042
|
}
|
|
1909
2043
|
function generateIdSelector(id) {
|
|
1910
2044
|
const escaped = escapeSelectorComponent(id);
|
|
@@ -2019,7 +2153,10 @@ class PseudoClassMatcher extends Matcher {
|
|
|
2019
2153
|
}
|
|
2020
2154
|
class Pattern {
|
|
2021
2155
|
constructor(pattern) {
|
|
2022
|
-
const match = pattern.match(/^([~+\->]?)((?:[*]|[^.#[:]+)?)(
|
|
2156
|
+
const match = pattern.match(/^([~+\->]?)((?:[*]|[^.#[:]+)?)([^]*)$/);
|
|
2157
|
+
if (!match) {
|
|
2158
|
+
throw new Error(`Failed to create selector pattern from "${pattern}"`);
|
|
2159
|
+
}
|
|
2023
2160
|
match.shift();
|
|
2024
2161
|
this.selector = pattern;
|
|
2025
2162
|
this.combinator = parseCombinator(match.shift(), pattern);
|
|
@@ -2074,13 +2211,8 @@ class Selector {
|
|
|
2074
2211
|
}
|
|
2075
2212
|
static parse(selector) {
|
|
2076
2213
|
selector = selector.replace(/([+~>]) /g, "$1");
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
return Array.from(selector.matchAll(delimiter), (match) => {
|
|
2080
|
-
const end = match.index + 1;
|
|
2081
|
-
const part = selector.slice(begin, end);
|
|
2082
|
-
begin = end + 1;
|
|
2083
|
-
return new Pattern(part);
|
|
2214
|
+
return Array.from(splitSelectorElements(selector), (element) => {
|
|
2215
|
+
return new Pattern(unescapeCodepoint(element));
|
|
2084
2216
|
});
|
|
2085
2217
|
}
|
|
2086
2218
|
static findCandidates(root, pattern) {
|
|
@@ -2411,7 +2543,8 @@ class HtmlElement extends DOMNode {
|
|
|
2411
2543
|
return this.cacheSet(ROLE, role.value);
|
|
2412
2544
|
}
|
|
2413
2545
|
if (this.metaElement) {
|
|
2414
|
-
const
|
|
2546
|
+
const { aria } = this.metaElement;
|
|
2547
|
+
const implicitRole = aria.implicitRole(this._adapter);
|
|
2415
2548
|
return this.cacheSet(ROLE, implicitRole);
|
|
2416
2549
|
}
|
|
2417
2550
|
return this.cacheSet(ROLE, null);
|
|
@@ -3153,6 +3286,48 @@ function interpolate(text, data) {
|
|
|
3153
3286
|
});
|
|
3154
3287
|
}
|
|
3155
3288
|
|
|
3289
|
+
const cacheKey = Symbol("aria-naming");
|
|
3290
|
+
const defaultValue = "allowed";
|
|
3291
|
+
const prohibitedRoles = [
|
|
3292
|
+
"caption",
|
|
3293
|
+
"code",
|
|
3294
|
+
"deletion",
|
|
3295
|
+
"emphasis",
|
|
3296
|
+
"generic",
|
|
3297
|
+
"insertion",
|
|
3298
|
+
"paragraph",
|
|
3299
|
+
"presentation",
|
|
3300
|
+
"strong",
|
|
3301
|
+
"subscript",
|
|
3302
|
+
"superscript"
|
|
3303
|
+
];
|
|
3304
|
+
function byRole(role) {
|
|
3305
|
+
return prohibitedRoles.includes(role) ? "prohibited" : "allowed";
|
|
3306
|
+
}
|
|
3307
|
+
function byMeta(element, meta) {
|
|
3308
|
+
return meta.aria.naming(element._adapter);
|
|
3309
|
+
}
|
|
3310
|
+
function ariaNaming(element) {
|
|
3311
|
+
var _a;
|
|
3312
|
+
const cached = element.cacheGet(cacheKey);
|
|
3313
|
+
if (cached) {
|
|
3314
|
+
return cached;
|
|
3315
|
+
}
|
|
3316
|
+
const role = (_a = element.getAttribute("role")) == null ? void 0 : _a.value;
|
|
3317
|
+
if (role) {
|
|
3318
|
+
if (role instanceof DynamicValue) {
|
|
3319
|
+
return element.cacheSet(cacheKey, defaultValue);
|
|
3320
|
+
} else {
|
|
3321
|
+
return element.cacheSet(cacheKey, byRole(role));
|
|
3322
|
+
}
|
|
3323
|
+
}
|
|
3324
|
+
const meta = element.meta;
|
|
3325
|
+
if (!meta) {
|
|
3326
|
+
return element.cacheSet(cacheKey, defaultValue);
|
|
3327
|
+
}
|
|
3328
|
+
return element.cacheSet(cacheKey, byMeta(element, meta));
|
|
3329
|
+
}
|
|
3330
|
+
|
|
3156
3331
|
const patternCache = /* @__PURE__ */ new Map();
|
|
3157
3332
|
function compileStringPattern(pattern) {
|
|
3158
3333
|
const regexp = pattern.replace(/[*]+/g, ".+");
|
|
@@ -3671,7 +3846,7 @@ class Rule {
|
|
|
3671
3846
|
}
|
|
3672
3847
|
}
|
|
3673
3848
|
|
|
3674
|
-
const defaults$
|
|
3849
|
+
const defaults$v = {
|
|
3675
3850
|
allowExternal: true,
|
|
3676
3851
|
allowRelative: true,
|
|
3677
3852
|
allowAbsolute: true,
|
|
@@ -3712,7 +3887,7 @@ function matchList(value, list) {
|
|
|
3712
3887
|
}
|
|
3713
3888
|
class AllowedLinks extends Rule {
|
|
3714
3889
|
constructor(options) {
|
|
3715
|
-
super({ ...defaults$
|
|
3890
|
+
super({ ...defaults$v, ...options });
|
|
3716
3891
|
this.allowExternal = parseAllow(this.options.allowExternal);
|
|
3717
3892
|
this.allowRelative = parseAllow(this.options.allowRelative);
|
|
3718
3893
|
this.allowAbsolute = parseAllow(this.options.allowAbsolute);
|
|
@@ -3876,7 +4051,7 @@ class AllowedLinks extends Rule {
|
|
|
3876
4051
|
}
|
|
3877
4052
|
}
|
|
3878
4053
|
|
|
3879
|
-
const defaults$
|
|
4054
|
+
const defaults$u = {
|
|
3880
4055
|
accessible: true
|
|
3881
4056
|
};
|
|
3882
4057
|
function findByTarget(target, siblings) {
|
|
@@ -3906,7 +4081,7 @@ function getDescription$1(context) {
|
|
|
3906
4081
|
}
|
|
3907
4082
|
class AreaAlt extends Rule {
|
|
3908
4083
|
constructor(options) {
|
|
3909
|
-
super({ ...defaults$
|
|
4084
|
+
super({ ...defaults$u, ...options });
|
|
3910
4085
|
}
|
|
3911
4086
|
static schema() {
|
|
3912
4087
|
return {
|
|
@@ -3985,6 +4160,9 @@ class AriaHiddenBody extends Rule {
|
|
|
3985
4160
|
}
|
|
3986
4161
|
}
|
|
3987
4162
|
|
|
4163
|
+
const defaults$t = {
|
|
4164
|
+
allowAnyNamable: false
|
|
4165
|
+
};
|
|
3988
4166
|
const whitelisted = [
|
|
3989
4167
|
"main",
|
|
3990
4168
|
"nav",
|
|
@@ -4023,6 +4201,9 @@ function isValidUsage(target, meta) {
|
|
|
4023
4201
|
return false;
|
|
4024
4202
|
}
|
|
4025
4203
|
class AriaLabelMisuse extends Rule {
|
|
4204
|
+
constructor(options) {
|
|
4205
|
+
super({ ...defaults$t, ...options });
|
|
4206
|
+
}
|
|
4026
4207
|
documentation() {
|
|
4027
4208
|
const valid = [
|
|
4028
4209
|
"Interactive elements",
|
|
@@ -4065,6 +4246,9 @@ ${lines}`,
|
|
|
4065
4246
|
if (isValidUsage(target, meta)) {
|
|
4066
4247
|
return;
|
|
4067
4248
|
}
|
|
4249
|
+
if (this.options.allowAnyNamable && ariaNaming(target) === "allowed") {
|
|
4250
|
+
return;
|
|
4251
|
+
}
|
|
4068
4252
|
this.report(target, `"aria-label" cannot be used on this element`, attr.keyLocation);
|
|
4069
4253
|
}
|
|
4070
4254
|
}
|
|
@@ -7562,7 +7746,7 @@ class NoRedundantRole extends Rule {
|
|
|
7562
7746
|
if (!meta) {
|
|
7563
7747
|
return;
|
|
7564
7748
|
}
|
|
7565
|
-
const implicitRole = meta.implicitRole(target._adapter);
|
|
7749
|
+
const implicitRole = meta.aria.implicitRole(target._adapter);
|
|
7566
7750
|
if (!implicitRole) {
|
|
7567
7751
|
return;
|
|
7568
7752
|
}
|
|
@@ -9344,7 +9528,7 @@ const config$4 = {
|
|
|
9344
9528
|
rules: {
|
|
9345
9529
|
"area-alt": ["error", { accessible: true }],
|
|
9346
9530
|
"aria-hidden-body": "error",
|
|
9347
|
-
"aria-label-misuse": "error",
|
|
9531
|
+
"aria-label-misuse": ["error", { allowAnyNamable: false }],
|
|
9348
9532
|
"deprecated-rule": "warn",
|
|
9349
9533
|
"empty-heading": "error",
|
|
9350
9534
|
"empty-title": "error",
|
|
@@ -9396,7 +9580,7 @@ const config$1 = {
|
|
|
9396
9580
|
rules: {
|
|
9397
9581
|
"area-alt": ["error", { accessible: true }],
|
|
9398
9582
|
"aria-hidden-body": "error",
|
|
9399
|
-
"aria-label-misuse": "error",
|
|
9583
|
+
"aria-label-misuse": ["error", { allowAnyNamable: false }],
|
|
9400
9584
|
"attr-case": "error",
|
|
9401
9585
|
"attr-delimiter": "error",
|
|
9402
9586
|
"attr-quotes": "error",
|
|
@@ -9477,6 +9661,7 @@ var recommended = config$1;
|
|
|
9477
9661
|
const config = {
|
|
9478
9662
|
rules: {
|
|
9479
9663
|
"area-alt": ["error", { accessible: false }],
|
|
9664
|
+
"aria-label-misuse": ["error", { allowAnyNamable: true }],
|
|
9480
9665
|
"attr-spacing": "error",
|
|
9481
9666
|
"attribute-allowed-values": "error",
|
|
9482
9667
|
"attribute-misuse": "error",
|
|
@@ -11729,7 +11914,7 @@ class HtmlValidate {
|
|
|
11729
11914
|
}
|
|
11730
11915
|
|
|
11731
11916
|
const name = "html-validate";
|
|
11732
|
-
const version = "8.
|
|
11917
|
+
const version = "8.11.1";
|
|
11733
11918
|
const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
|
|
11734
11919
|
|
|
11735
11920
|
function definePlugin(plugin) {
|
|
@@ -12636,6 +12821,7 @@ exports.TextNode = TextNode;
|
|
|
12636
12821
|
exports.UserError = UserError;
|
|
12637
12822
|
exports.Validator = Validator;
|
|
12638
12823
|
exports.WrappedError = WrappedError;
|
|
12824
|
+
exports.ariaNaming = ariaNaming;
|
|
12639
12825
|
exports.bugs = bugs;
|
|
12640
12826
|
exports.classifyNodeText = classifyNodeText;
|
|
12641
12827
|
exports.codeframe = codeframe;
|