From b36dd682e8821601dae6d7ea379930578ef39862 Mon Sep 17 00:00:00 2001 From: Anthon Fredriksson Date: Sat, 9 Jun 2018 11:22:51 +0200 Subject: [PATCH 1/7] Add `allow` option in style-prop-object --- .gitignore | 3 ++ docs/rules/style-prop-object.md | 30 +++++++++++++++++++ lib/rules/style-prop-object.js | 41 +++++++++++++++++++++++++- tests/lib/rules/style-prop-object.js | 44 ++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4b8d368260..e2d4c1415f 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,6 @@ sftp-config.json # Only apps should have lockfiles yarn.lock package-lock.json + +# Visual Code folder +.vscode diff --git a/docs/rules/style-prop-object.md b/docs/rules/style-prop-object.md index 464f889cb6..386c09cfb3 100644 --- a/docs/rules/style-prop-object.md +++ b/docs/rules/style-prop-object.md @@ -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": [, { + "allow": [] +}] +... +``` + +### `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 + +React.createElement(Hello, { style: "some styling" }); +``` + +The following patterns are **not** considered warnings: +```js + +React.createElement(MyComponent, { style: "some styling" }); +``` diff --git a/lib/rules/style-prop-object.js b/lib/rules/style-prop-object.js index 4a29d33d25..da401273b5 100644 --- a/lib/rules/style-prop-object.js +++ b/lib/rules/style-prop-object.js @@ -19,10 +19,24 @@ module.exports = { recommended: false, url: docsUrl('style-prop-object') }, - schema: [] + schema: [ + { + type: 'object', + properties: { + allow: { + type: 'array', + items: { + type: 'string' + } + } + } + } + ] }, create: function(context) { + const allowed = context.options.length > 0 && context.options[0].allow || []; + /** * @param {object} node An Identifier node */ @@ -53,6 +67,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.indexOf(componentName) > -1) { + // 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) { @@ -71,6 +95,21 @@ module.exports = { return; } + // parent element is a JSXOpeningElement + if (node.parent && node.parent.type === 'JSXOpeningElement') { + // store parent element + const jsxOpeningElement = node.parent; + + // get the name of the JSX element + const name = jsxOpeningElement.name && jsxOpeningElement.name.name; + + // allowed list contains the name + if (allowed.indexOf(name) > -1) { + // abort operation + return; + } + } + if (node.value.type !== 'JSXExpressionContainer' || isNonNullaryLiteral(node.value.expression)) { context.report(node, 'Style prop value must be an object'); } else if (node.value.expression.type === 'Identifier') { diff --git a/tests/lib/rules/style-prop-object.js b/tests/lib/rules/style-prop-object.js index c2d8b3d765..13fa702d8c 100644 --- a/tests/lib/rules/style-prop-object.js +++ b/tests/lib/rules/style-prop-object.js @@ -191,6 +191,22 @@ ruleTester.run('style-prop-object', rule, { ' });', '};' ].join('\n') + }, + { + code: '', + options: [ + { + allow: ['MyComponent'] + } + ] + }, + { + code: 'React.createElement(MyComponent, { style: "mySpecialStyle" })', + options: [ + { + allow: ['MyComponent'] + } + ] } ], invalid: [ @@ -262,6 +278,34 @@ ruleTester.run('style-prop-object', rule, { column: 22, type: 'Identifier' }] + }, + { + code: '', + 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' + }] } ] }); From 78397725bd2b2c8b2c9ce4943fea3adcb93319a4 Mon Sep 17 00:00:00 2001 From: Erwin Date: Thu, 6 Dec 2018 10:45:07 +0100 Subject: [PATCH 2/7] Remove IDE specific gitignore See https://github.com/yannickcr/eslint-plugin-react/pull/1819#discussion_r194589966 --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index e2d4c1415f..4b8d368260 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,3 @@ sftp-config.json # Only apps should have lockfiles yarn.lock package-lock.json - -# Visual Code folder -.vscode From b52fecc7a1b74a7b7fac5f555b721d0ab3ea8e67 Mon Sep 17 00:00:00 2001 From: Erwin Date: Thu, 6 Dec 2018 10:48:41 +0100 Subject: [PATCH 3/7] Create a set of allowed See: https://github.com/yannickcr/eslint-plugin-react/pull/1819#discussion_r194590034 --- lib/rules/style-prop-object.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rules/style-prop-object.js b/lib/rules/style-prop-object.js index da401273b5..7d27fd1755 100644 --- a/lib/rules/style-prop-object.js +++ b/lib/rules/style-prop-object.js @@ -35,7 +35,7 @@ module.exports = { }, create: function(context) { - const allowed = context.options.length > 0 && context.options[0].allow || []; + const allowed = context.options.length > 0 && new Set(context.options[0].allow || []); /** * @param {object} node An Identifier node @@ -72,7 +72,7 @@ module.exports = { const componentName = node.arguments[0].name; // allowed list contains the name - if (allowed.indexOf(componentName) > -1) { + if (allowed.has(componentName)) { // abort operation return; } From c02101973c86099487ba69abe666a469834d6783 Mon Sep 17 00:00:00 2001 From: Erwin Date: Thu, 6 Dec 2018 10:52:35 +0100 Subject: [PATCH 4/7] store parent prior to if See: https://github.com/yannickcr/eslint-plugin-react/pull/1819#discussion_r194590185 --- lib/rules/style-prop-object.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/rules/style-prop-object.js b/lib/rules/style-prop-object.js index 7d27fd1755..eb8debf535 100644 --- a/lib/rules/style-prop-object.js +++ b/lib/rules/style-prop-object.js @@ -94,14 +94,14 @@ module.exports = { if (!node.value || node.name.name !== 'style') { return; } - + // store parent element + const parentElement = node.parent; + // parent element is a JSXOpeningElement - if (node.parent && node.parent.type === 'JSXOpeningElement') { - // store parent element - const jsxOpeningElement = node.parent; + if (parentElement && parentElement.type === 'JSXOpeningElement') { // get the name of the JSX element - const name = jsxOpeningElement.name && jsxOpeningElement.name.name; + const name = parentElement.name && parentElement.name.name; // allowed list contains the name if (allowed.indexOf(name) > -1) { From 6be3e51647c7ebf2afe0d44f1a5413ad0becf228 Mon Sep 17 00:00:00 2001 From: Erwin Date: Thu, 6 Dec 2018 11:07:04 +0100 Subject: [PATCH 5/7] use allowed Set in JSXAttribute --- lib/rules/style-prop-object.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rules/style-prop-object.js b/lib/rules/style-prop-object.js index eb8debf535..ec654497e2 100644 --- a/lib/rules/style-prop-object.js +++ b/lib/rules/style-prop-object.js @@ -104,7 +104,7 @@ module.exports = { const name = parentElement.name && parentElement.name.name; // allowed list contains the name - if (allowed.indexOf(name) > -1) { + if (allowed.has(name)) { // abort operation return; } From 71f88808a1aec4e2fef1f4e676b72d4d64c55866 Mon Sep 17 00:00:00 2001 From: Erwin Date: Thu, 6 Dec 2018 11:10:47 +0100 Subject: [PATCH 6/7] Update style-prop-object.js --- lib/rules/style-prop-object.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rules/style-prop-object.js b/lib/rules/style-prop-object.js index ec654497e2..7af43e8c6b 100644 --- a/lib/rules/style-prop-object.js +++ b/lib/rules/style-prop-object.js @@ -35,7 +35,7 @@ module.exports = { }, create: function(context) { - const allowed = context.options.length > 0 && new Set(context.options[0].allow || []); + const allowed = new Set(context.options.length > 0 && context.options[0].allow || []); /** * @param {object} node An Identifier node From 28c27e6e6969cacd51ddec54f42d6dbb147a4c91 Mon Sep 17 00:00:00 2001 From: Erwin Date: Thu, 6 Dec 2018 11:19:06 +0100 Subject: [PATCH 7/7] Fix linter issues --- lib/rules/style-prop-object.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/rules/style-prop-object.js b/lib/rules/style-prop-object.js index 7af43e8c6b..7aa12eea39 100644 --- a/lib/rules/style-prop-object.js +++ b/lib/rules/style-prop-object.js @@ -96,10 +96,9 @@ module.exports = { } // 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;