Some checks failed
No response / noResponse (push) Has been cancelled
CI / Continuous releases (push) Has been cancelled
CI / test-dev (macos-latest) (push) Has been cancelled
CI / test-dev (ubuntu-latest) (push) Has been cancelled
CI / test-dev (windows-latest) (push) Has been cancelled
Maintenance / main (push) Has been cancelled
331 lines
9.6 KiB
JavaScript
331 lines
9.6 KiB
JavaScript
import {
|
|
createBaseConfig,
|
|
createTestConfig,
|
|
baseSpecRules,
|
|
createDocsConfig,
|
|
EXTENSION_TS,
|
|
EXTENSION_TEST_FILE,
|
|
EXTENSION_DTS,
|
|
} from '@mui/internal-code-infra/eslint';
|
|
import { defineConfig } from 'eslint/config';
|
|
import eslintPluginConsistentName from 'eslint-plugin-consistent-default-export-name';
|
|
import * as path from 'node:path';
|
|
import vitestPlugin from '@vitest/eslint-plugin';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const filename = fileURLToPath(import.meta.url);
|
|
const dirname = path.dirname(filename);
|
|
|
|
const OneLevelImportMessage = [
|
|
'Prefer one level nested imports to avoid bundling everything in dev mode or breaking CJS/ESM split.',
|
|
'See https://github.com/mui/material-ui/pull/24147 for the kind of win it can unlock.',
|
|
].join('\n');
|
|
// This only applies to packages published from this monorepo.
|
|
// If you build a library around `@mui/material` you can safely use `createStyles` without running into the same issue as we are.
|
|
const forbidCreateStylesMessage =
|
|
'Use `MuiStyles<ClassKey, Props>` instead if the styles are exported. Otherwise use `as const` assertions. ' +
|
|
'`createStyles` will lead to inlined, at-compile-time-resolved type-imports. ' +
|
|
'See https://github.com/microsoft/TypeScript/issues/36097#issuecomment-578324386 for more information';
|
|
|
|
const ENABLE_REACT_COMPILER_PLUGIN = false;
|
|
|
|
const NO_RESTRICTED_IMPORTS_PATHS_TOP_LEVEL_PACKAGES = [
|
|
{
|
|
name: '@mui/material',
|
|
message: OneLevelImportMessage,
|
|
},
|
|
{
|
|
name: '@mui/lab',
|
|
message: OneLevelImportMessage,
|
|
},
|
|
];
|
|
|
|
const NO_RESTRICTED_IMPORTS_PATTERNS_DEEPLY_NESTED = [
|
|
{
|
|
group: [
|
|
'@mui/*/*/*',
|
|
'@pigment-css/*/*/*',
|
|
// Allow any import depth with any internal packages
|
|
'!@mui/internal-*/**',
|
|
'!@mui/docs/**', // @mui/docs should be @mui/internal-docs
|
|
],
|
|
message: OneLevelImportMessage,
|
|
},
|
|
];
|
|
|
|
export default defineConfig(
|
|
createBaseConfig({
|
|
enableReactCompiler: ENABLE_REACT_COMPILER_PLUGIN,
|
|
baseDirectory: dirname,
|
|
}),
|
|
{
|
|
name: 'Material UI overrides',
|
|
files: [`**/*${EXTENSION_TS}`],
|
|
settings: {
|
|
'import/resolver': {
|
|
typescript: {
|
|
project: ['tsconfig.json'],
|
|
},
|
|
},
|
|
},
|
|
rules: {
|
|
'import/prefer-default-export': 'error',
|
|
'material-ui/straight-quotes': 'error',
|
|
'no-restricted-imports': [
|
|
'error',
|
|
{
|
|
patterns: NO_RESTRICTED_IMPORTS_PATTERNS_DEEPLY_NESTED,
|
|
},
|
|
],
|
|
'react/react-in-jsx-scope': 'off',
|
|
'react/sort-prop-types': 'off', // 228
|
|
'@typescript-eslint/ban-ts-comment': 'off', // 117
|
|
'@typescript-eslint/no-require-imports': 'off', // 133
|
|
'react/jsx-filename-extension': 'off',
|
|
|
|
// TODO enable:
|
|
'react-hooks/refs': 'off',
|
|
'react-hooks/globals': 'off',
|
|
'react-hooks/immutability': 'off',
|
|
'react-hooks/preserve-manual-memoization': 'off',
|
|
'react-hooks/incompatible-library': 'off',
|
|
'react-hooks/static-components': 'off',
|
|
'react-hooks/purity': 'off',
|
|
},
|
|
},
|
|
...['mui-material', 'mui-system', 'mui-utils', 'mui-lab', 'mui-utils', 'mui-styled-engine'].map(
|
|
(packageName) => ({
|
|
files: [`packages/${packageName}/src/**/*${EXTENSION_TEST_FILE}`],
|
|
ignores: ['**/*.test.*', '**/*.spec.*'],
|
|
rules: {
|
|
'material-ui/no-restricted-resolved-imports': [
|
|
'error',
|
|
[
|
|
{
|
|
pattern: `**/packages/${packageName}/src/index.*`,
|
|
message:
|
|
"Don't import from the package index. Import the specific module directly instead.",
|
|
},
|
|
],
|
|
],
|
|
},
|
|
}),
|
|
),
|
|
{
|
|
files: [`packages/**/*${EXTENSION_TS}`],
|
|
rules: {
|
|
// Our packages write .js + .d.ts files manually.
|
|
'react/jsx-filename-extension': ['error', { extensions: ['.js', '.tsx'] }],
|
|
},
|
|
},
|
|
// Test start
|
|
{
|
|
files: [`**/*${EXTENSION_TEST_FILE}`],
|
|
extends: createTestConfig({
|
|
useMocha: false,
|
|
useVitest: true,
|
|
}),
|
|
languageOptions: {
|
|
globals: {
|
|
...vitestPlugin.environments.env.globals,
|
|
},
|
|
},
|
|
rules: {
|
|
'material-ui/no-empty-box': 'off',
|
|
// Disabled temporarily. Enable one by one.
|
|
'testing-library/no-container': 'off',
|
|
// TODO: investigate and fix
|
|
'vitest/expect-expect': 'off',
|
|
},
|
|
},
|
|
// Test end
|
|
// Docs start
|
|
{
|
|
files: [`docs/**/*${EXTENSION_TS}`],
|
|
extends: createDocsConfig(),
|
|
rules: {
|
|
'@next/next/no-img-element': 'off',
|
|
'no-restricted-imports': [
|
|
'error',
|
|
{
|
|
paths: NO_RESTRICTED_IMPORTS_PATHS_TOP_LEVEL_PACKAGES,
|
|
patterns: NO_RESTRICTED_IMPORTS_PATTERNS_DEEPLY_NESTED,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
// Moved from docs/data/material/components/.eslintrc.js
|
|
{
|
|
files: [`docs/data/material/components/**/*${EXTENSION_TS}`],
|
|
rules: {
|
|
// useful for interactions feedback
|
|
'no-console': ['off', { allow: ['info'] }],
|
|
// not very friendly to prop forwarding
|
|
'react/jsx-handler-names': 'off',
|
|
},
|
|
},
|
|
// demos
|
|
{
|
|
files: [`docs/src/pages/**/*${EXTENSION_TS}`, `docs/data/**/*${EXTENSION_TS}`],
|
|
rules: {
|
|
// This most often reports data that is defined after the component definition.
|
|
// This is safe to do and helps readability of the demo code since the data is mostly irrelevant.
|
|
'@typescript-eslint/no-use-before-define': 'off',
|
|
'react/prop-types': 'off',
|
|
'no-alert': 'off',
|
|
'no-console': 'off',
|
|
},
|
|
},
|
|
// Next.js entry points pages
|
|
{
|
|
files: [`docs/pages/**/*${EXTENSION_TS}`, `packages/*/src/**/*.tsx`],
|
|
ignores: ['**/*.spec.tsx'],
|
|
rules: {
|
|
'react/prop-types': 'off',
|
|
},
|
|
},
|
|
{
|
|
files: [`docs/data/**/*${EXTENSION_TS}`],
|
|
ignores: [
|
|
// filenames/match-exported sees filename as 'file-name.d'
|
|
// Plugin looks unmaintain, find alternative? (e.g. eslint-plugin-project-structure)
|
|
'**/*.d.ts',
|
|
'docs/data/joy/getting-started/templates/**/*',
|
|
'docs/data/**/{css,system,tailwind}/*',
|
|
],
|
|
plugins: {
|
|
'consistent-default-export-name': eslintPluginConsistentName,
|
|
},
|
|
rules: {
|
|
'consistent-default-export-name/default-export-match-filename': ['error'],
|
|
},
|
|
},
|
|
// Docs end
|
|
{
|
|
files: [`**/*${EXTENSION_DTS}`],
|
|
rules: {
|
|
'import/export': 'off', // Not sure why it doesn't work
|
|
},
|
|
},
|
|
{
|
|
files: [`packages/*/src/*/*${EXTENSION_TS}`],
|
|
ignores: [
|
|
'**/*.spec.*',
|
|
'**/*.test.*',
|
|
// deprecated library
|
|
'**/mui-joy/**/*',
|
|
// used internally, not used on app router yet
|
|
'**/mui-docs/**/*',
|
|
],
|
|
rules: {
|
|
'material-ui/disallow-react-api-in-server-components': 'error',
|
|
},
|
|
},
|
|
{
|
|
files: [`packages/*/src/**/*${EXTENSION_TS}`],
|
|
ignores: ['**/*.spec.*'],
|
|
rules: {
|
|
'no-restricted-imports': [
|
|
'error',
|
|
{
|
|
paths: [
|
|
...NO_RESTRICTED_IMPORTS_PATHS_TOP_LEVEL_PACKAGES,
|
|
{
|
|
name: '@mui/utils',
|
|
message: OneLevelImportMessage,
|
|
},
|
|
{
|
|
name: '@mui/material/styles',
|
|
importNames: ['createStyles'],
|
|
message: forbidCreateStylesMessage,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
},
|
|
baseSpecRules,
|
|
{
|
|
files: ['packages-internal/scripts/typescript-to-proptypes/src/**/*.ts'],
|
|
rules: {
|
|
// Working with flags is common in TypeScript compiler
|
|
'no-bitwise': 'off',
|
|
},
|
|
},
|
|
{
|
|
files: [`packages/*/src/**/*${EXTENSION_TS}`],
|
|
ignores: ['**/*.d.ts', '**/*.spec.*', 'packages/mui-joy/**/*'],
|
|
rules: {
|
|
'material-ui/mui-name-matches-component-name': 'error',
|
|
},
|
|
},
|
|
{
|
|
files: ['test/bundling/scripts/**/*.js'],
|
|
rules: {
|
|
// ES modules need extensions
|
|
'import/extensions': ['error', 'ignorePackages'],
|
|
},
|
|
},
|
|
// Migrated config from packages/mui-icons-material/.eslintrc.js
|
|
{
|
|
files: [`packages/mui-icons-material/custom/**/*${EXTENSION_TS}`],
|
|
rules: {
|
|
'import/no-unresolved': 'off',
|
|
'import/extensions': 'off',
|
|
},
|
|
},
|
|
// Migrated config from packages/api-docs-builder/.eslintrc.js
|
|
{
|
|
files: [
|
|
`packages/api-docs-builder/**/*${EXTENSION_TS}`,
|
|
// Allow named exports for locales: https://github.com/mui/material-ui/pull/46933
|
|
`packages/mui-material/src/locale/*${EXTENSION_TS}`,
|
|
],
|
|
rules: {
|
|
'import/prefer-default-export': 'off',
|
|
},
|
|
},
|
|
// Migrated config from packages/api-docs-builder-core/.eslintrc.js
|
|
{
|
|
files: [`packages/api-docs-builder-core/**/*${EXTENSION_TS}`],
|
|
rules: {
|
|
'import/no-default-export': 'error',
|
|
'import/prefer-default-export': 'off',
|
|
},
|
|
},
|
|
{
|
|
files: [`examples/**/*${EXTENSION_TS}`],
|
|
rules: {
|
|
'import/no-relative-packages': 'off',
|
|
'react/react-in-jsx-scope': 'off',
|
|
'react/prop-types': 'off',
|
|
'import/prefer-default-export': 'off',
|
|
},
|
|
},
|
|
{
|
|
files: [`examples/**/*${EXTENSION_TS}`],
|
|
rules: {
|
|
'import/extensions': 'off',
|
|
'import/no-unresolved': 'off',
|
|
'no-console': 'off',
|
|
},
|
|
},
|
|
{
|
|
files: ['docs/src/pages/premium-themes/onepirate/modules/form/RFTextField.js'],
|
|
rules: {
|
|
// Otherwise, running docs:typescript:formatted rearranges the imports and also removes the eslint-disable comment
|
|
// if added.
|
|
'import/order': 'off',
|
|
},
|
|
},
|
|
{
|
|
files: [`test/**/*${EXTENSION_TS}`],
|
|
rules: {
|
|
'guard-for-in': 'off',
|
|
'testing-library/prefer-screen-queries': 'off', // Enable usage of playwright queries
|
|
'testing-library/no-await-sync-queries': 'off',
|
|
'testing-library/render-result-naming-convention': 'off', // inconsequential in regression tests
|
|
},
|
|
},
|
|
);
|