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.020;
2             # ABSTRACT: a section that gathers up specific commands
3              
4 5     5   43172 use Moose;
  5         11  
  5         47  
5             with 'Pod::Weaver::Role::Section',
6             'Pod::Weaver::Role::Transformer';
7              
8             # BEGIN BOILERPLATE
9 5     5   30754 use v5.20.0;
  5         16  
10 5     5   23 use warnings;
  5         27  
  5         275  
11 5     5   25 use utf8;
  5         9  
  5         46  
12 5     5   180 no feature 'switch';
  5         9  
  5         921  
13 5     5   31 use experimental qw(postderef postderef_qq); # This experiment gets mainlined.
  5         9  
  5         39  
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   436 use Pod::Elemental::Element::Pod5::Region;
  5         16  
  5         217  
32 5     5   23 use Pod::Elemental::Selectors -all;
  5         8  
  5         51  
33 5     5   2659 use List::Util 1.33 'any';
  5         109  
  5         1012  
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   2637 use Pod::Elemental::Transformer::Gatherer;
  5         194552  
  5         257  
86 5     5   72 use Pod::Elemental::Transformer::Nester;
  5         12  
  5         4314  
87              
88             has __used_container => (is => 'rw');
89              
90             sub transform_document {
91 20     20 0 65 my ($self, $document) = @_;
92              
93 20         894 my $command = $self->command;
94 20         113 my $selector = s_command($command);
95              
96 20         1104 my $children = $document->children;
97 20 100   126   360 unless (any { $selector->($_) } @$children) {
  126         10699  
98 13         1615 $self->log_debug("no $command commands in pod to collect");
99 13         668 return;
100             }
101              
102 7         914 $self->log_debug("transforming $command commands into standard pod");
103              
104 7         672 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         1114 my $c = $children->[$_];
  55         109  
115 55 100 66     1602 $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       77 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         609 $self->__used_container($container);
127              
128 7         391 my $gatherer = Pod::Elemental::Transformer::Gatherer->new({
129             gather_selector => $selector,
130             container => $container,
131             });
132              
133 7         1926 $nester->transform_node($document);
134 7         18512 my @children = $container->children->@*; # rescue children
135 7         96 $gatherer->transform_node($document); # insert host at position of first adopt-child and inject it with adopt-children
136 7         11745 foreach my $child ($container->children->@*) {
137 7 50       389 $child->command( $self->new_command ) if $child->command eq $command;
138             }
139 7         644 unshift $container->children->@*, @children; # give original children back to host
140             }
141              
142             sub weave_section {
143 20     20 0 58 my ($self, $document, $input) = @_;
144              
145 20 100       844 return unless $self->__used_container;
146              
147 7         248 my $in_node = $input->{pod_document}->children;
148              
149             my @found = grep {
150 7         65 my ($i, $para) = ($_, $in_node->[$_]);
  21         55  
151 21 100       886 ($para == $self->__used_container)
152             && $self->__used_container->children->@*;
153             } (0 .. $#$in_node);
154              
155 7         339 push $document->children->@*, map { splice @$in_node, $_, 1 } reverse @found;
  7         94  
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.020
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
192             released in the last two to three years. (That is, if the most recently
193             released version is v5.40, then this module should work on both v5.40 and
194             v5.38.)
195              
196             Although it may work on older versions of perl, no guarantee is made that the
197             minimum required version will not be increased. The version may be increased
198             for any reason, and there is no promise that patches will be accepted to
199             lower the minimum required perl.
200              
201             =head1 ATTRIBUTES
202              
203             =head2 command
204              
205             The command that will be collected (e.g. C<attr> or C<method>).
206             (required)
207              
208             =head2 new_command
209              
210             The command to be used in the output instead of the collected command.
211             (default: C<head2>)
212              
213             =head2 header_command
214              
215             The section command for the section to be added.
216             (default: C<head1>)
217              
218             =head2 header
219              
220             The title of the section to be added.
221             (default: the plugin name)
222              
223             =head1 AUTHOR
224              
225             Ricardo SIGNES <cpan@semiotic.systems>
226              
227             =head1 COPYRIGHT AND LICENSE
228              
229             This software is copyright (c) 2024 by Ricardo SIGNES.
230              
231             This is free software; you can redistribute it and/or modify it under
232             the same terms as the Perl 5 programming language system itself.
233              
234             =cut