refactor slightly and clean up selector code a bit
Matt S Trout [Sat, 20 Feb 2010 22:34:05 +0000 (22:34 +0000)]
lib/HTML/Zoom/FilterBuilder.pm
lib/HTML/Zoom/SelectorParser.pm
lib/HTML/Zoom/StreamUtils.pm

index bdfb920..316d56c 100644 (file)
@@ -21,6 +21,10 @@ sub _stream_concat {
   shift->_zconfig->stream_utils->stream_concat(@_)
 }
 
+sub _flatten_stream_of_streams {
+  shift->_zconfig->stream_utils->flatten_stream_of_streams(@_)
+}
+
 sub set_attribute {
   my ($self, $args) = @_;
   my ($name, $value) = @{$args}{qw(name value)};
@@ -211,23 +215,23 @@ sub repeat {
     # hasn't been populated yet - but we can test @between in the
     # map routine because it has been by then and that saves us doing
     # the extra stream construction if we don't need it.
-    if ($repeat_between) {
-      $s->map(sub {
-            local $_ = $self->_stream_from_array(@into);
-            (@between && $s->peek)
-              ? $self->_stream_concat(
-                  $_[0]->($_), $self->_stream_from_array(@between)
-                )
-              : $_[0]->($_)
-          })
-        ->flatten;
-    } else {
-      $s->map(sub {
-            local $_ = $self->_stream_from_array(@into);
-            $_[0]->($_)
+    $self->_flatten_stream_of_streams(do {
+      if ($repeat_between) {
+        $s->map(sub {
+              local $_ = $self->_stream_from_array(@into);
+              (@between && $s->peek)
+                ? $self->_stream_concat(
+                    $_[0]->($_), $self->_stream_from_array(@between)
+                  )
+                : $_[0]->($_)
+            })
+      } else {
+        $s->map(sub {
+              local $_ = $self->_stream_from_array(@into);
+              $_[0]->($_)
           })
-        ->flatten;
-    }
+      }
+    })
   };
   $self->replace($repeater, $options);
 }
index 7d3c6a5..ed1d586 100644 (file)
@@ -2,6 +2,7 @@ package HTML::Zoom::SelectorParser;
 
 use strict;
 use warnings FATAL => 'all';
+use base qw(HTML::Zoom::SubObject);
 use Carp qw(confess);
 
 my $sel_char = '-\w_';
@@ -41,7 +42,7 @@ sub _raw_parse_simple_selector {
         my @cl = split(/\./, $cls);
         sub {
           $_[0]->{attrs}{class}
-          && !grep $_[0]->{attrs}{class} !~ /\b$_\b/, @cl
+          && !grep $_[0]->{attrs}{class} !~ /(^|\s+)$_($|\s+)/, @cl
         }
       };
 
index cdfa430..16a029f 100644 (file)
@@ -44,8 +44,9 @@ sub stream_from_proto {
     return $proto->();
   } elsif ($ref eq 'SCALAR') {
     return $self->_zconfig->parser->html_to_stream($$proto);
-  } elsif (blessed($proto) && $proto->can('as_stream')) {
-    return $proto->as_stream;
+  } elsif (Scalar::Util::blessed($proto) && $proto->can('as_stream')) {
+    my $stream = $proto->as_stream;
+    return $self->stream_from_code(sub { $stream->next });
   }
   die "Don't know how to turn $proto (ref $ref) into a stream";
 }
@@ -67,4 +68,21 @@ sub stream_to_array {
   return @array;
 }
 
+sub flatten_stream_of_streams {
+  my ($self, $source_stream) = @_;
+  my $cur_stream;
+  HTML::Zoom::CodeStream->new({
+    code => sub {
+      return unless $source_stream;
+      my $next;
+      until (($next) = ($cur_stream ? $cur_stream->next : ())) {
+        unless (($cur_stream) = $source_stream->next) {
+          undef $source_stream; return;
+        }
+      }
+      return $next;
+    }
+  });
+}
+
 1;