#!perl
package CPAN::Search::Lite::HTML;
use CPAN::Search::Lite::DBI::Index;
use CPAN::Search::Lite::DBI qw($dbh);
use strict;
use warnings;
use File::Temp qw(tempfile);
use File::Basename;
use File::Path;
use File::Spec::Functions qw(splitdir catfile catdir
tmpdir splitpath canonpath);
use File::Copy;
use Pod::Html;
use Pod::Select;
use Perl::Tidy;
use HTML::TextToHTML;
use File::Find;
use Pod::Xhtml;
use CPAN::Search::Lite::Util qw(has_data);
our $VERSION = 0.77;
my $DEBUG = 1;
my %global_opts;
our $dbh = $CPAN::Search::Lite::DBI::dbh;
our $docs;
my $tmpfile = catfile(tmpdir(), 'csl_tmp_podfile.pod');
my $date = scalar localtime();
my $xhtml_version = $Pod::Xhtml::VERSION;
# replace the Pod::Xhtml package's seqL method
# so as to return jus the link if it contains [<>] tags
package MyPodXhtml;
use base qw(Pod::Xhtml);
$Pod::Xhtml::SEQ{L} = \&myseqL;
sub myseqL {
my ($self, $link) = @_;
if ($link =~ /[<>]/) {
return $link;
}
else {
return $self->SUPER::seqL($link);
}
}
# use MyLinkParser to make references to links
# to modules we have
package MyLinkParser;
use Pod::ParseUtils;
use base qw(Pod::Hyperlink);
sub parse {
my $self = shift;
my $link = shift;
$self->SUPER::parse($link);
my $htmlroot = $self->{htmlroot};
my $dist = $self->{dist};
my $page = $self->page;
my $kind = $self->type;
my $node = $self->node;
my $text = $self->text;
my $markup = $self->markup;
if ($node and not $page) {
(my $section = $node) =~ s{ }{_}g;
$section =~ s{\(|\)|\"|"}{}g;
$self->alttext($text);
if ($link =~ m{^(http|ftp)://}) {
$self->node($link);
}
else {
$self->node("#$section");
}
$self->type('hyperlink');
}
elsif (my $d = $docs->{$page}) {
if ($d ne $dist) {
$htmlroot =~ s/$dist/$d/;
}
(my $ref = $page) =~ s{::}{/}g;
$self->alttext($text);
my $rv = "$htmlroot/$ref.html";
if ($node) {
(my $section = $node) =~ s{ }{_}g;
$section =~ s{\(|\)|\"|"}{}g;
$rv .= "#$section";
}
$self->node($rv);
$self->type('hyperlink');
}
}
package CPAN::Search::Lite::HTML;
{
no warnings qw(redefine);
*Pod::Html::pod2html = \&mypod2html;
}
sub new {
my ($class, %args) = @_;
foreach (qw(pod_root html_root dist_docs db user
passwd dist_obj) ) {
die "Must supply a '$_' argument" unless defined $args{$_};
}
my $cdbi = CPAN::Search::Lite::DBI::Index->new(%args);
%global_opts = map {$_ => $args{$_}} qw(setup split_pod dist_info);
if ($args{pod_only} and $args{split_pod}) {
die qq{Please specify only one of "split_pod" or "pod_only"};
}
my $self = {pod_root => $args{pod_root},
html_root => $args{html_root},
css => $args{css},
up_img => $args{up_img},
pod_only => $args{pod_only},
split_pod => $args{split_pod},
dist_docs => $args{dist_docs},
dist_obj => $args{dist_obj},
dist_info => $args{dist_info},
};
bless $self, $class;
}
sub mypod2html {
my @opts = @_;
my %opts;
foreach my $opt(@opts) {
$opt =~ s/^--?//;
my @a = split /=/, $opt, 2;
$opts{$a[0]} = defined $a[1] ? $a[1] : 1;
}
my $infile = $opts{infile};
my $outfile = $opts{outfile};
my ($package, $filename, $line) = caller;
my $is_perltidy = ($package eq 'Perl::Tidy::HtmlWriter');
my $source = $infile;
if ($is_perltidy) {
$source = $tmpfile;
copy($infile, $source) or do {
warn "Cannot copy $infile to $source: $!";
return;
};
}
my $title = $opts{title};
my ($pack, $desc) = split / - /, $title;
$desc = '' unless $desc;
my $htmlroot = $opts{htmlroot};
(my $dist = $htmlroot) =~ s{.*/([^/]+)$}{$1};
(my $root_dir = $htmlroot) =~ s{/$dist$}{};
my $top;
my $backlink = $opts{backlink};
if ($backlink =~ /\.(gif|png|jpe?g)$/) {
$top = <<"END";
\n};
}
}
}
}
my $up = qq{\nBack to home page.\n};
print $fh qq{
$up\n};
close $fh;
chdir $out_root;
clean_pod($out_root);
}
unless ($global_opts{setup}) {
$self->remove_stale() or do {
warn "remove_stale() failed";
return;
};
}
unlink($tmpfile) if (-e $tmpfile);
return 1;
}
sub clean_pod {
my $dir = shift;
return unless ($dir and -d $dir);
my @goners;
finddepth(sub { push @goners, $File::Find::name
if $File::Find::name =~ /(pod2h|perltidy).*\.tmp$/i;},
$dir);
if (@goners) {
foreach my $f(@goners) {
$f = canonpath($f);
next unless -e $f;
unlink $f;
}
}
}
sub unix_path {
my $file = shift;
return $file unless $^O =~ /Win32/;
my @d = splitpath($file);
return File::Spec::Unix->catfile( splitdir($d[1]), $d[2]);
}
sub make_docs {
my $self = shift;
unless ($dbh) {
$self->{error_msg} = q{No db handle available};
return;
}
my $sql = q{ SELECT mod_name,dist_name,doc } .
q { FROM mods,dists WHERE mods.dist_id = dists.dist_id };
my $sth = $dbh->prepare($sql);
$sth->execute() or do {
$self->db_error($sth);
return;
};
while (my ($mod_name, $dist_name, $doc) = $sth->fetchrow_array) {
next unless $doc;
$docs->{$mod_name} = $dist_name;
}
$sth->finish;
}
sub remove_stale {
return if $global_opts{setup};
my $self = shift;
my $html_root = $self->{html_root};
my $pod_root = $self->{pod_root};
my $dist_obj;
unless ($dist_obj = $self->{dist_obj}) {
warn "No dist object available";
return;
}
my @goners = ();
my $data = $dist_obj->{delete};
if (has_data($data)) {
push @goners, keys %$data;
}
if (@goners) {
foreach my $dist_root (@goners) {
my $html_path = catdir $html_root, $dist_root;
if (-d $html_path) {
print "Removing $html_path\n";
rmtree($html_path, $DEBUG, 1)
or warn "Cannot rmtree $html_path: $!";
}
my $pod_path = catdir $pod_root, $dist_root;
if (-d $pod_path) {
print "Removing $pod_path\n";
rmtree($pod_path, $DEBUG, 1)
or warn "Cannot rmtree $pod_path: $!";
}
}
}
return 1;
}
sub db_error {
my ($obj, $sth) = @_;
return unless $dbh;
$sth->finish if $sth;
$obj->{error_msg} = q{Database error: } . $dbh->errstr;
}
1;
__END__
=head1 NAME
CPAN::Search::Lite::HTML - convert CPAN documentation to HTML
=head1 DESCRIPTION
This module converts the extracted pod to html_format,
placing the results underneath C.
It is assumed here that a local CPAN mirror exists; the C
configuration option will cause this extraction to be skipped.
=head1 SEE ALSO
L
=cut