File Coverage

blib/lib/Pod/Weaver/Section/Collect.pm
Criterion Covered Total %
statement 62 62 100.0
branch 11 12 91.6
condition 2 3 66.6
subroutine 14 14 100.0
pod 0 2 0.0
total 89 93 95.7


line stmt bran cond sub pod time code
1             package Pod::Weaver::Section::Collect 4.019;
2             # ABSTRACT: a section that gathers up specific commands
3              
4 5     5   45921 use Moose;
  5         16  
  5         47  
5             with 'Pod::Weaver::Role::Section',
6             'Pod::Weaver::Role::Transformer';
7              
8             # BEGIN BOILERPLATE
9 5     5   36624 use v5.20.0;
  5         18  
10 5     5   35 use warnings;
  5         15  
  5         200  
11 5     5   37 use utf8;
  5         11  
  5         66  
12 5     5   175 no feature 'switch';
  5         12  
  5         646  
13 5     5   44 use experimental qw(postderef postderef_qq); # This experiment gets mainlined.
  5         20  
  5         51  
14             # END BOILERPLATE
15              
16             #pod =head1 OVERVIEW
17             #pod
18             #pod Given the configuration:
19             #pod
20             #pod [Collect / METHODS]
21             #pod command = method
22             #pod
23             #pod This plugin will start off by gathering and nesting any C<=method> commands
24             #pod found in the C<pod_document>. Those commands, along with their nestable
25             #pod content, will be collected under a C<=head1 METHODS> header and placed in the
26             #pod correct location in the output stream. Their order will be preserved as it was
27             #pod in the source document.
28             #pod
29             #pod =cut
30              
31 5     5   664 use Pod::Elemental::Element::Pod5::Region;
  5         20  
  5         237  
32 5     5   32 use Pod::Elemental::Selectors -all;
  5         14  
  5         64  
33 5     5   3005 use List::Util 1.33 'any';
  5         103  
  5         1105  
34              
35             #pod =attr command
36             #pod
37             #pod The command that will be collected (e.g. C<attr> or C<method>).
38             #pod (required)
39             #pod
40             #pod =attr new_command
41             #pod
42             #pod The command to be used in the output instead of the collected command.
43             #pod (default: C<head2>)
44             #pod
45             #pod =attr header_command
46             #pod
47             #pod The section command for the section to be added.
48             #pod (default: C<head1>)
49             #pod
50             #pod =attr header
51             #pod
52             #pod The title of the section to be added.
53             #pod (default: the plugin name)
54             #pod
55             #pod =cut
56              
57             has command => (
58             is => 'ro',
59             isa => 'Str',
60             required => 1,
61             );
62              
63             has new_command => (
64             is => 'ro',
65             isa => 'Str',
66             required => 1,
67             default => 'head2',
68             );
69              
70             has header_command => (
71             is => 'ro',
72             isa => 'Str',
73             required => 1,
74             default => 'head1',
75             );
76              
77             has header => (
78             is => 'ro',
79             isa => 'Str',
80             lazy => 1,
81             required => 1,
82             default => sub { $_[0]->plugin_name },
83             );
84              
85 5     5   2871 use Pod::Elemental::Transformer::Gatherer;
  5         171066  
  5         242  
86 5     5   55 use Pod::Elemental::Transformer::Nester;
  5         10  
  5         3719  
87              
88             has __used_container => (is => 'rw');
89              
90             sub transform_document {
91 20     20 0 58 my ($self, $document) = @_;
92              
93 20         649 my $command = $self->command;
94 20         73 my $selector = s_command($command);
95              
96 20         693 my $children = $document->children;
97 20 100   126   218 unless (any { $selector->($_) } @$children) {
  126         8494  
98 13         1282 $self->log_debug("no $command commands in pod to collect");
99 13         395 return;
100             }
101              
102 7         782 $self->log_debug("transforming $command commands into standard pod");
103              
104 7         528 my $nester = Pod::Elemental::Transformer::Nester->new({
105             top_selector => $selector,
106             content_selectors => [
107             s_command([ qw(head3 head4 over item back) ]),
108             s_flat,
109             ],
110             });
111              
112             # try and find array position of suitable host
113             my ( $container_id ) = grep {
114 7         868 my $c = $children->[$_];
  55         101  
115 55 100 66     1126 $c->isa("Pod::Elemental::Element::Nested")
116             and $c->command eq $self->header_command and $c->content eq $self->header;
117             } 0 .. $#$children;
118              
119 7 100       90 my $container = $container_id
120             ? splice @$children, $container_id, 1 # excise host
121             : Pod::Elemental::Element::Nested->new({ # synthesize new host
122             command => $self->header_command,
123             content => $self->header,
124             });
125              
126 7         478 $self->__used_container($container);
127              
128 7         300 my $gatherer = Pod::Elemental::Transformer::Gatherer->new({
129             gather_selector => $selector,
130             container => $container,
131             });
132              
133 7         1541 $nester->transform_node($document);
134 7         13962 my @children = $container->children->@*; # rescue children
135 7         99 $gatherer->transform_node($document); # insert host at position of first adopt-child and inject it with adopt-children
136 7         9092 foreach my $child ($container->children->@*) {
137 7 50       280 $child->command( $self->new_command ) if $child->command eq $command;
138             }
139 7         391 unshift $container->children->@*, @children; # give original children back to host
140             }
141              
142             sub weave_section {
143 20     20 0 61 my ($self, $document, $input) = @_;
144              
145 20 100       597 return unless $self->__used_container;
146              
147 7         191 my $in_node = $input->{pod_document}->children;
148              
149             my @found = grep {
150 7         74 my ($i, $para) = ($_, $in_node->[$_]);
  21         68  
151 21 100       718 ($para == $self->__used_container)
152             && $self->__used_container->children->@*;
153             } (0 .. $#$in_node);
154              
155 7         273 push $document->children->@*, map { splice @$in_node, $_, 1 } reverse @found;
  7         114  
156             }
157              
158             __PACKAGE__->meta->make_immutable;
159             1;
160              
161             __END__
162              
163             =pod
164              
165             =encoding UTF-8
166              
167             =head1 NAME
168              
169             Pod::Weaver::Section::Collect - a section that gathers up specific commands
170              
171             =head1 VERSION
172              
173             version 4.019
174              
175             =head1 OVERVIEW
176              
177             Given the configuration:
178              
179             [Collect / METHODS]
180             command = method
181              
182             This plugin will start off by gathering and nesting any C<=method> commands
183             found in the C<pod_document>. Those commands, along with their nestable
184             content, will be collected under a C<=head1 METHODS> header and placed in the
185             correct location in the output stream. Their order will be preserved as it was
186             in the source document.
187              
188             =head1 PERL VERSION
189              
190             This module should work on any version of perl still receiving updates from
191             the Perl 5 Porters. This means it should work on any version of perl released
192             in the last two to three years. (That is, if the most recently released
193             version is v5.40, then this module should work on both v5.40 and v5.38.)
194              
195             Although it may work on older versions of perl, no guarantee is made that the
196             minimum required version will not be increased. The version may be increased
197             for any reason, and there is no promise that patches will be accepted to lower
198             the minimum required perl.
199              
200             =head1 ATTRIBUTES
201              
202             =head2 command
203              
204             The command that will be collected (e.g. C<attr> or C<method>).
205             (required)
206              
207             =head2 new_command
208              
209             The command to be used in the output instead of the collected command.
210             (default: C<head2>)
211              
212             =head2 header_command
213              
214             The section command for the section to be added.
215             (default: C<head1>)
216              
217             =head2 header
218              
219             The title of the section to be added.
220             (default: the plugin name)
221              
222             =head1 AUTHOR
223              
224             Ricardo SIGNES <cpan@semiotic.systems>
225              
226             =head1 COPYRIGHT AND LICENSE
227              
228             This software is copyright (c) 2023 by Ricardo SIGNES.
229              
230             This is free software; you can redistribute it and/or modify it under
231             the same terms as the Perl 5 programming language system itself.
232              
233             =cut