DOMParser解析HTML会丢节点,因其按修复后DOM树返回结果,无法反映原始语法瑕疵;需用parse5等符合HTML5规范的解析器保留token流,才能准确检测标签缺失、大小写混用及错误位置。

为什么直接用 DOMParser 解析 HTML 会丢节点?
浏览器原生的 DOMParser 在遇到不规范 HTML(比如未闭合的 <img>、错位的 </div>)时,会按“修复后”的 DOM 树返回结果,而非原始结构。这意味着你没法准确统计缺失闭合标签、嵌套错误或自闭合标签误写等问题。
真正做质量解析,得用符合 HTML5 规范的解析器,保留原始 token 流。推荐用 parse5——它默认启用“宽容模式”,能还原真实输入中的语法瑕疵。
-
parse5.parseFragment()适合检查片段(如组件模板),不会补全<html><body> - 若要校验完整文档,用
parse5.parse(),但需注意它会自动注入缺失的根结构,可能干扰“缺少<head>”类规则判断 - 避免用
jsdom:启动慢、内存开销大,且默认行为更“浏览器化”,掩盖问题
怎么提取所有标签名并统计大小写混用?
HTML 标签名本身不区分大小写,但团队规范常要求全小写。靠正则匹配 <[A-Z] 容易漏掉换行或属性换行后的标签,也不识别自闭合语法(<Img/>)。
正确做法是遍历 parse5 输出的 AST 节点,读取每个 element 的 tagName 字段:
立即学习“前端免费学习笔记(深入)”;
const ast = parse5.parseFragment(html);
function walk(node) {
if (node.tagName && node.tagName !== node.tagName.toLowerCase()) {
console.warn(`非小写标签: <${node.tagName}>`);
}
if (node.children) node.children.forEach(walk);
}
walk(ast);-
node.tagName是解析器标准化后的名称(如<DIV>→"div"),所以必须用原始 token 才能检测书写形式——需改用parse5.parseTreeAdapter.getTagName(node)配合parse5.treeAdapters.default.getAttrList(node)获取原始源码位置 - 更轻量方案:用
parse5.Parser+ 自定义treeAdapter,在createElement钩子中直接捕获原始标签字符串 - 注意
<svg>和<math>内部标签可大写,需按上下文跳过校验
如何定位未闭合的 <div> 或错配的 </span>?
这不是简单括号匹配问题。HTML 允许省略某些结束标签(如 <p>),但禁止在 <p> 内嵌 <div>。靠栈模拟会漏掉这些隐式规则。
依赖 parse5 的 errors 数组——它在解析时就记录了所有违反 HTML5 规范的节点插入/终止行为:
const { errors } = parse5.parse(html, {
onParseError: err => {} // 必须传空函数,否则错误被吞掉
});
errors.forEach(e => {
if (e.code === 'missing-end-tag') {
console.error(`缺少结束标签: ${e.startLine}:${e.startCol}`);
}
});- 常见错误码:
missing-end-tag(缺闭合)、unexpected-end-tag(多余闭合)、non-void-element-start-tag-with-trailing-solidus(<div/>这种非法写法) -
onParseError不设回调会导致errors为空,这是parse5的隐藏行为 - 错误位置(
startLine/startCol)基于原始字符串,不是 DOM 序列,可直接映射到编辑器高亮
怎样让工具支持 Vue/React 模板中的指令和插值?
纯 HTML 解析器会把 v-if、{{ count }} 当作普通属性或文本,无法识别语义。强行扩展 AST 会破坏标准兼容性。
务实做法是分层处理:先用 parse5 提取所有元素和文本节点,再对属性值和文本内容做二次正则扫描:
- 属性层面:检查
node.attrs中是否存在name === "v-if"或name.startsWith("@") || name.startsWith("v-") - 文本层面:用
/\{\{[^}]+\}\}/g匹配插值,但注意避开<script>和<style>内容——需提前提取这些特殊标签并跳过其子节点 - 不建议解析 JSX:它的语法远超 HTML 范畴,应交给 Babel 或 SWC 的 AST;HTML 质量工具只负责“模板壳层”合规性
真正容易被忽略的是注释节点:HTML 注释 <!-- ... --> 里混写 {{ 或 v- 不应触发警告,但默认解析器会把它当纯文本。需要单独过滤 node.nodeName === '#comment' 并跳过内容校验。



















