From 6e399072935b5ab7fa697d3df5b01f3f61abd919 Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Tue, 16 Jul 2024 22:33:10 +0200 Subject: [PATCH] feat: `eslint-plugin-react` supports ESLint v9 --- lib/config-generator.js | 35 +++---------------- ...ipt => problems-commonjs-react-javascript} | 11 +++--- ...ipt => problems-commonjs-react-typescript} | 10 +++--- ...vascript => problems-esm-react-javascript} | 9 +++-- ...pescript => problems-esm-react-typescript} | 9 +++-- .../problems-script-react-javascript | 24 +++++++++++++ ...cript => problems-script-react-typescript} | 13 +++---- .../syntax-commonjs-react-javascript | 21 +++++++++++ .../syntax-commonjs-react-typescript | 25 +++++++++++++ .../syntax-esm-react-eslint9.x-javascript | 24 ------------- ...javascript => syntax-esm-react-javascript} | 9 +++-- ...typescript => syntax-esm-react-typescript} | 9 +++-- .../syntax-script-react-javascript | 21 +++++++++++ .../syntax-script-react-typescript | 25 +++++++++++++ tests/config-snapshots.spec.js | 13 ++----- 15 files changed, 153 insertions(+), 105 deletions(-) rename tests/__snapshots__/{problems-esm-react-eslint9.x-javascript => problems-commonjs-react-javascript} (52%) rename tests/__snapshots__/{problems-esm-react-eslint9.x-typescript => problems-commonjs-react-typescript} (60%) rename tests/__snapshots__/{problems-esm-react-eslint8.x-javascript => problems-esm-react-javascript} (58%) rename tests/__snapshots__/{problems-esm-react-eslint8.x-typescript => problems-esm-react-typescript} (66%) create mode 100644 tests/__snapshots__/problems-script-react-javascript rename tests/__snapshots__/{syntax-esm-react-eslint9.x-typescript => problems-script-react-typescript} (55%) create mode 100644 tests/__snapshots__/syntax-commonjs-react-javascript create mode 100644 tests/__snapshots__/syntax-commonjs-react-typescript delete mode 100644 tests/__snapshots__/syntax-esm-react-eslint9.x-javascript rename tests/__snapshots__/{syntax-esm-react-eslint8.x-javascript => syntax-esm-react-javascript} (51%) rename tests/__snapshots__/{syntax-esm-react-eslint8.x-typescript => syntax-esm-react-typescript} (61%) create mode 100644 tests/__snapshots__/syntax-script-react-javascript create mode 100644 tests/__snapshots__/syntax-script-react-typescript diff --git a/lib/config-generator.js b/lib/config-generator.js index 1652f708..5ced98f2 100644 --- a/lib/config-generator.js +++ b/lib/config-generator.js @@ -74,19 +74,6 @@ export class ConfigGenerator { { message: "None of these", name: "none" } ] }, - { - type: "select", - name: "eslintVersion", - message: "The React plugin doesn't officially support ESLint v9 yet. What would you like to do?", - initial: 0, - choices: [ - { message: "Install ESLint v9.x with compatibility utilities", name: "9.x" }, - { message: "Install ESLint v8.x", name: "8.x" } - ], - skip() { - return this.state.answers.framework !== "react"; - } - }, { type: "select", name: "language", @@ -193,23 +180,10 @@ const compat = new FlatCompat({baseDirectory: __dirname, recommendedConfig: plug if (this.answers.language === "typescript") { extensions.push("tsx"); } - // eslint-plugin-react's flat configs have languageOptions as a non-enumerable property - exportContent = ` { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } },\n${exportContent}`; - if (this.answers.eslintVersion === "9.x") { - this.result.devDependencies.push("eslint-plugin-react", "@eslint/compat"); - if (!this.result.installFlags.includes("--force")) { - this.result.installFlags.push("--force"); - } - importContent += "import pluginReactConfig from \"eslint-plugin-react/configs/recommended.js\";\n"; - importContent += "import { fixupConfigRules } from \"@eslint/compat\";\n"; - exportContent += " ...fixupConfigRules(pluginReactConfig),\n"; - } else if (this.answers.eslintVersion === "8.x") { - this.result.devDependencies[0] = "eslint@8.x"; - this.result.devDependencies.push("eslint-plugin-react"); - importContent += "import pluginReactConfig from \"eslint-plugin-react/configs/recommended.js\";\n"; - exportContent += " pluginReactConfig,\n"; - } + this.result.devDependencies.push("eslint-plugin-react"); + importContent += "import pluginReact from \"eslint-plugin-react\";\n"; + exportContent += " pluginReact.configs.flat.recommended,\n"; } if (this.answers.config) { @@ -294,8 +268,7 @@ export default [\n${exportContent}];`; // removing `--force` when: // 1. yarn v2+ -- it does not support it. - // 2. eslint v8.x -- it does not need it. - if (packageManager === "yarn" || this.answers.eslintVersion === "8.x") { + if (packageManager === "yarn") { const index = this.result.installFlags.indexOf("--force"); if (index !== -1) { diff --git a/tests/__snapshots__/problems-esm-react-eslint9.x-javascript b/tests/__snapshots__/problems-commonjs-react-javascript similarity index 52% rename from tests/__snapshots__/problems-esm-react-eslint9.x-javascript rename to tests/__snapshots__/problems-commonjs-react-javascript index af854eaf..243ae176 100644 --- a/tests/__snapshots__/problems-esm-react-eslint9.x-javascript +++ b/tests/__snapshots__/problems-commonjs-react-javascript @@ -1,16 +1,15 @@ { "configContent": "import globals from "globals"; import pluginJs from "@eslint/js"; -import pluginReactConfig from "eslint-plugin-react/configs/recommended.js"; -import { fixupConfigRules } from "@eslint/compat"; +import pluginReact from "eslint-plugin-react"; export default [ {files: ["**/*.{js,mjs,cjs,jsx}"]}, - { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } }, - {languageOptions: { globals: globals.browser }}, + {files: ["**/*.js"], languageOptions: {sourceType: "commonjs"}}, + {languageOptions: { globals: {...globals.browser, ...globals.node} }}, pluginJs.configs.recommended, - ...fixupConfigRules(pluginReactConfig), + pluginReact.configs.flat.recommended, ];", "configFilename": "eslint.config.js", "devDependencies": [ @@ -18,10 +17,8 @@ export default [ "globals", "@eslint/js", "eslint-plugin-react", - "@eslint/compat", ], "installFlags": [ "-D", - "--force", ], } \ No newline at end of file diff --git a/tests/__snapshots__/problems-esm-react-eslint9.x-typescript b/tests/__snapshots__/problems-commonjs-react-typescript similarity index 60% rename from tests/__snapshots__/problems-esm-react-eslint9.x-typescript rename to tests/__snapshots__/problems-commonjs-react-typescript index 9b8fb017..87dd2a6d 100644 --- a/tests/__snapshots__/problems-esm-react-eslint9.x-typescript +++ b/tests/__snapshots__/problems-commonjs-react-typescript @@ -2,17 +2,16 @@ "configContent": "import globals from "globals"; import pluginJs from "@eslint/js"; import tseslint from "typescript-eslint"; -import pluginReactConfig from "eslint-plugin-react/configs/recommended.js"; -import { fixupConfigRules } from "@eslint/compat"; +import pluginReact from "eslint-plugin-react"; export default [ {files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"]}, - { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } }, - {languageOptions: { globals: globals.browser }}, + {files: ["**/*.js"], languageOptions: {sourceType: "commonjs"}}, + {languageOptions: { globals: {...globals.browser, ...globals.node} }}, pluginJs.configs.recommended, ...tseslint.configs.recommended, - ...fixupConfigRules(pluginReactConfig), + pluginReact.configs.flat.recommended, ];", "configFilename": "eslint.config.js", "devDependencies": [ @@ -21,7 +20,6 @@ export default [ "@eslint/js", "typescript-eslint", "eslint-plugin-react", - "@eslint/compat", ], "installFlags": [ "-D", diff --git a/tests/__snapshots__/problems-esm-react-eslint8.x-javascript b/tests/__snapshots__/problems-esm-react-javascript similarity index 58% rename from tests/__snapshots__/problems-esm-react-eslint8.x-javascript rename to tests/__snapshots__/problems-esm-react-javascript index 92faf874..deee239e 100644 --- a/tests/__snapshots__/problems-esm-react-eslint8.x-javascript +++ b/tests/__snapshots__/problems-esm-react-javascript @@ -1,19 +1,18 @@ { "configContent": "import globals from "globals"; import pluginJs from "@eslint/js"; -import pluginReactConfig from "eslint-plugin-react/configs/recommended.js"; +import pluginReact from "eslint-plugin-react"; export default [ {files: ["**/*.{js,mjs,cjs,jsx}"]}, - { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } }, - {languageOptions: { globals: globals.browser }}, + {languageOptions: { globals: {...globals.browser, ...globals.node} }}, pluginJs.configs.recommended, - pluginReactConfig, + pluginReact.configs.flat.recommended, ];", "configFilename": "eslint.config.js", "devDependencies": [ - "eslint@8.x", + "eslint@9.x", "globals", "@eslint/js", "eslint-plugin-react", diff --git a/tests/__snapshots__/problems-esm-react-eslint8.x-typescript b/tests/__snapshots__/problems-esm-react-typescript similarity index 66% rename from tests/__snapshots__/problems-esm-react-eslint8.x-typescript rename to tests/__snapshots__/problems-esm-react-typescript index 9b6ec641..1fa0179e 100644 --- a/tests/__snapshots__/problems-esm-react-eslint8.x-typescript +++ b/tests/__snapshots__/problems-esm-react-typescript @@ -2,20 +2,19 @@ "configContent": "import globals from "globals"; import pluginJs from "@eslint/js"; import tseslint from "typescript-eslint"; -import pluginReactConfig from "eslint-plugin-react/configs/recommended.js"; +import pluginReact from "eslint-plugin-react"; export default [ {files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"]}, - { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } }, - {languageOptions: { globals: globals.browser }}, + {languageOptions: { globals: {...globals.browser, ...globals.node} }}, pluginJs.configs.recommended, ...tseslint.configs.recommended, - pluginReactConfig, + pluginReact.configs.flat.recommended, ];", "configFilename": "eslint.config.js", "devDependencies": [ - "eslint@8.x", + "eslint@9.x", "globals", "@eslint/js", "typescript-eslint", diff --git a/tests/__snapshots__/problems-script-react-javascript b/tests/__snapshots__/problems-script-react-javascript new file mode 100644 index 00000000..077884a3 --- /dev/null +++ b/tests/__snapshots__/problems-script-react-javascript @@ -0,0 +1,24 @@ +{ + "configContent": "import globals from "globals"; +import pluginJs from "@eslint/js"; +import pluginReact from "eslint-plugin-react"; + + +export default [ + {files: ["**/*.{js,mjs,cjs,jsx}"]}, + {files: ["**/*.js"], languageOptions: {sourceType: "script"}}, + {languageOptions: { globals: {...globals.browser, ...globals.node} }}, + pluginJs.configs.recommended, + pluginReact.configs.flat.recommended, +];", + "configFilename": "eslint.config.js", + "devDependencies": [ + "eslint@9.x", + "globals", + "@eslint/js", + "eslint-plugin-react", + ], + "installFlags": [ + "-D", + ], +} \ No newline at end of file diff --git a/tests/__snapshots__/syntax-esm-react-eslint9.x-typescript b/tests/__snapshots__/problems-script-react-typescript similarity index 55% rename from tests/__snapshots__/syntax-esm-react-eslint9.x-typescript rename to tests/__snapshots__/problems-script-react-typescript index 9782593e..a4b451a4 100644 --- a/tests/__snapshots__/syntax-esm-react-eslint9.x-typescript +++ b/tests/__snapshots__/problems-script-react-typescript @@ -1,24 +1,25 @@ { "configContent": "import globals from "globals"; +import pluginJs from "@eslint/js"; import tseslint from "typescript-eslint"; -import pluginReactConfig from "eslint-plugin-react/configs/recommended.js"; -import { fixupConfigRules } from "@eslint/compat"; +import pluginReact from "eslint-plugin-react"; export default [ {files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"]}, - { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } }, - {languageOptions: { globals: globals.browser }}, + {files: ["**/*.js"], languageOptions: {sourceType: "script"}}, + {languageOptions: { globals: {...globals.browser, ...globals.node} }}, + pluginJs.configs.recommended, ...tseslint.configs.recommended, - ...fixupConfigRules(pluginReactConfig), + pluginReact.configs.flat.recommended, ];", "configFilename": "eslint.config.js", "devDependencies": [ "eslint@9.x", "globals", + "@eslint/js", "typescript-eslint", "eslint-plugin-react", - "@eslint/compat", ], "installFlags": [ "-D", diff --git a/tests/__snapshots__/syntax-commonjs-react-javascript b/tests/__snapshots__/syntax-commonjs-react-javascript new file mode 100644 index 00000000..ccc71b48 --- /dev/null +++ b/tests/__snapshots__/syntax-commonjs-react-javascript @@ -0,0 +1,21 @@ +{ + "configContent": "import globals from "globals"; +import pluginReact from "eslint-plugin-react"; + + +export default [ + {files: ["**/*.{js,mjs,cjs,jsx}"]}, + {files: ["**/*.js"], languageOptions: {sourceType: "commonjs"}}, + {languageOptions: { globals: {...globals.browser, ...globals.node} }}, + pluginReact.configs.flat.recommended, +];", + "configFilename": "eslint.config.js", + "devDependencies": [ + "eslint@9.x", + "globals", + "eslint-plugin-react", + ], + "installFlags": [ + "-D", + ], +} \ No newline at end of file diff --git a/tests/__snapshots__/syntax-commonjs-react-typescript b/tests/__snapshots__/syntax-commonjs-react-typescript new file mode 100644 index 00000000..9b74ef84 --- /dev/null +++ b/tests/__snapshots__/syntax-commonjs-react-typescript @@ -0,0 +1,25 @@ +{ + "configContent": "import globals from "globals"; +import tseslint from "typescript-eslint"; +import pluginReact from "eslint-plugin-react"; + + +export default [ + {files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"]}, + {files: ["**/*.js"], languageOptions: {sourceType: "commonjs"}}, + {languageOptions: { globals: {...globals.browser, ...globals.node} }}, + ...tseslint.configs.recommended, + pluginReact.configs.flat.recommended, +];", + "configFilename": "eslint.config.js", + "devDependencies": [ + "eslint@9.x", + "globals", + "typescript-eslint", + "eslint-plugin-react", + ], + "installFlags": [ + "-D", + "--force", + ], +} \ No newline at end of file diff --git a/tests/__snapshots__/syntax-esm-react-eslint9.x-javascript b/tests/__snapshots__/syntax-esm-react-eslint9.x-javascript deleted file mode 100644 index 12f7faf7..00000000 --- a/tests/__snapshots__/syntax-esm-react-eslint9.x-javascript +++ /dev/null @@ -1,24 +0,0 @@ -{ - "configContent": "import globals from "globals"; -import pluginReactConfig from "eslint-plugin-react/configs/recommended.js"; -import { fixupConfigRules } from "@eslint/compat"; - - -export default [ - {files: ["**/*.{js,mjs,cjs,jsx}"]}, - { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } }, - {languageOptions: { globals: globals.browser }}, - ...fixupConfigRules(pluginReactConfig), -];", - "configFilename": "eslint.config.js", - "devDependencies": [ - "eslint@9.x", - "globals", - "eslint-plugin-react", - "@eslint/compat", - ], - "installFlags": [ - "-D", - "--force", - ], -} \ No newline at end of file diff --git a/tests/__snapshots__/syntax-esm-react-eslint8.x-javascript b/tests/__snapshots__/syntax-esm-react-javascript similarity index 51% rename from tests/__snapshots__/syntax-esm-react-eslint8.x-javascript rename to tests/__snapshots__/syntax-esm-react-javascript index 61b5a178..46333a32 100644 --- a/tests/__snapshots__/syntax-esm-react-eslint8.x-javascript +++ b/tests/__snapshots__/syntax-esm-react-javascript @@ -1,17 +1,16 @@ { "configContent": "import globals from "globals"; -import pluginReactConfig from "eslint-plugin-react/configs/recommended.js"; +import pluginReact from "eslint-plugin-react"; export default [ {files: ["**/*.{js,mjs,cjs,jsx}"]}, - { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } }, - {languageOptions: { globals: globals.browser }}, - pluginReactConfig, + {languageOptions: { globals: {...globals.browser, ...globals.node} }}, + pluginReact.configs.flat.recommended, ];", "configFilename": "eslint.config.js", "devDependencies": [ - "eslint@8.x", + "eslint@9.x", "globals", "eslint-plugin-react", ], diff --git a/tests/__snapshots__/syntax-esm-react-eslint8.x-typescript b/tests/__snapshots__/syntax-esm-react-typescript similarity index 61% rename from tests/__snapshots__/syntax-esm-react-eslint8.x-typescript rename to tests/__snapshots__/syntax-esm-react-typescript index 5f6d2d5e..186730bd 100644 --- a/tests/__snapshots__/syntax-esm-react-eslint8.x-typescript +++ b/tests/__snapshots__/syntax-esm-react-typescript @@ -1,19 +1,18 @@ { "configContent": "import globals from "globals"; import tseslint from "typescript-eslint"; -import pluginReactConfig from "eslint-plugin-react/configs/recommended.js"; +import pluginReact from "eslint-plugin-react"; export default [ {files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"]}, - { languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } } }, - {languageOptions: { globals: globals.browser }}, + {languageOptions: { globals: {...globals.browser, ...globals.node} }}, ...tseslint.configs.recommended, - pluginReactConfig, + pluginReact.configs.flat.recommended, ];", "configFilename": "eslint.config.js", "devDependencies": [ - "eslint@8.x", + "eslint@9.x", "globals", "typescript-eslint", "eslint-plugin-react", diff --git a/tests/__snapshots__/syntax-script-react-javascript b/tests/__snapshots__/syntax-script-react-javascript new file mode 100644 index 00000000..bac9fed6 --- /dev/null +++ b/tests/__snapshots__/syntax-script-react-javascript @@ -0,0 +1,21 @@ +{ + "configContent": "import globals from "globals"; +import pluginReact from "eslint-plugin-react"; + + +export default [ + {files: ["**/*.{js,mjs,cjs,jsx}"]}, + {files: ["**/*.js"], languageOptions: {sourceType: "script"}}, + {languageOptions: { globals: {...globals.browser, ...globals.node} }}, + pluginReact.configs.flat.recommended, +];", + "configFilename": "eslint.config.js", + "devDependencies": [ + "eslint@9.x", + "globals", + "eslint-plugin-react", + ], + "installFlags": [ + "-D", + ], +} \ No newline at end of file diff --git a/tests/__snapshots__/syntax-script-react-typescript b/tests/__snapshots__/syntax-script-react-typescript new file mode 100644 index 00000000..f07418d1 --- /dev/null +++ b/tests/__snapshots__/syntax-script-react-typescript @@ -0,0 +1,25 @@ +{ + "configContent": "import globals from "globals"; +import tseslint from "typescript-eslint"; +import pluginReact from "eslint-plugin-react"; + + +export default [ + {files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"]}, + {files: ["**/*.js"], languageOptions: {sourceType: "script"}}, + {languageOptions: { globals: {...globals.browser, ...globals.node} }}, + ...tseslint.configs.recommended, + pluginReact.configs.flat.recommended, +];", + "configFilename": "eslint.config.js", + "devDependencies": [ + "eslint@9.x", + "globals", + "typescript-eslint", + "eslint-plugin-react", + ], + "installFlags": [ + "-D", + "--force", + ], +} \ No newline at end of file diff --git a/tests/config-snapshots.spec.js b/tests/config-snapshots.spec.js index e6195321..8ad899c5 100644 --- a/tests/config-snapshots.spec.js +++ b/tests/config-snapshots.spec.js @@ -18,21 +18,12 @@ describe("generate config for esm projects", () => { const choices = { purpose: ["syntax", "problems"], moduleType: ["esm", "commonjs", "script"], - framework: ["vue", "none"], + framework: ["react", "vue", "none"], language: ["javascript", "typescript"], env: ["browser", "node"] }; - const inputs = [ - { name: "syntax-esm-react-eslint8.x-javascript", answers: { purpose: "syntax", moduleType: "esm", framework: "react", eslintVersion: "8.x", language: "javascript", env: ["browser"] } }, - { name: "syntax-esm-react-eslint8.x-typescript", answers: { purpose: "syntax", moduleType: "esm", framework: "react", eslintVersion: "8.x", language: "typescript", env: ["browser"] } }, - { name: "syntax-esm-react-eslint9.x-javascript", answers: { purpose: "syntax", moduleType: "esm", framework: "react", eslintVersion: "9.x", language: "javascript", env: ["browser"] } }, - { name: "syntax-esm-react-eslint9.x-typescript", answers: { purpose: "syntax", moduleType: "esm", framework: "react", eslintVersion: "9.x", language: "typescript", env: ["browser"] } }, - { name: "problems-esm-react-eslint8.x-javascript", answers: { purpose: "problems", moduleType: "esm", framework: "react", eslintVersion: "8.x", language: "javascript", env: ["browser"] } }, - { name: "problems-esm-react-eslint8.x-typescript", answers: { purpose: "problems", moduleType: "esm", framework: "react", eslintVersion: "8.x", language: "typescript", env: ["browser"] } }, - { name: "problems-esm-react-eslint9.x-javascript", answers: { purpose: "problems", moduleType: "esm", framework: "react", eslintVersion: "9.x", language: "javascript", env: ["browser"] } }, - { name: "problems-esm-react-eslint9.x-typescript", answers: { purpose: "problems", moduleType: "esm", framework: "react", eslintVersion: "9.x", language: "typescript", env: ["browser"] } } - ]; + const inputs = []; // generate all possible combinations for (let i = 0; i < choices.purpose.length; i++) {