File Coverage

blib/lib/Pod/Abstract/BuildNode.pm
Criterion Covered Total %
statement 61 94 64.8
branch 4 8 50.0
condition n/a
subroutine 15 24 62.5
pod 15 18 83.3
total 95 144 65.9


line stmt bran cond sub pod time code
1             package Pod::Abstract::BuildNode;
2 3     3   17 use strict;
  3         7  
  3         110  
3              
4 3     3   14 use Exporter;
  3         6  
  3         100  
5 3     3   17 use Pod::Abstract;
  3         5  
  3         73  
6 3     3   1754 use Pod::Abstract::Parser;
  3         10  
  3         158  
7 3     3   21 use Pod::Abstract::Node;
  3         6  
  3         62  
8 3     3   15 use base qw(Exporter);
  3         8  
  3         3815  
9              
10             our $VERSION = '0.20';
11              
12             our @EXPORT_OK = qw(node nodes);
13              
14 7     7 0 52 sub node { 'Pod::Abstract::BuildNode' };
15 1     1 0 5 sub nodes { 'Pod::Abstract::BuildNode' };
16              
17             =head1 NAME
18              
19             Pod::Abstract::BuildNode - Build new nodes for use in Pod::Abstract.
20              
21             =head1 SYNOPSIS
22              
23             use Pod::Abstract::BuildNode qw(node nodes); # shorthand
24            
25             my $root_doc = node->root;
26             for(my $i = 1; $i < 10; $i ++) {
27             $root_doc->push(node->head1("Heading number $i"));
28             }
29             print $root_doc->pod;
30              
31             =head1 DESCRIPTION
32              
33             For building a new Pod::Abstract document, or adding nodes to an
34             existing one. This provides easy methods to generate correctly set
35             nodes for most common Pod::Abstract elements.
36              
37             =head1 NOTES
38              
39             Pod::Abstract::BuildNode can export two functions, C and
40             C. These are constant functions to provide a shorthand so
41             instead of writing:
42              
43             use Pod::Abstract::BuildNode;
44             # ...
45             my @nodes = Pod::Abstract::BuildNode->from_pod( $pod );
46              
47             You can instead write:
48              
49             use Pod::Abstract::BuildNode qw(node nodes);
50             # ...
51             my @nodes = nodes->from_pod($pod);
52              
53             Which is more readable, and less typing. C and C are both
54             synonyms of C.
55              
56             This shorthand form is shown in all the method examples below. All
57             methods operate on the class.
58              
59             =head1 METHODS
60              
61             =cut
62              
63             =head2 from_pod
64              
65             my @nodes = nodes->from_pod($pod_text);
66              
67             Given some literal Pod text, generate a full subtree of nodes. The
68             returned array is all of the top level nodes. The full document tree
69             will be populated under the returned nodes.
70              
71             =cut
72              
73             sub from_pod {
74 1     1 1 2 my $class = shift;
75 1         2 my $str = shift;
76            
77 1         6 my $root = Pod::Abstract->load_string($str);
78 1 50       17 return undef unless $root;
79            
80 1         3 my @r = map { $_->detach; $_ } $root->children;
  1         4  
  1         3  
81 1         10 return @r;
82             }
83              
84             =head2 root
85              
86             my $root = node->root;
87              
88             Generate a root node. A root node generates no output, and is used to
89             hold a document tree. Use this to make a new document.
90              
91             =cut
92              
93             sub root {
94 2     2 1 4 my $class = shift;
95 2         18 my $para = Pod::Abstract::Node->new(
96             type => '[ROOT]',
97             );
98             }
99              
100             =head2 begin
101              
102             my $begin_block = node->begin($command);
103              
104             Generates a begin/end block. Nodes nested inside the begin node will
105             appear between the begin/end.
106              
107             Note that there is no corresponding C method - the end command
108             belongs to it's corresponding begin.
109              
110             =cut
111              
112             sub begin {
113 0     0 1 0 my $class = shift;
114 0         0 my $cmd = shift;
115            
116 0         0 my $begin = Pod::Abstract::Node->new(
117             type => 'begin',
118             body => $cmd,
119             close_element => Pod::Abstract::Node->new(
120             type => 'end',
121             body => $cmd,
122             ),
123             );
124 0         0 return $begin;
125             }
126              
127             =head2 for
128              
129             my $for = node->for('overlay from ');
130              
131             Create a =for node. The argument is the literal body of the for node,
132             no parsing will be performed.
133              
134             =cut
135              
136             sub for {
137 0     0 1 0 my $class = shift;
138 0         0 my $str = shift;
139              
140 0         0 return Pod::Abstract::Node->new(
141             type => 'for',
142             body => $str,
143             );
144             }
145              
146             =head2 paragraph
147              
148             my $para = node->paragraph('Pod text');
149              
150             Generates a Pod paragraph, possibly containing interior sequences. The
151             argument will be parsed as Pod, and will generate text and sequence
152             nodes inside the paragraph.
153              
154             =cut
155              
156             sub paragraph {
157 2     2 1 5 my $class = shift;
158 2         3 my $str = shift;
159            
160 2         8 my $para = Pod::Abstract::Node->new(
161             type => ':paragraph',
162             );
163 2         7 my $parser = Pod::Abstract::Parser->new;
164 2         191 my $pt = $parser->parse_text($str);
165            
166 2 50       7 if($pt) {
167 2         6 $parser->load_pt($para,$pt);
168             } else {
169 0         0 return undef;
170             }
171             }
172              
173             =head2 verbatim
174              
175             my $v = node->verbatim($text);
176              
177             Add the given text as a verbatim node to the document. All lines in
178             the fiven C<$text> will be indented by one space to ensure they are
179             treated as verbatim.
180              
181             =cut
182              
183             sub verbatim {
184 0     0 1 0 my $class = shift;
185 0         0 my $str = shift;
186            
187 0         0 my @strs = split "\n",$str;
188 0         0 for(my $i = 0; $i < @strs; $i ++) {
189 0         0 my $str_line = $strs[$i];
190 0         0 $strs[$i] = ' '.$str_line;
191             }
192 0         0 my $verbatim = Pod::Abstract::Node->new(
193             type => ':verbatim',
194             body => (join("\n", @strs) . "\n\n"),
195             );
196 0         0 return $verbatim;
197             }
198              
199             =head2 heading
200              
201             my $head2 = node->heading(2, $heading);
202              
203             Generate a heading node at the given level. Nodes that "belong" in the
204             heading's section should be nested in the heading node. The
205             C<$heading> text will be parsed for interior sequences.
206              
207             =cut
208              
209             sub heading {
210 1     1 1 45 my $class = shift;
211 1         2 my $level = shift;
212 1         2 my $heading = shift;
213              
214 1         4 my $attr_node = Pod::Abstract::Node->new(
215             type => '@attribute',
216             );
217 1         7 my $parser = Pod::Abstract::Parser->new;
218 1         101 my $pt = $parser->parse_text($heading);
219 1         6 $parser->load_pt($attr_node, $pt);
220            
221 1         6 my $element_node = Pod::Abstract::Node->new(
222             type => "head$level",
223             heading => $attr_node,
224             body_attr => 'heading',
225             );
226 1         46 return $element_node;
227             }
228              
229             =head2 head1
230              
231             node->head1($heading);
232              
233             =cut
234              
235             sub head1 {
236 1     1 1 2 my $class = shift;
237 1         2 my $heading = shift;
238            
239 1         5 return $class->heading(1,$heading);
240             }
241              
242             =head2 head2
243              
244             node->head2($heading);
245              
246             =cut
247              
248             sub head2 {
249 0     0 1 0 my $class = shift;
250 0         0 my $heading = shift;
251            
252 0         0 return $class->heading(2,$heading);
253             }
254              
255             =head2 head3
256              
257             node->head3($heading);
258              
259             =cut
260              
261             sub head3 {
262 0     0 1 0 my $class = shift;
263 0         0 my $heading = shift;
264            
265 0         0 return $class->heading(3,$heading);
266             }
267              
268             =head2 head4
269              
270             node->head4($heading);
271              
272             =cut
273              
274             sub head4 {
275 0     0 1 0 my $class = shift;
276 0         0 my $heading = shift;
277            
278 0         0 return $class->heading(4,$heading);
279             }
280              
281             =head2 over
282              
283             my $list = node->over([$num]);
284              
285             Generates an over/back block, to contain list items. The optional
286             parameter C<$num> specifies the number of spaces to indent by. Note
287             that the back node is part of the over, there is no separate back
288             method.
289              
290             =cut
291              
292             sub over {
293 1     1 1 3 my $class = shift;
294 1         2 my $number = shift;
295 1 50       5 $number = '' unless defined $number;
296            
297 1 50       8 return Pod::Abstract::Node->new(
298             type => 'over',
299             body => ($number ? $number : undef),
300             close_element => Pod::Abstract::Node->new(
301             type => 'back',
302             ),
303             );
304             }
305              
306             =head2 item
307              
308             my $item = node->item('*');
309              
310             Generates an item with the specified label. To fill in the text of the
311             item, nest paragraphs into the item. Items should be contained in over
312             nodes.
313              
314             =cut
315              
316             sub item {
317 1     1 1 2 my $class = shift;
318 1         1 my $label = shift;
319            
320 1         5 my $attr_node = Pod::Abstract::Node->new(
321             type => '@attribute',
322             );
323 1         4 my $parser = Pod::Abstract::Parser->new;
324 1         36 my $pt = $parser->parse_text($label);
325 1         5 $parser->load_pt($attr_node, $pt);
326            
327 1         12 my $element_node = Pod::Abstract::Node->new(
328             type => "item",
329             label => $attr_node,
330             body_attr => 'label',
331             );
332 1         20 return $element_node;
333             }
334              
335             =head2 text
336              
337             my $text = node->text('Literal text');
338              
339             Generates a literal text node. You generally B want this, you
340             probably want a paragraph. Use this if you want to, for example,
341             append a word at the end of a paragraph.
342              
343             =cut
344              
345             sub text {
346 0     0 1   my $class = shift;
347 0           my $text = shift;
348            
349 0           my $attr_node = Pod::Abstract::Node->new(
350             type => ':text',
351             body => $text,
352             );
353 0           return $attr_node;
354             }
355              
356             =head2 pod
357              
358             my $n = node->pod;
359              
360             Generates an "=pod" command. Can be useful to force pod mode at the
361             end of cut nodes.
362              
363             Do not confuse with L!
364              
365             =cut
366              
367             sub pod {
368 0     0 1   my $class = shift;
369 0           return Pod::Abstract::Node->new(
370             type => 'pod',
371             body => '',
372             );
373             }
374              
375             =head1
376              
377             my $cut = node->cut;
378              
379             Generates an explicit "=cut" command.
380              
381             =cut
382              
383             sub cut {
384 0     0 0   my $class = shift;
385 0           return Pod::Abstract::Node->new(
386             type => '#cut',
387             body => "=cut\n\n",
388             );
389             }
390              
391             =head1 AUTHOR
392              
393             Ben Lilburne
394              
395             =head1 COPYRIGHT AND LICENSE
396              
397             Copyright (C) 2009 Ben Lilburne
398              
399             This program is free software; you can redistribute it and/or modify
400             it under the same terms as Perl itself.
401              
402             =cut
403              
404             1;