| 86 |
LI_EL | |
LI_EL | |
| 87 |
P_EL | |
P_EL | |
| 88 |
|
|
| 89 |
|
## ISSUE: option, optgroup, rt, rp? |
| 90 |
|
|
| 91 |
BODY_EL | |
BODY_EL | |
| 92 |
HTML_EL | |
HTML_EL | |
| 93 |
TABLE_CELL_EL | |
TABLE_CELL_EL | |
| 132 |
FORM_EL | |
FORM_EL | |
| 133 |
FRAMESET_EL | |
FRAMESET_EL | |
| 134 |
HEADING_EL | |
HEADING_EL | |
|
OPTION_EL | |
|
|
OPTGROUP_EL | |
|
| 135 |
SELECT_EL | |
SELECT_EL | |
| 136 |
TABLE_ROW_EL | |
TABLE_ROW_EL | |
| 137 |
TABLE_ROW_GROUP_EL | |
TABLE_ROW_GROUP_EL | |
| 249 |
mtext => FOREIGN_FLOW_CONTENT_EL, |
mtext => FOREIGN_FLOW_CONTENT_EL, |
| 250 |
}, |
}, |
| 251 |
$SVG_NS => { |
$SVG_NS => { |
| 252 |
foreignObject => FOREIGN_FLOW_CONTENT_EL, |
foreignObject => FOREIGN_FLOW_CONTENT_EL | MISC_SCOPING_EL, |
| 253 |
desc => FOREIGN_FLOW_CONTENT_EL, |
desc => FOREIGN_FLOW_CONTENT_EL, |
| 254 |
title => FOREIGN_FLOW_CONTENT_EL, |
title => FOREIGN_FLOW_CONTENT_EL, |
| 255 |
}, |
}, |
| 488 |
if (defined $charset_name) { |
if (defined $charset_name) { |
| 489 |
$charset = Message::Charset::Info->get_by_html_name ($charset_name); |
$charset = Message::Charset::Info->get_by_html_name ($charset_name); |
| 490 |
|
|
|
## ISSUE: Unsupported encoding is not ignored according to the spec. |
|
| 491 |
require Whatpm::Charset::DecodeHandle; |
require Whatpm::Charset::DecodeHandle; |
| 492 |
$buffer = Whatpm::Charset::DecodeHandle::ByteBuffer->new |
$buffer = Whatpm::Charset::DecodeHandle::ByteBuffer->new |
| 493 |
($byte_stream); |
($byte_stream); |
| 2484 |
!!!cp (160); |
!!!cp (160); |
| 2485 |
$self->{ct}->{name} = chr $self->{nc}; |
$self->{ct}->{name} = chr $self->{nc}; |
| 2486 |
delete $self->{ct}->{quirks}; |
delete $self->{ct}->{quirks}; |
|
## ISSUE: "Set the token's name name to the" in the spec |
|
| 2487 |
$self->{state} = DOCTYPE_NAME_STATE; |
$self->{state} = DOCTYPE_NAME_STATE; |
| 2488 |
!!!next-input-character; |
!!!next-input-character; |
| 2489 |
redo A; |
redo A; |
| 3783 |
## NOTE: Reprocess the token. |
## NOTE: Reprocess the token. |
| 3784 |
!!!ack-later; |
!!!ack-later; |
| 3785 |
return; ## Go to the "before head" insertion mode. |
return; ## Go to the "before head" insertion mode. |
|
|
|
|
## ISSUE: There is an issue in the spec |
|
| 3786 |
} # B |
} # B |
| 3787 |
|
|
| 3788 |
die "$0: _tree_construction_root_element: This should never be reached"; |
die "$0: _tree_construction_root_element: This should never be reached"; |
| 4518 |
pop @{$self->{open_elements}} |
pop @{$self->{open_elements}} |
| 4519 |
while $self->{open_elements}->[-1]->[1] & FOREIGN_EL; |
while $self->{open_elements}->[-1]->[1] & FOREIGN_EL; |
| 4520 |
|
|
| 4521 |
|
## NOTE: |<span><svg>| ... two parse errors, |<svg>| ... a parse error. |
| 4522 |
|
|
| 4523 |
$self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM; |
$self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM; |
| 4524 |
## Reprocess. |
## Reprocess. |
| 4525 |
next B; |
next B; |
| 4713 |
!!!cp ('t105'); |
!!!cp ('t105'); |
| 4714 |
} |
} |
| 4715 |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
| 4716 |
my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec. |
my $meta_el = pop @{$self->{open_elements}}; |
| 4717 |
|
|
| 4718 |
unless ($self->{confident}) { |
unless ($self->{confident}) { |
| 4719 |
if ($token->{attributes}->{charset}) { |
if ($token->{attributes}->{charset}) { |
| 5170 |
} else { |
} else { |
| 5171 |
die "$0: $token->{type}: Unknown token type"; |
die "$0: $token->{type}: Unknown token type"; |
| 5172 |
} |
} |
|
|
|
|
## ISSUE: An issue in the spec. |
|
| 5173 |
} elsif ($self->{insertion_mode} & BODY_IMS) { |
} elsif ($self->{insertion_mode} & BODY_IMS) { |
| 5174 |
if ($token->{type} == CHARACTER_TOKEN) { |
if ($token->{type} == CHARACTER_TOKEN) { |
| 5175 |
!!!cp ('t150'); |
!!!cp ('t150'); |
| 6797 |
} else { |
} else { |
| 6798 |
die "$0: $token->{type}: Unknown token type"; |
die "$0: $token->{type}: Unknown token type"; |
| 6799 |
} |
} |
|
|
|
|
## ISSUE: An issue in spec here |
|
| 6800 |
} else { |
} else { |
| 6801 |
die "$0: $self->{insertion_mode}: Unknown insertion mode"; |
die "$0: $self->{insertion_mode}: Unknown insertion mode"; |
| 6802 |
} |
} |
| 7058 |
} |
} |
| 7059 |
|
|
| 7060 |
## 5. (a) has a |p| element in scope |
## 5. (a) has a |p| element in scope |
|
## ISSUE: Is this step really necessary? |
|
| 7061 |
INSCOPE: for (reverse @{$self->{open_elements}}) { |
INSCOPE: for (reverse @{$self->{open_elements}}) { |
| 7062 |
if ($_->[1] & P_EL) { |
if ($_->[1] & P_EL) { |
| 7063 |
!!!cp ('t353'); |
!!!cp ('t353'); |
| 7064 |
|
|
| 7065 |
|
## NOTE: |<p><li>|, for example. |
| 7066 |
|
|
| 7067 |
!!!back-token; # <x> |
!!!back-token; # <x> |
| 7068 |
$token = {type => END_TAG_TOKEN, tag_name => 'p', |
$token = {type => END_TAG_TOKEN, tag_name => 'p', |
| 7069 |
line => $token->{line}, column => $token->{column}}; |
line => $token->{line}, column => $token->{column}}; |
| 7140 |
} |
} |
| 7141 |
|
|
| 7142 |
## 5. (a) has a |p| element in scope |
## 5. (a) has a |p| element in scope |
|
## ISSUE: Is this step really necessary? |
|
| 7143 |
INSCOPE: for (reverse @{$self->{open_elements}}) { |
INSCOPE: for (reverse @{$self->{open_elements}}) { |
| 7144 |
if ($_->[1] & P_EL) { |
if ($_->[1] & P_EL) { |
| 7145 |
!!!cp ('t353.1'); |
!!!cp ('t353.1'); |
| 7398 |
} |
} |
| 7399 |
!!!next-token; |
!!!next-token; |
| 7400 |
next B; |
next B; |
| 7401 |
|
} elsif ($token->{tag_name} eq 'optgroup' or |
| 7402 |
|
$token->{tag_name} eq 'option') { |
| 7403 |
|
## has an |option| element in scope |
| 7404 |
|
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 7405 |
|
my $node = $self->{open_elements}->[$_]; |
| 7406 |
|
if ($node->[1] & OPTION_EL) { |
| 7407 |
|
!!!cp ('t397.1'); |
| 7408 |
|
## NOTE: As if </option> |
| 7409 |
|
!!!back-token; # <option> or <optgroup> |
| 7410 |
|
$token = {type => END_TAG_TOKEN, tag_name => 'option', |
| 7411 |
|
line => $token->{line}, column => $token->{column}}; |
| 7412 |
|
next B; |
| 7413 |
|
} elsif ($node->[1] & SCOPING_EL) { |
| 7414 |
|
!!!cp ('t397.2'); |
| 7415 |
|
last INSCOPE; |
| 7416 |
|
} |
| 7417 |
|
} # INSCOPE |
| 7418 |
|
|
| 7419 |
|
$reconstruct_active_formatting_elements->($insert_to_current); |
| 7420 |
|
|
| 7421 |
|
!!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token); |
| 7422 |
|
|
| 7423 |
|
!!!nack ('t397.3'); |
| 7424 |
|
!!!next-token; |
| 7425 |
|
redo B; |
| 7426 |
} elsif ($token->{tag_name} eq 'rt' or |
} elsif ($token->{tag_name} eq 'rt' or |
| 7427 |
$token->{tag_name} eq 'rp') { |
$token->{tag_name} eq 'rp') { |
| 7428 |
## has a |ruby| element in scope |
## has a |ruby| element in scope |
| 7470 |
|
|
| 7471 |
if ($self->{self_closing}) { |
if ($self->{self_closing}) { |
| 7472 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 7473 |
!!!ack ('t398.1'); |
!!!ack ('t398.6'); |
| 7474 |
} else { |
} else { |
| 7475 |
!!!cp ('t398.2'); |
!!!cp ('t398.7'); |
| 7476 |
$self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM; |
$self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM; |
| 7477 |
## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion |
## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion |
| 7478 |
## mode, "in body" (not "in foreign content") secondary insertion |
## mode, "in body" (not "in foreign content") secondary insertion |
| 7483 |
next B; |
next B; |
| 7484 |
} elsif ({ |
} elsif ({ |
| 7485 |
caption => 1, col => 1, colgroup => 1, frame => 1, |
caption => 1, col => 1, colgroup => 1, frame => 1, |
| 7486 |
frameset => 1, head => 1, option => 1, optgroup => 1, |
frameset => 1, head => 1, |
| 7487 |
tbody => 1, td => 1, tfoot => 1, th => 1, |
tbody => 1, td => 1, tfoot => 1, th => 1, |
| 7488 |
thead => 1, tr => 1, |
thead => 1, tr => 1, |
| 7489 |
}->{$token->{tag_name}}) { |
}->{$token->{tag_name}}) { |
| 7494 |
!!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error. |
!!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error. |
| 7495 |
!!!next-token; |
!!!next-token; |
| 7496 |
next B; |
next B; |
| 7497 |
|
} elsif ($token->{tag_name} eq 'param' or |
| 7498 |
## ISSUE: An issue on HTML5 new elements in the spec. |
$token->{tag_name} eq 'source') { |
| 7499 |
|
!!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token); |
| 7500 |
|
pop @{$self->{open_elements}}; |
| 7501 |
|
|
| 7502 |
|
!!!ack ('t398.5'); |
| 7503 |
|
!!!next-token; |
| 7504 |
|
redo B; |
| 7505 |
} else { |
} else { |
| 7506 |
if ($token->{tag_name} eq 'image') { |
if ($token->{tag_name} eq 'image') { |
| 7507 |
!!!cp ('t384'); |
!!!cp ('t384'); |
| 7537 |
!!!ack ('t388.2'); |
!!!ack ('t388.2'); |
| 7538 |
} elsif ({ |
} elsif ({ |
| 7539 |
area => 1, basefont => 1, bgsound => 1, br => 1, |
area => 1, basefont => 1, bgsound => 1, br => 1, |
| 7540 |
embed => 1, img => 1, param => 1, spacer => 1, wbr => 1, |
embed => 1, img => 1, spacer => 1, wbr => 1, |
|
#image => 1, |
|
| 7541 |
}->{$token->{tag_name}}) { |
}->{$token->{tag_name}}) { |
| 7542 |
!!!cp ('t388.1'); |
!!!cp ('t388.1'); |
| 7543 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 7578 |
} |
} |
| 7579 |
} |
} |
| 7580 |
|
|
| 7581 |
!!!parse-error (type => 'start tag not allowed', |
## NOTE: |<marquee></body>|, |<svg><foreignobject></body>| |
| 7582 |
|
|
| 7583 |
|
!!!parse-error (type => 'unmatched end tag', |
| 7584 |
text => $token->{tag_name}, token => $token); |
text => $token->{tag_name}, token => $token); |
| 7585 |
## NOTE: Ignore the token. |
## NOTE: Ignore the token. |
| 7586 |
!!!next-token; |
!!!next-token; |
| 7607 |
## up-to-date, though it has same effect as speced. |
## up-to-date, though it has same effect as speced. |
| 7608 |
if (@{$self->{open_elements}} > 1 and |
if (@{$self->{open_elements}} > 1 and |
| 7609 |
$self->{open_elements}->[1]->[1] & BODY_EL) { |
$self->{open_elements}->[1]->[1] & BODY_EL) { |
|
## ISSUE: There is an issue in the spec. |
|
| 7610 |
unless ($self->{open_elements}->[-1]->[1] & BODY_EL) { |
unless ($self->{open_elements}->[-1]->[1] & BODY_EL) { |
| 7611 |
!!!cp ('t406'); |
!!!cp ('t406'); |
| 7612 |
!!!parse-error (type => 'not closed', |
!!!parse-error (type => 'not closed', |
| 7642 |
|
|
| 7643 |
applet => 1, button => 1, marquee => 1, object => 1, |
applet => 1, button => 1, marquee => 1, object => 1, |
| 7644 |
}->{$token->{tag_name}}) { |
}->{$token->{tag_name}}) { |
| 7645 |
|
## NOTE: Code for <li> start tags includes "as if </li>" code. |
| 7646 |
|
## Code for <dt> or <dd> start tags includes "as if </dt> or |
| 7647 |
|
## </dd>" code. |
| 7648 |
|
|
| 7649 |
## has an element in scope |
## has an element in scope |
| 7650 |
my $i; |
my $i; |
| 7651 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 7804 |
## NOTE: As normal, except </p> implies <p> and ... |
## NOTE: As normal, except </p> implies <p> and ... |
| 7805 |
|
|
| 7806 |
## has an element in scope |
## has an element in scope |
| 7807 |
|
my $non_optional; |
| 7808 |
my $i; |
my $i; |
| 7809 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 7810 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 7815 |
} elsif ($node->[1] & SCOPING_EL) { |
} elsif ($node->[1] & SCOPING_EL) { |
| 7816 |
!!!cp ('t411.1'); |
!!!cp ('t411.1'); |
| 7817 |
last INSCOPE; |
last INSCOPE; |
| 7818 |
|
} elsif ($node->[1] & END_TAG_OPTIONAL_EL) { |
| 7819 |
|
## NOTE: |END_TAG_OPTIONAL_EL| includes "p" |
| 7820 |
|
!!!cp ('t411.2'); |
| 7821 |
|
# |
| 7822 |
|
} else { |
| 7823 |
|
!!!cp ('t411.3'); |
| 7824 |
|
$non_optional ||= $node; |
| 7825 |
|
# |
| 7826 |
} |
} |
| 7827 |
} # INSCOPE |
} # INSCOPE |
| 7828 |
|
|
| 7829 |
if (defined $i) { |
if (defined $i) { |
| 7830 |
if ($self->{open_elements}->[-1]->[0]->manakai_local_name |
## 1. Generate implied end tags |
| 7831 |
ne $token->{tag_name}) { |
# |
| 7832 |
|
|
| 7833 |
|
## 2. If current node != "p", parse error |
| 7834 |
|
if ($non_optional) { |
| 7835 |
!!!cp ('t412.1'); |
!!!cp ('t412.1'); |
| 7836 |
!!!parse-error (type => 'not closed', |
!!!parse-error (type => 'not closed', |
| 7837 |
text => $self->{open_elements}->[-1]->[0] |
text => $non_optional->[0]->manakai_local_name, |
|
->manakai_local_name, |
|
| 7838 |
token => $token); |
token => $token); |
| 7839 |
} else { |
} else { |
| 7840 |
!!!cp ('t414.1'); |
!!!cp ('t414.1'); |
| 7841 |
} |
} |
| 7842 |
|
|
| 7843 |
|
## 3. Pop |
| 7844 |
splice @{$self->{open_elements}}, $i; |
splice @{$self->{open_elements}}, $i; |
| 7845 |
} else { |
} else { |
| 7846 |
!!!cp ('t413.1'); |
!!!cp ('t413.1'); |
| 7881 |
## Ignore the token. |
## Ignore the token. |
| 7882 |
!!!next-token; |
!!!next-token; |
| 7883 |
next B; |
next B; |
|
} elsif ({ |
|
|
caption => 1, col => 1, colgroup => 1, frame => 1, |
|
|
frameset => 1, head => 1, option => 1, optgroup => 1, |
|
|
tbody => 1, td => 1, tfoot => 1, th => 1, |
|
|
thead => 1, tr => 1, |
|
|
area => 1, basefont => 1, bgsound => 1, |
|
|
embed => 1, hr => 1, iframe => 1, image => 1, |
|
|
img => 1, input => 1, isindex => 1, noembed => 1, |
|
|
noframes => 1, param => 1, select => 1, spacer => 1, |
|
|
table => 1, textarea => 1, wbr => 1, |
|
|
noscript => 0, ## TODO: if scripting is enabled |
|
|
}->{$token->{tag_name}}) { |
|
|
!!!cp ('t429'); |
|
|
!!!parse-error (type => 'unmatched end tag', |
|
|
text => $token->{tag_name}, token => $token); |
|
|
## Ignore the token |
|
|
!!!next-token; |
|
|
next B; |
|
| 7884 |
} else { |
} else { |
| 7885 |
if ($token->{tag_name} eq 'sarcasm') { |
if ($token->{tag_name} eq 'sarcasm') { |
| 7886 |
sleep 0.001; # take a deep breath |
sleep 0.001; # take a deep breath |
| 7892 |
|
|
| 7893 |
## Step 2 |
## Step 2 |
| 7894 |
S2: { |
S2: { |
| 7895 |
if ($node->[0]->manakai_local_name eq $token->{tag_name}) { |
my $node_tag_name = $node->[0]->manakai_local_name; |
| 7896 |
|
$node_tag_name =~ tr/A-Z/a-z/; # for SVG camelCase tag names |
| 7897 |
|
if ($node_tag_name eq $token->{tag_name}) { |
| 7898 |
## Step 1 |
## Step 1 |
| 7899 |
## generate implied end tags |
## generate implied end tags |
| 7900 |
while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) { |
while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) { |
| 7907 |
} |
} |
| 7908 |
|
|
| 7909 |
## Step 2 |
## Step 2 |
| 7910 |
if ($self->{open_elements}->[-1]->[0]->manakai_local_name |
my $current_tag_name |
| 7911 |
ne $token->{tag_name}) { |
= $self->{open_elements}->[-1]->[0]->manakai_local_name; |
| 7912 |
|
$current_tag_name =~ tr/A-Z/a-z/; |
| 7913 |
|
if ($current_tag_name ne $token->{tag_name}) { |
| 7914 |
!!!cp ('t431'); |
!!!cp ('t431'); |
| 7915 |
## NOTE: <x><y></x> |
## NOTE: <x><y></x> |
| 7916 |
!!!parse-error (type => 'not closed', |
!!!parse-error (type => 'not closed', |