配置矩阵
说明
配置阵列是管理配置的一种方式,这种配置基于文件名的 glob 模式匹配. 每个配置阵列包含根据文件名确定任何文件正确配置所需的信息.
说明: 这是一个通用软件包,可以在ESLint之外使用. 它没有包含ESLint特定功能.
安装
对于节点和相容运行时间:
npm install @eslint/config-array
# or
yarn add @eslint/config-array
# or
pnpm install @eslint/config-array
# or
bun add @eslint/config-array
对于德诺:
deno add @eslint/config-array
背景情况
基本的想法是,所有配置,包括覆被,都可以由单个数组来表示,其中数组中的每个项目都是一个配置对象. 配置对象出现在数组后面, 覆盖在数组前面出现的配置对象 。 您可以通过翻转数组中的所有配置对象来计算给定文件的配置, 以找到匹配文件名的对象 。 匹配是通过在 files 财务报告和审定财务报表 ignores 每个配置对象的属性。 举个例子:
export default [
// match all JSON files
{
name: "JSON Handler",
files: ["**/*.json"],
handler: jsonHandler,
},
// match only package.json
{
name: "package.json Handler",
files: ["package.json"],
handler: packageJsonHandler,
},
];
在这个例子中,有两个配置对象:第一个匹配所有目录中的所有 JSON 文件,第二个匹配只是 package.json 在基础路径目录中(所有 globs 被评价为相对于一个可以指定的基础路径). 当您获取配置时 foo.json只有第一个配置对象匹配 handler 等于 jsonHandler; 当您获取配置时 package.json, (中文(简体) ), handler 等于 packageJsonHandler (因为两个配置对象都匹配,第二个获胜).
使用量
首先导入 ConfigArray 构造器 :
import { ConfigArray } from "@eslint/config-array";
// or using CommonJS
const { ConfigArray } = require("@eslint/config-array");
当你创建一个新的实例 ConfigArray,您必须在两个参数中通过:一组配置和一个选项对象。 配置的阵列最有可能从配置文件中读取,所以这里有一个典型的例子:
import path from "node:path";
import { pathToFileURL } from "node:url";
import { ConfigArray } from "@eslint/config-array";
const configFilename = path.resolve(process.cwd(), "my.config.js");
const { default: rawConfigs } = await import(pathToFileURL(configFilename));
const configs = new ConfigArray(rawConfigs, {
// the path to match filenames from
basePath: process.cwd(),
// additional items in each config
schema: mySchema,
});
此示例在对象或数组中读取: my.config.js 传入 ConfigArray 构造器作为第一个参数. 第二个参数是一个指定对象 basePath (目录中 my.config.js (已找到)和a schema 以定义配置对象之外的额外属性 files, (中文(简体) ), ignores, (中文(简体) ), basePath,以及 name。 。 。 .
指定外观
这个 schema 在配置对象中,您需要使用额外的属性。 schema 是一个对象,它遵循一个 ObjectSchema。这个计划既规定了验证规则,也规定了合并规则 ConfigArray 当有多个匹配时,实例需要组合配置。 举个例子:
const configFilename = path.resolve(process.cwd(), "my.config.js");
const { default: rawConfigs } = await import(pathToFileURL(configFilename));
const mySchema = {
// define the handler key in configs
handler: {
required: true,
merge(a, b) {
return b ?? a;
},
validate(value) {
if (typeof value !== "function") {
throw new TypeError("Function expected.");
}
},
},
};
const configs = new ConfigArray(rawConfigs, {
// the path to match filenames from
basePath: process.cwd(),
// additional item schemas in each config
schema: mySchema,
// additional config types supported (default: [])
extraConfigTypes: ["array", "function"],
});
配置矩阵
配置阵列可以是多维的,因此一个配置阵列有可能包含另一个配置阵列,当 extraConfigTypes 包含 "array",例如:
export default [
// JS config
{
files: ["**/*.js"],
handler: jsHandler,
},
// JSON configs
[
// match all JSON files
{
name: "JSON Handler",
files: ["**/*.json"],
handler: jsonHandler,
},
// match only package.json
{
name: "package.json Handler",
files: ["package.json"],
handler: packageJsonHandler,
},
],
// filename must match function
{
files: [filePath => filePath.endsWith(".md")],
handler: markdownHandler,
},
// filename must match all patterns in subarray
{
files: [["*.test.*", "*.js"]],
handler: jsTestHandler,
},
// filename must not match patterns beginning with !
{
name: "Non-JS files",
files: ["!*.js"],
settings: {
js: false,
},
},
// specific settings for files inside `src` directory
{
name: "Source files",
basePath: "src",
files: ["**/*"],
settings: {
source: true,
},
},
];
在这个例子中,阵列同时包含配置对象和一个配置阵列. 当一个配置阵列实现正态化(见下文细节)时,它被平整,所以仅保留了配置对象. 然而,评价的顺序保持不变.
如果 files 数组包含一个函数,然后该函数随文件的路径被调用。 该功能预计将返回 true 如果有一个匹配和 false 如果不是的话。 (本节) ignores 数组也可以包含函数. )
如果 files 数组包含一个字符串和函数的数组,然后所有图案必须相匹配才能匹配配置。 在上述例子中 *.test.* 财务报告和审定财务报表 *.js 要使用配置对象,必须匹配.
如果文件数组中的图案开始 ! 然后它排除了这种模式。 在前一个例子中,任何没有结束的文件名 .js 自动获得 settings.js 设置为 false。 。 。 .
您也可以指定一个 ignores 键将迫使匹配这些模式的文件不包含。 如果 ignores 键在配置对象中,没有其他键,那么这些被忽略的会永远被应用;否则,这些被忽略的会起到排除的作用。 举个例子:
export default [
// Always ignored
{
ignores: ["**/.git/**", "**/node_modules/**"],
},
// .eslintrc.js file is ignored only when .js file matches
{
files: ["**/*.js"],
ignores: [".eslintrc.js"],
handler: jsHandler,
},
];
您可以在 ignores 排除已被忽略的文件,例如:
export default [
// Ignore all JSON files except tsconfig.json
{
files: ["**/*"],
ignores: ["**/*.json", "!tsconfig.json"],
},
];
配置函数
配置数组也可以包括配置函数,当 extraConfigTypes 包含 "function"。一个配置函数接受单个参数, context (由您定义),并且必须返回一个配置对象或一个配置阵列(它不能返回另一个函数). 配置功能允许最终用户在创建适当的配置对象时执行代码. 举个例子:
export default [
// JS config
{
files: ["**/*.js"],
handler: jsHandler,
},
// JSON configs
function (context) {
return [
// match all JSON files
{
name: context.name + " JSON Handler",
files: ["**/*.json"],
handler: jsonHandler,
},
// match only package.json
{
name: context.name + " package.json Handler",
files: ["package.json"],
handler: packageJsonHandler,
},
];
},
];
当一个配置数组正常化时,每个函数都会被执行,并在配置数组中被替换为返回值.
说明: 配置函数也可以是async.
配置阵列规范化
一旦一个配置阵列被创建并装入了所有原始配置数据后,它就必须被正常化后才能被使用. 正常化进程贯穿并平整了配置阵列,以及执行所有配置功能以获得其最终值.
要将配置数组正常化,请调用 normalize() 上下文对象中的方法和通过:
await configs.normalize({
name: "MyApp",
});
这个 normalize() 方法返回一个承诺,所以一定要使用 await 操作员。 配置数组实例在位置上正常化,所以不需要创建新的变量.
如果您想要拒绝 async 配置函数, 您可以调用 normalizeSync() 换句话说 这种方法是完全同步的,不需要使用 await 操作者,因为它不还原诺言:
configs.normalizeSync({
name: "MyApp",
});
重要内容: 一次a ConfigArray 它已经正常化,不能再进一步改变。 不过,你可以创建一个新的 ConfigArray 并在正态实例中通过以创建非正态副本.
获取文件配置
要获取文件的配置, 请使用 getConfig() 在普通配置阵列上的方法,并在文件名中通过,以获得以下配置:
// pass in filename
const fileConfig = configs.getConfig(
path.resolve(process.cwd(), "package.json"),
);
配置阵列总是返回一个对象, 即使没有匹配给定文件名的配置 。 然后可以检查返回的配置对象,以确定如何进行.
有些事情要记住:
- 如果一个文件名不是绝对路径,则会相对于基础路径目录来解决.
- 返回的配置对象从未有过
files, (中文(简体) ),ignores, (中文(简体) ),basePath,或name属性;对象上唯一的属性将是指定的其他配置选项. - 配置数组缓存配置,所以后续调用到
getConfig()同一文件名将快速查找而不是进行其他计算. - 只有文件名符合条目时才会生成配置
files键。 不匹配配置将无法生成配置files密钥(配置不包含files键仅在另一个配置与 a 时应用files键被应用;没有配置files从未单独申请)。 任意配置files键入为*或结束于/**或者说/*将仅在同一条目中的另一条目中应用files密钥匹配或其他配置匹配.
确定被忽略的路径
您可以使用 isFileIgnored() 方法和在任何文件的路径中传递,例如此示例:
const ignored = configs.isFileIgnored("/foo/bar/baz.txt");
如果以下任何文件属实,则视为忽略 :
- 其父目录被忽略 . 例如,如果
foo进入ignores,则foo/a.js被视为被忽略. - 它有一个被忽略的祖先目录. 例如,如果
foo进入ignores,则foo/baz/a.js被视为被忽略. - 它符合被忽略的文件模式 . 例如,如果
**/a.js进入ignores,则foo/a.js财务报告和审定财务报表foo/baz/a.js被视为被忽略. - 如果匹配条目
files和在ignores。 。 。 . 例如,如果**/*.js进入files财务报告和审定财务报表**/a.js进入ignores,则foo/a.js财务报告和审定财务报表foo/baz/a.js被视为被忽略. - 文件在外边
basePath。 。 。 . 如果basePath实值/usr/me,则/foo/a.js被视为被忽略.
对于目录,请使用 isDirectoryIgnored() 在任何目录的路径中,如此示例中:
const ignored = configs.isDirectoryIgnored("/foo/bar/");
如果下列任何一种情况属实,则被视为被忽略:
- 其父目录被忽略 . 例如,如果
foo进入ignores,则foo/baz被视为被忽略. - 它有一个被忽略的祖先目录. 例如,如果
foo进入ignores,则foo/bar/baz/a.js被视为被忽略. - 它符合被忽略的文件模式 . 例如,如果
**/a.js进入ignores,则foo/a.js财务报告和审定财务报表foo/baz/a.js被视为被忽略. - 如果匹配条目
files和在ignores。 。 。 . 例如,如果**/*.js进入files财务报告和审定财务报表**/a.js进入ignores,则foo/a.js财务报告和审定财务报表foo/baz/a.js被视为被忽略. - 文件在外边
basePath。 。 。 . 如果basePath实值/usr/me,则/foo/a.js被视为被忽略.
重要内容: 类似模式 foo/** 意思是说 foo 财务报告和审定财务报表 foo/ 为: 没有 忽略时 foo/bar 被忽略。 如果你想忽略的话 foo 及其所有子目录,使用图案 foo 或者说 foo/ 内 ignores。 。 。 .
缓存机制
每个 ConfigArray 积极缓存配置对象以避免不必要的工作. 这种缓存有两种方式:
- 以文件为基础的 Caching. 对于被传递到方法的每个文件名,产生的配置都会被缓存到文件名上,这样你总是被保证从中获取相同的对象
getConfig()当你通过相同的文件名时. - 以索引为主的 Caching. 当计算出一个配置时,用于创建配置的配置元素也会被缓存. 因此,如果给定的文件名匹配元素 1、 5 和 7, 由此产生的配置将缓存 :
1,5,7。这样,如果通过另一个匹配相同配置元素的文件,结果已经知道,无需重新计算。 这意味着两个匹配所有相同元素的文件将返回相同的配置getConfig()。 。 。 .
鸣谢
这个项目的设计受到关于ESLint RFC的反馈的影响,并吸收了以下观点:
- 泰迪·卡茨 (@not-an-aardvark) (英语)
- 长岛同仁(@mysticata)
- 凯·卡特多(@kaicataldo)
许可证
Apache 2.0 (英语)
发起人
以下公司,组织,个人支持ESLint的持续维护与发展. 成为发起人 让你的标志在我们的读取器和 网站。 。 。 .



