liquid 3.0.6 → 4.0.0.rc1

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 (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