liquid 3.0.6 → 4.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +154 -58
  3. data/{MIT-LICENSE → LICENSE} +0 -0
  4. data/README.md +33 -0
  5. data/lib/liquid/block.rb +42 -125
  6. data/lib/liquid/block_body.rb +99 -79
  7. data/lib/liquid/condition.rb +52 -32
  8. data/lib/liquid/context.rb +57 -51
  9. data/lib/liquid/document.rb +19 -9
  10. data/lib/liquid/drop.rb +17 -16
  11. data/lib/liquid/errors.rb +20 -24
  12. data/lib/liquid/expression.rb +26 -10
  13. data/lib/liquid/extensions.rb +19 -7
  14. data/lib/liquid/file_system.rb +11 -11
  15. data/lib/liquid/forloop_drop.rb +42 -0
  16. data/lib/liquid/i18n.rb +6 -6
  17. data/lib/liquid/interrupts.rb +1 -2
  18. data/lib/liquid/lexer.rb +12 -8
  19. data/lib/liquid/locales/en.yml +6 -2
  20. data/lib/liquid/parse_context.rb +38 -0
  21. data/lib/liquid/parse_tree_visitor.rb +42 -0
  22. data/lib/liquid/parser_switching.rb +4 -4
  23. data/lib/liquid/profiler/hooks.rb +7 -7
  24. data/lib/liquid/profiler.rb +18 -19
  25. data/lib/liquid/range_lookup.rb +16 -1
  26. data/lib/liquid/resource_limits.rb +23 -0
  27. data/lib/liquid/standardfilters.rb +207 -61
  28. data/lib/liquid/strainer.rb +15 -8
  29. data/lib/liquid/tablerowloop_drop.rb +62 -0
  30. data/lib/liquid/tag.rb +9 -8
  31. data/lib/liquid/tags/assign.rb +25 -4
  32. data/lib/liquid/tags/break.rb +0 -3
  33. data/lib/liquid/tags/capture.rb +1 -1
  34. data/lib/liquid/tags/case.rb +27 -12
  35. data/lib/liquid/tags/comment.rb +2 -2
  36. data/lib/liquid/tags/cycle.rb +16 -8
  37. data/lib/liquid/tags/decrement.rb +1 -4
  38. data/lib/liquid/tags/for.rb +103 -75
  39. data/lib/liquid/tags/if.rb +60 -44
  40. data/lib/liquid/tags/ifchanged.rb +0 -2
  41. data/lib/liquid/tags/include.rb +71 -51
  42. data/lib/liquid/tags/raw.rb +32 -4
  43. data/lib/liquid/tags/table_row.rb +21 -31
  44. data/lib/liquid/tags/unless.rb +3 -4
  45. data/lib/liquid/template.rb +42 -54
  46. data/lib/liquid/tokenizer.rb +31 -0
  47. data/lib/liquid/truffle.rb +5 -0
  48. data/lib/liquid/utils.rb +52 -8
  49. data/lib/liquid/variable.rb +59 -46
  50. data/lib/liquid/variable_lookup.rb +14 -6
  51. data/lib/liquid/version.rb +2 -1
  52. data/lib/liquid.rb +10 -7
  53. data/test/integration/assign_test.rb +8 -8
  54. data/test/integration/blank_test.rb +14 -14
  55. data/test/integration/block_test.rb +12 -0
  56. data/test/integration/context_test.rb +2 -2
  57. data/test/integration/document_test.rb +19 -0
  58. data/test/integration/drop_test.rb +42 -40
  59. data/test/integration/error_handling_test.rb +96 -43
  60. data/test/integration/filter_test.rb +60 -20
  61. data/test/integration/hash_ordering_test.rb +9 -9
  62. data/test/integration/output_test.rb +26 -27
  63. data/test/integration/parse_tree_visitor_test.rb +247 -0
  64. data/test/integration/parsing_quirks_test.rb +19 -13
  65. data/test/integration/render_profiling_test.rb +20 -20
  66. data/test/integration/security_test.rb +23 -7
  67. data/test/integration/standard_filter_test.rb +426 -46
  68. data/test/integration/tags/break_tag_test.rb +1 -2
  69. data/test/integration/tags/continue_tag_test.rb +0 -1
  70. data/test/integration/tags/for_tag_test.rb +135 -100
  71. data/test/integration/tags/if_else_tag_test.rb +75 -77
  72. data/test/integration/tags/include_tag_test.rb +50 -31
  73. data/test/integration/tags/increment_tag_test.rb +10 -11
  74. data/test/integration/tags/raw_tag_test.rb +7 -1
  75. data/test/integration/tags/standard_tag_test.rb +121 -122
  76. data/test/integration/tags/statements_test.rb +3 -5
  77. data/test/integration/tags/table_row_test.rb +20 -19
  78. data/test/integration/tags/unless_else_tag_test.rb +6 -6
  79. data/test/integration/template_test.rb +199 -49
  80. data/test/integration/trim_mode_test.rb +529 -0
  81. data/test/integration/variable_test.rb +27 -13
  82. data/test/test_helper.rb +33 -6
  83. data/test/truffle/truffle_test.rb +9 -0
  84. data/test/unit/block_unit_test.rb +8 -5
  85. data/test/unit/condition_unit_test.rb +94 -77
  86. data/test/unit/context_unit_test.rb +69 -72
  87. data/test/unit/file_system_unit_test.rb +3 -3
  88. data/test/unit/i18n_unit_test.rb +2 -2
  89. data/test/unit/lexer_unit_test.rb +12 -9
  90. data/test/unit/parser_unit_test.rb +2 -2
  91. data/test/unit/regexp_unit_test.rb +1 -1
  92. data/test/unit/strainer_unit_test.rb +96 -1
  93. data/test/unit/tag_unit_test.rb +7 -2
  94. data/test/unit/tags/case_tag_unit_test.rb +1 -1
  95. data/test/unit/tags/for_tag_unit_test.rb +2 -2
  96. data/test/unit/tags/if_tag_unit_test.rb +1 -1
  97. data/test/unit/template_unit_test.rb +14 -5
  98. data/test/unit/tokenizer_unit_test.rb +24 -7
  99. data/test/unit/variable_unit_test.rb +60 -43
  100. metadata +62 -50
  101. data/lib/liquid/module_ex.rb +0 -62
  102. data/lib/liquid/token.rb +0 -18
  103. data/test/unit/module_ex_unit_test.rb +0 -87
@@ -6,11 +6,10 @@ class BreakTagTest < Minitest::Test
6
6
  # tests that no weird errors are raised if break is called outside of a
7
7
  # block
8
8
  def test_break_with_no_block
9
- assigns = {'i' => 1}
9
+ assigns = { 'i' => 1 }
10
10
  markup = '{% break %}'
11
11
  expected = ''
12
12
 
13
13
  assert_template_result(expected, markup, assigns)
14
14
  end
15
-
16
15
  end
@@ -12,5 +12,4 @@ class ContinueTagTest < Minitest::Test
12
12
 
13
13
  assert_template_result(expected, markup, assigns)
14
14
  end
15
-
16
15
  end
@@ -10,10 +10,10 @@ class ForTagTest < Minitest::Test
10
10
  include Liquid
11
11
 
12
12
  def test_for
13
- assert_template_result(' yo yo yo yo ','{%for item in array%} yo {%endfor%}','array' => [1,2,3,4])
14
- assert_template_result('yoyo','{%for item in array%}yo{%endfor%}','array' => [1,2])
15
- assert_template_result(' yo ','{%for item in array%} yo {%endfor%}','array' => [1])
16
- assert_template_result('','{%for item in array%}{%endfor%}','array' => [1,2])
13
+ assert_template_result(' yo yo yo yo ', '{%for item in array%} yo {%endfor%}', 'array' => [1, 2, 3, 4])
14
+ assert_template_result('yoyo', '{%for item in array%}yo{%endfor%}', 'array' => [1, 2])
15
+ assert_template_result(' yo ', '{%for item in array%} yo {%endfor%}', 'array' => [1])
16
+ assert_template_result('', '{%for item in array%}{%endfor%}', 'array' => [1, 2])
17
17
  expected = <<HERE
18
18
 
19
19
  yo
@@ -28,46 +28,52 @@ HERE
28
28
  yo
29
29
  {%endfor%}
30
30
  HERE
31
- assert_template_result(expected,template,'array' => [1,2,3])
31
+ assert_template_result(expected, template, 'array' => [1, 2, 3])
32
32
  end
33
33
 
34
34
  def test_for_reversed
35
- assigns = {'array' => [ 1, 2, 3] }
36
- assert_template_result('321','{%for item in array reversed %}{{item}}{%endfor%}',assigns)
35
+ assigns = { 'array' => [ 1, 2, 3] }
36
+ assert_template_result('321', '{%for item in array reversed %}{{item}}{%endfor%}', assigns)
37
37
  end
38
38
 
39
39
  def test_for_with_range
40
- assert_template_result(' 1 2 3 ','{%for item in (1..3) %} {{item}} {%endfor%}')
40
+ assert_template_result(' 1 2 3 ', '{%for item in (1..3) %} {{item}} {%endfor%}')
41
+
42
+ assert_raises(Liquid::ArgumentError) do
43
+ Template.parse('{% for i in (a..2) %}{% endfor %}').render!("a" => [1, 2])
44
+ end
45
+
46
+ assert_template_result(' 0 1 2 3 ', '{% for item in (a..3) %} {{item}} {% endfor %}', "a" => "invalid integer")
41
47
  end
42
48
 
43
49
  def test_for_with_variable_range
44
- assert_template_result(' 1 2 3 ','{%for item in (1..foobar) %} {{item}} {%endfor%}', "foobar" => 3)
50
+ assert_template_result(' 1 2 3 ', '{%for item in (1..foobar) %} {{item}} {%endfor%}', "foobar" => 3)
45
51
  end
46
52
 
47
53
  def test_for_with_hash_value_range
48
54
  foobar = { "value" => 3 }
49
- assert_template_result(' 1 2 3 ','{%for item in (1..foobar.value) %} {{item}} {%endfor%}', "foobar" => foobar)
55
+ assert_template_result(' 1 2 3 ', '{%for item in (1..foobar.value) %} {{item}} {%endfor%}', "foobar" => foobar)
50
56
  end
51
57
 
52
58
  def test_for_with_drop_value_range
53
59
  foobar = ThingWithValue.new
54
- assert_template_result(' 1 2 3 ','{%for item in (1..foobar.value) %} {{item}} {%endfor%}', "foobar" => foobar)
60
+ assert_template_result(' 1 2 3 ', '{%for item in (1..foobar.value) %} {{item}} {%endfor%}', "foobar" => foobar)
55
61
  end
56
62
 
57
63
  def test_for_with_variable
58
- assert_template_result(' 1 2 3 ','{%for item in array%} {{item}} {%endfor%}','array' => [1,2,3])
59
- assert_template_result('123','{%for item in array%}{{item}}{%endfor%}','array' => [1,2,3])
60
- assert_template_result('123','{% for item in array %}{{item}}{% endfor %}','array' => [1,2,3])
61
- assert_template_result('abcd','{%for item in array%}{{item}}{%endfor%}','array' => ['a','b','c','d'])
62
- assert_template_result('a b c','{%for item in array%}{{item}}{%endfor%}','array' => ['a',' ','b',' ','c'])
63
- assert_template_result('abc','{%for item in array%}{{item}}{%endfor%}','array' => ['a','','b','','c'])
64
+ assert_template_result(' 1 2 3 ', '{%for item in array%} {{item}} {%endfor%}', 'array' => [1, 2, 3])
65
+ assert_template_result('123', '{%for item in array%}{{item}}{%endfor%}', 'array' => [1, 2, 3])
66
+ assert_template_result('123', '{% for item in array %}{{item}}{% endfor %}', 'array' => [1, 2, 3])
67
+ assert_template_result('abcd', '{%for item in array%}{{item}}{%endfor%}', 'array' => ['a', 'b', 'c', 'd'])
68
+ assert_template_result('a b c', '{%for item in array%}{{item}}{%endfor%}', 'array' => ['a', ' ', 'b', ' ', 'c'])
69
+ assert_template_result('abc', '{%for item in array%}{{item}}{%endfor%}', 'array' => ['a', '', 'b', '', 'c'])
64
70
  end
65
71
 
66
72
  def test_for_helpers
67
- assigns = {'array' => [1,2,3] }
73
+ assigns = { 'array' => [1, 2, 3] }
68
74
  assert_template_result(' 1/3 2/3 3/3 ',
69
- '{%for item in array%} {{forloop.index}}/{{forloop.length}} {%endfor%}',
70
- assigns)
75
+ '{%for item in array%} {{forloop.index}}/{{forloop.length}} {%endfor%}',
76
+ assigns)
71
77
  assert_template_result(' 1 2 3 ', '{%for item in array%} {{forloop.index}} {%endfor%}', assigns)
72
78
  assert_template_result(' 0 1 2 ', '{%for item in array%} {{forloop.index0}} {%endfor%}', assigns)
73
79
  assert_template_result(' 2 1 0 ', '{%for item in array%} {{forloop.rindex0}} {%endfor%}', assigns)
@@ -77,20 +83,20 @@ HERE
77
83
  end
78
84
 
79
85
  def test_for_and_if
80
- assigns = {'array' => [1,2,3] }
86
+ assigns = { 'array' => [1, 2, 3] }
81
87
  assert_template_result('+--',
82
- '{%for item in array%}{% if forloop.first %}+{% else %}-{% endif %}{%endfor%}',
83
- assigns)
88
+ '{%for item in array%}{% if forloop.first %}+{% else %}-{% endif %}{%endfor%}',
89
+ assigns)
84
90
  end
85
91
 
86
92
  def test_for_else
87
- assert_template_result('+++', '{%for item in array%}+{%else%}-{%endfor%}', 'array'=>[1,2,3])
88
- assert_template_result('-', '{%for item in array%}+{%else%}-{%endfor%}', 'array'=>[])
89
- assert_template_result('-', '{%for item in array%}+{%else%}-{%endfor%}', 'array'=>nil)
93
+ assert_template_result('+++', '{%for item in array%}+{%else%}-{%endfor%}', 'array' => [1, 2, 3])
94
+ assert_template_result('-', '{%for item in array%}+{%else%}-{%endfor%}', 'array' => [])
95
+ assert_template_result('-', '{%for item in array%}+{%else%}-{%endfor%}', 'array' => nil)
90
96
  end
91
97
 
92
98
  def test_limiting
93
- assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
99
+ assigns = { 'array' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] }
94
100
  assert_template_result('12', '{%for i in array limit:2 %}{{ i }}{%endfor%}', assigns)
95
101
  assert_template_result('1234', '{%for i in array limit:4 %}{{ i }}{%endfor%}', assigns)
96
102
  assert_template_result('3456', '{%for i in array limit:4 offset:2 %}{{ i }}{%endfor%}', assigns)
@@ -98,7 +104,7 @@ HERE
98
104
  end
99
105
 
100
106
  def test_dynamic_variable_limiting
101
- assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
107
+ assigns = { 'array' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] }
102
108
  assigns['limit'] = 2
103
109
  assigns['offset'] = 2
104
110
 
@@ -106,17 +112,17 @@ HERE
106
112
  end
107
113
 
108
114
  def test_nested_for
109
- assigns = {'array' => [[1,2],[3,4],[5,6]] }
115
+ assigns = { 'array' => [[1, 2], [3, 4], [5, 6]] }
110
116
  assert_template_result('123456', '{%for item in array%}{%for i in item%}{{ i }}{%endfor%}{%endfor%}', assigns)
111
117
  end
112
118
 
113
119
  def test_offset_only
114
- assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
120
+ assigns = { 'array' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] }
115
121
  assert_template_result('890', '{%for i in array offset:7 %}{{ i }}{%endfor%}', assigns)
116
122
  end
117
123
 
118
124
  def test_pause_resume
119
- assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
125
+ assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] } }
120
126
  markup = <<-MKUP
121
127
  {%for i in array.items limit: 3 %}{{i}}{%endfor%}
122
128
  next
@@ -131,11 +137,11 @@ HERE
131
137
  next
132
138
  789
133
139
  XPCTD
134
- assert_template_result(expected,markup,assigns)
140
+ assert_template_result(expected, markup, assigns)
135
141
  end
136
142
 
137
143
  def test_pause_resume_limit
138
- assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
144
+ assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] } }
139
145
  markup = <<-MKUP
140
146
  {%for i in array.items limit:3 %}{{i}}{%endfor%}
141
147
  next
@@ -150,11 +156,11 @@ HERE
150
156
  next
151
157
  7
152
158
  XPCTD
153
- assert_template_result(expected,markup,assigns)
159
+ assert_template_result(expected, markup, assigns)
154
160
  end
155
161
 
156
- def test_pause_resume_BIG_limit
157
- assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
162
+ def test_pause_resume_big_limit
163
+ assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] } }
158
164
  markup = <<-MKUP
159
165
  {%for i in array.items limit:3 %}{{i}}{%endfor%}
160
166
  next
@@ -169,103 +175,102 @@ HERE
169
175
  next
170
176
  7890
171
177
  XPCTD
172
- assert_template_result(expected,markup,assigns)
178
+ assert_template_result(expected, markup, assigns)
173
179
  end
174
180
 
175
-
176
- def test_pause_resume_BIG_offset
177
- assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
178
- markup = %q({%for i in array.items limit:3 %}{{i}}{%endfor%}
181
+ def test_pause_resume_big_offset
182
+ assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] } }
183
+ markup = '{%for i in array.items limit:3 %}{{i}}{%endfor%}
179
184
  next
180
185
  {%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
181
186
  next
182
- {%for i in array.items offset:continue limit:3 offset:1000 %}{{i}}{%endfor%})
183
- expected = %q(123
187
+ {%for i in array.items offset:continue limit:3 offset:1000 %}{{i}}{%endfor%}'
188
+ expected = '123
184
189
  next
185
190
  456
186
191
  next
187
- )
188
- assert_template_result(expected,markup,assigns)
192
+ '
193
+ assert_template_result(expected, markup, assigns)
189
194
  end
190
195
 
191
196
  def test_for_with_break
192
- assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,10]}}
197
+ assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] } }
193
198
 
194
199
  markup = '{% for i in array.items %}{% break %}{% endfor %}'
195
200
  expected = ""
196
- assert_template_result(expected,markup,assigns)
201
+ assert_template_result(expected, markup, assigns)
197
202
 
198
203
  markup = '{% for i in array.items %}{{ i }}{% break %}{% endfor %}'
199
204
  expected = "1"
200
- assert_template_result(expected,markup,assigns)
205
+ assert_template_result(expected, markup, assigns)
201
206
 
202
207
  markup = '{% for i in array.items %}{% break %}{{ i }}{% endfor %}'
203
208
  expected = ""
204
- assert_template_result(expected,markup,assigns)
209
+ assert_template_result(expected, markup, assigns)
205
210
 
206
211
  markup = '{% for i in array.items %}{{ i }}{% if i > 3 %}{% break %}{% endif %}{% endfor %}'
207
212
  expected = "1234"
208
- assert_template_result(expected,markup,assigns)
213
+ assert_template_result(expected, markup, assigns)
209
214
 
210
215
  # tests to ensure it only breaks out of the local for loop
211
216
  # and not all of them.
212
- assigns = {'array' => [[1,2],[3,4],[5,6]] }
213
- markup = '{% for item in array %}' +
214
- '{% for i in item %}' +
215
- '{% if i == 1 %}' +
216
- '{% break %}' +
217
- '{% endif %}' +
218
- '{{ i }}' +
219
- '{% endfor %}' +
217
+ assigns = { 'array' => [[1, 2], [3, 4], [5, 6]] }
218
+ markup = '{% for item in array %}' \
219
+ '{% for i in item %}' \
220
+ '{% if i == 1 %}' \
221
+ '{% break %}' \
222
+ '{% endif %}' \
223
+ '{{ i }}' \
224
+ '{% endfor %}' \
220
225
  '{% endfor %}'
221
226
  expected = '3456'
222
227
  assert_template_result(expected, markup, assigns)
223
228
 
224
229
  # test break does nothing when unreached
225
- assigns = {'array' => {'items' => [1,2,3,4,5]}}
230
+ assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5] } }
226
231
  markup = '{% for i in array.items %}{% if i == 9999 %}{% break %}{% endif %}{{ i }}{% endfor %}'
227
232
  expected = '12345'
228
233
  assert_template_result(expected, markup, assigns)
229
234
  end
230
235
 
231
236
  def test_for_with_continue
232
- assigns = {'array' => {'items' => [1,2,3,4,5]}}
237
+ assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5] } }
233
238
 
234
239
  markup = '{% for i in array.items %}{% continue %}{% endfor %}'
235
240
  expected = ""
236
- assert_template_result(expected,markup,assigns)
241
+ assert_template_result(expected, markup, assigns)
237
242
 
238
243
  markup = '{% for i in array.items %}{{ i }}{% continue %}{% endfor %}'
239
244
  expected = "12345"
240
- assert_template_result(expected,markup,assigns)
245
+ assert_template_result(expected, markup, assigns)
241
246
 
242
247
  markup = '{% for i in array.items %}{% continue %}{{ i }}{% endfor %}'
243
248
  expected = ""
244
- assert_template_result(expected,markup,assigns)
249
+ assert_template_result(expected, markup, assigns)
245
250
 
246
251
  markup = '{% for i in array.items %}{% if i > 3 %}{% continue %}{% endif %}{{ i }}{% endfor %}'
247
252
  expected = "123"
248
- assert_template_result(expected,markup,assigns)
253
+ assert_template_result(expected, markup, assigns)
249
254
 
250
255
  markup = '{% for i in array.items %}{% if i == 3 %}{% continue %}{% else %}{{ i }}{% endif %}{% endfor %}'
251
256
  expected = "1245"
252
- assert_template_result(expected,markup,assigns)
257
+ assert_template_result(expected, markup, assigns)
253
258
 
254
259
  # tests to ensure it only continues the local for loop and not all of them.
255
- assigns = {'array' => [[1,2],[3,4],[5,6]] }
256
- markup = '{% for item in array %}' +
257
- '{% for i in item %}' +
258
- '{% if i == 1 %}' +
259
- '{% continue %}' +
260
- '{% endif %}' +
261
- '{{ i }}' +
262
- '{% endfor %}' +
260
+ assigns = { 'array' => [[1, 2], [3, 4], [5, 6]] }
261
+ markup = '{% for item in array %}' \
262
+ '{% for i in item %}' \
263
+ '{% if i == 1 %}' \
264
+ '{% continue %}' \
265
+ '{% endif %}' \
266
+ '{{ i }}' \
267
+ '{% endfor %}' \
263
268
  '{% endfor %}'
264
269
  expected = '23456'
265
270
  assert_template_result(expected, markup, assigns)
266
271
 
267
272
  # test continue does nothing when unreached
268
- assigns = {'array' => {'items' => [1,2,3,4,5]}}
273
+ assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5] } }
269
274
  markup = '{% for i in array.items %}{% if i == 9999 %}{% continue %}{% endif %}{{ i }}{% endfor %}'
270
275
  expected = '12345'
271
276
  assert_template_result(expected, markup, assigns)
@@ -277,25 +282,45 @@ HERE
277
282
  # the functionality for backwards compatibility
278
283
 
279
284
  assert_template_result('test string',
280
- '{%for val in string%}{{val}}{%endfor%}',
281
- 'string' => "test string")
285
+ '{%for val in string%}{{val}}{%endfor%}',
286
+ 'string' => "test string")
282
287
 
283
288
  assert_template_result('test string',
284
- '{%for val in string limit:1%}{{val}}{%endfor%}',
285
- 'string' => "test string")
289
+ '{%for val in string limit:1%}{{val}}{%endfor%}',
290
+ 'string' => "test string")
286
291
 
287
292
  assert_template_result('val-string-1-1-0-1-0-true-true-test string',
288
- '{%for val in string%}' +
289
- '{{forloop.name}}-' +
290
- '{{forloop.index}}-' +
291
- '{{forloop.length}}-' +
292
- '{{forloop.index0}}-' +
293
- '{{forloop.rindex}}-' +
294
- '{{forloop.rindex0}}-' +
295
- '{{forloop.first}}-' +
296
- '{{forloop.last}}-' +
297
- '{{val}}{%endfor%}',
298
- 'string' => "test string")
293
+ '{%for val in string%}' \
294
+ '{{forloop.name}}-' \
295
+ '{{forloop.index}}-' \
296
+ '{{forloop.length}}-' \
297
+ '{{forloop.index0}}-' \
298
+ '{{forloop.rindex}}-' \
299
+ '{{forloop.rindex0}}-' \
300
+ '{{forloop.first}}-' \
301
+ '{{forloop.last}}-' \
302
+ '{{val}}{%endfor%}',
303
+ 'string' => "test string")
304
+ end
305
+
306
+ def test_for_parentloop_references_parent_loop
307
+ assert_template_result('1.1 1.2 1.3 2.1 2.2 2.3 ',
308
+ '{% for inner in outer %}{% for k in inner %}' \
309
+ '{{ forloop.parentloop.index }}.{{ forloop.index }} ' \
310
+ '{% endfor %}{% endfor %}',
311
+ 'outer' => [[1, 1, 1], [1, 1, 1]])
312
+ end
313
+
314
+ def test_for_parentloop_nil_when_not_present
315
+ assert_template_result('.1 .2 ',
316
+ '{% for inner in outer %}' \
317
+ '{{ forloop.parentloop.index }}.{{ forloop.index }} ' \
318
+ '{% endfor %}',
319
+ 'outer' => [[1, 1, 1], [1, 1, 1]])
320
+ end
321
+
322
+ def test_inner_for_over_empty_input
323
+ assert_template_result 'oo', '{% for a in (1..2) %}o{% for b in empty %}{% endfor %}{% endfor %}'
299
324
  end
300
325
 
301
326
  def test_blank_string_not_iterable
@@ -311,7 +336,7 @@ HERE
311
336
  def test_spacing_with_variable_naming_in_for_loop
312
337
  expected = '12345'
313
338
  template = '{% for item in items %}{{item}}{% endfor %}'
314
- assigns = {'items' => [1,2,3,4,5]}
339
+ assigns = { 'items' => [1, 2, 3, 4, 5] }
315
340
  assert_template_result(expected, template, assigns)
316
341
  end
317
342
 
@@ -329,13 +354,13 @@ HERE
329
354
 
330
355
  def load_slice(from, to)
331
356
  @load_slice_called = true
332
- @data[(from..to-1)]
357
+ @data[(from..to - 1)]
333
358
  end
334
359
  end
335
360
 
336
361
  def test_iterate_with_each_when_no_limit_applied
337
- loader = LoaderDrop.new([1,2,3,4,5])
338
- assigns = {'items' => loader}
362
+ loader = LoaderDrop.new([1, 2, 3, 4, 5])
363
+ assigns = { 'items' => loader }
339
364
  expected = '12345'
340
365
  template = '{% for item in items %}{{item}}{% endfor %}'
341
366
  assert_template_result(expected, template, assigns)
@@ -344,8 +369,8 @@ HERE
344
369
  end
345
370
 
346
371
  def test_iterate_with_load_slice_when_limit_applied
347
- loader = LoaderDrop.new([1,2,3,4,5])
348
- assigns = {'items' => loader}
372
+ loader = LoaderDrop.new([1, 2, 3, 4, 5])
373
+ assigns = { 'items' => loader }
349
374
  expected = '1'
350
375
  template = '{% for item in items limit:1 %}{{item}}{% endfor %}'
351
376
  assert_template_result(expected, template, assigns)
@@ -354,8 +379,8 @@ HERE
354
379
  end
355
380
 
356
381
  def test_iterate_with_load_slice_when_limit_and_offset_applied
357
- loader = LoaderDrop.new([1,2,3,4,5])
358
- assigns = {'items' => loader}
382
+ loader = LoaderDrop.new([1, 2, 3, 4, 5])
383
+ assigns = { 'items' => loader }
359
384
  expected = '34'
360
385
  template = '{% for item in items offset:2 limit:2 %}{{item}}{% endfor %}'
361
386
  assert_template_result(expected, template, assigns)
@@ -364,12 +389,22 @@ HERE
364
389
  end
365
390
 
366
391
  def test_iterate_with_load_slice_returns_same_results_as_without
367
- loader = LoaderDrop.new([1,2,3,4,5])
368
- loader_assigns = {'items' => loader}
369
- array_assigns = {'items' => [1,2,3,4,5]}
392
+ loader = LoaderDrop.new([1, 2, 3, 4, 5])
393
+ loader_assigns = { 'items' => loader }
394
+ array_assigns = { 'items' => [1, 2, 3, 4, 5] }
370
395
  expected = '34'
371
396
  template = '{% for item in items offset:2 limit:2 %}{{item}}{% endfor %}'
372
397
  assert_template_result(expected, template, loader_assigns)
373
398
  assert_template_result(expected, template, array_assigns)
374
399
  end
400
+
401
+ def test_for_cleans_up_registers
402
+ context = Context.new(ErrorDrop.new)
403
+
404
+ assert_raises(StandardError) do
405
+ Liquid::Template.parse('{% for i in (1..2) %}{{ standard_error }}{% endfor %}').render!(context)
406
+ end
407
+
408
+ assert context.registers[:for_stack].empty?
409
+ end
375
410
  end