← Back to Blog
2026-03-123 min readby DevUtilz

Text Diff and Comparison Tools

DiffTextComparisonTools

Text Diff and Comparison Tools

Diff tools show the differences between two text versions. They're essential for code reviews, version control, and finding changes.

Simple Diff Algorithm

function simpleDiff(text1, text2) {
  const lines1 = text1.split('\n');
  const lines2 = text2.split('\n');
  const result = [];

  const maxLines = Math.max(lines1.length, lines2.length);

  for (let i = 0; i < maxLines; i++) {
    if (lines1[i] !== lines2[i]) {
      if (i < lines1.length && lines2[i] === undefined) {
        result.push({ type: 'removed', line: lines1[i], index: i });
      } else if (i >= lines1.length) {
        result.push({ type: 'added', line: lines2[i], index: i });
      } else {
        result.push({ type: 'changed', old: lines1[i], new: lines2[i], index: i });
      }
    }
  }

  return result;
}

Using diff Libraries

// diff npm package
import * as Diff from 'diff';

const changes = Diff.diffLines(oldText, newText);

changes.forEach(part => {
  if (part.added) console.log('+ ' + part.value);
  if (part.removed) console.log('- ' + part.value);
});

Visual Diff Display

function renderDiff(changes) {
  return changes.map(change => {
    const prefix = change.added ? '+ ' : change.removed ? '- ' : '  ';
    const color = change.added ? 'green' : change.removed ? 'red' : 'gray';
    return `<span style="color:${color}">${prefix}${change.value}</span>`;
  }).join('\n');
}

Word-level Diff

import { diffWords } from 'diff';

const changes = diffWords('Hello world', 'Hello beautiful world');

changes.forEach(part => {
  if (part.added) console.log(`[+] ${part.value}`);
  if (part.removed) console.log(`[-] ${part.value}`);
  if (!part.added && !part.removed) console.log(part.value);
});

Common Use Cases

1. Version Control (Git-style)

function gitStyleDiff(oldText, newText) {
  const changes = Diff.diffLines(oldText, newText);
  let output = '';
  let lineNum = 0;

  changes.forEach(change => {
    const lines = change.value.split('\n').filter(l => l);
    lines.forEach(line => {
      const prefix = change.added ? '+' : change.removed ? '-' : ' ';
      output += `${prefix} ${lineNum}: ${line}\n`;
      lineNum++;
    });
  });

  return output;
}

2. Show Only Changed Lines

function showChangesOnly(changes) {
  return changes.filter(c => c.added || c.removed);
}

3. Character-level Diff

import { diffChars } from 'diff';

const changes = diffChars('abc', 'axbc');
// Shows each character change

UI Implementation

// Simple diff view component
function DiffView({ oldText, newText }) {
  const changes = Diff.diffLines(oldText, newText);

  return (
    <pre>
      {changes.map((part, i) => (
        <span
          key={i}
          style={{
            backgroundColor: part.added ? '#e6ffed' : part.removed ? '#ffeef0' : 'transparent',
            color: part.added ? '#22863a' : part.removed ? '#b31d28' : 'inherit'
          }}
        >
          {part.value}
        </span>
      ))}
    </pre>
  );
}

Popular Libraries

| Library | Use Case | |---------|----------| | diff | General text diff | | jsdiff | JavaScript/TypeScript | | diff-match-patch | Google library | | monaco-editor | VS Code diff view |

Best Practices

  1. Line-level for code - Preserves code structure
  2. Word-level for prose - Shows text changes
  3. Character-level for precise - Most detailed

Conclusion

Use a library like diff or jsdiff for production. For most cases, line-level diff is sufficient. Consider word-level for prose documents.