ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Stylelint `declaration-block-no-redundant-longhand-properties` 规则完全指南:从配置、判定逻辑到自动修复

Stylelint `declaration-block-no-redundant-longhand-properties` 规则完全指南:从配置、判定逻辑到自动修复 Stylelintdeclaration-block-no-redundant-longhand-properties规则完全指南从配置、判定逻辑到自动修复【免费下载链接】stylelintA mighty CSS linter that helps you avoid errors and enforce conventions.项目地址: https://gitcode.com/gh_mirrors/st/stylelint导读declaration-block-no-redundant-longhand-properties是 Stylelint 内置的一条可自动修复fixable规则用于在声明块中检测完全可以用简写属性shorthand替代的冗余长手属性longhand例如同时书写padding-top/right/bottom/left时提示改用padding。本文以该规则的 官方文档 为骨架结合 规则实现源码、属性映射表 与 测试用例完整讲解规则的触发条件、全部可检测的简写属性清单、ignoreLonghands与ignoreShorthands两个次要选项以及自动修复的内部原理帮助读者在真实项目中准确配置、安全启用并理解其边界行为。规则概述它在检查什么该规则针对的是 CSS 中本可合并书写却拆开书写的冗余声明。例如a { padding-top: 1px; padding-right: 2px; padding-bottom: 3px; padding-left: 4px; }其中四个方向的长手属性完全可以更简洁地写成a { padding: 1px 2px 3px 4px; }规则的判定有一个关键前提只有当长手属性覆盖了简写属性将要设置的全部子属性allthe properties且这些值不是 CSS 通用关键字CSS-wide keywords时才报告问题。CSS 通用关键字包括initial、inherit、unset等源码中以 basicKeywords 集合表示测试中也验证了包含initial、unset、inherit的长手写法不会被判定为冗余见 测试用例 accept 段。换句话说这条规则追求的是表达方式的冗余而非值是否冗余。因此margin: 1px; margin-left: 1px;左侧值与简写重复同样会被视为问题而margin: 1px; margin-left: 2px;左侧值不同则不算问题——因为后者无法用单个简写表达。判定语义的一个重要提醒文档明确强调只要按规范可以用简写书写就视为冗余与任何单个浏览器的实际行为无关。文档给出了经典反例由于 IE 的 Flexbox 实现问题flex简写可能无法安全使用参见 Flexbugs但 IE 场景下flex: 1 1 0%的三个长手属性仍会被此规则报告。如果需要针对这类情况豁免可以结合下文介绍的ignoreShorthands: [/flex/]使用正则忽略。规则支持的全部简写属性清单规则的判定基础是 lib/reference/properties.mjs 中导出的longhandSubPropertiesOfShorthandProperties映射表共 1220 行按字母序排列规则实现通过遍历该表建立长手属性 → 可能的简写属性反向索引见 index.mjs 中 longhandToShorthands 的构建逻辑。该规则能够识别的简写属性包括animationbackgroundborder、border-block、border-block-end、border-block-start、border-bottom、border-color、border-image、border-inline、border-inline-end、border-inline-start、border-left、border-radius、border-right、border-style、border-top、border-widthcolumn-rule、columnsflex、flex-flowfont、font-synthesis、font-variantgap、grid、grid-area、grid-column、grid-gap、grid-row、grid-templateinset、inset-block、inset-inlinelist-stylemargin、margin-block、margin-inlinemaskoutline、overflow、overscroll-behaviorpadding、padding-block、padding-inlineplace-content、place-items、place-selfscroll-margin、scroll-margin-block、scroll-margin-inlinescroll-padding、scroll-padding-block、scroll-padding-inlinetext-decoration、text-emphasis、transition从映射表可以看出某些简写的子属性集合颇具规模例如border简写覆盖了 12 个方向属性加上border-width、border-style、border-color三个次一级简写background覆盖 8 个子属性animation覆盖 8 个子属性。这些集合正是是否覆盖全部子属性判定的数据依据。基本用法true在配置文件中启用该规则的最简形式{ declaration-block-no-redundant-longhand-properties: true }被视为问题的模式a { margin-top: 1px; margin-right: 2px; margin-bottom: 3px; margin-left: 4px; }a { font-style: italic; font-variant: normal; font-weight: bold; font-stretch: normal; font-size: 14px; line-height: 1.2; font-family: serif; }a { -webkit-transition-property: top; -webkit-transition-duration: 2s; -webkit-transition-timing-function: ease; -webkit-transition-delay: 0.5s; }a { margin: 1px; margin-left: 1px; }注意第三个例子带厂商前缀vendor prefix的过渡属性同样被支持。源码中通过vendor.prefix()/vendor.unprefixed()处理前缀见 index.mjs同一前缀下的长手集合会被识别并可合并为-webkit-transition。测试还验证了属性名大小写不敏感MARGIN-LEFT、-WEBKIT-transition-*均可被识别并修复见 测试用例。不视为问题的模式a { margin: 1px 2px 3px 4px; }a { font: italic normal bold normal 14px/1.2 serif; }a { -webkit-transition: top 2s ease 0.5s; }a { margin-top: 1px; margin-right: 2px; }a { margin-top: 1px; margin-right: 2px; margin-bottom: 3px; }a { margin: 1px; margin-left: 2px; }后三组之所以不报错前两组只覆盖了margin四个方向中的部分未覆盖全部子属性最后一组虽然同时出现简写与长手但长手值与简写值不同并非冗余。次要选项一ignoreLonghands当某个简写的个别子属性在项目中需要独立书写时可以用ignoreLonghands忽略指定长手属性{ ignoreLonghands: [array, of, properties] }例如text-decoration-thickness和background的size、origin、clip三个子属性无法安全地合并进简写background-size在background简写中必须紧跟background-position并以斜杠分隔配置为{ declaration-block-no-redundant-longhand-properties: [ true, { ignoreLonghands: [ text-decoration-thickness, background-size, background-origin, background-clip ] } ] }在此配置下以下模式仍视为问题因为被忽略的属性恰好不在其中a { text-decoration-line: underline; text-decoration-style: solid; text-decoration-color: purple; }a { background-repeat: repeat; background-attachment: scroll; background-position: 0% 0%; background-color: transparent; background-image: none; background-size: contain; background-origin: border-box; background-clip: text; }而以下模式不再视为问题冗余部分之外的属性已被忽略剩余属性无法构成完整简写a { text-decoration: underline solid purple; text-decoration-thickness: 1px; }a { background: none 0% 0% repeat scroll transparent; background-size: contain; background-origin: border-box; background-clip: text; }第二个示例的意义在于background-size出现在background简写之后且值不同配合忽略项使整段代码被放行。源码中ignoreLonghands的解析位于 index.mjs 与prefixedShorthandData过滤逻辑index.mjs被忽略的长手属性既不会参与覆盖全部子属性的计数也不会参与合并。次要选项二ignoreShorthandsignoreShorthands用于整体忽略某个简写及它对应的所有长手组合支持字符串数组和正则表达式{ ignoreShorthands: [array, of, shorthands, /regex/] }例如忽略padding以及所有以border开头的简写{ declaration-block-no-redundant-longhand-properties: [ true, { ignoreShorthands: [padding, /border/] } ] }以下模式在此配置下均不视为问题a { padding-top: 20px; padding-right: 10px; padding-bottom: 30px; padding-left: 10px; }a { border-top-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-right-width: 1px; }a { border-top-color: green; border-top-style: double; border-top-width: 7px; }正则在源码中通过optionsMatches工具匹配index.mjs因此文档开头提到的ignoreShorthands: [/flex/]可以一键豁免全部 Flexbox 相关简写。两个次要选项都通过validateOptions校验index.mjsignoreShorthands接受字符串或正则ignoreLonghands仅接受字符串。消息message与告警信息该规则支持最多 2 个消息参数对应的消息定义在 index.mjsexpected: (property)—— 当一组长手属性可合并为简写时报告参数为简写属性名消息形如Expected shorthand property marginunexpectedLonghand: (longhand, shorthand)—— 当简写之后又出现值完全相同的冗余长手时报告参数为长手属性与简写属性消息形如Redundant longhand property margin-left after shorthand property margin。两种消息对应两种触发路径前者是多个长手凑齐一个简写对应messages.expected后者是先写简写、再写同值长手对应messages.unexpectedLonghand见 index.mjs。在测试用例中可看到messages.expected(margin)的实际断言。自动修复fix能力与边界该规则的meta.fixable标记为trueindex.mjs可通过 CLI 的--fix或配置中的fix选项 自动修复大部分问题。修复策略分为三类默认合并按longhandSubPropertiesOfShorthandProperties中子属性的声明顺序将长手值按序拼接为简写值。例如margin-top/right/bottom/left修复为margin: 20px 10px 30px 40px;。自定义解析器customResolvers某些简写无法靠简单拼接还原源码为font、font-synthesis、grid-column、grid-row、grid-template、transition六个简写注册了专用解析函数见 index.mjs。典型如fontline-height必须以斜杠紧跟font-sizesize/line-height故解析器拼接出font: italic normal bold normal .8em/1.2 Arial;测试见 index.mjs 测试文件transition需按transition-property列表数量对 duration/timing/delay 做循环补齐。有意的修复豁免源码注释明确说明当background简写同时存在background-size时不会自动修复——因为background-size在简写中必须紧跟background-position并加斜杠直接拼接会生成非法 CSS见 index.mjs 中 resolveShorthandValue 的 TODO 说明。此时规则仍会报告问题但fix返回undefined表示无法安全修复。此外修复还有以下安全保护!important混用保护hasMixedImportant会检查集合内声明是否全部一致地带/不带!important只要存在混用部分带、部分不带就不合并index.mjs 与 hasMixedImportant 实现CSS 通用关键字豁免任一长手值为initial/inherit/unset等基础关键字时直接跳过index.mjs因为简写形式无法表达单个方向的这类关键字重叠简写处理border-width/border-style/border-color/border-top等会互相重叠的简写集合OVERLAPPING_SHORTHANDS见 index.mjs在一次修复后会从收集结果中剔除已消费的属性避免重复合并产生冲突——测试中 12 个方向属性被修复为border-width、border-color、border-style三条声明见 测试用例。与fix、--fix的配合及实践建议在实际项目中使用时命令行执行npx stylelint **/*.css --fix即可让规则自动合并冗余长手属性详见fix选项文档默认strict模式仅在无语法错误时修复lax模式配合 postcss-safe-parser 允许在存在语法错误时尽力修复若使用 Node.js API自动修复后的代码可通过返回对象的code属性获取规则还支持computeEditInfo--compute-edit-info, --cei计算更细粒度的编辑信息测试中通过computeEditInfo: true验证了range与text见 测试文件头部。实践层面的建议开启前先评估项目中是否有因历史浏览器兼容而必须保留长手写法的场景如旧的 Flexbox 写法如有用ignoreShorthands: [/flex/]之类正则精准豁免background-size、text-decoration-thickness等无法安全合并进简写的子属性建议通过ignoreLonghands显式放行避免出现报告了却无法自动修复的告警堆积若追求报告即修复可结合 CI 中先跑--fix再跑纯检查的流程确保合并结果已落盘。总结declaration-block-no-redundant-longhand-properties是 Stylelint 中可自动修复规则的代表作之一它依赖 属性映射表 完成长手是否凑齐简写的精确判定通过ignoreLonghands/ignoreShorthands提供灵活的豁免能力并借助自定义解析器在font、transition、grid等复杂简写场景下生成正确合并结果。理解其只看子属性覆盖是否完整、不看浏览器实际行为的判定语义以及混用!important、含 CSS 通用关键字、含background-size时不修复的安全边界就能在真实项目中安全地启用它让样式表更简洁、更易维护。【免费下载链接】stylelintA mighty CSS linter that helps you avoid errors and enforce conventions.项目地址: https://gitcode.com/gh_mirrors/st/stylelint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表