File Coverage

blib/lib/Template/Caribou/Role.pm
Criterion Covered Total %
statement 80 81 98.7
branch 15 22 68.1
condition 7 9 77.7
subroutine 28 28 100.0
pod 4 4 100.0
total 134 144 93.0


line stmt bran cond sub pod time code
1             package Template::Caribou::Role;
2             our $AUTHORITY = 'cpan:YANICK';
3             # ABSTRACT: Caribou core engine
4             $Template::Caribou::Role::VERSION = '1.2.1';
5              
6 13     13   127 use 5.20.0;
  13         34  
7 13     13   52 use strict;
  13         14  
  13         220  
8 13     13   39 use warnings;
  13         22  
  13         287  
9 13     13   38 no warnings qw/ uninitialized /;
  13         13  
  13         330  
10              
11 13     13   36 use Carp;
  13         17  
  13         627  
12 13     13   4126 use Moose::Role;
  13         2704813  
  13         70  
13 13     13   52097 use Template::Caribou::Utils;
  13         22  
  13         124  
14              
15 13     13   9098 use Path::Tiny;
  13         98544  
  13         673  
16              
17 13     13   3515 use Template::Caribou::Tags;
  13         29  
  13         231  
18              
19 13     13   3334 use List::AllUtils qw/ uniq any /;
  13         29136  
  13         716  
20              
21 13     13   85 use Moose::Exporter;
  13         18  
  13         107  
22             Moose::Exporter->setup_import_methods(
23             as_is => [ 'template' ],
24             );
25              
26 13     13   544 use experimental 'signatures';
  13         46  
  13         82  
27              
28             has indent => (
29             is => 'rw',
30             default => 1,
31             );
32              
33             has can_add_templates => (
34             is => 'rw',
35             );
36              
37             sub template {
38 19     19 1 17796 my $class = shift;
39              
40             # cute way to say $self might or might not be there
41 19         70 my( $coderef, $name, $self ) = reverse @_;
42              
43 19 100       60 if ( $self ) {
44 5         7 local $Carp::CarpLevel = 1;
45 5 100       166 croak "can only add templates from instances created via 'anon_instance' ",
46             "or with the attribute 'can_add_templates'" unless $self->can_add_templates;
47              
48 3         12 $class = $self->meta;
49             }
50              
51             carp "redefining '$name'"
52 17 50 66 361   264 if $class->can('get_all_method_names') and any { $name eq $_ } $class->get_all_method_names;
  361         18587  
53 17 50       187 carp "redefining '$name'" if $class->name->can($name);
54              
55              
56             $class->add_method( $name => sub {
57 16     16   5826 my( $self, @args ) = @_;
        8      
        8      
        8      
        8      
        8      
        8      
        8      
        5      
        5      
58 16 100       40 if( defined wantarray ) {
59 13         46 return $self->render( $coderef, @args );
60             }
61             else {
62             # void context
63 3         11 $self->render( $coderef, @args );
64 3         5 return;
65             }
66 17         117 });
67             }
68              
69              
70              
71 1 50   1 1 1054 sub anon_instance($class,@args) {
  1         3  
  1         3  
  1         1  
72 1         7 Class::MOP::Class
73             ->create_anon_class(superclasses => [ $class ])
74             ->new_object( can_add_templates => 1, @args);
75             }
76              
77             sub get_render {
78 111     111 1 162 my ( $self, $template, @args ) = @_;
79 111         108 local $Template::Caribou::IN_RENDER;
80 111         220 return $self->render($template,@args);
81             }
82              
83             sub render {
84 149     149 1 15127 my ( $self, $template, @args ) = @_;
85              
86             # 0.1 is true, and yet will round down to '0' for the first indentation
87 149   100     1042 local $Template::Caribou::TAG_INDENT_LEVEL
88             = $Template::Caribou::TAG_INDENT_LEVEL // 0.1 * !! $self->indent;
89              
90 149         404 my $output = $self->_render($template,@args);
91              
92             # if we are still within a render, we turn the string
93             # into an object to say "don't touch"
94 149 100       300 $output = Template::Caribou::String->new( $output )
95             if $Template::Caribou::IN_RENDER;
96              
97             # called in a void context and inside a template => print it
98 149 100       244 print ::RAW $output if $Template::Caribou::IN_RENDER;
99              
100 149         411 return $output;
101             }
102              
103 149 50   149   280 sub _render ($self, $method, @args) {
  149         143  
  149         153  
  149         301  
  149         137  
104 149         160 local $Template::Caribou::TEMPLATE = $self;
105            
106 149         137 local $Template::Caribou::IN_RENDER = 1;
107 149         128 local $Template::Caribou::OUTPUT;
108              
109 149 50       287 unless(ref $method) {
110 0 0       0 $method = $self->can($method)
111             or die "no template named '$method' found\n";
112             }
113              
114 149         256 local *STDOUT;
115 149         224 local *::RAW;
116 149         1101 tie *STDOUT, 'Template::Caribou::Output';
117 149         578 tie *::RAW, 'Template::Caribou::OutputRaw';
118              
119 149         280 select STDOUT;
120              
121 149         741 my $res = $method->( $self, @args );
122              
123 149   66     1060 return( $Template::Caribou::OUTPUT
124             or ref $res ? $res : Template::Caribou::Output::escape( $res ) );
125             }
126              
127             1;
128              
129             __END__
130              
131             =pod
132              
133             =encoding UTF-8
134              
135             =head1 NAME
136              
137             Template::Caribou::Role - Caribou core engine
138              
139             =head1 VERSION
140              
141             version 1.2.1
142              
143             =head1 SYNOPSIS
144              
145             package MyTemplate;
146              
147             use Template::Caribou;
148              
149             has name => ( is => 'ro' );
150              
151             template greetings => sub {
152             my $self = shift;
153              
154             print "hello there, ", $self->name;
155             };
156              
157             # later on...
158            
159             my $template = MyTemplate->new( name => 'Yanick' );
160              
161             print $template->greetings;
162              
163             =head1 DESCRIPTION
164              
165             This role implements the rendering core of Caribou, which mostly deals
166             with defining the templates of a class and calling them.
167              
168             =head2 The templates
169              
170             The templates are subs expected to print or return the content they are generating.
171             Under the hood, they are snugly wrapped within a C<render> call and turned
172             into methods of the template class.
173              
174             package MyTemplate;
175              
176             use Template::Caribou;
177              
178             has name => ( is => 'ro' );
179              
180             template greetings => sub {
181             my( $self, %args ) = @_;
182              
183             'hi there ' . $self->name . '!' x $args{excited};
184             };
185              
186             my $bou = MyTemplate->new( name => 'Yanick' );
187              
188             print $bou->greetings;
189             # prints 'hi there Yanick'
190              
191             print $bou->greetings(excited => 1);
192             # print 'hi there Yanick!
193              
194             In addition of those arguments, the file descriptions
195             C<::STDOUT> and C<::RAW> are locally defined. Anything printed to C<::RAW> is added verbatim to the
196             content of the template, whereas something printed to C<STDOUT> will be HTML-escaped.
197              
198             If nothing has been printed at all by the template, it'll take its return
199             value as its generated content.
200              
201             # prints '&lt;hey>'
202             print MyTemplate->render(sub{
203             print "<hey>";
204             });
205            
206             # prints '<hey>'
207             print MyTemplate->render(sub{
208             print ::RAW "<hey>";
209             });
210              
211             # prints 'onetwo'
212             print MyTemplate->render(sub{
213             print "one";
214             print "two";
215             });
216            
217             # prints 'one'
218             print MyTemplate->render(sub{
219             print "one";
220             return "ignored";
221             });
222            
223             # prints 'no print, not ignored'
224             print MyTemplate->render(sub{
225             return "no print, not ignored";
226             });
227              
228             Template methods can, of course, be called within other template methods.
229             When invoked from within a template, their content is implicitly printed
230             to C<::RAW>.
231              
232             template outer => sub {
233             my $self = shift;
234              
235             say 'alpha';
236             $self->inner;
237             say 'gamma';
238             };
239              
240             template inner => sub {
241             say 'beta';
242             };
243              
244             ...;
245              
246             print $bou->outer; # prints 'alpha beta gamma'
247              
248             =head2 Definiting templates via template instances
249              
250             Templates are usually defined for the class via the
251             C<template> keyword. C<template> can also be used as a method. By default,
252             though, it'll die as adding a template that way will not only add it to
253             the instance, but for to class itself, which is probably more
254             than you bargained for.
255              
256             $bou->template( foo => sub { ... } );
257             # dies with 'can only add templates from instances created
258             # via 'anon_instance' or with the attribute 'can_add_templates'
259              
260             If you want to add a template to a single instance, use
261             the class method C<anon_instance>, which will create a singleton
262             class inheriting from the main template class.
263              
264             my $bou = MyTemplate->anon_instance( name => 'Yanick' );
265              
266             $bou->template( foo => sub { ... } ); # will work
267              
268             Or if you really want to augment the whole class with new
269             templates, you can set the C<can_add_templates> attribute of
270             the object to C<true>.
271              
272             $bou->can_add_templates(1);
273             $bou->template( foo => sub { ... } ); # will work too
274              
275             =head1 METHODS
276              
277             =head2 new
278              
279             my $bou = MyTemplate->new(
280             indent => 1,
281             can_add_templates => 0,
282             );
283              
284             =over
285              
286             =item indent => $boolean
287              
288             If set to a C<true> value, the nested tags rendered inside
289             the templates will be indented. Defaults to C<true>.
290              
291             =item can_add_templates
292              
293             If templates can be added to the class via the method
294             invocation of C<template>.
295              
296             =back
297              
298             =head2 indent
299              
300             $bou->indent($bool);
301              
302             Accessor to the indent attribute. Indicates if the tags rendered
303             within the templates should be pretty-printed with indentation or not.
304              
305             =head2 can_add_templates
306              
307             $bou->can_add_templates($bool);
308              
309             Accessor. If set to C<true>, allows new templates to be
310             defined for the class via the C<template> method.
311              
312             =head2 template( $name => sub { ... } )
313              
314             Defines the template C<$name>. Will trigger an exception unless
315             C<can_add_templates> was set to C<true> or the object was
316             created via C<anon_instance>.
317              
318             Warnings will be issued if the template redefines an already-existing
319             function/method in the namespace.
320              
321             =head2 anon_instance(@args_for_new)
322              
323             Creates an anonymous class inheriting from the current one and builds an object instance
324             with the given arguments. Useful when wanting to define templates for one specific instance.
325              
326             =head2 render
327              
328             $bou->render( $coderef, @template_args );
329             $bou->render( $template_name, @template_args );
330              
331             Renders the given C<$coderef> as a template, passing it the C<@template_args>, and returns its generated output.
332              
333             print $bou->render( sub {
334             my( $self, $name ) = @_;
335              
336             'hi ' . $name . "\n";
337             }, $_ ) for @friends;
338              
339             The template can also be given by name.
340              
341             template foo => sub { ... };
342              
343             # later on
344              
345             $bou->render( 'foo', @args );
346              
347             # which is equivalent to
348              
349             $bou->foo(@args);
350              
351             =head2 get_render
352              
353             Like C<render>, but always return the generated template content, even
354             when called inside a template.
355              
356             template foo => sub { 'foo' };
357             template bar => sub { 'bar' };
358              
359             print $bou->render(sub{
360             my $self = shift;
361              
362             $self->foo;
363             my $bar = $self->get_render(sub{ $self->bar });
364             $bar =~ y/r/z/;
365             say $bar;
366             });
367              
368             # prints 'foobaz'
369              
370             =head1 SEE ALSO
371              
372             L<http://babyl.dyndns.org/techblog/entry/caribou> - The original blog entry
373             introducing L<Template::Caribou>.
374              
375             L<Template::Declare>
376              
377             =head1 AUTHOR
378              
379             Yanick Champoux <yanick@cpan.org>
380              
381             =head1 COPYRIGHT AND LICENSE
382              
383             This software is copyright (c) 2017 by Yanick Champoux.
384              
385             This is free software; you can redistribute it and/or modify it under
386             the same terms as the Perl 5 programming language system itself.
387              
388             =cut