/[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.24 by wakaba, Sat Jun 23 16:42:43 2007 UTC revision 1.25 by wakaba, Sun Jun 24 05:12:11 2007 UTC
# Line 2128  sub _tree_construction_main ($) { Line 2128  sub _tree_construction_main ($) {
2128      }      }
2129    }; # $clear_up_to_marker    }; # $clear_up_to_marker
2130    
2131    my $style_start_tag = sub {    my $parse_rcdata = sub ($$) {
2132      my $style_el; !!!create-element ($style_el, 'style', $token->{attributes});      my ($content_model_flag, $insert) = @_;
2133      ## $self->{insertion_mode} eq 'in head' and ... (always true)  
2134      (($self->{insertion_mode} eq 'in head' and defined $self->{head_element})      ## Step 1
2135       ? $self->{head_element} : $self->{open_elements}->[-1]->[0])      my $start_tag_name = $token->{tag_name};
2136        ->append_child ($style_el);      my $el;
2137      $self->{content_model_flag} = 'CDATA';      !!!create-element ($el, $start_tag_name, $token->{attributes});
2138    
2139        ## Step 2
2140        $insert->($el); # /context node/->append_child ($el)
2141    
2142        ## Step 3
2143        $self->{content_model_flag} = $content_model_flag; # CDATA or RCDATA
2144      delete $self->{escape}; # MUST      delete $self->{escape}; # MUST
2145                  
2146        ## Step 4
2147      my $text = '';      my $text = '';
2148      !!!next-token;      !!!next-token;
2149      while ($token->{type} eq 'character') {      while ($token->{type} eq 'character') { # or until stop tokenizing
2150        $text .= $token->{data};        $text .= $token->{data};
2151        !!!next-token;        !!!next-token;
2152      } # stop if non-character token or tokenizer stops tokenising      }
2153    
2154        ## Step 5
2155      if (length $text) {      if (length $text) {
2156        $style_el->manakai_append_text ($text);        my $text = $self->{document}->create_text_node ($text);
2157          $el->append_child ($text);
2158      }      }
2159        
2160        ## Step 6
2161      $self->{content_model_flag} = 'PCDATA';      $self->{content_model_flag} = 'PCDATA';
2162                  
2163      if ($token->{type} eq 'end tag' and $token->{tag_name} eq 'style') {      ## Step 7
2164        if ($token->{type} eq 'end tag' and $token->{tag_name} eq $start_tag_name) {
2165        ## Ignore the token        ## Ignore the token
2166      } else {      } else {
2167        !!!parse-error (type => 'in CDATA:#'.$token->{type});        !!!parse-error (type => 'in '.$content_model_flag.':#'.$token->{type});
       ## ISSUE: And ignore?  
2168      }      }
2169      !!!next-token;      !!!next-token;
2170    }; # $style_start_tag    }; # $parse_rcdata
2171    
2172    my $script_start_tag = sub {    my $script_start_tag = sub ($) {
2173        my $insert = $_[0];
2174      my $script_el;      my $script_el;
2175      !!!create-element ($script_el, 'script', $token->{attributes});      !!!create-element ($script_el, 'script', $token->{attributes});
2176      ## TODO: mark as "parser-inserted"      ## TODO: mark as "parser-inserted"
# Line 2192  sub _tree_construction_main ($) { Line 2204  sub _tree_construction_main ($) {
2204      } else {      } else {
2205        ## TODO: $old_insertion_point = current insertion point        ## TODO: $old_insertion_point = current insertion point
2206        ## TODO: insertion point = just before the next input character        ## TODO: insertion point = just before the next input character
2207          
2208        (($self->{insertion_mode} eq 'in head' and defined $self->{head_element})        $insert->($script_el);
        ? $self->{head_element} : $self->{open_elements}->[-1]->[0])->append_child ($script_el);  
2209                
2210        ## TODO: insertion point = $old_insertion_point (might be "undefined")        ## TODO: insertion point = $old_insertion_point (might be "undefined")
2211                
# Line 2388  sub _tree_construction_main ($) { Line 2399  sub _tree_construction_main ($) {
2399    }; # $formatting_end_tag    }; # $formatting_end_tag
2400    
2401    my $insert_to_current = sub {    my $insert_to_current = sub {
2402      $self->{open_elements}->[-1]->[0]->append_child (shift);      $self->{open_elements}->[-1]->[0]->append_child ($_[0]);
2403    }; # $insert_to_current    }; # $insert_to_current
2404    
2405    my $insert_to_foster = sub {    my $insert_to_foster = sub {
# Line 2426  sub _tree_construction_main ($) { Line 2437  sub _tree_construction_main ($) {
2437      my $insert = shift;      my $insert = shift;
2438      if ($token->{type} eq 'start tag') {      if ($token->{type} eq 'start tag') {
2439        if ($token->{tag_name} eq 'script') {        if ($token->{tag_name} eq 'script') {
2440          $script_start_tag->();          ## NOTE: This is an "as if in head" code clone
2441            $script_start_tag->($insert);
2442          return;          return;
2443        } elsif ($token->{tag_name} eq 'style') {        } elsif ($token->{tag_name} eq 'style') {
2444          $style_start_tag->();          ## NOTE: This is an "as if in head" code clone
2445            $parse_rcdata->('CDATA', $insert);
2446          return;          return;
2447        } elsif ({        } elsif ({
2448                  base => 1, link => 1, meta => 1,                  base => 1, link => 1, meta => 1,
2449                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
2450          ## NOTE: This is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone, only "-t" differs
2451          my $el;          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
2452          !!!create-element ($el, $token->{tag_name}, $token->{attributes});          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
         if ($self->{insertion_mode} eq 'in head' and  
             defined $self->{head_element}) {  
           $self->{head_element}->append_child ($el);  
         } else {  
           $insert->($el);  
         }  
           
2453          !!!next-token;          !!!next-token;
2454          return;          return;
2455        } elsif ($token->{tag_name} eq 'title') {        } elsif ($token->{tag_name} eq 'title') {
2456          !!!parse-error (type => 'in body:title');          !!!parse-error (type => 'in body:title');
2457          ## NOTE: There is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone
2458          my $title_el;          $parse_rcdata->('RCDATA', $insert);
         !!!create-element ($title_el, 'title', $token->{attributes});  
         (defined $self->{head_element} ? $self->{head_element} : $self->{open_elements}->[-1]->[0])  
           ->append_child ($title_el);  
         $self->{content_model_flag} = 'RCDATA';  
         delete $self->{escape}; # MUST  
           
         my $text = '';  
         !!!next-token;  
         while ($token->{type} eq 'character') {  
           $text .= $token->{data};  
           !!!next-token;  
         }  
         if (length $text) {  
           $title_el->manakai_append_text ($text);  
         }  
           
         $self->{content_model_flag} = 'PCDATA';  
           
         if ($token->{type} eq 'end tag' and  
             $token->{tag_name} eq 'title') {  
           ## Ignore the token  
         } else {  
           !!!parse-error (type => 'in RCDATA:#'.$token->{type});  
           ## ISSUE: And ignore?  
         }  
         !!!next-token;  
2459          return;          return;
2460        } elsif ($token->{tag_name} eq 'body') {        } elsif ($token->{tag_name} eq 'body') {
2461          !!!parse-error (type => 'in body:body');          !!!parse-error (type => 'in body:body');
# Line 2821  sub _tree_construction_main ($) { Line 2801  sub _tree_construction_main ($) {
2801          return;          return;
2802        } elsif ($token->{tag_name} eq 'xmp') {        } elsif ($token->{tag_name} eq 'xmp') {
2803          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
2804                    $parse_rcdata->('CDATA', $insert);
         !!!insert-element-t ($token->{tag_name}, $token->{attributes});  
           
         $self->{content_model_flag} = 'CDATA';  
         delete $self->{escape}; # MUST  
           
         !!!next-token;  
2805          return;          return;
2806        } elsif ($token->{tag_name} eq 'table') {        } elsif ($token->{tag_name} eq 'table') {
2807          ## has a p element in scope          ## has a p element in scope
# Line 2936  sub _tree_construction_main ($) { Line 2910  sub _tree_construction_main ($) {
2910            !!!back-token (@tokens);            !!!back-token (@tokens);
2911            return;            return;
2912          }          }
2913        } elsif ({        } elsif ($token->{tag_name} eq 'textarea') {
                 textarea => 1,  
                 iframe => 1,  
                 noembed => 1,  
                 noframes => 1,  
                 noscript => 0, ## TODO: 1 if scripting is enabled  
                }->{$token->{tag_name}}) {  
2914          my $tag_name = $token->{tag_name};          my $tag_name = $token->{tag_name};
2915          my $el;          my $el;
2916          !!!create-element ($el, $token->{tag_name}, $token->{attributes});          !!!create-element ($el, $token->{tag_name}, $token->{attributes});
2917                    
2918          if ($token->{tag_name} eq 'textarea') {          ## TODO: $self->{form_element} if defined
2919            ## TODO: $self->{form_element} if defined          $self->{content_model_flag} = 'RCDATA';
           $self->{content_model_flag} = 'RCDATA';  
         } else {  
           $self->{content_model_flag} = 'CDATA';  
         }  
2920          delete $self->{escape}; # MUST          delete $self->{escape}; # MUST
2921                    
2922          $insert->($el);          $insert->($el);
2923                    
2924          my $text = '';          my $text = '';
2925          if ($token->{tag_name} eq 'textarea') {          !!!next-token;
2926            !!!next-token;          if ($token->{type} eq 'character') {
2927            if ($token->{type} eq 'character') {            $token->{data} =~ s/^\x0A//;
2928              $token->{data} =~ s/^\x0A//;            unless (length $token->{data}) {
2929              unless (length $token->{data}) {              !!!next-token;
               !!!next-token;  
             }  
2930            }            }
         } else {  
           !!!next-token;  
2931          }          }
2932          while ($token->{type} eq 'character') {          while ($token->{type} eq 'character') {
2933            $text .= $token->{data};            $text .= $token->{data};
# Line 2983  sub _tree_construction_main ($) { Line 2943  sub _tree_construction_main ($) {
2943              $token->{tag_name} eq $tag_name) {              $token->{tag_name} eq $tag_name) {
2944            ## Ignore the token            ## Ignore the token
2945          } else {          } else {
2946            if ($token->{tag_name} eq 'textarea') {            !!!parse-error (type => 'in RCDATA:#'.$token->{type});
             !!!parse-error (type => 'in RCDATA:#'.$token->{type});  
           } else {  
             !!!parse-error (type => 'in CDATA:#'.$token->{type});  
           }  
           ## ISSUE: And ignore?  
2947          }          }
2948          !!!next-token;          !!!next-token;
2949          return;          return;
2950          } elsif ({
2951                    iframe => 1,
2952                    noembed => 1,
2953                    noframes => 1,
2954                    noscript => 0, ## TODO: 1 if scripting is enabled
2955                   }->{$token->{tag_name}}) {
2956            $parse_rcdata->('CDATA', $insert);
2957            return;
2958        } elsif ($token->{tag_name} eq 'select') {        } elsif ($token->{tag_name} eq 'select') {
2959          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
2960                    
# Line 3238  sub _tree_construction_main ($) { Line 3201  sub _tree_construction_main ($) {
3201                  #not $phrasing_category->{$node->[1]} and                  #not $phrasing_category->{$node->[1]} and
3202                  ($special_category->{$node->[1]} or                  ($special_category->{$node->[1]} or
3203                   $scoping_category->{$node->[1]})) {                   $scoping_category->{$node->[1]})) {
3204                !!!parse-error (type => 'not closed:'.$node->[1]);                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3205                ## Ignore the token                ## Ignore the token
3206                !!!next-token;                !!!next-token;
3207                last S2;                last S2;
# Line 3358  sub _tree_construction_main ($) { Line 3321  sub _tree_construction_main ($) {
3321            } else {            } else {
3322              die "$0: $token->{type}: Unknown type";              die "$0: $token->{type}: Unknown type";
3323            }            }
3324          } elsif ($self->{insertion_mode} eq 'in head') {          } elsif ($self->{insertion_mode} eq 'in head' or
3325                     $self->{insertion_mode} eq 'in head noscript' or
3326                     $self->{insertion_mode} eq 'after head') {
3327            if ($token->{type} eq 'character') {            if ($token->{type} eq 'character') {
3328              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {
3329                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
# Line 3375  sub _tree_construction_main ($) { Line 3340  sub _tree_construction_main ($) {
3340              !!!next-token;              !!!next-token;
3341              redo B;              redo B;
3342            } elsif ($token->{type} eq 'start tag') {            } elsif ($token->{type} eq 'start tag') {
3343              if ($token->{tag_name} eq 'title') {              if ({base => ($self->{insertion_mode} eq 'in head' or
3344                ## NOTE: There is an "as if in head" code clone                            $self->{insertion_mode} eq 'after head'),
3345                my $title_el;                   link => 1, meta => 1}->{$token->{tag_name}}) {
3346                !!!create-element ($title_el, 'title', $token->{attributes});                ## NOTE: There is a "as if in head" code clone.
3347                (defined $self->{head_element} ? $self->{head_element} : $self->{open_elements}->[-1]->[0])                if ($self->{insertion_mode} eq 'after head') {
3348                  ->append_child ($title_el);                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3349                $self->{content_model_flag} = 'RCDATA';                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3350                delete $self->{escape}; # MUST                }
3351                  !!!insert-element ($token->{tag_name}, $token->{attributes});
3352                my $text = '';                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
3353                  pop @{$self->{open_elements}}
3354                      if $self->{insertion_mode} eq 'after head';
3355                !!!next-token;                !!!next-token;
3356                while ($token->{type} eq 'character') {                redo B;
3357                  $text .= $token->{data};              } elsif ($token->{tag_name} eq 'title' and
3358                  !!!next-token;                       $self->{insertion_mode} eq 'in head') {
3359                  ## NOTE: There is a "as if in head" code clone.
3360                  if ($self->{insertion_mode} eq 'after head') {
3361                    !!!parse-error (type => 'after head:'.$token->{tag_name});
3362                    push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3363                }                }
3364                if (length $text) {                $parse_rcdata->('RCDATA', $insert_to_current);
3365                  $title_el->manakai_append_text ($text);                pop @{$self->{open_elements}}
3366                      if $self->{insertion_mode} eq 'after head';
3367                  redo B;
3368                } elsif ($token->{tag_name} eq 'style') {
3369                  ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and
3370                  ## insertion mode 'in head')
3371                  ## NOTE: There is a "as if in head" code clone.
3372                  if ($self->{insertion_mode} eq 'after head') {
3373                    !!!parse-error (type => 'after head:'.$token->{tag_name});
3374                    push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3375                }                }
3376                                $parse_rcdata->('CDATA', $insert_to_current);
3377                $self->{content_model_flag} = 'PCDATA';                pop @{$self->{open_elements}}
3378                                    if $self->{insertion_mode} eq 'after head';
3379                if ($token->{type} eq 'end tag' and                redo B;
3380                    $token->{tag_name} eq 'title') {              } elsif ($token->{tag_name} eq 'noscript') {
3381                  if ($self->{insertion_mode} eq 'in head') {
3382                    ## NOTE: and scripting is disalbed
3383                    !!!insert-element ($token->{tag_name}, $token->{attributes});
3384                    $self->{insertion_mode} = 'in head noscript';
3385                    !!!next-token;
3386                    redo B;
3387                  } elsif ($self->{insertion_mode} eq 'in head noscript') {
3388                    !!!parse-error (type => 'noscript in noscript');
3389                  ## Ignore the token                  ## Ignore the token
3390                    redo B;
3391                } else {                } else {
3392                  !!!parse-error (type => 'in RCDATA:#'.$token->{type});                  #
                 ## ISSUE: And ignore?  
3393                }                }
3394                } elsif ($token->{tag_name} eq 'head' and
3395                         $self->{insertion_mode} ne 'after head') {
3396                  !!!parse-error (type => 'in head:head'); # or in head noscript
3397                  ## Ignore the token
3398                !!!next-token;                !!!next-token;
3399                redo B;                redo B;
3400              } elsif ($token->{tag_name} eq 'style') {              } elsif ($self->{insertion_mode} ne 'in head noscript' and
3401                $style_start_tag->();                       $token->{tag_name} eq 'script') {
3402                redo B;                if ($self->{insertion_mode} eq 'after head') {
3403              } elsif ($token->{tag_name} eq 'script') {                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3404                $script_start_tag->();                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
               redo B;  
             } elsif ({base => 1, link => 1, meta => 1}->{$token->{tag_name}}) {  
               ## NOTE: There are "as if in head" code clones  
               my $el;  
               !!!create-element ($el, $token->{tag_name}, $token->{attributes});  
               if ($self->{insertion_mode} eq 'in head' and  
                   defined $self->{head_element}) {  
                 $self->{head_element}->append_child ($el);  
               } else {  
                 $self->{open_elements}->[-1]->[0]->append_child ($el);  
3405                }                }
3406                  ## NOTE: There is a "as if in head" code clone.
3407                  $script_start_tag->($insert_to_current);
3408                  pop @{$self->{open_elements}}
3409                      if $self->{insertion_mode} eq 'after head';
3410                  redo B;
3411                } elsif ($self->{insertion_mode} eq 'after head' and
3412                         $token->{tag_name} eq 'body') {
3413                  !!!insert-element ('body', $token->{attributes});
3414                  $self->{insertion_mode} = 'in body';
3415                !!!next-token;                !!!next-token;
3416                redo B;                redo B;
3417              } elsif ($token->{tag_name} eq 'head') {              } elsif ($self->{insertion_mode} eq 'after head' and
3418                !!!parse-error (type => 'in head:head');                       $token->{tag_name} eq 'frameset') {
3419                ## Ignore the token                !!!insert-element ('frameset', $token->{attributes});
3420                  $self->{insertion_mode} = 'in frameset';
3421                !!!next-token;                !!!next-token;
3422                redo B;                redo B;
3423              } else {              } else {
3424                #                #
3425              }              }
3426            } elsif ($token->{type} eq 'end tag') {            } elsif ($token->{type} eq 'end tag') {
3427              if ($token->{tag_name} eq 'head') {              if ($self->{insertion_mode} eq 'in head' and
3428                if ($self->{open_elements}->[-1]->[1] eq 'head') {                  $token->{tag_name} eq 'head') {
3429                  pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
               } else {  
                 !!!parse-error (type => 'unmatched end tag:head');  
               }  
3430                $self->{insertion_mode} = 'after head';                $self->{insertion_mode} = 'after head';
3431                !!!next-token;                !!!next-token;
3432                redo B;                redo B;
3433              } elsif ($token->{tag_name} eq 'body' or              } elsif ($self->{insertion_mode} eq 'in head noscript' and
3434                       $token->{tag_name} eq 'html') {                  $token->{tag_name} eq 'noscript') {
3435                  pop @{$self->{open_elements}};
3436                  $self->{insertion_mode} = 'in head';
3437                  !!!next-token;
3438                  redo B;
3439                } elsif ($self->{insertion_mode} eq 'in head' and
3440                         ($token->{tag_name} eq 'body' or
3441                          $token->{tag_name} eq 'html')) {
3442                #                #
3443              } else {              } elsif ($self->{insertion_mode} ne 'after head') {
3444                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3445                ## Ignore the token                ## Ignore the token
3446                !!!next-token;                !!!next-token;
3447                redo B;                redo B;
3448                } else {
3449                  #
3450              }              }
3451            } else {            } else {
3452              #              #
3453            }            }
3454    
3455            if ($self->{open_elements}->[-1]->[1] eq 'head') {            ## As if </head> or </noscript> or <body>
3456              ## As if </head>            if ($self->{insertion_mode} eq 'in head') {
3457                pop @{$self->{open_elements}};
3458                $self->{insertion_mode} = 'after head';
3459              } elsif ($self->{insertion_mode} eq 'in head noscript') {
3460              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
3461                !!!parse-error (type => 'in noscript:'.(defined $token->{tag_name} ? ($token->{type} eq 'end tag' ? '/' : '') . $token->{tag_name} : '#' . $token->{type}));
3462                $self->{insertion_mode} = 'in head';
3463              } else { # 'after head'
3464                !!!insert-element ('body');
3465                $self->{insertion_mode} = 'in body';
3466            }            }
           $self->{insertion_mode} = 'after head';  
3467            ## reprocess            ## reprocess
3468            redo B;            redo B;
3469    
3470            ## ISSUE: An issue in the spec.            ## ISSUE: An issue in the spec.
         } elsif ($self->{insertion_mode} eq 'after head') {  
           if ($token->{type} eq 'character') {  
             if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {  
               $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);  
               unless (length $token->{data}) {  
                 !!!next-token;  
                 redo B;  
               }  
             }  
               
             #  
           } elsif ($token->{type} eq 'comment') {  
             my $comment = $self->{document}->create_comment ($token->{data});  
             $self->{open_elements}->[-1]->[0]->append_child ($comment);  
             !!!next-token;  
             redo B;  
           } elsif ($token->{type} eq 'start tag') {  
             if ($token->{tag_name} eq 'body') {  
               !!!insert-element ('body', $token->{attributes});  
               $self->{insertion_mode} = 'in body';  
               !!!next-token;  
               redo B;  
             } elsif ($token->{tag_name} eq 'frameset') {  
               !!!insert-element ('frameset', $token->{attributes});  
               $self->{insertion_mode} = 'in frameset';  
               !!!next-token;  
               redo B;  
             } elsif ({  
                       base => 1, link => 1, meta => 1,  
                       script => 1, style => 1, title => 1,  
                      }->{$token->{tag_name}}) {  
               !!!parse-error (type => 'after head:'.$token->{tag_name});  
               $self->{insertion_mode} = 'in head';  
               ## reprocess  
               redo B;  
             } else {  
               #  
             }  
           } else {  
             #  
           }  
             
           ## As if <body>  
           !!!insert-element ('body');  
           $self->{insertion_mode} = 'in body';  
           ## reprocess  
           redo B;  
3471          } elsif ($self->{insertion_mode} eq 'in body') {          } elsif ($self->{insertion_mode} eq 'in body') {
3472            if ($token->{type} eq 'character') {            if ($token->{type} eq 'character') {
3473              ## NOTE: There is a code clone of "character in body".              ## NOTE: There is a code clone of "character in body".

Legend:
Removed from v.1.24  
changed lines
  Added in v.1.25

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24