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