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.10';
3 1     1   580 use strict;
  1         3  
  1         23  
4 1     1   4 use warnings;
  1         1  
  1         19  
5              
6 1     1   14 use 5.008;
  1         3  
7              
8 1     1   398 use HTML::TokeParser;
  1         8149  
  1         25  
9 1     1   6 use File::Find;
  1         8  
  1         50  
10 1     1   385 use File::Copy;
  1         1873  
  1         1133  
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             (
132             'form' => { 'action' => 1 },
133             'img' => { 'src' => 1},
134             'a' => { 'href' => 1},
135             'link' => { 'href' => 1},
136             );
137 0 0         if (exists($process_tags{$tag}))
138             {
139 0           my $ret = "<$tag";
140 0           my $attrseq = $token->[3];
141 0           my $attr_values = $token->[2];
142 0           my $process_attrs = $process_tags{$tag};
143 0           foreach my $attr (@$attrseq)
144             {
145 0           my $value = $attr_values->{$attr};
146 0 0         if (exists($process_attrs->{$attr}))
147             {
148             # If it's a local link that ends with slash -
149             # then append index.html
150 0 0 0       if (($value !~ /^[a-z]+:/) && ($value !~ /^\//) &&
      0        
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             # Remove the $src_dir from the filename;
226 0           $filename = substr($filename, length($src_dir));
227              
228 0 0         if (-d $_)
    0          
229             {
230 0           push @dirs, $filename;
231             }
232             elsif (/\.html?$/)
233             {
234 0           push @html_files, $filename;
235             }
236             else
237             {
238 0           push @other_files, $filename;
239             }
240 0           };
241              
242 0           find($wanted, $src_dir);
243              
244             my $soft_mkdir = sub {
245 0     0     my $dir = shift;
246 0 0         if (-d $dir)
    0          
247             {
248             # Do nothing
249             }
250             elsif (-e $dir)
251             {
252 0           die "$dir exists in destination and is not a directory";
253             }
254             else
255             {
256 0 0         mkdir($dir) || die "mkdir failed: $!\n";
257             }
258 0           };
259              
260             # Create the directory structure in $dest
261              
262 0           $soft_mkdir->($dest_dir);
263 0           foreach my $dir (@dirs)
264             {
265 0           $soft_mkdir->("$dest_dir/$dir");
266             }
267              
268 0           foreach my $file (@other_files)
269             {
270 0           my $src = "$src_dir/$file";
271 0           my $dest = "$dest_dir/$file";
272 0 0         if ($should_replace_file->($src, $dest))
273             {
274 0           copy($src, $dest);
275             }
276             }
277              
278 0           foreach my $file (@html_files)
279             {
280 0           my $src = "$src_dir/$file";
281 0           my $dest = "$dest_dir/$file";
282 0 0         if ($should_replace_file->($src,$dest))
283             {
284 0           $self->process_file($file);
285             }
286             }
287              
288 0           return 0;
289             }
290              
291             1;
292              
293             __END__