summaryrefslogtreecommitdiff
path: root/lib/Template.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Template.pm')
-rw-r--r--lib/Template.pm950
1 files changed, 950 insertions, 0 deletions
diff --git a/lib/Template.pm b/lib/Template.pm
new file mode 100644
index 0000000..18e1ec4
--- /dev/null
+++ b/lib/Template.pm
@@ -0,0 +1,950 @@
+#============================================================= -*-perl-*-
+#
+# Template
+#
+# DESCRIPTION
+# Module implementing a simple, user-oriented front-end to the Template
+# Toolkit.
+#
+# AUTHOR
+# Andy Wardley <abw@andywardley.com>
+#
+# COPYRIGHT
+# Copyright (C) 1996-2002 Andy Wardley. All Rights Reserved.
+# Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
+#
+# This module is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+#
+# REVISION
+# $Id: Template.pm,v 2.68 2003/04/29 12:38:58 abw Exp $
+#
+#========================================================================
+
+package Template;
+use base qw( Template::Base );
+
+require 5.005;
+
+use strict;
+use vars qw( $VERSION $AUTOLOAD $ERROR $DEBUG $BINMODE );
+use Template::Base;
+use Template::Config;
+use Template::Constants;
+use Template::Provider;
+use Template::Service;
+use File::Basename;
+use File::Path;
+
+## This is the main version number for the Template Toolkit.
+## It is extracted by ExtUtils::MakeMaker and inserted in various places.
+$VERSION = '2.10';
+$ERROR = '';
+$DEBUG = 0;
+
+# we used to default to binary mode for all win32 files but that make
+# line endings strange, so we're turning it off and letting users set
+# it explicitly as an argument to process()
+# $BINMODE = ($^O eq 'MSWin32') ? 1 : 0;
+$BINMODE = 0 unless defined $BINMODE;
+
+# preload all modules if we're running under mod_perl
+Template::Config->preload() if $ENV{ MOD_PERL };
+
+
+#------------------------------------------------------------------------
+# process($input, \%replace, $output)
+#
+# Main entry point for the Template Toolkit. The Template module
+# delegates most of the processing effort to the underlying SERVICE
+# object, an instance of the Template::Service class.
+#------------------------------------------------------------------------
+
+sub process {
+ my ($self, $template, $vars, $outstream, @opts) = @_;
+ my ($output, $error);
+ my $options = (@opts == 1) && UNIVERSAL::isa($opts[0], 'HASH')
+ ? shift(@opts) : { @opts };
+
+ $options->{ binmode } = $BINMODE
+ unless defined $options->{ binmode };
+
+ # we're using this for testing in t/output.t and t/filter.t so
+ # don't remove it if you don't want tests to fail...
+ $self->DEBUG("set binmode\n") if $DEBUG && $options->{ binmode };
+
+ $output = $self->{ SERVICE }->process($template, $vars);
+
+ if (defined $output) {
+ $outstream ||= $self->{ OUTPUT };
+ unless (ref $outstream) {
+ my $outpath = $self->{ OUTPUT_PATH };
+ $outstream = "$outpath/$outstream" if $outpath;
+ }
+
+ # send processed template to output stream, checking for error
+ return ($self->error($error))
+ if ($error = &_output($outstream, \$output, $options));
+
+ return 1;
+ }
+ else {
+ return $self->error($self->{ SERVICE }->error);
+ }
+}
+
+
+#------------------------------------------------------------------------
+# service()
+#
+# Returns a reference to the the internal SERVICE object which handles
+# all requests for this Template object
+#------------------------------------------------------------------------
+
+sub service {
+ my $self = shift;
+ return $self->{ SERVICE };
+}
+
+
+#------------------------------------------------------------------------
+# context()
+#
+# Returns a reference to the the CONTEXT object withint the SERVICE
+# object.
+#------------------------------------------------------------------------
+
+sub context {
+ my $self = shift;
+ return $self->{ SERVICE }->{ CONTEXT };
+}
+
+
+#========================================================================
+# -- PRIVATE METHODS --
+#========================================================================
+
+#------------------------------------------------------------------------
+# _init(\%config)
+#------------------------------------------------------------------------
+sub _init {
+ my ($self, $config) = @_;
+
+ # convert any textual DEBUG args to numerical form
+ my $debug = $config->{ DEBUG };
+ $config->{ DEBUG } = Template::Constants::debug_flags($self, $debug)
+ || return if defined $debug && $debug !~ /^\d+$/;
+
+ # prepare a namespace handler for any CONSTANTS definition
+ if (my $constants = $config->{ CONSTANTS }) {
+ my $ns = $config->{ NAMESPACE } ||= { };
+ my $cns = $config->{ CONSTANTS_NAMESPACE } || 'constants';
+ $constants = Template::Config->constants($constants)
+ || return $self->error(Template::Config->error);
+ $ns->{ $cns } = $constants;
+ }
+
+ $self->{ SERVICE } = $config->{ SERVICE }
+ || Template::Config->service($config)
+ || return $self->error(Template::Config->error);
+
+ $self->{ OUTPUT } = $config->{ OUTPUT } || \*STDOUT;
+ $self->{ OUTPUT_PATH } = $config->{ OUTPUT_PATH };
+
+ return $self;
+}
+
+
+#------------------------------------------------------------------------
+# _output($where, $text)
+#------------------------------------------------------------------------
+
+sub _output {
+ my ($where, $textref, $options) = @_;
+ my $reftype;
+ my $error = 0;
+
+ # call a CODE reference
+ if (($reftype = ref($where)) eq 'CODE') {
+ &$where($$textref);
+ }
+ # print to a glob (such as \*STDOUT)
+ elsif ($reftype eq 'GLOB') {
+ print $where $$textref;
+ }
+ # append output to a SCALAR ref
+ elsif ($reftype eq 'SCALAR') {
+ $$where .= $$textref;
+ }
+ # push onto ARRAY ref
+ elsif ($reftype eq 'ARRAY') {
+ push @$where, $$textref;
+ }
+ # call the print() method on an object that implements the method
+ # (e.g. IO::Handle, Apache::Request, etc)
+ elsif (UNIVERSAL::can($where, 'print')) {
+ $where->print($$textref);
+ }
+ # a simple string is taken as a filename
+ elsif (! $reftype) {
+ local *FP;
+ # make destination directory if it doesn't exist
+ my $dir = dirname($where);
+ eval { mkpath($dir) unless -d $dir; };
+ if ($@) {
+ # strip file name and line number from error raised by die()
+ ($error = $@) =~ s/ at \S+ line \d+\n?$//;
+ }
+ elsif (open(FP, ">$where")) {
+ binmode FP if $options->{ binmode };
+ print FP $$textref;
+ close FP;
+ }
+ else {
+ $error = "$where: $!";
+ }
+ }
+ # give up, we've done our best
+ else {
+ $error = "output_handler() cannot determine target type ($where)\n";
+ }
+
+ return $error;
+}
+
+
+1;
+
+__END__
+
+
+#------------------------------------------------------------------------
+# IMPORTANT NOTE
+# This documentation is generated automatically from source
+# templates. Any changes you make here may be lost.
+#
+# The 'docsrc' documentation source bundle is available for download
+# from http://www.template-toolkit.org/docs.html and contains all
+# the source templates, XML files, scripts, etc., from which the
+# documentation for the Template Toolkit is built.
+#------------------------------------------------------------------------
+
+=head1 NAME
+
+Template - Front-end module to the Template Toolkit
+
+=head1 SYNOPSIS
+
+ use Template;
+
+ # some useful options (see below for full list)
+ my $config = {
+ INCLUDE_PATH => '/search/path', # or list ref
+ INTERPOLATE => 1, # expand "$var" in plain text
+ POST_CHOMP => 1, # cleanup whitespace
+ PRE_PROCESS => 'header', # prefix each template
+ EVAL_PERL => 1, # evaluate Perl code blocks
+ };
+
+ # create Template object
+ my $template = Template->new($config);
+
+ # define template variables for replacement
+ my $vars = {
+ var1 => $value,
+ var2 => \%hash,
+ var3 => \@list,
+ var4 => \&code,
+ var5 => $object,
+ };
+
+ # specify input filename, or file handle, text reference, etc.
+ my $input = 'myfile.html';
+
+ # process input template, substituting variables
+ $template->process($input, $vars)
+ || die $template->error();
+
+=head1 DESCRIPTION
+
+This documentation describes the Template module which is the direct
+Perl interface into the Template Toolkit. It covers the use of the
+module and gives a brief summary of configuration options and template
+directives. Please see L<Template::Manual> for the complete reference
+manual which goes into much greater depth about the features and use
+of the Template Toolkit. The L<Template::Tutorial> is also available
+as an introductory guide to using the Template Toolkit.
+
+=head1 METHODS
+
+=head2 new(\%config)
+
+The new() constructor method (implemented by the Template::Base base
+class) instantiates a new Template object. A reference to a hash
+array of configuration items may be passed as a parameter.
+
+ my $tt = Template->new({
+ INCLUDE_PATH => '/usr/local/templates',
+ EVAL_PERL => 1,
+ }) || die $Template::ERROR, "\n";
+
+A reference to a new Template object is returned, or undef on error.
+In the latter case, the error message can be retrieved by calling
+error() as a class method (e.g. C<Template-E<gt>error()>) or by
+examining the $ERROR package variable directly
+(e.g. C<$Template::ERROR>).
+
+ my $tt = Template->new(\%config)
+ || die Template->error(), "\n";
+
+ my $tt = Template->new(\%config)
+ || die $Template::ERROR, "\n";
+
+For convenience, configuration items may also be specified as a list
+of items instead of a hash array reference. These are automatically
+folded into a hash array by the constructor.
+
+ my $tt = Template->new(INCLUDE_PATH => '/tmp', POST_CHOMP => 1)
+ || die $Template::ERROR, "\n";
+
+=head2 process($template, \%vars, $output, %options)
+
+The process() method is called to process a template. The first
+parameter indicates the input template as one of: a filename relative
+to INCLUDE_PATH, if defined; a reference to a text string containing
+the template text; or a file handle reference (e.g. IO::Handle or
+sub-class) or GLOB (e.g. \*STDIN), from which the template can be
+read. A reference to a hash array may be passed as the second
+parameter, containing definitions of template variables.
+
+ $text = "[% INCLUDE header %]\nHello world!\n[% INCLUDE footer %]";
+
+ # filename
+ $tt->process('welcome.tt2')
+ || die $tt->error(), "\n";
+
+ # text reference
+ $tt->process(\$text)
+ || die $tt->error(), "\n";
+
+ # GLOB
+ $tt->process(\*DATA)
+ || die $tt->error(), "\n";
+
+ __END__
+ [% INCLUDE header %]
+ This is a template defined in the __END__ section which is
+ accessible via the DATA "file handle".
+ [% INCLUDE footer %]
+
+By default, the processed template output is printed to STDOUT. The
+process() method then returns 1 to indicate success. A third
+parameter may be passed to the process() method to specify a different
+output location. This value may be one of: a plain string indicating
+a filename which will be opened (relative to OUTPUT_PATH, if defined)
+and the output written to; a file GLOB opened ready for output; a
+reference to a scalar (e.g. a text string) to which output/error is
+appended; a reference to a subroutine which is called, passing the
+output as a parameter; or any object reference which implements a
+'print' method (e.g. IO::Handle, Apache::Request, etc.) which will
+be called, passing the generated output as a parameter.
+
+Examples:
+
+ # output filename
+ $tt->process('welcome.tt2', $vars, 'welcome.html')
+ || die $tt->error(), "\n";
+
+ # reference to output subroutine
+ sub myout {
+ my $output = shift;
+ ...
+ }
+ $tt->process('welcome.tt2', $vars, \&myout)
+ || die $tt->error(), "\n";
+
+ # reference to output text string
+ my $output = '';
+ $tt->process('welcome.tt2', $vars, \$output)
+ || die $tt->error(), "\n";
+
+ print "output: $output\n";
+
+In an Apache/mod_perl handler:
+
+ sub handler {
+ my $req = shift;
+
+ ...
+
+ # direct output to Apache::Request via $req->print($output)
+ $tt->process($file, $vars, $req) || do {
+ $req->log_reason($tt->error());
+ return SERVER_ERROR;
+ };
+
+ return OK;
+ }
+
+After the optional third output argument can come an optional
+reference to a hash or a list of (name, value) pairs providing further
+options for the output. The only option currently supported is
+"binmode" which, when set to any true value will ensure that files
+created (but not any existing file handles passed) will be set to
+binary mode.
+
+ # either: hash reference of options
+ $tt->process($infile, $vars, $outfile, { binmode => 1 })
+ || die $tt->error(), "\n";
+
+ # or: list of name, value pairs
+ $tt->process($infile, $vars, $outfile, binmode => 1)
+ || die $tt->error(), "\n";
+
+The OUTPUT configuration item can be used to specify a default output
+location other than \*STDOUT. The OUTPUT_PATH specifies a directory
+which should be prefixed to all output locations specified as filenames.
+
+ my $tt = Template->new({
+ OUTPUT => sub { ... }, # default
+ OUTPUT_PATH => '/tmp',
+ ...
+ }) || die Template->error(), "\n";
+
+ # use default OUTPUT (sub is called)
+ $tt->process('welcome.tt2', $vars)
+ || die $tt->error(), "\n";
+
+ # write file to '/tmp/welcome.html'
+ $tt->process('welcome.tt2', $vars, 'welcome.html')
+ || die $tt->error(), "\n";
+
+The process() method returns 1 on success or undef on error. The error
+message generated in the latter case can be retrieved by calling the
+error() method. See also L<CONFIGURATION SUMMARY> which describes how
+error handling may be further customised.
+
+=head2 error()
+
+When called as a class method, it returns the value of the $ERROR package
+variable. Thus, the following are equivalent.
+
+ my $tt = Template->new()
+ || die Template->error(), "\n";
+
+ my $tt = Template->new()
+ || die $Template::ERROR, "\n";
+
+When called as an object method, it returns the value of the internal
+_ERROR variable, as set by an error condition in a previous call to
+process().
+
+ $tt->process('welcome.tt2')
+ || die $tt->error(), "\n";
+
+Errors are represented in the Template Toolkit by objects of the
+Template::Exception class. If the process() method returns a false
+value then the error() method can be called to return an object of
+this class. The type() and info() methods can called on the object to
+retrieve the error type and information string, respectively. The
+as_string() method can be called to return a string of the form "$type
+- $info". This method is also overloaded onto the stringification
+operator allowing the object reference itself to be printed to return
+the formatted error string.
+
+ $tt->process('somefile') || do {
+ my $error = $tt->error();
+ print "error type: ", $error->type(), "\n";
+ print "error info: ", $error->info(), "\n";
+ print $error, "\n";
+ };
+
+=head2 service()
+
+The Template module delegates most of the effort of processing templates
+to an underlying Template::Service object. This method returns a reference
+to that object.
+
+=head2 context()
+
+The Template::Service module uses a core Template::Context object for
+runtime processing of templates. This method returns a reference to
+that object and is equivalent to $template-E<gt>service-E<gt>context();
+
+=head1 CONFIGURATION SUMMARY
+
+The following list gives a short summary of each Template Toolkit
+configuration option. See L<Template::Manual::Config> for full details.
+
+=head2 Template Style and Parsing Options
+
+=over 4
+
+=item START_TAG, END_TAG
+
+Define tokens that indicate start and end of directives (default: '[%' and
+'%]').
+
+=item TAG_STYLE
+
+Set START_TAG and END_TAG according to a pre-defined style (default:
+'template', as above).
+
+=item PRE_CHOMP, POST_CHOMP
+
+Remove whitespace before/after directives (default: 0/0).
+
+=item TRIM
+
+Remove leading and trailing whitespace from template output (default: 0).
+
+=item INTERPOLATE
+
+Interpolate variables embedded like $this or ${this} (default: 0).
+
+=item ANYCASE
+
+Allow directive keywords in lower case (default: 0 - UPPER only).
+
+=back
+
+=head2 Template Files and Blocks
+
+=over 4
+
+=item INCLUDE_PATH
+
+One or more directories to search for templates.
+
+=item DELIMITER
+
+Delimiter for separating paths in INCLUDE_PATH (default: ':').
+
+=item ABSOLUTE
+
+Allow absolute file names, e.g. /foo/bar.html (default: 0).
+
+=item RELATIVE
+
+Allow relative filenames, e.g. ../foo/bar.html (default: 0).
+
+=item DEFAULT
+
+Default template to use when another not found.
+
+=item BLOCKS
+
+Hash array pre-defining template blocks.
+
+=item AUTO_RESET
+
+Enabled by default causing BLOCK definitions to be reset each time a
+template is processed. Disable to allow BLOCK definitions to persist.
+
+=item RECURSION
+
+Flag to permit recursion into templates (default: 0).
+
+=back
+
+=head2 Template Variables
+
+=over 4
+
+=item VARIABLES, PRE_DEFINE
+
+Hash array of variables and values to pre-define in the stash.
+
+=back
+
+=head2 Runtime Processing Options
+
+=over 4
+
+=item EVAL_PERL
+
+Flag to indicate if PERL/RAWPERL blocks should be processed (default: 0).
+
+=item PRE_PROCESS, POST_PROCESS
+
+Name of template(s) to process before/after main template.
+
+=item PROCESS
+
+Name of template(s) to process instead of main template.
+
+=item ERROR
+
+Name of error template or reference to hash array mapping error types to
+templates.
+
+=item OUTPUT
+
+Default output location or handler.
+
+=item OUTPUT_PATH
+
+Directory into which output files can be written.
+
+=item DEBUG
+
+Enable debugging messages.
+
+=back
+
+=head2 Caching and Compiling Options
+
+=over 4
+
+=item CACHE_SIZE
+
+Maximum number of compiled templates to cache in memory (default:
+undef - cache all)
+
+=item COMPILE_EXT
+
+Filename extension for compiled template files (default: undef - don't
+compile).
+
+=item COMPILE_DIR
+
+Root of directory in which compiled template files should be written
+(default: undef - don't compile).
+
+=back
+
+=head2 Plugins and Filters
+
+=over 4
+
+=item PLUGINS
+
+Reference to a hash array mapping plugin names to Perl packages.
+
+=item PLUGIN_BASE
+
+One or more base classes under which plugins may be found.
+
+=item LOAD_PERL
+
+Flag to indicate regular Perl modules should be loaded if a named plugin
+can't be found (default: 0).
+
+=item FILTERS
+
+Hash array mapping filter names to filter subroutines or factories.
+
+=back
+
+=head2 Compatibility, Customisation and Extension
+
+=over 4
+
+=item V1DOLLAR
+
+Backwards compatibility flag enabling version 1.* handling (i.e. ignore it)
+of leading '$' on variables (default: 0 - '$' indicates interpolation).
+
+=item LOAD_TEMPLATES
+
+List of template providers.
+
+=item LOAD_PLUGINS
+
+List of plugin providers.
+
+=item LOAD_FILTERS
+
+List of filter providers.
+
+=item TOLERANT
+
+Set providers to tolerate errors as declinations (default: 0).
+
+=item SERVICE
+
+Reference to a custom service object (default: Template::Service).
+
+=item CONTEXT
+
+Reference to a custom context object (default: Template::Context).
+
+=item STASH
+
+Reference to a custom stash object (default: Template::Stash).
+
+=item PARSER
+
+Reference to a custom parser object (default: Template::Parser).
+
+=item GRAMMAR
+
+Reference to a custom grammar object (default: Template::Grammar).
+
+=back
+
+=head1 DIRECTIVE SUMMARY
+
+The following list gives a short summary of each Template Toolkit directive.
+See L<Template::Manual::Directives> for full details.
+
+=over 4
+
+=item GET
+
+Evaluate and print a variable or value.
+
+ [% GET variable %] # 'GET' keyword is optional
+
+ [% variable %]
+ [% hash.key %]
+ [% list.n %]
+ [% code(args) %]
+ [% obj.meth(args) %]
+ [% "value: $var" %]
+
+=item CALL
+
+As per GET but without printing result (e.g. call code)
+
+ [% CALL variable %]
+
+=item SET
+
+Assign a values to variables.
+
+ [% SET variable = value %] # 'SET' also optional
+
+ [% variable = other_variable
+ variable = 'literal text @ $100'
+ variable = "interpolated text: $var"
+ list = [ val, val, val, val, ... ]
+ list = [ val..val ]
+ hash = { var => val, var => val, ... }
+ %]
+
+=item DEFAULT
+
+Like SET above, but variables are only set if currently unset (i.e. have no
+true value).
+
+ [% DEFAULT variable = value %]
+
+=item INSERT
+
+Insert a file without any processing performed on the contents.
+
+ [% INSERT legalese.txt %]
+
+=item INCLUDE
+
+Process another template file or block and include the output. Variables
+are localised.
+
+ [% INCLUDE template %]
+ [% INCLUDE template var = val, ... %]
+
+=item PROCESS
+
+As INCLUDE above, but without localising variables.
+
+ [% PROCESS template %]
+ [% PROCESS template var = val, ... %]
+
+=item WRAPPER
+
+Process the enclosed block WRAPPER ... END block then INCLUDE the
+named template, passing the block output in the 'content' variable.
+
+ [% WRAPPER template %]
+ content...
+ [% END %]
+
+=item BLOCK
+
+Define a named template block for subsequent INCLUDE, PROCESS, etc.,
+
+ [% BLOCK template %]
+ content
+ [% END %]
+
+=item FOREACH
+
+Repeat the enclosed FOREACH ... END block for each value in the list.
+
+ [% FOREACH variable = [ val, val, val ] %] # either
+ [% FOREACH variable = list %] # or
+ [% FOREACH list %] # or
+ content...
+ [% variable %]
+ [% END %]
+
+=item WHILE
+
+Enclosed WHILE ... END block is processed while condition is true.
+
+ [% WHILE condition %]
+ content
+ [% END %]
+
+=item IF / UNLESS / ELSIF / ELSE
+
+Enclosed block is processed if the condition is true / false.
+
+ [% IF condition %]
+ content
+ [% ELSIF condition %]
+ content
+ [% ELSE %]
+ content
+ [% END %]
+
+ [% UNLESS condition %]
+ content
+ [% # ELSIF/ELSE as per IF, above %]
+ content
+ [% END %]
+
+=item SWITCH / CASE
+
+Multi-way switch/case statement.
+
+ [% SWITCH variable %]
+ [% CASE val1 %]
+ content
+ [% CASE [ val2, val3 ] %]
+ content
+ [% CASE %] # or [% CASE DEFAULT %]
+ content
+ [% END %]
+
+=item MACRO
+
+Define a named macro.
+
+ [% MACRO name <directive> %]
+ [% MACRO name(arg1, arg2) <directive> %]
+ ...
+ [% name %]
+ [% name(val1, val2) %]
+
+=item FILTER
+
+Process enclosed FILTER ... END block then pipe through a filter.
+
+ [% FILTER name %] # either
+ [% FILTER name( params ) %] # or
+ [% FILTER alias = name( params ) %] # or
+ content
+ [% END %]
+
+=item USE
+
+Load a "plugin" module, or any regular Perl module if LOAD_PERL option is
+set.
+
+ [% USE name %] # either
+ [% USE name( params ) %] # or
+ [% USE var = name( params ) %] # or
+ ...
+ [% name.method %]
+ [% var.method %]
+
+=item PERL / RAWPERL
+
+Evaluate enclosed blocks as Perl code (requires EVAL_PERL option to be set).
+
+ [% PERL %]
+ # perl code goes here
+ $stash->set('foo', 10);
+ print "set 'foo' to ", $stash->get('foo'), "\n";
+ print $context->include('footer', { var => $val });
+ [% END %]
+
+ [% RAWPERL %]
+ # raw perl code goes here, no magic but fast.
+ $output .= 'some output';
+ [% END %]
+
+=item TRY / THROW / CATCH / FINAL
+
+Exception handling.
+
+ [% TRY %]
+ content
+ [% THROW type info %]
+ [% CATCH type %]
+ catch content
+ [% error.type %] [% error.info %]
+ [% CATCH %] # or [% CATCH DEFAULT %]
+ content
+ [% FINAL %]
+ this block is always processed
+ [% END %]
+
+=item NEXT
+
+Jump straight to the next item in a FOREACH/WHILE loop.
+
+ [% NEXT %]
+
+=item LAST
+
+Break out of FOREACH/WHILE loop.
+
+ [% LAST %]
+
+=item RETURN
+
+Stop processing current template and return to including templates.
+
+ [% RETURN %]
+
+=item STOP
+
+Stop processing all templates and return to caller.
+
+ [% STOP %]
+
+=item TAGS
+
+Define new tag style or characters (default: [% %]).
+
+ [% TAGS html %]
+ [% TAGS <!-- --> %]
+
+=item COMMENTS
+
+Ignored and deleted.
+
+ [% # this is a comment to the end of line
+ foo = 'bar'
+ %]
+
+ [%# placing the '#' immediately inside the directive
+ tag comments out the entire directive
+ %]
+
+=back
+
+=head1 AUTHOR
+
+Andy Wardley E<lt>abw@andywardley.comE<gt>
+
+L<http://www.andywardley.com/|http://www.andywardley.com/>
+
+
+
+
+=head1 VERSION
+
+Template Toolkit version 2.10, released on 24 July 2003.
+
+=head1 COPYRIGHT
+
+ Copyright (C) 1996-2003 Andy Wardley. All Rights Reserved.
+ Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+