Skip to content

Commit

Permalink
fix: Package-specific migration bugs (#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
nzakas authored Aug 26, 2024
1 parent 9250f28 commit 7f416f4
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 2 deletions.
6 changes: 6 additions & 0 deletions packages/migrate-config/src/compat-configs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* @fileoverview A list of shareable configs that need the compat utility.
* @author Nicholas C. Zakas
*/

export default ["eslint-config-react-app"];
33 changes: 31 additions & 2 deletions packages/migrate-config/src/migrate-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import * as recast from "recast";
import { Legacy } from "@eslint/eslintrc";
import camelCase from "camelcase";
import pluginsNeedingCompat from "./compat-plugins.js";
import configsNeedingCompat from "./compat-configs.js";
import { convertIgnorePatternToMinimatch } from "@eslint/compat";

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -147,6 +148,23 @@ function pluginNeedsCompat(pluginName) {
);
}

/**
* Determines if a shareable config needs the compat utility.
* @param {string} configName The name of the config.
* @returns {boolean} `true` if the config needs the compat utility.
*/
function configNeedsCompat(configName) {
const configNameToTest = configName.includes("/")
? configName.slice(0, configName.indexOf("/"))
: configName;

const fullConfigName = naming.normalizePackageName(
configNameToTest,
"eslint-config",
);
return configsNeedingCompat.includes(fullConfigName);
}

/**
* Gets the name of the variable to use for the plugin. If the plugin name
* contains slashes or an @ symbol, it will be normalized to a camelcase name.
Expand All @@ -165,6 +183,9 @@ function getPluginVariableName(pluginName) {
name = name.slice(1);
}

// replace slash with uppercase of following letter
name = name.replace(/\/(.)/gu, (_, letter) => letter.toUpperCase());

return camelCase(name);
}

Expand Down Expand Up @@ -682,11 +703,19 @@ function migrateConfigObject(migration, config) {

// Check if any of the extends are plugins that need the compat utility
const needsCompat = extendsArray.some(extend => {
if (!extend.startsWith("plugin:")) {
if (
extend.startsWith("eslint:") ||
extend.startsWith(".") ||
extend.startsWith("/")
) {
return false;
}

return pluginNeedsCompat(extend.slice(7));
if (extend.startsWith("plugin:")) {
return pluginNeedsCompat(extend.slice(7));
}

return configNeedsCompat(extend);
});

if (needsCompat) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": [
"react-app",
"prettier",
"plugin:jsx-a11y/recommended",
"plugin:@tanstack/eslint-plugin-query/recommended"
],
"plugins": [
"jsx-a11y",
"@tanstack/query"
]
}
30 changes: 30 additions & 0 deletions packages/migrate-config/tests/fixtures/slash-package/expected.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const {
fixupConfigRules,
fixupPluginRules,
} = require("@eslint/compat");

const jsxA11Y = require("eslint-plugin-jsx-a11y");
const tanstackQuery = require("@tanstack/eslint-plugin-query");
const js = require("@eslint/js");

const {
FlatCompat,
} = require("@eslint/eslintrc");

const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
});

module.exports = [...fixupConfigRules(compat.extends(
"react-app",
"prettier",
"plugin:jsx-a11y/recommended",
"plugin:@tanstack/eslint-plugin-query/recommended",
)), {
plugins: {
"jsx-a11y": fixupPluginRules(jsxA11Y),
"@tanstack/query": fixupPluginRules(tanstackQuery),
},
}];
27 changes: 27 additions & 0 deletions packages/migrate-config/tests/fixtures/slash-package/expected.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { fixupConfigRules, fixupPluginRules } from "@eslint/compat";
import jsxA11Y from "eslint-plugin-jsx-a11y";
import tanstackQuery from "@tanstack/eslint-plugin-query";
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
});

export default [...fixupConfigRules(compat.extends(
"react-app",
"prettier",
"plugin:jsx-a11y/recommended",
"plugin:@tanstack/eslint-plugin-query/recommended",
)), {
plugins: {
"jsx-a11y": fixupPluginRules(jsxA11Y),
"@tanstack/query": fixupPluginRules(tanstackQuery),
},
}];
2 changes: 2 additions & 0 deletions packages/migrate-config/tests/migrate-config-cli.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const filePaths = [
"gitignore-simple/.eslintrc.json",
"gitignore-complex/.eslintrc.json",
"import-duplicate/.eslintrc.cjs",
"slash-package/.eslintrc.json",
].map(file => `tests/fixtures/${file}`);

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -83,6 +84,7 @@ describe("@eslint/migrate-config", async () => {
// run the migration for mjs
execSync(
`node src/migrate-config-cli.js ${filePath} ${gitignoreFlag}`,
{ stdio: "inherit" },
);

// run the migration for cjs
Expand Down

0 comments on commit 7f416f4

Please sign in to comment.