From f0c7a3d1ab1d60df2c95b86c80d930d6ef15bde1 Mon Sep 17 00:00:00 2001 From: Jonathan Fuchs Date: Fri, 29 Oct 2021 12:12:52 -0700 Subject: [PATCH] Introduces an option on no-system-props to include utility components. --- .changeset/few-shoes-refuse.md | 5 +++++ README.md | 3 ++- docs/rules/no-system-props.md | 16 ++++++++++++++ src/rules/__tests__/no-system-props.test.js | 22 +++++++++++++++++++ src/rules/no-system-props.js | 24 +++++++++++++++++---- 5 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 .changeset/few-shoes-refuse.md diff --git a/.changeset/few-shoes-refuse.md b/.changeset/few-shoes-refuse.md new file mode 100644 index 0000000..9342664 --- /dev/null +++ b/.changeset/few-shoes-refuse.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-primer-react': minor +--- + +Introduced an option on no-system-props to include utility components (includeUtilityComponents). diff --git a/README.md b/README.md index a4e1957..449e1d5 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ ESLint rules for Primer React npm install --save-dev eslint-plugin-primer-react # or - + yarn add --dev eslint-plugin-primer-react ``` @@ -30,3 +30,4 @@ ESLint rules for Primer React ## Rules - [no-deprecated-colors](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-deprecated-colors.md) +- [no-system-props](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-system-props.md) diff --git a/docs/rules/no-system-props.md b/docs/rules/no-system-props.md index 75e361d..0bc2f70 100644 --- a/docs/rules/no-system-props.md +++ b/docs/rules/no-system-props.md @@ -38,3 +38,19 @@ import {Avatar} from 'some-other-library' // System props passed to non-Primer components are allowed ``` + +## Options + +- `includeUtilityComponents` (default: `false`) + + By default, `Box` and `Text` are excluded because styled system props are not deprecated in our utility components. If you prefer to avoid styled system props there as well for consistency, you can set `includeUtilityComponents` to `true`. + + ```js + /* eslint primer-react/no-system-props: ["warn", {"includeUtilityComponents": true}] */ + import {Box} from '@primer/components' + + function App() { + // Enabling `includeUtilityComponents` will find system prop usage on utility components like this: + return + } + ``` diff --git a/src/rules/__tests__/no-system-props.test.js b/src/rules/__tests__/no-system-props.test.js index 50a3bdc..56ebb5a 100644 --- a/src/rules/__tests__/no-system-props.test.js +++ b/src/rules/__tests__/no-system-props.test.js @@ -120,6 +120,28 @@ ruleTester.run('no-system-props', rule, { data: {propNames: 'width', componentName: 'Label'} } ] + }, + { + code: `import {Box} from '@primer/components'; `, + output: `import {Box} from '@primer/components'; `, + options: [{includeUtilityComponents: true}], + errors: [ + { + messageId: 'noSystemProps', + data: {propNames: 'width', componentName: 'Box'} + } + ] + }, + { + code: `import {Text} from '@primer/components'; `, + output: `import {Text} from '@primer/components'; `, + options: [{includeUtilityComponents: true}], + errors: [ + { + messageId: 'noSystemProps', + data: {propNames: 'width', componentName: 'Text'} + } + ] } ] }) diff --git a/src/rules/no-system-props.js b/src/rules/no-system-props.js index 5db05cb..91ae0b4 100644 --- a/src/rules/no-system-props.js +++ b/src/rules/no-system-props.js @@ -3,12 +3,13 @@ const {pick} = require('@styled-system/props') const {some, last} = require('lodash') // Components for which we allow all styled system props -const excludedComponents = new Set([ - 'Box', - 'Text', +const alwaysExcludedComponents = new Set([ 'BaseStyles' // BaseStyles will be deprecated eventually ]) +// Excluded by default, but optionally included: +const utilityComponents = new Set(['Box', 'Text']) + // Components for which we allow a set of prop names const excludedComponentProps = new Map([ ['AnchoredOverlay', new Set(['width', 'height'])], @@ -25,12 +26,27 @@ module.exports = { meta: { type: 'suggestion', fixable: 'code', - schema: [], + schema: [ + { + properties: { + includeUtilityComponents: { + type: 'boolean' + } + } + } + ], messages: { noSystemProps: 'Styled-system props are deprecated ({{ componentName }} called with props: {{ propNames }})' } }, create(context) { + const includeUtilityComponents = context.options[0] ? context.options[0].includeUtilityComponents : false + + const excludedComponents = new Set([ + ...alwaysExcludedComponents, + ...(includeUtilityComponents ? [] : utilityComponents) + ]) + return { JSXOpeningElement(jsxNode) { if (!isPrimerComponent(jsxNode.name, context.getScope(jsxNode))) return