Skip to content

Commit cebad8a

Browse files
committed
feat: update react options
1 parent 6cc70d3 commit cebad8a

File tree

2 files changed

+57
-33
lines changed

2 files changed

+57
-33
lines changed

src/configs/react.ts

+51-33
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,53 @@
1-
import { isPackageExists } from 'local-pkg'
2-
import { GLOB_SRC } from '../constants/glob'
3-
import { isUsingNext, isUsingRemix } from '../env'
4-
import { ensurePackages, interopDefault, toArray } from '../shared'
1+
import {
2+
GLOB_ASTRO_TS,
3+
GLOB_MARKDOWN,
4+
GLOB_SRC,
5+
GLOB_TS,
6+
GLOB_TSX,
7+
} from '../constants/glob'
8+
import { isAllowConstantExport, isUsingNext, isUsingRemix } from '../env'
9+
10+
import { ensurePackages, interopDefault } from '../shared'
511
import type {
612
OptionsFiles,
713
OptionsOverrides,
14+
OptionsTypeScriptParserOptions,
815
OptionsTypeScriptWithTypes,
916
TypedFlatConfigItem,
1017
} from '../types'
1118

12-
// react refresh
13-
const ReactRefreshAllowConstantExportPackages = ['vite']
14-
1519
export async function react(
16-
options: OptionsTypeScriptWithTypes & OptionsOverrides & OptionsFiles = {},
20+
options: OptionsTypeScriptParserOptions &
21+
OptionsTypeScriptWithTypes &
22+
OptionsOverrides &
23+
OptionsFiles = {},
1724
): Promise<TypedFlatConfigItem[]> {
18-
const { files = [GLOB_SRC], overrides = {} } = options
25+
const {
26+
files = [GLOB_SRC],
27+
filesTypeAware = [GLOB_TS, GLOB_TSX],
28+
ignoresTypeAware = [`${GLOB_MARKDOWN}/**`, GLOB_ASTRO_TS],
29+
overrides = {},
30+
tsconfigPath,
31+
} = options
1932

2033
await ensurePackages([
2134
'@eslint-react/eslint-plugin',
2235
'eslint-plugin-react-hooks',
2336
'eslint-plugin-react-refresh',
2437
])
2538

26-
const tsconfigPath = options?.tsconfigPath
27-
? toArray(options.tsconfigPath)
28-
: undefined
2939
const isTypeAware = !!tsconfigPath
3040

31-
const [pluginReact, pluginReactHooks, pluginReactRefresh, parserTs] =
32-
await Promise.all([
41+
const typeAwareRules: TypedFlatConfigItem['rules'] = {
42+
'react/no-leaked-conditional-rendering': 'warn',
43+
}
44+
45+
const [pluginReact, pluginReactHooks, pluginReactRefresh] = await Promise.all(
46+
[
3347
interopDefault(import('@eslint-react/eslint-plugin')),
3448
interopDefault(import('eslint-plugin-react-hooks')),
3549
interopDefault(import('eslint-plugin-react-refresh')),
36-
interopDefault(import('@typescript-eslint/parser')),
37-
] as const)
38-
39-
const isAllowConstantExport = ReactRefreshAllowConstantExportPackages.some(
40-
(i) => isPackageExists(i),
50+
] as const,
4151
)
4252

4353
const plugins = pluginReact.configs.all.plugins
@@ -57,12 +67,10 @@ export async function react(
5767
{
5868
files,
5969
languageOptions: {
60-
parser: parserTs,
6170
parserOptions: {
6271
ecmaFeatures: {
6372
jsx: true,
6473
},
65-
...(isTypeAware ? { project: tsconfigPath } : {}),
6674
},
6775
sourceType: 'module',
6876
},
@@ -117,25 +125,30 @@ export async function react(
117125

118126
// recommended rules from @eslint-react
119127
'react/ensure-forward-ref-using-ref': 'warn',
128+
'react/jsx-no-duplicate-props': 'warn',
129+
'react/jsx-uses-vars': 'warn',
120130
'react/no-access-state-in-setstate': 'error',
121131
'react/no-array-index-key': 'warn',
122132
'react/no-children-count': 'warn',
123133
'react/no-children-for-each': 'warn',
124134
'react/no-children-map': 'warn',
125135
'react/no-children-only': 'warn',
126-
'react/no-children-prop': 'warn',
127136
'react/no-children-to-array': 'warn',
128137
'react/no-clone-element': 'warn',
129138
'react/no-comment-textnodes': 'warn',
130139
'react/no-component-will-mount': 'error',
131140
'react/no-component-will-receive-props': 'error',
132141
'react/no-component-will-update': 'error',
142+
'react/no-context-provider': 'warn',
133143
'react/no-create-ref': 'error',
144+
'react/no-default-props': 'error',
134145
'react/no-direct-mutation-state': 'error',
135146
'react/no-duplicate-key': 'error',
136-
'react/no-implicit-key': 'error',
147+
'react/no-forward-ref': 'warn',
148+
'react/no-implicit-key': 'warn',
137149
'react/no-missing-key': 'error',
138-
'react/no-nested-components': 'warn',
150+
'react/no-nested-components': 'error',
151+
'react/no-prop-types': 'error',
139152
'react/no-redundant-should-component-update': 'error',
140153
'react/no-set-state-in-component-did-mount': 'warn',
141154
'react/no-set-state-in-component-did-update': 'warn',
@@ -144,24 +157,29 @@ export async function react(
144157
'react/no-unsafe-component-will-mount': 'warn',
145158
'react/no-unsafe-component-will-receive-props': 'warn',
146159
'react/no-unsafe-component-will-update': 'warn',
147-
'react/no-unstable-context-value': 'error',
148-
'react/no-unstable-default-props': 'error',
160+
'react/no-unstable-context-value': 'warn',
161+
'react/no-unstable-default-props': 'warn',
149162
'react/no-unused-class-component-members': 'warn',
150163
'react/no-unused-state': 'warn',
151-
'react/no-useless-fragment': 'warn',
152164
'react/prefer-destructuring-assignment': 'warn',
153165
'react/prefer-shorthand-boolean': 'warn',
154166
'react/prefer-shorthand-fragment': 'warn',
155167

156-
...(isTypeAware
157-
? {
158-
'react/no-leaked-conditional-rendering': 'warn',
159-
}
160-
: {}),
161-
162168
// overrides
163169
...overrides,
164170
},
165171
},
172+
...(isTypeAware
173+
? [
174+
{
175+
files: filesTypeAware,
176+
ignores: ignoresTypeAware,
177+
name: 'coderwyd/react/type-aware-rules',
178+
rules: {
179+
...typeAwareRules,
180+
},
181+
},
182+
]
183+
: []),
166184
]
167185
}

src/env.ts

+6
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,15 @@ const RemixPackages = [
2424

2525
const NextJsPackages = ['next']
2626

27+
// react refresh
28+
const ReactRefreshAllowConstantExportPackages = ['vite']
29+
2730
// export const hasReact = hasPackages(['react', ...RemixPackages, ...NextJsPackages])
2831
export const isUsingRemix = hasPackages(RemixPackages)
2932
export const isUsingNext = hasPackages(NextJsPackages)
33+
export const isAllowConstantExport = hasPackages(
34+
ReactRefreshAllowConstantExportPackages,
35+
)
3036

3137
function hasPackages(packages: string[]) {
3238
return packages.some((name) => isPackageExists(name))

0 commit comments

Comments
 (0)