| 28 |
my $XML_NS = q<http://www.w3.org/XML/1998/namespace>; |
my $XML_NS = q<http://www.w3.org/XML/1998/namespace>; |
| 29 |
my $XMLNS_NS = q<http://www.w3.org/2000/xmlns/>; |
my $XMLNS_NS = q<http://www.w3.org/2000/xmlns/>; |
| 30 |
|
|
| 31 |
sub A_EL () { 0b1 } |
## Bits 12-15 |
| 32 |
sub ADDRESS_EL () { 0b10 } |
sub SPECIAL_EL () { 0b1_000000000000000 } |
| 33 |
sub BODY_EL () { 0b100 } |
sub SCOPING_EL () { 0b1_00000000000000 } |
| 34 |
sub BUTTON_EL () { 0b1000 } |
sub FORMATTING_EL () { 0b1_0000000000000 } |
| 35 |
sub CAPTION_EL () { 0b10000 } |
sub PHRASING_EL () { 0b1_000000000000 } |
| 36 |
sub DD_EL () { 0b100000 } |
|
| 37 |
sub DIV_EL () { 0b1000000 } |
## Bits 10-11 |
| 38 |
sub DT_EL () { 0b10000000 } |
sub FOREIGN_EL () { 0b1_00000000000 } |
| 39 |
sub FORM_EL () { 0b100000000 } |
sub FOREIGN_FLOW_CONTENT_EL () { 0b1_0000000000 } |
| 40 |
sub FORMATTING_EL () { 0b1000000000 } |
|
| 41 |
sub FRAMESET_EL () { 0b10000000000 } |
## Bits 6-9 |
| 42 |
sub HEADING_EL () { 0b100000000000 } |
sub TABLE_SCOPING_EL () { 0b1_000000000 } |
| 43 |
sub HTML_EL () { 0b1000000000000 } |
sub TABLE_ROWS_SCOPING_EL () { 0b1_00000000 } |
| 44 |
sub LI_EL () { 0b10000000000000 } |
sub TABLE_ROW_SCOPING_EL () { 0b1_0000000 } |
| 45 |
sub NOBR_EL () { 0b100000000000000 } |
sub TABLE_ROWS_EL () { 0b1_000000 } |
|
sub OPTION_EL () { 0b1000000000000000 } |
|
|
sub OPTGROUP_EL () { 0b10000000000000000 } |
|
|
sub P_EL () { 0b100000000000000000 } |
|
|
sub SELECT_EL () { 0b1000000000000000000 } |
|
|
sub TABLE_EL () { 0b10000000000000000000 } |
|
|
sub TABLE_CELL_EL () { 0b100000000000000000000 } |
|
|
sub TABLE_ROW_EL () { 0b1000000000000000000000 } |
|
|
sub TABLE_ROW_GROUP_EL () { 0b10000000000000000000000 } |
|
|
sub MISC_SCOPING_EL () { 0b100000000000000000000000 } |
|
|
sub MISC_SPECIAL_EL () { 0b1000000000000000000000000 } |
|
|
sub FOREIGN_EL () { 0b10000000000000000000000000 } |
|
|
sub FOREIGN_FLOW_CONTENT_EL () { 0b100000000000000000000000000 } |
|
|
sub MML_AXML_EL () { 0b1000000000000000000000000000 } |
|
|
sub RUBY_EL () { 0b10000000000000000000000000000 } |
|
|
sub RUBY_COMPONENT_EL () { 0b100000000000000000000000000000 } |
|
|
|
|
|
sub TABLE_ROWS_EL () { |
|
|
TABLE_EL | |
|
|
TABLE_ROW_EL | |
|
|
TABLE_ROW_GROUP_EL |
|
|
} |
|
| 46 |
|
|
| 47 |
## NOTE: Used in "generate implied end tags" algorithm. |
## Bit 5 |
| 48 |
## NOTE: There is a code where a modified version of END_TAG_OPTIONAL_EL |
sub ADDRESS_DIV_P_EL () { 0b1_00000 } |
|
## is used in "generate implied end tags" implementation (search for the |
|
|
## function mae). |
|
|
sub END_TAG_OPTIONAL_EL () { |
|
|
DD_EL | |
|
|
DT_EL | |
|
|
LI_EL | |
|
|
P_EL | |
|
|
RUBY_COMPONENT_EL |
|
|
} |
|
| 49 |
|
|
| 50 |
## NOTE: Used in </body> and EOF algorithms. |
## NOTE: Used in </body> and EOF algorithms. |
| 51 |
sub ALL_END_TAG_OPTIONAL_EL () { |
## Bit 4 |
| 52 |
DD_EL | |
sub ALL_END_TAG_OPTIONAL_EL () { 0b1_0000 } |
|
DT_EL | |
|
|
LI_EL | |
|
|
P_EL | |
|
|
|
|
|
BODY_EL | |
|
|
HTML_EL | |
|
|
TABLE_CELL_EL | |
|
|
TABLE_ROW_EL | |
|
|
TABLE_ROW_GROUP_EL |
|
|
} |
|
| 53 |
|
|
| 54 |
sub SCOPING_EL () { |
## NOTE: Used in "generate implied end tags" algorithm. |
| 55 |
BUTTON_EL | |
## NOTE: There is a code where a modified version of |
| 56 |
CAPTION_EL | |
## END_TAG_OPTIONAL_EL is used in "generate implied end tags" |
| 57 |
HTML_EL | |
## implementation (search for the algorithm name). |
| 58 |
TABLE_EL | |
## Bit 3 |
| 59 |
TABLE_CELL_EL | |
sub END_TAG_OPTIONAL_EL () { 0b1_000 } |
| 60 |
MISC_SCOPING_EL |
|
| 61 |
|
## Bits 0-2 |
| 62 |
|
|
| 63 |
|
sub MISC_SPECIAL_EL () { SPECIAL_EL | 0b000 } |
| 64 |
|
sub FORM_EL () { SPECIAL_EL | 0b001 } |
| 65 |
|
sub FRAMESET_EL () { SPECIAL_EL | 0b010 } |
| 66 |
|
sub HEADING_EL () { SPECIAL_EL | 0b011 } |
| 67 |
|
sub SELECT_EL () { SPECIAL_EL | 0b100 } |
| 68 |
|
sub SCRIPT_EL () { SPECIAL_EL | 0b101 } |
| 69 |
|
|
| 70 |
|
sub ADDRESS_DIV_EL () { SPECIAL_EL | ADDRESS_DIV_P_EL | 0b001 } |
| 71 |
|
sub BODY_EL () { SPECIAL_EL | ALL_END_TAG_OPTIONAL_EL | 0b001 } |
| 72 |
|
|
| 73 |
|
sub DTDD_EL () { |
| 74 |
|
SPECIAL_EL | |
| 75 |
|
END_TAG_OPTIONAL_EL | |
| 76 |
|
ALL_END_TAG_OPTIONAL_EL | |
| 77 |
|
0b010 |
| 78 |
} |
} |
| 79 |
|
sub LI_EL () { |
| 80 |
sub TABLE_SCOPING_EL () { |
SPECIAL_EL | |
| 81 |
HTML_EL | |
END_TAG_OPTIONAL_EL | |
| 82 |
TABLE_EL |
ALL_END_TAG_OPTIONAL_EL | |
| 83 |
|
0b100 |
| 84 |
} |
} |
| 85 |
|
sub P_EL () { |
| 86 |
sub TABLE_ROWS_SCOPING_EL () { |
SPECIAL_EL | |
| 87 |
HTML_EL | |
ADDRESS_DIV_P_EL | |
| 88 |
TABLE_ROW_GROUP_EL |
END_TAG_OPTIONAL_EL | |
| 89 |
|
ALL_END_TAG_OPTIONAL_EL | |
| 90 |
|
0b001 |
| 91 |
} |
} |
| 92 |
|
|
| 93 |
sub TABLE_ROW_SCOPING_EL () { |
sub TABLE_ROW_EL () { |
| 94 |
HTML_EL | |
SPECIAL_EL | |
| 95 |
TABLE_ROW_EL |
TABLE_ROWS_EL | |
| 96 |
|
TABLE_ROW_SCOPING_EL | |
| 97 |
|
ALL_END_TAG_OPTIONAL_EL | |
| 98 |
|
0b001 |
| 99 |
|
} |
| 100 |
|
sub TABLE_ROW_GROUP_EL () { |
| 101 |
|
SPECIAL_EL | |
| 102 |
|
TABLE_ROWS_EL | |
| 103 |
|
TABLE_ROWS_SCOPING_EL | |
| 104 |
|
ALL_END_TAG_OPTIONAL_EL | |
| 105 |
|
0b001 |
| 106 |
} |
} |
| 107 |
|
|
| 108 |
sub SPECIAL_EL () { |
sub MISC_SCOPING_EL () { SCOPING_EL | 0b000 } |
| 109 |
ADDRESS_EL | |
sub BUTTON_EL () { SCOPING_EL | 0b001 } |
| 110 |
BODY_EL | |
sub CAPTION_EL () { SCOPING_EL | 0b010 } |
| 111 |
DIV_EL | |
sub HTML_EL () { |
| 112 |
|
SCOPING_EL | |
| 113 |
DD_EL | |
TABLE_SCOPING_EL | |
| 114 |
DT_EL | |
TABLE_ROWS_SCOPING_EL | |
| 115 |
LI_EL | |
TABLE_ROW_SCOPING_EL | |
| 116 |
P_EL | |
ALL_END_TAG_OPTIONAL_EL | |
| 117 |
|
0b001 |
| 118 |
FORM_EL | |
} |
| 119 |
FRAMESET_EL | |
sub TABLE_EL () { |
| 120 |
HEADING_EL | |
SCOPING_EL | |
| 121 |
OPTION_EL | |
TABLE_ROWS_EL | |
| 122 |
OPTGROUP_EL | |
TABLE_SCOPING_EL | |
| 123 |
SELECT_EL | |
0b001 |
|
TABLE_ROW_EL | |
|
|
TABLE_ROW_GROUP_EL | |
|
|
MISC_SPECIAL_EL |
|
| 124 |
} |
} |
| 125 |
|
sub TABLE_CELL_EL () { |
| 126 |
|
SCOPING_EL | |
| 127 |
|
TABLE_ROW_SCOPING_EL | |
| 128 |
|
ALL_END_TAG_OPTIONAL_EL | |
| 129 |
|
0b001 |
| 130 |
|
} |
| 131 |
|
|
| 132 |
|
sub MISC_FORMATTING_EL () { FORMATTING_EL | 0b000 } |
| 133 |
|
sub A_EL () { FORMATTING_EL | 0b001 } |
| 134 |
|
sub NOBR_EL () { FORMATTING_EL | 0b010 } |
| 135 |
|
|
| 136 |
|
sub RUBY_EL () { PHRASING_EL | 0b001 } |
| 137 |
|
|
| 138 |
|
## ISSUE: ALL_END_TAG_OPTIONAL_EL? |
| 139 |
|
sub OPTGROUP_EL () { PHRASING_EL | END_TAG_OPTIONAL_EL | 0b001 } |
| 140 |
|
sub OPTION_EL () { PHRASING_EL | END_TAG_OPTIONAL_EL | 0b010 } |
| 141 |
|
sub RUBY_COMPONENT_EL () { PHRASING_EL | END_TAG_OPTIONAL_EL | 0b100 } |
| 142 |
|
|
| 143 |
|
sub MML_AXML_EL () { PHRASING_EL | FOREIGN_EL | 0b001 } |
| 144 |
|
|
| 145 |
my $el_category = { |
my $el_category = { |
| 146 |
a => A_EL | FORMATTING_EL, |
a => A_EL, |
| 147 |
address => ADDRESS_EL, |
address => ADDRESS_DIV_EL, |
| 148 |
applet => MISC_SCOPING_EL, |
applet => MISC_SCOPING_EL, |
| 149 |
area => MISC_SPECIAL_EL, |
area => MISC_SPECIAL_EL, |
| 150 |
|
article => MISC_SPECIAL_EL, |
| 151 |
|
aside => MISC_SPECIAL_EL, |
| 152 |
b => FORMATTING_EL, |
b => FORMATTING_EL, |
| 153 |
base => MISC_SPECIAL_EL, |
base => MISC_SPECIAL_EL, |
| 154 |
basefont => MISC_SPECIAL_EL, |
basefont => MISC_SPECIAL_EL, |
| 162 |
center => MISC_SPECIAL_EL, |
center => MISC_SPECIAL_EL, |
| 163 |
col => MISC_SPECIAL_EL, |
col => MISC_SPECIAL_EL, |
| 164 |
colgroup => MISC_SPECIAL_EL, |
colgroup => MISC_SPECIAL_EL, |
| 165 |
dd => DD_EL, |
command => MISC_SPECIAL_EL, |
| 166 |
|
datagrid => MISC_SPECIAL_EL, |
| 167 |
|
dd => DTDD_EL, |
| 168 |
|
details => MISC_SPECIAL_EL, |
| 169 |
|
dialog => MISC_SPECIAL_EL, |
| 170 |
dir => MISC_SPECIAL_EL, |
dir => MISC_SPECIAL_EL, |
| 171 |
div => DIV_EL, |
div => ADDRESS_DIV_EL, |
| 172 |
dl => MISC_SPECIAL_EL, |
dl => MISC_SPECIAL_EL, |
| 173 |
dt => DT_EL, |
dt => DTDD_EL, |
| 174 |
em => FORMATTING_EL, |
em => FORMATTING_EL, |
| 175 |
embed => MISC_SPECIAL_EL, |
embed => MISC_SPECIAL_EL, |
| 176 |
|
eventsource => MISC_SPECIAL_EL, |
| 177 |
fieldset => MISC_SPECIAL_EL, |
fieldset => MISC_SPECIAL_EL, |
| 178 |
|
figure => MISC_SPECIAL_EL, |
| 179 |
font => FORMATTING_EL, |
font => FORMATTING_EL, |
| 180 |
|
footer => MISC_SPECIAL_EL, |
| 181 |
form => FORM_EL, |
form => FORM_EL, |
| 182 |
frame => MISC_SPECIAL_EL, |
frame => MISC_SPECIAL_EL, |
| 183 |
frameset => FRAMESET_EL, |
frameset => FRAMESET_EL, |
| 188 |
h5 => HEADING_EL, |
h5 => HEADING_EL, |
| 189 |
h6 => HEADING_EL, |
h6 => HEADING_EL, |
| 190 |
head => MISC_SPECIAL_EL, |
head => MISC_SPECIAL_EL, |
| 191 |
|
header => MISC_SPECIAL_EL, |
| 192 |
hr => MISC_SPECIAL_EL, |
hr => MISC_SPECIAL_EL, |
| 193 |
html => HTML_EL, |
html => HTML_EL, |
| 194 |
i => FORMATTING_EL, |
i => FORMATTING_EL, |
| 195 |
iframe => MISC_SPECIAL_EL, |
iframe => MISC_SPECIAL_EL, |
| 196 |
img => MISC_SPECIAL_EL, |
img => MISC_SPECIAL_EL, |
| 197 |
|
#image => MISC_SPECIAL_EL, ## NOTE: Commented out in the spec. |
| 198 |
input => MISC_SPECIAL_EL, |
input => MISC_SPECIAL_EL, |
| 199 |
isindex => MISC_SPECIAL_EL, |
isindex => MISC_SPECIAL_EL, |
| 200 |
li => LI_EL, |
li => LI_EL, |
| 203 |
marquee => MISC_SCOPING_EL, |
marquee => MISC_SCOPING_EL, |
| 204 |
menu => MISC_SPECIAL_EL, |
menu => MISC_SPECIAL_EL, |
| 205 |
meta => MISC_SPECIAL_EL, |
meta => MISC_SPECIAL_EL, |
| 206 |
nobr => NOBR_EL | FORMATTING_EL, |
nav => MISC_SPECIAL_EL, |
| 207 |
|
nobr => NOBR_EL, |
| 208 |
noembed => MISC_SPECIAL_EL, |
noembed => MISC_SPECIAL_EL, |
| 209 |
noframes => MISC_SPECIAL_EL, |
noframes => MISC_SPECIAL_EL, |
| 210 |
noscript => MISC_SPECIAL_EL, |
noscript => MISC_SPECIAL_EL, |
| 222 |
s => FORMATTING_EL, |
s => FORMATTING_EL, |
| 223 |
script => MISC_SPECIAL_EL, |
script => MISC_SPECIAL_EL, |
| 224 |
select => SELECT_EL, |
select => SELECT_EL, |
| 225 |
|
section => MISC_SPECIAL_EL, |
| 226 |
small => FORMATTING_EL, |
small => FORMATTING_EL, |
| 227 |
spacer => MISC_SPECIAL_EL, |
spacer => MISC_SPECIAL_EL, |
| 228 |
strike => FORMATTING_EL, |
strike => FORMATTING_EL, |
| 246 |
my $el_category_f = { |
my $el_category_f = { |
| 247 |
$MML_NS => { |
$MML_NS => { |
| 248 |
'annotation-xml' => MML_AXML_EL, |
'annotation-xml' => MML_AXML_EL, |
| 249 |
mi => FOREIGN_FLOW_CONTENT_EL, |
mi => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL, |
| 250 |
mo => FOREIGN_FLOW_CONTENT_EL, |
mo => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL, |
| 251 |
mn => FOREIGN_FLOW_CONTENT_EL, |
mn => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL, |
| 252 |
ms => FOREIGN_FLOW_CONTENT_EL, |
ms => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL, |
| 253 |
mtext => FOREIGN_FLOW_CONTENT_EL, |
mtext => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL, |
| 254 |
}, |
}, |
| 255 |
$SVG_NS => { |
$SVG_NS => { |
| 256 |
foreignObject => FOREIGN_FLOW_CONTENT_EL, |
foreignObject => SCOPING_EL | FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL, |
| 257 |
desc => FOREIGN_FLOW_CONTENT_EL, |
desc => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL, |
| 258 |
title => FOREIGN_FLOW_CONTENT_EL, |
title => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL, |
| 259 |
}, |
}, |
| 260 |
## NOTE: In addition, FOREIGN_EL is set to non-HTML elements. |
## NOTE: In addition, FOREIGN_EL is set to non-HTML elements. |
| 261 |
}; |
}; |
| 342 |
|
|
| 343 |
## ISSUE: xmlns:xlink="non-xlink-ns" is not an error. |
## ISSUE: xmlns:xlink="non-xlink-ns" is not an error. |
| 344 |
|
|
| 345 |
my $c1_entity_char = { |
my $charref_map = { |
| 346 |
|
0x0D => 0x000A, |
| 347 |
0x80 => 0x20AC, |
0x80 => 0x20AC, |
| 348 |
0x81 => 0xFFFD, |
0x81 => 0xFFFD, |
| 349 |
0x82 => 0x201A, |
0x82 => 0x201A, |
| 376 |
0x9D => 0xFFFD, |
0x9D => 0xFFFD, |
| 377 |
0x9E => 0x017E, |
0x9E => 0x017E, |
| 378 |
0x9F => 0x0178, |
0x9F => 0x0178, |
| 379 |
}; # $c1_entity_char |
}; # $charref_map |
| 380 |
|
$charref_map->{$_} = 0xFFFD |
| 381 |
|
for 0x0000..0x0008, 0x000B, 0x000E..0x001F, 0x007F, |
| 382 |
|
0xD800..0xDFFF, 0xFDD0..0xFDDF, ## ISSUE: 0xFDEF |
| 383 |
|
0xFFFE, 0xFFFF, 0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF, |
| 384 |
|
0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE, |
| 385 |
|
0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF, |
| 386 |
|
0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, 0xDFFFF, 0xEFFFE, |
| 387 |
|
0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, 0x10FFFF; |
| 388 |
|
|
| 389 |
|
## TODO: Invoke the reset algorithm when a resettable element is |
| 390 |
|
## created (cf. HTML5 revision 2259). |
| 391 |
|
|
| 392 |
sub parse_byte_string ($$$$;$) { |
sub parse_byte_string ($$$$;$) { |
| 393 |
my $self = shift; |
my $self = shift; |
| 432 |
## TODO: Is this ok? Transfer protocol's parameter should be |
## TODO: Is this ok? Transfer protocol's parameter should be |
| 433 |
## interpreted in its semantics? |
## interpreted in its semantics? |
| 434 |
|
|
|
## ISSUE: Unsupported encoding is not ignored according to the spec. |
|
| 435 |
($char_stream, $e_status) = $charset->get_decode_handle |
($char_stream, $e_status) = $charset->get_decode_handle |
| 436 |
($byte_stream, allow_error_reporting => 1, |
($byte_stream, allow_error_reporting => 1, |
| 437 |
allow_fallback => 1); |
allow_fallback => 1); |
| 439 |
$self->{confident} = 1; |
$self->{confident} = 1; |
| 440 |
last SNIFFING; |
last SNIFFING; |
| 441 |
} else { |
} else { |
| 442 |
## TODO: unsupported error |
!!!parse-error (type => 'charset:not supported', |
| 443 |
|
layer => 'encode', |
| 444 |
|
line => 1, column => 1, |
| 445 |
|
value => $charset_name, |
| 446 |
|
level => $self->{level}->{uncertain}); |
| 447 |
} |
} |
| 448 |
} |
} |
| 449 |
|
|
| 492 |
if (defined $charset_name) { |
if (defined $charset_name) { |
| 493 |
$charset = Message::Charset::Info->get_by_html_name ($charset_name); |
$charset = Message::Charset::Info->get_by_html_name ($charset_name); |
| 494 |
|
|
|
## ISSUE: Unsupported encoding is not ignored according to the spec. |
|
| 495 |
require Whatpm::Charset::DecodeHandle; |
require Whatpm::Charset::DecodeHandle; |
| 496 |
$buffer = Whatpm::Charset::DecodeHandle::ByteBuffer->new |
$buffer = Whatpm::Charset::DecodeHandle::ByteBuffer->new |
| 497 |
($byte_stream); |
($byte_stream); |
| 886 |
sub MD_HYPHEN_STATE () { 36 } # "markup declaration open state" in the spec |
sub MD_HYPHEN_STATE () { 36 } # "markup declaration open state" in the spec |
| 887 |
sub MD_DOCTYPE_STATE () { 37 } # "markup declaration open state" in the spec |
sub MD_DOCTYPE_STATE () { 37 } # "markup declaration open state" in the spec |
| 888 |
sub MD_CDATA_STATE () { 38 } # "markup declaration open state" in the spec |
sub MD_CDATA_STATE () { 38 } # "markup declaration open state" in the spec |
| 889 |
sub CDATA_PCDATA_CLOSE_TAG_STATE () { 39 } # "close tag open state" in the spec |
sub CDATA_RCDATA_CLOSE_TAG_STATE () { 39 } # "close tag open state" in the spec |
| 890 |
sub CDATA_SECTION_MSE1_STATE () { 40 } # "CDATA section state" in the spec |
sub CDATA_SECTION_MSE1_STATE () { 40 } # "CDATA section state" in the spec |
| 891 |
sub CDATA_SECTION_MSE2_STATE () { 41 } # "CDATA section state" in the spec |
sub CDATA_SECTION_MSE2_STATE () { 41 } # "CDATA section state" in the spec |
| 892 |
sub PUBLIC_STATE () { 42 } # "after DOCTYPE name state" in the spec |
sub PUBLIC_STATE () { 42 } # "after DOCTYPE name state" in the spec |
| 900 |
sub HEXREF_X_STATE () { 47 } |
sub HEXREF_X_STATE () { 47 } |
| 901 |
sub HEXREF_HEX_STATE () { 48 } |
sub HEXREF_HEX_STATE () { 48 } |
| 902 |
sub ENTITY_NAME_STATE () { 49 } |
sub ENTITY_NAME_STATE () { 49 } |
| 903 |
|
sub PCDATA_STATE () { 50 } # "data state" in the spec |
| 904 |
|
|
| 905 |
sub DOCTYPE_TOKEN () { 1 } |
sub DOCTYPE_TOKEN () { 1 } |
| 906 |
sub COMMENT_TOKEN () { 2 } |
sub COMMENT_TOKEN () { 2 } |
| 922 |
## NOTE: "in foreign content" insertion mode is special; it is combined |
## NOTE: "in foreign content" insertion mode is special; it is combined |
| 923 |
## with the secondary insertion mode. In this parser, they are stored |
## with the secondary insertion mode. In this parser, they are stored |
| 924 |
## together in the bit-or'ed form. |
## together in the bit-or'ed form. |
| 925 |
|
sub IN_CDATA_RCDATA_IM () { 0b1000000000000 } |
| 926 |
|
## NOTE: "in CDATA/RCDATA" insertion mode is also special; it is |
| 927 |
|
## combined with the original insertion mode. In thie parser, |
| 928 |
|
## they are stored together in the bit-or'ed form. |
| 929 |
|
|
| 930 |
## NOTE: "initial" and "before html" insertion modes have no constants. |
## NOTE: "initial" and "before html" insertion modes have no constants. |
| 931 |
|
|
| 1003 |
## TODO: Polytheistic slash SHOULD NOT be used. (Applied only to atheists.) |
## TODO: Polytheistic slash SHOULD NOT be used. (Applied only to atheists.) |
| 1004 |
## (This requirement was dropped from HTML5 spec, unfortunately.) |
## (This requirement was dropped from HTML5 spec, unfortunately.) |
| 1005 |
|
|
| 1006 |
|
my $is_space = { |
| 1007 |
|
0x0009 => 1, # CHARACTER TABULATION (HT) |
| 1008 |
|
0x000A => 1, # LINE FEED (LF) |
| 1009 |
|
#0x000B => 0, # LINE TABULATION (VT) |
| 1010 |
|
0x000C => 1, # FORM FEED (FF) |
| 1011 |
|
#0x000D => 1, # CARRIAGE RETURN (CR) |
| 1012 |
|
0x0020 => 1, # SPACE (SP) |
| 1013 |
|
}; |
| 1014 |
|
|
| 1015 |
sub _get_next_token ($) { |
sub _get_next_token ($) { |
| 1016 |
my $self = shift; |
my $self = shift; |
| 1017 |
|
|
| 1029 |
} |
} |
| 1030 |
|
|
| 1031 |
A: { |
A: { |
| 1032 |
if ($self->{state} == DATA_STATE) { |
if ($self->{state} == PCDATA_STATE) { |
| 1033 |
|
## NOTE: Same as |DATA_STATE|, but only for |PCDATA| content model. |
| 1034 |
|
|
| 1035 |
|
if ($self->{nc} == 0x0026) { # & |
| 1036 |
|
!!!cp (0.1); |
| 1037 |
|
## NOTE: In the spec, the tokenizer is switched to the |
| 1038 |
|
## "entity data state". In this implementation, the tokenizer |
| 1039 |
|
## is switched to the |ENTITY_STATE|, which is an implementation |
| 1040 |
|
## of the "consume a character reference" algorithm. |
| 1041 |
|
$self->{entity_add} = -1; |
| 1042 |
|
$self->{prev_state} = DATA_STATE; |
| 1043 |
|
$self->{state} = ENTITY_STATE; |
| 1044 |
|
!!!next-input-character; |
| 1045 |
|
redo A; |
| 1046 |
|
} elsif ($self->{nc} == 0x003C) { # < |
| 1047 |
|
!!!cp (0.2); |
| 1048 |
|
$self->{state} = TAG_OPEN_STATE; |
| 1049 |
|
!!!next-input-character; |
| 1050 |
|
redo A; |
| 1051 |
|
} elsif ($self->{nc} == -1) { |
| 1052 |
|
!!!cp (0.3); |
| 1053 |
|
!!!emit ({type => END_OF_FILE_TOKEN, |
| 1054 |
|
line => $self->{line}, column => $self->{column}}); |
| 1055 |
|
last A; ## TODO: ok? |
| 1056 |
|
} else { |
| 1057 |
|
!!!cp (0.4); |
| 1058 |
|
# |
| 1059 |
|
} |
| 1060 |
|
|
| 1061 |
|
# Anything else |
| 1062 |
|
my $token = {type => CHARACTER_TOKEN, |
| 1063 |
|
data => chr $self->{nc}, |
| 1064 |
|
line => $self->{line}, column => $self->{column}, |
| 1065 |
|
}; |
| 1066 |
|
$self->{read_until}->($token->{data}, q[<&], length $token->{data}); |
| 1067 |
|
|
| 1068 |
|
## Stay in the state. |
| 1069 |
|
!!!next-input-character; |
| 1070 |
|
!!!emit ($token); |
| 1071 |
|
redo A; |
| 1072 |
|
} elsif ($self->{state} == DATA_STATE) { |
| 1073 |
|
$self->{s_kwd} = '' unless defined $self->{s_kwd}; |
| 1074 |
if ($self->{nc} == 0x0026) { # & |
if ($self->{nc} == 0x0026) { # & |
| 1075 |
delete $self->{s_kwd}; |
$self->{s_kwd} = ''; |
| 1076 |
if ($self->{content_model} & CM_ENTITY and # PCDATA | RCDATA |
if ($self->{content_model} & CM_ENTITY and # PCDATA | RCDATA |
| 1077 |
not $self->{escape}) { |
not $self->{escape}) { |
| 1078 |
!!!cp (1); |
!!!cp (1); |
| 1091 |
} |
} |
| 1092 |
} elsif ($self->{nc} == 0x002D) { # - |
} elsif ($self->{nc} == 0x002D) { # - |
| 1093 |
if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA |
if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA |
| 1094 |
if (defined $self->{s_kwd}) { |
$self->{s_kwd} .= '-'; |
| 1095 |
!!!cp (2.1); |
|
|
$self->{s_kwd} .= '-'; |
|
|
} else { |
|
|
!!!cp (2.2); |
|
|
$self->{s_kwd} = '-'; |
|
|
} |
|
|
|
|
| 1096 |
if ($self->{s_kwd} eq '<!--') { |
if ($self->{s_kwd} eq '<!--') { |
| 1097 |
!!!cp (3); |
!!!cp (3); |
| 1098 |
$self->{escape} = 1; # unless $self->{escape}; |
$self->{escape} = 1; # unless $self->{escape}; |
| 1110 |
|
|
| 1111 |
# |
# |
| 1112 |
} elsif ($self->{nc} == 0x0021) { # ! |
} elsif ($self->{nc} == 0x0021) { # ! |
| 1113 |
if (defined $self->{s_kwd}) { |
if (length $self->{s_kwd}) { |
| 1114 |
!!!cp (5.1); |
!!!cp (5.1); |
| 1115 |
$self->{s_kwd} .= '!'; |
$self->{s_kwd} .= '!'; |
| 1116 |
# |
# |
| 1117 |
} else { |
} else { |
| 1118 |
!!!cp (5.2); |
!!!cp (5.2); |
| 1119 |
|
#$self->{s_kwd} = ''; |
| 1120 |
# |
# |
| 1121 |
} |
} |
| 1122 |
# |
# |
| 1123 |
} elsif ($self->{nc} == 0x003C) { # < |
} elsif ($self->{nc} == 0x003C) { # < |
|
delete $self->{s_kwd}; |
|
| 1124 |
if ($self->{content_model} & CM_FULL_MARKUP or # PCDATA |
if ($self->{content_model} & CM_FULL_MARKUP or # PCDATA |
| 1125 |
(($self->{content_model} & CM_LIMITED_MARKUP) and # CDATA | RCDATA |
(($self->{content_model} & CM_LIMITED_MARKUP) and # CDATA | RCDATA |
| 1126 |
not $self->{escape})) { |
not $self->{escape})) { |
| 1130 |
redo A; |
redo A; |
| 1131 |
} else { |
} else { |
| 1132 |
!!!cp (7); |
!!!cp (7); |
| 1133 |
|
$self->{s_kwd} = ''; |
| 1134 |
# |
# |
| 1135 |
} |
} |
| 1136 |
} elsif ($self->{nc} == 0x003E) { # > |
} elsif ($self->{nc} == 0x003E) { # > |
| 1137 |
if ($self->{escape} and |
if ($self->{escape} and |
| 1138 |
($self->{content_model} & CM_LIMITED_MARKUP)) { # RCDATA | CDATA |
($self->{content_model} & CM_LIMITED_MARKUP)) { # RCDATA | CDATA |
| 1139 |
if (defined $self->{s_kwd} and $self->{s_kwd} eq '--') { |
if ($self->{s_kwd} eq '--') { |
| 1140 |
!!!cp (8); |
!!!cp (8); |
| 1141 |
delete $self->{escape}; |
delete $self->{escape}; |
| 1142 |
} else { |
} else { |
| 1146 |
!!!cp (10); |
!!!cp (10); |
| 1147 |
} |
} |
| 1148 |
|
|
| 1149 |
delete $self->{s_kwd}; |
$self->{s_kwd} = ''; |
| 1150 |
# |
# |
| 1151 |
} elsif ($self->{nc} == -1) { |
} elsif ($self->{nc} == -1) { |
| 1152 |
!!!cp (11); |
!!!cp (11); |
| 1153 |
delete $self->{s_kwd}; |
$self->{s_kwd} = ''; |
| 1154 |
!!!emit ({type => END_OF_FILE_TOKEN, |
!!!emit ({type => END_OF_FILE_TOKEN, |
| 1155 |
line => $self->{line}, column => $self->{column}}); |
line => $self->{line}, column => $self->{column}}); |
| 1156 |
last A; ## TODO: ok? |
last A; ## TODO: ok? |
| 1157 |
} else { |
} else { |
| 1158 |
!!!cp (12); |
!!!cp (12); |
| 1159 |
delete $self->{s_kwd}; |
$self->{s_kwd} = ''; |
| 1160 |
# |
# |
| 1161 |
} |
} |
| 1162 |
|
|
| 1167 |
}; |
}; |
| 1168 |
if ($self->{read_until}->($token->{data}, q[-!<>&], |
if ($self->{read_until}->($token->{data}, q[-!<>&], |
| 1169 |
length $token->{data})) { |
length $token->{data})) { |
| 1170 |
delete $self->{s_kwd}; |
$self->{s_kwd} = ''; |
| 1171 |
} |
} |
| 1172 |
|
|
| 1173 |
## Stay in the data state |
## Stay in the data state. |
| 1174 |
|
if ($self->{content_model} == PCDATA_CONTENT_MODEL) { |
| 1175 |
|
!!!cp (13); |
| 1176 |
|
$self->{state} = PCDATA_STATE; |
| 1177 |
|
} else { |
| 1178 |
|
!!!cp (14); |
| 1179 |
|
## Stay in the state. |
| 1180 |
|
} |
| 1181 |
!!!next-input-character; |
!!!next-input-character; |
| 1182 |
!!!emit ($token); |
!!!emit ($token); |
| 1183 |
redo A; |
redo A; |
| 1282 |
} |
} |
| 1283 |
} elsif ($self->{state} == CLOSE_TAG_OPEN_STATE) { |
} elsif ($self->{state} == CLOSE_TAG_OPEN_STATE) { |
| 1284 |
## NOTE: The "close tag open state" in the spec is implemented as |
## NOTE: The "close tag open state" in the spec is implemented as |
| 1285 |
## |CLOSE_TAG_OPEN_STATE| and |CDATA_PCDATA_CLOSE_TAG_STATE|. |
## |CLOSE_TAG_OPEN_STATE| and |CDATA_RCDATA_CLOSE_TAG_STATE|. |
| 1286 |
|
|
| 1287 |
my ($l, $c) = ($self->{line_prev}, $self->{column_prev} - 1); # "<"of"</" |
my ($l, $c) = ($self->{line_prev}, $self->{column_prev} - 1); # "<"of"</" |
| 1288 |
if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA |
if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA |
| 1289 |
if (defined $self->{last_stag_name}) { |
if (defined $self->{last_stag_name}) { |
| 1290 |
$self->{state} = CDATA_PCDATA_CLOSE_TAG_STATE; |
$self->{state} = CDATA_RCDATA_CLOSE_TAG_STATE; |
| 1291 |
$self->{s_kwd} = ''; |
$self->{s_kwd} = ''; |
| 1292 |
## Reconsume. |
## Reconsume. |
| 1293 |
redo A; |
redo A; |
| 1358 |
## "bogus comment state" entry. |
## "bogus comment state" entry. |
| 1359 |
redo A; |
redo A; |
| 1360 |
} |
} |
| 1361 |
} elsif ($self->{state} == CDATA_PCDATA_CLOSE_TAG_STATE) { |
} elsif ($self->{state} == CDATA_RCDATA_CLOSE_TAG_STATE) { |
| 1362 |
my $ch = substr $self->{last_stag_name}, length $self->{s_kwd}, 1; |
my $ch = substr $self->{last_stag_name}, length $self->{s_kwd}, 1; |
| 1363 |
if (length $ch) { |
if (length $ch) { |
| 1364 |
my $CH = $ch; |
my $CH = $ch; |
| 1382 |
redo A; |
redo A; |
| 1383 |
} |
} |
| 1384 |
} else { # after "<{tag-name}" |
} else { # after "<{tag-name}" |
| 1385 |
unless ({ |
unless ($is_space->{$self->{nc}} or |
| 1386 |
0x0009 => 1, # HT |
{ |
|
0x000A => 1, # LF |
|
|
0x000B => 1, # VT |
|
|
0x000C => 1, # FF |
|
|
0x0020 => 1, # SP |
|
| 1387 |
0x003E => 1, # > |
0x003E => 1, # > |
| 1388 |
0x002F => 1, # / |
0x002F => 1, # / |
| 1389 |
-1 => 1, # EOF |
-1 => 1, # EOF |
| 1410 |
} |
} |
| 1411 |
} |
} |
| 1412 |
} elsif ($self->{state} == TAG_NAME_STATE) { |
} elsif ($self->{state} == TAG_NAME_STATE) { |
| 1413 |
if ($self->{nc} == 0x0009 or # HT |
if ($is_space->{$self->{nc}}) { |
|
$self->{nc} == 0x000A or # LF |
|
|
$self->{nc} == 0x000B or # VT |
|
|
$self->{nc} == 0x000C or # FF |
|
|
$self->{nc} == 0x0020) { # SP |
|
| 1414 |
!!!cp (34); |
!!!cp (34); |
| 1415 |
$self->{state} = BEFORE_ATTRIBUTE_NAME_STATE; |
$self->{state} = BEFORE_ATTRIBUTE_NAME_STATE; |
| 1416 |
!!!next-input-character; |
!!!next-input-character; |
| 1482 |
redo A; |
redo A; |
| 1483 |
} |
} |
| 1484 |
} elsif ($self->{state} == BEFORE_ATTRIBUTE_NAME_STATE) { |
} elsif ($self->{state} == BEFORE_ATTRIBUTE_NAME_STATE) { |
| 1485 |
if ($self->{nc} == 0x0009 or # HT |
if ($is_space->{$self->{nc}}) { |
|
$self->{nc} == 0x000A or # LF |
|
|
$self->{nc} == 0x000B or # VT |
|
|
$self->{nc} == 0x000C or # FF |
|
|
$self->{nc} == 0x0020) { # SP |
|
| 1486 |
!!!cp (45); |
!!!cp (45); |
| 1487 |
## Stay in the state |
## Stay in the state |
| 1488 |
!!!next-input-character; |
!!!next-input-character; |
| 1578 |
} |
} |
| 1579 |
}; # $before_leave |
}; # $before_leave |
| 1580 |
|
|
| 1581 |
if ($self->{nc} == 0x0009 or # HT |
if ($is_space->{$self->{nc}}) { |
|
$self->{nc} == 0x000A or # LF |
|
|
$self->{nc} == 0x000B or # VT |
|
|
$self->{nc} == 0x000C or # FF |
|
|
$self->{nc} == 0x0020) { # SP |
|
| 1582 |
!!!cp (59); |
!!!cp (59); |
| 1583 |
$before_leave->(); |
$before_leave->(); |
| 1584 |
$self->{state} = AFTER_ATTRIBUTE_NAME_STATE; |
$self->{state} = AFTER_ATTRIBUTE_NAME_STATE; |
| 1661 |
redo A; |
redo A; |
| 1662 |
} |
} |
| 1663 |
} elsif ($self->{state} == AFTER_ATTRIBUTE_NAME_STATE) { |
} elsif ($self->{state} == AFTER_ATTRIBUTE_NAME_STATE) { |
| 1664 |
if ($self->{nc} == 0x0009 or # HT |
if ($is_space->{$self->{nc}}) { |
|
$self->{nc} == 0x000A or # LF |
|
|
$self->{nc} == 0x000B or # VT |
|
|
$self->{nc} == 0x000C or # FF |
|
|
$self->{nc} == 0x0020) { # SP |
|
| 1665 |
!!!cp (71); |
!!!cp (71); |
| 1666 |
## Stay in the state |
## Stay in the state |
| 1667 |
!!!next-input-character; |
!!!next-input-character; |
| 1748 |
redo A; |
redo A; |
| 1749 |
} |
} |
| 1750 |
} elsif ($self->{state} == BEFORE_ATTRIBUTE_VALUE_STATE) { |
} elsif ($self->{state} == BEFORE_ATTRIBUTE_VALUE_STATE) { |
| 1751 |
if ($self->{nc} == 0x0009 or # HT |
if ($is_space->{$self->{nc}}) { |
|
$self->{nc} == 0x000A or # LF |
|
|
$self->{nc} == 0x000B or # VT |
|
|
$self->{nc} == 0x000C or # FF |
|
|
$self->{nc} == 0x0020) { # SP |
|
| 1752 |
!!!cp (83); |
!!!cp (83); |
| 1753 |
## Stay in the state |
## Stay in the state |
| 1754 |
!!!next-input-character; |
!!!next-input-character; |
| 1929 |
redo A; |
redo A; |
| 1930 |
} |
} |
| 1931 |
} elsif ($self->{state} == ATTRIBUTE_VALUE_UNQUOTED_STATE) { |
} elsif ($self->{state} == ATTRIBUTE_VALUE_UNQUOTED_STATE) { |
| 1932 |
if ($self->{nc} == 0x0009 or # HT |
if ($is_space->{$self->{nc}}) { |
|
$self->{nc} == 0x000A or # LF |
|
|
$self->{nc} == 0x000B or # HT |
|
|
$self->{nc} == 0x000C or # FF |
|
|
$self->{nc} == 0x0020) { # SP |
|
| 1933 |
!!!cp (107); |
!!!cp (107); |
| 1934 |
$self->{state} = BEFORE_ATTRIBUTE_NAME_STATE; |
$self->{state} = BEFORE_ATTRIBUTE_NAME_STATE; |
| 1935 |
!!!next-input-character; |
!!!next-input-character; |
| 2011 |
redo A; |
redo A; |
| 2012 |
} |
} |
| 2013 |
} elsif ($self->{state} == AFTER_ATTRIBUTE_VALUE_QUOTED_STATE) { |
} elsif ($self->{state} == AFTER_ATTRIBUTE_VALUE_QUOTED_STATE) { |
| 2014 |
if ($self->{nc} == 0x0009 or # HT |
if ($is_space->{$self->{nc}}) { |
|
$self->{nc} == 0x000A or # LF |
|
|
$self->{nc} == 0x000B or # VT |
|
|
$self->{nc} == 0x000C or # FF |
|
|
$self->{nc} == 0x0020) { # SP |
|
| 2015 |
!!!cp (118); |
!!!cp (118); |
| 2016 |
$self->{state} = BEFORE_ATTRIBUTE_NAME_STATE; |
$self->{state} = BEFORE_ATTRIBUTE_NAME_STATE; |
| 2017 |
!!!next-input-character; |
!!!next-input-character; |
| 2452 |
redo A; |
redo A; |
| 2453 |
} |
} |
| 2454 |
} elsif ($self->{state} == DOCTYPE_STATE) { |
} elsif ($self->{state} == DOCTYPE_STATE) { |
| 2455 |
if ($self->{nc} == 0x0009 or # HT |
if ($is_space->{$self->{nc}}) { |
|
$self->{nc} == 0x000A or # LF |
|
|
$self->{nc} == 0x000B or # VT |
|
|
$self->{nc} == 0x000C or # FF |
|
|
$self->{nc} == 0x0020) { # SP |
|
| 2456 |
!!!cp (155); |
!!!cp (155); |
| 2457 |
$self->{state} = BEFORE_DOCTYPE_NAME_STATE; |
$self->{state} = BEFORE_DOCTYPE_NAME_STATE; |
| 2458 |
!!!next-input-character; |
!!!next-input-character; |
| 2465 |
redo A; |
redo A; |
| 2466 |
} |
} |
| 2467 |
} elsif ($self->{state} == BEFORE_DOCTYPE_NAME_STATE) { |
} elsif ($self->{state} == BEFORE_DOCTYPE_NAME_STATE) { |
| 2468 |
if ($self->{nc} == 0x0009 or # HT |
if ($is_space->{$self->{nc}}) { |
|
$self->{nc} == 0x000A or # LF |
|
|
$self->{nc} == 0x000B or # VT |
|
|
$self->{nc} == 0x000C or # FF |
|
|
$self->{nc} == 0x0020) { # SP |
|
| 2469 |
!!!cp (157); |
!!!cp (157); |
| 2470 |
## Stay in the state |
## Stay in the state |
| 2471 |
!!!next-input-character; |
!!!next-input-character; |
| 2492 |
!!!cp (160); |
!!!cp (160); |
| 2493 |
$self->{ct}->{name} = chr $self->{nc}; |
$self->{ct}->{name} = chr $self->{nc}; |
| 2494 |
delete $self->{ct}->{quirks}; |
delete $self->{ct}->{quirks}; |
|
## ISSUE: "Set the token's name name to the" in the spec |
|
| 2495 |
$self->{state} = DOCTYPE_NAME_STATE; |
$self->{state} = DOCTYPE_NAME_STATE; |
| 2496 |
!!!next-input-character; |
!!!next-input-character; |
| 2497 |
redo A; |
redo A; |
| 2498 |
} |
} |
| 2499 |
} elsif ($self->{state} == DOCTYPE_NAME_STATE) { |
} elsif ($self->{state} == DOCTYPE_NAME_STATE) { |
| 2500 |
## ISSUE: Redundant "First," in the spec. |
## ISSUE: Redundant "First," in the spec. |
| 2501 |
if ($self->{nc} == 0x0009 or # HT |
if ($is_space->{$self->{nc}}) { |
|
$self->{nc} == 0x000A or # LF |
|
|
$self->{nc} == 0x000B or # VT |
|
|
$self->{nc} == 0x000C or # FF |
|
|
$self->{nc} == 0x0020) { # SP |
|
| 2502 |
!!!cp (161); |
!!!cp (161); |
| 2503 |
$self->{state} = AFTER_DOCTYPE_NAME_STATE; |
$self->{state} = AFTER_DOCTYPE_NAME_STATE; |
| 2504 |
!!!next-input-character; |
!!!next-input-character; |
| 2530 |
redo A; |
redo A; |
| 2531 |
} |
} |
| 2532 |
} elsif ($self->{state} == AFTER_DOCTYPE_NAME_STATE) { |
} elsif ($self->{state} == AFTER_DOCTYPE_NAME_STATE) { |
| 2533 |
if ($self->{nc} == 0x0009 or # HT |
if ($is_space->{$self->{nc}}) { |
|
$self->{nc} == 0x000A or # LF |
|
|
$self->{nc} == 0x000B or # VT |
|
|
$self->{nc} == 0x000C or # FF |
|
|
$self->{nc} == 0x0020) { # SP |
|
| 2534 |
!!!cp (165); |
!!!cp (165); |
| 2535 |
## Stay in the state |
## Stay in the state |
| 2536 |
!!!next-input-character; |
!!!next-input-character; |
| 2653 |
redo A; |
redo A; |
| 2654 |
} |
} |
| 2655 |
} elsif ($self->{state} == BEFORE_DOCTYPE_PUBLIC_IDENTIFIER_STATE) { |
} elsif ($self->{state} == BEFORE_DOCTYPE_PUBLIC_IDENTIFIER_STATE) { |
| 2656 |
if ({ |
if ($is_space->{$self->{nc}}) { |
|
0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, 0x0020 => 1, |
|
|
#0x000D => 1, # HT, LF, VT, FF, SP, CR |
|
|
}->{$self->{nc}}) { |
|
| 2657 |
!!!cp (181); |
!!!cp (181); |
| 2658 |
## Stay in the state |
## Stay in the state |
| 2659 |
!!!next-input-character; |
!!!next-input-character; |
| 2780 |
redo A; |
redo A; |
| 2781 |
} |
} |
| 2782 |
} elsif ($self->{state} == AFTER_DOCTYPE_PUBLIC_IDENTIFIER_STATE) { |
} elsif ($self->{state} == AFTER_DOCTYPE_PUBLIC_IDENTIFIER_STATE) { |
| 2783 |
if ({ |
if ($is_space->{$self->{nc}}) { |
|
0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, 0x0020 => 1, |
|
|
#0x000D => 1, # HT, LF, VT, FF, SP, CR |
|
|
}->{$self->{nc}}) { |
|
| 2784 |
!!!cp (195); |
!!!cp (195); |
| 2785 |
## Stay in the state |
## Stay in the state |
| 2786 |
!!!next-input-character; |
!!!next-input-character; |
| 2826 |
redo A; |
redo A; |
| 2827 |
} |
} |
| 2828 |
} elsif ($self->{state} == BEFORE_DOCTYPE_SYSTEM_IDENTIFIER_STATE) { |
} elsif ($self->{state} == BEFORE_DOCTYPE_SYSTEM_IDENTIFIER_STATE) { |
| 2829 |
if ({ |
if ($is_space->{$self->{nc}}) { |
|
0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, 0x0020 => 1, |
|
|
#0x000D => 1, # HT, LF, VT, FF, SP, CR |
|
|
}->{$self->{nc}}) { |
|
| 2830 |
!!!cp (201); |
!!!cp (201); |
| 2831 |
## Stay in the state |
## Stay in the state |
| 2832 |
!!!next-input-character; |
!!!next-input-character; |
| 2952 |
redo A; |
redo A; |
| 2953 |
} |
} |
| 2954 |
} elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) { |
} elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) { |
| 2955 |
if ({ |
if ($is_space->{$self->{nc}}) { |
|
0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, 0x0020 => 1, |
|
|
#0x000D => 1, # HT, LF, VT, FF, SP, CR |
|
|
}->{$self->{nc}}) { |
|
| 2956 |
!!!cp (215); |
!!!cp (215); |
| 2957 |
## Stay in the state |
## Stay in the state |
| 2958 |
!!!next-input-character; |
!!!next-input-character; |
| 2995 |
redo A; |
redo A; |
| 2996 |
} elsif ($self->{nc} == -1) { |
} elsif ($self->{nc} == -1) { |
| 2997 |
!!!cp (220); |
!!!cp (220); |
|
!!!parse-error (type => 'unclosed DOCTYPE'); |
|
| 2998 |
$self->{state} = DATA_STATE; |
$self->{state} = DATA_STATE; |
| 2999 |
## reconsume |
## reconsume |
| 3000 |
|
|
| 3083 |
redo A; |
redo A; |
| 3084 |
} |
} |
| 3085 |
} elsif ($self->{state} == ENTITY_STATE) { |
} elsif ($self->{state} == ENTITY_STATE) { |
| 3086 |
if ({ |
if ($is_space->{$self->{nc}} or |
| 3087 |
0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, # HT, LF, VT, FF, |
{ |
| 3088 |
0x0020 => 1, 0x003C => 1, 0x0026 => 1, -1 => 1, # SP, <, & |
0x003C => 1, 0x0026 => 1, -1 => 1, # <, & |
| 3089 |
$self->{entity_add} => 1, |
$self->{entity_add} => 1, |
| 3090 |
}->{$self->{nc}}) { |
}->{$self->{nc}}) { |
| 3091 |
!!!cp (1001); |
!!!cp (1001); |
| 3092 |
## Don't consume |
## Don't consume |
| 3093 |
## No error |
## No error |
| 3206 |
my $code = $self->{s_kwd}; |
my $code = $self->{s_kwd}; |
| 3207 |
my $l = $self->{line_prev}; |
my $l = $self->{line_prev}; |
| 3208 |
my $c = $self->{column_prev}; |
my $c = $self->{column_prev}; |
| 3209 |
if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) { |
if ($charref_map->{$code}) { |
| 3210 |
!!!cp (1015); |
!!!cp (1015); |
| 3211 |
!!!parse-error (type => 'invalid character reference', |
!!!parse-error (type => 'invalid character reference', |
| 3212 |
text => (sprintf 'U+%04X', $code), |
text => (sprintf 'U+%04X', $code), |
| 3213 |
line => $l, column => $c); |
line => $l, column => $c); |
| 3214 |
$code = 0xFFFD; |
$code = $charref_map->{$code}; |
| 3215 |
} elsif ($code > 0x10FFFF) { |
} elsif ($code > 0x10FFFF) { |
| 3216 |
!!!cp (1016); |
!!!cp (1016); |
| 3217 |
!!!parse-error (type => 'invalid character reference', |
!!!parse-error (type => 'invalid character reference', |
| 3218 |
text => (sprintf 'U-%08X', $code), |
text => (sprintf 'U-%08X', $code), |
| 3219 |
line => $l, column => $c); |
line => $l, column => $c); |
| 3220 |
$code = 0xFFFD; |
$code = 0xFFFD; |
|
} elsif ($code == 0x000D) { |
|
|
!!!cp (1017); |
|
|
!!!parse-error (type => 'CR character reference', |
|
|
line => $l, column => $c); |
|
|
$code = 0x000A; |
|
|
} elsif (0x80 <= $code and $code <= 0x9F) { |
|
|
!!!cp (1018); |
|
|
!!!parse-error (type => 'C1 character reference', |
|
|
text => (sprintf 'U+%04X', $code), |
|
|
line => $l, column => $c); |
|
|
$code = $c1_entity_char->{$code}; |
|
| 3221 |
} |
} |
| 3222 |
|
|
| 3223 |
if ($self->{prev_state} == DATA_STATE) { |
if ($self->{prev_state} == DATA_STATE) { |
| 3314 |
my $code = $self->{s_kwd}; |
my $code = $self->{s_kwd}; |
| 3315 |
my $l = $self->{line_prev}; |
my $l = $self->{line_prev}; |
| 3316 |
my $c = $self->{column_prev}; |
my $c = $self->{column_prev}; |
| 3317 |
if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) { |
if ($charref_map->{$code}) { |
| 3318 |
!!!cp (1008); |
!!!cp (1008); |
| 3319 |
!!!parse-error (type => 'invalid character reference', |
!!!parse-error (type => 'invalid character reference', |
| 3320 |
text => (sprintf 'U+%04X', $code), |
text => (sprintf 'U+%04X', $code), |
| 3321 |
line => $l, column => $c); |
line => $l, column => $c); |
| 3322 |
$code = 0xFFFD; |
$code = $charref_map->{$code}; |
| 3323 |
} elsif ($code > 0x10FFFF) { |
} elsif ($code > 0x10FFFF) { |
| 3324 |
!!!cp (1009); |
!!!cp (1009); |
| 3325 |
!!!parse-error (type => 'invalid character reference', |
!!!parse-error (type => 'invalid character reference', |
| 3326 |
text => (sprintf 'U-%08X', $code), |
text => (sprintf 'U-%08X', $code), |
| 3327 |
line => $l, column => $c); |
line => $l, column => $c); |
| 3328 |
$code = 0xFFFD; |
$code = 0xFFFD; |
|
} elsif ($code == 0x000D) { |
|
|
!!!cp (1010); |
|
|
!!!parse-error (type => 'CR character reference', line => $l, column => $c); |
|
|
$code = 0x000A; |
|
|
} elsif (0x80 <= $code and $code <= 0x9F) { |
|
|
!!!cp (1011); |
|
|
!!!parse-error (type => 'C1 character reference', text => (sprintf 'U+%04X', $code), line => $l, column => $c); |
|
|
$code = $c1_entity_char->{$code}; |
|
| 3329 |
} |
} |
| 3330 |
|
|
| 3331 |
if ($self->{prev_state} == DATA_STATE) { |
if ($self->{prev_state} == DATA_STATE) { |
| 3474 |
## When an interactive UA render the $self->{document} available |
## When an interactive UA render the $self->{document} available |
| 3475 |
## to the user, or when it begin accepting user input, are |
## to the user, or when it begin accepting user input, are |
| 3476 |
## not defined. |
## not defined. |
|
|
|
|
## Append a character: collect it and all subsequent consecutive |
|
|
## characters and insert one Text node whose data is concatenation |
|
|
## of all those characters. # MUST |
|
| 3477 |
|
|
| 3478 |
!!!next-token; |
!!!next-token; |
| 3479 |
|
|
| 3480 |
undef $self->{form_element}; |
undef $self->{form_element}; |
| 3481 |
undef $self->{head_element}; |
undef $self->{head_element}; |
| 3482 |
|
undef $self->{head_element_inserted}; |
| 3483 |
$self->{open_elements} = []; |
$self->{open_elements} = []; |
| 3484 |
undef $self->{inner_html_node}; |
undef $self->{inner_html_node}; |
| 3485 |
|
undef $self->{ignore_newline}; |
| 3486 |
|
|
| 3487 |
## NOTE: The "initial" insertion mode. |
## NOTE: The "initial" insertion mode. |
| 3488 |
$self->_tree_construction_initial; # MUST |
$self->_tree_construction_initial; # MUST |
| 3664 |
!!!ack-later; |
!!!ack-later; |
| 3665 |
return; |
return; |
| 3666 |
} elsif ($token->{type} == CHARACTER_TOKEN) { |
} elsif ($token->{type} == CHARACTER_TOKEN) { |
| 3667 |
if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { # \x0D |
if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) { |
| 3668 |
## Ignore the token |
## Ignore the token |
| 3669 |
|
|
| 3670 |
unless (length $token->{data}) { |
unless (length $token->{data}) { |
| 3721 |
!!!next-token; |
!!!next-token; |
| 3722 |
redo B; |
redo B; |
| 3723 |
} elsif ($token->{type} == CHARACTER_TOKEN) { |
} elsif ($token->{type} == CHARACTER_TOKEN) { |
| 3724 |
if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { # \x0D |
if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) { |
| 3725 |
## Ignore the token. |
## Ignore the token. |
| 3726 |
|
|
| 3727 |
unless (length $token->{data}) { |
unless (length $token->{data}) { |
| 3788 |
## NOTE: Reprocess the token. |
## NOTE: Reprocess the token. |
| 3789 |
!!!ack-later; |
!!!ack-later; |
| 3790 |
return; ## Go to the "before head" insertion mode. |
return; ## Go to the "before head" insertion mode. |
|
|
|
|
## ISSUE: There is an issue in the spec |
|
| 3791 |
} # B |
} # B |
| 3792 |
|
|
| 3793 |
die "$0: _tree_construction_root_element: This should never be reached"; |
die "$0: _tree_construction_root_element: This should never be reached"; |
| 3823 |
## SVG elements. Currently the HTML syntax supports only MathML and |
## SVG elements. Currently the HTML syntax supports only MathML and |
| 3824 |
## SVG elements as foreigners. |
## SVG elements as foreigners. |
| 3825 |
$new_mode = IN_BODY_IM | IN_FOREIGN_CONTENT_IM; |
$new_mode = IN_BODY_IM | IN_FOREIGN_CONTENT_IM; |
| 3826 |
} elsif ($node->[1] & TABLE_CELL_EL) { |
} elsif ($node->[1] == TABLE_CELL_EL) { |
| 3827 |
if ($last) { |
if ($last) { |
| 3828 |
!!!cp ('t28.2'); |
!!!cp ('t28.2'); |
| 3829 |
# |
# |
| 3852 |
$self->{insertion_mode} = $new_mode and return if defined $new_mode; |
$self->{insertion_mode} = $new_mode and return if defined $new_mode; |
| 3853 |
|
|
| 3854 |
## Step 15 |
## Step 15 |
| 3855 |
if ($node->[1] & HTML_EL) { |
if ($node->[1] == HTML_EL) { |
| 3856 |
unless (defined $self->{head_element}) { |
unless (defined $self->{head_element}) { |
| 3857 |
!!!cp ('t29'); |
!!!cp ('t29'); |
| 3858 |
$self->{insertion_mode} = BEFORE_HEAD_IM; |
$self->{insertion_mode} = BEFORE_HEAD_IM; |
| 3984 |
|
|
| 3985 |
## Step 1 |
## Step 1 |
| 3986 |
my $start_tag_name = $token->{tag_name}; |
my $start_tag_name = $token->{tag_name}; |
| 3987 |
my $el; |
!!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token); |
|
!!!create-element ($el, $HTML_NS, $start_tag_name, $token->{attributes}, $token); |
|
| 3988 |
|
|
| 3989 |
## Step 2 |
## Step 2 |
|
$insert->($el); |
|
|
|
|
|
## Step 3 |
|
| 3990 |
$self->{content_model} = $content_model_flag; # CDATA or RCDATA |
$self->{content_model} = $content_model_flag; # CDATA or RCDATA |
| 3991 |
delete $self->{escape}; # MUST |
delete $self->{escape}; # MUST |
| 3992 |
|
|
| 3993 |
## Step 4 |
## Step 3, 4 |
| 3994 |
my $text = ''; |
$self->{insertion_mode} |= IN_CDATA_RCDATA_IM; |
|
!!!nack ('t40.1'); |
|
|
!!!next-token; |
|
|
while ($token->{type} == CHARACTER_TOKEN) { # or until stop tokenizing |
|
|
!!!cp ('t40'); |
|
|
$text .= $token->{data}; |
|
|
!!!next-token; |
|
|
} |
|
| 3995 |
|
|
| 3996 |
## Step 5 |
!!!nack ('t40.1'); |
|
if (length $text) { |
|
|
!!!cp ('t41'); |
|
|
my $text = $self->{document}->create_text_node ($text); |
|
|
$el->append_child ($text); |
|
|
} |
|
|
|
|
|
## Step 6 |
|
|
$self->{content_model} = PCDATA_CONTENT_MODEL; |
|
|
|
|
|
## Step 7 |
|
|
if ($token->{type} == END_TAG_TOKEN and |
|
|
$token->{tag_name} eq $start_tag_name) { |
|
|
!!!cp ('t42'); |
|
|
## Ignore the token |
|
|
} else { |
|
|
## NOTE: An end-of-file token. |
|
|
if ($content_model_flag == CDATA_CONTENT_MODEL) { |
|
|
!!!cp ('t43'); |
|
|
!!!parse-error (type => 'in CDATA:#eof', token => $token); |
|
|
} elsif ($content_model_flag == RCDATA_CONTENT_MODEL) { |
|
|
!!!cp ('t44'); |
|
|
!!!parse-error (type => 'in RCDATA:#eof', token => $token); |
|
|
} else { |
|
|
die "$0: $content_model_flag in parse_rcdata"; |
|
|
} |
|
|
} |
|
| 3997 |
!!!next-token; |
!!!next-token; |
| 3998 |
}; # $parse_rcdata |
}; # $parse_rcdata |
| 3999 |
|
|
| 4000 |
my $script_start_tag = sub () { |
my $script_start_tag = sub () { |
| 4001 |
|
## Step 1 |
| 4002 |
my $script_el; |
my $script_el; |
| 4003 |
!!!create-element ($script_el, $HTML_NS, 'script', $token->{attributes}, $token); |
!!!create-element ($script_el, $HTML_NS, 'script', $token->{attributes}, $token); |
| 4004 |
|
|
| 4005 |
|
## Step 2 |
| 4006 |
## TODO: mark as "parser-inserted" |
## TODO: mark as "parser-inserted" |
| 4007 |
|
|
| 4008 |
|
## Step 3 |
| 4009 |
|
## TODO: Mark as "already executed", if ... |
| 4010 |
|
|
| 4011 |
|
## Step 4 |
| 4012 |
|
$insert->($script_el); |
| 4013 |
|
|
| 4014 |
|
## ISSUE: $script_el is not put into the stack |
| 4015 |
|
push @{$self->{open_elements}}, [$script_el, $el_category->{script}]; |
| 4016 |
|
|
| 4017 |
|
## Step 5 |
| 4018 |
$self->{content_model} = CDATA_CONTENT_MODEL; |
$self->{content_model} = CDATA_CONTENT_MODEL; |
| 4019 |
delete $self->{escape}; # MUST |
delete $self->{escape}; # MUST |
|
|
|
|
my $text = ''; |
|
|
!!!nack ('t45.1'); |
|
|
!!!next-token; |
|
|
while ($token->{type} == CHARACTER_TOKEN) { |
|
|
!!!cp ('t45'); |
|
|
$text .= $token->{data}; |
|
|
!!!next-token; |
|
|
} # stop if non-character token or tokenizer stops tokenising |
|
|
if (length $text) { |
|
|
!!!cp ('t46'); |
|
|
$script_el->manakai_append_text ($text); |
|
|
} |
|
|
|
|
|
$self->{content_model} = PCDATA_CONTENT_MODEL; |
|
| 4020 |
|
|
| 4021 |
if ($token->{type} == END_TAG_TOKEN and |
## Step 6-7 |
| 4022 |
$token->{tag_name} eq 'script') { |
$self->{insertion_mode} |= IN_CDATA_RCDATA_IM; |
|
!!!cp ('t47'); |
|
|
## Ignore the token |
|
|
} else { |
|
|
!!!cp ('t48'); |
|
|
!!!parse-error (type => 'in CDATA:#eof', token => $token); |
|
|
## ISSUE: And ignore? |
|
|
## TODO: mark as "already executed" |
|
|
} |
|
|
|
|
|
if (defined $self->{inner_html_node}) { |
|
|
!!!cp ('t49'); |
|
|
## TODO: mark as "already executed" |
|
|
} else { |
|
|
!!!cp ('t50'); |
|
|
## TODO: $old_insertion_point = current insertion point |
|
|
## TODO: insertion point = just before the next input character |
|
| 4023 |
|
|
| 4024 |
$insert->($script_el); |
!!!nack ('t40.2'); |
|
|
|
|
## TODO: insertion point = $old_insertion_point (might be "undefined") |
|
|
|
|
|
## TODO: if there is a script that will execute as soon as the parser resume, then... |
|
|
} |
|
|
|
|
| 4025 |
!!!next-token; |
!!!next-token; |
| 4026 |
}; # $script_start_tag |
}; # $script_start_tag |
| 4027 |
|
|
| 4028 |
## NOTE: $open_tables->[-1]->[0] is the "current table" element node. |
## NOTE: $open_tables->[-1]->[0] is the "current table" element node. |
| 4029 |
## NOTE: $open_tables->[-1]->[1] is the "tainted" flag. |
## NOTE: $open_tables->[-1]->[1] is the "tainted" flag. |
| 4030 |
|
## NOTE: $open_tables->[-1]->[2] is set false when non-Text node inserted. |
| 4031 |
my $open_tables = [[$self->{open_elements}->[0]->[0]]]; |
my $open_tables = [[$self->{open_elements}->[0]->[0]]]; |
| 4032 |
|
|
| 4033 |
my $formatting_end_tag = sub { |
my $formatting_end_tag = sub { |
| 4112 |
!!!cp ('t59'); |
!!!cp ('t59'); |
| 4113 |
$furthest_block = $node; |
$furthest_block = $node; |
| 4114 |
$furthest_block_i_in_open = $_; |
$furthest_block_i_in_open = $_; |
| 4115 |
|
## NOTE: The topmost (eldest) node. |
| 4116 |
} elsif ($node->[0] eq $formatting_element->[0]) { |
} elsif ($node->[0] eq $formatting_element->[0]) { |
| 4117 |
!!!cp ('t60'); |
!!!cp ('t60'); |
| 4118 |
last OE; |
last OE; |
| 4199 |
my $foster_parent_element; |
my $foster_parent_element; |
| 4200 |
my $next_sibling; |
my $next_sibling; |
| 4201 |
OE: for (reverse 0..$#{$self->{open_elements}}) { |
OE: for (reverse 0..$#{$self->{open_elements}}) { |
| 4202 |
if ($self->{open_elements}->[$_]->[1] & TABLE_EL) { |
if ($self->{open_elements}->[$_]->[1] == TABLE_EL) { |
| 4203 |
my $parent = $self->{open_elements}->[$_]->[0]->parent_node; |
my $parent = $self->{open_elements}->[$_]->[0]->parent_node; |
| 4204 |
if (defined $parent and $parent->node_type == 1) { |
if (defined $parent and $parent->node_type == 1) { |
| 4205 |
!!!cp ('t65.1'); |
!!!cp ('t65.1'); |
| 4259 |
$i = $_; |
$i = $_; |
| 4260 |
} |
} |
| 4261 |
} # OE |
} # OE |
| 4262 |
splice @{$self->{open_elements}}, $i + 1, 1, $clone; |
splice @{$self->{open_elements}}, $i + 1, 0, $clone; |
| 4263 |
|
|
| 4264 |
## Step 14 |
## Step 14 |
| 4265 |
redo FET; |
redo FET; |
| 4277 |
my $foster_parent_element; |
my $foster_parent_element; |
| 4278 |
my $next_sibling; |
my $next_sibling; |
| 4279 |
OE: for (reverse 0..$#{$self->{open_elements}}) { |
OE: for (reverse 0..$#{$self->{open_elements}}) { |
| 4280 |
if ($self->{open_elements}->[$_]->[1] & TABLE_EL) { |
if ($self->{open_elements}->[$_]->[1] == TABLE_EL) { |
| 4281 |
my $parent = $self->{open_elements}->[$_]->[0]->parent_node; |
my $parent = $self->{open_elements}->[$_]->[0]->parent_node; |
| 4282 |
if (defined $parent and $parent->node_type == 1) { |
if (defined $parent and $parent->node_type == 1) { |
| 4283 |
!!!cp ('t70'); |
!!!cp ('t70'); |
| 4302 |
} |
} |
| 4303 |
}; # $insert_to_foster |
}; # $insert_to_foster |
| 4304 |
|
|
| 4305 |
|
## NOTE: Insert a character (MUST): When a character is inserted, if |
| 4306 |
|
## the last node that was inserted by the parser is a Text node and |
| 4307 |
|
## the character has to be inserted after that node, then the |
| 4308 |
|
## character is appended to the Text node. However, if any other |
| 4309 |
|
## node is inserted by the parser, then a new Text node is created |
| 4310 |
|
## and the character is appended as that Text node. If I'm not |
| 4311 |
|
## wrong, for a parser with scripting disabled, there are only two |
| 4312 |
|
## cases where this occurs. One is the case where an element node |
| 4313 |
|
## is inserted to the |head| element. This is covered by using the |
| 4314 |
|
## |$self->{head_element_inserted}| flag. Another is the case where |
| 4315 |
|
## an element or comment is inserted into the |table| subtree while |
| 4316 |
|
## foster parenting happens. This is covered by using the [2] flag |
| 4317 |
|
## of the |$open_tables| structure. All other cases are handled |
| 4318 |
|
## simply by calling |manakai_append_text| method. |
| 4319 |
|
|
| 4320 |
|
## TODO: |<body><script>document.write("a<br>"); |
| 4321 |
|
## document.body.removeChild (document.body.lastChild); |
| 4322 |
|
## document.write ("b")</script>| |
| 4323 |
|
|
| 4324 |
B: while (1) { |
B: while (1) { |
| 4325 |
if ($token->{type} == DOCTYPE_TOKEN) { |
if ($token->{type} == DOCTYPE_TOKEN) { |
| 4326 |
!!!cp ('t73'); |
!!!cp ('t73'); |
| 4368 |
} else { |
} else { |
| 4369 |
!!!cp ('t87'); |
!!!cp ('t87'); |
| 4370 |
$self->{open_elements}->[-1]->[0]->append_child ($comment); |
$self->{open_elements}->[-1]->[0]->append_child ($comment); |
| 4371 |
|
$open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted |
| 4372 |
} |
} |
| 4373 |
!!!next-token; |
!!!next-token; |
| 4374 |
next B; |
next B; |
| 4375 |
|
} elsif ($self->{insertion_mode} & IN_CDATA_RCDATA_IM) { |
| 4376 |
|
if ($token->{type} == CHARACTER_TOKEN) { |
| 4377 |
|
$token->{data} =~ s/^\x0A// if $self->{ignore_newline}; |
| 4378 |
|
delete $self->{ignore_newline}; |
| 4379 |
|
|
| 4380 |
|
if (length $token->{data}) { |
| 4381 |
|
!!!cp ('t43'); |
| 4382 |
|
$self->{open_elements}->[-1]->[0]->manakai_append_text |
| 4383 |
|
($token->{data}); |
| 4384 |
|
} else { |
| 4385 |
|
!!!cp ('t43.1'); |
| 4386 |
|
} |
| 4387 |
|
!!!next-token; |
| 4388 |
|
next B; |
| 4389 |
|
} elsif ($token->{type} == END_TAG_TOKEN) { |
| 4390 |
|
delete $self->{ignore_newline}; |
| 4391 |
|
|
| 4392 |
|
if ($token->{tag_name} eq 'script') { |
| 4393 |
|
!!!cp ('t50'); |
| 4394 |
|
|
| 4395 |
|
## Para 1-2 |
| 4396 |
|
my $script = pop @{$self->{open_elements}}; |
| 4397 |
|
|
| 4398 |
|
## Para 3 |
| 4399 |
|
$self->{insertion_mode} &= ~ IN_CDATA_RCDATA_IM; |
| 4400 |
|
|
| 4401 |
|
## Para 4 |
| 4402 |
|
## TODO: $old_insertion_point = $current_insertion_point; |
| 4403 |
|
## TODO: $current_insertion_point = just before $self->{nc}; |
| 4404 |
|
|
| 4405 |
|
## Para 5 |
| 4406 |
|
## TODO: Run the $script->[0]. |
| 4407 |
|
|
| 4408 |
|
## Para 6 |
| 4409 |
|
## TODO: $current_insertion_point = $old_insertion_point; |
| 4410 |
|
|
| 4411 |
|
## Para 7 |
| 4412 |
|
## TODO: if ($pending_external_script) { |
| 4413 |
|
## TODO: ... |
| 4414 |
|
## TODO: } |
| 4415 |
|
|
| 4416 |
|
!!!next-token; |
| 4417 |
|
next B; |
| 4418 |
|
} else { |
| 4419 |
|
!!!cp ('t42'); |
| 4420 |
|
|
| 4421 |
|
pop @{$self->{open_elements}}; |
| 4422 |
|
|
| 4423 |
|
$self->{insertion_mode} &= ~ IN_CDATA_RCDATA_IM; |
| 4424 |
|
!!!next-token; |
| 4425 |
|
next B; |
| 4426 |
|
} |
| 4427 |
|
} elsif ($token->{type} == END_OF_FILE_TOKEN) { |
| 4428 |
|
delete $self->{ignore_newline}; |
| 4429 |
|
|
| 4430 |
|
!!!cp ('t44'); |
| 4431 |
|
!!!parse-error (type => 'not closed', |
| 4432 |
|
text => $self->{open_elements}->[-1]->[0] |
| 4433 |
|
->manakai_local_name, |
| 4434 |
|
token => $token); |
| 4435 |
|
|
| 4436 |
|
#if ($self->{open_elements}->[-1]->[1] == SCRIPT_EL) { |
| 4437 |
|
# ## TODO: Mark as "already executed" |
| 4438 |
|
#} |
| 4439 |
|
|
| 4440 |
|
pop @{$self->{open_elements}}; |
| 4441 |
|
|
| 4442 |
|
$self->{insertion_mode} &= ~ IN_CDATA_RCDATA_IM; |
| 4443 |
|
## Reprocess. |
| 4444 |
|
next B; |
| 4445 |
|
} else { |
| 4446 |
|
die "$0: $token->{type}: In CDATA/RCDATA: Unknown token type"; |
| 4447 |
|
} |
| 4448 |
} elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM) { |
} elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM) { |
| 4449 |
if ($token->{type} == CHARACTER_TOKEN) { |
if ($token->{type} == CHARACTER_TOKEN) { |
| 4450 |
!!!cp ('t87.1'); |
!!!cp ('t87.1'); |
| 4456 |
$self->{open_elements}->[-1]->[1] & FOREIGN_FLOW_CONTENT_EL) or |
$self->{open_elements}->[-1]->[1] & FOREIGN_FLOW_CONTENT_EL) or |
| 4457 |
not ($self->{open_elements}->[-1]->[1] & FOREIGN_EL) or |
not ($self->{open_elements}->[-1]->[1] & FOREIGN_EL) or |
| 4458 |
($token->{tag_name} eq 'svg' and |
($token->{tag_name} eq 'svg' and |
| 4459 |
$self->{open_elements}->[-1]->[1] & MML_AXML_EL)) { |
$self->{open_elements}->[-1]->[1] == MML_AXML_EL)) { |
| 4460 |
## NOTE: "using the rules for secondary insertion mode"then"continue" |
## NOTE: "using the rules for secondary insertion mode"then"continue" |
| 4461 |
!!!cp ('t87.2'); |
!!!cp ('t87.2'); |
| 4462 |
# |
# |
| 4557 |
pop @{$self->{open_elements}} |
pop @{$self->{open_elements}} |
| 4558 |
while $self->{open_elements}->[-1]->[1] & FOREIGN_EL; |
while $self->{open_elements}->[-1]->[1] & FOREIGN_EL; |
| 4559 |
|
|
| 4560 |
|
## NOTE: |<span><svg>| ... two parse errors, |<svg>| ... a parse error. |
| 4561 |
|
|
| 4562 |
$self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM; |
$self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM; |
| 4563 |
## Reprocess. |
## Reprocess. |
| 4564 |
next B; |
next B; |
| 4569 |
|
|
| 4570 |
if ($self->{insertion_mode} & HEAD_IMS) { |
if ($self->{insertion_mode} & HEAD_IMS) { |
| 4571 |
if ($token->{type} == CHARACTER_TOKEN) { |
if ($token->{type} == CHARACTER_TOKEN) { |
| 4572 |
if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { |
if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) { |
| 4573 |
unless ($self->{insertion_mode} == BEFORE_HEAD_IM) { |
unless ($self->{insertion_mode} == BEFORE_HEAD_IM) { |
| 4574 |
!!!cp ('t88.2'); |
if ($self->{head_element_inserted}) { |
| 4575 |
$self->{open_elements}->[-1]->[0]->manakai_append_text ($1); |
!!!cp ('t88.3'); |
| 4576 |
# |
$self->{open_elements}->[-1]->[0]->append_child |
| 4577 |
|
($self->{document}->create_text_node ($1)); |
| 4578 |
|
delete $self->{head_element_inserted}; |
| 4579 |
|
## NOTE: |</head> <link> | |
| 4580 |
|
# |
| 4581 |
|
} else { |
| 4582 |
|
!!!cp ('t88.2'); |
| 4583 |
|
$self->{open_elements}->[-1]->[0]->manakai_append_text ($1); |
| 4584 |
|
## NOTE: |</head>  | |
| 4585 |
|
# |
| 4586 |
|
} |
| 4587 |
} else { |
} else { |
| 4588 |
!!!cp ('t88.1'); |
!!!cp ('t88.1'); |
| 4589 |
## Ignore the token. |
## Ignore the token. |
| 4679 |
!!!cp ('t97'); |
!!!cp ('t97'); |
| 4680 |
} |
} |
| 4681 |
|
|
| 4682 |
if ($token->{tag_name} eq 'base') { |
if ($token->{tag_name} eq 'base') { |
| 4683 |
if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
| 4684 |
!!!cp ('t98'); |
!!!cp ('t98'); |
| 4685 |
## As if </noscript> |
## As if </noscript> |
| 4686 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 4687 |
!!!parse-error (type => 'in noscript', text => 'base', |
!!!parse-error (type => 'in noscript', text => 'base', |
| 4688 |
token => $token); |
token => $token); |
| 4689 |
|
|
| 4690 |
$self->{insertion_mode} = IN_HEAD_IM; |
$self->{insertion_mode} = IN_HEAD_IM; |
| 4691 |
## Reprocess in the "in head" insertion mode... |
## Reprocess in the "in head" insertion mode... |
| 4692 |
} else { |
} else { |
| 4693 |
!!!cp ('t99'); |
!!!cp ('t99'); |
| 4694 |
} |
} |
| 4695 |
|
|
| 4696 |
## NOTE: There is a "as if in head" code clone. |
## NOTE: There is a "as if in head" code clone. |
| 4697 |
if ($self->{insertion_mode} == AFTER_HEAD_IM) { |
if ($self->{insertion_mode} == AFTER_HEAD_IM) { |
| 4698 |
!!!cp ('t100'); |
!!!cp ('t100'); |
| 4699 |
!!!parse-error (type => 'after head', |
!!!parse-error (type => 'after head', |
| 4700 |
text => $token->{tag_name}, token => $token); |
text => $token->{tag_name}, token => $token); |
| 4701 |
push @{$self->{open_elements}}, |
push @{$self->{open_elements}}, |
| 4702 |
[$self->{head_element}, $el_category->{head}]; |
[$self->{head_element}, $el_category->{head}]; |
| 4703 |
} else { |
$self->{head_element_inserted} = 1; |
| 4704 |
!!!cp ('t101'); |
} else { |
| 4705 |
} |
!!!cp ('t101'); |
| 4706 |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
} |
| 4707 |
pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec. |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
| 4708 |
pop @{$self->{open_elements}} # <head> |
pop @{$self->{open_elements}}; |
| 4709 |
if $self->{insertion_mode} == AFTER_HEAD_IM; |
pop @{$self->{open_elements}} # <head> |
| 4710 |
!!!nack ('t101.1'); |
if $self->{insertion_mode} == AFTER_HEAD_IM; |
| 4711 |
!!!next-token; |
!!!nack ('t101.1'); |
| 4712 |
next B; |
!!!next-token; |
| 4713 |
} elsif ($token->{tag_name} eq 'link') { |
next B; |
| 4714 |
## NOTE: There is a "as if in head" code clone. |
} elsif ($token->{tag_name} eq 'link') { |
| 4715 |
if ($self->{insertion_mode} == AFTER_HEAD_IM) { |
## NOTE: There is a "as if in head" code clone. |
| 4716 |
!!!cp ('t102'); |
if ($self->{insertion_mode} == AFTER_HEAD_IM) { |
| 4717 |
!!!parse-error (type => 'after head', |
!!!cp ('t102'); |
| 4718 |
text => $token->{tag_name}, token => $token); |
!!!parse-error (type => 'after head', |
| 4719 |
push @{$self->{open_elements}}, |
text => $token->{tag_name}, token => $token); |
| 4720 |
[$self->{head_element}, $el_category->{head}]; |
push @{$self->{open_elements}}, |
| 4721 |
} else { |
[$self->{head_element}, $el_category->{head}]; |
| 4722 |
!!!cp ('t103'); |
$self->{head_element_inserted} = 1; |
| 4723 |
} |
} else { |
| 4724 |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
!!!cp ('t103'); |
| 4725 |
pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec. |
} |
| 4726 |
pop @{$self->{open_elements}} # <head> |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
| 4727 |
if $self->{insertion_mode} == AFTER_HEAD_IM; |
pop @{$self->{open_elements}}; |
| 4728 |
!!!ack ('t103.1'); |
pop @{$self->{open_elements}} # <head> |
| 4729 |
!!!next-token; |
if $self->{insertion_mode} == AFTER_HEAD_IM; |
| 4730 |
next B; |
!!!ack ('t103.1'); |
| 4731 |
} elsif ($token->{tag_name} eq 'meta') { |
!!!next-token; |
| 4732 |
## NOTE: There is a "as if in head" code clone. |
next B; |
| 4733 |
if ($self->{insertion_mode} == AFTER_HEAD_IM) { |
} elsif ($token->{tag_name} eq 'command' or |
| 4734 |
!!!cp ('t104'); |
$token->{tag_name} eq 'eventsource') { |
| 4735 |
!!!parse-error (type => 'after head', |
if ($self->{insertion_mode} == IN_HEAD_IM) { |
| 4736 |
text => $token->{tag_name}, token => $token); |
## NOTE: If the insertion mode at the time of the emission |
| 4737 |
push @{$self->{open_elements}}, |
## of the token was "before head", $self->{insertion_mode} |
| 4738 |
[$self->{head_element}, $el_category->{head}]; |
## is already changed to |IN_HEAD_IM|. |
| 4739 |
} else { |
|
| 4740 |
!!!cp ('t105'); |
## NOTE: There is a "as if in head" code clone. |
| 4741 |
} |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
| 4742 |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
pop @{$self->{open_elements}}; |
| 4743 |
my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec. |
pop @{$self->{open_elements}} # <head> |
| 4744 |
|
if $self->{insertion_mode} == AFTER_HEAD_IM; |
| 4745 |
|
!!!ack ('t103.2'); |
| 4746 |
|
!!!next-token; |
| 4747 |
|
next B; |
| 4748 |
|
} else { |
| 4749 |
|
## NOTE: "in head noscript" or "after head" insertion mode |
| 4750 |
|
## - in these cases, these tags are treated as same as |
| 4751 |
|
## normal in-body tags. |
| 4752 |
|
!!!cp ('t103.3'); |
| 4753 |
|
# |
| 4754 |
|
} |
| 4755 |
|
} elsif ($token->{tag_name} eq 'meta') { |
| 4756 |
|
## NOTE: There is a "as if in head" code clone. |
| 4757 |
|
if ($self->{insertion_mode} == AFTER_HEAD_IM) { |
| 4758 |
|
!!!cp ('t104'); |
| 4759 |
|
!!!parse-error (type => 'after head', |
| 4760 |
|
text => $token->{tag_name}, token => $token); |
| 4761 |
|
push @{$self->{open_elements}}, |
| 4762 |
|
[$self->{head_element}, $el_category->{head}]; |
| 4763 |
|
$self->{head_element_inserted} = 1; |
| 4764 |
|
} else { |
| 4765 |
|
!!!cp ('t105'); |
| 4766 |
|
} |
| 4767 |
|
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
| 4768 |
|
my $meta_el = pop @{$self->{open_elements}}; |
| 4769 |
|
|
| 4770 |
unless ($self->{confident}) { |
unless ($self->{confident}) { |
| 4771 |
if ($token->{attributes}->{charset}) { |
if ($token->{attributes}->{charset}) { |
| 4783 |
} elsif ($token->{attributes}->{content}) { |
} elsif ($token->{attributes}->{content}) { |
| 4784 |
if ($token->{attributes}->{content}->{value} |
if ($token->{attributes}->{content}->{value} |
| 4785 |
=~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt] |
=~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt] |
| 4786 |
[\x09-\x0D\x20]*= |
[\x09\x0A\x0C\x0D\x20]*= |
| 4787 |
[\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'| |
[\x09\x0A\x0C\x0D\x20]*(?>"([^"]*)"|'([^']*)'| |
| 4788 |
([^"'\x09-\x0D\x20][^\x09-\x0D\x20\x3B]*))/x) { |
([^"'\x09\x0A\x0C\x0D\x20] |
| 4789 |
|
[^\x09\x0A\x0C\x0D\x20\x3B]*))/x) { |
| 4790 |
!!!cp ('t107'); |
!!!cp ('t107'); |
| 4791 |
## NOTE: Whether the encoding is supported or not is handled |
## NOTE: Whether the encoding is supported or not is handled |
| 4792 |
## in the {change_encoding} callback. |
## in the {change_encoding} callback. |
| 4823 |
!!!ack ('t110.1'); |
!!!ack ('t110.1'); |
| 4824 |
!!!next-token; |
!!!next-token; |
| 4825 |
next B; |
next B; |
| 4826 |
} elsif ($token->{tag_name} eq 'title') { |
} elsif ($token->{tag_name} eq 'title') { |
| 4827 |
if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
| 4828 |
!!!cp ('t111'); |
!!!cp ('t111'); |
| 4829 |
## As if </noscript> |
## As if </noscript> |
| 4830 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 4831 |
!!!parse-error (type => 'in noscript', text => 'title', |
!!!parse-error (type => 'in noscript', text => 'title', |
| 4832 |
token => $token); |
token => $token); |
| 4833 |
|
|
| 4834 |
$self->{insertion_mode} = IN_HEAD_IM; |
$self->{insertion_mode} = IN_HEAD_IM; |
| 4835 |
## Reprocess in the "in head" insertion mode... |
## Reprocess in the "in head" insertion mode... |
| 4836 |
} elsif ($self->{insertion_mode} == AFTER_HEAD_IM) { |
} elsif ($self->{insertion_mode} == AFTER_HEAD_IM) { |
| 4837 |
!!!cp ('t112'); |
!!!cp ('t112'); |
| 4838 |
!!!parse-error (type => 'after head', |
!!!parse-error (type => 'after head', |
| 4839 |
text => $token->{tag_name}, token => $token); |
text => $token->{tag_name}, token => $token); |
| 4840 |
push @{$self->{open_elements}}, |
push @{$self->{open_elements}}, |
| 4841 |
[$self->{head_element}, $el_category->{head}]; |
[$self->{head_element}, $el_category->{head}]; |
| 4842 |
} else { |
$self->{head_element_inserted} = 1; |
| 4843 |
!!!cp ('t113'); |
} else { |
| 4844 |
} |
!!!cp ('t113'); |
| 4845 |
|
} |
| 4846 |
|
|
| 4847 |
## NOTE: There is a "as if in head" code clone. |
## NOTE: There is a "as if in head" code clone. |
| 4848 |
my $parent = defined $self->{head_element} ? $self->{head_element} |
$parse_rcdata->(RCDATA_CONTENT_MODEL); |
| 4849 |
: $self->{open_elements}->[-1]->[0]; |
## ISSUE: A spec bug [Bug 6038] |
| 4850 |
$parse_rcdata->(RCDATA_CONTENT_MODEL); |
splice @{$self->{open_elements}}, -2, 1, () # <head> |
| 4851 |
pop @{$self->{open_elements}} # <head> |
if ($self->{insertion_mode} & AFTER_HEAD_IM) == AFTER_HEAD_IM; |
| 4852 |
if $self->{insertion_mode} == AFTER_HEAD_IM; |
next B; |
| 4853 |
next B; |
} elsif ($token->{tag_name} eq 'style' or |
| 4854 |
} elsif ($token->{tag_name} eq 'style' or |
$token->{tag_name} eq 'noframes') { |
| 4855 |
$token->{tag_name} eq 'noframes') { |
## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and |
| 4856 |
## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and |
## insertion mode IN_HEAD_IM) |
| 4857 |
## insertion mode IN_HEAD_IM) |
## NOTE: There is a "as if in head" code clone. |
| 4858 |
## NOTE: There is a "as if in head" code clone. |
if ($self->{insertion_mode} == AFTER_HEAD_IM) { |
| 4859 |
if ($self->{insertion_mode} == AFTER_HEAD_IM) { |
!!!cp ('t114'); |
| 4860 |
!!!cp ('t114'); |
!!!parse-error (type => 'after head', |
| 4861 |
!!!parse-error (type => 'after head', |
text => $token->{tag_name}, token => $token); |
| 4862 |
text => $token->{tag_name}, token => $token); |
push @{$self->{open_elements}}, |
| 4863 |
push @{$self->{open_elements}}, |
[$self->{head_element}, $el_category->{head}]; |
| 4864 |
[$self->{head_element}, $el_category->{head}]; |
$self->{head_element_inserted} = 1; |
| 4865 |
} else { |
} else { |
| 4866 |
!!!cp ('t115'); |
!!!cp ('t115'); |
| 4867 |
} |
} |
| 4868 |
$parse_rcdata->(CDATA_CONTENT_MODEL); |
$parse_rcdata->(CDATA_CONTENT_MODEL); |
| 4869 |
pop @{$self->{open_elements}} # <head> |
## ISSUE: A spec bug [Bug 6038] |
| 4870 |
if $self->{insertion_mode} == AFTER_HEAD_IM; |
splice @{$self->{open_elements}}, -2, 1, () # <head> |
| 4871 |
next B; |
if ($self->{insertion_mode} & AFTER_HEAD_IM) == AFTER_HEAD_IM; |
| 4872 |
} elsif ($token->{tag_name} eq 'noscript') { |
next B; |
| 4873 |
|
} elsif ($token->{tag_name} eq 'noscript') { |
| 4874 |
if ($self->{insertion_mode} == IN_HEAD_IM) { |
if ($self->{insertion_mode} == IN_HEAD_IM) { |
| 4875 |
!!!cp ('t116'); |
!!!cp ('t116'); |
| 4876 |
## NOTE: and scripting is disalbed |
## NOTE: and scripting is disalbed |
| 4891 |
!!!cp ('t118'); |
!!!cp ('t118'); |
| 4892 |
# |
# |
| 4893 |
} |
} |
| 4894 |
} elsif ($token->{tag_name} eq 'script') { |
} elsif ($token->{tag_name} eq 'script') { |
| 4895 |
if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
| 4896 |
!!!cp ('t119'); |
!!!cp ('t119'); |
| 4897 |
## As if </noscript> |
## As if </noscript> |
| 4898 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 4899 |
!!!parse-error (type => 'in noscript', text => 'script', |
!!!parse-error (type => 'in noscript', text => 'script', |
| 4900 |
token => $token); |
token => $token); |
| 4901 |
|
|
| 4902 |
$self->{insertion_mode} = IN_HEAD_IM; |
$self->{insertion_mode} = IN_HEAD_IM; |
| 4903 |
## Reprocess in the "in head" insertion mode... |
## Reprocess in the "in head" insertion mode... |
| 4904 |
} elsif ($self->{insertion_mode} == AFTER_HEAD_IM) { |
} elsif ($self->{insertion_mode} == AFTER_HEAD_IM) { |
| 4905 |
!!!cp ('t120'); |
!!!cp ('t120'); |
| 4906 |
!!!parse-error (type => 'after head', |
!!!parse-error (type => 'after head', |
| 4907 |
text => $token->{tag_name}, token => $token); |
text => $token->{tag_name}, token => $token); |
| 4908 |
push @{$self->{open_elements}}, |
push @{$self->{open_elements}}, |
| 4909 |
[$self->{head_element}, $el_category->{head}]; |
[$self->{head_element}, $el_category->{head}]; |
| 4910 |
} else { |
$self->{head_element_inserted} = 1; |
| 4911 |
!!!cp ('t121'); |
} else { |
| 4912 |
} |
!!!cp ('t121'); |
| 4913 |
|
} |
| 4914 |
|
|
| 4915 |
## NOTE: There is a "as if in head" code clone. |
## NOTE: There is a "as if in head" code clone. |
| 4916 |
$script_start_tag->(); |
$script_start_tag->(); |
| 4917 |
pop @{$self->{open_elements}} # <head> |
## ISSUE: A spec bug [Bug 6038] |
| 4918 |
if $self->{insertion_mode} == AFTER_HEAD_IM; |
splice @{$self->{open_elements}}, -2, 1 # <head> |
| 4919 |
next B; |
if ($self->{insertion_mode} & AFTER_HEAD_IM) == AFTER_HEAD_IM; |
| 4920 |
} elsif ($token->{tag_name} eq 'body' or |
next B; |
| 4921 |
$token->{tag_name} eq 'frameset') { |
} elsif ($token->{tag_name} eq 'body' or |
| 4922 |
|
$token->{tag_name} eq 'frameset') { |
| 4923 |
if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
| 4924 |
!!!cp ('t122'); |
!!!cp ('t122'); |
| 4925 |
## As if </noscript> |
## As if </noscript> |
| 5054 |
} elsif ({ |
} elsif ({ |
| 5055 |
body => 1, html => 1, |
body => 1, html => 1, |
| 5056 |
}->{$token->{tag_name}}) { |
}->{$token->{tag_name}}) { |
| 5057 |
if ($self->{insertion_mode} == BEFORE_HEAD_IM or |
## TODO: This branch is entirely redundant. |
| 5058 |
|
if ($self->{insertion_mode} == BEFORE_HEAD_IM or |
| 5059 |
$self->{insertion_mode} == IN_HEAD_IM or |
$self->{insertion_mode} == IN_HEAD_IM or |
| 5060 |
$self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
$self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) { |
| 5061 |
!!!cp ('t140'); |
!!!cp ('t140'); |
| 5227 |
} else { |
} else { |
| 5228 |
die "$0: $token->{type}: Unknown token type"; |
die "$0: $token->{type}: Unknown token type"; |
| 5229 |
} |
} |
|
|
|
|
## ISSUE: An issue in the spec. |
|
| 5230 |
} elsif ($self->{insertion_mode} & BODY_IMS) { |
} elsif ($self->{insertion_mode} & BODY_IMS) { |
| 5231 |
if ($token->{type} == CHARACTER_TOKEN) { |
if ($token->{type} == CHARACTER_TOKEN) { |
| 5232 |
!!!cp ('t150'); |
!!!cp ('t150'); |
| 5246 |
## have an element in table scope |
## have an element in table scope |
| 5247 |
for (reverse 0..$#{$self->{open_elements}}) { |
for (reverse 0..$#{$self->{open_elements}}) { |
| 5248 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 5249 |
if ($node->[1] & TABLE_CELL_EL) { |
if ($node->[1] == TABLE_CELL_EL) { |
| 5250 |
!!!cp ('t151'); |
!!!cp ('t151'); |
| 5251 |
|
|
| 5252 |
## Close the cell |
## Close the cell |
| 5280 |
INSCOPE: { |
INSCOPE: { |
| 5281 |
for (reverse 0..$#{$self->{open_elements}}) { |
for (reverse 0..$#{$self->{open_elements}}) { |
| 5282 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 5283 |
if ($node->[1] & CAPTION_EL) { |
if ($node->[1] == CAPTION_EL) { |
| 5284 |
!!!cp ('t155'); |
!!!cp ('t155'); |
| 5285 |
$i = $_; |
$i = $_; |
| 5286 |
last INSCOPE; |
last INSCOPE; |
| 5306 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 5307 |
} |
} |
| 5308 |
|
|
| 5309 |
unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) { |
unless ($self->{open_elements}->[-1]->[1] == CAPTION_EL) { |
| 5310 |
!!!cp ('t159'); |
!!!cp ('t159'); |
| 5311 |
!!!parse-error (type => 'not closed', |
!!!parse-error (type => 'not closed', |
| 5312 |
text => $self->{open_elements}->[-1]->[0] |
text => $self->{open_elements}->[-1]->[0] |
| 5403 |
INSCOPE: { |
INSCOPE: { |
| 5404 |
for (reverse 0..$#{$self->{open_elements}}) { |
for (reverse 0..$#{$self->{open_elements}}) { |
| 5405 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 5406 |
if ($node->[1] & CAPTION_EL) { |
if ($node->[1] == CAPTION_EL) { |
| 5407 |
!!!cp ('t171'); |
!!!cp ('t171'); |
| 5408 |
$i = $_; |
$i = $_; |
| 5409 |
last INSCOPE; |
last INSCOPE; |
| 5428 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 5429 |
} |
} |
| 5430 |
|
|
| 5431 |
unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) { |
unless ($self->{open_elements}->[-1]->[1] == CAPTION_EL) { |
| 5432 |
!!!cp ('t175'); |
!!!cp ('t175'); |
| 5433 |
!!!parse-error (type => 'not closed', |
!!!parse-error (type => 'not closed', |
| 5434 |
text => $self->{open_elements}->[-1]->[0] |
text => $self->{open_elements}->[-1]->[0] |
| 5478 |
line => $token->{line}, |
line => $token->{line}, |
| 5479 |
column => $token->{column}}; |
column => $token->{column}}; |
| 5480 |
next B; |
next B; |
| 5481 |
} elsif ($node->[1] & TABLE_CELL_EL) { |
} elsif ($node->[1] == TABLE_CELL_EL) { |
| 5482 |
!!!cp ('t180'); |
!!!cp ('t180'); |
| 5483 |
$tn = $node->[0]->manakai_local_name; |
$tn = $node->[0]->manakai_local_name; |
| 5484 |
## NOTE: There is exactly one |td| or |th| element |
## NOTE: There is exactly one |td| or |th| element |
| 5507 |
my $i; |
my $i; |
| 5508 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 5509 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 5510 |
if ($node->[1] & CAPTION_EL) { |
if ($node->[1] == CAPTION_EL) { |
| 5511 |
!!!cp ('t184'); |
!!!cp ('t184'); |
| 5512 |
$i = $_; |
$i = $_; |
| 5513 |
last INSCOPE; |
last INSCOPE; |
| 5531 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 5532 |
} |
} |
| 5533 |
|
|
| 5534 |
unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) { |
unless ($self->{open_elements}->[-1]->[1] == CAPTION_EL) { |
| 5535 |
!!!cp ('t188'); |
!!!cp ('t188'); |
| 5536 |
!!!parse-error (type => 'not closed', |
!!!parse-error (type => 'not closed', |
| 5537 |
text => $self->{open_elements}->[-1]->[0] |
text => $self->{open_elements}->[-1]->[0] |
| 5598 |
} elsif ($self->{insertion_mode} & TABLE_IMS) { |
} elsif ($self->{insertion_mode} & TABLE_IMS) { |
| 5599 |
if ($token->{type} == CHARACTER_TOKEN) { |
if ($token->{type} == CHARACTER_TOKEN) { |
| 5600 |
if (not $open_tables->[-1]->[1] and # tainted |
if (not $open_tables->[-1]->[1] and # tainted |
| 5601 |
$token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { |
$token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) { |
| 5602 |
$self->{open_elements}->[-1]->[0]->manakai_append_text ($1); |
$self->{open_elements}->[-1]->[0]->manakai_append_text ($1); |
| 5603 |
|
|
| 5604 |
unless (length $token->{data}) { |
unless (length $token->{data}) { |
| 5612 |
|
|
| 5613 |
!!!parse-error (type => 'in table:#text', token => $token); |
!!!parse-error (type => 'in table:#text', token => $token); |
| 5614 |
|
|
| 5615 |
## As if in body, but insert into foster parent element |
## NOTE: As if in body, but insert into the foster parent element. |
| 5616 |
## ISSUE: Spec says that "whenever a node would be inserted |
$reconstruct_active_formatting_elements->($insert_to_foster); |
|
## into the current node" while characters might not be |
|
|
## result in a new Text node. |
|
|
$reconstruct_active_formatting_elements->($insert_to_foster); |
|
| 5617 |
|
|
| 5618 |
if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) { |
if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) { |
| 5619 |
# MUST |
# MUST |
| 5620 |
my $foster_parent_element; |
my $foster_parent_element; |
| 5621 |
my $next_sibling; |
my $next_sibling; |
| 5622 |
my $prev_sibling; |
my $prev_sibling; |
| 5623 |
OE: for (reverse 0..$#{$self->{open_elements}}) { |
OE: for (reverse 0..$#{$self->{open_elements}}) { |
| 5624 |
if ($self->{open_elements}->[$_]->[1] & TABLE_EL) { |
if ($self->{open_elements}->[$_]->[1] == TABLE_EL) { |
| 5625 |
my $parent = $self->{open_elements}->[$_]->[0]->parent_node; |
my $parent = $self->{open_elements}->[$_]->[0]->parent_node; |
| 5626 |
if (defined $parent and $parent->node_type == 1) { |
if (defined $parent and $parent->node_type == 1) { |
| 5627 |
!!!cp ('t196'); |
$foster_parent_element = $parent; |
| 5628 |
$foster_parent_element = $parent; |
!!!cp ('t196'); |
| 5629 |
$next_sibling = $self->{open_elements}->[$_]->[0]; |
$next_sibling = $self->{open_elements}->[$_]->[0]; |
| 5630 |
$prev_sibling = $next_sibling->previous_sibling; |
$prev_sibling = $next_sibling->previous_sibling; |
| 5631 |
} else { |
# |
|
!!!cp ('t197'); |
|
|
$foster_parent_element = $self->{open_elements}->[$_ - 1]->[0]; |
|
|
$prev_sibling = $foster_parent_element->last_child; |
|
|
} |
|
|
last OE; |
|
|
} |
|
|
} # OE |
|
|
$foster_parent_element = $self->{open_elements}->[0]->[0] and |
|
|
$prev_sibling = $foster_parent_element->last_child |
|
|
unless defined $foster_parent_element; |
|
|
if (defined $prev_sibling and |
|
|
$prev_sibling->node_type == 3) { |
|
|
!!!cp ('t198'); |
|
|
$prev_sibling->manakai_append_text ($token->{data}); |
|
| 5632 |
} else { |
} else { |
| 5633 |
!!!cp ('t199'); |
!!!cp ('t197'); |
| 5634 |
$foster_parent_element->insert_before |
$foster_parent_element = $self->{open_elements}->[$_ - 1]->[0]; |
| 5635 |
($self->{document}->create_text_node ($token->{data}), |
$prev_sibling = $foster_parent_element->last_child; |
| 5636 |
$next_sibling); |
# |
| 5637 |
} |
} |
| 5638 |
|
last OE; |
| 5639 |
|
} |
| 5640 |
|
} # OE |
| 5641 |
|
$foster_parent_element = $self->{open_elements}->[0]->[0] and |
| 5642 |
|
$prev_sibling = $foster_parent_element->last_child |
| 5643 |
|
unless defined $foster_parent_element; |
| 5644 |
|
undef $prev_sibling unless $open_tables->[-1]->[2]; # ~node inserted |
| 5645 |
|
if (defined $prev_sibling and |
| 5646 |
|
$prev_sibling->node_type == 3) { |
| 5647 |
|
!!!cp ('t198'); |
| 5648 |
|
$prev_sibling->manakai_append_text ($token->{data}); |
| 5649 |
|
} else { |
| 5650 |
|
!!!cp ('t199'); |
| 5651 |
|
$foster_parent_element->insert_before |
| 5652 |
|
($self->{document}->create_text_node ($token->{data}), |
| 5653 |
|
$next_sibling); |
| 5654 |
|
} |
| 5655 |
$open_tables->[-1]->[1] = 1; # tainted |
$open_tables->[-1]->[1] = 1; # tainted |
| 5656 |
|
$open_tables->[-1]->[2] = 1; # ~node inserted |
| 5657 |
} else { |
} else { |
| 5658 |
|
## NOTE: Fragment case or in a foster parent'ed element |
| 5659 |
|
## (e.g. |<table><span>a|). In fragment case, whether the |
| 5660 |
|
## character is appended to existing node or a new node is |
| 5661 |
|
## created is irrelevant, since the foster parent'ed nodes |
| 5662 |
|
## are discarded and fragment parsing does not invoke any |
| 5663 |
|
## script. |
| 5664 |
!!!cp ('t200'); |
!!!cp ('t200'); |
| 5665 |
$self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data}); |
$self->{open_elements}->[-1]->[0]->manakai_append_text |
| 5666 |
|
($token->{data}); |
| 5667 |
} |
} |
| 5668 |
|
|
| 5669 |
!!!next-token; |
!!!next-token; |
| 5700 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 5701 |
} |
} |
| 5702 |
|
|
| 5703 |
$self->{insertion_mode} = IN_ROW_IM; |
$self->{insertion_mode} = IN_ROW_IM; |
| 5704 |
if ($token->{tag_name} eq 'tr') { |
if ($token->{tag_name} eq 'tr') { |
| 5705 |
!!!cp ('t204'); |
!!!cp ('t204'); |
| 5706 |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
| 5707 |
!!!nack ('t204'); |
$open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted |
| 5708 |
!!!next-token; |
!!!nack ('t204'); |
| 5709 |
next B; |
!!!next-token; |
| 5710 |
} else { |
next B; |
| 5711 |
!!!cp ('t205'); |
} else { |
| 5712 |
!!!insert-element ('tr',, $token); |
!!!cp ('t205'); |
| 5713 |
## reprocess in the "in row" insertion mode |
!!!insert-element ('tr',, $token); |
| 5714 |
} |
## reprocess in the "in row" insertion mode |
| 5715 |
} else { |
} |
| 5716 |
!!!cp ('t206'); |
} else { |
| 5717 |
} |
!!!cp ('t206'); |
| 5718 |
|
} |
| 5719 |
|
|
| 5720 |
## Clear back to table row context |
## Clear back to table row context |
| 5721 |
while (not ($self->{open_elements}->[-1]->[1] |
while (not ($self->{open_elements}->[-1]->[1] |
| 5724 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 5725 |
} |
} |
| 5726 |
|
|
| 5727 |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
| 5728 |
$self->{insertion_mode} = IN_CELL_IM; |
$open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted |
| 5729 |
|
$self->{insertion_mode} = IN_CELL_IM; |
| 5730 |
|
|
| 5731 |
push @$active_formatting_elements, ['#marker', '']; |
push @$active_formatting_elements, ['#marker', '']; |
| 5732 |
|
|
| 5733 |
!!!nack ('t207.1'); |
!!!nack ('t207.1'); |
| 5734 |
|
!!!next-token; |
| 5735 |
|
next B; |
| 5736 |
|
} elsif ({ |
| 5737 |
|
caption => 1, col => 1, colgroup => 1, |
| 5738 |
|
tbody => 1, tfoot => 1, thead => 1, |
| 5739 |
|
tr => 1, # $self->{insertion_mode} == IN_ROW_IM |
| 5740 |
|
}->{$token->{tag_name}}) { |
| 5741 |
|
if ($self->{insertion_mode} == IN_ROW_IM) { |
| 5742 |
|
## As if </tr> |
| 5743 |
|
## have an element in table scope |
| 5744 |
|
my $i; |
| 5745 |
|
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 5746 |
|
my $node = $self->{open_elements}->[$_]; |
| 5747 |
|
if ($node->[1] == TABLE_ROW_EL) { |
| 5748 |
|
!!!cp ('t208'); |
| 5749 |
|
$i = $_; |
| 5750 |
|
last INSCOPE; |
| 5751 |
|
} elsif ($node->[1] & TABLE_SCOPING_EL) { |
| 5752 |
|
!!!cp ('t209'); |
| 5753 |
|
last INSCOPE; |
| 5754 |
|
} |
| 5755 |
|
} # INSCOPE |
| 5756 |
|
unless (defined $i) { |
| 5757 |
|
!!!cp ('t210'); |
| 5758 |
|
## TODO: This type is wrong. |
| 5759 |
|
!!!parse-error (type => 'unmacthed end tag', |
| 5760 |
|
text => $token->{tag_name}, token => $token); |
| 5761 |
|
## Ignore the token |
| 5762 |
|
!!!nack ('t210.1'); |
| 5763 |
!!!next-token; |
!!!next-token; |
| 5764 |
next B; |
next B; |
| 5765 |
} elsif ({ |
} |
|
caption => 1, col => 1, colgroup => 1, |
|
|
tbody => 1, tfoot => 1, thead => 1, |
|
|
tr => 1, # $self->{insertion_mode} == IN_ROW_IM |
|
|
}->{$token->{tag_name}}) { |
|
|
if ($self->{insertion_mode} == IN_ROW_IM) { |
|
|
## As if </tr> |
|
|
## have an element in table scope |
|
|
my $i; |
|
|
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
|
|
my $node = $self->{open_elements}->[$_]; |
|
|
if ($node->[1] & TABLE_ROW_EL) { |
|
|
!!!cp ('t208'); |
|
|
$i = $_; |
|
|
last INSCOPE; |
|
|
} elsif ($node->[1] & TABLE_SCOPING_EL) { |
|
|
!!!cp ('t209'); |
|
|
last INSCOPE; |
|
|
} |
|
|
} # INSCOPE |
|
|
unless (defined $i) { |
|
|
!!!cp ('t210'); |
|
|
## TODO: This type is wrong. |
|
|
!!!parse-error (type => 'unmacthed end tag', |
|
|
text => $token->{tag_name}, token => $token); |
|
|
## Ignore the token |
|
|
!!!nack ('t210.1'); |
|
|
!!!next-token; |
|
|
next B; |
|
|
} |
|
| 5766 |
|
|
| 5767 |
## Clear back to table row context |
## Clear back to table row context |
| 5768 |
while (not ($self->{open_elements}->[-1]->[1] |
while (not ($self->{open_elements}->[-1]->[1] |
| 5790 |
my $i; |
my $i; |
| 5791 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 5792 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 5793 |
if ($node->[1] & TABLE_ROW_GROUP_EL) { |
if ($node->[1] == TABLE_ROW_GROUP_EL) { |
| 5794 |
!!!cp ('t214'); |
!!!cp ('t214'); |
| 5795 |
$i = $_; |
$i = $_; |
| 5796 |
last INSCOPE; |
last INSCOPE; |
| 5832 |
!!!cp ('t218'); |
!!!cp ('t218'); |
| 5833 |
} |
} |
| 5834 |
|
|
| 5835 |
if ($token->{tag_name} eq 'col') { |
if ($token->{tag_name} eq 'col') { |
| 5836 |
## Clear back to table context |
## Clear back to table context |
| 5837 |
while (not ($self->{open_elements}->[-1]->[1] |
while (not ($self->{open_elements}->[-1]->[1] |
| 5838 |
& TABLE_SCOPING_EL)) { |
& TABLE_SCOPING_EL)) { |
| 5839 |
!!!cp ('t219'); |
!!!cp ('t219'); |
| 5840 |
## ISSUE: Can this state be reached? |
## ISSUE: Can this state be reached? |
| 5841 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 5842 |
} |
} |
| 5843 |
|
|
| 5844 |
!!!insert-element ('colgroup',, $token); |
!!!insert-element ('colgroup',, $token); |
| 5845 |
$self->{insertion_mode} = IN_COLUMN_GROUP_IM; |
$self->{insertion_mode} = IN_COLUMN_GROUP_IM; |
| 5846 |
## reprocess |
## reprocess |
| 5847 |
!!!ack-later; |
$open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted |
| 5848 |
next B; |
!!!ack-later; |
| 5849 |
} elsif ({ |
next B; |
| 5850 |
caption => 1, |
} elsif ({ |
| 5851 |
colgroup => 1, |
caption => 1, |
| 5852 |
tbody => 1, tfoot => 1, thead => 1, |
colgroup => 1, |
| 5853 |
}->{$token->{tag_name}}) { |
tbody => 1, tfoot => 1, thead => 1, |
| 5854 |
## Clear back to table context |
}->{$token->{tag_name}}) { |
| 5855 |
|
## Clear back to table context |
| 5856 |
while (not ($self->{open_elements}->[-1]->[1] |
while (not ($self->{open_elements}->[-1]->[1] |
| 5857 |
& TABLE_SCOPING_EL)) { |
& TABLE_SCOPING_EL)) { |
| 5858 |
!!!cp ('t220'); |
!!!cp ('t220'); |
| 5860 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 5861 |
} |
} |
| 5862 |
|
|
| 5863 |
push @$active_formatting_elements, ['#marker', ''] |
push @$active_formatting_elements, ['#marker', ''] |
| 5864 |
if $token->{tag_name} eq 'caption'; |
if $token->{tag_name} eq 'caption'; |
| 5865 |
|
|
| 5866 |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
| 5867 |
$self->{insertion_mode} = { |
$open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted |
| 5868 |
caption => IN_CAPTION_IM, |
$self->{insertion_mode} = { |
| 5869 |
colgroup => IN_COLUMN_GROUP_IM, |
caption => IN_CAPTION_IM, |
| 5870 |
tbody => IN_TABLE_BODY_IM, |
colgroup => IN_COLUMN_GROUP_IM, |
| 5871 |
tfoot => IN_TABLE_BODY_IM, |
tbody => IN_TABLE_BODY_IM, |
| 5872 |
thead => IN_TABLE_BODY_IM, |
tfoot => IN_TABLE_BODY_IM, |
| 5873 |
}->{$token->{tag_name}}; |
thead => IN_TABLE_BODY_IM, |
| 5874 |
!!!next-token; |
}->{$token->{tag_name}}; |
| 5875 |
!!!nack ('t220.1'); |
!!!next-token; |
| 5876 |
next B; |
!!!nack ('t220.1'); |
| 5877 |
} else { |
next B; |
| 5878 |
die "$0: in table: <>: $token->{tag_name}"; |
} else { |
| 5879 |
} |
die "$0: in table: <>: $token->{tag_name}"; |
| 5880 |
|
} |
| 5881 |
} elsif ($token->{tag_name} eq 'table') { |
} elsif ($token->{tag_name} eq 'table') { |
| 5882 |
!!!parse-error (type => 'not closed', |
!!!parse-error (type => 'not closed', |
| 5883 |
text => $self->{open_elements}->[-1]->[0] |
text => $self->{open_elements}->[-1]->[0] |
| 5889 |
my $i; |
my $i; |
| 5890 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 5891 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 5892 |
if ($node->[1] & TABLE_EL) { |
if ($node->[1] == TABLE_EL) { |
| 5893 |
!!!cp ('t221'); |
!!!cp ('t221'); |
| 5894 |
$i = $_; |
$i = $_; |
| 5895 |
last INSCOPE; |
last INSCOPE; |
| 5916 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 5917 |
} |
} |
| 5918 |
|
|
| 5919 |
unless ($self->{open_elements}->[-1]->[1] & TABLE_EL) { |
unless ($self->{open_elements}->[-1]->[1] == TABLE_EL) { |
| 5920 |
!!!cp ('t225'); |
!!!cp ('t225'); |
| 5921 |
## NOTE: |<table><tr><table>| |
## NOTE: |<table><tr><table>| |
| 5922 |
!!!parse-error (type => 'not closed', |
!!!parse-error (type => 'not closed', |
| 5940 |
!!!cp ('t227.8'); |
!!!cp ('t227.8'); |
| 5941 |
## NOTE: This is a "as if in head" code clone. |
## NOTE: This is a "as if in head" code clone. |
| 5942 |
$parse_rcdata->(CDATA_CONTENT_MODEL); |
$parse_rcdata->(CDATA_CONTENT_MODEL); |
| 5943 |
|
$open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted |
| 5944 |
next B; |
next B; |
| 5945 |
} else { |
} else { |
| 5946 |
!!!cp ('t227.7'); |
!!!cp ('t227.7'); |
| 5951 |
!!!cp ('t227.6'); |
!!!cp ('t227.6'); |
| 5952 |
## NOTE: This is a "as if in head" code clone. |
## NOTE: This is a "as if in head" code clone. |
| 5953 |
$script_start_tag->(); |
$script_start_tag->(); |
| 5954 |
|
$open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted |
| 5955 |
next B; |
next B; |
| 5956 |
} else { |
} else { |
| 5957 |
!!!cp ('t227.5'); |
!!!cp ('t227.5'); |
| 5967 |
text => $token->{tag_name}, token => $token); |
text => $token->{tag_name}, token => $token); |
| 5968 |
|
|
| 5969 |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
!!!insert-element ($token->{tag_name}, $token->{attributes}, $token); |
| 5970 |
|
$open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted |
| 5971 |
|
|
| 5972 |
## TODO: form element pointer |
## TODO: form element pointer |
| 5973 |
|
|
| 6005 |
my $i; |
my $i; |
| 6006 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 6007 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 6008 |
if ($node->[1] & TABLE_ROW_EL) { |
if ($node->[1] == TABLE_ROW_EL) { |
| 6009 |
!!!cp ('t228'); |
!!!cp ('t228'); |
| 6010 |
$i = $_; |
$i = $_; |
| 6011 |
last INSCOPE; |
last INSCOPE; |
| 6046 |
my $i; |
my $i; |
| 6047 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 6048 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 6049 |
if ($node->[1] & TABLE_ROW_EL) { |
if ($node->[1] == TABLE_ROW_EL) { |
| 6050 |
!!!cp ('t233'); |
!!!cp ('t233'); |
| 6051 |
$i = $_; |
$i = $_; |
| 6052 |
last INSCOPE; |
last INSCOPE; |
| 6084 |
my $i; |
my $i; |
| 6085 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 6086 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 6087 |
if ($node->[1] & TABLE_ROW_GROUP_EL) { |
if ($node->[1] == TABLE_ROW_GROUP_EL) { |
| 6088 |
!!!cp ('t237'); |
!!!cp ('t237'); |
| 6089 |
$i = $_; |
$i = $_; |
| 6090 |
last INSCOPE; |
last INSCOPE; |
| 6131 |
my $i; |
my $i; |
| 6132 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 6133 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 6134 |
if ($node->[1] & TABLE_EL) { |
if ($node->[1] == TABLE_EL) { |
| 6135 |
!!!cp ('t241'); |
!!!cp ('t241'); |
| 6136 |
$i = $_; |
$i = $_; |
| 6137 |
last INSCOPE; |
last INSCOPE; |
| 6190 |
my $i; |
my $i; |
| 6191 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 6192 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 6193 |
if ($node->[1] & TABLE_ROW_EL) { |
if ($node->[1] == TABLE_ROW_EL) { |
| 6194 |
!!!cp ('t250'); |
!!!cp ('t250'); |
| 6195 |
$i = $_; |
$i = $_; |
| 6196 |
last INSCOPE; |
last INSCOPE; |
| 6280 |
# |
# |
| 6281 |
} |
} |
| 6282 |
} elsif ($token->{type} == END_OF_FILE_TOKEN) { |
} elsif ($token->{type} == END_OF_FILE_TOKEN) { |
| 6283 |
unless ($self->{open_elements}->[-1]->[1] & HTML_EL and |
unless ($self->{open_elements}->[-1]->[1] == HTML_EL and |
| 6284 |
@{$self->{open_elements}} == 1) { # redundant, maybe |
@{$self->{open_elements}} == 1) { # redundant, maybe |
| 6285 |
!!!parse-error (type => 'in body:#eof', token => $token); |
!!!parse-error (type => 'in body:#eof', token => $token); |
| 6286 |
!!!cp ('t259.1'); |
!!!cp ('t259.1'); |
| 6297 |
} |
} |
| 6298 |
} elsif ($self->{insertion_mode} == IN_COLUMN_GROUP_IM) { |
} elsif ($self->{insertion_mode} == IN_COLUMN_GROUP_IM) { |
| 6299 |
if ($token->{type} == CHARACTER_TOKEN) { |
if ($token->{type} == CHARACTER_TOKEN) { |
| 6300 |
if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { |
if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) { |
| 6301 |
$self->{open_elements}->[-1]->[0]->manakai_append_text ($1); |
$self->{open_elements}->[-1]->[0]->manakai_append_text ($1); |
| 6302 |
unless (length $token->{data}) { |
unless (length $token->{data}) { |
| 6303 |
!!!cp ('t260'); |
!!!cp ('t260'); |
| 6322 |
} |
} |
| 6323 |
} elsif ($token->{type} == END_TAG_TOKEN) { |
} elsif ($token->{type} == END_TAG_TOKEN) { |
| 6324 |
if ($token->{tag_name} eq 'colgroup') { |
if ($token->{tag_name} eq 'colgroup') { |
| 6325 |
if ($self->{open_elements}->[-1]->[1] & HTML_EL) { |
if ($self->{open_elements}->[-1]->[1] == HTML_EL) { |
| 6326 |
!!!cp ('t264'); |
!!!cp ('t264'); |
| 6327 |
!!!parse-error (type => 'unmatched end tag', |
!!!parse-error (type => 'unmatched end tag', |
| 6328 |
text => 'colgroup', token => $token); |
text => 'colgroup', token => $token); |
| 6348 |
# |
# |
| 6349 |
} |
} |
| 6350 |
} elsif ($token->{type} == END_OF_FILE_TOKEN) { |
} elsif ($token->{type} == END_OF_FILE_TOKEN) { |
| 6351 |
if ($self->{open_elements}->[-1]->[1] & HTML_EL and |
if ($self->{open_elements}->[-1]->[1] == HTML_EL and |
| 6352 |
@{$self->{open_elements}} == 1) { # redundant, maybe |
@{$self->{open_elements}} == 1) { # redundant, maybe |
| 6353 |
!!!cp ('t270.2'); |
!!!cp ('t270.2'); |
| 6354 |
## Stop parsing. |
## Stop parsing. |
| 6366 |
} |
} |
| 6367 |
|
|
| 6368 |
## As if </colgroup> |
## As if </colgroup> |
| 6369 |
if ($self->{open_elements}->[-1]->[1] & HTML_EL) { |
if ($self->{open_elements}->[-1]->[1] == HTML_EL) { |
| 6370 |
!!!cp ('t269'); |
!!!cp ('t269'); |
| 6371 |
## TODO: Wrong error type? |
## TODO: Wrong error type? |
| 6372 |
!!!parse-error (type => 'unmatched end tag', |
!!!parse-error (type => 'unmatched end tag', |
| 6391 |
next B; |
next B; |
| 6392 |
} elsif ($token->{type} == START_TAG_TOKEN) { |
} elsif ($token->{type} == START_TAG_TOKEN) { |
| 6393 |
if ($token->{tag_name} eq 'option') { |
if ($token->{tag_name} eq 'option') { |
| 6394 |
if ($self->{open_elements}->[-1]->[1] & OPTION_EL) { |
if ($self->{open_elements}->[-1]->[1] == OPTION_EL) { |
| 6395 |
!!!cp ('t272'); |
!!!cp ('t272'); |
| 6396 |
## As if </option> |
## As if </option> |
| 6397 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 6404 |
!!!next-token; |
!!!next-token; |
| 6405 |
next B; |
next B; |
| 6406 |
} elsif ($token->{tag_name} eq 'optgroup') { |
} elsif ($token->{tag_name} eq 'optgroup') { |
| 6407 |
if ($self->{open_elements}->[-1]->[1] & OPTION_EL) { |
if ($self->{open_elements}->[-1]->[1] == OPTION_EL) { |
| 6408 |
!!!cp ('t274'); |
!!!cp ('t274'); |
| 6409 |
## As if </option> |
## As if </option> |
| 6410 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 6412 |
!!!cp ('t275'); |
!!!cp ('t275'); |
| 6413 |
} |
} |
| 6414 |
|
|
| 6415 |
if ($self->{open_elements}->[-1]->[1] & OPTGROUP_EL) { |
if ($self->{open_elements}->[-1]->[1] == OPTGROUP_EL) { |
| 6416 |
!!!cp ('t276'); |
!!!cp ('t276'); |
| 6417 |
## As if </optgroup> |
## As if </optgroup> |
| 6418 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 6442 |
my $i; |
my $i; |
| 6443 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 6444 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 6445 |
if ($node->[1] & SELECT_EL) { |
if ($node->[1] == SELECT_EL) { |
| 6446 |
!!!cp ('t278'); |
!!!cp ('t278'); |
| 6447 |
$i = $_; |
$i = $_; |
| 6448 |
last INSCOPE; |
last INSCOPE; |
| 6487 |
} |
} |
| 6488 |
} elsif ($token->{type} == END_TAG_TOKEN) { |
} elsif ($token->{type} == END_TAG_TOKEN) { |
| 6489 |
if ($token->{tag_name} eq 'optgroup') { |
if ($token->{tag_name} eq 'optgroup') { |
| 6490 |
if ($self->{open_elements}->[-1]->[1] & OPTION_EL and |
if ($self->{open_elements}->[-1]->[1] == OPTION_EL and |
| 6491 |
$self->{open_elements}->[-2]->[1] & OPTGROUP_EL) { |
$self->{open_elements}->[-2]->[1] == OPTGROUP_EL) { |
| 6492 |
!!!cp ('t283'); |
!!!cp ('t283'); |
| 6493 |
## As if </option> |
## As if </option> |
| 6494 |
splice @{$self->{open_elements}}, -2; |
splice @{$self->{open_elements}}, -2; |
| 6495 |
} elsif ($self->{open_elements}->[-1]->[1] & OPTGROUP_EL) { |
} elsif ($self->{open_elements}->[-1]->[1] == OPTGROUP_EL) { |
| 6496 |
!!!cp ('t284'); |
!!!cp ('t284'); |
| 6497 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 6498 |
} else { |
} else { |
| 6505 |
!!!next-token; |
!!!next-token; |
| 6506 |
next B; |
next B; |
| 6507 |
} elsif ($token->{tag_name} eq 'option') { |
} elsif ($token->{tag_name} eq 'option') { |
| 6508 |
if ($self->{open_elements}->[-1]->[1] & OPTION_EL) { |
if ($self->{open_elements}->[-1]->[1] == OPTION_EL) { |
| 6509 |
!!!cp ('t286'); |
!!!cp ('t286'); |
| 6510 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 6511 |
} else { |
} else { |
| 6522 |
my $i; |
my $i; |
| 6523 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 6524 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 6525 |
if ($node->[1] & SELECT_EL) { |
if ($node->[1] == SELECT_EL) { |
| 6526 |
!!!cp ('t288'); |
!!!cp ('t288'); |
| 6527 |
$i = $_; |
$i = $_; |
| 6528 |
last INSCOPE; |
last INSCOPE; |
| 6584 |
undef $i; |
undef $i; |
| 6585 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 6586 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 6587 |
if ($node->[1] & SELECT_EL) { |
if ($node->[1] == SELECT_EL) { |
| 6588 |
!!!cp ('t295'); |
!!!cp ('t295'); |
| 6589 |
$i = $_; |
$i = $_; |
| 6590 |
last INSCOPE; |
last INSCOPE; |
| 6623 |
next B; |
next B; |
| 6624 |
} |
} |
| 6625 |
} elsif ($token->{type} == END_OF_FILE_TOKEN) { |
} elsif ($token->{type} == END_OF_FILE_TOKEN) { |
| 6626 |
unless ($self->{open_elements}->[-1]->[1] & HTML_EL and |
unless ($self->{open_elements}->[-1]->[1] == HTML_EL and |
| 6627 |
@{$self->{open_elements}} == 1) { # redundant, maybe |
@{$self->{open_elements}} == 1) { # redundant, maybe |
| 6628 |
!!!cp ('t299.1'); |
!!!cp ('t299.1'); |
| 6629 |
!!!parse-error (type => 'in body:#eof', token => $token); |
!!!parse-error (type => 'in body:#eof', token => $token); |
| 6638 |
} |
} |
| 6639 |
} elsif ($self->{insertion_mode} & BODY_AFTER_IMS) { |
} elsif ($self->{insertion_mode} & BODY_AFTER_IMS) { |
| 6640 |
if ($token->{type} == CHARACTER_TOKEN) { |
if ($token->{type} == CHARACTER_TOKEN) { |
| 6641 |
if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { |
if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) { |
| 6642 |
my $data = $1; |
my $data = $1; |
| 6643 |
## As if in body |
## As if in body |
| 6644 |
$reconstruct_active_formatting_elements->($insert_to_current); |
$reconstruct_active_formatting_elements->($insert_to_current); |
| 6655 |
if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) { |
if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) { |
| 6656 |
!!!cp ('t301'); |
!!!cp ('t301'); |
| 6657 |
!!!parse-error (type => 'after html:#text', token => $token); |
!!!parse-error (type => 'after html:#text', token => $token); |
| 6658 |
|
# |
|
## Reprocess in the "after body" insertion mode. |
|
| 6659 |
} else { |
} else { |
| 6660 |
!!!cp ('t302'); |
!!!cp ('t302'); |
| 6661 |
|
## "after body" insertion mode |
| 6662 |
|
!!!parse-error (type => 'after body:#text', token => $token); |
| 6663 |
|
# |
| 6664 |
} |
} |
|
|
|
|
## "after body" insertion mode |
|
|
!!!parse-error (type => 'after body:#text', token => $token); |
|
| 6665 |
|
|
| 6666 |
$self->{insertion_mode} = IN_BODY_IM; |
$self->{insertion_mode} = IN_BODY_IM; |
| 6667 |
## reprocess |
## reprocess |
| 6671 |
!!!cp ('t303'); |
!!!cp ('t303'); |
| 6672 |
!!!parse-error (type => 'after html', |
!!!parse-error (type => 'after html', |
| 6673 |
text => $token->{tag_name}, token => $token); |
text => $token->{tag_name}, token => $token); |
| 6674 |
|
# |
|
## Reprocess in the "after body" insertion mode. |
|
| 6675 |
} else { |
} else { |
| 6676 |
!!!cp ('t304'); |
!!!cp ('t304'); |
| 6677 |
|
## "after body" insertion mode |
| 6678 |
|
!!!parse-error (type => 'after body', |
| 6679 |
|
text => $token->{tag_name}, token => $token); |
| 6680 |
|
# |
| 6681 |
} |
} |
| 6682 |
|
|
|
## "after body" insertion mode |
|
|
!!!parse-error (type => 'after body', |
|
|
text => $token->{tag_name}, token => $token); |
|
|
|
|
| 6683 |
$self->{insertion_mode} = IN_BODY_IM; |
$self->{insertion_mode} = IN_BODY_IM; |
| 6684 |
!!!ack-later; |
!!!ack-later; |
| 6685 |
## reprocess |
## reprocess |
| 6690 |
!!!parse-error (type => 'after html:/', |
!!!parse-error (type => 'after html:/', |
| 6691 |
text => $token->{tag_name}, token => $token); |
text => $token->{tag_name}, token => $token); |
| 6692 |
|
|
| 6693 |
$self->{insertion_mode} = AFTER_BODY_IM; |
$self->{insertion_mode} = IN_BODY_IM; |
| 6694 |
## Reprocess in the "after body" insertion mode. |
## Reprocess. |
| 6695 |
|
next B; |
| 6696 |
} else { |
} else { |
| 6697 |
!!!cp ('t306'); |
!!!cp ('t306'); |
| 6698 |
} |
} |
| 6730 |
} |
} |
| 6731 |
} elsif ($self->{insertion_mode} & FRAME_IMS) { |
} elsif ($self->{insertion_mode} & FRAME_IMS) { |
| 6732 |
if ($token->{type} == CHARACTER_TOKEN) { |
if ($token->{type} == CHARACTER_TOKEN) { |
| 6733 |
if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { |
if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) { |
| 6734 |
$self->{open_elements}->[-1]->[0]->manakai_append_text ($1); |
$self->{open_elements}->[-1]->[0]->manakai_append_text ($1); |
| 6735 |
|
|
| 6736 |
unless (length $token->{data}) { |
unless (length $token->{data}) { |
| 6740 |
} |
} |
| 6741 |
} |
} |
| 6742 |
|
|
| 6743 |
if ($token->{data} =~ s/^[^\x09\x0A\x0B\x0C\x20]+//) { |
if ($token->{data} =~ s/^[^\x09\x0A\x0C\x20]+//) { |
| 6744 |
if ($self->{insertion_mode} == IN_FRAMESET_IM) { |
if ($self->{insertion_mode} == IN_FRAMESET_IM) { |
| 6745 |
!!!cp ('t311'); |
!!!cp ('t311'); |
| 6746 |
!!!parse-error (type => 'in frameset:#text', token => $token); |
!!!parse-error (type => 'in frameset:#text', token => $token); |
| 6810 |
} elsif ($token->{type} == END_TAG_TOKEN) { |
} elsif ($token->{type} == END_TAG_TOKEN) { |
| 6811 |
if ($token->{tag_name} eq 'frameset' and |
if ($token->{tag_name} eq 'frameset' and |
| 6812 |
$self->{insertion_mode} == IN_FRAMESET_IM) { |
$self->{insertion_mode} == IN_FRAMESET_IM) { |
| 6813 |
if ($self->{open_elements}->[-1]->[1] & HTML_EL and |
if ($self->{open_elements}->[-1]->[1] == HTML_EL and |
| 6814 |
@{$self->{open_elements}} == 1) { |
@{$self->{open_elements}} == 1) { |
| 6815 |
!!!cp ('t325'); |
!!!cp ('t325'); |
| 6816 |
!!!parse-error (type => 'unmatched end tag', |
!!!parse-error (type => 'unmatched end tag', |
| 6824 |
} |
} |
| 6825 |
|
|
| 6826 |
if (not defined $self->{inner_html_node} and |
if (not defined $self->{inner_html_node} and |
| 6827 |
not ($self->{open_elements}->[-1]->[1] & FRAMESET_EL)) { |
not ($self->{open_elements}->[-1]->[1] == FRAMESET_EL)) { |
| 6828 |
!!!cp ('t327'); |
!!!cp ('t327'); |
| 6829 |
$self->{insertion_mode} = AFTER_FRAMESET_IM; |
$self->{insertion_mode} = AFTER_FRAMESET_IM; |
| 6830 |
} else { |
} else { |
| 6856 |
next B; |
next B; |
| 6857 |
} |
} |
| 6858 |
} elsif ($token->{type} == END_OF_FILE_TOKEN) { |
} elsif ($token->{type} == END_OF_FILE_TOKEN) { |
| 6859 |
unless ($self->{open_elements}->[-1]->[1] & HTML_EL and |
unless ($self->{open_elements}->[-1]->[1] == HTML_EL and |
| 6860 |
@{$self->{open_elements}} == 1) { # redundant, maybe |
@{$self->{open_elements}} == 1) { # redundant, maybe |
| 6861 |
!!!cp ('t331.1'); |
!!!cp ('t331.1'); |
| 6862 |
!!!parse-error (type => 'in body:#eof', token => $token); |
!!!parse-error (type => 'in body:#eof', token => $token); |
| 6869 |
} else { |
} else { |
| 6870 |
die "$0: $token->{type}: Unknown token type"; |
die "$0: $token->{type}: Unknown token type"; |
| 6871 |
} |
} |
|
|
|
|
## ISSUE: An issue in spec here |
|
| 6872 |
} else { |
} else { |
| 6873 |
die "$0: $self->{insertion_mode}: Unknown insertion mode"; |
die "$0: $self->{insertion_mode}: Unknown insertion mode"; |
| 6874 |
} |
} |
| 6886 |
$parse_rcdata->(CDATA_CONTENT_MODEL); |
$parse_rcdata->(CDATA_CONTENT_MODEL); |
| 6887 |
next B; |
next B; |
| 6888 |
} elsif ({ |
} elsif ({ |
| 6889 |
base => 1, link => 1, |
base => 1, command => 1, eventsource => 1, link => 1, |
| 6890 |
}->{$token->{tag_name}}) { |
}->{$token->{tag_name}}) { |
| 6891 |
!!!cp ('t334'); |
!!!cp ('t334'); |
| 6892 |
## NOTE: This is an "as if in head" code clone, only "-t" differs |
## NOTE: This is an "as if in head" code clone, only "-t" differs |
| 6893 |
!!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token); |
!!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token); |
| 6894 |
pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec. |
pop @{$self->{open_elements}}; |
| 6895 |
!!!ack ('t334.1'); |
!!!ack ('t334.1'); |
| 6896 |
!!!next-token; |
!!!next-token; |
| 6897 |
next B; |
next B; |
| 6898 |
} elsif ($token->{tag_name} eq 'meta') { |
} elsif ($token->{tag_name} eq 'meta') { |
| 6899 |
## NOTE: This is an "as if in head" code clone, only "-t" differs |
## NOTE: This is an "as if in head" code clone, only "-t" differs |
| 6900 |
!!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token); |
!!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token); |
| 6901 |
my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec. |
my $meta_el = pop @{$self->{open_elements}}; |
| 6902 |
|
|
| 6903 |
unless ($self->{confident}) { |
unless ($self->{confident}) { |
| 6904 |
if ($token->{attributes}->{charset}) { |
if ($token->{attributes}->{charset}) { |
| 6915 |
} elsif ($token->{attributes}->{content}) { |
} elsif ($token->{attributes}->{content}) { |
| 6916 |
if ($token->{attributes}->{content}->{value} |
if ($token->{attributes}->{content}->{value} |
| 6917 |
=~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt] |
=~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt] |
| 6918 |
[\x09-\x0D\x20]*= |
[\x09\x0A\x0C\x0D\x20]*= |
| 6919 |
[\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'| |
[\x09\x0A\x0C\x0D\x20]*(?>"([^"]*)"|'([^']*)'| |
| 6920 |
([^"'\x09-\x0D\x20][^\x09-\x0D\x20\x3B]*))/x) { |
([^"'\x09\x0A\x0C\x0D\x20][^\x09\x0A\x0C\x0D\x20\x3B]*)) |
| 6921 |
|
/x) { |
| 6922 |
!!!cp ('t336'); |
!!!cp ('t336'); |
| 6923 |
## NOTE: Whether the encoding is supported or not is handled |
## NOTE: Whether the encoding is supported or not is handled |
| 6924 |
## in the {change_encoding} callback. |
## in the {change_encoding} callback. |
| 6959 |
!!!parse-error (type => 'in body', text => 'body', token => $token); |
!!!parse-error (type => 'in body', text => 'body', token => $token); |
| 6960 |
|
|
| 6961 |
if (@{$self->{open_elements}} == 1 or |
if (@{$self->{open_elements}} == 1 or |
| 6962 |
not ($self->{open_elements}->[1]->[1] & BODY_EL)) { |
not ($self->{open_elements}->[1]->[1] == BODY_EL)) { |
| 6963 |
!!!cp ('t342'); |
!!!cp ('t342'); |
| 6964 |
## Ignore the token |
## Ignore the token |
| 6965 |
} else { |
} else { |
| 6977 |
!!!next-token; |
!!!next-token; |
| 6978 |
next B; |
next B; |
| 6979 |
} elsif ({ |
} elsif ({ |
| 6980 |
address => 1, blockquote => 1, center => 1, dir => 1, |
## NOTE: Start tags for non-phrasing flow content elements |
| 6981 |
div => 1, dl => 1, fieldset => 1, |
|
| 6982 |
h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1, |
## NOTE: The normal one |
| 6983 |
menu => 1, ol => 1, p => 1, ul => 1, |
address => 1, article => 1, aside => 1, blockquote => 1, |
| 6984 |
|
center => 1, datagrid => 1, details => 1, dialog => 1, |
| 6985 |
|
dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1, |
| 6986 |
|
footer => 1, h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, |
| 6987 |
|
h6 => 1, header => 1, menu => 1, nav => 1, ol => 1, p => 1, |
| 6988 |
|
section => 1, ul => 1, |
| 6989 |
|
## NOTE: As normal, but drops leading newline |
| 6990 |
pre => 1, listing => 1, |
pre => 1, listing => 1, |
| 6991 |
|
## NOTE: As normal, but interacts with the form element pointer |
| 6992 |
form => 1, |
form => 1, |
| 6993 |
|
|
| 6994 |
table => 1, |
table => 1, |
| 6995 |
hr => 1, |
hr => 1, |
| 6996 |
}->{$token->{tag_name}}) { |
}->{$token->{tag_name}}) { |
| 7005 |
|
|
| 7006 |
## has a p element in scope |
## has a p element in scope |
| 7007 |
INSCOPE: for (reverse @{$self->{open_elements}}) { |
INSCOPE: for (reverse @{$self->{open_elements}}) { |
| 7008 |
if ($_->[1] & P_EL) { |
if ($_->[1] == P_EL) { |
| 7009 |
!!!cp ('t344'); |
!!!cp ('t344'); |
| 7010 |
!!!back-token; # <form> |
!!!back-token; # <form> |
| 7011 |
$token = {type => END_TAG_TOKEN, tag_name => 'p', |
$token = {type => END_TAG_TOKEN, tag_name => 'p', |
| 7057 |
!!!next-token; |
!!!next-token; |
| 7058 |
} |
} |
| 7059 |
next B; |
next B; |
| 7060 |
} elsif ({li => 1, dt => 1, dd => 1}->{$token->{tag_name}}) { |
} elsif ($token->{tag_name} eq 'li') { |
| 7061 |
## has a p element in scope |
## NOTE: As normal, but imply </li> when there's another <li> ... |
| 7062 |
|
|
| 7063 |
|
## NOTE: Special, Scope (<li><foo><li> == <li><foo><li/></foo></li>) |
| 7064 |
|
## Interpreted as <li><foo/></li><li/> (non-conforming) |
| 7065 |
|
## blockquote (O9.27), center (O), dd (Fx3, O, S3.1.2, IE7), |
| 7066 |
|
## dt (Fx, O, S, IE), dl (O), fieldset (O, S, IE), form (Fx, O, S), |
| 7067 |
|
## hn (O), pre (O), applet (O, S), button (O, S), marquee (Fx, O, S), |
| 7068 |
|
## object (Fx) |
| 7069 |
|
## Generate non-tree (non-conforming) |
| 7070 |
|
## basefont (IE7 (where basefont is non-void)), center (IE), |
| 7071 |
|
## form (IE), hn (IE) |
| 7072 |
|
## address, div, p (<li><foo><li> == <li><foo/></li><li/>) |
| 7073 |
|
## Interpreted as <li><foo><li/></foo></li> (non-conforming) |
| 7074 |
|
## div (Fx, S) |
| 7075 |
|
|
| 7076 |
|
my $non_optional; |
| 7077 |
|
my $i = -1; |
| 7078 |
|
|
| 7079 |
|
## 1. |
| 7080 |
|
for my $node (reverse @{$self->{open_elements}}) { |
| 7081 |
|
if ($node->[1] == LI_EL) { |
| 7082 |
|
## 2. (a) As if </li> |
| 7083 |
|
{ |
| 7084 |
|
## If no </li> - not applied |
| 7085 |
|
# |
| 7086 |
|
|
| 7087 |
|
## Otherwise |
| 7088 |
|
|
| 7089 |
|
## 1. generate implied end tags, except for </li> |
| 7090 |
|
# |
| 7091 |
|
|
| 7092 |
|
## 2. If current node != "li", parse error |
| 7093 |
|
if ($non_optional) { |
| 7094 |
|
!!!parse-error (type => 'not closed', |
| 7095 |
|
text => $non_optional->[0]->manakai_local_name, |
| 7096 |
|
token => $token); |
| 7097 |
|
!!!cp ('t355'); |
| 7098 |
|
} else { |
| 7099 |
|
!!!cp ('t356'); |
| 7100 |
|
} |
| 7101 |
|
|
| 7102 |
|
## 3. Pop |
| 7103 |
|
splice @{$self->{open_elements}}, $i; |
| 7104 |
|
} |
| 7105 |
|
|
| 7106 |
|
last; ## 2. (b) goto 5. |
| 7107 |
|
} elsif ( |
| 7108 |
|
## NOTE: not "formatting" and not "phrasing" |
| 7109 |
|
($node->[1] & SPECIAL_EL or |
| 7110 |
|
$node->[1] & SCOPING_EL) and |
| 7111 |
|
## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|. |
| 7112 |
|
(not $node->[1] & ADDRESS_DIV_P_EL) |
| 7113 |
|
) { |
| 7114 |
|
## 3. |
| 7115 |
|
!!!cp ('t357'); |
| 7116 |
|
last; ## goto 5. |
| 7117 |
|
} elsif ($node->[1] & END_TAG_OPTIONAL_EL) { |
| 7118 |
|
!!!cp ('t358'); |
| 7119 |
|
# |
| 7120 |
|
} else { |
| 7121 |
|
!!!cp ('t359'); |
| 7122 |
|
$non_optional ||= $node; |
| 7123 |
|
# |
| 7124 |
|
} |
| 7125 |
|
## 4. |
| 7126 |
|
## goto 2. |
| 7127 |
|
$i--; |
| 7128 |
|
} |
| 7129 |
|
|
| 7130 |
|
## 5. (a) has a |p| element in scope |
| 7131 |
INSCOPE: for (reverse @{$self->{open_elements}}) { |
INSCOPE: for (reverse @{$self->{open_elements}}) { |
| 7132 |
if ($_->[1] & P_EL) { |
if ($_->[1] == P_EL) { |
| 7133 |
!!!cp ('t353'); |
!!!cp ('t353'); |
| 7134 |
|
|
| 7135 |
|
## NOTE: |<p><li>|, for example. |
| 7136 |
|
|
| 7137 |
!!!back-token; # <x> |
!!!back-token; # <x> |
| 7138 |
$token = {type => END_TAG_TOKEN, tag_name => 'p', |
$token = {type => END_TAG_TOKEN, tag_name => 'p', |
| 7139 |
line => $token->{line}, column => $token->{column}}; |
line => $token->{line}, column => $token->{column}}; |
| 7143 |
last INSCOPE; |
last INSCOPE; |
| 7144 |
} |
} |
| 7145 |
} # INSCOPE |
} # INSCOPE |
| 7146 |
|
|
| 7147 |
## Step 1 |
## 5. (b) insert |
| 7148 |
|
!!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token); |
| 7149 |
|
!!!nack ('t359.1'); |
| 7150 |
|
!!!next-token; |
| 7151 |
|
next B; |
| 7152 |
|
} elsif ($token->{tag_name} eq 'dt' or |
| 7153 |
|
$token->{tag_name} eq 'dd') { |
| 7154 |
|
## NOTE: As normal, but imply </dt> or </dd> when ... |
| 7155 |
|
|
| 7156 |
|
my $non_optional; |
| 7157 |
my $i = -1; |
my $i = -1; |
| 7158 |
my $node = $self->{open_elements}->[$i]; |
|
| 7159 |
my $li_or_dtdd = {li => {li => 1}, |
## 1. |
| 7160 |
dt => {dt => 1, dd => 1}, |
for my $node (reverse @{$self->{open_elements}}) { |
| 7161 |
dd => {dt => 1, dd => 1}}->{$token->{tag_name}}; |
if ($node->[1] == DTDD_EL) { |
| 7162 |
LI: { |
## 2. (a) As if </li> |
| 7163 |
## Step 2 |
{ |
| 7164 |
if ($li_or_dtdd->{$node->[0]->manakai_local_name}) { |
## If no </li> - not applied |
| 7165 |
if ($i != -1) { |
# |
| 7166 |
!!!cp ('t355'); |
|
| 7167 |
!!!parse-error (type => 'not closed', |
## Otherwise |
| 7168 |
text => $self->{open_elements}->[-1]->[0] |
|
| 7169 |
->manakai_local_name, |
## 1. generate implied end tags, except for </dt> or </dd> |
| 7170 |
token => $token); |
# |
| 7171 |
} else { |
|
| 7172 |
!!!cp ('t356'); |
## 2. If current node != "dt"|"dd", parse error |
| 7173 |
|
if ($non_optional) { |
| 7174 |
|
!!!parse-error (type => 'not closed', |
| 7175 |
|
text => $non_optional->[0]->manakai_local_name, |
| 7176 |
|
token => $token); |
| 7177 |
|
!!!cp ('t355.1'); |
| 7178 |
|
} else { |
| 7179 |
|
!!!cp ('t356.1'); |
| 7180 |
|
} |
| 7181 |
|
|
| 7182 |
|
## 3. Pop |
| 7183 |
|
splice @{$self->{open_elements}}, $i; |
| 7184 |
} |
} |
| 7185 |
splice @{$self->{open_elements}}, $i; |
|
| 7186 |
last LI; |
last; ## 2. (b) goto 5. |
| 7187 |
|
} elsif ( |
| 7188 |
|
## NOTE: not "formatting" and not "phrasing" |
| 7189 |
|
($node->[1] & SPECIAL_EL or |
| 7190 |
|
$node->[1] & SCOPING_EL) and |
| 7191 |
|
## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|. |
| 7192 |
|
|
| 7193 |
|
(not $node->[1] & ADDRESS_DIV_P_EL) |
| 7194 |
|
) { |
| 7195 |
|
## 3. |
| 7196 |
|
!!!cp ('t357.1'); |
| 7197 |
|
last; ## goto 5. |
| 7198 |
|
} elsif ($node->[1] & END_TAG_OPTIONAL_EL) { |
| 7199 |
|
!!!cp ('t358.1'); |
| 7200 |
|
# |
| 7201 |
} else { |
} else { |
| 7202 |
!!!cp ('t357'); |
!!!cp ('t359.1'); |
| 7203 |
} |
$non_optional ||= $node; |
| 7204 |
|
# |
|
## Step 3 |
|
|
if (not ($node->[1] & FORMATTING_EL) and |
|
|
#not $phrasing_category->{$node->[1]} and |
|
|
($node->[1] & SPECIAL_EL or |
|
|
$node->[1] & SCOPING_EL) and |
|
|
not ($node->[1] & ADDRESS_EL) and |
|
|
not ($node->[1] & DIV_EL)) { |
|
|
!!!cp ('t358'); |
|
|
last LI; |
|
| 7205 |
} |
} |
| 7206 |
|
## 4. |
| 7207 |
!!!cp ('t359'); |
## goto 2. |
|
## Step 4 |
|
| 7208 |
$i--; |
$i--; |
| 7209 |
$node = $self->{open_elements}->[$i]; |
} |
| 7210 |
redo LI; |
|
| 7211 |
} # LI |
## 5. (a) has a |p| element in scope |
| 7212 |
|
INSCOPE: for (reverse @{$self->{open_elements}}) { |
| 7213 |
|
if ($_->[1] == P_EL) { |
| 7214 |
|
!!!cp ('t353.1'); |
| 7215 |
|
!!!back-token; # <x> |
| 7216 |
|
$token = {type => END_TAG_TOKEN, tag_name => 'p', |
| 7217 |
|
line => $token->{line}, column => $token->{column}}; |
| 7218 |
|
next B; |
| 7219 |
|
} elsif ($_->[1] & SCOPING_EL) { |
| 7220 |
|
!!!cp ('t354.1'); |
| 7221 |
|
last INSCOPE; |
| 7222 |
|
} |
| 7223 |
|
} # INSCOPE |
| 7224 |
|
|
| 7225 |
|
## 5. (b) insert |
| 7226 |
!!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token); |
!!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token); |
| 7227 |
!!!nack ('t359.1'); |
!!!nack ('t359.2'); |
| 7228 |
!!!next-token; |
!!!next-token; |
| 7229 |
next B; |
next B; |
| 7230 |
} elsif ($token->{tag_name} eq 'plaintext') { |
} elsif ($token->{tag_name} eq 'plaintext') { |
| 7231 |
|
## NOTE: As normal, but effectively ends parsing |
| 7232 |
|
|
| 7233 |
## has a p element in scope |
## has a p element in scope |
| 7234 |
INSCOPE: for (reverse @{$self->{open_elements}}) { |
INSCOPE: for (reverse @{$self->{open_elements}}) { |
| 7235 |
if ($_->[1] & P_EL) { |
if ($_->[1] == P_EL) { |
| 7236 |
!!!cp ('t367'); |
!!!cp ('t367'); |
| 7237 |
!!!back-token; # <plaintext> |
!!!back-token; # <plaintext> |
| 7238 |
$token = {type => END_TAG_TOKEN, tag_name => 'p', |
$token = {type => END_TAG_TOKEN, tag_name => 'p', |
| 7254 |
} elsif ($token->{tag_name} eq 'a') { |
} elsif ($token->{tag_name} eq 'a') { |
| 7255 |
AFE: for my $i (reverse 0..$#$active_formatting_elements) { |
AFE: for my $i (reverse 0..$#$active_formatting_elements) { |
| 7256 |
my $node = $active_formatting_elements->[$i]; |
my $node = $active_formatting_elements->[$i]; |
| 7257 |
if ($node->[1] & A_EL) { |
if ($node->[1] == A_EL) { |
| 7258 |
!!!cp ('t371'); |
!!!cp ('t371'); |
| 7259 |
!!!parse-error (type => 'in a:a', token => $token); |
!!!parse-error (type => 'in a:a', token => $token); |
| 7260 |
|
|
| 7298 |
## has a |nobr| element in scope |
## has a |nobr| element in scope |
| 7299 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 7300 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 7301 |
if ($node->[1] & NOBR_EL) { |
if ($node->[1] == NOBR_EL) { |
| 7302 |
!!!cp ('t376'); |
!!!cp ('t376'); |
| 7303 |
!!!parse-error (type => 'in nobr:nobr', token => $token); |
!!!parse-error (type => 'in nobr:nobr', token => $token); |
| 7304 |
!!!back-token; # <nobr> |
!!!back-token; # <nobr> |
| 7321 |
## has a button element in scope |
## has a button element in scope |
| 7322 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 7323 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 7324 |
if ($node->[1] & BUTTON_EL) { |
if ($node->[1] == BUTTON_EL) { |
| 7325 |
!!!cp ('t378'); |
!!!cp ('t378'); |
| 7326 |
!!!parse-error (type => 'in button:button', token => $token); |
!!!parse-error (type => 'in button:button', token => $token); |
| 7327 |
!!!back-token; # <button> |
!!!back-token; # <button> |
| 7421 |
next B; |
next B; |
| 7422 |
} |
} |
| 7423 |
} elsif ($token->{tag_name} eq 'textarea') { |
} elsif ($token->{tag_name} eq 'textarea') { |
| 7424 |
my $tag_name = $token->{tag_name}; |
## Step 1 |
| 7425 |
my $el; |
!!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token); |
|
!!!create-element ($el, $HTML_NS, $token->{tag_name}, $token->{attributes}, $token); |
|
| 7426 |
|
|
| 7427 |
|
## Step 2 |
| 7428 |
## TODO: $self->{form_element} if defined |
## TODO: $self->{form_element} if defined |
| 7429 |
|
|
| 7430 |
|
## Step 3 |
| 7431 |
|
$self->{ignore_newline} = 1; |
| 7432 |
|
|
| 7433 |
|
## Step 4 |
| 7434 |
|
## ISSUE: This step is wrong. (r2302 enbugged) |
| 7435 |
|
|
| 7436 |
|
## Step 5 |
| 7437 |
$self->{content_model} = RCDATA_CONTENT_MODEL; |
$self->{content_model} = RCDATA_CONTENT_MODEL; |
| 7438 |
delete $self->{escape}; # MUST |
delete $self->{escape}; # MUST |
| 7439 |
|
|
| 7440 |
$insert->($el); |
## Step 6-7 |
| 7441 |
|
$self->{insertion_mode} |= IN_CDATA_RCDATA_IM; |
| 7442 |
my $text = ''; |
|
| 7443 |
!!!nack ('t392.1'); |
!!!nack ('t392.1'); |
| 7444 |
!!!next-token; |
!!!next-token; |
| 7445 |
if ($token->{type} == CHARACTER_TOKEN) { |
next B; |
| 7446 |
$token->{data} =~ s/^\x0A//; |
} elsif ($token->{tag_name} eq 'optgroup' or |
| 7447 |
unless (length $token->{data}) { |
$token->{tag_name} eq 'option') { |
| 7448 |
!!!cp ('t392'); |
## has an |option| element in scope |
| 7449 |
!!!next-token; |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 7450 |
} else { |
my $node = $self->{open_elements}->[$_]; |
| 7451 |
!!!cp ('t393'); |
if ($node->[1] == OPTION_EL) { |
| 7452 |
|
!!!cp ('t397.1'); |
| 7453 |
|
## NOTE: As if </option> |
| 7454 |
|
!!!back-token; # <option> or <optgroup> |
| 7455 |
|
$token = {type => END_TAG_TOKEN, tag_name => 'option', |
| 7456 |
|
line => $token->{line}, column => $token->{column}}; |
| 7457 |
|
next B; |
| 7458 |
|
} elsif ($node->[1] & SCOPING_EL) { |
| 7459 |
|
!!!cp ('t397.2'); |
| 7460 |
|
last INSCOPE; |
| 7461 |
} |
} |
| 7462 |
} else { |
} # INSCOPE |
| 7463 |
!!!cp ('t394'); |
|
| 7464 |
} |
$reconstruct_active_formatting_elements->($insert_to_current); |
| 7465 |
while ($token->{type} == CHARACTER_TOKEN) { |
|
| 7466 |
!!!cp ('t395'); |
!!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token); |
| 7467 |
$text .= $token->{data}; |
|
| 7468 |
!!!next-token; |
!!!nack ('t397.3'); |
|
} |
|
|
if (length $text) { |
|
|
!!!cp ('t396'); |
|
|
$el->manakai_append_text ($text); |
|
|
} |
|
|
|
|
|
$self->{content_model} = PCDATA_CONTENT_MODEL; |
|
|
|
|
|
if ($token->{type} == END_TAG_TOKEN and |
|
|
$token->{tag_name} eq $tag_name) { |
|
|
!!!cp ('t397'); |
|
|
## Ignore the token |
|
|
} else { |
|
|
!!!cp ('t398'); |
|
|
!!!parse-error (type => 'in RCDATA:#eof', token => $token); |
|
|
} |
|
| 7469 |
!!!next-token; |
!!!next-token; |
| 7470 |
next B; |
redo B; |
| 7471 |
} elsif ($token->{tag_name} eq 'rt' or |
} elsif ($token->{tag_name} eq 'rt' or |
| 7472 |
$token->{tag_name} eq 'rp') { |
$token->{tag_name} eq 'rp') { |
| 7473 |
## has a |ruby| element in scope |
## has a |ruby| element in scope |
| 7474 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 7475 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 7476 |
if ($node->[1] & RUBY_EL) { |
if ($node->[1] == RUBY_EL) { |
| 7477 |
!!!cp ('t398.1'); |
!!!cp ('t398.1'); |
| 7478 |
## generate implied end tags |
## generate implied end tags |
| 7479 |
while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) { |
while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) { |
| 7480 |
!!!cp ('t398.2'); |
!!!cp ('t398.2'); |
| 7481 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 7482 |
} |
} |
| 7483 |
unless ($self->{open_elements}->[-1]->[1] & RUBY_EL) { |
unless ($self->{open_elements}->[-1]->[1] == RUBY_EL) { |
| 7484 |
!!!cp ('t398.3'); |
!!!cp ('t398.3'); |
| 7485 |
!!!parse-error (type => 'not closed', |
!!!parse-error (type => 'not closed', |
| 7486 |
text => $self->{open_elements}->[-1]->[0] |
text => $self->{open_elements}->[-1]->[0] |
| 7487 |
->manakai_local_name, |
->manakai_local_name, |
| 7488 |
token => $token); |
token => $token); |
| 7489 |
pop @{$self->{open_elements}} |
pop @{$self->{open_elements}} |
| 7490 |
while not $self->{open_elements}->[-1]->[1] & RUBY_EL; |
while not $self->{open_elements}->[-1]->[1] == RUBY_EL; |
| 7491 |
} |
} |
| 7492 |
last INSCOPE; |
last INSCOPE; |
| 7493 |
} elsif ($node->[1] & SCOPING_EL) { |
} elsif ($node->[1] & SCOPING_EL) { |
| 7515 |
|
|
| 7516 |
if ($self->{self_closing}) { |
if ($self->{self_closing}) { |
| 7517 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 7518 |
!!!ack ('t398.1'); |
!!!ack ('t398.6'); |
| 7519 |
} else { |
} else { |
| 7520 |
!!!cp ('t398.2'); |
!!!cp ('t398.7'); |
| 7521 |
$self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM; |
$self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM; |
| 7522 |
## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion |
## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion |
| 7523 |
## mode, "in body" (not "in foreign content") secondary insertion |
## mode, "in body" (not "in foreign content") secondary insertion |
| 7528 |
next B; |
next B; |
| 7529 |
} elsif ({ |
} elsif ({ |
| 7530 |
caption => 1, col => 1, colgroup => 1, frame => 1, |
caption => 1, col => 1, colgroup => 1, frame => 1, |
| 7531 |
frameset => 1, head => 1, option => 1, optgroup => 1, |
frameset => 1, head => 1, |
| 7532 |
tbody => 1, td => 1, tfoot => 1, th => 1, |
tbody => 1, td => 1, tfoot => 1, th => 1, |
| 7533 |
thead => 1, tr => 1, |
thead => 1, tr => 1, |
| 7534 |
}->{$token->{tag_name}}) { |
}->{$token->{tag_name}}) { |
| 7539 |
!!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error. |
!!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error. |
| 7540 |
!!!next-token; |
!!!next-token; |
| 7541 |
next B; |
next B; |
| 7542 |
|
} elsif ($token->{tag_name} eq 'param' or |
| 7543 |
## ISSUE: An issue on HTML5 new elements in the spec. |
$token->{tag_name} eq 'source') { |
| 7544 |
|
!!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token); |
| 7545 |
|
pop @{$self->{open_elements}}; |
| 7546 |
|
|
| 7547 |
|
!!!ack ('t398.5'); |
| 7548 |
|
!!!next-token; |
| 7549 |
|
redo B; |
| 7550 |
} else { |
} else { |
| 7551 |
if ($token->{tag_name} eq 'image') { |
if ($token->{tag_name} eq 'image') { |
| 7552 |
!!!cp ('t384'); |
!!!cp ('t384'); |
| 7569 |
!!!nack ('t380.1'); |
!!!nack ('t380.1'); |
| 7570 |
} elsif ({ |
} elsif ({ |
| 7571 |
b => 1, big => 1, em => 1, font => 1, i => 1, |
b => 1, big => 1, em => 1, font => 1, i => 1, |
| 7572 |
s => 1, small => 1, strile => 1, |
s => 1, small => 1, strike => 1, |
| 7573 |
strong => 1, tt => 1, u => 1, |
strong => 1, tt => 1, u => 1, |
| 7574 |
}->{$token->{tag_name}}) { |
}->{$token->{tag_name}}) { |
| 7575 |
!!!cp ('t375'); |
!!!cp ('t375'); |
| 7582 |
!!!ack ('t388.2'); |
!!!ack ('t388.2'); |
| 7583 |
} elsif ({ |
} elsif ({ |
| 7584 |
area => 1, basefont => 1, bgsound => 1, br => 1, |
area => 1, basefont => 1, bgsound => 1, br => 1, |
| 7585 |
embed => 1, img => 1, param => 1, spacer => 1, wbr => 1, |
embed => 1, img => 1, spacer => 1, wbr => 1, |
|
#image => 1, |
|
| 7586 |
}->{$token->{tag_name}}) { |
}->{$token->{tag_name}}) { |
| 7587 |
!!!cp ('t388.1'); |
!!!cp ('t388.1'); |
| 7588 |
pop @{$self->{open_elements}}; |
pop @{$self->{open_elements}}; |
| 7613 |
my $i; |
my $i; |
| 7614 |
INSCOPE: { |
INSCOPE: { |
| 7615 |
for (reverse @{$self->{open_elements}}) { |
for (reverse @{$self->{open_elements}}) { |
| 7616 |
if ($_->[1] & BODY_EL) { |
if ($_->[1] == BODY_EL) { |
| 7617 |
!!!cp ('t405'); |
!!!cp ('t405'); |
| 7618 |
$i = $_; |
$i = $_; |
| 7619 |
last INSCOPE; |
last INSCOPE; |
| 7623 |
} |
} |
| 7624 |
} |
} |
| 7625 |
|
|
| 7626 |
!!!parse-error (type => 'start tag not allowed', |
## NOTE: |<marquee></body>|, |<svg><foreignobject></body>| |
| 7627 |
|
|
| 7628 |
|
!!!parse-error (type => 'unmatched end tag', |
| 7629 |
text => $token->{tag_name}, token => $token); |
text => $token->{tag_name}, token => $token); |
| 7630 |
## NOTE: Ignore the token. |
## NOTE: Ignore the token. |
| 7631 |
!!!next-token; |
!!!next-token; |
| 7651 |
## TODO: Update this code. It seems that the code below is not |
## TODO: Update this code. It seems that the code below is not |
| 7652 |
## up-to-date, though it has same effect as speced. |
## up-to-date, though it has same effect as speced. |
| 7653 |
if (@{$self->{open_elements}} > 1 and |
if (@{$self->{open_elements}} > 1 and |
| 7654 |
$self->{open_elements}->[1]->[1] & BODY_EL) { |
$self->{open_elements}->[1]->[1] == BODY_EL) { |
| 7655 |
## ISSUE: There is an issue in the spec. |
unless ($self->{open_elements}->[-1]->[1] == BODY_EL) { |
|
unless ($self->{open_elements}->[-1]->[1] & BODY_EL) { |
|
| 7656 |
!!!cp ('t406'); |
!!!cp ('t406'); |
| 7657 |
!!!parse-error (type => 'not closed', |
!!!parse-error (type => 'not closed', |
| 7658 |
text => $self->{open_elements}->[1]->[0] |
text => $self->{open_elements}->[1]->[0] |
| 7673 |
next B; |
next B; |
| 7674 |
} |
} |
| 7675 |
} elsif ({ |
} elsif ({ |
| 7676 |
address => 1, blockquote => 1, center => 1, dir => 1, |
## NOTE: End tags for non-phrasing flow content elements |
| 7677 |
div => 1, dl => 1, fieldset => 1, listing => 1, |
|
| 7678 |
menu => 1, ol => 1, pre => 1, ul => 1, |
## NOTE: The normal ones |
| 7679 |
|
address => 1, article => 1, aside => 1, blockquote => 1, |
| 7680 |
|
center => 1, datagrid => 1, details => 1, dialog => 1, |
| 7681 |
|
dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1, |
| 7682 |
|
footer => 1, header => 1, listing => 1, menu => 1, nav => 1, |
| 7683 |
|
ol => 1, pre => 1, section => 1, ul => 1, |
| 7684 |
|
|
| 7685 |
|
## NOTE: As normal, but ... optional tags |
| 7686 |
dd => 1, dt => 1, li => 1, |
dd => 1, dt => 1, li => 1, |
| 7687 |
|
|
| 7688 |
applet => 1, button => 1, marquee => 1, object => 1, |
applet => 1, button => 1, marquee => 1, object => 1, |
| 7689 |
}->{$token->{tag_name}}) { |
}->{$token->{tag_name}}) { |
| 7690 |
|
## NOTE: Code for <li> start tags includes "as if </li>" code. |
| 7691 |
|
## Code for <dt> or <dd> start tags includes "as if </dt> or |
| 7692 |
|
## </dd>" code. |
| 7693 |
|
|
| 7694 |
## has an element in scope |
## has an element in scope |
| 7695 |
my $i; |
my $i; |
| 7696 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 7717 |
dd => ($token->{tag_name} ne 'dd'), |
dd => ($token->{tag_name} ne 'dd'), |
| 7718 |
dt => ($token->{tag_name} ne 'dt'), |
dt => ($token->{tag_name} ne 'dt'), |
| 7719 |
li => ($token->{tag_name} ne 'li'), |
li => ($token->{tag_name} ne 'li'), |
| 7720 |
|
option => 1, |
| 7721 |
|
optgroup => 1, |
| 7722 |
p => 1, |
p => 1, |
| 7723 |
rt => 1, |
rt => 1, |
| 7724 |
rp => 1, |
rp => 1, |
| 7751 |
!!!next-token; |
!!!next-token; |
| 7752 |
next B; |
next B; |
| 7753 |
} elsif ($token->{tag_name} eq 'form') { |
} elsif ($token->{tag_name} eq 'form') { |
| 7754 |
|
## NOTE: As normal, but interacts with the form element pointer |
| 7755 |
|
|
| 7756 |
undef $self->{form_element}; |
undef $self->{form_element}; |
| 7757 |
|
|
| 7758 |
## has an element in scope |
## has an element in scope |
| 7759 |
my $i; |
my $i; |
| 7760 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 7761 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 7762 |
if ($node->[1] & FORM_EL) { |
if ($node->[1] == FORM_EL) { |
| 7763 |
!!!cp ('t418'); |
!!!cp ('t418'); |
| 7764 |
$i = $_; |
$i = $_; |
| 7765 |
last INSCOPE; |
last INSCOPE; |
| 7800 |
!!!next-token; |
!!!next-token; |
| 7801 |
next B; |
next B; |
| 7802 |
} elsif ({ |
} elsif ({ |
| 7803 |
|
## NOTE: As normal, except acts as a closer for any ... |
| 7804 |
h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1, |
h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1, |
| 7805 |
}->{$token->{tag_name}}) { |
}->{$token->{tag_name}}) { |
| 7806 |
## has an element in scope |
## has an element in scope |
| 7807 |
my $i; |
my $i; |
| 7808 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 7809 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 7810 |
if ($node->[1] & HEADING_EL) { |
if ($node->[1] == HEADING_EL) { |
| 7811 |
!!!cp ('t423'); |
!!!cp ('t423'); |
| 7812 |
$i = $_; |
$i = $_; |
| 7813 |
last INSCOPE; |
last INSCOPE; |
| 7846 |
!!!next-token; |
!!!next-token; |
| 7847 |
next B; |
next B; |
| 7848 |
} elsif ($token->{tag_name} eq 'p') { |
} elsif ($token->{tag_name} eq 'p') { |
| 7849 |
|
## NOTE: As normal, except </p> implies <p> and ... |
| 7850 |
|
|
| 7851 |
## has an element in scope |
## has an element in scope |
| 7852 |
|
my $non_optional; |
| 7853 |
my $i; |
my $i; |
| 7854 |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 7855 |
my $node = $self->{open_elements}->[$_]; |
my $node = $self->{open_elements}->[$_]; |
| 7856 |
if ($node->[1] & P_EL) { |
if ($node->[1] == P_EL) { |
| 7857 |
!!!cp ('t410.1'); |
!!!cp ('t410.1'); |
| 7858 |
$i = $_; |
$i = $_; |
| 7859 |
last INSCOPE; |
last INSCOPE; |
| 7860 |
} elsif ($node->[1] & SCOPING_EL) { |
} elsif ($node->[1] & SCOPING_EL) { |
| 7861 |
!!!cp ('t411.1'); |
!!!cp ('t411.1'); |
| 7862 |
last INSCOPE; |
last INSCOPE; |
| 7863 |
|
} elsif ($node->[1] & END_TAG_OPTIONAL_EL) { |
| 7864 |
|
## NOTE: |END_TAG_OPTIONAL_EL| includes "p" |
| 7865 |
|
!!!cp ('t411.2'); |
| 7866 |
|
# |
| 7867 |
|
} else { |
| 7868 |
|
!!!cp ('t411.3'); |
| 7869 |
|
$non_optional ||= $node; |
| 7870 |
|
# |
| 7871 |
} |
} |
| 7872 |
} # INSCOPE |
} # INSCOPE |
| 7873 |
|
|
| 7874 |
if (defined $i) { |
if (defined $i) { |
| 7875 |
if ($self->{open_elements}->[-1]->[0]->manakai_local_name |
## 1. Generate implied end tags |
| 7876 |
ne $token->{tag_name}) { |
# |
| 7877 |
|
|
| 7878 |
|
## 2. If current node != "p", parse error |
| 7879 |
|
if ($non_optional) { |
| 7880 |
!!!cp ('t412.1'); |
!!!cp ('t412.1'); |
| 7881 |
!!!parse-error (type => 'not closed', |
!!!parse-error (type => 'not closed', |
| 7882 |
text => $self->{open_elements}->[-1]->[0] |
text => $non_optional->[0]->manakai_local_name, |
|
->manakai_local_name, |
|
| 7883 |
token => $token); |
token => $token); |
| 7884 |
} else { |
} else { |
| 7885 |
!!!cp ('t414.1'); |
!!!cp ('t414.1'); |
| 7886 |
} |
} |
| 7887 |
|
|
| 7888 |
|
## 3. Pop |
| 7889 |
splice @{$self->{open_elements}}, $i; |
splice @{$self->{open_elements}}, $i; |
| 7890 |
} else { |
} else { |
| 7891 |
!!!cp ('t413.1'); |
!!!cp ('t413.1'); |
| 7905 |
} elsif ({ |
} elsif ({ |
| 7906 |
a => 1, |
a => 1, |
| 7907 |
b => 1, big => 1, em => 1, font => 1, i => 1, |
b => 1, big => 1, em => 1, font => 1, i => 1, |
| 7908 |
nobr => 1, s => 1, small => 1, strile => 1, |
nobr => 1, s => 1, small => 1, strike => 1, |
| 7909 |
strong => 1, tt => 1, u => 1, |
strong => 1, tt => 1, u => 1, |
| 7910 |
}->{$token->{tag_name}}) { |
}->{$token->{tag_name}}) { |
| 7911 |
!!!cp ('t427'); |
!!!cp ('t427'); |
| 7926 |
## Ignore the token. |
## Ignore the token. |
| 7927 |
!!!next-token; |
!!!next-token; |
| 7928 |
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; |
|
|
|
|
|
## ISSUE: Issue on HTML5 new elements in spec |
|
|
|
|
| 7929 |
} else { |
} else { |
| 7930 |
|
if ($token->{tag_name} eq 'sarcasm') { |
| 7931 |
|
sleep 0.001; # take a deep breath |
| 7932 |
|
} |
| 7933 |
|
|
| 7934 |
## Step 1 |
## Step 1 |
| 7935 |
my $node_i = -1; |
my $node_i = -1; |
| 7936 |
my $node = $self->{open_elements}->[$node_i]; |
my $node = $self->{open_elements}->[$node_i]; |
| 7937 |
|
|
| 7938 |
## Step 2 |
## Step 2 |
| 7939 |
S2: { |
S2: { |
| 7940 |
if ($node->[0]->manakai_local_name eq $token->{tag_name}) { |
my $node_tag_name = $node->[0]->manakai_local_name; |
| 7941 |
|
$node_tag_name =~ tr/A-Z/a-z/; # for SVG camelCase tag names |
| 7942 |
|
if ($node_tag_name eq $token->{tag_name}) { |
| 7943 |
## Step 1 |
## Step 1 |
| 7944 |
## generate implied end tags |
## generate implied end tags |
| 7945 |
while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) { |
while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) { |
| 7952 |
} |
} |
| 7953 |
|
|
| 7954 |
## Step 2 |
## Step 2 |
| 7955 |
if ($self->{open_elements}->[-1]->[0]->manakai_local_name |
my $current_tag_name |
| 7956 |
ne $token->{tag_name}) { |
= $self->{open_elements}->[-1]->[0]->manakai_local_name; |
| 7957 |
|
$current_tag_name =~ tr/A-Z/a-z/; |
| 7958 |
|
if ($current_tag_name ne $token->{tag_name}) { |
| 7959 |
!!!cp ('t431'); |
!!!cp ('t431'); |
| 7960 |
## NOTE: <x><y></x> |
## NOTE: <x><y></x> |
| 7961 |
!!!parse-error (type => 'not closed', |
!!!parse-error (type => 'not closed', |
| 7983 |
## Ignore the token |
## Ignore the token |
| 7984 |
!!!next-token; |
!!!next-token; |
| 7985 |
last S2; |
last S2; |
|
} |
|
| 7986 |
|
|
| 7987 |
|
## NOTE: |<span><dd></span>a|: In Safari 3.1.2 and Opera |
| 7988 |
|
## 9.27, "a" is a child of <dd> (conforming). In |
| 7989 |
|
## Firefox 3.0.2, "a" is a child of <body>. In WinIE 7, |
| 7990 |
|
## "a" is a child of both <body> and <dd>. |
| 7991 |
|
} |
| 7992 |
|
|
| 7993 |
!!!cp ('t434'); |
!!!cp ('t434'); |
| 7994 |
} |
} |
| 7995 |
|
|
| 8225 |
push @{$p->{open_elements}}, [$root, $el_category->{html}]; |
push @{$p->{open_elements}}, [$root, $el_category->{html}]; |
| 8226 |
|
|
| 8227 |
undef $p->{head_element}; |
undef $p->{head_element}; |
| 8228 |
|
undef $p->{head_element_inserted}; |
| 8229 |
|
|
| 8230 |
## Step 6 # MUST |
## Step 6 # MUST |
| 8231 |
$p->_reset_insertion_mode; |
$p->_reset_insertion_mode; |