@backstage/eslint-plugin 0.1.6 → 0.1.7-next.0
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/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/eslint-plugin",
|
|
3
|
+
"version": "0.1.7-next.0",
|
|
3
4
|
"description": "Backstage ESLint plugin",
|
|
4
|
-
"version": "0.1.6",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"minimatch": "^9.0.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@backstage/cli": "^0.26.
|
|
25
|
+
"@backstage/cli": "^0.26.3-next.1",
|
|
26
26
|
"eslint": "^8.33.0"
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -23,6 +23,7 @@ const KNOWN_STYLES = [
|
|
|
23
23
|
'styled',
|
|
24
24
|
'useTheme',
|
|
25
25
|
'Theme',
|
|
26
|
+
'ThemeProvider',
|
|
26
27
|
];
|
|
27
28
|
|
|
28
29
|
/** @type {import('eslint').Rule.RuleModule} */
|
|
@@ -73,70 +74,55 @@ module.exports = {
|
|
|
73
74
|
);
|
|
74
75
|
|
|
75
76
|
const specifiersMap = specifiers.map(s => {
|
|
76
|
-
const
|
|
77
|
+
const value = s.local.name;
|
|
78
|
+
const propsMatch = /^([A-Z]\w+)Props$/.exec(value);
|
|
79
|
+
|
|
80
|
+
const emitProp = propsMatch !== null;
|
|
81
|
+
const emitComponent = !emitProp;
|
|
82
|
+
const emitComponentAndProp =
|
|
83
|
+
emitProp && specifiers.some(s => s.local.name === propsMatch[1]);
|
|
77
84
|
|
|
78
85
|
return {
|
|
79
|
-
emitComponent:
|
|
80
|
-
emitProp
|
|
81
|
-
value
|
|
82
|
-
|
|
86
|
+
emitComponent: emitComponent || emitComponentAndProp,
|
|
87
|
+
emitProp,
|
|
88
|
+
value,
|
|
89
|
+
componentValue: propsMatch ? propsMatch[1] : undefined,
|
|
83
90
|
};
|
|
84
91
|
});
|
|
85
92
|
|
|
93
|
+
// Filter out duplicates where we have both component and component+prop
|
|
94
|
+
const filteredMap = specifiersMap.filter(
|
|
95
|
+
f => !specifiersMap.some(s => f.value === s.componentValue),
|
|
96
|
+
);
|
|
97
|
+
|
|
86
98
|
// We have 3 cases:
|
|
87
99
|
// 1 - Just Prop: import { TabProps } from '@material-ui/core';
|
|
88
100
|
// 2 - Just Component: import { Box } from '@material-ui/core';
|
|
89
101
|
// 3 - Component and Prop: import { SvgIcon, SvgIconProps } from '@material-ui/core';
|
|
90
102
|
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const props = specifiersMap
|
|
97
|
-
.filter(f => {
|
|
98
|
-
return f.emitProp;
|
|
99
|
-
})
|
|
100
|
-
.map(m => m.value);
|
|
101
|
-
|
|
102
|
-
if (
|
|
103
|
-
specifiersMap.some(s => s.emitProp) &&
|
|
104
|
-
!specifiersMap.some(s => s.emitComponent)
|
|
105
|
-
) {
|
|
106
|
-
// 1 - Just Prop
|
|
107
|
-
const propValue = specifiersMap
|
|
108
|
-
.filter(f => {
|
|
109
|
-
return f.emitProp;
|
|
110
|
-
})
|
|
111
|
-
.map(m => m.propValue);
|
|
112
|
-
replacements.push(
|
|
113
|
-
`import { ${props.join(', ')} } from '@material-ui/core/${
|
|
114
|
-
propValue[0]
|
|
115
|
-
}';`,
|
|
116
|
-
);
|
|
117
|
-
} else if (
|
|
118
|
-
!specifiersMap.some(s => s.emitProp) &&
|
|
119
|
-
specifiersMap.some(s => s.emitComponent)
|
|
120
|
-
) {
|
|
121
|
-
// 2 - Just Component
|
|
122
|
-
for (const specifier of specifiers) {
|
|
123
|
-
if (KNOWN_STYLES.includes(specifier.local.name)) {
|
|
124
|
-
styles.push(specifier.local.name);
|
|
103
|
+
for (const specifier of filteredMap) {
|
|
104
|
+
// Just Component
|
|
105
|
+
if (specifier.emitComponent && !specifier.emitProp) {
|
|
106
|
+
if (KNOWN_STYLES.includes(specifier.value)) {
|
|
107
|
+
styles.push(specifier.value);
|
|
125
108
|
} else {
|
|
126
|
-
const replacement = `import ${specifier.
|
|
109
|
+
const replacement = `import ${specifier.value} from '${node.source.value}/${specifier.value}';`;
|
|
127
110
|
replacements.push(replacement);
|
|
128
111
|
}
|
|
129
112
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
113
|
+
|
|
114
|
+
// Just Prop
|
|
115
|
+
if (specifier.emitProp && !specifier.emitComponent) {
|
|
116
|
+
const replacement = `import { ${specifier.value} } from '@material-ui/core/${specifier.componentValue}';`;
|
|
117
|
+
replacements.push(replacement);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Component and Prop
|
|
121
|
+
if (specifier.emitComponent && specifier.emitProp) {
|
|
122
|
+
replacements.push(
|
|
123
|
+
`import ${specifier.componentValue}, { ${specifier.value} } from '@material-ui/core/${specifier.componentValue}';`,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
140
126
|
}
|
|
141
127
|
|
|
142
128
|
if (styles.length > 0) {
|
|
@@ -57,6 +57,23 @@ import Typography from '@material-ui/core/Typography';`,
|
|
|
57
57
|
errors: [{ messageId: 'topLevelImport' }],
|
|
58
58
|
output: `import Box from '@material-ui/core/Box';`,
|
|
59
59
|
},
|
|
60
|
+
{
|
|
61
|
+
code: `import { ThemeProvider } from '@material-ui/core';`,
|
|
62
|
+
errors: [{ messageId: 'topLevelImport' }],
|
|
63
|
+
output: `import { ThemeProvider } from '@material-ui/core/styles';`,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
code: `import { Grid, GridProps, Theme, makeStyles } from '@material-ui/core';`,
|
|
67
|
+
errors: [{ messageId: 'topLevelImport' }],
|
|
68
|
+
output: `import Grid, { GridProps } from '@material-ui/core/Grid';
|
|
69
|
+
import { Theme, makeStyles } from '@material-ui/core/styles';`,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
code: `import { Grid, GridProps, SvgIcon, SvgIconProps } from '@material-ui/core';`,
|
|
73
|
+
errors: [{ messageId: 'topLevelImport' }],
|
|
74
|
+
output: `import Grid, { GridProps } from '@material-ui/core/Grid';
|
|
75
|
+
import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon';`,
|
|
76
|
+
},
|
|
60
77
|
{
|
|
61
78
|
code: `import {
|
|
62
79
|
Box,
|
|
@@ -65,6 +82,7 @@ import Typography from '@material-ui/core/Typography';`,
|
|
|
65
82
|
DialogTitle,
|
|
66
83
|
Grid,
|
|
67
84
|
makeStyles,
|
|
85
|
+
ThemeProvider,
|
|
68
86
|
} from '@material-ui/core';`,
|
|
69
87
|
errors: [{ messageId: 'topLevelImport' }],
|
|
70
88
|
output: `import Box from '@material-ui/core/Box';
|
|
@@ -72,7 +90,7 @@ import DialogActions from '@material-ui/core/DialogActions';
|
|
|
72
90
|
import DialogContent from '@material-ui/core/DialogContent';
|
|
73
91
|
import DialogTitle from '@material-ui/core/DialogTitle';
|
|
74
92
|
import Grid from '@material-ui/core/Grid';
|
|
75
|
-
import { makeStyles } from '@material-ui/core/styles';`,
|
|
93
|
+
import { makeStyles, ThemeProvider } from '@material-ui/core/styles';`,
|
|
76
94
|
},
|
|
77
95
|
{
|
|
78
96
|
code: `import { Box, Button, makeStyles } from '@material-ui/core';`,
|