自定义格式化器
自定义格式化器允许您以最适合您需求的格式显示代码检查结果,无论是特定的文件格式、特定的显示样式,还是针对特定工具优化的格式。
ESLint 还具有您可以使用的内置格式化器。
您可以直接在项目中包含自定义格式化器,或创建一个 npm 包以单独分发它们。
创建自定义格式化器
每个格式化器都是一个函数,它接收一个results
对象和一个context
作为参数并返回一个字符串。例如,以下是内置JSON 格式化器的实现方式
//my-awesome-formatter.js
module.exports = function(results, context) {
return JSON.stringify(results, null, 2);
};
格式化器也可以是异步函数(从 ESLint v8.4.0 开始),以下显示了一个简单的示例
//my-awesome-formatter.js
module.exports = async function(results) {
const formatted = await asyncTask();
return formatted;
};
要使用此格式化器运行 ESLint,您可以使用-f
(或--format
)命令行标志。您必须以句点 (.
) 开头本地定义的自定义格式化器的路径,例如./my-awesome-formatter.js
或../formatters/my-awesome-formatter.js
。
eslint -f ./my-awesome-formatter.js src/
本节的其余部分包含有关如何使用自定义格式化器函数的参考信息。
results 参数
传递给格式化器的results
对象是一个result
对象的数组,其中包含各个文件的代码检查结果。这是一个示例输出
[
{
filePath: "/path/to/a/file.js",
messages: [
{
ruleId: "curly",
severity: 2,
message: "Expected { after 'if' condition.",
line: 2,
column: 1,
nodeType: "IfStatement"
},
{
ruleId: "no-process-exit",
severity: 2,
message: "Don't use process.exit(); throw an error instead.",
line: 3,
column: 1,
nodeType: "CallExpression"
}
],
errorCount: 2,
warningCount: 0,
fixableErrorCount: 0,
fixableWarningCount: 0,
source:
"var err = doStuff();\nif (err) console.log('failed tests: ' + err);\nprocess.exit(1);\n"
},
{
filePath: "/path/to/Gruntfile.js",
messages: [],
errorCount: 0,
warningCount: 0,
fixableErrorCount: 0,
fixableWarningCount: 0
}
]
result 对象
results
数组中的每个对象都是一个result
对象。每个result
对象都包含已检查文件的路径以及遇到的代码检查问题的信息。以下是每个result
对象上可用的属性
- filePath:已检查文件的绝对路径。
- messages:
message
对象的数组。有关消息的更多信息,请参见下文。 - errorCount:给定文件的错误数。
- warningCount:给定文件的警告数。
- stats:仅在使用
stats
选项时存在的可选stats
对象。 - source:给定文件的源代码。如果此文件没有错误/警告或存在
output
属性,则会省略此属性。 - output:给定文件的源代码,其中应用了尽可能多的修复。如果不可用任何修复,则会省略此属性。
message 对象
每个message
对象都包含有关由某些源代码触发的 ESLint 规则的信息。每个message
对象上可用的属性为
- ruleId:生成错误或警告的规则的 ID。如果错误或警告不是由规则生成的(例如,如果它是解析错误),则为
null
。 - severity:故障的严重程度,
1
表示警告,2
表示错误。 - message:错误的人类可读描述。
- line:问题所在的行。
- column:问题所在的列。
- nodeType:(已弃用:此属性将在 ESLint 的未来版本中删除。)AST中节点的类型,如果问题与特定 AST 节点无关,则为
null
。
context 参数
格式化器函数以context
对象作为其第二个参数接收。该对象具有以下属性
cwd
:当前工作目录。此值来自ESLint类的cwd
构造函数选项。maxWarningsExceeded
(可选):如果设置了--max-warnings
并且警告数超过了限制,则此属性的值是一个包含两个属性的对象maxWarnings
:--max-warnings
选项的值foundWarnings
:lint 警告的数量
rulesMeta
:规则的meta
属性值。有关规则的更多信息,请参阅自定义规则页面。
例如,如果已运行规则no-extra-semi
,则该对象如下所示
{
cwd: "/path/to/cwd",
maxWarningsExceeded: {
maxWarnings: 5,
foundWarnings: 6
},
rulesMeta: {
"no-extra-semi": {
type: "suggestion",
docs: {
description: "disallow unnecessary semicolons",
recommended: true,
url: "https://eslint.org.cn/docs/rules/no-extra-semi"
},
fixable: "code",
schema: [],
messages: {
unexpected: "Unnecessary semicolon."
}
}
},
}
注意:如果代码检查由已弃用的CLIEngine
类执行,则context
参数可能具有不同的值,因为它取决于 API 用户。如果您希望支持旧版环境,请检查context
参数是否为预期值。
将参数传递给格式化器
虽然格式化器函数除了结果对象和上下文之外不接收参数,但可以使用下面描述的方法将其他数据传递到自定义格式化器中。
使用环境变量
自定义格式化器可以访问环境变量,因此可以根据环境变量数据更改其行为。
这是一个使用FORMATTER_SKIP_WARNINGS
环境变量来确定是否在结果中显示警告的示例
module.exports = function(results) {
var skipWarnings = process.env.FORMATTER_SKIP_WARNINGS === "true";
var results = results || [];
var summary = results.reduce(
function(seq, current) {
current.messages.forEach(function(msg) {
var logMessage = {
filePath: current.filePath,
ruleId: msg.ruleId,
message: msg.message,
line: msg.line,
column: msg.column
};
if (msg.severity === 1) {
logMessage.type = "warning";
seq.warnings.push(logMessage);
}
if (msg.severity === 2) {
logMessage.type = "error";
seq.errors.push(logMessage);
}
});
return seq;
},
{
errors: [],
warnings: []
}
);
if (summary.errors.length > 0 || summary.warnings.length > 0) {
var warnings = !skipWarnings ? summary.warnings : []; // skip the warnings in that case
var lines = summary.errors
.concat(warnings)
.map(function(msg) {
return (
"\n" +
msg.type +
" " +
msg.ruleId +
"\n " +
msg.filePath +
":" +
msg.line +
":" +
msg.column
);
})
.join("\n");
return lines + "\n";
}
};
您可以使用此自定义格式化器和设置的环境变量运行 ESLint,如下所示
FORMATTER_SKIP_WARNINGS=true eslint -f ./my-awesome-formatter.js src/
输出将是
error space-infix-ops
src/configs/bundler.js:6:8
error semi
src/configs/bundler.js:6:10
复杂的参数传递
如果您发现自定义格式化器模式没有提供足够的选择来满足您想要格式化 ESLint 结果的方式,最好的选择是使用 ESLint 的内置JSON 格式化器并将输出传递到第二个程序。例如
eslint -f json src/ | your-program-that-reads-JSON --option
在此示例中,your-program-that-reads-json
程序可以接受 ESLint 结果的原始 JSON 并对其进行处理,然后再输出其自己的结果格式。您可以向该程序传递尽可能多的命令行参数以自定义输出。
终端格式化
像iTerm2或Guake这样的现代终端期望特定的结果格式才能在单击时自动打开文件名。大多数终端都支持此格式以用于此目的
file:line:column
打包自定义格式化器
自定义格式化器可以通过 npm 包分发。为此,创建一个 npm 包,其名称格式为eslint-formatter-*
,其中*
是您的格式化器的名称(例如eslint-formatter-awesome
)。然后,项目应安装该包并使用-f
(或--format
)标志使用自定义格式化器,如下所示
eslint -f awesome src/
因为 ESLint 知道在指定的格式化器没有以句点开头时查找以eslint-formatter-
开头的包,所以使用打包的自定义格式化器时,您无需键入eslint-formatter-
。
自定义格式化器的 package.json 提示
- 主要的
main
入口点必须是实现自定义格式化器的 JavaScript 文件。 - 添加这些
keywords
以帮助用户找到您的格式化器"eslint"
"eslint-formatter"
"eslintformatter"
查看 npm 上的所有自定义格式化器。
示例
摘要格式化器
仅报告错误和警告总数的格式化器如下所示
module.exports = function(results, context) {
// accumulate the errors and warnings
var summary = results.reduce(
function(seq, current) {
seq.errors += current.errorCount;
seq.warnings += current.warningCount;
return seq;
},
{ errors: 0, warnings: 0 }
);
if (summary.errors > 0 || summary.warnings > 0) {
return (
"Errors: " +
summary.errors +
", Warnings: " +
summary.warnings +
"\n"
);
}
return "";
};
使用上述摘要格式化器运行eslint
eslint -f ./my-awesome-formatter.js src/
将产生以下输出
Errors: 2, Warnings: 4
详细格式化器
更复杂的报告可能如下所示
module.exports = function(results, context) {
var results = results || [];
var summary = results.reduce(
function(seq, current) {
current.messages.forEach(function(msg) {
var logMessage = {
filePath: current.filePath,
ruleId: msg.ruleId,
ruleUrl: context.rulesMeta[msg.ruleId].docs.url,
message: msg.message,
line: msg.line,
column: msg.column
};
if (msg.severity === 1) {
logMessage.type = "warning";
seq.warnings.push(logMessage);
}
if (msg.severity === 2) {
logMessage.type = "error";
seq.errors.push(logMessage);
}
});
return seq;
},
{
errors: [],
warnings: []
}
);
if (summary.errors.length > 0 || summary.warnings.length > 0) {
var lines = summary.errors
.concat(summary.warnings)
.map(function(msg) {
return (
"\n" +
msg.type +
" " +
msg.ruleId + (msg.ruleUrl ? " (" + msg.ruleUrl + ")" : "") +
"\n " +
msg.filePath +
":" +
msg.line +
":" +
msg.column
);
})
.join("\n");
return lines + "\n";
}
};
当您使用此自定义格式化器运行 ESLint 时
eslint -f ./my-awesome-formatter.js src/
输出为
error space-infix-ops (https://eslint.org.cn/docs/rules/space-infix-ops)
src/configs/bundler.js:6:8
error semi (https://eslint.org.cn/docs/rules/semi)
src/configs/bundler.js:6:10
warning no-unused-vars (https://eslint.org.cn/docs/rules/no-unused-vars)
src/configs/bundler.js:5:6
warning no-unused-vars (https://eslint.org.cn/docs/rules/no-unused-vars)
src/configs/bundler.js:6:6
warning no-shadow (https://eslint.org.cn/docs/rules/no-shadow)
src/configs/bundler.js:65:32
warning no-unused-vars (https://eslint.org.cn/docs/rules/no-unused-vars)
src/configs/clean.js:3:6