diff --git a/lib/liquid/tags/cycle.rb b/lib/liquid/tags/cycle.rb index 96f0d570e..b28bd37ce 100644 --- a/lib/liquid/tags/cycle.rb +++ b/lib/liquid/tags/cycle.rb @@ -26,8 +26,8 @@ def initialize(tag_name, markup, options) @variables = variables_from_string(Regexp.last_match(2)) @name = parse_expression(Regexp.last_match(1)) when SimpleSyntax - @variables = variables_from_string(markup) - @name = @variables.to_s + @variables, names = variables_and_names_from_string(markup) + @name = names.to_s else raise SyntaxError, options[:locale].t("errors.syntax.cycle") end @@ -65,6 +65,18 @@ def variables_from_string(markup) end.compact end + def variables_and_names_from_string(markup) + markup.split(',').collect do |var| + next unless var =~ /\s*(#{QuotedFragment})\s*/o + object = parse_expression(Regexp.last_match(1)) + if object.respond_to?(:evaluate) + [object, "#{object.class}-#{Regexp.last_match(1)}"] + else + [object, object] + end + end.transpose + end + class ParseTreeVisitor < Liquid::ParseTreeVisitor def children Array(@node.variables) diff --git a/test/integration/tags/standard_tag_test.rb b/test/integration/tags/standard_tag_test.rb index ea7dca158..ce245add1 100644 --- a/test/integration/tags/standard_tag_test.rb +++ b/test/integration/tags/standard_tag_test.rb @@ -272,6 +272,62 @@ def test_multiple_named_cycles_with_names_from_context '{%cycle var1: "one", "two" %} {%cycle var2: "one", "two" %} {%cycle var1: "one", "two" %} {%cycle var2: "one", "two" %} {%cycle var1: "one", "two" %} {%cycle var2: "one", "two" %}', assigns) end + def test_cycle_variables_from_context + assigns = { "a" => 1, "b" => 2, "c" => 3 } + assert_template_result('1 2 3', '{%cycle a,b,c%} {%cycle a,b,c%} {%cycle a,b,c%}', assigns) + end + + def test_cycle_undefined_variables + assert_template_result(' ', '{%cycle a,b,c%} {%cycle a,b,c%} {%cycle a,b,c%}') + end + + def test_cycle_string_and_integer_keys + assert_template_result('1 1 2 2', '{%cycle 1,2,3%} {%cycle "1","2","3"%} {%cycle 1,2,3%} {%cycle "1","2","3"%}') + end + + def test_cycle_mixed_context_variables_and_literals + assigns = { "a" => 1, "b" => 2 } + assert_template_result( + '1 2 three 1', + '{%cycle a,b,"three"%} {%cycle a,b,"three"%} {%cycle a,b,"three"%} {%cycle a,b,"three"%}', + assigns + ) + end + + def test_cycle_boolean_literals + assert_template_result( + 'true true false true', + '{%cycle true, true, false%} {%cycle true, true, false%} {%cycle true, true, false%} {%cycle true, true, false%}', + ) + end + + def test_cycle_variable_keys_dont_conflict_with_literals + assigns = { "a" => 1, "b" => 2, "c" => 3 } + assert_template_result( + '1 1 2 c', + '{%cycle a,b,"c"%} {%cycle a,b,c%} {%cycle a,b,"c"%} {%cycle a,b,"c"%}', + assigns + ) + end + + def test_cycle_over_changing_context_variables + assigns = { "a" => 1, "b" => 2, "c" => 3 } + assert_template_result( + '1 2 z x', + '{%cycle a,b,c%} {%assign a="x"%}{%assign c="z"%}{%cycle a,b,c%} {%cycle a,b,c%} {%cycle a,b,c%}', + assigns + ) + end + + def test_cycle_with_a_changing_variable_name + assigns = { "x" => "var1" } + assert_template_result( + 'a a b', + '{%cycle x: "a","b","c"%} {%assign x="var2" %}{%cycle x: "a","b","c"%} {%cycle x: "a","b","c"%}', + assigns + ) + end + def test_size_of_array assigns = { "array" => [1, 2, 3, 4] } assert_template_result('array has 4 elements', "array has {{ array.size }} elements", assigns)