/[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.183 by wakaba, Mon Sep 15 08:09:39 2008 UTC revision 1.198 by wakaba, Sat Oct 4 08:58:02 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 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 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 726  sub parse_char_stream ($$$;$$) { Line 755  sub parse_char_stream ($$$;$$) {
755            $self->{char_buffer_pos} += $count;            $self->{char_buffer_pos} += $count;
756            $self->{line_prev} = $self->{line};            $self->{line_prev} = $self->{line};
757            $self->{column_prev} = $self->{column} - 1;            $self->{column_prev} = $self->{column} - 1;
           $self->{prev_char} = [-1, -1, -1];  
758            $self->{nc} = -1;            $self->{nc} = -1;
759          }          }
760          return $count;          return $count;
# Line 739  sub parse_char_stream ($$$;$$) { Line 767  sub parse_char_stream ($$$;$$) {
767          $self->{column} += $count;          $self->{column} += $count;
768          $self->{line_prev} = $self->{line};          $self->{line_prev} = $self->{line};
769          $self->{column_prev} = $self->{column} - 1;          $self->{column_prev} = $self->{column} - 1;
         $self->{prev_char} = [-1, -1, -1];  
770          $self->{nc} = -1;          $self->{nc} = -1;
771        }        }
772        return $count;        return $count;
# Line 855  sub CDATA_SECTION_STATE () { 35 } Line 882  sub CDATA_SECTION_STATE () { 35 }
882  sub MD_HYPHEN_STATE () { 36 } # "markup declaration open state" in the spec  sub MD_HYPHEN_STATE () { 36 } # "markup declaration open state" in the spec
883  sub MD_DOCTYPE_STATE () { 37 } # "markup declaration open state" in the spec  sub MD_DOCTYPE_STATE () { 37 } # "markup declaration open state" in the spec
884  sub MD_CDATA_STATE () { 38 } # "markup declaration open state" in the spec  sub MD_CDATA_STATE () { 38 } # "markup declaration open state" in the spec
885  sub CDATA_PCDATA_CLOSE_TAG_STATE () { 39 } # "close tag open state" in the spec  sub CDATA_RCDATA_CLOSE_TAG_STATE () { 39 } # "close tag open state" in the spec
886  sub CDATA_SECTION_MSE1_STATE () { 40 } # "CDATA section state" in the spec  sub CDATA_SECTION_MSE1_STATE () { 40 } # "CDATA section state" in the spec
887  sub CDATA_SECTION_MSE2_STATE () { 41 } # "CDATA section state" in the spec  sub CDATA_SECTION_MSE2_STATE () { 41 } # "CDATA section state" in the spec
888  sub PUBLIC_STATE () { 42 } # "after DOCTYPE name state" in the spec  sub PUBLIC_STATE () { 42 } # "after DOCTYPE name state" in the spec
# Line 869  sub NCR_NUM_STATE () { 46 } Line 896  sub NCR_NUM_STATE () { 46 }
896  sub HEXREF_X_STATE () { 47 }  sub HEXREF_X_STATE () { 47 }
897  sub HEXREF_HEX_STATE () { 48 }  sub HEXREF_HEX_STATE () { 48 }
898  sub ENTITY_NAME_STATE () { 49 }  sub ENTITY_NAME_STATE () { 49 }
899    sub PCDATA_STATE () { 50 } # "data state" in the spec
900    
901  sub DOCTYPE_TOKEN () { 1 }  sub DOCTYPE_TOKEN () { 1 }
902  sub COMMENT_TOKEN () { 2 }  sub COMMENT_TOKEN () { 2 }
# Line 932  sub _initialize_tokenizer ($) { Line 960  sub _initialize_tokenizer ($) {
960    delete $self->{self_closing};    delete $self->{self_closing};
961    $self->{char_buffer} = '';    $self->{char_buffer} = '';
962    $self->{char_buffer_pos} = 0;    $self->{char_buffer_pos} = 0;
   $self->{prev_char} = [-1, -1, -1];  
963    $self->{nc} = -1; # next input character    $self->{nc} = -1; # next input character
964    #$self->{next_nc}    #$self->{next_nc}
965    !!!next-input-character;    !!!next-input-character;
# Line 968  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 985  sub _get_next_token ($) { Line 1021  sub _get_next_token ($) {
1021    }    }
1022    
1023    A: {    A: {
1024      if ($self->{state} == DATA_STATE) {      if ($self->{state} == PCDATA_STATE) {
1025          ## NOTE: Same as |DATA_STATE|, but only for |PCDATA| content model.
1026    
1027          if ($self->{nc} == 0x0026) { # &
1028            !!!cp (0.1);
1029            ## NOTE: In the spec, the tokenizer is switched to the
1030            ## "entity data state".  In this implementation, the tokenizer
1031            ## is switched to the |ENTITY_STATE|, which is an implementation
1032            ## of the "consume a character reference" algorithm.
1033            $self->{entity_add} = -1;
1034            $self->{prev_state} = DATA_STATE;
1035            $self->{state} = ENTITY_STATE;
1036            !!!next-input-character;
1037            redo A;
1038          } elsif ($self->{nc} == 0x003C) { # <
1039            !!!cp (0.2);
1040            $self->{state} = TAG_OPEN_STATE;
1041            !!!next-input-character;
1042            redo A;
1043          } elsif ($self->{nc} == -1) {
1044            !!!cp (0.3);
1045            !!!emit ({type => END_OF_FILE_TOKEN,
1046                      line => $self->{line}, column => $self->{column}});
1047            last A; ## TODO: ok?
1048          } else {
1049            !!!cp (0.4);
1050            #
1051          }
1052    
1053          # Anything else
1054          my $token = {type => CHARACTER_TOKEN,
1055                       data => chr $self->{nc},
1056                       line => $self->{line}, column => $self->{column},
1057                      };
1058          $self->{read_until}->($token->{data}, q[<&], length $token->{data});
1059    
1060          ## Stay in the state.
1061          !!!next-input-character;
1062          !!!emit ($token);
1063          redo A;
1064        } elsif ($self->{state} == DATA_STATE) {
1065          $self->{s_kwd} = '' unless defined $self->{s_kwd};
1066        if ($self->{nc} == 0x0026) { # &        if ($self->{nc} == 0x0026) { # &
1067            $self->{s_kwd} = '';
1068          if ($self->{content_model} & CM_ENTITY and # PCDATA | RCDATA          if ($self->{content_model} & CM_ENTITY and # PCDATA | RCDATA
1069              not $self->{escape}) {              not $self->{escape}) {
1070            !!!cp (1);            !!!cp (1);
# Line 1005  sub _get_next_token ($) { Line 1083  sub _get_next_token ($) {
1083          }          }
1084        } elsif ($self->{nc} == 0x002D) { # -        } elsif ($self->{nc} == 0x002D) { # -
1085          if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA          if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA
1086            unless ($self->{escape}) {            $self->{s_kwd} .= '-';
1087              if ($self->{prev_char}->[0] == 0x002D and # -            
1088                  $self->{prev_char}->[1] == 0x0021 and # !            if ($self->{s_kwd} eq '<!--') {
1089                  $self->{prev_char}->[2] == 0x003C) { # <              !!!cp (3);
1090                !!!cp (3);              $self->{escape} = 1; # unless $self->{escape};
1091                $self->{escape} = 1;              $self->{s_kwd} = '--';
1092              } else {              #
1093                !!!cp (4);            } elsif ($self->{s_kwd} eq '---') {
1094              }              !!!cp (4);
1095                $self->{s_kwd} = '--';
1096                #
1097            } else {            } else {
1098              !!!cp (5);              !!!cp (5);
1099                #
1100            }            }
1101          }          }
1102                    
1103          #          #
1104          } elsif ($self->{nc} == 0x0021) { # !
1105            if (length $self->{s_kwd}) {
1106              !!!cp (5.1);
1107              $self->{s_kwd} .= '!';
1108              #
1109            } else {
1110              !!!cp (5.2);
1111              #$self->{s_kwd} = '';
1112              #
1113            }
1114            #
1115        } elsif ($self->{nc} == 0x003C) { # <        } elsif ($self->{nc} == 0x003C) { # <
1116          if ($self->{content_model} & CM_FULL_MARKUP or # PCDATA          if ($self->{content_model} & CM_FULL_MARKUP or # PCDATA
1117              (($self->{content_model} & CM_LIMITED_MARKUP) and # CDATA | RCDATA              (($self->{content_model} & CM_LIMITED_MARKUP) and # CDATA | RCDATA
# Line 1030  sub _get_next_token ($) { Line 1122  sub _get_next_token ($) {
1122            redo A;            redo A;
1123          } else {          } else {
1124            !!!cp (7);            !!!cp (7);
1125              $self->{s_kwd} = '';
1126            #            #
1127          }          }
1128        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
1129          if ($self->{escape} and          if ($self->{escape} and
1130              ($self->{content_model} & CM_LIMITED_MARKUP)) { # RCDATA | CDATA              ($self->{content_model} & CM_LIMITED_MARKUP)) { # RCDATA | CDATA
1131            if ($self->{prev_char}->[0] == 0x002D and # -            if ($self->{s_kwd} eq '--') {
               $self->{prev_char}->[1] == 0x002D) { # -  
1132              !!!cp (8);              !!!cp (8);
1133              delete $self->{escape};              delete $self->{escape};
1134            } else {            } else {
# Line 1046  sub _get_next_token ($) { Line 1138  sub _get_next_token ($) {
1138            !!!cp (10);            !!!cp (10);
1139          }          }
1140                    
1141            $self->{s_kwd} = '';
1142          #          #
1143        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1144          !!!cp (11);          !!!cp (11);
1145            $self->{s_kwd} = '';
1146          !!!emit ({type => END_OF_FILE_TOKEN,          !!!emit ({type => END_OF_FILE_TOKEN,
1147                    line => $self->{line}, column => $self->{column}});                    line => $self->{line}, column => $self->{column}});
1148          last A; ## TODO: ok?          last A; ## TODO: ok?
1149        } else {        } else {
1150          !!!cp (12);          !!!cp (12);
1151            $self->{s_kwd} = '';
1152            #
1153        }        }
1154    
1155        # Anything else        # Anything else
1156        my $token = {type => CHARACTER_TOKEN,        my $token = {type => CHARACTER_TOKEN,
1157                     data => chr $self->{nc},                     data => chr $self->{nc},
1158                     line => $self->{line}, column => $self->{column},                     line => $self->{line}, column => $self->{column},
1159                    };                    };
1160        $self->{read_until}->($token->{data}, q[-!<>&], length $token->{data});        if ($self->{read_until}->($token->{data}, q[-!<>&],
1161                                    length $token->{data})) {
1162            $self->{s_kwd} = '';
1163          }
1164    
1165        ## Stay in the data state        ## Stay in the data state.
1166          if ($self->{content_model} == PCDATA_CONTENT_MODEL) {
1167            !!!cp (13);
1168            $self->{state} = PCDATA_STATE;
1169          } else {
1170            !!!cp (14);
1171            ## Stay in the state.
1172          }
1173        !!!next-input-character;        !!!next-input-character;
   
1174        !!!emit ($token);        !!!emit ($token);
   
1175        redo A;        redo A;
1176      } elsif ($self->{state} == TAG_OPEN_STATE) {      } elsif ($self->{state} == TAG_OPEN_STATE) {
1177        if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA        if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA
# Line 1075  sub _get_next_token ($) { Line 1180  sub _get_next_token ($) {
1180            !!!next-input-character;            !!!next-input-character;
1181            $self->{state} = CLOSE_TAG_OPEN_STATE;            $self->{state} = CLOSE_TAG_OPEN_STATE;
1182            redo A;            redo A;
1183            } elsif ($self->{nc} == 0x0021) { # !
1184              !!!cp (15.1);
1185              $self->{s_kwd} = '<' unless $self->{escape};
1186              #
1187          } else {          } else {
1188            !!!cp (16);            !!!cp (16);
1189            ## reconsume            #
           $self->{state} = DATA_STATE;  
   
           !!!emit ({type => CHARACTER_TOKEN, data => '<',  
                     line => $self->{line_prev},  
                     column => $self->{column_prev},  
                    });  
   
           redo A;  
1190          }          }
1191    
1192            ## reconsume
1193            $self->{state} = DATA_STATE;
1194            !!!emit ({type => CHARACTER_TOKEN, data => '<',
1195                      line => $self->{line_prev},
1196                      column => $self->{column_prev},
1197                     });
1198            redo A;
1199        } elsif ($self->{content_model} & CM_FULL_MARKUP) { # PCDATA        } elsif ($self->{content_model} & CM_FULL_MARKUP) { # PCDATA
1200          if ($self->{nc} == 0x0021) { # !          if ($self->{nc} == 0x0021) { # !
1201            !!!cp (17);            !!!cp (17);
# Line 1165  sub _get_next_token ($) { Line 1274  sub _get_next_token ($) {
1274        }        }
1275      } elsif ($self->{state} == CLOSE_TAG_OPEN_STATE) {      } elsif ($self->{state} == CLOSE_TAG_OPEN_STATE) {
1276        ## NOTE: The "close tag open state" in the spec is implemented as        ## NOTE: The "close tag open state" in the spec is implemented as
1277        ## |CLOSE_TAG_OPEN_STATE| and |CDATA_PCDATA_CLOSE_TAG_STATE|.        ## |CLOSE_TAG_OPEN_STATE| and |CDATA_RCDATA_CLOSE_TAG_STATE|.
1278    
1279        my ($l, $c) = ($self->{line_prev}, $self->{column_prev} - 1); # "<"of"</"        my ($l, $c) = ($self->{line_prev}, $self->{column_prev} - 1); # "<"of"</"
1280        if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA        if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA
1281          if (defined $self->{last_stag_name}) {          if (defined $self->{last_stag_name}) {
1282            $self->{state} = CDATA_PCDATA_CLOSE_TAG_STATE;            $self->{state} = CDATA_RCDATA_CLOSE_TAG_STATE;
1283            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1284            ## Reconsume.            ## Reconsume.
1285            redo A;            redo A;
# Line 1241  sub _get_next_token ($) { Line 1350  sub _get_next_token ($) {
1350          ## "bogus comment state" entry.          ## "bogus comment state" entry.
1351          redo A;          redo A;
1352        }        }
1353      } elsif ($self->{state} == CDATA_PCDATA_CLOSE_TAG_STATE) {      } elsif ($self->{state} == CDATA_RCDATA_CLOSE_TAG_STATE) {
1354        my $ch = substr $self->{last_stag_name}, length $self->{s_kwd}, 1;        my $ch = substr $self->{last_stag_name}, length $self->{s_kwd}, 1;
1355        if (length $ch) {        if (length $ch) {
1356          my $CH = $ch;          my $CH = $ch;
# Line 1265  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 1297  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 1373  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 1473  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 1560  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 1651  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 1836  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 1922  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 2367  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 2384  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 2415  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 2458  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 2585  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 2715  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 2764  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 2893  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 3028  sub _get_next_token ($) { Line 3076  sub _get_next_token ($) {
3076          redo A;          redo A;
3077        }        }
3078      } elsif ($self->{state} == ENTITY_STATE) {      } elsif ($self->{state} == ENTITY_STATE) {
3079        if ({        if ($is_space->{$self->{nc}} or
3080          0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, # HT, LF, VT, FF,            {
3081          0x0020 => 1, 0x003C => 1, 0x0026 => 1, -1 => 1, # SP, <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
3082          $self->{entity_add} => 1,              $self->{entity_add} => 1,
3083        }->{$self->{nc}}) {            }->{$self->{nc}}) {
3084          !!!cp (1001);          !!!cp (1001);
3085          ## Don't consume          ## Don't consume
3086          ## No error          ## No error
# Line 3151  sub _get_next_token ($) { Line 3199  sub _get_next_token ($) {
3199        my $code = $self->{s_kwd};        my $code = $self->{s_kwd};
3200        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3201        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3202        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {        if ($charref_map->{$code}) {
3203          !!!cp (1015);          !!!cp (1015);
3204          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3205                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
3206                          line => $l, column => $c);                          line => $l, column => $c);
3207          $code = 0xFFFD;          $code = $charref_map->{$code};
3208        } elsif ($code > 0x10FFFF) {        } elsif ($code > 0x10FFFF) {
3209          !!!cp (1016);          !!!cp (1016);
3210          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3211                          text => (sprintf 'U-%08X', $code),                          text => (sprintf 'U-%08X', $code),
3212                          line => $l, column => $c);                          line => $l, column => $c);
3213          $code = 0xFFFD;          $code = 0xFFFD;
       } elsif ($code == 0x000D) {  
         !!!cp (1017);  
         !!!parse-error (type => 'CR character reference',  
                         line => $l, column => $c);  
         $code = 0x000A;  
       } elsif (0x80 <= $code and $code <= 0x9F) {  
         !!!cp (1018);  
         !!!parse-error (type => 'C1 character reference',  
                         text => (sprintf 'U+%04X', $code),  
                         line => $l, column => $c);  
         $code = $c1_entity_char->{$code};  
3214        }        }
3215    
3216        if ($self->{prev_state} == DATA_STATE) {        if ($self->{prev_state} == DATA_STATE) {
# Line 3270  sub _get_next_token ($) { Line 3307  sub _get_next_token ($) {
3307        my $code = $self->{s_kwd};        my $code = $self->{s_kwd};
3308        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3309        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3310        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {        if ($charref_map->{$code}) {
3311          !!!cp (1008);          !!!cp (1008);
3312          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3313                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
3314                          line => $l, column => $c);                          line => $l, column => $c);
3315          $code = 0xFFFD;          $code = $charref_map->{$code};
3316        } elsif ($code > 0x10FFFF) {        } elsif ($code > 0x10FFFF) {
3317          !!!cp (1009);          !!!cp (1009);
3318          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3319                          text => (sprintf 'U-%08X', $code),                          text => (sprintf 'U-%08X', $code),
3320                          line => $l, column => $c);                          line => $l, column => $c);
3321          $code = 0xFFFD;          $code = 0xFFFD;
       } elsif ($code == 0x000D) {  
         !!!cp (1010);  
         !!!parse-error (type => 'CR character reference', line => $l, column => $c);  
         $code = 0x000A;  
       } elsif (0x80 <= $code and $code <= 0x9F) {  
         !!!cp (1011);  
         !!!parse-error (type => 'C1 character reference', text => (sprintf 'U+%04X', $code), line => $l, column => $c);  
         $code = $c1_entity_char->{$code};  
3322        }        }
3323    
3324        if ($self->{prev_state} == DATA_STATE) {        if ($self->{prev_state} == DATA_STATE) {
# Line 3630  sub _tree_construction_initial ($) { Line 3659  sub _tree_construction_initial ($) {
3659        !!!ack-later;        !!!ack-later;
3660        return;        return;
3661      } elsif ($token->{type} == CHARACTER_TOKEN) {      } elsif ($token->{type} == CHARACTER_TOKEN) {
3662        if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { # \x0D        if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
3663          ## Ignore the token          ## Ignore the token
3664    
3665          unless (length $token->{data}) {          unless (length $token->{data}) {
# Line 3687  sub _tree_construction_root_element ($) Line 3716  sub _tree_construction_root_element ($)
3716          !!!next-token;          !!!next-token;
3717          redo B;          redo B;
3718        } elsif ($token->{type} == CHARACTER_TOKEN) {        } elsif ($token->{type} == CHARACTER_TOKEN) {
3719          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { # \x0D          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
3720            ## Ignore the token.            ## Ignore the token.
3721    
3722            unless (length $token->{data}) {            unless (length $token->{data}) {
# Line 3754  sub _tree_construction_root_element ($) Line 3783  sub _tree_construction_root_element ($)
3783      ## NOTE: Reprocess the token.      ## NOTE: Reprocess the token.
3784      !!!ack-later;      !!!ack-later;
3785      return; ## Go to the "before head" insertion mode.      return; ## Go to the "before head" insertion mode.
   
     ## ISSUE: There is an issue in the spec  
3786    } # B    } # B
3787    
3788    die "$0: _tree_construction_root_element: This should never be reached";    die "$0: _tree_construction_root_element: This should never be reached";
# Line 4501  sub _tree_construction_main ($) { Line 4528  sub _tree_construction_main ($) {
4528    
4529      if ($self->{insertion_mode} & HEAD_IMS) {      if ($self->{insertion_mode} & HEAD_IMS) {
4530        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
4531          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
4532            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4533              !!!cp ('t88.2');              !!!cp ('t88.2');
4534              $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);              $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
# Line 4626  sub _tree_construction_main ($) { Line 4653  sub _tree_construction_main ($) {
4653                  !!!cp ('t101');                  !!!cp ('t101');
4654                }                }
4655                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4656                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.                pop @{$self->{open_elements}};
4657                pop @{$self->{open_elements}} # <head>                pop @{$self->{open_elements}} # <head>
4658                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4659                !!!nack ('t101.1');                !!!nack ('t101.1');
4660                !!!next-token;                !!!next-token;
4661                next B;                next B;
4662              } elsif ($token->{tag_name} eq 'link') {          } elsif ($token->{tag_name} eq 'link') {
4663                ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
4664                if ($self->{insertion_mode} == AFTER_HEAD_IM) {            if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4665                  !!!cp ('t102');              !!!cp ('t102');
4666                  !!!parse-error (type => 'after head',              !!!parse-error (type => 'after head',
4667                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
4668                  push @{$self->{open_elements}},              push @{$self->{open_elements}},
4669                      [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4670                } else {            } else {
4671                  !!!cp ('t103');              !!!cp ('t103');
4672                }            }
4673                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4674                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.            pop @{$self->{open_elements}};
4675                pop @{$self->{open_elements}} # <head>            pop @{$self->{open_elements}} # <head>
4676                    if $self->{insertion_mode} == AFTER_HEAD_IM;                if $self->{insertion_mode} == AFTER_HEAD_IM;
4677                !!!ack ('t103.1');            !!!ack ('t103.1');
4678                !!!next-token;            !!!next-token;
4679                next B;            next B;
4680            } elsif ($token->{tag_name} eq 'command' or
4681                     $token->{tag_name} eq 'eventsource') {
4682              if ($self->{insertion_mode} == IN_HEAD_IM) {
4683                ## NOTE: If the insertion mode at the time of the emission
4684                ## of the token was "before head", $self->{insertion_mode}
4685                ## is already changed to |IN_HEAD_IM|.
4686    
4687                ## NOTE: There is a "as if in head" code clone.
4688                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4689                pop @{$self->{open_elements}};
4690                pop @{$self->{open_elements}} # <head>
4691                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4692                !!!ack ('t103.2');
4693                !!!next-token;
4694                next B;
4695              } else {
4696                ## NOTE: "in head noscript" or "after head" insertion mode
4697                ## - in these cases, these tags are treated as same as
4698                ## normal in-body tags.
4699                !!!cp ('t103.3');
4700                #
4701              }
4702              } elsif ($token->{tag_name} eq 'meta') {              } elsif ($token->{tag_name} eq 'meta') {
4703                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
4704                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
# Line 4662  sub _tree_construction_main ($) { Line 4711  sub _tree_construction_main ($) {
4711                  !!!cp ('t105');                  !!!cp ('t105');
4712                }                }
4713                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4714                my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.                my $meta_el = pop @{$self->{open_elements}};
4715    
4716                unless ($self->{confident}) {                unless ($self->{confident}) {
4717                  if ($token->{attributes}->{charset}) {                  if ($token->{attributes}->{charset}) {
# Line 4680  sub _tree_construction_main ($) { Line 4729  sub _tree_construction_main ($) {
4729                  } elsif ($token->{attributes}->{content}) {                  } elsif ($token->{attributes}->{content}) {
4730                    if ($token->{attributes}->{content}->{value}                    if ($token->{attributes}->{content}->{value}
4731                        =~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt]                        =~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt]
4732                            [\x09-\x0D\x20]*=                            [\x09\x0A\x0C\x0D\x20]*=
4733                            [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                            [\x09\x0A\x0C\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
4734                            ([^"'\x09-\x0D\x20][^\x09-\x0D\x20\x3B]*))/x) {                            ([^"'\x09\x0A\x0C\x0D\x20]
4735                               [^\x09\x0A\x0C\x0D\x20\x3B]*))/x) {
4736                      !!!cp ('t107');                      !!!cp ('t107');
4737                      ## NOTE: Whether the encoding is supported or not is handled                      ## NOTE: Whether the encoding is supported or not is handled
4738                      ## in the {change_encoding} callback.                      ## in the {change_encoding} callback.
# Line 5118  sub _tree_construction_main ($) { Line 5168  sub _tree_construction_main ($) {
5168        } else {        } else {
5169          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
5170        }        }
   
           ## ISSUE: An issue in the spec.  
5171      } elsif ($self->{insertion_mode} & BODY_IMS) {      } elsif ($self->{insertion_mode} & BODY_IMS) {
5172            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
5173              !!!cp ('t150');              !!!cp ('t150');
# Line 5491  sub _tree_construction_main ($) { Line 5539  sub _tree_construction_main ($) {
5539      } elsif ($self->{insertion_mode} & TABLE_IMS) {      } elsif ($self->{insertion_mode} & TABLE_IMS) {
5540        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
5541          if (not $open_tables->[-1]->[1] and # tainted          if (not $open_tables->[-1]->[1] and # tainted
5542              $token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {              $token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
5543            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
5544                                
5545            unless (length $token->{data}) {            unless (length $token->{data}) {
# Line 6175  sub _tree_construction_main ($) { Line 6223  sub _tree_construction_main ($) {
6223        }        }
6224      } elsif ($self->{insertion_mode} == IN_COLUMN_GROUP_IM) {      } elsif ($self->{insertion_mode} == IN_COLUMN_GROUP_IM) {
6225            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
6226              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {              if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
6227                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
6228                unless (length $token->{data}) {                unless (length $token->{data}) {
6229                  !!!cp ('t260');                  !!!cp ('t260');
# Line 6516  sub _tree_construction_main ($) { Line 6564  sub _tree_construction_main ($) {
6564        }        }
6565      } elsif ($self->{insertion_mode} & BODY_AFTER_IMS) {      } elsif ($self->{insertion_mode} & BODY_AFTER_IMS) {
6566        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
6567          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
6568            my $data = $1;            my $data = $1;
6569            ## As if in body            ## As if in body
6570            $reconstruct_active_formatting_elements->($insert_to_current);            $reconstruct_active_formatting_elements->($insert_to_current);
# Line 6533  sub _tree_construction_main ($) { Line 6581  sub _tree_construction_main ($) {
6581          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
6582            !!!cp ('t301');            !!!cp ('t301');
6583            !!!parse-error (type => 'after html:#text', token => $token);            !!!parse-error (type => 'after html:#text', token => $token);
6584              #
           ## Reprocess in the "after body" insertion mode.  
6585          } else {          } else {
6586            !!!cp ('t302');            !!!cp ('t302');
6587              ## "after body" insertion mode
6588              !!!parse-error (type => 'after body:#text', token => $token);
6589              #
6590          }          }
           
         ## "after body" insertion mode  
         !!!parse-error (type => 'after body:#text', token => $token);  
6591    
6592          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
6593          ## reprocess          ## reprocess
# Line 6550  sub _tree_construction_main ($) { Line 6597  sub _tree_construction_main ($) {
6597            !!!cp ('t303');            !!!cp ('t303');
6598            !!!parse-error (type => 'after html',            !!!parse-error (type => 'after html',
6599                            text => $token->{tag_name}, token => $token);                            text => $token->{tag_name}, token => $token);
6600                        #
           ## Reprocess in the "after body" insertion mode.  
6601          } else {          } else {
6602            !!!cp ('t304');            !!!cp ('t304');
6603              ## "after body" insertion mode
6604              !!!parse-error (type => 'after body',
6605                              text => $token->{tag_name}, token => $token);
6606              #
6607          }          }
6608    
         ## "after body" insertion mode  
         !!!parse-error (type => 'after body',  
                         text => $token->{tag_name}, token => $token);  
   
6609          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
6610          !!!ack-later;          !!!ack-later;
6611          ## reprocess          ## reprocess
# Line 6570  sub _tree_construction_main ($) { Line 6616  sub _tree_construction_main ($) {
6616            !!!parse-error (type => 'after html:/',            !!!parse-error (type => 'after html:/',
6617                            text => $token->{tag_name}, token => $token);                            text => $token->{tag_name}, token => $token);
6618                        
6619            $self->{insertion_mode} = AFTER_BODY_IM;            $self->{insertion_mode} = IN_BODY_IM;
6620            ## Reprocess in the "after body" insertion mode.            ## Reprocess.
6621              next B;
6622          } else {          } else {
6623            !!!cp ('t306');            !!!cp ('t306');
6624          }          }
# Line 6609  sub _tree_construction_main ($) { Line 6656  sub _tree_construction_main ($) {
6656        }        }
6657      } elsif ($self->{insertion_mode} & FRAME_IMS) {      } elsif ($self->{insertion_mode} & FRAME_IMS) {
6658        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
6659          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
6660            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
6661                        
6662            unless (length $token->{data}) {            unless (length $token->{data}) {
# Line 6619  sub _tree_construction_main ($) { Line 6666  sub _tree_construction_main ($) {
6666            }            }
6667          }          }
6668                    
6669          if ($token->{data} =~ s/^[^\x09\x0A\x0B\x0C\x20]+//) {          if ($token->{data} =~ s/^[^\x09\x0A\x0C\x20]+//) {
6670            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
6671              !!!cp ('t311');              !!!cp ('t311');
6672              !!!parse-error (type => 'in frameset:#text', token => $token);              !!!parse-error (type => 'in frameset:#text', token => $token);
# Line 6748  sub _tree_construction_main ($) { Line 6795  sub _tree_construction_main ($) {
6795        } else {        } else {
6796          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
6797        }        }
   
       ## ISSUE: An issue in spec here  
6798      } else {      } else {
6799        die "$0: $self->{insertion_mode}: Unknown insertion mode";        die "$0: $self->{insertion_mode}: Unknown insertion mode";
6800      }      }
# Line 6767  sub _tree_construction_main ($) { Line 6812  sub _tree_construction_main ($) {
6812          $parse_rcdata->(CDATA_CONTENT_MODEL);          $parse_rcdata->(CDATA_CONTENT_MODEL);
6813          next B;          next B;
6814        } elsif ({        } elsif ({
6815                  base => 1, link => 1,                  base => 1, command => 1, eventsource => 1, link => 1,
6816                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
6817          !!!cp ('t334');          !!!cp ('t334');
6818          ## 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
6819          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6820          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          pop @{$self->{open_elements}};
6821          !!!ack ('t334.1');          !!!ack ('t334.1');
6822          !!!next-token;          !!!next-token;
6823          next B;          next B;
6824        } elsif ($token->{tag_name} eq 'meta') {        } elsif ($token->{tag_name} eq 'meta') {
6825          ## 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
6826          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6827          my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          my $meta_el = pop @{$self->{open_elements}};
6828    
6829          unless ($self->{confident}) {          unless ($self->{confident}) {
6830            if ($token->{attributes}->{charset}) {            if ($token->{attributes}->{charset}) {
# Line 6796  sub _tree_construction_main ($) { Line 6841  sub _tree_construction_main ($) {
6841            } elsif ($token->{attributes}->{content}) {            } elsif ($token->{attributes}->{content}) {
6842              if ($token->{attributes}->{content}->{value}              if ($token->{attributes}->{content}->{value}
6843                  =~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt]                  =~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt]
6844                      [\x09-\x0D\x20]*=                      [\x09\x0A\x0C\x0D\x20]*=
6845                      [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                      [\x09\x0A\x0C\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
6846                      ([^"'\x09-\x0D\x20][^\x09-\x0D\x20\x3B]*))/x) {                      ([^"'\x09\x0A\x0C\x0D\x20][^\x09\x0A\x0C\x0D\x20\x3B]*))
6847                       /x) {
6848                !!!cp ('t336');                !!!cp ('t336');
6849                ## NOTE: Whether the encoding is supported or not is handled                ## NOTE: Whether the encoding is supported or not is handled
6850                ## in the {change_encoding} callback.                ## in the {change_encoding} callback.
# Line 6857  sub _tree_construction_main ($) { Line 6903  sub _tree_construction_main ($) {
6903          !!!next-token;          !!!next-token;
6904          next B;          next B;
6905        } elsif ({        } elsif ({
6906                  address => 1, blockquote => 1, center => 1, dir => 1,                  ## NOTE: Start tags for non-phrasing flow content elements
6907                  div => 1, dl => 1, fieldset => 1,  
6908                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                  ## NOTE: The normal one
6909                  menu => 1, ol => 1, p => 1, ul => 1,                  address => 1, article => 1, aside => 1, blockquote => 1,
6910                    center => 1, datagrid => 1, details => 1, dialog => 1,
6911                    dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,
6912                    footer => 1, h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1,
6913                    h6 => 1, header => 1, menu => 1, nav => 1, ol => 1, p => 1,
6914                    section => 1, ul => 1,
6915                    ## NOTE: As normal, but drops leading newline
6916                  pre => 1, listing => 1,                  pre => 1, listing => 1,
6917                    ## NOTE: As normal, but interacts with the form element pointer
6918                  form => 1,                  form => 1,
6919                    
6920                  table => 1,                  table => 1,
6921                  hr => 1,                  hr => 1,
6922                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 6929  sub _tree_construction_main ($) { Line 6983  sub _tree_construction_main ($) {
6983            !!!next-token;            !!!next-token;
6984          }          }
6985          next B;          next B;
6986        } elsif ({li => 1, dt => 1, dd => 1}->{$token->{tag_name}}) {        } elsif ($token->{tag_name} eq 'li') {
6987          ## has a p element in scope          ## NOTE: As normal, but imply </li> when there's another <li> ...
6988    
6989            ## NOTE: Special, Scope (<li><foo><li> == <li><foo><li/></foo></li>)
6990              ## Interpreted as <li><foo/></li><li/> (non-conforming)
6991              ## blockquote (O9.27), center (O), dd (Fx3, O, S3.1.2, IE7),
6992              ## dt (Fx, O, S, IE), dl (O), fieldset (O, S, IE), form (Fx, O, S),
6993              ## hn (O), pre (O), applet (O, S), button (O, S), marquee (Fx, O, S),
6994              ## object (Fx)
6995              ## Generate non-tree (non-conforming)
6996              ## basefont (IE7 (where basefont is non-void)), center (IE),
6997              ## form (IE), hn (IE)
6998            ## address, div, p (<li><foo><li> == <li><foo/></li><li/>)
6999              ## Interpreted as <li><foo><li/></foo></li> (non-conforming)
7000              ## div (Fx, S)
7001    
7002            my $non_optional;
7003            my $i = -1;
7004    
7005            ## 1.
7006            for my $node (reverse @{$self->{open_elements}}) {
7007              if ($node->[1] & LI_EL) {
7008                ## 2. (a) As if </li>
7009                {
7010                  ## If no </li> - not applied
7011                  #
7012    
7013                  ## Otherwise
7014    
7015                  ## 1. generate implied end tags, except for </li>
7016                  #
7017    
7018                  ## 2. If current node != "li", parse error
7019                  if ($non_optional) {
7020                    !!!parse-error (type => 'not closed',
7021                                    text => $non_optional->[0]->manakai_local_name,
7022                                    token => $token);
7023                    !!!cp ('t355');
7024                  } else {
7025                    !!!cp ('t356');
7026                  }
7027    
7028                  ## 3. Pop
7029                  splice @{$self->{open_elements}}, $i;
7030                }
7031    
7032                last; ## 2. (b) goto 5.
7033              } elsif (
7034                       ## NOTE: not "formatting" and not "phrasing"
7035                       ($node->[1] & SPECIAL_EL or
7036                        $node->[1] & SCOPING_EL) and
7037                       ## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|.
7038    
7039                       (not $node->[1] & ADDRESS_EL) &
7040                       (not $node->[1] & DIV_EL) &
7041                       (not $node->[1] & P_EL)) {
7042                ## 3.
7043                !!!cp ('t357');
7044                last; ## goto 5.
7045              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7046                !!!cp ('t358');
7047                #
7048              } else {
7049                !!!cp ('t359');
7050                $non_optional ||= $node;
7051                #
7052              }
7053              ## 4.
7054              ## goto 2.
7055              $i--;
7056            }
7057    
7058            ## 5. (a) has a |p| element in scope
7059          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
7060            if ($_->[1] & P_EL) {            if ($_->[1] & P_EL) {
7061              !!!cp ('t353');              !!!cp ('t353');
7062    
7063                ## NOTE: |<p><li>|, for example.
7064    
7065              !!!back-token; # <x>              !!!back-token; # <x>
7066              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
7067                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
# Line 6943  sub _tree_construction_main ($) { Line 7071  sub _tree_construction_main ($) {
7071              last INSCOPE;              last INSCOPE;
7072            }            }
7073          } # INSCOPE          } # INSCOPE
7074              
7075          ## Step 1          ## 5. (b) insert
7076            !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7077            !!!nack ('t359.1');
7078            !!!next-token;
7079            next B;
7080          } elsif ($token->{tag_name} eq 'dt' or
7081                   $token->{tag_name} eq 'dd') {
7082            ## NOTE: As normal, but imply </dt> or </dd> when ...
7083    
7084            my $non_optional;
7085          my $i = -1;          my $i = -1;
7086          my $node = $self->{open_elements}->[$i];  
7087          my $li_or_dtdd = {li => {li => 1},          ## 1.
7088                            dt => {dt => 1, dd => 1},          for my $node (reverse @{$self->{open_elements}}) {
7089                            dd => {dt => 1, dd => 1}}->{$token->{tag_name}};            if ($node->[1] & DT_EL or $node->[1] & DD_EL) {
7090          LI: {              ## 2. (a) As if </li>
7091            ## Step 2              {
7092            if ($li_or_dtdd->{$node->[0]->manakai_local_name}) {                ## If no </li> - not applied
7093              if ($i != -1) {                #
7094                !!!cp ('t355');  
7095                !!!parse-error (type => 'not closed',                ## Otherwise
7096                                text => $self->{open_elements}->[-1]->[0]  
7097                                    ->manakai_local_name,                ## 1. generate implied end tags, except for </dt> or </dd>
7098                                token => $token);                #
7099              } else {  
7100                !!!cp ('t356');                ## 2. If current node != "dt"|"dd", parse error
7101                  if ($non_optional) {
7102                    !!!parse-error (type => 'not closed',
7103                                    text => $non_optional->[0]->manakai_local_name,
7104                                    token => $token);
7105                    !!!cp ('t355.1');
7106                  } else {
7107                    !!!cp ('t356.1');
7108                  }
7109    
7110                  ## 3. Pop
7111                  splice @{$self->{open_elements}}, $i;
7112              }              }
7113              splice @{$self->{open_elements}}, $i;  
7114              last LI;              last; ## 2. (b) goto 5.
7115              } elsif (
7116                       ## NOTE: not "formatting" and not "phrasing"
7117                       ($node->[1] & SPECIAL_EL or
7118                        $node->[1] & SCOPING_EL) and
7119                       ## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|.
7120    
7121                       (not $node->[1] & ADDRESS_EL) &
7122                       (not $node->[1] & DIV_EL) &
7123                       (not $node->[1] & P_EL)) {
7124                ## 3.
7125                !!!cp ('t357.1');
7126                last; ## goto 5.
7127              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7128                !!!cp ('t358.1');
7129                #
7130            } else {            } else {
7131              !!!cp ('t357');              !!!cp ('t359.1');
7132            }              $non_optional ||= $node;
7133                          #
           ## 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;  
7134            }            }
7135                        ## 4.
7136            !!!cp ('t359');            ## goto 2.
           ## Step 4  
7137            $i--;            $i--;
7138            $node = $self->{open_elements}->[$i];          }
7139            redo LI;  
7140          } # LI          ## 5. (a) has a |p| element in scope
7141                      INSCOPE: for (reverse @{$self->{open_elements}}) {
7142              if ($_->[1] & P_EL) {
7143                !!!cp ('t353.1');
7144                !!!back-token; # <x>
7145                $token = {type => END_TAG_TOKEN, tag_name => 'p',
7146                          line => $token->{line}, column => $token->{column}};
7147                next B;
7148              } elsif ($_->[1] & SCOPING_EL) {
7149                !!!cp ('t354.1');
7150                last INSCOPE;
7151              }
7152            } # INSCOPE
7153    
7154            ## 5. (b) insert
7155          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7156          !!!nack ('t359.1');          !!!nack ('t359.2');
7157          !!!next-token;          !!!next-token;
7158          next B;          next B;
7159        } elsif ($token->{tag_name} eq 'plaintext') {        } elsif ($token->{tag_name} eq 'plaintext') {
7160            ## NOTE: As normal, but effectively ends parsing
7161    
7162          ## has a p element in scope          ## has a p element in scope
7163          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
7164            if ($_->[1] & P_EL) {            if ($_->[1] & P_EL) {
# Line 7299  sub _tree_construction_main ($) { Line 7467  sub _tree_construction_main ($) {
7467          !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.          !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.
7468          !!!next-token;          !!!next-token;
7469          next B;          next B;
7470                  } elsif ($token->{tag_name} eq 'param' or
7471          ## ISSUE: An issue on HTML5 new elements in the spec.                 $token->{tag_name} eq 'source') {
7472            !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7473            pop @{$self->{open_elements}};
7474    
7475            !!!ack ('t398.5');
7476            !!!next-token;
7477            redo B;
7478        } else {        } else {
7479          if ($token->{tag_name} eq 'image') {          if ($token->{tag_name} eq 'image') {
7480            !!!cp ('t384');            !!!cp ('t384');
# Line 7323  sub _tree_construction_main ($) { Line 7497  sub _tree_construction_main ($) {
7497            !!!nack ('t380.1');            !!!nack ('t380.1');
7498          } elsif ({          } elsif ({
7499                    b => 1, big => 1, em => 1, font => 1, i => 1,                    b => 1, big => 1, em => 1, font => 1, i => 1,
7500                    s => 1, small => 1, strile => 1,                    s => 1, small => 1, strike => 1,
7501                    strong => 1, tt => 1, u => 1,                    strong => 1, tt => 1, u => 1,
7502                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
7503            !!!cp ('t375');            !!!cp ('t375');
# Line 7336  sub _tree_construction_main ($) { Line 7510  sub _tree_construction_main ($) {
7510            !!!ack ('t388.2');            !!!ack ('t388.2');
7511          } elsif ({          } elsif ({
7512                    area => 1, basefont => 1, bgsound => 1, br => 1,                    area => 1, basefont => 1, bgsound => 1, br => 1,
7513                    embed => 1, img => 1, param => 1, spacer => 1, wbr => 1,                    embed => 1, img => 1, spacer => 1, wbr => 1,
                   #image => 1,  
7514                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
7515            !!!cp ('t388.1');            !!!cp ('t388.1');
7516            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
# Line 7405  sub _tree_construction_main ($) { Line 7578  sub _tree_construction_main ($) {
7578          ## up-to-date, though it has same effect as speced.          ## up-to-date, though it has same effect as speced.
7579          if (@{$self->{open_elements}} > 1 and          if (@{$self->{open_elements}} > 1 and
7580              $self->{open_elements}->[1]->[1] & BODY_EL) {              $self->{open_elements}->[1]->[1] & BODY_EL) {
           ## ISSUE: There is an issue in the spec.  
7581            unless ($self->{open_elements}->[-1]->[1] & BODY_EL) {            unless ($self->{open_elements}->[-1]->[1] & BODY_EL) {
7582              !!!cp ('t406');              !!!cp ('t406');
7583              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
# Line 7427  sub _tree_construction_main ($) { Line 7599  sub _tree_construction_main ($) {
7599            next B;            next B;
7600          }          }
7601        } elsif ({        } elsif ({
7602                  address => 1, blockquote => 1, center => 1, dir => 1,                  ## NOTE: End tags for non-phrasing flow content elements
7603                  div => 1, dl => 1, fieldset => 1, listing => 1,  
7604                  menu => 1, ol => 1, pre => 1, ul => 1,                  ## NOTE: The normal ones
7605                    address => 1, article => 1, aside => 1, blockquote => 1,
7606                    center => 1, datagrid => 1, details => 1, dialog => 1,
7607                    dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,
7608                    footer => 1, header => 1, listing => 1, menu => 1, nav => 1,
7609                    ol => 1, pre => 1, section => 1, ul => 1,
7610    
7611                    ## NOTE: As normal, but ... optional tags
7612                  dd => 1, dt => 1, li => 1,                  dd => 1, dt => 1, li => 1,
7613    
7614                  applet => 1, button => 1, marquee => 1, object => 1,                  applet => 1, button => 1, marquee => 1, object => 1,
7615                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7616            ## NOTE: Code for <li> start tags includes "as if </li>" code.
7617            ## Code for <dt> or <dd> start tags includes "as if </dt> or
7618            ## </dd>" code.
7619    
7620          ## has an element in scope          ## has an element in scope
7621          my $i;          my $i;
7622          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
# Line 7459  sub _tree_construction_main ($) { Line 7643  sub _tree_construction_main ($) {
7643                    dd => ($token->{tag_name} ne 'dd'),                    dd => ($token->{tag_name} ne 'dd'),
7644                    dt => ($token->{tag_name} ne 'dt'),                    dt => ($token->{tag_name} ne 'dt'),
7645                    li => ($token->{tag_name} ne 'li'),                    li => ($token->{tag_name} ne 'li'),
7646                      option => 1,
7647                      optgroup => 1,
7648                    p => 1,                    p => 1,
7649                    rt => 1,                    rt => 1,
7650                    rp => 1,                    rp => 1,
# Line 7491  sub _tree_construction_main ($) { Line 7677  sub _tree_construction_main ($) {
7677          !!!next-token;          !!!next-token;
7678          next B;          next B;
7679        } elsif ($token->{tag_name} eq 'form') {        } elsif ($token->{tag_name} eq 'form') {
7680            ## NOTE: As normal, but interacts with the form element pointer
7681    
7682          undef $self->{form_element};          undef $self->{form_element};
7683    
7684          ## has an element in scope          ## has an element in scope
# Line 7538  sub _tree_construction_main ($) { Line 7726  sub _tree_construction_main ($) {
7726          !!!next-token;          !!!next-token;
7727          next B;          next B;
7728        } elsif ({        } elsif ({
7729                    ## NOTE: As normal, except acts as a closer for any ...
7730                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,
7731                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7732          ## has an element in scope          ## has an element in scope
# Line 7583  sub _tree_construction_main ($) { Line 7772  sub _tree_construction_main ($) {
7772          !!!next-token;          !!!next-token;
7773          next B;          next B;
7774        } elsif ($token->{tag_name} eq 'p') {        } elsif ($token->{tag_name} eq 'p') {
7775            ## NOTE: As normal, except </p> implies <p> and ...
7776    
7777          ## has an element in scope          ## has an element in scope
7778            my $non_optional;
7779          my $i;          my $i;
7780          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7781            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
# Line 7594  sub _tree_construction_main ($) { Line 7786  sub _tree_construction_main ($) {
7786            } elsif ($node->[1] & SCOPING_EL) {            } elsif ($node->[1] & SCOPING_EL) {
7787              !!!cp ('t411.1');              !!!cp ('t411.1');
7788              last INSCOPE;              last INSCOPE;
7789              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7790                ## NOTE: |END_TAG_OPTIONAL_EL| includes "p"
7791                !!!cp ('t411.2');
7792                #
7793              } else {
7794                !!!cp ('t411.3');
7795                $non_optional ||= $node;
7796                #
7797            }            }
7798          } # INSCOPE          } # INSCOPE
7799    
7800          if (defined $i) {          if (defined $i) {
7801            if ($self->{open_elements}->[-1]->[0]->manakai_local_name            ## 1. Generate implied end tags
7802                    ne $token->{tag_name}) {            #
7803    
7804              ## 2. If current node != "p", parse error
7805              if ($non_optional) {
7806              !!!cp ('t412.1');              !!!cp ('t412.1');
7807              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
7808                              text => $self->{open_elements}->[-1]->[0]                              text => $non_optional->[0]->manakai_local_name,
                                 ->manakai_local_name,  
7809                              token => $token);                              token => $token);
7810            } else {            } else {
7811              !!!cp ('t414.1');              !!!cp ('t414.1');
7812            }            }
7813    
7814              ## 3. Pop
7815            splice @{$self->{open_elements}}, $i;            splice @{$self->{open_elements}}, $i;
7816          } else {          } else {
7817            !!!cp ('t413.1');            !!!cp ('t413.1');
# Line 7628  sub _tree_construction_main ($) { Line 7831  sub _tree_construction_main ($) {
7831        } elsif ({        } elsif ({
7832                  a => 1,                  a => 1,
7833                  b => 1, big => 1, em => 1, font => 1, i => 1,                  b => 1, big => 1, em => 1, font => 1, i => 1,
7834                  nobr => 1, s => 1, small => 1, strile => 1,                  nobr => 1, s => 1, small => 1, strike => 1,
7835                  strong => 1, tt => 1, u => 1,                  strong => 1, tt => 1, u => 1,
7836                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7837          !!!cp ('t427');          !!!cp ('t427');
# Line 7667  sub _tree_construction_main ($) { Line 7870  sub _tree_construction_main ($) {
7870          ## Ignore the token          ## Ignore the token
7871          !!!next-token;          !!!next-token;
7872          next B;          next B;
           
         ## ISSUE: Issue on HTML5 new elements in spec  
           
7873        } else {        } else {
7874            if ($token->{tag_name} eq 'sarcasm') {
7875              sleep 0.001; # take a deep breath
7876            }
7877    
7878          ## Step 1          ## Step 1
7879          my $node_i = -1;          my $node_i = -1;
7880          my $node = $self->{open_elements}->[$node_i];          my $node = $self->{open_elements}->[$node_i];
# Line 7719  sub _tree_construction_main ($) { Line 7923  sub _tree_construction_main ($) {
7923                ## Ignore the token                ## Ignore the token
7924                !!!next-token;                !!!next-token;
7925                last S2;                last S2;
             }  
7926    
7927                  ## NOTE: |<span><dd></span>a|: In Safari 3.1.2 and Opera
7928                  ## 9.27, "a" is a child of <dd> (conforming).  In
7929                  ## Firefox 3.0.2, "a" is a child of <body>.  In WinIE 7,
7930                  ## "a" is a child of both <body> and <dd>.
7931                }
7932                
7933              !!!cp ('t434');              !!!cp ('t434');
7934            }            }
7935                        
# Line 7882  sub set_inner_html ($$$$;$) { Line 8091  sub set_inner_html ($$$$;$) {
8091              $p->{char_buffer_pos} += $count;              $p->{char_buffer_pos} += $count;
8092              $p->{line_prev} = $p->{line};              $p->{line_prev} = $p->{line};
8093              $p->{column_prev} = $p->{column} - 1;              $p->{column_prev} = $p->{column} - 1;
             $p->{prev_char} = [-1, -1, -1];  
8094              $p->{nc} = -1;              $p->{nc} = -1;
8095            }            }
8096            return $count;            return $count;
# Line 7894  sub set_inner_html ($$$$;$) { Line 8102  sub set_inner_html ($$$$;$) {
8102          if ($count) {          if ($count) {
8103            $p->{column} += $count;            $p->{column} += $count;
8104            $p->{column_prev} += $count;            $p->{column_prev} += $count;
           $p->{prev_char} = [-1, -1, -1];  
8105            $p->{nc} = -1;            $p->{nc} = -1;
8106          }          }
8107          return $count;          return $count;

Legend:
Removed from v.1.183  
changed lines
  Added in v.1.198

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24