news 2026/9/23 20:55:56

Stylelint `selector-combinator-allowed-list` 规则完全指南:用白名单约束选择器组合器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Stylelint `selector-combinator-allowed-list` 规则完全指南:用白名单约束选择器组合器

Stylelintselector-combinator-allowed-list规则完全指南:用白名单约束选择器组合器

【免费下载链接】stylelintA mighty CSS linter that helps you avoid errors and enforce conventions.项目地址: https://gitcode.com/gh_mirrors/st/stylelint

selector-combinator-allowed-list是 Stylelint 内置的"选择器组合器白名单"规则,用于限定样式表中允许出现的组合器(如>+~或后代空格),从而从源头约束选择器的书写习惯与可维护性。本文以该规则的官方文档(lib/rules/selector-combinator-allowed-list/README.md)为主体,结合仓库中的规则实现、工具函数与测试用例,讲解它的行为特性、配置方法、底层原理以及与selector-combinator-disallowed-list的搭配使用,帮助你把它准确落地到实际项目中。

规则概述:它检查什么

selector-combinator-allowed-list的功能一句话概括:指定一个允许使用的组合器列表(allowed list)。凡是出现在选择器中的组合器,只要不在该列表中,就会被报告为违规。

CSS 中的组合器主要包括:

组合器写法含义
后代组合器空格()匹配后代元素,如a b
子组合器>匹配直接子元素,如a > b
相邻兄弟组合器+匹配紧邻的下一个兄弟,如a + b
通用兄弟组合器~匹配后续所有兄弟,如a ~ b
列组合器\|\|匹配列(Selectors 4 中定义,兼容性有限)
引用组合器(reference)/for/用于 ID 引用语法,属非标准或特定场景

规则文档用如下代码片段直观标注了检查目标:

a + b {} /** ↑ * This combinator */

箭头所指的+就是本规则检查的对象。例如配置只允许>和空格时,a + b {}a ~ b {}会被报告,而a > b {}a b {}不会。

三条关键行为特性

除了"白名单过滤"这一核心逻辑,规则文档明确声明了三项行为约定,理解它们才能避免配置踩坑。

1. 后代组合器的空白会被规范化为单个空格

This rule normalizes the whitespace descendant combinator to be a single space.

选择器中的后代组合器本质上是"空白",但书写形式可能是一个空格、多个空格、制表符(Tab)甚至换行。规则在比较之前,会先把任意形式的空白统一规范为单个空格再与配置项比对。这意味着:

  • 配置" "(一个空格)时,a ba ba\tba\nb都算作使用了后代组合器,统一按"空格"处理;
  • 反过来,如果白名单里不含空格,那么任何形式的后代组合器(包括换行分隔)都会被视为违规。

该行为由 normalizeCombinator.mjs 实现,实现只有一行正则替换:

export default function normalizeCombinator(value) { return value.replace(/\s+/g, ' '); }

2. 引用组合器(reference combinators)被忽略

This rule ignores reference combinators e.g./for/.

形如/for//deep/这样被/包裹的引用组合器(见 W3C Selectors Level 4 的 idref combinators 规范),不会被本规则检查。也就是说,即使白名单中没有它们,也不会被报告。

判定逻辑位于 isStandardSyntaxCombinator.mjs:只要组合器节点的value/开头或以/结尾,就直接判定为非标准组合器并跳过:

// Ignore reference combinators like `/deep/` if (node.value.startsWith('/') || node.value.endsWith('/')) { return false; }

3. 支持 1 个消息参数:被禁止的组合器

规则文档注明:

This rule supports 1 message argument: the disallowed combinator.

即使用自定义message时,可以通过消息参数把"被拒绝的组合器"注入到提示文案中。结合 docs/user-guide/configure.md 中关于message次要选项的说明,可以这样配置:

/** @type {import('stylelint').Config} */ export default { rules: { "selector-combinator-allowed-list": [ [">", " "], { message: (combinator) => `组合器 "${combinator}" 不在允许列表中,请改用 ">" 或后代空格` } ] } };

如果配置文件是 JSON(不支持函数),可以使用printf风格的占位符:

{ "rules": { "selector-combinator-allowed-list": [ [">", " "], { "message": "Disallowed combinator \"%s\"" } ] } }

消息参数的值来自源码中messages.rejected的定义(lib/rules/selector-combinator-allowed-list/index.mjs):

const messages = ruleMessages(ruleName, { rejected: (combinator) => `Disallowed combinator "${combinator}"`, });

注意:注入的是规范化后的组合器值(即空白已被替换为单个空格),所以触发a\nb {}时消息中的参数是" "而不是原始换行。

选项配置:Array<string>

规则的唯一主要选项(primary option)是一个字符串数组,枚举所有允许出现的组合器:

["array", "of", "combinators"]

例如,只允许子组合器和后代组合器:

{ "rules": { "selector-combinator-allowed-list": [">", " "] } }

被视为问题的写法(Problems)

a + b {}
a ~ b {}

因为+~都不在白名单[">", " "]中。

不被视为问题的写法(Not considered problems)

a > b {}
a b {}
a b {}

最后一个例子值得注意:ab分处两行,但它是合法的后代组合器写法,经空白规范化后等价于单个空格,因此在白名单允许范围内,不构成问题。

该规则还设置了rule.primaryOptionArray = true(index.mjs),并从 lib/rules/index.mjs 的规则注册表中可以看到它与selector-combinator-disallowed-list成对存在。

源码级原理:一条完整的检查链路

阅读 index.mjs 的实现,可以完整还原规则的执行流程,核心链路如下:

  1. 选项校验validateOptions校验主要选项,要求数组内每个元素都是字符串(possible: [isString])。校验失败则直接返回,不产生任何报告。
  2. 遍历规则节点root.walkRules遍历样式树中的每一条 rule。
  3. 过滤非标准规则:调用 isStandardSyntaxRule.mjs,跳过 Less 的&:extend规则以及包含插值(如 SCSS/Stylus 插值语法)等非标准选择器的规则。
  4. 解析选择器:通过 parseSelector.mjs 使用postcss-selector-parser对选择器做 AST 解析;解析失败时记录parseError并跳过。获取原始选择器文本的是 getRuleSelector.mjs,它会优先使用raws.selector.raw(保留源码中的原始空白),保证换行、Tab 等信息不丢失。
  5. 遍历组合器walkCombinators逐个取出选择器中的组合器节点。
  6. 过滤非标准组合器:调用isStandardSyntaxCombinator,除忽略引用组合器外,还忽略位于容器首部或尾部的组合器节点(这些位置不构成真实的关系连接)。
  7. 规范化并比对normalizeCombinator(value)将空白压成单个空格,然后判断primary.includes(normalizedValue)——不在白名单中即触发报告。
  8. 精确定位报告:报告位置使用combinatorNode.sourceIndex作为起点,终点通过index + (raws?.value || value).length计算(index.mjs),确保编辑器中的高亮范围准确落在组合器字符本身。

从代码结构可以推断,规则的报告发生在 rule 节点上,并携带精确的index/endIndex,这与测试断言中的行列号(如line: 1, column: 3)完全对应。

selector-combinator-disallowed-list的对照使用

本规则有一个语义完全相反的孪生规则 selector-combinator-disallowed-list(指定禁止的组合器列表)。两者的源码结构几乎一致,唯一差异在第 47 行附近的判定逻辑:allowed-list 在primary.includes(normalizedValue)true时放行、为false时报告;disallowed-list 则恰好相反,命中列表即报告。

对比项selector-combinator-allowed-listselector-combinator-disallowed-list
语义允许列表,未列出即违规禁止列表,列出即违规
示例配置[">", " "][">", " "]
a > b {}不报告报告
a b {}不报告报告
a + b {}报告不报告
空白规范化相同相同
忽略引用组合器相同相同

两条规则的默认消息文案也都是Disallowed combinator "…",均支持 1 个消息参数。选择哪一条取决于你的风格策略:希望"只许用某几种"就选 allowed-list;希望"明令禁用某几种"(例如禁止深嵌套常用的>或禁止~依赖)就选 disallowed-list。

实战配置建议

基础接入(配置文件)

Stylelint 从当前目录向上查找stylelint.config.js(也支持.mjs.cjs.ts,详见 docs/user-guide/configure.md)。最小可用配置如下:

/** @type {import('stylelint').Config} */ export default { rules: { "selector-combinator-allowed-list": [">", " "] } };

常用组合器取值参考

  • 后代组合器:配置值始终写单个空格" ",因为任何空白都会被规范化;
  • 子组合器:">"
  • 相邻兄弟:"+"
  • 通用兄弟:"~"
  • 列组合器:"||"(如需支持)。

调整严重级别

借助severity次要选项,可以把违规从默认的"error"降级为"warning",适合渐进式推行阶段:

{ "rules": { "selector-combinator-allowed-list": [ [">", " "], { "severity": "warning" } ] } }

局部豁免

与其他规则一致,该规则也支持stylelint-disable系列注释。测试用例(tests/index.mjs)验证了stylelint-disable-next-line的豁免能力:

/* stylelint-disable-next-line selector-combinator-allowed-list */ a + b {}

测试用例印证

仓库为该规则提供了完整的测试覆盖(lib/rules/selector-combinator-allowed-list/tests/index.mjs),可以用这些用例来验证你对规则行为的理解:

配置['>', ' ']时,接受(accept)的写法包括:

  • a {}(无组合器)、a, b {}(逗号分隔,非组合器)
  • a /for/ b {}(引用组合器被忽略)
  • a > b {}a:not(b > c) {}(组合器出现在:not()内同样会被检查)
  • a b {}a\tb {}a\nb {}(各种空白形式的后代组合器)
  • stylelint-disable-next-line注释的a + b {}

拒绝(reject)的写法包括:

  • a ~ b {},报错Disallowed combinator "~",位置1:31:4
  • a:not(b ~ c) {},位置1:91:10(证明伪类内嵌套选择器也会被递归检查)
  • 多行a,\nb + c {},第二行2:3处报告+

另一个测试用例使用字符串配置config: '~'验证了反向场景:a b {}a\tb {}a\n\tb {}全部因后代空格不在白名单中而报告Disallowed combinator " "。这说明尽管规则文档以数组为示例形式,选项校验对"单个字符串"同样兼容,配置时应优先使用数组以保持一致性。

小结

selector-combinator-allowed-list是 Stylelint 组合器管理家族中的"白名单"成员,与selector-combinator-disallowed-list互补。它通过空白规范化、引用组合器豁免、消息参数支持与精确的源码定位,让团队能够以声明式配置统一选择器书写风格。若要深入其实现细节,建议从 规则实现、空白规范化工具、标准组合器判定 三个文件入手,并结合 测试用例 验证边界行为。

【免费下载链接】stylelintA mighty CSS linter that helps you avoid errors and enforce conventions.项目地址: https://gitcode.com/gh_mirrors/st/stylelint

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 20:47:57

ABB机器人系统选项解析:从Advanced RAPID到绝对精度

简介&#xff1a;这是一份面向ABB机器人系统集成工程师、调试与维护人员的PDF文档&#xff0c;系统梳理ABB机器人系统各选项的功能定位与使用方法&#xff0c;涵盖RobotWare操作系统、Advanced RAPID高级编程语言、位功能、数据搜索、别名I/O信号、配置与断电功能等核心知识点&…

作者头像 李华
网站建设 2026/9/23 20:44:56

Photoscan相机标定与畸变改正全流程:从内参原理到工程实践

简介&#xff1a;聚焦PhotoScan&#xff08;现Metashape&#xff09;的相机标定与畸变改正环节&#xff0c;面向航空摄影测量、三维重建的工程师与学生&#xff0c;讲述从原始照片到无畸变影像的关键流程。文档共1个docx文件&#xff0c;大小约2.37MB&#xff0c;以图文步骤呈现…

作者头像 李华
网站建设 2026/9/23 20:41:46

基于机器学习的入侵检测系统Python源码解析与课程设计实战

简介&#xff1a;本资源为基于机器学习的入侵检测系统Python完整项目源码&#xff0c;面向计算机、网络安全及人工智能相关专业的毕业设计、期末大作业与课程设计学生&#xff0c;也适合希望入门机器学习安全应用的开发者。项目以KDD99数据集为基础&#xff0c;涵盖数据预处理、…

作者头像 李华
网站建设 2026/9/23 20:40:09

WebSphere 8.5静默安装与补丁升级实战

简介&#xff1a;针对 WAS 8.5 的静默安装与补丁升级&#xff0c;这份 docx 文档梳理了完整的实操流程&#xff0c;适合需要批量部署 WebSphere Application Server 的系统运维与实施人员。内容包括安装包准备、目录结构规划、Installation Manager 静默安装、通过 repository.…

作者头像 李华
网站建设 2026/9/23 20:39:21

三星M393A2K40EB3-CWE vs M393A2K43EB3-CWE:16GB DDR4 RDIMM选型对比

一、为什么这两款型号值得单独对比 在三星DDR4 RDIMM的产品线中&#xff0c;M393A2K40EB3-CWE和M393A2K43EB3-CWE是两款容易被混淆的16GB型号。两者同为16GB容量、DDR4-3200速率、1.2V电压、288-pin RDIMM封装&#xff0c;连CL延迟都同为22。表面看几乎一样&#xff0c;但料号中…

作者头像 李华
网站建设 2026/9/23 20:38:27

红外小目标飞机检测数据集:从train目录到YOLOv11训练全解析

简介&#xff1a;面向红外小目标飞机检测的数据集&#xff0c;定位于计算机视觉、无人机监控与红外遥感场景&#xff0c;适合算法工程师与科研人员训练和评估以air为单一类别的检测模型。压缩包内共包含两千个文件&#xff0c;整体大小约三十七点四兆字节&#xff0c;文件构成包…

作者头像 李华