Browse Source

Started Printer

split-manual
Dustin Wilson 6 years ago
parent
commit
c5631050cc
  1. 2
      lib/ActiveFormattingElementsList.php
  2. 46
      lib/Exception.php
  3. 120
      lib/Printer.php
  4. 6
      lib/Stack.php

2
lib/ActiveFormattingElementsList.php

@ -24,7 +24,7 @@ class ActiveFormattingElementsList extends Stack {
public function offsetSet($offset, $value) {
if ($offset < 0 || $offset > count($this->_storage) - 1) {
throw new Exception(Exception::STACK_INVALID_INDEX);
throw new Exception(Exception::STACK_INVALID_INDEX, $offset);
}
if (is_null($offset)) {

46
lib/Exception.php

@ -7,47 +7,41 @@ class Exception extends \Exception {
const UNKNOWN_ERROR = 10001;
const INCORRECT_PARAMETERS_FOR_MESSAGE = 10002;
const PARSER_DOMDOCUMENT_EXPECTED = 10101;
const PARSER_DOMELEMENT_DOMDOCUMENT_DOMDOCUMENTFRAG_EXPECTED = 10102;
const PARSER_DOMNODE_EXPECTED = 10103;
const STACK_INVALID_INDEX = 10101;
const STACK_FRAGMENT_CONTEXT_DOMELEMENT_DOMDOCUMENT_DOMDOCUMENTFRAG_EXPECTED = 10102;
const STACK_INVALID_INDEX = 10201;
const STACK_DOMNODE_ONLY = 10202;
const STACK_FRAGMENT_CONTEXT_DOMELEMENT_DOMDOCUMENT_DOMDOCUMENTFRAG_EXPECTED = 10203;
const DATA_NODATA = 10201;
const DATA_INVALID_DATA_CONSUMPTION_LENGTH = 10202;
const DATA_NODATA = 10301;
const DATA_INVALID_DATA_CONSUMPTION_LENGTH = 10302;
const DOM_DOMDOCUMENT_EXPECTED = 10301;
const DOM_DOMELEMENT_STRING_OR_CLOSURE_EXPECTED = 10302;
const DOM_DOMDOCUMENT_EXPECTED = 10401;
const DOM_DOMELEMENT_STRING_OR_CLOSURE_EXPECTED = 10402;
const TOKENIZER_INVALID_STATE = 10401;
const TOKENIZER_INVALID_STATE = 10501;
const TREEBUILDER_FORMELEMENT_EXPECTED = 10501;
const TREEBUILDER_FRAGMENT_CONTEXT_DOMELEMENT_DOMDOCUMENT_DOMDOCUMENTFRAG_EXPECTED = 10502;
const TREEBUILDER_FORMELEMENT_EXPECTED = 10601;
const TREEBUILDER_FRAGMENT_CONTEXT_DOMELEMENT_DOMDOCUMENT_DOMDOCUMENTFRAG_EXPECTED = 10602;
const PRINTER_DOMELEMENT_DOMDOCUMENT_DOMDOCUMENTFRAG_EXPECTED = 10601;
protected static $messages = [10000 => 'Invalid error code',
10001 => 'Unknown error; escaping',
10002 => 'Incorrect number of parameters for Exception message; %s expected',
10101 => 'DOMDocument expected; found %s',
10102 => 'DOMElement, DOMDocument, or DOMDocumentFragment expected; found %s',
10103 => 'DOMNode expected; found %s',
10101 => '%s is an invalid Stack index',
10102 => 'DOMElement, DOMDocument, or DOMDocumentFragment expected for fragment context; found %s',
10201 => '%s is an invalid Stack index',
10202 => 'Instances of DOMNode are the only types allowed in a Stack',
10203 => 'DOMElement, DOMDocument, or DOMDocumentFragment expected for fragment context; found %s',
10201 => 'Data string expected; found %s',
10202 => '%s is an invalid data consumption length; a value of 1 or above is expected',
10301 => 'Data string expected; found %s',
10302 => '%s is an invalid data consumption length; a value of 1 or above is expected',
10301 => 'The first argument must be an instance of \DOMElement or null; found %s',
10302 => 'The first argument must either be an instance of \DOMElement, a string, or a closure; found %s',
10401 => 'The first argument must be an instance of \DOMElement or null; found %s',
10402 => 'The first argument must either be an instance of \DOMElement, a string, or a closure; found %s',
10401 => 'The Tokenizer has entered an invalid state',
10501 => 'The Tokenizer has entered an invalid state',
10501 => 'Form element expected, found %s',
10502 => 'DOMElement, DOMDocument, or DOMDocumentFragment expected; found %s',
10601 => 'Form element expected, found %s',
10602 => 'DOMElement, DOMDocument, or DOMDocumentFragment expected; found %s'];
10601 => 'DOMElement, DOMDocument, or DOMDocumentFragment expected; found %s',];
public function __construct(int $code, ...$args) {
if (!isset(static::$messages[$code])) {

120
lib/Printer.php

@ -0,0 +1,120 @@
<?php
declare(strict_types=1);
namespace dW\HTML5;
class Printer {
public static function serialize($node): string {
if (!$node instanceof DOMElement && !$node instanceof DOMDocument && !$node instanceof DOMDocumentFragment) {
throw new Exception(Exception::PRINTER_DOMELEMENT_DOMDOCUMENT_DOMDOCUMENTFRAG_EXPECTED, gettype($node));
}
# 1. Let s be a string, and initialize it to the empty string.
$s = '';
# 2. If the node is a template element, then let the node instead be the
# template element’s template contents (a DocumentFragment node).
// TODO
# 3. For each child node of the node, in tree order, run the following steps:
for ($i = 0; $i < $node->childNodes->length; $i++) {
# 1. Let current node be the child node being processed.
$currentNode = $node->childNodes->item($i);
# 2. Append the appropriate string from the following list to s:
## If current node is an Element
### If current node is an element in the HTML namespace, the MathML namespace,
### or the SVG namespace, then let tagname be current node’s local name.
### Otherwise, let tagname be current node’s qualified name.
if ($currentNode instanceof DOMElement && (is_null($currentNode->namespaceURI) || $currentNode->namespaceURI === Parser::MATHML_NAMESPACE || $currentNode->namespaceURI === Parser::SVG_NAMESPACE)) {
$tagName = $currentNode->localName;
} else {
$tagName = $currentNode->nodeName;
}
### Append a U+003C LESS-THAN SIGN character (<), followed by tagname.
$s .= "<$tagName";
### For each attribute that the element has, append a U+0020 SPACE character,
### the attribute’s serialized name as described below, a U+003D EQUALS SIGN
### character (=), a U+0022 QUOTATION MARK character ("), the attribute’s value,
### escaped as described below in attribute mode, and a second U+0022 QUOTATION
### MARK character (").
for ($j = 0; $j < $currentNode->attributes->length; $j++) {
$attr = $currentNode->attributes->item($j);
# An attribute’s serialized name for the purposes of the previous paragraph
# must be determined as follows:
switch ($attr->namespaceURI) {
# If the attribute has no namespace
case null:
# The attribute’s serialized name is the attribute’s local name.
$name = $attr->localName;
break;
# If the attribute is in the XML namespace
case Parser::XML_NAMESPACE:
# The attribute’s serialized name is the string "xml:" followed by the
# attribute’s local name.
$name = 'xml:' . $attr->localName;
break;
# If the attribute is in the XMLNS namespace...
case Parser::XMLNS_NAMESPACE:
# ...and the attribute’s local name is xmlns
if ($attr->localName === 'xmlns') {
# The attribute’s serialized name is the string "xmlns".
$name = 'xmlns';
}
# ...and the attribute’s local name is not xmlns
else {
# The attribute’s serialized name is the string "xmlns:" followed by the
# attribute’s local name.
$name = 'xmlns:' . $attr->localName;
}
break;
# If the attribute is in the XLink namespace
case Parser::XLINK_NAMESPACE:
# The attribute’s serialized name is the string "xlink:" followed by the
# attribute’s local name.
$name = 'xlink:' . $attr->localName;
break;
# If the attribute is in some other namespace
default:
# The attribute’s serialized name is the attribute’s qualified name.
$name = $attr->name;
}
$value = static::escapeString($attr->value, true);
$s .= " $name=\"$value\"";
}
### While the exact order of attributes is UA-defined, and may depend on factors
### such as the order that the attributes were given in the original markup, the
### sort order must be stable, such that consecutive invocations of this
### algorithm serialize an element’s attributes in the same order.
// Okay.
### Append a U+003E GREATER-THAN SIGN character (>).
$s .= '>';
}
}
protected static escapeString(string $string, bool $attribute = false): string {
# Escaping a string (for the purposes of the algorithm above) consists of
# running the following steps:
## 1. Replace any occurrence of the "&amp;" character by the string "&amp;amp;".
## 2. Replace any occurrences of the U+00A0 NO-BREAK SPACE character by the
## string "&amp;nbsp;".
$string = str_replace(['&amp;', chr(0x00A0)], ['&amp;amp;', '&amp;nbsp;'], $string);
## 3. If the algorithm was invoked in the attribute mode, replace any
## occurrences of the "&quot;" character by the string "&amp;quot;".
## 4. If the algorithm was not invoked in the attribute mode, replace any
## occurrences of the "&lt;" character by the string "&amp;lt;", and any
## occurrences of the "&gt;" character by the string "&amp;gt;".
if ($attribute) {
$string = str_replace(['&quot;', '&lt;', '&gt;'], ['&amp;quot;', '&amp;lt;', '&amp;gt;'], $string);
}
return $string;
}
}

6
lib/Stack.php

@ -9,7 +9,7 @@ class Stack implements \ArrayAccess {
public function offsetSet($offset, $value) {
if ($offset < 0) {
throw new Exception(Exception::STACK_INVALID_INDEX);
throw new Exception(Exception::STACK_INVALID_INDEX, $offset);
}
if (is_null($offset)) {
@ -25,7 +25,7 @@ class Stack implements \ArrayAccess {
public function offsetUnset($offset) {
if ($offset < 0 || $offset > count($this->_storage) - 1) {
throw new Exception(Exception::STACK_INVALID_INDEX);
throw new Exception(Exception::STACK_INVALID_INDEX, $offset);
}
unset($this->_storage[$offset]);
@ -35,7 +35,7 @@ class Stack implements \ArrayAccess {
public function offsetGet($offset) {
if ($offset < 0 || $offset > count($this->_storage) - 1) {
throw new Exception(Exception::STACK_INVALID_INDEX);
throw new Exception(Exception::STACK_INVALID_INDEX, $offset);
}
return $this->_storage[$offset];

Loading…
Cancel
Save