The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Template::Caribou::Role - Caribou core engine

VERSION

version 1.2.2

SYNOPSIS

package MyTemplate;

use Template::Caribou;

has name => ( is => 'ro' );

template greetings => sub {
    my $self = shift;

    print "hello there, ", $self->name;
};

# later on...

my $template =  MyTemplate->new( name => 'Yanick' );

print $template->greetings;

DESCRIPTION

This role implements the rendering core of Caribou, which mostly deals with defining the templates of a class and calling them.

The templates

The templates are subs expected to print or return the content they are generating. Under the hood, they are snugly wrapped within a render call and turned into methods of the template class.

package MyTemplate;

use Template::Caribou;

has name => ( is => 'ro' );

template greetings => sub {
    my( $self, %args ) = @_;

    'hi there ' . $self->name . '!' x $args{excited};
};

my $bou = MyTemplate->new( name => 'Yanick' );

print $bou->greetings; 
    # prints 'hi there Yanick'

print $bou->greetings(excited => 1);
    # print 'hi there Yanick!

In addition of those arguments, the file descriptions ::STDOUT and ::RAW are locally defined. Anything printed to ::RAW is added verbatim to the content of the template, whereas something printed to STDOUT will be HTML-escaped.

If nothing has been printed at all by the template, it'll take its return value as its generated content.

# prints '<hey>'
print MyTemplate->render(sub{
    print "<hey>";
});

# prints '<hey>'
print MyTemplate->render(sub{
    print ::RAW "<hey>";
});

# prints 'onetwo'
print MyTemplate->render(sub{
    print "one";
    print "two";
});

# prints 'one'
print MyTemplate->render(sub{
    print "one";
    return "ignored";
});

# prints 'no print, not ignored'
print MyTemplate->render(sub{
    return "no print, not ignored";
});

Template methods can, of course, be called within other template methods. When invoked from within a template, their content is implicitly printed to ::RAW.

template outer => sub {
    my $self = shift;

    say 'alpha';
    $self->inner;
    say 'gamma';
};

template inner => sub {
    say 'beta';
};

...;

print $bou->outer; # prints 'alpha beta gamma'

Definiting templates via template instances

Templates are usually defined for the class via the template keyword. template can also be used as a method. By default, though, it'll die as adding a template that way will not only add it to the instance, but for to class itself, which is probably more than you bargained for.

$bou->template( foo => sub { ... } );
# dies with 'can only add templates from instances created 
# via 'anon_instance' or with the attribute 'can_add_templates'

If you want to add a template to a single instance, use the class method anon_instance, which will create a singleton class inheriting from the main template class.

my $bou = MyTemplate->anon_instance( name => 'Yanick' );

$bou->template( foo => sub { ... } ); # will work

Or if you really want to augment the whole class with new templates, you can set the can_add_templates attribute of the object to true.

$bou->can_add_templates(1); 
$bou->template( foo => sub { ... } ); # will work too

METHODS

new

my $bou = MyTemplate->new(
    indent            => 1,
    can_add_templates => 0,
);
indent => $boolean

If set to a true value, the nested tags rendered inside the templates will be indented. Defaults to true.

can_add_templates

If templates can be added to the class via the method invocation of template.

indent

$bou->indent($bool);

Accessor to the indent attribute. Indicates if the tags rendered within the templates should be pretty-printed with indentation or not.

can_add_templates

$bou->can_add_templates($bool);

Accessor. If set to true, allows new templates to be defined for the class via the template method.

template( $name => sub { ... } )

Defines the template $name. Will trigger an exception unless can_add_templates was set to true or the object was created via anon_instance.

Warnings will be issued if the template redefines an already-existing function/method in the namespace.

anon_instance(@args_for_new)

Creates an anonymous class inheriting from the current one and builds an object instance with the given arguments. Useful when wanting to define templates for one specific instance.

render

$bou->render( $coderef, @template_args );
$bou->render( $template_name, @template_args );

Renders the given $coderef as a template, passing it the @template_args, and returns its generated output.

print $bou->render( sub {
    my( $self, $name ) = @_;

    'hi ' . $name . "\n";
}, $_ ) for @friends; 

The template can also be given by name.

template foo => sub { ... };

# later on

$bou->render( 'foo', @args );

# which is equivalent to

$bou->foo(@args);

get_render

Like render, but always return the generated template content, even when called inside a template.

template foo => sub { 'foo' };
template bar => sub { 'bar' };

print $bou->render(sub{
    my $self = shift;

    $self->foo;
    my $bar = $self->get_render(sub{ $self->bar });
    $bar =~  y/r/z/;
    say $bar;
});

# prints 'foobaz'

SEE ALSO

http://babyl.dyndns.org/techblog/entry/caribou - The original blog entry introducing Template::Caribou.

Template::Declare

AUTHOR

Yanick Champoux <yanick@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2023 by Yanick Champoux.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.