The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Solution::Tag - Documentation for Solution's Standard and Custom Tagset

Description

Tags are used for the logic in your template. New tags are very easy to code, so I hope to get many contributions to the standard tag library after releasing this code.

Standard Tagset

Expanding the list of supported tags is easy but here's the current standard set:

comment

Comment tags are simple blocks that do nothing during the render stage. Use these to temporarily disable blocks of code or do insert documentation into your source code.

    This is a {% comment %} secret {% endcomment %}line of text.

For more, see Solution::Tag::Comment.

if / elseif / else

    {% if post.body contains search_string %}
        <div class="post result" id="p-{{post.id}}">
            <p class="title">{{ post.title }}</p>
            ...
        </div>
    {% endunless %}

unless / elseif / else

This is sorta the opposite of if.

    {% unless some.value == 3 %}
        Well, the value sure ain't three.
    {% elseif some.value > 1 %}
        It's greater than one.
    {% else %}
       Well, is greater than one but not equal to three.
       Psst! It's {{some.value}}.
    {% endunless %}

For more, see Solution::Tag::Unless.

case

TODO

cycle

TODO

for

TODO

assign

TODO

capture

TODO

include

TODO

Extending Solution with Custom Tags

To create a new tag, simply inherit from Solution::Tag and register your block globallyregister_tag( ... )"> or locally with Solution::Template.

Your constructor should expect the following arguments:

$class

...you know what to do with this.

$args

This is a hash ref which contains these values (at least)

attrs

The attributes within the tag. For example, given {% for x in (1..10)%}, you would find x in (1..10) in the attrs value.

parent

The direct parent of this new node.

markup

The tag as it appears in the template. For example, given {% for x in (1..10)%}, the full markup would be {% for x in (1..10)%}.

tag_name

The name of the current tag. For example, given {% for x in (1..10)%}, the tag_name would be for.

template

A quick link back to the top level template object.

Your object should at least contain the parent and template values handed to you in $args. For completeness, you should also include a name (defined any way you want) and the $markup and tag_name from the $args variable.

Enough jibba jabba... here's some functioning code...

    package SolutionX::Tag::Random;
    use strict;
    use warnings;
    our @ISA = qw[Solution::Tag];
    Solution->register_tag('random') if $Solution::VERSION;

    sub new {
        my ($class, $args) = @_;
        $args->{'attrs'} ||= 50;
        my $self = bless {
                          max      => $args->{'attrs'},
                          name     => 'rand-' . $args->{'attrs'},
                          tag_name => $args->{'tag_name'},
                          parent   => $args->{'parent'},
                          template => $args->{'template'},
                          markup   => $args->{'markup'}
        }, $class;
        return $self;
    }

    sub render {
        my ($self) = @_;
        return int rand $self->resolve($self->{'max'});
    }
    1;

Using this new tag is as simple as...

    use Solution;
    use SolutionX::Tag::Random;

    print Solution::Template->parse('{% random max %}')->render({max => 30});

This will print a random integer between 0 and 30.

Creating Your Own Tag Blocks

If you just want a quick sample, see examples/custom_tag.pl. There you'll find an example {^% dump var %} tag named SolutionX::Tag::Dump.

Block-like tags are very similar to simple. Inherit from Solution::Tag and register your block globally or locally with Solution::Template.

The only difference is you define an end_tag in your object.

Here's an example...

    package SolutionX::Tag::Large::Hadron::Collider;
    use strict;
    use warnings;
    our @ISA = qw[Solution::Tag];
    Solution->register_tag('lhc') if $Solution::VERSION;

    sub new {
        my ($class, $args) = @_;
        my $self = bless {
                          odds     => $args->{'attrs'},
                          name     => 'LHC-' . $args->{'attrs'},
                          tag_name => $args->{'tag_name'},
                          parent   => $args->{'parent'},
                          template => $args->{'template'},
                          markup   => $args->{'markup'},
                          end_tag  => 'end' . $args->{'tag_name'}
        }, $class;
        return $self;
    }

    sub render {
        my ($self) = @_;
        return if int rand $self->resolve($self->{'odds'});
        return join '', @{$self->{'nodelist'}};
    }
    1;

Using this example tag...

    use Solution;
    use SolutionX::Tag::Large::Hadron::Collider;

    warn Solution::Template->parse(q[{% lhc 2 %}Now, that's money well spent!{% endlhc %}])->render();

Just like the real thing, our lhc tag works only 50% of the time.

The biggest changes between this and the random tag we build above are in the constructor.

The extra end_tag attribute in the object's reference lets the parser know that this is a block that will slurp until the end tag is found. In our example, we use 'end' . $args-{'tag_name'}> because you may eventually subclass this tag and let it inherit this constructor. Now that we're sure the parser knows what to look for, we go ahead and continue parsing the list of tokens. The parser will shove child nodes (tags, variables, and simple strings) onto your stack until the end_tag is found.

In the render step, we must return the stringification of all child nodes pushed onto the stack by the parser.

Creating Your Own Conditional Tag Blocks

The internals are still kinda rough around this bit so documenting it is on my TODO list. If you're a glutton for punishment, I guess you can skim the source for the if tag and its subclass, the unless tag.

Author

Sanko Robinson <sanko@cpan.org> - http://sankorobinson.com/

The original Liquid template system was developed by jadedPixel (http://jadedpixel.com/) and Tobias Lütke (http://blog.leetsoft.com/).

License and Legal

Copyright (C) 2009,2010 by Sanko Robinson <sanko@cpan.org>

This program is free software; you can redistribute it and/or modify it under the terms of The Artistic License 2.0. See the LICENSE file included with this distribution or http://www.perlfoundation.org/artistic_license_2_0. For clarification, see http://www.perlfoundation.org/artistic_2_0_notes.

When separated from the distribution, all original POD documentation is covered by the Creative Commons Attribution-Share Alike 3.0 License. See http://creativecommons.org/licenses/by-sa/3.0/us/legalcode. For clarification, see http://creativecommons.org/licenses/by-sa/3.0/us/.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 269:

Non-ASCII character seen before =encoding in 'Lütke'. Assuming UTF-8