Skip to content

Commit acbfd7d

Browse files
committed
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.
1 parent 7eba340 commit acbfd7d

File tree

3 files changed

+57
-30
lines changed

3 files changed

+57
-30
lines changed

example/dark-theme.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ a, a:visited {
130130
/*
131131
* HTML Merged Diff
132132
*/
133-
.DifferencesMerged td.ChangeInsert {
133+
.DifferencesMerged td.ChangeReplace {
134134
background: #FFDD88;
135135
color: #272822;
136136
}

example/styles.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ pre {
112112
/*
113113
* HTML Merged Diff
114114
*/
115-
.DifferencesMerged td.ChangeInsert {
115+
.DifferencesMerged td.ChangeReplace {
116116
background: #FFDD88;
117117
}
118118

lib/jblond/Diff/Renderer/Html/Merged.php

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public function generateSkippedLines(): string
112112

113113
return <<<HTML
114114
<tr>
115-
<th class="$headerClass" title="{$this->lastDeleted}">$marker</th>
115+
<th class="$headerClass" title="$this->lastDeleted">$marker</th>
116116
<td class="Skipped">&hellip;</td>
117117
</tr>
118118
HTML;
@@ -136,7 +136,7 @@ public function generateLinesEqual(array $changes): string
136136

137137
$html .= <<<HTML
138138
<tr>
139-
<th class="$headerClass" title="{$this->lastDeleted}">$fromLine</th>
139+
<th class="$headerClass" title="$this->lastDeleted">$fromLine</th>
140140
<td>$line</td>
141141
</tr>
142142
HTML;
@@ -165,7 +165,7 @@ public function generateLinesInsert(array $changes): string
165165

166166
$html .= <<<HTML
167167
<tr>
168-
<th class="$headerClass" title="{$this->lastDeleted}">$toLine</th>
168+
<th class="$headerClass" title="$this->lastDeleted">$toLine</th>
169169
<td><ins>$line</ins></td>
170170
</tr>
171171
HTML;
@@ -208,41 +208,68 @@ public function generateLinesDelete(array $changes): string
208208
*/
209209
public function generateLinesReplace(array $changes): string
210210
{
211-
$html = '';
212-
$headerClass = '';
213-
214-
foreach ($changes['base']['lines'] as $lineNo => $line) {
215-
$fromLine = $changes['base']['offset'] + $lineNo + 1 + $this->lineOffset;
216-
if (!$lineNo && $this->lastDeleted !== null) {
217-
$headerClass = 'ChangeDelete';
211+
$html = '';
212+
$baseLineCount = count($changes['base']['lines']);
213+
$changedLineCount = count($changes['changed']['lines']);
214+
215+
if (count($changes['base']['lines']) == $changedLineCount) {
216+
// Lines of Version 1 are modified at version 2.
217+
foreach ($changes['base']['lines'] as $lineNo => $line) {
218+
$fromLine = $changes['base']['offset'] + $lineNo + 1 + $this->lineOffset;
219+
220+
// Capture line-parts which are added to the same line at version 2.
221+
$addedParts = [];
222+
preg_match_all('/\x0.*?\x1/', $changes['changed']['lines'][$lineNo], $addedParts, PREG_PATTERN_ORDER);
223+
array_unshift($addedParts[0], '');
224+
225+
// Inline Replacement:
226+
// Concatenate line-parts which are removed at version2 with line-parts which are added at version 2.
227+
$line = preg_replace_callback(
228+
'/\x0.*?\x1/',
229+
function ($removedParts) use ($addedParts) {
230+
$addedPart = str_replace(["\0", "\1"], $this->options['insertMarkers'], next($addedParts[0]));
231+
$removedPart = str_replace(["\0", "\1"], $this->options['deleteMarkers'], $removedParts[0]);
232+
233+
return "$removedPart$addedPart";
234+
},
235+
$line
236+
);
237+
238+
$html .= <<<HTML
239+
<tr>
240+
<th>$fromLine</th>
241+
<td>$line</td>
242+
</tr>
243+
HTML;
218244
}
219245

220-
// Capture added parts.
221-
$addedParts = [];
222-
preg_match_all('/\x0.*?\x1/', $changes['changed']['lines'][$lineNo], $addedParts, PREG_PATTERN_ORDER);
223-
array_unshift($addedParts[0], '');
246+
return $html;
247+
}
224248

225-
// Concatenate removed parts with added parts.
226-
$line = preg_replace_callback(
227-
'/\x0.*?\x1/',
228-
function ($removedParts) use ($addedParts) {
229-
$addedPart = str_replace(["\0", "\1"], $this->options['insertMarkers'], next($addedParts[0]));
230-
$removedPart = str_replace(["\0", "\1"], $this->options['deleteMarkers'], $removedParts[0]);
249+
// More or less lines at version 2. Block of version 1 is replaced by block of version 2.
250+
$title = '';
231251

232-
return "$removedPart$addedPart";
233-
},
234-
$line
235-
);
252+
foreach ($changes['changed']['lines'] as $lineNo => $line) {
253+
$toLine = $changes['changed']['offset'] + $lineNo + 1;
236254

237-
$html .= <<<HTML
255+
if (!$lineNo) {
256+
$title = "Lines replaced at {$this->options['title1']}:\n";
257+
foreach ($changes['base']['lines'] as $baseLineNo => $baseLine) {
258+
$title .= $changes['base']['offset'] + $baseLineNo + 1 . ": $baseLine\n";
259+
}
260+
}
261+
262+
$title = htmlentities($title);
263+
$html .= <<<HTML
238264
<tr>
239-
<th class="$headerClass" title="{$this->lastDeleted}">$fromLine</th>
240-
<td>$line</td>
265+
<th class="ChangeReplace" title="$title">$toLine</th>
266+
<td class="ChangeReplace">$line</td>
241267
</tr>
242268
HTML;
243-
$this->lastDeleted = null;
244269
}
245270

271+
$this->lineOffset = $this->lineOffset + $changedLineCount - $baseLineCount;
272+
246273
return $html;
247274
}
248275

0 commit comments

Comments
 (0)