package DocSet::Source::POD; use strict; use warnings; use DocSet::Util; use DocSet::RunTime; use vars qw(@ISA); require DocSet::Doc; @ISA = qw(DocSet::Doc); use constant HEAD_MAX_LEVEL => 4; use constant MAX_DESC_LENGTH => 500; # META: we are presenting too early, or this code should be moved to # POD2HTML specific module require Pod::POM::View::HTML; my $mode = 'Pod::POM::View::HTML'; sub retrieve_meta_data { my ($self) = @_; $self->parse_pod; #print Pod::POM::View::HTML->print($pom); my $meta = { title => 'No Title', abstract => '', }; my $pom = $self->{parsed_tree}; my @sections = $pom->head1(); if (@sections) { # extract the title from the NAME section and remove it from content if ($sections[0]->title =~ /NAME/) { # don't present on purpose ->present($mode); there should # be no markup in NAME a problem with #
....(.*?)
.*|$1|s; $meta->{abstract} = $abstract; last; } } $meta->{link} = $self->{rel_dst_path}; # put all the meta data under the same attribute $self->{meta} = $meta; # build the toc datastructure my @toc = (); my $level = 1; for my $node (@sections) { push @toc, $self->render_toc_level($node, $level); } $self->{toc} = \@toc; } sub render_toc_level { my ($self, $node, $level) = @_; my $title = $node->title; my $link = "$title"; # must stringify to get the raw string $link =~ s/^\s*|\s*$//g; # strip leading and closing spaces $link =~ s/\W/_/g; # META: put into a sub? see Doc::Common::pod_pom_html_anchor # prepand '#' for internal links my $toc_link = "toc_$link"; # self referring toc entry $link = "#$link"; my %toc_entry = ( title => $title->present($mode), # run the formatting if any link => $link, toc_link => $toc_link, ); my @sub = (); $level++; if ($level <= HEAD_MAX_LEVEL) { # if there are deeper than =head4 levels we don't go down (spec is 1-4) my $method = "head$level"; for my $sub_node ($node->$method()) { push @sub, $self->render_toc_level($sub_node, $level); } } $toc_entry{subs} = \@sub if @sub; return \%toc_entry; } sub parse_pod { my ($self) = @_; # already parsed return if exists $self->{parsed_tree} && $self->{parsed_tree}; # print ${ $self->{content} }; use Pod::POM; my %options; my $parser = Pod::POM->new(\%options); my $pom = $parser->parse_text(${ $self->{content} }) or die $parser->error(); $self->{parsed_tree} = $pom; # examine any warnings raised if (my @warnings = $parser->warnings()) { print "\n", '-' x 40, "\n"; print "File: $self->{src_path}\n"; warn "$_\n" for @warnings; } } sub src_filter { my ($self) = @_; $self->extract_pod; $self->head2page_breaks() if $self->{docset}->options('slides_mode'); $self->podify_items() if $self->{docset}->options('podify_items'); } sub extract_pod { my ($self) = @_; my @pod = (); my $in_pod = 0; for (split /\n{2,}/, ${ $self->{content} }) { unless ($in_pod) { s/^[\s\n]*//ms; # skip empty lines in preamble $in_pod = /^=/s; } next unless $in_pod; $in_pod = 0 if /^=cut/; push @pod, $_; } # handle empty files unless (@pod) { push @pod, "=head1 NAME", "=head1 Not documented", "=cut"; } my $content = join "\n\n", @pod; $self->{content} = \$content; } sub podify_items { my ($self) = @_; # tmp storage my @paras = (); my $items = 0; my $second = 0; # we want the source in paragraphs my @content = split /\n\n/, ${ $self->{content} }; foreach (@content) { # is it an item? if (/^(\*|\d+)\s+((\*|\d+)\s+)?/) { $items++; if ($2) { $second++; s/^(\*|\d+)\s+//; # strip the first level shortcut s/^(\*|\d+)\s+/=item $1\n\n/; # do the second s/^/=over 4\n\n/ if $second == 1; # start 2nd level } else { # first time insert the =over pod tag s/^(\*|\d+)\s+/=item $1\n\n/; # start 1st level s/^/=over 4\n\n/ if $items == 1; s/^/=back\n\n/ if $second; # complete 2nd level $second = 0; # end 2nd level section } push @paras, split /\n\n/, $_; } else { # complete the =over =item =back tag $second=0, push @paras, "=back" if $second; # if 2nd level is not closed push @paras, "=back" if $items; push @paras, $_; # not a tag item $items = 0; } } my $content = join "\n\n", @paras; $self->{content} = \$content; } # add a page break for =headX in slides mode sub head2page_breaks { my ($self) = @_; # we want the source in paragraphs my @content = split /\n\n/, ${ $self->{content} }; my $count = 0; my @paras = (); foreach (@content) { # add a page break starting from the third head (since the # first is removed anyway, and we don't want to start a new # page on the very first page) if (/^=head/) { $count++; if ($count > 2) { push @paras, qq{=for html }; } } push @paras, $_; } my $content = join "\n\n", @paras; $self->{content} = \$content; } 1; __END__ =head1 NAME C