#!/usr/bin/env perl use Modern::Perl; ## script to generate a single PDF file with all POD documentation ## Based on https://gist.github.com/wki/2277444 BEGIN { if (@ARGV != 2) { print STDERR "usage: $0 DIR OUTPUT\n"; exit 1; } } { # a simple class that uses App::pod2pdf to create pdfs containing many pod files # The hierarchical outline is generated on the fly while traversing directories package MultiPDF; use Moose; use Path::Class; use App::pod2pdf; has parser => ( is => 'ro', isa => 'App::pod2pdf', lazy => 1, default => sub { App::pod2pdf->new }, ); has pdf => ( is => 'ro', isa => 'PDF::API2', lazy => 1, builder => '_build_pdf', ); sub _build_pdf { my $self = shift; $self->parser->{pdf},; } sub process_file { my $self = shift; my $file = shift; say "processing file: $file"; $self->parser->parse_from_file($file->stringify); $self->parser->formfeed; return $self; } sub process_dir { my $self = shift; my $dir = Path::Class::Dir->new(shift); my %structure; # { _outline => PDF::API2::Outline } $dir->recurse( depthfirst => 1, callback => sub { my $file = shift; return if !-f $file || $file->basename !~ m{[.](?:pm|pod|pl) \z}xms; ## Look for POD tags to skip files without documentation my $fh = $file->open or die "Failed to open " . $file->basename; my $has_pod = 0; while (<$fh>) { $has_pod = 1 if (/^=head1/); } close $fh; return unless ($has_pod); my $nr_pages = $self->pdf->pages; $self->process_file($file); my $name = $file->basename; $name =~ s{[.]\w+ \z}{}xms; my $tree = \%structure; my $outline = $structure{_outline} ||= $self->pdf->outlines->outline; foreach my $part (grep { $_ ne '.' } $file->relative($dir)->dir->dir_list, $name) { $tree = $tree->{$part} ||= { _outline => $outline->outline }; $outline = $tree->{_outline}; $outline->title($part); } $outline->dest($self->pdf->openpage($nr_pages)); } ); return $self; } sub print { my $self = shift; $self->parser->output; } sub save_as { my $self = shift; my $path = shift; $self->pdf->saveas($path); } } MultiPDF->new->process_dir($ARGV[0])->save_as($ARGV[1]);