Fast Javascript text diff using Myers' O(ND) Difference Algorithm
npx @tessl/cli install tessl/npm-fast-diff@1.3.0Fast Diff is a high-performance JavaScript text differencing library that implements Myers' O(ND) Difference Algorithm. It provides efficient text comparison functionality by finding the minimal set of changes needed to transform one string into another.
npm install fast-diffconst diff = require('fast-diff');For TypeScript:
import * as diff from 'fast-diff';
// or
import diff = require('fast-diff');const diff = require('fast-diff');
// Basic diff comparison
const result = diff('Good dog', 'Bad dog');
// Returns: [[-1, "Goo"], [1, "Ba"], [0, "d dog"]]
// Using operation constants
const operations = result.map(([op, text]) => {
switch (op) {
case diff.DELETE: return `Delete: "${text}"`;
case diff.INSERT: return `Insert: "${text}"`;
case diff.EQUAL: return `Keep: "${text}"`;
}
});Fast Diff is built on a sophisticated implementation of Myers' O(ND) Difference Algorithm with several key optimizations:
Compares two strings and returns an array of diff operations indicating insertions, deletions, and unchanged parts.
/**
* Find the differences between two texts using Myers' O(ND) Difference Algorithm
* @param {string} text1 - Old string to be diffed
* @param {string} text2 - New string to be diffed
* @param {number|CursorInfo} [cursor_pos] - Edit position in text1 or cursor info object
* @param {boolean} [cleanup] - Apply semantic cleanup before returning
* @returns {Array<[number, string]>} Array of diff tuples [operation, text]
*/
function diff(text1, text2, cursor_pos, cleanup);Usage Examples:
// Basic text comparison
const result = diff('abc', 'aec');
// Returns: [[0, "a"], [-1, "b"], [1, "e"], [0, "c"]]
// With cursor position (respects edit location for better results)
const result = diff('aaa', 'aaaa', 1);
// Returns: [[0, "a"], [1, "a"], [0, "aa"]]
// Insertion is positioned at cursor location
// With semantic cleanup (improves readability)
const result = diff('The quick brown fox', 'A quick brown fox', null, true);
// Applies semantic cleanup to make changes more meaningful
// Using cursor info object for complex edits
const result = diff('hello world', 'hello there world', {
oldRange: { index: 6, length: 0 },
newRange: { index: 6, length: 6 }
});Constants representing the type of operation in each diff tuple.
/** Constant representing a delete operation (-1) */
const DELETE = -1;
/** Constant representing an insert operation (1) */
const INSERT = 1;
/** Constant representing an equality/no change (0) */
const EQUAL = 0;Usage Examples:
const result = diff('old text', 'new text');
result.forEach(([operation, text]) => {
switch (operation) {
case diff.DELETE:
console.log(`Remove: "${text}"`);
break;
case diff.INSERT:
console.log(`Add: "${text}"`);
break;
case diff.EQUAL:
console.log(`Keep: "${text}"`);
break;
}
});
// Check for specific operations
const hasInsertions = result.some(([op]) => op === diff.INSERT);
const hasDelations = result.some(([op]) => op === diff.DELETE);/**
* Main diff function signature for TypeScript
*/
declare function diff(
text1: string,
text2: string,
cursorPos?: number | diff.CursorInfo,
cleanup?: boolean
): diff.Diff[];
/**
* Diff tuple representing an operation and its associated text
*/
type Diff = [-1 | 0 | 1, string];
/**
* Interface for providing detailed cursor position information
*/
interface CursorInfo {
/** Range in the old text */
oldRange: { index: number; length: number };
/** Range in the new text */
newRange: { index: number; length: number };
}
/**
* Operation constants
*/
const DELETE: -1;
const INSERT: 1;
const EQUAL: 0;The diff function returns an array of tuples where each tuple contains:
-1 (delete), 1 (insert), or 0 (equal)// Example return value for diff('abc', 'ac'):
[
[-1, "b"], // Delete "b"
[0, "ac"] // Keep "ac"
]
// Example return value for diff('ac', 'abc'):
[
[0, "a"], // Keep "a"
[1, "b"], // Insert "b"
[0, "c"] // Keep "c"
]The library handles various edge cases gracefully: