—#!/usr/local/bin/perl
use
strict;
use
File::Find;
use
File::Path;
use
Getopt::Long;
use
HTML::Stream;
use
IO::File;
use
Pod::Tree::HTML;
use
File::Spec;
my
%Options
= (
bgcolor
=>
'#ffffff'
,
text
=>
'#000000'
,
hr
=> 1,
toc
=> 1 );
my
$ok
= GetOptions(\
%Options
,
"base:s"
,
"css:s"
,
"bgcolor:s"
,
"empty"
,
"index:s"
,
"module"
,
"text:s"
,
"toc!"
,
"hr:i"
);
$ok
or
die
"Bad command line options\n"
;
my
%Index
;
my
@Dirs
;
my
(
$PodDir
,
$HTMLDir
) =
@ARGV
;
$HTMLDir
or
die
"pods2html PodDir HTMLDir\n"
;
$PodDir
= canonpath File::Spec
$PodDir
;
$HTMLDir
= rel2abs File::Spec
$HTMLDir
;
mkpath(
$HTMLDir
);
umask
0022;
find({
wanted
=> \
&Translate
,
no_chdir
=> 1 },
$PodDir
);
Index ()
if
$Options
{
index
};
Cleanup()
unless
$Options
{empty};
sub
Translate
{
-d and
&Translate_Dir
;
-f and
&Translate_POD
;
}
sub
MkDir
{
my
$dir
=
shift
;
-d
$dir
and
return
;
mkdir
$dir
, 0755 or
die
"Can't mkdir $dir: $!\n"
;
push
@Dirs
,
$dir
;
}
sub
Translate_Dir
{
my
$dir
=
$File::Find::name
;
if
(
$HTMLDir
eq rel2abs File::Spec
$dir
)
{
$File::Find::prune
= 1;
return
;
}
if
(
$Options
{module} and ( m(/t$) or m(/blib$) ) )
{
$File::Find::prune
= 1;
return
;
}
$dir
=~ s/^
$PodDir
/
$HTMLDir
/o;
-d
$dir
or MkDir
$dir
;
"$File::Find::name\n"
;
}
sub
Translate_POD
{
m( \.(pm|pod)$ )x or
return
;
my
$source
=
$File::Find::name
;
Hidden(
$source
) and
return
;
"$source\n"
;
my
$dest
=
$source
;
$dest
=~ s/^
$PodDir
/
$HTMLDir
/;
$dest
=~ s( \.\w+$ )(.html)x;
my
$depth
= Depth(
$source
);
my
$pod
=
$source
;
$pod
=~ s(^
$PodDir
/)();
$pod
=~ s( \.\w+$ )()x;
$Index
{
$pod
} = 1;
my
$html
= new Pod::Tree::HTML
$source
,
$dest
,
%Options
;
$html
->set_options(
depth
=>
$depth
);
$html
->translate;
}
sub
Hidden
{
my
$source
=
shift
;
$source
=~ m(\.pm$) or
return
0;
$source
=~ s(\.pm$)(.pod);
-e
$source
}
sub
Depth
{
my
$source
=
shift
;
my
$tree
= new Pod::Tree;
$tree
->load_file(
$source
);
my
$children
=
$tree
->get_root->get_children;
my
@pod
=
grep
{ is_pod
$_
}
@$children
;
my
$node1
=
$pod
[1];
$node1
or
return
''
;
my
$text
=
$node1
->get_deep_text;
my
(
$name
) =
split
m(\s+-+\s+),
$text
;
$name
=~ s(^\s+)();
my
@name
=
split
/::/,
$name
;
@name
-1
}
sub
Index
{
my
$index
=
"$HTMLDir/index.html"
;
my
$fh
= new IO::File
">$index"
;
defined
$fh
or
die
"Can't open $index: $!\n"
;
my
$stream
= new HTML::Stream
$fh
;
my
$title
=
$Options
{
index
};
my
$bgcolor
=
$Options
{bgcolor};
my
$text
=
$Options
{text};
$stream
-> HTML->HEAD;
$stream
-> TITLE->text(
$title
)->_TITLE;
$stream
->_HEAD
-> BODY(
BGCOLOR
=>
$bgcolor
,
TEXT
=>
$text
);
$stream
->H1->t(
$title
)->_H1;
Emit_Entries(
$stream
);
$stream
->_BODY->_HTML;
}
sub
Emit_Entries
{
my
$stream
=
shift
;
$stream
->UL;
for
my
$entry
(
sort
keys
%Index
)
{
$stream
->LI
->A(
HREF
=>
"$entry.html"
)
->t(
$entry
)
->_A
->_LI;
}
$stream
->_UL;
}
sub
Cleanup
{
while
(
@Dirs
)
{
my
$dir
=
pop
@Dirs
;
rmdir
$dir
;
# does nothing unless $dir is empty
}
}
__END__
=head1 NAME
pods2html - translate a tree of PODs to HTML
=head1 SYNOPSIS
C<pods2html>
[C<--base> I<url>]
[C<--css> I<url>]
[C<--empty>]
[C<--index> I<title>]
[C<--module>]
[C<-->[C<no>]C<toc>] [C<--hr> I<level>]
[C<--bgcolor> I<#rrggbb>] [C<--text> I<#rrggbb>]
I<PODdir> I<HTMLdir>
=head1 DESCRIPTION
C<pods2html> finds all the F<.pod> and F<.pm> files in the
directory tree rooted at I<PODdir>.
It translates each POD to HTML,
and writes it to a parallel directory tree rooted at I<HTMLdir>
It makes the HTML files world-readable.
=head1 OPTIONS
=over 4
=item C<--base> I<url>
Specifies a base URL for HTML links.
=item C<--css> I<url>
Specifies a Cascanding Style Sheet for the generated HTML pages.
=item C<--empty>
Creates HTML files for empty PODs.
If this options is not provided, then no HTML file is created for empty PODs.
=item C<--index> I<title>
Writes an index of all the HTML files to I<HTMLDir>F</index.html>.
I<title> is used as the title of the index page.
=item C<--module>
Ignores files in directories named F<t/> and F<blib/>.
Useful for translating PODs in a module development directory.
=item C<-->[C<no>]C<toc>
Includes or omits the table of contents.
Default is to include the TOC.
=item C<--hr> I<level>
Controls the profusion of horizontal lines in the output, as follows:
level horizontal lines
0 none
1 between TOC and body
2 after each =head1
3 after each =head1 and =head2
Default is level 1.
=item C<--bgcolor> I<#rrggbb>
Set the background color to I<#rrggbb>.
Default is white.
=item C<--text> I<#rrggbb>
Set the text color to I<#rrggbb>.
Default is black.
=back
=head1 REQUIRES
L<C<Pod::Tree::HTML>>,
L<C<HTML::Stream>>
=head1 BUGS
The recursion check doesn't work on Win32.
This means that the program will enter an infinite recursion
if I<HTMLdir> is a subdirectory of I<PODdir>.
=head1 SEE ALSO
L<C<pod2html>>,
L<C<Pod::Tree::HTML>>
=head1 AUTHOR
Steven McDougall, <swmcd@world.std.com>
=head1 COPYRIGHT
Copyright (c) 1999-2006 by Steven McDougall. This program is free software;
you can redistribute it and/or modify it under the same terms as Perl.