( parsedLines: DiffLine[], filename: string | undefined, tabWidth = DEFAULT_TAB_WIDTH, availableTerminalHeight: number | undefined, terminalWidth: number, )
| 166 | }; |
| 167 | |
| 168 | const renderDiffContent = ( |
| 169 | parsedLines: DiffLine[], |
| 170 | filename: string | undefined, |
| 171 | tabWidth = DEFAULT_TAB_WIDTH, |
| 172 | availableTerminalHeight: number | undefined, |
| 173 | terminalWidth: number, |
| 174 | ) => { |
| 175 | // 1. Normalize whitespace (replace tabs with spaces) *before* further processing |
| 176 | const normalizedLines = parsedLines.map((line) => ({ |
| 177 | ...line, |
| 178 | content: line.content.replace(/\t/g, ' '.repeat(tabWidth)), |
| 179 | })); |
| 180 | |
| 181 | // Filter out non-displayable lines (hunks, potentially 'other') using the normalized list |
| 182 | const displayableLines = normalizedLines.filter( |
| 183 | (l) => l.type !== 'hunk' && l.type !== 'other', |
| 184 | ); |
| 185 | |
| 186 | if (displayableLines.length === 0) { |
| 187 | return ( |
| 188 | <Box borderStyle="round" borderColor={Colors.Gray} padding={1}> |
| 189 | <Text dimColor>No changes detected.</Text> |
| 190 | </Box> |
| 191 | ); |
| 192 | } |
| 193 | |
| 194 | const maxLineNumber = Math.max( |
| 195 | 0, |
| 196 | ...displayableLines.map((l) => l.oldLine ?? 0), |
| 197 | ...displayableLines.map((l) => l.newLine ?? 0), |
| 198 | ); |
| 199 | const gutterWidth = Math.max(1, maxLineNumber.toString().length); |
| 200 | |
| 201 | const fileExtension = filename?.split('.').pop() || null; |
| 202 | const language = fileExtension |
| 203 | ? getLanguageFromExtension(fileExtension) |
| 204 | : null; |
| 205 | |
| 206 | // Calculate the minimum indentation across all displayable lines |
| 207 | let baseIndentation = Infinity; // Start high to find the minimum |
| 208 | for (const line of displayableLines) { |
| 209 | // Only consider lines with actual content for indentation calculation |
| 210 | if (line.content.trim() === '') continue; |
| 211 | |
| 212 | const firstCharIndex = line.content.search(/\S/); // Find index of first non-whitespace char |
| 213 | const currentIndent = firstCharIndex === -1 ? 0 : firstCharIndex; // Indent is 0 if no non-whitespace found |
| 214 | baseIndentation = Math.min(baseIndentation, currentIndent); |
| 215 | } |
| 216 | // If baseIndentation remained Infinity (e.g., no displayable lines with content), default to 0 |
| 217 | if (!isFinite(baseIndentation)) { |
| 218 | baseIndentation = 0; |
| 219 | } |
| 220 | |
| 221 | const key = filename |
| 222 | ? `diff-box-${filename}` |
| 223 | : `diff-box-${crypto.createHash('sha1').update(JSON.stringify(parsedLines)).digest('hex')}`; |
| 224 | |
| 225 | let lastLineNumber: number | null = null; |
no test coverage detected