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