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