@oxlint/migrate 1.50.0 → 1.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -14
- package/dist/bin/oxlint-migrate.mjs +19 -7
- package/dist/{settings-D8R7axmT.mjs → settings-R7dCJ7Y3.mjs} +124 -20
- package/dist/src/index.d.mts +85 -2649
- package/dist/src/index.mjs +10 -2
- package/package.json +12 -9
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @oxlint/migrate
|
|
2
2
|
|
|
3
3
|

|
|
4
|
-
[](https://
|
|
5
|
-
[](https://
|
|
4
|
+
[](https://npmx.dev/package/@oxlint/migrate)
|
|
5
|
+
[](https://npmx.dev/package/@oxlint/migrate)
|
|
6
6
|
|
|
7
7
|
Generates a `.oxlintrc.json` from an existing ESLint flat config.
|
|
8
8
|
|
|
@@ -18,15 +18,15 @@ When no config file is provided, the script searches for the default ESLint conf
|
|
|
18
18
|
|
|
19
19
|
### Options
|
|
20
20
|
|
|
21
|
-
| Options | Description
|
|
22
|
-
| --------------------------- |
|
|
23
|
-
| `--merge` | \* merge ESLint configuration with an existing .oxlintrc.json configuration
|
|
24
|
-
| `--type-aware` | Include type aware rules
|
|
25
|
-
| `--with-nursery` | Include oxlint rules which are currently under development
|
|
26
|
-
| `--js-plugins`
|
|
27
|
-
| `--details` | List rules that could not be migrated to oxlint
|
|
28
|
-
| `--output-file <file>` | The oxlint configuration file where ESLint v9 rules will be written to, default: `.oxlintrc.json`
|
|
29
|
-
| `--replace-eslint-comments` | Search in the project files for ESLint comments and replaces them with oxlint. Some ESLint comments are not supported and will be reported.
|
|
21
|
+
| Options | Description |
|
|
22
|
+
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
23
|
+
| `--merge` | \* merge ESLint configuration with an existing .oxlintrc.json configuration |
|
|
24
|
+
| `--type-aware` | Include type aware rules. These rules are supported with `oxlint --type-aware` and [oxlint-tsgolint](https://github.com/oxc-project/tsgolint). This will also enable the `typeAware` option in the generated configuration. |
|
|
25
|
+
| `--with-nursery` | Include oxlint rules which are currently under development |
|
|
26
|
+
| `--js-plugins [bool]` | \*\* Include ESLint plugins via `jsPlugins` key (enabled by default). Use `--js-plugins=false` to disable. |
|
|
27
|
+
| `--details` | List rules that could not be migrated to oxlint |
|
|
28
|
+
| `--output-file <file>` | The oxlint configuration file where ESLint v9 rules will be written to, default: `.oxlintrc.json` |
|
|
29
|
+
| `--replace-eslint-comments` | Search in the project files for ESLint comments and replaces them with oxlint. Some ESLint comments are not supported and will be reported. |
|
|
30
30
|
|
|
31
31
|
\* WARNING: When some `categories` are enabled, this tools will enable more rules with the combination of `plugins`.
|
|
32
32
|
Else we need to disable each rule `plugin/categories` combination, which is not covered by your ESLint configuration.
|
|
@@ -49,7 +49,7 @@ TypeScript configuration files, like `eslint.config.mts`, are supported in the f
|
|
|
49
49
|
- **Deno and Bun**: TypeScript configuration files are natively supported.
|
|
50
50
|
- **Node.js >=22.18.0**: TypeScript configuration files are supported natively with built-in type-stripping enabled by default.
|
|
51
51
|
- **Node.js >=22.6.0**: TypeScript configuration files can be used by setting `NODE_OPTIONS=--experimental-strip-types`.
|
|
52
|
-
- **Node.js <22.6.0**: TypeScript configuration files can be used by setting `NODE_OPTIONS=--import @oxc-node/core/register` and installing [@oxc-node/core](https://
|
|
52
|
+
- **Node.js <22.6.0**: TypeScript configuration files can be used by setting `NODE_OPTIONS=--import @oxc-node/core/register` and installing [@oxc-node/core](https://npmx.dev/package/@oxc-node/core) as a dev dependency.
|
|
53
53
|
|
|
54
54
|
If you attempt to use a TypeScript configuration file without the proper setup for your Node.js version, Node.js will throw an error when trying to import the file.
|
|
55
55
|
|
|
@@ -65,7 +65,7 @@ Here are some known caveats to be aware of:
|
|
|
65
65
|
|
|
66
66
|
**`settings` field migration**
|
|
67
67
|
|
|
68
|
-
The `settings` field (e.g. for setting the React version) is migrated for known oxlint-supported plugins: `jsx-a11y`, `next`, `react`, `jsdoc`, and `vitest`. By default, other settings keys are
|
|
68
|
+
The `settings` field (e.g. for setting the React version) is migrated for known oxlint-supported plugins: `jsx-a11y`, `next`, `react`, `jsdoc`, and `vitest`. By default, other settings keys are also migrated to support JS Plugins. Use `--js-plugins=false` to skip migrating unknown settings keys.
|
|
69
69
|
|
|
70
70
|
Note: Oxlint does not support `settings` in override configs. If your ESLint config has settings in configs with `files` patterns, those settings will be skipped and a warning will be shown.
|
|
71
71
|
|
|
@@ -73,7 +73,7 @@ Not all `settings` options are supported by oxlint, and so rule behavior in cert
|
|
|
73
73
|
|
|
74
74
|
**Local ESLint Plugins imported via path are not migrated**
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
JS plugin migration cannot migrate ESLint plugins from file paths in the same repo currently (e.g. if you have `../eslint-plugin-myplugin` in your `eslint.config.mjs`). You will need to copy them over into the `jsPlugins` manually. See [the JS Plugins docs]() for more info.
|
|
77
77
|
|
|
78
78
|
**`globals` field with large number of values**
|
|
79
79
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as preFixForJsPlugins, f as buildUnsupportedRuleExplanations, m as rules_exports, p as nurseryRules, u as isOffValue } from "../settings-
|
|
2
|
+
import { a as preFixForJsPlugins, f as buildUnsupportedRuleExplanations, m as rules_exports, p as nurseryRules, u as isOffValue } from "../settings-R7dCJ7Y3.mjs";
|
|
3
3
|
import main from "../src/index.mjs";
|
|
4
4
|
import { program } from "commander";
|
|
5
5
|
import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
@@ -33,7 +33,7 @@ const loadESLintConfig = async (filePath) => {
|
|
|
33
33
|
|
|
34
34
|
//#endregion
|
|
35
35
|
//#region package.json
|
|
36
|
-
var version = "1.
|
|
36
|
+
var version = "1.51.0";
|
|
37
37
|
|
|
38
38
|
//#endregion
|
|
39
39
|
//#region src/walker/comments/replaceRuleDirectiveComment.ts
|
|
@@ -357,7 +357,7 @@ function detectMissingFlags(byCategory, cliOptions) {
|
|
|
357
357
|
const missingFlags = [];
|
|
358
358
|
if (byCategory.nursery.length > 0 && !cliOptions.withNursery) missingFlags.push("--with-nursery");
|
|
359
359
|
if (byCategory["type-aware"].length > 0 && !cliOptions.typeAware) missingFlags.push("--type-aware");
|
|
360
|
-
if (byCategory["js-plugins"].length > 0 && !cliOptions.jsPlugins) missingFlags.push("--js-plugins");
|
|
360
|
+
if (byCategory["js-plugins"].length > 0 && !cliOptions.jsPlugins) missingFlags.push("--js-plugins=true");
|
|
361
361
|
return missingFlags;
|
|
362
362
|
}
|
|
363
363
|
/**
|
|
@@ -399,14 +399,25 @@ function formatMigrationOutput(data) {
|
|
|
399
399
|
}
|
|
400
400
|
return output;
|
|
401
401
|
}
|
|
402
|
+
function formatWarningsOutput(warnings) {
|
|
403
|
+
if (warnings.length === 0) return "";
|
|
404
|
+
let output = `⚠️ Warnings (${warnings.length}):\n`;
|
|
405
|
+
for (const warning of warnings) {
|
|
406
|
+
const [message, ...details] = warning.split("\n");
|
|
407
|
+
output += ` * ${message}\n`;
|
|
408
|
+
for (const detail of details.filter((line) => line.trim().length)) output += ` * ${detail}\n`;
|
|
409
|
+
}
|
|
410
|
+
return output.trimEnd();
|
|
411
|
+
}
|
|
402
412
|
function displayMigrationResult(outputMessage, warnings) {
|
|
403
413
|
console.log(outputMessage);
|
|
404
|
-
|
|
414
|
+
if (warnings.length > 0) console.warn(formatWarningsOutput(warnings));
|
|
405
415
|
}
|
|
406
416
|
|
|
407
417
|
//#endregion
|
|
408
418
|
//#region bin/oxlint-migrate.ts
|
|
409
419
|
const cwd = process.cwd();
|
|
420
|
+
const parseCliBoolean = (value) => value === "false" ? false : !!value;
|
|
410
421
|
const getFileContent = (absoluteFilePath) => {
|
|
411
422
|
try {
|
|
412
423
|
return readFileSync(absoluteFilePath, "utf-8");
|
|
@@ -429,8 +440,9 @@ const countEnabledRules = (config) => {
|
|
|
429
440
|
}
|
|
430
441
|
return enabledRules.size;
|
|
431
442
|
};
|
|
432
|
-
program.name("oxlint-migrate").version(version).argument("[eslint-config]", "The path to the eslint v9 config file").option("--output-file <file>", "The oxlint configuration file where to eslint v9 rules will be written to", ".oxlintrc.json").option("--merge", "Merge eslint configuration with an existing .oxlintrc.json configuration", false).option("--with-nursery", "Include oxlint rules which are currently under development", false).option("--replace-eslint-comments", "Search in the project files for eslint comments and replaces them with oxlint. Some eslint comments are not supported and will be reported.").option("--type-aware", "Includes supported type-aware rules. Needs the same flag in `oxlint` to enable it.").option("--js-plugins", "Tries to convert unsupported oxlint plugins with `jsPlugins`.").option("--details", "List rules that could not be migrated to oxlint.", false).action(async (filePath) => {
|
|
443
|
+
program.name("oxlint-migrate").version(version).argument("[eslint-config]", "The path to the eslint v9 config file").option("--output-file <file>", "The oxlint configuration file where to eslint v9 rules will be written to", ".oxlintrc.json").option("--merge", "Merge eslint configuration with an existing .oxlintrc.json configuration", false).option("--with-nursery", "Include oxlint rules which are currently under development", false).option("--replace-eslint-comments", "Search in the project files for eslint comments and replaces them with oxlint. Some eslint comments are not supported and will be reported.").option("--type-aware", "Includes supported type-aware rules. Needs the same flag in `oxlint` or the `typeAware` config option to enable it.").option("--js-plugins [bool]", "Tries to convert unsupported oxlint plugins with `jsPlugins`. Enabled by default; pass `--js-plugins=false` to disable.", true).option("--details", "List rules that could not be migrated to oxlint.", false).action(async (filePath) => {
|
|
433
444
|
const cliOptions = program.opts();
|
|
445
|
+
const jsPlugins = parseCliBoolean(cliOptions.jsPlugins);
|
|
434
446
|
const oxlintFilePath = path.join(cwd, cliOptions.outputFile);
|
|
435
447
|
const reporter = new DefaultReporter();
|
|
436
448
|
const options = {
|
|
@@ -438,7 +450,7 @@ program.name("oxlint-migrate").version(version).argument("[eslint-config]", "The
|
|
|
438
450
|
merge: !!cliOptions.merge,
|
|
439
451
|
withNursery: !!cliOptions.withNursery,
|
|
440
452
|
typeAware: !!cliOptions.typeAware,
|
|
441
|
-
jsPlugins
|
|
453
|
+
jsPlugins
|
|
442
454
|
};
|
|
443
455
|
if (cliOptions.replaceEslintComments) {
|
|
444
456
|
await walkAndReplaceProjectFiles(await getAllProjectFiles(), (filePath) => getFileContent(filePath), (filePath, content) => writeFile(filePath, content, "utf-8"), options);
|
|
@@ -467,7 +479,7 @@ program.name("oxlint-migrate").version(version).argument("[eslint-config]", "The
|
|
|
467
479
|
withNursery: !!cliOptions.withNursery,
|
|
468
480
|
typeAware: !!cliOptions.typeAware,
|
|
469
481
|
details: !!cliOptions.details,
|
|
470
|
-
jsPlugins
|
|
482
|
+
jsPlugins
|
|
471
483
|
},
|
|
472
484
|
eslintConfigPath: filePath
|
|
473
485
|
}), reporter.getWarnings());
|
|
@@ -1071,13 +1071,47 @@ const ignorePlugins = new Set([
|
|
|
1071
1071
|
...Object.values(rulesPrefixesForPlugins),
|
|
1072
1072
|
"local"
|
|
1073
1073
|
]);
|
|
1074
|
-
const
|
|
1074
|
+
const tryResolvePackage = (packageName) => {
|
|
1075
|
+
try {
|
|
1076
|
+
import.meta.resolve(packageName);
|
|
1077
|
+
return true;
|
|
1078
|
+
} catch {
|
|
1079
|
+
return false;
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
const pluginNameCache = /* @__PURE__ */ new Map();
|
|
1083
|
+
/**
|
|
1084
|
+
* Resolves the npm package name for an ESLint plugin given its scope name.
|
|
1085
|
+
*
|
|
1086
|
+
* For scoped plugin names (starting with `@`), the mapping is unambiguous:
|
|
1087
|
+
* - `@scope` -> `@scope/eslint-plugin`
|
|
1088
|
+
* - `@scope/sub` -> `@scope/eslint-plugin-sub`
|
|
1089
|
+
*
|
|
1090
|
+
* For non-scoped names, the npm package could follow either convention:
|
|
1091
|
+
* - `eslint-plugin-{name}` (e.g. `eslint-plugin-mocha`)
|
|
1092
|
+
* - `@{name}/eslint-plugin` (e.g. `@e18e/eslint-plugin`)
|
|
1093
|
+
*
|
|
1094
|
+
* We try to resolve both candidates against the installed packages and
|
|
1095
|
+
* use the one that is actually present, falling back to the standard
|
|
1096
|
+
* `eslint-plugin-{name}` convention when neither can be resolved.
|
|
1097
|
+
*/
|
|
1098
|
+
const resolveEslintPluginName = (pluginName) => {
|
|
1099
|
+
const cached = pluginNameCache.get(pluginName);
|
|
1100
|
+
if (cached !== void 0) return cached;
|
|
1101
|
+
let result;
|
|
1075
1102
|
if (pluginName.startsWith("@")) {
|
|
1076
1103
|
const [scope, maybeSub] = pluginName.split("/");
|
|
1077
|
-
if (maybeSub)
|
|
1078
|
-
|
|
1104
|
+
if (maybeSub) result = `${scope}/eslint-plugin-${maybeSub}`;
|
|
1105
|
+
else result = `${scope}/eslint-plugin`;
|
|
1106
|
+
} else {
|
|
1107
|
+
const standardName = `eslint-plugin-${pluginName}`;
|
|
1108
|
+
const scopedName = `@${pluginName}/eslint-plugin`;
|
|
1109
|
+
if (tryResolvePackage(standardName)) result = standardName;
|
|
1110
|
+
else if (tryResolvePackage(scopedName)) result = scopedName;
|
|
1111
|
+
else result = standardName;
|
|
1079
1112
|
}
|
|
1080
|
-
|
|
1113
|
+
pluginNameCache.set(pluginName, result);
|
|
1114
|
+
return result;
|
|
1081
1115
|
};
|
|
1082
1116
|
const extractPluginId = (ruleId) => {
|
|
1083
1117
|
const firstSlash = ruleId.indexOf("/");
|
|
@@ -1093,15 +1127,68 @@ const isIgnoredPluginRule = (ruleId) => {
|
|
|
1093
1127
|
if (pluginName === void 0) return true;
|
|
1094
1128
|
return ignorePlugins.has(pluginName);
|
|
1095
1129
|
};
|
|
1096
|
-
|
|
1130
|
+
/**
|
|
1131
|
+
* Derives the npm package name for a plugin from its `meta.name` field.
|
|
1132
|
+
*
|
|
1133
|
+
* If `meta.name` already looks like a full npm package name (contains
|
|
1134
|
+
* "eslint-plugin"), it is returned as-is. Otherwise it is fed through
|
|
1135
|
+
* {@link resolveEslintPluginName} for the usual heuristic resolution.
|
|
1136
|
+
*/
|
|
1137
|
+
const resolveFromMetaName = (metaName) => {
|
|
1138
|
+
if (metaName.includes("eslint-plugin")) return metaName;
|
|
1139
|
+
return resolveEslintPluginName(metaName);
|
|
1140
|
+
};
|
|
1141
|
+
/**
|
|
1142
|
+
* Derives the rule-ID prefix that an npm package exposes.
|
|
1143
|
+
*
|
|
1144
|
+
* Examples:
|
|
1145
|
+
* `eslint-plugin-react-dom` -> `react-dom`
|
|
1146
|
+
* `eslint-plugin-mocha` -> `mocha`
|
|
1147
|
+
* `@stylistic/eslint-plugin` -> `@stylistic`
|
|
1148
|
+
* `@stylistic/eslint-plugin-ts` -> `@stylistic/ts`
|
|
1149
|
+
*/
|
|
1150
|
+
const deriveRulePrefix = (packageName) => {
|
|
1151
|
+
if (packageName.startsWith("@")) {
|
|
1152
|
+
const slashIdx = packageName.indexOf("/");
|
|
1153
|
+
const scope = packageName.substring(0, slashIdx);
|
|
1154
|
+
const rest = packageName.substring(slashIdx + 1);
|
|
1155
|
+
if (rest === "eslint-plugin") return scope;
|
|
1156
|
+
if (rest.startsWith("eslint-plugin-")) return `${scope}/${rest.substring(14)}`;
|
|
1157
|
+
return packageName;
|
|
1158
|
+
}
|
|
1159
|
+
if (packageName.startsWith("eslint-plugin-")) return packageName.substring(14);
|
|
1160
|
+
return packageName;
|
|
1161
|
+
};
|
|
1162
|
+
/**
|
|
1163
|
+
* Resolves the canonical rule name for a jsPlugin rule.
|
|
1164
|
+
*
|
|
1165
|
+
* When a plugin is registered under an alias (e.g. `@eslint-react/dom`) but
|
|
1166
|
+
* its `meta.name` reveals a different canonical package (`eslint-plugin-react-dom`),
|
|
1167
|
+
* the rule must be rewritten so that oxlint can match it to the loaded plugin.
|
|
1168
|
+
*
|
|
1169
|
+
* For example:
|
|
1170
|
+
* `@eslint-react/dom/no-find-dom-node` -> `react-dom/no-find-dom-node`
|
|
1171
|
+
*/
|
|
1172
|
+
const resolveJsPluginRuleName = (rule, plugins) => {
|
|
1173
|
+
const pluginName = extractPluginId(rule);
|
|
1174
|
+
if (pluginName === void 0) return rule;
|
|
1175
|
+
const metaName = plugins?.[pluginName]?.meta?.name;
|
|
1176
|
+
if (!metaName || !metaName.includes("eslint-plugin")) return rule;
|
|
1177
|
+
const canonicalPrefix = deriveRulePrefix(metaName);
|
|
1178
|
+
if (canonicalPrefix === pluginName) return rule;
|
|
1179
|
+
return `${canonicalPrefix}/${rule.substring(pluginName.length + 1)}`;
|
|
1180
|
+
};
|
|
1181
|
+
const enableJsPluginRule = (targetConfig, rule, ruleEntry, plugins) => {
|
|
1097
1182
|
const pluginName = extractPluginId(rule);
|
|
1098
1183
|
if (pluginName === void 0) return false;
|
|
1099
1184
|
if (ignorePlugins.has(pluginName)) return false;
|
|
1100
1185
|
if (targetConfig.jsPlugins === void 0) targetConfig.jsPlugins = [];
|
|
1101
|
-
const
|
|
1186
|
+
const metaName = plugins?.[pluginName]?.meta?.name;
|
|
1187
|
+
const eslintPluginName = metaName ? resolveFromMetaName(metaName) : resolveEslintPluginName(pluginName);
|
|
1102
1188
|
if (!targetConfig.jsPlugins.includes(eslintPluginName)) targetConfig.jsPlugins.push(eslintPluginName);
|
|
1189
|
+
const resolvedRule = resolveJsPluginRuleName(rule, plugins);
|
|
1103
1190
|
targetConfig.rules = targetConfig.rules || {};
|
|
1104
|
-
targetConfig.rules[
|
|
1191
|
+
targetConfig.rules[resolvedRule] = ruleEntry;
|
|
1105
1192
|
return true;
|
|
1106
1193
|
};
|
|
1107
1194
|
|
|
@@ -1146,6 +1233,7 @@ var unsupportedRules = {
|
|
|
1146
1233
|
"import/no-deprecated": "No need to implement, already implemented by `typescript/no-deprecated` via tsgolint.",
|
|
1147
1234
|
"n/no-restricted-import": "No need to implement, already implemented by `no-restricted-imports` rule.",
|
|
1148
1235
|
"n/no-restricted-require": "No need to implement, already implemented by `no-restricted-imports` rule.",
|
|
1236
|
+
"import/order": "Not implementing this in Oxlint as its behavior is covered very well by [Oxfmt's import sorting](https://oxc.rs/docs/guide/usage/formatter/sorting.html).",
|
|
1149
1237
|
"jsdoc/type-formatting": "Experimental rule in the original plugin, may reconsider once stable.",
|
|
1150
1238
|
"jsdoc/convert-to-jsdoc-comments": "Experimental rule in the original plugin, may reconsider once stable.",
|
|
1151
1239
|
"jsdoc/check-examples": "Deprecated.",
|
|
@@ -1571,12 +1659,22 @@ const mergeRuleConfig = (existingConfig, newConfig) => {
|
|
|
1571
1659
|
if (Array.isArray(newConfig) && newConfig.length === 1 && existingIsArray && existingConfig.length > 1) return [newConfig[0], ...existingConfig.slice(1)];
|
|
1572
1660
|
return newConfig;
|
|
1573
1661
|
};
|
|
1574
|
-
const transformRuleEntry = (eslintConfig, targetConfig, baseConfig, options, overrides) => {
|
|
1662
|
+
const transformRuleEntry = (eslintConfig, targetConfig, baseConfig, options, overrides, globalPlugins) => {
|
|
1575
1663
|
if (eslintConfig.rules === void 0) return;
|
|
1576
1664
|
if (targetConfig.rules === void 0) targetConfig.rules = {};
|
|
1665
|
+
const effectivePlugins = globalPlugins ? {
|
|
1666
|
+
...globalPlugins,
|
|
1667
|
+
...eslintConfig.plugins
|
|
1668
|
+
} : eslintConfig.plugins;
|
|
1577
1669
|
for (const [rule, config] of Object.entries(eslintConfig.rules)) {
|
|
1578
1670
|
const normalizedConfig = normalizeSeverityValue(config);
|
|
1579
|
-
if (!options?.merge)
|
|
1671
|
+
if (!options?.merge) {
|
|
1672
|
+
removePreviousOverrideRule(rule, eslintConfig, overrides);
|
|
1673
|
+
if (options?.jsPlugins) {
|
|
1674
|
+
const resolved = resolveJsPluginRuleName(rule, effectivePlugins);
|
|
1675
|
+
if (resolved !== rule) removePreviousOverrideRule(resolved, eslintConfig, overrides);
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1580
1678
|
if (allRules.includes(rule)) {
|
|
1581
1679
|
if (!options?.withNursery && nurseryRules.includes(rule)) {
|
|
1582
1680
|
options?.reporter?.markSkipped(rule, "nursery");
|
|
@@ -1595,8 +1693,9 @@ const transformRuleEntry = (eslintConfig, targetConfig, baseConfig, options, ove
|
|
|
1595
1693
|
} else {
|
|
1596
1694
|
if (options?.jsPlugins) {
|
|
1597
1695
|
if (isOffValue(normalizedConfig)) {
|
|
1598
|
-
|
|
1599
|
-
|
|
1696
|
+
const resolvedRule = resolveJsPluginRuleName(rule, effectivePlugins);
|
|
1697
|
+
if (eslintConfig.files === void 0) delete targetConfig.rules[resolvedRule];
|
|
1698
|
+
else if (!isIgnoredPluginRule(rule)) targetConfig.rules[resolvedRule] = normalizedConfig;
|
|
1600
1699
|
if (eslintConfig.files === void 0) {
|
|
1601
1700
|
options?.reporter?.removeSkipped(rule, "js-plugins");
|
|
1602
1701
|
options?.reporter?.removeSkipped(rule, "not-implemented");
|
|
@@ -1604,7 +1703,7 @@ const transformRuleEntry = (eslintConfig, targetConfig, baseConfig, options, ove
|
|
|
1604
1703
|
}
|
|
1605
1704
|
continue;
|
|
1606
1705
|
}
|
|
1607
|
-
if (!enableJsPluginRule(targetConfig, rule, normalizedConfig)) {
|
|
1706
|
+
if (!enableJsPluginRule(targetConfig, rule, normalizedConfig, effectivePlugins)) {
|
|
1608
1707
|
const category = unsupportedRuleExplanations[rule] ? "unsupported" : "not-implemented";
|
|
1609
1708
|
options?.reporter?.markSkipped(rule, category);
|
|
1610
1709
|
}
|
|
@@ -1991,6 +2090,13 @@ const isSupportedSettingsKey = (key) => {
|
|
|
1991
2090
|
return OXLINT_SUPPORTED_SETTINGS_KEYS.includes(key);
|
|
1992
2091
|
};
|
|
1993
2092
|
/**
|
|
2093
|
+
* Format a list of settings keys into a newline-separated, backtick-quoted
|
|
2094
|
+
* string for warning output.
|
|
2095
|
+
*/
|
|
2096
|
+
const formatSettingsKeyList = (keys) => {
|
|
2097
|
+
return keys.map((key) => `\`${key}\``).join("\n");
|
|
2098
|
+
};
|
|
2099
|
+
/**
|
|
1994
2100
|
* Transform ESLint settings to oxlint settings.
|
|
1995
2101
|
*
|
|
1996
2102
|
* Only processes settings for the base config (not overrides) since oxlint
|
|
@@ -2027,24 +2133,22 @@ const transformSettings = (eslintConfig, targetConfig, options) => {
|
|
|
2027
2133
|
}
|
|
2028
2134
|
let settingsValue = value;
|
|
2029
2135
|
if (key === "react" && settingsValue.version === "detect") {
|
|
2030
|
-
options?.reporter?.addWarning("react.version \"detect\" is not supported
|
|
2136
|
+
options?.reporter?.addWarning("react.version \"detect\" is not supported. Specify an explicit version (e.g., \"18.2.0\") in your oxlint config.");
|
|
2031
2137
|
const { version: _, ...restReactSettings } = settingsValue;
|
|
2032
2138
|
settingsValue = restReactSettings;
|
|
2033
2139
|
}
|
|
2034
2140
|
const unsupportedSubKeys = UNSUPPORTED_SETTINGS_SUB_KEYS[key];
|
|
2035
2141
|
if (unsupportedSubKeys !== void 0) {
|
|
2036
|
-
const strippedKeys = [];
|
|
2037
2142
|
for (const subKey of unsupportedSubKeys) if (subKey in settingsValue) {
|
|
2038
|
-
|
|
2143
|
+
skippedKeys.push(`${key}.${subKey}`);
|
|
2039
2144
|
const { [subKey]: _, ...rest } = settingsValue;
|
|
2040
2145
|
settingsValue = rest;
|
|
2041
2146
|
}
|
|
2042
|
-
if (strippedKeys.length > 0) options?.reporter?.addWarning(`Settings not migrated (not supported by oxlint): ${strippedKeys.join(", ")}.`);
|
|
2043
2147
|
}
|
|
2044
2148
|
if (Object.keys(settingsValue).length === 0) continue;
|
|
2045
2149
|
filteredSettings[key] = settingsValue;
|
|
2046
2150
|
}
|
|
2047
|
-
if (skippedKeys.length > 0) options?.reporter?.addWarning(`Settings not migrated (not supported by oxlint)
|
|
2151
|
+
if (skippedKeys.length > 0) options?.reporter?.addWarning(`Settings not migrated (not supported by oxlint):\n${formatSettingsKeyList(skippedKeys)}`);
|
|
2048
2152
|
if (Object.keys(filteredSettings).length === 0) return;
|
|
2049
2153
|
if (targetConfig.settings === void 0) targetConfig.settings = {};
|
|
2050
2154
|
if (options?.merge) deepMerge(targetConfig.settings, filteredSettings);
|
|
@@ -2059,10 +2163,10 @@ const transformSettings = (eslintConfig, targetConfig, options) => {
|
|
|
2059
2163
|
*/
|
|
2060
2164
|
const warnSettingsInOverride = (eslintConfig, options) => {
|
|
2061
2165
|
if (eslintConfig.settings !== void 0 && eslintConfig.settings !== null && Object.keys(eslintConfig.settings).length > 0) {
|
|
2062
|
-
const settingsKeys = Object.keys(eslintConfig.settings)
|
|
2063
|
-
options?.reporter?.addWarning(
|
|
2166
|
+
const settingsKeys = Object.keys(eslintConfig.settings);
|
|
2167
|
+
options?.reporter?.addWarning("Settings found under a 'files' pattern — oxlint does not support settings in overrides and they will be skipped:\n" + formatSettingsKeyList(settingsKeys));
|
|
2064
2168
|
}
|
|
2065
2169
|
};
|
|
2066
2170
|
|
|
2067
2171
|
//#endregion
|
|
2068
|
-
export { preFixForJsPlugins as a, cleanUpOxlintConfig as c, transformRuleEntry as d, buildUnsupportedRuleExplanations as f,
|
|
2172
|
+
export { transformEnvAndGlobals as _, preFixForJsPlugins as a, cleanUpOxlintConfig as c, transformRuleEntry as d, buildUnsupportedRuleExplanations as f, detectEnvironmentByGlobals as g, typeAwareRules as h, fixForJsPlugins as i, detectNeededRulesPlugins as l, rules_exports as m, warnSettingsInOverride as n, detectSameOverride as o, nurseryRules as p, processConfigFiles as r, transformIgnorePatterns as s, transformSettings as t, isOffValue as u };
|