1
- // @ts -check
2
- import { FlatCompat } from '@eslint/eslintrc' ;
1
+ import cspellPlugin from '@cspell/eslint-plugin' ;
3
2
import eslint from '@eslint/js' ;
3
+ // @ts -expect-error eslint-plugin-next doesn't come with TypeScript definitions
4
+ import nextPlugin from '@next/eslint-plugin-next' ;
5
+ import stylistic from '@stylistic/eslint-plugin' ;
4
6
import eslintConfigPrettier from 'eslint-config-prettier' ;
5
7
import react from 'eslint-plugin-react' ;
6
8
import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort' ;
@@ -10,18 +12,21 @@ import { fileURLToPath } from 'url';
10
12
11
13
/**
12
14
* @see {@link https://github.com/typescript-eslint/typescript-eslint/blob/main/eslint.config.mjs }
15
+ * @see {@link https://github.com/vercel/next.js/issues/71763#issuecomment-2476838298 }
13
16
*/
14
17
15
- const tsconfigRootDir = fileURLToPath ( new URL ( '.' , import . meta. url ) ) ,
16
- flatCompat = new FlatCompat ( ) ;
18
+ const tsconfigRootDir = fileURLToPath ( new URL ( '.' , import . meta. url ) ) ;
17
19
18
20
export default tsEslint . config (
19
21
// register all of the plugins up-front
20
22
{
21
23
plugins : {
22
24
'@typescript-eslint' : tsEslint . plugin ,
25
+ '@next/next' : nextPlugin ,
23
26
react,
27
+ '@stylistic' : stylistic ,
24
28
'simple-import-sort' : simpleImportSortPlugin ,
29
+ '@cspell' : cspellPlugin ,
25
30
} ,
26
31
} ,
27
32
{
@@ -32,7 +37,6 @@ export default tsEslint.config(
32
37
// extends ...
33
38
eslint . configs . recommended ,
34
39
...tsEslint . configs . recommended ,
35
- ...flatCompat . extends ( 'plugin:@next/next/core-web-vitals' ) ,
36
40
37
41
// base config
38
42
{
@@ -45,13 +49,30 @@ export default tsEslint.config(
45
49
} ,
46
50
} ,
47
51
rules : {
52
+ ...nextPlugin . configs . recommended . rules ,
53
+ ...nextPlugin . configs [ 'core-web-vitals' ] . rules ,
54
+ 'arrow-body-style' : [ 'error' , 'as-needed' ] ,
48
55
'no-empty-pattern' : 'warn' ,
49
- 'simple-import-sort/exports' : 'error' ,
50
- 'simple-import-sort/imports' : 'error' ,
51
- '@typescript-eslint/no-unused-vars' : 'warn' ,
52
- '@typescript-eslint/no-explicit-any' : 'warn' ,
53
- '@typescript-eslint/no-empty-object-type' : 'off' ,
54
- '@typescript-eslint/no-unsafe-declaration-merging' : 'warn' ,
56
+ 'no-console' : [ 'error' , { allow : [ 'warn' , 'error' , 'info' ] } ] ,
57
+ 'no-restricted-syntax' : [
58
+ 'error' ,
59
+ {
60
+ selector : "TSPropertySignature[key.name='children']" ,
61
+ message :
62
+ 'Please use PropsWithChildren<T> instead of defining children manually' ,
63
+ } ,
64
+ ] ,
65
+ 'consistent-return' : 'warn' ,
66
+ 'prefer-destructuring' : [ 'error' , { object : true , array : true } ] ,
67
+ // next
68
+ '@next/next/no-sync-scripts' : 'warn' ,
69
+ // react
70
+ 'react/no-unescaped-entities' : 'off' ,
71
+ 'react/self-closing-comp' : [ 'error' , { component : true , html : true } ] ,
72
+ 'react/jsx-curly-brace-presence' : [
73
+ 'error' ,
74
+ { props : 'never' , children : 'never' } ,
75
+ ] ,
55
76
'react/jsx-no-target-blank' : 'warn' ,
56
77
'react/jsx-sort-props' : [
57
78
'error' ,
@@ -61,18 +82,47 @@ export default tsEslint.config(
61
82
noSortAlphabetically : true ,
62
83
} ,
63
84
] ,
64
- '@next/next/no-sync-scripts' : 'warn' ,
65
- } ,
66
- } ,
67
- {
68
- files : [ '**/*.js' ] ,
69
- extends : [ tsEslint . configs . disableTypeChecked ] ,
70
- rules : {
71
- // turn off other type-aware rules
72
- '@typescript-eslint/internal/no-poorly-typed-ts-props' : 'off' ,
85
+ // typescript
86
+ '@typescript-eslint/no-unused-vars' : 'warn' ,
87
+ '@typescript-eslint/no-explicit-any' : 'warn' ,
88
+ '@typescript-eslint/no-empty-object-type' : 'off' ,
89
+ '@typescript-eslint/no-unsafe-declaration-merging' : 'warn' ,
90
+ '@typescript-eslint/consistent-type-definitions' : [ 'error' , 'interface' ] ,
91
+
92
+ // stylistic
93
+ '@stylistic/padding-line-between-statements' : [
94
+ 'error' ,
95
+ { blankLine : 'always' , prev : '*' , next : 'return' } ,
96
+ { blankLine : 'always' , prev : 'directive' , next : '*' } ,
97
+ { blankLine : 'any' , prev : 'directive' , next : 'directive' } ,
98
+ {
99
+ blankLine : 'always' ,
100
+ prev : '*' ,
101
+ next : [ 'enum' , 'interface' , 'type' ] ,
102
+ } ,
103
+ ] ,
73
104
74
- // turn off rules that don't apply to JS code
75
- '@typescript-eslint/explicit-function-return-type' : 'off' ,
105
+ // simple-import-sort
106
+ 'simple-import-sort/exports' : 'error' ,
107
+ 'simple-import-sort/imports' : 'error' ,
108
+ // spellchecker
109
+ '@cspell/spellchecker' : [
110
+ 'warn' ,
111
+ {
112
+ cspell : {
113
+ language : 'en' ,
114
+ dictionaries : [
115
+ 'typescript' ,
116
+ 'node' ,
117
+ 'html' ,
118
+ 'css' ,
119
+ 'bash' ,
120
+ 'npm' ,
121
+ 'pnpm' ,
122
+ ] ,
123
+ } ,
124
+ } ,
125
+ ] ,
76
126
} ,
77
127
} ,
78
128
eslintConfigPrettier ,
0 commit comments