Convert diff results to XML and Google diff-match-patch formats. Enables integration with other diff tools and systems that require specific output formats.
Converts change objects to XML format with <ins> and <del> tags for added and removed content.
/**
* Convert change objects to XML format
* @param changes - Array of change objects from any diff function
* @returns String containing XML with <ins> and <del> tags
*/
function convertChangesToXML(changes);Converts change objects to Google diff-match-patch format using operation codes.
/**
* Convert change objects to diff-match-patch format
* @param changes - Array of change objects from any diff function
* @returns Array of [operation, text] tuples where operation is -1 (delete), 0 (equal), or 1 (insert)
*/
function convertChangesToDMP(changes);import { diffWords, convertChangesToXML } from "diff";
// Create a diff
const changes = diffWords("Hello world", "Hello universe");
// Convert to XML
const xmlOutput = convertChangesToXML(changes);
console.log(xmlOutput);
// Output: "Hello <del>world</del><ins>universe</ins>"
// Example with line diff
const lineChanges = diffLines(
"line 1\nline 2\nline 3",
"line 1\nmodified line 2\nline 3"
);
const xmlLines = convertChangesToXML(lineChanges);
console.log(xmlLines);
// Output: "line 1\n<del>line 2\n</del><ins>modified line 2\n</ins>line 3"import { diffChars, convertChangesToXML } from "diff";
function renderDiffAsHTML(oldText, newText) {
const changes = diffChars(oldText, newText);
const xmlDiff = convertChangesToXML(changes);
// Style the diff with CSS
return `
<div class="diff-container">
<style>
.diff-container ins { background-color: #d4edda; text-decoration: none; }
.diff-container del { background-color: #f8d7da; text-decoration: line-through; }
</style>
${xmlDiff}
</div>
`;
}
// Usage
const htmlDiff = renderDiffAsHTML("Hello world", "Hello universe");
document.getElementById('diff-output').innerHTML = htmlDiff;import { diffWords, convertChangesToDMP } from "diff";
// Create a diff
const changes = diffWords("The quick brown fox", "The slow brown fox");
// Convert to DMP format
const dmpFormat = convertChangesToDMP(changes);
console.log(dmpFormat);
// Output: [
// [0, "The "],
// [-1, "quick"],
// [1, "slow"],
// [0, " brown fox"]
// ]
// DMP operation codes:
// -1 = DELETE (removed text)
// 0 = EQUAL (unchanged text)
// 1 = INSERT (added text)import { diffLines, convertChangesToDMP } from "diff";
// Assuming you also have the diff-match-patch library installed
// import { diff_match_patch } from "diff-match-patch";
function integrateWithDiffMatchPatch(oldText, newText) {
// Use jsdiff for initial comparison
const changes = diffLines(oldText, newText);
const dmpFormat = convertChangesToDMP(changes);
// Now you can use the DMP format with Google's diff-match-patch library
// const dmp = new diff_match_patch();
// const patches = dmp.patch_make(dmpFormat);
// const patchText = dmp.patch_toText(patches);
return {
jsdiffChanges: changes,
dmpFormat: dmpFormat,
// patches: patches,
// patchText: patchText
};
}
// Usage
const integration = integrateWithDiffMatchPatch(originalCode, modifiedCode);
console.log("DMP format:", integration.dmpFormat);import { diffWords, convertChangesToXML } from "diff";
function createRichTextDiff(originalContent, newContent) {
const changes = diffWords(originalContent, newContent);
const xmlDiff = convertChangesToXML(changes);
// Convert to rich text editor format (example for a hypothetical editor)
return xmlDiff
.replace(/<del>/g, '<span class="deletion">')
.replace(/<\/del>/g, '</span>')
.replace(/<ins>/g, '<span class="insertion">')
.replace(/<\/ins>/g, '</span>');
}
// Usage
const richTextDiff = createRichTextDiff(
"The original document text",
"The modified document text"
);import { diffLines, convertChangesToXML, convertChangesToDMP } from "diff";
function exportDiffInMultipleFormats(oldContent, newContent, filename) {
const changes = diffLines(oldContent, newContent);
const formats = {
xml: convertChangesToXML(changes),
dmp: convertChangesToDMP(changes),
json: JSON.stringify(changes, null, 2),
summary: {
totalChanges: changes.filter(c => c.added || c.removed).length,
additions: changes.filter(c => c.added).length,
deletions: changes.filter(c => c.removed).length,
unchanged: changes.filter(c => !c.added && !c.removed).length
}
};
return formats;
}
// Usage
const multiFormat = exportDiffInMultipleFormats(oldFile, newFile, "changes");
console.log("XML format:", multiFormat.xml);
console.log("DMP format:", multiFormat.dmp);
console.log("Summary:", multiFormat.summary);import { diffLines, convertChangesToXML } from "diff";
function createWebDiffViewer(oldText, newText, options = {}) {
const changes = diffLines(oldText, newText);
const xmlDiff = convertChangesToXML(changes);
const viewerHTML = `
<!DOCTYPE html>
<html>
<head>
<title>Diff Viewer</title>
<style>
body { font-family: monospace; line-height: 1.4; }
.diff-container {
border: 1px solid #ddd;
padding: 20px;
background: #f9f9f9;
}
ins {
background-color: #d4edda;
color: #155724;
text-decoration: none;
padding: 2px 4px;
border-radius: 3px;
}
del {
background-color: #f8d7da;
color: #721c24;
text-decoration: line-through;
padding: 2px 4px;
border-radius: 3px;
}
.stats {
margin-bottom: 20px;
padding: 10px;
background: #e9ecef;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="stats">
<h3>Diff Statistics</h3>
<p>Changes: ${changes.filter(c => c.added || c.removed).length}</p>
<p>Lines added: ${changes.filter(c => c.added).length}</p>
<p>Lines removed: ${changes.filter(c => c.removed).length}</p>
</div>
<div class="diff-container">
<h3>Changes</h3>
<pre>${xmlDiff}</pre>
</div>
</body>
</html>`;
return viewerHTML;
}
// Usage
const diffViewer = createWebDiffViewer(oldCode, newCode);
// Save to file or serve via web serverimport { diffWords, convertChangesToXML } from "diff";
function convertToCustomXML(changes, options = {}) {
const {
insertTag = 'add',
deleteTag = 'remove',
attributes = {},
escapeHtml = true
} = options;
let result = '';
for (const change of changes) {
let value = change.value;
if (escapeHtml) {
value = value
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"');
}
if (change.added) {
const attrs = Object.entries(attributes)
.map(([k, v]) => `${k}="${v}"`)
.join(' ');
result += `<${insertTag}${attrs ? ' ' + attrs : ''}>${value}</${insertTag}>`;
} else if (change.removed) {
const attrs = Object.entries(attributes)
.map(([k, v]) => `${k}="${v}"`)
.join(' ');
result += `<${deleteTag}${attrs ? ' ' + attrs : ''}>${value}</${deleteTag}>`;
} else {
result += value;
}
}
return result;
}
// Usage
const changes = diffWords("old text", "new text");
const customXML = convertToCustomXML(changes, {
insertTag: 'insertion',
deleteTag: 'deletion',
attributes: { class: 'diff-change', timestamp: Date.now() },
escapeHtml: true
});import { diffLines, convertChangesToXML } from "diff";
function convertToMarkdownDiff(oldText, newText) {
const changes = diffLines(oldText, newText);
let markdown = '```diff\n';
changes.forEach(change => {
const lines = change.value.split('\n');
lines.forEach(line => {
if (!line && lines.length === 1) return; // Skip empty single lines
if (change.added) {
markdown += `+ ${line}\n`;
} else if (change.removed) {
markdown += `- ${line}\n`;
} else {
markdown += ` ${line}\n`;
}
});
});
markdown += '```';
return markdown;
}
// Usage
const markdownDiff = convertToMarkdownDiff(oldContent, newContent);
console.log("Markdown diff:\n", markdownDiff);import { diffLines, convertChangesToXML, convertChangesToDMP } from "diff";
function efficientFormatConversion(oldText, newText, targetFormats) {
// Compute diff once
const changes = diffLines(oldText, newText);
// Convert to requested formats
const results = {};
if (targetFormats.includes('xml')) {
results.xml = convertChangesToXML(changes);
}
if (targetFormats.includes('dmp')) {
results.dmp = convertChangesToDMP(changes);
}
if (targetFormats.includes('json')) {
results.json = JSON.stringify(changes);
}
if (targetFormats.includes('stats')) {
results.stats = {
additions: changes.filter(c => c.added).length,
deletions: changes.filter(c => c.removed).length,
unchanged: changes.filter(c => !c.added && !c.removed).length
};
}
return results;
}
// Usage - only compute what's needed
const formats = efficientFormatConversion(text1, text2, ['xml', 'stats']);