Skip to content

Commit 33a0d6e

Browse files
committed
Updated List Diffing.
1 parent 81dcc8e commit 33a0d6e

File tree

3 files changed

+67
-93
lines changed

3 files changed

+67
-93
lines changed

demo/demo_text.php

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,25 @@
22

33
$demos = array(
44
array(
5-
'old' => '<p>Return air openings for heating, ventilation and air-conditioning systems shall comply with all of the following:</p>
6-
<ol>
7-
<li>Openings shall not be located less than 10 feet (3048 mm) measured in any direction from an open combustion chamber or draft hood of another appliance located in the same room or space.</li>
8-
<li>Return air shall not be taken from a hazardous or insanitary location or a refrigeration room as defined in this code.</li>
9-
<li>The amount of return air taken from any room or space shall be not greater than the flow rate of supply air delivered to such room or space.</li>
10-
<li>Return and transfer openings shall be sized in accordance with the appliance or equipment manufacturer\'s installation instructions, ACCA Manual D or the design of the registered design professional.</li>
11-
<ol><li>This is me previously.</li></ol>
12-
<li>Return air taken from one dwelling unit shall not be discharged into another dwelling unit.</li>
13-
<li>Taking return air from a crawl space shall not be accomplished through a direct connection to the return side of a forced air furnace. Transfer openings in the crawl space enclosure shall not be prohibited.</li>
14-
<li>Return air shall not be taken from a closet, bathroom, toilet room, kitchen, garage, boiler room, furnace room or unconditioned attic.</li>
15-
</ol>
16-
<ul class="exception">
17-
<li><strong>Exceptions:</strong>
18-
<ol>
19-
<li>Taking return air from a kitchen is not prohibited where such return air openings serve the kitchen and are located not less than 10 feet (3048 mm) from the cooking appliances.</li>
20-
<li>Dedicated forced air systems serving only the garage shall not be prohibited from obtaining return air from the garage.</li>
21-
</ol></li>
22-
</ul>',
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>',
236

24-
'new' => '<p>Return air openings for heating, ventilation and air-conditioning systems shall comply with all of the following:</p>
25-
<ol>
26-
<li>Openings shall not be located less than 10 feet (3048 mm) measured in any direction from an open combustion chamber or draft hood of another appliance located in the same room or space.</li>
27-
<li>Return air shall not be taken from a hazardous or insanitary location or a refrigeration room as defined in this code.</li>
28-
<ol><li>This is me after the fact.</li></ol>
29-
<li>The amount of return air taken from any room or space shall be not greater than the flow rate of supply air delivered to such room or space.</li>
30-
<li>Return and transfer openings shall be sized in accordance with the appliance or equipment manufacturer\'s installation instructions, ACCA Manual D or the design of the registered design professional.</li>
31-
<li>Return air taken from one dwelling unit shall not be discharged into another dwelling unit.</li>
32-
<li>Taking return air from a crawl space shall not be accomplished through a direct connection to the return side of a forced air furnace. Transfer openings in the crawl space enclosure shall not be prohibited.</li>
33-
<li>Return air shall not be taken from a closet, bathroom, toilet room, kitchen, garage, boiler room, furnace room or unconditioned attic.</li>
34-
</ol>
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>
358
<ul class="exception">
36-
<li><strong>Exceptions:</strong>
9+
<li><span class="content_bold">Exceptions:</span>
3710
<ol>
38-
<li>Taking return air from a kitchen is not prohibited where such return air openings serve the kitchen and are located not less than 10 feet (3048 mm) from the cooking appliances.</li>
39-
<li>Dedicated forced air systems serving only the garage shall not be prohibited from obtaining return air from the garage.</li>
40-
</ol></li>
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>
4124
</ul>'
4225
)
4326
);

demo/index.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
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',
1010
'Caxy/HtmlDiff/HtmlDiff',
1111
'Caxy/HtmlDiff/Match',
1212
'Caxy/HtmlDiff/Operation',
13-
'Caxy/HtmlDiff/ListDiff'
13+
'Caxy/HtmlDiff/ListDiff',
1414
);
1515

1616
foreach ($classes as $class) {
@@ -21,11 +21,11 @@
2121

2222
if ($input) {
2323
$data = json_decode($input, true);
24-
$diff = new HtmlDiff($_POST['oldText'], $_POST['newText'], 'UTF-8', array());
25-
echo $diff->build();
24+
$diff = new HtmlDiff($data['oldText'], $data['newText'], 'UTF-8', array());
25+
$diff->build();
2626

27-
//header('Content-Type: application/json');
28-
//echo json_encode(array('diff' => $diff->getDifference()));
27+
header('Content-Type: application/json');
28+
echo json_encode(array('diff' => $diff->getDifference()));
2929
} else {
3030
header('Content-Type: text/html');
3131
echo file_get_contents('demo.html');

lib/Caxy/HtmlDiff/ListDiff.php

Lines changed: 45 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,8 @@ protected function diffListContent()
102102
$this->formatThisListContent();
103103

104104
/* Build an index of content outside of list tags.
105-
* Create an array of matches to be used when diffing.
106105
*/
107-
$this->matchAndCompareContent();
106+
$this->indexContent();
108107

109108
/* In cases where we're dealing with nested lists,
110109
* make sure we use placeholders to replace the nested lists
@@ -123,19 +122,10 @@ protected function diffListContent()
123122
$this->diff();
124123
}
125124

126-
protected function matchAndCompareContent()
127-
{
128-
$this->indexContent();
129-
130-
$this->matchContent();
131-
}
132-
133125
protected function indexContent()
134126
{
135127
$this->contentIndex = array();
136128
$this->diffOrderIndex = array();
137-
$type = 'new';
138-
$list = $this->list['new'];
139129
foreach ($this->list as $type => $list) {
140130

141131
$this->contentIndex[$type] = array();
@@ -187,31 +177,6 @@ protected function indexContent()
187177
}
188178
}
189179
}
190-
191-
protected function matchContent()
192-
{
193-
$this->createNewOldMatches($this->contentIndex, $this->contentMatches);
194-
}
195-
196-
197-
protected function dump($asset, $string = '')
198-
{
199-
ini_set('xdebug.var_display_max_depth', 5);
200-
ini_set('xdebug.var_display_max_children', 2000);
201-
ini_set('xdebug.var_display_max_data', 1024);
202-
203-
if ($string) {
204-
$trueString = "======================= " . $string;
205-
var_dump(strtoupper($trueString));
206-
}
207-
208-
var_dump($asset);
209-
210-
if (isset($trueString)) {
211-
$trueString .= " ========= END END END";
212-
var_dump(strtoupper($trueString));
213-
}
214-
}
215180

216181
/*
217182
* This function is used to remove the wrapped ul, ol, or dl characters from this list
@@ -440,44 +405,70 @@ protected function buildChildLists()
440405
* Build the content of the class.
441406
*/
442407
protected function diff()
443-
{
408+
{
444409
// Add the opening parent node from listType. So if ol, <ol>, etc.
445410
$this->content = $this->addListTypeWrapper();
446411

447-
// GOAL: Build the content and the lists.
448-
// HOW?
449-
// Cherry-pick the content between list nodes.
450-
451-
foreach ($this->diffOrderIndex['new'] as $index) {
452-
if ($index['type'] == 'list') {
453-
$match = $this->textMatches[$index['position']];
412+
$oldIndexCount = 0;
413+
foreach ($this->diffOrderIndex['new'] as $key => $index) {
414+
415+
if ($index['type'] == "list") {
416+
$match = $this->getArrayByColumnValue($this->textMatches, 'new', $index['position']);
454417
$newList = $this->childLists['new'][$match['new']];
455418
$oldList = $this->childLists['old'][$match['old']];
456-
$this->content .= "<li>";
457-
$this->content .= $this->processPlaceholders(
419+
420+
$content = "<li>";
421+
$content .= $this->processPlaceholders(
458422
$this->diffElements(
459423
$this->convertListContentArrayToString($oldList),
460424
$this->convertListContentArrayToString($newList),
461425
false
462426
),
463427
$match
464428
);
465-
$this->content .= "</li>"; //die;
466-
} else {
467-
$match = $this->contentMatches[$index['position']];
468-
$newContent = $this->contentIndex['new'][$match['new']];
469-
$oldContent = array_key_exists($match['old'], $this->contentIndex)
470-
? $this->contentIndex['old'][$match['old']]
429+
$content .= "</li>";
430+
$this->content .= $content;
431+
}
432+
433+
if ($index['type'] == 'content') {
434+
$newContent = $this->contentIndex['new'][$index['position']];
435+
436+
$oldDiffOrderIndexMatch = array_key_exists($oldIndexCount, $this->diffOrderIndex['old'])
437+
? $this->diffOrderIndex['old'][$oldIndexCount]
438+
: false;
439+
440+
$oldContent = $oldDiffOrderIndexMatch && array_key_exists($oldDiffOrderIndexMatch['position'], $this->contentIndex['old'])
441+
? $this->contentIndex['old'][$oldDiffOrderIndexMatch['position']]
471442
: '';
472-
$htmlDiff = new HtmlDiff($oldContent, $newContent);
473-
$this->content .= $htmlDiff->build();
443+
444+
$diffObject = new HtmlDiff($oldContent, $newContent);
445+
$content = $diffObject->build();
446+
$this->content .= $content;
474447
}
448+
449+
$oldIndexCount++;
475450
}
476451

477452
// Add the closing parent node from listType. So if ol, </ol>, etc.
478453
$this->content .= $this->addListTypeWrapper(false);
479454
}
480455

456+
protected function getArrayByColumnValue($parentArray, $column, $value, $allMatches = false)
457+
{
458+
$returnArray = array();
459+
foreach ($parentArray as $array) {
460+
if (array_key_exists($column, $array) && $array[$column] == $value) {
461+
if ($allMatches) {
462+
$returnArray[] = $array;
463+
} else {
464+
return $array;
465+
}
466+
}
467+
}
468+
469+
return $allMatches ? $returnArray : false;
470+
}
471+
481472
protected function diffThisList($word, $key)
482473
{
483474
$listIndexValue = $this->getListIndexValue($key);

0 commit comments

Comments
 (0)