ignore-lint-errors 1.0.0 → 1.1.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 +15 -1
- package/dist/bin/ignore-lint-errors.js +1 -1
- package/dist/src/steps/create-options.js +1 -0
- package/dist/src/steps/ignore-errors/index.js +1 -0
- package/dist/src/steps/ignore-errors/oxlint.js +16 -0
- package/dist/src/steps/ignore-errors.js +7 -1
- package/dist/src/steps/lint-files/index.js +1 -0
- package/dist/src/steps/lint-files/oxlint.js +25 -0
- package/dist/src/steps/lint-files.js +7 -1
- package/dist/src/utils/ignore-errors/oxlint.js +23 -0
- package/dist/src/utils/linters/oxlint.js +51 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,9 @@ You must pass `--linter` to indicate which linter to run.
|
|
|
46
46
|
# Run eslint
|
|
47
47
|
pnpx ignore-lint-errors --linter eslint
|
|
48
48
|
|
|
49
|
+
# Run oxlint
|
|
50
|
+
pnpx ignore-lint-errors --linter oxlint
|
|
51
|
+
|
|
49
52
|
# Run stylelint
|
|
50
53
|
pnpx ignore-lint-errors --linter stylelint
|
|
51
54
|
|
|
@@ -82,6 +85,17 @@ pnpx ignore-lint-errors --linter eslint --src app tests
|
|
|
82
85
|
pnpx ignore-lint-errors --linter eslint --src app/{components,templates}/**/*.gts
|
|
83
86
|
```
|
|
84
87
|
|
|
88
|
+
```sh
|
|
89
|
+
# oxlint supports files
|
|
90
|
+
pnpx ignore-lint-errors --linter oxlint --src app/components/example-1.gts app/templates/example-2.gts
|
|
91
|
+
|
|
92
|
+
# oxlint supports directories
|
|
93
|
+
pnpx ignore-lint-errors --linter oxlint --src app tests
|
|
94
|
+
|
|
95
|
+
# oxlint supports globs
|
|
96
|
+
pnpx ignore-lint-errors --linter oxlint --src app/{components,templates}/**/*.gts
|
|
97
|
+
```
|
|
98
|
+
|
|
85
99
|
```sh
|
|
86
100
|
# stylelint supports files
|
|
87
101
|
pnpx ignore-lint-errors --linter stylelint --src app/components/example-1.module.css app/templates/example-2.module.css
|
|
@@ -113,7 +127,7 @@ pnpm build
|
|
|
113
127
|
## Compatibility
|
|
114
128
|
|
|
115
129
|
- Node.js v22 or above
|
|
116
|
-
- Tested against `eslint@v9`, `glint@v2`, `stylelint@v17`, `typescript@v5`
|
|
130
|
+
- Tested against `eslint@v9`, `glint@v2`, `oxlint@v1`, `stylelint@v17`, `typescript@v5`
|
|
117
131
|
|
|
118
132
|
|
|
119
133
|
## Contributing
|
|
@@ -8,7 +8,7 @@ process.title = 'ignore-lint-errors';
|
|
|
8
8
|
// Set codemod options
|
|
9
9
|
const argv = yargs(hideBin(process.argv))
|
|
10
10
|
.option('linter', {
|
|
11
|
-
choices: ['eslint', 'stylelint', 'typescript'],
|
|
11
|
+
choices: ['eslint', 'oxlint', 'stylelint', 'typescript'],
|
|
12
12
|
describe: 'Linter to run',
|
|
13
13
|
type: 'string',
|
|
14
14
|
})
|
|
@@ -8,6 +8,7 @@ function findDependencies(projectRoot) {
|
|
|
8
8
|
return {
|
|
9
9
|
eslint: projectDependencies.has('eslint'),
|
|
10
10
|
glint: projectDependencies.has('@glint/ember-tsc'),
|
|
11
|
+
oxlint: projectDependencies.has('oxlint'),
|
|
11
12
|
stylelint: projectDependencies.has('stylelint'),
|
|
12
13
|
typescript: projectDependencies.has('typescript'),
|
|
13
14
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { removeFiles } from '@codemod-utils/files';
|
|
4
|
+
import { ignoreErrors } from '../../utils/ignore-errors/oxlint.js';
|
|
5
|
+
import { outputFilePath, parseOutputFile } from '../../utils/linters/oxlint.js';
|
|
6
|
+
export function ignoreErrorsFromOxlint(options) {
|
|
7
|
+
const { projectRoot } = options;
|
|
8
|
+
const outputFile = readFileSync(join(projectRoot, outputFilePath), 'utf8');
|
|
9
|
+
const filesWithErrors = parseOutputFile(outputFile);
|
|
10
|
+
filesWithErrors.forEach(({ filePath, lintErrors }) => {
|
|
11
|
+
const file = readFileSync(join(projectRoot, filePath), 'utf8');
|
|
12
|
+
const newFile = ignoreErrors(file, lintErrors);
|
|
13
|
+
writeFileSync(join(projectRoot, filePath), newFile, 'utf8');
|
|
14
|
+
});
|
|
15
|
+
removeFiles([outputFilePath], { projectRoot });
|
|
16
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ignoreErrorsFromEslint, ignoreErrorsFromStylelint, ignoreErrorsFromTypescript, } from './ignore-errors/index.js';
|
|
1
|
+
import { ignoreErrorsFromEslint, ignoreErrorsFromOxlint, ignoreErrorsFromStylelint, ignoreErrorsFromTypescript, } from './ignore-errors/index.js';
|
|
2
2
|
export function ignoreErrors(options) {
|
|
3
3
|
const { dependencies, linter } = options;
|
|
4
4
|
switch (linter) {
|
|
@@ -8,6 +8,12 @@ export function ignoreErrors(options) {
|
|
|
8
8
|
}
|
|
9
9
|
break;
|
|
10
10
|
}
|
|
11
|
+
case 'oxlint': {
|
|
12
|
+
if (dependencies.oxlint) {
|
|
13
|
+
ignoreErrorsFromOxlint(options);
|
|
14
|
+
}
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
11
17
|
case 'stylelint': {
|
|
12
18
|
if (dependencies.stylelint) {
|
|
13
19
|
ignoreErrorsFromStylelint(options);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { outputFilePath } from '../../utils/linters/oxlint.js';
|
|
3
|
+
function getSrc(options) {
|
|
4
|
+
const { src } = options;
|
|
5
|
+
if (src === undefined) {
|
|
6
|
+
return '';
|
|
7
|
+
}
|
|
8
|
+
return src.map((token) => `"${token}"`).join(' ');
|
|
9
|
+
}
|
|
10
|
+
export function runOxlint(options) {
|
|
11
|
+
const { projectRoot } = options;
|
|
12
|
+
const command = [
|
|
13
|
+
'./node_modules/.bin/oxlint',
|
|
14
|
+
getSrc(options),
|
|
15
|
+
'--format json',
|
|
16
|
+
'--quiet',
|
|
17
|
+
`> ${outputFilePath}`,
|
|
18
|
+
].join(' ');
|
|
19
|
+
try {
|
|
20
|
+
execSync(command, { cwd: projectRoot });
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Do nothing
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { runEslint, runStylelint, runTypescript } from './lint-files/index.js';
|
|
3
|
+
import { runEslint, runOxlint, runStylelint, runTypescript, } from './lint-files/index.js';
|
|
4
4
|
export function lintFiles(options) {
|
|
5
5
|
const { dependencies, linter, projectRoot } = options;
|
|
6
6
|
if (!existsSync(join(projectRoot, '.ignore-lint-errors'))) {
|
|
@@ -13,6 +13,12 @@ export function lintFiles(options) {
|
|
|
13
13
|
}
|
|
14
14
|
break;
|
|
15
15
|
}
|
|
16
|
+
case 'oxlint': {
|
|
17
|
+
if (dependencies.oxlint) {
|
|
18
|
+
runOxlint(options);
|
|
19
|
+
}
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
16
22
|
case 'stylelint': {
|
|
17
23
|
if (dependencies.stylelint) {
|
|
18
24
|
runStylelint(options);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { EOL } from 'node:os';
|
|
2
|
+
import { getIgnoredRules } from './shared/index.js';
|
|
3
|
+
export function ignoreErrors(file, lintErrors) {
|
|
4
|
+
const lines = file.split(EOL);
|
|
5
|
+
const ignoreDirective = 'oxlint-disable-next-line';
|
|
6
|
+
lintErrors.forEach(({ line, message }) => {
|
|
7
|
+
const currentIndex = line - 1;
|
|
8
|
+
const previousIndex = Math.max(currentIndex - 1, 0);
|
|
9
|
+
const ignoredRules = getIgnoredRules(lines[previousIndex], {
|
|
10
|
+
ignoreDirective,
|
|
11
|
+
});
|
|
12
|
+
if (ignoredRules.length === 0) {
|
|
13
|
+
lines.splice(currentIndex, 0, `// ${ignoreDirective} ${message}`);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
const newMessage = [...ignoredRules, ...message.split(', ')]
|
|
17
|
+
.sort()
|
|
18
|
+
.join(', ');
|
|
19
|
+
lines.splice(previousIndex, 1, `// ${ignoreDirective} ${newMessage}`);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
return lines.join(EOL);
|
|
23
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { getFilesWithErrors } from './shared/index.js';
|
|
2
|
+
export const outputFilePath = '.ignore-lint-errors/oxlint.txt';
|
|
3
|
+
function extractRuleId(code) {
|
|
4
|
+
const matches = code.match(/^.+\((.+)\)$/);
|
|
5
|
+
if (matches === null) {
|
|
6
|
+
throw new Error(`Unable to extract rule ID (code: ${code})`);
|
|
7
|
+
}
|
|
8
|
+
return matches[1];
|
|
9
|
+
}
|
|
10
|
+
function normalize(file) {
|
|
11
|
+
const filePathToData = new Map();
|
|
12
|
+
const { diagnostics } = JSON.parse(file);
|
|
13
|
+
const filePathToMessages = new Map();
|
|
14
|
+
diagnostics.forEach((diagnostic) => {
|
|
15
|
+
const { code, filename: filePath, labels } = diagnostic;
|
|
16
|
+
const line = labels[0].span.line;
|
|
17
|
+
const ruleId = extractRuleId(code);
|
|
18
|
+
const message = {
|
|
19
|
+
line,
|
|
20
|
+
ruleId,
|
|
21
|
+
};
|
|
22
|
+
if (filePathToMessages.has(filePath)) {
|
|
23
|
+
filePathToMessages.get(filePath).push(message);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
filePathToMessages.set(filePath, [message]);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
filePathToMessages.forEach((messages, filePath) => {
|
|
30
|
+
const data = new Map();
|
|
31
|
+
const lineToRules = new Map();
|
|
32
|
+
messages.forEach(({ line, ruleId }) => {
|
|
33
|
+
if (lineToRules.has(line)) {
|
|
34
|
+
lineToRules.get(line).push(ruleId);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
lineToRules.set(line, [ruleId]);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
lineToRules.forEach((rules, line) => {
|
|
41
|
+
const message = Array.from(new Set(rules.sort())).join(', ');
|
|
42
|
+
data.set(line, message);
|
|
43
|
+
});
|
|
44
|
+
filePathToData.set(filePath, data);
|
|
45
|
+
});
|
|
46
|
+
return filePathToData;
|
|
47
|
+
}
|
|
48
|
+
export function parseOutputFile(file) {
|
|
49
|
+
const filePathToData = normalize(file);
|
|
50
|
+
return getFilesWithErrors(filePathToData);
|
|
51
|
+
}
|