4 use warnings FATAL => 'all';
6 use HTML::Zoom::ZConfig;
7 use HTML::Zoom::MatchWithoutFilter;
10 my ($class, $args) = @_;
12 $new->{zconfig} = HTML::Zoom::ZConfig->new($args->{zconfig}||{});
16 sub zconfig { shift->_self_or_new->{zconfig} }
19 ref($_[0]) ? $_[0] : $_[0]->new
23 bless({ %{$_[0]}, %{$_[1]} }, ref($_[0]));
27 my $self = shift->_self_or_new;
29 initial_events => $self->zconfig->parser->html_to_events($_[0])
35 die "No events to build from - forgot to call from_html?"
36 unless $self->{initial_events};
37 my $sutils = $self->zconfig->stream_utils;
38 my $stream = $sutils->stream_from_array(@{$self->{initial_events}});
39 foreach my $filter_spec (@{$self->{filters}||[]}) {
40 $stream = $sutils->wrap_with_filter($stream, @{$filter_spec});
47 $self->zconfig->producer->html_from_stream($self->to_stream);
52 ref($self)->new($self)->from_html($self->to_html);
56 my ($self, $selector, $filter) = @_;
57 my $match = $self->parse_selector($selector);
59 filters => [ @{$self->{filters}||[]}, [ $match, $filter ] ]
64 my ($self, $selector) = @_;
65 my $match = $self->parse_selector($selector);
66 return HTML::Zoom::MatchWithoutFilter->construct(
67 $self, $match, $self->zconfig->filter_builder,
71 # There's a bug waiting to happen here: if you do something like
73 # $zoom->select('.foo')
74 # ->remove_attribute({ class => 'foo' })
76 # ->well_anything_really
78 # the second action won't execute because it doesn't match anymore.
79 # Ideally instead we'd merge the match subs but that's more complex to
80 # implement so I'm deferring it for the moment.
84 die "Can't call ->then without a previous filter"
85 unless $self->{filters};
86 $self->select($self->{filters}->[-1][0]);
90 my ($self, $selector) = @_;
91 return $selector if ref($selector); # already a match sub
92 $self->zconfig->selector_parser->parse_selector($selector);
99 HTML::Zoom - selector based streaming template engine
105 my $template = <<HTML;
108 <title>Hello people</title>
111 <h1 id="greeting">Placeholder</h1>
114 <p>Name: <span class="name">Bob</span></p>
115 <p>Age: <span class="age">23</span></p>
117 <hr class="between" />
123 my $output = HTML::Zoom
124 ->from_html($template)
125 ->select('title, #greeting')->replace_content('Hello world & dog!')
126 ->select('#list')->repeat_content(
129 $_->select('.name')->replace_content('Matt')
130 ->select('.age')->replace_content('26')
133 $_->select('.name')->replace_content('Mark')
134 ->select('.age')->replace_content('0x29')
137 $_->select('.name')->replace_content('Epitaph')
138 ->select('.age')->replace_content('<redacted>')
141 { repeat_between => '.between' }
155 <title>Hello world & dog!</title>
158 <h1 id="greeting">Hello world & dog!</h1>
161 <p>Name: <span class="name">Matt</span></p>
162 <p>Age: <span class="age">26</span></p>
164 <hr class="between" />
166 <p>Name: <span class="name">Mark</span></p>
167 <p>Age: <span class="age">0x29</span></p>
169 <hr class="between" />
171 <p>Name: <span class="name">Epitaph</span></p>
172 <p>Age: <span class="age"><redacted></span></p>
182 is($output, $expect, 'Synopsis code works ok');
186 =head1 SOMETHING ELSE