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.018;
2             # ABSTRACT: weave together a Pod document from an outline
3              
4 10     10   14170106 use Moose;
  10         104  
  10         89  
5 10     10   65913 use namespace::autoclean;
  10         21  
  10         94  
6              
7             # BEGIN BOILERPLATE
8 10     10   853 use v5.20.0;
  10         44  
9 10     10   62 use warnings;
  10         19  
  10         368  
10 10     10   56 use utf8;
  10         25  
  10         80  
11 10     10   402 no feature 'switch';
  10         17  
  10         1717  
12 10     10   5906 use experimental qw(postderef postderef_qq); # This experiment gets mainlined.
  10         35577  
  10         56  
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   1761 use File::Spec;
  10         19  
  10         301  
39 10     10   5907 use Log::Dispatchouli 1.100710; # proxy
  10         2214727  
  10         400  
40 10     10   88 use Pod::Elemental 0.100220;
  10         310  
  10         103  
41 10     10   3711 use Pod::Elemental::Document;
  10         25  
  10         271  
42 10     10   4967 use Pod::Weaver::Config::Finder;
  10         38  
  10         416  
43 10     10   5670 use Pod::Weaver::Role::Plugin;
  10         33  
  10         421  
44 10     10   77 use String::Flogger 1;
  10         180  
  10         69  
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 430 my ($self, $role) = @_;
95              
96 178         826 $role =~ s/^-/Pod::Weaver::Role::/;
97 178         4565 my @plugins = grep { $_->does($role) } $self->plugins->@*;
  1126         67042  
98              
99 178         10503 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 365117 my ($self, $input) = @_;
127              
128 36         1344 my $document = Pod::Elemental::Document->new;
129              
130 36         2989 for ($self->plugins_with(-Preparer)->@*) {
131 29         166 $_->prepare_input($input);
132             }
133              
134 36         187 for ($self->plugins_with(-Dialect)->@*) {
135 7         62 $_->translate_dialect($input->{pod_document});
136             }
137              
138 36         177 for ($self->plugins_with(-Transformer)->@*) {
139 49         1070 $_->transform_document($input->{pod_document});
140             }
141              
142 36         579 for ($self->plugins_with(-Section)->@*) {
143 167         15736 $_->weave_section($document, $input);
144             }
145              
146 34         2865 for ($self->plugins_with(-Finalizer)->@*) {
147 32         211 $_->finalize_document($document, $input);
148             }
149              
150 34         478 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 29294 my ($class, $arg) = @_;
162              
163 2         80 my $assembler = Pod::Weaver::Config::Assembler->new;
164              
165 2         60 my $root = $assembler->section_class->new({ name => '_' });
166 2         4263 $assembler->sequence->add_section($root);
167              
168 2         550 $assembler->change_section('@Default');
169 2         1326 $assembler->end_section;
170              
171 2         5918 return $class->new_from_config_sequence($assembler->sequence, $arg);
172             }
173              
174             sub new_from_config {
175 1     1 0 17359 my ($class, $arg, $new_arg) = @_;
176              
177 1   50     7 my $root = $arg->{root} || '.';
178 1         26 my $name = File::Spec->catfile($root, 'weaver');
179 1         47 my ($sequence) = Pod::Weaver::Config::Finder->new->read_config($name);
180              
181 1         33 return $class->new_from_config_sequence($sequence, $new_arg);
182             }
183              
184             sub new_from_config_sequence {
185 36     36 0 88029 my ($class, $seq, $arg) = @_;
186 36   100     253 $arg ||= {};
187              
188 36   50     218 my $merge = $arg->{root_config} || {};
189              
190 36 50 33     321 confess("config must be a Config::MVP::Sequence")
191             unless $seq and $seq->isa('Config::MVP::Sequence');
192              
193 36         132 my $core_config = $seq->section_named('_')->payload;
194              
195 36         3603 my $self = $class->new({
196             %$merge,
197             %$core_config,
198             });
199              
200 36         156 for my $section ($seq->sections) {
201 268 100       11148 next if $section->name eq '_';
202              
203 232         6627 my ($name, $plugin_class, $arg) = (
204             $section->name,
205             $section->package,
206             $section->payload,
207             );
208              
209 232         14065 $self->log_debug("initializing plugin $name ($plugin_class)");
210              
211             confess "arguments attempted to override 'plugin_name'"
212 232 50       4539 if defined $arg->{plugin_name};
213              
214             confess "arguments attempted to override 'weaver'"
215 232 50       526 if defined $arg->{weaver};
216              
217 232         5448 push $self->plugins->@*,
218             $plugin_class->new({
219             %$arg,
220             plugin_name => $name,
221             weaver => $self,
222             });
223             }
224              
225 36         1563 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.018
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 SUPPORT
267              
268             This module has the same support period as perl itself: it supports the two
269             most recent versions of perl. (That is, if the most recently released version
270             is v5.40, then this module should work on both v5.40 and v5.38.)
271              
272             Although it may work on older versions of perl, no guarantee is made that the
273             minimum required version will not be increased. The version may be increased
274             for any reason, and there is no promise that patches will be accepted to lower
275             the minimum required perl.
276              
277             =head1 ATTRIBUTES
278              
279             =head2 logger
280              
281             This attribute stores the logger, which must provide a log method. The
282             weaver's log method delegates to the logger's log method.
283              
284             =head2 plugins
285              
286             This attribute is an arrayref of objects that can perform the
287             L<Pod::Weaver::Role::Plugin> role. In general, its contents are found through
288             the C<L</plugins_with>> method.
289              
290             =head1 METHODS
291              
292             =head2 plugins_with
293              
294             my $plugins_array_ref = $weaver->plugins_with('-Section');
295              
296             This method will return an arrayref of plugins that perform the given role, in
297             the order of their registration. If the role name begins with a hyphen, the
298             method will prepend C<Pod::Weaver::Role::>.
299              
300             =head2 weave_document
301              
302             my $document = $weaver->weave_document(\%input);
303              
304             This is the most important method in Pod::Weaver. Given a set of input
305             parameters, it will weave a new document. Different section plugins will
306             expect different input parameters to be present, but some common ones include:
307              
308             pod_document - a Pod::Elemental::Document for the original Pod document
309             ppi_document - a PPI document for the source of the module being documented
310             license - a Software::License object for the source module's license
311             version - a version (string) to use in produced documentation
312              
313             The C<pod_document> should have gone through a L<Pod5
314             transformer|Pod::Elemental::Transformer::Pod5>, and should probably have had
315             its C<=head1> elements L<nested|Pod::Elemental::Transformer::Nester>.
316              
317             The method will return a new Pod::Elemental::Document. The input documents may
318             be destructively altered during the weaving process. If they should be
319             untouched, pass in copies.
320              
321             =head2 new_with_default_config
322              
323             This method returns a new Pod::Weaver with a stock configuration by using only
324             L<Pod::Weaver::PluginBundle::Default>.
325              
326             =head1 AUTHOR
327              
328             Ricardo SIGNES <rjbs@semiotic.systems>
329              
330             =head1 CONTRIBUTORS
331              
332             =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 Sam Graham Shlomi Fish
333              
334             =over 4
335              
336             =item *
337              
338             Alex Peters <lxp@cpan.org>
339              
340             =item *
341              
342             Apocalypse <perl@0ne.us>
343              
344             =item *
345              
346             Blabos de Blebe <blabos@cpan.org>
347              
348             =item *
349              
350             Caleb Cushing <xenoterracide@gmail.com>
351              
352             =item *
353              
354             Christian Walde <walde.christian@googlemail.com>
355              
356             =item *
357              
358             Christopher J. Madsen <perl@cjmweb.net>
359              
360             =item *
361              
362             Chris Weyl <cweyl@alumni.drew.edu>
363              
364             =item *
365              
366             Dave Houston <dave.houston@gmail.com>
367              
368             =item *
369              
370             Dave Rolsky <autarch@urth.org>
371              
372             =item *
373              
374             David E. Wheeler <david@justatheory.com>
375              
376             =item *
377              
378             David Golden <dagolden@cpan.org>
379              
380             =item *
381              
382             David Miguel Susano Pinto <carandraug+dev@gmail.com>
383              
384             =item *
385              
386             David Zurborg <post@david-zurb.org>
387              
388             =item *
389              
390             Doug Bell <doug@preaction.me>
391              
392             =item *
393              
394             Florian Ragwitz <rafl@debian.org>
395              
396             =item *
397              
398             Jonathan "Duke" Leto <jonathan@leto.net>
399              
400             =item *
401              
402             Joshua Keroes <joshua.keroes@integratelecom.com>
403              
404             =item *
405              
406             Karen Etheridge <ether@cpan.org>
407              
408             =item *
409              
410             Kent Fredric <kentfredric@gmail.com>
411              
412             =item *
413              
414             Kivanc Yazan <kyzn@cpan.org>
415              
416             =item *
417              
418             Marcel Gruenauer <hanekomu@gmail.com>
419              
420             =item *
421              
422             Randy Stauner <randy@magnificent-tears.com>
423              
424             =item *
425              
426             Sam Graham <git@illusori.co.uk>
427              
428             =item *
429              
430             Shlomi Fish <shlomif@shlomifish.org>
431              
432             =back
433              
434             =head1 COPYRIGHT AND LICENSE
435              
436             This software is copyright (c) 2021 by Ricardo SIGNES.
437              
438             This is free software; you can redistribute it and/or modify it under
439             the same terms as the Perl 5 programming language system itself.
440              
441             =cut