Browse Source

More active formatting elements stuff

ns
Dustin Wilson 6 years ago
parent
commit
0d21ed5d72
  1. 100
      lib/ActiveFormattingElementsList.php
  2. 2
      lib/Parser.php

100
lib/ActiveFormattingElementsList.php

@ -15,8 +15,13 @@ namespace dW\HTML5;
# associated with the token for which it was created, so that further elements
# can be created for that token if necessary.
class ActiveFormattingElementsList implements \ArrayAccess {
public $parser;
protected $storage = [];
public function __construct(Parser $parser) {
$this->parser = $parser;
}
public function offsetSet($offset, $value) {
if ($offset < 0) {
throw new Exception(Exception::STACK_INVALID_INDEX);
@ -99,6 +104,13 @@ class ActiveFormattingElementsList implements \ArrayAccess {
return $this->storage[$offset];
}
public function insert(StartTagToken $token, \DOMElement $element) {
$this->storage[] = [
'token' => $token,
'element' => $element
];
}
public function insertMarker() {
$this->offsetSet(null, new ActiveFormattingElementMarker());
}
@ -107,6 +119,94 @@ class ActiveFormattingElementsList implements \ArrayAccess {
return array_pop($this->storage);
}
public function reconstruct() {
# When the steps below require the UA to reconstruct the active formatting
# elements, the UA must perform the following steps:
// Yes, I know this uses gotos, but here are the reasons for using them:
// 1. The spec seems to actively encourage using them, even providing
// suggestions on what to name the labels.
// 2. It'd be a pain to program and maintain without them because of this.
# 1. If there are no entries in the list of active formatting elements, then
# there is nothing to reconstruct; stop this algorithm.
if (count($this->storage) === 0) {
return;
}
# 2. If the last (most recently added) entry in the list of active formatting
# elements is a marker, or if it is an element that is in the stack of open
# elements, then there is nothing to reconstruct; stop this algorithm.
$entry = end($this->storage);
if ($entry instanceof ActiveFormattingElementMarker || in_array($entry['element'], $this->parser->stack)) {
return;
}
# 3. Let entry be the last (most recently added) element in the list of active
# formatting elements.
// Done already.
# 4. Rewind: If there are no entries before entry in the list of active
# formatting elements, then jump to the step labeled Create.
rewind:
if (count($this->storage) === 1) {
goto create;
}
# 5. Let entry be the entry one earlier than entry in the list of active
# formatting elements.
$entry = prev($this->storage);
# 6. If entry is neither a marker nor an element that is also in the stack of
# open elements, go to the step labeled Rewind.
if (!$entry instanceof ActiveFormattingElementMarker && !in_array($entry['element'], $this->parser->stack)) {
goto rewind;
}
# 7. Advance: Let entry be the element one later than entry in the list of
# active formatting elements.
advance:
$entry = next($this->storage);
# 8. Create: Insert an HTML element for the token for which the element entry
# was created, to obtain new element.
create:
$element = $this->parser->insertElement($entry['token']);
# 9. Replace the entry for entry in the list with an entry for new element.
$this->storage[key($this->storage)]['element'] = $element;
# 10. If the entry for new element in the list of active formatting elements is
# not the last entry in the list, return to the step labeled Advance.
if ($entry !== $this->storage[count($this->storage) - 1]) {
goto advance;
}
}
public function clearToTheLastMarker() {
# When the steps below require the UA to clear the list of active formatting
# elements up to the last marker, the UA must perform the following steps:
# 1. Let entry be the last (most recently added) entry in the list of active
# formatting elements.
# 2. Remove entry from the list of active formatting elements.
# 3. If entry was a marker, then stop the algorithm at this point. The list has
# been cleared up to the last marker.
# 4. Go to step 1.
// Just going to go backwards through the array until a marker is reached. Does
// the same thing.
foreach (array_reverse($this->storage) as $key => $value) {
if ($value instanceof ActiveFormattingElementMarker) {
return;
}
unset($this->storage[$key]);
}
// Reindex the array.
$this->storage = array_values($this->storage);
}
public function __get($property) {
switch ($property) {
case 'lastMarker':

2
lib/Parser.php

@ -171,7 +171,7 @@ class Parser {
$this->insertionMode = static::INITIAL_MODE;
$this->quirksMode = static::QUIRKS_MODE_OFF;
$this->stack = new Stack();
$this->activeFormattingElementsList = new ActiveFormattingElementsList();
$this->activeFormattingElementsList = new ActiveFormattingElementsList($this);
}
public static function parse(string $data, bool $file = false) {

Loading…
Cancel
Save