import { diffArrays } from "diff"; import type { BlameRange } from "~/lib/code-intel"; const MAX_EDIT_LENGTH = 20_000; const DIFF_TIMEOUT_MS = 1000; /** Maps each new-version line index to its old-version index (-1 when added); null if the diff gave up. */ export function mapLines(oldLines: string[], newLines: string[]): Int32Array | null { const changes = diffArrays(oldLines, newLines, { maxEditLength: MAX_EDIT_LENGTH, timeout: DIFF_TIMEOUT_MS }); if (!changes) return null; const map = new Int32Array(newLines.length).fill(-1); let oldIndex = 0; let newIndex = 0; for (const change of changes) { const count = change.count; if (change.added) newIndex += count; else if (change.removed) oldIndex += count; else { for (let offset = 0; offset < count; offset++) map[newIndex + offset] = oldIndex + offset; oldIndex += count; newIndex += count; } } return map; } export function splitLines(text: string): string[] { const lines = text.split("\n"); if (lines.length > 1 && lines[lines.length - 1] === "") lines.pop(); return lines; } export function compressRanges(owners: Array, fallback: string): BlameRange[] { const ranges: BlameRange[] = []; for (let line = 0; line < owners.length; line++) { const sha = owners[line] ?? fallback; const last = ranges[ranges.length - 1]; if (last && last.sha === sha) last.count++; else ranges.push({ start: line, count: 1, sha }); } return ranges; } export function expandRanges(ranges: BlameRange[], lineCount: number): Array { const owners = new Array(lineCount).fill(null); for (const range of ranges) { for (let line = range.start; line < range.start + range.count && line < lineCount; line++) owners[line] = range.sha; } return owners; }