Skip to content

Commit d6b2ef6

Browse files
authored
Merge pull request #86 from JBlond/php-diff-82
php-diff-82
2 parents 3f44195 + 0bf1a08 commit d6b2ef6

14 files changed

+419
-50
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ $options = [
6161
'ignoreWhitespace' => true,
6262
'ignoreCase' => true,
6363
'context' => 2,
64-
'cliColor' => true // for cli output
64+
'cliColor' => true, // for cli output
65+
'ignoreLines' => Diff::DIFF_IGNORE_LINE_BLANK,
6566
];
6667

6768
// Initialize the diff class.
@@ -140,7 +141,6 @@ at [jQuery-Merge-for-php-diff](https://github.com/Xiphe/jQuery-Merge-for-php-dif
140141

141142
## Todo
142143

143-
* Ability to ignore blank line changes
144144
* 3 way diff support
145145

146146
## Contributors

example/dark-theme.css

+26
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ a, a:visited {
9797
background: #EEBB00;
9898
}
9999

100+
.DifferencesSideBySide .ChangeIgnore .Left,
101+
.DifferencesSideBySide .ChangeIgnore .Right {
102+
background: #FBF2BF;
103+
}
104+
105+
.DifferencesSideBySide .ChangeIgnore .Left.Ignore {
106+
background: #4B4C57;
107+
}
108+
109+
.DifferencesSideBySide .ChangeIgnore .Right.Ignore {
110+
background: #4B4C57;
111+
}
112+
100113
/*
101114
* HTML Unified Diff
102115
*/
@@ -127,6 +140,19 @@ a, a:visited {
127140
color: #272822;
128141
}
129142

143+
.DifferencesUnified .ChangeIgnore .Left,
144+
.DifferencesUnified .ChangeIgnore .Right {
145+
background: #FBF2BF;
146+
}
147+
148+
.DifferencesUnified .ChangeIgnore .Left.Ignore {
149+
background: #4B4C57;
150+
}
151+
152+
.DifferencesUnified .ChangeIgnore .Right.Ignore {
153+
background: #4B4C57;
154+
}
155+
130156
/*
131157
* HTML Merged Diff
132158
*/

example/example.php

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
'trimEqual' => false,
2121
'ignoreWhitespace' => true,
2222
'ignoreCase' => true,
23+
'ignoreLines' => Diff::DIFF_IGNORE_LINE_EMPTY,
2324
];
2425

2526
// Choose one of the initializations.

example/styles.css

+26
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,19 @@ pre {
7878
background: #FFDD88;
7979
}
8080

81+
.DifferencesSideBySide .ChangeIgnore .Left,
82+
.DifferencesSideBySide .ChangeIgnore .Right {
83+
background: #FBF2BF;
84+
}
85+
86+
.DifferencesSideBySide .ChangeIgnore .Left.Ignore {
87+
background: #F7F7F7;
88+
}
89+
90+
.DifferencesSideBySide .ChangeIgnore .Right.Ignore {
91+
background: #F7F7F7;
92+
}
93+
8194
.Differences ins,
8295
.Differences del {
8396
text-decoration: none;
@@ -109,6 +122,19 @@ pre {
109122
background: #EE9999;
110123
}
111124

125+
.DifferencesUnified .ChangeIgnore .Left,
126+
.DifferencesUnified .ChangeIgnore .Right {
127+
background: #FBF2BF;
128+
}
129+
130+
.DifferencesUnified .ChangeIgnore .Left.Ignore {
131+
background: #F7F7F7;
132+
}
133+
134+
.DifferencesUnified .ChangeIgnore .Right.Ignore {
135+
background: #F7F7F7;
136+
}
137+
112138
/*
113139
* HTML Merged Diff
114140
*/

lib/jblond/Diff.php

+11-9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace jblond;
66

77
use InvalidArgumentException;
8+
use jblond\Diff\ConstantsInterface;
89
use jblond\Diff\SequenceMatcher;
910
use jblond\Diff\Similarity;
1011
use OutOfRangeException;
@@ -26,7 +27,7 @@
2627
* @version 2.3.3
2728
* @link https://github.com/JBlond/php-diff
2829
*/
29-
class Diff
30+
class Diff implements ConstantsInterface
3031
{
3132
/**
3233
* @var array The first version to compare.
@@ -46,21 +47,22 @@ class Diff
4647
private $groupedCodes;
4748

4849
/**
49-
* @var array<string, string> Associative array containing the default options available
50-
* for the diff class and their default value.
50+
* @var array Associative array containing the default options available for the diff class and their default value.
5151
*
52-
* - context The amount of lines to include around blocks that differ.
53-
* - trimEqual Strip blocks of equal lines from the start and end of the text.
54-
* - ignoreWhitespace When true, tabs and spaces are ignored while comparing.
55-
* The spacing of version1 is leading.
56-
* - ignoreCase When true, character casing is ignored while comparing.
57-
* The casing of version1 is leading.
52+
* - context The amount of lines to include around blocks that differ.
53+
* - trimEqual Strip blocks of equal lines from the start and end of the text.
54+
* - ignoreWhitespace True to ignore differences in tabs and spaces.
55+
* - ignoreCase True to ignore differences in character casing.
56+
* - ignoreLines 0: None.
57+
* 1: Ignore empty lines.
58+
* 2: Ignore blank lines.
5859
*/
5960
private $defaultOptions = [
6061
'context' => 3,
6162
'trimEqual' => true,
6263
'ignoreWhitespace' => false,
6364
'ignoreCase' => false,
65+
'ignoreLines' => self::DIFF_IGNORE_LINE_NONE,
6466
];
6567

6668
/**
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace jblond\Diff;
4+
5+
/**
6+
* Constant Interface
7+
*
8+
* Defines the library constants which needs to be shared across the different classes.
9+
*
10+
* PHP version 7.2 or greater
11+
*
12+
* @package jblond
13+
* @author Ferry Cools <[email protected]>
14+
* @copyright (c) 2020 Mario Brandt
15+
* @license New BSD License http://www.opensource.org/licenses/bsd-license.php
16+
* @version 2.3.0
17+
* @link https://github.com/JBlond/php-diff
18+
*/
19+
interface ConstantsInterface
20+
{
21+
/**
22+
* Flag to disable ignore of successive empty/blank lines.
23+
*/
24+
public const DIFF_IGNORE_LINE_NONE = 0;
25+
/**
26+
* Flag to ignore empty lines.
27+
*/
28+
public const DIFF_IGNORE_LINE_EMPTY = 1;
29+
/**
30+
* Flag to ignore blank lines. (Lines which contain no or only non printable characters.)
31+
*/
32+
public const DIFF_IGNORE_LINE_BLANK = 2;
33+
}

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

+66
Original file line numberDiff line numberDiff line change
@@ -282,4 +282,70 @@ public function generateDiffFooter(): string
282282
{
283283
return '</table>';
284284
}
285+
286+
/**
287+
* @inheritDoc
288+
*
289+
* @return string Html code representing table rows showing ignored text.
290+
*/
291+
public function generateLinesIgnore(array $changes): string
292+
{
293+
$html = '';
294+
295+
// Is below comparison result ever false?
296+
if (count($changes['base']['lines']) >= count($changes['changed']['lines'])) {
297+
foreach ($changes['base']['lines'] as $lineNo => $line) {
298+
$fromLine = $changes['base']['offset'] + $lineNo + 1;
299+
$toLine = '&nbsp;';
300+
$changedLine = '&nbsp;';
301+
if (isset($changes['changed']['lines'][$lineNo])) {
302+
$toLine = $changes['changed']['offset'] + $lineNo + 1;
303+
$changedLine = $changes['changed']['lines'][$lineNo];
304+
}
305+
306+
$html .= <<<HTML
307+
<tr>
308+
<th>$fromLine</th>
309+
<td class="Left">
310+
<span>$line</span>
311+
</td>
312+
<th>$toLine</th>
313+
<td class="Right Ignore">
314+
<span>$changedLine</span>
315+
</td>
316+
</tr>
317+
HTML;
318+
}
319+
320+
return $html;
321+
}
322+
323+
foreach ($changes['changed']['lines'] as $lineNo => $changedLine) {
324+
$toLine = $changes['changed']['offset'] + $lineNo + 1;
325+
$fromLine = '&nbsp;';
326+
$line = '&nbsp;';
327+
if (isset($changes['base']['lines'][$lineNo])) {
328+
$fromLine = $changes['base']['offset'] + $lineNo + 1;
329+
$line = $changes['base']['lines'][$lineNo];
330+
}
331+
332+
$line = str_replace(["\0", "\1"], $this->options['deleteMarkers'], $line);
333+
$changedLine = str_replace(["\0", "\1"], $this->options['insertMarkers'], $changedLine);
334+
335+
$html .= <<<HTML
336+
<tr>
337+
<th>$fromLine</th>
338+
<td class="Left Ignore">
339+
<span>$line</span>
340+
</td>
341+
<th>$toLine</th>
342+
<td class="Right">
343+
<span>$changedLine</span>
344+
</td>
345+
</tr>
346+
HTML;
347+
}
348+
349+
return $html;
350+
}
285351
}

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

+38
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,44 @@ public function generateLinesReplace(array $changes): string
219219
return $html;
220220
}
221221

222+
/**
223+
* @inheritDoc
224+
*
225+
* @return string Html code representing table rows showing modified text.
226+
*/
227+
public function generateLinesIgnore(array $changes): string
228+
{
229+
$html = '';
230+
231+
foreach ($changes['base']['lines'] as $lineNo => $line) {
232+
$fromLine = $changes['base']['offset'] + $lineNo + 1;
233+
$html .= <<<HTML
234+
<tr>
235+
<th>$fromLine</th>
236+
<th></th>
237+
<td class="Left Ignore">
238+
<span>$line</span>
239+
</td>
240+
</tr>
241+
HTML;
242+
}
243+
244+
foreach ($changes['changed']['lines'] as $lineNo => $line) {
245+
$toLine = $changes['changed']['offset'] + $lineNo + 1;
246+
$html .= <<<HTML
247+
<tr>
248+
<th></th>
249+
<th>$toLine</th>
250+
<td class="Right Ignore">
251+
<span>$line</span>
252+
</td>
253+
</tr>
254+
HTML;
255+
}
256+
257+
return $html;
258+
}
259+
222260
/**
223261
* @inheritDoc
224262
*

lib/jblond/Diff/Renderer/MainRenderer.php

+32-10
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,23 @@ public function renderOutput(array $changes, object $subRenderer)
6565
strlen($this->options['equalityMarkers'][1])
6666
);
6767

68+
$deprecationTriggered = false;
6869
foreach ($blocks as $change) {
70+
if (
71+
$subRenderer instanceof MainRenderer &&
72+
!method_exists($subRenderer, 'generateLinesIgnore') &&
73+
$change['tag'] == 'ignore'
74+
) {
75+
if (!$deprecationTriggered) {
76+
trigger_error(
77+
'The use of a subRenderer without method generateLinesIgnore() is deprecated!',
78+
E_USER_DEPRECATED
79+
);
80+
$deprecationTriggered = true;
81+
}
82+
$change['tag'] =
83+
(count($change['base']['lines']) > count($change['changed']['lines'])) ? 'delete' : 'insert';
84+
}
6985
$output .= $subRenderer->generateBlockHeader($change);
7086
switch ($change['tag']) {
7187
case 'equal':
@@ -80,6 +96,10 @@ public function renderOutput(array $changes, object $subRenderer)
8096
case 'replace':
8197
$output .= $subRenderer->generateLinesReplace($change);
8298
break;
99+
case 'ignore':
100+
// TODO: Keep backward compatible with renderers?
101+
$output .= $subRenderer->generateLinesIgnore($change);
102+
break;
83103
}
84104

85105
$output .= $subRenderer->generateBlockFooter($change);
@@ -124,12 +144,14 @@ protected function renderSequences(): array
124144
* 4 - The end line in the second sequence.
125145
*
126146
* The different types of tags include:
127-
* replace - The string from $startOld to $endOld in $oldText should be replaced by
147+
* replace - The string in $oldText from $startOld to $endOld, should be replaced by
128148
* the string in $newText from $startNew to $endNew.
129149
* delete - The string in $oldText from $startOld to $endNew should be deleted.
130150
* insert - The string in $newText from $startNew to $endNew should be inserted at $startOld in
131151
* $oldText.
132152
* equal - The two strings with the specified ranges are equal.
153+
* ignore - The string in $oldText from $startOld to $endOld and
154+
* the string in $newText from $startNew to $endNew are different, but considered to be equal.
133155
*/
134156

135157
$blockSizeOld = $endOld - $startOld;
@@ -146,23 +168,23 @@ protected function renderSequences(): array
146168
$oldBlock = $this->formatLines(array_slice($oldText, $startOld, $blockSizeOld));
147169
$newBlock = $this->formatLines(array_slice($newText, $startNew, $blockSizeNew));
148170

149-
if ($tag == 'equal') {
150-
// Old block equals New block
171+
if ($tag != 'delete' && $tag != 'insert') {
172+
// Old block "equals" New block or is replaced.
151173
$blocks[$lastBlock]['base']['lines'] += $oldBlock;
152174
$blocks[$lastBlock]['changed']['lines'] += $newBlock;
153175
continue;
154176
}
155177

156-
if ($tag == 'replace' || $tag == 'delete') {
157-
// Inline differences or old block doesn't exist in the new text.
178+
if ($tag == 'delete') {
179+
// Block of version1 doesn't exist in version2.
158180
$blocks[$lastBlock]['base']['lines'] += $oldBlock;
181+
continue;
159182
}
160183

161-
if ($tag == 'replace' || $tag == 'insert') {
162-
// Inline differences or the new block doesn't exist in the old text.
163-
$blocks[$lastBlock]['changed']['lines'] += $newBlock;
164-
}
184+
// Block of version2 doesn't exist in version1.
185+
$blocks[$lastBlock]['changed']['lines'] += $newBlock;
165186
}
187+
166188
$changes[] = $blocks;
167189
}
168190

@@ -291,7 +313,7 @@ public function sequenceToArray(string $pattern, string $sequence): array
291313
* E.g.
292314
* <pre>
293315
* 1234567
294-
* OLd => "abcdefg" Start marker inserted at position 3
316+
* Old => "abcdefg" Start marker inserted at position 3
295317
* New => "ab123fg" End marker inserted at position 6
296318
* </pre>
297319
*

0 commit comments

Comments
 (0)