Line # Revision Author
1 160 dpavlin #!/usr/bin/perl
2
3 eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
4 if 0; # not running under some shell
5
6 use strict;
7 use Pod::Xhtml;
8 use Pod::Usage;
9 use Getopt::Long;
10 use File::Find;
11 use File::Slurp;
12
13 # Default options
14 my %opt = (index => 1, toplink => 'Top');
15 GetOptions(\%opt, qw(css=s toplink|backlink=s help index! infile:s outfile:s existing! frames:s))
16 || pod2usage();
17 pod2usage(-verbose => 2) if $opt{help};
18
19 my ($in,$out) = @ARGV;
20
21 pod2usage() unless ($in && $out);
22
23 my $toplink = $opt{toplink} ?
24 sprintf '<p><a href="#TOP" class="toplink">%s</a></p>', $opt{toplink} : '';
25
26 163 dpavlin $opt{css} ||= 'pod.css';
27 160 dpavlin
28 my $link_parser = new LinkResolver( $opt{css} );
29 my $parser = new Pod::Xhtml(StringMode => 1, LinkParser => $link_parser);
30
31 my $parser = new Pod::Xhtml(
32 MakeIndex => $opt{index},
33 TopLinks => $toplink,
34 LinkParser => $link_parser,
35 );
36 if ($opt{css}) {
37 $parser->addHeadText(qq[<link rel="stylesheet" href="$opt{css}"/>]);
38 }
39
40 my @navigation;
41
42 # collect existing files
43 find({
44 wanted => sub {
45 161 dpavlin return unless (-f && -s && m/.html*$/i);
46 160 dpavlin push @navigation, $_;
47 },
48 no_chdir => 1,
49 }, $out) if ($opt{existing});
50
51 # find all files to convert to pod
52 find({
53 wanted => sub {
54 175 dpavlin return unless (-f && -s && m/\.(pl|pm|pod)$/i);
55 160 dpavlin
56 my $in_pod = $_;
57 my $out_html = $_;
58
59 # strip all up to filename
60 # $out_html =~ s#^.*/([^/]+)$#$1#;
61
62 # strip common prefix
63 $out_html =~ s#.*$in/*##;
64 $out_html =~ s#/+#-#g;
65
66 # rename to .html
67 $out_html =~ s#\.(pl|pm|pod)$#.html#;
68 my $nav = $out_html;
69 $out_html = $out . '/' . $out_html;
70
71 print "$in_pod -> $out_html\n";
72
73 $parser->parse_from_file($in_pod, $out_html);
74
75 $nav =~ s#\.html$##i;
76 push @navigation, $nav;
77 },
78 no_chdir => 1,
79 }, $in);
80
81 163 dpavlin my $css_file = $out . '/' . $opt{css};
82 if (! -e $css_file) {
83 open(my $css, '>', $css_file) || die "can't open $css_file: $!";
84 while(<DATA>) {
85 print $css $_;
86 }
87 close($css);
88 }
89
90 160 dpavlin exit unless ($opt{frames});
91
92 # dump navigation html
93
94 my $nav = qq(
95 <html>
96 <head>
97 <link rel="stylesheet" href="pod.css"/>
98 </head>
99 <body>
100 <p>
101 );
102
103 my $first;
104
105 foreach my $f (sort @navigation) {
106
107 $first ||= $f;
108
109 $f =~ s#^$out/##;
110 $f =~ s#\.html*$##;
111 my $text = $f;
112 $text =~ s#-#::#g;
113
114 warn "+nav $f -> $text\n";
115
116 $nav .= qq{ <br/><a href="${f}.html" target="pod">$text</a>\n};
117 }
118
119 $nav .= qq{
120 </p>
121 </html>
122 };
123
124 write_file( "$out/toc.html", $nav );
125
126 my $frameset = qq(
127 <html>
128 <head>
129 <title>$opt{frames}</title>
130 </head>
131 <FRAMESET COLS="*, 250">
132 <FRAME src="./${first}.html" name="pod">
133 <FRAME src="./toc.html" name="toc">
134 <NOFRAMES>
135 <a style="display: none" href="./toc.html">Table of Contents</a>
136 </NOFRAMES>
137 </FRAMESET>
138 </html>
139 );
140
141 write_file( "$out/index.html", $frameset );
142
143 #
144 # Subclass Pod::Hyperlink to create self-referring links
145 #
146
147 package LinkResolver;
148 use Pod::ParseUtils;
149 use base qw(Pod::Hyperlink);
150
151 sub new
152 {
153 my $class = shift;
154 my $css = shift;
155 my $self = $class->SUPER::new();
156 $self->{css} = $css;
157 return $self;
158 }
159
160 sub node
161 {
162 my $self = shift;
163 if($self->SUPER::type() eq 'page')
164 {
165 my $url = $self->SUPER::page();
166 $url =~ s/::/-/g;
167 $url .= '.html';
168 return $url;
169 }
170 $self->SUPER::node(@_);
171 }
172
173 sub text
174 {
175 my $self = shift;
176 return $self->SUPER::page() if($self->SUPER::type() eq 'page');
177 $self->SUPER::text(@_);
178 }
179
180 sub type
181 {
182 my $self = shift;
183 return "hyperlink" if($self->SUPER::type() eq 'page');
184 $self->SUPER::type(@_);
185 }
186
187 1;
188
189 163 dpavlin package main;
190 160 dpavlin
191 =pod
192
193 =head1 NAME
194
195 allpod2xhtml - convert .pod files to .xhtml files
196
197 =head1 SYNOPSIS
198
199 allpod2xhtml [--help] [OPTIONS] source_dir dest_dir
200
201 =head1 DESCRIPTION
202
203 Converts files from pod format (see L<perlpod>) to XHTML format.
204
205 =head1 OPTIONS
206
207 =over 4
208
209 =item --help
210
211 display help
212
213 =item --infile FILENAME
214
215 the input filename. STDIN is used otherwise
216
217 =item --outfile FILENAME
218
219 the output filename. STDOUT is used otherwise
220
221 =item --css URL
222
223 Stylesheet URL
224
225 =item --index/--noindex
226
227 generate an index, or not. The default is to create an index.
228
229 =item --toplink LINK TEXT
230
231 set text for "back to top" links. The default is 'Top'.
232
233 =item --frames TITLE OF FRAMESET
234
235 create C<index.html> and C<toc.html> with frameset for all converted douments
236
237 =item --existing
238
239 include existing html files in C<dest_dir> in navigation
240
241 =back
242
243 =head1 BUGS
244
245 See L<Pod::Xhtml> for a list of known bugs in the translator.
246
247 =head1 AUTHOR
248
249 P Kent E<lt>cpan _at_ bbc _dot_ co _dot_ ukE<gt>
250
251 Dobrica Pavlinusic C<< <dpavlin@rot13.org> >>
252
253 =head1 COPYRIGHT
254
255 (c) BBC 2004. This program is free software; you can redistribute it and/or
256 modify it under the GNU GPL.
257
258 See the file COPYING in this distribution, or http://www.gnu.org/licenses/gpl.txt
259
260 =head1 SEE ALSO
261
262 L<perlpod>, L<Pod::Xhtml>
263
264 =cut
265 163 dpavlin
266 __DATA__
267 BODY {
268 color: black;
269 font-family: arial,sans-serif;
270 margin: 0;
271 padding: 1ex;
272 }
273
274 TABLE {
275 border-collapse: collapse;
276 border-spacing: 0;
277 border-width: 0;
278 color: inherit;
279 }
280
281 IMG { border: 0; }
282 FORM { margin: 0; }
283 input { margin: 2px; }
284
285 A:link, A:visited {
286 background: transparent;
287 color: #006699;
288 }
289
290 A[href="#POD_ERRORS"] {
291 background: transparent;
292 color: #FF0000;
293 }
294
295 TD {
296 margin: 0;
297 padding: 0;
298 }
299
300 DIV {
301 border-width: 0;
302 }
303
304 DT {
305 margin-top: 1em;
306 }
307
308 TH {
309 background: #bbbbbb;
310 color: inherit;
311 padding: 0.4ex 1ex;
312 text-align: left;
313 }
314
315 TH A:link, TH A:visited {
316 background: transparent;
317 color: black;
318 }
319
320 .pod PRE {
321 background: #eeeeee;
322 border: 1px solid #888888;
323 color: black;
324 padding: 1em;
325 padding-bottom: 0;
326 white-space: pre;
327 }
328
329 .pod H1 {
330 background: transparent;
331 color: #006699;
332 font-size: large;
333 }
334
335 .pod H2 {
336 background: transparent;
337 color: #006699;
338 font-size: medium;
339 }
340
341 .pod IMG {
342 vertical-align: top;
343 }
344
345 .pod .toc A {
346 text-decoration: none;
347 }
348
349 .pod .toc LI {
350 line-height: 1.2em;
351 list-style-type: none;
352 }
353
354 .faq DT {
355 font-size: 1.4em;
356 font-weight: bold;
357 }
358
359 .toplink {
360 margin: 0;
361 padding: 0;
362 float: right;
363 font-size: 80%;
364 }