2 use warnings FATAL => 'all';
7 use HTML::Zoom::Parser::BuiltIn;
8 use HTML::Zoom::Producer::BuiltIn;
9 use HTML::Zoom::SelectorParser;
10 use HTML::Zoom::FilterBuilder;
11 use HTML::Zoom::FilterStream;
16 <span class="hilight name">Bob</span>
17 <span class="career">Builder</span>
23 sub src_stream { HTML::Zoom::Parser::BuiltIn->html_to_stream($tmpl); }
25 sub html_sink { HTML::Zoom::Producer::BuiltIn->html_from_stream($_[0]) }
27 my $fb = HTML::Zoom::FilterBuilder->new;
29 my $sp = HTML::Zoom::SelectorParser->new;
32 my ($stream, $sel, $cb) = @_;
33 return HTML::Zoom::FilterStream->new({
35 match => $sp->parse_selector($sel),
36 filter => do { local $_ = $fb; $cb->($fb) }
53 ($expect = $tmpl) =~ s/class="main"/class="foo"/;
56 run_for { $_->set_attribute({ name => 'class', value => 'foo' }) },
58 'set attribute on existing attribute'
61 ($expect = $tmpl) =~ s/class="main"/class="main" foo="bar"/;
64 run_for { $_->set_attribute({ name => 'foo', value => 'bar' }) },
66 'set attribute on non existing attribute'
69 ($expect = $tmpl) =~ s/class="main"/class="main foo"/;
72 run_for { $_->add_attribute({ name => 'class', value => 'foo' }) },
74 'add attribute on existing attribute'
77 ($expect = $tmpl) =~ s/class="main"/class="main" foo="bar"/;
80 run_for { $_->add_attribute({ name => 'foo', value => 'bar' }) },
82 'add attribute on non existing attribute'
85 ($expect = $tmpl) =~ s/ class="main"//;
88 run_for { $_->remove_attribute({ name => 'class' }) },
90 'remove attribute on existing attribute'
94 run_for { $_->remove_attribute({ name => 'foo' }) },
96 'remove attribute on non existing attribute'
99 ($expect = $tmpl) =~ s/(?=<div)/O HAI/;
101 my $ohai = [ { type => 'TEXT', raw => 'O HAI' } ];
104 run_for { $_->add_before($ohai) },
109 ($expect = $tmpl) =~ s/(?<=<\/div>)/O HAI/;
112 run_for { $_->add_after($ohai) },
117 ($expect = $tmpl) =~ s/(?<=class="main">)/O HAI/;
120 run_for { $_->prepend_inside($ohai) },
125 ($expect = $tmpl) =~ s/<hr \/>/<hr>O HAI<\/hr>/;
128 (run_for { $_->prepend_inside($ohai) } 'hr'),
130 'prepend_inside ok with in place close'
134 run_for { $_->replace($ohai) },
145 run_for { $_->collect({ into => \@ev }) },
150 'collect removes without passthrough'
154 HTML::Zoom::Producer::BuiltIn->html_from_events(\@ev),
156 <span class="hilight name">Bob</span>
157 <span class="career">Builder</span>
160 'collect collected right events'
166 run_for { $_->collect({ into => \@ev, inside => 1 }) },
168 <div class="main"></div>
171 'collect w/inside removes correctly'
175 HTML::Zoom::Producer::BuiltIn->html_from_events(\@ev),
177 <span class="hilight name">Bob</span>
178 <span class="career">Builder</span>
181 'collect w/inside collects correctly'
185 run_for { $_->replace($ohai, { inside => 1 }) },
187 <div class="main">O HAI</div>
193 ($expect = $tmpl) =~ s/(?=<\/div>)/O HAI/;
196 run_for { $_->append_inside($ohai) },
205 my $r_inside = sub { my $r = shift; sub { $_->replace($r, { inside => 1 }) } };
213 filter($_ => '.name' => $r_inside->('mst'))
214 => '.career' => $r_inside->('Chainsaw Wielder')
218 filter($_ => '.name' => $r_inside->('mdk'))
219 => '.career' => $r_inside->('Adminion')
226 <span class="hilight name">mst</span>
227 <span class="career">Chainsaw Wielder</span>
229 </div><div class="main">
230 <span class="hilight name">mdk</span>
231 <span class="career">Adminion</span>