liquid 3.0.6 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +243 -58
  3. data/README.md +43 -4
  4. data/lib/liquid/block.rb +57 -123
  5. data/lib/liquid/block_body.rb +217 -85
  6. data/lib/liquid/condition.rb +92 -45
  7. data/lib/liquid/context.rb +154 -89
  8. data/lib/liquid/document.rb +57 -9
  9. data/lib/liquid/drop.rb +20 -17
  10. data/lib/liquid/errors.rb +27 -29
  11. data/lib/liquid/expression.rb +32 -20
  12. data/lib/liquid/extensions.rb +21 -7
  13. data/lib/liquid/file_system.rb +17 -15
  14. data/lib/liquid/forloop_drop.rb +92 -0
  15. data/lib/liquid/i18n.rb +10 -8
  16. data/lib/liquid/interrupts.rb +4 -3
  17. data/lib/liquid/lexer.rb +37 -26
  18. data/lib/liquid/locales/en.yml +13 -6
  19. data/lib/liquid/parse_context.rb +54 -0
  20. data/lib/liquid/parse_tree_visitor.rb +42 -0
  21. data/lib/liquid/parser.rb +30 -18
  22. data/lib/liquid/parser_switching.rb +20 -6
  23. data/lib/liquid/partial_cache.rb +24 -0
  24. data/lib/liquid/profiler/hooks.rb +26 -14
  25. data/lib/liquid/profiler.rb +72 -92
  26. data/lib/liquid/range_lookup.rb +28 -3
  27. data/lib/liquid/registers.rb +51 -0
  28. data/lib/liquid/resource_limits.rb +62 -0
  29. data/lib/liquid/standardfilters.rb +715 -132
  30. data/lib/liquid/strainer_factory.rb +41 -0
  31. data/lib/liquid/strainer_template.rb +62 -0
  32. data/lib/liquid/tablerowloop_drop.rb +121 -0
  33. data/lib/liquid/tag/disableable.rb +22 -0
  34. data/lib/liquid/tag/disabler.rb +21 -0
  35. data/lib/liquid/tag.rb +35 -12
  36. data/lib/liquid/tags/assign.rb +57 -18
  37. data/lib/liquid/tags/break.rb +15 -5
  38. data/lib/liquid/tags/capture.rb +24 -18
  39. data/lib/liquid/tags/case.rb +79 -30
  40. data/lib/liquid/tags/comment.rb +19 -4
  41. data/lib/liquid/tags/continue.rb +16 -12
  42. data/lib/liquid/tags/cycle.rb +47 -27
  43. data/lib/liquid/tags/decrement.rb +23 -24
  44. data/lib/liquid/tags/echo.rb +41 -0
  45. data/lib/liquid/tags/for.rb +155 -124
  46. data/lib/liquid/tags/if.rb +97 -63
  47. data/lib/liquid/tags/ifchanged.rb +11 -12
  48. data/lib/liquid/tags/include.rb +82 -73
  49. data/lib/liquid/tags/increment.rb +23 -17
  50. data/lib/liquid/tags/inline_comment.rb +43 -0
  51. data/lib/liquid/tags/raw.rb +50 -8
  52. data/lib/liquid/tags/render.rb +109 -0
  53. data/lib/liquid/tags/table_row.rb +57 -41
  54. data/lib/liquid/tags/unless.rb +38 -20
  55. data/lib/liquid/template.rb +71 -103
  56. data/lib/liquid/template_factory.rb +9 -0
  57. data/lib/liquid/tokenizer.rb +39 -0
  58. data/lib/liquid/usage.rb +8 -0
  59. data/lib/liquid/utils.rb +63 -9
  60. data/lib/liquid/variable.rb +74 -56
  61. data/lib/liquid/variable_lookup.rb +31 -15
  62. data/lib/liquid/version.rb +3 -1
  63. data/lib/liquid.rb +27 -12
  64. metadata +30 -106
  65. data/lib/liquid/module_ex.rb +0 -62
  66. data/lib/liquid/strainer.rb +0 -59
  67. data/lib/liquid/token.rb +0 -18
  68. data/test/fixtures/en_locale.yml +0 -9
  69. data/test/integration/assign_test.rb +0 -48
  70. data/test/integration/blank_test.rb +0 -106
  71. data/test/integration/capture_test.rb +0 -50
  72. data/test/integration/context_test.rb +0 -32
  73. data/test/integration/drop_test.rb +0 -271
  74. data/test/integration/error_handling_test.rb +0 -207
  75. data/test/integration/filter_test.rb +0 -138
  76. data/test/integration/hash_ordering_test.rb +0 -23
  77. data/test/integration/output_test.rb +0 -124
  78. data/test/integration/parsing_quirks_test.rb +0 -116
  79. data/test/integration/render_profiling_test.rb +0 -154
  80. data/test/integration/security_test.rb +0 -64
  81. data/test/integration/standard_filter_test.rb +0 -396
  82. data/test/integration/tags/break_tag_test.rb +0 -16
  83. data/test/integration/tags/continue_tag_test.rb +0 -16
  84. data/test/integration/tags/for_tag_test.rb +0 -375
  85. data/test/integration/tags/if_else_tag_test.rb +0 -190
  86. data/test/integration/tags/include_tag_test.rb +0 -234
  87. data/test/integration/tags/increment_tag_test.rb +0 -24
  88. data/test/integration/tags/raw_tag_test.rb +0 -25
  89. data/test/integration/tags/standard_tag_test.rb +0 -297
  90. data/test/integration/tags/statements_test.rb +0 -113
  91. data/test/integration/tags/table_row_test.rb +0 -63
  92. data/test/integration/tags/unless_else_tag_test.rb +0 -26
  93. data/test/integration/template_test.rb +0 -182
  94. data/test/integration/variable_test.rb +0 -82
  95. data/test/test_helper.rb +0 -89
  96. data/test/unit/block_unit_test.rb +0 -55
  97. data/test/unit/condition_unit_test.rb +0 -149
  98. data/test/unit/context_unit_test.rb +0 -492
  99. data/test/unit/file_system_unit_test.rb +0 -35
  100. data/test/unit/i18n_unit_test.rb +0 -37
  101. data/test/unit/lexer_unit_test.rb +0 -48
  102. data/test/unit/module_ex_unit_test.rb +0 -87
  103. data/test/unit/parser_unit_test.rb +0 -82
  104. data/test/unit/regexp_unit_test.rb +0 -44
  105. data/test/unit/strainer_unit_test.rb +0 -69
  106. data/test/unit/tag_unit_test.rb +0 -16
  107. data/test/unit/tags/case_tag_unit_test.rb +0 -10
  108. data/test/unit/tags/for_tag_unit_test.rb +0 -13
  109. data/test/unit/tags/if_tag_unit_test.rb +0 -8
  110. data/test/unit/template_unit_test.rb +0 -69
  111. data/test/unit/tokenizer_unit_test.rb +0 -38
  112. data/test/unit/variable_unit_test.rb +0 -145
  113. /data/{MIT-LICENSE → LICENSE} +0 -0
@@ -1,234 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestFileSystem
4
- def read_template_file(template_path, context)
5
- case template_path
6
- when "product"
7
- "Product: {{ product.title }} "
8
-
9
- when "locale_variables"
10
- "Locale: {{echo1}} {{echo2}}"
11
-
12
- when "variant"
13
- "Variant: {{ variant.title }}"
14
-
15
- when "nested_template"
16
- "{% include 'header' %} {% include 'body' %} {% include 'footer' %}"
17
-
18
- when "body"
19
- "body {% include 'body_detail' %}"
20
-
21
- when "nested_product_template"
22
- "Product: {{ nested_product_template.title }} {%include 'details'%} "
23
-
24
- when "recursively_nested_template"
25
- "-{% include 'recursively_nested_template' %}"
26
-
27
- when "pick_a_source"
28
- "from TestFileSystem"
29
-
30
- when 'assignments'
31
- "{% assign foo = 'bar' %}"
32
-
33
- else
34
- template_path
35
- end
36
- end
37
- end
38
-
39
- class OtherFileSystem
40
- def read_template_file(template_path, context)
41
- 'from OtherFileSystem'
42
- end
43
- end
44
-
45
- class CountingFileSystem
46
- attr_reader :count
47
- def read_template_file(template_path, context)
48
- @count ||= 0
49
- @count += 1
50
- 'from CountingFileSystem'
51
- end
52
- end
53
-
54
- class CustomInclude < Liquid::Tag
55
- Syntax = /(#{Liquid::QuotedFragment}+)(\s+(?:with|for)\s+(#{Liquid::QuotedFragment}+))?/o
56
-
57
- def initialize(tag_name, markup, tokens)
58
- markup =~ Syntax
59
- @template_name = $1
60
- super
61
- end
62
-
63
- def parse(tokens)
64
- end
65
-
66
- def render(context)
67
- @template_name[1..-2]
68
- end
69
- end
70
-
71
- class IncludeTagTest < Minitest::Test
72
- include Liquid
73
-
74
- def setup
75
- Liquid::Template.file_system = TestFileSystem.new
76
- end
77
-
78
- def test_include_tag_looks_for_file_system_in_registers_first
79
- assert_equal 'from OtherFileSystem',
80
- Template.parse("{% include 'pick_a_source' %}").render!({}, :registers => {:file_system => OtherFileSystem.new})
81
- end
82
-
83
-
84
- def test_include_tag_with
85
- assert_template_result "Product: Draft 151cm ",
86
- "{% include 'product' with products[0] %}", "products" => [ {'title' => 'Draft 151cm'}, {'title' => 'Element 155cm'} ]
87
- end
88
-
89
- def test_include_tag_with_default_name
90
- assert_template_result "Product: Draft 151cm ",
91
- "{% include 'product' %}", "product" => {'title' => 'Draft 151cm'}
92
- end
93
-
94
- def test_include_tag_for
95
- assert_template_result "Product: Draft 151cm Product: Element 155cm ",
96
- "{% include 'product' for products %}", "products" => [ {'title' => 'Draft 151cm'}, {'title' => 'Element 155cm'} ]
97
- end
98
-
99
- def test_include_tag_with_local_variables
100
- assert_template_result "Locale: test123 ", "{% include 'locale_variables' echo1: 'test123' %}"
101
- end
102
-
103
- def test_include_tag_with_multiple_local_variables
104
- assert_template_result "Locale: test123 test321",
105
- "{% include 'locale_variables' echo1: 'test123', echo2: 'test321' %}"
106
- end
107
-
108
- def test_include_tag_with_multiple_local_variables_from_context
109
- assert_template_result "Locale: test123 test321",
110
- "{% include 'locale_variables' echo1: echo1, echo2: more_echos.echo2 %}",
111
- 'echo1' => 'test123', 'more_echos' => { "echo2" => 'test321'}
112
- end
113
-
114
- def test_included_templates_assigns_variables
115
- assert_template_result "bar", "{% include 'assignments' %}{{ foo }}"
116
- end
117
-
118
- def test_nested_include_tag
119
- assert_template_result "body body_detail", "{% include 'body' %}"
120
-
121
- assert_template_result "header body body_detail footer", "{% include 'nested_template' %}"
122
- end
123
-
124
- def test_nested_include_with_variable
125
- assert_template_result "Product: Draft 151cm details ",
126
- "{% include 'nested_product_template' with product %}", "product" => {"title" => 'Draft 151cm'}
127
-
128
- assert_template_result "Product: Draft 151cm details Product: Element 155cm details ",
129
- "{% include 'nested_product_template' for products %}", "products" => [{"title" => 'Draft 151cm'}, {"title" => 'Element 155cm'}]
130
- end
131
-
132
- def test_recursively_included_template_does_not_produce_endless_loop
133
-
134
- infinite_file_system = Class.new do
135
- def read_template_file(template_path, context)
136
- "-{% include 'loop' %}"
137
- end
138
- end
139
-
140
- Liquid::Template.file_system = infinite_file_system.new
141
-
142
- assert_raises(Liquid::StackLevelError, SystemStackError) do
143
- Template.parse("{% include 'loop' %}").render!
144
- end
145
-
146
- end
147
-
148
- def test_backwards_compatability_support_for_overridden_read_template_file
149
- infinite_file_system = Class.new do
150
- def read_template_file(template_path) # testing only one argument here.
151
- "- hi mom"
152
- end
153
- end
154
-
155
- Liquid::Template.file_system = infinite_file_system.new
156
-
157
- Template.parse("{% include 'hi_mom' %}").render!
158
- end
159
-
160
- def test_dynamically_choosen_template
161
- assert_template_result "Test123", "{% include template %}", "template" => 'Test123'
162
- assert_template_result "Test321", "{% include template %}", "template" => 'Test321'
163
-
164
- assert_template_result "Product: Draft 151cm ", "{% include template for product %}",
165
- "template" => 'product', 'product' => { 'title' => 'Draft 151cm'}
166
- end
167
-
168
- def test_include_tag_caches_second_read_of_same_partial
169
- file_system = CountingFileSystem.new
170
- assert_equal 'from CountingFileSystemfrom CountingFileSystem',
171
- Template.parse("{% include 'pick_a_source' %}{% include 'pick_a_source' %}").render!({}, :registers => {:file_system => file_system})
172
- assert_equal 1, file_system.count
173
- end
174
-
175
- def test_include_tag_doesnt_cache_partials_across_renders
176
- file_system = CountingFileSystem.new
177
- assert_equal 'from CountingFileSystem',
178
- Template.parse("{% include 'pick_a_source' %}").render!({}, :registers => {:file_system => file_system})
179
- assert_equal 1, file_system.count
180
-
181
- assert_equal 'from CountingFileSystem',
182
- Template.parse("{% include 'pick_a_source' %}").render!({}, :registers => {:file_system => file_system})
183
- assert_equal 2, file_system.count
184
- end
185
-
186
- def test_include_tag_within_if_statement
187
- assert_template_result "foo_if_true", "{% if true %}{% include 'foo_if_true' %}{% endif %}"
188
- end
189
-
190
- def test_custom_include_tag
191
- original_tag = Liquid::Template.tags['include']
192
- Liquid::Template.tags['include'] = CustomInclude
193
- begin
194
- assert_equal "custom_foo",
195
- Template.parse("{% include 'custom_foo' %}").render!
196
- ensure
197
- Liquid::Template.tags['include'] = original_tag
198
- end
199
- end
200
-
201
- def test_custom_include_tag_within_if_statement
202
- original_tag = Liquid::Template.tags['include']
203
- Liquid::Template.tags['include'] = CustomInclude
204
- begin
205
- assert_equal "custom_foo_if_true",
206
- Template.parse("{% if true %}{% include 'custom_foo_if_true' %}{% endif %}").render!
207
- ensure
208
- Liquid::Template.tags['include'] = original_tag
209
- end
210
- end
211
-
212
- def test_does_not_add_error_in_strict_mode_for_missing_variable
213
- Liquid::Template.file_system = TestFileSystem.new
214
-
215
- a = Liquid::Template.parse(' {% include "nested_template" %}')
216
- a.render!
217
- assert_empty a.errors
218
- end
219
-
220
- def test_passing_options_to_included_templates
221
- assert_raises(Liquid::SyntaxError) do
222
- Template.parse("{% include template %}", error_mode: :strict).render!("template" => '{{ "X" || downcase }}')
223
- end
224
- with_error_mode(:lax) do
225
- assert_equal 'x', Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: true).render!("template" => '{{ "X" || downcase }}')
226
- end
227
- assert_raises(Liquid::SyntaxError) do
228
- Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: [:locale]).render!("template" => '{{ "X" || downcase }}')
229
- end
230
- with_error_mode(:lax) do
231
- assert_equal 'x', Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: [:error_mode]).render!("template" => '{{ "X" || downcase }}')
232
- end
233
- end
234
- end # IncludeTagTest
@@ -1,24 +0,0 @@
1
- require 'test_helper'
2
-
3
- class IncrementTagTest < Minitest::Test
4
- include Liquid
5
-
6
- def test_inc
7
- assert_template_result('0','{%increment port %}', {})
8
- assert_template_result('0 1','{%increment port %} {%increment port%}', {})
9
- assert_template_result('0 0 1 2 1',
10
- '{%increment port %} {%increment starboard%} ' +
11
- '{%increment port %} {%increment port%} ' +
12
- '{%increment starboard %}', {})
13
- end
14
-
15
- def test_dec
16
- assert_template_result('9','{%decrement port %}', { 'port' => 10})
17
- assert_template_result('-1 -2','{%decrement port %} {%decrement port%}', {})
18
- assert_template_result('1 5 2 2 5',
19
- '{%increment port %} {%increment starboard%} ' +
20
- '{%increment port %} {%decrement port%} ' +
21
- '{%decrement starboard %}', { 'port' => 1, 'starboard' => 5 })
22
- end
23
-
24
- end
@@ -1,25 +0,0 @@
1
- require 'test_helper'
2
-
3
- class RawTagTest < Minitest::Test
4
- include Liquid
5
-
6
- def test_tag_in_raw
7
- assert_template_result '{% comment %} test {% endcomment %}',
8
- '{% raw %}{% comment %} test {% endcomment %}{% endraw %}'
9
- end
10
-
11
- def test_output_in_raw
12
- assert_template_result '{{ test }}', '{% raw %}{{ test }}{% endraw %}'
13
- end
14
-
15
- def test_open_tag_in_raw
16
- assert_template_result ' Foobar {% invalid ', '{% raw %} Foobar {% invalid {% endraw %}'
17
- assert_template_result ' Foobar invalid %} ', '{% raw %} Foobar invalid %} {% endraw %}'
18
- assert_template_result ' Foobar {{ invalid ', '{% raw %} Foobar {{ invalid {% endraw %}'
19
- assert_template_result ' Foobar invalid }} ', '{% raw %} Foobar invalid }} {% endraw %}'
20
- assert_template_result ' Foobar {% invalid {% {% endraw ', '{% raw %} Foobar {% invalid {% {% endraw {% endraw %}'
21
- assert_template_result ' Foobar {% {% {% ', '{% raw %} Foobar {% {% {% {% endraw %}'
22
- assert_template_result ' test {% raw %} {% endraw %}', '{% raw %} test {% raw %} {% {% endraw %}endraw %}'
23
- assert_template_result ' Foobar {{ invalid 1', '{% raw %} Foobar {{ invalid {% endraw %}{{ 1 }}'
24
- end
25
- end
@@ -1,297 +0,0 @@
1
- require 'test_helper'
2
-
3
- class StandardTagTest < Minitest::Test
4
- include Liquid
5
-
6
- def test_no_transform
7
- assert_template_result('this text should come out of the template without change...',
8
- 'this text should come out of the template without change...')
9
-
10
- assert_template_result('blah','blah')
11
- assert_template_result('<blah>','<blah>')
12
- assert_template_result('|,.:','|,.:')
13
- assert_template_result('','')
14
-
15
- text = %|this shouldnt see any transformation either but has multiple lines
16
- as you can clearly see here ...|
17
- assert_template_result(text,text)
18
- end
19
-
20
- def test_has_a_block_which_does_nothing
21
- assert_template_result(%|the comment block should be removed .. right?|,
22
- %|the comment block should be removed {%comment%} be gone.. {%endcomment%} .. right?|)
23
-
24
- assert_template_result('','{%comment%}{%endcomment%}')
25
- assert_template_result('','{%comment%}{% endcomment %}')
26
- assert_template_result('','{% comment %}{%endcomment%}')
27
- assert_template_result('','{% comment %}{% endcomment %}')
28
- assert_template_result('','{%comment%}comment{%endcomment%}')
29
- assert_template_result('','{% comment %}comment{% endcomment %}')
30
- assert_template_result('','{% comment %} 1 {% comment %} 2 {% endcomment %} 3 {% endcomment %}')
31
-
32
- assert_template_result('','{%comment%}{%blabla%}{%endcomment%}')
33
- assert_template_result('','{% comment %}{% blabla %}{% endcomment %}')
34
- assert_template_result('','{%comment%}{% endif %}{%endcomment%}')
35
- assert_template_result('','{% comment %}{% endwhatever %}{% endcomment %}')
36
- assert_template_result('','{% comment %}{% raw %} {{%%%%}} }} { {% endcomment %} {% comment {% endraw %} {% endcomment %}')
37
-
38
- assert_template_result('foobar','foo{%comment%}comment{%endcomment%}bar')
39
- assert_template_result('foobar','foo{% comment %}comment{% endcomment %}bar')
40
- assert_template_result('foobar','foo{%comment%} comment {%endcomment%}bar')
41
- assert_template_result('foobar','foo{% comment %} comment {% endcomment %}bar')
42
-
43
- assert_template_result('foo bar','foo {%comment%} {%endcomment%} bar')
44
- assert_template_result('foo bar','foo {%comment%}comment{%endcomment%} bar')
45
- assert_template_result('foo bar','foo {%comment%} comment {%endcomment%} bar')
46
-
47
- assert_template_result('foobar','foo{%comment%}
48
- {%endcomment%}bar')
49
- end
50
-
51
- def test_hyphenated_assign
52
- assigns = {'a-b' => '1' }
53
- assert_template_result('a-b:1 a-b:2', 'a-b:{{a-b}} {%assign a-b = 2 %}a-b:{{a-b}}', assigns)
54
- end
55
-
56
- def test_assign_with_colon_and_spaces
57
- assigns = {'var' => {'a:b c' => {'paged' => '1' }}}
58
- assert_template_result('var2: 1', '{%assign var2 = var["a:b c"].paged %}var2: {{var2}}', assigns)
59
- end
60
-
61
- def test_capture
62
- assigns = {'var' => 'content' }
63
- assert_template_result('content foo content foo ',
64
- '{{ var2 }}{% capture var2 %}{{ var }} foo {% endcapture %}{{ var2 }}{{ var2 }}',
65
- assigns)
66
- end
67
-
68
- def test_capture_detects_bad_syntax
69
- assert_raises(SyntaxError) do
70
- assert_template_result('content foo content foo ',
71
- '{{ var2 }}{% capture %}{{ var }} foo {% endcapture %}{{ var2 }}{{ var2 }}',
72
- {'var' => 'content' })
73
- end
74
- end
75
-
76
- def test_case
77
- assigns = {'condition' => 2 }
78
- assert_template_result(' its 2 ',
79
- '{% case condition %}{% when 1 %} its 1 {% when 2 %} its 2 {% endcase %}',
80
- assigns)
81
-
82
- assigns = {'condition' => 1 }
83
- assert_template_result(' its 1 ',
84
- '{% case condition %}{% when 1 %} its 1 {% when 2 %} its 2 {% endcase %}',
85
- assigns)
86
-
87
- assigns = {'condition' => 3 }
88
- assert_template_result('',
89
- '{% case condition %}{% when 1 %} its 1 {% when 2 %} its 2 {% endcase %}',
90
- assigns)
91
-
92
- assigns = {'condition' => "string here" }
93
- assert_template_result(' hit ',
94
- '{% case condition %}{% when "string here" %} hit {% endcase %}',
95
- assigns)
96
-
97
- assigns = {'condition' => "bad string here" }
98
- assert_template_result('',
99
- '{% case condition %}{% when "string here" %} hit {% endcase %}',\
100
- assigns)
101
- end
102
-
103
- def test_case_with_else
104
- assigns = {'condition' => 5 }
105
- assert_template_result(' hit ',
106
- '{% case condition %}{% when 5 %} hit {% else %} else {% endcase %}',
107
- assigns)
108
-
109
- assigns = {'condition' => 6 }
110
- assert_template_result(' else ',
111
- '{% case condition %}{% when 5 %} hit {% else %} else {% endcase %}',
112
- assigns)
113
-
114
- assigns = {'condition' => 6 }
115
- assert_template_result(' else ',
116
- '{% case condition %} {% when 5 %} hit {% else %} else {% endcase %}',
117
- assigns)
118
- end
119
-
120
- def test_case_on_size
121
- assert_template_result('', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [])
122
- assert_template_result('1', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1])
123
- assert_template_result('2', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1, 1])
124
- assert_template_result('', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1, 1, 1])
125
- assert_template_result('', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1, 1, 1, 1])
126
- assert_template_result('', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1, 1, 1, 1, 1])
127
- end
128
-
129
- def test_case_on_size_with_else
130
- assert_template_result('else',
131
- '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}',
132
- 'a' => [])
133
-
134
- assert_template_result('1',
135
- '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}',
136
- 'a' => [1])
137
-
138
- assert_template_result('2',
139
- '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}',
140
- 'a' => [1, 1])
141
-
142
- assert_template_result('else',
143
- '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}',
144
- 'a' => [1, 1, 1])
145
-
146
- assert_template_result('else',
147
- '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}',
148
- 'a' => [1, 1, 1, 1])
149
-
150
- assert_template_result('else',
151
- '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}',
152
- 'a' => [1, 1, 1, 1, 1])
153
- end
154
-
155
- def test_case_on_length_with_else
156
- assert_template_result('else',
157
- '{% case a.empty? %}{% when true %}true{% when false %}false{% else %}else{% endcase %}',
158
- {})
159
-
160
- assert_template_result('false',
161
- '{% case false %}{% when true %}true{% when false %}false{% else %}else{% endcase %}',
162
- {})
163
-
164
- assert_template_result('true',
165
- '{% case true %}{% when true %}true{% when false %}false{% else %}else{% endcase %}',
166
- {})
167
-
168
- assert_template_result('else',
169
- '{% case NULL %}{% when true %}true{% when false %}false{% else %}else{% endcase %}',
170
- {})
171
- end
172
-
173
- def test_assign_from_case
174
- # Example from the shopify forums
175
- code = %q({% case collection.handle %}{% when 'menswear-jackets' %}{% assign ptitle = 'menswear' %}{% when 'menswear-t-shirts' %}{% assign ptitle = 'menswear' %}{% else %}{% assign ptitle = 'womenswear' %}{% endcase %}{{ ptitle }})
176
- template = Liquid::Template.parse(code)
177
- assert_equal "menswear", template.render!("collection" => {'handle' => 'menswear-jackets'})
178
- assert_equal "menswear", template.render!("collection" => {'handle' => 'menswear-t-shirts'})
179
- assert_equal "womenswear", template.render!("collection" => {'handle' => 'x'})
180
- assert_equal "womenswear", template.render!("collection" => {'handle' => 'y'})
181
- assert_equal "womenswear", template.render!("collection" => {'handle' => 'z'})
182
- end
183
-
184
- def test_case_when_or
185
- code = '{% case condition %}{% when 1 or 2 or 3 %} its 1 or 2 or 3 {% when 4 %} its 4 {% endcase %}'
186
- assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 1 })
187
- assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 2 })
188
- assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 3 })
189
- assert_template_result(' its 4 ', code, {'condition' => 4 })
190
- assert_template_result('', code, {'condition' => 5 })
191
-
192
- code = '{% case condition %}{% when 1 or "string" or null %} its 1 or 2 or 3 {% when 4 %} its 4 {% endcase %}'
193
- assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 1 })
194
- assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 'string' })
195
- assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => nil })
196
- assert_template_result('', code, {'condition' => 'something else' })
197
- end
198
-
199
- def test_case_when_comma
200
- code = '{% case condition %}{% when 1, 2, 3 %} its 1 or 2 or 3 {% when 4 %} its 4 {% endcase %}'
201
- assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 1 })
202
- assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 2 })
203
- assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 3 })
204
- assert_template_result(' its 4 ', code, {'condition' => 4 })
205
- assert_template_result('', code, {'condition' => 5 })
206
-
207
- code = '{% case condition %}{% when 1, "string", null %} its 1 or 2 or 3 {% when 4 %} its 4 {% endcase %}'
208
- assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 1 })
209
- assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 'string' })
210
- assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => nil })
211
- assert_template_result('', code, {'condition' => 'something else' })
212
- end
213
-
214
- def test_assign
215
- assert_template_result 'variable', '{% assign a = "variable"%}{{a}}'
216
- end
217
-
218
- def test_assign_unassigned
219
- assigns = { 'var' => 'content' }
220
- assert_template_result('var2: var2:content', 'var2:{{var2}} {%assign var2 = var%} var2:{{var2}}', assigns)
221
- end
222
-
223
- def test_assign_an_empty_string
224
- assert_template_result '', '{% assign a = ""%}{{a}}'
225
- end
226
-
227
- def test_assign_is_global
228
- assert_template_result 'variable', '{%for i in (1..2) %}{% assign a = "variable"%}{% endfor %}{{a}}'
229
- end
230
-
231
- def test_case_detects_bad_syntax
232
- assert_raises(SyntaxError) do
233
- assert_template_result('', '{% case false %}{% when %}true{% endcase %}', {})
234
- end
235
-
236
- assert_raises(SyntaxError) do
237
- assert_template_result('', '{% case false %}{% huh %}true{% endcase %}', {})
238
- end
239
-
240
- end
241
-
242
- def test_cycle
243
- assert_template_result('one','{%cycle "one", "two"%}')
244
- assert_template_result('one two','{%cycle "one", "two"%} {%cycle "one", "two"%}')
245
- assert_template_result(' two','{%cycle "", "two"%} {%cycle "", "two"%}')
246
-
247
- assert_template_result('one two one','{%cycle "one", "two"%} {%cycle "one", "two"%} {%cycle "one", "two"%}')
248
-
249
- assert_template_result('text-align: left text-align: right',
250
- '{%cycle "text-align: left", "text-align: right" %} {%cycle "text-align: left", "text-align: right"%}')
251
- end
252
-
253
- def test_multiple_cycles
254
- assert_template_result('1 2 1 1 2 3 1',
255
- '{%cycle 1,2%} {%cycle 1,2%} {%cycle 1,2%} {%cycle 1,2,3%} {%cycle 1,2,3%} {%cycle 1,2,3%} {%cycle 1,2,3%}')
256
- end
257
-
258
- def test_multiple_named_cycles
259
- assert_template_result('one one two two one one',
260
- '{%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %} {%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %} {%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %}')
261
- end
262
-
263
- def test_multiple_named_cycles_with_names_from_context
264
- assigns = {"var1" => 1, "var2" => 2 }
265
- assert_template_result('one one two two one one',
266
- '{%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)
267
- end
268
-
269
- def test_size_of_array
270
- assigns = {"array" => [1,2,3,4]}
271
- assert_template_result('array has 4 elements', "array has {{ array.size }} elements", assigns)
272
- end
273
-
274
- def test_size_of_hash
275
- assigns = {"hash" => {:a => 1, :b => 2, :c=> 3, :d => 4}}
276
- assert_template_result('hash has 4 elements', "hash has {{ hash.size }} elements", assigns)
277
- end
278
-
279
- def test_illegal_symbols
280
- assert_template_result('', '{% if true == empty %}?{% endif %}', {})
281
- assert_template_result('', '{% if true == null %}?{% endif %}', {})
282
- assert_template_result('', '{% if empty == true %}?{% endif %}', {})
283
- assert_template_result('', '{% if null == true %}?{% endif %}', {})
284
- end
285
-
286
- def test_ifchanged
287
- assigns = {'array' => [ 1, 1, 2, 2, 3, 3] }
288
- assert_template_result('123','{%for item in array%}{%ifchanged%}{{item}}{% endifchanged %}{%endfor%}',assigns)
289
-
290
- assigns = {'array' => [ 1, 1, 1, 1] }
291
- assert_template_result('1','{%for item in array%}{%ifchanged%}{{item}}{% endifchanged %}{%endfor%}',assigns)
292
- end
293
-
294
- def test_multiline_tag
295
- assert_template_result '0 1 2 3', "0{%\nfor i in (1..3)\n%} {{\ni\n}}{%\nendfor\n%}"
296
- end
297
- end # StandardTagTest