23 $new_html = $this->
normalize($html, $config, $context);
24 $new_html = $this->
wrapHTML($new_html, $config, $context);
26 $parser =
new HTML5($new_html);
27 $doc = $parser->save();
28 }
catch (DOMException $e) {
31 $context->register(
'PH5PError', $e);
32 return $lexer->tokenizeHTML($html, $config, $context);
36 $doc->getElementsByTagName(
'html')->item(0)->
37 getElementsByTagName(
'body')->item(0)->
38 getElementsByTagName(
'div')->item(0)
80 private $escape =
false;
81 private $entities = array(
468 $this->content_model = self::PCDATA;
470 $this->state =
'data';
472 while ($this->state !== null) {
473 $this->{$this->state .
'State'}();
479 return $this->tree->save();
484 return ($this->char < $this->
EOF)
485 ? $this->data[$this->char]
491 if ($s + $l < $this->
EOF) {
493 return $this->data[$s];
495 return substr($this->data, $s, $l);
502 return preg_replace(
'#^([' . $char_class .
']+).*#s',
'\\1', substr($this->data, $start));
509 $char = $this->char();
511 if ($char ===
'&' && ($this->content_model === self::PCDATA || $this->content_model === self::RCDATA)) {
516 $this->state =
'entityData';
518 } elseif ($char ===
'-') {
525 if (($this->content_model === self::RCDATA || $this->content_model ===
526 self::CDATA) && $this->escape ===
false &&
527 $this->
char >= 3 && $this->character($this->
char - 4, 4) ===
'<!--' 529 $this->escape =
true;
536 'type' => self::CHARACTR,
542 } elseif ($char ===
'<' && ($this->content_model === self::PCDATA ||
543 (($this->content_model === self::RCDATA ||
544 $this->content_model === self::CDATA) && $this->escape ===
false))
554 $this->state =
'tagOpen';
557 } elseif ($char ===
'>') {
563 if (($this->content_model === self::RCDATA ||
564 $this->content_model === self::CDATA) && $this->escape ===
true &&
565 $this->character($this->
char, 3) ===
'-->' 567 $this->escape =
false;
574 'type' => self::CHARACTR,
579 } elseif ($this->
char === $this->
EOF) {
584 } elseif ($this->content_model === self::PLAINTEXT) {
590 'type' => self::CHARACTR,
591 'data' => substr($this->data, $this->
char)
602 $len = strcspn($this->data,
'<&', $this->
char);
603 $char = substr($this->data, $this->
char, $len);
604 $this->
char += $len - 1;
608 'type' => self::CHARACTR,
613 $this->state =
'data';
620 $entity = $this->entity();
624 $char = (!$entity) ?
'&' : $entity;
627 'type' => self::CHARACTR,
633 $this->state =
'data';
638 switch ($this->content_model) {
646 if ($this->character($this->
char + 1) ===
'/') {
648 $this->state =
'closeTagOpen';
653 'type' => self::CHARACTR,
658 $this->state =
'data';
666 $char = $this->char();
671 $this->state =
'markupDeclarationOpen';
673 } elseif ($char ===
'/') {
676 $this->state =
'closeTagOpen';
678 } elseif (preg_match(
'/^[A-Za-z]$/', $char)) {
684 $this->token = array(
685 'name' => strtolower($char),
686 'type' => self::STARTTAG,
690 $this->state =
'tagName';
692 } elseif ($char ===
'>') {
698 'type' => self::CHARACTR,
703 $this->state =
'data';
705 } elseif ($char ===
'?') {
708 $this->state =
'bogusComment';
716 'type' => self::CHARACTR,
722 $this->state =
'data';
730 $next_node = strtolower($this->characters(
'A-Za-z', $this->
char + 1));
731 $the_same = count($this->tree->stack) > 0 && $next_node === end($this->tree->stack)->nodeName;
733 if (($this->content_model === self::RCDATA || $this->content_model === self::CDATA) &&
734 (!$the_same || ($the_same && (!preg_match(
735 '/[\t\n\x0b\x0c >\/]/',
736 $this->character($this->
char + 1 + strlen($next_node))
737 ) || $this->
EOF === $this->
char)))
756 'type' => self::CHARACTR,
761 $this->state =
'data';
768 $char = $this->char();
770 if (preg_match(
'/^[A-Za-z]$/', $char)) {
776 $this->token = array(
777 'name' => strtolower($char),
778 'type' => self::ENDTAG
781 $this->state =
'tagName';
783 } elseif ($char ===
'>') {
786 $this->state =
'data';
788 } elseif ($this->
char === $this->
EOF) {
794 'type' => self::CHARACTR,
800 $this->state =
'data';
804 $this->state =
'bogusComment';
813 $char = $this->character($this->
char);
815 if (preg_match(
'/^[\t\n\x0b\x0c ]$/', $char)) {
822 $this->state =
'beforeAttributeName';
824 } elseif ($char ===
'>') {
827 $this->emitToken($this->token);
828 $this->state =
'data';
830 } elseif ($this->
char === $this->
EOF) {
834 $this->emitToken($this->token);
837 $this->state =
'data';
839 } elseif ($char ===
'/') {
843 $this->state =
'beforeAttributeName';
849 $this->token[
'name'] .= strtolower($char);
850 $this->state =
'tagName';
858 $char = $this->character($this->
char);
860 if (preg_match(
'/^[\t\n\x0b\x0c ]$/', $char)) {
867 $this->state =
'beforeAttributeName';
869 } elseif ($char ===
'>') {
872 $this->emitToken($this->token);
873 $this->state =
'data';
875 } elseif ($char ===
'/') {
879 $this->state =
'beforeAttributeName';
881 } elseif ($this->
char === $this->
EOF) {
885 $this->emitToken($this->token);
888 $this->state =
'data';
895 $this->token[
'attr'][] = array(
896 'name' => strtolower($char),
900 $this->state =
'attributeName';
908 $char = $this->character($this->
char);
910 if (preg_match(
'/^[\t\n\x0b\x0c ]$/', $char)) {
917 $this->state =
'afterAttributeName';
919 } elseif ($char ===
'=') {
922 $this->state =
'beforeAttributeValue';
924 } elseif ($char ===
'>') {
927 $this->emitToken($this->token);
928 $this->state =
'data';
930 } elseif ($char ===
'/' && $this->character($this->
char + 1) !==
'>') {
934 $this->state =
'beforeAttributeName';
936 } elseif ($this->
char === $this->
EOF) {
940 $this->emitToken($this->token);
943 $this->state =
'data';
949 $last = count($this->token[
'attr']) - 1;
950 $this->token[
'attr'][$last][
'name'] .= strtolower($char);
952 $this->state =
'attributeName';
960 $char = $this->character($this->
char);
962 if (preg_match(
'/^[\t\n\x0b\x0c ]$/', $char)) {
969 $this->state =
'afterAttributeName';
971 } elseif ($char ===
'=') {
974 $this->state =
'beforeAttributeValue';
976 } elseif ($char ===
'>') {
979 $this->emitToken($this->token);
980 $this->state =
'data';
982 } elseif ($char ===
'/' && $this->character($this->
char + 1) !==
'>') {
986 $this->state =
'beforeAttributeName';
988 } elseif ($this->
char === $this->
EOF) {
992 $this->emitToken($this->token);
995 $this->state =
'data';
1002 $this->token[
'attr'][] = array(
1003 'name' => strtolower($char),
1007 $this->state =
'attributeName';
1015 $char = $this->character($this->
char);
1017 if (preg_match(
'/^[\t\n\x0b\x0c ]$/', $char)) {
1024 $this->state =
'beforeAttributeValue';
1026 } elseif ($char ===
'"') {
1029 $this->state =
'attributeValueDoubleQuoted';
1031 } elseif ($char ===
'&') {
1036 $this->state =
'attributeValueUnquoted';
1038 } elseif ($char ===
'\'') {
1041 $this->state =
'attributeValueSingleQuoted';
1043 } elseif ($char ===
'>') {
1046 $this->emitToken($this->token);
1047 $this->state =
'data';
1053 $last = count($this->token[
'attr']) - 1;
1054 $this->token[
'attr'][$last][
'value'] .= $char;
1056 $this->state =
'attributeValueUnquoted';
1064 $char = $this->character($this->
char);
1066 if ($char ===
'"') {
1069 $this->state =
'beforeAttributeName';
1071 } elseif ($char ===
'&') {
1074 $this->entityInAttributeValueState(
'double');
1076 } elseif ($this->
char === $this->
EOF) {
1080 $this->emitToken($this->token);
1083 $this->state =
'data';
1089 $last = count($this->token[
'attr']) - 1;
1090 $this->token[
'attr'][$last][
'value'] .= $char;
1092 $this->state =
'attributeValueDoubleQuoted';
1100 $char = $this->character($this->
char);
1102 if ($char ===
'\'') {
1105 $this->state =
'beforeAttributeName';
1107 } elseif ($char ===
'&') {
1110 $this->entityInAttributeValueState(
'single');
1112 } elseif ($this->
char === $this->
EOF) {
1116 $this->emitToken($this->token);
1119 $this->state =
'data';
1125 $last = count($this->token[
'attr']) - 1;
1126 $this->token[
'attr'][$last][
'value'] .= $char;
1128 $this->state =
'attributeValueSingleQuoted';
1136 $char = $this->character($this->
char);
1138 if (preg_match(
'/^[\t\n\x0b\x0c ]$/', $char)) {
1145 $this->state =
'beforeAttributeName';
1147 } elseif ($char ===
'&') {
1150 $this->entityInAttributeValueState();
1152 } elseif ($char ===
'>') {
1155 $this->emitToken($this->token);
1156 $this->state =
'data';
1162 $last = count($this->token[
'attr']) - 1;
1163 $this->token[
'attr'][$last][
'value'] .= $char;
1165 $this->state =
'attributeValueUnquoted';
1172 $entity = $this->entity();
1181 $last = count($this->token[
'attr']) - 1;
1182 $this->token[
'attr'][$last][
'value'] .= $char;
1195 $data = $this->characters(
'^>', $this->
char);
1199 'type' => self::COMMENT
1203 $this->
char += strlen(
$data);
1206 $this->state =
'data';
1209 if ($this->
char === $this->
EOF) {
1210 $this->
char = $this->
EOF - 1;
1219 if ($this->character($this->
char + 1, 2) ===
'--') {
1221 $this->state =
'comment';
1222 $this->token = array(
1224 'type' => self::COMMENT
1230 } elseif (strtolower($this->character($this->
char + 1, 7)) ===
'doctype') {
1232 $this->state =
'doctype';
1239 $this->state =
'bogusComment';
1247 $char = $this->char();
1250 if ($char ===
'-') {
1252 $this->state =
'commentDash';
1255 } elseif ($this->
char === $this->
EOF) {
1258 $this->emitToken($this->token);
1260 $this->state =
'data';
1266 $this->token[
'data'] .= $char;
1274 $char = $this->char();
1277 if ($char ===
'-') {
1279 $this->state =
'commentEnd';
1282 } elseif ($this->
char === $this->
EOF) {
1285 $this->emitToken($this->token);
1287 $this->state =
'data';
1293 $this->token[
'data'] .=
'-' . $char;
1294 $this->state =
'comment';
1302 $char = $this->char();
1304 if ($char ===
'>') {
1305 $this->emitToken($this->token);
1306 $this->state =
'data';
1308 } elseif ($char ===
'-') {
1309 $this->token[
'data'] .=
'-';
1311 } elseif ($this->
char === $this->
EOF) {
1312 $this->emitToken($this->token);
1314 $this->state =
'data';
1317 $this->token[
'data'] .=
'--' . $char;
1318 $this->state =
'comment';
1326 $char = $this->char();
1328 if (preg_match(
'/^[\t\n\x0b\x0c ]$/', $char)) {
1329 $this->state =
'beforeDoctypeName';
1333 $this->state =
'beforeDoctypeName';
1341 $char = $this->char();
1343 if (preg_match(
'/^[\t\n\x0b\x0c ]$/', $char)) {
1346 } elseif (preg_match(
'/^[a-z]$/', $char)) {
1347 $this->token = array(
1348 'name' => strtoupper($char),
1349 'type' => self::DOCTYPE,
1353 $this->state =
'doctypeName';
1355 } elseif ($char ===
'>') {
1359 'type' => self::DOCTYPE,
1364 $this->state =
'data';
1366 } elseif ($this->
char === $this->
EOF) {
1370 'type' => self::DOCTYPE,
1376 $this->state =
'data';
1379 $this->token = array(
1381 'type' => self::DOCTYPE,
1385 $this->state =
'doctypeName';
1393 $char = $this->char();
1395 if (preg_match(
'/^[\t\n\x0b\x0c ]$/', $char)) {
1396 $this->state =
'AfterDoctypeName';
1398 } elseif ($char ===
'>') {
1399 $this->emitToken($this->token);
1400 $this->state =
'data';
1402 } elseif (preg_match(
'/^[a-z]$/', $char)) {
1403 $this->token[
'name'] .= strtoupper($char);
1405 } elseif ($this->
char === $this->
EOF) {
1406 $this->emitToken($this->token);
1408 $this->state =
'data';
1411 $this->token[
'name'] .= $char;
1414 $this->token[
'error'] = ($this->token[
'name'] ===
'HTML')
1423 $char = $this->char();
1425 if (preg_match(
'/^[\t\n\x0b\x0c ]$/', $char)) {
1428 } elseif ($char ===
'>') {
1429 $this->emitToken($this->token);
1430 $this->state =
'data';
1432 } elseif ($this->
char === $this->
EOF) {
1433 $this->emitToken($this->token);
1435 $this->state =
'data';
1438 $this->token[
'error'] =
true;
1439 $this->state =
'bogusDoctype';
1447 $char = $this->char();
1449 if ($char ===
'>') {
1450 $this->emitToken($this->token);
1451 $this->state =
'data';
1453 } elseif ($this->
char === $this->
EOF) {
1454 $this->emitToken($this->token);
1456 $this->state =
'data';
1465 $start = $this->char;
1473 switch ($this->character($this->
char + 1)) {
1479 switch ($this->character($this->
char + 1)) {
1491 $char_class =
'0-9A-Fa-f';
1500 $char_class =
'0-9';
1507 $e_name = $this->characters($char_class, $this->
char + $char + 1);
1508 $entity = $this->character($start, $this->
char);
1509 $cond = strlen($e_name) > 0;
1519 $e_name = $this->characters(
'0-9A-Za-z;', $this->
char + 1);
1520 $len = strlen($e_name);
1522 for ($c = 1; $c <= $len; $c++) {
1523 $id = substr($e_name, 0, $c);
1526 if (in_array($id, $this->entities)) {
1527 if ($e_name[$c - 1] !==
';') {
1528 if ($c < $len && $e_name[$c] ==
';') {
1537 $cond = isset($entity);
1545 $this->
char = $start;
1551 return html_entity_decode(
'&' . $entity .
';', ENT_QUOTES,
'UTF-8');
1556 $emit = $this->tree->emitToken($token);
1558 if (is_int($emit)) {
1559 $this->content_model = $emit;
1561 } elseif ($token[
'type'] === self::ENDTAG) {
1562 $this->content_model = self::PCDATA;
1568 $this->state = null;
1569 $this->tree->emitToken(
1579 public $stack = array();
1584 private $foster_parent = null;
1585 private $a_formatting = array();
1587 private $head_pointer = null;
1588 private $form_pointer = null;
1590 private $scoping = array(
'button',
'caption',
'html',
'marquee',
'object',
'table',
'td',
'th');
1591 private $formatting = array(
1606 private $special = array(
1671 const INIT_PHASE = 0;
1672 const ROOT_PHASE = 1;
1673 const MAIN_PHASE = 2;
1674 const END_PHASE = 3;
1677 const BEFOR_HEAD = 0;
1679 const AFTER_HEAD = 2;
1682 const IN_CAPTION = 5;
1683 const IN_CGROUP = 6;
1687 const IN_SELECT = 10;
1688 const AFTER_BODY = 11;
1689 const IN_FRAME = 12;
1690 const AFTR_FRAME = 13;
1695 const FORMATTING = 2;
1702 $this->phase = self::INIT_PHASE;
1703 $this->mode = self::BEFOR_HEAD;
1706 $this->dom->encoding =
'UTF-8';
1707 $this->dom->preserveWhiteSpace =
true;
1708 $this->dom->substituteEntities =
true;
1709 $this->dom->strictErrorChecking =
false;
1715 switch ($this->phase) {
1716 case self::INIT_PHASE:
1717 return $this->initPhase($token);
1719 case self::ROOT_PHASE:
1720 return $this->rootElementPhase($token);
1722 case self::MAIN_PHASE:
1723 return $this->mainPhase($token);
1725 case self::END_PHASE :
1726 return $this->trailingEndPhase($token);
1744 if ((isset($token[
'error']) && $token[
'error']) ||
1750 !preg_match(
'/^[\t\n\x0b\x0c ]+$/', $token[
'data']))
1757 $this->phase = self::ROOT_PHASE;
1758 return $this->rootElementPhase($token);
1761 } elseif (isset($token[
'error']) && !$token[
'error']) {
1766 $doctype =
new DOMDocumentType(null, null,
'HTML');
1770 $this->phase = self::ROOT_PHASE;
1775 } elseif (isset($token[
'data']) && preg_match(
1776 '/^[\t\n\x0b\x0c ]+$/',
1781 $text = $this->dom->createTextNode($token[
'data']);
1782 $this->dom->appendChild($text);
1799 $comment = $this->dom->createComment($token[
'data']);
1806 preg_match(
'/^[\t\n\x0b\x0c ]+$/', $token[
'data'])
1809 $text = $this->dom->createTextNode($token[
'data']);
1810 $this->dom->appendChild($text);
1819 !preg_match(
'/^[\t\n\x0b\x0c ]+$/', $token[
'data'])) ||
1827 $html = $this->dom->createElement(
'html');
1828 $this->dom->appendChild($html);
1829 $this->stack[] = $html;
1831 $this->phase = self::MAIN_PHASE;
1832 return $this->mainPhase($token);
1845 } elseif ($token[
'type'] ===
HTML5::STARTTAG && $token[
'name'] ===
'html') {
1853 foreach ($token[
'attr'] as $attr) {
1854 if (!$this->stack[0]->hasAttribute($attr[
'name'])) {
1855 $this->stack[0]->setAttribute($attr[
'name'], $attr[
'value']);
1862 $this->generateImpliedEndTags();
1867 switch ($this->mode) {
1868 case self::BEFOR_HEAD:
1869 return $this->beforeHead($token);
1872 return $this->inHead($token);
1874 case self::AFTER_HEAD:
1875 return $this->afterHead($token);
1878 return $this->inBody($token);
1880 case self::IN_TABLE:
1881 return $this->inTable($token);
1883 case self::IN_CAPTION:
1884 return $this->inCaption($token);
1886 case self::IN_CGROUP:
1887 return $this->inColumnGroup($token);
1889 case self::IN_TBODY:
1890 return $this->inTableBody($token);
1893 return $this->inRow($token);
1896 return $this->inCell($token);
1898 case self::IN_SELECT:
1899 return $this->inSelect($token);
1901 case self::AFTER_BODY:
1902 return $this->afterBody($token);
1904 case self::IN_FRAME:
1905 return $this->inFrameset($token);
1907 case self::AFTR_FRAME:
1908 return $this->afterFrameset($token);
1910 case self::END_PHASE:
1911 return $this->trailingEndPhase($token);
1925 preg_match(
'/^[\t\n\x0b\x0c ]+$/', $token[
'data'])
1928 $this->insertText($token[
'data']);
1934 $this->insertComment($token[
'data']);
1937 } elseif ($token[
'type'] ===
HTML5::STARTTAG && $token[
'name'] ===
'head') {
1940 $element = $this->insertElement($token);
1943 $this->head_pointer = $element;
1946 $this->mode = self::IN_HEAD;
1954 ($token[
'type'] ===
HTML5::ENDTAG && $token[
'name'] ===
'html') ||
1956 '/^[\t\n\x0b\x0c ]$/',
1970 return $this->inHead($token);
1990 preg_match(
'/^[\t\n\x0b\x0c ]+$/', $token[
'data'])) || (
1992 end($this->stack)->nodeName,
1993 array(
'title',
'style',
'script')
1997 $this->insertText($token[
'data']);
2003 $this->insertComment($token[
'data']);
2006 in_array($token[
'name'], array(
'title',
'style',
'script'))
2008 array_pop($this->stack);
2012 } elseif ($token[
'type'] ===
HTML5::STARTTAG && $token[
'name'] ===
'title') {
2016 if ($this->head_pointer !== null) {
2017 $element = $this->insertElement($token,
false);
2018 $this->head_pointer->appendChild($element);
2021 $element = $this->insertElement($token);
2028 } elseif ($token[
'type'] ===
HTML5::STARTTAG && $token[
'name'] ===
'style') {
2032 if ($this->head_pointer !== null) {
2033 $element = $this->insertElement($token,
false);
2034 $this->head_pointer->appendChild($element);
2037 $this->insertElement($token);
2044 } elseif ($token[
'type'] ===
HTML5::STARTTAG && $token[
'name'] ===
'script') {
2046 $element = $this->insertElement($token,
false);
2047 $this->head_pointer->appendChild($element);
2055 array(
'base',
'link',
'meta')
2061 if ($this->head_pointer !== null) {
2062 $element = $this->insertElement($token,
false);
2063 $this->head_pointer->appendChild($element);
2064 array_pop($this->stack);
2067 $this->insertElement($token);
2071 } elseif ($token[
'type'] ===
HTML5::ENDTAG && $token[
'name'] ===
'head') {
2074 if ($this->head_pointer->isSameNode(end($this->stack))) {
2075 array_pop($this->stack);
2083 $this->mode = self::AFTER_HEAD;
2086 } elseif (($token[
'type'] ===
HTML5::STARTTAG && $token[
'name'] ===
'head') ||
2087 ($token[
'type'] ===
HTML5::ENDTAG && $token[
'name'] !==
'html')
2095 if ($this->head_pointer->isSameNode(end($this->stack))) {
2105 $this->mode = self::AFTER_HEAD;
2109 return $this->afterHead($token);
2121 preg_match(
'/^[\t\n\x0b\x0c ]+$/', $token[
'data'])
2124 $this->insertText($token[
'data']);
2130 $this->insertComment($token[
'data']);
2133 } elseif ($token[
'type'] ===
HTML5::STARTTAG && $token[
'name'] ===
'body') {
2135 $this->insertElement($token);
2138 $this->mode = self::IN_BODY;
2141 } elseif ($token[
'type'] ===
HTML5::STARTTAG && $token[
'name'] ===
'frameset') {
2143 $this->insertElement($token);
2146 $this->mode = self::IN_FRAME;
2152 array(
'base',
'link',
'meta',
'script',
'style',
'title')
2157 $this->mode = self::IN_HEAD;
2158 return $this->inHead($token);
2172 return $this->inBody($token);
2180 switch ($token[
'type']) {
2184 $this->reconstructActiveFormattingElements();
2187 $this->insertText($token[
'data']);
2194 $this->insertComment($token[
'data']);
2198 switch ($token[
'name']) {
2205 return $this->inHead($token);
2216 return $this->inHead($token);
2225 if (count($this->stack) === 1 || $this->stack[1]->nodeName !==
'body') {
2234 foreach ($token[
'attr'] as $attr) {
2235 if (!$this->stack[1]->hasAttribute($attr[
'name'])) {
2236 $this->stack[1]->setAttribute($attr[
'name'], $attr[
'value']);
2260 if ($this->elementInScope(
'p')) {
2270 $this->insertElement($token);
2277 if ($this->form_pointer !== null) {
2285 if ($this->elementInScope(
'p')) {
2296 $element = $this->insertElement($token);
2297 $this->form_pointer = $element;
2308 if ($this->elementInScope(
'p')) {
2317 $stack_length = count($this->stack) - 1;
2319 for (
$n = $stack_length; 0 <=
$n;
$n--) {
2323 $node = $this->stack[
$n];
2324 $cat = $this->getElementCategory($node->tagName);
2329 if ($token[
'name'] === $node->tagName || ($token[
'name'] !==
'li' 2330 && ($node->tagName ===
'dd' || $node->tagName ===
'dt'))
2332 for ($x = $stack_length; $x >=
$n; $x--) {
2333 array_pop($this->stack);
2342 if ($cat !== self::FORMATTING && $cat !== self::PHRASING &&
2343 $node->tagName !==
'address' && $node->tagName !==
'div' 2351 $this->insertElement($token);
2359 if ($this->elementInScope(
'p')) {
2369 $this->insertElement($token);
2384 if ($this->elementInScope(
'p')) {
2398 while ($this->elementInScope(array(
'h1',
'h2',
'h3',
'h4',
'h5',
'h6'))) {
2399 array_pop($this->stack);
2403 $this->insertElement($token);
2417 $leng = count($this->a_formatting);
2419 for (
$n = $leng - 1;
$n >= 0;
$n--) {
2420 if ($this->a_formatting[
$n] === self::MARKER) {
2423 } elseif ($this->a_formatting[
$n]->nodeName ===
'a') {
2435 $this->reconstructActiveFormattingElements();
2438 $el = $this->insertElement($token);
2442 $this->a_formatting[] = $el;
2460 $this->reconstructActiveFormattingElements();
2463 $el = $this->insertElement($token);
2467 $this->a_formatting[] = $el;
2476 if ($this->elementInScope(
'button')) {
2486 $this->reconstructActiveFormattingElements();
2489 $this->insertElement($token);
2493 $this->a_formatting[] = self::MARKER;
2500 $this->reconstructActiveFormattingElements();
2503 $this->insertElement($token);
2507 $this->a_formatting[] = self::MARKER;
2513 $this->reconstructActiveFormattingElements();
2516 $this->insertElement($token);
2526 if ($this->elementInScope(
'p')) {
2536 $this->insertElement($token);
2539 $this->mode = self::IN_TABLE;
2554 $this->reconstructActiveFormattingElements();
2557 $this->insertElement($token);
2560 array_pop($this->stack);
2567 if ($this->elementInScope(
'p')) {
2577 $this->insertElement($token);
2580 array_pop($this->stack);
2587 $token[
'name'] =
'img';
2588 return $this->inBody($token);
2594 $this->reconstructActiveFormattingElements();
2597 $element = $this->insertElement($token,
false);
2602 $this->form_pointer !== null
2603 ? $this->form_pointer->appendChild($element)
2604 : end($this->stack)->appendChild($element);
2607 array_pop($this->stack);
2617 if ($this->form_pointer === null) {
2660 'This is a searchable index. ' .
2661 'Insert your search keywords here: ' 2668 $attr = $token[
'attr'];
2669 $attr[] = array(
'name' =>
'name',
'value' =>
'isindex');
2682 'This is a searchable index. ' .
2683 'Insert your search keywords here: ' 2726 $this->insertElement($token);
2738 $this->insertElement($token);
2747 $this->reconstructActiveFormattingElements();
2750 $this->insertElement($token);
2753 $this->mode = self::IN_SELECT;
2779 case 'event-source':
2794 $this->reconstructActiveFormattingElements();
2796 $this->insertElement($token,
true,
true);
2802 switch ($token[
'name']) {
2808 if (count($this->stack) < 2 || $this->stack[1]->nodeName !==
'body') {
2813 } elseif (end($this->stack)->nodeName !==
'body') {
2818 $this->mode = self::AFTER_BODY;
2833 return $this->afterBody($token);
2854 if ($this->elementInScope($token[
'name'])) {
2855 $this->generateImpliedEndTags();
2866 for (
$n = count($this->stack) - 1;
$n >= 0;
$n--) {
2867 if ($this->stack[
$n]->nodeName === $token[
'name']) {
2871 array_pop($this->stack);
2881 if ($this->elementInScope($token[
'name'])) {
2882 $this->generateImpliedEndTags();
2886 if (end($this->stack)->nodeName !== $token[
'name']) {
2896 array_pop($this->stack);
2900 $this->form_pointer = null;
2907 if ($this->elementInScope(
'p')) {
2908 $this->generateImpliedEndTags(array(
'p'));
2917 for (
$n = count($this->stack) - 1;
$n >= 0;
$n--) {
2918 if ($this->elementInScope(
'p')) {
2919 array_pop($this->stack);
2936 if ($this->elementInScope($token[
'name'])) {
2937 $this->generateImpliedEndTags(array($token[
'name']));
2947 for (
$n = count($this->stack) - 1;
$n >= 0;
$n--) {
2948 if ($this->stack[
$n]->nodeName === $token[
'name']) {
2952 array_pop($this->stack);
2965 $elements = array(
'h1',
'h2',
'h3',
'h4',
'h5',
'h6');
2970 if ($this->elementInScope($elements)) {
2971 $this->generateImpliedEndTags();
2981 while ($this->elementInScope($elements)) {
2982 array_pop($this->stack);
3010 for ($a = count($this->a_formatting) - 1; $a >= 0; $a--) {
3011 if ($this->a_formatting[$a] === self::MARKER) {
3014 } elseif ($this->a_formatting[$a]->tagName === $token[
'name']) {
3015 $formatting_element = $this->a_formatting[$a];
3016 $in_stack = in_array($formatting_element, $this->stack,
true);
3026 if (!isset($formatting_element) || ($in_stack &&
3027 !$this->elementInScope($token[
'name']))
3035 } elseif (isset($formatting_element) && !$in_stack) {
3036 unset($this->a_formatting[$fe_af_pos]);
3037 $this->a_formatting = array_merge($this->a_formatting);
3046 $fe_s_pos = array_search($formatting_element, $this->stack,
true);
3047 $length = count($this->stack);
3049 for ($s = $fe_s_pos + 1; $s < $length; $s++) {
3050 $category = $this->getElementCategory($this->stack[$s]->nodeName);
3052 if ($category !== self::PHRASING && $category !== self::FORMATTING) {
3053 $furthest_block = $this->stack[$s];
3063 if (!isset($furthest_block)) {
3064 for (
$n = $length - 1;
$n >= $fe_s_pos;
$n--) {
3065 array_pop($this->stack);
3068 unset($this->a_formatting[$fe_af_pos]);
3069 $this->a_formatting = array_merge($this->a_formatting);
3076 $common_ancestor = $this->stack[$fe_s_pos - 1];
3080 if ($furthest_block->parentNode !== null) {
3081 $furthest_block->parentNode->removeChild($furthest_block);
3088 $bookmark = $fe_af_pos;
3092 $node = $furthest_block;
3093 $last_node = $furthest_block;
3096 for (
$n = array_search($node, $this->stack,
true) - 1;
$n >= 0;
$n--) {
3099 $node = $this->stack[
$n];
3105 if (!in_array($node, $this->a_formatting,
true)) {
3106 unset($this->stack[
$n]);
3107 $this->stack = array_merge($this->stack);
3117 if ($node === $formatting_element) {
3124 } elseif ($last_node === $furthest_block) {
3125 $bookmark = array_search($node, $this->a_formatting,
true) + 1;
3134 if ($node->hasChildNodes()) {
3135 $clone = $node->cloneNode();
3136 $s_pos = array_search($node, $this->stack,
true);
3137 $a_pos = array_search($node, $this->a_formatting,
true);
3139 $this->stack[$s_pos] = $clone;
3140 $this->a_formatting[$a_pos] = $clone;
3146 if ($last_node->parentNode !== null) {
3147 $last_node->parentNode->removeChild($last_node);
3150 $node->appendChild($last_node);
3160 if ($last_node->parentNode !== null) {
3161 $last_node->parentNode->removeChild($last_node);
3164 $common_ancestor->appendChild($last_node);
3168 $clone = $formatting_element->cloneNode();
3173 while ($furthest_block->hasChildNodes()) {
3174 $child = $furthest_block->firstChild;
3175 $furthest_block->removeChild($child);
3176 $clone->appendChild($child);
3180 $furthest_block->appendChild($clone);
3186 $fe_af_pos = array_search($formatting_element, $this->a_formatting,
true);
3187 unset($this->a_formatting[$fe_af_pos]);
3188 $this->a_formatting = array_merge($this->a_formatting);
3190 $af_part1 = array_slice($this->a_formatting, 0, $bookmark - 1);
3191 $af_part2 = array_slice($this->a_formatting, $bookmark, count($this->a_formatting));
3192 $this->a_formatting = array_merge($af_part1, array($clone), $af_part2);
3199 $fe_s_pos = array_search($formatting_element, $this->stack,
true);
3200 $fb_s_pos = array_search($furthest_block, $this->stack,
true);
3201 unset($this->stack[$fe_s_pos]);
3203 $s_part1 = array_slice($this->stack, 0, $fb_s_pos);
3204 $s_part2 = array_slice($this->stack, $fb_s_pos + 1, count($this->stack));
3205 $this->stack = array_merge($s_part1, array($clone), $s_part2);
3208 unset($formatting_element, $fe_af_pos, $fe_s_pos, $furthest_block);
3220 if ($this->elementInScope($token[
'name'])) {
3221 $this->generateImpliedEndTags();
3232 for (
$n = count($this->stack) - 1;
$n >= 0;
$n--) {
3233 if ($this->stack[
$n]->nodeName === $token[
'name']) {
3237 array_pop($this->stack);
3240 $marker = end(array_keys($this->a_formatting, self::MARKER,
true));
3242 for (
$n = count($this->a_formatting) - 1;
$n > $marker;
$n--) {
3243 array_pop($this->a_formatting);
3276 for (
$n = count($this->stack) - 1;
$n >= 0;
$n--) {
3279 $node = end($this->stack);
3283 if ($token[
'name'] === $node->nodeName) {
3285 $this->generateImpliedEndTags();
3294 for ($x = count($this->stack) -
$n; $x >=
$n; $x--) {
3295 array_pop($this->stack);
3299 $category = $this->getElementCategory($node);
3301 if ($category !== self::SPECIAL && $category !== self::SCOPING) {
3318 $clear = array(
'html',
'table');
3324 preg_match(
'/^[\t\n\x0b\x0c ]+$/', $token[
'data'])
3327 $text = $this->dom->createTextNode($token[
'data']);
3328 end($this->stack)->appendChild($text);
3334 $comment = $this->dom->createComment($token[
'data']);
3335 end($this->stack)->appendChild(
$comment);
3339 $token[
'name'] ===
'caption' 3342 $this->clearStackToTableContext($clear);
3346 $this->a_formatting[] = self::MARKER;
3350 $this->insertElement($token);
3351 $this->mode = self::IN_CAPTION;
3355 $token[
'name'] ===
'colgroup' 3358 $this->clearStackToTableContext($clear);
3362 $this->insertElement($token);
3363 $this->mode = self::IN_CGROUP;
3367 $token[
'name'] ===
'col' 3371 'name' =>
'colgroup',
3377 $this->inColumnGroup($token);
3382 array(
'tbody',
'tfoot',
'thead')
3386 $this->clearStackToTableContext($clear);
3390 $this->insertElement($token);
3391 $this->mode = self::IN_TBODY;
3395 in_array($token[
'name'], array(
'td',
'th',
'tr'))
3407 return $this->inTableBody($token);
3411 $token[
'name'] ===
'table' 3423 return $this->mainPhase($token);
3427 $token[
'name'] ===
'table' 3432 if (!$this->elementInScope($token[
'name'],
true)) {
3438 $this->generateImpliedEndTags();
3447 $current = end($this->stack)->nodeName;
3448 array_pop($this->stack);
3450 if ($current ===
'table') {
3456 $this->resetInsertionMode();
3489 end($this->stack)->nodeName,
3490 array(
'table',
'tbody',
'tfoot',
'thead',
'tr')
3504 for (
$n = count($this->stack) - 1;
$n >= 0;
$n--) {
3505 if ($this->stack[
$n]->nodeName ===
'table') {
3506 $table = $this->stack[
$n];
3511 if (isset($table) && $table->parentNode !== null) {
3512 $this->foster_parent = $table->parentNode;
3514 } elseif (!isset($table)) {
3515 $this->foster_parent = $this->stack[0];
3517 } elseif (isset($table) && ($table->parentNode === null ||
3518 $table->parentNode->nodeType !== XML_ELEMENT_NODE)
3520 $this->foster_parent = $this->stack[
$n - 1];
3524 $this->inBody($token);
3531 if ($token[
'type'] ===
HTML5::ENDTAG && $token[
'name'] ===
'caption') {
3535 if (!$this->elementInScope($token[
'name'],
true)) {
3541 $this->generateImpliedEndTags();
3550 $node = end($this->stack)->nodeName;
3551 array_pop($this->stack);
3553 if ($node ===
'caption') {
3560 $this->clearTheActiveFormattingElementsUpToTheLastMarker();
3563 $this->mode = self::IN_TABLE;
3583 $token[
'name'] ===
'table')
3590 'name' =>
'caption',
3595 return $this->inTable($token);
3619 $this->inBody($token);
3629 preg_match(
'/^[\t\n\x0b\x0c ]+$/', $token[
'data'])
3632 $text = $this->dom->createTextNode($token[
'data']);
3633 end($this->stack)->appendChild($text);
3639 $comment = $this->dom->createComment($token[
'data']);
3640 end($this->stack)->appendChild(
$comment);
3643 } elseif ($token[
'type'] ===
HTML5::STARTTAG && $token[
'name'] ===
'col') {
3646 $this->insertElement($token);
3647 array_pop($this->stack);
3651 $token[
'name'] ===
'colgroup' 3655 if (end($this->stack)->nodeName ===
'html') {
3662 array_pop($this->stack);
3663 $this->mode = self::IN_TABLE;
3667 } elseif ($token[
'type'] ===
HTML5::ENDTAG && $token[
'name'] ===
'col') {
3674 $this->inColumnGroup(
3676 'name' =>
'colgroup',
3681 return $this->inTable($token);
3687 $clear = array(
'tbody',
'tfoot',
'thead',
'html');
3692 $this->clearStackToTableContext($clear);
3696 $this->insertElement($token);
3697 $this->mode = self::IN_ROW;
3701 ($token[
'name'] ===
'th' || $token[
'name'] ===
'td')
3713 return $this->inRow($token);
3717 in_array($token[
'name'], array(
'tbody',
'tfoot',
'thead'))
3722 if (!$this->elementInScope($token[
'name'],
true)) {
3728 $this->clearStackToTableContext($clear);
3732 array_pop($this->stack);
3733 $this->mode = self::IN_TABLE;
3740 array(
'caption',
'col',
'colgroup',
'tbody',
'tfoor',
'thead')
3747 if (!$this->elementInScope(array(
'tbody',
'thead',
'tfoot'),
true)) {
3753 $this->clearStackToTableContext($clear);
3760 'name' => end($this->stack)->nodeName,
3765 return $this->mainPhase($token);
3772 array(
'body',
'caption',
'col',
'colgroup',
'html',
'td',
'th',
'tr')
3780 $this->inTable($token);
3786 $clear = array(
'tr',
'html');
3790 ($token[
'name'] ===
'th' || $token[
'name'] ===
'td')
3793 $this->clearStackToTableContext($clear);
3797 $this->insertElement($token);
3798 $this->mode = self::IN_CELL;
3802 $this->a_formatting[] = self::MARKER;
3805 } elseif ($token[
'type'] ===
HTML5::ENDTAG && $token[
'name'] ===
'tr') {
3809 if (!$this->elementInScope($token[
'name'],
true)) {
3815 $this->clearStackToTableContext($clear);
3820 array_pop($this->stack);
3821 $this->mode = self::IN_TBODY;
3828 array(
'caption',
'col',
'colgroup',
'tbody',
'tfoot',
'thead',
'tr')
3840 return $this->inCell($token);
3844 in_array($token[
'name'], array(
'tbody',
'tfoot',
'thead'))
3849 if (!$this->elementInScope($token[
'name'],
true)) {
3863 return $this->inCell($token);
3870 array(
'body',
'caption',
'col',
'colgroup',
'html',
'td',
'th',
'tr')
3878 $this->inTable($token);
3886 ($token[
'name'] ===
'td' || $token[
'name'] ===
'th')
3891 if (!$this->elementInScope($token[
'name'],
true)) {
3898 $this->generateImpliedEndTags(array($token[
'name']));
3907 $node = end($this->stack)->nodeName;
3908 array_pop($this->stack);
3910 if ($node === $token[
'name']) {
3917 $this->clearTheActiveFormattingElementsUpToTheLastMarker();
3921 $this->mode = self::IN_ROW;
3944 if (!$this->elementInScope(array(
'td',
'th'),
true)) {
3951 return $this->inRow($token);
3974 if (!$this->elementInScope(array(
'td',
'th'),
true)) {
3981 return $this->inRow($token);
3988 array(
'body',
'caption',
'col',
'colgroup',
'html')
3997 array(
'table',
'tbody',
'tfoot',
'thead',
'tr')
4004 if (!$this->elementInScope($token[
'name'],
true)) {
4011 return $this->inRow($token);
4017 $this->inBody($token);
4028 $this->insertText($token[
'data']);
4034 $this->insertComment($token[
'data']);
4038 $token[
'name'] ===
'option' 4042 if (end($this->stack)->nodeName ===
'option') {
4052 $this->insertElement($token);
4056 $token[
'name'] ===
'optgroup' 4060 if (end($this->stack)->nodeName ===
'option') {
4071 if (end($this->stack)->nodeName ===
'optgroup') {
4074 'name' =>
'optgroup',
4081 $this->insertElement($token);
4085 $token[
'name'] ===
'optgroup' 4091 $elements_in_stack = count($this->stack);
4093 if ($this->stack[$elements_in_stack - 1]->nodeName ===
'option' &&
4094 $this->stack[$elements_in_stack - 2]->nodeName ===
'optgroup' 4107 if ($this->stack[$elements_in_stack - 1] ===
'optgroup') {
4108 array_pop($this->stack);
4113 $token[
'name'] ===
'option' 4118 if (end($this->stack)->nodeName ===
'option') {
4119 array_pop($this->stack);
4124 $token[
'name'] ===
'select' 4129 if (!$this->elementInScope($token[
'name'],
true)) {
4137 $current = end($this->stack)->nodeName;
4138 array_pop($this->stack);
4140 if ($current ===
'select') {
4146 $this->resetInsertionMode();
4150 } elseif ($token[
'name'] ===
'select' &&
4185 if ($this->elementInScope($token[
'name'],
true)) {
4193 $this->mainPhase($token);
4210 preg_match(
'/^[\t\n\x0b\x0c ]+$/', $token[
'data'])
4214 $this->inBody($token);
4221 $comment = $this->dom->createComment($token[
'data']);
4222 $this->stack[0]->appendChild(
$comment);
4225 } elseif ($token[
'type'] ===
HTML5::ENDTAG && $token[
'name'] ===
'html') {
4232 $this->phase = self::END_PHASE;
4238 $this->mode = self::IN_BODY;
4239 return $this->inBody($token);
4251 preg_match(
'/^[\t\n\x0b\x0c ]+$/', $token[
'data'])
4254 $this->insertText($token[
'data']);
4260 $this->insertComment($token[
'data']);
4263 } elseif ($token[
'name'] ===
'frameset' &&
4266 $this->insertElement($token);
4269 } elseif ($token[
'name'] ===
'frameset' &&
4274 if (end($this->stack)->nodeName ===
'html') {
4280 array_pop($this->stack);
4286 $this->mode = self::AFTR_FRAME;
4290 } elseif ($token[
'name'] ===
'frame' &&
4294 $this->insertElement($token);
4297 array_pop($this->stack);
4300 } elseif ($token[
'name'] ===
'noframes' &&
4304 $this->inBody($token);
4320 preg_match(
'/^[\t\n\x0b\x0c ]+$/', $token[
'data'])
4323 $this->insertText($token[
'data']);
4329 $this->insertComment($token[
'data']);
4332 } elseif ($token[
'name'] ===
'html' &&
4336 $this->phase = self::END_PHASE;
4339 } elseif ($token[
'name'] ===
'noframes' &&
4343 $this->inBody($token);
4364 $comment = $this->dom->createComment($token[
'data']);
4371 preg_match(
'/^[\t\n\x0b\x0c ]+$/', $token[
'data'])
4374 $this->mainPhase($token);
4380 preg_match(
'/^[\t\n\x0b\x0c ]+$/', $token[
'data'])) ||
4385 $this->phase = self::MAIN_PHASE;
4386 return $this->mainPhase($token);
4400 $token[
'name'] = preg_replace(
'/[^a-z0-9-]/i',
'', $token[
'name']);
4402 $token[
'name'] = ltrim($token[
'name'],
'-0..9');
4404 if ($token[
'name'] ===
'') {
4405 $token[
'name'] =
'span';
4409 $el = $this->dom->createElement($token[
'name']);
4411 foreach ($token[
'attr'] as $attr) {
4412 if (!$el->hasAttribute($attr[
'name'])) {
4413 $el->setAttribute($attr[
'name'], $attr[
'value']);
4417 $this->appendToRealParent($el);
4418 $this->stack[] = $el;
4425 $text = $this->dom->createTextNode(
$data);
4426 $this->appendToRealParent($text);
4432 $this->appendToRealParent(
$comment);
4437 if ($this->foster_parent === null) {
4438 end($this->stack)->appendChild($node);
4440 } elseif ($this->foster_parent !== null) {
4447 for (
$n = count($this->stack) - 1;
$n >= 0;
$n--) {
4448 if ($this->stack[
$n]->nodeName ===
'table' &&
4449 $this->stack[
$n]->parentNode !== null
4451 $table = $this->stack[
$n];
4456 if (isset($table) && $this->foster_parent->isSameNode($table->parentNode)) {
4457 $this->foster_parent->insertBefore($node, $table);
4459 $this->foster_parent->appendChild($node);
4462 $this->foster_parent = null;
4468 if (is_array($el)) {
4469 foreach ($el as $element) {
4470 if ($this->elementInScope($element, $table)) {
4478 $leng = count($this->stack);
4480 for (
$n = 0;
$n < $leng;
$n++) {
4483 $node = $this->stack[$leng - 1 -
$n];
4485 if ($node->tagName === $el) {
4489 } elseif ($node->tagName ===
'table') {
4494 } elseif ($table ===
true && in_array(
4511 } elseif ($node === $node->ownerDocument->documentElement) {
4530 $formatting_elements = count($this->a_formatting);
4532 if ($formatting_elements === 0) {
4538 $entry = end($this->a_formatting);
4544 if ($entry === self::MARKER || in_array($entry, $this->stack,
true)) {
4548 for ($a = $formatting_elements - 1; $a >= 0;
true) {
4552 $step_seven =
false;
4559 $entry = $this->a_formatting[$a];
4563 if ($entry === self::MARKER || in_array($entry, $this->stack,
true)) {
4571 if (isset($step_seven) && $step_seven ===
true) {
4573 $entry = $this->a_formatting[$a];
4577 $clone = $entry->cloneNode();
4581 end($this->stack)->appendChild($clone);
4582 $this->stack[] = $clone;
4586 $this->a_formatting[$a] = $clone;
4590 if (end($this->a_formatting) !== $clone) {
4607 $entry = end($this->a_formatting);
4610 array_pop($this->a_formatting);
4614 if ($entry === self::MARKER) {
4627 $node = end($this->stack);
4628 $elements = array_diff(array(
'dd',
'dt',
'li',
'p',
'td',
'th',
'tr'),
$exclude);
4630 while (in_array(end($this->stack)->nodeName, $elements)) {
4631 array_pop($this->stack);
4637 $name = $node->tagName;
4638 if (in_array($name, $this->special)) {
4639 return self::SPECIAL;
4640 } elseif (in_array($name, $this->scoping)) {
4641 return self::SCOPING;
4642 } elseif (in_array($name, $this->formatting)) {
4643 return self::FORMATTING;
4645 return self::PHRASING;
4657 $node = end($this->stack)->nodeName;
4659 if (in_array($node, $elements)) {
4662 array_pop($this->stack);
4671 $leng = count($this->stack);
4673 for (
$n = $leng - 1;
$n >= 0;
$n--) {
4675 $node = $this->stack[
$n];
4681 if ($this->stack[0]->isSameNode($node)) {
4687 if ($node->nodeName ===
'select') {
4688 $this->mode = self::IN_SELECT;
4693 } elseif ($node->nodeName ===
'td' || $node->nodeName ===
'th') {
4694 $this->mode = self::IN_CELL;
4699 } elseif ($node->nodeName ===
'tr') {
4700 $this->mode = self::IN_ROW;
4705 } elseif (in_array($node->nodeName, array(
'tbody',
'thead',
'tfoot'))) {
4706 $this->mode = self::IN_TBODY;
4711 } elseif ($node->nodeName ===
'caption') {
4712 $this->mode = self::IN_CAPTION;
4717 } elseif ($node->nodeName ===
'colgroup') {
4718 $this->mode = self::IN_CGROUP;
4723 } elseif ($node->nodeName ===
'table') {
4724 $this->mode = self::IN_TABLE;
4730 } elseif ($node->nodeName ===
'head') {
4731 $this->mode = self::IN_BODY;
4736 } elseif ($node->nodeName ===
'body') {
4737 $this->mode = self::IN_BODY;
4742 } elseif ($node->nodeName ===
'frameset') {
4743 $this->mode = self::IN_FRAME;
4750 } elseif ($node->nodeName ===
'html') {
4751 $this->mode = ($this->head_pointer === null)
4760 $this->mode = self::IN_BODY;
4770 foreach (array(
'td',
'th') as $cell) {
4771 if ($this->elementInScope($cell,
true)) {
tokenizeDOM($node, &$tokens)
Iterative function that tokenizes a node, putting it into an accumulator.
attributeValueUnquotedState()
attributeValueSingleQuotedState()
getElementCategory($node)
wrapHTML($html, $config, $context)
Wraps an HTML fragment in the necessary HTML.
Experimental HTML5-based parser using Jeroen van der Meer's PH5P library.
clearTheActiveFormattingElementsUpToTheLastMarker()
characters($char_class, $start)
markupDeclarationOpenState()
Parser that uses PHP 5's DOM extension (part of the core).
tokenizeHTML($html, $config, $context)
beforeAttributeValueState()
Our in-house implementation of a parser.
generateImpliedEndTags($exclude=array())
entityInAttributeValueState()
clearStackToTableContext($elements)
elementInScope($el, $table=false)
normalize($html, $config, $context)
Takes a piece of HTML and normalizes it by converting entities, fixing encoding, extracting bits...
insertElement($token, $append=true, $check=false)
appendToRealParent($node)
afterAttributeNameState()
attributeValueDoubleQuotedState()
beforeAttributeNameState()
reconstructActiveFormattingElements()
const EOF
How fgetc() reports an End Of File.