Venus::Template

Template Class

Template Class for Perl 5

method: new method: render

package main;

use Venus::Template;

my $template = Venus::Template->new(
  'From: <{{ email }}>',
);

# $template->render;

# "From: <>"

This package provides a simple yet powerful templating system for Perl 5 that supports variable interpolation, loops, and conditional blocks. The templating system is designed to only operate on raw Perl data and as such does not support operators, filters, virtual method, etc.

+=head2 Syntax

+=head3 Tags

The opening and closing tags are {{ and }}. Content between these tags can be:

+=over 4

+=item *

Simple path access (e.g., {{ name }})

+=item *

Nested path access (e.g., {{ user.email }})

+=item *

Control structures (described below)

+=back

To include literal tags in your template, escape them using either:

+=over 4

+=item *

Single backslash: \{{ and \}}

+=item *

Escaped braces: \{\{ and \}\}

+=back

+=head3 Tokens

Variable substitution uses dot notation to access nested data:

# access hash key 'name' in hash 'user'
{{ user.name }}

# access hash key 'name' in first element of array 'users'
{{ users.0.name }}

# access deeply nested hash keys
{{ profile.address.zip }}

+=head3 Loops

Loops iterate over arrays using the for control structure:

{{ for users }}
  Name: {{ user.name }}
{{ end users }}

Special loop variables are available within for blocks:

+=over 4

+=item *

{{ loop.index }} - Zero-based iteration counter

+=item *

{{ loop.place }} - One-based iteration counter

+=item *

{{ loop.item }} - Current item value (useful for arrays of simple values)

+=back

For nested loops, parent loop information is accessible via:

+=over 4

+=item *

{{ loop.parent }} - Immediate parent loop's data

+=item *

{{ loop.level.0 }} - First loop

+=item *

{{ loop.level.1 }} - Second loop

+=item *

{{ loop.level.2 }} - Third loop

+=back

+=head3 Controls

Conditional blocks use if, if not, and optional else:

{{ if user.admin }}
  Admin: {{ user.name }}
{{ else user.admin }}
  User: {{ user.name }}
{{ end user.admin }}

{{ if not user.active }}
  Account inactive
{{ end user.active }}

+=head2 Structure

The template engine expects variables to be provided as hashrefs. Arrays should be provided as arrayrefs. When iterating over arrays:

+=over 4

+=item *

Arrays of hashrefs: Access hash keys via {{ user.name }}

+=item *

Arrays of simple values: Access values via {{ loop.item }}

+=back

Example data structure:

{
  user => {
    name => 'Alice',
    admin => 1,
    profile => {
      email => 'alice@example.com'
    }
  },
  items => [
    'a', 'b', 'c'
  ],
  users => [
    {
      name => 'Bob',
      role => 'user'
    },
    {
      name => 'Carol',
      role => 'admin'
    }
  ]
}

+=head2 Context

The template engine expects variables to be provided via the "context" attribute, or as an argument to the "render" method after the template.

Setting context during object construction:

package main;

use Venus::Template;

my $template = Venus::Template->new(context => {email => 'alice@example.com'});

$template->render('From: <{{ email }}>');

Setting context during template rendering:

package main;

use Venus::Template;

my $template = Venus::Template->new(value => 'From: <{{ email }}>');

$template->render(undef, {email => 'alice@example.com'});

Venus::Kind::Utility

Venus::Role::Accessible Venus::Role::Buildable Venus::Role::Explainable Venus::Role::Valuable

The context attribute is read-write, accepts (hashref) values, and is optional.

context(hashref $context) (hashref)

{ since => '4.15', }

The new method constructs an instance of the package.

new(any @args) (Venus::Template)

{ since => '4.15', }

The render method processes the template by replacing the tokens and control structurs with the appropriate replacements and returns the result. Note: The rendering process expects variables to be hashrefs and sets (arrayrefs) of hashrefs. Within a for loop, special values are available under the loop variable:

+=over 4

+=item *

{{ loop.index }} - Zero-based index of current iteration

+=item *

{{ loop.place }} - One-based index of current iteration

+=item *

{{ loop.item }} - Current item value (especially useful for arrays of simple values, e.g. strings)

+=item *

{{ loop.parent }} - Access to parent loop's metadata (if within nested loops)

+=item *

{{ loop.level }} - Access to multi-level parent loop metadata (if within nested loops)

+=back

For nested loops, you can also access specific loop levels using zero-based numbering:

+=over 4

+=item *

{{ loop.level.0 }} - Top-level loop

+=item *

{{ loop.level.1 }} - One level under the top-level loop

+=item *

{{ loop.level.2 }} - Two levels under the top-level loop

+=back

render(string $template, hashref $context) (string)

{ since => '0.01', }

=example-1 render

# given: synopsis;

my $result = $template->render;

# "From: <>"

This package overloads the "" operator.

This package overloads the ~~ operator.

t/Venus.t: present: authors t/Venus.t: present: license

39 POD Errors

The following errors were encountered while parsing the POD:

Around line 14:

Unknown directive: =name

Around line 22:

Unknown directive: =tagline

Around line 30:

Unknown directive: =abstract

Around line 38:

Unknown directive: =includes

Around line 47:

Unknown directive: =synopsis

Around line 74:

Unknown directive: =description

Around line 265:

Unknown directive: =inherits

Around line 273:

Unknown directive: =integrates

Around line 284:

Unknown directive: =attribute

Around line 289:

Unknown directive: =signature

Around line 293:

Unknown directive: =metadata

Around line 311:

=cut found outside a pod block. Skipping to next block.

Around line 333:

=cut found outside a pod block. Skipping to next block.

Around line 343:

Unknown directive: =method

Around line 347:

Unknown directive: =signature

Around line 351:

Unknown directive: =metadata

Around line 369:

=cut found outside a pod block. Skipping to next block.

Around line 389:

=cut found outside a pod block. Skipping to next block.

Around line 410:

=cut found outside a pod block. Skipping to next block.

Around line 431:

=cut found outside a pod block. Skipping to next block.

Around line 442:

Unknown directive: =method

Around line 492:

Unknown directive: =signature

Around line 496:

Unknown directive: =metadata

Around line 536:

=cut found outside a pod block. Skipping to next block.

Around line 563:

=cut found outside a pod block. Skipping to next block.

Around line 599:

=cut found outside a pod block. Skipping to next block.

Around line 644:

=cut found outside a pod block. Skipping to next block.

Around line 684:

=cut found outside a pod block. Skipping to next block.

Around line 724:

=cut found outside a pod block. Skipping to next block.

Around line 764:

=cut found outside a pod block. Skipping to next block.

Around line 800:

=cut found outside a pod block. Skipping to next block.

Around line 843:

=cut found outside a pod block. Skipping to next block.

Around line 889:

=cut found outside a pod block. Skipping to next block.

Around line 906:

Unknown directive: =operator

Around line 922:

=cut found outside a pod block. Skipping to next block.

Around line 940:

=cut found outside a pod block. Skipping to next block.

Around line 950:

Unknown directive: =operator

Around line 966:

=cut found outside a pod block. Skipping to next block.

Around line 972:

Unknown directive: =partials