-
-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathrole-has-required-aria-props.ts
70 lines (62 loc) · 1.89 KB
/
role-has-required-aria-props.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import type { Rule } from "eslint";
import type { AST } from "vue-eslint-parser";
import { ARIARoleDefinitionKey, dom, roles } from "aria-query";
import {
defineTemplateBodyVisitor,
getElementAttribute,
getElementAttributeValue,
getElementType,
makeDocsURL
} from "../utils";
function hasAttributes(node: AST.VElement, names: string[]) {
return names.every((name) => getElementAttribute(node, name) !== null);
}
function isAriaRoleDefinitionKey(role: any): role is ARIARoleDefinitionKey {
return roles.has(role);
}
const rule: Rule.RuleModule = {
meta: {
type: "problem",
docs: {
url: makeDocsURL("role-has-required-aria-props")
},
messages: {
default: `Elements with the ARIA role "{{role}}" must have the following attributes defined: {{attributes}}`
},
schema: []
},
create(context) {
return defineTemplateBodyVisitor(context, {
VElement(node) {
const elementType = getElementType(node);
if (!dom.get(elementType)) {
return;
}
const roleValue = getElementAttributeValue(node, "role");
if (!roleValue || typeof roleValue !== "string") {
return;
}
roleValue
.toLowerCase()
.split(" ")
.forEach((role) => {
if (isAriaRoleDefinitionKey(role)) {
const roleDefinition = roles.get(role) as any;
const requiredProps = Object.keys(roleDefinition.requiredProps);
if (requiredProps && !hasAttributes(node, requiredProps)) {
context.report({
node: node as any,
messageId: "default",
data: {
role: role.toLowerCase(),
attributes: requiredProps.join(", ").toLowerCase()
}
});
}
}
});
}
});
}
};
export default rule;