跳至主要内容

编写规则

请帮助我们创建、增强和调试我们的规则!

添加规则

您应该准备好贡献代码

定义规则

规则必须是

  • 仅适用于标准 CSS 语法
  • 通常有用;不与特殊模式绑定

并且具有

  • 明确的完成状态
  • 单一目的,不与其他规则重叠

它的名称分为两部分

  • 规则应用于的事物,例如 at-rule
  • 规则检查的内容,例如 disallowed-list

除非它适用于整个源代码,否则没有第一部分。

编写测试

您应该为所有被认为是

  • 问题的模式
  • 被认为是问题的模式

您应该使用

  • 真实的 CSS,避免使用省略号
  • 尽可能少的代码,例如,如果针对选择器,则使用空规则
  • {} 用于空规则,而不是 { }
  • 默认情况下使用 a 类型选择器
  • 默认情况下使用 @media at-rules
  • 默认情况下使用 color 属性
  • 默认情况下使用 red
  • 默认情况下使用 (min-)width 媒体特征
  • foobarbaz 用于名称,例如 .foo#bar--baz

您应该

  • 在测试中改变列和行位置
  • 至少包含一个具有 2 个警告的测试
  • isStandardSyntax* 实用程序中测试非标准语法,而不是在规则本身中测试

常见的被忽略的边缘情况

您应该问问自己,您的规则如何处理

  • 变量(例如 var(--custom-property))?
  • CSS 字符串(例如 content: "anything goes";)?
  • CSS 注释(例如 /* anything goes */)?
  • 空函数(例如 var())?
  • url() 函数,包括数据 URI(例如 url(anything/goes.jpg))?
  • 供应商前缀(例如 @-webkit-keyframes name {})?
  • 大小写敏感(例如 @KEYFRAMES name {})?
  • 伪类组合与伪元素(例如 a:hover::before)?
  • 嵌套(例如,您是否解析 & a {},或者按原样检查它?)?
  • 空格和标点符号(例如,比较 rgb(0,0,0)rgb(0, 0, 0))?

编写规则

编写规则时,您应该

  • 默认情况下使规则严格
  • 添加辅助 ignore 选项以使规则更宽松
  • 不包含特定于 SCSS 等语言扩展的代码

您应该使用

  • PostCSS API
  • 特定于构造的解析器
  • 实用程序函数

PostCSS API

使用PostCSS API 导航和分析 CSS 语法树。我们建议使用 walk 迭代器(例如 walkDecls),而不是使用 forEach 循环遍历节点。

在节点上使用数组方法时,例如 findsomefilter 等,您应该在尝试访问其他属性之前显式检查节点的 type 属性。例如

const hasProperty = nodes.find(
({ type, prop }) => type === "decl" && prop === propertyName
);

PostCSS AST 访问原始字符串时,使用 node.raws 而不是 node.raw()

特定于构造的解析器

根据规则,我们还建议使用

与正则表达式或 indexOf 搜索相比,使用这些解析器有很大的好处(即使它们并不总是性能最好的方法)。

实用程序函数

Stylelint 有实用程序函数,这些函数在现有规则中使用,也可能对您有用。请查看这些函数,以便您知道有哪些可用函数。(如果您有新的函数,您认为可能普遍有用,请将其添加到列表中!)。

使用

  • validateOptions() 实用程序来警告用户有关无效选项
  • isStandardSyntax* 实用程序来忽略非标准语法

添加选项

每个规则都可以接受一个主选项和一个可选的辅助选项。

仅当选项解决请求的用例时才将其添加到规则中,以避免使用未使用的功能污染工具。

主选项

每个规则必须有一个主选项。例如,在

  • "font-weight-notation": "numeric" 中,主选项是 "numeric"
  • "selector-max-type": [2, { "ignoreTypes": ["custom"] }] 中,主选项是 2

规则的命名是为了鼓励使用显式的主选项。例如,font-weight-notation: "numeric"|"named-where-possible" 而不是 font-weight-numeric: "always"|"never"。因为 font-weight-named: "never" 暗示总是使用数字,而 font-weight-notation: "numeric" 使其明确

辅助选项

某些规则需要额外的灵活性来解决边缘情况。这些规则可以使用可选的辅助选项对象。例如,在

  • "font-weight-notation": "numeric" 中没有辅助选项对象
  • "selector-max-type": [2, { "ignore": ["descendant] }] 中,辅助选项对象是 { "ignore": ["descendant] }

最典型的辅助选项是 "ignore": []"except": []

关键字 "ignore""except"

"ignore""except" 选项接受一个预定义关键字选项数组,例如 ["relative", "first-nested", "descendant"]

  • "ignore" 跳过特定模式
  • "except" 反转特定模式的主选项
用户定义的 "ignore*"

某些规则接受一个用户定义的忽略项列表。这采用 "ignore<Things>": [] 的形式,例如 "ignoreAtRules": []

ignore* 选项允许用户在配置级别忽略非标准语法。例如,

  • CSS 模块中引入的 :global:local 伪类
  • SCSS 中引入的 @debug@extend at-rules

方法和语言扩展的出现和消失很快,这种方法确保我们的代码库不会因过时事物的代码而变得杂乱无章。

如果您的规则可以接受数组作为其主选项,则必须通过在规则函数上设置属性 primaryOptionArray = true 来指定这一点。例如

function rule(primary, secondary) {
return (root, result) => {
/* .. */
};
}

rule.primaryOptionArray = true;

module.exports = rule;

这里有一个注意事项:如果您的规则接受一个主选项数组,它也不能接受一个主选项对象。只要有可能,如果您希望您的规则接受一个主选项数组,您应该使数组成为唯一可能性,而不是允许使用各种数据结构。

添加问题消息

以以下形式添加问题消息

  • "预期 [某些内容] [在某些上下文中]"
  • "意外 [某些内容] [在某些上下文中]"

如果规则具有自动修复功能,请使用

  • '预期 "[未修复]" 为 "[已修复]"' 用于短字符串
  • '预期 "[主选项]" ... 表示法' 用于长字符串

添加自动修复

根据规则,可以使用PostCSS API 通过修改 PostCSS AST(抽象语法树)来自动修复规则的问题。

meta.fixable = true 设置为规则

const meta = {
url: /* .. */,
+ fixable: true,
};

context 变量添加到规则参数中

-function rule(primary, secondary) {
+function rule(primary, secondary, context) {
return (root, result) => {
/* .. */
};
}

context 是一个对象,它可能具有三个属性

  • configurationComment(字符串):字符串,用于前缀配置注释,例如 /* stylelint-disable */
  • fix(布尔值):如果为 true,则您的规则可以应用自动修复。
  • newline(字符串):当前 lint 文件中使用的换行符。

如果 context.fixtrue,则使用 PostCSS API 更改 root,并在调用 report() 之前提前返回。

if (context.fix) {
// Apply fixes using PostCSS API
return; // Return and don't report a problem
}

report(/* .. */);

编写 README

每个规则都附带一个以下格式的 README

  1. 规则名称。
  2. 单行描述。
  3. 原型代码示例。
  4. 扩展描述(如有必要)。
  5. 选项。
  6. 被认为是问题的示例模式(对于每个选项值)。
  7. 被认为是问题的示例模式(对于每个选项值)。
  8. 可选选项(如果适用)。

单行描述采用以下形式

  • "禁止 ..." 用于 no 规则
  • "限制 ..." 用于 max 规则
  • "要求 ..." 用于接受 "always""never" 选项的规则
  • "指定 ..." 用于其他所有内容

您应该

  • 从测试中选择示例
  • 仅在示例和选项中使用标准 CSS 语法
  • 添加尽可能少的示例来传达规则的意图,而不是显示边缘情况
  • css 代码围栏之前使用 <!-- prettier-ignore -->
  • 使用“此规则”来指代规则,例如“此规则忽略 ...”
  • 将原型代码示例中的箭头与突出显示的构造的开头对齐
  • 将原型代码示例中的文本尽可能地向左对齐

例如

 @media screen and (min-width: 768px) {}
/** ↑ ↑
* These names and values */

查看其他规则的 README 文件,以了解更常见的模式。

连接规则

最后一步是在以下位置添加对新规则的引用

向规则添加选项

您应该

  1. 准备好贡献代码
  2. 添加新的单元测试来测试该选项。
  3. 更改规则的验证以允许使用新选项。
  4. 向规则添加(尽可能少)逻辑以使测试通过。
  5. 添加有关新选项的文档。

修复规则中的错误

您应该

  1. 准备好贡献代码
  2. 编写失败的单元测试来举例说明错误。
  3. 调整规则,直到这些新测试通过。

弃用规则

弃用规则并不常见。当你这样做时,你必须

  1. stylelintReference 链接指向 GitHub 网站上规则 README 的特定版本,以便它始终可访问。
  2. 添加适当的元数据以将规则标记为已弃用,例如 rule.meta = { deprecated: true }

提高规则的性能

你可以使用以下命令对任何给定规则运行基准测试,并使用任何有效的配置

npm run benchmark-rule -- ruleName ruleOptions [ruleContext]

如果 ruleOptions 参数不是字符串或布尔值,则它必须是包含在引号中的有效 JSON。

npm run benchmark-rule -- value-keyword-case lower
npm run benchmark-rule -- value-keyword-case '["lower", {"camelCaseSvgKeywords": true}]'

如果指定了 ruleContext 参数,则将应用相同的过程

npm run benchmark-rule -- value-keyword-case '["lower", {"camelCaseSvgKeywords": true}]' '{"fix": true}'

该脚本加载 Bootstrap 的 CSS(来自其 CDN)并通过配置的规则运行它。

它最终会打印一些简单的统计信息,如下所示

Warnings: 1441
Mean: 74.17598357142856 ms
Deviation: 16.63969674310928 ms

在编写新规则或重构现有规则时,使用这些度量来确定代码的效率。

Stylelint 规则可以多次重复其核心逻辑(例如,检查庞大 CSS 代码库中每个声明的每个值节点)。因此,值得关注性能并尽力改进它!

提高规则的性能是如果你想要一个快速的小项目,这是一个很好的贡献方式。 尝试选择一个规则,看看你是否可以做些什么来加快它的速度。

确保你在你的拉取请求中包含基准测试测量结果!