/[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.185 by wakaba, Mon Sep 15 09:27:53 2008 UTC revision 1.204 by wakaba, Sun Oct 5 05:59:35 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 966  sub _initialize_tokenizer ($) { Line 995  sub _initialize_tokenizer ($) {
995  ## TODO: Polytheistic slash SHOULD NOT be used. (Applied only to atheists.)  ## TODO: Polytheistic slash SHOULD NOT be used. (Applied only to atheists.)
996  ## (This requirement was dropped from HTML5 spec, unfortunately.)  ## (This requirement was dropped from HTML5 spec, unfortunately.)
997    
998    my $is_space = {
999      0x0009 => 1, # CHARACTER TABULATION (HT)
1000      0x000A => 1, # LINE FEED (LF)
1001      #0x000B => 0, # LINE TABULATION (VT)
1002      0x000C => 1, # FORM FEED (FF)
1003      #0x000D => 1, # CARRIAGE RETURN (CR)
1004      0x0020 => 1, # SPACE (SP)
1005    };
1006    
1007  sub _get_next_token ($) {  sub _get_next_token ($) {
1008    my $self = shift;    my $self = shift;
1009    
# Line 1336  sub _get_next_token ($) { Line 1374  sub _get_next_token ($) {
1374            redo A;            redo A;
1375          }          }
1376        } else { # after "<{tag-name}"        } else { # after "<{tag-name}"
1377          unless ({          unless ($is_space->{$self->{nc}} or
1378                   0x0009 => 1, # HT                  {
                  0x000A => 1, # LF  
                  0x000B => 1, # VT  
                  0x000C => 1, # FF  
                  0x0020 => 1, # SP  
1379                   0x003E => 1, # >                   0x003E => 1, # >
1380                   0x002F => 1, # /                   0x002F => 1, # /
1381                   -1 => 1, # EOF                   -1 => 1, # EOF
# Line 1368  sub _get_next_token ($) { Line 1402  sub _get_next_token ($) {
1402          }          }
1403        }        }
1404      } elsif ($self->{state} == TAG_NAME_STATE) {      } elsif ($self->{state} == TAG_NAME_STATE) {
1405        if ($self->{nc} == 0x0009 or # HT        if ($is_space->{$self->{nc}}) {
           $self->{nc} == 0x000A or # LF  
           $self->{nc} == 0x000B or # VT  
           $self->{nc} == 0x000C or # FF  
           $self->{nc} == 0x0020) { # SP  
1406          !!!cp (34);          !!!cp (34);
1407          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;
1408          !!!next-input-character;          !!!next-input-character;
# Line 1444  sub _get_next_token ($) { Line 1474  sub _get_next_token ($) {
1474          redo A;          redo A;
1475        }        }
1476      } elsif ($self->{state} == BEFORE_ATTRIBUTE_NAME_STATE) {      } elsif ($self->{state} == BEFORE_ATTRIBUTE_NAME_STATE) {
1477        if ($self->{nc} == 0x0009 or # HT        if ($is_space->{$self->{nc}}) {
           $self->{nc} == 0x000A or # LF  
           $self->{nc} == 0x000B or # VT  
           $self->{nc} == 0x000C or # FF  
           $self->{nc} == 0x0020) { # SP  
1478          !!!cp (45);          !!!cp (45);
1479          ## Stay in the state          ## Stay in the state
1480          !!!next-input-character;          !!!next-input-character;
# Line 1544  sub _get_next_token ($) { Line 1570  sub _get_next_token ($) {
1570          }          }
1571        }; # $before_leave        }; # $before_leave
1572    
1573        if ($self->{nc} == 0x0009 or # HT        if ($is_space->{$self->{nc}}) {
           $self->{nc} == 0x000A or # LF  
           $self->{nc} == 0x000B or # VT  
           $self->{nc} == 0x000C or # FF  
           $self->{nc} == 0x0020) { # SP  
1574          !!!cp (59);          !!!cp (59);
1575          $before_leave->();          $before_leave->();
1576          $self->{state} = AFTER_ATTRIBUTE_NAME_STATE;          $self->{state} = AFTER_ATTRIBUTE_NAME_STATE;
# Line 1631  sub _get_next_token ($) { Line 1653  sub _get_next_token ($) {
1653          redo A;          redo A;
1654        }        }
1655      } elsif ($self->{state} == AFTER_ATTRIBUTE_NAME_STATE) {      } elsif ($self->{state} == AFTER_ATTRIBUTE_NAME_STATE) {
1656        if ($self->{nc} == 0x0009 or # HT        if ($is_space->{$self->{nc}}) {
           $self->{nc} == 0x000A or # LF  
           $self->{nc} == 0x000B or # VT  
           $self->{nc} == 0x000C or # FF  
           $self->{nc} == 0x0020) { # SP  
1657          !!!cp (71);          !!!cp (71);
1658          ## Stay in the state          ## Stay in the state
1659          !!!next-input-character;          !!!next-input-character;
# Line 1722  sub _get_next_token ($) { Line 1740  sub _get_next_token ($) {
1740          redo A;                  redo A;        
1741        }        }
1742      } elsif ($self->{state} == BEFORE_ATTRIBUTE_VALUE_STATE) {      } elsif ($self->{state} == BEFORE_ATTRIBUTE_VALUE_STATE) {
1743        if ($self->{nc} == 0x0009 or # HT        if ($is_space->{$self->{nc}}) {
           $self->{nc} == 0x000A or # LF  
           $self->{nc} == 0x000B or # VT  
           $self->{nc} == 0x000C or # FF  
           $self->{nc} == 0x0020) { # SP        
1744          !!!cp (83);          !!!cp (83);
1745          ## Stay in the state          ## Stay in the state
1746          !!!next-input-character;          !!!next-input-character;
# Line 1907  sub _get_next_token ($) { Line 1921  sub _get_next_token ($) {
1921          redo A;          redo A;
1922        }        }
1923      } elsif ($self->{state} == ATTRIBUTE_VALUE_UNQUOTED_STATE) {      } elsif ($self->{state} == ATTRIBUTE_VALUE_UNQUOTED_STATE) {
1924        if ($self->{nc} == 0x0009 or # HT        if ($is_space->{$self->{nc}}) {
           $self->{nc} == 0x000A or # LF  
           $self->{nc} == 0x000B or # HT  
           $self->{nc} == 0x000C or # FF  
           $self->{nc} == 0x0020) { # SP  
1925          !!!cp (107);          !!!cp (107);
1926          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;
1927          !!!next-input-character;          !!!next-input-character;
# Line 1993  sub _get_next_token ($) { Line 2003  sub _get_next_token ($) {
2003          redo A;          redo A;
2004        }        }
2005      } elsif ($self->{state} == AFTER_ATTRIBUTE_VALUE_QUOTED_STATE) {      } elsif ($self->{state} == AFTER_ATTRIBUTE_VALUE_QUOTED_STATE) {
2006        if ($self->{nc} == 0x0009 or # HT        if ($is_space->{$self->{nc}}) {
           $self->{nc} == 0x000A or # LF  
           $self->{nc} == 0x000B or # VT  
           $self->{nc} == 0x000C or # FF  
           $self->{nc} == 0x0020) { # SP  
2007          !!!cp (118);          !!!cp (118);
2008          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;
2009          !!!next-input-character;          !!!next-input-character;
# Line 2438  sub _get_next_token ($) { Line 2444  sub _get_next_token ($) {
2444          redo A;          redo A;
2445        }        }
2446      } elsif ($self->{state} == DOCTYPE_STATE) {      } elsif ($self->{state} == DOCTYPE_STATE) {
2447        if ($self->{nc} == 0x0009 or # HT        if ($is_space->{$self->{nc}}) {
           $self->{nc} == 0x000A or # LF  
           $self->{nc} == 0x000B or # VT  
           $self->{nc} == 0x000C or # FF  
           $self->{nc} == 0x0020) { # SP  
2448          !!!cp (155);          !!!cp (155);
2449          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
2450          !!!next-input-character;          !!!next-input-character;
# Line 2455  sub _get_next_token ($) { Line 2457  sub _get_next_token ($) {
2457          redo A;          redo A;
2458        }        }
2459      } elsif ($self->{state} == BEFORE_DOCTYPE_NAME_STATE) {      } elsif ($self->{state} == BEFORE_DOCTYPE_NAME_STATE) {
2460        if ($self->{nc} == 0x0009 or # HT        if ($is_space->{$self->{nc}}) {
           $self->{nc} == 0x000A or # LF  
           $self->{nc} == 0x000B or # VT  
           $self->{nc} == 0x000C or # FF  
           $self->{nc} == 0x0020) { # SP  
2461          !!!cp (157);          !!!cp (157);
2462          ## Stay in the state          ## Stay in the state
2463          !!!next-input-character;          !!!next-input-character;
# Line 2486  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;
2490        }        }
2491      } elsif ($self->{state} == DOCTYPE_NAME_STATE) {      } elsif ($self->{state} == DOCTYPE_NAME_STATE) {
2492  ## ISSUE: Redundant "First," in the spec.  ## ISSUE: Redundant "First," in the spec.
2493        if ($self->{nc} == 0x0009 or # HT        if ($is_space->{$self->{nc}}) {
           $self->{nc} == 0x000A or # LF  
           $self->{nc} == 0x000B or # VT  
           $self->{nc} == 0x000C or # FF  
           $self->{nc} == 0x0020) { # SP  
2494          !!!cp (161);          !!!cp (161);
2495          $self->{state} = AFTER_DOCTYPE_NAME_STATE;          $self->{state} = AFTER_DOCTYPE_NAME_STATE;
2496          !!!next-input-character;          !!!next-input-character;
# Line 2529  sub _get_next_token ($) { Line 2522  sub _get_next_token ($) {
2522          redo A;          redo A;
2523        }        }
2524      } elsif ($self->{state} == AFTER_DOCTYPE_NAME_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_NAME_STATE) {
2525        if ($self->{nc} == 0x0009 or # HT        if ($is_space->{$self->{nc}}) {
           $self->{nc} == 0x000A or # LF  
           $self->{nc} == 0x000B or # VT  
           $self->{nc} == 0x000C or # FF  
           $self->{nc} == 0x0020) { # SP  
2526          !!!cp (165);          !!!cp (165);
2527          ## Stay in the state          ## Stay in the state
2528          !!!next-input-character;          !!!next-input-character;
# Line 2656  sub _get_next_token ($) { Line 2645  sub _get_next_token ($) {
2645          redo A;          redo A;
2646        }        }
2647      } elsif ($self->{state} == BEFORE_DOCTYPE_PUBLIC_IDENTIFIER_STATE) {      } elsif ($self->{state} == BEFORE_DOCTYPE_PUBLIC_IDENTIFIER_STATE) {
2648        if ({        if ($is_space->{$self->{nc}}) {
             0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, 0x0020 => 1,  
             #0x000D => 1, # HT, LF, VT, FF, SP, CR  
           }->{$self->{nc}}) {  
2649          !!!cp (181);          !!!cp (181);
2650          ## Stay in the state          ## Stay in the state
2651          !!!next-input-character;          !!!next-input-character;
# Line 2786  sub _get_next_token ($) { Line 2772  sub _get_next_token ($) {
2772          redo A;          redo A;
2773        }        }
2774      } elsif ($self->{state} == AFTER_DOCTYPE_PUBLIC_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_PUBLIC_IDENTIFIER_STATE) {
2775        if ({        if ($is_space->{$self->{nc}}) {
             0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, 0x0020 => 1,  
             #0x000D => 1, # HT, LF, VT, FF, SP, CR  
           }->{$self->{nc}}) {  
2776          !!!cp (195);          !!!cp (195);
2777          ## Stay in the state          ## Stay in the state
2778          !!!next-input-character;          !!!next-input-character;
# Line 2835  sub _get_next_token ($) { Line 2818  sub _get_next_token ($) {
2818          redo A;          redo A;
2819        }        }
2820      } elsif ($self->{state} == BEFORE_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == BEFORE_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
2821        if ({        if ($is_space->{$self->{nc}}) {
             0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, 0x0020 => 1,  
             #0x000D => 1, # HT, LF, VT, FF, SP, CR  
           }->{$self->{nc}}) {  
2822          !!!cp (201);          !!!cp (201);
2823          ## Stay in the state          ## Stay in the state
2824          !!!next-input-character;          !!!next-input-character;
# Line 2964  sub _get_next_token ($) { Line 2944  sub _get_next_token ($) {
2944          redo A;          redo A;
2945        }        }
2946      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
2947        if ({        if ($is_space->{$self->{nc}}) {
             0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, 0x0020 => 1,  
             #0x000D => 1, # HT, LF, VT, FF, SP, CR  
           }->{$self->{nc}}) {  
2948          !!!cp (215);          !!!cp (215);
2949          ## Stay in the state          ## Stay in the state
2950          !!!next-input-character;          !!!next-input-character;
# Line 3010  sub _get_next_token ($) { Line 2987  sub _get_next_token ($) {
2987          redo A;          redo A;
2988        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2989          !!!cp (220);          !!!cp (220);
         !!!parse-error (type => 'unclosed DOCTYPE');  
2990          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2991          ## reconsume          ## reconsume
2992    
# Line 3099  sub _get_next_token ($) { Line 3075  sub _get_next_token ($) {
3075          redo A;          redo A;
3076        }        }
3077      } elsif ($self->{state} == ENTITY_STATE) {      } elsif ($self->{state} == ENTITY_STATE) {
3078        if ({        if ($is_space->{$self->{nc}} or
3079          0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, # HT, LF, VT, FF,            {
3080          0x0020 => 1, 0x003C => 1, 0x0026 => 1, -1 => 1, # SP, <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
3081          $self->{entity_add} => 1,              $self->{entity_add} => 1,
3082        }->{$self->{nc}}) {            }->{$self->{nc}}) {
3083          !!!cp (1001);          !!!cp (1001);
3084          ## Don't consume          ## Don't consume
3085          ## No error          ## No error
# Line 3222  sub _get_next_token ($) { Line 3198  sub _get_next_token ($) {
3198        my $code = $self->{s_kwd};        my $code = $self->{s_kwd};
3199        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3200        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3201        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {        if ($charref_map->{$code}) {
3202          !!!cp (1015);          !!!cp (1015);
3203          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3204                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
3205                          line => $l, column => $c);                          line => $l, column => $c);
3206          $code = 0xFFFD;          $code = $charref_map->{$code};
3207        } elsif ($code > 0x10FFFF) {        } elsif ($code > 0x10FFFF) {
3208          !!!cp (1016);          !!!cp (1016);
3209          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3210                          text => (sprintf 'U-%08X', $code),                          text => (sprintf 'U-%08X', $code),
3211                          line => $l, column => $c);                          line => $l, column => $c);
3212          $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};  
3213        }        }
3214    
3215        if ($self->{prev_state} == DATA_STATE) {        if ($self->{prev_state} == DATA_STATE) {
# Line 3341  sub _get_next_token ($) { Line 3306  sub _get_next_token ($) {
3306        my $code = $self->{s_kwd};        my $code = $self->{s_kwd};
3307        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3308        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3309        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {        if ($charref_map->{$code}) {
3310          !!!cp (1008);          !!!cp (1008);
3311          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3312                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
3313                          line => $l, column => $c);                          line => $l, column => $c);
3314          $code = 0xFFFD;          $code = $charref_map->{$code};
3315        } elsif ($code > 0x10FFFF) {        } elsif ($code > 0x10FFFF) {
3316          !!!cp (1009);          !!!cp (1009);
3317          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3318                          text => (sprintf 'U-%08X', $code),                          text => (sprintf 'U-%08X', $code),
3319                          line => $l, column => $c);                          line => $l, column => $c);
3320          $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};  
3321        }        }
3322    
3323        if ($self->{prev_state} == DATA_STATE) {        if ($self->{prev_state} == DATA_STATE) {
# Line 3509  sub _construct_tree ($) { Line 3466  sub _construct_tree ($) {
3466    ## When an interactive UA render the $self->{document} available    ## When an interactive UA render the $self->{document} available
3467    ## to the user, or when it begin accepting user input, are    ## to the user, or when it begin accepting user input, are
3468    ## not defined.    ## not defined.
   
   ## Append a character: collect it and all subsequent consecutive  
   ## characters and insert one Text node whose data is concatenation  
   ## of all those characters. # MUST  
3469        
3470    !!!next-token;    !!!next-token;
3471    
3472    undef $self->{form_element};    undef $self->{form_element};
3473    undef $self->{head_element};    undef $self->{head_element};
3474      undef $self->{head_element_inserted};
3475    $self->{open_elements} = [];    $self->{open_elements} = [];
3476    undef $self->{inner_html_node};    undef $self->{inner_html_node};
3477    
# Line 3701  sub _tree_construction_initial ($) { Line 3655  sub _tree_construction_initial ($) {
3655        !!!ack-later;        !!!ack-later;
3656        return;        return;
3657      } elsif ($token->{type} == CHARACTER_TOKEN) {      } elsif ($token->{type} == CHARACTER_TOKEN) {
3658        if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { # \x0D        if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
3659          ## Ignore the token          ## Ignore the token
3660    
3661          unless (length $token->{data}) {          unless (length $token->{data}) {
# Line 3758  sub _tree_construction_root_element ($) Line 3712  sub _tree_construction_root_element ($)
3712          !!!next-token;          !!!next-token;
3713          redo B;          redo B;
3714        } elsif ($token->{type} == CHARACTER_TOKEN) {        } elsif ($token->{type} == CHARACTER_TOKEN) {
3715          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { # \x0D          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
3716            ## Ignore the token.            ## Ignore the token.
3717    
3718            unless (length $token->{data}) {            unless (length $token->{data}) {
# Line 3825  sub _tree_construction_root_element ($) Line 3779  sub _tree_construction_root_element ($)
3779      ## NOTE: Reprocess the token.      ## NOTE: Reprocess the token.
3780      !!!ack-later;      !!!ack-later;
3781      return; ## Go to the "before head" insertion mode.      return; ## Go to the "before head" insertion mode.
   
     ## ISSUE: There is an issue in the spec  
3782    } # B    } # B
3783    
3784    die "$0: _tree_construction_root_element: This should never be reached";    die "$0: _tree_construction_root_element: This should never be reached";
# Line 4127  sub _tree_construction_main ($) { Line 4079  sub _tree_construction_main ($) {
4079    
4080    ## NOTE: $open_tables->[-1]->[0] is the "current table" element node.    ## NOTE: $open_tables->[-1]->[0] is the "current table" element node.
4081    ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag.    ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag.
4082      ## NOTE: $open_tables->[-1]->[2] is set false when non-Text node inserted.
4083    my $open_tables = [[$self->{open_elements}->[0]->[0]]];    my $open_tables = [[$self->{open_elements}->[0]->[0]]];
4084    
4085    my $formatting_end_tag = sub {    my $formatting_end_tag = sub {
# Line 4211  sub _tree_construction_main ($) { Line 4164  sub _tree_construction_main ($) {
4164            !!!cp ('t59');            !!!cp ('t59');
4165            $furthest_block = $node;            $furthest_block = $node;
4166            $furthest_block_i_in_open = $_;            $furthest_block_i_in_open = $_;
4167              ## NOTE: The topmost (eldest) node.
4168          } elsif ($node->[0] eq $formatting_element->[0]) {          } elsif ($node->[0] eq $formatting_element->[0]) {
4169            !!!cp ('t60');            !!!cp ('t60');
4170            last OE;            last OE;
# Line 4357  sub _tree_construction_main ($) { Line 4311  sub _tree_construction_main ($) {
4311            $i = $_;            $i = $_;
4312          }          }
4313        } # OE        } # OE
4314        splice @{$self->{open_elements}}, $i + 1, 1, $clone;        splice @{$self->{open_elements}}, $i + 1, 0, $clone;
4315                
4316        ## Step 14        ## Step 14
4317        redo FET;        redo FET;
# Line 4400  sub _tree_construction_main ($) { Line 4354  sub _tree_construction_main ($) {
4354      }      }
4355    }; # $insert_to_foster    }; # $insert_to_foster
4356    
4357      ## NOTE: Insert a character (MUST): When a character is inserted, if
4358      ## the last node that was inserted by the parser is a Text node and
4359      ## the character has to be inserted after that node, then the
4360      ## character is appended to the Text node.  However, if any other
4361      ## node is inserted by the parser, then a new Text node is created
4362      ## and the character is appended as that Text node.  If I'm not
4363      ## wrong, for a parser with scripting disabled, there are only two
4364      ## cases where this occurs.  One is the case where an element node
4365      ## is inserted to the |head| element.  This is covered by using the
4366      ## |$self->{head_element_inserted}| flag.  Another is the case where
4367      ## an element or comment is inserted into the |table| subtree while
4368      ## foster parenting happens.  This is covered by using the [2] flag
4369      ## of the |$open_tables| structure.  All other cases are handled
4370      ## simply by calling |manakai_append_text| method.
4371    
4372      ## TODO: |<body><script>document.write("a<br>");
4373      ## document.body.removeChild (document.body.lastChild);
4374      ## document.write ("b")</script>|
4375    
4376    B: while (1) {    B: while (1) {
4377      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
4378        !!!cp ('t73');        !!!cp ('t73');
# Line 4447  sub _tree_construction_main ($) { Line 4420  sub _tree_construction_main ($) {
4420        } else {        } else {
4421          !!!cp ('t87');          !!!cp ('t87');
4422          $self->{open_elements}->[-1]->[0]->append_child ($comment);          $self->{open_elements}->[-1]->[0]->append_child ($comment);
4423            $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
4424        }        }
4425        !!!next-token;        !!!next-token;
4426        next B;        next B;
# Line 4562  sub _tree_construction_main ($) { Line 4536  sub _tree_construction_main ($) {
4536          pop @{$self->{open_elements}}          pop @{$self->{open_elements}}
4537              while $self->{open_elements}->[-1]->[1] & FOREIGN_EL;              while $self->{open_elements}->[-1]->[1] & FOREIGN_EL;
4538    
4539            ## NOTE: |<span><svg>| ... two parse errors, |<svg>| ... a parse error.
4540    
4541          $self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM;          $self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM;
4542          ## Reprocess.          ## Reprocess.
4543          next B;          next B;
# Line 4572  sub _tree_construction_main ($) { Line 4548  sub _tree_construction_main ($) {
4548    
4549      if ($self->{insertion_mode} & HEAD_IMS) {      if ($self->{insertion_mode} & HEAD_IMS) {
4550        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
4551          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
4552            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4553              !!!cp ('t88.2');              if ($self->{head_element_inserted}) {
4554              $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);                !!!cp ('t88.3');
4555              #                $self->{open_elements}->[-1]->[0]->append_child
4556                    ($self->{document}->create_text_node ($1));
4557                  delete $self->{head_element_inserted};
4558                  ## NOTE: |</head> <link> |
4559                  #
4560                } else {
4561                  !!!cp ('t88.2');
4562                  $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
4563                  ## NOTE: |</head> &#x20;|
4564                  #
4565                }
4566            } else {            } else {
4567              !!!cp ('t88.1');              !!!cp ('t88.1');
4568              ## Ignore the token.              ## Ignore the token.
# Line 4672  sub _tree_construction_main ($) { Line 4658  sub _tree_construction_main ($) {
4658            !!!cp ('t97');            !!!cp ('t97');
4659          }          }
4660    
4661              if ($token->{tag_name} eq 'base') {          if ($token->{tag_name} eq 'base') {
4662                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4663                  !!!cp ('t98');              !!!cp ('t98');
4664                  ## As if </noscript>              ## As if </noscript>
4665                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
4666                  !!!parse-error (type => 'in noscript', text => 'base',              !!!parse-error (type => 'in noscript', text => 'base',
4667                                  token => $token);                              token => $token);
4668                            
4669                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
4670                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
4671                } else {            } else {
4672                  !!!cp ('t99');              !!!cp ('t99');
4673                }            }
4674    
4675                ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
4676                if ($self->{insertion_mode} == AFTER_HEAD_IM) {            if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4677                  !!!cp ('t100');              !!!cp ('t100');
4678                  !!!parse-error (type => 'after head',              !!!parse-error (type => 'after head',
4679                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
4680                  push @{$self->{open_elements}},              push @{$self->{open_elements}},
4681                      [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4682                } else {              $self->{head_element_inserted} = 1;
4683                  !!!cp ('t101');            } else {
4684                }              !!!cp ('t101');
4685                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            }
4686                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4687                pop @{$self->{open_elements}} # <head>            pop @{$self->{open_elements}};
4688                    if $self->{insertion_mode} == AFTER_HEAD_IM;            pop @{$self->{open_elements}} # <head>
4689                !!!nack ('t101.1');                if $self->{insertion_mode} == AFTER_HEAD_IM;
4690                !!!next-token;            !!!nack ('t101.1');
4691                next B;            !!!next-token;
4692              } elsif ($token->{tag_name} eq 'link') {            next B;
4693                ## NOTE: There is a "as if in head" code clone.          } elsif ($token->{tag_name} eq 'link') {
4694                if ($self->{insertion_mode} == AFTER_HEAD_IM) {            ## NOTE: There is a "as if in head" code clone.
4695                  !!!cp ('t102');            if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4696                  !!!parse-error (type => 'after head',              !!!cp ('t102');
4697                                  text => $token->{tag_name}, token => $token);              !!!parse-error (type => 'after head',
4698                  push @{$self->{open_elements}},                              text => $token->{tag_name}, token => $token);
4699                      [$self->{head_element}, $el_category->{head}];              push @{$self->{open_elements}},
4700                } else {                  [$self->{head_element}, $el_category->{head}];
4701                  !!!cp ('t103');              $self->{head_element_inserted} = 1;
4702                }            } else {
4703                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);              !!!cp ('t103');
4704                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.            }
4705                pop @{$self->{open_elements}} # <head>            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4706                    if $self->{insertion_mode} == AFTER_HEAD_IM;            pop @{$self->{open_elements}};
4707                !!!ack ('t103.1');            pop @{$self->{open_elements}} # <head>
4708                !!!next-token;                if $self->{insertion_mode} == AFTER_HEAD_IM;
4709                next B;            !!!ack ('t103.1');
4710              } elsif ($token->{tag_name} eq 'meta') {            !!!next-token;
4711                ## NOTE: There is a "as if in head" code clone.            next B;
4712                if ($self->{insertion_mode} == AFTER_HEAD_IM) {          } elsif ($token->{tag_name} eq 'command' or
4713                  !!!cp ('t104');                   $token->{tag_name} eq 'eventsource') {
4714                  !!!parse-error (type => 'after head',            if ($self->{insertion_mode} == IN_HEAD_IM) {
4715                                  text => $token->{tag_name}, token => $token);              ## NOTE: If the insertion mode at the time of the emission
4716                  push @{$self->{open_elements}},              ## of the token was "before head", $self->{insertion_mode}
4717                      [$self->{head_element}, $el_category->{head}];              ## is already changed to |IN_HEAD_IM|.
4718                } else {  
4719                  !!!cp ('t105');              ## NOTE: There is a "as if in head" code clone.
4720                }              !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4721                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);              pop @{$self->{open_elements}};
4722                my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.              pop @{$self->{open_elements}} # <head>
4723                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4724                !!!ack ('t103.2');
4725                !!!next-token;
4726                next B;
4727              } else {
4728                ## NOTE: "in head noscript" or "after head" insertion mode
4729                ## - in these cases, these tags are treated as same as
4730                ## normal in-body tags.
4731                !!!cp ('t103.3');
4732                #
4733              }
4734            } elsif ($token->{tag_name} eq 'meta') {
4735              ## NOTE: There is a "as if in head" code clone.
4736              if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4737                !!!cp ('t104');
4738                !!!parse-error (type => 'after head',
4739                                text => $token->{tag_name}, token => $token);
4740                push @{$self->{open_elements}},
4741                    [$self->{head_element}, $el_category->{head}];
4742                $self->{head_element_inserted} = 1;
4743              } else {
4744                !!!cp ('t105');
4745              }
4746              !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4747              my $meta_el = pop @{$self->{open_elements}};
4748    
4749                unless ($self->{confident}) {                unless ($self->{confident}) {
4750                  if ($token->{attributes}->{charset}) {                  if ($token->{attributes}->{charset}) {
# Line 4751  sub _tree_construction_main ($) { Line 4762  sub _tree_construction_main ($) {
4762                  } elsif ($token->{attributes}->{content}) {                  } elsif ($token->{attributes}->{content}) {
4763                    if ($token->{attributes}->{content}->{value}                    if ($token->{attributes}->{content}->{value}
4764                        =~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt]                        =~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt]
4765                            [\x09-\x0D\x20]*=                            [\x09\x0A\x0C\x0D\x20]*=
4766                            [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                            [\x09\x0A\x0C\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
4767                            ([^"'\x09-\x0D\x20][^\x09-\x0D\x20\x3B]*))/x) {                            ([^"'\x09\x0A\x0C\x0D\x20]
4768                               [^\x09\x0A\x0C\x0D\x20\x3B]*))/x) {
4769                      !!!cp ('t107');                      !!!cp ('t107');
4770                      ## NOTE: Whether the encoding is supported or not is handled                      ## NOTE: Whether the encoding is supported or not is handled
4771                      ## in the {change_encoding} callback.                      ## in the {change_encoding} callback.
# Line 4790  sub _tree_construction_main ($) { Line 4802  sub _tree_construction_main ($) {
4802                !!!ack ('t110.1');                !!!ack ('t110.1');
4803                !!!next-token;                !!!next-token;
4804                next B;                next B;
4805              } elsif ($token->{tag_name} eq 'title') {          } elsif ($token->{tag_name} eq 'title') {
4806                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4807                  !!!cp ('t111');              !!!cp ('t111');
4808                  ## As if </noscript>              ## As if </noscript>
4809                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
4810                  !!!parse-error (type => 'in noscript', text => 'title',              !!!parse-error (type => 'in noscript', text => 'title',
4811                                  token => $token);                              token => $token);
4812                            
4813                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
4814                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
4815                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4816                  !!!cp ('t112');              !!!cp ('t112');
4817                  !!!parse-error (type => 'after head',              !!!parse-error (type => 'after head',
4818                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
4819                  push @{$self->{open_elements}},              push @{$self->{open_elements}},
4820                      [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4821                } else {              $self->{head_element_inserted} = 1;
4822                  !!!cp ('t113');            } else {
4823                }              !!!cp ('t113');
4824              }
4825    
4826                ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
4827                my $parent = defined $self->{head_element} ? $self->{head_element}            $parse_rcdata->(RCDATA_CONTENT_MODEL);
4828                    : $self->{open_elements}->[-1]->[0];            pop @{$self->{open_elements}} # <head>
4829                $parse_rcdata->(RCDATA_CONTENT_MODEL);                if $self->{insertion_mode} == AFTER_HEAD_IM;
4830                pop @{$self->{open_elements}} # <head>            next B;
4831                    if $self->{insertion_mode} == AFTER_HEAD_IM;          } elsif ($token->{tag_name} eq 'style' or
4832                next B;                   $token->{tag_name} eq 'noframes') {
4833              } elsif ($token->{tag_name} eq 'style' or            ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and
4834                       $token->{tag_name} eq 'noframes') {            ## insertion mode IN_HEAD_IM)
4835                ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and            ## NOTE: There is a "as if in head" code clone.
4836                ## insertion mode IN_HEAD_IM)            if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4837                ## NOTE: There is a "as if in head" code clone.              !!!cp ('t114');
4838                if ($self->{insertion_mode} == AFTER_HEAD_IM) {              !!!parse-error (type => 'after head',
4839                  !!!cp ('t114');                              text => $token->{tag_name}, token => $token);
4840                  !!!parse-error (type => 'after head',              push @{$self->{open_elements}},
4841                                  text => $token->{tag_name}, token => $token);                  [$self->{head_element}, $el_category->{head}];
4842                  push @{$self->{open_elements}},              $self->{head_element_inserted} = 1;
4843                      [$self->{head_element}, $el_category->{head}];            } else {
4844                } else {              !!!cp ('t115');
4845                  !!!cp ('t115');            }
4846                }            $parse_rcdata->(CDATA_CONTENT_MODEL);
4847                $parse_rcdata->(CDATA_CONTENT_MODEL);            pop @{$self->{open_elements}} # <head>
4848                pop @{$self->{open_elements}} # <head>                if $self->{insertion_mode} == AFTER_HEAD_IM;
4849                    if $self->{insertion_mode} == AFTER_HEAD_IM;            next B;
               next B;  
4850              } elsif ($token->{tag_name} eq 'noscript') {              } elsif ($token->{tag_name} eq 'noscript') {
4851                if ($self->{insertion_mode} == IN_HEAD_IM) {                if ($self->{insertion_mode} == IN_HEAD_IM) {
4852                  !!!cp ('t116');                  !!!cp ('t116');
# Line 4856  sub _tree_construction_main ($) { Line 4868  sub _tree_construction_main ($) {
4868                  !!!cp ('t118');                  !!!cp ('t118');
4869                  #                  #
4870                }                }
4871              } elsif ($token->{tag_name} eq 'script') {          } elsif ($token->{tag_name} eq 'script') {
4872                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4873                  !!!cp ('t119');              !!!cp ('t119');
4874                  ## As if </noscript>              ## As if </noscript>
4875                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
4876                  !!!parse-error (type => 'in noscript', text => 'script',              !!!parse-error (type => 'in noscript', text => 'script',
4877                                  token => $token);                              token => $token);
4878                            
4879                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
4880                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
4881                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4882                  !!!cp ('t120');              !!!cp ('t120');
4883                  !!!parse-error (type => 'after head',              !!!parse-error (type => 'after head',
4884                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
4885                  push @{$self->{open_elements}},              push @{$self->{open_elements}},
4886                      [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4887                } else {              $self->{head_element_inserted} = 1;
4888                  !!!cp ('t121');            } else {
4889                }              !!!cp ('t121');
4890              }
4891    
4892                ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
4893                $script_start_tag->();            $script_start_tag->();
4894                pop @{$self->{open_elements}} # <head>            pop @{$self->{open_elements}} # <head>
4895                    if $self->{insertion_mode} == AFTER_HEAD_IM;                if $self->{insertion_mode} == AFTER_HEAD_IM;
4896                next B;            next B;
4897              } elsif ($token->{tag_name} eq 'body' or          } elsif ($token->{tag_name} eq 'body' or
4898                       $token->{tag_name} eq 'frameset') {                   $token->{tag_name} eq 'frameset') {
4899                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4900                  !!!cp ('t122');                  !!!cp ('t122');
4901                  ## As if </noscript>                  ## As if </noscript>
# Line 5017  sub _tree_construction_main ($) { Line 5030  sub _tree_construction_main ($) {
5030              } elsif ({              } elsif ({
5031                        body => 1, html => 1,                        body => 1, html => 1,
5032                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
5033                if ($self->{insertion_mode} == BEFORE_HEAD_IM or                ## TODO: This branch is entirely redundant.
5034                  if ($self->{insertion_mode} == BEFORE_HEAD_IM or
5035                    $self->{insertion_mode} == IN_HEAD_IM or                    $self->{insertion_mode} == IN_HEAD_IM or
5036                    $self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                    $self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
5037                  !!!cp ('t140');                  !!!cp ('t140');
# Line 5189  sub _tree_construction_main ($) { Line 5203  sub _tree_construction_main ($) {
5203        } else {        } else {
5204          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
5205        }        }
   
           ## ISSUE: An issue in the spec.  
5206      } elsif ($self->{insertion_mode} & BODY_IMS) {      } elsif ($self->{insertion_mode} & BODY_IMS) {
5207            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
5208              !!!cp ('t150');              !!!cp ('t150');
# Line 5562  sub _tree_construction_main ($) { Line 5574  sub _tree_construction_main ($) {
5574      } elsif ($self->{insertion_mode} & TABLE_IMS) {      } elsif ($self->{insertion_mode} & TABLE_IMS) {
5575        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
5576          if (not $open_tables->[-1]->[1] and # tainted          if (not $open_tables->[-1]->[1] and # tainted
5577              $token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {              $token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
5578            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
5579                                
5580            unless (length $token->{data}) {            unless (length $token->{data}) {
# Line 5576  sub _tree_construction_main ($) { Line 5588  sub _tree_construction_main ($) {
5588    
5589          !!!parse-error (type => 'in table:#text', token => $token);          !!!parse-error (type => 'in table:#text', token => $token);
5590    
5591              ## As if in body, but insert into foster parent element          ## NOTE: As if in body, but insert into the foster parent element.
5592              ## 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);  
5593                            
5594              if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {          if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {
5595                # MUST            # MUST
5596                my $foster_parent_element;            my $foster_parent_element;
5597                my $next_sibling;            my $next_sibling;
5598                my $prev_sibling;            my $prev_sibling;
5599                OE: for (reverse 0..$#{$self->{open_elements}}) {            OE: for (reverse 0..$#{$self->{open_elements}}) {
5600                  if ($self->{open_elements}->[$_]->[1] & TABLE_EL) {              if ($self->{open_elements}->[$_]->[1] & TABLE_EL) {
5601                    my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
5602                    if (defined $parent and $parent->node_type == 1) {                if (defined $parent and $parent->node_type == 1) {
5603                      !!!cp ('t196');                  $foster_parent_element = $parent;
5604                      $foster_parent_element = $parent;                  !!!cp ('t196');
5605                      $next_sibling = $self->{open_elements}->[$_]->[0];                  $next_sibling = $self->{open_elements}->[$_]->[0];
5606                      $prev_sibling = $next_sibling->previous_sibling;                  $prev_sibling = $next_sibling->previous_sibling;
5607                    } 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});  
5608                } else {                } else {
5609                  !!!cp ('t199');                  !!!cp ('t197');
5610                  $foster_parent_element->insert_before                  $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];
5611                    ($self->{document}->create_text_node ($token->{data}),                  $prev_sibling = $foster_parent_element->last_child;
5612                     $next_sibling);                  #
5613                }                }
5614                  last OE;
5615                }
5616              } # OE
5617              $foster_parent_element = $self->{open_elements}->[0]->[0] and
5618              $prev_sibling = $foster_parent_element->last_child
5619                  unless defined $foster_parent_element;
5620              undef $prev_sibling unless $open_tables->[-1]->[2]; # ~node inserted
5621              if (defined $prev_sibling and
5622                  $prev_sibling->node_type == 3) {
5623                !!!cp ('t198');
5624                $prev_sibling->manakai_append_text ($token->{data});
5625              } else {
5626                !!!cp ('t199');
5627                $foster_parent_element->insert_before
5628                    ($self->{document}->create_text_node ($token->{data}),
5629                     $next_sibling);
5630              }
5631            $open_tables->[-1]->[1] = 1; # tainted            $open_tables->[-1]->[1] = 1; # tainted
5632              $open_tables->[-1]->[2] = 1; # ~node inserted
5633          } else {          } else {
5634              ## NOTE: Fragment case or in a foster parent'ed element
5635              ## (e.g. |<table><span>a|).  In fragment case, whether the
5636              ## character is appended to existing node or a new node is
5637              ## created is irrelevant, since the foster parent'ed nodes
5638              ## are discarded and fragment parsing does not invoke any
5639              ## script.
5640            !!!cp ('t200');            !!!cp ('t200');
5641            $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});            $self->{open_elements}->[-1]->[0]->manakai_append_text
5642                  ($token->{data});
5643          }          }
5644                            
5645          !!!next-token;          !!!next-token;
# Line 5656  sub _tree_construction_main ($) { Line 5676  sub _tree_construction_main ($) {
5676                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5677              }              }
5678                                    
5679                  $self->{insertion_mode} = IN_ROW_IM;              $self->{insertion_mode} = IN_ROW_IM;
5680                  if ($token->{tag_name} eq 'tr') {              if ($token->{tag_name} eq 'tr') {
5681                    !!!cp ('t204');                !!!cp ('t204');
5682                    !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5683                    !!!nack ('t204');                $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5684                    !!!next-token;                !!!nack ('t204');
5685                    next B;                !!!next-token;
5686                  } else {                next B;
5687                    !!!cp ('t205');              } else {
5688                    !!!insert-element ('tr',, $token);                !!!cp ('t205');
5689                    ## reprocess in the "in row" insertion mode                !!!insert-element ('tr',, $token);
5690                  }                ## reprocess in the "in row" insertion mode
5691                } else {              }
5692                  !!!cp ('t206');            } else {
5693                }              !!!cp ('t206');
5694              }
5695    
5696                ## Clear back to table row context                ## Clear back to table row context
5697                while (not ($self->{open_elements}->[-1]->[1]                while (not ($self->{open_elements}->[-1]->[1]
# Line 5679  sub _tree_construction_main ($) { Line 5700  sub _tree_construction_main ($) {
5700                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
5701                }                }
5702                                
5703                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5704                $self->{insertion_mode} = IN_CELL_IM;            $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5705              $self->{insertion_mode} = IN_CELL_IM;
5706    
5707                push @$active_formatting_elements, ['#marker', ''];            push @$active_formatting_elements, ['#marker', ''];
5708                                
5709                !!!nack ('t207.1');            !!!nack ('t207.1');
5710              !!!next-token;
5711              next B;
5712            } elsif ({
5713                      caption => 1, col => 1, colgroup => 1,
5714                      tbody => 1, tfoot => 1, thead => 1,
5715                      tr => 1, # $self->{insertion_mode} == IN_ROW_IM
5716                     }->{$token->{tag_name}}) {
5717              if ($self->{insertion_mode} == IN_ROW_IM) {
5718                ## As if </tr>
5719                ## have an element in table scope
5720                my $i;
5721                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5722                  my $node = $self->{open_elements}->[$_];
5723                  if ($node->[1] & TABLE_ROW_EL) {
5724                    !!!cp ('t208');
5725                    $i = $_;
5726                    last INSCOPE;
5727                  } elsif ($node->[1] & TABLE_SCOPING_EL) {
5728                    !!!cp ('t209');
5729                    last INSCOPE;
5730                  }
5731                } # INSCOPE
5732                unless (defined $i) {
5733                  !!!cp ('t210');
5734                  ## TODO: This type is wrong.
5735                  !!!parse-error (type => 'unmacthed end tag',
5736                                  text => $token->{tag_name}, token => $token);
5737                  ## Ignore the token
5738                  !!!nack ('t210.1');
5739                !!!next-token;                !!!next-token;
5740                next B;                next B;
5741              } 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;  
                 }  
5742                                    
5743                  ## Clear back to table row context                  ## Clear back to table row context
5744                  while (not ($self->{open_elements}->[-1]->[1]                  while (not ($self->{open_elements}->[-1]->[1]
# Line 5786  sub _tree_construction_main ($) { Line 5808  sub _tree_construction_main ($) {
5808                  !!!cp ('t218');                  !!!cp ('t218');
5809                }                }
5810    
5811                if ($token->{tag_name} eq 'col') {            if ($token->{tag_name} eq 'col') {
5812                  ## Clear back to table context              ## Clear back to table context
5813                  while (not ($self->{open_elements}->[-1]->[1]              while (not ($self->{open_elements}->[-1]->[1]
5814                                  & TABLE_SCOPING_EL)) {                              & TABLE_SCOPING_EL)) {
5815                    !!!cp ('t219');                !!!cp ('t219');
5816                    ## ISSUE: Can this state be reached?                ## ISSUE: Can this state be reached?
5817                    pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5818                  }              }
5819                                
5820                  !!!insert-element ('colgroup',, $token);              !!!insert-element ('colgroup',, $token);
5821                  $self->{insertion_mode} = IN_COLUMN_GROUP_IM;              $self->{insertion_mode} = IN_COLUMN_GROUP_IM;
5822                  ## reprocess              ## reprocess
5823                  !!!ack-later;              $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5824                  next B;              !!!ack-later;
5825                } elsif ({              next B;
5826                          caption => 1,            } elsif ({
5827                          colgroup => 1,                      caption => 1,
5828                          tbody => 1, tfoot => 1, thead => 1,                      colgroup => 1,
5829                         }->{$token->{tag_name}}) {                      tbody => 1, tfoot => 1, thead => 1,
5830                  ## Clear back to table context                     }->{$token->{tag_name}}) {
5831                ## Clear back to table context
5832                  while (not ($self->{open_elements}->[-1]->[1]                  while (not ($self->{open_elements}->[-1]->[1]
5833                                  & TABLE_SCOPING_EL)) {                                  & TABLE_SCOPING_EL)) {
5834                    !!!cp ('t220');                    !!!cp ('t220');
# Line 5813  sub _tree_construction_main ($) { Line 5836  sub _tree_construction_main ($) {
5836                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
5837                  }                  }
5838                                    
5839                  push @$active_formatting_elements, ['#marker', '']              push @$active_formatting_elements, ['#marker', '']
5840                      if $token->{tag_name} eq 'caption';                  if $token->{tag_name} eq 'caption';
5841                                    
5842                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);              !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5843                  $self->{insertion_mode} = {              $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5844                                             caption => IN_CAPTION_IM,              $self->{insertion_mode} = {
5845                                             colgroup => IN_COLUMN_GROUP_IM,                                         caption => IN_CAPTION_IM,
5846                                             tbody => IN_TABLE_BODY_IM,                                         colgroup => IN_COLUMN_GROUP_IM,
5847                                             tfoot => IN_TABLE_BODY_IM,                                         tbody => IN_TABLE_BODY_IM,
5848                                             thead => IN_TABLE_BODY_IM,                                         tfoot => IN_TABLE_BODY_IM,
5849                                            }->{$token->{tag_name}};                                         thead => IN_TABLE_BODY_IM,
5850                  !!!next-token;                                        }->{$token->{tag_name}};
5851                  !!!nack ('t220.1');              !!!next-token;
5852                  next B;              !!!nack ('t220.1');
5853                } else {              next B;
5854                  die "$0: in table: <>: $token->{tag_name}";            } else {
5855                }              die "$0: in table: <>: $token->{tag_name}";
5856              }
5857              } elsif ($token->{tag_name} eq 'table') {              } elsif ($token->{tag_name} eq 'table') {
5858                !!!parse-error (type => 'not closed',                !!!parse-error (type => 'not closed',
5859                                text => $self->{open_elements}->[-1]->[0]                                text => $self->{open_elements}->[-1]->[0]
# Line 5892  sub _tree_construction_main ($) { Line 5916  sub _tree_construction_main ($) {
5916              !!!cp ('t227.8');              !!!cp ('t227.8');
5917              ## NOTE: This is a "as if in head" code clone.              ## NOTE: This is a "as if in head" code clone.
5918              $parse_rcdata->(CDATA_CONTENT_MODEL);              $parse_rcdata->(CDATA_CONTENT_MODEL);
5919                $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5920              next B;              next B;
5921            } else {            } else {
5922              !!!cp ('t227.7');              !!!cp ('t227.7');
# Line 5902  sub _tree_construction_main ($) { Line 5927  sub _tree_construction_main ($) {
5927              !!!cp ('t227.6');              !!!cp ('t227.6');
5928              ## NOTE: This is a "as if in head" code clone.              ## NOTE: This is a "as if in head" code clone.
5929              $script_start_tag->();              $script_start_tag->();
5930                $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5931              next B;              next B;
5932            } else {            } else {
5933              !!!cp ('t227.5');              !!!cp ('t227.5');
# Line 5917  sub _tree_construction_main ($) { Line 5943  sub _tree_construction_main ($) {
5943                                  text => $token->{tag_name}, token => $token);                                  text => $token->{tag_name}, token => $token);
5944    
5945                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5946                    $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5947    
5948                  ## TODO: form element pointer                  ## TODO: form element pointer
5949    
# Line 6246  sub _tree_construction_main ($) { Line 6273  sub _tree_construction_main ($) {
6273        }        }
6274      } elsif ($self->{insertion_mode} == IN_COLUMN_GROUP_IM) {      } elsif ($self->{insertion_mode} == IN_COLUMN_GROUP_IM) {
6275            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
6276              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {              if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
6277                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
6278                unless (length $token->{data}) {                unless (length $token->{data}) {
6279                  !!!cp ('t260');                  !!!cp ('t260');
# Line 6587  sub _tree_construction_main ($) { Line 6614  sub _tree_construction_main ($) {
6614        }        }
6615      } elsif ($self->{insertion_mode} & BODY_AFTER_IMS) {      } elsif ($self->{insertion_mode} & BODY_AFTER_IMS) {
6616        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
6617          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
6618            my $data = $1;            my $data = $1;
6619            ## As if in body            ## As if in body
6620            $reconstruct_active_formatting_elements->($insert_to_current);            $reconstruct_active_formatting_elements->($insert_to_current);
# Line 6604  sub _tree_construction_main ($) { Line 6631  sub _tree_construction_main ($) {
6631          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
6632            !!!cp ('t301');            !!!cp ('t301');
6633            !!!parse-error (type => 'after html:#text', token => $token);            !!!parse-error (type => 'after html:#text', token => $token);
6634              #
           ## Reprocess in the "after body" insertion mode.  
6635          } else {          } else {
6636            !!!cp ('t302');            !!!cp ('t302');
6637              ## "after body" insertion mode
6638              !!!parse-error (type => 'after body:#text', token => $token);
6639              #
6640          }          }
           
         ## "after body" insertion mode  
         !!!parse-error (type => 'after body:#text', token => $token);  
6641    
6642          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
6643          ## reprocess          ## reprocess
# Line 6621  sub _tree_construction_main ($) { Line 6647  sub _tree_construction_main ($) {
6647            !!!cp ('t303');            !!!cp ('t303');
6648            !!!parse-error (type => 'after html',            !!!parse-error (type => 'after html',
6649                            text => $token->{tag_name}, token => $token);                            text => $token->{tag_name}, token => $token);
6650                        #
           ## Reprocess in the "after body" insertion mode.  
6651          } else {          } else {
6652            !!!cp ('t304');            !!!cp ('t304');
6653              ## "after body" insertion mode
6654              !!!parse-error (type => 'after body',
6655                              text => $token->{tag_name}, token => $token);
6656              #
6657          }          }
6658    
         ## "after body" insertion mode  
         !!!parse-error (type => 'after body',  
                         text => $token->{tag_name}, token => $token);  
   
6659          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
6660          !!!ack-later;          !!!ack-later;
6661          ## reprocess          ## reprocess
# Line 6641  sub _tree_construction_main ($) { Line 6666  sub _tree_construction_main ($) {
6666            !!!parse-error (type => 'after html:/',            !!!parse-error (type => 'after html:/',
6667                            text => $token->{tag_name}, token => $token);                            text => $token->{tag_name}, token => $token);
6668                        
6669            $self->{insertion_mode} = AFTER_BODY_IM;            $self->{insertion_mode} = IN_BODY_IM;
6670            ## Reprocess in the "after body" insertion mode.            ## Reprocess.
6671              next B;
6672          } else {          } else {
6673            !!!cp ('t306');            !!!cp ('t306');
6674          }          }
# Line 6680  sub _tree_construction_main ($) { Line 6706  sub _tree_construction_main ($) {
6706        }        }
6707      } elsif ($self->{insertion_mode} & FRAME_IMS) {      } elsif ($self->{insertion_mode} & FRAME_IMS) {
6708        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
6709          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
6710            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
6711                        
6712            unless (length $token->{data}) {            unless (length $token->{data}) {
# Line 6690  sub _tree_construction_main ($) { Line 6716  sub _tree_construction_main ($) {
6716            }            }
6717          }          }
6718                    
6719          if ($token->{data} =~ s/^[^\x09\x0A\x0B\x0C\x20]+//) {          if ($token->{data} =~ s/^[^\x09\x0A\x0C\x20]+//) {
6720            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
6721              !!!cp ('t311');              !!!cp ('t311');
6722              !!!parse-error (type => 'in frameset:#text', token => $token);              !!!parse-error (type => 'in frameset:#text', token => $token);
# Line 6819  sub _tree_construction_main ($) { Line 6845  sub _tree_construction_main ($) {
6845        } else {        } else {
6846          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
6847        }        }
   
       ## ISSUE: An issue in spec here  
6848      } else {      } else {
6849        die "$0: $self->{insertion_mode}: Unknown insertion mode";        die "$0: $self->{insertion_mode}: Unknown insertion mode";
6850      }      }
# Line 6838  sub _tree_construction_main ($) { Line 6862  sub _tree_construction_main ($) {
6862          $parse_rcdata->(CDATA_CONTENT_MODEL);          $parse_rcdata->(CDATA_CONTENT_MODEL);
6863          next B;          next B;
6864        } elsif ({        } elsif ({
6865                  base => 1, link => 1,                  base => 1, command => 1, eventsource => 1, link => 1,
6866                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
6867          !!!cp ('t334');          !!!cp ('t334');
6868          ## 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
6869          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6870          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          pop @{$self->{open_elements}};
6871          !!!ack ('t334.1');          !!!ack ('t334.1');
6872          !!!next-token;          !!!next-token;
6873          next B;          next B;
6874        } elsif ($token->{tag_name} eq 'meta') {        } elsif ($token->{tag_name} eq 'meta') {
6875          ## 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
6876          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6877          my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          my $meta_el = pop @{$self->{open_elements}};
6878    
6879          unless ($self->{confident}) {          unless ($self->{confident}) {
6880            if ($token->{attributes}->{charset}) {            if ($token->{attributes}->{charset}) {
# Line 6867  sub _tree_construction_main ($) { Line 6891  sub _tree_construction_main ($) {
6891            } elsif ($token->{attributes}->{content}) {            } elsif ($token->{attributes}->{content}) {
6892              if ($token->{attributes}->{content}->{value}              if ($token->{attributes}->{content}->{value}
6893                  =~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt]                  =~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt]
6894                      [\x09-\x0D\x20]*=                      [\x09\x0A\x0C\x0D\x20]*=
6895                      [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                      [\x09\x0A\x0C\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
6896                      ([^"'\x09-\x0D\x20][^\x09-\x0D\x20\x3B]*))/x) {                      ([^"'\x09\x0A\x0C\x0D\x20][^\x09\x0A\x0C\x0D\x20\x3B]*))
6897                       /x) {
6898                !!!cp ('t336');                !!!cp ('t336');
6899                ## NOTE: Whether the encoding is supported or not is handled                ## NOTE: Whether the encoding is supported or not is handled
6900                ## in the {change_encoding} callback.                ## in the {change_encoding} callback.
# Line 6928  sub _tree_construction_main ($) { Line 6953  sub _tree_construction_main ($) {
6953          !!!next-token;          !!!next-token;
6954          next B;          next B;
6955        } elsif ({        } elsif ({
6956                  address => 1, blockquote => 1, center => 1, dir => 1,                  ## NOTE: Start tags for non-phrasing flow content elements
6957                  div => 1, dl => 1, fieldset => 1,  
6958                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                  ## NOTE: The normal one
6959                  menu => 1, ol => 1, p => 1, ul => 1,                  address => 1, article => 1, aside => 1, blockquote => 1,
6960                    center => 1, datagrid => 1, details => 1, dialog => 1,
6961                    dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,
6962                    footer => 1, h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1,
6963                    h6 => 1, header => 1, menu => 1, nav => 1, ol => 1, p => 1,
6964                    section => 1, ul => 1,
6965                    ## NOTE: As normal, but drops leading newline
6966                  pre => 1, listing => 1,                  pre => 1, listing => 1,
6967                    ## NOTE: As normal, but interacts with the form element pointer
6968                  form => 1,                  form => 1,
6969                    
6970                  table => 1,                  table => 1,
6971                  hr => 1,                  hr => 1,
6972                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 7000  sub _tree_construction_main ($) { Line 7033  sub _tree_construction_main ($) {
7033            !!!next-token;            !!!next-token;
7034          }          }
7035          next B;          next B;
7036        } elsif ({li => 1, dt => 1, dd => 1}->{$token->{tag_name}}) {        } elsif ($token->{tag_name} eq 'li') {
7037          ## has a p element in scope          ## NOTE: As normal, but imply </li> when there's another <li> ...
7038    
7039            ## NOTE: Special, Scope (<li><foo><li> == <li><foo><li/></foo></li>)
7040              ## Interpreted as <li><foo/></li><li/> (non-conforming)
7041              ## blockquote (O9.27), center (O), dd (Fx3, O, S3.1.2, IE7),
7042              ## dt (Fx, O, S, IE), dl (O), fieldset (O, S, IE), form (Fx, O, S),
7043              ## hn (O), pre (O), applet (O, S), button (O, S), marquee (Fx, O, S),
7044              ## object (Fx)
7045              ## Generate non-tree (non-conforming)
7046              ## basefont (IE7 (where basefont is non-void)), center (IE),
7047              ## form (IE), hn (IE)
7048            ## address, div, p (<li><foo><li> == <li><foo/></li><li/>)
7049              ## Interpreted as <li><foo><li/></foo></li> (non-conforming)
7050              ## div (Fx, S)
7051    
7052            my $non_optional;
7053            my $i = -1;
7054    
7055            ## 1.
7056            for my $node (reverse @{$self->{open_elements}}) {
7057              if ($node->[1] & LI_EL) {
7058                ## 2. (a) As if </li>
7059                {
7060                  ## If no </li> - not applied
7061                  #
7062    
7063                  ## Otherwise
7064    
7065                  ## 1. generate implied end tags, except for </li>
7066                  #
7067    
7068                  ## 2. If current node != "li", parse error
7069                  if ($non_optional) {
7070                    !!!parse-error (type => 'not closed',
7071                                    text => $non_optional->[0]->manakai_local_name,
7072                                    token => $token);
7073                    !!!cp ('t355');
7074                  } else {
7075                    !!!cp ('t356');
7076                  }
7077    
7078                  ## 3. Pop
7079                  splice @{$self->{open_elements}}, $i;
7080                }
7081    
7082                last; ## 2. (b) goto 5.
7083              } elsif (
7084                       ## NOTE: not "formatting" and not "phrasing"
7085                       ($node->[1] & SPECIAL_EL or
7086                        $node->[1] & SCOPING_EL) and
7087                       ## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|.
7088    
7089                       (not $node->[1] & ADDRESS_EL) &
7090                       (not $node->[1] & DIV_EL) &
7091                       (not $node->[1] & P_EL)) {
7092                ## 3.
7093                !!!cp ('t357');
7094                last; ## goto 5.
7095              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7096                !!!cp ('t358');
7097                #
7098              } else {
7099                !!!cp ('t359');
7100                $non_optional ||= $node;
7101                #
7102              }
7103              ## 4.
7104              ## goto 2.
7105              $i--;
7106            }
7107    
7108            ## 5. (a) has a |p| element in scope
7109          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
7110            if ($_->[1] & P_EL) {            if ($_->[1] & P_EL) {
7111              !!!cp ('t353');              !!!cp ('t353');
7112    
7113                ## NOTE: |<p><li>|, for example.
7114    
7115              !!!back-token; # <x>              !!!back-token; # <x>
7116              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
7117                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
# Line 7014  sub _tree_construction_main ($) { Line 7121  sub _tree_construction_main ($) {
7121              last INSCOPE;              last INSCOPE;
7122            }            }
7123          } # INSCOPE          } # INSCOPE
7124              
7125          ## Step 1          ## 5. (b) insert
7126            !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7127            !!!nack ('t359.1');
7128            !!!next-token;
7129            next B;
7130          } elsif ($token->{tag_name} eq 'dt' or
7131                   $token->{tag_name} eq 'dd') {
7132            ## NOTE: As normal, but imply </dt> or </dd> when ...
7133    
7134            my $non_optional;
7135          my $i = -1;          my $i = -1;
7136          my $node = $self->{open_elements}->[$i];  
7137          my $li_or_dtdd = {li => {li => 1},          ## 1.
7138                            dt => {dt => 1, dd => 1},          for my $node (reverse @{$self->{open_elements}}) {
7139                            dd => {dt => 1, dd => 1}}->{$token->{tag_name}};            if ($node->[1] & DT_EL or $node->[1] & DD_EL) {
7140          LI: {              ## 2. (a) As if </li>
7141            ## Step 2              {
7142            if ($li_or_dtdd->{$node->[0]->manakai_local_name}) {                ## If no </li> - not applied
7143              if ($i != -1) {                #
7144                !!!cp ('t355');  
7145                !!!parse-error (type => 'not closed',                ## Otherwise
7146                                text => $self->{open_elements}->[-1]->[0]  
7147                                    ->manakai_local_name,                ## 1. generate implied end tags, except for </dt> or </dd>
7148                                token => $token);                #
7149              } else {  
7150                !!!cp ('t356');                ## 2. If current node != "dt"|"dd", parse error
7151                  if ($non_optional) {
7152                    !!!parse-error (type => 'not closed',
7153                                    text => $non_optional->[0]->manakai_local_name,
7154                                    token => $token);
7155                    !!!cp ('t355.1');
7156                  } else {
7157                    !!!cp ('t356.1');
7158                  }
7159    
7160                  ## 3. Pop
7161                  splice @{$self->{open_elements}}, $i;
7162              }              }
7163              splice @{$self->{open_elements}}, $i;  
7164              last LI;              last; ## 2. (b) goto 5.
7165              } elsif (
7166                       ## NOTE: not "formatting" and not "phrasing"
7167                       ($node->[1] & SPECIAL_EL or
7168                        $node->[1] & SCOPING_EL) and
7169                       ## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|.
7170    
7171                       (not $node->[1] & ADDRESS_EL) &
7172                       (not $node->[1] & DIV_EL) &
7173                       (not $node->[1] & P_EL)) {
7174                ## 3.
7175                !!!cp ('t357.1');
7176                last; ## goto 5.
7177              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7178                !!!cp ('t358.1');
7179                #
7180            } else {            } else {
7181              !!!cp ('t357');              !!!cp ('t359.1');
7182            }              $non_optional ||= $node;
7183                          #
           ## 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;  
7184            }            }
7185                        ## 4.
7186            !!!cp ('t359');            ## goto 2.
           ## Step 4  
7187            $i--;            $i--;
7188            $node = $self->{open_elements}->[$i];          }
7189            redo LI;  
7190          } # LI          ## 5. (a) has a |p| element in scope
7191                      INSCOPE: for (reverse @{$self->{open_elements}}) {
7192              if ($_->[1] & P_EL) {
7193                !!!cp ('t353.1');
7194                !!!back-token; # <x>
7195                $token = {type => END_TAG_TOKEN, tag_name => 'p',
7196                          line => $token->{line}, column => $token->{column}};
7197                next B;
7198              } elsif ($_->[1] & SCOPING_EL) {
7199                !!!cp ('t354.1');
7200                last INSCOPE;
7201              }
7202            } # INSCOPE
7203    
7204            ## 5. (b) insert
7205          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7206          !!!nack ('t359.1');          !!!nack ('t359.2');
7207          !!!next-token;          !!!next-token;
7208          next B;          next B;
7209        } elsif ($token->{tag_name} eq 'plaintext') {        } elsif ($token->{tag_name} eq 'plaintext') {
7210            ## NOTE: As normal, but effectively ends parsing
7211    
7212          ## has a p element in scope          ## has a p element in scope
7213          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
7214            if ($_->[1] & P_EL) {            if ($_->[1] & P_EL) {
# Line 7299  sub _tree_construction_main ($) { Line 7446  sub _tree_construction_main ($) {
7446          }          }
7447          !!!next-token;          !!!next-token;
7448          next B;          next B;
7449          } elsif ($token->{tag_name} eq 'optgroup' or
7450                   $token->{tag_name} eq 'option') {
7451            ## has an |option| element in scope
7452            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7453              my $node = $self->{open_elements}->[$_];
7454              if ($node->[1] & OPTION_EL) {
7455                !!!cp ('t397.1');
7456                ## NOTE: As if </option>
7457                !!!back-token; # <option> or <optgroup>
7458                $token = {type => END_TAG_TOKEN, tag_name => 'option',
7459                          line => $token->{line}, column => $token->{column}};
7460                next B;
7461              } elsif ($node->[1] & SCOPING_EL) {
7462                !!!cp ('t397.2');
7463                last INSCOPE;
7464              }
7465            } # INSCOPE
7466    
7467            $reconstruct_active_formatting_elements->($insert_to_current);
7468    
7469            !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7470    
7471            !!!nack ('t397.3');
7472            !!!next-token;
7473            redo B;
7474        } elsif ($token->{tag_name} eq 'rt' or        } elsif ($token->{tag_name} eq 'rt' or
7475                 $token->{tag_name} eq 'rp') {                 $token->{tag_name} eq 'rp') {
7476          ## has a |ruby| element in scope          ## has a |ruby| element in scope
# Line 7346  sub _tree_construction_main ($) { Line 7518  sub _tree_construction_main ($) {
7518                    
7519          if ($self->{self_closing}) {          if ($self->{self_closing}) {
7520            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
7521            !!!ack ('t398.1');            !!!ack ('t398.6');
7522          } else {          } else {
7523            !!!cp ('t398.2');            !!!cp ('t398.7');
7524            $self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM;            $self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM;
7525            ## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion            ## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion
7526            ## mode, "in body" (not "in foreign content") secondary insertion            ## mode, "in body" (not "in foreign content") secondary insertion
# Line 7359  sub _tree_construction_main ($) { Line 7531  sub _tree_construction_main ($) {
7531          next B;          next B;
7532        } elsif ({        } elsif ({
7533                  caption => 1, col => 1, colgroup => 1, frame => 1,                  caption => 1, col => 1, colgroup => 1, frame => 1,
7534                  frameset => 1, head => 1, option => 1, optgroup => 1,                  frameset => 1, head => 1,
7535                  tbody => 1, td => 1, tfoot => 1, th => 1,                  tbody => 1, td => 1, tfoot => 1, th => 1,
7536                  thead => 1, tr => 1,                  thead => 1, tr => 1,
7537                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 7370  sub _tree_construction_main ($) { Line 7542  sub _tree_construction_main ($) {
7542          !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.          !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.
7543          !!!next-token;          !!!next-token;
7544          next B;          next B;
7545                  } elsif ($token->{tag_name} eq 'param' or
7546          ## ISSUE: An issue on HTML5 new elements in the spec.                 $token->{tag_name} eq 'source') {
7547            !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7548            pop @{$self->{open_elements}};
7549    
7550            !!!ack ('t398.5');
7551            !!!next-token;
7552            redo B;
7553        } else {        } else {
7554          if ($token->{tag_name} eq 'image') {          if ($token->{tag_name} eq 'image') {
7555            !!!cp ('t384');            !!!cp ('t384');
# Line 7394  sub _tree_construction_main ($) { Line 7572  sub _tree_construction_main ($) {
7572            !!!nack ('t380.1');            !!!nack ('t380.1');
7573          } elsif ({          } elsif ({
7574                    b => 1, big => 1, em => 1, font => 1, i => 1,                    b => 1, big => 1, em => 1, font => 1, i => 1,
7575                    s => 1, small => 1, strile => 1,                    s => 1, small => 1, strike => 1,
7576                    strong => 1, tt => 1, u => 1,                    strong => 1, tt => 1, u => 1,
7577                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
7578            !!!cp ('t375');            !!!cp ('t375');
# Line 7407  sub _tree_construction_main ($) { Line 7585  sub _tree_construction_main ($) {
7585            !!!ack ('t388.2');            !!!ack ('t388.2');
7586          } elsif ({          } elsif ({
7587                    area => 1, basefont => 1, bgsound => 1, br => 1,                    area => 1, basefont => 1, bgsound => 1, br => 1,
7588                    embed => 1, img => 1, param => 1, spacer => 1, wbr => 1,                    embed => 1, img => 1, spacer => 1, wbr => 1,
                   #image => 1,  
7589                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
7590            !!!cp ('t388.1');            !!!cp ('t388.1');
7591            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
# Line 7449  sub _tree_construction_main ($) { Line 7626  sub _tree_construction_main ($) {
7626              }              }
7627            }            }
7628    
7629            !!!parse-error (type => 'start tag not allowed',            ## NOTE: |<marquee></body>|, |<svg><foreignobject></body>|
7630    
7631              !!!parse-error (type => 'unmatched end tag',
7632                            text => $token->{tag_name}, token => $token);                            text => $token->{tag_name}, token => $token);
7633            ## NOTE: Ignore the token.            ## NOTE: Ignore the token.
7634            !!!next-token;            !!!next-token;
# Line 7476  sub _tree_construction_main ($) { Line 7655  sub _tree_construction_main ($) {
7655          ## up-to-date, though it has same effect as speced.          ## up-to-date, though it has same effect as speced.
7656          if (@{$self->{open_elements}} > 1 and          if (@{$self->{open_elements}} > 1 and
7657              $self->{open_elements}->[1]->[1] & BODY_EL) {              $self->{open_elements}->[1]->[1] & BODY_EL) {
           ## ISSUE: There is an issue in the spec.  
7658            unless ($self->{open_elements}->[-1]->[1] & BODY_EL) {            unless ($self->{open_elements}->[-1]->[1] & BODY_EL) {
7659              !!!cp ('t406');              !!!cp ('t406');
7660              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
# Line 7498  sub _tree_construction_main ($) { Line 7676  sub _tree_construction_main ($) {
7676            next B;            next B;
7677          }          }
7678        } elsif ({        } elsif ({
7679                  address => 1, blockquote => 1, center => 1, dir => 1,                  ## NOTE: End tags for non-phrasing flow content elements
7680                  div => 1, dl => 1, fieldset => 1, listing => 1,  
7681                  menu => 1, ol => 1, pre => 1, ul => 1,                  ## NOTE: The normal ones
7682                    address => 1, article => 1, aside => 1, blockquote => 1,
7683                    center => 1, datagrid => 1, details => 1, dialog => 1,
7684                    dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,
7685                    footer => 1, header => 1, listing => 1, menu => 1, nav => 1,
7686                    ol => 1, pre => 1, section => 1, ul => 1,
7687    
7688                    ## NOTE: As normal, but ... optional tags
7689                  dd => 1, dt => 1, li => 1,                  dd => 1, dt => 1, li => 1,
7690    
7691                  applet => 1, button => 1, marquee => 1, object => 1,                  applet => 1, button => 1, marquee => 1, object => 1,
7692                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7693            ## NOTE: Code for <li> start tags includes "as if </li>" code.
7694            ## Code for <dt> or <dd> start tags includes "as if </dt> or
7695            ## </dd>" code.
7696    
7697          ## has an element in scope          ## has an element in scope
7698          my $i;          my $i;
7699          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
# Line 7530  sub _tree_construction_main ($) { Line 7720  sub _tree_construction_main ($) {
7720                    dd => ($token->{tag_name} ne 'dd'),                    dd => ($token->{tag_name} ne 'dd'),
7721                    dt => ($token->{tag_name} ne 'dt'),                    dt => ($token->{tag_name} ne 'dt'),
7722                    li => ($token->{tag_name} ne 'li'),                    li => ($token->{tag_name} ne 'li'),
7723                      option => 1,
7724                      optgroup => 1,
7725                    p => 1,                    p => 1,
7726                    rt => 1,                    rt => 1,
7727                    rp => 1,                    rp => 1,
# Line 7562  sub _tree_construction_main ($) { Line 7754  sub _tree_construction_main ($) {
7754          !!!next-token;          !!!next-token;
7755          next B;          next B;
7756        } elsif ($token->{tag_name} eq 'form') {        } elsif ($token->{tag_name} eq 'form') {
7757            ## NOTE: As normal, but interacts with the form element pointer
7758    
7759          undef $self->{form_element};          undef $self->{form_element};
7760    
7761          ## has an element in scope          ## has an element in scope
# Line 7609  sub _tree_construction_main ($) { Line 7803  sub _tree_construction_main ($) {
7803          !!!next-token;          !!!next-token;
7804          next B;          next B;
7805        } elsif ({        } elsif ({
7806                    ## NOTE: As normal, except acts as a closer for any ...
7807                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,
7808                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7809          ## has an element in scope          ## has an element in scope
# Line 7654  sub _tree_construction_main ($) { Line 7849  sub _tree_construction_main ($) {
7849          !!!next-token;          !!!next-token;
7850          next B;          next B;
7851        } elsif ($token->{tag_name} eq 'p') {        } elsif ($token->{tag_name} eq 'p') {
7852            ## NOTE: As normal, except </p> implies <p> and ...
7853    
7854          ## has an element in scope          ## has an element in scope
7855            my $non_optional;
7856          my $i;          my $i;
7857          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7858            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
# Line 7665  sub _tree_construction_main ($) { Line 7863  sub _tree_construction_main ($) {
7863            } elsif ($node->[1] & SCOPING_EL) {            } elsif ($node->[1] & SCOPING_EL) {
7864              !!!cp ('t411.1');              !!!cp ('t411.1');
7865              last INSCOPE;              last INSCOPE;
7866              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7867                ## NOTE: |END_TAG_OPTIONAL_EL| includes "p"
7868                !!!cp ('t411.2');
7869                #
7870              } else {
7871                !!!cp ('t411.3');
7872                $non_optional ||= $node;
7873                #
7874            }            }
7875          } # INSCOPE          } # INSCOPE
7876    
7877          if (defined $i) {          if (defined $i) {
7878            if ($self->{open_elements}->[-1]->[0]->manakai_local_name            ## 1. Generate implied end tags
7879                    ne $token->{tag_name}) {            #
7880    
7881              ## 2. If current node != "p", parse error
7882              if ($non_optional) {
7883              !!!cp ('t412.1');              !!!cp ('t412.1');
7884              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
7885                              text => $self->{open_elements}->[-1]->[0]                              text => $non_optional->[0]->manakai_local_name,
                                 ->manakai_local_name,  
7886                              token => $token);                              token => $token);
7887            } else {            } else {
7888              !!!cp ('t414.1');              !!!cp ('t414.1');
7889            }            }
7890    
7891              ## 3. Pop
7892            splice @{$self->{open_elements}}, $i;            splice @{$self->{open_elements}}, $i;
7893          } else {          } else {
7894            !!!cp ('t413.1');            !!!cp ('t413.1');
# Line 7699  sub _tree_construction_main ($) { Line 7908  sub _tree_construction_main ($) {
7908        } elsif ({        } elsif ({
7909                  a => 1,                  a => 1,
7910                  b => 1, big => 1, em => 1, font => 1, i => 1,                  b => 1, big => 1, em => 1, font => 1, i => 1,
7911                  nobr => 1, s => 1, small => 1, strile => 1,                  nobr => 1, s => 1, small => 1, strike => 1,
7912                  strong => 1, tt => 1, u => 1,                  strong => 1, tt => 1, u => 1,
7913                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7914          !!!cp ('t427');          !!!cp ('t427');
# Line 7720  sub _tree_construction_main ($) { Line 7929  sub _tree_construction_main ($) {
7929          ## Ignore the token.          ## Ignore the token.
7930          !!!next-token;          !!!next-token;
7931          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  
           
7932        } else {        } else {
7933            if ($token->{tag_name} eq 'sarcasm') {
7934              sleep 0.001; # take a deep breath
7935            }
7936    
7937          ## Step 1          ## Step 1
7938          my $node_i = -1;          my $node_i = -1;
7939          my $node = $self->{open_elements}->[$node_i];          my $node = $self->{open_elements}->[$node_i];
7940    
7941          ## Step 2          ## Step 2
7942          S2: {          S2: {
7943            if ($node->[0]->manakai_local_name eq $token->{tag_name}) {            my $node_tag_name = $node->[0]->manakai_local_name;
7944              $node_tag_name =~ tr/A-Z/a-z/; # for SVG camelCase tag names
7945              if ($node_tag_name eq $token->{tag_name}) {
7946              ## Step 1              ## Step 1
7947              ## generate implied end tags              ## generate implied end tags
7948              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
# Line 7761  sub _tree_construction_main ($) { Line 7955  sub _tree_construction_main ($) {
7955              }              }
7956                    
7957              ## Step 2              ## Step 2
7958              if ($self->{open_elements}->[-1]->[0]->manakai_local_name              my $current_tag_name
7959                      ne $token->{tag_name}) {                  = $self->{open_elements}->[-1]->[0]->manakai_local_name;
7960                $current_tag_name =~ tr/A-Z/a-z/;
7961                if ($current_tag_name ne $token->{tag_name}) {
7962                !!!cp ('t431');                !!!cp ('t431');
7963                ## NOTE: <x><y></x>                ## NOTE: <x><y></x>
7964                !!!parse-error (type => 'not closed',                !!!parse-error (type => 'not closed',
# Line 7790  sub _tree_construction_main ($) { Line 7986  sub _tree_construction_main ($) {
7986                ## Ignore the token                ## Ignore the token
7987                !!!next-token;                !!!next-token;
7988                last S2;                last S2;
             }  
7989    
7990                  ## NOTE: |<span><dd></span>a|: In Safari 3.1.2 and Opera
7991                  ## 9.27, "a" is a child of <dd> (conforming).  In
7992                  ## Firefox 3.0.2, "a" is a child of <body>.  In WinIE 7,
7993                  ## "a" is a child of both <body> and <dd>.
7994                }
7995                
7996              !!!cp ('t434');              !!!cp ('t434');
7997            }            }
7998                        
# Line 8027  sub set_inner_html ($$$$;$) { Line 8228  sub set_inner_html ($$$$;$) {
8228      push @{$p->{open_elements}}, [$root, $el_category->{html}];      push @{$p->{open_elements}}, [$root, $el_category->{html}];
8229    
8230      undef $p->{head_element};      undef $p->{head_element};
8231        undef $p->{head_element_inserted};
8232    
8233      ## Step 6 # MUST      ## Step 6 # MUST
8234      $p->_reset_insertion_mode;      $p->_reset_insertion_mode;

Legend:
Removed from v.1.185  
changed lines
  Added in v.1.204

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24