liquid 4.0.1 → 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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +142 -0
  3. data/README.md +10 -4
  4. data/lib/liquid/block.rb +31 -14
  5. data/lib/liquid/block_body.rb +169 -56
  6. data/lib/liquid/condition.rb +59 -23
  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 +29 -33
  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 +31 -24
  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 +42 -0
  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 +616 -129
  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 +44 -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 +69 -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 +45 -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 +97 -89
  46. data/lib/liquid/tags/if.rb +61 -35
  47. data/lib/liquid/tags/ifchanged.rb +11 -10
  48. data/lib/liquid/tags/include.rb +56 -56
  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 +53 -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 +52 -41
  61. data/lib/liquid/variable_lookup.rb +24 -10
  62. data/lib/liquid/version.rb +3 -1
  63. data/lib/liquid.rb +19 -6
  64. metadata +21 -104
  65. data/lib/liquid/strainer.rb +0 -66
  66. data/test/fixtures/en_locale.yml +0 -9
  67. data/test/integration/assign_test.rb +0 -48
  68. data/test/integration/blank_test.rb +0 -106
  69. data/test/integration/block_test.rb +0 -12
  70. data/test/integration/capture_test.rb +0 -50
  71. data/test/integration/context_test.rb +0 -32
  72. data/test/integration/document_test.rb +0 -19
  73. data/test/integration/drop_test.rb +0 -273
  74. data/test/integration/error_handling_test.rb +0 -260
  75. data/test/integration/filter_test.rb +0 -178
  76. data/test/integration/hash_ordering_test.rb +0 -23
  77. data/test/integration/output_test.rb +0 -123
  78. data/test/integration/parsing_quirks_test.rb +0 -122
  79. data/test/integration/render_profiling_test.rb +0 -154
  80. data/test/integration/security_test.rb +0 -80
  81. data/test/integration/standard_filter_test.rb +0 -626
  82. data/test/integration/tags/break_tag_test.rb +0 -15
  83. data/test/integration/tags/continue_tag_test.rb +0 -15
  84. data/test/integration/tags/for_tag_test.rb +0 -410
  85. data/test/integration/tags/if_else_tag_test.rb +0 -188
  86. data/test/integration/tags/include_tag_test.rb +0 -245
  87. data/test/integration/tags/increment_tag_test.rb +0 -23
  88. data/test/integration/tags/raw_tag_test.rb +0 -31
  89. data/test/integration/tags/standard_tag_test.rb +0 -296
  90. data/test/integration/tags/statements_test.rb +0 -111
  91. data/test/integration/tags/table_row_test.rb +0 -64
  92. data/test/integration/tags/unless_else_tag_test.rb +0 -26
  93. data/test/integration/template_test.rb +0 -332
  94. data/test/integration/trim_mode_test.rb +0 -529
  95. data/test/integration/variable_test.rb +0 -96
  96. data/test/test_helper.rb +0 -116
  97. data/test/unit/block_unit_test.rb +0 -58
  98. data/test/unit/condition_unit_test.rb +0 -166
  99. data/test/unit/context_unit_test.rb +0 -489
  100. data/test/unit/file_system_unit_test.rb +0 -35
  101. data/test/unit/i18n_unit_test.rb +0 -37
  102. data/test/unit/lexer_unit_test.rb +0 -51
  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 -164
  106. data/test/unit/tag_unit_test.rb +0 -21
  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 -78
  111. data/test/unit/tokenizer_unit_test.rb +0 -55
  112. data/test/unit/variable_unit_test.rb +0 -162
@@ -1,245 +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
- else
34
- template_path
35
- end
36
- end
37
- end
38
-
39
- class OtherFileSystem
40
- def read_template_file(template_path)
41
- 'from OtherFileSystem'
42
- end
43
- end
44
-
45
- class CountingFileSystem
46
- attr_reader :count
47
- def read_template_file(template_path)
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
- def test_include_tag_with
84
- assert_template_result "Product: Draft 151cm ",
85
- "{% include 'product' with products[0] %}", "products" => [ { 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' } ]
86
- end
87
-
88
- def test_include_tag_with_default_name
89
- assert_template_result "Product: Draft 151cm ",
90
- "{% include 'product' %}", "product" => { 'title' => 'Draft 151cm' }
91
- end
92
-
93
- def test_include_tag_for
94
- assert_template_result "Product: Draft 151cm Product: Element 155cm ",
95
- "{% include 'product' for products %}", "products" => [ { 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' } ]
96
- end
97
-
98
- def test_include_tag_with_local_variables
99
- assert_template_result "Locale: test123 ", "{% include 'locale_variables' echo1: 'test123' %}"
100
- end
101
-
102
- def test_include_tag_with_multiple_local_variables
103
- assert_template_result "Locale: test123 test321",
104
- "{% include 'locale_variables' echo1: 'test123', echo2: 'test321' %}"
105
- end
106
-
107
- def test_include_tag_with_multiple_local_variables_from_context
108
- assert_template_result "Locale: test123 test321",
109
- "{% include 'locale_variables' echo1: echo1, echo2: more_echos.echo2 %}",
110
- 'echo1' => 'test123', 'more_echos' => { "echo2" => 'test321' }
111
- end
112
-
113
- def test_included_templates_assigns_variables
114
- assert_template_result "bar", "{% include 'assignments' %}{{ foo }}"
115
- end
116
-
117
- def test_nested_include_tag
118
- assert_template_result "body body_detail", "{% include 'body' %}"
119
-
120
- assert_template_result "header body body_detail footer", "{% include 'nested_template' %}"
121
- end
122
-
123
- def test_nested_include_with_variable
124
- assert_template_result "Product: Draft 151cm details ",
125
- "{% include 'nested_product_template' with product %}", "product" => { "title" => 'Draft 151cm' }
126
-
127
- assert_template_result "Product: Draft 151cm details Product: Element 155cm details ",
128
- "{% include 'nested_product_template' for products %}", "products" => [{ "title" => 'Draft 151cm' }, { "title" => 'Element 155cm' }]
129
- end
130
-
131
- def test_recursively_included_template_does_not_produce_endless_loop
132
- infinite_file_system = Class.new do
133
- def read_template_file(template_path)
134
- "-{% include 'loop' %}"
135
- end
136
- end
137
-
138
- Liquid::Template.file_system = infinite_file_system.new
139
-
140
- assert_raises(Liquid::StackLevelError) do
141
- Template.parse("{% include 'loop' %}").render!
142
- end
143
- end
144
-
145
- def test_dynamically_choosen_template
146
- assert_template_result "Test123", "{% include template %}", "template" => 'Test123'
147
- assert_template_result "Test321", "{% include template %}", "template" => 'Test321'
148
-
149
- assert_template_result "Product: Draft 151cm ", "{% include template for product %}",
150
- "template" => 'product', 'product' => { 'title' => 'Draft 151cm' }
151
- end
152
-
153
- def test_include_tag_caches_second_read_of_same_partial
154
- file_system = CountingFileSystem.new
155
- assert_equal 'from CountingFileSystemfrom CountingFileSystem',
156
- Template.parse("{% include 'pick_a_source' %}{% include 'pick_a_source' %}").render!({}, registers: { file_system: file_system })
157
- assert_equal 1, file_system.count
158
- end
159
-
160
- def test_include_tag_doesnt_cache_partials_across_renders
161
- file_system = CountingFileSystem.new
162
- assert_equal 'from CountingFileSystem',
163
- Template.parse("{% include 'pick_a_source' %}").render!({}, registers: { file_system: file_system })
164
- assert_equal 1, file_system.count
165
-
166
- assert_equal 'from CountingFileSystem',
167
- Template.parse("{% include 'pick_a_source' %}").render!({}, registers: { file_system: file_system })
168
- assert_equal 2, file_system.count
169
- end
170
-
171
- def test_include_tag_within_if_statement
172
- assert_template_result "foo_if_true", "{% if true %}{% include 'foo_if_true' %}{% endif %}"
173
- end
174
-
175
- def test_custom_include_tag
176
- original_tag = Liquid::Template.tags['include']
177
- Liquid::Template.tags['include'] = CustomInclude
178
- begin
179
- assert_equal "custom_foo",
180
- Template.parse("{% include 'custom_foo' %}").render!
181
- ensure
182
- Liquid::Template.tags['include'] = original_tag
183
- end
184
- end
185
-
186
- def test_custom_include_tag_within_if_statement
187
- original_tag = Liquid::Template.tags['include']
188
- Liquid::Template.tags['include'] = CustomInclude
189
- begin
190
- assert_equal "custom_foo_if_true",
191
- Template.parse("{% if true %}{% include 'custom_foo_if_true' %}{% endif %}").render!
192
- ensure
193
- Liquid::Template.tags['include'] = original_tag
194
- end
195
- end
196
-
197
- def test_does_not_add_error_in_strict_mode_for_missing_variable
198
- Liquid::Template.file_system = TestFileSystem.new
199
-
200
- a = Liquid::Template.parse(' {% include "nested_template" %}')
201
- a.render!
202
- assert_empty a.errors
203
- end
204
-
205
- def test_passing_options_to_included_templates
206
- assert_raises(Liquid::SyntaxError) do
207
- Template.parse("{% include template %}", error_mode: :strict).render!("template" => '{{ "X" || downcase }}')
208
- end
209
- with_error_mode(:lax) do
210
- assert_equal 'x', Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: true).render!("template" => '{{ "X" || downcase }}')
211
- end
212
- assert_raises(Liquid::SyntaxError) do
213
- Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: [:locale]).render!("template" => '{{ "X" || downcase }}')
214
- end
215
- with_error_mode(:lax) do
216
- assert_equal 'x', Template.parse("{% include template %}", error_mode: :strict, include_options_blacklist: [:error_mode]).render!("template" => '{{ "X" || downcase }}')
217
- end
218
- end
219
-
220
- def test_render_raise_argument_error_when_template_is_undefined
221
- assert_raises(Liquid::ArgumentError) do
222
- template = Liquid::Template.parse('{% include undefined_variable %}')
223
- template.render!
224
- end
225
- assert_raises(Liquid::ArgumentError) do
226
- template = Liquid::Template.parse('{% include nil %}')
227
- template.render!
228
- end
229
- end
230
-
231
- def test_including_via_variable_value
232
- assert_template_result "from TestFileSystem", "{% assign page = 'pick_a_source' %}{% include page %}"
233
-
234
- assert_template_result "Product: Draft 151cm ", "{% assign page = 'product' %}{% include page %}", "product" => { 'title' => 'Draft 151cm' }
235
-
236
- assert_template_result "Product: Draft 151cm ", "{% assign page = 'product' %}{% include page for foo %}", "foo" => { 'title' => 'Draft 151cm' }
237
- end
238
-
239
- def test_including_with_strict_variables
240
- template = Liquid::Template.parse("{% include 'simple' %}", error_mode: :warn)
241
- template.render(nil, strict_variables: true)
242
-
243
- assert_equal [], template.errors
244
- end
245
- 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