-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
/
button-has-type.js
121 lines (104 loc) · 3.06 KB
/
button-has-type.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
* @fileoverview Forbid "button" element without an explicit "type" attribute
* @author Filipp Riabchun
*/
'use strict';
const getProp = require('jsx-ast-utils/getProp');
const getLiteralPropValue = require('jsx-ast-utils/getLiteralPropValue');
// ------------------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------------------
function isCreateElement(node) {
return node.callee
&& node.callee.type === 'MemberExpression'
&& node.callee.property.name === 'createElement'
&& node.arguments.length > 0;
}
// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
module.exports = {
meta: {
docs: {
description: 'Forbid "button" element without an explicit "type" attribute',
category: 'Possible Errors',
recommended: false
},
schema: [{
type: 'object',
properties: {
button: {
default: true,
type: 'boolean'
},
submit: {
default: true,
type: 'boolean'
},
reset: {
default: true,
type: 'boolean'
}
},
additionalProperties: false
}]
},
create: function(context) {
const configuration = Object.assign({
button: true,
submit: true,
reset: true
}, context.options[0]);
function reportMissing(node) {
context.report({
node: node,
message: 'Missing an explicit type attribute for button'
});
}
function checkValue(node, value) {
if (!(value in configuration)) {
context.report({
node: node,
message: `"${value}" is an invalid value for button type attribute`
});
} else if (!configuration[value]) {
context.report({
node: node,
message: `"${value}" is a forbidden value for button type attribute`
});
}
}
return {
JSXElement: function(node) {
if (node.openingElement.name.name !== 'button') {
return;
}
const typeProp = getProp(node.openingElement.attributes, 'type');
if (!typeProp) {
reportMissing(node);
return;
}
checkValue(node, getLiteralPropValue(typeProp));
},
CallExpression: function(node) {
if (!isCreateElement(node)) {
return;
}
if (node.arguments[0].type !== 'Literal' || node.arguments[0].value !== 'button') {
return;
}
if (!node.arguments[1] || node.arguments[1].type !== 'ObjectExpression') {
reportMissing(node);
return;
}
const props = node.arguments[1].properties;
const typeProp = props.find(prop => prop.key && prop.key.name === 'type');
if (!typeProp || typeProp.value.type !== 'Literal') {
reportMissing(node);
return;
}
checkValue(node, typeProp.value.value);
}
};
}
};