Support for binary operators in where_exp filter (#6998)
Merge pull request 6998
This commit is contained in:
parent
4550f02b58
commit
e819bc4af0
|
@ -365,23 +365,49 @@ module Jekyll
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# ----------- The following set of code was *adapted* from Liquid::If
|
||||||
|
# ----------- ref: https://git.io/vp6K6
|
||||||
|
|
||||||
# Parse a string to a Liquid Condition
|
# Parse a string to a Liquid Condition
|
||||||
def parse_condition(exp)
|
def parse_condition(exp)
|
||||||
parser = Liquid::Parser.new(exp)
|
parser = Liquid::Parser.new(exp)
|
||||||
left_expr = parser.expression
|
condition = parse_binary_comparison(parser)
|
||||||
operator = parser.consume?(:comparison)
|
|
||||||
condition =
|
|
||||||
if operator
|
|
||||||
Liquid::Condition.new(Liquid::Expression.parse(left_expr),
|
|
||||||
operator,
|
|
||||||
Liquid::Expression.parse(parser.expression))
|
|
||||||
else
|
|
||||||
Liquid::Condition.new(Liquid::Expression.parse(left_expr))
|
|
||||||
end
|
|
||||||
parser.consume(:end_of_string)
|
|
||||||
|
|
||||||
|
parser.consume(:end_of_string)
|
||||||
condition
|
condition
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Generate a Liquid::Condition object from a Liquid::Parser object additionally processing
|
||||||
|
# the parsed expression based on whether the expression consists of binary operations with
|
||||||
|
# Liquid operators `and` or `or`
|
||||||
|
#
|
||||||
|
# - parser: an instance of Liquid::Parser
|
||||||
|
#
|
||||||
|
# Returns an instance of Liquid::Condition
|
||||||
|
def parse_binary_comparison(parser)
|
||||||
|
parse_comparison(parser).tap do |condition|
|
||||||
|
binary_operator = parser.id?("and") || parser.id?("or")
|
||||||
|
condition.send(binary_operator, parse_comparison(parser)) if binary_operator
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generates a Liquid::Condition object from a Liquid::Parser object based on whether the parsed
|
||||||
|
# expression involves a "comparison" operator (e.g. <, ==, >, !=, etc)
|
||||||
|
#
|
||||||
|
# - parser: an instance of Liquid::Parser
|
||||||
|
#
|
||||||
|
# Returns an instance of Liquid::Condition
|
||||||
|
def parse_comparison(parser)
|
||||||
|
left_operand = Liquid::Expression.parse(parser.expression)
|
||||||
|
operator = parser.consume?(:comparison)
|
||||||
|
|
||||||
|
# No comparison-operator detected. Initialize a Liquid::Condition using only left operand
|
||||||
|
return Liquid::Condition.new(left_operand) unless operator
|
||||||
|
|
||||||
|
# Parse what remained after extracting the left operand and the `:comparison` operator
|
||||||
|
# and initialize a Liquid::Condition object using the operands and the comparison-operator
|
||||||
|
Liquid::Condition.new(left_operand, operator, Liquid::Expression.parse(parser.expression))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ class TestFilters < JekyllUnitTest
|
||||||
@time_as_numeric = 1_399_680_607
|
@time_as_numeric = 1_399_680_607
|
||||||
@integer_as_string = "142857"
|
@integer_as_string = "142857"
|
||||||
@array_of_objects = [
|
@array_of_objects = [
|
||||||
|
{ "color" => "teal", "size" => "large" },
|
||||||
{ "color" => "red", "size" => "large" },
|
{ "color" => "red", "size" => "large" },
|
||||||
{ "color" => "red", "size" => "medium" },
|
{ "color" => "red", "size" => "medium" },
|
||||||
{ "color" => "blue", "size" => "medium" },
|
{ "color" => "blue", "size" => "medium" },
|
||||||
|
@ -914,6 +915,28 @@ class TestFilters < JekyllUnitTest
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
should "filter objects appropriately with 'or', 'and' operators" do
|
||||||
|
assert_equal(
|
||||||
|
[
|
||||||
|
{ "color" => "teal", "size" => "large" },
|
||||||
|
{ "color" => "red", "size" => "large" },
|
||||||
|
{ "color" => "red", "size" => "medium" },
|
||||||
|
],
|
||||||
|
@filter.where_exp(
|
||||||
|
@array_of_objects, "item", "item.color == 'red' or item.size == 'large'"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_equal(
|
||||||
|
[
|
||||||
|
{ "color" => "red", "size" => "large" },
|
||||||
|
],
|
||||||
|
@filter.where_exp(
|
||||||
|
@array_of_objects, "item", "item.color == 'red' and item.size == 'large'"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
should "stringify during comparison for compatibility with liquid parsing" do
|
should "stringify during comparison for compatibility with liquid parsing" do
|
||||||
hash = {
|
hash = {
|
||||||
"The Words" => { "rating" => 1.2, "featured" => false },
|
"The Words" => { "rating" => 1.2, "featured" => false },
|
||||||
|
|
Loading…
Reference in New Issue