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.