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

NAME

 HTML::Transmorgify::Metatags - Template language processor

SYNOPSIS

 use HTML::Transmorgify;

 my $magic = HTML::Transmorgify->new(xml_quoting => 1);

 $magic->mixin('HTML::Transmorgify::Metatags');

 my $output = $magic->process($input_text, { %options }, %variables);

 use HTML::Transmorgify::Metatags qw(%transformations);
 use HTML::Transmorgify::Metatags qw(@include_dirs);
 use HTML::Transmorgify::Metatags qw(%allowed_functions);

DESCRIPTION

HTML::Transmorgify::Metatags provices an HTML-esque template language for transforming HTML.

HTML::Transmorgify is a framework for compiling HTML transformations and HTML::Transmorgify::Metatags uses it to compile the template transformations. Applying the transformations is a two step process with a compile-time part and a run-time part. Compiled templates are cached so a second invocation of the same template will skip the compile-time part.

HTML::Transmorgify::Metatags does not provide an escape-to-perl mechenism for template writers. Instead template writers are considered to be only semi-trusted (by default they can embed javascript) and real programming is expected to be done either outside the template system or by creating add-on modules for the template system to use.

HTML::Transmorgify::Metatags directives look like regular HMTL tags. They are interpreted by HTML::Transmorgify and are not included in the final output stream.

MACROS

The <macro> tag is used to expand a variable or macro. The form of the call is:

 <macro VAR_NAME>
 <macro name=VAR_NAME>
 <macro name=VAR_NAME encode=ENCODING=>

Macro expansions can be done inside attribute values of other tags:

 <img alt="<macro alttag>">

Some macro values are evaluated at runtime. These might in turn use other macros. All named attributes to a <macro> are added as temporary macros while doing a lookup.

Defining Macro Values

Macro values can be set in the invocation of HTML::Transmorgify:

 my $output = $magic->process($input_text, { %options }, 
        alt_tag => 'my image',
        my_title => 'yea, we did it',
        an_array => [ 'foo', 'bar' ],
        a_hash => { foo => 'bar' },
        an_object => $object,
 );

If a macro name has periods in it, then variable is expected to be a complex object or structure. For example, if the variable name is an_array.1 then first an_array would be looked up. Assuming that what's found is a object, array, or hash, then 1 would be looked up in the result. With the values initialized in the previous example, the result would be bar.

When a variable refers to an object, if there are additional elements to the variable name, they will be looked up by using the lookup method. If there are no additional elements to refine the lookup, then the object is turned to text with the text method.

A virtual base clase that objects can inherit from is defined in HTML::Transmorgify::ObjectGlue.

Macros can also be defined with the <define> directive. All of these do the same thing:

 <define title>my new title</define>
 
 <define name="title">my new title</define>
 
 <define title value="my new title" />
  
 <define name="title" value="my new title" />

The <define> tag uses some attributes to control it's behavior:

eval

Normally, <define> values are evaluated at runtime. If you know that the value is never going to change, then you can use the eval attribute set to false to force the value to be evaluated and locked in at compile time. This can provide a performance boost. Setting eval=false can have bad consequences if the values change.

 <define fullname><macro firstname> <macro lastname></define>

Compile-time only happens once so if firstname and lastname are parameters that change from invocation to invocation, evaluating them should be deferred until runtime by using the eval="true" attribute.

name

The name of the Macro being defined.

value

The text of the new defintion.

trim

The trim attribute will eleminate some of the whitespace from within the new value:

start

Trims whitespace from the beginning of the definition

end

Trims whitespace from the end of the definition

all

Trims whitespace from both ends of all text blocks within the definition. The only things that are not text blocks are other tags that compile to something other than literal text. For example, another <define> tag.

All attribute values of the <define> tag become temporary overrides (local variables) for that define.

 <define firstname>John</define>
 <define middlename>Fredricks</define>
 <define lastname>Smith</define>
 <define name lastname="Jones" eval=1><macro firstname> <macro middlename> <macro lastname></define>
 <macro name middlename="Simon" lastname="Barney">

The output from this will be John Simon Johnes. The firstname is John because that is the only value it gets. The middle name is Simon because it is overridden in the <macro> invocation. The last name is Jones because the it is overriden twice: first in the macro invocation and then in the definition of the name <macro>.

Transformations

When a <macro> is expanded, the new value can be transformed. The syntax is

 <macro macro_name encode="ENCODING">

Where ENCODING is one of the following:

html

Substitute &lt; for < and &gt; for > and all similar HTMl entity transformations handled by HTML::Entities. This is the default transformation. Use

 encode="none"

if you do not want this.

uri / url

Encode for a URL: Substitute %20 for space and all the rest of the substitutions handled by URI::Escape.

comment

Throw away the value and return the empty string. XXX currently this still evaluates things within the comment, it's just the final result that is tossed. XXX add a <silent> or <empty> tag to supplant the current <comment> and have <comment> ignore its contents.

none

Pass the expanded value through unchanged.

Transformations can also be invoked on any section of input text using the >transform< tag.

 <transform html>Really sloppy stuff with <> and the like.</transform>

 <transform encode=url>http://my.url/with spaces in it</transform>

Additional transformations can be added by modifying the hash %HTML::Transmorgify::Metatags::transformations which is exported by request.

CONTROL FLOW

HTML::Transmorgify::Metatags also provides control flow directives: conditionals, loops, and include files.

<if> <elsif> <else>

There are two ways to write the conditional for an <if> tag:

 <if is_set="MACRO_NAME">

 <if expr="<macro age> < 18">

The is_set test is true if the macro variable MACRO_NAME is set to a non-empty string.

The expr test supports a syntax that closely matches the expresssion syntax supported by perl. It is not evaluated with perl's eval but rather the expression is parsed at compile time and evaluated at runtime using a grammer.

The grammer includes calling functions. Only the functions defined in %HTML::Transmorgify::Metatags::allowed_functions (exported on request) are allowed. Add more to that hash if you need them.

The pre-defined functions are:

abs()

absolute value

defined()

value is defined

min()

From List::Util

max()

From List::Util

The <if> block finishes with

 </if>

<elsif> and <else> are optional and do not have their own closing tags.

<foreach varname container(s) [assignments]>

The <foreach> tag provides looping.

The first parameter for <foreach> is the name of the macro that will change with each iteration. This can also be set with var=SOME_NAME.

All suceeding parameters that are of the form of just an attribute name (without an equals sign for an attribute value) will be treated as macros that will be expanded into lists (if they can be). The resulting values from these expansions is what will be looped over in the <foreach>.

If there are no such parameters then <foreach> will look for a container= parameter.

Any additional attributes with values will be temporary overrides to macros.

When looping over a hash, <macro varname> will be set to each of the values in turn. When looping over an array, it will be set to each of the values in turn. The keys from a hash will be available as <macro _varname> (notice the underscore). The index positions from ann array will be <macro _varname>.

<include>

The <include> tag incoporates the contents of another file into the current output. The name of the file can be specified as either the first attribute of the <include> tag or as the named attribute file. Both of the following examples do the same thing:

        <include body.inc>

        <include file="body.inc">

The filename must be a relative path.

Files are searched for by traversing the array @HTML::Transmorgify::Metatags::include_dirs which is exported by request. If any elements in that array are CODE references, then they will be invoked with the filename that is being searched for as an argument. Their return value should be undef or a filename.

DIVERSIONS

HTML::Transmorgify::Metatags provides diversions. The macros that control this are <capture> and <playback>. What is capture'd is removed from the normal output flow of the document. It can be included somewhere else with <playback>. Diversions do not effect the runtime execution order so the text for a capture will be captured sequenced as if the capture didn't exist.

For example you have:

 Before
 <define x value=before>
 <capture A>
 A
 x1=<macro x>
 <define x value=A>
 x2=<macro x>
 </capture A>
 After
 x3=<macro x>
 <define x value=after>
 <playback A />

You'll get:

  Before
  After
  x3=A
  A
  x1=before
  x2=A

Diversions are resolved as a post-processing step so the <capture> and <playback> tags can be used in nearly any order. You can <playback> a diverison before it is saved wtih <capture>.

A <playback> inside a <capture> creates a dependency: the playback'ed diversion must be resolved before the catpure'd diversion. Circular dependencies are not allowed.

RESERVED WORDS

The following macros/variables are reserved for future use and should not be used at the current time:

        _diversions
        _current_diversion