File Coverage

blib/lib/Text/Template/Simple.pm
Criterion Covered Total %
statement 109 151 72.1
branch 23 52 44.2
condition 10 25 40.0
subroutine 24 27 88.8
pod 7 7 100.0
total 173 262 66.0


line stmt bran cond sub pod time code
1             package Text::Template::Simple;
2 60     60   895205 use strict;
  60         84  
  60         1406  
3 60     60   203 use warnings;
  60         65  
  60         2014  
4              
5             our $VERSION = '0.90';
6              
7 60     60   210 use File::Spec;
  60         65  
  60         1004  
8              
9 60     60   21479 use Text::Template::Simple::Cache;
  60         103  
  60         1545  
10 60     60   20315 use Text::Template::Simple::Cache::ID;
  60         96  
  60         1247  
11 60     60   20047 use Text::Template::Simple::Caller;
  60         79  
  60         1277  
12 60     60   17918 use Text::Template::Simple::Compiler;
  60         84  
  60         1132  
13 60     60   18103 use Text::Template::Simple::Compiler::Safe;
  60         87  
  60         1358  
14 60     60   223 use Text::Template::Simple::Constants qw(:all);
  60         55  
  60         21637  
15 60     60   257 use Text::Template::Simple::Dummy;
  60         63  
  60         872  
16 60     60   19421 use Text::Template::Simple::IO;
  60         86  
  60         1206  
17 60     60   20259 use Text::Template::Simple::Tokenizer;
  60         89  
  60         1512  
18 60     60   271 use Text::Template::Simple::Util qw(:all);
  60         57  
  60         7874  
19              
20 60         22278 use base qw(
21             Text::Template::Simple::Base::Compiler
22             Text::Template::Simple::Base::Examine
23             Text::Template::Simple::Base::Include
24             Text::Template::Simple::Base::Parser
25 60     60   264 );
  60         63  
26              
27             my %CONNECTOR = qw(
28             Cache Text::Template::Simple::Cache
29             Cache::ID Text::Template::Simple::Cache::ID
30             IO Text::Template::Simple::IO
31             Tokenizer Text::Template::Simple::Tokenizer
32             );
33              
34             my %DEFAULT = ( # default object attributes
35             delimiters => [ DELIMS ], # default delimiters
36             cache => 0, # use cache or not
37             cache_dir => EMPTY_STRING, # will use hdd intead of memory for caching...
38             strict => 1, # set to false for toleration to un-declared vars
39             safe => 0, # use safe compartment?
40             header => 0, # template header. i.e. global codes.
41             add_args => EMPTY_STRING, # will unshift template argument list. ARRAYref.
42             warn_ids => 0, # warn template ids?
43             capture_warnings => 0, # bool
44             iolayer => EMPTY_STRING, # I/O layer for filehandles
45             stack => EMPTY_STRING, # dump caller stack?
46             user_thandler => undef, # user token handler callback
47             monolith => 0, # use monolithic template & cache ?
48             include_paths => [], # list of template dirs
49             verbose_errors => 0, # bool
50             pre_chomp => CHOMP_NONE,
51             post_chomp => CHOMP_NONE,
52             taint_mode => TAINT_CHECK_NORMAL,
53             );
54              
55             my @EXPORT_OK = qw( tts );
56              
57             sub import {
58 58     58   1689 my($class, @args) = @_;
59 58 50       16827 return if ! @args;
60 0         0 my $caller = caller;
61 0         0 my %ok = map { ($_, $_) } @EXPORT_OK;
  0         0  
62              
63 60     60   315 no strict qw( refs );
  60         81  
  60         55896  
64 0         0 foreach my $name ( @args ) {
65 0 0       0 fatal('tts.main.import.invalid', $name, $class) if ! $ok{$name};
66 0 0       0 fatal('tts.main.import.undef', $name, $class) if ! defined &{ $name };
  0         0  
67 0         0 my $target = $caller . q{::} . $name;
68 0 0       0 fatal('tts.main.import.redefine', $name, $caller) if defined &{ $target };
  0         0  
69 0         0 *{ $target } = \&{ $name }; # install
  0         0  
  0         0  
70             }
71              
72 0         0 return;
73             }
74              
75             sub tts {
76 0     0 1 0 my @args = @_;
77 0 0       0 fatal('tts.main.tts.args') if ! @args;
78 0 0       0 my @new = ref $args[0] eq 'HASH' ? %{ shift @args } : ();
  0         0  
79 0         0 return __PACKAGE__->new( @new )->compile( @args );
80             }
81              
82             sub new {
83 90     90 1 2479939 my($class, @args) = @_;
84 90 50       407 my %param = @args % 2 ? () : (@args);
85 90         214 my $self = [ map { undef } 0 .. MAXOBJFIELD ];
  3150         2466  
86 90         214 bless $self, $class;
87              
88 90 50       331 LOG( CONSTRUCT => $self->class_id . q{ @ } . (scalar localtime time) )
89             if DEBUG();
90              
91 90         125 my($fid, $fval);
92 90         629 INITIALIZE: foreach my $field ( keys %DEFAULT ) {
93 1620         1420 $fid = uc $field;
94 1620 50       4763 next INITIALIZE if ! $class->can( $fid );
95 1620         2346 $fid = $class->$fid();
96 1620         1143 $fval = delete $param{$field};
97 1620 100       2494 $self->[$fid] = defined $fval ? $fval : $DEFAULT{$field};
98             }
99              
100 90         280 foreach my $bogus ( keys %param ) {
101 0         0 warn "'$bogus' is not a known parameter. Did you make a typo?\n";
102             }
103              
104 90         270 $self->_init;
105 90         440 return $self;
106             }
107              
108             sub connector {
109 724     724 1 643 my $self = shift;
110 724   33     1225 my $id = shift || fatal('tts.main.connector.args');
111 724   33     2498 return $CONNECTOR{ $id } || fatal('tts.main.connector.invalid', $id);
112             }
113              
114 1298     1298 1 9421 sub cache { return shift->[CACHE_OBJECT] }
115 2444     2444 1 5325 sub io { return shift->[IO_OBJECT] }
116              
117             sub compile {
118 488     488 1 41900 my($self, @args) = @_;
119 488         1729 my $rv = $self->_compile( @args );
120             # we need to reset this to prevent false positives
121             # the trick is: this is set in _compile() and sub includes call _compile()
122             # instead of compile(), so it will only be reset here
123 482         522 $self->[COUNTER_INCLUDE] = undef;
124 482         1382 return $rv;
125             }
126              
127             # -------------------[ P R I V A T E M E T H O D S ]------------------- #
128              
129             sub _init {
130 90     90   126 my $self = shift;
131 90         145 my $d = $self->[DELIMITERS];
132 90   66     290 my $bogus_args = $self->[ADD_ARGS] && ref $self->[ADD_ARGS] ne 'ARRAY';
133              
134 90 50       221 fatal('tts.main.bogus_args') if $bogus_args;
135 90 50 33     397 fatal('tts.main.bogus_delims') if ref $d ne 'ARRAY' || $#{ $d } != 1;
  90         411  
136 90 50       317 fatal('tts.main.dslen') if length($d->[DELIM_START]) < 2;
137 90 50       256 fatal('tts.main.delen') if length($d->[DELIM_END]) < 2;
138 90 50       361 fatal('tts.main.dsws') if $d->[DELIM_START] =~ m{\s}xms;
139 90 50       268 fatal('tts.main.dews') if $d->[DELIM_END] =~ m{\s}xms;
140              
141 90         161 $self->[TYPE] = EMPTY_STRING;
142 90         114 $self->[COUNTER] = 0;
143 90         250 $self->[FAKER] = $self->_output_buffer_var;
144 90         229 $self->[FAKER_HASH] = $self->_output_buffer_var('hash');
145 90         217 $self->[FAKER_SELF] = $self->_output_buffer_var('self');
146 90         141 $self->[INSIDE_INCLUDE] = RESET_FIELD;
147 90         118 $self->[NEEDS_OBJECT] = 0; # the template needs $self ?
148 90         133 $self->[DEEP_RECURSION] = 0; # recursion detector
149              
150 90 50 33     301 fatal('tts.main.init.thandler')
151             if $self->[USER_THANDLER] && ref $self->[USER_THANDLER] ne 'CODE';
152              
153 90 50 33     598 fatal('tts.main.init.include')
154             if $self->[INCLUDE_PATHS] && ref $self->[INCLUDE_PATHS] ne 'ARRAY';
155              
156             $self->[IO_OBJECT] = $self->connector('IO')->new(
157 90         269 @{ $self }[ IOLAYER, INCLUDE_PATHS, TAINT_MODE ],
  90         654  
158             );
159              
160 90 100       263 if ( $self->[CACHE_DIR] ) {
161 4 50       14 $self->[CACHE_DIR] = $self->io->validate( dir => $self->[CACHE_DIR] )
162             or fatal( 'tts.main.cdir' => $self->[CACHE_DIR] );
163             }
164              
165 90         191 $self->[CACHE_OBJECT] = $self->connector('Cache')->new($self);
166              
167 90         151 return;
168             }
169              
170             sub _output_buffer_var {
171 764     764   702 my $self = shift;
172 764   100     1975 my $type = shift || 'scalar';
173 764 100       1666 my $id = $type eq 'hash' ? {}
    100          
174             : $type eq 'array' ? []
175             : \my $fake
176             ;
177 764         1089 $id = "$id";
178 764         3568 $id .= int rand $$; # . rand() . time;
179 764         990 $id =~ tr/a-zA-Z_0-9//cd;
180 764 100       1458 $id =~ s{SCALAR}{SELF}xms if $type eq 'self';
181 764         1745 return q{$} . $id;
182             }
183              
184             sub class_id {
185 6     6 1 12 my $self = shift;
186 6   33     27 my $class = ref($self) || $self;
187 6         332 return sprintf q{%s v%s}, $class, $self->VERSION;
188             }
189              
190             sub _tidy { ## no critic (ProhibitUnusedPrivateSubroutines)
191 0     0     my $self = shift;
192 0           my $code = shift;
193              
194             TEST_TIDY: {
195 0           local($@, $SIG{__DIE__});
  0            
196 0           my $ok = eval { require Perl::Tidy; 1; };
  0            
  0            
197 0 0         if ( ! $ok ) { # :(
198 0           $code =~ s{;}{;\n}xmsgo; # new lines makes it easy to debug
199 0           return $code;
200             }
201             }
202              
203             # We have Perl::Tidy, yay!
204 0           my($buf, $stderr);
205 0           my @argv; # extra arguments
206              
207 0           Perl::Tidy::perltidy(
208             source => \$code,
209             destination => \$buf,
210             stderr => \$stderr,
211             argv => \@argv,
212             );
213              
214 0 0         LOG( TIDY_WARNING => $stderr ) if $stderr;
215 0           return $buf;
216             }
217              
218             sub DESTROY {
219 0   0 0     my $self = shift || return;
220 0           undef $self->[CACHE_OBJECT];
221 0           undef $self->[IO_OBJECT];
222 0           @{ $self } = ();
  0            
223 0 0         LOG( DESTROY => ref $self ) if DEBUG();
224 0           return;
225             }
226              
227             1;
228              
229             __END__
230              
231             =head1 NAME
232              
233             Text::Template::Simple - Simple text template engine
234              
235             =head1 SYNOPSIS
236              
237             use Text::Template::Simple;
238             my $tts = Text::Template::Simple->new();
239             print $tts->compile( $FILEHANDLE );
240             print $tts->compile('Hello, your perl is at <%= $^X %>');
241             print $tts->compile(
242             'hello.tts', # the template file
243             [ name => 'Burak', location => 'Istanbul' ]
244             );
245              
246             Where C<hello.tts> has this content:
247              
248             <% my %p = @_; %>
249             Hello <%= $p{name} %>,
250             I hope it's sunny in <%= $p{location} %>.
251             Local time is <%= scalar localtime time %>
252              
253             =head1 DESCRIPTION
254              
255             This document describes version C<0.90> of C<Text::Template::Simple>
256             released on C<5 July 2016>.
257              
258             This is a simple template module. There is no extra template/mini
259             language. Instead, it uses Perl as the template language. Templates
260             can be cached on disk or inside the memory via the internal cache
261             manager. It is also possible to use static/dynamic includes,
262             pass parameters to includes and apply filters on them.
263             Also see L<Text::Template::Simple::API> for the full C<API> reference.
264              
265             =head1 SYNTAX
266              
267             Template syntax is very simple. There are few kinds of delimiters:
268              
269             =over 4
270              
271             =item *
272              
273             C<< <% %> >> Code Blocks
274              
275             =item *
276              
277             C<< <%= %> >> Self-printing Blocks
278              
279             =item *
280              
281             C<< <%! %> >> Escaped Delimiters
282              
283             =item *
284              
285             C<< <%+ %> >> Static Include Directives
286              
287             =item *
288              
289             C<< <%* %> >> Dynamic include directives
290              
291             =item *
292              
293             C<< <%# %> >> Comment Directives
294              
295             =item *
296              
297             C<< <%| %> >> Blocks with commands
298              
299             =back
300              
301             A simple example:
302              
303             <% foreach my $x (@foo) { %>
304             Element is <%= $x %>
305             <% } %>
306              
307             Do not directly use print() statements, since they'll break the template
308             compilation. Use the self printing C<< <%= %> >> blocks.
309              
310             It is also possible to alter the delimiters:
311              
312             $tts = Text::Template::Simple->new(
313             delimiters => [qw/<?perl ?>/],
314             );
315              
316             then you can use them inside templates:
317              
318             <?perl
319             my @foo = qw(bar baz);
320             foreach my $x (@foo) {
321             ?>
322             Element is <?perl= $x ?>
323             <?perl } ?>
324              
325             If you need to remove a code temporarily without deleting, or need to add
326             comments:
327              
328             <%#
329             This
330             whole
331             block
332             will
333             be
334             ignored
335             %>
336              
337             If you put a space before the pound sign, the block will be a code block:
338              
339             <%
340             # this is normal code not a comment directive
341             my $foo = 42;
342             %>
343              
344             If you want to include a text or I<HTML> file, you can use the
345             static include directive:
346              
347             <%+ my_other.html %>
348             <%+ my_other.txt %>
349              
350             Included files won't be parsed and included statically. To enable
351             parsing for the included files, use the dynamic includes:
352              
353             <%* my_other.html %>
354             <%* my_other.txt %>
355              
356             Interpolation is also supported with both kinds of includes, so the following
357             is valid code:
358              
359             <%+ "/path/to/" . $txt %>
360             <%* "/path/to/" . $myfile %>
361              
362             =head2 Chomping
363              
364             Chomping is the removal of white space before and after your directives. This
365             can be useful if you're generating plain text (instead of HTML which will ignore
366             spaces most of the time). You can either remove all space or replace multiple
367             white space with a single space (collapse). Chomping can be enabled per
368             directive or globally via options to the constructor.
369             See L<Text::Template::Simple::API/pre_chomp> and
370             L<Text::Template::Simple::API/post_chomp> options to
371             L<Text::Template::Simple::API/new> to globally enable chomping.
372              
373             Chomping is enabled with second level commands for all directives. Here is
374             a list of commands:
375              
376             - Chomp
377             ~ Collapse
378             ^ No chomp (override global)
379              
380             All directives can be chomped. Here are some examples:
381              
382             Chomp:
383              
384             raw content
385             <%- my $foo = 42; -%>
386             raw content
387             <%=- $foo -%>
388             raw content
389             <%*- /mt/dynamic.tts -%>
390             raw content
391              
392             Collapse:
393              
394             raw content
395             <%~ my $foo = 42; ~%>
396             raw content
397             <%=~ $foo ~%>
398             raw content
399             <%*~ /mt/dynamic.tts ~%>
400             raw content
401              
402             No chomp:
403              
404             raw content
405             <%^ my $foo = 42; ^%>
406             raw content
407             <%=^ $foo ^%>
408             raw content
409             <%*^ /mt/dynamic.tts ^%>
410             raw content
411              
412             It is also possible to mix the chomping types:
413              
414             raw content
415             <%- my $foo = 42; ^%>
416             raw content
417             <%=^ $foo ~%>
418             raw content
419             <%*^ /mt/dynamic.tts -%>
420             raw content
421              
422             For example this template:
423              
424             Foo
425             <%- $prehistoric = $] < 5.008 -%>
426             Bar
427              
428             Will become:
429              
430             FooBar
431              
432             And this one:
433              
434             Foo
435             <%~ $prehistoric = $] < 5.008 -%>
436             Bar
437              
438             Will become:
439              
440             Foo Bar
441              
442             Chomping is inspired by Template Toolkit (mostly the same functionality,
443             although C<TT> seems to miss collapse/no-chomp per directive option).
444              
445             =head2 Accessing Template Names
446              
447             You can use C<$0> to get the template path/name inside the template:
448              
449             I am <%= $0 %>
450              
451             =head2 Escaping Delimiters
452              
453             If you have to build templates like this:
454              
455             Test: <%abc>
456              
457             or this:
458              
459             Test: <%abc%>
460              
461             This will result with a template compilation error. You have to use the
462             delimiter escape command C<!>:
463              
464             Test: <%!abc>
465             Test: <%!abc%>
466              
467             Those will be compiled as:
468              
469             Test: <%abc>
470             Test: <%abc%>
471              
472             Alternatively, you can change the default delimiters to solve this issue.
473             See the L<Text::Template::Simple::API/delimiters> option for
474             L<Text::Template::Simple::API/new> for more information on how to
475             do this.
476              
477             =head2 Template Parameters
478              
479             You can fetch parameters (passed to compile) in the usual C<perl> way:
480              
481             <%
482             my $foo = shift;
483             my %bar = @_;
484             %>
485             Baz is <%= $bar{baz} %>
486              
487             =head2 INCLUDE COMMANDS
488              
489             Include commands are separated by pipes in an include directive.
490             Currently supported parameters are:
491              
492             =over 4
493              
494             =item C<PARAM>
495              
496             =item FILTER
497              
498             =item SHARE
499              
500             =back
501              
502             <%+ /path/to/static.tts | FILTER: MyFilter %>
503             <%* /path/to/dynamic.tts | FILTER: MyFilter | PARAM: test => 123 %>
504              
505             C<PARAM> defines the parameter list to pass to the included file.
506             C<FILTER> defines the list of filters to apply to the output of the include.
507             C<SHARE> used to list the variables to share with the included template when
508             the monolith option is disabled.
509              
510             =head3 INCLUDE FILTERS
511              
512             Use the include command C<FILTER:> (notice the colon in the command):
513              
514             <%+ /path/to/static.tts | FILTER: First, Second %>
515             <%* /path/to/dynamic.tts | FILTER: Third, Fourth, Fifth %>
516              
517             =head4 IMPLEMENTING INCLUDE FILTERS
518              
519             Define the filter inside C<Text::Template::Simple::Dummy> with a C<filter_>
520             prefix:
521              
522             package Text::Template::Simple::Dummy;
523             sub filter_MyFilter {
524             # $tts is the current Text::Template::Simple object
525             # $output_ref is the scalar reference to the output of
526             # the template.
527             my($tts, $output_ref) = @_;
528             $$output_ref .= "FILTER APPLIED"; # add to output
529             return;
530             }
531              
532             =head3 INCLUDE PARAMETERS
533              
534             Just pass the parameters as described above and fetch them via C<@_> inside
535             the included file.
536              
537             =head3 SHARED VARIABLES
538              
539             C<Text::Template::Simple> compiles every template individually with separate
540             scopes. A variable defined in the master template is not accessible from a
541             dynamic include. The exception to this rule is the C<monolith> option to C<new>.
542             If it is enabled; the master template and any includes it has will be compiled
543             into a single document, thus making every variable defined at the top available
544             to the includes below. But this method has several drawbacks, it disables cache
545             check for the sub files (includes) --you'll need to edit the master template
546             to force a cache reload-- and it can not be used with interpolated includes.
547             If you use an interpolated include with monolith enabled, you'll get an error.
548              
549             If you don't use C<monolith> (disabled by default), then you'll need to share
550             the variables somehow to don't repeat yourself. Variable sharing is demonstrated
551             in the below template:
552              
553             <%
554             my $foo = 42;
555             my $bar = 23;
556             %>
557             <%* dyna.inc | SHARE: $foo, $bar %>
558              
559             And then you can access C<$foo> and C<$bar> inside C<dyna.inc>. There is one
560             drawback by shared variables: only C<SCALARs> can be shared. You can not share
561             anything else. If you want to share an array, use an array reference instead:
562              
563             <%
564             my @foo = (1..10);
565             my $fooref = \@foo;
566             %>
567             <%* dyna.inc | SHARE: $fooref %>
568              
569             =head2 BLOCKS
570              
571             A block consists of a header part and the content.
572              
573             <%| HEADER;
574             BODY
575             %>
576              
577             C<HEADER> includes the commands and terminated with a semicolon. C<BODY> is the
578             actual block content.
579              
580             =head3 BLOCK FILTERS
581              
582             B<WARNING> Block filters are considered to be experimental. They may be changed
583             or completely removed in the future.
584              
585             Identical to include filters, but works on blocks of text:
586              
587             <%| FILTER: HTML, OtherFilter;
588             <p>&FooBar=42</p>
589             %>
590              
591             Note that you can not use any variables in these blocks. They are static.
592              
593             =head1 METHODS & FUNCTIONS
594              
595             =head2 new
596              
597             =head2 cache
598              
599             =head2 class_id
600              
601             =head2 compile
602              
603             =head2 connector
604              
605             =head2 C<io>
606              
607             =head2 C<tts>
608              
609             See L<Text::Template::Simple::API> for the technical/gory details.
610              
611             =head1 EXAMPLES
612              
613             TODO
614              
615             =head1 ERROR HANDLING
616              
617             You may need to C<eval> your code blocks to trap exceptions. Some recoverable
618             failures are silently ignored, but you can display them as warnings
619             if you enable debugging.
620              
621             =head1 BUGS
622              
623             Contact the author if you find any bugs.
624              
625             =head1 CAVEATS
626              
627             =head2 No mini language
628              
629             There is no mini-language. Only C<perl> is used as the template
630             language. So, this may or may not be I<safe> from your point
631             of view. If this is a problem for you, just don't use this
632             module. There are plenty of template modules with mini-languages
633             inside C<CPAN>.
634              
635             =head2 Speed
636              
637             There is an initialization cost and this will show itself after
638             the first compilation process. The second and any following compilations
639             will be much faster. Using cache can also improve speed, since this will
640             eliminate the parsing phase. Also, using memory cache will make
641             the program run more faster under persistent environments. But the
642             overall speed really depends on your environment.
643              
644             Internal cache manager generates ids for all templates. If you supply
645             your own id parameter, this will improve performance.
646              
647             =head2 Optional Dependencies
648              
649             Some methods/functionality of the module needs these optional modules:
650              
651             Devel::Size
652             Text::Table
653             Perl::Tidy
654              
655             =head1 SEE ALSO
656              
657             L<Text::Template::Simple::API>, L<Apache::SimpleTemplate>, L<Text::Template>,
658             L<Text::ScriptTemplate>, L<Safe>, L<Opcode>.
659              
660             =head2 MONOLITHIC VERSION
661              
662             C<Text::Template::Simple> consists of C<15+> separate modules. If you are
663             after a single C<.pm> file to ease deployment, download the distribution
664             from a C<CPAN> mirror near you to get a monolithic C<Text::Template::Simple>.
665             It is automatically generated from the separate modules and distributed in
666             the C<monolithic_version> directory.
667              
668             However, be aware that the monolithic version is B<not supported>.
669              
670             =head1 AUTHOR
671              
672             Burak Gursoy <burak@cpan.org>.
673              
674             =head1 COPYRIGHT
675              
676             Copyright 2004 - 2016 Burak Gursoy. All rights reserved.
677              
678             =head1 LICENSE
679              
680             This library is free software; you can redistribute it and/or modify
681             it under the same terms as Perl itself, either Perl version 5.24.0 or,
682             at your option, any later version of Perl 5 you may have available.
683             =cut