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