htmlhint自定义规则必须编写commonjs模块,导出含id、description和init方法的对象,在init中通过parser.addlistener监听事件并调用reporter.warn/error,不可直接执行同步校验。

HTMLHint 支持自定义规则,但不是通过修改配置文件字符串就能生效——必须写 JavaScript 模块并注册到解析器事件流中。
如何编写一个可被 HTMLHint 加载的自定义规则
自定义规则本质是一个导出 id、description 和 init 方法的对象,init 接收 parser、reporter 和 options 三个参数。关键在于监听解析器事件(如 tagstart、attr、text),并在合适时机调用 reporter.error() 或 reporter.warn()。
- 规则文件必须是 CommonJS 格式(
module.exports = { ... }),ESM 不被原生支持 -
parser.addListener('tagstart', handler)是最常用入口,event.tagName可获取标签名,event.attrs是属性数组 - 不要在
init中直接执行检查逻辑,所有校验必须放在事件回调里,否则无法获取位置信息(event.line/event.col) - 若需访问完整 AST 或嵌套结构,得自己维护栈状态(
parser是流式解析器,不生成完整树)
怎样把自定义规则加入 HTMLHint 配置
不能靠 .htmlhintrc 的 rules 字段直接引用路径——必须通过编程方式加载,或使用 CLI 的 --rulesdir 参数。
- CLI 场景:把规则文件放在
rules/目录下,运行htmlhint --rulesdir ./rules *.html - Node.js API 场景:用
HTMLHint.registerRule(require('./my-rule'))显式注册,再调用HTMLHint.verify(html, options) - VS Code 插件默认不加载自定义规则,需配合
htmlhint.customRules设置项(值为绝对路径数组) - Webpack 插件(
htmlhint-webpack-plugin)需在options.rulesDir中指定目录,且该目录内文件名不能含.(如my-rule.js可,my.rule.js不行)
常见自定义需求与对应事件选择
不同检查目标要绑定不同解析事件,选错会导致漏报或误报。
- 检查某个标签是否缺失子元素(如
<nav></nav>必须含<a></a>):监听tagstart记录进入,tagend时查栈顶标签 + 当前内容是否匹配 - 禁止特定 class 值(如
class="legacy-xxx"):监听attr事件,当event.name === 'class'且event.value匹配正则时上报 - 要求
<img>的src必须以/assets/开头:在tagstart中判断event.tagName === 'img',再遍历event.attrs找src属性值 - 检测注释是否含 TODO/FIXME:监听
comment事件(注意:默认解析器不触发此事件,需确认所用版本是否启用)
为什么自定义规则常报“no reporter”或位置错乱
根本原因在于规则未正确接入事件流,或解析器未按预期触发事件。
-
reporter是空对象?说明init没被调用——检查规则文件是否被正确加载(console.log在init开头验证) - 错误定位总在第 1 行?大概率是用了同步校验逻辑(如直接遍历字符串),没走事件回调,丢失了
event.line/event.col - 同一处报多次错误?因为一个标签可能触发多个事件(如
tagstart+ 多个attr),需用event.raw去重或加守卫条件 - 规则在 CLI 生效但在 Webpack 不生效?确认
rulesDir路径是相对于 Webpack 配置文件所在目录,不是项目根目录
真正难的不是写逻辑,而是理解 HTMLHint 的流式解析模型——它不建 DOM 树,只发事件;所有规则都是“事件驱动的断言”,而不是“文档快照分析”。这点和 ESLint 完全不同,容易按惯性踩坑。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











