Initial Commit

This commit is contained in:
Riley Schneider
2025-12-03 16:38:10 +01:00
parent c5e26bf594
commit b732d8d4b5
17680 changed files with 5977495 additions and 2 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,113 @@
#============================================================= -*-perl-*-
#
# Template::Manual::Credits
#
# AUTHOR
# Andy Wardley <abw@wardley.org>
#
# COPYRIGHT
# Copyright (C) 1996-2020 Andy Wardley. All Rights Reserved.
#
# This module is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
#========================================================================
=encoding utf8
=head1 NAME
Template::Manual::Credits - Author and contributor credits
=head1 HISTORY
The Template Toolkit began its life as the C<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/)
C<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.
(CRE), 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.
Version 3 has been in development ever since.
=head1 AUTHOR
Andy Wardley E<lt>abw@wardley.orgE<gt> L<http://wardley.org/>
=head1 COPYRIGHT
Copyright (C) 1996-2020 Andy Wardley. All Rights Reserved.
The Template Toolkit is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=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.
If you submit a patch/pull request then please make sure you add your
own name to this list and include it in the changes.
Adam Kennedy, ahollandECS, Alexey A. Kiritchun, Amiri Barksdale, Andreas Koenig,
Andy Wardley, Autrijus Tang, Axel Gerstmair, Barrie Slaymaker, Ben Tilly,
Breno G. de Oliveira, Briac PilprE<eacute>, Brian Fraser, Brian Wightman,
Bryce Harrington, Chris Dean, Chris Winters, Christian, chromatic, Colin Johnson,
Colin Keith, Craig Barratt, Darren Chamberlain, Dave Cash, Dave Cross, Dave Hodgkinson,
Dave Howorth, Dave Jacoby, David Steinbrunner, Denis F. Latypoff, Dennis Clark,
Doug, Drew Taylor, Dylan, E. Choroba, eadjei, Eric Cholet, Francois Desarmenien,
François Andriot, fREW Schmidt, gordon-fish, Guido Flohr, Hans von Lengerke,
Harald Joerg, Horst Dumcke, Ivan Krylov, Ivan Kurmanov, Jacques Germishuys,
Jason Lewis, Jay Hannah, Jens Rehsack, Jess Robinson, Jim Vaughan, John Lightsey,
John Napiorkowski, Jon Jensen, Jonas Liljegren, Jonathon Padfield, José Joaquín Atria,
Jose Luis Martinez, Josh Rosenbaum, Kenny Gatdula, Kent Fredric, Kevin M. Goess, Koenig,
Leon Brocard, Leslie Michael Orchard, Lubomir, Lyle Brooks, Marc Remy, Mark Fowler,
Martin, Matthew Somerville, Michael Fowler, Michael Stevens, Mike Schilli,
Mikhail Klyuchnikov from Positive Technologies, nataraj, Neil Bowers, Nick Hibma,
Nicolas R, Nik Clayton, Norbert Buchmüller, Paul Orrock, Paul Seamons, Paul Sharpe,
Perrin Harkins, Philippe Bruhat (BooK), Piers Cawley, Portman, Rafael Kitover,
Randal L. Schwartz, Ricardo Signes, Richard Tietjen, Robin Berjon, Rod Taylor, Schaffner,
sdeseille, Sean McAfee, Sean Zellmer, Simon, Simon Dawson, Simon Matthews, Simon Napiorkowski,
Slaven Rezic, Smylers, Stas Bekman, Stathy G. Touloumis, stefano-b, Steinwand,
Steve Peters, Swen, Thierry-Michel Barral, Thuemmler, Timmy Chan, Todd Rinaldo, Tom Delmas,
Tony Bowden, Tosh Cooey, Ville SkyttE<auml>, Vivek Khera, Wilcox, William Hardison,
Yanick Champoux, Yuri Pimenov.
=cut
# Local Variables:
# mode: perl
# perl-indent-level: 4
# indent-tabs-mode: nil
# End:
#
# vim: expandtab shiftwidth=4:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,507 @@
#============================================================= -*-perl-*-
#
# Template::Manual::Filters
#
# AUTHOR
# Andy Wardley <abw@wardley.org>
#
# COPYRIGHT
# Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
#
# This module is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
#========================================================================
=encoding latin1
=head1 NAME
Template::Manual::Filters - Standard filters
=head1 format(format)
The C<format> filter takes a format string as a parameter (as per
C<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. -->
=head1 upper
Folds the input to UPPER CASE.
[% "hello world" FILTER upper %]
Output:
HELLO WORLD
=head1 lower
Folds the input to lower case.
[% "Hello World" FILTER lower %]
Output:
hello world
=head1 ucfirst
Folds the first character of the input to UPPER CASE.
[% "hello" FILTER ucfirst %]
Output:
Hello
=head1 lcfirst
Folds the first character of the input to lower case.
[% "HELLO" FILTER lcfirst %]
Output:
hELLO
=head1 trim
Trims any leading or trailing whitespace from the input text. Particularly
useful in conjunction with C<INCLUDE>, C<PROCESS>, etc., having the same effect
as the C<TRIM> configuration option.
[% INCLUDE myfile | trim %]
=head1 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
=head1 html
Converts the characters C<E<lt>>, C<E<gt>>, C<&> and C<"> to C<&lt;>,
C<&gt;>, C<&amp;>, and C<&quot;> 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 "&lt;=&gt;" returns -1, 0, or 1 depending on...
=head1 html_entity
The C<html> filter is fast and simple but it doesn't encode the full
range of HTML entities that your text may contain. The C<html_entity>
filter uses either the C<Apache::Util> module (which is written in C and
is therefore faster) or the C<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 C<escape_html()> or C<encode_entities()> subroutines
respectively) to convert all extended characters into their appropriate HTML
entities (e.g. converting 'C<?>' to 'C<&eacute;>'). If neither module is
available on your system then an 'C<html_entity>' exception will be thrown
reporting an appropriate message.
If you want to force TT to use one of the above modules in preference to
the other, then call either of the L<Template::Filters> class methods:
L<use_html_entities()|Template::Filters/use_html_entities()> or
L<use_apache_util()|Template::Filters/use_apache_util()>.
use Template::Filters;
Template::Filters->use_html_entities;
For further information on HTML entity encoding, see
L<http://www.w3.org/TR/REC-html40/sgml/entities.html>.
=head1 xml
Same as the C<html> filter, but adds C<&apos;> which is the fifth XML
built-in entity.
=head1 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 C<E<lt>pE<gt>>...C<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>
=head1 html_break / html_para_break
Similar to the html_para filter described above, but uses the HTML tag
sequence C<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.
=head1 html_line_break
This filter replaces any newlines with C<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>
=head1 uri
This filter URI escapes the input text, converting any characters
outside of the permitted URI character set (as defined by RFC 3986)
into a C<%nn> hex escape.
[% 'my file.html' | uri %]
Output:
my%20file.html
The uri filter correctly encodes all reserved characters, including
C<&>, C<@>, C</>, C<;>, C<:>, C<=>, C<+>, C<?> and C<$>. This filter
is typically used to encode parameters in a URL that could otherwise
be interpreted as part of the URL. Here's an example:
[% path = 'http://tt2.org/example'
back = '/other?foo=bar&baz=bam'
title = 'Earth: "Mostly Harmless"'
%]
<a href="[% path %]?back=[% back | uri %]&title=[% title | uri %]">
The output generated is rather long so we'll show it split across two
lines:
<a href="http://tt2.org/example?back=%2Fother%3Ffoo%3Dbar%26
baz%3Dbam&title=Earth%3A%20%22Mostly%20Harmless%22">
Without the uri filter the output would look like this (also split across
two lines).
<a href="http://tt2.org/example?back=/other?foo=bar
&baz=bam&title=Earth: "Mostly Harmless"">
In this rather contrived example we've manage to generate both a broken URL
(the repeated C<?> is not allowed) and a broken HTML element (the href
attribute is terminated by the first C<"> after C<Earth: > leaving C<Mostly
Harmless"> dangling on the end of the tag in precisely the way that harmless
things shouldn't dangle). So don't do that. Always use the uri filter to
encode your URL parameters.
However, you should B<not> use the uri filter to encode an entire URL.
<a href="[% page_url | uri %]"> # WRONG!
This will incorrectly encode any reserved characters like C<:> and C</>
and that's almost certainly not what you want in this case. Instead
you should use the B<url> (note spelling) filter for this purpose.
<a href="[% page_url | url %]"> # CORRECT
Please note that this behaviour was changed in version 2.16 of the
Template Toolkit. Prior to that, the uri filter did not encode the
reserved characters, making it technically incorrect according to the
RFC 2396 specification (since superceded by RFC2732 and RFC3986). So we
fixed it in 2.16 and provided the url filter to implement the old behaviour
of not encoding reserved characters.
As of version 2.28 of the Template Toolkit, the C<uri> and L<url> filters
use the unsafe character set defined by RFC3986. This means that certain
characters ("(", ")", "*", "!", "'", and '"') are now deemed unsafe and
will be escaped as hex character sequences.
The ability to use the RFC3986 character set was added in 2.26 but not
enabled by default; double quote was incorrectly deemed safe in 2.26 but
correctly escaped in 2.27.
If you want to enable the old behaviour then call the C<use_rfc2732()>
method in L<Template::Filters>
use Template::Filters
Template::Filters->use_rfc2732;
=head1 url
The url filter is a less aggressive version of the uri filter. It encodes
any characters outside of the permitted URI character set (as defined by RFC 2396)
into C<%nn> hex escapes. However, unlike the uri filter, the url filter does
B<not> encode the reserved characters C<&>, C<@>, C</>, C<;>, C<:>, C<=>, C<+>,
C<?> and C<$>.
=head1 indent(pad)
Indents the text block by a fixed pad string or width. The 'C<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
=head1 truncate(length,dots)
Truncates the text block to the length specified, or a default length
of 32. Truncated text will be terminated with 'C<...>' (i.e. the 'C<...>'
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...
If you want to use something other than 'C<...>' you can pass that as a
second argument.
[% FILTER truncate(26, '&hellip;') %]
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&hellip;
=head1 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!
=head1 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
=head1 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
=head1 redirect(file, options)
The C<redirect> filter redirects the output of the block into a separate
file, specified relative to the C<OUTPUT_PATH> configuration item.
[% FOREACH user IN myorg.userlist %]
[% FILTER redirect("users/${user.id}.html") %]
[% INCLUDE userinfo %]
[% END %]
[% END %]
or more succinctly, using side-effect notation:
[% FOREACH user IN myorg.userlist;
INCLUDE userinfo
FILTER redirect("users/${user.id}.html");
END
%]
A C<file> exception will be thrown if the C<OUTPUT_PATH> option is undefined.
An optional C<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 C<binmode> option
as shown in the first example.
=head1 eval / evaltt
The C<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 C<evaltt> filter is provided as an alias for C<eval>.
=head1 perl / evalperl
The C<perl> filter evaluates the block as Perl code. The C<EVAL_PERL>
option must be set to a true value or a C<perl> exception will be
thrown.
[% my_perl_code | perl %]
In most cases, the C<[% PERL %]> ... C<[% 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 C<evalperl> filter is provided as an alias for C<perl> for backwards
compatibility.
=head1 stdout(options)
The stdout filter prints the output generated by the enclosing block to
C<STDOUT>. The C<binmode> option can be passed as either a named parameter
or a single argument to set C<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 C<stdout> filter can be used to force C<binmode> on C<STDOUT>, or also
inside C<redirect>, C<null> or C<stderr> blocks to make sure that particular
output goes to C<STDOUT>. See the C<null> filter below for an example.
=head1 stderr
The stderr filter prints the output generated by the enclosing block to
C<STDERR>.
=head1 null
The C<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 C<stdout> filter to ensure that a particular expression
generates output to C<STDOUT> (in this case in binary mode).
=cut
# Local Variables:
# mode: perl
# perl-indent-level: 4
# indent-tabs-mode: nil
# End:
#
# vim: expandtab shiftwidth=4:

View File

@@ -0,0 +1,452 @@
#============================================================= -*-perl-*-
#
# Template::Manual::Internals
#
# AUTHOR
# Andy Wardley <abw@wardley.org>
#
# COPYRIGHT
# Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
#
# This module is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
#========================================================================
=head1 NAME
Template::Manual::Internals - Template Toolkit internals
=head1 Introduction
This section of the documentation is aimed at developers wishing to
know more about how the Template Toolkit works on the inside in order
to extend or adapt it to their own needs.
If that doesn't sound like you then you probably don't need to read this.
There is no test afterwards.
=head1 Outside Looking In
The L<Template> module is simply a front end module which creates and
uses a L<Template::Service> and pipes the output wherever you want it to
go (C<STDOUT> by default, or maybe a file, scalar, etc). The
C<Apache::Template> module (available separately from CPAN) is another
front end. That creates a C<Template::Service::Apache> object, calls on
it as required and sends the output back to the relevant
C<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 C<Apache::Template>
front end, for example, handles C<Apache::Request> specifics and
configuration via the F<httpd.conf>. The regular L<Template> front-end
deals with C<STDOUT>, variable refs, etc. Otherwise it is
L<Template::Service> (or subclass) which does all the work.
The L<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.
L<Template::Service> hides that all away and makes everything look simple to
the outsider. It provides extra features, like C<PRE_PROCESS>, C<PROCESS> and
C<POST_PROCESS>, and also provides the error recovery mechanism via C<ERROR>.
You ask it to process a template and it takes care of everything for you. The
C<Template::Service::Apache> module goes a little bit further, adding some extra
headers to the L<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
L<process()|Template::Service#process()> method and schedules the named
template specified as an argument, and possibly several other templates
(C<PRE_PROCESS>, etc) to be processed in order. It doesn't actually process
the templates itself, but instead makes a
L<process()|Template::Context#process()> call against a L<Template::Context>
object.
L<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
L<Template::Provider> objects (the C<LOAD_TEMPLATES> posse) who themselves
might get involved with a L<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
L<template()|Template::Context#template()> method. You call it passing a
template name as an argument, and it returns a compiled template in the form
of a L<Template::Document> object, or otherwise raises an exception.
A L<Template::Document> is a thin object wrapper around a compiled template
subroutine. The object implements a L<process()|Template::Document#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 L<block()|Template::Document#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
L<template()|Template::Context#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 L<process()|Template::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 L<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);
}
=head1 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 C<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
L<Template::Exception> object. An exception object is really just a
convenient wrapper for the 'C<type>' and 'C<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 L<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 L<Template::Service> object calls on
L<Template::Context> to handle a L<process()|Template::Context#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 L<Template::Stash> object.
This is a blessed hash array in which template variables are defined. The
object wrapper provides L<get()|Template::Stash#get()> and
L<set()|Template::Stash#set()> method which implement all the
I<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 L<stash()|Template::Context#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 L<get()|Template::Stash#get()> method hides the details of the
underlying variable types, automatically calling code references, checking
return values, and performing other such tricks. If 'C<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 call:
$stash->get([ 'title', ['The Cat Sat on the Mat'] ]);
Dotted compound variables can be requested by passing a single
list reference to the C<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 L<set()|Template::Stash#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 L<process()|Template::Context#process()> method lies the
L<include()|Template::Context#include()> method. Just as with the C<PROCESS> /
C<INCLUDE> directives, the key difference is in variable localisation. Before
processing a template, the C<process()> method simply updates the stash to set
any new variable definitions, overwriting any existing values. In contrast,
the C<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 C<include()> method restores the previous variable state by I<decloning> the
stash.
The context also provides an L<insert()|Template::Context#insert()> method to
implement the C<INSERT> directive, but no C<wrapper()> method. This functionality
can be implemented by rewriting the Perl code and calling C<include()>.
[% WRAPPER foo -%]
blah blah [% x %]
[%- END %]
$context->include('foo', {
content => 'blah blah ' . $stash->get('x'),
});
Other than the template processing methods C<process()>, C<include()> and
C<insert()>, the context defines methods for fetching plugin objects,
L<plugin()|Template::Context#plugin()>, and filters,
L<filter()|Template::Context#filter()>.
# TT USE directive
[% USE foo = Bar(10) %]
# equivalent Perl
$stash->set('foo', $context->plugin('Bar', [10]));
# TT FILTER block
[% FILTER bar(20) %]
blah blah blah
[% END %]
# equivalent Perl
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 C<IF>, C<UNLESS>, C<FOREACH> and so on all have direct
counterparts in Perl.
# TT IF directive
[% IF msg %]
Message: [% msg %]
[% END %];
# equivalent Perl
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 C<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 C<STDOUT> remains as you would expect:
The dog sat on the log
The output sent to C<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.
The source code repository for the Template Toolkit is hosted at Github.
https://github.com/abw/Template2
Clone the repository, make your changes, commit them, then send a pull
request.
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 C<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 C<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 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 C<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).
Then add a line to the Changes file giving a very brief description of what
you've done. There's no need to go into detail here (save that for the commit
message, comments in code or docuemtation where appropriate).
Please also make sure you add your name to the lib/Template/Manual/Credits.pod
file (if it isn't already there).
Then commit your changes and send a pull request.
=cut
# Local Variables:
# mode: perl
# perl-indent-level: 4
# indent-tabs-mode: nil
# End:
#
# vim: expandtab shiftwidth=4:

View File

@@ -0,0 +1,242 @@
#============================================================= -*-perl-*-
#
# Template::Manual::Intro
#
# AUTHOR
# Andy Wardley <abw@wardley.org>
#
# COPYRIGHT
# Copyright (C) 1996-2020 Andy Wardley. All Rights Reserved.
#
# This module is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
#========================================================================
=head1 NAME
Template::Manual::Intro - Introduction to the Template Toolkit
=head1 Introduction
The Template Toolkit is a collection of Perl modules which implement a
fast, flexible, powerful and extensible template processing system.
It is most often used for generating dynamic web content, although it can
be used equally well for processing any kind of text documents.
At the simplest level it provides an easy way to process template
files, filling in embedded variable references with their equivalent
values. Here's an example of a template.
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 C<[%> ... C<%]> but you can change these and various other
options to configure how the Template Toolkit looks, feels and works.
You can set the C<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.
...etc...
=head1 The Template Perl Module
The L<Template> Perl module is the front end to the Template Toolkit for Perl
programmers, 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 L<Template>
constructor method, L<new()|Template#new()>, which are then used to
configure the generate object.
use Template;
my $tt = Template->new({
INCLUDE_PATH => '/usr/local/templates',
INTERPOLATE => 1,
}) || die "$Template::ERROR\n";
The L<Template> object implements a L<process()|Template#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 L<process()|Template#process()> method returns a true value (C<1>) on success
and prints the template output to C<STDOUT>, by default. On error, the
L<process()|Template#process()> method returns a false value (C<undef>).
The L<error()|Template#error()> method can then be called to retrieve
details of the error.
=head1 Component Based Content Construction
A number of special directives are provided, such as C<INSERT>, C<INCLUDE> and
C<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>
=head1 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 'C<.>' is used to access into lists and hashes or to call object
methods. The C<FOREACH> directive is provided for iterating through lists, and
various logical tests are available using directives such as C<IF>, C<UNLESS>,
C<ELSIF>, C<ELSE>, C<SWITCH>, C<CASE>, etc.
[% FOREACH section = menu %]
<a href="[% root %]/[% section %]/index.html">[% section %]</a>
[% END %]
<b>Client</b>: [% 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 %]
=head1 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.
=head1 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.
=head1 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.
=cut
# Local Variables:
# mode: perl
# perl-indent-level: 4
# indent-tabs-mode: nil
# End:
#
# vim: expandtab shiftwidth=4:

View File

@@ -0,0 +1,313 @@
#============================================================= -*-perl-*-
#
# Template::Manual::Plugins
#
# AUTHOR
# Andy Wardley <abw@wardley.org>
#
# COPYRIGHT
# Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
#
# This module is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
#========================================================================
=head1 NAME
Template::Manual::Plugins - Standard plugins
=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 Assert
New in 2.20! The L<Assert|Template::Plugin::Assert> plugin adds an
C<assert> virtual method that you can use to catch undefined values.
For example, consider this dotop:
[% user.name %]
If C<user.name> is an undefined value then TT will silently ignore the
fact and print nothing. If you C<USE> the C<assert> plugin then you
can add the C<assert> vmethod between the C<user> and C<name> elements,
like so:
[% user.assert.name %]
Now, if C<user.name> is an undefined value, an exception will be thrown:
assert error - undefined value for name
=head2 CGI
The L<CGI|Template::Plugin::CGI> plugin is a wrapper around Lincoln Stein's
CGI.pm module. The plugin is distributed with the Template Toolkit (see
L<Template::Plugin::CGI>) and the L<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 in the 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 L<Date|Template::Plugin::Date> plugin provides an easy way to generate
formatted time and date strings by delegating to the L<POSIX> C<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 L<Directory|Template::Plugin::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 C<DBI> plugin is no longer distributed as part of the Template Toolkit
(as of version 2.15). It is now available as a separate L<Template::DBI>
distribution from CPAN.
=head2 Dumper
The L<Dumper|Template::Plugin::Dumper> plugin provides an interface to the
Data::Dumper module. See L<Template::Plugin::Dumper> and L<Data::Dumper> for
further details.
[% USE dumper(indent=0, pad="<br>") %]
[% dumper.dump(myvar, yourvar) %]
=head2 File
The L<File|Template::Plugin::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;
}
Example of use:
# 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 L<Format|Template::Plugin::Format> plugin provides a simple way to format
text according to a C<printf()>-like format. See L<Template::Plugin::Format> for
further details.
[% USE bold = format('<b>%s</b>') %]
[% bold('Hello') %]
=head2 GD
The C<GD> plugins are no longer part of the core Template Toolkit distribution.
They are now available from CPAN in a separate L<Template::GD> distribution.
=head2 HTML
The L<HTML|Template::Plugin::HTML> plugin is 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.
[% 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 L<Iterator|Template::Plugin::Iterator> plugin provides a way to create a
L<Template::Iterator> object to iterate over a data set. An iterator is
created automatically by the C<FOREACH> directive and is aliased to the C<loop>
variable. This plugin allows an iterator to be explicitly created with a given
name, or the default plugin name, C<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 Scalar
The Template Toolkit calls user-defined subroutines and object methods
using Perl's array context by default.
# TT2 calls object methods in array context by default
[% object.method %]
This plugin module provides a way for you to call subroutines and methods
in scalar context.
[% USE scalar %]
# force it to use scalar context
[% object.scalar.method %]
# also works with subroutine references
[% scalar.my_sub_ref %]
=head2 String
The L<String|Template::Plugin::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 L<Table|Template::Plugin::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 L<URL|Template::Plugin::URL> plugin provides a simple way of constructing
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 L<Wrap|Template::Plugin::Wrap> plugin uses the L<Text::Wrap> module 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 C<Text::Wrap> module is available from CPAN:
http://www.cpan.org/modules/by-module/Text/
=head2 XML
The C<XML::DOM>, C<XML::RSS>, C<XML::Simple> and C<XML::XPath> plugins are no
longer distributed with the Template Toolkit as of version 2.15
They are now available in a separate L<Template::XML> distribution.
=cut
# Local Variables:
# mode: perl
# perl-indent-level: 4
# indent-tabs-mode: nil
# End:
#
# vim: expandtab shiftwidth=4:

View File

@@ -0,0 +1,327 @@
#============================================================= -*-perl-*-
#
# Template::Manual::Syntax
#
# AUTHOR
# Andy Wardley <abw@wardley.org>
#
# COPYRIGHT
# Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
#
# This module is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
#========================================================================
=head1 NAME
Template::Manual::Syntax - Directive syntax, structure and semantics
=head1 Tag Styles
Template directives are embedded between start and end markers tags.
By default these tag markers are C<[%> and C<%]>.
[% 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 C<START_TAG>, C<END_TAG> and
C<TAG_STYLE> configuration options. You can also use the C<TAGS> directive to
define a new tag style for the current template file.
You can also set the C<INTERPOLATE> option to allow simple variable references
to be embedded directly in templates, prefixed by a C<$>.
# 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%])
=head1 Outline Tags
As of version 2.26, the Template Toolkit supports "outline" tags. These have
a designated marker at the start of a line (C<%%> by default) and continue to
the end of a line. The newline character at the end of the line is discarded
(aka "chomped").
So rather than writing something like this:
[% IF some.list.size -%]
<ul>
[% FOREACH item IN some.list -%]
<li>[% item.html %]</li>
[% END -%]
</ul>
[% END -%]
You can write it like this instead:
%% IF some.list.size
<ul>
%% FOREACH item IN some.list
<li>[% item.html %]</li>
%% END
</ul>
%% END
Outline tags aren't enabled by default. There are a numbers of ways you can
enable them. The first is to use the C<TAGS> directive to set the tag style
to C<outline> in any templates where you want to use them. This will enable
outline tags from that point on.
[% TAGS outline -%]
%% INCLUDE header
You can set the C<TAGS> back to the C<default> value at some point later in the
template if you want to disable them:
[% TAGS default -%]
You can set the C<TAG_STYLE> configuration option if you want then enabled in
all templates by default. You can always use the C<[% TAGS default %]>
directive to disable them in any templates or parts of templates if necessary.
my $tt = Template->new({
TAG_STYLE => 'outline',
});
The C<OUTLINE_TAG> option allows you to set the outline tag marker to something
else if you're not a fan of percent signs. Setting this option will
automatically enable outline tags.
my $tt = Template->new({
OUTLINE_TAG => '>>',
});
You can also use the C<TAGS> directive to define your own custom tags (start,
end and now optionally, outline) for a template or part of a template.
[% TAGS <* *> >> %]
>> INCLUDE header # outline tag
Hello <* name *> # inline tag
If you only specify a start and end tag then outline tags will be disabled.
[% TAGS <* *> %] # no outline tags
=head1 Comments
The C<#> 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>
%]
=head1 Chomping Whitespace
You can add C<-> or C<+> to the immediate start or end of a directive
tag to control the whitespace chomping options. See the C<PRE_CHOMP> and
C<POST_CHOMP> options for further details.
[% BLOCK foo -%] # remove trailing newline
This is block foo
[%- END %] # remove leading newline
=head1 Implicit Directives: GET and SET
The simplest directives are C<GET> and C<SET> which retrieve and update
variable values respectively. The C<GET> and C<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 C<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 C<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 C<stop> which is
entirely separate from the C<STOP> directive.
[% stop = 'Clackett Lane Bus Depot' %]
The bus will next stop at [% stop %] # variable
[% STOP %] # directive
=head1 Block Directives
Directives such as C<FOREACH>, C<WHILE>, C<BLOCK>, C<FILTER>, etc., mark the
start of a block which may contain text or other directives up to the matching
C<END> directive. Blocks may be nested indefinitely. The C<IF>, C<UNLESS>,
C<ELSIF> and C<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 %]
=head1 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 C<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 %] # does not work
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 C<IF> block which returns
C<'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 %]
=head1 Chaining Filters
Multiple C<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, C<|>, can also be used as an alias for C<FILTER>.
[% PROCESS somefile | truncate(100) | html %]
=head1 Multiple Directive Blocks
Multiple directives can be included within a single tag when delimited
by semi-colons. Note however that the C<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 %]
=cut
# Local Variables:
# mode: perl
# perl-indent-level: 4
# indent-tabs-mode: nil
# End:
#
# vim: expandtab shiftwidth=4:

View File

@@ -0,0 +1,736 @@
#============================================================= -*-perl-*-
#
# Template::Manual::VMethods
#
# AUTHOR
# Andy Wardley <abw@wardley.org>
#
# COPYRIGHT
# Copyright (C) 1996-2015 Andy Wardley. All Rights Reserved.
#
# This module is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
#========================================================================
=head1 NAME
Template::Manual::VMethods - Virtual Methods
=head1 Scalar Virtual Methods
=head2 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
=head2 collapse
Returns the text with any leading and trailing whitespace removed and any
internal sequences of whitespace converted to a single space
[% text = " The bird\n is the word" %]
[% text.collapse %] # The bird is the word
=head2 defined
Returns true if the value is defined.
[% user = get_user(uid) IF uid.defined %]
=head2 dquote
Returns the text with any double quote characters escaped with a backslash
prefix. Any newline characters in the text will be replaced with "\n".
[% quote = 'He said "Oh really?"' %]
[% quote.dquote %] # He said \"Oh really?\"
=head2 hash
Return the value as a hash reference containing a single entry with
the key C<value> indicating the original scalar value. As with the
C<list> virtual method, this is generally used to help massage data
into different formats.
=head2 lcfirst
Returns the text with the first letter converted to lower case.
[% word = 'BIRD' %]
[% word.lcfirst %] # bIRD
=head2 length
Returns the length of the string representation of the item:
[% IF password.length < 8 %]
Password too short, dumbass!
[% END %]
=head2 empty
Returns true if the string is empty:
[% IF details.empty %]
No details specified
[% END %]
=head2 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 C<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
=head2 lower
Returns the text in lower case.
[% word = 'BIRD' %]
[% word.lower %] # bird
=head2 match(pattern, global)
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);
%]
To perform a global search to match the pattern as many times as it
appears in the source string, provide a true value for the C<global>
argument following the pattern.
[% text = 'bandanna';
text.match('an+', 1).join(', ') # an, ann
%]
=head2 repeat(n)
Repeat the string a specified number of times.
[% name = 'foo' %]
[% name.repeat(3) %] # foofoofoo
=head2 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
You can use C<$1>, C<$2>, etc., to reference captured parts (in parentheses)
in the regular expression. Just be careful to I<single> quote the replacement
string. If you use I<double> quotes then TT will try and interpolate the
variables before passing the string to the C<replace> vmethod.
[% name = 'FooBarBaz' %]
[% name.replace('([A-Z])', ' $1') %] # Foo Bar Baz
=head2 remove(pattern)
Outputs the string with all instances of the pattern (specified
as a Perl regular expression) removed.
[% name = 'foo, bar & baz' %]
[% name.remove('\W+') %] # foobarbaz
=head2 search(pattern)
Performs a similar function to L<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 L<match>. Move along
now, there's nothing more to see here.
=head2 size
Always returns 1 for scalar values. This method is provided for
consistency with the hash and list size methods.
=head2 split(pattern)
Calls Perl's C<split()> function to split a string into a list of
strings.
[% FOREACH dir IN mypath.split(':') %]
[% dir %]
[% END %]
=head2 substr(offset, length, replacement)
Returns a substring starting at C<offset>, for C<length> characters.
[% str 'foo bar baz wiz waz woz') %]
[% str.substr(4, 3) %] # bar
If C<length> is not specified then it returns everything from the
C<offset> to the end of the string.
[% str.substr(12) %] # wiz waz woz
If both C<length> and C<replacement> are specified, then the method
replaces everything from C<offset> for C<length> characters with
C<$replacement>. The substring removed from the string is then returned.
[% str.substr(0, 11, 'FOO') %] # foo bar baz
[% str %] # FOO wiz waz woz
=head2 squote
Returns the text with any single quote characters escaped with a backslash
prefix.
[% tim = "Tim O'Reilly" %]
[% tim.squote %] # Tim O\'Reilly
=head2 trim
Returns the text with any leading and trailing whitespace removed.
[% text = ' hello world ' %]
[% text.trim %] # hello world
=head2 ucfirst
Returns the text with the first letter converted to upper case.
[% word = 'bird' %]
[% word.ucfirst %] # Bird
=head2 upper
Returns the text in upper case.
[% word = 'bird' %]
[% word.upper %] # BIRD
=head1 Hash Virtual Methods
=head2 keys
Returns a list of keys in the hash. They are not returned in any
particular order, but the order is the same as for the corresponding
values method.
[% FOREACH key IN hash.keys %]
* [% key %]
[% END %]
If you want the keys in sorted order, use the list C<sort> method.
[% FOREACH key IN hash.keys.sort %]
* [% key %]
[% END %]
Having got the keys in sorted order, you can then use variable
interpolation to fetch the value. This is shown in the following
example by the use of C<$key> to fetch the item from C<hash> whose
key is stored in the C<key> variable.
[% FOREACH key IN hash.keys.sort %]
* [% key %] = [% hash.$key %]
[% END %]
Alternately, you can use the C<pairs> method to get a list of
key/value pairs in sorted order.
=head2 values
Returns a list of the values in the hash. As with the C<keys> method,
they are not returned in any particular order, although it is the same
order that the keys are returned in.
[% hash.values.join(', ') %]
=head2 items
Returns a list of both the keys and the values expanded into a single list.
[% hash = {
a = 10
b = 20
};
hash.items.join(', ') # a, 10, b, 20
%]
=head2 each
This method currently returns the same thing as the C<items> method.
However, please note that this method will change in the next major
version of the Template Toolkit (v3) to return the same thing as the
C<pairs> method. This will be done in an effort to make these virtual
method more consistent with each other and how Perl works.
In anticipation of this, we recommend that you stop using C<hash.each>
and instead use C<hash.items>.
=head2 pairs
This method returns a list of key/value pairs. They are returned in
sorted order according to the keys.
[% FOREACH pair IN product.pairs %]
* [% pair.key %] is [% pair.value %]
[% END %]
=head2 list
Returns the contents of the hash in list form. An argument can be
passed to indicate the desired items required in the list: C<keys> to
return a list of the keys (same as C<hash.keys>), C<values> to return a
list of the values (same as C<hash.values>), C<each> to return as list
of key and values (same as C<hash.each>), or C<pairs> to return a list
of key/value pairs (same as C<hash.pairs>).
[% keys = hash.list('keys') %]
[% values = hash.list('values') %]
[% items = hash.list('each') %]
[% pairs = hash.list('pairs') %]
When called without an argument it currently returns the same thing as
the C<pairs> method. However, please note that this method will change
in the next major version of the Template Toolkit (v3) to return a
reference to a list containing the single hash reference (as per the
scalar list method).
In anticipation of this, we recommend that you stop using C<hash.list>
and instead use C<hash.pairs>.
=head2 sort, nsort
Return a list of the keys, sorted alphabetically (C<sort>) or numerically
(C<nsort>) according to the corresponding values in the hash.
[% FOREACH n IN phones.sort %]
[% phones.$n %] is [% n %],
[% END %]
=head2 import
The C<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 C<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
=head2 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' %]
When called without any argument, C<hash.defined> returns true if the hash
itself is defined (e.g. the same effect as C<scalar.defined>).
=head2 delete
Delete one or more items from the hash.
[% hash.delete('foo', 'bar') %]
=head2 size
Returns the number of key/value pairs in the hash.
=head2 empty
Returns true if the hash is empty:
[% IF config.empty %]
No configuration available
[% END %]
=head2 item
Returns an item from the hash using a key passed as an argument.
[% hash.item('foo') %] # same as hash.foo
=head1 List Virtual Methods
=head2 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(", ") %].
=head2 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
=head2 empty
Returns true if the list is empty:
[% IF results.empty %]
No results found
[% END %]
=head2 defined
Returns a true or false value if the item in the list denoted by the
argument is defined.
[% list.defined(3) ? 'yes' : 'no' %]
When called without any argument, C<list.defined> returns true if the list
itself is defined (e.g. the same effect as C<scalar.defined>).
=head2 reverse
Returns the items of the list in reverse order.
[% FOREACH s IN scores.reverse %]
...
[% END %]
=head2 join
Joins the items in the list into a single string, using Perl's C<join()>
function.
[% items.join(', ') %]
=head2 grep
Returns a list of the items in the list that match a regular expression
pattern.
[% FOREACH directory.files.grep('\.txt$') %]
...
[% END %]
=head2 sort, nsort
Returns the items in alpha (C<sort>) or numerical (C<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 C<books> list can contains hash references with
an C<author> key or objects with an C<author> method.
You can also specify multiple sort keys.
[% library = books.sort('author', 'title') %]
In this case the books will be sorted primarily by author. If two or more
books have authors with the same name then they will be sorted by title.
=head2 unshift(item), push(item)
The C<push()> method adds an item or items to the end of list.
[% mylist.push(foo) %]
[% mylist.push(foo, bar) %]
The C<unshift()> method adds an item or items to the start of a list.
[% mylist.unshift(foo) %]
[% mylist.push(foo, bar) %]
=head2 shift, pop
Removes the first/last item from the list and returns it.
[% first = mylist.shift %]
[% last = mylist.pop %]
=head2 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 %]
=head2 import
Appends the contents of one or more other lists to the end of the
current list.
[% one = [ 1 2 3 ];
two = [ 4 5 6 ];
three = [ 7 8 9 ];
one.import(two, three);
one.join(', '); # 1, 2, 3, 4, 5, 6, 7, 8, 9
%]
Import also allows chaining. The below syntax is equivalent.
[% one = [ 1 2 3 ];
two = [ 4 5 6 ];
three = [ 7 8 9 ];
one.import(two, three).join(', '); # 1, 2, 3, 4, 5, 6, 7, 8, 9
# or: one.import(two).import(three).join(', '); # 1, 2, 3, 4, 5, 6, 7, 8, 9
%]
=head2 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.
=head2 slice(from, to)
Returns a slice of items in the list between the bounds passed as
arguments. If the second argument, C<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) %]
=head2 splice(offset, length, list)
Behaves just like Perl's C<splice()> function allowing you to selectively
remove and/or replace elements in a list. It removes C<length> items
from the list, starting at C<offset> and replaces them with the items
in C<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 C<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 ]);
%]
=head2 hash
Returns a reference to a hash array comprised of the elements in the
list. The even-numbered elements (0, 2, 4, etc) become the keys and
the odd-numbered elements (1, 3, 5, etc) the values.
[% list = ['pi', 3.14, 'e', 2.718] %]
[% hash = list.hash %]
[% hash.pi %] # 3.14
[% hash.e %] # 2.718
If a numerical argument is provided then the hash returned will have
keys generated for each item starting at the number specified.
[% list = ['beer', 'peanuts'] %]
[% hash = list.hash(1) %]
[% hash.1 %] # beer
[% hash.2 %] # peanuts
=head2 item
Returns an item from the list using an index passed as an argument.
[% list.item(0) %] # same as list.0
=head1 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). C<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 C<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 the C<something> variable is bound to a subroutine which
may return one or more items:
[% FOREACH item IN 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 C<first> method, for example, then that
will be called, as expected, in preference to the list virtual method.
=head1 Defining Custom Virtual Methods
You can define your own virtual methods for scalars, lists and hash arrays.
The L<Template::Stash> package variables C<$SCALAR_OPS>, C<$LIST_OPS> and
C<$HASH_OPS> are references to hash arrays that define these virtual methods.
C<HASH_OPS> and C<LIST_OPS> methods are subroutines that accept a hash/list
reference as the first item. C<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 ];
};
Example template:
[% primes = [ 2, 3, 5, 7, 9 ] %]
[% primes.odd.join(', ') %] # 3, 5, 7, 9
TODO: document the define_vmethod() method which makes this even easier
=cut
# Local Variables:
# mode: perl
# perl-indent-level: 4
# indent-tabs-mode: nil
# End:
#
# vim: expandtab shiftwidth=4:

View File

@@ -0,0 +1,838 @@
#============================================================= -*-perl-*-
#
# Template::Manual::Variables
#
# AUTHOR
# Andy Wardley <abw@wardley.org>
#
# COPYRIGHT
# Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
#
# This module is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
#========================================================================
=head1 NAME
Template::Manual::Variables - Template variables and code bindings
=head1 Template Variables
A reference to a hash array may be passed as the second argument to the
L<process()|Template#process()> method, containing definitions of template
variables. The C<VARIABLES> (a.k.a. C<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);
F<myfile> template:
This is version [% version %] ([% release %]).
Serial number: [% serial_no %]
Generated 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 'C<foo>', 'C<Foo>' and
'C<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 data:
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'),
};
Example 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') %]
Generated 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 'C<.>' operator.
Example data:
my $vars = {
'home' => 'http://www.myserver.com/homepage.html',
'page' => {
'this' => 'mypage.html',
'next' => 'nextpage.html',
'prev' => 'prevpage.html',
},
};
Example template:
<a href="[% home %]">Home</a>
<a href="[% page.prev %]">Previous Page</a>
<a href="[% page.next %]">Next Page</a>
Generated 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 'C<_>' or 'C<.>' 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
C<DEBUG> option is enabled).
Example data:
my $vars = {
message => 'Hello World!',
_secret => "On the Internet, no-one knows you're a dog",
thing => {
public => 123,
_private => 456,
'.hidden' => 789,
},
};
Example template:
[% message %] # outputs "Hello World!"
[% _secret %] # no output
[% thing.public %] # outputs "123"
[% thing._private %] # no output
[% thing..hidden %] # ERROR: unexpected token (..)
You can disable this feature by setting the C<$Template::Stash::PRIVATE>
package variable to a false value.
$Template::Stash::PRIVATE = undef; # now you can thing._private
To access a hash entry using a key stored in another variable, prefix
the key variable with 'C<$>' 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 'C<.>' characters in the name),
any hashes required to represent intermediate namespaces will be
created automatically. In this following example, the C<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
Generated output:
The XYZ-2000 Bogon Generator
costs $666.00
You can use Perl's familiar C<{> ... C<}> construct to explicitly create
a hash and assign it to a variable. Note that commas are optional
between key/value pairs and C<=> can be used in place of C<=E<gt>>.
# minimal TT style
[% product = {
id = 'XYZ-2000'
desc = 'Bogon Generator'
price = 666
}
%]
# perl style
[% product = {
id => 'XYZ-2000',
desc => 'Bogon Generator',
price => 666,
}
%]
=head2 List References
Items in lists are also accessed by use of the dot operator.
Example data:
my $vars = {
people => [ 'Tom', 'Dick', 'Larry' ],
};
Example template:
[% people.0 %] # Tom
[% people.1 %] # Dick
[% people.2 %] # Larry
The C<FOREACH> directive can be used to iterate through items in a list.
[% FOREACH person IN people %]
Hello [% person %]
[% END %]
Generated output:
Hello Tom
Hello Dick
Hello Larry
Lists can be constructed in-situ using the regular anonymous list
C<[> ... C<]> construct. Commas between items are optional.
[% cols = [ 'red', 'green', 'blue' ] %]
[% FOREACH c IN cols %]
[% c %]
[% END %]
or:
[% FOREACH c IN [ 'red', 'green', 'blue' ] %]
[% c %]
[% END %]
You can also create simple numerical sequences using the C<..> range
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!', @_) },
};
Example 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'),
};
Example template:
[% FOREACH p IN cgi.param %] # returns list of param keys
[% p %] => [% cgi.param(p) %] # fetch each param value
[% END %]
Generated 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 Passing Parameters and Returning 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 C<=E<gt>> or C<=> 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 } || ' + ', @_);
}
Example template:
[% myjoin(10, 20, 30) %]
[% myjoin(10, 20, 30, joint = ' - ' %]
[% myjoin(joint => ' * ', 10, 20, 30 %]
Generated 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' ) },
};
Example template:
[% FOREACH i IN items1 %]
...
[% END %]
[% FOREACH i IN items2 %]
...
[% END %]
=head2 Error Handling
Errors can be reported from user code by calling C<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 C<error>
variable.
my $vars = {
barf => sub {
die "a sick error has occurred\n";
},
};
Example 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 C<die()> are converted to exceptions of type
C<undef> (the literal string "undef" rather than the undefined value).
Exceptions of user-defined types can be thrown by calling C<die()> with
a reference to a L<Template::Exception> object.
use Template::Exception;
my $vars = {
login => sub {
...do something...
die Template::Exception->new( badpwd => 'password too silly' );
},
};
Example template:
[% TRY %]
[% login %]
[% CATCH badpwd %]
Bad password: [% error.info %]
[% CATCH %]
Some other '[% error.type %]' error: [% error.info %]
[% END %]
The exception types C<stop> and C<return> are used to implement the
C<STOP> and C<RETURN> directives. Throwing an exception as:
die (Template::Exception->new('stop'));
has the same effect as the directive:
[% STOP %]
=head1 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 C<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 C<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.
=head1 Variable Interpolation
The Template Toolkit uses C<$> 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 C<INTERPOLATE> option is set:
Dear $honorific $firstname $surname,
The same rules apply within directives. If a variable is prefixed
with a C<$> 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' %]
[% users.$uid %] # same as 'users.abw'
Curly braces can be used to delimit interpolated variable names where
necessary.
[% users.${me.id}.name %]
Directives such as C<INCLUDE>, C<PROCESS>, etc., that accept a template name
as the first argument, will automatically quote it for convenience.
[% INCLUDE foo/bar.txt %]
The above example is equivalent to:
[% INCLUDE "foo/bar.txt" %]
To C<INCLUDE> a template whose name is stored in a variable, simply
prefix the variable name with C<$> to have it interpolated.
[% myfile = 'header' %]
[% INCLUDE $myfile %]
This is equivalent to:
[% INCLUDE header %]
Note also that a variable containing a reference to a L<Template::Document>
object can also be processed in this way.
my $vars = {
header => Template::Document->new({ ... }),
};
Example template:
[% INCLUDE $header %]
=head1 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 C<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 C<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 %]
=head1 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 C<CONSTANTS> hash as a
constructor item as per C<VARIABLES>. The C<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 C<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
C<joint> is a runtime variable and cannot be determined at compile
time.
# ERROR: runtime variable argument!
[% constants.col.keys.sort.join(joint) %]
The C<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 %]
=head1 Special Variables
A number of special variables are automatically defined by the Template
Toolkit.
=head2 template
The C<template> variable contains a reference to the main template being
processed, in the form of a L<Template::Document> object. This variable is
correctly defined within C<PRE_PROCESS>, C<PROCESS> and C<POST_PROCESS>
templates, allowing standard headers, footers, etc., to access metadata items
from the main template. The C<name> and C<modtime> metadata items are
automatically provided, giving the template name and modification time in
seconds since the epoch.
Note that the C<template> variable always references the top-level
template, even when processing other template components via C<INCLUDE>,
C<PROCESS>, etc.
=head2 component
The C<component> variable is like C<template> but always contains a
reference to the current, innermost template component being processed.
In the main template, the C<template> and C<component> variable will
reference the same L<Template::Document> object. In any other template
component called from the main template, the C<template> variable
will remain unchanged, but C<component> will contain a new reference
to the current component.
This example should demonstrate the difference:
$template->process('foo')
|| die $template->error(), "\n";
F<foo> template:
[% template.name %] # foo
[% component.name %] # foo
[% PROCESS footer %]
F<footer> template:
[% template.name %] # foo
[% component.name %] # footer
Additionally, the C<component> variable has two special fields:
C<caller> and C<callers>. C<caller> contains the name of the template
that called the current template (or undef if the values of C<template>
and C<component> are the same). C<callers> contains a reference to a
list of all the templates that have been called on the road to calling
the current component template (like a call stack), with the
outer-most template first.
Here's an example:
F<outer.tt2> template:
[% component.name %] # 'outer.tt2'
[% component.caller %] # undef
[% component.callers %] # undef
[% PROCESS 'middle.tt2' %]
F<middle.tt2> template:
[% component.name %] # 'middle.tt2'
[% component.caller %] # 'outer.tt2'
[% component.callers %] # [ 'outer.tt2' ]
[% PROCESS 'inner.tt2' %]
F<inner.tt2> template:
[% component.name %] # 'inner.tt2'
[% component.caller %] # 'middle.tt2'
[% component.callers %] # [ 'outer.tt2', 'middle.tt2' ]
=head2 loop
Within a C<FOREACH> loop, the C<loop> variable references the
L<Template::Iterator> object responsible for controlling the loop.
[% FOREACH item = [ 'foo', 'bar', 'baz' ] -%]
[% "Items:\n" IF loop.first -%]
[% loop.count %]/[% loop.size %]: [% item %]
[% END %]
=head2 error
Within a C<CATCH> block, the C<error> variable contains a reference to the
L<Template::Exception> object thrown from within the C<TRY> block. The
C<type> and C<info> methods can be called or the variable itself can
be printed for automatic stringification into a message of the form
"C<$type error - $info>". See L<Template::Exception> for further details.
[% TRY %]
...
[% CATCH %]
[% error %]
[% END %]
=head2 content
The C<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 %]
<blockquote class="prose">
[% content %]
</blockquote>
[% END %]
=head1 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.
=cut
# Local Variables:
# mode: perl
# perl-indent-level: 4
# indent-tabs-mode: nil
# End:
#
# vim: expandtab shiftwidth=4:

View File

@@ -0,0 +1,586 @@
#============================================================= -*-perl-*-
#
# Template::Manual::Views
#
# AUTHOR
# Andy Wardley <abw@wardley.org>
#
# COPYRIGHT
# Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
#
# This module is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
#========================================================================
=head1 NAME
Template::Manual::Views - Template Toolkit views (experimental)
=head1 Overview
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
C<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 independent, 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.
=head1 Views as Template Collectors/Providers
The C<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 C<END> directive.
[% VIEW myview %]
...
[% END %]
The first role of a view is to act as a collector and provider of templates.
The C<include()> method can be called on a view to effectively do the same
thing as the C<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 'C<prefix>' and 'C<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 C<AUTOLOAD> method which maps method names to the
C<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') %]
=head1 Local BLOCK Definitions
A C<VIEW> definition can include C<BLOCK> definitions which remain local to
the view. A request for a particular template will return a C<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 C<BLOCK> definitions, a C<VIEW> can contain any other
template directives. The entire C<VIEW> definition block is processed to
initialise the view but no output is generated (this may change RSN -
and get stored as 'C<output>' item, subsequently accessible as C<[%
view.output %]>). However, directives that have side-effects, such as
those that update a variable, will have noticeable consequences.
=head1 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 (C<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 C<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 'C<title>' as a simple variable, a template
defined in an external file, possibly with a prefix/suffix automatically
appended, or as a local C<BLOCK> definition within the C<[% VIEW %] ... [% END %]>
definition. If you use the syntax above then the view will Do The Right
Thing to return the appropriate output.
At the C<END> of the C<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 C<END> of the C<VIEW> definition block then
a C<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 C<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 C<base>
parameter. This example shows how a base class view is defined which
applies a C<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 C<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 C<INCLUDE/PROCESS/WRAPPER> directives work entirely
independently 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
C<VIEW ... END> block by its specified name and also by the special name
'C<view>' (similar to the C<my $self = shift;> in a Perl method or the
'C<this>' pointer in C++, etc). The view is initially unsealed allowing
any data items to be defined and updated within the C<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 (C<SEALED>), it should be possible to set an option in the view to
allow external contexts to update existing variables (C<UPDATE>) or even
create totally new view variables (C<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, 'C<fancy>', or by the general name, 'C<view>'. Outside of the
view block, however, you should always use the given name, 'C<fancy>':
[% fancy.title %]
[% fancy.author %]
[% fancy.col.bg %]
The choice of given name or 'C<view>' is much more important when it
comes to C<BLOCK> definitions within a C<VIEW>. It is generally recommended
that you use 'C<view>' inside a C<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 'C<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 C<foo> variable, the header
block still correctly accesses the C<title> attribute of the view to
which it belongs. Whenever a view C<BLOCK> is processed, the C<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 C<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 C<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 'C<::>' converted to a single 'C<_>'.
[% 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 ('C<thingies>' and 'C<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 C<default> map entry, specified as part of the C<map>
hash or as a parameter by itself.
[% VIEW foo
map = { ... },
default = 'whatever'
%]
...
[% END %]
or
[% VIEW foo %]
[% view.map = { ... }
view.default = 'whatever'
%]
...
[% END %]
The C<print()> method provides one more piece of magic. If you pass it a
reference to an object which provides a C<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 C<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 I<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 C<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 C<XML::DOM> trees. The documentation for the
C<Template::Plugin::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 C<File>/C<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 C<pod/html/head1>, C<pod/html/head2>, C<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: F<t/pod.t> and
F<t/view.t> which may shed some more light on this. See the distribution
sub-directory F<examples/pod/html> for examples of Pod -E<gt> HTML templates.
=cut
# Local Variables:
# mode: perl
# perl-indent-level: 4
# indent-tabs-mode: nil
# End:
#
# vim: expandtab shiftwidth=4: