结论:应让ai直接输出html并前端安全清洗挂载,而非用marked等库流式解析markdown——因其设计不支持中断输入,会导致标题裂开、代码块卡死、列表错乱;需指令ai输出自包含html、禁用外部依赖,并用dompurify过滤后挂载,再手动处理mermaid渲染和代码块复制功能。

直接说结论:别再用 marked 或 markdown-it 做 AI 流式 Markdown 渲染了——它们不是为逐 token 输出设计的,硬套会导致标题裂开、代码块卡死、列表嵌套错乱。真要实时渲染,得切换思路:让 AI 直接输出 HTML,前端只做安全清洗和挂载。
为什么流式 Markdown 解析在 AI 场景下必然失败
AI 逐字/逐 token 输出时,marked 的 parse() 函数每次调用都假设输入是完整语法单元。但实际收到的是:
-
"# This is a "(标题未闭合) -
"heading\n\n- item1\n- "(列表中断在破折号后) -
"```py\ndef foo():\n re"(代码块未结束)
这些片段单独喂给解析器,会触发错误状态机回退、标签提前闭合,甚至 DOM 插入时被浏览器自动修正成非法结构(比如把 <h2>xxx</h2>
<p></p> 中的 <p></p> 吞进 <h2></h2> 里)。这不是库的 bug,是设计边界问题。
真正可行的方案:跳过 Markdown,让 AI 输出 HTML
Anthropic、Claude Code 团队已全面转向该模式——不是“渲染 Markdown”,而是“接收 HTML”。关键在于指令层控制输出格式,而非前端补救:
- 明确要求模型输出「自包含 HTML」:
"Output only valid, self-contained HTML. No markdown, no explanations, no backticks. Wrap everything in ...." - 禁用外部依赖:
"Do not use external CSS or JS. Inline all styles with <style> and all scripts with <script> if needed."</style> - 对安全性做兜底:用
DOMPurify.sanitize()过滤后,再innerHTML = sanitizedHtml,不走v-html等直插风险路径
实测中,DOMPurify 对 <style></style> 和 <script></script> 的默认策略足够保守,能拦住内联 onerror、javascript: 协议等常见 XSS 载荷,且不影响 SVG、表格、颜色等视觉表达。
必须处理的三个前端细节
即使 AI 输出了 HTML,直接插入仍会出问题:
-
Mermaid 图表不触发:AI 可能输出
<div class="mermaid">graph LR; A-->B</div>,但浏览器不会自动执行 Mermaid 渲染。需在挂载后手动扫描:document.querySelectorAll('.mermaid'),再调用mermaid.render() -
代码块复制按钮失效:AI 输出的
<pre class="brush:php;toolbar:false;"><code class="js">...</code></pre>缺少交互逻辑。需用事件委托绑定复制事件,不能依赖innerHTML后的静态节点 -
响应式断点错乱:AI 生成的
<style></style>可能含@media (min-width: 768px),但若父容器宽度未设,媒体查询永远不生效。建议强制包裹一层<div style="width: 100%; max-width: 800px; margin: 0 auto;">...</div>
最常被忽略的一点:AI 生成的 HTML 很可能含 <meta name="viewport"> 或 <base href>,这些标签若重复插入会破坏页面全局行为。清洗时得用正则或 DOM 操作显式剔除,不能只依赖 DOMPurify 默认白名单。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











