Support for simple boolean comparisons and boolean assignments

This commit is contained in:
Albert Chu
2025-03-04 17:08:23 -07:00
parent a2de2dcdb6
commit 19e9ba36ec
3 changed files with 42 additions and 7 deletions
+1
View File
@@ -89,3 +89,4 @@ require 'liquid/partial_cache'
require 'liquid/usage'
require 'liquid/registers'
require 'liquid/template_factory'
require 'liquid/boolean_expression'
+21
View File
@@ -0,0 +1,21 @@
# frozen_string_literal: true
module Liquid
class BooleanExpression
def self.parse(markup, ss = StringScanner.new(""), cache = nil)
# Split the markup by comparison operators
if (match = markup.match(/\A\s*(.+?)\s*(==|!=|<>|<=|>=|<|>|contains)\s*(.+)\s*\z/))
left = Expression.parse(match[1], ss, cache)
operator = match[2]
right = Expression.parse(match[3], ss, cache)
# Create a condition object to evaluate the expression
condition = Condition.new(left, operator, right)
return condition
end
# If no comparison operator is found, just parse as regular expression
Expression.parse(markup, ss, cache)
end
end
end
+20 -7
View File
@@ -17,6 +17,7 @@ module Liquid
FilterArgsRegex = /(?:#{FilterArgumentSeparator}|#{ArgumentSeparator})\s*((?:\w+\s*\:\s*)?#{QuotedFragment})/o
JustTagAttributes = /\A#{TagAttributes}\z/o
MarkupWithQuotedFragment = /(#{QuotedFragment})(.*)/om
ComparisonOperator = /==|!=|<>|<=|>=|<|>|contains/o
attr_accessor :filters, :name, :line_number
attr_reader :parse_context
@@ -47,7 +48,14 @@ module Liquid
name_markup = Regexp.last_match(1)
filter_markup = Regexp.last_match(2)
@name = parse_context.parse_expression(name_markup)
# Check if name_markup contains a comparison operator
@name = if /\s*(#{ComparisonOperator})\s*/.match?(name_markup)
BooleanExpression.parse(name_markup)
else
parse_context.parse_expression(name_markup)
end
if filter_markup =~ FilterMarkupRegex
filters = Regexp.last_match(1).scan(FilterParser)
filters.each do |f|
@@ -65,13 +73,18 @@ module Liquid
return if p.look(:end_of_string)
@name = parse_context.parse_expression(p.expression)
while p.consume?(:pipe)
filtername = p.consume(:id)
filterargs = p.consume?(:colon) ? parse_filterargs(p) : Const::EMPTY_ARRAY
@filters << parse_filter_expressions(filtername, filterargs)
# Check if markup contains a comparison operator
if /\s*(#{ComparisonOperator})\s*/.match?(markup)
@name = BooleanExpression.parse(markup)
else
@name = parse_context.parse_expression(p.expression)
while p.consume?(:pipe)
filtername = p.consume(:id)
filterargs = p.consume?(:colon) ? parse_filterargs(p) : Const::EMPTY_ARRAY
@filters << parse_filter_expressions(filtername, filterargs)
end
p.consume(:end_of_string)
end
p.consume(:end_of_string)
end
def parse_filterargs(p)