Created
December 10, 2023 19:49
-
-
Save siliconjungle/b028885947713b7c0753e0eade4c17de to your computer and use it in GitHub Desktop.
Simple diff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a basic diff mechanism, it is not going to work for characters that take up more than | |
// one byte. It is also not going to normalise text. | |
// these are things that *should happen* in the future, but for now they are going to be ignored. | |
// returns the insert position & the text to insert as well as the delete position & the text to delete | |
// one of the problems with this kind of diff is that you can't tell in some cases where the insert | |
// actually occurred. | |
// for this you will need to take into account the cursor start & end. | |
export const diff = (a, b) => { | |
if (a === b) { | |
return [] | |
} | |
const ops = [] | |
// Handle the case where one string is empty | |
if (!a.length || !b.length) { | |
return [{ | |
type: a.length ? 'remove' : 'insert', | |
pos: 0, | |
text: a.length ? a : b, | |
}] | |
} | |
// Find the start of the change | |
let start = 0 | |
while (start < a.length && start < b.length && a[start] === b[start]) { | |
start++ | |
} | |
// Find the end of the change | |
let endA = a.length, endB = b.length | |
while (endA > start && endB > start && a[endA - 1] === b[endB - 1]) { | |
endA-- | |
endB-- | |
} | |
// Determine removal operation | |
if (endA - start > 0) { | |
ops.push({ | |
type: 'remove', | |
pos: start, | |
amount: endA - start, | |
}) | |
} | |
// Determine insertion operation | |
if (endB - start > 0) { | |
ops.push({ | |
type: 'insert', | |
pos: start, | |
text: b.substring(start, endB), | |
}) | |
} | |
return ops | |
} | |
console.log(diff('Hello world', 'Hello!')) | |
console.log(diff('Hello!', 'Hello world')) | |
console.log(diff('abc', '')) | |
console.log(diff('', 'abc')) | |
console.log(diff('Hello world', 'Hello brave world')) | |
console.log(diff('Hello brave world', 'Hello beautiful world')) | |
console.log(diff('abc', 'cba')) | |
console.log(diff('The quick brown fox', 'The slow red fox jumps over')) | |
console.log(diff('Hello world', 'Hello world')) | |
console.log(diff('Hello World', 'hello world')) | |
console.log(diff('Hello\nWorld', 'Hello World')) | |
console.log(diff('Café', 'Cafe')) | |
console.log(diff('こんにちは', 'こんばんは')) | |
console.log(diff('', '')) | |
// These cases are weird. | |
// Not going to bother with them *yet*. | |
console.log(diff('👍', '👍🏽')) | |
console.log(diff('👨👩👦', '👨👩👧')) | |
console.log(diff('🇫🇷', '🇩🇪')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment