Add rigid_parse to case/when

This commit is contained in:
Guilherme Carreiro
2025-10-27 16:33:31 +01:00
committed by Guilherme Carreiro
parent e2a15334f0
commit 65a1c167b3
3 changed files with 167 additions and 6 deletions
+4
View File
@@ -37,6 +37,10 @@ module Liquid
end
end
def rigid_mode?
parse_context.error_mode == :rigid
end
private
def rigid_parse_with_error_context(markup)
+43 -6
View File
@@ -31,12 +31,7 @@ module Liquid
def initialize(tag_name, markup, options)
super
@blocks = []
if markup =~ Syntax
@left = parse_expression(Regexp.last_match(1))
else
raise SyntaxError, options[:locale].t("errors.syntax.case")
end
parse_with_selected_parser(markup)
end
def parse(tokens)
@@ -91,9 +86,51 @@ module Liquid
private
def rigid_parse(markup)
parser = @parse_context.new_parser(markup)
@left = safe_parse_expression(parser)
parser.consume(:end_of_string)
end
def strict_parse(markup)
lax_parse(markup)
end
def lax_parse(markup)
if markup =~ Syntax
@left = parse_expression(Regexp.last_match(1))
else
raise SyntaxError, options[:locale].t("errors.syntax.case")
end
end
def record_when_condition(markup)
body = new_body
if rigid_mode?
parse_rigid_when(markup, body)
else
parse_lax_when(markup, body)
end
end
def parse_rigid_when(markup, body)
parser = @parse_context.new_parser(markup)
loop do
expr = safe_parse_expression(parser)
block = Condition.new(@left, '==', expr)
block.attach(body)
@blocks << block
# Temporarily until support :or lexeme.
break unless parser.id?('or') || parser.consume?(:comma)
end
parser.consume(:end_of_string)
end
def parse_lax_when(markup, body)
while markup
unless markup =~ WhenSyntax
raise SyntaxError, options[:locale].t("errors.syntax.case_invalid_when")
+120
View File
@@ -9,4 +9,124 @@ class CaseTagUnitTest < Minitest::Test
template = Liquid::Template.parse('{% case var %}{% when true %}WHEN{% else %}ELSE{% endcase %}')
assert_equal(['WHEN', 'ELSE'], template.root.nodelist[0].nodelist.map(&:nodelist).flatten)
end
def test_case_with_trailing_element
template = <<~LIQUID
{%- case 1 bar -%}
{%- when 1 -%}
one
{%- else -%}
two
{%- endcase -%}
LIQUID
[:lax, :strict].each do |mode|
with_error_mode(mode) { assert_template_result("one", template) }
end
with_error_mode(:rigid) do
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
assert_match(/Expected end_of_string but found/, error.message)
end
end
def test_case_when_trailing_element
template = <<~LIQUID
{%- case 1 -%}
{%- when 1 bar -%}
one
{%- else -%}
two
{%- endcase -%}
LIQUID
[:lax, :strict].each do |mode|
with_error_mode(mode) { assert_template_result("one", template) }
end
with_error_mode(:rigid) do
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
assert_match(/Expected end_of_string but found/, error.message)
end
end
def test_case_when_with_comma
template = <<~LIQUID
{%- case 1 -%}
{%- when 2, 1 -%}
one
{%- else -%}
two
{%- endcase -%}
LIQUID
[:lax, :strict, :rigid].each do |mode|
with_error_mode(mode) { assert_template_result("one", template) }
end
end
def test_case_when_with_or
template = <<~LIQUID
{%- case 1 -%}
{%- when 2 or 1 -%}
one
{%- else -%}
two
{%- endcase -%}
LIQUID
[:lax, :strict, :rigid].each do |mode|
with_error_mode(mode) { assert_template_result("one", template) }
end
end
def test_case_with_invalid_expression
template = <<~LIQUID
{%- case foo=>bar -%}
{%- when 'baz' -%}
one
{%- else -%}
two
{%- endcase -%}
LIQUID
assigns = { 'foo' => { 'bar' => 'baz' } }
[:lax, :strict].each do |mode|
with_error_mode(mode) do
assert_template_result("one", template, assigns)
end
end
with_error_mode(:rigid) do
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
assert_match(/Unexpected character =/, error.message)
end
end
def test_case_when_with_invalid_expression
template = <<~LIQUID
{%- case 'baz' -%}
{%- when foo=>bar -%}
one
{%- else -%}
two
{%- endcase -%}
LIQUID
assigns = { 'foo' => { 'bar' => 'baz' } }
[:lax, :strict].each do |mode|
with_error_mode(mode) do
assert_template_result("one", template, assigns)
end
end
with_error_mode(:rigid) do
error = assert_raises(Liquid::SyntaxError) { Template.parse(template) }
assert_match(/Unexpected character =/, error.message)
end
end
end