(
diffLine1: string,
diffLine2: string,
isCombined: boolean,
config: RenderConfig = {},
)
| 237 | * Highlight differences between @diffLine1 and @diffLine2 using <ins> and <del> tags |
| 238 | */ |
| 239 | export function diffHighlight( |
| 240 | diffLine1: string, |
| 241 | diffLine2: string, |
| 242 | isCombined: boolean, |
| 243 | config: RenderConfig = {}, |
| 244 | ): HighlightedLines { |
| 245 | const { matching, maxLineLengthHighlight, matchWordsThreshold, diffStyle } = { ...defaultRenderConfig, ...config }; |
| 246 | |
| 247 | const line1 = deconstructLine(diffLine1, isCombined, false); |
| 248 | const line2 = deconstructLine(diffLine2, isCombined, false); |
| 249 | |
| 250 | if (line1.content.length > maxLineLengthHighlight || line2.content.length > maxLineLengthHighlight) { |
| 251 | return { |
| 252 | oldLine: { |
| 253 | prefix: line1.prefix, |
| 254 | content: escapeForHtml(line1.content), |
| 255 | }, |
| 256 | newLine: { |
| 257 | prefix: line2.prefix, |
| 258 | content: escapeForHtml(line2.content), |
| 259 | }, |
| 260 | }; |
| 261 | } |
| 262 | |
| 263 | const diff = |
| 264 | diffStyle === 'char' |
| 265 | ? jsDiff.diffChars(line1.content, line2.content) |
| 266 | : jsDiff.diffWordsWithSpace(line1.content, line2.content); |
| 267 | |
| 268 | const changedWords: jsDiff.Change[] = []; |
| 269 | if (diffStyle === 'word' && matching === 'words') { |
| 270 | const removed = diff.filter(element => element.removed); |
| 271 | const added = diff.filter(element => element.added); |
| 272 | const chunks = matcher(added, removed); |
| 273 | chunks.forEach(chunk => { |
| 274 | if (chunk[0].length === 1 && chunk[1].length === 1) { |
| 275 | const dist = distance(chunk[0][0], chunk[1][0]); |
| 276 | if (dist < matchWordsThreshold) { |
| 277 | changedWords.push(chunk[0][0]); |
| 278 | changedWords.push(chunk[1][0]); |
| 279 | } |
| 280 | } |
| 281 | }); |
| 282 | } |
| 283 | |
| 284 | const highlightedLine = diff.reduce((highlightedLine, part) => { |
| 285 | const elemType = part.added ? 'ins' : part.removed ? 'del' : null; |
| 286 | const addClass = changedWords.indexOf(part) > -1 ? ' class="d2h-change"' : ''; |
| 287 | const escapedValue = escapeForHtml(part.value); |
| 288 | |
| 289 | return elemType !== null |
| 290 | ? `${highlightedLine}<${elemType}${addClass}>${escapedValue}</${elemType}>` |
| 291 | : `${highlightedLine}${escapedValue}`; |
| 292 | }, ''); |
| 293 | |
| 294 | return { |
| 295 | oldLine: { |
| 296 | prefix: line1.prefix, |
no test coverage detected
searching dependent graphs…