ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

eslint-plugin-unicorn 快照测试深度解析:prefer-dom-node-text-content 规则如何把 `.innerText` 改为 `.textContent`

eslint-plugin-unicorn 快照测试深度解析:prefer-dom-node-text-content 规则如何把 `.innerText` 改为 `.textContent` eslint-plugin-unicorn 快照测试深度解析prefer-dom-node-text-content 规则如何把.innerText改为.textContent【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn本篇技术指南以 eslint-plugin-unicorn 仓库中prefer-dom-node-text-content规则的 AVA 快照测试报告为主体完整讲解该规则覆盖的 15 个违规场景、每个场景的错误定位与自动修复输出并结合规则源码与测试用例剖析其检测原理成员访问监听 解构模式监听 非 DOM 节点类型过滤。读完本文你将理解如何通过快照报告逆向读懂一条 ESLint 规则的完整行为边界包括可选链、赋值、重命名解构、默认值与嵌套解构等边界情形。快照报告是什么规则行为的“逐帧录像”test/snapshots/prefer-dom-node-text-content.js.md是一份由 AVA 测试框架自动生成的快照报告Snapshot report它忠实记录了test/prefer-dom-node-text-content.js中全部 15 个 invalid 用例的运行结果——包括输入代码、错误消息、定位列号以及编辑器可用的自动修复建议。真实的快照数据保存在同目录的prefer-dom-node-text-content.js.snap文件中.md版本是其可读性更强的渲染副本。报告头部给出了三条关键元信息被测文件test/prefer-dom-node-text-content.js即规则的单测入口快照本体prefer-dom-node-text-content.js.snap生成工具AVAavajs.devESLint 生态中常用的 Node.js 测试运行器。每条用例在报告中以invalid(N): 代码的标题出现随后依次展示 Input输入源码与行号标注和 Error 1/1错误详情消息文本、^定位以及Suggestion建议修复。规则核心为什么必须用.textContent而不是.innerText该规则的官方文档位于 docs/rules/prefer-dom-node-text-content.md其宗旨是对 DOM 节点强制使用.textContent而非.innerText。理由来自 MDN 对Node.textContent的说明.textContent在性能上更优且更新文本内容时行为更可预测.innerText受 CSS 样式与排版影响其读取结果可能因渲染状态而异。规则同时提示两者存在语义差异例如.innerText会触发重排、只返回可见文本在个别场景下不能直接等价替换。规则元数据见 rules/prefer-dom-node-text-content.js显示type: suggestion属于建议型规则报告的问题是代码风格/可维护性问题而非确定性 bugrecommended: unopinionated默认纳入unopinionated配置集该文档标题旁的 ☑️ 标记hasSuggestions: true规则的修复以“编辑器建议editor suggestions”形式提供需要开发者手动确认而非自动应用languages: [js/js]作用于 JavaScript 文件。15 个违规用例全景成员访问与解构两大阵营快照报告完整呈现了规则能够捕获的全部 15 个违规场景。它们可以清晰地划分为两组成员表达式MemberExpression访问与对象解构模式ObjectPattern中的属性键。第一组成员访问用例 1–4用例输入修复建议1node.innerText;node.textContent;2node?.innerText;node?.textContent;3node.innerText foo;node.textContent foo;4innerText.innerText;innerText.textContent;这组用例验证了规则对三种读取/写入形式的覆盖普通读取用例 1成员访问出现在表达式语句中错误定位在node.innerText的innerText部分快照中以^^^^^^^^^标记列号与属性名对齐可选链读取用例 2node?.innerText同样命中修复保留?.前缀只替换属性名属性赋值用例 3node.innerText foo的写入场景同样被拦截修复后变为node.textContent foo同名链式访问用例 4innerText.innerText只报告内层innerText对象上访问的属性而不会把独立的innerText变量误判为违规——这与下方 valid 用例innerText.textContent相互印证说明规则只关心属性访问不关心标识符本身叫什么名字。第二组对象解构模式用例 5–15解构场景是规则最精细的部分快照覆盖了简写、带尾逗号、重命名、默认值、赋值模式、函数参数与嵌套解构的全部组合用例输入修复建议5const {innerText} node;const {textContent: innerText} node;6const {innerText,} node;const {textContent: innerText,} node;7const {innerText: text} node;const {textContent: text} node;8const {innerText default text} node;const {textContent: innerText default text} node;9const {innerText: text default text} node;const {textContent: text default text} node;10({innerText} node);({textContent: innerText} node);11({innerText: text} node);({textContent: text} node);12({innerText default text} node);({textContent: innerText default text} node);13({innerText: text default text} node);({textContent: text default text} node);14function foo({innerText}) {return innerText}function foo({textContent: innerText}) {return innerText}15for (const [{innerText}] of elements);for (const [{textContent: innerText}] of elements);从快照中可以提炼出修复策略的规律简写属性必须展开{innerText}这种简写形式无法直接改名否则局部变量名会丢失因此修复为{textContent: innerText}——保留原变量名只把“来源键”改为textContent已重命名的属性只换键名{innerText: text}修复为{textContent: text}{innerText: text default text}修复为{textContent: text default text}默认值default text原样保留赋值模式同样命中用例 10–13 展示了解构赋值语句({innerText} node)的四种变体修复逻辑与变量声明一致函数参数与嵌套解构不遗漏用例 14函数形参和用例 15for...of中的嵌套数组解构[{innerText}]表明无论解构嵌套多深、出现在什么位置只要对象模式中的属性键是innerText都会被规则捕获。规则源码如何实现这些检测两条监听路径规则注册了两个独立的 AST 监听器见 rules/prefer-dom-node-text-content.jsMemberExpression监听器第 32–54 行负责捕获node.innerText形式的成员访问。它使用仓库自带的 AST 工具isMemberExpression精确匹配property: innerText。该工具位于 rules/ast/is-member-expression.js支持对property、computed、optional等维度做约束匹配当只传property时computed默认被约束为false——这正是测试中node[innerText]字符串计算属性和node[innerText]变量计算属性被视为 valid 的原因。Identifier监听器第 56–86 行负责捕获解构模式中的innerText键。它有一组严格的父链校验条件节点必须名为innerText、是Property的key非计算属性、kind为init、且外层是ObjectPattern。这条链路保证了const foo {innerText}普通对象字面量、const {[innerText]: text} node计算键等场景不会被误报。非 DOM 节点的类型过滤两条监听路径在报告错误前都调用isKnownNonDomNode来自 rules/utils/is-dom-node.js做反向排除如果能够推断出对象不是DOM 节点就直接放行。这样避免了把接口/普通对象上的同名属性误报为违规。is-dom-node.js基于通用类型推断引擎createTypeCheckers见 rules/utils/type-helpers.js构建将CharacterData、Document、DocumentFragment、Element、HTMLElement、Node、SVGElement、Text视为 DOM 节点类型名集合通过变量定义追踪、类型注解、导入绑定等途径推断表达式类型。prefer-dom-node-text-content.js中还额外实现了isKnownNonDomObjectPattern第 11–26 行专门为解构模式追查其初始化器VariableDeclarator.init或赋值右侧AssignmentExpression.right是否确认为非 DOM 节点。建议型修复Suggestion两处监听器都返回messageId: error与suggest数组其中唯一的建议项messageId: suggestion提供修复函数成员访问路径直接fixer.replaceText(node, textContent)第 50 行解构路径则需要区分简写与否简写时替换为textContent: innerText非简写时只替换键名第 79–82 行。这与快照中每条用例末尾的Suggestion 1/1输出一一对应。不误报的边界valid 用例对照快照报告只收录 invalid 用例但 test/prefer-dom-node-text-content.js 中的 valid 列表同样关键它划定了规则“不该管”的边界裸标识符innerText;、innerText true;、innerText.textContent——innerText作为普通变量名出现时不触发计算属性访问node[innerText];、node[innerText];——计算成员表达式不匹配property: innerText且computed: false的约束数组解构const [innerText] node;、[innerText] node;——规则只针对对象解构对象字面量const foo {innerText}、const foo {innerText: text}——字面量属性定义不属于对象解构模式TypeScript 接口场景当innerText是接口Value的字段时value.innerText、const {innerText} value、函数参数解构均不报告——这正是isKnownNonDomNode类型过滤在起作用接口类型不在 DOM 节点类型名集合中。如何查看与运行这套测试若想在本仓库中复现快照结果可以执行npx ava test/prefer-dom-node-text-content.js新增或修改用例后快照会因输出变化而失败此时可配合 AVA 的快照更新机制重新生成.snap与.md文件仓库文档 docs/write-tests.md 说明了规则测试的编写约定。阅读快照时建议三份文件对照test/prefer-dom-node-text-content.js.md可读报告、同目录的.snap机器快照与 rules/prefer-dom-node-text-content.js规则实现即可完整还原从输入代码到错误输出、再到修复建议的全链路行为。小结通过这份快照报告我们可以得出prefer-dom-node-text-content规则的完整行为模型它捕获 DOM 节点上的.innerText成员访问含读取、赋值、可选链与对象解构中的innerText键含重命名、默认值、赋值模式、函数参数与嵌套解构统一建议改为.textContent同时借助类型推断机制精确排除接口、普通对象等非 DOM 场景避免误报。这种“快照报告 测试用例 源码实现”三合一的阅读方式同样适用于该仓库 test/snapshots 下其他 300 条规则的测试理解。【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表