From: Robert Buels Date: Sun, 10 Apr 2011 23:30:34 +0000 (-0700) Subject: add transform_attribute, which runs a coderef on the value of an attribute, and can... X-Git-Tag: release_0.009005~5 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FHTML-Zoom.git;a=commitdiff_plain;h=5cac799ef22c33ef914b2cf9ba1c66a2a1b403e1 add transform_attribute, which runs a coderef on the value of an attribute, and can either add or delete the attribute as well --- diff --git a/lib/HTML/Zoom.pm b/lib/HTML/Zoom.pm index 4f1c599..402ca1f 100644 --- a/lib/HTML/Zoom.pm +++ b/lib/HTML/Zoom.pm @@ -733,6 +733,8 @@ Joe Highton John Napiorkowski +Robert Buels + =head1 COPYRIGHT Copyright (c) 2010-2011 the HTML::Zoom L and L diff --git a/lib/HTML/Zoom/FilterBuilder.pm b/lib/HTML/Zoom/FilterBuilder.pm index 92961dc..45b57f2 100644 --- a/lib/HTML/Zoom/FilterBuilder.pm +++ b/lib/HTML/Zoom/FilterBuilder.pm @@ -83,6 +83,38 @@ sub remove_attribute { }; } +sub transform_attribute { + my $self = shift; + my ( $name, $code ) = @_ > 1 ? @_ : @{$_[0]}{qw(name code)}; + + sub { + my $evt = $_[0]; + my %a = %{ $evt->{attrs} }; + my @names = @{ $evt->{attr_names} }; + + my $existed_before = exists $a{$name}; + my $v = $code->( $a{$name} ); + my $deleted = $existed_before && ! defined $v; + my $added = ! $existed_before && defined $v; + if( $added ) { + push @names, $name; + $a{$name} = $v; + } + elsif( $deleted ) { + delete $a{$name}; + @names = grep $_ ne $name, @names; + } else { + $a{$name} = $v; + } + +{ %$evt, raw => undef, raw_attrs => undef, + attrs => \%a, + ( $deleted || $added + ? (attr_names => \@names ) + : () ) + } + }; +} + sub collect { my ($self, $options) = @_; my ($into, $passthrough, $content, $filter, $flush_before) = @@ -433,6 +465,20 @@ Removes an attribute and all its values. Removes attributes from the original stream or events already added. +=head2 transform_attribute + +Transforms (or creates or deletes) an attribute by running the passed +coderef on it. If the coderef returns nothing, the attribute is +removed. + + $html_zoom + ->select('a') + ->transform_attribute( href => sub { + ( my $a = shift ) =~ s/localhost/example.com/; + return $a; + }, + ); + =head2 collect Collects and extracts results of L. It takes the following diff --git a/t/actions.t b/t/actions.t index c89a5b8..6e1541b 100644 --- a/t/actions.t +++ b/t/actions.t @@ -93,6 +93,64 @@ is( 'remove attribute on non existing attribute' ); +($expect = $tmpl) =~ s/ class="main"//; + +is( + run_for { + $_->transform_attribute({ + name => 'class', + code => sub { + my $a = shift; + return if $a eq 'main'; + return $a; + }, + }) + }, + $expect, + 'transform_attribute deletes the attr if code returns undef', + ); + +($expect = $tmpl) =~ s/ class="main"/ class="moan"/; + +is( + run_for { + $_->transform_attribute({ + name => 'class', + code => sub { + ( my $b = shift ) =~ s/main/moan/; + $b + }, + }) + }, + $expect, + 'transform_attribute transforms something', + ); + +($expect = $tmpl) =~ s/ class="main"/ class="main" noggin="zonk"/; + +is( + run_for { + $_->transform_attribute({ + name => 'noggin', + code => sub { 'zonk' }, + }) + }, + $expect, + 'transform_attribute adds attribute if not there before', + ); + +is( + run_for { + $_->transform_attribute({ + name => 'noggin', + code => sub { }, + }) + }, + $tmpl, + 'transform_attribute on nonexistent att does not add it if code returns undef', + ); + + ($expect = $tmpl) =~ s/(?= 'TEXT', raw => 'O HAI' } ];