NAME
Text::MagicTemplate - magic merger of runtime values with template
SYNOPSIS
- the template
-
The template file 'my_template_file'... (this example uses plain text for clarity, but MagicTemplate works with any type of text file)
A scalar variable: {a_scalar}. A reference to a scalar variable: {a_ref_to_scalar}. A subroutine: {a_sub} A reference to subroutine: {a_ref_to_sub} A reference to reference: {a_ref_to_ref} A hash: {a_hash}this block contains a {a_scalar} and a {a_sub}{/a_hash} A loop:{an_array_of_hashes} Iteration #{ID}: {guy} is a {job}{/an_array_of_hashes} An included file: {'my_included_file'}
... and another template file 'my_included_file' that will be included...
this is the included file 'my_included_file' that contains a label: {a_scalar}
- the code
-
... some variables and subroutines already defined somewhere in your code...
$a_scalar = 'THIS IS A SCALAR VALUE'; $a_ref_to_scalar = \$a_scalar; @an_array_of_hashes = ( { ID => 1, guy => 'JOHN SMITH', job => 'PROGRAMMER' }, { ID => 2, guy => 'TED BLACK', job => 'WEBMASTER' }, { ID => 3, guy => 'DAVID BYRNE', job => 'MUSICIAN' } ); %a_hash = ( a_scalar => 'NEW SCALAR VALUE' a_sub => sub { 'NEW SUB RESULT' } ); sub a_sub { 'THIS SUB RETURNS A SCALAR' } sub a_ref_to_sub { \&a_sub } sub a_ref_to_ref { $a_ref_to_scalar }
Just add these 3 magic lines...
use Text::MagicTemplate; $mt = new Text::MagicTemplate; $mt->print( 'my_template_file' );
- the output
-
(in this example Lower case are from templates and Upper case are from code):
A scalar variable: THIS IS A SCALAR VALUE. A reference to a scalar variable: THIS IS A SCALAR VALUE. A subroutine: THIS SUB RETURNS A SCALAR A reference to subroutine: THIS SUB RETURNS A SCALAR A reference to reference: THIS IS A SCALAR VALUE A hash: this block contains a NEW SCALAR VALUE and a NEW SUB RESULT A loop: Iteration #1: JOHN SMITH is a PROGRAMMER Iteration #2: TED BLACK is a WEBMASTER Iteration #3: DAVID BYRNE is a MUSICIAN An included file: this is the included file 'my_included_file' that contains a label: THIS IS A SCALAR VALUE.
DESCRIPTION
Text::MagicTemplate is a "magic" interface between programming and design. It makes "magically" available all the runtime values - stored in your variables or returned by your subroutines - inside a static template file. There's usually no need to assign values to the object. Template outputs are linked to runtime values by their identifiers, which are added to the template in the form of simple labels or blocks of content.
a label: {identifier}
a block: {identifier} content of the block {/identifier}
From the designer point of view, this makes things very simple. The designer has just to decide what value and where to put it. Nothing else is required, no complicated new syntax to learn!
On the other side, the programmer has just to define variables and subroutines as usual and their values will appear in the right place within the output. The automatic interface allows the programmer to focus just on the code, saving him the hassle of interfacing code with output, and even complicated output - with complex switch branching and nested loops - can be easily organized by minding just a few simple concepts (see "How it works").
Features
There are several "similar" modules, so why yet another one? These features are the answer:
Simple, flexible and powerful to use
In most cases, you will have just to use
new()
andprint(template)
methods, without having to pass any other value to the object: it will do the right job for you.Extremely simple and configurable template syntax
The template syntax is so simple and code-independent that even the less skilled webmaster will manage it without bothering you :-). By default Text::MagicTemplate recognizes labels in the form of simple identifiers surrounded by braces ({my_identifier}), but you can easily use a different template syntax (see "Redefine Syntax").
Automatic or manual lookup of values
By default, Text::MagicTemplate compares any label identifier defined in your template with any variable or subroutine identifier defined in the caller namespace. However, you can explicitly define the lookup otherwise, by passing to the
new()
method a list of package namespaces and/or hash references.Support for unlimited nested included templates
Sometimes it can be useful to split a template into differents files. No nesting limit when including files into files. (see "Include a file")
Support for branching
You can easily create simple or complex if-elsif-else conditions to print just the blocks linked with the true conditions (see "Setup an if-else condition" and "Setup a switch condition")
Support for unlimited nested loops
When you need complex outputs you can build any immaginable nested loop, even mixed with control switches and included templates (see "Build a loop" and "Build a nested loop")
Support for placeholders and simulated areas
Placeholders and simulated areas can help in designing the template for a more consistent preview of the final output. (see "Setup placeholders" and "Setup simulated areas")
Template block management
When you need complex management of templates files, you have a couple of static methods to extract, mix and set blocks inside any template. (see
get_block()
andset_block()
static methods)Template perl embedding
Even if I don't encourage this approach, however you can very easily embed any quantity of perl code into any template. (See "Bypassing the rules")
Simple to maintain
Change your code and Text::MagicTemplate will change its behaviour accordingly. In most cases you will not have to reconfigure, either the object, or the template.
Very lightweight
MagicTemplate.pm doesn't use any other module and its code is just about 90 lines (easier to write that this documentation :-) )
How it works
The Text::MagicTemplate object is a blessed hash containing locations that it uses to look up identifiers. The locations array can store package namespaces or references to hashes. If no parameter is passed to the constructor, the package namespace of the caller will be used by default.
Text::MagicTemplate compares any label identifier defined in your template with any variable or subroutine identifier (for package locations) or key (for hash locations) defined in each stored location. When it find a match, it looks for the value. If the value represents a CODE, it will be executed (passing to the subroutine the content of the block itself as a parameter) to achieve a returned value; if the value represents a reference, it will be dereferenced until the actual value will be achieved.
The VALUE TYPE of the found value will determine the behaviour of MagicTemplate:
An UNDEF value type will delete label or block.
A SCALAR value type will replace label or block with the scalar value.
A HASH value type will set that HASH as a temporary location for the lookup of the block. Text::MagicTemplate first uses that location to look up the identifiers contained in the block; then, if unsuccessful, it will search into the stored locations.
An ARRAY value type will generate a loop, merging each value in the array with the the block and replacing the block with the sequence of the outputs.
Examples:
The same template: '{block}|before-{label}-after|{/block}'
... with these values... ...produce these outputs
------------------------------------------------------------------------
$label = 'THE VALUE'; >
$block = undef;
------------------------------------------------------------------------
$label = 'THE VALUE'; > NEW CONTENT
$block = 'NEW CONTENT';
------------------------------------------------------------------------
$label = 'THE VALUE'; > |before-THE VALUE-after|
$block = {};
------------------------------------------------------------------------
$label = undef; > |before--after|
$block = {};
------------------------------------------------------------------------
$label = 'THE VALUE'; > |before-NEW VALUE-after|
%block = (label=>'NEW VALUE');
------------------------------------------------------------------------
$label = 'THE VALUE'; > |before-NEW VALUE-after|
$block = {label=>'NEW VALUE'};
------------------------------------------------------------------------
$label = 'THE VALUE'; > NEW CONTENT|before-THE VALUE-after|
@block = ('NEW CONTENT', |before-NEW VALUE-after|
{},
{label=>'NEW VALUE'});
------------------------------------------------------------------------
$label = 'THE VALUE'; > NEW CONTENT|before-THE VALUE-after|
$block = ['NEW CONTENT', |before-NEW VALUE-after|
{},
{label=>'NEW VALUE'}];
------------------------------------------------------------------------
sub label { scalar localtime } > |before-Tue Sep 10 14:52:24 2002-
$block = {}; after|
------------------------------------------------------------------------
$label = 'THE VALUE'; > |BEFORE-{LABEL}-AFTER|
sub block { uc shift }
------------------------------------------------------------------------
Different combinations of values, labels and blocks can easily produce complex ouputs. See the "HOW TO..." section in this documentation.
Illegal blocks
Each block in the template can contain arbitrary quantities of nested labels and/or blocks, but it cannot contain itself (a block with its same identifier), or cannot be cross-nested.
Legal block: {block1}...{block2}...{/block2}...{/block1}
Illegal auto-nested block: {block1}...{block1}...{/block1}...{/block1}
Illegal cross-nested block: {block1}...{block2}...{/block1}...{/block2}
If the template contains any illegal block, unpredictable behaviours may occur.
Bypassing the rules
The main philosophy of Text::MagicTemplate is: keep separate designing from coding, giving all the power to the programmer and letting designer do only design. In other words: while the code include ALL the active and dynamic directions to generate the output, the template is a mere passive and static file, containing just placeholder (identifiers) that the code will replace with real data.
This philosophy keep both jobs very tidy and simple to do, avoiding confusion and enforcing clearness, specially when programmer and designer are 2 different people. But another aspect of the philosophy of Text::MagicTemplate is flexibility, something that give you the possibility to easily bypass the rules.
Even if I don't encourage breaking the main rule (keep separate designing from coding), sometimes you might find useful to put inside a template some degree of perl code, or may be you want just to interact DIRECTLY with the content of the template (See "Using subroutines to rewrite links").
Text::MagicTemplate can execute subroutines from your code: when you use a block identifier that matches with a subroutine identifier, the subroutine will receive the content of the block as a single parameter and will be executed. This is very useful when you want to return a modified copy of the template content itself, or if you want to allow the designer to pass parameter to the subroutines, or if you want to evaluate a perl expression inside the template.
Passing parameters to a subroutine
This example show you how to allow the designer to pass some parameters to a subroutine in your code.
- the template
-
{matrix}5,3{/matrix}
The content of 'matrix' block ('5,3') is used as parameter
- the code
-
sub matrix { my ($block_content) = shift; my ($column, $row) = split ',' , $block_content; # split the parameters my $out; for (0..$row-1) {$out .= 'X' x $column. "\n"}; $out; }
The sub 'matrix' receive the content of the template block as a single parameter, and return the output for the block
- the output
-
XXXXX XXXXX XXXXX
Embed perl into a template
This example represents the maximum degree of inclusion of perl code into a template: in this situation, virtually any code inside the 'perl_eval' block will be executed from the template. For obvious reasons you should use this type of configuration ONLY if you are the programmer AND the designer.
- the template
-
{perl_eval}$char x ($num+1){/perl_eval}
The content of 'perl_eval' block could be any perl expression
- the code
-
$char = 'W'; $num = 5; sub perl_eval { eval shift }
The sub 'perl_eval' just return the evaluated content of the block
- the output
-
WWWWWW
Since a block can contain any quantity of text, you could use this type of configuration as a cheap way to embed perl into (HTML) files.
Note that the default syntax markers ({/}) could somehow clash with perl blocks, so if you want to embed perl into your templates, you should consider to redefine the syntax with some more appropriate marker (See "Redefine Syntax").
METHODS
- new ( [lookup_list] )
-
The constructor method creates a blessed hash reference. The object contains an array of locations where the methods will look up the identifiers present in the template. Locations are packages or hashes: with packages locations, the lookup is done with all the IDENTIFIERS defined in the package namespace, with hash locations it is done with the KEYS existing in the hash.
If you want to make available all the identifiers of your current package, just call the constructor without parameters:
# default lookup in the caller package $mt = new Text::MagicTemplate ; # same thing but explicit $mt = new Text::MagicTemplate __PACKAGE__ ;
If you want to keep unavailable some variable or subroutine from the template, you can pass just the reference of some hash containing just the identifiers used in the template. This is the best method to use the module IF you allow untrustworthy people to edit the template AND if you have any potentially dangerous subroutine in your code. (see "CAVEATS").
# lookup in %my_hash only $mt = new Text::MagicTemplate \%my_hash ;
You can also define an arbitrary list of packages and/or references to hashes as the lookup: the precedence of the lookup will be inherited from the order of the items passed, and the first found mach will return the value.
# lookup in several location $mt = new Text::MagicTemplate \%my_hash, 'main', \%my_other_hash ;
In this example, the lookup will be done in
%my_hash
first - if unsuccessful - it will be done in the'main' package
and - if unsuccessful - it will be done in%my_other_hash
. - output ( template [, identifier] )
-
This method merges the runtime values with the template and returns a reference to the output. It accepts one template parameter that can be a reference to a SCALAR content, a path to a template file or a filehandle. If any identifier is passed, it returns a reference to the output of just that block.
# template is a path $output = $mt->output( '/temp/template_file.html' ) ; # template is a reference $output = $mt->output( \$tpl_content ) ; #template is a filehandler $output = $mt->output( *FILEHANDLER ); # this limits the output to just 'my_block_identifier' $my_block_output = $mt->output( \$tpl_content, 'my_block_identifier');
- print ( template [, identifier] )
-
This method merges the runtime values with the template and prints the output. It accepts one template parameter that can be a reference to a SCALAR content, a path to a template file or a filehandle. If any identifier is passed, it prints the output of just that block.
# template is a path $mt->print( '/temp/template_file.html' ); # template is a reference $mt->print( \$tpl_content ) ; #template is a filehandler $mt->print( *FILEHANDLER ); # this limits the output to just 'my_block_identifier' $mt->print( \$tpl_content, 'my_block_identifier' );
STATIC METHODS
To use any of the static method in this section you must load the module:
use Text::MagicTemplate;
and use them directly by using the class name:
CLASS_NAME->static_method_identifier(parameters)
Examples
... Text::MagicTemplate->get_block ( ....... )
... Text::MagicTemplate->set_block ( ....... )
... Text::MagicTemplate::HTML->get_block ( ....... )
... Local::myCustomSyntax->set_block ( ....... )
... Text::MagicTemplate::HTML->no_code_execution
...
- syntax ( START_MARKER, END_MARKER_ID, END_MARKER )
-
This static method redefine the syntax for the class. This is the basic structure of a generic label:
+--------------+---------------+------------+------------+ | START_MARKER | END_MARKER_ID | IDENTIFIER | END_MARKER | +--------------+---------------+------------+------------+
where END_MARKER_ID is exclusively used to produce an end label, and is omitted in every other case.
These are the default values of the markers that define the label.
START_MARKER: { END_MARKER_ID: / END_MARKER: }
You can redefine them using this static method:
Text::MagicTemplate->syntax (qw|__ END_ __|);
where '__' is the START_MARKER, 'END_' is the END_MARKER_ID and '__' is the END_MARKER;
NOTE: Each parameter of syntax static method is parsed as a regular expression as:
qr/parameter/
, so you can extend the syntax beyond a static string marker. This syntax:Text::MagicTemplate->syntax ('\d{3}', '\W', '\d{3}'); # weird markers :-)
will match this block:
235identifier690 content of block 563-identifier054
See "Redefine Syntax" to have more details.
- subs_execution ()
-
This static method enable or disables the execution of subroutines from your code. Default enabled. (see "CAVEATS" for details).
Text::MagicTemplate->subs_execution( 0 ); Text::MagicTemplate->subs_execution( 1 );
- get_block ( template [, identifier] )
-
This static method returns a reference to the template content or to a block inside the template, without merging values. It accepts one template parameter that can be a reference to a SCALAR content, a path to a template file or a filehandle. If any identifier is passed, it returns just that block.
# this returns a ref to the whole template content $tpl_content = Text::MagicTemplate->get_block ( '/temp/template_file.html' ); # this return a ref to the 'my_block_identifier' block $tpl_block = Text::MagicTemplate->get_block ( '/temp/template_file.html', 'my_block_identifier' ); # same thing passing a reference $tpl_block = Text::MagicTemplate->get_block ( $tpl_content, 'my_block_identifier' );
- set_block ( template, identifier, new_content )
-
This static method sets the content of the block (or blocks) identifier inside a template - without merging values - and returns a reference to the changed template. It accepts one template parameter that can be a reference to a SCALAR content, a path to a template file or a filehandle. New_content can be a reference to the content or the content itself.
# this return a ref to the 'my_block' block $new_content = Text::MagicTemplate->get_block ( '/temp/template_file_2.html', 'my_block' ); # this returns a ref to the changed template content, $changed_content = Text::MagicTemplate->set_block ( '/temp/template_file.html', 'my_old_block', $new_content );
- set_ID_output ()
-
Calling this method will redefine some behaviours of the module, so your program will generate a pretty formatted output of only the identifiers present in the template. Thus the programmer can pass a description of each label and block within a template to a designer
- Deprecated methods
-
no_code_execution()
,code_execution()
,code_execution_ON()
,code_execution_OFF()
: use subs_execution() instead.
HOW TO...
Please, carefully read and understand section "How it works", before reading this section.
Include a file
To include a file in a template just set a label with the pathname of the file as identifier, surrounded by quotes:
{'/temp/footer.html'}
The file will be included in place of the label and if it is a template, it will be processed as usual.
Redefine Syntax
- by using a prebuilt syntax module
-
The standard installation comes with a HTML friendly syntax module that implements a HTML-comment-like syntax. If your output is an HTML text - or just because you prefer that particular look - you can use it instead of using the standard module. Read the documentation of Text::MagicTemplate::HTML to know the details.
- by adding one line to your code
-
To redefine syntax use the
syntax()
static method, directly in your code:use Text::MagicTemplate; Text::MagicTemplate->syntax( qw|<- / ->| ); # redefine the markers as needed
- by subclassing Text::MagicTemplate class
-
If you need some custom and permanent solution you can subclass the
Text::MagicTemplate
class. As an added benefit, this method allows you to use different syntaxes in the same script.This is an example that explains you how to write and use a custom syntax module Local::myCustomSyntax.pm (obviously you can use the class name you prefer).
Redefine the markers and save this code as file Local::myCustomSyntax.pm
package Local::myCustomSyntax; # choose a meaningful package namespace :-) use Text::MagicTemplate; push @ISA, qw(Text::MagicTemplate); __PACKAGE__->syntax( qw|__ END_ __| ); # redefine these values as needed 1;
Use it by loading the module as usual:
use Local::myCustomSyntax;
and use methods as usual...
$mt = new Local::myCustomSyntax; $mt->print( 'my_custom_template_file' );
This syntax would work with this block labeled 'my_identifier':
__my_identifier__ content of block __END_my_identifier__
If you write some custom syntax module - useful for any particular output - please, let me know.
Setup a template
A quick way to setup a template in 4 simple steps is the following:
- 1 Prepare an output
-
Prepare a complete output as your code could print. Place all the static items of your output where they should go, place placeholders (any runtime value that your code would supply) where they should go and format everything as you want
- 2 Choose names
-
Choose meaningful names (or variables and subroutines names if you already have a code) for labels and blocks
- 3 Insert single labels
-
Find the dynamic items in the template and replace them with a label, or if you want to keep them as visible placeholders, transform each one of them into a block
- 4 Define blocks
-
If you have any area that will be repeated by a loop or that will be printed just under certain conditions transform it into a block.
Setup placeholders
These are a couple of templates that use a HTML friendly sintax (implemented in Text::MagicTemplate::HTML). The output will be the same for both templates, with or without placeholders: the difference is the way you can look at the template.
- template without placeholders
-
<p><hr>Name: <b style="color:blue"><!--{name}--></b><br> Surname: <b style="color:blue"><!--{surname}--></b><hr></p>
This is what you would see in a WYSIWYG editor: (you should be using a browser to see the example below this line)
- template with placeholders
-
The placeholders "John" and "Smith" are included in blocks and will be replaced by the actual values of 'name' and 'surname' from your code.
Name: John
This is what you would see in a WYSIWYG editor: I<(you should be using a browser to see the example below this line)> Setup simulated areas
Surname: SmithIf you want to include in your template some area only for design purpose I<(for example to see, right in the template, how could look a large nested loop)>, just transform it into a block and give it an identifier that will never be defined in your code. {my_simulated_area}this block simulates a possible output and it will never generate any output{/my_simulated_area} Setup labeled areas
Build a loop
- the template
- A loop is represented by a block, usually containing labels: A loop: {my_loop}------------------- Date: {date} Operation: {operation} {/my_loop}------------------- the code
- You should have some array of hashes (or a reference to) defined somewhere: $my_loop = [ { date => '8-2-02', operation => 'purchase' }, { date => '9-3-02', operation => 'payment' } ] ; the output
Build a nested loop
- the template
- A nested loop is represented by a block nested into another block: A nested loop: {my_nested_loop}------------------- Date: {date} Operation: {operation} Details:{details} - {quantity} {item}{/details} {/my_nested_loop}------------------- Note that the block I<'details'> is nested into the block I<'my_nested_loop'>. the code
- You should have some array nested into some other array, defined somewhere: # a couple of nested "for" loops may produce this: $my_nested_loop = [ { date => '8-2-02', operation => 'purchase', details => [ {quantity => 5, item => 'balls'}, {quantity => 3, item => 'cubes'}, {quantity => 6, item => 'cones'} ] }, { date => '9-3-02', operation => 'payment', details => [ {quantity => 2, item => 'cones'}, {quantity => 4, item => 'cubes'} ] } ] ; Note that the value of the keys I<'details'> are a reference to an array of hashes. the output
Setup an if-else condition
- the template
- An if-else condition is represented with 2 blocks {OK_block}This is the OK block, containig {a_scalar}{/OK_block} {NO_block}This is the NO block{/NO_block} the code
- Remember that a block will be deleted if the lookup of the identifier returns the UNDEF value, so your code will determine what block will generate output (defined identifier) and what not (undefined identifier). if ($OK) { $OK_block = {a_scalar => 'A SCALAR VARIABLE'} } else { $NO_block = {} } Same thing here: $a_scalar = 'A SCALAR VARIABLE'; $OK ? $OK_block={} : $NO_block={}; the output
Setup a switch condition
- the template
- A simple switch (if-elsif-elsif) condition is represented with multiple blocks: {type_A}type A block with {a_scalar_1}{/type_A} {type_B}type B block with {a_scalar_2}{/type_B} {type_C}type C block with {a_scalar_1}{/type_C} {type_D}type D block with {a_scalar_2}{/type_D} the code
- Your code will determine what block will generate output (defined identifier) and what not (undefined identifier). In the following example, value of C<$type> will determine what block will produce output, then the next line will define C<$type_C> using a symbolic reference: $type = 'type_C'; $$type = { a_scalar_1 => 'THE SCALAR 1', a_scalar_2 => 'THE SCALAR 2' }; Same thing yet but with a different programming style: $a_scalar_1 = 'THE SCALAR 1'; $a_scalar_2 = 'THE SCALAR 2'; $type = 'type_D'; $$type = {}; Same thing without using any symbolic reference: $type = 'type_D'; $my_hash{$type} = { a_scalar_1 => 'THE SCALAR 1', a_scalar_2 => 'THE SCALAR 2' }; $mt = new Text::MagicTemplate \%my_hash; the output
Using subroutines to rewrite links
- the template
- Working links pointing to static templates files (useful for testing and preview purpose, without passing through the program) the code
- sub modify_link { my ($action) = shift =~ m|([^/]*).html$|; return '/path/to/myprog.cgi?action='.$action; } the output
Prepare the identifiers description list
- 1 Add the following line anywhere before printing the output:
- Text::MagicTemplate->set_ID_output; 2 Capture the outputs of your program
- Your program will run exactly the same way, but instead of print the regular outputs, it will print just a pretty formatted list of all the identifiers present in any output. 3 Add the description
CAVEATS
Read this section just in case you are planning to allow untrustworthy people to edit the template. Allowing untrustworthy people to edit the template
F does not use any eval() statement, it just do a recursive search and replace with the content of the template. Besides, the allowed characters for identifiers are only alphanumeric C<(\w+)>, so even dealing with tainted templates should not raise any security problem that you wouldn't have in your program itself. However, since the module is just about 90 lines of code, you should consider to analise it directly. If you do this, please send me some feedback. Avoid unwanted executions
- potentially unsafe code
- sub my_potentially_dangerous_sub { unlink 'database_file' }; $name = 'John'; $surname = 'Smith'; $mt = new Text::MagicTemplate ; # automatic lookup in __PACKAGE__ namespace With this code, a malicious person allowed to edit the template could add the label I<{my_potentially_dangerous_sub}> in the template and that label would trigger the deletion of 'database_file'. code with subs_execution disabled
- Use the same code, but add this line: Text::MagicTemplate->subs_execution(0); ... so Text::MagicTemplate will execute no subroutines Note that if you use a subclass - as C - you must use the correct subclass name: Text::MagicTemplate::HTML->subs_execution(0); # or Local::myCustomSyntax->subs_execution(0); code with restricted lookups
GLOSSARY
- behaviour
- The action generated by Text::MagicTemplate and triggered by the value type. (i.e. an UNDEF value type triggers the deletion of the label or the block, a ARRAY value type generate a loop). block
- A I is a chunk of text in a I delimited by (and including) a I and an I: +-------+-------------------+------------+ | LABEL | CONTENT | END_LABEL | +-------+-------------------+------------+ Example: B<{my_identifier} content of the block {/my_identifier}> where C<'{my_identifier}'> is the LABEL, C<' content of the block '> is the CONTENT and C<'{/my_identifier}'> is the END_LABEL. end label
- An I is a string in the form of: +--------------+---------------+------------+------------+ | START_MARKER | END_MARKER_ID | IDENTIFIER | END_MARKER | +--------------+---------------+------------+------------+ Example of end label : B<{/my_identifier}> where C<'{'> is the START_MARKER, C<'/'> is the END_MARKER_ID, C<'my_identifier'> is the IDENTIFIER, and C<'}'> is the END_MARKER. identifier
- A I is a alphanumeric name C<(\w+)> that represents (and usually matches) a variable or a subroutine identifier of your code. include label
- An I is a I used to include a I file. The I must be surrounded by single or double quotes and should be a valid path. Example: B<{'/templates/temp_file.html'}> label
- A I is a string in the form of: +--------------+------------+------------+ | START_MARKER | IDENTIFIER | END_MARKER | +--------------+------------+------------+ Example: B<{my_identifier}> where C<'{'> is the START_MARKER, C<'my_identifier'> is the IDENTIFIER and C<'}'> is the END_MARKER. locations
- I are packages namespaces or hashes used to perform lookups. lookup
- The action performed by a method to compare label I with code identifier (variable identifiers, subroutine identifiers and hash keys). nested block
- A I is a I contained in another I: +----------------------+ | CONTAINER_BLOCK | | +----------------+ | | | NESTED_BLOCK | | | +----------------+ | +----------------------+ Example: {my_container_identifier} B<{my_nested_identifier} content of the block {/my_nested_identifier}> {/my_container_identifier} where all the above is the CONTAINER_BLOCK and C<'{my_nested_identifier} content of the block {/my_nested_identifier}'> is the NESTED_BLOCK. output
- The I is the result of the merger of runtimes data with a template template
- A I is a text content or a text file (i.e. plain, HTML, XML, etc.) containing some I or I. value type
SUPPORT and FEEDBACK
I would like to have just a line of feedback from everybody who tries or actually uses this module. Feel free to write me any comment, suggestion or request. AUTHOR
Domizio Demichelis, . COPYRIGHT
Copyright (c)2002 Domizio Demichelis. All Rights Reserved. This module is free software; it may be used freely and redistributed for free providing this copyright header remains part of the module. You may not charge for the redistribution of this module. Selling this code without Domizio Demichelis' written permission is expressly forbidden. This module may not be modified without first notifying the author (this is to enable me to track modifications). In all cases the copyright header should remain fully intact in all modifications. This code is provided on an "As Is'' basis, without warranty, expressed or implied. The author disclaims all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall the author, be liable for any special, indirect or consequential damages or any damages whatsoever including but not limited to loss of use, data or profits. By using this module you agree to indemnify the author from any liability that might arise from it is use. Should this code prove defective, you assume the cost of any and all necessary repairs, servicing, correction and any other costs arising directly or indrectly from it is use. The copyright notice must remain fully intact at all times. Use of this program or its output constitutes acceptance of these terms.
6 POD Errors
The following errors were encountered while parsing the POD:
- Around line 468:
You forgot a '=back' before '=head2'
- Around line 538:
You forgot a '=back' before '=head2'
- Around line 542:
=over without closing =back
- Around line 555:
'=end' without a target? (Should be "=end html")
- Around line 570:
'=end' without a target? (Should be "=end html")
- Around line 572:
=back without =over