File Coverage

blib/lib/Template/Liquid.pm
Criterion Covered Total %
statement 86 86 100.0
branch 4 4 100.0
condition 1 3 33.3
subroutine 28 28 100.0
pod 3 7 42.8
total 122 128 95.3


line stmt bran cond sub pod time code
1             our $VERSION = '1.0.21';
2             use strict;
3 24     24   2024959 use warnings;
  24         257  
  24         576  
4 24     24   135 our (%tags, %filters);
  24         49  
  24         882  
5             #
6             use Template::Liquid::Document;
7 24     24   8851 use Template::Liquid::Context;
  24         57  
  24         598  
8 24     24   9816 use Template::Liquid::Tag;
  24         55  
  24         719  
9 24     24   9550 use Template::Liquid::Block;
  24         56  
  24         544  
10 24     24   8262 use Template::Liquid::Condition;
  24         65  
  24         570  
11 24     24   9747 use Template::Liquid::Tag::Assign;
  24         60  
  24         1540  
12 313     313 1 9336 use Template::Liquid::Tag::Break;
13 588     588 0 4133 use Template::Liquid::Tag::Capture;
14 24     24   9423 use Template::Liquid::Tag::Case;
  24         53  
  24         91  
15 24     24   8518 use Template::Liquid::Tag::Comment;
  24         56  
  24         89  
16 24     24   8590 use Template::Liquid::Tag::Continue;
  24         57  
  24         148  
17 24     24   9031 use Template::Liquid::Tag::Cycle;
  24         68  
  24         125  
18 24     24   9003 use Template::Liquid::Tag::Decrement;
  24         51  
  24         81  
19 24     24   8381 use Template::Liquid::Tag::For;
  24         54  
  24         78  
20 24     24   8527 use Template::Liquid::Tag::If;
  24         56  
  24         101  
21 24     24   8341 use Template::Liquid::Tag::Increment;
  24         56  
  24         119  
22 24     24   9021 use Template::Liquid::Tag::Raw;
  24         61  
  24         85  
23 24     24   110 use Template::Liquid::Tag::Unless;
  24         41  
  24         90  
24 24     24   104  
  24         40  
  24         120  
25 24     24   8383 # merge
  24         55  
  24         83  
26 24     24   8289 use Template::Liquid::Filters;
  24         57  
  24         75  
27 24     24 1 6661 #
28 185     185 0 3251 my ($class) = @_;
29             my $s = bless {break => 0,
30             continue => 0,
31 24     24   10572 tags => {},
  24         65  
  24         173  
32             filters => {},
33             line => 1,
34 361     361 0 862 column => 0
35 361         1395 }, $class;
36             return $s;
37             }
38              
39             my ($class, $source) = @_;
40             my $s = ref $class ? $class : $class->new();
41             my @tokens = Template::Liquid::Utility::tokenize($source);
42 361         644 $s->{'document'} ||= Template::Liquid::Document->new({template => $s});
43             $s->{'document'}->parse(\@tokens);
44             return $s;
45             }
46 359     359 0 540443  
47 359 100       968 my ($s, %assigns) = @_;
48 359         1112 my $result;
49 359   33     2057 if (!$s->{context}) {
50 359         1264 $s->{context}
51 359         2184 = Template::Liquid::Context->new(template => $s,
52             assigns => \%assigns);
53             $result = $s->{document}->render();
54             }
55 376     376 1 1262 else {
56 376         482 # This is quite similar to $s->{context}->block(), but
57 376 100       794 # we want %assigns to override what is currently in the scope
58             my $old_scope = $s->{context}->{scopes}->[-1];
59 358         1086 $s->{context}->push({%$old_scope, %assigns});
60             $result = $s->{document}->render();
61 358         846 $s->{context}->pop;
62             }
63             return $result;
64             }
65             1;
66 18         34  
67 18         151 =pod
68 18         57  
69 18         73 =encoding UTF-8
70              
71 376         2275 =begin stopwords
72              
73             sorta whitespace non-evaling
74              
75             =end stopwords
76              
77             =head1 NAME
78              
79             Template::Liquid - A Simple, Stateless Template System
80              
81             =head1 Synopsis
82              
83             use Template::Liquid;
84             my $template = Template::Liquid->parse(
85             '{% for x in (1..3) reversed %}{{ x }}, {% endfor %}{{ some.text }}');
86             print $template->render(some => {text => 'Contact!'}); # 3, 2, 1, Contact!
87              
88             =head1 Description
89              
90             The original Liquid template engine was crafted for very specific requirements:
91              
92             =over 4
93              
94             =item * It has to have simple markup and beautiful results.
95              
96             Template engines which don't produce good looking results are no fun to use.
97              
98             =item * It needs to be non-evaling and secure.
99              
100             Liquid templates are made so that users can edit them. You don't want to run
101             code on your server which your users wrote.
102              
103             =item * It has to be stateless.
104              
105             The compile and render steps have to be separate so the expensive parsing and
106             compiling can be done once; later on, you can just render it by passing in a
107             hash with local variables and objects.
108              
109             =item * It needs to be able to style email as well as HTML.
110              
111             =back
112              
113             =head1 Getting Started
114              
115             It's very simple to get started. Templates are built and used in two steps:
116             Parse and Render.
117              
118             If you're in a hurry, you could just...
119              
120             use Template::Liquid;
121             print Template::Liquid->parse('Hi, {{name}}!')->render(name => 'Sanko');
122              
123             But because Liquid is stateless, you can split that part. Keep reading.
124              
125             =head2 Parse
126              
127             use Template::Liquid;
128             my $sol = Template::Liquid->new(); # Create a Template::Liquid object
129             $sol->parse('Hi, {{name}}!'); # Parse and compile the template
130              
131             ...or...
132              
133             use Template::Liquid;
134             my $sol = Template::Liquid->parse('Hi, {{name}}!'); # Obj is auto-created
135              
136             The C<parse> step creates a fully compiled template which can be re-used as
137             often as you like. You can store it in memory or in a cache for faster
138             rendering later. Templates are simple, blessed references so you could do...
139              
140             use Template::Liquid;
141             use Data::Dump qw[pp];
142             my $greet = Template::Liquid->parse('Hi, {{name}}!');
143             my $dump = pp($greet);
144              
145             ...store C<$dump> somewhere (a file, database, etc.) and then eval the
146             structure later without doing the 'expensive' parsing step again.
147              
148             =head2 Render
149              
150             To complete our C<$sol> examples from the previous section, rendering a
151             template is as easy as...
152              
153             $sol->render(name => 'Sanko'); # Returns 'Hi, Sanko!'
154             $sol->render(name => 'Megatron'); # Returns 'Hi, Megatron!'
155              
156             All parameters you want Template::Liquid to work with must be passed to the
157             C<render> method. Template::Liquid is a closed ecosystem; it does not know
158             about your local, instance, global, or environment variables. If your template
159             requires any of those, you must pass them along:
160              
161             use Template::Liquid;
162             print Template::Liquid->parse(
163             '@INC: {%for item in inc%}{{item}}, {%endfor%}')
164             ->render(inc => \@INC);
165              
166             =head1 Standard Liquid Tags
167              
168             L<Expanding the list of supported tags|/"Extending Template::Liquid"> is easy
169             but here's the current standard set:
170              
171             =head2 C<comment>
172              
173             Comment tags are simple blocks that do nothing during the L<render|/"Render">
174             stage. Use these to temporarily disable blocks of code or to insert
175             documentation.
176              
177             This is a {% comment %} secret {% endcomment %}line of text.
178              
179             ...renders to...
180              
181             This is a line of text.
182              
183             For more, see L<Template::Liquid::Tag::Comment|Template::Liquid::Tag::Comment>.
184              
185             =head2 C<raw>
186              
187             Raw temporarily disables tag processing. This is useful for generating content
188             (Mustache, Handlebars) which uses conflicting syntax.
189              
190             {% raw %}
191             In Handlebars, {{ this }} will be HTML-escaped, but {{{ that }}} will not.
192             {% endraw %}
193              
194             ...renders to...
195              
196             In Handlebars, {{ this }} will be HTML-escaped, but {{{ that }}} will not.
197              
198             For more, see L<Template::Liquid::Tag::Raw|Template::Liquid::Tag::Raw>.
199              
200             =head2 C<if> / C<elseif> / C<else>
201              
202             {% if post.body contains search_string %}
203             <div class="post result" id="p-{{post.id}}">
204             <p class="title">{{ post.title }}</p>
205             ...
206             </div>
207             {% endunless %}
208              
209             For more, see L<Template::Liquid::Tag::If|Template::Liquid::Tag::If> and
210             L<Template::Liquid::Condition|Template::Liquid::Condition>. .
211              
212             =head2 C<unless> / C<elseif> / C<else>
213              
214             This is sorta the opposite of C<if>.
215              
216             {% unless some.value == 3 %}
217             Well, the value sure ain't three.
218             {% elseif some.value > 1 %}
219             It's greater than one.
220             {% else %}
221             Well, is greater than one but not equal to three.
222             Psst! It's {{some.value}}.
223             {% endunless %}
224              
225             For more, see L<Template::Liquid::Tag::Unless|Template::Liquid::Tag::Unless>
226             and L<Template::Liquid::Condition|Template::Liquid::Condition>.
227              
228             =head2 C<case>
229              
230             If you need more conditions, you can use the case statement:
231              
232             {% case condition %}
233             {% when 1 %}
234             hit 1
235             {% when 2 or 3 %}
236             hit 2 or 3
237             {% else %}
238             ... else ...
239             {% endcase %}
240              
241             For more, see L<Template::Liquid::Tag::Case|Template::Liquid::Tag::Case>.
242              
243             =head2 C<cycle>
244              
245             Often you have to alternate between different colors or similar tasks. Liquid
246             has built-in support for such operations, using the cycle tag.
247              
248             {% cycle 'one', 'two', 'three' %}
249             {% cycle 'one', 'two', 'three' %}
250             {% cycle 'one', 'two', 'three' %}
251             {% cycle 'one', 'two', 'three' %}
252              
253             ...will result in...
254              
255             one
256             two
257             three
258             one
259              
260             If no name is supplied for the cycle group, then it's assumed that multiple
261             calls with the same parameters are one group.
262              
263             If you want to have total control over cycle groups, you can optionally specify
264             the name of the group. This can even be a variable.
265              
266             {% cycle 'group 1': 'one', 'two', 'three' %}
267             {% cycle 'group 1': 'one', 'two', 'three' %}
268             {% cycle 'group 2': 'one', 'two', 'three' %}
269             {% cycle 'group 2': 'one', 'two', 'three' %}
270              
271             ...will result in...
272              
273             one
274             two
275             one
276             two
277              
278             For more, see L<Template::Liquid::Tag::Cycle|Template::Liquid::Tag::Cycle>.
279              
280             =head2 C<increment>
281              
282             Creates a new number variable, and increases its value by one every time it is
283             called. The initial value is C<0>.
284              
285             {% increment my_counter %}
286             {% increment my_counter %}
287             {% increment my_counter %}
288              
289             ...would become...
290              
291             0
292             1
293             2
294              
295             =head2 C<decrement>
296              
297             Creates a new number variable, and decreases its value by one every time it is
298             called. The initial value is C<-1>.
299              
300             {% decrement variable %}
301             {% decrement variable %}
302             {% decrement variable %}
303              
304             ...would become...
305              
306             -1
307             -2
308             -3
309              
310             For more, see
311             L<Template::Liquid::Tag::Decrement|Template::Liquid::Tag::Decrement>.
312              
313             =head2 C<for>
314              
315             Liquid allows for loops over collections:
316              
317             {% for item in array %}
318             {{ item }}
319             {% endfor %}
320              
321             Please see see L<Template::Liquid::Tag::For|Template::Liquid::Tag::For>.
322              
323             =head2 C<assign>
324              
325             You can store data in your own variables, to be used in output or other tags as
326             desired. The simplest way to create a variable is with the assign tag, which
327             has a pretty straightforward syntax:
328              
329             {% assign name = 'freestyle' %}
330              
331             {% for t in collections.tags %}{% if t == name %}
332             <p>Freestyle!</p>
333             {% endif %}{% endfor %}
334              
335             Another way of doing this would be to assign true / false values to the
336             variable:
337              
338             {% assign freestyle = false %}
339              
340             {% for t in collections.tags %}{% if t == 'freestyle' %}
341             {% assign freestyle = true %}
342             {% endif %}{% endfor %}
343              
344             {% if freestyle %}
345             <p>Freestyle!</p>
346             {% endif %}
347              
348             If you want to combine a number of strings into a single string and save it to
349             a variable, you can do that with the capture tag.
350              
351             For more, see L<Template::Liquid::Tag::Assign|Template::Liquid::Tag::Assign>.
352              
353             =head2 C<capture>
354              
355             This tag is a block which "captures" whatever is rendered inside it, then
356             assigns the captured value to the given variable instead of rendering it to the
357             screen.
358              
359             {% capture attribute_name %}{{ item.title | handleize }}-{{ i }}-color{% endcapture %}
360              
361             <label for="{{ attribute_name }}">Color:</label>
362             <select name="attributes[{{ attribute_name }}]" id="{{ attribute_name }}">
363             <option value="red">Red</option>
364             <option value="green">Green</option>
365             <option value="blue">Blue</option>
366             </select>
367              
368             For more, see L<Template::Liquid::Tag::Capture|Template::Liquid::Tag::Capture>.
369              
370             =head1 Standard Liquid Filters
371              
372             Please see L<Template::Liquid::Filters|Template::Liquid::Filters>.
373              
374             =head1 Whitespace Control
375              
376             In Liquid, you can include a hyphen in your tag syntax C<{{->, C<-}}>, C<{%->,
377             and C<-%}> to strip whitespace from the left or right side of a rendered tag.
378              
379             See https://shopify.github.io/liquid/basics/whitespace/
380              
381             =head1 Extending Template::Liquid
382              
383             Extending the Template::Liquid template engine for your needs is almost too
384             simple. Keep reading.
385              
386             =head2 Custom Tags
387              
388             See the section entitled L<Extending Template::Liquid with Custom
389             Tags|Template::Liquid::Tag/"Extending Template::Liquid with Custom Tags"> in
390             L<Template::Liquid::Tag> for more information.
391              
392             Also check out the examples of L<Template::LiquidX::Tag::Dump> and
393             L<Template::LiquidX::Tag::Include> now on CPAN.
394              
395             To assist with custom tag creation, Template::Liquid provides several basic tag
396             types for subclassing and exposes the following methods:
397              
398             =head3 C<< Template::Liquid::register_tag( ... ) >>
399              
400             This registers a package which must contain (directly or through inheritance)
401             both a C<parse> and C<render> method.
402              
403             # Register a new tag which Template::Liquid will look for in the calling package
404             Template::Liquid::register_tag( 'newtag' );
405              
406             # Or simply say...
407             Template::Liquid::register_tag( 'newtag' );
408             # ...and Template::Liquid will assume the new tag is in the calling package
409              
410             Pre-existing tags are replaced when new tags are registered with the same name.
411             You may want to do this to override some functionality.
412              
413             =head2 Custom Filters
414              
415             Filters are simple subs called when needed. They are not passed any state data
416             by design and must return the modified content.
417              
418             =for todo I need to write Template::Liquid::Filter which will be POD with all sorts of info in it. Yeah.
419              
420             =head3 C<< Template::Liquid::register_filter( ... ) >>
421              
422             This registers a package which Template::Liquid will assume contains one or
423             more filters.
424              
425             # Register a package as a filter
426             Template::Liquid::register_filter( 'Template::Solution::Filter::Amalgamut' );
427              
428             # Or simply say...
429             Template::Liquid::register_filter( );
430             # ...and Template::Liquid will assume the filters are in the calling package
431              
432             =head1 Why should I use Template::Liquid?
433              
434             =over 4
435              
436             =item * You want to allow your users to edit the appearance of your
437             application, but don't want them to run insecure code on your server.
438              
439             =item * You want to render templates directly from the database.
440              
441             =item * You like Smarty-style template engines.
442              
443             =item * You need a template engine which does HTML just as well as email.
444              
445             =item * You don't like the markup language of your current template engine.
446              
447             =item * You wasted three days reinventing this wheel when you could have been
448             doing something productive like volunteering or catching up on past seasons of
449             I<Doctor Who>.
450              
451             =back
452              
453             =head1 Why shouldn't I use Template::Liquid?
454              
455             =over 4
456              
457             =item * You've found or written a template engine which fills your needs
458             better than Liquid or Template::Liquid ever could.
459              
460             =item * You are uncomfortable with text that you didn't copy and paste
461             yourself. Everyone knows computers cannot be trusted.
462              
463             =back
464              
465             =head1 Template::LiquidX or Solution?
466              
467             I'd really rather use Solution::{Package} for extensions but Template::LiquidX
468             really is a better choice.
469              
470             As I understand it, the original project's name, Liquid, is a reference to the
471             classical states of matter (the engine itself being stateless). I wanted to use
472             L<solution|http://en.wikipedia.org/wiki/Solution> because it's liquid but with
473             bits of other stuff floating in it. (Pretend you majored in chemistry instead
474             of mathematics or computer science.) Liquid templates will I<always> work with
475             Template::Liquid but (due to Template::LiquidX's expanded syntax)
476             Template::LiquidX templates I<may not> be compatible with Liquid or
477             Template::Liquid.
478              
479             =head1 Author
480              
481             Sanko Robinson <sanko@cpan.org> - http://sankorobinson.com/
482              
483             CPAN ID: SANKO
484              
485             =encoding utf8
486              
487             The original Liquid template system was developed by
488             L<jadedPixel|http://jadedpixel.com/> and L<Tobias
489             Lütke|http://blog.leetsoft.com/>.
490              
491             =head1 License and Legal
492              
493             Copyright (C) 2009-2022 by Sanko Robinson <sanko@cpan.org>
494              
495             This program is free software; you can redistribute it and/or modify it under
496             the terms of L<The Artistic License
497             2.0|http://www.perlfoundation.org/artistic_license_2_0>. See the F<LICENSE>
498             file included with this distribution or L<notes on the Artistic License
499             2.0|http://www.perlfoundation.org/artistic_2_0_notes> for clarification.
500              
501             When separated from the distribution, all original POD documentation is covered
502             by the L<Creative Commons Attribution-Share Alike 3.0
503             License|http://creativecommons.org/licenses/by-sa/3.0/us/legalcode>. See the
504             L<clarification of the
505             CCA-SA3.0|http://creativecommons.org/licenses/by-sa/3.0/us/>.
506              
507             =cut