A JavaScript text diff implementation based on the Myers algorithm for comparing text at different granularities.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Generic array comparison with customizable equality functions. Ideal for comparing sequences of any data type, from simple arrays to complex object collections.
Performs element-level diff between two arrays with strict equality comparison by default.
/**
* Compare two arrays element by element
* @param oldArr - Original array
* @param newArr - New array to compare against
* @param options - Configuration options
* @returns Array of change objects representing the diff
*/
function diffArrays(oldArr, newArr, options);Options:
interface ArrayDiffOptions extends DiffOptions {
comparator?: (left: any, right: any) => boolean; // Custom equality function
}Usage Examples:
import { diffArrays } from "diff";
// Basic array comparison
const result = diffArrays(
[1, 2, 3, 4],
[1, 2, 5, 4]
);
console.log(result);
// [
// { value: [1, 2], count: 2 },
// { value: [3], removed: true, count: 1 },
// { value: [5], added: true, count: 1 },
// { value: [4], count: 1 }
// ]
// String array comparison
const stringResult = diffArrays(
["apple", "banana", "cherry"],
["apple", "blueberry", "cherry"]
);
// Object array with custom comparator
const objectResult = diffArrays(
[{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }],
[{ id: 1, name: "Alice" }, { id: 2, name: "Bobby" }],
{
comparator: (left, right) => left.id === right.id && left.name === right.name
}
);Pre-configured Diff instance for array comparisons with array-specific handling.
/**
* Pre-configured array diff instance
* Preserves array structure and handles empty elements
*/
const arrayDiff: Diff;import { diffArrays } from "diff";
// Case-insensitive string comparison
const caseInsensitive = diffArrays(
["Hello", "World"],
["hello", "WORLD"],
{
comparator: (a, b) => a.toLowerCase() === b.toLowerCase()
}
);
// Object comparison by specific properties
const userComparison = diffArrays(
[
{ id: 1, name: "Alice", age: 25 },
{ id: 2, name: "Bob", age: 30 }
],
[
{ id: 1, name: "Alice", age: 26 }, // Age changed
{ id: 2, name: "Bob", age: 30 }
],
{
comparator: (a, b) => a.id === b.id && a.name === b.name
// Ignores age differences
}
);
// Deep object comparison
function deepEqual(obj1, obj2) {
return JSON.stringify(obj1) === JSON.stringify(obj2);
}
const deepComparison = diffArrays(
[{ nested: { value: 1 } }],
[{ nested: { value: 2 } }],
{ comparator: deepEqual }
);import { diffArrays } from "diff";
// Comparing lists of complex objects
function compareDataSets(oldData, newData) {
return diffArrays(oldData, newData, {
comparator: (a, b) => {
// Custom business logic comparison
return a.uniqueId === b.uniqueId &&
a.version === b.version &&
a.status === b.status;
}
});
}
// Comparing ordered sequences
function compareSequences(seq1, seq2) {
const changes = diffArrays(seq1, seq2);
return {
insertions: changes.filter(c => c.added).length,
deletions: changes.filter(c => c.removed).length,
unchanged: changes.filter(c => !c.added && !c.removed).length,
totalElements: changes.reduce((sum, c) => sum + c.count, 0)
};
}import { diffArrays } from "diff";
// Convert sets to arrays for comparison
function compareSets(set1, set2) {
const arr1 = Array.from(set1).sort();
const arr2 = Array.from(set2).sort();
return diffArrays(arr1, arr2);
}
// Usage
const oldSet = new Set([1, 2, 3, 4]);
const newSet = new Set([1, 2, 5, 6]);
const setDiff = compareSets(oldSet, newSet);import { diffArrays } from "diff";
// Comparing tokenized text as arrays
function compareTokenSequences(text1, text2) {
const tokens1 = text1.split(/\s+/);
const tokens2 = text2.split(/\s+/);
return diffArrays(tokens1, tokens2, {
comparator: (a, b) => a.toLowerCase() === b.toLowerCase()
});
}
const tokenDiff = compareTokenSequences(
"The quick brown fox",
"The slow brown fox"
);import { diffArrays } from "diff";
// Async processing for large arrays
function diffLargeArrays(arr1, arr2, callback) {
diffArrays(arr1, arr2, {
callback: callback,
maxEditLength: 10000, // Limit computation
timeout: 20000, // 20 second timeout
comparator: (a, b) => a === b // Can be customized
});
}
// Usage
diffLargeArrays(largeArray1, largeArray2, (result) => {
if (result) {
console.log(`Array diff completed: ${result.length} change blocks`);
} else {
console.log("Arrays too different to compute diff efficiently");
}
});import { arrayDiff } from "diff";
// Using the pre-configured instance
const directResult = arrayDiff.diff([1, 2, 3], [1, 3, 4]);
// Access to tokenization (returns the array itself)
const tokens = arrayDiff.tokenize([1, 2, 3]);
console.log("Array tokens:", tokens); // [1, 2, 3]
// The arrayDiff instance preserves empty elements
const withEmpties = arrayDiff.diff(
[1, , 3], // Sparse array
[1, 2, 3]
);import { diffArrays } from "diff";
// Optimize comparisons for large objects
function efficientObjectComparison(arr1, arr2) {
return diffArrays(arr1, arr2, {
comparator: (a, b) => {
// Quick reference check first
if (a === b) return true;
// Then check critical properties only
return a.id === b.id && a.hash === b.hash;
}
});
}
// Pre-process arrays for better performance
function preprocessAndCompare(arr1, arr2) {
// Create lightweight comparison objects
const processed1 = arr1.map(item => ({
id: item.id,
key: item.importantField
}));
const processed2 = arr2.map(item => ({
id: item.id,
key: item.importantField
}));
return diffArrays(processed1, processed2);
}