Parent Directory
|
Revision Log
|
Patch
| revision 1.30 by wakaba, Sat Jun 30 13:12:32 2007 UTC | revision 1.36 by wakaba, Mon Jul 16 04:51:22 2007 UTC | |
|---|---|---|
| # | Line 7 our $VERSION=do{my @r=(q$Revision$=~/\d+ | Line 7 our $VERSION=do{my @r=(q$Revision$=~/\d+ |
| 7 | ## doc.write (''); | ## doc.write (''); |
| 8 | ## alert (doc.compatMode); | ## alert (doc.compatMode); |
| 9 | ||
| 10 | ## ISSUE: HTML5 revision 967 says that the encoding layer MUST NOT | |
| 11 | ## strip BOM and the HTML layer MUST ignore it. Whether we can do it | |
| 12 | ## is not yet clear. | |
| 13 | ## "{U+FEFF}..." in UTF-16BE/UTF-16LE is three or four characters? | |
| 14 | ## "{U+FEFF}..." in GB18030? | |
| 15 | ||
| 16 | my $permitted_slash_tag_name = { | my $permitted_slash_tag_name = { |
| 17 | base => 1, | base => 1, |
| 18 | link => 1, | link => 1, |
| # | Line 699 sub _get_next_token ($) { | Line 705 sub _get_next_token ($) { |
| 705 | # | # |
| 706 | } else { | } else { |
| 707 | !!!parse-error (type => 'nestc'); | !!!parse-error (type => 'nestc'); |
| 708 | ## TODO: Different error type for <aa / bb> than <aa/> | |
| 709 | } | } |
| 710 | $self->{state} = 'before attribute name'; | $self->{state} = 'before attribute name'; |
| 711 | # next-input-character is already done | # next-input-character is already done |
| # | Line 1078 sub _get_next_token ($) { | Line 1085 sub _get_next_token ($) { |
| 1085 | redo A; | redo A; |
| 1086 | } else { | } else { |
| 1087 | $self->{current_token}->{data} # comment | $self->{current_token}->{data} # comment |
| 1088 | .= chr ($self->{next_input_character}); | .= '-' . chr ($self->{next_input_character}); |
| 1089 | $self->{state} = 'comment'; | $self->{state} = 'comment'; |
| 1090 | !!!next-input-character; | !!!next-input-character; |
| 1091 | redo A; | redo A; |
| # | Line 2011 sub _tree_construction_root_element ($) | Line 2018 sub _tree_construction_root_element ($) |
| 2018 | my $root_element; !!!create-element ($root_element, 'html'); | my $root_element; !!!create-element ($root_element, 'html'); |
| 2019 | $self->{document}->append_child ($root_element); | $self->{document}->append_child ($root_element); |
| 2020 | push @{$self->{open_elements}}, [$root_element, 'html']; | push @{$self->{open_elements}}, [$root_element, 'html']; |
| #$phase = 'main'; | ||
| 2021 | ## reprocess | ## reprocess |
| 2022 | #redo B; | #redo B; |
| 2023 | return; | return; ## Go to the main phase. |
| 2024 | } # B | } # B |
| 2025 | } # _tree_construction_root_element | } # _tree_construction_root_element |
| 2026 | ||
| # | Line 2090 sub _reset_insertion_mode ($) { | Line 2096 sub _reset_insertion_mode ($) { |
| 2096 | sub _tree_construction_main ($) { | sub _tree_construction_main ($) { |
| 2097 | my $self = shift; | my $self = shift; |
| 2098 | ||
| 2099 | my $phase = 'main'; | my $previous_insertion_mode; |
| 2100 | ||
| 2101 | my $active_formatting_elements = []; | my $active_formatting_elements = []; |
| 2102 | ||
| # | Line 2491 sub _tree_construction_main ($) { | Line 2497 sub _tree_construction_main ($) { |
| 2497 | $parse_rcdata->('CDATA', $insert); | $parse_rcdata->('CDATA', $insert); |
| 2498 | return; | return; |
| 2499 | } elsif ({ | } elsif ({ |
| 2500 | base => 1, link => 1, meta => 1, | base => 1, link => 1, |
| 2501 | }->{$token->{tag_name}}) { | }->{$token->{tag_name}}) { |
| 2502 | ## 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 |
| 2503 | !!!insert-element-t ($token->{tag_name}, $token->{attributes}); | !!!insert-element-t ($token->{tag_name}, $token->{attributes}); |
| 2504 | pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec. | pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec. |
| 2505 | !!!next-token; | !!!next-token; |
| 2506 | ## TODO: Extracting |charset| from |meta|. | return; |
| 2507 | } elsif ($token->{tag_name} eq 'meta') { | |
| 2508 | ## NOTE: This is an "as if in head" code clone, only "-t" differs | |
| 2509 | !!!insert-element-t ($token->{tag_name}, $token->{attributes}); | |
| 2510 | pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec. | |
| 2511 | ||
| 2512 | unless ($self->{confident}) { | |
| 2513 | my $charset; | |
| 2514 | if ($token->{attributes}->{charset}) { ## TODO: And if supported | |
| 2515 | $charset = $token->{attributes}->{charset}->{value}; | |
| 2516 | } | |
| 2517 | if ($token->{attributes}->{'http-equiv'}) { | |
| 2518 | ## ISSUE: Algorithm name in the spec was incorrect so that not linked to the definition. | |
| 2519 | if ($token->{attributes}->{'http-equiv'}->{value} | |
| 2520 | =~ /\A[^;]*;[\x09-\x0D\x20]*charset[\x09-\x0D\x20]*= | |
| 2521 | [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'| | |
| 2522 | ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) { | |
| 2523 | $charset = defined $1 ? $1 : defined $2 ? $2 : $3; | |
| 2524 | } ## TODO: And if supported | |
| 2525 | } | |
| 2526 | ## TODO: Change the encoding | |
| 2527 | } | |
| 2528 | ||
| 2529 | !!!next-token; | |
| 2530 | return; | return; |
| 2531 | } elsif ($token->{tag_name} eq 'title') { | } elsif ($token->{tag_name} eq 'title') { |
| 2532 | !!!parse-error (type => 'in body:title'); | !!!parse-error (type => 'in body:title'); |
| 2533 | ## NOTE: This is an "as if in head" code clone | ## NOTE: This is an "as if in head" code clone |
| 2534 | $parse_rcdata->('RCDATA', $insert); | $parse_rcdata->('RCDATA', sub { |
| 2535 | if (defined $self->{head_element}) { | |
| 2536 | $self->{head_element}->append_child ($_[0]); | |
| 2537 | } else { | |
| 2538 | $insert->($_[0]); | |
| 2539 | } | |
| 2540 | }); | |
| 2541 | return; | return; |
| 2542 | } elsif ($token->{tag_name} eq 'body') { | } elsif ($token->{tag_name} eq 'body') { |
| 2543 | !!!parse-error (type => 'in body:body'); | !!!parse-error (type => 'in body:body'); |
| # | Line 2795 sub _tree_construction_main ($) { | Line 2830 sub _tree_construction_main ($) { |
| 2830 | INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { | INSCOPE: for (reverse 0..$#{$self->{open_elements}}) { |
| 2831 | my $node = $self->{open_elements}->[$_]; | my $node = $self->{open_elements}->[$_]; |
| 2832 | if ($node->[1] eq 'nobr') { | if ($node->[1] eq 'nobr') { |
| 2833 | !!!parse-error (type => 'not closed:nobr'); | |
| 2834 | !!!back-token; | !!!back-token; |
| 2835 | $token = {type => 'end tag', tag_name => 'nobr'}; | $token = {type => 'end tag', tag_name => 'nobr'}; |
| 2836 | return; | return; |
| # | Line 2878 sub _tree_construction_main ($) { | Line 2914 sub _tree_construction_main ($) { |
| 2914 | !!!parse-error (type => 'image'); | !!!parse-error (type => 'image'); |
| 2915 | $token->{tag_name} = 'img'; | $token->{tag_name} = 'img'; |
| 2916 | } | } |
| 2917 | ||
| 2918 | ## NOTE: There is an "as if <br>" code clone. | |
| 2919 | $reconstruct_active_formatting_elements->($insert_to_current); | $reconstruct_active_formatting_elements->($insert_to_current); |
| 2920 | ||
| 2921 | !!!insert-element-t ($token->{tag_name}, $token->{attributes}); | !!!insert-element-t ($token->{tag_name}, $token->{attributes}); |
| # | Line 3036 sub _tree_construction_main ($) { | Line 3073 sub _tree_construction_main ($) { |
| 3073 | unless ({ | unless ({ |
| 3074 | dd => 1, dt => 1, li => 1, p => 1, td => 1, | dd => 1, dt => 1, li => 1, p => 1, td => 1, |
| 3075 | th => 1, tr => 1, body => 1, html => 1, | th => 1, tr => 1, body => 1, html => 1, |
| 3076 | tbody => 1, tfoot => 1, thead => 1, | |
| 3077 | }->{$_->[1]}) { | }->{$_->[1]}) { |
| 3078 | !!!parse-error (type => 'not closed:'.$_->[1]); | !!!parse-error (type => 'not closed:'.$_->[1]); |
| 3079 | } | } |
| # | Line 3085 sub _tree_construction_main ($) { | Line 3123 sub _tree_construction_main ($) { |
| 3123 | li => ($token->{tag_name} ne 'li'), | li => ($token->{tag_name} ne 'li'), |
| 3124 | p => ($token->{tag_name} ne 'p'), | p => ($token->{tag_name} ne 'p'), |
| 3125 | td => 1, th => 1, tr => 1, | td => 1, th => 1, tr => 1, |
| 3126 | tbody => 1, tfoot=> 1, thead => 1, | |
| 3127 | }->{$self->{open_elements}->[-1]->[1]}) { | }->{$self->{open_elements}->[-1]->[1]}) { |
| 3128 | !!!back-token; | !!!back-token; |
| 3129 | $token = {type => 'end tag', | $token = {type => 'end tag', |
| # | Line 3102 sub _tree_construction_main ($) { | Line 3141 sub _tree_construction_main ($) { |
| 3141 | } # INSCOPE | } # INSCOPE |
| 3142 | ||
| 3143 | if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) { | if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) { |
| 3144 | !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]); | if (defined $i) { |
| 3145 | !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]); | |
| 3146 | } else { | |
| 3147 | !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}); | |
| 3148 | } | |
| 3149 | } | } |
| 3150 | ||
| 3151 | splice @{$self->{open_elements}}, $i if defined $i; | if (defined $i) { |
| 3152 | splice @{$self->{open_elements}}, $i; | |
| 3153 | } elsif ($token->{tag_name} eq 'p') { | |
| 3154 | ## As if <p>, then reprocess the current token | |
| 3155 | my $el; | |
| 3156 | !!!create-element ($el, 'p'); | |
| 3157 | $insert->($el); | |
| 3158 | } | |
| 3159 | $clear_up_to_marker->() | $clear_up_to_marker->() |
| 3160 | if { | if { |
| 3161 | button => 1, marquee => 1, object => 1, | button => 1, marquee => 1, object => 1, |
| # | Line 3121 sub _tree_construction_main ($) { | Line 3171 sub _tree_construction_main ($) { |
| 3171 | if ({ | if ({ |
| 3172 | dd => 1, dt => 1, li => 1, p => 1, | dd => 1, dt => 1, li => 1, p => 1, |
| 3173 | td => 1, th => 1, tr => 1, | td => 1, th => 1, tr => 1, |
| 3174 | tbody => 1, tfoot=> 1, thead => 1, | |
| 3175 | }->{$self->{open_elements}->[-1]->[1]}) { | }->{$self->{open_elements}->[-1]->[1]}) { |
| 3176 | !!!back-token; | !!!back-token; |
| 3177 | $token = {type => 'end tag', | $token = {type => 'end tag', |
| # | Line 3159 sub _tree_construction_main ($) { | Line 3210 sub _tree_construction_main ($) { |
| 3210 | if ({ | if ({ |
| 3211 | dd => 1, dt => 1, li => 1, p => 1, | dd => 1, dt => 1, li => 1, p => 1, |
| 3212 | td => 1, th => 1, tr => 1, | td => 1, th => 1, tr => 1, |
| 3213 | tbody => 1, tfoot=> 1, thead => 1, | |
| 3214 | }->{$self->{open_elements}->[-1]->[1]}) { | }->{$self->{open_elements}->[-1]->[1]}) { |
| 3215 | !!!back-token; | !!!back-token; |
| 3216 | $token = {type => 'end tag', | $token = {type => 'end tag', |
| # | Line 3189 sub _tree_construction_main ($) { | Line 3241 sub _tree_construction_main ($) { |
| 3241 | strong => 1, tt => 1, u => 1, | strong => 1, tt => 1, u => 1, |
| 3242 | }->{$token->{tag_name}}) { | }->{$token->{tag_name}}) { |
| 3243 | $formatting_end_tag->($token->{tag_name}); | $formatting_end_tag->($token->{tag_name}); |
| 3244 | ## TODO: <http://html5.org/tools/web-apps-tracker?from=883&to=884> | return; |
| 3245 | } elsif ($token->{tag_name} eq 'br') { | |
| 3246 | !!!parse-error (type => 'unmatched end tag:br'); | |
| 3247 | ||
| 3248 | ## As if <br> | |
| 3249 | $reconstruct_active_formatting_elements->($insert_to_current); | |
| 3250 | ||
| 3251 | my $el; | |
| 3252 | !!!create-element ($el, 'br'); | |
| 3253 | $insert->($el); | |
| 3254 | ||
| 3255 | ## Ignore the token. | |
| 3256 | !!!next-token; | |
| 3257 | return; | return; |
| 3258 | } elsif ({ | } elsif ({ |
| 3259 | caption => 1, col => 1, colgroup => 1, frame => 1, | caption => 1, col => 1, colgroup => 1, frame => 1, |
| 3260 | frameset => 1, head => 1, option => 1, optgroup => 1, | frameset => 1, head => 1, option => 1, optgroup => 1, |
| 3261 | tbody => 1, td => 1, tfoot => 1, th => 1, | tbody => 1, td => 1, tfoot => 1, th => 1, |
| 3262 | thead => 1, tr => 1, | thead => 1, tr => 1, |
| 3263 | area => 1, basefont => 1, bgsound => 1, br => 1, | area => 1, basefont => 1, bgsound => 1, |
| 3264 | embed => 1, hr => 1, iframe => 1, image => 1, | embed => 1, hr => 1, iframe => 1, image => 1, |
| 3265 | img => 1, input => 1, isindex => 1, noembed => 1, | img => 1, input => 1, isindex => 1, noembed => 1, |
| 3266 | noframes => 1, param => 1, select => 1, spacer => 1, | noframes => 1, param => 1, select => 1, spacer => 1, |
| # | Line 3223 sub _tree_construction_main ($) { | Line 3287 sub _tree_construction_main ($) { |
| 3287 | if ({ | if ({ |
| 3288 | dd => 1, dt => 1, li => 1, p => 1, | dd => 1, dt => 1, li => 1, p => 1, |
| 3289 | td => 1, th => 1, tr => 1, | td => 1, th => 1, tr => 1, |
| 3290 | tbody => 1, tfoot=> 1, thead => 1, | |
| 3291 | }->{$self->{open_elements}->[-1]->[1]}) { | }->{$self->{open_elements}->[-1]->[1]}) { |
| 3292 | !!!back-token; | !!!back-token; |
| 3293 | $token = {type => 'end tag', | $token = {type => 'end tag', |
| # | Line 3266 sub _tree_construction_main ($) { | Line 3331 sub _tree_construction_main ($) { |
| 3331 | }; # $in_body | }; # $in_body |
| 3332 | ||
| 3333 | B: { | B: { |
| 3334 | if ($phase eq 'main') { | if ($token->{type} eq 'DOCTYPE') { |
| 3335 | if ($token->{type} eq 'DOCTYPE') { | !!!parse-error (type => 'DOCTYPE in the middle'); |
| 3336 | !!!parse-error (type => 'in html:#DOCTYPE'); | ## Ignore the token |
| 3337 | ## Ignore the token | ## Stay in the phase |
| 3338 | ## Stay in the phase | !!!next-token; |
| 3339 | !!!next-token; | redo B; |
| 3340 | redo B; | } elsif ($token->{type} eq 'end-of-file') { |
| 3341 | } elsif ($token->{type} eq 'start tag' and | if ($token->{insertion_mode} ne 'trailing end') { |
| $token->{tag_name} eq 'html') { | ||
| ## ISSUE: "aa<html>" is not a parse error. | ||
| ## ISSUE: "<html>" in fragment is not a parse error. | ||
| unless ($token->{first_start_tag}) { | ||
| !!!parse-error (type => 'not first start tag'); | ||
| } | ||
| my $top_el = $self->{open_elements}->[0]->[0]; | ||
| for my $attr_name (keys %{$token->{attributes}}) { | ||
| unless ($top_el->has_attribute_ns (undef, $attr_name)) { | ||
| $top_el->set_attribute_ns | ||
| (undef, [undef, $attr_name], | ||
| $token->{attributes}->{$attr_name}->{value}); | ||
| } | ||
| } | ||
| !!!next-token; | ||
| redo B; | ||
| } elsif ($token->{type} eq 'end-of-file') { | ||
| 3342 | ## Generate implied end tags | ## Generate implied end tags |
| 3343 | if ({ | if ({ |
| 3344 | dd => 1, dt => 1, li => 1, p => 1, td => 1, th => 1, tr => 1, | dd => 1, dt => 1, li => 1, p => 1, td => 1, th => 1, tr => 1, |
| 3345 | tbody => 1, tfoot=> 1, thead => 1, | |
| 3346 | }->{$self->{open_elements}->[-1]->[1]}) { | }->{$self->{open_elements}->[-1]->[1]}) { |
| 3347 | !!!back-token; | !!!back-token; |
| 3348 | $token = {type => 'end tag', tag_name => $self->{open_elements}->[-1]->[1]}; | $token = {type => 'end tag', tag_name => $self->{open_elements}->[-1]->[1]}; |
| # | Line 3309 sub _tree_construction_main ($) { | Line 3358 sub _tree_construction_main ($) { |
| 3358 | !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]); | !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]); |
| 3359 | } | } |
| 3360 | ||
| ## Stop parsing | ||
| last B; | ||
| 3361 | ## ISSUE: There is an issue in the spec. | ## ISSUE: There is an issue in the spec. |
| 3362 | } | |
| 3363 | ||
| 3364 | ## Stop parsing | |
| 3365 | last B; | |
| 3366 | } elsif ($token->{type} eq 'start tag' and | |
| 3367 | $token->{tag_name} eq 'html') { | |
| 3368 | if ($self->{insertion_mode} eq 'trailing end') { | |
| 3369 | ## Turn into the main phase | |
| 3370 | !!!parse-error (type => 'after html:html'); | |
| 3371 | $self->{insertion_mode} = $previous_insertion_mode; | |
| 3372 | } | |
| 3373 | ||
| 3374 | ## ISSUE: "aa<html>" is not a parse error. | |
| 3375 | ## ISSUE: "<html>" in fragment is not a parse error. | |
| 3376 | unless ($token->{first_start_tag}) { | |
| 3377 | !!!parse-error (type => 'not first start tag'); | |
| 3378 | } | |
| 3379 | my $top_el = $self->{open_elements}->[0]->[0]; | |
| 3380 | for my $attr_name (keys %{$token->{attributes}}) { | |
| 3381 | unless ($top_el->has_attribute_ns (undef, $attr_name)) { | |
| 3382 | $top_el->set_attribute_ns | |
| 3383 | (undef, [undef, $attr_name], | |
| 3384 | $token->{attributes}->{$attr_name}->{value}); | |
| 3385 | } | |
| 3386 | } | |
| 3387 | !!!next-token; | |
| 3388 | redo B; | |
| 3389 | } elsif ($token->{type} eq 'comment') { | |
| 3390 | my $comment = $self->{document}->create_comment ($token->{data}); | |
| 3391 | if ($self->{insertion_mode} eq 'trailing end') { | |
| 3392 | $self->{document}->append_child ($comment); | |
| 3393 | } elsif ($self->{insertion_mode} eq 'after body') { | |
| 3394 | $self->{open_elements}->[0]->[0]->append_child ($comment); | |
| 3395 | } else { | } else { |
| 3396 | if ($self->{insertion_mode} eq 'before head') { | $self->{open_elements}->[-1]->[0]->append_child ($comment); |
| 3397 | } | |
| 3398 | !!!next-token; | |
| 3399 | redo B; | |
| 3400 | } elsif ($self->{insertion_mode} eq 'before head') { | |
| 3401 | if ($token->{type} eq 'character') { | if ($token->{type} eq 'character') { |
| 3402 | if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { | if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { |
| 3403 | $self->{open_elements}->[-1]->[0]->manakai_append_text ($1); | $self->{open_elements}->[-1]->[0]->manakai_append_text ($1); |
| # | Line 3330 sub _tree_construction_main ($) { | Line 3413 sub _tree_construction_main ($) { |
| 3413 | $self->{insertion_mode} = 'in head'; | $self->{insertion_mode} = 'in head'; |
| 3414 | ## reprocess | ## reprocess |
| 3415 | redo B; | redo B; |
| } elsif ($token->{type} eq 'comment') { | ||
| my $comment = $self->{document}->create_comment ($token->{data}); | ||
| $self->{open_elements}->[-1]->[0]->append_child ($comment); | ||
| !!!next-token; | ||
| redo B; | ||
| 3416 | } elsif ($token->{type} eq 'start tag') { | } elsif ($token->{type} eq 'start tag') { |
| 3417 | my $attr = $token->{tag_name} eq 'head' ? $token->{attributes} : {}; | my $attr = $token->{tag_name} eq 'head' ? $token->{attributes} : {}; |
| 3418 | !!!create-element ($self->{head_element}, 'head', $attr); | !!!create-element ($self->{head_element}, 'head', $attr); |
| # | Line 3353 sub _tree_construction_main ($) { | Line 3431 sub _tree_construction_main ($) { |
| 3431 | } | } |
| 3432 | redo B; | redo B; |
| 3433 | } elsif ($token->{type} eq 'end tag') { | } elsif ($token->{type} eq 'end tag') { |
| 3434 | if ({head => 1, body => 1, html => 1}->{$token->{tag_name}}) { | if ({ |
| 3435 | head => 1, body => 1, html => 1, | |
| 3436 | p => 1, br => 1, | |
| 3437 | }->{$token->{tag_name}}) { | |
| 3438 | ## As if <head> | ## As if <head> |
| 3439 | !!!create-element ($self->{head_element}, 'head'); | !!!create-element ($self->{head_element}, 'head'); |
| 3440 | $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element}); | $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element}); |
| # | Line 3383 sub _tree_construction_main ($) { | Line 3464 sub _tree_construction_main ($) { |
| 3464 | } | } |
| 3465 | ||
| 3466 | # | # |
| } elsif ($token->{type} eq 'comment') { | ||
| my $comment = $self->{document}->create_comment ($token->{data}); | ||
| $self->{open_elements}->[-1]->[0]->append_child ($comment); | ||
| !!!next-token; | ||
| redo B; | ||
| 3467 | } elsif ($token->{type} eq 'start tag') { | } elsif ($token->{type} eq 'start tag') { |
| 3468 | if ({base => ($self->{insertion_mode} eq 'in head' or | if ({base => ($self->{insertion_mode} eq 'in head' or |
| 3469 | $self->{insertion_mode} eq 'after head'), | $self->{insertion_mode} eq 'after head'), |
| 3470 | link => 1, meta => 1}->{$token->{tag_name}}) { | link => 1}->{$token->{tag_name}}) { |
| 3471 | ## NOTE: There is a "as if in head" code clone. | ## NOTE: There is a "as if in head" code clone. |
| 3472 | if ($self->{insertion_mode} eq 'after head') { | if ($self->{insertion_mode} eq 'after head') { |
| 3473 | !!!parse-error (type => 'after head:'.$token->{tag_name}); | !!!parse-error (type => 'after head:'.$token->{tag_name}); |
| # | Line 3399 sub _tree_construction_main ($) { | Line 3475 sub _tree_construction_main ($) { |
| 3475 | } | } |
| 3476 | !!!insert-element ($token->{tag_name}, $token->{attributes}); | !!!insert-element ($token->{tag_name}, $token->{attributes}); |
| 3477 | pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec. | pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec. |
| 3478 | pop @{$self->{open_elements}} | |
| 3479 | if $self->{insertion_mode} eq 'after head'; | |
| 3480 | !!!next-token; | |
| 3481 | redo B; | |
| 3482 | } elsif ($token->{tag_name} eq 'meta') { | |
| 3483 | ## NOTE: There is a "as if in head" code clone. | |
| 3484 | if ($self->{insertion_mode} eq 'after head') { | |
| 3485 | !!!parse-error (type => 'after head:'.$token->{tag_name}); | |
| 3486 | push @{$self->{open_elements}}, [$self->{head_element}, 'head']; | |
| 3487 | } | |
| 3488 | !!!insert-element ($token->{tag_name}, $token->{attributes}); | |
| 3489 | pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec. | |
| 3490 | ||
| 3491 | unless ($self->{confident}) { | |
| 3492 | my $charset; | |
| 3493 | if ($token->{attributes}->{charset}) { ## TODO: And if supported | |
| 3494 | $charset = $token->{attributes}->{charset}->{value}; | |
| 3495 | } | |
| 3496 | if ($token->{attributes}->{'http-equiv'}) { | |
| 3497 | ## ISSUE: Algorithm name in the spec was incorrect so that not linked to the definition. | |
| 3498 | if ($token->{attributes}->{'http-equiv'}->{value} | |
| 3499 | =~ /\A[^;]*;[\x09-\x0D\x20]*charset[\x09-\x0D\x20]*= | |
| 3500 | [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'| | |
| 3501 | ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) { | |
| 3502 | $charset = defined $1 ? $1 : defined $2 ? $2 : $3; | |
| 3503 | } ## TODO: And if supported | |
| 3504 | } | |
| 3505 | ## TODO: Change the encoding | |
| 3506 | } | |
| 3507 | ||
| 3508 | ## TODO: Extracting |charset| from |meta|. | ## TODO: Extracting |charset| from |meta|. |
| 3509 | pop @{$self->{open_elements}} | pop @{$self->{open_elements}} |
| 3510 | if $self->{insertion_mode} eq 'after head'; | if $self->{insertion_mode} eq 'after head'; |
| # | Line 3411 sub _tree_construction_main ($) { | Line 3517 sub _tree_construction_main ($) { |
| 3517 | !!!parse-error (type => 'after head:'.$token->{tag_name}); | !!!parse-error (type => 'after head:'.$token->{tag_name}); |
| 3518 | push @{$self->{open_elements}}, [$self->{head_element}, 'head']; | push @{$self->{open_elements}}, [$self->{head_element}, 'head']; |
| 3519 | } | } |
| 3520 | $parse_rcdata->('RCDATA', $insert_to_current); | my $parent = defined $self->{head_element} ? $self->{head_element} |
| 3521 | : $self->{open_elements}->[-1]->[0]; | |
| 3522 |