liquid 5.1.0 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.md +35 -0
- data/README.md +4 -4
- data/lib/liquid/block_body.rb +6 -6
- data/lib/liquid/condition.rb +7 -1
- data/lib/liquid/context.rb +6 -2
- data/lib/liquid/expression.rb +11 -10
- data/lib/liquid/forloop_drop.rb +44 -1
- data/lib/liquid/locales/en.yml +6 -5
- data/lib/liquid/partial_cache.rb +3 -3
- data/lib/liquid/registers.rb +51 -0
- data/lib/liquid/standardfilters.rb +463 -75
- data/lib/liquid/strainer_factory.rb +15 -10
- data/lib/liquid/strainer_template.rb +9 -0
- data/lib/liquid/tablerowloop_drop.rb +58 -1
- data/lib/liquid/tags/assign.rb +12 -8
- data/lib/liquid/tags/break.rb +8 -0
- data/lib/liquid/tags/capture.rb +13 -10
- data/lib/liquid/tags/case.rb +21 -0
- data/lib/liquid/tags/comment.rb +13 -0
- data/lib/liquid/tags/continue.rb +8 -9
- data/lib/liquid/tags/cycle.rb +12 -11
- data/lib/liquid/tags/decrement.rb +16 -17
- data/lib/liquid/tags/echo.rb +16 -9
- data/lib/liquid/tags/for.rb +22 -43
- data/lib/liquid/tags/if.rb +11 -9
- data/lib/liquid/tags/include.rb +15 -13
- data/lib/liquid/tags/increment.rb +16 -14
- data/lib/liquid/tags/inline_comment.rb +43 -0
- data/lib/liquid/tags/raw.rb +11 -0
- data/lib/liquid/tags/render.rb +29 -4
- data/lib/liquid/tags/table_row.rb +22 -0
- data/lib/liquid/tags/unless.rb +15 -4
- data/lib/liquid/template.rb +2 -3
- data/lib/liquid/variable.rb +4 -4
- data/lib/liquid/variable_lookup.rb +10 -7
- data/lib/liquid/version.rb +1 -1
- data/lib/liquid.rb +4 -4
- metadata +7 -121
- data/lib/liquid/register.rb +0 -6
- data/lib/liquid/static_registers.rb +0 -44
- data/test/fixtures/en_locale.yml +0 -9
- data/test/integration/assign_test.rb +0 -117
- data/test/integration/blank_test.rb +0 -109
- data/test/integration/block_test.rb +0 -58
- data/test/integration/capture_test.rb +0 -58
- data/test/integration/context_test.rb +0 -636
- data/test/integration/document_test.rb +0 -21
- data/test/integration/drop_test.rb +0 -257
- data/test/integration/error_handling_test.rb +0 -272
- data/test/integration/expression_test.rb +0 -46
- data/test/integration/filter_test.rb +0 -189
- data/test/integration/hash_ordering_test.rb +0 -25
- data/test/integration/output_test.rb +0 -125
- data/test/integration/parsing_quirks_test.rb +0 -134
- data/test/integration/profiler_test.rb +0 -213
- data/test/integration/security_test.rb +0 -89
- data/test/integration/standard_filter_test.rb +0 -880
- data/test/integration/tag/disableable_test.rb +0 -59
- data/test/integration/tag_test.rb +0 -45
- data/test/integration/tags/break_tag_test.rb +0 -17
- data/test/integration/tags/continue_tag_test.rb +0 -17
- data/test/integration/tags/echo_test.rb +0 -13
- data/test/integration/tags/for_tag_test.rb +0 -466
- data/test/integration/tags/if_else_tag_test.rb +0 -190
- data/test/integration/tags/include_tag_test.rb +0 -269
- data/test/integration/tags/increment_tag_test.rb +0 -25
- data/test/integration/tags/liquid_tag_test.rb +0 -116
- data/test/integration/tags/raw_tag_test.rb +0 -34
- data/test/integration/tags/render_tag_test.rb +0 -213
- data/test/integration/tags/standard_tag_test.rb +0 -303
- data/test/integration/tags/statements_test.rb +0 -113
- data/test/integration/tags/table_row_test.rb +0 -66
- data/test/integration/tags/unless_else_tag_test.rb +0 -28
- data/test/integration/template_test.rb +0 -340
- data/test/integration/trim_mode_test.rb +0 -563
- data/test/integration/variable_test.rb +0 -138
- data/test/test_helper.rb +0 -207
- data/test/unit/block_unit_test.rb +0 -53
- data/test/unit/condition_unit_test.rb +0 -168
- data/test/unit/file_system_unit_test.rb +0 -37
- data/test/unit/i18n_unit_test.rb +0 -39
- data/test/unit/lexer_unit_test.rb +0 -53
- data/test/unit/parse_tree_visitor_test.rb +0 -261
- data/test/unit/parser_unit_test.rb +0 -84
- data/test/unit/partial_cache_unit_test.rb +0 -128
- data/test/unit/regexp_unit_test.rb +0 -46
- data/test/unit/static_registers_unit_test.rb +0 -156
- data/test/unit/strainer_factory_unit_test.rb +0 -100
- data/test/unit/strainer_template_unit_test.rb +0 -82
- data/test/unit/tag_unit_test.rb +0 -23
- data/test/unit/tags/case_tag_unit_test.rb +0 -12
- data/test/unit/tags/for_tag_unit_test.rb +0 -15
- data/test/unit/tags/if_tag_unit_test.rb +0 -10
- data/test/unit/template_factory_unit_test.rb +0 -12
- data/test/unit/template_unit_test.rb +0 -87
- data/test/unit/tokenizer_unit_test.rb +0 -62
- data/test/unit/variable_unit_test.rb +0 -164
@@ -22,39 +22,99 @@ module Liquid
|
|
22
22
|
)
|
23
23
|
STRIP_HTML_TAGS = /<.*?>/m
|
24
24
|
|
25
|
-
#
|
25
|
+
# @liquid_public_docs
|
26
|
+
# @liquid_type filter
|
27
|
+
# @liquid_category array
|
28
|
+
# @liquid_summary
|
29
|
+
# Returns the size of a string or array.
|
30
|
+
# @liquid_description
|
31
|
+
# The size of a string is the number of characters that the string includes. The size of an array is the number of items
|
32
|
+
# in the array.
|
33
|
+
# @liquid_syntax variable | size
|
34
|
+
# @liquid_return [number]
|
26
35
|
def size(input)
|
27
36
|
input.respond_to?(:size) ? input.size : 0
|
28
37
|
end
|
29
38
|
|
30
|
-
#
|
39
|
+
# @liquid_public_docs
|
40
|
+
# @liquid_type filter
|
41
|
+
# @liquid_category string
|
42
|
+
# @liquid_summary
|
43
|
+
# Converts a string to all lowercase characters.
|
44
|
+
# @liquid_syntax string | downcase
|
45
|
+
# @liquid_return [string]
|
31
46
|
def downcase(input)
|
32
47
|
input.to_s.downcase
|
33
48
|
end
|
34
49
|
|
35
|
-
#
|
50
|
+
# @liquid_public_docs
|
51
|
+
# @liquid_type filter
|
52
|
+
# @liquid_category string
|
53
|
+
# @liquid_summary
|
54
|
+
# Converts a string to all uppercase characters.
|
55
|
+
# @liquid_syntax string | upcase
|
56
|
+
# @liquid_return [string]
|
36
57
|
def upcase(input)
|
37
58
|
input.to_s.upcase
|
38
59
|
end
|
39
60
|
|
40
|
-
#
|
61
|
+
# @liquid_public_docs
|
62
|
+
# @liquid_type filter
|
63
|
+
# @liquid_category string
|
64
|
+
# @liquid_summary
|
65
|
+
# Capitalizes the first word in a string.
|
66
|
+
# @liquid_syntax string | capitalize
|
67
|
+
# @liquid_return [string]
|
41
68
|
def capitalize(input)
|
42
69
|
input.to_s.capitalize
|
43
70
|
end
|
44
71
|
|
72
|
+
# @liquid_public_docs
|
73
|
+
# @liquid_type filter
|
74
|
+
# @liquid_category string
|
75
|
+
# @liquid_summary
|
76
|
+
# Escapes a string.
|
77
|
+
# @liquid_syntax string | escape
|
78
|
+
# @liquid_return [string]
|
45
79
|
def escape(input)
|
46
80
|
CGI.escapeHTML(input.to_s) unless input.nil?
|
47
81
|
end
|
48
82
|
alias_method :h, :escape
|
49
83
|
|
84
|
+
# @liquid_public_docs
|
85
|
+
# @liquid_type filter
|
86
|
+
# @liquid_category string
|
87
|
+
# @liquid_summary
|
88
|
+
# Escapes a string without changing characters that have already been escaped.
|
89
|
+
# @liquid_syntax string | escape_once
|
90
|
+
# @liquid_return [string]
|
50
91
|
def escape_once(input)
|
51
92
|
input.to_s.gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE)
|
52
93
|
end
|
53
94
|
|
95
|
+
# @liquid_public_docs
|
96
|
+
# @liquid_type filter
|
97
|
+
# @liquid_category string
|
98
|
+
# @liquid_summary
|
99
|
+
# Converts any URL-unsafe characters in a string to the
|
100
|
+
# [percent-encoded](https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding) equivalent.
|
101
|
+
# @liquid_description
|
102
|
+
# > Note:
|
103
|
+
# > Spaces are converted to a `+` character, instead of a percent-encoded character.
|
104
|
+
# @liquid_syntax string | url_encode
|
105
|
+
# @liquid_return [string]
|
54
106
|
def url_encode(input)
|
55
107
|
CGI.escape(input.to_s) unless input.nil?
|
56
108
|
end
|
57
109
|
|
110
|
+
# @liquid_public_docs
|
111
|
+
# @liquid_type filter
|
112
|
+
# @liquid_category string
|
113
|
+
# @liquid_summary
|
114
|
+
# Decodes any [percent-encoded](https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding) characters
|
115
|
+
# in a string.
|
116
|
+
# @liquid_syntax string | url_decode
|
117
|
+
# @liquid_return [string]
|
58
118
|
def url_decode(input)
|
59
119
|
return if input.nil?
|
60
120
|
|
@@ -64,26 +124,64 @@ module Liquid
|
|
64
124
|
result
|
65
125
|
end
|
66
126
|
|
127
|
+
# @liquid_public_docs
|
128
|
+
# @liquid_type filter
|
129
|
+
# @liquid_category string
|
130
|
+
# @liquid_summary
|
131
|
+
# Encodes a string to [Base64 format](https://developer.mozilla.org/en-US/docs/Glossary/Base64).
|
132
|
+
# @liquid_syntax string | base64_encode
|
133
|
+
# @liquid_return [string]
|
67
134
|
def base64_encode(input)
|
68
135
|
Base64.strict_encode64(input.to_s)
|
69
136
|
end
|
70
137
|
|
138
|
+
# @liquid_public_docs
|
139
|
+
# @liquid_type filter
|
140
|
+
# @liquid_category string
|
141
|
+
# @liquid_summary
|
142
|
+
# Decodes a string in [Base64 format](https://developer.mozilla.org/en-US/docs/Glossary/Base64).
|
143
|
+
# @liquid_syntax string | base64_decode
|
144
|
+
# @liquid_return [string]
|
71
145
|
def base64_decode(input)
|
72
146
|
Base64.strict_decode64(input.to_s)
|
73
147
|
rescue ::ArgumentError
|
74
148
|
raise Liquid::ArgumentError, "invalid base64 provided to base64_decode"
|
75
149
|
end
|
76
150
|
|
151
|
+
# @liquid_public_docs
|
152
|
+
# @liquid_type filter
|
153
|
+
# @liquid_category string
|
154
|
+
# @liquid_summary
|
155
|
+
# Encodes a string to URL-safe [Base64 format](https://developer.mozilla.org/en-US/docs/Glossary/Base64).
|
156
|
+
# @liquid_syntax string | base64_url_safe_encode
|
157
|
+
# @liquid_return [string]
|
77
158
|
def base64_url_safe_encode(input)
|
78
159
|
Base64.urlsafe_encode64(input.to_s)
|
79
160
|
end
|
80
161
|
|
162
|
+
# @liquid_public_docs
|
163
|
+
# @liquid_type filter
|
164
|
+
# @liquid_category string
|
165
|
+
# @liquid_summary
|
166
|
+
# Decodes a string in URL-safe [Base64 format](https://developer.mozilla.org/en-US/docs/Glossary/Base64).
|
167
|
+
# @liquid_syntax string | base64_url_safe_decode
|
168
|
+
# @liquid_return [string]
|
81
169
|
def base64_url_safe_decode(input)
|
82
170
|
Base64.urlsafe_decode64(input.to_s)
|
83
171
|
rescue ::ArgumentError
|
84
172
|
raise Liquid::ArgumentError, "invalid base64 provided to base64_url_safe_decode"
|
85
173
|
end
|
86
174
|
|
175
|
+
# @liquid_public_docs
|
176
|
+
# @liquid_type filter
|
177
|
+
# @liquid_category string
|
178
|
+
# @liquid_summary
|
179
|
+
# Returns a substring or series of array items, starting at a given 0-based index.
|
180
|
+
# @liquid_description
|
181
|
+
# By default, the substring has a length of one character, and the array series has one array item. However, you can
|
182
|
+
# provide a second parameter to specify the number of characters or array items.
|
183
|
+
# @liquid_syntax string | slice
|
184
|
+
# @liquid_return [string]
|
87
185
|
def slice(input, offset, length = nil)
|
88
186
|
offset = Utils.to_integer(offset)
|
89
187
|
length = length ? Utils.to_integer(length) : 1
|
@@ -95,7 +193,16 @@ module Liquid
|
|
95
193
|
end
|
96
194
|
end
|
97
195
|
|
98
|
-
#
|
196
|
+
# @liquid_public_docs
|
197
|
+
# @liquid_type filter
|
198
|
+
# @liquid_category string
|
199
|
+
# @liquid_summary
|
200
|
+
# Truncates a string down to a given number of characters.
|
201
|
+
# @liquid_description
|
202
|
+
# If the specified number of characters is less than the length of the string, then an ellipsis (`...`) is appended to
|
203
|
+
# the truncated string. The ellipsis is included in the character count of the truncated string.
|
204
|
+
# @liquid_syntax string | truncate: number
|
205
|
+
# @liquid_return [string]
|
99
206
|
def truncate(input, length = 50, truncate_string = "...")
|
100
207
|
return if input.nil?
|
101
208
|
input_str = input.to_s
|
@@ -109,6 +216,20 @@ module Liquid
|
|
109
216
|
input_str.length > length ? input_str[0...l].concat(truncate_string_str) : input_str
|
110
217
|
end
|
111
218
|
|
219
|
+
# @liquid_public_docs
|
220
|
+
# @liquid_type filter
|
221
|
+
# @liquid_category string
|
222
|
+
# @liquid_summary
|
223
|
+
# Truncates a string down to a given number of words.
|
224
|
+
# @liquid_description
|
225
|
+
# If the specified number of words is less than the number of words in the string, then an ellipsis (`...`) is appended to
|
226
|
+
# the truncated string.
|
227
|
+
#
|
228
|
+
# > Caution:
|
229
|
+
# > HTML tags are treated as words, so you should strip any HTML from truncated content. If you don't strip HTML, then
|
230
|
+
# > closing HTML tags can be removed, which can result in unexpected behavior.
|
231
|
+
# @liquid_syntax string | truncatewords: number
|
232
|
+
# @liquid_return [string]
|
112
233
|
def truncatewords(input, words = 15, truncate_string = "...")
|
113
234
|
return if input.nil?
|
114
235
|
input = input.to_s
|
@@ -128,27 +249,57 @@ module Liquid
|
|
128
249
|
wordlist.join(" ").concat(truncate_string.to_s)
|
129
250
|
end
|
130
251
|
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
252
|
+
# @liquid_public_docs
|
253
|
+
# @liquid_type filter
|
254
|
+
# @liquid_category string
|
255
|
+
# @liquid_summary
|
256
|
+
# Splits a string into an array of substrings based on a given separator.
|
257
|
+
# @liquid_syntax string | split: string
|
258
|
+
# @liquid_return [array[string]]
|
136
259
|
def split(input, pattern)
|
137
260
|
input.to_s.split(pattern.to_s)
|
138
261
|
end
|
139
262
|
|
263
|
+
# @liquid_public_docs
|
264
|
+
# @liquid_type filter
|
265
|
+
# @liquid_category string
|
266
|
+
# @liquid_summary
|
267
|
+
# Strips all whitespace from the left and right of a string.
|
268
|
+
# @liquid_syntax string | strip
|
269
|
+
# @liquid_return [string]
|
140
270
|
def strip(input)
|
141
271
|
input.to_s.strip
|
142
272
|
end
|
143
273
|
|
274
|
+
# @liquid_public_docs
|
275
|
+
# @liquid_type filter
|
276
|
+
# @liquid_category string
|
277
|
+
# @liquid_summary
|
278
|
+
# Strips all whitespace from the left of a string.
|
279
|
+
# @liquid_syntax string | lstrip
|
280
|
+
# @liquid_return [string]
|
144
281
|
def lstrip(input)
|
145
282
|
input.to_s.lstrip
|
146
283
|
end
|
147
284
|
|
285
|
+
# @liquid_public_docs
|
286
|
+
# @liquid_type filter
|
287
|
+
# @liquid_category string
|
288
|
+
# @liquid_summary
|
289
|
+
# Strips all whitespace from the right of a string.
|
290
|
+
# @liquid_syntax string | rstrip
|
291
|
+
# @liquid_return [string]
|
148
292
|
def rstrip(input)
|
149
293
|
input.to_s.rstrip
|
150
294
|
end
|
151
295
|
|
296
|
+
# @liquid_public_docs
|
297
|
+
# @liquid_type filter
|
298
|
+
# @liquid_category string
|
299
|
+
# @liquid_summary
|
300
|
+
# Strips all HTML tags from a string.
|
301
|
+
# @liquid_syntax string | strip_html
|
302
|
+
# @liquid_return [string]
|
152
303
|
def strip_html(input)
|
153
304
|
empty = ''
|
154
305
|
result = input.to_s.gsub(STRIP_HTML_BLOCKS, empty)
|
@@ -156,18 +307,35 @@ module Liquid
|
|
156
307
|
result
|
157
308
|
end
|
158
309
|
|
159
|
-
#
|
310
|
+
# @liquid_public_docs
|
311
|
+
# @liquid_type filter
|
312
|
+
# @liquid_category string
|
313
|
+
# @liquid_summary
|
314
|
+
# Strips all newline characters (line breaks) from a string.
|
315
|
+
# @liquid_syntax string | strip_newlines
|
316
|
+
# @liquid_return [string]
|
160
317
|
def strip_newlines(input)
|
161
318
|
input.to_s.gsub(/\r?\n/, '')
|
162
319
|
end
|
163
320
|
|
164
|
-
#
|
321
|
+
# @liquid_public_docs
|
322
|
+
# @liquid_type filter
|
323
|
+
# @liquid_category array
|
324
|
+
# @liquid_summary
|
325
|
+
# Combines all of the items in an array into a single string, separated by a space.
|
326
|
+
# @liquid_syntax array | join
|
327
|
+
# @liquid_return [string]
|
165
328
|
def join(input, glue = ' ')
|
166
329
|
InputIterator.new(input, context).join(glue)
|
167
330
|
end
|
168
331
|
|
169
|
-
#
|
170
|
-
#
|
332
|
+
# @liquid_public_docs
|
333
|
+
# @liquid_type filter
|
334
|
+
# @liquid_category array
|
335
|
+
# @liquid_summary
|
336
|
+
# Sorts the items in an array in case-sensitive alphabetical, or numerical, order.
|
337
|
+
# @liquid_syntax array | sort
|
338
|
+
# @liquid_return [array[untyped]]
|
171
339
|
def sort(input, property = nil)
|
172
340
|
ary = InputIterator.new(input, context)
|
173
341
|
|
@@ -186,8 +354,17 @@ module Liquid
|
|
186
354
|
end
|
187
355
|
end
|
188
356
|
|
189
|
-
#
|
190
|
-
#
|
357
|
+
# @liquid_public_docs
|
358
|
+
# @liquid_type filter
|
359
|
+
# @liquid_category array
|
360
|
+
# @liquid_summary
|
361
|
+
# Sorts the items in an array in case-insensitive alphabetical order.
|
362
|
+
# @liquid_description
|
363
|
+
# > Caution:
|
364
|
+
# > You shouldn't use the `sort_natural` filter to sort numerical values. When comparing items an array, each item is converted to a
|
365
|
+
# > string, so sorting on numerical values can lead to unexpected results.
|
366
|
+
# @liquid_syntax array | sort_natural
|
367
|
+
# @liquid_return [array[untyped]]
|
191
368
|
def sort_natural(input, property = nil)
|
192
369
|
ary = InputIterator.new(input, context)
|
193
370
|
|
@@ -206,30 +383,48 @@ module Liquid
|
|
206
383
|
end
|
207
384
|
end
|
208
385
|
|
209
|
-
#
|
210
|
-
#
|
386
|
+
# @liquid_public_docs
|
387
|
+
# @liquid_type filter
|
388
|
+
# @liquid_category array
|
389
|
+
# @liquid_summary
|
390
|
+
# Filters an array to include only items with a specific property value.
|
391
|
+
# @liquid_description
|
392
|
+
# This requires you to provide both the property name and the associated value.
|
393
|
+
# @liquid_syntax array | where: string, string
|
394
|
+
# @liquid_return [array[untyped]]
|
211
395
|
def where(input, property, target_value = nil)
|
212
396
|
ary = InputIterator.new(input, context)
|
213
397
|
|
214
398
|
if ary.empty?
|
215
399
|
[]
|
216
|
-
elsif
|
217
|
-
|
218
|
-
|
400
|
+
elsif target_value.nil?
|
401
|
+
ary.select do |item|
|
402
|
+
item[property]
|
219
403
|
rescue TypeError
|
220
404
|
raise_property_error(property)
|
405
|
+
rescue NoMethodError
|
406
|
+
return nil unless item.respond_to?(:[])
|
407
|
+
raise
|
221
408
|
end
|
222
|
-
|
223
|
-
|
224
|
-
|
409
|
+
else
|
410
|
+
ary.select do |item|
|
411
|
+
item[property] == target_value
|
225
412
|
rescue TypeError
|
226
413
|
raise_property_error(property)
|
414
|
+
rescue NoMethodError
|
415
|
+
return nil unless item.respond_to?(:[])
|
416
|
+
raise
|
227
417
|
end
|
228
418
|
end
|
229
419
|
end
|
230
420
|
|
231
|
-
#
|
232
|
-
#
|
421
|
+
# @liquid_public_docs
|
422
|
+
# @liquid_type filter
|
423
|
+
# @liquid_category array
|
424
|
+
# @liquid_summary
|
425
|
+
# Removes any duplicate items in an array.
|
426
|
+
# @liquid_syntax array | uniq
|
427
|
+
# @liquid_return [array[untyped]]
|
233
428
|
def uniq(input, property = nil)
|
234
429
|
ary = InputIterator.new(input, context)
|
235
430
|
|
@@ -237,22 +432,37 @@ module Liquid
|
|
237
432
|
ary.uniq
|
238
433
|
elsif ary.empty? # The next two cases assume a non-empty array.
|
239
434
|
[]
|
240
|
-
|
241
|
-
|
242
|
-
|
435
|
+
else
|
436
|
+
ary.uniq do |item|
|
437
|
+
item[property]
|
243
438
|
rescue TypeError
|
244
439
|
raise_property_error(property)
|
440
|
+
rescue NoMethodError
|
441
|
+
return nil unless item.respond_to?(:[])
|
442
|
+
raise
|
245
443
|
end
|
246
444
|
end
|
247
445
|
end
|
248
446
|
|
249
|
-
#
|
447
|
+
# @liquid_public_docs
|
448
|
+
# @liquid_type filter
|
449
|
+
# @liquid_category array
|
450
|
+
# @liquid_summary
|
451
|
+
# Reverses the order of the items in an array.
|
452
|
+
# @liquid_syntax array | reverse
|
453
|
+
# @liquid_return [array[untyped]]
|
250
454
|
def reverse(input)
|
251
455
|
ary = InputIterator.new(input, context)
|
252
456
|
ary.reverse
|
253
457
|
end
|
254
458
|
|
255
|
-
#
|
459
|
+
# @liquid_public_docs
|
460
|
+
# @liquid_type filter
|
461
|
+
# @liquid_category array
|
462
|
+
# @liquid_summary
|
463
|
+
# Creates an array of values from a specific property of the items in an array.
|
464
|
+
# @liquid_syntax array | map: string
|
465
|
+
# @liquid_return [array[untyped]]
|
256
466
|
def map(input, property)
|
257
467
|
InputIterator.new(input, context).map do |e|
|
258
468
|
e = e.call if e.is_a?(Proc)
|
@@ -268,8 +478,13 @@ module Liquid
|
|
268
478
|
raise_property_error(property)
|
269
479
|
end
|
270
480
|
|
271
|
-
#
|
272
|
-
#
|
481
|
+
# @liquid_public_docs
|
482
|
+
# @liquid_type filter
|
483
|
+
# @liquid_category array
|
484
|
+
# @liquid_summary
|
485
|
+
# Removes any `nil` items from an array.
|
486
|
+
# @liquid_syntax array | compact
|
487
|
+
# @liquid_return [array[untyped]]
|
273
488
|
def compact(input, property = nil)
|
274
489
|
ary = InputIterator.new(input, context)
|
275
490
|
|
@@ -277,40 +492,116 @@ module Liquid
|
|
277
492
|
ary.compact
|
278
493
|
elsif ary.empty? # The next two cases assume a non-empty array.
|
279
494
|
[]
|
280
|
-
|
281
|
-
|
282
|
-
|
495
|
+
else
|
496
|
+
ary.reject do |item|
|
497
|
+
item[property].nil?
|
283
498
|
rescue TypeError
|
284
499
|
raise_property_error(property)
|
500
|
+
rescue NoMethodError
|
501
|
+
return nil unless item.respond_to?(:[])
|
502
|
+
raise
|
285
503
|
end
|
286
504
|
end
|
287
505
|
end
|
288
506
|
|
289
|
-
#
|
507
|
+
# @liquid_public_docs
|
508
|
+
# @liquid_type filter
|
509
|
+
# @liquid_category string
|
510
|
+
# @liquid_summary
|
511
|
+
# Replaces any instance of a substring inside a string with a given string.
|
512
|
+
# @liquid_syntax string | replace: string, string
|
513
|
+
# @liquid_return [string]
|
290
514
|
def replace(input, string, replacement = '')
|
291
515
|
input.to_s.gsub(string.to_s, replacement.to_s)
|
292
516
|
end
|
293
517
|
|
294
|
-
#
|
518
|
+
# @liquid_public_docs
|
519
|
+
# @liquid_type filter
|
520
|
+
# @liquid_category string
|
521
|
+
# @liquid_summary
|
522
|
+
# Replaces the first instance of a substring inside a string with a given string.
|
523
|
+
# @liquid_syntax string | replace_first: string, string
|
524
|
+
# @liquid_return [string]
|
295
525
|
def replace_first(input, string, replacement = '')
|
296
526
|
input.to_s.sub(string.to_s, replacement.to_s)
|
297
527
|
end
|
298
528
|
|
299
|
-
#
|
300
|
-
|
301
|
-
|
529
|
+
# @liquid_public_docs
|
530
|
+
# @liquid_type filter
|
531
|
+
# @liquid_category string
|
532
|
+
# @liquid_summary
|
533
|
+
# Replaces the last instance of a substring inside a string with a given string.
|
534
|
+
# @liquid_syntax string | replace_last: string, string
|
535
|
+
# @liquid_return [string]
|
536
|
+
def replace_last(input, string, replacement)
|
537
|
+
input = input.to_s
|
538
|
+
string = string.to_s
|
539
|
+
replacement = replacement.to_s
|
540
|
+
|
541
|
+
start_index = input.rindex(string)
|
542
|
+
|
543
|
+
return input unless start_index
|
544
|
+
|
545
|
+
output = input.dup
|
546
|
+
output[start_index, string.length] = replacement
|
547
|
+
output
|
302
548
|
end
|
303
549
|
|
304
|
-
#
|
305
|
-
|
306
|
-
|
550
|
+
# @liquid_public_docs
|
551
|
+
# @liquid_type filter
|
552
|
+
# @liquid_category string
|
553
|
+
# @liquid_summary
|
554
|
+
# Removes any instance of a substring inside a string.
|
555
|
+
# @liquid_syntax string | remove: string
|
556
|
+
# @liquid_return [string]
|
557
|
+
def remove(input, string)
|
558
|
+
replace(input, string, '')
|
307
559
|
end
|
308
560
|
|
309
|
-
#
|
561
|
+
# @liquid_public_docs
|
562
|
+
# @liquid_type filter
|
563
|
+
# @liquid_category string
|
564
|
+
# @liquid_summary
|
565
|
+
# Removes the first instance of a substring inside a string.
|
566
|
+
# @liquid_syntax string | remove_first: string
|
567
|
+
# @liquid_return [string]
|
568
|
+
def remove_first(input, string)
|
569
|
+
replace_first(input, string, '')
|
570
|
+
end
|
571
|
+
|
572
|
+
# @liquid_public_docs
|
573
|
+
# @liquid_type filter
|
574
|
+
# @liquid_category string
|
575
|
+
# @liquid_summary
|
576
|
+
# Removes the last instance of a substring inside a string.
|
577
|
+
# @liquid_syntax string | remove_last: string
|
578
|
+
# @liquid_return [string]
|
579
|
+
def remove_last(input, string)
|
580
|
+
replace_last(input, string, '')
|
581
|
+
end
|
582
|
+
|
583
|
+
# @liquid_public_docs
|
584
|
+
# @liquid_type filter
|
585
|
+
# @liquid_category string
|
586
|
+
# @liquid_summary
|
587
|
+
# Adds a given string to the end of a string.
|
588
|
+
# @liquid_syntax string | append: string
|
589
|
+
# @liquid_return [string]
|
310
590
|
def append(input, string)
|
311
591
|
input.to_s + string.to_s
|
312
592
|
end
|
313
593
|
|
594
|
+
# @liquid_public_docs
|
595
|
+
# @liquid_type filter
|
596
|
+
# @liquid_category array
|
597
|
+
# @liquid_summary
|
598
|
+
# Concatenates (combines) two arrays.
|
599
|
+
# @liquid_description
|
600
|
+
# > Note:
|
601
|
+
# > The `concat` filter won't filter out duplicates. If you want to remove duplicates, then you need to use the
|
602
|
+
# > [`uniq` filter](/api/liquid/filters#uniq).
|
603
|
+
# @liquid_syntax array | concat: array
|
604
|
+
# @liquid_return [array[untyped]]
|
314
605
|
def concat(input, array)
|
315
606
|
unless array.respond_to?(:to_ary)
|
316
607
|
raise ArgumentError, "concat filter requires an array argument"
|
@@ -318,12 +609,24 @@ module Liquid
|
|
318
609
|
InputIterator.new(input, context).concat(array)
|
319
610
|
end
|
320
611
|
|
321
|
-
#
|
612
|
+
# @liquid_public_docs
|
613
|
+
# @liquid_type filter
|
614
|
+
# @liquid_category string
|
615
|
+
# @liquid_summary
|
616
|
+
# Adds a given string to the beginning of a string.
|
617
|
+
# @liquid_syntax string | prepend: string
|
618
|
+
# @liquid_return [string]
|
322
619
|
def prepend(input, string)
|
323
620
|
string.to_s + input.to_s
|
324
621
|
end
|
325
622
|
|
326
|
-
#
|
623
|
+
# @liquid_public_docs
|
624
|
+
# @liquid_type filter
|
625
|
+
# @liquid_category string
|
626
|
+
# @liquid_summary
|
627
|
+
# Converts newlines (`\n`) in a string to HTML line breaks (`<br>`).
|
628
|
+
# @liquid_syntax string | newline_to_br
|
629
|
+
# @liquid_return [string]
|
327
630
|
def newline_to_br(input)
|
328
631
|
input.to_s.gsub(/\r?\n/, "<br />\n")
|
329
632
|
end
|
@@ -367,58 +670,106 @@ module Liquid
|
|
367
670
|
date.strftime(format.to_s)
|
368
671
|
end
|
369
672
|
|
370
|
-
#
|
371
|
-
#
|
372
|
-
#
|
373
|
-
#
|
374
|
-
#
|
673
|
+
# @liquid_public_docs
|
674
|
+
# @liquid_type filter
|
675
|
+
# @liquid_category array
|
676
|
+
# @liquid_summary
|
677
|
+
# Returns the first item in an array.
|
678
|
+
# @liquid_syntax array | first
|
679
|
+
# @liquid_return [untyped]
|
375
680
|
def first(array)
|
376
681
|
array.first if array.respond_to?(:first)
|
377
682
|
end
|
378
683
|
|
379
|
-
#
|
380
|
-
#
|
381
|
-
#
|
382
|
-
#
|
383
|
-
#
|
684
|
+
# @liquid_public_docs
|
685
|
+
# @liquid_type filter
|
686
|
+
# @liquid_category array
|
687
|
+
# @liquid_summary
|
688
|
+
# Returns the last item in an array.
|
689
|
+
# @liquid_syntax array | last
|
690
|
+
# @liquid_return [untyped]
|
384
691
|
def last(array)
|
385
692
|
array.last if array.respond_to?(:last)
|
386
693
|
end
|
387
694
|
|
388
|
-
#
|
695
|
+
# @liquid_public_docs
|
696
|
+
# @liquid_type filter
|
697
|
+
# @liquid_category math
|
698
|
+
# @liquid_summary
|
699
|
+
# Returns the absolute value of a number.
|
700
|
+
# @liquid_syntax number | abs
|
701
|
+
# @liquid_return [number]
|
389
702
|
def abs(input)
|
390
703
|
result = Utils.to_number(input).abs
|
391
704
|
result.is_a?(BigDecimal) ? result.to_f : result
|
392
705
|
end
|
393
706
|
|
394
|
-
#
|
707
|
+
# @liquid_public_docs
|
708
|
+
# @liquid_type filter
|
709
|
+
# @liquid_category math
|
710
|
+
# @liquid_summary
|
711
|
+
# Adds two numbers.
|
712
|
+
# @liquid_syntax number | plus: number
|
713
|
+
# @liquid_return [number]
|
395
714
|
def plus(input, operand)
|
396
715
|
apply_operation(input, operand, :+)
|
397
716
|
end
|
398
717
|
|
399
|
-
#
|
718
|
+
# @liquid_public_docs
|
719
|
+
# @liquid_type filter
|
720
|
+
# @liquid_category math
|
721
|
+
# @liquid_summary
|
722
|
+
# Subtracts a given number from another number.
|
723
|
+
# @liquid_syntax number | minus: number
|
724
|
+
# @liquid_return [number]
|
400
725
|
def minus(input, operand)
|
401
726
|
apply_operation(input, operand, :-)
|
402
727
|
end
|
403
728
|
|
404
|
-
#
|
729
|
+
# @liquid_public_docs
|
730
|
+
# @liquid_type filter
|
731
|
+
# @liquid_category math
|
732
|
+
# @liquid_summary
|
733
|
+
# Multiplies a number by a given number.
|
734
|
+
# @liquid_syntax number | times: number
|
735
|
+
# @liquid_return [number]
|
405
736
|
def times(input, operand)
|
406
737
|
apply_operation(input, operand, :*)
|
407
738
|
end
|
408
739
|
|
409
|
-
#
|
740
|
+
# @liquid_public_docs
|
741
|
+
# @liquid_type filter
|
742
|
+
# @liquid_category math
|
743
|
+
# @liquid_summary
|
744
|
+
# Divides a number by a given number.
|
745
|
+
# @liquid_syntax number | divided_by: number
|
746
|
+
# @liquid_return [number]
|
410
747
|
def divided_by(input, operand)
|
411
748
|
apply_operation(input, operand, :/)
|
412
749
|
rescue ::ZeroDivisionError => e
|
413
750
|
raise Liquid::ZeroDivisionError, e.message
|
414
751
|
end
|
415
752
|
|
753
|
+
# @liquid_public_docs
|
754
|
+
# @liquid_type filter
|
755
|
+
# @liquid_category math
|
756
|
+
# @liquid_summary
|
757
|
+
# Returns the remainder of dividing a number by a given number.
|
758
|
+
# @liquid_syntax number | modulo: number
|
759
|
+
# @liquid_return [number]
|
416
760
|
def modulo(input, operand)
|
417
761
|
apply_operation(input, operand, :%)
|
418
762
|
rescue ::ZeroDivisionError => e
|
419
763
|
raise Liquid::ZeroDivisionError, e.message
|
420
764
|
end
|
421
765
|
|
766
|
+
# @liquid_public_docs
|
767
|
+
# @liquid_type filter
|
768
|
+
# @liquid_category math
|
769
|
+
# @liquid_summary
|
770
|
+
# Rounds a number to the nearest integer.
|
771
|
+
# @liquid_syntax number | round
|
772
|
+
# @liquid_return [number]
|
422
773
|
def round(input, n = 0)
|
423
774
|
result = Utils.to_number(input).round(Utils.to_number(n))
|
424
775
|
result = result.to_f if result.is_a?(BigDecimal)
|
@@ -428,18 +779,39 @@ module Liquid
|
|
428
779
|
raise Liquid::FloatDomainError, e.message
|
429
780
|
end
|
430
781
|
|
782
|
+
# @liquid_public_docs
|
783
|
+
# @liquid_type filter
|
784
|
+
# @liquid_category math
|
785
|
+
# @liquid_summary
|
786
|
+
# Rounds a number up to the nearest integer.
|
787
|
+
# @liquid_syntax number | ceil
|
788
|
+
# @liquid_return [number]
|
431
789
|
def ceil(input)
|
432
790
|
Utils.to_number(input).ceil.to_i
|
433
791
|
rescue ::FloatDomainError => e
|
434
792
|
raise Liquid::FloatDomainError, e.message
|
435
793
|
end
|
436
794
|
|
795
|
+
# @liquid_public_docs
|
796
|
+
# @liquid_type filter
|
797
|
+
# @liquid_category math
|
798
|
+
# @liquid_summary
|
799
|
+
# Rounds a number down to the nearest integer.
|
800
|
+
# @liquid_syntax number | floor
|
801
|
+
# @liquid_return [number]
|
437
802
|
def floor(input)
|
438
803
|
Utils.to_number(input).floor.to_i
|
439
804
|
rescue ::FloatDomainError => e
|
440
805
|
raise Liquid::FloatDomainError, e.message
|
441
806
|
end
|
442
807
|
|
808
|
+
# @liquid_public_docs
|
809
|
+
# @liquid_type filter
|
810
|
+
# @liquid_category math
|
811
|
+
# @liquid_summary
|
812
|
+
# Limits a number to a minimum value.
|
813
|
+
# @liquid_syntax number | at_least
|
814
|
+
# @liquid_return [number]
|
443
815
|
def at_least(input, n)
|
444
816
|
min_value = Utils.to_number(n)
|
445
817
|
|
@@ -448,6 +820,13 @@ module Liquid
|
|
448
820
|
result.is_a?(BigDecimal) ? result.to_f : result
|
449
821
|
end
|
450
822
|
|
823
|
+
# @liquid_public_docs
|
824
|
+
# @liquid_type filter
|
825
|
+
# @liquid_category math
|
826
|
+
# @liquid_summary
|
827
|
+
# Limits a number to a maximum value.
|
828
|
+
# @liquid_syntax number | at_most
|
829
|
+
# @liquid_return [number]
|
451
830
|
def at_most(input, n)
|
452
831
|
max_value = Utils.to_number(n)
|
453
832
|
|
@@ -456,16 +835,18 @@ module Liquid
|
|
456
835
|
result.is_a?(BigDecimal) ? result.to_f : result
|
457
836
|
end
|
458
837
|
|
459
|
-
#
|
460
|
-
#
|
461
|
-
#
|
462
|
-
#
|
463
|
-
#
|
464
|
-
# Use `allow_false` when an input should only be tested against nil or empty and not false.
|
465
|
-
#
|
466
|
-
# Example:
|
467
|
-
# {{ product.title | default: "No Title", allow_false: true }}
|
838
|
+
# @liquid_public_docs
|
839
|
+
# @liquid_type filter
|
840
|
+
# @liquid_category default
|
841
|
+
# @liquid_summary
|
842
|
+
# Sets a default value for any variable whose value is one of the following:
|
468
843
|
#
|
844
|
+
# - [`empty`](/api/liquid/basics#empty)
|
845
|
+
# - [`false`](/api/liquid/basics#truthy-and-falsy)
|
846
|
+
# - [`nil`](/api/liquid/basics#nil)
|
847
|
+
# @liquid_syntax variable | default: variable
|
848
|
+
# @liquid_return [untyped]
|
849
|
+
# @liquid_optional_param allow_false [boolean] Whether to use false values instead of the default.
|
469
850
|
def default(input, default_value = '', options = {})
|
470
851
|
options = {} unless options.is_a?(Hash)
|
471
852
|
false_check = options['allow_false'] ? input.nil? : !Liquid::Utils.to_liquid_value(input)
|
@@ -486,10 +867,16 @@ module Liquid
|
|
486
867
|
end
|
487
868
|
|
488
869
|
def nil_safe_compare(a, b)
|
489
|
-
|
490
|
-
|
870
|
+
result = a <=> b
|
871
|
+
|
872
|
+
if result
|
873
|
+
result
|
874
|
+
elsif a.nil?
|
875
|
+
1
|
876
|
+
elsif b.nil?
|
877
|
+
-1
|
491
878
|
else
|
492
|
-
|
879
|
+
raise Liquid::ArgumentError, "cannot sort values of incompatible types"
|
493
880
|
end
|
494
881
|
end
|
495
882
|
|
@@ -544,8 +931,9 @@ module Liquid
|
|
544
931
|
|
545
932
|
def each
|
546
933
|
@input.each do |e|
|
934
|
+
e = e.respond_to?(:to_liquid) ? e.to_liquid : e
|
547
935
|
e.context = @context if e.respond_to?(:context=)
|
548
|
-
yield(e
|
936
|
+
yield(e)
|
549
937
|
end
|
550
938
|
end
|
551
939
|
end
|