Squirrel::Template - simple templating system
use Squirrel::Template; my $templater = Squirrel::Template->new(template_dir => $some_dir); my $result = $templater->show_page($base, $filename, \%acts, undef, $alt); my $result = $templater->replace_template($text, \%acts, undef, $display_name); my @errors = $templater->errors; my @args = $templater->get_parms($args, \%acts, $keep_unknown)
BSE's template engine.
new()
$templater = Squirrel::Template->new(%opts);
Create a new templating object.
Possible options are:
If a tag isn't found in the actions then it is replaced with an error message rather than being left in place.
Used to find wrapper and include templates. This can be either a scalar, or a reference to an array of locations to search for the wrapper.
If this is true then the template engine works in unicode internally.
Template files are read into memory using the charecter set specified
by charset
.
Ignored unless utf8
is true. Specifies the character encoding used
by template files. Defaults to "utf-8"
.
A BSE::Cache object to use for caching compiled templates. Note that templates are currently only cached by filename.
show_page()
$text = $templ->show_page($base, $template, \%acts, $iter)
Performs template replacement on the text from the file $template in directory $base.
replace_template()
$text = $templ->replace_template($intext, \%acts, $iter, $name)
Performs template replacement on $intext
using the tags in
%acts
. $iter
is accepted only for backward compatibility and it
no longer used. Errors are reported as if $intext
had been read
from a file called $name
.
errors()
Return errors from the last show_page()
or replace_template()
.
This can include:
tokenization errors - an unknown token was found in the template
parsing errors - mismatched if/eif, etc
processing errors - die from tag handlers, etc
file errors - missing include or wrap files, and recursion from those.
Returns a list of error tokens, each of which is an array reference with:
The text "error".
An template text that caused the error. This may be blank some cases.
The line number.
The filename. If you called replace_template()
this will be the
$name
supplied to replace_template()
.
An error message.
get_parms()
my @args = get_parms($args, $acts, $keep_unknown)
Does simple and stupid processing of $args
parsing it for a list of
arguments.
Possible arguments that are parsed are:
[
tagname arguments ]
- return the results of calling the
specified tag. Only a limited amount of nesting is parsed.
"
text"
- quoted text. No escaping is done on the text.
text - plain text not containing any [
or ]
.
Returns a list of parsed arguments.
If tagname in $args
isn't defined, dies with an ENOIMPL\n
message.
This syntax provides mechanisms similar to those provided by Template Toolkit or Mason, while retaining the older syntax below.
See the Squirrel::Template::Expr manpage for information on expression syntax.
<:= expression :>
<:= expression | format :>
Replaced with the result of evaluating expression and formatted by the formatter specified by format.
<:% expression ; ... :>
A list of expressions, evaluated in order. The expression results are discarded.
<:.if expression :>
content
<:.elsif expression :>
content
<:.else :>
content
<:.end:>
Evaluate each expression in turn and return the matching content.
.elsif
clauses can be repeated as desired. The .else
clause is
optional. The .end
token can be .end if
.
<:.set variable = expression :>
Set the specified variable to the value of the expression.
<:.for variable-name in expression :> content <:.end:>
Loop over the contents of the specified list.
Also sets the loop
variable to a hash containing useful
information, see The loop variable below.
If you're calling a perl method on an object directly, you will typically want to surround the call with [] to process the call in list content:
<:.for i in [ article.children ]:>
The .end
token can also be .end for
.
<:.define name :> content <:.end:>
Define a macro called name with the specified content. The .end
token can be .end define
.
eg.
<:.define somename:> some content <:.end define:>
<:.call name-expression :>
<:.call name-expression, variable-name-expression:expression, ...:>
Call the named macro, or if there is no such macro, the named template file setting specified variables to the given values.
eg.
<:# call foo, setting bar to "hello" :> <:.call "foo", "bar":"hello":>
While variable-name-expression is currently an expression, it should be limited to a quoted identifier.
Changes to any top level variables are scoped to inside the called macro or file.
<:.iterateover callback :> content <:.end :>
<:.iterateover callback, arguments... :> content <:.end :>
Calls back into the target supplied callback to set variables which can then be replaced on each iteration.
Each .for
loop defines a loop
variable. If you have nested
loops, you can define an alias to the variable, eg:
<:.for i in outer:> <:.set outerloop = loop:> <:.for j in inner:> <:= outerloop.count :> <:.end:> <:.end:>
The following values are set in loop
first, last - the first and last values in the list. These may be undef if the list is empty.
size - the number of elements in the list
is_last, is_first - true if the current element is the last or first element respectively.
count - the index of the current element, starting from 1.
index - the index of the current element, starting from 0.
parity - "odd" or "even". The first element is "even".
odd, even - true if the parity is "odd" or "even", respectively.
prev, next - the previous or next element respectively, if any.
list - the list argument to .for
.
This is the older template syntax that is retained for compatibility.
In general, if the tag has no definition the original tag directive is
left in place. If the tag has sub-components (like if
or
iterate
) tag replacement is done on the sub-components.
Template directives start with <:
, if a -
is found
immediately after the :
any whitespace before the tag is also
replaced.
Template directives end with :>
, if a -
if found immediately
before the :
any whitespace after the tag is also replaced.
eg.
<: tag foo -:> sample <:- tag bar :>
is treated the same as:
<: tag foo :>sample<: tag bar :>
Directives available in templates:
<: name args :>
Replaced with the value of the tag. See Simple tag evaluation.
<: iterator begin name args :> text <: iterator separator name :> separator <: iterator end name :>
<: iterator begin name args :> text <: iterator end name :>
Replaced with repeated templating of text separated by separator.
<: ifName args :> true <: or :> false <: eif :>
<: ifName args :> true <: eif :>
<: if Name args :> true <: or Name :> false <: eif Name :>
<: if Name args :> true <: eif Name :>
Emits true if the tag evaluates to a true value, otherwise the false text. See Conditional tag evaluation.
Note that only the if
now requires the Name
. The or
and
eif
may include the name, but it is not required. If the Name
is supplied it must match the if
Name
or an error will be
returned.
<: if!Name args :> false <: eif :>
<: if !Name args :> false <: eif Name :>
Emits false if the tag evaluates to a false value. See Conditional tag evaluation.
<: with begin name args :> replaced <: with end name :>
Calls $acts->{"with_name"}->($args, $replaced, "", \%acts,
$name, $templaer)
where $replaced
is the processed text and
inserts that.
<: # your comment :>
A comment, not included in the output.
<:switch:><:case Name optional-args :>content ... <:endswitch:>
Replaced with the first matching conditional where <:case Name
optional-args :>
is treated like an if
.
A case may also be <:case !Name :>
, in which the case
matches the same as an if !Name
.
A <:case default:>
is always true.
<: include filename options :>
Replaced with the content of the supplied filename.
If the file filename is not found, this results in an error being
inserted (and reported via errors()) unless options contains
optional
.
No more than 10 levels of include can be nested.
<: wrap templatename :> wrapped <:endwrap:>
<: wrap templatename name => value, ... :> wrapped <:endwrap>
The <:endwrap:>
is optional. A wrapper will be terminated by
end of file if not otherwise terminated.
Processes templatename as a template. Within that template <:
wrap here :>
will be replaced with wrapped.
The values specified by the name => value
are used to
populate the value of the built-in param tag.
Wrapping can be nested up to 10 levels.
<: wrap here :>
Returns the wrapped content within a wrapper template. Returns an error if not within a wrapper template.
Tag definitions in %acts
can be in any of five forms:
A simple scalar - the value of the scalar is returned.
A scalar reference - the referred to scalar is returned.
A code reference - the code reference is called as:
$code->($args, \%acts, $tagname, $templater)
An array reference starting with a code reference, followed by
arguments, eg [ \&tag_sometag, $foo, $bar ]
. This is called
as:
$code->($foo, $bar, \%acts, $tagname, $templater)
An array reference starting with a scalar, followed by an object or
class name, followed by arguments, eg [ method => $obj, $foo, $bar
]
. This is called as:
$obj->$method($foo, $bar, \%acts, $tagname, $templater)
A warning is produced if the tag returns an undef value.
Given a ifSomeName
, does Simple tag evaluation on the
first tag of ifSomeName
or someName
found.
Unlike simple tag evaluation this does not warn if the result is undef.
This uses two members of %acts
:
iterate_name_reset
- called to start iteration. Optional
but recommended.
iterate_name
- called until it returns false for each
iteration.
Either can be any of:
a code reference - called as:
$code->($args, \%acts, $name, $templater)
an array reference starting with a code reference:
$arrayref->[0]->(@{$arrayref}[1 .. $#$arrayref], \%acts, $name, $templater);
an array reference starting with a scalar:
$arrayref->[1]->$method(@{$arrayref}[2 .. $#$arrayref], \%acts, $name, $templater);
So far there's just one:
If the _format action is defined in your $acts then if a function tag has |text at the end of it then the function is evaluated, and the resulting text and the text after the | is passed to the format function.
Squirrel::Row(3p), Squirel::Table(3p)
Started as a quick hack from seeing the hacky template replacement done by an employer.
It grew.
Largely rewritten in 2012 to avoid processing the same string a few hundred times.