@@ -12,13 +12,13 @@ const components = {
12
12
replacement : 'div' ,
13
13
messageId : 'unecessaryBox' ,
14
14
message : 'Prefer plain HTML elements over `Box` when not using `sx` for styling.' ,
15
- allowedProps : [ 'sx' ] , // + styled-system props
15
+ allowedProps : new Set ( [ 'sx' ] ) , // + styled-system props
16
16
} ,
17
17
Text : {
18
18
replacement : 'span' ,
19
19
messageId : 'unecessarySpan' ,
20
20
message : 'Prefer plain HTML elements over `Text` when not using `sx` for styling.' ,
21
- allowedProps : [ 'sx' , 'size' , 'weight' ] , // + styled-system props
21
+ allowedProps : new Set ( [ 'sx' , 'size' , 'weight' ] ) , // + styled-system props
22
22
} ,
23
23
}
24
24
@@ -70,6 +70,9 @@ const rule = ESLintUtils.RuleCreator.withoutDocs({
70
70
const isPrimer = skipImportCheck || isPrimerComponent ( name , context . sourceCode . getScope ( openingElement ) )
71
71
if ( ! isPrimer ) return
72
72
73
+ /** @param {string } name */
74
+ const isAllowedProp = name => componentConfig . allowedProps . has ( name ) || isStyledSystemProp ( name )
75
+
73
76
// Validate the attributes and ensure an allowed prop is present or spreaded in
74
77
/** @type {typeof attributes[number] | undefined | null } */
75
78
let asProp = undefined
@@ -80,25 +83,23 @@ const rule = ESLintUtils.RuleCreator.withoutDocs({
80
83
const typeChecker = services . program . getTypeChecker ( )
81
84
82
85
const spreadType = services . getTypeAtLocation ( attribute . argument )
83
- for ( const allowedProp of componentConfig . allowedProps )
84
- if ( typeChecker . getPropertyOfType ( spreadType , allowedProp ) !== undefined ) return
85
86
86
87
// Check if the spread type has a string index signature - this could hide an allowed property
87
88
if ( typeChecker . getIndexTypeOfType ( spreadType , IndexKind . String ) !== undefined ) return
88
89
90
+ const spreadPropNames = typeChecker . getPropertiesOfType ( spreadType ) . map ( prop => prop . getName ( ) )
91
+
92
+ // If an allowed prop gets spread in, this is a valid use of the component
93
+ if ( spreadPropNames . some ( isAllowedProp ) ) return
94
+
89
95
// If there is an `as` inside the spread object, we can't autofix reliably
90
- if ( typeChecker . getPropertyOfType ( spreadType , 'as' ) !== undefined ) asProp = null
96
+ if ( spreadPropNames . includes ( 'as' ) ) asProp = null
91
97
92
98
continue
93
99
}
94
100
95
101
// Has an allowed prop, so should keep using this component
96
- for ( const allowedProp of componentConfig . allowedProps )
97
- if (
98
- attribute . name . type === 'JSXIdentifier' &&
99
- ( attribute . name . name === allowedProp || isStyledSystemProp ( attribute . name . name ) )
100
- )
101
- return
102
+ if ( attribute . name . type === 'JSXIdentifier' && isAllowedProp ( attribute . name . name ) ) return
102
103
103
104
// If there is an `as` prop we will need to account for that when autofixing
104
105
if ( attribute . name . type === 'JSXIdentifier' && attribute . name . name === 'as' ) asProp = attribute
0 commit comments