Pod-Tree-1.17/000700 023614 023614 00000000000 11407641713 013355 5ustar00swmcdswmcd000000 000000 Pod-Tree-1.17/Changes000644 023614 023614 00000015577 11407600513 014672 0ustar00swmcdswmcd000000 000000 Revision history for Perl extension Pod::Tree 1.17 2010 Jun 21 pods2html - quote paths in REs 1.16 2009 Apr 10 Pod::Tree::HTML - fix to work with IO::File 1.13 (RT 34755, 38307) mod2html - added to distribution Makefile.PL - added all required modules to PREREQ_PM 1.15 2007 Jun 24 Rename pod2html -> podtree2html (RT 18742) Pod::Tree::HTML - Changed destination resolution to accept a scalar reference, or anything with a 'print' method. (RT 12335) podtree2html, pods2html - documented HTML elements for CSS rules (RT 6118) pod.css - add example style sheet 1.14 2007 Jun 12 Pod::Tree::HTML - remove use vars qw(&isa); (RT 14530) - document translate() error conditions (RT 12336) Makefile.PL - add Text::Template prerequisite (RT 26440) 1.13 2007 Apr 06 Pod::Tree - rename the Stream package Pod::Tree::HTML - change the X<> markup to render as empty, per the perlpod manpage - rename the BitBucket package - add template support Pod::Tree:PerlUtil - handle malformed NAME paragraphs more gracefully pod2html - add template support pods2html - add template support 1.12 2006 Apr 22 Pod::Tree::PerlBin - ignore non-existant directories on $PATH - protect File::Find::find from empty directory list Pod::Tree:PerlFunc - find the pod/ directory under either perl/ or perl/lib/ (Win32 issue) Pod::Tree::PerlLib - increase default col_width to 30 Pod::Tree:PerlTop - find the pod/ directory under either perl/ or perl/lib/ (Win32 issue) Pod::Tree:PerlUtil - clean up whitespace in module names and descriptions pods2html - recursion check compares absolute paths instead of inodes (Win32 issue) t/pods2html.t - use rmtree instead of system "rm -r" (Win32 issue) 1.11 2004 Oct Pod::Tree - recognize blank lines per perlpodspec - added support for =head3 and =head4 commands - recognize \n, \r, \r\n line endings - separate paragraphs on blank (/^\s*$/) lines Pod::Tree::HTML - added support for =head3 and =head4 commands - expose the emit_toc and emit_body methods - drop the tags in the TOC. It was the easiest way to fix the nesting problem. - added { empty => 1 } option Pod::Tree::Node - added support for =head3 and =head4 commands - consolidate consecutive verbatim paragraphs pods2html - added --module option - get depth from module name, not file path - added --empty option t/pod2html.t t/pods2html.t - invoke $Config{perlpath}, not 'perl' GENERAL - Set default BGCOLOR to ffffff - Removed all the use 5.x; require 5.x statements - reviewed all the copyright notices 1.10 2003 Jan Pod::Tree - documentation typos - dropped the require 5.6.0; statement Pod::Tree::HTML - added support for $link_map->url methods - deprecated $link_map->map methods - exposed escape_2396 and assemble_url methods - documentation Pod::Tree::Node - documentation typos Pod::Tree::Pod - dropped the require 5.6.0; statement t/mapper.t t/mapper.d - created 1.09 2002 Jul Makefile.PL - traded in ABSTRACT for ABSTRACT_FROM Pod::Tree::Node - recoded _unescape_text to use Pod::Escapes - expand the HTTP domain to include e.g. mailto: Pod::Tree::Pod - changed _escape to handle non-ASCII chars Pod::Tree::PerlUtils - Handle module names that contain dashes Pod::Tree::HTML - Handle PODs that have "name--description" with multiple dashes - Change default bgcolor to white - added css => $url option perl2html - traded in hard-coded /:/ for /$Config{path_sep}/ pod2html - added -css URL option pods2html - added -css URL option - fixed recursion check on Win32 t/pod2html.d t/pod2html.t - created t/pods2html.t - enable some tests on Win32 - wrote RDiff() to ignore CVS directories 1.08 2001 May 30 t/pods2html.t - skip test on Win32 1.07 2001 May 29 Makefile.PL - added EXE_FILES key - added PREREQ_PM key Pod::Tree - preserve paragraph endings - preserve non-POD content - added has_pod() method Pod::Tree::Node - added code() and is_code() - added get_brackets() method - added get_raw() method - added clone() method - added set_filename()/get_filename() methods - added get_domain() and support for L - carry =pod and =cut in command nodes - SplitBar() split(/\|/,,2) to protect links with a verbar Pod::Tree:HTML - fixed load_paragraphs() call in resolve_source() - added depth option - render =for image foo.gif as - rewhacked _emit_link to support target domains Pod::Tree::Pod - correctly reconstructs L<> markups Pod::Tree::PerlDist - added perl* links for the README.* files Pod::Tree::PerlFunc - fixed ShiftItems() to handle the getpw* items in perlfunc.pod Pod::Tree::PerlTop - added _get_dist_links() to pick up the README.* files pods2html - fixed relative links - don't translate foo.pm if foo.pod exists - works if HTMLDir is a subdir of PodDir - create HTMLDir with File::Path::mkpath t/ - moved all the test files into .d/ directories 1.06 2000 Oct 17 Added Pod::Tree::Pod Pod::Tree::Node - fixed SpitBar() 1.05 2000 Oct 12 Pod::Tree::Node - Added $VERSION to quiet CPAN.pm 1.04 2000 Oct 11 Pod::Tree::HTML - Added $VERSION to quiet CPAN.pm 1.03 2000 Oct 09 - Cleaned up $VERSION variables (we hope) Pod::Tree::HTML - fixed \$pod bug in new() Pod::Tree::PerlBin - fixed xsubpp bug Pod::Tree::PerlFunc - fixed to handle do() properly Pod::Tree::PerlPod - compress whitespace in description lines pods2html - Fixed to handle relative paths perl2html - Fixed to handle relative paths 1.02 2000 May 19 Pod::Tree::Node - added support for x<<>> style markups Pod::Tree::PerlFunc - added
tags to lists in perlfunc.pod sub-pages - sort function names within alphebetical index paragraphs Pod::Tree::PerlLib - scan for .pod files under @INC - added stop_file list Pod::Tree::PerlPod - don't convert PODs under /ext/ 1.01 2000 Mar 11 Pod::Tree - added limit => n option - added get_root(), set_root() - added push(), pop() - added walk() Pod::Tree::Node - allow text items to begin with * or number - parse L as "sec tion" in this man page - close line breaks in L<> markups Pod::Tree::HTML - emit

and tags - suppress

markups from a single ordinary list item - changed _escape_text() to conform to RFC 2369 - added linkMap => \&linkMap option - added link() constructor - close line breaks in markups - emit anchors for
items in
lists - accept =for HTML or =for html - emit

around =for HTLM paragraphs Makefile.PL - add DISTNAME key pod2html - fixed the shebang pods2html - fixed the shebang - added --index option Added - Pod::Tree::PerlBin - Pod::Tree::PerlDist - Pod::Tree::PerlFunc - Pod::Tree::PerlLib - Pod::Tree::PerlMap - Pod::Tree::PerlPod - Pod::Tree::PerlTop - Pod::Tree::PerlUtil - perl2html - ToDo 1.00 1999 Jun 23 - original version; created by h2xs 1.18 mit anchors for
items in
lists - accept =for HTML or =for html - emit

around =for HTLM paragraphs Makefile.Pod-Tree-1.17/MANIFEST000644 023614 023614 00000010305 11167777321 014527 0ustar00swmcdswmcd000000 000000 Changes MANIFEST META.yml Makefile.PL README ToDo ToDo.Not lib/Pod/Tree.pm lib/Pod/Tree/HTML.pm lib/Pod/Tree/Node.pm lib/Pod/Tree/PerlBin.pm lib/Pod/Tree/PerlDist.pm lib/Pod/Tree/PerlFunc.pm lib/Pod/Tree/PerlLib.pm lib/Pod/Tree/PerlMap.pm lib/Pod/Tree/PerlPod.pm lib/Pod/Tree/PerlTop.pm lib/Pod/Tree/PerlUtil.pm lib/Pod/Tree/Pod.pm mod2html perl2html pod.css pods2html podtree2html skeleton t/cut.d/cut.pod t/cut.d/file0.exp t/cut.d/file1.exp t/cut.d/fileU.exp t/cut.d/string0.exp t/cut.d/string1.exp t/cut.d/stringU.exp t/cut.t t/html.d/base.exp t/html.d/body.exp t/html.d/cut.exp t/html.d/cut.pod t/html.d/depth.exp t/html.d/empty.pod t/html.d/for.exp t/html.d/for.pod t/html.d/link.exp t/html.d/link.pod t/html.d/list.exp t/html.d/list.pod t/html.d/paragraph.exp t/html.d/paragraph.pod t/html.d/sequence.exp t/html.d/sequence.pod t/html.d/toc.exp t/html.t t/load.d/list.exp t/load.d/list.pod t/load.t t/mapper.d/cut.exp t/mapper.d/cut.pod t/mapper.d/for.exp t/mapper.d/for.pod t/mapper.d/link.exp t/mapper.d/link.pod t/mapper.d/list.exp t/mapper.d/list.pod t/mapper.d/paragraph.exp t/mapper.d/paragraph.pod t/mapper.d/sequence.exp t/mapper.d/sequence.pod t/mapper.t t/option.d/base.pod t/option.d/baseD.exp t/option.d/baseU.exp t/option.d/hr.pod t/option.d/hr0.exp t/option.d/hr1.exp t/option.d/hr2.exp t/option.d/hr3.exp t/option.d/toc.pod t/option.d/toc0.exp t/option.d/toc1.exp t/option.t t/pod.d/cut.pod t/pod.d/for.pod t/pod.d/link.pod t/pod.d/list.pod t/pod.d/paragraph.pod t/pod.d/sequence.pod t/pod.t t/pod2html.d/cut.exp t/pod2html.d/cut.exp_t t/pod2html.d/cut.exp_tv t/pod2html.d/cut.pod t/pod2html.d/for.exp t/pod2html.d/for.exp_t t/pod2html.d/for.exp_tv t/pod2html.d/for.pod t/pod2html.d/link.exp t/pod2html.d/link.exp_t t/pod2html.d/link.exp_tv t/pod2html.d/link.pod t/pod2html.d/list.exp t/pod2html.d/list.exp_t t/pod2html.d/list.exp_tv t/pod2html.d/list.pod t/pod2html.d/paragraph.exp t/pod2html.d/paragraph.exp_t t/pod2html.d/paragraph.exp_tv t/pod2html.d/paragraph.pod t/pod2html.d/sequence.exp t/pod2html.d/sequence.exp_t t/pod2html.d/sequence.exp_tv t/pod2html.d/sequence.pod t/pod2html.d/template.txt t/pod2html.d/values.pl t/pod2html.t t/pods2html.d/empty_exp/A.html t/pods2html.d/empty_exp/A/B.html t/pods2html.d/empty_exp/C.html t/pods2html.d/empty_exp/C/D.html t/pods2html.d/empty_exp/C/D/E.html t/pods2html.d/empty_exp/empty.html t/pods2html.d/html_exp/A.html t/pods2html.d/html_exp/A/B.html t/pods2html.d/html_exp/C.html t/pods2html.d/html_exp/C/D.html t/pods2html.d/html_exp/C/D/E.html t/pods2html.d/html_exp_t/A.html t/pods2html.d/html_exp_t/A/B.html t/pods2html.d/html_exp_t/C.html t/pods2html.d/html_exp_t/C/D.html t/pods2html.d/html_exp_t/C/D/E.html t/pods2html.d/html_exp_tv/A.html t/pods2html.d/html_exp_tv/A/B.html t/pods2html.d/html_exp_tv/C.html t/pods2html.d/html_exp_tv/C/D.html t/pods2html.d/html_exp_tv/C/D/E.html t/pods2html.d/pod/A.pm t/pods2html.d/pod/A.pod t/pods2html.d/pod/A/B.pod t/pods2html.d/pod/C.pod t/pods2html.d/pod/C/D.pod t/pods2html.d/pod/C/D/E.pod t/pods2html.d/pod/empty.pod t/pods2html.d/podR/A.pm t/pods2html.d/podR/A.pod t/pods2html.d/podR/A/B.pod t/pods2html.d/podR/C.pod t/pods2html.d/podR/C/D.pod t/pods2html.d/podR/C/D/E.pod t/pods2html.d/podR_exp/A.pm t/pods2html.d/podR_exp/A.pod t/pods2html.d/podR_exp/A/B.pod t/pods2html.d/podR_exp/C.pod t/pods2html.d/podR_exp/C/D.pod t/pods2html.d/podR_exp/C/D/E.pod t/pods2html.d/podR_exp/HTML/A.html t/pods2html.d/podR_exp/HTML/A/B.html t/pods2html.d/podR_exp/HTML/C.html t/pods2html.d/podR_exp/HTML/C/D.html t/pods2html.d/podR_exp/HTML/C/D/E.html t/pods2html.d/template.txt t/pods2html.d/values.pl t/pods2html.t t/template.t t/template.d/cut.exp t/template.d/cut.pod t/template.d/for.exp t/template.d/for.pod t/template.d/link.exp t/template.d/link.pod t/template.d/list.exp t/template.d/list.pod t/template.d/paragraph.exp t/template.d/paragraph.pod t/template.d/sequence.exp t/template.d/sequence.pod t/template.d/template.txt t/tree.d/code.pm t/tree.d/cut.exp t/tree.d/cut.pod t/tree.d/empty.pod t/tree.d/for.exp t/tree.d/for.pod t/tree.d/link.exp t/tree.d/link.pod t/tree.d/list.exp t/tree.d/list.pod t/tree.d/paragraph.exp t/tree.d/paragraph.pod t/tree.d/sequence.exp t/tree.d/sequence.pod t/tree.t META.yml Module meta-data (added by MakeMaker) exp t/template.d/list.pod t/template.d/paragraph.exp t/template.d/paragraph.pod t/template.d/sequence.exp t/template.d/sequence.pod t/template.d/template.txt t/tree.d/code.pm t/tree.d/cut.exp t/tree.d/cut.pod t/tree.d/empty.pod t/tree.d/for.exp t/tree.d/for.pod t/tree.d/link.exp t/tree.d/link.pod t/tree.d/list.expPod-Tree-1.17/META.yml000600 023614 023614 00000001163 11407641713 014631 0ustar00swmcdswmcd000000 000000 --- #YAML:1.0 name: Pod-Tree version: 1.17 abstract: Create a static syntax tree for a POD license: ~ generated_by: ExtUtils::MakeMaker version 6.32 distribution_type: module requires: File::Find: 1 HTML::Stream: 1.49 IO::File: 1 IO::String: 1 Pod::Escapes: 1.02 Text::Template: 1 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.2.html version: 1.2 author: - Steven McDougall (swmcd@world.std.com) ree for a POD license: ~ generated_by: ExtUtils::MakeMaker version 6.32 distribution_type: module requires: File::Find: 1 HTML::Stream: 1.49 IO::File: 1 IO::String: 1 Pod::Escapes: 1.02 Text::Template: 1 meta-spec: url: http://moduPod-Tree-1.17/Makefile.PL000644 023614 023614 00000001672 11170004150 015330 0ustar00swmcdswmcd000000 000000 use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile(NAME => 'Pod::Tree', VERSION_FROM => 'lib/Pod/Tree.pm', # finds $VERSION DISTNAME => 'Pod-Tree', ($] >= 5.005 ? (ABSTRACT_FROM => 'lib/Pod/Tree.pm', AUTHOR => 'Steven McDougall (swmcd@world.std.com)') : ()), clean => { FILES => "t/pod2html.d/*.html* t/pods2html.d/A t/pods2html.d/html_act* t/pods2html.d/podR/HTML t/*/*.act lib/Pod/Tree/*~" }, dist => { COMPRESS => 'gzip --best', SUFFIX => '.gz' }, EXE_FILES => [qw(mod2html podtree2html pods2html perl2html)], PREREQ_PM => { File::Find => 1, HTML::Stream => 1.49, IO::File => 1, IO::String => 1, Pod::Escapes => 1.02, Text::Template => 1 }, ); => { FILES => "t/pod2html.d/*.html* t/pods2html.d/A t/pods2html.dPod-Tree-1.17/README000644 023614 023614 00000004267 11407600242 014250 0ustar00swmcdswmcd000000 000000 Pod::Tree - Tree-based POD parser DESCRIPTION Modules Pod::Tree parses a POD into a static syntax tree. Applications walk the tree to recover the structure and content of the POD. Pod::Tree::HTML walks a Pod::Tree and translates it to HTML. Pod::Tree::Pod walks a Pod::Tree and translates it back to POD. Pod::Tree::Perl* translate the PODs in the Perl distribution to HTML. Executables pod2html translates a POD file to an HTML file. pods2html walks a directory tree, translates all the PODs that it finds into HTML files, and puts the HTML files into a parallel directory tree. perl2html translates the PODs in the Perl distribution to HTML PREREQUISITES Perl 5 File::Find HTML::Stream IO::File IO::String Pod::Escapes Text::Template HOW TO BUILD AND INSTALL perl Makefile.PL make make test make install You may see a message like Warning: prerequisite HTML::Stream 1.49 not found. You can ignore this, provided that you actually have HTML::Stream 1.49 or later installed. TODO See the ToDo and ToDo.Not files. Send suggestions, bugs, etc. to swmcd@world.std.com, or open a ticket at http://rt.cpan.org/Dist/Display.html?Queue=Pod-Tree ACKNOWLEDGMENTS Paul Bettinger Sean M. Burke Brad Choate Havard Eidnes Rudi Farkas Paul Gibeault Jay Hannah Martin Hans Paul Hawkins Jost Krieger Marc A. Lehmann Jonas Liljegren Thomas Linden Johan Lindstrom Terry Luedtke Rob Napier Kate L Pugh Christopher Shalah Blair Sutton Johan Vromans COPYRIGHT Copyright (c) 1999-2010 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. s Liljegren Thomas Linden Johan Lindstrom Terry Luedtke Rob Napier Kate L Pugh Christopher Shalah Blair Sutton Johan Vromans Thomas Linden Johan Lindstrom Terry Luedtke Rob Napier Kate L Pugh Christopher Shalah Blair Sutton Johan Vromans = 5.005 ? key from Makefile.PL I had a complaint that this syntax breaks on Cygwin, but I can no longer contact the person who reported it to confirm the problem. 3. Generate an index and TOC in the sytle of Marek::Pod::Html This is - beyond the scope of POD - beyond the scope of Pod::Tree 4. XHTML support I've had a request for XHTML compliance. I thought this would be easy - downcase all the tags - maybe a few other tweaks However, Pod::Tree::HTML uses HTML::Stream to emit the HTML, so doing this means either hacking or replacing that module. I don't want to do the first, and the second is a big job. 5. Solaris problem A test failure on Solaris that I don't understand and probably can't reproduce. This may be another example of the $Config{perlpath} vs. perl problem. 6. Complaint of -w warnings on empty paragraphs I can't reproduce this, and I haven't been able to contact the reporter. 7. HTML classes for CSS I have a request to specify HTML classes to support CSS. It's not hard to do, but it bulks up both the code and the generated HTML, and it isn't clear that it gains anything. Style sheets can use HTML element names as selectors. POD is so simple that I don't think there are any HTML elements that are used in more than one context. erlpath} vs. perl problem. 6. Complaint of -w warnings on empty paragraphs I can't reproduce this, and I haven't been able to contact the reporter. 7. HTML classes for CSS I have a request to specify HTML classes to support CSS. It's not hard to do, but it bulks up both the code and the generated HTML, and it isn't clear that it gains anything. Style sheets can use HTML element names as selectors. POD is so simple that I don't think there are any HTML elements tPod-Tree-1.17/lib/000700 023614 023614 00000000000 11407641712 014122 5ustar00swmcdswmcd000000 000000 Pod-Tree-1.17/lib/Pod/000700 023614 023614 00000000000 11407641713 014645 5ustar00swmcdswmcd000000 000000 Pod-Tree-1.17/lib/Pod/Tree/000700 023614 023614 00000000000 11407641713 015544 5ustar00swmcdswmcd000000 000000 Pod-Tree-1.17/lib/Pod/Tree/HTML.pm000644 023614 023614 00000063762 11170002031 016653 0ustar00swmcdswmcd000000 000000 # Copyright (c) 1999-2007 by Steven McDougall. This module is free # software; you can redistribute it and/or modify it under the same # terms as Perl itself. use strict; use HTML::Stream; use IO::File; use IO::String; use Pod::Tree; use Text::Template; package Pod::Tree::BitBucket; sub new { bless {}, shift } sub AUTOLOAD { shift } package Pod::Tree::StrStream; sub new { my($class, $ref) = @_; if ($ref) { return bless $ref, $class } else { my $st = ''; return bless \$st, $class; } } sub print { my $st = shift; $$st .= join('', @_); } sub get { my $st = shift; my $s = $$st; $$st = ''; $s } package Pod::Tree::HTML; use constant BGCOLOR => '#ffffff'; use constant TEXT => '#000000'; our $VERSION = '1.10'; sub new { my($class, $source, $dest, %options) = @_; defined $dest or die "Pod::Tree::HTML::new: not enough arguments\n"; my $tree = _resolve_source($source); my($fh, $stream) = _resolve_dest ($dest , $tree, \%options); my $options = { bgcolor => BGCOLOR, depth => 0, hr => 1, link_map => Pod::Tree::HTML::LinkMap->new(), text => TEXT, toc => 1, }; my $HTML = { tree => $tree, root => $tree->get_root, stream => $stream, fh => $fh, text_method => 'text', options => $options, }; bless $HTML, $class; $HTML->set_options(%options); $HTML } sub _resolve_source { my $source = shift; my $ref = ref $source; local *isa = \&UNIVERSAL::isa; isa($source, 'Pod::Tree') and return $source; my $tree = new Pod::Tree; not $ref and $tree->load_file ( $source); isa($source, 'IO::File') and $tree->load_fh ( $source); $ref eq 'SCALAR' and $tree->load_string ($$source); $ref eq 'ARRAY' and $tree->load_paragraphs( $source); $tree->loaded or die "Pod::Tree::HTML::_resolve_source: Can't load POD from $source\n"; $tree } sub _resolve_dest { my($dest, $tree, $options) = @_; $tree->has_pod or $options->{empty} or return (undef, new Pod::Tree::BitBucket); local *isa = \&UNIVERSAL::isa; local *can = \&UNIVERSAL::can; isa($dest, 'HTML::Stream') and return (undef, $dest); isa($dest, 'IO::File' ) and return ($dest, new HTML::Stream $dest); can($dest, 'print' ) and return ($dest, new HTML::Stream $dest); if (ref $dest eq 'SCALAR') { my $fh = new IO::String $$dest; return ($fh, new HTML::Stream $fh); } if (ref $dest eq '' and $dest) { my $fh = new IO::File; $fh->open($dest, '>') or die "Pod::Tree::HTML::new: Can't open $dest: $!\n"; return ($fh, new HTML::Stream $fh); } die "Pod::Tree::HTML::_resolve_dest: Can't write HTML to $dest\n"; } sub set_options { my($html, %options) = @_; my($key, $value); while (($key, $value) = each %options) { $html->{options}{$key} = $value; } } sub get_options { my($html, @options) = @_; map { $html->{options}{$_} } @options } sub get_stream { shift->{stream} } sub translate { my($html, $template) = @_; if ($template) { $html->_template($template); } else { $html->_translate; } } sub _translate { my $html = shift; my $stream = $html->{stream}; my $bgcolor = $html->{options}{bgcolor}; my $text = $html->{options}{text}; my $title = $html->_make_title; my $base = $html->{options}{base}; my $css = $html->{options}{css}; $stream->HTML->HEAD; defined $title and $stream->TITLE->text($title)->_TITLE; defined $base and $stream->BASE(href => $base); defined $css and $stream->LINK(href => $css, type => "text/css", rel => "stylesheet"); $stream->_HEAD ->BODY(BGCOLOR => $bgcolor, TEXT => $text); $html->emit_toc; $html->emit_body; $stream->nl ->_BODY ->_HTML } sub _template { my ($html, $tSource) = @_; my $fh = $html->{fh}; my $sStream = new Pod::Tree::StrStream; $html->{stream} = new HTML::Stream $sStream; our $bgcolor = $html->{options}{bgcolor}; our $text = $html->{options}{text}; our $title = $html->_make_title; our $base = $html->{options}{base}; our $css = $html->{options}{css}; $html->emit_toc; our $toc = $sStream->get; $html->emit_body; our $body = $sStream->get; my $template = new Text::Template SOURCE => $tSource or die "Can't create Text::Template object: $Text::Template::ERROR\n"; $template->fill_in(OUTPUT => $fh) or die $Text::Template::ERROR; } sub _make_title { my $html = shift; my $title = $html->{options}{title}; defined $title and return $title; my $children = $html->{root}->get_children; my $node1; my $i = 0; for my $child (@$children) { is_pod $child or next; $i++ and $node1 = $child; $node1 and last; } $node1 or return undef; my $text = $node1->get_deep_text; ($title) = split m(\s+-), $text; $title or return undef; # to quiet -w $title =~ s(\s+$)(); $title } sub emit_toc { my $html = shift; $html->{options}{toc} or return; my $root = $html->{root}; my $nodes = $root->get_children; my @nodes = @$nodes; $html->_emit_toc_1(\@nodes); $html->{options}{hr} > 0 and $html->{stream}->HR; } sub _emit_toc_1 { my($html, $nodes) = @_; my $stream = $html->{stream}; $stream->UL; while (@$nodes) { my $node = $nodes->[0]; is_c_head2 $node and $html->_emit_toc_2 ($nodes), next; is_c_head1 $node and $html->_emit_toc_item($node ); shift @$nodes; } $stream->_UL; } sub _emit_toc_2 { my($html, $nodes) = @_; my $stream = $html->{stream}; $stream->UL; while (@$nodes) { my $node = $nodes->[0]; is_c_head1 $node and last; is_c_head2 $node and $html->_emit_toc_item($node); shift @$nodes; } $stream->_UL; } sub _emit_toc_item { my($html, $node) = @_; my $stream = $html->{stream}; my $target = $html->_make_anchor($node); $stream->LI->A(HREF => "#$target"); $html->_emit_children($node); $stream->_A; } sub emit_body { my $html = shift; my $root = $html->{root}; $html->_emit_children($root); } sub _emit_children { my($html, $node) = @_; my $children = $node->get_children; for my $child (@$children) { $html->_emit_node($child); } } sub _emit_siblings { my($html, $node) = @_; my $siblings = $node->get_siblings; if (@$siblings==1 and $siblings->[0]{type} eq 'ordinary') { # don't put

around a single ordinary paragraph $html->_emit_children($siblings->[0]); } else { for my $sibling (@$siblings) { $html->_emit_node($sibling); } } } sub _emit_node { my($html, $node) = @_; my $type = $node->{type}; for ($type) { /command/ and $html->_emit_command ($node); /for/ and $html->_emit_for ($node); /item/ and $html->_emit_item ($node); /list/ and $html->_emit_list ($node); /ordinary/ and $html->_emit_ordinary($node); /sequence/ and $html->_emit_sequence($node); /text/ and $html->_emit_text ($node); /verbatim/ and $html->_emit_verbatim($node); } } my %HeadTag = ( head1 => { 'open' => 'H1', 'close' => '_H1', level => 1 }, head2 => { 'open' => 'H2', 'close' => '_H2', level => 2 }, head3 => { 'open' => 'H3', 'close' => '_H3', level => 3 }, head4 => { 'open' => 'H4', 'close' => '_H4', level => 4 } ); sub _emit_command { my($html, $node) = @_; my $stream = $html->{stream}; my $command = $node->get_command; my $head_tag = $HeadTag{$command}; $head_tag or return; my $anchor = $html->_make_anchor($node); $html->_emit_hr($head_tag->{level}); my $tag; $tag = $head_tag->{'open'}; $stream->$tag()->A(NAME => $anchor); $html->_emit_children($node); $tag = $head_tag->{'close'}; $stream->_A->$tag(); } sub _emit_hr { my($html, $level) = @_; $html->{options}{hr} > $level or return; $html->{skip_first}++ or return; $html->{stream}->HR; } sub _emit_for { my($html, $node) = @_; my $interpreter = lc $node->get_arg; my $emit = "_emit_for_$interpreter"; $html->$emit($node) if $html->can($emit); } sub _emit_for_html { my($html, $node) = @_; my $stream = $html->{stream}; $stream->P; $stream->io->print($node->get_text); $stream->_P; } sub _emit_for_image { my($html, $node) = @_; my $stream = $html->{stream}; my $link = $node->get_text; $link =~ s(\s+$)(); $stream->IMG(src => $link); } sub _emit_item { my($html, $node) = @_; my $stream = $html->{stream}; my $item_type = $node->get_item_type; for ($item_type) { /bullet/ and do { $stream->LI(); $html->_emit_siblings($node); $stream->_LI(); }; /number/ and do { $stream->LI(); $html->_emit_siblings($node); $stream->_LI(); }; /text/ and do { my $anchor = $html->_make_anchor($node); $stream->DT->A(NAME => "$anchor"); $html->_emit_children($node); $stream->_A->_DT->DD; $html->_emit_siblings($node); $stream->_DD; }; } } my %ListTag = (bullet => { 'open' => 'UL', 'close' => '_UL' }, number => { 'open' => 'OL', 'close' => '_OL' }, text => { 'open' => 'DL', 'close' => '_DL' } ); sub _emit_list { my($html, $node) = @_; my($list_tag, $tag); # to quiet -w, see beloew my $stream = $html->{stream}; my $list_type = $node->get_list_type; $list_type and $list_tag = $ListTag{$list_type}; $list_tag and $tag = $list_tag->{'open'}; $tag and $stream->$tag(); $html->_emit_children($node); $list_tag and $tag = $list_tag->{'close'}; $tag and $stream->$tag(); } sub _emit_ordinary { my($html, $node) = @_; my $stream = $html->{stream}; $stream->P; $html->_emit_children($node); $stream->_P; } sub _emit_sequence { my($html, $node) = @_; for ($node->get_letter) { /I|B|C|F/ and $html->_emit_element($node), last; /S/ and $html->_emit_nbsp ($node), last; /L/ and $html->_emit_link ($node), last; /X/ and $html->_emit_index ($node), last; /E/ and $html->_emit_entity ($node), last; } } my %ElementTag = (I => { 'open' => 'I' , 'close' => '_I' }, B => { 'open' => 'B' , 'close' => '_B' }, C => { 'open' => 'CODE', 'close' => '_CODE' }, F => { 'open' => 'I' , 'close' => '_I' } ); sub _emit_element { my($html, $node) = @_; my $letter = $node->get_letter; my $stream = $html->{stream}; my $tag; $tag = $ElementTag{$letter}{'open'}; $stream->$tag(); $html->_emit_children($node); $tag = $ElementTag{$letter}{'close'}; $stream->$tag(); } sub _emit_nbsp { my($html, $node) = @_; my $old_method = $html->{text_method}; $html->{text_method} = 'text_nbsp'; $html->_emit_children($node); $html->{text_method} = $old_method; } sub _emit_link { my($html, $node) = @_; my $stream = $html->{stream}; my $target = $node->get_target; my $domain = $target->get_domain; my $method = "make_${domain}_URL"; my $url = $html->$method($target); $stream->A(HREF=>$url); $html->_emit_children($node); $stream->_A; } sub make_POD_URL { my($html, $target) = @_; my $link_map = $html->{options}{link_map}; return $link_map->url($html, $target) if $link_map->can("url"); $html->make_mapped_URL($target) } sub make_mapped_URL { my($html, $target) = @_; my $link_map = $html->{options}{link_map}; my $base = $html->{options}{base} || ''; my $page = $target->get_page; my $section = $target->get_section; my $depth = $html->{options}{depth}; ($base, $page, $section) = $link_map->map($base, $page, $section, $depth); $base =~ s(/$)(); $page .= '.html' if $page; my $fragment = $html->escape_2396($section); my $url = $html->assemble_url($base, $page, $fragment); $url } sub make_HTTP_URL { my($html, $target) = @_; $target->get_page } sub _emit_index { my($html, $node) = @_; my $stream = $html->{stream}; my $anchor = $html->_make_anchor($node); $stream->A(NAME=>$anchor)->_A; } sub _emit_entity { my($html, $node) = @_; my $stream = $html->{stream}; my $entity = $node->get_deep_text; $stream->ent($entity); } sub _emit_text { my($html, $node) = @_; my $stream = $html->{stream}; my $text = $node->get_text; my $text_method = $html->{text_method}; $stream->$text_method($text); } sub _emit_verbatim { my($html, $node) = @_; my $stream = $html->{stream}; my $text = $node->get_text; $text =~ s(\n\n$)(); $stream->PRE->text($text)->_PRE; } sub _make_anchor { my($html, $node) = @_; my $text = $node->get_deep_text; $text =~ s( \s*\n\s*/ )( )xg; # close line breaks $text =~ s( ^\s+ | \s+$ )()xg; # clip leading and trailing WS $html->escape_2396($text) } sub bin { oct '0b' . join '', @_ } my @LinkFormat = ( sub { my($b,$p,$f)=@_; "" }, sub { my($b,$p,$f)=@_; "#$f" }, sub { my($b,$p,$f)=@_; "$p" }, sub { my($b,$p,$f)=@_; "$p#$f" }, sub { my($b,$p,$f)=@_; "$b/" }, sub { my($b,$p,$f)=@_; "#$f" }, sub { my($b,$p,$f)=@_; "$b/$p" }, sub { my($b,$p,$f)=@_; "$b/$p#$f" } ); sub assemble_url { my($html, $base, $page, $fragment) = @_; my $i = bin map { length($_) ? 1 : 0 } ($base, $page, $fragment); my $url = $LinkFormat[$i]($base, $page, $fragment); $url } sub escape_2396 { my($html, $text) = @_; $text =~ s(([^\w\-.!~*'()]))(sprintf("%%%02x", ord($1)))eg; $text } package Pod::Tree::HTML::LinkMap; sub new { my $class = shift; bless {}, $class } sub url { my($link_map, $html, $target) = @_; my $depth = $html->{options}{depth}; my $base = join '/', ('..') x $depth; my $page = $target->get_page; $page =~ s(::)(/)g; $page .= '.html' if $page; my $section = $target->get_section; my $fragment = $html->escape_2396 ($section); my $url = $html->assemble_url($base, $page, $fragment); $url } __END__ =head1 NAME Pod::Tree::HTML - Generate HTML from a Pod::Tree =head1 SYNOPSIS use Pod::Tree::HTML; $source = new Pod::Tree %options; $source = "file.pod"; $source = new IO::File; $source = \$pod; $source = \@pod; $dest = new HTML::Stream; $dest = new IO::File; $dest = "file.html"; $html = new Pod::Tree::HTML $source, $dest, %options; $html->set_options(%options); @values = $html->get_options(@keys); $html->translate; $html->translate($template); $html->emit_toc; $html->emit_body; $fragment = $html->escape_2396 ($section); $url = $html->assemble_url($base, $page, $fragment); =head1 REQUIRES C, C =head1 DESCRIPTION C reads a POD and translates it to HTML. The source and destination are fixed when the object is created. Options are provided for controlling details of the translation. The C method does the actual translation. For convenience, C can read PODs from a variety of sources, and write HTML to a variety of destinations. The C method resolves the I<$source> and I<$dest> arguments. C can also use C to fill in an HTML template file. =head2 Source resolution C can obtain a POD from any of 5 sources. C resolves I<$source> by checking these things, in order: =over 4 =item 1 If I<$source> C C, then the POD is taken from that tree. =item 2 If I<$source> is not a reference, then it is taken to be the name of a file containing a POD. =item 3 If I<$source> C C, then it is taken to be an C object that is already open on a file containing a POD. =item 4 If I<$source> is a SCALAR reference, then the text of the POD is taken from that scalar. =item 5 if I<$source> is an ARRAY reference, then the paragraphs of the POD are taken from that array. =back If I<$source> isn't any of these things, C Cs. =head2 Destination resolution C can write HTML to any of 5 destinations. C resolves I<$dest> by checking these things, in order: =over 4 =item 1 If I<$dest> C C, then C writes HTML to that stream. =item 2 If I<$dest> C C, then C writes HTML to that file. =item 3 If I<$dest> has a C method, then C passes HTML to that method. =item 4 If I<$dest> is a SCALAR reference, then C writes HTML to that scalar. =item 5 If I<$dest> is a string, then C writes HTML to the file with that name. =back If I<$dest> isn't any of these things, C Cs. =head1 METHODS =over 4 =item I<$html> = C C I<$source>, I<$dest>, I<%options> Creates a new C object. I<$html> reads a POD from I<$source>, and writes HTML to I<$dest>. See L and L for details. Options controlling the translation may be passed in the I<%options> hash. See L for details. =item I<$html>->C(I<%options>) Sets options controlling the translation. See L for details. =item I<@values> = I<$html>->C(I<@keys>) Returns the current values of the options specified in I<@keys>. See L for details. =item I<$html>->C =item I<$html>->C(I<$template>) Translates the POD to HTML. This method should only be called once. In the second form, I<$template> is the name of a file containing a template. The template will be filled in by the C module. Here is a minimal template, showing example usage of all the variables that are set by C. {$title} {$toc} {$body} The program fragments in the template are evaulted in the C package. Any variables that you set in this package will be available to your template. When a template is used, the destination must not be an C object. C doesn't return anything. The first form always returns. The second form Cs if there is an error creating or filling in the template. =item I<$html>->C =item I<$html>->C Emits the table of contents and body of the HTML document. These methods are called automatically by C. They are exposed in the API for applications that wish to embed the HTML inside a larger document. =back =head2 Utility methods These methods are provided for implementors who write their own link mapper objects. =over 4 =item I<$fragment> = I<$html>->C(I<$section>) Escapes I<$section> according to RFC 2396. For example, the section some section is returned as some%20section =item I<$url> = I<$html>->C(I<$base>, I<$page>, I<$fragment>) Assembles I<$base>, I<$page>, and I<$fragment> into a URL, of the form $base/$page#$fragment Attempts to construct a valid URL, even if some of I<$base>, I<$page>, and I<$fragment> are empty. =back =head1 OPTIONS =over 4 =item C => I<$url> Specifies a base URL for relative HTML links. =item C => I<#rrggbb> Set the background color to I<#rrggbb>. Default is white. =item C => I<$url> Specifies a Cascading Style Sheet for the generated HTML page. =item C => I<$depth> Specifies the depth of the generated HTML page in a directory tree. See L for details. =item C => C<1> Causes the C method to emit an HTML file, even if the POD is empty. If this option is not provided, then no HTML file is created for empty PODs. =item C
=> I<$level> Controls the profusion of horizontal lines in the output, as follows: $level horizontal lines 0 none 1 between TOC and body 2 after each =head1 3 after each =head1 and =head2 Default is level 1. =item C => I<$link_map> Sets the link mapper. See L for details. =item C => I<#rrggbb> Set the text color to I<#rrggbb>. Default is black. =item C => I<title> Set the page title to I<title>. If no C<title> option is given, C<Pod::Tree::HTML> will attempt construct a title from the second paragrah of the POD. This supports the following style: =head1 NAME ls - list contents of directory =item C<toc> => [C<0>|C<1>] Includes or omits the table of contents. Default is to include the TOC. =back =head1 LINKS and TARGETS C<Pod::Tree::HTML> automatically generates HTML destination anchors for all =headI<n> command paragraphs, and for text items in =over lists. The text of the paragraph becomes the C<name> attribute of the anchor. Markups are ignored and the text is escaped according to RFC 2396. For example, the paragraph =head1 C<Foo> Bar is translated to <h1><a name="Foo%20Bar"><code>Foo</code> Bar</a></h1> To link to a heading, simply give the text of the heading in an C<< LZ<><> >> markup. The text must match exactly; markups may vary. Either of these would link to the heading shown above L</C<Foo> Bar> L</Foo Bar> To generate destination anchors in other places, use the index (C<< XZ<><> >>) markup We can link to X<this text> this text. and link to it as usual L</this text> uses the index markup. Earlier versions of this module also emitted the content of the XZ<><> markup as visible text. However, L<perlpod> now specifies that XZ<><> markups render as an empty string, so C<Pod::Tree::HTML> has been changed to do that. =head1 LINK MAPPING The POD specification provides the C<< LZ<><> >> markup to link from one document to another. HTML provides anchors (C<< <a href=""></a> >>) for the same purpose. Obviously, a POD2HTML translator should convert the first to the second. In general, this is a hard problem. In particular, the POD format is not powerful enough to support the kind of hyper-linking that people want in a complex documentation system. Rather than try to be all things to all people, C<Pod::Tree::HTML> uses a I<link mapper> object to translate the target of a POD link to a URL. The default link mapper does a simple translation, described below. If you don't like the default translation, you can provide your own link mapper with the L<< C<link_map> => I<$link_map> >> option. =head2 Default The default link mapper obtains the I<page> and I<section> from the target. It translates C<::> sequences in the I<page> to C</>, and returns a URL of the form [C<../>...][I<page>C<.html>][C<#>I<section>] If the L<< C<depth> => I<$depth> >> option is given, a corresponding number of C<../> sequences are prepended to I<page>. This is a relative URL, so it will be interpreted relative to the L<< C<base> => I<$base> >> option, if any. =head2 Custom To use your own link mapper, create a link mapper object and provide it to C<Pod::Tree::HTML> with the C<link_map> option sub MyMapper::new { bless {}, shift } sub MyMapper::url { my($mapper, $html, $target) = @_; ... return $url; } $mapper = new MyMapper; $html = new Pod::Tree::HTML link_map => $mapper; Your object should implement one method =over 4 =item I<$url> = I<$mapper>->C<url>(I<$html>, I<$target>) When I<$html>->C<translate>() encounters an C<< LZ<><> >> markup, it calls I<$mapper>->C<url>. I<$html> is the C<Pod::Tree::HTML> object itself. I<$target> is a C<Pod::Tree::Node> object representing the the target of the link. See L<Pod::Tree::Node/target nodes> for information on interpreting I<$target>. The C<url> method must return a string, which will be emitted as the value of the C<href> attribute of an HTML anchor: C<< <a href=" >>I<$url>C<< "> >>...C<< </a> >> C<Pod:Tree:HTML> provides the C<escape_2396> and C<assemble_url> methods for convenience in implementing link mappers. =back If the link mapper does not provide a C<url> method, C<Pod::Tree::HTML> will call C<map> =over 4 =item (I<$base>, I<$page>, I<$section>) = I<$mapper>-E<gt>C<map>(I<$base>, I<$page>, I<$section>, I<$depth>); Where =over 4 =item I<$base> is the URL given in the C<base> option. =item I<$page> is the man page named in the LE<lt>E<gt> markup. =item I<$section> is the man page section given in the LE<lt>E<gt> markup. =item I<$depth> is the value of the C<depth> option. =back The C<map> method may perform arbitrary mappings on its arguments. C<Pod::Tree::HTML> takes the returned values and constructs a URL of the form [I<$base>/][I<$page>C<.html>][C<#>I<$fragment>] =back The C<map> method is =over 4 =item * deprecated =item * less flexible than the C<url> method =item * supported for backwards compatability with older versions of C<Pod::Tree::HTML> =back =head1 DIAGNOSTICS =over 4 =item C<Pod::Tree::HTML::new: not enough arguments> (F) C<new> called with fewer than 2 arguments. =item C<Pod::Tree::HTML::new: Can't load POD from $source> (F) C<new> couldn't resolve the I<$source> argument. See L</Source resolution> for details. =item C<Pod::Tree::HTML::new: Can't write HTML to $dest> (F) C<new> couldn't resolve the I<$dest> argument. See L</Destination resolution> for details. =item C<Pod::Tree::HTML::new: Can't open $dest: $!> (F) The destination file couldn't be opened. =back =head1 SEE ALSO perl(1), L<C<Pod::Tree>>, L<C<Pod::Tree::Node>>, L<C<Text::Template>> =head1 AUTHOR Steven McDougall, swmcd@world.std.com =head1 COPYRIGHT Copyright (c) 1999-2009 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. ew> couldn't rPod-Tree-1.17/lib/Pod/Tree/Node.pm������������������������������������������������������������������000644 �023614 �023614 �00000076652 10132367650 017020� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 1999-2004 by Steven McDougall. This module is free # software; you can redistribute it and/or modify it under the same # terms as Perl itself. package Pod::Tree::Node; use strict; use Pod::Escapes (); $Pod::Tree::Node::VERSION = '1.10'; sub root # ctor { my($class, $children) = @_; my $node = { type => 'root', children => $children }; bless $node, $class } sub code #ctor { my($class, $paragraph) = @_; my $node = { type => 'code', text => $paragraph }; bless $node, $class } sub verbatim # ctor { my($class, $paragraph) = @_; my $node = { type => 'verbatim', raw => $paragraph, text => $paragraph }; bless $node, $class } my %Argumentative = map { $_ => 1 } qw(=over =for =begin =end); sub command # ctor { my($class, $paragraph) = @_; my($command, $arg, $text); ($command) = split(/\s/, $paragraph); if ($Argumentative{$command}) { ($command, $arg, $text) = split(/\s+/, $paragraph, 3); } else { ($command, $text) = split(/\s+/, $paragraph, 2); $arg = ''; } $command =~ s/^=//; my $node = { type => 'command', raw => $paragraph, command => $command, arg => $arg, text => $text }; bless $node, $class } sub ordinary # ctor { my($class, $paragraph) = @_; my $node = { type => 'ordinary', raw => $paragraph, text => $paragraph }; bless $node, $class } sub letter # ctor { my($class, $token) = @_; my $node = { type => 'letter', letter => substr($token, 0, 1), width => $token =~ tr/</</ }; bless $node, $class } sub sequence # ctor { my($class, $letter, $children) = @_; my $node = { type => 'sequence', 'letter' => $letter->{'letter'}, children => $children }; bless $node, $class } sub text # ctor { my($class, $text) = @_; my $node = { type => 'text', text => $text }; bless $node, $class } sub target # ctor { my($class, $children) = @_; my $node = bless { type => 'target', children => $children }, $class; $node->unescape; my $text = $node->get_deep_text; if ($text =~ m(^[A-Za-z]+:(?!:))) # a URL { $node->{page } = $text; $node->{section} = ''; $node->{domain } = 'HTTP'; } else # a POD link { my($page, $section) = SplitTarget($text); $node->{page } = $page; $node->{section} = $section; $node->{domain } = 'POD'; } $node } sub SplitTarget { my $text = shift; my($page, $section); if ($text =~ /^"(.*)"$/s) # L<"sec">; { $page = ''; $section = $1; } else # all other cases { ($page, $section) = (split(m(/), $text, 2), '', ''); $page =~ s/\s*\(\d\)$//; # ls (1) -> ls $section =~ s( ^" | "$ )()xg; # lose the quotes # L<section in this man page> (without quotes) if ($page !~ /^[\w.-]+(::[\w.-]+)*$/ and $section eq '') { $section = $page; $page = ''; } } $section =~ s( \s*\n\s* )( )xg; # close line breaks $section =~ s( ^\s+ | \s+$ )()xg; # clip leading and trailing WS ($page, $section) } sub link # ctor { my($class, $node, $page, $section) = @_; my $target = bless { type => 'target', domain => 'POD', children => [ $node ], page => $page, section => $section }, $class; my $link = bless { type => 'sequence', letter => 'L', children => [ $node ], target => $target }, $class; $link } sub is_code { shift->{type} eq 'code' } sub is_command { shift->{type} eq 'command' } sub is_for { shift->{type} eq 'for' } sub is_item { shift->{type} eq 'item' } sub is_letter { shift->{type} eq 'letter' } sub is_list { shift->{type} eq 'list' } sub is_ordinary { shift->{type} eq 'ordinary' } sub is_root { shift->{type} eq 'root' } sub is_sequence { shift->{type} eq 'sequence' } sub is_text { shift->{type} eq 'text' } sub is_verbatim { shift->{type} eq 'verbatim' } sub is_link { my $node = shift; is_sequence $node and $node->{'letter'} eq 'L' } sub is_pod { my $node = shift; not is_code $node and not is_c_cut $node and not is_c_pod $node } sub is_c_head1 { my $node = shift; $node->{type} eq 'command' and $node->{'command'} eq 'head1' } sub is_c_head2 { my $node = shift; $node->{type} eq 'command' and $node->{'command'} eq 'head2' } sub is_c_head3 { my $node = shift; $node->{type} eq 'command' and $node->{'command'} eq 'head3' } sub is_c_head4 { my $node = shift; $node->{type} eq 'command' and $node->{'command'} eq 'head4' } sub is_c_cut { my $node = shift; $node->{type} eq 'command' and $node->{'command'} eq 'cut' } sub is_c_pod { my $node = shift; $node->{type} eq 'command' and $node->{'command'} eq 'pod' } sub is_c_over { my $node = shift; $node->{type} eq 'command' and $node->{'command'} eq 'over' } sub is_c_back { my $node = shift; $node->{type} eq 'command' and $node->{'command'} eq 'back' } sub is_c_item { my $node = shift; $node->{type} eq 'command' and $node->{'command'} eq 'item' } sub is_c_for { my $node = shift; $node->{type} eq 'command' and $node->{'command'} eq 'for' } sub is_c_begin { my $node = shift; $node->{type} eq 'command' and $node->{'command'} eq 'begin' } sub is_c_end { my $node = shift; $node->{type} eq 'command' and $node->{'command'} eq 'end' } sub get_arg { shift->{ arg } } sub get_back { shift->{ back } } sub get_children { shift->{ children } } sub get_command { shift->{'command' } } sub get_domain { shift->{ domain } } sub get_item_type { shift->{ item_type } } sub get_letter { shift->{'letter' } } sub get_list_type { shift->{ list_type } } sub get_page { shift->{ page } } sub get_raw { shift->{ raw } } sub get_raw_kids { shift->{ raw_kids } } sub get_section { shift->{ section } } sub get_siblings { shift->{ siblings } } sub get_target { shift->{'target' } } sub get_text { shift->{'text' } } sub get_type { shift->{'type' } } sub get_url { shift->{'url' } } sub get_brackets { my $node = shift; my $brackets = $node->{brackets}; $brackets } sub get_deep_text { my $node = shift; for ($node->get_type) { /text/ and return $node->{'text'}; /verbatim/ and return $node->{'text'}; } join '', map { $_->get_deep_text } @{$node->{children}} } sub force_text { my($node, $text) = @_; $node->{ type } = 'text'; $node->{'text'} = $text; undef $node->{children}; } sub force_for { my $node = shift; $node->{type } = 'for'; my($bracket) = $node->{raw} =~ /^(=\w+\s+\w+\s+)/; $node->{brackets} = [ $bracket ]; } sub parse_begin { my($node, $nodes) = @_; my $foreign; my @raw; while (@$nodes) { $foreign = shift @$nodes; is_c_end $foreign and last; push @raw, $foreign->{'raw'}; } $node->{'text'} = join '', @raw; my $interpreter = $foreign->{arg}; $interpreter and $interpreter ne $node->{arg} and $node->_warn("Mismatched =begin/=end tags around\n$node->{'text'}"); $node->{type } = 'for'; $node->{brackets} = [ $node->{raw}, $foreign->{raw} ]; } sub set_children { my($node, $children) = @_; $node->{children} = $children; } sub make_sequences { my $node = shift; my $text = $node->{'text'}; my @tokens = split /( [A-Z]<<+\s+ | [A-Z]< | \s+>>+ | > )/x, $text; my $sequences = _parse_text(\@tokens); $node->{children} = $sequences; } sub _parse_text { my $tokens = shift; my(@stack, @width); while (@$tokens) { my $token = shift @$tokens; length $token or next; $token =~ /^[A-Z]</ and do { my $width = $token =~ tr/</</; push @width, $width; my $node = letter Pod::Tree::Node $token; push @stack, $node; next; }; @width and $token =~ />{$width[-1],}$/ and do { my $width = pop @width; my($letter, $interior) = _pop_sequence(\@stack, $width); my $node = sequence Pod::Tree::Node $letter, $interior; push @stack, $node; $token =~ s/^\s*>{$width}//; my @tokens = split //, $token; unshift @$tokens, @tokens; next; }; my $node = text Pod::Tree::Node $token; push @stack, $node; } if (@width) { my @text = map { $_->get_deep_text } @stack; Pod::Tree::Node->_warn("Missing '>' delimiter in\n@text"); } \@stack } sub _pop_sequence { my($stack, $width) = @_; my($node, @interior); while (@$stack) { $node = pop @$stack; is_letter $node and $node->{width} == $width and return ($node, \@interior); unshift @interior, $node; } my @text = map { $_->get_deep_text } @interior; $node->_warn("Mismatched sequence delimiters around\n@text"); $node = letter Pod::Tree::Node ' '; $node, \@interior; } sub parse_links { my $node = shift; is_link $node and $node->_parse_link; my $children = $node->{children}; for my $child (@$children) { $child->parse_links; } } sub _parse_link { my $node = shift; $node->{raw_kids} = $node->clone->{children}; my $children = $node->{children}; my($text_kids, $target_kids) = SplitBar($children); $node->{ children } = $text_kids; $node->{'target' } = target Pod::Tree::Node $target_kids; } sub SplitBar { my $children = shift; my(@text, @link); while (@$children) { my $child = shift @$children; is_text $child or do { push @text, $child; next; }; my($text, $link) = split m(\|), $child->{'text'}, 2; $link and do { push @text, text Pod::Tree::Node $text if $text; push @link, (text Pod::Tree::Node $link), @$children; return (\@text, \@link) }; push @text, $child; } (\@text, \@text) } sub unescape { my $node = shift; my $children = $node->{children}; for my $child (@$children) { $child->unescape; } is_sequence $node and $node->_unescape_sequence; } sub _unescape_sequence { my $node = shift; for ($node->{'letter'}) { /Z/ and $node->force_text(''), last; /E/ and do { my $child = $node->{children}[0]; $child or last; my $text = $child->_unescape_text; $text and $node->force_text($text); last; }; } } sub _unescape_text { my $node = shift; my $text = $node->{'text'}; defined $text ? Pod::Escapes::e2char($text) : "E<UNDEF?!>"; } sub consolidate { my $node = shift; my $old = $node->{children}; $old and @$old or return; my $new = []; push @$new, shift @$old; while (@$old) { if (is_text $new->[-1] and is_text $old->[ 0] or is_verbatim $new->[-1] and is_verbatim $old->[ 0] or is_code $new->[-1] and is_code $old->[ 0] ) { $new->[-1]{'text'} .= $old->[0]{'text'}; shift @$old; } else { push @$new, shift @$old; } } $node->{children} = $new; for my $child (@$new) { $child->consolidate; } } sub make_lists { my $root = shift; my $nodes = $root->{children}; $root->_make_lists($nodes); } sub _make_lists { my($node, $old) = @_; my $new = []; my $back; while (@$old) { my $child = shift @$old; is_c_over $child and $child->_make_lists($old); is_c_item $child and $child->_make_item ($old); is_c_back $child and $back = $child, last; push @$new, $child; } $node->{children} = $new; is_root $node and return; $node->{type} = 'list'; $node->{back} = $back; $node->_set_list_type; } sub _set_list_type { my $list = shift; my $children = $list->{children}; $list->{list_type} = ''; # -w for my $child (@$children) { $child->{type} eq 'item' or next; $list->{list_type} = $child->{item_type}; last; } } sub _make_item { my($item, $old) = @_; my $siblings = []; while (@$old) { my $sibling = $old->[0]; is_c_item $sibling and last; is_c_back $sibling and last; shift @$old; is_c_over $sibling and do { $sibling->_make_lists($old); }; push @$siblings, $sibling; } $item->{type } = 'item'; $item->{siblings} = $siblings; $item->_set_item_type; } sub _set_item_type { my $item = shift; my $text = $item->{'text'}; $text =~ m(^\s* \* \s*$ )x and $item->{item_type} = 'bullet'; $text =~ m(^\s* \d+ \s*$ )x and $item->{item_type} = 'number'; $item->{item_type} or $item->{item_type} = 'text'; } sub clone { my $node = shift; my $clone = { %$node }; my $children = $node->{children}; $clone->{children} = [ map { $_->clone } @$children ]; bless $clone, ref $node } my $Indent; my $String; sub dump { my $node = shift; $Indent = 0; $String = ''; $node->_dump; $String } sub _dump { my $node = shift; my $type = $node->get_type; $String .= ' ' x $Indent . uc $type . " "; for ($type) { /command/ and $String .= $node->_dump_command; /code/ and $String .= $node->_dump_code; /for/ and $String .= $node->_dump_for; /item/ and $String .= $node->_dump_item; /list/ and $String .= $node->_dump_list; /ordinary/ and $String .= "\n"; /root/ and $String .= "\n"; /sequence/ and $String .= $node->_dump_sequence; /text/ and $String .= $node->_dump_text; /verbatim/ and $String .= $node->_dump_verbatim; } $node->_dump_children; $node->_dump_siblings; } sub _dump_command { my $node = shift; my $command = $node->get_command; my $arg = $node->get_arg; "$command $arg\n" } sub _dump_code { my $node = shift; my $text = _indent($node->get_text, 3); my $block = "\n{\n$text}\n"; _indent($block, $Indent) } sub _dump_for { my $node = shift; my $arg = $node->get_arg; my $text = _indent($node->get_text, $Indent+3); "$arg\n$text\n" } sub _dump_item { my $node = shift; uc $node->get_item_type . "\n" } sub _dump_list { my $node = shift; uc $node->get_list_type . "\n" } sub _dump_sequence { my $node = shift; my $letter = $node->get_letter; my $link = $node->is_link ? $node->_dump_target : ''; "$letter$link\n"; } sub _dump_text { my $node = shift; my $text = $node->get_text; $text =~ s/([\x80-\xff])/sprintf("\\x%02x", ord($1))/eg; my $indent = ' ' x ($Indent+5); $text =~ s( (?<=\n) (?=.) )($indent)xg; "$text\n" } sub _dump_verbatim { my $node = shift; "\n" . $node->get_text . "\n" } sub _dump_target { my $node = shift; my $target = $node->get_target; my $page = $target->{page}; my $section = $target->{section}; " $page / $section" } sub _dump_children { my $node = shift; my $children = $node->get_children; $children and DumpList($children, '{', '}'); } sub _dump_siblings { my $node = shift; my $siblings = $node->get_siblings; $siblings and DumpList($siblings, '[', ']'); } sub DumpList { my($nodes, $open, $close) = @_; $String .= ' ' x $Indent . "$open\n"; $Indent += 3; for my $node (@$nodes) { $node->_dump; } $Indent -= 3; $String .= ' ' x $Indent . "$close\n"; } sub _indent { my($text, $spaces) = @_; my $indent = ' ' x $spaces; $text =~ s( (?<=\n) (?=.) )($indent)xg; $indent . $text } sub _warn { my($node, $message) = @_; my $filename = $node->get_filename; my $tag = $filename ? "in $filename" : $filename; warn "$message $tag\n"; } sub set_filename { my($package, $filename) = @_; $Pod::Tree::Node::filename = $filename; } sub get_filename { $Pod::Tree::Node::filename } 1 __END__ =head1 NAME Pod::Tree::Node - nodes in a Pod::Tree =head1 SYNOPSIS $node = root Pod::Tree::Node \@paragraphs; $node = code Pod::Tree::Node $paragraph; $node = verbatim Pod::Tree::Node $paragraph; $node = command Pod::Tree::Node $paragraph; $node = ordinary Pod::Tree::Node $paragraph; $node = letter Pod::Tree::Node $token; $node = sequence Pod::Tree::Node $letter, \@children; $node = text Pod::Tree::Node $text; $node = target Pod::Tree::Node $target; $node = link Pod::Tree::Node $node, $page, $section; is_code $node and ... is_command $node and ... is_for $node and ... is_item $node and ... is_letter $node and ... is_list $node and ... is_ordinary $node and ... is_pod $node and ... is_root $node and ... is_sequence $node and ... is_text $node and ... is_verbatim $node and ... is_link $node and ... is_c_head1 $node and ... is_c_head2 $node and ... is_c_head3 $node and ... is_c_head4 $node and ... is_c_cut $node and ... is_c_pod $node and ... is_c_over $node and ... is_c_back $node and ... is_c_item $node and ... is_c_for $node and ... is_c_begin $node and ... is_c_end $node and ... $arg = get_arg $node; $brackets = get_brackets $node; $children = get_children $node; $command = get_command $node; $domain = get_domain $node; $item_type = get_item_type $node; $letter = get_letter $node; $list_type = get_list_type $node; $page = get_page $node; $raw = get_raw $node; $raw_kids = get_raw_kids $node; $section = get_section $node; $siblings = get_siblings $node; $target = get_target $node; $text = get_text $node; $type = get_type $node; $deep_text = get_deep_text $node; $node->force_text($text); $node->force_for; $node->parse_begin (\@nodes); $node->set_children(\@children); $node->make_sequences; $node->parse_links; $node->unescape; $node->consolidate; $node->make_lists; $node->clone; $node->dump; Pod::Tree::Node->set_filename($filename); $filename = $node->get_filename; =head1 REQUIRES Pod::Escapes =head1 DESCRIPTION C<Pod::Tree::Node> objects are nodes in a tree that represents a POD. Applications walk the tree to recover the structure and content of the POD. Methods are provided for =over 4 =item * creating nodes in the tree =item * parsing the POD into nodes =item * returning information about nodes =item * walking the tree =back =head1 TREE STRUCTURE =head2 Root node The tree descends from a single root node; C<is_root> returns true on this node and no other. $children = $root->get_children returns a reference to an array of nodes. These nodes represent the POD. =head2 Node types For each node, call C<get_type> to discover the type of the node for $child (@$children) { $type = $child->get_type; } I<$type> will be one of these strings: =over 4 =item 'root' The node is the root of the tree. =item 'code' The node represents a paragraph that is not part of the POD. =item 'verbatim' The node represents a verbatim paragraph. =item 'ordinary' The node represents an ordinary paragraph. =item 'command' The node represents an =command paragraph (but not an =over paragraph). =item 'sequence' The node represents an interior sequence. =item 'target' The node represents the target of a link (An LE<lt>E<gt> markup). =item 'text' The node represents text that contains no interior sequences. =item 'list' The node represents an =over list. =item 'item' The node represents an item in an =over list. =item 'for' The node represents a =for paragraph, or it represents the paragraphs between =begin/=end commands. =back Here are instructions for walking these node types. =head2 root node Call $children = $node->get_children to get a list of nodes representing the POD. =head2 code nodes A code node contains the text of a paragraph that is not part of the POD, for example, a paragraph that follows an C<=cut> command. Call $text = $node->get_text to recover the text of the paragraph. =head2 verbatim nodes A verbatim node contains the text of a verbatim paragraph. Call $text = $node->get_text to recover the text of the paragraph. =head2 ordinary nodes An ordinary node represents the text of an ordinary paragraph. The text is parsed into a list of text and sequence nodes; these nodes are the children of the ordinary node. Call $children = $node->get_children to get a list of the children. Iterate over this list to recover the text of the paragraph. =head2 command nodes A command node represents an =command paragraph. Call $command = $node->get_command; to recover the name of the command. The name is returned I<without> the equals sign. Z<>=over paragraphs are represented by list nodes, not command nodes; see L<list nodes>, below. The text of a command paragraph is parsed into a list of text and sequence nodes; these nodes are the children of the command node. Call $children = $node->get_children; to get a list of the children. Iterate over this list to recover the text of the paragraph. =head2 sequence nodes A sequence node represents a single interior sequence (a <> markup). Call $node->get_letter to recover the original markup letter. The contents of the markup are parsed into a list of text and sequence nodes; these nodes are the children of the sequence node. Call $node->get_children to recover them. ZE<lt>E<gt> and EE<lt>E<gt> markups do not generate sequence nodes; these markups are expanded by C<Pod::Tree> when the tree is built. =head2 target nodes If a sequence node represents a link (an C<< LZ<><> >> markup), then is_link $node returns true and $target = $node->get_target returns a node representing the target of the link. C<Pod::Tree::Node> can represent targets in two I<domains>: C<POD> and C<HTTP>. The C<POD> domain represents the L<page/section> markups that are described in L<perlpod>. The C<HTTP> domain represents C<< LZ<><> >> markups that contain a URL, e.g. L<http://foo.bar.com/page.html#fragment> Call $domain = $target->get_domain to discover the domain of the target. For targets in the POD domain, call $page = $target->get_page; $section = $target->get_section; to recover the man page and section that the link refers to. For targets in the HTTP domain, call $url = $target->get_page; to recover the URL for the link. I<$target> is used only for constructing hyper-links; the text to be displayed for the link is recovered by walking the children of I<$node>, as for any other interior sequence. =head2 text nodes A text node represents text that contains no interior sequences. Call $text = $node->get_text to recover the text. =head2 list nodes A list node represents an =over list. Call $list_type = $node->get_list_type; to discover the type of the list. This will be one of the strings =over 4 =item 'bullet' =item 'number' =item 'text' =back The type of a list is the type of the first item in the list. The children of a list node are item nodes; each item node represents one item in the list. You can call $node->get_arg; to recover the indent value following the =over. =head2 item nodes An item node represents one item in an =over list. Call $item_type = $node->get_item_type; to discover the type of the item. This will be one of the strings shown above for L<list nodes>. Typically, all the items in a list have the same type, but C<Pod::Tree::Node> doesn't assume this. The children of an item node represent the text of the =item paragraph; this is usually of interest only for 'text' items. Call $children = $node->get_children to get a list of the children; these will be sequence and text nodes, as for any other =command paragraph. Each item node also has a list of nodes representing all the paragraphs following it, up to the next =item command, or the end of the list. These nodes are called I<siblings> of the item node. Call $siblings = $node->get_siblings to get a list of sibling nodes. =head2 for nodes for nodes represent text that is to be passed to an external formatter. Call $formatter = $node->get_arg; to discover the name of the formatter. Call $text = $node->get_text; to obtain the text to be passed to the formatter. This will either be the text of an =for command, or all of the text between =begin and =end commands. =head2 Walking the tree PODs have a recursive structure; therefore, any application that walks a Pod::Tree must also be recursive. See F<skeleton> for an example of the necessary code. =head1 METHODS =head2 Constructors These methods construct C<Pod::Tree::Node> objects. They are used to build trees. They aren't necessary to walk trees. $node = root Pod::Tree::Node \@paragraphs; $node = code Pod::Tree::Node $paragraph; $node = verbatim Pod::Tree::Node $paragraph; $node = command Pod::Tree::Node $paragraph; $node = ordinary Pod::Tree::Node $paragraph; $node = letter Pod::Tree::Node $token; $node = sequence Pod::Tree::Node $letter, \@children; $node = text Pod::Tree::Node $text; $node = target Pod::Tree::Node $target; $node = link Pod::Tree::Node $node, $page, $section; =over 4 =item I<$link> = C<Pod::Tree::Node>->C<link>(I<$node>, I<$page>, I<$section>) Creates a new sequence node representing an C<< LZ<><> >> markup. I<$node> becomes the sole child of the new node. The target of the node is constructed from I<$page> and I<$section>. This method isn't used to parse PODs. It is provided for applications that want to create new links in an existing C<Pod::Tree> structure. =back =head2 Tests These methods return true iff I<$node> has the type indicated by the method name. is_code $node and ... is_command $node and ... is_for $node and ... is_item $node and ... is_letter $node and ... is_link $node and ... is_list $node and ... is_ordinary $node and ... is_pod $node and ... is_root $node and ... is_sequence $node and ... is_text $node and ... is_verbatim $node and ... C<is_pod> returns true for all nodes except code, C<=pod>, and C<=cut> nodes. These methods return true iff I<$node> is a command node, and the command is the one indicated by the method name. is_c_head1 $node and ... is_c_head2 $node and ... is_c_head3 $node and ... is_c_head4 $node and ... is_c_cut $node and ... is_c_pod $node and ... is_c_over $node and ... is_c_back $node and ... is_c_item $node and ... is_c_for $node and ... is_c_begin $node and ... is_c_end $node and ... =head2 Accessors These methods return information about nodes. Most accessors are only relevant for certain types of nodes. =over 4 =item I<$arg> = C<get_arg> I<$node> Returns the argument of I<$node>. This is the number following an =over command, or the name of an external translator for =for, =begin, and =end commands. Only relevant for these four command nodes. =item I<$brackets> = C<get_brackets> I<$node> Only relevant for for nodes. If the node represents an =for command, I<@$brackets> is a single-element list. The list element is the text of the =for command and its argument, i.e. the name of the external formatter. If the node represents a =begin/=end construct, I<@$brackets> is a two-element list containing the text of the =begin and =end paragraphs. =item I<$children> = C<get_children> I<$node> Returns a reference to the list of nodes that are children of I<$node>. May be called on any node. The list may be empty. =item I<$command> = C<get_command> I<$node> Returns the name of a command, without the equals sign. Only relevant for command nodes. =item I<$domain> = C<get_domain> I<$node> Only relevant for target nodes. Returns the domain of the target. This will be one of the strings =over 4 =item 'HTTP' =item 'POD' =back =item I<$item_type> = C<get_item_type> I<$node> Returns the type of an item node. The type will be one of =over 4 =item 'bullet' =item 'number' =item 'text' =back =item I<$letter> = C<get_letter> I<$node> Returns the letter that introduces an interior sequence. Only relevant for sequence nodes. =item I<$list_type> = C<get_list_type> I<$node> Returns the type of a list node. The type of a list node is the type of the first item node in the list. =item I<$page> = C<get_page> I<$node> Only relevant for target nodes. For targets in the C<POD> domain, returns the man page that is the target of the link. For targets in the C<HTTP> domain, returns the URL that is the target of the link. =item I<$raw> = C<get_raw> I<$node> Returns the original text of a paragraph. Currently provided for command, verbatim, and ordinary paragraphs. =item I<$raw_kids> = C<get_raw_kids> I<$node> Only provided for LZ<><> sequence nodes. Returns a reference to a list of nodes representing the entire text of the LZ<><> sequence, including any part following a vertical bar (|). The original text of the LZ<><> markup can be reconstructed from this list. =item I<$section> = C<get_section> I<$node> Only relevant for target nodes in the C<POD> domain. Returns the section that is the target of a link. =item I<$siblings> = C<get_siblings> I<$node> Returns the siblings of a node. May be called on any node. Only item nodes have siblings. =item I<$target> = C<get_target> I<$node> Returns the target of a node. Only relevant for sequence nodes that represent links (C<LE<lt>E<gt>> markups). C<is_link> returns true on these nodes. =item I<$text> = C<get_text> I<$node> Returns the text of a node. I<$text> will not contain any interior sequences. Only relevant for text nodes. =item I<$type> = C<get_type> I<$node> Returns the type of I<$node>. May be called on any node. See L</TREE STRUCTURE> for descriptions of the node types. =item I<$deep_text> = C<get_deep_text> I<$node> Recursively walks the children of a node, catenates together the text from each node, and returns all that text as a single string. All interior sequence markups are discarded. C<get_deep_text> is provided as a convenience for applications that want to ignore markups in a POD paragraph. =back =head2 Parsing These methods manipulate the tree while it is being built. They aren't necessary to walk the tree. $node->force_text($text) $node->force_for; $node->parse_begin (\@nodes); $node->set_children(\@children); $node->make_sequences; $node->parse_links; $node->unescape; $node->consolidate; $node->make_lists; =head2 Utility =over 4 =item I<$node>->C<clone> Returns a deep copy of a node. Only implemented for C<text> and C<sequence> nodes. =item I<$node>->C<dump> Returns a string containing a pretty-printed representation of the node. Calling C<dump> on the root node of a tree will show the entire POD. =item C<Pod::Tree::Node>->C<set_filename>(I<$filename>) Sets the file name to be reported in error messages. =item I<$filename> = $I<node>->C<getfile_name> Returns the file name set by C<set_file_name>. =back =head1 EXAMPLES The F<t/> directory in the C<Pod::Tree> distribution contains examples of PODs, together with dumps of the trees that C<Pod::Tree> constructs for them. The tree for C<t/>F<file>C<.pod> is in C<t/>F<file>C<.p_exp>. C<Pod::Tree::Node::dump> is a simple example of code that walks a POD tree. F<skeleton> is a skeleton application that walks a POD tree. =head1 NOTES =over 4 =item * There is no provision in L<perlpod> for C<< LZ<><> >> markups to contain URLs, but due to popular demand, this is now supported in C<Pod::Tree::Node>. =back =head1 SEE ALSO perl(1), L<C<Pod::Tree>> =head1 AUTHOR Steven McDougall, swmcd@world.std.com =head1 COPYRIGHT Copyright (c) 1999-2004 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. s a skeleton application that walks a POD tree. =head1 NOTES =over 4 =item * TherPod-Tree-1.17/lib/Pod/Tree/PerlBin.pm���������������������������������������������������������������000644 �023614 �023614 �00000015333 10420610435 017443� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������use strict; use 5.005; use File::Find; use HTML::Stream; use Pod::Tree; use Pod::Tree::HTML; use Pod::Tree::PerlUtil; package Pod::Tree::PerlBin; use base qw(Pod::Tree::PerlUtil); sub new { my %defaults = (col_width => 25, bgcolor => '#ffffff', text => '#000000'); my($class, $perl_dir, $html_dir, $link_map, %options) = @_; my $options = { %defaults, %options, link_map => $link_map }; my $perl_bin = { perl_dir => $perl_dir, html_dir => $html_dir, bin_dir => 'bin', top_page => 'bin.html', depth => 1, options => $options }; bless $perl_bin, $class } sub scan { my($perl_bin, @dirs) = @_; $perl_bin->report1("scan"); for my $dir (@dirs) { opendir(DIR, $dir) or next; # Windows apps sometimes leave non-existant dirs on $PATH for my $file (readdir(DIR)) { my $path = "$dir/$file"; -f $path and -x $path and -T $path or next; $perl_bin->scan_file($dir, $file); } } $perl_bin->scan_xsubpp; } # A Very Special search for a Very Special executable sub scan_xsubpp { my $perl_bin = shift; my @inc = grep { m(^/) } @INC; # Don't ask. File::Find::find(sub { $perl_bin->_scan_xsubpp }, @inc) if @inc; } sub _scan_xsubpp { my $perl_bin = shift; /^xsubpp$/ and $perl_bin->scan_file($File::Find::dir, $_); } sub scan_file { my($perl_bin, $dir, $file) = @_; my $source = "$dir/$file"; my $html_dir = $perl_bin->{html_dir}; my $bin_dir = $perl_bin->{bin_dir}; my $link = "$bin_dir/$file"; my $dest = "$html_dir/$link.html"; my($name, $description) = $perl_bin->get_name($source); $name or return; # Translate the first copy found in $PATH $perl_bin->{index}{$name} and return; $perl_bin->report2($source); my $entry = { source => $source, dest => $dest, file => $file, description => $description }; $perl_bin->{index}{$name} = $entry; $perl_bin->{options}{link_map}->add_page($file, $link); $perl_bin->{options}{link_map}->add_page($name, $link); } sub index { my $perl_bin = shift; $perl_bin->report1("index"); my $html_dir = $perl_bin->{html_dir}; my $bin_dir = $perl_bin->{bin_dir}; my $top_page = $perl_bin->{top_page}; my $dest = "$html_dir/$top_page"; $perl_bin->mkdir("$html_dir/$bin_dir"); my $fh = new IO::File ">$dest"; defined $fh or die "Pod::Tree::PerlBin::index: Can't open $dest: $!\n"; my $stream = new HTML::Stream $fh; my $options = $perl_bin->{options}; my $bgcolor = $options->{bgcolor}; my $text = $options->{text}; my $title = "Perl Executables"; $stream-> HTML->HEAD; $stream-> TITLE->text($title)->_TITLE; $stream->_HEAD -> BODY(BGCOLOR => $bgcolor, TEXT => $text); $stream->H1->t($title)->_H1; $perl_bin->_emit_entries($stream); $stream->_BODY->_HTML; } sub get_top_entry { my $perl_bin = shift; +{ URL => $perl_bin->{top_page}, description => 'Executables' } } sub _emit_entries { my($perl_bin, $stream) = @_; my $bin_dir = $perl_bin->{bin_dir}; my $index = $perl_bin->{index}; my $options = $perl_bin->{options}; my $col_width = $options->{col_width}; $stream->PRE; for my $name (sort keys %$index) { my $entry = $index->{$name}; my $file = $entry->{file}; my $desc = $entry->{description}; my $pad = $col_width - length $name; $stream->A(HREF => "$bin_dir/$file.html")->t($name)->_A; $pad < 1 and do { $stream->nl; $pad = $col_width; }; $stream->t(' ' x $pad, $desc)->nl; } $stream->_PRE; } sub translate { my $perl_bin = shift; $perl_bin->report1("translate"); my $index = $perl_bin->{index}; my $options = $perl_bin->{options}; for my $name (sort keys %$index) { $perl_bin->report2($name); my $depth = $perl_bin->{depth}; $options->{link_map}->set_depth($depth); my $entry = $index->{$name}; my $source = $entry->{source}; my $dest = $entry->{dest}; my $html = new Pod::Tree::HTML $source, $dest, %$options; $html->translate; } } 1 __END__ =head1 NAME Pod::Tree::PerlBin - translate program PODs to HTML =head1 SYNOPSIS $perl_map = new Pod::Tree::PerlMap; $perl_bin = new Pod::Tree::PerlBin $perl_dir, $HTML_dir, $perl_map, %opts; $perl_bin->scan(@path); $perl_bin->index; $perl_bin->translate; $top = $perl_bin->get_top_entry; =head1 DESCRIPTION C<Pod::Tree::PerlBin> translates program PODs to HTML. It searches for programs in a list of directories (typically a PATH), and searches for PODs withing the programs. Only text (-T) files are considered. C<Pod::Tree::PerlBin> generates a top-level index of all the program PODs, and writes it to I<HTML_dir>C</bin.html>. C<Pod::Tree::PerlBin> generates and uses an index of the PODs that it finds to construct HTML links. Other modules can also use this index. =head1 METHODS =over 4 =item I<$perl_bin> = C<new> C<Pod::Tree::PerlBin> I<$perl_dir>, I<$HTML_dir>, I<$perl_map>, I<%options> Creates and returns a new C<Pod::Tree::PerlBin> object. I<$HTML_dir> is the directory where HTML files will be written. I<$perl_map> maps program names to URLs. I<%options> are passed through to C<Pod::Tree::HTML>. The I<$perl_dir> argument is included for consistency with the other C<Pod::Tree::Perl*> modules, but is currently unused. =item I<$perl_bin>->C<scan>(I<@path>) Scans all the directories in I<@path> for program PODs. Only text (-T) files are considered. The search does not recurse through subdirectories. Each POD that is located is entered into I<$perl_map>. =item I<$perl_bin>->C<index> Generates a top-level index of all the program PODs, and writes it to I<HTML_dir>C</bin.html>. =item I<$perl_bin>->C<translate> Translates each program POD found by C<scan> to HTML. The HTML pages are written to I<HTML_dir>. =item I<$perl_bin>->C<get_top_entry> Returns a hash reference of the form { URL => $URL, description => $description } C<Pod::Tree::PerlTop> uses this to build a top-level index of all the Perl PODs. =back =head1 LINKING C<Pod::Tree::PerlBin> expects the second paragraph of the POD to have the form name - description and enters I<name> into I<$perl_map>. To link to a program POD from another POD, write L<name> =head1 REQUIRES 5.005 File::Find HTML::Stream Pod::Tree Pod::Tree::HTML Pod::Tree::PerlUtil =head1 EXPORTS Nothing. =head1 SEE ALSO L<C<Pod::Tree::HTML>>, L<C<Pod::Tree::PerlMap>>, =head1 AUTHOR Steven McDougall, swmcd@world.std.com =head1 COPYRIGHT Copyright (c) 2000 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl. me> into I<$perl_map>. To link to a program POD from another POD, write L<name> =head1 REQUIRES 5.005 File::Find HTML::Stream Pod::Tree Pod::Tree::HTML Pod::Tree::PerlUtil =head1 EXPORTS Nothing. =head1 SEE ALSO L<C<Pod::Tree::HTML>>, L<C<Pod::Tree::PerlMap>Pod-Tree-1.17/lib/Pod/Tree/PerlDist.pm��������������������������������������������������������������000644 �023614 �023614 �00000016667 10132367650 017661� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������use strict; use 5.005; use HTML::Stream; use Pod::Tree; use Pod::Tree::HTML; use Pod::Tree::PerlUtil; package Pod::Tree::PerlDist; use base qw(Pod::Tree::PerlUtil); sub new { my %defaults = (bgcolor => '#ffffff', text => '#000000'); my @stop_base = qw(Configure configpm configure installhtml installman installperl mv-if-diff perlsh); my($class, $perl_dir, $html_dir, $link_map, %options) = @_; my $options = { %defaults, %options, link_map => $link_map }; my $perl_dist = { perl_dir => $perl_dir, html_dir => $html_dir, top_page => 'dist.html', stop_ext => [qw(SH c diff fixer h pl sym y)], stop_base => [@stop_base], depth => 0, options => $options }; bless $perl_dist, $class } sub scan { my $perl_dist = shift; $perl_dist->report1("scan"); my $perl_dir = $perl_dist->{perl_dir}; my $html_dir = $perl_dist->{html_dir}; opendir(DIR, $perl_dir) or die "Can't opendir $perl_dir: $!\n"; my $stop_ext = $perl_dist->{stop_ext}; my %stop_ext = map { $_ => 1 } @$stop_ext; my $stop_base = $perl_dist->{stop_base}; my %stop_base = map { $_ => 1 } @$stop_base; for my $file (readdir(DIR)) { -f "$perl_dir/$file" and -T "$perl_dir/$file" or next; my($base, $ext) = split m(\.), $file; $stop_ext {$ext } and next; $stop_base{$base} and next; $perl_dist->report2 ($file); $perl_dist->scan_file($file); } } sub scan_file { my($perl_dist, $file) = @_; my $perl_dir = $perl_dist->{perl_dir}; my $html_dir = $perl_dist->{html_dir}; my $source = "$perl_dir/$file"; my $dest = "$html_dir/$file.html"; my $entry = { file => $file, source => $source, dest => $dest }; $perl_dist->{index}{$file} = $entry; $perl_dist->{options}{link_map}->add_page($file, $file); my($base, $ext) = split m(\.), $file; $base eq 'README' and $ext and $perl_dist->{options}{link_map}->add_page("perl$ext", $file); } sub index { my $perl_dist = shift; $perl_dist->report1("index"); my $html_dir = $perl_dist->{html_dir}; my $top_page = $perl_dist->{top_page}; my $dest = "$html_dir/$top_page"; my $fh = new IO::File ">$dest"; defined $fh or die "Pod::Tree::PerlDist::index: Can't open $dest: $!\n"; my $stream = new HTML::Stream $fh; my $options = $perl_dist->{options}; my $bgcolor = $options->{bgcolor}; my $text = $options->{text}; my $title = "Perl Distribution Documents"; $stream-> HTML->HEAD; $stream-> TITLE->text($title)->_TITLE; $stream->_HEAD -> BODY(BGCOLOR => $bgcolor, TEXT => $text); $stream->H1->t($title)->_H1; $perl_dist->_emit_entries($stream); $stream->_BODY->_HTML; } sub get_top_entry { my $perl_dist = shift; +{ URL => $perl_dist->{top_page}, description => 'distribution documents' } } sub _emit_entries { my($perl_dist, $stream) = @_; my $index = $perl_dist->{index}; my $options = $perl_dist->{options}; $stream->PRE; for my $name (sort keys %$index) { $stream->A(HREF => "$name.html")->t($name)->_A->nl; } $stream->_PRE; } sub translate { my $perl_dist = shift; $perl_dist->report1("translate"); my $depth = $perl_dist->{depth}; my $index = $perl_dist->{index}; $perl_dist->{options}{link_map}->set_depth($depth); for my $name (sort keys %$index) { $perl_dist->report2($name); my $entry = $index->{$name}; my $source = $entry->{source}; open(FILE, $source) or die "Pod::Tree::PerlDist::translate: Can't open $source: $!\n"; my @file = <FILE>; my $translate = (grep { /^=\w+/ } @file) ? 'translate_pod' : 'translate_text'; $perl_dist->$translate($entry); } } sub translate_pod { my($perl_dist, $entry) = @_; my $source = $entry->{source}; my $dest = $entry->{dest}; my $options = $perl_dist->{options}; my $html = new Pod::Tree::HTML $source, $dest, %$options; $html->translate; } sub translate_text { my($perl_dist, $entry) = @_; my $source = $entry->{source}; my $dest = $entry->{dest}; open(SOURCE, $source) or die "Pod::Tree::PerlDist::translate_text: Can't open $source: $!\n"; my $fh = new IO::File ">$dest"; defined $fh or die "Pod::Tree::PerlDist::translate_text: Can't open $dest: $!\n"; my $stream = new HTML::Stream $fh; my $options = $perl_dist->{options}; my $bgcolor = $options ->{bgcolor}; my $text = $options ->{text}; my $title = $entry ->{file}; $stream-> HTML->HEAD; $stream-> TITLE->text($title)->_TITLE; $stream->_HEAD -> BODY(BGCOLOR => $bgcolor, TEXT => $text); $stream->H1->t($title)->_H1; $stream->PRE; while (my $line = <SOURCE>) { $stream->t($line); } $stream->_PRE; $stream->_BODY->_HTML; } 1 __END__ =head1 NAME Pod::Tree::PerlDist - translate Perl distribution documentation to HTML =head1 SYNOPSIS $perl_map = new Pod::Tree::PerlMap; $perl_dist = new Pod::Tree::PerlDist $perl_dir, $HTML_dir, $perl_map, %opts; $perl_dist->scan; $perl_dist->index; $perl_dist->translate; $top = $perl_dist->get_top_entry; =head1 DESCRIPTION C<Pod::Tree::PerlDist> translates documents in the Perl distribution to HTML. These include F<Changes>, F<README>, and assored other files that appear in the top level of the Perl source tree. Files that contain PODs are parsed as PODs; files that do not contain PODs are converted to HTML as preformatted text. C<Pod::Tree::PerlDist> generates and uses an index of the files that it finds to construct HTML links. Other modules can also use this index. =head1 METHODS =over 4 =item I<$perl_dist> = C<new> C<Pod::Tree::PerlDist> I<$perl_dir>, I<$HTML_dir>, I<$perl_map>, I<%options> Creates and returns a new C<Pod::Tree::PerlDist> object. I<$perl_dir> is the root of the Perl source tree. I<$HTML_dir> is the directory where HTML files will be written. I<$perl_map> maps file names to URLs. I<%options> are passed through to C<Pod::Tree::HTML>. =item I<$perl_dist>->C<scan> Scans the top level of the Perl source tree for documentation files. Files that do not generally contain user-level documentation, such as source files, are ignored. The search does not recurse through subdirectories. Each file that is located is entered into I<$perl_map>. =item I<$perl_dist>->C<index> Generates a top-level index of all the distribution documents, and writes it to I<HTML_dir>C</dist.html>. =item I<$perl_dist>->C<translate> Translates each distribution document found by C<scan> to HTML. The HTML pages are written to I<HTML_dir>. =item I<$perl_dist>->C<get_top_entry> Returns a hash reference of the form { URL => $URL, description => $description } C<Pod::Tree::PerlTop> uses this to build a top-level index of all the Perl PODs. =back =head1 LINKING C<Pod::Tree::PerlDist> indexes files by their name. To link to a file named F<README.win32> write L<README.win32> =head1 REQUIRES 5.005; HTML::Stream; Pod::Tree; Pod::Tree::HTML; Pod::Tree::PerlUtil; =head1 EXPORTS Nothing. =head1 SEE ALSO L<C<Pod::Tree::HTML>>, L<C<Pod::Tree::PerlMap>>, =head1 AUTHOR Steven McDougall, swmcd@world.std.com =head1 COPYRIGHT Copyright (c) 2000 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl. ndexes files by their name. To link to a file named F<README.win32> writePod-Tree-1.17/lib/Pod/Tree/PerlFunc.pm��������������������������������������������������������������000644 �023614 �023614 �00000016576 10420610435 017640� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������use strict; use 5.005; use Pod::Tree; use Pod::Tree::HTML; use Pod::Tree::PerlUtil; package Pod::Tree::PerlFunc; use base qw(Pod::Tree::PerlUtil); sub new { my %defaults = (bgcolor => '#ffffff', text => '#000000'); my($class, $perl_dir, $html_dir, $link_map, %options) = @_; my $options = { %defaults, %options, link_map => $link_map }; my $perl_func = { perl_dir => $perl_dir, html_dir => $html_dir, pod_dir => 'pod', func_dir => 'func', page => 'perlfunc', options => $options }; bless $perl_func, $class } sub scan { my $perl_func = shift; $perl_func->report1("scan"); $perl_func->load_tree; $perl_func->scan_tree; } sub load_tree { my $perl_func = shift; my $perl_dir = $perl_func->{perl_dir}; my $pod_dir = $perl_func->{pod_dir}; my $page = $perl_func->{page}; my $source = "$perl_dir/$pod_dir/$page.pod"; my $win_source = "$perl_dir/lib/$pod_dir/$page.pod"; my $tree = new Pod::Tree; $tree->load_file($source ) or # for building the doc set from a Perl distribution $tree->load_file($win_source) or # for building the doc set from a Windows installation die "Pod::Tree::PerlFunc::scan: Can't find $source or $win_source\n"; my $node = $tree->pop; my $funcs = $node->get_children; $perl_func->{tree } = $tree; $perl_func->{funcs} = $funcs; } sub scan_tree { my $perl_func = shift; my $funcs = $perl_func->{funcs}; my @funcs = @$funcs; my $link_map = $perl_func->{options}{link_map}; while (@funcs) { my @items = Shift_Items(\@funcs); my($func0, $file0) = Parse_Name($items[0]); for my $item (@items) { my($func, $file) = Parse_Name($item); $perl_func->report2($func); $perl_func->{index}{$func} = $file0; $link_map->add_func($file, $file0); } } } sub index { my $perl_func = shift; $perl_func->report1("index"); $perl_func->add_links; $perl_func->add_index; my $tree = $perl_func->{tree}; my $html_dir = $perl_func->{html_dir}; my $pod_dir = $perl_func->{pod_dir}; my $page = $perl_func->{page}; my $options = $perl_func->{options}; $perl_func->mkdir("$html_dir/$pod_dir/"); $options->{link_map}->set_depth(1); my $dest = "$html_dir/$pod_dir/$page.html"; my $html = new Pod::Tree::HTML $tree, $dest, %$options; $html->translate; } sub add_links { my $perl_func = shift; my $tree = $perl_func->{tree}; $tree->walk(sub { $perl_func->_add_links(shift) } ); } sub _add_links { my($perl_func, $node) = @_; is_sequence $node or return 1; $node->get_letter eq 'C' or return 1; my($func) = Parse_Name($node); my $file = $perl_func->{index}{$func}; $file or return 1; # :TRICKY: *replaces* the node in the tree my $page = $perl_func->{page}; $_[1] = Pod::Tree::Node->link($node, $page, $file); 0 } sub add_index { my $perl_func = shift; my %funcs; my $index = $perl_func->{index}; for my $func (sort keys %$index) { my $file = $index->{$func}; my $letter = substr($func, 0, 1); push @{$funcs{$letter}}, [ $func, $file ]; } my $page = $perl_func->{page}; my @lines; for my $letter (sort keys %funcs) { my $funcs = $funcs{$letter}; my @links = map { "L<C<$_->[0]>|$page/$_->[1]>" } @$funcs; my $line = join ", ", @links; push @lines, $line; } my $pod = join "\n\n", @lines; my $index = new Pod::Tree; $index->load_string($pod); my $children = $index->get_root->get_children; $perl_func->{tree}->push(@$children); } sub translate { my $perl_func = shift; $perl_func->report1("translate"); my $html_dir = $perl_func->{html_dir}; my $pod_dir = $perl_func->{pod_dir}; my $func_dir = $perl_func->{func_dir}; $perl_func->mkdir("$html_dir/$pod_dir/$func_dir"); my $perl_dir = $perl_func->{perl_dir}; my $funcs = $perl_func->{funcs}; my $options = $perl_func->{options}; my $link_map = $options->{link_map}; $link_map->set_depth(2); $link_map->force_func(1); $options ->{toc} = 0; while (@$funcs) { my @items = Shift_Items($funcs); my($func, $file) = Parse_Name($items[0]); $perl_func->report2("func/$file"); my $tree = new Pod::Tree; $tree->load_string("=head1 $func\n\n=over 4\n\n=back"); my $list = $tree->get_root->get_children->[1]; $list->set_children(\@items); $list->_set_list_type; $options->{title} = $func; my $dest = "$html_dir/$pod_dir/$func_dir/$file.html"; my $html = new Pod::Tree::HTML $tree, $dest, %$options; $html->translate; } $link_map->force_func(0); } sub Shift_Items { my $funcs = shift; my @items; while (@$funcs) { my $item = shift @$funcs; push @items, $item; @$funcs or last; my($func0) = Parse_Name($item); my($func1) = Parse_Name($funcs->[0]); my $sibs0 = $item->get_siblings; $func0 eq $func1 or @$sibs0==0 or last; } @items } sub Parse_Name { my $item = shift; my $text = $item->get_deep_text; my @words = split m([^\w\-]+), $text; my $func = $words[0]; my $file = $func; $file =~ tr(A-Za-z0-9_-)()cd; ($func, $file) } 1 __END__ =head1 NAME Pod::Tree::PerlFunc - translate F<perlfunc.pod> to HTML =head1 SYNOPSIS $perl_map = new Pod::Tree::PerlMap; $perl_func = new Pod::Tree::PerlFunc $perl_dir, $HTML_dir, $perl_map, %opts; $perl_func->scan; $perl_func->index; $perl_func->translate; =head1 DESCRIPTION C<Pod::Tree::PerlFunc> translates F<perlfunc.pod> to HTML. It creates a separate HTML page for each function description in F<perlfunc.pod>. The pages for the individual descriptions are named after the function and written to a F<func/> subdirectory. F<perlfunc.html> is generated as an index to all the pages in F<func/>. C<Pod::Tree::PerlFunc> generates and uses an index of the functions that it finds in F<perlfunc.pod> to construct HTML links. Other modules can also use this index. =head1 METHODS =over 4 =item I<$perl_func> = C<new> C<Pod::Tree::PerlFunc> I<$perl_dir>, I<$HTML_dir>, I<$perl_map>, I<%options> Creates and returns a new C<Pod::Tree::PerlFunc> object. I<$perl_dir> is the root of the Perl source tree. I<$HTML_dir> is the directory where HTML files will be written. I<$perl_map> maps function names to URLs. I<%options> are passed through to C<Pod::Tree::HTML>. =item I<$perl_func>->C<scan> Reads F<perlfunc.pod> and identifies all the functions in it. Each function that is identified is entered into I<$perl_map>. =item I<$perl_func>->C<index> Generates a top-level index of all the functions. The index is written to I<HTML_dir>C</pod/perlfunc.html>. =item I<$perl_func>->C<translate> Translates each function found by C<scan> to HTML. The HTML pages are written to I<HTML_dir>C</pod/func/>. =back =head1 LINKING C<Pod::Tree::PerlFunc> indexes every C<=item> paragraph in F<perlfunc.html>. To link, for example, to the C<abs> function, write L<func/abs> =head1 REQUIRES 5.005; Pod::Tree; Pod::Tree::HTML; Pod::Tree::PerlUtil; =head1 EXPORTS Nothing. =head1 SEE ALSO L<C<Pod::Tree::HTML>>, L<C<Pod::Tree::PerlMap>>, =head1 AUTHOR Steven McDougall, swmcd@world.std.com =head1 COPYRIGHT Copyright (c) 2000 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. tem> paragraph in F<perlfunc.html>. To link, for example, to the C<abs> function, write L<func/abs> =head1 REQUIRES 5.Pod-Tree-1.17/lib/Pod/Tree/PerlLib.pm���������������������������������������������������������������000644 �023614 �023614 �00000016650 10605602167 017454� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������use strict; use 5.6.0; use HTML::Stream; use Pod::Tree; use Pod::Tree::HTML; use Pod::Tree::PerlUtil; package Pod::Tree::PerlLib; use base qw(Pod::Tree::PerlUtil); use constant COLUMN_WIDTH => 30; sub new { my %defaults = (col_width => COLUMN_WIDTH, bgcolor => '#ffffff', text => '#000000'); my($class, $perl_dir, $html_dir, $link_map, %options) = @_; my $options = { %defaults, %options, link_map => $link_map }; my %stop_files = map { $_ => 1 } qw(perllocal.pod); my $perl_lib = { perl_dir => $perl_dir, html_dir => $html_dir, lib_dir => 'lib', top_page => 'lib.html', stop_files => \%stop_files, options => $options }; bless $perl_lib, $class } sub scan { my($perl_lib, @dirs) = @_; $perl_lib->report1("scan"); # Don't try to install PODs for modules on relative paths in @INC # (Typically `.') @dirs = grep { m(^/) } @dirs; $perl_lib->_stop_dirs(@dirs); for my $dir (@dirs) { $perl_lib->{find_dir} = $dir; File::Find::find({wanted => sub {$perl_lib->_scan}, # Closures rock! no_chdir => 1 }, $dir); } } sub _stop_dirs { my($perl_lib, @dirs) = @_; for my $dir (@dirs) { for my $stop_dir (@dirs) { $stop_dir =~ /^$dir./ and $perl_lib->{stop_dir}{$dir}{$stop_dir} = 1; } } } sub _scan { my $perl_lib = shift; my $source = $File::Find::name; -d $source and $perl_lib->_scan_dir ($source); -f $source and $perl_lib->_scan_file($source); } sub _scan_dir { my($perl_lib, $dir) = @_; my $find_dir = $perl_lib->{find_dir}; if ($perl_lib->{stop_dir}{$find_dir}{$dir} or $dir =~ /pod$/) { $File::Find::prune = 1; return; } my $html_dir = $perl_lib->{html_dir}; my $lib_dir = $perl_lib->{lib_dir}; $dir =~ s(^$find_dir)($html_dir/$lib_dir); $perl_lib->mkdir($dir); } sub _scan_file { my($perl_lib, $source) = @_; $source =~ m(\. (?: pl | pm | pod ) $ )x or return; my $file = (split m(/), $source)[-1]; $perl_lib->{stop_files}{$file} and return; my $module = $source; my $find_dir = $perl_lib->{find_dir}; $module =~ s(^$find_dir/)(); $module =~ s( \.\w+$ )()x; # Foo/Bar my $html_dir = $perl_lib->{html_dir}; my $lib_dir = $perl_lib->{lib_dir}; my $dest = "$html_dir/$lib_dir/$module.html"; my($name, $description) = $perl_lib->get_name($source); $name or return; $perl_lib->report2($name); my $href = "$module.html"; my $link = "$lib_dir/$module"; my $entry = { source => $source, # .../Foo/Bar.pm dest => $dest, # .../html/lib/Foo/Bar.html href => $href, # Foo/Bar.html description => $description }; $perl_lib->{index}{$name} = $entry; $perl_lib->{options}{link_map}->add_page($name, $link); } sub index { my $perl_lib = shift; $perl_lib->report1("index"); my $html_dir = $perl_lib->{html_dir}; my $top_page = $perl_lib->{top_page}; my $dest = "$html_dir/$top_page"; my $fh = new IO::File ">$dest"; defined $fh or die "Pod::Tree::PerlLib::index: Can't open $dest: $!\n"; my $stream = new HTML::Stream $fh; my $options = $perl_lib->{options}; my $bgcolor = $options->{bgcolor}; my $text = $options->{text}; my $title = "Perl Modules"; $stream-> HTML->HEAD; $stream-> TITLE->text($title)->_TITLE; $stream->_HEAD -> BODY(BGCOLOR => $bgcolor, TEXT => $text); $stream->H1->t($title)->_H1; $perl_lib->_emit_entries($stream); $stream->_BODY->_HTML; } sub get_top_entry { my $perl_lib = shift; +{ URL => $perl_lib->{top_page}, description => 'Modules' } } sub _emit_entries { my($perl_lib, $stream) = @_; my $lib_dir = $perl_lib->{lib_dir}; my $index = $perl_lib->{index}; my $options = $perl_lib->{options}; my $col_width = $options->{col_width}; $stream->PRE; for my $name (sort keys %$index) { my $entry = $index->{$name}; my $href = $entry->{href}; my $desc = $entry->{description}; my $pad = $col_width - length $name; $stream->A(HREF => "$lib_dir/$href")->t($name)->_A; $pad < 1 and do { $stream->nl; $pad = $col_width; }; $stream->t(' ' x $pad, $desc)->nl; } $stream->_PRE; } sub translate { my $perl_lib = shift; $perl_lib->report1("translate"); my $index = $perl_lib->{index}; my $options = $perl_lib->{options}; for my $name (sort keys %$index) { $perl_lib->report2($name); my @path = split m(::), $name; my $depth = @path; # no -1 because they are all under /lib/ $options->{link_map}->set_depth($depth); my $entry = $index->{$name}; my $source = $entry->{source}; my $dest = $entry->{dest}; my $html = new Pod::Tree::HTML $source, $dest, %$options; $html->translate; } } 1 __END__ =head1 NAME Pod::Tree::PerlLib - translate module PODs to HTML =head1 SYNOPSIS $perl_map = new Pod::Tree::PerlMap; $perl_lib = new Pod::Tree::PerlLib $perl_dir, $HTML_dir, $perl_map, %opts; $perl_lib->scan(@INC); $perl_lib->index; $perl_lib->translate; $top = $perl_lib->get_top_entry; =head1 DESCRIPTION C<Pod::Tree::PerlLib> translates module PODs to HTML. It does a recursive subdirectory search through a list of directories (typically C<@INC>) to find PODs. C<Pod::Tree::PerlLib> generates a top-level index of all the PODs that it finds, and writes it to I<HTML_dir>C</lib.html>. C<Pod::Tree::PerlLib> generates and uses an index of the PODs that it finds to construct HTML links. Other modules can also use this index. =head1 METHODS =over 4 =item I<$perl_lib> = C<new> C<Pod::Tree::PerlLib> I<$perl_dir>, I<$HTML_dir>, I<$perl_map>, I<%options> Creates and returns a new C<Pod::Tree::PerlLib> object. I<$HTML_dir> is the directory where HTML files will be written. I<$perl_map> maps module names to URLs. I<%options> are passed through to C<Pod::Tree::HTML>. The I<$perl_dir> argument is included for consistency with the other C<Pod::Tree::Perl*> modules, but is currently unused. =item I<$perl_lib>->C<scan>(I<@INC>) Does a recursive subdirectory search through I<@INC> to locate module PODs. Each module that is identified is entered into I<$perl_map>. =item I<$perl_lib>->C<index> Generates a top-level index of all the modules. The index is written to I<HTML_dir>C</lib.html>. =item I<$perl_lib>->C<translate> Translates each module POD found by C<scan> to HTML. The HTML pages are written to I<HTML_dir>C</lib/>, in a subdirectory hierarchy that maps the module names. =item I<$perl_lib>->C<get_top_entry> Returns a hash reference of the form { URL => $URL, description => $description } C<Pod::Tree::PerlTop> uses this to build a top-level index of all the Perl PODs. =back =head1 LINKING C<Pod::Tree::PerlLib> expects the second paragraph of the POD to have the form Foo::Bar - description and enters I<Foo::Bar> into I<$perl_map>. To link to a module POD, write L<Foo::Bar> =head1 REQUIRES 5.005; HTML::Stream; Pod::Tree; Pod::Tree::HTML; Pod::Tree::PerlUtil; =head1 EXPORTS Nothing. =head1 SEE ALSO L<C<Pod::Tree::HTML>>, L<C<Pod::Tree::PerlMap>> =head1 AUTHOR Steven McDougall, swmcd@world.std.com =head1 COPYRIGHT Copyright (c) 2000 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl. ption and enters I<Foo::Bar> into I<$perl_map>. To link to a module POD, write L<FPod-Tree-1.17/lib/Pod/Tree/PerlMap.pm���������������������������������������������������������������000644 �023614 �023614 �00000006426 10132367651 017464� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������use strict; package Pod::Tree::PerlMap; sub new { my($class) = @_; my $perl_map = { prefix => '' }; bless $perl_map, $class } sub set_depth { my($perl_map, $depth) = @_; $perl_map->{prefix} = '../' x $depth; } sub add_page { my($perl_map, $page, $file) = @_; $perl_map->{page}{$page} = $file; } sub add_func { my($perl_map, $func, $file) = @_; $perl_map->{func}{$func} = $file; } sub force_func { my($perl_map, $force_func) = @_; $perl_map->{force_func} = $force_func; } sub map { my($perl_map, $base, $page, $section) = @_; # print "map $base, $page, $section ->"; my $prefix = $perl_map->{prefix}; my $force_func = $perl_map->{force_func}; my $func = (split m(\s+), $section)[0]; # e.g. L<"eval BLOCK"> my $file = $perl_map->{func}{$func}; if ( ($page eq 'perlfunc' or $page eq '' and $force_func) and $file) { $page = $prefix . 'pod/func/' . $file; $section = ''; } elsif ($perl_map->{page}{$page}) { $page = $prefix . $perl_map->{page}{$page}; } # print "$base, $page, $section\n"; ($base, $page, $section) } 1 __END__ =head1 NAME Pod::Tree::PerlMap - map names to URLs =head1 SYNOPSIS $perl_map = new Pod::Tree::PerlMap; $perl_map->add_page ($name, $file); $perl_map->add_func ($func, $file); $perl_map->force_func(0); $perl_map->force_func(1); $perl_map->set_depth ($depth); ($base, $page, $section) = $perl_map->map($base, $page, $section); =head1 DESCRIPTION C<Pod::Tree::PerlMap> maps LE<lt>E<gt> markups to URLs. The C<Pod::Tree::Perl*> translators make entries in the map. C<Pod::Tree::HTML> uses the map to translate links before it emits them. =head1 METHODS =over 4 =item I<$perl_map>->C<add_page>(I<$name>, I<$file>) Map I<$name> to I<$file>. I<$name> is the name of a POD, as used in LE<lt>E<gt> markups. I<$file> is the path to the HTML file that is the target of the link. =item I<$perl_map>->C<add_func>(I<$func>, I<$file>) Maps I<$func> to I<$file>. I<$func> is the name of a function described in F<perlfunc.pod>. I<$file> is the name of the HTML file where it is described. =item I<$perl_map>->C<force_func>(I<$state>) Controls interpretation of links of the form LE<lt>funcE<gt>. If I<$state> is true, calls to C<map> will interpret LE<lt>funcE<gt> as LE<lt>perlfunc/funcE<gt>. If I<$state> is false, calls to C<map> will interpret LE<lt>funcE<gt> normally. =item I<$perl_map>->C<set_depth>(I<$depth>) Informs I<$perl_map> of the depth of the referring page in the HTML directory tree. I<$perl_map> needs to know this so that it can construct relative links. =item (I<$base>, I<$page>, I<$section>) = I<$perl_map>->C<map>(I<$base>, I<$page>, I<$section>) Remaps a link. I<$base> is the base URL for the HTML page, if any. I<$page> is the page given in an LE<lt>E<gt> markup. I<$section> is the section given in the LE<lt>E<gt> markup, if any. C<map> returns a new I<$base>, I<$page>, and I<$section> that can be used to construct a link to the HTML page. =back =head1 REQUIRES Nothing. =head1 EXPORTS Nothing. =head1 AUTHOR Steven McDougall, swmcd@world.std.com =head1 COPYRIGHT Copyright (c) 2000 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl. . I<$page> is the page given in an LE<lt>E<gt> markup. I<$section> is the section given in the LE<lt>E<gt> markup, if any. C<map> returns a new I<$base>, I<$page>, and I<$section> that can be used to construct a link to the HTML pagePod-Tree-1.17/lib/Pod/Tree/PerlPod.pm���������������������������������������������������������������000644 �023614 �023614 �00000015207 10132367651 017466� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������use strict; use 5.6.0; use File::Find; use HTML::Stream; use IO::File; use Pod::Tree::HTML; use Pod::Tree::PerlUtil; package Pod::Tree::PerlPod; use base qw(Pod::Tree::PerlUtil); sub new { my %defaults = (col_width => 20, bgcolor => '#ffffff', text => '#000000'); my($class, $perl_dir, $html_dir, $link_map, %options) = @_; my $options = { %defaults, %options, link_map => $link_map }; my %special = map { $_ => 1 } qw(pod/perl pod/perlfunc); my $perl_pod = { perl_dir => $perl_dir, html_dir => $html_dir, top_page => 'pod.html', special => \%special, options => $options }; bless $perl_pod, $class } sub scan { my $perl_pod = shift; $perl_pod->report1("scan"); my $perl_dir = $perl_pod->{perl_dir}; File::Find::find({ wanted => sub {$perl_pod->_scan}, # Perl rocks! no_chdir => 1 }, $perl_dir); } sub _scan { my $perl_pod = shift; my $source = $File::Find::name; my $dest = $source; my $perl_dir = $perl_pod->{perl_dir}; my $html_dir = $perl_pod->{html_dir}; $dest =~ s(^$perl_dir)($html_dir); -d $source and $perl_pod->_scan_dir ( $dest); -f $source and $perl_pod->_scan_file($source, $dest); } sub _scan_dir { my($perl_pod, $dir) = @_; $dir =~ m(/ext$) and do # extensions are handled by Pod::Tree::PerlLib { $File::Find::prune = 1; return; }; -d $dir or mkdir $dir, 0755 or die "Pod::Tree::PerlPod::_scan_dir: Can't mkdir $dir: $!\n"; } sub _scan_file { my($perl_pod, $source, $dest) = @_; $source =~ m( (\w+)\.pod$ )x or return; my $link = $source; my $perl_dir = $perl_pod->{perl_dir}; $link =~ s(^$perl_dir/)(); $link =~ s( \.pod$ )()x; $perl_pod->report2($link); my $name = (split m(/), $link)[-1]; my $desc = $perl_pod->get_description($source); $dest =~ s( \.\w+$ )(.html)x; my $pod = { name => $name, # perldata desc => $desc, # Perl data types link => $link, # pod/perldata source => $source, # .../perl5.5.650/pod/perldata.pod dest => $dest }; # .../public_html/perl/pod/perldata.html $perl_pod->{pods}{$link} = $pod; $perl_pod->{options}{link_map}->add_page($name, $link); } sub index { my $perl_pod = shift; $perl_pod->report1("index"); my $html_dir = $perl_pod->{html_dir}; my $top_page = $perl_pod->{top_page}; my $dest = "$html_dir/$top_page"; my $fh = new IO::File ">$dest"; defined $fh or die "Pod::Tree::PerlPod::index: Can't open $dest: $!\n"; my $stream = new HTML::Stream $fh; my $options = $perl_pod->{options}; my $bgcolor = $options->{bgcolor}; my $text = $options->{text}; my $title = "Perl PODs"; $stream-> HTML->HEAD; $stream-> TITLE->text($title)->_TITLE; $stream->_HEAD -> BODY(BGCOLOR => $bgcolor, TEXT => $text); $stream->H1->t($title)->_H1; $perl_pod->_emit_entries($stream); $stream->_BODY->_HTML; } sub get_top_entry { my $perl_dist = shift; +{ URL => $perl_dist->{top_page}, description => 'PODs' } } sub _emit_entries { my($perl_pod, $stream) = @_; my $pods = $perl_pod->{pods}; my $options = $perl_pod->{options}; my $col_width = $options ->{col_width}; $stream->PRE; my $pods = $perl_pod->{pods}; for my $link (sort keys %$pods) { my $pad = $col_width - length $link; $stream->A(HREF => "$link.html")->t($link)->_A; $pad < 1 and do { $stream->nl; $pad = $col_width; }; $stream->t(' ' x $pad, $pods->{$link}{desc})->nl; } $stream->_PRE; } sub translate { my $perl_pod = shift; $perl_pod->report1("translate"); my $pods = $perl_pod->{pods}; my $special = $perl_pod->{special}; for my $link (sort keys %$pods) { $special->{$link} and next; $perl_pod->report2($link); $perl_pod->_translate($link); } } sub _translate { my($perl_pod, $link) = @_; my $pod = $perl_pod->{pods}{$link}; my $source = $pod->{source}; my $dest = $pod->{dest}; my $options = $perl_pod->{options}; my @path = split m(\/), $link; my $depth = @path - 1; $options->{link_map}->set_depth($depth); my $html = new Pod::Tree::HTML $source, $dest, %$options; $html->translate; } 1 __END__ =head1 NAME Pod::Tree::PerlPod - translate Perl PODs to HTML =head1 SYNOPSIS $perl_map = new Pod::Tree::PerlMap; $perl_pod = new Pod::Tree::PerlPod $perl_dir, $HTML_dir, $perl_map, %opts; $perl_pod->scan; $perl_pod->index; $perl_pod->translate; $top = $perl_pod->get_top_entry; =head1 DESCRIPTION C<Pod::Tree::PerlPod> translates Perl PODs to HTML. It does a recursive subdirectory search through I<$perl_dir> to find PODs. C<Pod::Tree::PerlPod> generates a top-level index of all the PODs that it finds, and writes it to I<HTML_dir>C</pod.html>. C<Pod::Tree::PerlPod> generates and uses an index of the PODs that it finds to construct HTML links. Other modules can also use this index. =head1 METHODS =over 4 =item I<$perl_pod> = C<new> C<Pod::Tree::PerlPod> I<$perl_dir>, I<$HTML_dir>, I<$perl_map>, I<%options> Creates and returns a new C<Pod::Tree::PerlPod> object. I<$perl_dir> is the root of the Perl source tree. I<$HTML_dir> is the directory where HTML files will be written. I<$perl_map> maps POD names to URLs. I<%options> are passed through to C<Pod::Tree::HTML>. =item I<$perl_pod>->C<scan>; Does a recursive subdirectory search through I<$perl_dir> to locate PODs. Each POD that is located is entered into I<$perl_map>. =item I<$perl_pod>->C<index> Generates a top-level index of all the PODs. The index is written to I<HTML_dir>C</pod.html>. =item I<$perl_pod>->C<translate> Translates each POD found by C<scan> to HTML. The HTML pages are written to I<HTML_dir>, in a subdirectory hierarchy that mirrors the the Perl source distribution. =item I<$perl_pod>->C<get_top_entry> Returns a hash reference of the form { URL => $URL, description => $description } C<Pod::Tree::PerlTop> uses this to build a top-level index of all the Perl PODs. =back =head1 LINKING C<Pod::Tree::PerlPod> indexes PODs by the base name of the POD file. To link to F<perlsub.pod>, write L<perlsub> =head1 REQUIRES 5.005; File::Find; HTML::Stream; IO::File; Pod::Tree::HTML; Pod::Tree::PerlUtil; =head1 EXPORTS Nothing. =head1 SEE ALSO L<C<Pod::Tree::HTML>>, L<C<Pod::Tree::PerlMap>>, =head1 AUTHOR Steven McDougall, swmcd@world.std.com =head1 COPYRIGHT Copyright (c) 2000 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl. the base name of the POD file. To link to F<perlsub.pod>, write L<perlsub> =head1 REQUIRES 5.005; File::Find; HTML::Stream; IO::File; Pod::Tree::HTML; Pod::Tree::PerlUtil; =head1 EXPORTS Nothing. =head1 SEE ALSO L<C<Pod::Tree::HTML>>, L<C<Pod::Tree::PerlMap>>, =head1 AUTHOR Steven McDougall, swmcd@world.std.com =head1 COPYRIGHT CopyrigPod-Tree-1.17/lib/Pod/Tree/PerlTop.pm���������������������������������������������������������������000644 �023614 �023614 �00000014536 10420610435 017501� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������use strict; use 5.005; use Pod::Tree::HTML; use Pod::Tree::PerlUtil; package Pod::Tree::HTML::PerlTop; use base qw(Pod::Tree::HTML); sub set_links { my($html, $links) = @_; $html->{links} = $links; } sub _emit_verbatim { my($html, $node) = @_; my $stream = $html->{stream}; my $links = $html->{links}; my $text = $node->get_text; $text =~ s( \n\n$ )()x; my @words = split m/(\s+)/, $text; $stream->PRE; for my $word (@words) { if ($links->{$word}) { my $link = $links->{$word}; $stream->A(HREF => "$link.html")->text($word)->_A; } else { $stream->text($word); } } $stream->_PRE; } package Pod::Tree::PerlTop; use base qw(Pod::Tree::PerlUtil); sub new { my %defaults = (bgcolor => '#ffffff', text => '#000000'); my($class, $perl_dir, $html_dir, $link_map, %options) = @_; my $options = { %defaults, %options, link_map => $link_map }; my $pod_src = -d "$perl_dir/pod" ? 'pod' # for building the doc set from a Perl distribution : 'lib/pod'; # for building the doc set from a Windows installation my $perl_top = { perl_dir => $perl_dir, html_dir => $html_dir, index => 'index.html', pod_src => 'pod', pod_dst => 'pod', page => 'perl', options => $options }; bless $perl_top, $class } sub index { my($perl_top, @translators) = @_; $perl_top->report1("index"); my @entries = map { $_->get_top_entry } @translators; my $html_dir = $perl_top->{html_dir}; my $dest = "$html_dir/index.html"; my $fh = new IO::File ">$dest"; defined $fh or die "Pod::Tree::PerlTop::index: Can't open $dest: $!\n"; my $stream = new HTML::Stream $fh; my $options = $perl_top->{options}; my $bgcolor = $options->{bgcolor}; my $text = $options->{text}; my $title = "Perl Documentation"; $stream-> HTML->HEAD; $stream-> TITLE->text($title)->_TITLE; $stream->_HEAD -> BODY(BGCOLOR => $bgcolor, TEXT => $text); $stream->H1->t($title)->_H1; $perl_top->_emit_entries($stream, @entries); $stream->_BODY->_HTML; } sub _emit_entries { my($perl_top, $stream, @entries) = @_; $stream->UL; for my $entry (@entries) { $stream->LI ->A(HREF => $entry->{URL}) ->t($entry->{description}) ->_A ->_LI; } $stream->_UL; } sub translate { my $perl_top = shift; $perl_top->report1("translate"); my $perl_dir = $perl_top->{perl_dir}; my $options = $perl_top->{options}; $options->{link_map}->set_depth(1); my $html_dir = $perl_top->{html_dir}; my $pod_src = $perl_top->{pod_src}; my $pod_dst = $perl_top->{pod_dst}; my $page = $perl_top->{page}; my $source = "$perl_dir/$pod_src/$page.pod"; my $dest = "$html_dir/$pod_dst/$page.html"; my $html = new Pod::Tree::HTML::PerlTop $source, $dest, %$options; my $links = $perl_top->_get_links; $html->set_links($links); $html->translate; } sub get_top_entry { my $perl_top = shift; my $pod_dst = $perl_top->{pod_dst}; my $page = $perl_top->{page}; +{ URL => "$pod_dst/$page.html", description => 'perl(1)' } } sub _get_links { my $perl_top = shift; my $links = {}; $perl_top->_get_pod_links ($links); $perl_top->_get_dist_links($links); $links } sub _get_pod_links { my($perl_top, $links) = @_; my $perl_dir = $perl_top->{perl_dir}; my $pod_src = $perl_top->{pod_src}; my $dir = "$perl_dir/$pod_src"; opendir(DIR, $dir) or die "Pod::Tree::PerlTop::get_pod_links: Can't opendir $dir: $!\n"; my @files = readdir(DIR); closedir(DIR); my @pods = grep { m( \.pod$ )x } @files; my @others = grep { $_ ne 'perl.pod' } @pods; for my $other (@others) { $other =~ s( \.pod$ )()x; $links->{$other} = $other; } } sub _get_dist_links { my($perl_top, $links) = @_; my $dir = $perl_top->{perl_dir}; opendir(DIR, $dir) or die "Pod::Tree::PerlTop::get_dist_links: Can't opendir $dir: $!\n"; my @files = readdir(DIR); closedir(DIR); my @README = grep { /^README/ } @files; for my $file (@README) { my($base, $ext) = split m(\.), $file; $links->{"perl$ext"} = "../$file"; } } 1 __END__ =head1 NAME Pod::Tree::PerlTop - generate a top-level index for Perl PODs =head1 SYNOPSIS $perl_map = new Pod::Tree::PerlMap; $perl_top = new Pod::Tree::PerlTop $perl_dir, $HTML_dir, $perl_map, %opts; $perl_top->index(@translators); $perl_top->translate; $top = $perl_top->get_top_entry; =head1 DESCRIPTION C<Pod::Tree::PerlTop> generates a top-level index for Perl PODs. It also translates F<perl.pod> to F<perl.html> The translator is specially hacked to insert links into the big verbatim paragraph that lists all the other Perl PODs. =head1 METHODS =over 4 =item I<$perl_top> = C<new> C<Pod::Tree::PerlTop> I<$perl_dir>, I<$HTML_dir>, I<$perl_map>, I<%options> Creates and returns a new C<Pod::Tree::PerlTop> object. I<$perl_dir> is the root of the Perl source tree. I<$HTML_dir> is the directory where HTML files will be written. I<$perl_map> maps POD names to URLs. C<Pod::Tree::PerlTop> uses it to resolve links in the F<perl.pod> page. I<%options> are passed through to C<Pod::Tree::HTML>. =item I<$perl_top>->C<index>(I<@translators>) Generates a top-level index of all the PODs. The index is written to I<HTML_dir>C</index.html>. I<@translators> is a list of other C<Pod::Tree::Perl*> translator objects. C<index> makes a C<get_top_entry> call on each of them to obtain URLs and descriptions of the pages that it links to. =item I<$perl_top>->C<translate> Translates the F<perl.pod> file to HTML. The HTML page is written to I<HTML_dir>C</pod/perl.html> =item I<$perl_top>->C<get_top_entry> Returns a hash reference of the form { URL => $URL, description => $description } C<Pod::Tree::PerlTop> uses this to build a top-level index of all the Perl PODs. =back =head1 REQUIRES 5.005; Pod::Tree::HTML; Pod::Tree::PerlUtil; =head1 EXPORTS Nothing. =head1 SEE ALSO L<C<Pod::Tree::HTML>>, L<C<Pod::Tree::PerlMap>>, =head1 AUTHOR Steven McDougall, swmcd@world.std.com =head1 COPYRIGHT Copyright (c) 2000 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl. RL, description => $description } C<Pod::Tree::PerlTop> uses this to build a top-level index of all the Perl PODs. =back =head1 REQUIRES 5.005; PPod-Tree-1.17/lib/Pod/Tree/PerlUtil.pm��������������������������������������������������������������000644 �023614 �023614 �00000003562 10605602167 017661� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������use strict; use 5.005; package Pod::Tree::PerlUtil; sub mkdir { my($translator, $dir) = @_; -d $dir or CORE::mkdir $dir, 0755 or die "Pod::Tree::PerlUtil::mkdir: Can't mkdir $dir: $!\n"; } sub report1 { my($translator, $routine) = @_; $translator->{options}{v} < 1 and return; my $package = ref $translator; my $name = "${package}::$routine"; my $pad = 60 - length $name; print STDERR $name, ' ' x $pad, "\n"; } sub report2 { my($translator, $page) = @_; my $verbosity = $translator->{options}{v}; $verbosity==2 and do { my $pad = 60 - length $page; print STDERR $page, ' ' x $pad, "\r"; }; $verbosity==3 and print STDERR "$page\n"; } sub get_name { my($node, $source) = @_; my $tree = new Pod::Tree; $tree->load_file($source); my $children = $tree->get_root->get_children; my @pod = grep { is_pod $_ } @$children; my $node1 = $pod[1]; $node1 or return (); my $text = $node1->get_deep_text; $text =~ s(\s+)( )g; $text =~ s(^ )(); $text =~ s( $)(); my($name, $description) = split m(\s+-+\s+), $text, 2; $name or return (); # empty!!! if ($name =~ /\s/ and not $description) { $description = $name; my @description = split ' ', $description; if (@description > 1 and $description[0] =~ /::/) { $name = shift @description; # guess $description = join ' ', @description; } else # desperation { my @source = split m(/), $source; $name = pop @source; } } ($name, $description) } sub get_description { my($node, $source) = @_; my($name, $description) = $node->get_name($source); $description } 1 __END__ Copyright (c) 2000 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. = shift @description; # guess $description = join ' ', @description; } else # desperation { my @source = split m(/), $Pod-Tree-1.17/lib/Pod/Tree/Pod.pm�������������������������������������������������������������������000644 �023614 �023614 �00000015112 10132367651 016636� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2000-2003 by Steven McDougall. This module is free # software; you can redistribute it and/or modify it under the same # terms as Perl itself. package Pod::Tree::Pod; use strict; use IO::File; use Pod::Tree; sub new { my($class, $tree, $dest) = @_; defined $dest or die "Pod::Tree::Pod::new: not enough arguments\n"; my $file = _resolve_dest($dest); my $pod = { tree => $tree, root => $tree->get_root, file => $file, interior => 0, link => 0 }; bless $pod, $class } sub _resolve_dest { my $dest = shift; ref $dest and return $dest; my $fh = new IO::File; $fh->open(">$dest") or die "Pod::Tree::Pod::new: Can't open $dest: $!\n"; $fh } sub translate { my $pod = shift; my $root = $pod->{root}; $pod->_emit_children($root); } sub _emit_children { my($pod, $node) = @_; my $children = $node->get_children; for my $child (@$children) { $pod->_emit_node($child); } } sub _emit_siblings { my($pod, $node) = @_; my $siblings = $node->get_siblings; for my $sibling (@$siblings) { $pod->_emit_node($sibling); } } sub _emit_node { my($pod, $node) = @_; my $type = $node->{type}; for ($type) { /code/ and $pod->_emit_code ($node); /command/ and $pod->_emit_command ($node); /for/ and $pod->_emit_for ($node); /item/ and $pod->_emit_item ($node); /list/ and $pod->_emit_list ($node); /ordinary/ and $pod->_emit_ordinary($node); /sequence/ and $pod->_emit_sequence($node); /text/ and $pod->_emit_text ($node); /verbatim/ and $pod->_emit_verbatim($node); } } sub _emit_code { my($pod, $node) = @_; my $file = $pod->{file}; my $text = $node->get_text; $file->print($text); } sub _emit_command { my($pod, $node) = @_; my $file = $pod->{file}; my $raw = $node->get_raw; $file->print($raw); } sub _emit_for { my($pod, $node) = @_; my $file = $pod->{file}; my $brackets = $node->get_brackets; $file->print($brackets->[0]); $file->print($node->get_text); $file->print($brackets->[1]) if $brackets->[1]; } sub _emit_item { my($pod, $node) = @_; my $file = $pod->{file}; $file->print("=item "); $pod->_emit_children($node); $pod->_emit_siblings($node); } sub _emit_list { my($pod, $node) = @_; my $file = $pod->{file}; my $over = $node->get_raw; $file->print($over); $pod->_emit_children($node); my $back = $node->get_back; $back and $file->print($back->get_raw); } sub _emit_ordinary { my($pod, $node) = @_; $pod->_emit_children($node); } sub _emit_sequence { my($pod, $node) = @_; $pod->{interior}++; for ($node->get_letter) { /I|B|C|E|F|S|X/ and $pod->_emit_element($node), last; /L/ and $pod->_emit_link ($node), last; } $pod->{interior}--; } sub _emit_element { my($pod, $node) = @_; my $letter = $node->get_letter; my $file = $pod->{file}; $file->print("$letter<"); $pod->_emit_children($node); $file->print(">"); } sub _emit_link { my($pod, $node) = @_; my $file = $pod->{file}; $file->print("L<"); my $children = $node->get_raw_kids; for my $child (@$children) { $pod->_emit_node($child); } $file->print(">"); } sub _emit_link_hide { my($pod, $node) = @_; my $file = $pod->{file}; my $target = $node->get_target; my $page = $target->get_page; my $section = $target->get_section; my $slash = $section ? '/' : ''; my $link = "$page$slash$section"; if ($link eq $node->get_deep_text) { $file->print("L<"); $pod->_emit_children($node); $file->print(">"); } else { $pod->{link}++; $file->print("L<"); $pod->_emit_children($node); $page = $pod->_escape($page ); $section = $pod->_escape($section); $file->print("|$page$slash$section>"); $pod->{link}--; } } sub _emit_text { my($pod, $node) = @_; my $file = $pod->{file}; my $text = $node->get_text; $text = $pod->_escape($text); $file->print($text); } sub _escape { my($pod, $text) = @_; $text =~ s/^=(\w)/=Z<>$1/; if ($pod->{interior}) { $text =~ s/([A-Z])</$1E<lt>/g; $text =~ s/>/E<gt>/g; } if ($pod->{link}) { $text =~ s(\|)(E<verbar>)g; $text =~ s(/)(E<sol>)g; } $text =~ s/([\x80-\xff])/sprintf("E<%d>", ord($1))/eg; $text } sub _emit_verbatim { my($pod, $node) = @_; my $file = $pod->{file}; my $text = $node->get_text; $file->print($text); } 1 __END__ =head1 NAME Pod::Tree::Pod - Convert a Pod::Tree back to a POD =head1 SYNOPSIS use Pod::Tree::Pod; $tree = new Pod::Tree; $dest = new IO::File; $dest = "file.pod"; $pod = new Pod::Tree::Pod $tree, $dest; $pod->translate; =head1 DESCRIPTION C<Pod::Tree::Pod> converts a Pod::Tree back to a POD. The destination is fixed when the object is created. The C<translate> method does the actual translation. For convenience, Pod::Tree::Pod can write the POD to a variety of destinations. The C<new> method resolves the I<$dest> argument. =head2 Destination resolution C<Pod::Tree::Pod> can write HTML to either of 2 destinations. C<new> resolves I<$dest> by checking these things, in order: =over 4 =item 1 If I<$dest> is a reference, then it is taken to be an C<IO::File> object that is already open on the file where the POD will be written. =item 2 If I<$dest> is not a reference, then it is taken to be the name of the file where the POD will be written. =back =head1 METHODS =over 4 =item I<$pod> = C<new> C<Pod::Tree::Pod> I<$tree>, I<$dest> Creates a new C<Pod::Tree::Pod> object. I<$tree> is a C<Pod::Tree> object that represents a POD. I<$pod> writes the POD to I<$dest>. See L</Destination resolution> for details. =item I<$pod>->C<translate> Writes the text of the POD. This method should only be called once. =back =head1 DIAGNOSTICS =over 4 =item C<Pod::Tree::Pod::new: not enough arguments> (F) C<new> called with fewer than 2 arguments. =item C<Pod::Tree::HTML::new: Can't open $dest: $!> (F) The destination file couldn't be opened. =back =head1 NOTES =over 4 =item * The destination doesn't actually have to be an C<IO::File> object. It may be any object that has a C<print> method. =back =head1 SEE ALSO perl(1), L<C<Pod::Tree>>, L<C<Pod::Tree::Node>> =head1 AUTHOR Steven McDougall, swmcd@world.std.com =head1 COPYRIGHT Copyright (c) 2000-2003 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. $dest: $!> (F) The destination file couldn't be opened. =back =head1 NOTES =over 4 =item * The destination doesn't actually have to be an C<IO::File> object. It may be any object that has a C<print> method. =back =head1 SEE ALSO perl(1), L<C<Pod::Tree>>, L<C<Pod::Tree::Node>> =head1 AUTHOR Steven McDougall, swmcd@world.std.com =head1 COPYRIGHT Copyright (c) 2000-2003 by Steven McDougall. This module is free software; you Pod-Tree-1.17/lib/Pod/Tree.pm�����������������������������������������������������������������������000644 �023614 �023614 �00000026540 11407600662 016121� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 1999-2009 by Steven McDougall. This module is free # software; you can redistribute it and/or modify it under the same # terms as Perl itself. package Pod::Tree::Stream; sub new { my($package, $fh) = @_; my $stream = { fh => $fh, line => '' }; bless $stream, $package } sub get_paragraph { my $stream = shift; my $fh = $stream->{fh}; my $line = $stream->{line}; defined $line or return undef; my(@lines) = ($line); while ($line = $fh->getline) { push @lines, $line; $line =~ /\S/ or last; } while ($line = $fh->getline) { $line =~ /\S/ and last; push @lines, $line; } $stream->{line} = $line; join '', @lines } package Pod::Tree; require Exporter; use strict; use IO::File; use Pod::Tree::Node; use base qw(Exporter); $Pod::Tree::VERSION = '1.17'; sub new { my $class = shift; my $tree = { loaded => 0, paragraphs => [] }; bless $tree, $class } sub load_file { my($tree, $file, %options) = @_; Pod::Tree::Node->set_filename($file); my $fh = new IO::File; $fh->open($file) or return ''; $tree->load_fh($fh, %options); Pod::Tree::Node->set_filename(""); 1 } sub load_fh { my($tree, $fh, %options) = @_; $tree->{in_pod} = 0; $tree->_load_options(%options); my $limit = $tree->{limit}; my $stream = new Pod::Tree::Stream $fh; my $paragraph; my @paragraphs; while ($paragraph = $stream->get_paragraph) { push @paragraphs, $paragraph; $limit and $limit==@paragraphs and last; } $tree->{paragraphs} = \@paragraphs; $tree->_parse; } sub load_string { my($tree, $string, %options) = @_; my @chunks = split /( \n\s*\n | \r\s*\r | \r\n\s*\r\n )/x, $string; my(@paragraphs); while (@chunks) { push @paragraphs, join '', splice @chunks, 0, 2; } $tree->load_paragraphs(\@paragraphs, %options); } sub load_paragraphs { my($tree, $paragraphs, %options) = @_; $tree->{in_pod} = 1; $tree->_load_options(%options); my $limit = $tree->{limit}; my @paragraphs = @$paragraphs; $limit and splice @paragraphs, $limit; $tree->{paragraphs} = \@paragraphs; $tree->_parse; } sub loaded { shift->{'loaded'} } sub _load_options { my($tree, %options) = @_; my($key, $value); while (($key, $value) = each %options) { $tree->{$key} = $value; } } sub _parse { my $tree = shift; $tree->_make_nodes; $tree->_make_for; $tree->_make_sequences; my $root = $tree->{root}; $root->parse_links; $root->unescape; $root->consolidate; $root->make_lists; $tree->{'loaded'} = 1; } sub _add_paragraph { my($tree, $paragraph) = @_; for ($paragraph) { /^=cut/ and do { $tree->{in_pod}=0; last }; $tree->{in_pod} and do { push @{$tree->{paragraphs}}, $paragraph; last }; /^=\w/ and do { $tree->{in_pod}=1; push @{$tree->{paragraphs}}, $paragraph; last }; } } my %Command = map { $_ => 1 } qw(=pod =cut =head1 =head2 =head3 =head4 =over =item =back =for =begin =end); sub _make_nodes { my $tree = shift; my $paragraphs = $tree->{paragraphs}; my $in_pod = $tree->{in_pod}; my @children; for my $paragraph (@$paragraphs) { my($word) = split(/\s/, $paragraph); my $node; if ($in_pod) { if ($paragraph =~ /^\s/) { $node = verbatim Pod::Tree::Node $paragraph; } elsif ($Command{$word}) { $node = command Pod::Tree::Node $paragraph; $in_pod = $word ne '=cut'; } else { $node = ordinary Pod::Tree::Node $paragraph; } } else { if ($Command{$word}) { $node = command Pod::Tree::Node $paragraph; $in_pod = $word ne '=cut'; } else { $node = code Pod::Tree::Node $paragraph; } } push @children, $node; } $tree->{root} = root Pod::Tree::Node \@children; } sub _make_for { my $tree = shift; my $root = $tree->{root}; my $old = $root->get_children; my @new; while (@$old) { my $node = shift @$old; is_c_for $node and $node->force_for; is_c_begin $node and $node->parse_begin($old); push @new, $node; } $root->set_children(\@new); } sub _make_sequences { my $tree = shift; my $root = $tree->{root}; my $nodes = $root->get_children; for my $node (@$nodes) { is_code $node and next; is_verbatim $node and next; is_for $node and next; $node->make_sequences; } } sub dump { my $tree = shift; $tree->{root}->dump } sub get_root { shift->{root} } sub set_root { my($tree, $root) = @_; $tree->{root} = $root; } sub push { my($tree, @nodes) = @_; my $root = $tree->{root}; my $children = $root->get_children; push @$children, @nodes; } sub pop { my $tree = shift; my $root = $tree->get_root; my $children = $root->get_children; pop @$children } sub walk { my($tree, $sub) = @_; my $root = $tree->get_root; _walk($root, $sub); } sub _walk { my $sub = $_[1]; my $descend = &$sub($_[0]); # :TRICKY: sub can modify node $descend or return; my $node = $_[0]; my $children = $node->get_children; for my $child (@$children) { _walk($child, $sub); } my $siblings = $node->get_siblings; for my $sibling (@$siblings) { _walk($sibling, $sub); } } sub has_pod { my $tree = shift; my $root = $tree->get_root; my $children = $root->get_children; scalar grep { $_->get_type ne 'code' } @$children; } 1 __END__ =head1 NAME Pod::Tree - Create a static syntax tree for a POD =head1 SYNOPSIS use Pod::Tree; $tree = new Pod::Tree; $tree->load_file ( $file, %options) $tree->load_fh ( $fh , %options); $tree->load_string ( $pod , %options); $tree->load_paragraphs(\@pod , %options); $loaded = $tree->loaded; $node = $tree->get_root; $tree->set_root ($node); $node = $tree->pop; $tree->push(@nodes); $tree->walk(\&sub); $tree->has_pod and ... print $tree->dump; =head1 REQUIRES Pod::Escapes =head1 EXPORTS Nothing =head1 DESCRIPTION C<Pod::Tree> parses a POD into a static syntax tree. Applications walk the tree to recover the structure and content of the POD. See L<C<Pod::Tree::Node>> for a description of the tree. =head1 METHODS =over 4 =item I<$tree> = C<new> C<Pod::Tree> Creates a new C<Pod::Tree> object. The syntax tree is initially empty. =item I<$ok> = I<$tree>->C<load_file>(I<$file>, I<%options>) Parses a POD and creates a syntax tree for it. I<$file> is the name of a file containing the POD. Returns null iff it can't open I<$file>. See L</OPTIONS> for a description of I<%options> =item I<$tree>->C<load_fh>(I<$fh>, I<%options>) Parses a POD and creates a syntax tree for it. I<$fh> is an C<IO::File> object that is open on a file containing the POD. See L</OPTIONS> for a description of I<%options> =item I<$tree>->C<load_string>(I<$pod>, I<%options>) Parses a POD and creates a syntax tree for it. I<$pod> is a single string containing the POD. See L</OPTIONS> for a description of I<%options> =item I<$tree>->C<load_paragraphs>(\I<@pod>, I<%options>) Parses a POD and creates a syntax tree for it. I<\@pod> is a reference to an array of strings. Each string is one paragraph of the POD. See L</OPTIONS> for a description of I<%options> =item I<$loaded> = I<$tree>->C<loaded> Returns true iff one of the C<load_>* methods has been called on I<$tree>. =item I<$node> = I<$tree>->C<get_root> Returns the root node of the syntax tree. See L<Pod::Tree::Node> for a description of the syntax tree. =item I<$tree>->C<set_root>(I<$node>) Sets the root of the syntax tree to I<$node>. =item I<$tree>->C<push>(I<@nodes>) Pushes I<@nodes> onto the end of the top-level list of nodes in I<$tree>. =item I<$node> = I<$tree>->C<pop> Pops I<$node> off of the end of the top-level list of nodes in I<$tree>. =item I<$tree>->C<walk>(I<\&sub>) Walks the syntax tree, depth first. Calls I<sub> once for each node in the tree. The current node is passed as the first argument to I<sub>. C<walk> descends to the children and siblings of I<$node> iff I<sub()> returns true. =item I<$tree>->C<has_pod> Returns true iff I<$tree> contains POD paragraphs. =item I<$tree>->C<dump> Pretty prints the syntax tree. This will show you how C<Pod::Tree> interpreted your POD. =back =head1 OPTIONS These options may be passed in the I<%options> hash to the C<load_>* methods. =over 4 =item C<< in_pod => 0 >> =item C<< in_pod => 1 >> Sets the initial value of C<in_pod>. When C<in_pod> is false, the parser ignores all text until the next =command paragraph. The initial value of C<in_pod> defaults to false for C<load_file()> and C<load_fh()> calls and true for C<load_string()> and C<load_paragraphs()> calls. This is usually what you want, unless you want consistency. If this isn't what you want, pass different initial values in the I<%options> hash. =item C<limit> => I<n> Only parse the first I<n> paragraphs in the POD. =back =head1 DIAGNOSTICS =over 4 =item C<load_file>(I<$file>) Returns null iff it can't open I<$file>. =back =head1 NOTES =head2 No round-tripping Currently, C<Pod::Tree> does not provide a complete, exact representation of its input. For example, it doesn't distingish between C<$foo-E<gt>bar> and C<< $foo->bar >> As a result, it is not guaranteed that a file can be exactly reconstructed from its C<Pod::Tree> representation. =head2 LZ<><> markups In the documentation of the L<"sec"> section in this manual page markup, L<C<perlpod>> has always claimed (the quotes are optional) However, there is no way to decide from the syntax alone whether L<foo> is a link to the F<foo> man page or a link to the C<foo> section of this man page. C<Pod::Tree> parses C<< LZ<><foo> >> as a link to a section if C<foo> looks like a section name (e.g. contains whitespace), and as a link to a man page otherswise. In practice, this tends to break links to sections. If you want your section links to work reliably, write them as C<< LZ<><"foo"> >> or C<< LZ<></foo> >>. =head1 SEE ALSO perl(1), L<C<Pod::Tree::Node>>, L<C<Pod::Tree::HTML>> =head1 ACKNOWLEDGMENTS =over 4 =item * <crazyinsomniac@yahoo.com> =item * <joenio@cpan.org> =item * Paul Bettinger <paul@n8geil.de> =item * Sean M. Burke <sburke@spinn.net> =item * Brad Choate <brad@bradchoate.com> =item * Havard Eidnes <he@NetBSD.org> =item * Rudi Farkas <rudif@bluemail.ch> =item * Paul Gibeault <pagibeault@micron.com> =item * Jay Hannah <jhannah@omnihotels.com> =item * Paul Hawkins <phawkins@datajunction.com> =item * Jost Krieger <Jost.Krieger@ruhr-uni-bochum.de> =item * Marc A. Lehmann <pcg@goof.com> =item * Jonas Liljegren <jonas@jonas.rit.se> =item * Thomas Linden <tom@co.daemon.de> =item * Johan Lindstrom <johanl@bahnhof.se> =item * Terry Luedtke <terry_luedtke@nlm.nih.gov> =item * Rob Napier <rnapier@employees.org> =item * Kate L Pugh <kake@earth.li> =item * Christopher Shalah <trance@drizzle.com> =item * Johan Vromans <JVromans@Squirrel.nl> =back =head1 AUTHOR Steven McDougall <swmcd@world.std.com> =head1 COPYRIGHT Copyright (c) 1999-2009 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. item * Johan Lindstrom <johanl@bahnhof.se> =item * Terry Luedtke <terry_luedtke@nlm.nih.gov> =item * Rob Napier <rnapier@employees.org> =item * Kate L PuPod-Tree-1.17/mod2html������������������������������������������������������������������������������000644 �023614 �023614 �00000010350 10132367650 015036� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/local/bin/perl use strict; use File::Find; use File::Path; use Getopt::Long; use HTML::Stream; use IO::File; use Pod::Tree::HTML; my %Options = (bgcolor => '#ffffff'); my %Index; my $ok = GetOptions(\%Options, "base:s", "css:s", "index:s", "toc!", "hr:i", "bgcolor:s", "text:s"); $ok or die "Bad command line options\n"; my($ModDir, $HTMLDir) = @ARGV; $HTMLDir or die "mod2html modDir HTMLDir\n"; $ModDir =~ s( /$ )()x; $HTMLDir =~ s( /$ )()x; mkpath($HTMLDir); my $HTML_inode = (stat $HTMLDir)[1]; umask 0022; find({ wanted => \&Translate, no_chdir => 1 }, $ModDir); Index() if $Options{index}; sub Translate { -d and &Translate_Dir; -f and &Translate_POD; } sub Translate_Dir { my $dir = $File::Find::name; my $inode = (stat $dir)[1]; # always 0 on Win32 if ($inode and $inode == $HTML_inode) { $File::Find::prune = 1; return; } $dir =~ s/^$ModDir/$HTMLDir/o; -d $dir or mkdir $dir, 0755 or die "Can't mkdir $dir: $!\n"; print "$File::Find::name\n"; } sub Translate_POD { m( \.(pm|pod)$ )x or return; my $source = $File::Find::name; Hidden($source) and return; print "$source\n"; my $dest = $source; $dest =~ s/^$ModDir/$HTMLDir/; $dest =~ s( \.\w+$ )(.html)x; my $depth = Depth($source); my $pod = $source; $pod =~ s(^$ModDir/)(); $pod =~ s( \.\w+$ )()x; $Index{$pod} = 1; my $html = new Pod::Tree::HTML $source, $dest; $html->set_options(%Options, depth => $depth); $html->translate; } sub Hidden { my $source = shift; $source =~ m(\.pm$) or return 0; $source =~ s(\.pm$)(.pod); -e $source } sub Depth { my $path = shift; $path =~ s(^$ModDir/)(); my @path = split m(/), $path; @path - 1 } sub Index { my $index = "$HTMLDir/index.html"; my $fh = new IO::File ">$index"; defined $fh or die "Can't open $index: $!\n"; my $stream = new HTML::Stream $fh; my $title = $Options{index}; my $bgcolor = $Options{bgcolor}; my $text = $Options{text}; $stream-> HTML->HEAD; $stream-> TITLE->text($title)->_TITLE; $stream->_HEAD -> BODY(BGCOLOR => $bgcolor, TEXT => $text); $stream->H1->t($title)->_H1; Emit_Entries($stream); $stream->_BODY->_HTML; } sub Emit_Entries { my $stream = shift; $stream->UL; for my $entry (sort keys %Index) { $stream->LI ->A(HREF => "$entry.html") ->t($entry) ->_A ->_LI; } $stream->_UL; } __END__ =head1 NAME mod2html - translate module PODs to HTML =head1 SYNOPSIS C<mod2html> [C<--base> I<url>] [C<--css> I<url>] [C<--index> I<title>] [C<-->[C<no>]C<toc>] [C<--hr> I<level>] [C<--bgcolor> I<#rrggbb>] [C<--text> I<#rrggbb>] I<modDir> I<HTMLdir> =head1 DESCRIPTION C<mod2html> locates all the PODs under I<modDir> translates them to HTML, and writes them to a directory tree under F<HTMLdir>. The directory tree maps the module namespaces. It makes the HTML files world-readable. =head1 OPTIONS =over 4 =item C<--base> I<url> Translate C<LE<lt>E<gt>> sequences into HTML links relative to I<url>. =item C<--css> I<url> Specifies a Cascanding Style Sheet for the generated HTML page. =item C<--index> I<title> Writes an index of all the HTML files to I<HTMLDir>F</index.html>. I<title> is used as the title of the index page. =item C<-->[C<no>]C<toc> Includes or omits the table of contents. Default is to include the TOC. =item C<--hr> I<level> Controls the profusion of horizontal lines in the output, as follows: level horizontal lines 0 none 1 between TOC and body 2 after each =head1 3 after each =head1 and =head2 Default is level 1. =item C<--bgcolor> I<#rrggbb> Set the background color to I<#rrggbb>. Default is white. =item C<--text> I<#rrggbb> Set the text color to I<#rrggbb>. Default is black. =back =head1 REQUIRES L<C<Pod::Tree::HTML>> =head1 SEE ALSO L<C<pod2html>>, L<C<pods2html>>, L<C<Pod::Tree::HTML>> =head1 AUTHOR Steven McDougall, <swmcd@world.std.com> =head1 COPYRIGHT Copyright (c) 2003 by Steven McDougall. This program is free software; you can redistribute it and/or modify it under the same terms as Perl. 1. =item C<--bgcolor> I<#rrggbb> Set the background color to I<#rrggbb>. Default is white. =item C<--text> I<#rrggbb> Set the text color to I<#rrggbb>. Default is black. =back =head1 REQUIRES L<C<Pod::Tree::HTML>> =head1 SEE ALSO L<C<pod2html>>, L<C<pods2html>>, L<C<Pod:Pod-Tree-1.17/perl2html�����������������������������������������������������������������������������000755 �023614 �023614 �00000006750 10032077432 015230� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/local/bin/perl use 5.005; use strict; use Config; use Getopt::Long; use Pod::Tree::PerlBin; use Pod::Tree::PerlDist; use Pod::Tree::PerlFunc; use Pod::Tree::PerlLib; use Pod::Tree::PerlMap; use Pod::Tree::PerlPod; use Pod::Tree::PerlTop; my %Opts; $Opts{toc} = 1; my $ok = GetOptions(\%Opts, "v:i", "toc!", "hr:i", "bgcolor:s", "text:s"); $ok or die "Bad command line options\n"; my($Perl_Dir, $HTML_Dir) = @ARGV; $HTML_Dir or die "perl2html Perl_Dir HTML_Dir\n"; $Perl_Dir =~ s( /$ )()x; $HTML_Dir =~ s( /$ )()x; $| = 1; umask 0022; -d $HTML_Dir or mkdir $HTML_Dir, 0777 or die "Can't mkdir $HTML_Dir: $!\n"; my($Perl_Map); my($Perl_Bin, $Perl_Dist, $Perl_Func, $Perl_Lib, $Perl_Pod, $Perl_Top); $Perl_Map = new Pod::Tree::PerlMap; $Perl_Bin = new Pod::Tree::PerlBin $Perl_Dir, $HTML_Dir, $Perl_Map, %Opts; $Perl_Dist = new Pod::Tree::PerlDist $Perl_Dir, $HTML_Dir, $Perl_Map, %Opts; $Perl_Func = new Pod::Tree::PerlFunc $Perl_Dir, $HTML_Dir, $Perl_Map, %Opts; $Perl_Lib = new Pod::Tree::PerlLib $Perl_Dir, $HTML_Dir, $Perl_Map, %Opts; $Perl_Pod = new Pod::Tree::PerlPod $Perl_Dir, $HTML_Dir, $Perl_Map, %Opts; $Perl_Top = new Pod::Tree::PerlTop $Perl_Dir, $HTML_Dir, $Perl_Map, %Opts; $Perl_Pod ->scan; $Perl_Bin ->scan(split /$Config{path_sep}/, $ENV{PATH}); $Perl_Dist->scan; $Perl_Func->scan; $Perl_Lib ->scan(@INC); $Perl_Bin ->index; $Perl_Dist->index; $Perl_Func->index; $Perl_Lib ->index; $Perl_Pod ->index; $Perl_Top ->index($Perl_Top, $Perl_Pod, $Perl_Lib, $Perl_Bin, $Perl_Dist); $Perl_Bin ->translate; $Perl_Dist->translate; $Perl_Func->translate; $Perl_Lib ->translate; $Perl_Pod ->translate; $Perl_Top ->translate; __END__ =head1 NAME perl2html - generate Perl documentation in HTML =head1 SYNOPSIS B<perl2html> [B<-->[B<no>]B<toc>] [B<--hr> I<level>] [B<--bgcolor> B<#>I<rrggbb>] [B<--text> B<#>I<rrggbb>] [B<--v> I<verbosity>] I<PerlDir> I<HTMLDir> =head1 DESCRIPTION B<perl2html> translates Perl documentation to HTML. I<PerlDir> is the root of the Perl source tree. The HTML pages are organized into a directory tree rooted at I<HTMLDir>. A top-level index is written to I<HTMLDir>C</index.html> In addition to the Perl sources, B<perl2html> searches C<@INC> for module PODs, and C<$ENV{PATH}> for program PODS. All the HTML pages are created world-readable. I<Perldir> and I<HTMLDir> must be absolute path names. =head1 OPTIONS =over 4 =item C<-->[C<no>]C<toc> Includes or omits a table of contents in each page. Default is to include the TOC. =item C<--hr> I<level> Controls the profusion of horizontal lines in the output, as follows: level horizontal lines 0 none 1 between TOC and body 2 after each =head1 3 after each =head1 and =head2 Default is level 1. =item C<--bgcolor> I<#rrggbb> Set the background color to I<#rrggbb>. Default is off-white. =item C<--text> I<#rrggbb> Set the text color to I<#rrggbb>. Default is black. =item C<--v> I<verbosity> Verbosity level: 0, 1, 2, 3 =back =head1 REQUIRES Perl 5 L<C<Getopt::Long>>, =head1 SEE ALSO L<C<pods2html>>, L<C<Pod::Tree>>, L<C<Pod::Tree::HTML>>, L<C<Pod::Tree::PerlBin>>, L<C<Pod::Tree::PerlDist>>, L<C<Pod::Tree::PerlFunc>>, L<C<Pod::Tree::PerlLib>>, L<C<Pod::Tree::PerlMap>>, L<C<Pod::Tree::PerlPod>>, L<C<Pod::Tree::PerlTop>> =head1 AUTHOR Steven McDougall, swmcd@world.std.com =head1 COPYRIGHT Copyright 2000 by Steven McDougall. This program is free software; you can redistribute it and/or modify it under the same terms as Perl. 1 REQUIRES Perl 5 L<C<GPod-Tree-1.17/pod.css�������������������������������������������������������������������������������000644 �023614 �023614 �00000001022 11167777054 014671� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Example style sheet for pod*2html converters */ a:link { background: #ff8080 } body { background: #f0f0f0 } code { background: #c0ffc0 } dd { background: #ffffe0 } dl { background: #fffff0 } dt { background: #ffffc0 } h1 { background: #ffc0c0 } h2 { background: #ffe0e0 } hr { background: #ff0000; height: 5px } i { background: #ffc0c0 } li { background: #e0e0e0 } ol { background: #fff0ff } p { background: #f0f0ff } pre { background: #f0fff0 } ul { background: #f0ffff } heet for pod*2html converters */ a:link { background: #ff8080 } body { background: #f0f0f0 } code { background: #c0ffc0 } dd { background: #ffffe0 } dl { background: #fffff0 } dt { background: #ffffc0 } h1 { background: #ffc0c0 } h2 { background: #ffe0e0 } hr { background: #ff0000; height: 5px } i { background: #ffc0c0 } li { background: #e0e0e0 } ol { background: #fff0ff } p { background: #f0f0ff } pre { background: #f0fff0 } ul { backPod-Tree-1.17/pods2html�����������������������������������������������������������������������������000755 �023614 �023614 �00000016567 11407641523 015247� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/local/bin/perl use strict; use File::Find; use File::Path; use Getopt::Long; use HTML::Stream; use IO::File; use Pod::Tree::HTML; use File::Spec; my %Options = (bgcolor => '#ffffff', text => '#000000', hr => 1, toc => 1 ); my $ok = GetOptions(\%Options, "base:s", "css:s", "bgcolor:s", "empty", "index:s", "module", "text:s", "toc!", "hr:i", "variables:s"); $ok or die "Bad command line options\n"; my %Index; my @Dirs; my($PodDir, $HTMLDir, $Template, @Variables) = @ARGV; $HTMLDir or die "pods2html PodDir HTMLDir\n"; $PodDir = canonpath File::Spec $PodDir; $HTMLDir = rel2abs File::Spec $HTMLDir; mkpath($HTMLDir); do $Options{variables} if $Options{variables}; for (@Variables) { chomp; my($name, $value) = split /=/, $_, 2; $name =~ s(^\$)(); ${$Pod::Tree::HTML::{$name}} = $value; } umask 0022; find({ wanted => \&Translate, no_chdir => 1 }, $PodDir); Index () if $Options{index}; Cleanup() unless $Options{empty}; sub Translate { -d and &Translate_Dir; -f and &Translate_POD; } sub MkDir { my $dir = shift; -d $dir and return; mkdir $dir, 0755 or die "Can't mkdir $dir: $!\n"; push @Dirs, $dir; } sub Translate_Dir { my $dir = $File::Find::name; if ($HTMLDir eq rel2abs File::Spec $dir) { $File::Find::prune = 1; return; } if ($Options{module} and ( m(/t$) or m(/blib$) ) ) { $File::Find::prune = 1; return; } $dir =~ s/^\Q$PodDir/$HTMLDir/o; -d $dir or MkDir $dir; print "$File::Find::name\n"; } sub Translate_POD { m( \.(pm|pod)$ )x or return; my $source = $File::Find::name; Hidden($source) and return; print "$source\n"; my $dest = $source; $dest =~ s/^\Q$PodDir/$HTMLDir/o; $dest =~ s( \.\w+$ )(.html)x; my $depth = Depth($source); my $pod = $source; $pod =~ s(^$PodDir/)(); $pod =~ s( \.\w+$ )()x; $Index{$pod} = 1; my $html = new Pod::Tree::HTML $source, $dest, %Options; $html->set_options(depth => $depth); $html->translate($Template); } sub Hidden { my $source = shift; $source =~ m(\.pm$) or return 0; $source =~ s(\.pm$)(.pod); -e $source } sub Depth { my $source = shift; my $tree = new Pod::Tree; $tree->load_file($source); my $children = $tree->get_root->get_children; my @pod = grep { is_pod $_ } @$children; my $node1 = $pod[1]; $node1 or return ''; my $text = $node1->get_deep_text; my($name) = split m(\s+-+\s+), $text; $name =~ s(^\s+)(); my @name = split /::/, $name; @name-1 } sub Index { my $index = "$HTMLDir/index.html"; my $fh = new IO::File ">$index"; defined $fh or die "Can't open $index: $!\n"; my $stream = new HTML::Stream $fh; my $title = $Options{index}; my $bgcolor = $Options{bgcolor}; my $text = $Options{text}; $stream-> HTML->HEAD; $stream-> TITLE->text($title)->_TITLE; $stream->_HEAD -> BODY(BGCOLOR => $bgcolor, TEXT => $text); $stream->H1->t($title)->_H1; Emit_Entries($stream); $stream->_BODY->_HTML; } sub Emit_Entries { my $stream = shift; $stream->UL; for my $entry (sort keys %Index) { $stream->LI ->A(HREF => "$entry.html") ->t($entry) ->_A ->_LI; } $stream->_UL; } sub Cleanup { while (@Dirs) { my $dir = pop @Dirs; rmdir $dir; # does nothing unless $dir is empty } } __END__ =head1 NAME pods2html - translate a tree of PODs to HTML =head1 SYNOPSIS C<pods2html> [C<--base> I<url>] [C<--css> I<url>] [C<--empty>] [C<--index> I<title>] [C<--module>] [C<-->[C<no>]C<toc>] [C<--hr> I<level>] [C<--bgcolor> I<#rrggbb>] [C<--text> I<#rrggbb>] [C<--variables> I<values.pl>] I<PODdir> I<HTMLdir> [F<template> [I<variable>=I<value> ...]] =head1 DESCRIPTION C<pods2html> finds all the F<.pod> and F<.pm> files in the directory tree rooted at I<PODdir>. It translates each POD to HTML, and writes it to a parallel directory tree rooted at I<HTMLdir> It makes the HTML files world-readable. If a F<template> file is provided, then F<template> will be filled in by the C<Text::Template> module and written to F<dest>. Here is a minimal template, showing all the variables that are set by C<pods2html>. <html> <head> <base href="{$base}"> <link href="{$css}" rel="stylesheet" type="text/css"> <title>{$title} {$toc} {$body} If the C<--variables> option is provided, then the file I will be executed with a C call before the template is filled in. I may contain arbitrary Perl code. The program fragments in the template are evaulted in the C package. Any variables that I sets in this package will be available to the template. Additional scalar variables may be set on the command line with the I=I syntax. Variables set on the command line override variables set in I. =head1 OPTIONS =over 4 =item C<--base> I Specifies a base URL for HTML links. =item C<--css> I Specifies a Cascanding Style Sheet for the generated HTML pages. Here are example rules for all the different HTML elements that may appear in a POD. a:link { background: #ff8080 } body { background: #f0f0f0 } code { background: #c0ffc0 } dd { background: #ffffe0 } dl { background: #fffff0 } dt { background: #ffffc0 } h1 { background: #ffc0c0 } h2 { background: #ffe0e0 } hr { background: #ff0000; height: 5px } i { background: #ffc0c0 } li { background: #e0e0e0 } ol { background: #fff0ff } p { background: #f0f0ff } pre { background: #f0fff0 } ul { background: #f0ffff } =item C<--empty> Creates HTML files for empty PODs. If this option is not provided, then no HTML file is created for empty PODs. =item C<--index> I Writes an index of all the HTML files to I<HTMLDir>F</index.html>. I<title> is used as the title of the index page. =item C<--module> Ignores files in directories named F<t/> and F<blib/>. Useful for translating PODs in a module development directory. =item C<-->[C<no>]C<toc> Includes or omits the table of contents. Default is to include the TOC. =item C<--hr> I<level> Controls the profusion of horizontal lines in the output, as follows: level horizontal lines 0 none 1 between TOC and body 2 after each =head1 3 after each =head1 and =head2 Default is level 1. =item C<--bgcolor> I<#rrggbb> Set the background color to I<#rrggbb>. Default is white. =item C<--text> I<#rrggbb> Set the text color to I<#rrggbb>. Default is black. =back =head1 REQUIRES L<C<Pod::Tree::HTML>>, L<C<HTML::Stream>> =head1 BUGS The recursion check doesn't work on Win32. This means that the program will enter an infinite recursion if I<HTMLdir> is a subdirectory of I<PODdir>. =head1 SEE ALSO L<C<pod2html>>, L<C<Pod::Tree::HTML>> =head1 AUTHOR Steven McDougall, <swmcd@world.std.com> =head1 COPYRIGHT Copyright (c) 1999-2010 by Steven McDougall. This program is free software; you can redistribute it and/or modify it under the same terms as Perl. ack =head1 REQUIRES L<C<Pod::Tree::HTML>>, L<C<HTML::Stream>> =head1 BUGS The recursion check doesn't work on Win32. This means thaPod-Tree-1.17/podtree2html��������������������������������������������������������������������������000755 �023614 �023614 �00000007752 11167777117 015754� 0����������������������������������������������������������������������������������������������������ustar�00swmcd���������������������������swmcd���������������������������000000 �000000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/local/bin/perl use strict; use Getopt::Long; use Pod::Tree::HTML; my %Options; $Options{toc} = 1; my $ok = GetOptions(\%Options, "base:s", "css:s", "toc!", "hr:i", "bgcolor:s", "text:s", "variables:s"); $ok or die "Bad command line options\n"; umask 0022; @ARGV < 2 and die "podtree2html PODfile HTMLfile [templateFile]\n"; my($source, $dest, $template, @variables) = @ARGV; my $html = new Pod::Tree::HTML $source, $dest; $html->set_options(%Options); do $Options{variables} if $Options{variables}; for (@variables) { chomp; my($name, $value) = split /=/, $_, 2; $name =~ s(^\$)(); ${$Pod::Tree::HTML::{$name}} = $value; } $html->translate($template); __END__ =head1 NAME podtree2html - translate a POD to HTML =head1 SYNOPSIS C<podtree2html> [C<--base> I<url>] [C<--css> I<url>] [C<-->[C<no>]C<toc>] [C<--hr> I<level>] [C<--bgcolor> I<#rrggbb>] [C<--text> I<#rrggbb>] [C<--variables> I<values.pl>] F<source> F<dest> [F<template>] [I<variable>=I<value> ...]] =head1 DESCRIPTION C<podtree2html> reads the POD in file F<source>, translates it to HTML, and writes it to file F<dest>. F<dest> is created world-readable. If a F<template> file is provided, then F<template> will be filled in by the C<Text::Template> module and written to F<dest>. Here is a minimal template, showing all the variables that are set by C<podtree2html>. <html> <head> <base href="{$base}"> <link href="{$css}" rel="stylesheet" type="text/css"> <title>{$title} {$toc} {$body} If the C<--variables> option is provided, then the file I will be executed with a C call before the template is filled in. I may contain arbitrary Perl code. The program fragments in the template are evaulted in the C package. Any variables that I sets in this package will be available to the template. Additional scalar variables may be set on the command line with the I=I syntax. Do not prefix I with a C<$> sigil. Variables set on the command line override variables set in I. =head1 OPTIONS =over 4 =item C<--base> I Translate CE> sequences into HTML links relative to I. =item C<--css> I Specifies a Cascanding Style Sheet for the generated HTML page. Here are example rules for all the different HTML elements that may appear in a POD. a:link { background: #ff8080 } body { background: #f0f0f0 } code { background: #c0ffc0 } dd { background: #ffffe0 } dl { background: #fffff0 } dt { background: #ffffc0 } h1 { background: #ffc0c0 } h2 { background: #ffe0e0 } hr { background: #ff0000; height: 5px } i { background: #ffc0c0 } li { background: #e0e0e0 } ol { background: #fff0ff } p { background: #f0f0ff } pre { background: #f0fff0 } ul { background: #f0ffff } =item C<-->[C]C Includes or omits the table of contents. Default is to include the TOC. =item C<--hr> I Controls the profusion of horizontal lines in the output, as follows: level horizontal lines 0 none 1 between TOC and body 2 after each =head1 3 after each =head1 and =head2 Default is level 1. =item C<--bgcolor> I<#rrggbb> Set the background color to I<#rrggbb>. Default is white. =item C<--text> I<#rrggbb> Set the text color to I<#rrggbb>. Default is black. =item C<--variables> I Execute the file I with a C call before filling in I