File Coverage

blib/lib/Dist/Zilla/Plugin/InsertExample/FromMojoTemplates.pm
Criterion Covered Total %
statement 22 24 91.6
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 30 32 93.7


line stmt bran cond sub pod time code
1             package Dist::Zilla::Plugin::InsertExample::FromMojoTemplates;
2             $Dist::Zilla::Plugin::InsertExample::FromMojoTemplates::VERSION = '0.02.00';
3 1     1   41155 use strict;
  1         3  
  1         47  
4 1     1   6 use warnings;
  1         2  
  1         30  
5 1     1   15 use 5.10.1;
  1         4  
  1         61  
6              
7 1     1   1081 use File::Find::Rule;
  1         10620  
  1         11  
8 1     1   1166 use MojoX::CustomTemplateFileParser;
  1         1053223  
  1         52  
9 1     1   9 use Moose;
  1         3  
  1         7  
10 1     1   8375 use Path::Tiny;
  1         2  
  1         62  
11 1     1   2784 use Dist::Zilla::File::InMemory;
  0            
  0            
12              
13             with ('Dist::Zilla::Role::FileMunger', 'Dist::Zilla::Role::FileGatherer');
14             with 'Dist::Zilla::Role::FileFinderUser' => {
15             default_finders => [':InstallModules', ':ExecFiles'],
16             };
17              
18             has directory => (
19             is => 'ro',
20             isa => 'Str',
21             default => sub { 'examples/source' },
22             );
23             has filepattern => (
24             is => 'ro',
25             default => sub { qr/\w+-\d+\.mojo/ },
26             );
27             has make_examples => (
28             is => 'ro',
29             isa => 'Bool',
30             default => sub { 1 },
31             );
32              
33             has example_directory => (
34             is => 'ro',
35             isa => 'Str',
36             default => sub { 'examples' },
37             );
38              
39             sub gather_files {
40             my $self = shift;
41             my $arg = shift;
42              
43             return if !$self->make_examples;
44             my $html_template_path = (File::Find::Rule->file->name('template.html')->in($self->directory))[0];
45             my $html_template = path($html_template_path)->slurp;
46              
47             my @paths = File::Find::Rule->file->name(qr/@{[ $self->filepattern ]}/)->in($self->directory);
48             foreach my $path (@paths) {
49             my $contents = MojoX::CustomTemplateFileParser->new(path => path($path)->absolute->canonpath, output => ['Html'])->to_html;
50             $contents = $html_template =~ s{\[EXAMPLES\]}{$contents}r;
51             my $filename = path($path)->basename(qr{\.[^.]+});
52              
53             my $file = Dist::Zilla::File::InMemory->new(
54             name => ''.path($self->example_directory)->child("$filename.html"),
55             content => $contents,
56             );
57             $self->add_file($file);
58              
59             }
60              
61             return;
62             }
63              
64              
65             sub munge_files {
66             my $self = shift;
67             $self->munge_file($_) for @{ $self->found_files };
68             }
69              
70             sub munge_file {
71             my $self = shift;
72             my $file = shift;
73              
74             my $content = $file->content;
75             my $re = $self->filepattern;
76             if($content =~ m{# \s* EXAMPLE: \s* ($re):(.*)}xm) {
77             my $linere = qr{^\s*#\s*EXAMPLE:\s*([^:]+):(.*)$};
78             my @lines = grep { m{$linere} } split /\n/ => $content;
79              
80             my $newcontent = $content;
81              
82             LINE:
83             foreach my $line (@lines) {
84             $line =~ m{$linere};
85              
86             my $filename = $1;
87              
88             my $what = $2;
89             $what =~ s{ }{}g;
90             $what =~ s{,,+}{,}g;
91              
92             my @configs = split m/,/ => $what;
93             my @wanted = ();
94             my @unwanted = ();
95             my $all = 0;
96             my $want_all_examples = 0;
97              
98             CONFIG:
99             foreach my $config (@configs) {
100             if($config eq 'examples') {
101             $want_all_examples = 1;
102             }
103             elsif($config eq 'all') {
104             $all = 1;
105             }
106             elsif($config =~ m{^ (!)? (\d+) (?:-(\d+))? }x) {
107             my $exclude = defined $1 ? 1 : 0;
108             my $first = $2;
109             my $second = $3 || $first;
110              
111             map { push @wanted => $_ } ($first..$second) if !$exclude;
112             map { push @unwanted => $_ } ($first..$second) if $exclude;
113             }
114             }
115              
116             my $parser = MojoX::CustomTemplateFileParser->new( path => path($self->directory)->child($filename)->absolute->canonpath, output => ['Pod'] );
117             my $testcount = $parser->test_count;
118             @wanted = (1..$testcount) if $all || $want_all_examples;
119              
120             my %unwanted;
121             $unwanted{ $_ } = 1 for @unwanted;
122             @wanted = grep { !exists $unwanted{ $_ } } @wanted;
123              
124             my $tomunge = '';
125             foreach my $test (@wanted) {
126             $tomunge .= $parser->to_pod($test, $want_all_examples);
127             }
128              
129             my $success = $newcontent =~ s{$line}{$tomunge};
130              
131             }
132              
133             if($newcontent ne $content) {
134             $file->content($newcontent);
135             }
136              
137             }
138             }
139              
140             __PACKAGE__->meta->make_immutable;
141              
142             1;
143             __END__
144              
145             =encoding utf-8
146              
147             =head1 NAME
148              
149             Dist::Zilla::Plugin::InsertExample::FromMojoTemplates - Creates POD examples from custom L<Mojolicious> templates.
150              
151             =for html <p><a style="float: left;" href="https://travis-ci.org/Csson/p5-Dist-Zilla-Plugin-InsertExample-FromMojoTemplates"><img src="https://travis-ci.org/Csson/p5-Dist-Zilla-Plugin-InsertExample-FromMojoTemplates.svg?branch=master">&nbsp;</a>
152              
153             =head1 SYNOPSIS
154              
155             ; In dist.ini
156             [InsertExample::FromMojoTemplates]
157             directory = examples/source
158             filepattern = ^\w+-\d+\.mojo$
159              
160             =head1 DESCRIPTION
161              
162             Dist::Zilla::Plugin::InsertExample::FromMojoTemplates inserts examples from L<MojoX::CustomTemplateFileParser> type files into POD.
163             Together with L<Dist::Zilla::Plugin::Test::CreateFromMojo> this produces examples in POD from the same source that creates the tests.
164             The purpose is to help develop tag helpers for L<Mojolicious>.
165              
166             =head2 Attributes
167              
168             B<C<directory>>
169              
170             Default: C<examples/source>
171              
172             Where DZP::IE::FMT should look for source files.
173              
174             B<C<filepattern>>
175              
176             Default: C<^\w+-\d+\.mojo$>
177              
178             Look for files that matches a certain pattern.
179              
180             B<C<make_examples>>
181              
182             Default: C<1>
183              
184             If true, will create html files in the chosen directory.
185              
186             B<C<example_directory>>
187              
188             Default: C<examples>
189              
190             The directory for html files.
191              
192             =head2 USAGE
193              
194             Source files looks like this:
195              
196             ==test example 1==
197             --t--
198             %= link_to 'The example 3' => ['http://www.perl.org/']
199             --t--
200             --e--
201             <a href="http://www.perl.org/">Perl</a>
202             --e--
203              
204             This is a test block. One file can have many test blocks.
205              
206             In your pod:
207              
208             # EXAMPLE: filename.mojo:1, 3-30, !5, !22-26
209              
210             # EXAMPLE: filename.mojo:all
211              
212             # EXAMPLE: filename.mojo:examples
213              
214             B<C<all>>
215              
216             Adds all examples in the source file. C<all> can be used by itself or combined with exclusion commands.
217              
218             B<C<1>>
219              
220             Adds example number C<3>. The test number is sequential. Looping tests count as one. You can add a number as in the example to make it easier to follow.
221              
222             B<C<3-30>>
223              
224             Add examples numbered C<5> through C<30>.
225              
226             B<C<!5>>
227              
228             Excludes example C<5> from the previous range.
229              
230             B<C<!22-26>>
231              
232             Excludes examples numbered C<22-26> from the previous range. If an example has been excluded it can't be included later. Exclusions are final.
233              
234             B<C<examples>>
235              
236             Includes all tests marked C<==test example==> in the source file. Exclusion works as with C<all>.
237              
238              
239             =head1 AUTHOR
240              
241             Erik Carlsson E<lt>info@code301.comE<gt>
242              
243             =head1 COPYRIGHT
244              
245             Copyright 2014- Erik Carlsson
246              
247             =head1 LICENSE
248              
249             This library is free software; you can redistribute it and/or modify
250             it under the same terms as Perl itself.
251              
252             =head1 SEE ALSO
253              
254             =cut