Skip to content

Commit 8cac676

Browse files
committed
Resolved issues with diffing.
1 parent b0f859d commit 8cac676

File tree

4 files changed

+94
-56
lines changed

4 files changed

+94
-56
lines changed

demo/demo_text.php

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,10 @@
11
<?php
22

33
$demos = array(
4-
/*array(
5-
'old' => "<ol>
6-
<li>During the 40 kW exposure, flames <li>yeaaaa she <li>MICKEY <li>HAPPY MEAL</li> MOUSE</li> did</li> <li>noooooo</li> shall not spread to the ceiling.</li>
7-
<li>The flame shall not spread to the outer extremities of the samples on the 8-foot by 12-foot (203 by 305 mm) walls.</li>
8-
<li>Flashover, as defined in NFPA 265, shall not occur.</li>
9-
<li>The total smoke released throughout the test shall not exceed 1,000 m<sup>2</sup>. Stuff: <ol>
10-
<li>All the stuff I didnt</li>
11-
<li>Ok, I can</li>
12-
<li>Oh no she didnt.</li>
13-
</ol>
14-
</li>
15-
</ol>",
16-
17-
'new' => "<ol> <li>During the 40 kW exposure, flames shall not spread to the ceiling.</li> <li>The flame shall not spread to the outer extremities of the samples on the 8-foot by 12-foot (203 by 305 mm) walls.</li> <li>Flashover, as defined in NFPA 265, shall not occur.</li> <li>The total smoke <li>yep she did</li> released throughout the test shall not exceed 1,000 m<sup>2</sup>. Stuff: <ol> <li>All the stuff I didnt</li> <li>Ok, I can</li> <li>Oh no she didnt.</li> </ol> </li> </ol>"
18-
)*/
194
array(
205
'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>',
21-
'new' => '
22-
<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>
6+
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>
238
<ul class="exception">
249
<li><span class="content_bold">Exceptions:</span>
2510
<ol>

demo/index.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use Caxy\HtmlDiff\HtmlDiff;
44

55
ini_set('display_errors', 1);
6-
error_reporting(E_ALL);
6+
error_reporting(E_ERROR);
77

88
$classes = array(
99
'Caxy/HtmlDiff/AbstractDiff',
@@ -21,16 +21,11 @@
2121

2222
if ($input) {
2323
$data = json_decode($input, true);
24-
$diff = new HtmlDiff($_POST['oldText'], $_POST['newText'], 'UTF-8', array());
24+
$diff = new HtmlDiff($data['oldText'], $data['newText'], 'UTF-8', array());
2525
$diff->build();
26-
try{
27-
echo $diff->build();
28-
} catch (Exception $e) {
29-
echo $e->getMessage();
30-
}
3126

32-
//header('Content-Type: application/json');
33-
//echo json_encode(array('diff' => $diff->getDifference()));
27+
header('Content-Type: application/json');
28+
echo json_encode(array('diff' => $diff->getDifference()));
3429
} else {
3530
header('Content-Type: text/html');
3631
echo file_get_contents('demo.html');

lib/Caxy/HtmlDiff/HtmlDiff.php

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,95 @@ protected function indexNewWords()
6363
$this->wordIndices[ $word ] = array( $i );
6464
}
6565
}
66+
//$this->dump($this->wordIndices, " ============= WORD INDICES");
6667
}
6768

6869
protected function replaceIsolatedDiffTags()
6970
{
71+
//$this->dump($this->oldWords, "========== SPLIT INTO NEW WORDS === OLD WORDS >>> BEFORE");
72+
//$this->dump($this->newWords, "========== SPLIT INTO NEW WORDS === NEW WORDS >>> BEFORE");
7073
$this->oldIsolatedDiffTags = $this->createIsolatedDiffTagPlaceholders($this->oldWords);
7174
$this->newIsolatedDiffTags = $this->createIsolatedDiffTagPlaceholders($this->newWords);
75+
//$this->dump($this->oldWords, "========== SPLIT INTO NEW WORDS === OLD WORDS");
76+
//$this->dump($this->newWords, "========== SPLIT INTO NEW WORDS === NEW WORDS");
77+
//$this->dump($this->oldIsolatedDiffTags, " ======================= ReplaceIsolatedDiffTags === old isolated diff tags");
78+
//$this->dump($this->newIsolatedDiffTags, " ======================= ReplaceIsolatedDiffTags === new isolated diff tags");
79+
80+
}
81+
82+
protected function convertHtmlToListOfWords($characterString)
83+
{
84+
$mode = 'character';
85+
$current_word = '';
86+
$words = array();
87+
foreach ($characterString as $i => $character) {
88+
switch ($mode) {
89+
case 'character':
90+
if ( $this->isStartOfTag( $character ) ) {
91+
if ($current_word != '') {
92+
$words[] = $current_word;
93+
}
94+
$current_word = "<";
95+
$mode = 'tag';
96+
} elseif ( preg_match( "[^\s]", $character ) > 0 ) {
97+
if ($current_word != '') {
98+
$words[] = $current_word;
99+
}
100+
$current_word = $character;
101+
$mode = 'whitespace';
102+
} else {
103+
if (
104+
(ctype_alnum($character) && (strlen($current_word) == 0 || $this->isPartOfWord($current_word))) ||
105+
(in_array($character, $this->specialCaseChars) && isset($characterString[$i+1]) && $this->isPartOfWord($characterString[$i+1]))
106+
) {
107+
$current_word .= $character;
108+
} else {
109+
$words[] = $current_word;
110+
$current_word = $character;
111+
}
112+
}
113+
break;
114+
case 'tag' :
115+
if ( $this->isEndOfTag( $character ) ) {
116+
$current_word .= ">";
117+
$words[] = $current_word;
118+
$current_word = "";
119+
120+
if ( !preg_match('[^\s]', $character ) ) {
121+
$mode = 'whitespace';
122+
} else {
123+
$mode = 'character';
124+
}
125+
} else {
126+
$current_word .= $character;
127+
}
128+
break;
129+
case 'whitespace':
130+
if ( $this->isStartOfTag( $character ) ) {
131+
if ($current_word != '') {
132+
$words[] = $current_word;
133+
}
134+
$current_word = "<";
135+
$mode = 'tag';
136+
} elseif ( preg_match( "[^\s]", $character ) ) {
137+
$current_word .= $character;
138+
} else {
139+
if ($current_word != '') {
140+
$words[] = $current_word;
141+
}
142+
$current_word = $character;
143+
$mode = 'character';
144+
}
145+
break;
146+
default:
147+
break;
148+
}
149+
}
150+
if ($current_word != '') {
151+
$words[] = $current_word;
152+
}
153+
154+
return $words;
72155
}
73156

74157
protected function createIsolatedDiffTagPlaceholders(&$words)
@@ -196,7 +279,7 @@ protected function diffElements($oldText, $newText)
196279
$matches = array();
197280
$wrapStart = '';
198281
$wrapEnd = '';
199-
//preg_match_all($pattern, $newText, $testmatches); var_dump($testmatches);
282+
200283
if (preg_match_all($pattern, $newText, $matches)) {
201284
$wrapStart = count($matches[0]) ? $matches[0][0] : '';
202285
$wrapEnd = count($matches[0]) > 1 ? $matches[0][1] : '';
@@ -221,7 +304,6 @@ protected function processEqualOperation($operation)
221304
foreach ($this->newWords as $pos => $s) {
222305

223306
if ($pos >= $operation->startInNew && $pos < $operation->endInNew) {
224-
225307
if (in_array($s, $this->isolatedDiffTags) && isset($this->newIsolatedDiffTags[$pos])) {
226308

227309
$oldText = implode("", $this->findIsolatedDiffTagsInOld($operation, $pos));

lib/Caxy/HtmlDiff/ListDiff.php

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class ListDiff extends HtmlDiff
1212
'ul' => '[[REPLACE_UNORDERED_LIST]]',
1313
'dl' => '[[REPLACE_DEFINITION_LIST]]',
1414
);
15-
15+
protected static $listPlaceHolder = "[[REPLACE_LIST_ITEM]]";
1616
protected $listType; // holds the type of list this is ol, ul, dl
1717
protected $list; // hold the old/new content of the content of the list
1818
protected $childLists; // contains the old/new child lists content within this list
@@ -257,12 +257,11 @@ protected function convertListContentArrayToString($listContentArray)
257257
}
258258

259259
$content = array();
260-
$listString = '[[REPLACE_LIST_ITEM]]';
261260

262261
$words = explode(" ", $listContentArray['content']);
263262
$nestedListCount = 0;
264263
foreach ($words as $word) {
265-
$match = $word == $listString;
264+
$match = $word == self::$listPlaceHolder;
266265

267266
$content[] = $match
268267
? "<li>" . $this->convertListContentArrayToString($listContentArray['kids'][$nestedListCount]) . "</li>"
@@ -282,7 +281,6 @@ protected function convertListContentArrayToString($listContentArray)
282281
*/
283282
protected function processPlaceholders($text, array $matches)
284283
{
285-
$this->dump("============================= PROCESS PLACEHOLDERS");
286284
// Prepare return
287285
$returnText = array();
288286
// Save the contents of all list nodes, new and old.
@@ -291,9 +289,6 @@ protected function processPlaceholders($text, array $matches)
291289
'new' => $this->getListContent('new', $matches)
292290
);
293291

294-
$this->dump($contentVault, '================= content vault');
295-
$this->dump($matches, '================== matches');
296-
297292
$count = 0;
298293
// Loop through the text checking for placeholders. If a nested list is found, create a new ListDiff object for it.
299294
foreach (explode(' ', $text) as $word) {
@@ -350,11 +345,6 @@ protected function stripNewLine($text)
350345
*/
351346
protected function getListContent($indexKey = 'new', array $matches)
352347
{
353-
$this->dump("============================= GET LIST CONTENT FUNCTION");
354-
$this->dump($indexKey, "=========== indexKey");
355-
$this->dump($matches, "======== MATCHES");
356-
$this->dump($matches[$indexKey], "============= \$matches[\$indexKey] value");
357-
$this->dump($this->listsIndex[$indexKey], "================ listsIndex[indexKey]");
358348
$bucket = array();
359349
$start = $this->listsIndex[$indexKey][$matches[$indexKey]];
360350
$stop = array_key_exists(($matches[$indexKey] + 1), $this->listsIndex[$indexKey])
@@ -442,7 +432,6 @@ protected function getListsContent(array $contentArray, $stripTags = true)
442432
{
443433
$lematches = array();
444434
$arrayDepth = 0;
445-
$status = "//////////////////// STATUS \\\\\\\\\\\\\\\\\\\\\\";
446435
$nestedCount = array();
447436
foreach ($contentArray as $index => $word) {
448437

@@ -494,7 +483,7 @@ protected function addStringToArrayByDepth($word, &$array, $targetDepth, $thisDe
494483
if (array_key_exists('kids', $array)) {
495484
if ($nestedCount[$targetDepth] > count($array['kids'])) {
496485
$array['kids'][] = $newArray;
497-
$array['content'] .= "[[REPLACE_LIST_ITEM]]";
486+
$array['content'] .= self::$listPlaceHolder;
498487
}
499488

500489
// continue to the next depth
@@ -513,7 +502,7 @@ protected function addStringToArrayByDepth($word, &$array, $targetDepth, $thisDe
513502
} else {
514503
if ($nestedCount[$targetDepth] > count($array[count($array) - 1]['kids'])) {
515504
$array[count($array) - 1]['kids'][] = $newArray;
516-
$array[count($array) - 1]['content'] .= "[[REPLACE_LIST_ITEM]]";
505+
$array[count($array) - 1]['content'] .= self::$listPlaceHolder;
517506
}
518507
// continue to the next depth
519508
$thisDepth++;
@@ -531,19 +520,6 @@ protected function addStringToArrayByDepth($word, &$array, $targetDepth, $thisDe
531520
}
532521
}
533522

534-
protected function dump($content, $text = null)
535-
{
536-
ini_set('xdebug.var_display_max_depth', '10');
537-
ini_set('xdebug.var_display_max_data', '4096');
538-
ini_set('xdebug.max_nesting_level', '200');
539-
ini_set('xdebug.var_display_max_children', 256);
540-
if ($text) {
541-
var_dump($text);
542-
}
543-
544-
var_dump($content);
545-
}
546-
547523
protected function isOpeningListTag($item)
548524
{
549525
if (preg_match("#<li[^>]*>\\s*#iU", $item)) {

0 commit comments

Comments
 (0)