( oldContent: string, newContent: string, )
| 57 | } |
| 58 | |
| 59 | export function myersCharDiff( |
| 60 | oldContent: string, |
| 61 | newContent: string, |
| 62 | ): DiffChar[] { |
| 63 | // Process the content character by character. |
| 64 | // We will handle newlines separately, |
| 65 | // because diffChars does not have an option to ignore eol newlines. |
| 66 | const theirFormat = diffChars(oldContent, newContent); |
| 67 | |
| 68 | // Track indices as we process the diff. |
| 69 | let oldIndex = 0; |
| 70 | let newIndex = 0; |
| 71 | let oldLineIndex = 0; |
| 72 | let newLineIndex = 0; |
| 73 | let oldCharIndexInLine = 0; |
| 74 | let newCharIndexInLine = 0; |
| 75 | |
| 76 | const result: DiffChar[] = []; |
| 77 | |
| 78 | for (const change of theirFormat) { |
| 79 | // Split the change value by newlines to handle them separately. |
| 80 | if (change.value.includes("\n")) { |
| 81 | const parts = change.value.split(/(\n)/g); // This keeps the newlines as separate entries. |
| 82 | |
| 83 | for (let i = 0; i < parts.length; i++) { |
| 84 | const part = parts[i]; |
| 85 | if (part === "") continue; |
| 86 | |
| 87 | if (part === "\n") { |
| 88 | // Handle newline. |
| 89 | if (change.added) { |
| 90 | result.push({ |
| 91 | type: "new", |
| 92 | char: part, |
| 93 | newIndex: newIndex, |
| 94 | newLineIndex: newLineIndex, |
| 95 | newCharIndexInLine: newCharIndexInLine, |
| 96 | }); |
| 97 | newIndex += part.length; |
| 98 | newLineIndex++; |
| 99 | newCharIndexInLine = 0; // Reset when moving to a new line. |
| 100 | } else if (change.removed) { |
| 101 | result.push({ |
| 102 | type: "old", |
| 103 | char: part, |
| 104 | oldIndex: oldIndex, |
| 105 | oldLineIndex: oldLineIndex, |
| 106 | oldCharIndexInLine: oldCharIndexInLine, |
| 107 | }); |
| 108 | oldIndex += part.length; |
| 109 | oldLineIndex++; |
| 110 | oldCharIndexInLine = 0; // Reset when moving to a new line. |
| 111 | } else { |
| 112 | result.push({ |
| 113 | type: "same", |
| 114 | char: part, |
| 115 | oldIndex: oldIndex, |
| 116 | newIndex: newIndex, |
no test coverage detected