comparison vendor/masterminds/html5/src/HTML5/Parser/TreeBuildingRules.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 129ea1e6d783
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
1 <?php
2 namespace Masterminds\HTML5\Parser;
3
4 /**
5 * Handles special-case rules for the DOM tree builder.
6 *
7 * Many tags have special rules that need to be accomodated on an
8 * individual basis. This class handles those rules.
9 *
10 * See section 8.1.2.4 of the spec.
11 *
12 * @todo - colgroup and col special behaviors
13 * - body and head special behaviors
14 */
15 class TreeBuildingRules
16 {
17
18 protected static $tags = array(
19 'li' => 1,
20 'dd' => 1,
21 'dt' => 1,
22 'rt' => 1,
23 'rp' => 1,
24 'tr' => 1,
25 'th' => 1,
26 'td' => 1,
27 'thead' => 1,
28 'tfoot' => 1,
29 'tbody' => 1,
30 'table' => 1,
31 'optgroup' => 1,
32 'option' => 1
33 );
34
35 /**
36 * Build a new rules engine.
37 *
38 * @param \DOMDocument $doc
39 * The DOM document to use for evaluation and modification.
40 */
41 public function __construct($doc)
42 {
43 $this->doc = $doc;
44 }
45
46 /**
47 * Returns true if the given tagname has special processing rules.
48 */
49 public function hasRules($tagname)
50 {
51 return isset(static::$tags[$tagname]);
52 }
53
54 /**
55 * Evaluate the rule for the current tag name.
56 *
57 * This may modify the existing DOM.
58 *
59 * @return \DOMElement The new Current DOM element.
60 */
61 public function evaluate($new, $current)
62 {
63 switch ($new->tagName) {
64 case 'li':
65 return $this->handleLI($new, $current);
66 case 'dt':
67 case 'dd':
68 return $this->handleDT($new, $current);
69 case 'rt':
70 case 'rp':
71 return $this->handleRT($new, $current);
72 case 'optgroup':
73 return $this->closeIfCurrentMatches($new, $current, array(
74 'optgroup'
75 ));
76 case 'option':
77 return $this->closeIfCurrentMatches($new, $current, array(
78 'option',
79 ));
80 case 'tr':
81 return $this->closeIfCurrentMatches($new, $current, array(
82 'tr'
83 ));
84 case 'td':
85 case 'th':
86 return $this->closeIfCurrentMatches($new, $current, array(
87 'th',
88 'td'
89 ));
90 case 'tbody':
91 case 'thead':
92 case 'tfoot':
93 case 'table': // Spec isn't explicit about this, but it's necessary.
94
95 return $this->closeIfCurrentMatches($new, $current, array(
96 'thead',
97 'tfoot',
98 'tbody'
99 ));
100 }
101
102 return $current;
103 }
104
105 protected function handleLI($ele, $current)
106 {
107 return $this->closeIfCurrentMatches($ele, $current, array(
108 'li'
109 ));
110 }
111
112 protected function handleDT($ele, $current)
113 {
114 return $this->closeIfCurrentMatches($ele, $current, array(
115 'dt',
116 'dd'
117 ));
118 }
119
120 protected function handleRT($ele, $current)
121 {
122 return $this->closeIfCurrentMatches($ele, $current, array(
123 'rt',
124 'rp'
125 ));
126 }
127
128 protected function closeIfCurrentMatches($ele, $current, $match)
129 {
130 $tname = $current->tagName;
131 if (in_array($current->tagName, $match)) {
132 $current->parentNode->appendChild($ele);
133 } else {
134 $current->appendChild($ele);
135 }
136
137 return $ele;
138 }
139 }