ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5
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  }

Member Function Documentation

◆ afterBody()

HTML5TreeConstructer::afterBody (   $token)
private

Definition at line 4201 of file PH5P.php.

References $comment, HTML5\CHARACTR, HTML5\COMMENT, and HTML5\ENDTAG.

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  }
const COMMENT
Definition: PH5P.php:457
$comment
Definition: buildRTE.php:83
const CHARACTR
Definition: PH5P.php:458
const ENDTAG
Definition: PH5P.php:456

◆ afterFrameset()

HTML5TreeConstructer::afterFrameset (   $token)
private

Definition at line 4311 of file PH5P.php.

References HTML5\CHARACTR, HTML5\COMMENT, HTML5\ENDTAG, and HTML5\STARTTAG.

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  }
const COMMENT
Definition: PH5P.php:457
insertComment($data)
Definition: PH5P.php:4428
const CHARACTR
Definition: PH5P.php:458
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455

◆ afterHead()

HTML5TreeConstructer::afterHead (   $token)
private

Definition at line 2112 of file PH5P.php.

References HTML5\CHARACTR, HTML5\COMMENT, and HTML5\STARTTAG.

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  }
const COMMENT
Definition: PH5P.php:457
afterHead($token)
Definition: PH5P.php:2112
insertElement($token, $append=true, $check=false)
Definition: PH5P.php:4393
insertComment($data)
Definition: PH5P.php:4428
const CHARACTR
Definition: PH5P.php:458
const STARTTAG
Definition: PH5P.php:455

◆ appendToRealParent()

HTML5TreeConstructer::appendToRealParent (   $node)
private

Definition at line 4434 of file PH5P.php.

References $n.

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

◆ beforeHead()

HTML5TreeConstructer::beforeHead (   $token)
private

Definition at line 1916 of file PH5P.php.

References HTML5\CHARACTR, HTML5\COMMENT, HTML5\ENDTAG, and HTML5\STARTTAG.

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  }
const COMMENT
Definition: PH5P.php:457
beforeHead($token)
Definition: PH5P.php:1916
insertElement($token, $append=true, $check=false)
Definition: PH5P.php:4393
insertComment($data)
Definition: PH5P.php:4428
const CHARACTR
Definition: PH5P.php:458
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455

◆ 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  }

◆ 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  }

◆ closeCell()

HTML5TreeConstructer::closeCell ( )
private

Definition at line 4765 of file PH5P.php.

References HTML5\ENDTAG.

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
const ENDTAG
Definition: PH5P.php:456

◆ elementInScope()

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

Definition at line 4465 of file PH5P.php.

References $n.

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  }
elementInScope($el, $table=false)
Definition: PH5P.php:4465
$n
Definition: RandomTest.php:80

◆ 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
initPhase($token)
Definition: PH5P.php:1730
trailingEndPhase($token)
Definition: PH5P.php:4350
mainPhase($token)
Definition: PH5P.php:1835

◆ generateImpliedEndTags()

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

Definition at line 4619 of file PH5P.php.

References $exclude.

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

◆ 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  }

◆ inBody()

HTML5TreeConstructer::inBody (   $token)
private

Definition at line 2175 of file PH5P.php.

References $n, $x, HTML5\CDATA, HTML5\CHARACTR, HTML5\COMMENT, HTML5\ENDTAG, HTML5\PLAINTEXT, HTML5\RCDATA, and HTML5\STARTTAG.

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  }
emitToken($token)
Definition: PH5P.php:1712
const RCDATA
Definition: PH5P.php:450
getElementCategory($node)
Definition: PH5P.php:4634
const COMMENT
Definition: PH5P.php:457
$x
Definition: example_009.php:98
afterBody($token)
Definition: PH5P.php:4201
const CDATA
Definition: PH5P.php:451
const PLAINTEXT
Definition: PH5P.php:452
generateImpliedEndTags($exclude=array())
Definition: PH5P.php:4619
elementInScope($el, $table=false)
Definition: PH5P.php:4465
$n
Definition: RandomTest.php:80
insertElement($token, $append=true, $check=false)
Definition: PH5P.php:4393
insertComment($data)
Definition: PH5P.php:4428
const CHARACTR
Definition: PH5P.php:458
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455
reconstructActiveFormattingElements()
Definition: PH5P.php:4525

◆ inCaption()

HTML5TreeConstructer::inCaption (   $token)
private

Definition at line 3527 of file PH5P.php.

References HTML5\ENDTAG, and HTML5\STARTTAG.

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  }
clearTheActiveFormattingElementsUpToTheLastMarker()
Definition: PH5P.php:4597
generateImpliedEndTags($exclude=array())
Definition: PH5P.php:4619
inCaption($token)
Definition: PH5P.php:3527
elementInScope($el, $table=false)
Definition: PH5P.php:4465
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455

◆ inCell()

HTML5TreeConstructer::inCell (   $token)
private

Definition at line 3881 of file PH5P.php.

References HTML5\ENDTAG, and HTML5\STARTTAG.

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  }
clearTheActiveFormattingElementsUpToTheLastMarker()
Definition: PH5P.php:4597
generateImpliedEndTags($exclude=array())
Definition: PH5P.php:4619
elementInScope($el, $table=false)
Definition: PH5P.php:4465
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455

◆ inColumnGroup()

HTML5TreeConstructer::inColumnGroup (   $token)
private

Definition at line 3622 of file PH5P.php.

References $comment, $text, HTML5\CHARACTR, HTML5\COMMENT, HTML5\ENDTAG, and HTML5\STARTTAG.

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  }
const COMMENT
Definition: PH5P.php:457
inColumnGroup($token)
Definition: PH5P.php:3622
insertElement($token, $append=true, $check=false)
Definition: PH5P.php:4393
$comment
Definition: buildRTE.php:83
const CHARACTR
Definition: PH5P.php:458
$text
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455

◆ inFrameset()

HTML5TreeConstructer::inFrameset (   $token)
private

Definition at line 4242 of file PH5P.php.

References HTML5\CHARACTR, HTML5\COMMENT, HTML5\ENDTAG, and HTML5\STARTTAG.

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  }
const COMMENT
Definition: PH5P.php:457
insertElement($token, $append=true, $check=false)
Definition: PH5P.php:4393
insertComment($data)
Definition: PH5P.php:4428
const CHARACTR
Definition: PH5P.php:458
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455

◆ inHead()

HTML5TreeConstructer::inHead (   $token)
private

Definition at line 1977 of file PH5P.php.

References HTML5\CDATA, HTML5\CHARACTR, HTML5\COMMENT, HTML5\ENDTAG, HTML5\PCDATA, HTML5\RCDATA, and HTML5\STARTTAG.

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 RCDATA
Definition: PH5P.php:450
const COMMENT
Definition: PH5P.php:457
const CDATA
Definition: PH5P.php:451
afterHead($token)
Definition: PH5P.php:2112
insertElement($token, $append=true, $check=false)
Definition: PH5P.php:4393
insertComment($data)
Definition: PH5P.php:4428
const CHARACTR
Definition: PH5P.php:458
const ENDTAG
Definition: PH5P.php:456
const PCDATA
Definition: PH5P.php:449
const STARTTAG
Definition: PH5P.php:455

◆ initPhase()

HTML5TreeConstructer::initPhase (   $token)
private

Definition at line 1730 of file PH5P.php.

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

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 COMMENT
Definition: PH5P.php:457
EOF()
Definition: PH5P.php:1565
rootElementPhase($token)
Definition: PH5P.php:1785
const CHARACTR
Definition: PH5P.php:458
$text
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455
+ Here is the call graph for this function:

◆ inRow()

HTML5TreeConstructer::inRow (   $token)
private

Definition at line 3783 of file PH5P.php.

References HTML5\ENDTAG, and HTML5\STARTTAG.

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
elementInScope($el, $table=false)
Definition: PH5P.php:4465
insertElement($token, $append=true, $check=false)
Definition: PH5P.php:4393
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455

◆ inSelect()

HTML5TreeConstructer::inSelect (   $token)
private

Definition at line 4020 of file PH5P.php.

References HTML5\CHARACTR, HTML5\COMMENT, HTML5\ENDTAG, and HTML5\STARTTAG.

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
const COMMENT
Definition: PH5P.php:457
elementInScope($el, $table=false)
Definition: PH5P.php:4465
insertElement($token, $append=true, $check=false)
Definition: PH5P.php:4393
insertComment($data)
Definition: PH5P.php:4428
const CHARACTR
Definition: PH5P.php:458
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455
mainPhase($token)
Definition: PH5P.php:1835

◆ insertComment()

HTML5TreeConstructer::insertComment (   $data)
private

Definition at line 4428 of file PH5P.php.

References $comment, and $data.

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

◆ 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  }
appendToRealParent($node)
Definition: PH5P.php:4434

◆ insertText()

HTML5TreeConstructer::insertText (   $data)
private

Definition at line 4422 of file PH5P.php.

References $data, and $text.

4423  {
4424  $text = $this->dom->createTextNode($data);
4425  $this->appendToRealParent($text);
4426  }
$data
appendToRealParent($node)
Definition: PH5P.php:4434
$text

◆ inTable()

HTML5TreeConstructer::inTable (   $token)
private

Definition at line 3315 of file PH5P.php.

References $comment, $n, $text, HTML5\CHARACTR, HTML5\COMMENT, HTML5\ENDTAG, and HTML5\STARTTAG.

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  }
const COMMENT
Definition: PH5P.php:457
generateImpliedEndTags($exclude=array())
Definition: PH5P.php:4619
clearStackToTableContext($elements)
Definition: PH5P.php:4648
inTableBody($token)
Definition: PH5P.php:3684
elementInScope($el, $table=false)
Definition: PH5P.php:4465
inColumnGroup($token)
Definition: PH5P.php:3622
$n
Definition: RandomTest.php:80
insertElement($token, $append=true, $check=false)
Definition: PH5P.php:4393
$comment
Definition: buildRTE.php:83
const CHARACTR
Definition: PH5P.php:458
$text
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455
mainPhase($token)
Definition: PH5P.php:1835

◆ inTableBody()

HTML5TreeConstructer::inTableBody (   $token)
private

Definition at line 3684 of file PH5P.php.

References HTML5\ENDTAG, and HTML5\STARTTAG.

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  }
clearStackToTableContext($elements)
Definition: PH5P.php:4648
inTableBody($token)
Definition: PH5P.php:3684
elementInScope($el, $table=false)
Definition: PH5P.php:4465
insertElement($token, $append=true, $check=false)
Definition: PH5P.php:4393
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455
mainPhase($token)
Definition: PH5P.php:1835

◆ mainPhase()

HTML5TreeConstructer::mainPhase (   $token)
private

Definition at line 1835 of file PH5P.php.

References HTML5\DOCTYPE, HTML5\EOF(), and HTML5\STARTTAG.

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  }
inSelect($token)
Definition: PH5P.php:4020
EOF()
Definition: PH5P.php:1565
afterBody($token)
Definition: PH5P.php:4201
generateImpliedEndTags($exclude=array())
Definition: PH5P.php:4619
beforeHead($token)
Definition: PH5P.php:1916
afterHead($token)
Definition: PH5P.php:2112
inCaption($token)
Definition: PH5P.php:3527
afterFrameset($token)
Definition: PH5P.php:4311
inFrameset($token)
Definition: PH5P.php:4242
inTableBody($token)
Definition: PH5P.php:3684
const DOCTYPE
Definition: PH5P.php:454
inColumnGroup($token)
Definition: PH5P.php:3622
trailingEndPhase($token)
Definition: PH5P.php:4350
const STARTTAG
Definition: PH5P.php:455
+ Here is the call 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  }

◆ resetInsertionMode()

HTML5TreeConstructer::resetInsertionMode ( )
private

Definition at line 4666 of file PH5P.php.

References $n.

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  }
$n
Definition: RandomTest.php:80

◆ rootElementPhase()

HTML5TreeConstructer::rootElementPhase (   $token)
private

Definition at line 1785 of file PH5P.php.

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

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  }
const COMMENT
Definition: PH5P.php:457
EOF()
Definition: PH5P.php:1565
const DOCTYPE
Definition: PH5P.php:454
$comment
Definition: buildRTE.php:83
const CHARACTR
Definition: PH5P.php:458
$text
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455
$html
Definition: example_001.php:87
mainPhase($token)
Definition: PH5P.php:1835
+ Here is the call graph for this function:

◆ save()

HTML5TreeConstructer::save ( )

Definition at line 4783 of file PH5P.php.

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

◆ trailingEndPhase()

HTML5TreeConstructer::trailingEndPhase (   $token)
private

Definition at line 4350 of file PH5P.php.

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

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  }
const COMMENT
Definition: PH5P.php:457
EOF()
Definition: PH5P.php:1565
const DOCTYPE
Definition: PH5P.php:454
$comment
Definition: buildRTE.php:83
const CHARACTR
Definition: PH5P.php:458
const ENDTAG
Definition: PH5P.php:456
const STARTTAG
Definition: PH5P.php:455
mainPhase($token)
Definition: PH5P.php:1835
+ Here is the call 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.

◆ $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.

◆ AFTER_HEAD

const HTML5TreeConstructer::AFTER_HEAD = 2

Definition at line 1678 of file PH5P.php.

◆ AFTR_FRAME

const HTML5TreeConstructer::AFTR_FRAME = 13

Definition at line 1689 of file PH5P.php.

◆ BEFOR_HEAD

const HTML5TreeConstructer::BEFOR_HEAD = 0

Definition at line 1676 of file PH5P.php.

◆ END_PHASE

const HTML5TreeConstructer::END_PHASE = 3

Definition at line 1673 of file PH5P.php.

◆ FORMATTING

const HTML5TreeConstructer::FORMATTING = 2

Definition at line 1694 of file PH5P.php.

◆ IN_BODY

const HTML5TreeConstructer::IN_BODY = 3

Definition at line 1679 of file PH5P.php.

◆ IN_CAPTION

const HTML5TreeConstructer::IN_CAPTION = 5

Definition at line 1681 of file PH5P.php.

◆ IN_CELL

const HTML5TreeConstructer::IN_CELL = 9

Definition at line 1685 of file PH5P.php.

◆ IN_CGROUP

const HTML5TreeConstructer::IN_CGROUP = 6

Definition at line 1682 of file PH5P.php.

◆ IN_FRAME

const HTML5TreeConstructer::IN_FRAME = 12

Definition at line 1688 of file PH5P.php.

◆ IN_HEAD

const HTML5TreeConstructer::IN_HEAD = 1

Definition at line 1677 of file PH5P.php.

◆ IN_ROW

const HTML5TreeConstructer::IN_ROW = 8

Definition at line 1684 of file PH5P.php.

◆ IN_SELECT

const HTML5TreeConstructer::IN_SELECT = 10

Definition at line 1686 of file PH5P.php.

◆ IN_TABLE

const HTML5TreeConstructer::IN_TABLE = 4

Definition at line 1680 of file PH5P.php.

◆ IN_TBODY

const HTML5TreeConstructer::IN_TBODY = 7

Definition at line 1683 of file PH5P.php.

◆ INIT_PHASE

const HTML5TreeConstructer::INIT_PHASE = 0

Definition at line 1670 of file PH5P.php.

◆ MAIN_PHASE

const HTML5TreeConstructer::MAIN_PHASE = 2

Definition at line 1672 of file PH5P.php.

◆ MARKER

const HTML5TreeConstructer::MARKER = 0

Definition at line 1697 of file PH5P.php.

◆ PHRASING

const HTML5TreeConstructer::PHRASING = 3

Definition at line 1695 of file PH5P.php.

◆ ROOT_PHASE

const HTML5TreeConstructer::ROOT_PHASE = 1

Definition at line 1671 of file PH5P.php.

◆ SCOPING

const HTML5TreeConstructer::SCOPING = 1

Definition at line 1693 of file PH5P.php.

◆ SPECIAL

const HTML5TreeConstructer::SPECIAL = 0

Definition at line 1692 of file PH5P.php.


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