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
@@ -14,7 +14,7 @@ module FunnyFilter
14
14
  end
15
15
 
16
16
  def add_tag(input, tag = "p", id = "foo")
17
- %|<#{tag} id="#{id}">#{input}</#{tag}>|
17
+ %(<#{tag} id="#{id}">#{input}</#{tag}>)
18
18
  end
19
19
 
20
20
  def paragraph(input)
@@ -22,9 +22,8 @@ module FunnyFilter
22
22
  end
23
23
 
24
24
  def link_to(name, url)
25
- %|<a href="#{url}">#{name}</a>|
25
+ %(<a href="#{url}">#{name}</a>)
26
26
  end
27
-
28
27
  end
29
28
 
30
29
  class OutputTest < Minitest::Test
@@ -33,14 +32,14 @@ class OutputTest < Minitest::Test
33
32
  def setup
34
33
  @assigns = {
35
34
  'best_cars' => 'bmw',
36
- 'car' => {'bmw' => 'good', 'gm' => 'bad'}
37
- }
35
+ 'car' => { 'bmw' => 'good', 'gm' => 'bad' }
36
+ }
38
37
  end
39
38
 
40
39
  def test_variable
41
- text = %| {{best_cars}} |
40
+ text = %( {{best_cars}} )
42
41
 
43
- expected = %| bmw |
42
+ expected = %( bmw )
44
43
  assert_equal expected, Template.parse(text).render!(@assigns)
45
44
  end
46
45
 
@@ -53,72 +52,72 @@ class OutputTest < Minitest::Test
53
52
  end
54
53
 
55
54
  def test_variable_traversing
56
- text = %| {{car.bmw}} {{car.gm}} {{car.bmw}} |
55
+ text = %( {{car.bmw}} {{car.gm}} {{car.bmw}} )
57
56
 
58
- expected = %| good bad good |
57
+ expected = %( good bad good )
59
58
  assert_equal expected, Template.parse(text).render!(@assigns)
60
59
  end
61
60
 
62
61
  def test_variable_piping
63
62
  text = %( {{ car.gm | make_funny }} )
64
- expected = %| LOL |
63
+ expected = %( LOL )
65
64
 
66
- assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
65
+ assert_equal expected, Template.parse(text).render!(@assigns, filters: [FunnyFilter])
67
66
  end
68
67
 
69
68
  def test_variable_piping_with_input
70
69
  text = %( {{ car.gm | cite_funny }} )
71
- expected = %| LOL: bad |
70
+ expected = %( LOL: bad )
72
71
 
73
- assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
72
+ assert_equal expected, Template.parse(text).render!(@assigns, filters: [FunnyFilter])
74
73
  end
75
74
 
76
75
  def test_variable_piping_with_args
77
76
  text = %! {{ car.gm | add_smiley : ':-(' }} !
78
77
  expected = %| bad :-( |
79
78
 
80
- assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
79
+ assert_equal expected, Template.parse(text).render!(@assigns, filters: [FunnyFilter])
81
80
  end
82
81
 
83
82
  def test_variable_piping_with_no_args
84
- text = %! {{ car.gm | add_smiley }} !
83
+ text = %( {{ car.gm | add_smiley }} )
85
84
  expected = %| bad :-) |
86
85
 
87
- assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
86
+ assert_equal expected, Template.parse(text).render!(@assigns, filters: [FunnyFilter])
88
87
  end
89
88
 
90
89
  def test_multiple_variable_piping_with_args
91
90
  text = %! {{ car.gm | add_smiley : ':-(' | add_smiley : ':-('}} !
92
91
  expected = %| bad :-( :-( |
93
92
 
94
- assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
93
+ assert_equal expected, Template.parse(text).render!(@assigns, filters: [FunnyFilter])
95
94
  end
96
95
 
97
96
  def test_variable_piping_with_multiple_args
98
- text = %! {{ car.gm | add_tag : 'span', 'bar'}} !
99
- expected = %| <span id="bar">bad</span> |
97
+ text = %( {{ car.gm | add_tag : 'span', 'bar'}} )
98
+ expected = %( <span id="bar">bad</span> )
100
99
 
101
- assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
100
+ assert_equal expected, Template.parse(text).render!(@assigns, filters: [FunnyFilter])
102
101
  end
103
102
 
104
103
  def test_variable_piping_with_variable_args
105
- text = %! {{ car.gm | add_tag : 'span', car.bmw}} !
106
- expected = %| <span id="good">bad</span> |
104
+ text = %( {{ car.gm | add_tag : 'span', car.bmw}} )
105
+ expected = %( <span id="good">bad</span> )
107
106
 
108
- assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
107
+ assert_equal expected, Template.parse(text).render!(@assigns, filters: [FunnyFilter])
109
108
  end
110
109
 
111
110
  def test_multiple_pipings
112
111
  text = %( {{ best_cars | cite_funny | paragraph }} )
113
- expected = %| <p>LOL: bmw</p> |
112
+ expected = %( <p>LOL: bmw</p> )
114
113
 
115
- assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
114
+ assert_equal expected, Template.parse(text).render!(@assigns, filters: [FunnyFilter])
116
115
  end
117
116
 
118
117
  def test_link_to
119
118
  text = %( {{ 'Typo' | link_to: 'http://typo.leetsoft.com' }} )
120
- expected = %| <a href="http://typo.leetsoft.com">Typo</a> |
119
+ expected = %( <a href="http://typo.leetsoft.com">Typo</a> )
121
120
 
122
- assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
121
+ assert_equal expected, Template.parse(text).render!(@assigns, filters: [FunnyFilter])
123
122
  end
124
123
  end # OutputTest
@@ -0,0 +1,247 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class ParseTreeVisitorTest < Minitest::Test
6
+ include Liquid
7
+
8
+ def test_variable
9
+ assert_equal(
10
+ ["test"],
11
+ visit(%({{ test }}))
12
+ )
13
+ end
14
+
15
+ def test_varible_with_filter
16
+ assert_equal(
17
+ ["test", "infilter"],
18
+ visit(%({{ test | split: infilter }}))
19
+ )
20
+ end
21
+
22
+ def test_dynamic_variable
23
+ assert_equal(
24
+ ["test", "inlookup"],
25
+ visit(%({{ test[inlookup] }}))
26
+ )
27
+ end
28
+
29
+ def test_if_condition
30
+ assert_equal(
31
+ ["test"],
32
+ visit(%({% if test %}{% endif %}))
33
+ )
34
+ end
35
+
36
+ def test_complex_if_condition
37
+ assert_equal(
38
+ ["test"],
39
+ visit(%({% if 1 == 1 and 2 == test %}{% endif %}))
40
+ )
41
+ end
42
+
43
+ def test_if_body
44
+ assert_equal(
45
+ ["test"],
46
+ visit(%({% if 1 == 1 %}{{ test }}{% endif %}))
47
+ )
48
+ end
49
+
50
+ def test_unless_condition
51
+ assert_equal(
52
+ ["test"],
53
+ visit(%({% unless test %}{% endunless %}))
54
+ )
55
+ end
56
+
57
+ def test_complex_unless_condition
58
+ assert_equal(
59
+ ["test"],
60
+ visit(%({% unless 1 == 1 and 2 == test %}{% endunless %}))
61
+ )
62
+ end
63
+
64
+ def test_unless_body
65
+ assert_equal(
66
+ ["test"],
67
+ visit(%({% unless 1 == 1 %}{{ test }}{% endunless %}))
68
+ )
69
+ end
70
+
71
+ def test_elsif_condition
72
+ assert_equal(
73
+ ["test"],
74
+ visit(%({% if 1 == 1 %}{% elsif test %}{% endif %}))
75
+ )
76
+ end
77
+
78
+ def test_complex_elsif_condition
79
+ assert_equal(
80
+ ["test"],
81
+ visit(%({% if 1 == 1 %}{% elsif 1 == 1 and 2 == test %}{% endif %}))
82
+ )
83
+ end
84
+
85
+ def test_elsif_body
86
+ assert_equal(
87
+ ["test"],
88
+ visit(%({% if 1 == 1 %}{% elsif 2 == 2 %}{{ test }}{% endif %}))
89
+ )
90
+ end
91
+
92
+ def test_else_body
93
+ assert_equal(
94
+ ["test"],
95
+ visit(%({% if 1 == 1 %}{% else %}{{ test }}{% endif %}))
96
+ )
97
+ end
98
+
99
+ def test_case_left
100
+ assert_equal(
101
+ ["test"],
102
+ visit(%({% case test %}{% endcase %}))
103
+ )
104
+ end
105
+
106
+ def test_case_condition
107
+ assert_equal(
108
+ ["test"],
109
+ visit(%({% case 1 %}{% when test %}{% endcase %}))
110
+ )
111
+ end
112
+
113
+ def test_case_when_body
114
+ assert_equal(
115
+ ["test"],
116
+ visit(%({% case 1 %}{% when 2 %}{{ test }}{% endcase %}))
117
+ )
118
+ end
119
+
120
+ def test_case_else_body
121
+ assert_equal(
122
+ ["test"],
123
+ visit(%({% case 1 %}{% else %}{{ test }}{% endcase %}))
124
+ )
125
+ end
126
+
127
+ def test_for_in
128
+ assert_equal(
129
+ ["test"],
130
+ visit(%({% for x in test %}{% endfor %}))
131
+ )
132
+ end
133
+
134
+ def test_for_limit
135
+ assert_equal(
136
+ ["test"],
137
+ visit(%({% for x in (1..5) limit: test %}{% endfor %}))
138
+ )
139
+ end
140
+
141
+ def test_for_offset
142
+ assert_equal(
143
+ ["test"],
144
+ visit(%({% for x in (1..5) offset: test %}{% endfor %}))
145
+ )
146
+ end
147
+
148
+ def test_for_body
149
+ assert_equal(
150
+ ["test"],
151
+ visit(%({% for x in (1..5) %}{{ test }}{% endfor %}))
152
+ )
153
+ end
154
+
155
+ def test_tablerow_in
156
+ assert_equal(
157
+ ["test"],
158
+ visit(%({% tablerow x in test %}{% endtablerow %}))
159
+ )
160
+ end
161
+
162
+ def test_tablerow_limit
163
+ assert_equal(
164
+ ["test"],
165
+ visit(%({% tablerow x in (1..5) limit: test %}{% endtablerow %}))
166
+ )
167
+ end
168
+
169
+ def test_tablerow_offset
170
+ assert_equal(
171
+ ["test"],
172
+ visit(%({% tablerow x in (1..5) offset: test %}{% endtablerow %}))
173
+ )
174
+ end
175
+
176
+ def test_tablerow_body
177
+ assert_equal(
178
+ ["test"],
179
+ visit(%({% tablerow x in (1..5) %}{{ test }}{% endtablerow %}))
180
+ )
181
+ end
182
+
183
+ def test_cycle
184
+ assert_equal(
185
+ ["test"],
186
+ visit(%({% cycle test %}))
187
+ )
188
+ end
189
+
190
+ def test_assign
191
+ assert_equal(
192
+ ["test"],
193
+ visit(%({% assign x = test %}))
194
+ )
195
+ end
196
+
197
+ def test_capture
198
+ assert_equal(
199
+ ["test"],
200
+ visit(%({% capture x %}{{ test }}{% endcapture %}))
201
+ )
202
+ end
203
+
204
+ def test_include
205
+ assert_equal(
206
+ ["test"],
207
+ visit(%({% include test %}))
208
+ )
209
+ end
210
+
211
+ def test_include_with
212
+ assert_equal(
213
+ ["test"],
214
+ visit(%({% include "hai" with test %}))
215
+ )
216
+ end
217
+
218
+ def test_include_for
219
+ assert_equal(
220
+ ["test"],
221
+ visit(%({% include "hai" for test %}))
222
+ )
223
+ end
224
+
225
+ def test_preserve_tree_structure
226
+ assert_equal(
227
+ [[nil, [
228
+ [nil, [[nil, [["other", []]]]]],
229
+ ["test", []],
230
+ ["xs", []]
231
+ ]]],
232
+ traversal(%({% for x in xs offset: test %}{{ other }}{% endfor %})).visit
233
+ )
234
+ end
235
+
236
+ private
237
+
238
+ def traversal(template)
239
+ ParseTreeVisitor
240
+ .for(Template.parse(template).root)
241
+ .add_callback_for(VariableLookup, &:name)
242
+ end
243
+
244
+ def visit(template)
245
+ traversal(template).visit.flatten.compact
246
+ end
247
+ end
@@ -28,11 +28,14 @@ class ParsingQuirksTest < Minitest::Test
28
28
 
29
29
  def test_error_on_empty_filter
30
30
  assert Template.parse("{{test}}")
31
- assert Template.parse("{{|test}}")
31
+
32
+ with_error_mode(:lax) do
33
+ assert Template.parse("{{|test}}")
34
+ end
35
+
32
36
  with_error_mode(:strict) do
33
- assert_raises(SyntaxError) do
34
- Template.parse("{{test |a|b|}}")
35
- end
37
+ assert_raises(SyntaxError) { Template.parse("{{|test}}") }
38
+ assert_raises(SyntaxError) { Template.parse("{{test |a|b|}}") }
36
39
  end
37
40
  end
38
41
 
@@ -59,25 +62,25 @@ class ParsingQuirksTest < Minitest::Test
59
62
  end
60
63
 
61
64
  def test_no_error_on_lax_empty_filter
62
- assert Template.parse("{{test |a|b|}}", :error_mode => :lax)
63
- assert Template.parse("{{test}}", :error_mode => :lax)
64
- assert Template.parse("{{|test|}}", :error_mode => :lax)
65
+ assert Template.parse("{{test |a|b|}}", error_mode: :lax)
66
+ assert Template.parse("{{test}}", error_mode: :lax)
67
+ assert Template.parse("{{|test|}}", error_mode: :lax)
65
68
  end
66
69
 
67
70
  def test_meaningless_parens_lax
68
71
  with_error_mode(:lax) do
69
- assigns = {'b' => 'bar', 'c' => 'baz'}
72
+ assigns = { 'b' => 'bar', 'c' => 'baz' }
70
73
  markup = "a == 'foo' or (b == 'bar' and c == 'baz') or false"
71
- assert_template_result(' YES ',"{% if #{markup} %} YES {% endif %}", assigns)
74
+ assert_template_result(' YES ', "{% if #{markup} %} YES {% endif %}", assigns)
72
75
  end
73
76
  end
74
77
 
75
78
  def test_unexpected_characters_silently_eat_logic_lax
76
79
  with_error_mode(:lax) do
77
80
  markup = "true && false"
78
- assert_template_result(' YES ',"{% if #{markup} %} YES {% endif %}")
81
+ assert_template_result(' YES ', "{% if #{markup} %} YES {% endif %}")
79
82
  markup = "false || true"
80
- assert_template_result('',"{% if #{markup} %} YES {% endif %}")
83
+ assert_template_result('', "{% if #{markup} %} YES {% endif %}")
81
84
  end
82
85
  end
83
86
 
@@ -89,14 +92,14 @@ class ParsingQuirksTest < Minitest::Test
89
92
 
90
93
  def test_unanchored_filter_arguments
91
94
  with_error_mode(:lax) do
92
- assert_template_result('hi',"{{ 'hi there' | split$$$:' ' | first }}")
95
+ assert_template_result('hi', "{{ 'hi there' | split$$$:' ' | first }}")
93
96
 
94
97
  assert_template_result('x', "{{ 'X' | downcase) }}")
95
98
 
96
99
  # After the messed up quotes a filter without parameters (reverse) should work
97
100
  # but one with parameters (remove) shouldn't be detected.
98
101
  assert_template_result('here', "{{ 'hi there' | split:\"t\"\" | reverse | first}}")
99
- assert_template_result('hi ', "{{ 'hi there' | split:\"t\"\" | remove:\"i\" | first}}")
102
+ assert_template_result('hi ', "{{ 'hi there' | split:\"t\"\" | remove:\"i\" | first}}")
100
103
  end
101
104
  end
102
105
 
@@ -113,4 +116,7 @@ class ParsingQuirksTest < Minitest::Test
113
116
  end
114
117
  end
115
118
 
119
+ def test_contains_in_id
120
+ assert_template_result(' YES ', '{% if containsallshipments == true %} YES {% endif %}', 'containsallshipments' => true)
121
+ end
116
122
  end # ParsingQuirksTest
@@ -4,7 +4,7 @@ class RenderProfilingTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  class ProfilingFileSystem
7
- def read_template_file(template_path, context)
7
+ def read_template_file(template_path)
8
8
  "Rendering template {% assign template_name = '#{template_path}'%}\n{{ template_name }}"
9
9
  end
10
10
  end
@@ -21,7 +21,7 @@ class RenderProfilingTest < Minitest::Test
21
21
  end
22
22
 
23
23
  def test_parse_makes_available_simple_profiling
24
- t = Template.parse("{{ 'a string' | upcase }}", :profile => true)
24
+ t = Template.parse("{{ 'a string' | upcase }}", profile: true)
25
25
  t.render!
26
26
 
27
27
  assert_equal 1, t.profiler.length
@@ -31,14 +31,14 @@ class RenderProfilingTest < Minitest::Test
31
31
  end
32
32
 
33
33
  def test_render_ignores_raw_strings_when_profiling
34
- t = Template.parse("This is raw string\nstuff\nNewline", :profile => true)
34
+ t = Template.parse("This is raw string\nstuff\nNewline", profile: true)
35
35
  t.render!
36
36
 
37
37
  assert_equal 0, t.profiler.length
38
38
  end
39
39
 
40
40
  def test_profiling_includes_line_numbers_of_liquid_nodes
41
- t = Template.parse("{{ 'a string' | upcase }}\n{% increment test %}", :profile => true)
41
+ t = Template.parse("{{ 'a string' | upcase }}\n{% increment test %}", profile: true)
42
42
  t.render!
43
43
  assert_equal 2, t.profiler.length
44
44
 
@@ -49,7 +49,7 @@ class RenderProfilingTest < Minitest::Test
49
49
  end
50
50
 
51
51
  def test_profiling_includes_line_numbers_of_included_partials
52
- t = Template.parse("{% include 'a_template' %}", :profile => true)
52
+ t = Template.parse("{% include 'a_template' %}", profile: true)
53
53
  t.render!
54
54
 
55
55
  included_children = t.profiler[0].children
@@ -61,7 +61,7 @@ class RenderProfilingTest < Minitest::Test
61
61
  end
62
62
 
63
63
  def test_profiling_times_the_rendering_of_tokens
64
- t = Template.parse("{% include 'a_template' %}", :profile => true)
64
+ t = Template.parse("{% include 'a_template' %}", profile: true)
65
65
  t.render!
66
66
 
67
67
  node = t.profiler[0]
@@ -69,14 +69,14 @@ class RenderProfilingTest < Minitest::Test
69
69
  end
70
70
 
71
71
  def test_profiling_times_the_entire_render
72
- t = Template.parse("{% include 'a_template' %}", :profile => true)
72
+ t = Template.parse("{% include 'a_template' %}", profile: true)
73
73
  t.render!
74
74
 
75
75
  assert t.profiler.total_render_time >= 0, "Total render time was not calculated"
76
76
  end
77
77
 
78
78
  def test_profiling_uses_include_to_mark_children
79
- t = Template.parse("{{ 'a string' | upcase }}\n{% include 'a_template' %}", :profile => true)
79
+ t = Template.parse("{{ 'a string' | upcase }}\n{% include 'a_template' %}", profile: true)
80
80
  t.render!
81
81
 
82
82
  include_node = t.profiler[1]
@@ -84,47 +84,47 @@ class RenderProfilingTest < Minitest::Test
84
84
  end
85
85
 
86
86
  def test_profiling_marks_children_with_the_name_of_included_partial
87
- t = Template.parse("{{ 'a string' | upcase }}\n{% include 'a_template' %}", :profile => true)
87
+ t = Template.parse("{{ 'a string' | upcase }}\n{% include 'a_template' %}", profile: true)
88
88
  t.render!
89
89
 
90
90
  include_node = t.profiler[1]
91
91
  include_node.children.each do |child|
92
- assert_equal "'a_template'", child.partial
92
+ assert_equal "a_template", child.partial
93
93
  end
94
94
  end
95
95
 
96
96
  def test_profiling_supports_multiple_templates
97
- t = Template.parse("{{ 'a string' | upcase }}\n{% include 'a_template' %}\n{% include 'b_template' %}", :profile => true)
97
+ t = Template.parse("{{ 'a string' | upcase }}\n{% include 'a_template' %}\n{% include 'b_template' %}", profile: true)
98
98
  t.render!
99
99
 
100
100
  a_template = t.profiler[1]
101
101
  a_template.children.each do |child|
102
- assert_equal "'a_template'", child.partial
102
+ assert_equal "a_template", child.partial
103
103
  end
104
104
 
105
105
  b_template = t.profiler[2]
106
106
  b_template.children.each do |child|
107
- assert_equal "'b_template'", child.partial
107
+ assert_equal "b_template", child.partial
108
108
  end
109
109
  end
110
110
 
111
111
  def test_profiling_supports_rendering_the_same_partial_multiple_times
112
- t = Template.parse("{{ 'a string' | upcase }}\n{% include 'a_template' %}\n{% include 'a_template' %}", :profile => true)
112
+ t = Template.parse("{{ 'a string' | upcase }}\n{% include 'a_template' %}\n{% include 'a_template' %}", profile: true)
113
113
  t.render!
114
114
 
115
115
  a_template1 = t.profiler[1]
116
116
  a_template1.children.each do |child|
117
- assert_equal "'a_template'", child.partial
117
+ assert_equal "a_template", child.partial
118
118
  end
119
119
 
120
120
  a_template2 = t.profiler[2]
121
121
  a_template2.children.each do |child|
122
- assert_equal "'a_template'", child.partial
122
+ assert_equal "a_template", child.partial
123
123
  end
124
124
  end
125
125
 
126
126
  def test_can_iterate_over_each_profiling_entry
127
- t = Template.parse("{{ 'a string' | upcase }}\n{% increment test %}", :profile => true)
127
+ t = Template.parse("{{ 'a string' | upcase }}\n{% increment test %}", profile: true)
128
128
  t.render!
129
129
 
130
130
  timing_count = 0
@@ -136,7 +136,7 @@ class RenderProfilingTest < Minitest::Test
136
136
  end
137
137
 
138
138
  def test_profiling_marks_children_of_if_blocks
139
- t = Template.parse("{% if true %} {% increment test %} {{ test }} {% endif %}", :profile => true)
139
+ t = Template.parse("{% if true %} {% increment test %} {{ test }} {% endif %}", profile: true)
140
140
  t.render!
141
141
 
142
142
  assert_equal 1, t.profiler.length
@@ -144,8 +144,8 @@ class RenderProfilingTest < Minitest::Test
144
144
  end
145
145
 
146
146
  def test_profiling_marks_children_of_for_blocks
147
- t = Template.parse("{% for item in collection %} {{ item }} {% endfor %}", :profile => true)
148
- t.render!({"collection" => ["one", "two"]})
147
+ t = Template.parse("{% for item in collection %} {{ item }} {% endfor %}", profile: true)
148
+ t.render!({ "collection" => ["one", "two"] })
149
149
 
150
150
  assert_equal 1, t.profiler.length
151
151
  # Will profile each invocation of the for block
@@ -9,34 +9,36 @@ end
9
9
  class SecurityTest < Minitest::Test
10
10
  include Liquid
11
11
 
12
+ def setup
13
+ @assigns = {}
14
+ end
15
+
12
16
  def test_no_instance_eval
13
17
  text = %( {{ '1+1' | instance_eval }} )
14
- expected = %| 1+1 |
18
+ expected = %( 1+1 )
15
19
 
16
20
  assert_equal expected, Template.parse(text).render!(@assigns)
17
21
  end
18
22
 
19
23
  def test_no_existing_instance_eval
20
24
  text = %( {{ '1+1' | __instance_eval__ }} )
21
- expected = %| 1+1 |
25
+ expected = %( 1+1 )
22
26
 
23
27
  assert_equal expected, Template.parse(text).render!(@assigns)
24
28
  end
25
29
 
26
-
27
30
  def test_no_instance_eval_after_mixing_in_new_filter
28
31
  text = %( {{ '1+1' | instance_eval }} )
29
- expected = %| 1+1 |
32
+ expected = %( 1+1 )
30
33
 
31
34
  assert_equal expected, Template.parse(text).render!(@assigns)
32
35
  end
33
36
 
34
-
35
37
  def test_no_instance_eval_later_in_chain
36
38
  text = %( {{ '1+1' | add_one | instance_eval }} )
37
- expected = %| 1+1 + 1 |
39
+ expected = %( 1+1 + 1 )
38
40
 
39
- assert_equal expected, Template.parse(text).render!(@assigns, :filters => SecurityFilter)
41
+ assert_equal expected, Template.parse(text).render!(@assigns, filters: SecurityFilter)
40
42
  end
41
43
 
42
44
  def test_does_not_add_filters_to_symbol_table
@@ -61,4 +63,18 @@ class SecurityTest < Minitest::Test
61
63
 
62
64
  assert_equal [], (Symbol.all_symbols - current_symbols)
63
65
  end
66
+
67
+ def test_max_depth_nested_blocks_does_not_raise_exception
68
+ depth = Liquid::Block::MAX_DEPTH
69
+ code = "{% if true %}" * depth + "rendered" + "{% endif %}" * depth
70
+ assert_equal "rendered", Template.parse(code).render!
71
+ end
72
+
73
+ def test_more_than_max_depth_nested_blocks_raises_exception
74
+ depth = Liquid::Block::MAX_DEPTH + 1
75
+ code = "{% if true %}" * depth + "rendered" + "{% endif %}" * depth
76
+ assert_raises(Liquid::StackLevelError) do
77
+ Template.parse(code).render!
78
+ end
79
+ end
64
80
  end # SecurityTest