/
no-redundant-roles.js
78 lines (67 loc) · 2.44 KB
/
no-redundant-roles.js
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
71
72
73
74
75
76
77
78
/**
* @fileoverview Enforce explicit role property is not the
* same as implicit/default role property on element.
* @author Ethan Cohen <@evcohen>
* @flow
*/
// ----------------------------------------------------------------------------
// Rule Definition
// ----------------------------------------------------------------------------
import { elementType } from 'jsx-ast-utils';
import includes from 'array-includes';
import has from 'has';
import type { JSXOpeningElement } from 'ast-types-flow';
import type { ESLintConfig, ESLintContext, ESLintVisitorSelectorConfig } from '../../flow/eslint';
import getExplicitRole from '../util/getExplicitRole';
import getImplicitRole from '../util/getImplicitRole';
const errorMessage = (element, implicitRole) => (
`The element ${element} has an implicit role of ${implicitRole}. Defining this explicitly is redundant and should be avoided.`
);
const DEFAULT_ROLE_EXCEPTIONS = { nav: ['navigation'] };
export default ({
meta: {
docs: {
url: 'https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/tree/HEAD/docs/rules/no-redundant-roles.md',
description: 'Enforce explicit role property is not the same as implicit/default role property on element.',
},
schema: [{
type: 'object',
additionalProperties: {
type: 'array',
items: {
type: 'string',
},
uniqueItems: true,
},
}],
},
create: (context: ESLintContext): ESLintVisitorSelectorConfig => {
const { options } = context;
return {
JSXOpeningElement: (node: JSXOpeningElement) => {
const type = elementType(node);
const implicitRole = getImplicitRole(type, node.attributes);
const explicitRole = getExplicitRole(type, node.attributes);
if (!implicitRole || !explicitRole) {
return;
}
if (implicitRole === explicitRole) {
const allowedRedundantRoles = (options[0] || {});
let redundantRolesForElement;
if (has(allowedRedundantRoles, type)) {
redundantRolesForElement = allowedRedundantRoles[type];
} else {
redundantRolesForElement = DEFAULT_ROLE_EXCEPTIONS[type] || [];
}
if (includes(redundantRolesForElement, implicitRole)) {
return;
}
context.report({
node,
message: errorMessage(type, implicitRole.toLowerCase()),
});
}
},
};
},
}: ESLintConfig);