File Coverage

lib/Pod/HtmlTree.pm
Criterion Covered Total %
statement 110 123 89.4
branch 17 30 56.6
condition 5 8 62.5
subroutine 19 20 95.0
pod 2 7 28.5
total 153 188 81.3


line stmt bran cond sub pod time code
1             ############################################################
2             package Pod::HtmlTree;
3             ############################################################
4 1     1   356 use strict;
  1         1  
  1         26  
5 1     1   4 use warnings;
  1         1  
  1         21  
6              
7 1     1   4 use Exporter;
  1         3  
  1         35  
8 1     1   1008 use Pod::Html;
  1         106987  
  1         72  
9 1     1   986 use Text::Wrap;
  1         3048  
  1         54  
10 1     1   7 use File::Find;
  1         2  
  1         59  
11 1     1   6 use File::Spec;
  1         2  
  1         21  
12 1     1   6 use File::Basename;
  1         2  
  1         61  
13 1     1   5 use File::Path;
  1         2  
  1         46  
14 1     1   6 use Pod::Html;
  1         2  
  1         41  
15 1     1   5 use Cwd;
  1         2  
  1         55  
16 1     1   3830 use File::Temp qw(tempfile);
  1         24399  
  1         1408  
17              
18             our $VERSION = '0.97';
19              
20             our @ISA = qw(Exporter);
21              
22             our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
23             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} },
24             qw(pms modules
25             pod2htmltree banner
26             ) );
27             our @EXPORT = qw( );
28              
29             my $HTML_DIR = "docs/html";
30             my $BASE = cwd();
31             my @SEARCH_DIRS = qw(. lib);
32             my $SEARCH_DIRS_PATTERN = join('|', map { "^" . quotemeta($_) } @SEARCH_DIRS);
33              
34             ############################################################
35             # Get a list of all *.pm files in the specified directory
36             # and recursively in its subdirectories. Prune the find
37             # tree in the given dirs.
38             ############################################################
39             sub pms {
40             ############################################################
41 4     4 0 599 my($start_dir, $prune_dirs) = @_;
42              
43             # Default if no prune_dirs are given
44 4   50     21 $prune_dirs ||= ['blib', 'docs'];
45              
46 4         6 my @pms = ();
47              
48             File::Find::find( sub {
49              
50 88 100   88   776 if(-d $_) {
51 28         41 for my $dir (@$prune_dirs) {
52 52 100       102 if($_ eq $dir) {
53 4         7 $File::Find::prune = 1;
54 4         125 return;
55             }
56             }
57             }
58            
59 84 100 66     2963 return if ! -f or ! (/\.pm$/ || /\.pod$/);
      66        
60              
61 4         16 (my $path = $File::Find::name) =~ s#^./##;
62              
63 4         71 push @pms, $path;
64 4         221 }, $start_dir );
65              
66 4         34 return @pms;
67             }
68              
69             ############################################################
70             # Get a list of all modules (pm files) in the tree.
71             ############################################################
72             sub modules {
73             ############################################################
74 2     2 0 179 my($start_dir, $prune_dirs) = @_;
75              
76 2         4 my @pms = paths_to_modules(pms($start_dir, $prune_dirs));
77              
78 2         6 return @pms;
79             }
80              
81             ############################################################
82             # Format something in form of a banner
83             ############################################################
84             sub banner {
85             ############################################################
86              
87 0     0 1 0 my $TOTAL_LEN = 50;
88              
89 0         0 my $out = "*" x $TOTAL_LEN;
90 0         0 $out .= "\n";
91 0         0 $Text::Wrap::columns = $TOTAL_LEN - 2;
92 0         0 for my $line (split /\n/, Text::Wrap::fill('* ','* ', @_)) {
93 0         0 chomp $line;
94 0 0       0 if(length($line) < $TOTAL_LEN - 2) {
95 0         0 $line .= (" " x ($TOTAL_LEN - 2 - length($line))) . " *\n";
96             }
97 0         0 $out .= $line;
98             }
99 0         0 $out .= "*" x $TOTAL_LEN;
100 0         0 $out .= "\n";
101              
102 0         0 return $out;
103             }
104              
105             ############################################################
106             sub paths_to_modules {
107             ############################################################
108 3     3 0 6 my(@paths) = @_;
109              
110 3         6 my @modules = map { s#$SEARCH_DIRS_PATTERN##o;
  3         31  
111 3         10 s#^/##;
112 3         8 s#/#::#g;
113 3         7 s#\.pm##;
114 3         6 s#\.pod##;
115 3         32 $_;
116             } @paths;
117              
118             # Remove double entries (e.g. If a module consists of a .pm
119             # and a .pod file)
120 3         4 @modules = do { my %myhash; @myhash{@modules} = (); keys %myhash};
  3         4  
  3         6  
  3         10  
121              
122 3         7 return @modules;
123             }
124              
125             ############################################################
126             # Set up the doc tree
127             ############################################################
128             sub pod2htmltree {
129             ############################################################
130 1     1 1 175 my($htmlroot_to_module, $htmldocdir) = @_;
131              
132 1 50       3 $htmldocdir = $HTML_DIR unless defined $htmldocdir;
133              
134 1         9 my ($fh,$tmpfile) = tempfile();
135 1         639 close $fh;
136              
137 1         3 my @dirs = pms(".");
138 1         4 my @modules = modules(".");
139              
140 1         6 my $see_also = "=head1 SEE ALSO\n\n";
141 1         2 $see_also .= join ', ', map( { "L<$_|$_>" } @modules );
  1         4  
142 1         3 $see_also .= "\n\n";
143 1         1 $see_also .= "B _SRC_HERE_\n\n";
144              
145 1 50       325 mkpath $htmldocdir unless -d $htmldocdir;
146              
147 1         2 for my $pm (@dirs) {
148 1         13 (my $module) = paths_to_modules($pm);
149 1         21 (my $relpath = $pm) =~ s#$SEARCH_DIRS_PATTERN##o;
150 1         16 my $htmlfile = File::Spec->catfile($htmldocdir, $relpath);
151 1         7 $htmlfile =~ s/\.pm$/\.html/;
152 1         2 $htmlfile =~ s/\.pod$/\.html/;
153              
154 1         31 my $dir = dirname($htmlfile);
155              
156 1 50       126 mkpath($dir) unless -d $dir;
157              
158 1 50       33 open FILE, "<$pm" or die "Cannot open $pm";
159 1         253 my $data = join '', ;
160 1         31 close FILE;
161              
162 1         23 $data =~ s/^=head1 SEE ALSO.*?(?=^=)/$see_also/ms;
163              
164 1 50       52 open FILE, ">$tmpfile" or die "Cannot open $tmpfile";
165 1         44 print FILE $data;
166 1         33 close FILE;
167              
168 1 50       11 my $podroot = (-d "lib" ? "lib" : ".");
169              
170 1         13 pod2html("--infile=$tmpfile",
171             "--outfile=$htmlfile",
172             "--podroot=$podroot",
173             "--podpath=.",
174             '--recurse',
175             "--htmlroot=$htmlroot_to_module/$htmldocdir",
176             "--css=$htmlroot_to_module/$htmldocdir/default.css",
177             );
178              
179             # Patch src link
180 1 50       33596 open FILE, "<$htmlfile" or die "Cannot open $htmlfile";
181 1         139 $data = join '', ;
182 1         23 close FILE;
183 1 50       100 open FILE, ">$htmlfile" or die "Cannot open $htmlfile";
184             # If it's a separate pod, link to the .pm
185 1         4 $pm =~ s/\.pod$/.pm/;
186 1 50       20 if(-f $pm) {
187 1         26 $data =~ s#_SRC_HERE_#$module#g;
188             } else {
189 0         0 $data =~ s#_SRC_HERE_##g;
190             }
191 1         47 print FILE $data;
192 1         42 close FILE;
193             }
194              
195             #unlink $tmpfile;
196 1         22 stylesheet_write(File::Spec->catfile($htmldocdir, "default.css"));
197             }
198              
199             ############################################################
200             sub stylesheet_write {
201             ############################################################
202 1     1 0 4 my($dstfile, $csstext) = @_;
203              
204 1 50       6 $csstext = stylesheet_default() unless defined $csstext;
205              
206 1 50       864 open FILE, ">$dstfile" or die "Cannot open $dstfile";
207 1         7 print FILE $csstext;
208 1         54 close FILE;
209             }
210              
211             ############################################################
212             # Default style sheet
213             ############################################################
214             sub stylesheet_default {
215             ############################################################
216 1     1 0 8 return <
217             body {
218             background: #FFFFFF;
219             font-family: Arial;
220             }
221             input {
222             font-size: 12px;
223             }
224             select {
225             font-size: 12px;
226             }
227             tt {
228             font-family: Lucida Console;
229             font-size: 10px;
230             }
231             pre {
232             font-family: Lucida Console;
233             font-size: 12px;
234             }
235             code {
236             font-family: Lucida Console;
237             font-size: 12px;
238             }
239             p {
240             color: #000000;
241             font-size: 12px;
242             font-family: Arial;
243             }
244             blockquote {
245             color: #000000;
246             font-size: 12px;
247             font-family: Arial;
248             font-weight: normal;
249             }
250             b {
251             font-weight: bold;
252             }
253              
254             h1 {
255             font-family: Arial;
256             font-size: 16px;
257             font-weight: bold;
258             color: #B82831;
259             }
260             h2 {
261             font-family: Arial;
262             font-size: 14px;
263             font-weight: bold;
264             color: #B82831;
265             }
266             a:link {
267             color: #B82831;
268             text-decoration: underline;
269             }
270             a:visited {
271             color: #80933F;
272             text-decoration: underline;
273             }
274             EOT
275             }
276              
277             1;
278              
279             __END__