将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
真正有效的验证方式是观察浏览器实际生成的 dom:通过 chrome devtools elements 面板查看真实节点树,执行 js 遍历检查子元素类型,或使用 html-validate、nu-html-checker 等语义校验工具定位非法嵌套。

标签的嵌套关系不能靠“解析字符串”来判断,因为浏览器根本不会按你写的字符串结构生成 DOM——它会强制修正非法嵌套。想看清真实关系,得绕过字符串,直击解析后的 DOM。
DOMParser 解析后结构已失真,不能用于嵌套验证
DOMParser.parseFromString() 对 HTML 是宽容模式,遇到 <p></p>
<div>xxx</div>
<p></p>
<div>xxx</div>
<p></p>,返回的 Document 看似合法,但原始嵌套语义全丢。
你无法从它身上看出“这里本该嵌套却失败了”,因为它已经帮你“修好了”。
- 它不报错、不警告、不保留源位置信息
- document.querySelector('p > div') 返回 null,但这不是解析失败,而是修复完成后的正常结果
- 若用于模板预检或 SSR 前校验,容易误判为“结构 OK”,埋下运行时隐患
真正有效的验证方式:看浏览器实际生成的 DOM
别信源码缩进,也别信编辑器高亮——只信 Elements 面板里展开的真实节点树:
- 打开 Chrome DevTools → Elements 面板,找到目标 <p></p> 节点
- 展开它,如果子节点为空,旁边却紧挨着一个独立的 <div> 或 <code><h2></h2>,说明已被静默拆出
- 右键该 <p></p> → “Edit as HTML”,删一个空格再回车:若 <div> 突然跳到外面或缩进重排,就是嵌套违规的铁证
- 控制台执行:<code>document.querySelectorAll('p').forEach(p => { console.log(p.outerHTML); Array.from(p.children).forEach(c => console.log('→', c.tagName)) }),只要输出里出现 DIV、H2、SECTION,就代表当前 DOM 已被修复,原始写法非法
自动化检测必须用语义校验工具,不是 DOM 操作
靠 JS 遍历 DOM 写规则太重且易漏,推荐轻量可靠的静态检查:
- 本地批量检查:html-validate CLI,启用 element-permitted-content 规则,它会按 HTML Living Standard 逐个比对父-子组合是否被允许
- CI/CD 中接入:nu-html-checker 或 tidy -errors,它们能明确报出类似 Element div not allowed as child of element p 的错误行号
- VS Code 插件:HTMLHint 配合自定义规则,或 eslint-plugin-html(需搭配 eslint-plugin-jsx-a11y 补充可访问性检查)
- 注意:W3C Validator(validator.w3.org)仍是黄金标准,粘贴 HTML 即可定位到具体第几行、哪个元素越界
动态内容场景下最容易忽略的点
服务端拼接、JS 模板字符串、Vue/React JSX 中的 v-html 或 dangerouslySetInnerHTML,都可能在运行时生成非法嵌套。这类结构不会出现在初始 HTML 中,所以 W3C 校验器扫不到。
- 必须在组件 mount 后、或 SSR 输出前,用 document.querySelectorAll('p > *') 主动扫描
- 特别注意循环渲染中误将块级结构塞进 <p v-for></p>:比如 Vue 模板里写 <p v-for="item in list"></p>
<h3>{{ item.title }}</h3>
<p>{{ item.desc }}</p>
<p><section></section></p> 在作祟










