eslint-plugin-primer-react 8.1.0 → 8.2.0-rc.1772227
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-primer-react",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.2.0-rc.1772227",
|
|
4
4
|
"description": "ESLint rules for Primer React",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"engines": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@styled-system/props": "^5.1.5",
|
|
35
|
-
"@typescript-eslint/utils": "8.39.0",
|
|
35
|
+
"@typescript-eslint/utils": "^8.39.0",
|
|
36
36
|
"eslint-plugin-github": "^6.0.0",
|
|
37
37
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
|
38
38
|
"eslint-traverse": "^1.0.0",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"@github/markdownlint-github": "^0.6.3",
|
|
47
47
|
"@github/prettier-config": "0.0.6",
|
|
48
48
|
"@types/jest": "^30.0.0",
|
|
49
|
-
"@typescript-eslint/rule-tester": "8.
|
|
49
|
+
"@typescript-eslint/rule-tester": "8.42.0",
|
|
50
50
|
"eslint": "^9.0.0",
|
|
51
51
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
|
52
52
|
"eslint-plugin-filenames": "^1.3.2",
|
|
@@ -56,6 +56,48 @@ ruleTester.run('use-styled-react-import', rule, {
|
|
|
56
56
|
],
|
|
57
57
|
},
|
|
58
58
|
|
|
59
|
+
// Invalid: ActionList.Item with sx prop and ActionList imported from @primer/react
|
|
60
|
+
{
|
|
61
|
+
code: `import { ActionList } from '@primer/react'
|
|
62
|
+
const Component = () => <ActionList.Item sx={{ color: 'red' }}>Content</ActionList.Item>`,
|
|
63
|
+
output: `import { ActionList } from '@primer/styled-react'
|
|
64
|
+
const Component = () => <ActionList.Item sx={{ color: 'red' }}>Content</ActionList.Item>`,
|
|
65
|
+
errors: [
|
|
66
|
+
{
|
|
67
|
+
messageId: 'useStyledReactImport',
|
|
68
|
+
data: {componentName: 'ActionList'},
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
// Invalid: FormControl used both with and without sx prop - should move to styled-react
|
|
74
|
+
{
|
|
75
|
+
code: `import { FormControl } from '@primer/react'
|
|
76
|
+
const Component = () => (
|
|
77
|
+
<div>
|
|
78
|
+
<FormControl></FormControl>
|
|
79
|
+
<FormControl sx={{ color: 'red' }}>
|
|
80
|
+
<FormControl.Label visuallyHidden>Label</FormControl.Label>
|
|
81
|
+
</FormControl>
|
|
82
|
+
</div>
|
|
83
|
+
)`,
|
|
84
|
+
output: `import { FormControl } from '@primer/styled-react'
|
|
85
|
+
const Component = () => (
|
|
86
|
+
<div>
|
|
87
|
+
<FormControl></FormControl>
|
|
88
|
+
<FormControl sx={{ color: 'red' }}>
|
|
89
|
+
<FormControl.Label visuallyHidden>Label</FormControl.Label>
|
|
90
|
+
</FormControl>
|
|
91
|
+
</div>
|
|
92
|
+
)`,
|
|
93
|
+
errors: [
|
|
94
|
+
{
|
|
95
|
+
messageId: 'useStyledReactImport',
|
|
96
|
+
data: {componentName: 'FormControl'},
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
|
|
59
101
|
// Invalid: Button with sx prop imported from @primer/react
|
|
60
102
|
{
|
|
61
103
|
code: `import { Button } from '@primer/react'
|
|
@@ -70,6 +112,41 @@ ruleTester.run('use-styled-react-import', rule, {
|
|
|
70
112
|
],
|
|
71
113
|
},
|
|
72
114
|
|
|
115
|
+
// Invalid: ActionList used without sx, ActionList.Item used with sx - should move ActionList to styled-react
|
|
116
|
+
{
|
|
117
|
+
code: `import { ActionList, ActionMenu } from '@primer/react'
|
|
118
|
+
const Component = () => (
|
|
119
|
+
<ActionMenu>
|
|
120
|
+
<ActionMenu.Overlay>
|
|
121
|
+
<ActionList>
|
|
122
|
+
<ActionList.Item sx={{ paddingLeft: 'calc(1 * var(--base-size-12))' }}>
|
|
123
|
+
Item
|
|
124
|
+
</ActionList.Item>
|
|
125
|
+
</ActionList>
|
|
126
|
+
</ActionMenu.Overlay>
|
|
127
|
+
</ActionMenu>
|
|
128
|
+
)`,
|
|
129
|
+
output: `import { ActionMenu } from '@primer/react'
|
|
130
|
+
import { ActionList } from '@primer/styled-react'
|
|
131
|
+
const Component = () => (
|
|
132
|
+
<ActionMenu>
|
|
133
|
+
<ActionMenu.Overlay>
|
|
134
|
+
<ActionList>
|
|
135
|
+
<ActionList.Item sx={{ paddingLeft: 'calc(1 * var(--base-size-12))' }}>
|
|
136
|
+
Item
|
|
137
|
+
</ActionList.Item>
|
|
138
|
+
</ActionList>
|
|
139
|
+
</ActionMenu.Overlay>
|
|
140
|
+
</ActionMenu>
|
|
141
|
+
)`,
|
|
142
|
+
errors: [
|
|
143
|
+
{
|
|
144
|
+
messageId: 'useStyledReactImport',
|
|
145
|
+
data: {componentName: 'ActionList'},
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
|
|
73
150
|
// Invalid: Multiple components, one with sx prop
|
|
74
151
|
{
|
|
75
152
|
code: `import { Button, Box, Avatar } from '@primer/react'
|
|
@@ -138,7 +215,7 @@ import { Button } from '@primer/styled-react'
|
|
|
138
215
|
],
|
|
139
216
|
},
|
|
140
217
|
|
|
141
|
-
// Invalid: <Link /> and <
|
|
218
|
+
// Invalid: <Link /> and <Button /> imported from styled-react but used without sx prop
|
|
142
219
|
{
|
|
143
220
|
code: `import { Button } from '@primer/react'
|
|
144
221
|
import { Button as StyledButton, Link } from '@primer/styled-react'
|
|
@@ -155,7 +232,7 @@ import { Button as StyledButton, Link } from '@primer/styled-react'
|
|
|
155
232
|
<div>
|
|
156
233
|
<Link />
|
|
157
234
|
<Button>Regular button</Button>
|
|
158
|
-
<
|
|
235
|
+
<StyledButton>Styled button</StyledButton>
|
|
159
236
|
</div>
|
|
160
237
|
)`,
|
|
161
238
|
errors: [
|
|
@@ -167,10 +244,6 @@ import { Button as StyledButton, Link } from '@primer/styled-react'
|
|
|
167
244
|
messageId: 'usePrimerReactImport',
|
|
168
245
|
data: {componentName: 'Link'},
|
|
169
246
|
},
|
|
170
|
-
{
|
|
171
|
-
messageId: 'usePrimerReactImport',
|
|
172
|
-
data: {componentName: 'Button'},
|
|
173
|
-
},
|
|
174
247
|
],
|
|
175
248
|
},
|
|
176
249
|
|
|
@@ -213,7 +286,7 @@ import { Button } from '@primer/react'
|
|
|
213
286
|
],
|
|
214
287
|
},
|
|
215
288
|
|
|
216
|
-
// Invalid: Button used
|
|
289
|
+
// Invalid: Button and Link used with sx prop - should move both to styled-react
|
|
217
290
|
{
|
|
218
291
|
code: `import { Button, Link } from '@primer/react'
|
|
219
292
|
const Component = () => (
|
|
@@ -223,27 +296,83 @@ import { Button } from '@primer/react'
|
|
|
223
296
|
<Button sx={{ color: 'red' }}>Styled button</Button>
|
|
224
297
|
</div>
|
|
225
298
|
)`,
|
|
226
|
-
output: `import { Button } from '@primer/react'
|
|
227
|
-
import { Button as StyledButton, Link } from '@primer/styled-react'
|
|
299
|
+
output: `import { Link, Button } from '@primer/styled-react'
|
|
228
300
|
const Component = () => (
|
|
229
301
|
<div>
|
|
230
302
|
<Link sx={{ color: 'red' }} />
|
|
231
303
|
<Button>Regular button</Button>
|
|
232
|
-
<
|
|
304
|
+
<Button sx={{ color: 'red' }}>Styled button</Button>
|
|
233
305
|
</div>
|
|
234
306
|
)`,
|
|
235
307
|
errors: [
|
|
236
308
|
{
|
|
237
|
-
messageId: '
|
|
238
|
-
data: {componentName: 'Button'
|
|
309
|
+
messageId: 'useStyledReactImport',
|
|
310
|
+
data: {componentName: 'Button'},
|
|
239
311
|
},
|
|
240
312
|
{
|
|
241
313
|
messageId: 'useStyledReactImport',
|
|
242
314
|
data: {componentName: 'Link'},
|
|
243
315
|
},
|
|
316
|
+
],
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
// Test configuration options
|
|
322
|
+
ruleTester.run('use-styled-react-import with custom configuration', rule, {
|
|
323
|
+
valid: [
|
|
324
|
+
// Valid: Custom component not in default list
|
|
325
|
+
{
|
|
326
|
+
code: `import { CustomButton } from '@primer/react'
|
|
327
|
+
const Component = () => <CustomButton sx={{ color: 'red' }}>Click me</CustomButton>`,
|
|
328
|
+
options: [{}], // Using default configuration
|
|
329
|
+
},
|
|
330
|
+
|
|
331
|
+
// Valid: Custom component in custom list used without sx prop
|
|
332
|
+
{
|
|
333
|
+
code: `import { CustomButton } from '@primer/react'
|
|
334
|
+
const Component = () => <CustomButton>Click me</CustomButton>`,
|
|
335
|
+
options: [{styledComponents: ['CustomButton']}],
|
|
336
|
+
},
|
|
337
|
+
|
|
338
|
+
// Valid: Custom component with sx prop imported from styled-react
|
|
339
|
+
{
|
|
340
|
+
code: `import { CustomButton } from '@primer/styled-react'
|
|
341
|
+
const Component = () => <CustomButton sx={{ color: 'red' }}>Click me</CustomButton>`,
|
|
342
|
+
options: [{styledComponents: ['CustomButton']}],
|
|
343
|
+
},
|
|
344
|
+
|
|
345
|
+
// Valid: Box not in custom list, so sx usage is allowed from @primer/react
|
|
346
|
+
{
|
|
347
|
+
code: `import { Box } from '@primer/react'
|
|
348
|
+
const Component = () => <Box sx={{ color: 'red' }}>Content</Box>`,
|
|
349
|
+
options: [{styledComponents: ['CustomButton']}], // Box not included
|
|
350
|
+
},
|
|
351
|
+
],
|
|
352
|
+
invalid: [
|
|
353
|
+
// Invalid: Custom component with sx prop should be from styled-react
|
|
354
|
+
{
|
|
355
|
+
code: `import { CustomButton } from '@primer/react'
|
|
356
|
+
const Component = () => <CustomButton sx={{ color: 'red' }}>Click me</CustomButton>`,
|
|
357
|
+
output: `import { CustomButton } from '@primer/styled-react'
|
|
358
|
+
const Component = () => <CustomButton sx={{ color: 'red' }}>Click me</CustomButton>`,
|
|
359
|
+
options: [{styledComponents: ['CustomButton']}],
|
|
360
|
+
errors: [
|
|
361
|
+
{
|
|
362
|
+
messageId: 'useStyledReactImport',
|
|
363
|
+
data: {componentName: 'CustomButton'},
|
|
364
|
+
},
|
|
365
|
+
],
|
|
366
|
+
},
|
|
367
|
+
// Invalid: Custom utility should be from styled-react
|
|
368
|
+
{
|
|
369
|
+
code: `import { customSx } from '@primer/react'`,
|
|
370
|
+
output: `import { customSx } from '@primer/styled-react'`,
|
|
371
|
+
options: [{styledUtilities: ['customSx']}],
|
|
372
|
+
errors: [
|
|
244
373
|
{
|
|
245
|
-
messageId: '
|
|
246
|
-
data: {
|
|
374
|
+
messageId: 'moveToStyledReact',
|
|
375
|
+
data: {importName: 'customSx'},
|
|
247
376
|
},
|
|
248
377
|
],
|
|
249
378
|
},
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
const url = require('../url')
|
|
4
4
|
const {getJSXOpeningElementName} = require('../utils/get-jsx-opening-element-name')
|
|
5
5
|
|
|
6
|
-
//
|
|
7
|
-
const
|
|
6
|
+
// Default components that should be imported from @primer/styled-react when used with sx prop
|
|
7
|
+
const defaultStyledComponents = [
|
|
8
8
|
'ActionList',
|
|
9
9
|
'ActionMenu',
|
|
10
10
|
'Box',
|
|
@@ -23,13 +23,13 @@ const styledComponents = new Set([
|
|
|
23
23
|
'Truncate',
|
|
24
24
|
'Octicon',
|
|
25
25
|
'Dialog',
|
|
26
|
-
]
|
|
26
|
+
]
|
|
27
27
|
|
|
28
|
-
//
|
|
29
|
-
const
|
|
28
|
+
// Default types that should be imported from @primer/styled-react
|
|
29
|
+
const defaultStyledTypes = ['BoxProps', 'SxProp', 'BetterSystemStyleObject']
|
|
30
30
|
|
|
31
|
-
//
|
|
32
|
-
const
|
|
31
|
+
// Default utilities that should be imported from @primer/styled-react
|
|
32
|
+
const defaultStyledUtilities = ['sx']
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* @type {import('eslint').Rule.RuleModule}
|
|
@@ -43,25 +43,46 @@ module.exports = {
|
|
|
43
43
|
url: url(module),
|
|
44
44
|
},
|
|
45
45
|
fixable: 'code',
|
|
46
|
-
schema: [
|
|
46
|
+
schema: [
|
|
47
|
+
{
|
|
48
|
+
type: 'object',
|
|
49
|
+
properties: {
|
|
50
|
+
styledComponents: {
|
|
51
|
+
type: 'array',
|
|
52
|
+
items: {type: 'string'},
|
|
53
|
+
description: 'Components that should be imported from @primer/styled-react when used with sx prop',
|
|
54
|
+
},
|
|
55
|
+
styledTypes: {
|
|
56
|
+
type: 'array',
|
|
57
|
+
items: {type: 'string'},
|
|
58
|
+
description: 'Types that should be imported from @primer/styled-react',
|
|
59
|
+
},
|
|
60
|
+
styledUtilities: {
|
|
61
|
+
type: 'array',
|
|
62
|
+
items: {type: 'string'},
|
|
63
|
+
description: 'Utilities that should be imported from @primer/styled-react',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
additionalProperties: false,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
47
69
|
messages: {
|
|
48
70
|
useStyledReactImport: 'Import {{ componentName }} from "@primer/styled-react" when using with sx prop',
|
|
49
|
-
useStyledReactImportWithAlias:
|
|
50
|
-
'Import {{ componentName }} as {{ aliasName }} from "@primer/styled-react" when using with sx prop (conflicts with non-sx usage)',
|
|
51
|
-
useAliasedComponent: 'Use {{ aliasName }} instead of {{ componentName }} when using sx prop',
|
|
52
71
|
moveToStyledReact: 'Move {{ importName }} import to "@primer/styled-react"',
|
|
53
72
|
usePrimerReactImport: 'Import {{ componentName }} from "@primer/react" when not using sx prop',
|
|
54
73
|
},
|
|
55
74
|
},
|
|
56
75
|
create(context) {
|
|
76
|
+
// Get configuration options or use defaults
|
|
77
|
+
const options = context.options[0] || {}
|
|
78
|
+
const styledComponents = new Set(options.styledComponents || defaultStyledComponents)
|
|
79
|
+
const styledTypes = new Set(options.styledTypes || defaultStyledTypes)
|
|
80
|
+
const styledUtilities = new Set(options.styledUtilities || defaultStyledUtilities)
|
|
57
81
|
const componentsWithSx = new Set()
|
|
58
82
|
const componentsWithoutSx = new Set() // Track components used without sx
|
|
59
83
|
const allUsedComponents = new Set() // Track all used components
|
|
60
84
|
const primerReactImports = new Map() // Map of component name to import node
|
|
61
85
|
const styledReactImports = new Map() // Map of components imported from styled-react to import node
|
|
62
|
-
const aliasMapping = new Map() // Map local name to original component name for aliased imports
|
|
63
|
-
const jsxElementsWithSx = [] // Track JSX elements that use sx prop
|
|
64
|
-
const jsxElementsWithoutSx = [] // Track JSX elements that don't use sx prop
|
|
65
86
|
|
|
66
87
|
return {
|
|
67
88
|
ImportDeclaration(node) {
|
|
@@ -86,13 +107,7 @@ module.exports = {
|
|
|
86
107
|
for (const specifier of node.specifiers) {
|
|
87
108
|
if (specifier.type === 'ImportSpecifier') {
|
|
88
109
|
const importedName = specifier.imported.name
|
|
89
|
-
const localName = specifier.local.name
|
|
90
110
|
styledReactImports.set(importedName, {node, specifier})
|
|
91
|
-
|
|
92
|
-
// Track alias mapping for styled-react imports
|
|
93
|
-
if (localName !== importedName) {
|
|
94
|
-
aliasMapping.set(localName, importedName)
|
|
95
|
-
}
|
|
96
111
|
}
|
|
97
112
|
}
|
|
98
113
|
}
|
|
@@ -102,12 +117,12 @@ module.exports = {
|
|
|
102
117
|
const openingElement = node.openingElement
|
|
103
118
|
const componentName = getJSXOpeningElementName(openingElement)
|
|
104
119
|
|
|
105
|
-
//
|
|
106
|
-
const
|
|
120
|
+
// For compound components like "ActionList.Item", we need to check the parent component
|
|
121
|
+
const parentComponentName = componentName.includes('.') ? componentName.split('.')[0] : componentName
|
|
107
122
|
|
|
108
123
|
// Track all used components that are in our styled components list
|
|
109
|
-
if (styledComponents.has(
|
|
110
|
-
allUsedComponents.add(
|
|
124
|
+
if (styledComponents.has(parentComponentName)) {
|
|
125
|
+
allUsedComponents.add(parentComponentName)
|
|
111
126
|
|
|
112
127
|
// Check if this component has an sx prop
|
|
113
128
|
const hasSxProp = openingElement.attributes.some(
|
|
@@ -115,20 +130,9 @@ module.exports = {
|
|
|
115
130
|
)
|
|
116
131
|
|
|
117
132
|
if (hasSxProp) {
|
|
118
|
-
componentsWithSx.add(
|
|
119
|
-
jsxElementsWithSx.push({node, componentName: originalComponentName, openingElement})
|
|
133
|
+
componentsWithSx.add(parentComponentName)
|
|
120
134
|
} else {
|
|
121
|
-
componentsWithoutSx.add(
|
|
122
|
-
|
|
123
|
-
// If this is an aliased component without sx, we need to track it for renaming
|
|
124
|
-
if (aliasMapping.has(componentName)) {
|
|
125
|
-
jsxElementsWithoutSx.push({
|
|
126
|
-
node,
|
|
127
|
-
localName: componentName,
|
|
128
|
-
originalName: originalComponentName,
|
|
129
|
-
openingElement,
|
|
130
|
-
})
|
|
131
|
-
}
|
|
135
|
+
componentsWithoutSx.add(parentComponentName)
|
|
132
136
|
}
|
|
133
137
|
}
|
|
134
138
|
},
|
|
@@ -141,23 +145,16 @@ module.exports = {
|
|
|
141
145
|
for (const componentName of componentsWithSx) {
|
|
142
146
|
const importInfo = primerReactImports.get(componentName)
|
|
143
147
|
if (importInfo && !styledReactImports.has(componentName)) {
|
|
144
|
-
const hasConflict = componentsWithoutSx.has(componentName)
|
|
145
148
|
const {node: importNode} = importInfo
|
|
146
149
|
|
|
147
150
|
if (!importNodeChanges.has(importNode)) {
|
|
148
151
|
importNodeChanges.set(importNode, {
|
|
149
152
|
toMove: [],
|
|
150
|
-
toAlias: [],
|
|
151
153
|
originalSpecifiers: [...importNode.specifiers],
|
|
152
154
|
})
|
|
153
155
|
}
|
|
154
156
|
|
|
155
|
-
|
|
156
|
-
if (hasConflict) {
|
|
157
|
-
changes.toAlias.push(componentName)
|
|
158
|
-
} else {
|
|
159
|
-
changes.toMove.push(componentName)
|
|
160
|
-
}
|
|
157
|
+
importNodeChanges.get(importNode).toMove.push(componentName)
|
|
161
158
|
}
|
|
162
159
|
}
|
|
163
160
|
|
|
@@ -165,15 +162,12 @@ module.exports = {
|
|
|
165
162
|
for (const componentName of componentsWithSx) {
|
|
166
163
|
const importInfo = primerReactImports.get(componentName)
|
|
167
164
|
if (importInfo && !styledReactImports.has(componentName)) {
|
|
168
|
-
// Check if this component is also used without sx prop (conflict scenario)
|
|
169
|
-
const hasConflict = componentsWithoutSx.has(componentName)
|
|
170
|
-
|
|
171
165
|
context.report({
|
|
172
166
|
node: importInfo.specifier,
|
|
173
|
-
messageId:
|
|
174
|
-
data:
|
|
167
|
+
messageId: 'useStyledReactImport',
|
|
168
|
+
data: {componentName},
|
|
175
169
|
fix(fixer) {
|
|
176
|
-
const {node: importNode
|
|
170
|
+
const {node: importNode} = importInfo
|
|
177
171
|
const changes = importNodeChanges.get(importNode)
|
|
178
172
|
|
|
179
173
|
if (!changes) {
|
|
@@ -181,10 +175,7 @@ module.exports = {
|
|
|
181
175
|
}
|
|
182
176
|
|
|
183
177
|
// Only apply the fix once per import node (for the first component processed)
|
|
184
|
-
const isFirstComponent =
|
|
185
|
-
changes.originalSpecifiers[0] === specifier ||
|
|
186
|
-
(changes.toMove.length > 0 && changes.toMove[0] === componentName) ||
|
|
187
|
-
(changes.toAlias.length > 0 && changes.toAlias[0] === componentName)
|
|
178
|
+
const isFirstComponent = changes.toMove[0] === componentName
|
|
188
179
|
|
|
189
180
|
if (!isFirstComponent) {
|
|
190
181
|
return null
|
|
@@ -196,27 +187,13 @@ module.exports = {
|
|
|
196
187
|
// Find specifiers that remain in original import
|
|
197
188
|
const remainingSpecifiers = changes.originalSpecifiers.filter(spec => {
|
|
198
189
|
const name = spec.imported.name
|
|
199
|
-
// Keep components that are not being moved (only aliased components stay for non-sx usage)
|
|
200
190
|
return !componentsToMove.has(name)
|
|
201
191
|
})
|
|
202
192
|
|
|
203
|
-
// If no components remain, replace with new
|
|
193
|
+
// If no components remain, replace with new import directly
|
|
204
194
|
if (remainingSpecifiers.length === 0) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
// Add imports for moved components
|
|
209
|
-
for (const componentName of changes.toMove) {
|
|
210
|
-
newImports.push(`import { ${componentName} } from '@primer/styled-react'`)
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Add aliased imports for conflicted components
|
|
214
|
-
for (const componentName of changes.toAlias) {
|
|
215
|
-
const aliasName = `Styled${componentName}`
|
|
216
|
-
newImports.push(`import { ${componentName} as ${aliasName} } from '@primer/styled-react'`)
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
fixes.push(fixer.replaceText(importNode, newImports.join('\n')))
|
|
195
|
+
const movedComponents = changes.toMove.join(', ')
|
|
196
|
+
fixes.push(fixer.replaceText(importNode, `import { ${movedComponents} } from '@primer/styled-react'`))
|
|
220
197
|
} else {
|
|
221
198
|
// Otherwise, update the import to only include remaining components
|
|
222
199
|
const remainingNames = remainingSpecifiers.map(spec => spec.imported.name)
|
|
@@ -224,56 +201,11 @@ module.exports = {
|
|
|
224
201
|
fixer.replaceText(importNode, `import { ${remainingNames.join(', ')} } from '@primer/react'`),
|
|
225
202
|
)
|
|
226
203
|
|
|
227
|
-
//
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
const aliasName = `Styled${componentName}`
|
|
233
|
-
styledReactImports.push(`${componentName} as ${aliasName}`)
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Add moved components second
|
|
237
|
-
for (const componentName of changes.toMove) {
|
|
238
|
-
styledReactImports.push(componentName)
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (styledReactImports.length > 0) {
|
|
242
|
-
fixes.push(
|
|
243
|
-
fixer.insertTextAfter(
|
|
244
|
-
importNode,
|
|
245
|
-
`\nimport { ${styledReactImports.join(', ')} } from '@primer/styled-react'`,
|
|
246
|
-
),
|
|
247
|
-
)
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return fixes
|
|
252
|
-
},
|
|
253
|
-
})
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Report on JSX elements that should use aliased components
|
|
258
|
-
for (const {node: jsxNode, componentName, openingElement} of jsxElementsWithSx) {
|
|
259
|
-
const hasConflict = componentsWithoutSx.has(componentName)
|
|
260
|
-
const isImportedFromPrimerReact = primerReactImports.has(componentName)
|
|
261
|
-
|
|
262
|
-
if (hasConflict && isImportedFromPrimerReact && !styledReactImports.has(componentName)) {
|
|
263
|
-
const aliasName = `Styled${componentName}`
|
|
264
|
-
context.report({
|
|
265
|
-
node: openingElement,
|
|
266
|
-
messageId: 'useAliasedComponent',
|
|
267
|
-
data: {componentName, aliasName},
|
|
268
|
-
fix(fixer) {
|
|
269
|
-
const fixes = []
|
|
270
|
-
|
|
271
|
-
// Replace the component name in the JSX opening tag
|
|
272
|
-
fixes.push(fixer.replaceText(openingElement.name, aliasName))
|
|
273
|
-
|
|
274
|
-
// Replace the component name in the JSX closing tag if it exists
|
|
275
|
-
if (jsxNode.closingElement) {
|
|
276
|
-
fixes.push(fixer.replaceText(jsxNode.closingElement.name, aliasName))
|
|
204
|
+
// Add new styled-react import
|
|
205
|
+
const movedComponents = changes.toMove.join(', ')
|
|
206
|
+
fixes.push(
|
|
207
|
+
fixer.insertTextAfter(importNode, `\nimport { ${movedComponents} } from '@primer/styled-react'`),
|
|
208
|
+
)
|
|
277
209
|
}
|
|
278
210
|
|
|
279
211
|
return fixes
|
|
@@ -403,30 +335,6 @@ module.exports = {
|
|
|
403
335
|
}
|
|
404
336
|
}
|
|
405
337
|
|
|
406
|
-
// Report and fix JSX elements that use aliased components without sx prop
|
|
407
|
-
for (const {node: jsxNode, originalName, openingElement} of jsxElementsWithoutSx) {
|
|
408
|
-
if (!componentsWithSx.has(originalName) && styledReactImports.has(originalName)) {
|
|
409
|
-
context.report({
|
|
410
|
-
node: openingElement,
|
|
411
|
-
messageId: 'usePrimerReactImport',
|
|
412
|
-
data: {componentName: originalName},
|
|
413
|
-
fix(fixer) {
|
|
414
|
-
const fixes = []
|
|
415
|
-
|
|
416
|
-
// Replace the aliased component name with the original component name in JSX opening tag
|
|
417
|
-
fixes.push(fixer.replaceText(openingElement.name, originalName))
|
|
418
|
-
|
|
419
|
-
// Replace the aliased component name in JSX closing tag if it exists
|
|
420
|
-
if (jsxNode.closingElement) {
|
|
421
|
-
fixes.push(fixer.replaceText(jsxNode.closingElement.name, originalName))
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
return fixes
|
|
425
|
-
},
|
|
426
|
-
})
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
338
|
// Also report for types and utilities that should always be from styled-react
|
|
431
339
|
for (const [importName, importInfo] of primerReactImports) {
|
|
432
340
|
if ((styledTypes.has(importName) || styledUtilities.has(importName)) && !styledReactImports.has(importName)) {
|