File Coverage

lib/HTML/TokeParser/Simple/Token/Tag/Start.pm
Criterion Covered Total %
statement 84 85 98.8
branch 17 18 94.4
condition 2 2 100.0
subroutine 26 27 96.3
pod 14 14 100.0
total 143 146 97.9


line stmt bran cond sub pod time code
1             package HTML::TokeParser::Simple::Token::Tag::Start;
2              
3 5     5   52 use strict;
  5         9  
  5         252  
4              
5             our $VERSION = '3.16';
6 5     5   62 use base 'HTML::TokeParser::Simple::Token::Tag';
  5         8  
  5         386  
7              
8 5     5   24 use HTML::Entities qw/encode_entities/;
  5         8  
  5         6448  
9              
10             my %TOKEN = (
11             tag => 1,
12             attr => 2,
13             attrseq => 3,
14             text => 4
15             );
16              
17             my %INSTANCE;
18              
19             sub _init {
20 66     66   99 my $self = shift;
21 66 100       176 if ('S' eq $self->[0]) {
22 56         187 $INSTANCE{$self}{offset} = 0;
23 56         189 $INSTANCE{$self}{tag} = $self->[1];
24             }
25             else {
26 10         27 $INSTANCE{$self}{offset} = -1;
27 10         18 my $tag = $self->[0];
28 10         23 $tag =~ s/^\///;
29 10         28 $INSTANCE{$self}{tag} = $tag;
30             }
31 66         281 return $self;
32             }
33              
34 87     87   321 sub _get_offset { return $INSTANCE{+shift}{offset} }
35 55     55   1463 sub _get_text { return shift->[-1] }
36              
37             sub _get_tag {
38 41     41   296 my $self = shift;
39 41         388 return $INSTANCE{$self}{tag};
40             }
41              
42             sub _get_attrseq {
43 38     38   41 my $self = shift;
44 38         76 my $index = $TOKEN{attrseq} + $self->_get_offset;
45 38         91 return $self->[$index];
46             }
47              
48             sub _get_attr {
49 49     49   59 my $self = shift;
50 49         122 my $index = $TOKEN{attr} + $self->_get_offset;
51 49         139 return $self->[$index];
52             }
53              
54 46     46   5696 sub DESTROY { delete $INSTANCE{+shift} }
55              
56 4     4 1 1290 sub return_attr { goto &get_attr }
57 2     2 1 4335 sub return_attrseq { goto &get_attrseq }
58 2     2 1 12 sub return_tag { goto &get_tag }
59              
60             # attribute munging methods
61              
62             sub set_attr {
63 8     8 1 24 my ($self, $name, $value) = @_;
64 8 100       35 return 'HASH' eq ref $name
65             ? $self->_set_attr_from_hashref($name)
66             : $self->_set_attr_from_string($name, $value);
67             }
68              
69             sub _set_attr_from_string {
70 7     7   16 my ($self, $name, $value) = @_;
71 7         11 $name = lc $name;
72 7         29 my $attr = $self->get_attr;
73 7         21 my $attrseq = $self->get_attrseq;
74 7 100       27 unless (exists $attr->{$name}) {
75 2         6 push @$attrseq => $name;
76             }
77 7         14 $attr->{$name} = $value;
78 7         17 $self->rewrite_tag;
79             }
80              
81             sub _set_attr_from_hashref {
82 1     1   5 my ($self, $attr_hash) = @_;
83 1         6 while (my ($attr, $value) = each %$attr_hash) {
84 2         7 $self->set_attr($attr, $value);
85             }
86 1         3 return $self;
87             }
88              
89             sub rewrite_tag {
90 19     19 1 48 my $self = shift;
91 19         39 my $attr = $self->get_attr;
92 19         39 my $attrseq = $self->get_attrseq;
93              
94             # capture the final slash if the tag is self-closing
95 19         39 my ($self_closing) = $self->_get_text =~ m{(\s?/)>$};
96 19   100     73 $self_closing ||= '';
97            
98 19         23 my $tag = '';
99 19         35 foreach ( @$attrseq ) {
100 30 100       282 next if $_ eq '/'; # is this a bug in HTML::TokeParser?
101 24         111 $tag .= sprintf qq{ %s="%s"} => $_, encode_entities($attr->{$_});
102             }
103 19 50       179 my $first = $self->is_end_tag ? '/' : '';
104 19         46 $tag = sprintf '<%s%s%s%s>', $first, $self->get_tag, $tag, $self_closing;
105 19         69 $self->_set_text($tag);
106 19         52 return $self;
107             }
108              
109             sub delete_attr {
110 5     5 1 13 my ($self,$name) = @_;
111 5         9 $name = lc $name;
112 5         12 my $attr = $self->get_attr;
113 5 100       17 return unless exists $attr->{$name};
114 4         10 delete $attr->{$name};
115 4         10 my $attrseq = $self->get_attrseq;
116 4         10 @$attrseq = grep { $_ ne $name } @$attrseq;
  10         30  
117 4         12 $self->rewrite_tag;
118             }
119              
120             # get_foo methods
121              
122             sub return_text {
123 1     1 1 8 require Carp;
124 1         201 Carp::carp('return_text() is deprecated. Use as_is() instead');
125 1         34 goto &as_is;
126             }
127              
128             sub as_is {
129 34     34 1 1032 return shift->_get_text;
130             }
131              
132             sub get_tag {
133 23     23 1 68 return shift->_get_tag;
134             }
135              
136             sub get_token0 {
137 0     0 1 0 return '';
138             }
139              
140             sub get_attr {
141 46     46 1 1995 my $self = shift;
142 46         84 my $attributes = $self->_get_attr;
143 46 100       167 return @_ ? $attributes->{lc shift} : $attributes;
144             }
145              
146             sub get_attrseq {
147 35     35 1 2049 my $self = shift;
148 35         68 $self->_get_attrseq;
149             }
150              
151             # is_foo methods
152              
153             sub is_tag {
154 5     5 1 11 my $self = shift;
155 5         14 return $self->is_start_tag( @_ );
156             }
157              
158             sub is_start_tag {
159 18     18 1 544 my ($self, $tag) = @_;
160 18 100       67 return $tag ? $self->_match_tag($tag) : 1;
161             }
162              
163             sub _match_tag {
164 15     15   22 my ($self, $tag) = @_;
165 15 100       58 return 'Regexp' eq ref $tag
166             ? $self->_get_tag =~ $tag
167             : $self->_get_tag eq lc $tag;
168             }
169              
170             1;
171              
172             __END__
173              
174             =head1 NAME
175              
176             HTML::TokeParser::Simple::Token::Tag::Start - Token.pm "start tag" class.
177              
178             =head1 SYNOPSIS
179              
180             use HTML::TokeParser::Simple;
181             my $p = HTML::TokeParser::Simple->new( $somefile );
182              
183             while ( my $token = $p->get_token ) {
184             # This prints all text in an HTML doc (i.e., it strips the HTML)
185             next unless $token->is_text;
186             print $token->as_is;
187             }
188              
189             =head1 DESCRIPTION
190              
191             This class does most of the heavy lifting for C<HTML::TokeParser::Simple>. See
192             the C<HTML::TokeParser::Simple> docs for details.
193              
194             =head1 OVERRIDDEN METHODS
195              
196             =over 4
197              
198             =item * as_is
199              
200             =item * delete_attr
201              
202             =item * get_attr
203              
204             =item * get_attrseq
205              
206             =item * get_tag
207              
208             =item * get_token0
209              
210             =item * is_start_tag
211              
212             =item * is_tag
213              
214             =item * return_attr
215              
216             =item * return_attrseq
217              
218             =item * return_tag
219              
220             =item * return_text
221              
222             =item * rewrite_tag
223              
224             =item * set_attr
225              
226             =back
227              
228             =cut
229