File Coverage

blib/lib/Pod/Weaver.pm
Criterion Covered Total %
statement 85 85 100.0
branch 5 8 62.5
condition 5 9 55.5
subroutine 19 19 100.0
pod 3 5 60.0
total 117 126 92.8


line stmt bran cond sub pod time code
1             package Pod::Weaver 4.020;
2             # ABSTRACT: weave together a Pod document from an outline
3              
4 10     10   16774364 use Moose;
  10         33  
  10         117  
5 10     10   78168 use namespace::autoclean;
  10         18  
  10         118  
6              
7             # BEGIN BOILERPLATE
8 10     10   916 use v5.20.0;
  10         56  
9 10     10   52 use warnings;
  10         24  
  10         621  
10 10     10   117 use utf8;
  10         42  
  10         116  
11 10     10   479 no feature 'switch';
  10         25  
  10         7449  
12 10     10   6312 use experimental qw(postderef postderef_qq); # This experiment gets mainlined.
  10         21961  
  10         69  
13             # END BOILERPLATE
14              
15             #pod =head1 SYNOPSIS
16             #pod
17             #pod my $weaver = Pod::Weaver->new_with_default_config;
18             #pod
19             #pod my $document = $weaver->weave_document({
20             #pod pod_document => $pod_elemental_document,
21             #pod ppi_document => $ppi_document,
22             #pod
23             #pod license => $software_license,
24             #pod version => $version_string,
25             #pod authors => \@author_names,
26             #pod })
27             #pod
28             #pod =head1 DESCRIPTION
29             #pod
30             #pod Pod::Weaver is a system for building Pod documents from templates. It doesn't
31             #pod perform simple text substitution, but instead builds a
32             #pod Pod::Elemental::Document. Its plugins sketch out a series of sections
33             #pod that will be produced based on an existing Pod document or other provided
34             #pod information.
35             #pod
36             #pod =cut
37              
38 10     10   1247 use File::Spec;
  10         32  
  10         443  
39 10     10   6347 use Log::Dispatchouli 1.100710; # proxy
  10         2392842  
  10         549  
40 10     10   93 use Pod::Elemental 0.100220;
  10         420  
  10         122  
41 10     10   4470 use Pod::Elemental::Document;
  10         25  
  10         313  
42 10     10   5902 use Pod::Weaver::Config::Finder;
  10         187  
  10         631  
43 10     10   7351 use Pod::Weaver::Role::Plugin;
  10         89  
  10         618  
44 10     10   107 use String::Flogger 1;
  10         194  
  10         77  
45              
46             #pod =attr logger
47             #pod
48             #pod This attribute stores the logger, which must provide a log method. The
49             #pod weaver's log method delegates to the logger's log method.
50             #pod
51             #pod =cut
52              
53             has logger => (
54             is => 'ro',
55             lazy => 1,
56             default => sub {
57             Log::Dispatchouli->new({
58             ident => 'Pod::Weaver',
59             to_stdout => 1,
60             log_pid => 0,
61             });
62             },
63             handles => [ qw(log log_fatal log_debug) ]
64             );
65              
66             #pod =attr plugins
67             #pod
68             #pod This attribute is an arrayref of objects that can perform the
69             #pod L<Pod::Weaver::Role::Plugin> role. In general, its contents are found through
70             #pod the C<L</plugins_with>> method.
71             #pod
72             #pod =cut
73              
74             has plugins => (
75             is => 'ro',
76             isa => 'ArrayRef[Pod::Weaver::Role::Plugin]',
77             required => 1,
78             lazy => 1,
79             init_arg => undef,
80             default => sub { [] },
81             );
82              
83             #pod =method plugins_with
84             #pod
85             #pod my $plugins_array_ref = $weaver->plugins_with('-Section');
86             #pod
87             #pod This method will return an arrayref of plugins that perform the given role, in
88             #pod the order of their registration. If the role name begins with a hyphen, the
89             #pod method will prepend C<Pod::Weaver::Role::>.
90             #pod
91             #pod =cut
92              
93             sub plugins_with {
94 178     178 1 575 my ($self, $role) = @_;
95              
96 178         956 $role =~ s/^-/Pod::Weaver::Role::/;
97 178         6883 my @plugins = grep { $_->does($role) } $self->plugins->@*;
  1126         85661  
98              
99 178         13369 return \@plugins;
100             }
101              
102             #pod =method weave_document
103             #pod
104             #pod my $document = $weaver->weave_document(\%input);
105             #pod
106             #pod This is the most important method in Pod::Weaver. Given a set of input
107             #pod parameters, it will weave a new document. Different section plugins will
108             #pod expect different input parameters to be present, but some common ones include:
109             #pod
110             #pod pod_document - a Pod::Elemental::Document for the original Pod document
111             #pod ppi_document - a PPI document for the source of the module being documented
112             #pod license - a Software::License object for the source module's license
113             #pod version - a version (string) to use in produced documentation
114             #pod
115             #pod The C<pod_document> should have gone through a L<Pod5
116             #pod transformer|Pod::Elemental::Transformer::Pod5>, and should probably have had
117             #pod its C<=head1> elements L<nested|Pod::Elemental::Transformer::Nester>.
118             #pod
119             #pod The method will return a new Pod::Elemental::Document. The input documents may
120             #pod be destructively altered during the weaving process. If they should be
121             #pod untouched, pass in copies.
122             #pod
123             #pod =cut
124              
125             sub weave_document {
126 36     36 1 429223 my ($self, $input) = @_;
127              
128 36         2073 my $document = Pod::Elemental::Document->new;
129              
130 36         3797 for ($self->plugins_with(-Preparer)->@*) {
131 29         213 $_->prepare_input($input);
132             }
133              
134 36         284 for ($self->plugins_with(-Dialect)->@*) {
135 7         74 $_->translate_dialect($input->{pod_document});
136             }
137              
138 36         182 for ($self->plugins_with(-Transformer)->@*) {
139 49         1532 $_->transform_document($input->{pod_document});
140             }
141              
142 36         724 for ($self->plugins_with(-Section)->@*) {
143 167         20780 $_->weave_section($document, $input);
144             }
145              
146 34         3962 for ($self->plugins_with(-Finalizer)->@*) {
147 32         198 $_->finalize_document($document, $input);
148             }
149              
150 34         660 return $document;
151             }
152              
153             #pod =method new_with_default_config
154             #pod
155             #pod This method returns a new Pod::Weaver with a stock configuration by using only
156             #pod L<Pod::Weaver::PluginBundle::Default>.
157             #pod
158             #pod =cut
159              
160             sub new_with_default_config {
161 2     2 1 1191712 my ($class, $arg) = @_;
162              
163 2         110 my $assembler = Pod::Weaver::Config::Assembler->new;
164              
165 2         71 my $root = $assembler->section_class->new({ name => '_' });
166 2         5942 $assembler->sequence->add_section($root);
167              
168 2         765 $assembler->change_section('@Default');
169 2         1668 $assembler->end_section;
170              
171 2         8007 return $class->new_from_config_sequence($assembler->sequence, $arg);
172             }
173              
174             sub new_from_config {
175 1     1 0 352142 my ($class, $arg, $new_arg) = @_;
176              
177 1   50     5 my $root = $arg->{root} || '.';
178 1         21 my $name = File::Spec->catfile($root, 'weaver');
179 1         66 my ($sequence) = Pod::Weaver::Config::Finder->new->read_config($name);
180              
181 1         24 return $class->new_from_config_sequence($sequence, $new_arg);
182             }
183              
184             sub new_from_config_sequence {
185 36     36 0 119098 my ($class, $seq, $arg) = @_;
186 36   100     326 $arg ||= {};
187              
188 36   50     275 my $merge = $arg->{root_config} || {};
189              
190 36 50 33     368 confess("config must be a Config::MVP::Sequence")
191             unless $seq and $seq->isa('Config::MVP::Sequence');
192              
193 36         200 my $core_config = $seq->section_named('_')->payload;
194              
195 36         5197 my $self = $class->new({
196             %$merge,
197             %$core_config,
198             });
199              
200 36         209 for my $section ($seq->sections) {
201 268 100       14607 next if $section->name eq '_';
202              
203 232         8435 my ($name, $plugin_class, $arg) = (
204             $section->name,
205             $section->package,
206             $section->payload,
207             );
208              
209 232         18188 $self->log_debug("initializing plugin $name ($plugin_class)");
210              
211             confess "arguments attempted to override 'plugin_name'"
212 232 50       7029 if defined $arg->{plugin_name};
213              
214             confess "arguments attempted to override 'weaver'"
215 232 50       653 if defined $arg->{weaver};
216              
217 232         7213 push $self->plugins->@*,
218             $plugin_class->new({
219             %$arg,
220             plugin_name => $name,
221             weaver => $self,
222             });
223             }
224              
225 36         2241 return $self;
226             }
227              
228             __PACKAGE__->meta->make_immutable;
229             1;
230              
231             __END__
232              
233             =pod
234              
235             =encoding UTF-8
236              
237             =head1 NAME
238              
239             Pod::Weaver - weave together a Pod document from an outline
240              
241             =head1 VERSION
242              
243             version 4.020
244              
245             =head1 SYNOPSIS
246              
247             my $weaver = Pod::Weaver->new_with_default_config;
248              
249             my $document = $weaver->weave_document({
250             pod_document => $pod_elemental_document,
251             ppi_document => $ppi_document,
252              
253             license => $software_license,
254             version => $version_string,
255             authors => \@author_names,
256             })
257              
258             =head1 DESCRIPTION
259              
260             Pod::Weaver is a system for building Pod documents from templates. It doesn't
261             perform simple text substitution, but instead builds a
262             Pod::Elemental::Document. Its plugins sketch out a series of sections
263             that will be produced based on an existing Pod document or other provided
264             information.
265              
266             =head1 PERL VERSION
267              
268             This module should work on any version of perl still receiving updates from
269             the Perl 5 Porters. This means it should work on any version of perl
270             released in the last two to three years. (That is, if the most recently
271             released version is v5.40, then this module should work on both v5.40 and
272             v5.38.)
273              
274             Although it may work on older versions of perl, no guarantee is made that the
275             minimum required version will not be increased. The version may be increased
276             for any reason, and there is no promise that patches will be accepted to
277             lower the minimum required perl.
278              
279             =head1 ATTRIBUTES
280              
281             =head2 logger
282              
283             This attribute stores the logger, which must provide a log method. The
284             weaver's log method delegates to the logger's log method.
285              
286             =head2 plugins
287              
288             This attribute is an arrayref of objects that can perform the
289             L<Pod::Weaver::Role::Plugin> role. In general, its contents are found through
290             the C<L</plugins_with>> method.
291              
292             =head1 METHODS
293              
294             =head2 plugins_with
295              
296             my $plugins_array_ref = $weaver->plugins_with('-Section');
297              
298             This method will return an arrayref of plugins that perform the given role, in
299             the order of their registration. If the role name begins with a hyphen, the
300             method will prepend C<Pod::Weaver::Role::>.
301              
302             =head2 weave_document
303              
304             my $document = $weaver->weave_document(\%input);
305              
306             This is the most important method in Pod::Weaver. Given a set of input
307             parameters, it will weave a new document. Different section plugins will
308             expect different input parameters to be present, but some common ones include:
309              
310             pod_document - a Pod::Elemental::Document for the original Pod document
311             ppi_document - a PPI document for the source of the module being documented
312             license - a Software::License object for the source module's license
313             version - a version (string) to use in produced documentation
314              
315             The C<pod_document> should have gone through a L<Pod5
316             transformer|Pod::Elemental::Transformer::Pod5>, and should probably have had
317             its C<=head1> elements L<nested|Pod::Elemental::Transformer::Nester>.
318              
319             The method will return a new Pod::Elemental::Document. The input documents may
320             be destructively altered during the weaving process. If they should be
321             untouched, pass in copies.
322              
323             =head2 new_with_default_config
324              
325             This method returns a new Pod::Weaver with a stock configuration by using only
326             L<Pod::Weaver::PluginBundle::Default>.
327              
328             =head1 AUTHOR
329              
330             Ricardo SIGNES <cpan@semiotic.systems>
331              
332             =head1 CONTRIBUTORS
333              
334             =for stopwords Alex Peters Apocalypse Blabos de Blebe Caleb Cushing Christian Walde Christopher J. Madsen Chris Weyl Dave Houston Rolsky David E. Wheeler Golden Miguel Susano Pinto Zurborg Doug Bell Florian Ragwitz Jonathan "Duke" Leto Joshua Keroes Karen Etheridge Kent Fredric Kivanc Yazan Marcel Gruenauer Randy Stauner Ricardo Signes Sam Graham Shlomi Fish
335              
336             =over 4
337              
338             =item *
339              
340             Alex Peters <lxp@cpan.org>
341              
342             =item *
343              
344             Apocalypse <perl@0ne.us>
345              
346             =item *
347              
348             Blabos de Blebe <blabos@cpan.org>
349              
350             =item *
351              
352             Caleb Cushing <xenoterracide@gmail.com>
353              
354             =item *
355              
356             Christian Walde <walde.christian@googlemail.com>
357              
358             =item *
359              
360             Christopher J. Madsen <perl@cjmweb.net>
361              
362             =item *
363              
364             Chris Weyl <cweyl@alumni.drew.edu>
365              
366             =item *
367              
368             Dave Houston <dave.houston@gmail.com>
369              
370             =item *
371              
372             Dave Rolsky <autarch@urth.org>
373              
374             =item *
375              
376             David E. Wheeler <david@justatheory.com>
377              
378             =item *
379              
380             David Golden <dagolden@cpan.org>
381              
382             =item *
383              
384             David Miguel Susano Pinto <carandraug+dev@gmail.com>
385              
386             =item *
387              
388             David Zurborg <post@david-zurb.org>
389              
390             =item *
391              
392             Doug Bell <doug@preaction.me>
393              
394             =item *
395              
396             Florian Ragwitz <rafl@debian.org>
397              
398             =item *
399              
400             Jonathan "Duke" Leto <jonathan@leto.net>
401              
402             =item *
403              
404             Joshua Keroes <joshua.keroes@integratelecom.com>
405              
406             =item *
407              
408             Karen Etheridge <ether@cpan.org>
409              
410             =item *
411              
412             Kent Fredric <kentfredric@gmail.com>
413              
414             =item *
415              
416             Kivanc Yazan <kyzn@cpan.org>
417              
418             =item *
419              
420             Marcel Gruenauer <hanekomu@gmail.com>
421              
422             =item *
423              
424             Randy Stauner <randy@magnificent-tears.com>
425              
426             =item *
427              
428             Ricardo Signes <rjbs@semiotic.systems>
429              
430             =item *
431              
432             Sam Graham <git@illusori.co.uk>
433              
434             =item *
435              
436             Shlomi Fish <shlomif@shlomifish.org>
437              
438             =back
439              
440             =head1 COPYRIGHT AND LICENSE
441              
442             This software is copyright (c) 2024 by Ricardo SIGNES.
443              
444             This is free software; you can redistribute it and/or modify it under
445             the same terms as the Perl 5 programming language system itself.
446              
447             =cut