liquid 4.0.3 → 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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +89 -0
  3. data/README.md +10 -4
  4. data/lib/liquid/block.rb +31 -14
  5. data/lib/liquid/block_body.rb +169 -57
  6. data/lib/liquid/condition.rb +48 -21
  7. data/lib/liquid/context.rb +111 -52
  8. data/lib/liquid/document.rb +47 -9
  9. data/lib/liquid/drop.rb +4 -2
  10. data/lib/liquid/errors.rb +20 -18
  11. data/lib/liquid/expression.rb +28 -32
  12. data/lib/liquid/extensions.rb +2 -0
  13. data/lib/liquid/file_system.rb +6 -4
  14. data/lib/liquid/forloop_drop.rb +54 -4
  15. data/lib/liquid/i18n.rb +5 -3
  16. data/lib/liquid/interrupts.rb +3 -1
  17. data/lib/liquid/lexer.rb +30 -23
  18. data/lib/liquid/locales/en.yml +8 -5
  19. data/lib/liquid/parse_context.rb +20 -4
  20. data/lib/liquid/parse_tree_visitor.rb +2 -2
  21. data/lib/liquid/parser.rb +30 -18
  22. data/lib/liquid/parser_switching.rb +17 -3
  23. data/lib/liquid/partial_cache.rb +24 -0
  24. data/lib/liquid/profiler/hooks.rb +26 -14
  25. data/lib/liquid/profiler.rb +67 -86
  26. data/lib/liquid/range_lookup.rb +13 -3
  27. data/lib/liquid/registers.rb +51 -0
  28. data/lib/liquid/resource_limits.rb +47 -8
  29. data/lib/liquid/standardfilters.rb +551 -114
  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 +64 -5
  33. data/lib/liquid/tag/disableable.rb +22 -0
  34. data/lib/liquid/tag/disabler.rb +21 -0
  35. data/lib/liquid/tag.rb +28 -6
  36. data/lib/liquid/tags/assign.rb +36 -18
  37. data/lib/liquid/tags/break.rb +16 -3
  38. data/lib/liquid/tags/capture.rb +24 -18
  39. data/lib/liquid/tags/case.rb +61 -27
  40. data/lib/liquid/tags/comment.rb +18 -3
  41. data/lib/liquid/tags/continue.rb +16 -12
  42. data/lib/liquid/tags/cycle.rb +37 -25
  43. data/lib/liquid/tags/decrement.rb +22 -20
  44. data/lib/liquid/tags/echo.rb +41 -0
  45. data/lib/liquid/tags/for.rb +90 -87
  46. data/lib/liquid/tags/if.rb +50 -32
  47. data/lib/liquid/tags/ifchanged.rb +11 -10
  48. data/lib/liquid/tags/include.rb +49 -60
  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 +25 -11
  52. data/lib/liquid/tags/render.rb +109 -0
  53. data/lib/liquid/tags/table_row.rb +45 -19
  54. data/lib/liquid/tags/unless.rb +38 -19
  55. data/lib/liquid/template.rb +52 -72
  56. data/lib/liquid/template_factory.rb +9 -0
  57. data/lib/liquid/tokenizer.rb +18 -10
  58. data/lib/liquid/usage.rb +8 -0
  59. data/lib/liquid/utils.rb +13 -3
  60. data/lib/liquid/variable.rb +49 -44
  61. data/lib/liquid/variable_lookup.rb +18 -10
  62. data/lib/liquid/version.rb +2 -1
  63. data/lib/liquid.rb +18 -6
  64. metadata +20 -108
  65. data/lib/liquid/strainer.rb +0 -66
  66. data/lib/liquid/truffle.rb +0 -5
  67. data/test/fixtures/en_locale.yml +0 -9
  68. data/test/integration/assign_test.rb +0 -48
  69. data/test/integration/blank_test.rb +0 -106
  70. data/test/integration/block_test.rb +0 -12
  71. data/test/integration/capture_test.rb +0 -50
  72. data/test/integration/context_test.rb +0 -32
  73. data/test/integration/document_test.rb +0 -19
  74. data/test/integration/drop_test.rb +0 -273
  75. data/test/integration/error_handling_test.rb +0 -260
  76. data/test/integration/filter_test.rb +0 -178
  77. data/test/integration/hash_ordering_test.rb +0 -23
  78. data/test/integration/output_test.rb +0 -123
  79. data/test/integration/parse_tree_visitor_test.rb +0 -247
  80. data/test/integration/parsing_quirks_test.rb +0 -122
  81. data/test/integration/render_profiling_test.rb +0 -154
  82. data/test/integration/security_test.rb +0 -80
  83. data/test/integration/standard_filter_test.rb +0 -776
  84. data/test/integration/tags/break_tag_test.rb +0 -15
  85. data/test/integration/tags/continue_tag_test.rb +0 -15
  86. data/test/integration/tags/for_tag_test.rb +0 -410
  87. data/test/integration/tags/if_else_tag_test.rb +0 -188
  88. data/test/integration/tags/include_tag_test.rb +0 -253
  89. data/test/integration/tags/increment_tag_test.rb +0 -23
  90. data/test/integration/tags/raw_tag_test.rb +0 -31
  91. data/test/integration/tags/standard_tag_test.rb +0 -296
  92. data/test/integration/tags/statements_test.rb +0 -111
  93. data/test/integration/tags/table_row_test.rb +0 -64
  94. data/test/integration/tags/unless_else_tag_test.rb +0 -26
  95. data/test/integration/template_test.rb +0 -332
  96. data/test/integration/trim_mode_test.rb +0 -529
  97. data/test/integration/variable_test.rb +0 -96
  98. data/test/test_helper.rb +0 -116
  99. data/test/truffle/truffle_test.rb +0 -9
  100. data/test/unit/block_unit_test.rb +0 -58
  101. data/test/unit/condition_unit_test.rb +0 -166
  102. data/test/unit/context_unit_test.rb +0 -489
  103. data/test/unit/file_system_unit_test.rb +0 -35
  104. data/test/unit/i18n_unit_test.rb +0 -37
  105. data/test/unit/lexer_unit_test.rb +0 -51
  106. data/test/unit/parser_unit_test.rb +0 -82
  107. data/test/unit/regexp_unit_test.rb +0 -44
  108. data/test/unit/strainer_unit_test.rb +0 -164
  109. data/test/unit/tag_unit_test.rb +0 -21
  110. data/test/unit/tags/case_tag_unit_test.rb +0 -10
  111. data/test/unit/tags/for_tag_unit_test.rb +0 -13
  112. data/test/unit/tags/if_tag_unit_test.rb +0 -8
  113. data/test/unit/template_unit_test.rb +0 -78
  114. data/test/unit/tokenizer_unit_test.rb +0 -55
  115. data/test/unit/variable_unit_test.rb +0 -162
@@ -1,253 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestFileSystem
4
- def read_template_file(template_path)
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
- when 'break'
34
- "{% break %}"
35
-
36
- else
37
- template_path
38
- end
39
- end
40
- end
41
-
42
- class OtherFileSystem
43
- def read_template_file(template_path)
44
- 'from OtherFileSystem'
45
- end
46
- end
47
-
48
- class CountingFileSystem
49
- attr_reader :count
50
- def read_template_file(template_path)
51
- @count ||= 0
52
- @count += 1
53
- 'from CountingFileSystem'
54
- end
55
- end
56
-
57
- class CustomInclude < Liquid::Tag
58
- Syntax = /(#{Liquid::QuotedFragment}+)(\s+(?:with|for)\s+(#{Liquid::QuotedFragment}+))?/o
59
-
60
- def initialize(tag_name, markup, tokens)
61
- markup =~ Syntax
62
- @template_name = $1
63
- super
64
- end
65
-
66
- def parse(tokens)
67
- end
68
-
69
- def render(context)
70
- @template_name[1..-2]
71
- end
72
- end
73
-
74
- class IncludeTagTest < Minitest::Test
75
- include Liquid
76
-
77
- def setup
78
- Liquid::Template.file_system = TestFileSystem.new
79
- end
80
-
81
- def test_include_tag_looks_for_file_system_in_registers_first
82
- assert_equal 'from OtherFileSystem',
83
- Template.parse("{% include 'pick_a_source' %}").render!({}, registers: { file_system: OtherFileSystem.new })
84
- end
85
-
86
- def test_include_tag_with
87
- assert_template_result "Product: Draft 151cm ",
88
- "{% include 'product' with products[0] %}", "products" => [ { 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' } ]
89
- end
90
-
91
- def test_include_tag_with_default_name
92
- assert_template_result "Product: Draft 151cm ",
93
- "{% include 'product' %}", "product" => { 'title' => 'Draft 151cm' }
94
- end
95
-
96
- def test_include_tag_for
97
- assert_template_result "Product: Draft 151cm Product: Element 155cm ",
98
- "{% include 'product' for products %}", "products" => [ { 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' } ]
99
- end
100
-
101
- def test_include_tag_with_local_variables
102
- assert_template_result "Locale: test123 ", "{% include 'locale_variables' echo1: 'test123' %}"
103
- end
104
-
105
- def test_include_tag_with_multiple_local_variables
106
- assert_template_result "Locale: test123 test321",
107
- "{% include 'locale_variables' echo1: 'test123', echo2: 'test321' %}"
108
- end
109
-
110
- def test_include_tag_with_multiple_local_variables_from_context
111
- assert_template_result "Locale: test123 test321",
112
- "{% include 'locale_variables' echo1: echo1, echo2: more_echos.echo2 %}",
113
- 'echo1' => 'test123', 'more_echos' => { "echo2" => 'test321' }
114
- end
115
-
116
- def test_included_templates_assigns_variables
117
- assert_template_result "bar", "{% include 'assignments' %}{{ foo }}"
118
- end
119
-
120
- def test_nested_include_tag
121
- assert_template_result "body body_detail", "{% include 'body' %}"
122
-
123
- assert_template_result "header body body_detail footer", "{% include 'nested_template' %}"
124
- end
125
-
126
- def test_nested_include_with_variable
127
- assert_template_result "Product: Draft 151cm details ",
128
- "{% include 'nested_product_template' with product %}", "product" => { "title" => 'Draft 151cm' }
129
-
130
- assert_template_result "Product: Draft 151cm details Product: Element 155cm details ",
131
- "{% include 'nested_product_template' for products %}", "products" => [{ "title" => 'Draft 151cm' }, { "title" => 'Element 155cm' }]
132
- end
133
-
134
- def test_recursively_included_template_does_not_produce_endless_loop
135
- infinite_file_system = Class.new do
136
- def read_template_file(template_path)
137
- "-{% include 'loop' %}"
138
- end
139
- end
140
-
141
- Liquid::Template.file_system = infinite_file_system.new
142
-
143
- assert_raises(Liquid::StackLevelError) do
144
- Template.parse("{% include 'loop' %}").render!
145
- end
146
- end
147
-
148
- def test_dynamically_choosen_template
149
- assert_template_result "Test123", "{% include template %}", "template" => 'Test123'
150
- assert_template_result "Test321", "{% include template %}", "template" => 'Test321'
151
-
152
- assert_template_result "Product: Draft 151cm ", "{% include template for product %}",
153
- "template" => 'product', 'product' => { 'title' => 'Draft 151cm' }
154
- end
155
-
156
- def test_include_tag_caches_second_read_of_same_partial
157
- file_system = CountingFileSystem.new
158
- assert_equal 'from CountingFileSystemfrom CountingFileSystem',
159
- Template.parse("{% include 'pick_a_source' %}{% include 'pick_a_source' %}").render!({}, registers: { file_system: file_system })
160
- assert_equal 1, file_system.count
161
- end
162
-
163
- def test_include_tag_doesnt_cache_partials_across_renders
164
- file_system = CountingFileSystem.new
165
- assert_equal 'from CountingFileSystem',
166
- Template.parse("{% include 'pick_a_source' %}").render!({}, registers: { file_system: file_system })
167
- assert_equal 1, file_system.count
168
-
169
- assert_equal 'from CountingFileSystem',
170
- Template.parse("{% include 'pick_a_source' %}").render!({}, registers: { file_system: file_system })
171
- assert_equal 2, file_system.count
172
- end
173
-
174
- def test_include_tag_within_if_statement
175
- assert_template_result "foo_if_true", "{% if true %}{% include 'foo_if_true' %}{% endif %}"
176
- end
177
-
178
- def test_custom_include_tag
179
- original_tag = Liquid::Template.tags['include']
180
- Liquid::Template.tags['include'] = CustomInclude
181
- begin
182
- assert_equal "custom_foo",
183
- Template.parse("{% include 'custom_foo' %}").render!
184
- ensure
185
- Liquid::Template.tags['include'] = original_tag
186
- end
187
- end
188
-
189
- def test_custom_include_tag_within_if_statement
190
- original_tag = Liquid::Template.tags['include']
191
- Liquid::Template.tags['include'] = CustomInclude
192
- begin
193
- assert_equal "custom_foo_if_true",
194
- Template.parse("{% if true %}{% include 'custom_foo_if_true' %}{% endif %}").render!
195
- ensure
196
- Liquid::Template.tags['include'] = original_tag
197
- end
198
- end
199
-
200
- def test_does_not_add_error_in_strict_mode_for_missing_variable
201
- Liquid::Template.file_system = TestFileSystem.new
202
-
203
- a = Liquid::Template.parse(' {% include "nested_template" %}')
204
- a.render!
205
- assert_empty a.errors
206
- end
207
-
208
- def test_passing_options_to_included_templates
209
- assert_raises(Liquid::SyntaxError) do
210
- Template.parse("{% include template %}", error_mode: :strict).render!("template" => '{{ "X" || downcase }}')
211
- end
212
- with_error_mode(:lax) do
213
- assert_equal 'x', Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: true).render!("template" => '{{ "X" || downcase }}')
214
- end
215
- assert_raises(Liquid::SyntaxError) do
216
- Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: [:locale]).render!("template" => '{{ "X" || downcase }}')
217
- end
218
- with_error_mode(:lax) do
219
- assert_equal 'x', Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: [:error_mode]).render!("template" => '{{ "X" || downcase }}')
220
- end
221
- end
222
-
223
- def test_render_raise_argument_error_when_template_is_undefined
224
- assert_raises(Liquid::ArgumentError) do
225
- template = Liquid::Template.parse('{% include undefined_variable %}')
226
- template.render!
227
- end
228
- assert_raises(Liquid::ArgumentError) do
229
- template = Liquid::Template.parse('{% include nil %}')
230
- template.render!
231
- end
232
- end
233
-
234
- def test_including_via_variable_value
235
- assert_template_result "from TestFileSystem", "{% assign page = 'pick_a_source' %}{% include page %}"
236
-
237
- assert_template_result "Product: Draft 151cm ", "{% assign page = 'product' %}{% include page %}", "product" => { 'title' => 'Draft 151cm' }
238
-
239
- assert_template_result "Product: Draft 151cm ", "{% assign page = 'product' %}{% include page for foo %}", "foo" => { 'title' => 'Draft 151cm' }
240
- end
241
-
242
- def test_including_with_strict_variables
243
- template = Liquid::Template.parse("{% include 'simple' %}", error_mode: :warn)
244
- template.render(nil, strict_variables: true)
245
-
246
- assert_equal [], template.errors
247
- end
248
-
249
- def test_break_through_include
250
- assert_template_result "1", "{% for i in (1..3) %}{{ i }}{% break %}{{ i }}{% endfor %}"
251
- assert_template_result "1", "{% for i in (1..3) %}{{ i }}{% include 'break' %}{{ i }}{% endfor %}"
252
- end
253
- end # IncludeTagTest
@@ -1,23 +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
- end
@@ -1,31 +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
-
26
- def test_invalid_raw
27
- assert_match_syntax_error(/tag was never closed/, '{% raw %} foo')
28
- assert_match_syntax_error(/Valid syntax/, '{% raw } foo {% endraw %}')
29
- assert_match_syntax_error(/Valid syntax/, '{% raw } foo %}{% endraw %}')
30
- end
31
- end
@@ -1,296 +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 = "{% 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
- end
240
-
241
- def test_cycle
242
- assert_template_result('one', '{%cycle "one", "two"%}')
243
- assert_template_result('one two', '{%cycle "one", "two"%} {%cycle "one", "two"%}')
244
- assert_template_result(' two', '{%cycle "", "two"%} {%cycle "", "two"%}')
245
-
246
- assert_template_result('one two one', '{%cycle "one", "two"%} {%cycle "one", "two"%} {%cycle "one", "two"%}')
247
-
248
- assert_template_result('text-align: left text-align: right',
249
- '{%cycle "text-align: left", "text-align: right" %} {%cycle "text-align: left", "text-align: right"%}')
250
- end
251
-
252
- def test_multiple_cycles
253
- assert_template_result('1 2 1 1 2 3 1',
254
- '{%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%}')
255
- end
256
-
257
- def test_multiple_named_cycles
258
- assert_template_result('one one two two one one',
259
- '{%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %} {%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %} {%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %}')
260
- end
261
-
262
- def test_multiple_named_cycles_with_names_from_context
263
- assigns = { "var1" => 1, "var2" => 2 }
264
- assert_template_result('one one two two one one',
265
- '{%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)
266
- end
267
-
268
- def test_size_of_array
269
- assigns = { "array" => [1, 2, 3, 4] }
270
- assert_template_result('array has 4 elements', "array has {{ array.size }} elements", assigns)
271
- end
272
-
273
- def test_size_of_hash
274
- assigns = { "hash" => { a: 1, b: 2, c: 3, d: 4 } }
275
- assert_template_result('hash has 4 elements', "hash has {{ hash.size }} elements", assigns)
276
- end
277
-
278
- def test_illegal_symbols
279
- assert_template_result('', '{% if true == empty %}?{% endif %}', {})
280
- assert_template_result('', '{% if true == null %}?{% endif %}', {})
281
- assert_template_result('', '{% if empty == true %}?{% endif %}', {})
282
- assert_template_result('', '{% if null == true %}?{% endif %}', {})
283
- end
284
-
285
- def test_ifchanged
286
- assigns = { 'array' => [ 1, 1, 2, 2, 3, 3] }
287
- assert_template_result('123', '{%for item in array%}{%ifchanged%}{{item}}{% endifchanged %}{%endfor%}', assigns)
288
-
289
- assigns = { 'array' => [ 1, 1, 1, 1] }
290
- assert_template_result('1', '{%for item in array%}{%ifchanged%}{{item}}{% endifchanged %}{%endfor%}', assigns)
291
- end
292
-
293
- def test_multiline_tag
294
- assert_template_result '0 1 2 3', "0{%\nfor i in (1..3)\n%} {{\ni\n}}{%\nendfor\n%}"
295
- end
296
- end # StandardTagTest