File Coverage

blib/lib/Pod/Readme.pm
Criterion Covered Total %
statement 68 76 89.4
branch 11 26 42.3
condition 5 7 71.4
subroutine 17 17 100.0
pod 5 5 100.0
total 106 131 80.9


line stmt bran cond sub pod time code
1             package Pod::Readme;
2              
3             =head1 NAME
4              
5             Pod::Readme - Intelligently generate a README file from POD
6              
7             =for readme plugin version
8              
9             =head1 SYNOPSIS
10              
11             In a module's POD:
12              
13             =head1 NAME
14              
15             MyApp - my nifty app
16              
17             =for readme plugin version
18              
19             =head1 DESCRIPTION
20              
21             This is a nifty app.
22              
23             =begin :readme
24              
25             =for readme plugin requires
26              
27             =head1 INSTALLATION
28              
29             ...
30              
31             =end :readme
32              
33             =for readme stop
34              
35             =head1 METHODS
36              
37             ...
38              
39             Then from the command-line:
40              
41             pod2readme lib/MyModule.pm README
42              
43             =for readme stop
44              
45             From within Perl:
46              
47             use Pod::Readme;
48              
49             my $prf = Pod::Readme->new(
50             input_file => 'lib/MyModule.pm',
51             translate_to_file => $dest,
52             translation_class => 'Pod::Simple::Text',
53             );
54              
55             $prf->run();
56              
57             =for readme start
58              
59             =head1 DESCRIPTION
60              
61             This module filters POD to generate a F file, by using POD
62             commands to specify which parts are included or excluded from the
63             F file.
64              
65             =begin :readme
66              
67             See the L documentation for more details on the POD
68             syntax that this module recognizes.
69              
70             See L for command-line usage.
71              
72             =head1 INSTALLATION
73              
74             See
75             L.
76              
77             =for readme plugin requires heading-level=2 title="Required Modules"
78              
79             =for readme plugin changes
80              
81             =end :readme
82              
83             =for readme stop
84              
85             =head1 POD COMMANDS
86              
87             =head2 C<=for readme stop>
88              
89             Stop including the POD that follows in the F.
90              
91             =head2 C<=for readme start>
92              
93             =head2 C<=for readme continue>
94              
95             Start (or continue to) include the POD that follows in the F.
96              
97             Note that the C command was added as a synonym in version
98             1.0.0.
99              
100             =head2 C<=for readme include>
101              
102             =for readme include file="INSTALL" type="text"
103              
104             Include a text or POD file in the F. It accepts the following
105             options:
106              
107             =over
108              
109             =item C
110              
111             Required. This is the file name to include.
112              
113             =item C
114              
115             Can be "text" or "pod" (default).
116              
117             =item C
118              
119             An optional regex of where to start including the file.
120              
121             =item C
122              
123             An optional regex of where to stop including the file.
124              
125             =back
126              
127             =head2 C<=for readme plugin>
128              
129             Loads a plugin, e.g.
130              
131             =for readme plugin version
132              
133             Note that specific plugins may add options, e.g.
134              
135             =for readme plugin changes title='CHANGES'
136              
137             See L for more information.
138              
139             Note that the C command was added in version 1.0.0.
140              
141             =head2 C<=begin :readme>
142              
143             =head2 C<=end :readme>
144              
145             Specify a block of POD to include only in the F.
146              
147             You can also specify a block in another format:
148              
149             =begin readme text
150              
151             ...
152              
153             =end readme text
154              
155             This will be translated into
156              
157             =begin text
158              
159             ...
160              
161             =end text
162              
163             and will only be included in F files of that format.
164              
165             Note: earlier versions of this module suggested using
166              
167             =begin readme
168              
169             ...
170              
171             =end readme
172              
173             While this version supports that syntax for backwards compatibility,
174             it is not standard POD.
175              
176             =cut
177              
178 4     4   2573 use v5.10.1;
  4         12  
179              
180 4     4   1817 use Moo;
  4         38710  
  4         16  
181             extends 'Pod::Readme::Filter';
182              
183             our $VERSION = 'v1.2.1';
184              
185 4     4   5192 use Carp;
  4         8  
  4         191  
186 4     4   21 use IO qw/ File Handle /;
  4         5  
  4         21  
187 4     4   5523 use List::Util 1.33 qw/ any /;
  4         57  
  4         322  
188 4     4   1626 use Module::Load qw/ load /;
  4         3955  
  4         26  
189 4     4   284 use Path::Tiny qw/ path tempfile /;
  4         7  
  4         198  
190 4     4   1817 use Types::Standard qw/ Bool Maybe Str /;
  4         265411  
  4         44  
191              
192 4     4   5265 use Pod::Readme::Types qw/ File WriteIO /;
  4         10  
  4         3486  
193              
194             =head1 ATTRIBUTES
195              
196             This module extends L with the following
197             attributes:
198              
199             =head2 C
200              
201             The class used to translate the filtered POD into another format,
202             e.g. L.
203              
204             If it is C, then there is no translation.
205              
206             Only subclasses of L are supported.
207              
208             =cut
209              
210             has translation_class => (
211             is => 'ro',
212             isa => Maybe [Str],
213             default => undef,
214             );
215              
216             =head2 C
217              
218             The L to save the translated file to.
219              
220             =cut
221              
222             has translate_to_fh => (
223             is => 'ro',
224             isa => WriteIO,
225             lazy => 1,
226             builder => '_build_translate_to_fh',
227             coerce => sub { WriteIO->coerce(@_) },
228             );
229              
230             sub _build_translate_to_fh {
231 2     2   45 my ($self) = @_;
232 2 50       39 if ( $self->translate_to_file ) {
233 2         61 $self->translate_to_file->openw;
234             }
235             else {
236 0         0 my $fh = IO::Handle->new;
237 0 0       0 if ( $fh->fdopen( fileno(STDOUT), 'w' ) ) {
238 0         0 return $fh;
239             }
240             else {
241 0         0 croak "Cannot get a filehandle for STDOUT";
242             }
243             }
244             }
245              
246             =head2 C
247              
248             The L filename to save the translated file to. If omitted,
249             then it will be saved to C.
250              
251             =cut
252              
253             has translate_to_file => (
254             is => 'ro',
255             isa => File,
256             coerce => sub { File->coerce(@_) },
257             lazy => 1,
258             builder => 'default_readme_file',
259             );
260              
261             =head2 C
262              
263             The L C will default to a temporary
264             file.
265              
266             =cut
267              
268             has '+output_file' => (
269             lazy => 1,
270             default => sub { tempfile( SUFFIX => '.pod', UNLINK => 1 ); },
271             );
272              
273             around '_build_output_fh' => sub {
274             my ( $orig, $self ) = @_;
275             if ( defined $self->translation_class ) {
276             $self->$orig();
277             }
278             else {
279             $self->translate_to_fh;
280             }
281             };
282              
283             =head2 C
284              
285             For a new F to be generated, even if the dependencies have not
286             been updated.
287              
288             See L.
289              
290             =cut
291              
292             has 'force' => (
293             is => 'ro',
294             isa => Bool,
295             default => 0,
296             );
297              
298             =head2 C
299              
300             For use with L plugins.
301              
302             This allows plugins which normally depend on files in the distribution
303             to use metadata from here instead.
304              
305             =cut
306              
307             =head1 METHODS
308              
309             This module extends L with the following methods:
310              
311             =head2 C
312              
313             The default name of the F file, which depends on the
314             L.
315              
316             =cut
317              
318             sub default_readme_file {
319 3     3 1 74 my ($self) = @_;
320              
321 3         27 my $name = uc( $self->target );
322              
323 3         21 state $extensions = {
324             'Pod::Man' => '.1',
325             'Pod::Markdown' => '.md',
326             'Pod::Simple::HTML' => '.html',
327             'Pod::Simple::LaTeX' => '.tex',
328             'Pod::Simple::RTF' => '.rtf',
329             'Pod::Simple::Text' => '',
330             'Pod::Simple::XHTML' => '.xhtml',
331             };
332              
333 3         18 my $class = $self->translation_class;
334 3 50       13 if ( defined $class ) {
335 0 0       0 if ( my $ext = $extensions->{$class} ) {
336 0         0 $name .= $ext;
337             }
338             }
339             else {
340 3         7 $name .= '.pod';
341             }
342              
343 3         20 path( $self->base_dir, $name );
344             }
345              
346             =head2 C
347              
348             This method runs translates the resulting POD from C.
349              
350             =cut
351              
352             sub translate_file {
353 4     4 1 10 my ($self) = @_;
354              
355 4 50       14 if ( my $class = $self->translation_class ) {
356              
357 4         18 load $class;
358 4 50       36918 my $converter = $class->new()
359             or croak "Cannot instantiate a ${class} object";
360              
361 4 50       350 if ( $converter->isa('Pod::Simple') ) {
362              
363 4         100 my $tmp_file = $self->output_file->stringify;
364              
365 4 50       115 close $self->output_fh
366             or croak "Unable to close file ${tmp_file}";
367              
368 4         514 $converter->output_fh( $self->translate_to_fh );
369 4         126 $converter->parse_file($tmp_file);
370              
371             }
372             else {
373              
374 0         0 croak "Don't know how to translate POD using ${class}";
375              
376             }
377              
378             }
379             }
380              
381             =head2 C
382              
383             Used to determine when the dependencies have been updated, and a
384             translation can be run.
385              
386             Note that this only returns a meaningful value after the POD has been
387             processed, since plugins may add to the dependencies. A side-effect
388             of this is that when generating a POD formatted F is that it
389             will always be updated, even when L is false.
390              
391             =cut
392              
393             sub dependencies_updated {
394 3     3 1 2870 my ($self) = @_;
395              
396 3         75 my $dest = $self->translate_to_file;
397              
398 3 50 33     109 if ( $dest and $self->input_file) {
399              
400 3 50       30 return 1 unless -e $dest;
401              
402 3         84 my $stat = $dest->stat;
403 3 50       18839 return 1 unless $stat;
404              
405 3         57 my $time = $stat->mtime;
406 3     6   87 return any { $_->mtime > $time } ( map { $_->stat } $self->depends_on );
  6         423  
  6         352  
407              
408             }
409             else {
410 0         0 return 1;
411             }
412             }
413              
414             =head2 C
415              
416             This method runs C and then L.
417              
418             =cut
419              
420             around 'run' => sub {
421             my ( $orig, $self ) = @_;
422             $self->$orig();
423             if ( $self->force or $self->dependencies_updated ) {
424             $self->translate_file();
425             }
426             };
427              
428             =head2 C
429              
430             my $parser = Pod::Readme->new();
431             $parser->parse_from_file( 'README.pod', 'README' );
432              
433             Pod::Readme->parse_from_file( 'README.pod', 'README' );
434              
435             This is a class method that acts as a L compatibility
436             shim for software that is designed for versions of L
437             prior to v1.0.
438              
439             Its use is deprecated, and will be deleted in later versions.
440              
441             =cut
442              
443             sub parse_from_file {
444 2     2 1 5560 my ( $self, $source, $dest ) = @_;
445              
446 2   100     44 my $class = ref($self) || __PACKAGE__;
447 2         62 my $prf = $class->new(
448             input_file => $source,
449             translate_to_file => $dest,
450             translation_class => 'Pod::Simple::Text',
451             force => 1,
452             );
453 2         96 $prf->run();
454             }
455              
456             =head2 C
457              
458             Like L, this exists as a compatibility shim.
459              
460             Its use is deprecated, and will be deleted in later versions.
461              
462             =cut
463              
464             sub parse_from_filehandle {
465 2     2 1 5478 my ( $self, $source_fh, $dest_fh ) = @_;
466              
467 2   100     15 my $class = ref($self) || __PACKAGE__;
468              
469 2 50       18 my $src_io =
470             IO::Handle->new_from_fd( ( defined $source_fh ) ? fileno($source_fh) : 0,
471             'r' );
472              
473 2 50       166 my $dest_io =
474             IO::Handle->new_from_fd( ( defined $dest_fh ) ? fileno($dest_fh) : 1,
475             'w' );
476              
477 2         182 my $prf = $class->new(
478             input_fh => $src_io,
479             translate_to_fh => $dest_io,
480             translation_class => 'Pod::Simple::Text',
481             force => 1,
482             );
483 2         101 $prf->run();
484             }
485              
486 4     4   1621 use namespace::autoclean;
  4         46527  
  4         15  
487              
488             1;
489              
490             =for readme start
491              
492             =head1 CAVEATS
493              
494             This module is intended to be used by module authors for their own
495             modules. It is not recommended for generating F files from
496             arbitrary Perl modules from untrusted sources.
497              
498             =head1 SEE ALSO
499              
500             See L, L and L.
501              
502             =head1 AUTHORS
503              
504             The original version was by Robert Rothenberg until
505             2010, when maintenance was taken over by David Precious
506             .
507              
508             In 2014, Robert Rothenberg rewrote the module to use filtering instead
509             of subclassing a POD parser.
510              
511             =head2 Acknowledgements
512              
513             Thanks to people who gave feedback and suggestions to posts about the
514             rewrite of this module on L.
515              
516             =head2 Suggestions, Bug Reporting and Contributing
517              
518             This module is developed on GitHub at
519             L
520              
521             =head1 LICENSE
522              
523             Copyright (c) 2005-2014 Robert Rothenberg. All rights reserved.
524             This program is free software; you can redistribute it and/or
525             modify it under the same terms as Perl itself.
526              
527             =cut