1 package Template::Simple ;
8 use Scalar::Util qw( reftype blessed ) ;
11 our $VERSION = '0.06';
16 post_delim => qr/%\]/,
21 search_dirs => [ qw( templates ) ],
26 my( $class, %opts ) = @_ ;
28 my $self = bless {}, $class ;
30 # get all the options or defaults into the object
32 # support the old name 'include_paths' ;
34 $opts{search_dirs} ||= delete $opts{include_paths} ;
36 while( my( $name, $default ) = each %opt_defaults ) {
38 $self->{$name} = defined( $opts{$name} ) ?
39 $opts{$name} : $default ;
42 croak "search_dirs is not an ARRAY reference" unless
43 ref $self->{search_dirs} eq 'ARRAY' ;
45 # make up the regexes to parse the markup from templates
47 # this matches scalar markups and grabs the name
49 $self->{scalar_re} = qr{
51 \s* # optional leading whitespace
52 ($self->{token_re}) # grab scalar name
53 \s* # optional trailing whitespace
55 }xi ; # case insensitive
57 #print "RE <$self->{scalar_re}>\n" ;
59 # this grabs the body of a chunk in either greedy or non-greedy modes
61 my $chunk_body = $self->{greedy_chunk} ? qr/.+/s : qr/.+?/s ;
63 # this matches a marked chunk and grabs its name and text body
65 $self->{chunk_re} = qr{
67 \s* # optional leading whitespace
68 START # required START token
69 \s+ # required whitespace
70 ($self->{token_re}) # grab the chunk name
71 \s* # optional trailing whitespace
73 ($chunk_body) # grab the chunk body
75 \s* # optional leading whitespace
76 END # required END token
77 \s+ # required whitespace
78 \1 # match the grabbed chunk name
79 \s* # optional trailing whitespace
81 }xi ; # case insensitive
83 #print "RE <$self->{chunk_re}>\n" ;
85 # this matches a include markup and grabs its template name
87 $self->{include_re} = qr{
89 \s* # optional leading whitespace
90 INCLUDE # required INCLUDE token
91 \s+ # required whitespace
92 ($self->{token_re}) # grab the included template name
93 \s* # optional trailing whitespace
95 }xi ; # case insensitive
97 # load in any templates
99 $self->add_templates( $opts{templates} ) ;
106 my( $self, $template_name ) = @_ ;
108 my $tmpl_ref = eval {
109 $self->_get_template( $template_name ) ;
112 #print Dumper $self ;
114 croak "Template::Simple $@" if $@ ;
116 my $included = $self->_render_includes( $tmpl_ref ) ;
118 # compile a copy of the template as it will be destroyed
120 my $code_body = $self->_compile_chunk( '', "${$included}", "\t" ) ;
122 my $source = <<CODE ;
130 use Scalar::Util qw( reftype ) ;
139 my $code_ref = eval $source ;
143 $self->{compiled_cache}{$template_name} = $code_ref ;
144 $self->{source_cache}{$template_name} = $source ;
149 my( $self, $chunk_name, $template, $indent ) = @_ ;
151 return '' unless length $template ;
153 # generate a lookup in data for this chunk name (unless it is the top
154 # level). this descends down the data tree during rendering
156 my $data_init = $chunk_name ? "\$data->{$chunk_name}" : '$data' ;
159 ${indent}my \@data = $data_init ;
160 ${indent}while( \@data ) {
162 ${indent} my \$data = shift \@data ;
163 ${indent} if ( reftype \$data eq 'ARRAY' ) {
164 ${indent} push \@data, \@{\$data} ;
172 # loop all nested chunks and the text separating them
174 while( my( $parsed_name, $parsed_body ) =
175 $template =~ m{$self->{chunk_re}} ) {
177 my $chunk_left_index = $-[0] ;
178 my $chunk_right_index = $+[0] ;
180 # get the pre-match text and compile its scalars and text. append to the code
182 $code .= $self->_compile_scalars(
183 substr( $template, 0, $chunk_left_index ), $indent ) ;
185 # print "CHUNK: [$1] BODY [$2]\n\n" ;
186 # print "TRUNC: [", substr( $template, 0, $chunk_right_index ), "]\n\n" ;
187 # print "PRE: [", substr( $template, 0, $chunk_left_index ), "]\n\n" ;
189 # chop off the pre-match and the chunk
191 substr( $template, 0, $chunk_right_index, '' ) ;
193 # print "REMAIN: [$template]\n\n" ;
195 # compile the nested chunk and append to the code
197 $code .= $self->_compile_chunk(
198 $parsed_name, $parsed_body, $indent
202 # compile trailing text for scalars and append to the code
204 $code .= $self->_compile_scalars( $template, $indent ) ;
208 # now we end the loop for this chunk
216 sub _compile_scalars {
218 my( $self, $template, $indent ) = @_ ;
220 # if the template is empty return no parts
222 return '' unless length $template ;
226 while( $template =~ m{$self->{scalar_re}}g ) {
228 # get the pre-match text before the scalar markup and generate code to
232 _dump_text( substr( $template, 0, $-[0] ) ),
236 # truncate the matched text so the next match starts at begining of string
238 substr( $template, 0, $+[0], '' ) ;
241 # keep any trailing text part
243 push @parts, _dump_text( $template ) ;
245 my $parts_code = join( "\n$indent.\n$indent", @parts ) ;
249 ${indent}\$out .= reftype \$data ne 'HASH' ? \$data :
250 ${indent}$parts_code ;
256 # internal sub to dump text for the template compiler. the output is
257 # a legal perl double quoted string without any leading text before
258 # the opening " and no trailing newline or ;
264 return unless length $text ;
266 local( $Data::Dumper::Useqq ) = 1 ;
268 my $dumped = Dumper $text ;
270 $dumped =~ s/^[^"]+// ;
271 $dumped =~ s/;\n$// ;
278 my( $self, $template_name ) = @_ ;
280 return $self->{source_cache}{$template_name} ;
285 my( $self, $template_name, $data ) = @_ ;
287 my $tmpl_ref = ref $template_name eq 'SCALAR' ? $template_name : '' ;
289 unless( $tmpl_ref ) {
291 # render with cached code and return if we precompiled this template
293 if ( my $compiled = $self->{compiled_cache}{$template_name} ) {
295 return $compiled->($data) ;
298 # not compiled so try to get this template by name or
299 # assume the template name are is the actual template
302 eval{ $self->_get_template( $template_name ) } ||
306 my $rendered = $self->_render_includes( $tmpl_ref ) ;
308 #print "INC EXP <$rendered>\n" ;
311 $self->_render_chunk( $rendered, $data ) ;
314 croak "Template::Simple $@" if $@ ;
319 sub _render_includes {
321 my( $self, $tmpl_ref ) = @_ ;
323 # make a copy of the initial template so we can render it.
325 my $rendered = ${$tmpl_ref} ;
327 # loop until we can render no more include markups
330 s{$self->{include_re}}{ ${ $self->_get_template($1) }}e ;
337 SCALAR => sub { return $_[2] },
338 '' => sub { return \$_[2] },
339 HASH => \&_render_hash,
340 ARRAY => \&_render_array,
341 CODE => \&_render_code,
342 # if no ref then data is a scalar so replace the template with just the data
348 my( $self, $tmpl_ref, $data ) = @_ ;
350 #print "T ref [$tmpl_ref] [$$tmpl_ref]\n" ;
351 #print "CHUNK ref [$tmpl_ref] TMPL\n<$$tmpl_ref>\n" ;
353 #print Dumper $data ;
355 return \'' unless defined $data ;
357 # get the type of this data. handle blessed types
359 my $reftype = blessed( $data ) ;
361 #print "REF $reftype\n" ;
363 # handle the case of a qr// which blessed returns as Regexp
367 $reftype = reftype $data unless $reftype eq 'Regexp' ;
370 $reftype = ref $data ;
373 #print "REF2 $reftype\n" ;
375 # now render this chunk based on the type of data
377 my $renderer = $renderers{ $reftype || ''} ;
379 #print "EXP $renderer\nREF $reftype\n" ;
381 croak "unknown template data type '$data'\n" unless defined $renderer ;
383 return $self->$renderer( $tmpl_ref, $data ) ;
388 my( $self, $tmpl_ref, $href ) = @_ ;
390 return $tmpl_ref unless keys %{$href} ;
392 # we need a local copy of the template to render
394 my $rendered = ${$tmpl_ref} ;
396 # recursively render all top level chunks in this chunk
398 $rendered =~ s{$self->{chunk_re}}
400 # print "CHUNK $1\nBODY\n----\n<$2>\n\n------\n" ;
401 # print "CHUNK $1\nBODY\n----\n<$2>\n\n------\n" ;
402 # print "pre CHUNK [$`]\n" ;
403 ${ $self->_render_chunk( \"$2", $href->{$1} ) }
408 #print "HREF: ", Dumper $href ;
410 $rendered =~ s{$self->{scalar_re}}
412 # print "SCALAR $1 VAL $href->{$1}\n" ;
413 defined $href->{$1} ? $href->{$1} : ''
416 #print "HASH REND3\n<$rendered>\n" ;
423 my( $self, $tmpl_ref, $aref ) = @_ ;
425 # render this $tmpl_ref for each element of the aref and join them
429 #print "AREF: ", Dumper $aref ;
431 $rendered .= ${$self->_render_chunk( $tmpl_ref, $_ )} for @{$aref} ;
438 my( $self, $tmpl_ref, $cref ) = @_ ;
440 my $rendered = $cref->( $tmpl_ref ) ;
442 croak <<DIE if ref $rendered ne 'SCALAR' ;
443 data callback to code didn't return a scalar or scalar reference
451 my( $self, $tmpls ) = @_ ;
453 #print Dumper $tmpls ;
454 return unless defined $tmpls ;
456 ref $tmpls eq 'HASH' or croak "templates argument is not a hash ref" ;
458 # copy all the templates from the arg hash and force the values to be
461 while( my( $name, $tmpl ) = each %{$tmpls} ) {
463 defined $tmpl or croak "undefined template value for '$name'" ;
465 # cache the a scalar ref of the template
467 $self->{tmpl_cache}{$name} = ref $tmpl eq 'SCALAR' ?
468 \"${$tmpl}" : \"$tmpl"
471 #print Dumper $self->{tmpl_cache} ;
476 sub delete_templates {
478 my( $self, @names ) = @_ ;
480 # delete all the cached stuff or just the names passed in
482 @names = keys %{$self->{tmpl_cache}} unless @names ;
484 #print "NAMES @names\n" ;
485 # clear out all the caches
486 # TODO: reorg these into a hash per name
488 delete @{$self->{tmpl_cache}}{ @names } ;
489 delete @{$self->{compiled_cache}}{ @names } ;
490 delete @{$self->{source_cache}}{ @names } ;
492 # also remove where we found it to force a fresh search
494 delete @{$self->{template_paths}}{ @names } ;
501 my( $self, $tmpl_name ) = @_ ;
503 #print "INC $tmpl_name\n" ;
505 my $tmpls = $self->{tmpl_cache} ;
507 # get the template from the cache and send it back if it was found there
509 my $template = $tmpls->{ $tmpl_name } ;
510 return $template if $template ;
512 # not found, so find, slurp in and cache the template
514 $template = $self->_find_template( $tmpl_name ) ;
515 $tmpls->{ $tmpl_name } = $template ;
522 my( $self, $tmpl_name ) = @_ ;
524 #print "FIND $tmpl_name\n" ;
525 foreach my $dir ( @{$self->{search_dirs}} ) {
527 my $tmpl_path = "$dir/$tmpl_name.tmpl" ;
529 #print "PATH: $tmpl_path\n" ;
531 next if $tmpl_path =~ /\n/ ;
532 next unless -r $tmpl_path ;
534 # cache the path to this template
536 $self->{template_paths}{$tmpl_name} = $tmpl_path ;
538 # slurp in the template file and return it as a scalar ref
540 #print "FOUND $tmpl_name\n" ;
542 return read_file( $tmpl_path, scalar_ref => 1 ) ;
545 #print "CAN'T FIND $tmpl_name\n" ;
548 can't find template '$tmpl_name' in '@{$self->{search_dirs}}'
553 1; # End of Template::Simple
559 Template::Simple - A simple and very fast template module
567 use Template::Simple;
569 my $tmpl = Template::Simple->new();
571 # here is a simple template store in a scalar
572 # the header and footer templates will be included from the cache or files.
574 my $template_text = <<TMPL ;
577 [%first%] - [%second%]
582 # this is data that will be used to render that template the keys
583 # are mapped to the chunk names (START & END markups) in the
584 # template the row is an array reference so multiple rows will be
585 # rendered usually the data tree is generated by code instead of
590 date => 'Jan 1, 2008',
591 author => 'Me, myself and I',
595 first => 'row 1 value 1',
596 second => 'row 1 value 2',
599 first => 'row 2 value 1',
600 second => 'row 2 value 2',
604 modified => 'Aug 31, 2006',
608 # this call renders the template with the data tree
610 my $rendered = $tmpl->render( \$template_text, $data ) ;
612 # here we add the template to the cache and give it a name
614 $tmpl->add_templates( { demo => $template_text } ) ;
616 # this compiles and then renders that template with the same data
619 $tmpl->compile( 'demo' ) ;
620 my $rendered = $tmpl->render( 'demo', $data ) ;
625 Template::Simple is a very fast template rendering module with a
626 simple markup. It can do almost any templating task and is extendable
627 with user callbacks. It can render templates directly or compile them
634 You create a Template::Simple by calling the class method new:
636 my $tmpl = Template::Simple->new() ;
638 All the arguments to C<new()> are key/value options that change how
639 the object will render templates.
643 This option sets the string or regex that is the starting delimiter
644 for all markups. You can use a plain string or a qr// but you need to
645 escape (with \Q or \) any regex metachars if you want them to be plain
646 chars. The default is qr/\[%/.
648 my $tmpl = Template::Simple->new(
652 my $rendered = $tmpl->render( '<%FOO%]', 'bar' ) ;
656 This option sets the string or regex that is the ending delimiter
657 for all markups. You can use a plain string or a qr// but you need to
658 escape (with \Q or \) any regex metachars if you want them to be plain
659 chars. The default is qr/%]/.
661 my $tmpl = Template::Simple->new(
665 my $rendered = $tmpl->render( '[%FOO%>', 'bar' ) ;
669 This option overrides the regular expression that is used match a
670 token or name in the markup. It should be a qr// and you may need to
671 escape (with \Q or \) any regex metachars if you want them to be plain
672 chars. The default is qr/\w+?/.
674 my $tmpl = Template::Simple->new(
675 token_re => qr/[\w-]+?/,
678 my $rendered = $tmpl->render(
679 '[% id-with-hyphens %]',
680 { 'id-with-hyphens' => 'bar' }
685 This boolean option will cause the regex that grabs a chunk of text
686 between the C<START/END> markups to become greedy (.+). The default is
687 a not-greedy grab of the chunk text. (UNTESTED)
691 This option lets you load templates directly into the cache of the
692 Template::Simple object. See <TEMPLATE CACHE> for more on this.
694 my $tmpl = Template::Simple->new(
697 [%baz%] is a [%quux%]
700 [%user%] is not a [%fool%]
705 =head2 search_dirs, include_paths
707 This option lets you set the directory paths to search for template
708 files. Its value is an array reference with the paths. Its default is
711 my $tmpl = Template::Simple->new(
718 NOTE: This option was called C<include_paths> but since it is used to
719 locate named templates as well as included ones, it was changed to
720 C<search_dirs>. The older name C<include_paths> is still supported
721 but new code should use C<search_dirs>.
727 This method is passed a template and a data tree and it renders it and
728 returns a reference to the resulting string.
730 If the template argument is a scalar reference, then it is the
731 template text to be rendered. A scalar template argument is first
732 assumed to be a template name which is searched for in the template
733 cache and the compiled template caches. If found in there it is used
734 as the template. If not found there, it is searched for in the
735 directories of the C<search_dirs>. Finally if not found, it will be
736 used as the template text.
738 The data tree argument can be any value allowed by Template::Simple
739 when rendering a template. It can also be a blessed reference (Perl
740 object) since C<Scalar::Util::reftype> is used instead of C<ref> to
741 determine the data type.
743 Note that the author recommends against passing in an object as this
744 breaks encapsulation and forces your object to be (most likely) a
745 hash. It would be better to create a simple method that copies the
746 object contents to a hash reference and pass that. But other current
747 templaters allow passing in objects so that is supported here as well.
749 my $rendered = $tmpl->render( $template, $data ) ;
753 This method takes a template and compiles it to make it run much
754 faster. Its only argument is a template name and that is used to
755 locate the template in the object cache or it is loaded from a file
756 (with the same search technique as regular rendering). The compiled
757 template is stored in its own cache and can be rendered by a call to
758 the render method and passing the name and the data tree.
760 $tmpl->compile( 'foo' ) ;
761 my $rendered = $tmpl->render( 'foo', $data ) ;
763 There are a couple of restrictions to compiled templates. They don't
764 support code references in the data tree (that may get supported in
765 the future). Also since the include expansion happens one time during
766 the compiling, any changes to the template or its includes will not be
767 detected when rendering a compiled template. You need to re-compile a
768 template to force it to use changed templates. Note that you may need
769 to delete templates from the object cache (with the delete_templates
770 method) to force them to be reloaded from files.
774 This method adds templates to the object cache. It takes a list of
775 template names and texts just like the C<templates> constructor
776 option. These templates are located by name when compiling or
779 $tmpl->add_templates(
781 foo => \$foo_template,
782 bar => '[%include bar%]',
786 =head2 delete_templates
788 This method takes a list of template names and will delete them from
789 the template cache in the object. If you pass no arguments then all
790 the cached templates will be deleted. This can be used when you know
791 a template file has been updated and you want to get it loaded back
794 # this deletes only the foo and bar templates from the object cache
796 $tmpl->delete_templates( qw( foo bar ) ;
798 # this deletes all of templates from the object cache
800 $tmpl->delete_templates() ;
804 $tmpl->get_source( 'bar' ) ;
806 This method is passed a compiled template name and returns the
807 generated Perl source for a compiled template. You can compile a
808 template and paste the generated source (a single sub per template)
809 into another program. The sub can be called and passed a data tree and
810 return a rendered template. It saves the compile time for that
811 template but it still needs to be compiled by Perl. This method is
812 also useful for debugging the template compiler.
814 =head1 TEMPLATE CACHE
816 This cache is stored in the object and will be searched to find any
817 template by name. It is initially loaded via the C<templates> option
818 to new and more can be added with the C<add_templates> method. You can
819 delete templates from the cache with the C<delete_templates>
820 method. Compiled templates have their own cache in the
821 module. Deleting a template also deletes it from the compiled cache.
823 =head1 INCLUDE EXPANSION
825 Before a template is either rendered or compiled it undergoes include
826 expansion. All include markups are replaced by a templated located in
827 the cache or from a file. Included templates can include other
828 templates. This expansion keeps going until no more includes are
831 =head1 LOCATING TEMPLATES
833 When a template needs to be loaded by name (when rendering, compiling
834 or expanding includes) it is first searched for in the object cache
835 (and the compiled cache for compiled templates). If not found there,
836 the C<templates_paths> are searched for files with that name and a
837 suffix of .tmpl. If a file is found, it used and also loaded into the
838 template cache in the object with the searched for name as its key.
842 All the markups in Template::Simple use the same delimiters which are
843 C<[%> and C<%]>. You can change the delimiters with the C<pre_delim>
844 and C<post_delim> options in the C<new()> constructor.
848 A token is a single markup with a C<\w+> Perl word inside. The token
849 can have optional whitespace before and after it. A token is replaced
850 by a value looked up in a hash with the token as the key. The hash
851 lookup keeps the same case as parsed from the token markup. You can
852 override the regular expression used to match a token with the
857 Those will be replaced by C<$href->{foo}> and C<$href->{BAR}> assuming
858 C<$href> is the current data for this rendering. Tokens are only
859 parsed out during hash data rendering so see Hash Data for more.
863 Chunks are regions of text in a template that are marked off with a
864 start and end markers with the same name. A chunk start marker is
865 C<[%START name%]> and the end marker for that chunk is C<[%END
866 name%]>. C<name> is matched with C<\w+?> and that is the name of this
867 chunk. The whitespace between C<START/END> and C<name> is required and
868 there is optional whitespace before C<START/END> and after the
869 C<name>. C<START/END> are case insensitive but the C<name>'s case is
870 kept. Chunks are the primary way to markup templates for structures
871 (sets of tokens), nesting (hashes of hashes), repeats (array
872 references) and callbacks to user code. By default a chunk will be a
873 non-greedy grab but you can change that in the constructor by enabling
874 the C<greedy_chunk> option. You can override the regular expression
875 used to match the chunk name with the C<token_re> option.
885 When a markup C<[%include name%]> is seen, that text is replaced by
886 the template of that name. C<name> is matched with C<\w+?> which is
887 the name of the template. You can override the regular expression used
888 to match the include C<name> with the C<token_re> option.
890 See C<INCLUDE EXPANSION> for more on this.
892 =head1 RENDERING RULES
894 Template::Simple has a short list of rendering rules and they are easy
895 to understand. There are two types of renderings, include rendering
896 and chunk rendering. In the C<render> method, the template is an
897 unnamed top level chunk of text and it first gets its C<INCLUDE>
898 markups rendered. The text then undergoes a chunk rendering and a
899 scalar reference to that rendered template is returned to the caller.
901 =head2 Include Rendering
903 All include file rendering happens before any other rendering is
904 done. After this phase, the rendered template will not have
905 C<[%include name%]> markups in it.
907 =head2 Chunk Rendering
909 A chunk is the text found between matching C<START> and C<END> markups
910 and it gets its name from the C<START> markup. The top level template
911 is considered an unamed chunk and also gets chunk rendered.
913 The data for a chunk determines how it will be rendered. The data can
914 be a scalar or scalar reference or an array, hash or code
915 reference. Since chunks can contain nested chunks, rendering will
916 recurse down the data tree as it renders the chunks. Each of these
917 renderings are explained below. Also see the IDIOMS and BEST PRACTICES
918 section for examples and used of these renderings.
922 =item Hash Data Rendering
924 If the current data for a chunk is a hash reference then two phases of
925 rendering happen, nested chunk rendering and token rendering. First
926 nested chunks are parsed of of this chunk along with their names. Each
927 parsed out chunk is rendered based on the value in the current hash
928 with the nested chunk's name as the key.
930 If a value is not found (undefined), then the nested chunk is replaced
931 by the empty string. Otherwise the nested chunk is rendered according
932 to the type of its data (see chunk rendering) and it is replaced by
935 Chunk name and token lookup in the hash data is case sensitive.
937 Note that to keep a plain text chunk or to just have the all of its
938 markups (chunks and tokens) be deleted just pass in an empty hash
939 reference C<{}> as the data for the chunk. It will be rendered but all
940 markups will be replaced by the empty string.
942 The second phase is token rendering. Markups of the form [%token%] are
943 replaced by the value of the hash element with the token as the
944 key. If a token's value is not defined it is replaced by the empty
945 string. This means if a token key is missing in the hash or its value
946 is undefined or its value is the empty string, the [%token%] markup
947 will be deleted in the rendering.
949 =item Array Data Rendering
951 If the current data for a chunk is an array reference it will do a
952 full chunk rendering for each value in the array. It will replace the
953 original chunk text with the concatenated list of rendered
954 chunks. This is how you do repeated sections in Template::Simple and
955 why there is no need for any loop markups. Note that this means that
956 rendering a chunk with $data and [ $data ] will do the exact same
957 thing. A value of an empty array C<[]> will cause the chunk to be
958 replaced by the empty string.
960 =item Scalar Data Rendering
962 If the current data for a chunk is a scalar or scalar reference, the
963 entire chunk is replaced by the scalar's value. This can be used to
964 overwrite one default section of text with from the data tree.
966 =item Code Data Rendering
968 If the current data for a chunk is a code reference (also called
969 anonymous sub) then the code reference is called and it is passed a
970 scalar reference to the that chunk's text. The code must return a
971 scalar or a scalar reference and its value replaces the chunk's text
972 in the template. If the code returns any other type of data it is a
973 fatal error. Code rendering is how you can do custom renderings and
974 plugins. A key idiom is to use closures as the data in code renderings
975 and keep the required outside data in the closure.
985 When using compiled templates T::S is one of the fastest template
986 tools around. There is a benchmark script in the extras/ directory
987 comparing it to Template `Toolkit and Template::Teeny
989 =item * Support most common template operations
991 It can recursively include other templates, replace tokens (scalars),
992 recursively render nested chunks of text and render lists. By using
993 simple idioms you can get conditional renderings.
995 =item * Complete isolation of template from program code
997 Template design and programming the data logic can be done by
998 different people. Templates and data logic can be mixed and matched
999 which improves reuse and flexibility.
1001 =item * Very simple template markup (only 4 markups)
1003 The only markups are C<INCLUDE>, C<START>, C<END> and C<token>. See
1006 =item * Easy to follow rendering rules
1008 Rendering of templates and chunks is driven from a data tree. The type
1009 of the data element used in an rendering controls how the rendering
1010 happens. The data element can be a scalar, scalar reference, or an
1011 array, hash or code reference.
1013 =item * Efficient template rendering
1015 Rendering is very simple and uses Perl's regular expressions
1016 efficiently. Because the markup is so simple less processing is needed
1017 than many other templaters. You can precompile templates for even
1018 faster rendering but with some minor restrictions in flexibility
1020 =item * Easy user extensions
1022 User code can be called during an rendering so you can do custom
1023 renderings and plugins. Closures can be used so the code can have its
1024 own private data for use in rendering its template chunk.
1030 Please report any bugs or feature requests to
1031 C<bug-template-simple at rt.cpan.org>, or through the web interface at
1032 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Template-Simple>.
1033 I will be notified, and then you'll automatically be notified of progress on
1034 your bug as I make changes.
1038 =item * RT: CPAN's request tracker
1040 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Template-Simple>
1044 L<http://search.cpan.org/dist/Template-Simple>
1048 =head1 ACKNOWLEDGEMENTS
1050 I wish to thank Turbo10 for their support in developing this module.
1058 Copyright 2011 Uri Guttman, all rights reserved.
1062 An article on file slurping in extras/slurp_article.pod. There is
1063 also a benchmarking script in extras/slurp_bench.pl.
1067 Uri Guttman, E<lt>uri@stemsystems.comE<gt>