8000 Implement r3769 for PHP. I fudged the refactoring of "in scope" that… · html5lib/html5lib-php@6f0af54 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6f0af54

Browse files
committed
Implement r3769 for PHP. I fudged the refactoring of "in scope" that Hixie did.
1 parent 8e27661 commit 6f0af54

File tree

2 files changed

+57
-20
lines changed

2 files changed

+57
-20
lines changed

SPEC

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
3768
1+
3769
22

33
This is the last revision of the spec this library has been audited against.
44

library/HTML5/TreeBuilder.php

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ private function strConst($number) {
139139
const NS_XML = 'http://www.w3.org/XML/1998/namespace';
140140
const NS_XMLNS = 'http://www.w3.org/2000/xmlns/';
141141

142+
// Different types of scopes to test for elements
143+
const SCOPE = 0;
144+
const SCOPE_LISTITEM = 1;
145+
const SCOPE_TABLE = 2;
146+
142147
public function __construct() {
143148
$this->mode = self::INITIAL;
144149
$this->dom = new DOMDocument;
@@ -1575,8 +1580,31 @@ public function emitToken($token, $mode = null) {
15751580
}
15761581
break;
15771582

1583+
/* An end tag whose tag name is "li" */
1584+
case 'li':
1585+
/* If the stack of open elements does not have an element
1586+
* in list item scope with the same tag name as that of the
1587+
* token, then this is a parse error; ignore the token. */
1588+
if ($this->elementInScope($token['name'], self::SCOPE_LISTITEM)) {
1589+
/* Generate implied end tags, except for elements with the
1590+
* same tag name as the token. */
1591+
$this->generateImpliedEndTags(array($token['name']));
1592+
/* If the current node is not an element with the same tag
1593+
* name as that of the token, then this is a parse error. */
1594+
// XERROR: parse error
1595+
/* Pop elements from the stack of open elements until an
1596+
* element with the same tag name as the token has been
1597+
* popped from the stack. */
1598+
do {
1599+
$node = array_pop($this->stack);
1600+
} while ($node->tagName !== $token['name']);
1601+
} else {
1602+
// XERROR: parse error
1603+
}
1604+
break;
1605+
15781606
/* An end tag whose tag name is "dd", "dt", or "li" */
1579-
case 'dd': case 'dt': case 'li':
1607+
case 'dd': case 'dt':
15801608
if($this->elementInScope($token['name'])) {
15811609
$this->generateImpliedEndTags(array($token['name']));
15821610

@@ -1592,7 +1620,7 @@ public function emitToken($token, $mode = null) {
15921620
} while ($node->tagName !== $token['name']);
15931621

15941622
} else {
1595-
// parse error
1623+
// XERROR: parse error
15961624
}
15971625
break;
15981626

@@ -2073,7 +2101,7 @@ public function emitToken($token, $mode = null) {
20732101
/* If the stack of open elements does not have an element in table
20742102
scope with the same tag name as the token, this is a parse error.
20752103
Ignore the token. (fragment case) */
2076-
if(!$this->elementInScope($token['name'], true)) {
2104+
if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
20772105
$this->ignored = true;
20782106

20792107
/* Otherwise: */
@@ -2185,7 +2213,7 @@ public function emitToken($token, $mode = null) {
21852213
/* If the stack of open elements does not have an element in table
21862214
scope with the same tag name as the token, this is a parse error.
21872215
Ignore the token. (fragment case) */
2188-
if(!$this->elementInScope($token['name'], true)) {
2216+
if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
21892217
$this->ignored = true;
21902218
// Ignore
21912219

@@ -2343,7 +2371,7 @@ public function emitToken($token, $mode = null) {
23432371
/* If the stack of open elements does not have an element in table
23442372
scope with the same tag name as the token, this is a parse error.
23452373
Ignore the token. */
2346-
if(!$this->elementInScope($token['name'], true)) {
2374+
if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
23472375
// Parse error
23482376
$this->ignored = true;
23492377

@@ -2366,7 +2394,7 @@ public function emitToken($token, $mode = null) {
23662394
/* If the stack of open elements does not have a tbody, thead, or
23672395
tfoot element in table scope, this is a parse error. Ignore the
23682396
token. (fragment case) */
2369-
if(!$this->elementInScope(array('tbody', 'thead', 'tfoot'), true)) {
2397+
if(!$this->elementInScope(array('tbody', 'thead', 'tfoot'), self::SCOPE_TABLE)) {
23702398
// parse error
23712399
$this->ignored = true;
23722400

@@ -2423,7 +2451,7 @@ public function emitToken($token, $mode = null) {
24232451
/* If the stack of open elements does not have an element in table
24242452
scope with the same tag name as the token, this is a parse error.
24252453
Ignore the token. (fragment case) */
2426-
if(!$this->elementInScope($token['name'], true)) {
2454+
if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
24272455
// Ignore.
24282456
$this->ignored = true;
24292457

@@ -2458,7 +2486,7 @@ public function emitToken($token, $mode = null) {
24582486
/* If the stack of open elements does not have an element in table
24592487
scope with the same tag name as the token, this is a parse error.
24602488
Ignore the token. */
2461-
if(!$this->elementInScope($token['name'], true)) {
2489+
if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
24622490
$this->ignored = true;
24632491

24642492
/* Otherwise: */
@@ -2494,7 +2522,7 @@ public function emitToken($token, $mode = null) {
24942522
/* If the stack of open elements does not have an element in table
24952523
scope with the same tag name as that of the token, then this is a
24962524
parse error and the token must be ignored. */
2497-
if(!$this->elementInScope($token['name'], true)) {
2525+
if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
24982526
$this->ignored = true;
24992527

25002528
/* Otherwise: */
@@ -2530,7 +2558,7 @@ public function emitToken($token, $mode = null) {
25302558
/* If the stack of open elements does not have a td or th element
25312559
in table scope, then this is a parse error; ignore the token.
25322560
(fragment case) */
2533-
if(!$this->elementInScope(array('td', 'th'), true)) {
2561+
if(!$this->elementInScope(array('td', 'th'), self::SCOPE_TABLE)) {
25342562
// parse error
25352563
$this->ignored = true;
25362564

@@ -2555,7 +2583,7 @@ public function emitToken($token, $mode = null) {
25552583
/* If the stack of open elements does not have a td or th element
25562584
in table scope, then this is a parse error; ignore the token.
25572585
(innerHTML case) */
2558-
if(!$this->elementInScope(array('td', 'th'), true)) {
2586+
if(!$this->elementInScope(array('td', 'th'), self::SCOPE_TABLE)) {
25592587
// Parse error
25602588
$this->ignored = true;
25612589

@@ -2681,7 +2709,7 @@ public function emitToken($token, $mode = null) {
26812709
/* If the stack of open elements does not have an element in table
26822710
scope with the same tag name as the token, this is a parse error.
26832711
Ignore the token. (fragment case) */
2684-
if(!$this->elementInScope($token['name'], true)) {
2712+
if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {
26852713
$this->ignored = true;
26862714
// parse error
26872715

@@ -2752,7 +2780,7 @@ public function emitToken($token, $mode = null) {
27522780
the same tag name as that of the token, then act as if an end tag
27532781
with the tag name "select" had been seen, and reprocess the token.
27542782
Otherwise, ignore the token. */
2755-
if($this->elementInScope($token['name'], true)) {
2783+
if($this->elementInScope($token['name'], self::SCOPE_TABLE)) {
27562784
$this->emitToken(array(
27572785
'name' => 'select',
27582786
'type' => HTML5_Tokenizer::ENDTAG
@@ -3170,10 +3198,10 @@ private function appendToRealParent($node) {
31703198
}
31713199
}
31723200

3173-
private function elementInScope($el, $table = false) {
3201+
private function elementInScope($el, $scope = self::SCOPE) {
31743202
if(is_array($el)) {
31753203
foreach($el as $element) {
3176-
if($this->elementInScope($element, $table)) {
3204+
if($this->elementInScope($element, $scope)) {
31773205
return true;
31783206
}
31793207
}
@@ -3192,16 +3220,25 @@ private function elementInScope($el, $table = false) {
31923220
/* 2. If node is the target node, terminate in a match state. */
31933221
return true;
31943222

3195-
// these are the common states for "in scope" and "in table scope"
3223+
// We've expanded the logic for these states a little differently;
3224+
// Hixie's refactoring into "specific scope" is more general, but
3225+
// this "gets the job done"
3226+
3227+
// these are the common states for all scopes
31963228
} elseif($node->tagName === 'table' || $node->tagName === 'html') {
31973229
return false;
31983230

3199-
// these are only valid for "in scope"
3200-
} elseif(!$table &&
3231+
// these are valid for "in scope" and "in list item scope"
3232+
} elseif($scope !== self::SCOPE_TABLE &&
32013233
(in_array($node->tagName, array('applet', 'caption', 'td',
32023234
'th', 'button', 'marquee', 'object')) ||
32033235
$node->tagName === 'foreignObject' && $node->namespaceURI === self::NS_SVG)) {
32043236
return false;
3237+
3238+
3239+
// these are valid for "in list item scope"
3240+
} elseif($scope === self::SCOPE_LISTITEM && in_array($node->tagName, array('ol', 'ul'))) {
3241+
return false;
32053242
}
32063243

32073244
/* Otherwise, set node to the previous entry in the stack of open
@@ -3461,7 +3498,7 @@ private function closeCell() {
34613498
/* If the stack of open elements has a td or th element in table scope,
34623499
then act as if an end tag token with that tag name had been seen. */
34633500
foreach(array('td', 'th') as $cell) {
3464-
if($this->elementInScope($cell, true)) {
3501+
if($this->elementInScope($cell, self::SCOPE_TABLE)) {
34653502
$this->emitToken(array(
34663503
'name' => $cell,
34673504
'type' => HTML5_Tokenizer::ENDTAG

0 commit comments

Comments
 (0)
0