3
3
const { ESLintUtils} = require ( '@typescript-eslint/utils' )
4
4
const { IndexKind} = require ( 'typescript' )
5
5
const { pick : pickStyledSystemProps } = require ( '@styled-system/props' )
6
+ const { isPrimerComponent} = require ( '../utils/is-primer-component' )
6
7
7
8
/** @typedef {import('@typescript-eslint/types').TSESTree.JSXAttribute } JSXAttribute */
8
9
@@ -36,23 +37,24 @@ const rule = ESLintUtils.RuleCreator.withoutDocs({
36
37
[ components . Text . messageId ] : components . Text . message ,
37
38
} ,
38
39
type : 'problem' ,
39
- schema : [ ] ,
40
+ schema : [
41
+ {
42
+ type : 'object' ,
43
+ properties : {
44
+ skipImportCheck : {
45
+ type : 'boolean' ,
46
+ } ,
47
+ } ,
48
+ additionalProperties : false ,
49
+ } ,
50
+ ] ,
40
51
fixable : 'code' ,
41
52
} ,
42
- defaultOptions : [ ] ,
53
+ defaultOptions : [ { skipImportCheck : false } ] ,
43
54
create ( context ) {
44
- /**
45
- * Cache components that we've verified are imported from @primer/react in this file, to save a bit of time
46
- * @type {Map<string, boolean> }
47
- */
48
- const validatedComponents = new Map ( )
49
-
50
55
return {
51
- JSXElement ( node ) {
52
- const {
53
- openingElement : { name, attributes} ,
54
- closingElement,
55
- } = node
56
+ JSXElement ( { openingElement, closingElement} ) {
57
+ const { name, attributes} = openingElement
56
58
57
59
// Ensure this is one of the components we are looking for. Note this doesn't account for import aliases; this
58
60
// is intentional to avoid having to do the scope tree traversal for every component of every name, which would
@@ -62,28 +64,9 @@ const rule = ESLintUtils.RuleCreator.withoutDocs({
62
64
63
65
// Only continue if the variable declaration is an import from @primer /react. Otherwise it could, for example,
64
66
// be an import from @primer /brand, which would be valid without sx.
65
- let isImportedFromPrimer = validatedComponents . get ( name . name )
66
- if ( isImportedFromPrimer === undefined ) {
67
- // Find the variable declaration for this component
68
- let variable
69
- /** @type {import('@typescript-eslint/utils/ts-eslint').Scope.Scope | undefined } */
70
- let scope = context . sourceCode . getScope ( name )
71
- while ( scope && ! variable ) {
72
- variable = scope . variables . find ( v => v . name === name . name )
73
- scope = scope . upper ?? undefined
74
- }
75
-
76
- isImportedFromPrimer =
77
- variable ?. defs . some (
78
- def =>
79
- def . type === 'ImportBinding' &&
80
- def . parent . type === 'ImportDeclaration' &&
81
- def . parent . source . value === '@primer/react' ,
82
- ) ?? false
83
-
84
- validatedComponents . set ( name . name , isImportedFromPrimer )
85
- }
86
- if ( ! isImportedFromPrimer ) return
67
+ const skipImportCheck = context . options [ 0 ] ?. skipImportCheck
68
+ const isPrimer = skipImportCheck || isPrimerComponent ( name , context . sourceCode . getScope ( openingElement ) )
69
+ if ( ! isPrimer ) return
87
70
88
71
// Validate the attributes and ensure an `sx` prop is present or spreaded in
89
72
/** @type {typeof attributes[number] | undefined | null } */
0 commit comments