ignore-lint-errors 0.2.0 → 0.4.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/ignore-lint-errors.js +1 -1
- package/dist/src/steps/create-options.js +1 -0
- package/dist/src/steps/ignore-errors/eslint.js +6 -10
- package/dist/src/steps/ignore-errors/index.js +1 -0
- package/dist/src/steps/ignore-errors/stylelint.js +16 -0
- package/dist/src/steps/ignore-errors/typescript.js +6 -29
- 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/stylelint.js +19 -0
- package/dist/src/steps/lint-files.js +7 -1
- package/dist/src/utils/ignore-errors/eslint.js +9 -0
- package/dist/src/utils/ignore-errors/stylelint.js +9 -0
- package/dist/src/utils/ignore-errors/typescript.js +74 -0
- package/dist/src/utils/linters/eslint.js +9 -4
- package/dist/src/utils/linters/stylelint.js +51 -0
- package/dist/src/utils/linters/typescript.js +3 -0
- package/package.json +2 -1
|
@@ -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', 'typescript'],
|
|
11
|
+
choices: ['eslint', 'stylelint', 'typescript'],
|
|
12
12
|
describe: 'Linter to run',
|
|
13
13
|
type: 'string',
|
|
14
14
|
})
|
|
@@ -9,6 +9,7 @@ function findDependencies(projectRoot) {
|
|
|
9
9
|
eslint: projectDependencies.has('eslint'),
|
|
10
10
|
glint: projectDependencies.has('@glint/core') ||
|
|
11
11
|
projectDependencies.has('@glint/ember-tsc'),
|
|
12
|
+
stylelint: projectDependencies.has('stylelint'),
|
|
12
13
|
typescript: projectDependencies.has('typescript'),
|
|
13
14
|
};
|
|
14
15
|
}
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { EOL } from 'node:os';
|
|
3
2
|
import { join } from 'node:path';
|
|
4
3
|
import { removeFiles } from '@codemod-utils/files';
|
|
4
|
+
import { ignoreErrors } from '../../utils/ignore-errors/stylelint.js';
|
|
5
5
|
import { outputFilePath, parseOutputFile } from '../../utils/linters/eslint.js';
|
|
6
6
|
export function ignoreErrorsFromEslint(options) {
|
|
7
7
|
const { projectRoot } = options;
|
|
8
8
|
const outputFile = readFileSync(join(projectRoot, outputFilePath), 'utf8');
|
|
9
|
-
const filesWithErrors = parseOutputFile(outputFile);
|
|
10
|
-
filesWithErrors.forEach(({
|
|
11
|
-
const file = readFileSync(
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const ignoreDirective = `// @ts-expect-error: ${message}`;
|
|
15
|
-
lines.splice(line - 1, 0, ignoreDirective);
|
|
16
|
-
});
|
|
17
|
-
writeFileSync(absoluteFilePath, lines.join(EOL), 'utf8');
|
|
9
|
+
const filesWithErrors = parseOutputFile(outputFile, projectRoot);
|
|
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');
|
|
18
14
|
});
|
|
19
15
|
removeFiles([outputFilePath], { projectRoot });
|
|
20
16
|
}
|
|
@@ -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/stylelint.js';
|
|
5
|
+
import { outputFilePath, parseOutputFile, } from '../../utils/linters/stylelint.js';
|
|
6
|
+
export function ignoreErrorsFromStylelint(options) {
|
|
7
|
+
const { projectRoot } = options;
|
|
8
|
+
const outputFile = readFileSync(join(projectRoot, outputFilePath), 'utf8');
|
|
9
|
+
const filesWithErrors = parseOutputFile(outputFile, projectRoot);
|
|
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,42 +1,19 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { EOL } from 'node:os';
|
|
3
2
|
import { join } from 'node:path';
|
|
4
|
-
import { findTemplateTags } from '@codemod-utils/ast-template-tag';
|
|
5
3
|
import { removeFiles } from '@codemod-utils/files';
|
|
4
|
+
import { ignoreErrors, ignoreErrorsFallback, isParseable, } from '../../utils/ignore-errors/typescript.js';
|
|
6
5
|
import { outputFilePath, parseOutputFile, } from '../../utils/linters/typescript.js';
|
|
7
|
-
function findLinesWithTemplate(file) {
|
|
8
|
-
function getLOC(file) {
|
|
9
|
-
const matches = file.match(/\r?\n/g);
|
|
10
|
-
return (matches ?? []).length;
|
|
11
|
-
}
|
|
12
|
-
const templateTags = findTemplateTags(file);
|
|
13
|
-
const linesWithTemplate = [];
|
|
14
|
-
templateTags.forEach((templateTag) => {
|
|
15
|
-
const { range } = templateTag;
|
|
16
|
-
const lineStart = getLOC(file.substring(0, range.startChar)) + 1;
|
|
17
|
-
const lineEnd = getLOC(file.substring(0, range.endChar)) + 1;
|
|
18
|
-
linesWithTemplate.push([lineStart, lineEnd]);
|
|
19
|
-
});
|
|
20
|
-
return linesWithTemplate;
|
|
21
|
-
}
|
|
22
6
|
export function ignoreErrorsFromTypescript(options) {
|
|
23
7
|
const { projectRoot } = options;
|
|
24
8
|
const outputFile = readFileSync(join(projectRoot, outputFilePath), 'utf8');
|
|
25
9
|
const filesWithErrors = parseOutputFile(outputFile);
|
|
26
10
|
filesWithErrors.forEach(({ filePath, lintErrors }) => {
|
|
27
11
|
const file = readFileSync(join(projectRoot, filePath), 'utf8');
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
});
|
|
34
|
-
const ignoreDirective = erroredInTemplate
|
|
35
|
-
? `{{! @glint-expect-error: ${message} }}`
|
|
36
|
-
: `// @ts-expect-error: ${message}`;
|
|
37
|
-
lines.splice(line - 1, 0, ignoreDirective);
|
|
38
|
-
});
|
|
39
|
-
writeFileSync(join(projectRoot, filePath), lines.join(EOL), 'utf8');
|
|
12
|
+
let newFile = ignoreErrors(file, lintErrors);
|
|
13
|
+
if (!isParseable(newFile)) {
|
|
14
|
+
newFile = ignoreErrorsFallback(file, lintErrors);
|
|
15
|
+
}
|
|
16
|
+
writeFileSync(join(projectRoot, filePath), newFile, 'utf8');
|
|
40
17
|
});
|
|
41
18
|
removeFiles([outputFilePath], { projectRoot });
|
|
42
19
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ignoreErrorsFromEslint, ignoreErrorsFromTypescript, } from './ignore-errors/index.js';
|
|
1
|
+
import { ignoreErrorsFromEslint, 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 'stylelint': {
|
|
12
|
+
if (dependencies.stylelint) {
|
|
13
|
+
ignoreErrorsFromStylelint(options);
|
|
14
|
+
}
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
11
17
|
case 'typescript': {
|
|
12
18
|
if (dependencies.typescript) {
|
|
13
19
|
ignoreErrorsFromTypescript(options);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { outputFilePath } from '../../utils/linters/stylelint.js';
|
|
3
|
+
export function runStylelint(options) {
|
|
4
|
+
const { projectRoot } = options;
|
|
5
|
+
const command = [
|
|
6
|
+
'./node_modules/.bin/stylelint "**/*.css"',
|
|
7
|
+
'--allow-empty-input',
|
|
8
|
+
'--formatter json',
|
|
9
|
+
`--output-file ${outputFilePath}`,
|
|
10
|
+
'--quiet',
|
|
11
|
+
'2>/dev/null', // Suppress output to process.stderr
|
|
12
|
+
].join(' ');
|
|
13
|
+
try {
|
|
14
|
+
execSync(command, { cwd: projectRoot });
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Do nothing
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { runEslint, runTypescript } from './lint-files/index.js';
|
|
3
|
+
import { runEslint, 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 'stylelint': {
|
|
17
|
+
if (dependencies.stylelint) {
|
|
18
|
+
runStylelint(options);
|
|
19
|
+
}
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
16
22
|
case 'typescript': {
|
|
17
23
|
if (dependencies.typescript) {
|
|
18
24
|
runTypescript(options);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EOL } from 'node:os';
|
|
2
|
+
export function ignoreErrors(file, lintErrors) {
|
|
3
|
+
const lines = file.split(EOL);
|
|
4
|
+
lintErrors.forEach(({ line, message }) => {
|
|
5
|
+
const ignoreDirective = `// eslint-disable-next-line ${message}`;
|
|
6
|
+
lines.splice(line - 1, 0, ignoreDirective);
|
|
7
|
+
});
|
|
8
|
+
return lines.join(EOL);
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EOL } from 'node:os';
|
|
2
|
+
export function ignoreErrors(file, lintErrors) {
|
|
3
|
+
const lines = file.split(EOL);
|
|
4
|
+
lintErrors.forEach(({ line, message }) => {
|
|
5
|
+
const ignoreDirective = `/* stylelint-disable-next-line ${message} */`;
|
|
6
|
+
lines.splice(line - 1, 0, ignoreDirective);
|
|
7
|
+
});
|
|
8
|
+
return lines.join(EOL);
|
|
9
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { EOL } from 'node:os';
|
|
2
|
+
import { AST } from '@codemod-utils/ast-template';
|
|
3
|
+
import { findTemplateTags, updateTemplates, } from '@codemod-utils/ast-template-tag';
|
|
4
|
+
export function findLinesWithTemplate(file) {
|
|
5
|
+
function getLOC(file) {
|
|
6
|
+
const matches = file.match(/\r?\n/g);
|
|
7
|
+
return (matches ?? []).length;
|
|
8
|
+
}
|
|
9
|
+
const templateTags = findTemplateTags(file);
|
|
10
|
+
const linesWithTemplate = [];
|
|
11
|
+
templateTags.forEach((templateTag) => {
|
|
12
|
+
const { range } = templateTag;
|
|
13
|
+
const lineStart = getLOC(file.substring(0, range.startChar)) + 1;
|
|
14
|
+
const lineEnd = getLOC(file.substring(0, range.endChar)) + 1;
|
|
15
|
+
linesWithTemplate.push([lineStart, lineEnd]);
|
|
16
|
+
});
|
|
17
|
+
return linesWithTemplate;
|
|
18
|
+
}
|
|
19
|
+
export function ignoreErrors(file, lintErrors) {
|
|
20
|
+
const linesWithTemplate = findLinesWithTemplate(file);
|
|
21
|
+
const lines = file.split(EOL);
|
|
22
|
+
lintErrors.forEach(({ line, message }) => {
|
|
23
|
+
const erroredInTemplate = linesWithTemplate.some(([lineStart, lineEnd]) => {
|
|
24
|
+
return lineStart <= line && line <= lineEnd;
|
|
25
|
+
});
|
|
26
|
+
const ignoreDirective = erroredInTemplate
|
|
27
|
+
? `{{! @glint-expect-error: ${message} }}`
|
|
28
|
+
: `// @ts-expect-error: ${message}`;
|
|
29
|
+
lines.splice(line - 1, 0, ignoreDirective);
|
|
30
|
+
});
|
|
31
|
+
return lines.join(EOL);
|
|
32
|
+
}
|
|
33
|
+
// For fallback, ignore type checks in templates
|
|
34
|
+
export function ignoreErrorsFallback(file, lintErrors) {
|
|
35
|
+
const linesWithTemplate = findLinesWithTemplate(file);
|
|
36
|
+
const lines = file.split(EOL);
|
|
37
|
+
let hasErrorInTemplate = false;
|
|
38
|
+
lintErrors.forEach(({ line, message }) => {
|
|
39
|
+
const erroredInTemplate = linesWithTemplate.some(([lineStart, lineEnd]) => {
|
|
40
|
+
return lineStart <= line && line <= lineEnd;
|
|
41
|
+
});
|
|
42
|
+
if (erroredInTemplate) {
|
|
43
|
+
hasErrorInTemplate = true;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const ignoreDirective = `// @ts-expect-error: ${message}`;
|
|
47
|
+
lines.splice(line - 1, 0, ignoreDirective);
|
|
48
|
+
});
|
|
49
|
+
let newFile = lines.join(EOL);
|
|
50
|
+
if (hasErrorInTemplate) {
|
|
51
|
+
newFile = updateTemplates(newFile, (code) => {
|
|
52
|
+
const ignoreDirective = '{{! @glint-nocheck }}';
|
|
53
|
+
return [ignoreDirective, code].join(EOL);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return newFile;
|
|
57
|
+
}
|
|
58
|
+
export function isParseable(file) {
|
|
59
|
+
const traverse = AST.traverse();
|
|
60
|
+
let isParseable = true;
|
|
61
|
+
function parseTemplate(template) {
|
|
62
|
+
try {
|
|
63
|
+
traverse(template);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
isParseable = false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const templateTags = findTemplateTags(file);
|
|
70
|
+
templateTags.forEach((templateTag) => {
|
|
71
|
+
parseTemplate(templateTag.contents);
|
|
72
|
+
});
|
|
73
|
+
return isParseable;
|
|
74
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { relative, sep } from 'node:path';
|
|
1
2
|
export const outputFilePath = '.ignore-lint-errors/eslint.txt';
|
|
2
|
-
export function parseOutputFile(file) {
|
|
3
|
+
export function parseOutputFile(file, projectRoot) {
|
|
3
4
|
const filePathToData = new Map();
|
|
4
5
|
const records = JSON.parse(file);
|
|
5
6
|
records.forEach((record) => {
|
|
@@ -13,10 +14,11 @@ export function parseOutputFile(file) {
|
|
|
13
14
|
data.set(line, [ruleId]);
|
|
14
15
|
}
|
|
15
16
|
});
|
|
16
|
-
|
|
17
|
+
const filePath = relative(projectRoot, absoluteFilePath).replaceAll(sep, '/');
|
|
18
|
+
filePathToData.set(filePath, data);
|
|
17
19
|
});
|
|
18
20
|
const filesWithErrors = [];
|
|
19
|
-
filePathToData.forEach((data,
|
|
21
|
+
filePathToData.forEach((data, filePath) => {
|
|
20
22
|
const lintErrors = [];
|
|
21
23
|
data.forEach((allMessages, line) => {
|
|
22
24
|
const ruleIds = Array.from(new Set(allMessages.sort()));
|
|
@@ -25,6 +27,9 @@ export function parseOutputFile(file) {
|
|
|
25
27
|
message: ruleIds.join(', '),
|
|
26
28
|
});
|
|
27
29
|
});
|
|
30
|
+
if (lintErrors.length === 0) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
28
33
|
lintErrors.sort((a, b) => {
|
|
29
34
|
if (a.line < b.line) {
|
|
30
35
|
return 1;
|
|
@@ -35,7 +40,7 @@ export function parseOutputFile(file) {
|
|
|
35
40
|
return 0;
|
|
36
41
|
});
|
|
37
42
|
filesWithErrors.push({
|
|
38
|
-
|
|
43
|
+
filePath,
|
|
39
44
|
lintErrors,
|
|
40
45
|
});
|
|
41
46
|
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { relative, sep } from 'node:path';
|
|
2
|
+
export const outputFilePath = '.ignore-lint-errors/stylelint.txt';
|
|
3
|
+
export function parseOutputFile(file, projectRoot) {
|
|
4
|
+
const filePathToData = new Map();
|
|
5
|
+
const records = JSON.parse(file);
|
|
6
|
+
records.forEach((record) => {
|
|
7
|
+
const { errored, source: absoluteFilePath, warnings } = record;
|
|
8
|
+
if (!errored) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const data = new Map();
|
|
12
|
+
warnings.forEach(({ line, rule }) => {
|
|
13
|
+
if (data.has(line)) {
|
|
14
|
+
data.get(line).push(rule);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
data.set(line, [rule]);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const filePath = relative(projectRoot, absoluteFilePath).replaceAll(sep, '/');
|
|
21
|
+
filePathToData.set(filePath, data);
|
|
22
|
+
});
|
|
23
|
+
const filesWithErrors = [];
|
|
24
|
+
filePathToData.forEach((data, filePath) => {
|
|
25
|
+
const lintErrors = [];
|
|
26
|
+
data.forEach((allMessages, line) => {
|
|
27
|
+
const ruleIds = Array.from(new Set(allMessages.sort()));
|
|
28
|
+
lintErrors.push({
|
|
29
|
+
line,
|
|
30
|
+
message: ruleIds.join(', '),
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
if (lintErrors.length === 0) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
lintErrors.sort((a, b) => {
|
|
37
|
+
if (a.line < b.line) {
|
|
38
|
+
return 1;
|
|
39
|
+
}
|
|
40
|
+
if (b.line < a.line) {
|
|
41
|
+
return -1;
|
|
42
|
+
}
|
|
43
|
+
return 0;
|
|
44
|
+
});
|
|
45
|
+
filesWithErrors.push({
|
|
46
|
+
filePath,
|
|
47
|
+
lintErrors,
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
return filesWithErrors;
|
|
51
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ignore-lint-errors",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Codemod to add ignore directives",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"codemod",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
+
"@codemod-utils/ast-template": "^3.0.1",
|
|
20
21
|
"@codemod-utils/ast-template-tag": "^2.1.0",
|
|
21
22
|
"@codemod-utils/files": "^4.0.1",
|
|
22
23
|
"@codemod-utils/package-json": "^4.0.1",
|