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