/* eslint-disable prefer-named-capture-group */ export function getChangedLineNumbersFromPatch(patch: string): number[] { const fileLinesRegex = /^@@ -([0-9]*),?\S* \+([0-9]*),?/; const frontMatterRegex = /^([a-z_]+: .+)|(---)$/; const codeSampleRegex = /^```.*$/; const lineNumbersInDiff: number[] = []; function splitIntoParts(lines: string[], separator: string) { const parts: string[][] = []; let currentPart: undefined | string[] = undefined; lines.forEach((line) => { if (line.startsWith(separator)) { if (currentPart) { parts.push(currentPart); } currentPart = [line]; } else if (currentPart) { currentPart.push(line); } }); if (currentPart) { parts.push(currentPart); } return parts; } splitIntoParts(patch.split('\n'), '@@ ').forEach((lines) => { const fileLinesLine = lines.shift() as string; const matches = fileLinesLine.match(fileLinesRegex); if (!matches) return; const [, , startLineNo] = matches; let lineNo = parseInt(startLineNo, 10); let inCodeSample: boolean = false; lines.forEach((line: string) => { if (line.startsWith('+')) { // Don't count blank lines and front matter changes const newLine: string = line.substring(1); const codeFenceLine: boolean = Boolean(newLine.match(codeSampleRegex)); if (newLine.length > 0 && !newLine.match(frontMatterRegex) && !codeFenceLine && !inCodeSample) { lineNumbersInDiff.push(lineNo); } inCodeSample = inCodeSample ? !codeFenceLine : codeFenceLine; } else if (line.startsWith('-')) { lineNo -= 1; } lineNo += 1; }); }); return lineNumbersInDiff; }