(source: string, filePath?: string)
| 14 | * between hunks. |
| 15 | */ |
| 16 | export function parseUnifiedDiff(source: string, filePath?: string): DiffLine[] { |
| 17 | if (!source) return [] |
| 18 | |
| 19 | try { |
| 20 | const patches = parsePatch(source) |
| 21 | if (!patches || patches.length === 0) return [] |
| 22 | |
| 23 | const patch = filePath |
| 24 | ? (patches.find((p) => |
| 25 | [p.newFileName, p.oldFileName].some( |
| 26 | (n) => typeof n === "string" && (n === filePath || (n as string).endsWith("/" + filePath)), |
| 27 | ), |
| 28 | ) ?? patches[0]) |
| 29 | : patches[0] |
| 30 | |
| 31 | if (!patch) return [] |
| 32 | |
| 33 | const lines: DiffLine[] = [] |
| 34 | let prevHunk: any = null |
| 35 | for (const hunk of (patch as any).hunks || []) { |
| 36 | // Insert a compact "hidden lines" separator between hunks |
| 37 | if (prevHunk) { |
| 38 | const gapNew = hunk.newStart - (prevHunk.newStart + prevHunk.newLines) |
| 39 | const gapOld = hunk.oldStart - (prevHunk.oldStart + prevHunk.oldLines) |
| 40 | const hidden = Math.max(gapNew, gapOld) |
| 41 | if (hidden > 0) { |
| 42 | lines.push({ |
| 43 | oldLineNum: null, |
| 44 | newLineNum: null, |
| 45 | type: "gap", |
| 46 | content: "", |
| 47 | hiddenCount: hidden, |
| 48 | }) |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | let oldLine = hunk.oldStart |
| 53 | let newLine = hunk.newStart |
| 54 | |
| 55 | for (const raw of hunk.lines || []) { |
| 56 | const firstChar = (raw as string)[0] |
| 57 | const content = (raw as string).slice(1) |
| 58 | |
| 59 | if (firstChar === "-") { |
| 60 | lines.push({ |
| 61 | oldLineNum: oldLine, |
| 62 | newLineNum: null, |
| 63 | type: "deletion", |
| 64 | content, |
| 65 | }) |
| 66 | oldLine++ |
| 67 | } else if (firstChar === "+") { |
| 68 | lines.push({ |
| 69 | oldLineNum: null, |
| 70 | newLineNum: newLine, |
| 71 | type: "addition", |
| 72 | content, |
| 73 | }) |
no test coverage detected