File Coverage

blib/lib/Pod/Abstract.pm
Criterion Covered Total %
statement 38 38 100.0
branch n/a
condition n/a
subroutine 9 9 100.0
pod 3 3 100.0
total 50 50 100.0


line stmt bran cond sub pod time code
1             package Pod::Abstract;
2 6     6   960757 use strict;
  6         13  
  6         245  
3 6     6   63 use warnings;
  6         13  
  6         409  
4              
5 6     6   3622 use Pod::Abstract::Node;
  6         20  
  6         276  
6 6     6   3727 use Pod::Abstract::Path;
  6         26  
  6         322  
7 6     6   2047 use Pod::Abstract::Parser;
  6         29  
  6         8426  
8 6     6   3448 use IO::String;
  6         31487  
  6         2308  
9              
10             our $VERSION = '0.26';
11              
12             =head1 NAME
13              
14             Pod::Abstract - Abstract document tree for Perl POD documents
15              
16             =head1 SYNOPSIS
17              
18             use Pod::Abstract;
19             use Pod::Abstract::BuildNode qw(node);
20              
21             # Get all the first level headings, and put them in a verbatim block
22             # at the start of the document
23             my $pa = Pod::Abstract->load_filehandle(\*STDIN);
24             my @headings = $pa->select('/head1@heading');
25             my @headings_text = map { $_->pod } @headings;
26             my $headings_node = node->verbatim(join "\n",@headings_text);
27              
28             $pa->unshift( node->cut );
29             $pa->unshift( $headings_node );
30             $pa->unshift( node->pod );
31              
32             print $pa->pod;
33              
34             =head1 DESCRIPTION
35              
36             C provides a means to load a POD document without direct
37             reference to it's syntax, and perform manipulations on the abstract
38             syntax tree.
39              
40             This can be used to support additional features for POD, to format
41             output, to compile into alternative formats, etc.
42              
43             POD documents are not a natural tree, but do have a logical nesting
44             structure. C makes this explicit - C<=head*> commands
45             create nested sections, =over and =back create nested lists, etc.
46              
47             The "paf summary" command provides easy visualisation of the created
48             tree.
49              
50             =head2 USAGE
51              
52             C allows easy manupulation and traversal of POD or Perl
53             files containing POD, without having to manually do any string
54             manipulation.
55              
56             It allows you to easily write formatters, filters, test scripts, etc
57             for POD.
58              
59             C is based on the standard L module.
60              
61             =head2 PROCESSING MODEL
62              
63             C allows documents to be loaded, decorated, and
64             manupulated in multiple steps. It can also make generating a POD
65             formatter very simple. You can easily add features to an existing POD
66             formatter, since any POD abstract object can be written out as a POD
67             document.
68              
69             Rather than write or fork a whole translator, a single inline
70             "decorator" can be added.
71              
72             The C utility provides a good starting point, which also allows
73             you to hook in to an existing filter/transform library. Add a
74             C class to the namespace and it should start
75             working as a C command.
76              
77             =head2 EXAMPLE
78              
79             Suppose you are frustrated by the verbose list syntax used by regular
80             POD. You might reasonably want to define a simplified list format for
81             your own use, except POD formatters won't support it.
82              
83             With Pod::Abstract you can write an inline filter to convert:
84              
85             * item 1
86             * item 2
87             * item 3
88              
89             into:
90              
91             =over
92              
93             =item *
94              
95             item 1
96              
97             =item *
98              
99             item 2
100              
101             =item *
102              
103             item 3
104              
105             =back
106              
107             This transformation can be performed on the document tree. If your
108             formatter does not use Pod::Abstract, you can pipe out POD and use a
109             regular formatter. If your formatter supports Pod::Abstract, you can
110             feed in the syntax tree without having to re-serialise and parse the
111             document.
112              
113             The source document is still valid Pod, you aren't breaking
114             compatibility with regular perldoc just by making Pod::Abstract
115             transformations.
116              
117             =head2 POD SUPPORT
118              
119             C supports all POD rules defined in perlpodspec.
120              
121             =head1 COMPONENTS
122              
123             Pod::Abstract is comprised of:
124              
125             =over
126              
127             =item *
128              
129             The parser, which loads a document tree.
130              
131             e.g:
132              
133             my $pa = Pod::Abstract->load_filehandle(\*STDIN);
134              
135             =item *
136              
137             The document tree, returned from the parser. The root node (C<$pa>
138             above) represents the whole document. Calling B<< ->pod >> on the root node
139             will give you back your original document.
140              
141             Note the document includes C<#cut> nodes, which are generally the Perl
142             code - the parts that aren't POD. These will be included in the output
143             of B<< ->pod >> unless you remove them, so you can modify a Perl module
144             as a POD document in POD abstract, and it will work the same
145             afterwards.
146              
147             e.g
148              
149             my $pod_text = $pa->pod; # $pod_text is reserialized from the tree.
150              
151             See L
152              
153             =item *
154              
155             L, a node selection language. Called via C<<
156             $node->select(PATH_EXP) >>. Pod paths are a powerful feature allowing
157             declarative traversal of a document.
158              
159             For example -
160              
161             "Find all head2s under METHODS"
162              
163             /head1[@heading=~{^METHODS$}]/head2
164              
165             "Find all bold text anywhere"
166              
167             //B
168              
169             =item *
170              
171             The node builder, L. This exports methods to
172             allow adding content to POD documents.
173              
174             You can also combine documents -
175              
176             use Pod::Abstract::BuildNode qw(node nodes);
177             # ...
178             my @nodes = nodes->from_pod($pod);
179              
180             Where C<$pod> is a text with POD formatting.
181              
182             =back
183              
184             =head2 Using paths
185              
186             The easiest way to traverse a C<$pa> tree is to use the C
187             nodes, and paths.
188              
189             C
190             L. These nodes also support the select method - for example:
191              
192             my @headings = $pa->select('/head1'); # Get all heading 1
193             my @X = $headings[0]->select('//:X'); # Get all X (index) sequences inside that heading
194             my @indices = map { $_->text } @X; # Map out the contents of those as plain text.
195              
196             You can combine path expressions with other methods, for example - C
197             will give all the child nodes of a POD node, C, C, C and
198             C allow traversal from a given node.
199              
200             From any node you can then call C
201             there. The above methods also have comparable expressions in
202             L.
203              
204             =head2 Traversing for document generation
205              
206             To traverse the tree for document generation, you can follow C from
207             the first node, then examine each node type to determine what you should
208             generate.
209              
210             The nodes will generate in a tree, so headings have nested children with
211             subheadings and texts. In most cases the C method will give the text (or
212             POD nodes) next to the command, while the C method will give the
213             contained POD.
214              
215             Special types are C<:paragraph>, C<:text>, <#cut>. Interior sequences are also
216             started with a : for their type, like C<:L>, C<:B>, C<:I> for Link, Bold,
217             Italic.
218              
219             Use the C<< $node->ptree >> method to see a visualised tree of a parsed document.
220              
221             =head1 METHODS
222              
223             =cut
224              
225              
226             =head2 load_file
227              
228             my $pa = Pod::Abstract->load_file( FILENAME );
229              
230             Read the POD document in the named file. Returns the root node of the
231             document.
232              
233             =cut
234              
235             sub load_file {
236 1     1 1 223361 my $class = shift;
237 1         4 my $filename = shift;
238            
239 1         15 my $p = Pod::Abstract::Parser->new;
240 1         310 $p->parse_from_file($filename);
241 1         8 $p->root->coalesce_body(":verbatim");
242 1         9 $p->root->coalesce_body(":text");
243              
244             # Remove any blank verbatim nodes.
245 1         11 $_->detach foreach $p->root->select('//:verbatim[ . =~ {^[\s]*$}]');
246 1         8 return $p->root;
247             }
248              
249             =head2 load_filehandle
250              
251             my $pa = Pod::Abstract->load_file( FH );
252              
253             Load a POD document from the provided filehandle reference. Returns
254             the root node of the document.
255              
256             =cut
257              
258             sub load_filehandle {
259 10     10 1 22 my $class = shift;
260 10         18 my $fh = shift;
261              
262 10         69 my $p = Pod::Abstract::Parser->new;
263 10         577 $p->parse_from_filehandle($fh);
264 10         39 $p->root->coalesce_body(":verbatim");
265 10         64 $p->root->coalesce_body(":text");
266              
267             # Remove blank verbatim nodes.
268 10         44 $_->detach foreach $p->root->select('//:verbatim[ . =~ {^[\s]*$}]');
269 10         43 return $p->root;
270             }
271              
272             =head2 load_string
273              
274             my $pa = Pod::Abstract->load_string( STRING );
275              
276             Loads a POD document from a scalar string value. Returns the root node
277             of the document.
278              
279             =cut
280              
281             sub load_string {
282 10     10 1 453918 my $class = shift;
283 10         27 my $str = shift;
284            
285 10         83 my $fh = IO::String->new($str);
286 10         689 return $class->load_filehandle($fh);
287             }
288              
289             =head1 AUTHOR
290              
291             Ben Lilburne
292              
293             =head1 COPYRIGHT AND LICENSE
294              
295             Copyright (C) 2009-2025 Ben Lilburne
296              
297             This program is free software; you can redistribute it and/or modify
298             it under the same terms as Perl itself.
299              
300             =cut
301              
302             1;