// A file's lines as the review store counts them (format ยง7.3, blobLines in // src/main/reviews/store/anchors.ts): each LF ends a line, and a last line // without LF counts. An editor instead counts the empty line after a final // LF, which the viewer must neither show nor offer for comments. /** Lines in `text` as the store counts them: 0 for an empty text. */ export function lineCount(text: string): number { let n = 0 for (let i = text.indexOf('\n'); i >= 0; i = text.indexOf('\n', i + 1)) n++ return text.length && !text.endsWith('\n') ? n + 1 : n } /** * The text an editor shows: without the line break that ends the last line * (LF or CRLF), so it has one line per store line. Line numbers and the * positions of every character stay those of `text`. */ export const viewText = (text: string): string => text.replace(/\r?\n$/, '') /** A 1-based line range cut to lines 1..count, or null when none of it is a line. */ export function clampLines(range: readonly [number, number], count: number): [number, number] | null { const from = Math.max(1, range[0]) const to = Math.min(count, range[1]) return from <= to ? [from, to] : null }