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