@oxlint/migrate 1.7.0 → 1.8.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 +6 -5
- package/dist/bin/oxlint-migrate.mjs +27 -5
- package/dist/bin/project-loader.mjs +16 -0
- package/dist/package.json.mjs +1 -1
- package/dist/src/constants.mjs +2 -1
- package/dist/src/generated/rules.mjs +1 -1
- package/dist/src/walker/comments/index.d.ts +2 -0
- package/dist/src/walker/comments/index.mjs +20 -0
- package/dist/src/walker/comments/replaceRuleDirectiveComment.d.ts +2 -0
- package/dist/src/walker/comments/replaceRuleDirectiveComment.mjs +59 -0
- package/dist/src/walker/comments/replaceRuleDirectiveComment.test.d.ts +1 -0
- package/dist/src/walker/index.d.ts +10 -0
- package/dist/src/walker/index.mjs +19 -0
- package/dist/src/walker/partialSourceTextLoader.d.ts +10 -0
- package/dist/src/walker/partialSourceTextLoader.mjs +167 -0
- package/dist/src/walker/partialSourceTextLoader.test.d.ts +1 -0
- package/dist/src/walker/replaceCommentsInFile.d.ts +2 -0
- package/dist/src/walker/replaceCommentsInFile.mjs +60 -0
- package/dist/src/walker/replaceCommentsInFile.test.d.ts +1 -0
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -16,11 +16,12 @@ When no config file provided, the script searches for the default eslint config
|
|
|
16
16
|
|
|
17
17
|
### Options
|
|
18
18
|
|
|
19
|
-
| Options
|
|
20
|
-
|
|
|
21
|
-
| `--merge`
|
|
22
|
-
| `--with-nursery`
|
|
23
|
-
| `--output-file <file>`
|
|
19
|
+
| Options | Description |
|
|
20
|
+
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
21
|
+
| `--merge` | \* merge eslint configuration with an existing .oxlintrc.json configuration |
|
|
22
|
+
| `--with-nursery` | Include oxlint rules which are currently under development |
|
|
23
|
+
| `--output-file <file>` | The oxlint configuration file where to eslint v9 rules will be written to, default: `.oxlintrc.json` |
|
|
24
|
+
| `--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. |
|
|
24
25
|
|
|
25
26
|
\* WARNING: When some `categories` are enabled, this tools will enable more rules with the combination of `plugins`.
|
|
26
27
|
Else we need to disable each rule `plugin/categories` combination, which is not covered by your eslint configuration.
|
|
@@ -5,7 +5,17 @@ import path from "node:path";
|
|
|
5
5
|
import { getAutodetectedEslintConfigName, loadESLintConfig } from "./config-loader.mjs";
|
|
6
6
|
import main from "../src/index.mjs";
|
|
7
7
|
import packageJson from "../package.json.mjs";
|
|
8
|
+
import { walkAndReplaceProjectFiles } from "../src/walker/index.mjs";
|
|
9
|
+
import { getAllProjectFiles } from "./project-loader.mjs";
|
|
10
|
+
import { writeFile } from "node:fs/promises";
|
|
8
11
|
const cwd = process.cwd();
|
|
12
|
+
const getFileContent = (absoluteFilePath) => {
|
|
13
|
+
try {
|
|
14
|
+
return readFileSync(absoluteFilePath, "utf-8");
|
|
15
|
+
} catch {
|
|
16
|
+
return void 0;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
9
19
|
program.name("oxlint-migrate").version(packageJson.version).argument("[eslint-config]", "The path to the eslint v9 config file").option(
|
|
10
20
|
"--output-file <file>",
|
|
11
21
|
"The oxlint configuration file where to eslint v9 rules will be written to",
|
|
@@ -18,9 +28,26 @@ program.name("oxlint-migrate").version(packageJson.version).argument("[eslint-co
|
|
|
18
28
|
"--with-nursery",
|
|
19
29
|
"Include oxlint rules which are currently under development",
|
|
20
30
|
false
|
|
31
|
+
).option(
|
|
32
|
+
"--replace-eslint-comments",
|
|
33
|
+
"Search in the project files for eslint comments and replaces them with oxlint. Some eslint comments are not supported and will be reported."
|
|
21
34
|
).action(async (filePath) => {
|
|
22
35
|
const cliOptions = program.opts();
|
|
23
36
|
const oxlintFilePath = path.join(cwd, cliOptions.outputFile);
|
|
37
|
+
const options = {
|
|
38
|
+
reporter: console.warn,
|
|
39
|
+
merge: !!cliOptions.merge,
|
|
40
|
+
withNursery: !!cliOptions.withNursery
|
|
41
|
+
};
|
|
42
|
+
if (cliOptions.replaceEslintComments) {
|
|
43
|
+
await walkAndReplaceProjectFiles(
|
|
44
|
+
await getAllProjectFiles(),
|
|
45
|
+
(filePath2) => getFileContent(filePath2),
|
|
46
|
+
(filePath2, content) => writeFile(filePath2, content, "utf-8"),
|
|
47
|
+
options
|
|
48
|
+
);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
24
51
|
if (filePath === void 0) {
|
|
25
52
|
filePath = getAutodetectedEslintConfigName(cwd);
|
|
26
53
|
} else {
|
|
@@ -30,11 +57,6 @@ program.name("oxlint-migrate").version(packageJson.version).argument("[eslint-co
|
|
|
30
57
|
program.error(`could not autodetect eslint config file`);
|
|
31
58
|
}
|
|
32
59
|
const eslintConfigs = await loadESLintConfig(filePath);
|
|
33
|
-
const options = {
|
|
34
|
-
reporter: console.warn,
|
|
35
|
-
merge: !!cliOptions.merge,
|
|
36
|
-
withNursery: !!cliOptions.withNursery
|
|
37
|
-
};
|
|
38
60
|
let config;
|
|
39
61
|
if (options.merge && existsSync(oxlintFilePath)) {
|
|
40
62
|
config = JSON.parse(
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { glob } from "tinyglobby";
|
|
2
|
+
const getAllProjectFiles = () => {
|
|
3
|
+
return glob(
|
|
4
|
+
[
|
|
5
|
+
"**/*.{js,cjs,mjs,ts,cts,mts,vue,astro,svelte}",
|
|
6
|
+
"!**/node_modules/**",
|
|
7
|
+
"!**/dist/**"
|
|
8
|
+
],
|
|
9
|
+
{
|
|
10
|
+
absolute: true
|
|
11
|
+
}
|
|
12
|
+
);
|
|
13
|
+
};
|
|
14
|
+
export {
|
|
15
|
+
getAllProjectFiles
|
|
16
|
+
};
|
package/dist/package.json.mjs
CHANGED
package/dist/src/constants.mjs
CHANGED
|
@@ -218,7 +218,6 @@ const styleRules = [
|
|
|
218
218
|
"unicorn/prefer-object-from-entries",
|
|
219
219
|
"unicorn/prefer-array-index-of",
|
|
220
220
|
"unicorn/prefer-spread",
|
|
221
|
-
"unicorn/prefer-array-flat-map",
|
|
222
221
|
"unicorn/prefer-dom-node-text-content",
|
|
223
222
|
"unicorn/prefer-includes",
|
|
224
223
|
"unicorn/prefer-logical-operator-over-ternary",
|
|
@@ -588,6 +587,7 @@ const perfRules = [
|
|
|
588
587
|
"react-perf/jsx-no-new-function-as-prop",
|
|
589
588
|
"react-perf/jsx-no-new-object-as-prop",
|
|
590
589
|
"unicorn/prefer-array-find",
|
|
590
|
+
"unicorn/prefer-array-flat-map",
|
|
591
591
|
"unicorn/prefer-set-has"
|
|
592
592
|
];
|
|
593
593
|
export {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import replaceRuleDirectiveComment from "./replaceRuleDirectiveComment.mjs";
|
|
2
|
+
function replaceComments(comment, type, options) {
|
|
3
|
+
const originalComment = comment;
|
|
4
|
+
comment = comment.trim();
|
|
5
|
+
if (comment.startsWith("eslint-")) {
|
|
6
|
+
return replaceRuleDirectiveComment(originalComment, type, options);
|
|
7
|
+
} else if (type === "Block") {
|
|
8
|
+
if (comment.startsWith("eslint ")) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
"changing eslint rules with inline comment is not supported"
|
|
11
|
+
);
|
|
12
|
+
} else if (comment.startsWith("global ")) {
|
|
13
|
+
throw new Error("changing globals with inline comment is not supported");
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return originalComment;
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
replaceComments as default
|
|
20
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as rules from "../../generated/rules.mjs";
|
|
2
|
+
import { nurseryRules } from "../../generated/rules.mjs";
|
|
3
|
+
const allRules = Object.values(rules).flat();
|
|
4
|
+
function replaceRuleDirectiveComment(comment, type, options) {
|
|
5
|
+
const originalComment = comment;
|
|
6
|
+
comment = comment.split(" -- ")[0].trimStart();
|
|
7
|
+
if (!comment.startsWith("eslint-")) {
|
|
8
|
+
return originalComment;
|
|
9
|
+
}
|
|
10
|
+
comment = comment.substring(7);
|
|
11
|
+
if (comment.startsWith("enable")) {
|
|
12
|
+
comment = comment.substring(6);
|
|
13
|
+
} else if (comment.startsWith("disable")) {
|
|
14
|
+
comment = comment.substring(7);
|
|
15
|
+
if (type === "Line") {
|
|
16
|
+
if (comment.startsWith("-next-line")) {
|
|
17
|
+
comment = comment.substring(10);
|
|
18
|
+
} else if (comment.startsWith("-line")) {
|
|
19
|
+
comment = comment.substring(5);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
} else {
|
|
23
|
+
return originalComment;
|
|
24
|
+
}
|
|
25
|
+
if (!comment.startsWith(" ")) {
|
|
26
|
+
return originalComment;
|
|
27
|
+
}
|
|
28
|
+
comment = comment.trimStart();
|
|
29
|
+
if (comment.length === 0) {
|
|
30
|
+
return originalComment;
|
|
31
|
+
}
|
|
32
|
+
while (comment.length) {
|
|
33
|
+
let foundRule = false;
|
|
34
|
+
for (const rule of allRules) {
|
|
35
|
+
if (comment.startsWith(rule)) {
|
|
36
|
+
if (!options.withNursery && nurseryRules.includes(rule)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
foundRule = true;
|
|
40
|
+
comment = comment.substring(rule.length).trimStart();
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!foundRule) {
|
|
45
|
+
return originalComment;
|
|
46
|
+
}
|
|
47
|
+
if (!comment.length) {
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
if (!comment.startsWith(", ")) {
|
|
51
|
+
return originalComment;
|
|
52
|
+
}
|
|
53
|
+
comment = comment.substring(1).trimStart();
|
|
54
|
+
}
|
|
55
|
+
return originalComment.replace(/eslint-/, "oxlint-");
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
replaceRuleDirectiveComment as default
|
|
59
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Options } from '../types.js';
|
|
2
|
+
export declare const walkAndReplaceProjectFiles: (
|
|
3
|
+
/** all projects files to check */
|
|
4
|
+
projectFiles: string[],
|
|
5
|
+
/** function for reading the file */
|
|
6
|
+
readFileSync: (filePath: string) => string | undefined,
|
|
7
|
+
/** function for writing the file */
|
|
8
|
+
writeFile: (filePath: string, content: string) => Promise<void>,
|
|
9
|
+
/** options for the walker, for `reporter` and `withNurseryRules` */
|
|
10
|
+
options: Options) => Promise<void[]>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import replaceCommentsInFile from "./replaceCommentsInFile.mjs";
|
|
2
|
+
const walkAndReplaceProjectFiles = (projectFiles, readFileSync, writeFile, options) => {
|
|
3
|
+
return Promise.all(
|
|
4
|
+
projectFiles.map((file) => {
|
|
5
|
+
const sourceText = readFileSync(file);
|
|
6
|
+
if (!sourceText) {
|
|
7
|
+
return Promise.resolve();
|
|
8
|
+
}
|
|
9
|
+
const newSourceText = replaceCommentsInFile(file, sourceText, options);
|
|
10
|
+
if (newSourceText === sourceText) {
|
|
11
|
+
return Promise.resolve();
|
|
12
|
+
}
|
|
13
|
+
return writeFile(file, newSourceText);
|
|
14
|
+
})
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
walkAndReplaceProjectFiles
|
|
19
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type PartialSourceText = {
|
|
2
|
+
sourceText: string;
|
|
3
|
+
offset: number;
|
|
4
|
+
lang?: 'js' | 'jsx' | 'ts' | 'tsx';
|
|
5
|
+
sourceType?: 'script' | 'module';
|
|
6
|
+
};
|
|
7
|
+
export default function partialSourceTextLoader(absoluteFilePath: string, fileContent: string): PartialSourceText[];
|
|
8
|
+
export declare function partialVueSourceTextLoader(sourceText: string): PartialSourceText[];
|
|
9
|
+
export declare function partialSvelteSourceTextLoader(sourceText: string): PartialSourceText[];
|
|
10
|
+
export declare function partialAstroSourceTextLoader(sourceText: string): PartialSourceText[];
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
function extractLangAttribute(source) {
|
|
2
|
+
const langIndex = source.indexOf("lang");
|
|
3
|
+
if (langIndex === -1) return void 0;
|
|
4
|
+
let cursor = langIndex + 4;
|
|
5
|
+
while (cursor < source.length && isWhitespace(source[cursor])) {
|
|
6
|
+
cursor++;
|
|
7
|
+
}
|
|
8
|
+
if (source[cursor] !== "=") return void 0;
|
|
9
|
+
cursor++;
|
|
10
|
+
while (cursor < source.length && isWhitespace(source[cursor])) {
|
|
11
|
+
cursor++;
|
|
12
|
+
}
|
|
13
|
+
const quote = source[cursor];
|
|
14
|
+
if (quote !== '"' && quote !== "'") return void 0;
|
|
15
|
+
cursor++;
|
|
16
|
+
let value = "";
|
|
17
|
+
while (cursor < source.length && source[cursor] !== quote) {
|
|
18
|
+
value += source[cursor++];
|
|
19
|
+
}
|
|
20
|
+
if (value === "js" || value === "jsx" || value === "ts" || value === "tsx") {
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
return void 0;
|
|
24
|
+
}
|
|
25
|
+
function extractScriptBlocks(sourceText, offset, maxBlocks, parseLangAttribute) {
|
|
26
|
+
const results = [];
|
|
27
|
+
while (offset < sourceText.length) {
|
|
28
|
+
const idx = sourceText.indexOf("<script", offset);
|
|
29
|
+
if (idx === -1) break;
|
|
30
|
+
const nextChar = sourceText[idx + 7];
|
|
31
|
+
if (nextChar !== " " && nextChar !== ">" && nextChar !== "\n" && nextChar !== " ") {
|
|
32
|
+
offset = idx + 7;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
let i = idx + 7;
|
|
36
|
+
let inQuote = null;
|
|
37
|
+
let genericDepth = 0;
|
|
38
|
+
let selfClosing = false;
|
|
39
|
+
while (i < sourceText.length) {
|
|
40
|
+
const c = sourceText[i];
|
|
41
|
+
if (inQuote) {
|
|
42
|
+
if (c === inQuote) inQuote = null;
|
|
43
|
+
} else if (c === '"' || c === "'") {
|
|
44
|
+
inQuote = c;
|
|
45
|
+
} else if (c === "<") {
|
|
46
|
+
genericDepth++;
|
|
47
|
+
} else if (c === ">") {
|
|
48
|
+
if (genericDepth > 0) {
|
|
49
|
+
genericDepth--;
|
|
50
|
+
} else {
|
|
51
|
+
if (i > idx && sourceText[i - 1] === "/") {
|
|
52
|
+
selfClosing = true;
|
|
53
|
+
}
|
|
54
|
+
i++;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
i++;
|
|
59
|
+
}
|
|
60
|
+
if (selfClosing) {
|
|
61
|
+
offset = i;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (i >= sourceText.length) break;
|
|
65
|
+
let lang = void 0;
|
|
66
|
+
if (parseLangAttribute) {
|
|
67
|
+
lang = extractLangAttribute(sourceText.slice(idx, i));
|
|
68
|
+
}
|
|
69
|
+
const contentStart = i;
|
|
70
|
+
const closeTag = "<\/script>";
|
|
71
|
+
const closeIdx = sourceText.indexOf(closeTag, contentStart);
|
|
72
|
+
if (closeIdx === -1) break;
|
|
73
|
+
const content = sourceText.slice(contentStart, closeIdx);
|
|
74
|
+
results.push({ sourceText: content, offset: contentStart, lang });
|
|
75
|
+
if (results.length >= maxBlocks) {
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
offset = closeIdx + closeTag.length;
|
|
79
|
+
}
|
|
80
|
+
return results;
|
|
81
|
+
}
|
|
82
|
+
function partialSourceTextLoader(absoluteFilePath, fileContent) {
|
|
83
|
+
if (absoluteFilePath.endsWith(".vue")) {
|
|
84
|
+
return partialVueSourceTextLoader(fileContent);
|
|
85
|
+
} else if (absoluteFilePath.endsWith(".astro")) {
|
|
86
|
+
return partialAstroSourceTextLoader(fileContent);
|
|
87
|
+
} else if (absoluteFilePath.endsWith(".svelte")) {
|
|
88
|
+
return partialSvelteSourceTextLoader(fileContent);
|
|
89
|
+
}
|
|
90
|
+
return [
|
|
91
|
+
{
|
|
92
|
+
sourceText: fileContent,
|
|
93
|
+
offset: 0
|
|
94
|
+
}
|
|
95
|
+
];
|
|
96
|
+
}
|
|
97
|
+
function isWhitespace(char) {
|
|
98
|
+
return char === " " || char === " " || char === "\r";
|
|
99
|
+
}
|
|
100
|
+
function findDelimiter(sourceText, startPos) {
|
|
101
|
+
let i = startPos;
|
|
102
|
+
while (i < sourceText.length) {
|
|
103
|
+
if (i === 0 || sourceText[i - 1] === "\n") {
|
|
104
|
+
let j = i;
|
|
105
|
+
while (j < sourceText.length && isWhitespace(sourceText[j])) j++;
|
|
106
|
+
if (sourceText[j] === "-" && sourceText[j + 1] === "-" && sourceText[j + 2] === "-") {
|
|
107
|
+
let k = j + 3;
|
|
108
|
+
while (k < sourceText.length && sourceText[k] !== "\n") {
|
|
109
|
+
if (!isWhitespace(sourceText[k])) break;
|
|
110
|
+
k++;
|
|
111
|
+
}
|
|
112
|
+
if (k === sourceText.length || sourceText[k] === "\n") {
|
|
113
|
+
return j;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
i++;
|
|
118
|
+
}
|
|
119
|
+
return -1;
|
|
120
|
+
}
|
|
121
|
+
function partialVueSourceTextLoader(sourceText) {
|
|
122
|
+
return extractScriptBlocks(sourceText, 0, 2, true);
|
|
123
|
+
}
|
|
124
|
+
function partialSvelteSourceTextLoader(sourceText) {
|
|
125
|
+
return extractScriptBlocks(sourceText, 0, 2, true);
|
|
126
|
+
}
|
|
127
|
+
function partialAstroSourceTextLoader(sourceText) {
|
|
128
|
+
const results = [];
|
|
129
|
+
let pos = 0;
|
|
130
|
+
const frontmatterStartDelimiter = findDelimiter(sourceText, pos);
|
|
131
|
+
if (frontmatterStartDelimiter !== -1) {
|
|
132
|
+
const frontmatterContentStart = frontmatterStartDelimiter + 3;
|
|
133
|
+
const frontmatterEndDelimiter = findDelimiter(
|
|
134
|
+
sourceText,
|
|
135
|
+
frontmatterContentStart
|
|
136
|
+
);
|
|
137
|
+
if (frontmatterEndDelimiter !== -1) {
|
|
138
|
+
const content = sourceText.slice(
|
|
139
|
+
frontmatterContentStart,
|
|
140
|
+
frontmatterEndDelimiter
|
|
141
|
+
);
|
|
142
|
+
results.push({
|
|
143
|
+
sourceText: content,
|
|
144
|
+
offset: frontmatterContentStart,
|
|
145
|
+
lang: "ts",
|
|
146
|
+
sourceType: "module"
|
|
147
|
+
});
|
|
148
|
+
pos = frontmatterEndDelimiter + 3;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
results.push(
|
|
152
|
+
...extractScriptBlocks(sourceText, pos, Number.MAX_SAFE_INTEGER, false).map(
|
|
153
|
+
(sourceText2) => ({
|
|
154
|
+
...sourceText2,
|
|
155
|
+
lang: "ts",
|
|
156
|
+
sourceType: "module"
|
|
157
|
+
})
|
|
158
|
+
)
|
|
159
|
+
);
|
|
160
|
+
return results;
|
|
161
|
+
}
|
|
162
|
+
export {
|
|
163
|
+
partialSourceTextLoader as default,
|
|
164
|
+
partialAstroSourceTextLoader,
|
|
165
|
+
partialSvelteSourceTextLoader,
|
|
166
|
+
partialVueSourceTextLoader
|
|
167
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { parseSync } from "oxc-parser";
|
|
2
|
+
import replaceComments from "./comments/index.mjs";
|
|
3
|
+
import partialSourceTextLoader from "./partialSourceTextLoader.mjs";
|
|
4
|
+
const getComments = (absoluteFilePath, partialSourceText, options) => {
|
|
5
|
+
const parserResult = parseSync(
|
|
6
|
+
absoluteFilePath,
|
|
7
|
+
partialSourceText.sourceText,
|
|
8
|
+
{
|
|
9
|
+
lang: partialSourceText.lang,
|
|
10
|
+
sourceType: partialSourceText.sourceType
|
|
11
|
+
}
|
|
12
|
+
);
|
|
13
|
+
if (parserResult.errors.length > 0 && options.reporter) {
|
|
14
|
+
options.reporter(`${absoluteFilePath}: failed to parse`);
|
|
15
|
+
}
|
|
16
|
+
return parserResult.comments;
|
|
17
|
+
};
|
|
18
|
+
function replaceCommentsInSourceText(absoluteFilePath, partialSourceText, options) {
|
|
19
|
+
const comments = getComments(absoluteFilePath, partialSourceText, options);
|
|
20
|
+
let sourceText = partialSourceText.sourceText;
|
|
21
|
+
for (const comment of comments) {
|
|
22
|
+
try {
|
|
23
|
+
const replacedStr = replaceComments(comment.value, comment.type, options);
|
|
24
|
+
if (replacedStr !== comment.value) {
|
|
25
|
+
const newComment = comment.type === "Line" ? `//${replacedStr}` : `/*${replacedStr}*/`;
|
|
26
|
+
sourceText = sourceText.slice(0, comment.start) + newComment + sourceText.slice(comment.end);
|
|
27
|
+
}
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (error instanceof Error && options.reporter) {
|
|
30
|
+
options.reporter(
|
|
31
|
+
`${absoluteFilePath}, char offset ${comment.start + partialSourceText.offset}: ${error.message}`
|
|
32
|
+
);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return sourceText;
|
|
39
|
+
}
|
|
40
|
+
function replaceCommentsInFile(absoluteFilePath, fileContent, options) {
|
|
41
|
+
for (const partialSourceText of partialSourceTextLoader(
|
|
42
|
+
absoluteFilePath,
|
|
43
|
+
fileContent
|
|
44
|
+
)) {
|
|
45
|
+
const newSourceText = replaceCommentsInSourceText(
|
|
46
|
+
absoluteFilePath,
|
|
47
|
+
partialSourceText,
|
|
48
|
+
options
|
|
49
|
+
);
|
|
50
|
+
if (newSourceText !== partialSourceText.sourceText) {
|
|
51
|
+
fileContent = fileContent.slice(0, partialSourceText.offset) + newSourceText + fileContent.slice(
|
|
52
|
+
partialSourceText.offset + partialSourceText.sourceText.length
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return fileContent;
|
|
57
|
+
}
|
|
58
|
+
export {
|
|
59
|
+
replaceCommentsInFile as default
|
|
60
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxlint/migrate",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Generates a `.oxlintrc.json` from a existing eslint flat config",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -57,12 +57,15 @@
|
|
|
57
57
|
"eslint-plugin-jsdoc": "^51.2.3",
|
|
58
58
|
"eslint-plugin-local": "^6.0.0",
|
|
59
59
|
"eslint-plugin-oxlint": "^1.3.0",
|
|
60
|
+
"eslint-plugin-react": "^7.37.5",
|
|
61
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
62
|
+
"eslint-plugin-react-perf": "^3.3.3",
|
|
60
63
|
"eslint-plugin-regexp": "^2.9.0",
|
|
61
64
|
"eslint-plugin-unicorn": "^59.0.1",
|
|
62
65
|
"husky": "^9.1.7",
|
|
63
66
|
"jiti": "^2.4.2",
|
|
64
67
|
"lint-staged": "^16.1.2",
|
|
65
|
-
"oxlint": "^1.
|
|
68
|
+
"oxlint": "^1.8.0",
|
|
66
69
|
"prettier": "^3.6.1",
|
|
67
70
|
"typescript": "^5.8.3",
|
|
68
71
|
"typescript-eslint": "^8.35.0",
|
|
@@ -74,7 +77,9 @@
|
|
|
74
77
|
"*": "prettier --ignore-unknown --write"
|
|
75
78
|
},
|
|
76
79
|
"dependencies": {
|
|
77
|
-
"commander": "^14.0.0"
|
|
80
|
+
"commander": "^14.0.0",
|
|
81
|
+
"oxc-parser": "^0.77.0",
|
|
82
|
+
"tinyglobby": "^0.2.14"
|
|
78
83
|
},
|
|
79
84
|
"peerDependencies": {
|
|
80
85
|
"globals": "^14.0.0 || ^15.0.0 || ^16.0.0",
|