File Coverage

blib/lib/HTML/Links/Localize.pm
Criterion Covered Total %
statement 17 131 12.9
branch 0 42 0.0
condition 0 13 0.0
subroutine 6 21 28.5
pod 4 4 100.0
total 27 211 12.8


line stmt bran cond sub pod time code
1             package HTML::Links::Localize;
2             $HTML::Links::Localize::VERSION = '0.2.11';
3 1     1   691 use strict;
  1         2  
  1         30  
4 1     1   5 use warnings;
  1         2  
  1         23  
5              
6 1     1   17 use 5.008;
  1         4  
7              
8 1     1   490 use HTML::TokeParser ();
  1         10151  
  1         32  
9 1     1   7 use File::Find qw/ find /;
  1         2  
  1         77  
10 1     1   493 use File::Copy qw/ copy /;
  1         2362  
  1         1456  
11              
12             # Two utility functions
13             sub _is_older
14             {
15 0     0     my $file1 = shift;
16 0           my $file2 = shift;
17 0           my @stat1 = stat($file1);
18 0           my @stat2 = stat($file2);
19 0           return ( $stat1[9] <= $stat2[9] );
20             }
21              
22             sub _is_newer
23             {
24 0     0     my $file1 = shift;
25 0           my $file2 = shift;
26 0           return ( !_is_older( $file1, $file2 ) );
27             }
28              
29             sub new
30             {
31 0     0 1   my $class = shift;
32 0           my $self = {};
33 0           bless $self, $class;
34              
35 0           $self->_init(@_);
36              
37 0           return $self;
38             }
39              
40             sub _set_base_dir
41             {
42 0     0     my $self = shift;
43              
44 0           my $base_dir = shift;
45              
46 0           $base_dir =~ s{/*$}{/};
47              
48 0           $self->{'base_dir'} = $base_dir;
49              
50 0           return 0;
51             }
52              
53             sub _get_base_dir
54             {
55 0     0     my $self = shift;
56              
57 0           return $self->{'base_dir'};
58             }
59              
60             sub _set_dest_dir
61             {
62 0     0     my $self = shift;
63              
64 0           my $dest_dir = shift;
65              
66 0           $self->{'dest_dir'} = $dest_dir;
67              
68 0           return 0;
69             }
70              
71             sub _get_dest_dir
72             {
73 0     0     my $self = shift;
74              
75 0           return $self->{'dest_dir'};
76             }
77              
78             sub _init
79             {
80 0     0     my $self = shift;
81              
82 0           my %args = @_;
83              
84 0   0       $self->_set_base_dir( $args{'base_dir'} || "." );
85              
86 0   0       $self->_set_dest_dir( $args{'dest_dir'} || "./dest" );
87              
88 0           return 0;
89             }
90              
91             sub process_content
92             {
93 0     0 1   my $self = shift;
94              
95 0           my $fh = shift;
96              
97 0           my $out_content = "";
98              
99             my $out = sub {
100 0     0     $out_content .= join( "", @_ );
101 0           };
102              
103 0           my $parser = HTML::TokeParser->new($fh);
104 0           while ( my $token = $parser->get_token() )
105             {
106 0           my $type = $token->[0];
107 0 0         if ( $type eq "E" )
    0          
    0          
    0          
    0          
    0          
108             {
109 0           $out->( $token->[2] );
110             }
111             elsif ( $type eq "C" )
112             {
113 0           $out->( $token->[1] );
114             }
115             elsif ( $type eq "T" )
116             {
117 0           $out->( $token->[1] );
118             }
119             elsif ( $type eq "D" )
120             {
121 0           $out->( $token->[1] );
122             }
123             elsif ( $type eq "PI" )
124             {
125 0           $out->( $token->[2] );
126             }
127             elsif ( $type eq "S" )
128             {
129 0           my $tag = $token->[1];
130 0           my %process_tags = (
131             'form' => { 'action' => 1 },
132             'img' => { 'src' => 1 },
133             'a' => { 'href' => 1 },
134             'link' => { 'href' => 1 },
135             );
136 0 0         if ( exists( $process_tags{$tag} ) )
137             {
138 0           my $ret = "<$tag";
139 0           my $attrseq = $token->[3];
140 0           my $attr_values = $token->[2];
141 0           my $process_attrs = $process_tags{$tag};
142 0           foreach my $attr (@$attrseq)
143             {
144 0           my $value = $attr_values->{$attr};
145 0 0         if ( exists( $process_attrs->{$attr} ) )
146             {
147             # If it's a local link that ends with slash -
148             # then append index.html
149 0 0 0       if ( ( $value !~ /^[a-z]+:/ )
      0        
150             && ( $value !~ /^\// )
151             && ( $value =~ /\/(#[^#\/]*)?$/ ) )
152             {
153 0           my $pos = rindex( $value, "/" );
154 0           substr( $value, $pos + 1, 0 ) = "index.html";
155             }
156             }
157 0 0         if ( $attr eq "/" )
158             {
159 0           $ret .= " /";
160             }
161             else
162             {
163 0           $ret .= " $attr=\"$value\"";
164             }
165             }
166 0           $out->($ret);
167 0           $out->(">");
168             }
169             else
170             {
171 0           $out->( $token->[4] );
172             }
173             }
174             }
175              
176 0           return $out_content;
177             }
178              
179             sub process_file
180             {
181 0     0 1   my $self = shift;
182 0           my $filename = shift;
183              
184 0           my $dest_dir = $self->_get_dest_dir();
185 0           my $src_dir = $self->_get_base_dir();
186              
187 0 0         open my $in, '<', "$src_dir/$filename"
188             or die "Cannot open '$src_dir/$filename' - $!";
189 0 0         open my $out, '>', "$dest_dir/$filename"
190             or die "Cannot open '$dest_dir/$filename' for writing- $!";
191 0           print {$out} $self->process_content($in);
  0            
192 0           close($in);
193 0           close($out);
194             }
195              
196             sub process_dir_tree
197             {
198 0     0 1   my $self = shift;
199              
200 0           my %args = @_;
201              
202             my $should_replace_file = sub {
203 0     0     my ( $src, $dest ) = @_;
204 0 0         if ( $args{'only-newer'} )
205             {
206 0   0       return ( ( !-e $dest ) || ( _is_newer( $src, $dest ) ) );
207             }
208             else
209             {
210 0           return 1;
211             }
212 0           };
213              
214 0           my $src_dir = $self->_get_base_dir();
215 0           my $dest_dir = $self->_get_dest_dir();
216              
217 0           my ( @dirs, @other_files, @html_files );
218              
219             my $wanted = sub {
220 0     0     my $filename = $File::Find::name;
221 0 0         if ( length($filename) < length($src_dir) )
222             {
223 0           return;
224             }
225              
226             # Remove the $src_dir from the filename;
227 0           $filename = substr( $filename, length($src_dir) );
228              
229 0 0         if ( -d $_ )
    0          
230             {
231 0           push @dirs, $filename;
232             }
233             elsif (/\.html?$/)
234             {
235 0           push @html_files, $filename;
236             }
237             else
238             {
239 0           push @other_files, $filename;
240             }
241 0           };
242              
243 0           find( $wanted, $src_dir );
244              
245             my $soft_mkdir = sub {
246 0     0     my $dir = shift;
247 0 0         if ( -d $dir )
    0          
248             {
249             # Do nothing
250             }
251             elsif ( -e $dir )
252             {
253 0           die "$dir exists in destination and is not a directory";
254             }
255             else
256             {
257 0 0         mkdir($dir) || die "mkdir failed: $!\n";
258             }
259 0           };
260              
261             # Create the directory structure in $dest
262              
263 0           $soft_mkdir->($dest_dir);
264 0           foreach my $dir (@dirs)
265             {
266 0           $soft_mkdir->("$dest_dir/$dir");
267             }
268              
269 0           foreach my $file (@other_files)
270             {
271 0           my $src = "$src_dir/$file";
272 0           my $dest = "$dest_dir/$file";
273 0 0         if ( $should_replace_file->( $src, $dest ) )
274             {
275 0           copy( $src, $dest );
276             }
277             }
278              
279 0           foreach my $file (@html_files)
280             {
281 0           my $src = "$src_dir/$file";
282 0           my $dest = "$dest_dir/$file";
283 0 0         if ( $should_replace_file->( $src, $dest ) )
284             {
285 0           $self->process_file($file);
286             }
287             }
288              
289 0           return 0;
290             }
291              
292             1;
293              
294             __END__