/[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.208 by wakaba, Tue Oct 14 02:27:55 2008 UTC revision 1.232 by wakaba, Sun Sep 6 01:30:08 2009 UTC
# Line 179  my $el_category = { Line 179  my $el_category = {
179    dt => DTDD_EL,    dt => DTDD_EL,
180    em => FORMATTING_EL,    em => FORMATTING_EL,
181    embed => MISC_SPECIAL_EL,    embed => MISC_SPECIAL_EL,
   eventsource => MISC_SPECIAL_EL,  
182    fieldset => MISC_SPECIAL_EL,    fieldset => MISC_SPECIAL_EL,
183    figure => MISC_SPECIAL_EL,    figure => MISC_SPECIAL_EL,
184    font => FORMATTING_EL,    font => FORMATTING_EL,
# Line 203  my $el_category = { Line 202  my $el_category = {
202    #image => MISC_SPECIAL_EL, ## NOTE: Commented out in the spec.    #image => MISC_SPECIAL_EL, ## NOTE: Commented out in the spec.
203    input => MISC_SPECIAL_EL,    input => MISC_SPECIAL_EL,
204    isindex => MISC_SPECIAL_EL,    isindex => MISC_SPECIAL_EL,
205      ## XXX keygen? (Whether a void element is in Special or not does not
206      ## affect to the processing, however.)
207    li => LI_EL,    li => LI_EL,
208    link => MISC_SPECIAL_EL,    link => MISC_SPECIAL_EL,
209    listing => MISC_SPECIAL_EL,    listing => MISC_SPECIAL_EL,
# Line 525  sub parse_byte_stream ($$$$;$$) { Line 526  sub parse_byte_stream ($$$$;$$) {
526            
527      if ($char_stream) { # if supported      if ($char_stream) { # if supported
528        ## "Change the encoding" algorithm:        ## "Change the encoding" algorithm:
   
       ## Step 1      
       if ($charset->{category} &  
           Message::Charset::Info::CHARSET_CATEGORY_UTF16 ()) {  
         $charset = Message::Charset::Info->get_by_html_name ('utf-8');  
         ($char_stream, $e_status) = $charset->get_decode_handle  
             ($byte_stream,  
              byte_buffer => \ $buffer->{buffer});  
       }  
       $charset_name = $charset->get_iana_name;  
529                
530        ## Step 2        ## Step 1
531        if (defined $self->{input_encoding} and        if (defined $self->{input_encoding} and
532            $self->{input_encoding} eq $charset_name) {            $self->{input_encoding} eq $charset_name) {
533          !!!parse-error (type => 'charset label:matching',          !!!parse-error (type => 'charset label:matching',
# Line 546  sub parse_byte_stream ($$$$;$$) { Line 537  sub parse_byte_stream ($$$$;$$) {
537          return;          return;
538        }        }
539    
540          ## Step 2 (HTML5 revision 3205)
541          if (defined $self->{input_encoding} and
542              Message::Charset::Info->get_by_html_name ($self->{input_encoding})
543              ->{category} & Message::Charset::Info::CHARSET_CATEGORY_UTF16 ()) {
544            $self->{confident} = 1;
545            return;
546          }
547    
548          ## Step 3
549          if ($charset->{category} &
550              Message::Charset::Info::CHARSET_CATEGORY_UTF16 ()) {
551            $charset = Message::Charset::Info->get_by_html_name ('utf-8');
552            ($char_stream, $e_status) = $charset->get_decode_handle
553                ($byte_stream,
554                 byte_buffer => \ $buffer->{buffer});
555          }
556          $charset_name = $charset->get_iana_name;
557    
558        !!!parse-error (type => 'charset label detected',        !!!parse-error (type => 'charset label detected',
559                        text => $self->{input_encoding},                        text => $self->{input_encoding},
560                        value => $charset_name,                        value => $charset_name,
561                        level => $self->{level}->{warn},                        level => $self->{level}->{warn},
562                        token => $token);                        token => $token);
563                
564        ## Step 3        ## Step 4
565        # if (can) {        # if (can) {
566          ## change the encoding on the fly.          ## change the encoding on the fly.
567          #$self->{confident} = 1;          #$self->{confident} = 1;
568          #return;          #return;
569        # }        # }
570                
571        ## Step 4        ## Step 5
572        throw Whatpm::HTML::RestartParser ();        throw Whatpm::HTML::RestartParser ();
573      }      }
574    }; # $self->{change_encoding}    }; # $self->{change_encoding}
# Line 820  sub IN_CDATA_RCDATA_IM () { 0b1000000000 Line 829  sub IN_CDATA_RCDATA_IM () { 0b1000000000
829      ## combined with the original insertion mode.  In thie parser,      ## combined with the original insertion mode.  In thie parser,
830      ## they are stored together in the bit-or'ed form.      ## they are stored together in the bit-or'ed form.
831    
832    sub IM_MASK () { 0b11111111111 }
833    
834  ## NOTE: "initial" and "before html" insertion modes have no constants.  ## NOTE: "initial" and "before html" insertion modes have no constants.
835    
836  ## NOTE: "after after body" insertion mode.  ## NOTE: "after after body" insertion mode.
# Line 901  sub _tree_construction_initial ($) { Line 912  sub _tree_construction_initial ($) {
912    
913    INITIAL: {    INITIAL: {
914      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
915        ## NOTE: Conformance checkers MAY, instead of reporting "not HTML5"        ## NOTE: Conformance checkers MAY, instead of reporting "not
916        ## error, switch to a conformance checking mode for another        ## HTML5" error, switch to a conformance checking mode for
917        ## language.        ## another language.  (We don't support such mode switchings; it
918          ## is nonsense to do anything different from what browsers do.)
919        my $doctype_name = $token->{name};        my $doctype_name = $token->{name};
920        $doctype_name = '' unless defined $doctype_name;        $doctype_name = '' unless defined $doctype_name;
921        $doctype_name =~ tr/a-z/A-Z/; # ASCII case-insensitive        my $doctype = $self->{document}->create_document_type_definition
922        if (not defined $token->{name} or # <!DOCTYPE>            ($doctype_name);
923            defined $token->{sysid}) {  
924          $doctype_name =~ tr/A-Z/a-z/; # ASCII case-insensitive
925          if ($doctype_name ne 'html') {
926          !!!cp ('t1');          !!!cp ('t1');
927          !!!parse-error (type => 'not HTML5', token => $token);          !!!parse-error (type => 'not HTML5', token => $token);
928        } elsif ($doctype_name ne 'HTML') {        } elsif (defined $token->{pubid}) {
929          !!!cp ('t2');          !!!cp ('t2');
930            ## XXX Obsolete permitted DOCTYPEs
931          !!!parse-error (type => 'not HTML5', token => $token);          !!!parse-error (type => 'not HTML5', token => $token);
932        } elsif (defined $token->{pubid}) {        } elsif (defined $token->{sysid}) {
933          if ($token->{pubid} eq 'XSLT-compat') {          if ($token->{sysid} eq 'about:legacy-compat') {
934            !!!cp ('t1.2');            !!!cp ('t1.2'); ## <!DOCTYPE HTML SYSTEM "about:legacy-compat">
935            !!!parse-error (type => 'XSLT-compat', token => $token,            !!!parse-error (type => 'XSLT-compat', token => $token,
936                            level => $self->{level}->{should});                            level => $self->{level}->{should});
937          } else {          } else {
938            !!!parse-error (type => 'not HTML5', token => $token);            !!!parse-error (type => 'not HTML5', token => $token);
939          }          }
940        } else {        } else { ## <!DOCTYPE HTML>
941          !!!cp ('t3');          !!!cp ('t3');
942          #          #
943        }        }
944                
       my $doctype = $self->{document}->create_document_type_definition  
         ($token->{name}); ## ISSUE: If name is missing (e.g. <!DOCTYPE>)?  
945        ## NOTE: Default value for both |public_id| and |system_id| attributes        ## NOTE: Default value for both |public_id| and |system_id| attributes
946        ## are empty strings, so that we don't set any value in missing cases.        ## are empty strings, so that we don't set any value in missing cases.
947        $doctype->public_id ($token->{pubid}) if defined $token->{pubid};        $doctype->public_id ($token->{pubid}) if defined $token->{pubid};
948        $doctype->system_id ($token->{sysid}) if defined $token->{sysid};        $doctype->system_id ($token->{sysid}) if defined $token->{sysid};
949    
950        ## NOTE: Other DocumentType attributes are null or empty lists.        ## NOTE: Other DocumentType attributes are null or empty lists.
951        ## ISSUE: internalSubset = null??        ## In Firefox3, |internalSubset| attribute is set to the empty
952          ## string, while |null| is an allowed value for the attribute
953          ## according to DOM3 Core.
954        $self->{document}->append_child ($doctype);        $self->{document}->append_child ($doctype);
955                
956        if ($token->{quirks} or $doctype_name ne 'HTML') {        if ($token->{quirks} or $doctype_name ne 'html') {
957          !!!cp ('t4');          !!!cp ('t4');
958          $self->{document}->manakai_compat_mode ('quirks');          $self->{document}->manakai_compat_mode ('quirks');
959        } elsif (defined $token->{pubid}) {        } elsif (defined $token->{pubid}) {
# Line 1407  sub _tree_construction_main ($) { Line 1423  sub _tree_construction_main ($) {
1423      ## Step 3      ## Step 3
1424      ## TODO: Mark as "already executed", if ...      ## TODO: Mark as "already executed", if ...
1425    
1426      ## Step 4      ## Step 4 (HTML5 revision 2702)
1427      $insert->($script_el);      $insert->($script_el);
   
     ## ISSUE: $script_el is not put into the stack  
1428      push @{$self->{open_elements}}, [$script_el, $el_category->{script}];      push @{$self->{open_elements}}, [$script_el, $el_category->{script}];
1429    
1430      ## Step 5      ## Step 5
# Line 1425  sub _tree_construction_main ($) { Line 1439  sub _tree_construction_main ($) {
1439    }; # $script_start_tag    }; # $script_start_tag
1440    
1441    ## NOTE: $open_tables->[-1]->[0] is the "current table" element node.    ## NOTE: $open_tables->[-1]->[0] is the "current table" element node.
1442    ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag.    ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag (OBSOLETE; unused).
1443    ## NOTE: $open_tables->[-1]->[2] is set false when non-Text node inserted.    ## NOTE: $open_tables->[-1]->[2] is set false when non-Text node inserted.
1444    my $open_tables = [[$self->{open_elements}->[0]->[0]]];    my $open_tables = [[$self->{open_elements}->[0]->[0]]];
1445    
# Line 1721  sub _tree_construction_main ($) { Line 1735  sub _tree_construction_main ($) {
1735    ## document.write ("b")</script>|    ## document.write ("b")</script>|
1736    
1737    B: while (1) {    B: while (1) {
1738    
1739        ## The "in table text" insertion mode.
1740        if ($self->{insertion_mode} & TABLE_IMS and
1741            not $self->{insertion_mode} & IN_FOREIGN_CONTENT_IM and
1742            not $self->{insertion_mode} & IN_CDATA_RCDATA_IM) {
1743          C: {
1744            my $s;
1745            if ($token->{type} == CHARACTER_TOKEN) {
1746              !!!cp ('t194');
1747              $self->{pending_chars} ||= [];
1748              push @{$self->{pending_chars}}, $token;
1749              !!!next-token;
1750              next B;
1751            } else {
1752              if ($self->{pending_chars}) {
1753                $s = join '', map { $_->{data} } @{$self->{pending_chars}};
1754                delete $self->{pending_chars};
1755                if ($s =~ /[^\x09\x0A\x0C\x0D\x20]/) {
1756                  !!!cp ('t195');
1757                  #
1758                } else {
1759                  !!!cp ('t195.1');
1760                  #$self->{open_elements}->[-1]->[0]->manakai_append_text ($s);
1761                  $self->{open_elements}->[-1]->[0]->append_child
1762                      ($self->{document}->create_text_node ($s));
1763                  last C;
1764                }
1765              } else {
1766                !!!cp ('t195.2');
1767                last C;
1768              }
1769            }
1770    
1771            ## Foster parenting
1772            !!!parse-error (type => 'in table:#text', token => $token);
1773    
1774            ## NOTE: As if in body, but insert into the foster parent element.
1775            $reconstruct_active_formatting_elements->($insert_to_foster);
1776                
1777            if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {
1778              # MUST
1779              my $foster_parent_element;
1780              my $next_sibling;
1781              #my $prev_sibling;
1782              OE: for (reverse 0..$#{$self->{open_elements}}) {
1783                if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {
1784                  my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
1785                  if (defined $parent and $parent->node_type == 1) {
1786                    $foster_parent_element = $parent;
1787                    !!!cp ('t196');
1788                    $next_sibling = $self->{open_elements}->[$_]->[0];
1789              #      $prev_sibling = $next_sibling->previous_sibling;
1790                    #
1791                  } else {
1792                    !!!cp ('t197');
1793                    $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];
1794              #      $prev_sibling = $foster_parent_element->last_child;
1795                    #
1796                  }
1797                  last OE;
1798                }
1799              } # OE
1800              $foster_parent_element = $self->{open_elements}->[0]->[0] #and
1801              #$prev_sibling = $foster_parent_element->last_child
1802                  unless defined $foster_parent_element;
1803              #undef $prev_sibling unless $open_tables->[-1]->[2]; # ~node inserted
1804              #if (defined $prev_sibling and
1805              #    $prev_sibling->node_type == 3) {
1806              #  !!! cp ('t198');
1807              #  $prev_sibling->manakai_append_text ($s);
1808              #} else {
1809                !!!cp ('t199');
1810                $foster_parent_element->insert_before
1811                    ($self->{document}->create_text_node ($s), $next_sibling);
1812              #}
1813              $open_tables->[-1]->[1] = 1; # tainted
1814              $open_tables->[-1]->[2] = 1; # ~node inserted
1815            } else {
1816              ## NOTE: Fragment case or in a foster parent'ed element
1817              ## (e.g. |<table><span>a|).  In fragment case, whether the
1818              ## character is appended to existing node or a new node is
1819              ## created is irrelevant, since the foster parent'ed nodes
1820              ## are discarded and fragment parsing does not invoke any
1821              ## script.
1822              !!!cp ('t200');
1823              $self->{open_elements}->[-1]->[0]->manakai_append_text ($s);
1824            }
1825          } # C
1826        } # TABLE_IMS
1827    
1828      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
1829        !!!cp ('t73');        !!!cp ('t73');
1830        !!!parse-error (type => 'in html:#DOCTYPE', token => $token);        !!!parse-error (type => 'in html:#DOCTYPE', token => $token);
# Line 1862  sub _tree_construction_main ($) { Line 1966  sub _tree_construction_main ($) {
1966          } elsif ({          } elsif ({
1967                    b => 1, big => 1, blockquote => 1, body => 1, br => 1,                    b => 1, big => 1, blockquote => 1, body => 1, br => 1,
1968                    center => 1, code => 1, dd => 1, div => 1, dl => 1, dt => 1,                    center => 1, code => 1, dd => 1, div => 1, dl => 1, dt => 1,
1969                    em => 1, embed => 1, font => 1, h1 => 1, h2 => 1, h3 => 1,                    em => 1, embed => 1, h1 => 1, h2 => 1, h3 => 1,
1970                    h4 => 1, h5 => 1, h6 => 1, head => 1, hr => 1, i => 1,                    h4 => 1, h5 => 1, h6 => 1, head => 1, hr => 1, i => 1,
1971                    img => 1, li => 1, listing => 1, menu => 1, meta => 1,                    img => 1, li => 1, listing => 1, menu => 1, meta => 1,
1972                    nobr => 1, ol => 1, p => 1, pre => 1, ruby => 1, s => 1,                    nobr => 1, ol => 1, p => 1, pre => 1, ruby => 1, s => 1,
1973                    small => 1, span => 1, strong => 1, strike => 1, sub => 1,                    small => 1, span => 1, strong => 1, strike => 1, sub => 1,
1974                    sup => 1, table => 1, tt => 1, u => 1, ul => 1, var => 1,                    sup => 1, table => 1, tt => 1, u => 1, ul => 1, var => 1,
1975                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}} or
1976                     ($token->{tag_name} eq 'font' and
1977                      ($token->{attributes}->{color} or
1978                       $token->{attributes}->{face} or
1979                       $token->{attributes}->{size}))) {
1980            !!!cp ('t87.2');            !!!cp ('t87.2');
1981            !!!parse-error (type => 'not closed',            !!!parse-error (type => 'not closed',
1982                            text => $self->{open_elements}->[-1]->[0]                            text => $self->{open_elements}->[-1]->[0]
# Line 1944  sub _tree_construction_main ($) { Line 2052  sub _tree_construction_main ($) {
2052          }          }
2053        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
2054          ## NOTE: "using the rules for secondary insertion mode" then "continue"          ## NOTE: "using the rules for secondary insertion mode" then "continue"
2055          !!!cp ('t87.5');          if ($token->{tag_name} eq 'script') {
2056          #            !!!cp ('t87.41');
2057              #
2058              ## XXXscript: Execute script here.
2059            } else {
2060              !!!cp ('t87.5');
2061              #
2062            }
2063        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
2064          !!!cp ('t87.6');          !!!cp ('t87.6');
2065          !!!parse-error (type => 'not closed',          !!!parse-error (type => 'not closed',
# Line 2129  sub _tree_construction_main ($) { Line 2243  sub _tree_construction_main ($) {
2243            !!!ack ('t103.1');            !!!ack ('t103.1');
2244            !!!next-token;            !!!next-token;
2245            next B;            next B;
2246          } elsif ($token->{tag_name} eq 'command' or          } elsif ($token->{tag_name} eq 'command') {
                  $token->{tag_name} eq 'eventsource') {  
2247            if ($self->{insertion_mode} == IN_HEAD_IM) {            if ($self->{insertion_mode} == IN_HEAD_IM) {
2248              ## NOTE: If the insertion mode at the time of the emission              ## NOTE: If the insertion mode at the time of the emission
2249              ## of the token was "before head", $self->{insertion_mode}              ## of the token was "before head", $self->{insertion_mode}
# Line 2245  sub _tree_construction_main ($) { Line 2358  sub _tree_construction_main ($) {
2358    
2359            ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
2360            $parse_rcdata->(RCDATA_CONTENT_MODEL);            $parse_rcdata->(RCDATA_CONTENT_MODEL);
2361            ## ISSUE: A spec bug [Bug 6038]  
2362              ## NOTE: At this point the stack of open elements contain
2363              ## the |head| element (index == -2) and the |script| element
2364              ## (index == -1).  In the "after head" insertion mode the
2365              ## |head| element is inserted only for the purpose of
2366              ## providing the context for the |script| element, and
2367              ## therefore we can now and have to remove the element from
2368              ## the stack.
2369            splice @{$self->{open_elements}}, -2, 1, () # <head>            splice @{$self->{open_elements}}, -2, 1, () # <head>
2370                if ($self->{insertion_mode} & AFTER_HEAD_IM) == AFTER_HEAD_IM;                if ($self->{insertion_mode} & IM_MASK) == AFTER_HEAD_IM;
2371            next B;            next B;
2372          } elsif ($token->{tag_name} eq 'style' or          } elsif ($token->{tag_name} eq 'style' or
2373                   $token->{tag_name} eq 'noframes') {                   $token->{tag_name} eq 'noframes') {
# Line 2267  sub _tree_construction_main ($) { Line 2387  sub _tree_construction_main ($) {
2387            $parse_rcdata->(CDATA_CONTENT_MODEL);            $parse_rcdata->(CDATA_CONTENT_MODEL);
2388            ## ISSUE: A spec bug [Bug 6038]            ## ISSUE: A spec bug [Bug 6038]
2389            splice @{$self->{open_elements}}, -2, 1, () # <head>            splice @{$self->{open_elements}}, -2, 1, () # <head>
2390                if ($self->{insertion_mode} & AFTER_HEAD_IM) == AFTER_HEAD_IM;                if ($self->{insertion_mode} & IM_MASK) == AFTER_HEAD_IM;
2391            next B;            next B;
2392          } elsif ($token->{tag_name} eq 'noscript') {          } elsif ($token->{tag_name} eq 'noscript') {
2393                if ($self->{insertion_mode} == IN_HEAD_IM) {                if ($self->{insertion_mode} == IN_HEAD_IM) {
# Line 2315  sub _tree_construction_main ($) { Line 2435  sub _tree_construction_main ($) {
2435            $script_start_tag->();            $script_start_tag->();
2436            ## ISSUE: A spec bug  [Bug 6038]            ## ISSUE: A spec bug  [Bug 6038]
2437            splice @{$self->{open_elements}}, -2, 1 # <head>            splice @{$self->{open_elements}}, -2, 1 # <head>
2438                if ($self->{insertion_mode} & AFTER_HEAD_IM) == AFTER_HEAD_IM;                if ($self->{insertion_mode} & IM_MASK) == AFTER_HEAD_IM;
2439            next B;            next B;
2440          } elsif ($token->{tag_name} eq 'body' or          } elsif ($token->{tag_name} eq 'body' or
2441                   $token->{tag_name} eq 'frameset') {                   $token->{tag_name} eq 'frameset') {
# Line 2480  sub _tree_construction_main ($) { Line 2600  sub _tree_construction_main ($) {
2600                ## Ignore the token                ## Ignore the token
2601                !!!next-token;                !!!next-token;
2602                next B;                next B;
2603              } elsif ($token->{tag_name} eq 'br') {          } elsif ($token->{tag_name} eq 'br') {
2604                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {            if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
2605                  !!!cp ('t142.2');              !!!cp ('t142.2');
2606                  ## (before head) as if <head>, (in head) as if </head>              ## (before head) as if <head>, (in head) as if </head>
2607                  !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);              !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
2608                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});              $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
2609                  $self->{insertion_mode} = AFTER_HEAD_IM;              $self->{insertion_mode} = AFTER_HEAD_IM;
2610        
2611                  ## Reprocess in the "after head" insertion mode...              ## Reprocess in the "after head" insertion mode...
2612                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {            } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
2613                  !!!cp ('t143.2');              !!!cp ('t143.2');
2614                  ## As if </head>              ## As if </head>
2615                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
2616                  $self->{insertion_mode} = AFTER_HEAD_IM;              $self->{insertion_mode} = AFTER_HEAD_IM;
2617        
2618                  ## Reprocess in the "after head" insertion mode...              ## Reprocess in the "after head" insertion mode...
2619                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
2620                  !!!cp ('t143.3');              !!!cp ('t143.3');
2621                  ## ISSUE: Two parse errors for <head><noscript></br>              ## NOTE: Two parse errors for <head><noscript></br>
2622                  !!!parse-error (type => 'unmatched end tag',              !!!parse-error (type => 'unmatched end tag',
2623                                  text => 'br', token => $token);                              text => 'br', token => $token);
2624                  ## As if </noscript>              ## As if </noscript>
2625                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
2626                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
2627    
2628                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
2629                  ## As if </head>              ## As if </head>
2630                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
2631                  $self->{insertion_mode} = AFTER_HEAD_IM;              $self->{insertion_mode} = AFTER_HEAD_IM;
2632    
2633                  ## Reprocess in the "after head" insertion mode...              ## Reprocess in the "after head" insertion mode...
2634                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
2635                  !!!cp ('t143.4');              !!!cp ('t143.4');
2636                  #              #
2637                } else {            } else {
2638                  die "$0: $self->{insertion_mode}: Unknown insertion mode";              die "$0: $self->{insertion_mode}: Unknown insertion mode";
2639                }            }
2640    
2641                ## ISSUE: does not agree with IE7 - it doesn't ignore </br>.            #
2642                !!!parse-error (type => 'unmatched end tag',          } else { ## Other end tags
                               text => 'br', token => $token);  
               ## Ignore the token  
               !!!next-token;  
               next B;  
             } else {  
2643                !!!cp ('t145');                !!!cp ('t145');
2644                !!!parse-error (type => 'unmatched end tag',                !!!parse-error (type => 'unmatched end tag',
2645                                text => $token->{tag_name}, token => $token);                                text => $token->{tag_name}, token => $token);
# Line 2568  sub _tree_construction_main ($) { Line 2683  sub _tree_construction_main ($) {
2683              !!!insert-element ('body',, $token);              !!!insert-element ('body',, $token);
2684              $self->{insertion_mode} = IN_BODY_IM;              $self->{insertion_mode} = IN_BODY_IM;
2685              ## reprocess              ## reprocess
2686              next B;          next B;
2687        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
2688          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
2689            !!!cp ('t149.1');            !!!cp ('t149.1');
# Line 2641  sub _tree_construction_main ($) { Line 2756  sub _tree_construction_main ($) {
2756                   caption => 1, col => 1, colgroup => 1, tbody => 1,                   caption => 1, col => 1, colgroup => 1, tbody => 1,
2757                   td => 1, tfoot => 1, th => 1, thead => 1, tr => 1,                   td => 1, tfoot => 1, th => 1, thead => 1, tr => 1,
2758                  }->{$token->{tag_name}}) {                  }->{$token->{tag_name}}) {
2759                if ($self->{insertion_mode} == IN_CELL_IM) {                if (($self->{insertion_mode} & IM_MASK) == IN_CELL_IM) {
2760                  ## have an element in table scope                  ## have an element in table scope
2761                  for (reverse 0..$#{$self->{open_elements}}) {                  for (reverse 0..$#{$self->{open_elements}}) {
2762                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
# Line 2669  sub _tree_construction_main ($) { Line 2784  sub _tree_construction_main ($) {
2784                  !!!nack ('t153.1');                  !!!nack ('t153.1');
2785                  !!!next-token;                  !!!next-token;
2786                  next B;                  next B;
2787                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {                } elsif (($self->{insertion_mode} & IM_MASK) == IN_CAPTION_IM) {
2788                  !!!parse-error (type => 'not closed', text => 'caption',                  !!!parse-error (type => 'not closed', text => 'caption',
2789                                  token => $token);                                  token => $token);
2790                                    
# Line 2734  sub _tree_construction_main ($) { Line 2849  sub _tree_construction_main ($) {
2849              }              }
2850            } elsif ($token->{type} == END_TAG_TOKEN) {            } elsif ($token->{type} == END_TAG_TOKEN) {
2851              if ($token->{tag_name} eq 'td' or $token->{tag_name} eq 'th') {              if ($token->{tag_name} eq 'td' or $token->{tag_name} eq 'th') {
2852                if ($self->{insertion_mode} == IN_CELL_IM) {                if (($self->{insertion_mode} & IM_MASK) == IN_CELL_IM) {
2853                  ## have an element in table scope                  ## have an element in table scope
2854                  my $i;                  my $i;
2855                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
# Line 2784  sub _tree_construction_main ($) { Line 2899  sub _tree_construction_main ($) {
2899                                    
2900                  !!!next-token;                  !!!next-token;
2901                  next B;                  next B;
2902                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {                } elsif (($self->{insertion_mode} & IM_MASK) == IN_CAPTION_IM) {
2903                  !!!cp ('t169');                  !!!cp ('t169');
2904                  !!!parse-error (type => 'unmatched end tag',                  !!!parse-error (type => 'unmatched end tag',
2905                                  text => $token->{tag_name}, token => $token);                                  text => $token->{tag_name}, token => $token);
# Line 2796  sub _tree_construction_main ($) { Line 2911  sub _tree_construction_main ($) {
2911                  #                  #
2912                }                }
2913              } elsif ($token->{tag_name} eq 'caption') {              } elsif ($token->{tag_name} eq 'caption') {
2914                if ($self->{insertion_mode} == IN_CAPTION_IM) {                if (($self->{insertion_mode} & IM_MASK) == IN_CAPTION_IM) {
2915                  ## have a table element in table scope                  ## have a table element in table scope
2916                  my $i;                  my $i;
2917                  INSCOPE: {                  INSCOPE: {
# Line 2845  sub _tree_construction_main ($) { Line 2960  sub _tree_construction_main ($) {
2960                                    
2961                  !!!next-token;                  !!!next-token;
2962                  next B;                  next B;
2963                } elsif ($self->{insertion_mode} == IN_CELL_IM) {                } elsif (($self->{insertion_mode} & IM_MASK) == IN_CELL_IM) {
2964                  !!!cp ('t177');                  !!!cp ('t177');
2965                  !!!parse-error (type => 'unmatched end tag',                  !!!parse-error (type => 'unmatched end tag',
2966                                  text => $token->{tag_name}, token => $token);                                  text => $token->{tag_name}, token => $token);
# Line 2860  sub _tree_construction_main ($) { Line 2975  sub _tree_construction_main ($) {
2975                        table => 1, tbody => 1, tfoot => 1,                        table => 1, tbody => 1, tfoot => 1,
2976                        thead => 1, tr => 1,                        thead => 1, tr => 1,
2977                       }->{$token->{tag_name}} and                       }->{$token->{tag_name}} and
2978                       $self->{insertion_mode} == IN_CELL_IM) {                       ($self->{insertion_mode} & IM_MASK) == IN_CELL_IM) {
2979                ## have an element in table scope                ## have an element in table scope
2980                my $i;                my $i;
2981                my $tn;                my $tn;
# Line 2897  sub _tree_construction_main ($) { Line 3012  sub _tree_construction_main ($) {
3012                  next B;                  next B;
3013                } # INSCOPE                } # INSCOPE
3014              } elsif ($token->{tag_name} eq 'table' and              } elsif ($token->{tag_name} eq 'table' and
3015                       $self->{insertion_mode} == IN_CAPTION_IM) {                       ($self->{insertion_mode} & IM_MASK) == IN_CAPTION_IM) {
3016                !!!parse-error (type => 'not closed', text => 'caption',                !!!parse-error (type => 'not closed', text => 'caption',
3017                                token => $token);                                token => $token);
3018    
# Line 2917  sub _tree_construction_main ($) { Line 3032  sub _tree_construction_main ($) {
3032                } # INSCOPE                } # INSCOPE
3033                unless (defined $i) {                unless (defined $i) {
3034                  !!!cp ('t186');                  !!!cp ('t186');
3035            ## TODO: Wrong error type?
3036                  !!!parse-error (type => 'unmatched end tag',                  !!!parse-error (type => 'unmatched end tag',
3037                                  text => 'caption', token => $token);                                  text => 'caption', token => $token);
3038                  ## Ignore the token                  ## Ignore the token
# Line 2962  sub _tree_construction_main ($) { Line 3078  sub _tree_construction_main ($) {
3078                  !!!cp ('t191');                  !!!cp ('t191');
3079                  #                  #
3080                }                }
3081              } elsif ({          } elsif ({
3082                        tbody => 1, tfoot => 1,                    tbody => 1, tfoot => 1,
3083                        thead => 1, tr => 1,                    thead => 1, tr => 1,
3084                       }->{$token->{tag_name}} and                   }->{$token->{tag_name}} and
3085                       $self->{insertion_mode} == IN_CAPTION_IM) {                   ($self->{insertion_mode} & IM_MASK) == IN_CAPTION_IM) {
3086                !!!cp ('t192');            !!!cp ('t192');
3087                !!!parse-error (type => 'unmatched end tag',            !!!parse-error (type => 'unmatched end tag',
3088                                text => $token->{tag_name}, token => $token);                            text => $token->{tag_name}, token => $token);
3089                ## Ignore the token            ## Ignore the token
3090                !!!next-token;            !!!next-token;
3091                next B;            next B;
3092              } else {          } else {
3093                !!!cp ('t193');            !!!cp ('t193');
3094                #            #
3095              }          }
3096        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
3097          for my $entry (@{$self->{open_elements}}) {          for my $entry (@{$self->{open_elements}}) {
3098            unless ($entry->[1] & ALL_END_TAG_OPTIONAL_EL) {            unless ($entry->[1] & ALL_END_TAG_OPTIONAL_EL) {
# Line 2995  sub _tree_construction_main ($) { Line 3111  sub _tree_construction_main ($) {
3111        $insert = $insert_to_current;        $insert = $insert_to_current;
3112        #        #
3113      } elsif ($self->{insertion_mode} & TABLE_IMS) {      } elsif ($self->{insertion_mode} & TABLE_IMS) {
3114        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == START_TAG_TOKEN) {
         if (not $open_tables->[-1]->[1] and # tainted  
             $token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {  
           $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);  
                 
           unless (length $token->{data}) {  
             !!!cp ('t194');  
             !!!next-token;  
             next B;  
           } else {  
             !!!cp ('t195');  
           }  
         }  
   
         !!!parse-error (type => 'in table:#text', token => $token);  
   
         ## NOTE: As if in body, but insert into the foster parent element.  
         $reconstruct_active_formatting_elements->($insert_to_foster);  
               
         if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {  
           # MUST  
           my $foster_parent_element;  
           my $next_sibling;  
           my $prev_sibling;  
           OE: for (reverse 0..$#{$self->{open_elements}}) {  
             if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {  
               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;  
               if (defined $parent and $parent->node_type == 1) {  
                 $foster_parent_element = $parent;  
                 !!!cp ('t196');  
                 $next_sibling = $self->{open_elements}->[$_]->[0];  
                 $prev_sibling = $next_sibling->previous_sibling;  
                 #  
               } 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;  
           undef $prev_sibling unless $open_tables->[-1]->[2]; # ~node inserted  
           if (defined $prev_sibling and  
               $prev_sibling->node_type == 3) {  
             !!!cp ('t198');  
             $prev_sibling->manakai_append_text ($token->{data});  
           } else {  
             !!!cp ('t199');  
             $foster_parent_element->insert_before  
                 ($self->{document}->create_text_node ($token->{data}),  
                  $next_sibling);  
           }  
           $open_tables->[-1]->[1] = 1; # tainted  
           $open_tables->[-1]->[2] = 1; # ~node inserted  
         } else {  
           ## NOTE: Fragment case or in a foster parent'ed element  
           ## (e.g. |<table><span>a|).  In fragment case, whether the  
           ## character is appended to existing node or a new node is  
           ## created is irrelevant, since the foster parent'ed nodes  
           ## are discarded and fragment parsing does not invoke any  
           ## script.  
           !!!cp ('t200');  
           $self->{open_elements}->[-1]->[0]->manakai_append_text  
               ($token->{data});  
         }  
               
         !!!next-token;  
         next B;  
       } elsif ($token->{type} == START_TAG_TOKEN) {  
3115          if ({          if ({
3116               tr => ($self->{insertion_mode} != IN_ROW_IM),               tr => (($self->{insertion_mode} & IM_MASK) != IN_ROW_IM),
3117               th => 1, td => 1,               th => 1, td => 1,
3118              }->{$token->{tag_name}}) {              }->{$token->{tag_name}}) {
3119            if ($self->{insertion_mode} == IN_TABLE_IM) {            if (($self->{insertion_mode} & IM_MASK) == IN_TABLE_IM) {
3120              ## Clear back to table context              ## Clear back to table context
3121              while (not ($self->{open_elements}->[-1]->[1]              while (not ($self->{open_elements}->[-1]->[1]
3122                              & TABLE_SCOPING_EL)) {                              & TABLE_SCOPING_EL)) {
# Line 3085  sub _tree_construction_main ($) { Line 3129  sub _tree_construction_main ($) {
3129              ## reprocess in the "in table body" insertion mode...              ## reprocess in the "in table body" insertion mode...
3130            }            }
3131                        
3132            if ($self->{insertion_mode} == IN_TABLE_BODY_IM) {            if (($self->{insertion_mode} & IM_MASK) == IN_TABLE_BODY_IM) {
3133              unless ($token->{tag_name} eq 'tr') {              unless ($token->{tag_name} eq 'tr') {
3134                !!!cp ('t202');                !!!cp ('t202');
3135                !!!parse-error (type => 'missing start tag:tr', token => $token);                !!!parse-error (type => 'missing start tag:tr', token => $token);
# Line 3137  sub _tree_construction_main ($) { Line 3181  sub _tree_construction_main ($) {
3181                    tbody => 1, tfoot => 1, thead => 1,                    tbody => 1, tfoot => 1, thead => 1,
3182                    tr => 1, # $self->{insertion_mode} == IN_ROW_IM                    tr => 1, # $self->{insertion_mode} == IN_ROW_IM
3183                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
3184            if ($self->{insertion_mode} == IN_ROW_IM) {            if (($self->{insertion_mode} & IM_MASK) == IN_ROW_IM) {
3185              ## As if </tr>              ## As if </tr>
3186              ## have an element in table scope              ## have an element in table scope
3187              my $i;              my $i;
# Line 3184  sub _tree_construction_main ($) { Line 3228  sub _tree_construction_main ($) {
3228                  }                  }
3229                }                }
3230    
3231                if ($self->{insertion_mode} == IN_TABLE_BODY_IM) {                if (($self->{insertion_mode} & IM_MASK) == IN_TABLE_BODY_IM) {
3232                  ## have an element in table scope                  ## have an element in table scope
3233                  my $i;                  my $i;
3234                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
# Line 3398  sub _tree_construction_main ($) { Line 3442  sub _tree_construction_main ($) {
3442          $insert = $insert_to_foster;          $insert = $insert_to_foster;
3443          #          #
3444        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
3445              if ($token->{tag_name} eq 'tr' and          if ($token->{tag_name} eq 'tr' and
3446                  $self->{insertion_mode} == IN_ROW_IM) {              ($self->{insertion_mode} & IM_MASK) == IN_ROW_IM) {
3447                ## have an element in table scope            ## have an element in table scope
3448                my $i;                my $i;
3449                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
3450                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
# Line 3439  sub _tree_construction_main ($) { Line 3483  sub _tree_construction_main ($) {
3483                !!!nack ('t231.1');                !!!nack ('t231.1');
3484                next B;                next B;
3485              } elsif ($token->{tag_name} eq 'table') {              } elsif ($token->{tag_name} eq 'table') {
3486                if ($self->{insertion_mode} == IN_ROW_IM) {                if (($self->{insertion_mode} & IM_MASK) == IN_ROW_IM) {
3487                  ## As if </tr>                  ## As if </tr>
3488                  ## have an element in table scope                  ## have an element in table scope
3489                  my $i;                  my $i;
# Line 3478  sub _tree_construction_main ($) { Line 3522  sub _tree_construction_main ($) {
3522                  ## reprocess in the "in table body" insertion mode...                  ## reprocess in the "in table body" insertion mode...
3523                }                }
3524    
3525                if ($self->{insertion_mode} == IN_TABLE_BODY_IM) {                if (($self->{insertion_mode} & IM_MASK) == IN_TABLE_BODY_IM) {
3526                  ## have an element in table scope                  ## have an element in table scope
3527                  my $i;                  my $i;
3528                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
# Line 3560  sub _tree_construction_main ($) { Line 3604  sub _tree_construction_main ($) {
3604                        tbody => 1, tfoot => 1, thead => 1,                        tbody => 1, tfoot => 1, thead => 1,
3605                       }->{$token->{tag_name}} and                       }->{$token->{tag_name}} and
3606                       $self->{insertion_mode} & ROW_IMS) {                       $self->{insertion_mode} & ROW_IMS) {
3607                if ($self->{insertion_mode} == IN_ROW_IM) {                if (($self->{insertion_mode} & IM_MASK) == IN_ROW_IM) {
3608                  ## have an element in table scope                  ## have an element in table scope
3609                  my $i;                  my $i;
3610                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
# Line 3694  sub _tree_construction_main ($) { Line 3738  sub _tree_construction_main ($) {
3738        } else {        } else {
3739          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
3740        }        }
3741      } elsif ($self->{insertion_mode} == IN_COLUMN_GROUP_IM) {      } elsif (($self->{insertion_mode} & IM_MASK) == IN_COLUMN_GROUP_IM) {
3742            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
3743              if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {              if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
3744                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
# Line 3824  sub _tree_construction_main ($) { Line 3868  sub _tree_construction_main ($) {
3868            !!!next-token;            !!!next-token;
3869            next B;            next B;
3870          } elsif ({          } elsif ({
3871                     select => 1, input => 1, textarea => 1,                     select => 1, input => 1, textarea => 1, keygen => 1,
3872                   }->{$token->{tag_name}} or                   }->{$token->{tag_name}} or
3873                   ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and                   (($self->{insertion_mode} & IM_MASK)
3874                          == IN_SELECT_IN_TABLE_IM and
3875                    {                    {
3876                     caption => 1, table => 1,                     caption => 1, table => 1,
3877                     tbody => 1, tfoot => 1, thead => 1,                     tbody => 1, tfoot => 1, thead => 1,
3878                     tr => 1, td => 1, th => 1,                     tr => 1, td => 1, th => 1,
3879                    }->{$token->{tag_name}})) {                    }->{$token->{tag_name}})) {
3880            ## TODO: The type below is not good - <select> is replaced by </select>  
3881            !!!parse-error (type => 'not closed', text => 'select',            ## 1. Parse error.
3882                            token => $token);            if ($token->{tag_name} eq 'select') {
3883            ## NOTE: As if the token were </select> (<select> case) or                !!!parse-error (type => 'select in select', ## XXX: documentation
3884            ## as if there were </select> (otherwise).                                token => $token);
3885            ## have an element in table scope            } else {
3886                !!!parse-error (type => 'not closed', text => 'select',
3887                                token => $token);
3888              }
3889    
3890              ## 2./<select>-1. Unless "have an element in table scope" (select):
3891            my $i;            my $i;
3892            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
3893              my $node = $self->{open_elements}->[$_];              my $node = $self->{open_elements}->[$_];
# Line 3852  sub _tree_construction_main ($) { Line 3902  sub _tree_construction_main ($) {
3902            } # INSCOPE            } # INSCOPE
3903            unless (defined $i) {            unless (defined $i) {
3904              !!!cp ('t280');              !!!cp ('t280');
3905              !!!parse-error (type => 'unmatched end tag',              if ($token->{tag_name} eq 'select') {
3906                              text => 'select', token => $token);                ## NOTE: This error would be raised when
3907              ## Ignore the token                ## |select.innerHTML = '<select>'| is executed; in this
3908                  ## case two errors, "select in select" and "unmatched
3909                  ## end tags" are reported to the user, the latter might
3910                  ## be confusing but this is what the spec requires.
3911                  !!!parse-error (type => 'unmatched end tag',
3912                                  text => 'select',
3913                                  token => $token);
3914                }
3915                ## Ignore the token.
3916              !!!nack ('t280.1');              !!!nack ('t280.1');
3917              !!!next-token;              !!!next-token;
3918              next B;              next B;
3919            }            }
3920    
3921              ## 3. Otherwise, as if there were <select>:
3922                                
3923            !!!cp ('t281');            !!!cp ('t281');
3924            splice @{$self->{open_elements}}, $i;            splice @{$self->{open_elements}}, $i;
# Line 3875  sub _tree_construction_main ($) { Line 3935  sub _tree_construction_main ($) {
3935              ## Reprocess the token.              ## Reprocess the token.
3936              next B;              next B;
3937            }            }
3938            } elsif ($token->{tag_name} eq 'script') {
3939              !!!cp ('t281.3');
3940              ## NOTE: This is an "as if in head" code clone
3941              $script_start_tag->();
3942              next B;
3943          } else {          } else {
3944            !!!cp ('t282');            !!!cp ('t282');
3945            !!!parse-error (type => 'in select',            !!!parse-error (type => 'in select',
# Line 3948  sub _tree_construction_main ($) { Line 4013  sub _tree_construction_main ($) {
4013            !!!nack ('t291.1');            !!!nack ('t291.1');
4014            !!!next-token;            !!!next-token;
4015            next B;            next B;
4016          } elsif ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and          } elsif (($self->{insertion_mode} & IM_MASK)
4017                         == IN_SELECT_IN_TABLE_IM and
4018                   {                   {
4019                    caption => 1, table => 1, tbody => 1,                    caption => 1, table => 1, tbody => 1,
4020                    tfoot => 1, thead => 1, tr => 1, td => 1, th => 1,                    tfoot => 1, thead => 1, tr => 1, td => 1, th => 1,
# Line 4285  sub _tree_construction_main ($) { Line 4351  sub _tree_construction_main ($) {
4351          $parse_rcdata->(CDATA_CONTENT_MODEL);          $parse_rcdata->(CDATA_CONTENT_MODEL);
4352          next B;          next B;
4353        } elsif ({        } elsif ({
4354                  base => 1, command => 1, eventsource => 1, link => 1,                  base => 1, command => 1, link => 1,
4355                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
4356          !!!cp ('t334');          !!!cp ('t334');
4357          ## 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
# Line 4393  sub _tree_construction_main ($) { Line 4459  sub _tree_construction_main ($) {
4459                  table => 1,                  table => 1,
4460                  hr => 1,                  hr => 1,
4461                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
4462    
4463            ## 1. When there is an opening |form| element:
4464          if ($token->{tag_name} eq 'form' and defined $self->{form_element}) {          if ($token->{tag_name} eq 'form' and defined $self->{form_element}) {
4465            !!!cp ('t350');            !!!cp ('t350');
4466            !!!parse-error (type => 'in form:form', token => $token);            !!!parse-error (type => 'in form:form', token => $token);
# Line 4402  sub _tree_construction_main ($) { Line 4470  sub _tree_construction_main ($) {
4470            next B;            next B;
4471          }          }
4472    
4473          ## has a p element in scope          ## 2. Close the |p| element, if any.
4474          INSCOPE: for (reverse @{$self->{open_elements}}) {          if ($token->{tag_name} ne 'table' or # The Hixie Quirk
4475            if ($_->[1] == P_EL) {              $self->{document}->manakai_compat_mode ne 'quirks') {
4476              !!!cp ('t344');            ## has a p element in scope
4477              !!!back-token; # <form>            INSCOPE: for (reverse @{$self->{open_elements}}) {
4478              $token = {type => END_TAG_TOKEN, tag_name => 'p',              if ($_->[1] == P_EL) {
4479                        line => $token->{line}, column => $token->{column}};                !!!cp ('t344');
4480              next B;                !!!back-token; # <form>
4481            } elsif ($_->[1] & SCOPING_EL) {                $token = {type => END_TAG_TOKEN, tag_name => 'p',
4482              !!!cp ('t345');                          line => $token->{line}, column => $token->{column}};
4483              last INSCOPE;                next B;
4484                } elsif ($_->[1] & SCOPING_EL) {
4485                  !!!cp ('t345');
4486                  last INSCOPE;
4487                }
4488              } # INSCOPE
4489            }
4490    
4491            ## 3. Close the opening <hn> element, if any.
4492            if ({h1 => 1, h2 => 1, h3 => 1,
4493                 h4 => 1, h5 => 1, h6 => 1}->{$token->{tag_name}}) {
4494              if ($self->{open_elements}->[-1]->[1] == HEADING_EL) {
4495                !!!parse-error (type => 'not closed',
4496                                text => $self->{open_elements}->[-1]->[0]->manakai_local_name,
4497                                token => $token);
4498                pop @{$self->{open_elements}};
4499            }            }
4500          } # INSCOPE          }
4501              
4502            ## 4. Insertion.
4503          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
4504          if ($token->{tag_name} eq 'pre' or $token->{tag_name} eq 'listing') {          if ($token->{tag_name} eq 'pre' or $token->{tag_name} eq 'listing') {
4505            !!!nack ('t346.1');            !!!nack ('t346.1');
# Line 4459  sub _tree_construction_main ($) { Line 4543  sub _tree_construction_main ($) {
4543        } elsif ($token->{tag_name} eq 'li') {        } elsif ($token->{tag_name} eq 'li') {
4544          ## NOTE: As normal, but imply </li> when there's another <li> ...          ## NOTE: As normal, but imply </li> when there's another <li> ...
4545    
4546          ## NOTE: Special, Scope (<li><foo><li> == <li><foo><li/></foo></li>)          ## NOTE: Special, Scope (<li><foo><li> == <li><foo><li/></foo></li>)::
4547            ## Interpreted as <li><foo/></li><li/> (non-conforming)            ## Interpreted as <li><foo/></li><li/> (non-conforming):
4548            ## blockquote (O9.27), center (O), dd (Fx3, O, S3.1.2, IE7),            ## blockquote (O9.27), center (O), dd (Fx3, O, S3.1.2, IE7),
4549            ## dt (Fx, O, S, IE), dl (O), fieldset (O, S, IE), form (Fx, O, S),            ## dt (Fx, O, S, IE), dl (O), fieldset (O, S, IE), form (Fx, O, S),
4550            ## hn (O), pre (O), applet (O, S), button (O, S), marquee (Fx, O, S),            ## hn (O), pre (O), applet (O, S), button (O, S), marquee (Fx, O, S),
4551            ## object (Fx)            ## object (Fx)
4552            ## Generate non-tree (non-conforming)            ## Generate non-tree (non-conforming):
4553            ## basefont (IE7 (where basefont is non-void)), center (IE),            ## basefont (IE7 (where basefont is non-void)), center (IE),
4554            ## form (IE), hn (IE)            ## form (IE), hn (IE)
4555          ## address, div, p (<li><foo><li> == <li><foo/></li><li/>)          ## address, div, p (<li><foo><li> == <li><foo/></li><li/>)::
4556            ## Interpreted as <li><foo><li/></foo></li> (non-conforming)            ## Interpreted as <li><foo><li/></foo></li> (non-conforming):
4557            ## div (Fx, S)            ## div (Fx, S)
4558    
4559          my $non_optional;          my $non_optional;
# Line 4785  sub _tree_construction_main ($) { Line 4869  sub _tree_construction_main ($) {
4869                           line => $token->{line}, column => $token->{column}},                           line => $token->{line}, column => $token->{column}},
4870                          {type => START_TAG_TOKEN, tag_name => 'hr',                          {type => START_TAG_TOKEN, tag_name => 'hr',
4871                           line => $token->{line}, column => $token->{column}},                           line => $token->{line}, column => $token->{column}},
                         {type => START_TAG_TOKEN, tag_name => 'p',  
                          line => $token->{line}, column => $token->{column}},  
4872                          {type => START_TAG_TOKEN, tag_name => 'label',                          {type => START_TAG_TOKEN, tag_name => 'label',
4873                           line => $token->{line}, column => $token->{column}},                           line => $token->{line}, column => $token->{column}},
4874                         );                         );
# Line 4809  sub _tree_construction_main ($) { Line 4891  sub _tree_construction_main ($) {
4891                          #{type => CHARACTER_TOKEN, data => ''}, # SHOULD                          #{type => CHARACTER_TOKEN, data => ''}, # SHOULD
4892                          {type => END_TAG_TOKEN, tag_name => 'label',                          {type => END_TAG_TOKEN, tag_name => 'label',
4893                           line => $token->{line}, column => $token->{column}},                           line => $token->{line}, column => $token->{column}},
                         {type => END_TAG_TOKEN, tag_name => 'p',  
                          line => $token->{line}, column => $token->{column}},  
4894                          {type => START_TAG_TOKEN, tag_name => 'hr',                          {type => START_TAG_TOKEN, tag_name => 'hr',
4895                           line => $token->{line}, column => $token->{column}},                           line => $token->{line}, column => $token->{column}},
4896                          {type => END_TAG_TOKEN, tag_name => 'form',                          {type => END_TAG_TOKEN, tag_name => 'form',
# Line 4820  sub _tree_construction_main ($) { Line 4900  sub _tree_construction_main ($) {
4900            next B;            next B;
4901          }          }
4902        } elsif ($token->{tag_name} eq 'textarea') {        } elsif ($token->{tag_name} eq 'textarea') {
4903          ## Step 1          ## 1. Insert
4904          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
4905                    
4906          ## Step 2          ## Step 2 # XXX
4907          ## TODO: $self->{form_element} if defined          ## TODO: $self->{form_element} if defined
4908    
4909          ## Step 3          ## 2. Drop U+000A LINE FEED
4910          $self->{ignore_newline} = 1;          $self->{ignore_newline} = 1;
4911    
4912          ## Step 4          ## 3. RCDATA
         ## ISSUE: This step is wrong. (r2302 enbugged)  
   
         ## Step 5  
4913          $self->{content_model} = RCDATA_CONTENT_MODEL;          $self->{content_model} = RCDATA_CONTENT_MODEL;
4914          delete $self->{escape}; # MUST          delete $self->{escape}; # MUST
4915    
4916          ## Step 6-7          ## 4., 6. Insertion mode
4917          $self->{insertion_mode} |= IN_CDATA_RCDATA_IM;          $self->{insertion_mode} |= IN_CDATA_RCDATA_IM;
4918    
4919            ## XXX: 5. frameset-ok flag
4920    
4921          !!!nack ('t392.1');          !!!nack ('t392.1');
4922          !!!next-token;          !!!next-token;
4923          next B;          next B;
# Line 4894  sub _tree_construction_main ($) { Line 4973  sub _tree_construction_main ($) {
4973              last INSCOPE;              last INSCOPE;
4974            }            }
4975          } # INSCOPE          } # INSCOPE
4976              
4977            ## TODO: <non-ruby><rt> is not allowed.
4978    
4979          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
4980    
# Line 4982  sub _tree_construction_main ($) { Line 5063  sub _tree_construction_main ($) {
5063          } elsif ({          } elsif ({
5064                    area => 1, basefont => 1, bgsound => 1, br => 1,                    area => 1, basefont => 1, bgsound => 1, br => 1,
5065                    embed => 1, img => 1, spacer => 1, wbr => 1,                    embed => 1, img => 1, spacer => 1, wbr => 1,
5066                      keygen => 1,
5067                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
5068            !!!cp ('t388.1');            !!!cp ('t388.1');
5069            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
# Line 4991  sub _tree_construction_main ($) { Line 5073  sub _tree_construction_main ($) {
5073                    
5074            if ($self->{insertion_mode} & TABLE_IMS or            if ($self->{insertion_mode} & TABLE_IMS or
5075                $self->{insertion_mode} & BODY_TABLE_IMS or                $self->{insertion_mode} & BODY_TABLE_IMS or
5076                $self->{insertion_mode} == IN_COLUMN_GROUP_IM) {                ($self->{insertion_mode} & IM_MASK) == IN_COLUMN_GROUP_IM) {
5077              !!!cp ('t400.1');              !!!cp ('t400.1');
5078              $self->{insertion_mode} = IN_SELECT_IN_TABLE_IM;              $self->{insertion_mode} = IN_SELECT_IN_TABLE_IM;
5079            } else {            } else {
# Line 5008  sub _tree_construction_main ($) { Line 5090  sub _tree_construction_main ($) {
5090        }        }
5091      } elsif ($token->{type} == END_TAG_TOKEN) {      } elsif ($token->{type} == END_TAG_TOKEN) {
5092        if ($token->{tag_name} eq 'body') {        if ($token->{tag_name} eq 'body') {
5093          ## has a |body| element in scope  
5094            ## 1. If not "have an element in scope":
5095            ## "has a |body| element in scope"
5096          my $i;          my $i;
5097          INSCOPE: {          INSCOPE: {
5098            for (reverse @{$self->{open_elements}}) {            for (reverse @{$self->{open_elements}}) {
# Line 5031  sub _tree_construction_main ($) { Line 5115  sub _tree_construction_main ($) {
5115            next B;            next B;
5116          } # INSCOPE          } # INSCOPE
5117    
5118            ## 2. If unclosed elements:
5119          for (@{$self->{open_elements}}) {          for (@{$self->{open_elements}}) {
5120            unless ($_->[1] & ALL_END_TAG_OPTIONAL_EL) {            unless ($_->[1] & ALL_END_TAG_OPTIONAL_EL ||
5121                      $_->[1] == OPTGROUP_EL ||
5122                      $_->[1] == OPTION_EL ||
5123                      $_->[1] == RUBY_COMPONENT_EL) {
5124              !!!cp ('t403');              !!!cp ('t403');
5125              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
5126                              text => $_->[0]->manakai_local_name,                              text => $_->[0]->manakai_local_name,
# Line 5043  sub _tree_construction_main ($) { Line 5131  sub _tree_construction_main ($) {
5131            }            }
5132          }          }
5133    
5134            ## 3. Switch the insertion mode.
5135          $self->{insertion_mode} = AFTER_BODY_IM;          $self->{insertion_mode} = AFTER_BODY_IM;
5136          !!!next-token;          !!!next-token;
5137          next B;          next B;
# Line 5429  sub _tree_construction_main ($) { Line 5518  sub _tree_construction_main ($) {
5518    ## TODO: script stuffs    ## TODO: script stuffs
5519  } # _tree_construct_main  } # _tree_construct_main
5520    
5521    ## XXX: How this method is organized is somewhat out of date, although
5522    ## it still does what the current spec documents.
5523  sub set_inner_html ($$$$;$) {  sub set_inner_html ($$$$;$) {
5524    my $class = shift;    my $class = shift;
5525    my $node = shift;    my $node = shift; # /context/
5526    #my $s = \$_[0];    #my $s = \$_[0];
5527    my $onerror = $_[1];    my $onerror = $_[1];
5528    my $get_wrapper = $_[2] || sub ($) { return $_[0] };    my $get_wrapper = $_[2] || sub ($) { return $_[0] };
# Line 5439  sub set_inner_html ($$$$;$) { Line 5530  sub set_inner_html ($$$$;$) {
5530    ## ISSUE: Should {confident} be true?    ## ISSUE: Should {confident} be true?
5531    
5532    my $nt = $node->node_type;    my $nt = $node->node_type;
5533    if ($nt == 9) {    if ($nt == 9) { # Document (invoke the algorithm with no /context/ element)
5534      # MUST      # MUST
5535            
5536      ## Step 1 # MUST      ## Step 1 # MUST
# Line 5454  sub set_inner_html ($$$$;$) { Line 5545  sub set_inner_html ($$$$;$) {
5545    
5546      ## Step 3, 4, 5 # MUST      ## Step 3, 4, 5 # MUST
5547      $class->parse_char_string ($_[0] => $node, $onerror, $get_wrapper);      $class->parse_char_string ($_[0] => $node, $onerror, $get_wrapper);
5548    } elsif ($nt == 1) {    } elsif ($nt == 1) { # Element (invoke the algorithm with /context/ element)
5549      ## TODO: If non-html element      ## TODO: If non-html element
5550    
5551      ## NOTE: Most of this code is copied from |parse_string|      ## NOTE: Most of this code is copied from |parse_string|
5552    
5553  ## TODO: Support for $get_wrapper  ## TODO: Support for $get_wrapper
5554    
5555      ## Step 1 # MUST      ## F1. Create an HTML document.
5556      my $this_doc = $node->owner_document;      my $this_doc = $node->owner_document;
5557      my $doc = $this_doc->implementation->create_document;      my $doc = $this_doc->implementation->create_document;
5558      $doc->manakai_is_html (1);      $doc->manakai_is_html (1);
5559    
5560        ## F2. Propagate quirkness flag
5561        my $node_doc = $node->owner_document;
5562        $doc->manakai_compat_mode ($node_doc->manakai_compat_mode);
5563    
5564        ## F3. Create an HTML parser
5565      my $p = $class->new;      my $p = $class->new;
5566      $p->{document} = $doc;      $p->{document} = $doc;
5567    
# Line 5592  sub set_inner_html ($$$$;$) { Line 5689  sub set_inner_html ($$$$;$) {
5689      $p->_initialize_tokenizer;      $p->_initialize_tokenizer;
5690      $p->_initialize_tree_constructor;      $p->_initialize_tree_constructor;
5691    
5692      ## Step 2      ## F4. If /context/ is not undef...
5693    
5694        ## F4.1. content model flag
5695      my $node_ln = $node->manakai_local_name;      my $node_ln = $node->manakai_local_name;
5696      $p->{content_model} = {      $p->{content_model} = {
5697        title => RCDATA_CONTENT_MODEL,        title => RCDATA_CONTENT_MODEL,
# Line 5608  sub set_inner_html ($$$$;$) { Line 5707  sub set_inner_html ($$$$;$) {
5707      }->{$node_ln};      }->{$node_ln};
5708      $p->{content_model} = PCDATA_CONTENT_MODEL      $p->{content_model} = PCDATA_CONTENT_MODEL
5709          unless defined $p->{content_model};          unless defined $p->{content_model};
         ## ISSUE: What is "the name of the element"? local name?  
5710    
5711      $p->{inner_html_node} = [$node, $el_category->{$node_ln}];      $p->{inner_html_node} = [$node, $el_category->{$node_ln}];
5712        ## TODO: Foreign element OK?        ## TODO: Foreign element OK?
5713    
5714      ## Step 3      ## F4.2. Root |html| element
5715      my $root = $doc->create_element_ns      my $root = $doc->create_element_ns
5716        ('http://www.w3.org/1999/xhtml', [undef, 'html']);        ('http://www.w3.org/1999/xhtml', [undef, 'html']);
5717    
5718      ## Step 4 # MUST      ## F4.3.
5719      $doc->append_child ($root);      $doc->append_child ($root);
5720    
5721      ## Step 5 # MUST      ## F4.4.
5722      push @{$p->{open_elements}}, [$root, $el_category->{html}];      push @{$p->{open_elements}}, [$root, $el_category->{html}];
5723    
5724      undef $p->{head_element};      undef $p->{head_element};
5725      undef $p->{head_element_inserted};      undef $p->{head_element_inserted};
5726    
5727      ## Step 6 # MUST      ## F4.5.
5728      $p->_reset_insertion_mode;      $p->_reset_insertion_mode;
5729    
5730      ## Step 7 # MUST      ## F4.6.
5731      my $anode = $node;      my $anode = $node;
5732      AN: while (defined $anode) {      AN: while (defined $anode) {
5733        if ($anode->node_type == 1) {        if ($anode->node_type == 1) {
# Line 5644  sub set_inner_html ($$$$;$) { Line 5742  sub set_inner_html ($$$$;$) {
5742        }        }
5743        $anode = $anode->parent_node;        $anode = $anode->parent_node;
5744      } # AN      } # AN
5745        
5746      ## Step 9 # MUST      ## F.6. Start the parser.
5747      {      {
5748        my $self = $p;        my $self = $p;
5749        !!!next-token;        !!!next-token;
5750      }      }
5751      $p->_tree_construction_main;      $p->_tree_construction_main;
5752    
5753      ## Step 10 # MUST      ## F.7.
5754      my @cn = @{$node->child_nodes};      my @cn = @{$node->child_nodes};
5755      for (@cn) {      for (@cn) {
5756        $node->remove_child ($_);        $node->remove_child ($_);

Legend:
Removed from v.1.208  
changed lines
  Added in v.1.232

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24