package Pod::HtmlPsPdf::Chapter; use strict; use Pod::HtmlPsPdf::Html (); use Pod::HtmlPsPdf::Common (); use Pod::HtmlPsPdf::Config (); my $config = Pod::HtmlPsPdf::Config->new(); ######## sub new{ my $class = shift; # book object my $book_obj = shift; my ($file_name, $src_root, $src_file, $verbose, $doc_root, $curr_page, $curr_page_index, $prev_page, $next_page) = @_; # extract the base name # Note that this must match Book.pm pod_newer_split() my ($base_name) = ($file_name =~ /^(.+)\.pod$/); # make it html ext if it was a pod $file_name =~ s/\.pod$/.html/; my $self = bless { book_obj => $book_obj, base_name => $base_name, file_name => $file_name, src_file => $src_file, src_root => $src_root, verbose => $verbose, curr_page => $curr_page, curr_page_index => $curr_page_index, prev_page => $prev_page, next_page => $next_page, doc_root => $doc_root, content => [], title => '', body => '', index => '', change_time_stamp => '', }, ref($class)||$class; # read the file and attributes $self->get_pod_file(); return $self; } # end of sub new # you can only retrieve data from this class, you cannot modify it. ############## sub get_param{ my $self = shift; return () unless @_; return unless defined wantarray; my @values = map {defined $self->{$_} ? $self->{$_} : ''} @_; return wantarray ? @values : $values[0]; } # end of sub get_param # read the file set the content and attibutes ############# sub get_pod_file{ my $self = shift; my $src_file = $self->{src_file}; Pod::HtmlPsPdf::Common::read_file($src_file,$self->{content}); # file change timestamp my ($mon,$day,$year) = (localtime ( (stat($src_file))[9] ) )[4,3,5]; $self->{change_time_stamp} = sprintf "%02d/%02d/%04d", ++$mon,$day,1900+$year; } # end of sub get_pod_file =item podify_items() podify_items(\@pars); Podify text to represent items in pod, e.g: 1 Some text from item Item1 2 Some text from item Item2 becomes: =over 4 =item 1 Some text from item Item1 =item 2 Some text from item Item2 =back podify_items() accepts 'C<*>' and digits as bullets podify_items() receives a ref to array of paragraphs as a parameter and modifies it. Nothing returned. =cut ################# sub podify_items{ my $self = shift; # tmp result my @pars = (); my $items = 0; foreach (@{$self->{content}}) { # is it an item? if (s/^(\*|\d+)\s+/=item $1\n\n/) { $items++; # first time insert the =over pod tag push @pars, "=over 4" if $items == 1; push @pars, split /\n\n/, $_; } else { # comlete the =over =item =back tag push @pars, "=back" if $items; push @pars, $_; # not a tag item $items = 0; } } # end of foreach (@$r_pars) # update the content @{$self->{content}} = @pars; } # end of sub podify_items # convert POD => HTML ############# sub pod2html{ my $self = shift; my @podpath = qw(.); my $book_obj = $self->{book_obj}; my ($rh_main_toc,$rh_valid_anchors, $rh_links_to_check) = $self->{book_obj}->get_param(qw(rh_main_toc rh_valid_anchors rh_links_to_check)); # print "###: $rh_valid_anchors, $rh_links_to_check\n"; # @content enters as pod, when returns - it's html Pod::HtmlPsPdf::Html::pod2html(\@podpath, $self->{src_root}, $self->{doc_root}, $self->{verbose}, $self->{content}, $rh_main_toc, $self->{curr_page}, $self->{curr_page_index}, $rh_valid_anchors, $rh_links_to_check ); # print "###: $rh_valid_anchors, $rh_links_to_check\n"; } # end of sub pod2html # splits the content into parts like title, index, body ############# sub parse_html{ my $self = shift; my $content = join "", @{$self->{content}}; # extract the body my ($title) = ($content =~ m|(.*)|si); my ($body) = ($content =~ m|]*>(.*)|si); $title ||= ''; $body ||= ''; # extract index my $index = $body =~ s|(.*)||si ? $1 : ''; # remove first header $body =~ s|||si; # add a left colour bar for
 sections
  $body =~ 
    s{
      
(.*?)
} {
 
$1
}gsix; $self->{title} = $title || ''; $self->{body} = $body || ''; $self->{index} = $index || ''; # for (qw(title index)) { # print "\n" x 3, "$_ :\n",$self->{$_},"\n"; # } # exit; } # end of sub parse_html # writes an html file ################## sub write_html_file{ my $self = shift; # read the template page my $template = $config->get_param('tmpl_page_html'); my @page_tmpl = (); Pod::HtmlPsPdf::Common::read_file($template,\@page_tmpl); # convert $self->template2release(\@page_tmpl); ### apply html version specific changes # # add the for each para # my $anchor_count = 0; # for (@page_tmpl){ # s|\n

\n|qq{\n

\n}|seg # } # add the links to #toc, before the


tags. But skip the first #
tgas, so we will start the replace after the TOC itself. my $after_toc = 0; for (@page_tmpl){ $after_toc = 1 if !$after_toc and m||i; next unless $after_toc; s|
|[ TOC ]\n
|sgi } # write the file my $rel_root = $config->get_param('rel_root'); Pod::HtmlPsPdf::Common::write_file("$rel_root/$self->{file_name}",\@page_tmpl); } # end of sub write_html_file # writes an html file for the later PS generation ################## sub write_ps_html_file{ my $self = shift; # read the template page my $template = $config->get_param('tmpl_page_ps'); my @page_tmpl = (); Pod::HtmlPsPdf::Common::read_file($template,\@page_tmpl); # convert $self->template2release(\@page_tmpl); ### apply html PS version specific changes for (@page_tmpl){ if ($Pod::HtmlPsPdf::RunTime::options{slides_mode}) { # create the page breakers for slides s|
|
|gsi; } else { # remove the
tags s|
||gsi; } # bump up the $digit in the by one to create a # nice structured PS/PDF, must skip the first

standing for # the name of the chapter s|(|$1.($2+1).">"|egsi; } # write the file my $ps_root = $config->get_param('ps_root'); Pod::HtmlPsPdf::Common::write_file("$ps_root/$self->{file_name}",\@page_tmpl); } # end of sub write_ps_html_file # convert the template into the release version # input: ref to template array ################### sub template2release{ my $self = shift; my $ra_tmpl = shift; my %replace_map = ( DOC_ROOT => $self->{doc_root}, PREVPAGE => ($self->{prev_page} ? qq{Prev} : '' ), NEXTPAGE => ($self->{next_page} ? qq{Next} : '' ), TITLE => $self->{title}, INDEX => $self->{index}, BODY => $self->{body}, MODIFIED => $self->{change_time_stamp}, ); for (@{$ra_tmpl}){ s/\[(\w+)\]/$replace_map{$1}/g } } # end of sub template2release # writes a split html files for easier searching if the original html # is too big # # note that this function destroyes all the parsed structures, if you # intend to make a use of them later, consider using the copy instead. # ################## sub write_split_html_files{ my $self = shift; print "+++ Making split\n" if $Pod::HtmlPsPdf::RunTime::options{verbose}; # prepare directory my $split_root = $config->get_param('split_root'); my $split_base_dir = "$split_root/".$self->{base_name}; my $dir_mode = $config->get_param('dir_mode'); mkdir $split_base_dir, $dir_mode unless -d $split_base_dir; # read the template page my $template = $config->get_param('tmpl_page_split_html'); my @page_tmpl = (); Pod::HtmlPsPdf::Common::read_file($template,\@page_tmpl); ### parse html ### # 1. parse index # 2. parse body ### parse index ### ######################################### # the datastructure we are going to build # # $node->[$idx_link]->$ # $node->[$idx_level]->$ # $node->[$idx_parent]->$ # $node->[$idx_kids]->[] ######################################### my $root_anchor = 'index.html'; my @parents = ($root_anchor); my @keys = qw(link level parent kids); my %keys = (); @keys{@keys} = 0..$#keys; my %index = (); my $level = 0; # initialize the root entry $index{$root_anchor}->[$keys{link}] = qq{
  • }.$self->{title}.qq{}; $index{$root_anchor}->[$keys{level}] = $level; $index{$root_anchor}->[$keys{parent}] = ''; $index{$root_anchor}->[$keys{kids}] = []; while ( $self->{index} =~ /(.*\n)/g ){ local $_ = $1 || ''; # assumption: there can be one tag/item per line! chomp; # start of level if (m|
      |i){ $level++; next; } # end of level if (m|
    |i){ $level--; pop @parents; next; } next unless m|
  • |i; s/A HREF="#(\w+)"/A HREF="$1.html"/i; my $anchor = $1 || ''; warn("!!! No anchor found"), next unless $anchor; # make it html $anchor .= '.html'; $index{$anchor}->[$keys{link}] = $_; $index{$anchor}->[$keys{level}] = $level; my $parent_anchor = $parents[$level-1]; $index{$anchor}->[$keys{parent}] = $parent_anchor; splice @parents,$level,1,$anchor; # now update parent's kids field by pushing yourself to the end push @{ $index{$parent_anchor}->[$keys{kids}] }, $anchor; # init your kids $index{$anchor}->[$keys{kids}] = []; } # end of while ( $self->{index} =~ /(.*\n)/g ) ### parse body ### # create the split version: my %sections = (); my $prev_anchor = ''; my %item = (); while ( $self->{body} =~ /(.*\n)/g ){ my $line = $1; if ( $line =~ m|([^>]+){body} =~ /(.*)/g ){ # last item add (cannot be added in while loop) if (%item) { # curr anchor is the 'next' for the 'prev' item $item{next} = ''; # store it away %{$sections{$item{anchor}}} = %item; # reset the prev item %item = (); } # end of if (%item) ### generate split html pages ### my $pod_title = $self->{title}; for my $sec (keys %sections) { my $anchor = "$sec.html"; ### prepare the top index with parents dynasty only ### my $top_index = ''; my $parent_anchor = $anchor; my @parents = (); while ($parent_anchor = $index{$parent_anchor}->[$keys{parent}]) { unshift @parents, $parent_anchor; } my @close_top_index = (); # top level { local $_ = $anchor; $top_index .= ""; } for (@parents,$anchor) { my $level = $index{$_}->[$keys{level}] + 1; $level *= 4; $top_index .= ' ' x $level . "
      \n"; if ($_ eq $anchor) { my $title = $sections{$sec}->{title}; $top_index .= qq{

      $title

      \n}; } else { $top_index .= $index{$_}->[$keys{link}] . "\n"; } unshift @close_top_index,' ' x $level ."
    "; } $top_index .= join "\n",@close_top_index,"\n"; ### generate sub-index for this section ### my $level = $index{$anchor}->[$keys{level}]; my @close_bot_index = (); my $bot_index = "\n"; for (0..$level) { $bot_index .= " " x $level . "
      \n"; } $bot_index .= nested_kids(\%index,$anchor,$keys{kids},$keys{link}); for (0..$level) { $bot_index .= " " x $level . "
    \n"; } # recursive function ################ sub nested_kids{ my $r_index = shift; my $anchor = shift; my $kids_key = shift; my $link_key = shift; my @kids = @{$r_index->{$anchor}->[$kids_key]}; return '' unless @kids; my $subidx .= "
      \n"; for my $kid_anchor (@kids){ $subidx .= $r_index->{$kid_anchor}->[$link_key] . "\n"; $subidx .= nested_kids($r_index,$kid_anchor,$kids_key,$link_key); } $subidx .= "
    \n"; return $subidx; } # end of sub nested_kids # set values for template conversion. # these destroy the original values $self->{full_title} = $top_index; $self->{title} = $sections{$sec}->{title}; $self->{body} = $sections{$sec}->{content}; # fix internal links to work with subdirs created by the split version $self->{body} =~ s|A HREF="(?:[\./]*)?([^.]+)\.html#?"|A HREF="../$1/index.html"|g; $self->{body} =~ s|A HREF="(?:[\./]*)?([^.]+)\.html#(.+?)"|A HREF="../$1/$2.html"|g; # append the submenu $self->{body} .= $bot_index; # convert my @tmpl_copy = @page_tmpl; $self->split_template2release(\@tmpl_copy); # write the section as a file my $filename = "$split_base_dir/".$sections{$sec}->{anchor}.".html"; Pod::HtmlPsPdf::Common::write_file($filename,\@tmpl_copy); } # end of for (keys %sections) ### now write the index.html for original file ### # correct the links $self->{index} =~ s/A HREF="#([^\"]*)"/A HREF="$1.html"/g; $self->{body} = $self->{index}."\n
    "; $self->{full_title} = qq{

    $pod_title

    \n}; $self->{title} = $pod_title; my @tmpl_copy = @page_tmpl; $self->split_template2release(\@tmpl_copy); # write the file my $filename = "$split_base_dir/index.html"; Pod::HtmlPsPdf::Common::write_file($filename,\@tmpl_copy); } # end of sub write_split_html_files # convert the template into the release version # input: ref to template array ################### use File::Basename; sub split_template2release{ my $self = shift; my $ra_tmpl = shift; my $full_file_name = $self->{curr_page}; #$full_file_name =~ s|^.*?(\w+)\.\w+$|$1|; # Just want the basename, correct? Is it always .pod? $full_file_name = $1 if $full_file_name =~ m!([^/]+)\.\w+$!; my %replace_map = ( PAGE => $full_file_name, DOC_ROOT => $self->{doc_root}, PREVPAGE => ($self->{prev_page} ? qq{Prev} : '' ), NEXTPAGE => ($self->{next_page} ? qq{Next} : '' ), FULLTITLE=> $self->{full_title}, TITLE => $self->{title}, # INDEX => $self->{index}, BODY => $self->{body}, MODIFIED => $self->{change_time_stamp}, ); for (@{$ra_tmpl}){ s/\[(\w+)\]/$replace_map{$1}/g } } # end of sub split_template2release 1; __END__