ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

stylelint 的 function-disallowed-list 规则:禁用 CSS 函数的黑名单配置实战与源码解析

stylelint 的 function-disallowed-list 规则:禁用 CSS 函数的黑名单配置实战与源码解析 stylelint 的 function-disallowed-list 规则禁用 CSS 函数的黑名单配置实战与源码解析【免费下载链接】stylelintA mighty CSS linter that helps you avoid errors and enforce conventions.项目地址: https://gitcode.com/gh_mirrors/st/stylelintstylelint 的function-disallowed-list规则允许你指定一组禁止在样式表中出现的 CSS 函数如scale()、rgba()凡是命中黑名单的函数调用都会触发警告。本文以该规则为核心完整讲解它的配置选项、匹配语义、嵌套场景与自定义消息并结合 lib/rules/function-disallowed-list/index.mjs 的源码实现与 lib/rules/function-disallowed-list/tests/index.mjs 的测试用例让你不仅会配置还理解它底层如何解析、匹配与报告问题。规则概述管住样式里的危险函数CSS 函数种类繁多从颜色函数rgb()、rgba()、hsl()到变换函数scale()、rotate()、translateX()再到渐变函数linear-gradient()、radial-gradient()。团队可能出于兼容性、性能或代码风格约定希望某些函数不再被使用。function-disallowed-list就是为此设计的黑名单规则a { transform: scale(1); } /** ↑ * 这个函数会被命中黑名单并报告 */它与配套的白名单规则 function-allowed-list 互补一个只许用这些一个不许用这些。两个规则都已注册在 lib/rules/index.mjs 的规则清单中可直接通过配置文件启用。配置方式数组形式的黑名单该规则的选项为Arraystring数组中的每一项可以是函数名字符串例如scale以/开头和结尾的正则表达式字符串例如/^(-moz-)?linear-gradient$/。{ function-disallowed-list: [scale, rgba, /^(-moz-)?linear-gradient$/] }将上面的配置应用到以下样式三处函数调用会全部被判定为问题a { transform: scale(1); } a { color: rgba(0, 0, 0, 0.5); } a { background: red, -moz-linear-gradient(45deg, blue, red); }而不包含任何禁用函数的样式则不会报错a { background: red; }在tests/index.mjs 的测试中上述三组命中场景对应的报告位置分别为第 1 行第 16–21 列scale、第 1 行第 12–16 列rgba与第 1 行第 22–42 列-moz-linear-gradient说明规则会精确地定位到函数名本身而非整条声明。匹配语义字符串精确匹配正则按需使用字符串大小写敏感的精确匹配当配置项是普通字符串时规则对函数名做严格相等比较value comparison见 matchesStringOrRegExp.mjs因此默认大小写敏感。测试用例明确覆盖了这一行为配置[scale]时scale(1)报错而SCALE(1)、sCaLe(1)均被接受见测试第 13–17 行。正则字符串以/包裹即被识别为正则任何以/开头、以/结尾的配置项会被解释为正则表达式若以/regex/i形式结尾还会附加i修饰符实现忽略大小写匹配。同样在 matchesStringOrRegExp.mjs 中可以看到字符串形式正则会被new RegExp()重新构造。例如配置/^(-moz-)?linear-gradient$/则linear-gradient(...)与-moz-linear-gradient(...)都会被命中而-webkit-radial-gradient(...)不会。测试第 29 行也验证了这一点。正则对象大小写混合场景除了字符串配置文件如果是 JS 格式也可以直接传入RegExp对象。测试第 153 行的config: [/rgb/]会同时命中rgb()与rgba()因为/rgb/是子串匹配而不会命中hsl()。测试第 184 行的组合配置[skewx, translateX, SCALEX, /rotate/i, /MATRIX/]则展示了一个更贴近实战的混合用法字符串skewx仅命中全小写的skewx(10deg)不命中stewX(10deg)字符串translateX仅命中精确大小写的translateX(5px)translateY(5px)不受影响字符串SCALEX仅命中全大写的SCALEX(1)scaleX(1)不受影响正则/rotate/i大小写不敏感rotatex、rotateX、ROTATEX全部命中正则/MATRIX/子串匹配MATRIX3d(a1)命中而matrix3d(a1)小写不命中。提示字符串黑名单适合精确禁用少数函数正则黑名单适合批量拦截一类函数如所有带厂商前缀的渐变、所有translate*变换。源码原理一次函数调用如何被揪出来规则实现位于 lib/rules/function-disallowed-list/index.mjs整个检查流程可以拆解为五步1. 校验选项规则通过validateOptions检查主选项是否为字符串或正则的数组非法配置会在启动时给出配置错误而不是静默失效const validOptions validateOptions(result, ruleName, { actual: primary, possible: [isString, isRegExp], });同时规则声明了rule.primaryOptionArray true表明主选项必须是数组形式。2. 遍历所有声明通过root.walkDecls遍历样式树中的每一条decl声明并用decl.value.includes(()做快速过滤——没有括号的值不可能包含函数调用直接跳过避免无谓的解析开销。3. 用 postcss-value-parser 解析值对候选声明使用postcss-value-parser将值解析为节点树并walk每个节点。借助 typeGuards.mjs 中的isValueFunction判断节点类型是否为function。4. 排除非标准语法函数isStandardSyntaxFunction.mjs 会排除三种看起来像函数但不是普通 CSS 函数的节点没有名字的括号内容如 Sass 列表测试第 38 行的$scale: (value, value2)正是此类场景会被忽略#{...}形式的插值如 Sass/Less 插值${...}与反引号形式的 CSS-in-JS 插值。这一设计保证了规则不会误伤预处理器变量、插值表达式和 CSS-in-JS 模板语法。5. 匹配并精确报告函数名与黑名单经matchesStringOrRegExp比对命中后利用declarationValueIndex(decl) sourceIndex计算出函数名在整条声明中的起始位置调用report输出警告。从测试的column断言可以看到报告位置精确指向函数名例如scale(1)报在第 16 列起、transform: scale(1)中的空格变化会同步改变列号这对编辑器的 inline 提示非常友好。嵌套场景函数套函数也逃不掉CSS 中函数可以互相嵌套例如a { color: color(rgba(0, 0, 0, 0.5) lightness(50%)); }valueParser的walk会遍历所有层级的函数节点因此嵌套在color()内部的rgba()同样会被检测。测试第 93 行正是该场景配置[rgba, scale, ...]时color(rgba(...) lightness(...))中的rgba被精确报告在第 18–22 列media规则内的声明测试第 108 行同样会被覆盖因为walkDecls作用于整棵样式树。自定义提示消息让报错更有指导性该规则支持 1 个 message 参数被禁用的函数名。你可以在配置文件的 secondary options 中使用message字段定制提示语。消息格式与 docs/user-guide/configure.md 中描述的通用机制一致在 JS/TS 格式的配置中message可以是接收函数名参数的函数export default { rules: { function-disallowed-list: [ [scale, rgba], { message: (name) 请勿使用已废弃的函数 ${name}改用推荐写法 } ] } };在 JSON 配置中使用printf风格的%s占位符{ rules: { function-disallowed-list: [ [scale, rgba], { message: Disallowed function \%s\ is not allowed in this project } ] } }规则默认消息由 ruleMessages.mjs 统一拼接而成即Disallowed function ${name} (function-disallowed-list)其中(function-disallowed-list)后缀会自动追加便于在多个规则同时报错时快速定位来源。如何验证与调试仓库为每条规则都配备了完整的测试套件规则测试位于 lib/rules/function-disallowed-list/tests/index.mjs覆盖了大小写敏感、正则字符串、正则对象、嵌套函数、Sass 列表忽略、media内声明、报告行列位置等场景。如果你想在本地验证自己配置的效果可以使用 stylelint CLI 配合一个最小配置运行npx stylelint **/*.css --config .stylelintrc.json或在 Node 中通过stylelint.lintAPI 检查参见 docs/user-guide/node-api.md。新增黑名单条目后建议同时为它补一条 accept/reject 测试遵循仓库测试规范详见 docs/contributor-guide/rules.md。实战建议与注意事项与白名单规则二选一function-disallowed-list与 function-allowed-list 功能相反同时启用会让配置难以维护建议根据团队风格选择其一。注意大小写语义字符串匹配默认大小写敏感容易漏掉Scale()之类的写法若想彻底封禁某函数推荐使用带i修饰符的正则如/^scale$/i。善用正则批量拦截针对渐变、变换、颜色等函数族编写正则比逐个枚举字符串更省心例如/^(-webkit-|-moz-)?(linear|radial)-gradient$/。预处理与 CSS-in-JS 不受影响Sass 列表、插值表达式和 CSS-in-JS 模板语法已被 isStandardSyntaxFunction.mjs 显式排除不会产生误报。配合自定义 message 提供迁移指引黑名单规则的价值不仅在禁止更在于告知替代方案善用message参数告诉开发者该改用哪个函数能显著降低规则上线时的抵触成本。【免费下载链接】stylelintA mighty CSS linter that helps you avoid errors and enforce conventions.项目地址: https://gitcode.com/gh_mirrors/st/stylelint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进