/[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.58 by wakaba, Tue Sep 4 11:19:07 2007 UTC revision 1.64 by wakaba, Sun Nov 11 08:39:42 2007 UTC
# Line 1  Line 1 
1  package Whatpm::HTML;  package Whatpm::HTML;
2  use strict;  use strict;
3  our $VERSION=do{my @r=(q$Revision$=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};  our $VERSION=do{my @r=(q$Revision$=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
4    use Error qw(:try);
5    
6  ## ISSUE:  ## ISSUE:
7  ## var doc = implementation.createDocument (null, null, null);  ## var doc = implementation.createDocument (null, null, null);
# Line 84  my $formatting_category = { Line 85  my $formatting_category = {
85  };  };
86  # $phrasing_category: all other elements  # $phrasing_category: all other elements
87    
88    sub parse_byte_string ($$$$;$) {
89      my $self = ref $_[0] ? shift : shift->new;
90      my $charset = shift;
91      my $bytes_s = ref $_[0] ? $_[0] : \($_[0]);
92      my $s;
93      
94      if (defined $charset) {
95        require Encode; ## TODO: decode(utf8) don't delete BOM
96        $s = \ (Encode::decode ($charset, $$bytes_s));
97        $self->{input_encoding} = lc $charset; ## TODO: normalize name
98        $self->{confident} = 1;
99      } else {
100        $charset = 'windows-1252'; ## TODO: for now.
101        $s = \ (Encode::decode ($charset, $$bytes_s));
102        $self->{input_encoding} = $charset;
103        $self->{confident} = 0;
104      }
105    
106      $self->{change_encoding} = sub {
107        my $self = shift;
108        my $charset = lc shift;
109        ## TODO: if $charset is supported
110        ## TODO: normalize charset name
111    
112        ## "Change the encoding" algorithm:
113    
114        ## Step 1    
115        if ($charset eq 'utf-16') { ## ISSUE: UTF-16BE -> UTF-8? UTF-16LE -> UTF-8?
116          $charset = 'utf-8';
117        }
118    
119        ## Step 2
120        if (defined $self->{input_encoding} and
121            $self->{input_encoding} eq $charset) {
122          $self->{confident} = 1;
123          return;
124        }
125    
126        !!!parse-error (type => 'charset label detected:'.$self->{input_encoding}.
127            ':'.$charset, level => 'w');
128    
129        ## Step 3
130        # if (can) {
131          ## change the encoding on the fly.
132          #$self->{confident} = 1;
133          #return;
134        # }
135    
136        ## Step 4
137        throw Whatpm::HTML::RestartParser (charset => $charset);
138      }; # $self->{change_encoding}
139    
140      my @args = @_; shift @args; # $s
141      my $return;
142      try {
143        $return = $self->parse_char_string ($s, @args);  
144      } catch Whatpm::HTML::RestartParser with {
145        my $charset = shift->{charset};
146        $s = \ (Encode::decode ($charset, $$bytes_s));    
147        $self->{input_encoding} = $charset; ## TODO: normalize
148        $self->{confident} = 1;
149        $return = $self->parse_char_string ($s, @args);
150      };
151      return $return;
152    } # parse_byte_string
153    
154    *parse_char_string = \&parse_string;
155    
156  sub parse_string ($$$;$) {  sub parse_string ($$$;$) {
157    my $self = shift->new;    my $self = ref $_[0] ? shift : shift->new;
158    my $s = \$_[0];    my $s = ref $_[0] ? $_[0] : \($_[0]);
159    $self->{document} = $_[1];    $self->{document} = $_[1];
160      @{$self->{document}->child_nodes} = ();
161    
162    ## NOTE: |set_inner_html| copies most of this method's code    ## NOTE: |set_inner_html| copies most of this method's code
163    
164      $self->{confident} = 1 unless exists $self->{confident};
165      $self->{document}->input_encoding ($self->{input_encoding})
166          if defined $self->{input_encoding};
167    
168    my $i = 0;    my $i = 0;
169    my $line = 1;    my $line = 1;
170    my $column = 0;    my $column = 0;
# Line 147  sub new ($) { Line 221  sub new ($) {
221    $self->{parse_error} = sub {    $self->{parse_error} = sub {
222      #      #
223    };    };
224      $self->{change_encoding} = sub {
225        # if ($_[0] is a supported encoding) {
226        #   run "change the encoding" algorithm;
227        #   throw Whatpm::HTML::RestartParser (charset => $new_encoding);
228        # }
229      };
230      $self->{application_cache_selection} = sub {
231        #
232      };
233    return $self;    return $self;
234  } # new  } # new
235    
# Line 263  sub _initialize_tokenizer ($) { Line 346  sub _initialize_tokenizer ($) {
346  ## has completed loading.  If one has, then it MUST be executed  ## has completed loading.  If one has, then it MUST be executed
347  ## and removed from the list.  ## and removed from the list.
348    
349    ## NOTE: HTML5 "Writing HTML documents" section, applied to
350    ## documents and not to user agents and conformance checkers,
351    ## contains some requirements that are not detected by the
352    ## parsing algorithm:
353    ## - Some requirements on character encoding declarations. ## TODO
354    ## - "Elements MUST NOT contain content that their content model disallows."
355    ##   ... Some are parse error, some are not (will be reported by c.c.).
356    ## - Polytheistic slash SHOULD NOT be used. (Applied only to atheists.) ## TODO
357    ## - Text (in elements, attributes, and comments) SHOULD NOT contain
358    ##   control characters other than space characters. ## TODO: (what is control character? C0, C1 and DEL?  Unicode control character?)
359    
360    ## TODO: HTML5 poses authors two SHOULD-level requirements that cannot
361    ## be detected by the HTML5 parsing algorithm:
362    ## - Text,
363    
364  sub _get_next_token ($) {  sub _get_next_token ($) {
365    my $self = shift;    my $self = shift;
366    if (@{$self->{token}}) {    if (@{$self->{token}}) {
# Line 2080  sub _tree_construction_root_element ($) Line 2178  sub _tree_construction_root_element ($)
2178              redo B;              redo B;
2179            }            }
2180          }          }
2181    
2182            $self->{application_cache_selection}->(undef);
2183    
2184            #
2185          } elsif ($token->{type} == START_TAG_TOKEN) {
2186            if ($token->{tag_name} eq 'html' and
2187                $token->{attributes}->{manifest}) { ## ISSUE: Spec spells as "application"
2188              $self->{application_cache_selection}
2189                   ->($token->{attributes}->{manifest}->{value});
2190              ## ISSUE: No relative reference resolution?
2191            } else {
2192              $self->{application_cache_selection}->(undef);
2193            }
2194    
2195            ## ISSUE: There is an issue in the spec
2196          #          #
2197        } elsif ({        } elsif ({
                 START_TAG_TOKEN, 1,  
2198                  END_TAG_TOKEN, 1,                  END_TAG_TOKEN, 1,
2199                  END_OF_FILE_TOKEN, 1,                  END_OF_FILE_TOKEN, 1,
2200                 }->{$token->{type}}) {                 }->{$token->{type}}) {
2201            $self->{application_cache_selection}->(undef);
2202    
2203          ## ISSUE: There is an issue in the spec          ## ISSUE: There is an issue in the spec
2204          #          #
2205        } else {        } else {
2206          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
2207        }        }
2208    
2209        my $root_element; !!!create-element ($root_element, 'html');        my $root_element; !!!create-element ($root_element, 'html');
2210        $self->{document}->append_child ($root_element);        $self->{document}->append_child ($root_element);
2211        push @{$self->{open_elements}}, [$root_element, 'html'];        push @{$self->{open_elements}}, [$root_element, 'html'];
# Line 2750  sub _tree_construction_main ($) { Line 2865  sub _tree_construction_main ($) {
2865                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
2866    
2867                unless ($self->{confident}) {                unless ($self->{confident}) {
                 my $charset;  
2868                  if ($token->{attributes}->{charset}) { ## TODO: And if supported                  if ($token->{attributes}->{charset}) { ## TODO: And if supported
2869                    $charset = $token->{attributes}->{charset}->{value};                    $self->{change_encoding}
2870                  }                        ->($self, $token->{attributes}->{charset}->{value});
2871                  if ($token->{attributes}->{'http-equiv'}) {                  } elsif ($token->{attributes}->{content}) {
2872                    ## ISSUE: Algorithm name in the spec was incorrect so that not linked to the definition.                    ## ISSUE: Algorithm name in the spec was incorrect so that not linked to the definition.
2873                    if ($token->{attributes}->{'http-equiv'}->{value}                    if ($token->{attributes}->{content}->{value}
2874                        =~ /\A[^;]*;[\x09-\x0D\x20]*charset[\x09-\x0D\x20]*=                        =~ /\A[^;]*;[\x09-\x0D\x20]*charset[\x09-\x0D\x20]*=
2875                            [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                            [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
2876                            ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {                            ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {
2877                      $charset = defined $1 ? $1 : defined $2 ? $2 : $3;                      $self->{change_encoding}
2878                    } ## TODO: And if supported                          ->($self, defined $1 ? $1 : defined $2 ? $2 : $3);
2879                      }
2880                  }                  }
                 ## TODO: Change the encoding  
2881                }                }
2882    
               ## TODO: Extracting |charset| from |meta|.  
2883                pop @{$self->{open_elements}}                pop @{$self->{open_elements}}
2884                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
2885                !!!next-token;                !!!next-token;
# Line 4340  sub _tree_construction_main ($) { Line 4453  sub _tree_construction_main ($) {
4453          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
4454    
4455          unless ($self->{confident}) {          unless ($self->{confident}) {
           my $charset;  
4456            if ($token->{attributes}->{charset}) { ## TODO: And if supported            if ($token->{attributes}->{charset}) { ## TODO: And if supported
4457              $charset = $token->{attributes}->{charset}->{value};              $self->{change_encoding}
4458            }                  ->($self, $token->{attributes}->{charset}->{value});
4459            if ($token->{attributes}->{'http-equiv'}) {            } elsif ($token->{attributes}->{content}) {
4460              ## ISSUE: Algorithm name in the spec was incorrect so that not linked to the definition.              ## ISSUE: Algorithm name in the spec was incorrect so that not linked to the definition.
4461              if ($token->{attributes}->{'http-equiv'}->{value}              if ($token->{attributes}->{content}->{value}
4462                  =~ /\A[^;]*;[\x09-\x0D\x20]*charset[\x09-\x0D\x20]*=                  =~ /\A[^;]*;[\x09-\x0D\x20]*charset[\x09-\x0D\x20]*=
4463                      [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                      [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
4464                      ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {                      ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {
4465                $charset = defined $1 ? $1 : defined $2 ? $2 : $3;                $self->{change_encoding}
4466              } ## TODO: And if supported                    ->($self, defined $1 ? $1 : defined $2 ? $2 : $3);
4467                }
4468            }            }
           ## TODO: Change the encoding  
4469          }          }
4470    
4471          !!!next-token;          !!!next-token;
# Line 5179  sub set_inner_html ($$$) { Line 5291  sub set_inner_html ($$$) {
5291    my $s = \$_[0];    my $s = \$_[0];
5292    my $onerror = $_[1];    my $onerror = $_[1];
5293    
5294      ## ISSUE: Should {confident} be true?
5295    
5296    my $nt = $node->node_type;    my $nt = $node->node_type;
5297    if ($nt == 9) {    if ($nt == 9) {
5298      # MUST      # MUST
# Line 5331  sub set_inner_html ($$$) { Line 5445  sub set_inner_html ($$$) {
5445    
5446  } # tree construction stage  } # tree construction stage
5447    
5448  sub get_inner_html ($$$) {  package Whatpm::HTML::RestartParser;
5449    my (undef, $node, $on_error) = @_;  push our @ISA, 'Error';
   
   ## Step 1  
   my $s = '';  
   
   my $in_cdata;  
   my $parent = $node;  
   while (defined $parent) {  
     if ($parent->node_type == 1 and  
         $parent->namespace_uri eq 'http://www.w3.org/1999/xhtml' and  
         {  
           style => 1, script => 1, xmp => 1, iframe => 1,  
           noembed => 1, noframes => 1, noscript => 1,  
         }->{$parent->local_name}) { ## TODO: case thingy  
       $in_cdata = 1;  
     }  
     $parent = $parent->parent_node;  
   }  
   
   ## Step 2  
   my @node = @{$node->child_nodes};  
   C: while (@node) {  
     my $child = shift @node;  
     unless (ref $child) {  
       if ($child eq 'cdata-out') {  
         $in_cdata = 0;  
       } else {  
         $s .= $child; # end tag  
       }  
       next C;  
     }  
       
     my $nt = $child->node_type;  
     if ($nt == 1) { # Element  
       my $tag_name = $child->tag_name; ## TODO: manakai_tag_name  
       $s .= '<' . $tag_name;  
       ## NOTE: Non-HTML case:  
       ## <http://permalink.gmane.org/gmane.org.w3c.whatwg.discuss/11191>  
   
       my @attrs = @{$child->attributes}; # sort order MUST be stable  
       for my $attr (@attrs) { # order is implementation dependent  
         my $attr_name = $attr->name; ## TODO: manakai_name  
         $s .= ' ' . $attr_name . '="';  
         my $attr_value = $attr->value;  
         ## escape  
         $attr_value =~ s/&/&amp;/g;  
         $attr_value =~ s/</&lt;/g;  
         $attr_value =~ s/>/&gt;/g;  
         $attr_value =~ s/"/&quot;/g;  
         $s .= $attr_value . '"';  
       }  
       $s .= '>';  
         
       next C if {  
         area => 1, base => 1, basefont => 1, bgsound => 1,  
         br => 1, col => 1, embed => 1, frame => 1, hr => 1,  
         img => 1, input => 1, link => 1, meta => 1, param => 1,  
         spacer => 1, wbr => 1,  
       }->{$tag_name};  
   
       $s .= "\x0A" if $tag_name eq 'pre' or $tag_name eq 'textarea';  
   
       if (not $in_cdata and {  
         style => 1, script => 1, xmp => 1, iframe => 1,  
         noembed => 1, noframes => 1, noscript => 1,  
         plaintext => 1,  
       }->{$tag_name}) {  
         unshift @node, 'cdata-out';  
         $in_cdata = 1;  
       }  
   
       unshift @node, @{$child->child_nodes}, '</' . $tag_name . '>';  
     } elsif ($nt == 3 or $nt == 4) {  
       if ($in_cdata) {  
         $s .= $child->data;  
       } else {  
         my $value = $child->data;  
         $value =~ s/&/&amp;/g;  
         $value =~ s/</&lt;/g;  
         $value =~ s/>/&gt;/g;  
         $value =~ s/"/&quot;/g;  
         $s .= $value;  
       }  
     } elsif ($nt == 8) {  
       $s .= '<!--' . $child->data . '-->';  
     } elsif ($nt == 10) {  
       $s .= '<!DOCTYPE ' . $child->name . '>';  
     } elsif ($nt == 5) { # entrefs  
       push @node, @{$child->child_nodes};  
     } else {  
       $on_error->($child) if defined $on_error;  
     }  
     ## ISSUE: This code does not support PIs.  
   } # C  
     
   ## Step 3  
   return \$s;  
 } # get_inner_html  
5450    
5451  1;  1;
5452  # $Date$  # $Date$

Legend:
Removed from v.1.58  
changed lines
  Added in v.1.64

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24