File Coverage

blib/lib/Dist/Zilla/Plugin/Pod2Html.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             #-----------------------------------------------------------------
2             # Dist::Zilla::Plugin::Pod2Html
3             # Author: Martin Senger <martin.senger@gmail.com>
4             # For copyright and disclaimer in the POD.
5             #
6             # ABSTRACT: create CSS-rich HTML pages from the POD-aware files
7             # PODNAME: Dist::Zilla::Plugin::Pod2Html
8             #-----------------------------------------------------------------
9 1     1   46511 use warnings;
  1         4  
  1         112  
10 1     1   7 use strict;
  1         5  
  1         187  
11             package Dist::Zilla::Plugin::Pod2Html;
12             our $VERSION = '0.1.2'; # VERSION
13              
14 1     1   662 use Moose;
  0            
  0            
15             use Moose::Autobox;
16             use PPI;
17             use File::Basename;
18             use File::Spec;
19             use Pod::Simple::HTML;
20             use Encode qw( encode );
21             use Dist::Zilla::File::InMemory;
22              
23             with ('Dist::Zilla::Role::InstallTool', # will be done after PodWeaver
24             'Dist::Zilla::Role::FileFinderUser' => { # where to take input files from
25             default_finders => [ ':InstallModules', ':ExecFiles' ],
26             },
27             );
28              
29             sub mvp_multivalue_args { return qw( ignore ) }
30              
31             # ------------------------------------------------------------------
32             # Where to create HTML output files.
33             # ------------------------------------------------------------------
34             has dir => (
35             is => 'ro',
36             isa => 'Str',
37             default => 'docs',
38             );
39              
40             # ------------------------------------------------------------------
41             # Which input files to ignore.
42             # ------------------------------------------------------------------
43             has ignore => (
44             is => 'rw',
45             isa => 'ArrayRef[Str]',
46             default => sub { [] },
47             );
48              
49             # ------------------------------------------------------------------
50             # Return $file if it could be an input file for us. Otherwise return
51             # undef. (Partly taken from Dzill::Zilla::Plugin::MinimumPerl)
52             # ------------------------------------------------------------------
53             sub is_interesting_file {
54             my ($self, $file) = @_;
55              
56             return if $file->name =~ m{^corpus/};
57             return if $file->name =~ m{\.t$}i;
58             return if @{ $self->ignore->grep ( sub { $_ eq $file->name } )} > 0;
59             return $file if $file->name =~ m{\.(?:pm|pl)$}i;
60             return $file if $file->content =~ m{^#!(?:.*)perl(?:$|\s)};
61             return;
62             }
63              
64             # ------------------------------------------------------------------
65             # The main job
66             # ------------------------------------------------------------------
67             sub setup_installer {
68             my ($self, $arg) = @_;
69              
70             $self->log_debug ("Attribute DIR: " . $self->dir);
71             $self->log_debug ("Attribute IGNORE: " . join (" | ", @{ $self->ignore }));
72              
73             my $result_count = 0;
74             my $files = $self->found_files;
75             foreach my $file (@$files) {
76             next unless $self->is_interesting_file ($file);
77             my $content = $file->content;
78             my $document = PPI::Document->new (\$content);
79             if ($document) {
80             # does it contain any POD?
81             if ($document->find_any ('PPI::Token::Pod')) {
82             my $new_file = Dist::Zilla::File::InMemory->new ({
83             content => $self->pod2html ($file),
84             name => $self->output_filename ($file),
85             });
86             $self->add_file ($new_file);
87             $result_count++;
88             }
89             }
90             }
91             $self->log("$result_count documentation files created in '" . $self->dir . "'");
92             return;
93             }
94              
95             # ------------------------------------------------------------------
96             # Create and return a suitable name for the output file for the given
97             # input $file.
98             # ------------------------------------------------------------------
99             sub output_filename {
100             my ($self, $file) = @_;
101              
102             my ($basename, $path, $suffix) = fileparse ($file->name, qr{\.[^.]*});
103             $path =~ s{^(lib|bin)[/\\]}{};
104             $path =~ s{[/\\]}{-}g;
105             return File::Spec->catfile (
106             $self->dir,
107             "$path$basename.html"
108             );
109             }
110              
111             # ------------------------------------------------------------------
112             # Convert the content of the $file to the HTML output, and return it.
113             # ------------------------------------------------------------------
114             sub pod2html {
115             my ($self, $file) = @_;
116              
117             # CSS-style to be added to the resulting files
118             my $style = $self->get_css_style();
119              
120             # make the POD to HTML conversion
121             my $result;
122             my $parser = Pod::Simple::HTML->new;
123             $parser->index (1);
124             $parser->html_css ("\n$style\n");
125             $parser->output_string (\$result);
126             $parser->parse_string_document ($file->content);
127              
128             # ...and perhaps encode it
129             if (defined $parser->{encoding}) {
130             return encode ($parser->{encoding} , $result);
131             } else {
132             return $result;
133             }
134             }
135              
136             # ------------------------------------------------------------------
137             # Return a string containing CSS-style to be added to the resulting
138             # HTML files. It is read from the <DATA> section of this module
139             # (unless a subclass overwrites this method).
140             # ------------------------------------------------------------------
141             my $Style; # global (we can read <DATA> only once)
142             sub get_css_style {
143             my $self = shift;
144             unless ($Style) {
145             my @style = <DATA>;
146             $Style = join ("", @style);
147             }
148             return $Style;
149             }
150              
151             __PACKAGE__->meta->make_immutable;
152             no Moose;
153              
154             1;
155              
156              
157              
158              
159             =pod
160              
161             =head1 NAME
162              
163             Dist::Zilla::Plugin::Pod2Html - create CSS-rich HTML pages from the POD-aware files
164              
165             =head1 VERSION
166              
167             version 0.1.2
168              
169             =head1 SYNOPSIS
170              
171             # dist.ini
172             [Pod2Html]
173              
174             # or
175             [Pod2Html]
176             dir = my_docs ; where to create HTML files
177              
178             # or
179             [Pod2Html]
180             ignore = bin/myscript1 ; what input file to ignore
181             ignore = bin/myscript2 ; another input to ignore
182              
183             =head1 DESCRIPTION
184              
185             This plugin generates HTML pages from the POD files and puts them into
186             the distribution in a separate directory (not as a tree of files but
187             flatten). The created HTML pages have the same (or, at least, similar)
188             style as the modules' documentation shown at CPAN.
189              
190             It creates HTML pages from all files in the C<lib> and C<bin>
191             directory that contain a POD section and that have C<.pm> or C<.pl>
192             extension or that have the word C<perl> in their first line. The
193             plugin is run after other plugins that may munge files and create the
194             POD sections (such as I<PodWeaver>).
195              
196             =head1 ATTRIBUTES
197              
198             All attributes are optional.
199              
200             =head3 dir
201              
202             This attribute changes the destination of the generated HTML files. It
203             is a directory (or even a path) relative to the distribution root
204             directory. Default value is C<docs>. For example:
205              
206             [Pod2Html]
207             dir = docs/html
208              
209             =head3 ignore
210              
211             This attribute allows to ignore some input files that would be
212             otherwise converted to HTML. Its value is a file name that should be
213             ignored (relative to the distribution root directory). By default no
214             (appropriate) files are ignored. The attribute can be repeated if you
215             wish to ignore more files. For example:
216              
217             [Pod2Html]
218             ignore = lib/My/Sample.pm
219             ignore = bin/obscure-script
220              
221             =head1 SUBCLASSING
222              
223             New plugins can be created by subclassing this plugin. The subclass
224             may consider to overwrite following methods:
225              
226             =head3 is_interesting_file ($file)
227              
228             The method decides (by returning something or undef) whether the given
229             file should be a candidate for the conversion to the HTML. The
230             parameter is a blessed object with the C<Dist::Zilla::Role::File>
231             role.
232              
233             =head3 pod2html ($file)
234              
235             This method does the conversion to the HTML (using module
236             C<Pod::Simple::HTML>). It gets an input file (a blessed object with
237             the C<Dist::Zilla::Role::File> role) and it should return a converted
238             content. By overwriting this method a new plugin can make any
239             conversion, to anything.
240              
241             =head3 get_css_style
242              
243             It returns a string containing CSS-style definitions. The string will
244             be used in the C<head> section of the created HTML file. See its
245             default value in the I<__DATA__> section of this module.
246              
247             =head1 AUTHOR
248              
249             Martin Senger <martin.senger@gmail.com>
250              
251             =head1 COPYRIGHT AND LICENSE
252              
253             This software is copyright (c) 2013 by Martin Senger, CBRC - KAUST (Computational Biology Research Center - King Abdullah University of Science and Technology) All Rights Reserved..
254              
255             This is free software; you can redistribute it and/or modify it under
256             the same terms as the Perl 5 programming language system itself.
257              
258             =cut
259              
260              
261             __DATA__
262             <style type="text/css">
263             <!--/*--><![CDATA[/*><!--*/
264             BODY {
265             background: white;
266             color: black;
267             font-family: arial,sans-serif;
268             margin: 0;
269             padding: 1ex;
270             }
271              
272             A:link, A:visited {
273             background: transparent;
274             color: #006699;
275             }
276              
277             A[href="#POD_ERRORS"] {
278             background: transparent;
279             color: #FF0000;
280             }
281              
282             DIV {
283             border-width: 0;
284             }
285              
286             DT {
287             margin-top: 1em;
288             margin-left: 1em;
289             }
290              
291             .pod { margin-right: 20ex; }
292              
293             .pod PRE {
294             background: #eeeeee;
295             border: 1px solid #888888;
296             color: black;
297             padding: 1em;
298             white-space: pre;
299             }
300              
301             .pod H1 {
302             background: transparent;
303             color: #006699;
304             font-size: large;
305             }
306              
307             .pod H1 A { text-decoration: none; }
308             .pod H2 A { text-decoration: none; }
309             .pod H3 A { text-decoration: none; }
310             .pod H4 A { text-decoration: none; }
311              
312             .pod H2 {
313             background: transparent;
314             color: #006699;
315             font-size: medium;
316             }
317              
318             .pod H3 {
319             background: transparent;
320             color: #006699;
321             font-size: medium;
322             font-style: italic;
323             }
324              
325             .pod H4 {
326             background: transparent;
327             color: #006699;
328             font-size: medium;
329             font-weight: normal;
330             }
331              
332             .pod IMG {
333             vertical-align: top;
334             }
335              
336             .pod .toc A {
337             text-decoration: none;
338             }
339              
340             .pod .toc LI {
341             line-height: 1.2em;
342             list-style-type: none;
343             }
344              
345             /*]]>*/-->
346             </style>