File Coverage

blib/lib/HTML/ResolveLink.pm
Criterion Covered Total %
statement 58 59 98.3
branch 17 20 85.0
condition 4 5 80.0
subroutine 11 11 100.0
pod 3 3 100.0
total 93 98 94.9


line stmt bran cond sub pod time code
1             package HTML::ResolveLink;
2              
3 2     2   49507 use strict;
  2         5  
  2         99  
4             our $VERSION = '0.05';
5 2     2   9 use base qw(HTML::Parser);
  2         4  
  2         2256  
6              
7 2     2   13188 use Carp;
  2         9  
  2         173  
8 2     2   1752 use HTML::Tagset ();
  2         2970  
  2         59  
9 2     2   2293 use URI;
  2         17636  
  2         1370  
10              
11             sub new {
12 2     2 1 27 my($class, %p) = @_;
13 2         27 my $self = $class->SUPER::new(
14             start_h => [ \&_start_tag, "self,tagname,attr,attrseq,text" ],
15             default_h => [ \&_default, "self,tagname,attr,text" ],
16             );
17              
18 2 50       179 unless ($p{base}) {
19 0         0 Carp::croak("HTML::ResolveLink->new: base is a required parameter");
20             }
21              
22 2 50       21 $p{base} = URI->new($p{base}) unless ref $p{base};
23 2         9518 $self->{resolvelink_base} = $p{base};
24 2 100       17 $self->{resolvelink_callback} = $p{callback} if $p{callback};
25              
26 2         10 $self;
27             }
28              
29             sub _start_tag {
30 11     11   25 my($self, $tagname, $attr, $attrseq, $text) = @_;
31              
32 11 100 66     37 if ($tagname eq 'base' && defined $attr->{href}) {
33 2         6 $self->{resolvelink_base} = $attr->{href};
34             }
35              
36 11         21 my $base = $self->{resolvelink_base};
37              
38 11   100     37 my $links = $HTML::Tagset::linkElements{$tagname} || [];
39 11 50       28 $links = [$links] unless ref $links;
40              
41 11         21 for my $a (@$links) {
42 13 100       40 next unless exists $attr->{$a};
43              
44 10         21 my $link = $attr->{$a};
45 10         35 my $uri = URI->new($link);
46              
47             # relative link:
48 10 100       1857 unless (defined $uri->scheme) {
49 6         170 my $old = $uri;
50 6         20 $uri = $uri->abs($base);
51 6         1342 $attr->{$a} = $uri->as_string;
52 6 100       50 if ($self->{resolvelink_callback}) {
53 5         17 $self->{resolvelink_callback}->($uri, $old);
54             }
55 6         87 $self->{resolvelink_count}++;
56             }
57             }
58              
59 11         151 $self->{resolvelink_html} .= "<$tagname";
60 11         21 for my $a (@$attrseq) {
61 14 100       35 next if $a eq '/';
62 12         32 $self->{resolvelink_html} .= sprintf qq( %s="%s"), $a, _escape($attr->{$a});
63             }
64 11 100       30 $self->{resolvelink_html} .= ' /' if $attr->{'/'};
65 11         77 $self->{resolvelink_html} .= '>';
66             }
67              
68             sub _default {
69 32     32   52 my($self, $tagname, $attr, $text) = @_;
70 32         180 $self->{resolvelink_html} .= $text;
71             }
72              
73             my %escape = (
74             '<' => '<',
75             '>' => '>',
76             '"' => '"',
77             '&' => '&',
78             );
79             my $esc_re = join '|', keys %escape;
80              
81             sub _escape {
82 12     12   16 my $str = shift;
83 12         86 $str =~ s/($esc_re)/$escape{$1}/g;
84 12         107 $str;
85             }
86              
87             sub resolve {
88 3     3 1 2594 my($self, $html) = @_;
89              
90             # init
91 3         10 $self->{resolvelink_html} = '';
92 3         7 $self->{resolvelink_count} = 0;
93              
94 3         45 $self->parse($html);
95 3         24 $self->eof;
96              
97 3         25 $self->{resolvelink_html};
98             }
99              
100             sub resolved_count {
101 1     1 1 1191 my $self = shift;
102 1         6 $self->{resolvelink_count};
103             }
104              
105             1;
106             __END__