Changeset 72
- Timestamp:
- 2007年07月09日 22時57分28秒 (1 year ago)
- Location:
- Nenshi/trunk
- Files:
-
- 2 added
- 3 modified
- 1 moved
-
Makefile.PL (modified) (1 diff)
-
lib/Nenshi/Filter/HTMLFormFiller.pm (modified) (9 diffs)
-
lib/Nenshi/Input.pm (modified) (4 diffs)
-
t/12_input_xml.t (moved) (moved from Nenshi/trunk/t/12_input.t)
-
t/41_builder.t (added)
-
t/51_filter_fill.t (added)
Legend:
- Unmodified
- Added
- Removed
-
Nenshi/trunk/Makefile.PL
r71 r72 26 26 build_requires 'Test::More'; 27 27 28 #use_test_base;28 use_test_base; 29 29 auto_include; 30 30 WriteAll; -
Nenshi/trunk/lib/Nenshi/Filter/HTMLFormFiller.pm
r61 r72 4 4 use warnings; 5 5 6 use Iterator::Simple qw(ifilter );6 use Iterator::Simple qw(ifilter iter); 7 7 use List::Util qw(first); 8 8 use Nenshi::Core qw(:eventkind Attrs QName); 9 9 10 use overload 11 '&{}' => sub { my $self = shift; sub { $self->__call__(@_) } }; 10 12 sub new { 11 13 my $self = bless {}, shift; … … 14 16 $self->{name} = $o{name}; 15 17 $self->{data} = $o{data} || {}; 18 $self; 16 19 } 17 20 … … 31 34 32 35 if($tagname eq 'form' and ( 33 $self->{name} and $attrs->get('name') ==$self->{name} or34 $self->{id} and $attrs->get('id') =$self->{id} or36 $self->{name} and $attrs->get('name') eq $self->{name} or 37 $self->{id} and $attrs->get('id') eq $self->{id} or 35 38 not($self->{id} or $self->{name})) 36 39 ) { … … 51 54 } 52 55 else { 53 $checked = scalar @{(grep { $_ } @$value)}56 $checked = scalar (grep { $_ } @$value) 54 57 } 55 58 } … … 63 66 } 64 67 if($checked) { 65 $attrs |= [[ checked=> 'checked']];68 $attrs |= [[QName('checked') => 'checked']]; 66 69 } 67 elsif($attrs->has('checked') {70 elsif($attrs->has('checked')) { 68 71 $attrs -= 'checked'; 69 72 } … … 78 81 } 79 82 if(defined $value) { 80 $attrs |= [[ value =>"$value" ]];83 $attrs |= [[ QName('value'), "$value" ]]; 81 84 } 82 85 } … … 90 93 } 91 94 } 92 elsif($tagname =='textarea') {95 elsif($tagname eq 'textarea') { 93 96 my $name = $attrs->get('name'); 94 97 if(exists $self->{data}{$name}) { … … 143 146 my($tag, $attrs) = @$odata; 144 147 if($selected) { 145 $attrs |= [[ selected=> 'selected']];148 $attrs |= [[QName('selected') => 'selected']]; 146 149 } 147 150 else { … … 163 166 $in_textarea = 0; 164 167 } 165 return iter([@buf, [$kind, $data ], $pos]);168 return iter([@buf, [$kind, $data, $pos]]); 166 169 } 167 170 else { -
Nenshi/trunk/lib/Nenshi/Input.pm
r71 r72 14 14 use base qw(Exporter); 15 15 16 our @EXPORT = qw(XML HTML XMLParser );16 our @EXPORT = qw(XML HTML XMLParser HTMLParser); 17 17 18 18 sub XMLParser { Nenshi::XMLParser->new(@_); } 19 sub HTMLParser { Nenshi::HTMLParser->new(@_); } 19 20 sub XML { Stream(list(XMLParser(IO::String->new($_[0])))); } 20 21 sub HTML { Stream(list(HTMLParser(IO::String->new(@_)))); } … … 165 166 $parser->parse_done; 166 167 undef $parser; 167 $self->{source}->close;168 168 delete $self->{parser}; 169 169 delete $self->{source}; … … 195 195 } 196 196 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 } 197 341 1; 342 198 343 __END__ 199 sub _coalesce { 344 345 sub _coalesce { 200 346 my($stream) = @_; 201 347 my @textbuf; … … 232 378 1; 233 379 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
