/[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.184 by wakaba, Mon Sep 15 09:02:27 2008 UTC revision 1.207 by wakaba, Mon Oct 13 08:27:44 2008 UTC
# Line 28  my $XLINK_NS = q<http://www.w3.org/1999/ Line 28  my $XLINK_NS = q<http://www.w3.org/1999/
28  my $XML_NS = q<http://www.w3.org/XML/1998/namespace>;  my $XML_NS = q<http://www.w3.org/XML/1998/namespace>;
29  my $XMLNS_NS = q<http://www.w3.org/2000/xmlns/>;  my $XMLNS_NS = q<http://www.w3.org/2000/xmlns/>;
30    
31  sub A_EL () { 0b1 }  ## Bits 12-15
32  sub ADDRESS_EL () { 0b10 }  sub SPECIAL_EL () { 0b1_000000000000000 }
33  sub BODY_EL () { 0b100 }  sub SCOPING_EL () { 0b1_00000000000000 }
34  sub BUTTON_EL () { 0b1000 }  sub FORMATTING_EL () { 0b1_0000000000000 }
35  sub CAPTION_EL () { 0b10000 }  sub PHRASING_EL () { 0b1_000000000000 }
36  sub DD_EL () { 0b100000 }  
37  sub DIV_EL () { 0b1000000 }  ## Bits 10-11
38  sub DT_EL () { 0b10000000 }  sub FOREIGN_EL () { 0b1_00000000000 }
39  sub FORM_EL () { 0b100000000 }  sub FOREIGN_FLOW_CONTENT_EL () { 0b1_0000000000 }
40  sub FORMATTING_EL () { 0b1000000000 }  
41  sub FRAMESET_EL () { 0b10000000000 }  ## Bits 6-9
42  sub HEADING_EL () { 0b100000000000 }  sub TABLE_SCOPING_EL () { 0b1_000000000 }
43  sub HTML_EL () { 0b1000000000000 }  sub TABLE_ROWS_SCOPING_EL () { 0b1_00000000 }
44  sub LI_EL () { 0b10000000000000 }  sub TABLE_ROW_SCOPING_EL () { 0b1_0000000 }
45  sub NOBR_EL () { 0b100000000000000 }  sub TABLE_ROWS_EL () { 0b1_000000 }
 sub OPTION_EL () { 0b1000000000000000 }  
 sub OPTGROUP_EL () { 0b10000000000000000 }  
 sub P_EL () { 0b100000000000000000 }  
 sub SELECT_EL () { 0b1000000000000000000 }  
 sub TABLE_EL () { 0b10000000000000000000 }  
 sub TABLE_CELL_EL () { 0b100000000000000000000 }  
 sub TABLE_ROW_EL () { 0b1000000000000000000000 }  
 sub TABLE_ROW_GROUP_EL () { 0b10000000000000000000000 }  
 sub MISC_SCOPING_EL () { 0b100000000000000000000000 }  
 sub MISC_SPECIAL_EL () { 0b1000000000000000000000000 }  
 sub FOREIGN_EL () { 0b10000000000000000000000000 }  
 sub FOREIGN_FLOW_CONTENT_EL () { 0b100000000000000000000000000 }  
 sub MML_AXML_EL () { 0b1000000000000000000000000000 }  
 sub RUBY_EL () { 0b10000000000000000000000000000 }  
 sub RUBY_COMPONENT_EL () { 0b100000000000000000000000000000 }  
   
 sub TABLE_ROWS_EL () {  
   TABLE_EL |  
   TABLE_ROW_EL |  
   TABLE_ROW_GROUP_EL  
 }  
46    
47  ## NOTE: Used in "generate implied end tags" algorithm.  ## Bit 5
48  ## NOTE: There is a code where a modified version of END_TAG_OPTIONAL_EL  sub ADDRESS_DIV_P_EL () { 0b1_00000 }
 ## is used in "generate implied end tags" implementation (search for the  
 ## function mae).  
 sub END_TAG_OPTIONAL_EL () {  
   DD_EL |  
   DT_EL |  
   LI_EL |  
   P_EL |  
   RUBY_COMPONENT_EL  
 }  
49    
50  ## NOTE: Used in </body> and EOF algorithms.  ## NOTE: Used in </body> and EOF algorithms.
51  sub ALL_END_TAG_OPTIONAL_EL () {  ## Bit 4
52    DD_EL |  sub ALL_END_TAG_OPTIONAL_EL () { 0b1_0000 }
   DT_EL |  
   LI_EL |  
   P_EL |  
   
   BODY_EL |  
   HTML_EL |  
   TABLE_CELL_EL |  
   TABLE_ROW_EL |  
   TABLE_ROW_GROUP_EL  
 }  
53    
54  sub SCOPING_EL () {  ## NOTE: Used in "generate implied end tags" algorithm.
55    BUTTON_EL |  ## NOTE: There is a code where a modified version of
56    CAPTION_EL |  ## END_TAG_OPTIONAL_EL is used in "generate implied end tags"
57    HTML_EL |  ## implementation (search for the algorithm name).
58    TABLE_EL |  ## Bit 3
59    TABLE_CELL_EL |  sub END_TAG_OPTIONAL_EL () { 0b1_000 }
60    MISC_SCOPING_EL  
61    ## Bits 0-2
62    
63    sub MISC_SPECIAL_EL () { SPECIAL_EL | 0b000 }
64    sub FORM_EL () { SPECIAL_EL | 0b001 }
65    sub FRAMESET_EL () { SPECIAL_EL | 0b010 }
66    sub HEADING_EL () { SPECIAL_EL | 0b011 }
67    sub SELECT_EL () { SPECIAL_EL | 0b100 }
68    sub SCRIPT_EL () { SPECIAL_EL | 0b101 }
69    
70    sub ADDRESS_DIV_EL () { SPECIAL_EL | ADDRESS_DIV_P_EL | 0b001 }
71    sub BODY_EL () { SPECIAL_EL | ALL_END_TAG_OPTIONAL_EL | 0b001 }
72    
73    sub DTDD_EL () {
74      SPECIAL_EL |
75      END_TAG_OPTIONAL_EL |
76      ALL_END_TAG_OPTIONAL_EL |
77      0b010
78  }  }
79    sub LI_EL () {
80  sub TABLE_SCOPING_EL () {    SPECIAL_EL |
81    HTML_EL |    END_TAG_OPTIONAL_EL |
82    TABLE_EL    ALL_END_TAG_OPTIONAL_EL |
83      0b100
84  }  }
85    sub P_EL () {
86  sub TABLE_ROWS_SCOPING_EL () {    SPECIAL_EL |
87    HTML_EL |    ADDRESS_DIV_P_EL |
88    TABLE_ROW_GROUP_EL    END_TAG_OPTIONAL_EL |
89      ALL_END_TAG_OPTIONAL_EL |
90      0b001
91  }  }
92    
93  sub TABLE_ROW_SCOPING_EL () {  sub TABLE_ROW_EL () {
94    HTML_EL |    SPECIAL_EL |
95    TABLE_ROW_EL    TABLE_ROWS_EL |
96      TABLE_ROW_SCOPING_EL |
97      ALL_END_TAG_OPTIONAL_EL |
98      0b001
99    }
100    sub TABLE_ROW_GROUP_EL () {
101      SPECIAL_EL |
102      TABLE_ROWS_EL |
103      TABLE_ROWS_SCOPING_EL |
104      ALL_END_TAG_OPTIONAL_EL |
105      0b001
106  }  }
107    
108  sub SPECIAL_EL () {  sub MISC_SCOPING_EL () { SCOPING_EL | 0b000 }
109    ADDRESS_EL |  sub BUTTON_EL () { SCOPING_EL | 0b001 }
110    BODY_EL |  sub CAPTION_EL () { SCOPING_EL | 0b010 }
111    DIV_EL |  sub HTML_EL () {
112      SCOPING_EL |
113    DD_EL |    TABLE_SCOPING_EL |
114    DT_EL |    TABLE_ROWS_SCOPING_EL |
115    LI_EL |    TABLE_ROW_SCOPING_EL |
116    P_EL |    ALL_END_TAG_OPTIONAL_EL |
117      0b001
118    FORM_EL |  }
119    FRAMESET_EL |  sub TABLE_EL () {
120    HEADING_EL |    SCOPING_EL |
121    OPTION_EL |    TABLE_ROWS_EL |
122    OPTGROUP_EL |    TABLE_SCOPING_EL |
123    SELECT_EL |    0b001
   TABLE_ROW_EL |  
   TABLE_ROW_GROUP_EL |  
   MISC_SPECIAL_EL  
124  }  }
125    sub TABLE_CELL_EL () {
126      SCOPING_EL |
127      TABLE_ROW_SCOPING_EL |
128      ALL_END_TAG_OPTIONAL_EL |
129      0b001
130    }
131    
132    sub MISC_FORMATTING_EL () { FORMATTING_EL | 0b000 }
133    sub A_EL () { FORMATTING_EL | 0b001 }
134    sub NOBR_EL () { FORMATTING_EL | 0b010 }
135    
136    sub RUBY_EL () { PHRASING_EL | 0b001 }
137    
138    ## ISSUE: ALL_END_TAG_OPTIONAL_EL?
139    sub OPTGROUP_EL () { PHRASING_EL | END_TAG_OPTIONAL_EL | 0b001 }
140    sub OPTION_EL () { PHRASING_EL | END_TAG_OPTIONAL_EL | 0b010 }
141    sub RUBY_COMPONENT_EL () { PHRASING_EL | END_TAG_OPTIONAL_EL | 0b100 }
142    
143    sub MML_AXML_EL () { PHRASING_EL | FOREIGN_EL | 0b001 }
144    
145  my $el_category = {  my $el_category = {
146    a => A_EL | FORMATTING_EL,    a => A_EL,
147    address => ADDRESS_EL,    address => ADDRESS_DIV_EL,
148    applet => MISC_SCOPING_EL,    applet => MISC_SCOPING_EL,
149    area => MISC_SPECIAL_EL,    area => MISC_SPECIAL_EL,
150      article => MISC_SPECIAL_EL,
151      aside => MISC_SPECIAL_EL,
152    b => FORMATTING_EL,    b => FORMATTING_EL,
153    base => MISC_SPECIAL_EL,    base => MISC_SPECIAL_EL,
154    basefont => MISC_SPECIAL_EL,    basefont => MISC_SPECIAL_EL,
# Line 154  my $el_category = { Line 162  my $el_category = {
162    center => MISC_SPECIAL_EL,    center => MISC_SPECIAL_EL,
163    col => MISC_SPECIAL_EL,    col => MISC_SPECIAL_EL,
164    colgroup => MISC_SPECIAL_EL,    colgroup => MISC_SPECIAL_EL,
165    dd => DD_EL,    command => MISC_SPECIAL_EL,
166      datagrid => MISC_SPECIAL_EL,
167      dd => DTDD_EL,
168      details => MISC_SPECIAL_EL,
169      dialog => MISC_SPECIAL_EL,
170    dir => MISC_SPECIAL_EL,    dir => MISC_SPECIAL_EL,
171    div => DIV_EL,    div => ADDRESS_DIV_EL,
172    dl => MISC_SPECIAL_EL,    dl => MISC_SPECIAL_EL,
173    dt => DT_EL,    dt => DTDD_EL,
174    em => FORMATTING_EL,    em => FORMATTING_EL,
175    embed => MISC_SPECIAL_EL,    embed => MISC_SPECIAL_EL,
176      eventsource => MISC_SPECIAL_EL,
177    fieldset => MISC_SPECIAL_EL,    fieldset => MISC_SPECIAL_EL,
178      figure => MISC_SPECIAL_EL,
179    font => FORMATTING_EL,    font => FORMATTING_EL,
180      footer => MISC_SPECIAL_EL,
181    form => FORM_EL,    form => FORM_EL,
182    frame => MISC_SPECIAL_EL,    frame => MISC_SPECIAL_EL,
183    frameset => FRAMESET_EL,    frameset => FRAMESET_EL,
# Line 173  my $el_category = { Line 188  my $el_category = {
188    h5 => HEADING_EL,    h5 => HEADING_EL,
189    h6 => HEADING_EL,    h6 => HEADING_EL,
190    head => MISC_SPECIAL_EL,    head => MISC_SPECIAL_EL,
191      header => MISC_SPECIAL_EL,
192    hr => MISC_SPECIAL_EL,    hr => MISC_SPECIAL_EL,
193    html => HTML_EL,    html => HTML_EL,
194    i => FORMATTING_EL,    i => FORMATTING_EL,
195    iframe => MISC_SPECIAL_EL,    iframe => MISC_SPECIAL_EL,
196    img => MISC_SPECIAL_EL,    img => MISC_SPECIAL_EL,
197      #image => MISC_SPECIAL_EL, ## NOTE: Commented out in the spec.
198    input => MISC_SPECIAL_EL,    input => MISC_SPECIAL_EL,
199    isindex => MISC_SPECIAL_EL,    isindex => MISC_SPECIAL_EL,
200    li => LI_EL,    li => LI_EL,
# Line 186  my $el_category = { Line 203  my $el_category = {
203    marquee => MISC_SCOPING_EL,    marquee => MISC_SCOPING_EL,
204    menu => MISC_SPECIAL_EL,    menu => MISC_SPECIAL_EL,
205    meta => MISC_SPECIAL_EL,    meta => MISC_SPECIAL_EL,
206    nobr => NOBR_EL | FORMATTING_EL,    nav => MISC_SPECIAL_EL,
207      nobr => NOBR_EL,
208    noembed => MISC_SPECIAL_EL,    noembed => MISC_SPECIAL_EL,
209    noframes => MISC_SPECIAL_EL,    noframes => MISC_SPECIAL_EL,
210    noscript => MISC_SPECIAL_EL,    noscript => MISC_SPECIAL_EL,
# Line 204  my $el_category = { Line 222  my $el_category = {
222    s => FORMATTING_EL,    s => FORMATTING_EL,
223    script => MISC_SPECIAL_EL,    script => MISC_SPECIAL_EL,
224    select => SELECT_EL,    select => SELECT_EL,
225      section => MISC_SPECIAL_EL,
226    small => FORMATTING_EL,    small => FORMATTING_EL,
227    spacer => MISC_SPECIAL_EL,    spacer => MISC_SPECIAL_EL,
228    strike => FORMATTING_EL,    strike => FORMATTING_EL,
# Line 227  my $el_category = { Line 246  my $el_category = {
246  my $el_category_f = {  my $el_category_f = {
247    $MML_NS => {    $MML_NS => {
248      'annotation-xml' => MML_AXML_EL,      'annotation-xml' => MML_AXML_EL,
249      mi => FOREIGN_FLOW_CONTENT_EL,      mi => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
250      mo => FOREIGN_FLOW_CONTENT_EL,      mo => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
251      mn => FOREIGN_FLOW_CONTENT_EL,      mn => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
252      ms => FOREIGN_FLOW_CONTENT_EL,      ms => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
253      mtext => FOREIGN_FLOW_CONTENT_EL,      mtext => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
254    },    },
255    $SVG_NS => {    $SVG_NS => {
256      foreignObject => FOREIGN_FLOW_CONTENT_EL,      foreignObject => SCOPING_EL | FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
257      desc => FOREIGN_FLOW_CONTENT_EL,      desc => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
258      title => FOREIGN_FLOW_CONTENT_EL,      title => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
259    },    },
260    ## NOTE: In addition, FOREIGN_EL is set to non-HTML elements.    ## NOTE: In addition, FOREIGN_EL is set to non-HTML elements.
261  };  };
# Line 323  my $foreign_attr_xname = { Line 342  my $foreign_attr_xname = {
342    
343  ## ISSUE: xmlns:xlink="non-xlink-ns" is not an error.  ## ISSUE: xmlns:xlink="non-xlink-ns" is not an error.
344    
345  my $c1_entity_char = {  my $charref_map = {
346      0x0D => 0x000A,
347    0x80 => 0x20AC,    0x80 => 0x20AC,
348    0x81 => 0xFFFD,    0x81 => 0xFFFD,
349    0x82 => 0x201A,    0x82 => 0x201A,
# Line 356  my $c1_entity_char = { Line 376  my $c1_entity_char = {
376    0x9D => 0xFFFD,    0x9D => 0xFFFD,
377    0x9E => 0x017E,    0x9E => 0x017E,
378    0x9F => 0x0178,    0x9F => 0x0178,
379  }; # $c1_entity_char  }; # $charref_map
380    $charref_map->{$_} = 0xFFFD
381        for 0x0000..0x0008, 0x000B, 0x000E..0x001F, 0x007F,
382            0xD800..0xDFFF, 0xFDD0..0xFDDF, ## ISSUE: 0xFDEF
383            0xFFFE, 0xFFFF, 0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF,
384            0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE,
385            0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF,
386            0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, 0xDFFFF, 0xEFFFE,
387            0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, 0x10FFFF;
388    
389    ## TODO: Invoke the reset algorithm when a resettable element is
390    ## created (cf. HTML5 revision 2259).
391    
392  sub parse_byte_string ($$$$;$) {  sub parse_byte_string ($$$$;$) {
393    my $self = shift;    my $self = shift;
# Line 401  sub parse_byte_stream ($$$$;$$) { Line 432  sub parse_byte_stream ($$$$;$$) {
432            ## TODO: Is this ok?  Transfer protocol's parameter should be            ## TODO: Is this ok?  Transfer protocol's parameter should be
433            ## interpreted in its semantics?            ## interpreted in its semantics?
434    
       ## ISSUE: Unsupported encoding is not ignored according to the spec.  
435        ($char_stream, $e_status) = $charset->get_decode_handle        ($char_stream, $e_status) = $charset->get_decode_handle
436            ($byte_stream, allow_error_reporting => 1,            ($byte_stream, allow_error_reporting => 1,
437             allow_fallback => 1);             allow_fallback => 1);
# Line 409  sub parse_byte_stream ($$$$;$$) { Line 439  sub parse_byte_stream ($$$$;$$) {
439          $self->{confident} = 1;          $self->{confident} = 1;
440          last SNIFFING;          last SNIFFING;
441        } else {        } else {
442          ## TODO: unsupported error          !!!parse-error (type => 'charset:not supported',
443                            layer => 'encode',
444                            line => 1, column => 1,
445                            value => $charset_name,
446                            level => $self->{level}->{uncertain});
447        }        }
448      }      }
449    
# Line 458  sub parse_byte_stream ($$$$;$$) { Line 492  sub parse_byte_stream ($$$$;$$) {
492      if (defined $charset_name) {      if (defined $charset_name) {
493        $charset = Message::Charset::Info->get_by_html_name ($charset_name);        $charset = Message::Charset::Info->get_by_html_name ($charset_name);
494    
       ## ISSUE: Unsupported encoding is not ignored according to the spec.  
495        require Whatpm::Charset::DecodeHandle;        require Whatpm::Charset::DecodeHandle;
496        $buffer = Whatpm::Charset::DecodeHandle::ByteBuffer->new        $buffer = Whatpm::Charset::DecodeHandle::ByteBuffer->new
497            ($byte_stream);            ($byte_stream);
# Line 853  sub CDATA_SECTION_STATE () { 35 } Line 886  sub CDATA_SECTION_STATE () { 35 }
886  sub MD_HYPHEN_STATE () { 36 } # "markup declaration open state" in the spec  sub MD_HYPHEN_STATE () { 36 } # "markup declaration open state" in the spec
887  sub MD_DOCTYPE_STATE () { 37 } # "markup declaration open state" in the spec  sub MD_DOCTYPE_STATE () { 37 } # "markup declaration open state" in the spec
888  sub MD_CDATA_STATE () { 38 } # "markup declaration open state" in the spec  sub MD_CDATA_STATE () { 38 } # "markup declaration open state" in the spec
889  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
890  sub CDATA_SECTION_MSE1_STATE () { 40 } # "CDATA section state" in the spec  sub CDATA_SECTION_MSE1_STATE () { 40 } # "CDATA section state" in the spec
891  sub CDATA_SECTION_MSE2_STATE () { 41 } # "CDATA section state" in the spec  sub CDATA_SECTION_MSE2_STATE () { 41 } # "CDATA section state" in the spec
892  sub PUBLIC_STATE () { 42 } # "after DOCTYPE name state" in the spec  sub PUBLIC_STATE () { 42 } # "after DOCTYPE name state" in the spec
# Line 867  sub NCR_NUM_STATE () { 46 } Line 900  sub NCR_NUM_STATE () { 46 }
900  sub HEXREF_X_STATE () { 47 }  sub HEXREF_X_STATE () { 47 }
901  sub HEXREF_HEX_STATE () { 48 }  sub HEXREF_HEX_STATE () { 48 }
902  sub ENTITY_NAME_STATE () { 49 }  sub ENTITY_NAME_STATE () { 49 }
903    sub PCDATA_STATE () { 50 } # "data state" in the spec
904    
905  sub DOCTYPE_TOKEN () { 1 }  sub DOCTYPE_TOKEN () { 1 }
906  sub COMMENT_TOKEN () { 2 }  sub COMMENT_TOKEN () { 2 }
# Line 888  sub IN_FOREIGN_CONTENT_IM () { 0b1000000 Line 922  sub IN_FOREIGN_CONTENT_IM () { 0b1000000
922      ## NOTE: "in foreign content" insertion mode is special; it is combined      ## NOTE: "in foreign content" insertion mode is special; it is combined
923      ## with the secondary insertion mode.  In this parser, they are stored      ## with the secondary insertion mode.  In this parser, they are stored
924      ## together in the bit-or'ed form.      ## together in the bit-or'ed form.
925    sub IN_CDATA_RCDATA_IM () { 0b1000000000000 }
926        ## NOTE: "in CDATA/RCDATA" insertion mode is also special; it is
927        ## combined with the original insertion mode.  In thie parser,
928        ## they are stored together in the bit-or'ed form.
929    
930  ## NOTE: "initial" and "before html" insertion modes have no constants.  ## NOTE: "initial" and "before html" insertion modes have no constants.
931    
# Line 965  sub _initialize_tokenizer ($) { Line 1003  sub _initialize_tokenizer ($) {
1003  ## TODO: Polytheistic slash SHOULD NOT be used. (Applied only to atheists.)  ## TODO: Polytheistic slash SHOULD NOT be used. (Applied only to atheists.)
1004  ## (This requirement was dropped from HTML5 spec, unfortunately.)  ## (This requirement was dropped from HTML5 spec, unfortunately.)
1005    
1006    my $is_space = {
1007      0x0009 => 1, # CHARACTER TABULATION (HT)
1008      0x000A => 1, # LINE FEED (LF)
1009      #0x000B => 0, # LINE TABULATION (VT)
1010      0x000C => 1, # FORM FEED (FF)
1011      #0x000D => 1, # CARRIAGE RETURN (CR)
1012      0x0020 => 1, # SPACE (SP)
1013    };
1014    
1015  sub _get_next_token ($) {  sub _get_next_token ($) {
1016    my $self = shift;    my $self = shift;
1017    
# Line 982  sub _get_next_token ($) { Line 1029  sub _get_next_token ($) {
1029    }    }
1030    
1031    A: {    A: {
1032      if ($self->{state} == DATA_STATE) {      if ($self->{state} == PCDATA_STATE) {
1033          ## NOTE: Same as |DATA_STATE|, but only for |PCDATA| content model.
1034    
1035          if ($self->{nc} == 0x0026) { # &
1036            !!!cp (0.1);
1037            ## NOTE: In the spec, the tokenizer is switched to the
1038            ## "entity data state".  In this implementation, the tokenizer
1039            ## is switched to the |ENTITY_STATE|, which is an implementation
1040            ## of the "consume a character reference" algorithm.
1041            $self->{entity_add} = -1;
1042            $self->{prev_state} = DATA_STATE;
1043            $self->{state} = ENTITY_STATE;
1044            !!!next-input-character;
1045            redo A;
1046          } elsif ($self->{nc} == 0x003C) { # <
1047            !!!cp (0.2);
1048            $self->{state} = TAG_OPEN_STATE;
1049            !!!next-input-character;
1050            redo A;
1051          } elsif ($self->{nc} == -1) {
1052            !!!cp (0.3);
1053            !!!emit ({type => END_OF_FILE_TOKEN,
1054                      line => $self->{line}, column => $self->{column}});
1055            last A; ## TODO: ok?
1056          } else {
1057            !!!cp (0.4);
1058            #
1059          }
1060    
1061          # Anything else
1062          my $token = {type => CHARACTER_TOKEN,
1063                       data => chr $self->{nc},
1064                       line => $self->{line}, column => $self->{column},
1065                      };
1066          $self->{read_until}->($token->{data}, q[<&], length $token->{data});
1067    
1068          ## Stay in the state.
1069          !!!next-input-character;
1070          !!!emit ($token);
1071          redo A;
1072        } elsif ($self->{state} == DATA_STATE) {
1073          $self->{s_kwd} = '' unless defined $self->{s_kwd};
1074        if ($self->{nc} == 0x0026) { # &        if ($self->{nc} == 0x0026) { # &
1075          delete $self->{s_kwd};          $self->{s_kwd} = '';
1076          if ($self->{content_model} & CM_ENTITY and # PCDATA | RCDATA          if ($self->{content_model} & CM_ENTITY and # PCDATA | RCDATA
1077              not $self->{escape}) {              not $self->{escape}) {
1078            !!!cp (1);            !!!cp (1);
# Line 1003  sub _get_next_token ($) { Line 1091  sub _get_next_token ($) {
1091          }          }
1092        } elsif ($self->{nc} == 0x002D) { # -        } elsif ($self->{nc} == 0x002D) { # -
1093          if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA          if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA
1094            if (defined $self->{s_kwd}) {            $self->{s_kwd} .= '-';
1095              !!!cp (2.1);            
             $self->{s_kwd} .= '-';  
           } else {  
             !!!cp (2.2);  
             $self->{s_kwd} = '-';  
           }  
   
1096            if ($self->{s_kwd} eq '<!--') {            if ($self->{s_kwd} eq '<!--') {
1097              !!!cp (3);              !!!cp (3);
1098              $self->{escape} = 1; # unless $self->{escape};              $self->{escape} = 1; # unless $self->{escape};
# Line 1028  sub _get_next_token ($) { Line 1110  sub _get_next_token ($) {
1110                    
1111          #          #
1112        } elsif ($self->{nc} == 0x0021) { # !        } elsif ($self->{nc} == 0x0021) { # !
1113          if (defined $self->{s_kwd}) {          if (length $self->{s_kwd}) {
1114            !!!cp (5.1);            !!!cp (5.1);
1115            $self->{s_kwd} .= '!';            $self->{s_kwd} .= '!';
1116            #            #
1117          } else {          } else {
1118            !!!cp (5.2);            !!!cp (5.2);
1119              #$self->{s_kwd} = '';
1120            #            #
1121          }          }
1122          #          #
1123        } elsif ($self->{nc} == 0x003C) { # <        } elsif ($self->{nc} == 0x003C) { # <
         delete $self->{s_kwd};  
1124          if ($self->{content_model} & CM_FULL_MARKUP or # PCDATA          if ($self->{content_model} & CM_FULL_MARKUP or # PCDATA
1125              (($self->{content_model} & CM_LIMITED_MARKUP) and # CDATA | RCDATA              (($self->{content_model} & CM_LIMITED_MARKUP) and # CDATA | RCDATA
1126               not $self->{escape})) {               not $self->{escape})) {
# Line 1048  sub _get_next_token ($) { Line 1130  sub _get_next_token ($) {
1130            redo A;            redo A;
1131          } else {          } else {
1132            !!!cp (7);            !!!cp (7);
1133              $self->{s_kwd} = '';
1134            #            #
1135          }          }
1136        } elsif ($self->{nc} == 0x003E) { # >        } elsif ($self->{nc} == 0x003E) { # >
1137          if ($self->{escape} and          if ($self->{escape} and
1138              ($self->{content_model} & CM_LIMITED_MARKUP)) { # RCDATA | CDATA              ($self->{content_model} & CM_LIMITED_MARKUP)) { # RCDATA | CDATA
1139            if (defined $self->{s_kwd} and $self->{s_kwd} eq '--') {            if ($self->{s_kwd} eq '--') {
1140              !!!cp (8);              !!!cp (8);
1141              delete $self->{escape};              delete $self->{escape};
1142            } else {            } else {
# Line 1063  sub _get_next_token ($) { Line 1146  sub _get_next_token ($) {
1146            !!!cp (10);            !!!cp (10);
1147          }          }
1148                    
1149          delete $self->{s_kwd};          $self->{s_kwd} = '';
1150          #          #
1151        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
1152          !!!cp (11);          !!!cp (11);
1153          delete $self->{s_kwd};          $self->{s_kwd} = '';
1154          !!!emit ({type => END_OF_FILE_TOKEN,          !!!emit ({type => END_OF_FILE_TOKEN,
1155                    line => $self->{line}, column => $self->{column}});                    line => $self->{line}, column => $self->{column}});
1156          last A; ## TODO: ok?          last A; ## TODO: ok?
1157        } else {        } else {
1158          !!!cp (12);          !!!cp (12);
1159          delete $self->{s_kwd};          $self->{s_kwd} = '';
1160          #          #
1161        }        }
1162    
# Line 1084  sub _get_next_token ($) { Line 1167  sub _get_next_token ($) {
1167                    };                    };
1168        if ($self->{read_until}->($token->{data}, q[-!<>&],        if ($self->{read_until}->($token->{data}, q[-!<>&],
1169                                  length $token->{data})) {                                  length $token->{data})) {
1170          delete $self->{s_kwd};          $self->{s_kwd} = '';
1171        }        }
1172    
1173        ## Stay in the data state        ## Stay in the data state.
1174          if ($self->{content_model} == PCDATA_CONTENT_MODEL) {
1175            !!!cp (13);
1176            $self->{state} = PCDATA_STATE;
1177          } else {
1178            !!!cp (14);
1179            ## Stay in the state.
1180          }
1181        !!!next-input-character;        !!!next-input-character;
1182        !!!emit ($token);        !!!emit ($token);
1183        redo A;        redo A;
# Line 1192  sub _get_next_token ($) { Line 1282  sub _get_next_token ($) {
1282        }        }
1283      } elsif ($self->{state} == CLOSE_TAG_OPEN_STATE) {      } elsif ($self->{state} == CLOSE_TAG_OPEN_STATE) {
1284        ## NOTE: The "close tag open state" in the spec is implemented as        ## NOTE: The "close tag open state" in the spec is implemented as
1285        ## |CLOSE_TAG_OPEN_STATE| and |CDATA_PCDATA_CLOSE_TAG_STATE|.        ## |CLOSE_TAG_OPEN_STATE| and |CDATA_RCDATA_CLOSE_TAG_STATE|.
1286    
1287        my ($l, $c) = ($self->{line_prev}, $self->{column_prev} - 1); # "<"of"</"        my ($l, $c) = ($self->{line_prev}, $self->{column_prev} - 1); # "<"of"</"
1288        if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA        if ($self->{content_model} & CM_LIMITED_MARKUP) { # RCDATA | CDATA
1289          if (defined $self->{last_stag_name}) {          if (defined $self->{last_stag_name}) {
1290            $self->{state} = CDATA_PCDATA_CLOSE_TAG_STATE;            $self->{state} = CDATA_RCDATA_CLOSE_TAG_STATE;
1291            $self->{s_kwd} = '';            $self->{s_kwd} = '';
1292            ## Reconsume.            ## Reconsume.
1293            redo A;            redo A;
# Line 1268  sub _get_next_token ($) { Line 1358  sub _get_next_token ($) {
1358          ## "bogus comment state" entry.          ## "bogus comment state" entry.
1359          redo A;          redo A;
1360        }        }
1361      } elsif ($self->{state} == CDATA_PCDATA_CLOSE_TAG_STATE) {      } elsif ($self->{state} == CDATA_RCDATA_CLOSE_TAG_STATE) {
1362        my $ch = substr $self->{last_stag_name}, length $self->{s_kwd}, 1;        my $ch = substr $self->{last_stag_name}, length $self->{s_kwd}, 1;
1363        if (length $ch) {        if (length $ch) {
1364          my $CH = $ch;          my $CH = $ch;
# Line 1292  sub _get_next_token ($) { Line 1382  sub _get_next_token ($) {
1382            redo A;            redo A;
1383          }          }
1384        } else { # after "<{tag-name}"        } else { # after "<{tag-name}"
1385          unless ({          unless ($is_space->{$self->{nc}} or
1386                   0x0009 => 1, # HT                  {
                  0x000A => 1, # LF  
                  0x000B => 1, # VT  
                  0x000C => 1, # FF  
                  0x0020 => 1, # SP  
1387                   0x003E => 1, # >                   0x003E => 1, # >
1388                   0x002F => 1, # /                   0x002F => 1, # /
1389                   -1 => 1, # EOF                   -1 => 1, # EOF
# Line 1324  sub _get_next_token ($) { Line 1410  sub _get_next_token ($) {
1410          }          }
1411        }        }
1412      } elsif ($self->{state} == TAG_NAME_STATE) {      } elsif ($self->{state} == TAG_NAME_STATE) {
1413        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  
1414          !!!cp (34);          !!!cp (34);
1415          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;
1416          !!!next-input-character;          !!!next-input-character;
# Line 1400  sub _get_next_token ($) { Line 1482  sub _get_next_token ($) {
1482          redo A;          redo A;
1483        }        }
1484      } elsif ($self->{state} == BEFORE_ATTRIBUTE_NAME_STATE) {      } elsif ($self->{state} == BEFORE_ATTRIBUTE_NAME_STATE) {
1485        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  
1486          !!!cp (45);          !!!cp (45);
1487          ## Stay in the state          ## Stay in the state
1488          !!!next-input-character;          !!!next-input-character;
# Line 1500  sub _get_next_token ($) { Line 1578  sub _get_next_token ($) {
1578          }          }
1579        }; # $before_leave        }; # $before_leave
1580    
1581        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  
1582          !!!cp (59);          !!!cp (59);
1583          $before_leave->();          $before_leave->();
1584          $self->{state} = AFTER_ATTRIBUTE_NAME_STATE;          $self->{state} = AFTER_ATTRIBUTE_NAME_STATE;
# Line 1587  sub _get_next_token ($) { Line 1661  sub _get_next_token ($) {
1661          redo A;          redo A;
1662        }        }
1663      } elsif ($self->{state} == AFTER_ATTRIBUTE_NAME_STATE) {      } elsif ($self->{state} == AFTER_ATTRIBUTE_NAME_STATE) {
1664        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  
1665          !!!cp (71);          !!!cp (71);
1666          ## Stay in the state          ## Stay in the state
1667          !!!next-input-character;          !!!next-input-character;
# Line 1678  sub _get_next_token ($) { Line 1748  sub _get_next_token ($) {
1748          redo A;                  redo A;        
1749        }        }
1750      } elsif ($self->{state} == BEFORE_ATTRIBUTE_VALUE_STATE) {      } elsif ($self->{state} == BEFORE_ATTRIBUTE_VALUE_STATE) {
1751        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        
1752          !!!cp (83);          !!!cp (83);
1753          ## Stay in the state          ## Stay in the state
1754          !!!next-input-character;          !!!next-input-character;
# Line 1863  sub _get_next_token ($) { Line 1929  sub _get_next_token ($) {
1929          redo A;          redo A;
1930        }        }
1931      } elsif ($self->{state} == ATTRIBUTE_VALUE_UNQUOTED_STATE) {      } elsif ($self->{state} == ATTRIBUTE_VALUE_UNQUOTED_STATE) {
1932        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  
1933          !!!cp (107);          !!!cp (107);
1934          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;
1935          !!!next-input-character;          !!!next-input-character;
# Line 1949  sub _get_next_token ($) { Line 2011  sub _get_next_token ($) {
2011          redo A;          redo A;
2012        }        }
2013      } elsif ($self->{state} == AFTER_ATTRIBUTE_VALUE_QUOTED_STATE) {      } elsif ($self->{state} == AFTER_ATTRIBUTE_VALUE_QUOTED_STATE) {
2014        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  
2015          !!!cp (118);          !!!cp (118);
2016          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;          $self->{state} = BEFORE_ATTRIBUTE_NAME_STATE;
2017          !!!next-input-character;          !!!next-input-character;
# Line 2394  sub _get_next_token ($) { Line 2452  sub _get_next_token ($) {
2452          redo A;          redo A;
2453        }        }
2454      } elsif ($self->{state} == DOCTYPE_STATE) {      } elsif ($self->{state} == DOCTYPE_STATE) {
2455        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  
2456          !!!cp (155);          !!!cp (155);
2457          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;          $self->{state} = BEFORE_DOCTYPE_NAME_STATE;
2458          !!!next-input-character;          !!!next-input-character;
# Line 2411  sub _get_next_token ($) { Line 2465  sub _get_next_token ($) {
2465          redo A;          redo A;
2466        }        }
2467      } elsif ($self->{state} == BEFORE_DOCTYPE_NAME_STATE) {      } elsif ($self->{state} == BEFORE_DOCTYPE_NAME_STATE) {
2468        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  
2469          !!!cp (157);          !!!cp (157);
2470          ## Stay in the state          ## Stay in the state
2471          !!!next-input-character;          !!!next-input-character;
# Line 2442  sub _get_next_token ($) { Line 2492  sub _get_next_token ($) {
2492          !!!cp (160);          !!!cp (160);
2493          $self->{ct}->{name} = chr $self->{nc};          $self->{ct}->{name} = chr $self->{nc};
2494          delete $self->{ct}->{quirks};          delete $self->{ct}->{quirks};
 ## ISSUE: "Set the token's name name to the" in the spec  
2495          $self->{state} = DOCTYPE_NAME_STATE;          $self->{state} = DOCTYPE_NAME_STATE;
2496          !!!next-input-character;          !!!next-input-character;
2497          redo A;          redo A;
2498        }        }
2499      } elsif ($self->{state} == DOCTYPE_NAME_STATE) {      } elsif ($self->{state} == DOCTYPE_NAME_STATE) {
2500  ## ISSUE: Redundant "First," in the spec.  ## ISSUE: Redundant "First," in the spec.
2501        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  
2502          !!!cp (161);          !!!cp (161);
2503          $self->{state} = AFTER_DOCTYPE_NAME_STATE;          $self->{state} = AFTER_DOCTYPE_NAME_STATE;
2504          !!!next-input-character;          !!!next-input-character;
# Line 2485  sub _get_next_token ($) { Line 2530  sub _get_next_token ($) {
2530          redo A;          redo A;
2531        }        }
2532      } elsif ($self->{state} == AFTER_DOCTYPE_NAME_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_NAME_STATE) {
2533        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  
2534          !!!cp (165);          !!!cp (165);
2535          ## Stay in the state          ## Stay in the state
2536          !!!next-input-character;          !!!next-input-character;
# Line 2612  sub _get_next_token ($) { Line 2653  sub _get_next_token ($) {
2653          redo A;          redo A;
2654        }        }
2655      } elsif ($self->{state} == BEFORE_DOCTYPE_PUBLIC_IDENTIFIER_STATE) {      } elsif ($self->{state} == BEFORE_DOCTYPE_PUBLIC_IDENTIFIER_STATE) {
2656        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}}) {  
2657          !!!cp (181);          !!!cp (181);
2658          ## Stay in the state          ## Stay in the state
2659          !!!next-input-character;          !!!next-input-character;
# Line 2742  sub _get_next_token ($) { Line 2780  sub _get_next_token ($) {
2780          redo A;          redo A;
2781        }        }
2782      } elsif ($self->{state} == AFTER_DOCTYPE_PUBLIC_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_PUBLIC_IDENTIFIER_STATE) {
2783        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}}) {  
2784          !!!cp (195);          !!!cp (195);
2785          ## Stay in the state          ## Stay in the state
2786          !!!next-input-character;          !!!next-input-character;
# Line 2791  sub _get_next_token ($) { Line 2826  sub _get_next_token ($) {
2826          redo A;          redo A;
2827        }        }
2828      } elsif ($self->{state} == BEFORE_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == BEFORE_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
2829        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}}) {  
2830          !!!cp (201);          !!!cp (201);
2831          ## Stay in the state          ## Stay in the state
2832          !!!next-input-character;          !!!next-input-character;
# Line 2920  sub _get_next_token ($) { Line 2952  sub _get_next_token ($) {
2952          redo A;          redo A;
2953        }        }
2954      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {      } elsif ($self->{state} == AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE) {
2955        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}}) {  
2956          !!!cp (215);          !!!cp (215);
2957          ## Stay in the state          ## Stay in the state
2958          !!!next-input-character;          !!!next-input-character;
# Line 2966  sub _get_next_token ($) { Line 2995  sub _get_next_token ($) {
2995          redo A;          redo A;
2996        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
2997          !!!cp (220);          !!!cp (220);
         !!!parse-error (type => 'unclosed DOCTYPE');  
2998          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
2999          ## reconsume          ## reconsume
3000    
# Line 3055  sub _get_next_token ($) { Line 3083  sub _get_next_token ($) {
3083          redo A;          redo A;
3084        }        }
3085      } elsif ($self->{state} == ENTITY_STATE) {      } elsif ($self->{state} == ENTITY_STATE) {
3086        if ({        if ($is_space->{$self->{nc}} or
3087          0x0009 => 1, 0x000A => 1, 0x000B => 1, 0x000C => 1, # HT, LF, VT, FF,            {
3088          0x0020 => 1, 0x003C => 1, 0x0026 => 1, -1 => 1, # SP, <, &              0x003C => 1, 0x0026 => 1, -1 => 1, # <, &
3089          $self->{entity_add} => 1,              $self->{entity_add} => 1,
3090        }->{$self->{nc}}) {            }->{$self->{nc}}) {
3091          !!!cp (1001);          !!!cp (1001);
3092          ## Don't consume          ## Don't consume
3093          ## No error          ## No error
# Line 3178  sub _get_next_token ($) { Line 3206  sub _get_next_token ($) {
3206        my $code = $self->{s_kwd};        my $code = $self->{s_kwd};
3207        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3208        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3209        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {        if ($charref_map->{$code}) {
3210          !!!cp (1015);          !!!cp (1015);
3211          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3212                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
3213                          line => $l, column => $c);                          line => $l, column => $c);
3214          $code = 0xFFFD;          $code = $charref_map->{$code};
3215        } elsif ($code > 0x10FFFF) {        } elsif ($code > 0x10FFFF) {
3216          !!!cp (1016);          !!!cp (1016);
3217          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3218                          text => (sprintf 'U-%08X', $code),                          text => (sprintf 'U-%08X', $code),
3219                          line => $l, column => $c);                          line => $l, column => $c);
3220          $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};  
3221        }        }
3222    
3223        if ($self->{prev_state} == DATA_STATE) {        if ($self->{prev_state} == DATA_STATE) {
# Line 3297  sub _get_next_token ($) { Line 3314  sub _get_next_token ($) {
3314        my $code = $self->{s_kwd};        my $code = $self->{s_kwd};
3315        my $l = $self->{line_prev};        my $l = $self->{line_prev};
3316        my $c = $self->{column_prev};        my $c = $self->{column_prev};
3317        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {        if ($charref_map->{$code}) {
3318          !!!cp (1008);          !!!cp (1008);
3319          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3320                          text => (sprintf 'U+%04X', $code),                          text => (sprintf 'U+%04X', $code),
3321                          line => $l, column => $c);                          line => $l, column => $c);
3322          $code = 0xFFFD;          $code = $charref_map->{$code};
3323        } elsif ($code > 0x10FFFF) {        } elsif ($code > 0x10FFFF) {
3324          !!!cp (1009);          !!!cp (1009);
3325          !!!parse-error (type => 'invalid character reference',          !!!parse-error (type => 'invalid character reference',
3326                          text => (sprintf 'U-%08X', $code),                          text => (sprintf 'U-%08X', $code),
3327                          line => $l, column => $c);                          line => $l, column => $c);
3328          $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};  
3329        }        }
3330    
3331        if ($self->{prev_state} == DATA_STATE) {        if ($self->{prev_state} == DATA_STATE) {
# Line 3465  sub _construct_tree ($) { Line 3474  sub _construct_tree ($) {
3474    ## When an interactive UA render the $self->{document} available    ## When an interactive UA render the $self->{document} available
3475    ## to the user, or when it begin accepting user input, are    ## to the user, or when it begin accepting user input, are
3476    ## 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  
3477        
3478    !!!next-token;    !!!next-token;
3479    
3480    undef $self->{form_element};    undef $self->{form_element};
3481    undef $self->{head_element};    undef $self->{head_element};
3482      undef $self->{head_element_inserted};
3483    $self->{open_elements} = [];    $self->{open_elements} = [];
3484    undef $self->{inner_html_node};    undef $self->{inner_html_node};
3485      undef $self->{ignore_newline};
3486    
3487    ## NOTE: The "initial" insertion mode.    ## NOTE: The "initial" insertion mode.
3488    $self->_tree_construction_initial; # MUST    $self->_tree_construction_initial; # MUST
# Line 3657  sub _tree_construction_initial ($) { Line 3664  sub _tree_construction_initial ($) {
3664        !!!ack-later;        !!!ack-later;
3665        return;        return;
3666      } elsif ($token->{type} == CHARACTER_TOKEN) {      } elsif ($token->{type} == CHARACTER_TOKEN) {
3667        if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { # \x0D        if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
3668          ## Ignore the token          ## Ignore the token
3669    
3670          unless (length $token->{data}) {          unless (length $token->{data}) {
# Line 3714  sub _tree_construction_root_element ($) Line 3721  sub _tree_construction_root_element ($)
3721          !!!next-token;          !!!next-token;
3722          redo B;          redo B;
3723        } elsif ($token->{type} == CHARACTER_TOKEN) {        } elsif ($token->{type} == CHARACTER_TOKEN) {
3724          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) { # \x0D          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
3725            ## Ignore the token.            ## Ignore the token.
3726    
3727            unless (length $token->{data}) {            unless (length $token->{data}) {
# Line 3781  sub _tree_construction_root_element ($) Line 3788  sub _tree_construction_root_element ($)
3788      ## NOTE: Reprocess the token.      ## NOTE: Reprocess the token.
3789      !!!ack-later;      !!!ack-later;
3790      return; ## Go to the "before head" insertion mode.      return; ## Go to the "before head" insertion mode.
   
     ## ISSUE: There is an issue in the spec  
3791    } # B    } # B
3792    
3793    die "$0: _tree_construction_root_element: This should never be reached";    die "$0: _tree_construction_root_element: This should never be reached";
# Line 3818  sub _reset_insertion_mode ($) { Line 3823  sub _reset_insertion_mode ($) {
3823          ## SVG elements.  Currently the HTML syntax supports only MathML and          ## SVG elements.  Currently the HTML syntax supports only MathML and
3824          ## SVG elements as foreigners.          ## SVG elements as foreigners.
3825          $new_mode = IN_BODY_IM | IN_FOREIGN_CONTENT_IM;          $new_mode = IN_BODY_IM | IN_FOREIGN_CONTENT_IM;
3826        } elsif ($node->[1] & TABLE_CELL_EL) {        } elsif ($node->[1] == TABLE_CELL_EL) {
3827          if ($last) {          if ($last) {
3828            !!!cp ('t28.2');            !!!cp ('t28.2');
3829            #            #
# Line 3847  sub _reset_insertion_mode ($) { Line 3852  sub _reset_insertion_mode ($) {
3852        $self->{insertion_mode} = $new_mode and return if defined $new_mode;        $self->{insertion_mode} = $new_mode and return if defined $new_mode;
3853                
3854        ## Step 15        ## Step 15
3855        if ($node->[1] & HTML_EL) {        if ($node->[1] == HTML_EL) {
3856          unless (defined $self->{head_element}) {          unless (defined $self->{head_element}) {
3857            !!!cp ('t29');            !!!cp ('t29');
3858            $self->{insertion_mode} = BEFORE_HEAD_IM;            $self->{insertion_mode} = BEFORE_HEAD_IM;
# Line 3979  sub _tree_construction_main ($) { Line 3984  sub _tree_construction_main ($) {
3984    
3985      ## Step 1      ## Step 1
3986      my $start_tag_name = $token->{tag_name};      my $start_tag_name = $token->{tag_name};
3987      my $el;      !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
     !!!create-element ($el, $HTML_NS, $start_tag_name, $token->{attributes}, $token);  
3988    
3989      ## Step 2      ## Step 2
     $insert->($el);  
   
     ## Step 3  
3990      $self->{content_model} = $content_model_flag; # CDATA or RCDATA      $self->{content_model} = $content_model_flag; # CDATA or RCDATA
3991      delete $self->{escape}; # MUST      delete $self->{escape}; # MUST
3992    
3993      ## Step 4      ## Step 3, 4
3994      my $text = '';      $self->{insertion_mode} |= IN_CDATA_RCDATA_IM;
     !!!nack ('t40.1');  
     !!!next-token;  
     while ($token->{type} == CHARACTER_TOKEN) { # or until stop tokenizing  
       !!!cp ('t40');  
       $text .= $token->{data};  
       !!!next-token;  
     }  
3995    
3996      ## Step 5      !!!nack ('t40.1');
     if (length $text) {  
       !!!cp ('t41');  
       my $text = $self->{document}->create_text_node ($text);  
       $el->append_child ($text);  
     }  
   
     ## Step 6  
     $self->{content_model} = PCDATA_CONTENT_MODEL;  
   
     ## Step 7  
     if ($token->{type} == END_TAG_TOKEN and  
         $token->{tag_name} eq $start_tag_name) {  
       !!!cp ('t42');  
       ## Ignore the token  
     } else {  
       ## NOTE: An end-of-file token.  
       if ($content_model_flag == CDATA_CONTENT_MODEL) {  
         !!!cp ('t43');  
         !!!parse-error (type => 'in CDATA:#eof', token => $token);  
       } elsif ($content_model_flag == RCDATA_CONTENT_MODEL) {  
         !!!cp ('t44');  
         !!!parse-error (type => 'in RCDATA:#eof', token => $token);  
       } else {  
         die "$0: $content_model_flag in parse_rcdata";  
       }  
     }  
3997      !!!next-token;      !!!next-token;
3998    }; # $parse_rcdata    }; # $parse_rcdata
3999    
4000    my $script_start_tag = sub () {    my $script_start_tag = sub () {
4001        ## Step 1
4002      my $script_el;      my $script_el;
4003      !!!create-element ($script_el, $HTML_NS, 'script', $token->{attributes}, $token);      !!!create-element ($script_el, $HTML_NS, 'script', $token->{attributes}, $token);
4004    
4005        ## Step 2
4006      ## TODO: mark as "parser-inserted"      ## TODO: mark as "parser-inserted"
4007    
4008        ## Step 3
4009        ## TODO: Mark as "already executed", if ...
4010    
4011        ## Step 4
4012        $insert->($script_el);
4013    
4014        ## ISSUE: $script_el is not put into the stack
4015        push @{$self->{open_elements}}, [$script_el, $el_category->{script}];
4016    
4017        ## Step 5
4018      $self->{content_model} = CDATA_CONTENT_MODEL;      $self->{content_model} = CDATA_CONTENT_MODEL;
4019      delete $self->{escape}; # MUST      delete $self->{escape}; # MUST
       
     my $text = '';  
     !!!nack ('t45.1');  
     !!!next-token;  
     while ($token->{type} == CHARACTER_TOKEN) {  
       !!!cp ('t45');  
       $text .= $token->{data};  
       !!!next-token;  
     } # stop if non-character token or tokenizer stops tokenising  
     if (length $text) {  
       !!!cp ('t46');  
       $script_el->manakai_append_text ($text);  
     }  
                 
     $self->{content_model} = PCDATA_CONTENT_MODEL;  
4020    
4021      if ($token->{type} == END_TAG_TOKEN and      ## Step 6-7
4022          $token->{tag_name} eq 'script') {      $self->{insertion_mode} |= IN_CDATA_RCDATA_IM;
       !!!cp ('t47');  
       ## Ignore the token  
     } else {  
       !!!cp ('t48');  
       !!!parse-error (type => 'in CDATA:#eof', token => $token);  
       ## ISSUE: And ignore?  
       ## TODO: mark as "already executed"  
     }  
       
     if (defined $self->{inner_html_node}) {  
       !!!cp ('t49');  
       ## TODO: mark as "already executed"  
     } else {  
       !!!cp ('t50');  
       ## TODO: $old_insertion_point = current insertion point  
       ## TODO: insertion point = just before the next input character  
4023    
4024        $insert->($script_el);      !!!nack ('t40.2');
         
       ## TODO: insertion point = $old_insertion_point (might be "undefined")  
         
       ## TODO: if there is a script that will execute as soon as the parser resume, then...  
     }  
       
4025      !!!next-token;      !!!next-token;
4026    }; # $script_start_tag    }; # $script_start_tag
4027    
4028    ## NOTE: $open_tables->[-1]->[0] is the "current table" element node.    ## NOTE: $open_tables->[-1]->[0] is the "current table" element node.
4029    ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag.    ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag.
4030      ## NOTE: $open_tables->[-1]->[2] is set false when non-Text node inserted.
4031    my $open_tables = [[$self->{open_elements}->[0]->[0]]];    my $open_tables = [[$self->{open_elements}->[0]->[0]]];
4032    
4033    my $formatting_end_tag = sub {    my $formatting_end_tag = sub {
# Line 4167  sub _tree_construction_main ($) { Line 4112  sub _tree_construction_main ($) {
4112            !!!cp ('t59');            !!!cp ('t59');
4113            $furthest_block = $node;            $furthest_block = $node;
4114            $furthest_block_i_in_open = $_;            $furthest_block_i_in_open = $_;
4115              ## NOTE: The topmost (eldest) node.
4116          } elsif ($node->[0] eq $formatting_element->[0]) {          } elsif ($node->[0] eq $formatting_element->[0]) {
4117            !!!cp ('t60');            !!!cp ('t60');
4118            last OE;            last OE;
# Line 4253  sub _tree_construction_main ($) { Line 4199  sub _tree_construction_main ($) {
4199          my $foster_parent_element;          my $foster_parent_element;
4200          my $next_sibling;          my $next_sibling;
4201          OE: for (reverse 0..$#{$self->{open_elements}}) {          OE: for (reverse 0..$#{$self->{open_elements}}) {
4202            if ($self->{open_elements}->[$_]->[1] & TABLE_EL) {            if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {
4203                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
4204                               if (defined $parent and $parent->node_type == 1) {                               if (defined $parent and $parent->node_type == 1) {
4205                                 !!!cp ('t65.1');                                 !!!cp ('t65.1');
# Line 4313  sub _tree_construction_main ($) { Line 4259  sub _tree_construction_main ($) {
4259            $i = $_;            $i = $_;
4260          }          }
4261        } # OE        } # OE
4262        splice @{$self->{open_elements}}, $i + 1, 1, $clone;        splice @{$self->{open_elements}}, $i + 1, 0, $clone;
4263                
4264        ## Step 14        ## Step 14
4265        redo FET;        redo FET;
# Line 4331  sub _tree_construction_main ($) { Line 4277  sub _tree_construction_main ($) {
4277        my $foster_parent_element;        my $foster_parent_element;
4278        my $next_sibling;        my $next_sibling;
4279        OE: for (reverse 0..$#{$self->{open_elements}}) {        OE: for (reverse 0..$#{$self->{open_elements}}) {
4280          if ($self->{open_elements}->[$_]->[1] & TABLE_EL) {          if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {
4281                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
4282                               if (defined $parent and $parent->node_type == 1) {                               if (defined $parent and $parent->node_type == 1) {
4283                                 !!!cp ('t70');                                 !!!cp ('t70');
# Line 4356  sub _tree_construction_main ($) { Line 4302  sub _tree_construction_main ($) {
4302      }      }
4303    }; # $insert_to_foster    }; # $insert_to_foster
4304    
4305      ## NOTE: Insert a character (MUST): When a character is inserted, if
4306      ## the last node that was inserted by the parser is a Text node and
4307      ## the character has to be inserted after that node, then the
4308      ## character is appended to the Text node.  However, if any other
4309      ## node is inserted by the parser, then a new Text node is created
4310      ## and the character is appended as that Text node.  If I'm not
4311      ## wrong, for a parser with scripting disabled, there are only two
4312      ## cases where this occurs.  One is the case where an element node
4313      ## is inserted to the |head| element.  This is covered by using the
4314      ## |$self->{head_element_inserted}| flag.  Another is the case where
4315      ## an element or comment is inserted into the |table| subtree while
4316      ## foster parenting happens.  This is covered by using the [2] flag
4317      ## of the |$open_tables| structure.  All other cases are handled
4318      ## simply by calling |manakai_append_text| method.
4319    
4320      ## TODO: |<body><script>document.write("a<br>");
4321      ## document.body.removeChild (document.body.lastChild);
4322      ## document.write ("b")</script>|
4323    
4324    B: while (1) {    B: while (1) {
4325      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
4326        !!!cp ('t73');        !!!cp ('t73');
# Line 4403  sub _tree_construction_main ($) { Line 4368  sub _tree_construction_main ($) {
4368        } else {        } else {
4369          !!!cp ('t87');          !!!cp ('t87');
4370          $self->{open_elements}->[-1]->[0]->append_child ($comment);          $self->{open_elements}->[-1]->[0]->append_child ($comment);
4371            $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
4372        }        }
4373        !!!next-token;        !!!next-token;
4374        next B;        next B;
4375        } elsif ($self->{insertion_mode} & IN_CDATA_RCDATA_IM) {
4376          if ($token->{type} == CHARACTER_TOKEN) {
4377            $token->{data} =~ s/^\x0A// if $self->{ignore_newline};
4378            delete $self->{ignore_newline};
4379    
4380            if (length $token->{data}) {
4381              !!!cp ('t43');
4382              $self->{open_elements}->[-1]->[0]->manakai_append_text
4383                  ($token->{data});
4384            } else {
4385              !!!cp ('t43.1');
4386            }
4387            !!!next-token;
4388            next B;
4389          } elsif ($token->{type} == END_TAG_TOKEN) {
4390            delete $self->{ignore_newline};
4391    
4392            if ($token->{tag_name} eq 'script') {
4393              !!!cp ('t50');
4394              
4395              ## Para 1-2
4396              my $script = pop @{$self->{open_elements}};
4397              
4398              ## Para 3
4399              $self->{insertion_mode} &= ~ IN_CDATA_RCDATA_IM;
4400    
4401              ## Para 4
4402              ## TODO: $old_insertion_point = $current_insertion_point;
4403              ## TODO: $current_insertion_point = just before $self->{nc};
4404    
4405              ## Para 5
4406              ## TODO: Run the $script->[0].
4407    
4408              ## Para 6
4409              ## TODO: $current_insertion_point = $old_insertion_point;
4410    
4411              ## Para 7
4412              ## TODO: if ($pending_external_script) {
4413                ## TODO: ...
4414              ## TODO: }
4415    
4416              !!!next-token;
4417              next B;
4418            } else {
4419              !!!cp ('t42');
4420    
4421              pop @{$self->{open_elements}};
4422    
4423              $self->{insertion_mode} &= ~ IN_CDATA_RCDATA_IM;
4424              !!!next-token;
4425              next B;
4426            }
4427          } elsif ($token->{type} == END_OF_FILE_TOKEN) {
4428            delete $self->{ignore_newline};
4429    
4430            !!!cp ('t44');
4431            !!!parse-error (type => 'not closed',
4432                            text => $self->{open_elements}->[-1]->[0]
4433                                ->manakai_local_name,
4434                            token => $token);
4435    
4436            #if ($self->{open_elements}->[-1]->[1] == SCRIPT_EL) {
4437            #  ## TODO: Mark as "already executed"
4438            #}
4439    
4440            pop @{$self->{open_elements}};
4441    
4442            $self->{insertion_mode} &= ~ IN_CDATA_RCDATA_IM;
4443            ## Reprocess.
4444            next B;
4445          } else {
4446            die "$0: $token->{type}: In CDATA/RCDATA: Unknown token type";        
4447          }
4448      } elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM) {      } elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM) {
4449        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
4450          !!!cp ('t87.1');          !!!cp ('t87.1');
# Line 4417  sub _tree_construction_main ($) { Line 4456  sub _tree_construction_main ($) {
4456               $self->{open_elements}->[-1]->[1] & FOREIGN_FLOW_CONTENT_EL) or               $self->{open_elements}->[-1]->[1] & FOREIGN_FLOW_CONTENT_EL) or
4457              not ($self->{open_elements}->[-1]->[1] & FOREIGN_EL) or              not ($self->{open_elements}->[-1]->[1] & FOREIGN_EL) or
4458              ($token->{tag_name} eq 'svg' and              ($token->{tag_name} eq 'svg' and
4459               $self->{open_elements}->[-1]->[1] & MML_AXML_EL)) {               $self->{open_elements}->[-1]->[1] == MML_AXML_EL)) {
4460            ## NOTE: "using the rules for secondary insertion mode"then"continue"            ## NOTE: "using the rules for secondary insertion mode"then"continue"
4461            !!!cp ('t87.2');            !!!cp ('t87.2');
4462            #            #
# Line 4518  sub _tree_construction_main ($) { Line 4557  sub _tree_construction_main ($) {
4557          pop @{$self->{open_elements}}          pop @{$self->{open_elements}}
4558              while $self->{open_elements}->[-1]->[1] & FOREIGN_EL;              while $self->{open_elements}->[-1]->[1] & FOREIGN_EL;
4559    
4560            ## NOTE: |<span><svg>| ... two parse errors, |<svg>| ... a parse error.
4561    
4562          $self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM;          $self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM;
4563          ## Reprocess.          ## Reprocess.
4564          next B;          next B;
# Line 4528  sub _tree_construction_main ($) { Line 4569  sub _tree_construction_main ($) {
4569    
4570      if ($self->{insertion_mode} & HEAD_IMS) {      if ($self->{insertion_mode} & HEAD_IMS) {
4571        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
4572          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
4573            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4574              !!!cp ('t88.2');              if ($self->{head_element_inserted}) {
4575              $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);                !!!cp ('t88.3');
4576              #                $self->{open_elements}->[-1]->[0]->append_child
4577                    ($self->{document}->create_text_node ($1));
4578                  delete $self->{head_element_inserted};
4579                  ## NOTE: |</head> <link> |
4580                  #
4581                } else {
4582                  !!!cp ('t88.2');
4583                  $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
4584                  ## NOTE: |</head> &#x20;|
4585                  #
4586                }
4587            } else {            } else {
4588              !!!cp ('t88.1');              !!!cp ('t88.1');
4589              ## Ignore the token.              ## Ignore the token.
# Line 4628  sub _tree_construction_main ($) { Line 4679  sub _tree_construction_main ($) {
4679            !!!cp ('t97');            !!!cp ('t97');
4680          }          }
4681    
4682              if ($token->{tag_name} eq 'base') {          if ($token->{tag_name} eq 'base') {
4683                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4684                  !!!cp ('t98');              !!!cp ('t98');
4685                  ## As if </noscript>              ## As if </noscript>
4686                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
4687                  !!!parse-error (type => 'in noscript', text => 'base',              !!!parse-error (type => 'in noscript', text => 'base',
4688                                  token => $token);                              token => $token);
4689                            
4690                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
4691                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
4692                } else {            } else {
4693                  !!!cp ('t99');              !!!cp ('t99');
4694                }            }
4695    
4696                ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
4697                if ($self->{insertion_mode} == AFTER_HEAD_IM) {            if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4698                  !!!cp ('t100');              !!!cp ('t100');
4699                  !!!parse-error (type => 'after head',              !!!parse-error (type => 'after head',
4700                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
4701                  push @{$self->{open_elements}},              push @{$self->{open_elements}},
4702                      [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4703                } else {              $self->{head_element_inserted} = 1;
4704                  !!!cp ('t101');            } else {
4705                }              !!!cp ('t101');
4706                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            }
4707                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4708                pop @{$self->{open_elements}} # <head>            pop @{$self->{open_elements}};
4709                    if $self->{insertion_mode} == AFTER_HEAD_IM;            pop @{$self->{open_elements}} # <head>
4710                !!!nack ('t101.1');                if $self->{insertion_mode} == AFTER_HEAD_IM;
4711                !!!next-token;            !!!nack ('t101.1');
4712                next B;            !!!next-token;
4713              } elsif ($token->{tag_name} eq 'link') {            next B;
4714                ## NOTE: There is a "as if in head" code clone.          } elsif ($token->{tag_name} eq 'link') {
4715                if ($self->{insertion_mode} == AFTER_HEAD_IM) {            ## NOTE: There is a "as if in head" code clone.
4716                  !!!cp ('t102');            if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4717                  !!!parse-error (type => 'after head',              !!!cp ('t102');
4718                                  text => $token->{tag_name}, token => $token);              !!!parse-error (type => 'after head',
4719                  push @{$self->{open_elements}},                              text => $token->{tag_name}, token => $token);
4720                      [$self->{head_element}, $el_category->{head}];              push @{$self->{open_elements}},
4721                } else {                  [$self->{head_element}, $el_category->{head}];
4722                  !!!cp ('t103');              $self->{head_element_inserted} = 1;
4723                }            } else {
4724                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);              !!!cp ('t103');
4725                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.            }
4726                pop @{$self->{open_elements}} # <head>            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4727                    if $self->{insertion_mode} == AFTER_HEAD_IM;            pop @{$self->{open_elements}};
4728                !!!ack ('t103.1');            pop @{$self->{open_elements}} # <head>
4729                !!!next-token;                if $self->{insertion_mode} == AFTER_HEAD_IM;
4730                next B;            !!!ack ('t103.1');
4731              } elsif ($token->{tag_name} eq 'meta') {            !!!next-token;
4732                ## NOTE: There is a "as if in head" code clone.            next B;
4733                if ($self->{insertion_mode} == AFTER_HEAD_IM) {          } elsif ($token->{tag_name} eq 'command' or
4734                  !!!cp ('t104');                   $token->{tag_name} eq 'eventsource') {
4735                  !!!parse-error (type => 'after head',            if ($self->{insertion_mode} == IN_HEAD_IM) {
4736                                  text => $token->{tag_name}, token => $token);              ## NOTE: If the insertion mode at the time of the emission
4737                  push @{$self->{open_elements}},              ## of the token was "before head", $self->{insertion_mode}
4738                      [$self->{head_element}, $el_category->{head}];              ## is already changed to |IN_HEAD_IM|.
4739                } else {  
4740                  !!!cp ('t105');              ## NOTE: There is a "as if in head" code clone.
4741                }              !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4742                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);              pop @{$self->{open_elements}};
4743                my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.              pop @{$self->{open_elements}} # <head>
4744                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4745                !!!ack ('t103.2');
4746                !!!next-token;
4747                next B;
4748              } else {
4749                ## NOTE: "in head noscript" or "after head" insertion mode
4750                ## - in these cases, these tags are treated as same as
4751                ## normal in-body tags.
4752                !!!cp ('t103.3');
4753                #
4754              }
4755            } elsif ($token->{tag_name} eq 'meta') {
4756              ## NOTE: There is a "as if in head" code clone.
4757              if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4758                !!!cp ('t104');
4759                !!!parse-error (type => 'after head',
4760                                text => $token->{tag_name}, token => $token);
4761                push @{$self->{open_elements}},
4762                    [$self->{head_element}, $el_category->{head}];
4763                $self->{head_element_inserted} = 1;
4764              } else {
4765                !!!cp ('t105');
4766              }
4767              !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4768              my $meta_el = pop @{$self->{open_elements}};
4769    
4770                unless ($self->{confident}) {                unless ($self->{confident}) {
4771                  if ($token->{attributes}->{charset}) {                  if ($token->{attributes}->{charset}) {
# Line 4707  sub _tree_construction_main ($) { Line 4783  sub _tree_construction_main ($) {
4783                  } elsif ($token->{attributes}->{content}) {                  } elsif ($token->{attributes}->{content}) {
4784                    if ($token->{attributes}->{content}->{value}                    if ($token->{attributes}->{content}->{value}
4785                        =~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt]                        =~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt]
4786                            [\x09-\x0D\x20]*=                            [\x09\x0A\x0C\x0D\x20]*=
4787                            [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                            [\x09\x0A\x0C\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
4788                            ([^"'\x09-\x0D\x20][^\x09-\x0D\x20\x3B]*))/x) {                            ([^"'\x09\x0A\x0C\x0D\x20]
4789                               [^\x09\x0A\x0C\x0D\x20\x3B]*))/x) {
4790                      !!!cp ('t107');                      !!!cp ('t107');
4791                      ## NOTE: Whether the encoding is supported or not is handled                      ## NOTE: Whether the encoding is supported or not is handled
4792                      ## in the {change_encoding} callback.                      ## in the {change_encoding} callback.
# Line 4746  sub _tree_construction_main ($) { Line 4823  sub _tree_construction_main ($) {
4823                !!!ack ('t110.1');                !!!ack ('t110.1');
4824                !!!next-token;                !!!next-token;
4825                next B;                next B;
4826              } elsif ($token->{tag_name} eq 'title') {          } elsif ($token->{tag_name} eq 'title') {
4827                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4828                  !!!cp ('t111');              !!!cp ('t111');
4829                  ## As if </noscript>              ## As if </noscript>
4830                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
4831                  !!!parse-error (type => 'in noscript', text => 'title',              !!!parse-error (type => 'in noscript', text => 'title',
4832                                  token => $token);                              token => $token);
4833                            
4834                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
4835                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
4836                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4837                  !!!cp ('t112');              !!!cp ('t112');
4838                  !!!parse-error (type => 'after head',              !!!parse-error (type => 'after head',
4839                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
4840                  push @{$self->{open_elements}},              push @{$self->{open_elements}},
4841                      [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4842                } else {              $self->{head_element_inserted} = 1;
4843                  !!!cp ('t113');            } else {
4844                }              !!!cp ('t113');
4845              }
4846    
4847                ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
4848                my $parent = defined $self->{head_element} ? $self->{head_element}            $parse_rcdata->(RCDATA_CONTENT_MODEL);
4849                    : $self->{open_elements}->[-1]->[0];            ## ISSUE: A spec bug [Bug 6038]
4850                $parse_rcdata->(RCDATA_CONTENT_MODEL);            splice @{$self->{open_elements}}, -2, 1, () # <head>
4851                pop @{$self->{open_elements}} # <head>                if ($self->{insertion_mode} & AFTER_HEAD_IM) == AFTER_HEAD_IM;
4852                    if $self->{insertion_mode} == AFTER_HEAD_IM;            next B;
4853                next B;          } elsif ($token->{tag_name} eq 'style' or
4854              } elsif ($token->{tag_name} eq 'style' or                   $token->{tag_name} eq 'noframes') {
4855                       $token->{tag_name} eq 'noframes') {            ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and
4856                ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and            ## insertion mode IN_HEAD_IM)
4857                ## insertion mode IN_HEAD_IM)            ## NOTE: There is a "as if in head" code clone.
4858                ## NOTE: There is a "as if in head" code clone.            if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4859                if ($self->{insertion_mode} == AFTER_HEAD_IM) {              !!!cp ('t114');
4860                  !!!cp ('t114');              !!!parse-error (type => 'after head',
4861                  !!!parse-error (type => 'after head',                              text => $token->{tag_name}, token => $token);
4862                                  text => $token->{tag_name}, token => $token);              push @{$self->{open_elements}},
4863                  push @{$self->{open_elements}},                  [$self->{head_element}, $el_category->{head}];
4864                      [$self->{head_element}, $el_category->{head}];              $self->{head_element_inserted} = 1;
4865                } else {            } else {
4866                  !!!cp ('t115');              !!!cp ('t115');
4867                }            }
4868                $parse_rcdata->(CDATA_CONTENT_MODEL);            $parse_rcdata->(CDATA_CONTENT_MODEL);
4869                pop @{$self->{open_elements}} # <head>            ## ISSUE: A spec bug [Bug 6038]
4870                    if $self->{insertion_mode} == AFTER_HEAD_IM;            splice @{$self->{open_elements}}, -2, 1, () # <head>
4871                next B;                if ($self->{insertion_mode} & AFTER_HEAD_IM) == AFTER_HEAD_IM;
4872              } elsif ($token->{tag_name} eq 'noscript') {            next B;
4873            } elsif ($token->{tag_name} eq 'noscript') {
4874                if ($self->{insertion_mode} == IN_HEAD_IM) {                if ($self->{insertion_mode} == IN_HEAD_IM) {
4875                  !!!cp ('t116');                  !!!cp ('t116');
4876                  ## NOTE: and scripting is disalbed                  ## NOTE: and scripting is disalbed
# Line 4812  sub _tree_construction_main ($) { Line 4891  sub _tree_construction_main ($) {
4891                  !!!cp ('t118');                  !!!cp ('t118');
4892                  #                  #
4893                }                }
4894              } elsif ($token->{tag_name} eq 'script') {          } elsif ($token->{tag_name} eq 'script') {
4895                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4896                  !!!cp ('t119');              !!!cp ('t119');
4897                  ## As if </noscript>              ## As if </noscript>
4898                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
4899                  !!!parse-error (type => 'in noscript', text => 'script',              !!!parse-error (type => 'in noscript', text => 'script',
4900                                  token => $token);                              token => $token);
4901                            
4902                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
4903                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
4904                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4905                  !!!cp ('t120');              !!!cp ('t120');
4906                  !!!parse-error (type => 'after head',              !!!parse-error (type => 'after head',
4907                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
4908                  push @{$self->{open_elements}},              push @{$self->{open_elements}},
4909                      [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4910                } else {              $self->{head_element_inserted} = 1;
4911                  !!!cp ('t121');            } else {
4912                }              !!!cp ('t121');
4913              }
4914    
4915                ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
4916                $script_start_tag->();            $script_start_tag->();
4917                pop @{$self->{open_elements}} # <head>            ## ISSUE: A spec bug  [Bug 6038]
4918                    if $self->{insertion_mode} == AFTER_HEAD_IM;            splice @{$self->{open_elements}}, -2, 1 # <head>
4919                next B;                if ($self->{insertion_mode} & AFTER_HEAD_IM) == AFTER_HEAD_IM;
4920              } elsif ($token->{tag_name} eq 'body' or            next B;
4921                       $token->{tag_name} eq 'frameset') {          } elsif ($token->{tag_name} eq 'body' or
4922                     $token->{tag_name} eq 'frameset') {
4923                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4924                  !!!cp ('t122');                  !!!cp ('t122');
4925                  ## As if </noscript>                  ## As if </noscript>
# Line 4973  sub _tree_construction_main ($) { Line 5054  sub _tree_construction_main ($) {
5054              } elsif ({              } elsif ({
5055                        body => 1, html => 1,                        body => 1, html => 1,
5056                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
5057                if ($self->{insertion_mode} == BEFORE_HEAD_IM or                ## TODO: This branch is entirely redundant.
5058                  if ($self->{insertion_mode} == BEFORE_HEAD_IM or
5059                    $self->{insertion_mode} == IN_HEAD_IM or                    $self->{insertion_mode} == IN_HEAD_IM or
5060                    $self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                    $self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
5061                  !!!cp ('t140');                  !!!cp ('t140');
# Line 5145  sub _tree_construction_main ($) { Line 5227  sub _tree_construction_main ($) {
5227        } else {        } else {
5228          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
5229        }        }
   
           ## ISSUE: An issue in the spec.  
5230      } elsif ($self->{insertion_mode} & BODY_IMS) {      } elsif ($self->{insertion_mode} & BODY_IMS) {
5231            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
5232              !!!cp ('t150');              !!!cp ('t150');
# Line 5166  sub _tree_construction_main ($) { Line 5246  sub _tree_construction_main ($) {
5246                  ## have an element in table scope                  ## have an element in table scope
5247                  for (reverse 0..$#{$self->{open_elements}}) {                  for (reverse 0..$#{$self->{open_elements}}) {
5248                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
5249                    if ($node->[1] & TABLE_CELL_EL) {                    if ($node->[1] == TABLE_CELL_EL) {
5250                      !!!cp ('t151');                      !!!cp ('t151');
5251    
5252                      ## Close the cell                      ## Close the cell
# Line 5200  sub _tree_construction_main ($) { Line 5280  sub _tree_construction_main ($) {
5280                  INSCOPE: {                  INSCOPE: {
5281                    for (reverse 0..$#{$self->{open_elements}}) {                    for (reverse 0..$#{$self->{open_elements}}) {
5282                      my $node = $self->{open_elements}->[$_];                      my $node = $self->{open_elements}->[$_];
5283                      if ($node->[1] & CAPTION_EL) {                      if ($node->[1] == CAPTION_EL) {
5284                        !!!cp ('t155');                        !!!cp ('t155');
5285                        $i = $_;                        $i = $_;
5286                        last INSCOPE;                        last INSCOPE;
# Line 5226  sub _tree_construction_main ($) { Line 5306  sub _tree_construction_main ($) {
5306                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
5307                  }                  }
5308    
5309                  unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {                  unless ($self->{open_elements}->[-1]->[1] == CAPTION_EL) {
5310                    !!!cp ('t159');                    !!!cp ('t159');
5311                    !!!parse-error (type => 'not closed',                    !!!parse-error (type => 'not closed',
5312                                    text => $self->{open_elements}->[-1]->[0]                                    text => $self->{open_elements}->[-1]->[0]
# Line 5323  sub _tree_construction_main ($) { Line 5403  sub _tree_construction_main ($) {
5403                  INSCOPE: {                  INSCOPE: {
5404                    for (reverse 0..$#{$self->{open_elements}}) {                    for (reverse 0..$#{$self->{open_elements}}) {
5405                      my $node = $self->{open_elements}->[$_];                      my $node = $self->{open_elements}->[$_];
5406                      if ($node->[1] & CAPTION_EL) {                      if ($node->[1] == CAPTION_EL) {
5407                        !!!cp ('t171');                        !!!cp ('t171');
5408                        $i = $_;                        $i = $_;
5409                        last INSCOPE;                        last INSCOPE;
# Line 5348  sub _tree_construction_main ($) { Line 5428  sub _tree_construction_main ($) {
5428                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
5429                  }                  }
5430                                    
5431                  unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {                  unless ($self->{open_elements}->[-1]->[1] == CAPTION_EL) {
5432                    !!!cp ('t175');                    !!!cp ('t175');
5433                    !!!parse-error (type => 'not closed',                    !!!parse-error (type => 'not closed',
5434                                    text => $self->{open_elements}->[-1]->[0]                                    text => $self->{open_elements}->[-1]->[0]
# Line 5398  sub _tree_construction_main ($) { Line 5478  sub _tree_construction_main ($) {
5478                                line => $token->{line},                                line => $token->{line},
5479                                column => $token->{column}};                                column => $token->{column}};
5480                      next B;                      next B;
5481                    } elsif ($node->[1] & TABLE_CELL_EL) {                    } elsif ($node->[1] == TABLE_CELL_EL) {
5482                      !!!cp ('t180');                      !!!cp ('t180');
5483                      $tn = $node->[0]->manakai_local_name;                      $tn = $node->[0]->manakai_local_name;
5484                      ## NOTE: There is exactly one |td| or |th| element                      ## NOTE: There is exactly one |td| or |th| element
# Line 5427  sub _tree_construction_main ($) { Line 5507  sub _tree_construction_main ($) {
5507                my $i;                my $i;
5508                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5509                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
5510                  if ($node->[1] & CAPTION_EL) {                  if ($node->[1] == CAPTION_EL) {
5511                    !!!cp ('t184');                    !!!cp ('t184');
5512                    $i = $_;                    $i = $_;
5513                    last INSCOPE;                    last INSCOPE;
# Line 5451  sub _tree_construction_main ($) { Line 5531  sub _tree_construction_main ($) {
5531                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
5532                }                }
5533    
5534                unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {                unless ($self->{open_elements}->[-1]->[1] == CAPTION_EL) {
5535                  !!!cp ('t188');                  !!!cp ('t188');
5536                  !!!parse-error (type => 'not closed',                  !!!parse-error (type => 'not closed',
5537                                  text => $self->{open_elements}->[-1]->[0]                                  text => $self->{open_elements}->[-1]->[0]
# Line 5518  sub _tree_construction_main ($) { Line 5598  sub _tree_construction_main ($) {
5598      } elsif ($self->{insertion_mode} & TABLE_IMS) {      } elsif ($self->{insertion_mode} & TABLE_IMS) {
5599        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
5600          if (not $open_tables->[-1]->[1] and # tainted          if (not $open_tables->[-1]->[1] and # tainted
5601              $token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {              $token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
5602            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
5603                                
5604            unless (length $token->{data}) {            unless (length $token->{data}) {
# Line 5532  sub _tree_construction_main ($) { Line 5612  sub _tree_construction_main ($) {
5612    
5613          !!!parse-error (type => 'in table:#text', token => $token);          !!!parse-error (type => 'in table:#text', token => $token);
5614    
5615              ## As if in body, but insert into foster parent element          ## NOTE: As if in body, but insert into the foster parent element.
5616              ## 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);  
5617                            
5618              if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {          if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {
5619                # MUST            # MUST
5620                my $foster_parent_element;            my $foster_parent_element;
5621                my $next_sibling;            my $next_sibling;
5622                my $prev_sibling;            my $prev_sibling;
5623                OE: for (reverse 0..$#{$self->{open_elements}}) {            OE: for (reverse 0..$#{$self->{open_elements}}) {
5624                  if ($self->{open_elements}->[$_]->[1] & TABLE_EL) {              if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {
5625                    my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
5626                    if (defined $parent and $parent->node_type == 1) {                if (defined $parent and $parent->node_type == 1) {
5627                      !!!cp ('t196');                  $foster_parent_element = $parent;
5628                      $foster_parent_element = $parent;                  !!!cp ('t196');
5629                      $next_sibling = $self->{open_elements}->[$_]->[0];                  $next_sibling = $self->{open_elements}->[$_]->[0];
5630                      $prev_sibling = $next_sibling->previous_sibling;                  $prev_sibling = $next_sibling->previous_sibling;
5631                    } 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});  
5632                } else {                } else {
5633                  !!!cp ('t199');                  !!!cp ('t197');
5634                  $foster_parent_element->insert_before                  $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];
5635                    ($self->{document}->create_text_node ($token->{data}),                  $prev_sibling = $foster_parent_element->last_child;
5636                     $next_sibling);                  #
5637                }                }
5638                  last OE;
5639                }
5640              } # OE
5641              $foster_parent_element = $self->{open_elements}->[0]->[0] and
5642              $prev_sibling = $foster_parent_element->last_child
5643                  unless defined $foster_parent_element;
5644              undef $prev_sibling unless $open_tables->[-1]->[2]; # ~node inserted
5645              if (defined $prev_sibling and
5646                  $prev_sibling->node_type == 3) {
5647                !!!cp ('t198');
5648                $prev_sibling->manakai_append_text ($token->{data});
5649              } else {
5650                !!!cp ('t199');
5651                $foster_parent_element->insert_before
5652                    ($self->{document}->create_text_node ($token->{data}),
5653                     $next_sibling);
5654              }
5655            $open_tables->[-1]->[1] = 1; # tainted            $open_tables->[-1]->[1] = 1; # tainted
5656              $open_tables->[-1]->[2] = 1; # ~node inserted
5657          } else {          } else {
5658              ## NOTE: Fragment case or in a foster parent'ed element
5659              ## (e.g. |<table><span>a|).  In fragment case, whether the
5660              ## character is appended to existing node or a new node is
5661              ## created is irrelevant, since the foster parent'ed nodes
5662              ## are discarded and fragment parsing does not invoke any
5663              ## script.
5664            !!!cp ('t200');            !!!cp ('t200');
5665            $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});            $self->{open_elements}->[-1]->[0]->manakai_append_text
5666                  ($token->{data});
5667          }          }
5668                            
5669          !!!next-token;          !!!next-token;
# Line 5612  sub _tree_construction_main ($) { Line 5700  sub _tree_construction_main ($) {
5700                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5701              }              }
5702                                    
5703                  $self->{insertion_mode} = IN_ROW_IM;              $self->{insertion_mode} = IN_ROW_IM;
5704                  if ($token->{tag_name} eq 'tr') {              if ($token->{tag_name} eq 'tr') {
5705                    !!!cp ('t204');                !!!cp ('t204');
5706                    !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5707                    !!!nack ('t204');                $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5708                    !!!next-token;                !!!nack ('t204');
5709                    next B;                !!!next-token;
5710                  } else {                next B;
5711                    !!!cp ('t205');              } else {
5712                    !!!insert-element ('tr',, $token);                !!!cp ('t205');
5713                    ## reprocess in the "in row" insertion mode                !!!insert-element ('tr',, $token);
5714                  }                ## reprocess in the "in row" insertion mode
5715                } else {              }
5716                  !!!cp ('t206');            } else {
5717                }              !!!cp ('t206');
5718              }
5719    
5720                ## Clear back to table row context                ## Clear back to table row context
5721                while (not ($self->{open_elements}->[-1]->[1]                while (not ($self->{open_elements}->[-1]->[1]
# Line 5635  sub _tree_construction_main ($) { Line 5724  sub _tree_construction_main ($) {
5724                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
5725                }                }
5726                                
5727                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5728                $self->{insertion_mode} = IN_CELL_IM;            $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5729              $self->{insertion_mode} = IN_CELL_IM;
5730    
5731                push @$active_formatting_elements, ['#marker', ''];            push @$active_formatting_elements, ['#marker', ''];
5732                                
5733                !!!nack ('t207.1');            !!!nack ('t207.1');
5734              !!!next-token;
5735              next B;
5736            } elsif ({
5737                      caption => 1, col => 1, colgroup => 1,
5738                      tbody => 1, tfoot => 1, thead => 1,
5739                      tr => 1, # $self->{insertion_mode} == IN_ROW_IM
5740                     }->{$token->{tag_name}}) {
5741              if ($self->{insertion_mode} == IN_ROW_IM) {
5742                ## As if </tr>
5743                ## have an element in table scope
5744                my $i;
5745                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5746                  my $node = $self->{open_elements}->[$_];
5747                  if ($node->[1] == TABLE_ROW_EL) {
5748                    !!!cp ('t208');
5749                    $i = $_;
5750                    last INSCOPE;
5751                  } elsif ($node->[1] & TABLE_SCOPING_EL) {
5752                    !!!cp ('t209');
5753                    last INSCOPE;
5754                  }
5755                } # INSCOPE
5756                unless (defined $i) {
5757                  !!!cp ('t210');
5758                  ## TODO: This type is wrong.
5759                  !!!parse-error (type => 'unmacthed end tag',
5760                                  text => $token->{tag_name}, token => $token);
5761                  ## Ignore the token
5762                  !!!nack ('t210.1');
5763                !!!next-token;                !!!next-token;
5764                next B;                next B;
5765              } 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;  
                 }  
5766                                    
5767                  ## Clear back to table row context                  ## Clear back to table row context
5768                  while (not ($self->{open_elements}->[-1]->[1]                  while (not ($self->{open_elements}->[-1]->[1]
# Line 5700  sub _tree_construction_main ($) { Line 5790  sub _tree_construction_main ($) {
5790                  my $i;                  my $i;
5791                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5792                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
5793                    if ($node->[1] & TABLE_ROW_GROUP_EL) {                    if ($node->[1] == TABLE_ROW_GROUP_EL) {
5794                      !!!cp ('t214');                      !!!cp ('t214');
5795                      $i = $_;                      $i = $_;
5796                      last INSCOPE;                      last INSCOPE;
# Line 5742  sub _tree_construction_main ($) { Line 5832  sub _tree_construction_main ($) {
5832                  !!!cp ('t218');                  !!!cp ('t218');
5833                }                }
5834    
5835                if ($token->{tag_name} eq 'col') {            if ($token->{tag_name} eq 'col') {
5836                  ## Clear back to table context              ## Clear back to table context
5837                  while (not ($self->{open_elements}->[-1]->[1]              while (not ($self->{open_elements}->[-1]->[1]
5838                                  & TABLE_SCOPING_EL)) {                              & TABLE_SCOPING_EL)) {
5839                    !!!cp ('t219');                !!!cp ('t219');
5840                    ## ISSUE: Can this state be reached?                ## ISSUE: Can this state be reached?
5841                    pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5842                  }              }
5843                                
5844                  !!!insert-element ('colgroup',, $token);              !!!insert-element ('colgroup',, $token);
5845                  $self->{insertion_mode} = IN_COLUMN_GROUP_IM;              $self->{insertion_mode} = IN_COLUMN_GROUP_IM;
5846                  ## reprocess              ## reprocess
5847                  !!!ack-later;              $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5848                  next B;              !!!ack-later;
5849                } elsif ({              next B;
5850                          caption => 1,            } elsif ({
5851                          colgroup => 1,                      caption => 1,
5852                          tbody => 1, tfoot => 1, thead => 1,                      colgroup => 1,
5853                         }->{$token->{tag_name}}) {                      tbody => 1, tfoot => 1, thead => 1,
5854                  ## Clear back to table context                     }->{$token->{tag_name}}) {
5855                ## Clear back to table context
5856                  while (not ($self->{open_elements}->[-1]->[1]                  while (not ($self->{open_elements}->[-1]->[1]
5857                                  & TABLE_SCOPING_EL)) {                                  & TABLE_SCOPING_EL)) {
5858                    !!!cp ('t220');                    !!!cp ('t220');
# Line 5769  sub _tree_construction_main ($) { Line 5860  sub _tree_construction_main ($) {
5860                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
5861                  }                  }
5862                                    
5863                  push @$active_formatting_elements, ['#marker', '']              push @$active_formatting_elements, ['#marker', '']
5864                      if $token->{tag_name} eq 'caption';                  if $token->{tag_name} eq 'caption';
5865                                    
5866                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);              !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5867                  $self->{insertion_mode} = {              $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5868                                             caption => IN_CAPTION_IM,              $self->{insertion_mode} = {
5869                                             colgroup => IN_COLUMN_GROUP_IM,                                         caption => IN_CAPTION_IM,
5870                                             tbody => IN_TABLE_BODY_IM,                                         colgroup => IN_COLUMN_GROUP_IM,
5871                                             tfoot => IN_TABLE_BODY_IM,                                         tbody => IN_TABLE_BODY_IM,
5872                                             thead => IN_TABLE_BODY_IM,                                         tfoot => IN_TABLE_BODY_IM,
5873                                            }->{$token->{tag_name}};                                         thead => IN_TABLE_BODY_IM,
5874                  !!!next-token;                                        }->{$token->{tag_name}};
5875                  !!!nack ('t220.1');              !!!next-token;
5876                  next B;              !!!nack ('t220.1');
5877                } else {              next B;
5878                  die "$0: in table: <>: $token->{tag_name}";            } else {
5879                }              die "$0: in table: <>: $token->{tag_name}";
5880              }
5881              } elsif ($token->{tag_name} eq 'table') {              } elsif ($token->{tag_name} eq 'table') {
5882                !!!parse-error (type => 'not closed',                !!!parse-error (type => 'not closed',
5883                                text => $self->{open_elements}->[-1]->[0]                                text => $self->{open_elements}->[-1]->[0]
# Line 5797  sub _tree_construction_main ($) { Line 5889  sub _tree_construction_main ($) {
5889                my $i;                my $i;
5890                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5891                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
5892                  if ($node->[1] & TABLE_EL) {                  if ($node->[1] == TABLE_EL) {
5893                    !!!cp ('t221');                    !!!cp ('t221');
5894                    $i = $_;                    $i = $_;
5895                    last INSCOPE;                    last INSCOPE;
# Line 5824  sub _tree_construction_main ($) { Line 5916  sub _tree_construction_main ($) {
5916                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
5917                }                }
5918    
5919                unless ($self->{open_elements}->[-1]->[1] & TABLE_EL) {                unless ($self->{open_elements}->[-1]->[1] == TABLE_EL) {
5920                  !!!cp ('t225');                  !!!cp ('t225');
5921                  ## NOTE: |<table><tr><table>|                  ## NOTE: |<table><tr><table>|
5922                  !!!parse-error (type => 'not closed',                  !!!parse-error (type => 'not closed',
# Line 5848  sub _tree_construction_main ($) { Line 5940  sub _tree_construction_main ($) {
5940              !!!cp ('t227.8');              !!!cp ('t227.8');
5941              ## NOTE: This is a "as if in head" code clone.              ## NOTE: This is a "as if in head" code clone.
5942              $parse_rcdata->(CDATA_CONTENT_MODEL);              $parse_rcdata->(CDATA_CONTENT_MODEL);
5943                $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5944              next B;              next B;
5945            } else {            } else {
5946              !!!cp ('t227.7');              !!!cp ('t227.7');
# Line 5858  sub _tree_construction_main ($) { Line 5951  sub _tree_construction_main ($) {
5951              !!!cp ('t227.6');              !!!cp ('t227.6');
5952              ## NOTE: This is a "as if in head" code clone.              ## NOTE: This is a "as if in head" code clone.
5953              $script_start_tag->();              $script_start_tag->();
5954                $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5955              next B;              next B;
5956            } else {            } else {
5957              !!!cp ('t227.5');              !!!cp ('t227.5');
# Line 5873  sub _tree_construction_main ($) { Line 5967  sub _tree_construction_main ($) {
5967                                  text => $token->{tag_name}, token => $token);                                  text => $token->{tag_name}, token => $token);
5968    
5969                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5970                    $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5971    
5972                  ## TODO: form element pointer                  ## TODO: form element pointer
5973    
# Line 5910  sub _tree_construction_main ($) { Line 6005  sub _tree_construction_main ($) {
6005                my $i;                my $i;
6006                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6007                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
6008                  if ($node->[1] & TABLE_ROW_EL) {                  if ($node->[1] == TABLE_ROW_EL) {
6009                    !!!cp ('t228');                    !!!cp ('t228');
6010                    $i = $_;                    $i = $_;
6011                    last INSCOPE;                    last INSCOPE;
# Line 5951  sub _tree_construction_main ($) { Line 6046  sub _tree_construction_main ($) {
6046                  my $i;                  my $i;
6047                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6048                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
6049                    if ($node->[1] & TABLE_ROW_EL) {                    if ($node->[1] == TABLE_ROW_EL) {
6050                      !!!cp ('t233');                      !!!cp ('t233');
6051                      $i = $_;                      $i = $_;
6052                      last INSCOPE;                      last INSCOPE;
# Line 5989  sub _tree_construction_main ($) { Line 6084  sub _tree_construction_main ($) {
6084                  my $i;                  my $i;
6085                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6086                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
6087                    if ($node->[1] & TABLE_ROW_GROUP_EL) {                    if ($node->[1] == TABLE_ROW_GROUP_EL) {
6088                      !!!cp ('t237');                      !!!cp ('t237');
6089                      $i = $_;                      $i = $_;
6090                      last INSCOPE;                      last INSCOPE;
# Line 6036  sub _tree_construction_main ($) { Line 6131  sub _tree_construction_main ($) {
6131                my $i;                my $i;
6132                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6133                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
6134                  if ($node->[1] & TABLE_EL) {                  if ($node->[1] == TABLE_EL) {
6135                    !!!cp ('t241');                    !!!cp ('t241');
6136                    $i = $_;                    $i = $_;
6137                    last INSCOPE;                    last INSCOPE;
# Line 6095  sub _tree_construction_main ($) { Line 6190  sub _tree_construction_main ($) {
6190                  my $i;                  my $i;
6191                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6192                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
6193                    if ($node->[1] & TABLE_ROW_EL) {                    if ($node->[1] == TABLE_ROW_EL) {
6194                      !!!cp ('t250');                      !!!cp ('t250');
6195                      $i = $_;                      $i = $_;
6196                      last INSCOPE;                      last INSCOPE;
# Line 6185  sub _tree_construction_main ($) { Line 6280  sub _tree_construction_main ($) {
6280            #            #
6281          }          }
6282        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
6283          unless ($self->{open_elements}->[-1]->[1] & HTML_EL and          unless ($self->{open_elements}->[-1]->[1] == HTML_EL and
6284                  @{$self->{open_elements}} == 1) { # redundant, maybe                  @{$self->{open_elements}} == 1) { # redundant, maybe
6285            !!!parse-error (type => 'in body:#eof', token => $token);            !!!parse-error (type => 'in body:#eof', token => $token);
6286            !!!cp ('t259.1');            !!!cp ('t259.1');
# Line 6202  sub _tree_construction_main ($) { Line 6297  sub _tree_construction_main ($) {
6297        }        }
6298      } elsif ($self->{insertion_mode} == IN_COLUMN_GROUP_IM) {      } elsif ($self->{insertion_mode} == IN_COLUMN_GROUP_IM) {
6299            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
6300              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {              if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
6301                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
6302                unless (length $token->{data}) {                unless (length $token->{data}) {
6303                  !!!cp ('t260');                  !!!cp ('t260');
# Line 6227  sub _tree_construction_main ($) { Line 6322  sub _tree_construction_main ($) {
6322              }              }
6323            } elsif ($token->{type} == END_TAG_TOKEN) {            } elsif ($token->{type} == END_TAG_TOKEN) {
6324              if ($token->{tag_name} eq 'colgroup') {              if ($token->{tag_name} eq 'colgroup') {
6325                if ($self->{open_elements}->[-1]->[1] & HTML_EL) {                if ($self->{open_elements}->[-1]->[1] == HTML_EL) {
6326                  !!!cp ('t264');                  !!!cp ('t264');
6327                  !!!parse-error (type => 'unmatched end tag',                  !!!parse-error (type => 'unmatched end tag',
6328                                  text => 'colgroup', token => $token);                                  text => 'colgroup', token => $token);
# Line 6253  sub _tree_construction_main ($) { Line 6348  sub _tree_construction_main ($) {
6348                #                #
6349              }              }
6350        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
6351          if ($self->{open_elements}->[-1]->[1] & HTML_EL and          if ($self->{open_elements}->[-1]->[1] == HTML_EL and
6352              @{$self->{open_elements}} == 1) { # redundant, maybe              @{$self->{open_elements}} == 1) { # redundant, maybe
6353            !!!cp ('t270.2');            !!!cp ('t270.2');
6354            ## Stop parsing.            ## Stop parsing.
# Line 6271  sub _tree_construction_main ($) { Line 6366  sub _tree_construction_main ($) {
6366        }        }
6367    
6368            ## As if </colgroup>            ## As if </colgroup>
6369            if ($self->{open_elements}->[-1]->[1] & HTML_EL) {            if ($self->{open_elements}->[-1]->[1] == HTML_EL) {
6370              !!!cp ('t269');              !!!cp ('t269');
6371  ## TODO: Wrong error type?  ## TODO: Wrong error type?
6372              !!!parse-error (type => 'unmatched end tag',              !!!parse-error (type => 'unmatched end tag',
# Line 6296  sub _tree_construction_main ($) { Line 6391  sub _tree_construction_main ($) {
6391          next B;          next B;
6392        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
6393          if ($token->{tag_name} eq 'option') {          if ($token->{tag_name} eq 'option') {
6394            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {            if ($self->{open_elements}->[-1]->[1] == OPTION_EL) {
6395              !!!cp ('t272');              !!!cp ('t272');
6396              ## As if </option>              ## As if </option>
6397              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
# Line 6309  sub _tree_construction_main ($) { Line 6404  sub _tree_construction_main ($) {
6404            !!!next-token;            !!!next-token;
6405            next B;            next B;
6406          } elsif ($token->{tag_name} eq 'optgroup') {          } elsif ($token->{tag_name} eq 'optgroup') {
6407            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {            if ($self->{open_elements}->[-1]->[1] == OPTION_EL) {
6408              !!!cp ('t274');              !!!cp ('t274');
6409              ## As if </option>              ## As if </option>
6410              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
# Line 6317  sub _tree_construction_main ($) { Line 6412  sub _tree_construction_main ($) {
6412              !!!cp ('t275');              !!!cp ('t275');
6413            }            }
6414    
6415            if ($self->{open_elements}->[-1]->[1] & OPTGROUP_EL) {            if ($self->{open_elements}->[-1]->[1] == OPTGROUP_EL) {
6416              !!!cp ('t276');              !!!cp ('t276');
6417              ## As if </optgroup>              ## As if </optgroup>
6418              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
# Line 6347  sub _tree_construction_main ($) { Line 6442  sub _tree_construction_main ($) {
6442            my $i;            my $i;
6443            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6444              my $node = $self->{open_elements}->[$_];              my $node = $self->{open_elements}->[$_];
6445              if ($node->[1] & SELECT_EL) {              if ($node->[1] == SELECT_EL) {
6446                !!!cp ('t278');                !!!cp ('t278');
6447                $i = $_;                $i = $_;
6448                last INSCOPE;                last INSCOPE;
# Line 6392  sub _tree_construction_main ($) { Line 6487  sub _tree_construction_main ($) {
6487          }          }
6488        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
6489          if ($token->{tag_name} eq 'optgroup') {          if ($token->{tag_name} eq 'optgroup') {
6490            if ($self->{open_elements}->[-1]->[1] & OPTION_EL and            if ($self->{open_elements}->[-1]->[1] == OPTION_EL and
6491                $self->{open_elements}->[-2]->[1] & OPTGROUP_EL) {                $self->{open_elements}->[-2]->[1] == OPTGROUP_EL) {
6492              !!!cp ('t283');              !!!cp ('t283');
6493              ## As if </option>              ## As if </option>
6494              splice @{$self->{open_elements}}, -2;              splice @{$self->{open_elements}}, -2;
6495            } elsif ($self->{open_elements}->[-1]->[1] & OPTGROUP_EL) {            } elsif ($self->{open_elements}->[-1]->[1] == OPTGROUP_EL) {
6496              !!!cp ('t284');              !!!cp ('t284');
6497              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
6498            } else {            } else {
# Line 6410  sub _tree_construction_main ($) { Line 6505  sub _tree_construction_main ($) {
6505            !!!next-token;            !!!next-token;
6506            next B;            next B;
6507          } elsif ($token->{tag_name} eq 'option') {          } elsif ($token->{tag_name} eq 'option') {
6508            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {            if ($self->{open_elements}->[-1]->[1] == OPTION_EL) {
6509              !!!cp ('t286');              !!!cp ('t286');
6510              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
6511            } else {            } else {
# Line 6427  sub _tree_construction_main ($) { Line 6522  sub _tree_construction_main ($) {
6522            my $i;            my $i;
6523            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6524              my $node = $self->{open_elements}->[$_];              my $node = $self->{open_elements}->[$_];
6525              if ($node->[1] & SELECT_EL) {              if ($node->[1] == SELECT_EL) {
6526                !!!cp ('t288');                !!!cp ('t288');
6527                $i = $_;                $i = $_;
6528                last INSCOPE;                last INSCOPE;
# Line 6489  sub _tree_construction_main ($) { Line 6584  sub _tree_construction_main ($) {
6584            undef $i;            undef $i;
6585            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6586              my $node = $self->{open_elements}->[$_];              my $node = $self->{open_elements}->[$_];
6587              if ($node->[1] & SELECT_EL) {              if ($node->[1] == SELECT_EL) {
6588                !!!cp ('t295');                !!!cp ('t295');
6589                $i = $_;                $i = $_;
6590                last INSCOPE;                last INSCOPE;
# Line 6528  sub _tree_construction_main ($) { Line 6623  sub _tree_construction_main ($) {
6623            next B;            next B;
6624          }          }
6625        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
6626          unless ($self->{open_elements}->[-1]->[1] & HTML_EL and          unless ($self->{open_elements}->[-1]->[1] == HTML_EL and
6627                  @{$self->{open_elements}} == 1) { # redundant, maybe                  @{$self->{open_elements}} == 1) { # redundant, maybe
6628            !!!cp ('t299.1');            !!!cp ('t299.1');
6629            !!!parse-error (type => 'in body:#eof', token => $token);            !!!parse-error (type => 'in body:#eof', token => $token);
# Line 6543  sub _tree_construction_main ($) { Line 6638  sub _tree_construction_main ($) {
6638        }        }
6639      } elsif ($self->{insertion_mode} & BODY_AFTER_IMS) {      } elsif ($self->{insertion_mode} & BODY_AFTER_IMS) {
6640        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
6641          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
6642            my $data = $1;            my $data = $1;
6643            ## As if in body            ## As if in body
6644            $reconstruct_active_formatting_elements->($insert_to_current);            $reconstruct_active_formatting_elements->($insert_to_current);
# Line 6560  sub _tree_construction_main ($) { Line 6655  sub _tree_construction_main ($) {
6655          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
6656            !!!cp ('t301');            !!!cp ('t301');
6657            !!!parse-error (type => 'after html:#text', token => $token);            !!!parse-error (type => 'after html:#text', token => $token);
6658              #
           ## Reprocess in the "after body" insertion mode.  
6659          } else {          } else {
6660            !!!cp ('t302');            !!!cp ('t302');
6661              ## "after body" insertion mode
6662              !!!parse-error (type => 'after body:#text', token => $token);
6663              #
6664          }          }
           
         ## "after body" insertion mode  
         !!!parse-error (type => 'after body:#text', token => $token);  
6665    
6666          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
6667          ## reprocess          ## reprocess
# Line 6577  sub _tree_construction_main ($) { Line 6671  sub _tree_construction_main ($) {
6671            !!!cp ('t303');            !!!cp ('t303');
6672            !!!parse-error (type => 'after html',            !!!parse-error (type => 'after html',
6673                            text => $token->{tag_name}, token => $token);                            text => $token->{tag_name}, token => $token);
6674                        #
           ## Reprocess in the "after body" insertion mode.  
6675          } else {          } else {
6676            !!!cp ('t304');            !!!cp ('t304');
6677              ## "after body" insertion mode
6678              !!!parse-error (type => 'after body',
6679                              text => $token->{tag_name}, token => $token);
6680              #
6681          }          }
6682    
         ## "after body" insertion mode  
         !!!parse-error (type => 'after body',  
                         text => $token->{tag_name}, token => $token);  
   
6683          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
6684          !!!ack-later;          !!!ack-later;
6685          ## reprocess          ## reprocess
# Line 6597  sub _tree_construction_main ($) { Line 6690  sub _tree_construction_main ($) {
6690            !!!parse-error (type => 'after html:/',            !!!parse-error (type => 'after html:/',
6691                            text => $token->{tag_name}, token => $token);                            text => $token->{tag_name}, token => $token);
6692                        
6693            $self->{insertion_mode} = AFTER_BODY_IM;            $self->{insertion_mode} = IN_BODY_IM;
6694            ## Reprocess in the "after body" insertion mode.            ## Reprocess.
6695              next B;
6696          } else {          } else {
6697            !!!cp ('t306');            !!!cp ('t306');
6698          }          }
# Line 6636  sub _tree_construction_main ($) { Line 6730  sub _tree_construction_main ($) {
6730        }        }
6731      } elsif ($self->{insertion_mode} & FRAME_IMS) {      } elsif ($self->{insertion_mode} & FRAME_IMS) {
6732        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
6733          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
6734            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
6735                        
6736            unless (length $token->{data}) {            unless (length $token->{data}) {
# Line 6646  sub _tree_construction_main ($) { Line 6740  sub _tree_construction_main ($) {
6740            }            }
6741          }          }
6742                    
6743          if ($token->{data} =~ s/^[^\x09\x0A\x0B\x0C\x20]+//) {          if ($token->{data} =~ s/^[^\x09\x0A\x0C\x20]+//) {
6744            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
6745              !!!cp ('t311');              !!!cp ('t311');
6746              !!!parse-error (type => 'in frameset:#text', token => $token);              !!!parse-error (type => 'in frameset:#text', token => $token);
# Line 6716  sub _tree_construction_main ($) { Line 6810  sub _tree_construction_main ($) {
6810        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
6811          if ($token->{tag_name} eq 'frameset' and          if ($token->{tag_name} eq 'frameset' and
6812              $self->{insertion_mode} == IN_FRAMESET_IM) {              $self->{insertion_mode} == IN_FRAMESET_IM) {
6813            if ($self->{open_elements}->[-1]->[1] & HTML_EL and            if ($self->{open_elements}->[-1]->[1] == HTML_EL and
6814                @{$self->{open_elements}} == 1) {                @{$self->{open_elements}} == 1) {
6815              !!!cp ('t325');              !!!cp ('t325');
6816              !!!parse-error (type => 'unmatched end tag',              !!!parse-error (type => 'unmatched end tag',
# Line 6730  sub _tree_construction_main ($) { Line 6824  sub _tree_construction_main ($) {
6824            }            }
6825    
6826            if (not defined $self->{inner_html_node} and            if (not defined $self->{inner_html_node} and
6827                not ($self->{open_elements}->[-1]->[1] & FRAMESET_EL)) {                not ($self->{open_elements}->[-1]->[1] == FRAMESET_EL)) {
6828              !!!cp ('t327');              !!!cp ('t327');
6829              $self->{insertion_mode} = AFTER_FRAMESET_IM;              $self->{insertion_mode} = AFTER_FRAMESET_IM;
6830            } else {            } else {
# Line 6762  sub _tree_construction_main ($) { Line 6856  sub _tree_construction_main ($) {
6856            next B;            next B;
6857          }          }
6858        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
6859          unless ($self->{open_elements}->[-1]->[1] & HTML_EL and          unless ($self->{open_elements}->[-1]->[1] == HTML_EL and
6860                  @{$self->{open_elements}} == 1) { # redundant, maybe                  @{$self->{open_elements}} == 1) { # redundant, maybe
6861            !!!cp ('t331.1');            !!!cp ('t331.1');
6862            !!!parse-error (type => 'in body:#eof', token => $token);            !!!parse-error (type => 'in body:#eof', token => $token);
# Line 6775  sub _tree_construction_main ($) { Line 6869  sub _tree_construction_main ($) {
6869        } else {        } else {
6870          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
6871        }        }
   
       ## ISSUE: An issue in spec here  
6872      } else {      } else {
6873        die "$0: $self->{insertion_mode}: Unknown insertion mode";        die "$0: $self->{insertion_mode}: Unknown insertion mode";
6874      }      }
# Line 6794  sub _tree_construction_main ($) { Line 6886  sub _tree_construction_main ($) {
6886          $parse_rcdata->(CDATA_CONTENT_MODEL);          $parse_rcdata->(CDATA_CONTENT_MODEL);
6887          next B;          next B;
6888        } elsif ({        } elsif ({
6889                  base => 1, link => 1,                  base => 1, command => 1, eventsource => 1, link => 1,
6890                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
6891          !!!cp ('t334');          !!!cp ('t334');
6892          ## 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
6893          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6894          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          pop @{$self->{open_elements}};
6895          !!!ack ('t334.1');          !!!ack ('t334.1');
6896          !!!next-token;          !!!next-token;
6897          next B;          next B;
6898        } elsif ($token->{tag_name} eq 'meta') {        } elsif ($token->{tag_name} eq 'meta') {
6899          ## 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
6900          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6901          my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          my $meta_el = pop @{$self->{open_elements}};
6902    
6903          unless ($self->{confident}) {          unless ($self->{confident}) {
6904            if ($token->{attributes}->{charset}) {            if ($token->{attributes}->{charset}) {
# Line 6823  sub _tree_construction_main ($) { Line 6915  sub _tree_construction_main ($) {
6915            } elsif ($token->{attributes}->{content}) {            } elsif ($token->{attributes}->{content}) {
6916              if ($token->{attributes}->{content}->{value}              if ($token->{attributes}->{content}->{value}
6917                  =~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt]                  =~ /[Cc][Hh][Aa][Rr][Ss][Ee][Tt]
6918                      [\x09-\x0D\x20]*=                      [\x09\x0A\x0C\x0D\x20]*=
6919                      [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                      [\x09\x0A\x0C\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
6920                      ([^"'\x09-\x0D\x20][^\x09-\x0D\x20\x3B]*))/x) {                      ([^"'\x09\x0A\x0C\x0D\x20][^\x09\x0A\x0C\x0D\x20\x3B]*))
6921                       /x) {
6922                !!!cp ('t336');                !!!cp ('t336');
6923                ## NOTE: Whether the encoding is supported or not is handled                ## NOTE: Whether the encoding is supported or not is handled
6924                ## in the {change_encoding} callback.                ## in the {change_encoding} callback.
# Line 6866  sub _tree_construction_main ($) { Line 6959  sub _tree_construction_main ($) {
6959          !!!parse-error (type => 'in body', text => 'body', token => $token);          !!!parse-error (type => 'in body', text => 'body', token => $token);
6960                                
6961          if (@{$self->{open_elements}} == 1 or          if (@{$self->{open_elements}} == 1 or
6962              not ($self->{open_elements}->[1]->[1] & BODY_EL)) {              not ($self->{open_elements}->[1]->[1] == BODY_EL)) {
6963            !!!cp ('t342');            !!!cp ('t342');
6964            ## Ignore the token            ## Ignore the token
6965          } else {          } else {
# Line 6884  sub _tree_construction_main ($) { Line 6977  sub _tree_construction_main ($) {
6977          !!!next-token;          !!!next-token;
6978          next B;          next B;
6979        } elsif ({        } elsif ({
6980                  address => 1, blockquote => 1, center => 1, dir => 1,                  ## NOTE: Start tags for non-phrasing flow content elements
6981                  div => 1, dl => 1, fieldset => 1,  
6982                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                  ## NOTE: The normal one
6983                  menu => 1, ol => 1, p => 1, ul => 1,                  address => 1, article => 1, aside => 1, blockquote => 1,
6984                    center => 1, datagrid => 1, details => 1, dialog => 1,
6985                    dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,
6986                    footer => 1, h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1,
6987                    h6 => 1, header => 1, menu => 1, nav => 1, ol => 1, p => 1,
6988                    section => 1, ul => 1,
6989                    ## NOTE: As normal, but drops leading newline
6990                  pre => 1, listing => 1,                  pre => 1, listing => 1,
6991                    ## NOTE: As normal, but interacts with the form element pointer
6992                  form => 1,                  form => 1,
6993                    
6994                  table => 1,                  table => 1,
6995                  hr => 1,                  hr => 1,
6996                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 6904  sub _tree_construction_main ($) { Line 7005  sub _tree_construction_main ($) {
7005    
7006          ## has a p element in scope          ## has a p element in scope
7007          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
7008            if ($_->[1] & P_EL) {            if ($_->[1] == P_EL) {
7009              !!!cp ('t344');              !!!cp ('t344');
7010              !!!back-token; # <form>              !!!back-token; # <form>
7011              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
# Line 6956  sub _tree_construction_main ($) { Line 7057  sub _tree_construction_main ($) {
7057            !!!next-token;            !!!next-token;
7058          }          }
7059          next B;          next B;
7060        } elsif ({li => 1, dt => 1, dd => 1}->{$token->{tag_name}}) {        } elsif ($token->{tag_name} eq 'li') {
7061          ## has a p element in scope          ## NOTE: As normal, but imply </li> when there's another <li> ...
7062    
7063            ## NOTE: Special, Scope (<li><foo><li> == <li><foo><li/></foo></li>)
7064              ## Interpreted as <li><foo/></li><li/> (non-conforming)
7065              ## blockquote (O9.27), center (O), dd (Fx3, O, S3.1.2, IE7),
7066              ## dt (Fx, O, S, IE), dl (O), fieldset (O, S, IE), form (Fx, O, S),
7067              ## hn (O), pre (O), applet (O, S), button (O, S), marquee (Fx, O, S),
7068              ## object (Fx)
7069              ## Generate non-tree (non-conforming)
7070              ## basefont (IE7 (where basefont is non-void)), center (IE),
7071              ## form (IE), hn (IE)
7072            ## address, div, p (<li><foo><li> == <li><foo/></li><li/>)
7073              ## Interpreted as <li><foo><li/></foo></li> (non-conforming)
7074              ## div (Fx, S)
7075    
7076            my $non_optional;
7077            my $i = -1;
7078    
7079            ## 1.
7080            for my $node (reverse @{$self->{open_elements}}) {
7081              if ($node->[1] == LI_EL) {
7082                ## 2. (a) As if </li>
7083                {
7084                  ## If no </li> - not applied
7085                  #
7086    
7087                  ## Otherwise
7088    
7089                  ## 1. generate implied end tags, except for </li>
7090                  #
7091    
7092                  ## 2. If current node != "li", parse error
7093                  if ($non_optional) {
7094                    !!!parse-error (type => 'not closed',
7095                                    text => $non_optional->[0]->manakai_local_name,
7096                                    token => $token);
7097                    !!!cp ('t355');
7098                  } else {
7099                    !!!cp ('t356');
7100                  }
7101    
7102                  ## 3. Pop
7103                  splice @{$self->{open_elements}}, $i;
7104                }
7105    
7106                last; ## 2. (b) goto 5.
7107              } elsif (
7108                       ## NOTE: not "formatting" and not "phrasing"
7109                       ($node->[1] & SPECIAL_EL or
7110                        $node->[1] & SCOPING_EL) and
7111                       ## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|.
7112                       (not $node->[1] & ADDRESS_DIV_P_EL)
7113                      ) {
7114                ## 3.
7115                !!!cp ('t357');
7116                last; ## goto 5.
7117              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7118                !!!cp ('t358');
7119                #
7120              } else {
7121                !!!cp ('t359');
7122                $non_optional ||= $node;
7123                #
7124              }
7125              ## 4.
7126              ## goto 2.
7127              $i--;
7128            }
7129    
7130            ## 5. (a) has a |p| element in scope
7131          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
7132            if ($_->[1] & P_EL) {            if ($_->[1] == P_EL) {
7133              !!!cp ('t353');              !!!cp ('t353');
7134    
7135                ## NOTE: |<p><li>|, for example.
7136    
7137              !!!back-token; # <x>              !!!back-token; # <x>
7138              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
7139                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
# Line 6970  sub _tree_construction_main ($) { Line 7143  sub _tree_construction_main ($) {
7143              last INSCOPE;              last INSCOPE;
7144            }            }
7145          } # INSCOPE          } # INSCOPE
7146              
7147          ## Step 1          ## 5. (b) insert
7148            !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7149            !!!nack ('t359.1');
7150            !!!next-token;
7151            next B;
7152          } elsif ($token->{tag_name} eq 'dt' or
7153                   $token->{tag_name} eq 'dd') {
7154            ## NOTE: As normal, but imply </dt> or </dd> when ...
7155    
7156            my $non_optional;
7157          my $i = -1;          my $i = -1;
7158          my $node = $self->{open_elements}->[$i];  
7159          my $li_or_dtdd = {li => {li => 1},          ## 1.
7160                            dt => {dt => 1, dd => 1},          for my $node (reverse @{$self->{open_elements}}) {
7161                            dd => {dt => 1, dd => 1}}->{$token->{tag_name}};            if ($node->[1] == DTDD_EL) {
7162          LI: {              ## 2. (a) As if </li>
7163            ## Step 2              {
7164            if ($li_or_dtdd->{$node->[0]->manakai_local_name}) {                ## If no </li> - not applied
7165              if ($i != -1) {                #
7166                !!!cp ('t355');  
7167                !!!parse-error (type => 'not closed',                ## Otherwise
7168                                text => $self->{open_elements}->[-1]->[0]  
7169                                    ->manakai_local_name,                ## 1. generate implied end tags, except for </dt> or </dd>
7170                                token => $token);                #
7171              } else {  
7172                !!!cp ('t356');                ## 2. If current node != "dt"|"dd", parse error
7173                  if ($non_optional) {
7174                    !!!parse-error (type => 'not closed',
7175                                    text => $non_optional->[0]->manakai_local_name,
7176                                    token => $token);
7177                    !!!cp ('t355.1');
7178                  } else {
7179                    !!!cp ('t356.1');
7180                  }
7181    
7182                  ## 3. Pop
7183                  splice @{$self->{open_elements}}, $i;
7184              }              }
7185              splice @{$self->{open_elements}}, $i;  
7186              last LI;              last; ## 2. (b) goto 5.
7187              } elsif (
7188                       ## NOTE: not "formatting" and not "phrasing"
7189                       ($node->[1] & SPECIAL_EL or
7190                        $node->[1] & SCOPING_EL) and
7191                       ## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|.
7192    
7193                       (not $node->[1] & ADDRESS_DIV_P_EL)
7194                      ) {
7195                ## 3.
7196                !!!cp ('t357.1');
7197                last; ## goto 5.
7198              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7199                !!!cp ('t358.1');
7200                #
7201            } else {            } else {
7202              !!!cp ('t357');              !!!cp ('t359.1');
7203            }              $non_optional ||= $node;
7204                          #
           ## 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;  
7205            }            }
7206                        ## 4.
7207            !!!cp ('t359');            ## goto 2.
           ## Step 4  
7208            $i--;            $i--;
7209            $node = $self->{open_elements}->[$i];          }
7210            redo LI;  
7211          } # LI          ## 5. (a) has a |p| element in scope
7212                      INSCOPE: for (reverse @{$self->{open_elements}}) {
7213              if ($_->[1] == P_EL) {
7214                !!!cp ('t353.1');
7215                !!!back-token; # <x>
7216                $token = {type => END_TAG_TOKEN, tag_name => 'p',
7217                          line => $token->{line}, column => $token->{column}};
7218                next B;
7219              } elsif ($_->[1] & SCOPING_EL) {
7220                !!!cp ('t354.1');
7221                last INSCOPE;
7222              }
7223            } # INSCOPE
7224    
7225            ## 5. (b) insert
7226          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7227          !!!nack ('t359.1');          !!!nack ('t359.2');
7228          !!!next-token;          !!!next-token;
7229          next B;          next B;
7230        } elsif ($token->{tag_name} eq 'plaintext') {        } elsif ($token->{tag_name} eq 'plaintext') {
7231            ## NOTE: As normal, but effectively ends parsing
7232    
7233          ## has a p element in scope          ## has a p element in scope
7234          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
7235            if ($_->[1] & P_EL) {            if ($_->[1] == P_EL) {
7236              !!!cp ('t367');              !!!cp ('t367');
7237              !!!back-token; # <plaintext>              !!!back-token; # <plaintext>
7238              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
# Line 7042  sub _tree_construction_main ($) { Line 7254  sub _tree_construction_main ($) {
7254        } elsif ($token->{tag_name} eq 'a') {        } elsif ($token->{tag_name} eq 'a') {
7255          AFE: for my $i (reverse 0..$#$active_formatting_elements) {          AFE: for my $i (reverse 0..$#$active_formatting_elements) {
7256            my $node = $active_formatting_elements->[$i];            my $node = $active_formatting_elements->[$i];
7257            if ($node->[1] & A_EL) {            if ($node->[1] == A_EL) {
7258              !!!cp ('t371');              !!!cp ('t371');
7259              !!!parse-error (type => 'in a:a', token => $token);              !!!parse-error (type => 'in a:a', token => $token);
7260                            
# Line 7086  sub _tree_construction_main ($) { Line 7298  sub _tree_construction_main ($) {
7298          ## has a |nobr| element in scope          ## has a |nobr| element in scope
7299          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7300            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
7301            if ($node->[1] & NOBR_EL) {            if ($node->[1] == NOBR_EL) {
7302              !!!cp ('t376');              !!!cp ('t376');
7303              !!!parse-error (type => 'in nobr:nobr', token => $token);              !!!parse-error (type => 'in nobr:nobr', token => $token);
7304              !!!back-token; # <nobr>              !!!back-token; # <nobr>
# Line 7109  sub _tree_construction_main ($) { Line 7321  sub _tree_construction_main ($) {
7321          ## has a button element in scope          ## has a button element in scope
7322          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7323            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
7324            if ($node->[1] & BUTTON_EL) {            if ($node->[1] == BUTTON_EL) {
7325              !!!cp ('t378');              !!!cp ('t378');
7326              !!!parse-error (type => 'in button:button', token => $token);              !!!parse-error (type => 'in button:button', token => $token);
7327              !!!back-token; # <button>              !!!back-token; # <button>
# Line 7209  sub _tree_construction_main ($) { Line 7421  sub _tree_construction_main ($) {
7421            next B;            next B;
7422          }          }
7423        } elsif ($token->{tag_name} eq 'textarea') {        } elsif ($token->{tag_name} eq 'textarea') {
7424          my $tag_name = $token->{tag_name};          ## Step 1
7425          my $el;          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
         !!!create-element ($el, $HTML_NS, $token->{tag_name}, $token->{attributes}, $token);  
7426                    
7427            ## Step 2
7428          ## TODO: $self->{form_element} if defined          ## TODO: $self->{form_element} if defined
7429    
7430            ## Step 3
7431            $self->{ignore_newline} = 1;
7432    
7433            ## Step 4
7434            ## ISSUE: This step is wrong. (r2302 enbugged)
7435    
7436            ## Step 5
7437          $self->{content_model} = RCDATA_CONTENT_MODEL;          $self->{content_model} = RCDATA_CONTENT_MODEL;
7438          delete $self->{escape}; # MUST          delete $self->{escape}; # MUST
7439            
7440          $insert->($el);          ## Step 6-7
7441                    $self->{insertion_mode} |= IN_CDATA_RCDATA_IM;
7442          my $text = '';  
7443          !!!nack ('t392.1');          !!!nack ('t392.1');
7444          !!!next-token;          !!!next-token;
7445          if ($token->{type} == CHARACTER_TOKEN) {          next B;
7446            $token->{data} =~ s/^\x0A//;        } elsif ($token->{tag_name} eq 'optgroup' or
7447            unless (length $token->{data}) {                 $token->{tag_name} eq 'option') {
7448              !!!cp ('t392');          ## has an |option| element in scope
7449              !!!next-token;          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7450            } else {            my $node = $self->{open_elements}->[$_];
7451              !!!cp ('t393');            if ($node->[1] == OPTION_EL) {
7452                !!!cp ('t397.1');
7453                ## NOTE: As if </option>
7454                !!!back-token; # <option> or <optgroup>
7455                $token = {type => END_TAG_TOKEN, tag_name => 'option',
7456                          line => $token->{line}, column => $token->{column}};
7457                next B;
7458              } elsif ($node->[1] & SCOPING_EL) {
7459                !!!cp ('t397.2');
7460                last INSCOPE;
7461            }            }
7462          } else {          } # INSCOPE
7463            !!!cp ('t394');  
7464          }          $reconstruct_active_formatting_elements->($insert_to_current);
7465          while ($token->{type} == CHARACTER_TOKEN) {  
7466            !!!cp ('t395');          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7467            $text .= $token->{data};  
7468            !!!next-token;          !!!nack ('t397.3');
         }  
         if (length $text) {  
           !!!cp ('t396');  
           $el->manakai_append_text ($text);  
         }  
           
         $self->{content_model} = PCDATA_CONTENT_MODEL;  
           
         if ($token->{type} == END_TAG_TOKEN and  
             $token->{tag_name} eq $tag_name) {  
           !!!cp ('t397');  
           ## Ignore the token  
         } else {  
           !!!cp ('t398');  
           !!!parse-error (type => 'in RCDATA:#eof', token => $token);  
         }  
7469          !!!next-token;          !!!next-token;
7470          next B;          redo B;
7471        } elsif ($token->{tag_name} eq 'rt' or        } elsif ($token->{tag_name} eq 'rt' or
7472                 $token->{tag_name} eq 'rp') {                 $token->{tag_name} eq 'rp') {
7473          ## has a |ruby| element in scope          ## has a |ruby| element in scope
7474          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7475            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
7476            if ($node->[1] & RUBY_EL) {            if ($node->[1] == RUBY_EL) {
7477              !!!cp ('t398.1');              !!!cp ('t398.1');
7478              ## generate implied end tags              ## generate implied end tags
7479              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
7480                !!!cp ('t398.2');                !!!cp ('t398.2');
7481                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
7482              }              }
7483              unless ($self->{open_elements}->[-1]->[1] & RUBY_EL) {              unless ($self->{open_elements}->[-1]->[1] == RUBY_EL) {
7484                !!!cp ('t398.3');                !!!cp ('t398.3');
7485                !!!parse-error (type => 'not closed',                !!!parse-error (type => 'not closed',
7486                                text => $self->{open_elements}->[-1]->[0]                                text => $self->{open_elements}->[-1]->[0]
7487                                    ->manakai_local_name,                                    ->manakai_local_name,
7488                                token => $token);                                token => $token);
7489                pop @{$self->{open_elements}}                pop @{$self->{open_elements}}
7490                    while not $self->{open_elements}->[-1]->[1] & RUBY_EL;                    while not $self->{open_elements}->[-1]->[1] == RUBY_EL;
7491              }              }
7492              last INSCOPE;              last INSCOPE;
7493            } elsif ($node->[1] & SCOPING_EL) {            } elsif ($node->[1] & SCOPING_EL) {
# Line 7302  sub _tree_construction_main ($) { Line 7515  sub _tree_construction_main ($) {
7515                    
7516          if ($self->{self_closing}) {          if ($self->{self_closing}) {
7517            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
7518            !!!ack ('t398.1');            !!!ack ('t398.6');
7519          } else {          } else {
7520            !!!cp ('t398.2');            !!!cp ('t398.7');
7521            $self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM;            $self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM;
7522            ## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion            ## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion
7523            ## mode, "in body" (not "in foreign content") secondary insertion            ## mode, "in body" (not "in foreign content") secondary insertion
# Line 7315  sub _tree_construction_main ($) { Line 7528  sub _tree_construction_main ($) {
7528          next B;          next B;
7529        } elsif ({        } elsif ({
7530                  caption => 1, col => 1, colgroup => 1, frame => 1,                  caption => 1, col => 1, colgroup => 1, frame => 1,
7531                  frameset => 1, head => 1, option => 1, optgroup => 1,                  frameset => 1, head => 1,
7532                  tbody => 1, td => 1, tfoot => 1, th => 1,                  tbody => 1, td => 1, tfoot => 1, th => 1,
7533                  thead => 1, tr => 1,                  thead => 1, tr => 1,
7534                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 7326  sub _tree_construction_main ($) { Line 7539  sub _tree_construction_main ($) {
7539          !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.          !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.
7540          !!!next-token;          !!!next-token;
7541          next B;          next B;
7542                  } elsif ($token->{tag_name} eq 'param' or
7543          ## ISSUE: An issue on HTML5 new elements in the spec.                 $token->{tag_name} eq 'source') {
7544            !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7545            pop @{$self->{open_elements}};
7546    
7547            !!!ack ('t398.5');
7548            !!!next-token;
7549            redo B;
7550        } else {        } else {
7551          if ($token->{tag_name} eq 'image') {          if ($token->{tag_name} eq 'image') {
7552            !!!cp ('t384');            !!!cp ('t384');
# Line 7350  sub _tree_construction_main ($) { Line 7569  sub _tree_construction_main ($) {
7569            !!!nack ('t380.1');            !!!nack ('t380.1');
7570          } elsif ({          } elsif ({
7571                    b => 1, big => 1, em => 1, font => 1, i => 1,                    b => 1, big => 1, em => 1, font => 1, i => 1,
7572                    s => 1, small => 1, strile => 1,                    s => 1, small => 1, strike => 1,
7573                    strong => 1, tt => 1, u => 1,                    strong => 1, tt => 1, u => 1,
7574                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
7575            !!!cp ('t375');            !!!cp ('t375');
# Line 7363  sub _tree_construction_main ($) { Line 7582  sub _tree_construction_main ($) {
7582            !!!ack ('t388.2');            !!!ack ('t388.2');
7583          } elsif ({          } elsif ({
7584                    area => 1, basefont => 1, bgsound => 1, br => 1,                    area => 1, basefont => 1, bgsound => 1, br => 1,
7585                    embed => 1, img => 1, param => 1, spacer => 1, wbr => 1,                    embed => 1, img => 1, spacer => 1, wbr => 1,
                   #image => 1,  
7586                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
7587            !!!cp ('t388.1');            !!!cp ('t388.1');
7588            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
# Line 7395  sub _tree_construction_main ($) { Line 7613  sub _tree_construction_main ($) {
7613          my $i;          my $i;
7614          INSCOPE: {          INSCOPE: {
7615            for (reverse @{$self->{open_elements}}) {            for (reverse @{$self->{open_elements}}) {
7616              if ($_->[1] & BODY_EL) {              if ($_->[1] == BODY_EL) {
7617                !!!cp ('t405');                !!!cp ('t405');
7618                $i = $_;                $i = $_;
7619                last INSCOPE;                last INSCOPE;
# Line 7405  sub _tree_construction_main ($) { Line 7623  sub _tree_construction_main ($) {
7623              }              }
7624            }            }
7625    
7626            !!!parse-error (type => 'start tag not allowed',            ## NOTE: |<marquee></body>|, |<svg><foreignobject></body>|
7627    
7628              !!!parse-error (type => 'unmatched end tag',
7629                            text => $token->{tag_name}, token => $token);                            text => $token->{tag_name}, token => $token);
7630            ## NOTE: Ignore the token.            ## NOTE: Ignore the token.
7631            !!!next-token;            !!!next-token;
# Line 7431  sub _tree_construction_main ($) { Line 7651  sub _tree_construction_main ($) {
7651          ## TODO: Update this code.  It seems that the code below is not          ## TODO: Update this code.  It seems that the code below is not
7652          ## up-to-date, though it has same effect as speced.          ## up-to-date, though it has same effect as speced.
7653          if (@{$self->{open_elements}} > 1 and          if (@{$self->{open_elements}} > 1 and
7654              $self->{open_elements}->[1]->[1] & BODY_EL) {              $self->{open_elements}->[1]->[1] == BODY_EL) {
7655            ## ISSUE: There is an issue in the spec.            unless ($self->{open_elements}->[-1]->[1] == BODY_EL) {
           unless ($self->{open_elements}->[-1]->[1] & BODY_EL) {  
7656              !!!cp ('t406');              !!!cp ('t406');
7657              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
7658                              text => $self->{open_elements}->[1]->[0]                              text => $self->{open_elements}->[1]->[0]
# Line 7454  sub _tree_construction_main ($) { Line 7673  sub _tree_construction_main ($) {
7673            next B;            next B;
7674          }          }
7675        } elsif ({        } elsif ({
7676                  address => 1, blockquote => 1, center => 1, dir => 1,                  ## NOTE: End tags for non-phrasing flow content elements
7677                  div => 1, dl => 1, fieldset => 1, listing => 1,  
7678                  menu => 1, ol => 1, pre => 1, ul => 1,                  ## NOTE: The normal ones
7679                    address => 1, article => 1, aside => 1, blockquote => 1,
7680                    center => 1, datagrid => 1, details => 1, dialog => 1,
7681                    dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,
7682                    footer => 1, header => 1, listing => 1, menu => 1, nav => 1,
7683                    ol => 1, pre => 1, section => 1, ul => 1,
7684    
7685                    ## NOTE: As normal, but ... optional tags
7686                  dd => 1, dt => 1, li => 1,                  dd => 1, dt => 1, li => 1,
7687    
7688                  applet => 1, button => 1, marquee => 1, object => 1,                  applet => 1, button => 1, marquee => 1, object => 1,
7689                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7690            ## NOTE: Code for <li> start tags includes "as if </li>" code.
7691            ## Code for <dt> or <dd> start tags includes "as if </dt> or
7692            ## </dd>" code.
7693    
7694          ## has an element in scope          ## has an element in scope
7695          my $i;          my $i;
7696          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
# Line 7486  sub _tree_construction_main ($) { Line 7717  sub _tree_construction_main ($) {
7717                    dd => ($token->{tag_name} ne 'dd'),                    dd => ($token->{tag_name} ne 'dd'),
7718                    dt => ($token->{tag_name} ne 'dt'),                    dt => ($token->{tag_name} ne 'dt'),
7719                    li => ($token->{tag_name} ne 'li'),                    li => ($token->{tag_name} ne 'li'),
7720                      option => 1,
7721                      optgroup => 1,
7722                    p => 1,                    p => 1,
7723                    rt => 1,                    rt => 1,
7724                    rp => 1,                    rp => 1,
# Line 7518  sub _tree_construction_main ($) { Line 7751  sub _tree_construction_main ($) {
7751          !!!next-token;          !!!next-token;
7752          next B;          next B;
7753        } elsif ($token->{tag_name} eq 'form') {        } elsif ($token->{tag_name} eq 'form') {
7754            ## NOTE: As normal, but interacts with the form element pointer
7755    
7756          undef $self->{form_element};          undef $self->{form_element};
7757    
7758          ## has an element in scope          ## has an element in scope
7759          my $i;          my $i;
7760          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7761            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
7762            if ($node->[1] & FORM_EL) {            if ($node->[1] == FORM_EL) {
7763              !!!cp ('t418');              !!!cp ('t418');
7764              $i = $_;              $i = $_;
7765              last INSCOPE;              last INSCOPE;
# Line 7565  sub _tree_construction_main ($) { Line 7800  sub _tree_construction_main ($) {
7800          !!!next-token;          !!!next-token;
7801          next B;          next B;
7802        } elsif ({        } elsif ({
7803                    ## NOTE: As normal, except acts as a closer for any ...
7804                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,
7805                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7806          ## has an element in scope          ## has an element in scope
7807          my $i;          my $i;
7808          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7809            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
7810            if ($node->[1] & HEADING_EL) {            if ($node->[1] == HEADING_EL) {
7811              !!!cp ('t423');              !!!cp ('t423');
7812              $i = $_;              $i = $_;
7813              last INSCOPE;              last INSCOPE;
# Line 7610  sub _tree_construction_main ($) { Line 7846  sub _tree_construction_main ($) {
7846          !!!next-token;          !!!next-token;
7847          next B;          next B;
7848        } elsif ($token->{tag_name} eq 'p') {        } elsif ($token->{tag_name} eq 'p') {
7849            ## NOTE: As normal, except </p> implies <p> and ...
7850    
7851          ## has an element in scope          ## has an element in scope
7852            my $non_optional;
7853          my $i;          my $i;
7854          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7855            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
7856            if ($node->[1] & P_EL) {            if ($node->[1] == P_EL) {
7857              !!!cp ('t410.1');              !!!cp ('t410.1');
7858              $i = $_;              $i = $_;
7859              last INSCOPE;              last INSCOPE;
7860            } elsif ($node->[1] & SCOPING_EL) {            } elsif ($node->[1] & SCOPING_EL) {
7861              !!!cp ('t411.1');              !!!cp ('t411.1');
7862              last INSCOPE;              last INSCOPE;
7863              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7864                ## NOTE: |END_TAG_OPTIONAL_EL| includes "p"
7865                !!!cp ('t411.2');
7866                #
7867              } else {
7868                !!!cp ('t411.3');
7869                $non_optional ||= $node;
7870                #
7871            }            }
7872          } # INSCOPE          } # INSCOPE
7873    
7874          if (defined $i) {          if (defined $i) {
7875            if ($self->{open_elements}->[-1]->[0]->manakai_local_name            ## 1. Generate implied end tags
7876                    ne $token->{tag_name}) {            #
7877    
7878              ## 2. If current node != "p", parse error
7879              if ($non_optional) {
7880              !!!cp ('t412.1');              !!!cp ('t412.1');
7881              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
7882                              text => $self->{open_elements}->[-1]->[0]                              text => $non_optional->[0]->manakai_local_name,
                                 ->manakai_local_name,  
7883                              token => $token);                              token => $token);
7884            } else {            } else {
7885              !!!cp ('t414.1');              !!!cp ('t414.1');
7886            }            }
7887    
7888              ## 3. Pop
7889            splice @{$self->{open_elements}}, $i;            splice @{$self->{open_elements}}, $i;
7890          } else {          } else {
7891            !!!cp ('t413.1');            !!!cp ('t413.1');
# Line 7655  sub _tree_construction_main ($) { Line 7905  sub _tree_construction_main ($) {
7905        } elsif ({        } elsif ({
7906                  a => 1,                  a => 1,
7907                  b => 1, big => 1, em => 1, font => 1, i => 1,                  b => 1, big => 1, em => 1, font => 1, i => 1,
7908                  nobr => 1, s => 1, small => 1, strile => 1,                  nobr => 1, s => 1, small => 1, strike => 1,
7909                  strong => 1, tt => 1, u => 1,                  strong => 1, tt => 1, u => 1,
7910                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7911          !!!cp ('t427');          !!!cp ('t427');
# Line 7676  sub _tree_construction_main ($) { Line 7926  sub _tree_construction_main ($) {
7926          ## Ignore the token.          ## Ignore the token.
7927          !!!next-token;          !!!next-token;
7928          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  
           
7929        } else {        } else {
7930            if ($token->{tag_name} eq 'sarcasm') {
7931              sleep 0.001; # take a deep breath
7932            }
7933    
7934          ## Step 1          ## Step 1
7935          my $node_i = -1;          my $node_i = -1;
7936          my $node = $self->{open_elements}->[$node_i];          my $node = $self->{open_elements}->[$node_i];
7937    
7938          ## Step 2          ## Step 2
7939          S2: {          S2: {
7940            if ($node->[0]->manakai_local_name eq $token->{tag_name}) {            my $node_tag_name = $node->[0]->manakai_local_name;
7941              $node_tag_name =~ tr/A-Z/a-z/; # for SVG camelCase tag names
7942              if ($node_tag_name eq $token->{tag_name}) {
7943              ## Step 1              ## Step 1
7944              ## generate implied end tags              ## generate implied end tags
7945              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
# Line 7717  sub _tree_construction_main ($) { Line 7952  sub _tree_construction_main ($) {
7952              }              }
7953                    
7954              ## Step 2              ## Step 2
7955              if ($self->{open_elements}->[-1]->[0]->manakai_local_name              my $current_tag_name
7956                      ne $token->{tag_name}) {                  = $self->{open_elements}->[-1]->[0]->manakai_local_name;
7957                $current_tag_name =~ tr/A-Z/a-z/;
7958                if ($current_tag_name ne $token->{tag_name}) {
7959                !!!cp ('t431');                !!!cp ('t431');
7960                ## NOTE: <x><y></x>                ## NOTE: <x><y></x>
7961                !!!parse-error (type => 'not closed',                !!!parse-error (type => 'not closed',
# Line 7746  sub _tree_construction_main ($) { Line 7983  sub _tree_construction_main ($) {
7983                ## Ignore the token                ## Ignore the token
7984                !!!next-token;                !!!next-token;
7985                last S2;                last S2;
             }  
7986    
7987                  ## NOTE: |<span><dd></span>a|: In Safari 3.1.2 and Opera
7988                  ## 9.27, "a" is a child of <dd> (conforming).  In
7989                  ## Firefox 3.0.2, "a" is a child of <body>.  In WinIE 7,
7990                  ## "a" is a child of both <body> and <dd>.
7991                }
7992                
7993              !!!cp ('t434');              !!!cp ('t434');
7994            }            }
7995                        
# Line 7983  sub set_inner_html ($$$$;$) { Line 8225  sub set_inner_html ($$$$;$) {
8225      push @{$p->{open_elements}}, [$root, $el_category->{html}];      push @{$p->{open_elements}}, [$root, $el_category->{html}];
8226    
8227      undef $p->{head_element};      undef $p->{head_element};
8228        undef $p->{head_element_inserted};
8229    
8230      ## Step 6 # MUST      ## Step 6 # MUST
8231      $p->_reset_insertion_mode;      $p->_reset_insertion_mode;

Legend:
Removed from v.1.184  
changed lines
  Added in v.1.207

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24