Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New] style-prop-object: Add allow option #1819

Merged
merged 1 commit into from Feb 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 30 additions & 0 deletions docs/rules/style-prop-object.md
Expand Up @@ -49,3 +49,33 @@ React.createElement("Hello", { style: { color: 'red' }});
const styles = { height: '100px' };
React.createElement("div", { style: styles });
```
## Rule Options

```js
...
"react/style-prop-object": [<enabled>, {
"allow": [<string>]
}]
...
```

### `allow`
A list of elements that are allowed to have a non-object value in their style attribute. The default value is `[]`.

#### Example
```js
{
"allow": ["MyComponent"]
}
```
The following patterns are considered warnings:
```js
<Hello style="a string">
React.createElement(Hello, { style: "some styling" });
```

The following patterns are **not** considered warnings:
```js
<MyComponent style="a string">
React.createElement(MyComponent, { style: "some styling" });
```
42 changes: 41 additions & 1 deletion lib/rules/style-prop-object.js
Expand Up @@ -20,10 +20,26 @@ module.exports = {
recommended: false,
url: docsUrl('style-prop-object')
},
schema: []
schema: [
{
type: 'object',
properties: {
allow: {
type: 'array',
items: {
type: 'string'
},
additionalItems: false,
uniqueItems: true
}
}
}
]
},

create(context) {
const allowed = new Set(context.options.length > 0 && context.options[0].allow || []);

/**
* @param {ASTNode} expression An Identifier node
* @returns {boolean}
Expand Down Expand Up @@ -58,6 +74,16 @@ module.exports = {
node.callee.property.name === 'createElement' &&
node.arguments.length > 1
) {
if (node.arguments[0].name) {
// store name of component
const componentName = node.arguments[0].name;

// allowed list contains the name
if (allowed.has(componentName)) {
// abort operation
return;
}
}
if (node.arguments[1].type === 'ObjectExpression') {
const style = node.arguments[1].properties.find(property => property.key && property.key.name === 'style' && !property.computed);
if (style) {
Expand All @@ -78,6 +104,20 @@ module.exports = {
if (!node.value || node.name.name !== 'style') {
return;
}
// store parent element
const parentElement = node.parent;

// parent element is a JSXOpeningElement
if (parentElement && parentElement.type === 'JSXOpeningElement') {
// get the name of the JSX element
const name = parentElement.name && parentElement.name.name;

// allowed list contains the name
if (allowed.has(name)) {
// abort operation
return;
}
}

if (node.value.type !== 'JSXExpressionContainer' || isNonNullaryLiteral(node.value.expression)) {
context.report({
Expand Down
44 changes: 44 additions & 0 deletions tests/lib/rules/style-prop-object.js
Expand Up @@ -192,6 +192,22 @@ ruleTester.run('style-prop-object', rule, {
' });',
'};'
].join('\n')
},
{
code: '<MyComponent style="myStyle" />',
options: [
{
allow: ['MyComponent']
}
]
},
{
code: 'React.createElement(MyComponent, { style: "mySpecialStyle" })',
options: [
{
allow: ['MyComponent']
}
]
}
],
invalid: [
Expand Down Expand Up @@ -263,6 +279,34 @@ ruleTester.run('style-prop-object', rule, {
column: 22,
type: 'Identifier'
}]
},
{
code: '<MyComponent style="myStyle" />',
options: [
{
allow: ['MyOtherComponent']
}
],
errors: [{
message: 'Style prop value must be an object',
line: 1,
column: 14,
type: 'JSXAttribute'
}]
},
{
code: 'React.createElement(MyComponent, { style: "mySpecialStyle" })',
options: [
{
allow: ['MyOtherComponent']
}
],
errors: [{
message: 'Style prop value must be an object',
line: 1,
column: 43,
type: 'Literal'
}]
}
]
});