Skip to content

Commit 10b24b0

Browse files
committed
feat(plugins): introduce recommended configurations for each plugin
1 parent 3dcb56e commit 10b24b0

File tree

30 files changed

+640
-341
lines changed

30 files changed

+640
-341
lines changed

.vscode/settings.json

+1-11
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,7 @@
3333
"eslint.workingDirectories": [
3434
{
3535
"changeProcessCWD": true,
36-
"mode": "location"
37-
},
38-
{
39-
"changeProcessCWD": true,
40-
"mode": "auto",
41-
"pattern": "examples/*"
42-
},
43-
{
44-
"changeProcessCWD": true,
45-
"mode": "auto",
46-
"pattern": "apps/*"
36+
"mode": "auto"
4737
}
4838
],
4939
"files.exclude": {

examples/dual-react-dom-lib/eslint.config.mjs

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import eslintJs from "@eslint/js";
2-
import eslintReact from "@eslint-react/eslint-plugin";
2+
import eslintPluginReactx from "eslint-plugin-react-x";
3+
import eslintPluginReactDom from "eslint-plugin-react-dom";
4+
import eslintPluginReactWebApi from "eslint-plugin-react-web-api";
35
import eslintPluginReactHooks from "eslint-plugin-react-hooks";
6+
import eslintPluginReactHooksExtra from "eslint-plugin-react-hooks-extra";
7+
import eslintPluginReactNamingConvention from "eslint-plugin-react-naming-convention";
48
import tseslint from "typescript-eslint";
59

610
import TSCONFIG from "./tsconfig.json" with { type: "json" };
@@ -45,12 +49,23 @@ export default tseslint.config(
4549
"no-console": "off",
4650
},
4751
},
48-
// React configuration
52+
// react specific configurations
4953
{
5054
files: TSCONFIG.include,
51-
...eslintReact.configs["recommended-type-checked"],
55+
...eslintPluginReactx.configs["recommended-type-checked"],
56+
},
57+
{
58+
files: TSCONFIG.include,
59+
...eslintPluginReactDom.configs.recommended,
60+
},
61+
{
62+
files: TSCONFIG.include,
63+
...eslintPluginReactWebApi.configs.recommended,
64+
},
65+
{
66+
files: TSCONFIG.include,
67+
...eslintPluginReactHooksExtra.configs.recommended,
5268
},
53-
// React Hooks configuration
5469
{
5570
files: TSCONFIG.include,
5671
plugins: {

examples/dual-react-dom-lib/package.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@
3131
"prepare": "pnpm run build"
3232
},
3333
"devDependencies": {
34-
"@eslint-react/eslint-plugin": "workspace:*",
34+
"eslint-plugin-react-x": "workspace:*",
35+
"eslint-plugin-react-dom": "workspace:*",
36+
"eslint-plugin-react-web-api": "workspace:*",
37+
"eslint-plugin-react-hooks-extra": "workspace:*",
38+
"eslint-plugin-react-naming-convention": "workspace:*",
3539
"@eslint/js": "^9.20.0",
3640
"@tsconfig/node22": "^22.0.0",
3741
"@tsconfig/strictest": "^2.0.5",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { RulePreset } from "@eslint-react/shared";
2+
import { DEFAULT_ESLINT_REACT_SETTINGS } from "@eslint-react/shared";
3+
4+
export const name = "react-debug/all";
5+
6+
export const rules = {
7+
"react-debug/class-component": "warn",
8+
"react-debug/function-component": "warn",
9+
"react-debug/hook": "warn",
10+
"react-debug/is-from-react": "off",
11+
} as const satisfies RulePreset;
12+
13+
export const settings = {
14+
"react-x": DEFAULT_ESLINT_REACT_SETTINGS,
15+
};
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
1-
import { name, version } from "../package.json";
2-
import classComponent from "./rules/class-component";
3-
import functionComponent from "./rules/function-component";
4-
import hook from "./rules/hook";
5-
import isFromReact from "./rules/is-from-react";
1+
import type { Linter } from "eslint";
62

7-
export default {
8-
meta: {
9-
name,
10-
version,
11-
},
12-
rules: {
13-
"class-component": classComponent,
14-
"function-component": functionComponent,
15-
hook: hook,
16-
"is-from-react": isFromReact,
3+
import * as allConfig from "./configs/all";
4+
import { plugin } from "./plugin";
5+
6+
function makeConfig(config: Linter.Config): Linter.Config {
7+
return {
8+
...config,
9+
plugins: {
10+
...config.plugins,
11+
"react-dom": plugin,
12+
},
13+
};
14+
}
1715

18-
// Part: deprecated rules
19-
/** @deprecated Use `hook` instead */
20-
"react-hooks": hook,
16+
function toLegacyConfig({ rules }: Linter.Config): Linter.LegacyConfig {
17+
return {
18+
plugins: ["react-debug"],
19+
rules,
20+
};
21+
}
22+
23+
export default {
24+
...plugin,
25+
configs: {
26+
["all"]: makeConfig(allConfig),
27+
["all-legacy"]: toLegacyConfig(allConfig),
2128
},
22-
} as const;
29+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type { ESLint } from "eslint";
2+
3+
import { name, version } from "../package.json";
4+
import classComponent from "./rules/class-component";
5+
import functionComponent from "./rules/function-component";
6+
import hook from "./rules/hook";
7+
import isFromReact from "./rules/is-from-react";
8+
9+
export const plugin = {
10+
meta: {
11+
name,
12+
version,
13+
},
14+
rules: {
15+
"class-component": classComponent,
16+
"function-component": functionComponent,
17+
hook: hook,
18+
"is-from-react": isFromReact,
19+
20+
// Part: deprecated rules
21+
/** @deprecated Use `hook` instead */
22+
"react-hooks": hook,
23+
},
24+
// remove this type assertion when the typescript-eslint and eslint type incompatible issue is resolved
25+
} as unknown as ESLint.Plugin;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { RulePreset } from "@eslint-react/shared";
2+
import { DEFAULT_ESLINT_REACT_SETTINGS } from "@eslint-react/shared";
3+
4+
export const name = "react-dom/recommended";
5+
6+
export const rules = {
7+
"react-dom/no-dangerously-set-innerhtml": "warn",
8+
"react-dom/no-dangerously-set-innerhtml-with-children": "error",
9+
"react-dom/no-find-dom-node": "error",
10+
"react-dom/no-missing-button-type": "warn",
11+
"react-dom/no-missing-iframe-sandbox": "warn",
12+
"react-dom/no-namespace": "error",
13+
"react-dom/no-render-return-value": "error",
14+
"react-dom/no-script-url": "warn",
15+
"react-dom/no-unknown-property": "warn",
16+
"react-dom/no-unsafe-iframe-sandbox": "warn",
17+
"react-dom/no-unsafe-target-blank": "warn",
18+
"react-dom/no-void-elements-with-children": "warn",
19+
} as const satisfies RulePreset;
20+
21+
export const settings = {
22+
"react-x": DEFAULT_ESLINT_REACT_SETTINGS,
23+
};
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,29 @@
1-
import { name, version } from "../package.json";
2-
import noDangerouslySetInnerHTML from "./rules/no-dangerously-set-innerhtml";
3-
import noDangerouslySetInnerHTMLWithChildren from "./rules/no-dangerously-set-innerhtml-with-children";
4-
import noFindDomNode from "./rules/no-find-dom-node";
5-
import noMissingButtonType from "./rules/no-missing-button-type";
6-
import noMissingIframeSandbox from "./rules/no-missing-iframe-sandbox";
7-
import noNamespace from "./rules/no-namespace";
8-
import noRenderReturnValue from "./rules/no-render-return-value";
9-
import noScriptUrl from "./rules/no-script-url";
10-
import noUnknownProperty from "./rules/no-unknown-property";
11-
import noUnsafeIframeSandbox from "./rules/no-unsafe-iframe-sandbox";
12-
import noUnsafeTargetBlank from "./rules/no-unsafe-target-blank";
13-
import noVoidElementsWithChildren from "./rules/no-void-elements-with-children";
1+
import type { Linter } from "eslint";
142

15-
export default {
16-
meta: {
17-
name,
18-
version,
19-
},
20-
rules: {
21-
"no-dangerously-set-innerhtml": noDangerouslySetInnerHTML,
22-
"no-dangerously-set-innerhtml-with-children": noDangerouslySetInnerHTMLWithChildren,
23-
"no-find-dom-node": noFindDomNode,
24-
"no-missing-button-type": noMissingButtonType,
25-
"no-missing-iframe-sandbox": noMissingIframeSandbox,
26-
"no-namespace": noNamespace,
27-
"no-render-return-value": noRenderReturnValue,
28-
"no-script-url": noScriptUrl,
29-
"no-unknown-property": noUnknownProperty,
30-
"no-unsafe-iframe-sandbox": noUnsafeIframeSandbox,
31-
"no-unsafe-target-blank": noUnsafeTargetBlank,
32-
"no-void-elements-with-children": noVoidElementsWithChildren,
3+
import * as recommendedConfig from "./configs/recommended";
4+
import { plugin } from "./plugin";
5+
6+
function makeConfig(config: Linter.Config): Linter.Config {
7+
return {
8+
...config,
9+
plugins: {
10+
...config.plugins,
11+
"react-dom": plugin,
12+
},
13+
};
14+
}
3315

34-
// Part: deprecated rules
35-
/** @deprecated Use `no-void-elements-with-children` instead */
36-
"no-children-in-void-dom-elements": noVoidElementsWithChildren,
16+
function toLegacyConfig({ rules }: Linter.Config): Linter.LegacyConfig {
17+
return {
18+
plugins: ["react-dom"],
19+
rules,
20+
};
21+
}
22+
23+
export default {
24+
...plugin,
25+
configs: {
26+
["recommended"]: makeConfig(recommendedConfig),
27+
["recommended-legacy"]: toLegacyConfig(recommendedConfig),
3728
},
38-
} as const;
29+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import type { ESLint } from "eslint";
2+
3+
import { name, version } from "../package.json";
4+
import noDangerouslySetInnerHTML from "./rules/no-dangerously-set-innerhtml";
5+
import noDangerouslySetInnerHTMLWithChildren from "./rules/no-dangerously-set-innerhtml-with-children";
6+
import noFindDomNode from "./rules/no-find-dom-node";
7+
import noMissingButtonType from "./rules/no-missing-button-type";
8+
import noMissingIframeSandbox from "./rules/no-missing-iframe-sandbox";
9+
import noNamespace from "./rules/no-namespace";
10+
import noRenderReturnValue from "./rules/no-render-return-value";
11+
import noScriptUrl from "./rules/no-script-url";
12+
import noUnknownProperty from "./rules/no-unknown-property";
13+
import noUnsafeIframeSandbox from "./rules/no-unsafe-iframe-sandbox";
14+
import noUnsafeTargetBlank from "./rules/no-unsafe-target-blank";
15+
import noVoidElementsWithChildren from "./rules/no-void-elements-with-children";
16+
17+
export const plugin = {
18+
meta: {
19+
name,
20+
version,
21+
},
22+
rules: {
23+
"no-dangerously-set-innerhtml": noDangerouslySetInnerHTML,
24+
"no-dangerously-set-innerhtml-with-children": noDangerouslySetInnerHTMLWithChildren,
25+
"no-find-dom-node": noFindDomNode,
26+
"no-missing-button-type": noMissingButtonType,
27+
"no-missing-iframe-sandbox": noMissingIframeSandbox,
28+
"no-namespace": noNamespace,
29+
"no-render-return-value": noRenderReturnValue,
30+
"no-script-url": noScriptUrl,
31+
"no-unknown-property": noUnknownProperty,
32+
"no-unsafe-iframe-sandbox": noUnsafeIframeSandbox,
33+
"no-unsafe-target-blank": noUnsafeTargetBlank,
34+
"no-void-elements-with-children": noVoidElementsWithChildren,
35+
36+
// Part: deprecated rules
37+
/** @deprecated Use `no-void-elements-with-children` instead */
38+
"no-children-in-void-dom-elements": noVoidElementsWithChildren,
39+
},
40+
// remove this type assertion when the typescript-eslint and eslint type incompatible issue is resolved
41+
} as unknown as ESLint.Plugin;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { RulePreset } from "@eslint-react/shared";
2+
3+
export const name = "react-hooks-extra/recommended";
4+
5+
export const rules = {
6+
"react-hooks-extra/no-direct-set-state-in-use-effect": "warn",
7+
"react-hooks-extra/no-useless-custom-hooks": "warn",
8+
"react-hooks-extra/prefer-use-state-lazy-initialization": "warn",
9+
} as const satisfies RulePreset;
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,29 @@
1-
import { name, version } from "../package.json";
2-
import noDirectSetStateInUseEffect from "./rules/no-direct-set-state-in-use-effect";
3-
import noDirectSetStateInUseLayoutEffect from "./rules/no-direct-set-state-in-use-layout-effect";
4-
import noUnnecessaryUseCallback from "./rules/no-unnecessary-use-callback";
5-
import noUnnecessaryUseMemo from "./rules/no-unnecessary-use-memo";
6-
import noUselessCustomHooks from "./rules/no-useless-custom-hooks";
7-
import preferUseStateLazyInitialization from "./rules/prefer-use-state-lazy-initialization";
1+
import type { Linter } from "eslint";
82

9-
export default {
10-
meta: {
11-
name,
12-
version,
13-
},
14-
rules: {
15-
"no-direct-set-state-in-use-effect": noDirectSetStateInUseEffect,
16-
"no-direct-set-state-in-use-layout-effect": noDirectSetStateInUseLayoutEffect,
17-
"no-unnecessary-use-callback": noUnnecessaryUseCallback,
18-
"no-unnecessary-use-memo": noUnnecessaryUseMemo,
19-
"no-useless-custom-hooks": noUselessCustomHooks,
20-
"prefer-use-state-lazy-initialization": preferUseStateLazyInitialization,
3+
import * as recommendedConfig from "./configs/recommended";
4+
import { plugin } from "./plugin";
5+
6+
function makeConfig(config: Linter.Config): Linter.Config {
7+
return {
8+
...config,
9+
plugins: {
10+
...config.plugins,
11+
"react-hooks-extra": plugin,
12+
},
13+
};
14+
}
2115

22-
// Part: deprecated rules
23-
/** @deprecated Use `no-useless-custom-hooks` instead */
24-
"ensure-custom-hooks-using-other-hooks": noUselessCustomHooks,
25-
/** @deprecated Use `no-unnecessary-use-callback` instead */
26-
"ensure-use-callback-has-non-empty-deps": noUnnecessaryUseCallback,
27-
/** @deprecated Use `no-unnecessary-use-memo` instead */
28-
"ensure-use-memo-has-non-empty-deps": noUnnecessaryUseMemo,
29-
/** @deprecated Use `no-useless-custom-hooks` instead */
30-
"no-redundant-custom-hook": noUselessCustomHooks,
16+
function toLegacyConfig({ rules }: Linter.Config): Linter.LegacyConfig {
17+
return {
18+
plugins: ["react-hooks-extra"],
19+
rules,
20+
};
21+
}
22+
23+
export default {
24+
...plugin,
25+
configs: {
26+
["recommended"]: makeConfig(recommendedConfig),
27+
["recommended-legacy"]: toLegacyConfig(recommendedConfig),
3128
},
32-
} as const;
29+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type { ESLint } from "eslint";
2+
3+
import { name, version } from "../package.json";
4+
import noDirectSetStateInUseEffect from "./rules/no-direct-set-state-in-use-effect";
5+
import noDirectSetStateInUseLayoutEffect from "./rules/no-direct-set-state-in-use-layout-effect";
6+
import noUnnecessaryUseCallback from "./rules/no-unnecessary-use-callback";
7+
import noUnnecessaryUseMemo from "./rules/no-unnecessary-use-memo";
8+
import noUselessCustomHooks from "./rules/no-useless-custom-hooks";
9+
import preferUseStateLazyInitialization from "./rules/prefer-use-state-lazy-initialization";
10+
11+
export const plugin = {
12+
meta: {
13+
name,
14+
version,
15+
},
16+
rules: {
17+
"no-direct-set-state-in-use-effect": noDirectSetStateInUseEffect,
18+
"no-direct-set-state-in-use-layout-effect": noDirectSetStateInUseLayoutEffect,
19+
"no-unnecessary-use-callback": noUnnecessaryUseCallback,
20+
"no-unnecessary-use-memo": noUnnecessaryUseMemo,
21+
"no-useless-custom-hooks": noUselessCustomHooks,
22+
"prefer-use-state-lazy-initialization": preferUseStateLazyInitialization,
23+
24+
// Part: deprecated rules
25+
/** @deprecated Use `no-useless-custom-hooks` instead */
26+
"ensure-custom-hooks-using-other-hooks": noUselessCustomHooks,
27+
/** @deprecated Use `no-unnecessary-use-callback` instead */
28+
"ensure-use-callback-has-non-empty-deps": noUnnecessaryUseCallback,
29+
/** @deprecated Use `no-unnecessary-use-memo` instead */
30+
"ensure-use-memo-has-non-empty-deps": noUnnecessaryUseMemo,
31+
/** @deprecated Use `no-useless-custom-hooks` instead */
32+
"no-redundant-custom-hook": noUselessCustomHooks,
33+
},
34+
// remove this type assertion when the typescript-eslint and eslint type incompatible issue is resolved
35+
} as unknown as ESLint.Plugin;

0 commit comments

Comments
 (0)