NAME Template::Plex - Templates in (P)erl using (Lex)ical Aliasing SYNOPSIS use Template::Plex; #Data for templates to alias and access my $base_data={ name=>"James", age=>"12", fruit=>"banana" }; #The actual template text # my $inline_template='$name\'s age $age and favourite fruit is $fruit' #Preparing the template in Template::Plex object # my $t=plex [$inline_template], $base_data, %options; #Render with the values aliased in $base_data $t->render; # #=> James's age is 12 and favourite fruit is banana #Update the data in the hash used during preparation. # $base_data->{qw}=qw; #Rendering again will use updated aliased values # $t->render; # #=> John's age is 12 and favourite fruit is apple DESCRIPTION This module is a mechanism to facilitate the use of perl (not embedded perl) as a text processing template language. Conceptually, a "Template::Plex" template is just a string returned from a subroutine in perl's double quoted context, with the outer operators removed: #PERL "This is is a perl string interpolating @{[ map uc, qw]}" # or qq{This is is a perl string interpolating @{[ map uc, qw]}} #PLEX template. Same as PERL syntax, without the outer double quotes This is is a perl string interpolating @{[ map uc, qw]}; #OUTPUT is the same for all of the above: This is is a perl string interpolating A B C D Because of the powerful and flexible interpolation of strings in perl, you can do just about anything in a Plex template. After all the template is just perl. The 'lexical' part of this modules refers to ability of variables to be aliased into the template (more on this later). It improves the style and usage of variables in a template while also allowing sub templates to access/override variables using lexical scoping. Some feature highlights: * Templates are written in perl syntax * Templates are compiled into a perl subroutine * Lexical and package variables accessed/created within templates * Call and create subroutines within templates * 'Include' Templates within templates easily * Recursive and conditional sub template loading * Declare variables and subroutines in templates * "use" other modules directly in templates To get started after installation, copy the following lines into perl and execute: use strict; use warnings; use feature "say"; use Template::Plex; my %vars=(name=>"Susan", age=>99); my $template=plex ['this is ${name}\'s inline template. $age young'], \%vars; say $template->render; @vars{qw}=qw; say $template->render; For more examples, checkout the examples directory in this distribution. MOTIATION * So many templating systems available, yet none use perl as the template language? * Lexical aliasing allows the input variables to be accessed directly by name (i.e. $name) instead of as a member of a hash ref (i.e. "$fields->{name}") or by delimiting with custom syntax (i.e. "<%= name %>") * The perl syntax "@{[...]}" will execute arbitrary perl statements in a double quoted string. * Other templating system are very powerful, but have huge a huge APIs and options. Template::Plex could have a very minimal API with perl doing the hard work TODO * More tests * Add a guide document * CLI app to render .plex files * Fix any bugs API "plex" plex $path, $variables_hash, %options Creates a new instance of a template, loaded from a scalar, file path or an existing file handle. Multi Argument Version If 2 or more arguments are provided, the template is loaded and prepared and returned. The returned template can be rendered by calling the "render" method on it. Single Argument Version If only the first argument is supplied, the template is loaded, prepared, and rendered immediately. The rendered text is returned. This is useful when using sub templates, as the variables and options are already available from the top level template. The arguments are detailed below: $path This is a required argument. If $path is a string, it is treated as a file path to a template file. The file is opened and slurped with the content being used as the template If $path is filehandle, or GLOB ref, it is slurped with the content being used as the template. Can be used to read template stored in "__DATA__" for example If $path is an array ref, the items of the array are joined into a string, which is used directly as the template. $variables_hash This is an optional argument but if present must be an empty hash ref "{}" or "undef". The top level items of the $variables_hash hash are aliased into the template using the key name (key names must be valid for a variable name for this to operate). This allows an element such as "$fields{name"}> to be directly accessible as $name. It also means any external modification of the items in $variable_hash will be visible in the template. In addition, the $variables_hash itself is aliased to %fields variable (note the %) and directly usable in the template like a normal hash e.g. $fields{name} If the $variables_hash is an empty hash ref "{}" or "undef" then no variables will be lexically aliased. The only variables accessible to the template will be via the "render" method call "Options" These are non required arguments, but must be key value pairs when used. Options are stored lexically in the rendering sub in the variable %options for recursive "plex" calls within a template. Currently supported options are: root "root" is a directory path, which if present, is prepended to to the $path parameter if $path is a string (file path). no_include Disables the uses of the preprocessor include feature. The template text will not be scanned and will prevent the "include" feature from operating. See "include" for more details This doesn't impact recursive calls to "plex" when dynamically/conditionally loading templates. package Specifies a package to run the template in. Any "our" variables defined in the template will be in this package. If a package is not specified, a unique package name is created to prevent name collisions Return value The return value is "Template::Plex" object which can be rendered using the "render" method Example Usage my $hash={ name=>"bob", age=>98 }; my $template_dir="/path/to/dir"; my $obj=plex "template.plex", $hash, root=>$template_dir; "render" $obj->render($fields); This object method renders a template object created by "plex" into a string. It takes an optional argument $fields which is a reference to a hash containing field variables. "fields" is aliased into the template as %fields which is directly accessible in the template eg my $more_data={ name=>"John", }; my $string=$template->render($more_data); #Template: My name is $fields{John} Note that the lexically aliased variables in "plex" are independent to the %fields variable and can both be used simultaneously in a template "include" @{[include("path")}] where $path is path to template file to inject Used in templates only. This is a special directive that substitutes the text @{[include("path")]} with the contents of the file pointed to by path. This is a preprocessing step which happens before the template is prepared for execution This API is only available in templates. If "root" was included in the options to "plex", then it is prepended to "path" if defined. When a template is loaded by "plex" the processing of this is subject to the "no_include" option. If "no_include" is specified, any template text that contains the "@{[include("path")}]" text will result in a syntax error PLEX TEMPLATE SYNTAX \w EXAMPLES Well, its just perl. Seriously. But if you haven't grasped the concept just yet, a Template::Plex template is a perl program with the two following constraints: * consists only of perl syntax permissible in a double quoted string * outermost double quote operators are ommited from the program/template This is best illustrated by example. Suppose the following text is stored in a file or in the "__DATA__ " section: The pot of gold at the end of the rainbow has $amount gold coins As for the rainbow, the colors are: @{[ map ucfirst."\n", @$colors ]} Good day! Everything in the text is valid syntax in double quote operator, but the outer double quote operator is omitted. Or in other words, the template looks like plain text, but with double quoted added, it is valid perl code. Neat! Following sections show example of particular scenarios Access to Existing Scalars, Arrays and Hashes If $variables_hash was supplied during a "plex" call, the top level elements will be aliased and accessible as normal scalars in the template. This template uses a scalar $name that was lexically aliased Here the same variable can be accessed via $fields{name} Calling render with an hash argument will override the $fields{name} AReallylong${word}WithAVariable access the array element $array->[$index] Accessing element $hash->{key} just for fun Executing a single (or list) of Statements To achieve this, a neat trick is to dereference an inline reference to an anonymous array. That is "@{[...]}". The contents of the array is then the result of the statements. Sounds like a mouthful, but it is only a couple of braces and lets you do some powerful things: Calling a subrotine @{[ my_sub() ]} Doing math a + b = @{[ $a+$b ]} Building an array @{[ uc("red"),uc("blue")]} Mapping @{[ join "\n", map uc, @items]} Executing Multiple Statements When a single statement won't do, the "do{}" construct executes a block, which can have any number of statements and returns the last statement executed into the template Executing multiple statments @{[ do { my $a=1; $a++; ($a,-$a) } ]} in this template Using/Requiring Modules Again standard perl syntax for the win Template will call hi res time The time is: @{[ time ]} @{[ do { BEGIN { use Time::HiRes qw