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