| Template-Trivial documentation | Contained in the Template-Trivial distribution. |
Template::Trivial - Simple (yet powerful) and fast substitution templates
use Template::Trivial;
my $tmpl = new Template::Trivial( templates => '/path/to/templates' );
$tmpl->define( main => 'main.tmpl',
list => 'list.tmpl' );
$tmpl->define_from_string( item => '<li>{ITEM}' );
for $i ( 1 .. 3 ) {
$tmpl->assign( ITEM => "Thingy $_" );
$tmpl->parse( '.ITEMS' => 'item' );
}
$tmpl->parse(LIST => 'list' );
$tmpl->parse(MAIN => 'main' );
## print out
print $tmpl->to_string('MAIN');
Template::Trivial is heavily inspired by the excellent and stable CGI::FastTemplate written by Jason Moore. We introduce a slightly modified syntax, fewer features, and a slight execution improvment over CGI::FastTemplate.
The design goals of Template::Trivial were:
For those wanting to dig in, here is an absolute barebones reference. The rest of the document is just details.
my $tmpl = new Template::Trivial;
$tmpl->templates('/usr/opt/templates');
$tmpl->define( main => 'main.tmpl',
head => 'head.tmpl',
body => 'body.tmpl', );
<html>
{HEAD}
{BODY}
</html>
<body>
<h2>{TITLE}</h2>
Blah blah blah.
</body>
$tmpl->assign(TITLE => "My own web page");
[A-Z][A-Z0-9_-]*
$tmpl->parse(BODY => 'body');
<body>
<h2>{TITLE}</h2>
Blah blah blah.
</body>
<body>
<h2>My own web page</h2>
Blah blah blah.
</body>
print $tmpl->to_string('MAIN');
That's Template::Trivial in a nutshell. Here is a complete example:
Write some templates and put them in files:
<html>
{HEAD}
{BODY}
</html>
<head>
<title>{TITLE}</title>
</head>
<body>
<h2>{TITLE}</h2>
This is a {TEST}.
</body>
Now, write the program to use the templates:
use Template::Trivial;
my $tmpl = new Template::Trivial;
$tmpl->define( main => 'main.tmpl',
head => 'head.tmpl',
body => 'body.tmpl' );
$tmpl->assign(TITLE => "This is the title");
$tmpl->assign(TEST => "Testing 1 2 3...");
$tmpl->parse(HEAD => 'head');
$tmpl->parse(BODY => 'body');
$tmpl->parse(MAIN => 'main');
print $tmpl->to_string('MAIN');
That's it. Here's a play-by-play:
Create the Template::Trivial object:
my $tmpl = new Template::Trivial;
Tell the object where to find the templates and give aliases for the templates. The aliases are the same pattern as variables except lowercase letters:
$tmpl->define( main => 'main.tmpl',
head => 'head.tmpl',
body => 'body.tmpl' );
Assign some variable data:
$tmpl->assign(TITLE => "This is the title");
$tmpl->assign(TEST => "Testing 1 2 3...");
Parse the 'head' template (which points to head.tmpl). When this template is parsed, its contents will be saved in the 'HEAD' template variable, which the 'main' template uses:
$tmpl->parse(HEAD => 'head');
So the 'HEAD' variable is now:
<head>
<title>This is the title</title>
</head>
Parse the 'body' template. This works just like 'head'; it must be processed before 'main' is processed, since 'main' depends on 'BODY' to be already defined:
$tmpl->parse(BODY => 'body');
So the 'BODY' variable is now:
<body>
<h2>This is the title</h2>
This is a Testing 1 2 3....
</body>
Now parse the "top" template 'main':
$tmpl->parse(MAIN => 'main')
We recall that the 'main' template was:
<html>
{HEAD}
{BODY}
</html>
The parse method replaces the 'HEAD' and 'BODY' variables with their contents:
<html>
<head>
<title>This is the title</title>
</head>
<body>
<h2>This is the title</h2>
This is a Testing 1 2 3....
</body>
</html>
This new string is assigned to the variable 'MAIN' in the parse method.
Print out our results:
print $tmpl->to_string('MAIN');
The following methods are specified in order of how they might appear in a real program (i.e., in the order you might use them).
Create a new template object.
my $tmpl = new Template::Trivial;
new optionally takes the following arguments:
strict => 0
templates => '/path/to/templates'
Tells the template object where to look for templates you define in from_file.
$tmpl->templates('/path/to/templates');
This may also be set in the constructor. The default value is the empty string ''.
Will emit a warning when any of the following conditions occur:
- a template alias in 'define' does not match the lowercase regular
expression pattern: /^[a-z][a-z0-9_-]*?$/
- a file in a 'define' statement is not a regular file or character
special device
- a variable in 'assign' does not match the uppercase regular
expression pattern: /^[A-Z][A-Z0-9_-]*?$/
- a variable in 'assign_from_file' does not match the uppercase
regular expression pattern: /^[A-Z][A-Z0-9_-]*?$/
- a file in an 'assign_from_file' statement is not a regular file
or character special device
- a variable in 'append' does not match the uppercase regular
expression pattern: /^[A-Z][A-Z0-9_-]*?$/
- an undefined variable is encountered in a template during 'parse'
- an undefined variable is encountered in 'to_string'
Example:
$tmpl->strict(0);
The strict option may be set in the constructor. It defaults to '1'.
Defines a mapping of template aliases to filenames.
$tmpl->define( main => 'main.tmpl',
head => '/usr/opt/tmpl/head.tmpl',
body => 'body.tmpl', );
The path specified by templates will be prepended to the filenames specified in define, except when the filename begins with a slash '/', in which case the absolute path will be used.
Defines a mapping of template names to the contents of a string.
$tmpl->define_from_string( footer => "created on ${DATE}" );
This is a quick way for a programmer to make a template without writing one to file. Useful for testing or "locking away" parts of a template set. See Philosophy.
Assigns the specified string to the specified template variable.
$tmpl->assign( FOO => 'this is foo' );
or using a "here" document:
$tmpl->assign( FOO => <<_BLECH_ );
This is a longer foo
with multiple lines.
_BLECH_
Subsequent assignments to the same template will override previous assignments.
You can make multiple assignments in one call:
$tmpl->assign( FOO => 'foo string',
BAR => 'bar string' );
You can also append a string to an existing variable by prepending a dot to the variable:
$tmpl->assign('.FOO' => ' and more foo');
but this is accomplished more cleanly with the append method (below). This usage is deprecated and is included chiefly for CGI::FastTemplate compatibility (and partly for nostalgia).
Assigns the contents of a specified file to the specified variable. Paths are relative to the value of the templates method. from_file may be used multiple times, or may take several list arguments:
$tmpl->assign_from_file( FOO => 'foo.txt',
BAR => 'bar.txt' );
is the same as:
$tmpl->assign_from_file( FOO => 'foo.txt' );
$tmpl->assign_from_file( BAR => 'bar.txt' );
If the filename begins with a slash, the value of templates will not be prepended:
$tmpl->assign_from_file( MAH => '/path/to/mah.txt' );
Parses the specified template and saves its results in the specified variable.
$tmpl->parse( MAIN => 'main' );
Multiple variable/alias pairs may be specified:
$tmpl->parse( JOE => 'joe', BOB => 'bob_file');
but the templates are not guaranteed to be parsed in the order specified. Because of this, you should not put codependent templates in the same parse statement.
Returns the contents of a template variable as a string. Useful for assignment or printing.
print $tmpl->to_string('FOO');
That concludes this example.
We'd like to be as complete as CGI::FastTemplate sometime, but we wanted to get this out the door. Here are some features to look for around Q1 or Q2 of 2004.
$tmpl->define( foo => '' );
$tmpl->define( foo => undef );
$tmpl->assign( FOO => '' );
$tmpl->assign( FOO => undef );
CGI::FastTemplate(3).
Scott Wiersdorf, <scott@perlcode.org>
Copyright (C) 2007 by Scott Wiersdorf
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.6 or, at your option, any later version of Perl 5 you may have available.
| Template-Trivial documentation | Contained in the Template-Trivial distribution. |
package Template::Trivial; use 5.00503; use strict; use warnings; use vars qw($VERSION); $VERSION = '0.08'; use vars qw($STRICT); ## template stricture use vars qw($TMPL_DIR); ## template directory use vars qw(%VARIABLES); ## template variables (e.g., FOO, BAR) use vars qw(%TEMPLATE_NAME); ## template aliases (e.g., foo, bar) use vars qw(%TEMPLATE_CACHE); ## template contents my $VAR_RE = qr(^[A-Z][A-Z0-9_-]*?$)o; my $TMPL_RE = qr(^[a-z][a-z0-9_-]*?$)o; my $TVAR_RE = qr!\{([A-Z][A-Z0-9_-]*?)\}!o; sub new { my $class = shift; my $proto = ref($class) || $class; my $self = { }; my %parms = @_; bless $self, $proto; $STRICT = ( defined $parms{strict} ? $parms{strict} : 1 ); $TMPL_DIR = ( defined $parms{templates} ? $parms{templates} : '' ); %VARIABLES = (); %TEMPLATE_NAME = (); %TEMPLATE_CACHE = (); return $self; } sub strict { my $self = shift; $STRICT = ( @_ ? shift : $STRICT ); } sub templates { my $self = shift; if( @_ ) { ## new assignment $TMPL_DIR = shift; if( $TMPL_DIR && $TMPL_DIR !~ m!/$! ) { $TMPL_DIR .= '/'; } } return $TMPL_DIR; } sub define { my $self = shift; my %defines = @_; for my $tmpl ( keys %defines ) { my $path = ( $defines{$tmpl} =~ m!^/!o ? $defines{$tmpl} : $TMPL_DIR . $defines{$tmpl} ); if( $STRICT ) { warn "Illegal template alias name '$tmpl'\n" unless $tmpl =~ $TMPL_RE; unless( -f $path || -c _ ) { warn "File '$path' ($tmpl) is not a file\n"; next; } } $TEMPLATE_NAME{$tmpl} = $path; ## redefining a template clears it from the cache delete $TEMPLATE_CACHE{$tmpl} if exists $TEMPLATE_CACHE{$tmpl}; } } ## FIXME: add an alias or two for define_from_string method sub define_from_string { my $self = shift; my %defines = @_; for my $tmpl ( keys %defines ) { $TEMPLATE_CACHE{$tmpl} = $defines{$tmpl}; } } sub assign { my $self = shift; my %assign = @_; for my $var ( keys %assign ) { my $append = $var =~ s/^\.//o; if( $STRICT ) { warn "Illegal variable name '$var'\n" unless $var =~ $VAR_RE; } if( $append ) { $VARIABLES{$var} .= $assign{".$var"}; } else { $VARIABLES{$var} = $assign{$var}; } } } sub assign_from_file { my $self = shift; my %assign = @_; for my $var ( keys %assign ) { my $append = $var =~ s/^\.//o; my $path = ( $assign{$var} =~ m!^/! ? $assign{$var} : $TMPL_DIR . $assign{$var} ); if( $STRICT ) { warn "Illegal variable name '$var'\n" unless $var =~ $VAR_RE; unless( -f $path || -c _ ) { warn "File '$path' is not a file\n"; next; } } open FILE, "$path" or do { warn "Could not open '$path': $!\n"; next; }; local($/) = undef; if( $append ) { $VARIABLES{$var} .= <FILE>; } else { $VARIABLES{$var} = <FILE>; } close FILE; } } sub append { my $self = shift; my %assign = @_; for my $var ( keys %assign ) { if( $STRICT ) { warn "Illegal key name '$var'\n" unless $var =~ $VAR_RE; } $VARIABLES{$var} .= $assign{$var}; } } ## FIXME: append_from_file? ## FIXME: any defaults for to_string('MAIN'), etc.? How about ## FIXME: parse('MAIN') implies parse('MAIN => 'main')? sub parse { my $self = shift; my %parse = @_; while( my($var, $tmpl) = each %parse ) { my $append = $var =~ s/^\.//o; my $file; ## find the template in our cache unless( defined $TEMPLATE_CACHE{$tmpl} ) { open TMPL, "$TEMPLATE_NAME{$tmpl}" or do { warn "Could not open template ($tmpl) '$TEMPLATE_NAME{$tmpl}': $!\n"; next; }; local($/) = undef; $TEMPLATE_CACHE{$tmpl} = <TMPL>; close TMPL; } $file = $TEMPLATE_CACHE{$tmpl}; ## parse the template $file =~ s{$TVAR_RE}{ if( exists $VARIABLES{$+} ) { $VARIABLES{$+}; } else { if( $STRICT ) { warn "Unknown variable '$+' found.\n"; } "{$+}"; ## put it back how it was } }xge; if( $append ) { $VARIABLES{$var} .= $file; } else { $VARIABLES{$var} = $file; } } } sub to_string { my $self = shift; if( $STRICT ) { unless( $_[0] && exists $VARIABLES{$_[0]} && $_[0] =~ $VAR_RE ) { warn "Undefined or unknown variable '$_[0]' found.\n"; return undef; } } return ( defined $VARIABLES{$_[0]} ? $VARIABLES{$_[0]}: '' ); } ## FIXME: clear methods? 1; __END__