不能直接 diff.innerHTML 或 innerText,因为原始 HTML 中含 、、 时,字符串比对虽看似“错”,实则是防 XSS 的安全底线;误用 innerHTML 替换会撕裂标签、触发脚本执行、破坏 DOM 结构。

直接用 diff-match-patch 处理 HTML 字符串最稳,但必须先转义、限制长度、重写 <ins></ins>/<del></del> 样式;diff -u 命令行生成静态差异更省事,适合本地笔记比对。
为什么不能直接 diff.innerHTML 或 innerText
原始 HTML 里有 <script></script>、<style></style>、<img onload="..." alt="HTML文档怎么动态高亮显示差异内容" > 时,直接比对字符串会把它们当普通文本——这看似“错”,实则是安全底线:你本就不该让笔记 HTML 执行 JS。但若误用 innerHTML 替换(比如搜索高亮时),会撕开标签、触发 XSS、破坏 DOM 结构。
常见错误现象包括:document.getElementById('a').innerHTML = str.replace(/xxx/g, '<mark>$&</mark>') 导致 <code>console.log() 变成 <code>console.<mark>log</mark>(),浏览器解析失败;或用户输入 <img src="x" onerror="alert(1)" alt="HTML文档怎么动态高亮显示差异内容" > 被原样插入并执行。
- 永远只操作纯文本节点:用
document.createTreeWalker(element, NodeFilter.SHOW_TEXT) - 匹配前双重转义:正则元字符(
.*?等)和 HTML 特殊字符(&")都要处理 - 替换时用
document.createElement('mark')+node.parentNode.replaceChild(),不碰innerHTML
用 diff-match-patch 实现实时 HTML 差异高亮
diff-match-patch 不解析 DOM,只做字符串 diff,轻量且防 XSS,是浏览器内实时对比的首选。但它默认输出的 <ins></ins>/<del></del> 样式在多数页面里不可见——浏览器默认只加下划线和删除线,没背景色、没 padding、深色模式下完全糊成一团。
立即学习“前端免费学习笔记(深入)”;
调用流程很简单:
const dmp = new diff_match_patch(); const diffs = dmp.diff_main(html1, html2); const htmlPatch = dmp.diff_prettyHtml(diffs);
但必须加三道防护:
- 输入前用
DOMPurify.sanitize()过滤,或至少encodeURIComponent()后再解码(避免执行任意脚本) - 输出后重写 CSS:
ins { background-color: #d1e7dd; text-decoration: none; } del { background-color: #f8d7da; text-decoration: line-through; } - 单次比对超 50KB HTML 字符串时,
dmp.diff_main()会明显卡顿,建议截断或加loading提示
用 diff -u + pygmentize 快速生成静态差异 HTML
如果你只是比两版本地 HTML 笔记(如 note_v1.html 和 note_v2.html),命令行方式更快、更可控,且天然规避 XSS 和性能问题。
一行搞定:
diff -u note_v1.html note_v2.html | pygmentize -l diff -f html -O full=false
没装 Pygments?用 Node.js 方案:
npx diff2html-cli -i stdin -F diff.html -- -u note_v1.html note_v2.html
注意两个关键点:
- 原始 HTML 中的
<script></script>和<style></style>会被当成文本比对——这是正确行为,别试图“智能跳过” - 输出 HTML 是完整文件(含
),若要嵌入现有页面,得手动提取<div class="highlight"> 内容<h3>ins/del 样式为什么必须重写</h3> <p>浏览器对 <code><ins></ins>和<del></del>的默认样式极弱:ins只有下划线、del只有删除线,在深色主题、高对比度模式、邮件客户端(如 Outlook)中几乎不可见。更糟的是,某些 CSS 重置库(如 normalize.css)会清空它们的所有样式。最小可用样式应包含:
-
background-color(必设,不能只靠 UA 默认) -
color(显式声明,避免被父级颜色覆盖) -
padding(2px 左右,让高亮呼吸) -
border-radius(可选,但提升可读性) - 暗色模式适配:
@media (prefers-color-scheme: dark) { ins { background-color: #2d7d46; } }
别漏掉 WCAG 对比度要求:背景色与文字色的亮度对比至少达 4.5:1,否则视障用户无法识别。
-



















