eslint-plugin-unicorn no-shorthand-property-overrides 规则:快照报告解读与 CSS 简写属性覆盖检测原理

eslint-plugin-unicorn no-shorthand-property-overrides 规则:快照报告解读与 CSS 简写属性覆盖检测原理 eslint-plugin-unicorn no-shorthand-property-overrides 规则快照报告解读与 CSS 简写属性覆盖检测原理【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn本文以test/snapshots/no-shorthand-property-overrides.js.md这份 AVA 快照报告为主体完整收录其记录的 11 个无效invalidCSS 用例及规则产生的精确错误消息并结合 规则实现、测试用例 与规则文档 深入讲解no-shorthand-property-overrides规则的工作机制它如何维护简写/展开属性映射表、如何按声明块检测覆盖、如何处理厂商前缀与大小写以及如何在 ESLint 中为 CSS 文件启用该规则。快照报告是什么test/snapshots/no-shorthand-property-overrides.js.md 是对 测试文件 的 AVA 快照报告文件开头声明了其与二进制快照的对应关系The actual snapshot is saved inno-shorthand-property-overrides.js.snap. Generated by AVA.也就是说.md报告是供人阅读的可视化版本实际做测试断比对的快照保存在 test/snapshots/no-shorthand-property-overrides.js.snap 中。报告中的每一条invalid(n): 代码小节都包含两部分Input被 Linter 检查的 CSS 输入␊表示换行符Error x/y规则报告的消息含行内列位置^下划线标出错列范围与消息文本。这些输入全部来自 测试文件 中的invalid数组通过 测试工具 中的test.snapshot(...)驱动执行并绑定 CSS 语言插件eslint/css即css/css语言使 ESLint 能够解析 CSS 语法树。规则机制简写属性覆盖检测核心消息与映射表规则实现 顶部定义了唯一的消息模板const MESSAGE_ID no-shorthand-property-overrides; const messages { [MESSAGE_ID]: The shorthand property {{shorthand}} overrides the previously declared {{longhand}} property., };这正是快照报告中每一条Message:文本的来源。规则内置了一张约 50 个条目的简写→展开属性映射表shorthandPropertiesrules/no-shorthand-property-overrides.js#L6-L114把简写属性名映射到它覆盖的所有 longhand 属性的Set。表中涵盖了快照报告中全部 11 个用例涉及的简写属性例如简写属性覆盖的 longhand节选paddingpadding-top、padding-right、padding-bottom、padding-leftbackgroundbackground-image、background-size、background-position、background-repeat、background-origin、background-clip、background-attachment、background-colorborder12 个border-{边}-{width/style/color}、border-width、border-style、border-color以及border-image全家族border-image-source等 5 个fontfont-style、font-variant、font-weight、font-size、line-height、font-family等 19 个transitiontransition-property、transition-duration、transition-timing-function、transition-delaygrid-rowgrid-row-start、grid-row-endinset-blockinset-block-start、inset-block-endscroll-paddingscroll-padding-top、scroll-padding-right、scroll-padding-bottom、scroll-padding-left此外映射表还包含animation、border-radius、columns、flex、font-variant、grid、mask、text-decoration、place-items等完整 CSS 简写体系可对照 源码 L6-L114 查看完整清单。检测算法块内顺序扫描create函数监听Block节点即 CSS 声明块逻辑如下rules/no-shorthand-property-overrides.js#L121-L157遍历块内每个Declaration子节点把属性名小写化用正则/^-\w-/u提取厂商前缀如-webkit-得到去前缀的属性名将该属性名记入declarationsMap以全小写名为键保留原始拼写为值用于消息展示若该属性是简写则遍历它覆盖的所有 longhand检查declarations中是否已存在「同前缀 同 longhand」的先前声明若存在立即上报错误消息中shorthand使用简写声明的原始拼写longhand使用先前声明的原始拼写。由此可以解释三个关键行为只检测同一声明块内的覆盖跨选择器不同块不检查大小写不敏感比较前先toLowerCase()但报错时保留原始大小写前缀必须匹配-webkit-transition-property只会被-webkit-transition触发不会被无前缀的transition触发反之亦然。该规则没有自动修复output恒为null元信息声明为type: problem、recommended: unopinionated并注册了js/js与css/css两种语言rules/no-shorthand-property-overrides.js#L159-L176。在 readme.md 的规则表中该规则在unopinionated配置中标记为启用✅。快照报告逐条解读11 个 invalid 用例以下按报告顺序还原全部 11 个无效用例每个用例均包含输入、错误列位置与消息。1. padding 覆盖 padding-lefta { padding-left: 10px; padding: 20px; }报告错误 1 | a { padding-left: 10px; padding: 20px; } | ^^^^^^^^^^^^^ The shorthand property padding overrides the previously declared padding-left property.下划线从padding: 20px的简写属性名起含简写与值精确标出引发覆盖的声明。2. background 覆盖 background-repeata { background-repeat: no-repeat; background: url(lion.png); }| ^^^^^^^^^^^^^^^^^^^^^^^^^ The shorthand property background overrides the previously declared background-repeat property.3. border 覆盖 border-image-sourcea { border-image-source: url(border.png); border: 1px solid; }| ^^^^^^^^^^^^^^^^^ The shorthand property border overrides the previously declared border-image-source property.这个用例能成立是因为映射表中border的 longhand 列表显式包含border-image-source等border-image-*属性rules/no-shorthand-property-overrides.js#L9-L34——这符合 CSS 规范border简写会把border-image-*重置为初始值。4. font 覆盖 font-variant-capsa { font-variant-caps: small-caps; font: 1em sans-serif; }| ^^^^^^^^^^^^^^^^^^^^ The shorthand property font overrides the previously declared font-variant-caps property.font是映射表中最长的条目之一19 个 longhandfont-variant-caps位列其中。5. transition 覆盖 transition-propertya { transition-property: opacity; transition: opacity 1s linear; }| ^^^^^^^^^^^^^^^^^^^^^^^^^ The shorthand property transition overrides the previously declared transition-property property.6. grid-row 覆盖 grid-row-starta { grid-row-start: 1; grid-row: 1 / 3; }| ^^^^^^^^^^^^^^^ The shorthand property grid-row overrides the previously declared grid-row-start property.7. inset-block 覆盖 inset-block-enda { inset-block-end: 1px; inset-block: 2px; }| ^^^^^^^^^^^^^^^^ The shorthand property inset-block overrides the previously declared inset-block-end property.8. scroll-padding 覆盖 scroll-padding-lefta { scroll-padding-left: 1px; scroll-padding: 2px; }| ^^^^^^^^^^^^^^^ The shorthand property scroll-padding overrides the previously declared scroll-padding-left property.9. 全大写属性名大小写不敏感检测a { PADDING-LEFT: 10px; PADDING: 20px; }| ^^^^^^^^^^^^^ The shorthand property PADDING overrides the previously declared PADDING-LEFT property.检测前先小写化PADDING→padding从而命中映射表而消息中的PADDING、PADDING-LEFT保留了源文件中的原始拼写——对应实现中declarations.set(property, declaration.property)用原始拼写做值的设计。10. 厂商前缀匹配-webkit-transition 覆盖 -webkit-transition-propertya { -webkit-transition-property: opacity; -webkit-transition: opacity 1s linear; }| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The shorthand property -webkit-transition overrides the previously declared -webkit-transition-property property.前缀通过正则/^-\w-/u提取且查找 longhand 时使用vendorPrefix longhand拼接键rules/no-shorthand-property-overrides.js#L116、L141-L154因此只有同前缀的声明对才会互相触发。11. 一条简写触发多条错误a { padding-top: 10px; padding-left: 20px; padding: 30px; }该用例产生2 条错误Error 1/2与Error 2/2分别指向padding-top与padding-left 1 | a { padding-top: 10px; padding-left: 20px; padding: 30px; } | ^^^^^^^^^^^^^ The shorthand property padding overrides the previously declared padding-top property. 1 | a { padding-top: 10px; padding-left: 20px; padding: 30px; } | ^^^^^^^^^^^^^ The shorthand property padding overrides the previously declared padding-left property.两条错误的下划线位置完全相同都指向简写声明本身但longhand各不相同——因为padding的映射表同时包含padding-top和padding-left遍历Set时逐一命中已登记的先前声明。对照 valid 用例规则不报什么测试文件 中同样定义了 8 个 valid 用例它们与 invalid 用例互为镜像共同界定了规则的边界/* 1. 顺序正确简写在前longhand 在后 —— 合法覆盖方向 */ a { padding: 20px; padding-left: 10px; } /* 2. 跨声明块不同选择器之间不检查 */ a { padding-left: 10px; } b { padding: 20px; } /* 3. 前缀不匹配无前缀的 transition 不覆盖 -webkit-transition-property */ a { -webkit-transition-property: opacity; transition: opacity 1s linear; } /* 4. 前缀不匹配反向 */ a { transition-property: opacity; -webkit-transition: opacity 1s linear; } /* 5. CSS 自定义属性-- 开头不算普通属性 */ a { --padding-left: 10px; padding: 20px; } /* 6. CSS 转义属性名被有意忽略 */ a { p\61 dding-left: 10px; padding: 20px; } /* 7. 无关属性与简写共存 */ a { color: red; padding: 20px; } /* 8. 嵌套 media 块各自独立跨块不检查 */ a { padding-left: 10px; media (width 0px) { padding: 20px; } }其中第 6 条与 规则文档 中 “intentionally ignores CSS-escaped property names” 的说明一致实现中直接使用declaration.property而 CSS 解析器对转义属性的property值带转义序列无法命中映射表。第 8 条则验证了on(Block)是按块独立建declarationsMap 的——嵌套media是另一个Block节点不共享外层声明记录。在项目中启用该规则该规则作用于 CSS 文件需借助eslint/css语言插件。规则文档 给出的推荐配置为import css from eslint/css; import {defineConfig} from eslint/config; import unicorn from eslint-plugin-unicorn; export default defineConfig([ { files: [**/*.css], plugins: { css, unicorn, }, language: css/css, rules: { unicorn/no-shorthand-property-overrides: error, }, }, ]);规则通过 rules/index.js 导出规则名为unicorn/no-shorthand-property-overrides。由于它在unopinionated推荐集中启用meta.docs.recommended: unopinionated启用对应推荐配置的项目会自动获得该检查。小结这份快照报告完整固化了no-shorthand-property-overrides规则对外可见的全部行为契约消息模板、错误列位置指向简写声明、大小写保留、前缀精确匹配、同块限定、多 longhand 命中多报。理解它的实现只需抓住三点——shorthandProperties映射表L6-L114、前缀提取正则L116、块内顺序扫描 declarationsMapL121-L157。该规则提醒开发者CSS 简写会静默重置所有被省略的 longhand把简写放在 longhand 之前或用显式 longhand 组合替代才能避免意外的样式丢失。【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考