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.
- checksums.yaml +4 -4
- data/History.md +89 -58
- data/{MIT-LICENSE → LICENSE} +0 -0
- data/lib/liquid.rb +7 -6
- data/lib/liquid/block.rb +31 -124
- data/lib/liquid/block_body.rb +54 -57
- data/lib/liquid/condition.rb +23 -22
- data/lib/liquid/context.rb +50 -42
- data/lib/liquid/document.rb +19 -9
- data/lib/liquid/drop.rb +12 -13
- data/lib/liquid/errors.rb +16 -17
- data/lib/liquid/expression.rb +15 -3
- data/lib/liquid/extensions.rb +7 -7
- data/lib/liquid/file_system.rb +3 -3
- data/lib/liquid/forloop_drop.rb +42 -0
- data/lib/liquid/i18n.rb +5 -5
- data/lib/liquid/interrupts.rb +1 -2
- data/lib/liquid/lexer.rb +6 -4
- data/lib/liquid/locales/en.yml +3 -1
- data/lib/liquid/parse_context.rb +37 -0
- data/lib/liquid/parser_switching.rb +4 -4
- data/lib/liquid/profiler.rb +18 -19
- data/lib/liquid/profiler/hooks.rb +7 -7
- data/lib/liquid/range_lookup.rb +16 -1
- data/lib/liquid/resource_limits.rb +23 -0
- data/lib/liquid/standardfilters.rb +101 -56
- data/lib/liquid/strainer.rb +4 -5
- data/lib/liquid/tablerowloop_drop.rb +62 -0
- data/lib/liquid/tag.rb +9 -8
- data/lib/liquid/tags/assign.rb +5 -4
- data/lib/liquid/tags/break.rb +0 -3
- data/lib/liquid/tags/capture.rb +1 -1
- data/lib/liquid/tags/case.rb +19 -12
- data/lib/liquid/tags/comment.rb +2 -2
- data/lib/liquid/tags/cycle.rb +6 -6
- data/lib/liquid/tags/decrement.rb +1 -4
- data/lib/liquid/tags/for.rb +93 -75
- data/lib/liquid/tags/if.rb +49 -44
- data/lib/liquid/tags/ifchanged.rb +0 -2
- data/lib/liquid/tags/include.rb +60 -52
- data/lib/liquid/tags/raw.rb +26 -4
- data/lib/liquid/tags/table_row.rb +12 -30
- data/lib/liquid/tags/unless.rb +3 -4
- data/lib/liquid/template.rb +23 -50
- data/lib/liquid/tokenizer.rb +31 -0
- data/lib/liquid/utils.rb +48 -8
- data/lib/liquid/variable.rb +46 -45
- data/lib/liquid/variable_lookup.rb +3 -3
- data/lib/liquid/version.rb +1 -1
- data/test/integration/assign_test.rb +8 -8
- data/test/integration/blank_test.rb +14 -14
- data/test/integration/context_test.rb +2 -2
- data/test/integration/document_test.rb +19 -0
- data/test/integration/drop_test.rb +42 -40
- data/test/integration/error_handling_test.rb +64 -45
- data/test/integration/filter_test.rb +60 -20
- data/test/integration/output_test.rb +26 -27
- data/test/integration/parsing_quirks_test.rb +15 -13
- data/test/integration/render_profiling_test.rb +20 -20
- data/test/integration/security_test.rb +5 -7
- data/test/integration/standard_filter_test.rb +119 -37
- data/test/integration/tags/break_tag_test.rb +1 -2
- data/test/integration/tags/continue_tag_test.rb +0 -1
- data/test/integration/tags/for_tag_test.rb +133 -98
- data/test/integration/tags/if_else_tag_test.rb +75 -77
- data/test/integration/tags/include_tag_test.rb +23 -30
- data/test/integration/tags/increment_tag_test.rb +10 -11
- data/test/integration/tags/raw_tag_test.rb +7 -1
- data/test/integration/tags/standard_tag_test.rb +121 -122
- data/test/integration/tags/statements_test.rb +3 -5
- data/test/integration/tags/table_row_test.rb +20 -19
- data/test/integration/tags/unless_else_tag_test.rb +6 -6
- data/test/integration/template_test.rb +91 -45
- data/test/integration/variable_test.rb +23 -13
- data/test/test_helper.rb +33 -5
- data/test/unit/block_unit_test.rb +6 -5
- data/test/unit/condition_unit_test.rb +82 -77
- data/test/unit/context_unit_test.rb +48 -57
- data/test/unit/file_system_unit_test.rb +3 -3
- data/test/unit/i18n_unit_test.rb +2 -2
- data/test/unit/lexer_unit_test.rb +11 -8
- data/test/unit/parser_unit_test.rb +2 -2
- data/test/unit/regexp_unit_test.rb +1 -1
- data/test/unit/strainer_unit_test.rb +13 -2
- data/test/unit/tag_unit_test.rb +7 -2
- data/test/unit/tags/case_tag_unit_test.rb +1 -1
- data/test/unit/tags/for_tag_unit_test.rb +2 -2
- data/test/unit/tags/if_tag_unit_test.rb +1 -1
- data/test/unit/template_unit_test.rb +6 -5
- data/test/unit/tokenizer_unit_test.rb +24 -7
- data/test/unit/variable_unit_test.rb +60 -43
- metadata +44 -41
- data/lib/liquid/module_ex.rb +0 -62
- data/lib/liquid/token.rb +0 -18
- 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
|
-
|
22
|
-
|
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
|
-
|
26
|
-
|
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
|
-
|
32
|
-
|
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
|
-
|
39
|
-
|
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
|
-
|
45
|
-
|
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
|
-
|
48
|
-
|
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
|
-
|
55
|
-
|
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
|
-
|
61
|
-
|
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
|
-
|
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
|
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'] =
|
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' =>
|
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 =
|
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 =
|
92
|
-
assert_equal "Liquid error: Memory limits exceeded", t.render
|
93
|
-
assert t.resource_limits
|
94
|
-
|
95
|
-
|
96
|
-
|
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 =
|
102
|
-
assert_equal "Liquid error: Memory limits exceeded", t.render
|
103
|
-
assert t.resource_limits
|
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 =
|
106
|
-
assert_equal "Liquid error: Memory limits exceeded", t.render
|
107
|
-
assert t.resource_limits
|
108
|
-
|
109
|
-
|
110
|
-
|
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 =
|
116
|
-
assert_equal "Liquid error: Memory limits exceeded", t.render
|
117
|
-
assert t.resource_limits
|
118
|
-
|
119
|
-
|
120
|
-
|
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 =
|
126
|
-
assert_equal "Liquid error: Memory limits exceeded", t.render
|
127
|
-
assert t.resource_limits
|
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
|
134
|
-
assert t.resource_limits
|
135
|
-
assert t.resource_limits
|
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
|
143
|
-
assert context.resource_limits
|
144
|
-
assert context.resource_limits
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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
|
|
data/test/test_helper.rb
CHANGED
@@ -4,8 +4,9 @@ ENV["MT_NO_EXPECTATIONS"] = "1"
|
|
4
4
|
require 'minitest/autorun'
|
5
5
|
require 'spy/integration'
|
6
6
|
|
7
|
-
|
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(
|
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,
|
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
|