liquid 3.0.6 → 4.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +89 -58
  3. data/{MIT-LICENSE → LICENSE} +0 -0
  4. data/lib/liquid.rb +7 -6
  5. data/lib/liquid/block.rb +31 -124
  6. data/lib/liquid/block_body.rb +54 -57
  7. data/lib/liquid/condition.rb +23 -22
  8. data/lib/liquid/context.rb +50 -42
  9. data/lib/liquid/document.rb +19 -9
  10. data/lib/liquid/drop.rb +12 -13
  11. data/lib/liquid/errors.rb +16 -17
  12. data/lib/liquid/expression.rb +15 -3
  13. data/lib/liquid/extensions.rb +7 -7
  14. data/lib/liquid/file_system.rb +3 -3
  15. data/lib/liquid/forloop_drop.rb +42 -0
  16. data/lib/liquid/i18n.rb +5 -5
  17. data/lib/liquid/interrupts.rb +1 -2
  18. data/lib/liquid/lexer.rb +6 -4
  19. data/lib/liquid/locales/en.yml +3 -1
  20. data/lib/liquid/parse_context.rb +37 -0
  21. data/lib/liquid/parser_switching.rb +4 -4
  22. data/lib/liquid/profiler.rb +18 -19
  23. data/lib/liquid/profiler/hooks.rb +7 -7
  24. data/lib/liquid/range_lookup.rb +16 -1
  25. data/lib/liquid/resource_limits.rb +23 -0
  26. data/lib/liquid/standardfilters.rb +101 -56
  27. data/lib/liquid/strainer.rb +4 -5
  28. data/lib/liquid/tablerowloop_drop.rb +62 -0
  29. data/lib/liquid/tag.rb +9 -8
  30. data/lib/liquid/tags/assign.rb +5 -4
  31. data/lib/liquid/tags/break.rb +0 -3
  32. data/lib/liquid/tags/capture.rb +1 -1
  33. data/lib/liquid/tags/case.rb +19 -12
  34. data/lib/liquid/tags/comment.rb +2 -2
  35. data/lib/liquid/tags/cycle.rb +6 -6
  36. data/lib/liquid/tags/decrement.rb +1 -4
  37. data/lib/liquid/tags/for.rb +93 -75
  38. data/lib/liquid/tags/if.rb +49 -44
  39. data/lib/liquid/tags/ifchanged.rb +0 -2
  40. data/lib/liquid/tags/include.rb +60 -52
  41. data/lib/liquid/tags/raw.rb +26 -4
  42. data/lib/liquid/tags/table_row.rb +12 -30
  43. data/lib/liquid/tags/unless.rb +3 -4
  44. data/lib/liquid/template.rb +23 -50
  45. data/lib/liquid/tokenizer.rb +31 -0
  46. data/lib/liquid/utils.rb +48 -8
  47. data/lib/liquid/variable.rb +46 -45
  48. data/lib/liquid/variable_lookup.rb +3 -3
  49. data/lib/liquid/version.rb +1 -1
  50. data/test/integration/assign_test.rb +8 -8
  51. data/test/integration/blank_test.rb +14 -14
  52. data/test/integration/context_test.rb +2 -2
  53. data/test/integration/document_test.rb +19 -0
  54. data/test/integration/drop_test.rb +42 -40
  55. data/test/integration/error_handling_test.rb +64 -45
  56. data/test/integration/filter_test.rb +60 -20
  57. data/test/integration/output_test.rb +26 -27
  58. data/test/integration/parsing_quirks_test.rb +15 -13
  59. data/test/integration/render_profiling_test.rb +20 -20
  60. data/test/integration/security_test.rb +5 -7
  61. data/test/integration/standard_filter_test.rb +119 -37
  62. data/test/integration/tags/break_tag_test.rb +1 -2
  63. data/test/integration/tags/continue_tag_test.rb +0 -1
  64. data/test/integration/tags/for_tag_test.rb +133 -98
  65. data/test/integration/tags/if_else_tag_test.rb +75 -77
  66. data/test/integration/tags/include_tag_test.rb +23 -30
  67. data/test/integration/tags/increment_tag_test.rb +10 -11
  68. data/test/integration/tags/raw_tag_test.rb +7 -1
  69. data/test/integration/tags/standard_tag_test.rb +121 -122
  70. data/test/integration/tags/statements_test.rb +3 -5
  71. data/test/integration/tags/table_row_test.rb +20 -19
  72. data/test/integration/tags/unless_else_tag_test.rb +6 -6
  73. data/test/integration/template_test.rb +91 -45
  74. data/test/integration/variable_test.rb +23 -13
  75. data/test/test_helper.rb +33 -5
  76. data/test/unit/block_unit_test.rb +6 -5
  77. data/test/unit/condition_unit_test.rb +82 -77
  78. data/test/unit/context_unit_test.rb +48 -57
  79. data/test/unit/file_system_unit_test.rb +3 -3
  80. data/test/unit/i18n_unit_test.rb +2 -2
  81. data/test/unit/lexer_unit_test.rb +11 -8
  82. data/test/unit/parser_unit_test.rb +2 -2
  83. data/test/unit/regexp_unit_test.rb +1 -1
  84. data/test/unit/strainer_unit_test.rb +13 -2
  85. data/test/unit/tag_unit_test.rb +7 -2
  86. data/test/unit/tags/case_tag_unit_test.rb +1 -1
  87. data/test/unit/tags/for_tag_unit_test.rb +2 -2
  88. data/test/unit/tags/if_tag_unit_test.rb +1 -1
  89. data/test/unit/template_unit_test.rb +6 -5
  90. data/test/unit/tokenizer_unit_test.rb +24 -7
  91. data/test/unit/variable_unit_test.rb +60 -43
  92. metadata +44 -41
  93. data/lib/liquid/module_ex.rb +0 -62
  94. data/lib/liquid/token.rb +0 -18
  95. data/test/unit/module_ex_unit_test.rb +0 -87
@@ -37,7 +37,6 @@ class StatementsTest < Minitest::Test
37
37
  text = ' {% if null <= 0 %} true {% else %} false {% endif %} '
38
38
  assert_template_result ' false ', text
39
39
 
40
-
41
40
  text = ' {% if 0 <= null %} true {% else %} false {% endif %} '
42
41
  assert_template_result ' false ', text
43
42
  end
@@ -72,18 +71,17 @@ class StatementsTest < Minitest::Test
72
71
  assert_template_result ' true ', text, 'var' => 'hello there!'
73
72
  end
74
73
 
75
-
76
74
  def test_var_and_long_string_are_equal_backwards
77
75
  text = " {% if 'hello there!' == var %} true {% else %} false {% endif %} "
78
76
  assert_template_result ' true ', text, 'var' => 'hello there!'
79
77
  end
80
78
 
81
- #def test_is_nil
79
+ # def test_is_nil
82
80
  # text = %| {% if var != nil %} true {% else %} false {% end %} |
83
81
  # @template.assigns = { 'var' => 'hello there!'}
84
82
  # expected = %| true |
85
83
  # assert_equal expected, @template.parse(text)
86
- #end
84
+ # end
87
85
 
88
86
  def test_is_collection_empty
89
87
  text = ' {% if array == empty %} true {% else %} false {% endif %} '
@@ -92,7 +90,7 @@ class StatementsTest < Minitest::Test
92
90
 
93
91
  def test_is_not_collection_empty
94
92
  text = ' {% if array == empty %} true {% else %} false {% endif %} '
95
- assert_template_result ' false ', text, 'array' => [1,2,3]
93
+ assert_template_result ' false ', text, 'array' => [1, 2, 3]
96
94
  end
97
95
 
98
96
  def test_nil
@@ -16,48 +16,49 @@ class TableRowTest < Minitest::Test
16
16
  end
17
17
 
18
18
  def test_table_row
19
-
20
19
  assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
21
- '{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
22
- 'numbers' => [1,2,3,4,5,6])
20
+ '{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
21
+ 'numbers' => [1, 2, 3, 4, 5, 6])
23
22
 
24
23
  assert_template_result("<tr class=\"row1\">\n</tr>\n",
25
- '{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
26
- 'numbers' => [])
24
+ '{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
25
+ 'numbers' => [])
27
26
  end
28
27
 
29
28
  def test_table_row_with_different_cols
30
29
  assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td><td class=\"col4\"> 4 </td><td class=\"col5\"> 5 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 6 </td></tr>\n",
31
- '{% tablerow n in numbers cols:5%} {{n}} {% endtablerow %}',
32
- 'numbers' => [1,2,3,4,5,6])
33
-
30
+ '{% tablerow n in numbers cols:5%} {{n}} {% endtablerow %}',
31
+ 'numbers' => [1, 2, 3, 4, 5, 6])
34
32
  end
35
33
 
36
34
  def test_table_col_counter
37
35
  assert_template_result("<tr class=\"row1\">\n<td class=\"col1\">1</td><td class=\"col2\">2</td></tr>\n<tr class=\"row2\"><td class=\"col1\">1</td><td class=\"col2\">2</td></tr>\n<tr class=\"row3\"><td class=\"col1\">1</td><td class=\"col2\">2</td></tr>\n",
38
- '{% tablerow n in numbers cols:2%}{{tablerowloop.col}}{% endtablerow %}',
39
- 'numbers' => [1,2,3,4,5,6])
36
+ '{% tablerow n in numbers cols:2%}{{tablerowloop.col}}{% endtablerow %}',
37
+ 'numbers' => [1, 2, 3, 4, 5, 6])
40
38
  end
41
39
 
42
40
  def test_quoted_fragment
43
41
  assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
44
- "{% tablerow n in collections.frontpage cols:3%} {{n}} {% endtablerow %}",
45
- 'collections' => {'frontpage' => [1,2,3,4,5,6]})
42
+ "{% tablerow n in collections.frontpage cols:3%} {{n}} {% endtablerow %}",
43
+ 'collections' => { 'frontpage' => [1, 2, 3, 4, 5, 6] })
46
44
  assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
47
- "{% tablerow n in collections['frontpage'] cols:3%} {{n}} {% endtablerow %}",
48
- 'collections' => {'frontpage' => [1,2,3,4,5,6]})
49
-
45
+ "{% tablerow n in collections['frontpage'] cols:3%} {{n}} {% endtablerow %}",
46
+ 'collections' => { 'frontpage' => [1, 2, 3, 4, 5, 6] })
50
47
  end
51
48
 
52
49
  def test_enumerable_drop
53
50
  assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
54
- '{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
55
- 'numbers' => ArrayDrop.new([1,2,3,4,5,6]))
51
+ '{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
52
+ 'numbers' => ArrayDrop.new([1, 2, 3, 4, 5, 6]))
56
53
  end
57
54
 
58
55
  def test_offset_and_limit
59
56
  assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
60
- '{% tablerow n in numbers cols:3 offset:1 limit:6%} {{n}} {% endtablerow %}',
61
- 'numbers' => [0,1,2,3,4,5,6,7])
57
+ '{% tablerow n in numbers cols:3 offset:1 limit:6%} {{n}} {% endtablerow %}',
58
+ 'numbers' => [0, 1, 2, 3, 4, 5, 6, 7])
59
+ end
60
+
61
+ def test_blank_string_not_iterable
62
+ assert_template_result("<tr class=\"row1\">\n</tr>\n", "{% tablerow char in characters cols:3 %}I WILL NOT BE OUTPUT{% endtablerow %}", 'characters' => '')
62
63
  end
63
64
  end
@@ -4,16 +4,16 @@ class UnlessElseTagTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_unless
7
- assert_template_result(' ',' {% unless true %} this text should not go into the output {% endunless %} ')
7
+ assert_template_result(' ', ' {% unless true %} this text should not go into the output {% endunless %} ')
8
8
  assert_template_result(' this text should go into the output ',
9
- ' {% unless false %} this text should go into the output {% endunless %} ')
10
- assert_template_result(' you rock ?','{% unless true %} you suck {% endunless %} {% unless false %} you rock {% endunless %}?')
9
+ ' {% unless false %} this text should go into the output {% endunless %} ')
10
+ assert_template_result(' you rock ?', '{% unless true %} you suck {% endunless %} {% unless false %} you rock {% endunless %}?')
11
11
  end
12
12
 
13
13
  def test_unless_else
14
- assert_template_result(' YES ','{% unless true %} NO {% else %} YES {% endunless %}')
15
- assert_template_result(' YES ','{% unless false %} YES {% else %} NO {% endunless %}')
16
- assert_template_result(' YES ','{% unless "foo" %} NO {% else %} YES {% endunless %}')
14
+ assert_template_result(' YES ', '{% unless true %} NO {% else %} YES {% endunless %}')
15
+ assert_template_result(' YES ', '{% unless false %} YES {% else %} NO {% endunless %}')
16
+ assert_template_result(' YES ', '{% unless "foo" %} NO {% else %} YES {% endunless %}')
17
17
  end
18
18
 
19
19
  def test_unless_in_loop
@@ -1,7 +1,8 @@
1
1
  require 'test_helper'
2
+ require 'timeout'
2
3
 
3
4
  class TemplateContextDrop < Liquid::Drop
4
- def before_method(method)
5
+ def liquid_method_missing(method)
5
6
  method
6
7
  end
7
8
 
@@ -14,12 +15,10 @@ class TemplateContextDrop < Liquid::Drop
14
15
  end
15
16
  end
16
17
 
17
- class SomethingWithLength
18
+ class SomethingWithLength < Liquid::Drop
18
19
  def length
19
20
  nil
20
21
  end
21
-
22
- liquid_methods :length
23
22
  end
24
23
 
25
24
  class ErroneousDrop < Liquid::Drop
@@ -37,6 +36,16 @@ class TemplateTest < Minitest::Test
37
36
  assert_equal 'from instance assigns', t.parse("{{ foo }}").render!
38
37
  end
39
38
 
39
+ def test_warnings_is_not_exponential_time
40
+ str = "false"
41
+ 100.times do
42
+ str = "{% if true %}true{% else %}#{str}{% endif %}"
43
+ end
44
+
45
+ t = Template.parse(str)
46
+ assert_equal [], Timeout.timeout(1) { t.warnings }
47
+ end
48
+
40
49
  def test_instance_assigns_persist_on_same_template_parsing_between_renders
41
50
  t = Template.new.parse("{{ foo }}{% assign foo = 'foo' %}{{ foo }}")
42
51
  assert_equal 'foo', t.render!
@@ -64,7 +73,7 @@ class TemplateTest < Minitest::Test
64
73
 
65
74
  def test_lambda_is_called_once_from_persistent_assigns_over_multiple_parses_and_renders
66
75
  t = Template.new
67
- t.assigns['number'] = lambda { @global ||= 0; @global += 1 }
76
+ t.assigns['number'] = -> { @global ||= 0; @global += 1 }
68
77
  assert_equal '1', t.parse("{{number}}").render!
69
78
  assert_equal '1', t.parse("{{number}}").render!
70
79
  assert_equal '1', t.render!
@@ -73,7 +82,7 @@ class TemplateTest < Minitest::Test
73
82
 
74
83
  def test_lambda_is_called_once_from_custom_assigns_over_multiple_parses_and_renders
75
84
  t = Template.new
76
- assigns = {'number' => lambda { @global ||= 0; @global += 1 }}
85
+ assigns = { 'number' => -> { @global ||= 0; @global += 1 } }
77
86
  assert_equal '1', t.parse("{{number}}").render!(assigns)
78
87
  assert_equal '1', t.parse("{{number}}").render!(assigns)
79
88
  assert_equal '1', t.render!(assigns)
@@ -82,69 +91,92 @@ class TemplateTest < Minitest::Test
82
91
 
83
92
  def test_resource_limits_works_with_custom_length_method
84
93
  t = Template.parse("{% assign foo = bar %}")
85
- t.resource_limits = { :render_length_limit => 42 }
94
+ t.resource_limits.render_length_limit = 42
86
95
  assert_equal "", t.render!("bar" => SomethingWithLength.new)
87
96
  end
88
97
 
89
98
  def test_resource_limits_render_length
90
99
  t = Template.parse("0123456789")
91
- t.resource_limits = { :render_length_limit => 5 }
92
- assert_equal "Liquid error: Memory limits exceeded", t.render()
93
- assert t.resource_limits[:reached]
94
- t.resource_limits = { :render_length_limit => 10 }
95
- assert_equal "0123456789", t.render!()
96
- refute_nil t.resource_limits[:render_length_current]
100
+ t.resource_limits.render_length_limit = 5
101
+ assert_equal "Liquid error: Memory limits exceeded", t.render
102
+ assert t.resource_limits.reached?
103
+
104
+ t.resource_limits.render_length_limit = 10
105
+ assert_equal "0123456789", t.render!
106
+ refute_nil t.resource_limits.render_length
97
107
  end
98
108
 
99
109
  def test_resource_limits_render_score
100
110
  t = Template.parse("{% for a in (1..10) %} {% for a in (1..10) %} foo {% endfor %} {% endfor %}")
101
- t.resource_limits = { :render_score_limit => 50 }
102
- assert_equal "Liquid error: Memory limits exceeded", t.render()
103
- assert t.resource_limits[:reached]
111
+ t.resource_limits.render_score_limit = 50
112
+ assert_equal "Liquid error: Memory limits exceeded", t.render
113
+ assert t.resource_limits.reached?
114
+
104
115
  t = Template.parse("{% for a in (1..100) %} foo {% endfor %}")
105
- t.resource_limits = { :render_score_limit => 50 }
106
- assert_equal "Liquid error: Memory limits exceeded", t.render()
107
- assert t.resource_limits[:reached]
108
- t.resource_limits = { :render_score_limit => 200 }
109
- assert_equal (" foo " * 100), t.render!()
110
- refute_nil t.resource_limits[:render_score_current]
116
+ t.resource_limits.render_score_limit = 50
117
+ assert_equal "Liquid error: Memory limits exceeded", t.render
118
+ assert t.resource_limits.reached?
119
+
120
+ t.resource_limits.render_score_limit = 200
121
+ assert_equal (" foo " * 100), t.render!
122
+ refute_nil t.resource_limits.render_score
111
123
  end
112
124
 
113
125
  def test_resource_limits_assign_score
114
126
  t = Template.parse("{% assign foo = 42 %}{% assign bar = 23 %}")
115
- t.resource_limits = { :assign_score_limit => 1 }
116
- assert_equal "Liquid error: Memory limits exceeded", t.render()
117
- assert t.resource_limits[:reached]
118
- t.resource_limits = { :assign_score_limit => 2 }
119
- assert_equal "", t.render!()
120
- refute_nil t.resource_limits[:assign_score_current]
127
+ t.resource_limits.assign_score_limit = 1
128
+ assert_equal "Liquid error: Memory limits exceeded", t.render
129
+ assert t.resource_limits.reached?
130
+
131
+ t.resource_limits.assign_score_limit = 2
132
+ assert_equal "", t.render!
133
+ refute_nil t.resource_limits.assign_score
121
134
  end
122
135
 
123
136
  def test_resource_limits_aborts_rendering_after_first_error
124
137
  t = Template.parse("{% for a in (1..100) %} foo1 {% endfor %} bar {% for a in (1..100) %} foo2 {% endfor %}")
125
- t.resource_limits = { :render_score_limit => 50 }
126
- assert_equal "Liquid error: Memory limits exceeded", t.render()
127
- assert t.resource_limits[:reached]
138
+ t.resource_limits.render_score_limit = 50
139
+ assert_equal "Liquid error: Memory limits exceeded", t.render
140
+ assert t.resource_limits.reached?
128
141
  end
129
142
 
130
143
  def test_resource_limits_hash_in_template_gets_updated_even_if_no_limits_are_set
131
144
  t = Template.parse("{% for a in (1..100) %} {% assign foo = 1 %} {% endfor %}")
132
- t.render!()
133
- assert t.resource_limits[:assign_score_current] > 0
134
- assert t.resource_limits[:render_score_current] > 0
135
- assert t.resource_limits[:render_length_current] > 0
145
+ t.render!
146
+ assert t.resource_limits.assign_score > 0
147
+ assert t.resource_limits.render_score > 0
148
+ assert t.resource_limits.render_length > 0
149
+ end
150
+
151
+ def test_render_length_persists_between_blocks
152
+ t = Template.parse("{% if true %}aaaa{% endif %}")
153
+ t.resource_limits.render_length_limit = 7
154
+ assert_equal "Liquid error: Memory limits exceeded", t.render
155
+ t.resource_limits.render_length_limit = 8
156
+ assert_equal "aaaa", t.render
157
+
158
+ t = Template.parse("{% if true %}aaaa{% endif %}{% if true %}bbb{% endif %}")
159
+ t.resource_limits.render_length_limit = 13
160
+ assert_equal "Liquid error: Memory limits exceeded", t.render
161
+ t.resource_limits.render_length_limit = 14
162
+ assert_equal "aaaabbb", t.render
163
+
164
+ t = Template.parse("{% if true %}a{% endif %}{% if true %}b{% endif %}{% if true %}a{% endif %}{% if true %}b{% endif %}{% if true %}a{% endif %}{% if true %}b{% endif %}")
165
+ t.resource_limits.render_length_limit = 5
166
+ assert_equal "Liquid error: Memory limits exceeded", t.render
167
+ t.resource_limits.render_length_limit = 11
168
+ assert_equal "Liquid error: Memory limits exceeded", t.render
169
+ t.resource_limits.render_length_limit = 12
170
+ assert_equal "ababab", t.render
136
171
  end
137
172
 
138
173
  def test_default_resource_limits_unaffected_by_render_with_context
139
174
  context = Context.new
140
175
  t = Template.parse("{% for a in (1..100) %} {% assign foo = 1 %} {% endfor %}")
141
176
  t.render!(context)
142
- assert context.resource_limits[:assign_score_current] > 0
143
- assert context.resource_limits[:render_score_current] > 0
144
- assert context.resource_limits[:render_length_current] > 0
145
- refute Template.default_resource_limits.key?(:assign_score_current)
146
- refute Template.default_resource_limits.key?(:render_score_current)
147
- refute Template.default_resource_limits.key?(:render_length_current)
177
+ assert context.resource_limits.assign_score > 0
178
+ assert context.resource_limits.render_score > 0
179
+ assert context.resource_limits.render_length > 0
148
180
  end
149
181
 
150
182
  def test_can_use_drop_as_context
@@ -157,7 +189,7 @@ class TemplateTest < Minitest::Test
157
189
  end
158
190
 
159
191
  def test_render_bang_force_rethrow_errors_on_passed_context
160
- context = Context.new({'drop' => ErroneousDrop.new})
192
+ context = Context.new({ 'drop' => ErroneousDrop.new })
161
193
  t = Template.new.parse('{{ drop.bad_method }}')
162
194
 
163
195
  e = assert_raises RuntimeError do
@@ -169,14 +201,28 @@ class TemplateTest < Minitest::Test
169
201
  def test_exception_handler_doesnt_reraise_if_it_returns_false
170
202
  exception = nil
171
203
  Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_handler: ->(e) { exception = e; false })
172
- assert exception.is_a?(ZeroDivisionError)
204
+ assert exception.is_a?(Liquid::ZeroDivisionError)
173
205
  end
174
206
 
175
207
  def test_exception_handler_does_reraise_if_it_returns_true
176
208
  exception = nil
177
- assert_raises(ZeroDivisionError) do
209
+ assert_raises(Liquid::ZeroDivisionError) do
178
210
  Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_handler: ->(e) { exception = e; true })
179
211
  end
180
- assert exception.is_a?(ZeroDivisionError)
212
+ assert exception.is_a?(Liquid::ZeroDivisionError)
213
+ end
214
+
215
+ def test_global_filter_option_on_render
216
+ global_filter_proc = ->(output) { "#{output} filtered" }
217
+ rendered_template = Template.parse("{{name}}").render({ "name" => "bob" }, global_filter: global_filter_proc)
218
+
219
+ assert_equal 'bob filtered', rendered_template
220
+ end
221
+
222
+ def test_global_filter_option_when_native_filters_exist
223
+ global_filter_proc = ->(output) { "#{output} filtered" }
224
+ rendered_template = Template.parse("{{name | upcase}}").render({ "name" => "bob" }, global_filter: global_filter_proc)
225
+
226
+ assert_equal 'BOB filtered', rendered_template
181
227
  end
182
228
  end
@@ -4,7 +4,7 @@ class VariableTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
6
  def test_simple_variable
7
- template = Template.parse(%|{{test}}|)
7
+ template = Template.parse(%({{test}}))
8
8
  assert_equal 'worked', template.render!('test' => 'worked')
9
9
  assert_equal 'worked wonderfully', template.render!('test' => 'worked wonderfully')
10
10
  end
@@ -14,19 +14,29 @@ class VariableTest < Minitest::Test
14
14
  end
15
15
 
16
16
  def test_simple_with_whitespaces
17
- template = Template.parse(%| {{ test }} |)
17
+ template = Template.parse(%( {{ test }} ))
18
18
  assert_equal ' worked ', template.render!('test' => 'worked')
19
19
  assert_equal ' worked wonderfully ', template.render!('test' => 'worked wonderfully')
20
20
  end
21
21
 
22
22
  def test_ignore_unknown
23
- template = Template.parse(%|{{ test }}|)
23
+ template = Template.parse(%({{ test }}))
24
+ assert_equal '', template.render!
25
+ end
26
+
27
+ def test_using_blank_as_variable_name
28
+ template = Template.parse("{% assign foo = blank %}{{ foo }}")
29
+ assert_equal '', template.render!
30
+ end
31
+
32
+ def test_using_empty_as_variable_name
33
+ template = Template.parse("{% assign foo = empty %}{{ foo }}")
24
34
  assert_equal '', template.render!
25
35
  end
26
36
 
27
37
  def test_hash_scoping
28
- template = Template.parse(%|{{ test.test }}|)
29
- assert_equal 'worked', template.render!('test' => {'test' => 'worked'})
38
+ template = Template.parse(%({{ test.test }}))
39
+ assert_equal 'worked', template.render!('test' => { 'test' => 'worked' })
30
40
  end
31
41
 
32
42
  def test_false_renders_as_false
@@ -40,23 +50,23 @@ class VariableTest < Minitest::Test
40
50
  end
41
51
 
42
52
  def test_preset_assigns
43
- template = Template.parse(%|{{ test }}|)
53
+ template = Template.parse(%({{ test }}))
44
54
  template.assigns['test'] = 'worked'
45
55
  assert_equal 'worked', template.render!
46
56
  end
47
57
 
48
58
  def test_reuse_parsed_template
49
- template = Template.parse(%|{{ greeting }} {{ name }}|)
59
+ template = Template.parse(%({{ greeting }} {{ name }}))
50
60
  template.assigns['greeting'] = 'Goodbye'
51
61
  assert_equal 'Hello Tobi', template.render!('greeting' => 'Hello', 'name' => 'Tobi')
52
62
  assert_equal 'Hello ', template.render!('greeting' => 'Hello', 'unknown' => 'Tobi')
53
63
  assert_equal 'Hello Brian', template.render!('greeting' => 'Hello', 'name' => 'Brian')
54
64
  assert_equal 'Goodbye Brian', template.render!('name' => 'Brian')
55
- assert_equal({'greeting'=>'Goodbye'}, template.assigns)
65
+ assert_equal({ 'greeting' => 'Goodbye' }, template.assigns)
56
66
  end
57
67
 
58
68
  def test_assigns_not_polluted_from_template
59
- template = Template.parse(%|{{ test }}{% assign test = 'bar' %}{{ test }}|)
69
+ template = Template.parse(%({{ test }}{% assign test = 'bar' %}{{ test }}))
60
70
  template.assigns['test'] = 'baz'
61
71
  assert_equal 'bazbar', template.render!
62
72
  assert_equal 'bazbar', template.render!
@@ -65,14 +75,14 @@ class VariableTest < Minitest::Test
65
75
  end
66
76
 
67
77
  def test_hash_with_default_proc
68
- template = Template.parse(%|Hello {{ test }}|)
69
- assigns = Hash.new { |h,k| raise "Unknown variable '#{k}'" }
78
+ template = Template.parse(%(Hello {{ test }}))
79
+ assigns = Hash.new { |h, k| raise "Unknown variable '#{k}'" }
70
80
  assigns['test'] = 'Tobi'
71
81
  assert_equal 'Hello Tobi', template.render!(assigns)
72
82
  assigns.delete('test')
73
- e = assert_raises(RuntimeError) {
83
+ e = assert_raises(RuntimeError) do
74
84
  template.render!(assigns)
75
- }
85
+ end
76
86
  assert_equal "Unknown variable 'test'", e.message
77
87
  end
78
88
 
@@ -4,8 +4,9 @@ ENV["MT_NO_EXPECTATIONS"] = "1"
4
4
  require 'minitest/autorun'
5
5
  require 'spy/integration'
6
6
 
7
- $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
7
+ $LOAD_PATH.unshift(File.join(File.expand_path(__dir__), '..', 'lib'))
8
8
  require 'liquid.rb'
9
+ require 'liquid/profiler'
9
10
 
10
11
  mode = :strict
11
12
  if env_mode = ENV['LIQUID_PARSER_MODE']
@@ -14,6 +15,11 @@ if env_mode = ENV['LIQUID_PARSER_MODE']
14
15
  end
15
16
  Liquid::Template.error_mode = mode
16
17
 
18
+ if ENV['LIQUID-C'] == '1'
19
+ puts "-- LIQUID C"
20
+ require 'liquid/c'
21
+ end
22
+
17
23
  if Minitest.const_defined?('Test')
18
24
  # We're on Minitest 5+. Nothing to do here.
19
25
  else
@@ -24,7 +30,7 @@ end
24
30
  module Minitest
25
31
  class Test
26
32
  def fixture(name)
27
- File.join(File.expand_path(File.dirname(__FILE__)), "fixtures", name)
33
+ File.join(File.expand_path(__dir__), "fixtures", name)
28
34
  end
29
35
  end
30
36
 
@@ -41,10 +47,10 @@ module Minitest
41
47
  assert_match expected, Template.parse(template).render!(assigns), message
42
48
  end
43
49
 
44
- def assert_match_syntax_error(match, template, registers = {})
45
- exception = assert_raises(Liquid::SyntaxError) {
50
+ def assert_match_syntax_error(match, template, assigns = {})
51
+ exception = assert_raises(Liquid::SyntaxError) do
46
52
  Template.parse(template).render(assigns)
47
- }
53
+ end
48
54
  assert_match match, exception.message
49
55
  end
50
56
 
@@ -87,3 +93,25 @@ class ThingWithToLiquid
87
93
  'foobar'
88
94
  end
89
95
  end
96
+
97
+ class ErrorDrop < Liquid::Drop
98
+ def standard_error
99
+ raise Liquid::StandardError, 'standard error'
100
+ end
101
+
102
+ def argument_error
103
+ raise Liquid::ArgumentError, 'argument error'
104
+ end
105
+
106
+ def syntax_error
107
+ raise Liquid::SyntaxError, 'syntax error'
108
+ end
109
+
110
+ def runtime_error
111
+ raise 'runtime error'
112
+ end
113
+
114
+ def exception
115
+ raise Exception, 'exception'
116
+ end
117
+ end