最省事的本地 HTML 差异生成方式是用 diff -u 结合 pygmentize 或 diff2html-cli;纯前端实时对比推荐 diff-match-patch,需转义输入并自定义 ins/del 样式。

用 diff 命令生成 HTML 差异片段最省事
本地有两版 HTML 笔记文件(比如 note_v1.html 和 note_v2.html),直接用命令行比对生成带高亮的 HTML 片段,比手写 JS 库快得多,也更可控。
- 先用
diff -u输出统一格式差异,再用pygmentize(需安装 Pygments)转成带 class 的 HTML:diff -u note_v1.html note_v2.html | pygmentize -l diff -f html -O full=false
- 若没装 Pygments,可用
diff2html-cli(Node.js):运行npx diff2html-cli -i stdin -F diff.html -- -u note_v1.html note_v2.html,输出含内联样式的完整 HTML 文件 - 注意:原始 HTML 中若有
<script>或<style>标签,diff会把它们当纯文本比对——这是对的,你本就不该在笔记 HTML 里嵌动态逻辑
纯前端用 diff-match-patch 做行级高亮
如果必须在浏览器里实时对比两个 HTML 字符串(比如编辑器预览区),diff-match-patch 是目前最轻、最稳的选择,它不解析 DOM,只处理字符串,避免 XSS 风险和解析错乱。
- 加载库:
<script src="https://unpkg.com/diff-match-patch@1.0.5/index.js"></script> - 调用时传入两个 HTML 字符串,用
dmp.diff_main()得到操作列表,再用dmp.diff_prettyHtml()生成带<ins>/<del>的 HTML 片段 - 关键点:必须先对原始 HTML 做
encodeURIComponent级别转义(或用DOMPurify.sanitize()过滤),否则用户输入的<img onload=alert(1)>会被原样插入并执行 - 性能提示:超过 50KB 的 HTML 字符串会让
diff_main()明显卡顿,建议限制单次对比长度,或加 loading 提示
highlight.js 不适合 HTML 差异高亮
很多人第一反应是用 highlight.js 给 diff 输出上色,但它默认只认语言类型(如 language-diff),不理解 HTML 内容结构,会导致:
-
<div class="new">这种行被当成普通文本,class 名、引号、尖括号全乱色 - 无法区分「新增标签」和「新增文字内容」,
<p>Hello</p>变成<p>绿、Hello绿、</p>绿,失去语义 - 如果你硬要塞进
<pre><code class="diff">,得自己先把 HTML 转义成<div>,再让 highlight.js 渲染——多此一举,不如直接用 <code>diff-match-patch样式必须重写
ins和del的默认行为浏览器对
<ins>默认加下划线、<del>加删除线,但笔记对比中你需要更克制的视觉反馈。立即学习“前端免费学习笔记(深入)”;
- 至少覆盖:去掉
text-decoration,改用背景色 + 边框,例如:ins { background-color: #d4edda; border-radius: 2px; }<br>del { background-color: #f8d7da; text-decoration: none; } - 如果对比的是代码块内的 HTML(比如 Markdown 渲染后的内容),还要防止
ins/del被父级pre或code的white-space截断——给ins, del加white-space: normal - 别依赖
!important,用足够具体的 CSS 选择器,比如.note-diff ins,避免污染全局
实际做笔记版本对比时,最易被忽略的是 HTML 字符串的预处理粒度:不是“整个文件丢进去”,而是按语义块(如每个
<h2>段落)分段 diff,否则一个标题改了,后面所有内容的行号全偏移,高亮就失去定位意义。 - 至少覆盖:去掉



















