(item: DiffLine, width: number, maxWidth: number, dim: boolean, overrideTheme?: ThemeName)
| 235 | |
| 236 | // Process word-level diffs with manual wrapping support |
| 237 | function generateWordDiffElements(item: DiffLine, width: number, maxWidth: number, dim: boolean, overrideTheme?: ThemeName): React.ReactNode[] | null { |
| 238 | const { |
| 239 | type, |
| 240 | i, |
| 241 | wordDiff, |
| 242 | matchedLine, |
| 243 | originalCode |
| 244 | } = item; |
| 245 | if (!wordDiff || !matchedLine) { |
| 246 | return null; // This function only handles word-level diff rendering |
| 247 | } |
| 248 | const removedLineText = type === 'remove' ? originalCode : matchedLine.originalCode; |
| 249 | const addedLineText = type === 'remove' ? matchedLine.originalCode : originalCode; |
| 250 | const wordDiffs = calculateWordDiffs(removedLineText, addedLineText); |
| 251 | |
| 252 | // Check if we should use word-level diffing |
| 253 | const totalLength = removedLineText.length + addedLineText.length; |
| 254 | const changedLength = wordDiffs.filter(part => part.added || part.removed).reduce((sum, part) => sum + part.value.length, 0); |
| 255 | const changeRatio = changedLength / totalLength; |
| 256 | if (changeRatio > CHANGE_THRESHOLD || dim) { |
| 257 | return null; // Fall back to standard rendering for major changes |
| 258 | } |
| 259 | |
| 260 | // Calculate available width for content |
| 261 | const diffPrefix = type === 'add' ? '+' : '-'; |
| 262 | const diffPrefixWidth = diffPrefix.length; |
| 263 | const availableContentWidth = Math.max(1, width - maxWidth - 1 - diffPrefixWidth); |
| 264 | |
| 265 | // Manually wrap the word diff parts with better space efficiency |
| 266 | const wrappedLines: { |
| 267 | content: React.ReactNode[]; |
| 268 | contentWidth: number; |
| 269 | }[] = []; |
| 270 | let currentLine: React.ReactNode[] = []; |
| 271 | let currentLineWidth = 0; |
| 272 | wordDiffs.forEach((part, partIndex) => { |
| 273 | // Determine if this part should be shown for this line type |
| 274 | let shouldShow = false; |
| 275 | let partBgColor: 'diffAddedWord' | 'diffRemovedWord' | undefined; |
| 276 | if (type === 'add') { |
| 277 | if (part.added) { |
| 278 | shouldShow = true; |
| 279 | partBgColor = 'diffAddedWord'; |
| 280 | } else if (!part.removed) { |
| 281 | shouldShow = true; |
| 282 | } |
| 283 | } else if (type === 'remove') { |
| 284 | if (part.removed) { |
| 285 | shouldShow = true; |
| 286 | partBgColor = 'diffRemovedWord'; |
| 287 | } else if (!part.added) { |
| 288 | shouldShow = true; |
| 289 | } |
| 290 | } |
| 291 | if (!shouldShow) return; |
| 292 | |
| 293 | // Use wrapText to wrap this individual part if it's long |
| 294 | const partWrapped = wrapText(part.value, availableContentWidth, 'wrap'); |
no test coverage detected