abledom 0.6.0 → 0.6.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/esm/index.js +487 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.cts +47 -1
- package/dist/index.d.ts +47 -1
- package/dist/index.js +490 -0
- package/dist/index.js.map +1 -1
- package/dist/ts3.9/index.d.ts +41 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -231,6 +231,52 @@ declare class CustomNotifyRule extends ValidationRule {
|
|
|
231
231
|
customNotify(message: string, element?: HTMLElement): void;
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
/*!
|
|
235
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
236
|
+
* Licensed under the MIT License.
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
declare class RequiredParentRule extends ValidationRule {
|
|
240
|
+
type: ValidationRuleType;
|
|
241
|
+
name: string;
|
|
242
|
+
anchored: boolean;
|
|
243
|
+
private parentRequirements;
|
|
244
|
+
accept(element: HTMLElement): boolean;
|
|
245
|
+
validate(element: HTMLElement): ValidationResult | null;
|
|
246
|
+
private hasValidParent;
|
|
247
|
+
private createIssue;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/*!
|
|
251
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
252
|
+
* Licensed under the MIT License.
|
|
253
|
+
*/
|
|
254
|
+
|
|
255
|
+
declare class NestedInteractiveElementRule extends ValidationRule {
|
|
256
|
+
type: ValidationRuleType;
|
|
257
|
+
name: string;
|
|
258
|
+
anchored: boolean;
|
|
259
|
+
private _isAriaHidden;
|
|
260
|
+
private _isInteractive;
|
|
261
|
+
private _findNestedInteractive;
|
|
262
|
+
accept(element: HTMLElement): boolean;
|
|
263
|
+
validate(element: HTMLElement): ValidationResult | null;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/*!
|
|
267
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
268
|
+
* Licensed under the MIT License.
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
declare class TabIndexRule extends ValidationRule {
|
|
272
|
+
type: ValidationRuleType;
|
|
273
|
+
name: string;
|
|
274
|
+
anchored: boolean;
|
|
275
|
+
accept(element: HTMLElement): boolean;
|
|
276
|
+
private isInteractiveElement;
|
|
277
|
+
validate(element: HTMLElement): ValidationResult | null;
|
|
278
|
+
}
|
|
279
|
+
|
|
234
280
|
interface HTMLElementAttributes {
|
|
235
281
|
readonly [name: string]: string;
|
|
236
282
|
}
|
|
@@ -240,4 +286,4 @@ declare function matchesSelector(element: HTMLElement, selector: string): boolea
|
|
|
240
286
|
declare function isDisplayNone(element: HTMLElement): boolean;
|
|
241
287
|
declare function isElementVisible(element: HTMLElement): boolean;
|
|
242
288
|
|
|
243
|
-
export { AbleDOM, type AbleDOMProps, AtomicRule, BadFocusRule, type BlurIssue, ContrastRule, CustomNotifyRule, ExistingIdRule, FindElementRule, FocusLostRule, FocusableElementLabelRule, type ValidationIssue, type ValidationResult, ValidationRule, ValidationRuleType, hasAccessibilityAttribute, isAccessibilityAffectingElement, isDisplayNone, isElementVisible, matchesSelector };
|
|
289
|
+
export { AbleDOM, type AbleDOMProps, AtomicRule, BadFocusRule, type BlurIssue, ContrastRule, CustomNotifyRule, ExistingIdRule, FindElementRule, FocusLostRule, FocusableElementLabelRule, NestedInteractiveElementRule, RequiredParentRule, TabIndexRule, type ValidationIssue, type ValidationResult, ValidationRule, ValidationRuleType, hasAccessibilityAttribute, isAccessibilityAffectingElement, isDisplayNone, isElementVisible, matchesSelector };
|
package/dist/index.d.ts
CHANGED
|
@@ -231,6 +231,52 @@ declare class CustomNotifyRule extends ValidationRule {
|
|
|
231
231
|
customNotify(message: string, element?: HTMLElement): void;
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
/*!
|
|
235
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
236
|
+
* Licensed under the MIT License.
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
declare class RequiredParentRule extends ValidationRule {
|
|
240
|
+
type: ValidationRuleType;
|
|
241
|
+
name: string;
|
|
242
|
+
anchored: boolean;
|
|
243
|
+
private parentRequirements;
|
|
244
|
+
accept(element: HTMLElement): boolean;
|
|
245
|
+
validate(element: HTMLElement): ValidationResult | null;
|
|
246
|
+
private hasValidParent;
|
|
247
|
+
private createIssue;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/*!
|
|
251
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
252
|
+
* Licensed under the MIT License.
|
|
253
|
+
*/
|
|
254
|
+
|
|
255
|
+
declare class NestedInteractiveElementRule extends ValidationRule {
|
|
256
|
+
type: ValidationRuleType;
|
|
257
|
+
name: string;
|
|
258
|
+
anchored: boolean;
|
|
259
|
+
private _isAriaHidden;
|
|
260
|
+
private _isInteractive;
|
|
261
|
+
private _findNestedInteractive;
|
|
262
|
+
accept(element: HTMLElement): boolean;
|
|
263
|
+
validate(element: HTMLElement): ValidationResult | null;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/*!
|
|
267
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
268
|
+
* Licensed under the MIT License.
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
declare class TabIndexRule extends ValidationRule {
|
|
272
|
+
type: ValidationRuleType;
|
|
273
|
+
name: string;
|
|
274
|
+
anchored: boolean;
|
|
275
|
+
accept(element: HTMLElement): boolean;
|
|
276
|
+
private isInteractiveElement;
|
|
277
|
+
validate(element: HTMLElement): ValidationResult | null;
|
|
278
|
+
}
|
|
279
|
+
|
|
234
280
|
interface HTMLElementAttributes {
|
|
235
281
|
readonly [name: string]: string;
|
|
236
282
|
}
|
|
@@ -240,4 +286,4 @@ declare function matchesSelector(element: HTMLElement, selector: string): boolea
|
|
|
240
286
|
declare function isDisplayNone(element: HTMLElement): boolean;
|
|
241
287
|
declare function isElementVisible(element: HTMLElement): boolean;
|
|
242
288
|
|
|
243
|
-
export { AbleDOM, type AbleDOMProps, AtomicRule, BadFocusRule, type BlurIssue, ContrastRule, CustomNotifyRule, ExistingIdRule, FindElementRule, FocusLostRule, FocusableElementLabelRule, type ValidationIssue, type ValidationResult, ValidationRule, ValidationRuleType, hasAccessibilityAttribute, isAccessibilityAffectingElement, isDisplayNone, isElementVisible, matchesSelector };
|
|
289
|
+
export { AbleDOM, type AbleDOMProps, AtomicRule, BadFocusRule, type BlurIssue, ContrastRule, CustomNotifyRule, ExistingIdRule, FindElementRule, FocusLostRule, FocusableElementLabelRule, NestedInteractiveElementRule, RequiredParentRule, TabIndexRule, type ValidationIssue, type ValidationResult, ValidationRule, ValidationRuleType, hasAccessibilityAttribute, isAccessibilityAffectingElement, isDisplayNone, isElementVisible, matchesSelector };
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,9 @@ __export(index_exports, {
|
|
|
31
31
|
FindElementRule: () => FindElementRule,
|
|
32
32
|
FocusLostRule: () => FocusLostRule,
|
|
33
33
|
FocusableElementLabelRule: () => FocusableElementLabelRule,
|
|
34
|
+
NestedInteractiveElementRule: () => NestedInteractiveElementRule,
|
|
35
|
+
RequiredParentRule: () => RequiredParentRule,
|
|
36
|
+
TabIndexRule: () => TabIndexRule,
|
|
34
37
|
ValidationRule: () => ValidationRule,
|
|
35
38
|
ValidationRuleType: () => ValidationRuleType,
|
|
36
39
|
hasAccessibilityAttribute: () => hasAccessibilityAttribute,
|
|
@@ -899,10 +902,17 @@ var AccessibilityAffectingElements = {
|
|
|
899
902
|
aside: true,
|
|
900
903
|
body: true,
|
|
901
904
|
button: true,
|
|
905
|
+
caption: true,
|
|
906
|
+
col: true,
|
|
907
|
+
colgroup: true,
|
|
902
908
|
datalist: true,
|
|
909
|
+
dd: true,
|
|
903
910
|
details: true,
|
|
904
911
|
dialog: true,
|
|
905
912
|
dl: true,
|
|
913
|
+
dt: true,
|
|
914
|
+
figcaption: true,
|
|
915
|
+
figure: true,
|
|
906
916
|
form: true,
|
|
907
917
|
h1: true,
|
|
908
918
|
h2: true,
|
|
@@ -914,6 +924,7 @@ var AccessibilityAffectingElements = {
|
|
|
914
924
|
iframe: true,
|
|
915
925
|
img: true,
|
|
916
926
|
input: true,
|
|
927
|
+
legend: true,
|
|
917
928
|
li: true,
|
|
918
929
|
link: true,
|
|
919
930
|
main: true,
|
|
@@ -923,15 +934,22 @@ var AccessibilityAffectingElements = {
|
|
|
923
934
|
nav: true,
|
|
924
935
|
object: true,
|
|
925
936
|
ol: true,
|
|
937
|
+
optgroup: true,
|
|
926
938
|
option: true,
|
|
927
939
|
progress: true,
|
|
928
940
|
section: true,
|
|
929
941
|
select: true,
|
|
942
|
+
source: true,
|
|
943
|
+
summary: true,
|
|
944
|
+
table: true,
|
|
930
945
|
tbody: true,
|
|
946
|
+
td: true,
|
|
931
947
|
textarea: true,
|
|
932
948
|
tfoot: true,
|
|
933
949
|
th: true,
|
|
934
950
|
thead: true,
|
|
951
|
+
tr: true,
|
|
952
|
+
track: true,
|
|
935
953
|
ul: true
|
|
936
954
|
};
|
|
937
955
|
var AccessibilityAttributes = {
|
|
@@ -2101,6 +2119,475 @@ var CustomNotifyRule = class extends ValidationRule {
|
|
|
2101
2119
|
});
|
|
2102
2120
|
}
|
|
2103
2121
|
};
|
|
2122
|
+
|
|
2123
|
+
// src/rules/requiredparent.ts
|
|
2124
|
+
var RequiredParentRule = class extends ValidationRule {
|
|
2125
|
+
constructor() {
|
|
2126
|
+
super(...arguments);
|
|
2127
|
+
__publicField(this, "type", 1 /* Error */);
|
|
2128
|
+
__publicField(this, "name", "aria-required-parent");
|
|
2129
|
+
__publicField(this, "anchored", true);
|
|
2130
|
+
__publicField(this, "parentRequirements", /* @__PURE__ */ new Map([
|
|
2131
|
+
[
|
|
2132
|
+
"LI",
|
|
2133
|
+
{
|
|
2134
|
+
allowedParents: ["UL", "OL"],
|
|
2135
|
+
allowedParentRoles: ["list"]
|
|
2136
|
+
}
|
|
2137
|
+
],
|
|
2138
|
+
[
|
|
2139
|
+
"DT",
|
|
2140
|
+
{
|
|
2141
|
+
allowedParents: ["DL"],
|
|
2142
|
+
allowIntermediateWrappers: true,
|
|
2143
|
+
allowedWrappers: ["DIV"]
|
|
2144
|
+
}
|
|
2145
|
+
],
|
|
2146
|
+
[
|
|
2147
|
+
"DD",
|
|
2148
|
+
{
|
|
2149
|
+
allowedParents: ["DL"],
|
|
2150
|
+
allowIntermediateWrappers: true,
|
|
2151
|
+
allowedWrappers: ["DIV"]
|
|
2152
|
+
}
|
|
2153
|
+
],
|
|
2154
|
+
[
|
|
2155
|
+
"TR",
|
|
2156
|
+
{
|
|
2157
|
+
allowedParents: ["TABLE", "THEAD", "TBODY", "TFOOT"],
|
|
2158
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2159
|
+
}
|
|
2160
|
+
],
|
|
2161
|
+
[
|
|
2162
|
+
"TH",
|
|
2163
|
+
{
|
|
2164
|
+
allowedParents: ["TR"],
|
|
2165
|
+
allowedParentRoles: ["row"]
|
|
2166
|
+
}
|
|
2167
|
+
],
|
|
2168
|
+
[
|
|
2169
|
+
"TD",
|
|
2170
|
+
{
|
|
2171
|
+
allowedParents: ["TR"],
|
|
2172
|
+
allowedParentRoles: ["row"]
|
|
2173
|
+
}
|
|
2174
|
+
],
|
|
2175
|
+
[
|
|
2176
|
+
"THEAD",
|
|
2177
|
+
{
|
|
2178
|
+
allowedParents: ["TABLE"],
|
|
2179
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2180
|
+
}
|
|
2181
|
+
],
|
|
2182
|
+
[
|
|
2183
|
+
"TBODY",
|
|
2184
|
+
{
|
|
2185
|
+
allowedParents: ["TABLE"],
|
|
2186
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2187
|
+
}
|
|
2188
|
+
],
|
|
2189
|
+
[
|
|
2190
|
+
"TFOOT",
|
|
2191
|
+
{
|
|
2192
|
+
allowedParents: ["TABLE"],
|
|
2193
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2194
|
+
}
|
|
2195
|
+
],
|
|
2196
|
+
[
|
|
2197
|
+
"CAPTION",
|
|
2198
|
+
{
|
|
2199
|
+
allowedParents: ["TABLE"]
|
|
2200
|
+
}
|
|
2201
|
+
],
|
|
2202
|
+
[
|
|
2203
|
+
"COLGROUP",
|
|
2204
|
+
{
|
|
2205
|
+
allowedParents: ["TABLE"]
|
|
2206
|
+
}
|
|
2207
|
+
],
|
|
2208
|
+
[
|
|
2209
|
+
"COL",
|
|
2210
|
+
{
|
|
2211
|
+
allowedParents: ["COLGROUP"]
|
|
2212
|
+
}
|
|
2213
|
+
],
|
|
2214
|
+
[
|
|
2215
|
+
"FIGCAPTION",
|
|
2216
|
+
{
|
|
2217
|
+
allowedParents: ["FIGURE"]
|
|
2218
|
+
}
|
|
2219
|
+
],
|
|
2220
|
+
[
|
|
2221
|
+
"OPTION",
|
|
2222
|
+
{
|
|
2223
|
+
allowedParents: ["SELECT", "OPTGROUP", "DATALIST"]
|
|
2224
|
+
}
|
|
2225
|
+
],
|
|
2226
|
+
[
|
|
2227
|
+
"OPTGROUP",
|
|
2228
|
+
{
|
|
2229
|
+
allowedParents: ["SELECT"]
|
|
2230
|
+
}
|
|
2231
|
+
],
|
|
2232
|
+
[
|
|
2233
|
+
"LEGEND",
|
|
2234
|
+
{
|
|
2235
|
+
allowedParents: ["FIELDSET"]
|
|
2236
|
+
}
|
|
2237
|
+
],
|
|
2238
|
+
[
|
|
2239
|
+
"SUMMARY",
|
|
2240
|
+
{
|
|
2241
|
+
allowedParents: ["DETAILS"]
|
|
2242
|
+
}
|
|
2243
|
+
],
|
|
2244
|
+
[
|
|
2245
|
+
"SOURCE",
|
|
2246
|
+
{
|
|
2247
|
+
allowedParents: ["AUDIO", "VIDEO", "PICTURE"]
|
|
2248
|
+
}
|
|
2249
|
+
],
|
|
2250
|
+
[
|
|
2251
|
+
"TRACK",
|
|
2252
|
+
{
|
|
2253
|
+
allowedParents: ["AUDIO", "VIDEO"]
|
|
2254
|
+
}
|
|
2255
|
+
],
|
|
2256
|
+
[
|
|
2257
|
+
"role=menuitem",
|
|
2258
|
+
{
|
|
2259
|
+
allowedParentRoles: ["menu", "menubar", "group"]
|
|
2260
|
+
}
|
|
2261
|
+
],
|
|
2262
|
+
[
|
|
2263
|
+
"role=menuitemcheckbox",
|
|
2264
|
+
{
|
|
2265
|
+
allowedParentRoles: ["menu", "menubar", "group"]
|
|
2266
|
+
}
|
|
2267
|
+
],
|
|
2268
|
+
[
|
|
2269
|
+
"role=menuitemradio",
|
|
2270
|
+
{
|
|
2271
|
+
allowedParentRoles: ["menu", "menubar", "group"]
|
|
2272
|
+
}
|
|
2273
|
+
],
|
|
2274
|
+
[
|
|
2275
|
+
"role=listitem",
|
|
2276
|
+
{
|
|
2277
|
+
allowedParentRoles: ["list", "group"]
|
|
2278
|
+
}
|
|
2279
|
+
],
|
|
2280
|
+
[
|
|
2281
|
+
"role=treeitem",
|
|
2282
|
+
{
|
|
2283
|
+
allowedParentRoles: ["tree", "group"]
|
|
2284
|
+
}
|
|
2285
|
+
],
|
|
2286
|
+
[
|
|
2287
|
+
"role=tab",
|
|
2288
|
+
{
|
|
2289
|
+
allowedParentRoles: ["tablist"]
|
|
2290
|
+
}
|
|
2291
|
+
],
|
|
2292
|
+
[
|
|
2293
|
+
"role=row",
|
|
2294
|
+
{
|
|
2295
|
+
allowedParentRoles: ["table", "grid", "treegrid", "rowgroup"]
|
|
2296
|
+
}
|
|
2297
|
+
],
|
|
2298
|
+
[
|
|
2299
|
+
"role=cell",
|
|
2300
|
+
{
|
|
2301
|
+
allowedParentRoles: ["row"]
|
|
2302
|
+
}
|
|
2303
|
+
],
|
|
2304
|
+
[
|
|
2305
|
+
"role=gridcell",
|
|
2306
|
+
{
|
|
2307
|
+
allowedParentRoles: ["row"]
|
|
2308
|
+
}
|
|
2309
|
+
],
|
|
2310
|
+
[
|
|
2311
|
+
"role=columnheader",
|
|
2312
|
+
{
|
|
2313
|
+
allowedParentRoles: ["row"]
|
|
2314
|
+
}
|
|
2315
|
+
],
|
|
2316
|
+
[
|
|
2317
|
+
"role=rowheader",
|
|
2318
|
+
{
|
|
2319
|
+
allowedParentRoles: ["row"]
|
|
2320
|
+
}
|
|
2321
|
+
],
|
|
2322
|
+
[
|
|
2323
|
+
"role=rowgroup",
|
|
2324
|
+
{
|
|
2325
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2326
|
+
}
|
|
2327
|
+
],
|
|
2328
|
+
[
|
|
2329
|
+
"role=option",
|
|
2330
|
+
{
|
|
2331
|
+
allowedParentRoles: ["listbox", "group"]
|
|
2332
|
+
}
|
|
2333
|
+
]
|
|
2334
|
+
]));
|
|
2335
|
+
}
|
|
2336
|
+
accept(element) {
|
|
2337
|
+
const tagName = element.tagName;
|
|
2338
|
+
const role = element.getAttribute("role");
|
|
2339
|
+
if (this.parentRequirements.has(tagName)) {
|
|
2340
|
+
return true;
|
|
2341
|
+
}
|
|
2342
|
+
if (role && this.parentRequirements.has(`role=${role}`)) {
|
|
2343
|
+
return true;
|
|
2344
|
+
}
|
|
2345
|
+
return false;
|
|
2346
|
+
}
|
|
2347
|
+
validate(element) {
|
|
2348
|
+
const tagName = element.tagName;
|
|
2349
|
+
const role = element.getAttribute("role");
|
|
2350
|
+
let requirement;
|
|
2351
|
+
let identifier = "";
|
|
2352
|
+
if (role && this.parentRequirements.has(`role=${role}`)) {
|
|
2353
|
+
requirement = this.parentRequirements.get(`role=${role}`);
|
|
2354
|
+
identifier = `role="${role}"`;
|
|
2355
|
+
} else if (this.parentRequirements.has(tagName)) {
|
|
2356
|
+
requirement = this.parentRequirements.get(tagName);
|
|
2357
|
+
identifier = `<${tagName.toLowerCase()}>`;
|
|
2358
|
+
}
|
|
2359
|
+
if (!requirement) {
|
|
2360
|
+
return null;
|
|
2361
|
+
}
|
|
2362
|
+
if (requirement.customValidator) {
|
|
2363
|
+
if (requirement.customValidator(element)) {
|
|
2364
|
+
return null;
|
|
2365
|
+
} else {
|
|
2366
|
+
return this.createIssue(element, identifier, requirement);
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
if (this.hasValidParent(element, requirement)) {
|
|
2370
|
+
return null;
|
|
2371
|
+
}
|
|
2372
|
+
return this.createIssue(element, identifier, requirement);
|
|
2373
|
+
}
|
|
2374
|
+
hasValidParent(element, requirement) {
|
|
2375
|
+
var _a, _b, _c;
|
|
2376
|
+
let parent = element.parentElement;
|
|
2377
|
+
let depth = 0;
|
|
2378
|
+
const maxDepth = requirement.allowIntermediateWrappers ? 2 : 1;
|
|
2379
|
+
while (parent && depth < maxDepth) {
|
|
2380
|
+
if ((_a = requirement.allowedParents) == null ? void 0 : _a.includes(parent.tagName)) {
|
|
2381
|
+
return true;
|
|
2382
|
+
}
|
|
2383
|
+
const parentRole = parent.getAttribute("role");
|
|
2384
|
+
if (parentRole && ((_b = requirement.allowedParentRoles) == null ? void 0 : _b.includes(parentRole))) {
|
|
2385
|
+
return true;
|
|
2386
|
+
}
|
|
2387
|
+
if (depth === 0 && !requirement.allowIntermediateWrappers) {
|
|
2388
|
+
break;
|
|
2389
|
+
}
|
|
2390
|
+
if (depth === 0 && requirement.allowIntermediateWrappers) {
|
|
2391
|
+
if (!((_c = requirement.allowedWrappers) == null ? void 0 : _c.includes(parent.tagName))) {
|
|
2392
|
+
break;
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
parent = parent.parentElement;
|
|
2396
|
+
depth++;
|
|
2397
|
+
}
|
|
2398
|
+
return false;
|
|
2399
|
+
}
|
|
2400
|
+
createIssue(element, identifier, requirement) {
|
|
2401
|
+
var _a, _b;
|
|
2402
|
+
const allowedParentsText = [
|
|
2403
|
+
...((_a = requirement.allowedParents) == null ? void 0 : _a.map((p) => `<${p.toLowerCase()}>`)) || [],
|
|
2404
|
+
...((_b = requirement.allowedParentRoles) == null ? void 0 : _b.map((r) => `role="${r}"`)) || []
|
|
2405
|
+
].join(", ");
|
|
2406
|
+
const message = `${identifier} must be contained by ${allowedParentsText}`;
|
|
2407
|
+
return {
|
|
2408
|
+
issue: {
|
|
2409
|
+
id: "aria-required-parent",
|
|
2410
|
+
message,
|
|
2411
|
+
element,
|
|
2412
|
+
help: "https://dequeuniversity.com/rules/axe/4.2/aria-required-parent"
|
|
2413
|
+
}
|
|
2414
|
+
};
|
|
2415
|
+
}
|
|
2416
|
+
};
|
|
2417
|
+
|
|
2418
|
+
// src/rules/nestedInteractive.ts
|
|
2419
|
+
var interactiveElementSelector = [
|
|
2420
|
+
"a[href]",
|
|
2421
|
+
"button",
|
|
2422
|
+
"input:not([type='hidden'])",
|
|
2423
|
+
"select",
|
|
2424
|
+
"textarea",
|
|
2425
|
+
"details",
|
|
2426
|
+
"audio[controls]",
|
|
2427
|
+
"video[controls]",
|
|
2428
|
+
"*[role='button']",
|
|
2429
|
+
"*[role='link']",
|
|
2430
|
+
"*[role='checkbox']",
|
|
2431
|
+
"*[role='radio']",
|
|
2432
|
+
"*[role='switch']",
|
|
2433
|
+
"*[role='tab']",
|
|
2434
|
+
"*[role='menuitem']",
|
|
2435
|
+
"*[role='menuitemcheckbox']",
|
|
2436
|
+
"*[role='menuitemradio']",
|
|
2437
|
+
"*[role='option']",
|
|
2438
|
+
"*[role='treeitem']"
|
|
2439
|
+
].join(", ");
|
|
2440
|
+
var NestedInteractiveElementRule = class extends ValidationRule {
|
|
2441
|
+
constructor() {
|
|
2442
|
+
super(...arguments);
|
|
2443
|
+
__publicField(this, "type", 1 /* Error */);
|
|
2444
|
+
__publicField(this, "name", "NestedInteractiveElementRule");
|
|
2445
|
+
__publicField(this, "anchored", true);
|
|
2446
|
+
}
|
|
2447
|
+
_isAriaHidden(element) {
|
|
2448
|
+
return element.ownerDocument.evaluate(
|
|
2449
|
+
`ancestor-or-self::*[@aria-hidden = 'true' or @hidden]`,
|
|
2450
|
+
element,
|
|
2451
|
+
null,
|
|
2452
|
+
XPathResult.BOOLEAN_TYPE,
|
|
2453
|
+
null
|
|
2454
|
+
).booleanValue;
|
|
2455
|
+
}
|
|
2456
|
+
_isInteractive(element) {
|
|
2457
|
+
return matchesSelector(element, interactiveElementSelector);
|
|
2458
|
+
}
|
|
2459
|
+
_findNestedInteractive(element) {
|
|
2460
|
+
const descendants = element.querySelectorAll(interactiveElementSelector);
|
|
2461
|
+
for (let i = 0; i < descendants.length; i++) {
|
|
2462
|
+
const descendant = descendants[i];
|
|
2463
|
+
if (this._isAriaHidden(descendant)) {
|
|
2464
|
+
continue;
|
|
2465
|
+
}
|
|
2466
|
+
return descendant;
|
|
2467
|
+
}
|
|
2468
|
+
return null;
|
|
2469
|
+
}
|
|
2470
|
+
accept(element) {
|
|
2471
|
+
return this._isInteractive(element);
|
|
2472
|
+
}
|
|
2473
|
+
validate(element) {
|
|
2474
|
+
if (this._isAriaHidden(element)) {
|
|
2475
|
+
return null;
|
|
2476
|
+
}
|
|
2477
|
+
const nestedElement = this._findNestedInteractive(element);
|
|
2478
|
+
if (nestedElement) {
|
|
2479
|
+
const elementTag = element.tagName.toLowerCase();
|
|
2480
|
+
const elementRole = element.getAttribute("role");
|
|
2481
|
+
const nestedTag = nestedElement.tagName.toLowerCase();
|
|
2482
|
+
const nestedRole = nestedElement.getAttribute("role");
|
|
2483
|
+
const elementDesc = elementRole ? `${elementTag}[role="${elementRole}"]` : elementTag;
|
|
2484
|
+
const nestedDesc = nestedRole ? `${nestedTag}[role="${nestedRole}"]` : nestedTag;
|
|
2485
|
+
return {
|
|
2486
|
+
issue: isElementVisible(element) ? {
|
|
2487
|
+
id: "nested-interactive",
|
|
2488
|
+
message: `Interactive element <${elementDesc}> contains a nested interactive element <${nestedDesc}>. This can confuse users and assistive technologies.`,
|
|
2489
|
+
element,
|
|
2490
|
+
rel: nestedElement,
|
|
2491
|
+
help: "https://dequeuniversity.com/rules/axe/4.4/nested-interactive"
|
|
2492
|
+
} : void 0
|
|
2493
|
+
};
|
|
2494
|
+
}
|
|
2495
|
+
return null;
|
|
2496
|
+
}
|
|
2497
|
+
};
|
|
2498
|
+
|
|
2499
|
+
// src/rules/tabindex.ts
|
|
2500
|
+
var INTERACTIVE_ELEMENTS = /* @__PURE__ */ new Set([
|
|
2501
|
+
"A",
|
|
2502
|
+
"BUTTON",
|
|
2503
|
+
"INPUT",
|
|
2504
|
+
"SELECT",
|
|
2505
|
+
"TEXTAREA",
|
|
2506
|
+
"DETAILS",
|
|
2507
|
+
"SUMMARY",
|
|
2508
|
+
"AUDIO",
|
|
2509
|
+
"VIDEO"
|
|
2510
|
+
]);
|
|
2511
|
+
var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
|
|
2512
|
+
"button",
|
|
2513
|
+
"link",
|
|
2514
|
+
"checkbox",
|
|
2515
|
+
"radio",
|
|
2516
|
+
"textbox",
|
|
2517
|
+
"combobox",
|
|
2518
|
+
"listbox",
|
|
2519
|
+
"menu",
|
|
2520
|
+
"menubar",
|
|
2521
|
+
"menuitem",
|
|
2522
|
+
"menuitemcheckbox",
|
|
2523
|
+
"menuitemradio",
|
|
2524
|
+
"option",
|
|
2525
|
+
"searchbox",
|
|
2526
|
+
"slider",
|
|
2527
|
+
"spinbutton",
|
|
2528
|
+
"switch",
|
|
2529
|
+
"tab",
|
|
2530
|
+
"tablist",
|
|
2531
|
+
"tree",
|
|
2532
|
+
"treegrid",
|
|
2533
|
+
"treeitem",
|
|
2534
|
+
"grid",
|
|
2535
|
+
"gridcell"
|
|
2536
|
+
]);
|
|
2537
|
+
var TabIndexRule = class extends ValidationRule {
|
|
2538
|
+
constructor() {
|
|
2539
|
+
super(...arguments);
|
|
2540
|
+
__publicField(this, "type", 2 /* Warning */);
|
|
2541
|
+
__publicField(this, "name", "tabindex");
|
|
2542
|
+
__publicField(this, "anchored", true);
|
|
2543
|
+
}
|
|
2544
|
+
accept(element) {
|
|
2545
|
+
return element.hasAttribute("tabindex");
|
|
2546
|
+
}
|
|
2547
|
+
isInteractiveElement(element) {
|
|
2548
|
+
if (INTERACTIVE_ELEMENTS.has(element.tagName)) {
|
|
2549
|
+
if (element.hasAttribute("disabled")) {
|
|
2550
|
+
return false;
|
|
2551
|
+
}
|
|
2552
|
+
if (element.tagName === "A" && !element.hasAttribute("href")) {
|
|
2553
|
+
return false;
|
|
2554
|
+
}
|
|
2555
|
+
return true;
|
|
2556
|
+
}
|
|
2557
|
+
const role = element.getAttribute("role");
|
|
2558
|
+
if (role && INTERACTIVE_ROLES.has(role)) {
|
|
2559
|
+
return true;
|
|
2560
|
+
}
|
|
2561
|
+
if (element.isContentEditable) {
|
|
2562
|
+
return true;
|
|
2563
|
+
}
|
|
2564
|
+
return false;
|
|
2565
|
+
}
|
|
2566
|
+
validate(element) {
|
|
2567
|
+
const tabindex = parseInt(element.getAttribute("tabindex") || "0", 10);
|
|
2568
|
+
if (tabindex > 0 && this.isInteractiveElement(element)) {
|
|
2569
|
+
return {
|
|
2570
|
+
issue: {
|
|
2571
|
+
id: "tabindex",
|
|
2572
|
+
message: `Avoid positive tabindex values (found: ${tabindex})`,
|
|
2573
|
+
element,
|
|
2574
|
+
help: "https://dequeuniversity.com/rules/axe/4.2/tabindex"
|
|
2575
|
+
}
|
|
2576
|
+
};
|
|
2577
|
+
}
|
|
2578
|
+
if (!this.isInteractiveElement(element)) {
|
|
2579
|
+
return {
|
|
2580
|
+
issue: {
|
|
2581
|
+
id: "tabindex-non-interactive",
|
|
2582
|
+
message: `Avoid using tabindex on non-interactive elements (<${element.tagName.toLowerCase()}>). Consider adding an interactive role or making the element naturally interactive.`,
|
|
2583
|
+
element,
|
|
2584
|
+
help: "https://dequeuniversity.com/rules/axe/4.2/tabindex"
|
|
2585
|
+
}
|
|
2586
|
+
};
|
|
2587
|
+
}
|
|
2588
|
+
return null;
|
|
2589
|
+
}
|
|
2590
|
+
};
|
|
2104
2591
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2105
2592
|
0 && (module.exports = {
|
|
2106
2593
|
AbleDOM,
|
|
@@ -2112,6 +2599,9 @@ var CustomNotifyRule = class extends ValidationRule {
|
|
|
2112
2599
|
FindElementRule,
|
|
2113
2600
|
FocusLostRule,
|
|
2114
2601
|
FocusableElementLabelRule,
|
|
2602
|
+
NestedInteractiveElementRule,
|
|
2603
|
+
RequiredParentRule,
|
|
2604
|
+
TabIndexRule,
|
|
2115
2605
|
ValidationRule,
|
|
2116
2606
|
ValidationRuleType,
|
|
2117
2607
|
hasAccessibilityAttribute,
|