package HTML::Zoom;
-use strict;
-use warnings FATAL => 'all';
+use strictures 1;
use HTML::Zoom::ZConfig;
-use HTML::Zoom::MatchWithoutFilter;
use HTML::Zoom::ReadFH;
use HTML::Zoom::Transform;
+use HTML::Zoom::TransformBuilder;
+use Scalar::Util ();
+
+our $VERSION = '0.009007';
+
+$VERSION = eval $VERSION;
sub new {
my ($class, $args) = @_;
bless({ %{$_[0]}, %{$_[1]} }, ref($_[0]));
}
-sub from_html {
+sub from_events {
my $self = shift->_self_or_new;
$self->_with({
- initial_events => $self->zconfig->parser->html_to_events($_[0])
+ initial_events => shift,
});
}
+sub from_html {
+ my $self = shift->_self_or_new;
+ $self->from_events($self->zconfig->parser->html_to_events($_[0]))
+}
+
sub from_file {
my $self = shift->_self_or_new;
my $filename = shift;
unless $self->{initial_events};
my $sutils = $self->zconfig->stream_utils;
my $stream = $sutils->stream_from_array(@{$self->{initial_events}});
- foreach my $filter_spec (@{$self->{filters}||[]}) {
- $stream = HTML::Zoom::Transform->new({
- selector => $filter_spec->[0],
- filters => [ $filter_spec->[1] ],
- zconfig => $self->zconfig,
- })->apply_to_stream($stream);
- #$stream = $sutils->wrap_with_filter($stream, @{$filter_spec});
- }
+ $stream = $_->apply_to_stream($stream) for @{$self->{transforms}||[]};
$stream
}
HTML::Zoom::ReadFH->from_zoom(shift);
}
+sub to_events {
+ my $self = shift;
+ [ $self->zconfig->stream_utils->stream_to_array($self->to_stream) ];
+}
+
sub run {
my $self = shift;
- $self->zconfig->stream_utils->stream_to_array($self->to_stream);
+ $self->to_events;
return
}
$self->$code;
}
+sub apply_if {
+ my ($self, $predicate, $code) = @_;
+ if($predicate) {
+ local $_ = $self;
+ $self->$code;
+ }
+ else {
+ $self;
+ }
+}
+
sub to_html {
my $self = shift;
$self->zconfig->producer->html_from_stream($self->to_stream);
ref($self)->new($self)->from_html($self->to_html);
}
-sub with_filter {
+sub with_transform {
my $self = shift->_self_or_new;
- my ($selector, $filter) = @_;
- my $match = $self->parse_selector($selector);
+ my ($transform) = @_;
$self->_with({
- filters => [ @{$self->{filters}||[]}, [ $match, $filter ] ]
+ transforms => [
+ @{$self->{transforms}||[]},
+ $transform
+ ]
});
}
+
+sub with_filter {
+ my $self = shift->_self_or_new;
+ my ($selector, $filter) = @_;
+ $self->with_transform(
+ HTML::Zoom::Transform->new({
+ zconfig => $self->zconfig,
+ selector => $selector,
+ filters => [ $filter ]
+ })
+ );
+}
sub select {
my $self = shift->_self_or_new;
my ($selector) = @_;
- my $match = $self->parse_selector($selector);
- return HTML::Zoom::MatchWithoutFilter->construct(
- $self, $match, $self->zconfig->filter_builder,
- );
+ return HTML::Zoom::TransformBuilder->new({
+ zconfig => $self->zconfig,
+ selector => $selector,
+ proto => $self
+ });
}
# There's a bug waiting to happen here: if you do something like
sub then {
my $self = shift;
- die "Can't call ->then without a previous filter"
- unless $self->{filters};
- $self->select($self->{filters}->[-1][0]);
+ die "Can't call ->then without a previous transform"
+ unless $self->{transforms};
+ $self->select($self->{transforms}->[-1]->selector);
}
-sub parse_selector {
- my ($self, $selector) = @_;
- return $selector if ref($selector); # already a match sub
- $self->zconfig->selector_parser->parse_selector($selector);
+sub AUTOLOAD {
+ my ($self, $selector, @args) = @_;
+ my $sel = $self->select($selector);
+ my $meth = our $AUTOLOAD;
+ $meth =~ s/.*:://;
+ if(my $cr = $sel->_zconfig->filter_builder->can($meth)) {
+ return $sel->$meth(@args);
+ } else {
+ die "We can't do $meth on ->select('$selector')";
+ }
}
+sub DESTROY {}
+
1;
=head1 NAME
map { my $field = $_; sub {
$_->select('label')
- ->add_attribute( for => $field->{id} )
+ ->add_to_attribute( for => $field->{id} )
->then
->replace_content( $field->{label} )
->select('input')
- ->add_attribute( name => $field->{name} )
+ ->add_to_attribute( name => $field->{name} )
->then
- ->add_attribute( type => $field->{type} )
+ ->add_to_attribute( type => $field->{type} )
->then
- ->add_attribute( value => $field->{value} )
+ ->add_to_attribute( value => $field->{value} )
} } @fields
]);
Convenience method - slurps the contents of $file and calls from_html with it.
+=head2 from_events
+
+ my $zoom = HTML::Zoom->from_events($evt);
+
+Create a new Zoom object from collected events
+
=head2 to_stream
my $stream = $zoom->to_stream;
my $z2 = $sub->($z1);
+=head2 apply_if
+
+ my $z2 = $z1->apply_if($cond, sub {
+ $_->select('div')->replace_content('I AM A DIV!') })
+ });
+
+->apply but will only run the tranform if $cond is true
+
=head2 to_html
my $html = $zoom->to_html;
my $z2 = $z1->select('div')->replace_content('I AM A DIV!');
-Returns an intermediary object of the class L<HTML::Zoom::MatchWithoutFilter>
+Returns an intermediary object of the class L<HTML::Zoom::TransformBuilder>
on which methods of your L<HTML::Zoom::FilterBuilder> object can be called.
In normal usage you should generally always put the pair of method calls
=head2 then
- my $z2 = $z1->select('div')->add_attribute(class => 'spoon')
+ my $z2 = $z1->select('div')->add_to_attribute(class => 'spoon')
->then
->replace_content('I AM A DIV!');
Re-runs the previous select to allow you to chain actions together on the
same selector.
-=head2 parse_selector
+=head1 AUTOLOAD METHODS
- my $matcher = $zoom->parse_selector('div');
+L<HTML::Zoom> AUTOLOADS methods against L</select> so that you can reduce a
+certain amount of boilerplate typing. This allows you to replace:
-Used by L</select> and L</with_filter> to invoke the current
-L<HTML::Zoom::SelectorParser> object to create a matcher object (currently
-a coderef but this is an implementation detail) for that selector.
+ $z->select('div')->replace_content("Hello World");
+
+With:
-In normal usage, you probably don't need to call this yourself.
+ $z->replace_content(div => "Hello World");
+
+Besides saving a few keys per invocations, you may feel this looks neater
+in your code and increases understanding.
+
+=head1 AUTHOR
+
+mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>
+
+=head1 CONTRIBUTORS
+
+Oliver Charles
+
+Jakub Nareski
+
+Simon Elliott
+
+Joe Highton
+
+John Napiorkowski
+
+Robert Buels
+
+David Dorward
+
+=head1 COPYRIGHT
+
+Copyright (c) 2010-2011 the HTML::Zoom L</AUTHOR> and L</CONTRIBUTORS>
+as listed above.
+
+=head1 LICENSE
+
+This library is free software, you can redistribute it and/or modify
+it under the same terms as Perl itself.
=cut
+