File Coverage

blib/lib/HTML/String/Value.pm
Criterion Covered Total %
statement 55 67 82.0
branch 14 22 63.6
condition 3 9 33.3
subroutine 13 17 76.4
pod 4 4 100.0
total 89 119 74.7


line stmt bran cond sub pod time code
1             package HTML::String::Value;
2              
3 1     1   4 use strictures 1;
  1         5  
  1         19  
4 1     1   952 use UNIVERSAL::ref;
  1         119775  
  1         11  
5 1     1   1114 use Safe::Isa;
  1         553  
  1         150  
6 1     1   5 use Scalar::Util qw(blessed);
  1         2  
  1         36  
7 1     1   893 use Data::Munge;
  1         1451  
  1         97  
8              
9             use overload
10 1         8 '""' => '_hsv_escaped_string',
11             '.' => '_hsv_dot',
12             'bool' => '_hsv_is_true',
13              
14             fallback => 1,
15 1     1   1660 ;
  1         1099  
16              
17             sub new {
18 16 100   16 1 53 if (blessed($_[0])) {
19 1         3 my $c = shift;
20 1         3 return $c->_hsv_unescaped_string->new(@_);
21             }
22 15         28 my ($class, @raw_parts) = @_;
23              
24 15 100       40 my $opts = (ref($raw_parts[-1]) eq 'HASH') ? pop(@raw_parts) : {};
25              
26             my @parts = map {
27 15 50       22 if (ref($_) eq 'ARRAY') {
  15 50       51  
28 0         0 $_
29             } elsif ($_->$_isa(__PACKAGE__)) {
30 0         0 @{$_->{parts}}
  0         0  
31             } else {
32 15         133 [ $_, 0 ]
33             }
34             } @raw_parts;
35              
36 15         50 my $self = bless { parts => \@parts, %$opts }, $class;
37              
38 15         188 return $self;
39             }
40              
41             sub AUTOLOAD {
42 1     1   3 my $invocant = shift;
43 1         4 (my $meth = our $AUTOLOAD) =~ s/.*:://;
44 1 50       9 die "No such method ${meth} on ${invocant}"
45             unless ref($invocant);
46 1         16 return $invocant->_hsv_unescaped_string->$meth(@_);
47             }
48              
49             sub _hsv_escaped_string {
50 14     14   197 my $self = shift;
51              
52 14 50       44 if ($self->{ignore}{scalar caller}) {
53 0         0 return $self->_hsv_unescaped_string;
54             }
55              
56             return join '', map +(
57             $_->[1]
58             ? byval {
59 8     8   51 s/&/&/g;
60 8         21 s/
61 8         16 s/>/>/g;
62 8         12 s/"/"/g;
63 8         14 s/'/'/g;
64 14         115 } $_->[0]
65             : $_->[0]
66 14 100       16 ), @{$self->{parts}};
67             }
68              
69             sub _hsv_unescaped_string {
70 8     8   12 my $self = shift;
71              
72 8         10 return join '', map $_->[0], @{$self->{parts}};
  8         104  
73             }
74              
75             sub _hsv_dot {
76 12     12   23 my ($self, $str, $prefix) = @_;
77              
78 12 50 33     46 return $self unless defined $str && length $str;
79              
80 12         15 my @parts = @{$self->{parts}};
  12         26  
81              
82 6         20 my @new_parts = (
83             $str->$_isa(__PACKAGE__)
84 12 100       26 ? @{$str->{parts}}
85             : [ $str, 1 ]
86             );
87              
88 12 50       62 if ( $prefix ) {
89 0         0 unshift @parts, @new_parts;
90             } else {
91 12         14 push @parts, @new_parts;
92             }
93              
94 12         91 return bless({ %$self, parts => \@parts }, blessed($self));
95             }
96              
97             sub _hsv_is_true {
98 0     0   0 my ($self) = @_;
99 0 0       0 return 1 if grep $_, map $_->[0], @{$self->{parts}};
  0         0  
100             }
101              
102             # we need to local $@ here because some modules (cough, TT, cough)
103             # will do a 'die $@ if $@' without realising that it wasn't their eval
104             # that set it
105              
106             sub isa {
107 8     8 1 402 my $self = shift;
108             return (
109 8   66     9 do {
110             local $@;
111             eval { blessed($self) and $self->_hsv_unescaped_string->isa(@_) }
112             }
113             or $self->SUPER::isa(@_)
114             );
115             }
116              
117             sub can {
118 0     0 1   my $self = shift;
119             return (
120 0   0       do {
121             local $@;
122             eval { blessed($self) and $self->_hsv_unescaped_string->can(@_) }
123             }
124             or $self->SUPER::can(@_)
125             );
126             }
127              
128 0     0 1   sub ref { '' }
129              
130 0     0     sub DESTROY { }
131              
132             1;
133              
134             __END__