liquid 5.1.0 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.md +35 -0
- data/README.md +4 -4
- data/lib/liquid/block_body.rb +6 -6
- data/lib/liquid/condition.rb +7 -1
- data/lib/liquid/context.rb +6 -2
- data/lib/liquid/expression.rb +11 -10
- data/lib/liquid/forloop_drop.rb +44 -1
- data/lib/liquid/locales/en.yml +6 -5
- data/lib/liquid/partial_cache.rb +3 -3
- data/lib/liquid/registers.rb +51 -0
- data/lib/liquid/standardfilters.rb +463 -75
- data/lib/liquid/strainer_factory.rb +15 -10
- data/lib/liquid/strainer_template.rb +9 -0
- data/lib/liquid/tablerowloop_drop.rb +58 -1
- data/lib/liquid/tags/assign.rb +12 -8
- data/lib/liquid/tags/break.rb +8 -0
- data/lib/liquid/tags/capture.rb +13 -10
- data/lib/liquid/tags/case.rb +21 -0
- data/lib/liquid/tags/comment.rb +13 -0
- data/lib/liquid/tags/continue.rb +8 -9
- data/lib/liquid/tags/cycle.rb +12 -11
- data/lib/liquid/tags/decrement.rb +16 -17
- data/lib/liquid/tags/echo.rb +16 -9
- data/lib/liquid/tags/for.rb +22 -43
- data/lib/liquid/tags/if.rb +11 -9
- data/lib/liquid/tags/include.rb +15 -13
- data/lib/liquid/tags/increment.rb +16 -14
- data/lib/liquid/tags/inline_comment.rb +43 -0
- data/lib/liquid/tags/raw.rb +11 -0
- data/lib/liquid/tags/render.rb +29 -4
- data/lib/liquid/tags/table_row.rb +22 -0
- data/lib/liquid/tags/unless.rb +15 -4
- data/lib/liquid/template.rb +2 -3
- data/lib/liquid/variable.rb +4 -4
- data/lib/liquid/variable_lookup.rb +10 -7
- data/lib/liquid/version.rb +1 -1
- data/lib/liquid.rb +4 -4
- metadata +7 -121
- data/lib/liquid/register.rb +0 -6
- data/lib/liquid/static_registers.rb +0 -44
- data/test/fixtures/en_locale.yml +0 -9
- data/test/integration/assign_test.rb +0 -117
- data/test/integration/blank_test.rb +0 -109
- data/test/integration/block_test.rb +0 -58
- data/test/integration/capture_test.rb +0 -58
- data/test/integration/context_test.rb +0 -636
- data/test/integration/document_test.rb +0 -21
- data/test/integration/drop_test.rb +0 -257
- data/test/integration/error_handling_test.rb +0 -272
- data/test/integration/expression_test.rb +0 -46
- data/test/integration/filter_test.rb +0 -189
- data/test/integration/hash_ordering_test.rb +0 -25
- data/test/integration/output_test.rb +0 -125
- data/test/integration/parsing_quirks_test.rb +0 -134
- data/test/integration/profiler_test.rb +0 -213
- data/test/integration/security_test.rb +0 -89
- data/test/integration/standard_filter_test.rb +0 -880
- data/test/integration/tag/disableable_test.rb +0 -59
- data/test/integration/tag_test.rb +0 -45
- data/test/integration/tags/break_tag_test.rb +0 -17
- data/test/integration/tags/continue_tag_test.rb +0 -17
- data/test/integration/tags/echo_test.rb +0 -13
- data/test/integration/tags/for_tag_test.rb +0 -466
- data/test/integration/tags/if_else_tag_test.rb +0 -190
- data/test/integration/tags/include_tag_test.rb +0 -269
- data/test/integration/tags/increment_tag_test.rb +0 -25
- data/test/integration/tags/liquid_tag_test.rb +0 -116
- data/test/integration/tags/raw_tag_test.rb +0 -34
- data/test/integration/tags/render_tag_test.rb +0 -213
- data/test/integration/tags/standard_tag_test.rb +0 -303
- data/test/integration/tags/statements_test.rb +0 -113
- data/test/integration/tags/table_row_test.rb +0 -66
- data/test/integration/tags/unless_else_tag_test.rb +0 -28
- data/test/integration/template_test.rb +0 -340
- data/test/integration/trim_mode_test.rb +0 -563
- data/test/integration/variable_test.rb +0 -138
- data/test/test_helper.rb +0 -207
- data/test/unit/block_unit_test.rb +0 -53
- data/test/unit/condition_unit_test.rb +0 -168
- data/test/unit/file_system_unit_test.rb +0 -37
- data/test/unit/i18n_unit_test.rb +0 -39
- data/test/unit/lexer_unit_test.rb +0 -53
- data/test/unit/parse_tree_visitor_test.rb +0 -261
- data/test/unit/parser_unit_test.rb +0 -84
- data/test/unit/partial_cache_unit_test.rb +0 -128
- data/test/unit/regexp_unit_test.rb +0 -46
- data/test/unit/static_registers_unit_test.rb +0 -156
- data/test/unit/strainer_factory_unit_test.rb +0 -100
- data/test/unit/strainer_template_unit_test.rb +0 -82
- data/test/unit/tag_unit_test.rb +0 -23
- data/test/unit/tags/case_tag_unit_test.rb +0 -12
- data/test/unit/tags/for_tag_unit_test.rb +0 -15
- data/test/unit/tags/if_tag_unit_test.rb +0 -10
- data/test/unit/template_factory_unit_test.rb +0 -12
- data/test/unit/template_unit_test.rb +0 -87
- data/test/unit/tokenizer_unit_test.rb +0 -62
- data/test/unit/variable_unit_test.rb +0 -164
@@ -1,66 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
class TableRowTest < Minitest::Test
|
6
|
-
include Liquid
|
7
|
-
|
8
|
-
class ArrayDrop < Liquid::Drop
|
9
|
-
include Enumerable
|
10
|
-
|
11
|
-
def initialize(array)
|
12
|
-
@array = array
|
13
|
-
end
|
14
|
-
|
15
|
-
def each(&block)
|
16
|
-
@array.each(&block)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_table_row
|
21
|
-
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",
|
22
|
-
'{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
|
23
|
-
'numbers' => [1, 2, 3, 4, 5, 6])
|
24
|
-
|
25
|
-
assert_template_result("<tr class=\"row1\">\n</tr>\n",
|
26
|
-
'{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
|
27
|
-
'numbers' => [])
|
28
|
-
end
|
29
|
-
|
30
|
-
def test_table_row_with_different_cols
|
31
|
-
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",
|
32
|
-
'{% tablerow n in numbers cols:5%} {{n}} {% endtablerow %}',
|
33
|
-
'numbers' => [1, 2, 3, 4, 5, 6])
|
34
|
-
end
|
35
|
-
|
36
|
-
def test_table_col_counter
|
37
|
-
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])
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_quoted_fragment
|
43
|
-
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] })
|
46
|
-
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
|
-
end
|
50
|
-
|
51
|
-
def test_enumerable_drop
|
52
|
-
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",
|
53
|
-
'{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
|
54
|
-
'numbers' => ArrayDrop.new([1, 2, 3, 4, 5, 6]))
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_offset_and_limit
|
58
|
-
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",
|
59
|
-
'{% tablerow n in numbers cols:3 offset:1 limit:6%} {{n}} {% endtablerow %}',
|
60
|
-
'numbers' => [0, 1, 2, 3, 4, 5, 6, 7])
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_blank_string_not_iterable
|
64
|
-
assert_template_result("<tr class=\"row1\">\n</tr>\n", "{% tablerow char in characters cols:3 %}I WILL NOT BE OUTPUT{% endtablerow %}", 'characters' => '')
|
65
|
-
end
|
66
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
class UnlessElseTagTest < Minitest::Test
|
6
|
-
include Liquid
|
7
|
-
|
8
|
-
def test_unless
|
9
|
-
assert_template_result(' ', ' {% unless true %} this text should not go into the output {% endunless %} ')
|
10
|
-
assert_template_result(' this text should go into the output ',
|
11
|
-
' {% unless false %} this text should go into the output {% endunless %} ')
|
12
|
-
assert_template_result(' you rock ?', '{% unless true %} you suck {% endunless %} {% unless false %} you rock {% endunless %}?')
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_unless_else
|
16
|
-
assert_template_result(' YES ', '{% unless true %} NO {% else %} YES {% endunless %}')
|
17
|
-
assert_template_result(' YES ', '{% unless false %} YES {% else %} NO {% endunless %}')
|
18
|
-
assert_template_result(' YES ', '{% unless "foo" %} NO {% else %} YES {% endunless %}')
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_unless_in_loop
|
22
|
-
assert_template_result('23', '{% for i in choices %}{% unless i %}{{ forloop.index }}{% endunless %}{% endfor %}', 'choices' => [1, nil, false])
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_unless_else_in_loop
|
26
|
-
assert_template_result(' TRUE 2 3 ', '{% for i in choices %}{% unless i %} {{ forloop.index }} {% else %} TRUE {% endunless %}{% endfor %}', 'choices' => [1, nil, false])
|
27
|
-
end
|
28
|
-
end # UnlessElseTest
|
@@ -1,340 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
require 'timeout'
|
5
|
-
|
6
|
-
class TemplateContextDrop < Liquid::Drop
|
7
|
-
def liquid_method_missing(method)
|
8
|
-
method
|
9
|
-
end
|
10
|
-
|
11
|
-
def foo
|
12
|
-
'fizzbuzz'
|
13
|
-
end
|
14
|
-
|
15
|
-
def baz
|
16
|
-
@context.registers['lulz']
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
class SomethingWithLength < Liquid::Drop
|
21
|
-
def length
|
22
|
-
nil
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class ErroneousDrop < Liquid::Drop
|
27
|
-
def bad_method
|
28
|
-
raise 'ruby error in drop'
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class DropWithUndefinedMethod < Liquid::Drop
|
33
|
-
def foo
|
34
|
-
'foo'
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
class TemplateTest < Minitest::Test
|
39
|
-
include Liquid
|
40
|
-
|
41
|
-
def test_instance_assigns_persist_on_same_template_object_between_parses
|
42
|
-
t = Template.new
|
43
|
-
assert_equal('from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render!)
|
44
|
-
assert_equal('from instance assigns', t.parse("{{ foo }}").render!)
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_warnings_is_not_exponential_time
|
48
|
-
str = "false"
|
49
|
-
100.times do
|
50
|
-
str = "{% if true %}true{% else %}#{str}{% endif %}"
|
51
|
-
end
|
52
|
-
|
53
|
-
t = Template.parse(str)
|
54
|
-
assert_equal([], Timeout.timeout(1) { t.warnings })
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_instance_assigns_persist_on_same_template_parsing_between_renders
|
58
|
-
t = Template.new.parse("{{ foo }}{% assign foo = 'foo' %}{{ foo }}")
|
59
|
-
assert_equal('foo', t.render!)
|
60
|
-
assert_equal('foofoo', t.render!)
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_custom_assigns_do_not_persist_on_same_template
|
64
|
-
t = Template.new
|
65
|
-
assert_equal('from custom assigns', t.parse("{{ foo }}").render!('foo' => 'from custom assigns'))
|
66
|
-
assert_equal('', t.parse("{{ foo }}").render!)
|
67
|
-
end
|
68
|
-
|
69
|
-
def test_custom_assigns_squash_instance_assigns
|
70
|
-
t = Template.new
|
71
|
-
assert_equal('from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render!)
|
72
|
-
assert_equal('from custom assigns', t.parse("{{ foo }}").render!('foo' => 'from custom assigns'))
|
73
|
-
end
|
74
|
-
|
75
|
-
def test_persistent_assigns_squash_instance_assigns
|
76
|
-
t = Template.new
|
77
|
-
assert_equal('from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render!)
|
78
|
-
t.assigns['foo'] = 'from persistent assigns'
|
79
|
-
assert_equal('from persistent assigns', t.parse("{{ foo }}").render!)
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_lambda_is_called_once_from_persistent_assigns_over_multiple_parses_and_renders
|
83
|
-
t = Template.new
|
84
|
-
t.assigns['number'] = -> {
|
85
|
-
@global ||= 0
|
86
|
-
@global += 1
|
87
|
-
}
|
88
|
-
assert_equal('1', t.parse("{{number}}").render!)
|
89
|
-
assert_equal('1', t.parse("{{number}}").render!)
|
90
|
-
assert_equal('1', t.render!)
|
91
|
-
@global = nil
|
92
|
-
end
|
93
|
-
|
94
|
-
def test_lambda_is_called_once_from_custom_assigns_over_multiple_parses_and_renders
|
95
|
-
t = Template.new
|
96
|
-
assigns = { 'number' => -> {
|
97
|
-
@global ||= 0
|
98
|
-
@global += 1
|
99
|
-
} }
|
100
|
-
assert_equal('1', t.parse("{{number}}").render!(assigns))
|
101
|
-
assert_equal('1', t.parse("{{number}}").render!(assigns))
|
102
|
-
assert_equal('1', t.render!(assigns))
|
103
|
-
@global = nil
|
104
|
-
end
|
105
|
-
|
106
|
-
def test_resource_limits_works_with_custom_length_method
|
107
|
-
t = Template.parse("{% assign foo = bar %}")
|
108
|
-
t.resource_limits.render_length_limit = 42
|
109
|
-
assert_equal("", t.render!("bar" => SomethingWithLength.new))
|
110
|
-
end
|
111
|
-
|
112
|
-
def test_resource_limits_render_length
|
113
|
-
t = Template.parse("0123456789")
|
114
|
-
t.resource_limits.render_length_limit = 9
|
115
|
-
assert_equal("Liquid error: Memory limits exceeded", t.render)
|
116
|
-
assert(t.resource_limits.reached?)
|
117
|
-
|
118
|
-
t.resource_limits.render_length_limit = 10
|
119
|
-
assert_equal("0123456789", t.render!)
|
120
|
-
end
|
121
|
-
|
122
|
-
def test_resource_limits_render_score
|
123
|
-
t = Template.parse("{% for a in (1..10) %} {% for a in (1..10) %} foo {% endfor %} {% endfor %}")
|
124
|
-
t.resource_limits.render_score_limit = 50
|
125
|
-
assert_equal("Liquid error: Memory limits exceeded", t.render)
|
126
|
-
assert(t.resource_limits.reached?)
|
127
|
-
|
128
|
-
t = Template.parse("{% for a in (1..100) %} foo {% endfor %}")
|
129
|
-
t.resource_limits.render_score_limit = 50
|
130
|
-
assert_equal("Liquid error: Memory limits exceeded", t.render)
|
131
|
-
assert(t.resource_limits.reached?)
|
132
|
-
|
133
|
-
t.resource_limits.render_score_limit = 200
|
134
|
-
assert_equal((" foo " * 100), t.render!)
|
135
|
-
refute_nil(t.resource_limits.render_score)
|
136
|
-
end
|
137
|
-
|
138
|
-
def test_resource_limits_aborts_rendering_after_first_error
|
139
|
-
t = Template.parse("{% for a in (1..100) %} foo1 {% endfor %} bar {% for a in (1..100) %} foo2 {% endfor %}")
|
140
|
-
t.resource_limits.render_score_limit = 50
|
141
|
-
assert_equal("Liquid error: Memory limits exceeded", t.render)
|
142
|
-
assert(t.resource_limits.reached?)
|
143
|
-
end
|
144
|
-
|
145
|
-
def test_resource_limits_hash_in_template_gets_updated_even_if_no_limits_are_set
|
146
|
-
t = Template.parse("{% for a in (1..100) %}x{% assign foo = 1 %} {% endfor %}")
|
147
|
-
t.render!
|
148
|
-
assert(t.resource_limits.assign_score > 0)
|
149
|
-
assert(t.resource_limits.render_score > 0)
|
150
|
-
end
|
151
|
-
|
152
|
-
def test_render_length_persists_between_blocks
|
153
|
-
t = Template.parse("{% if true %}aaaa{% endif %}")
|
154
|
-
t.resource_limits.render_length_limit = 3
|
155
|
-
assert_equal("Liquid error: Memory limits exceeded", t.render)
|
156
|
-
t.resource_limits.render_length_limit = 4
|
157
|
-
assert_equal("aaaa", t.render)
|
158
|
-
|
159
|
-
t = Template.parse("{% if true %}aaaa{% endif %}{% if true %}bbb{% endif %}")
|
160
|
-
t.resource_limits.render_length_limit = 6
|
161
|
-
assert_equal("Liquid error: Memory limits exceeded", t.render)
|
162
|
-
t.resource_limits.render_length_limit = 7
|
163
|
-
assert_equal("aaaabbb", t.render)
|
164
|
-
|
165
|
-
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 %}")
|
166
|
-
t.resource_limits.render_length_limit = 5
|
167
|
-
assert_equal("Liquid error: Memory limits exceeded", t.render)
|
168
|
-
t.resource_limits.render_length_limit = 6
|
169
|
-
assert_equal("ababab", t.render)
|
170
|
-
end
|
171
|
-
|
172
|
-
def test_render_length_uses_number_of_bytes_not_characters
|
173
|
-
t = Template.parse("{% if true %}すごい{% endif %}")
|
174
|
-
t.resource_limits.render_length_limit = 8
|
175
|
-
assert_equal("Liquid error: Memory limits exceeded", t.render)
|
176
|
-
t.resource_limits.render_length_limit = 9
|
177
|
-
assert_equal("すごい", t.render)
|
178
|
-
end
|
179
|
-
|
180
|
-
def test_default_resource_limits_unaffected_by_render_with_context
|
181
|
-
context = Context.new
|
182
|
-
t = Template.parse("{% for a in (1..100) %}x{% assign foo = 1 %} {% endfor %}")
|
183
|
-
t.render!(context)
|
184
|
-
assert(context.resource_limits.assign_score > 0)
|
185
|
-
assert(context.resource_limits.render_score > 0)
|
186
|
-
end
|
187
|
-
|
188
|
-
def test_can_use_drop_as_context
|
189
|
-
t = Template.new
|
190
|
-
t.registers['lulz'] = 'haha'
|
191
|
-
drop = TemplateContextDrop.new
|
192
|
-
assert_equal('fizzbuzz', t.parse('{{foo}}').render!(drop))
|
193
|
-
assert_equal('bar', t.parse('{{bar}}').render!(drop))
|
194
|
-
assert_equal('haha', t.parse("{{baz}}").render!(drop))
|
195
|
-
end
|
196
|
-
|
197
|
-
def test_render_bang_force_rethrow_errors_on_passed_context
|
198
|
-
context = Context.new('drop' => ErroneousDrop.new)
|
199
|
-
t = Template.new.parse('{{ drop.bad_method }}')
|
200
|
-
|
201
|
-
e = assert_raises(RuntimeError) do
|
202
|
-
t.render!(context)
|
203
|
-
end
|
204
|
-
assert_equal('ruby error in drop', e.message)
|
205
|
-
end
|
206
|
-
|
207
|
-
def test_exception_renderer_that_returns_string
|
208
|
-
exception = nil
|
209
|
-
handler = ->(e) {
|
210
|
-
exception = e
|
211
|
-
'<!-- error -->'
|
212
|
-
}
|
213
|
-
|
214
|
-
output = Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_renderer: handler)
|
215
|
-
|
216
|
-
assert(exception.is_a?(Liquid::ZeroDivisionError))
|
217
|
-
assert_equal('<!-- error -->', output)
|
218
|
-
end
|
219
|
-
|
220
|
-
def test_exception_renderer_that_raises
|
221
|
-
exception = nil
|
222
|
-
assert_raises(Liquid::ZeroDivisionError) do
|
223
|
-
Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_renderer: ->(e) {
|
224
|
-
exception = e
|
225
|
-
raise
|
226
|
-
})
|
227
|
-
end
|
228
|
-
assert(exception.is_a?(Liquid::ZeroDivisionError))
|
229
|
-
end
|
230
|
-
|
231
|
-
def test_global_filter_option_on_render
|
232
|
-
global_filter_proc = ->(output) { "#{output} filtered" }
|
233
|
-
rendered_template = Template.parse("{{name}}").render({ "name" => "bob" }, global_filter: global_filter_proc)
|
234
|
-
|
235
|
-
assert_equal('bob filtered', rendered_template)
|
236
|
-
end
|
237
|
-
|
238
|
-
def test_global_filter_option_when_native_filters_exist
|
239
|
-
global_filter_proc = ->(output) { "#{output} filtered" }
|
240
|
-
rendered_template = Template.parse("{{name | upcase}}").render({ "name" => "bob" }, global_filter: global_filter_proc)
|
241
|
-
|
242
|
-
assert_equal('BOB filtered', rendered_template)
|
243
|
-
end
|
244
|
-
|
245
|
-
def test_undefined_variables
|
246
|
-
t = Template.parse("{{x}} {{y}} {{z.a}} {{z.b}} {{z.c.d}}")
|
247
|
-
result = t.render({ 'x' => 33, 'z' => { 'a' => 32, 'c' => { 'e' => 31 } } }, strict_variables: true)
|
248
|
-
|
249
|
-
assert_equal('33 32 ', result)
|
250
|
-
assert_equal(3, t.errors.count)
|
251
|
-
assert_instance_of(Liquid::UndefinedVariable, t.errors[0])
|
252
|
-
assert_equal('Liquid error: undefined variable y', t.errors[0].message)
|
253
|
-
assert_instance_of(Liquid::UndefinedVariable, t.errors[1])
|
254
|
-
assert_equal('Liquid error: undefined variable b', t.errors[1].message)
|
255
|
-
assert_instance_of(Liquid::UndefinedVariable, t.errors[2])
|
256
|
-
assert_equal('Liquid error: undefined variable d', t.errors[2].message)
|
257
|
-
end
|
258
|
-
|
259
|
-
def test_nil_value_does_not_raise
|
260
|
-
t = Template.parse("some{{x}}thing", error_mode: :strict)
|
261
|
-
result = t.render!({ 'x' => nil }, strict_variables: true)
|
262
|
-
|
263
|
-
assert_equal(0, t.errors.count)
|
264
|
-
assert_equal('something', result)
|
265
|
-
end
|
266
|
-
|
267
|
-
def test_undefined_variables_raise
|
268
|
-
t = Template.parse("{{x}} {{y}} {{z.a}} {{z.b}} {{z.c.d}}")
|
269
|
-
|
270
|
-
assert_raises(UndefinedVariable) do
|
271
|
-
t.render!({ 'x' => 33, 'z' => { 'a' => 32, 'c' => { 'e' => 31 } } }, strict_variables: true)
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
def test_undefined_drop_methods
|
276
|
-
d = DropWithUndefinedMethod.new
|
277
|
-
t = Template.new.parse('{{ foo }} {{ woot }}')
|
278
|
-
result = t.render(d, strict_variables: true)
|
279
|
-
|
280
|
-
assert_equal('foo ', result)
|
281
|
-
assert_equal(1, t.errors.count)
|
282
|
-
assert_instance_of(Liquid::UndefinedDropMethod, t.errors[0])
|
283
|
-
end
|
284
|
-
|
285
|
-
def test_undefined_drop_methods_raise
|
286
|
-
d = DropWithUndefinedMethod.new
|
287
|
-
t = Template.new.parse('{{ foo }} {{ woot }}')
|
288
|
-
|
289
|
-
assert_raises(UndefinedDropMethod) do
|
290
|
-
t.render!(d, strict_variables: true)
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
def test_undefined_filters
|
295
|
-
t = Template.parse("{{a}} {{x | upcase | somefilter1 | somefilter2 | somefilter3}}")
|
296
|
-
filters = Module.new do
|
297
|
-
def somefilter3(v)
|
298
|
-
"-#{v}-"
|
299
|
-
end
|
300
|
-
end
|
301
|
-
result = t.render({ 'a' => 123, 'x' => 'foo' }, filters: [filters], strict_filters: true)
|
302
|
-
|
303
|
-
assert_equal('123 ', result)
|
304
|
-
assert_equal(1, t.errors.count)
|
305
|
-
assert_instance_of(Liquid::UndefinedFilter, t.errors[0])
|
306
|
-
assert_equal('Liquid error: undefined filter somefilter1', t.errors[0].message)
|
307
|
-
end
|
308
|
-
|
309
|
-
def test_undefined_filters_raise
|
310
|
-
t = Template.parse("{{x | somefilter1 | upcase | somefilter2}}")
|
311
|
-
|
312
|
-
assert_raises(UndefinedFilter) do
|
313
|
-
t.render!({ 'x' => 'foo' }, strict_filters: true)
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
def test_using_range_literal_works_as_expected
|
318
|
-
t = Template.parse("{% assign foo = (x..y) %}{{ foo }}")
|
319
|
-
result = t.render('x' => 1, 'y' => 5)
|
320
|
-
assert_equal('1..5', result)
|
321
|
-
|
322
|
-
t = Template.parse("{% assign nums = (x..y) %}{% for num in nums %}{{ num }}{% endfor %}")
|
323
|
-
result = t.render('x' => 1, 'y' => 5)
|
324
|
-
assert_equal('12345', result)
|
325
|
-
end
|
326
|
-
|
327
|
-
def test_source_string_subclass
|
328
|
-
string_subclass = Class.new(String) do
|
329
|
-
# E.g. ActiveSupport::SafeBuffer does this, so don't just rely on to_s to return a String
|
330
|
-
def to_s
|
331
|
-
self
|
332
|
-
end
|
333
|
-
end
|
334
|
-
source = string_subclass.new("{% assign x = 2 -%} x= {{- x }}")
|
335
|
-
assert_instance_of(string_subclass, source)
|
336
|
-
output = Template.parse(source).render!
|
337
|
-
assert_equal("x=2", output)
|
338
|
-
assert_instance_of(String, output)
|
339
|
-
end
|
340
|
-
end
|