1 package Template::Simple;
8 use Scalar::Util qw( reftype ) ;
12 our $VERSION = '0.03';
17 post_delim => qr/%\]/,
21 include_paths => [ qw( templates ) ],
26 my( $class, %opts ) = @_ ;
28 my $self = bless {}, $class ;
30 # get all the options or defaults into the object
32 while( my( $name, $default ) = each %opt_defaults ) {
34 $self->{$name} = defined( $opts{$name} ) ?
35 $opts{$name} : $default ;
38 # make up the regexes to parse the markup from templates
40 # this matches scalar markups and grabs the name
42 $self->{scalar_re} = qr{
44 \s* # optional leading whitespace
45 (\w+?) # grab scalar name
46 \s* # optional trailing whitespace
48 }xi ; # case insensitive
50 #print "RE <$self->{scalar_re}>\n" ;
52 # this grabs the body of a chunk in either greedy or non-greedy modes
54 my $chunk_body = $self->{greedy_chunk} ? qr/.+/s : qr/.+?/s ;
56 # this matches a marked chunk and grabs its name and text body
58 $self->{chunk_re} = qr{
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
66 ($chunk_body) # grab the chunk body
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
74 }xi ; # case insensitive
76 #print "RE <$self->{chunk_re}>\n" ;
78 # this matches a include markup and grabs its template name
80 $self->{include_re} = qr{
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
88 }xi ; # case insensitive
90 # load in any templates
92 $self->add_templates( $opts{templates} ) ;
99 my( $self, $template_name ) = @_ ;
101 my $tmpl_ref = eval {
102 $self->_get_template( $template_name ) ;
105 croak "Template::Simple $@" if $@ ;
107 # compile a copy of the template as it will be destroyed
109 my $code_body = $self->_compile_chunk( '', "${$tmpl_ref}", "\t" ) ;
111 my $source = <<CODE ;
126 my $code_ref = eval $source ;
130 $self->{compiled_cache}{$template_name} = $code_ref ;
131 $self->{source_cache}{$template_name} = $source ;
136 my( $self, $chunk_name, $template, $indent ) = @_ ;
138 return '' unless length $template ;
140 # generate a lookup in data for this chunk name (unless it is the top
141 # level). this descends down the data tree during rendering
143 my $data_init = $chunk_name ? "\$data->{$chunk_name}" : '$data' ;
146 ${indent}my \@data = $data_init ;
147 ${indent}while( \@data ) {
149 ${indent} my \$data = shift \@data ;
150 ${indent} if ( ref \$data eq 'ARRAY' ) {
151 ${indent} push \@data, \@{\$data} ;
159 # loop all nested chunks and the text separating them
161 while( my( $parsed_name, $parsed_body ) =
162 $template =~ m{$self->{chunk_re}} ) {
164 # get the pre-match text and compile its scalars and text. append to the code
166 $code .= $self->_compile_scalars(
167 substr( $template, 0, $-[0] ), $indent ) ;
169 # print "OFF: $-[0] $+[0]\n" ;
170 # print "PRE: [", substr( $template, 0, $-[0] ), "]\n\n" ;
171 # print "CHUNK: [$1] BODY [$2]\n\n" ;
172 # print "TRUNC: [", substr( $template, 0, $+[0] ), "]\n\n" ;
173 # print "LEFT: [$template]\n\n" ;
175 # compile the nested chunk and append to the code
177 $code .= $self->_compile_chunk(
178 $parsed_name, $parsed_body, $indent
181 # chop off the pre-match and the chunk
183 substr( $template, 0, $+[0], '' ) ;
186 # compile trailing text for scalars and append to the code
188 $code .= $self->_compile_scalars( $template, $indent ) ;
192 # now we end the loop for this chunk
200 sub _compile_scalars {
202 my( $self, $template, $indent ) = @_ ;
204 # if the template is empty return no parts
206 return '' unless length $template ;
210 while( $template =~ m{$self->{scalar_re}}g ) {
212 # get the pre-match text before the scalar markup and generate code to
216 dump_text( substr( $template, 0, $-[0] ) ),
220 # truncate the matched text so the next match starts at begining of string
222 substr( $template, 0, $+[0], '' ) ;
225 # keep any trailing text part
227 push @parts, dump_text( $template ) ;
229 my $parts_code = join( "\n$indent.\n$indent", @parts ) ;
233 ${indent}\$out .= ref \$data ne 'HASH' ? \$data :
234 ${indent}$parts_code ;
244 return unless length $text ;
246 local( $Data::Dumper::Useqq ) = 1 ;
248 my $dumped = Dumper $text ;
250 $dumped =~ s/^[^"]+// ;
251 $dumped =~ s/;\n$// ;
258 my( $self, $template_name ) = @_ ;
260 return $self->{source_cache}{$template_name} ;
265 my( $self, $template_name, $data ) = @_ ;
267 my $tmpl_ref = ref $template_name eq 'SCALAR' ? $template_name : '' ;
269 unless( $tmpl_ref ) {
271 # render with cached code and return if we precompiled this template
273 if ( my $compiled = $self->{compiled_cache}{$template_name} ) {
275 return $compiled->($data) ;
278 # not compiled so get this template by name
280 $tmpl_ref ||= eval{ $self->_get_template($template_name) } ;
282 # we couldn't find this template name so assume it is the template text
284 $tmpl_ref ||= \$template_name ;
287 my $rendered = $self->_render_includes( $tmpl_ref ) ;
289 #print "INC EXP <$rendered>\n" ;
292 $self->_render_chunk( $rendered, $data ) ;
295 croak "Template::Simple $@" if $@ ;
300 sub _render_includes {
302 my( $self, $tmpl_ref ) = @_ ;
304 # make a copy of the initial template so we can render it.
306 my $rendered = ${$tmpl_ref} ;
308 # loop until we can render no more include markups
311 s{$self->{include_re}}
312 { ${ $self->_get_template($1) }
320 HASH => \&_render_hash,
321 ARRAY => \&_render_array,
322 CODE => \&_render_code,
323 # if no ref then data is a scalar so replace the template with just the data
324 '' => sub { \$_[2] },
330 my( $self, $tmpl_ref, $data ) = @_ ;
332 #print "T ref [$tmpl_ref] [$$tmpl_ref]\n" ;
333 #print "CHUNK ref [$tmpl_ref] TMPL\n<$$tmpl_ref>\n" ;
335 #print Dumper $data ;
337 return \'' unless defined $data ;
339 # now render this chunk based on the type of data
341 my $renderer = $renderers{reftype $data || ''} ;
343 #print "EXP $renderer\nREF ", reftype $data, "\n" ;
345 die "unknown template data type '$data'\n" unless defined $renderer ;
347 return $self->$renderer( $tmpl_ref, $data ) ;
352 my( $self, $tmpl_ref, $href ) = @_ ;
354 return $tmpl_ref unless keys %{$href} ;
356 # we need a local copy of the template to render
358 my $rendered = ${$tmpl_ref} ;
361 # recursively render all top level chunks in this chunk
363 $rendered =~ s{$self->{chunk_re}}
365 # print "CHUNK $1\nBODY\n----\n<$2>\n\n------\n" ;
366 # print "CHUNK $1\nBODY\n----\n<$2>\n\n------\n" ;
367 # print "pre CHUNK [$`]\n" ;
368 ${ $self->_render_chunk( \"$2", $href->{$1} ) }
373 #print "HREF: ", Dumper $href ;
375 $rendered =~ s{$self->{scalar_re}}
377 # print "SCALAR $1 VAL $href->{$1}\n" ;
378 defined $href->{$1} ? $href->{$1} : ''
381 #print "HASH REND3\n<$rendered>\n" ;
388 my( $self, $tmpl_ref, $aref ) = @_ ;
390 # render this $tmpl_ref for each element of the aref and join them
394 #print "AREF: ", Dumper $aref ;
396 $rendered .= ${$self->_render_chunk( $tmpl_ref, $_ )} for @{$aref} ;
403 my( $self, $tmpl_ref, $cref ) = @_ ;
405 my $rendered = $cref->( $tmpl_ref ) ;
407 die <<DIE if ref $rendered ne 'SCALAR' ;
408 data callback to code didn't return a scalar or scalar reference
416 my( $self, $tmpls ) = @_ ;
418 #print Dumper $tmpls ;
419 return unless defined $tmpls ;
421 ref $tmpls eq 'HASH' or croak "templates argument is not a hash ref" ;
423 # copy all the templates from the arg hash and force the values to be
426 @{ $self->{tmpl_cache}}{ keys %{$tmpls} } =
427 map ref $_ eq 'SCALAR' ? \"${$_}" : \"$_", values %{$tmpls} ;
429 #print Dumper $self->{tmpl_cache} ;
434 sub delete_templates {
436 my( $self, @names ) = @_ ;
438 # delete all the cached stuff or just the names passed in
440 @names = keys %{$self->{tmpl_cache}} unless @names ;
442 # clear out all the caches
443 # TODO: reorg these into a hash per name
445 delete @{$self->{tmpl_cache}}{ @names } ;
446 delete @{$self->{compiled_cache}}{ @names } ;
447 delete @{$self->{source_cache}}{ @names } ;
449 # also remove where we found it to force a fresh search
451 delete @{$self->{template_paths}}{ @names } ;
458 my( $self, $tmpl_name ) = @_ ;
460 #print "INC $tmpl_name\n" ;
462 my $tmpls = $self->{tmpl_cache} ;
464 # get the template from the cache and send it back if it was found there
466 my $template = $tmpls->{ $tmpl_name } ;
467 return $template if $template ;
469 # not found, so find, slurp in and cache the template
471 $template = $self->_find_template( $tmpl_name ) ;
472 $tmpls->{ $tmpl_name } = $template ;
479 my( $self, $tmpl_name ) = @_ ;
481 foreach my $dir ( @{$self->{include_paths}} ) {
483 my $tmpl_path = "$dir/$tmpl_name.tmpl" ;
485 #print "PATH: $tmpl_path\n" ;
486 next unless -r $tmpl_path ;
488 # cache the path to this template
490 $self->{template_paths}{$tmpl_name} = $tmpl_path ;
492 # slurp in the template file and return it as a scalar ref
494 return scalar read_file( $tmpl_path, scalar_ref => 1 ) ;
498 can't find template '$tmpl_name' in '@{$self->{include_paths}}'
503 1; # End of Template::Simple
509 Template::Simple - A simple and fast template module
517 use Template::Simple;
519 my $tmpl = Template::Simple->new();
521 my $template = <<TMPL ;
524 [%first%] - [%second%]
531 date => 'Jan 1, 2008',
532 author => 'Me, myself and I',
536 first => 'row 1 value 1',
537 second => 'row 1 value 2',
540 first => 'row 2 value 1',
541 second => 'row 2 value 2',
545 modified => 'Aug 31, 2006',
549 my $rendered = $tmpl->render( $template, $data ) ;
553 Template::Simple has these goals:
557 =item * Support most common template operations
559 It can recursively include other templates, replace tokens (scalars),
560 recursively render nested chunks of text and render lists. By using
561 simple idioms you can get conditional renderings.
563 =item * Complete isolation of template from program code
565 This is very important as template design can be done by different
566 people than the program logic. It is rare that one person is well
567 skilled in both template design and also programming.
569 =item * Very simple template markup (only 4 markups)
571 The only markups are C<INCLUDE>, C<START>, C<END> and C<token>. See
574 =item * Easy to follow rendering rules
576 Rendering of templates and chunks is driven from a data tree. The type
577 of the data element used in an rendering controls how the rendering
578 happens. The data element can be a scalar or scalar reference or an
579 array, hash or code reference.
581 =item * Efficient template rendering
583 Rendering is very simple and uses Perl's regular expressions
584 efficiently. Because the markup is so simple less processing is needed
585 than many other templaters. Precompiling templates is not supported
586 yet but that optimization is on the TODO list.
588 =item * Easy user extensions
590 User code can be called during an rendering so you can do custom
591 renderings and plugins. Closures can be used so the code can have its
592 own private data for use in rendering its template chunk.
598 You create a Template::Simple by calling the class method new:
600 my $tmpl = Template::Simple->new() ;
602 All the arguments to C<new()> are key/value options that change how
603 the object will do renderings.
609 This option sets the string or regex that is the starting delimiter
610 for all markups. You can use a plain string or a qr// but you need to
611 escape (with \Q or \) any regex metachars if you want them to be plain
612 chars. The default is qr/\[%/.
614 my $tmpl = Template::Simple->new(
618 my $rendered = $tmpl->render( '<%FOO%]', 'bar' ) ;
622 This option sets the string or regex that is the ending delimiter
623 for all markups. You can use a plain string or a qr// but you need to
624 escape (with \Q or \) any regex metachars if you want them to be plain
625 chars. The default is qr/%]/.
627 my $tmpl = Template::Simple->new(
631 my $rendered = $tmpl->render( '[%FOO%>', 'bar' ) ;
635 This boolean option will cause the regex that grabs a chunk of text
636 between the C<START/END> markups to become greedy (.+). The default is
637 a not-greedy grab of the chunk text. (UNTESTED)
641 This option lets you load templates directly into the cache of the
642 Template::Simple object. This cache will be searched by the C<INCLUDE>
643 markup which will be replaced by the template if found. The option
644 value is a hash reference which has template names (the name in the
645 C<INCLUDE> markup) for keys and their template text as their
646 values. You can delete or clear templates from the object cache with
647 the C<delete_template> method.
650 my $tmpl = Template::Simple->new(
654 [%baz%] is a [%quux%]
657 [%user%] is not a [%fool%]
662 my $template = <<TMPL ;
666 my $rendered = $tmpl->render(
676 Template::Simple can also load C<INCLUDE> templates from files. This
677 option lets you set the directory paths to search for those
678 files. Note that the template name in the C<INCLUDE> markup has the
679 .tmpl suffix appended to it when searched for in one of these
680 paths. The loaded file is cached inside the Template::Simple object
681 along with any loaded by the C<templates> option.
689 This method is passed a template and a data tree and it renders it and
690 returns a reference to the resulting string. The template argument can
691 be a scalar or a scalar reference. The data tree argument can be any
692 value allowed by Template::Simple when rendering a template. It can
693 also be a blessed reference (Perl object) since
694 C<Scalar::Util::reftype> is used instead of C<ref> to determine the
697 Note that the author recommends against passing in an object as this
698 breaks encapsulation and forces your object to be (most likely) a
699 hash. It would be better to create a simple method that copies the
700 object contents to a hash reference and pass that. But current
701 templaters allow passing in objects so that is supported here as well.
703 my $rendered = $tmpl->render( $template, $data ) ;
707 This method adds templates to the object cache. It takes a list of template names and texts just like the C<templates> constructor option.
709 $tmpl->add_templates(
711 foo => \$foo_template,
712 bar => '[%include bar%]',
716 =head2 delete_templates
718 This method takes a list of template names and will delete them from
719 the template cache in the object. If you pass in an empty list then
720 all the templates will be deleted. This can be used when you know a
721 template file has been updated and you want to get it loaded back into
722 the cache. Note that you can delete templates that were loaded
723 directly (via the C<templates> constructor option or the
724 C<add_templates> method) or loaded from a file.
726 # this deletes only the foo and bar templates from the object cache
728 $tmpl->delete_templates( qw( foo bar ) ;
730 # this deletes all of templates from the object cache
732 $tmpl->delete_templates() ;
734 =head2 get_dependencies
736 This method render the only C<INCLUDE> markups of a template and it
737 returns a list of the file paths that were found and loaded. It is
738 meant to be used to build up a dependency list of included templates
739 for a main template. Typically this can be called from a script (see
740 TODO) that will do this for a set of main templates and will generate
741 Makefile dependencies for them. Then you can regenerate rendered
742 templates only when any of their included templates have changed. It
743 takes a single argument of a template.
745 UNKNOWN: will this require a clearing of the cache or will it do the
746 right thing on its own? or will it use the file path cache?
749 $tmpl->get_dependencies( '[%INCLUDE top_level%]' );
753 All the markups in Template::Simple use the same delimiters which are
754 C<[%> and C<%]>. You can change the delimiters with the C<pre_delim>
755 and C<post_delim> options in the C<new()> constructor.
759 A token is a single markup with a C<\w+> Perl word inside. The token
760 can have optional whitespace before and after it. A token is replaced
761 by a value looked up in a hash with the token as the key. The hash
762 lookup keeps the same case as parsed from the token markup.
766 Those will be replaced by C<$href->{foo}> and C<$href->{BAR}> assuming
767 C<$href> is the current data for this rendering. Tokens are only
768 parsed out during hash data rendering so see Hash Data for more.
772 Chunks are regions of text in a template that are marked off with a
773 start and end markers with the same name. A chunk start marker is
774 C<[%START name%]> and the end marker for that chunk is C<[%END
775 name%]>. C<name> is a C<\w+> Perl word which is the name of this
776 chunk. The whitespace between C<START/END> and C<name> is required and
777 there is optional whitespace before C<START/END> and after the
778 C<name>. C<START/END> are case insensitive but the C<name>'s case is
779 kept. C<name> must match in the C<START/END> pair and it used as a key
780 in a hash data rendering. Chunks are the primary way to markup
781 templates for structures (sets of tokens), nesting (hashes of hashes),
782 repeats (array references) and callbacks to user code. Chunks are only
783 parsed out during hash data rendering so see Hash Data for more.
785 The body of text between the C<START/END> markups is grabbed with a
786 C<.+?> regular expression with the /s option enabled so it will match
787 all characters. By default it will be a non-greedy grab but you can
788 change that in the constructor by enabling the C<greedy_chunk> option.
798 =head1 RENDERING RULES
800 Template::Simple has a short list of rendering rules and they are easy
801 to understand. There are two types of renderings, include rendering
802 and chunk rendering. In the C<render> method, the template is an
803 unnamed top level chunk of text and it first gets its C<INCLUDE>
804 markups rendered. The text then undergoes a chunk rendering and a
805 scalar reference to that rendered template is returned to the caller.
807 =head2 Include Rendering
809 Include rendering is performed one time on a top level template. When
810 it is done the template is ready for chunk rendering. Any markup of
811 the form C<[%INCLUDE name]%> will be replaced by the text found in the
812 template C<name>. The template name is looked up in the object's
813 template cache and if it is found there its text is used as the
816 If a template is not found in the cache, it will be searched for in
817 the list of directories in the C<include_paths> option. The file name
818 will be a directory in that list appended with the template name and
819 the C<.tmpl> suffix. The first template file found will be read in and
820 stored in the cache. Its path is also saved and those will be returned
821 in the C<get_dependencies> method. See the C<add_templates> and
822 C<delete_templates> methods and the C<include_paths> option.
824 Rendered include text can contain more C<INCLUDE> markups and they
825 will also be rendered. The include rendering phase ends where there
826 are no more C<INCLUDE> found.
828 =head2 Chunk Rendering
830 A chunk is the text found between C<START> and C<END> markups and it
831 gets its named from the C<START> markup. The top level template is
832 considered an unamed chunk and also gets chunk rendered.
834 The data for a chunk determines how it will be rendered. The data can
835 be a scalar or scalar reference or an array, hash or code
836 reference. Since chunks can contain nested chunks, rendering will
837 recurse down the data tree as it renders the chunks. Each of these
838 renderings are explained below. Also see the IDIOMS and BEST PRACTICES
839 section for examples and used of these renderings.
841 =head2 Scalar Data Rendering
843 If the current data for a chunk is a scalar or scalar reference, the
844 chunk's text in the templated is replaced by the scalar's value. This
845 can be used to overwrite one default section of text with from the
848 =head2 Code Data Rendering
850 If the current data for a chunk is a code reference (also called
851 anonymous sub) then the code reference is called and it is passed a
852 scalar reference to the that chunk's text. The code must return a
853 scalar or a scalar reference and its value replaces the chunk's text
854 in the template. If the code returns any other type of data it is a
855 fatal error. Code rendering is how you can do custom renderings and
856 plugins. A key idiom is to use closures as the data in code renderings
857 and keep the required outside data in the closure.
859 =head2 Array Data Rendering
861 If the current data for a chunk is an array reference do a full chunk
862 rendering for each value in the array. It will replace the original
863 chunk text with the joined list of rendered chunks. This is how you do
864 repeated sections in Template::Simple and why there is no need for any
865 loop markups. Note that this means that rendering a chunk with $data
866 and [ $data ] will do the exact same thing. A value of an empty array
867 C<[]> will cause the chunk to be replaced by the empty string.
869 =head2 Hash Data Rendering
871 If the current data for a chunk is a hash reference then two phases of
872 rendering happen, nested chunk rendering and token rendering. First
873 nested chunks are parsed of of this chunk along with their names. Each
874 parsed out chunk is rendered based on the value in the current hash
875 with the nested chunk's name as the key.
877 If a value is not found (undefined), then the nested chunk is replaced
878 by the empty string. Otherwise the nested chunk is rendered according
879 to the type of its data (see chunk rendering) and it is replaced by
882 Chunk name and token lookup in the hash data is case sensitive (see
883 the TODO for cased lookups).
885 Note that to keep a plain text chunk or to just have the all of its
886 markups (chunks and tokens) be deleted just pass in an empty hash
887 reference C<{}> as the data for the chunk. It will be rendered but all
888 markups will be replaced by the empty string.
890 =head2 Token Rendering
892 The second phase is token rendering. Markups of the form [%token%] are
893 replaced by the value of the hash element with the token as the
894 key. If a token's value is not defined it is replaced by the empty
895 string. This means if a token key is missing in the hash or its value
896 is undefined or its value is the empty string, the [%token%] markup
897 will be deleted in the rendering.
899 =head1 IDIOMS and BEST PRACTICES
901 With all template systems there are better ways to do things and
902 Template::Simple is no different. This section will show some ways to
903 handle typical template needs while using only the 4 markups in this
908 This conditional idiom can be when building a fresh data tree or
909 modifying an existing one.
911 $href->{$chunk_name} = $keep_chunk ? {} : '' ;
913 If you are building a fresh data tree you can use this idiom to do a
916 $href->{$chunk_name} = {} if $keep_chunk ;
918 To handle an if/else conditional use two chunks, with the else chunk's
919 name prefixed with NOT_ (or use any name munging you want). Then you
920 set the data for either the true chunk (just the plain name) or the
921 false trunk with the NOT_ name. You can use a different name for the
922 else chunk if you want but keeping the names of the if/else chunks
923 related is a good idea. Here are two ways to set the if/else data. The
924 first one uses the same data for both the if and else chunks and the
925 second one uses different data so the it uses the full if/else code
928 $href->{ ($boolean ? '' : 'NOT_') . $chunk_name} = $data
931 $href->{ $chunk_name} = $true_data ;
933 $href->{ "NOT_$chunk_name" } = $false_data ;
936 NOTE TO ALPHA USERS: i am also thinking that a non-existing key or
937 undefined hash value should leave the chunk as is. then you would need
938 to explicitly replace a chunk with the empty string if you wanted it
939 deleted. It does affect the list of styles idiom. Any thoughts on
940 this change of behavior? Since this hasn't been released it is the
943 =head2 Chunked Includes
945 One of the benefits of using include templates is the ability to share
946 and reuse existing work. But if an included template has a top level
947 named chunk, then that name would also be the same everywhere where
948 this template is included. If a template included another template in
949 multiple places, its data tree would use the same name for each and
950 not allow unique data to be rendered for each include. A better way is
951 to have the current template wrap an include markup in a named chunk
952 markup. Then the data tree could use unique names for each included
953 template. Here is how it would look:
955 [%START foo_prime%][%INCLUDE foo%][%START foo_prime%]
957 [%START foo_second%][%INCLUDE foo%][%START foo_second%]
959 See the TODO section for some ideas on how to make this even more high level.
961 =head2 Repeated Sections
963 If you looked at the markup of Template::Simple you have noticed that
964 there is no loop or repeat construct. That is because there is no need
965 for one. Any chunk can be rendered in a loop just by having its
966 rendering data be an anonymous array. The renderer will loop over each
967 element of the array and do a fresh rendering of the chunk with this
968 data. A join (on '') of the list of renderings replaces the original
969 chunk and you have a repeated chunk.
971 =head2 A List of Mixed Styles
973 One formating style is to have a list of sections each which can have
974 its own style or content. Template::Simple can do this very easily
975 with just a 2 level nested chunk and an array of data for
976 rendering. The outer chunk includes (or contains) each of the desired
977 styles in any order. It looks like this:
979 [%START para_styles%]
981 [%INCLUDE para_style_main%]
984 [%INCLUDE para_style_sub%]
986 [%START footer_style%]
987 [%INCLUDE para_style_footer%]
991 The other part to make this work is in the data tree. The data for
992 para_styles should be a list of hashes. Each hash contains the data
993 for one pargraph style which is keyed by the style's chunk name. Since
994 the other styles's chunk names are not hash they are deleted. Only the
995 style which has its name as a key in the hash is rendered. The data
996 tree would look something like this:
1000 main_style => $main_data,
1003 sub_style => $sub_data,
1006 sub_style => $other_sub_data,
1009 footer_style => $footer_data,
1015 The test scripts use a common test driver module in t/common.pl. It is
1016 passed a list of hashes, each of which has the data for one test. A
1017 test can create a ne Template::Simple object or use the one from the
1018 previous test. The template source, the data tree and the expected
1019 results are also important keys. See the test scripts for examples of
1020 how to write tests using this common driver.
1026 This is the name of the test and is used by Test::More
1030 This is a hash ref of the options passed to the Template::Simple
1031 constructor. The object is not built if the C<keep_obj> key is set.
1035 If set, this will make this test keep the Template::Simple object from
1036 the previous test and not build a new one.
1040 This is the template to render for this test. If not set, the test
1041 driver will use the template from the previous test. This is useful to
1042 run a series of test variants with the same template.
1046 This is the data tree for the rendering of the template.
1050 This is the text that is expected after the rendering.
1054 If set, this test is skipped.
1060 Even though this template system is simple, that doesn't mean it can't
1061 be extended in many ways. Here are some features and designs that
1062 would be good extensions which add useful functionality without adding
1063 too much complexity.
1065 =head2 Compiled Templates
1067 A commonly performed optimization in template modules is to precompile
1068 (really preparse) templates into a internal form that will render
1069 faster. Precompiling is slower than rendering from the original
1070 template which means you won't want to do it for each rendering. This
1071 means it has a downside that you lose out when you want to render
1072 using templates which change often. Template::Simple makes it very
1073 easy to precompile as it already has the regexes to parse out the
1074 markup. So instead of calling subs to do actual rendering, a
1075 precompiler would call subs to generate a compiled rendering tree.
1076 The rendering tree can then be run or processes with rendering data
1077 passed to it. You can think of a precompiled template as having all
1078 the nested chunks be replaced by nested code that does the same
1079 rendering. It can still do the dynamic rendering of the data but it
1080 saves the time of parsing the template souice. There are three
1081 possible internal formats for the precompiled template:
1087 This precompiler will generate source code that can be stored and/or
1088 eval'ed. The eval'ed top level sub can then be called and passed the
1091 =item Closure call tree
1093 The internal format can be a nested set of closures. Each closure would contain
1094 private data such as fixed text parts of the original template, lists
1095 of other closures to run, etc. It is trivial to write a basic closure
1096 generator which will make build this tree a simple task.
1098 =item Code ref call tree
1100 This format is a Perl data tree where the nodes have a code reference
1101 and its args (which can be nested instances of the same
1102 nodes). Instead of executing this directly, you will need a small
1103 interpreter to execute all the code refs as it runs through the tree.
1105 This would make for a challenging project to any intermediate Perl
1106 hacker. It just involves knowing recursion, data trees and code refs.
1107 Contact me if you are interested in doing this.
1111 =head2 Cased Hash Lookups
1113 One possible option is to allow hash renderings to always use upper or
1114 lower cased keys in their lookups.
1116 =head2 Render tokens before includes and chunks
1118 Currently tokens are rendered after includes and chunks. If tokens
1119 were rendered in a pass before the others, the include and chunk names
1120 could be dynamically set. This would make it harder to precompile
1121 templates as too much would be dynamic, i.e. you won't know what the
1122 fixed text to parse out is since anything can be included at render
1123 time. But the extra flexibility of changing the include and chunk
1124 names would be interesting. It could be done easily and enabled by an
1129 There are two different potential areas in Template::Simple that could
1130 use plugins. The first is with the rendering of chunkas and
1131 dispatching based on the data type. This dispatch table can easily be
1132 replaced by loaded modules which offer a different way to
1133 render. These include the precompiled renderers mentioned above. The
1134 other area is with code references as the data type. By defining a
1135 closure (or a closure making) API you can create different code refs
1136 for the rendering data. The range of plugins is endless some of the
1137 major template modules have noticed. One idea is to make a closure
1138 which contains a different Template::Simple object than the current
1139 one. This will allow rendering of a nested chunk with different rules
1140 than the current chunk being rendered.
1142 =head2 Data Escaping
1144 Some templaters have options to properly escape data for some types of
1145 text files such as html. this can be done with some variant of the
1146 _render_hash routine which also does the scalar rendering (which is
1147 where data is rendered). The rendering scalars code could be factored
1148 out into a set of subs one of which is used based on any escaping
1151 =head2 Data Tree is an Object
1153 This is a concept I don't like but it was requested so it goes into
1154 the TODO file. Currently C<render> can only be passed a regular
1155 (unblessed) ref (or a scalar) for its data tree. Passing in an object
1156 would break encapsulation and force the object layout to be a hash
1157 tree that matches the layout of the template. I doubt that most
1158 objects will want to be organized to match a template. I have two
1159 ideas, one is that you add a method to that object that builds up a
1160 proper (unblessed) data tree to pass to C<render>. The other is by
1161 subclassing C<Template::Simple> and overriding C<render> with a sub
1162 that does take an object hash and it can unbless it or build a proper
1163 data tree and then call C<render> in SUPER::. A quick solution is to
1164 use C<reftype> (from Scalar::Utils) instead of C<ref> to allow object
1165 hashes to be passed in.
1167 =head2 Includes and Closure Synergy
1169 By pairing up an include template along with code that can generate
1170 the appropriate data tree for its rendering, you can create a higher
1171 level template framework (the synergy). Additional code can be
1172 associated with them that will handle input processing and
1173 verification for the templates (e.g. web forms) that need it. A key to
1174 this will be making all the closures for the data tree. This can be
1175 greatly simplified by using a closure maker sub that can create all
1176 the required closures.
1178 =head2 Metafields and UI Generation
1180 Taking the synergy up to a much higher level is the concept of meta
1181 knowledge of fields which can generate templates, output processing
1182 (data tree generation), input processing, DB backing and more. If you
1183 want to discuss such grandiose wacky application schemes in a long
1184 rambling mind bending conversation, please contact me.
1186 =head2 More Examples and Idioms
1188 As I convert several scripts over to this module (they all used the
1189 hack version), I will add them to an examples section or possibly put
1190 them in another (pod only) module. Similarly the Idioms section needs
1191 rendering and could be also put into a pod module. One goal requested
1192 by an early alpha tester is to keep the primary docs as simple as the
1193 markup itself. This means moving all the extra stuff (and plenty of
1194 that) into other pod modules. All the pod modules would be in the same
1195 cpan tarball so you get all the docs and examples when you install
1200 Uri Guttman, C<< <uri at sysarch.com> >>
1204 Please report any bugs or feature requests to
1205 C<bug-template-simple at rt.cpan.org>, or through the web interface at
1206 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Template-Simple>.
1207 I will be notified, and then you'll automatically be notified of progress on
1208 your bug as I make changes.
1212 You can find documentation for this module with the perldoc command.
1214 perldoc Template::Simple
1216 You can also look for information at:
1220 =item * RT: CPAN's request tracker
1222 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Template-Simple>
1226 L<http://search.cpan.org/dist/Template-Simple>
1230 =head1 ACKNOWLEDGEMENTS
1232 I wish to thank Turbo10 for their support in developing this module.
1234 =head1 COPYRIGHT & LICENSE
1236 Copyright 2006 Uri Guttman, all rights reserved.
1238 This program is free software; you can redistribute it and/or modify it
1239 under the same terms as Perl itself.
1244 find templates and tests
1252 delete_templates test
1260 slurp dependency in makefile.pl