This patch contains the changes to Pod::Simple::HTML that are in use on search.cpan.org The rest is all done with CSS. For those who use Mason, an example component <%args> $filename <%perl> my $pod = Pod::Simple::HTML->new; # This adds the link to the top of the page next to the headers $pod->{'Tagmap'}{'/head1'} = " ^\n"; $pod->set_source($filename); $pod->output_string(\my $html); $pod->do_middle;
<% $pod->contents %>
<% $html %>
diff -ur Pod-Simple-2.04.orig/lib/Pod/Simple/HTML.pm Pod-Simple-2.04/lib/Pod/Simple/HTML.pm --- Pod-Simple-2.04.orig/lib/Pod/Simple/HTML.pm Tue Sep 2 07:30:45 2003 +++ Pod-Simple-2.04/lib/Pod/Simple/HTML.pm Wed Oct 15 07:56:26 2003 @@ -3,17 +3,16 @@ package Pod::Simple::HTML; use strict; use Pod::Simple::PullParser (); -use vars qw(@ISA %Tagmap $Computerese $Lame $Linearization_Limit $VERSION); +use vars qw(@ISA %Tagmap $Computerese $Linearization_Limit $VERSION); @ISA = ('Pod::Simple::PullParser'); -$VERSION = '2.01'; +$VERSION = '2.01_01'; use UNIVERSAL (); sub DEBUG () {0} use utf8; -$Computerese = " lang='und' xml:lang='und'" unless defined $Computerese; -$Lame = ' class="pad"' unless defined $Lame; +$Computerese = "" unless defined $Computerese; $Linearization_Limit = 90 unless defined $Linearization_Limit; # headings/items longer than that won't get an @@ -41,10 +40,10 @@ 'head2' => "\n

", # '' 'head3' => "\n

", # '' 'head4' => "\n

", # '' - '/head1' => "

\n", - '/head2' => "\n", - '/head3' => "\n", - '/head4' => "\n", + '/head1' => "\n", + '/head2' => "\n", + '/head3' => "\n", + '/head4' => "\n", 'X' => "", @@ -79,11 +78,11 @@ ] # no point in providing a way to get ..., I think ), - '/item-bullet' => "

\n", - '/item-number' => "

\n", - '/item-text' => "

\n", - 'Para_item' => "\n
", - '/Para_item' => "

\n", + '/item-bullet' => "\n", + '/item-number' => "\n", + '/item-text' => "\n", + 'item-body' => "\n
", + '/item-body' => "
\n", 'B' => "", '/B' => "", 'I' => "", '/I' => "", @@ -128,6 +127,15 @@ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +sub escape_url { + $_[0] =~ s/([^\x00-\xFF])/join '', map sprintf('%%%02X',$_), unpack 'C*', $1/eg; + $_[0] =~ s/([^\._abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789])/sprintf('%%%02X',ord($1))/eg; + # Yes, stipulate the list without a range, so that this can work right on + # all charsets that this module happens to run under. + # Altho, hmm, what about that ord? Presumably that won't work right + # under non-ASCII charsets. Something should be done about that. +} + sub do_pod_link { my($self, $link) = @_; my $to = $link->attr('to'); @@ -138,6 +146,7 @@ ); if(defined $to and length $to) { + # resolve_pod_page_link must return a properly escaped URL $to = $self->resolve_pod_page_link($to, $section); return undef unless defined $to and length $to; # resolve_pod_page_link returning undef is how it @@ -152,22 +161,10 @@ $section = $self->unicode_escape_url($section); # Turn char 1234 into "(1234)" $section = '_' unless length $section; + escape_url($section); } - - - foreach my $it ($to, $section) { - if( defined $it ) { - $it =~ s/([^\x00-\xFF])/join '', map sprintf('%%%02X',$_), unpack 'C*', $1/eg; - $it =~ s/([^\._abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789])/sprintf('%%%02X',ord($1))/eg; - # Yes, stipulate the list without a range, so that this can work right on - # all charsets that this module happens to run under. - # Altho, hmm, what about that ord? Presumably that won't work right - # under non-ASCII charsets. Something should be done about that. - } - } - - my $out = $to if defined $to and length $to; + my $out = (defined $to) ? $to : ''; $out .= "#" . $section if defined $section and length $section; return undef unless length $out; return $out; @@ -175,9 +172,10 @@ sub resolve_pod_page_link { - my($self, $to) = @_; - - return 'TODO'; + escape_url(my $to = $_[1]); + + "http://search.cpan.org/perldoc?$to"; + # We should make this configurable, but this is a good default } sub do_url_link { return $_[1]->attr('to') } @@ -203,10 +201,15 @@ } +sub do_anchor { $_[1] } + sub do_middle { # the main work my $self = $_[0]; my $fh = $self->{'output_fh'}; + my $tagmap = $self->{'Tagmap'}; + print $fh $self->version_tag_comment, "\n"; + my($token, $type, $tagname); my @stack; my $dont_wrap = 0; @@ -223,7 +226,11 @@ } } elsif ($tagname eq 'item-text' or $tagname =~ m/^head\d$/s) { - print $fh $self->{'Tagmap'}{$tagname} || next; + if( $stack[-1] and $tagname eq 'item-text' ) { + print $fh $stack[-1]; + $stack[-1] = ''; + } + print $fh $tagmap->{$tagname} || next; my @to_unget; while(1) { @@ -232,14 +239,16 @@ and $to_unget[-1]->tagname eq $tagname; } my $name = $self->linearize_tokens(@to_unget); + $name = $self->do_anchor($name, $token) if defined $name; if(defined $name) { # ludicrously long, so nevermind + push @{$self->{contents}}, [ $1, $name ] + if $tagname =~ m/^head(\d)$/; $name =~ tr/ /_/; - print $fh ""; + print $fh ""; DEBUG and print "Linearized ", scalar(@to_unget), " tokens as \"$name\".\n"; } else { - print $fh ""; # Yes, an 'a' element with no attributes! DEBUG and print "Linearized ", scalar(@to_unget), " tokens, but it was too long, so nevermind.\n"; } @@ -257,12 +266,13 @@ next; } else { - if( $tagname =~ m/^over-(.+)$/s ) { - push @stack, $1; - } elsif( $tagname eq 'Para') { - $tagname = 'Para_item' if @stack and $stack[-1] eq 'text'; + if( $tagname =~ m/^over-/s ) { + push @stack, ''; + } elsif( $tagname =~ m/^item-/s and @stack and $stack[-1] ) { + print $fh $stack[-1]; + $stack[-1] = ''; } - print $fh $self->{'Tagmap'}{$tagname} || next; + print $fh $tagmap->{$tagname} || next; ++$dont_wrap if $tagname eq 'Verbatim' or $tagname eq "VerbatimFormatted" or $tagname eq 'X'; } @@ -270,11 +280,21 @@ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - } elsif( $type eq 'end' ) { if( ($tagname = $token->tagname) =~ m/^over-/s ) { - pop @stack; - } elsif( $tagname eq 'Para' ) { - $tagname = 'Para_item' if @stack and $stack[-1] eq 'text'; + if( my $end = pop @stack ) { + print $fh $end; + } + } elsif( $tagname =~ m/^item-/s and @stack) { + $stack[-1] = $tagmap->{"/$tagname"}; + if( $tagname eq 'item-text' and defined(my $next = $self->get_token) ) { + $self->unget_token($next); + if( $next->type eq 'start' and $next->tagname !~ m/^item-/s ) { + print $fh $tagmap->{"/item-text"},$tagmap->{"item-body"}; + $stack[-1] = $tagmap->{"/item-body"}; + } + } + next; } - print $fh $self->{'Tagmap'}{"/$tagname"} || next; + print $fh $tagmap->{"/$tagname"} || next; --$dont_wrap if $tagname eq 'Verbatim' or $tagname eq 'X'; # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -285,27 +305,42 @@ } } + print $fh "\n"; return 1; } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +sub do_head { + my $self = $_[0]; + esc(my $title = $self->{'Title'}); + + print {$self->{'output_fh'}} <$title + +HEAD + +} + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + sub do_beginning { my $self = $_[0]; - my $title = $self->get_short_title(); + $self->{'Title'} = $self->get_short_title(); unless($self->content_seen) { DEBUG and print "No content seen in search for title.\n"; return; } - $self->{'Title'} = $title; - esc($title); print {$self->{'output_fh'}} - "\n$title\n\n\n", - $self->version_tag_comment, - "\n", - ; + qq{\n}, + qq{\n}; + + $self->do_head; + print {$self->{'output_fh'}} "
\n"; + # TODO: more configurability there DEBUG and print "Returning from do_beginning...\n"; @@ -325,7 +360,7 @@ sub do_end { my $self = $_[0]; - print {$self->{'output_fh'}} "\n\n\n"; + print {$self->{'output_fh'}} "
\n\n"; # TODO: allow for a footer return 1; } @@ -397,6 +432,30 @@ } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +sub contents { + my $self = shift; + my $contents = $self->{contents} + or return ''; + my $str = ''; + my $lvl = 0; + foreach my $entry (@$contents) { + my ($nlvl, $label) = @$entry; + if (my $n = $nlvl - $lvl) { + if ($n > 0) { + $str .= substr("
    • " x $n, 4); + } + else { + $str .= "
    \n" x -$n; + } + $lvl = $nlvl; + } + (my $name = $label) =~ tr/ /_/; + $str .= sprintf qq{
  • %s\n}, esc($name),esc($label); + } + $str .= "\n" x $lvl; + $str; +} 1; __END__