Skip to content

Commit 5d492a4

Browse files
committed
Merge pull request #14 from caxy/feature-list_diffing-new
Created ListDiff class to handle diffing of lists.
2 parents 4888c71 + fab1ef7 commit 5d492a4

File tree

4 files changed

+716
-28
lines changed

4 files changed

+716
-28
lines changed

demo/demo_text.php

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,26 @@
22

33
$demos = array(
44
array(
5-
'old' => "<p><i>This is</i> some sample text to <strong>demonstrate</strong> the capability of the <strong>HTML diff tool</strong>.</p>
6-
<p>It is based on the <b>Ruby</b> implementation found <a href='http://github.com/myobie/htmldiff'>here</a>. Note how the link has no tooltip</p>
7-
<table cellpadding='0' cellspacing='0'>
8-
<tr><td>Some sample text</td><td>Some sample value</td></tr>
9-
<tr><td>Data 1 (this row will be removed)</td><td>Data 2</td></tr>
10-
</table>
11-
Here is a number 2 32<br />
12-
Section 602.1 NAME OF SECTION<br />
13-
Large number 5,000",
5+
'old' => '<p>The required capacity of each door opening shall be sufficient for the <em>occupant load</em> thereof and shall provide a minimum clear width of 32 inches (813 mm). Clear openings of doorways with swinging doors shall be measured between the face of the door and the stop, with the door open 90 degrees (1.57 rad). Where this section requires a minimum clear width of 32 inches (813 mm) and a door opening includes two door leaves without a mullion, one leaf shall provide a clear opening width of 32 inches (813 mm). The maximum width of a swinging door leaf shall be 48 inches (1219 mm) nominal. <em>Means of egress</em> doors in a Group I-2 occupancy used for the movement of beds shall provide a clear width not less than 41<sup>1</sup>/ <sub><sub>2 </sub></sub> inches (1054 mm). The height of door openings shall be not less than 80 inches (2032 mm).</p><ul class="exception"><li><strong>Exceptions:</strong><ol><li>The minimum and maximum width shall not apply to door openings that are not part of the required <em>means of egress </em>in Group R-2 and R-3 occupancies.</li><li>Door openings to resident <em>sleeping units</em> in Group I-3 occupancies shall have a clear width of not less than 28 inches (711 mm).</li><li>Door openings to storage closets less than 10 square feet (0.93 m<sup>2</sup>) in area shall not be limited by the minimum width.</li><li>Width of door leaves in revolving doors that comply with Section 1010.1.4.1 shall not be limited.</li><li>Door openings within a <em>dwelling unit</em> or <em>sleeping unit</em> shall be not less than 78 inches (1981 mm) in height.</li><li>Exterior door openings in <em>dwelling units</em> and <em>sleeping units</em>, other than the required <em>exit </em>door, shall be not less than 76 inches (1930 mm) in height.</li><li>In other than Group R-1 occupancies, the minimum widths shall not apply to interior egress doors within a <em>dwelling unit</em> or <em>sleeping unit</em> that is not required to be an <em>Accessible unit</em>, <em>Type A unit </em>or <em>Type B unit</em>.</li><li>Door openings required to be <em>accessible</em> within <em>Type B units</em> shall have a minimum clear width of 31.75 inches (806 mm).</li><li>Doors to walk-in freezers and coolers less than 1,000 square feet (93 m<sup>2</sup>) in area shall have a maximum width of 60 inches (1524 mm).</li><li>In Group R-1 <em>dwelling units</em> or <em>sleeping units</em> not required to be <em>Accessible units</em>, the minimum width shall not apply to doors for showers or saunas.</li></ol></li></ul>',
146

15-
'new' => "<p>This is some sample <strong>text to</strong> demonstrate the awesome capabilities of the <strong>HTML <u>diff</u> tool</strong>.</p><br/><br/>Extra spacing here that was not here before.
16-
<p>It is <i>based</i> on the Ruby implementation found <a title='Cool tooltip' href='http://github.com/myobie/htmldiff'>here</a>. Note how the link has a tooltip now and the HTML diff algorithm has preserved formatting.</p>
17-
<table cellpadding='0' cellspacing='0'>
18-
<tr><td>Some sample <strong>bold text</strong></td><td>Some sample value</td></tr>
19-
</table>
20-
Here is a number 2 <sup>32</sup><br />
21-
Section 602.2 NAME OF SECTION.<br />
22-
Large numbers 5,001 and 10,000,154"
7+
'new' => '<p>The required capacity of each door opening shall be sufficient for the <span class="content_italics">occupant load</span> thereof and shall provide a minimum clear&nbsp;opening&nbsp;width of 32 inches (813 mm). The clear opening width&nbsp;of doorways with swinging doors shall be measured between the face of the door and the stop, with the door open 90 degrees (1.57 rad). Where this section requires a minimum clear opening width of 32 inches (813 mm) and a door opening includes two door leaves without a mullion, one leaf shall provide a minimum clear opening width of 32 inches (813 mm). In Group I-2, doors serving as &nbsp;<em>m</em><span class="content_italics">eans of egress</span> doors where&nbsp;used for the movement of beds shall provide a minimum clear opening width of&nbsp;41<sup>1</sup>/ <sub>2 </sub> inches (1054 mm). The maximum width of a swinging door leaf shall be 48 inches (1219 mm) nominal. The minimum clear opening height of doors shall be 80 inches (2032 mm).</p>
8+
<ul class="exception">
9+
<li><span class="content_bold">Exceptions:</span>
10+
<ol>
11+
<li>In Group R-2 and R-3 dwelling and sleeping units that are not required to be an Accessible unit, Type A unit or Type B unit, the minimum and maximum width shall not apply to door openings that are not part of the required <span class="content_italics">means of egress</span>.</li>
12+
<li>In Group I-3, door openings to resident <span class="content_italics">sleeping units</span>&nbsp;that are not required to be an Accessible unit shall have a minimum clear opening width of 28 inches (711 mm).</li>
13+
<li>Door openings to storage closets less than 10 square feet (0.93 m<sup>2</sup>) in area shall not be limited by the minimum clear opening width.</li>
14+
<li>The width of door leaves in revolving doors that comply with Section 1010.1.4.1 shall not be limited.</li>
15+
<li>Door openings within a <span class="content_italics">dwelling unit</span> or <span class="content_italics">sleeping unit</span> shall have a minimum clear opening height&nbsp;than 78 inches (1981 mm) in height.</li>
16+
<li>In dwelling and sleeping units that are not required to be Accessible, Type A or Type B units, exterior door openings, other than the required <span class="content_italics">exit </span>door, shall have a minimum clear opening height of&nbsp;76 inches (1930 mm) in height.</li>
17+
<li>Groups I-1, R-2, R-3 and R-4&nbsp;occupancies, in dwelling and sleeping units that are not required to be Accessible, Type A or Type B units, the minimum clear opening widths shall not apply to interior egress doors.</li>
18+
<li>Door openings within <span class="content_italics">Type B units</span>&nbsp;intended for user passage shall have a minimum clear opening width of 31.75 inches (806 mm).</li>
19+
<li>Doors to walk-in freezers and coolers less than 1,000 square feet (93 m<sup>2</sup>) in area shall have a maximum width of 60 inches (1524 mm) nominal.</li>
20+
<li>The minimum clear opening width shall not apply to doors for non-accessible shower or sauna compartments.</li>
21+
<li>The minimum clear opening width shall not apply to the doors for non-accessible toilet stalls.</li>
22+
</ol>
23+
</li>
24+
</ul>'
2325
)
2426
);
2527
header('Content-Type: application/json');

demo/index.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
'Caxy/HtmlDiff/HtmlDiff',
1111
'Caxy/HtmlDiff/Match',
1212
'Caxy/HtmlDiff/Operation',
13+
'Caxy/HtmlDiff/ListDiff'
1314
);
1415

1516
foreach ($classes as $class) {

lib/Caxy/HtmlDiff/HtmlDiff.php

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,14 @@ class HtmlDiff extends AbstractDiff
88
protected $insertSpaceInReplace = false;
99
protected $newIsolatedDiffTags;
1010
protected $oldIsolatedDiffTags;
11-
protected $isolatedDiffTags = array ('ol' => '[[REPLACE_ORDERED_LIST]]', 'ul' => '[[REPLACE_UNORDERED_LIST]]', 'sub' => '[[REPLACE_SUB_SCRIPT]]' , 'sup' => '[[REPLACE_SUPER_SCRIPT]]', 'dl' => '[[REPLACE_DEFINITION_LIST]]', 'table' => '[[REPLACE_TABLE]]');
11+
protected $isolatedDiffTags = array (
12+
'ol' => '[[REPLACE_ORDERED_LIST]]',
13+
'ul' => '[[REPLACE_UNORDERED_LIST]]',
14+
'sub' => '[[REPLACE_SUB_SCRIPT]]',
15+
'sup' => '[[REPLACE_SUPER_SCRIPT]]',
16+
'dl' => '[[REPLACE_DEFINITION_LIST]]',
17+
'table' => '[[REPLACE_TABLE]]'
18+
);
1219

1320
/**
1421
* @param boolean $boolean
@@ -62,6 +69,7 @@ protected function replaceIsolatedDiffTags()
6269
{
6370
$this->oldIsolatedDiffTags = $this->createIsolatedDiffTagPlaceholders($this->oldWords);
6471
$this->newIsolatedDiffTags = $this->createIsolatedDiffTagPlaceholders($this->newWords);
72+
6573
}
6674

6775
protected function createIsolatedDiffTagPlaceholders(&$words)
@@ -183,33 +191,50 @@ protected function processDeleteOperation($operation, $cssClass)
183191
$this->insertTag( "del", $cssClass, $text );
184192
}
185193

186-
protected function diffElements($oldText, $newText)
194+
protected function diffElements($oldText, $newText, $stripWrappingTags = true)
187195
{
188-
$pattern = '/(^<[^>]+>)|(<\/[^>]+>$)/i';
189-
$matches = array();
190196
$wrapStart = '';
191197
$wrapEnd = '';
192-
if (preg_match_all($pattern, $newText, $matches)) {
193-
$wrapStart = $matches[0][0];
194-
$wrapEnd = $matches[0][1];
198+
199+
if ($stripWrappingTags) {
200+
$pattern = '/(^<[^>]+>)|(<\/[^>]+>$)/i';
201+
$matches = array();
202+
203+
if (preg_match_all($pattern, $newText, $matches)) {
204+
$wrapStart = isset($matches[0][0]) ? $matches[0][0] : '';
205+
$wrapEnd = isset($matches[0][1]) ? $matches[0][1] : '';
206+
}
207+
$oldText = preg_replace($pattern, '', $oldText);
208+
$newText = preg_replace($pattern, '', $newText);
195209
}
196-
$oldText = preg_replace($pattern, '', $oldText);
197-
$newText = preg_replace($pattern, '', $newText);
198210

199-
$diff = new HtmlDiff($oldText, $newText, $this->encoding, $this->isolatedDiffTags, $this->groupDiffs);
211+
$diff = new HtmlDiff($oldText, $newText, $this->encoding, $this->specialCaseTags, $this->groupDiffs);
200212

201213
return $wrapStart . $diff->build() . $wrapEnd;
202214
}
203215

216+
protected function diffList($oldText, $newText)
217+
{
218+
$diff = new ListDiff($oldText, $newText, $this->encoding, $this->specialCaseTags, $this->groupDiffs);
219+
return $diff->build();
220+
}
221+
204222
protected function processEqualOperation($operation)
205223
{
206224
$result = array();
207225
foreach ($this->newWords as $pos => $s) {
226+
208227
if ($pos >= $operation->startInNew && $pos < $operation->endInNew) {
209228
if (in_array($s, $this->isolatedDiffTags) && isset($this->newIsolatedDiffTags[$pos])) {
229+
210230
$oldText = implode("", $this->findIsolatedDiffTagsInOld($operation, $pos));
211231
$newText = implode("", $this->newIsolatedDiffTags[$pos]);
212-
$result[] = $this->diffElements($oldText, $newText);
232+
233+
if ($this->isListPlaceholder($s)) {
234+
$result[] = $this->diffList($oldText, $newText);
235+
} else {
236+
$result[] = $this->diffElements($oldText, $newText);
237+
}
213238
} else {
214239
$result[] = $s;
215240
}
@@ -218,6 +243,19 @@ protected function processEqualOperation($operation)
218243
$this->content .= implode( "", $result );
219244
}
220245

246+
protected function isListPlaceholder($text)
247+
{
248+
if (in_array($text, array(
249+
$this->isolatedDiffTags['ol'],
250+
$this->isolatedDiffTags['dl'],
251+
$this->isolatedDiffTags['ul']
252+
))) {
253+
return true;
254+
}
255+
256+
return false;
257+
}
258+
221259
protected function findIsolatedDiffTagsInOld($operation, $posInNew)
222260
{
223261
$offset = $posInNew - $operation->startInNew;

0 commit comments

Comments
 (0)