\n",
'B' => "", '/B' => "",
'I' => "", '/I' => "",
'F' => "", '/F' => "",
'C' => "", '/C' => "",
'L' => "", # ideally never used!
'/L' => "",
);
sub changes {
return map {; m/^([-_:0-9a-zA-Z]+)=([-_:0-9a-zA-Z]+)$/s
? ( $1, => "\n<$2>", "/$1", => "$2>\n" ) : die "Funky $_"
} @_;
}
sub changes2 {
return map {; m/^([-_:0-9a-zA-Z]+)=([-_:0-9a-zA-Z]+)$/s
? ( $1, => "<$2>", "/$1", => "$2>" ) : die "Funky $_"
} @_;
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sub go { Pod::Simple::HTML->parse_from_file(@ARGV); exit 0 }
# Just so we can run from the command line. No options.
# For that, use perldoc!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sub new {
my $new = shift->SUPER::new(@_);
#$new->nix_X_codes(1);
$new->nbsp_for_S(1);
$new->accept_targets( 'html', 'HTML' );
$new->accept_codes('VerbatimFormatted');
$new->accept_codes(@_to_accept);
DEBUG > 2 and print STDERR "To accept: ", join(' ',@_to_accept), "\n";
$new->perldoc_url_prefix( $Perldoc_URL_Prefix );
$new->perldoc_url_postfix( $Perldoc_URL_Postfix );
$new->man_url_prefix( $Man_URL_Prefix );
$new->man_url_postfix( $Man_URL_Postfix );
$new->title_prefix( $Title_Prefix );
$new->title_postfix( $Title_Postfix );
$new->html_header_before_title(
qq[$Doctype_decl]
);
$new->html_header_after_title( join "\n" =>
"",
$Content_decl,
"\n",
$new->version_tag_comment,
"\n",
);
$new->html_footer( qq[\n\n\n\n] );
$new->top_anchor( "\n" );
$new->{'Tagmap'} = {%Tagmap};
return $new;
}
sub __adjust_html_h_levels {
my ($self) = @_;
my $Tagmap = $self->{'Tagmap'};
my $add = $self->html_h_level;
return unless defined $add;
return if ($self->{'Adjusted_html_h_levels'}||0) == $add;
$add -= 1;
for (1 .. 6) {
$Tagmap->{"head$_"} =~ s/$_/$_ + $add/e;
$Tagmap->{"/head$_"} =~ s/$_/$_ + $add/e;
}
}
sub batch_mode_page_object_init {
my($self, $batchconvobj, $module, $infile, $outfile, $depth) = @_;
DEBUG and print STDERR "Initting $self\n for $module\n",
" in $infile\n out $outfile\n depth $depth\n";
$self->batch_mode(1);
$self->batch_mode_current_level($depth);
return $self;
}
sub run {
my $self = $_[0];
return $self->do_middle if $self->bare_output;
return
$self->do_beginning && $self->do_middle && $self->do_end;
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sub do_beginning {
my $self = $_[0];
my $title;
if(defined $self->force_title) {
$title = $self->force_title;
DEBUG and print STDERR "Forcing title to be $title\n";
} else {
# Actually try looking for the title in the document:
$title = $self->get_short_title();
unless($self->content_seen) {
DEBUG and print STDERR "No content seen in search for title.\n";
return;
}
$self->{'Title'} = $title;
if(defined $title and $title =~ m/\S/) {
$title = $self->title_prefix . esc($title) . $self->title_postfix;
} else {
$title = $self->default_title;
$title = '' unless defined $title;
DEBUG and print STDERR "Title defaults to $title\n";
}
}
my $after = $self->html_header_after_title || '';
if($self->html_css) {
my $link =
$self->html_css =~ m/
? $self->html_css # It's a big blob of markup, let's drop it in
: sprintf( # It's just a URL, so let's wrap it up
qq[\n],
$self->html_css,
);
$after =~ s{()}{$link\n$1}i; # otherwise nevermind
}
$self->_add_top_anchor(\$after);
if($self->html_javascript) {
my $link =
$self->html_javascript =~ m/
? $self->html_javascript # It's a big blob of markup, let's drop it in
: sprintf( # It's just a URL, so let's wrap it up
qq[\n],
$self->html_javascript,
);
$after =~ s{()}{$link\n$1}i; # otherwise nevermind
}
print {$self->{'output_fh'}}
$self->html_header_before_title || '',
$title, # already escaped
$after,
;
DEBUG and print STDERR "Returning from do_beginning...\n";
return 1;
}
sub _add_top_anchor {
my($self, $text_r) = @_;
unless($$text_r and $$text_r =~ m/name=['"]___top['"]/) { # a hack
$$text_r .= $self->top_anchor || '';
}
return;
}
sub version_tag_comment {
my $self = shift;
return sprintf
"\n",
esc(
ref($self), $self->VERSION(), $ISA[0], $ISA[0]->VERSION(),
$], scalar(gmtime($ENV{SOURCE_DATE_EPOCH} || time)),
), $self->_modnote(),
;
}
sub _modnote {
my $class = ref($_[0]) || $_[0];
return join "\n " => grep m/\S/, split "\n",
qq{
If you want to change this HTML document, you probably shouldn't do that
by changing it directly. Instead, see about changing the calling options
to $class, and/or subclassing $class,
then reconverting this document from the Pod source.
When in doubt, email the author of $class for advice.
See 'perldoc $class' for more info.
};
}
sub do_end {
my $self = $_[0];
print {$self->{'output_fh'}} $self->html_footer || '';
return 1;
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Normally this would just be a call to _do_middle_main_loop -- but we
# have to do some elaborate things to emit all the content and then
# summarize it and output it /before/ the content that it's a summary of.
sub do_middle {
my $self = $_[0];
return $self->_do_middle_main_loop unless $self->index;
if( $self->output_string ) {
# An efficiency hack
my $out = $self->output_string; #it's a reference to it
my $sneakytag = "\f\f\e\e\b\bIndex Here\e\e\b\b\f\f\n";
$$out .= $sneakytag;
$self->_do_middle_main_loop;
$sneakytag = quotemeta($sneakytag);
my $index = $self->index_as_html();
if( $$out =~ s/$sneakytag/$index/s ) {
# Expected case
DEBUG and print STDERR "Inserted ", length($index), " bytes of index HTML into $out.\n";
} else {
DEBUG and print STDERR "Odd, couldn't find where to insert the index in the output!\n";
# I don't think this should ever happen.
}
return 1;
}
unless( $self->output_fh ) {
require Carp;
Carp::confess("Parser object \$p doesn't seem to have any output object! I don't know how to deal with that.");
}
# If we get here, we're outputting to a FH. So we need to do some magic.
# Namely, divert all content to a string, which we output after the index.
my $fh = $self->output_fh;
my $content = '';
{
# Our horrible bait and switch:
$self->output_string( \$content );
$self->_do_middle_main_loop;
$self->abandon_output_string();
$self->output_fh($fh);
}
print $fh $self->index_as_html();
print $fh $content;
return 1;
}
###########################################################################
sub index_as_html {
my $self = $_[0];
# This is meant to be called AFTER the input document has been parsed!
my $points = $self->{'PSHTML_index_points'} || [];
@$points > 1 or return qq[\n];
# There's no point in having a 0-item or 1-item index, I dare say.
my(@out) = qq{\n
};
my $level = 0;
my( $target_level, $previous_tagname, $tagname, $text, $anchorname, $indent);
foreach my $p (@$points, ['head0', '(end)']) {
($tagname, $text) = @$p;
$anchorname = $self->section_escape($text);
if( $tagname =~ m{^head(\d+)$} ) {
$target_level = 0 + $1;
} else { # must be some kinda list item
if($previous_tagname =~ m{^head\d+$} ) {
$target_level = $level + 1;
} else {
$target_level = $level; # no change needed
}
}
# Get to target_level by opening or closing ULs
while($level > $target_level)
{ --$level; push @out, (" " x $level) . ""; }
while($level < $target_level)
{ ++$level; push @out, (" " x ($level-1))
. "
"; }
$previous_tagname = $tagname;
next unless $level;
$indent = ' ' x $level;
push @out, sprintf
"%s
and through the rest of the head
till the opening of the body
$p->html_header_after_title('...');
=head2 html_footer
The very end of the document:
$p->html_footer( qq[\n\n\n\n] );
=head1 SUBCLASSING
Can use any of the methods described above but for further customization
one needs to override some of the methods:
package My::Pod;
use strict;
use warnings;
use base 'Pod::Simple::HTML';
# needs to return a URL string such
# http://some.other.com/page.html
# #anchor_in_the_same_file
# /internal/ref.html
sub do_pod_link {
# My::Pod object and Pod::Simple::PullParserStartToken object
my ($self, $link) = @_;
say $link->tagname; # will be L for links
say $link->attr('to'); #
say $link->attr('type'); # will be 'pod' always
say $link->attr('section');
# Links local to our web site
if ($link->tagname eq 'L' and $link->attr('type') eq 'pod') {
my $to = $link->attr('to');
if ($to =~ /^Padre::/) {
$to =~ s{::}{/}g;
return "/docs/Padre/$to.html";
}
}
# all other links are generated by the parent class
my $ret = $self->SUPER::do_pod_link($link);
return $ret;
}
1;
Meanwhile in script.pl:
use My::Pod;
my $p = My::Pod->new;
my $html;
$p->output_string(\$html);
$p->parse_file('path/to/Module/Name.pm');
open my $out, '>', 'out.html' or die;
print $out $html;
TODO
maybe override do_beginning do_end
=head1 SEE ALSO
L, L
TODO: a corpus of sample Pod input and HTML output? Or common
idioms?
=head1 SUPPORT
Questions or discussion about POD and Pod::Simple should be sent to the
pod-people@perl.org mail list. Send an empty email to
pod-people-subscribe@perl.org to subscribe.
This module is managed in an open GitHub repository,
L. Feel free to fork and contribute, or
to clone L and send patches!
Patches against Pod::Simple are welcome. Please send bug reports to
.
=head1 COPYRIGHT AND DISCLAIMERS
Copyright (c) 2002-2004 Sean M. Burke.
This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
This program is distributed in the hope that it will be useful, but
without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose.
=head1 ACKNOWLEDGEMENTS
Thanks to L for permission to use its
L site for man page links.
Thanks to L for permission to use the
site for Perl module links.
=head1 AUTHOR
Pod::Simple was created by Sean M. Burke .
But don't bother him, he's retired.
Pod::Simple is maintained by:
=over
=item * Allison Randal C
=item * Hans Dieter Pearcey C
=item * David E. Wheeler C
=back
=cut