| 2489 |
## reprocess |
## reprocess |
| 2490 |
!!!ack-later; |
!!!ack-later; |
| 2491 |
next B; |
next B; |
| 2492 |
} elsif ($token->{type} == END_TAG_TOKEN) { |
} elsif ($token->{type} == END_TAG_TOKEN) { |
| 2493 |
if ($token->{tag_name} eq 'head') { |
## "Before head", "in head", and "after head" insertion modes |
| 2494 |
if ($self->{insertion_mode} == BEFORE_HEAD_IM) { |
## ignore most of end tags. Exceptions are "body", "html", |
| 2495 |
!!!cp ('t132'); |
## and "br" end tags. "Before head" and "in head" insertion |
| 2496 |
## As if <head> |
## modes also recognize "head" end tag. "In head noscript" |
| 2497 |
!!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token); |
## insertion modes ignore end tags except for "noscript" and |
| 2498 |
$self->{open_elements}->[-1]->[0]->append_child ($self->{head_element}); |
## "br". |
|
push @{$self->{open_elements}}, |
|
|
[$self->{head_element}, $el_category->{head}]; |
|
| 2499 |
|
|
| 2500 |
## Reprocess in the "in head" insertion mode... |
if ($token->{tag_name} eq 'head') { |
| 2501 |
pop @{$self->{open_elements}}; |
if ($self->{insertion_mode} == BEFORE_HEAD_IM) { |
| 2502 |
$self->{insertion_mode} = AFTER_HEAD_IM; |
!!!cp ('t132'); |
| 2503 |
!!!next-token; |
## As if <head> |
| 2504 |
next B; |
!!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token); |
| 2505 |
} elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
$self->{open_elements}->[-1]->[0]->append_child ($self->{head_element}); |
| 2506 |
!!!cp ('t133'); |
push @{$self->{open_elements}}, |
| 2507 |
## As if </noscript> |
[$self->{head_element}, $el_category->{head}]; |
| 2508 |
pop @{$self->{open_elements}}; |
|
| 2509 |
!!!parse-error (type => 'in noscript:/', |
## Reprocess in the "in head" insertion mode... |
| 2510 |
text => 'head', token => $token); |
pop @{$self->{open_elements}}; |
| 2511 |
|
$self->{insertion_mode} = AFTER_HEAD_IM; |
| 2512 |
## Reprocess in the "in head" insertion mode... |
!!!next-token; |
| 2513 |
pop @{$self->{open_elements}}; |
next B; |
| 2514 |
$self->{insertion_mode} = AFTER_HEAD_IM; |
} elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
| 2515 |
!!!next-token; |
!!!cp ('t133'); |
| 2516 |
next B; |
# |
| 2517 |
} elsif ($self->{insertion_mode} == IN_HEAD_IM) { |
} elsif ($self->{insertion_mode} == IN_HEAD_IM) { |
| 2518 |
!!!cp ('t134'); |
!!!cp ('t134'); |
| 2519 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 2520 |
$self->{insertion_mode} = AFTER_HEAD_IM; |
$self->{insertion_mode} = AFTER_HEAD_IM; |
| 2521 |
!!!next-token; |
!!!next-token; |
| 2522 |
next B; |
next B; |
| 2523 |
} elsif ($self->{insertion_mode} == AFTER_HEAD_IM) { |
} elsif ($self->{insertion_mode} == AFTER_HEAD_IM) { |
| 2524 |
!!!cp ('t134.1'); |
!!!cp ('t134.1'); |
| 2525 |
!!!parse-error (type => 'unmatched end tag', text => 'head', |
# |
| 2526 |
token => $token); |
} else { |
| 2527 |
## Ignore the token |
die "$0: $self->{insertion_mode}: Unknown insertion mode"; |
| 2528 |
!!!next-token; |
} |
| 2529 |
next B; |
} elsif ($token->{tag_name} eq 'noscript') { |
| 2530 |
} else { |
if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
| 2531 |
die "$0: $self->{insertion_mode}: Unknown insertion mode"; |
!!!cp ('t136'); |
| 2532 |
} |
pop @{$self->{open_elements}}; |
| 2533 |
} elsif ($token->{tag_name} eq 'noscript') { |
$self->{insertion_mode} = IN_HEAD_IM; |
| 2534 |
if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
!!!next-token; |
| 2535 |
!!!cp ('t136'); |
next B; |
| 2536 |
pop @{$self->{open_elements}}; |
} else { |
| 2537 |
$self->{insertion_mode} = IN_HEAD_IM; |
!!!cp ('t138'); |
| 2538 |
!!!next-token; |
# |
| 2539 |
next B; |
} |
| 2540 |
} elsif ($self->{insertion_mode} == BEFORE_HEAD_IM or |
} elsif ({ |
| 2541 |
$self->{insertion_mode} == AFTER_HEAD_IM) { |
body => ($self->{insertion_mode} != IN_HEAD_NOSCRIPT_IM), |
| 2542 |
!!!cp ('t137'); |
html => ($self->{insertion_mode} != IN_HEAD_NOSCRIPT_IM), |
| 2543 |
!!!parse-error (type => 'unmatched end tag', |
br => 1, |
| 2544 |
text => 'noscript', token => $token); |
}->{$token->{tag_name}}) { |
|
## Ignore the token ## ISSUE: An issue in the spec. |
|
|
!!!next-token; |
|
|
next B; |
|
|
} else { |
|
|
!!!cp ('t138'); |
|
|
# |
|
|
} |
|
|
} elsif ({ |
|
|
body => 1, html => 1, |
|
|
}->{$token->{tag_name}}) { |
|
|
## TODO: This branch is entirely redundant. |
|
|
if ($self->{insertion_mode} == BEFORE_HEAD_IM or |
|
|
$self->{insertion_mode} == IN_HEAD_IM or |
|
|
$self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
|
|
!!!cp ('t140'); |
|
|
!!!parse-error (type => 'unmatched end tag', |
|
|
text => $token->{tag_name}, token => $token); |
|
|
## Ignore the token |
|
|
!!!next-token; |
|
|
next B; |
|
|
} elsif ($self->{insertion_mode} == AFTER_HEAD_IM) { |
|
|
!!!cp ('t140.1'); |
|
|
!!!parse-error (type => 'unmatched end tag', |
|
|
text => $token->{tag_name}, token => $token); |
|
|
## Ignore the token |
|
|
!!!next-token; |
|
|
next B; |
|
|
} else { |
|
|
die "$0: $self->{insertion_mode}: Unknown insertion mode"; |
|
|
} |
|
|
} elsif ($token->{tag_name} eq 'p') { |
|
|
!!!cp ('t142'); |
|
|
!!!parse-error (type => 'unmatched end tag', |
|
|
text => $token->{tag_name}, token => $token); |
|
|
## Ignore the token |
|
|
!!!next-token; |
|
|
next B; |
|
|
} elsif ($token->{tag_name} eq 'br') { |
|
| 2545 |
if ($self->{insertion_mode} == BEFORE_HEAD_IM) { |
if ($self->{insertion_mode} == BEFORE_HEAD_IM) { |
| 2546 |
!!!cp ('t142.2'); |
!!!cp ('t142.2'); |
| 2547 |
## (before head) as if <head>, (in head) as if </head> |
## (before head) as if <head>, (in head) as if </head> |
| 2561 |
!!!cp ('t143.3'); |
!!!cp ('t143.3'); |
| 2562 |
## NOTE: Two parse errors for <head><noscript></br> |
## NOTE: Two parse errors for <head><noscript></br> |
| 2563 |
!!!parse-error (type => 'unmatched end tag', |
!!!parse-error (type => 'unmatched end tag', |
| 2564 |
text => 'br', token => $token); |
text => $token->{tag_name}, token => $token); |
| 2565 |
## As if </noscript> |
## As if </noscript> |
| 2566 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 2567 |
$self->{insertion_mode} = IN_HEAD_IM; |
$self->{insertion_mode} = IN_HEAD_IM; |
| 2579 |
die "$0: $self->{insertion_mode}: Unknown insertion mode"; |
die "$0: $self->{insertion_mode}: Unknown insertion mode"; |
| 2580 |
} |
} |
| 2581 |
|
|
| 2582 |
# |
## "after head" insertion mode |
| 2583 |
} else { ## Other end tags |
## As if <body> |
| 2584 |
!!!cp ('t145'); |
!!!insert-element ('body',, $token); |
| 2585 |
!!!parse-error (type => 'unmatched end tag', |
$self->{insertion_mode} = IN_BODY_IM; |
| 2586 |
text => $token->{tag_name}, token => $token); |
## Reprocess. |
| 2587 |
## Ignore the token |
next B; |
| 2588 |
!!!next-token; |
} |
|
next B; |
|
|
} |
|
|
|
|
|
if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
|
|
!!!cp ('t146'); |
|
|
## As if </noscript> |
|
|
pop @{$self->{open_elements}}; |
|
|
!!!parse-error (type => 'in noscript:/', |
|
|
text => $token->{tag_name}, token => $token); |
|
|
|
|
|
## Reprocess in the "in head" insertion mode... |
|
|
## As if </head> |
|
|
pop @{$self->{open_elements}}; |
|
|
|
|
|
## Reprocess in the "after head" insertion mode... |
|
|
} elsif ($self->{insertion_mode} == IN_HEAD_IM) { |
|
|
!!!cp ('t147'); |
|
|
## As if </head> |
|
|
pop @{$self->{open_elements}}; |
|
|
|
|
|
## Reprocess in the "after head" insertion mode... |
|
|
} elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) { |
|
|
## ISSUE: This case cannot be reached? |
|
|
!!!cp ('t148'); |
|
|
!!!parse-error (type => 'unmatched end tag', |
|
|
text => $token->{tag_name}, token => $token); |
|
|
## Ignore the token ## ISSUE: An issue in the spec. |
|
|
!!!next-token; |
|
|
next B; |
|
|
} else { |
|
|
!!!cp ('t149'); |
|
|
} |
|
| 2589 |
|
|
| 2590 |
## "after head" insertion mode |
## End tags are ignored by default. |
| 2591 |
## As if <body> |
!!!cp ('t145'); |
| 2592 |
!!!insert-element ('body',, $token); |
!!!parse-error (type => 'unmatched end tag', |
| 2593 |
$self->{insertion_mode} = IN_BODY_IM; |
text => $token->{tag_name}, token => $token); |
| 2594 |
## reprocess |
## Ignore the token. |
| 2595 |
|
!!!next-token; |
| 2596 |
next B; |
next B; |
| 2597 |
} elsif ($token->{type} == END_OF_FILE_TOKEN) { |
} elsif ($token->{type} == END_OF_FILE_TOKEN) { |
| 2598 |
if ($self->{insertion_mode} == BEFORE_HEAD_IM) { |
if ($self->{insertion_mode} == BEFORE_HEAD_IM) { |
| 4430 |
!!!cp ('t386'); |
!!!cp ('t386'); |
| 4431 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 4432 |
|
|
| 4433 |
!!!nack ('t386.1'); |
!!!ack ('t386.1'); |
| 4434 |
!!!next-token; |
!!!next-token; |
| 4435 |
} else { |
} else { |
| 4436 |
!!!nack ('t347.1'); |
!!!nack ('t347.1'); |
| 4986 |
next B; |
next B; |
| 4987 |
} |
} |
| 4988 |
} elsif ($token->{type} == END_TAG_TOKEN) { |
} elsif ($token->{type} == END_TAG_TOKEN) { |
| 4989 |
if ($token->{tag_name} eq 'body') { |
if ($token->{tag_name} eq 'body' or $token->{tag_name} eq 'html') { |
| 4990 |
|
|
| 4991 |
## 1. If not "have an element in scope": |
## 1. If not "have an element in scope": |
| 4992 |
## "has a |body| element in scope" |
## "has a |body| element in scope" |
| 5003 |
} |
} |
| 5004 |
} |
} |
| 5005 |
|
|
| 5006 |
## NOTE: |<marquee></body>|, |<svg><foreignobject></body>| |
## NOTE: |<marquee></body>|, |<svg><foreignobject></body>|, |
| 5007 |
|
## and fragment cases. |
| 5008 |
|
|
| 5009 |
!!!parse-error (type => 'unmatched end tag', |
!!!parse-error (type => 'unmatched end tag', |
| 5010 |
text => $token->{tag_name}, token => $token); |
text => $token->{tag_name}, token => $token); |
| 5011 |
## NOTE: Ignore the token. |
## Ignore the token. (</body> or </html>) |
| 5012 |
!!!next-token; |
!!!next-token; |
| 5013 |
next B; |
next B; |
| 5014 |
} # INSCOPE |
} # INSCOPE |
| 5031 |
|
|
| 5032 |
## 3. Switch the insertion mode. |
## 3. Switch the insertion mode. |
| 5033 |
$self->{insertion_mode} = AFTER_BODY_IM; |
$self->{insertion_mode} = AFTER_BODY_IM; |
| 5034 |
!!!next-token; |
if ($token->{tag_name} eq 'body') { |
|
next B; |
|
|
} elsif ($token->{tag_name} eq 'html') { |
|
|
## TODO: Update this code. It seems that the code below is not |
|
|
## up-to-date, though it has same effect as speced. |
|
|
if (@{$self->{open_elements}} > 1 and |
|
|
$self->{open_elements}->[1]->[1] == BODY_EL) { |
|
|
unless ($self->{open_elements}->[-1]->[1] == BODY_EL) { |
|
|
!!!cp ('t406'); |
|
|
!!!parse-error (type => 'not closed', |
|
|
text => $self->{open_elements}->[1]->[0] |
|
|
->manakai_local_name, |
|
|
token => $token); |
|
|
} else { |
|
|
!!!cp ('t407'); |
|
|
} |
|
|
$self->{insertion_mode} = AFTER_BODY_IM; |
|
|
## reprocess |
|
|
next B; |
|
|
} else { |
|
|
!!!cp ('t408'); |
|
|
!!!parse-error (type => 'unmatched end tag', |
|
|
text => $token->{tag_name}, token => $token); |
|
|
## Ignore the token |
|
| 5035 |
!!!next-token; |
!!!next-token; |
| 5036 |
next B; |
} else { # html |
| 5037 |
|
## Reprocess. |
| 5038 |
} |
} |
| 5039 |
|
next B; |
| 5040 |
} elsif ({ |
} elsif ({ |
| 5041 |
## NOTE: End tags for non-phrasing flow content elements |
## NOTE: End tags for non-phrasing flow content elements |
| 5042 |
|
|