The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Text::Templar - a document-generation object class

SYNOPSIS

  use Text::Templar;
  
  my $template = <<'EOF';
  
  <html><head><title>This is the title: <% METHOD title %></title></head>
  
  <body>
  
  <% METHOD body %>
  
  <address>
  <% METHOD footer %>
  </address>
  
  </body>
  </html>
  EOF
  
  my $templateObject = new Text::Templar
        [ $template ];
  
  $templateObject->title( "The Rest of the Story" );
  $templateObject->body( @content );
  $templateObject->footer( "Page 1" );
  
  print $templateObject->render;

REQUIRES

Class::Translucent, IO::File, IO::Handle, Scalar::Util, Data::Dumper, Text::Templar::Parser, Text::Templar::Exceptions

EXPORTS

None.

AUTHOR/S

Michael Granger <ged@FaerieMUD.org> and Dave McCorkhill <scotus@FaerieMUD.org>.

Copyright (c) 1998-2003 Michael Granger and The FaerieMUD Consortium. All rights reserved.

This module is free software. You may use, modify, and/or redistribute this software under the terms of the Perl Artistic License. (See http://language.perl.com/misc/Artistic.html)

DESCRIPTION

This module is an object class for generating text. It is configured by creating template files with specially formatted tags.

It differs from other templating modules in that it has an inverted control model. This means that the template itself is a passive element of the controlling program, allowing a decoupling of the presentation or data output part of a program and the logic/control part. Templar templates only concern themselves with manipulating the data that is directly used for presentation. The actual mechanism for gathering, modifying, and controlling the data is assumed to be in the program that uses the template.

The template object is created by parsing lines of text which have HTML-like tags embedded in them, which are referred to as "directives" in this document. Directives define the interface and behaviors of the instantiated template object, and the output is manipulated purely by interacting with the template objects.

Template Phases

Template objects have a three-phase life cycle: parse phase, interaction phase, and rendering phase.

Parse Phase

The parse phase is entered when the load() method is called, either explicitly or by passing a source file name to the new() method. The template source is parsed, and an object is returned which can be manipulated by the controlling program. Directives parsed from the template source control the structure and behavior of the resultant object. If the template content fails to parse, an exception is generated which you may catch by wrapping the call to load() in an eval BLOCK, or by using the try/catch functions from the Text::Templar::Exceptions module.

Interaction Phase

In this phase, the controlling program can insert data into the template object to (possibly) modify the final output. It does this by calling methods on the template object with the desired data. Each such method acts as an appender, adding the specified input to a content array which is later accessed by the template object itself when it is rendered.

Render Phase

After the controlling program finishes with the interaction phase, it can call the render() method on the template object, which causes the template to return rendered content. Rendering is when the template actually does any processing it needs to do to turn the data given to it by the controlling program into text output.

TEMPLATE DIRECTIVES

Directives are embedded tags of the form:

  <% DIRECTIVE attributes %>

A directive may have one or more forms with different attributes. There are three basic types of directive: the unitag, container tag, and the conditional tag.

Directive Attributes

name

The directive name, which must begin with a letter, and consist of alphanumeric characters and underscores. A directive with a name attribute will cause a method of the same name to be created in the template object. Any data specified as an argument to this method will be made available to the directive at render time.

codeblock

A Perl codeblock of the form:

  { <code> }

The codeblock you specify will have access to any DEFINEd variables as lexical scalars, and will also have at least the following constants defined:

$TEMPLATE_PATH

The fully-qualified path to the template which contains the directive, or '(anonymous)' if the template source came from an array.

$TEMPLATE_OBJECT

A reference to the template object in which the codeblock is executing.

$TEMPLAR_VERSION

The version number of the Text::Templar module in which the codeblock is running.

$TEMPLAR_RCSID

The RCS-style id string from the Text::Templar module in which the codeblock is running.

format

A printf-style format string which will be applied to each rendered element of the directive's content directly. The format should contain only one formatting directive.

See the documentation for the Perl printf function for details.

methodchain

A chain of elements which can be method calls, hash element keys, or array indexes. The meaning of the element is decided by looking at the type of data it is being performed on, so that an element that applies to an object is assumed to be a method call, an element applied to a hashref is assumed to be a hash lookup, and an element applied to an arrayref is assumed to be an index.

Each element in the chain is separated by either a '.' or '->', and method calls can optionally have zero or more arguments in parentheses. For example, a method chain of the following form:

  customer()

would call the 'customer' method on whatever object it was applied to. If the 'customer' method returns an object, then you could change it to read:

  customer->name

to retrieve the customer's name from the customer object. Note that you needn't use parenthesis if you are not passing arguments. If the customer class defines a phoneNumbers method which returns a reference to a hash of telephone numbers, you could look up phone number associated with the 'work' key with the following syntax:

  customer->phoneNumbers->work

You could also use '.' as method call separators to do it like this:

  customer.phoneNumbers.work

Similarly, you can look up a single element from an arrayref by adding its index to the methodchain:

  customer.orders.5.orderNumber

quotedArgument

A quoted literal argument. You can use any style of quotes valid in Perl. Eg., 'John', "John", q{John}, qq/John/, and qw#John# are all equivalent.

variable

A valid Perl variable name, with prepended type-indicator. Examples:

  $name
  
  @includePath
  
  %lookupTable

path

An absolute or relative Unix pathname. It must be quoted with any valid Perl quoting mechanism. Eg.,

  q{/www/templates/main.tmpl}
  
  "/mnt/docs/My Documents/something"

question

A quoted string (any Perl quote), which is used as a prompt for the user.

matchspec

A matching specification used in QUERY and conditional directives, which may be in one of three forms: a regular expression, an array of matches, or a hash lookup table.

A regexp matchspec causes a simple regexp match to be attempted against candidate values, and any saved subexpressions (if present) are returned.

An array matchspec specifies a list of acceptable values, and simply returns any elements of the array which exactly (stringwise) match the candidate value.

A hash matchspec specifies a hash of key-value pairs that act like abbreviations. The keys are compared (stringwise) to candidate values, and if any match, the expanded version (the value) is returned.

iterator

For looping container constructs (FOREACH, MAP, GREP, SORT, and JOIN), you may specify the name of an iterator which is used as the name of the iterated value inside the loop. This name falls under the same constraints as the "name" attribute, and only exists inside of the loop, much the same way perl's local works. If another named directive is contained in the same page, the iterator moves the old value out of the way prior to replacing it, and when the loop is finished, moves it back.

Unitags

A unitag is one directive by itself which possibly contains attributes that provide the specifics for that directive.

METHOD directive

  <% METHOD <name> <codeblock> %>
  <% METHOD <name> <format> %>
  <% METHOD <name> %>

Creates a template method with the specified "name", which when called, will insert its arguments into the rendered output at any place the named directive appears. A method may appear with the same "name" more than once, in which case the arguments passed to the method appear in each place the method directive is defined. Methods may have an optional "format" or "codeblock" attribute.

The "format" attribute is a printf-style format string which is applied to each template value after it has been rendered.

The "codeblock" attribute is a Perl subroutine which acts as a preprocessor for data that is given to the method. The subroutine is called once for each value that has been passed to the named method at render time, and any values it returns are inserted into the place the directive occupies. The subroutine is passed three arguments: a reference to the template object, a reference to the METHOD node object, and the content item itself.

Examples:

In the template:

  <TITLE><% METHOD title %></TITLE>
  <P>The total number of dollars collected: $<% METHOD totalDollars '%05.2f' %></P>
  
  <P><% METHOD pagelinks {
        my ( $template, $node, $data ) = @_;
    
        return qq{[ <A href="$data->{href}">$data->{link}</A> ]};
  } %>

In the program:

  $template->title( "How the West Was Won" );
  $template->totalDollars( 15 );
  
  $template->pagelinks({ href => 'pageone.html', link => 'Page One' });
  $template->pagelinks({ href => 'pagetwo.html', link => 'Page Two' });
  $template->pagelinks({ href => 'pagethree.html', link => 'Page Three' });

Would render as:

  <TITLE>How the West Was Won</TITLE>
  <P>The total number of dollars collected: $00015.00</P>
  
  <A href="pageone.html">Page One</A>
  <A href="pagetwo.html">Page Two</A>
  <A href="pagethree.html">Page Three</A>

METHODCALL directive

  <% METHODCALL <name> <methodchain> <format> %>
  <% METHODCALL <name> <methodchain> %>

Creates a template method with the specified "name". When the template is rendered, the specified method chain will be called on the data passed as arguments to the template method, and any return values are rendered and inserted in place of the directive. See the "methodchain" attribute elsewhere in this document for more.

Methodcall directives may have an optional "format" attribute.

Examples:

In the template:

  <TITLE><% METHODCALL account customer.wholeName %>'s Account</TITLE>
  <P>Balance: $<% METHODCALL account calculateCurrencyValue('USD') '%.2f' %></P>

In the program:

  my $account = lookup Account 15;
  $template->account( $account );

Would, if account object 15 contained a customer object whose name was 'Alfred Rohe', and a balance of $1634.15, render as:

  <TITLE>Alfred Rohe's Account</TITLE>
  <P>Balance: $1634.15</P>

DUMP directive

  <% DUMP <name> %>

Creates a template method with the specified "name". When the template is rendered, the specified value will be dumped as Perl code into the rendered output.

Examples:

In the template:

  <P>The hash looks like this:</P>
  <PRE>
  <% DUMP myHash %>
  </PRE>

In the program:

  my $hash = { some => 'test', values => 'for', demonstration => 'purposes' };
  $template->myHash( $hash );

Would render looking something like:

  <P>The hash looks like this:</P>
  <PRE>
  $myHash = {
              'values' => 'for',
              'demonstration' => 'purposes',
              'some' => 'test'
            };
  </PRE>

DEFINE directive

  <% DEFINE <name> [=] <quotedArgument> %>
  <% DEFINE <variable> [=] <quotedArgument> %>
  <% DEFINE <name> [=] <codeblock> %>
  <% DEFINE <variable> [=] <codeblock> %>

The DEFINE directive causes a template attribute with the "name" specified to be defined. These attributes will thenceforth be available to any evaluated "codeblock" in the same template.

The first directive attribute can either be a "name", in which case it is assumed to be a scalar value of the same "name", or a "variable".

The '=' part of the directive is syntactic sugar, and doesn't really cause anything different to happen.

The second argument can be either a quoted string or a "codeblock" to be evaluated. The result from the "codeblock" will be assigned to the defined attribute.

After the template is parsed, you can access defined values through the defines(), getDefines(), setDefines(), and deleteDefines() methods, or inside any evaluated value as a lexical variable.

Examples:

In the template:

  <% DEFINE $parseTime { scalar localtime } %>
  <% DEFINE bodyColor '#FFFFFF' %>
  <% DEFINE linkColor '#FF0000' %>
  <BODY bgcolor="<% EVAL $bodyColor %>" link="<% EVAL $linkColor %>">
  <P>Parsed at: <% EVAL $parseTime %></P>
  </BODY>

In the program:

  $oldLinkColor = $template->getDefines( 'linkColor' );
  
  # Set a new link color
  $template->setDefines( linkColor => '#00FF00' );

Rendered, the template would look like:

  <BODY bgcolor="#FFFFFF" link="#00FF00">
  <P>Parsed at: Mon Apr  3 15:43:40 2000</P>
  </BODY>

STOP directive

  <% STOP %>

The STOP directive indicates that the parser should stop rendering at the point at which it is encountered. Template content below the STOP directive will be parsed, and will be reflected in the structure of the template object, but will not show up when rendered.

Examples:

In the template:

  This stuff will be rendered.
  
  <% STOP %>
  
  This stuff won't. But I can still <% DEFINE something = 'here' %>.

In the program:

  $template->getDefines( 'something' ); # -> Returns 'here'

Would render as:

  This stuff will be rendered.

CUT directive

  <% CUT %>

The CUT directive is a top-wise STOP; it indicates that the parser should not start rendering until the point at which it is encountered. Template content above the CUT directive will be parsed, and will be reflected in the structure of the template object, but will not show up when rendered.

Examples:

In the template:

  This stuff won't be rendered. But I can still <% DEFINE something = 'here' %>.

  <% CUT %>
  
  This stuff will be rendered.
  

In the program:

  $template->getDefines( 'something' ); # -> Returns 'here'

Would render as:

  This stuff will be rendered.

EVAL directive

  <% EVAL <variable> <format> %>
  <% EVAL <variable> %>
  <% EVAL <codeblock> <format> %>
  <% EVAL <codeblock> %>

The EVAL directive is used to insert a value in the template at the moment in which it is encountered. The value inserted can be either a "variable" that is either "DEFINE"d elsewhere, or one of the constants defined by the Text::Templar class itself (see the "codeblock" for more about the environment in which EVALs happen.

Examples:

In the template:

  Template:       <% EVAL $TEMPLATE_PATH %>
  Parsed:         <% EVAL { scalar localtime } %>

In the program:

  $template = new Text::Templar '/www/templates/base.tmpl';

Would render as:

  Template:             /www/templates/base.tmpl
  Parsed:               Mon Apr  3 16:01:53 2000

INCLUDE directive

  <% INCLUDE <path> %>

Parse and insert the specified template into the current template body.

Examples:

In the template:

  <HTML>
  <HEAD>
  <TITLE>The Page</TITLE>
  <% INCLUDE /www/templates/metatags.incl %>
  </HEAD>
  <BODY>Aha!</BODY>
  </HTML>

In 'metatags.incl':

  <META name="author" content="Bertrand Russell">
  <META name="author-email" content="btrand@philosphers.org">

Would render as:

  <HTML>
  <HEAD>
  <TITLE>The Page</TITLE>
  <META name="author" content="Bertrand Russell">
  <META name="author-email" content="btrand@philosphers.org">
  </HEAD>
  <BODY>Aha!</BODY>
  </HTML>

QUERY directive

  <% QUERY <name> <question> <matchspec> %>

Create and insert a query object into the template object. Query objects can be used to build interactive prompts, specify untainting tables, or to otherwise specify a means of extracting useful data from user input.

Examples:

In the template:

  <% QUERY clientName 'Your name: ' /([\w\s]+)}/ %>

In the program:

  my @queries = $template->queries;
  
  foreach my $query ( @queries ) {
        print $query->question;
        chomp( my $response = <STDIN> );
        redo unless $query->matchspec->matches( $response );
  }

ENV directive

  <% ENV <name> <format> %>
  <% ENV <name> %>

This directive inserts the environment variable specified by "name" into the rendered template output after being formatted by the optional "format" string.

Examples:

In the template:

  <% ENV HTTP_USER_AGENT %>

Might render as:

  Mozilla (X11; I; Linux 2.0.32 i586)

META directive

  <% META  <name> <quotedArgument> %>

Define metadata for the template. This can be used by the template creator to list template details which do not belong in the regular template attributes.

Examples:

  <% META template-author 'Michael Granger' %>
  <% META rscid q$Id: Templar.pod,v 1.18 2003/01/15 21:20:19 deveiant Exp $>

INHERIT directive

  <% INHERIT <name> %>

Inherit the content container with the specified "name" from an enclosing template, if it exists. This allows you to propagate content from a container template to the subtemplates that it contains.

Examples:

In the outer-most template:

  The cutoff date will be: <% METHOD targetDate %><BR>
  <% METHOD subTemplate %>

In a subordinate template:

  <% INHERIT targetDate %>
  If you should wish to register before <% METHOD targetDate %>, then the place
  to do so is: ...

In the program:

  $outermostTemplate->targetDate( '10/15/1999' );
  $outermostTemplate->subTemplate( $subTemplateObject );
  $outermostTemplate->render;

Would render as:

  The date will be: 10/15/1999
  If you should wish to register before 10/15/1999, then the place
  to do so is: ...

Container Tags

Container tags are directives which operate on a chunk of the template content. They define the content to operate on by delimiting it with the opening tag + attributes and a closing tag, just as in most markup languages. The closing tag is a tag of the same form, but without any attributes, and with either a '/' or an 'END ' prepended to the directive name.

FOREACH directive

  <% FOREACH <iterator> [IN] <name> <methodchain> %>
  <% FOREACH <iterator> [IN] <name> %>
  <% FOREACH <iterator> [IN] DEREF <name> <methodchain> %>
  <% FOREACH <iterator> [IN] DEREF <name> %>
  <% FOREACH PAIR <iterator> [IN] <name> %>
  <% FOREACH PAIR <iterator> [IN] <name> SORTED BY_KEY %>
  <% FOREACH PAIR <iterator> [IN] <name> SORTED BY_VALUE %>
  <% FOREACH PAIR <iterator> [IN] <name> SORT [WITH] <codeblock> %>
  <% FOREACH PAIR <iterator> [IN] <name> <methodchain> %>
  <% FOREACH PAIR <iterator> [IN] <name> <methodchain> SORTED BY_KEY %>
  <% FOREACH PAIR <iterator> [IN] <name> <methodchain> SORTED BY_VALUE %>
  <% FOREACH PAIR <iterator> [IN] <name> <methodchain> SORT [WITH] <codeblock> %>
  <% FOREACH <name> %>

The FOREACH directive is an "iterator" directive for inserting a bit of content once for each item of a list.

The first form calls the specified "methodchain" on the "name"d data, loops over each element of the return value, and inserts the contents contained within the opening and closing tags once for each iteration with the "iterator" set to the current item. The 'IN' is just syntactic sugar, and may be omitted.

The second form does the same thing, but the "name"d parameter is assumed to be the list of content to iterate over instead of data on which to apply a "methodchain".

The third and fourth forms do the same thing as the first and second form, but cause the "name"d data to be dereferenced first. This is sometimes useful with nested FOREACH directives, where the outer loop may be iterating over an array of arrayrefs, for example.

The fifth through twelfth forms are hash "iterator"s. They expect a hash or hashref as the value of "name", or as the return value of the specified "methodchain" called on the "name"d object. It iterates over each key/value pair, setting "iterator" to a hashref with key and value pairs. The forms that include SORT or SORTED (either may be used interchangeably), sort by the given criteria; BY_KEY causes the iteration to be sorted (stringwise) by each pair's key element; BY_VALUE does the same for each pair's value element. The forms that specify a "codeblock" act like the "codeblock" of a "SORT"

The fifth form iterates over the "name"d list, using the "name" as the iterator inside each loop.

Inside the contents of a FOREACH directive, there is a defined variable '$ITERATION' which can be used for counting the number of iterations that have been executed.

The 'IN' in the first four forms is syntactic sugar, and may be omitted.

Examples:

In the template:

  <B>Team batting averages:</B>
  <TABLE>
  <TR>
          <TH>Team Name</TH>
          <TH>Batting Average</TH>
  </TR>
  
  <% FOREACH team IN league getTeams %>
  <TR>
          <TD><% METHODCALL team name %></TD>
          <TD><% METHODCALL team getBattingAverage %></TD>
  </TR>
  <% END FOREACH %>
  
  </TABLE>
  
  <H2>The following links are related to this topic:</H2>
  <% FOREACH link %>
  <P><A href="<% METHOD link %>"><% METHOD link %></A></P>
  <% /FOREACH %>

In the program:

  my $league = lookup League 15;
  $template->league( $league );
  
  my @links = qw{http://www.netscape.com/ http://www.leaguelink.com/ http://www.google.com/
                 http://slashdot.org/ http://www.linux.com/};
  $template->links( @links );

Assuming the league had three teams, the rendered output might look like:

  <B>Team batting averages:</B>
  <TABLE>
  <TR>
          <TH>Team Name</TH>
          <TH>Batting Average</TH>
  </TR>
  
  <% FOREACH team IN league getTeams %>
  <TR>
          <TD>Argyle Argonauts</TD>
          <TD>.175</TD>
  </TR>
  <TR>
          <TD>Rawndee Redhawks</TD>
          <TD>.333</TD>
  </TR>
  <TR>
          <TD>Billings Bobcats</TD>
          <TD>.285</TD>
  </TR>
  <% END FOREACH %>
  
  </TABLE>
  
  <H2>The following links are related to this topic:</H2>
  <P><A href="http://www.netscape.com/">http://www.netscape.com/</A></P>
  <P><A href="http://www.leaguelink.com/">http://www.leaguelink.com/</A></P>
  <P><A href="http://www.google.com/">http://www.google.com/</A></P>
  <P><A href="http://slashdot.org/">http://slashdot.org/</A></P>
  <P><A href="http://www.linux.com/">http://www.linux.com/</A></P>

An example of hash iteration:

  <SELECT name="team">
  <% FOREACH PAIR team IN teams %>
  <% IF team value %>
    <OPTION value="<% METHODCALL team key %>" selected><% METHODCALL team key %></OPTION>
  <% ELSE %>
    <OPTION value="<% METHODCALL team key %>"><% METHODCALL team key %></OPTION>
  <% END IF %>
  </SELECT>

The same iteration, but sorted by key:

  <SELECT name="team">
  <% FOREACH PAIR team IN teams SORTED BY_KEY %>
  <% IF team value %>
    <OPTION value="<% METHODCALL team key %>" selected><% METHODCALL team key %></OPTION>
  <% ELSE %>
    <OPTION value="<% METHODCALL team key %>"><% METHODCALL team key %></OPTION>
  <% END IF %>
  </SELECT>

JOIN directive

  <% JOIN <iterator> [IN] <name> <methodchain> [WITH] <quotedArgument> %>
  <% JOIN <iterator> [IN] <name> [WITH] <quotedArgument> %>
  <% JOIN <name> [WITH] <quotedArgument> %>

The JOIN directive acts like a FOREACH "iterator" that joins the rendered output of each of its loops together with the string specified by the "quotedArgument".

The operation of the join directive is otherwise the same as that for the FOREACH directive.

The words in brackets are syntactic sugar, and may be omitted.

Examples:

In the template:

  <% JOIN team IN league getTeams WITH q{, } %>
  <A href="http://leaguelink.com/homepages/<% METHOD team url %>"><% METHOD team name %></A>
  <% END JOIN %>

Might render something like this:

  <A href="http://leaguelink.com/homepages/1024">Bruins</A>, 
  <A href="http://leaguelink.com/homepages/768">Argonauts</A>,
  <A href="http://leaguelink.com/homepages/512">Redhawks</A>,
  <A href="http://leaguelink.com/homepages/256">Bobcats</A>

SORT directive

  <% SORT <iterator> [IN] <name> <methodchain> [WITH] <codeblock> %>
  <% SORT <iterator> [IN] <name> [WITH] <codeblock> %>
  <% SORT <name> [WITH] <codeblock> %>

The SORT directive is used to sort a content array, just as in Perl's sort function.

The first form calls the specified "methodchain" on the "name"d object and uses the "codeblock" to sort the list. The two elements to be compared are passed as the first two arguments, or can be accessed as in Perl's sort with the variables $a and $b. A return value of less than zero indicates that the first argument should be sorted before the second, a return value of 0 indicates that the two items are equal, and a return value of greater than zero indicates the second item should be sorted before the first. Once sorted, the array of values are assigned to the temporary "iterator", and the contents between the opening and closing SORT tags is inserted once into the rendered output.

The second form sorts in the same manner, but without a "methodchain" call on the "name"d parameter.

The third form substitutes the sorted list for the specified "name" inside the contained content instead of using an "iterator".

The words in brackets are syntactic sugar, and may be omitted.

Examples:

  <% SORT artistNames WITH { $a cmp $b } %>
  <% SORT album IN collection albums WITH { $a->title cmp $b->title } %>

MAP directive

  <% MAP <iterator> [IN] <name> <methodchain> [WITH] <codeblock> %>
  <% MAP <name> [WITH] <codeblock> %>

The MAP directive is used to apply some transform function to each element of an array, just as in Perl's map function.

The first form calls the specified "methodchain" on the "name"d object and executes the "codeblock" for each element. It assigns the array of return values of the "codeblock" calls to the temporary "iterator", and then inserts the contents contained between the opening and closing tags once.

The second form transforms the "name"d content with the specified "codeblock" and temporarily substitutes the transformed array for the original in the context of its beginning and end tags.

The words in brackets are syntactic sugar, and may be omitted.

Examples:

In the template:

  <!-- A Schwartzian Transform to sort players by first name -->
  <% MAP players {[ $_[0], $_[0]->name ]} %>
  <% SORT players { $[0]->[1] cmp $_[1]->[1] } %>
          <% MAP players { $_->[0] } %>
          <% FOREACH player IN players %>
          <% END MAP %>
  <% END SORT %>
  <% END MAP %>

GREP directive

  <% GREP <iterator> [IN] <name> <methodchain> [WITH] <codeblock> %>
  <% GREP <name> [WITH] <codeblock> %>

The GREP directive is used to modify a content array using "codeblock" as a filter function.

The first form calls the specified "methodchain" on the "name"d object and executes the "codeblock" for each element. If the "codeblock" returns a true value, the value is retained and is added to the contents for the block. If it returns a false value, the item is omitted from the contents. Each retained item is added to the temporary "iterator" array, and the contents of the tag are inserted once.

The second form filters the "name"d content with the specified "codeblock" and temporarily substitutes the filtered array for the original in the context of its beginning and end tags.

Examples:

In the template:

  <!-- Eliminate teams who haven't registered from the list -->
  <P>Registered teams:</P>
  <% GREP teams IN league getTeams WITH { $_[0]->isRegistered } %>
  <% FOREACH team IN teams %><% METHODCALL team name %><BR><% END FOREACH %>
  <% END GREP %>

COMMENT directive

  <% COMMENT %>

The COMMENT directive is used for inserting content into the template which do not affect the template object at all. Comments are stripped during preprocessing, so can be used to insert comments which do not show up in the rendered output, or to temporarily remove a section of template content from the object.

Examples:

In the template:

  <% COMMENT %>
    Template RCSID: $Id: Templar.pod,v 1.18 2003/01/15 21:20:19 deveiant Exp $
  <% /COMMENT %>
  
  <P>Something</P>

Would render as:

  <P>Something</P>

MAXLENGTH directive

  <% MAXLENGTH <object> <methodchain> %>
  <% MAXLENGTH <integer> %>
  <% MAXLENGTH <name> %>
  <% MAXLENGTH <codeblock> %>
  <% MAXLENGTH <variable> %>

The MAXLENGTH directive limits the character length of the rendered contents to the value specified, including spaces and newlines. The value may be specified in one of five ways: the result of a "methodchain", a literal integer, the value passed to a method call, the result of a code block, or the value of a specified "variable".

Examples:

In the template:

  <TD><% MAXLENGTH maxCellWidth %><% METHOD orgName %><% END MAXLENGTH %></TD>

In the program:

  $template->orgName( 'Crimson Permanent Assurance' );
  $template->maxCellWidth( 10 );

Would render as:

  <TD>Crimson Pe</TD>

Conditional Tags

Conditional tags are groups of directives which contain optional content delimited, as with container directives, with the opening tag + attributes and a closing tag. The closing tag of any conditional block is an <% END IF %> or <% /IF %> tag.

IF directive

  <% IF <name> %>
  <% IF <name> [MATCHES] <matchspec> %>
  <% IF <object> <methodchain> %>
  <% IF <object> <methodchain> [AMTCHES] <matchspec> %>
  <% IF <variable> %>
  <% IF <variable> [MATCHES] <matchspec> %>
  <% IF <codeblock> %>

The IF directive without a MATCHES clause evaluates the last-inserted content of the specified "name", the specified "methodchain" of the last-inserted "object", or the specified "codeblock" or "variable" in its attributes and includes the contained content if it evaluates to a true value.

With a MATCHES clause, the contained content is included if all of the content of the specified "name", the specified "methodchain" of the last-inserted "object", or the specified "codeblock" or "variable" match the "matchspec". If the "matchspec" is a regexp, each item must match it, if the "matchspec" is an array or a hash, each item must be equal (stringwise) to at least one of the items in the array or one of the keys of the hash.

The words in brackets are syntactic sugar, and may be omitted.

ELSE directive

  <% ELSE %>

The content contained after the ELSE directive is executed if none of the conditional clauses before it have been true.

ELSIF directive

  <% ELSIF <name> %>
  <% ELSIF <name> [MATCHES] <matchspec> %>
  <% ELSIF <object> <methodchain> %>
  <% ELSIF <object> <methodchain> [AMTCHES] <matchspec> %>
  <% ELSIF <variable> %>
  <% ELSIF <variable> [MATCHES] <matchspec> %>
  <% ELSIF <codeblock> %>

The content contained after the ELSIF directive is executed if none of the conditional clauses before it have been true and the condition matches using the same rules as the IF directive.

The words in brackets are syntactic sugar, and may be omitted.

Examples:

In the template:

  <% IF shopName %><H1>Welcome to <% METHOD shopName %></H1><% END IF %>
  
  <P>We are currently <% IF {
                my $hour = (localtime)[2]; $hour < 19 && $hour > 6 } %>
        open
  <% ELSIF { (localtime)[6] == 6 && (localtime)[2] < 21 && (localtime)[2] > 6 } %>
    open
  <% ELSE %>
        closed
  <% END IF %>.</P>

Between 7 AM and 7 PM, or between 7 AM and 9 PM on Saturday would render as:

  <H1>Welcome to Binghjii's Bazaar of Wonder</H1>
  
  <P>We are currently open.</P>

and any other time would render as:

  <H1>Welcome to Binghjii's Bazaar of Wonder</H1>
  
  <P>We are currently closed.</P>

A more complex example:

  <% IF request header_in('host') matches /^dev/ %>
         <P align="center"><STRONG>This is the development server.</STRONG></P>
  <% ELSIF request connection.remote_host matches /internal\.net/ %>
    <P align="center"><A href="viewRequest">View this request</A></P>
  <% END IF %>

FUNCTIONS

Protected Functions

_buildParseError( \@errors )

Given an array of parser errors, return a formatted error message composed of all of them.

METHODS

addContentNode( $nodeName )

Add a content container for the node specified if it doesn't already exist. Returns a true value on success, and throws an exception on any error.

addInheritedNode( $nodeName )

Add an inherited content container for the node specified if it doesn't already exist. Returns a true value on success, and throws an exception on any error.

addNodeContent( $nodeName, @contents )

Add elements to the contents of the node specified. Returns the number of elements after adding the ones given. Throws an exception on any error.

cacheSource( $boolean )

Get/set the attribute which turns source caching on or off. If this is set to a true value, the template source from any file will be cached after loading it the first time, and will be reused the next time the template is requested. If the file the source is from changes, the caching mechanism will notice and abandon the cached source. (Translucent method)

cacheTrees( $boolean )

Get/set the attribute which turns syntax tree caching on or off. If this is set to a true value, the template object's syntax tree will be reused the next time it is loaded, skipping the parse phase altogether. (Translucent method)

clear( undef )

Clear the content from this template.

commentClose( $string )

Get/set the comment close string used when rendering comments into the output. Defaults to ' -->', which is the HTML comment close string.

commentOpen( $string )

Get/set the comment open string used when rendering comments into the output. Defaults to '<!-- ', which is the HTML comment open string. (Translucent method)

defines( \%variableDefinitions )

Get/set the template variables associated with the template. The defines hash is a hash of variable name => variable value pairs. These variables will be visible to any code evaluated in the template's scope. If a variable does not have a perl-style variable prefix, it is assumed to be a scalar value. (Translucent method)

deleteDefines( @variableNames )

Remove and return the specified key-value pairs from the template definitions hash. (Translucent method)

deleteMetafields( @fieldNames )

Remove and return the named values from the object's metafields hash. (Translucent method)

errorOutput( $outputConfig )

Get/set the errorOutput attribute. This attribute controls where the output from errors generated in the template object end up. Setting it to 'stderr' (the default) causes errors to be output on STDERR. Setting it to 'inline' renders the errors as comments (see commentOpen() and commentClose()) into the output of the template at the place where they occur. If errorOutput() is 'tailed', the errors will be rendered as more-detailed error stacktraces at the end of the template's output. A value of 'both' means to use both inline and tailed output types. Setting errorOutput() to 'ignore' will cause errors to be ignored silently. Any other value is treated as the filename of some sort of log, and errors are piped to it as they occur. Setting this to a filename which cannot be opened results in a fatal exception being thrown. (Translucent method)

filterSyntaxTree( \@nodes, $phaseName )

Filter the given nodes by calling the appropriate method for each node as indicated by the phase name. Returns the filtered nodes, and throws an exception on any error.

getContentHash( undef )

Returns a hash of content that is the result of merging this template's content and any content inherited from containing templates

getDefines( @defineNames )

Get the evaluated values of the defines specified. Returns the values if called in list context, and the number of defines returned in scalar context. Throw an exception on any error.

getMetafields( @fieldNames )

Return the values of the specified metadata fields. (Translucent method)

getNodeContent( $nodeName )

Get the content given by the user for the specified node, if any. Returns the list of content, or throws an exception on any error.

includePath( \@newPath )

Get/set the list of directories to check when searching for template files. The path is a reference to an array of directories. (Translucent method)

load( $sourceFileName | \@sourceArray )

Load template data from a file or arrayref, parse it, and create the object's structure by examining the resulting syntax tree. Returns a true value if all goes well, or throws an exception on any error.

maxIncludeDepth( $depth )

Get/set the maximum include depth. If the number of recursive includes for a given template exceeds this value, an exception is generated and the include will fail. The default value is 15. (Translucent method)

metafields( \%newFields )

Get/set the hash of metadata associated with the template. (Translucent method)

missingMethodIsFatal( $boolean )

Get/set the flag that controls what happens when a method is called on the template which hasn't been defined in the template file. If this is set to a false value (which is the default), the call won't do anything. If it is set to a true value, a call to an undefined method will throw an exception.

parse( $sourcePath | \@sourceArray )

Given an absolute path to a template, or an arrayref of template content, create an initial syntax tree and preprocess it to create the object attributes necessary to interact with the template. Returns a processed syntax tree.

popIncludePath( undef )

Remove and return the last element of the include path. (Translucent method)

popQueries( undef )

Remove and return the last element of the query list. (Translucent method)

popSyntaxTree( undef )

Remove and return the last element of the syntax tree. (Translucent method)

preprocessCOMMENT( $node )

Process the given 'COMMENT' node in the parse phase. Throws an exception on any error.

preprocessDEFINE( $node )

Process the given 'DEFINE' node in the parse phase. Throws an exception on any error.

preprocessDELAYED( $node )

Process the given 'DELAYED' node in the parse phase. The DELAYED tag just delays the processing of the nodes it contains until the next phase, so this method just returns the DELAYED node's subnodes. Throws an exception on any error.

preprocessDUMP( $node )

Process the given 'DUMP' node in the parse phase. Throws an exception on any error.

preprocessELSE( $node )

Process the given 'ELSE' node in the parse phase. The else node doesn't require any preprocessing, so we just return it to its native habitat unharmed. 'Say, Terri. Look at that deadly poisonous ELSE directive: what a beautiful animal.'

preprocessELSIF( $node )

Process the given 'ELSIF' node in the parse phase.

preprocessENV( $node )

Process the given 'ENV' node in the parse phase. Throws an exception on any error.

preprocessEVAL( $node )

Process the given 'EVAL' node in the parse phase. Returns the result of evaluating the codeblock or variable specified in the node. Throws an exception on any error.

preprocessFOREACH( $node )

Process the given 'FOREACH' node in the parse phase. Throws an exception on any error.

preprocessGREP( $node )

Process the given 'GREP' node in the parse phase. Throws an exception on any error.

preprocessIF( $node )

Process the given 'IF' node in the parse phase. Throws an exception on any error.

preprocessINCLUDE( $node )

Process the given 'INCLUDE' node in the parse phase. Throws an exception on any error.

preprocessINHERIT( $node )

Process the given 'INHERIT' node in the parse phase. Throws an exception on any error.

preprocessJOIN( $node )

Process the given 'JOIN' node in the parse phase. Throws an exception on any error.

preprocessMAP( $node )

Process the given 'MAP' node in the parse phase. Throws an exception on any error.

preprocessMAXLENGTH( $node )

Process the given 'MAXLENGTH' node in the parse phase. Just returns the node. Throws an exception on any error.

preprocessMETA( $node )

Process the given 'META' node in the parse phase. Throws an exception on any error.

preprocessMETHOD( $node )

Process the given 'METHOD' node in the parse phase. Throws an exception on any error.

preprocessMETHODCALL( $node )

Process the given 'METHODCALL' node in the parse phase. Returns the (possibly modified?) node if it should be kept in the syntax tree, and returns the undefined value otherwise. Throws an exception on any error.

preprocessQUERY( $node )

Process the given 'QUERY' node in the parse phase. Throws an exception on any error.

preprocessSORT( $node )

Process the given 'SORT' node in the parse phase. Throws an exception on any error.

preprocessSTOP( $node )

Process the given 'STOP' node in the parse phase. Since an end node is only meaningful in the render phase, this method just returns the specified node. Throws an exception on any error.

propagateContent( \%contentHash )

Add the key/value pairs from the given hash to this template's content if the key has been specified as one that should be inherited. Returns the number of content pairs propagated, or throws an exception on any error.

pushIncludePath( @directories )

Add the specified directories on to the end of the include path. Returns the total number of paths after adding. (Translucent method)

pushQueries( @nodes=Text::Templar::QUERY )

Add the specified nodes on to the end of the query list. Returns the total number of nodes after adding. (Translucent method)

pushSyntaxTree( @nodes=Text::Templar::node )

Add the specified nodes on to the end of the syntax tree. Returns the total number of nodes after adding. (Translucent method)

queries( \@queryNodes=Text::Templar::QUERY )

Get/set the array of query nodes for this template. Query nodes are generated for QUERY directives in the template. See for more about how to use QUERY nodes. (Translucent method)

render( undef )

Returns the syntax tree rendered into the final output form.

renderCOMMENT( $node )

Process the given 'COMMENT' node in the render phase. Throws an exception on any error.

renderDEFINE( $node )

Process the given 'DEFINE' node in the render phase. Throws an exception on any error.

renderDELAYED( $node )

Process the given 'DELAYED' node in the render phase. Since the DELAY is supposed to postpone processing until the render phase, encountering a DELAY node here is an error, so all this method does is generate an exception with a message to that effect.

renderDUMP( $node )

Process the given 'DUMP' node in the render phase. Returns the content that should be placed in the position occupied by the DUMP tag. Throws an exception on any error.

renderELSE( $node )

Process the given 'ELSE' node in the parse phase. Rendering an ELSE outside of an enclosing IF is an error, so this method just generates an exception with a message to that effect.

renderELSIF( $node )

Process the given 'ELSIF' node in the parse phase. Rendering an ELSIF outside of an enclosing IF is an error, so this method just generates an exception with a message to that effect.

renderENV( $node )

Process the given 'ENV' node in the render phase. Throws an exception on any error.

renderEVAL( $node )

Process the given 'EVAL' node in the render phase. Returns the result of evaluating the codeblock or variable specified in the node. Throws an exception on any error.

renderFOREACH( $node )

Process the given 'FOREACH' node in the render phase. Throws an exception on any error.

renderGREP( $node )

Process the given 'GREP' node in the render phase. Throws an exception on any error.

renderIF( $node )

Process the given 'IF' node in the render phase. Throws an exception on any error.

renderINCLUDE( $node )

Process the given 'INCLUDE' node in the render phase. Throws an exception on any error.

renderINHERIT( $node )

Process the given 'INHERIT' node in the render phase. Since inheritance happens before the parse phase, this generates an exception.

renderJOIN( $node )

Process the given 'JOIN' node in the render phase. Throws an exception on any error.

renderMAP( $node )

Process the given 'MAP' node in the render phase. Throws an exception on any error.

renderMAXLENGTH( $node )

Process the given 'MAXLENGTH' node in the render phase. Throws an exception on any error.

renderMETA( $node )

Process the given 'META' node in the render phase. Since metafields are really only useful before the render phase, this method just returns the empty list. Throws an exception on any error.

renderMETHOD( $node )

Process the given 'METHOD' node in the render phase. Returns the content that should be placed in the position occupied by the METHOD tag. Throws an exception on any error.

renderMETHODCALL( $node )

Process the given 'METHODCALL' node in the render phase. Returns the content that should be placed in the position occupied by the METHODCALL tag. Throws an exception on any error.

renderQUERY( $node )

Process the given 'QUERY' node in the render phase. Since queries are really only useful before the render phase, this method just returns the empty list. Throws an exception on any error.

renderSORT( $node )

Process the given 'SORT' node in the render phase. Throws an exception on any error.

renderSTOP( $node )

Process the given 'STOP' node in the render phase. Since an end node indicates the end of the syntax tree while in the parse phase, we shouldn't ever reach this method, and all this method does is throw an exception with a message to that effect.

setDefines( %variablePairs )

Set the value of the specified variable pairs in the template definitions hash (Translucent method)

setMetafields( %fieldPairs )

Set the value of the metadata field specified to the specified value. (Translucent method)

setNodeContent( $nodeName, @contents )

Set the contents of the node specified to the given contents. Returns the number of elements after setting. Throws an exception on any error.

shiftIncludePath( undef )

Remove and return the first element of the template include path. (Translucent method)

shiftQueries( undef )

Remove and return the first element of the query list. (Translucent method)

shiftSyntaxTree( undef )

Remove and return the first element of the syntax tree. (Translucent method)

sliceIncludePath( @indexes )

Returns the directories specified by the indexes from the include path without removing them from the path. (Translucent method)

sliceQueries( @indexes )

Return the query list nodes specified by the indexes from the query list without removing them. (Translucent method)

sliceSyntaxTree( @indexes )

Return the syntax tree nodes specified by the indexes from the syntax tree without removing them. (Translucent method)

sourceName( $pathname )

Get/set the path name of the source file the template was/should be loaded from. Note that changing this value after loading a template will not have any effect on the actual template content. Setting this value before calling load() will cause the template source to be loaded from the specified file. (Translucent method)

spliceIncludePath( $offset, $length, @newDirs )

Removes the directories specified by offset and length from the include path, replacing them with the new directories, if specified. This method works similarly to Perl's splice(). (Translucent method)

spliceQueries( $offset, $length, @newnodes=Text::Templar::QUERY )

Removes the nodes specified by offset and length from the query list, replacing them with the new nodes, if specified. This method works similarly to Perl's splice(). (Translucent method)

spliceSyntaxTree( $offset, $length, @newnodes=Text::Templar::node )

Removes the nodes specified by offset and length from the syntax tree, replacing them with the new nodes, if specified. This method works similarly to Perl's splice(). (Translucent method)

syntaxTree( \@syntaxTree=Text::Templar::node )

Get/set the syntaxTree that the object uses in rendering. By getting/setting this attribute, you can prune elements out of the rendered content. (Translucent method)

undefinedValue( $newValue )

Get/set the value that is inserted when templar encounters an undefined value. Defaults to the empty string.

unshiftIncludePath( @directories )

Add the specified directories onto the beginning of the include path. Returns the number of directories in the tree after adding. (Translucent method)

unshiftQueries( @queries=Text::Templar::QUERY )

Add the specified nodes onto the top of the query list. Returns the number of nodes in the list after adding. (Translucent method)

unshiftSyntaxTree( @args )

Add the specified nodes onto the top of the syntax tree. Returns the number of nodes in the tree after adding. (Translucent method)

Constructor Methods

new( [ $sourceFileName | \@sourceArray ][, %configHash] )

Constructs and returns a new template object. If the optional sourceFileName or sourceArray argument is specified, the template content is parsed. If the optional configHash contains any key-value pairs, the per-object attributes specified are set. Throws an exception on any error.

Private Methods

__closureCount( @args )

Get/set the number of closures that have been constructed. This is used for constructing a unique namespace for each closure. (Translucent method)

Private Readonly Methods

__RCSID( @args )

Get the RCS id string for Text::Templar.

__VERSION( @args )

Get the version string for Text::Templar.

Private Static Methods

__ErroutIsInitialized( @args )

Get/set the flag that denotes that the error output filehandle has been initialized. (Translucent method)

__InitErrorOutput( undef )

Nasty kluge to assure that error output is initialized in the case that it's not explicitly configured either before or during the first constructor call.

Protected Methods

_buildClosure( $code )

Builds a returns a closure with the code specified.

_buildComment( $message )

Builds and returns a comment in the manner defined by the object's commentOpen and commentClose attributes. Throws an exception on any error.

_buildHashIteratedContent( $node, @content )

Attempt to build a list of hashrefs with key and value pairs for hash iterators.

_buildIteratedContent( $node )

Build a list of content that will be iterated over out of the given node.

_depth( @args )

Get/set the current include depth. (Translucent method)

_deref( $value )

Handle dereference of a target value for METHODCALL DEREF <name>, FOREACH DEREF <name>, etc.

_errorOutputFh( @args )

Get/set the output filehandle that should be used for printing exceptions as they occur, if any. See errorOutput() for more info. (Translucent method)

_evaluateCondition( $node )

Evaluate the "matchspec" associated with the given node with the node's content, returning '1' if the condition is true, and the empty list if it is not.

_findFile( $filename )

Given a possibly relative filename, attempt to figure out an absolute one and return it.

_getEvaluatedValue( $code )

Evaluates the specified code inside a private environment and returns the result. Throws an exception if the code to be evaluated produces an error, and on any other error.

_getFileHandle( $filename )

Opens and returns an IO object opened to the file specified.

_getRenderedEvaluatedValue( $code )

Evaluates the specified code inside a private environment, renders it, and returns the result. Handles exceptions generated by the specified code by rendering them according to the errorOutput configuration. Throws an exception on any error.

_getRenderedValues( @values )

Render each value into a suitable string for output. Handles simple scalar values, array references, hash references, templar objects, exceptions, and other objects of a class that defines a stringify(), as_string, asString, or render method. Returns an array of rendered values if called in list context, or the rendered values joined together in a a single string if called in scalar context. Throws an exception on any error.

_getStderrHandle( undef )

Opens and returns an IO object opened write-only on STDERR.

_handleException( $exception=Text::Templar::Exception, $mode )

Take action on an exception that occurs in a template. The action taken is configured via the errorOutput() configuration method. Returns a handled version of the exception (either the exception object or the empty list if the exception object should be ignored at the current point of execution).

_loadFile( $path )

Load the file specified by path and return its contents as an array (list context) or arrayref (scalar context). Throws an exception on any error.

_parseArray( \@contentArray )

Parse an array reference of template source, returning the resultant syntax tree. Throws an exception on any error.

_parseFile( $filename )

Load and parse a file, returning the resultant syntax tree. Throws an exception on any error.

_parseTemplateSource( \@source, $sourceName )

Parse the given source and return a syntax tree

_parsed( @args )

Get/set the flag that designates the template object as parsed. (Translucent method)

_popTailedErrors( undef )

Remove and return the last exception from the tailed exception list. (Translucent method)

_pushTailedErrors( @exceptions=Text::Templar::Exception )

Add the specified exceptions on to the end of the tailed error list. Returns the total number of exceptions after adding. (Translucent method)

_shiftTailedErrors( undef )

Remove and return the first element of the tailed exception list. (Translucent method)

_sliceTailedErrors( @indexes )

Return the query list exceptions specified by the indexes from the tailed exceptions list without removing them. (Translucent method)

_spliceTailedErrors( $offset, $length, @exceptions=Text::Templar::Exception )

Removes the exceptions specified by offset and length from the tailed exceptions list, replacing them with the new exceptions, if specified. This method works similarly to Perl's splice(). (Translucent method)

_tailedErrors( \@exceptions=Text::Templar::Exception )

Get/set the array of exception objects to be appended to the end of the rendered output. (Translucent method)

_traverseMethodChain( $object, \@methodChain=Text::Templar::method )

Traverse each element in a "methodchain", calling a method or fetching a value from a reference for each one.

_unshiftTailedErrors( @exceptions=Text::Templar::Exception )

Add the specified exceptions onto the top of the tailed exception list. Returns the number of exceptions in the list after adding. (Translucent method)

Protected Class Methods

_GetParser( undef )

Get the parser object for parsing templar templates. Constructs a new parser if necessary. Return the parser object, and throws an exception on any error.

Protected Static Methods

_Parser( $newParser=Text::Templar::Parser )

Get/set the parser object used to generate syntax trees. (Translucent method)

Proxy Methods

AUTOLOAD( @args )

Handles method calls for the phases we don't have explicit handlers for, and client calls to directive methods.