JS Diff 文本差分
最近在项目的开发过程中遇到了需要对比两个单词并且加粗显示diff字母的业务场景,我使用了一个好用且经典的js库 diff 来完成。
库简介
diff是一个基于javascript实现的文本内容diff的库。它基于已发表论文中的算法An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
安装
npm install diff --save
引用
// 不支持import 语法,也就是module引入
const jsDiff = require('diff');
API
JsDiff.diffChars(oldStr, newStr[, options]) 将比较两段文字,比较的维度是基于单个字符,返回一个由描述改变的对象组成的array,再通过遍历对array中的每一个对象进行我们希望的操作(加粗显示、颜色区分等)。例如,要比较的两个单词为woras和words,diffChars返回的array为:
[
{ "count": 3, "value": "wor" },
{ "count": 1, "removed": true, "value": "a" },
{ "count": 1, "added": true, "value": "d" },
{ "count": 1, "value": "s" }
]
added表示是否是添加内容,removed表示是否为删除内容。共有的内容这两个属性都没有,value表示内容,count表示字符的个数。- 可选的配置属性
ignoreCase: 标记为true时忽略字符的大小写,默认为false。
项目示例(Vue版)
diff.js
function StringBuffer() {
this.strings = [];
}
StringBuffer.prototype.append = function (str) {
this.strings.push(str);
return this;
};
StringBuffer.prototype.appendFormat = function (str) {
this.strings.push(str);
return this;
};
StringBuffer.prototype.toString = function () {
return this.strings.join('');
};
StringBuffer.prototype.clear = function () {
this.strings = [];
};
StringBuffer.prototype.size = function () {
return this.strings.length;
};
// 引入diff库
const Diff = require('diff');
const formatDiffLetter = (oldStr, str) => {
const diff = Diff.diffChars(oldStr, str);
// console.log(diff)
const result = new StringBuffer();
diff.forEach((part) => {
if (part.added) {
result.append("<span class='strong-letter'>");
result.append(part.value);
result.append('</span>');
} else if (!part.removed) {
result.append("<span class='normal-letter'>");
result.append(part.value);
result.append('</span>');
}
});
return result;
};
export default formatDiffLetter;
error.vue
<template>
...
<div v-html="formatDiffLetter(itemData.orgChunk, itemData.correctChunk)" />
...
</template>
<script>
import formatDiffLetter from './diff.js';
export default {
...
methods: {
formatDiffLetter,
},
...
</script>
<style scoped>
::v-deep .strong-letter {
font-weight: 600;
font-size: 20px;
color: rgba(255, 255, 255, 1);
}
::v-deep .normal-letter {
font-weight: 500;
font-size: 18px;
color: rgba(255, 255, 255, 0.9);
}
</style>
应用说明
候选词与原词 diff 字母加粗,有以下三种简单场景:
- Change:候选词与原词同位置的某字母不同,替换后的字母加粗
- Add:候选词增加字母,新增的字母加粗
- Remove:候选词较与原词删除字母,无法diff,无加粗
更多复杂场景可由以上三种简单场景组合衍生,例如:
- Add + Change:新增字母 s 加粗,替换字母 a 加粗
- Remove + Change :删除字母 s 不加粗,替换字母 a 加粗
- Remove + Add :删除字母 e 不加粗,新增字母 c 加粗