/[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.136 by wakaba, Sat May 17 12:29:24 2008 UTC revision 1.140 by wakaba, Sat May 24 09:59:52 2008 UTC
# Line 11  use Error qw(:try); Line 11  use Error qw(:try);
11  ## TODO: 1252 parse error (revision 1264)  ## TODO: 1252 parse error (revision 1264)
12  ## TODO: 8859-11 = 874 (revision 1271)  ## TODO: 8859-11 = 874 (revision 1271)
13    
14    require IO::Handle;
15    
16  my $HTML_NS = q<http://www.w3.org/1999/xhtml>;  my $HTML_NS = q<http://www.w3.org/1999/xhtml>;
17  my $MML_NS = q<http://www.w3.org/1998/Math/MathML>;  my $MML_NS = q<http://www.w3.org/1998/Math/MathML>;
18  my $SVG_NS = q<http://www.w3.org/2000/svg>;  my $SVG_NS = q<http://www.w3.org/2000/svg>;
# Line 332  my $c1_entity_char = { Line 334  my $c1_entity_char = {
334  }; # $c1_entity_char  }; # $c1_entity_char
335    
336  sub parse_byte_string ($$$$;$) {  sub parse_byte_string ($$$$;$) {
337      my $self = shift;
338      my $charset_name = shift;
339      open my $input, '<', ref $_[0] ? $_[0] : \($_[0]);
340      return $self->parse_byte_stream ($charset_name, $input, @_[1..$#_]);
341    } # parse_byte_string
342    
343    sub parse_byte_stream ($$$$;$) {
344    my $self = ref $_[0] ? shift : shift->new;    my $self = ref $_[0] ? shift : shift->new;
345    my $charset_name = shift;    my $charset_name = shift;
346    open my $byte_stream, '<', ref $_[0] ? $_[0] : \($_[0]);    my $byte_stream = $_[0];
347    
348    my $onerror = $_[2] || sub {    my $onerror = $_[2] || sub {
349      my (%opt) = @_;      my (%opt) = @_;
# Line 513  sub parse_byte_string ($$$$;$) { Line 522  sub parse_byte_string ($$$$;$) {
522    
523    my $char_onerror = sub {    my $char_onerror = sub {
524      my (undef, $type, %opt) = @_;      my (undef, $type, %opt) = @_;
525      !!!parse-error (%opt, type => $type);      !!!parse-error (%opt, type => $type,
526                        line => $self->{line}, column => $self->{column} + 1);
527      if ($opt{octets}) {      if ($opt{octets}) {
528        ${$opt{octets}} = "\x{FFFD}"; # relacement character        ${$opt{octets}} = "\x{FFFD}"; # relacement character
529      }      }
# Line 545  sub parse_byte_string ($$$$;$) { Line 555  sub parse_byte_string ($$$$;$) {
555      $return = $self->parse_char_stream ($char_stream, @args);      $return = $self->parse_char_stream ($char_stream, @args);
556    };    };
557    return $return;    return $return;
558  } # parse_byte_string  } # parse_byte_stream
559    
560  ## NOTE: HTML5 spec says that the encoding layer MUST NOT strip BOM  ## NOTE: HTML5 spec says that the encoding layer MUST NOT strip BOM
561  ## and the HTML layer MUST ignore it.  However, we does strip BOM in  ## and the HTML layer MUST ignore it.  However, we does strip BOM in
# Line 558  sub parse_byte_string ($$$$;$) { Line 568  sub parse_byte_string ($$$$;$) {
568    
569  sub parse_char_string ($$$;$) {  sub parse_char_string ($$$;$) {
570    my $self = shift;    my $self = shift;
571    open my $input, '<:utf8', ref $_[0] ? $_[0] : \($_[0]);    require utf8;
572      my $s = ref $_[0] ? $_[0] : \($_[0]);
573      open my $input, '<' . (utf8::is_utf8 ($$s) ? ':utf8' : ''), $s;
574    return $self->parse_char_stream ($input, @_[1..$#_]);    return $self->parse_char_stream ($input, @_[1..$#_]);
575  } # parse_char_string  } # parse_char_string
576  *parse_string = \&parse_char_string;  *parse_string = \&parse_char_string;
# Line 584  sub parse_char_stream ($$$;$) { Line 596  sub parse_char_stream ($$$;$) {
596      pop @{$self->{prev_char}};      pop @{$self->{prev_char}};
597      unshift @{$self->{prev_char}}, $self->{next_char};      unshift @{$self->{prev_char}}, $self->{next_char};
598    
599      my $char = $input->getc;      my $char;
600        if (defined $self->{next_next_char}) {
601          $char = $self->{next_next_char};
602          delete $self->{next_next_char};
603        } else {
604          $char = $input->getc;
605        }
606      $self->{next_char} = -1 and return unless defined $char;      $self->{next_char} = -1 and return unless defined $char;
607      $self->{next_char} = ord $char;      $self->{next_char} = ord $char;
608    
# Line 599  sub parse_char_stream ($$$;$) { Line 617  sub parse_char_stream ($$$;$) {
617      } elsif ($self->{next_char} == 0x000D) { # CR      } elsif ($self->{next_char} == 0x000D) { # CR
618        !!!cp ('j2');        !!!cp ('j2');
619        my $next = $input->getc;        my $next = $input->getc;
620        if ($next ne "\x0A") {        if (defined $next and $next ne "\x0A") {
621          $input->ungetc ($next);          $self->{next_next_char} = $next;
622        }        }
623        $self->{next_char} = 0x000A; # LF # MUST        $self->{next_char} = 0x000A; # LF # MUST
624        $self->{line}++;        $self->{line}++;
# Line 3356  sub _reset_insertion_mode ($) { Line 3374  sub _reset_insertion_mode ($) {
3374        if ($self->{open_elements}->[0]->[0] eq $node->[0]) {        if ($self->{open_elements}->[0]->[0] eq $node->[0]) {
3375          $last = 1;          $last = 1;
3376          if (defined $self->{inner_html_node}) {          if (defined $self->{inner_html_node}) {
3377            if ($self->{inner_html_node}->[1] & TABLE_CELL_EL) {            !!!cp ('t28');
3378              !!!cp ('t27');            $node = $self->{inner_html_node};
3379              #          } else {
3380            } else {            die "_reset_insertion_mode: t27";
             !!!cp ('t28');  
             $node = $self->{inner_html_node};  
           }  
3381          }          }
3382        }        }
3383              
3384      ## Step 4..14        ## Step 4..14
3385      my $new_mode;        my $new_mode;
3386      if ($node->[1] & FOREIGN_EL) {        if ($node->[1] & FOREIGN_EL) {
3387        ## NOTE: Strictly spaking, the line below only applies to MathML and          !!!cp ('t28.1');
3388        ## SVG elements.  Currently the HTML syntax supports only MathML and          ## NOTE: Strictly spaking, the line below only applies to MathML and
3389        ## SVG elements as foreigners.          ## SVG elements.  Currently the HTML syntax supports only MathML and
3390        $new_mode = $self->{insertion_mode} | IN_FOREIGN_CONTENT_IM;          ## SVG elements as foreigners.
3391        ## ISSUE: What is set as the secondary insertion mode?          $new_mode = $self->{insertion_mode} | IN_FOREIGN_CONTENT_IM;
3392      } else {          ## ISSUE: What is set as the secondary insertion mode?
3393        $new_mode = {        } elsif ($node->[1] & TABLE_CELL_EL) {
3394            if ($last) {
3395              !!!cp ('t28.2');
3396              #
3397            } else {
3398              !!!cp ('t28.3');
3399              $new_mode = IN_CELL_IM;
3400            }
3401          } else {
3402            !!!cp ('t28.4');
3403            $new_mode = {
3404                        select => IN_SELECT_IM,                        select => IN_SELECT_IM,
3405                        ## NOTE: |option| and |optgroup| do not set                        ## NOTE: |option| and |optgroup| do not set
3406                        ## insertion mode to "in select" by themselves.                        ## insertion mode to "in select" by themselves.
                       td => IN_CELL_IM,  
                       th => IN_CELL_IM,  
3407                        tr => IN_ROW_IM,                        tr => IN_ROW_IM,
3408                        tbody => IN_TABLE_BODY_IM,                        tbody => IN_TABLE_BODY_IM,
3409                        thead => IN_TABLE_BODY_IM,                        thead => IN_TABLE_BODY_IM,
# Line 3392  sub _reset_insertion_mode ($) { Line 3415  sub _reset_insertion_mode ($) {
3415                        body => IN_BODY_IM,                        body => IN_BODY_IM,
3416                        frameset => IN_FRAMESET_IM,                        frameset => IN_FRAMESET_IM,
3417                       }->{$node->[0]->manakai_local_name};                       }->{$node->[0]->manakai_local_name};
3418      }        }
3419      $self->{insertion_mode} = $new_mode and return if defined $new_mode;        $self->{insertion_mode} = $new_mode and return if defined $new_mode;
3420                
3421        ## Step 15        ## Step 15
3422        if ($node->[1] & HTML_EL) {        if ($node->[1] & HTML_EL) {
# Line 4136  sub _tree_construction_main ($) { Line 4159  sub _tree_construction_main ($) {
4159              !!!next-token;              !!!next-token;
4160              next B;              next B;
4161            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4162              !!!cp ('t94');              !!!cp ('t93.2');
4163              #              !!!parse-error (type => 'after head:head', token => $token); ## TODO: error type
4164                ## Ignore the token
4165                !!!nack ('t93.3');
4166                !!!next-token;
4167                next B;
4168            } else {            } else {
4169              !!!cp ('t95');              !!!cp ('t95');
4170              !!!parse-error (type => 'in head:head', token => $token); # or in head noscript              !!!parse-error (type => 'in head:head', token => $token); # or in head noscript
# Line 4459  sub _tree_construction_main ($) { Line 4486  sub _tree_construction_main ($) {
4486                  $self->{insertion_mode} = AFTER_HEAD_IM;                  $self->{insertion_mode} = AFTER_HEAD_IM;
4487                  !!!next-token;                  !!!next-token;
4488                  next B;                  next B;
4489                  } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4490                    !!!cp ('t134.1');
4491                    !!!parse-error (type => 'unmatched end tag:head', token => $token);
4492                    ## Ignore the token
4493                    !!!next-token;
4494                    next B;
4495                } else {                } else {
4496                  !!!cp ('t135');                  die "$0: $self->{insertion_mode}: Unknown insertion mode";
                 #  
4497                }                }
4498              } elsif ($token->{tag_name} eq 'noscript') {              } elsif ($token->{tag_name} eq 'noscript') {
4499                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
# Line 4470  sub _tree_construction_main ($) { Line 4502  sub _tree_construction_main ($) {
4502                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
4503                  !!!next-token;                  !!!next-token;
4504                  next B;                  next B;
4505                } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {                } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM or
4506                           $self->{insertion_mode} == AFTER_HEAD_IM) {
4507                  !!!cp ('t137');                  !!!cp ('t137');
4508                  !!!parse-error (type => 'unmatched end tag:noscript', token => $token);                  !!!parse-error (type => 'unmatched end tag:noscript', token => $token);
4509                  ## Ignore the token ## ISSUE: An issue in the spec.                  ## Ignore the token ## ISSUE: An issue in the spec.
# Line 4483  sub _tree_construction_main ($) { Line 4516  sub _tree_construction_main ($) {
4516              } elsif ({              } elsif ({
4517                        body => 1, html => 1,                        body => 1, html => 1,
4518                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
4519                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM or
4520                  !!!cp ('t139');                    $self->{insertion_mode} == IN_HEAD_IM or
4521                  ## As if <head>                    $self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
                 !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);  
                 $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});  
                 push @{$self->{open_elements}},  
                     [$self->{head_element}, $el_category->{head}];  
   
                 $self->{insertion_mode} = IN_HEAD_IM;  
                 ## Reprocess in the "in head" insertion mode...  
               } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {  
4522                  !!!cp ('t140');                  !!!cp ('t140');
4523                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4524                  ## Ignore the token                  ## Ignore the token
4525                  !!!next-token;                  !!!next-token;
4526                  next B;                  next B;
4527                  } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4528                    !!!cp ('t140.1');
4529                    !!!parse-error (type => 'unmatched end tag:' . $token->{tag_name}, token => $token);
4530                    ## Ignore the token
4531                    !!!next-token;
4532                    next B;
4533                } else {                } else {
4534                  !!!cp ('t141');                  die "$0: $self->{insertion_mode}: Unknown insertion mode";
4535                }                }
4536                              } elsif ($token->{tag_name} eq 'p') {
4537                #                !!!cp ('t142');
4538              } elsif ({                !!!parse-error (type => 'unmatched end tag:p', token => $token);
4539                        p => 1, br => 1,                ## Ignore the token
4540                       }->{$token->{tag_name}}) {                !!!next-token;
4541                  next B;
4542                } elsif ($token->{tag_name} eq 'br') {
4543                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4544                  !!!cp ('t142');                  !!!cp ('t142.2');
4545                  ## As if <head>                  ## (before head) as if <head>, (in head) as if </head>
4546                  !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);                  !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
4547                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
4548                  push @{$self->{open_elements}},                  $self->{insertion_mode} = AFTER_HEAD_IM;
4549                      [$self->{head_element}, $el_category->{head}];    
4550                    ## Reprocess in the "after head" insertion mode...
4551                  } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
4552                    !!!cp ('t143.2');
4553                    ## As if </head>
4554                    pop @{$self->{open_elements}};
4555                    $self->{insertion_mode} = AFTER_HEAD_IM;
4556      
4557                    ## Reprocess in the "after head" insertion mode...
4558                  } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4559                    !!!cp ('t143.3');
4560                    ## ISSUE: Two parse errors for <head><noscript></br>
4561                    !!!parse-error (type => 'unmatched end tag:br', token => $token);
4562                    ## As if </noscript>
4563                    pop @{$self->{open_elements}};
4564                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
4565    
4566                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
4567                } else {                  ## As if </head>
4568                  !!!cp ('t143');                  pop @{$self->{open_elements}};
4569                }                  $self->{insertion_mode} = AFTER_HEAD_IM;
4570    
4571                #                  ## Reprocess in the "after head" insertion mode...
4572              } else {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4573                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                  !!!cp ('t143.4');
                 !!!cp ('t144');  
4574                  #                  #
4575                } else {                } else {
4576                  !!!cp ('t145');                  die "$0: $self->{insertion_mode}: Unknown insertion mode";
                 !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);  
                 ## Ignore the token  
                 !!!next-token;  
                 next B;  
4577                }                }
4578    
4579                  ## ISSUE: does not agree with IE7 - it doesn't ignore </br>.
4580                  !!!parse-error (type => 'unmatched end tag:br', token => $token);
4581                  ## Ignore the token
4582                  !!!next-token;
4583                  next B;
4584                } else {
4585                  !!!cp ('t145');
4586                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name}, token => $token);
4587                  ## Ignore the token
4588                  !!!next-token;
4589                  next B;
4590              }              }
4591    
4592              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {

Legend:
Removed from v.1.136  
changed lines
  Added in v.1.140

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24