/[suikacvs]/markup/html/whatpm/Whatpm/HTML.pm.src
Suika

Diff of /markup/html/whatpm/Whatpm/HTML.pm.src

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.189 by wakaba, Sat Sep 20 11:25:56 2008 UTC revision 1.202 by wakaba, Sat Oct 4 14:31:28 2008 UTC
# Line 66  sub TABLE_ROWS_EL () { Line 66  sub TABLE_ROWS_EL () {
66  }  }
67    
68  ## NOTE: Used in "generate implied end tags" algorithm.  ## NOTE: Used in "generate implied end tags" algorithm.
69  ## NOTE: There is a code where a modified version of END_TAG_OPTIONAL_EL  ## NOTE: There is a code where a modified version of
70  ## is used in "generate implied end tags" implementation (search for the  ## END_TAG_OPTIONAL_EL is used in "generate implied end tags"
71  ## function mae).  ## implementation (search for the algorithm name).
72  sub END_TAG_OPTIONAL_EL () {  sub END_TAG_OPTIONAL_EL () {
73    DD_EL |    DD_EL |
74    DT_EL |    DT_EL |
75    LI_EL |    LI_EL |
76      OPTION_EL |
77      OPTGROUP_EL |
78    P_EL |    P_EL |
79    RUBY_COMPONENT_EL    RUBY_COMPONENT_EL
80  }  }
# Line 84  sub ALL_END_TAG_OPTIONAL_EL () { Line 86  sub ALL_END_TAG_OPTIONAL_EL () {
86    LI_EL |    LI_EL |
87    P_EL |    P_EL |
88    
89      ## ISSUE: option, optgroup, rt, rp?
90    
91    BODY_EL |    BODY_EL |
92    HTML_EL |    HTML_EL |
93    TABLE_CELL_EL |    TABLE_CELL_EL |
# Line 128  sub SPECIAL_EL () { Line 132  sub SPECIAL_EL () {
132    FORM_EL |    FORM_EL |
133    FRAMESET_EL |    FRAMESET_EL |
134    HEADING_EL |    HEADING_EL |
   OPTION_EL |  
   OPTGROUP_EL |  
135    SELECT_EL |    SELECT_EL |
136    TABLE_ROW_EL |    TABLE_ROW_EL |
137    TABLE_ROW_GROUP_EL |    TABLE_ROW_GROUP_EL |
# Line 141  my $el_category = { Line 143  my $el_category = {
143    address => ADDRESS_EL,    address => ADDRESS_EL,
144    applet => MISC_SCOPING_EL,    applet => MISC_SCOPING_EL,
145    area => MISC_SPECIAL_EL,    area => MISC_SPECIAL_EL,
146      article => MISC_SPECIAL_EL,
147      aside => MISC_SPECIAL_EL,
148    b => FORMATTING_EL,    b => FORMATTING_EL,
149    base => MISC_SPECIAL_EL,    base => MISC_SPECIAL_EL,
150    basefont => MISC_SPECIAL_EL,    basefont => MISC_SPECIAL_EL,
# Line 154  my $el_category = { Line 158  my $el_category = {
158    center => MISC_SPECIAL_EL,    center => MISC_SPECIAL_EL,
159    col => MISC_SPECIAL_EL,    col => MISC_SPECIAL_EL,
160    colgroup => MISC_SPECIAL_EL,    colgroup => MISC_SPECIAL_EL,
161      command => MISC_SPECIAL_EL,
162      datagrid => MISC_SPECIAL_EL,
163    dd => DD_EL,    dd => DD_EL,
164      details => MISC_SPECIAL_EL,
165      dialog => MISC_SPECIAL_EL,
166    dir => MISC_SPECIAL_EL,    dir => MISC_SPECIAL_EL,
167    div => DIV_EL,    div => DIV_EL,
168    dl => MISC_SPECIAL_EL,    dl => MISC_SPECIAL_EL,
169    dt => DT_EL,    dt => DT_EL,
170    em => FORMATTING_EL,    em => FORMATTING_EL,
171    embed => MISC_SPECIAL_EL,    embed => MISC_SPECIAL_EL,
172      eventsource => MISC_SPECIAL_EL,
173    fieldset => MISC_SPECIAL_EL,    fieldset => MISC_SPECIAL_EL,
174      figure => MISC_SPECIAL_EL,
175    font => FORMATTING_EL,    font => FORMATTING_EL,
176      footer => MISC_SPECIAL_EL,
177    form => FORM_EL,    form => FORM_EL,
178    frame => MISC_SPECIAL_EL,    frame => MISC_SPECIAL_EL,
179    frameset => FRAMESET_EL,    frameset => FRAMESET_EL,
# Line 173  my $el_category = { Line 184  my $el_category = {
184    h5 => HEADING_EL,    h5 => HEADING_EL,
185    h6 => HEADING_EL,    h6 => HEADING_EL,
186    head => MISC_SPECIAL_EL,    head => MISC_SPECIAL_EL,
187      header => MISC_SPECIAL_EL,
188    hr => MISC_SPECIAL_EL,    hr => MISC_SPECIAL_EL,
189    html => HTML_EL,    html => HTML_EL,
190    i => FORMATTING_EL,    i => FORMATTING_EL,
191    iframe => MISC_SPECIAL_EL,    iframe => MISC_SPECIAL_EL,
192    img => MISC_SPECIAL_EL,    img => MISC_SPECIAL_EL,
193      #image => MISC_SPECIAL_EL, ## NOTE: Commented out in the spec.
194    input => MISC_SPECIAL_EL,    input => MISC_SPECIAL_EL,
195    isindex => MISC_SPECIAL_EL,    isindex => MISC_SPECIAL_EL,
196    li => LI_EL,    li => LI_EL,
# Line 186  my $el_category = { Line 199  my $el_category = {
199    marquee => MISC_SCOPING_EL,    marquee => MISC_SCOPING_EL,
200    menu => MISC_SPECIAL_EL,    menu => MISC_SPECIAL_EL,
201    meta => MISC_SPECIAL_EL,    meta => MISC_SPECIAL_EL,
202      nav => MISC_SPECIAL_EL,
203    nobr => NOBR_EL | FORMATTING_EL,    nobr => NOBR_EL | FORMATTING_EL,
204    noembed => MISC_SPECIAL_EL,    noembed => MISC_SPECIAL_EL,
205    noframes => MISC_SPECIAL_EL,    noframes => MISC_SPECIAL_EL,
# Line 204  my $el_category = { Line 218  my $el_category = {
218    s => FORMATTING_EL,    s => FORMATTING_EL,
219    script => MISC_SPECIAL_EL,    script => MISC_SPECIAL_EL,
220    select => SELECT_EL,    select => SELECT_EL,
221      section => MISC_SPECIAL_EL,
222    small => FORMATTING_EL,    small => FORMATTING_EL,
223    spacer => MISC_SPECIAL_EL,    spacer => MISC_SPECIAL_EL,
224    strike => FORMATTING_EL,    strike => FORMATTING_EL,
# Line 234  my $el_category_f = { Line 249  my $el_category_f = {
249      mtext => FOREIGN_FLOW_CONTENT_EL,      mtext => FOREIGN_FLOW_CONTENT_EL,
250    },    },
251    $SVG_NS => {    $SVG_NS => {
252      foreignObject => FOREIGN_FLOW_CONTENT_EL,      foreignObject => FOREIGN_FLOW_CONTENT_EL | MISC_SCOPING_EL,
253      desc => FOREIGN_FLOW_CONTENT_EL,      desc => FOREIGN_FLOW_CONTENT_EL,
254      title => FOREIGN_FLOW_CONTENT_EL,      title => FOREIGN_FLOW_CONTENT_EL,
255    },    },
# Line 323  my $foreign_attr_xname = { Line 338  my $foreign_attr_xname = {
338    
339  ## ISSUE: xmlns:xlink="non-xlink-ns" is not an error.  ## ISSUE: xmlns:xlink="non-xlink-ns" is not an error.
340    
341  my $c1_entity_char = {  my $charref_map = {
342      0x0D => 0x000A,
343    0x80 => 0x20AC,    0x80 => 0x20AC,
344    0x81 => 0xFFFD,    0x81 => 0xFFFD,
345    0x82 => 0x201A,    0x82 => 0x201A,
# Line 356  my $c1_entity_char = { Line 372  my $c1_entity_char = {
372    0x9D => 0xFFFD,    0x9D => 0xFFFD,
373    0x9E => 0x017E,    0x9E => 0x017E,
374    0x9F => 0x0178,    0x9F => 0x0178,
375  }; # $c1_entity_char  }; # $charref_map
376    $charref_map->{$_} = 0xFFFD
377        for 0x0000..0x0008, 0x000B, 0x000E..0x001F, 0x007F,
378            0xD800..0xDFFF, 0xFDD0..0xFDDF, ## ISSUE: 0xFDEF
379            0xFFFE, 0xFFFF, 0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF,
380            0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE,
381            0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF,
382            0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, 0xDFFFF, 0xEFFFE,
383            0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, 0x10FFFF;
384    
385    ## TODO: Invoke the reset algorithm when a resettable element is
386    ## created (cf. HTML5 revision 2259).
387    
388  sub parse_byte_string ($$$$;$) {  sub parse_byte_string ($$$$;$) {
389    my $self = shift;    my $self = shift;
# Line 401  sub parse_byte_stream ($$$$;$$) { Line 428  sub parse_byte_stream ($$$$;$$) {
428            ## TODO: Is this ok?  Transfer protocol's parameter should be            ## TODO: Is this ok?  Transfer protocol's parameter should be
429            ## interpreted in its semantics?            ## interpreted in its semantics?
430    
       ## ISSUE: Unsupported encoding is not ignored according to the spec.  
431        ($char_stream, $e_status) = $charset->get_decode_handle        ($char_stream, $e_status) = $charset->get_decode_handle
432            ($byte_stream, allow_error_reporting => 1,            ($byte_stream, allow_error_reporting => 1,
433             allow_fallback => 1);             allow_fallback => 1);
# Line 409  sub parse_byte_stream ($$$$;$$) { Line 435  sub parse_byte_stream ($$$$;$$) {
435          $self->{confident} = 1;          $self->{confident} = 1;
436          last SNIFFING;          last SNIFFING;
437        } else {        } else {
438          ## TODO: unsupported error          !!!parse-error (type => 'charset:not supported',
439                            layer => 'encode',
440                            line => 1, column => 1,
441                            value => $charset_name,
442                            level => $self->{level}->{uncertain});
443        }        }
444      }      }
445    
# Line 458  sub parse_byte_stream ($$$$;$$) { Line 488  sub parse_byte_stream ($$$$;$$) {
488      if (defined $charset_name) {      if (defined $charset_name) {
489        $charset = Message::Charset::Info->get_by_html_name ($charset_name);        $charset = Message::Charset::Info->get_by_html_name ($charset_name);
490    
       ## ISSUE: Unsupported encoding is not ignored according to the spec.  
491        require Whatpm::Charset::DecodeHandle;        require Whatpm::Charset::DecodeHandle;
492        $buffer = Whatpm::Charset::DecodeHandle::ByteBuffer->new        $buffer = Whatpm::Charset::DecodeHandle::ByteBuffer->new
493            ($byte_stream);            ($byte_stream);
# Line 2455  sub _get_next_token ($) { Line 2484  sub _get_next_token ($) {
2484          !!!cp (160);          !!!cp (160);
2485          $self->{ct}->{name} = chr $self->{nc};          $self->{ct}->{name} = chr $self->{nc};
2486          delete $self->{ct}->{quirks};          delete $self->{ct}->{quirks};
 ## ISSUE: "Set the token's name name to the" in the spec  
2487          $self->{state} = DOCTYPE_NAME_STATE;          $self->{state} = DOCTYPE_NAME_STATE;
2488          !!!next-input-character;          !!!next-input-character;
2489          redo A;          redo A;
# Line 3171  sub _get_next_token ($) { Line 3199  sub _get_next_token ($) {
3199        my $code = $self->{s_kwd};        my $code = $self->{s_kwd};
3200        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3201        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3202        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {        if ($charref_map->{$code}) {
3203          !!!cp (1015);          !!!cp (1015);
3204          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3205                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
3206                          line => $l, column => $c);                          line => $l, column => $c);
3207          $code = 0xFFFD;          $code = $charref_map->{$code};
3208        } elsif ($code > 0x10FFFF) {        } elsif ($code > 0x10FFFF) {
3209          !!!cp (1016);          !!!cp (1016);
3210          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3211                          text => (sprintf 'U-%08X', $code),                          text => (sprintf 'U-%08X', $code),
3212                          line => $l, column => $c);                          line => $l, column => $c);
3213          $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};  
3214        }        }
3215    
3216        if ($self->{prev_state} == DATA_STATE) {        if ($self->{prev_state} == DATA_STATE) {
# Line 3290  sub _get_next_token ($) { Line 3307  sub _get_next_token ($) {
3307        my $code = $self->{s_kwd};        my $code = $self->{s_kwd};
3308        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3309        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3310        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {        if ($charref_map->{$code}) {
3311          !!!cp (1008);          !!!cp (1008);
3312          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3313                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
3314                          line => $l, column => $c);                          line => $l, column => $c);
3315          $code = 0xFFFD;          $code = $charref_map->{$code};
3316        } elsif ($code > 0x10FFFF) {        } elsif ($code > 0x10FFFF) {
3317          !!!cp (1009);          !!!cp (1009);
3318          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3319                          text => (sprintf 'U-%08X', $code),                          text => (sprintf 'U-%08X', $code),
3320                          line => $l, column => $c);                          line => $l, column => $c);
3321          $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};  
3322        }        }
3323    
3324        if ($self->{prev_state} == DATA_STATE) {        if ($self->{prev_state} == DATA_STATE) {
# Line 3467  sub _construct_tree ($) { Line 3476  sub _construct_tree ($) {
3476    
3477    undef $self->{form_element};    undef $self->{form_element};
3478    undef $self->{head_element};    undef $self->{head_element};
3479      undef $self->{head_element_inserted};
3480    $self->{open_elements} = [];    $self->{open_elements} = [];
3481    undef $self->{inner_html_node};    undef $self->{inner_html_node};
3482    
# Line 3774  sub _tree_construction_root_element ($) Line 3784  sub _tree_construction_root_element ($)
3784      ## NOTE: Reprocess the token.      ## NOTE: Reprocess the token.
3785      !!!ack-later;      !!!ack-later;
3786      return; ## Go to the "before head" insertion mode.      return; ## Go to the "before head" insertion mode.
   
     ## ISSUE: There is an issue in the spec  
3787    } # B    } # B
3788    
3789    die "$0: _tree_construction_root_element: This should never be reached";    die "$0: _tree_construction_root_element: This should never be reached";
# Line 4076  sub _tree_construction_main ($) { Line 4084  sub _tree_construction_main ($) {
4084    
4085    ## NOTE: $open_tables->[-1]->[0] is the "current table" element node.    ## NOTE: $open_tables->[-1]->[0] is the "current table" element node.
4086    ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag.    ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag.
4087      ## NOTE: $open_tables->[-1]->[2] is set false when non-Text node inserted.
4088    my $open_tables = [[$self->{open_elements}->[0]->[0]]];    my $open_tables = [[$self->{open_elements}->[0]->[0]]];
4089    
4090    my $formatting_end_tag = sub {    my $formatting_end_tag = sub {
# Line 4349  sub _tree_construction_main ($) { Line 4358  sub _tree_construction_main ($) {
4358      }      }
4359    }; # $insert_to_foster    }; # $insert_to_foster
4360    
4361      ## NOTE: When a character is inserted, if the last node that was
4362      ## inserted by the parser is a Text node and the character has to be
4363      ## inserted after that node, then the character is appended to the
4364      ## Text node.  However, if any other node is inserted by the parser,
4365      ## then a new Text node is created and the character is appended as
4366      ## that Text node.  If I'm not wrong, there are only two cases where
4367      ## this occurs.  One is the case where an element node is inserted
4368      ## to the |head| element.  This is covered by using the
4369      ## |$self->{head_element_inserted}| flag.  Another is the case where
4370      ## an element or comment is inserted into the |table| subtree while
4371      ## foster parenting happens.  This is covered by using the [2] flag
4372      ## of the |$open_tables| structure.  All other cases are handled
4373      ## simply by calling |manakai_append_text| method.
4374    
4375    B: while (1) {    B: while (1) {
4376      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
4377        !!!cp ('t73');        !!!cp ('t73');
# Line 4396  sub _tree_construction_main ($) { Line 4419  sub _tree_construction_main ($) {
4419        } else {        } else {
4420          !!!cp ('t87');          !!!cp ('t87');
4421          $self->{open_elements}->[-1]->[0]->append_child ($comment);          $self->{open_elements}->[-1]->[0]->append_child ($comment);
4422            $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
4423        }        }
4424        !!!next-token;        !!!next-token;
4425        next B;        next B;
# Line 4511  sub _tree_construction_main ($) { Line 4535  sub _tree_construction_main ($) {
4535          pop @{$self->{open_elements}}          pop @{$self->{open_elements}}
4536              while $self->{open_elements}->[-1]->[1] & FOREIGN_EL;              while $self->{open_elements}->[-1]->[1] & FOREIGN_EL;
4537    
4538            ## NOTE: |<span><svg>| ... two parse errors, |<svg>| ... a parse error.
4539    
4540          $self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM;          $self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM;
4541          ## Reprocess.          ## Reprocess.
4542          next B;          next B;
# Line 4523  sub _tree_construction_main ($) { Line 4549  sub _tree_construction_main ($) {
4549        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
4550          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
4551            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4552              !!!cp ('t88.2');              if ($self->{head_element_inserted}) {
4553              $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);                !!!cp ('t88.3');
4554              #                $self->{open_elements}->[-1]->[0]->append_child
4555                    ($self->{document}->create_text_node ($1));
4556                  delete $self->{head_element_inserted};
4557                  ## NOTE: |</head> <link> |
4558                  #
4559                } else {
4560                  !!!cp ('t88.2');
4561                  $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
4562                  ## NOTE: |</head> &#x20;|
4563                  #
4564                }
4565            } else {            } else {
4566              !!!cp ('t88.1');              !!!cp ('t88.1');
4567              ## Ignore the token.              ## Ignore the token.
# Line 4621  sub _tree_construction_main ($) { Line 4657  sub _tree_construction_main ($) {
4657            !!!cp ('t97');            !!!cp ('t97');
4658          }          }
4659    
4660              if ($token->{tag_name} eq 'base') {          if ($token->{tag_name} eq 'base') {
4661                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4662                  !!!cp ('t98');              !!!cp ('t98');
4663                  ## As if </noscript>              ## As if </noscript>
4664                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
4665                  !!!parse-error (type => 'in noscript', text => 'base',              !!!parse-error (type => 'in noscript', text => 'base',
4666                                  token => $token);                              token => $token);
4667                            
4668                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
4669                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
4670                } else {            } else {
4671                  !!!cp ('t99');              !!!cp ('t99');
4672                }            }
4673    
4674                ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
4675                if ($self->{insertion_mode} == AFTER_HEAD_IM) {            if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4676                  !!!cp ('t100');              !!!cp ('t100');
4677                  !!!parse-error (type => 'after head',              !!!parse-error (type => 'after head',
4678                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
4679                  push @{$self->{open_elements}},              push @{$self->{open_elements}},
4680                      [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4681                } else {              $self->{head_element_inserted} = 1;
4682                  !!!cp ('t101');            } else {
4683                }              !!!cp ('t101');
4684                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            }
4685                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4686                pop @{$self->{open_elements}} # <head>            pop @{$self->{open_elements}};
4687                    if $self->{insertion_mode} == AFTER_HEAD_IM;            pop @{$self->{open_elements}} # <head>
4688                !!!nack ('t101.1');                if $self->{insertion_mode} == AFTER_HEAD_IM;
4689                !!!next-token;            !!!nack ('t101.1');
4690                next B;            !!!next-token;
4691              } elsif ($token->{tag_name} eq 'link') {            next B;
4692                ## NOTE: There is a "as if in head" code clone.          } elsif ($token->{tag_name} eq 'link') {
4693                if ($self->{insertion_mode} == AFTER_HEAD_IM) {            ## NOTE: There is a "as if in head" code clone.
4694                  !!!cp ('t102');            if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4695                  !!!parse-error (type => 'after head',              !!!cp ('t102');
4696                                  text => $token->{tag_name}, token => $token);              !!!parse-error (type => 'after head',
4697                  push @{$self->{open_elements}},                              text => $token->{tag_name}, token => $token);
4698                      [$self->{head_element}, $el_category->{head}];              push @{$self->{open_elements}},
4699                } else {                  [$self->{head_element}, $el_category->{head}];
4700                  !!!cp ('t103');              $self->{head_element_inserted} = 1;
4701                }            } else {
4702                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);              !!!cp ('t103');
4703                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.            }
4704                pop @{$self->{open_elements}} # <head>            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4705                    if $self->{insertion_mode} == AFTER_HEAD_IM;            pop @{$self->{open_elements}};
4706                !!!ack ('t103.1');            pop @{$self->{open_elements}} # <head>
4707                !!!next-token;                if $self->{insertion_mode} == AFTER_HEAD_IM;
4708                next B;            !!!ack ('t103.1');
4709              } elsif ($token->{tag_name} eq 'meta') {            !!!next-token;
4710                ## NOTE: There is a "as if in head" code clone.            next B;
4711                if ($self->{insertion_mode} == AFTER_HEAD_IM) {          } elsif ($token->{tag_name} eq 'command' or
4712                  !!!cp ('t104');                   $token->{tag_name} eq 'eventsource') {
4713                  !!!parse-error (type => 'after head',            if ($self->{insertion_mode} == IN_HEAD_IM) {
4714                                  text => $token->{tag_name}, token => $token);              ## NOTE: If the insertion mode at the time of the emission
4715                  push @{$self->{open_elements}},              ## of the token was "before head", $self->{insertion_mode}
4716                      [$self->{head_element}, $el_category->{head}];              ## is already changed to |IN_HEAD_IM|.
4717                } else {  
4718                  !!!cp ('t105');              ## NOTE: There is a "as if in head" code clone.
4719                }              !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4720                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);              pop @{$self->{open_elements}};
4721                my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.              pop @{$self->{open_elements}} # <head>
4722                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4723                !!!ack ('t103.2');
4724                !!!next-token;
4725                next B;
4726              } else {
4727                ## NOTE: "in head noscript" or "after head" insertion mode
4728                ## - in these cases, these tags are treated as same as
4729                ## normal in-body tags.
4730                !!!cp ('t103.3');
4731                #
4732              }
4733            } elsif ($token->{tag_name} eq 'meta') {
4734              ## NOTE: There is a "as if in head" code clone.
4735              if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4736                !!!cp ('t104');
4737                !!!parse-error (type => 'after head',
4738                                text => $token->{tag_name}, token => $token);
4739                push @{$self->{open_elements}},
4740                    [$self->{head_element}, $el_category->{head}];
4741                $self->{head_element_inserted} = 1;
4742              } else {
4743                !!!cp ('t105');
4744              }
4745              !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4746              my $meta_el = pop @{$self->{open_elements}};
4747    
4748                unless ($self->{confident}) {                unless ($self->{confident}) {
4749                  if ($token->{attributes}->{charset}) {                  if ($token->{attributes}->{charset}) {
# Line 4740  sub _tree_construction_main ($) { Line 4801  sub _tree_construction_main ($) {
4801                !!!ack ('t110.1');                !!!ack ('t110.1');
4802                !!!next-token;                !!!next-token;
4803                next B;                next B;
4804              } elsif ($token->{tag_name} eq 'title') {          } elsif ($token->{tag_name} eq 'title') {
4805                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4806                  !!!cp ('t111');              !!!cp ('t111');
4807                  ## As if </noscript>              ## As if </noscript>
4808                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
4809                  !!!parse-error (type => 'in noscript', text => 'title',              !!!parse-error (type => 'in noscript', text => 'title',
4810                                  token => $token);                              token => $token);
4811                            
4812                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
4813                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
4814                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4815                  !!!cp ('t112');              !!!cp ('t112');
4816                  !!!parse-error (type => 'after head',              !!!parse-error (type => 'after head',
4817                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
4818                  push @{$self->{open_elements}},              push @{$self->{open_elements}},
4819                      [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4820                } else {              $self->{head_element_inserted} = 1;
4821                  !!!cp ('t113');            } else {
4822                }              !!!cp ('t113');
4823              }
4824    
4825                ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
4826                my $parent = defined $self->{head_element} ? $self->{head_element}            $parse_rcdata->(RCDATA_CONTENT_MODEL);
4827                    : $self->{open_elements}->[-1]->[0];            pop @{$self->{open_elements}} # <head>
4828                $parse_rcdata->(RCDATA_CONTENT_MODEL);                if $self->{insertion_mode} == AFTER_HEAD_IM;
4829                pop @{$self->{open_elements}} # <head>            next B;
4830                    if $self->{insertion_mode} == AFTER_HEAD_IM;          } elsif ($token->{tag_name} eq 'style' or
4831                next B;                   $token->{tag_name} eq 'noframes') {
4832              } elsif ($token->{tag_name} eq 'style' or            ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and
4833                       $token->{tag_name} eq 'noframes') {            ## insertion mode IN_HEAD_IM)
4834                ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and            ## NOTE: There is a "as if in head" code clone.
4835                ## insertion mode IN_HEAD_IM)            if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4836                ## NOTE: There is a "as if in head" code clone.              !!!cp ('t114');
4837                if ($self->{insertion_mode} == AFTER_HEAD_IM) {              !!!parse-error (type => 'after head',
4838                  !!!cp ('t114');                              text => $token->{tag_name}, token => $token);
4839                  !!!parse-error (type => 'after head',              push @{$self->{open_elements}},
4840                                  text => $token->{tag_name}, token => $token);                  [$self->{head_element}, $el_category->{head}];
4841                  push @{$self->{open_elements}},              $self->{head_element_inserted} = 1;
4842                      [$self->{head_element}, $el_category->{head}];            } else {
4843                } else {              !!!cp ('t115');
4844                  !!!cp ('t115');            }
4845                }            $parse_rcdata->(CDATA_CONTENT_MODEL);
4846                $parse_rcdata->(CDATA_CONTENT_MODEL);            pop @{$self->{open_elements}} # <head>
4847                pop @{$self->{open_elements}} # <head>                if $self->{insertion_mode} == AFTER_HEAD_IM;
4848                    if $self->{insertion_mode} == AFTER_HEAD_IM;            next B;
               next B;  
4849              } elsif ($token->{tag_name} eq 'noscript') {              } elsif ($token->{tag_name} eq 'noscript') {
4850                if ($self->{insertion_mode} == IN_HEAD_IM) {                if ($self->{insertion_mode} == IN_HEAD_IM) {
4851                  !!!cp ('t116');                  !!!cp ('t116');
# Line 4806  sub _tree_construction_main ($) { Line 4867  sub _tree_construction_main ($) {
4867                  !!!cp ('t118');                  !!!cp ('t118');
4868                  #                  #
4869                }                }
4870              } elsif ($token->{tag_name} eq 'script') {          } elsif ($token->{tag_name} eq 'script') {
4871                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4872                  !!!cp ('t119');              !!!cp ('t119');
4873                  ## As if </noscript>              ## As if </noscript>
4874                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
4875                  !!!parse-error (type => 'in noscript', text => 'script',              !!!parse-error (type => 'in noscript', text => 'script',
4876                                  token => $token);                              token => $token);
4877                            
4878                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
4879                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
4880                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4881                  !!!cp ('t120');              !!!cp ('t120');
4882                  !!!parse-error (type => 'after head',              !!!parse-error (type => 'after head',
4883                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
4884                  push @{$self->{open_elements}},              push @{$self->{open_elements}},
4885                      [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4886                } else {              $self->{head_element_inserted} = 1;
4887                  !!!cp ('t121');            } else {
4888                }              !!!cp ('t121');
4889              }
4890    
4891                ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
4892                $script_start_tag->();            $script_start_tag->();
4893                pop @{$self->{open_elements}} # <head>            pop @{$self->{open_elements}} # <head>
4894                    if $self->{insertion_mode} == AFTER_HEAD_IM;                if $self->{insertion_mode} == AFTER_HEAD_IM;
4895                next B;            next B;
4896              } elsif ($token->{tag_name} eq 'body' or          } elsif ($token->{tag_name} eq 'body' or
4897                       $token->{tag_name} eq 'frameset') {                   $token->{tag_name} eq 'frameset') {
4898                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4899                  !!!cp ('t122');                  !!!cp ('t122');
4900                  ## As if </noscript>                  ## As if </noscript>
# Line 5139  sub _tree_construction_main ($) { Line 5201  sub _tree_construction_main ($) {
5201        } else {        } else {
5202          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
5203        }        }
   
           ## ISSUE: An issue in the spec.  
5204      } elsif ($self->{insertion_mode} & BODY_IMS) {      } elsif ($self->{insertion_mode} & BODY_IMS) {
5205            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
5206              !!!cp ('t150');              !!!cp ('t150');
# Line 5526  sub _tree_construction_main ($) { Line 5586  sub _tree_construction_main ($) {
5586    
5587          !!!parse-error (type => 'in table:#text', token => $token);          !!!parse-error (type => 'in table:#text', token => $token);
5588    
5589              ## As if in body, but insert into foster parent element          ## NOTE: As if in body, but insert into the foster parent element.
5590              ## 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);  
5591                            
5592              if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {          if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {
5593                # MUST            # MUST
5594                my $foster_parent_element;            my $foster_parent_element;
5595                my $next_sibling;            my $next_sibling;
5596                my $prev_sibling;            my $prev_sibling;
5597                OE: for (reverse 0..$#{$self->{open_elements}}) {            OE: for (reverse 0..$#{$self->{open_elements}}) {
5598                  if ($self->{open_elements}->[$_]->[1] & TABLE_EL) {              if ($self->{open_elements}->[$_]->[1] & TABLE_EL) {
5599                    my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
5600                    if (defined $parent and $parent->node_type == 1) {                if (defined $parent and $parent->node_type == 1) {
5601                      !!!cp ('t196');                  $foster_parent_element = $parent;
5602                      $foster_parent_element = $parent;                  !!!cp ('t196');
5603                      $next_sibling = $self->{open_elements}->[$_]->[0];                  $next_sibling = $self->{open_elements}->[$_]->[0];
5604                      $prev_sibling = $next_sibling->previous_sibling;                  $prev_sibling = $next_sibling->previous_sibling;
5605                    } 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});  
5606                } else {                } else {
5607                  !!!cp ('t199');                  !!!cp ('t197');
5608                  $foster_parent_element->insert_before                  $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];
5609                    ($self->{document}->create_text_node ($token->{data}),                  $prev_sibling = $foster_parent_element->last_child;
5610                     $next_sibling);                  #
5611                }                }
5612                  last OE;
5613                }
5614              } # OE
5615              $foster_parent_element = $self->{open_elements}->[0]->[0] and
5616              $prev_sibling = $foster_parent_element->last_child
5617                  unless defined $foster_parent_element;
5618              undef $prev_sibling unless $open_tables->[-1]->[2]; # ~node inserted
5619              if (defined $prev_sibling and
5620                  $prev_sibling->node_type == 3) {
5621                !!!cp ('t198');
5622                $prev_sibling->manakai_append_text ($token->{data});
5623              } else {
5624                !!!cp ('t199');
5625                $foster_parent_element->insert_before
5626                    ($self->{document}->create_text_node ($token->{data}),
5627                     $next_sibling);
5628              }
5629            $open_tables->[-1]->[1] = 1; # tainted            $open_tables->[-1]->[1] = 1; # tainted
5630              $open_tables->[-1]->[2] = 1; # ~node inserted
5631          } else {          } else {
5632              ## NOTE: Fragment case or in a foster parent'ed element
5633              ## (e.g. |<table><span>a|).  In fragment case, whether the
5634              ## character is appended to existing node or a new node is
5635              ## created is irrelevant, since the foster parent'ed nodes
5636              ## are discarded and fragment parsing does not invoke any
5637              ## script.
5638            !!!cp ('t200');            !!!cp ('t200');
5639            $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});            $self->{open_elements}->[-1]->[0]->manakai_append_text
5640                  ($token->{data});
5641          }          }
5642                            
5643          !!!next-token;          !!!next-token;
# Line 5606  sub _tree_construction_main ($) { Line 5674  sub _tree_construction_main ($) {
5674                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5675              }              }
5676                                    
5677                  $self->{insertion_mode} = IN_ROW_IM;              $self->{insertion_mode} = IN_ROW_IM;
5678                  if ($token->{tag_name} eq 'tr') {              if ($token->{tag_name} eq 'tr') {
5679                    !!!cp ('t204');                !!!cp ('t204');
5680                    !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5681                    !!!nack ('t204');                $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5682                    !!!next-token;                !!!nack ('t204');
5683                    next B;                !!!next-token;
5684                  } else {                next B;
5685                    !!!cp ('t205');              } else {
5686                    !!!insert-element ('tr',, $token);                !!!cp ('t205');
5687                    ## reprocess in the "in row" insertion mode                !!!insert-element ('tr',, $token);
5688                  }                ## reprocess in the "in row" insertion mode
5689                } else {              }
5690                  !!!cp ('t206');            } else {
5691                }              !!!cp ('t206');
5692              }
5693    
5694                ## Clear back to table row context                ## Clear back to table row context
5695                while (not ($self->{open_elements}->[-1]->[1]                while (not ($self->{open_elements}->[-1]->[1]
# Line 5629  sub _tree_construction_main ($) { Line 5698  sub _tree_construction_main ($) {
5698                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
5699                }                }
5700                                
5701                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5702                $self->{insertion_mode} = IN_CELL_IM;            $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5703              $self->{insertion_mode} = IN_CELL_IM;
5704    
5705                push @$active_formatting_elements, ['#marker', ''];            push @$active_formatting_elements, ['#marker', ''];
5706                                
5707                !!!nack ('t207.1');            !!!nack ('t207.1');
5708              !!!next-token;
5709              next B;
5710            } elsif ({
5711                      caption => 1, col => 1, colgroup => 1,
5712                      tbody => 1, tfoot => 1, thead => 1,
5713                      tr => 1, # $self->{insertion_mode} == IN_ROW_IM
5714                     }->{$token->{tag_name}}) {
5715              if ($self->{insertion_mode} == IN_ROW_IM) {
5716                ## As if </tr>
5717                ## have an element in table scope
5718                my $i;
5719                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5720                  my $node = $self->{open_elements}->[$_];
5721                  if ($node->[1] & TABLE_ROW_EL) {
5722                    !!!cp ('t208');
5723                    $i = $_;
5724                    last INSCOPE;
5725                  } elsif ($node->[1] & TABLE_SCOPING_EL) {
5726                    !!!cp ('t209');
5727                    last INSCOPE;
5728                  }
5729                } # INSCOPE
5730                unless (defined $i) {
5731                  !!!cp ('t210');
5732                  ## TODO: This type is wrong.
5733                  !!!parse-error (type => 'unmacthed end tag',
5734                                  text => $token->{tag_name}, token => $token);
5735                  ## Ignore the token
5736                  !!!nack ('t210.1');
5737                !!!next-token;                !!!next-token;
5738                next B;                next B;
5739              } 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;  
                 }  
5740                                    
5741                  ## Clear back to table row context                  ## Clear back to table row context
5742                  while (not ($self->{open_elements}->[-1]->[1]                  while (not ($self->{open_elements}->[-1]->[1]
# Line 5736  sub _tree_construction_main ($) { Line 5806  sub _tree_construction_main ($) {
5806                  !!!cp ('t218');                  !!!cp ('t218');
5807                }                }
5808    
5809                if ($token->{tag_name} eq 'col') {            if ($token->{tag_name} eq 'col') {
5810                  ## Clear back to table context              ## Clear back to table context
5811                  while (not ($self->{open_elements}->[-1]->[1]              while (not ($self->{open_elements}->[-1]->[1]
5812                                  & TABLE_SCOPING_EL)) {                              & TABLE_SCOPING_EL)) {
5813                    !!!cp ('t219');                !!!cp ('t219');
5814                    ## ISSUE: Can this state be reached?                ## ISSUE: Can this state be reached?
5815                    pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5816                  }              }
5817                                
5818                  !!!insert-element ('colgroup',, $token);              !!!insert-element ('colgroup',, $token);
5819                  $self->{insertion_mode} = IN_COLUMN_GROUP_IM;              $self->{insertion_mode} = IN_COLUMN_GROUP_IM;
5820                  ## reprocess              ## reprocess
5821                  !!!ack-later;              $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5822                  next B;              !!!ack-later;
5823                } elsif ({              next B;
5824                          caption => 1,            } elsif ({
5825                          colgroup => 1,                      caption => 1,
5826                          tbody => 1, tfoot => 1, thead => 1,                      colgroup => 1,
5827                         }->{$token->{tag_name}}) {                      tbody => 1, tfoot => 1, thead => 1,
5828                  ## Clear back to table context                     }->{$token->{tag_name}}) {
5829                ## Clear back to table context
5830                  while (not ($self->{open_elements}->[-1]->[1]                  while (not ($self->{open_elements}->[-1]->[1]
5831                                  & TABLE_SCOPING_EL)) {                                  & TABLE_SCOPING_EL)) {
5832                    !!!cp ('t220');                    !!!cp ('t220');
# Line 5763  sub _tree_construction_main ($) { Line 5834  sub _tree_construction_main ($) {
5834                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
5835                  }                  }
5836                                    
5837                  push @$active_formatting_elements, ['#marker', '']              push @$active_formatting_elements, ['#marker', '']
5838                      if $token->{tag_name} eq 'caption';                  if $token->{tag_name} eq 'caption';
5839                                    
5840                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);              !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5841                  $self->{insertion_mode} = {              $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5842                                             caption => IN_CAPTION_IM,              $self->{insertion_mode} = {
5843                                             colgroup => IN_COLUMN_GROUP_IM,                                         caption => IN_CAPTION_IM,
5844                                             tbody => IN_TABLE_BODY_IM,                                         colgroup => IN_COLUMN_GROUP_IM,
5845                                             tfoot => IN_TABLE_BODY_IM,                                         tbody => IN_TABLE_BODY_IM,
5846                                             thead => IN_TABLE_BODY_IM,                                         tfoot => IN_TABLE_BODY_IM,
5847                                            }->{$token->{tag_name}};                                         thead => IN_TABLE_BODY_IM,
5848                  !!!next-token;                                        }->{$token->{tag_name}};
5849                  !!!nack ('t220.1');              !!!next-token;
5850                  next B;              !!!nack ('t220.1');
5851                } else {              next B;
5852                  die "$0: in table: <>: $token->{tag_name}";            } else {
5853                }              die "$0: in table: <>: $token->{tag_name}";
5854              }
5855              } elsif ($token->{tag_name} eq 'table') {              } elsif ($token->{tag_name} eq 'table') {
5856                !!!parse-error (type => 'not closed',                !!!parse-error (type => 'not closed',
5857                                text => $self->{open_elements}->[-1]->[0]                                text => $self->{open_elements}->[-1]->[0]
# Line 5842  sub _tree_construction_main ($) { Line 5914  sub _tree_construction_main ($) {
5914              !!!cp ('t227.8');              !!!cp ('t227.8');
5915              ## NOTE: This is a "as if in head" code clone.              ## NOTE: This is a "as if in head" code clone.
5916              $parse_rcdata->(CDATA_CONTENT_MODEL);              $parse_rcdata->(CDATA_CONTENT_MODEL);
5917                $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5918              next B;              next B;
5919            } else {            } else {
5920              !!!cp ('t227.7');              !!!cp ('t227.7');
# Line 5852  sub _tree_construction_main ($) { Line 5925  sub _tree_construction_main ($) {
5925              !!!cp ('t227.6');              !!!cp ('t227.6');
5926              ## NOTE: This is a "as if in head" code clone.              ## NOTE: This is a "as if in head" code clone.
5927              $script_start_tag->();              $script_start_tag->();
5928                $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5929              next B;              next B;
5930            } else {            } else {
5931              !!!cp ('t227.5');              !!!cp ('t227.5');
# Line 5867  sub _tree_construction_main ($) { Line 5941  sub _tree_construction_main ($) {
5941                                  text => $token->{tag_name}, token => $token);                                  text => $token->{tag_name}, token => $token);
5942    
5943                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5944                    $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5945    
5946                  ## TODO: form element pointer                  ## TODO: form element pointer
5947    
# Line 6768  sub _tree_construction_main ($) { Line 6843  sub _tree_construction_main ($) {
6843        } else {        } else {
6844          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
6845        }        }
   
       ## ISSUE: An issue in spec here  
6846      } else {      } else {
6847        die "$0: $self->{insertion_mode}: Unknown insertion mode";        die "$0: $self->{insertion_mode}: Unknown insertion mode";
6848      }      }
# Line 6787  sub _tree_construction_main ($) { Line 6860  sub _tree_construction_main ($) {
6860          $parse_rcdata->(CDATA_CONTENT_MODEL);          $parse_rcdata->(CDATA_CONTENT_MODEL);
6861          next B;          next B;
6862        } elsif ({        } elsif ({
6863                  base => 1, link => 1,                  base => 1, command => 1, eventsource => 1, link => 1,
6864                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
6865          !!!cp ('t334');          !!!cp ('t334');
6866          ## 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
6867          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6868          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          pop @{$self->{open_elements}};
6869          !!!ack ('t334.1');          !!!ack ('t334.1');
6870          !!!next-token;          !!!next-token;
6871          next B;          next B;
6872        } elsif ($token->{tag_name} eq 'meta') {        } elsif ($token->{tag_name} eq 'meta') {
6873          ## 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
6874          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6875          my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          my $meta_el = pop @{$self->{open_elements}};
6876    
6877          unless ($self->{confident}) {          unless ($self->{confident}) {
6878            if ($token->{attributes}->{charset}) {            if ($token->{attributes}->{charset}) {
# Line 6878  sub _tree_construction_main ($) { Line 6951  sub _tree_construction_main ($) {
6951          !!!next-token;          !!!next-token;
6952          next B;          next B;
6953        } elsif ({        } elsif ({
6954                  address => 1, blockquote => 1, center => 1, dir => 1,                  ## NOTE: Start tags for non-phrasing flow content elements
6955                  div => 1, dl => 1, fieldset => 1,  
6956                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                  ## NOTE: The normal one
6957                  menu => 1, ol => 1, p => 1, ul => 1,                  address => 1, article => 1, aside => 1, blockquote => 1,
6958                    center => 1, datagrid => 1, details => 1, dialog => 1,
6959                    dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,
6960                    footer => 1, h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1,
6961                    h6 => 1, header => 1, menu => 1, nav => 1, ol => 1, p => 1,
6962                    section => 1, ul => 1,
6963                    ## NOTE: As normal, but drops leading newline
6964                  pre => 1, listing => 1,                  pre => 1, listing => 1,
6965                    ## NOTE: As normal, but interacts with the form element pointer
6966                  form => 1,                  form => 1,
6967                    
6968                  table => 1,                  table => 1,
6969                  hr => 1,                  hr => 1,
6970                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 6950  sub _tree_construction_main ($) { Line 7031  sub _tree_construction_main ($) {
7031            !!!next-token;            !!!next-token;
7032          }          }
7033          next B;          next B;
7034        } elsif ({li => 1, dt => 1, dd => 1}->{$token->{tag_name}}) {        } elsif ($token->{tag_name} eq 'li') {
7035          ## has a p element in scope          ## NOTE: As normal, but imply </li> when there's another <li> ...
7036    
7037            ## NOTE: Special, Scope (<li><foo><li> == <li><foo><li/></foo></li>)
7038              ## Interpreted as <li><foo/></li><li/> (non-conforming)
7039              ## blockquote (O9.27), center (O), dd (Fx3, O, S3.1.2, IE7),
7040              ## dt (Fx, O, S, IE), dl (O), fieldset (O, S, IE), form (Fx, O, S),
7041              ## hn (O), pre (O), applet (O, S), button (O, S), marquee (Fx, O, S),
7042              ## object (Fx)
7043              ## Generate non-tree (non-conforming)
7044              ## basefont (IE7 (where basefont is non-void)), center (IE),
7045              ## form (IE), hn (IE)
7046            ## address, div, p (<li><foo><li> == <li><foo/></li><li/>)
7047              ## Interpreted as <li><foo><li/></foo></li> (non-conforming)
7048              ## div (Fx, S)
7049    
7050            my $non_optional;
7051            my $i = -1;
7052    
7053            ## 1.
7054            for my $node (reverse @{$self->{open_elements}}) {
7055              if ($node->[1] & LI_EL) {
7056                ## 2. (a) As if </li>
7057                {
7058                  ## If no </li> - not applied
7059                  #
7060    
7061                  ## Otherwise
7062    
7063                  ## 1. generate implied end tags, except for </li>
7064                  #
7065    
7066                  ## 2. If current node != "li", parse error
7067                  if ($non_optional) {
7068                    !!!parse-error (type => 'not closed',
7069                                    text => $non_optional->[0]->manakai_local_name,
7070                                    token => $token);
7071                    !!!cp ('t355');
7072                  } else {
7073                    !!!cp ('t356');
7074                  }
7075    
7076                  ## 3. Pop
7077                  splice @{$self->{open_elements}}, $i;
7078                }
7079    
7080                last; ## 2. (b) goto 5.
7081              } elsif (
7082                       ## NOTE: not "formatting" and not "phrasing"
7083                       ($node->[1] & SPECIAL_EL or
7084                        $node->[1] & SCOPING_EL) and
7085                       ## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|.
7086    
7087                       (not $node->[1] & ADDRESS_EL) &
7088                       (not $node->[1] & DIV_EL) &
7089                       (not $node->[1] & P_EL)) {
7090                ## 3.
7091                !!!cp ('t357');
7092                last; ## goto 5.
7093              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7094                !!!cp ('t358');
7095                #
7096              } else {
7097                !!!cp ('t359');
7098                $non_optional ||= $node;
7099                #
7100              }
7101              ## 4.
7102              ## goto 2.
7103              $i--;
7104            }
7105    
7106            ## 5. (a) has a |p| element in scope
7107          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
7108            if ($_->[1] & P_EL) {            if ($_->[1] & P_EL) {
7109              !!!cp ('t353');              !!!cp ('t353');
7110    
7111                ## NOTE: |<p><li>|, for example.
7112    
7113              !!!back-token; # <x>              !!!back-token; # <x>
7114              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
7115                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
# Line 6964  sub _tree_construction_main ($) { Line 7119  sub _tree_construction_main ($) {
7119              last INSCOPE;              last INSCOPE;
7120            }            }
7121          } # INSCOPE          } # INSCOPE
7122              
7123          ## Step 1          ## 5. (b) insert
7124            !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7125            !!!nack ('t359.1');
7126            !!!next-token;
7127            next B;
7128          } elsif ($token->{tag_name} eq 'dt' or
7129                   $token->{tag_name} eq 'dd') {
7130            ## NOTE: As normal, but imply </dt> or </dd> when ...
7131    
7132            my $non_optional;
7133          my $i = -1;          my $i = -1;
7134          my $node = $self->{open_elements}->[$i];  
7135          my $li_or_dtdd = {li => {li => 1},          ## 1.
7136                            dt => {dt => 1, dd => 1},          for my $node (reverse @{$self->{open_elements}}) {
7137                            dd => {dt => 1, dd => 1}}->{$token->{tag_name}};            if ($node->[1] & DT_EL or $node->[1] & DD_EL) {
7138          LI: {              ## 2. (a) As if </li>
7139            ## Step 2              {
7140            if ($li_or_dtdd->{$node->[0]->manakai_local_name}) {                ## If no </li> - not applied
7141              if ($i != -1) {                #
7142                !!!cp ('t355');  
7143                !!!parse-error (type => 'not closed',                ## Otherwise
7144                                text => $self->{open_elements}->[-1]->[0]  
7145                                    ->manakai_local_name,                ## 1. generate implied end tags, except for </dt> or </dd>
7146                                token => $token);                #
7147              } else {  
7148                !!!cp ('t356');                ## 2. If current node != "dt"|"dd", parse error
7149                  if ($non_optional) {
7150                    !!!parse-error (type => 'not closed',
7151                                    text => $non_optional->[0]->manakai_local_name,
7152                                    token => $token);
7153                    !!!cp ('t355.1');
7154                  } else {
7155                    !!!cp ('t356.1');
7156                  }
7157    
7158                  ## 3. Pop
7159                  splice @{$self->{open_elements}}, $i;
7160              }              }
7161              splice @{$self->{open_elements}}, $i;  
7162              last LI;              last; ## 2. (b) goto 5.
7163              } elsif (
7164                       ## NOTE: not "formatting" and not "phrasing"
7165                       ($node->[1] & SPECIAL_EL or
7166                        $node->[1] & SCOPING_EL) and
7167                       ## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|.
7168    
7169                       (not $node->[1] & ADDRESS_EL) &
7170                       (not $node->[1] & DIV_EL) &
7171                       (not $node->[1] & P_EL)) {
7172                ## 3.
7173                !!!cp ('t357.1');
7174                last; ## goto 5.
7175              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7176                !!!cp ('t358.1');
7177                #
7178            } else {            } else {
7179              !!!cp ('t357');              !!!cp ('t359.1');
7180            }              $non_optional ||= $node;
7181                          #
           ## 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;  
7182            }            }
7183                        ## 4.
7184            !!!cp ('t359');            ## goto 2.
           ## Step 4  
7185            $i--;            $i--;
7186            $node = $self->{open_elements}->[$i];          }
7187            redo LI;  
7188          } # LI          ## 5. (a) has a |p| element in scope
7189                      INSCOPE: for (reverse @{$self->{open_elements}}) {
7190              if ($_->[1] & P_EL) {
7191                !!!cp ('t353.1');
7192                !!!back-token; # <x>
7193                $token = {type => END_TAG_TOKEN, tag_name => 'p',
7194                          line => $token->{line}, column => $token->{column}};
7195                next B;
7196              } elsif ($_->[1] & SCOPING_EL) {
7197                !!!cp ('t354.1');
7198                last INSCOPE;
7199              }
7200            } # INSCOPE
7201    
7202            ## 5. (b) insert
7203          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7204          !!!nack ('t359.1');          !!!nack ('t359.2');
7205          !!!next-token;          !!!next-token;
7206          next B;          next B;
7207        } elsif ($token->{tag_name} eq 'plaintext') {        } elsif ($token->{tag_name} eq 'plaintext') {
7208            ## NOTE: As normal, but effectively ends parsing
7209    
7210          ## has a p element in scope          ## has a p element in scope
7211          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
7212            if ($_->[1] & P_EL) {            if ($_->[1] & P_EL) {
# Line 7249  sub _tree_construction_main ($) { Line 7444  sub _tree_construction_main ($) {
7444          }          }
7445          !!!next-token;          !!!next-token;
7446          next B;          next B;
7447          } elsif ($token->{tag_name} eq 'optgroup' or
7448                   $token->{tag_name} eq 'option') {
7449            ## has an |option| element in scope
7450            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7451              my $node = $self->{open_elements}->[$_];
7452              if ($node->[1] & OPTION_EL) {
7453                !!!cp ('t397.1');
7454                ## NOTE: As if </option>
7455                !!!back-token; # <option> or <optgroup>
7456                $token = {type => END_TAG_TOKEN, tag_name => 'option',
7457                          line => $token->{line}, column => $token->{column}};
7458                next B;
7459              } elsif ($node->[1] & SCOPING_EL) {
7460                !!!cp ('t397.2');
7461                last INSCOPE;
7462              }
7463            } # INSCOPE
7464    
7465            $reconstruct_active_formatting_elements->($insert_to_current);
7466    
7467            !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7468    
7469            !!!nack ('t397.3');
7470            !!!next-token;
7471            redo B;
7472        } elsif ($token->{tag_name} eq 'rt' or        } elsif ($token->{tag_name} eq 'rt' or
7473                 $token->{tag_name} eq 'rp') {                 $token->{tag_name} eq 'rp') {
7474          ## has a |ruby| element in scope          ## has a |ruby| element in scope
# Line 7296  sub _tree_construction_main ($) { Line 7516  sub _tree_construction_main ($) {
7516                    
7517          if ($self->{self_closing}) {          if ($self->{self_closing}) {
7518            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
7519            !!!ack ('t398.1');            !!!ack ('t398.6');
7520          } else {          } else {
7521            !!!cp ('t398.2');            !!!cp ('t398.7');
7522            $self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM;            $self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM;
7523            ## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion            ## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion
7524            ## mode, "in body" (not "in foreign content") secondary insertion            ## mode, "in body" (not "in foreign content") secondary insertion
# Line 7309  sub _tree_construction_main ($) { Line 7529  sub _tree_construction_main ($) {
7529          next B;          next B;
7530        } elsif ({        } elsif ({
7531                  caption => 1, col => 1, colgroup => 1, frame => 1,                  caption => 1, col => 1, colgroup => 1, frame => 1,
7532                  frameset => 1, head => 1, option => 1, optgroup => 1,                  frameset => 1, head => 1,
7533                  tbody => 1, td => 1, tfoot => 1, th => 1,                  tbody => 1, td => 1, tfoot => 1, th => 1,
7534                  thead => 1, tr => 1,                  thead => 1, tr => 1,
7535                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 7320  sub _tree_construction_main ($) { Line 7540  sub _tree_construction_main ($) {
7540          !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.          !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.
7541          !!!next-token;          !!!next-token;
7542          next B;          next B;
7543                  } elsif ($token->{tag_name} eq 'param' or
7544          ## ISSUE: An issue on HTML5 new elements in the spec.                 $token->{tag_name} eq 'source') {
7545            !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7546            pop @{$self->{open_elements}};
7547    
7548            !!!ack ('t398.5');
7549            !!!next-token;
7550            redo B;
7551        } else {        } else {
7552          if ($token->{tag_name} eq 'image') {          if ($token->{tag_name} eq 'image') {
7553            !!!cp ('t384');            !!!cp ('t384');
# Line 7344  sub _tree_construction_main ($) { Line 7570  sub _tree_construction_main ($) {
7570            !!!nack ('t380.1');            !!!nack ('t380.1');
7571          } elsif ({          } elsif ({
7572                    b => 1, big => 1, em => 1, font => 1, i => 1,                    b => 1, big => 1, em => 1, font => 1, i => 1,
7573                    s => 1, small => 1, strile => 1,                    s => 1, small => 1, strike => 1,
7574                    strong => 1, tt => 1, u => 1,                    strong => 1, tt => 1, u => 1,
7575                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
7576            !!!cp ('t375');            !!!cp ('t375');
# Line 7357  sub _tree_construction_main ($) { Line 7583  sub _tree_construction_main ($) {
7583            !!!ack ('t388.2');            !!!ack ('t388.2');
7584          } elsif ({          } elsif ({
7585                    area => 1, basefont => 1, bgsound => 1, br => 1,                    area => 1, basefont => 1, bgsound => 1, br => 1,
7586                    embed => 1, img => 1, param => 1, spacer => 1, wbr => 1,                    embed => 1, img => 1, spacer => 1, wbr => 1,
                   #image => 1,  
7587                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
7588            !!!cp ('t388.1');            !!!cp ('t388.1');
7589            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
# Line 7399  sub _tree_construction_main ($) { Line 7624  sub _tree_construction_main ($) {
7624              }              }
7625            }            }
7626    
7627            !!!parse-error (type => 'start tag not allowed',            ## NOTE: |<marquee></body>|, |<svg><foreignobject></body>|
7628    
7629              !!!parse-error (type => 'unmatched end tag',
7630                            text => $token->{tag_name}, token => $token);                            text => $token->{tag_name}, token => $token);
7631            ## NOTE: Ignore the token.            ## NOTE: Ignore the token.
7632            !!!next-token;            !!!next-token;
# Line 7426  sub _tree_construction_main ($) { Line 7653  sub _tree_construction_main ($) {
7653          ## up-to-date, though it has same effect as speced.          ## up-to-date, though it has same effect as speced.
7654          if (@{$self->{open_elements}} > 1 and          if (@{$self->{open_elements}} > 1 and
7655              $self->{open_elements}->[1]->[1] & BODY_EL) {              $self->{open_elements}->[1]->[1] & BODY_EL) {
           ## ISSUE: There is an issue in the spec.  
7656            unless ($self->{open_elements}->[-1]->[1] & BODY_EL) {            unless ($self->{open_elements}->[-1]->[1] & BODY_EL) {
7657              !!!cp ('t406');              !!!cp ('t406');
7658              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
# Line 7448  sub _tree_construction_main ($) { Line 7674  sub _tree_construction_main ($) {
7674            next B;            next B;
7675          }          }
7676        } elsif ({        } elsif ({
7677                  address => 1, blockquote => 1, center => 1, dir => 1,                  ## NOTE: End tags for non-phrasing flow content elements
7678                  div => 1, dl => 1, fieldset => 1, listing => 1,  
7679                  menu => 1, ol => 1, pre => 1, ul => 1,                  ## NOTE: The normal ones
7680                    address => 1, article => 1, aside => 1, blockquote => 1,
7681                    center => 1, datagrid => 1, details => 1, dialog => 1,
7682                    dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,
7683                    footer => 1, header => 1, listing => 1, menu => 1, nav => 1,
7684                    ol => 1, pre => 1, section => 1, ul => 1,
7685    
7686                    ## NOTE: As normal, but ... optional tags
7687                  dd => 1, dt => 1, li => 1,                  dd => 1, dt => 1, li => 1,
7688    
7689                  applet => 1, button => 1, marquee => 1, object => 1,                  applet => 1, button => 1, marquee => 1, object => 1,
7690                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7691            ## NOTE: Code for <li> start tags includes "as if </li>" code.
7692            ## Code for <dt> or <dd> start tags includes "as if </dt> or
7693            ## </dd>" code.
7694    
7695          ## has an element in scope          ## has an element in scope
7696          my $i;          my $i;
7697          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
# Line 7480  sub _tree_construction_main ($) { Line 7718  sub _tree_construction_main ($) {
7718                    dd => ($token->{tag_name} ne 'dd'),                    dd => ($token->{tag_name} ne 'dd'),
7719                    dt => ($token->{tag_name} ne 'dt'),                    dt => ($token->{tag_name} ne 'dt'),
7720                    li => ($token->{tag_name} ne 'li'),                    li => ($token->{tag_name} ne 'li'),
7721                      option => 1,
7722                      optgroup => 1,
7723                    p => 1,                    p => 1,
7724                    rt => 1,                    rt => 1,
7725                    rp => 1,                    rp => 1,
# Line 7512  sub _tree_construction_main ($) { Line 7752  sub _tree_construction_main ($) {
7752          !!!next-token;          !!!next-token;
7753          next B;          next B;
7754        } elsif ($token->{tag_name} eq 'form') {        } elsif ($token->{tag_name} eq 'form') {
7755            ## NOTE: As normal, but interacts with the form element pointer
7756    
7757          undef $self->{form_element};          undef $self->{form_element};
7758    
7759          ## has an element in scope          ## has an element in scope
# Line 7559  sub _tree_construction_main ($) { Line 7801  sub _tree_construction_main ($) {
7801          !!!next-token;          !!!next-token;
7802          next B;          next B;
7803        } elsif ({        } elsif ({
7804                    ## NOTE: As normal, except acts as a closer for any ...
7805                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,
7806                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7807          ## has an element in scope          ## has an element in scope
# Line 7604  sub _tree_construction_main ($) { Line 7847  sub _tree_construction_main ($) {
7847          !!!next-token;          !!!next-token;
7848          next B;          next B;
7849        } elsif ($token->{tag_name} eq 'p') {        } elsif ($token->{tag_name} eq 'p') {
7850            ## NOTE: As normal, except </p> implies <p> and ...
7851    
7852          ## has an element in scope          ## has an element in scope
7853            my $non_optional;
7854          my $i;          my $i;
7855          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7856            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
# Line 7615  sub _tree_construction_main ($) { Line 7861  sub _tree_construction_main ($) {
7861            } elsif ($node->[1] & SCOPING_EL) {            } elsif ($node->[1] & SCOPING_EL) {
7862              !!!cp ('t411.1');              !!!cp ('t411.1');
7863              last INSCOPE;              last INSCOPE;
7864              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7865                ## NOTE: |END_TAG_OPTIONAL_EL| includes "p"
7866                !!!cp ('t411.2');
7867                #
7868              } else {
7869                !!!cp ('t411.3');
7870                $non_optional ||= $node;
7871                #
7872            }            }
7873          } # INSCOPE          } # INSCOPE
7874    
7875          if (defined $i) {          if (defined $i) {
7876            if ($self->{open_elements}->[-1]->[0]->manakai_local_name            ## 1. Generate implied end tags
7877                    ne $token->{tag_name}) {            #
7878    
7879              ## 2. If current node != "p", parse error
7880              if ($non_optional) {
7881              !!!cp ('t412.1');              !!!cp ('t412.1');
7882              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
7883                              text => $self->{open_elements}->[-1]->[0]                              text => $non_optional->[0]->manakai_local_name,
                                 ->manakai_local_name,  
7884                              token => $token);                              token => $token);
7885            } else {            } else {
7886              !!!cp ('t414.1');              !!!cp ('t414.1');
7887            }            }
7888    
7889              ## 3. Pop
7890            splice @{$self->{open_elements}}, $i;            splice @{$self->{open_elements}}, $i;
7891          } else {          } else {
7892            !!!cp ('t413.1');            !!!cp ('t413.1');
# Line 7649  sub _tree_construction_main ($) { Line 7906  sub _tree_construction_main ($) {
7906        } elsif ({        } elsif ({
7907                  a => 1,                  a => 1,
7908                  b => 1, big => 1, em => 1, font => 1, i => 1,                  b => 1, big => 1, em => 1, font => 1, i => 1,
7909                  nobr => 1, s => 1, small => 1, strile => 1,                  nobr => 1, s => 1, small => 1, strike => 1,
7910                  strong => 1, tt => 1, u => 1,                  strong => 1, tt => 1, u => 1,
7911                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7912          !!!cp ('t427');          !!!cp ('t427');
# Line 7670  sub _tree_construction_main ($) { Line 7927  sub _tree_construction_main ($) {
7927          ## Ignore the token.          ## Ignore the token.
7928          !!!next-token;          !!!next-token;
7929          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  
           
7930        } else {        } else {
7931            if ($token->{tag_name} eq 'sarcasm') {
7932              sleep 0.001; # take a deep breath
7933            }
7934    
7935          ## Step 1          ## Step 1
7936          my $node_i = -1;          my $node_i = -1;
7937          my $node = $self->{open_elements}->[$node_i];          my $node = $self->{open_elements}->[$node_i];
7938    
7939          ## Step 2          ## Step 2
7940          S2: {          S2: {
7941            if ($node->[0]->manakai_local_name eq $token->{tag_name}) {            my $node_tag_name = $node->[0]->manakai_local_name;
7942              $node_tag_name =~ tr/A-Z/a-z/; # for SVG camelCase tag names
7943              if ($node_tag_name eq $token->{tag_name}) {
7944              ## Step 1              ## Step 1
7945              ## generate implied end tags              ## generate implied end tags
7946              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
# Line 7711  sub _tree_construction_main ($) { Line 7953  sub _tree_construction_main ($) {
7953              }              }
7954                    
7955              ## Step 2              ## Step 2
7956              if ($self->{open_elements}->[-1]->[0]->manakai_local_name              my $current_tag_name
7957                      ne $token->{tag_name}) {                  = $self->{open_elements}->[-1]->[0]->manakai_local_name;
7958                $current_tag_name =~ tr/A-Z/a-z/;
7959                if ($current_tag_name ne $token->{tag_name}) {
7960                !!!cp ('t431');                !!!cp ('t431');
7961                ## NOTE: <x><y></x>                ## NOTE: <x><y></x>
7962                !!!parse-error (type => 'not closed',                !!!parse-error (type => 'not closed',
# Line 7740  sub _tree_construction_main ($) { Line 7984  sub _tree_construction_main ($) {
7984                ## Ignore the token                ## Ignore the token
7985                !!!next-token;                !!!next-token;
7986                last S2;                last S2;
             }  
7987    
7988                  ## NOTE: |<span><dd></span>a|: In Safari 3.1.2 and Opera
7989                  ## 9.27, "a" is a child of <dd> (conforming).  In
7990                  ## Firefox 3.0.2, "a" is a child of <body>.  In WinIE 7,
7991                  ## "a" is a child of both <body> and <dd>.
7992                }
7993                
7994              !!!cp ('t434');              !!!cp ('t434');
7995            }            }
7996                        
# Line 7977  sub set_inner_html ($$$$;$) { Line 8226  sub set_inner_html ($$$$;$) {
8226      push @{$p->{open_elements}}, [$root, $el_category->{html}];      push @{$p->{open_elements}}, [$root, $el_category->{html}];
8227    
8228      undef $p->{head_element};      undef $p->{head_element};
8229        undef $p->{head_element_inserted};
8230    
8231      ## Step 6 # MUST      ## Step 6 # MUST
8232      $p->_reset_insertion_mode;      $p->_reset_insertion_mode;

Legend:
Removed from v.1.189  
changed lines
  Added in v.1.202

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24