Skip to content

Commit

Permalink
feat: add recommended presets for each plugin (#940)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rel1cx authored Feb 18, 2025
1 parent 74a6eac commit 102d4e0
Show file tree
Hide file tree
Showing 27 changed files with 614 additions and 280 deletions.
12 changes: 1 addition & 11 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,7 @@
"eslint.workingDirectories": [
{
"changeProcessCWD": true,
"mode": "location"
},
{
"changeProcessCWD": true,
"mode": "auto",
"pattern": "examples/*"
},
{
"changeProcessCWD": true,
"mode": "auto",
"pattern": "apps/*"
"mode": "auto"
}
],
"files.exclude": {
Expand Down
23 changes: 19 additions & 4 deletions examples/dual-react-dom-lib/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import eslintJs from "@eslint/js";
import eslintReact from "@eslint-react/eslint-plugin";
import eslintPluginReactx from "eslint-plugin-react-x";
import eslintPluginReactDom from "eslint-plugin-react-dom";
import eslintPluginReactWebApi from "eslint-plugin-react-web-api";
import eslintPluginReactHooks from "eslint-plugin-react-hooks";
import eslintPluginReactHooksExtra from "eslint-plugin-react-hooks-extra";
import eslintPluginReactNamingConvention from "eslint-plugin-react-naming-convention";
import tseslint from "typescript-eslint";

import TSCONFIG from "./tsconfig.json" with { type: "json" };
Expand Down Expand Up @@ -45,12 +49,23 @@ export default tseslint.config(
"no-console": "off",
},
},
// React configuration
// react specific configurations
{
files: TSCONFIG.include,
...eslintReact.configs["recommended-type-checked"],
...eslintPluginReactx.configs["recommended-type-checked"],
},
{
files: TSCONFIG.include,
...eslintPluginReactDom.configs.recommended,
},
{
files: TSCONFIG.include,
...eslintPluginReactWebApi.configs.recommended,
},
{
files: TSCONFIG.include,
...eslintPluginReactHooksExtra.configs.recommended,
},
// React Hooks configuration
{
files: TSCONFIG.include,
plugins: {
Expand Down
6 changes: 5 additions & 1 deletion examples/dual-react-dom-lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@
"prepare": "pnpm run build"
},
"devDependencies": {
"@eslint-react/eslint-plugin": "workspace:*",
"eslint-plugin-react-x": "workspace:*",
"eslint-plugin-react-dom": "workspace:*",
"eslint-plugin-react-web-api": "workspace:*",
"eslint-plugin-react-hooks-extra": "workspace:*",
"eslint-plugin-react-naming-convention": "workspace:*",
"@eslint/js": "^9.20.0",
"@tsconfig/node22": "^22.0.0",
"@tsconfig/strictest": "^2.0.5",
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,18 @@
},
"pnpm": {
"overrides": {
"is-core-module": "npm:@socketregistry/is-core-module@^1.0.7",
"safe-buffer": "npm:@socketregistry/safe-buffer@^1.0.6",
"safer-buffer": "npm:@socketregistry/safer-buffer@^1.0.6",
"typedarray": "npm:@socketregistry/typedarray@^1.0.5",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"cross-spawn": "^7.0.6",
"esbuild": "^0.25.0",
"is-core-module": "npm:@socketregistry/is-core-module@^1.0.7",
"next": "^15.1.7",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"safe-buffer": "npm:@socketregistry/safe-buffer@^1.0.6",
"safer-buffer": "npm:@socketregistry/safer-buffer@^1.0.6",
"ts-api-utils": "^2.0.1",
"typedarray": "npm:@socketregistry/typedarray@^1.0.5",
"typescript": "^5.7.3"
}
}
Expand Down
15 changes: 15 additions & 0 deletions packages/plugins/eslint-plugin-react-debug/src/configs/all.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { RulePreset } from "@eslint-react/shared";
import { DEFAULT_ESLINT_REACT_SETTINGS } from "@eslint-react/shared";

export const name = "react-debug/all";

export const rules = {
"react-debug/class-component": "warn",
"react-debug/function-component": "warn",
"react-debug/hook": "warn",
"react-debug/is-from-react": "off",
} as const satisfies RulePreset;

export const settings = {
"react-x": DEFAULT_ESLINT_REACT_SETTINGS,
};
44 changes: 25 additions & 19 deletions packages/plugins/eslint-plugin-react-debug/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
import { name, version } from "../package.json";
import classComponent from "./rules/class-component";
import functionComponent from "./rules/function-component";
import hook from "./rules/hook";
import isFromReact from "./rules/is-from-react";
import type { RulePreset } from "@eslint-react/shared";

export default {
meta: {
name,
version,
},
rules: {
"class-component": classComponent,
"function-component": functionComponent,
hook: hook,
"is-from-react": isFromReact,
import * as allConfig from "./configs/all";
import { plugin } from "./plugin";

function makeConfig(config: { name: string; rules: RulePreset }) {
return {
...config,
plugins: {
"react-x": plugin,
},
};
}

// Part: deprecated rules
/** @deprecated Use `hook` instead */
"react-hooks": hook,
function makeLegacyConfig(config: { rules: RulePreset }) {
return {
plugins: ["react-x"],
rules: config.rules,
};
}

export default {
...plugin,
configs: {
["all"]: makeConfig(allConfig),
["all-legacy"]: makeLegacyConfig(allConfig),
},
} as const;
};
22 changes: 22 additions & 0 deletions packages/plugins/eslint-plugin-react-debug/src/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { name, version } from "../package.json";
import classComponent from "./rules/class-component";
import functionComponent from "./rules/function-component";
import hook from "./rules/hook";
import isFromReact from "./rules/is-from-react";

export const plugin = {
meta: {
name,
version,
},
rules: {
"class-component": classComponent,
"function-component": functionComponent,
hook: hook,
"is-from-react": isFromReact,

// Part: deprecated rules
/** @deprecated Use `hook` instead */
"react-hooks": hook,
},
} as const;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { RulePreset } from "@eslint-react/shared";
import { DEFAULT_ESLINT_REACT_SETTINGS } from "@eslint-react/shared";

export const name = "react-dom/recommended";

export const rules = {
"react-dom/no-dangerously-set-innerhtml": "warn",
"react-dom/no-dangerously-set-innerhtml-with-children": "error",
"react-dom/no-find-dom-node": "error",
"react-dom/no-missing-button-type": "warn",
"react-dom/no-missing-iframe-sandbox": "warn",
"react-dom/no-namespace": "error",
"react-dom/no-render-return-value": "error",
"react-dom/no-script-url": "warn",
"react-dom/no-unknown-property": "warn",
"react-dom/no-unsafe-iframe-sandbox": "warn",
"react-dom/no-unsafe-target-blank": "warn",
"react-dom/no-void-elements-with-children": "warn",
} as const satisfies RulePreset;

export const settings = {
"react-x": DEFAULT_ESLINT_REACT_SETTINGS,
};
60 changes: 25 additions & 35 deletions packages/plugins/eslint-plugin-react-dom/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,28 @@
import { name, version } from "../package.json";
import noDangerouslySetInnerHTML from "./rules/no-dangerously-set-innerhtml";
import noDangerouslySetInnerHTMLWithChildren from "./rules/no-dangerously-set-innerhtml-with-children";
import noFindDomNode from "./rules/no-find-dom-node";
import noMissingButtonType from "./rules/no-missing-button-type";
import noMissingIframeSandbox from "./rules/no-missing-iframe-sandbox";
import noNamespace from "./rules/no-namespace";
import noRenderReturnValue from "./rules/no-render-return-value";
import noScriptUrl from "./rules/no-script-url";
import noUnknownProperty from "./rules/no-unknown-property";
import noUnsafeIframeSandbox from "./rules/no-unsafe-iframe-sandbox";
import noUnsafeTargetBlank from "./rules/no-unsafe-target-blank";
import noVoidElementsWithChildren from "./rules/no-void-elements-with-children";
import type { RulePreset } from "@eslint-react/shared";

export default {
meta: {
name,
version,
},
rules: {
"no-dangerously-set-innerhtml": noDangerouslySetInnerHTML,
"no-dangerously-set-innerhtml-with-children": noDangerouslySetInnerHTMLWithChildren,
"no-find-dom-node": noFindDomNode,
"no-missing-button-type": noMissingButtonType,
"no-missing-iframe-sandbox": noMissingIframeSandbox,
"no-namespace": noNamespace,
"no-render-return-value": noRenderReturnValue,
"no-script-url": noScriptUrl,
"no-unknown-property": noUnknownProperty,
"no-unsafe-iframe-sandbox": noUnsafeIframeSandbox,
"no-unsafe-target-blank": noUnsafeTargetBlank,
"no-void-elements-with-children": noVoidElementsWithChildren,
import * as recommendedConfig from "./configs/recommended";
import { plugin } from "./plugin";

function makeConfig(config: { name: string; rules: RulePreset }) {
return {
...config,
plugins: {
"react-x": plugin,
},
};
}

// Part: deprecated rules
/** @deprecated Use `no-void-elements-with-children` instead */
"no-children-in-void-dom-elements": noVoidElementsWithChildren,
function makeLegacyConfig(config: { rules: RulePreset }) {
return {
plugins: ["react-x"],
rules: config.rules,
};
}

export default {
...plugin,
configs: {
["recommended"]: makeConfig(recommendedConfig),
["recommended-legacy"]: makeLegacyConfig(recommendedConfig),
},
} as const;
};
38 changes: 38 additions & 0 deletions packages/plugins/eslint-plugin-react-dom/src/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { name, version } from "../package.json";
import noDangerouslySetInnerHTML from "./rules/no-dangerously-set-innerhtml";
import noDangerouslySetInnerHTMLWithChildren from "./rules/no-dangerously-set-innerhtml-with-children";
import noFindDomNode from "./rules/no-find-dom-node";
import noMissingButtonType from "./rules/no-missing-button-type";
import noMissingIframeSandbox from "./rules/no-missing-iframe-sandbox";
import noNamespace from "./rules/no-namespace";
import noRenderReturnValue from "./rules/no-render-return-value";
import noScriptUrl from "./rules/no-script-url";
import noUnknownProperty from "./rules/no-unknown-property";
import noUnsafeIframeSandbox from "./rules/no-unsafe-iframe-sandbox";
import noUnsafeTargetBlank from "./rules/no-unsafe-target-blank";
import noVoidElementsWithChildren from "./rules/no-void-elements-with-children";

export const plugin = {
meta: {
name,
version,
},
rules: {
"no-dangerously-set-innerhtml": noDangerouslySetInnerHTML,
"no-dangerously-set-innerhtml-with-children": noDangerouslySetInnerHTMLWithChildren,
"no-find-dom-node": noFindDomNode,
"no-missing-button-type": noMissingButtonType,
"no-missing-iframe-sandbox": noMissingIframeSandbox,
"no-namespace": noNamespace,
"no-render-return-value": noRenderReturnValue,
"no-script-url": noScriptUrl,
"no-unknown-property": noUnknownProperty,
"no-unsafe-iframe-sandbox": noUnsafeIframeSandbox,
"no-unsafe-target-blank": noUnsafeTargetBlank,
"no-void-elements-with-children": noVoidElementsWithChildren,

// Part: deprecated rules
/** @deprecated Use `no-void-elements-with-children` instead */
"no-children-in-void-dom-elements": noVoidElementsWithChildren,
},
} as const;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { RulePreset } from "@eslint-react/shared";

export const name = "react-hooks-extra/recommended";

export const rules = {
"react-hooks-extra/no-direct-set-state-in-use-effect": "warn",
"react-hooks-extra/no-useless-custom-hooks": "warn",
"react-hooks-extra/prefer-use-state-lazy-initialization": "warn",
} as const satisfies RulePreset;
54 changes: 25 additions & 29 deletions packages/plugins/eslint-plugin-react-hooks-extra/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
import { name, version } from "../package.json";
import noDirectSetStateInUseEffect from "./rules/no-direct-set-state-in-use-effect";
import noDirectSetStateInUseLayoutEffect from "./rules/no-direct-set-state-in-use-layout-effect";
import noUnnecessaryUseCallback from "./rules/no-unnecessary-use-callback";
import noUnnecessaryUseMemo from "./rules/no-unnecessary-use-memo";
import noUselessCustomHooks from "./rules/no-useless-custom-hooks";
import preferUseStateLazyInitialization from "./rules/prefer-use-state-lazy-initialization";
import type { RulePreset } from "@eslint-react/shared";

export default {
meta: {
name,
version,
},
rules: {
"no-direct-set-state-in-use-effect": noDirectSetStateInUseEffect,
"no-direct-set-state-in-use-layout-effect": noDirectSetStateInUseLayoutEffect,
"no-unnecessary-use-callback": noUnnecessaryUseCallback,
"no-unnecessary-use-memo": noUnnecessaryUseMemo,
"no-useless-custom-hooks": noUselessCustomHooks,
"prefer-use-state-lazy-initialization": preferUseStateLazyInitialization,
import * as recommendedConfig from "./configs/recommended";
import { plugin } from "./plugin";

function makeConfig(config: { name: string; rules: RulePreset }) {
return {
...config,
plugins: {
"react-x": plugin,
},
};
}

// Part: deprecated rules
/** @deprecated Use `no-useless-custom-hooks` instead */
"ensure-custom-hooks-using-other-hooks": noUselessCustomHooks,
/** @deprecated Use `no-unnecessary-use-callback` instead */
"ensure-use-callback-has-non-empty-deps": noUnnecessaryUseCallback,
/** @deprecated Use `no-unnecessary-use-memo` instead */
"ensure-use-memo-has-non-empty-deps": noUnnecessaryUseMemo,
/** @deprecated Use `no-useless-custom-hooks` instead */
"no-redundant-custom-hook": noUselessCustomHooks,
function makeLegacyConfig(config: { rules: RulePreset }) {
return {
plugins: ["react-x"],
rules: config.rules,
};
}

export default {
...plugin,
configs: {
["recommended"]: makeConfig(recommendedConfig),
["recommended-legacy"]: makeLegacyConfig(recommendedConfig),
},
} as const;
};
Loading

0 comments on commit 102d4e0

Please sign in to comment.