File Coverage

blib/lib/Dist/Zilla/Plugin/Template/Tiny.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package Dist::Zilla::Plugin::Template::Tiny;
2              
3 1     1   1281 use Moose;
  0            
  0            
4             use Template::Tiny;
5             use Dist::Zilla::File::InMemory;
6             use List::Util qw(first);
7              
8             # ABSTRACT: process template files in your dist using Template::Tiny
9             our $VERSION = '0.04'; # VERSION
10              
11              
12             with 'Dist::Zilla::Role::FileGatherer';
13             with 'Dist::Zilla::Role::FileMunger';
14             with 'Dist::Zilla::Role::FileInjector';
15             with 'Dist::Zilla::Role::FilePruner';
16              
17             use namespace::autoclean;
18              
19              
20             has finder => (
21             is => 'ro',
22             isa => 'Str',
23             );
24              
25              
26             has output_regex => (
27             is => 'ro',
28             isa => 'Str',
29             default => '/\.tt$//',
30             );
31              
32              
33             has trim => (
34             is => 'ro',
35             isa => 'Bool',
36             default => 0,
37             );
38              
39              
40             has var => (
41             is => 'ro',
42             isa => 'ArrayRef[Str]',
43             default => sub { [] },
44             );
45              
46              
47             has replace => (
48             is => 'ro',
49             isa => 'Bool',
50             default => 0,
51             );
52              
53             has _munge_list => (
54             is => 'ro',
55             isa => 'ArrayRef[Dist::Zilla::Role::File]',
56             default => sub { [] },
57             );
58              
59             has _tt => (
60             is => 'ro',
61             isa => 'Template::Tiny',
62             lazy => 1,
63             default => sub {
64             Template::Tiny->new( TRIM => shift->trim );
65             },
66             );
67              
68              
69             has prune => (
70             is => 'ro',
71             isa => 'Bool',
72             default => 0,
73             );
74              
75             has _prune_list => (
76             is => 'ro',
77             isa => 'ArrayRef[Dist::Zilla::Role::File]',
78             default => sub { [] },
79             );
80              
81              
82             sub gather_files
83             {
84             my($self, $arg) = @_;
85              
86             my $list =
87             defined $self->finder
88             ? $self->zilla->find_files($self->finder)
89             : [ grep { $_->name =~ /\.tt$/ } @{ $self->zilla->files } ];
90              
91             foreach my $template (@$list)
92             {
93             my $filename = do {
94             my $filename = $template->name;
95             eval q{ $filename =~ s} . $self->output_regex;
96             $self->log("processing " . $template->name . " => $filename");
97             $filename;
98             };
99             my $exists = first { $_->name eq $filename } @{ $self->zilla->files };
100             if($self->replace && $exists)
101             {
102             push @{ $self->_munge_list }, [ $template, $exists ];
103             }
104             else
105             {
106             my $file = Dist::Zilla::File::InMemory->new(
107             name => $filename,
108             content => do {
109             my $output = '';
110             my $input = $template->content;
111             $self->_tt->process(\$input, $self->_vars, \$output);
112             $output;
113             },
114             );
115             $self->add_file($file);
116             }
117             push @{ $self->_prune_list }, $template if $self->prune;
118             }
119             }
120              
121             sub _vars
122             {
123             my($self) = @_;
124            
125             unless(defined $self->{_vars})
126             {
127            
128             my %vars = ( dzil => $self->zilla );
129             foreach my $var (@{ $self->var })
130             {
131             if($var =~ /^(.*?)=(.*)$/)
132             {
133             my $name = $1;
134             my $value = $2;
135             for($name,$value) {
136             s/^\s+//;
137             s/\s+$//;
138             }
139             $vars{$name} = $value;
140             }
141             }
142            
143             $self->{_vars} = \%vars;
144             }
145            
146             return $self->{_vars};
147             }
148              
149              
150             sub munge_files
151             {
152             my($self) = @_;
153             foreach my $item (@{ $self->_munge_list })
154             {
155             my($template,$file) = @$item;
156             my $output = '';
157             my $input = $template->content;
158             $self->_tt->process(\$input, $self->_vars, \$output);
159             $file->content($output);
160             }
161             $self->prune_files;
162             }
163              
164              
165             sub prune_files
166             {
167             my($self) = @_;
168             foreach my $template (@{ $self->_prune_list })
169             {
170             $self->log("pruning " . $template->name);
171             $self->zilla->prune_file($template);
172             }
173            
174             @{ $self->_prune_list } = ();
175             }
176              
177              
178             sub mvp_multivalue_args { qw(var) }
179              
180             __PACKAGE__->meta->make_immutable;
181              
182             1;
183              
184             __END__
185              
186             =pod
187              
188             =encoding UTF-8
189              
190             =head1 NAME
191              
192             Dist::Zilla::Plugin::Template::Tiny - process template files in your dist using Template::Tiny
193              
194             =head1 VERSION
195              
196             version 0.04
197              
198             =head1 SYNOPSIS
199              
200             [Template::Tiny]
201              
202             =head1 DESCRIPTION
203              
204             This plugin processes TT template files included in your distribution using
205             L<Template::Tiny> (a subset of L<Template Toolkit|Template>). It provides
206             a single variable C<dzil> which is an instance of L<Dist::Zilla> which can
207             be queried for things like the version or name of the distribution.
208              
209             =head1 ATTRIBUTES
210              
211             =head2 finder
212              
213             Specifies a L<FileFinder|Dist::Zilla::Role::FileFinder> for the TT files that
214             you want processed. If not specified all TT files with the .tt extension will
215             be processed.
216              
217             [FileFinder::ByName / TTFiles]
218             file = *.tt
219             [Template::Tiny]
220             finder = TTFiles
221              
222             =head2 output_regex
223              
224             Regular expression substitution used to generate the output filenames. By default
225             this is
226              
227             [Template::Tiny]
228             output_regex = /\.tt$//
229              
230             which generates a C<Foo.pm> for each C<Foo.pm.tt>.
231              
232             =head2 trim
233              
234             Passed as C<TRIM> to the constructor for L<Template::Tiny>.
235              
236             =head2 var
237              
238             Specify additional variables for use by your template. The format is I<name> = I<value>
239             so to specify foo = 1 and bar = 'hello world' you would include this in your dist.ini:
240              
241             [Template::Tiny]
242             var = foo = 1
243             var = bar = hello world
244              
245             =head2 replace
246              
247             If set to a true value, existing files in the source tree will be replaced, if necessary.
248              
249             =head2 prune
250              
251             If set to a true value, the original template files will NOT be included in the built distribution.
252              
253             =head1 METHODS
254              
255             =head2 $plugin-E<gt>gather_files( $arg )
256              
257             This method processes the TT files and injects the results into your dist.
258              
259             =head2 $plugin-E<gt>munge_files
260              
261             This method is used to munge files that need to be replaced instead of injected.
262              
263             =head2 $plugin-E<gt>prune_files
264              
265             This method is used to prune the original templates if the C<prune> attribute is
266             set.
267              
268             =head2 $plugin-E<gt>mvp_multivalue_args
269              
270             Returns list of attributes that can be specified multiple times.
271              
272             =head1 EXAMPLES
273              
274             Why would you even need templates that get processed when you build your distribution
275             anyway? There are many useful L<Dist::Zilla> plugins that provide mechanisms for
276             manipulating POD and Perl after all. I work on Perl distributions that are web apps
277             that include CSS and JavaScript, and I needed a way to get the distribution version into
278             the JavaScript. This seemed to be the clearest and most simple way to go about this.
279              
280             First of all, I have a share directory called public that gets installed via
281             L<[ShareDir]|Dist::Zilla::Plugin::ShareDir>.
282              
283             [ShareDir]
284             dir = public
285              
286             Next I use this plugin to process .js.tt files in the appropriate directory, so that
287             .js files are produced.
288              
289             [FileFinder::ByName / JavaScriptTTFiles]
290             dir = public/js
291             file = *.js.tt
292             [Template::Tiny]
293             finder = JavaScriptTTFiles
294             replace = 1
295             prune = 1
296              
297             Finally, I create a version.js.tt file
298              
299             if(PlugAuth === undefined) var PlugAuth = {};
300             if(PlugAuth.UI === undefined) PlugAuth.UI = {};
301            
302             PlugAuth.UI.Name = 'PlugAuth WebUI';
303             PlugAuth.UI.VERSION = '[% dzil.version %]';
304              
305             which gets processed and used when the distribution is built and later installed. I also
306             create a version.js file in the same directory so that I can use the distribution without
307             having to build it.
308              
309             if(PlugAuth === undefined) var PlugAuth = {};
310             if(PlugAuth === undefined) PlugAuth.UI = {};
311            
312             PlugAuth.UI.Name = 'PlugAuth WebUI';
313             PlugAuth.UI.VERSION = 'dev';
314              
315             Now when I run it out of the checked out distribution I get C<dev> reported as the version
316             and the actual version reported when I run from an installed copy.
317              
318             There are probably other use cases and ways to get yourself into trouble.
319              
320             =cut
321              
322             =head1 AUTHOR
323              
324             Graham Ollis <plicease@cpan.org>
325              
326             =head1 COPYRIGHT AND LICENSE
327              
328             This software is copyright (c) 2012 by Graham Ollis.
329              
330             This is free software; you can redistribute it and/or modify it under
331             the same terms as the Perl 5 programming language system itself.
332              
333             =cut