@utoo/lint 0.3.7 → 0.3.9
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 -0
- package/index.cjs +9 -28
- package/index.js +9 -28
- package/lib/stylish-formatter.cjs +79 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -244,6 +244,20 @@ const results = await eslint.lintFiles(["src"]);
|
|
|
244
244
|
await ESLint.outputFixes(results);
|
|
245
245
|
```
|
|
246
246
|
|
|
247
|
+
`await eslint.loadFormatter()` and `cliEngine.getFormatter()` default to an
|
|
248
|
+
ESLint-style `stylish` report: aligned columns, blank lines between files,
|
|
249
|
+
diagnostics sorted by line and column, and a summary of fixable errors and
|
|
250
|
+
warnings. Rule messages (including punctuation), result arrays, and exit codes
|
|
251
|
+
are unchanged. Only actual autofixes count toward the `--fix` hint, not editor
|
|
252
|
+
suggestions; missing JSX keys still need a manually chosen stable, unique key.
|
|
253
|
+
|
|
254
|
+
The stylish formatter detects color support on stdout. Pass `color: true` or
|
|
255
|
+
`color: false` to the `ESLint` or `CLIEngine` constructor to override detection.
|
|
256
|
+
Otherwise, `NO_COLOR` or `NODE_DISABLE_COLORS` disables color; `FORCE_COLOR`
|
|
257
|
+
forces it (`0` disables), followed by `CLICOLOR_FORCE` and stdout TTY detection
|
|
258
|
+
(`TERM=dumb` disables automatic color). Constructor `env` overrides also apply.
|
|
259
|
+
JSON, JSON-with-metadata, compact, unix, and native CLI text formats are unchanged.
|
|
260
|
+
|
|
247
261
|
Raw reports include active diagnostics, suppressed diagnostics, fixed outputs,
|
|
248
262
|
and an exit code. The compatibility layer also exports `Linter`, `CLIEngine`,
|
|
249
263
|
`RuleTester`, and `SourceCode` APIs.
|
package/index.cjs
CHANGED
|
@@ -6,6 +6,7 @@ const { dirname, extname, isAbsolute, join, relative, resolve: resolvePath } = r
|
|
|
6
6
|
|
|
7
7
|
const { platformPackageName, resolveBinary } = require("./lib/binary.cjs");
|
|
8
8
|
const { createLegacyConfigResolver } = require("./lib/legacy-config.cjs");
|
|
9
|
+
const { formatESLintResults } = require("./lib/stylish-formatter.cjs");
|
|
9
10
|
const {
|
|
10
11
|
findConfigPath: findConfigPathFromDirectory,
|
|
11
12
|
readConfig
|
|
@@ -396,6 +397,10 @@ const BUILTIN_RULE_IDS = [
|
|
|
396
397
|
"react/void-dom-elements-no-children",
|
|
397
398
|
"react-hooks/exhaustive-deps",
|
|
398
399
|
"react-hooks/rules-of-hooks",
|
|
400
|
+
"react-hooks/use-memo",
|
|
401
|
+
"react-hooks/void-use-memo",
|
|
402
|
+
"react-hooks/set-state-in-render",
|
|
403
|
+
"react-hooks/purity",
|
|
399
404
|
"unused-imports/no-unused-imports",
|
|
400
405
|
"@typescript-eslint/adjacent-overload-signatures",
|
|
401
406
|
"@typescript-eslint/array-type",
|
|
@@ -626,7 +631,7 @@ class UtooLint {
|
|
|
626
631
|
format(results) {
|
|
627
632
|
return formatResultsByName(results, name, {
|
|
628
633
|
rulesMeta: (results) => eslint.getRulesMetaForResults(results)
|
|
629
|
-
});
|
|
634
|
+
}, eslint.options);
|
|
630
635
|
}
|
|
631
636
|
};
|
|
632
637
|
}
|
|
@@ -704,7 +709,7 @@ class CLIEngine {
|
|
|
704
709
|
|
|
705
710
|
getFormatter(name = "stylish") {
|
|
706
711
|
return (results) => {
|
|
707
|
-
return formatResultsByName(results, name);
|
|
712
|
+
return formatResultsByName(results, name, {}, this.options);
|
|
708
713
|
};
|
|
709
714
|
}
|
|
710
715
|
|
|
@@ -5004,31 +5009,7 @@ function maybeFilterQuietResults(results, options = {}) {
|
|
|
5004
5009
|
return results;
|
|
5005
5010
|
}
|
|
5006
5011
|
|
|
5007
|
-
function
|
|
5008
|
-
const lines = [];
|
|
5009
|
-
let errorCount = 0;
|
|
5010
|
-
let warningCount = 0;
|
|
5011
|
-
|
|
5012
|
-
for (const result of results) {
|
|
5013
|
-
if (result.messages.length === 0) continue;
|
|
5014
|
-
lines.push(result.filePath);
|
|
5015
|
-
for (const message of result.messages) {
|
|
5016
|
-
const severity = message.severity === 2 ? "error" : "warning";
|
|
5017
|
-
lines.push(` ${message.line}:${message.column} ${severity} ${message.message} ${message.ruleId}`);
|
|
5018
|
-
}
|
|
5019
|
-
errorCount += result.errorCount;
|
|
5020
|
-
warningCount += result.warningCount;
|
|
5021
|
-
}
|
|
5022
|
-
|
|
5023
|
-
if (errorCount || warningCount) {
|
|
5024
|
-
lines.push("");
|
|
5025
|
-
lines.push(`x ${errorCount + warningCount} problem${errorCount + warningCount === 1 ? "" : "s"} (${errorCount} error${errorCount === 1 ? "" : "s"}, ${warningCount} warning${warningCount === 1 ? "" : "s"})`);
|
|
5026
|
-
}
|
|
5027
|
-
|
|
5028
|
-
return lines.join("\n");
|
|
5029
|
-
}
|
|
5030
|
-
|
|
5031
|
-
function formatResultsByName(input, name = "stylish", metadata = {}) {
|
|
5012
|
+
function formatResultsByName(input, name = "stylish", metadata = {}, options = {}) {
|
|
5032
5013
|
const results = formatterResults(input);
|
|
5033
5014
|
if (name === "json") {
|
|
5034
5015
|
return JSON.stringify(input);
|
|
@@ -5047,7 +5028,7 @@ function formatResultsByName(input, name = "stylish", metadata = {}) {
|
|
|
5047
5028
|
if (name === "unix") {
|
|
5048
5029
|
return formatUnixResults(results);
|
|
5049
5030
|
}
|
|
5050
|
-
return formatESLintResults(results);
|
|
5031
|
+
return formatESLintResults(results, options);
|
|
5051
5032
|
}
|
|
5052
5033
|
|
|
5053
5034
|
function formatterResults(input) {
|
package/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
|
|
8
8
|
import { resolveBinary } from "./lib/binary.js";
|
|
9
9
|
import { createLegacyConfigResolver } from "./lib/legacy-config.cjs";
|
|
10
|
+
import { formatESLintResults } from "./lib/stylish-formatter.cjs";
|
|
10
11
|
import {
|
|
11
12
|
findConfigPath as findConfigPathFromDirectory,
|
|
12
13
|
readConfig
|
|
@@ -399,6 +400,10 @@ const BUILTIN_RULE_IDS = [
|
|
|
399
400
|
"react/void-dom-elements-no-children",
|
|
400
401
|
"react-hooks/exhaustive-deps",
|
|
401
402
|
"react-hooks/rules-of-hooks",
|
|
403
|
+
"react-hooks/use-memo",
|
|
404
|
+
"react-hooks/void-use-memo",
|
|
405
|
+
"react-hooks/set-state-in-render",
|
|
406
|
+
"react-hooks/purity",
|
|
402
407
|
"unused-imports/no-unused-imports",
|
|
403
408
|
"@typescript-eslint/adjacent-overload-signatures",
|
|
404
409
|
"@typescript-eslint/array-type",
|
|
@@ -629,7 +634,7 @@ export class UtooLint {
|
|
|
629
634
|
format(results) {
|
|
630
635
|
return formatResultsByName(results, name, {
|
|
631
636
|
rulesMeta: (results) => eslint.getRulesMetaForResults(results)
|
|
632
|
-
});
|
|
637
|
+
}, eslint.options);
|
|
633
638
|
}
|
|
634
639
|
};
|
|
635
640
|
}
|
|
@@ -2603,7 +2608,7 @@ export class CLIEngine {
|
|
|
2603
2608
|
|
|
2604
2609
|
getFormatter(name = "stylish") {
|
|
2605
2610
|
return (results) => {
|
|
2606
|
-
return formatResultsByName(results, name);
|
|
2611
|
+
return formatResultsByName(results, name, {}, this.options);
|
|
2607
2612
|
};
|
|
2608
2613
|
}
|
|
2609
2614
|
|
|
@@ -5007,31 +5012,7 @@ function maybeFilterQuietResults(results, options = {}) {
|
|
|
5007
5012
|
return results;
|
|
5008
5013
|
}
|
|
5009
5014
|
|
|
5010
|
-
function
|
|
5011
|
-
const lines = [];
|
|
5012
|
-
let errorCount = 0;
|
|
5013
|
-
let warningCount = 0;
|
|
5014
|
-
|
|
5015
|
-
for (const result of results) {
|
|
5016
|
-
if (result.messages.length === 0) continue;
|
|
5017
|
-
lines.push(result.filePath);
|
|
5018
|
-
for (const message of result.messages) {
|
|
5019
|
-
const severity = message.severity === 2 ? "error" : "warning";
|
|
5020
|
-
lines.push(` ${message.line}:${message.column} ${severity} ${message.message} ${message.ruleId}`);
|
|
5021
|
-
}
|
|
5022
|
-
errorCount += result.errorCount;
|
|
5023
|
-
warningCount += result.warningCount;
|
|
5024
|
-
}
|
|
5025
|
-
|
|
5026
|
-
if (errorCount || warningCount) {
|
|
5027
|
-
lines.push("");
|
|
5028
|
-
lines.push(`x ${errorCount + warningCount} problem${errorCount + warningCount === 1 ? "" : "s"} (${errorCount} error${errorCount === 1 ? "" : "s"}, ${warningCount} warning${warningCount === 1 ? "" : "s"})`);
|
|
5029
|
-
}
|
|
5030
|
-
|
|
5031
|
-
return lines.join("\n");
|
|
5032
|
-
}
|
|
5033
|
-
|
|
5034
|
-
function formatResultsByName(input, name = "stylish", metadata = {}) {
|
|
5015
|
+
function formatResultsByName(input, name = "stylish", metadata = {}, options = {}) {
|
|
5035
5016
|
const results = formatterResults(input);
|
|
5036
5017
|
if (name === "json") {
|
|
5037
5018
|
return JSON.stringify(input);
|
|
@@ -5050,7 +5031,7 @@ function formatResultsByName(input, name = "stylish", metadata = {}) {
|
|
|
5050
5031
|
if (name === "unix") {
|
|
5051
5032
|
return formatUnixResults(results);
|
|
5052
5033
|
}
|
|
5053
|
-
return formatESLintResults(results);
|
|
5034
|
+
return formatESLintResults(results, options);
|
|
5054
5035
|
}
|
|
5055
5036
|
|
|
5056
5037
|
function formatterResults(input) {
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const { stripVTControlCharacters } = require("node:util");
|
|
2
|
+
|
|
3
|
+
function formatESLintResults(results, options = {}) {
|
|
4
|
+
const color = shouldUseColor(options);
|
|
5
|
+
const paint = (text, open, close) => color ? `\u001b[${open}m${text}\u001b[${close}m` : text;
|
|
6
|
+
const lines = [""];
|
|
7
|
+
let errorCount = 0;
|
|
8
|
+
let warningCount = 0;
|
|
9
|
+
let fixableErrorCount = 0;
|
|
10
|
+
let fixableWarningCount = 0;
|
|
11
|
+
|
|
12
|
+
for (const result of results) {
|
|
13
|
+
if (result.messages.length === 0) continue;
|
|
14
|
+
lines.push(paint(result.filePath, 4, 24));
|
|
15
|
+
// Sort a copy: formatting must not reorder the caller's results or JSON output.
|
|
16
|
+
const messages = [...result.messages].sort((left, right) =>
|
|
17
|
+
(left.line ?? 0) - (right.line ?? 0) || (left.column ?? 0) - (right.column ?? 0)
|
|
18
|
+
);
|
|
19
|
+
const rows = messages.map((message) => [
|
|
20
|
+
String(message.line || 0),
|
|
21
|
+
String(message.column || 0),
|
|
22
|
+
message.fatal || message.severity === 2 ? "error" : "warning",
|
|
23
|
+
// Unlike ESLint stylish, retain punctuation in the original rule message.
|
|
24
|
+
message.message,
|
|
25
|
+
message.ruleId || "",
|
|
26
|
+
]);
|
|
27
|
+
const widths = [0, 0, 0, 0];
|
|
28
|
+
for (const row of rows) {
|
|
29
|
+
for (let index = 0; index < widths.length; index += 1) {
|
|
30
|
+
widths[index] = Math.max(widths[index], stripVTControlCharacters(row[index]).length);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
for (const [line, column, severity, message, ruleId] of rows) {
|
|
34
|
+
const location = " ".repeat(widths[0] - line.length)
|
|
35
|
+
+ paint(`${line}:${column}`, 2, 22)
|
|
36
|
+
+ " ".repeat(widths[1] - column.length);
|
|
37
|
+
const label = paint(severity, severity === "error" ? 31 : 33, 39)
|
|
38
|
+
+ " ".repeat(widths[2] - severity.length);
|
|
39
|
+
const padding = " ".repeat(widths[3] - stripVTControlCharacters(message).length);
|
|
40
|
+
const description = ruleId ? `${message}${padding} ${paint(ruleId, 2, 22)}` : message;
|
|
41
|
+
lines.push(` ${location} ${label} ${description}`);
|
|
42
|
+
}
|
|
43
|
+
lines.push("");
|
|
44
|
+
errorCount += result.errorCount;
|
|
45
|
+
warningCount += result.warningCount;
|
|
46
|
+
fixableErrorCount += result.fixableErrorCount ?? 0;
|
|
47
|
+
fixableWarningCount += result.fixableWarningCount ?? 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (errorCount || warningCount) {
|
|
51
|
+
const summary = (text) => paint(paint(text, 1, 22), errorCount ? 31 : 33, 39);
|
|
52
|
+
lines.push(summary(
|
|
53
|
+
`✖ ${pluralize(errorCount + warningCount, "problem")} (${pluralize(errorCount, "error")}, ${pluralize(warningCount, "warning")})`
|
|
54
|
+
));
|
|
55
|
+
if (fixableErrorCount || fixableWarningCount) {
|
|
56
|
+
lines.push(summary(
|
|
57
|
+
` ${pluralize(fixableErrorCount, "error")} and ${pluralize(fixableWarningCount, "warning")} potentially fixable with the \`--fix\` option.`
|
|
58
|
+
));
|
|
59
|
+
}
|
|
60
|
+
lines.push("");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return lines.join("\n");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function pluralize(count, noun) {
|
|
67
|
+
return `${count} ${noun}${count === 1 ? "" : "s"}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function shouldUseColor(options) {
|
|
71
|
+
if (typeof options.color === "boolean") return options.color;
|
|
72
|
+
const env = options.env ? { ...process.env, ...options.env } : process.env;
|
|
73
|
+
if (env.NO_COLOR !== undefined || env.NODE_DISABLE_COLORS !== undefined) return false;
|
|
74
|
+
if (env.FORCE_COLOR !== undefined) return env.FORCE_COLOR !== "0";
|
|
75
|
+
if (env.CLICOLOR_FORCE && env.CLICOLOR_FORCE !== "0") return true;
|
|
76
|
+
return env.TERM !== "dumb" && Boolean(process.stdout.isTTY);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
module.exports = { formatESLintResults };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@utoo/lint",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
4
4
|
"description": "High-performance JavaScript and TypeScript linter powered by Yuku",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -76,11 +76,11 @@
|
|
|
76
76
|
"use-at-your-own-risk.js"
|
|
77
77
|
],
|
|
78
78
|
"optionalDependencies": {
|
|
79
|
-
"@utoo/lint-darwin-arm64": "0.3.
|
|
80
|
-
"@utoo/lint-darwin-x64": "0.3.
|
|
81
|
-
"@utoo/lint-linux-arm64": "0.3.
|
|
82
|
-
"@utoo/lint-linux-x64": "0.3.
|
|
83
|
-
"@utoo/lint-win32-x64": "0.3.
|
|
79
|
+
"@utoo/lint-darwin-arm64": "0.3.9",
|
|
80
|
+
"@utoo/lint-darwin-x64": "0.3.9",
|
|
81
|
+
"@utoo/lint-linux-arm64": "0.3.9",
|
|
82
|
+
"@utoo/lint-linux-x64": "0.3.9",
|
|
83
|
+
"@utoo/lint-win32-x64": "0.3.9"
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
86
|
"@eslint/eslintrc": "2.1.4",
|