页面效果:
jsdiff 是一个 JavaScript 库,用于实现文本差异比较。这个库提供了多种方法来计算和展示两个文本之间的差异,可以用于多种文本差异比较的场景 - 标准 Diff 格式数据
轻量级、算法精度较强、需自行实现可视化的渲染、大文件受限
createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options)
createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options)
oldFileName: 旧文件的文件名。
newFileName: 新文件的文件名。
oldStr: 原始字符串值
newStr: 新的字符串值
oldHeader: 可选,允许在旧文件的头部添加额外的信息。
newHeader: 可选,用于在新文件的头部添加额外的信息。
options: 一个包含选项的对象,可以用来自定义补丁的生成方式:
context: 描述应该包含多少行上下文。设置为 Number.MAX_SAFE_INTEGER 或 Infinity 可以包含整个文件内容在一个块(hunk)中。
ignoreWhitespace: 与 diffLines 中的用法相同,用于忽略空白字符差异。默认为 false。
stripTrailingCr: 与 diffLines 中的用法相同,用于在执行差异比较之前去除所有尾随的回车符( )。这有助于在比较 UNIX 和 Windows 文本文件时得到有用的差异结果。默认为 false。
diff2html 是一个用于将差异(diff)结果转换成 HTML 格式的工具,它通常用于在网页上展示文件或文本内容之间的差异。这个库提供了一种方便的方式来生成美观的差异比较视图,使得用户可以轻松地查看和理解两个版本之间的变化。
相关 js和css引入
引入文件依赖源码:可以找一个vue项目npm下载,然后在node_modules文件夹中找到对应文件夹 复制对应js以及css文件引入
npm install diff --save
npm install diff2html --save
<link rel="stylesheet" type="text/css" href="./css/diff2html.min.css"/>
<script src="./js/diff2html-ui.min.js"></script>
<script src="./js/diff2html.min.js"></script>
<script src="./js/diff.min.js"></script>
diff2html使用
// 比对文本函数
function compareText() {
// 生成标准diff格式
const gitDiffContent = Diff.createPatch(
'SQL脚本', //文件名称
leftContent, //对比左侧内容
rightContent, //对比右侧内容
'',
'',
{
context: Infinity //保留无差异内容
}
);
// 使用Diff2Html 传入生成的标准diff格式数据 生成可视化的html
const diffHTML = Diff2Html.html(gitDiffContent, {
inputFormat: 'diff',
outputFormat: 'side-by-side', //左右分列的形式
matching: 'none',
drawFileList: false,
highlight: true,
showFiles: true,
renderNothingWhenEmpty: false
});
$('#diff-container').html(diffHTML); //内容区域id: diff-container
//回显当前锁定左右侧区域
var index = currentSide == 'left' ? 0 : 1
$(".d2h-file-side-diff").eq(index).addClass('side_active')
// 同步滚动
syncScroll();
}
// 同步滚动函数
function syncScroll() {
const leftContent = $('.d2h-file-side-diff')[0];
const rightContent = $('.d2h-file-side-diff')[1];
leftContent.addEventListener('scroll', function() {
rightContent.scrollTop = leftContent.scrollTop;
rightContent.scrollLeft = leftContent.scrollLeft;
});
rightContent.addEventListener('scroll', function() {
leftContent.scrollTop = rightContent.scrollTop;
leftContent.scrollLeft = rightContent.scrollLeft;
});
}
注意事项:
- 若外层有flex样式会有冲突,显示异常,添加以下样式即可
.d2h-files-diff {
height: calc(100% - 35px);
}
.d2h-file-side-diff {
overflow-y: scroll;
}
/* 强制行号容器同步滚动 */
.d2h-code-side-linenumber {
position: relative !important; /* 覆盖sticky定位 */
float: left;
width: 40px; /* 固定行号列宽度 */
}
/* 主滚动容器修正 */
.d2h-file-side-diff {
overflow-x: auto !important;
-webkit-overflow-scrolling: touch; /* iOS滚动优化 */
}
/* 隐藏原生滚动条 */
.d2h-code-side-line::-webkit-scrollbar {
display: none;
}
- 无任何差异文件数据展示
使用 jsdiff 生成的diff数据结果渲染出来会有一个问题,当传入的两个字符串没有任何差异的时候,不显示文件内容,仅显示一行“without any changes”,如果修改要显示全部的文件数据,可以修改diff.js 中的源码
function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
if (typeof options === 'function') {
options = { callback: options };
}
if (!(options === null || options === void 0 ? void 0 : options.callback)) {
const patchObj = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options);
if (!patchObj) {
return;
}
//判断是否有差异的逻辑
if(patchObj.hunks.length > 0) {
return formatPatch(patchObj);
} else {
return createFullPatch(oldFileName, newFileName, oldStr)
}
}
else {
const { callback } = options;
structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, Object.assign(Object.assign({}, options), { callback: patchObj => {
if (!patchObj) {
callback(undefined);
}
else {
console.log(patchObj);
callback(formatPatch(patchObj));
}
} }));
}
}
//无任何差异调用的方法
function createFullPatch(oldFile, newFile, content) {
const lines = content.split('\n').length;
return `--- ${oldFile}\n+++ ${newFile}\n@@ -1,${lines} +1,${lines} @@\n` +
content.split('\n').map(line => ` ${line}`).join('\n');
}