-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdiff.js
More file actions
66 lines (51 loc) · 1.8 KB
/
Copy pathdiff.js
File metadata and controls
66 lines (51 loc) · 1.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// diff.js - Diff 比对与 HTML 生成模块
/* HTML 转义工具 */
export const escapeHtml = s => String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/\n/g, '<br>');
/* 生成 Diff HTML */
export function buildDiffHTML(myText, aiText) {
const DMP = window.diff_match_patch;
if (!DMP) {
console.error("❌ 错误:diff_match_patch 库未找到。");
return escapeHtml(aiText) || 'Diff library not loaded.';
}
const myClean = String(myText || '').trim();
const aiClean = String(aiText || '').trim();
if (!myClean || !aiClean) {
return escapeHtml(aiText) || '';
}
const dmp = new DMP();
let diffs = dmp.diff_main(myClean, aiClean);
dmp.diff_cleanupSemantic(diffs);
let html = '';
const original = myClean;
let originalIndex = 0;
const isPunctuationOrSpace = char => char.match(/^[\s,.!?;:'"()\[\]@#$%^&*-]$/);
diffs.forEach(([type, text]) => {
for (let i = 0; i < text.length; i++) {
const char = text[i];
const escapedChar = escapeHtml(char);
if (isPunctuationOrSpace(char) && type === 0) {
html += escapedChar;
originalIndex++;
continue;
}
if (type === 0) {
const originalChar = original[originalIndex];
if (originalChar &&
originalChar.toLowerCase() === char.toLowerCase() &&
originalChar !== char) {
html += `<span class="w-case">${escapedChar}</span>`;
} else {
html += escapedChar;
}
originalIndex++;
} else if (type === 1) {
html += `<span class="w-add">${escapedChar}</span>`;
} else if (type === -1) {
html += `<span class="w-rem">${escapedChar}</span>`;
originalIndex++;
}
}
});
return html.trim() || 'No differences';
}