版本

创建插件

ESLint 插件通过附加功能扩展 ESLint。在大多数情况下,您将通过创建封装所需附加功能的插件来扩展 ESLint,以便在多个项目之间共享这些功能。

创建一个插件

插件是一个 JavaScript 对象,它向 ESLint 暴露某些属性

  • meta - 关于插件的信息。
  • configs - 包含命名配置的对象。
  • rules - 包含自定义规则定义的对象。
  • processors - 包含命名处理器的对象。

要开始,创建一个 JavaScript 文件并导出包含您希望 ESLint 使用的属性的对象。为了使您的插件尽可能易于维护,我们建议您将插件入口点文件格式化为如下所示

const plugin = {
	meta: {},
	configs: {},
	rules: {},
	processors: {},
};

// for ESM
export default plugin;

// OR for CommonJS
module.exports = plugin;

如果您计划将您的插件作为 npm 包分发,请确保导出插件对象的模块是您包的默认导出。这将使 ESLint 能够在命令行中通过 --plugin 选项 指定时导入插件。

插件中的元数据

为了更轻松地调试和更有效地缓存插件,建议在插件的根目录下提供一个 meta 对象,其中包含 nameversionnamespace,如下所示

const plugin = {
	// preferred location of name and version
	meta: {
		name: "eslint-plugin-example",
		version: "1.2.3",
		namespace: "example",
	},
	rules: {
		// add rules here
	},
};

// for ESM
export default plugin;

// OR for CommonJS
module.exports = plugin;

meta.name 属性应与您的插件的 npm 包名称匹配,而 meta.version 属性应与您的插件的 npm 包版本匹配。meta.namespace 属性应与您希望用户用于访问插件的规则、处理器、语言和配置的前缀匹配。命名空间通常是在您的包名称中 eslint-plugin- 之后的内容,这就是为什么本示例使用 "example"。提供命名空间允许 defineConfig() 函数即使在用户在他们的配置文件中指定了不同的命名空间时也能找到您的插件。

最简单的方法是从您的 package.json 中读取名称和版本信息,如下所示

import fs from "fs";

const pkg = JSON.parse(
	fs.readFileSync(new URL("./package.json", import.meta.url), "utf8"),
);

const plugin = {
	// preferred location of name and version
	meta: {
		name: pkg.name,
		version: pkg.version,
		namespace: "example",
	},
	rules: {
		// add rules here
	},
};

export default plugin;

或者,您也可以在插件的根目录下暴露 nameversion 属性,如下所示

const plugin = {
	// alternate location of name and version
	name: "eslint-plugin-example",
	version: "1.2.3",
	rules: {
		// add rules here
	},
};

// for ESM
export default plugin;

// OR for CommonJS
module.exports = plugin;

插件中的规则

插件可以暴露自定义规则供 ESLint 使用。为此,插件必须导出一个 rules 对象,其中包含规则 ID 到规则的键值映射。规则 ID 不需要遵循任何命名约定,除了它不应包含 / 字符(因此它可以是 dollar-sign,但不能是 foo/dollar-sign,例如)。要了解有关在插件中创建自定义规则的更多信息,请参阅 自定义规则

const plugin = {
	meta: {
		name: "eslint-plugin-example",
		version: "1.2.3",
	},
	rules: {
		"dollar-sign": {
			create(context) {
				// rule implementation ...
			},
		},
	},
};

// for ESM
export default plugin;

// OR for CommonJS
module.exports = plugin;

为了在配置文件中使用插件中的规则,请导入插件并在 plugins 键中包含它,指定一个命名空间。然后,使用该命名空间在 rules 配置中引用该规则,如下所示

// eslint.config.js
import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";

export default defineConfig([
	{
		files: ["**/*.js"], // any patterns you want to apply the config to
		plugins: {
			example,
		},
		rules: {
			"example/dollar-sign": "error",
		},
	},
]);

插件中的处理器

插件可以通过提供 processors 对象暴露 处理器 供配置文件使用。与规则类似,processors 对象中的每个键都是处理器的名称,每个值都是处理器对象本身。这是一个例子

const plugin = {
	meta: {
		name: "eslint-plugin-example",
		version: "1.2.3",
	},
	processors: {
		"processor-name": {
			preprocess(text, filename) {
				/* ... */
			},
			postprocess(messages, filename) {
				/* ... */
			},
		},
	},
};

// for ESM
export default plugin;

// OR for CommonJS
module.exports = plugin;

为了在配置文件中使用插件中的处理器,请导入插件并在 plugins 键中包含它,指定一个命名空间。然后,使用该命名空间在 processor 配置中引用该处理器,如下所示

// 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",
	},
]);

插件中的配置

您可以将配置捆绑在插件中,方法是在 configs 键下指定它们。当您希望将一组自定义规则与启用推荐选项的配置捆绑在一起时,这会很有用。每个插件支持多个配置。

您可以在也包含在插件中的配置中包含来自插件的单个规则。在配置中,您必须在 plugins 对象中指定您的插件名称,以及您想要启用的插件中的任何规则。任何插件规则都必须以插件命名空间为前缀。这是一个例子

const plugin = {
	meta: {
		name: "eslint-plugin-example",
		version: "1.2.3",
	},
	configs: {},
	rules: {
		"dollar-sign": {
			create(context) {
				// rule implementation ...
			},
		},
	},
};

// assign configs here so we can reference `plugin`
Object.assign(plugin.configs, {
	recommended: [
		{
			plugins: {
				example: plugin,
			},
			rules: {
				"example/dollar-sign": "error",
			},
			languageOptions: {
				globals: {
					myGlobal: "readonly",
				},
				parserOptions: {
					ecmaFeatures: {
						jsx: true,
					},
				},
			},
		},
	],
});

// for ESM
export default plugin;

// OR for CommonJS
module.exports = plugin;

此插件导出一个 recommended 配置,该配置是一个包含一个配置对象的数组。如果只有一个配置对象,您也可以仅导出该对象,而无需包含数组。

为了在配置文件中使用插件中的配置,请导入插件并使用 extends 键引用配置的名称,如下所示

// eslint.config.js
import { defineConfig } from "eslint/config";
import example from "eslint-plugin-example";

export default defineConfig([
	{
		files: ["**/*.js"], // any patterns you want to apply the config to
		plugins: {
			example,
		},
		extends: ["example/recommended"],
	},
]);

旧版配置的向后兼容性

如果您的插件需要导出与当前(flat config)系统和旧(eslintrc)系统都兼容的配置,则可以从 configs 键导出两种类型的配置。在导出旧版配置时,我们建议使用 "legacy-" 前缀命名(例如,"legacy-recommended"),以明确如何使用该配置。

如果您正在开发一个存在于 ESLint v9.0.0 之前的插件,那么您可能已经具有名为 "recommended" 的旧版配置。如果您不想更新配置名称,您也可以在 configs 对象中创建一个附加条目,并以 "flat/" 为前缀(例如,"flat/recommended")。这是一个例子

const plugin = {
	meta: {
		name: "eslint-plugin-example",
		version: "1.2.3",
	},
	configs: {},
	rules: {
		"dollar-sign": {
			create(context) {
				// rule implementation ...
			},
		},
	},
};

// assign configs here so we can reference `plugin`
Object.assign(plugin.configs, {
	// flat config format
	"flat/recommended": [
		{
			plugins: {
				example: plugin,
			},
			rules: {
				"example/dollar-sign": "error",
			},
			languageOptions: {
				globals: {
					myGlobal: "readonly",
				},
				parserOptions: {
					ecmaFeatures: {
						jsx: true,
					},
				},
			},
		},
	],

	// eslintrc format
	recommended: {
		plugins: ["example"],
		rules: {
			"example/dollar-sign": "error",
		},
		globals: {
			myGlobal: "readonly",
		},
		parserOptions: {
			ecmaFeatures: {
				jsx: true,
			},
		},
	},
});

// for ESM
export default plugin;

// OR for CommonJS
module.exports = plugin;

使用这种方法,两种配置系统都识别 "recommended"。旧的配置系统使用 recommended 键,而当前的配置系统使用 flat/recommended 键。defineConfig() 助手首先查找 recommended 键,如果该键不在正确的格式中,则查找 flat/recommended 键。这为您提供了一个升级路径,如果您以后想将 flat/recommended 重命名为 recommended,而不再需要支持旧的配置系统。

测试插件

ESLint 提供了 RuleTester 工具,以便轻松测试插件的规则。

Lint 插件

插件也应该进行 Lint 检查!建议使用以下推荐配置来 Lint 您的插件

共享插件

为了使您的插件公开可用,您必须在 npm 上发布它。在这样做时,请务必

  1. 将 ESLint 列为 peer 依赖项。 由于插件旨在与 ESLint 一起使用,因此将 eslint 包添加为 peer 依赖项非常重要。为此,手动编辑您的 package.json 文件以包含一个 peerDependencies 块,如下所示

    {
    	"peerDependencies": {
    		"eslint": ">=9.0.0"
    	}
    }
    
  2. 指定关键字。 ESLint 插件应在 package.json 文件中指定 eslinteslintplugineslint-plugin 作为 关键字

更改语言