fixed bug in compiler where it lost $+[0] during recursion
[urisagit/Template-Simple.git] / lib / Template / Simple.pm
CommitLineData
e374d8da 1package Template::Simple;
2
3use warnings;
4use strict;
5
6use Carp ;
9d1a25cd 7use Data::Dumper ;
e374d8da 8use Scalar::Util qw( reftype ) ;
9use File::Slurp ;
10
e374d8da 11
12our $VERSION = '0.03';
13
14my %opt_defaults = (
15
16 pre_delim => qr/\[%/,
17 post_delim => qr/%\]/,
18 greedy_chunk => 0,
19# upper_case => 0,
20# lower_case => 0,
21 include_paths => [ qw( templates ) ],
22) ;
23
24sub new {
25
26 my( $class, %opts ) = @_ ;
27
28 my $self = bless {}, $class ;
29
30# get all the options or defaults into the object
31
32 while( my( $name, $default ) = each %opt_defaults ) {
33
34 $self->{$name} = defined( $opts{$name} ) ?
35 $opts{$name} : $default ;
36 }
37
38# make up the regexes to parse the markup from templates
39
40# this matches scalar markups and grabs the name
41
42 $self->{scalar_re} = qr{
43 $self->{pre_delim}
44 \s* # optional leading whitespace
45 (\w+?) # grab scalar name
46 \s* # optional trailing whitespace
47 $self->{post_delim}
48 }xi ; # case insensitive
49
50#print "RE <$self->{scalar_re}>\n" ;
51
52# this grabs the body of a chunk in either greedy or non-greedy modes
53
54 my $chunk_body = $self->{greedy_chunk} ? qr/.+/s : qr/.+?/s ;
55
56# this matches a marked chunk and grabs its name and text body
57
58 $self->{chunk_re} = qr{
59 $self->{pre_delim}
60 \s* # optional leading whitespace
61 START # required START token
62 \s+ # required whitespace
63 (\w+?) # grab the chunk name
64 \s* # optional trailing whitespace
65 $self->{post_delim}
66 ($chunk_body) # grab the chunk body
67 $self->{pre_delim}
68 \s* # optional leading whitespace
69 END # required END token
70 \s+ # required whitespace
71 \1 # match the grabbed chunk name
72 \s* # optional trailing whitespace
73 $self->{post_delim}
74 }xi ; # case insensitive
75
76#print "RE <$self->{chunk_re}>\n" ;
77
78# this matches a include markup and grabs its template name
79
80 $self->{include_re} = qr{
81 $self->{pre_delim}
82 \s* # optional leading whitespace
83 INCLUDE # required INCLUDE token
84 \s+ # required whitespace
85 (\w+?) # grab the included template name
86 \s* # optional trailing whitespace
87 $self->{post_delim}
88 }xi ; # case insensitive
89
90# load in any templates
91
92 $self->add_templates( $opts{templates} ) ;
93
94 return $self ;
95}
96
59d7205c 97sub compile {
e374d8da 98
59d7205c 99 my( $self, $template_name ) = @_ ;
100
101 my $tmpl_ref = eval {
102 $self->_get_template( $template_name ) ;
103 } ;
104
105 croak "Template::Simple $@" if $@ ;
106
107# compile a copy of the template as it will be destroyed
108
109 my $code_body = $self->_compile_chunk( '', "${$tmpl_ref}", "\t" ) ;
110
89bd07c7 111 my $source = <<CODE ;
59d7205c 112no warnings ;
113
114sub {
115 my( \$data ) = \@_ ;
116
9d1a25cd 117 my \$out ;
59d7205c 118
9d1a25cd 119$code_body
59d7205c 120 return \\\$out ;
121}
122CODE
123
89bd07c7 124#print $source ;
59d7205c 125
89bd07c7 126 my $code_ref = eval $source ;
59d7205c 127
ca30cbfe 128print $@ if $@ ;
59d7205c 129
130 $self->{compiled_cache}{$template_name} = $code_ref ;
89bd07c7 131 $self->{source_cache}{$template_name} = $source ;
132}
133
9d1a25cd 134sub _compile_chunk {
89bd07c7 135
9d1a25cd 136 my( $self, $chunk_name, $template, $indent ) = @_ ;
89bd07c7 137
9d1a25cd 138 return '' unless length $template ;
59d7205c 139
9d1a25cd 140# generate a lookup in data for this chunk name (unless it is the top
141# level). this descends down the data tree during rendering
59d7205c 142
9d1a25cd 143 my $data_init = $chunk_name ? "\$data->{$chunk_name}" : '$data' ;
59d7205c 144
9d1a25cd 145 my $code = <<CODE ;
146${indent}my \@data = $data_init ;
52705b1c 147${indent}while( \@data ) {
59d7205c 148
52705b1c 149${indent} my \$data = shift \@data ;
9d1a25cd 150${indent} if ( ref \$data eq 'ARRAY' ) {
151${indent} push \@data, \@{\$data} ;
152${indent} next ;
153${indent} }
59d7205c 154
9d1a25cd 155CODE
156
157 $indent .= "\t" ;
59d7205c 158
159# loop all nested chunks and the text separating them
160
52705b1c 161 while( my( $parsed_name, $parsed_body ) =
162 $template =~ m{$self->{chunk_re}} ) {
59d7205c 163
544b9c25 164 my $chunk_left_index = $-[0] ;
165 my $chunk_right_index = $+[0] ;
166
9d1a25cd 167# get the pre-match text and compile its scalars and text. append to the code
59d7205c 168
9d1a25cd 169 $code .= $self->_compile_scalars(
544b9c25 170 substr( $template, 0, $chunk_left_index ), $indent ) ;
59d7205c 171
ca30cbfe 172# print "CHUNK: [$1] BODY [$2]\n\n" ;
544b9c25 173# print "TRUNC: [", substr( $template, 0, $chunk_right_index ), "]\n\n" ;
174# print "PRE: [", substr( $template, 0, $chunk_left_index ), "]\n\n" ;
175
176# chop off the pre-match and the chunk
177
178 substr( $template, 0, $chunk_right_index, '' ) ;
179
180# print "REMAIN: [$template]\n\n" ;
ca30cbfe 181
9d1a25cd 182# compile the nested chunk and append to the code
59d7205c 183
52705b1c 184 $code .= $self->_compile_chunk(
185 $parsed_name, $parsed_body, $indent
186 ) ;
59d7205c 187 }
188
9d1a25cd 189# compile trailing text for scalars and append to the code
59d7205c 190
9d1a25cd 191 $code .= $self->_compile_scalars( $template, $indent ) ;
7dd12000 192
193 chop $indent ;
59d7205c 194
9d1a25cd 195# now we end the loop for this chunk
7dd12000 196 $code .= <<CODE ;
7dd12000 197$indent}
7dd12000 198CODE
59d7205c 199
59d7205c 200 return $code ;
201}
202
203sub _compile_scalars {
204
9d1a25cd 205 my( $self, $template, $indent ) = @_ ;
59d7205c 206
207# if the template is empty return no parts
208
9d1a25cd 209 return '' unless length $template ;
59d7205c 210
211 my @parts ;
212
213 while( $template =~ m{$self->{scalar_re}}g ) {
214
9d1a25cd 215# get the pre-match text before the scalar markup and generate code to
216# access the scalar
59d7205c 217
218 push( @parts,
219 dump_text( substr( $template, 0, $-[0] ) ),
220 "\$data->{$1}"
221 ) ;
ca30cbfe 222
223# truncate the matched text so the next match starts at begining of string
224
59d7205c 225 substr( $template, 0, $+[0], '' ) ;
226 }
227
228# keep any trailing text part
229
230 push @parts, dump_text( $template ) ;
231
9d1a25cd 232 my $parts_code = join( "\n$indent.\n$indent", @parts ) ;
233
234 return <<CODE ;
235
236${indent}\$out .= ref \$data ne 'HASH' ? \$data :
237${indent}$parts_code ;
238
239CODE
59d7205c 240}
241
59d7205c 242
243sub dump_text {
244
245 my( $text ) = @_ ;
246
247 return unless length $text ;
248
249 local( $Data::Dumper::Useqq ) = 1 ;
250
251 my $dumped = Dumper $text ;
252
253 $dumped =~ s/^[^"]+// ;
254 $dumped =~ s/;\n$// ;
255
256 return $dumped ;
257}
e374d8da 258
9d1a25cd 259sub get_source {
260
261 my( $self, $template_name ) = @_ ;
262
263 return $self->{source_cache}{$template_name} ;
264}
265
e374d8da 266sub render {
267
59d7205c 268 my( $self, $template_name, $data ) = @_ ;
269
7dd12000 270 my $tmpl_ref = ref $template_name eq 'SCALAR' ? $template_name : '' ;
59d7205c 271
7dd12000 272 unless( $tmpl_ref ) {
59d7205c 273
7dd12000 274# render with cached code and return if we precompiled this template
e374d8da 275
7dd12000 276 if ( my $compiled = $self->{compiled_cache}{$template_name} ) {
59d7205c 277
7dd12000 278 return $compiled->($data) ;
279 }
59d7205c 280
544b9c25 281# not compiled so try to get this template by name or
282# assume the template name are is the actual template
7dd12000 283
544b9c25 284 $tmpl_ref =
285 eval{ $self->_get_template($template_name) } ||
286 \$template_name ;
7dd12000 287 }
e374d8da 288
289 my $rendered = $self->_render_includes( $tmpl_ref ) ;
290
291#print "INC EXP <$rendered>\n" ;
292
293 $rendered = eval {
294 $self->_render_chunk( $rendered, $data ) ;
295 } ;
296
297 croak "Template::Simple $@" if $@ ;
298
299 return $rendered ;
300}
301
302sub _render_includes {
303
304 my( $self, $tmpl_ref ) = @_ ;
305
306# make a copy of the initial template so we can render it.
307
308 my $rendered = ${$tmpl_ref} ;
309
310# loop until we can render no more include markups
311
312 1 while $rendered =~
313 s{$self->{include_re}}
314 { ${ $self->_get_template($1) }
315 }e ;
316
317 return \$rendered ;
318}
319
320my %renderers = (
321
322 HASH => \&_render_hash,
323 ARRAY => \&_render_array,
324 CODE => \&_render_code,
325# if no ref then data is a scalar so replace the template with just the data
326 '' => sub { \$_[2] },
327) ;
328
329
330sub _render_chunk {
331
332 my( $self, $tmpl_ref, $data ) = @_ ;
333
334#print "T ref [$tmpl_ref] [$$tmpl_ref]\n" ;
335#print "CHUNK ref [$tmpl_ref] TMPL\n<$$tmpl_ref>\n" ;
336
337#print Dumper $data ;
338
339 return \'' unless defined $data ;
340
341# now render this chunk based on the type of data
342
343 my $renderer = $renderers{reftype $data || ''} ;
344
345#print "EXP $renderer\nREF ", reftype $data, "\n" ;
346
347 die "unknown template data type '$data'\n" unless defined $renderer ;
348
349 return $self->$renderer( $tmpl_ref, $data ) ;
350}
351
352sub _render_hash {
353
354 my( $self, $tmpl_ref, $href ) = @_ ;
355
356 return $tmpl_ref unless keys %{$href} ;
357
358# we need a local copy of the template to render
359
360 my $rendered = ${$tmpl_ref} ;
361
362
363# recursively render all top level chunks in this chunk
364
365 $rendered =~ s{$self->{chunk_re}}
366 {
367 # print "CHUNK $1\nBODY\n----\n<$2>\n\n------\n" ;
ca30cbfe 368# print "CHUNK $1\nBODY\n----\n<$2>\n\n------\n" ;
369# print "pre CHUNK [$`]\n" ;
e374d8da 370 ${ $self->_render_chunk( \"$2", $href->{$1} ) }
371 }gex ;
372
373# now render scalars
374
375#print "HREF: ", Dumper $href ;
376
377 $rendered =~ s{$self->{scalar_re}}
378 {
379 # print "SCALAR $1 VAL $href->{$1}\n" ;
380 defined $href->{$1} ? $href->{$1} : ''
381 }ge ;
382
383#print "HASH REND3\n<$rendered>\n" ;
384
385 return \$rendered ;
386}
387
388sub _render_array {
389
390 my( $self, $tmpl_ref, $aref ) = @_ ;
391
392# render this $tmpl_ref for each element of the aref and join them
393
394 my $rendered ;
395
396#print "AREF: ", Dumper $aref ;
397
398 $rendered .= ${$self->_render_chunk( $tmpl_ref, $_ )} for @{$aref} ;
399
400 return \$rendered ;
401}
402
403sub _render_code {
404
405 my( $self, $tmpl_ref, $cref ) = @_ ;
406
407 my $rendered = $cref->( $tmpl_ref ) ;
408
409 die <<DIE if ref $rendered ne 'SCALAR' ;
410data callback to code didn't return a scalar or scalar reference
411DIE
412
413 return $rendered ;
414}
415
416sub add_templates {
417
418 my( $self, $tmpls ) = @_ ;
419
420#print Dumper $tmpls ;
421 return unless defined $tmpls ;
422
423 ref $tmpls eq 'HASH' or croak "templates argument is not a hash ref" ;
59d7205c 424
425# copy all the templates from the arg hash and force the values to be
426# scalar refs
e374d8da 427
59d7205c 428 @{ $self->{tmpl_cache}}{ keys %{$tmpls} } =
e374d8da 429 map ref $_ eq 'SCALAR' ? \"${$_}" : \"$_", values %{$tmpls} ;
430
59d7205c 431#print Dumper $self->{tmpl_cache} ;
e374d8da 432
433 return ;
434}
435
436sub delete_templates {
437
438 my( $self, @names ) = @_ ;
439
060b866c 440# delete all the cached stuff or just the names passed in
441
59d7205c 442 @names = keys %{$self->{tmpl_cache}} unless @names ;
e374d8da 443
060b866c 444# clear out all the caches
445# TODO: reorg these into a hash per name
446
59d7205c 447 delete @{$self->{tmpl_cache}}{ @names } ;
060b866c 448 delete @{$self->{compiled_cache}}{ @names } ;
449 delete @{$self->{source_cache}}{ @names } ;
450
451# also remove where we found it to force a fresh search
e374d8da 452
453 delete @{$self->{template_paths}}{ @names } ;
454
455 return ;
456}
457
458sub _get_template {
459
460 my( $self, $tmpl_name ) = @_ ;
461
462#print "INC $tmpl_name\n" ;
463
59d7205c 464 my $tmpls = $self->{tmpl_cache} ;
e374d8da 465
466# get the template from the cache and send it back if it was found there
467
468 my $template = $tmpls->{ $tmpl_name } ;
469 return $template if $template ;
470
471# not found, so find, slurp in and cache the template
472
473 $template = $self->_find_template( $tmpl_name ) ;
474 $tmpls->{ $tmpl_name } = $template ;
475
476 return $template ;
477}
478
479sub _find_template {
480
481 my( $self, $tmpl_name ) = @_ ;
482
483 foreach my $dir ( @{$self->{include_paths}} ) {
484
485 my $tmpl_path = "$dir/$tmpl_name.tmpl" ;
486
487#print "PATH: $tmpl_path\n" ;
488 next unless -r $tmpl_path ;
489
490# cache the path to this template
491
492 $self->{template_paths}{$tmpl_name} = $tmpl_path ;
493
494# slurp in the template file and return it as a scalar ref
495
496 return scalar read_file( $tmpl_path, scalar_ref => 1 ) ;
497 }
498
499 die <<DIE ;
500can't find template '$tmpl_name' in '@{$self->{include_paths}}'
501DIE
502
503}
504
5051; # End of Template::Simple
506
507__END__
508
509=head1 NAME
510
511Template::Simple - A simple and fast template module
512
513=head1 VERSION
514
515Version 0.03
516
517=head1 SYNOPSIS
518
519 use Template::Simple;
520
521 my $tmpl = Template::Simple->new();
522
523 my $template = <<TMPL ;
524[%INCLUDE header%]
525[%START row%]
526 [%first%] - [%second%]
527[%END row%]
528[%INCLUDE footer%]
529TMPL
530
531 my $data = {
532 header => {
533 date => 'Jan 1, 2008',
534 author => 'Me, myself and I',
535 },
536 row => [
537 {
538 first => 'row 1 value 1',
539 second => 'row 1 value 2',
540 },
541 {
542 first => 'row 2 value 1',
543 second => 'row 2 value 2',
544 },
545 ],
546 footer => {
547 modified => 'Aug 31, 2006',
548 },
549 } ;
550
551 my $rendered = $tmpl->render( $template, $data ) ;
552
553=head1 DESCRIPTION
554
555Template::Simple has these goals:
556
557=over 4
558
559=item * Support most common template operations
560
561It can recursively include other templates, replace tokens (scalars),
562recursively render nested chunks of text and render lists. By using
563simple idioms you can get conditional renderings.
564
565=item * Complete isolation of template from program code
566
567This is very important as template design can be done by different
568people than the program logic. It is rare that one person is well
569skilled in both template design and also programming.
570
571=item * Very simple template markup (only 4 markups)
572
573The only markups are C<INCLUDE>, C<START>, C<END> and C<token>. See
574MARKUP for more.
575
576=item * Easy to follow rendering rules
577
578Rendering of templates and chunks is driven from a data tree. The type
579of the data element used in an rendering controls how the rendering
580happens. The data element can be a scalar or scalar reference or an
581array, hash or code reference.
582
583=item * Efficient template rendering
584
585Rendering is very simple and uses Perl's regular expressions
586efficiently. Because the markup is so simple less processing is needed
587than many other templaters. Precompiling templates is not supported
588yet but that optimization is on the TODO list.
589
590=item * Easy user extensions
591
592User code can be called during an rendering so you can do custom
593renderings and plugins. Closures can be used so the code can have its
594own private data for use in rendering its template chunk.
595
596=back
597
598=head2 new()
599
600You create a Template::Simple by calling the class method new:
601
602 my $tmpl = Template::Simple->new() ;
603
604All the arguments to C<new()> are key/value options that change how
605the object will do renderings.
606
607=over 4
608
609=item pre_delim
610
611This option sets the string or regex that is the starting delimiter
612for all markups. You can use a plain string or a qr// but you need to
613escape (with \Q or \) any regex metachars if you want them to be plain
614chars. The default is qr/\[%/.
615
616 my $tmpl = Template::Simple->new(
617 pre_delim => '<%',
618 );
619
620 my $rendered = $tmpl->render( '<%FOO%]', 'bar' ) ;
621
622=item post_delim
623
624This option sets the string or regex that is the ending delimiter
625for all markups. You can use a plain string or a qr// but you need to
626escape (with \Q or \) any regex metachars if you want them to be plain
627chars. The default is qr/%]/.
628
629 my $tmpl = Template::Simple->new(
630 post_delim => '%>',
631 );
632
633 my $rendered = $tmpl->render( '[%FOO%>', 'bar' ) ;
634
635=item greedy_chunk
636
637This boolean option will cause the regex that grabs a chunk of text
638between the C<START/END> markups to become greedy (.+). The default is
639a not-greedy grab of the chunk text. (UNTESTED)
640
641=item templates
642
643This option lets you load templates directly into the cache of the
644Template::Simple object. This cache will be searched by the C<INCLUDE>
645markup which will be replaced by the template if found. The option
646value is a hash reference which has template names (the name in the
647C<INCLUDE> markup) for keys and their template text as their
648values. You can delete or clear templates from the object cache with
649the C<delete_template> method.
650
651
652 my $tmpl = Template::Simple->new(
653 templates => {
654
655 foo => <<FOO,
656[%baz%] is a [%quux%]
657FOO
658 bar => <<BAR,
659[%user%] is not a [%fool%]
660BAR
661 },
662 );
663
664 my $template = <<TMPL ;
665[%INCLUDE foo %]
666TMPL
667
668 my $rendered = $tmpl->render(
669 $template,
670 {
671 baz => 'blue',
672 quux => 'color,
673 }
674 ) ;
675
676=item include_paths
677
678Template::Simple can also load C<INCLUDE> templates from files. This
679option lets you set the directory paths to search for those
680files. Note that the template name in the C<INCLUDE> markup has the
681.tmpl suffix appended to it when searched for in one of these
682paths. The loaded file is cached inside the Template::Simple object
683along with any loaded by the C<templates> option.
684
685=back
686
687=head1 METHODS
688
689=head2 render
690
691This method is passed a template and a data tree and it renders it and
692returns a reference to the resulting string. The template argument can
693be a scalar or a scalar reference. The data tree argument can be any
694value allowed by Template::Simple when rendering a template. It can
695also be a blessed reference (Perl object) since
696C<Scalar::Util::reftype> is used instead of C<ref> to determine the
697data type.
698
699Note that the author recommends against passing in an object as this
700breaks encapsulation and forces your object to be (most likely) a
701hash. It would be better to create a simple method that copies the
702object contents to a hash reference and pass that. But current
703templaters allow passing in objects so that is supported here as well.
704
705 my $rendered = $tmpl->render( $template, $data ) ;
706
707=head2 add_templates
708
709This method adds templates to the object cache. It takes a list of template names and texts just like the C<templates> constructor option.
710
711 $tmpl->add_templates(
712 {
713 foo => \$foo_template,
714 bar => '[%include bar%]',
715 }
716 ) ;
717
718=head2 delete_templates
719
720This method takes a list of template names and will delete them from
721the template cache in the object. If you pass in an empty list then
722all the templates will be deleted. This can be used when you know a
723template file has been updated and you want to get it loaded back into
724the cache. Note that you can delete templates that were loaded
725directly (via the C<templates> constructor option or the
726C<add_templates> method) or loaded from a file.
727
728 # this deletes only the foo and bar templates from the object cache
729
730 $tmpl->delete_templates( qw( foo bar ) ;
731
732 # this deletes all of templates from the object cache
733
734 $tmpl->delete_templates() ;
735
736=head2 get_dependencies
737
738This method render the only C<INCLUDE> markups of a template and it
739returns a list of the file paths that were found and loaded. It is
740meant to be used to build up a dependency list of included templates
741for a main template. Typically this can be called from a script (see
742TODO) that will do this for a set of main templates and will generate
743Makefile dependencies for them. Then you can regenerate rendered
744templates only when any of their included templates have changed. It
745takes a single argument of a template.
746
747UNKNOWN: will this require a clearing of the cache or will it do the
748right thing on its own? or will it use the file path cache?
749
750 my @dependencies =
751 $tmpl->get_dependencies( '[%INCLUDE top_level%]' );
752
753=head1 MARKUP
754
755All the markups in Template::Simple use the same delimiters which are
756C<[%> and C<%]>. You can change the delimiters with the C<pre_delim>
757and C<post_delim> options in the C<new()> constructor.
758
759=head2 Tokens
760
761A token is a single markup with a C<\w+> Perl word inside. The token
762can have optional whitespace before and after it. A token is replaced
763by a value looked up in a hash with the token as the key. The hash
764lookup keeps the same case as parsed from the token markup.
765
766 [% foo %] [%BAR%]
767
768Those will be replaced by C<$href->{foo}> and C<$href->{BAR}> assuming
769C<$href> is the current data for this rendering. Tokens are only
770parsed out during hash data rendering so see Hash Data for more.
771
772=head2 Chunks
773
774Chunks are regions of text in a template that are marked off with a
775start and end markers with the same name. A chunk start marker is
776C<[%START name%]> and the end marker for that chunk is C<[%END
777name%]>. C<name> is a C<\w+> Perl word which is the name of this
778chunk. The whitespace between C<START/END> and C<name> is required and
779there is optional whitespace before C<START/END> and after the
780C<name>. C<START/END> are case insensitive but the C<name>'s case is
781kept. C<name> must match in the C<START/END> pair and it used as a key
782in a hash data rendering. Chunks are the primary way to markup
783templates for structures (sets of tokens), nesting (hashes of hashes),
784repeats (array references) and callbacks to user code. Chunks are only
785parsed out during hash data rendering so see Hash Data for more.
786
787The body of text between the C<START/END> markups is grabbed with a
788C<.+?> regular expression with the /s option enabled so it will match
789all characters. By default it will be a non-greedy grab but you can
790change that in the constructor by enabling the C<greedy_chunk> option.
791
792 [%Start FOO%]
793 [% START bar %]
794 [% field %]
795 [% end bar %]
796 [%End FOO%]
797
798=head2 Includes
799
800=head1 RENDERING RULES
801
802Template::Simple has a short list of rendering rules and they are easy
803to understand. There are two types of renderings, include rendering
804and chunk rendering. In the C<render> method, the template is an
805unnamed top level chunk of text and it first gets its C<INCLUDE>
806markups rendered. The text then undergoes a chunk rendering and a
807scalar reference to that rendered template is returned to the caller.
808
809=head2 Include Rendering
810
811Include rendering is performed one time on a top level template. When
812it is done the template is ready for chunk rendering. Any markup of
813the form C<[%INCLUDE name]%> will be replaced by the text found in the
814template C<name>. The template name is looked up in the object's
815template cache and if it is found there its text is used as the
816replacement.
817
818If a template is not found in the cache, it will be searched for in
819the list of directories in the C<include_paths> option. The file name
820will be a directory in that list appended with the template name and
821the C<.tmpl> suffix. The first template file found will be read in and
822stored in the cache. Its path is also saved and those will be returned
823in the C<get_dependencies> method. See the C<add_templates> and
824C<delete_templates> methods and the C<include_paths> option.
825
826Rendered include text can contain more C<INCLUDE> markups and they
827will also be rendered. The include rendering phase ends where there
828are no more C<INCLUDE> found.
829
830=head2 Chunk Rendering
831
832A chunk is the text found between C<START> and C<END> markups and it
833gets its named from the C<START> markup. The top level template is
834considered an unamed chunk and also gets chunk rendered.
835
836The data for a chunk determines how it will be rendered. The data can
837be a scalar or scalar reference or an array, hash or code
838reference. Since chunks can contain nested chunks, rendering will
839recurse down the data tree as it renders the chunks. Each of these
840renderings are explained below. Also see the IDIOMS and BEST PRACTICES
841section for examples and used of these renderings.
842
843=head2 Scalar Data Rendering
844
845If the current data for a chunk is a scalar or scalar reference, the
846chunk's text in the templated is replaced by the scalar's value. This
847can be used to overwrite one default section of text with from the
848data tree.
849
850=head2 Code Data Rendering
851
852If the current data for a chunk is a code reference (also called
853anonymous sub) then the code reference is called and it is passed a
854scalar reference to the that chunk's text. The code must return a
855scalar or a scalar reference and its value replaces the chunk's text
856in the template. If the code returns any other type of data it is a
857fatal error. Code rendering is how you can do custom renderings and
858plugins. A key idiom is to use closures as the data in code renderings
859and keep the required outside data in the closure.
860
861=head2 Array Data Rendering
862
863If the current data for a chunk is an array reference do a full chunk
864rendering for each value in the array. It will replace the original
865chunk text with the joined list of rendered chunks. This is how you do
866repeated sections in Template::Simple and why there is no need for any
867loop markups. Note that this means that rendering a chunk with $data
868and [ $data ] will do the exact same thing. A value of an empty array
869C<[]> will cause the chunk to be replaced by the empty string.
870
871=head2 Hash Data Rendering
872
873If the current data for a chunk is a hash reference then two phases of
874rendering happen, nested chunk rendering and token rendering. First
875nested chunks are parsed of of this chunk along with their names. Each
876parsed out chunk is rendered based on the value in the current hash
877with the nested chunk's name as the key.
878
879If a value is not found (undefined), then the nested chunk is replaced
880by the empty string. Otherwise the nested chunk is rendered according
881to the type of its data (see chunk rendering) and it is replaced by
882the rendered text.
883
884Chunk name and token lookup in the hash data is case sensitive (see
885the TODO for cased lookups).
886
887Note that to keep a plain text chunk or to just have the all of its
888markups (chunks and tokens) be deleted just pass in an empty hash
889reference C<{}> as the data for the chunk. It will be rendered but all
890markups will be replaced by the empty string.
891
892=head2 Token Rendering
893
894The second phase is token rendering. Markups of the form [%token%] are
895replaced by the value of the hash element with the token as the
896key. If a token's value is not defined it is replaced by the empty
897string. This means if a token key is missing in the hash or its value
898is undefined or its value is the empty string, the [%token%] markup
899will be deleted in the rendering.
900
901=head1 IDIOMS and BEST PRACTICES
902
903With all template systems there are better ways to do things and
904Template::Simple is no different. This section will show some ways to
905handle typical template needs while using only the 4 markups in this
906module.
907
908=head2 Conditionals
909
910This conditional idiom can be when building a fresh data tree or
911modifying an existing one.
912
913 $href->{$chunk_name} = $keep_chunk ? {} : '' ;
914
915If you are building a fresh data tree you can use this idiom to do a
916conditional chunk:
917
918 $href->{$chunk_name} = {} if $keep_chunk ;
919
920To handle an if/else conditional use two chunks, with the else chunk's
921name prefixed with NOT_ (or use any name munging you want). Then you
922set the data for either the true chunk (just the plain name) or the
923false trunk with the NOT_ name. You can use a different name for the
924else chunk if you want but keeping the names of the if/else chunks
925related is a good idea. Here are two ways to set the if/else data. The
926first one uses the same data for both the if and else chunks and the
927second one uses different data so the it uses the full if/else code
928for that.
929
930 $href->{ ($boolean ? '' : 'NOT_') . $chunk_name} = $data
931
932 if ( $boolean ) {
933 $href->{ $chunk_name} = $true_data ;
934 else {
935 $href->{ "NOT_$chunk_name" } = $false_data ;
936 }
937
938NOTE TO ALPHA USERS: i am also thinking that a non-existing key or
939undefined hash value should leave the chunk as is. then you would need
940to explicitly replace a chunk with the empty string if you wanted it
941deleted. It does affect the list of styles idiom. Any thoughts on
942this change of behavior? Since this hasn't been released it is the
943time to decide this.
944
945=head2 Chunked Includes
946
947One of the benefits of using include templates is the ability to share
948and reuse existing work. But if an included template has a top level
949named chunk, then that name would also be the same everywhere where
950this template is included. If a template included another template in
951multiple places, its data tree would use the same name for each and
952not allow unique data to be rendered for each include. A better way is
953to have the current template wrap an include markup in a named chunk
954markup. Then the data tree could use unique names for each included
955template. Here is how it would look:
956
957 [%START foo_prime%][%INCLUDE foo%][%START foo_prime%]
958 random noise
959 [%START foo_second%][%INCLUDE foo%][%START foo_second%]
960
961See the TODO section for some ideas on how to make this even more high level.
962
963=head2 Repeated Sections
964
965If you looked at the markup of Template::Simple you have noticed that
966there is no loop or repeat construct. That is because there is no need
967for one. Any chunk can be rendered in a loop just by having its
968rendering data be an anonymous array. The renderer will loop over each
969element of the array and do a fresh rendering of the chunk with this
970data. A join (on '') of the list of renderings replaces the original
971chunk and you have a repeated chunk.
972
973=head2 A List of Mixed Styles
974
975One formating style is to have a list of sections each which can have
976its own style or content. Template::Simple can do this very easily
977with just a 2 level nested chunk and an array of data for
978rendering. The outer chunk includes (or contains) each of the desired
979styles in any order. It looks like this:
980
981 [%START para_styles%]
982 [%START main_style%]
983 [%INCLUDE para_style_main%]
984 [%END main_style%]
985 [%START sub_style%]
986 [%INCLUDE para_style_sub%]
987 [%END sub_style%]
988 [%START footer_style%]
989 [%INCLUDE para_style_footer%]
990 [%END footer_style%]
991 [%END para_styles%]
992
993The other part to make this work is in the data tree. The data for
994para_styles should be a list of hashes. Each hash contains the data
995for one pargraph style which is keyed by the style's chunk name. Since
996the other styles's chunk names are not hash they are deleted. Only the
997style which has its name as a key in the hash is rendered. The data
998tree would look something like this:
999
1000 [
1001 {
1002 main_style => $main_data,
1003 },
1004 {
1005 sub_style => $sub_data,
1006 },
1007 {
1008 sub_style => $other_sub_data,
1009 },
1010 {
1011 footer_style => $footer_data,
1012 },
1013 ]
1014
1015=head1 TESTS
1016
1017The test scripts use a common test driver module in t/common.pl. It is
1018passed a list of hashes, each of which has the data for one test. A
1019test can create a ne Template::Simple object or use the one from the
1020previous test. The template source, the data tree and the expected
1021results are also important keys. See the test scripts for examples of
1022how to write tests using this common driver.
1023
1024=over 4
1025
1026=item name
1027
1028This is the name of the test and is used by Test::More
1029
1030=item opts
1031
1032This is a hash ref of the options passed to the Template::Simple
1033constructor. The object is not built if the C<keep_obj> key is set.
1034
1035=item keep_obj
1036
1037If set, this will make this test keep the Template::Simple object from
1038the previous test and not build a new one.
1039
1040=item template
1041
1042This is the template to render for this test. If not set, the test
1043driver will use the template from the previous test. This is useful to
1044run a series of test variants with the same template.
1045
1046=item data
1047
1048This is the data tree for the rendering of the template.
1049
1050=item expected
1051
1052This is the text that is expected after the rendering.
1053
1054=item skip
1055
1056If set, this test is skipped.
1057
1058=back
1059
1060=head1 TODO
1061
1062Even though this template system is simple, that doesn't mean it can't
1063be extended in many ways. Here are some features and designs that
1064would be good extensions which add useful functionality without adding
1065too much complexity.
1066
1067=head2 Compiled Templates
1068
1069A commonly performed optimization in template modules is to precompile
1070(really preparse) templates into a internal form that will render
1071faster. Precompiling is slower than rendering from the original
1072template which means you won't want to do it for each rendering. This
1073means it has a downside that you lose out when you want to render
1074using templates which change often. Template::Simple makes it very
1075easy to precompile as it already has the regexes to parse out the
1076markup. So instead of calling subs to do actual rendering, a
1077precompiler would call subs to generate a compiled rendering tree.
1078The rendering tree can then be run or processes with rendering data
1079passed to it. You can think of a precompiled template as having all
1080the nested chunks be replaced by nested code that does the same
1081rendering. It can still do the dynamic rendering of the data but it
1082saves the time of parsing the template souice. There are three
1083possible internal formats for the precompiled template:
1084
1085=over 4
1086
1087=item Source code
1088
1089This precompiler will generate source code that can be stored and/or
1090eval'ed. The eval'ed top level sub can then be called and passed the
1091rendering data.
1092
1093=item Closure call tree
1094
1095The internal format can be a nested set of closures. Each closure would contain
1096private data such as fixed text parts of the original template, lists
1097of other closures to run, etc. It is trivial to write a basic closure
1098generator which will make build this tree a simple task.
1099
1100=item Code ref call tree
1101
1102This format is a Perl data tree where the nodes have a code reference
1103and its args (which can be nested instances of the same
1104nodes). Instead of executing this directly, you will need a small
1105interpreter to execute all the code refs as it runs through the tree.
1106
1107This would make for a challenging project to any intermediate Perl
1108hacker. It just involves knowing recursion, data trees and code refs.
1109Contact me if you are interested in doing this.
1110
1111=back
1112
1113=head2 Cased Hash Lookups
1114
1115One possible option is to allow hash renderings to always use upper or
1116lower cased keys in their lookups.
1117
1118=head2 Render tokens before includes and chunks
1119
1120Currently tokens are rendered after includes and chunks. If tokens
1121were rendered in a pass before the others, the include and chunk names
1122could be dynamically set. This would make it harder to precompile
1123templates as too much would be dynamic, i.e. you won't know what the
1124fixed text to parse out is since anything can be included at render
1125time. But the extra flexibility of changing the include and chunk
1126names would be interesting. It could be done easily and enabled by an
1127option.
1128
1129=head2 Plugins
1130
1131There are two different potential areas in Template::Simple that could
1132use plugins. The first is with the rendering of chunkas and
1133dispatching based on the data type. This dispatch table can easily be
1134replaced by loaded modules which offer a different way to
1135render. These include the precompiled renderers mentioned above. The
1136other area is with code references as the data type. By defining a
1137closure (or a closure making) API you can create different code refs
1138for the rendering data. The range of plugins is endless some of the
1139major template modules have noticed. One idea is to make a closure
1140which contains a different Template::Simple object than the current
1141one. This will allow rendering of a nested chunk with different rules
1142than the current chunk being rendered.
1143
1144=head2 Data Escaping
1145
1146Some templaters have options to properly escape data for some types of
1147text files such as html. this can be done with some variant of the
1148_render_hash routine which also does the scalar rendering (which is
1149where data is rendered). The rendering scalars code could be factored
1150out into a set of subs one of which is used based on any escaping
1151needs.
1152
1153=head2 Data Tree is an Object
1154
1155This is a concept I don't like but it was requested so it goes into
1156the TODO file. Currently C<render> can only be passed a regular
1157(unblessed) ref (or a scalar) for its data tree. Passing in an object
1158would break encapsulation and force the object layout to be a hash
1159tree that matches the layout of the template. I doubt that most
1160objects will want to be organized to match a template. I have two
1161ideas, one is that you add a method to that object that builds up a
1162proper (unblessed) data tree to pass to C<render>. The other is by
1163subclassing C<Template::Simple> and overriding C<render> with a sub
1164that does take an object hash and it can unbless it or build a proper
1165data tree and then call C<render> in SUPER::. A quick solution is to
1166use C<reftype> (from Scalar::Utils) instead of C<ref> to allow object
1167hashes to be passed in.
1168
1169=head2 Includes and Closure Synergy
1170
1171By pairing up an include template along with code that can generate
1172the appropriate data tree for its rendering, you can create a higher
1173level template framework (the synergy). Additional code can be
1174associated with them that will handle input processing and
1175verification for the templates (e.g. web forms) that need it. A key to
1176this will be making all the closures for the data tree. This can be
1177greatly simplified by using a closure maker sub that can create all
1178the required closures.
1179
1180=head2 Metafields and UI Generation
1181
1182Taking the synergy up to a much higher level is the concept of meta
1183knowledge of fields which can generate templates, output processing
1184(data tree generation), input processing, DB backing and more. If you
1185want to discuss such grandiose wacky application schemes in a long
1186rambling mind bending conversation, please contact me.
1187
1188=head2 More Examples and Idioms
1189
1190As I convert several scripts over to this module (they all used the
1191hack version), I will add them to an examples section or possibly put
1192them in another (pod only) module. Similarly the Idioms section needs
1193rendering and could be also put into a pod module. One goal requested
1194by an early alpha tester is to keep the primary docs as simple as the
1195markup itself. This means moving all the extra stuff (and plenty of
1196that) into other pod modules. All the pod modules would be in the same
1197cpan tarball so you get all the docs and examples when you install
1198this.
1199
1200=head1 AUTHOR
1201
1202Uri Guttman, C<< <uri at sysarch.com> >>
1203
1204=head1 BUGS
1205
1206Please report any bugs or feature requests to
1207C<bug-template-simple at rt.cpan.org>, or through the web interface at
1208L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Template-Simple>.
1209I will be notified, and then you'll automatically be notified of progress on
1210your bug as I make changes.
1211
1212=head1 SUPPORT
1213
1214You can find documentation for this module with the perldoc command.
1215
1216 perldoc Template::Simple
1217
1218You can also look for information at:
1219
1220=over 4
1221
1222=item * RT: CPAN's request tracker
1223
1224L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Template-Simple>
1225
1226=item * Search CPAN
1227
1228L<http://search.cpan.org/dist/Template-Simple>
1229
1230=back
1231
1232=head1 ACKNOWLEDGEMENTS
1233
1234I wish to thank Turbo10 for their support in developing this module.
1235
1236=head1 COPYRIGHT & LICENSE
1237
1238Copyright 2006 Uri Guttman, all rights reserved.
1239
1240This program is free software; you can redistribute it and/or modify it
1241under the same terms as Perl itself.
1242
1243=cut
1244
1245
1246find templates and tests
1247
1248deep nesting tests
1249
1250greedy tests
1251
1252methods pod
1253
1254delete_templates test
1255
1256pod cleanup
1257
1258fine edit
1259
1260more tests
1261
1262slurp dependency in makefile.pl
1263