line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
our $VERSION = '1.0.21'; |
2
|
|
|
|
|
|
|
use strict; |
3
|
24
|
|
|
24
|
|
136
|
use warnings; |
|
24
|
|
|
|
|
36
|
|
|
24
|
|
|
|
|
573
|
|
4
|
24
|
|
|
24
|
|
99
|
|
|
24
|
|
|
|
|
37
|
|
|
24
|
|
|
|
|
79480
|
|
5
|
|
|
|
|
|
|
Template::Liquid::register_filter( |
6
|
|
|
|
|
|
|
qw[ |
7
|
24
|
|
|
24
|
|
121
|
abs append at_least at_most |
8
|
|
|
|
|
|
|
capitalize ceil compact concat |
9
|
|
|
|
|
|
|
date default divided_by downcase |
10
|
|
|
|
|
|
|
escape escape_once |
11
|
|
|
|
|
|
|
first floor |
12
|
|
|
|
|
|
|
join |
13
|
|
|
|
|
|
|
last lstrip |
14
|
|
|
|
|
|
|
map minus modulo |
15
|
|
|
|
|
|
|
newline_to_br |
16
|
|
|
|
|
|
|
plus prepend |
17
|
|
|
|
|
|
|
remove remove_first replace replace_first reverse round rstrip |
18
|
|
|
|
|
|
|
size slice sort sort_natural split strip strip_html strip_newlines |
19
|
|
|
|
|
|
|
times truncate truncatewords |
20
|
|
|
|
|
|
|
uniq upcase url_decode url_encode |
21
|
|
|
|
|
|
|
where |
22
|
|
|
|
|
|
|
money stock_price |
23
|
|
|
|
|
|
|
] |
24
|
|
|
|
|
|
|
); |
25
|
|
|
|
|
|
|
} |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=pod |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=encoding UTF-8 |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=begin stopwords |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
Lütke jadedPixel truthy html newlines endcapture vs |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=end stopwords |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head1 NAME |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
Template::Liquid::Filters - Default Filters Based on Liquid's Standard Set |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=head1 Synopsis |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
Filters are simple methods that modify the output of numbers, strings, |
44
|
|
|
|
|
|
|
variables and objects. They are placed within an output tag C<{{ }}> and are |
45
|
|
|
|
|
|
|
denoted by a pipe character C<|>. |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
# product.title = "Awesome Shoes" |
48
|
|
|
|
|
|
|
{{ product.title | upcase }} |
49
|
|
|
|
|
|
|
# Output: AWESOME SHOES |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
In the example above, C<product> is the object, C<title> is its attribute, and |
52
|
|
|
|
|
|
|
C<upcase> is the filter being applied. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
Some filters require a parameter to be passed. |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
{{ product.title | remove: "Awesome" }} |
57
|
|
|
|
|
|
|
# Output: Shoes |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
Multiple filters can be used on one output. They are applied from left to |
60
|
|
|
|
|
|
|
right. |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
{{ product.title | upcase | remove: "AWESOME" }} |
63
|
|
|
|
|
|
|
# SHOES |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=head1 Standard Filters |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
These are the current default filters. They have been written to behave exactly |
69
|
|
|
|
|
|
|
like their Ruby Liquid counterparts accept where Perl makes improvement |
70
|
|
|
|
|
|
|
irresistible. |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=head2 C<abs> |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
Returns the absolute value of a number. |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
{{ 4 | abs }} => 4 |
77
|
|
|
|
|
|
|
{{ -4 | abs }} => 4 |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=cut |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=head2 C<append> |
83
|
2
|
|
|
2
|
1
|
7
|
|
84
|
|
|
|
|
|
|
Append a string. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
{{ 'foo' | append:'bar' }} => 'foobar' |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=cut |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=head2 C<at_least> |
92
|
|
|
|
|
|
|
|
93
|
1
|
50
|
|
1
|
1
|
4
|
Limits a number to a minimum value. |
|
1
|
|
|
|
|
5
|
|
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
{{ 4 | at_least: 5 }} => 5 |
96
|
|
|
|
|
|
|
{{ 4 | at_least: 3 }} => 4 |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=cut |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
my ($value, $min) = @_; |
101
|
|
|
|
|
|
|
$min > $value ? $min : $value; |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=head2 C<at_most> |
105
|
2
|
|
|
2
|
1
|
8
|
|
106
|
2
|
100
|
|
|
|
7
|
Limits a number to a maximum value. |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
{{ 4 | at_most: 5 }} => 4 |
109
|
|
|
|
|
|
|
{{ 4 | at_most: 3 }} => 3 |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=cut |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
my ($value, $max) = @_; |
114
|
|
|
|
|
|
|
$max < $value ? $max : $value; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=head2 C<capitalize> |
118
|
|
|
|
|
|
|
|
119
|
2
|
|
|
2
|
1
|
8
|
Capitalize words in the input sentence. This filter first applies Perl's C<lc> |
120
|
2
|
100
|
|
|
|
8
|
function and then the C<ucfirst> function. |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
{{ 'this is ONLY a test.' | capitalize }} => This is only a test. |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=cut |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=head2 C<ceil> |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
Rounds an integer up to the nearest integer. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
{{ 4.6 | ceil }} => 5 |
132
|
3
|
|
|
3
|
1
|
9
|
{{ 4.3 | ceil }} => 5 |
|
3
|
|
|
|
|
12
|
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=cut |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=head2 C<compact> |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
Removes any undefined values from an array. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
For this example, assume C<site.pages> is an array of content pages for a |
142
|
|
|
|
|
|
|
website, and some of these pages have an attribute called category that |
143
|
4
|
100
|
|
4
|
1
|
7
|
specifies their content category. If we map those categories to an array, some |
|
4
|
|
|
|
|
28
|
|
144
|
|
|
|
|
|
|
of the array items might be undefined if any pages do not have a category |
145
|
|
|
|
|
|
|
attribute. |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
{% assign all_categories = site.pages | map: "category" %} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
{% for item in all_categories %} |
150
|
|
|
|
|
|
|
- {{ item }} |
151
|
|
|
|
|
|
|
{% endfor %} |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
The output of this template would look like this: |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
- business |
156
|
|
|
|
|
|
|
- celebrities |
157
|
|
|
|
|
|
|
- |
158
|
|
|
|
|
|
|
- lifestyle |
159
|
|
|
|
|
|
|
- sports |
160
|
|
|
|
|
|
|
- |
161
|
|
|
|
|
|
|
- technology |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
By using compact when we create our C<site_categories> array, we can remove all |
164
|
|
|
|
|
|
|
the nil values in the array. |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
{% assign all_categories = site.pages | map: "category" | compact %} |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
{% for item in all_categories %} |
169
|
|
|
|
|
|
|
- {{ item }} |
170
|
|
|
|
|
|
|
{% endfor %} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
The output of this template would look like this: |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
- business |
175
|
|
|
|
|
|
|
- celebrities |
176
|
|
|
|
|
|
|
- lifestyle |
177
|
|
|
|
|
|
|
- sports |
178
|
|
|
|
|
|
|
- technology |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=cut |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
my ($list) = @_; |
183
|
|
|
|
|
|
|
[grep { defined $_ } @$list]; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=head2 C<concat> |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
Concatenates (joins together) multiple arrays. The resulting array contains all |
189
|
|
|
|
|
|
|
the items from the input arrays. |
190
|
|
|
|
|
|
|
|
191
|
1
|
|
|
1
|
1
|
3
|
|
192
|
1
|
|
|
|
|
3
|
{% assign fruits = "apples, oranges, peaches" | split: ", " %} |
|
7
|
|
|
|
|
12
|
|
193
|
|
|
|
|
|
|
{% assign vegetables = "carrots, turnips, potatoes" | split: ", " %} |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
{% assign everything = fruits | concat: vegetables %} |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
{% for item in everything %} |
198
|
|
|
|
|
|
|
- {{ item }} |
199
|
|
|
|
|
|
|
{% endfor %} |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
...becomes... |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
- apples |
204
|
|
|
|
|
|
|
- oranges |
205
|
|
|
|
|
|
|
- peaches |
206
|
|
|
|
|
|
|
- carrots |
207
|
|
|
|
|
|
|
- turnips |
208
|
|
|
|
|
|
|
- potatoes |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
You can string together two or more array elements with the C<concat> filter: |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
{% assign furniture = "chairs, tables, shelves" | split: ", " %} |
213
|
|
|
|
|
|
|
{% assign vegetables = "carrots, turnips, potatoes" | split: ", " %} |
214
|
|
|
|
|
|
|
{% assign fruits = "apples, oranges, peaches" | split: ", " %} |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
{% assign everything = fruits | concat: vegetables | concat: furniture %} |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
{% for item in everything %} |
219
|
|
|
|
|
|
|
- {{ item }} |
220
|
|
|
|
|
|
|
{% endfor %} |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
...becomes... |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
- apples |
225
|
|
|
|
|
|
|
- oranges |
226
|
|
|
|
|
|
|
- peaches |
227
|
|
|
|
|
|
|
- carrots |
228
|
|
|
|
|
|
|
- turnips |
229
|
|
|
|
|
|
|
- potatoes |
230
|
|
|
|
|
|
|
- chairs |
231
|
|
|
|
|
|
|
- tables |
232
|
|
|
|
|
|
|
- shelves |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=cut |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
my ($values, $more) = @_; |
237
|
|
|
|
|
|
|
[map {@$_} grep {defined} $values, $more]; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=head2 C<date> |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
Converts a timestamp into another date format. The format for this syntax is |
243
|
|
|
|
|
|
|
the same as C<strftime>. |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
{{ article.published_at | date: "%a, %b %d, %y" }} => Fri, Jul 17, 15 |
246
|
3
|
|
|
3
|
1
|
8
|
|
247
|
3
|
|
|
|
|
8
|
{{ article.published_at | date: "%Y" }} => 2015 |
|
6
|
|
|
|
|
16
|
|
|
6
|
|
|
|
|
13
|
|
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
C<date> works on strings if they contain well-formatted dates: |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
{{ "March 14, 2016" | date: "%b %d, %y" }} => Mar 14, 16 |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
Natural language dates are parsed by C<DateTime::Format::Natural>. |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
To get the current time, pass the special word <"now"> (or C<"today">) to date: |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
This page was last updated at {{ "now" | date: "%Y-%m-%d %H:%M" }}. |
259
|
|
|
|
|
|
|
=> This page was last updated at 2019-09-19 17:48. |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
Note that the value will be the current time of when the page was last |
262
|
|
|
|
|
|
|
generated from the template, not when the page is presented to a user if |
263
|
|
|
|
|
|
|
caching or static site generation is involved. |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=cut |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
CORE::state $DateTimeFormatNatural; |
268
|
|
|
|
|
|
|
my ($x, $y) = @_; |
269
|
|
|
|
|
|
|
$x = time() if lc $x eq 'now' || lc $x eq 'today'; |
270
|
|
|
|
|
|
|
if (ref $x ne 'DateTime' && $x =~ m[\D]) { # Any non-digit |
271
|
|
|
|
|
|
|
if (!defined $DateTimeFormatNatural) { |
272
|
|
|
|
|
|
|
require DateTime::Format::Natural; |
273
|
|
|
|
|
|
|
$DateTimeFormatNatural = DateTime::Format::Natural->new(); |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
$x = $DateTimeFormatNatural->parse_datetime($x); |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
# |
278
|
7
|
|
|
7
|
1
|
13
|
$y = defined $y ? $y : '%c'; |
279
|
7
|
|
|
|
|
25
|
return $x->strftime($y) if ref $x && $x->can('strftime'); |
280
|
7
|
100
|
100
|
|
|
25
|
return if $x !~ m[^(\d*\.)?\d+?$]o; |
281
|
7
|
100
|
100
|
|
|
96
|
require POSIX; |
282
|
1
|
50
|
|
|
|
4
|
return POSIX::strftime($y, gmtime($x)); |
283
|
1
|
|
|
|
|
522
|
} |
284
|
1
|
|
|
|
|
38220
|
|
285
|
|
|
|
|
|
|
=head2 C<default> |
286
|
1
|
|
|
|
|
30916
|
|
287
|
|
|
|
|
|
|
Allows you to specify a fallback in case a value doesn't exist. default will |
288
|
|
|
|
|
|
|
show its value if the left side is nil, false, or empty. |
289
|
7
|
50
|
|
|
|
11157
|
|
290
|
7
|
100
|
66
|
|
|
31
|
In this example, C<product_price> is not defined, so the default value is used. |
291
|
5
|
50
|
|
|
|
24
|
|
292
|
5
|
|
|
|
|
27
|
{{ product_price | default: 2.99 }} => 2.99 |
293
|
5
|
|
|
|
|
207
|
|
294
|
|
|
|
|
|
|
In this example, C<product_price> is defined, so the default value is not used. |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
{% assign product_price = 4.99 %} |
297
|
|
|
|
|
|
|
{{ product_price | default: 2.99 }} => 4.99 |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
In this example, C<product_price> is empty, so the default value is used. |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
{% assign product_price = "" %} |
302
|
|
|
|
|
|
|
{{ product_price | default: 2.99 }} => 2.99 |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
=cut |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
my ($x, $y) = @_; |
307
|
|
|
|
|
|
|
return length $x ? $x : $y if !ref $x; |
308
|
|
|
|
|
|
|
return defined $x ? $x : $y; |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=head2 C<divided_by> |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
Divides a number by another number. |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
The result is rounded down to the nearest integer (that is, the floor) if the |
316
|
|
|
|
|
|
|
divisor is an integer. |
317
|
|
|
|
|
|
|
|
318
|
7
|
|
|
7
|
1
|
16
|
{{ 16 | divided_by: 4 }} => 4 |
319
|
7
|
100
|
|
|
|
33
|
|
|
|
50
|
|
|
|
|
|
320
|
0
|
0
|
|
|
|
0
|
|
321
|
|
|
|
|
|
|
{{ 5 | divided_by: 3 }} = 1 |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=head3 Controlling rounding |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
C<divided_by> produces a result of the same type as the divisor -- that is, if |
326
|
|
|
|
|
|
|
you divide by an integer, the result will be an integer. If you divide by a |
327
|
|
|
|
|
|
|
float (a number with a decimal in it), the result will be a float. |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
For example, here the divisor is an integer: |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
{{ 20 | divided_by: 7 }} => 2 |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
Here it is a float: |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
{{ 20 | divided_by: 7.0 }} => 2.85714285714286 |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
Note that floats will not match thanks to how perl and ruby handle floating |
338
|
|
|
|
|
|
|
point numbers. |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
=cut |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
my ($x, $y) = @_; |
343
|
|
|
|
|
|
|
my $r = $x / $y; |
344
|
|
|
|
|
|
|
my ($_x) = $x =~ m[\.(\d+)$]; |
345
|
|
|
|
|
|
|
my ($_y) = $y =~ m[\.(\d+)$]; |
346
|
|
|
|
|
|
|
my ($_r) = $r =~ m[\.(\d+)$]; |
347
|
|
|
|
|
|
|
$_x //= ''; |
348
|
|
|
|
|
|
|
$_y //= ''; |
349
|
|
|
|
|
|
|
$_r //= ''; |
350
|
|
|
|
|
|
|
my $_lx = length $_x; |
351
|
|
|
|
|
|
|
my $_ly = length $_y; |
352
|
|
|
|
|
|
|
my $_lr = length $_r; |
353
|
|
|
|
|
|
|
($_lx || $_ly) |
354
|
|
|
|
|
|
|
? (sprintf '%0.' . ([sort $_lr, 1]->[-1]) . 'f', $r) |
355
|
6
|
|
|
6
|
1
|
15
|
: int $r; |
356
|
6
|
|
|
|
|
20
|
} |
357
|
6
|
|
|
|
|
14
|
|
358
|
6
|
|
|
|
|
12
|
=head2 C<downcase> |
359
|
6
|
|
|
|
|
34
|
|
360
|
6
|
|
50
|
|
|
25
|
Makes each character in a string lowercase. It has no effect on strings which |
361
|
6
|
|
100
|
|
|
19
|
are already all lowercase. |
362
|
6
|
|
100
|
|
|
15
|
|
363
|
6
|
|
|
|
|
9
|
{{ "Parker Moore" | downcase }} => parker moore |
364
|
6
|
|
|
|
|
7
|
|
365
|
6
|
|
|
|
|
7
|
{{ "apple" | downcase }} => apple |
366
|
6
|
100
|
66
|
|
|
43
|
|
367
|
|
|
|
|
|
|
=cut |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
=head2 C<escape> |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
Escapes a string by replacing characters with escape sequences (so that the |
373
|
|
|
|
|
|
|
string can be used in a URL, for example). It doesn't change strings that don't |
374
|
|
|
|
|
|
|
have anything to escape. |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
{{ "Have you read 'James & the Giant Peach'?" | escape }} |
377
|
|
|
|
|
|
|
=> Have you read 'James & the Giant Peach'? |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
{{ "Tetsuro Takara" | escape }} => Tetsuro Takara |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
=cut |
382
|
3
|
|
|
3
|
1
|
7
|
|
|
3
|
|
|
|
|
9
|
|
383
|
|
|
|
|
|
|
my ($x) = @_; |
384
|
|
|
|
|
|
|
$x =~ s/([^A-Za-z0-9\-\._~ \?])/ |
385
|
|
|
|
|
|
|
my $x = ord $1; |
386
|
|
|
|
|
|
|
sprintf('&%s;', |
387
|
|
|
|
|
|
|
$1 eq '&' ? 'amp' : |
388
|
|
|
|
|
|
|
$1 eq '>' ? 'gt' : |
389
|
|
|
|
|
|
|
$1 eq '<' ? 'lt' : |
390
|
|
|
|
|
|
|
$1 eq '"' ? 'quot' : |
391
|
|
|
|
|
|
|
$1 eq "'" ? '#39' : |
392
|
|
|
|
|
|
|
"#$x") |
393
|
|
|
|
|
|
|
/gei; |
394
|
|
|
|
|
|
|
$x; |
395
|
|
|
|
|
|
|
} |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
=head2 C<escape_once> |
398
|
2
|
|
|
2
|
1
|
4
|
|
399
|
2
|
|
|
|
|
8
|
Escapes a string without changing existing escaped entities. It doesn't change |
400
|
3
|
|
|
|
|
7
|
strings that don't have anything to escape. |
401
|
3
|
50
|
|
|
|
20
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
402
|
|
|
|
|
|
|
{{ "1 < 2 & 3" | escape_once }} => 1 < 2 & 3 |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
{{ "1 < 2 & 3" | escape_once }} => 1 < 2 & 3 |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
=cut |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
my ($x) = @_; |
409
|
2
|
|
|
|
|
6
|
$x =~ s/("|>|<|'|&(?!([a-z]+|(#\d+));))/ |
410
|
|
|
|
|
|
|
sprintf('&%s;', |
411
|
|
|
|
|
|
|
$1 eq '&' ? 'amp' : |
412
|
|
|
|
|
|
|
$1 eq '>' ? 'gt' : |
413
|
|
|
|
|
|
|
$1 eq '<' ? 'lt' : |
414
|
|
|
|
|
|
|
$1 eq '"' ? 'quot' : |
415
|
|
|
|
|
|
|
$1 eq "'" ? '#39' : |
416
|
|
|
|
|
|
|
"#$x;") |
417
|
|
|
|
|
|
|
/gei; |
418
|
|
|
|
|
|
|
$x; |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
=head2 C<first> |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
Returns the first item of an array. |
424
|
2
|
|
|
2
|
1
|
4
|
|
425
|
2
|
|
|
|
|
13
|
{{ "Ground control to Major Tom." | split: " " | first }} => Ground |
426
|
2
|
0
|
|
|
|
18
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
{% assign my_array = "zebra, octopus, giraffe, tiger" | split: ", " %} |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
{{ my_array.first }} |
431
|
|
|
|
|
|
|
=> zebra |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
You can use C<first> with dot notation when you need to use the filter inside a |
434
|
2
|
|
|
|
|
9
|
tag: |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
{% if my_array.first == "zebra" %} |
437
|
|
|
|
|
|
|
Here comes a zebra! |
438
|
|
|
|
|
|
|
{% endif %} |
439
|
|
|
|
|
|
|
=> Here comes a zebra! |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
=cut |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
my ($x) = @_; |
444
|
|
|
|
|
|
|
return ref $x eq 'ARRAY' ? @{$x}[0] : substr($x, 0, 1); |
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
=head2 C<floor> |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
Rounds an integer down to the nearest integer. |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
{{ 1.2 | floor }} => 1 |
452
|
|
|
|
|
|
|
{{ 2.0 | floor }} => 2 |
453
|
|
|
|
|
|
|
{{ 183.357 | floor }} => 183 |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
Here the input value is a string: |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
{{ "3.5" | floor }} => 3 |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
=cut |
460
|
4
|
|
|
4
|
1
|
11
|
|
461
|
4
|
100
|
|
|
|
14
|
|
|
3
|
|
|
|
|
10
|
|
462
|
|
|
|
|
|
|
=head2 C<join> |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
Combines the items in an array into a single string using the argument as a |
465
|
|
|
|
|
|
|
separator. |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
{% assign beatles = "John, Paul, George, Ringo" | split: ", " %} |
468
|
|
|
|
|
|
|
{{ beatles | join: " and " }} => John and Paul and George and Ringo |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
=cut |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
my ($x, $y) = @_; |
473
|
|
|
|
|
|
|
return CORE::join($y, @{$x}) if ref $x eq 'ARRAY'; |
474
|
|
|
|
|
|
|
return CORE::join($y, keys %{$x}) if ref $x eq 'HASH'; |
475
|
|
|
|
|
|
|
return $x; |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
|
478
|
4
|
|
|
4
|
1
|
14
|
=head2 C<last> |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
Returns the last item of an array. |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
{{ "Ground control to Major Tom." | split: " " | last }} => Tom. |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
{% assign my_array = "zebra, octopus, giraffe, tiger" | split: ", " %} |
485
|
|
|
|
|
|
|
{{ my_array.last }} => tiger |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
You can use C<last> with dot notation when you need to use the filter inside a |
488
|
|
|
|
|
|
|
tag: |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
{% assign my_array = "zebra, octopus, giraffe, tiger" | split: ", " %} |
491
|
9
|
|
|
9
|
1
|
21
|
{% if my_array.last == "tiger" %} |
492
|
9
|
50
|
|
|
|
23
|
There goes a tiger! |
|
9
|
|
|
|
|
31
|
|
493
|
0
|
0
|
|
|
|
0
|
{% endif %} |
|
0
|
|
|
|
|
0
|
|
494
|
0
|
|
|
|
|
0
|
|
495
|
|
|
|
|
|
|
=cut |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
my ($x, $y) = @_; |
498
|
|
|
|
|
|
|
my $ref = ref $x; |
499
|
|
|
|
|
|
|
return substr $x, -1 if !$ref; |
500
|
|
|
|
|
|
|
return @{$x}[-1] if $ref eq 'ARRAY'; |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
=head2 C<lstrip> |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
Removes all whitespace (tabs, spaces, and newlines) from the left side of a |
506
|
|
|
|
|
|
|
string. It does not affect spaces between words. |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
{{ " So much room for activities! " | lstrip }} |
509
|
|
|
|
|
|
|
=> So much room for activities! |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
=cut |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
my ($x) = @_; |
514
|
|
|
|
|
|
|
$x =~ s[^\s*][]; |
515
|
|
|
|
|
|
|
$x; |
516
|
|
|
|
|
|
|
} |
517
|
4
|
|
|
4
|
1
|
10
|
|
518
|
4
|
|
|
|
|
7
|
=head2 C<map> |
519
|
4
|
100
|
|
|
|
10
|
|
520
|
3
|
50
|
|
|
|
9
|
Creates an array of values by extracting the values of a named property from |
|
3
|
|
|
|
|
8
|
|
521
|
|
|
|
|
|
|
another object. |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
In this example, assume the object C<site.pages> contains all the metadata for |
524
|
|
|
|
|
|
|
a website. Using assign with the map filter creates a variable that contains |
525
|
|
|
|
|
|
|
only the values of the category properties of everything in the site.pages |
526
|
|
|
|
|
|
|
object. |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
{% assign all_categories = site.pages | map: "category" %} |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
{% for item in all_categories %} |
531
|
|
|
|
|
|
|
- {{ item }} |
532
|
|
|
|
|
|
|
{% endfor %} |
533
|
|
|
|
|
|
|
|
534
|
1
|
|
|
1
|
1
|
9
|
The output of this template would look like this: |
535
|
1
|
|
|
|
|
4
|
|
536
|
1
|
|
|
|
|
3
|
- business |
537
|
|
|
|
|
|
|
- celebrities |
538
|
|
|
|
|
|
|
- lifestyle |
539
|
|
|
|
|
|
|
- sports |
540
|
|
|
|
|
|
|
- technology |
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
=cut |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
my ($list, $key) = @_; |
545
|
|
|
|
|
|
|
[map { $_->{$key} } @$list]; |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
=head2 C<minus> |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
Subtracts a number from another number. |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
{{ 4 | minus: 2 }} => 2 |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
{{ 16 | minus: 4 }} => 12 |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
{{ 183.357 | minus: 12 }} => 171.357 |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
=cut |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
my ($x, $y) = @_; |
561
|
|
|
|
|
|
|
$x ||= 0; |
562
|
|
|
|
|
|
|
return $x =~ m[^[\+-]?(\d*\.)?\d+?$]o && |
563
|
|
|
|
|
|
|
$y =~ m[^[\+-]?(\d*\.)?\d+?$]o ? $x - $y : (); |
564
|
|
|
|
|
|
|
} |
565
|
|
|
|
|
|
|
|
566
|
4
|
|
|
4
|
1
|
13
|
=head2 C<modulo> |
567
|
4
|
|
|
|
|
9
|
|
|
23
|
|
|
|
|
42
|
|
568
|
|
|
|
|
|
|
Returns the remainder of a division operation. |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
{{ 3 | modulo: 2 }} => 1 |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
{{ 24 | modulo: 7 }} => 3 |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
{{ 183.357 | modulo: 12 }} => 3.357 |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
=cut |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
my ($x, $y) = @_; |
579
|
|
|
|
|
|
|
require POSIX; |
580
|
|
|
|
|
|
|
POSIX::fmod($x, $y); |
581
|
|
|
|
|
|
|
} |
582
|
|
|
|
|
|
|
|
583
|
11
|
|
|
11
|
1
|
45
|
=head2 C<newline_to_br> |
584
|
11
|
|
50
|
|
|
22
|
|
585
|
11
|
100
|
66
|
|
|
82
|
Replaces each newline (C<\n>) with html break (C<< <br />\n >>). |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
{% capture string_with_newlines %} |
588
|
|
|
|
|
|
|
Hello |
589
|
|
|
|
|
|
|
there |
590
|
|
|
|
|
|
|
{% endcapture %} |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
{{ string_with_newlines | newline_to_br }} |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
...becomes... |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
<br /> |
597
|
|
|
|
|
|
|
Hello<br /> |
598
|
|
|
|
|
|
|
there<br /> |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
=cut |
601
|
|
|
|
|
|
|
|
602
|
3
|
|
|
3
|
1
|
9
|
|
603
|
3
|
|
|
|
|
16
|
=head2 C<plus> |
604
|
3
|
|
|
|
|
25
|
|
605
|
|
|
|
|
|
|
Adds a number to another number. |
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
{{ 154 | plus:1183 }} => 1337 |
608
|
|
|
|
|
|
|
{{ 4 | plus: 2 }} => 6 |
609
|
|
|
|
|
|
|
{{ 16 | plus: 4 }} => 20 |
610
|
|
|
|
|
|
|
{{ 183.357 | plus: 12 }} => 195.357 |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
{{ 'What' | plus:'Uhu' }} => WhatUhu |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
=head3 MATHFAIL! |
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
Please note that integer behavior differs with Perl vs. Ruby so... |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
{{ '1' | plus: '1' }} |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
...becomes C<11> in Ruby but C<2> in Perl. |
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
=cut |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
my ($x, $y) = @_; |
625
|
|
|
|
|
|
|
$x ||= 0; |
626
|
2
|
|
|
2
|
1
|
8
|
return $x =~ m[^[\+-]?(\d*\.)?\d+?$]o && |
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
6
|
|
627
|
|
|
|
|
|
|
$y =~ m[^[\+-]?(\d*\.)?\d+?$]o ? $x + $y : $x . $y; |
628
|
|
|
|
|
|
|
} |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
=head2 C<prepend> |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
Adds the specified string to the beginning of another string. |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
{{ 'bar' | prepend:'foo' }} => 'foobar' |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
{{ "apples, oranges, and bananas" | prepend: "Some fruit: " }} |
637
|
|
|
|
|
|
|
=> Some fruit: apples, oranges, and bananas |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
{% assign url = "example.com" %} |
640
|
|
|
|
|
|
|
{{ "/index.html" | prepend: url }} => example.com/index.html |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
=cut |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
=head2 C<remove> |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
Removes every occurrence of the specified substring from a string. |
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
{{ 'foobarfoobar' | remove:'foo' }} => 'barbar' |
650
|
7
|
|
|
7
|
1
|
16
|
|
651
|
7
|
|
50
|
|
|
12
|
{{ "I strained to see the train through the rain" | remove: "rain" }} |
652
|
7
|
100
|
66
|
|
|
63
|
=> I sted to see the t through the |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
=cut |
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
=head2 C<remove_first> |
658
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
Remove the first occurrence of a string. |
660
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
{{ 'barbar' | remove_first:'bar' }} => bar |
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
{{ "I strained to see the train through the rain" | remove_first: "rain" }} |
664
|
|
|
|
|
|
|
=> I sted to see the train through the rain |
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
=cut |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
my ($x, $y) = @_; |
669
|
|
|
|
|
|
|
$y = quotemeta($y); |
670
|
7
|
100
|
|
7
|
1
|
15
|
$x =~ s{$y}{}; |
|
7
|
|
|
|
|
25
|
|
671
|
|
|
|
|
|
|
return $x; |
672
|
|
|
|
|
|
|
} |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
=head2 C<replace> |
675
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
Replaces every occurrence of the first argument in a string with the second |
677
|
|
|
|
|
|
|
argument. |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
The replacement value is optional and defaults to an empty string (C<''>). |
680
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
{{ 'foofoo' | replace:'foo','bar' }} => barbar |
682
|
|
|
|
|
|
|
{% assign this = 'that' %} |
683
|
3
|
|
|
3
|
1
|
22
|
{{ 'Replace that with this' | replace:this,'this' }} => Replace this with this |
|
3
|
|
|
|
|
14
|
|
|
3
|
|
|
|
|
35
|
|
|
3
|
|
|
|
|
12
|
|
684
|
|
|
|
|
|
|
{{ 'I have a listhp.' | replace:'th' }} => I have a lisp. |
685
|
|
|
|
|
|
|
{{ "Take my protein pills and put my helmet on" | replace: "my", "your" }} |
686
|
|
|
|
|
|
|
=> Take your protein pills and put your helmet on |
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
=cut |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
my ($x, $y, $z) = @_; |
691
|
|
|
|
|
|
|
$z = defined $z ? $z : ''; |
692
|
|
|
|
|
|
|
$y = quotemeta($y); |
693
|
|
|
|
|
|
|
$x =~ s{$y}{$z}g if $y; |
694
|
|
|
|
|
|
|
return $x; |
695
|
|
|
|
|
|
|
} |
696
|
|
|
|
|
|
|
|
697
|
3
|
|
|
3
|
1
|
10
|
=head2 C<replace_first> |
698
|
3
|
|
|
|
|
11
|
|
699
|
3
|
|
|
|
|
35
|
Replaces only the first occurrence of the first argument in a string with the |
700
|
3
|
|
|
|
|
11
|
second argument. |
701
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
The replacement value is optional and defaults to an empty string (C<''>). |
703
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
{{ 'barbar' | replace_first:'bar','foo' }} => 'foobar' |
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
{{ "Take my protein pills and put my helmet on" | replace_first: "my", "your" }} |
707
|
|
|
|
|
|
|
=> Take your protein pills and put my helmet on |
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
=cut |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
my ($x, $y, $z) = @_; |
712
|
|
|
|
|
|
|
$z = defined $z ? $z : ''; |
713
|
|
|
|
|
|
|
$y = quotemeta($y); |
714
|
|
|
|
|
|
|
$x =~ s{$y}{$z}; |
715
|
|
|
|
|
|
|
return $x; |
716
|
|
|
|
|
|
|
} |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
=head2 C<reverse> |
719
|
|
|
|
|
|
|
|
720
|
5
|
|
|
5
|
1
|
16
|
Reverses the order of the items in an array. C<reverse> cannot reverse a |
721
|
5
|
100
|
|
|
|
12
|
string. |
722
|
5
|
|
|
|
|
13
|
|
723
|
5
|
50
|
|
|
|
66
|
{% assign my_array = "apples, oranges, peaches, plums" | split: ", " %} |
724
|
5
|
|
|
|
|
15
|
{{ my_array | reverse | join: ", " }} => plums, peaches, oranges, apples |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
Although C<reverse> cannot be used directly on a string, you can split a string |
727
|
|
|
|
|
|
|
into an array, reverse the array, and rejoin it by chaining together filters: |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
{{ "Ground control to Major Tom." | split: "" | reverse | join: "" }} |
730
|
|
|
|
|
|
|
=> .moT rojaM ot lortnoc dnuorG |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
=cut |
733
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
my ($args) = @_; |
735
|
|
|
|
|
|
|
[reverse @$args]; |
736
|
|
|
|
|
|
|
} |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
=head2 C<round> |
739
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
Rounds a number to the nearest integer or, if a number is passed as an |
741
|
|
|
|
|
|
|
argument, to that number of decimal places. |
742
|
3
|
|
|
3
|
1
|
9
|
|
743
|
3
|
50
|
|
|
|
25
|
{{ 4.6 | round }} => 5 |
744
|
3
|
|
|
|
|
8
|
{{ 4.3 | round }} => 4 |
745
|
3
|
|
|
|
|
39
|
{{ 1.2 | round }} => 1 |
746
|
3
|
|
|
|
|
10
|
{{ 2.7 | round }} => 3 |
747
|
|
|
|
|
|
|
{{ 4.5612 | round: 2 }} => 4.56 |
748
|
|
|
|
|
|
|
{{ 183.357 | round: 2 }} => 183.36 |
749
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
=cut |
751
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
my ($x, $y) = @_; |
753
|
|
|
|
|
|
|
return if $x !~ m[^(\d*\.)?\d+?$]o; |
754
|
|
|
|
|
|
|
return sprintf '%.' . int($y || 0) . 'f', $x; |
755
|
|
|
|
|
|
|
} |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
=head2 C<rstrip> |
758
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
Removes all whitespace (tabs, spaces, and newlines) from the right side of a |
760
|
|
|
|
|
|
|
string. It does not affect spaces between words. |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
{{ " So much room for activities! " | rstrip }} |
763
|
|
|
|
|
|
|
=> So much room for activities! |
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
=cut |
766
|
2
|
|
|
2
|
1
|
8
|
|
767
|
2
|
|
|
|
|
8
|
my ($x) = @_; |
768
|
|
|
|
|
|
|
$x =~ s[\s*$][]; |
769
|
|
|
|
|
|
|
$x; |
770
|
|
|
|
|
|
|
} |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
=head2 C<size> |
773
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
Returns the number of characters in a string, the number of items in an array, |
775
|
|
|
|
|
|
|
or the number of keys in a hash reference. Undefined values return C<0>. |
776
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
# Where array is [1..6] and hash is { child => 'blarg'} |
778
|
|
|
|
|
|
|
{{ array | size }} => 6 |
779
|
|
|
|
|
|
|
{{ 'Testing' | size }} => 7 |
780
|
|
|
|
|
|
|
{{ hash | size }} => 1 |
781
|
|
|
|
|
|
|
{{ undefined | size }} => 0 |
782
|
|
|
|
|
|
|
{{ "Ground control to Major Tom." | size }} => 28 |
783
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
{% assign my_array = "apples, oranges, peaches, plums" | split: ", " %} |
785
|
6
|
|
|
6
|
1
|
13
|
{{ my_array.size }} => 4 |
786
|
6
|
50
|
|
|
|
24
|
|
787
|
6
|
|
100
|
|
|
52
|
You can use C<size> with dot notation when you need to use the filter inside a |
788
|
|
|
|
|
|
|
tag: |
789
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
{% if site.pages.size > 10 %} |
791
|
|
|
|
|
|
|
This is a big website! |
792
|
|
|
|
|
|
|
{% endif %} |
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
=cut |
795
|
|
|
|
|
|
|
|
796
|
|
|
|
|
|
|
my ($x, $y) = @_; |
797
|
|
|
|
|
|
|
return 0 if !defined $x; |
798
|
|
|
|
|
|
|
return scalar @{$x} if ref $x eq 'ARRAY'; |
799
|
|
|
|
|
|
|
return scalar keys %{$x} if ref $x eq 'HASH'; |
800
|
|
|
|
|
|
|
return length $x; |
801
|
1
|
|
|
1
|
1
|
3
|
} |
802
|
1
|
|
|
|
|
8
|
|
803
|
1
|
|
|
|
|
5
|
=head2 C<slice> |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
Returns a substring of 1 character beginning at the index specified by the |
806
|
|
|
|
|
|
|
first argument. An optional second argument specifies the length of the |
807
|
|
|
|
|
|
|
substring to be returned. |
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
String indices are numbered starting from 0. |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
{{ "Liquid" | slice: 0 }} => L |
812
|
|
|
|
|
|
|
{{ "Liquid" | slice: 2 }} => q |
813
|
|
|
|
|
|
|
{{ "Liquid" | slice: 2, 5 }} => quid |
814
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
If the first argument is a negative number, the indices are counted from the |
816
|
|
|
|
|
|
|
end of the string: |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
{{ "Liquid" | slice: -3, 2 }} => ui |
819
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
=cut |
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
my ($x, $pos, $len) = @_; |
823
|
|
|
|
|
|
|
$len = 1 unless defined $len; |
824
|
|
|
|
|
|
|
substr $x, $pos, $len; |
825
|
|
|
|
|
|
|
} |
826
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
=head2 C<sort> |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
Sorts items in an array in case-sensitive order. |
830
|
|
|
|
|
|
|
|
831
|
5
|
|
|
5
|
1
|
12
|
{% assign my_array = "zebra, octopus, giraffe, Sally Snake" | split: ", " %} |
832
|
5
|
100
|
|
|
|
14
|
{{ my_array | sort | join: ", " }} => Sally Snake, giraffe, octopus, zebra |
833
|
4
|
100
|
|
|
|
11
|
|
|
1
|
|
|
|
|
3
|
|
834
|
3
|
100
|
|
|
|
15
|
An optional argument specifies which property of the array's items to use for |
|
1
|
|
|
|
|
4
|
|
835
|
2
|
|
|
|
|
5
|
sorting. |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
{% assign products_by_price = collection.products | sort: "price" %} |
838
|
|
|
|
|
|
|
{% for product in products_by_price %} |
839
|
|
|
|
|
|
|
<h4>{{ product.title }}</h4> |
840
|
|
|
|
|
|
|
{% endfor %} |
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
=cut |
843
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
my ($x, $y) = @_; |
845
|
|
|
|
|
|
|
return [sort { ($a =~ m[\D] || $b =~ m[\D]) ? $a cmp $b : $a <=> $b } |
846
|
|
|
|
|
|
|
@{$x}] |
847
|
|
|
|
|
|
|
if ref $x eq 'ARRAY'; |
848
|
|
|
|
|
|
|
return |
849
|
|
|
|
|
|
|
sort { ($a =~ m[\D] || $b =~ m[\D]) ? $a cmp $b : $a <=> $b } |
850
|
|
|
|
|
|
|
keys %{$x} |
851
|
|
|
|
|
|
|
if ref $x eq 'HASH'; |
852
|
|
|
|
|
|
|
return $x; |
853
|
|
|
|
|
|
|
} |
854
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
=head2 C<sort_natural> |
856
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
Sorts items in an array in case-sensitive order. |
858
|
4
|
|
|
4
|
1
|
14
|
|
859
|
4
|
100
|
|
|
|
17
|
{% assign my_array = "zebra, octopus, giraffe, Sally Snake" | split: ", " %} |
860
|
4
|
|
|
|
|
14
|
{{ my_array | sort_natural | join: ", " }} => giraffe, octopus, Sally Snake, zebra |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
An optional argument specifies which property of the array's items to use for |
863
|
|
|
|
|
|
|
sorting. |
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
{% assign products_by_company = collection.products | sort_natural: "company" %} |
866
|
|
|
|
|
|
|
{% for product in products_by_company %} |
867
|
|
|
|
|
|
|
<h4>{{ product.title }}</h4> |
868
|
|
|
|
|
|
|
{% endfor %} |
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
=cut |
871
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
my ($x, $y) = @_; |
873
|
|
|
|
|
|
|
return [ |
874
|
|
|
|
|
|
|
sort { |
875
|
|
|
|
|
|
|
($a->{$y} =~ m[\D] || $b->{$y} =~ m[\D]) |
876
|
|
|
|
|
|
|
? $a->{$y} cmp $b->{$y} |
877
|
|
|
|
|
|
|
: $a->{$y} <=> $b->{$y} |
878
|
|
|
|
|
|
|
} @{$x} |
879
|
|
|
|
|
|
|
] |
880
|
|
|
|
|
|
|
if ref $x eq 'HASH' && defined $y; |
881
|
2
|
|
|
2
|
1
|
5
|
return [ |
882
|
15
|
100
|
66
|
|
|
62
|
sort { ($a =~ m[\D] || $b =~ m[\D]) ? lc $a cmp lc $b : $a <=> $b } |
883
|
2
|
50
|
|
|
|
9
|
@{$x} |
|
2
|
|
|
|
|
97
|
|
884
|
|
|
|
|
|
|
] |
885
|
|
|
|
|
|
|
if ref $x eq 'ARRAY'; |
886
|
0
|
0
|
0
|
|
|
0
|
return |
887
|
0
|
0
|
|
|
|
0
|
sort { ($a =~ m[\D] || $b =~ m[\D]) ? lc $a cmp lc $b : $a <=> $b } |
|
0
|
|
|
|
|
0
|
|
888
|
|
|
|
|
|
|
keys %{$x} |
889
|
0
|
|
|
|
|
0
|
if ref $x eq 'HASH'; |
890
|
|
|
|
|
|
|
return $x; |
891
|
|
|
|
|
|
|
} |
892
|
|
|
|
|
|
|
|
893
|
|
|
|
|
|
|
=head2 C<split> |
894
|
|
|
|
|
|
|
|
895
|
|
|
|
|
|
|
Divides a string into an array using the argument as a separator. C<split> is |
896
|
|
|
|
|
|
|
commonly used to convert comma-separated items from a string to an array. |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
{% assign beatles = "John, Paul, George, Ringo" | split: ", " %} |
899
|
|
|
|
|
|
|
{% for member in beatles %} |
900
|
|
|
|
|
|
|
{{ member }} |
901
|
|
|
|
|
|
|
{% endfor %} |
902
|
|
|
|
|
|
|
|
903
|
|
|
|
|
|
|
...becomes... |
904
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
John |
906
|
|
|
|
|
|
|
Paul |
907
|
|
|
|
|
|
|
George |
908
|
|
|
|
|
|
|
Ringo |
909
|
|
|
|
|
|
|
|
910
|
1
|
|
|
1
|
1
|
9
|
=cut |
911
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
my ($x, $y) = @_; |
913
|
|
|
|
|
|
|
return [] if !defined $x; |
914
|
|
|
|
|
|
|
[split $y, $x]; |
915
|
0
|
0
|
0
|
|
|
0
|
} |
916
|
1
|
50
|
33
|
|
|
8
|
|
|
0
|
|
|
|
|
0
|
|
917
|
|
|
|
|
|
|
=head2 C<strip> |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
Removes all whitespace (tabs, spaces, and newlines) from both the left and |
920
|
5
|
50
|
33
|
|
|
121
|
right sides of a string. It does not affect spaces between words. |
921
|
1
|
50
|
|
|
|
4
|
|
|
1
|
|
|
|
|
4
|
|
922
|
|
|
|
|
|
|
|{{ " So much room for activities! " | strip }}| |
923
|
|
|
|
|
|
|
=> |So much room for activities!| |
924
|
|
|
|
|
|
|
|
925
|
0
|
0
|
0
|
|
|
0
|
=cut |
926
|
0
|
0
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
927
|
|
|
|
|
|
|
my ($x) = @_; |
928
|
0
|
|
|
|
|
0
|
$x =~ s[^\s+|\s+$][]g; |
929
|
|
|
|
|
|
|
$x; |
930
|
|
|
|
|
|
|
} |
931
|
|
|
|
|
|
|
|
932
|
|
|
|
|
|
|
=head2 C<strip_html> |
933
|
|
|
|
|
|
|
|
934
|
|
|
|
|
|
|
Removes any HTML tags from a string. |
935
|
|
|
|
|
|
|
|
936
|
|
|
|
|
|
|
{{ '<div>Hello, <em id="whom">world!</em></div>' | strip_html }} => Hello, world! |
937
|
|
|
|
|
|
|
'{{ '<IMG SRC = "foo.gif" ALT = "A > B">' | strip_html }}' => ' B">' |
938
|
|
|
|
|
|
|
'{{ '<!-- <A comment> -->' | strip_html }}' => ' -->' |
939
|
|
|
|
|
|
|
{{ "Have <em>you</em> read <strong>Ulysses</strong>?" | strip_html }} => Have you read Ulysses? |
940
|
|
|
|
|
|
|
|
941
|
|
|
|
|
|
|
Note that this filter uses C<s[<.*?>][]g> in emulation of the Ruby Liquid |
942
|
|
|
|
|
|
|
library's strip_html function. ...so don't email me if you (correctly) think |
943
|
|
|
|
|
|
|
this is a brain dead way of stripping html. |
944
|
|
|
|
|
|
|
|
945
|
|
|
|
|
|
|
=cut |
946
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
my ($x, $y) = @_; |
948
|
|
|
|
|
|
|
$x =~ s[<.*?>][]go; |
949
|
|
|
|
|
|
|
$x =~ s[<!--.*?-->][]go; |
950
|
|
|
|
|
|
|
$x =~ s[<script.*?<\/script>][]go; |
951
|
20
|
|
|
20
|
1
|
40
|
return $x; |
952
|
20
|
50
|
|
|
|
40
|
} |
953
|
20
|
|
|
|
|
277
|
|
954
|
|
|
|
|
|
|
=head2 C<strip_newlines> |
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
Removes any newline characters (line breaks) from a string. |
957
|
|
|
|
|
|
|
|
958
|
|
|
|
|
|
|
{% capture string_with_newlines %} Hello there {% endcapture %} |
959
|
|
|
|
|
|
|
|
960
|
|
|
|
|
|
|
{{ string_with_newlines | strip_newlines }} => Hellothere |
961
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
=cut |
963
|
|
|
|
|
|
|
|
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
=head2 C<times> |
966
|
|
|
|
|
|
|
|
967
|
1
|
|
|
1
|
1
|
3
|
Simple multiplication or string repetition. |
968
|
1
|
|
|
|
|
8
|
|
969
|
1
|
|
|
|
|
3
|
{{ 'foo' | times: 4 }} => foofoofoofoo |
970
|
|
|
|
|
|
|
{{ 5 | times: 4 }} => 20 |
971
|
|
|
|
|
|
|
{{ 3 | times: 2 }} => 6 |
972
|
|
|
|
|
|
|
{{ 24 | times: 7 }} => 168 |
973
|
|
|
|
|
|
|
{{ 183.357 | times: 12 }} => 2200.284 |
974
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
=cut |
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
my ($x, $y) = @_; |
978
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
#warn sprintf '%s | %s', $x, $y; |
980
|
|
|
|
|
|
|
return unless $y; |
981
|
|
|
|
|
|
|
my $r; |
982
|
|
|
|
|
|
|
$r = $x if $y !~ m[^[\+-]?(\d*\.)?\d+?$]o; |
983
|
|
|
|
|
|
|
return $x x $y if $x !~ m[^[\+-]?(\d*\.)?\d+?$]o; |
984
|
|
|
|
|
|
|
$r = $x * $y unless defined $r; |
985
|
|
|
|
|
|
|
my ($_x) = $x =~ m[\.(\d+)$]; |
986
|
|
|
|
|
|
|
my ($_y) = $y =~ m[\.(\d+)$]; |
987
|
|
|
|
|
|
|
my ($_r) = $r =~ m[\.(\d+)$]; |
988
|
3
|
|
|
3
|
1
|
9
|
$_x //= ''; |
989
|
3
|
|
|
|
|
16
|
$_y //= ''; |
990
|
3
|
|
|
|
|
7
|
$_r //= ''; |
991
|
3
|
|
|
|
|
10
|
my $_lx = length $_x; |
992
|
3
|
|
|
|
|
6
|
my $_ly = length $_y; |
993
|
|
|
|
|
|
|
my $_lr = length $_r; |
994
|
|
|
|
|
|
|
( ($_lx || $_ly || $_lr) |
995
|
|
|
|
|
|
|
? (sprintf '%0.' . ([sort $_lx, $_ly, $_lr]->[-1]) . 'f', $r) |
996
|
|
|
|
|
|
|
: $r); |
997
|
|
|
|
|
|
|
} |
998
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
=head2 C<truncate> |
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
Shortens a string down to the number of characters passed as an argument. If |
1002
|
|
|
|
|
|
|
the specified number of characters is less than the length of the string, an |
1003
|
|
|
|
|
|
|
ellipsis (...) is appended to the string and is included in the character |
1004
|
|
|
|
|
|
|
count. |
1005
|
2
|
|
|
2
|
1
|
24
|
|
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
5
|
|
1006
|
|
|
|
|
|
|
{{ "Ground control to Major Tom." | truncate: 20 }} => Ground control to... |
1007
|
|
|
|
|
|
|
{{ 'Running the halls!!!' | truncate:19 }} => Running the hall.. |
1008
|
|
|
|
|
|
|
{% assign blarg = 'STOP!' %} |
1009
|
|
|
|
|
|
|
{{ 'Any Colour You Like' | truncate:10,blarg }} => Any CSTOP! |
1010
|
|
|
|
|
|
|
{{ 'Why are you running away?' | truncate:4,'?' }} => Why? |
1011
|
|
|
|
|
|
|
{{ 'Ha' | truncate:4 }} => Ha |
1012
|
|
|
|
|
|
|
{{ 'Ha' | truncate:1,'Laugh' }} => Laugh |
1013
|
|
|
|
|
|
|
{{ 'Ha' | truncate:1,'...' }} => ... |
1014
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
...and... |
1016
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
{{ 'This is a long line of text to test the default values for truncate' | truncate }} |
1018
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
...becomes... |
1020
|
6
|
|
|
6
|
1
|
15
|
|
1021
|
|
|
|
|
|
|
This is a long line of text to test the default... |
1022
|
|
|
|
|
|
|
|
1023
|
6
|
50
|
|
|
|
24
|
=head3 Custom ellipsis |
1024
|
6
|
|
|
|
|
7
|
|
1025
|
6
|
50
|
|
|
|
25
|
C<truncate> takes an optional second argument that specifies the sequence of |
1026
|
6
|
100
|
|
|
|
21
|
characters to be appended to the truncated string. By default this is an |
1027
|
5
|
50
|
|
|
|
18
|
ellipsis (...), but you can specify a different sequence. |
1028
|
5
|
|
|
|
|
14
|
|
1029
|
5
|
|
|
|
|
10
|
The length of the second argument counts against the number of characters |
1030
|
5
|
|
|
|
|
18
|
specified by the first argument. For example, if you want to truncate a string |
1031
|
5
|
|
100
|
|
|
17
|
to exactly 10 characters, and use a 3-character ellipsis, use B<13> for the |
1032
|
5
|
|
100
|
|
|
18
|
first argument of truncate, since the ellipsis counts as 3 characters. |
1033
|
5
|
|
100
|
|
|
21
|
|
1034
|
5
|
|
|
|
|
8
|
{{ "Ground control to Major Tom." | truncate: 25, ", and so on" }} |
1035
|
5
|
|
|
|
|
6
|
=> Ground control, and so on |
1036
|
5
|
|
|
|
|
8
|
|
1037
|
5
|
100
|
66
|
|
|
46
|
=head3 No ellipsis |
1038
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
You can truncate to the exact number of characters specified by the first |
1040
|
|
|
|
|
|
|
argument and avoid showing trailing characters by passing a blank string as the |
1041
|
|
|
|
|
|
|
second argument: |
1042
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
{{ "Ground control to Major Tom." | truncate: 20, "" }} |
1044
|
|
|
|
|
|
|
=> Ground control to Ma |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
=cut |
1047
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
my ($data, $length, $truncate_string) = @_; |
1049
|
|
|
|
|
|
|
$length = defined $length ? $length : 50; |
1050
|
|
|
|
|
|
|
$truncate_string = defined $truncate_string ? $truncate_string : '...'; |
1051
|
|
|
|
|
|
|
return if !$data; |
1052
|
|
|
|
|
|
|
my $l = $length - length($truncate_string); |
1053
|
|
|
|
|
|
|
$l = 0 if $l < 0; |
1054
|
|
|
|
|
|
|
return |
1055
|
|
|
|
|
|
|
length($data) > $length |
1056
|
|
|
|
|
|
|
? substr($data, 0, $l) . $truncate_string |
1057
|
|
|
|
|
|
|
: $data; |
1058
|
|
|
|
|
|
|
} |
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
=head2 C<truncatewords> |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
Shortens a string down to the number of words passed as an argument. If the |
1063
|
|
|
|
|
|
|
specified number of words is less than the number of words in the string, an |
1064
|
|
|
|
|
|
|
ellipsis (...) is appended to the string. |
1065
|
|
|
|
|
|
|
|
1066
|
|
|
|
|
|
|
{{ "Ground control to Major Tom." | truncatewords: 3 }} => Ground control to... |
1067
|
|
|
|
|
|
|
|
1068
|
|
|
|
|
|
|
=head3 Custom ellipsis |
1069
|
|
|
|
|
|
|
|
1070
|
|
|
|
|
|
|
C<truncatewords> takes an optional second argument that specifies the sequence |
1071
|
|
|
|
|
|
|
of characters to be appended to the truncated string. By default this is an |
1072
|
|
|
|
|
|
|
ellipsis (...), but you can specify a different sequence. |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
{{ "Ground control to Major Tom." | truncatewords: 3, "--" }} => Ground control to-- |
1075
|
|
|
|
|
|
|
|
1076
|
|
|
|
|
|
|
=head3 No ellipsis |
1077
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
You can avoid showing trailing characters by passing a blank string as the |
1079
|
|
|
|
|
|
|
second argument: |
1080
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
{{ "Ground control to Major Tom." | truncatewords: 3, "" }} => Ground control to |
1082
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
=cut |
1084
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
my ($data, $words, $truncate_string) = @_; |
1086
|
|
|
|
|
|
|
$words = defined $words ? $words : 15; |
1087
|
|
|
|
|
|
|
$truncate_string = defined $truncate_string ? $truncate_string : '...'; |
1088
|
|
|
|
|
|
|
return if !$data; |
1089
|
|
|
|
|
|
|
my @wordlist = split ' ', $data; |
1090
|
|
|
|
|
|
|
my $l = $words - 1; |
1091
|
|
|
|
|
|
|
$l = 0 if $l < 0; |
1092
|
5
|
|
|
5
|
1
|
10
|
return $#wordlist > $l |
1093
|
5
|
50
|
|
|
|
10
|
? CORE::join(' ', @wordlist[0 .. $l]) . $truncate_string |
1094
|
5
|
100
|
|
|
|
10
|
: $data; |
1095
|
5
|
50
|
|
|
|
8
|
} |
1096
|
5
|
|
|
|
|
13
|
|
1097
|
5
|
50
|
|
|
|
10
|
=head2 C<uniq> |
1098
|
|
|
|
|
|
|
|
1099
|
5
|
50
|
|
|
|
20
|
Removes any duplicate elements in an array. |
1100
|
|
|
|
|
|
|
|
1101
|
|
|
|
|
|
|
{% assign my_array = "ants, bugs, bees, bugs, ants" | split: ", " %} |
1102
|
|
|
|
|
|
|
{{ my_array | uniq | join: ", " }} => ants, bugs, bees |
1103
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
=cut |
1105
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
my ($array) = @_; |
1107
|
|
|
|
|
|
|
my @retval; |
1108
|
|
|
|
|
|
|
for my $element (@$array) { |
1109
|
|
|
|
|
|
|
push @retval, $element unless grep { $_ eq $element } @retval; |
1110
|
|
|
|
|
|
|
} |
1111
|
|
|
|
|
|
|
\@retval; |
1112
|
|
|
|
|
|
|
} |
1113
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
=head2 C<upcase> |
1115
|
|
|
|
|
|
|
|
1116
|
|
|
|
|
|
|
Makes each character in a string uppercase. It has no effect on strings which |
1117
|
|
|
|
|
|
|
are already all uppercase. |
1118
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
{{ "Parker Moore" | upcase }} => PARKER MOORE |
1120
|
|
|
|
|
|
|
|
1121
|
|
|
|
|
|
|
{{ "APPLE" | upcase }} => APPLE |
1122
|
|
|
|
|
|
|
|
1123
|
|
|
|
|
|
|
=cut |
1124
|
|
|
|
|
|
|
|
1125
|
|
|
|
|
|
|
|
1126
|
|
|
|
|
|
|
=head2 C<url_decode> |
1127
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
Decodes a string that has been encoded as a URL or by C<url_encode>. |
1129
|
|
|
|
|
|
|
|
1130
|
5
|
|
|
5
|
1
|
16
|
{{ "%27Stop%21%27+said+Fred" | url_decode }} => 'Stop!' said Fred |
1131
|
5
|
100
|
|
|
|
14
|
|
1132
|
5
|
100
|
|
|
|
11
|
=cut |
1133
|
5
|
50
|
|
|
|
10
|
|
1134
|
5
|
|
|
|
|
17
|
my ($x) = @_; |
1135
|
5
|
|
|
|
|
9
|
$x =~ s[\+][ ]g; |
1136
|
5
|
50
|
|
|
|
11
|
$x =~ s[%(\d+)][chr hex $1]gex; |
1137
|
5
|
50
|
|
|
|
30
|
$x; |
1138
|
|
|
|
|
|
|
} |
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
=head2 C<url_encode> |
1141
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
Converts any URL-unsafe characters in a string into percent-encoded characters. |
1143
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
{{ "john@liquid.com" | url_encode }} => john%40liquid.com |
1145
|
|
|
|
|
|
|
|
1146
|
|
|
|
|
|
|
{{ "Tetsuro Takara" | url_encode }} => Tetsuro+Takara |
1147
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
{{ "'Stop!'" said Fred" | url_encode }} => %27Stop%21%27+said+Fred |
1149
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
=cut |
1151
|
|
|
|
|
|
|
|
1152
|
1
|
|
|
1
|
1
|
8
|
my $s = shift; |
1153
|
1
|
|
|
|
|
3
|
$s =~ s/ /+/g; |
1154
|
1
|
|
|
|
|
2
|
$s =~ s/([^A-Za-z0-9\+-\.])/sprintf("%%%02X", ord($1))/seg; |
1155
|
5
|
100
|
|
|
|
10
|
return $s; |
|
9
|
|
|
|
|
17
|
|
1156
|
|
|
|
|
|
|
} |
1157
|
1
|
|
|
|
|
6
|
|
1158
|
|
|
|
|
|
|
=head2 C<where> |
1159
|
|
|
|
|
|
|
|
1160
|
|
|
|
|
|
|
Creates an array including only the objects with a given property value, or any |
1161
|
|
|
|
|
|
|
truthy value by default. |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
In this example, assume you have a list of products and you want to show your |
1164
|
|
|
|
|
|
|
kitchen products separately. Using C<where>, you can create an array containing |
1165
|
|
|
|
|
|
|
only the products that have a C<"type"> of C<"kitchen">. |
1166
|
|
|
|
|
|
|
|
1167
|
|
|
|
|
|
|
All products: |
1168
|
|
|
|
|
|
|
{% for product in products %} |
1169
|
|
|
|
|
|
|
- {{ product.title }} |
1170
|
|
|
|
|
|
|
{% endfor %} |
1171
|
4
|
|
|
4
|
1
|
11
|
|
|
4
|
|
|
|
|
12
|
|
1172
|
|
|
|
|
|
|
{% assign kitchen_products = products | where: "type", "kitchen" %} |
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
Kitchen products: |
1175
|
|
|
|
|
|
|
{% for product in kitchen_products %} |
1176
|
|
|
|
|
|
|
- {{ product.title }} |
1177
|
|
|
|
|
|
|
{% endfor %} |
1178
|
|
|
|
|
|
|
|
1179
|
|
|
|
|
|
|
...rendered with this data... |
1180
|
|
|
|
|
|
|
|
1181
|
|
|
|
|
|
|
products => [ |
1182
|
1
|
|
|
1
|
1
|
5
|
{ title => 'Vacuum', type => 'carpet', }, |
1183
|
1
|
|
|
|
|
10
|
{ title => 'Spatula', type => 'kitchen' }, |
1184
|
1
|
|
|
|
|
6
|
{ title => 'Television', type => 'den' }, |
|
3
|
|
|
|
|
12
|
|
1185
|
1
|
|
|
|
|
3
|
{ title => 'Garlic press', type => 'kitchen' }, |
1186
|
|
|
|
|
|
|
] |
1187
|
|
|
|
|
|
|
|
1188
|
|
|
|
|
|
|
...becomes... |
1189
|
|
|
|
|
|
|
|
1190
|
|
|
|
|
|
|
All products: |
1191
|
|
|
|
|
|
|
- Vacuum |
1192
|
|
|
|
|
|
|
- Spatula |
1193
|
|
|
|
|
|
|
- Television |
1194
|
|
|
|
|
|
|
- Garlic press |
1195
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
Kitchen products: |
1197
|
|
|
|
|
|
|
- Spatula |
1198
|
|
|
|
|
|
|
- Garlic press |
1199
|
|
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
Say instead you have a list of products and you only want to show those that |
1201
|
3
|
|
|
3
|
1
|
5
|
are available to buy. You can where with a property name but no target value to |
1202
|
3
|
|
|
|
|
11
|
include all products with a truthy "available" value. |
1203
|
3
|
|
|
|
|
14
|
|
|
4
|
|
|
|
|
19
|
|
1204
|
3
|
|
|
|
|
9
|
All products: |
1205
|
|
|
|
|
|
|
{% for product in products %} |
1206
|
|
|
|
|
|
|
- {{ product.title }} |
1207
|
|
|
|
|
|
|
{% endfor %} |
1208
|
|
|
|
|
|
|
|
1209
|
|
|
|
|
|
|
{% assign available_products = products | where: "available" %} |
1210
|
|
|
|
|
|
|
|
1211
|
|
|
|
|
|
|
Available products: |
1212
|
|
|
|
|
|
|
{% for product in available_products %} |
1213
|
|
|
|
|
|
|
- {{ product.title }} |
1214
|
|
|
|
|
|
|
{% endfor %} |
1215
|
|
|
|
|
|
|
|
1216
|
|
|
|
|
|
|
...rendered with this data... |
1217
|
|
|
|
|
|
|
|
1218
|
|
|
|
|
|
|
products => [ |
1219
|
|
|
|
|
|
|
{ title => 'Coffee mug', available => 1}, |
1220
|
|
|
|
|
|
|
{ title => 'Limited edition sneakers', available => 0}, |
1221
|
|
|
|
|
|
|
{ title => 'Boring sneakers', available => 1} |
1222
|
|
|
|
|
|
|
] |
1223
|
|
|
|
|
|
|
|
1224
|
|
|
|
|
|
|
...becomes... |
1225
|
|
|
|
|
|
|
|
1226
|
|
|
|
|
|
|
All products: |
1227
|
|
|
|
|
|
|
- Coffee mug |
1228
|
|
|
|
|
|
|
- Limited edition sneakers |
1229
|
|
|
|
|
|
|
- Boring sneakers |
1230
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
Available products: |
1232
|
|
|
|
|
|
|
- Coffee mug |
1233
|
|
|
|
|
|
|
- Boring sneakers |
1234
|
|
|
|
|
|
|
|
1235
|
|
|
|
|
|
|
The C<where> filter can also be used to find a single object in an array when |
1236
|
|
|
|
|
|
|
combined with the C<first> filter. For example, say you want to show off the |
1237
|
|
|
|
|
|
|
shirt in your new fall collection. |
1238
|
|
|
|
|
|
|
|
1239
|
|
|
|
|
|
|
{% assign new_shirt = products | where: "type", "shirt" | first %} |
1240
|
|
|
|
|
|
|
|
1241
|
|
|
|
|
|
|
Featured product: {{ new_shirt.title }} |
1242
|
|
|
|
|
|
|
|
1243
|
|
|
|
|
|
|
...rendered with the following data... |
1244
|
|
|
|
|
|
|
|
1245
|
|
|
|
|
|
|
products => [ |
1246
|
|
|
|
|
|
|
{ title => 'Limited edition sneakers', type => 'shoes' }, |
1247
|
|
|
|
|
|
|
{ title => 'Hawaiian print sweater vest', type => 'shirt' }, |
1248
|
|
|
|
|
|
|
{ title => 'Tuxedo print tshirt', type => 'shirt' }, |
1249
|
|
|
|
|
|
|
{ title => 'Jorts', type => 'shorts' } |
1250
|
|
|
|
|
|
|
] |
1251
|
|
|
|
|
|
|
|
1252
|
|
|
|
|
|
|
...becomes... |
1253
|
|
|
|
|
|
|
|
1254
|
|
|
|
|
|
|
Featured product: Hawaiian print sweater vest |
1255
|
|
|
|
|
|
|
|
1256
|
|
|
|
|
|
|
=cut |
1257
|
|
|
|
|
|
|
|
1258
|
|
|
|
|
|
|
my ($list, $key, $value) = @_; |
1259
|
|
|
|
|
|
|
[grep { defined $value ? $_->{$key} eq $value : !!$_->{$key} } @$list]; |
1260
|
|
|
|
|
|
|
} |
1261
|
|
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
=head2 C<money> |
1263
|
|
|
|
|
|
|
|
1264
|
|
|
|
|
|
|
Formats floats and integers as if they were money. |
1265
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
{{ 4.6 | money }} => $4.60 |
1267
|
|
|
|
|
|
|
{{ -4.3 | money }} => -$4.30 |
1268
|
|
|
|
|
|
|
{{ 4.5612 | money }} => $4.56 |
1269
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
You may pass a currency symbol to override the default dollar sign (C<$>). |
1271
|
|
|
|
|
|
|
|
1272
|
|
|
|
|
|
|
{{ 4.6 | money:'€' }} => €4.60 |
1273
|
|
|
|
|
|
|
|
1274
|
|
|
|
|
|
|
=cut |
1275
|
|
|
|
|
|
|
|
1276
|
|
|
|
|
|
|
my ($x, $y) = @_; |
1277
|
|
|
|
|
|
|
return if $x !~ m[^[\+-]?(\d*\.)?\d+?$]o; |
1278
|
|
|
|
|
|
|
return (($x < 0 ? '-' : '') . (defined $y ? $y : '$') . sprintf '%.2f', |
1279
|
|
|
|
|
|
|
CORE::abs($x)); |
1280
|
|
|
|
|
|
|
} |
1281
|
|
|
|
|
|
|
|
1282
|
|
|
|
|
|
|
=head2 C<stock_price> |
1283
|
|
|
|
|
|
|
|
1284
|
|
|
|
|
|
|
Formats floats and integers as if they were stock prices. |
1285
|
|
|
|
|
|
|
|
1286
|
|
|
|
|
|
|
{{ 4.6 | stock_price }} => $4.60 |
1287
|
|
|
|
|
|
|
{{ 0.30 | stock_price }} => $0.3000 |
1288
|
|
|
|
|
|
|
{{ 4.5612 | stock_price }} => $4.56 |
1289
|
|
|
|
|
|
|
|
1290
|
|
|
|
|
|
|
You may pass a currency symbol to override the default dollar sign (C<$>). |
1291
|
|
|
|
|
|
|
|
1292
|
|
|
|
|
|
|
{{ 4.6 | stock_price:'€' }} => €4.60 |
1293
|
|
|
|
|
|
|
|
1294
|
|
|
|
|
|
|
=cut |
1295
|
|
|
|
|
|
|
|
1296
|
|
|
|
|
|
|
my ($x, $y) = @_; |
1297
|
|
|
|
|
|
|
return if $x !~ m[^[\+-]?(\d*\.)?\d+?$]o; |
1298
|
|
|
|
|
|
|
return (($x < 0 ? '-' : '') . (defined $y ? $y : '$') . |
1299
|
|
|
|
|
|
|
sprintf '%.' . (int(CORE::abs($x)) > 0 ? 2 : 4) . 'f', |
1300
|
|
|
|
|
|
|
CORE::abs($x) |
1301
|
|
|
|
|
|
|
); |
1302
|
|
|
|
|
|
|
} |
1303
|
|
|
|
|
|
|
|
1304
|
|
|
|
|
|
|
=head1 Author |
1305
|
|
|
|
|
|
|
|
1306
|
|
|
|
|
|
|
Sanko Robinson <sanko@cpan.org> - http://sankorobinson.com/ |
1307
|
|
|
|
|
|
|
|
1308
|
3
|
|
|
3
|
1
|
8
|
CPAN ID: SANKO |
1309
|
3
|
100
|
|
|
|
6
|
|
|
11
|
|
|
|
|
30
|
|
1310
|
|
|
|
|
|
|
=head1 License and Legal |
1311
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
Copyright (C) 2009-2020 by Sanko Robinson E<lt>sanko@cpan.orgE<gt> |
1313
|
|
|
|
|
|
|
|
1314
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it under |
1315
|
|
|
|
|
|
|
the terms of L<The Artistic License |
1316
|
|
|
|
|
|
|
2.0|http://www.perlfoundation.org/artistic_license_2_0>. See the F<LICENSE> |
1317
|
|
|
|
|
|
|
file included with this distribution or L<notes on the Artistic License |
1318
|
|
|
|
|
|
|
2.0|http://www.perlfoundation.org/artistic_2_0_notes> for clarification. |
1319
|
|
|
|
|
|
|
|
1320
|
|
|
|
|
|
|
When separated from the distribution, all original POD documentation is covered |
1321
|
|
|
|
|
|
|
by the L<Creative Commons Attribution-Share Alike 3.0 |
1322
|
|
|
|
|
|
|
License|http://creativecommons.org/licenses/by-sa/3.0/us/legalcode>. See the |
1323
|
|
|
|
|
|
|
L<clarification of the |
1324
|
|
|
|
|
|
|
CCA-SA3.0|http://creativecommons.org/licenses/by-sa/3.0/us/>. |
1325
|
|
|
|
|
|
|
|
1326
|
|
|
|
|
|
|
=cut |