Skip to content

Commit f9b0d82

Browse files
authored
[refactor] - Transform rules to new eslint rule format (#73)
Fixes #71
1 parent 08c5bc1 commit f9b0d82

22 files changed

+820
-688
lines changed

src/rules/anchor-has-content.js

Lines changed: 56 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -18,58 +18,64 @@ const anchors = [
1818
'Link',
1919
];
2020

21-
module.exports = context => ({
22-
JSXOpeningElement: node => {
23-
const typeCheck = anchors.concat(context.options[0]);
24-
const nodeType = elementType(node);
21+
module.exports = {
22+
meta: {
23+
docs: {},
2524

26-
// Only check anchor elements and custom types.
27-
if (typeCheck.indexOf(nodeType) === -1) {
28-
return;
29-
}
30-
const isAccessible = node.parent.children.some(child => {
31-
switch (child.type) {
32-
case 'Literal':
33-
return Boolean(child.value);
34-
case 'JSXElement':
35-
return !isHiddenFromScreenReader(
36-
elementType(child.openingElement),
37-
child.openingElement.attributes
38-
);
39-
case 'JSXExpressionContainer':
40-
if (child.expression.type === 'Identifier') {
41-
return child.expression.name !== 'undefined';
42-
}
43-
return true;
44-
default:
45-
return false;
46-
}
47-
}) || hasProp(node.attributes, 'dangerouslySetInnerHTML');
48-
49-
50-
if (isAccessible) {
51-
return;
52-
}
53-
54-
context.report({
55-
node,
56-
message: errorMessage,
57-
});
58-
},
59-
});
60-
61-
module.exports.schema = [
62-
{
63-
oneOf: [
64-
{ type: 'string' },
25+
schema: [
6526
{
66-
type: 'array',
67-
items: {
68-
type: 'string',
69-
},
70-
minItems: 1,
71-
uniqueItems: true,
27+
oneOf: [
28+
{ type: 'string' },
29+
{
30+
type: 'array',
31+
items: {
32+
type: 'string',
33+
},
34+
minItems: 1,
35+
uniqueItems: true,
36+
},
37+
],
7238
},
7339
],
7440
},
75-
];
41+
42+
create: context => ({
43+
JSXOpeningElement: node => {
44+
const typeCheck = anchors.concat(context.options[0]);
45+
const nodeType = elementType(node);
46+
47+
// Only check anchor elements and custom types.
48+
if (typeCheck.indexOf(nodeType) === -1) {
49+
return;
50+
}
51+
const isAccessible = node.parent.children.some(child => {
52+
switch (child.type) {
53+
case 'Literal':
54+
return Boolean(child.value);
55+
case 'JSXElement':
56+
return !isHiddenFromScreenReader(
57+
elementType(child.openingElement),
58+
child.openingElement.attributes
59+
);
60+
case 'JSXExpressionContainer':
61+
if (child.expression.type === 'Identifier') {
62+
return child.expression.name !== 'undefined';
63+
}
64+
return true;
65+
default:
66+
return false;
67+
}
68+
}) || hasProp(node.attributes, 'dangerouslySetInnerHTML');
69+
70+
71+
if (isAccessible) {
72+
return;
73+
}
74+
75+
context.report({
76+
node,
77+
message: errorMessage,
78+
});
79+
},
80+
}),
81+
};

src/rules/aria-props.js

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,33 @@ const errorMessage = name => {
2323
return message;
2424
};
2525

26-
module.exports = context => ({
27-
JSXAttribute: attribute => {
28-
const name = propName(attribute);
29-
const normalizedName = name ? name.toUpperCase() : '';
30-
31-
// `aria` needs to be prefix of property.
32-
if (normalizedName.indexOf('ARIA-') !== 0) {
33-
return;
34-
}
35-
36-
const isValid = Object.keys(ariaAttributes).indexOf(normalizedName) > -1;
37-
38-
if (isValid === false) {
39-
context.report({
40-
node: attribute,
41-
message: errorMessage(name),
42-
});
43-
}
26+
module.exports = {
27+
meta: {
28+
docs: {},
29+
30+
schema: [
31+
{ type: 'object' },
32+
],
4433
},
45-
});
4634

47-
module.exports.schema = [
48-
{ type: 'object' },
49-
];
35+
create: context => ({
36+
JSXAttribute: attribute => {
37+
const name = propName(attribute);
38+
const normalizedName = name ? name.toUpperCase() : '';
39+
40+
// `aria` needs to be prefix of property.
41+
if (normalizedName.indexOf('ARIA-') !== 0) {
42+
return;
43+
}
44+
45+
const isValid = Object.keys(ariaAttributes).indexOf(normalizedName) > -1;
46+
47+
if (isValid === false) {
48+
context.report({
49+
node: attribute,
50+
message: errorMessage(name),
51+
});
52+
}
53+
},
54+
}),
55+
};

src/rules/aria-proptypes.js

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -50,43 +50,49 @@ const validityCheck = (value, expectedType, permittedValues) => {
5050
}
5151
};
5252

53-
module.exports = context => ({
54-
JSXAttribute: attribute => {
55-
const name = propName(attribute);
56-
const normalizedName = name ? name.toUpperCase() : '';
53+
module.exports = {
54+
meta: {
55+
docs: {},
5756

58-
// Not a valid aria-* state or property.
59-
if (normalizedName.indexOf('ARIA-') !== 0 || ariaAttributes[normalizedName] === undefined) {
60-
return;
61-
}
57+
schema: [
58+
{ type: 'object' },
59+
],
60+
},
6261

63-
const value = getLiteralPropValue(attribute);
62+
create: context => ({
63+
JSXAttribute: attribute => {
64+
const name = propName(attribute);
65+
const normalizedName = name ? name.toUpperCase() : '';
6466

65-
// We only want to check literal prop values, so just pass if it's null.
66-
if (value === null) {
67-
return;
68-
}
67+
// Not a valid aria-* state or property.
68+
if (normalizedName.indexOf('ARIA-') !== 0 || ariaAttributes[normalizedName] === undefined) {
69+
return;
70+
}
6971

70-
// These are the attributes of the property/state to check against.
71-
const attributes = ariaAttributes[normalizedName];
72-
const permittedType = attributes.type;
73-
const allowUndefined = attributes.allowUndefined || false;
74-
const permittedValues = attributes.values || [];
72+
const value = getLiteralPropValue(attribute);
7573

76-
const isValid = validityCheck(value, permittedType, permittedValues) ||
77-
(allowUndefined && value === undefined);
74+
// We only want to check literal prop values, so just pass if it's null.
75+
if (value === null) {
76+
return;
77+
}
7878

79-
if (isValid) {
80-
return;
81-
}
79+
// These are the attributes of the property/state to check against.
80+
const attributes = ariaAttributes[normalizedName];
81+
const permittedType = attributes.type;
82+
const allowUndefined = attributes.allowUndefined || false;
83+
const permittedValues = attributes.values || [];
8284

83-
context.report({
84-
node: attribute,
85-
message: errorMessage(name, permittedType, permittedValues),
86-
});
87-
},
88-
});
85+
const isValid = validityCheck(value, permittedType, permittedValues) ||
86+
(allowUndefined && value === undefined);
8987

90-
module.exports.schema = [
91-
{ type: 'object' },
92-
];
88+
if (isValid) {
89+
return;
90+
}
91+
92+
context.report({
93+
node: attribute,
94+
message: errorMessage(name, permittedType, permittedValues),
95+
});
96+
},
97+
}),
98+
};

src/rules/aria-role.js

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,45 @@ import { getLiteralPropValue, propName } from 'jsx-ast-utils';
1212

1313
const errorMessage = 'Elements with ARIA roles must use a valid, non-abstract ARIA role.';
1414

15-
module.exports = context => ({
16-
JSXAttribute: attribute => {
17-
const name = propName(attribute);
18-
const normalizedName = name ? name.toUpperCase() : '';
19-
20-
if (normalizedName !== 'ROLE') {
21-
return;
22-
}
23-
24-
const value = getLiteralPropValue(attribute);
25-
26-
// If value is undefined, then the role attribute will be dropped in the DOM.
27-
// If value is null, then getLiteralAttributeValue is telling us that the
28-
// value isn't in the form of a literal.
29-
if (value === undefined || value === null) {
30-
return;
31-
}
32-
33-
const normalizedValues = String(value).toUpperCase().split(' ');
34-
const validRoles = Object.keys(roles).filter(role => roles[role].abstract === false);
35-
const isValid = normalizedValues.every(val => validRoles.indexOf(val) > -1);
36-
37-
if (isValid === true) {
38-
return;
39-
}
40-
41-
context.report({
42-
node: attribute,
43-
message: errorMessage,
44-
});
15+
module.exports = {
16+
meta: {
17+
docs: {},
18+
19+
schema: [
20+
{ type: 'object' },
21+
],
4522
},
46-
});
4723

48-
module.exports.schema = [
49-
{ type: 'object' },
50-
];
24+
create: context => ({
25+
JSXAttribute: attribute => {
26+
const name = propName(attribute);
27+
const normalizedName = name ? name.toUpperCase() : '';
28+
29+
if (normalizedName !== 'ROLE') {
30+
return;
31+
}
32+
33+
const value = getLiteralPropValue(attribute);
34+
35+
// If value is undefined, then the role attribute will be dropped in the DOM.
36+
// If value is null, then getLiteralAttributeValue is telling us that the
37+
// value isn't in the form of a literal.
38+
if (value === undefined || value === null) {
39+
return;
40+
}
41+
42+
const normalizedValues = String(value).toUpperCase().split(' ');
43+
const validRoles = Object.keys(roles).filter(role => roles[role].abstract === false);
44+
const isValid = normalizedValues.every(val => validRoles.indexOf(val) > -1);
45+
46+
if (isValid === true) {
47+
return;
48+
}
49+
50+
context.report({
51+
node: attribute,
52+
message: errorMessage,
53+
});
54+
},
55+
}),
56+
};

0 commit comments

Comments
 (0)