Skip to content

Commit edc5fe2

Browse files
Anthon Fredrikssonljharb
Anthon Fredriksson
authored andcommitted
[New] style-prop-object: Add allow option
Fixes #1813 Co-Authored-By: Erwin <[email protected]> Co-Authored-By: hornta <[email protected]> Co-Authored-By: Anthon Fredriksson <[email protected]> fix trailing comma causing eslint error
1 parent 9b5d6aa commit edc5fe2

File tree

3 files changed

+115
-1
lines changed

3 files changed

+115
-1
lines changed

docs/rules/style-prop-object.md

+30
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,33 @@ React.createElement("Hello", { style: { color: 'red' }});
4949
const styles = { height: '100px' };
5050
React.createElement("div", { style: styles });
5151
```
52+
## Rule Options
53+
54+
```js
55+
...
56+
"react/style-prop-object": [<enabled>, {
57+
"allow": [<string>]
58+
}]
59+
...
60+
```
61+
62+
### `allow`
63+
A list of elements that are allowed to have a non-object value in their style attribute. The default value is `[]`.
64+
65+
#### Example
66+
```js
67+
{
68+
"allow": ["MyComponent"]
69+
}
70+
```
71+
The following patterns are considered warnings:
72+
```js
73+
<Hello style="a string">
74+
React.createElement(Hello, { style: "some styling" });
75+
```
76+
77+
The following patterns are **not** considered warnings:
78+
```js
79+
<MyComponent style="a string">
80+
React.createElement(MyComponent, { style: "some styling" });
81+
```

lib/rules/style-prop-object.js

+41-1
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,26 @@ module.exports = {
2020
recommended: false,
2121
url: docsUrl('style-prop-object')
2222
},
23-
schema: []
23+
schema: [
24+
{
25+
type: 'object',
26+
properties: {
27+
allow: {
28+
type: 'array',
29+
items: {
30+
type: 'string'
31+
},
32+
additionalItems: false,
33+
uniqueItems: true
34+
}
35+
}
36+
}
37+
]
2438
},
2539

2640
create(context) {
41+
const allowed = new Set(context.options.length > 0 && context.options[0].allow || []);
42+
2743
/**
2844
* @param {ASTNode} expression An Identifier node
2945
* @returns {boolean}
@@ -58,6 +74,16 @@ module.exports = {
5874
node.callee.property.name === 'createElement' &&
5975
node.arguments.length > 1
6076
) {
77+
if (node.arguments[0].name) {
78+
// store name of component
79+
const componentName = node.arguments[0].name;
80+
81+
// allowed list contains the name
82+
if (allowed.has(componentName)) {
83+
// abort operation
84+
return;
85+
}
86+
}
6187
if (node.arguments[1].type === 'ObjectExpression') {
6288
const style = node.arguments[1].properties.find(property => property.key && property.key.name === 'style' && !property.computed);
6389
if (style) {
@@ -78,6 +104,20 @@ module.exports = {
78104
if (!node.value || node.name.name !== 'style') {
79105
return;
80106
}
107+
// store parent element
108+
const parentElement = node.parent;
109+
110+
// parent element is a JSXOpeningElement
111+
if (parentElement && parentElement.type === 'JSXOpeningElement') {
112+
// get the name of the JSX element
113+
const name = parentElement.name && parentElement.name.name;
114+
115+
// allowed list contains the name
116+
if (allowed.has(name)) {
117+
// abort operation
118+
return;
119+
}
120+
}
81121

82122
if (node.value.type !== 'JSXExpressionContainer' || isNonNullaryLiteral(node.value.expression)) {
83123
context.report({

tests/lib/rules/style-prop-object.js

+44
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,22 @@ ruleTester.run('style-prop-object', rule, {
192192
' });',
193193
'};'
194194
].join('\n')
195+
},
196+
{
197+
code: '<MyComponent style="myStyle" />',
198+
options: [
199+
{
200+
allow: ['MyComponent']
201+
}
202+
]
203+
},
204+
{
205+
code: 'React.createElement(MyComponent, { style: "mySpecialStyle" })',
206+
options: [
207+
{
208+
allow: ['MyComponent']
209+
}
210+
]
195211
}
196212
],
197213
invalid: [
@@ -263,6 +279,34 @@ ruleTester.run('style-prop-object', rule, {
263279
column: 22,
264280
type: 'Identifier'
265281
}]
282+
},
283+
{
284+
code: '<MyComponent style="myStyle" />',
285+
options: [
286+
{
287+
allow: ['MyOtherComponent']
288+
}
289+
],
290+
errors: [{
291+
message: 'Style prop value must be an object',
292+
line: 1,
293+
column: 14,
294+
type: 'JSXAttribute'
295+
}]
296+
},
297+
{
298+
code: 'React.createElement(MyComponent, { style: "mySpecialStyle" })',
299+
options: [
300+
{
301+
allow: ['MyOtherComponent']
302+
}
303+
],
304+
errors: [{
305+
message: 'Style prop value must be an object',
306+
line: 1,
307+
column: 43,
308+
type: 'Literal'
309+
}]
266310
}
267311
]
268312
});

0 commit comments

Comments
 (0)