ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
HTML5TreeConstructer Class Reference
+ Collaboration diagram for HTML5TreeConstructer:

Public Member Functions

 __construct ()
 
 emitToken ($token)
 
 save ()
 

Data Fields

 $stack = array()
 
const INIT_PHASE = 0
 
const ROOT_PHASE = 1
 
const MAIN_PHASE = 2
 
const END_PHASE = 3
 
const BEFOR_HEAD = 0
 
const IN_HEAD = 1
 
const AFTER_HEAD = 2
 
const IN_BODY = 3
 
const IN_TABLE = 4
 
const IN_CAPTION = 5
 
const IN_CGROUP = 6
 
const IN_TBODY = 7
 
const IN_ROW = 8
 
const IN_CELL = 9
 
const IN_SELECT = 10
 
const AFTER_BODY = 11
 
const IN_FRAME = 12
 
const AFTR_FRAME = 13
 
const SPECIAL = 0
 
const SCOPING = 1
 
const FORMATTING = 2
 
const PHRASING = 3
 
const MARKER = 0
 

Private Member Functions

 initPhase ($token)
 
 rootElementPhase ($token)
 
 mainPhase ($token)
 
 beforeHead ($token)
 
 inHead ($token)
 
 afterHead ($token)
 
 inBody ($token)
 
 inTable ($token)
 
 inCaption ($token)
 
 inColumnGroup ($token)
 
 inTableBody ($token)
 
 inRow ($token)
 
 inCell ($token)
 
 inSelect ($token)
 
 afterBody ($token)
 
 inFrameset ($token)
 
 afterFrameset ($token)
 
 trailingEndPhase ($token)
 
 insertElement ($token, $append=true, $check=false)
 
 insertText ($data)
 
 insertComment ($data)
 
 appendToRealParent ($node)
 
 elementInScope ($el, $table=false)
 
 reconstructActiveFormattingElements ()
 
 clearTheActiveFormattingElementsUpToTheLastMarker ()
 
 generateImpliedEndTags ($exclude=array())
 
 getElementCategory ($node)
 
 clearStackToTableContext ($elements)
 
 resetInsertionMode ()
 
 closeCell ()
 

Private Attributes

 $phase
 
 $mode
 
 $dom
 
 $foster_parent = null
 
 $a_formatting = array()
 
 $head_pointer = null
 
 $form_pointer = null
 
 $scoping = array('button', 'caption', 'html', 'marquee', 'object', 'table', 'td', 'th')
 
 $formatting
 
 $special
 

Detailed Description

Definition at line 1576 of file PH5P.php.

Constructor & Destructor Documentation

◆ __construct()

HTML5TreeConstructer::__construct ( )

Definition at line 1699 of file PH5P.php.

1700 {
1701 $this->phase = self::INIT_PHASE;
1702 $this->mode = self::BEFOR_HEAD;
1703 $this->dom = new DOMDocument;
1704
1705 $this->dom->encoding = 'UTF-8';
1706 $this->dom->preserveWhiteSpace = true;
1707 $this->dom->substituteEntities = true;
1708 $this->dom->strictErrorChecking = false;
1709 }

References BEFOR_HEAD, and INIT_PHASE.

Member Function Documentation

◆ afterBody()

HTML5TreeConstructer::afterBody (   $token)
private

Definition at line 4201 of file PH5P.php.

4202 {
4203 /* Handle the token as follows: */
4204
4205 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
4206 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
4207 or U+0020 SPACE */
4208 if ($token['type'] === HTML5::CHARACTR &&
4209 preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
4210 ) {
4211 /* Process the token as it would be processed if the insertion mode
4212 was "in body". */
4213 $this->inBody($token);
4214
4215 /* A comment token */
4216 } elseif ($token['type'] === HTML5::COMMENT) {
4217 /* Append a Comment node to the first element in the stack of open
4218 elements (the html element), with the data attribute set to the
4219 data given in the comment token. */
4220 $comment = $this->dom->createComment($token['data']);
4221 $this->stack[0]->appendChild($comment);
4222
4223 /* An end tag with the tag name "html" */
4224 } elseif ($token['type'] === HTML5::ENDTAG && $token['name'] === 'html') {
4225 /* If the parser was originally created in order to handle the
4226 setting of an element's innerHTML attribute, this is a parse error;
4227 ignore the token. (The element will be an html element in this
4228 case.) (innerHTML case) */
4229
4230 /* Otherwise, switch to the trailing end phase. */
4231 $this->phase = self::END_PHASE;
4232
4233 /* Anything else */
4234 } else {
4235 /* Parse error. Set the insertion mode to "in body" and reprocess
4236 the token. */
4237 $this->mode = self::IN_BODY;
4238 return $this->inBody($token);
4239 }
4240 }
$comment
Definition: buildRTE.php:83
const CHARACTR
Definition: PH5P.php:458
const COMMENT
Definition: PH5P.php:457
const ENDTAG
Definition: PH5P.php:456

References $comment, HTML5\CHARACTR, HTML5\COMMENT, END_PHASE, HTML5\ENDTAG, IN_BODY, and inBody().

Referenced by inBody(), and mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ afterFrameset()

HTML5TreeConstructer::afterFrameset (   $token)
private

Definition at line 4311 of file PH5P.php.

4312 {
4313 /* Handle the token as follows: */
4314
4315 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
4316 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
4317 U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */
4318 if ($token['type'] === HTML5::CHARACTR &&
4319 preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
4320 ) {
4321 /* Append the character to the current node. */
4322 $this->insertText($token['data']);
4323
4324 /* A comment token */
4325 } elseif ($token['type'] === HTML5::COMMENT) {
4326 /* Append a Comment node to the current node with the data
4327 attribute set to the data given in the comment token. */
4328 $this->insertComment($token['data']);
4329
4330 /* An end tag with the tag name "html" */
4331 } elseif ($token['name'] === 'html' &&
4332 $token['type'] === HTML5::ENDTAG
4333 ) {
4334 /* Switch to the trailing end phase. */
4335 $this->phase = self::END_PHASE;
4336
4337 /* A start tag with the tag name "noframes" */
4338 } elseif ($token['name'] === 'noframes' &&
4339 $token['type'] === HTML5::STARTTAG
4340 ) {
4341 /* Process the token as if the insertion mode had been "in body". */
4342 $this->inBody($token);
4343
4344 /* Anything else */
4345 } else {
4346 /* Parse error. Ignore the token. */
4347 }
4348 }
insertComment($data)
Definition: PH5P.php:4428
const STARTTAG
Definition: PH5P.php:455

References HTML5\CHARACTR, HTML5\COMMENT, END_PHASE, HTML5\ENDTAG, inBody(), insertComment(), insertText(), and HTML5\STARTTAG.

Referenced by mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ afterHead()

HTML5TreeConstructer::afterHead (   $token)
private

Definition at line 2112 of file PH5P.php.

2113 {
2114 /* Handle the token as follows: */
2115
2116 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
2117 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
2118 or U+0020 SPACE */
2119 if ($token['type'] === HTML5::CHARACTR &&
2120 preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
2121 ) {
2122 /* Append the character to the current node. */
2123 $this->insertText($token['data']);
2124
2125 /* A comment token */
2126 } elseif ($token['type'] === HTML5::COMMENT) {
2127 /* Append a Comment node to the current node with the data attribute
2128 set to the data given in the comment token. */
2129 $this->insertComment($token['data']);
2130
2131 /* A start tag token with the tag name "body" */
2132 } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'body') {
2133 /* Insert a body element for the token. */
2134 $this->insertElement($token);
2135
2136 /* Change the insertion mode to "in body". */
2137 $this->mode = self::IN_BODY;
2138
2139 /* A start tag token with the tag name "frameset" */
2140 } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'frameset') {
2141 /* Insert a frameset element for the token. */
2142 $this->insertElement($token);
2143
2144 /* Change the insertion mode to "in frameset". */
2145 $this->mode = self::IN_FRAME;
2146
2147 /* A start tag token whose tag name is one of: "base", "link", "meta",
2148 "script", "style", "title" */
2149 } elseif ($token['type'] === HTML5::STARTTAG && in_array(
2150 $token['name'],
2151 array('base', 'link', 'meta', 'script', 'style', 'title')
2152 )
2153 ) {
2154 /* Parse error. Switch the insertion mode back to "in head" and
2155 reprocess the token. */
2156 $this->mode = self::IN_HEAD;
2157 return $this->inHead($token);
2158
2159 /* Anything else */
2160 } else {
2161 /* Act as if a start tag token with the tag name "body" and no
2162 attributes had been seen, and then reprocess the current token. */
2163 $this->afterHead(
2164 array(
2165 'name' => 'body',
2166 'type' => HTML5::STARTTAG,
2167 'attr' => array()
2168 )
2169 );
2170
2171 return $this->inBody($token);
2172 }
2173 }
insertElement($token, $append=true, $check=false)
Definition: PH5P.php:4393
afterHead($token)
Definition: PH5P.php:2112

References afterHead(), HTML5\CHARACTR, HTML5\COMMENT, IN_BODY, IN_FRAME, IN_HEAD, inBody(), inHead(), insertComment(), insertElement(), insertText(), and HTML5\STARTTAG.

Referenced by afterHead(), inHead(), and mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ appendToRealParent()

HTML5TreeConstructer::appendToRealParent (   $node)
private

Definition at line 4434 of file PH5P.php.

4435 {
4436 if ($this->foster_parent === null) {
4437 end($this->stack)->appendChild($node);
4438
4439 } elseif ($this->foster_parent !== null) {
4440 /* If the foster parent element is the parent element of the
4441 last table element in the stack of open elements, then the new
4442 node must be inserted immediately before the last table element
4443 in the stack of open elements in the foster parent element;
4444 otherwise, the new node must be appended to the foster parent
4445 element. */
4446 for ($n = count($this->stack) - 1; $n >= 0; $n--) {
4447 if ($this->stack[$n]->nodeName === 'table' &&
4448 $this->stack[$n]->parentNode !== null
4449 ) {
4450 $table = $this->stack[$n];
4451 break;
4452 }
4453 }
4454
4455 if (isset($table) && $this->foster_parent->isSameNode($table->parentNode)) {
4456 $this->foster_parent->insertBefore($node, $table);
4457 } else {
4458 $this->foster_parent->appendChild($node);
4459 }
4460
4461 $this->foster_parent = null;
4462 }
4463 }
$n
Definition: RandomTest.php:80

References $n.

Referenced by insertComment(), insertElement(), and insertText().

+ Here is the caller graph for this function:

◆ beforeHead()

HTML5TreeConstructer::beforeHead (   $token)
private

Definition at line 1916 of file PH5P.php.

1917 {
1918 /* Handle the token as follows: */
1919
1920 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
1921 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
1922 or U+0020 SPACE */
1923 if ($token['type'] === HTML5::CHARACTR &&
1924 preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
1925 ) {
1926 /* Append the character to the current node. */
1927 $this->insertText($token['data']);
1928
1929 /* A comment token */
1930 } elseif ($token['type'] === HTML5::COMMENT) {
1931 /* Append a Comment node to the current node with the data attribute
1932 set to the data given in the comment token. */
1933 $this->insertComment($token['data']);
1934
1935 /* A start tag token with the tag name "head" */
1936 } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'head') {
1937 /* Create an element for the token, append the new element to the
1938 current node and push it onto the stack of open elements. */
1939 $element = $this->insertElement($token);
1940
1941 /* Set the head element pointer to this new element node. */
1942 $this->head_pointer = $element;
1943
1944 /* Change the insertion mode to "in head". */
1945 $this->mode = self::IN_HEAD;
1946
1947 /* A start tag token whose tag name is one of: "base", "link", "meta",
1948 "script", "style", "title". Or an end tag with the tag name "html".
1949 Or a character token that is not one of U+0009 CHARACTER TABULATION,
1950 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
1951 or U+0020 SPACE. Or any other start tag token */
1952 } elseif ($token['type'] === HTML5::STARTTAG ||
1953 ($token['type'] === HTML5::ENDTAG && $token['name'] === 'html') ||
1954 ($token['type'] === HTML5::CHARACTR && !preg_match(
1955 '/^[\t\n\x0b\x0c ]$/',
1956 $token['data']
1957 ))
1958 ) {
1959 /* Act as if a start tag token with the tag name "head" and no
1960 attributes had been seen, then reprocess the current token. */
1961 $this->beforeHead(
1962 array(
1963 'name' => 'head',
1964 'type' => HTML5::STARTTAG,
1965 'attr' => array()
1966 )
1967 );
1968
1969 return $this->inHead($token);
1970
1971 /* Any other end tag */
1972 } elseif ($token['type'] === HTML5::ENDTAG) {
1973 /* Parse error. Ignore the token. */
1974 }
1975 }
beforeHead($token)
Definition: PH5P.php:1916

References beforeHead(), HTML5\CHARACTR, HTML5\COMMENT, HTML5\ENDTAG, IN_HEAD, inHead(), insertComment(), insertElement(), insertText(), and HTML5\STARTTAG.

Referenced by beforeHead(), and mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ clearStackToTableContext()

HTML5TreeConstructer::clearStackToTableContext (   $elements)
private

Definition at line 4648 of file PH5P.php.

4649 {
4650 /* When the steps above require the UA to clear the stack back to a
4651 table context, it means that the UA must, while the current node is not
4652 a table element or an html element, pop elements from the stack of open
4653 elements. If this causes any elements to be popped from the stack, then
4654 this is a parse error. */
4655 while (true) {
4656 $node = end($this->stack)->nodeName;
4657
4658 if (in_array($node, $elements)) {
4659 break;
4660 } else {
4661 array_pop($this->stack);
4662 }
4663 }
4664 }

Referenced by inRow(), inTable(), and inTableBody().

+ Here is the caller graph for this function:

◆ clearTheActiveFormattingElementsUpToTheLastMarker()

HTML5TreeConstructer::clearTheActiveFormattingElementsUpToTheLastMarker ( )
private

Definition at line 4597 of file PH5P.php.

4598 {
4599 /* When the steps below require the UA to clear the list of active
4600 formatting elements up to the last marker, the UA must perform the
4601 following steps: */
4602
4603 while (true) {
4604 /* 1. Let entry be the last (most recently added) entry in the list
4605 of active formatting elements. */
4606 $entry = end($this->a_formatting);
4607
4608 /* 2. Remove entry from the list of active formatting elements. */
4609 array_pop($this->a_formatting);
4610
4611 /* 3. If entry was a marker, then stop the algorithm at this point.
4612 The list has been cleared up to the last marker. */
4613 if ($entry === self::MARKER) {
4614 break;
4615 }
4616 }
4617 }

Referenced by inCaption(), and inCell().

+ Here is the caller graph for this function:

◆ closeCell()

HTML5TreeConstructer::closeCell ( )
private

Definition at line 4765 of file PH5P.php.

4766 {
4767 /* If the stack of open elements has a td or th element in table scope,
4768 then act as if an end tag token with that tag name had been seen. */
4769 foreach (array('td', 'th') as $cell) {
4770 if ($this->elementInScope($cell, true)) {
4771 $this->inCell(
4772 array(
4773 'name' => $cell,
4774 'type' => HTML5::ENDTAG
4775 )
4776 );
4777
4778 break;
4779 }
4780 }
4781 }
elementInScope($el, $table=false)
Definition: PH5P.php:4465

References elementInScope(), HTML5\ENDTAG, and inCell().

Referenced by inCell().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ elementInScope()

HTML5TreeConstructer::elementInScope (   $el,
  $table = false 
)
private

Definition at line 4465 of file PH5P.php.

4466 {
4467 if (is_array($el)) {
4468 foreach ($el as $element) {
4469 if ($this->elementInScope($element, $table)) {
4470 return true;
4471 }
4472 }
4473
4474 return false;
4475 }
4476
4477 $leng = count($this->stack);
4478
4479 for ($n = 0; $n < $leng; $n++) {
4480 /* 1. Initialise node to be the current node (the bottommost node of
4481 the stack). */
4482 $node = $this->stack[$leng - 1 - $n];
4483
4484 if ($node->tagName === $el) {
4485 /* 2. If node is the target node, terminate in a match state. */
4486 return true;
4487
4488 } elseif ($node->tagName === 'table') {
4489 /* 3. Otherwise, if node is a table element, terminate in a failure
4490 state. */
4491 return false;
4492
4493 } elseif ($table === true && in_array(
4494 $node->tagName,
4495 array(
4496 'caption',
4497 'td',
4498 'th',
4499 'button',
4500 'marquee',
4501 'object'
4502 )
4503 )
4504 ) {
4505 /* 4. Otherwise, if the algorithm is the "has an element in scope"
4506 variant (rather than the "has an element in table scope" variant),
4507 and node is one of the following, terminate in a failure state. */
4508 return false;
4509
4510 } elseif ($node === $node->ownerDocument->documentElement) {
4511 /* 5. Otherwise, if node is an html element (root element), terminate
4512 in a failure state. (This can only happen if the node is the topmost
4513 node of the stack of open elements, and prevents the next step from
4514 being invoked if there are no more elements in the stack.) */
4515 return false;
4516 }
4517
4518 /* Otherwise, set node to the previous entry in the stack of open
4519 elements and return to step 2. (This will never fail, since the loop
4520 will always terminate in the previous step if the top of the stack
4521 is reached.) */
4522 }
4523 }

References $n, and elementInScope().

Referenced by closeCell(), elementInScope(), inBody(), inCaption(), inCell(), inRow(), inSelect(), inTable(), and inTableBody().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ emitToken()

HTML5TreeConstructer::emitToken (   $token)

Definition at line 1712 of file PH5P.php.

1713 {
1714 switch ($this->phase) {
1715 case self::INIT_PHASE:
1716 return $this->initPhase($token);
1717 break;
1718 case self::ROOT_PHASE:
1719 return $this->rootElementPhase($token);
1720 break;
1721 case self::MAIN_PHASE:
1722 return $this->mainPhase($token);
1723 break;
1724 case self::END_PHASE :
1725 return $this->trailingEndPhase($token);
1726 break;
1727 }
1728 }
rootElementPhase($token)
Definition: PH5P.php:1785
mainPhase($token)
Definition: PH5P.php:1835
trailingEndPhase($token)
Definition: PH5P.php:4350
initPhase($token)
Definition: PH5P.php:1730

References END_PHASE, INIT_PHASE, initPhase(), MAIN_PHASE, mainPhase(), ROOT_PHASE, rootElementPhase(), and trailingEndPhase().

Referenced by inBody().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateImpliedEndTags()

HTML5TreeConstructer::generateImpliedEndTags (   $exclude = array())
private

Definition at line 4619 of file PH5P.php.

4620 {
4621 /* When the steps below require the UA to generate implied end tags,
4622 then, if the current node is a dd element, a dt element, an li element,
4623 a p element, a td element, a th element, or a tr element, the UA must
4624 act as if an end tag with the respective tag name had been seen and
4625 then generate implied end tags again. */
4626 $node = end($this->stack);
4627 $elements = array_diff(array('dd', 'dt', 'li', 'p', 'td', 'th', 'tr'), $exclude);
4628
4629 while (in_array(end($this->stack)->nodeName, $elements)) {
4630 array_pop($this->stack);
4631 }
4632 }
if(! $in) $exclude

References $exclude.

Referenced by inBody(), inCaption(), inCell(), inTable(), and mainPhase().

+ Here is the caller graph for this function:

◆ getElementCategory()

HTML5TreeConstructer::getElementCategory (   $node)
private

Definition at line 4634 of file PH5P.php.

4635 {
4636 $name = $node->tagName;
4637 if (in_array($name, $this->special)) {
4638 return self::SPECIAL;
4639 } elseif (in_array($name, $this->scoping)) {
4640 return self::SCOPING;
4641 } elseif (in_array($name, $this->formatting)) {
4642 return self::FORMATTING;
4643 } else {
4644 return self::PHRASING;
4645 }
4646 }

References FORMATTING, PHRASING, SCOPING, and SPECIAL.

Referenced by inBody().

+ Here is the caller graph for this function:

◆ inBody()

HTML5TreeConstructer::inBody (   $token)
private

Definition at line 2175 of file PH5P.php.

2176 {
2177 /* Handle the token as follows: */
2178
2179 switch ($token['type']) {
2180 /* A character token */
2181 case HTML5::CHARACTR:
2182 /* Reconstruct the active formatting elements, if any. */
2184
2185 /* Append the token's character to the current node. */
2186 $this->insertText($token['data']);
2187 break;
2188
2189 /* A comment token */
2190 case HTML5::COMMENT:
2191 /* Append a Comment node to the current node with the data
2192 attribute set to the data given in the comment token. */
2193 $this->insertComment($token['data']);
2194 break;
2195
2196 case HTML5::STARTTAG:
2197 switch ($token['name']) {
2198 /* A start tag token whose tag name is one of: "script",
2199 "style" */
2200 case 'script':
2201 case 'style':
2202 /* Process the token as if the insertion mode had been "in
2203 head". */
2204 return $this->inHead($token);
2205 break;
2206
2207 /* A start tag token whose tag name is one of: "base", "link",
2208 "meta", "title" */
2209 case 'base':
2210 case 'link':
2211 case 'meta':
2212 case 'title':
2213 /* Parse error. Process the token as if the insertion mode
2214 had been "in head". */
2215 return $this->inHead($token);
2216 break;
2217
2218 /* A start tag token with the tag name "body" */
2219 case 'body':
2220 /* Parse error. If the second element on the stack of open
2221 elements is not a body element, or, if the stack of open
2222 elements has only one node on it, then ignore the token.
2223 (innerHTML case) */
2224 if (count($this->stack) === 1 || $this->stack[1]->nodeName !== 'body') {
2225 // Ignore
2226
2227 /* Otherwise, for each attribute on the token, check to see
2228 if the attribute is already present on the body element (the
2229 second element) on the stack of open elements. If it is not,
2230 add the attribute and its corresponding value to that
2231 element. */
2232 } else {
2233 foreach ($token['attr'] as $attr) {
2234 if (!$this->stack[1]->hasAttribute($attr['name'])) {
2235 $this->stack[1]->setAttribute($attr['name'], $attr['value']);
2236 }
2237 }
2238 }
2239 break;
2240
2241 /* A start tag whose tag name is one of: "address",
2242 "blockquote", "center", "dir", "div", "dl", "fieldset",
2243 "listing", "menu", "ol", "p", "ul" */
2244 case 'address':
2245 case 'blockquote':
2246 case 'center':
2247 case 'dir':
2248 case 'div':
2249 case 'dl':
2250 case 'fieldset':
2251 case 'listing':
2252 case 'menu':
2253 case 'ol':
2254 case 'p':
2255 case 'ul':
2256 /* If the stack of open elements has a p element in scope,
2257 then act as if an end tag with the tag name p had been
2258 seen. */
2259 if ($this->elementInScope('p')) {
2260 $this->emitToken(
2261 array(
2262 'name' => 'p',
2263 'type' => HTML5::ENDTAG
2264 )
2265 );
2266 }
2267
2268 /* Insert an HTML element for the token. */
2269 $this->insertElement($token);
2270 break;
2271
2272 /* A start tag whose tag name is "form" */
2273 case 'form':
2274 /* If the form element pointer is not null, ignore the
2275 token with a parse error. */
2276 if ($this->form_pointer !== null) {
2277 // Ignore.
2278
2279 /* Otherwise: */
2280 } else {
2281 /* If the stack of open elements has a p element in
2282 scope, then act as if an end tag with the tag name p
2283 had been seen. */
2284 if ($this->elementInScope('p')) {
2285 $this->emitToken(
2286 array(
2287 'name' => 'p',
2288 'type' => HTML5::ENDTAG
2289 )
2290 );
2291 }
2292
2293 /* Insert an HTML element for the token, and set the
2294 form element pointer to point to the element created. */
2295 $element = $this->insertElement($token);
2296 $this->form_pointer = $element;
2297 }
2298 break;
2299
2300 /* A start tag whose tag name is "li", "dd" or "dt" */
2301 case 'li':
2302 case 'dd':
2303 case 'dt':
2304 /* If the stack of open elements has a p element in scope,
2305 then act as if an end tag with the tag name p had been
2306 seen. */
2307 if ($this->elementInScope('p')) {
2308 $this->emitToken(
2309 array(
2310 'name' => 'p',
2311 'type' => HTML5::ENDTAG
2312 )
2313 );
2314 }
2315
2316 $stack_length = count($this->stack) - 1;
2317
2318 for ($n = $stack_length; 0 <= $n; $n--) {
2319 /* 1. Initialise node to be the current node (the
2320 bottommost node of the stack). */
2321 $stop = false;
2322 $node = $this->stack[$n];
2323 $cat = $this->getElementCategory($node->tagName);
2324
2325 /* 2. If node is an li, dd or dt element, then pop all
2326 the nodes from the current node up to node, including
2327 node, then stop this algorithm. */
2328 if ($token['name'] === $node->tagName || ($token['name'] !== 'li'
2329 && ($node->tagName === 'dd' || $node->tagName === 'dt'))
2330 ) {
2331 for ($x = $stack_length; $x >= $n; $x--) {
2332 array_pop($this->stack);
2333 }
2334
2335 break;
2336 }
2337
2338 /* 3. If node is not in the formatting category, and is
2339 not in the phrasing category, and is not an address or
2340 div element, then stop this algorithm. */
2341 if ($cat !== self::FORMATTING && $cat !== self::PHRASING &&
2342 $node->tagName !== 'address' && $node->tagName !== 'div'
2343 ) {
2344 break;
2345 }
2346 }
2347
2348 /* Finally, insert an HTML element with the same tag
2349 name as the token's. */
2350 $this->insertElement($token);
2351 break;
2352
2353 /* A start tag token whose tag name is "plaintext" */
2354 case 'plaintext':
2355 /* If the stack of open elements has a p element in scope,
2356 then act as if an end tag with the tag name p had been
2357 seen. */
2358 if ($this->elementInScope('p')) {
2359 $this->emitToken(
2360 array(
2361 'name' => 'p',
2362 'type' => HTML5::ENDTAG
2363 )
2364 );
2365 }
2366
2367 /* Insert an HTML element for the token. */
2368 $this->insertElement($token);
2369
2370 return HTML5::PLAINTEXT;
2371 break;
2372
2373 /* A start tag whose tag name is one of: "h1", "h2", "h3", "h4",
2374 "h5", "h6" */
2375 case 'h1':
2376 case 'h2':
2377 case 'h3':
2378 case 'h4':
2379 case 'h5':
2380 case 'h6':
2381 /* If the stack of open elements has a p element in scope,
2382 then act as if an end tag with the tag name p had been seen. */
2383 if ($this->elementInScope('p')) {
2384 $this->emitToken(
2385 array(
2386 'name' => 'p',
2387 'type' => HTML5::ENDTAG
2388 )
2389 );
2390 }
2391
2392 /* If the stack of open elements has in scope an element whose
2393 tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then
2394 this is a parse error; pop elements from the stack until an
2395 element with one of those tag names has been popped from the
2396 stack. */
2397 while ($this->elementInScope(array('h1', 'h2', 'h3', 'h4', 'h5', 'h6'))) {
2398 array_pop($this->stack);
2399 }
2400
2401 /* Insert an HTML element for the token. */
2402 $this->insertElement($token);
2403 break;
2404
2405 /* A start tag whose tag name is "a" */
2406 case 'a':
2407 /* If the list of active formatting elements contains
2408 an element whose tag name is "a" between the end of the
2409 list and the last marker on the list (or the start of
2410 the list if there is no marker on the list), then this
2411 is a parse error; act as if an end tag with the tag name
2412 "a" had been seen, then remove that element from the list
2413 of active formatting elements and the stack of open
2414 elements if the end tag didn't already remove it (it
2415 might not have if the element is not in table scope). */
2416 $leng = count($this->a_formatting);
2417
2418 for ($n = $leng - 1; $n >= 0; $n--) {
2419 if ($this->a_formatting[$n] === self::MARKER) {
2420 break;
2421
2422 } elseif ($this->a_formatting[$n]->nodeName === 'a') {
2423 $this->emitToken(
2424 array(
2425 'name' => 'a',
2426 'type' => HTML5::ENDTAG
2427 )
2428 );
2429 break;
2430 }
2431 }
2432
2433 /* Reconstruct the active formatting elements, if any. */
2435
2436 /* Insert an HTML element for the token. */
2437 $el = $this->insertElement($token);
2438
2439 /* Add that element to the list of active formatting
2440 elements. */
2441 $this->a_formatting[] = $el;
2442 break;
2443
2444 /* A start tag whose tag name is one of: "b", "big", "em", "font",
2445 "i", "nobr", "s", "small", "strike", "strong", "tt", "u" */
2446 case 'b':
2447 case 'big':
2448 case 'em':
2449 case 'font':
2450 case 'i':
2451 case 'nobr':
2452 case 's':
2453 case 'small':
2454 case 'strike':
2455 case 'strong':
2456 case 'tt':
2457 case 'u':
2458 /* Reconstruct the active formatting elements, if any. */
2460
2461 /* Insert an HTML element for the token. */
2462 $el = $this->insertElement($token);
2463
2464 /* Add that element to the list of active formatting
2465 elements. */
2466 $this->a_formatting[] = $el;
2467 break;
2468
2469 /* A start tag token whose tag name is "button" */
2470 case 'button':
2471 /* If the stack of open elements has a button element in scope,
2472 then this is a parse error; act as if an end tag with the tag
2473 name "button" had been seen, then reprocess the token. (We don't
2474 do that. Unnecessary.) */
2475 if ($this->elementInScope('button')) {
2476 $this->inBody(
2477 array(
2478 'name' => 'button',
2479 'type' => HTML5::ENDTAG
2480 )
2481 );
2482 }
2483
2484 /* Reconstruct the active formatting elements, if any. */
2486
2487 /* Insert an HTML element for the token. */
2488 $this->insertElement($token);
2489
2490 /* Insert a marker at the end of the list of active
2491 formatting elements. */
2492 $this->a_formatting[] = self::MARKER;
2493 break;
2494
2495 /* A start tag token whose tag name is one of: "marquee", "object" */
2496 case 'marquee':
2497 case 'object':
2498 /* Reconstruct the active formatting elements, if any. */
2500
2501 /* Insert an HTML element for the token. */
2502 $this->insertElement($token);
2503
2504 /* Insert a marker at the end of the list of active
2505 formatting elements. */
2506 $this->a_formatting[] = self::MARKER;
2507 break;
2508
2509 /* A start tag token whose tag name is "xmp" */
2510 case 'xmp':
2511 /* Reconstruct the active formatting elements, if any. */
2513
2514 /* Insert an HTML element for the token. */
2515 $this->insertElement($token);
2516
2517 /* Switch the content model flag to the CDATA state. */
2518 return HTML5::CDATA;
2519 break;
2520
2521 /* A start tag whose tag name is "table" */
2522 case 'table':
2523 /* If the stack of open elements has a p element in scope,
2524 then act as if an end tag with the tag name p had been seen. */
2525 if ($this->elementInScope('p')) {
2526 $this->emitToken(
2527 array(
2528 'name' => 'p',
2529 'type' => HTML5::ENDTAG
2530 )
2531 );
2532 }
2533
2534 /* Insert an HTML element for the token. */
2535 $this->insertElement($token);
2536
2537 /* Change the insertion mode to "in table". */
2538 $this->mode = self::IN_TABLE;
2539 break;
2540
2541 /* A start tag whose tag name is one of: "area", "basefont",
2542 "bgsound", "br", "embed", "img", "param", "spacer", "wbr" */
2543 case 'area':
2544 case 'basefont':
2545 case 'bgsound':
2546 case 'br':
2547 case 'embed':
2548 case 'img':
2549 case 'param':
2550 case 'spacer':
2551 case 'wbr':
2552 /* Reconstruct the active formatting elements, if any. */
2554
2555 /* Insert an HTML element for the token. */
2556 $this->insertElement($token);
2557
2558 /* Immediately pop the current node off the stack of open elements. */
2559 array_pop($this->stack);
2560 break;
2561
2562 /* A start tag whose tag name is "hr" */
2563 case 'hr':
2564 /* If the stack of open elements has a p element in scope,
2565 then act as if an end tag with the tag name p had been seen. */
2566 if ($this->elementInScope('p')) {
2567 $this->emitToken(
2568 array(
2569 'name' => 'p',
2570 'type' => HTML5::ENDTAG
2571 )
2572 );
2573 }
2574
2575 /* Insert an HTML element for the token. */
2576 $this->insertElement($token);
2577
2578 /* Immediately pop the current node off the stack of open elements. */
2579 array_pop($this->stack);
2580 break;
2581
2582 /* A start tag whose tag name is "image" */
2583 case 'image':
2584 /* Parse error. Change the token's tag name to "img" and
2585 reprocess it. (Don't ask.) */
2586 $token['name'] = 'img';
2587 return $this->inBody($token);
2588 break;
2589
2590 /* A start tag whose tag name is "input" */
2591 case 'input':
2592 /* Reconstruct the active formatting elements, if any. */
2594
2595 /* Insert an input element for the token. */
2596 $element = $this->insertElement($token, false);
2597
2598 /* If the form element pointer is not null, then associate the
2599 input element with the form element pointed to by the form
2600 element pointer. */
2601 $this->form_pointer !== null
2602 ? $this->form_pointer->appendChild($element)
2603 : end($this->stack)->appendChild($element);
2604
2605 /* Pop that input element off the stack of open elements. */
2606 array_pop($this->stack);
2607 break;
2608
2609 /* A start tag whose tag name is "isindex" */
2610 case 'isindex':
2611 /* Parse error. */
2612 // w/e
2613
2614 /* If the form element pointer is not null,
2615 then ignore the token. */
2616 if ($this->form_pointer === null) {
2617 /* Act as if a start tag token with the tag name "form" had
2618 been seen. */
2619 $this->inBody(
2620 array(
2621 'name' => 'body',
2622 'type' => HTML5::STARTTAG,
2623 'attr' => array()
2624 )
2625 );
2626
2627 /* Act as if a start tag token with the tag name "hr" had
2628 been seen. */
2629 $this->inBody(
2630 array(
2631 'name' => 'hr',
2632 'type' => HTML5::STARTTAG,
2633 'attr' => array()
2634 )
2635 );
2636
2637 /* Act as if a start tag token with the tag name "p" had
2638 been seen. */
2639 $this->inBody(
2640 array(
2641 'name' => 'p',
2642 'type' => HTML5::STARTTAG,
2643 'attr' => array()
2644 )
2645 );
2646
2647 /* Act as if a start tag token with the tag name "label"
2648 had been seen. */
2649 $this->inBody(
2650 array(
2651 'name' => 'label',
2652 'type' => HTML5::STARTTAG,
2653 'attr' => array()
2654 )
2655 );
2656
2657 /* Act as if a stream of character tokens had been seen. */
2658 $this->insertText(
2659 'This is a searchable index. ' .
2660 'Insert your search keywords here: '
2661 );
2662
2663 /* Act as if a start tag token with the tag name "input"
2664 had been seen, with all the attributes from the "isindex"
2665 token, except with the "name" attribute set to the value
2666 "isindex" (ignoring any explicit "name" attribute). */
2667 $attr = $token['attr'];
2668 $attr[] = array('name' => 'name', 'value' => 'isindex');
2669
2670 $this->inBody(
2671 array(
2672 'name' => 'input',
2673 'type' => HTML5::STARTTAG,
2674 'attr' => $attr
2675 )
2676 );
2677
2678 /* Act as if a stream of character tokens had been seen
2679 (see below for what they should say). */
2680 $this->insertText(
2681 'This is a searchable index. ' .
2682 'Insert your search keywords here: '
2683 );
2684
2685 /* Act as if an end tag token with the tag name "label"
2686 had been seen. */
2687 $this->inBody(
2688 array(
2689 'name' => 'label',
2690 'type' => HTML5::ENDTAG
2691 )
2692 );
2693
2694 /* Act as if an end tag token with the tag name "p" had
2695 been seen. */
2696 $this->inBody(
2697 array(
2698 'name' => 'p',
2699 'type' => HTML5::ENDTAG
2700 )
2701 );
2702
2703 /* Act as if a start tag token with the tag name "hr" had
2704 been seen. */
2705 $this->inBody(
2706 array(
2707 'name' => 'hr',
2708 'type' => HTML5::ENDTAG
2709 )
2710 );
2711
2712 /* Act as if an end tag token with the tag name "form" had
2713 been seen. */
2714 $this->inBody(
2715 array(
2716 'name' => 'form',
2717 'type' => HTML5::ENDTAG
2718 )
2719 );
2720 }
2721 break;
2722
2723 /* A start tag whose tag name is "textarea" */
2724 case 'textarea':
2725 $this->insertElement($token);
2726
2727 /* Switch the tokeniser's content model flag to the
2728 RCDATA state. */
2729 return HTML5::RCDATA;
2730 break;
2731
2732 /* A start tag whose tag name is one of: "iframe", "noembed",
2733 "noframes" */
2734 case 'iframe':
2735 case 'noembed':
2736 case 'noframes':
2737 $this->insertElement($token);
2738
2739 /* Switch the tokeniser's content model flag to the CDATA state. */
2740 return HTML5::CDATA;
2741 break;
2742
2743 /* A start tag whose tag name is "select" */
2744 case 'select':
2745 /* Reconstruct the active formatting elements, if any. */
2747
2748 /* Insert an HTML element for the token. */
2749 $this->insertElement($token);
2750
2751 /* Change the insertion mode to "in select". */
2752 $this->mode = self::IN_SELECT;
2753 break;
2754
2755 /* A start or end tag whose tag name is one of: "caption", "col",
2756 "colgroup", "frame", "frameset", "head", "option", "optgroup",
2757 "tbody", "td", "tfoot", "th", "thead", "tr". */
2758 case 'caption':
2759 case 'col':
2760 case 'colgroup':
2761 case 'frame':
2762 case 'frameset':
2763 case 'head':
2764 case 'option':
2765 case 'optgroup':
2766 case 'tbody':
2767 case 'td':
2768 case 'tfoot':
2769 case 'th':
2770 case 'thead':
2771 case 'tr':
2772 // Parse error. Ignore the token.
2773 break;
2774
2775 /* A start or end tag whose tag name is one of: "event-source",
2776 "section", "nav", "article", "aside", "header", "footer",
2777 "datagrid", "command" */
2778 case 'event-source':
2779 case 'section':
2780 case 'nav':
2781 case 'article':
2782 case 'aside':
2783 case 'header':
2784 case 'footer':
2785 case 'datagrid':
2786 case 'command':
2787 // Work in progress!
2788 break;
2789
2790 /* A start tag token not covered by the previous entries */
2791 default:
2792 /* Reconstruct the active formatting elements, if any. */
2794
2795 $this->insertElement($token, true, true);
2796 break;
2797 }
2798 break;
2799
2800 case HTML5::ENDTAG:
2801 switch ($token['name']) {
2802 /* An end tag with the tag name "body" */
2803 case 'body':
2804 /* If the second element in the stack of open elements is
2805 not a body element, this is a parse error. Ignore the token.
2806 (innerHTML case) */
2807 if (count($this->stack) < 2 || $this->stack[1]->nodeName !== 'body') {
2808 // Ignore.
2809
2810 /* If the current node is not the body element, then this
2811 is a parse error. */
2812 } elseif (end($this->stack)->nodeName !== 'body') {
2813 // Parse error.
2814 }
2815
2816 /* Change the insertion mode to "after body". */
2817 $this->mode = self::AFTER_BODY;
2818 break;
2819
2820 /* An end tag with the tag name "html" */
2821 case 'html':
2822 /* Act as if an end tag with tag name "body" had been seen,
2823 then, if that token wasn't ignored, reprocess the current
2824 token. */
2825 $this->inBody(
2826 array(
2827 'name' => 'body',
2828 'type' => HTML5::ENDTAG
2829 )
2830 );
2831
2832 return $this->afterBody($token);
2833 break;
2834
2835 /* An end tag whose tag name is one of: "address", "blockquote",
2836 "center", "dir", "div", "dl", "fieldset", "listing", "menu",
2837 "ol", "pre", "ul" */
2838 case 'address':
2839 case 'blockquote':
2840 case 'center':
2841 case 'dir':
2842 case 'div':
2843 case 'dl':
2844 case 'fieldset':
2845 case 'listing':
2846 case 'menu':
2847 case 'ol':
2848 case 'pre':
2849 case 'ul':
2850 /* If the stack of open elements has an element in scope
2851 with the same tag name as that of the token, then generate
2852 implied end tags. */
2853 if ($this->elementInScope($token['name'])) {
2854 $this->generateImpliedEndTags();
2855
2856 /* Now, if the current node is not an element with
2857 the same tag name as that of the token, then this
2858 is a parse error. */
2859 // w/e
2860
2861 /* If the stack of open elements has an element in
2862 scope with the same tag name as that of the token,
2863 then pop elements from this stack until an element
2864 with that tag name has been popped from the stack. */
2865 for ($n = count($this->stack) - 1; $n >= 0; $n--) {
2866 if ($this->stack[$n]->nodeName === $token['name']) {
2867 $n = -1;
2868 }
2869
2870 array_pop($this->stack);
2871 }
2872 }
2873 break;
2874
2875 /* An end tag whose tag name is "form" */
2876 case 'form':
2877 /* If the stack of open elements has an element in scope
2878 with the same tag name as that of the token, then generate
2879 implied end tags. */
2880 if ($this->elementInScope($token['name'])) {
2881 $this->generateImpliedEndTags();
2882
2883 }
2884
2885 if (end($this->stack)->nodeName !== $token['name']) {
2886 /* Now, if the current node is not an element with the
2887 same tag name as that of the token, then this is a parse
2888 error. */
2889 // w/e
2890
2891 } else {
2892 /* Otherwise, if the current node is an element with
2893 the same tag name as that of the token pop that element
2894 from the stack. */
2895 array_pop($this->stack);
2896 }
2897
2898 /* In any case, set the form element pointer to null. */
2899 $this->form_pointer = null;
2900 break;
2901
2902 /* An end tag whose tag name is "p" */
2903 case 'p':
2904 /* If the stack of open elements has a p element in scope,
2905 then generate implied end tags, except for p elements. */
2906 if ($this->elementInScope('p')) {
2907 $this->generateImpliedEndTags(array('p'));
2908
2909 /* If the current node is not a p element, then this is
2910 a parse error. */
2911 // k
2912
2913 /* If the stack of open elements has a p element in
2914 scope, then pop elements from this stack until the stack
2915 no longer has a p element in scope. */
2916 for ($n = count($this->stack) - 1; $n >= 0; $n--) {
2917 if ($this->elementInScope('p')) {
2918 array_pop($this->stack);
2919
2920 } else {
2921 break;
2922 }
2923 }
2924 }
2925 break;
2926
2927 /* An end tag whose tag name is "dd", "dt", or "li" */
2928 case 'dd':
2929 case 'dt':
2930 case 'li':
2931 /* If the stack of open elements has an element in scope
2932 whose tag name matches the tag name of the token, then
2933 generate implied end tags, except for elements with the
2934 same tag name as the token. */
2935 if ($this->elementInScope($token['name'])) {
2936 $this->generateImpliedEndTags(array($token['name']));
2937
2938 /* If the current node is not an element with the same
2939 tag name as the token, then this is a parse error. */
2940 // w/e
2941
2942 /* If the stack of open elements has an element in scope
2943 whose tag name matches the tag name of the token, then
2944 pop elements from this stack until an element with that
2945 tag name has been popped from the stack. */
2946 for ($n = count($this->stack) - 1; $n >= 0; $n--) {
2947 if ($this->stack[$n]->nodeName === $token['name']) {
2948 $n = -1;
2949 }
2950
2951 array_pop($this->stack);
2952 }
2953 }
2954 break;
2955
2956 /* An end tag whose tag name is one of: "h1", "h2", "h3", "h4",
2957 "h5", "h6" */
2958 case 'h1':
2959 case 'h2':
2960 case 'h3':
2961 case 'h4':
2962 case 'h5':
2963 case 'h6':
2964 $elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6');
2965
2966 /* If the stack of open elements has in scope an element whose
2967 tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then
2968 generate implied end tags. */
2969 if ($this->elementInScope($elements)) {
2970 $this->generateImpliedEndTags();
2971
2972 /* Now, if the current node is not an element with the same
2973 tag name as that of the token, then this is a parse error. */
2974 // w/e
2975
2976 /* If the stack of open elements has in scope an element
2977 whose tag name is one of "h1", "h2", "h3", "h4", "h5", or
2978 "h6", then pop elements from the stack until an element
2979 with one of those tag names has been popped from the stack. */
2980 while ($this->elementInScope($elements)) {
2981 array_pop($this->stack);
2982 }
2983 }
2984 break;
2985
2986 /* An end tag whose tag name is one of: "a", "b", "big", "em",
2987 "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u" */
2988 case 'a':
2989 case 'b':
2990 case 'big':
2991 case 'em':
2992 case 'font':
2993 case 'i':
2994 case 'nobr':
2995 case 's':
2996 case 'small':
2997 case 'strike':
2998 case 'strong':
2999 case 'tt':
3000 case 'u':
3001 /* 1. Let the formatting element be the last element in
3002 the list of active formatting elements that:
3003 * is between the end of the list and the last scope
3004 marker in the list, if any, or the start of the list
3005 otherwise, and
3006 * has the same tag name as the token.
3007 */
3008 while (true) {
3009 for ($a = count($this->a_formatting) - 1; $a >= 0; $a--) {
3010 if ($this->a_formatting[$a] === self::MARKER) {
3011 break;
3012
3013 } elseif ($this->a_formatting[$a]->tagName === $token['name']) {
3014 $formatting_element = $this->a_formatting[$a];
3015 $in_stack = in_array($formatting_element, $this->stack, true);
3016 $fe_af_pos = $a;
3017 break;
3018 }
3019 }
3020
3021 /* If there is no such node, or, if that node is
3022 also in the stack of open elements but the element
3023 is not in scope, then this is a parse error. Abort
3024 these steps. The token is ignored. */
3025 if (!isset($formatting_element) || ($in_stack &&
3026 !$this->elementInScope($token['name']))
3027 ) {
3028 break;
3029
3030 /* Otherwise, if there is such a node, but that node
3031 is not in the stack of open elements, then this is a
3032 parse error; remove the element from the list, and
3033 abort these steps. */
3034 } elseif (isset($formatting_element) && !$in_stack) {
3035 unset($this->a_formatting[$fe_af_pos]);
3036 $this->a_formatting = array_merge($this->a_formatting);
3037 break;
3038 }
3039
3040 /* 2. Let the furthest block be the topmost node in the
3041 stack of open elements that is lower in the stack
3042 than the formatting element, and is not an element in
3043 the phrasing or formatting categories. There might
3044 not be one. */
3045 $fe_s_pos = array_search($formatting_element, $this->stack, true);
3046 $length = count($this->stack);
3047
3048 for ($s = $fe_s_pos + 1; $s < $length; $s++) {
3049 $category = $this->getElementCategory($this->stack[$s]->nodeName);
3050
3051 if ($category !== self::PHRASING && $category !== self::FORMATTING) {
3052 $furthest_block = $this->stack[$s];
3053 }
3054 }
3055
3056 /* 3. If there is no furthest block, then the UA must
3057 skip the subsequent steps and instead just pop all
3058 the nodes from the bottom of the stack of open
3059 elements, from the current node up to the formatting
3060 element, and remove the formatting element from the
3061 list of active formatting elements. */
3062 if (!isset($furthest_block)) {
3063 for ($n = $length - 1; $n >= $fe_s_pos; $n--) {
3064 array_pop($this->stack);
3065 }
3066
3067 unset($this->a_formatting[$fe_af_pos]);
3068 $this->a_formatting = array_merge($this->a_formatting);
3069 break;
3070 }
3071
3072 /* 4. Let the common ancestor be the element
3073 immediately above the formatting element in the stack
3074 of open elements. */
3075 $common_ancestor = $this->stack[$fe_s_pos - 1];
3076
3077 /* 5. If the furthest block has a parent node, then
3078 remove the furthest block from its parent node. */
3079 if ($furthest_block->parentNode !== null) {
3080 $furthest_block->parentNode->removeChild($furthest_block);
3081 }
3082
3083 /* 6. Let a bookmark note the position of the
3084 formatting element in the list of active formatting
3085 elements relative to the elements on either side
3086 of it in the list. */
3087 $bookmark = $fe_af_pos;
3088
3089 /* 7. Let node and last node be the furthest block.
3090 Follow these steps: */
3091 $node = $furthest_block;
3092 $last_node = $furthest_block;
3093
3094 while (true) {
3095 for ($n = array_search($node, $this->stack, true) - 1; $n >= 0; $n--) {
3096 /* 7.1 Let node be the element immediately
3097 prior to node in the stack of open elements. */
3098 $node = $this->stack[$n];
3099
3100 /* 7.2 If node is not in the list of active
3101 formatting elements, then remove node from
3102 the stack of open elements and then go back
3103 to step 1. */
3104 if (!in_array($node, $this->a_formatting, true)) {
3105 unset($this->stack[$n]);
3106 $this->stack = array_merge($this->stack);
3107
3108 } else {
3109 break;
3110 }
3111 }
3112
3113 /* 7.3 Otherwise, if node is the formatting
3114 element, then go to the next step in the overall
3115 algorithm. */
3116 if ($node === $formatting_element) {
3117 break;
3118
3119 /* 7.4 Otherwise, if last node is the furthest
3120 block, then move the aforementioned bookmark to
3121 be immediately after the node in the list of
3122 active formatting elements. */
3123 } elseif ($last_node === $furthest_block) {
3124 $bookmark = array_search($node, $this->a_formatting, true) + 1;
3125 }
3126
3127 /* 7.5 If node has any children, perform a
3128 shallow clone of node, replace the entry for
3129 node in the list of active formatting elements
3130 with an entry for the clone, replace the entry
3131 for node in the stack of open elements with an
3132 entry for the clone, and let node be the clone. */
3133 if ($node->hasChildNodes()) {
3134 $clone = $node->cloneNode();
3135 $s_pos = array_search($node, $this->stack, true);
3136 $a_pos = array_search($node, $this->a_formatting, true);
3137
3138 $this->stack[$s_pos] = $clone;
3139 $this->a_formatting[$a_pos] = $clone;
3140 $node = $clone;
3141 }
3142
3143 /* 7.6 Insert last node into node, first removing
3144 it from its previous parent node if any. */
3145 if ($last_node->parentNode !== null) {
3146 $last_node->parentNode->removeChild($last_node);
3147 }
3148
3149 $node->appendChild($last_node);
3150
3151 /* 7.7 Let last node be node. */
3152 $last_node = $node;
3153 }
3154
3155 /* 8. Insert whatever last node ended up being in
3156 the previous step into the common ancestor node,
3157 first removing it from its previous parent node if
3158 any. */
3159 if ($last_node->parentNode !== null) {
3160 $last_node->parentNode->removeChild($last_node);
3161 }
3162
3163 $common_ancestor->appendChild($last_node);
3164
3165 /* 9. Perform a shallow clone of the formatting
3166 element. */
3167 $clone = $formatting_element->cloneNode();
3168
3169 /* 10. Take all of the child nodes of the furthest
3170 block and append them to the clone created in the
3171 last step. */
3172 while ($furthest_block->hasChildNodes()) {
3173 $child = $furthest_block->firstChild;
3174 $furthest_block->removeChild($child);
3175 $clone->appendChild($child);
3176 }
3177
3178 /* 11. Append that clone to the furthest block. */
3179 $furthest_block->appendChild($clone);
3180
3181 /* 12. Remove the formatting element from the list
3182 of active formatting elements, and insert the clone
3183 into the list of active formatting elements at the
3184 position of the aforementioned bookmark. */
3185 $fe_af_pos = array_search($formatting_element, $this->a_formatting, true);
3186 unset($this->a_formatting[$fe_af_pos]);
3187 $this->a_formatting = array_merge($this->a_formatting);
3188
3189 $af_part1 = array_slice($this->a_formatting, 0, $bookmark - 1);
3190 $af_part2 = array_slice($this->a_formatting, $bookmark, count($this->a_formatting));
3191 $this->a_formatting = array_merge($af_part1, array($clone), $af_part2);
3192
3193 /* 13. Remove the formatting element from the stack
3194 of open elements, and insert the clone into the stack
3195 of open elements immediately after (i.e. in a more
3196 deeply nested position than) the position of the
3197 furthest block in that stack. */
3198 $fe_s_pos = array_search($formatting_element, $this->stack, true);
3199 $fb_s_pos = array_search($furthest_block, $this->stack, true);
3200 unset($this->stack[$fe_s_pos]);
3201
3202 $s_part1 = array_slice($this->stack, 0, $fb_s_pos);
3203 $s_part2 = array_slice($this->stack, $fb_s_pos + 1, count($this->stack));
3204 $this->stack = array_merge($s_part1, array($clone), $s_part2);
3205
3206 /* 14. Jump back to step 1 in this series of steps. */
3207 unset($formatting_element, $fe_af_pos, $fe_s_pos, $furthest_block);
3208 }
3209 break;
3210
3211 /* An end tag token whose tag name is one of: "button",
3212 "marquee", "object" */
3213 case 'button':
3214 case 'marquee':
3215 case 'object':
3216 /* If the stack of open elements has an element in scope whose
3217 tag name matches the tag name of the token, then generate implied
3218 tags. */
3219 if ($this->elementInScope($token['name'])) {
3220 $this->generateImpliedEndTags();
3221
3222 /* Now, if the current node is not an element with the same
3223 tag name as the token, then this is a parse error. */
3224 // k
3225
3226 /* Now, if the stack of open elements has an element in scope
3227 whose tag name matches the tag name of the token, then pop
3228 elements from the stack until that element has been popped from
3229 the stack, and clear the list of active formatting elements up
3230 to the last marker. */
3231 for ($n = count($this->stack) - 1; $n >= 0; $n--) {
3232 if ($this->stack[$n]->nodeName === $token['name']) {
3233 $n = -1;
3234 }
3235
3236 array_pop($this->stack);
3237 }
3238
3239 $marker = end(array_keys($this->a_formatting, self::MARKER, true));
3240
3241 for ($n = count($this->a_formatting) - 1; $n > $marker; $n--) {
3242 array_pop($this->a_formatting);
3243 }
3244 }
3245 break;
3246
3247 /* Or an end tag whose tag name is one of: "area", "basefont",
3248 "bgsound", "br", "embed", "hr", "iframe", "image", "img",
3249 "input", "isindex", "noembed", "noframes", "param", "select",
3250 "spacer", "table", "textarea", "wbr" */
3251 case 'area':
3252 case 'basefont':
3253 case 'bgsound':
3254 case 'br':
3255 case 'embed':
3256 case 'hr':
3257 case 'iframe':
3258 case 'image':
3259 case 'img':
3260 case 'input':
3261 case 'isindex':
3262 case 'noembed':
3263 case 'noframes':
3264 case 'param':
3265 case 'select':
3266 case 'spacer':
3267 case 'table':
3268 case 'textarea':
3269 case 'wbr':
3270 // Parse error. Ignore the token.
3271 break;
3272
3273 /* An end tag token not covered by the previous entries */
3274 default:
3275 for ($n = count($this->stack) - 1; $n >= 0; $n--) {
3276 /* Initialise node to be the current node (the bottommost
3277 node of the stack). */
3278 $node = end($this->stack);
3279
3280 /* If node has the same tag name as the end tag token,
3281 then: */
3282 if ($token['name'] === $node->nodeName) {
3283 /* Generate implied end tags. */
3284 $this->generateImpliedEndTags();
3285
3286 /* If the tag name of the end tag token does not
3287 match the tag name of the current node, this is a
3288 parse error. */
3289 // k
3290
3291 /* Pop all the nodes from the current node up to
3292 node, including node, then stop this algorithm. */
3293 for ($x = count($this->stack) - $n; $x >= $n; $x--) {
3294 array_pop($this->stack);
3295 }
3296
3297 } else {
3298 $category = $this->getElementCategory($node);
3299
3300 if ($category !== self::SPECIAL && $category !== self::SCOPING) {
3301 /* Otherwise, if node is in neither the formatting
3302 category nor the phrasing category, then this is a
3303 parse error. Stop this algorithm. The end tag token
3304 is ignored. */
3305 return false;
3306 }
3307 }
3308 }
3309 break;
3310 }
3311 break;
3312 }
3313 }
getElementCategory($node)
Definition: PH5P.php:4634
emitToken($token)
Definition: PH5P.php:1712
afterBody($token)
Definition: PH5P.php:4201
generateImpliedEndTags($exclude=array())
Definition: PH5P.php:4619
reconstructActiveFormattingElements()
Definition: PH5P.php:4525
const CDATA
Definition: PH5P.php:451
const RCDATA
Definition: PH5P.php:450
const PLAINTEXT
Definition: PH5P.php:452
$x
Definition: example_009.php:98

References $n, $x, AFTER_BODY, afterBody(), HTML5\CDATA, HTML5\CHARACTR, HTML5\COMMENT, elementInScope(), emitToken(), HTML5\ENDTAG, generateImpliedEndTags(), getElementCategory(), IN_SELECT, IN_TABLE, inBody(), inHead(), insertComment(), insertElement(), insertText(), MARKER, HTML5\PLAINTEXT, HTML5\RCDATA, reconstructActiveFormattingElements(), and HTML5\STARTTAG.

Referenced by afterBody(), afterFrameset(), afterHead(), inBody(), inCaption(), inCell(), inFrameset(), inTable(), and mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inCaption()

HTML5TreeConstructer::inCaption (   $token)
private

Definition at line 3527 of file PH5P.php.

3528 {
3529 /* An end tag whose tag name is "caption" */
3530 if ($token['type'] === HTML5::ENDTAG && $token['name'] === 'caption') {
3531 /* If the stack of open elements does not have an element in table
3532 scope with the same tag name as the token, this is a parse error.
3533 Ignore the token. (innerHTML case) */
3534 if (!$this->elementInScope($token['name'], true)) {
3535 // Ignore
3536
3537 /* Otherwise: */
3538 } else {
3539 /* Generate implied end tags. */
3540 $this->generateImpliedEndTags();
3541
3542 /* Now, if the current node is not a caption element, then this
3543 is a parse error. */
3544 // w/e
3545
3546 /* Pop elements from this stack until a caption element has
3547 been popped from the stack. */
3548 while (true) {
3549 $node = end($this->stack)->nodeName;
3550 array_pop($this->stack);
3551
3552 if ($node === 'caption') {
3553 break;
3554 }
3555 }
3556
3557 /* Clear the list of active formatting elements up to the last
3558 marker. */
3560
3561 /* Switch the insertion mode to "in table". */
3562 $this->mode = self::IN_TABLE;
3563 }
3564
3565 /* A start tag whose tag name is one of: "caption", "col", "colgroup",
3566 "tbody", "td", "tfoot", "th", "thead", "tr", or an end tag whose tag
3567 name is "table" */
3568 } elseif (($token['type'] === HTML5::STARTTAG && in_array(
3569 $token['name'],
3570 array(
3571 'caption',
3572 'col',
3573 'colgroup',
3574 'tbody',
3575 'td',
3576 'tfoot',
3577 'th',
3578 'thead',
3579 'tr'
3580 )
3581 )) || ($token['type'] === HTML5::ENDTAG &&
3582 $token['name'] === 'table')
3583 ) {
3584 /* Parse error. Act as if an end tag with the tag name "caption"
3585 had been seen, then, if that token wasn't ignored, reprocess the
3586 current token. */
3587 $this->inCaption(
3588 array(
3589 'name' => 'caption',
3590 'type' => HTML5::ENDTAG
3591 )
3592 );
3593
3594 return $this->inTable($token);
3595
3596 /* An end tag whose tag name is one of: "body", "col", "colgroup",
3597 "html", "tbody", "td", "tfoot", "th", "thead", "tr" */
3598 } elseif ($token['type'] === HTML5::ENDTAG && in_array(
3599 $token['name'],
3600 array(
3601 'body',
3602 'col',
3603 'colgroup',
3604 'html',
3605 'tbody',
3606 'tfoot',
3607 'th',
3608 'thead',
3609 'tr'
3610 )
3611 )
3612 ) {
3613 // Parse error. Ignore the token.
3614
3615 /* Anything else */
3616 } else {
3617 /* Process the token as if the insertion mode was "in body". */
3618 $this->inBody($token);
3619 }
3620 }
inCaption($token)
Definition: PH5P.php:3527
clearTheActiveFormattingElementsUpToTheLastMarker()
Definition: PH5P.php:4597

References clearTheActiveFormattingElementsUpToTheLastMarker(), elementInScope(), HTML5\ENDTAG, generateImpliedEndTags(), IN_TABLE, inBody(), inCaption(), inTable(), and HTML5\STARTTAG.

Referenced by inCaption(), and mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inCell()

HTML5TreeConstructer::inCell (   $token)
private

Definition at line 3881 of file PH5P.php.

3882 {
3883 /* An end tag whose tag name is one of: "td", "th" */
3884 if ($token['type'] === HTML5::ENDTAG &&
3885 ($token['name'] === 'td' || $token['name'] === 'th')
3886 ) {
3887 /* If the stack of open elements does not have an element in table
3888 scope with the same tag name as that of the token, then this is a
3889 parse error and the token must be ignored. */
3890 if (!$this->elementInScope($token['name'], true)) {
3891 // Ignore.
3892
3893 /* Otherwise: */
3894 } else {
3895 /* Generate implied end tags, except for elements with the same
3896 tag name as the token. */
3897 $this->generateImpliedEndTags(array($token['name']));
3898
3899 /* Now, if the current node is not an element with the same tag
3900 name as the token, then this is a parse error. */
3901 // k
3902
3903 /* Pop elements from this stack until an element with the same
3904 tag name as the token has been popped from the stack. */
3905 while (true) {
3906 $node = end($this->stack)->nodeName;
3907 array_pop($this->stack);
3908
3909 if ($node === $token['name']) {
3910 break;
3911 }
3912 }
3913
3914 /* Clear the list of active formatting elements up to the last
3915 marker. */
3917
3918 /* Switch the insertion mode to "in row". (The current node
3919 will be a tr element at this point.) */
3920 $this->mode = self::IN_ROW;
3921 }
3922
3923 /* A start tag whose tag name is one of: "caption", "col", "colgroup",
3924 "tbody", "td", "tfoot", "th", "thead", "tr" */
3925 } elseif ($token['type'] === HTML5::STARTTAG && in_array(
3926 $token['name'],
3927 array(
3928 'caption',
3929 'col',
3930 'colgroup',
3931 'tbody',
3932 'td',
3933 'tfoot',
3934 'th',
3935 'thead',
3936 'tr'
3937 )
3938 )
3939 ) {
3940 /* If the stack of open elements does not have a td or th element
3941 in table scope, then this is a parse error; ignore the token.
3942 (innerHTML case) */
3943 if (!$this->elementInScope(array('td', 'th'), true)) {
3944 // Ignore.
3945
3946 /* Otherwise, close the cell (see below) and reprocess the current
3947 token. */
3948 } else {
3949 $this->closeCell();
3950 return $this->inRow($token);
3951 }
3952
3953 /* A start tag whose tag name is one of: "caption", "col", "colgroup",
3954 "tbody", "td", "tfoot", "th", "thead", "tr" */
3955 } elseif ($token['type'] === HTML5::STARTTAG && in_array(
3956 $token['name'],
3957 array(
3958 'caption',
3959 'col',
3960 'colgroup',
3961 'tbody',
3962 'td',
3963 'tfoot',
3964 'th',
3965 'thead',
3966 'tr'
3967 )
3968 )
3969 ) {
3970 /* If the stack of open elements does not have a td or th element
3971 in table scope, then this is a parse error; ignore the token.
3972 (innerHTML case) */
3973 if (!$this->elementInScope(array('td', 'th'), true)) {
3974 // Ignore.
3975
3976 /* Otherwise, close the cell (see below) and reprocess the current
3977 token. */
3978 } else {
3979 $this->closeCell();
3980 return $this->inRow($token);
3981 }
3982
3983 /* An end tag whose tag name is one of: "body", "caption", "col",
3984 "colgroup", "html" */
3985 } elseif ($token['type'] === HTML5::ENDTAG && in_array(
3986 $token['name'],
3987 array('body', 'caption', 'col', 'colgroup', 'html')
3988 )
3989 ) {
3990 /* Parse error. Ignore the token. */
3991
3992 /* An end tag whose tag name is one of: "table", "tbody", "tfoot",
3993 "thead", "tr" */
3994 } elseif ($token['type'] === HTML5::ENDTAG && in_array(
3995 $token['name'],
3996 array('table', 'tbody', 'tfoot', 'thead', 'tr')
3997 )
3998 ) {
3999 /* If the stack of open elements does not have an element in table
4000 scope with the same tag name as that of the token (which can only
4001 happen for "tbody", "tfoot" and "thead", or, in the innerHTML case),
4002 then this is a parse error and the token must be ignored. */
4003 if (!$this->elementInScope($token['name'], true)) {
4004 // Ignore.
4005
4006 /* Otherwise, close the cell (see below) and reprocess the current
4007 token. */
4008 } else {
4009 $this->closeCell();
4010 return $this->inRow($token);
4011 }
4012
4013 /* Anything else */
4014 } else {
4015 /* Process the token as if the insertion mode was "in body". */
4016 $this->inBody($token);
4017 }
4018 }

References clearTheActiveFormattingElementsUpToTheLastMarker(), closeCell(), elementInScope(), HTML5\ENDTAG, generateImpliedEndTags(), IN_ROW, inBody(), inRow(), and HTML5\STARTTAG.

Referenced by closeCell(), inRow(), and mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inColumnGroup()

HTML5TreeConstructer::inColumnGroup (   $token)
private

Definition at line 3622 of file PH5P.php.

3623 {
3624 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
3625 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
3626 or U+0020 SPACE */
3627 if ($token['type'] === HTML5::CHARACTR &&
3628 preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
3629 ) {
3630 /* Append the character to the current node. */
3631 $text = $this->dom->createTextNode($token['data']);
3632 end($this->stack)->appendChild($text);
3633
3634 /* A comment token */
3635 } elseif ($token['type'] === HTML5::COMMENT) {
3636 /* Append a Comment node to the current node with the data
3637 attribute set to the data given in the comment token. */
3638 $comment = $this->dom->createComment($token['data']);
3639 end($this->stack)->appendChild($comment);
3640
3641 /* A start tag whose tag name is "col" */
3642 } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'col') {
3643 /* Insert a col element for the token. Immediately pop the current
3644 node off the stack of open elements. */
3645 $this->insertElement($token);
3646 array_pop($this->stack);
3647
3648 /* An end tag whose tag name is "colgroup" */
3649 } elseif ($token['type'] === HTML5::ENDTAG &&
3650 $token['name'] === 'colgroup'
3651 ) {
3652 /* If the current node is the root html element, then this is a
3653 parse error, ignore the token. (innerHTML case) */
3654 if (end($this->stack)->nodeName === 'html') {
3655 // Ignore
3656
3657 /* Otherwise, pop the current node (which will be a colgroup
3658 element) from the stack of open elements. Switch the insertion
3659 mode to "in table". */
3660 } else {
3661 array_pop($this->stack);
3662 $this->mode = self::IN_TABLE;
3663 }
3664
3665 /* An end tag whose tag name is "col" */
3666 } elseif ($token['type'] === HTML5::ENDTAG && $token['name'] === 'col') {
3667 /* Parse error. Ignore the token. */
3668
3669 /* Anything else */
3670 } else {
3671 /* Act as if an end tag with the tag name "colgroup" had been seen,
3672 and then, if that token wasn't ignored, reprocess the current token. */
3673 $this->inColumnGroup(
3674 array(
3675 'name' => 'colgroup',
3676 'type' => HTML5::ENDTAG
3677 )
3678 );
3679
3680 return $this->inTable($token);
3681 }
3682 }
inColumnGroup($token)
Definition: PH5P.php:3622
$text

References $comment, $text, HTML5\CHARACTR, HTML5\COMMENT, HTML5\ENDTAG, IN_TABLE, inColumnGroup(), insertElement(), inTable(), and HTML5\STARTTAG.

Referenced by inColumnGroup(), inTable(), and mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inFrameset()

HTML5TreeConstructer::inFrameset (   $token)
private

Definition at line 4242 of file PH5P.php.

4243 {
4244 /* Handle the token as follows: */
4245
4246 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
4247 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
4248 U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */
4249 if ($token['type'] === HTML5::CHARACTR &&
4250 preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
4251 ) {
4252 /* Append the character to the current node. */
4253 $this->insertText($token['data']);
4254
4255 /* A comment token */
4256 } elseif ($token['type'] === HTML5::COMMENT) {
4257 /* Append a Comment node to the current node with the data
4258 attribute set to the data given in the comment token. */
4259 $this->insertComment($token['data']);
4260
4261 /* A start tag with the tag name "frameset" */
4262 } elseif ($token['name'] === 'frameset' &&
4263 $token['type'] === HTML5::STARTTAG
4264 ) {
4265 $this->insertElement($token);
4266
4267 /* An end tag with the tag name "frameset" */
4268 } elseif ($token['name'] === 'frameset' &&
4269 $token['type'] === HTML5::ENDTAG
4270 ) {
4271 /* If the current node is the root html element, then this is a
4272 parse error; ignore the token. (innerHTML case) */
4273 if (end($this->stack)->nodeName === 'html') {
4274 // Ignore
4275
4276 } else {
4277 /* Otherwise, pop the current node from the stack of open
4278 elements. */
4279 array_pop($this->stack);
4280
4281 /* If the parser was not originally created in order to handle
4282 the setting of an element's innerHTML attribute (innerHTML case),
4283 and the current node is no longer a frameset element, then change
4284 the insertion mode to "after frameset". */
4285 $this->mode = self::AFTR_FRAME;
4286 }
4287
4288 /* A start tag with the tag name "frame" */
4289 } elseif ($token['name'] === 'frame' &&
4290 $token['type'] === HTML5::STARTTAG
4291 ) {
4292 /* Insert an HTML element for the token. */
4293 $this->insertElement($token);
4294
4295 /* Immediately pop the current node off the stack of open elements. */
4296 array_pop($this->stack);
4297
4298 /* A start tag with the tag name "noframes" */
4299 } elseif ($token['name'] === 'noframes' &&
4300 $token['type'] === HTML5::STARTTAG
4301 ) {
4302 /* Process the token as if the insertion mode had been "in body". */
4303 $this->inBody($token);
4304
4305 /* Anything else */
4306 } else {
4307 /* Parse error. Ignore the token. */
4308 }
4309 }

References AFTR_FRAME, HTML5\CHARACTR, HTML5\COMMENT, HTML5\ENDTAG, inBody(), insertComment(), insertElement(), insertText(), and HTML5\STARTTAG.

Referenced by mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inHead()

HTML5TreeConstructer::inHead (   $token)
private

Definition at line 1977 of file PH5P.php.

1978 {
1979 /* Handle the token as follows: */
1980
1981 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
1982 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
1983 or U+0020 SPACE.
1984
1985 THIS DIFFERS FROM THE SPEC: If the current node is either a title, style
1986 or script element, append the character to the current node regardless
1987 of its content. */
1988 if (($token['type'] === HTML5::CHARACTR &&
1989 preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) || (
1990 $token['type'] === HTML5::CHARACTR && in_array(
1991 end($this->stack)->nodeName,
1992 array('title', 'style', 'script')
1993 ))
1994 ) {
1995 /* Append the character to the current node. */
1996 $this->insertText($token['data']);
1997
1998 /* A comment token */
1999 } elseif ($token['type'] === HTML5::COMMENT) {
2000 /* Append a Comment node to the current node with the data attribute
2001 set to the data given in the comment token. */
2002 $this->insertComment($token['data']);
2003
2004 } elseif ($token['type'] === HTML5::ENDTAG &&
2005 in_array($token['name'], array('title', 'style', 'script'))
2006 ) {
2007 array_pop($this->stack);
2008 return HTML5::PCDATA;
2009
2010 /* A start tag with the tag name "title" */
2011 } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'title') {
2012 /* Create an element for the token and append the new element to the
2013 node pointed to by the head element pointer, or, if that is null
2014 (innerHTML case), to the current node. */
2015 if ($this->head_pointer !== null) {
2016 $element = $this->insertElement($token, false);
2017 $this->head_pointer->appendChild($element);
2018
2019 } else {
2020 $element = $this->insertElement($token);
2021 }
2022
2023 /* Switch the tokeniser's content model flag to the RCDATA state. */
2024 return HTML5::RCDATA;
2025
2026 /* A start tag with the tag name "style" */
2027 } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'style') {
2028 /* Create an element for the token and append the new element to the
2029 node pointed to by the head element pointer, or, if that is null
2030 (innerHTML case), to the current node. */
2031 if ($this->head_pointer !== null) {
2032 $element = $this->insertElement($token, false);
2033 $this->head_pointer->appendChild($element);
2034
2035 } else {
2036 $this->insertElement($token);
2037 }
2038
2039 /* Switch the tokeniser's content model flag to the CDATA state. */
2040 return HTML5::CDATA;
2041
2042 /* A start tag with the tag name "script" */
2043 } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'script') {
2044 /* Create an element for the token. */
2045 $element = $this->insertElement($token, false);
2046 $this->head_pointer->appendChild($element);
2047
2048 /* Switch the tokeniser's content model flag to the CDATA state. */
2049 return HTML5::CDATA;
2050
2051 /* A start tag with the tag name "base", "link", or "meta" */
2052 } elseif ($token['type'] === HTML5::STARTTAG && in_array(
2053 $token['name'],
2054 array('base', 'link', 'meta')
2055 )
2056 ) {
2057 /* Create an element for the token and append the new element to the
2058 node pointed to by the head element pointer, or, if that is null
2059 (innerHTML case), to the current node. */
2060 if ($this->head_pointer !== null) {
2061 $element = $this->insertElement($token, false);
2062 $this->head_pointer->appendChild($element);
2063 array_pop($this->stack);
2064
2065 } else {
2066 $this->insertElement($token);
2067 }
2068
2069 /* An end tag with the tag name "head" */
2070 } elseif ($token['type'] === HTML5::ENDTAG && $token['name'] === 'head') {
2071 /* If the current node is a head element, pop the current node off
2072 the stack of open elements. */
2073 if ($this->head_pointer->isSameNode(end($this->stack))) {
2074 array_pop($this->stack);
2075
2076 /* Otherwise, this is a parse error. */
2077 } else {
2078 // k
2079 }
2080
2081 /* Change the insertion mode to "after head". */
2082 $this->mode = self::AFTER_HEAD;
2083
2084 /* A start tag with the tag name "head" or an end tag except "html". */
2085 } elseif (($token['type'] === HTML5::STARTTAG && $token['name'] === 'head') ||
2086 ($token['type'] === HTML5::ENDTAG && $token['name'] !== 'html')
2087 ) {
2088 // Parse error. Ignore the token.
2089
2090 /* Anything else */
2091 } else {
2092 /* If the current node is a head element, act as if an end tag
2093 token with the tag name "head" had been seen. */
2094 if ($this->head_pointer->isSameNode(end($this->stack))) {
2095 $this->inHead(
2096 array(
2097 'name' => 'head',
2098 'type' => HTML5::ENDTAG
2099 )
2100 );
2101
2102 /* Otherwise, change the insertion mode to "after head". */
2103 } else {
2104 $this->mode = self::AFTER_HEAD;
2105 }
2106
2107 /* Then, reprocess the current token. */
2108 return $this->afterHead($token);
2109 }
2110 }
const PCDATA
Definition: PH5P.php:449

References AFTER_HEAD, afterHead(), HTML5\CDATA, HTML5\CHARACTR, HTML5\COMMENT, HTML5\ENDTAG, inHead(), insertComment(), insertElement(), insertText(), HTML5\PCDATA, HTML5\RCDATA, and HTML5\STARTTAG.

Referenced by afterHead(), beforeHead(), inBody(), inHead(), and mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ initPhase()

HTML5TreeConstructer::initPhase (   $token)
private

Definition at line 1730 of file PH5P.php.

1731 {
1732 /* Initially, the tree construction stage must handle each token
1733 emitted from the tokenisation stage as follows: */
1734
1735 /* A DOCTYPE token that is marked as being in error
1736 A comment token
1737 A start tag token
1738 An end tag token
1739 A character token that is not one of one of U+0009 CHARACTER TABULATION,
1740 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
1741 or U+0020 SPACE
1742 An end-of-file token */
1743 if ((isset($token['error']) && $token['error']) ||
1744 $token['type'] === HTML5::COMMENT ||
1745 $token['type'] === HTML5::STARTTAG ||
1746 $token['type'] === HTML5::ENDTAG ||
1747 $token['type'] === HTML5::EOF ||
1748 ($token['type'] === HTML5::CHARACTR && isset($token['data']) &&
1749 !preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data']))
1750 ) {
1751 /* This specification does not define how to handle this case. In
1752 particular, user agents may ignore the entirety of this specification
1753 altogether for such documents, and instead invoke special parse modes
1754 with a greater emphasis on backwards compatibility. */
1755
1756 $this->phase = self::ROOT_PHASE;
1757 return $this->rootElementPhase($token);
1758
1759 /* A DOCTYPE token marked as being correct */
1760 } elseif (isset($token['error']) && !$token['error']) {
1761 /* Append a DocumentType node to the Document node, with the name
1762 attribute set to the name given in the DOCTYPE token (which will be
1763 "HTML"), and the other attributes specific to DocumentType objects
1764 set to null, empty lists, or the empty string as appropriate. */
1765 $doctype = new DOMDocumentType(null, null, 'HTML');
1766
1767 /* Then, switch to the root element phase of the tree construction
1768 stage. */
1769 $this->phase = self::ROOT_PHASE;
1770
1771 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
1772 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
1773 or U+0020 SPACE */
1774 } elseif (isset($token['data']) && preg_match(
1775 '/^[\t\n\x0b\x0c ]+$/',
1776 $token['data']
1777 )
1778 ) {
1779 /* Append that character to the Document node. */
1780 $text = $this->dom->createTextNode($token['data']);
1781 $this->dom->appendChild($text);
1782 }
1783 }
const EOF
Definition: PH5P.php:459

References $text, HTML5\CHARACTR, HTML5\COMMENT, HTML5\ENDTAG, HTML5\EOF, ROOT_PHASE, rootElementPhase(), and HTML5\STARTTAG.

Referenced by emitToken().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inRow()

HTML5TreeConstructer::inRow (   $token)
private

Definition at line 3783 of file PH5P.php.

3784 {
3785 $clear = array('tr', 'html');
3786
3787 /* A start tag whose tag name is one of: "th", "td" */
3788 if ($token['type'] === HTML5::STARTTAG &&
3789 ($token['name'] === 'th' || $token['name'] === 'td')
3790 ) {
3791 /* Clear the stack back to a table row context. */
3792 $this->clearStackToTableContext($clear);
3793
3794 /* Insert an HTML element for the token, then switch the insertion
3795 mode to "in cell". */
3796 $this->insertElement($token);
3797 $this->mode = self::IN_CELL;
3798
3799 /* Insert a marker at the end of the list of active formatting
3800 elements. */
3801 $this->a_formatting[] = self::MARKER;
3802
3803 /* An end tag whose tag name is "tr" */
3804 } elseif ($token['type'] === HTML5::ENDTAG && $token['name'] === 'tr') {
3805 /* If the stack of open elements does not have an element in table
3806 scope with the same tag name as the token, this is a parse error.
3807 Ignore the token. (innerHTML case) */
3808 if (!$this->elementInScope($token['name'], true)) {
3809 // Ignore.
3810
3811 /* Otherwise: */
3812 } else {
3813 /* Clear the stack back to a table row context. */
3814 $this->clearStackToTableContext($clear);
3815
3816 /* Pop the current node (which will be a tr element) from the
3817 stack of open elements. Switch the insertion mode to "in table
3818 body". */
3819 array_pop($this->stack);
3820 $this->mode = self::IN_TBODY;
3821 }
3822
3823 /* A start tag whose tag name is one of: "caption", "col", "colgroup",
3824 "tbody", "tfoot", "thead", "tr" or an end tag whose tag name is "table" */
3825 } elseif ($token['type'] === HTML5::STARTTAG && in_array(
3826 $token['name'],
3827 array('caption', 'col', 'colgroup', 'tbody', 'tfoot', 'thead', 'tr')
3828 )
3829 ) {
3830 /* Act as if an end tag with the tag name "tr" had been seen, then,
3831 if that token wasn't ignored, reprocess the current token. */
3832 $this->inRow(
3833 array(
3834 'name' => 'tr',
3835 'type' => HTML5::ENDTAG
3836 )
3837 );
3838
3839 return $this->inCell($token);
3840
3841 /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */
3842 } elseif ($token['type'] === HTML5::ENDTAG &&
3843 in_array($token['name'], array('tbody', 'tfoot', 'thead'))
3844 ) {
3845 /* If the stack of open elements does not have an element in table
3846 scope with the same tag name as the token, this is a parse error.
3847 Ignore the token. */
3848 if (!$this->elementInScope($token['name'], true)) {
3849 // Ignore.
3850
3851 /* Otherwise: */
3852 } else {
3853 /* Otherwise, act as if an end tag with the tag name "tr" had
3854 been seen, then reprocess the current token. */
3855 $this->inRow(
3856 array(
3857 'name' => 'tr',
3858 'type' => HTML5::ENDTAG
3859 )
3860 );
3861
3862 return $this->inCell($token);
3863 }
3864
3865 /* An end tag whose tag name is one of: "body", "caption", "col",
3866 "colgroup", "html", "td", "th" */
3867 } elseif ($token['type'] === HTML5::ENDTAG && in_array(
3868 $token['name'],
3869 array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th', 'tr')
3870 )
3871 ) {
3872 /* Parse error. Ignore the token. */
3873
3874 /* Anything else */
3875 } else {
3876 /* Process the token as if the insertion mode was "in table". */
3877 $this->inTable($token);
3878 }
3879 }
clearStackToTableContext($elements)
Definition: PH5P.php:4648

References clearStackToTableContext(), elementInScope(), HTML5\ENDTAG, IN_CELL, IN_TBODY, inCell(), inRow(), insertElement(), inTable(), MARKER, and HTML5\STARTTAG.

Referenced by inCell(), inRow(), inTableBody(), and mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inSelect()

HTML5TreeConstructer::inSelect (   $token)
private

Definition at line 4020 of file PH5P.php.

4021 {
4022 /* Handle the token as follows: */
4023
4024 /* A character token */
4025 if ($token['type'] === HTML5::CHARACTR) {
4026 /* Append the token's character to the current node. */
4027 $this->insertText($token['data']);
4028
4029 /* A comment token */
4030 } elseif ($token['type'] === HTML5::COMMENT) {
4031 /* Append a Comment node to the current node with the data
4032 attribute set to the data given in the comment token. */
4033 $this->insertComment($token['data']);
4034
4035 /* A start tag token whose tag name is "option" */
4036 } elseif ($token['type'] === HTML5::STARTTAG &&
4037 $token['name'] === 'option'
4038 ) {
4039 /* If the current node is an option element, act as if an end tag
4040 with the tag name "option" had been seen. */
4041 if (end($this->stack)->nodeName === 'option') {
4042 $this->inSelect(
4043 array(
4044 'name' => 'option',
4045 'type' => HTML5::ENDTAG
4046 )
4047 );
4048 }
4049
4050 /* Insert an HTML element for the token. */
4051 $this->insertElement($token);
4052
4053 /* A start tag token whose tag name is "optgroup" */
4054 } elseif ($token['type'] === HTML5::STARTTAG &&
4055 $token['name'] === 'optgroup'
4056 ) {
4057 /* If the current node is an option element, act as if an end tag
4058 with the tag name "option" had been seen. */
4059 if (end($this->stack)->nodeName === 'option') {
4060 $this->inSelect(
4061 array(
4062 'name' => 'option',
4063 'type' => HTML5::ENDTAG
4064 )
4065 );
4066 }
4067
4068 /* If the current node is an optgroup element, act as if an end tag
4069 with the tag name "optgroup" had been seen. */
4070 if (end($this->stack)->nodeName === 'optgroup') {
4071 $this->inSelect(
4072 array(
4073 'name' => 'optgroup',
4074 'type' => HTML5::ENDTAG
4075 )
4076 );
4077 }
4078
4079 /* Insert an HTML element for the token. */
4080 $this->insertElement($token);
4081
4082 /* An end tag token whose tag name is "optgroup" */
4083 } elseif ($token['type'] === HTML5::ENDTAG &&
4084 $token['name'] === 'optgroup'
4085 ) {
4086 /* First, if the current node is an option element, and the node
4087 immediately before it in the stack of open elements is an optgroup
4088 element, then act as if an end tag with the tag name "option" had
4089 been seen. */
4090 $elements_in_stack = count($this->stack);
4091
4092 if ($this->stack[$elements_in_stack - 1]->nodeName === 'option' &&
4093 $this->stack[$elements_in_stack - 2]->nodeName === 'optgroup'
4094 ) {
4095 $this->inSelect(
4096 array(
4097 'name' => 'option',
4098 'type' => HTML5::ENDTAG
4099 )
4100 );
4101 }
4102
4103 /* If the current node is an optgroup element, then pop that node
4104 from the stack of open elements. Otherwise, this is a parse error,
4105 ignore the token. */
4106 if ($this->stack[$elements_in_stack - 1] === 'optgroup') {
4107 array_pop($this->stack);
4108 }
4109
4110 /* An end tag token whose tag name is "option" */
4111 } elseif ($token['type'] === HTML5::ENDTAG &&
4112 $token['name'] === 'option'
4113 ) {
4114 /* If the current node is an option element, then pop that node
4115 from the stack of open elements. Otherwise, this is a parse error,
4116 ignore the token. */
4117 if (end($this->stack)->nodeName === 'option') {
4118 array_pop($this->stack);
4119 }
4120
4121 /* An end tag whose tag name is "select" */
4122 } elseif ($token['type'] === HTML5::ENDTAG &&
4123 $token['name'] === 'select'
4124 ) {
4125 /* If the stack of open elements does not have an element in table
4126 scope with the same tag name as the token, this is a parse error.
4127 Ignore the token. (innerHTML case) */
4128 if (!$this->elementInScope($token['name'], true)) {
4129 // w/e
4130
4131 /* Otherwise: */
4132 } else {
4133 /* Pop elements from the stack of open elements until a select
4134 element has been popped from the stack. */
4135 while (true) {
4136 $current = end($this->stack)->nodeName;
4137 array_pop($this->stack);
4138
4139 if ($current === 'select') {
4140 break;
4141 }
4142 }
4143
4144 /* Reset the insertion mode appropriately. */
4145 $this->resetInsertionMode();
4146 }
4147
4148 /* A start tag whose tag name is "select" */
4149 } elseif ($token['name'] === 'select' &&
4150 $token['type'] === HTML5::STARTTAG
4151 ) {
4152 /* Parse error. Act as if the token had been an end tag with the
4153 tag name "select" instead. */
4154 $this->inSelect(
4155 array(
4156 'name' => 'select',
4157 'type' => HTML5::ENDTAG
4158 )
4159 );
4160
4161 /* An end tag whose tag name is one of: "caption", "table", "tbody",
4162 "tfoot", "thead", "tr", "td", "th" */
4163 } elseif (in_array(
4164 $token['name'],
4165 array(
4166 'caption',
4167 'table',
4168 'tbody',
4169 'tfoot',
4170 'thead',
4171 'tr',
4172 'td',
4173 'th'
4174 )
4175 ) && $token['type'] === HTML5::ENDTAG
4176 ) {
4177 /* Parse error. */
4178 // w/e
4179
4180 /* If the stack of open elements has an element in table scope with
4181 the same tag name as that of the token, then act as if an end tag
4182 with the tag name "select" had been seen, and reprocess the token.
4183 Otherwise, ignore the token. */
4184 if ($this->elementInScope($token['name'], true)) {
4185 $this->inSelect(
4186 array(
4187 'name' => 'select',
4188 'type' => HTML5::ENDTAG
4189 )
4190 );
4191
4192 $this->mainPhase($token);
4193 }
4194
4195 /* Anything else */
4196 } else {
4197 /* Parse error. Ignore the token. */
4198 }
4199 }
inSelect($token)
Definition: PH5P.php:4020

References HTML5\CHARACTR, HTML5\COMMENT, elementInScope(), HTML5\ENDTAG, inSelect(), insertComment(), insertElement(), insertText(), mainPhase(), resetInsertionMode(), and HTML5\STARTTAG.

Referenced by inSelect(), and mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ insertComment()

HTML5TreeConstructer::insertComment (   $data)
private

Definition at line 4428 of file PH5P.php.

4429 {
4430 $comment = $this->dom->createComment($data);
4432 }
appendToRealParent($node)
Definition: PH5P.php:4434
$data

References $comment, $data, and appendToRealParent().

Referenced by afterFrameset(), afterHead(), beforeHead(), inBody(), inFrameset(), inHead(), and inSelect().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ insertElement()

HTML5TreeConstructer::insertElement (   $token,
  $append = true,
  $check = false 
)
private

Definition at line 4393 of file PH5P.php.

4394 {
4395 // Proprietary workaround for libxml2's limitations with tag names
4396 if ($check) {
4397 // Slightly modified HTML5 tag-name modification,
4398 // removing anything that's not an ASCII letter, digit, or hyphen
4399 $token['name'] = preg_replace('/[^a-z0-9-]/i', '', $token['name']);
4400 // Remove leading hyphens and numbers
4401 $token['name'] = ltrim($token['name'], '-0..9');
4402 // In theory, this should ever be needed, but just in case
4403 if ($token['name'] === '') {
4404 $token['name'] = 'span';
4405 } // arbitrary generic choice
4406 }
4407
4408 $el = $this->dom->createElement($token['name']);
4409
4410 foreach ($token['attr'] as $attr) {
4411 if (!$el->hasAttribute($attr['name'])) {
4412 $el->setAttribute($attr['name'], $attr['value']);
4413 }
4414 }
4415
4416 $this->appendToRealParent($el);
4417 $this->stack[] = $el;
4418
4419 return $el;
4420 }

References appendToRealParent().

Referenced by afterHead(), beforeHead(), inBody(), inColumnGroup(), inFrameset(), inHead(), inRow(), inSelect(), inTable(), and inTableBody().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ insertText()

HTML5TreeConstructer::insertText (   $data)
private

Definition at line 4422 of file PH5P.php.

4423 {
4424 $text = $this->dom->createTextNode($data);
4425 $this->appendToRealParent($text);
4426 }

References $data, $text, and appendToRealParent().

Referenced by afterFrameset(), afterHead(), beforeHead(), inBody(), inFrameset(), inHead(), and inSelect().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inTable()

HTML5TreeConstructer::inTable (   $token)
private

Definition at line 3315 of file PH5P.php.

3316 {
3317 $clear = array('html', 'table');
3318
3319 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
3320 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
3321 or U+0020 SPACE */
3322 if ($token['type'] === HTML5::CHARACTR &&
3323 preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
3324 ) {
3325 /* Append the character to the current node. */
3326 $text = $this->dom->createTextNode($token['data']);
3327 end($this->stack)->appendChild($text);
3328
3329 /* A comment token */
3330 } elseif ($token['type'] === HTML5::COMMENT) {
3331 /* Append a Comment node to the current node with the data
3332 attribute set to the data given in the comment token. */
3333 $comment = $this->dom->createComment($token['data']);
3334 end($this->stack)->appendChild($comment);
3335
3336 /* A start tag whose tag name is "caption" */
3337 } elseif ($token['type'] === HTML5::STARTTAG &&
3338 $token['name'] === 'caption'
3339 ) {
3340 /* Clear the stack back to a table context. */
3341 $this->clearStackToTableContext($clear);
3342
3343 /* Insert a marker at the end of the list of active
3344 formatting elements. */
3345 $this->a_formatting[] = self::MARKER;
3346
3347 /* Insert an HTML element for the token, then switch the
3348 insertion mode to "in caption". */
3349 $this->insertElement($token);
3350 $this->mode = self::IN_CAPTION;
3351
3352 /* A start tag whose tag name is "colgroup" */
3353 } elseif ($token['type'] === HTML5::STARTTAG &&
3354 $token['name'] === 'colgroup'
3355 ) {
3356 /* Clear the stack back to a table context. */
3357 $this->clearStackToTableContext($clear);
3358
3359 /* Insert an HTML element for the token, then switch the
3360 insertion mode to "in column group". */
3361 $this->insertElement($token);
3362 $this->mode = self::IN_CGROUP;
3363
3364 /* A start tag whose tag name is "col" */
3365 } elseif ($token['type'] === HTML5::STARTTAG &&
3366 $token['name'] === 'col'
3367 ) {
3368 $this->inTable(
3369 array(
3370 'name' => 'colgroup',
3371 'type' => HTML5::STARTTAG,
3372 'attr' => array()
3373 )
3374 );
3375
3376 $this->inColumnGroup($token);
3377
3378 /* A start tag whose tag name is one of: "tbody", "tfoot", "thead" */
3379 } elseif ($token['type'] === HTML5::STARTTAG && in_array(
3380 $token['name'],
3381 array('tbody', 'tfoot', 'thead')
3382 )
3383 ) {
3384 /* Clear the stack back to a table context. */
3385 $this->clearStackToTableContext($clear);
3386
3387 /* Insert an HTML element for the token, then switch the insertion
3388 mode to "in table body". */
3389 $this->insertElement($token);
3390 $this->mode = self::IN_TBODY;
3391
3392 /* A start tag whose tag name is one of: "td", "th", "tr" */
3393 } elseif ($token['type'] === HTML5::STARTTAG &&
3394 in_array($token['name'], array('td', 'th', 'tr'))
3395 ) {
3396 /* Act as if a start tag token with the tag name "tbody" had been
3397 seen, then reprocess the current token. */
3398 $this->inTable(
3399 array(
3400 'name' => 'tbody',
3401 'type' => HTML5::STARTTAG,
3402 'attr' => array()
3403 )
3404 );
3405
3406 return $this->inTableBody($token);
3407
3408 /* A start tag whose tag name is "table" */
3409 } elseif ($token['type'] === HTML5::STARTTAG &&
3410 $token['name'] === 'table'
3411 ) {
3412 /* Parse error. Act as if an end tag token with the tag name "table"
3413 had been seen, then, if that token wasn't ignored, reprocess the
3414 current token. */
3415 $this->inTable(
3416 array(
3417 'name' => 'table',
3418 'type' => HTML5::ENDTAG
3419 )
3420 );
3421
3422 return $this->mainPhase($token);
3423
3424 /* An end tag whose tag name is "table" */
3425 } elseif ($token['type'] === HTML5::ENDTAG &&
3426 $token['name'] === 'table'
3427 ) {
3428 /* If the stack of open elements does not have an element in table
3429 scope with the same tag name as the token, this is a parse error.
3430 Ignore the token. (innerHTML case) */
3431 if (!$this->elementInScope($token['name'], true)) {
3432 return false;
3433
3434 /* Otherwise: */
3435 } else {
3436 /* Generate implied end tags. */
3437 $this->generateImpliedEndTags();
3438
3439 /* Now, if the current node is not a table element, then this
3440 is a parse error. */
3441 // w/e
3442
3443 /* Pop elements from this stack until a table element has been
3444 popped from the stack. */
3445 while (true) {
3446 $current = end($this->stack)->nodeName;
3447 array_pop($this->stack);
3448
3449 if ($current === 'table') {
3450 break;
3451 }
3452 }
3453
3454 /* Reset the insertion mode appropriately. */
3455 $this->resetInsertionMode();
3456 }
3457
3458 /* An end tag whose tag name is one of: "body", "caption", "col",
3459 "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr" */
3460 } elseif ($token['type'] === HTML5::ENDTAG && in_array(
3461 $token['name'],
3462 array(
3463 'body',
3464 'caption',
3465 'col',
3466 'colgroup',
3467 'html',
3468 'tbody',
3469 'td',
3470 'tfoot',
3471 'th',
3472 'thead',
3473 'tr'
3474 )
3475 )
3476 ) {
3477 // Parse error. Ignore the token.
3478
3479 /* Anything else */
3480 } else {
3481 /* Parse error. Process the token as if the insertion mode was "in
3482 body", with the following exception: */
3483
3484 /* If the current node is a table, tbody, tfoot, thead, or tr
3485 element, then, whenever a node would be inserted into the current
3486 node, it must instead be inserted into the foster parent element. */
3487 if (in_array(
3488 end($this->stack)->nodeName,
3489 array('table', 'tbody', 'tfoot', 'thead', 'tr')
3490 )
3491 ) {
3492 /* The foster parent element is the parent element of the last
3493 table element in the stack of open elements, if there is a
3494 table element and it has such a parent element. If there is no
3495 table element in the stack of open elements (innerHTML case),
3496 then the foster parent element is the first element in the
3497 stack of open elements (the html element). Otherwise, if there
3498 is a table element in the stack of open elements, but the last
3499 table element in the stack of open elements has no parent, or
3500 its parent node is not an element, then the foster parent
3501 element is the element before the last table element in the
3502 stack of open elements. */
3503 for ($n = count($this->stack) - 1; $n >= 0; $n--) {
3504 if ($this->stack[$n]->nodeName === 'table') {
3505 $table = $this->stack[$n];
3506 break;
3507 }
3508 }
3509
3510 if (isset($table) && $table->parentNode !== null) {
3511 $this->foster_parent = $table->parentNode;
3512
3513 } elseif (!isset($table)) {
3514 $this->foster_parent = $this->stack[0];
3515
3516 } elseif (isset($table) && ($table->parentNode === null ||
3517 $table->parentNode->nodeType !== XML_ELEMENT_NODE)
3518 ) {
3519 $this->foster_parent = $this->stack[$n - 1];
3520 }
3521 }
3522
3523 $this->inBody($token);
3524 }
3525 }
inTableBody($token)
Definition: PH5P.php:3684

References $comment, $n, $text, HTML5\CHARACTR, clearStackToTableContext(), HTML5\COMMENT, elementInScope(), HTML5\ENDTAG, generateImpliedEndTags(), IN_CAPTION, IN_CGROUP, IN_TBODY, inBody(), inColumnGroup(), insertElement(), inTable(), inTableBody(), mainPhase(), MARKER, resetInsertionMode(), and HTML5\STARTTAG.

Referenced by inCaption(), inColumnGroup(), inRow(), inTable(), inTableBody(), and mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inTableBody()

HTML5TreeConstructer::inTableBody (   $token)
private

Definition at line 3684 of file PH5P.php.

3685 {
3686 $clear = array('tbody', 'tfoot', 'thead', 'html');
3687
3688 /* A start tag whose tag name is "tr" */
3689 if ($token['type'] === HTML5::STARTTAG && $token['name'] === 'tr') {
3690 /* Clear the stack back to a table body context. */
3691 $this->clearStackToTableContext($clear);
3692
3693 /* Insert a tr element for the token, then switch the insertion
3694 mode to "in row". */
3695 $this->insertElement($token);
3696 $this->mode = self::IN_ROW;
3697
3698 /* A start tag whose tag name is one of: "th", "td" */
3699 } elseif ($token['type'] === HTML5::STARTTAG &&
3700 ($token['name'] === 'th' || $token['name'] === 'td')
3701 ) {
3702 /* Parse error. Act as if a start tag with the tag name "tr" had
3703 been seen, then reprocess the current token. */
3704 $this->inTableBody(
3705 array(
3706 'name' => 'tr',
3707 'type' => HTML5::STARTTAG,
3708 'attr' => array()
3709 )
3710 );
3711
3712 return $this->inRow($token);
3713
3714 /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */
3715 } elseif ($token['type'] === HTML5::ENDTAG &&
3716 in_array($token['name'], array('tbody', 'tfoot', 'thead'))
3717 ) {
3718 /* If the stack of open elements does not have an element in table
3719 scope with the same tag name as the token, this is a parse error.
3720 Ignore the token. */
3721 if (!$this->elementInScope($token['name'], true)) {
3722 // Ignore
3723
3724 /* Otherwise: */
3725 } else {
3726 /* Clear the stack back to a table body context. */
3727 $this->clearStackToTableContext($clear);
3728
3729 /* Pop the current node from the stack of open elements. Switch
3730 the insertion mode to "in table". */
3731 array_pop($this->stack);
3732 $this->mode = self::IN_TABLE;
3733 }
3734
3735 /* A start tag whose tag name is one of: "caption", "col", "colgroup",
3736 "tbody", "tfoot", "thead", or an end tag whose tag name is "table" */
3737 } elseif (($token['type'] === HTML5::STARTTAG && in_array(
3738 $token['name'],
3739 array('caption', 'col', 'colgroup', 'tbody', 'tfoor', 'thead')
3740 )) ||
3741 ($token['type'] === HTML5::STARTTAG && $token['name'] === 'table')
3742 ) {
3743 /* If the stack of open elements does not have a tbody, thead, or
3744 tfoot element in table scope, this is a parse error. Ignore the
3745 token. (innerHTML case) */
3746 if (!$this->elementInScope(array('tbody', 'thead', 'tfoot'), true)) {
3747 // Ignore.
3748
3749 /* Otherwise: */
3750 } else {
3751 /* Clear the stack back to a table body context. */
3752 $this->clearStackToTableContext($clear);
3753
3754 /* Act as if an end tag with the same tag name as the current
3755 node ("tbody", "tfoot", or "thead") had been seen, then
3756 reprocess the current token. */
3757 $this->inTableBody(
3758 array(
3759 'name' => end($this->stack)->nodeName,
3760 'type' => HTML5::ENDTAG
3761 )
3762 );
3763
3764 return $this->mainPhase($token);
3765 }
3766
3767 /* An end tag whose tag name is one of: "body", "caption", "col",
3768 "colgroup", "html", "td", "th", "tr" */
3769 } elseif ($token['type'] === HTML5::ENDTAG && in_array(
3770 $token['name'],
3771 array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th', 'tr')
3772 )
3773 ) {
3774 /* Parse error. Ignore the token. */
3775
3776 /* Anything else */
3777 } else {
3778 /* Process the token as if the insertion mode was "in table". */
3779 $this->inTable($token);
3780 }
3781 }

References clearStackToTableContext(), elementInScope(), HTML5\ENDTAG, IN_ROW, IN_TABLE, inRow(), insertElement(), inTable(), inTableBody(), mainPhase(), and HTML5\STARTTAG.

Referenced by inTable(), inTableBody(), and mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mainPhase()

HTML5TreeConstructer::mainPhase (   $token)
private

Definition at line 1835 of file PH5P.php.

1836 {
1837 /* Tokens in the main phase must be handled as follows: */
1838
1839 /* A DOCTYPE token */
1840 if ($token['type'] === HTML5::DOCTYPE) {
1841 // Parse error. Ignore the token.
1842
1843 /* A start tag token with the tag name "html" */
1844 } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'html') {
1845 /* If this start tag token was not the first start tag token, then
1846 it is a parse error. */
1847
1848 /* For each attribute on the token, check to see if the attribute
1849 is already present on the top element of the stack of open elements.
1850 If it is not, add the attribute and its corresponding value to that
1851 element. */
1852 foreach ($token['attr'] as $attr) {
1853 if (!$this->stack[0]->hasAttribute($attr['name'])) {
1854 $this->stack[0]->setAttribute($attr['name'], $attr['value']);
1855 }
1856 }
1857
1858 /* An end-of-file token */
1859 } elseif ($token['type'] === HTML5::EOF) {
1860 /* Generate implied end tags. */
1861 $this->generateImpliedEndTags();
1862
1863 /* Anything else. */
1864 } else {
1865 /* Depends on the insertion mode: */
1866 switch ($this->mode) {
1867 case self::BEFOR_HEAD:
1868 return $this->beforeHead($token);
1869 break;
1870 case self::IN_HEAD:
1871 return $this->inHead($token);
1872 break;
1873 case self::AFTER_HEAD:
1874 return $this->afterHead($token);
1875 break;
1876 case self::IN_BODY:
1877 return $this->inBody($token);
1878 break;
1879 case self::IN_TABLE:
1880 return $this->inTable($token);
1881 break;
1882 case self::IN_CAPTION:
1883 return $this->inCaption($token);
1884 break;
1885 case self::IN_CGROUP:
1886 return $this->inColumnGroup($token);
1887 break;
1888 case self::IN_TBODY:
1889 return $this->inTableBody($token);
1890 break;
1891 case self::IN_ROW:
1892 return $this->inRow($token);
1893 break;
1894 case self::IN_CELL:
1895 return $this->inCell($token);
1896 break;
1897 case self::IN_SELECT:
1898 return $this->inSelect($token);
1899 break;
1900 case self::AFTER_BODY:
1901 return $this->afterBody($token);
1902 break;
1903 case self::IN_FRAME:
1904 return $this->inFrameset($token);
1905 break;
1906 case self::AFTR_FRAME:
1907 return $this->afterFrameset($token);
1908 break;
1909 case self::END_PHASE:
1910 return $this->trailingEndPhase($token);
1911 break;
1912 }
1913 }
1914 }
inFrameset($token)
Definition: PH5P.php:4242
afterFrameset($token)
Definition: PH5P.php:4311
const DOCTYPE
Definition: PH5P.php:454

References AFTER_BODY, AFTER_HEAD, afterBody(), afterFrameset(), afterHead(), AFTR_FRAME, BEFOR_HEAD, beforeHead(), HTML5\DOCTYPE, END_PHASE, HTML5\EOF, generateImpliedEndTags(), IN_BODY, IN_CAPTION, IN_CELL, IN_CGROUP, IN_FRAME, IN_HEAD, IN_ROW, IN_SELECT, IN_TABLE, IN_TBODY, inBody(), inCaption(), inCell(), inColumnGroup(), inFrameset(), inHead(), inRow(), inSelect(), inTable(), inTableBody(), HTML5\STARTTAG, and trailingEndPhase().

Referenced by emitToken(), inSelect(), inTable(), inTableBody(), rootElementPhase(), and trailingEndPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reconstructActiveFormattingElements()

HTML5TreeConstructer::reconstructActiveFormattingElements ( )
private

Definition at line 4525 of file PH5P.php.

4526 {
4527 /* 1. If there are no entries in the list of active formatting elements,
4528 then there is nothing to reconstruct; stop this algorithm. */
4529 $formatting_elements = count($this->a_formatting);
4530
4531 if ($formatting_elements === 0) {
4532 return false;
4533 }
4534
4535 /* 3. Let entry be the last (most recently added) element in the list
4536 of active formatting elements. */
4537 $entry = end($this->a_formatting);
4538
4539 /* 2. If the last (most recently added) entry in the list of active
4540 formatting elements is a marker, or if it is an element that is in the
4541 stack of open elements, then there is nothing to reconstruct; stop this
4542 algorithm. */
4543 if ($entry === self::MARKER || in_array($entry, $this->stack, true)) {
4544 return false;
4545 }
4546
4547 for ($a = $formatting_elements - 1; $a >= 0; true) {
4548 /* 4. If there are no entries before entry in the list of active
4549 formatting elements, then jump to step 8. */
4550 if ($a === 0) {
4551 $step_seven = false;
4552 break;
4553 }
4554
4555 /* 5. Let entry be the entry one earlier than entry in the list of
4556 active formatting elements. */
4557 $a--;
4558 $entry = $this->a_formatting[$a];
4559
4560 /* 6. If entry is neither a marker nor an element that is also in
4561 thetack of open elements, go to step 4. */
4562 if ($entry === self::MARKER || in_array($entry, $this->stack, true)) {
4563 break;
4564 }
4565 }
4566
4567 while (true) {
4568 /* 7. Let entry be the element one later than entry in the list of
4569 active formatting elements. */
4570 if (isset($step_seven) && $step_seven === true) {
4571 $a++;
4572 $entry = $this->a_formatting[$a];
4573 }
4574
4575 /* 8. Perform a shallow clone of the element entry to obtain clone. */
4576 $clone = $entry->cloneNode();
4577
4578 /* 9. Append clone to the current node and push it onto the stack
4579 of open elements so that it is the new current node. */
4580 end($this->stack)->appendChild($clone);
4581 $this->stack[] = $clone;
4582
4583 /* 10. Replace the entry for entry in the list with an entry for
4584 clone. */
4585 $this->a_formatting[$a] = $clone;
4586
4587 /* 11. If the entry for clone in the list of active formatting
4588 elements is not the last entry in the list, return to step 7. */
4589 if (end($this->a_formatting) !== $clone) {
4590 $step_seven = true;
4591 } else {
4592 break;
4593 }
4594 }
4595 }

Referenced by inBody().

+ Here is the caller graph for this function:

◆ resetInsertionMode()

HTML5TreeConstructer::resetInsertionMode ( )
private

Definition at line 4666 of file PH5P.php.

4667 {
4668 /* 1. Let last be false. */
4669 $last = false;
4670 $leng = count($this->stack);
4671
4672 for ($n = $leng - 1; $n >= 0; $n--) {
4673 /* 2. Let node be the last node in the stack of open elements. */
4674 $node = $this->stack[$n];
4675
4676 /* 3. If node is the first node in the stack of open elements, then
4677 set last to true. If the element whose innerHTML attribute is being
4678 set is neither a td element nor a th element, then set node to the
4679 element whose innerHTML attribute is being set. (innerHTML case) */
4680 if ($this->stack[0]->isSameNode($node)) {
4681 $last = true;
4682 }
4683
4684 /* 4. If node is a select element, then switch the insertion mode to
4685 "in select" and abort these steps. (innerHTML case) */
4686 if ($node->nodeName === 'select') {
4687 $this->mode = self::IN_SELECT;
4688 break;
4689
4690 /* 5. If node is a td or th element, then switch the insertion mode
4691 to "in cell" and abort these steps. */
4692 } elseif ($node->nodeName === 'td' || $node->nodeName === 'th') {
4693 $this->mode = self::IN_CELL;
4694 break;
4695
4696 /* 6. If node is a tr element, then switch the insertion mode to
4697 "in row" and abort these steps. */
4698 } elseif ($node->nodeName === 'tr') {
4699 $this->mode = self::IN_ROW;
4700 break;
4701
4702 /* 7. If node is a tbody, thead, or tfoot element, then switch the
4703 insertion mode to "in table body" and abort these steps. */
4704 } elseif (in_array($node->nodeName, array('tbody', 'thead', 'tfoot'))) {
4705 $this->mode = self::IN_TBODY;
4706 break;
4707
4708 /* 8. If node is a caption element, then switch the insertion mode
4709 to "in caption" and abort these steps. */
4710 } elseif ($node->nodeName === 'caption') {
4711 $this->mode = self::IN_CAPTION;
4712 break;
4713
4714 /* 9. If node is a colgroup element, then switch the insertion mode
4715 to "in column group" and abort these steps. (innerHTML case) */
4716 } elseif ($node->nodeName === 'colgroup') {
4717 $this->mode = self::IN_CGROUP;
4718 break;
4719
4720 /* 10. If node is a table element, then switch the insertion mode
4721 to "in table" and abort these steps. */
4722 } elseif ($node->nodeName === 'table') {
4723 $this->mode = self::IN_TABLE;
4724 break;
4725
4726 /* 11. If node is a head element, then switch the insertion mode
4727 to "in body" ("in body"! not "in head"!) and abort these steps.
4728 (innerHTML case) */
4729 } elseif ($node->nodeName === 'head') {
4730 $this->mode = self::IN_BODY;
4731 break;
4732
4733 /* 12. If node is a body element, then switch the insertion mode to
4734 "in body" and abort these steps. */
4735 } elseif ($node->nodeName === 'body') {
4736 $this->mode = self::IN_BODY;
4737 break;
4738
4739 /* 13. If node is a frameset element, then switch the insertion
4740 mode to "in frameset" and abort these steps. (innerHTML case) */
4741 } elseif ($node->nodeName === 'frameset') {
4742 $this->mode = self::IN_FRAME;
4743 break;
4744
4745 /* 14. If node is an html element, then: if the head element
4746 pointer is null, switch the insertion mode to "before head",
4747 otherwise, switch the insertion mode to "after head". In either
4748 case, abort these steps. (innerHTML case) */
4749 } elseif ($node->nodeName === 'html') {
4750 $this->mode = ($this->head_pointer === null)
4751 ? self::BEFOR_HEAD
4752 : self::AFTER_HEAD;
4753
4754 break;
4755
4756 /* 15. If last is true, then set the insertion mode to "in body"
4757 and abort these steps. (innerHTML case) */
4758 } elseif ($last) {
4759 $this->mode = self::IN_BODY;
4760 break;
4761 }
4762 }
4763 }

References $n, IN_BODY, IN_CAPTION, IN_CELL, IN_CGROUP, IN_FRAME, IN_ROW, IN_SELECT, IN_TABLE, and IN_TBODY.

Referenced by inSelect(), and inTable().

+ Here is the caller graph for this function:

◆ rootElementPhase()

HTML5TreeConstructer::rootElementPhase (   $token)
private

Definition at line 1785 of file PH5P.php.

1786 {
1787 /* After the initial phase, as each token is emitted from the tokenisation
1788 stage, it must be processed as described in this section. */
1789
1790 /* A DOCTYPE token */
1791 if ($token['type'] === HTML5::DOCTYPE) {
1792 // Parse error. Ignore the token.
1793
1794 /* A comment token */
1795 } elseif ($token['type'] === HTML5::COMMENT) {
1796 /* Append a Comment node to the Document object with the data
1797 attribute set to the data given in the comment token. */
1798 $comment = $this->dom->createComment($token['data']);
1799 $this->dom->appendChild($comment);
1800
1801 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
1802 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
1803 or U+0020 SPACE */
1804 } elseif ($token['type'] === HTML5::CHARACTR &&
1805 preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
1806 ) {
1807 /* Append that character to the Document node. */
1808 $text = $this->dom->createTextNode($token['data']);
1809 $this->dom->appendChild($text);
1810
1811 /* A character token that is not one of U+0009 CHARACTER TABULATION,
1812 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED
1813 (FF), or U+0020 SPACE
1814 A start tag token
1815 An end tag token
1816 An end-of-file token */
1817 } elseif (($token['type'] === HTML5::CHARACTR &&
1818 !preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) ||
1819 $token['type'] === HTML5::STARTTAG ||
1820 $token['type'] === HTML5::ENDTAG ||
1821 $token['type'] === HTML5::EOF
1822 ) {
1823 /* Create an HTMLElement node with the tag name html, in the HTML
1824 namespace. Append it to the Document object. Switch to the main
1825 phase and reprocess the current token. */
1826 $html = $this->dom->createElement('html');
1827 $this->dom->appendChild($html);
1828 $this->stack[] = $html;
1829
1830 $this->phase = self::MAIN_PHASE;
1831 return $this->mainPhase($token);
1832 }
1833 }
$html
Definition: example_001.php:87

References $comment, $html, $text, HTML5\CHARACTR, HTML5\COMMENT, HTML5\DOCTYPE, HTML5\ENDTAG, HTML5\EOF, MAIN_PHASE, mainPhase(), and HTML5\STARTTAG.

Referenced by emitToken(), and initPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ save()

HTML5TreeConstructer::save ( )

Definition at line 4783 of file PH5P.php.

4784 {
4785 return $this->dom;
4786 }

References $dom.

◆ trailingEndPhase()

HTML5TreeConstructer::trailingEndPhase (   $token)
private

Definition at line 4350 of file PH5P.php.

4351 {
4352 /* After the main phase, as each token is emitted from the tokenisation
4353 stage, it must be processed as described in this section. */
4354
4355 /* A DOCTYPE token */
4356 if ($token['type'] === HTML5::DOCTYPE) {
4357 // Parse error. Ignore the token.
4358
4359 /* A comment token */
4360 } elseif ($token['type'] === HTML5::COMMENT) {
4361 /* Append a Comment node to the Document object with the data
4362 attribute set to the data given in the comment token. */
4363 $comment = $this->dom->createComment($token['data']);
4364 $this->dom->appendChild($comment);
4365
4366 /* A character token that is one of one of U+0009 CHARACTER TABULATION,
4367 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
4368 or U+0020 SPACE */
4369 } elseif ($token['type'] === HTML5::CHARACTR &&
4370 preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
4371 ) {
4372 /* Process the token as it would be processed in the main phase. */
4373 $this->mainPhase($token);
4374
4375 /* A character token that is not one of U+0009 CHARACTER TABULATION,
4376 U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
4377 or U+0020 SPACE. Or a start tag token. Or an end tag token. */
4378 } elseif (($token['type'] === HTML5::CHARACTR &&
4379 preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) ||
4380 $token['type'] === HTML5::STARTTAG || $token['type'] === HTML5::ENDTAG
4381 ) {
4382 /* Parse error. Switch back to the main phase and reprocess the
4383 token. */
4384 $this->phase = self::MAIN_PHASE;
4385 return $this->mainPhase($token);
4386
4387 /* An end-of-file token */
4388 } elseif ($token['type'] === HTML5::EOF) {
4389 /* OMG DONE!! */
4390 }
4391 }

References $comment, HTML5\CHARACTR, HTML5\COMMENT, HTML5\DOCTYPE, HTML5\ENDTAG, HTML5\EOF, MAIN_PHASE, mainPhase(), and HTML5\STARTTAG.

Referenced by emitToken(), and mainPhase().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Field Documentation

◆ $a_formatting

HTML5TreeConstructer::$a_formatting = array()
private

Definition at line 1584 of file PH5P.php.

◆ $dom

HTML5TreeConstructer::$dom
private

Definition at line 1582 of file PH5P.php.

Referenced by save().

◆ $form_pointer

HTML5TreeConstructer::$form_pointer = null
private

Definition at line 1587 of file PH5P.php.

◆ $formatting

HTML5TreeConstructer::$formatting
private
Initial value:
= array(
'a',
'b',
'big',
'em',
'font',
'i',
'nobr',
's',
'small',
'strike',
'strong',
'tt',
'u'
)

Definition at line 1590 of file PH5P.php.

◆ $foster_parent

HTML5TreeConstructer::$foster_parent = null
private

Definition at line 1583 of file PH5P.php.

◆ $head_pointer

HTML5TreeConstructer::$head_pointer = null
private

Definition at line 1586 of file PH5P.php.

◆ $mode

HTML5TreeConstructer::$mode
private

Definition at line 1581 of file PH5P.php.

◆ $phase

HTML5TreeConstructer::$phase
private

Definition at line 1580 of file PH5P.php.

◆ $scoping

HTML5TreeConstructer::$scoping = array('button', 'caption', 'html', 'marquee', 'object', 'table', 'td', 'th')
private

Definition at line 1589 of file PH5P.php.

◆ $special

HTML5TreeConstructer::$special
private

Definition at line 1605 of file PH5P.php.

◆ $stack

HTML5TreeConstructer::$stack = array()

Definition at line 1578 of file PH5P.php.

◆ AFTER_BODY

const HTML5TreeConstructer::AFTER_BODY = 11

Definition at line 1687 of file PH5P.php.

Referenced by inBody(), and mainPhase().

◆ AFTER_HEAD

const HTML5TreeConstructer::AFTER_HEAD = 2

Definition at line 1678 of file PH5P.php.

Referenced by inHead(), and mainPhase().

◆ AFTR_FRAME

const HTML5TreeConstructer::AFTR_FRAME = 13

Definition at line 1689 of file PH5P.php.

Referenced by inFrameset(), and mainPhase().

◆ BEFOR_HEAD

const HTML5TreeConstructer::BEFOR_HEAD = 0

Definition at line 1676 of file PH5P.php.

Referenced by __construct(), and mainPhase().

◆ END_PHASE

const HTML5TreeConstructer::END_PHASE = 3

Definition at line 1673 of file PH5P.php.

Referenced by afterBody(), afterFrameset(), emitToken(), and mainPhase().

◆ FORMATTING

const HTML5TreeConstructer::FORMATTING = 2

Definition at line 1694 of file PH5P.php.

Referenced by getElementCategory().

◆ IN_BODY

const HTML5TreeConstructer::IN_BODY = 3

Definition at line 1679 of file PH5P.php.

Referenced by afterBody(), afterHead(), mainPhase(), and resetInsertionMode().

◆ IN_CAPTION

const HTML5TreeConstructer::IN_CAPTION = 5

Definition at line 1681 of file PH5P.php.

Referenced by inTable(), mainPhase(), and resetInsertionMode().

◆ IN_CELL

const HTML5TreeConstructer::IN_CELL = 9

Definition at line 1685 of file PH5P.php.

Referenced by inRow(), mainPhase(), and resetInsertionMode().

◆ IN_CGROUP

const HTML5TreeConstructer::IN_CGROUP = 6

Definition at line 1682 of file PH5P.php.

Referenced by inTable(), mainPhase(), and resetInsertionMode().

◆ IN_FRAME

const HTML5TreeConstructer::IN_FRAME = 12

Definition at line 1688 of file PH5P.php.

Referenced by afterHead(), mainPhase(), and resetInsertionMode().

◆ IN_HEAD

const HTML5TreeConstructer::IN_HEAD = 1

Definition at line 1677 of file PH5P.php.

Referenced by afterHead(), beforeHead(), and mainPhase().

◆ IN_ROW

const HTML5TreeConstructer::IN_ROW = 8

Definition at line 1684 of file PH5P.php.

Referenced by inCell(), inTableBody(), mainPhase(), and resetInsertionMode().

◆ IN_SELECT

const HTML5TreeConstructer::IN_SELECT = 10

Definition at line 1686 of file PH5P.php.

Referenced by inBody(), mainPhase(), and resetInsertionMode().

◆ IN_TABLE

const HTML5TreeConstructer::IN_TABLE = 4

Definition at line 1680 of file PH5P.php.

Referenced by inBody(), inCaption(), inColumnGroup(), inTableBody(), mainPhase(), and resetInsertionMode().

◆ IN_TBODY

const HTML5TreeConstructer::IN_TBODY = 7

Definition at line 1683 of file PH5P.php.

Referenced by inRow(), inTable(), mainPhase(), and resetInsertionMode().

◆ INIT_PHASE

const HTML5TreeConstructer::INIT_PHASE = 0

Definition at line 1670 of file PH5P.php.

Referenced by __construct(), and emitToken().

◆ MAIN_PHASE

const HTML5TreeConstructer::MAIN_PHASE = 2

Definition at line 1672 of file PH5P.php.

Referenced by emitToken(), rootElementPhase(), and trailingEndPhase().

◆ MARKER

const HTML5TreeConstructer::MARKER = 0

Definition at line 1697 of file PH5P.php.

Referenced by inBody(), inRow(), and inTable().

◆ PHRASING

const HTML5TreeConstructer::PHRASING = 3

Definition at line 1695 of file PH5P.php.

Referenced by getElementCategory().

◆ ROOT_PHASE

const HTML5TreeConstructer::ROOT_PHASE = 1

Definition at line 1671 of file PH5P.php.

Referenced by emitToken(), and initPhase().

◆ SCOPING

const HTML5TreeConstructer::SCOPING = 1

Definition at line 1693 of file PH5P.php.

Referenced by getElementCategory().

◆ SPECIAL

const HTML5TreeConstructer::SPECIAL = 0

Definition at line 1692 of file PH5P.php.

Referenced by getElementCategory().


The documentation for this class was generated from the following file: