2 use warnings FATAL => 'all';
5 use HTML::Zoom::Parser::BuiltIn;
6 use HTML::Zoom::Producer::BuiltIn;
7 use HTML::Zoom::SelectorParser;
8 use HTML::Zoom::FilterBuilder;
9 use HTML::Zoom::FilterStream;
14 <span class="hilight name">Bob</span>
15 <span class="career">Builder</span>
21 sub src_stream { HTML::Zoom::Parser::BuiltIn->new->html_to_stream($tmpl); }
23 sub html_sink { HTML::Zoom::Producer::BuiltIn->new->html_from_stream($_[0]) }
25 my $fb = HTML::Zoom::FilterBuilder->new;
27 my $sp = HTML::Zoom::SelectorParser->new;
30 my ($stream, $sel, $cb) = @_;
31 return HTML::Zoom::FilterStream->new({
33 match => $sp->parse_selector($sel),
34 filter => do { local $_ = $fb; $cb->($fb) }
51 ($expect = $tmpl) =~ s/class="main"/class="foo"/;
54 run_for { $_->set_attribute({ name => 'class', value => 'foo' }) },
56 'set attribute on existing attribute'
59 ($expect = $tmpl) =~ s/class="main"/class="main" foo="bar"/;
62 run_for { $_->set_attribute({ name => 'foo', value => 'bar' }) },
64 'set attribute on non existing attribute'
67 ($expect = $tmpl) =~ s/class="main"/class="main foo"/;
70 run_for { $_->add_to_attribute({ name => 'class', value => 'foo' }) },
72 'add attribute on existing attribute'
75 ($expect = $tmpl) =~ s/class="main"/class="main" foo="bar"/;
78 run_for { $_->add_to_attribute({ name => 'foo', value => 'bar' }) },
80 'add attribute on non existing attribute'
83 ($expect = $tmpl) =~ s/ class="main"//;
86 run_for { $_->remove_attribute({ name => 'class' }) },
88 'remove attribute on existing attribute'
92 run_for { $_->remove_attribute({ name => 'foo' }) },
94 'remove attribute on non existing attribute'
97 ($expect = $tmpl) =~ s/(?=<div)/O HAI/;
99 my $ohai = [ { type => 'TEXT', raw => 'O HAI' } ];
102 run_for { $_->add_before($ohai) },
107 ($expect = $tmpl) =~ s/(?<=<\/div>)/O HAI/;
110 run_for { $_->add_after($ohai) },
115 ($expect = $tmpl) =~ s/(?<=class="main">)/O HAI/;
118 run_for { $_->prepend_content($ohai) },
123 ($expect = $tmpl) =~ s/<hr \/>/<hr>O HAI<\/hr>/;
126 (run_for { $_->prepend_content($ohai) } 'hr'),
128 'prepend_content ok with in place close'
132 run_for { $_->replace($ohai) },
143 run_for { $_->collect({ into => \@ev }) },
148 'collect removes without passthrough'
152 HTML::Zoom::Producer::BuiltIn->html_from_events(\@ev),
154 <span class="hilight name">Bob</span>
155 <span class="career">Builder</span>
158 'collect collected right events'
164 run_for { $_->collect({ into => \@ev, content => 1 }) },
166 <div class="main"></div>
169 'collect w/content removes correctly'
173 HTML::Zoom::Producer::BuiltIn->html_from_events(\@ev),
175 <span class="hilight name">Bob</span>
176 <span class="career">Builder</span>
179 'collect w/content collects correctly'
183 run_for { $_->replace($ohai, { content => 1 }) },
185 <div class="main">O HAI</div>
191 ($expect = $tmpl) =~ s/(?=<\/div>)/O HAI/;
194 run_for { $_->append_content($ohai) },
199 my $r_content = sub { my $r = shift; sub { $_->replace($r, { content => 1 }) } };
207 filter($_ => '.name' => $r_content->('mst'))
208 => '.career' => $r_content->('Chainsaw Wielder')
212 filter($_ => '.name' => $r_content->('mdk'))
213 => '.career' => $r_content->('Adminion')
220 <span class="hilight name">mst</span>
221 <span class="career">Chainsaw Wielder</span>
223 </div><div class="main">
224 <span class="hilight name">mdk</span>
225 <span class="career">Adminion</span>
239 filter($_ => '.name' => $r_content->('mst'))
240 => '.career' => $r_content->('Chainsaw Wielder')
244 filter($_ => '.name' => $r_content->('mdk'))
245 => '.career' => $r_content->('Adminion')
252 <span class="hilight name">mst</span>
253 <span class="career">Chainsaw Wielder</span>
256 <span class="hilight name">mdk</span>
257 <span class="career">Adminion</span>
271 HTML::Zoom::ArrayStream->new({ array => [
273 filter($_ => '.name' => $r_content->('mst'))
274 => '.career' => $r_content->('Chainsaw Wielder')),
275 HTML::Zoom::ArrayStream->new({ array => \@between })
280 filter($_ => '.name' => $r_content->('mdk'))
281 => '.career' => $r_content->('Adminion')
285 filter $_[0] => 'hr' => sub { $_->collect({ into => \@between }) }
292 <span class="hilight name">mst</span>
293 <span class="career">Chainsaw Wielder</span>
295 <span class="hilight name">mdk</span>
296 <span class="career">Adminion</span>
301 'repeat_content with filter ok'
311 filter($_ => '.name' => $r_content->('mst'))
312 => '.career' => $r_content->('Chainsaw Wielder')
316 filter($_ => '.name' => $r_content->('mdk'))
317 => '.career' => $r_content->('Adminion')
320 { repeat_between => 'hr' }
325 <span class="hilight name">mst</span>
326 <span class="career">Chainsaw Wielder</span>
328 <span class="hilight name">mdk</span>
329 <span class="career">Adminion</span>
334 'repeat_content using repeat_between ok'