liquid 3.0.0.rc1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +4 -0
- data/README.md +2 -2
- data/lib/liquid.rb +8 -0
- data/lib/liquid/block.rb +50 -46
- data/lib/liquid/block_body.rb +123 -0
- data/lib/liquid/condition.rb +12 -5
- data/lib/liquid/context.rb +75 -148
- data/lib/liquid/errors.rb +50 -2
- data/lib/liquid/expression.rb +33 -0
- data/lib/liquid/parser_switching.rb +31 -0
- data/lib/liquid/profiler.rb +159 -0
- data/lib/liquid/profiler/hooks.rb +23 -0
- data/lib/liquid/range_lookup.rb +22 -0
- data/lib/liquid/standardfilters.rb +29 -4
- data/lib/liquid/tag.rb +6 -25
- data/lib/liquid/tags/assign.rb +2 -1
- data/lib/liquid/tags/case.rb +1 -1
- data/lib/liquid/tags/if.rb +5 -5
- data/lib/liquid/tags/ifchanged.rb +1 -1
- data/lib/liquid/tags/include.rb +11 -1
- data/lib/liquid/tags/raw.rb +1 -4
- data/lib/liquid/tags/table_row.rb +1 -1
- data/lib/liquid/template.rb +55 -4
- data/lib/liquid/token.rb +18 -0
- data/lib/liquid/variable.rb +68 -41
- data/lib/liquid/variable_lookup.rb +78 -0
- data/lib/liquid/version.rb +1 -1
- data/test/integration/assign_test.rb +12 -1
- data/test/integration/blank_test.rb +1 -1
- data/test/integration/capture_test.rb +1 -1
- data/test/integration/context_test.rb +10 -11
- data/test/integration/drop_test.rb +29 -3
- data/test/integration/error_handling_test.rb +138 -41
- data/test/integration/filter_test.rb +7 -7
- data/test/integration/hash_ordering_test.rb +6 -8
- data/test/integration/output_test.rb +1 -1
- data/test/integration/parsing_quirks_test.rb +40 -18
- data/test/integration/render_profiling_test.rb +154 -0
- data/test/integration/security_test.rb +1 -1
- data/test/integration/standard_filter_test.rb +47 -1
- data/test/integration/tags/break_tag_test.rb +1 -1
- data/test/integration/tags/continue_tag_test.rb +1 -1
- data/test/integration/tags/for_tag_test.rb +2 -2
- data/test/integration/tags/if_else_tag_test.rb +23 -20
- data/test/integration/tags/include_tag_test.rb +24 -2
- data/test/integration/tags/increment_tag_test.rb +1 -1
- data/test/integration/tags/raw_tag_test.rb +1 -1
- data/test/integration/tags/standard_tag_test.rb +4 -4
- data/test/integration/tags/statements_test.rb +1 -1
- data/test/integration/tags/table_row_test.rb +1 -1
- data/test/integration/tags/unless_else_tag_test.rb +1 -1
- data/test/integration/template_test.rb +16 -4
- data/test/integration/variable_test.rb +11 -1
- data/test/test_helper.rb +59 -31
- data/test/unit/block_unit_test.rb +2 -5
- data/test/unit/condition_unit_test.rb +5 -1
- data/test/unit/context_unit_test.rb +13 -7
- data/test/unit/file_system_unit_test.rb +5 -5
- data/test/unit/i18n_unit_test.rb +3 -3
- data/test/unit/lexer_unit_test.rb +1 -1
- data/test/unit/module_ex_unit_test.rb +1 -1
- data/test/unit/parser_unit_test.rb +1 -1
- data/test/unit/regexp_unit_test.rb +1 -1
- data/test/unit/strainer_unit_test.rb +3 -2
- data/test/unit/tag_unit_test.rb +6 -1
- data/test/unit/tags/case_tag_unit_test.rb +1 -1
- data/test/unit/tags/for_tag_unit_test.rb +1 -1
- data/test/unit/tags/if_tag_unit_test.rb +1 -1
- data/test/unit/template_unit_test.rb +1 -1
- data/test/unit/tokenizer_unit_test.rb +10 -1
- data/test/unit/variable_unit_test.rb +49 -46
- metadata +71 -47
data/lib/liquid/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class AssignTest < Test
|
3
|
+
class AssignTest < Minitest::Test
|
4
4
|
include Liquid
|
5
5
|
|
6
6
|
def test_assigned_variable
|
@@ -24,4 +24,15 @@ class AssignTest < Test::Unit::TestCase
|
|
24
24
|
'{% assign foo not values %}.',
|
25
25
|
'values' => "foo,bar,baz")
|
26
26
|
end
|
27
|
+
|
28
|
+
def test_assign_uses_error_mode
|
29
|
+
with_error_mode(:strict) do
|
30
|
+
assert_raises(SyntaxError) do
|
31
|
+
Template.parse("{% assign foo = ('X' | downcase) %}")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
with_error_mode(:lax) do
|
35
|
+
assert Template.parse("{% assign foo = ('X' | downcase) %}")
|
36
|
+
end
|
37
|
+
end
|
27
38
|
end # AssignTest
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class ContextTest < Test
|
3
|
+
class ContextTest < Minitest::Test
|
4
4
|
include Liquid
|
5
5
|
|
6
6
|
def test_override_global_filter
|
@@ -16,18 +16,17 @@ class ContextTest < Test::Unit::TestCase
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
with_global_filter(global) do
|
20
|
+
assert_equal 'Global test', Template.parse("{{'test' | notice }}").render!
|
21
|
+
assert_equal 'Local test', Template.parse("{{'test' | notice }}").render!({}, :filters => [local])
|
22
|
+
end
|
22
23
|
end
|
23
24
|
|
24
25
|
def test_has_key_will_not_add_an_error_for_missing_keys
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
assert_empty context.errors
|
26
|
+
with_error_mode :strict do
|
27
|
+
context = Context.new
|
28
|
+
context.has_key?('unknown')
|
29
|
+
assert_empty context.errors
|
30
|
+
end
|
32
31
|
end
|
33
32
|
end
|
@@ -48,6 +48,10 @@ class ProductDrop < Liquid::Drop
|
|
48
48
|
ContextDrop.new
|
49
49
|
end
|
50
50
|
|
51
|
+
def user_input
|
52
|
+
"foo".taint
|
53
|
+
end
|
54
|
+
|
51
55
|
protected
|
52
56
|
def callmenot
|
53
57
|
"protected"
|
@@ -100,12 +104,34 @@ class RealEnumerableDrop < Liquid::Drop
|
|
100
104
|
end
|
101
105
|
end
|
102
106
|
|
103
|
-
class DropsTest < Test
|
107
|
+
class DropsTest < Minitest::Test
|
104
108
|
include Liquid
|
105
109
|
|
106
110
|
def test_product_drop
|
107
|
-
|
108
|
-
|
111
|
+
tpl = Liquid::Template.parse(' ')
|
112
|
+
assert_equal ' ', tpl.render!('product' => ProductDrop.new)
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_rendering_raises_on_tainted_attr
|
116
|
+
with_taint_mode(:error) do
|
117
|
+
tpl = Liquid::Template.parse('{{ product.user_input }}')
|
118
|
+
assert_raises TaintedError do
|
119
|
+
tpl.render!('product' => ProductDrop.new)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_rendering_warns_on_tainted_attr
|
125
|
+
with_taint_mode(:warn) do
|
126
|
+
tpl = Liquid::Template.parse('{{ product.user_input }}')
|
127
|
+
tpl.render!('product' => ProductDrop.new)
|
128
|
+
assert_match /tainted/, tpl.warnings.first
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_rendering_doesnt_raise_on_escaped_tainted_attr
|
133
|
+
with_taint_mode(:error) do
|
134
|
+
tpl = Liquid::Template.parse('{{ product.user_input | escape }}')
|
109
135
|
tpl.render!('product' => ProductDrop.new)
|
110
136
|
end
|
111
137
|
end
|
@@ -19,92 +19,189 @@ class ErrorDrop < Liquid::Drop
|
|
19
19
|
|
20
20
|
end
|
21
21
|
|
22
|
-
class ErrorHandlingTest < Test
|
22
|
+
class ErrorHandlingTest < Minitest::Test
|
23
23
|
include Liquid
|
24
24
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
assert_equal ' Liquid error: standard error ', template.render('errors' => ErrorDrop.new)
|
25
|
+
def test_templates_parsed_with_line_numbers_renders_them_in_errors
|
26
|
+
template = <<-LIQUID
|
27
|
+
Hello,
|
29
28
|
|
30
|
-
|
31
|
-
assert_equal StandardError, template.errors.first.class
|
32
|
-
end
|
33
|
-
end
|
29
|
+
{{ errors.standard_error }} will raise a standard error.
|
34
30
|
|
35
|
-
|
31
|
+
Bla bla test.
|
36
32
|
|
37
|
-
|
33
|
+
{{ errors.syntax_error }} will raise a syntax error.
|
38
34
|
|
39
|
-
|
40
|
-
assert_equal ' Liquid syntax error: syntax error ', template.render('errors' => ErrorDrop.new)
|
35
|
+
This is an argument error: {{ errors.argument_error }}
|
41
36
|
|
42
|
-
|
43
|
-
|
37
|
+
Bla.
|
38
|
+
LIQUID
|
44
39
|
|
45
|
-
|
40
|
+
expected = <<-TEXT
|
41
|
+
Hello,
|
42
|
+
|
43
|
+
Liquid error (line 3): standard error will raise a standard error.
|
44
|
+
|
45
|
+
Bla bla test.
|
46
|
+
|
47
|
+
Liquid syntax error (line 7): syntax error will raise a syntax error.
|
48
|
+
|
49
|
+
This is an argument error: Liquid error (line 9): argument error
|
50
|
+
|
51
|
+
Bla.
|
52
|
+
TEXT
|
53
|
+
|
54
|
+
output = Liquid::Template.parse(template, line_numbers: true).render('errors' => ErrorDrop.new)
|
55
|
+
assert_equal expected, output
|
46
56
|
end
|
47
57
|
|
48
|
-
def
|
49
|
-
|
58
|
+
def test_standard_error
|
59
|
+
template = Liquid::Template.parse( ' {{ errors.standard_error }} ' )
|
60
|
+
assert_equal ' Liquid error: standard error ', template.render('errors' => ErrorDrop.new)
|
50
61
|
|
51
|
-
|
52
|
-
|
62
|
+
assert_equal 1, template.errors.size
|
63
|
+
assert_equal StandardError, template.errors.first.class
|
64
|
+
end
|
53
65
|
|
54
|
-
|
55
|
-
|
56
|
-
|
66
|
+
def test_syntax
|
67
|
+
template = Liquid::Template.parse( ' {{ errors.syntax_error }} ' )
|
68
|
+
assert_equal ' Liquid syntax error: syntax error ', template.render('errors' => ErrorDrop.new)
|
69
|
+
|
70
|
+
assert_equal 1, template.errors.size
|
71
|
+
assert_equal SyntaxError, template.errors.first.class
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_argument
|
75
|
+
template = Liquid::Template.parse( ' {{ errors.argument_error }} ' )
|
76
|
+
assert_equal ' Liquid error: argument error ', template.render('errors' => ErrorDrop.new)
|
77
|
+
|
78
|
+
assert_equal 1, template.errors.size
|
79
|
+
assert_equal ArgumentError, template.errors.first.class
|
57
80
|
end
|
58
81
|
|
59
82
|
def test_missing_endtag_parse_time_error
|
60
|
-
|
83
|
+
assert_raises(Liquid::SyntaxError) do
|
61
84
|
Liquid::Template.parse(' {% for a in b %} ... ')
|
62
85
|
end
|
63
86
|
end
|
64
87
|
|
65
88
|
def test_unrecognized_operator
|
66
89
|
with_error_mode(:strict) do
|
67
|
-
|
90
|
+
assert_raises(SyntaxError) do
|
68
91
|
Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ')
|
69
92
|
end
|
70
93
|
end
|
71
94
|
end
|
72
|
-
|
95
|
+
|
73
96
|
def test_lax_unrecognized_operator
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
97
|
+
template = Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ', :error_mode => :lax)
|
98
|
+
assert_equal ' Liquid error: Unknown operator =! ', template.render
|
99
|
+
assert_equal 1, template.errors.size
|
100
|
+
assert_equal Liquid::ArgumentError, template.errors.first.class
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_with_line_numbers_adds_numbers_to_parser_errors
|
104
|
+
err = assert_raises(SyntaxError) do
|
105
|
+
template = Liquid::Template.parse(%q{
|
106
|
+
foobar
|
107
|
+
|
108
|
+
{% "cat" | foobar %}
|
109
|
+
|
110
|
+
bla
|
111
|
+
},
|
112
|
+
:line_numbers => true
|
113
|
+
)
|
114
|
+
end
|
115
|
+
|
116
|
+
assert_match /Liquid syntax error \(line 4\)/, err.message
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_parsing_warn_with_line_numbers_adds_numbers_to_lexer_errors
|
120
|
+
template = Liquid::Template.parse(%q{
|
121
|
+
foobar
|
122
|
+
|
123
|
+
{% if 1 =! 2 %}ok{% endif %}
|
124
|
+
|
125
|
+
bla
|
126
|
+
},
|
127
|
+
:error_mode => :warn,
|
128
|
+
:line_numbers => true
|
129
|
+
)
|
130
|
+
|
131
|
+
assert_equal ['Liquid syntax error (line 4): Unexpected character = in "1 =! 2"'],
|
132
|
+
template.warnings.map(&:message)
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_parsing_strict_with_line_numbers_adds_numbers_to_lexer_errors
|
136
|
+
err = assert_raises(SyntaxError) do
|
137
|
+
Liquid::Template.parse(%q{
|
138
|
+
foobar
|
139
|
+
|
140
|
+
{% if 1 =! 2 %}ok{% endif %}
|
141
|
+
|
142
|
+
bla
|
143
|
+
},
|
144
|
+
:error_mode => :strict,
|
145
|
+
:line_numbers => true
|
146
|
+
)
|
147
|
+
end
|
148
|
+
|
149
|
+
assert_equal 'Liquid syntax error (line 4): Unexpected character = in "1 =! 2"', err.message
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_syntax_errors_in_nested_blocks_have_correct_line_number
|
153
|
+
err = assert_raises(SyntaxError) do
|
154
|
+
Liquid::Template.parse(%q{
|
155
|
+
foobar
|
156
|
+
|
157
|
+
{% if 1 != 2 %}
|
158
|
+
{% foo %}
|
159
|
+
{% endif %}
|
160
|
+
|
161
|
+
bla
|
162
|
+
},
|
163
|
+
:line_numbers => true
|
164
|
+
)
|
79
165
|
end
|
166
|
+
|
167
|
+
assert_equal "Liquid syntax error (line 5): Unknown tag 'foo'", err.message
|
80
168
|
end
|
81
169
|
|
82
170
|
def test_strict_error_messages
|
83
|
-
err =
|
171
|
+
err = assert_raises(SyntaxError) do
|
84
172
|
Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ', :error_mode => :strict)
|
85
173
|
end
|
86
|
-
assert_equal 'Unexpected character = in "1 =! 2"', err.message
|
174
|
+
assert_equal 'Liquid syntax error: Unexpected character = in "1 =! 2"', err.message
|
87
175
|
|
88
|
-
err =
|
176
|
+
err = assert_raises(SyntaxError) do
|
89
177
|
Liquid::Template.parse('{{%%%}}', :error_mode => :strict)
|
90
178
|
end
|
91
|
-
assert_equal 'Unexpected character % in "{{%%%}}"', err.message
|
179
|
+
assert_equal 'Liquid syntax error: Unexpected character % in "{{%%%}}"', err.message
|
92
180
|
end
|
93
181
|
|
94
182
|
def test_warnings
|
95
183
|
template = Liquid::Template.parse('{% if ~~~ %}{{%%%}}{% else %}{{ hello. }}{% endif %}', :error_mode => :warn)
|
96
184
|
assert_equal 3, template.warnings.size
|
97
|
-
assert_equal 'Unexpected character ~ in "~~~"', template.warnings[0].
|
98
|
-
assert_equal 'Unexpected character % in "{{%%%}}"', template.warnings[1].
|
99
|
-
assert_equal 'Expected id but found end_of_string in "{{ hello. }}"', template.warnings[2].
|
185
|
+
assert_equal 'Unexpected character ~ in "~~~"', template.warnings[0].to_s(false)
|
186
|
+
assert_equal 'Unexpected character % in "{{%%%}}"', template.warnings[1].to_s(false)
|
187
|
+
assert_equal 'Expected id but found end_of_string in "{{ hello. }}"', template.warnings[2].to_s(false)
|
100
188
|
assert_equal '', template.render
|
101
189
|
end
|
102
190
|
|
191
|
+
def test_warning_line_numbers
|
192
|
+
template = Liquid::Template.parse("{% if ~~~ %}\n{{%%%}}{% else %}\n{{ hello. }}{% endif %}", :error_mode => :warn, :line_numbers => true)
|
193
|
+
assert_equal 'Liquid syntax error (line 1): Unexpected character ~ in "~~~"', template.warnings[0].message
|
194
|
+
assert_equal 'Liquid syntax error (line 2): Unexpected character % in "{{%%%}}"', template.warnings[1].message
|
195
|
+
assert_equal 'Liquid syntax error (line 3): Expected id but found end_of_string in "{{ hello. }}"', template.warnings[2].message
|
196
|
+
assert_equal 3, template.warnings.size
|
197
|
+
assert_equal [1,2,3], template.warnings.map(&:line_number)
|
198
|
+
end
|
199
|
+
|
103
200
|
# Liquid should not catch Exceptions that are not subclasses of StandardError, like Interrupt and NoMemoryError
|
104
201
|
def test_exceptions_propagate
|
105
|
-
|
106
|
-
template = Liquid::Template.parse(
|
202
|
+
assert_raises Exception do
|
203
|
+
template = Liquid::Template.parse('{{ errors.exception }}')
|
107
204
|
template.render('errors' => ErrorDrop.new)
|
108
205
|
end
|
109
206
|
end
|
110
|
-
end
|
207
|
+
end
|
@@ -22,7 +22,7 @@ module SubstituteFilter
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
class FiltersTest < Test
|
25
|
+
class FiltersTest < Minitest::Test
|
26
26
|
include Liquid
|
27
27
|
|
28
28
|
def setup
|
@@ -107,15 +107,15 @@ class FiltersTest < Test::Unit::TestCase
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
-
class FiltersInTemplate < Test
|
110
|
+
class FiltersInTemplate < Minitest::Test
|
111
111
|
include Liquid
|
112
112
|
|
113
113
|
def test_local_global
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
114
|
+
with_global_filter(MoneyFilter) do
|
115
|
+
assert_equal " 1000$ ", Template.parse("{{1000 | money}}").render!(nil, nil)
|
116
|
+
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render!(nil, :filters => CanadianMoneyFilter)
|
117
|
+
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render!(nil, :filters => [CanadianMoneyFilter])
|
118
|
+
end
|
119
119
|
end
|
120
120
|
|
121
121
|
def test_local_filter_with_deprecated_syntax
|
@@ -12,14 +12,12 @@ module CanadianMoneyFilter
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
class HashOrderingTest < Test
|
15
|
+
class HashOrderingTest < Minitest::Test
|
16
16
|
include Liquid
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
|
18
|
+
def test_global_register_order
|
19
|
+
with_global_filter(MoneyFilter, CanadianMoneyFilter) do
|
20
|
+
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render(nil, nil)
|
21
|
+
end
|
22
|
+
end
|
25
23
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class ParsingQuirksTest < Test
|
3
|
+
class ParsingQuirksTest < Minitest::Test
|
4
4
|
include Liquid
|
5
5
|
|
6
6
|
def test_parsing_css
|
@@ -9,30 +9,28 @@ class ParsingQuirksTest < Test::Unit::TestCase
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def test_raise_on_single_close_bracet
|
12
|
-
|
12
|
+
assert_raises(SyntaxError) do
|
13
13
|
Template.parse("text {{method} oh nos!")
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
def test_raise_on_label_and_no_close_bracets
|
18
|
-
|
18
|
+
assert_raises(SyntaxError) do
|
19
19
|
Template.parse("TEST {{ ")
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
def test_raise_on_label_and_no_close_bracets_percent
|
24
|
-
|
24
|
+
assert_raises(SyntaxError) do
|
25
25
|
Template.parse("TEST {% ")
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
29
|
def test_error_on_empty_filter
|
30
|
-
|
31
|
-
|
32
|
-
Template.parse("{{|test}}")
|
33
|
-
end
|
30
|
+
assert Template.parse("{{test}}")
|
31
|
+
assert Template.parse("{{|test}}")
|
34
32
|
with_error_mode(:strict) do
|
35
|
-
|
33
|
+
assert_raises(SyntaxError) do
|
36
34
|
Template.parse("{{test |a|b|}}")
|
37
35
|
end
|
38
36
|
end
|
@@ -40,7 +38,7 @@ class ParsingQuirksTest < Test::Unit::TestCase
|
|
40
38
|
|
41
39
|
def test_meaningless_parens_error
|
42
40
|
with_error_mode(:strict) do
|
43
|
-
|
41
|
+
assert_raises(SyntaxError) do
|
44
42
|
markup = "a == 'foo' or (b == 'bar' and c == 'baz') or false"
|
45
43
|
Template.parse("{% if #{markup} %} YES {% endif %}")
|
46
44
|
end
|
@@ -49,11 +47,11 @@ class ParsingQuirksTest < Test::Unit::TestCase
|
|
49
47
|
|
50
48
|
def test_unexpected_characters_syntax_error
|
51
49
|
with_error_mode(:strict) do
|
52
|
-
|
50
|
+
assert_raises(SyntaxError) do
|
53
51
|
markup = "true && false"
|
54
52
|
Template.parse("{% if #{markup} %} YES {% endif %}")
|
55
53
|
end
|
56
|
-
|
54
|
+
assert_raises(SyntaxError) do
|
57
55
|
markup = "false || true"
|
58
56
|
Template.parse("{% if #{markup} %} YES {% endif %}")
|
59
57
|
end
|
@@ -61,11 +59,9 @@ class ParsingQuirksTest < Test::Unit::TestCase
|
|
61
59
|
end
|
62
60
|
|
63
61
|
def test_no_error_on_lax_empty_filter
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
Template.parse("{{|test|}}", :error_mode => :lax)
|
68
|
-
end
|
62
|
+
assert Template.parse("{{test |a|b|}}", :error_mode => :lax)
|
63
|
+
assert Template.parse("{{test}}", :error_mode => :lax)
|
64
|
+
assert Template.parse("{{|test|}}", :error_mode => :lax)
|
69
65
|
end
|
70
66
|
|
71
67
|
def test_meaningless_parens_lax
|
@@ -86,9 +82,35 @@ class ParsingQuirksTest < Test::Unit::TestCase
|
|
86
82
|
end
|
87
83
|
|
88
84
|
def test_raise_on_invalid_tag_delimiter
|
89
|
-
|
85
|
+
assert_raises(Liquid::SyntaxError) do
|
90
86
|
Template.new.parse('{% end %}')
|
91
87
|
end
|
92
88
|
end
|
93
89
|
|
90
|
+
def test_unanchored_filter_arguments
|
91
|
+
with_error_mode(:lax) do
|
92
|
+
assert_template_result('hi',"{{ 'hi there' | split$$$:' ' | first }}")
|
93
|
+
|
94
|
+
assert_template_result('x', "{{ 'X' | downcase) }}")
|
95
|
+
|
96
|
+
# After the messed up quotes a filter without parameters (reverse) should work
|
97
|
+
# but one with parameters (remove) shouldn't be detected.
|
98
|
+
assert_template_result('here', "{{ 'hi there' | split:\"t\"\" | reverse | first}}")
|
99
|
+
assert_template_result('hi ', "{{ 'hi there' | split:\"t\"\" | remove:\"i\" | first}}")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_invalid_variables_work
|
104
|
+
with_error_mode(:lax) do
|
105
|
+
assert_template_result('bar', "{% assign 123foo = 'bar' %}{{ 123foo }}")
|
106
|
+
assert_template_result('123', "{% assign 123 = 'bar' %}{{ 123 }}")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_extra_dots_in_ranges
|
111
|
+
with_error_mode(:lax) do
|
112
|
+
assert_template_result('12345', "{% for i in (1...5) %}{{ i }}{% endfor %}")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
94
116
|
end # ParsingQuirksTest
|