diff options
| author | Andreas Brachold <vdr07@deltab.de> | 2007-08-13 18:41:27 +0000 |
|---|---|---|
| committer | Andreas Brachold <vdr07@deltab.de> | 2007-08-13 18:41:27 +0000 |
| commit | bcbf441e09fb502cf64924ff2530fa144bdf52c5 (patch) | |
| tree | f377707a2dac078db8cd0c7d7abfe69ac1006d71 /lib/Template/Manual | |
| download | xxv-bcbf441e09fb502cf64924ff2530fa144bdf52c5.tar.gz xxv-bcbf441e09fb502cf64924ff2530fa144bdf52c5.tar.bz2 | |
* Move files to trunk
Diffstat (limited to 'lib/Template/Manual')
| -rw-r--r-- | lib/Template/Manual/Config.pod | 2122 | ||||
| -rw-r--r-- | lib/Template/Manual/Credits.pod | 188 | ||||
| -rw-r--r-- | lib/Template/Manual/Directives.pod | 2179 | ||||
| -rw-r--r-- | lib/Template/Manual/Filters.pod | 529 | ||||
| -rw-r--r-- | lib/Template/Manual/Internals.pod | 556 | ||||
| -rw-r--r-- | lib/Template/Manual/Intro.pod | 295 | ||||
| -rw-r--r-- | lib/Template/Manual/Plugins.pod | 552 | ||||
| -rw-r--r-- | lib/Template/Manual/Refs.pod | 171 | ||||
| -rw-r--r-- | lib/Template/Manual/Syntax.pod | 306 | ||||
| -rw-r--r-- | lib/Template/Manual/VMethods.pod | 529 | ||||
| -rw-r--r-- | lib/Template/Manual/Variables.pod | 868 | ||||
| -rw-r--r-- | lib/Template/Manual/Views.pod | 642 |
12 files changed, 8937 insertions, 0 deletions
diff --git a/lib/Template/Manual/Config.pod b/lib/Template/Manual/Config.pod new file mode 100644 index 0000000..5020556 --- /dev/null +++ b/lib/Template/Manual/Config.pod @@ -0,0 +1,2122 @@ +#============================================================= -*-perl-*- +# +# Template::Manual::Config +# +# DESCRIPTION +# This section contains details of all the configuration options that +# can be used to customise the behaviour and extend the features of +# the Template Toolkit. +# +# AUTHOR +# Andy Wardley <abw@andywardley.com> +# +# COPYRIGHT +# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved. +# Copyright (C) 1998-2001 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 +# +# +#======================================================================== + + +#------------------------------------------------------------------------ +# 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::Manual::Config - Configuration options + +=head1 DESCRIPTION + +This section contains details of all the configuration options that can +be used to customise the behaviour and extend the features of the +Template Toolkit. + +=head2 Template Style and Parsing Options + +=over 4 + + + +=item START_TAG, END_TAG + +The START_TAG and END_TAG options are used to specify character +sequences or regular expressions that mark the start and end of a +template directive. The default values for START_TAG and END_TAG are +'[%' and '%]' respectively, giving us the familiar directive style: + + [% example %] + +Any Perl regex characters can be used and therefore should be escaped +(or use the Perl C<quotemeta> function) if they are intended to +represent literal characters. + + my $template = Template->new({ + START_TAG => quotemeta('<+'), + END_TAG => quotemeta('+>'), + }); + +example: + + <+ INCLUDE foobar +> + +The TAGS directive can also be used to set the START_TAG and END_TAG values +on a per-template file basis. + + [% TAGS <+ +> %] + + + + + + +=item TAG_STYLE + +The TAG_STYLE option can be used to set both START_TAG and END_TAG +according to pre-defined tag styles. + + my $template = Template->new({ + TAG_STYLE => 'star', + }); + +Available styles are: + + template [% ... %] (default) + template1 [% ... %] or %% ... %% (TT version 1) + metatext %% ... %% (Text::MetaText) + star [* ... *] (TT alternate) + php <? ... ?> (PHP) + asp <% ... %> (ASP) + mason <% ... > (HTML::Mason) + html <!-- ... --> (HTML comments) + +Any values specified for START_TAG and/or END_TAG will over-ride +those defined by a TAG_STYLE. + +The TAGS directive may also be used to set a TAG_STYLE + + [% TAGS html %] + <!-- INCLUDE header --> + + + + + + +=item PRE_CHOMP, POST_CHOMP + +Anything outside a directive tag is considered plain text and is +generally passed through unaltered (but see the INTERPOLATE option). +This includes all whitespace and newlines characters surrounding +directive tags. Directives that don't generate any output will leave +gaps in the output document. + +Example: + + Foo + [% a = 10 %] + Bar + +Output: + + Foo + + Bar + +The PRE_CHOMP and POST_CHOMP options can help to clean up some of this +extraneous whitespace. Both are disabled by default. + + my $template = Template->new({ + PRE_CHOMP => 1, + POST_CHOMP => 1, + }); + +With PRE_CHOMP set to 1, the newline and whitespace preceding a directive +at the start of a line will be deleted. This has the effect of +concatenating a line that starts with a directive onto the end of the +previous line. + + Foo <----------. + | + ,---(PRE_CHOMP)----' + | + `-- [% a = 10 %] --. + | + ,---(POST_CHOMP)---' + | + `-> Bar + +With POST_CHOMP set to 1, any whitespace after a directive up to and +including the newline will be deleted. This has the effect of joining +a line that ends with a directive onto the start of the next line. + +If PRE_CHOMP or POST_CHOMP is set to 2, then instead of removing all +the whitespace, the whitespace will be collapsed to a single space. +This is useful for HTML, where (usually) a contiguous block of +whitespace is rendered the same as a single space. + +You may use the CHOMP_NONE, CHOMP_ALL, and CHOMP_COLLAPSE constants +from the Template::Constants module to deactivate chomping, remove +all whitespace, or collapse whitespace to a single space. + +PRE_CHOMP and POST_CHOMP can be activated for individual directives by +placing a '-' immediately at the start and/or end of the directive. + + [% FOREACH user = userlist %] + [%- user -%] + [% END %] + +The '-' characters activate both PRE_CHOMP and POST_CHOMP for the one +directive '[%- name -%]'. Thus, the template will be processed as if +written: + + [% FOREACH user = userlist %][% user %][% END %] + +Note that this is the same as if PRE_CHOMP and POST_CHOMP were set +to CHOMP_ALL; the only way to get the CHOMP_COLLAPSE behavior is +to set PRE_CHOMP or POST_CHOMP accordingly. If PRE_CHOMP or POST_CHOMP +is already set to CHOMP_COLLAPSE, using '-' will give you CHOMP_COLLAPSE +behavior, not CHOMP_ALL behavior. + +Similarly, '+' characters can be used to disable PRE_CHOMP or +POST_CHOMP (i.e. leave the whitespace/newline intact) options on a +per-directive basis. + + [% FOREACH user = userlist %] + User: [% user +%] + [% END %] + +With POST_CHOMP enabled, the above example would be parsed as if written: + + [% FOREACH user = userlist %]User: [% user %] + [% END %] + + + + + +=item TRIM + +The TRIM option can be set to have any leading and trailing whitespace +automatically removed from the output of all template files and BLOCKs. + +By example, the following BLOCK definition + + [% BLOCK foo %] + Line 1 of foo + [% END %] + +will be processed is as "\nLine 1 of foo\n". When INCLUDEd, the surrounding +newlines will also be introduced. + + before + [% INCLUDE foo %] + after + +output: + before + + Line 1 of foo + + after + +With the TRIM option set to any true value, the leading and trailing +newlines (which count as whitespace) will be removed from the output +of the BLOCK. + + before + Line 1 of foo + after + +The TRIM option is disabled (0) by default. + + + + + +=item INTERPOLATE + +The INTERPOLATE flag, when set to any true value will cause variable +references in plain text (i.e. not surrounded by START_TAG and END_TAG) +to be recognised and interpolated accordingly. + + my $template = Template->new({ + INTERPOLATE => 1, + }); + +Variables should be prefixed by a '$' to identify them. Curly braces +can be used in the familiar Perl/shell style to explicitly scope the +variable name where required. + + # INTERPOLATE => 0 + <a href="http://[% server %]/[% help %]"> + <img src="[% images %]/help.gif"></a> + [% myorg.name %] + + # INTERPOLATE => 1 + <a href="http://$server/$help"> + <img src="$images/help.gif"></a> + $myorg.name + + # explicit scoping with { } + <img src="$images/${icon.next}.gif"> + +Note that a limitation in Perl's regex engine restricts the maximum length +of an interpolated template to around 32 kilobytes or possibly less. Files +that exceed this limit in size will typically cause Perl to dump core with +a segmentation fault. If you routinely process templates of this size +then you should disable INTERPOLATE or split the templates in several +smaller files or blocks which can then be joined backed together via +PROCESS or INCLUDE. + + + + + + + +=item ANYCASE + +By default, directive keywords should be expressed in UPPER CASE. The +ANYCASE option can be set to allow directive keywords to be specified +in any case. + + # ANYCASE => 0 (default) + [% INCLUDE foobar %] # OK + [% include foobar %] # ERROR + [% include = 10 %] # OK, 'include' is a variable + + # ANYCASE => 1 + [% INCLUDE foobar %] # OK + [% include foobar %] # OK + [% include = 10 %] # ERROR, 'include' is reserved word + +One side-effect of enabling ANYCASE is that you cannot use a variable +of the same name as a reserved word, regardless of case. The reserved +words are currently: + + GET CALL SET DEFAULT INSERT INCLUDE PROCESS WRAPPER + IF UNLESS ELSE ELSIF FOR FOREACH WHILE SWITCH CASE + USE PLUGIN FILTER MACRO PERL RAWPERL BLOCK META + TRY THROW CATCH FINAL NEXT LAST BREAK RETURN STOP + CLEAR TO STEP AND OR NOT MOD DIV END + + +The only lower case reserved words that cannot be used for variables, +regardless of the ANYCASE option, are the operators: + + and or not mod div + + + + + + +=back + +=head2 Template Files and Blocks + +=over 4 + + + +=item INCLUDE_PATH + +The INCLUDE_PATH is used to specify one or more directories in which +template files are located. When a template is requested that isn't +defined locally as a BLOCK, each of the INCLUDE_PATH directories is +searched in turn to locate the template file. Multiple directories +can be specified as a reference to a list or as a single string where +each directory is delimited by ':'. + + my $template = Template->new({ + INCLUDE_PATH => '/usr/local/templates', + }); + + my $template = Template->new({ + INCLUDE_PATH => '/usr/local/templates:/tmp/my/templates', + }); + + my $template = Template->new({ + INCLUDE_PATH => [ '/usr/local/templates', + '/tmp/my/templates' ], + }); + +On Win32 systems, a little extra magic is invoked, ignoring delimiters +that have ':' followed by a '/' or '\'. This avoids confusion when using +directory names like 'C:\Blah Blah'. + +When specified as a list, the INCLUDE_PATH path can contain elements +which dynamically generate a list of INCLUDE_PATH directories. These +generator elements can be specified as a reference to a subroutine or +an object which implements a paths() method. + + my $template = Template->new({ + INCLUDE_PATH => [ '/usr/local/templates', + \&incpath_generator, + My::IncPath::Generator->new( ... ) ], + }); + +Each time a template is requested and the INCLUDE_PATH examined, the +subroutine or object method will be called. A reference to a list of +directories should be returned. Generator subroutines should report +errors using die(). Generator objects should return undef and make an +error available via its error() method. + +For example: + + sub incpath_generator { + + # ...some code... + + if ($all_is_well) { + return \@list_of_directories; + } + else { + die "cannot generate INCLUDE_PATH...\n"; + } + } + +or: + + package My::IncPath::Generator; + + # Template::Base (or Class::Base) provides error() method + use Template::Base; + use base qw( Template::Base ); + + sub paths { + my $self = shift; + + # ...some code... + + if ($all_is_well) { + return \@list_of_directories; + } + else { + return $self->error("cannot generate INCLUDE_PATH...\n"); + } + } + + 1; + + + + + +=item DELIMITER + +Used to provide an alternative delimiter character sequence for +separating paths specified in the INCLUDE_PATH. The default +value for DELIMITER is ':'. + + # tolerate Silly Billy's file system conventions + my $template = Template->new({ + DELIMITER => '; ', + INCLUDE_PATH => 'C:/HERE/NOW; D:/THERE/THEN', + }); + + # better solution: install Linux! :-) + +On Win32 systems, the default delimiter is a little more intelligent, +splitting paths only on ':' characters that aren't followed by a '/'. +This means that the following should work as planned, splitting the +INCLUDE_PATH into 2 separate directories, C:/foo and C:/bar. + + # on Win32 only + my $template = Template->new({ + INCLUDE_PATH => 'C:/Foo:C:/Bar' + }); + +However, if you're using Win32 then it's recommended that you +explicitly set the DELIMITER character to something else (e.g. ';') +rather than rely on this subtle magic. + + + + +=item ABSOLUTE + +The ABSOLUTE flag is used to indicate if templates specified with +absolute filenames (e.g. '/foo/bar') should be processed. It is +disabled by default and any attempt to load a template by such a +name will cause a 'file' exception to be raised. + + my $template = Template->new({ + ABSOLUTE => 1, + }); + + # this is why it's disabled by default + [% INSERT /etc/passwd %] + +On Win32 systems, the regular expression for matching absolute +pathnames is tweaked slightly to also detect filenames that start +with a driver letter and colon, such as: + + C:/Foo/Bar + + + + + + +=item RELATIVE + +The RELATIVE flag is used to indicate if templates specified with +filenames relative to the current directory (e.g. './foo/bar' or +'../../some/where/else') should be loaded. It is also disabled by +default, and will raise a 'file' error if such template names are +encountered. + + my $template = Template->new({ + RELATIVE => 1, + }); + + [% INCLUDE ../logs/error.log %] + + + + + +=item DEFAULT + +The DEFAULT option can be used to specify a default template which should +be used whenever a specified template can't be found in the INCLUDE_PATH. + + my $template = Template->new({ + DEFAULT => 'notfound.html', + }); + +If a non-existant template is requested through the Template process() +method, or by an INCLUDE, PROCESS or WRAPPER directive, then the +DEFAULT template will instead be processed, if defined. Note that the +DEFAULT template is not used when templates are specified with +absolute or relative filenames, or as a reference to a input file +handle or text string. + + + + + +=item BLOCKS + +The BLOCKS option can be used to pre-define a default set of template +blocks. These should be specified as a reference to a hash array +mapping template names to template text, subroutines or Template::Document +objects. + + my $template = Template->new({ + BLOCKS => { + header => 'The Header. [% title %]', + footer => sub { return $some_output_text }, + another => Template::Document->new({ ... }), + }, + }); + + + + +=item AUTO_RESET + +The AUTO_RESET option is set by default and causes the local BLOCKS +cache for the Template::Context object to be reset on each call to the +Template process() method. This ensures that any BLOCKs defined +within a template will only persist until that template is finished +processing. This prevents BLOCKs defined in one processing request +from interfering with other independent requests subsequently +processed by the same context object. + +The BLOCKS item may be used to specify a default set of block definitions +for the Template::Context object. Subsequent BLOCK definitions in templates +will over-ride these but they will be reinstated on each reset if AUTO_RESET +is enabled (default), or if the Template::Context reset() method is called. + + + + + + + + + +=item RECURSION + +The template processor will raise a file exception if it detects +direct or indirect recursion into a template. Setting this option to +any true value will allow templates to include each other recursively. + + + +=back + +=head2 Template Variables + +=over 4 + +=item VARIABLES, PRE_DEFINE + +The VARIABLES option (or PRE_DEFINE - they're equivalent) can be used +to specify a hash array of template variables that should be used to +pre-initialise the stash when it is created. These items are ignored +if the STASH item is defined. + + my $template = Template->new({ + VARIABLES => { + title => 'A Demo Page', + author => 'Joe Random Hacker', + version => 3.14, + }, + }; + +or + + my $template = Template->new({ + PRE_DEFINE => { + title => 'A Demo Page', + author => 'Joe Random Hacker', + version => 3.14, + }, + }; + + + + +=item CONSTANTS + +The CONSTANTS option can be used to specify a hash array of template +variables that are compile-time constants. These variables are +resolved once when the template is compiled, and thus don't require +further resolution at runtime. This results in significantly faster +processing of the compiled templates and can be used for variables that +don't change from one request to the next. + + my $template = Template->new({ + CONSTANTS => { + title => 'A Demo Page', + author => 'Joe Random Hacker', + version => 3.14, + }, + }; + +=item CONSTANT_NAMESPACE + +Constant variables are accessed via the 'constants' namespace by +default. + + [% constants.title %] + +The CONSTANTS_NAMESPACE option can be set to specify an alternate +namespace. + + my $template = Template->new({ + CONSTANTS => { + title => 'A Demo Page', + # ...etc... + }, + CONSTANTS_NAMESPACE => 'const', + }; + +In this case the constants would then be accessed as: + + [% const.title %] + +=item NAMESPACE + +The constant folding mechanism described above is an example of a +namespace handler. Namespace handlers can be defined to provide +alternate parsing mechanisms for variables in different namespaces. + +Under the hood, the Template module converts a constructor configuration +such as: + + my $template = Template->new({ + CONSTANTS => { + title => 'A Demo Page', + # ...etc... + }, + CONSTANTS_NAMESPACE => 'const', + }; + +into one like: + + my $template = Template->new({ + NAMESPACE => { + const => Template:::Namespace::Constants->new({ + title => 'A Demo Page', + # ...etc... + }), + }, + }; + +You can use this mechanism to define multiple constant namespaces, or +to install custom handlers of your own. + + my $template = Template->new({ + NAMESPACE => { + site => Template:::Namespace::Constants->new({ + title => "Wardley's Widgets", + version => 2.718, + }), + author => Template:::Namespace::Constants->new({ + name => 'Andy Wardley', + email => 'abw@andywardley.com', + }), + voodoo => My::Namespace::Handler->new( ... ), + }, + }; + +Now you have 2 constant namespaces, for example: + + [% site.title %] + [% author.name %] + +as well as your own custom namespace handler installed for the 'voodoo' +namespace. + + [% voodoo.magic %] + +See L<Template::Namespace::Constants|Template::Namespace::Constants> +for an example of what a namespace handler looks like on the inside. + + + + + +=back + +=head2 Template Processing Options + + +The following options are used to specify any additional templates +that should be processed before, after, around or instead of the +template passed as the first argument to the Template process() +method. These options can be perform various useful tasks such as +adding standard headers or footers to all pages, wrapping page output +in other templates, pre-defining variables or performing +initialisation or cleanup tasks, automatically generating page summary +information, navigation elements, and so on. + +The task of processing the template is delegated internally to the +Template::Service module which, unsurprisingly, also has a process() +method. Any templates defined by the PRE_PROCESS option are processed +first and any output generated is added to the output buffer. Then +the main template is processed, or if one or more PROCESS templates +are defined then they are instead processed in turn. In this case, +one of the PROCESS templates is responsible for processing the main +template, by a directive such as: + + [% PROCESS $template %] + +The output of processing the main template or the PROCESS template(s) +is then wrapped in any WRAPPER templates, if defined. WRAPPER +templates don't need to worry about explicitly processing the template +because it will have been done for them already. Instead WRAPPER +templates access the content they are wrapping via the 'content' +variable. + + wrapper before + [% content %] + wrapper after + +This output generated from processing the main template, and/or any +PROCESS or WRAPPER templates is added to the output buffer. Finally, +any POST_PROCESS templates are processed and their output is also +added to the output buffer which is then returned. + +If the main template throws an exception during processing then any +relevant template(s) defined via the ERROR option will be processed +instead. If defined and successfully processed, the output from the +error template will be added to the output buffer in place of the +template that generated the error and processing will continue, +applying any WRAPPER and POST_PROCESS templates. If no relevant ERROR +option is defined, or if the error occurs in one of the PRE_PROCESS, +WRAPPER or POST_PROCESS templates, then the process will terminate +immediately and the error will be returned. + + + +=over 4 + + + +=item PRE_PROCESS, POST_PROCESS + +These values may be set to contain the name(s) of template files +(relative to INCLUDE_PATH) which should be processed immediately +before and/or after each template. These do not get added to +templates processed into a document via directives such as INCLUDE, +PROCESS, WRAPPER etc. + + my $template = Template->new({ + PRE_PROCESS => 'header', + POST_PROCESS => 'footer', + }; + +Multiple templates may be specified as a reference to a list. Each is +processed in the order defined. + + my $template = Template->new({ + PRE_PROCESS => [ 'config', 'header' ], + POST_PROCESS => 'footer', + }; + +Alternately, multiple template may be specified as a single string, +delimited by ':'. This delimiter string can be changed via the +DELIMITER option. + + my $template = Template->new({ + PRE_PROCESS => 'config:header', + POST_PROCESS => 'footer', + }; + +The PRE_PROCESS and POST_PROCESS templates are evaluated in the same +variable context as the main document and may define or update +variables for subsequent use. + +config: + + [% # set some site-wide variables + bgcolor = '#ffffff' + version = 2.718 + %] + +header: + + [% DEFAULT title = 'My Funky Web Site' %] + <html> + <head> + <title>[% title %]</title> + </head> + <body bgcolor="[% bgcolor %]"> + +footer: + + <hr> + Version [% version %] + </body> + </html> + +The Template::Document object representing the main template being processed +is available within PRE_PROCESS and POST_PROCESS templates as the 'template' +variable. Metadata items defined via the META directive may be accessed +accordingly. + + $template->process('mydoc.html', $vars); + +mydoc.html: + + [% META title = 'My Document Title' %] + blah blah blah + ... + +header: + + <html> + <head> + <title>[% template.title %]</title></head> + <body bgcolor="[% bgcolor %]"> + + + + + + + + + + + + + + +=item PROCESS + +The PROCESS option may be set to contain the name(s) of template files +(relative to INCLUDE_PATH) which should be processed instead of the +main template passed to the Template process() method. This can +be used to apply consistent wrappers around all templates, similar to +the use of PRE_PROCESS and POST_PROCESS templates. + + my $template = Template->new({ + PROCESS => 'content', + }; + + # processes 'content' instead of 'foo.html' + $template->process('foo.html'); + +A reference to the original template is available in the 'template' +variable. Metadata items can be inspected and the template can be +processed by specifying it as a variable reference (i.e. prefixed by +'$') to an INCLUDE, PROCESS or WRAPPER directive. + +content: + + <html> + <head> + <title>[% template.title %]</title> + </head> + + <body> + [% PROCESS $template %] + <hr> + © Copyright [% template.copyright %] + </body> + </html> + +foo.html: + + [% META + title = 'The Foo Page' + author = 'Fred Foo' + copyright = '2000 Fred Foo' + %] + <h1>[% template.title %]</h1> + Welcome to the Foo Page, blah blah blah + +output: + + <html> + <head> + <title>The Foo Page</title> + </head> + + <body> + <h1>The Foo Page</h1> + Welcome to the Foo Page, blah blah blah + <hr> + © Copyright 2000 Fred Foo + </body> + </html> + + + + + + + +=item WRAPPER + +The WRAPPER option can be used to specify one or more templates which +should be used to wrap around the output of the main page template. +The main template is processed first (or any PROCESS template(s)) and +the output generated is then passed as the 'content' variable to the +WRAPPER template(s) as they are processed. + + my $template = Template->new({ + WRAPPER => 'wrapper', + }; + + # process 'foo' then wrap in 'wrapper' + $template->process('foo', { message => 'Hello World!' }); + +wrapper: + + <wrapper> + [% content %] + </wrapper> + +foo: + + This is the foo file! + Message: [% message %] + +The output generated from this example is: + + <wrapper> + This is the foo file! + Message: Hello World! + </wrapper> + +You can specify more than one WRAPPER template by setting the value to +be a reference to a list of templates. The WRAPPER templates will be +processed in reverse order with the output of each being passed to the +next (or previous, depending on how you look at it) as the 'content' +variable. It sounds complicated, but the end result is that it just +"Does The Right Thing" to make wrapper templates nest in the order you +specify. + + my $template = Template->new({ + WRAPPER => [ 'outer', 'inner' ], + }; + + # process 'foo' then wrap in 'inner', then in 'outer' + $template->process('foo', { message => 'Hello World!' }); + +outer: + + <outer> + [% content %] + </outer> + +inner: + + <inner> + [% content %] + </inner> + +The output generated is then: + + <outer> + <inner> + This is the foo file! + Message: Hello World! + </inner> + </outer> + +One side-effect of the "inside-out" processing of the WRAPPER +configuration item (and also the WRAPPER directive) is that any +variables set in the template being wrapped will be visible to the +template doing the wrapping, but not the other way around. + +You can use this to good effect in allowing page templates to set +pre-defined values which are then used in the wrapper templates. For +example, our main page template 'foo' might look like this: + +foo: + + [% page = { + title = 'Foo Page' + subtitle = 'Everything There is to Know About Foo' + author = 'Frank Oliver Octagon' + } + %] + + <p> + Welcome to the page that tells you everything about foo + blah blah blah... + </p> + +The 'foo' template is processed before the wrapper template meaning +that the 'page' data structure will be defined for use in the wrapper +template. + +wrapper: + + <html> + <head> + <title>[% page.title %]</title> + </head> + <body> + <h1>[% page.title %]</h1> + <h2>[% page.subtitle %]</h1> + <h3>by [% page.author %]</h3> + + [% content %] + </body> + </html> + +It achieves the same effect as defining META items which are then +accessed via the 'template' variable (which you are still free to +use within WRAPPER templates), but gives you more flexibility in +the type and complexity of data that you can define. + + + + + +=item ERROR + +The ERROR (or ERRORS if you prefer) configuration item can be used to +name a single template or specify a hash array mapping exception types +to templates which should be used for error handling. If an uncaught +exception is raised from within a template then the appropriate error +template will instead be processed. + +If specified as a single value then that template will be processed +for all uncaught exceptions. + + my $template = Template->new({ + ERROR => 'error.html' + }); + +If the ERROR item is a hash reference the keys are assumed to be +exception types and the relevant template for a given exception will +be selected. A 'default' template may be provided for the general +case. Note that 'ERROR' can be pluralised to 'ERRORS' if you find +it more appropriate in this case. + + my $template = Template->new({ + ERRORS => { + user => 'user/index.html', + dbi => 'error/database', + default => 'error/default', + }, + }); + +In this example, any 'user' exceptions thrown will cause the +'user/index.html' template to be processed, 'dbi' errors are handled +by 'error/database' and all others by the 'error/default' template. +Any PRE_PROCESS and/or POST_PROCESS templates will also be applied +to these error templates. + +Note that exception types are hierarchical and a 'foo' handler will +catch all 'foo.*' errors (e.g. foo.bar, foo.bar.baz) if a more +specific handler isn't defined. Be sure to quote any exception types +that contain periods to prevent Perl concatenating them into a single +string (i.e. C<user.passwd> is parsed as 'user'.'passwd'). + + my $template = Template->new({ + ERROR => { + 'user.login' => 'user/login.html', + 'user.passwd' => 'user/badpasswd.html', + 'user' => 'user/index.html', + 'default' => 'error/default', + }, + }); + +In this example, any template processed by the $template object, or +other templates or code called from within, can raise a 'user.login' +exception and have the service redirect to the 'user/login.html' +template. Similarly, a 'user.passwd' exception has a specific +handling template, 'user/badpasswd.html', while all other 'user' or +'user.*' exceptions cause a redirection to the 'user/index.html' page. +All other exception types are handled by 'error/default'. + + +Exceptions can be raised in a template using the THROW directive, + + [% THROW user.login 'no user id: please login' %] + +or by calling the throw() method on the current Template::Context object, + + $context->throw('user.passwd', 'Incorrect Password'); + $context->throw('Incorrect Password'); # type 'undef' + +or from Perl code by calling die() with a Template::Exception object, + + die (Template::Exception->new('user.denied', 'Invalid User ID')); + +or by simply calling die() with an error string. This is +automagically caught and converted to an exception of 'undef' +type which can then be handled in the usual way. + + die "I'm sorry Dave, I can't do that"; + + + + + + +=back + +=head2 Template Runtime Options + +=over 4 + + + + +=item EVAL_PERL + +This flag is used to indicate if PERL and/or RAWPERL blocks should be +evaluated. By default, it is disabled and any PERL or RAWPERL blocks +encountered will raise exceptions of type 'perl' with the message +'EVAL_PERL not set'. Note however that any RAWPERL blocks should +always contain valid Perl code, regardless of the EVAL_PERL flag. The +parser will fail to compile templates that contain invalid Perl code +in RAWPERL blocks and will throw a 'file' exception. + +When using compiled templates (see +L<COMPILE_EXT|Template::Manual::Config/Caching_and_Compiling_Options> and +L<COMPILE_DIR|Template::Manual::Config/Caching_and_Compiling_Options>), +the EVAL_PERL has an affect when the template is compiled, and again +when the templates is subsequently processed, possibly in a different +context to the one that compiled it. + +If the EVAL_PERL is set when a template is compiled, then all PERL and +RAWPERL blocks will be included in the compiled template. If the +EVAL_PERL option isn't set, then Perl code will be generated which +B<always> throws a 'perl' exception with the message 'EVAL_PERL not +set' B<whenever> the compiled template code is run. + +Thus, you must have EVAL_PERL set if you want your compiled templates +to include PERL and RAWPERL blocks. + +At some point in the future, using a different invocation of the +Template Toolkit, you may come to process such a pre-compiled +template. Assuming the EVAL_PERL option was set at the time the +template was compiled, then the output of any RAWPERL blocks will be +included in the compiled template and will get executed when the +template is processed. This will happen regardless of the runtime +EVAL_PERL status. + +Regular PERL blocks are a little more cautious, however. If the +EVAL_PERL flag isn't set for the I<current> context, that is, the +one which is trying to process it, then it will throw the familiar 'perl' +exception with the message, 'EVAL_PERL not set'. + +Thus you can compile templates to include PERL blocks, but optionally +disable them when you process them later. Note however that it is +possible for a PERL block to contain a Perl "BEGIN { # some code }" +block which will always get run regardless of the runtime EVAL_PERL +status. Thus, if you set EVAL_PERL when compiling templates, it is +assumed that you trust the templates to Do The Right Thing. Otherwise +you must accept the fact that there's no bulletproof way to prevent +any included code from trampling around in the living room of the +runtime environment, making a real nuisance of itself if it really +wants to. If you don't like the idea of such uninvited guests causing +a bother, then you can accept the default and keep EVAL_PERL disabled. + + + + + + + +=item OUTPUT + +Default output location or handler. This may be specified as one of: +a file name (relative to OUTPUT_PATH, if defined, or the current +working directory if not specified absolutely); a file handle +(e.g. GLOB or IO::Handle) opened for writing; a reference to a text +string to which the output is appended (the string isn't cleared); a +reference to a subroutine which is called, passing the output text as +an argument; as a reference to an array, onto which the content will be +push()ed; or as a reference to any object that supports the print() +method. This latter option includes the Apache::Request object which +is passed as the argument to Apache/mod_perl handlers. + +example 1 (file name): + + my $template = Template->new({ + OUTPUT => "/tmp/foo", + }); + +example 2 (text string): + + my $output = ''; + + my $template = Template->new({ + OUTPUT => \$output, + }); + +example 3 (file handle): + + open (TOUT, "> $file") || die "$file: $!\n"; + + my $template = Template->new({ + OUTPUT => \*TOUT, + }); + +example 4 (subroutine): + + sub output { my $out = shift; print "OUTPUT: $out" } + + my $template = Template->new({ + OUTPUT => \&output, + }); + +example 5 (array reference): + + my $template = Template->new({ + OUTPUT => \@output, + }) + +example 6 (Apache/mod_perl handler): + + sub handler { + my $r = shift; + + my $t = Template->new({ + OUTPUT => $r, + }); + ... + } + +The default OUTPUT location be overridden by passing a third parameter +to the Template process() method. This can be specified as any of the +above argument types. + + $t->process($file, $vars, "/tmp/foo"); + $t->process($file, $vars, "bar"); + $t->process($file, $vars, \*MYGLOB); + $t->process($file, $vars, \@output); + $t->process($file, $vars, $r); # Apache::Request + ... + + + + + + + + +=item OUTPUT_PATH + +The OUTPUT_PATH allows a directory to be specified into which output +files should be written. An output file can be specified by the +OUTPUT option, or passed by name as the third parameter to the +Template process() method. + + my $template = Template->new({ + INCLUDE_PATH => "/tmp/src", + OUTPUT_PATH => "/tmp/dest", + }); + + my $vars = { + ... + }; + + foreach my $file ('foo.html', 'bar.html') { + $template->process($file, $vars, $file) + || die $template->error(); + } + +This example will read the input files '/tmp/src/foo.html' and +'/tmp/src/bar.html' and write the processed output to '/tmp/dest/foo.html' +and '/tmp/dest/bar.html', respectively. + + + + + + + + +=item DEBUG + +The DEBUG option can be used to enable debugging within the various +different modules that comprise the Template Toolkit. The +L<Template::Constants|Template::Constants> module defines a set of +DEBUG_XXXX constants which can be combined using the logical OR +operator, '|'. + + use Template::Constants qw( :debug ); + + my $template = Template->new({ + DEBUG => DEBUG_PARSER | DEBUG_PROVIDER, + }); + +For convenience, you can also provide a string containing a list +of lower case debug options, separated by any non-word characters. + + my $template = Template->new({ + DEBUG => 'parser, provider', + }); + +The following DEBUG_XXXX flags can be used: + +=over 4 + +=item DEBUG_SERVICE + +Enables general debugging messages for the +L<Template::Service|Template::Service> module. + +=item DEBUG_CONTEXT + +Enables general debugging messages for the +L<Template::Context|Template::Context> module. + +=item DEBUG_PROVIDER + +Enables general debugging messages for the +L<Template::Provider|Template::Provider> module. + +=item DEBUG_PLUGINS + +Enables general debugging messages for the +L<Template::Plugins|Template::Plugins> module. + +=item DEBUG_FILTERS + +Enables general debugging messages for the +L<Template::Filters|Template::Filters> module. + +=item DEBUG_PARSER + +This flag causes the L<Template::Parser|Template::Parser> to generate +debugging messages that show the Perl code generated by parsing and +compiling each template. + +=item DEBUG_UNDEF + +This option causes the Template Toolkit to throw an 'undef' error +whenever it encounters an undefined variable value. + +=item DEBUG_DIRS + +This option causes the Template Toolkit to generate comments +indicating the source file, line and original text of each directive +in the template. These comments are embedded in the template output +using the format defined in the DEBUG_FORMAT configuration item, or a +simple default format if unspecified. + +For example, the following template fragment: + + + Hello World + +would generate this output: + + ## input text line 1 : ## + Hello + ## input text line 2 : World ## + World + +=item DEBUG_ALL + +Enables all debugging messages. + +=item DEBUG_CALLER + +This option causes all debug messages that aren't newline terminated +to have the file name and line number of the caller appended to them. + + +=back + +=item DEBUG_FORMAT + +The DEBUG_FORMAT option can be used to specify a format string for the +debugging messages generated via the DEBUG_DIRS option described +above. Any occurances of C<$file>, C<$line> or C<$text> will be +replaced with the current file name, line or directive text, +respectively. Notice how the format is single quoted to prevent Perl +from interpolating those tokens as variables. + + my $template = Template->new({ + DEBUG => 'dirs', + DEBUG_FORMAT => '<!-- $file line $line : [% $text %] -->', + }); + +The following template fragment: + + [% foo = 'World' %] + Hello [% foo %] + +would then generate this output: + + <!-- input text line 2 : [% foo = 'World' %] --> + Hello <!-- input text line 3 : [% foo %] -->World + +The DEBUG directive can also be used to set a debug format within +a template. + + [% DEBUG format '<!-- $file line $line : [% $text %] -->' %] + + +=back + +=head2 Caching and Compiling Options + +=over 4 + + + +=item CACHE_SIZE + +The Template::Provider module caches compiled templates to avoid the need +to re-parse template files or blocks each time they are used. The CACHE_SIZE +option is used to limit the number of compiled templates that the module +should cache. + +By default, the CACHE_SIZE is undefined and all compiled templates are +cached. When set to any positive value, the cache will be limited to +storing no more than that number of compiled templates. When a new +template is loaded and compiled and the cache is full (i.e. the number +of entries == CACHE_SIZE), the least recently used compiled template +is discarded to make room for the new one. + +The CACHE_SIZE can be set to 0 to disable caching altogether. + + my $template = Template->new({ + CACHE_SIZE => 64, # only cache 64 compiled templates + }); + + my $template = Template->new({ + CACHE_SIZE => 0, # don't cache any compiled templates + }); + + + + + + +=item COMPILE_EXT + +From version 2 onwards, the Template Toolkit has the ability to +compile templates to Perl code and save them to disk for subsequent +use (i.e. cache persistence). The COMPILE_EXT option may be +provided to specify a filename extension for compiled template files. +It is undefined by default and no attempt will be made to read or write +any compiled template files. + + my $template = Template->new({ + COMPILE_EXT => '.ttc', + }); + +If COMPILE_EXT is defined (and COMPILE_DIR isn't, see below) then compiled +template files with the COMPILE_EXT extension will be written to the same +directory from which the source template files were loaded. + +Compiling and subsequent reuse of templates happens automatically +whenever the COMPILE_EXT or COMPILE_DIR options are set. The Template +Toolkit will automatically reload and reuse compiled files when it +finds them on disk. If the corresponding source file has been modified +since the compiled version as written, then it will load and re-compile +the source and write a new compiled version to disk. + +This form of cache persistence offers significant benefits in terms of +time and resources required to reload templates. Compiled templates can +be reloaded by a simple call to Perl's require(), leaving Perl to handle +all the parsing and compilation. This is a Good Thing. + +=item COMPILE_DIR + +The COMPILE_DIR option is used to specify an alternate directory root +under which compiled template files should be saved. + + my $template = Template->new({ + COMPILE_DIR => '/tmp/ttc', + }); + +The COMPILE_EXT option may also be specified to have a consistent file +extension added to these files. + + my $template1 = Template->new({ + COMPILE_DIR => '/tmp/ttc', + COMPILE_EXT => '.ttc1', + }); + + my $template2 = Template->new({ + COMPILE_DIR => '/tmp/ttc', + COMPILE_EXT => '.ttc2', + }); + + +When COMPILE_EXT is undefined, the compiled template files have the +same name as the original template files, but reside in a different +directory tree. + +Each directory in the INCLUDE_PATH is replicated in full beneath the +COMPILE_DIR directory. This example: + + my $template = Template->new({ + COMPILE_DIR => '/tmp/ttc', + INCLUDE_PATH => '/home/abw/templates:/usr/share/templates', + }); + +would create the following directory structure: + + /tmp/ttc/home/abw/templates/ + /tmp/ttc/usr/share/templates/ + +Files loaded from different INCLUDE_PATH directories will have their +compiled forms save in the relevant COMPILE_DIR directory. + +On Win32 platforms a filename may by prefixed by a drive letter and +colon. e.g. + + C:/My Templates/header + +The colon will be silently stripped from the filename when it is added +to the COMPILE_DIR value(s) to prevent illegal filename being generated. +Any colon in COMPILE_DIR elements will be left intact. For example: + + # Win32 only + my $template = Template->new({ + DELIMITER => ';', + COMPILE_DIR => 'C:/TT2/Cache', + INCLUDE_PATH => 'C:/TT2/Templates;D:/My Templates', + }); + +This would create the following cache directories: + + C:/TT2/Cache/C/TT2/Templates + C:/TT2/Cache/D/My Templates + + +=back + +=head2 Plugins and Filters + +=over 4 + + + +=item PLUGINS + +The PLUGINS options can be used to provide a reference to a hash array +that maps plugin names to Perl module names. A number of standard +plugins are defined (e.g. 'table', 'cgi', 'dbi', etc.) which map to +their corresponding Template::Plugin::* counterparts. These can be +redefined by values in the PLUGINS hash. + + my $template = Template->new({ + PLUGINS => { + cgi => 'MyOrg::Template::Plugin::CGI', + foo => 'MyOrg::Template::Plugin::Foo', + bar => 'MyOrg::Template::Plugin::Bar', + }, + }); + +The USE directive is used to create plugin objects and does so by +calling the plugin() method on the current Template::Context object. +If the plugin name is defined in the PLUGINS hash then the +corresponding Perl module is loaded via require(). The context then +calls the load() class method which should return the class name +(default and general case) or a prototype object against which the +new() method can be called to instantiate individual plugin objects. + +If the plugin name is not defined in the PLUGINS hash then the PLUGIN_BASE +and/or LOAD_PERL options come into effect. + + + + + +=item PLUGIN_BASE + +If a plugin is not defined in the PLUGINS hash then the PLUGIN_BASE is used +to attempt to construct a correct Perl module name which can be successfully +loaded. + +The PLUGIN_BASE can be specified as a single value or as a reference +to an array of multiple values. The default PLUGIN_BASE value, +'Template::Plugin', is always added the the end of the PLUGIN_BASE +list (a single value is first converted to a list). Each value should +contain a Perl package name to which the requested plugin name is +appended. + +example 1: + + my $template = Template->new({ + PLUGIN_BASE => 'MyOrg::Template::Plugin', + }); + + [% USE Foo %] # => MyOrg::Template::Plugin::Foo + or Template::Plugin::Foo + +example 2: + + my $template = Template->new({ + PLUGIN_BASE => [ 'MyOrg::Template::Plugin', + 'YourOrg::Template::Plugin' ], + }); + + [% USE Foo %] # => MyOrg::Template::Plugin::Foo + or YourOrg::Template::Plugin::Foo + or Template::Plugin::Foo + + + + + + +=item LOAD_PERL + +If a plugin cannot be loaded using the PLUGINS or PLUGIN_BASE +approaches then the provider can make a final attempt to load the +module without prepending any prefix to the module path. This allows +regular Perl modules (i.e. those that don't reside in the +Template::Plugin or some other such namespace) to be loaded and used +as plugins. + +By default, the LOAD_PERL option is set to 0 and no attempt will be made +to load any Perl modules that aren't named explicitly in the PLUGINS +hash or reside in a package as named by one of the PLUGIN_BASE +components. + +Plugins loaded using the PLUGINS or PLUGIN_BASE receive a reference to +the current context object as the first argument to the new() +constructor. Modules loaded using LOAD_PERL are assumed to not +conform to the plugin interface. They must provide a new() class +method for instantiating objects but it will not receive a reference +to the context as the first argument. Plugin modules should provide a +load() class method (or inherit the default one from the +Template::Plugin base class) which is called the first time the plugin +is loaded. Regular Perl modules need not. In all other respects, +regular Perl objects and Template Toolkit plugins are identical. + +If a particular Perl module does not conform to the common, but not +unilateral, new() constructor convention then a simple plugin wrapper +can be written to interface to it. + + + + +=item FILTERS + +The FILTERS option can be used to specify custom filters which can +then be used with the FILTER directive like any other. These are +added to the standard filters which are available by default. Filters +specified via this option will mask any standard filters of the same +name. + +The FILTERS option should be specified as a reference to a hash array +in which each key represents the name of a filter. The corresponding +value should contain a reference to an array containing a subroutine +reference and a flag which indicates if the filter is static (0) or +dynamic (1). A filter may also be specified as a solitary subroutine +reference and is assumed to be static. + + $template = Template->new({ + FILTERS => { + 'sfilt1' => \&static_filter, # static + 'sfilt2' => [ \&static_filter, 0 ], # same as above + 'dfilt1' => [ \&dyanamic_filter_factory, 1 ], + }, + }); + +Additional filters can be specified at any time by calling the +define_filter() method on the current Template::Context object. +The method accepts a filter name, a reference to a filter +subroutine and an optional flag to indicate if the filter is +dynamic. + + my $context = $template->context(); + $context->define_filter('new_html', \&new_html); + $context->define_filter('new_repeat', \&new_repeat, 1); + +Static filters are those where a single subroutine reference is used +for all invocations of a particular filter. Filters that don't accept +any configuration parameters (e.g. 'html') can be implemented +statically. The subroutine reference is simply returned when that +particular filter is requested. The subroutine is called to filter +the output of a template block which is passed as the only argument. +The subroutine should return the modified text. + + sub static_filter { + my $text = shift; + # do something to modify $text... + return $text; + } + +The following template fragment: + + [% FILTER sfilt1 %] + Blah blah blah. + [% END %] + +is approximately equivalent to: + + &static_filter("\nBlah blah blah.\n"); + +Filters that can accept parameters (e.g. 'truncate') should be +implemented dynamically. In this case, the subroutine is taken to be +a filter 'factory' that is called to create a unique filter subroutine +each time one is requested. A reference to the current +Template::Context object is passed as the first parameter, followed by +any additional parameters specified. The subroutine should return +another subroutine reference (usually a closure) which implements the +filter. + + sub dynamic_filter_factory { + my ($context, @args) = @_; + + return sub { + my $text = shift; + # do something to modify $text... + return $text; + } + } + +The following template fragment: + + [% FILTER dfilt1(123, 456) %] + Blah blah blah + [% END %] + +is approximately equivalent to: + + my $filter = &dynamic_filter_factory($context, 123, 456); + &$filter("\nBlah blah blah.\n"); + +See the FILTER directive for further examples. + + +=back + +=head2 Compatibility, Customisation and Extension + +=over 4 + + + +=item V1DOLLAR + +In version 1 of the Template Toolkit, an optional leading '$' could be placed +on any template variable and would be silently ignored. + + # VERSION 1 + [% $foo %] === [% foo %] + [% $hash.$key %] === [% hash.key %] + +To interpolate a variable value the '${' ... '}' construct was used. +Typically, one would do this to index into a hash array when the key +value was stored in a variable. + +example: + + my $vars = { + users => { + aba => { name => 'Alan Aardvark', ... }, + abw => { name => 'Andy Wardley', ... }, + ... + }, + uid => 'aba', + ... + }; + + $template->process('user/home.html', $vars) + || die $template->error(), "\n"; + +'user/home.html': + + [% user = users.${uid} %] # users.aba + Name: [% user.name %] # Alan Aardvark + +This was inconsistent with double quoted strings and also the +INTERPOLATE mode, where a leading '$' in text was enough to indicate a +variable for interpolation, and the additional curly braces were used +to delimit variable names where necessary. Note that this use is +consistent with UNIX and Perl conventions, among others. + + # double quoted string interpolation + [% name = "$title ${user.name}" %] + + # INTERPOLATE = 1 + <img src="$images/help.gif"></a> + <img src="$images/${icon.next}.gif"> + +For version 2, these inconsistencies have been removed and the syntax +clarified. A leading '$' on a variable is now used exclusively to +indicate that the variable name should be interpolated +(e.g. subsituted for its value) before being used. The earlier example +from version 1: + + # VERSION 1 + [% user = users.${uid} %] + Name: [% user.name %] + +can now be simplified in version 2 as: + + # VERSION 2 + [% user = users.$uid %] + Name: [% user.name %] + +The leading dollar is no longer ignored and has the same effect of +interpolation as '${' ... '}' in version 1. The curly braces may +still be used to explicitly scope the interpolated variable name +where necessary. + +e.g. + + [% user = users.${me.id} %] + Name: [% user.name %] + +The rule applies for all variables, both within directives and in +plain text if processed with the INTERPOLATE option. This means that +you should no longer (if you ever did) add a leading '$' to a variable +inside a directive, unless you explicitly want it to be interpolated. + +One obvious side-effect is that any version 1 templates with variables +using a leading '$' will no longer be processed as expected. Given +the following variable definitions, + + [% foo = 'bar' + bar = 'baz' + %] + +version 1 would interpret the following as: + + # VERSION 1 + [% $foo %] => [% GET foo %] => bar + +whereas version 2 interprets it as: + + # VERSION 2 + [% $foo %] => [% GET $foo %] => [% GET bar %] => baz + +In version 1, the '$' is ignored and the value for the variable 'foo' is +retrieved and printed. In version 2, the variable '$foo' is first interpolated +to give the variable name 'bar' whose value is then retrieved and printed. + +The use of the optional '$' has never been strongly recommended, but +to assist in backwards compatibility with any version 1 templates that +may rely on this "feature", the V1DOLLAR option can be set to 1 +(default: 0) to revert the behaviour and have leading '$' characters +ignored. + + my $template = Template->new({ + V1DOLLAR => 1, + }); + + + + +=item LOAD_TEMPLATES + +The LOAD_TEMPLATE option can be used to provide a reference to a list +of Template::Provider objects or sub-classes thereof which will take +responsibility for loading and compiling templates. + + my $template = Template->new({ + LOAD_TEMPLATES => [ + MyOrg::Template::Provider->new({ ... }), + Template::Provider->new({ ... }), + ], + }); + +When a PROCESS, INCLUDE or WRAPPER directive is encountered, the named +template may refer to a locally defined BLOCK or a file relative to +the INCLUDE_PATH (or an absolute or relative path if the appropriate +ABSOLUTE or RELATIVE options are set). If a BLOCK definition can't be +found (see the Template::Context template() method for a discussion of +BLOCK locality) then each of the LOAD_TEMPLATES provider objects is +queried in turn via the fetch() method to see if it can supply the +required template. Each provider can return a compiled template, an +error, or decline to service the request in which case the +responsibility is passed to the next provider. If none of the +providers can service the request then a 'not found' error is +returned. The same basic provider mechanism is also used for the +INSERT directive but it bypasses any BLOCK definitions and doesn't +attempt is to parse or process the contents of the template file. + +This is an implementation of the 'Chain of Responsibility' +design pattern as described in +"Design Patterns", Erich Gamma, Richard Helm, Ralph Johnson, John +Vlissides), Addision-Wesley, ISBN 0-201-63361-2, page 223 +. + +If LOAD_TEMPLATES is undefined, a single default provider will be +instantiated using the current configuration parameters. For example, +the Template::Provider INCLUDE_PATH option can be specified in the Template configuration and will be correctly passed to the provider's +constructor method. + + my $template = Template->new({ + INCLUDE_PATH => '/here:/there', + }); + + + + + +=item LOAD_PLUGINS + +The LOAD_PLUGINS options can be used to specify a list of provider +objects (i.e. they implement the fetch() method) which are responsible +for loading and instantiating template plugin objects. The +Template::Content plugin() method queries each provider in turn in a +"Chain of Responsibility" as per the template() and filter() methods. + + my $template = Template->new({ + LOAD_PLUGINS => [ + MyOrg::Template::Plugins->new({ ... }), + Template::Plugins->new({ ... }), + ], + }); + +By default, a single Template::Plugins object is created using the +current configuration hash. Configuration items destined for the +Template::Plugins constructor may be added to the Template +constructor. + + my $template = Template->new({ + PLUGIN_BASE => 'MyOrg::Template::Plugins', + LOAD_PERL => 1, + }); + + + + + +=item LOAD_FILTERS + +The LOAD_FILTERS option can be used to specify a list of provider +objects (i.e. they implement the fetch() method) which are responsible +for returning and/or creating filter subroutines. The +Template::Context filter() method queries each provider in turn in a +"Chain of Responsibility" as per the template() and plugin() methods. + + my $template = Template->new({ + LOAD_FILTERS => [ + MyTemplate::Filters->new(), + Template::Filters->new(), + ], + }); + +By default, a single Template::Filters object is created for the +LOAD_FILTERS list. + + + + + +=item TOLERANT + +The TOLERANT flag is used by the various Template Toolkit provider +modules (Template::Provider, Template::Plugins, Template::Filters) to +control their behaviour when errors are encountered. By default, any +errors are reported as such, with the request for the particular +resource (template, plugin, filter) being denied and an exception +raised. When the TOLERANT flag is set to any true values, errors will +be silently ignored and the provider will instead return +STATUS_DECLINED. This allows a subsequent provider to take +responsibility for providing the resource, rather than failing the +request outright. If all providers decline to service the request, +either through tolerated failure or a genuine disinclination to +comply, then a 'E<lt>resourceE<gt> not found' exception is raised. + + + + + + +=item SERVICE + +A reference to a Template::Service object, or sub-class thereof, to which +the Template module should delegate. If unspecified, a Template::Service +object is automatically created using the current configuration hash. + + my $template = Template->new({ + SERVICE => MyOrg::Template::Service->new({ ... }), + }); + + + + + +=item CONTEXT + +A reference to a Template::Context object which is used to define a +specific environment in which template are processed. A Template::Context +object is passed as the only parameter to the Perl subroutines that +represent "compiled" template documents. Template subroutines make +callbacks into the context object to access Template Toolkit functionality, +for example, to to INCLUDE or PROCESS another template (include() and +process() methods, respectively), to USE a plugin (plugin()) or +instantiate a filter (filter()) or to access the stash (stash()) which +manages variable definitions via the get() and set() methods. + + my $template = Template->new({ + CONTEXT => MyOrg::Template::Context->new({ ... }), + }); + + + +=item STASH + +A reference to a Template::Stash object or sub-class which will take +responsibility for managing template variables. + + my $stash = MyOrg::Template::Stash->new({ ... }); + my $template = Template->new({ + STASH => $stash, + }); + +If unspecified, a default stash object is created using the VARIABLES +configuration item to initialise the stash variables. These may also +be specified as the PRE_DEFINE option for backwards compatibility with +version 1. + + my $template = Template->new({ + VARIABLES => { + id => 'abw', + name => 'Andy Wardley', + }, + }; + + + + + +=item PARSER + +The Template::Parser module implements a parser object for compiling +templates into Perl code which can then be executed. A default object +of this class is created automatically and then used by the +Template::Provider whenever a template is loaded and requires +compilation. The PARSER option can be used to provide a reference to +an alternate parser object. + + my $template = Template->new({ + PARSER => MyOrg::Template::Parser->new({ ... }), + }); + + + + + +=item GRAMMAR + +The GRAMMAR configuration item can be used to specify an alternate +grammar for the parser. This allows a modified or entirely new +template language to be constructed and used by the Template Toolkit. + +Source templates are compiled to Perl code by the Template::Parser +using the Template::Grammar (by default) to define the language +structure and semantics. Compiled templates are thus inherently +"compatible" with each other and there is nothing to prevent any +number of different template languages being compiled and used within +the same Template Toolkit processing environment (other than the usual +time and memory constraints). + +The Template::Grammar file is constructed from a YACC like grammar +(using Parse::YAPP) and a skeleton module template. These files are +provided, along with a small script to rebuild the grammar, in the +'parser' sub-directory of the distribution. You don't have to know or +worry about these unless you want to hack on the template language or +define your own variant. There is a README file in the same directory +which provides some small guidance but it is assumed that you know +what you're doing if you venture herein. If you grok LALR parsers, +then you should find it comfortably familiar. + +By default, an instance of the default Template::Grammar will be +created and used automatically if a GRAMMAR item isn't specified. + + use MyOrg::Template::Grammar; + + my $template = Template->new({ + GRAMMAR = MyOrg::Template::Grammar->new(); + }); + + + +=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.13, released on 30 January 2004. + +=head1 COPYRIGHT + + Copyright (C) 1996-2004 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. + + + +=cut + +# Local Variables: +# mode: perl +# perl-indent-level: 4 +# indent-tabs-mode: nil +# End: +# +# vim: expandtab shiftwidth=4: diff --git a/lib/Template/Manual/Credits.pod b/lib/Template/Manual/Credits.pod new file mode 100644 index 0000000..64999ac --- /dev/null +++ b/lib/Template/Manual/Credits.pod @@ -0,0 +1,188 @@ +#============================================================= -*-perl-*- +# +# Template::Manual::Credits +# +# DESCRIPTION +# This section provides a brief history of the Template Toolkit and +# details the primary author and numerous other people who have +# contributed to it. +# +# AUTHOR +# Andy Wardley <abw@andywardley.com> +# +# COPYRIGHT +# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved. +# Copyright (C) 1998-2001 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 +# +# +#======================================================================== + + +#------------------------------------------------------------------------ +# 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::Manual::Credits - Author and contributor credits + +=head1 DESCRIPTION + +This section provides a brief history of the Template Toolkit and +details the primary author and numerous other people who have +contributed to it. + +=head1 HISTORY + +The Template Toolkit began its life as the Text::MetaText module, +originally released to CPAN around 1996. This itself was the public +manifestation of an earlier template processing system I developed +while working at Peritas (now Knowledge Pool - + http://www.knowledgepool.com/) + +Text::MetaText was the prototype - the one we always planned to throw +away. It did the job well, showing us what worked and what didn't, what +was good and what was bad, and gave us some ideas about what could be +done better, given the chance to start again from scratch. + +Some time late in 1998 I threw away the prototype and started work on +the Template Toolkit. By then I was working at Canon Research Centre +Europe Ltd. (http://www.cre.canon.co.uk), involved in a general +research programme related to web publishing and dynamic content +generation. The first alpha release was in June 1999, followed by +numerous more alpha and beta releases culminating in 1.00 being +released on 2nd December 1999. + +A month or so later, work had begun on version 2.00. The plan was to +get the template language relatively stable in version 1.00 and not +worry too much about performance or other internal matters. Then, +version 2.00 would follow to improve performance, clean up the +architecture and fix anything that, with the benefit of hindsight, we +thought could be improved. As it happens, me starting work on version +2.00 coincided with Doug Steinwand sending me his parser variant which +compiled templates to Perl code, giving a major performance boost. +As well as the speedups, there are a whole host of significant new +features in version 2.00, and a greatly improved internal architecture. +Apart from a few minor "fixups" the template directives and language +have remained the same as in version 1.00 + +Version 2.00 was available in beta release form in July 2000, just +in time for the 4th Perl Conference where version 1.00 was awarded +"Best New Perl Module". After another extended beta release period, +version 2.00 was released on 1st December 2000. + + + + +=head1 CONTRIBUTORS + +Many people have contributed ideas, inspiration, fixes and features to +the Template Toolkit. Their efforts continue to be very much appreciated. +Please let me know if you think anyone is missing from this list. + + Chuck Adams <scrytch@uswest.net> + Stephen Adkins <stephen.adkins@officevision.com> + Ivan Adzhubey <iadzhubey@rics.bwh.harvard.edu> + Mark Anderson <mda@discerning.com> + Bradley Baetz <bbaetz@student.usyd.edu.au> + Thierry-Michel Barral <kktos@electron-libre.com> + Craig Barratt <craig@arraycomm.com> + Stas Bekman <stas@stason.org> + Tony Bowden <tony-tt@kasei.com> + Neil Bowers <neilb@cre.canon.co.uk> + Leon Brocard <acme@astray.com> + Lyle Brooks <brooks@deseret.com> + Dave Cash <dave@gnofn.org> + Piers Cawley <pdcawley@bofh.org.uk> + Darren Chamberlain <dlc@users.sourceforge.net> + Eric Cholet <cholet@logilune.com> + Dave Cross <dave@dave.org.uk> + Chris Dean <ctdean@babycenter.com> + Francois Desarmenien <desar@club-internet.fr> + Horst Dumcke <hdumcke@cisco.com> + Mark Fowler <mark@indicosoftware.com> + Michael Fowler <michael@shoebox.net> + Axel Gerstmair <anthill@web.de> + Dylan William Hardison <dylanwh@tampabay.rr.com> + Perrin Harkins <pharkins@etoys.com> + Bryce Harrington <bryce@osdl.org> + Dave Hodgkinson <daveh@davehodgkinson.com> + Harald Joerg <Harald.Joerg@fujitsu-siemens.com> + Colin Johnson <colin@knowledgepool.com> + Vivek Khera <khera@kciLink.com> + Rafael Kitover <caelum@debian.org> + Ivan Kurmanov <http://www.ahinea.com> + Hans von Lengerke <hans@lengerke.org> + Jonas Liljegren <jonas@paranormal.se> + Simon Luff <simon@sports.com> + Paul Makepeace <Paul.Makepeace@realprogrammers.com> + Gervase Markham <gerv@mozilla.org> + Simon Matthews <sam@knowledgepool.com> + Robert McArthur <mcarthur@dstc.edu.au> + Craig McLane <mclanec@oxy.edu> + Leslie Michael Orchard <deus_x@ninjacode.com> + Eugene Miretskiy <eugene@invision.net> + Tatsuhiko Miyagawa <miyagawa@edge.co.jp> + Keith G. Murphy <keithmur@mindspring.com> + Chris Nandor <pudge@pobox.com> + Briac Pilpré <briac@pilpre.com> + Martin Portman <mrp@cre.canon.co.uk> + Slaven Rezic <slaven.rezic@berlin.de> + Christian Schaffner <schaffner@eeh.ee.ethz.ch> + Randal L. Schwartz <merlyn@stonehenge.com> + Paul Sharpe <paul@miraclefish.com> + Ville Skyttä <ville.skytta@iki.fi> + Doug Steinwand <dsteinwand@etoys.com> + Michael Stevens <michael@etla.org> + Drew Taylor <dtaylor@vialogix.com> + Swen Thuemmler <Swen.Thuemmler@paderlinx.de> + Richard Tietjen <Richard_Tietjen@mcgraw-hill.com> + Stathy G. Touloumis <stathy.touloumis@edventions.com> + Jim Vaughan <jim@mrjim.com> + Simon Wilcox <simonw@simonwilcox.co.uk> + Chris Winters <cwinters@intes.net> + +=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.13, released on 30 January 2004. + +=head1 COPYRIGHT + + Copyright (C) 1996-2004 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. + + + +=cut + +# Local Variables: +# mode: perl +# perl-indent-level: 4 +# indent-tabs-mode: nil +# End: +# +# vim: expandtab shiftwidth=4: diff --git a/lib/Template/Manual/Directives.pod b/lib/Template/Manual/Directives.pod new file mode 100644 index 0000000..3b8af3e --- /dev/null +++ b/lib/Template/Manual/Directives.pod @@ -0,0 +1,2179 @@ +#============================================================= -*-perl-*- +# +# Template::Manual::Directives +# +# DESCRIPTION +# This section provides a reference of all Template Toolkit +# directives, complete with examples of use. +# +# AUTHOR +# Andy Wardley <abw@andywardley.com> +# +# COPYRIGHT +# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved. +# Copyright (C) 1998-2001 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 +# +# +#======================================================================== + + +#------------------------------------------------------------------------ +# 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::Manual::Directives - Template directives + +=head1 DESCRIPTION + +This section provides a reference of all Template Toolkit directives, +complete with examples of use. + +=head2 Accessing and Updating Template Variables + +=over 4 + + +=item GET + +The GET directive retrieves and outputs the value of the named variable. + + [% GET foo %] + +The GET keyword is optional. A variable can be specified in a directive +tag by itself. + + [% foo %] + +The variable can have an unlimited number of elements, each separated +by a dot '.'. Each element can have arguments specified within +parentheses. + + [% foo %] + [% bar.baz %] + [% biz.baz(10) %] + ...etc... + +See L<Template::Manual::Variables> for a full discussion on template +variables. + +You can also specify expressions using the logical (and, or, not, ?:) and +mathematic operators (+ - * / % mod div). + + [% template.title or default.title %] + + [% score * 100 %] + + [% order.nitems ? checkout(order.total) : 'no items' %] + +The 'div' operator returns the integer result of division. Both '%' and +'mod' return the modulus (i.e. remainder) of division. 'mod' is provided +as an alias for '%' for backwards compatibility with version 1. + + [% 15 / 6 %] # 2.5 + [% 15 div 6 %] # 2 + [% 15 mod 6 %] # 3 + + + +=item CALL + +The CALL directive is similar to GET in evaluating the variable named, +but doesn't print the result returned. This can be useful when a +variable is bound to a sub-routine or object method which you want to +call but aren't interested in the value returned. + + [% CALL dbi.disconnect %] + + [% CALL inc_page_counter(page_count) %] + + + + +=item SET + +The SET directive allows you to assign new values to existing variables +or create new temporary variables. + + [% SET title = 'Hello World' %] + +The SET keyword is also optional. + + [% title = 'Hello World' %] + +Variables may be assigned the values of other variables, unquoted +numbers (digits), literal text ('single quotes') or quoted text +("double quotes"). In the latter case, any variable references within +the text will be interpolated when the string is evaluated. Variables +should be prefixed by '$', using curly braces to explicitly scope +the variable name where necessary. + + [% foo = 'Foo' %] # literal value 'Foo' + [% bar = foo %] # value of variable 'foo' + [% cost = '$100' %] # literal value '$100' + [% item = "$bar: ${cost}.00" %] # value "Foo: $100.00" + +Multiple variables may be assigned in the same directive and are +evaluated in the order specified. Thus, the above could have been +written: + + [% foo = 'Foo' + bar = foo + cost = '$100' + item = "$bar: ${cost}.00" + %] + +Simple expressions can also be used, as per GET. + + [% ten = 10 + twenty = 20 + thirty = twenty + ten + forty = 2 * twenty + fifty = 100 div 2 + six = twenty mod 7 + %] + +You can concatenate strings together using the ' _ ' operator. In Perl 5, +the '.' is used for string concatenation, but in Perl 6, as in the Template +Toolkit, the '.' will be used as the method calling operator and ' _ ' will +be used for string concatenation. Note that the operator must be +specified with surrounding whitespace which, as Larry says, is construed as +a feature: + + [% copyright = '(C) Copyright' _ year _ ' ' _ author %] + +You can, of course, achieve a similar effect with double quoted string +interpolation. + + [% copyright = "(C) Copyright $year $author" %] + + + + + +=item DEFAULT + +The DEFAULT directive is similar to SET but only updates variables +that are currently undefined or have no "true" value (in the Perl +sense). + + [% DEFAULT + name = 'John Doe' + id = 'jdoe' + %] + +This can be particularly useful in common template components to +ensure that some sensible default are provided for otherwise +undefined variables. + + [% DEFAULT + title = 'Hello World' + bgcol = '#ffffff' + %] + <html> + <head> + <title>[% title %]</title> + </head> + + <body bgcolor="[% bgcol %]"> + + +=back + +=head2 Processing Other Template Files and Blocks + +=over 4 + + +=item INSERT + +The INSERT directive is used to insert the contents of an external file +at the current position. + + [% INSERT myfile %] + +No attempt to parse or process the file is made. The contents, +possibly including any embedded template directives, are inserted +intact. + +The filename specified should be relative to one of the INCLUDE_PATH +directories. Absolute (i.e. starting with C</>) and relative +(i.e. starting with C<.>) filenames may be used if the ABSOLUTE and +RELATIVE options are set, respectively. Both these options are +disabled by default. + + my $template = Template->new({ + INCLUDE_PATH => '/here:/there', + }); + + $template->process('myfile'); + +'myfile': + + [% INSERT foo %] # looks for /here/foo then /there/foo + [% INSERT /etc/passwd %] # file error: ABSOLUTE not set + [% INSERT ../secret %] # file error: RELATIVE not set + +For convenience, the filename does not need to be quoted as long as it +contains only alphanumeric characters, underscores, dots or forward +slashes. Names containing any other characters should be quoted. + + [% INSERT misc/legalese.txt %] + [% INSERT 'dos98/Program Files/stupid' %] + +To evaluate a variable to specify a filename, you should explicitly +prefix it with a '$' or use double-quoted string interpolation. + + [% language = 'en' + legalese = 'misc/legalese.txt' + %] + + [% INSERT $legalese %] # 'misc/legalese.txt' + [% INSERT "$language/$legalese" %] # 'en/misc/legalese.txt' + +Multiple files can be specified using '+' as a delimiter. All files +should be unquoted names or quoted strings. Any variables should be +interpolated into double-quoted strings. + + [% INSERT legalese.txt + warning.txt %] + [% INSERT "$legalese" + warning.txt %] # requires quoting + + + + + + + + + + + + + + + + + +=item INCLUDE + +The INCLUDE directive is used to process and include the output of +another template file or block. + + [% INCLUDE header %] + +If a BLOCK of the specified name is defined in the same file, or in a file +from which the current template has been called (i.e. a parent template) +then it will be used in preference to any file of the same name. + + [% INCLUDE table %] # uses BLOCK defined below + + [% BLOCK table %] + <table> + ... + </table> + [% END %] + +If a BLOCK definition is not currently visible then the template name +should be a file relative to one of the INCLUDE_PATH directories, or +an absolute or relative file name if the ABSOLUTE/RELATIVE options are +appropriately enabled. The INCLUDE directive automatically quotes the +filename specified, as per INSERT described above. When a variable +contains the name of the template for the INCLUDE directive, it should +be explicitly prefixed by '$' or double-quoted + + [% myheader = 'my/misc/header' %] + [% INCLUDE myheader %] # 'myheader' + [% INCLUDE $myheader %] # 'my/misc/header' + [% INCLUDE "$myheader" %] # 'my/misc/header' + +Any template directives embedded within the file will be processed +accordingly. All variables currently defined will be visible and +accessible from within the included template. + + [% title = 'Hello World' %] + [% INCLUDE header %] + <body> + ... + +'header': + + <html> + <title>[% title %]</title> + +output: + + <html> + <title>Hello World</title> + <body> + ... + +Local variable definitions may be specified after the template name, +temporarily masking any existing variables. Insignificant whitespace +is ignored within directives so you can add variable definitions on the +same line, the next line or split across several line with comments +interspersed, if you prefer. + + [% INCLUDE table %] + + [% INCLUDE table title="Active Projects" %] + + [% INCLUDE table + title = "Active Projects" + bgcolor = "#80ff00" # chartreuse + border = 2 + %] + +The INCLUDE directive localises (i.e. copies) all variables before +processing the template. Any changes made within the included +template will not affect variables in the including template. + + [% foo = 10 %] + + foo is originally [% foo %] + [% INCLUDE bar %] + foo is still [% foo %] + + [% BLOCK bar %] + foo was [% foo %] + [% foo = 20 %] + foo is now [% foo %] + [% END %] + +output: + foo is originally 10 + foo was 10 + foo is now 20 + foo is still 10 + +Technical Note: the localisation of the stash (that is, the process by +which variables are copied before an INCLUDE to prevent being +overwritten) is only skin deep. The top-level variable namespace +(hash) is copied, but no attempt is made to perform a deep-copy of +other structures (hashes, arrays, objects, etc.) Therefore, a 'foo' +variable referencing a hash will be copied to create a new 'foo' +variable but which points to the same hash array. Thus, if you update +compound variables (e.g. foo.bar) then you will change the original +copy, regardless of any stash localisation. If you're not worried +about preserving variable values, or you trust the templates you're +including then you might prefer to use the PROCESS directive which is +faster by virtue of not performing any localisation. + +From version 2.04 onwards, you can specify dotted variables as "local" +variables to an INCLUDE directive. However, be aware that because of +the localisation issues explained above (if you skipped the previous +Technical Note above then you might want to go back and read it or +skip this section too), the variables might not actualy be "local". +If the first element of the variable name already references a hash +array then the variable update will affect the original variable. + + [% foo = { + bar = 'Baz' + } + %] + + [% INCLUDE somefile foo.bar='Boz' %] + + [% foo.bar %] # Boz + +This behaviour can be a little unpredictable (and may well be improved +upon in a future version). If you know what you're doing with it and +you're sure that the variables in question are defined (nor not) as you +expect them to be, then you can rely on this feature to implement some +powerful "global" data sharing techniques. Otherwise, you might prefer +to steer well clear and always pass simple (undotted) variables as +parameters to INCLUDE and other similar directives. + +If you want to process several templates in one go then you can +specify each of their names (quoted or unquoted names only, no unquoted +'$variables') joined together by '+'. The INCLUDE directive +will then process them in order. + + [% INCLUDE html/header + "site/$header" + site/menu + title = "My Groovy Web Site" + %] + +The variable stash is localised once and then the templates specified +are processed in order, all within that same variable context. This +makes it slightly faster than specifying several separate INCLUDE +directives (because you only clone the variable stash once instead of +n times), but not quite as "safe" because any variable changes in the +first file will be visible in the second, third and so on. This +might be what you want, of course, but then again, it might not. + + + +=item PROCESS + +The PROCESS directive is similar to INCLUDE but does not perform any +localisation of variables before processing the template. Any changes +made to variables within the included template will be visible in the +including template. + + [% foo = 10 %] + + foo is [% foo %] + [% PROCESS bar %] + foo is [% foo %] + + [% BLOCK bar %] + [% foo = 20 %] + changed foo to [% foo %] + [% END %] + +output: + + foo is 10 + changed foo to 20 + foo is 20 + +Parameters may be specified in the PROCESS directive, but these too will +become visible changes to current variable values. + + [% foo = 10 %] + foo is [% foo %] + [% PROCESS bar + foo = 20 + %] + foo is [% foo %] + + [% BLOCK bar %] + this is bar, foo is [% foo %] + [% END %] + +output: + + foo is 10 + this is bar, foo is 20 + foo is 20 + +The PROCESS directive is slightly faster than INCLUDE because it +avoids the need to localise (i.e. copy) the variable stash before +processing the template. As with INSERT and INCLUDE, the first +parameter does not need to be quoted as long as it contains only +alphanumeric characters, underscores, periods or forward slashes. +A '$' prefix can be used to explicitly indicate a variable which +should be interpolated to provide the template name: + + [% myheader = 'my/misc/header' %] + [% PROCESS myheader %] # 'myheader' + [% PROCESS $myheader %] # 'my/misc/header' + +As with INCLUDE, multiple templates can be specified, delimited by +'+', and are processed in order. + + [% PROCESS html/header + my/header %] + + + + + +=item WRAPPER + +It's not unusual to find yourself adding common headers and footers to +pages or sub-sections within a page. Something like this: + + [% INCLUDE section/header + title = 'Quantum Mechanics' + %] + Quantum mechanics is a very interesting subject wish + should prove easy for the layman to fully comprehend. + [% INCLUDE section/footer %] + + [% INCLUDE section/header + title = 'Desktop Nuclear Fusion for under $50' + %] + This describes a simple device which generates significant + sustainable electrical power from common tap water by process + of nuclear fusion. + [% INCLUDE section/footer %] + +The individual template components being included might look like these: + +section/header: + + <p> + <h2>[% title %]</h2> + +section/footer: + + </p> + +The WRAPPER directive provides a way of simplifying this a little. It +encloses a block up to a matching END directive, which is first +processed to generate some output. This is then passed to the named +template file or BLOCK as the 'content' variable. + + [% WRAPPER section + title = 'Quantum Mechanics' + %] + Quantum mechanics is a very interesting subject wish + should prove easy for the layman to fully comprehend. + [% END %] + + [% WRAPPER section + title = 'Desktop Nuclear Fusion for under $50' + %] + This describes a simple device which generates significant + sustainable electrical power from common tap water by process + of nuclear fusion. + [% END %] + +The single 'section' template can then be defined as: + + <p> + <h2>[% title %]</h2> + [% content %] + </p> + +Like other block directives, it can be used in side-effect notation: + + [% INSERT legalese.txt WRAPPER big_bold_table %] + +It's also possible to specify multiple templates to a WRAPPER directive. +The specification order indicates outermost to innermost wrapper templates. +For example, given the following template block definitions: + + [% BLOCK bold %]<b>[% content %]</b>[% END %] + [% BLOCK italic %]<i>[% content %]</i>[% END %] + +the directive + + [% WRAPPER bold+italic %]Hello World[% END %] + +would generate the following output: + + <b><i>Hello World</i></b> + + + + + + + + + + + + + + + + + + +=item BLOCK + +The BLOCK ... END construct can be used to define template component +blocks which can be processed with the INCLUDE, PROCESS and WRAPPER +directives. + + [% BLOCK tabrow %] + <tr><td>[% name %]<td><td>[% email %]</td></tr> + [% END %] + + <table> + [% PROCESS tabrow name='Fred' email='fred@nowhere.com' %] + [% PROCESS tabrow name='Alan' email='alan@nowhere.com' %] + </table> + +A BLOCK definition can be used before it is defined, as long as the +definition resides in the same file. The block definition itself does +not generate any output. + + [% PROCESS tmpblk %] + + [% BLOCK tmpblk %] This is OK [% END %] + +You can use an anonymous BLOCK to capture the output of a template +fragment. + + [% julius = BLOCK %] + And Caesar's spirit, ranging for revenge, + With Ate by his side come hot from hell, + Shall in these confines with a monarch's voice + Cry 'Havoc', and let slip the dogs of war; + That this foul deed shall smell above the earth + With carrion men, groaning for burial. + [% END %] + +Like a named block, it can contain any other template directives which +are processed when the block is defined. The output generated by the +block is then assigned to the variable 'julius'. + +Anonymous BLOCKs can also be used to define block macros. The +enclosing block is processed each time the macro is called. + + [% MACRO locate BLOCK %] + The [% animal %] sat on the [% place %]. + [% END %] + + [% locate(animal='cat', place='mat') %] # The cat sat on the mat + [% locate(animal='dog', place='log') %] # The dog sat on the log + + + +=back + +=head2 Conditional Processing + +=over 4 + + +=item IF / UNLESS / ELSIF / ELSE + +The IF and UNLESS directives can be used to process or ignore a +block based on some run-time condition. + + [% IF frames %] + [% INCLUDE frameset %] + [% END %] + + [% UNLESS text_mode %] + [% INCLUDE biglogo %] + [% END %] + +Multiple conditions may be joined with ELSIF and/or ELSE blocks. + + [% IF age < 10 %] + Hello [% name %], does your mother know you're + using her AOL account? + [% ELSIF age < 18 %] + Sorry, you're not old enough to enter + (and too dumb to lie about your age) + [% ELSE %] + Welcome [% name %]. + [% END %] + +The following conditional and boolean operators may be used: + + == != < <= > >= && || ! and or not + +Note that C<and>, C<or> and C<not> are also provided as aliases for +C<&&>, C<||> and C<!>, respectively. + +Conditions may be arbitrarily complex and are evaluated with the same +precedence as in Perl. Parenthesis may be used to explicitly +determine evaluation order. + + # ridiculously contrived complex example + [% IF (name == 'admin' || uid <= 0) && mode == 'debug' %] + I'm confused. + [% ELSIF more > less %] + That's more or less correct. + [% END %] + + + + + + +=item SWITCH / CASE + +The SWITCH / CASE construct can be used to perform a multi-way +conditional test. The SWITCH directive expects an expression which is +first evaluated and then compared against each CASE statement in turn. +Each CASE directive should contain a single value or a list of values +which should match. CASE may also be left blank or written as [% CASE +DEFAULT %] to specify a default match. Only one CASE matches, there +is no drop-through between CASE statements. + + [% SWITCH myvar %] + [% CASE value1 %] + ... + [% CASE [ value2 value3 ] %] # multiple values + ... + [% CASE myhash.keys %] # ditto + ... + [% CASE %] # default + ... + [% END %] + + + + +=back + +=head2 Loop Processing + +=over 4 + + +=item FOREACH + +The FOREACH directive will iterate through the items in a list, processing +the enclosed block for each one. + + my $vars = { + foo => 'Foo', + items => [ 'one', 'two', 'three' ], + }; + +template: + + Things: + [% FOREACH thing = [ foo 'Bar' "$foo Baz" ] %] + * [% thing %] + [% END %] + + Items: + [% FOREACH i = items %] + * [% i %] + [% END %] + + Stuff: + [% stuff = [ foo "$foo Bar" ] %] + [% FOREACH s = stuff %] + * [% s %] + [% END %] + +output: + + Things: + * Foo + * Bar + * Foo Baz + + Items: + * one + * two + * three + + Stuff: + * Foo + * Foo Bar + +You can use also use 'IN' instead of '=' if you prefer. + + [% FOREACH crook IN government %] + +When the FOREACH directive is used without specifying a target variable, +any iterated values which are hash references will be automatically +imported. + + [% userlist = [ + { id => 'tom', name => 'Thomas' }, + { id => 'dick', name => 'Richard' }, + { id => 'larry', name => 'Lawrence' }, + ] + %] + + [% FOREACH user IN userlist %] + [% user.id %] [% user.name %] + [% END %] + +short form: + + [% FOREACH userlist %] + [% id %] [% name %] + [% END %] + +Note that this particular usage creates a localised variable context +to prevent the imported hash keys from overwriting any existing +variables. The imported definitions and any other variables defined +in such a FOREACH loop will be lost at the end of the loop, when the +previous context and variable values are restored. + +However, under normal operation, the loop variable remains in scope +after the FOREACH loop has ended (caveat: overwriting any variable +previously in scope). This is useful as the loop variable is secretly +an iterator object (see below) and can be used to analyse the last +entry processed by the loop. + +The FOREACH directive can also be used to iterate through the entries +in a hash array. Each entry in the hash is returned in sorted order +(based on the key) as a hash array containing 'key' and 'value' items. + + [% users = { + tom => 'Thomas', + dick => 'Richard', + larry => 'Lawrence', + } + %] + + [% FOREACH u IN users %] + * [% u.key %] : [% u.value %] + [% END %] + +Output: + + * dick : Richard + * larry : Lawrence + * tom : Thomas + +The NEXT directive starts the next iteration in the FOREACH loop. + + [% FOREACH user IN userlist %] + [% NEXT IF user.isguest %] + Name: [% user.name %] Email: [% user.email %] + [% END %] + +The LAST directive can be used to prematurely exit the loop. BREAK is +also provided as an alias for LAST. + + [% FOREACH match IN results.nsort('score').reverse %] + [% LAST IF match.score < 50 %] + [% match.score %] : [% match.url %] + [% END %] + +The FOREACH directive is implemented using the Template::Iterator +module. A reference to the iterator object for a FOREACH directive is +implicitly available in the 'loop' variable. The following methods +can be called on the 'loop' iterator. + + size() number of elements in the list + max() index number of last element (size - 1) + index() index of current iteration from 0 to max() + count() iteration counter from 1 to size() (i.e. index() + 1) + first() true if the current iteration is the first + last() true if the current iteration is the last + prev() return the previous item in the list + next() return the next item in the list + +See L<Template::Iterator> for further details. + +Example: + + [% FOREACH item IN [ 'foo', 'bar', 'baz' ] -%] + [%- "<ul>\n" IF loop.first %] + <li>[% loop.count %]/[% loop.size %]: [% item %] + [%- "</ul>\n" IF loop.last %] + [% END %] + +Output: + + <ul> + <li>1/3: foo + <li>2/3: bar + <li>3/3: baz + </ul> + +Note that the number() method is supported as an alias for count() for +backwards compatibility but may be deprecated in some future version. + +Nested loops will work as expected, with the 'loop' variable correctly +referencing the innermost loop and being restored to any previous +value (i.e. an outer loop) at the end of the loop. + + [% FOREACH group IN grouplist; + # loop => group iterator + "Groups:\n" IF loop.first; + + FOREACH user IN group.userlist; + # loop => user iterator + "$loop.count: $user.name\n"; + END; + + # loop => group iterator + "End of Groups\n" IF loop.last; + END + %] + +The 'iterator' plugin can also be used to explicitly create an +iterator object. This can be useful within nested loops where you +need to keep a reference to the outer iterator within the inner loop. +The iterator plugin effectively allows you to create an iterator by a +name other than 'loop'. See Template::Plugin::Iterator for further +details. + + [% USE giter = iterator(grouplist) %] + + [% FOREACH group IN giter %] + [% FOREACH user IN group.userlist %] + user #[% loop.count %] in + group [% giter.count %] is + named [% user.name %] + [% END %] + [% END %] + + + + +=item WHILE + +The WHILE directive can be used to repeatedly process a template block +while a conditional expression evaluates true. The expression may +be arbitrarily complex as per IF / UNLESS. + + [% WHILE total < 100 %] + ... + [% total = calculate_new_total %] + [% END %] + +An assignment can be enclosed in parenthesis to evaluate the assigned +value. + + [% WHILE (user = get_next_user_record) %] + [% user.name %] + [% END %] + +The NEXT directive can be used to start the next iteration of a +WHILE loop and BREAK can be used to exit the loop, both as per FOREACH. + +The Template Toolkit uses a failsafe counter to prevent runaway WHILE +loops which would otherwise never terminate. If the loop exceeds 1000 +iterations then an 'undef' exception will be thrown, reporting the +error: + + WHILE loop terminated (> 1000 iterations) + +The $Template::Directive::WHILE_MAX variable controls this behaviour +and can be set to a higher value if necessary. + + +=back + +=head2 Filters, Plugins, Macros and Perl + +=over 4 + + +=item FILTER + +The FILTER directive can be used to post-process the output of a +block. A number of standard filters are provided with the Template +Toolkit. The 'html' filter, for example, escapes the 'E<lt>', 'E<gt>' +and '&' characters to prevent them from being interpreted as HTML tags +or entity reference markers. + + [% FILTER html %] + HTML text may have < and > characters embedded + which you want converted to the correct HTML entities. + [% END %] + +output: + + HTML text may have < and > characters embedded + which you want converted to the correct HTML entities. + +The FILTER directive can also follow various other non-block directives. +For example: + + [% INCLUDE mytext FILTER html %] + +The '|' character can also be used as an alias for 'FILTER'. + + [% INCLUDE mytext | html %] + +Multiple filters can be chained together and will be called in sequence. + + [% INCLUDE mytext FILTER html FILTER html_para %] + +or + + [% INCLUDE mytext | html | html_para %] + +Filters come in two flavours, known as 'static' or 'dynamic'. A +static filter is a simple subroutine which accepts a text string as +the only argument and returns the modified text. The 'html' filter is +an example of a static filter, implemented as: + + sub html_filter { + my $text = shift; + for ($text) { + s/&/&/g; + s/</</g; + s/>/>/g; + } + return $text; + } + +Dynamic filters can accept arguments which are specified when the filter +is called from a template. The 'repeat' filter is such an example, +accepting a numerical argument which specifies the number of times +that the input text should be repeated. + + [% FILTER repeat(3) %]blah [% END %] + +output: + + blah blah blah + +These are implemented as filter 'factories'. The factory subroutine +is passed a reference to the current Template::Context object along +with any additional arguments specified. It should then return a +subroutine reference (e.g. a closure) which implements the filter. +The 'repeat' filter factory is implemented like this: + + sub repeat_filter_factory { + my ($context, $iter) = @_; + $iter = 1 unless defined $iter; + + return sub { + my $text = shift; + $text = '' unless defined $text; + return join('\n', $text) x $iter; + } + } + +The FILTERS option, described in L<Template::Manual::Config>, allows +custom filters to be defined when a Template object is instantiated. +The Template::Context define_filter() method allows further filters +to be defined at any time. + +When using a filter, it is possible to assign an alias to it for +further use. This is most useful for dynamic filters that you want +to re-use with the same configuration. + + [% FILTER echo = repeat(2) %] + Is there anybody out there? + [% END %] + + [% FILTER echo %] + Mother, should I build a wall? + [% END %] + +Output: + + Is there anybody out there? + Is there anybody out there? + + Mother, should I build a wall? + Mother, should I build a wall? + +The FILTER directive automatically quotes the name of the filter. As +with INCLUDE et al, you can use a variable to provide the name of the +filter, prefixed by '$'. + + [% myfilter = 'html' %] + [% FILTER $myfilter %] # same as [% FILTER html %] + ... + [% END %] + +A template variable can also be used to define a static filter +subroutine. However, the Template Toolkit will automatically call any +subroutine bound to a variable and use the value returned. Thus, the +above example could be implemented as: + + my $vars = { + myfilter => sub { return 'html' }, + }; + +template: + + [% FILTER $myfilter %] # same as [% FILTER html %] + ... + [% END %] + +To define a template variable that evaluates to a subroutine reference +that can be used by the FILTER directive, you should create a +subroutine that, when called automatically by the Template Toolkit, +returns another subroutine reference which can then be used to perform +the filter operation. Note that only static filters can be +implemented in this way. + + my $vars = { + myfilter => sub { \&my_filter_sub }, + }; + + sub my_filter_sub { + my $text = shift; + # do something + return $text; + } + +template: + + [% FILTER $myfilter %] + ... + [% END %] + +Alternately, you can bless a subroutine reference into a class (any +class will do) to fool the Template Toolkit into thinking it's an +object rather than a subroutine. This will then bypass the automatic +"call-a-subroutine-to-return-a-value" magic. + + my $vars = { + myfilter => bless(\&my_filter_sub, 'anything_you_like'), + }; + +template: + + [% FILTER $myfilter %] + ... + [% END %] + +Filters bound to template variables remain local to the variable +context in which they are defined. That is, if you define a filter in +a PERL block within a template that is loaded via INCLUDE, then the +filter definition will only exist until the end of that template when +the stash is delocalised, restoring the previous variable state. If +you want to define a filter which persists for the lifetime of the +processor, or define additional dynamic filter factories, then you can +call the define_filter() method on the current Template::Context +object. + +See L<Template::Manual::Filters> for a complete list of available filters, +their descriptions and examples of use. + + + + + + +=item USE + +The USE directive can be used to load and initialise "plugin" +extension modules. + + [% USE myplugin %] + +A plugin is a regular Perl module that conforms to a particular +object-oriented interface, allowing it to be loaded into and used +automatically by the Template Toolkit. For details of this interface +and information on writing plugins, consult L<Template::Plugin>. + +The plugin name is case-sensitive and will be appended to the +PLUGIN_BASE value (default: 'Template::Plugin') to construct a full +module name. Any periods, '.', in the name will be converted to '::'. + + [% USE MyPlugin %] # => Template::Plugin::MyPlugin + [% USE Foo.Bar %] # => Template::Plugin::Foo::Bar + +Various standard plugins are included with the Template Toolkit (see +below and L<Template::Manual::Plugins>). These can be specified in lower +case and are mapped to the appropriate name. + + [% USE cgi %] # => Template::Plugin::CGI + [% USE table %] # => Template::Plugin::Table + +Any additional parameters supplied in parenthesis after the plugin +name will be also be passed to the new() constructor. A reference to +the current Template::Context object is always passed as the first +parameter. + + [% USE MyPlugin('foo', 123) %] + +equivalent to: + + Template::Plugin::MyPlugin->new($context, 'foo', 123); + +Named parameters may also be specified. These are collated into a +hash which is passed by reference as the last parameter to the +constructor, as per the general code calling interface. + + [% USE url('/cgi-bin/foo', mode='submit', debug=1) %] + +equivalent to: + + Template::Plugin::URL->new($context, '/cgi-bin/foo' + { mode => 'submit', debug => 1 }); + +The plugin may represent any data type; a simple variable, hash, list or +code reference, but in the general case it will be an object reference. +Methods can be called on the object (or the relevant members of the +specific data type) in the usual way: + + [% USE table(mydata, rows=3) %] + + [% FOREACH row = table.rows %] + <tr> + [% FOREACH item = row %] + <td>[% item %]</td> + [% END %] + </tr> + [% END %] + +An alternative name may be provided for the plugin by which it can be +referenced: + + [% USE scores = table(myscores, cols=5) %] + + [% FOREACH row = scores.rows %] + ... + [% END %] + +You can use this approach to create multiple plugin objects with +different configurations. This example shows how the 'format' plugin +is used to create sub-routines bound to variables for formatting text +as per printf(). + + [% USE bold = format('<b>%s</b>') %] + [% USE ital = format('<i>%s</i>') %] + + [% bold('This is bold') %] + [% ital('This is italic') %] + +Output: + + <b>This is bold</b> + <i>This is italic</i> + +This next example shows how the URL plugin can be used to build +dynamic URLs from a base part and optional query parameters. + + [% USE mycgi = URL('/cgi-bin/foo.pl', debug=1) %] + <a href="[% mycgi %]">... + <a href="[% mycgi(mode='submit') %]"... + +Output: + + <a href="/cgi-bin/foo.pl?debug=1">... + <a href="/cgi-bin/foo.pl?mode=submit&debug=1">... + +The CGI plugin is an example of one which delegates to another Perl +module. In this this case, it is to Lincoln Stein's CGI.pm module. +All of the methods provided by CGI.pm are available via the plugin. + + [% USE CGI %] + + [% CGI.start_form %] + + [% CGI.checkbox_group(name => 'colours', + values => [ 'red' 'green' 'blue' ]) + %] + + [% CGI.popup_menu(name => 'items', + values => [ 'foo' 'bar' 'baz' ]) + %] + + [% CGI.end_form %] + +Simon Matthews has written the DBI plugin which provides an interface +to Tim Bunce's DBI module (available from CPAN). Here's a short +example: + + [% USE DBI('DBI:mSQL:mydbname') %] + + [% FOREACH user = DBI.query('SELECT * FROM users') %] + [% user.id %] [% user.name %] [% user.etc.etc %] + [% END %] + +See L<Template::Manual::Plugins> for more information on the plugins +distributed with the toolkit or available from CPAN. + +The LOAD_PERL option (disabled by default) provides a further way by +which external Perl modules may be loaded. If a regular Perl module +(i.e. not a Template::Plugin::* or other module relative to some +PLUGIN_BASE) supports an object-oriented interface and a new() +constructor then it can be loaded and instantiated automatically. The +following trivial example shows how the IO::File module might be used. + + [% USE file = IO.File('/tmp/mydata') %] + + [% WHILE (line = file.getline) %] + <!-- [% line %] --> + [% END %] + + + + + + +=item MACRO + +The MACRO directive allows you to define a directive or directive block +which is then evaluated each time the macro is called. + + [% MACRO header INCLUDE header %] + +Calling the macro as: + + [% header %] + +is then equivalent to: + + [% INCLUDE header %] + +Macros can be passed named parameters when called. These values remain +local to the macro. + + [% header(title='Hello World') %] + +equivalent to: + + [% INCLUDE header title='Hello World' %] + +A MACRO definition may include parameter names. Values passed to the +macros are then mapped to these local variables. Other named parameters +may follow these. + + [% MACRO header(title) INCLUDE header %] + + [% header('Hello World') %] + [% header('Hello World', bgcol='#123456') %] + +equivalent to: + + [% INCLUDE header title='Hello World' %] + [% INCLUDE header title='Hello World' bgcol='#123456' %] + +Here's another example, defining a macro for display numbers +in comma-delimited groups of 3, using the chunk and join virtual +method. + + [% MACRO number(n) GET n.chunk(-3).join(',') %] + + [% number(1234567) %] # 1,234,567 + +A MACRO may precede any directive and must conform to the structure +of the directive. + + [% MACRO header IF frames %] + [% INCLUDE frames/header %] + [% ELSE %] + [% INCLUDE header %] + [% END %] + + [% header %] + +A MACRO may also be defined as an anonymous BLOCK. The block will be +evaluated each time the macro is called. + + [% MACRO header BLOCK %] + ...content... + [% END %] + + [% header %] + +If you've got the EVAL_PERL option set, then you can even define a +MACRO as a PERL block (see below): + + [% MACRO triple(n) PERL %] + my $n = $stash->get('n'); + print $n * 3; + [% END -%] + + + + + + + +=item PERL + +(for the advanced reader) + +The PERL directive is used to mark the start of a block which contains +Perl code for evaluation. The EVAL_PERL option must be enabled for Perl +code to be evaluated or a 'perl' exception will be thrown with the +message 'EVAL_PERL not set'. + +Perl code is evaluated in the Template::Perl package. The $context +package variable contains a reference to the current Template::Context +object. This can be used to access the functionality of the Template +Toolkit to process other templates, load plugins, filters, etc. +See L<Template::Context> for further details. + + [% PERL %] + print $context->include('myfile'); + [% END %] + +The $stash variable contains a reference to the top-level stash object +which manages template variables. Through this, variable values can +be retrieved and updated. See L<Template::Stash> for further details. + + [% PERL %] + $stash->set(foo => 'bar'); + print "foo value: ", $stash->get('foo'); + [% END %] + +Output + foo value: bar + +Output is generated from the PERL block by calling print(). Note that +the Template::Perl::PERLOUT handle is selected (tied to an output +buffer) instead of STDOUT. + + [% PERL %] + print "foo\n"; # OK + print PERLOUT "bar\n"; # OK, same as above + print Template::Perl::PERLOUT "baz\n"; # OK, same as above + print STDOUT "qux\n"; # WRONG! + [% END %] + +The PERL block may contain other template directives. These are +processed before the Perl code is evaluated. + + [% name = 'Fred Smith' %] + + [% PERL %] + print "[% name %]\n"; + [% END %] + +Thus, the Perl code in the above example is evaluated as: + + print "Fred Smith\n"; + +Exceptions may be thrown from within PERL blocks via die() and will be +correctly caught by enclosing TRY blocks. + + [% TRY %] + [% PERL %] + die "nothing to live for\n"; + [% END %] + [% CATCH %] + error: [% error.info %] + [% END %] + +output: + error: nothing to live for + + + + +=item RAWPERL + +(for the very advanced reader) + +The Template Toolkit parser reads a source template and generates the +text of a Perl subroutine as output. It then uses eval() to evaluate +it into a subroutine reference. This subroutine is then called to +process the template, passing a reference to the current +Template::Context object through which the functionality of the +Template Toolkit can be accessed. The subroutine reference can be +cached, allowing the template to be processed repeatedly without +requiring any further parsing. + +For example, a template such as: + + [% PROCESS header %] + The [% animal %] sat on the [% location %] + [% PROCESS footer %] + +is converted into the following Perl subroutine definition: + + sub { + my $context = shift; + my $stash = $context->stash; + my $output = ''; + my $error; + + eval { BLOCK: { + $output .= $context->process('header'); + $output .= "The "; + $output .= $stash->get('animal'); + $output .= " sat on the "; + $output .= $stash->get('location'); + $output .= $context->process('footer'); + $output .= "\n"; + } }; + if ($@) { + $error = $context->catch($@, \$output); + die $error unless $error->type eq 'return'; + } + + return $output; + } + +To examine the Perl code generated, such as in the above example, set +the $Template::Parser::DEBUG package variable to any true value. You +can also set the $Template::Directive::PRETTY variable true to have +the code formatted in a readable manner for human consumption. The +source code for each generated template subroutine will be printed to +STDERR on compilation (i.e. the first time a template is used). + + $Template::Parser::DEBUG = 1; + $Template::Directive::PRETTY = 1; + + ... + + $template->process($file, $vars) + || die $template->error(), "\n"; + +The PERL ... END construct allows Perl code to be embedded into a +template (when the EVAL_PERL option is set), but it is evaluated at +"runtime" using eval() each time the template subroutine is called. +This is inherently flexible, but not as efficient as it could be, +especially in a persistent server environment where a template may be +processed many times. + +The RAWPERL directive allows you to write Perl code that is integrated +directly into the generated Perl subroutine text. It is evaluated +once at compile time and is stored in cached form as part of the +compiled template subroutine. This makes RAWPERL blocks more +efficient than PERL blocks. + +The downside is that you must code much closer to the metal. Within +PERL blocks, you can call print() to generate some output. RAWPERL +blocks don't afford such luxury. The code is inserted directly into +the generated subroutine text and should conform to the convention of +appending to the '$output' variable. + + [% PROCESS header %] + + [% RAWPERL %] + $output .= "Some output\n"; + ... + $output .= "Some more output\n"; + [% END %] + +The critical section of the generated subroutine for this example would +then look something like: + + ... + eval { BLOCK: { + $output .= $context->process('header'); + $output .= "\n"; + $output .= "Some output\n"; + ... + $output .= "Some more output\n"; + $output .= "\n"; + } }; + ... + +As with PERL blocks, the $context and $stash references are pre-defined +and available for use within RAWPERL code. + + +=back + +=head2 Exception Handling and Flow Control + +=over 4 + + +=item TRY / THROW / CATCH / FINAL + +(more advanced material) + +The Template Toolkit supports fully functional, nested exception +handling. The TRY directive introduces an exception handling scope +which continues until the matching END directive. Any errors that +occur within that block will be caught and can be handled by one +of the CATCH blocks defined. + + [% TRY %] + ...blah...blah... + [% CALL somecode %] + ...etc... + [% INCLUDE someblock %] + ...and so on... + [% CATCH %] + An error occurred! + [% END %] + +Errors are raised as exceptions (objects of the Template::Exception +class) and contain two fields, 'type' and 'info'. The exception +'type' can be any string containing letters, numbers, '_' or '.', and +is used to indicate the kind of error that occurred. The 'info' field +contains an error message indicating what actually went wrong. Within +a catch block, the exception object is aliased to the 'error' variable. +You can access the 'type' and 'info' fields directly. + + [% mydsn = 'dbi:MySQL:foobar' %] + ... + + [% TRY %] + [% USE DBI(mydsn) %] + [% CATCH %] + ERROR! Type: [% error.type %] + Info: [% error.info %] + [% END %] + +output (assuming a non-existant database called 'foobar'): + + ERROR! Type: DBI + Info: Unknown database "foobar" + +The 'error' variable can also be specified by itself and will return a +string of the form "$type error - $info". + + ... + [% CATCH %] + ERROR: [% error %] + [% END %] + +output: + + ERROR: DBI error - Unknown database "foobar" + +Each CATCH block may be specified with a particular exception type +denoting the kind of error that it should catch. Multiple CATCH +blocks can be provided to handle different types of exception that may +be thrown in the TRY block. A CATCH block specified without any type, +as in the previous example, is a default handler which will catch any +otherwise uncaught exceptions. This can also be specified as +[% CATCH DEFAULT %]. + + [% TRY %] + [% INCLUDE myfile %] + [% USE DBI(mydsn) %] + [% CALL somecode %] + ... + [% CATCH file %] + File Error! [% error.info %] + [% CATCH DBI %] + [% INCLUDE database/error.html %] + [% CATCH %] + [% error %] + [% END %] + +Remember that you can specify multiple directives within a single tag, +each delimited by ';'. Thus, you might prefer to write your simple +CATCH blocks more succinctly as: + + [% TRY %] + ... + [% CATCH file; "File Error! $error.info" %] + [% CATCH DBI; INCLUDE database/error.html %] + [% CATCH; error %] + [% END %] + +or even: + + [% TRY %] + ... + [% CATCH file ; + "File Error! $error.info" ; + CATCH DBI ; + INCLUDE database/error.html ; + CATCH ; + error ; + END + %] + +The DBI plugin throws exceptions of the 'DBI' type (in case that +wasn't already obvious). The other specific exception caught here is +of the 'file' type. + +A 'file' error is automatically thrown by the Template Toolkit when it +can't find a file, or fails to load, parse or process a file that has +been requested by an INCLUDE, PROCESS, INSERT or WRAPPER directive. +If 'myfile' can't be found in the example above, the [% INCLUDE myfile +%] directive will raise a 'file' exception which is then caught by the +[% CATCH file %] block, generating the output: + + File Error! myfile: not found + +Note that the DEFAULT option (disabled by default) allows you to +specify a default file to be used any time a template file can't be +found. This will prevent file exceptions from ever being raised when +a non-existant file is requested (unless, of course, the DEFAULT file +doesn't exist). Errors encountered once the file has been found +(i.e. read error, parse error) will be raised as file exceptions as per +usual. + +Uncaught exceptions (i.e. the TRY block doesn't have a type specific +or default CATCH handler) may be caught by enclosing TRY blocks which +can be nested indefinitely across multiple templates. If the error +isn't caught at any level then processing will stop and the Template +process() method will return a false value to the caller. The +relevant Template::Exception object can be retrieved by calling the +error() method. + + [% TRY %] + ... + [% TRY %] + [% INCLUDE $user.header %] + [% CATCH file %] + [% INCLUDE header %] + [% END %] + ... + [% CATCH DBI %] + [% INCLUDE database/error.html %] + [% END %] + +In this example, the inner TRY block is used to ensure that the first +INCLUDE directive works as expected. We're using a variable to +provide the name of the template we want to include, user.header, and +it's possible this contains the name of a non-existant template, or +perhaps one containing invalid template directives. If the INCLUDE fails + with a 'file' error then we CATCH it in the inner block and INCLUDE +the default 'header' file instead. Any DBI errors that occur within +the scope of the outer TRY block will be caught in the relevant CATCH +block, causing the 'database/error.html' template to be processed. +Note that included templates inherit all currently defined template +variable so these error files can quite happily access the 'error' +variable to retrieve information about the currently caught exception. +e.g. + +'database/error.html': + + <h2>Database Error</h2> + A database error has occurred: [% error.info %] + +You can also specify a FINAL block. This is always processed +regardless of the outcome of the TRY and/or CATCH block. If an +exception is uncaught then the FINAL block is processed before jumping +to the enclosing block or returning to the caller. + + [% TRY %] + ... + [% CATCH this %] + ... + [% CATCH that %] + ... + [% FINAL %] + All done! + [% END %] + +The output from the TRY block is left intact up to the point where an +exception occurs. For example, this template: + + [% TRY %] + This gets printed + [% THROW food 'carrots' %] + This doesn't + [% CATCH food %] + culinary delights: [% error.info %] + [% END %] + +generates the following output: + + This gets printed + culinary delights: carrots + +The CLEAR directive can be used in a CATCH or FINAL block to clear +any output created in the TRY block. + + [% TRY %] + This gets printed + [% THROW food 'carrots' %] + This doesn't + [% CATCH food %] + [% CLEAR %] + culinary delights: [% error.info %] + [% END %] + +output: + + culinary delights: carrots + +Exception types are hierarchical, with each level being separated by +the familiar dot operator. A 'DBI.connect' exception is a more +specific kind of 'DBI' error. Similarly, a 'myown.error.barf' is a +more specific kind of 'myown.error' type which itself is also a +'myown' error. A CATCH handler that specifies a general exception +type (such as 'DBI' or 'myown.error') will also catch more specific +types that have the same prefix as long as a more specific handler +isn't defined. Note that the order in which CATCH handlers are +defined is irrelevant; a more specific handler will always catch an +exception in preference to a more generic or default one. + + [% TRY %] + ... + [% CATCH DBI ; + INCLUDE database/error.html ; + CATCH DBI.connect ; + INCLUDE database/connect.html ; + CATCH ; + INCLUDE error.html ; + END + %] + +In this example, a 'DBI.connect' error has it's own handler, a more +general 'DBI' block is used for all other DBI or DBI.* errors and a +default handler catches everything else. + +Exceptions can be raised in a template using the THROW directive. The +first parameter is the exception type which doesn't need to be quoted +(but can be, it's the same as INCLUDE) followed by the relevant error +message which can be any regular value such as a quoted string, +variable, etc. + + [% THROW food "Missing ingredients: $recipe.error" %] + + [% THROW user.login 'no user id: please login' %] + + [% THROW $myerror.type "My Error: $myerror.info" %] + +It's also possible to specify additional positional or named +parameters to the THROW directive if you want to pass more than +just a simple message back as the error info field. + + [% THROW food 'eggs' 'flour' msg='Missing Ingredients' %] + +In this case, the error 'info' field will be a hash array containing +the named arguments, in this case 'msg' =E<gt> 'Missing Ingredients', +and an 'args' item which contains a list of the positional arguments, +in this case 'eggs' and 'flour'. The error 'type' field remains +unchanged, here set to 'food'. + + [% CATCH food %] + [% error.info.msg %] + [% FOREACH item = error.info.args %] + * [% item %] + [% END %] + [% END %] + +This produces the output: + + Missing Ingredients + * eggs + * flour + +In addition to specifying individual positional arguments as +[% error.info.args.n %], the 'info' hash contains keys directly +pointing to the positional arguments, as a convenient shortcut. + + [% error.info.0 %] # same as [% error.info.args.0 %] + +Exceptions can also be thrown from Perl code which you've bound to +template variables, or defined as a plugin or other extension. To +raise an exception, call die() passing a reference to a +Template::Exception object as the argument. This will then be caught +by any enclosing TRY blocks from where the code was called. + + use Template::Exception; + ... + + my $vars = { + foo => sub { + # ... do something ... + die Template::Exception->new('myerr.naughty', + 'Bad, bad error'); + }, + }; + +template: + + [% TRY %] + ... + [% foo %] + ... + [% CATCH myerr ; + "Error: $error" ; + END + %] + +output: + + Error: myerr.naughty error - Bad, bad error + +The 'info' field can also be a reference to another object or data +structure, if required. + + die Template::Exception->new('myerror', { + module => 'foo.pl', + errors => [ 'bad permissions', 'naughty boy' ], + }); + +Later, in a template: + + [% TRY %] + ... + [% CATCH myerror %] + [% error.info.errors.size or 'no'; + error.info.errors.size == 1 ? ' error' : ' errors' %] + in [% error.info.module %]: + [% error.info.errors.join(', ') %]. + [% END %] + +Generating the output: + + 2 errors in foo.pl: + bad permissions, naughty boy. + +You can also call die() with a single string, as is common in much +existing Perl code. This will automatically be converted to an +exception of the 'undef' type (that's the literal string 'undef', +not the undefined value). If the string isn't terminated with a +newline then Perl will append the familiar " at $file line $line" +message. + + sub foo { + # ... do something ... + die "I'm sorry, Dave, I can't do that\n"; + } + +If you're writing a plugin, or some extension code that has the +current Template::Context in scope (you can safely skip this section +if this means nothing to you) then you can also raise an exception by +calling the context throw() method. You can pass it an +Template::Exception object reference, a pair of ($type, $info) parameters +or just an $info string to create an exception of 'undef' type. + + $context->throw($e); # exception object + $context->throw('Denied'); # 'undef' type + $context->throw('user.passwd', 'Bad Password'); + + + + + + + +=item NEXT + +The NEXT directive can be used to start the next iteration of a FOREACH +or WHILE loop. + + [% FOREACH user = userlist %] + [% NEXT IF user.isguest %] + Name: [% user.name %] Email: [% user.email %] + [% END %] + + + + + +=item LAST + +The LAST directive can be used to prematurely exit a FOREACH or WHILE +loop. + + [% FOREACH user = userlist %] + Name: [% user.name %] Email: [% user.email %] + [% LAST IF some.condition %] + [% END %] + +BREAK can also be used as an alias for LAST. + + + + +=item RETURN + +The RETURN directive can be used to stop processing the current +template and return to the template from which it was called, resuming +processing at the point immediately after the INCLUDE, PROCESS or +WRAPPER directive. If there is no enclosing template then the +Template process() method will return to the calling code with a +true value. + + Before + [% INCLUDE half_wit %] + After + + [% BLOCK half_wit %] + This is just half... + [% RETURN %] + ...a complete block + [% END %] + +output: + + Before + This is just half... + After + + + + +=item STOP + +The STOP directive can be used to indicate that the processor should +stop gracefully without processing any more of the template document. +This is a planned stop and the Template process() method will return a +B<true> value to the caller. This indicates that the template was +processed successfully according to the directives within it. + + [% IF something.terrible.happened %] + [% INCLUDE fatal/error.html %] + [% STOP %] + [% END %] + + [% TRY %] + [% USE DBI(mydsn) %] + ... + [% CATCH DBI.connect %] + <p>Cannot connect to the database: [% error.info %]</p> + <br> + We apologise for the inconvenience. The cleaning lady + has removed the server power to plug in her vacuum cleaner. + Please try again later. + </p> + [% INCLUDE footer %] + [% STOP %] + [% END %] + + + + +=item CLEAR + +The CLEAR directive can be used to clear the output buffer for the current +enclosing block. It is most commonly used to clear the output generated +from a TRY block up to the point where the error occurred. + + [% TRY %] + blah blah blah # this is normally left intact + [% THROW some 'error' %] # up to the point of error + ... + [% CATCH %] + [% CLEAR %] # clear the TRY output + [% error %] # print error string + [% END %] + + + + +=back + +=head2 Miscellaneous + +=over 4 + + +=item META + +The META directive allows simple metadata items to be defined within a +template. These are evaluated when the template is parsed and as such +may only contain simple values (e.g. it's not possible to interpolate +other variables values into META variables). + + [% META + title = 'The Cat in the Hat' + author = 'Dr. Seuss' + version = 1.23 + %] + +The 'template' variable contains a reference to the main template +being processed. These metadata items may be retrieved as attributes +of the template. + + <h1>[% template.title %]</h1> + <h2>[% template.author %]</h2> + +The 'name' and 'modtime' metadata items are automatically defined for +each template to contain its name and modification time in seconds +since the epoch. + + [% USE date %] # use Date plugin to format time + ... + [% template.name %] last modified + at [% date.format(template.modtime) %] + +The PRE_PROCESS and POST_PROCESS options allow common headers and +footers to be added to all templates. The 'template' reference is +correctly defined when these templates are processed, allowing headers +and footers to reference metadata items from the main template. + + $template = Template->new({ + PRE_PROCESS => 'header', + POST_PROCESS => 'footer', + }); + + $template->process('cat_in_hat'); + +header: + + <html> + <head> + <title>[% template.title %]</title> + </head> + <body> + +cat_in_hat: + + [% META + title = 'The Cat in the Hat' + author = 'Dr. Seuss' + version = 1.23 + year = 2000 + %] + + The cat in the hat sat on the mat. + +footer: + + <hr> + © [% template.year %] [% template.author %] + </body> + </html> + +The output generated from the above example is: + + <html> + <head> + <title>The Cat in the Hat</title> + </head> + <body> + + The cat in the hat sat on the mat. + + <hr> + © 2000 Dr. Seuss + </body> + </html> + + + +=item TAGS + +The TAGS directive can be used to set the START_TAG and END_TAG values +on a per-template file basis. + + [% TAGS <+ +> %] + + <+ INCLUDE header +> + +The TAGS directive may also be used to set a named TAG_STYLE + + [% TAGS html %] + <!-- INCLUDE header --> + +See the TAGS and TAG_STYLE configuration options for further details. + + + + + + + + +=item DEBUG + +The DEBUG directive can be used to enable or disable directive debug +messages within a template. The DEBUG configuration option must be +set to include DEBUG_DIRS for the DEBUG directives to have any effect. +If DEBUG_DIRS is not set then the parser will automatically ignore and +remove any DEBUG directives. + +The DEBUG directive can be used with an 'on' or 'off' parameter to +enable or disable directive debugging messages from that point +forward. When enabled, the output of each directive in the generated +output will be prefixed by a comment indicate the file, line and +original directive text. + + [% DEBUG on %] + directive debugging is on (assuming DEBUG option is set true) + [% DEBUG off %] + directive debugging is off + +The 'format' parameter can be used to change the format of the debugging +message. + + [% DEBUG format '<!-- $file line $line : [% $text %] -->' %] + + + + + +=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.13, released on 30 January 2004. + +=head1 COPYRIGHT + + Copyright (C) 1996-2004 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. + + + +=cut + +# Local Variables: +# mode: perl +# perl-indent-level: 4 +# indent-tabs-mode: nil +# End: +# +# vim: expandtab shiftwidth=4: diff --git a/lib/Template/Manual/Filters.pod b/lib/Template/Manual/Filters.pod new file mode 100644 index 0000000..c42f2ef --- /dev/null +++ b/lib/Template/Manual/Filters.pod @@ -0,0 +1,529 @@ +#============================================================= -*-perl-*- +# +# Template::Manual::Filters +# +# DESCRIPTION +# This section lists all the standard filters distributed with the +# Template Toolkit for post-processing output. +# +# AUTHOR +# Andy Wardley <abw@andywardley.com> +# +# COPYRIGHT +# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved. +# Copyright (C) 1998-2001 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 +# +# +#======================================================================== + + +#------------------------------------------------------------------------ +# 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::Manual::Filters - Standard filters + +=head1 DESCRIPTION + +This section lists all the standard filters distributed with the +Template Toolkit for post-processing output. + +=head1 STANDARD FILTERS + + + +=head2 format(format) + +The 'format' filter takes a format string as a parameter (as per +printf()) and formats each line of text accordingly. + + [% FILTER format('<!-- %-40s -->') %] + This is a block of text filtered + through the above format. + [% END %] + +output: + + <!-- This is a block of text filtered --> + <!-- through the above format. --> + +=head2 upper + +Folds the input to UPPER CASE. + + [% "hello world" FILTER upper %] + +output: + + HELLO WORLD + +=head2 lower + +Folds the input to lower case. + + [% "Hello World" FILTER lower %] + +output: + + hello world + +=head2 ucfirst + +Folds the first character of the input to UPPER CASE. + + [% "hello" FILTER ucfirst %] + +output: + + Hello + +=head2 lcfirst + +Folds the first character of the input to lower case. + + [% "HELLO" FILTER lcfirst %] + +output: + + hELLO + +=head2 trim + +Trims any leading or trailing whitespace from the input text. Particularly +useful in conjunction with INCLUDE, PROCESS, etc., having the same effect +as the TRIM configuration option. + + [% INCLUDE myfile | trim %] + +=head2 collapse + +Collapse any whitespace sequences in the input text into a single space. +Leading and trailing whitespace (which would be reduced to a single space) +is removed, as per trim. + + [% FILTER collapse %] + + The cat + + sat on + + the mat + + [% END %] + +output: + + The cat sat on the mat + +=head2 html + +Converts the characters 'E<lt>', 'E<gt>' and '&' to '<', '>' and +'&', respectively, protecting them from being interpreted as +representing HTML tags or entities. + + [% FILTER html %] + Binary "<=>" returns -1, 0, or 1 depending on... + [% END %] + +output: + + Binary "<=>" returns -1, 0, or 1 depending on... + +=head2 html_entity + +The html filter is fast and simple but it doesn't encode the full +range of HTML entities that your text may contain. The html_entity +filter uses either the Apache::Util module (which is written in C and +is therefore faster) or the HTML::Entities module (written in Perl but +equally as comprehensive) to perform the encoding. If one or other of +these modules are installed on your system then the text will be +encoded (via the escape_html() or encode_entities() subroutines +respectively) to convert all extended characters into their +appropriate HTML entities (e.g. converting 'é' to 'é'). If +neither module is available on your system then an 'html_entity' exception +will be thrown reporting an appropriate message. + +For further information on HTML entity encoding, see +http://www.w3.org/TR/REC-html40/sgml/entities.html. + +=head2 html_para + +This filter formats a block of text into HTML paragraphs. A sequence of +two or more newlines is used as the delimiter for paragraphs which are +then wrapped in HTML E<lt>pE<gt>...E<lt>/pE<gt> tags. + + [% FILTER html_para %] + The cat sat on the mat. + + Mary had a little lamb. + [% END %] + +output: + + <p> + The cat sat on the mat. + </p> + + <p> + Mary had a little lamb. + </p> + +=head2 html_break / html_para_break + +Similar to the html_para filter described above, but uses the HTML tag +sequence E<lt>brE<gt>E<lt>brE<gt> to join paragraphs. + + [% FILTER html_break %] + The cat sat on the mat. + + Mary had a little lamb. + [% END %] + +output: + + The cat sat on the mat. + <br> + <br> + Mary had a little lamb. + +=head2 html_line_break + +This filter replaces any newlines with E<lt>brE<gt> HTML tags, +thus preserving the line breaks of the original text in the +HTML output. + + [% FILTER html_line_break %] + The cat sat on the mat. + Mary had a little lamb. + [% END %] + +output: + + The cat sat on the mat.<br> + Mary had a little lamb.<br> + +=head2 uri + +This filter URI escapes the input text, converting any characters +outside of the permitted URI character set (as defined by RFC 2396) +into a C<%nn> hex escape. + + [% 'my file.html' | uri %] + +output: + + my%20file.html + +Note that URI escaping isn't always enough when generating hyperlinks in +an HTML document. The C<&> character, for example, is valid in a URI and +will not be escaped by the URI filter. In this case you should also filter +the text through the 'html' filter. + + <a href="[% filename | uri | html %]">click here</a> + +=head2 indent(pad) + +Indents the text block by a fixed pad string or width. The 'pad' argument +can be specified as a string, or as a numerical value to indicate a pad +width (spaces). Defaults to 4 spaces if unspecified. + + [% FILTER indent('ME> ') %] + blah blah blah + cabbages, rhubard, onions + [% END %] + +output: + + ME> blah blah blah + ME> cabbages, rhubard, onions + +=head2 truncate(length) + +Truncates the text block to the length specified, or a default length of +32. Truncated text will be terminated with '...' (i.e. the '...' falls +inside the required length, rather than appending to it). + + [% FILTER truncate(21) %] + I have much to say on this matter that has previously + been said on more than one occasion. + [% END %] + +output: + + I have much to say... + +=head2 repeat(iterations) + +Repeats the text block for as many iterations as are specified (default: 1). + + [% FILTER repeat(3) %] + We want more beer and we want more beer, + [% END %] + We are the more beer wanters! + +output: + + We want more beer and we want more beer, + We want more beer and we want more beer, + We want more beer and we want more beer, + We are the more beer wanters! + +=head2 remove(string) + +Searches the input text for any occurrences of the specified string and +removes them. A Perl regular expression may be specified as the search +string. + + [% "The cat sat on the mat" FILTER remove('\s+') %] + +output: + + Thecatsatonthemat + +=head2 replace(search, replace) + +Similar to the remove filter described above, but taking a second parameter +which is used as a replacement string for instances of the search string. + + [% "The cat sat on the mat" | replace('\s+', '_') %] + +output: + + The_cat_sat_on_the_mat + +=head2 redirect(file, options) + +The 'redirect' filter redirects the output of the block into a separate +file, specified relative to the OUTPUT_PATH configuration item. + + [% FOREACH user = myorg.userlist %] + [% FILTER redirect("users/${user.id}.html") %] + [% INCLUDE userinfo %] + [% END %] + [% END %] + +or more succinctly, using side-effect notation: + + [% INCLUDE userinfo + FILTER redirect("users/${user.id}.html") + FOREACH user = myorg.userlist + %] + +A 'file' exception will be thrown if the OUTPUT_PATH option is undefined. + +An optional 'binmode' argument can follow the filename to explicitly set +the output file to binary mode. + + [% PROCESS my/png/generator + FILTER redirect("images/logo.png", binmode=1) %] + +For backwards compatibility with earlier versions, a single true/false +value can be used to set binary mode. + + [% PROCESS my/png/generator + FILTER redirect("images/logo.png", 1) %] + +For the sake of future compatibility and clarity, if nothing else, we +would strongly recommend you explicitly use the named 'binmode' option +as shown in the first example. + +=head2 eval / evaltt + +The 'eval' filter evaluates the block as template text, processing +any directives embedded within it. This allows template variables to +contain template fragments, or for some method to be provided for +returning template fragments from an external source such as a +database, which can then be processed in the template as required. + + my $vars = { + fragment => "The cat sat on the [% place %]", + }; + $template->process($file, $vars); + +The following example: + + [% fragment | eval %] + +is therefore equivalent to + + The cat sat on the [% place %] + +The 'evaltt' filter is provided as an alias for 'eval'. + +=head2 perl / evalperl + +The 'perl' filter evaluates the block as Perl code. The EVAL_PERL +option must be set to a true value or a 'perl' exception will be +thrown. + + [% my_perl_code | perl %] + +In most cases, the [% PERL %] ... [% END %] block should suffice for +evaluating Perl code, given that template directives are processed +before being evaluate as Perl. Thus, the previous example could have +been written in the more verbose form: + + [% PERL %] + [% my_perl_code %] + [% END %] + +as well as + + [% FILTER perl %] + [% my_perl_code %] + [% END %] + +The 'evalperl' filter is provided as an alias for 'perl' for backwards +compatibility. + +=head2 stdout(options) + +The stdout filter prints the output generated by the enclosing block to +STDOUT. The 'binmode' option can be passed as either a named parameter +or a single argument to set STDOUT to binary mode (see the +binmode perl function). + + [% PROCESS something/cool + FILTER stdout(binmode=1) # recommended %] + + [% PROCESS something/cool + FILTER stdout(1) # alternate %] + +The stdout filter can be used to force binmode on STDOUT, or also inside +redirect, null or stderr blocks to make sure that particular output goes +to stdout. See the null filter below for an example. + +=head2 stderr + +The stderr filter prints the output generated by the enclosing block to +STDERR. + +=head2 null + +The null filter prints nothing. This is useful for plugins whose +methods return values that you don't want to appear in the output. +Rather than assigning every plugin method call to a dummy variable +to silence it, you can wrap the block in a null filter: + + [% FILTER null; + USE im = GD.Image(100,100); + black = im.colorAllocate(0, 0, 0); + red = im.colorAllocate(255,0, 0); + blue = im.colorAllocate(0, 0, 255); + im.arc(50,50,95,75,0,360,blue); + im.fill(50,50,red); + im.png | stdout(1); + END; + -%] + +Notice the use of the stdout filter to ensure that a particular expression +generates output to stdout (in this case in binary mode). + +=head2 latex(outputType) + +Passes the text block to LaTeX and produces either PDF, DVI or +PostScript output. The 'outputType' argument determines the output +format and it should be set to one of the strings: "pdf" (default), +"dvi", or "ps". + +The text block should be a complete LaTeX source file. + + [% FILTER latex("pdf") -%] + \documentclass{article} + + \begin{document} + + \title{A Sample TT2 \LaTeX\ Source File} + \author{Craig Barratt} + \maketitle + + \section{Introduction} + This is some text. + + \end{document} + [% END -%] + +The output will be a PDF file. You should be careful not to prepend or +append any extraneous characters or text outside the FILTER block, +since this text will wrap the (binary) output of the latex filter. +Notice the END directive uses '-%]' for the END_TAG to remove the +trailing new line. + +One example where you might prepend text is in a CGI script where +you might include the Content-Type before the latex output, eg: + + Content-Type: application/pdf + + [% FILTER latex("pdf") -%] + \documentclass{article} + \begin{document} + ... + \end{document} + [% END -%] + +In other cases you might use the redirect filter to put the output +into a file, rather than delivering it to stdout. This might be +suitable for batch scripts: + + [% output = FILTER latex("pdf") -%] + \documentclass{article} + \begin{document} + ... + \end{document} + [% END; output | redirect("document.pdf", 1) -%] + +(Notice the second argument to redirect to force binary mode.) + +Note that the latex filter runs one or two external programs, so it +isn't very fast. But for modest documents the performance is adequate, +even for interactive applications. + +A error of type 'latex' will be thrown if there is an error reported +by latex, pdflatex or dvips. + +=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.13, released on 30 January 2004. + +=head1 COPYRIGHT + + Copyright (C) 1996-2004 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. + + + +=cut + +# Local Variables: +# mode: perl +# perl-indent-level: 4 +# indent-tabs-mode: nil +# End: +# +# vim: expandtab shiftwidth=4: diff --git a/lib/Template/Manual/Internals.pod b/lib/Template/Manual/Internals.pod new file mode 100644 index 0000000..b8cf80b --- /dev/null +++ b/lib/Template/Manual/Internals.pod @@ -0,0 +1,556 @@ +#============================================================= -*-perl-*- +# +# Template::Manual::Internals +# +# DESCRIPTION +# This document provides an overview of the internal architecture of +# the Template Toolkit. It is a work in progress and is far from +# complete, currently providing little more than an overview of how +# the major components fit together. Nevertheless, it's a good +# starting point for anyone wishing to delve into the source code to +# find out how it all works. +# +# AUTHOR +# Andy Wardley <abw@andywardley.com> +# +# COPYRIGHT +# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved. +# Copyright (C) 1998-2001 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 +# +# +#======================================================================== + + +#------------------------------------------------------------------------ +# 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::Manual::Internals - Template Toolkit internals + +=head1 DESCRIPTION + +This document provides an overview of the internal architecture of the +Template Toolkit. It is a work in progress and is far from complete, +currently providing little more than an overview of how the major +components fit together. Nevertheless, it's a good starting point for +anyone wishing to delve into the source code to find out how it all +works. + +=head2 Outside Looking In + +The B<Template> module is simply a front end module which creates and +uses a Template::Service and pipes the output wherever you want it to +go (STDOUT by default, or maybe a file, scalar, etc). The +Apache::Template module (available separately from CPAN) is another +front end. That creates a Template::Service::Apache object, calls on +it as required and sends the output back to the relevant +Apache::Request object. + +These front-end modules are really only there to handle any specifics +of the environment in which they're being used. The Apache::Template +front end, for example, handles Apache::Request specifics and +configuration via the httpd.conf. The regular Template front-end +deals with STDOUT, variable refs, etc. Otherwise it is +Template::Service (or subclass) which does all the work. + +The B<Template::Service> module provides a high-quality template +delivery service, with bells, whistles, signed up service level +agreement and a 30-day no quibble money back guarantee. "Have +a good time, all the time", that's our motto. + +Within the lower levels of the Template Toolkit, there are lots of +messy details that we generally don't want to have to worry about most +of the time. Things like templates not being found, or failing to +parse correctly, uncaught exceptions being thrown, missing plugin +modules or dependencies, and so on. Template::Service hides that all +away and makes everything look simple to the outsider. It provides +extra features, like PRE_PROCESS, PROCESS and POST_PROCESS, and also +provides the error recovery mechanism via ERROR. You ask it to +process a template and it takes care of everything for you. The +Template::Service::Apache module goes a little bit further, adding +some extra headers to the Apache::Request, setting a few extra template +variables, and so on. + +For the most part, the job of a service is really just one of +scheduling and dispatching. It receives a request in the form of a +call to its process() method and schedules the named template +specified as an argument, and possibly several other templates +(PRE_PROCESS, etc) to be processed in order. It doesn't actually +process the templates itself, but instead makes a process() call +against a Template::Context object. + +B<Template::Context> is the runtime engine for the Template Toolkit - +the module that hangs everything together in the lower levels of the +Template Toolkit and that one that does most of the real work, albeit +by crafty delegation to various other friendly helper modules. + +Given a template name (or perhaps a reference to a scalar or file +handle) the context process() method must load and compile, or fetch a +cached copy of a previously compiled template, corresponding to that +name. It does this by calling on a list of one or more +Template::Provider objects (the LOAD_TEMPLATES posse) who themselves +might get involved with a Template::Parser to help turn source +templates into executable Perl code (but more on that later). Thankfully, +all of this complexity is hidden away behind a simple template() +method. You call it passing a template name as an argument, and it +returns a compiled template in the form of a Template::Document +object, or otherwise raises an exception. + +A B<Template::Document> is a thin object wrapper around a compiled +template subroutine. The object implements a process() method which +performs a little bit of housekeeping and then calls the template +subroutine. The object also defines template metadata (defined in +C<[% META ... %]> directives) and has a block() method which returns +a hash of any additional C<[% BLOCK xxxx %]> definitions found in the +template source. + +So the context fetches a compiled document via its own template() +method and then gets ready to process it. It first updates the stash +(the place where template variables get defined - more on that +shortly) to set any template variable definitions specified as the +second argument by reference to hash array. Then, it calls the +document process() method, passing a reference to itself, the context +object, as an argument. In doing this, it provides itself as an +object against which template code can make callbacks to access +runtime resources and Template Toolkit functionality. + +What we're trying to say here is this: not only does the Template::Context +object receive calls from the I<outside>, i.e. those originating in user +code calling the process() method on a Template object, but it also +receives calls from the I<inside>, i.e. those originating in template +directives of the form C<[% PROCESS template %]>. + +Before we move on to that, here's a simple structure diagram showing +the outer layers of the Template Toolkit heading inwards, with pseudo +code annotations showing a typical invocation sequence. + + ,--------. + | Caller | use Template; + `--------' my $tt = Template->new( ... ); + | $tt->process($template, \%vars); + | Outside + - - - - | - - - - - - - - - - - - - - - - - - - - - - - - - - - - T T + | package Template; Inside + V + +----------+ sub process($template, \%vars) { + | Template | $out = $self->SERVICE->process($template, $vars); + +----------+ print $out or send it to $self->OUTPUT; + | } + | + | package Template::Service; + | + | sub process($template, \%vars) { + | try { + +----------+ foreach $p in @self->PRE_PROCESS + | Service | $self->CONTEXT->process($p, $vars); + +----------+ + | $self->CONTEXT->process($template, $vars); + | + | foreach $p @self->POST_PROCESS + | $self->CONTEXT->process($p, $vars); + | } + | catch { + | $self->CONTEXT->process($self->ERROR); + | } + | } + | + V package Template::Context; + +----------+ + | Context | sub process($template, \%vars) { + +----------+ # fetch compiled template + | $template = $self->template($template) + | # update stash + | $self->STASH->update($vars); + | # process template + | $template->process($self) + | } + V + +----------+ package Template::Document; + | Document | + +----------+ sub process($context) { + $output = &{ $self->BLOCK }($context); + } + + +=head2 Inside Looking Out + +To understand more about what's going on in these lower levels, we +need to look at what a compiled template looks like. In fact, a +compiled template is just a regular Perl sub-routine. Here's a very +simple one. + + sub my_compiled_template { + return "This is a compiled template.\n"; + } + +You're unlikely to see a compiled template this simple unless you +wrote it yourself but it is entirely valid. All a template subroutine +is obliged to do is return some output (which may be an empty of +course). If it can't for some reason, then it should raise an error +via die(). + + sub my_todo_template { + die "This template not yet implemented\n"; + } + +If it wants to get fancy, it can raise an error as a +Template::Exception object. An exception object is really just a +convenient wrapper for the 'type' and 'info' fields. + + sub my_solilique_template { + die (Template::Exception->new('yorrick', 'Fellow of infinite jest')); + } + +Templates generally need to do a lot more than just generate static +output or raise errors. They may want to inspect variable values, +process another template, load a plugin, run a filter, and so on. +Whenever a template subroutine is called, it gets passed a reference +to a Template::Context object. It is through this context object that +template code can access the features of the Template Toolkit. + +We described earlier how the Template::Service object calls on +Template::Context to handle a process() request from the I<outside>. +We can make a similar request on a context to process a template, but +from within the code of another template. This is a call from the +I<inside>. + + sub my_process_template { + my $context = shift; + + my $output = $context->process('header', { title => 'Hello World' }) + . "\nsome content\n" + . $context->process('footer'); + } + +This is then roughly equivalent to a source template something +like this: + + [% PROCESS header + title = 'Hello World' + %] + some content + [% PROCESS footer %] + +Template variables are stored in, and managed by a B<Template::Stash> +object. This is a blessed hash array in which template variables are +defined. The object wrapper provides get() and set() method which +implement all the magical.variable.features of the Template Toolkit. + +Each context object has its own stash, a reference to which can be +returned by the appropriately named stash() method. So to print the +value of some template variable, or for example, to represent the +following source template: + + <title>[% title %]</title> + +we might have a subroutine definition something like this: + + sub { + my $context = shift; + my $stash = $context->stash(); + return '<title>' . $stash->get('title') . '</title>'; + } + +The stash get() method hides the details of the underlying variable +types, automatically calling code references, checking return values, +and performing other such tricks. If 'title' happens to be bound to a +subroutine then we can specify additional parameters as a list +reference passed as the second argument to get(). + + [% title('The Cat Sat on the Mat') %] + +This translates to the stash get() call: + + $stash->get([ 'title', ['The Cat Sat on the Mat'] ]); + +Dotted compound variables can be requested by passing a single +list reference to the get() method in place of the variable +name. Each pair of elements in the list should correspond to the +variable name and reference to a list of arguments for each +dot-delimited element of the variable. + + [% foo(1, 2).bar(3, 4).baz(5) %] + +is thus equivalent to + + $stash->get([ foo => [1,2], bar => [3,4], baz => [5] ]); + +If there aren't any arguments for an element, you can specify an +empty, zero or null argument list. + + [% foo.bar %] + $stash->get([ 'foo', 0, 'bar', 0 ]); + +The set() method works in a similar way. It takes a variable +name and a variable value which should be assigned to it. + + [% x = 10 %] + $stash->set('x', 10); + + [% x.y = 10 %] + $stash->set([ 'x', 0, 'y', 0 ], 10); + +So the stash gives us access to template variables and the context +provides the higher level functionality. Alongside the process() +method lies the include() method. Just as with the PROCESS / INCLUDE +directives, the key difference is in variable localisation. Before +processing a template, the process() method simply updates the stash +to set any new variable definitions, overwriting any existing values. +In contrast, the include() method creates a copy of the existing +stash, in a process known as I<cloning> the stash, and then uses that +as a temporary variable store. Any previously existing variables are +still defined, but any changes made to variables, including setting +the new variable values passed aas arguments will affect only the +local copy of the stash (although note that it's only a shallow copy, +so it's not foolproof). When the template has been processed, the include() +method restores the previous variable state by I<decloning> the stash. + +The context also provides an insert() method to implement the INSERT +directive, but no wrapper() method. This functionality can be implemented +by rewriting the Perl code and calling include(). + + [% WRAPPER foo -%] + blah blah [% x %] + [%- END %] + + $context->include('foo', { + content => 'blah blah ' . $stash->get('x'), + }); + +Other than the template processing methods process(), include() and insert(), +the context defines methods for fetching plugin objects, plugin(), and +filters, filter(). + + [% USE foo = Bar(10) %] + + $stash->set('foo', $context->plugin('Bar', [10])); + + [% FILTER bar(20) %] + blah blah blah + [% END %] + + my $filter = $context->filter('bar', [20]); + &$filter('blah blah blah'); + +Pretty much everything else you might want to do in a template can be done +in Perl code. Things like IF, UNLESS, FOREACH and so on all have direct +counterparts in Perl. + + [% IF msg %] + Message: [% msg %] + [% END %]; + + if ($stash->get('msg')) { + $output .= 'Message: '; + $output .= $stash->get('msg'); + } + +The best way to get a better understanding of what's going on underneath +the hood is to set the C<$Template::Parser::DEBUG> flag to a true value +and start processing templates. This will cause the parser to print the +generated Perl code for each template it compiles to STDERR. You'll +probably also want to set the C<$Template::Directive::PRETTY> option to +have the Perl pretty-printed for human consumption. + + use Template; + use Template::Parser; + use Template::Directive; + + $Template::Parser::DEBUG = 1; + $Template::Directive::PRETTY = 1; + + my $template = Template->new(); + $template->process(\*DATA, { cat => 'dog', mat => 'log' }); + + __DATA__ + The [% cat %] sat on the [% mat %] + +The output sent to STDOUT remains as you would expect: + + The dog sat on the log + +The output sent to STDERR would look something like this: + + compiled main template document block: + sub { + my $context = shift || die "template sub called without context\n"; + my $stash = $context->stash; + my $output = ''; + my $error; + + eval { BLOCK: { + $output .= "The "; + $output .= $stash->get('cat'); + $output .= " sat on the "; + $output .= $stash->get('mat'); + $output .= "\n"; + } }; + if ($@) { + $error = $context->catch($@, \$output); + die $error unless $error->type eq 'return'; + } + + return $output; + } + + +=head1 HACKING ON THE TEMPLATE TOOLKIT + +Please feel free to hack on the Template Toolkit. If you find a bug +that needs fixing, if you have an idea for something that's missing, +or you feel inclined to tackle something on the TODO list, then by all +means go ahead and do it! + +If you're contemplating something non-trivial then you'll probably +want to bring it up on the mailing list first to get an idea about the +current state of play, find out if anyone's already working on it, and +so on. + +When you start to hack on the Template Toolkit, please make sure you +start from the latest developer release. Stable releases are uploaded +to CPAN and have all-numerical version numbers, e.g. 2.04, 2.05. +Developer releases are available from the Template Toolkit web site +and have a character suffix on the version, e.g. 2.04a, 2.04b, etc. + +Once you've made your changes, please remember to update the test +suite by adding extra tests to one of the existing test scripts in +the 't' sub-directory, or by adding a new test script of your own. +And of course, run C<make test> to ensure that all the tests pass +with your new code. + +Don't forget that any files you do add will need to be added to the +MANIFEST. Running 'make manifest' will do this for you, but you need +to make sure you haven't got any other temporary files lying around +that might also get added to it. + +Documentation is often something that gets overlooked but it's just +as important as the code. If you're updating existing documentation +then you should download the 'docsrc' bundle from which all the +Template Toolkit documentation is built and make your changes in there. +It's also available from the Template Toolkit web site. See the +README distributed in the archive for further information. + +If you're adding a new module, a plugin module, for example, then it's +OK to include the POD documentation in with the module, but I<please> +write it all in one piece at the end of the file, I<after> the code +(just look at any other Template::* module for an example). It's a +religious issue, I know, but I have a strong distaste for POD documentation +interspersed throughout the code. In my not-so-humble opinion, it makes +both the code and the documentation harder to read (same kinda problem +as embedding Perl in HTML). + +Aesthetics aside, if I do want to extract the documentation into the +docsrc bundle then it's easy for me to do it if it's all written in +one chunk and extremely tedious if not. So for practical reasons +alone, please keep Perl and POD sections separate. Comment blocks +within the code are of course welcome. + +To share your changes with the rest of the world, you'll need to +prepare a patch file. To do this you should have 2 directories +side-by-side, one which is the original, unmodified distribution +directory for the latest developer release, and the other is a +copy of that same directory which includes your changes. + +The following example shows a typical hacking session. First we +unpack the latest developer release. + + $ tar zxf Template-Toolkit-2.05c.tar.gz + +At this point, it's a good idea to rename the directory to give +some indicate of what it contains. + + $ mv Template-Toolkit-2.05c Template-Toolkit-2.05c-abw-xyz-hack + +Then go hack! + + $ cd Template-Toolkit-2.05c-abw-xyz-hack + + [ hacking ] + + $ cd .. + +When you're all done and ready to prepare a patch, unpack the +distribution archive again so that you've got the original to +diff against your new code. + + $ tar zxf Template-Toolkit-2.05c.tar.gz + +You should now have an original distribution directory and a modified +version of that same directory, side-by-side. + + $ ls + Template-Toolkit-2.05c Template-Toolkit-2.05c-abw-xyz-hack + +Now run diff and save the output into an appropriately named patch +file. + + $ diff -Naur Template-Toolkit-2.05c Template-Toolkit-2.05c-abw-xyz-hack > patch-TT205c-abw-xyz-hack + +You can then post the generated patch file to the mailing list, +describing what it does, why it does it, how it does it and any +other relevant information. + +If you want to apply someone else's patch then you should start with the +same original distribution source on which the patch is based. From within +the root of the distribution, run 'patch' feeding in the patch file as +standard input. The 'p1' option is required to strip the first element +of the path name (e.g. Template-Toolkit-2.05c/README becomes README which +is then the correct path). + + $ tar zxf Template-Toolkit-2.05c.tar.gz + $ cd Template-Toolkit-2.05c + $ patch -p1 < ../patch-TT205c-abw-xyz-hack + +The output generated by 'patch' should be something like the following: + + patching file README + patching file lib/Template.pm + patching file lib/Template/Provider.pm + patching file t/provider.t + +=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.13, released on 30 January 2004. + +=head1 COPYRIGHT + + Copyright (C) 1996-2004 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. + + + +=cut + +# Local Variables: +# mode: perl +# perl-indent-level: 4 +# indent-tabs-mode: nil +# End: +# +# vim: expandtab shiftwidth=4: diff --git a/lib/Template/Manual/Intro.pod b/lib/Template/Manual/Intro.pod new file mode 100644 index 0000000..c50c9e8 --- /dev/null +++ b/lib/Template/Manual/Intro.pod @@ -0,0 +1,295 @@ +#============================================================= -*-perl-*- +# +# Template::Manual::Intro +# +# DESCRIPTION +# This section provides a general introduction to the Template +# Toolkit, giving a quick overview of features, examples of template +# directives and use of the Template.pm module. It also described the +# basic concept underlying the toolkit: the separation of +# presentation elements from application logic and data. +# +# AUTHOR +# Andy Wardley <abw@andywardley.com> +# +# COPYRIGHT +# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved. +# Copyright (C) 1998-2001 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 +# +# +#======================================================================== + + +#------------------------------------------------------------------------ +# 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::Manual::Intro - Introduction to the Template Toolkit + +=head1 DESCRIPTION + +This section provides a general introduction to the Template Toolkit, +giving a quick overview of features, examples of template directives +and use of the Template.pm module. It also described the basic concept +underlying the toolkit: the separation of presentation elements from +application logic and data. + +The Template Toolkit is a collection of modules which implement a +fast, flexible, powerful and extensible template processing system. +It was originally designed and remains primarily useful for generating +dynamic web content, but it can be used equally well for processing +any kind of text documents. This POD documentation is all generated +using the Template Toolkit batch mode utility F<ttree>, for example. + +At the simplest level it provides an easy way to process template +files, filling in embedded variable references with their equivalent +values. + + Dear [% name %], + + It has come to our attention that your account is in + arrears to the sum of [% debt %]. + + Please settle your account before [% deadline %] or we + will be forced to revoke your Licence to Thrill. + + The Management. + +By default, template directives are embedded within the character +sequences '[%' ... '%]' but you can change these and various other +options to configure how the Template Toolkit looks, feels and works. +You can set the INTERPOLATE option, for example, if you prefer to +embed your variables in Perl style: + + Dear $name, + + It has come to our attention that your account is in + arrears to the sum of $debt. + ... + +=head2 Template.pm + +The Template.pm module is the front end to the Template Toolkit, +providing access to the full range of functionality through a single +module with a simple interface. It loads the other modules as +required and instantiates a default set of objects to handle +subsequent template processing requests. Configuration parameters may +be passed to the Template.pm constructor, new(), which are then used +to configure the underlying objects. + + use Template; + + my $tt = Template->new({ + INCLUDE_PATH => '/usr/local/templates', + INTERPOLATE => 1, + }) || die "$Template::ERROR\n"; + +The Template object implements a process() method for processing template +files or text. The name of the input template (or various other sources) +is passed as the first argument, followed by a reference to a hash array +of variable definitions for substitution in the template. + + my $vars = { + name => 'Count Edward van Halen', + debt => '3 riffs and a solo', + deadline => 'the next chorus', + }; + + $tt->process('letters/overdrawn', $vars) + || die $tt->error(), "\n"; + + +The process() method returns true (1) on success and prints the +template output to STDOUT, by default. On error, the process() method +returns false (undef). The error() method can then be called to +retrieve details of the error. + +=head2 Component Based Content Construction + +A number of special directives are provided, such as INSERT, INCLUDE +and PROCESS, which allow content to be built up from smaller template +components. This permits a modular approach to building a web site or +other content repository, promoting reusability, cross-site +consistency, ease of construction and subsequent maintenance. Common +elements such as headers, footers, menu bars, tables, and so on, can +be created as separate template files which can then be processed into +other documents as required. All defined variables are inherited by +these templates along with any additional "local" values specified. + + [% PROCESS header + title = "The Cat Sat on the Mat" + %] + + [% PROCESS menu %] + + The location of the missing feline has now been established. + Thank you for your assistance. + + [% INSERT legal/disclaimer %] + + [% PROCESS footer %] + +You can also define a template as a BLOCK within the same file and +PROCESS it just like any other template file. This can be invaluable +for building up repetitive elements such as tables, menus, etc. + + [% BLOCK tabrow %] + <tr><td>[% name %]</td><td>[% email %]</td></tr> + [% END %] + + <table> + [% PROCESS tabrow name="tom" email="tom@here.org" %] + [% PROCESS tabrow name="dick" email="disk@there.org" %] + [% PROCESS tabrow name="larry" email="larry@where.org" %] + </table> + +=head2 Data and Code Binding + +One of the key features that sets the Template Toolkit apart from +other template processors is the ability to bind template variables to +any kind of Perl data: scalars, lists, hash arrays, sub-routines and +objects. + + my $vars = { + root => 'http://here.com/there', + menu => [ 'modules', 'authors', 'scripts' ], + client => { + name => 'Doctor Joseph von Satriani', + id => 'JVSAT', + }, + checkout => sub { my $total = shift; ...; return $something }, + shopcart => My::Cool::Shopping::Cart->new(), + }; + +The Template Toolkit will automatically Do The Right Thing to access +the data in an appropriate manner to return some value which can then +be output. The dot operator '.' is used to access into lists and +hashes or to call object methods. The FOREACH directive is provided for +iterating through lists, and various logical tests are available using +directives such as IF, UNLESS, ELSIF, ELSE, SWITCH, CASE, etc. + + [% FOREACH section = menu %] + <a href="[% root %]/[% section %]/index.html">[% section %]</a> + [% END %] + + <b>Client</a>: [% client.name %] (id: [% client.id %]) + + [% IF shopcart.nitems %] + Your shopping cart contains the following items: + <ul> + [% FOREACH item = shopcart.contents %] + <li>[% item.name %] : [% item.qty %] @ [% item.price %] + [% END %] + </ul> + + [% checkout(shopcart.total) %] + + [% ELSE %] + No items currently in shopping cart. + [% END %] + +=head2 Advanced Features: Filters, Macros, Exceptions, Plugins + +The Template Toolkit also provides a number of additional directives +for advanced processing and programmatical functionality. It supports +output filters (FILTER), allows custom macros to be defined (MACRO), +has a fully-featured exception handling system (TRY, THROW, CATCH, +FINAL) and supports a plugin architecture (USE) which allows special +plugin modules and even regular Perl modules to be loaded and used +with the minimum of fuss. The Template Toolkit is "just" a template +processor but you can trivially extend it to incorporate the +functionality of any Perl module you can get your hands on. Thus, it +is also a scalable and extensible template framework, ideally suited +for managing the presentation layer for application servers, content +management systems and other web applications. + +=head2 Separating Presentation and Application Logic + +Rather than embedding Perl code or some other scripting language +directly into template documents, it encourages you to keep functional +components (i.e. Perl code) separate from presentation components +(e.g. HTML templates). The template variables provide the interface +between the two layers, allowing data to be generated in code and then +passed to a template component for displaying (pipeline model) or for +sub-routine or object references to be bound to variables which can +then be called from the template as and when required (callback +model). + +The directives that the Template Toolkit provide implement their own +mini programming language, but they're not really designed for +serious, general purpose programming. Perl is a far more appropriate +language for that. If you embed application logic (e.g. Perl or other +scripting language fragments) in HTML templates then you risk losing +the clear separation of concerns between functionality and +presentation. It becomes harder to maintain the two elements in +isolation and more difficult, if not impossible, to reuse code or +presentation elements by themselves. It is far better to write your +application code in separate Perl modules, libraries or scripts and +then use templates to control how the resulting data is presented as +output. Thus you should think of the Template Toolkit language as a +set of layout directives for displaying data, not calculating it. + +Having said that, the Template Toolkit doesn't force you into one +approach or the other. It attempts to be pragmatic rather than +dogmatic in allowing you to do whatever best gets the job done. +Thus, if you enable the EVAL_PERL option then you can happily embed +real Perl code in your templates within PERL ... END directives. + +=head2 Performance + +The Template Toolkit uses a fast YACC-like parser which compiles +templates into Perl code for maximum runtime efficiency. It also has +an advanced caching mechanism which manages in-memory and on-disk +(i.e. persistent) versions of compiled templates. The modules that +comprise the toolkit are highly configurable and the architecture +around which they're built is designed to be extensible. The Template +Toolkit provides a powerful framework around which content creation +and delivery systems can be built while also providing a simple +interface through the Template front-end module for general use. + +=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.13, released on 30 January 2004. + +=head1 COPYRIGHT + + Copyright (C) 1996-2004 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. + + + +=cut + +# Local Variables: +# mode: perl +# perl-indent-level: 4 +# indent-tabs-mode: nil +# End: +# +# vim: expandtab shiftwidth=4: diff --git a/lib/Template/Manual/Plugins.pod b/lib/Template/Manual/Plugins.pod new file mode 100644 index 0000000..7955640 --- /dev/null +++ b/lib/Template/Manual/Plugins.pod @@ -0,0 +1,552 @@ +#============================================================= -*-perl-*- +# +# Template::Manual::Plugins +# +# DESCRIPTION +# This section lists the standard plugins which can be used to extend +# the runtime functionality of the Template Toolkit. The plugins are +# distributed with the Template Toolkit but may required additional +# modules from CPAN. +# +# AUTHOR +# Andy Wardley <abw@andywardley.com> +# +# COPYRIGHT +# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved. +# Copyright (C) 1998-2001 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 +# +# +#======================================================================== + + +#------------------------------------------------------------------------ +# 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::Manual::Plugins - Standard plugins + +=head1 DESCRIPTION + +This section lists the standard plugins which can be used to extend the +runtime functionality of the Template Toolkit. The plugins are +distributed with the Template Toolkit but may required additional +modules from CPAN. + + + +=head1 TEMPLATE TOOLKIT PLUGINS + +The following plugin modules are distributed with the Template +Toolkit. Some of the plugins interface to external modules (detailed +below) which should be downloaded from any CPAN site and installed +before using the plugin. + +=head2 Autoformat + +The Autoformat plugin is an interface to Damian Conway's Text::Autoformat +Perl module which provides advanced text wrapping and formatting. See +L<Template::Plugin::Autoformat> and L<Text::Autoformat> for further +details. + + [% USE autoformat(left=10, right=20) %] + [% autoformat(mytext) %] # call autoformat sub + [% mytext FILTER autoformat %] # or use autoformat filter + +The Text::Autoformat module is available from CPAN: + + http://www.cpan.org/modules/by-module/Text/ + +=head2 CGI + +The CGI plugin is a wrapper around Lincoln Stein's +E<lt>lstein@genome.wi.mit.eduE<gt> CGI.pm module. The plugin is +distributed with the Template Toolkit (see L<Template::Plugin::CGI>) +and the CGI module itself is distributed with recent versions Perl, +or is available from CPAN. + + [% USE CGI %] + [% CGI.param('param_name') %] + [% CGI.start_form %] + [% CGI.popup_menu( Name => 'color', + Values => [ 'Green', 'Brown' ] ) %] + [% CGI.end_form %] + +=head2 Datafile + +Provides an interface to data stored in a plain text file in a simple +delimited format. The first line in the file specifies field names +which should be delimiter by any non-word character sequence. +Subsequent lines define data using the same delimiter as int he first +line. Blank lines and comments (lines starting '#') are ignored. See +L<Template::Plugin::Datafile> for further details. + +/tmp/mydata: + + # define names for each field + id : email : name : tel + # here's the data + fred : fred@here.com : Fred Smith : 555-1234 + bill : bill@here.com : Bill White : 555-5678 + +example: + + [% USE userlist = datafile('/tmp/mydata') %] + + [% FOREACH user = userlist %] + [% user.name %] ([% user.id %]) + [% END %] + +=head2 Date + +The Date plugin provides an easy way to generate formatted time and date +strings by delegating to the POSIX strftime() routine. See +L<Template::Plugin::Date> and L<POSIX> for further details. + + [% USE date %] + [% date.format %] # current time/date + + File last modified: [% date.format(template.modtime) %] + +=head2 Directory + +The Directory plugin provides a simple interface to a directory and +the files within it. See L<Template::Plugin::Directory> for further +details. + + [% USE dir = Directory('/tmp') %] + [% FOREACH file = dir.files %] + # all the plain files in the directory + [% END %] + [% FOREACH file = dir.dirs %] + # all the sub-directories + [% END %] + +=head2 DBI + +The DBI plugin, developed by Simon Matthews +E<lt>sam@knowledgepool.comE<gt>, brings the full power of Tim Bunce's +E<lt>Tim.Bunce@ig.co.ukE<gt> database interface module (DBI) to your +templates. See L<Template::Plugin::DBI> and L<DBI> for further details. + + [% USE DBI('dbi:driver:database', 'user', 'pass') %] + + [% FOREACH user = DBI.query( 'SELECT * FROM users' ) %] + [% user.id %] [% user.name %] + [% END %] + +The DBI and relevant DBD modules are available from CPAN: + + http://www.cpan.org/modules/by-module/DBI/ + +=head2 Dumper + +The Dumper plugin provides an interface to the Data::Dumper module. See +L<Template::Plugin::Dumper> and L<Data::Dumper> for futher details. + + [% USE dumper(indent=0, pad="<br>") %] + [% dumper.dump(myvar, yourvar) %] + +=head2 File + +The File plugin provides a general abstraction for files and can be +used to fetch information about specific files within a filesystem. +See L<Template::Plugin::File> for further details. + + [% USE File('/tmp/foo.html') %] + [% File.name %] # foo.html + [% File.dir %] # /tmp + [% File.mtime %] # modification time + +=head2 Filter + +This module implements a base class plugin which can be subclassed +to easily create your own modules that define and install new filters. + + package MyOrg::Template::Plugin::MyFilter; + + use Template::Plugin::Filter; + use base qw( Template::Plugin::Filter ); + + sub filter { + my ($self, $text) = @_; + + # ...mungify $text... + + return $text; + } + + # now load it... + [% USE MyFilter %] + + # ...and use the returned object as a filter + [% FILTER $MyFilter %] + ... + [% END %] + +See L<Template::Plugin::Filter> for further details. + +=head2 Format + +The Format plugin provides a simple way to format text according to a +printf()-like format. See L<Template::Plugin::Format> for further +details. + + [% USE bold = format('<b>%s</b>') %] + [% bold('Hello') %] + +=head2 GD::Image, GD::Polygon, GD::Constants + +These plugins provide access to the GD graphics library via Lincoln +D. Stein's GD.pm interface. These plugins allow PNG, JPEG and other +graphical formats to be generated. + + [% FILTER null; + USE im = GD.Image(100,100); + # allocate some colors + black = im.colorAllocate(0, 0, 0); + red = im.colorAllocate(255,0, 0); + blue = im.colorAllocate(0, 0, 255); + # Draw a blue oval + im.arc(50,50,95,75,0,360,blue); + # And fill it with red + im.fill(50,50,red); + # Output image in PNG format + im.png | stdout(1); + END; + -%] + +See L<Template::Plugin::GD::Image> for further details. + +=head2 GD::Text, GD::Text::Align, GD::Text::Wrap + +These plugins provide access to Martien Verbruggen's GD::Text, +GD::Text::Align and GD::Text::Wrap modules. These plugins allow the +layout, alignment and wrapping of text when drawing text in GD images. + + [% FILTER null; + USE gd = GD.Image(200,400); + USE gdc = GD.Constants; + black = gd.colorAllocate(0, 0, 0); + green = gd.colorAllocate(0, 255, 0); + txt = "This is some long text. " | repeat(10); + USE wrapbox = GD.Text.Wrap(gd, + line_space => 4, + color => green, + text => txt, + ); + wrapbox.set_font(gdc.gdMediumBoldFont); + wrapbox.set(align => 'center', width => 160); + wrapbox.draw(20, 20); + gd.png | stdout(1); + END; + -%] + +See L<Template::Plugin::GD::Text>, L<Template::Plugin::GD::Text::Align> +and L<Template::Plugin::GD::Text::Wrap> for further details. + +=head2 GD::Graph::lines, GD::Graph::bars, GD::Graph::points, GD::Graph::linespoin +ts, GD::Graph::area, GD::Graph::mixed, GD::Graph::pie + +These plugins provide access to Martien Verbruggen's GD::Graph module +that allows graphs, plots and charts to be created. These plugins allow +graphs, plots and charts to be generated in PNG, JPEG and other +graphical formats. + + [% FILTER null; + data = [ + ["1st","2nd","3rd","4th","5th","6th"], + [ 4, 2, 3, 4, 3, 3.5] + ]; + USE my_graph = GD.Graph.pie(250, 200); + my_graph.set( + title => 'A Pie Chart', + label => 'Label', + axislabelclr => 'black', + pie_height => 36, + transparent => 0, + ); + my_graph.plot(data).png | stdout(1); + END; + -%] + +See +L<Template::Plugin::GD::Graph::lines>, +L<Template::Plugin::GD::Graph::bars>, +L<Template::Plugin::GD::Graph::points>, +L<Template::Plugin::GD::Graph::linespoints>, +L<Template::Plugin::GD::Graph::area>, +L<Template::Plugin::GD::Graph::mixed>, +L<Template::Plugin::GD::Graph::pie>, and +L<GD::Graph>, +for more details. + +=head2 GD::Graph::bars3d, GD::Graph::lines3d, GD::Graph::pie3d + +These plugins provide access to Jeremy Wadsack's GD::Graph3d +module. This allows 3D bar charts and 3D lines plots to +be generated. + + [% FILTER null; + data = [ + ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"], + [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4], + ]; + USE my_graph = GD.Graph.bars3d(); + my_graph.set( + x_label => 'X Label', + y_label => 'Y label', + title => 'A 3d Bar Chart', + y_max_value => 8, + y_tick_number => 8, + y_label_skip => 2, + # shadows + bar_spacing => 8, + shadow_depth => 4, + shadowclr => 'dred', + transparent => 0, + my_graph.plot(data).png | stdout(1); + END; + -%] + +See +L<Template::Plugin::GD::Graph::lines3d>, +L<Template::Plugin::GD::Graph::bars3d>, and +L<Template::Plugin::GD::Graph::pie3d> +for more details. + +=head2 HTML + +The HTML plugin is very new and very basic, implementing a few useful +methods for generating HTML. It is likely to be extended in the future +or integrated with a larger project to generate HTML elements in a generic +way (as discussed recently on the mod_perl mailing list). + + [% USE HTML %] + [% HTML.escape("if (a < b && c > d) ..." %] + [% HTML.attributes(border => 1, cellpadding => 2) %] + [% HTML.element(table => { border => 1, cellpadding => 2 }) %] + +See L<Template::Plugin::HTML> for further details. + +=head2 Iterator + +The Iterator plugin provides a way to create a Template::Iterator +object to iterate over a data set. An iterator is created +automatically by the FOREACH directive and is aliased to the 'loop' +variable. This plugin allows an iterator to be explicitly created +with a given name, or the default plugin name, 'iterator'. See +L<Template::Plugin::Iterator> for further details. + + [% USE iterator(list, args) %] + + [% FOREACH item = iterator %] + [% '<ul>' IF iterator.first %] + <li>[% item %] + [% '</ul>' IF iterator.last %] + [% END %] + +=head2 Pod + +This plugin provides an interface to the L<Pod::POM|Pod::POM> module +which parses POD documents into an internal object model which can +then be traversed and presented through the Template Toolkit. + + [% USE Pod(podfile) %] + + [% FOREACH head1 = Pod.head1; + FOREACH head2 = head1/head2; + ... + END; + END + %] + +=head2 String + +The String plugin implements an object-oriented interface for +manipulating strings. See L<Template::Plugin::String> for further +details. + + [% USE String 'Hello' %] + [% String.append(' World') %] + + [% msg = String.new('Another string') %] + [% msg.replace('string', 'text') %] + + The string "[% msg %]" is [% msg.length %] characters long. + +=head2 Table + +The Table plugin allows you to format a list of data items into a +virtual table by specifying a fixed number of rows or columns, with +an optional overlap. See L<Template::Plugin::Table> for further +details. + + [% USE table(list, rows=10, overlap=1) %] + + [% FOREACH item = table.col(3) %] + [% item %] + [% END %] + +=head2 URL + +The URL plugin provides a simple way of contructing URLs from a base +part and a variable set of parameters. See L<Template::Plugin::URL> +for further details. + + [% USE mycgi = url('/cgi-bin/bar.pl', debug=1) %] + + [% mycgi %] + # ==> /cgi/bin/bar.pl?debug=1 + + [% mycgi(mode='submit') %] + # ==> /cgi/bin/bar.pl?mode=submit&debug=1 + +=head2 Wrap + +The Wrap plugin uses the Text::Wrap module by David Muir Sharnoff +E<lt>muir@idiom.comE<gt> (with help from Tim Pierce and many many others) +to provide simple paragraph formatting. See L<Template::Plugin::Wrap> +and L<Text::Wrap> for further details. + + [% USE wrap %] + [% wrap(mytext, 40, '* ', ' ') %] # use wrap sub + [% mytext FILTER wrap(40) -%] # or wrap FILTER + +The Text::Wrap module is available from CPAN: + + http://www.cpan.org/modules/by-module/Text/ + +=head2 XML::DOM + +The XML::DOM plugin gives access to the XML Document Object Module via +Clark Cooper E<lt>cooper@sch.ge.comE<gt> and Enno Derksen's +E<lt>enno@att.comE<gt> XML::DOM module. See L<Template::Plugin::XML::DOM> +and L<XML::DOM> for further details. + + [% USE dom = XML.DOM %] + [% doc = dom.parse(filename) %] + + [% FOREACH node = doc.getElementsByTagName('CODEBASE') %] + * [% node.getAttribute('href') %] + [% END %] + +The plugin requires the XML::DOM module, available from CPAN: + + http://www.cpan.org/modules/by-module/XML/ + +=head2 XML::RSS + +The XML::RSS plugin is a simple interface to Jonathan Eisenzopf's +E<lt>eisen@pobox.comE<gt> XML::RSS module. A RSS (Rich Site Summary) +file is typically used to store short news 'headlines' describing +different links within a site. This plugin allows you to parse RSS +files and format the contents accordingly using templates. +See L<Template::Plugin::XML::RSS> and L<XML::RSS> for further details. + + [% USE news = XML.RSS(filename) %] + + [% FOREACH item = news.items %] + <a href="[% item.link %]">[% item.title %]</a> + [% END %] + +The XML::RSS module is available from CPAN: + + http://www.cpan.org/modules/by-module/XML/ + +=head2 XML::Simple + +This plugin implements an interface to the L<XML::Simple|XML::Simple> +module. + + [% USE xml = XML.Simple(xml_file_or_text) %] + + [% xml.head.title %] + +See L<Template::Plugin::XML::Simple> for further details. + +=head2 XML::Style + +This plugin defines a filter for performing simple stylesheet based +transformations of XML text. + + [% USE xmlstyle + table = { + attributes = { + border = 0 + cellpadding = 4 + cellspacing = 1 + } + } + %] + + [% FILTER xmlstyle %] + <table> + <tr> + <td>Foo</td> <td>Bar</td> <td>Baz</td> + </tr> + </table> + [% END %] + +See L<Template::Plugin::XML::Style> for further details. + +=head2 XML::XPath + +The XML::XPath plugin provides an interface to Matt Sergeant's +E<lt>matt@sergeant.orgE<gt> XML::XPath module. See +L<Template::Plugin::XML::XPath> and L<XML::XPath> for further details. + + [% USE xpath = XML.XPath(xmlfile) %] + [% FOREACH page = xpath.findnodes('/html/body/page') %] + [% page.getAttribute('title') %] + [% END %] + +The plugin requires the XML::XPath module, available from CPAN: + + http://www.cpan.org/modules/by-module/XML/ + +=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.13, released on 30 January 2004. + +=head1 COPYRIGHT + + Copyright (C) 1996-2004 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. + + + +=cut + +# Local Variables: +# mode: perl +# perl-indent-level: 4 +# indent-tabs-mode: nil +# End: +# +# vim: expandtab shiftwidth=4: diff --git a/lib/Template/Manual/Refs.pod b/lib/Template/Manual/Refs.pod new file mode 100644 index 0000000..b0c9719 --- /dev/null +++ b/lib/Template/Manual/Refs.pod @@ -0,0 +1,171 @@ +#============================================================= -*-perl-*- +# +# Template::Manual::Refs +# +# DESCRIPTION +# This section provides references to external modules, projects and +# other resources related to the Template Toolkit. +# +# AUTHOR +# Andy Wardley <abw@andywardley.com> +# +# COPYRIGHT +# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved. +# Copyright (C) 1998-2001 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 +# +# +#======================================================================== + + +#------------------------------------------------------------------------ +# 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::Manual::Refs - Related modules, projects and other resources + +=head1 DESCRIPTION + +This section provides references to external modules, projects and +other resources related to the Template Toolkit. + +=head2 Resources + +The Template Toolkit web site contains the latest information, news and +other resources. + + http://www.template-toolkit.org/ + +A mailing list exists for up-to-date information on the Template Toolkit +and for following and contributing to the development process. To +subscribe, send an email to + + templates-request@template-toolkit.org + +with the message 'subscribe' in the body. You can also use the web +interface to subscribe or browse the archives: + + http://www.template-toolkit.org/mailman/listinfo/templates + +The F<tpage> and F<ttree> scripts are distributed and installed along +with the Template Toolkit. The F<tpage> script simply processes named +files or STDIN if unspecified, using a default Template object. The +F<ttree> script can be used to process entire directory trees of templates, +allowing large content systems such as web sites to be rebuilt from a +single command or configuration file. + + perldoc tpage + perldoc ttree + +The F<Template::Tutorial> document provides an introduction to the Template +Toolkit and shows some typical examples of usage. + + perldoc Template::Tutorial + +You may also like to consult the paper 'Building and Managing Web Systems +with the Template Toolkit' and accompanying slides from the presentation +at the 4th Perl Conference. These are available from the Template +Toolkit web site: + + http://www.template-toolkit.org/docs.html + + + +=head2 Projects + +There are a number of other projects related to the Template Toolkit. + +=over 4 + +=item OpenInteract + +OpenInteract is a robust web application framework built to run under +Apache and mod_perl using the Template Toolkit as a foundation. + + http://www.openinteract.org/ + +=item Apache::Template + +This is an Apache/mod_perl interface to the Template Toolkit. Available +from CPAN in the directory: + + http://www.cpan.org/modules/by-module/Apache/ + +=item AxKit::Template + +AxKit is Matt Sergeant's Apache XML Delivery Toolkit. AxKit::Template +provides an interface between AxKit and the Template Toolkit. Available +from CPAN in the directory: + + http://www.cpan.org/modules/by-module/Apache/ + +=item Slashcode + +Slashcode is the code which runs Slashdot. Version 2 uses the +Template Toolkit for generating the user interface from database +driven template. + + http://slashcode.org/ + +=item OpenFrame + +OpenFrame is an open source application framework for distributed +media applications. It ships with a generator for the Template +Toolkit. + + http://openframe.fotango.com/ + +=item PCMT + +PCMT is the Personal Content Management Toolkit. It uses the Template +Toolkit as the presentation engine. + + http://pcmt.sf.net/ + +=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.13, released on 30 January 2004. + +=head1 COPYRIGHT + + Copyright (C) 1996-2004 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. + + + +=cut + +# Local Variables: +# mode: perl +# perl-indent-level: 4 +# indent-tabs-mode: nil +# End: +# +# vim: expandtab shiftwidth=4: diff --git a/lib/Template/Manual/Syntax.pod b/lib/Template/Manual/Syntax.pod new file mode 100644 index 0000000..cc1b6c8 --- /dev/null +++ b/lib/Template/Manual/Syntax.pod @@ -0,0 +1,306 @@ +#============================================================= -*-perl-*- +# +# Template::Manual::Syntax +# +# DESCRIPTION +# This section describes the syntax, structure and semantics of the +# Template Toolkit directives and general presentation language. +# +# AUTHOR +# Andy Wardley <abw@andywardley.com> +# +# COPYRIGHT +# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved. +# Copyright (C) 1998-2001 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 +# +# +#======================================================================== + + +#------------------------------------------------------------------------ +# 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::Manual::Syntax - Directive syntax, structure and semantics + +=head1 DESCRIPTION + +This section describes the syntax, structure and semantics of the +Template Toolkit directives and general presentation language. + +=head2 Tag Styles + +By default, template directives are embedded within the character sequences +'[%' and '%]'. e.g. + + [% PROCESS header %] + + <h1>Hello World!</h1> + <a href="[% page.next %]"><img src="[% icon.next %].gif"></a> + + [% PROCESS footer %] + +You can change the tag characters using the START_TAG, END_TAG and +TAG_STYLE configuration options. You can also use the TAGS directive +to define a new tag style for the current template file. + +You can also set the INTERPOLATE option to allow simple variable +references to be embedded directly in templates, prefixed by a '$'. + + # INTERPOLATE => 0 + <td>[% name %]</td> <td>[% email %]</td> + + # INTERPOLATE => 1 + <td>$name</td> <td>$email</td> + +Directives may be embedded anywhere in a line of text and can be split +across several lines. Insignificant whitespace is generally ignored +within the directive. + + [% INCLUDE header + title = 'Hello World' + bgcol = '#ffffff' + %] + + [%INCLUDE menu align='right'%] + + Name: [% name %] ([%id%]) + +=head2 Comments + +The '#' character is used to indicate comments within a directive. +When placed immediately inside the opening directive tag, it causes +the entire directive to be ignored. + + [%# this entire directive is ignored no + matter how many lines it wraps onto + %] + +In any other position, it causes the remainder of the current line to +be treated as a comment. + + [% # this is a comment + theta = 20 # so is this + rho = 30 # <aol>me too!</aol> + %] + +=head2 Chomping Whitespace + +You can add '-' or '+' to the immediate start or end of a directive +tag to control the whitespace chomping options. See the PRE_CHOMP and +POST_CHOMP options for further details. + + [% BLOCK foo -%] # remove trailing newline + This is block foo + [%- END %] # remove leading newline + +=head2 Implicit Directives: GET and SET + +The simplest directives are GET and SET which retrieve and update +variable values respectively. The GET and SET keywords are actually +optional as the parser is smart enough to see them for what they +really are (but note the caveat below on using side-effect notation). +Thus, you'll generally see: + + [% SET foo = 10 %] + [% GET foo %] + +written as: + + [% foo = 10 %] + [% foo %] + +You can also express simple logical statements as implicit GET directives: + + [% title or template.title or 'Default Title' %] + + [% mode == 'graphics' ? "Graphics Mode Enabled" : "Text Mode" %] + +All other directives should start with a keyword specified in UPPER +CASE (but see the ANYCASE option). All directives keywords are in +UPPER CASE to make them visually distinctive and to distinguish them +from variables of the same name but different case. It is perfectly +valid, for example, to define a variable called 'stop' which is +entirely separate from the STOP directive. + + [% stop = 'Clackett Lane Bus Depot' %] + + The bus will next stop at [% stop %] # variable + + [% STOP %] # directive + +=head2 Block Directives + +Directives such as FOREACH, WHILE, BLOCK, FILTER, etc., mark the start +of a block which may contain text or other directives up to the +matching END directive. Blocks may be nested indefinitely. The +IF, UNLESS, ELSIF and ELSE directives also define blocks and may be +grouped together in the usual manner. + + [% FOREACH item = [ 'foo' 'bar' 'baz' ] %] + * Item: [% item %] + [% END %] + + [% BLOCK footer %] + Copyright 2000 [% me %] + [% INCLUDE company/logo %] + [% END %] + + [% IF foo %] + [% FOREACH thing = foo.things %] + [% thing %] + [% END %] + [% ELSIF bar %] + [% INCLUDE barinfo %] + [% ELSE %] + do nothing... + [% END %] + +Block directives can also be used in a convenient side-effect notation. + + [% INCLUDE userinfo FOREACH user = userlist %] + + [% INCLUDE debugtxt msg="file: $error.info" + IF debugging %] + + [% "Danger Will Robinson" IF atrisk %] + +versus: + + [% FOREACH user = userlist %] + [% INCLUDE userinfo %] + [% END %] + + [% IF debugging %] + [% INCLUDE debugtxt msg="file: $error.info" %] + [% END %] + + [% IF atrisk %] + Danger Will Robinson + [% END %] + +=head2 Capturing Block Output + +The output of a directive can be captured by simply assigning the directive +to a variable. + + [% headtext = PROCESS header title="Hello World" %] + + [% people = PROCESS userinfo FOREACH user = userlist %] + +This can be used in conjunction with the BLOCK directive for defining large +blocks of text or other content. + + [% poem = BLOCK %] + The boy stood on the burning deck, + His fleece was white as snow. + A rolling stone gathers no moss, + And Keith is sure to follow. + [% END %] + +Note one important caveat of using this syntax in conjunction with side-effect +notation. The following directive does not behave as might be expected: + + [% var = 'value' IF some_condition %] + +In this case, the directive is interpreted as (spacing added for clarity) + + [% var = IF some_condition %] + value + [% END %] + +rather than + + [% IF some_condition %] + [% var = 'value' %] + [% END %] + +The variable is assigned the output of the IF block which returns +'value' if true, but nothing if false. In other words, the following +directive will always cause 'var' to be cleared. + + [% var = 'value' IF 0 %] + +To achieve the expected behaviour, the directive should be written as: + + [% SET var = 'value' IF some_condition %] + +=head2 Chaining Filters + +Multiple FILTER directives can be chained together in sequence. They +are called in the order defined, piping the output of one into the +input of the next. + + [% PROCESS somefile FILTER truncate(100) FILTER html %] + +The pipe character, '|', can also be used as an alias for FILTER. + + [% PROCESS somefile | truncate(100) | html %] + +=head2 Multiple Directive Blocks + +Multiple directives can be included within a single tag when delimited +by semi-colons, ';'. Note however that the TAGS directive must always +be specified in a tag by itself. + + [% IF title; + INCLUDE header; + ELSE; + INCLUDE other/header title="Some Other Title"; + END + %] + +versus + + [% IF title %] + [% INCLUDE header %] + [% ELSE %] + [% INCLUDE other/header title="Some Other Title" %] + [% END %] + +=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.13, released on 30 January 2004. + +=head1 COPYRIGHT + + Copyright (C) 1996-2004 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. + + + +=cut + +# Local Variables: +# mode: perl +# perl-indent-level: 4 +# indent-tabs-mode: nil +# End: +# +# vim: expandtab shiftwidth=4: diff --git a/lib/Template/Manual/VMethods.pod b/lib/Template/Manual/VMethods.pod new file mode 100644 index 0000000..7e380fa --- /dev/null +++ b/lib/Template/Manual/VMethods.pod @@ -0,0 +1,529 @@ +#============================================================= -*-perl-*- +# +# Template::Manual::VMethods +# +# DESCRIPTION +# The Template Toolkit provides virtual methods for manipulating +# variable values. Most of them are analogous to regular Perl +# functions of the same names. This section describes the different +# virtual methods that can be applied to scalar, list and hash +# values. +# +# AUTHOR +# Andy Wardley <abw@andywardley.com> +# +# COPYRIGHT +# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved. +# Copyright (C) 1998-2001 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 +# +# +#======================================================================== + + +#------------------------------------------------------------------------ +# 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::Manual::VMethods - Virtual Methods + +=head1 DESCRIPTION + +The Template Toolkit provides virtual methods for manipulating variable +values. Most of them are analogous to regular Perl functions of the +same names. This section describes the different virtual methods that +can be applied to scalar, list and hash values. + +=head2 Scalar Virtual Methods + +=over 4 + +=item defined + +Returns true if the value is defined. + + [% user = get_user(uid) IF uid.defined %] + +=item length + +Returns the length of the string representation of the item: + + [% IF password.length < 8 %] + Password too short, dumbass! + [% END %] + +=item repeat(n) + +Repeat the string a specified number of times. + + [% name = 'foo' %] + [% name.repeat(3) %] # foofoofoo + +=item replace(search, replace) + +Outputs the string with all instances of the first argument (specified +as a Perl regular expression) with the second. + + [% name = 'foo, bar & baz' %] + [% name.replace('\W+', '_') %] # foo_bar_baz + +=item match(pattern) + +Performs a regular expression match on the string using the pattern +passed as an argument. If the pattern matches the string then the +method returns a reference to a list of any strings captured within +parenthesis in the pattern. + + [% name = 'Larry Wall' %] + [% matches = name.match('(\w+) (\w+)') %] + [% matches.1 %], [% matches.0 %] # Wall, Larry + +If the pattern does not match then the method returns false, rather +than returning an empty list which Perl and the Template Toolkit both +consider to be a true value. This allows you to write expression like +this. + + [% "We're not worthy!" IF name.match('Larry Wall') %] + + [% IF (matches = name.match('(\w+) (\w+)')) %] + pattern matches: [% matches.join(', ') %] + [% ELSE %] + pattern does not match + [% END %] + +Any regex modifiers, like C</s>, should be added in the regex using +the C<(?s)> syntax. For example, to modify the regex to disregard +whitespace (the C</x> switch), use: + + [% re = '(?x) + (\w+) + [ ] + (\w+) + '; + matches = name.match(re); + %] + +=item search(pattern) + +Performs a similar function to 'match' but simply returns true if the +string matches the regular expression pattern passed as an argument. + + [% name = 'foo bar baz' %] + [% name.search('bar') ? 'bar' : 'no bar' %] # bar + +This virtual method is now deprecated in favour of 'match'. Move along +now, there's nothing more to see here. + +=item split(pattern) + +Calls Perl's split() function to split a string into a list of +strings. + + [% FOREACH dir = mypath.split(':') %] + [% dir %] + [% END %] + +=item chunk(size) + +Splits the value into a list of chunks of a certain size. + + [% ccard_no = "1234567824683579"; + ccard_no.chunk(4).join + %] + +Output: + + 1234 5678 2468 3579 + +If the size is specified as a negative number then the text will +be chunked from right-to-left. This gives the correct grouping +for numbers, for example. + + [% number = 1234567; + number.chunk(-3).join(',') + %] + +Output: + + 1,234,567 + +=item list + +Return the value as a single element list. This can be useful if you +have a variable which may contain a single item or a list and you want +to treat them equally. The 'list' method can be called against a list +reference and will simply return the original reference, effectively +a no-op. + + [% thing.list.size %] # thing can be a scalar or a list + +=item hash + +Return the value as a hash reference containing a single entry with +the key 'value' indicating the original scalar value. As with the +'list' virtual method, this is generally used to help massage data +into different formats. + +=item size + +Always returns 1 for scalar values. This method is provided for +consistency with the hash and list size methods. + +=back + + +=head2 Hash Virtual Methods + +=over 4 + +=item keys, values, each + +The regular hash operators returning lists of keys, values or both. +Note how we use a '$' prefix on the 'key' variable in this example to +have it interpolated (i.e. replaced with its value) before use. + + [% FOREACH key = product.keys %] + [% key %] => [% product.$key %] + [% END %] + +=item sort, nsort + +Return a list of the keys, sorted alphabetically (sort) or numerically +(nsort) according to the corresponding values in the hash. + + [% FOREACH n = phones.sort %] + [% phones.$n %] is [% n %], + [% END %] + +=item import + +The import method can be called on a hash array to import the contents +of another hash array. + + [% hash1 = { + foo => 'Foo', + bar => 'Bar', + } + hash2 = { + wiz => 'Wiz', + woz => 'Woz', + } + %] + + [% hash1.import(hash2) %] + [% hash1.wiz %] # Wiz + +You can also call the import() method by itself to import a hash array +into the current namespace hash. + + [% user = { id => 'lwall', name => 'Larry Wall' } %] + [% import(user) %] + [% id %]: [% name %] # lwall: Larry Wall + +=item defined, exists + +Returns a true or false value if an item in the hash denoted by the key +passed as an argument is defined or exists, respectively. + + [% hash.defined('somekey') ? 'yes' : 'no' %] + [% hash.exists('somekey') ? 'yes' : 'no' %] + +=item size + +Returns the number of key =E<gt> value pairs in the hash. + +=item item + +Returns an item from the hash using a key passed as an argument. + + [% hash.item('foo') %] # same as hash.foo + +=item list + +Returns the contents of the hash in list form. An argument can be +passed to indicate the desired items required in the list: 'keys' to +return a list of the keys (same as hash.keys), 'values' to return a +list of the values (same as hash.values), or 'each' to return as list +of (key, value) pairs (same as hash.each). When called without an +argument it returns a list of hash references, each of which contains +a 'key' and 'value' item representing a single key =E<gt> value pair +in the hash. + +=back + + +=head2 List Virtual Methods + +=over 4 + +=item first, last + +Returns the first/last item in the list. The item is not removed from the +list. + + [% results.first %] to [% results.last %] + +If either is given a numeric argument C<n>, they return the first or +last C<n> elements: + + The first 5 results are [% results.first(5).join(", ") %]. + +=item size, max + +Returns the size of a list (number of elements) and the maximum +index number (size - 1), respectively. + + [% results.size %] search results matched your query + +=item reverse + +Returns the items of the list in reverse order. + + [% FOREACH s = scores.reverse %] + ... + [% END %] + +=item join + +Joins the items in the list into a single string, using Perl's join +function. + + [% items.join(', ') %] + +=item grep + +Returns a list of the items in the list that match a regular expression +pattern. + + [% FOREACH directory.files.grep('\.txt$') %] + ... + [% END %] + +=item sort, nsort + +Returns the items in alpha (sort) or numerical (nsort) order. + + [% library = books.sort %] + +An argument can be provided to specify a search key. Where an item in +the list is a hash reference, the search key will be used to retrieve a +value from the hash which will then be used as the comparison value. +Where an item is an object which implements a method of that name, the +method will be called to return a comparison value. + + [% library = books.sort('author') %] + +In the example, the 'books' list can contains hash references with +an 'author' key or objects with an 'author' method. + +=item unshift(item), push(item) + +Adds an item to the start/end of a list. + + [% mylist.unshift('prev item') %] + [% mylist.push('next item') %] + +=item shift, pop + +Removes the first/last item from the list and returns it. + + [% first = mylist.shift %] + [% last = mylist.pop %] + +=item unique + +Returns a list of the unique elements in a list, in the same order +as in the list itself. + + [% mylist = [ 1, 2, 3, 2, 3, 4, 1, 4, 3, 4, 5 ] %] + [% numbers = mylist.unique %] + +While this can be explicitly sorted, it is not required that the list +be sorted before the unique elements are pulled out (unlike the Unix +command line utility). + + [% numbers = mylist.unique.sort %] + +=item merge + +Returns a list composed of zero or more other lists: + + [% list_one = [ 1 2 3 ]; + list_two = [ 4 5 6 ]; + list_three = [ 7 8 9 ]; + list_four = list_one.merge(list_two, list_three); + %] + +The original lists are not modified. + +=item slice(from, to) + +Returns a slice of items in the list between the bounds passed as +arguments. If the second argument, 'to', isn't specified, then it +defaults to the last item in the list. The original list is not +modified. + + [% first_three = list.slice(0,2) %] + + [% last_three = list.slice(-3, -1) %] + +=item splice(offset, length, list) + +Behaves just like Perl's splice() function allowing you to selectively +remove and/or replace elements in a list. It removes 'length' items +from the list, starting at 'offset' and replaces them with the items +in 'list'. + + [% play_game = [ 'play', 'scrabble' ]; + ping_pong = [ 'ping', 'pong' ]; + redundant = play_game.splice(1, 1, ping_pong); + + redundant.join; # scrabble + play_game.join; # play ping pong + %] + +The method returns a list of the items removed by the splice. +You can use the CALL directive to ignore the output if you're +not planning to do anything with it. + + [% CALL play_game.splice(1, 1, ping_pong) %] + +As well as providing a reference to a list of replacement values, +you can pass in a list of items. + + [% CALL list.splice(-1, 0, 'foo', 'bar') %] + +Be careful about passing just one item in as a replacement value. +If it is a reference to a list then the contents of the list will +be used. If it's not a list, then it will be treated as a single +value. You can use square brackets around a single item if you +need to be explicit: + + [% # push a single item, an_item + CALL list.splice(-1, 0, an_item); + + # push the items from another_list + CALL list.splice(-1, 0, another_list); + + # push a reference to another_list + CALL list.splice(-1, 0, [ another_list ]); + %] + +=back + +=head2 Automagic Promotion of Scalar to List for Virtual Methods + +In addition to the scalar virtual methods listed in the previous +section, you can also call any list virtual method against a scalar. +The item will be automagically promoted to a single element list and +the appropriate list virtual method will be called. + +One particular benefit of this comes when calling subroutines or +object methods that return a list of items, rather than the +preferred reference to a list of items. In this case, the +Template Toolkit automatically folds the items returned into +a list. + +The upshot is that you can continue to use existing Perl modules or +code that returns lists of items, without having to refactor it +just to keep the Template Toolkit happy (by returning references +to list). Class::DBI module is just one example of a particularly +useful module which returns values this way. + +If only a single item is returned from a subroutine then the +Template Toolkit assumes it meant to return a single item (rather +than a list of 1 item) and leaves it well alone, returning the +single value as it is. If you're executing a database query, +for example, you might get 1 item returned, or perhaps many +items which are then folded into a list. + +The FOREACH directive will happily accept either a list or a single +item which it will treat as a list. So it's safe to write directives +like this, where we assume that 'something' is bound to a subroutine +which might return 1 or more items: + + [% FOREACH item = something %] + ... + [% END %] + +The automagic promotion of scalars to single item lists means +that you can also use list virtual methods safely, even if you +only get one item returned. For example: + + [% something.first %] + [% something.join %] + [% something.reverse.join(', ') %] + +Note that this is very much a last-ditch behaviour. If the single +item return is an object with a 'first' method, for example, then that +will be called, as expected, in preference to the list virtual method. + +=head2 Defining Custom Virtual Methods + +You can define your own virtual methods for scalars, lists and hash +arrays. The Template::Stash package variables $SCALAR_OPS, $LIST_OPS +and $HASH_OPS are references to hash arrays that define these virtual +methods. HASH_OPS and LIST_OPS methods are subroutines that accept a +hash/list reference as the first item. SCALAR_OPS are subroutines +that accept a scalar value as the first item. Any other arguments +specified when the method is called will be passed to the subroutine. + + # load Template::Stash to make method tables visible + use Template::Stash; + + # define list method to return new list of odd numbers only + $Template::Stash::LIST_OPS->{ odd } = sub { + my $list = shift; + return [ grep { $_ % 2 } @$list ]; + }; + +template: + + [% primes = [ 2, 3, 5, 7, 9 ] %] + [% primes.odd.join(', ') %] # 3, 5, 7, 9 + +=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.13, released on 30 January 2004. + +=head1 COPYRIGHT + + Copyright (C) 1996-2004 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. + + + +=cut + +# Local Variables: +# mode: perl +# perl-indent-level: 4 +# indent-tabs-mode: nil +# End: +# +# vim: expandtab shiftwidth=4: diff --git a/lib/Template/Manual/Variables.pod b/lib/Template/Manual/Variables.pod new file mode 100644 index 0000000..e8d998c --- /dev/null +++ b/lib/Template/Manual/Variables.pod @@ -0,0 +1,868 @@ +#============================================================= -*-perl-*- +# +# Template::Manual::Variables +# +# DESCRIPTION +# This section describes the different ways in which Perl data can be +# bound to template variables and accessed via Template Toolkit +# directives. +# +# AUTHOR +# Andy Wardley <abw@andywardley.com> +# +# COPYRIGHT +# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved. +# Copyright (C) 1998-2001 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 +# +# +#======================================================================== + + +#------------------------------------------------------------------------ +# 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::Manual::Variables - Template variables and code bindings + +=head1 DESCRIPTION + +This section describes the different ways in which Perl data can be +bound to template variables and accessed via Template Toolkit +directives. + +=head2 Template Variables + +A reference to a hash array may be passed as the second argument to +the process() method, containing definitions of template variables. +The VARIABLES (a.k.a. PRE_DEFINE) option can also be used to pre-define +variables for all templates processed by the object. + + my $tt = Template->new({ + VARIABLES => { + version => 3.14, + release => 'Sahara', + }, + }); + + my $vars = { + serial_no => 271828, + }; + + $tt->process('myfile', $vars); + +'myfile': + + This is version [% version %] ([% release %]). + Serial number: [% serial_no %] + +output: + + This is version 3.14 (Sahara) + Serial number: 271828 + +Variable names may contain any alphanumeric characters or underscores. +They may be lower, upper or mixed case although the usual convention +is to use lower case. The case I<is> significant however, and 'foo', +'Foo' and 'FOO' are all different variables. Upper case variable +names are permitted, but not recommended due to a possible conflict +with an existing or future reserved word. As of version 2.00, these +are: + + GET CALL SET DEFAULT INSERT INCLUDE PROCESS WRAPPER + IF UNLESS ELSE ELSIF FOR FOREACH WHILE SWITCH CASE + USE PLUGIN FILTER MACRO PERL RAWPERL BLOCK META + TRY THROW CATCH FINAL NEXT LAST BREAK RETURN STOP + CLEAR TO STEP AND OR NOT MOD DIV END + + +The variable values may be of virtually any Perl type, including +simple scalars, references to lists, hash arrays, subroutines or +objects. The Template Toolkit will automatically apply the correct +procedure to accessing these values as they are used in the template. + +Example: + + my $vars = { + article => 'The Third Shoe', + person => { + id => 314, + name => 'Mr. Blue', + email => 'blue@nowhere.org', + }, + primes => [ 2, 3, 5, 7, 11, 13 ], + wizard => sub { return join(' ', 'Abracadabra!', @_) }, + cgi => CGI->new('mode=submit&debug=1'), + }; + +template: + + [% article %] + + [% person.id %]: [% person.name %] <[% person.email %]> + + [% primes.first %] - [% primes.last %], including [% primes.3 %] + [% primes.size %] prime numbers: [% primes.join(', ') %] + + [% wizard %] + [% wizard('Hocus Pocus!') %] + + [% cgi.param('mode') %] + +output: + + The Third Shoe + + 314: Mr. Blue <blue@nowhere.org> + + 2 - 13, including 7 + 6 prime numbers: 2, 3, 5, 7, 11, 13 + + Abracadabra! + Abracadabra! Hocus Pocus! + + submit + +=head2 Scalar Values + +Regular scalar variables are accessed by simply specifying their name. +As these are just entries in the top-level variable hash they can be +considered special cases of hash array referencing as described below, +with the main namespace hash automatically implied. + + [% article %] + +=head2 Hash Array References + +Members of hash arrays are accessed by specifying the hash reference +and key separated by the dot '.' operator. + + my $vars = { + 'home' => 'http://www.myserver.com/homepage.html', + 'page' => { + 'this' => 'mypage.html', + 'next' => 'nextpage.html', + 'prev' => 'prevpage.html', + }, + }; + +template: + + <a href="[% home %]">Home</a> + <a href="[% page.prev %]">Previous Page</a> + <a href="[% page.next %]">Next Page</a> + +output: + + <a href="http://www.myserver.com/homepage.html">Home</a> + <a href="prevpage.html">Previous Page</a> + <a href="nextpage.html">Next Page</a> + +Any key in a hash which starts with a '_' or '.' character will be +considered private and cannot be evaluated or updated from within a +template. The undefined value will be returned for any such variable +accessed which the Template Toolkit will silently ignore (unless the +DEBUG option is enabled). + + my $vars = { + message => 'Hello World!', + _secret => "On the Internet, no-one knows you're a dog", + thing => { + public => 123, + _private => 456, + '.hidden' => 789, + }, + }; + +template: + + [% message %] # outputs "Hello World!" + [% _secret %] # no output + [% thing.public %] # outputs "123" + [% thing._private %] # no output + [% thing..hidden %] # ERROR: unexpected token (..) + +To access a hash entry using a key stored in another variable, prefix +the key variable with '$' to have it interpolated before use (see +L<Variable Interpolation>). + + [% pagename = 'next' %] + [% page.$pagename %] # same as [% page.next %] + +When you assign to a variable that contains multiple namespace +elements (i.e. it has one or more '.' characters in the name), +any hashes required to represent intermediate namespaces will be +created automatically. In this following example, the 'product' +variable automatically springs into life as a hash array unless +otherwise defined. + + [% product.id = 'XYZ-2000' + product.desc = 'Bogon Generator' + product.price = 666 + %] + + The [% product.id %] [% product.desc %] + costs $[% product.price %].00 + +output: + + The XYZ-2000 Bogon Generator + costs $666.00 + +You can use Perl's familiar '{' ... '}' construct to explicitly create +a hash and assign it to a variable. Note that commas are optional +between key/value pairs and '=' can be used in place of '=E<gt>'. + + [% product = { + id => 'XYZ-2000', + desc => 'Bogon Generator', + price => 666, + } + %] + +=head2 List References + +Items in lists are also accessed by use of the dot operator. + + my $vars = { + 'people' => [ 'Tom', 'Dick', 'Larry' ], + }; + +template: + + [% people.0 %] # Tom + [% people.1 %] # Dick + [% people.2 %] # Larry + +The FOREACH directive can be used to iterate through items in a list. + + [% FOREACH person = people %] + Hello [% person %] + [% END %] + +output: + + Hello Tom + Hello Dick + Hello Larry + +Lists can be constructed in-situ using the regular anonymous list +'[' ... ']' construct. Commas between items are optional. + + [% cols = [ 'red', 'green', 'blue' ] %] + + [% FOREACH c = cols %] + ... + +or: + + [% FOREACH c = [ 'red', 'green', 'blue' ] %] + ... + +You can also create simple numerical sequences using the familiar '..' +operator: + + [% n = [ 1 .. 4 ] %] # n is [ 1, 2, 3, 4 ] + + [% x = 4 + y = 8 + z = [x..y] # z is [ 4, 5, 6, 7, 8 ] + %] + +=head2 Subroutines + +Template variables can contain references to Perl subroutines. When +the variable is used, the Template Toolkit will automatically call the +subroutine, passing any additional arguments specified. The return +value from the subroutine is used as the variable value and inserted +into the document output. + + my $vars = { + wizard => sub { return join(' ', 'Abracadabra!', @_) }, + }; + +template: + + [% wizard %] # Abracadabra! + [% wizard('Hocus Pocus!') %] # Abracadabra! Hocus Pocus! + + +=head2 Objects + +Template variables can also contain references to Perl objects. +Methods are called using the dot operator to specify the method +against the object variable. Additional arguments can be specified +as with subroutines. + + use CGI; + + ... + + my $vars = { + # hard coded CGI params for purpose of example + cgi => CGI->new('mode=submit&debug=1'), + }; + +template: + + [% FOREACH p = cgi.param %] # returns list of param keys + [% p %] => [% cgi.param(p) %] # fetch each param value + [% END %] + +output: + + mode => submit + debug => 1 + +Object methods can also be called as lvalues. That is, they can appear on +the left side of an assignment. The method will be called passing the +assigning value as an argument. + + [% myobj.method = 10 %] + +equivalent to: + + [% myobj.method(10) %] + +=head2 Parameters and Return Values + +Subroutines and methods will be passed any arguments specified in the +template. Any template variables in the argument list will first be +evaluated and their resultant values passed to the code. + + my $vars = { + mycode => sub { return 'received ' . join(', ', @_) }, + }; + +template: + + [% foo = 10 %] + [% mycode(foo, 20) %] # received 10, 20 + +Named parameters may also be specified. These are automatically collected +into a single hash array which is passed by reference as the B<last> +parameter to the sub-routine. Named parameters can be specified using +either '=E<gt>' or '=' and can appear anywhere in the argument list. + + my $vars = { + myjoin => \&myjoin, + }; + + sub myjoin { + # look for hash ref as last argument + my $params = ref $_[-1] eq 'HASH' ? pop : { }; + return join($params->{ joint } || ' + ', @_); + } + +template: + + [% myjoin(10, 20, 30) %] + [% myjoin(10, 20, 30, joint = ' - ' %] + [% myjoin(joint => ' * ', 10, 20, 30 %] + +output: + + 10 + 20 + 30 + 10 - 20 - 30 + 10 * 20 * 30 + +Parenthesised parameters may be added to any element of a variable, +not just those that are bound to code or object methods. At present, +parameters will be ignored if the variable isn't "callable" but are +supported for future extensions. Think of them as "hints" to that +variable, rather than just arguments passed to a function. + + [% r = 'Romeo' %] + [% r(100, 99, s, t, v) %] # outputs "Romeo" + +User code should return a value for the variable it represents. This +can be any of the Perl data types described above: a scalar, or +reference to a list, hash, subroutine or object. Where code returns a +list of multiple values the items will automatically be folded into a +list reference which can be accessed as per normal. + + my $vars = { + # either is OK, first is recommended + items1 => sub { return [ 'foo', 'bar', 'baz' ] }, + items2 => sub { return ( 'foo', 'bar', 'baz' ) }, + }; + +template: + + [% FOREACH i = items1 %] + ... + [% END %] + + [% FOREACH i = items2 %] + ... + [% END %] + +=head2 Error Handling + +Errors can be reported from user code by calling die(). Errors raised +in this way are caught by the Template Toolkit and converted to +structured exceptions which can be handled from within the template. +A reference to the exception object is then available as the 'error' +variable. + + my $vars = { + barf => sub { + die "a sick error has occurred\n"; + }, + }; + +template: + + [% TRY %] + [% barf %] # calls sub which throws error via die() + [% CATCH %] + [% error.info %] # outputs "a sick error has occurred\n" + [% END %] + +Error messages thrown via die() are converted to exceptions of type +'undef'. Exceptions of user-defined types can be thrown by calling +die() with a reference to a Template::Exception object. + + use Template::Exception; + + ... + + my $vars = { + login => sub { + ... + die Template::Exception->new('badpwd', + 'password too silly'); + }, + }; + +template: + + [% TRY %] + [% login %] + [% CATCH badpwd %] + Bad password: [% error.info %] + [% CATCH %] + Some other '[% error.type %]' error: [% error.info %] + [% END %] + +The exception types 'stop' and 'return' are used to implement the +STOP and RETURN directives. Throwing an exception as: + + die (Template::Exception->new('stop')); + +has the same effect as the directive: + + [% STOP %] + +Subroutines and methods can also raise errors by returning a list or +reference to a list containing the undefined value (undef) followed by +an exception object or error message. This is supported for backwards +compatibility with version 1 but may be deprecated in some future +version. + + my $vars = { + # currently equivalent + barf => sub { + die "I'm sorry Dave, I can't do that"; + }, + yack => sub { + return (undef, "I'm sorry Dave, I can't do that"); + }, + }; + +=head2 Virtual Methods + +The Template Toolkit implements a number of "virtual methods" which +can be applied to scalars, hashes or lists. For example: + + [% mylist = [ 'foo', 'bar', 'baz' ] %] + [% newlist = mylist.sort %] + +Here 'mylist' is a regular reference to a list, and 'sort' is +a virtual method that returns a new list of the items in sorted +order. You can chain multiple virtual methods together. For +example: + + [% mylist.sort.join(', ') %] + +Here the 'join' virtual method is called to join the sorted list into +a single string, generating the following output: + + bar, baz, foo + +See L<Template::Manual::VMethods> for details of all the virtual +methods available. + +=head2 Variable Interpolation + +The Template Toolkit uses '$' consistently to indicate that a variable +should be interpolated in position. Most frequently, you see this in +double-quoted strings: + + [% fullname = "$honorific $firstname $surname" %] + +Or embedded in plain text when the INTERPOLATE option is set: + + Dear $honorific $firstname $surname, + +The same rules apply within directives. If a variable is prefixed +with a '$' then it is replaced with its value before being used. The +most common use is to retrieve an element from a hash where the key is +stored in a variable. + + [% uid = 'abw' %] + [% userlist.$uid %] # same as 'userlist.abw' + +Curly braces can be used to delimit interpolated variable names where +necessary. + + [% userlist.${me.id}.name %] + +Directives such as INCLUDE, PROCESS, etc., that accept a template name +as the first argument, will automatically quote it for convenience. + + [% INCLUDE foo/bar.txt %] + +equivalent to: + + [% INCLUDE "foo/bar.txt" %] + +To INCLUDE a template whose name is stored in a variable, simply +prefix the variable name with '$' to have it interpolated. + + [% myfile = 'header' %] + [% INCLUDE $myfile %] + +equivalent to: + + [% INCLUDE header %] + +Note also that a variable containing a reference to a Template::Document +object can also be processed in this way. + + my $vars = { + header => Template::Document->new({ ... }), + }; + +template: + + [% INCLUDE $header %] + +=head2 Local and Global Variables + +Any simple variables that you create, or any changes you make to +existing variables, will only persist while the template is being +processed. The top-level variable hash is copied before processing +begins and any changes to variables are made in this copy, leaving the +original intact. The same thing happens when you INCLUDE another +template. The current namespace hash is cloned to prevent any +variable changes made in the included template from interfering with +existing variables. The PROCESS option bypasses the localisation step +altogether making it slightly faster, but requiring greater attention +to the possibility of side effects caused by creating or changing any +variables within the processed template. + + [% BLOCK change_name %] + [% name = 'bar' %] + [% END %] + + [% name = 'foo' %] + [% INCLUDE change_name %] + [% name %] # foo + [% PROCESS change_name %] + [% name %] # bar + +Dotted compound variables behave slightly differently because the +localisation process is only skin deep. The current variable +namespace hash is copied, but no attempt is made to perform a +deep-copy of other structures within it (hashes, arrays, objects, +etc). A variable referencing a hash, for example, will be copied to +create a new reference but which points to the same hash. Thus, the +general rule is that simple variables (undotted variables) are +localised, but existing complex structures (dotted variables) are not. + + [% BLOCK all_change %] + [% x = 20 %] # changes copy + [% y.z = 'zulu' %] # changes original + [% END %] + + [% x = 10 + y = { z => 'zebra' } + %] + [% INCLUDE all_change %] + [% x %] # still '10' + [% y.z %] # now 'zulu' + + +If you create a complex structure such as a hash or list reference +within a local template context then it will cease to exist when +the template is finished processing. + + [% BLOCK new_stuff %] + [% # define a new 'y' hash array in local context + y = { z => 'zulu' } + %] + [% END %] + + [% x = 10 %] + [% INCLUDE new_stuff %] + [% x %] # outputs '10' + [% y %] # nothing, y is undefined + +Similarly, if you update an element of a compound variable which +I<doesn't> already exists then a hash will be created automatically +and deleted again at the end of the block. + + [% BLOCK new_stuff %] + [% y.z = 'zulu' %] + [% END %] + +However, if the hash I<does> already exist then you will modify the +original with permanent effect. To avoid potential confusion, it is +recommended that you don't update elements of complex variables from +within blocks or templates included by another. + +If you want to create or update truly global variables then you can +use the 'global' namespace. This is a hash array automatically created +in the top-level namespace which all templates, localised or otherwise +see the same reference to. Changes made to variables within this +hash are visible across all templates. + + [% global.version = 123 %] + +=head2 Compile Time Constant Folding + +In addition to variables that get resolved each time a template is +processed, you can also define variables that get resolved just once +when the template is compiled. This generally results in templates +processing faster because there is less work to be done. + +To define compile-time constants, specify a CONSTANTS hash as a +constructor item as per VARIABLES. The CONSTANTS hash can contain any +kind of complex, nested, or dynamic data structures, just like regular +variables. + + my $tt = Template->new({ + CONSTANTS => { + version => 3.14, + release => 'skyrocket', + col => { + back => '#ffffff', + fore => '#000000', + }, + myobj => My::Object->new(), + mysub => sub { ... }, + joint => ', ', + }, + }); + +Within a template, you access these variables using the 'constants' +namespace prefix. + + Version [% constants.version %] ([% constants.release %]) + + Background: [% constants.col.back %] + +When the template is compiled, these variable references are replaced +with the corresponding value. No further variable lookup is then +required when the template is processed. + +You can call subroutines, object methods, and even virtual methods on +constant variables. + + [% constants.mysub(10, 20) %] + [% constants.myobj(30, 40) %] + [% constants.col.keys.sort.join(', ') %] + +One important proviso is that any arguments you pass to subroutines +or methods must also be literal values or compile time constants. + +For example, these are both fine: + + # literal argument + [% constants.col.keys.sort.join(', ') %] + + # constant argument + [% constants.col.keys.sort.join(constants.joint) %] + +But this next example will raise an error at parse time because +'joint' is a runtime variable and cannot be determined at compile +time. + + # ERROR: runtime variable argument! + [% constants.col.keys.sort.join(joint) %] + +The CONSTANTS_NAMESPACE option can be used to provide a different +namespace prefix for constant variables. For example: + + my $tt = Template->new({ + CONSTANTS => { + version => 3.14, + # ...etc... + }, + CONSTANTS_NAMESPACE => 'const', + }); + +Constants would then be referenced in templates as: + + [% const.version %] + +=head2 Special Variables + +A number of special variables are automatically defined by the Template +Toolkit. + +=over 4 + +=item template + +The 'template' variable contains a reference to the main template +being processed, in the form of a Template::Document object. This +variable is correctly defined within PRE_PROCESS, PROCESS and +POST_PROCESS templates, allowing standard headers, footers, etc., to +access metadata items from the main template. The 'name' and +'modtime' metadata items are automatically provided, giving the +template name and modification time in seconds since the epoch. + +Note that the 'template' variable always references the top-level +template, even when processing other template components via INCLUDE, +PROCESS, etc. + +=item component + +The 'component' variable is like 'template' but always contains a +reference to the current, innermost template component being processed. +In the main template, the 'template' and 'component' variable will +reference the same Template::Document object. In any other template +component called from the main template, the 'template' variable +will remain unchanged, but 'component' will contain a new reference +to the current component. + +This example should demonstrate the difference: + + $template->process('foo') + || die $template->error(), "\n"; + +'foo': + + [% template.name %] # foo + [% component.name %] # foo + [% PROCESS footer %] + +'footer': + + [% template.name %] # foo + [% component.name %] # footer + +=item loop + +Within a FOREACH loop, the 'loop' variable references the Template::Iterator +object responsible for controlling the loop. + + [% FOREACH item = [ 'foo', 'bar', 'baz' ] -%] + [% "Items:\n" IF loop.first -%] + [% loop.count %]/[% loop.size %]: [% item %] + [% END %] + +=item error + +Within a CATCH block, the 'error' variable contains a reference to the +Template::Exception object thrown from within the TRY block. The +'type' and 'info' methods can be called or the variable itself can +be printed for automatic stringification into a message of the form +"$type error - $info". See L<Template::Exception> for further details. + + [% TRY %] + ... + [% CATCH %] + [% error %] + [% END %] + +=item content + +The WRAPPER method captures the output from a template block and then +includes a named template, passing the captured output as the 'content' +variable. + + [% WRAPPER box %] + Be not afeard; the isle is full of noises, + Sounds and sweet airs, that give delight and hurt not. + [% END %] + + [% BLOCK box %] + <table border=1> + <tr> + <td> + [% content %] + </td> + </tr> + </table> + [% END %] + +=back + +=head2 Compound Variables + +Compound 'dotted' variables may contain any number of separate +elements. Each element may evaluate to any of the permitted variable +types and the processor will then correctly use this value to evaluate +the rest of the variable. Arguments may be passed to any of the +intermediate elements. + + [% myorg.people.sort('surname').first.fullname %] + +Intermediate variables may be used and will behave entirely as expected. + + [% sorted = myorg.people.sort('surname') %] + [% sorted.first.fullname %] + +This simplified dotted notation has the benefit of hiding the +implementation details of your data. For example, you could implement +a data structure as a hash array one day and then change it to an +object the next without requiring any change to the templates. + +=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.13, released on 30 January 2004. + +=head1 COPYRIGHT + + Copyright (C) 1996-2004 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. + + + +=cut + +# Local Variables: +# mode: perl +# perl-indent-level: 4 +# indent-tabs-mode: nil +# End: +# +# vim: expandtab shiftwidth=4: diff --git a/lib/Template/Manual/Views.pod b/lib/Template/Manual/Views.pod new file mode 100644 index 0000000..7bc53b0 --- /dev/null +++ b/lib/Template/Manual/Views.pod @@ -0,0 +1,642 @@ +#============================================================= -*-perl-*- +# +# Template::Manual::Views +# +# DESCRIPTION +# This section describes dynamic views: a powerful but experimental +# new feature in version 2.01 of the Template Toolkit. +# +# AUTHOR +# Andy Wardley <abw@andywardley.com> +# +# COPYRIGHT +# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved. +# Copyright (C) 1998-2001 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 +# +# +#======================================================================== + + +#------------------------------------------------------------------------ +# 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::Manual::Views - Template Toolkit views (experimental) + +=head1 DESCRIPTION + +This section describes dynamic views: a powerful but experimental new +feature in version 2.01 of the Template Toolkit. + +A view is effectively a collection of templates and/or variable +definitions which can be passed around as a self-contained unit. This +then represents a particular interface or presentation style for other +objects or items of data. + +You can use views to implement custom "skins" for an application or +content set. You can use them to help simplify the presentation of +common objects or data types. You can even use then to automate the +presentation of complex data structures such as that generated in an +XML::DOM tree or similar. You let an iterator do the walking, and the +view does the talking (or in this case, the presenting). Voila - you +have view independant, structure shy traversal using templates. + +In general, views can be used in a number of different ways to achieve +several different things. They elegantly solve some problems which +were otherwise difficult or complicated, and make easy some things +that were previously hard. + +At the moment, they're still very experimental. The directive syntax +and underlying API are likely to change quite considerably over the +next version or two. Please be very wary about building your +multi-million dollar e-commerce solutions based around this feature. + +=head2 Views as Template Collectors/Providers + +The VIEW directive starts a view definition and includes a name by +which the view can be referenced. The view definition continues up to +the matching END directive. + + [% VIEW myview %] + ... + [% END %] + +The first role of a view is to act as a collector and provider of templates. +The include() method can be called on a view to effectively do the same +thing as the INCLUDE directive. The template name is passed as the first +argument, followed by any local variable definitions for the template. + + [% myview.include('header', title='The Title') %] + + # equivalent to + [% INCLUDE header title='The Title' %] + +Views accept a number of configuration options which can be used to control +different aspects of their behaviour. The 'prefix' and 'suffix' options +can be specified to add a fixed prefix and/or suffix to the name of each template. + + [% VIEW myview + prefix = 'my/' + suffix = '.tt2' ; + END + %] + +Now the call + + [% myview.include('header', title='The Title') %] + +is equivalent to + + [% INCLUDE my/header.tt2 title='The Title' %] + +Views provide an AUTOLOAD method which maps method names to the +include() method. Thus, the following are all equivalent: + + [% myview.include('header', title='Hello World') %] + [% myview.include_header(title='Hello World') %] + [% myview.header(title='Hello World') %] + +=head2 Local BLOCK Definitions + +A VIEW definition can include BLOCK definitions which remain local to +the view. A request for a particular template will return a BLOCK, +if defined, in preference to any other template of the same name. + + [% BLOCK foo %] + public foo block + [% END %] + + [% VIEW plain %] + [% BLOCK foo %] + plain foo block + [% END %] + [% END %] + + [% VIEW fancy %] + [% BLOCK foo %] + fancy foo block + [% END %] + [% END %] + + [% INCLUDE foo %] # public foo block + [% plain.foo %] # plain foo block + [% fancy.foo %] # fancy foo block + +In addition to BLOCK definitions, a VIEW can contain any other +template directives. The entire VIEW definition block is processed to +initialise the view but no output is generated (this may change RSN - +and get stored as 'output' item, subsequently accessible as [% +view.output %]). However, directives that have side-effects, such as +those that update a variable, will have noticable consequences. + +=head2 Preserving Variable State within Views + +Views can also be used to save the values of any existing variables, +or to create new ones at the point at which the view is defined. +Unlike simple template metadata (META) which can only contain static +string values, the view initialisation block can contain any template +directives and generate any kind of dynamic output and/or data items. + + [% VIEW my_web_site %] + [% view.title = title or 'My Cool Web Site' %] + [% view.author = "$abw.name, $abw.email" %] + [% view.sidebar = INCLUDE my/sidebar.tt2 %] + [% END %] + +Note that additional data items can be specified as arguments to the VIEW +directive. Anything that doesn't look like a configuration parameter is +assumed to be a data item. This can be a little hazardous, of course, because +you never know when a new configuration item might get added which interferes +with your data. + + [% VIEW my_web_site + # config options + prefix = 'my/' + # misc data + title = title or 'My Cool Web Site' + author = "$abw.name, $abw.email" + sidebar = INCLUDE my/sidebar.tt2 + %] + ... + [% END %] + +Outside of the view definition you can access the view variables as, for +example: + + [% my_web_site.title %] + +One important feature is the equivalence of simple variables and templates. +You can implement the view item 'title' as a simple variable, a template +defined in an external file, possibly with a prefix/suffix automatically +appended, or as a local BLOCK definition within the [% VIEW %] ... [% END %] +definition. If you use the syntax above then the view will Do The Right +Thing to return the appropriate output. + +At the END of the VIEW definition the view is "sealed" to prevent you +from accidentally updating any variable values. If you attempt to change +the value of a variable after the END of the VIEW definition block then +an 'view' error will be thrown. + + [% TRY; + my_web_site.title = 'New Title'; + CATCH; + error; + END + %] + +The error above will be reported as: + + view error - cannot update item in sealed view: title + +The same is true if you pass a parameter to a view variable. This is +interpreted as an attempt to update the variable and will raise the same +warning. + + [% my_web_site.title('New Title') %] # view error! + +You can set the 'silent' parameter to have the view ignore these +parameters and simply return the variable value. + + [% VIEW my_web_site + silent = 1 + title = title or 'My Cool Web Site' + # ... ; + END + %] + + [% my_web_site.title('Blah Blah') %] # My Cool Web Site + +Alternately, you can specify that a view is unsealed allowing existing +variables to be updated and new variables defined. + + [% VIEW my_web_site + sealed = 0 + title = title or 'My Cool Web Site' + # ... ; + END + %] + + [% my_web_site.title('Blah Blah') %] # Blah Blah + [% my_web_site.title %] # Blah Blah + +=head2 Inheritance, Delegation and Reuse + +Views can be inherited from previously defined views by use of the 'base' +parameter. This example shows how a base class view is defined which +applies a 'view/default/' prefix to all template names. + + [% VIEW my.view.default + prefix = 'view/default/'; + END + %] + +Thus the directive: + + [% my.view.default.header(title='Hello World') %] + +is now equivalent to: + + [% INCLUDE view/default/header title='Hello World' %] + +A second view can be defined which specifies the default view as a +base. + + [% VIEW my.view.fancy + base = my.view.default + prefix = 'view/fancy/'; + END + %] + +Now the directive: + + [% my.view.fancy.header(title='Hello World') %] + +will resolve to: + + [% INCLUDE view/fancy/header title='Hello World' %] + +or if that doesn't exist, it will be handled by the base view as: + + [% INCLUDE view/default/header title='Hello World' %] + +When a parent view is specified via the 'base' parameter, the +delegation of a view to its parent for fetching templates and accessing +user defined variables is automatic. You can also implement your own +inheritance, delegation or other reuse patterns by explicitly +delegating to other views. + + [% BLOCK foo %] + public foo block + [% END %] + + [% VIEW plain %] + [% BLOCK foo %] + <plain>[% PROCESS foo %]</plain> + [% END %] + [% END %] + + [% VIEW fancy %] + [% BLOCK foo %] + [% plain.foo | replace('plain', 'fancy') %] + [% END %] + [% END %] + + [% plain.foo %] # <plain>public foo block</plain> + [% fancy.foo %] # <fancy>public foo block</fancy> + +Note that the regular INCLUDE/PROCESS/WRAPPER directives work entirely +independantly of views and will always get the original, unaltered +template name rather than any local per-view definition. + +=head2 Self-Reference + +A reference to the view object under definition is available with the +VIEW ... END block by its specified name and also by the special name +'view' (similar to the C<my $self = shift;> in a Perl method or the +'this' pointer in C++, etc). The view is initially unsealed allowing +any data items to be defined and updated within the VIEW ... END +block. The view is automatically sealed at the end of the definition +block, preventing any view data from being subsequently changed. + +(NOTE: sealing should be optional. As well as sealing a view to prevent +updates (SEALED), it should be possible to set an option in the view to +allow external contexts to update existing variables (UPDATE) or even +create totally new view variables (CREATE)). + + [% VIEW fancy %] + [% fancy.title = 'My Fancy Title' %] + [% fancy.author = 'Frank Open' %] + [% fancy.col = { bg => '#ffffff', bar => '#a0a0ff' } %] + [% END %] + +or + + [% VIEW fancy %] + [% view.title = 'My Fancy Title' %] + [% view.author = 'Frank Open' %] + [% view.col = { bg => '#ffffff', bar => '#a0a0ff' } %] + [% END %] + +It makes no real difference in this case if you refer to the view by +its name, 'fancy', or by the general name, 'view'. Outside of the +view block, however, you should always use the given name, 'fancy': + + [% fancy.title %] + [% fancy.author %] + [% fancy.col.bg %] + +The choice of given name or 'view' is much more important when it +comes to BLOCK definitions within a VIEW. It is generally recommended +that you use 'view' inside a VIEW definition because this is guaranteed +to be correctly defined at any point in the future when the block gets +called. The original name of the view might have long since been changed +or reused but the self-reference via 'view' should always be intact and +valid. + +Take the following VIEW as an example: + + [% VIEW foo %] + [% view.title = 'Hello World' %] + [% BLOCK header %] + Title: [% view.title %] + [% END %] + [% END %] + +Even if we rename the view, or create a new 'foo' variable, the header +block still correctly accesses the 'title' attribute of the view to +which it belongs. Whenever a view BLOCK is processed, the 'view' +variable is always updated to contain the correct reference to the +view object to which it belongs. + + [% bar = foo %] + [% foo = { title => "New Foo" } %] # no problem + [% bar.header %] # => Title: Hello World + +=head2 Saving References to External Views + +When it comes to view inheritance, it's always a good idea to take a +local copy of a parent or delegate view and store it as an attribute +within the view for later use. This ensures that the correct view +reference is always available, even if the external name of a view +has been changed. + + [% VIEW plain %] + ... + [% END %] + + [% VIEW fancy %] + [% view.plain = plain %] + [% BLOCK foo %] + [% view.plain.foo | replace('plain', 'fancy') %] + [% END %] + [% END %] + + [% plain.foo %] # => <plain>public foo block</plain> + [% plain = 'blah' %] # no problem + [% fancy.foo %] # => <fancy>public foo block</fancy> + + +=head2 Views as Data Presenters + +Another key role of a view is to act as a dispatcher to automatically +apply the correct template to present a particular object or data +item. This is handled via the print() method. + +Here's an example: + + [% VIEW foo %] + + [% BLOCK text %] + Some text: [% item %] + [% END %] + + [% BLOCK hash %] + a hash: + [% FOREACH key = item.keys.sort -%] + [% key %] => [% item.$key %] + [% END -%] + [% END %] + + [% BLOCK list %] + a list: [% item.sort.join(', ') %] + [% END %] + + [% END %] + +We can now use the view to print text, hashes or lists. The print() +method includes the right template depending on the typing of the +argument (or arguments) passed. + + [% some_text = 'I read the news today, oh boy.' %] + [% a_hash = { house => 'Lords', hall => 'Albert' } %] + [% a_list = [ 'sure', 'Nobody', 'really' ] %] + + [% view.print(some_text) %] + # Some text: I read the news today, oh boy. + + [% view.print(a_hash) %] + # a hash: + hall => Albert + house => Lords + [% view.print(a_list) %] + # a list: Nobody, really, sure + + +You can also provide templates to print objects of any other class. +The class name is mapped to a template name with all non-word +character sequences such as '::' converted to a single '_'. + + [% VIEW foo %] + [% BLOCK Foo_Bar %] + a Foo::Bar object: + thingies: [% view.print(item.thingies) %] + doodahs: [% view.print(item.doodahs) %] + [% END %] + [% END %] + + [% USE fubar = Foo::Bar(...) %] + + [% foo.print(fubar) %] + +Note how we use the view object to display various items within the +objects ('thingies' and 'doodahs'). We don't need to worry what +kind of data these represent (text, list, hash, etc) because we can +let the view worry about it, automatically mapping the data type to +the correct template. + +Views may define their own type =E<gt> template map. + + [% VIEW foo + map = { TEXT => 'plain_text', + ARRAY => 'show_list', + HASH => 'show_hash', + My::Module => 'template_name' + default => 'any_old_data' + } + %] + [% BLOCK plain_text %] + ... + [% END %] + + ... + + [% END %] + +They can also provide a 'default' map entry, specified as part of the 'map' +hash or as a parameter by itself. + + + [% VIEW foo + map = { ... }, + default = 'whatever' + %] + ... + [% END %] + +or + + [% VIEW foo %] + [% view.map = { ... } + view.default = 'whatever' + %] + ... + [% END %] + +The print() method provides one more piece of magic. If you pass it a +reference to an object which provides a present() method, then the +method will be called passing the view as an argument. This then gives +any object a chance to determine how it should be presented via the +view. + + package Foo::Bar; + + ... + + sub present { + my ($self, $view) = @_; + return "a Foo::Bar object:\n" + . "thingies: " . $view.print($self->{ _THINGIES }) . "\n" + . "doodahs: " . $view.print($self->{ _DOODAHS }) . "\n"; + } + +The object is free to delve deeply into its innards and mess around with +its own private data, before presenting the relevant data via the view. +In a more complex example, a present() method might walk part of a tree +making calls back against the view to present different nodes within the +tree. We may not want to expose the internal structure of the tree +(because that would break encapsulation and make our presentation code +dependant on it) but we want to have some way of walking the tree and +presenting items found in a particular manner. + +This is known as Structure Shy Traversal. Our view object doesn't require +prior knowledge about the internal structure of any data set to be able +to traverse it and present the data contained therein. The data items +themselves, via the present() method, can implement the internal iterators +to guide the view along the right path to presentation happiness. + +The upshot is that you can use views to greatly simplify the display +of data structures like XML::DOM trees. The documentation for the +Template::Plugins::XML::DOM module contains an example of this. In +essence, it looks something like this: + +XML source: + + <user name="Andy Wardley"> + <project id="iCan" title="iCan, but theyCan't"/> + <project id="p45" title="iDid, but theyDidn't"/> + </user> + +TT View: + + [% VIEW fancy %] + [% BLOCK user %] + User: [% item.name %] + [% item.content(myview) %] + [% END %] + + [% BLOCK project %] + Project: [% project.id %] - [% project.name %] + [% END %] + [% END %] + +Generate view: + + [% USE dom = XML.DOM %] + [% fancy.print(dom.parse(xml_source)) %] + +Output: + + User: Andy Wardley + Project: iCan - iCan, but theyCan't + Project: p45 - iDid, but theyDidn't + +The same approach can be applied to many other areas. Here's an example from +the File/Directory plugins. + + [% VIEW myview %] + [% BLOCK file %] + - [% item.name %] + [% END %] + + [% BLOCK directory %] + * [% item.name %] + [% item.content(myview) FILTER indent %] + [% END %] + [% END %] + + [% USE dir = Directory(dirpath) %] + [% myview.print(dir) %] + +And here's the same approach use to convert Pod documentation to any +other format via template. + + [% # load Pod plugin and parse source file into Pod Object Model + USE Pod; + pom = Pod.parse_file(my_pod_file); + + # define view to map all Pod elements to "pod/html/xxx" templates + VIEW pod2html + prefix='pod/html'; + END; + + # now print document via view (i.e. as HTML) + pod2html.print(pom) + %] + +Here we simply define a template prefix for the view which causes the +view to look for 'pod/html/head1', 'pod/html/head2', 'pod/html/over' +as templates to present the different sections of the parsed Pod document. + +There are some examples in the Template Toolkit test suite: t/pod.t and +t/view.t which may shed some more light on this. See the distribution +sub-directory 'examples/pod/html' for examples of Pod -E<gt> HTML templates. + +(This documentation is incomplete but I'm not going to get it 100% pefect +until the syntax and API stabilise). + +=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.13, released on 30 January 2004. + +=head1 COPYRIGHT + + Copyright (C) 1996-2004 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. + + + +=cut + +# Local Variables: +# mode: perl +# perl-indent-level: 4 +# indent-tabs-mode: nil +# End: +# +# vim: expandtab shiftwidth=4: |
