@oxlint/migrate 1.32.0 → 1.34.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/dist/bin/oxlint-migrate.d.mts +1 -0
- package/dist/bin/oxlint-migrate.mjs +330 -78
- package/dist/src/index.d.mts +46 -0
- package/dist/src/index.mjs +3 -80
- package/dist/src-MX2M8fZn.mjs +1494 -0
- package/package.json +37 -38
- package/dist/bin/config-loader.mjs +0 -46
- package/dist/bin/project-loader.mjs +0 -16
- package/dist/package.json.mjs +0 -8
- package/dist/src/cleanup.d.ts +0 -2
- package/dist/src/cleanup.mjs +0 -154
- package/dist/src/cleanup.test.d.ts +0 -1
- package/dist/src/constants.d.ts +0 -3
- package/dist/src/constants.mjs +0 -104
- package/dist/src/env_globals.d.ts +0 -16
- package/dist/src/env_globals.mjs +0 -233
- package/dist/src/generated/rules.d.ts +0 -7
- package/dist/src/generated/rules.mjs +0 -697
- package/dist/src/ignorePatterns.d.ts +0 -3
- package/dist/src/ignorePatterns.mjs +0 -20
- package/dist/src/index.d.ts +0 -4
- package/dist/src/jsPlugins.d.ts +0 -3
- package/dist/src/jsPlugins.mjs +0 -52
- package/dist/src/js_plugin_fixes.d.ts +0 -5
- package/dist/src/js_plugin_fixes.mjs +0 -39
- package/dist/src/overrides.d.ts +0 -2
- package/dist/src/overrides.mjs +0 -16
- package/dist/src/plugins_rules.d.ts +0 -13
- package/dist/src/plugins_rules.mjs +0 -251
- package/dist/src/reporter.d.ts +0 -10
- package/dist/src/reporter.mjs +0 -12
- package/dist/src/types.d.ts +0 -39
- package/dist/src/utilities.d.ts +0 -1
- package/dist/src/utilities.mjs +0 -12
- package/dist/src/walker/comments/index.d.ts +0 -2
- package/dist/src/walker/comments/index.mjs +0 -20
- package/dist/src/walker/comments/replaceRuleDirectiveComment.d.ts +0 -2
- package/dist/src/walker/comments/replaceRuleDirectiveComment.mjs +0 -59
- package/dist/src/walker/index.d.ts +0 -10
- package/dist/src/walker/index.mjs +0 -19
- package/dist/src/walker/partialSourceTextLoader.d.ts +0 -10
- package/dist/src/walker/partialSourceTextLoader.mjs +0 -167
- package/dist/src/walker/replaceCommentsInFile.d.ts +0 -2
- package/dist/src/walker/replaceCommentsInFile.mjs +0 -60
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -1,88 +1,340 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { i as rules_exports, n as preFixForJsPlugins, r as nurseryRules, t as src_default } from "../src-MX2M8fZn.mjs";
|
|
2
3
|
import { program } from "commander";
|
|
3
4
|
import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
4
5
|
import path from "node:path";
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import { walkAndReplaceProjectFiles } from "../src/walker/index.mjs";
|
|
9
|
-
import { getAllProjectFiles } from "./project-loader.mjs";
|
|
6
|
+
import { pathToFileURL } from "node:url";
|
|
7
|
+
import { parseSync } from "oxc-parser";
|
|
8
|
+
import { glob } from "tinyglobby";
|
|
10
9
|
import { writeFile } from "node:fs/promises";
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
|
|
11
|
+
//#region bin/config-loader.ts
|
|
12
|
+
const FLAT_CONFIG_FILENAMES = [
|
|
13
|
+
"eslint.config.js",
|
|
14
|
+
"eslint.config.mjs",
|
|
15
|
+
"eslint.config.cjs",
|
|
16
|
+
"eslint.config.ts",
|
|
17
|
+
"eslint.config.mts",
|
|
18
|
+
"eslint.config.cts"
|
|
19
|
+
];
|
|
20
|
+
const getAutodetectedEslintConfigName = (cwd$1) => {
|
|
21
|
+
for (const filename of FLAT_CONFIG_FILENAMES) {
|
|
22
|
+
const filePath = path.join(cwd$1, filename);
|
|
23
|
+
if (existsSync(filePath)) return filePath;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const loadESLintConfig = async (filePath) => {
|
|
27
|
+
if (filePath.endsWith("json")) throw new Error(`json format is not supported. @oxlint/migrate only supports the eslint flat configuration`);
|
|
28
|
+
let url = pathToFileURL(filePath).toString();
|
|
29
|
+
if (!existsSync(filePath)) throw new Error(`eslint config file not found: ${filePath}`);
|
|
30
|
+
if ("Bun" in globalThis || "Deno" in globalThis) return import(url);
|
|
31
|
+
if (filePath.endsWith(".ts") || filePath.endsWith(".mts") || filePath.endsWith(".cts")) {
|
|
32
|
+
const { createJiti } = await import("jiti");
|
|
33
|
+
return createJiti(filePath, {
|
|
34
|
+
interopDefault: false,
|
|
35
|
+
moduleCache: false
|
|
36
|
+
}).import(url);
|
|
37
|
+
}
|
|
38
|
+
return import(url);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region package.json
|
|
43
|
+
var version = "1.34.0";
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/walker/comments/replaceRuleDirectiveComment.ts
|
|
47
|
+
const allRules = Object.values(rules_exports).flat();
|
|
48
|
+
function replaceRuleDirectiveComment(comment, type, options) {
|
|
49
|
+
const originalComment = comment;
|
|
50
|
+
comment = comment.split(" -- ")[0].trimStart();
|
|
51
|
+
if (!comment.startsWith("eslint-")) return originalComment;
|
|
52
|
+
comment = comment.substring(7);
|
|
53
|
+
if (comment.startsWith("enable")) comment = comment.substring(6);
|
|
54
|
+
else if (comment.startsWith("disable")) {
|
|
55
|
+
comment = comment.substring(7);
|
|
56
|
+
if (type === "Line") {
|
|
57
|
+
if (comment.startsWith("-next-line")) comment = comment.substring(10);
|
|
58
|
+
else if (comment.startsWith("-line")) comment = comment.substring(5);
|
|
59
|
+
}
|
|
60
|
+
} else return originalComment;
|
|
61
|
+
if (!comment.startsWith(" ")) return originalComment;
|
|
62
|
+
comment = comment.trimStart();
|
|
63
|
+
if (comment.length === 0) return originalComment;
|
|
64
|
+
while (comment.length) {
|
|
65
|
+
let foundRule = false;
|
|
66
|
+
for (const rule of allRules) if (comment.startsWith(rule)) {
|
|
67
|
+
if (!options.withNursery && nurseryRules.includes(rule)) continue;
|
|
68
|
+
foundRule = true;
|
|
69
|
+
comment = comment.substring(rule.length).trimStart();
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
if (!foundRule) return originalComment;
|
|
73
|
+
if (!comment.length) break;
|
|
74
|
+
if (!comment.startsWith(", ")) return originalComment;
|
|
75
|
+
comment = comment.substring(1).trimStart();
|
|
76
|
+
}
|
|
77
|
+
return originalComment.replace(/eslint-/, "oxlint-");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region src/walker/comments/index.ts
|
|
82
|
+
function replaceComments(comment, type, options) {
|
|
83
|
+
const originalComment = comment;
|
|
84
|
+
comment = comment.trim();
|
|
85
|
+
if (comment.startsWith("eslint-")) return replaceRuleDirectiveComment(originalComment, type, options);
|
|
86
|
+
else if (type === "Block") {
|
|
87
|
+
if (comment.startsWith("eslint ")) throw new Error("changing eslint rules with inline comment is not supported");
|
|
88
|
+
else if (comment.startsWith("global ")) throw new Error("changing globals with inline comment is not supported");
|
|
89
|
+
}
|
|
90
|
+
return originalComment;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/walker/partialSourceTextLoader.ts
|
|
95
|
+
function extractLangAttribute(source) {
|
|
96
|
+
const langIndex = source.indexOf("lang");
|
|
97
|
+
if (langIndex === -1) return void 0;
|
|
98
|
+
let cursor = langIndex + 4;
|
|
99
|
+
while (cursor < source.length && isWhitespace(source[cursor])) cursor++;
|
|
100
|
+
if (source[cursor] !== "=") return void 0;
|
|
101
|
+
cursor++;
|
|
102
|
+
while (cursor < source.length && isWhitespace(source[cursor])) cursor++;
|
|
103
|
+
const quote = source[cursor];
|
|
104
|
+
if (quote !== "\"" && quote !== "'") return void 0;
|
|
105
|
+
cursor++;
|
|
106
|
+
let value = "";
|
|
107
|
+
while (cursor < source.length && source[cursor] !== quote) value += source[cursor++];
|
|
108
|
+
if (value === "js" || value === "jsx" || value === "ts" || value === "tsx") return value;
|
|
109
|
+
}
|
|
110
|
+
function extractScriptBlocks(sourceText, offset, maxBlocks, parseLangAttribute) {
|
|
111
|
+
const results = [];
|
|
112
|
+
while (offset < sourceText.length) {
|
|
113
|
+
const idx = sourceText.indexOf("<script", offset);
|
|
114
|
+
if (idx === -1) break;
|
|
115
|
+
const nextChar = sourceText[idx + 7];
|
|
116
|
+
if (nextChar !== " " && nextChar !== ">" && nextChar !== "\n" && nextChar !== " ") {
|
|
117
|
+
offset = idx + 7;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
let i = idx + 7;
|
|
121
|
+
let inQuote = null;
|
|
122
|
+
let genericDepth = 0;
|
|
123
|
+
let selfClosing = false;
|
|
124
|
+
while (i < sourceText.length) {
|
|
125
|
+
const c = sourceText[i];
|
|
126
|
+
if (inQuote) {
|
|
127
|
+
if (c === inQuote) inQuote = null;
|
|
128
|
+
} else if (c === "\"" || c === "'") inQuote = c;
|
|
129
|
+
else if (c === "<") genericDepth++;
|
|
130
|
+
else if (c === ">") if (genericDepth > 0) genericDepth--;
|
|
131
|
+
else {
|
|
132
|
+
if (i > idx && sourceText[i - 1] === "/") selfClosing = true;
|
|
133
|
+
i++;
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
i++;
|
|
137
|
+
}
|
|
138
|
+
if (selfClosing) {
|
|
139
|
+
offset = i;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (i >= sourceText.length) break;
|
|
143
|
+
let lang = void 0;
|
|
144
|
+
if (parseLangAttribute) lang = extractLangAttribute(sourceText.slice(idx, i));
|
|
145
|
+
const contentStart = i;
|
|
146
|
+
const closeIdx = sourceText.indexOf("<\/script>", contentStart);
|
|
147
|
+
if (closeIdx === -1) break;
|
|
148
|
+
const content = sourceText.slice(contentStart, closeIdx);
|
|
149
|
+
results.push({
|
|
150
|
+
sourceText: content,
|
|
151
|
+
offset: contentStart,
|
|
152
|
+
lang
|
|
153
|
+
});
|
|
154
|
+
if (results.length >= maxBlocks) break;
|
|
155
|
+
offset = closeIdx + 9;
|
|
156
|
+
}
|
|
157
|
+
return results;
|
|
158
|
+
}
|
|
159
|
+
function partialSourceTextLoader(absoluteFilePath, fileContent) {
|
|
160
|
+
if (absoluteFilePath.endsWith(".vue")) return partialVueSourceTextLoader(fileContent);
|
|
161
|
+
else if (absoluteFilePath.endsWith(".astro")) return partialAstroSourceTextLoader(fileContent);
|
|
162
|
+
else if (absoluteFilePath.endsWith(".svelte")) return partialSvelteSourceTextLoader(fileContent);
|
|
163
|
+
return [{
|
|
164
|
+
sourceText: fileContent,
|
|
165
|
+
offset: 0
|
|
166
|
+
}];
|
|
167
|
+
}
|
|
168
|
+
function isWhitespace(char) {
|
|
169
|
+
return char === " " || char === " " || char === "\r";
|
|
170
|
+
}
|
|
171
|
+
function findDelimiter(sourceText, startPos) {
|
|
172
|
+
let i = startPos;
|
|
173
|
+
while (i < sourceText.length) {
|
|
174
|
+
if (i === 0 || sourceText[i - 1] === "\n") {
|
|
175
|
+
let j = i;
|
|
176
|
+
while (j < sourceText.length && isWhitespace(sourceText[j])) j++;
|
|
177
|
+
if (sourceText[j] === "-" && sourceText[j + 1] === "-" && sourceText[j + 2] === "-") {
|
|
178
|
+
let k = j + 3;
|
|
179
|
+
while (k < sourceText.length && sourceText[k] !== "\n") {
|
|
180
|
+
if (!isWhitespace(sourceText[k])) break;
|
|
181
|
+
k++;
|
|
182
|
+
}
|
|
183
|
+
if (k === sourceText.length || sourceText[k] === "\n") return j;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
i++;
|
|
187
|
+
}
|
|
188
|
+
return -1;
|
|
189
|
+
}
|
|
190
|
+
function partialVueSourceTextLoader(sourceText) {
|
|
191
|
+
return extractScriptBlocks(sourceText, 0, 2, true);
|
|
192
|
+
}
|
|
193
|
+
function partialSvelteSourceTextLoader(sourceText) {
|
|
194
|
+
return extractScriptBlocks(sourceText, 0, 2, true);
|
|
195
|
+
}
|
|
196
|
+
function partialAstroSourceTextLoader(sourceText) {
|
|
197
|
+
const results = [];
|
|
198
|
+
let pos = 0;
|
|
199
|
+
const frontmatterStartDelimiter = findDelimiter(sourceText, pos);
|
|
200
|
+
if (frontmatterStartDelimiter !== -1) {
|
|
201
|
+
const frontmatterContentStart = frontmatterStartDelimiter + 3;
|
|
202
|
+
const frontmatterEndDelimiter = findDelimiter(sourceText, frontmatterContentStart);
|
|
203
|
+
if (frontmatterEndDelimiter !== -1) {
|
|
204
|
+
const content = sourceText.slice(frontmatterContentStart, frontmatterEndDelimiter);
|
|
205
|
+
results.push({
|
|
206
|
+
sourceText: content,
|
|
207
|
+
offset: frontmatterContentStart,
|
|
208
|
+
lang: "ts",
|
|
209
|
+
sourceType: "module"
|
|
210
|
+
});
|
|
211
|
+
pos = frontmatterEndDelimiter + 3;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
results.push(...extractScriptBlocks(sourceText, pos, Number.MAX_SAFE_INTEGER, false).map((sourceText$1) => {
|
|
215
|
+
return Object.assign(sourceText$1, {
|
|
216
|
+
lang: `ts`,
|
|
217
|
+
sourceType: `module`
|
|
218
|
+
});
|
|
219
|
+
}));
|
|
220
|
+
return results;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
//#endregion
|
|
224
|
+
//#region src/walker/replaceCommentsInFile.ts
|
|
225
|
+
const getComments = (absoluteFilePath, partialSourceText, options) => {
|
|
226
|
+
const parserResult = parseSync(absoluteFilePath, partialSourceText.sourceText, {
|
|
227
|
+
lang: partialSourceText.lang,
|
|
228
|
+
sourceType: partialSourceText.sourceType
|
|
229
|
+
});
|
|
230
|
+
if (parserResult.errors.length > 0) options.reporter?.report(`${absoluteFilePath}: failed to parse`);
|
|
231
|
+
return parserResult.comments;
|
|
232
|
+
};
|
|
233
|
+
function replaceCommentsInSourceText(absoluteFilePath, partialSourceText, options) {
|
|
234
|
+
const comments = getComments(absoluteFilePath, partialSourceText, options);
|
|
235
|
+
let sourceText = partialSourceText.sourceText;
|
|
236
|
+
for (const comment of comments) try {
|
|
237
|
+
const replacedStr = replaceComments(comment.value, comment.type, options);
|
|
238
|
+
if (replacedStr !== comment.value) {
|
|
239
|
+
const newComment = comment.type === "Line" ? `//${replacedStr}` : `/*${replacedStr}*/`;
|
|
240
|
+
sourceText = sourceText.slice(0, comment.start) + newComment + sourceText.slice(comment.end);
|
|
241
|
+
}
|
|
242
|
+
} catch (error) {
|
|
243
|
+
if (error instanceof Error) {
|
|
244
|
+
options.reporter?.report(`${absoluteFilePath}, char offset ${comment.start + partialSourceText.offset}: ${error.message}`);
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
return sourceText;
|
|
250
|
+
}
|
|
251
|
+
function replaceCommentsInFile(absoluteFilePath, fileContent, options) {
|
|
252
|
+
for (const partialSourceText of partialSourceTextLoader(absoluteFilePath, fileContent)) {
|
|
253
|
+
const newSourceText = replaceCommentsInSourceText(absoluteFilePath, partialSourceText, options);
|
|
254
|
+
if (newSourceText !== partialSourceText.sourceText) fileContent = fileContent.slice(0, partialSourceText.offset) + newSourceText + fileContent.slice(partialSourceText.offset + partialSourceText.sourceText.length);
|
|
255
|
+
}
|
|
256
|
+
return fileContent;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
//#endregion
|
|
260
|
+
//#region src/walker/index.ts
|
|
261
|
+
const walkAndReplaceProjectFiles = (projectFiles, readFileSync$1, writeFile$1, options) => {
|
|
262
|
+
return Promise.all(projectFiles.map((file) => {
|
|
263
|
+
const sourceText = readFileSync$1(file);
|
|
264
|
+
if (!sourceText) return Promise.resolve();
|
|
265
|
+
const newSourceText = replaceCommentsInFile(file, sourceText, options);
|
|
266
|
+
if (newSourceText === sourceText) return Promise.resolve();
|
|
267
|
+
return writeFile$1(file, newSourceText);
|
|
268
|
+
}));
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
//#endregion
|
|
272
|
+
//#region bin/project-loader.ts
|
|
273
|
+
const getAllProjectFiles = () => {
|
|
274
|
+
return glob([
|
|
275
|
+
"**/*.{js,cjs,mjs,ts,cts,mts,jsx,tsx,vue,astro,svelte}",
|
|
276
|
+
"!**/node_modules/**",
|
|
277
|
+
"!**/dist/**"
|
|
278
|
+
], { absolute: true });
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
//#endregion
|
|
282
|
+
//#region src/reporter.ts
|
|
283
|
+
var DefaultReporter = class {
|
|
284
|
+
reports = /* @__PURE__ */ new Set();
|
|
285
|
+
report(message) {
|
|
286
|
+
this.reports.add(message);
|
|
287
|
+
}
|
|
288
|
+
remove(message) {
|
|
289
|
+
this.reports.delete(message);
|
|
290
|
+
}
|
|
291
|
+
getReports() {
|
|
292
|
+
return Array.from(this.reports);
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
//#endregion
|
|
297
|
+
//#region bin/oxlint-migrate.ts
|
|
13
298
|
const cwd = process.cwd();
|
|
14
299
|
const getFileContent = (absoluteFilePath) => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
300
|
+
try {
|
|
301
|
+
return readFileSync(absoluteFilePath, "utf-8");
|
|
302
|
+
} catch {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
20
305
|
};
|
|
21
|
-
program.name("oxlint-migrate").version(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
jsPlugins: !!cliOptions.jsPlugins
|
|
52
|
-
};
|
|
53
|
-
if (cliOptions.replaceEslintComments) {
|
|
54
|
-
await walkAndReplaceProjectFiles(
|
|
55
|
-
await getAllProjectFiles(),
|
|
56
|
-
(filePath2) => getFileContent(filePath2),
|
|
57
|
-
(filePath2, content) => writeFile(filePath2, content, "utf-8"),
|
|
58
|
-
options
|
|
59
|
-
);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
if (filePath === void 0) {
|
|
63
|
-
filePath = getAutodetectedEslintConfigName(cwd);
|
|
64
|
-
} else {
|
|
65
|
-
filePath = path.join(cwd, filePath);
|
|
66
|
-
}
|
|
67
|
-
if (filePath === void 0) {
|
|
68
|
-
program.error(`could not autodetect eslint config file`);
|
|
69
|
-
}
|
|
70
|
-
const resetPreFix = await preFixForJsPlugins();
|
|
71
|
-
const eslintConfigs = await loadESLintConfig(filePath);
|
|
72
|
-
resetPreFix();
|
|
73
|
-
let config;
|
|
74
|
-
if (options.merge && existsSync(oxlintFilePath)) {
|
|
75
|
-
config = JSON.parse(
|
|
76
|
-
readFileSync(oxlintFilePath, { encoding: "utf8", flag: "r" })
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
const oxlintConfig = "default" in eslintConfigs ? await main(eslintConfigs.default, config, options) : await main(eslintConfigs, config, options);
|
|
80
|
-
if (existsSync(oxlintFilePath)) {
|
|
81
|
-
renameSync(oxlintFilePath, `${oxlintFilePath}.bak`);
|
|
82
|
-
}
|
|
83
|
-
writeFileSync(oxlintFilePath, JSON.stringify(oxlintConfig, null, 2));
|
|
84
|
-
for (const report of reporter.getReports()) {
|
|
85
|
-
console.warn(report);
|
|
86
|
-
}
|
|
306
|
+
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`.").action(async (filePath) => {
|
|
307
|
+
const cliOptions = program.opts();
|
|
308
|
+
const oxlintFilePath = path.join(cwd, cliOptions.outputFile);
|
|
309
|
+
const reporter = new DefaultReporter();
|
|
310
|
+
const options = {
|
|
311
|
+
reporter,
|
|
312
|
+
merge: !!cliOptions.merge,
|
|
313
|
+
withNursery: !!cliOptions.withNursery,
|
|
314
|
+
typeAware: !!cliOptions.typeAware,
|
|
315
|
+
jsPlugins: !!cliOptions.jsPlugins
|
|
316
|
+
};
|
|
317
|
+
if (cliOptions.replaceEslintComments) {
|
|
318
|
+
await walkAndReplaceProjectFiles(await getAllProjectFiles(), (filePath$1) => getFileContent(filePath$1), (filePath$1, content) => writeFile(filePath$1, content, "utf-8"), options);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
if (filePath === void 0) filePath = getAutodetectedEslintConfigName(cwd);
|
|
322
|
+
else filePath = path.join(cwd, filePath);
|
|
323
|
+
if (filePath === void 0) program.error(`could not autodetect eslint config file`);
|
|
324
|
+
const resetPreFix = await preFixForJsPlugins();
|
|
325
|
+
const eslintConfigs = await loadESLintConfig(filePath);
|
|
326
|
+
resetPreFix();
|
|
327
|
+
let config;
|
|
328
|
+
if (options.merge && existsSync(oxlintFilePath)) config = JSON.parse(readFileSync(oxlintFilePath, {
|
|
329
|
+
encoding: "utf8",
|
|
330
|
+
flag: "r"
|
|
331
|
+
}));
|
|
332
|
+
const oxlintConfig = "default" in eslintConfigs ? await src_default(eslintConfigs.default, config, options) : await src_default(eslintConfigs, config, options);
|
|
333
|
+
if (existsSync(oxlintFilePath)) renameSync(oxlintFilePath, `${oxlintFilePath}.bak`);
|
|
334
|
+
writeFileSync(oxlintFilePath, JSON.stringify(oxlintConfig, null, 2));
|
|
335
|
+
for (const report of reporter.getReports()) console.warn(report);
|
|
87
336
|
});
|
|
88
337
|
program.parse();
|
|
338
|
+
|
|
339
|
+
//#endregion
|
|
340
|
+
export { };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Linter } from "eslint";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
type OxlintConfigPlugins = string[];
|
|
5
|
+
type OxlintConfigJsPlugins = string[];
|
|
6
|
+
type OxlintConfigCategories = Partial<Record<Category, unknown>>;
|
|
7
|
+
type OxlintConfigEnv = Record<string, boolean>;
|
|
8
|
+
type OxlintConfigIgnorePatterns = string[];
|
|
9
|
+
type OxlintConfigOverride = {
|
|
10
|
+
files: string[];
|
|
11
|
+
env?: OxlintConfigEnv;
|
|
12
|
+
globals?: Linter.Globals;
|
|
13
|
+
plugins?: OxlintConfigPlugins;
|
|
14
|
+
jsPlugins?: OxlintConfigJsPlugins;
|
|
15
|
+
categories?: OxlintConfigCategories;
|
|
16
|
+
rules?: Partial<Linter.RulesRecord>;
|
|
17
|
+
};
|
|
18
|
+
type OxlintConfig = {
|
|
19
|
+
$schema?: string;
|
|
20
|
+
env?: OxlintConfigEnv;
|
|
21
|
+
globals?: Linter.Globals;
|
|
22
|
+
plugins?: OxlintConfigPlugins;
|
|
23
|
+
jsPlugins?: OxlintConfigJsPlugins;
|
|
24
|
+
categories?: OxlintConfigCategories;
|
|
25
|
+
rules?: Partial<Linter.RulesRecord>;
|
|
26
|
+
overrides?: OxlintConfigOverride[];
|
|
27
|
+
ignorePatterns?: OxlintConfigIgnorePatterns;
|
|
28
|
+
};
|
|
29
|
+
type Reporter = {
|
|
30
|
+
report(message: string): void;
|
|
31
|
+
remove(message: string): void;
|
|
32
|
+
getReports(): string[];
|
|
33
|
+
};
|
|
34
|
+
type Options = {
|
|
35
|
+
reporter?: Reporter;
|
|
36
|
+
merge?: boolean;
|
|
37
|
+
withNursery?: boolean;
|
|
38
|
+
typeAware?: boolean;
|
|
39
|
+
jsPlugins?: boolean;
|
|
40
|
+
};
|
|
41
|
+
type Category = 'style' | 'correctness' | 'nursery' | 'suspicious' | 'pedantic' | 'perf' | 'restriction';
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/index.d.ts
|
|
44
|
+
declare const main: (configs: Linter.Config | Linter.Config[] | Promise<Linter.Config> | Promise<Linter.Config[]>, oxlintConfig?: OxlintConfig, options?: Options) => Promise<OxlintConfig>;
|
|
45
|
+
//#endregion
|
|
46
|
+
export { main as default };
|
package/dist/src/index.mjs
CHANGED
|
@@ -1,80 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { transformRuleEntry, detectNeededRulesPlugins } from "./plugins_rules.mjs";
|
|
5
|
-
import { detectSameOverride } from "./overrides.mjs";
|
|
6
|
-
import fixForJsPlugins from "./js_plugin_fixes.mjs";
|
|
7
|
-
const buildConfig = (configs, oxlintConfig, options) => {
|
|
8
|
-
if (oxlintConfig === void 0) {
|
|
9
|
-
if (options?.merge) {
|
|
10
|
-
oxlintConfig = {
|
|
11
|
-
// disable all plugins and check later
|
|
12
|
-
plugins: ["oxc", "typescript", "unicorn", "react"],
|
|
13
|
-
categories: {
|
|
14
|
-
correctness: "warn"
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
} else {
|
|
18
|
-
oxlintConfig = {
|
|
19
|
-
$schema: "./node_modules/oxlint/configuration_schema.json",
|
|
20
|
-
// disable all plugins and check later
|
|
21
|
-
plugins: [],
|
|
22
|
-
categories: {
|
|
23
|
-
// ToDo: for merge set the default category manuel when it is not found
|
|
24
|
-
// ToDo: later we can remove it again
|
|
25
|
-
// default category
|
|
26
|
-
correctness: "off"
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
if (oxlintConfig.$schema === void 0 && options?.merge) {
|
|
32
|
-
oxlintConfig.$schema = "./node_modules/oxlint/configuration_schema.json";
|
|
33
|
-
}
|
|
34
|
-
if (oxlintConfig.env?.builtin === void 0) {
|
|
35
|
-
if (oxlintConfig.env === void 0) {
|
|
36
|
-
oxlintConfig.env = {};
|
|
37
|
-
}
|
|
38
|
-
oxlintConfig.env.builtin = true;
|
|
39
|
-
}
|
|
40
|
-
const overrides = options?.merge ? oxlintConfig.overrides ?? [] : [];
|
|
41
|
-
for (const config of configs) {
|
|
42
|
-
if (config.name?.startsWith("oxlint/")) {
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
let targetConfig;
|
|
46
|
-
if (config.files === void 0) {
|
|
47
|
-
targetConfig = oxlintConfig;
|
|
48
|
-
} else {
|
|
49
|
-
targetConfig = {
|
|
50
|
-
files: Array.isArray(config.files) ? config.files : [config.files]
|
|
51
|
-
};
|
|
52
|
-
const [push, result] = detectSameOverride(oxlintConfig, targetConfig);
|
|
53
|
-
if (push) {
|
|
54
|
-
overrides.push(result);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
if (config.settings !== void 0) ;
|
|
58
|
-
transformIgnorePatterns(config, targetConfig, options);
|
|
59
|
-
transformRuleEntry(config, targetConfig, options);
|
|
60
|
-
transformEnvAndGlobals(config, targetConfig, options);
|
|
61
|
-
if ("files" in targetConfig) {
|
|
62
|
-
detectNeededRulesPlugins(targetConfig);
|
|
63
|
-
detectEnvironmentByGlobals(targetConfig);
|
|
64
|
-
cleanUpOxlintConfig(targetConfig);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
oxlintConfig.overrides = overrides;
|
|
68
|
-
detectNeededRulesPlugins(oxlintConfig);
|
|
69
|
-
detectEnvironmentByGlobals(oxlintConfig);
|
|
70
|
-
cleanUpOxlintConfig(oxlintConfig);
|
|
71
|
-
return oxlintConfig;
|
|
72
|
-
};
|
|
73
|
-
const main = async (configs, oxlintConfig, options) => {
|
|
74
|
-
const resolved = await Promise.resolve(fixForJsPlugins(configs));
|
|
75
|
-
const resolvedConfigs = Array.isArray(resolved) ? resolved : [resolved];
|
|
76
|
-
return buildConfig(resolvedConfigs, oxlintConfig, options);
|
|
77
|
-
};
|
|
78
|
-
export {
|
|
79
|
-
main as default
|
|
80
|
-
};
|
|
1
|
+
import { t as src_default } from "../src-MX2M8fZn.mjs";
|
|
2
|
+
|
|
3
|
+
export { src_default as default };
|