File Coverage

blib/lib/Template/Liquid/Tag.pm
Criterion Covered Total %
statement 11 14 78.5
branch n/a
condition 4 4 100.0
subroutine 5 8 62.5
pod 0 5 0.0
total 20 31 64.5


line stmt bran cond sub pod time code
1             package Template::Liquid::Tag;
2             our $VERSION = '1.0.23';
3 25     25   182 use strict;
  25         66  
  25         830  
4 25     25   146 use warnings;
  25         63  
  25         764  
5 25     25   139 use base 'Template::Liquid::Document';
  25         74  
  25         7873  
6 0     0 0 0 sub tag { return $_[0]->{'tag_name'}; }
7 436   100 436 0 3130 sub end_tag { return $_[0]->{'end_tag'} || undef; }
8 473   100 473 0 2444 sub conditional_tag { return $_[0]->{'conditional_tag'} || undef; }
9              
10             # Should be overridden by child classes
11             sub new {
12             return
13             Template::Liquid::Error->new(
14             {type => 'Subclass',
15             template => $_[0]->{template},
16 0     0 0   message => 'Please define a constructor in ' . $_[0]
17             }
18             );
19             }
20              
21             sub push_block {
22             return
23             Template::Liquid::Error->new(
24             {type => 'Subclass',
25             template => $_[0]->{template},
26 0     0 0   message =>
27             'Please define a push_block method (for conditional tags) in ' .
28             $_[0]
29             }
30             );
31             }
32             1;
33              
34             =pod
35              
36             =encoding UTF-8
37              
38             =begin stopwords
39              
40             Lütke jadedPixel kinda jibba jabba
41              
42             =end stopwords
43              
44             =head1 NAME
45              
46             Template::Liquid::Tag - Documentation for Template::Liquid's Standard Tagsets
47              
48             =head1 Description
49              
50             Tags are used for the logic in your L<template|Template::Liquid>. For a list of
51             standard tags, see the L<Liquid|Template::Liquid/"Standard Tagset">
52             documentation.
53              
54             =head1 Extending the Basic Liquid Syntax with Custom Tags
55              
56             To create a new tag, simply inherit from
57             L<Template::Liquid::Tag|Template::Liquid::Tag> and register your block
58             L<globally|Template::Liquid/"Template::Liquid::register_tag( ... )">.
59              
60             For a complete example of this, keep reading. To see real world examples, check
61             out L<Template::LiquidX::Tag::Include> and L<Template::LiquidX::Tag::Dump> on
62             CPAN.
63              
64             Your constructor should expect the following arguments:
65              
66             =over 4
67              
68             =item C<$class>
69              
70             ...you know what to do with this.
71              
72             =item C<$args>
73              
74             This is a hash ref which contains these values (at least)
75              
76             =over 4
77              
78             =item C<attrs>
79              
80             The attributes within the tag. For example, given C<{% for x in (1..10)%}>, you
81             would find C<x in (1..10)> in the C<attrs> value.
82              
83             =item C<parent>
84              
85             The direct parent of this new node.
86              
87             =item C<markup>
88              
89             The tag as it appears in the template. For example, given C<{% for x in
90             (1..10)%}>, the full C<markup> would be C<{% for x in (1..10)%}>.
91              
92             =item C<tag_name>
93              
94             The name of the current tag. For example, given C<{% for x in (1..10)%}>, the
95             C<tag_name> would be C<for>.
96              
97             =item C<template>
98              
99             A quick link back to the top level template object.
100              
101             =back
102              
103             =back
104              
105             Your object should at least contain the C<parent> and C<template> values handed
106             to you in C<$args>. For completeness, you should also include a C<name>
107             (defined any way you want) and the C<$markup> and C<tag_name> from the C<$args>
108             variable.
109              
110             Enough jibba jabba... the next few sections show actual code...
111              
112             =head2
113              
114             package Template::LiquidX::Tag::Random;
115             use base 'Template::Liquid::Tag';
116             sub import { Template::Liquid::register_tag('random') }
117              
118             sub new {
119             my ($class, $args) = @_;
120             $args->{'attrs'} ||= 50;
121             my $s = bless {
122             max => $args->{'attrs'},
123             name => 'rand-' . $args->{'attrs'},
124             tag_name => $args->{'tag_name'},
125             parent => $args->{'parent'},
126             template => $args->{'template'},
127             markup => $args->{'markup'}
128             }, $class;
129             return $s;
130             }
131              
132             sub render {
133             my ($s) = @_;
134             return int rand $s->{template}{context}->get($s->{'max'});
135             }
136             1;
137              
138             Using this new tag is as simple as...
139              
140             use Template::Liquid;
141             use Template::LiquidX::Tag::Random;
142              
143             print Template::Liquid->parse('{% random max %}')->render(max => 30);
144              
145             This will print a random integer between C<0> and C<30>.
146              
147             =head2 User-defined, Balanced (Block-like) Tags
148              
149             If you just want a quick sample, you'll find an example C<{^% dump var %}> tag
150             bundled as a separate dist named C<Template::LiquidX::Tag::Dump> on CPAN.
151              
152             Block-like tags are very similar to L<simple|Template::Liquid::Tag/"Create Your
153             Own Tags">. Inherit from L<Template::Liquid::Tag|Template::Liquid::Tag> and
154             register your block L<globally|Template::Liquid/"register_tag">.
155              
156             The only difference is you define an C<end_tag> in your object.
157              
158             Here's an example...
159              
160             package Template::LiquidX::Tag::Random;
161             use base 'Template::Liquid::Tag';
162             sub import { Template::Liquid::register_tag('random') }
163              
164             sub new {
165             my ($class, $args) = @_;
166             raise Template::Liquid::Error {
167             template => $s->{template},
168             type => 'Syntax',
169             message => 'Missing argument list in ' . $args->{'markup'},
170             fatal => 1
171             }
172             if !defined $args->{'attrs'} || $args->{'attrs'} !~ m[\S$]o;
173             my $s = bless {odds => $args->{'attrs'},
174             name => 'Rand-' . $args->{'attrs'},
175             tag_name => $args->{'tag_name'},
176             parent => $args->{'parent'},
177             template => $args->{'template'},
178             markup => $args->{'markup'},
179             end_tag => 'end' . $args->{'tag_name'}
180             }, $class;
181             return $s;
182             }
183              
184             sub render {
185             my $s = shift;
186             my $return = '';
187             if (!int rand $s->{template}{context}->get($s->{'odds'})) {
188             for my $node (@{$s->{'nodelist'}}) {
189             my $rendering = ref $node ? $node->render() : $node;
190             $return .= defined $rendering ? $rendering : '';
191             }
192             }
193             $return;
194             }
195             1;
196              
197             Using this example tag...
198              
199             use Template::Liquid;
200             use Template::LiquidX::Tag::Random;
201              
202             print Template::Liquid->parse(q[{% random 2 %}Now, that's money well spent!{% endrandom %}])->render();
203              
204             In this example, we expect a single argument. During the render stage, we
205             resolve the variable (this allows for constructs like: C<{% random value
206             %}...>) and depending on a call to C<rand($odds)> the tag either renders to an
207             empty string or we continue to render the child nodes. Here, our C<random> tag
208             prints only 50% of the time, C<{% random 1 %}> would work every time.
209              
210             The biggest changes between this and the L<random tag|Template::Liquid/"Create
211             Your Own Tags"> we build above are in the constructor.
212              
213             The extra C<end_tag> attribute in the object's reference lets the parser know
214             that this is a block that will slurp until the end tag is found. In our
215             example, we use C<'end' . $args->{'tag_name'}> because you may eventually
216             subclass this tag and let it inherit this constructor. Now that we're sure the
217             parser knows what to look for, we go ahead and continue
218             L<parsing|Template::Liquid/"parse"> the list of tokens. The parser will shove
219             child nodes (L<tags|Template::Liquid::Tag>,
220             L<variables|Template::Liquid::Variable>, and simple strings) onto your stack
221             until the C<end_tag> is found.
222              
223             In the render step, we must return the stringification of all child nodes
224             pushed onto the stack by the parser.
225              
226             =head2 Creating Your Own Conditional Tag Blocks
227              
228             The internals are still kinda rough around this bit so documenting it is on my
229             TODO list. If you're a glutton for punishment, I guess you can skim the source
230             for the L<if tag|Template::Liquid::Tag::If> and its subclass, the L<unless
231             tag|Template::Liquid::Tag::Unless>.
232              
233             =head1 Author
234              
235             Sanko Robinson <sanko@cpan.org> - http://sankorobinson.com/
236              
237             The original Liquid template system was developed by jadedPixel
238             (http://jadedpixel.com/) and Tobias Lütke (http://blog.leetsoft.com/).
239              
240             =head1 License and Legal
241              
242             Copyright (C) 2009-2022 by Sanko Robinson E<lt>sanko@cpan.orgE<gt>
243              
244             This program is free software; you can redistribute it and/or modify it under
245             the terms of The Artistic License 2.0. See the F<LICENSE> file included with
246             this distribution or http://www.perlfoundation.org/artistic_license_2_0. For
247             clarification, see http://www.perlfoundation.org/artistic_2_0_notes.
248              
249             When separated from the distribution, all original POD documentation is covered
250             by the Creative Commons Attribution-Share Alike 3.0 License. See
251             http://creativecommons.org/licenses/by-sa/3.0/us/legalcode. For clarification,
252             see http://creativecommons.org/licenses/by-sa/3.0/us/.
253              
254             =cut