Changeset 72

Show
Ignore:
Timestamp:
2007年07月09日 22時57分28秒 (1 year ago)
Author:
rintaro
Message:

Nenshi:

  • HTMLFormFiller fix and testcase use Test::Base;
  • Makefile.PL changed: use_test_base
  • HTMLParser and test.
Location:
Nenshi/trunk
Files:
2 added
3 modified
1 moved

Legend:

Unmodified
Added
Removed
  • Nenshi/trunk/Makefile.PL

    r71 r72  
    2626build_requires 'Test::More'; 
    2727 
    28 #use_test_base; 
     28use_test_base; 
    2929auto_include; 
    3030WriteAll; 
  • Nenshi/trunk/lib/Nenshi/Filter/HTMLFormFiller.pm

    r61 r72  
    44use warnings; 
    55 
    6 use Iterator::Simple qw(ifilter); 
     6use Iterator::Simple qw(ifilter iter); 
    77use List::Util qw(first); 
    88use Nenshi::Core qw(:eventkind Attrs QName); 
    99 
     10use overload  
     11        '&{}' => sub { my $self = shift; sub { $self->__call__(@_) } }; 
    1012sub new { 
    1113        my $self = bless {}, shift; 
     
    1416        $self->{name} = $o{name}; 
    1517        $self->{data} = $o{data} || {}; 
     18        $self; 
    1619} 
    1720 
     
    3134 
    3235                        if($tagname eq 'form' and ( 
    33                                 $self->{name} and $attrs->get('name') == $self->{name} or 
    34                                 $self->{id} and $attrs->get('id') = $self->{id} or 
     36                                $self->{name} and $attrs->get('name') eq $self->{name} or 
     37                                $self->{id} and $attrs->get('id') eq $self->{id} or 
    3538                                not($self->{id} or $self->{name})) 
    3639                        ) { 
     
    5154                                                                } 
    5255                                                                else { 
    53                                                                         $checked = scalar @{(grep { $_ } @$value)} 
     56                                                                        $checked = scalar (grep { $_ } @$value) 
    5457                                                                } 
    5558                                                        } 
     
    6366                                                        } 
    6467                                                        if($checked) { 
    65                                                                 $attrs |= [[checked => 'checked']]; 
     68                                                                $attrs |= [[QName('checked') => 'checked']]; 
    6669                                                        } 
    67                                                         elsif($attrs->has('checked') { 
     70                                                        elsif($attrs->has('checked')) { 
    6871                                                                $attrs -= 'checked'; 
    6972                                                        } 
     
    7881                                                        } 
    7982                                                        if(defined $value) { 
    80                                                                 $attrs |= [[ value => "$value" ]]; 
     83                                                                $attrs |= [[ QName('value'), "$value" ]]; 
    8184                                                        } 
    8285                                                } 
     
    9093                                        } 
    9194                                } 
    92                                 elsif($tagname == 'textarea') { 
     95                                elsif($tagname eq 'textarea') { 
    9396                                        my $name = $attrs->get('name'); 
    9497                                        if(exists $self->{data}{$name}) { 
     
    143146                                my($tag, $attrs) = @$odata; 
    144147                                if($selected) { 
    145                                         $attrs |= [[selected => 'selected']]; 
     148                                        $attrs |= [[QName('selected') => 'selected']]; 
    146149                                } 
    147150                                else { 
     
    163166                                $in_textarea = 0; 
    164167                        } 
    165                         return iter([@buf, [$kind, $data], $pos]); 
     168                        return iter([@buf, [$kind, $data, $pos]]); 
    166169                } 
    167170                else { 
  • Nenshi/trunk/lib/Nenshi/Input.pm

    r71 r72  
    1414use base qw(Exporter); 
    1515 
    16 our @EXPORT = qw(XML HTML XMLParser); 
     16our @EXPORT = qw(XML HTML XMLParser HTMLParser); 
    1717 
    1818sub XMLParser { Nenshi::XMLParser->new(@_); } 
     19sub HTMLParser { Nenshi::HTMLParser->new(@_); } 
    1920sub XML { Stream(list(XMLParser(IO::String->new($_[0])))); } 
    2021sub HTML { Stream(list(HTMLParser(IO::String->new(@_)))); } 
     
    165166                                                $parser->parse_done; 
    166167                                                undef $parser; 
    167                                                 $self->{source}->close; 
    168168                                                delete $self->{parser}; 
    169169                                                delete  $self->{source}; 
     
    195195} 
    196196 
     197{ 
     198        package Nenshi::HTMLParser; 
     199 
     200        use base qw(HTML::Parser); 
     201        use Iterator::Simple qw( iterator iter ); 
     202        use Nenshi::Core qw( :eventkind Stream Attrs QName ); 
     203        use Nenshi::Util qw( set ); 
     204        use HTML::Entities; 
     205 
     206        use constant _EMPTY_ELEMS => set( 
     207                qw( area base basefont br col frame hr img input isindex link meta param ) 
     208        ); 
     209 
     210        sub init { 
     211                my($self, $source, $o) = @_; 
     212                $self->SUPER::init( 
     213                        api_version => 3, 
     214                        handlers => { 
     215                                start => ['handle_start', 'self,tagname,attr,attrseq,line,column'], 
     216                                end => ['handle_end', 'self,tagname,line,column'], 
     217                                text => ['handle_text', 'self,text,line,column'], 
     218                                comment => ['handle_comment', 'self,text,line,column'], 
     219                                declaration => ['handle_doctype', 'self,tokens,line,column'], 
     220                                process => ['handle_process', 'self,token0,line,column'], 
     221                        }, 
     222                        unbroken_text => 1, 
     223                        attr_encoded => 1, 
     224                        #utf8_mode => 1, 
     225                ); 
     226                $self->{source} = $source; 
     227                $self->{encoding} = $o->{encoding} || 'utf8'; 
     228                $self->{filename} = $o->{filename}; 
     229                $self->{_queue} = []; 
     230                $self->{_open_tags} = []; 
     231                $self; 
     232        } 
     233         
     234        sub _enqueue { 
     235                my $self = shift; 
     236                push @{$self->{_queue}}, [ @_[0,1], [$self->{filename}, @{$_[2]}] ] 
     237        } 
     238 
     239        sub handle_start { 
     240                my $self = shift; 
     241                my($tag, $attr, $attrseq, $line, $col) = @_; 
     242                my @fixed_attr; 
     243                for my $name (@$attrseq) { 
     244                        my $val = $attr->{$name}; 
     245                        if(not Encode::is_utf8($val)) { 
     246                                $val = Encode::decode($self->{encoding}, $val); 
     247                        } 
     248                        decode_entities($val); 
     249                        push @fixed_attr, [QName($name), $val], 
     250                } 
     251                $self->_enqueue(START_, [ QName($tag), Attrs(\@fixed_attr) ], [$line, $col] ); 
     252                if(_EMPTY_ELEMS->contains($tag)) { 
     253                        $self->_enqueue(END_, QName($tag), [$line, $col]); 
     254                } 
     255                else { 
     256                        push @{$self->{_open_tags}}, $tag; 
     257                } 
     258        } 
     259 
     260        sub handle_end { 
     261                my $self = shift; 
     262                my($tag, $line, $col) = @_; 
     263                if(not _EMPTY_ELEMS->contains($tag)) { 
     264                        while(@{$self->{_open_tags}}) { 
     265                                my $open_tag = pop @{$self->{_open_tags}}; 
     266                                $self->_enqueue(END_, QName($open_tag), [$line, $col]); 
     267                                last if $open_tag eq $tag; 
     268                        } 
     269                } 
     270        } 
     271 
     272        sub handle_text { 
     273                my $self = shift; 
     274                my($text, $line, $col) =@_; 
     275                if(not Encode::is_utf8($text)) { 
     276                        $text = Encode::decode($self->{encoding}, $text); 
     277                } 
     278                decode_entities($text); 
     279                $self->_enqueue(TEXT, $text, [$line, $col]); 
     280        } 
     281 
     282        sub handle_comment { 
     283                my $self = shift; 
     284                my($text, $line, $col) = @_; 
     285                $self->_enqueue(COMMENT, $text, [$line, $col]); 
     286        } 
     287 
     288        sub handle_process { 
     289                my $self = shift; 
     290                my($data, $line, $col) = @_; 
     291                my $target; 
     292                ($target, $data) = split(' ', $data, 2); 
     293                $data =~ s/\s*\??$//s; # strip last '?' 
     294                $self->_enqueue(PI, [$target, $data], [$line, $col]); 
     295        } 
     296 
     297        sub handle_declaration { 
     298                my $self = shift; 
     299                my($data, $line, $col); 
     300                warn $data; 
     301        } 
     302 
     303        sub parse { 
     304                my($self) = @_; 
     305                my $bufsize = 4096; 
     306                my $_queue = $self->{_queue}; 
     307                my $finished = 0; 
     308 
     309                my $generator = iterator { 
     310                        while(1) { 
     311                                if(@$_queue) { 
     312                                        return shift @$_queue; 
     313                                } 
     314                                return if $finished; 
     315                                my $data; 
     316                                if($self->{source}->read($data, $bufsize)) { 
     317                                        $self->SUPER::parse($data); 
     318                                        next; 
     319                                } 
     320                                else { 
     321                                        $self->eof; 
     322                                        delete $self->{source}; 
     323                                        $finished = 1; 
     324                                        next; 
     325                                } 
     326                                 
     327                                if($@) { 
     328                                        Nenshi::ParseError->throw("$@",$self->{filename},$self->current_line, $self->current_column); 
     329                                } 
     330                        } 
     331                        return; 
     332                }; 
     333                return Stream($generator); 
     334        } 
     335 
     336        sub __iter__ { 
     337                my($self) = @_; 
     338                return iter($self->parse()) 
     339        } 
     340} 
    1973411; 
     342 
    198343__END__ 
    199         sub _coalesce { 
     344 
     345sub _coalesce { 
    200346                my($stream) = @_; 
    201347                my @textbuf; 
     
    2323781; 
    233379 
    234 __END__ 
    235 package Nenshi::HTMLParser; 
    236 { 
    237  
    238 use base qw(HTML::Parser); 
    239 use Nenshi::Stream qw( :eventkind ); 
    240  
    241 my %_EMPTY_ELEMS = ( 
    242         map {$_ => 1} qw( area base basefont br col frame hr img input isindex link meta param ) 
    243 ); 
    244  
    245 sub new { 
    246         my $class = shift; 
    247         my $file = shift; 
    248         my $options = shift; 
    249  
    250         my $self = $self->SUPER::new(); 
    251 } 
    252  
    253 sub _enqueue { 
    254         my $self = shift; 
    255         push @{$self->{_queue}}, [ @_[0,1], [$self->{filename}, $_[3][0], $_[3][1]] ] 
    256 } 
    257  
    258 sub handle_text { 
    259         my $self = shift; 
    260 } 
    261  
    262 sub handle_starttag { 
    263         my $self = shift; 
    264         my($tagname, $attr, $attrseq, $line, $pos) = @_; 
    265         my @fixed_attr; 
    266         for(@$attrseq) { 
    267                 my $val = $attr->{$_} 
    268                 if(defined $val) { 
    269                         $val = $_; 
    270                 } 
    271                 push @fixed_attr, [$_, $val]; 
    272         } 
    273         $self->_enqueue(START, [ QName($tagname), Attrs(\@fixed_attr) ], [$line, $pos] ); 
    274  
    275 sub handle_end { 
    276 } 
    277  
    278 sub handle_declaration { 
    279 } 
    280  
    281 comment, process 
    282 } 
     380