@mui/internal-code-infra 0.0.2-canary.52 → 0.0.2-canary.54

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": "@mui/internal-code-infra",
3
- "version": "0.0.2-canary.52",
3
+ "version": "0.0.2-canary.54",
4
4
  "description": "Infra scripts and configs to be used across MUI repos.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -21,13 +21,15 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@argos-ci/core": "^4.0.3",
24
+ "@babel/cli": "^7.28.3",
24
25
  "@babel/core": "^7.28.3",
25
- "@babel/plugin-transform-runtime": "^7.28.3",
26
26
  "@babel/plugin-syntax-typescript": "^7.27.1",
27
+ "@babel/plugin-transform-runtime": "^7.28.3",
27
28
  "@babel/preset-env": "^7.28.3",
28
29
  "@babel/preset-react": "^7.27.1",
29
30
  "@babel/preset-typescript": "^7.27.1",
30
31
  "@eslint/compat": "^1.3.2",
32
+ "@eslint/js": "^9.33.0",
31
33
  "@next/eslint-plugin-next": "^15.4.6",
32
34
  "@octokit/rest": "^22.0.0",
33
35
  "@pnpm/find-workspace-dir": "^1000.1.2",
@@ -36,8 +38,6 @@
36
38
  "babel-plugin-transform-react-remove-prop-types": "^0.4.24",
37
39
  "babel-plugin-transform-remove-imports": "^1.8.0",
38
40
  "chalk": "^5.5.0",
39
- "eslint-config-airbnb": "^19.0.4",
40
- "eslint-config-airbnb-base": "^15.0.0",
41
41
  "eslint-config-prettier": "^10.1.8",
42
42
  "eslint-import-resolver-typescript": "^4.4.4",
43
43
  "eslint-module-utils": "^2.12.1",
@@ -57,13 +57,14 @@
57
57
  "semver": "^7.7.2",
58
58
  "typescript-eslint": "^8.39.1",
59
59
  "yargs": "^18.0.0",
60
- "@mui/internal-babel-plugin-display-name": "1.0.4-canary.4",
60
+ "@mui/internal-babel-plugin-display-name": "1.0.4-canary.5",
61
61
  "@mui/internal-babel-plugin-minify-errors": "2.0.8-canary.6",
62
- "@mui/internal-babel-plugin-resolve-imports": "2.0.7-canary.16"
62
+ "@mui/internal-babel-plugin-resolve-imports": "2.0.7-canary.17"
63
63
  },
64
64
  "peerDependencies": {
65
65
  "eslint": "^9.0.0",
66
- "prettier": "^3.5.3"
66
+ "prettier": "^3.5.3",
67
+ "typescript": "^5.0.0"
67
68
  },
68
69
  "devDependencies": {
69
70
  "@types/babel__core": "^7.20.5",
@@ -89,7 +90,7 @@
89
90
  "publishConfig": {
90
91
  "access": "public"
91
92
  },
92
- "gitSha": "eca4b1b3b0d63fff48e756a7d6264bae3877fa50",
93
+ "gitSha": "79ad58df711429581fc497ec6344e9c16c9f7de5",
93
94
  "scripts": {
94
95
  "typescript": "tsc -p tsconfig.json",
95
96
  "test": "pnpm -w test --project @mui/internal-code-infra",
package/src/cli/babel.mjs CHANGED
@@ -134,11 +134,13 @@ export async function babelBuild({
134
134
  };
135
135
  const res = await $({
136
136
  stdio: 'inherit',
137
+ preferLocal: true,
138
+ localDir: import.meta.dirname,
137
139
  env: {
138
140
  ...process.env,
139
141
  ...env,
140
142
  },
141
- })`pnpm babel --config-file ${configFile} --extensions ${TO_TRANSFORM_EXTENSIONS.join(',')} ${sourceDir} --out-dir ${outDir} --ignore ${BASE_IGNORES.concat(ignores).join(',')} --out-file-extension ${outExtension !== '.js' ? outExtension : '.js'} --compact ${hasLargeFiles ? 'false' : 'auto'}`;
143
+ })`babel --config-file ${configFile} --extensions ${TO_TRANSFORM_EXTENSIONS.join(',')} ${sourceDir} --out-dir ${outDir} --ignore ${BASE_IGNORES.concat(ignores).join(',')} --out-file-extension ${outExtension !== '.js' ? outExtension : '.js'} --compact ${hasLargeFiles ? 'false' : 'auto'}`;
142
144
 
143
145
  if (res.stderr) {
144
146
  throw new Error(`Command: '${res.escapedCommand}' failed with \n${res.stderr}`);
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable no-console */
2
2
  import { $ } from 'execa';
3
- import { globby } from 'globby';
4
3
  import set from 'lodash-es/set.js';
5
4
  import * as fs from 'node:fs/promises';
6
5
  import * as path from 'node:path';
@@ -307,6 +306,8 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
307
306
 
308
307
  console.log(`Selected output directory: "${buildDirBase}"`);
309
308
 
309
+ await fs.rm(buildDir, { recursive: true, force: true });
310
+
310
311
  let babelRuntimeVersion = packageJson.dependencies['@babel/runtime'];
311
312
  if (babelRuntimeVersion === 'catalog:') {
312
313
  // resolve the version from the given package
@@ -423,16 +424,5 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
423
424
  outputDir: buildDir,
424
425
  addTypes: buildTypes,
425
426
  });
426
-
427
- // cleanup
428
- const tsbuildinfo = await globby('**/*.tsbuildinfo', {
429
- absolute: true,
430
- cwd: buildDir,
431
- });
432
- await Promise.all(
433
- tsbuildinfo.map(async (file) => {
434
- await fs.rm(file);
435
- }),
436
- );
437
427
  },
438
428
  });
@@ -17,8 +17,17 @@ const $$ = $({ stdio: 'inherit' });
17
17
  * @param {string} outDir - The output directory for the declaration files.
18
18
  */
19
19
  export async function emitDeclarations(tsconfig, outDir) {
20
- console.log(`Building types for ${tsconfig} in ${outDir}`);
21
- await $$`tsc -p ${tsconfig} --outDir ${outDir} --declaration --emitDeclarationOnly`;
20
+ const tsconfigDir = path.dirname(tsconfig);
21
+ const rootDir = path.resolve(tsconfigDir, './src');
22
+ await $$`tsc
23
+ -p ${tsconfig}
24
+ --rootDir ${rootDir}
25
+ --outDir ${outDir}
26
+ --declaration
27
+ --emitDeclarationOnly
28
+ --noEmit false
29
+ --composite false
30
+ --incremental false`;
22
31
  }
23
32
 
24
33
  /**
@@ -137,6 +146,7 @@ export async function createTypes({ bundles, srcDir, buildDir, cwd, skipTsc, isM
137
146
  `The package root is '${cwd}'`,
138
147
  );
139
148
  }
149
+ console.log(`Building types for ${tsconfigPath} in ${tmpDir}`);
140
150
  await emitDeclarations(tsconfigPath, tmpDir);
141
151
  }
142
152
 
@@ -1,14 +1,16 @@
1
1
  import { includeIgnoreFile } from '@eslint/compat';
2
+ import eslintJs from '@eslint/js';
2
3
  import prettier from 'eslint-config-prettier/flat';
3
- import reactCompilerPlugin from 'eslint-plugin-react-compiler';
4
+ import importPlugin from 'eslint-plugin-import';
5
+ import jsxA11yPlugin from 'eslint-plugin-jsx-a11y';
6
+ import reactPlugin from 'eslint-plugin-react';
7
+ import { configs as reactCompilerPluginConfigs } from 'eslint-plugin-react-compiler';
4
8
  import { configs as reactHookConfigs } from 'eslint-plugin-react-hooks';
5
9
  import globals from 'globals';
6
- import * as tseslint from 'typescript-eslint';
7
10
  import * as fs from 'node:fs';
8
11
  import * as path from 'node:path';
12
+ import * as tseslint from 'typescript-eslint';
9
13
 
10
- import { airbnbBaseConfig, airbnbReactConfig } from './airbnb/base.mjs';
11
- import airbnbTypescript from './airbnb/typescript.mjs';
12
14
  import { createCoreConfig } from './material-ui/config.mjs';
13
15
  import muiPlugin from './material-ui/index.mjs';
14
16
  /**
@@ -36,16 +38,19 @@ export function createBaseConfig(
36
38
  return /** @type {import('eslint').Linter.Config[]} */ (
37
39
  tseslint.config(
38
40
  ...ignoreRules,
39
- airbnbBaseConfig,
40
- airbnbReactConfig,
41
- airbnbTypescript,
41
+ eslintJs.configs.recommended,
42
+ importPlugin.flatConfigs.recommended,
43
+ importPlugin.flatConfigs.react,
44
+ jsxA11yPlugin.flatConfigs.recommended,
45
+ reactPlugin.configs.flat.recommended,
42
46
  reactHookConfigs.recommended,
43
- enableReactCompiler ? reactCompilerPlugin.configs.recommended : {},
47
+ tseslint.configs.recommended,
48
+ importPlugin.flatConfigs.typescript,
49
+ enableReactCompiler ? reactCompilerPluginConfigs.recommended : {},
44
50
  prettier,
45
51
  {
46
52
  name: 'typescript-eslint-parser',
47
53
  languageOptions: {
48
- parser: tseslint.parser,
49
54
  ecmaVersion: 7,
50
55
  globals: {
51
56
  ...globals.es2020,
@@ -54,19 +59,8 @@ export function createBaseConfig(
54
59
  },
55
60
  },
56
61
  plugins: {
57
- '@typescript-eslint': tseslint.plugin,
58
62
  'material-ui': muiPlugin,
59
63
  },
60
- settings: {
61
- 'import/parsers': {
62
- '@typescript-eslint/parser': ['.ts', '.tsx'],
63
- },
64
- 'import/resolver': {
65
- typescript: {
66
- project: ['tsconfig.node.json', 'apps/*/tsconfig.json', 'packages/*/tsconfig.json'],
67
- },
68
- },
69
- },
70
64
  extends: createCoreConfig({ reactCompilerEnabled: enableReactCompiler }),
71
65
  },
72
66
  {
@@ -82,7 +76,6 @@ export function createBaseConfig(
82
76
  ],
83
77
  },
84
78
  },
85
-
86
79
  // Lint rule to disallow usage of typescript namespaces.We've seen at least two problems with them:
87
80
  // * Creates non-portable types in base ui. [1]
88
81
  // * This pattern [2] leads to broken bundling in codesandbox [3].
@@ -96,6 +89,14 @@ export function createBaseConfig(
96
89
  '@typescript-eslint/no-namespace': 'error',
97
90
  },
98
91
  },
92
+ // Part of the migration away from airbnb config. Turned of initially.
93
+ {
94
+ rules: {
95
+ '@typescript-eslint/no-explicit-any': 'off',
96
+ '@typescript-eslint/no-unsafe-function-type': 'off',
97
+ '@typescript-eslint/no-empty-object-type': 'off',
98
+ },
99
+ },
99
100
  )
100
101
  );
101
102
  }
@@ -5,6 +5,301 @@ const restrictedSyntaxRules = restrictedMethods.map((method) => ({
5
5
  selector: `MemberExpression[object.name='window'][property.name='${method}']`,
6
6
  }));
7
7
 
8
+ /**
9
+ * Critical Airbnb rules missing from individual plugin recommended configs
10
+ * @type {import('eslint').Linter.Config['rules']}
11
+ */
12
+ const criticalAirbnbRules = {
13
+ // Security & Best Practices
14
+ 'no-eval': 'error',
15
+ 'no-script-url': 'error',
16
+ 'array-callback-return': ['error', { allowImplicit: true }],
17
+ 'consistent-return': 'error',
18
+ eqeqeq: ['error', 'always', { null: 'ignore' }],
19
+ // 'no-param-reassign': ['error', { props: true }],
20
+ 'guard-for-in': 'error',
21
+ radix: 'error',
22
+ // disallow usage of __proto__ property
23
+ // https://eslint.org/docs/rules/no-proto
24
+ 'no-proto': 'error',
25
+ 'vars-on-top': 'error',
26
+ // disallow use of labels for anything other than loops and switches
27
+ // https://eslint.org/docs/rules/no-labels
28
+ 'no-labels': ['error', { allowLoop: false, allowSwitch: false }],
29
+ // disallow unnecessary nested blocks
30
+ // https://eslint.org/docs/rules/no-lone-blocks
31
+ 'no-lone-blocks': 'error',
32
+ // disallow use of new operator when not part of the assignment or comparison
33
+ // https://eslint.org/docs/rules/no-new
34
+ 'no-new': 'error',
35
+ // disallow use of new operator for Function object
36
+ // https://eslint.org/docs/rules/no-new-func
37
+ 'no-new-func': 'error',
38
+
39
+ // disallow comparisons where both sides are exactly the same
40
+ // https://eslint.org/docs/rules/no-self-compare
41
+ 'no-self-compare': 'error',
42
+ 'no-restricted-globals': ['error', 'isFinite', 'isNaN'],
43
+
44
+ // Styles
45
+ // require or disallow an empty line between class members
46
+ // https://eslint.org/docs/rules/lines-between-class-members
47
+ 'lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: false }],
48
+ // require a capital letter for constructors
49
+ 'new-cap': [
50
+ 'error',
51
+ {
52
+ newIsCap: true,
53
+ newIsCapExceptions: [],
54
+ capIsNew: false,
55
+ capIsNewExceptions: ['Immutable.Map', 'Immutable.Set', 'Immutable.List'],
56
+ },
57
+ ],
58
+ // disallow use of unary operators, ++ and --
59
+ // https://eslint.org/docs/rules/no-plusplus
60
+ 'no-plusplus': 'error',
61
+ // disallow use of bitwise operators
62
+ // https://eslint.org/docs/rules/no-bitwise
63
+ 'no-bitwise': 'error',
64
+ // disallow if as the only statement in an else block
65
+ // https://eslint.org/docs/rules/no-lonely-if
66
+ 'no-lonely-if': 'error',
67
+
68
+ // ES6+ Modern JavaScript
69
+ 'no-var': 'error',
70
+ 'prefer-const': ['error', { destructuring: 'any', ignoreReadBeforeAssign: true }],
71
+ 'prefer-template': 'error',
72
+ 'object-shorthand': ['error', 'always'],
73
+
74
+ // Error
75
+ // Disallow template literal placeholder syntax in regular strings
76
+ // https://eslint.org/docs/rules/no-template-curly-in-string
77
+ 'no-template-curly-in-string': 'error',
78
+ // Disallow returning values from Promise executor functions
79
+ // https://eslint.org/docs/rules/no-promise-executor-return
80
+ 'no-promise-executor-return': 'error',
81
+
82
+ // Import rules (critical ones not in recommended)
83
+ 'import/order': ['error', { groups: [['builtin', 'external', 'internal']] }],
84
+ 'import/first': 'error',
85
+ 'import/no-mutable-exports': 'error',
86
+ 'import/newline-after-import': 'error',
87
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/namespace.md
88
+ 'import/namespace': 'off',
89
+ // Forbid require() calls with expressions
90
+ // https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-dynamic-require.md
91
+ 'import/no-dynamic-require': 'error',
92
+
93
+ // Additional best practices
94
+ 'default-case': ['error', { commentPattern: '^no default$' }],
95
+ 'default-case-last': 'error',
96
+ 'no-else-return': ['error', { allowElseIf: false }],
97
+ 'no-multi-assign': 'error',
98
+ 'no-nested-ternary': 'error',
99
+ 'no-unneeded-ternary': ['error', { defaultAssignment: false }],
100
+ 'spaced-comment': [
101
+ 'error',
102
+ 'always',
103
+ {
104
+ line: { markers: ['/'], exceptions: ['-', '+'] },
105
+ block: { markers: ['*'], exceptions: ['*'], balanced: true },
106
+ },
107
+ ],
108
+ // require all requires be top-level
109
+ // https://eslint.org/docs/rules/global-require
110
+ 'global-require': 'error',
111
+ // disallow use of assignment in return statement
112
+ // https://eslint.org/docs/rules/no-return-assign
113
+ 'no-return-assign': ['error', 'always'],
114
+ // disallow useless string concatenation
115
+ // https://eslint.org/docs/rules/no-useless-concat
116
+ 'no-useless-concat': 'error',
117
+
118
+ // Disallow await inside of loops
119
+ // https://eslint.org/docs/rules/no-await-in-loop
120
+ 'no-await-in-loop': 'error',
121
+ // disallow assignment in conditional expressions
122
+ 'no-cond-assign': ['error', 'always'],
123
+
124
+ // React
125
+ // Prevent usage of button elements without an explicit type attribute
126
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/843d71a432baf0f01f598d7cf1eea75ad6896e4b/docs/rules/button-has-type.md
127
+ 'react/button-has-type': [
128
+ 'error',
129
+ {
130
+ button: true,
131
+ submit: true,
132
+ reset: false,
133
+ },
134
+ ],
135
+ // Prevent missing displayName in a React component definition
136
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/display-name.md
137
+ 'react/display-name': ['off', { ignoreTranspilerName: false }],
138
+ // Enforce a specific function type for function components
139
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/function-component-definition.md
140
+ 'react/function-component-definition': [
141
+ 'error',
142
+ {
143
+ namedComponents: ['function-declaration', 'function-expression'],
144
+ unnamedComponents: 'function-expression',
145
+ },
146
+ ],
147
+ // Prevent react contexts from taking non-stable values
148
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/e2eaadae316f9506d163812a09424eb42698470a/docs/rules/jsx-no-constructed-context-values.md
149
+ 'react/jsx-no-constructed-context-values': 'error',
150
+ // Require stateless functions when not using lifecycle methods, setState or ref
151
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md
152
+ 'react/prefer-stateless-function': ['error', { ignorePureComponents: true }],
153
+ // Forbids using non-exported propTypes
154
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/forbid-foreign-prop-types.md
155
+ // this is intentionally set to "warn". it would be "error",
156
+ // but it's only critical if you're stripping propTypes in production.
157
+ 'react/forbid-foreign-prop-types': ['warn', { allowInPropTypes: true }],
158
+ // Validate JSX has key prop when in array or iterator
159
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-key.md
160
+ // Turned off because it has too many false positives
161
+ 'react/jsx-key': 'off',
162
+ // Prevent unused propType definitions
163
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-unused-prop-types.md
164
+ 'react/no-unused-prop-types': [
165
+ 'error',
166
+ {
167
+ customValidators: [],
168
+ skipShapeProps: true,
169
+ },
170
+ ],
171
+ };
172
+
173
+ /**
174
+ * TypeScript-specific rules (replaces Airbnb TypeScript config)
175
+ * @type {import('eslint').Linter.Config['rules']}
176
+ */
177
+ const typescriptOverrides = {
178
+ // The following rules are enabled in Airbnb config, but are recommended to be disabled within TypeScript projects
179
+ // See: https://github.com/typescript-eslint/typescript-eslint/blob/13583e65f5973da2a7ae8384493c5e00014db51b/docs/linting/TROUBLESHOOTING.md#eslint-plugin-import
180
+ 'import/named': 'off',
181
+ 'import/no-named-as-default-member': 'off',
182
+ 'import/no-unresolved': 'off',
183
+
184
+ // TypeScript equivalents of ESLint rules
185
+ 'default-param-last': 'off',
186
+ '@typescript-eslint/default-param-last': 'error',
187
+ 'no-array-constructor': 'off',
188
+ '@typescript-eslint/no-array-constructor': 'error',
189
+ '@typescript-eslint/triple-slash-reference': 'off',
190
+ 'no-empty-function': 'off',
191
+ // disallow empty functions, except for standalone funcs/arrows
192
+ // https://eslint.org/docs/rules/no-empty-function
193
+ '@typescript-eslint/no-empty-function': [
194
+ 'error',
195
+ {
196
+ allow: ['arrowFunctions', 'functions', 'methods'],
197
+ },
198
+ ],
199
+ 'no-loss-of-precision': 'error',
200
+ 'no-loop-func': 'off',
201
+ '@typescript-eslint/no-loop-func': 'error',
202
+ 'no-shadow': 'off',
203
+ '@typescript-eslint/no-shadow': 'error',
204
+ 'no-unused-expressions': 'off',
205
+ '@typescript-eslint/no-unused-expressions': [
206
+ 'error',
207
+ { allowShortCircuit: false, allowTernary: false },
208
+ ],
209
+ 'no-useless-constructor': 'off',
210
+ '@typescript-eslint/no-useless-constructor': 'error',
211
+ 'require-await': 'off',
212
+
213
+ // TypeScript naming convention (replaces camelcase)
214
+ camelcase: 'off',
215
+
216
+ // The `@typescript-eslint/naming-convention` rule allows `leadingUnderscore` and `trailingUnderscore` settings. However, the existing `no-underscore-dangle` rule already takes care of this.
217
+ '@typescript-eslint/naming-convention': [
218
+ 'error',
219
+ // Allow camelCase variables (23.2), PascalCase variables (23.8), and UPPER_CASE variables (23.10)
220
+ {
221
+ selector: 'variable',
222
+ format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
223
+ },
224
+ // Allow camelCase functions (23.2), and PascalCase functions (23.8)
225
+ {
226
+ selector: 'function',
227
+ format: ['camelCase', 'PascalCase'],
228
+ },
229
+ // Airbnb recommends PascalCase for classes (23.3), and although Airbnb does not make TypeScript recommendations, we are assuming this rule would similarly apply to anything "type like", including interfaces, type aliases, and enums
230
+ {
231
+ selector: 'typeLike',
232
+ format: ['PascalCase'],
233
+ },
234
+ ],
235
+
236
+ // Namespace rule
237
+ '@typescript-eslint/no-namespace': 'off',
238
+ '@typescript-eslint/no-this-alias': 'off',
239
+
240
+ // TypeScript extensions handling
241
+ 'import/extensions': [
242
+ 'error',
243
+ 'ignorePackages',
244
+ {
245
+ js: 'never',
246
+ mjs: 'never',
247
+ jsx: 'never',
248
+ ts: 'never',
249
+ tsx: 'never',
250
+ },
251
+ ],
252
+ };
253
+
254
+ /**
255
+ * @type {import('eslint').Linter.Config['rules']}
256
+ */
257
+ const airbnbJsxA11y = {
258
+ // Enforce that all elements that require alternative text have meaningful information
259
+ // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/alt-text.md
260
+ 'jsx-a11y/alt-text': [
261
+ 'error',
262
+ {
263
+ elements: ['img'],
264
+ },
265
+ ],
266
+
267
+ // ensure <a> tags are valid
268
+ // https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/0745af376cdc8686d85a361ce36952b1fb1ccf6e/docs/rules/anchor-is-valid.md
269
+ 'jsx-a11y/anchor-is-valid': [
270
+ 'error',
271
+ {
272
+ components: ['Link'],
273
+ specialLink: ['to'],
274
+ aspects: ['noHref', 'invalidHref', 'preferButton'],
275
+ },
276
+ ],
277
+
278
+ // Enforce that a control (an interactive element) has a text label.
279
+ // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/control-has-associated-label.md
280
+ 'jsx-a11y/control-has-associated-label': [
281
+ 'error',
282
+ {
283
+ labelAttributes: ['label'],
284
+ controlComponents: [],
285
+ ignoreElements: ['audio', 'canvas', 'embed', 'input', 'textarea', 'tr', 'video'],
286
+ ignoreRoles: [
287
+ 'grid',
288
+ 'listbox',
289
+ 'menu',
290
+ 'menubar',
291
+ 'radiogroup',
292
+ 'row',
293
+ 'tablist',
294
+ 'toolbar',
295
+ 'tree',
296
+ 'treegrid',
297
+ ],
298
+ depth: 5,
299
+ },
300
+ ],
301
+ };
302
+
8
303
  /**
9
304
  * @param {Object} [options]
10
305
  * @param {boolean} [options.reactCompilerEnabled] - Whether the config is for spec files.
@@ -14,7 +309,29 @@ export function createCoreConfig(options = {}) {
14
309
  return [
15
310
  {
16
311
  name: 'material-ui-base',
312
+ settings: {
313
+ 'import/resolver': {
314
+ node: {
315
+ extensions: ['.mjs', '.js', '.json'],
316
+ },
317
+ typescript: {
318
+ project: ['tsconfig.node.json', 'apps/*/tsconfig.json', 'packages/*/tsconfig.json'],
319
+ },
320
+ },
321
+ 'import/extensions': ['.js', '.mjs', '.jsx', '.ts', '.tsx', '.d.ts'],
322
+ 'import/core-modules': [],
323
+ 'import/ignore': ['node_modules', '\\.(css|svg|json)$'],
324
+ // Override with TypeScript-specific settings
325
+ 'import/parsers': {
326
+ '@typescript-eslint/parser': ['.ts', '.tsx'],
327
+ },
328
+ // Extend Airbnb extensions with TypeScript
329
+ 'import/external-module-folders': ['node_modules', 'node_modules/@types'],
330
+ },
17
331
  rules: {
332
+ ...criticalAirbnbRules,
333
+ ...airbnbJsxA11y,
334
+ ...typescriptOverrides,
18
335
  'no-redeclare': 'off',
19
336
  '@typescript-eslint/no-redeclare': 'off',
20
337
  'consistent-this': ['error', 'self'],
@@ -39,9 +356,7 @@ export function createCoreConfig(options = {}) {
39
356
  'no-throw-literal': 'error',
40
357
  // Use the proptype inheritance chain
41
358
  'no-prototype-builtins': 'off',
42
- 'no-return-await': 'error',
43
359
  'no-underscore-dangle': 'error',
44
- 'nonblock-statement-body-position': 'error',
45
360
  'prefer-arrow-callback': ['error', { allowNamedFunctions: true }],
46
361
  // Destructuring harm grep potential.
47
362
  'prefer-destructuring': 'off',
@@ -18,6 +18,7 @@ export const baseSpecRules = {
18
18
  '@typescript-eslint/no-unused-expressions': 'off',
19
19
  '@typescript-eslint/no-unused-vars': 'off',
20
20
  '@typescript-eslint/no-use-before-define': 'off',
21
+ '@typescript-eslint/ban-ts-comment': 'off',
21
22
 
22
23
  'import/prefer-default-export': 'off',
23
24
 
@@ -84,6 +85,12 @@ export function createTestConfig(options = {}) {
84
85
  // that they don't need type-checking
85
86
  'react/prop-types': 'off',
86
87
  'react/no-unused-prop-types': 'off',
88
+ // Part of the migration away from airbnb config. Turned of initially.
89
+ '@typescript-eslint/no-empty-function': 'off',
90
+ '@typescript-eslint/ban-ts-comment': 'off',
91
+ 'testing-library/no-node-access': 'off',
92
+ '@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
93
+ // end migration
87
94
  ...(useMocha
88
95
  ? {
89
96
  'mocha/consistent-spacing-between-blocks': 'off',
@@ -1,113 +0,0 @@
1
- /**
2
- * Reassembles the ESLint Airbnb base configuration for usage with
3
- * flat Eslint configuration.
4
- */
5
- import baseBestPractices from 'eslint-config-airbnb-base/rules/best-practices';
6
- import baseErrors from 'eslint-config-airbnb-base/rules/errors';
7
- import baseEs6 from 'eslint-config-airbnb-base/rules/es6';
8
- import baseImports from 'eslint-config-airbnb-base/rules/imports';
9
- import baseNode from 'eslint-config-airbnb-base/rules/node';
10
- import baseStrict from 'eslint-config-airbnb-base/rules/strict';
11
- import baseStyle from 'eslint-config-airbnb-base/rules/style';
12
- import baseVariables from 'eslint-config-airbnb-base/rules/variables';
13
- import airbnbReact from 'eslint-config-airbnb/rules/react';
14
- import airbnbReactA11y from 'eslint-config-airbnb/rules/react-a11y';
15
- import eslintPluginImport from 'eslint-plugin-import';
16
- import eslintPluginJsxA11y from 'eslint-plugin-jsx-a11y';
17
- import eslintPluginReact from 'eslint-plugin-react';
18
-
19
- import globals from 'globals';
20
- import * as tseslint from 'typescript-eslint';
21
-
22
- const baseES6Plugin = {
23
- languageOptions: {
24
- globals: {
25
- ...globals.es2016,
26
- },
27
- parserOptions: baseEs6.parserOptions,
28
- },
29
- rules: baseEs6.rules,
30
- };
31
-
32
- const baseImportPlugin = {
33
- languageOptions: {
34
- globals: {
35
- ...globals.es2016,
36
- },
37
- parserOptions: baseImports.parserOptions,
38
- },
39
- settings: baseImports.settings,
40
- rules: baseImports.rules,
41
- plugins: {
42
- import: eslintPluginImport,
43
- },
44
- };
45
-
46
- const baseNodePlugin = {
47
- languageOptions: {
48
- globals: {
49
- ...globals.node,
50
- },
51
- },
52
- rules: baseNode.rules,
53
- };
54
-
55
- export const airbnbBaseConfig = /** @type {import('eslint').Linter.Config[]} */ (
56
- tseslint.config(
57
- {
58
- name: 'base-best-practices',
59
- ...baseBestPractices,
60
- },
61
- {
62
- name: 'base-errors',
63
- ...baseErrors,
64
- },
65
- {
66
- name: 'base-node',
67
- ...baseNodePlugin,
68
- },
69
- { name: 'base-style', ...baseStyle },
70
- { name: 'base-variables', ...baseVariables },
71
- { name: 'base-es6-plugin', ...baseES6Plugin },
72
- { name: 'base-import-plugin', ...baseImportPlugin },
73
- { name: 'base-strict', ...baseStrict },
74
- )
75
- );
76
-
77
- /**
78
- * @type {import('typescript-eslint').InfiniteDepthConfigWithExtends}
79
- */
80
- const airbnbReactPlugin = {
81
- languageOptions: {
82
- parserOptions: {
83
- ecmaFeatures: {
84
- jsx: true,
85
- },
86
- },
87
- },
88
- plugins: {
89
- react: eslintPluginReact,
90
- },
91
- rules: airbnbReact.rules,
92
- };
93
-
94
- const airbnbReactA11yPlugin = {
95
- plugins: {
96
- 'jsx-a11y': eslintPluginJsxA11y,
97
- },
98
- languageOptions: {
99
- parserOptions: {
100
- ecmaFeatures: {
101
- jsx: true,
102
- },
103
- },
104
- },
105
- rules: airbnbReactA11y.rules,
106
- };
107
-
108
- export const airbnbReactConfig = /** @type {import('eslint').Linter.Config[]} */ (
109
- tseslint.config(
110
- { name: 'airbnb-react', ...airbnbReactPlugin },
111
- { name: 'airbnb-react-a11y', ...airbnbReactA11yPlugin },
112
- )
113
- );
@@ -1,126 +0,0 @@
1
- /**
2
- * Reassembles the ESLint Airbnb typescript configuration for usage with
3
- * flat Eslint configuration.
4
- */
5
- import baseBestPractices from 'eslint-config-airbnb-base/rules/best-practices';
6
- import baseEs6 from 'eslint-config-airbnb-base/rules/es6';
7
- import baseImports from 'eslint-config-airbnb-base/rules/imports';
8
- import baseStyle from 'eslint-config-airbnb-base/rules/style';
9
- import baseVariables from 'eslint-config-airbnb-base/rules/variables';
10
- import * as tseslint from 'typescript-eslint';
11
-
12
- const baseImportsRules = baseImports.rules;
13
-
14
- if (!Array.isArray(baseImportsRules?.['import/extensions'])) {
15
- throw new Error(
16
- 'Expected `import/extensions` rule to be an array in `eslint-config-airbnb-base/rules/imports`',
17
- );
18
- }
19
-
20
- export default /** @type {import('typescript-eslint').ConfigArray} */ (
21
- tseslint.config(
22
- {
23
- settings: {
24
- 'import/parsers': {
25
- '@typescript-eslint/parser': ['.ts', '.tsx', '.d.ts'],
26
- },
27
- 'import/resolver': {
28
- node: {
29
- extensions: ['.mjs', '.js', '.jsx', '.json', '.ts', '.tsx', '.d.ts'],
30
- },
31
- },
32
- // Append 'ts' extensions to Airbnb 'import/extensions' setting
33
- // Original: ['.js', '.mjs', '.jsx']
34
- 'import/extensions': ['.js', '.mjs', '.jsx', '.ts', '.tsx', '.d.ts'],
35
- // Resolve type definition packages
36
- 'import/external-module-folders': ['node_modules', 'node_modules/@types'],
37
- },
38
- rules: {
39
- camelcase: 'off',
40
- // The `@typescript-eslint/naming-convention` rule allows `leadingUnderscore` and `trailingUnderscore` settings. However, the existing `no-underscore-dangle` rule already takes care of this.
41
- '@typescript-eslint/naming-convention': [
42
- 'error',
43
- // Allow camelCase variables (23.2), PascalCase variables (23.8), and UPPER_CASE variables (23.10)
44
- {
45
- selector: 'variable',
46
- format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
47
- },
48
- // Allow camelCase functions (23.2), and PascalCase functions (23.8)
49
- {
50
- selector: 'function',
51
- format: ['camelCase', 'PascalCase'],
52
- },
53
- // Airbnb recommends PascalCase for classes (23.3), and although Airbnb does not make TypeScript recommendations, we are assuming this rule would similarly apply to anything "type like", including interfaces, type aliases, and enums
54
- {
55
- selector: 'typeLike',
56
- format: ['PascalCase'],
57
- },
58
- ],
59
- 'default-param-last': 'off',
60
- '@typescript-eslint/default-param-last': baseBestPractices.rules?.['default-param-last'],
61
- 'no-array-constructor': 'off',
62
- '@typescript-eslint/no-array-constructor': baseStyle.rules?.['no-array-constructor'],
63
- 'no-empty-function': 'off',
64
- '@typescript-eslint/no-empty-function': baseBestPractices.rules?.['no-empty-function'],
65
- 'no-loss-of-precision': 'error',
66
- 'no-loop-func': 'off',
67
- '@typescript-eslint/no-loop-func': baseBestPractices.rules?.['no-loop-func'],
68
- 'no-magic-numbers': 'off',
69
- '@typescript-eslint/no-magic-numbers': baseBestPractices.rules?.['no-magic-numbers'],
70
- 'no-shadow': 'off',
71
- '@typescript-eslint/no-shadow': baseVariables.rules?.['no-shadow'],
72
- 'no-unused-expressions': 'off',
73
- '@typescript-eslint/no-unused-expressions':
74
- baseBestPractices.rules?.['no-unused-expressions'],
75
- 'no-useless-constructor': 'off',
76
- '@typescript-eslint/no-useless-constructor': baseEs6.rules?.['no-useless-constructor'],
77
- 'require-await': 'off',
78
- '@typescript-eslint/require-await': baseBestPractices.rules?.['require-await'],
79
-
80
- // Append 'ts' and 'tsx' to Airbnb 'import/extensions' rule
81
- // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md
82
- 'import/extensions': [
83
- baseImportsRules['import/extensions'][0],
84
- baseImportsRules['import/extensions'][1],
85
- typeof baseImportsRules['import/extensions'][2] === 'object'
86
- ? {
87
- ...baseImportsRules['import/extensions'][2],
88
- ts: 'never',
89
- tsx: 'never',
90
- }
91
- : { ts: 'never', tsx: 'never' },
92
- ],
93
- },
94
- },
95
- {
96
- files: ['**/*.ts', '**/*.tsx'],
97
- rules: {
98
- // The following rules are enabled in Airbnb config, but are already checked (more thoroughly) by the TypeScript compiler
99
- // Some of the rules also fail in TypeScript files, for example: https://github.com/typescript-eslint/typescript-eslint/issues/662#issuecomment-507081586
100
- // Rules are inspired by: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/eslint-recommended.ts
101
- 'constructor-super': 'off',
102
- 'getter-return': 'off',
103
- 'no-const-assign': 'off',
104
- 'no-dupe-args': 'off',
105
- 'no-dupe-class-members': 'off',
106
- 'no-dupe-keys': 'off',
107
- 'no-func-assign': 'off',
108
- 'no-import-assign': 'off',
109
- 'no-new-symbol': 'off',
110
- 'no-obj-calls': 'off',
111
- 'no-redeclare': 'off',
112
- 'no-setter-return': 'off',
113
- 'no-this-before-super': 'off',
114
- 'no-undef': 'off',
115
- 'no-unreachable': 'off',
116
- 'no-unsafe-negation': 'off',
117
- 'valid-typeof': 'off',
118
- // The following rules are enabled in Airbnb config, but are recommended to be disabled within TypeScript projects
119
- // See: https://github.com/typescript-eslint/typescript-eslint/blob/13583e65f5973da2a7ae8384493c5e00014db51b/docs/linting/TROUBLESHOOTING.md#eslint-plugin-import
120
- 'import/named': 'off',
121
- 'import/no-named-as-default-member': 'off',
122
- 'import/no-unresolved': 'off',
123
- },
124
- },
125
- )
126
- );