Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/dark-jobs-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'eslint-plugin-primer-react': patch
---

Fix `no-unnecessary-components` rule to support `@primer/styled-react` imports.
85 changes: 85 additions & 0 deletions src/rules/__tests__/no-unnecessary-components.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const rule = require('../no-unnecessary-components')
const {components} = require('../no-unnecessary-components')

const prcImport = 'import React from "react"; import {Box, Text} from "@primer/react";'
const styledReactImport = 'import React from "react"; import {Box, Text} from "@primer/styled-react";'
const brandImport = 'import React from "react"; import {Box, Text} from "@primer/react-brand";'

/** @param {string} content */
Expand Down Expand Up @@ -66,6 +67,26 @@ ruleTester.run('unnecessary-components', rule, {
code: `${prcImport}${stringRecordDeclaration}${jsx(`<${component} {...props}>Hello World</${component}>`)}`,
filename,
},
{
name: `${component} from @primer/styled-react with sx prop`,
code: `${styledReactImport}${jsx(`<${component} sx={{color: "red"}}>Hello World</${component}>`)}`,
filename,
},
{
name: `${component} from @primer/styled-react with any styled-system prop`,
code: `${styledReactImport}${jsx(`<${component} flex="row">Hello World</${component}>`)}`,
filename,
},
{
name: `${component} from @primer/styled-react with spread sx prop`,
code: `${styledReactImport}${sxObjectDeclaration}${jsx(`<${component} {...props}>Hello World</${component}>`)}`,
filename,
},
{
name: `${component} from @primer/styled-react with string index spread props`,
code: `${styledReactImport}${stringRecordDeclaration}${jsx(`<${component} {...props}>Hello World</${component}>`)}`,
filename,
},
]),
{
name: `Text with weight prop`,
Expand Down Expand Up @@ -151,5 +172,69 @@ ruleTester.run('unnecessary-components', rule, {
errors: [{messageId}],
options: [{skipImportCheck: true}],
},
{
name: `${component} from @primer/styled-react without any styled-system props`,
code: `${styledReactImport}${jsx(`<${component}>Hello World</${component}>`)}`,
output: `${styledReactImport}${jsx(`<${replacement}>Hello World</${replacement}>`)}`,
errors: [{messageId}],
filename,
},
{
name: `Self-closing ${component} from @primer/styled-react without any styled-system props`,
code: `${styledReactImport}${jsx(`<${component} />`)}`,
output: `${styledReactImport}${jsx(`<${replacement} />`)}`,
errors: [{messageId}],
filename,
},
{
name: `${component} from @primer/styled-react with spread props without sx`,
code: `${styledReactImport}${testIdObjectDeclaration}${jsx(`<${component} {...props}>Hello World</${component}>`)}`,
output: `${styledReactImport}${testIdObjectDeclaration}${jsx(`<${replacement} {...props}>Hello World</${replacement}>`)}`,
errors: [{messageId}],
filename,
},
{
name: `${component} from @primer/styled-react with string element 'as' prop`,
code: `${styledReactImport}${jsx(`<${component} as="code">Hello world</${component}>`)}`,
// There is extra whitespace here we don't worry about since formatters would get rid of it
output: `${styledReactImport}${jsx(`<code >Hello world</code>`)}`,
errors: [{messageId}],
filename,
},
{
name: `${component} from @primer/styled-react with single-character 'as' prop`,
code: `${styledReactImport}${jsx(`<${component} as="p">Hello world</${component}>`)}`,
output: `${styledReactImport}${jsx(`<p >Hello world</p>`)}`,
errors: [{messageId}],
filename,
},
{
name: `${component} from @primer/styled-react with string element 'as' prop surrounded by unnecessary braces`,
code: `${styledReactImport}${jsx(`<${component} as={"code"}>Hello world</${component}>`)}`,
output: `${styledReactImport}${jsx(`<code >Hello world</code>`)}`,
errors: [{messageId}],
filename,
},
{
name: `${component} from @primer/styled-react with component reference 'as' prop`,
code: `${styledReactImport}${componentDeclaration}${jsx(`<${component} as={OtherComponent}>Hello world</${component}>`)}`,
output: `${styledReactImport}${componentDeclaration}${jsx(`<OtherComponent >Hello world</OtherComponent>`)}`,
errors: [{messageId}],
filename,
},
{
name: `${component} from @primer/styled-react with spread 'as' prop`,
code: `${styledReactImport}${asObjectDeclaration}${jsx(`<${component} {...props}>Hello world</${component}>`)}`,
output: null,
errors: [{messageId}],
filename,
},
{
name: `${component} from @primer/styled-react with unusable lowercase reference 'as' prop`,
code: `${styledReactImport}${asConstDeclaration}${jsx(`<${component} as={as}>Hello world</${component}>`)}`,
output: null,
errors: [{messageId}],
filename,
},
]),
})
6 changes: 3 additions & 3 deletions src/utils/is-primer-component.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const {isImportedFrom} = require('./is-imported-from')

/**
* Check if `name` is a JSX component that is imported from `@primer/react` or
* a subpath `@primer/react/*`.
* Check if `name` is a JSX component that is imported from `@primer/react`,
* `@primer/styled-react`, or a subpath of either.
* @returns {boolean}
*/
function isPrimerComponent(name, scope) {
Expand All @@ -18,6 +18,6 @@ function isPrimerComponent(name, scope) {
default:
return false
}
return isImportedFrom(/^@primer\/react(?:$|\/)/, identifier, scope)
return isImportedFrom(/^@primer\/(?:styled-)?react(?:$|\/)/, identifier, scope)
}
exports.isPrimerComponent = isPrimerComponent
Loading