From acbfd7d6a03395479a5dfb2be092bd12daa02e11 Mon Sep 17 00:00:00 2001 From: DigiLive Date: Sat, 27 Mar 2021 11:36:42 +0100 Subject: [PATCH] Fix #90 - Merged Diff shows result only partially * Renderer doesn't show lines which where added to version 2 of a replaced block. Code assumed the same amount of lines in replacement blocks at both versions. Now it handles replacement block differently when the amount of lines are equal or differs. * Code cleanup. * ClassName for lines of replacement blocks are incorrect. Insertion is insinuated, but should be replacement. --- example/dark-theme.css | 2 +- example/styles.css | 2 +- lib/jblond/Diff/Renderer/Html/Merged.php | 83 ++++++++++++++++-------- 3 files changed, 57 insertions(+), 30 deletions(-) diff --git a/example/dark-theme.css b/example/dark-theme.css index bbbc31b..175b075 100644 --- a/example/dark-theme.css +++ b/example/dark-theme.css @@ -130,7 +130,7 @@ a, a:visited { /* * HTML Merged Diff */ -.DifferencesMerged td.ChangeInsert { +.DifferencesMerged td.ChangeReplace { background: #FFDD88; color: #272822; } diff --git a/example/styles.css b/example/styles.css index bd61746..5dd6abe 100644 --- a/example/styles.css +++ b/example/styles.css @@ -112,7 +112,7 @@ pre { /* * HTML Merged Diff */ -.DifferencesMerged td.ChangeInsert { +.DifferencesMerged td.ChangeReplace { background: #FFDD88; } diff --git a/lib/jblond/Diff/Renderer/Html/Merged.php b/lib/jblond/Diff/Renderer/Html/Merged.php index ab75577..679b6a7 100644 --- a/lib/jblond/Diff/Renderer/Html/Merged.php +++ b/lib/jblond/Diff/Renderer/Html/Merged.php @@ -112,7 +112,7 @@ public function generateSkippedLines(): string return << - $marker + $marker … HTML; @@ -136,7 +136,7 @@ public function generateLinesEqual(array $changes): string $html .= << - $fromLine + $fromLine $line HTML; @@ -165,7 +165,7 @@ public function generateLinesInsert(array $changes): string $html .= << - $toLine + $toLine $line HTML; @@ -208,41 +208,68 @@ public function generateLinesDelete(array $changes): string */ public function generateLinesReplace(array $changes): string { - $html = ''; - $headerClass = ''; - - foreach ($changes['base']['lines'] as $lineNo => $line) { - $fromLine = $changes['base']['offset'] + $lineNo + 1 + $this->lineOffset; - if (!$lineNo && $this->lastDeleted !== null) { - $headerClass = 'ChangeDelete'; + $html = ''; + $baseLineCount = count($changes['base']['lines']); + $changedLineCount = count($changes['changed']['lines']); + + if (count($changes['base']['lines']) == $changedLineCount) { + // Lines of Version 1 are modified at version 2. + foreach ($changes['base']['lines'] as $lineNo => $line) { + $fromLine = $changes['base']['offset'] + $lineNo + 1 + $this->lineOffset; + + // Capture line-parts which are added to the same line at version 2. + $addedParts = []; + preg_match_all('/\x0.*?\x1/', $changes['changed']['lines'][$lineNo], $addedParts, PREG_PATTERN_ORDER); + array_unshift($addedParts[0], ''); + + // Inline Replacement: + // Concatenate line-parts which are removed at version2 with line-parts which are added at version 2. + $line = preg_replace_callback( + '/\x0.*?\x1/', + function ($removedParts) use ($addedParts) { + $addedPart = str_replace(["\0", "\1"], $this->options['insertMarkers'], next($addedParts[0])); + $removedPart = str_replace(["\0", "\1"], $this->options['deleteMarkers'], $removedParts[0]); + + return "$removedPart$addedPart"; + }, + $line + ); + + $html .= << + $fromLine + $line + +HTML; } - // Capture added parts. - $addedParts = []; - preg_match_all('/\x0.*?\x1/', $changes['changed']['lines'][$lineNo], $addedParts, PREG_PATTERN_ORDER); - array_unshift($addedParts[0], ''); + return $html; + } - // Concatenate removed parts with added parts. - $line = preg_replace_callback( - '/\x0.*?\x1/', - function ($removedParts) use ($addedParts) { - $addedPart = str_replace(["\0", "\1"], $this->options['insertMarkers'], next($addedParts[0])); - $removedPart = str_replace(["\0", "\1"], $this->options['deleteMarkers'], $removedParts[0]); + // More or less lines at version 2. Block of version 1 is replaced by block of version 2. + $title = ''; - return "$removedPart$addedPart"; - }, - $line - ); + foreach ($changes['changed']['lines'] as $lineNo => $line) { + $toLine = $changes['changed']['offset'] + $lineNo + 1; - $html .= << $baseLine) { + $title .= $changes['base']['offset'] + $baseLineNo + 1 . ": $baseLine\n"; + } + } + + $title = htmlentities($title); + $html .= << - $fromLine - $line + $toLine + $line HTML; - $this->lastDeleted = null; } + $this->lineOffset = $this->lineOffset + $changedLineCount - $baseLineCount; + return $html; }