1- import { dirname } from 'path' ;
2- import { fileURLToPath } from 'url' ;
3- import { FlatCompat } from '@eslint/eslintrc' ;
1+ import { dirname } from 'path' ;
2+ import { fileURLToPath } from 'url' ;
3+ import { FlatCompat } from '@eslint/eslintrc' ;
44import js from '@eslint/js' ;
55import tseslint from 'typescript-eslint' ;
66import eslintPluginPrettier from 'eslint-plugin-prettier' ;
77import importPlugin from 'eslint-plugin-import' ;
88import eslintPluginJest from 'eslint-plugin-jest' ;
9+ import reactPlugin from 'eslint-plugin-react' ;
910
1011const __filename = fileURLToPath ( import . meta. url ) ;
1112const __dirname = dirname ( __filename ) ;
@@ -21,6 +22,7 @@ export default tseslint.config(
2122 ...compat . extends ( 'next/core-web-vitals' , 'next/typescript' ) ,
2223 ...compat . extends ( 'plugin:jest/recommended' ) ,
2324 ...compat . extends ( 'plugin:prettier/recommended' ) ,
25+ ...compat . extends ( 'plugin:react/recommended' ) ,
2426
2527 {
2628 ignores : [ '*' , '!src/**' , '!tests/**' ] ,
@@ -37,65 +39,40 @@ export default tseslint.config(
3739 prettier : eslintPluginPrettier ,
3840 import : importPlugin ,
3941 jest : eslintPluginJest ,
42+ react : reactPlugin ,
4043 } ,
4144 rules : {
42- // Formatting
43- 'prettier/prettier' : [ 'warn' , { semi : true } ] ,
44- semi : [ 'error' , 'always' ] ,
45- 'max-len' : [ 'warn' , { code : 300 , ignoreUrls : true } ] ,
45+ /* Ban unsafe casts */
46+ 'no-restricted-syntax' : [
47+ 'error' ,
48+ {
49+ selector : 'TSAsExpression > TSAnyKeyword' ,
50+ message : 'Do not use `as any`, types must be explicit and safe.' ,
51+ } ,
52+ {
53+ selector : "JSXOpeningElement[name.type='JSXIdentifier'][name.name=/^[a-z]/]" ,
54+ message :
55+ 'Do not use native HTML elements: use an MUI component (PascalCase) instead.' ,
56+ } ,
57+ ] ,
4658
47- // Code structure and clarity
59+ /* Code structure and clarity */
4860 // 'max-params': ['warn', 1],
4961 'default-case' : 'warn' ,
50- 'require-await' : 'error' ,
62+ 'import/no-unresolved' : 'error' ,
63+ 'no-inline-comments' : 'warn' ,
5164 'no-undefined' : 'warn' ,
5265 'no-var' : 'error' ,
53- 'prefer-const' : [ 'error' , { destructuring : 'all' } ] ,
66+ 'prefer-const' : [ 'error' , { destructuring : 'all' } ] ,
67+ 'require-await' : 'error' ,
5468 'require-object-destructuring' : 'off' ,
55- 'import/no-unresolved' : 'error' ,
56- 'no-inline-comments' : 'warn' ,
5769
58- // TypeScript strictness
59- '@typescript-eslint/explicit-member-accessibility' : [
60- 'error' ,
61- { accessibility : 'explicit' } ,
62- ] ,
63- '@typescript-eslint/explicit-function-return-type' : [
64- 'error' ,
65- { allowExpressions : false } ,
66- ] ,
67- '@typescript-eslint/explicit-module-boundary-types' : 'error' ,
68- '@typescript-eslint/no-explicit-any' : 'error' ,
69- '@typescript-eslint/no-inferrable-types' : 'off' ,
70- '@typescript-eslint/no-namespace' : 'off' ,
71- '@typescript-eslint/prefer-readonly' : 'warn' ,
72- '@typescript-eslint/prefer-reduce-type-parameter' : 'warn' ,
73- '@typescript-eslint/prefer-function-type' : 'warn' ,
74- '@typescript-eslint/no-magic-numbers' : [
75- 'warn' ,
76- { ignoreEnums : true , ignore : [ 0 , 1 ] , enforceConst : true } ,
77- ] ,
78- '@typescript-eslint/no-unsafe-member-access' : 'warn' ,
79- '@typescript-eslint/no-unused-vars' : [
80- 'error' ,
81- { argsIgnorePattern : '^_' } ,
82- ] ,
83- '@typescript-eslint/no-extraneous-class' : [
84- 'error' ,
85- { allowConstructorOnly : false } ,
86- ] ,
87- '@typescript-eslint/class-literal-property-style' : [ 'warn' , 'fields' ] ,
88- '@typescript-eslint/no-empty-function' : [ 'warn' ] ,
89- '@typescript-eslint/adjacent-overload-signatures' : 'warn' ,
90- '@typescript-eslint/consistent-type-imports' : [
91- 'error' ,
92- {
93- prefer : 'type-imports' ,
94- disallowTypeAnnotations : false ,
95- } ,
96- ] ,
70+ /* Formatting */
71+ 'max-len' : [ 'warn' , { code : 300 , ignoreUrls : true } ] ,
72+ 'prettier/prettier' : [ 'warn' , { semi : true } ] ,
73+ semi : [ 'error' , 'always' ] ,
9774
98- // Naming conventions
75+ /* Naming conventions */
9976 '@typescript-eslint/naming-convention' : [
10077 'error' ,
10178 {
@@ -117,15 +94,59 @@ export default tseslint.config(
11794 format : [ 'PascalCase' ] ,
11895 } ,
11996 ] ,
97+ '@typescript-eslint/typedef' : [
98+ 'error' ,
99+ {
100+ variableDeclaration : true ,
101+ memberVariableDeclaration : true ,
102+ propertyDeclaration : false ,
103+ arrayDestructuring : false ,
104+ objectDestructuring : false ,
105+ parameter : false ,
106+ arrowParameter : false ,
107+ variableDeclarationIgnoreFunction : true ,
108+ } ,
109+ ] ,
120110
121- // Ban unsafe casts
122- 'no-restricted-syntax' : [
111+ /* TypeScript strictness */
112+ '@typescript-eslint/adjacent-overload-signatures' : 'warn' ,
113+ '@typescript-eslint/class-literal-property-style' : [ 'warn' , 'fields' ] ,
114+ '@typescript-eslint/consistent-type-imports' : [
123115 'error' ,
124116 {
125- selector : 'TSAsExpression > TSAnyKeyword ' ,
126- message : 'Do not use `as any`, types must be explicit and safe.' ,
117+ prefer : 'type-imports ' ,
118+ disallowTypeAnnotations : false ,
127119 } ,
128120 ] ,
121+ '@typescript-eslint/explicit-function-return-type' : [
122+ 'error' ,
123+ { allowExpressions : false } ,
124+ ] ,
125+ '@typescript-eslint/explicit-member-accessibility' : [
126+ 'error' ,
127+ { accessibility : 'explicit' } ,
128+ ] ,
129+ '@typescript-eslint/explicit-module-boundary-types' : 'error' ,
130+ '@typescript-eslint/no-empty-function' : [ 'warn' ] ,
131+ '@typescript-eslint/no-extraneous-class' : [
132+ 'error' ,
133+ { allowConstructorOnly : false } ,
134+ ] ,
135+ '@typescript-eslint/no-explicit-any' : 'error' ,
136+ '@typescript-eslint/no-inferrable-types' : 'off' ,
137+ '@typescript-eslint/no-magic-numbers' : [
138+ 'warn' ,
139+ { ignoreEnums : true , ignore : [ 0 , 1 ] , enforceConst : true } ,
140+ ] ,
141+ '@typescript-eslint/no-namespace' : 'off' ,
142+ '@typescript-eslint/no-unsafe-member-access' : 'warn' ,
143+ '@typescript-eslint/no-unused-vars' : [
144+ 'error' ,
145+ { argsIgnorePattern : '^_' } ,
146+ ] ,
147+ '@typescript-eslint/prefer-function-type' : 'warn' ,
148+ '@typescript-eslint/prefer-readonly' : 'warn' ,
149+ '@typescript-eslint/prefer-reduce-type-parameter' : 'warn' ,
129150 } ,
130151 settings : {
131152 'import/resolver' : {
@@ -134,14 +155,17 @@ export default tseslint.config(
134155 project : './tsconfig.json' ,
135156 } ,
136157 } ,
158+ react : {
159+ version : 'detect' ,
160+ } ,
137161 } ,
138162 } ,
139163
140164 {
141165 files : [ '**/*.test.ts' , '**/*.spec.ts' , '**/*.test.tsx' , '**/*.spec.tsx' ] ,
142- plugins : { jest : eslintPluginJest } ,
166+ plugins : { jest : eslintPluginJest } ,
143167 settings : {
144- jest : { version : 29 } ,
168+ jest : { version : 29 } ,
145169 } ,
146170 } ,
147171 ] ,
0 commit comments