Module: Liquid2::Filters
- Defined in:
- lib/liquid2/filter.rb,
lib/liquid2/filters/date.rb,
lib/liquid2/filters/json.rb,
lib/liquid2/filters/math.rb,
lib/liquid2/filters/size.rb,
lib/liquid2/filters/sort.rb,
lib/liquid2/filters/array.rb,
lib/liquid2/filters/slice.rb,
lib/liquid2/filters/string.rb,
lib/liquid2/filters/default.rb
Overview
Liquid filters and helper methods.
Constant Summary collapse
- INFINITY_ARRAY =
: [Float]
[Float::INFINITY].freeze
- RE_HTML_BLOCKS =
Regexp.union( %r{<script.*?</script>}m, /<!--.*?-->/m, %r{<style.*?</style>}m )
- RE_HTML_TAGS =
/<.*?>/m
Class Method Summary collapse
-
.abs(left) ⇒ Object
Return the absolute value of left.
-
.append(left, right) ⇒ Object
Return left concatenated with right.
-
.at_least(left, right) ⇒ Object
Return the maximum of left and right.
-
.at_most(left, right) ⇒ Object
Return the minimum of left and right.
- .base64_decode(left) ⇒ Object
- .base64_encode(left) ⇒ Object
- .base64_url_safe_decode(left) ⇒ Object
- .base64_url_safe_encode(left) ⇒ Object
- .better_slice(left, start_ = :undefined, stop_ = :undefined, step_ = :undefined, start: :undefined, stop: :undefined, step: :undefined) ⇒ Object
-
.capitalize(left) ⇒ Object
Return left with the first character in uppercase and the rest lowercase.
-
.ceil(left) ⇒ Object
Return left rounded up to the next whole number.
-
.compact(left, key = :undefined, context:) ⇒ Object
Return a copy of left with nil items removed.
-
.concat(left, right) ⇒ Object
Return left concatenated with right, or nil if right is not an array.
-
.date(left, format) ⇒ Object
Format date and time object left with format.
-
.default(left, default = "", context:, allow_false: false) ⇒ Object
Return left, or default if obj is
nil,falseor empty. -
.divided_by(left, right) ⇒ Object
Return the result of dividing left by right.
-
.downcase(left) ⇒ Object
Return left with all characters converted to lowercase.
-
.escape(left) ⇒ Object
Return left with special HTML characters replaced with their HTML-safe escape sequences.
-
.escape_once(left) ⇒ Object
Return left with special HTML characters replaced with their HTML-safe escape sequences.
- .fetch(obj, key, default = nil) ⇒ Object
- .find(left, key, value = nil, context:) ⇒ Object
- .find_index(left, key, value = nil, context:) ⇒ Object
-
.first(left) ⇒ Object
Return the first item in left, or
nilif left does not have a first item. -
.floor(left) ⇒ Object
Return left rounded down to the next whole number.
- .has(left, key, value = nil, context:) ⇒ Object
- .ints(obj) ⇒ Object
-
.join(left, sep = " ") ⇒ Object
Return the concatenation of items in left separated by sep.
-
.json(left, pretty: false) ⇒ Object
Return left serialized in JSON format.
-
.last(left) ⇒ Object
Return the last item in left, or
nilif left does not have a last item. -
.lstrip(left) ⇒ Object
Return left with leading whitespace removed.
- .map(left, key, context:) ⇒ Object
-
.minus(left, right) ⇒ Object
Return right subtracted from left.
-
.modulo(left, right) ⇒ Object
Return the remainder of dividing left by right.
-
.newline_to_br(left) ⇒ Object
Return left with LF or CRLF replaced with
<br />\n. - .nil_safe_casecmp(left, right) ⇒ Object
- .nil_safe_compare(left, right) ⇒ Object
- .numeric_compare(left, right) ⇒ Object
-
.plus(left, right) ⇒ Object
Return right added to left.
-
.prepend(left, right) ⇒ Object
Return right concatenated with left.
- .reject(left, key, value = nil, context:) ⇒ Object
-
.remove(left, pattern) ⇒ Object
Return left with all occurrences of pattern removed.
-
.remove_first(left, pattern) ⇒ Object
Return left with the first occurrence of pattern removed.
-
.remove_last(left, pattern) ⇒ Object
Return left with the last occurrence of pattern removed.
-
.replace(left, pattern, replacement = "") ⇒ Object
Return left with all occurrences of pattern replaced with replacement.
-
.replace_first(left, pattern, replacement = "") ⇒ Object
Return left with the first occurrence of pattern replaced with replacement.
-
.replace_last(left, pattern, replacement) ⇒ Object
Return left with the last occurrence of pattern replaced with replacement.
-
.reverse(left) ⇒ Object
Return left with all items in reverse order.
-
.round(left, ndigits = 0) ⇒ Object
Return left rounded to ndigits decimal digits.
-
.rstrip(left) ⇒ Object
Return left with trailing whitespace removed.
-
.size(left) ⇒ Object
Return the size of left, or zero if left has no size.
-
.slice(left, start, length = 1) ⇒ Object
Return the subsequence of left starting at start up to length.
- .sort(left, key = nil, context:) ⇒ Object
- .sort_natural(left, key = nil, context:) ⇒ Object
- .sort_numeric(left, key = nil, context:) ⇒ Object
-
.split(left, pattern) ⇒ Object
Split left on every occurrence of pattern.
-
.strip(left) ⇒ Object
Return left with leading and trailing whitespace removed.
-
.strip_html(left) ⇒ Object
Return left with HTML tags removed.
-
.strip_newlines(left) ⇒ Object
Return left with CR and LF removed.
- .sum(left, key = nil, context:) ⇒ Object
-
.times(left, right) ⇒ Object
Return the result of multiplying left by right.
-
.to_date(obj) ⇒ Object
Cast obj to a date and time.
-
.to_decimal(obj, default: 0) ⇒ Object
Cast obj to a number, favouring BigDecimal over Float.
-
.to_enumerable(obj) ⇒ Enumerable
Cast obj to an enumerable for use in a Liquid filter.
-
.to_integer(obj) ⇒ Object
Case obj to an Integer.
-
.to_number(obj, default: 0) ⇒ Object
Cast obj to a number.
- .truncate(left, max_length = 50, ellipsis = "...") ⇒ Object
- .truncatewords(left, max_words = 15, ellipsis = "...") ⇒ Object
-
.uniq(left, key = nil, context:) ⇒ Object
Deduplicate items in left.
-
.upcase(left) ⇒ Object
Return left with all characters converted to uppercase.
- .url_decode(left) ⇒ Object
- .url_encode(left) ⇒ Object
- .where(left, key, value = nil, context:) ⇒ Object
Class Method Details
.abs(left) ⇒ Object
Return the absolute value of left.
7 8 9 |
# File 'lib/liquid2/filters/math.rb', line 7 def self.abs(left) to_number(left).abs end |
.append(left, right) ⇒ Object
Return left concatenated with right. Coerce left and right to strings if they aren't strings already.
11 12 13 |
# File 'lib/liquid2/filters/string.rb', line 11 def self.append(left, right) Liquid2.to_s(left) + Liquid2.to_s(right) end |
.at_least(left, right) ⇒ Object
Return the maximum of left and right.
12 13 14 |
# File 'lib/liquid2/filters/math.rb', line 12 def self.at_least(left, right) [to_number(left), to_number(right)].max end |
.at_most(left, right) ⇒ Object
Return the minimum of left and right.
17 18 19 |
# File 'lib/liquid2/filters/math.rb', line 17 def self.at_most(left, right) [to_number(left), to_number(right)].min end |
.base64_decode(left) ⇒ Object
190 191 192 193 |
# File 'lib/liquid2/filters/string.rb', line 190 def self.base64_decode(left) decoded = Base64.strict_decode64(Liquid2.to_s(left)).force_encoding(Encoding::UTF_8) decoded if decoded.valid_encoding? end |
.base64_encode(left) ⇒ Object
186 187 188 |
# File 'lib/liquid2/filters/string.rb', line 186 def self.base64_encode(left) Base64.strict_encode64(Liquid2.to_s(left)).force_encoding(Encoding::UTF_8) end |
.base64_url_safe_decode(left) ⇒ Object
199 200 201 202 |
# File 'lib/liquid2/filters/string.rb', line 199 def self.base64_url_safe_decode(left) decoded = Base64.urlsafe_decode64(Liquid2.to_s(left)).force_encoding(Encoding::UTF_8) decoded if decoded.valid_encoding? end |
.base64_url_safe_encode(left) ⇒ Object
195 196 197 |
# File 'lib/liquid2/filters/string.rb', line 195 def self.base64_url_safe_encode(left) Base64.urlsafe_encode64(Liquid2.to_s(left)).force_encoding(Encoding::UTF_8) end |
.better_slice(left, start_ = :undefined, stop_ = :undefined, step_ = :undefined, start: :undefined, stop: :undefined, step: :undefined) ⇒ Object
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/liquid2/filters/slice.rb', line 17 def self.better_slice( left, start_ = :undefined, stop_ = :undefined, step_ = :undefined, start: :undefined, stop: :undefined, step: :undefined ) # Give priority to keyword arguments, default to nil if neither are given. start = start_ == :undefined ? nil : start_ if start == :undefined stop = stop_ == :undefined ? nil : stop_ if stop == :undefined step = step_ == :undefined ? nil : step_ if step == :undefined step = to_integer(step || 1) length = left.length return [] if length.zero? || step.zero? start = to_integer(start) unless start.nil? stop = to_integer(stop) unless stop.nil? normalized_start = if start.nil? step.negative? ? length - 1 : 0 elsif start&.negative? [length + start, 0].max else [start, length - 1].min end normalized_stop = if stop.nil? step.negative? ? -1 : length elsif stop&.negative? [length + stop, -1].max else [stop, length].min end # This does not work with Ruby 3.1 # left[(normalized_start...normalized_stop).step(step)] # # But this does. (normalized_start...normalized_stop).step(step).map { |i| left[i] } end |
.capitalize(left) ⇒ Object
Return left with the first character in uppercase and the rest lowercase. Coerce left to a string if it is not one already.
17 18 19 |
# File 'lib/liquid2/filters/string.rb', line 17 def self.capitalize(left) Liquid2.to_s(left).capitalize end |
.ceil(left) ⇒ Object
Return left rounded up to the next whole number.
22 23 24 |
# File 'lib/liquid2/filters/math.rb', line 22 def self.ceil(left) to_number(left).ceil end |
.compact(left, key = :undefined, context:) ⇒ Object
Return a copy of left with nil items removed. Coerce left to an array-like object if it is not one already.
If key is given, assume items in left are hash-like and remove items from left
where item.fetch(key, nil) is nil.
If key is not :undefined, coerce it to a string before calling fetch on items in
left.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/liquid2/filters/array.rb', line 21 def self.compact(left, key = :undefined, context:) left = Liquid2::Filters.to_enumerable(left) case key when Liquid2::Lambda key.map(context, left).zip(left).reject do |r, _i| r.nil? || r.is_a?(Liquid2::Undefined) end.map(&:last) when :undefined left.compact else left.reject do |item| item.respond_to?(:fetch) ? item.fetch(key, nil).nil? : true end end end |
.concat(left, right) ⇒ Object
Return left concatenated with right, or nil if right is not an array. Coerce left to an array if it isn't an array already.
40 41 42 43 44 45 46 |
# File 'lib/liquid2/filters/array.rb', line 40 def self.concat(left, right) unless right.respond_to?(:to_ary) raise Liquid2::LiquidArgumentError.new("expected an array", nil) end Filters.to_enumerable(left).to_a.concat(right) end |
.date(left, format) ⇒ Object
Format date and time object left with format.
Coerce left to a Time if it is not a time-like object already.
Coerce format to a string if it is not a string already.
9 10 11 12 13 14 15 16 17 18 |
# File 'lib/liquid2/filters/date.rb', line 9 def self.date(left, format) format = Liquid2.to_s(format) return left if format.empty? if (date = Filters.to_date(left)) date.strftime(format) else left end end |
.default(left, default = "", context:, allow_false: false) ⇒ Object
Return left, or default if obj is nil, false or empty.
If allow_false is true, left is returned if left is false.
8 9 10 11 12 13 14 |
# File 'lib/liquid2/filters/default.rb', line 8 def self.default(left, default = "", context:, allow_false: false) return default if left.respond_to?(:force_default) && left.force_default obj = left.respond_to?(:to_liquid) ? left.to_liquid(context) : left falsey = allow_false ? left.nil? : !obj falsey || (left.respond_to?(:empty?) && left.empty?) ? default : left end |
.divided_by(left, right) ⇒ Object
Return the result of dividing left by right. If both left and right are integers, integer division is performed.
28 29 30 31 32 |
# File 'lib/liquid2/filters/math.rb', line 28 def self.divided_by(left, right) to_decimal(left) / to_decimal(right) # steep:ignore rescue ZeroDivisionError => e raise LiquidTypeError.new(e., nil) end |
.downcase(left) ⇒ Object
Return left with all characters converted to lowercase. Coerce left to a string if it is not one already.
23 24 25 |
# File 'lib/liquid2/filters/string.rb', line 23 def self.downcase(left) Liquid2.to_s(left).downcase end |
.escape(left) ⇒ Object
Return left with special HTML characters replaced with their HTML-safe escape sequences. Coerce left to a string if it is not one already.
35 36 37 |
# File 'lib/liquid2/filters/string.rb', line 35 def self.escape(left) CGI.escape_html(Liquid2.to_s(left)) unless left.nil? end |
.escape_once(left) ⇒ Object
Return left with special HTML characters replaced with their HTML-safe escape sequences. Coerce left to a string if it is not one already.
It is safe to use escape_once on string values that already contain HTML-escape sequences.
43 44 45 |
# File 'lib/liquid2/filters/string.rb', line 43 def self.escape_once(left) CGI.escape_html(CGI.unescape_html(Liquid2.to_s(left))) end |
.fetch(obj, key, default = nil) ⇒ Object
86 87 88 89 90 91 92 |
# File 'lib/liquid2/filter.rb', line 86 def self.fetch(obj, key, default = nil) # TODO: benchmark without rescue # TODO: try defensive respond_to? obj[key] rescue ArgumentError, TypeError, NoMethodError default end |
.find(left, key, value = nil, context:) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/liquid2/filters/array.rb', line 48 def self.find(left, key, value = nil, context:) left = Liquid2::Filters.to_enumerable(left) if key.is_a?(Liquid2::Lambda) key.map(context, left).zip(left).reject do |r, i| return i unless r.is_a?(Liquid2::Undefined) || !Liquid2.truthy?(context, r) end elsif !value.nil? && !Liquid2.undefined?(value) left.each do |item| return item if fetch(item, key) == value end else left.each do |item| return item if fetch(item, key) end end nil end |
.find_index(left, key, value = nil, context:) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/liquid2/filters/array.rb', line 68 def self.find_index(left, key, value = nil, context:) left = Liquid2::Filters.to_enumerable(left) if key.is_a?(Liquid2::Lambda) key.map(context, left).reject.with_index do |r, index| return index unless r.is_a?(Liquid2::Undefined) || !Liquid2.truthy?(context, r) end elsif !value.nil? && !Liquid2.undefined?(value) left.each_with_index do |item, index| return index if fetch(item, key) == value end else left.each_with_index do |item, index| return index if fetch(item, key) end end nil end |
.first(left) ⇒ Object
Return the first item in left, or nil if left does not have a first item.
109 110 111 112 113 114 115 116 |
# File 'lib/liquid2/filters/array.rb', line 109 def self.first(left) case left when String left[0] else left.first if left.respond_to?(:first) end end |
.floor(left) ⇒ Object
Return left rounded down to the next whole number.
40 41 42 |
# File 'lib/liquid2/filters/math.rb', line 40 def self.floor(left) to_number(left).floor end |
.has(left, key, value = nil, context:) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/liquid2/filters/array.rb', line 88 def self.has(left, key, value = nil, context:) left = Liquid2::Filters.to_enumerable(left) if key.is_a?(Liquid2::Lambda) key.map(context, left).reject do |r| return true unless r.is_a?(Liquid2::Undefined) || !Liquid2.truthy?(context, r) end elsif !value.nil? && !Liquid2.undefined?(value) left.each do |item| return true if fetch(item, key) == value end else left.each do |item| return true if fetch(item, key) end end false end |
.ints(obj) ⇒ Object
86 87 88 89 90 91 92 93 94 95 |
# File 'lib/liquid2/filters/sort.rb', line 86 def self.ints(obj) if obj.is_a?(Integer) || obj.is_a?(Float) || obj.is_a?(BigDecimal) [obj] else numeric = obj.to_s.scan(/(?<=\.)0+|-?\d+/) return INFINITY_ARRAY if numeric.empty? numeric.map(&:to_i) end end |
.join(left, sep = " ") ⇒ Object
Return the concatenation of items in left separated by sep. Coerce items in left to strings if they aren't strings already.
8 9 10 11 |
# File 'lib/liquid2/filters/array.rb', line 8 def self.join(left, sep = " ") sep = Liquid2.to_s(sep) to_enumerable(left).map { |item| Liquid2.to_s(item) }.join(Liquid2.to_s(sep)) end |
.json(left, pretty: false) ⇒ Object
Return left serialized in JSON format.
7 8 9 10 11 12 13 |
# File 'lib/liquid2/filters/json.rb', line 7 def self.json(left, pretty: false) if pretty JSON.pretty_generate(left) else JSON.generate(left) end end |
.last(left) ⇒ Object
Return the last item in left, or nil if left does not have a last item.
119 120 121 122 123 124 125 126 |
# File 'lib/liquid2/filters/array.rb', line 119 def self.last(left) case left when String left[-1] else left.last if left.respond_to?(:last) end end |
.lstrip(left) ⇒ Object
Return left with leading whitespace removed. Coerce left to a string if it is not one already.
49 50 51 |
# File 'lib/liquid2/filters/string.rb', line 49 def self.lstrip(left) Liquid2.to_s(left).lstrip end |
.map(left, key, context:) ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/liquid2/filters/array.rb', line 128 def self.map(left, key, context:) left = Liquid2::Filters.to_enumerable(left) if key.is_a?(Liquid2::Lambda) key.map(context, left).map do |item| item.is_a?(Liquid2::Undefined) ? nil : item end else key = Liquid2.to_s(key) left.map { |item| item[key] } end end |
.minus(left, right) ⇒ Object
Return right subtracted from left.
45 46 47 |
# File 'lib/liquid2/filters/math.rb', line 45 def self.minus(left, right) to_decimal(left) - to_decimal(right) # steep:ignore end |
.modulo(left, right) ⇒ Object
Return the remainder of dividing left by right.
50 51 52 53 54 |
# File 'lib/liquid2/filters/math.rb', line 50 def self.modulo(left, right) to_decimal(left) % to_decimal(right) # steep:ignore rescue ZeroDivisionError => e raise LiquidTypeError.new(e., nil) end |
.newline_to_br(left) ⇒ Object
Return left with LF or CRLF replaced with <br />\n.
66 67 68 |
# File 'lib/liquid2/filters/string.rb', line 66 def self.newline_to_br(left) Liquid2.to_s(left).gsub(/\r?\n/, "<br />\n") end |
.nil_safe_casecmp(left, right) ⇒ Object
70 71 72 73 74 75 76 77 78 |
# File 'lib/liquid2/filters/sort.rb', line 70 def self.nil_safe_casecmp(left, right) if !left.nil? && !right.nil? left.to_s.casecmp(right.to_s) elsif left.nil? && right.nil? 0 else left.nil? ? 1 : -1 end end |
.nil_safe_compare(left, right) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/liquid2/filters/sort.rb', line 56 def self.nil_safe_compare(left, right) result = left <=> right if result result elsif left.nil? 1 elsif right.nil? -1 else raise Liquid2::LiquidArgumentError.new("can't sort incomparable type", nil) end end |
.numeric_compare(left, right) ⇒ Object
80 81 82 83 84 |
# File 'lib/liquid2/filters/sort.rb', line 80 def self.numeric_compare(left, right) # @type var res: untyped res = ints(left) <=> ints(right) res || -1 end |
.plus(left, right) ⇒ Object
Return right added to left.
57 58 59 |
# File 'lib/liquid2/filters/math.rb', line 57 def self.plus(left, right) to_decimal(left) + to_decimal(right) # steep:ignore end |
.prepend(left, right) ⇒ Object
Return right concatenated with left. Coerce left and right to strings if they aren't strings already.
72 73 74 |
# File 'lib/liquid2/filters/string.rb', line 72 def self.prepend(left, right) Liquid2.to_s(right) + Liquid2.to_s(left) end |
.reject(left, key, value = nil, context:) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/liquid2/filters/array.rb', line 147 def self.reject(left, key, value = nil, context:) left = Liquid2::Filters.to_enumerable(left) if key.is_a?(Liquid2::Lambda) key.map(context, left).zip(left).reject do |r, _item| r.is_a?(Liquid2::Undefined) || Liquid2.truthy?(context, r) end.map(&:last) elsif !value.nil? && !Liquid2.undefined?(value) key = Liquid2.to_s(key) left.reject do |item| fetch(item, key) == value end else key = Liquid2.to_s(key) left.reject do |item| Liquid2.truthy?(context, fetch(item, key)) end end end |
.remove(left, pattern) ⇒ Object
Return left with all occurrences of pattern removed. All arguments are coerced to strings if they aren't strings already.
101 102 103 |
# File 'lib/liquid2/filters/string.rb', line 101 def self.remove(left, pattern) Liquid2.to_s(left).gsub(Liquid2.to_s(pattern), Liquid2.to_s("")) end |
.remove_first(left, pattern) ⇒ Object
Return left with the first occurrence of pattern removed. All arguments are coerced to strings if they aren't strings already.
107 108 109 |
# File 'lib/liquid2/filters/string.rb', line 107 def self.remove_first(left, pattern) Liquid2.to_s(left).sub(Liquid2.to_s(pattern), Liquid2.to_s("")) end |
.remove_last(left, pattern) ⇒ Object
Return left with the last occurrence of pattern removed. All arguments are coerced to strings if they aren't strings already.
113 114 115 116 117 118 119 120 |
# File 'lib/liquid2/filters/string.rb', line 113 def self.remove_last(left, pattern) return left if Liquid2.undefined?(pattern) head, match, tail = Liquid2.to_s(left).rpartition(Liquid2.to_s(pattern)) return left if match.empty? head + tail end |
.replace(left, pattern, replacement = "") ⇒ Object
Return left with all occurrences of pattern replaced with replacement. All arguments are coerced to strings if they aren't strings already.
78 79 80 |
# File 'lib/liquid2/filters/string.rb', line 78 def self.replace(left, pattern, replacement = "") Liquid2.to_s(left).gsub(Liquid2.to_s(pattern), Liquid2.to_s(replacement)) end |
.replace_first(left, pattern, replacement = "") ⇒ Object
Return left with the first occurrence of pattern replaced with replacement. All arguments are coerced to strings if they aren't strings already.
84 85 86 |
# File 'lib/liquid2/filters/string.rb', line 84 def self.replace_first(left, pattern, replacement = "") Liquid2.to_s(left).sub(Liquid2.to_s(pattern), Liquid2.to_s(replacement)) end |
.replace_last(left, pattern, replacement) ⇒ Object
Return left with the last occurrence of pattern replaced with replacement. All arguments are coerced to strings if they aren't strings already.
90 91 92 93 94 95 96 97 |
# File 'lib/liquid2/filters/string.rb', line 90 def self.replace_last(left, pattern, replacement) return left + replacement if Liquid2.undefined?(pattern) head, match, tail = Liquid2.to_s(left).rpartition(Liquid2.to_s(pattern)) return left if match.empty? head + Liquid2.to_s(replacement) + tail end |
.reverse(left) ⇒ Object
Return left with all items in reverse order. Coerce left to an array if it isn't an array already.
143 144 145 |
# File 'lib/liquid2/filters/array.rb', line 143 def self.reverse(left) to_enumerable(left).to_a.reverse end |
.round(left, ndigits = 0) ⇒ Object
Return left rounded to ndigits decimal digits.
62 63 64 65 66 67 |
# File 'lib/liquid2/filters/math.rb', line 62 def self.round(left, ndigits = 0) left = to_decimal(left) return left.round if ndigits == 0 # rubocop:disable Style/NumericPredicate left.round(to_decimal(ndigits)) # steep:ignore end |
.rstrip(left) ⇒ Object
Return left with trailing whitespace removed. Coerce left to a string if it is not one already.
55 56 57 |
# File 'lib/liquid2/filters/string.rb', line 55 def self.rstrip(left) Liquid2.to_s(left).rstrip end |
.size(left) ⇒ Object
Return the size of left, or zero if left has no size.
7 8 9 |
# File 'lib/liquid2/filters/size.rb', line 7 def self.size(left) left.respond_to?(:size) ? left.size : 0 end |
.slice(left, start, length = 1) ⇒ Object
Return the subsequence of left starting at start up to length.
7 8 9 10 11 12 13 14 15 |
# File 'lib/liquid2/filters/slice.rb', line 7 def self.slice(left, start, length = 1) length = 1 if Liquid2.undefined?(length) case left when Array left.slice(to_integer(start), to_integer(length)) || [] else Liquid2.to_s(left).slice(to_integer(start), to_integer(length)) || "" end end |
.sort(left, key = nil, context:) ⇒ Object
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/liquid2/filters/sort.rb', line 8 def self.sort(left, key = nil, context:) left = Liquid2::Filters.to_enumerable(left) case key when Liquid2::Lambda key.map(context, left).zip(left).sort do |a, b| nil_safe_compare(a.first, b.first) end.map(&:last) when nil, Liquid2::Undefined left.sort { |a, b| nil_safe_compare(a, b) } else key = Liquid2.to_s(key) left.sort { |a, b| nil_safe_compare(fetch(a, key), fetch(b, key)) } end end |
.sort_natural(left, key = nil, context:) ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/liquid2/filters/sort.rb', line 24 def self.sort_natural(left, key = nil, context:) left = Liquid2::Filters.to_enumerable(left) case key when Liquid2::Lambda key.map(context, left).zip(left).sort do |a, b| nil_safe_casecmp(a.first, b.first) end.map(&:last) when nil, Liquid2::Undefined left.sort { |a, b| nil_safe_casecmp(a, b) } else key = Liquid2.to_s(key) left.sort { |a, b| nil_safe_casecmp(fetch(a, key), fetch(b, key)) } end end |
.sort_numeric(left, key = nil, context:) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/liquid2/filters/sort.rb', line 40 def self.sort_numeric(left, key = nil, context:) left = Liquid2::Filters.to_enumerable(left) case key when Liquid2::Lambda key.map(context, left).zip(left).sort do |a, b| numeric_compare(a.first, b.first) end.map(&:last) when nil, Liquid2::Undefined left.sort { |a, b| numeric_compare(a, b) } else key = Liquid2.to_s(key) left.sort { |a, b| numeric_compare(fetch(a, key), fetch(b, key)) } end end |
.split(left, pattern) ⇒ Object
Split left on every occurrence of pattern.
123 124 125 |
# File 'lib/liquid2/filters/string.rb', line 123 def self.split(left, pattern) Liquid2.to_s(left).split(Liquid2.to_s(pattern)) end |
.strip(left) ⇒ Object
Return left with leading and trailing whitespace removed. Coerce left to a string if it is not one already.
61 62 63 |
# File 'lib/liquid2/filters/string.rb', line 61 def self.strip(left) Liquid2.to_s(left).strip end |
.strip_html(left) ⇒ Object
Return left with HTML tags removed.
136 137 138 |
# File 'lib/liquid2/filters/string.rb', line 136 def self.strip_html(left) Liquid2.to_s(left).gsub(RE_HTML_BLOCKS, "").gsub(RE_HTML_TAGS, "") end |
.strip_newlines(left) ⇒ Object
Return left with CR and LF removed.
141 142 143 |
# File 'lib/liquid2/filters/string.rb', line 141 def self.strip_newlines(left) Liquid2.to_s(left).gsub(/\r?\n/, "") end |
.sum(left, key = nil, context:) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/liquid2/filters/math.rb', line 69 def self.sum(left, key = nil, context:) left = Liquid2::Filters.to_enumerable(left) case key when Liquid2::Lambda items = key.map(context, left).reject do |item| Liquid2.undefined?(item) end items.sum { |item| Liquid2::Filters.to_decimal(item) } when nil, Liquid2::Undefined left.sum { |item| Liquid2::Filters.to_decimal(item) } # steep:ignore else k = Liquid2.to_s(key) left.sum { |item| Liquid2::Filters.to_decimal(fetch(item, k)) } # steep:ignore end end |
.times(left, right) ⇒ Object
Return the result of multiplying left by right.
35 36 37 |
# File 'lib/liquid2/filters/math.rb', line 35 def self.times(left, right) to_decimal(left) * to_decimal(right) # steep:ignore end |
.to_date(obj) ⇒ Object
Cast obj to a date and time. Return nil if casting fails.
NOTE: This was copied from Shopify/liquid.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/liquid2/filter.rb', line 65 def self.to_date(obj) return obj if obj.respond_to?(:strftime) if obj.is_a?(String) return nil if obj.empty? obj = obj.downcase end case obj when "now", "today" Time.now when /\A\d+\z/, Integer Time.at(obj.to_i) when String Time.parse(obj) end rescue ::ArgumentError nil end |
.to_decimal(obj, default: 0) ⇒ Object
Cast obj to a number, favouring BigDecimal over Float.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/liquid2/filter.rb', line 48 def self.to_decimal(obj, default: 0) case obj when String obj.match?(/\A-?\d+(?:[eE]\+?\d+)?\Z/) ? obj.to_f.to_i : BigDecimal(obj) when Float BigDecimal(obj.to_s) when Integer, BigDecimal, Numeric obj else default end rescue ArgumentError default end |
.to_enumerable(obj) ⇒ Enumerable
Cast obj to an enumerable for use in a Liquid filter.
12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/liquid2/filter.rb', line 12 def self.to_enumerable(obj) case obj when Array obj.flatten when Hash, String [obj] when Enumerable obj else obj.respond_to?(:each) ? obj.each : [obj] end end |
.to_integer(obj) ⇒ Object
Case obj to an Integer.
43 44 45 |
# File 'lib/liquid2/filter.rb', line 43 def self.to_integer(obj) obj.is_a?(Integer) ? obj : Integer(obj) end |
.to_number(obj, default: 0) ⇒ Object
Cast obj to a number.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/liquid2/filter.rb', line 26 def self.to_number(obj, default: 0) case obj when String # Cast to float before integer as `to_f` will parse exponents, `to_i` will not. # Use `Float(obj)` instead of `obj.to_f` because `to_f` ignores trailing non-digit chars. obj.match?(/\A-?\d+(?:[eE]\+?\d+)?\Z/) ? obj.to_f.to_i : Float(obj) when Float, Integer, BigDecimal, Numeric # Numeric is the base class for heap allocated numbers. obj else default end rescue ArgumentError default end |
.truncate(left, max_length = 50, ellipsis = "...") ⇒ Object
145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/liquid2/filters/string.rb', line 145 def self.truncate(left, max_length = 50, ellipsis = "...") return if left.nil? || Liquid2.undefined?(left) left = Liquid2.to_s(left) max_length = to_integer(max_length) return left if left.length <= max_length ellipsis = Liquid2.to_s(ellipsis) return ellipsis[0, max_length] if ellipsis.length >= max_length "#{left[0...max_length - ellipsis.length]}#{ellipsis}" end |
.truncatewords(left, max_words = 15, ellipsis = "...") ⇒ Object
158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/liquid2/filters/string.rb', line 158 def self.truncatewords(left, max_words = 15, ellipsis = "...") return if left.nil? || Liquid2.undefined?(left) left = Liquid2.to_s(left) max_words = to_integer(max_words).clamp(1, 10_000) words = left.split(" ", max_words + 1) return left if words.length <= max_words ellipsis = Liquid2.to_s(ellipsis) words.pop "#{words.join(" ")}#{ellipsis}" end |
.uniq(left, key = nil, context:) ⇒ Object
Deduplicate items in left. Coerce left to an array if it isn't an array already.
189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/liquid2/filters/array.rb', line 189 def self.uniq(left, key = nil, context:) left = Liquid2::Filters.to_enumerable(left) if key.nil? left.to_a.uniq elsif key.is_a?(Liquid2::Lambda) key.map(context, left).zip(left).uniq { |r, _item| r }.map(&:last) else left.to_a.uniq { |item| fetch(item, key) } end end |
.upcase(left) ⇒ Object
Return left with all characters converted to uppercase. Coerce left to a string if it is not one already.
29 30 31 |
# File 'lib/liquid2/filters/string.rb', line 29 def self.upcase(left) Liquid2.to_s(left).upcase end |
.url_decode(left) ⇒ Object
175 176 177 178 179 180 181 182 183 184 |
# File 'lib/liquid2/filters/string.rb', line 175 def self.url_decode(left) return if left.nil? || Liquid2.undefined?(left) decoded = CGI.unescape(Liquid2.to_s(left)) unless decoded.valid_encoding? raise Liquid2::LiquidArgumentError.new("invalid byte sequence", nil) end decoded end |
.url_encode(left) ⇒ Object
171 172 173 |
# File 'lib/liquid2/filters/string.rb', line 171 def self.url_encode(left) CGI.escape(Liquid2.to_s(left)) unless left.nil? || Liquid2.undefined?(left) end |
.where(left, key, value = nil, context:) ⇒ Object
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/liquid2/filters/array.rb', line 167 def self.where(left, key, value = nil, context:) left = Liquid2::Filters.to_enumerable(left) if key.is_a?(Liquid2::Lambda) key.map(context, left).zip(left).filter do |r, _item| r.is_a?(Liquid2::Undefined) || Liquid2.truthy?(context, r) end.map(&:last) elsif !value.nil? && !Liquid2.undefined?(value) key = Liquid2.to_s(key) left.filter do |item| fetch(item, key) == value end else key = Liquid2.to_s(key) left.filter do |item| Liquid2.truthy?(context, fetch(item, key)) end end end |