@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
@@ -1,5 +1,12 @@
1
1
  # @backstage/eslint-plugin
2
2
 
3
+ ## 0.1.7-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 9ef572d: fix lint rule fixer for more than one `Component + Prop`
8
+ - 3a7eee7: eslint autofix for mui ThemeProvider
9
+
3
10
  ## 0.1.6
4
11
 
5
12
  ### Patch Changes
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.0",
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 propsMatch = /^([A-Z]\w+)Props$/.exec(s.local.name);
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: !(propsMatch !== null),
80
- emitProp: propsMatch !== null,
81
- value: s.local.name,
82
- propValue: propsMatch ? propsMatch[1] : undefined,
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 components = specifiersMap
92
- .filter(f => {
93
- return f.emitComponent;
94
- })
95
- .map(m => m.value);
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.local.name} from '${node.source.value}/${specifier.local.name}';`;
109
+ const replacement = `import ${specifier.value} from '${node.source.value}/${specifier.value}';`;
127
110
  replacements.push(replacement);
128
111
  }
129
112
  }
130
- } else if (
131
- specifiersMap.some(s => s.emitProp) &&
132
- specifiersMap.some(s => s.emitComponent)
133
- ) {
134
- // 3 - Component and Prop
135
- replacements.push(
136
- `import ${components[0]}, { ${props.join(
137
- ', ',
138
- )} } from '@material-ui/core/${components[0]}';`,
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';`,