自定义处理器
你还可以创建自定义处理器,告诉 ESLint 如何处理除标准 JavaScript 之外的文件。例如,你可以编写自定义处理器,从 Markdown 文件中提取并处理 JavaScript(@eslint/markdown 包含用于此目的的自定义处理器)。
🌐 You can also create custom processors that tell ESLint how to process files other than standard JavaScript. For example, you could write a custom processor to extract and process JavaScript from Markdown files (@eslint/markdown includes a custom processor for this).
定制处理器规范
🌐 Custom Processor Specification
为了创建自定义处理器,从你的模块导出的对象必须符合以下接口:
🌐 In order to create a custom processor, the object exported from your module has to conform to the following interface:
const plugin = {
meta: {
name: "eslint-plugin-example",
version: "1.2.3",
},
processors: {
"processor-name": {
meta: {
name: "eslint-processor-name",
version: "1.2.3",
},
// takes text of the file and filename
preprocess(text, filename) {
// here, you can strip out any non-JS content
// and split into multiple strings to lint
return [
// return an array of code blocks to lint
{ text: code1, filename: "0.js" },
{ text: code2, filename: "1.js" },
];
},
// takes a Message[][] and filename
postprocess(messages, filename) {
// `messages` argument contains two-dimensional array of Message objects
// where each top-level array item contains array of lint messages related
// to the text that was returned in array from preprocess() method
// you need to return a one-dimensional array of the messages you want to keep
return [].concat(...messages);
},
supportsAutofix: true, // (optional, defaults to false)
},
},
};
// for ESM
export default plugin;
// OR for CommonJS
module.exports = plugin;
preprocess 方法 接受文件内容和文件名作为参数,并返回一个要进行 lint 的代码块数组。代码块将被分别 lint,但仍会注册到该文件名下。
一个代码块有两个属性 text 和 filename。text 属性是代码块的内容,filename 属性是代码块的名称。代码块的名称可以是任意的,但应包含文件扩展名,这告诉 ESLint 如何处理当前代码块。ESLint 会检查项目配置中匹配的 files 条目,以确定是否应该对代码块进行 lint 检查。
🌐 A code block has two properties text and filename. The text property is the content of the block and the filename property is the name of the block. The name of the block can be anything, but should include the file extension, which tells ESLint how to process the current block. ESLint checks matching files entries in the project’s config to determine if the code blocks should be linted.
由插件来决定它是否只需要返回非 JavaScript 文件的一部分或多个部分。例如,在处理 .html 文件的情况下,你可能只想通过合并所有脚本返回数组中的一个项目。但是,对于 .md 文件,你可以返回多个项目,因为每个 JavaScript 块可能是独立的。
🌐 It’s up to the plugin to decide if it needs to return just one part of the non-JavaScript file or multiple pieces. For example in the case of processing .html files, you might want to return just one item in the array by combining all scripts. However, for .md files, you can return multiple items because each JavaScript block might be independent.
postprocess 方法 接受一个二维数组(包含 lint 消息的数组)和文件名。输入数组中的每一项对应于 preprocess 方法返回的部分。postprocess 方法必须调整所有错误的位置,以对应原始未处理代码中的位置,并将它们聚合成一个单一的平面数组并返回。
报告的问题在每条 lint 消息中具有以下位置信息:
🌐 Reported problems have the following location information in each lint message:
type LintMessage = {
/// The 1-based line number where the message occurs.
line?: number;
/// The 1-based column number where the message occurs.
column?: number;
/// The 1-based line number of the end location.
endLine?: number;
/// The 1-based column number of the end location.
endColumn?: number;
/// If `true`, this is a fatal error.
fatal?: boolean;
/// Information for an autofix.
fix: Fix;
/// The error message.
message: string;
/// The ID of the rule which generated the message, or `null` if not applicable.
ruleId: string | null;
/// The severity of the message.
severity: 0 | 1 | 2;
/// Information for suggestions.
suggestions?: Suggestion[];
};
type Fix = {
range: [number, number];
text: string;
};
type Suggestion = {
desc?: string;
messageId?: string;
fix: Fix;
};
默认情况下,当使用自定义处理器时,即使在命令行上启用了 --fix 标志,ESLint 也不会执行自动修复。为了在使用你的处理器时让 ESLint 自动修复代码,你应该采取以下额外步骤:
🌐 By default, ESLint does not perform autofixes when a custom processor is used, even when the --fix flag is enabled on the command line. To allow ESLint to autofix code when using your processor, you should take the following additional steps:
-
更新
postprocess方法,以额外转换已报告问题的fix属性。所有可自动修复的问题都有一个fix属性,该属性是一个具有以下模式的对象:{ range: [number, number], text: string }range属性包含代码中的两个索引,指的是将被替换的连续文本段的起始和结束位置。text属性指的是将替换给定范围的文本。在初始问题列表中,
fix属性将指向已处理 JavaScript 中的修复。postprocess方法应将对象转换为指向原始未处理文件中的修复。 -
在处理器中添加一个
supportsAutofix: true属性。
你可以在一个插件中同时拥有规则和自定义处理器。你也可以在一个插件中拥有多个处理器。要支持多个扩展,请将每一个添加到 processors 元素中并将它们指向同一个对象。
🌐 You can have both rules and custom processors in a single plugin. You can also have multiple processors in one plugin. To support multiple extensions, add each one to the processors element and point them to the same object.
meta 对象的使用方式
🌐 How meta Objects are Used
meta 对象帮助 ESLint 缓存使用处理器的配置,并提供更友好的调试信息。
🌐 The meta object helps ESLint cache configurations that use a processor and to provide more friendly debug messages.
插件 meta 对象
🌐 Plugin meta Object
插件 meta 对象 提供有关插件本身的信息。当使用字符串格式 plugin-name/processor-name 指定处理器时,ESLint 会自动使用插件 meta 为处理器生成名称。这是处理器最常见的情况。
🌐 The plugin meta object provides information about the plugin itself. When a processor is specified using the string format plugin-name/processor-name, ESLint automatically uses the plugin meta to generate a name for the processor. This is the most common case for processors.
示例:
🌐 Example:
// eslint.config.js
import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";
export default defineConfig([
{
files: ["**/*.txt"], // apply processor to text files
plugins: {
example,
},
processor: "example/processor-name",
},
// ... other configs
]);
在此示例中,处理器名称是 "example/processor-name",这就是将用于序列化配置的值。
🌐 In this example, the processor name is "example/processor-name", and that’s the value that will be used for serializing configurations.
处理器 meta 对象
🌐 Processor meta Object
每个处理器也可以指定自己的 meta 对象。当处理器对象直接传递给配置中的 processor 时,会使用此信息。在这种情况下,ESLint 不知道该处理器属于哪个插件。meta.name 属性应与处理器名称匹配,meta.version 属性应与处理器的 npm 包版本匹配。实现这一点的最简单方法是从你的 package.json 中读取此信息。
🌐 Each processor can also specify its own meta object. This information is used when the processor object is passed directly to processor in a configuration. In that case, ESLint doesn’t know which plugin the processor belongs to. The meta.name property should match the processor name and the meta.version property should match the npm package version for your processors. The easiest way to accomplish this is by reading this information from your package.json.
示例:
🌐 Example:
// eslint.config.js
import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";
export default defineConfig([
{
files: ["**/*.txt"],
processor: example.processors["processor-name"],
},
// ... other configs
]);
在此示例中,指定 example.processors["processor-name"] 会直接使用处理器自身的 meta 对象,当处理器不是通过插件名称引用时,必须定义该对象以确保正确处理。
🌐 In this example, specifying example.processors["processor-name"] directly uses the processor’s own meta object, which must be defined to ensure proper handling when the processor is not referenced through the plugin name.
为什么需要两个元对象
🌐 Why Both Meta Objects are Needed
建议插件和每个处理器都提供各自的元对象。这确保依赖元对象的功能,例如 --print-config 和 --cache,无论处理器在配置中如何指定,都能正确运行。
🌐 It is recommended that both the plugin and each processor provide their respective meta objects. This ensures that features relying on meta objects, such as --print-config and --cache, work correctly regardless of how the processor is specified in the configuration.
在配置文件中指定处理器
🌐 Specify Processor in Config Files
为了在配置文件中使用来自插件的处理器,需要导入该插件并将其包含在 plugins 键中,同时指定一个命名空间。然后,使用该命名空间在 processor 配置中引用该处理器,如下所示:
🌐 In order to use a processor from a plugin in a configuration file, import the plugin and include it in the plugins key, specifying a namespace. Then, use that namespace to reference the processor in the processor configuration, like this:
// eslint.config.js
import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";
export default defineConfig([
{
files: ["**/*.txt"],
plugins: {
example,
},
processor: "example/processor-name",
},
]);
有关更多详情,请参阅插件配置文档中的 指定处理器。
🌐 See Specify a Processor in the Plugin Configuration documentation for more details.