Skip to content

Commit

Permalink
[New] style-prop-object: Add allow option
Browse files Browse the repository at this point in the history
Fixes #1813

Co-Authored-By: Erwin <evosch@users.noreply.github.com>
Co-Authored-By: hornta <4553604+hornta@users.noreply.github.com>
Co-Authored-By: Anthon Fredriksson <anthonnorrby@gmail.com>

fix trailing comma causing eslint error
  • Loading branch information
Anthon Fredriksson authored and ljharb committed Jun 9, 2018
1 parent 9b5d6aa commit edc5fe2
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 1 deletion.
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'
}]
}
]
});

0 comments on commit edc5fe2

Please sign in to comment.