liquid 4.0.3 → 5.0.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 +33 -0
- data/README.md +6 -0
- data/lib/liquid.rb +17 -5
- data/lib/liquid/block.rb +31 -14
- data/lib/liquid/block_body.rb +164 -54
- data/lib/liquid/condition.rb +39 -18
- data/lib/liquid/context.rb +106 -51
- data/lib/liquid/document.rb +47 -9
- data/lib/liquid/drop.rb +4 -2
- data/lib/liquid/errors.rb +20 -18
- data/lib/liquid/expression.rb +29 -34
- data/lib/liquid/extensions.rb +2 -0
- data/lib/liquid/file_system.rb +6 -4
- data/lib/liquid/forloop_drop.rb +11 -4
- data/lib/liquid/i18n.rb +5 -3
- data/lib/liquid/interrupts.rb +3 -1
- data/lib/liquid/lexer.rb +30 -23
- data/lib/liquid/locales/en.yml +3 -1
- data/lib/liquid/parse_context.rb +16 -4
- data/lib/liquid/parse_tree_visitor.rb +2 -2
- data/lib/liquid/parser.rb +30 -18
- data/lib/liquid/parser_switching.rb +17 -3
- data/lib/liquid/partial_cache.rb +24 -0
- data/lib/liquid/profiler.rb +67 -86
- data/lib/liquid/profiler/hooks.rb +26 -14
- data/lib/liquid/range_lookup.rb +5 -3
- data/lib/liquid/register.rb +6 -0
- data/lib/liquid/resource_limits.rb +47 -8
- data/lib/liquid/standardfilters.rb +63 -44
- data/lib/liquid/static_registers.rb +44 -0
- data/lib/liquid/strainer_factory.rb +36 -0
- data/lib/liquid/strainer_template.rb +53 -0
- data/lib/liquid/tablerowloop_drop.rb +6 -4
- data/lib/liquid/tag.rb +28 -6
- data/lib/liquid/tag/disableable.rb +22 -0
- data/lib/liquid/tag/disabler.rb +21 -0
- data/lib/liquid/tags/assign.rb +24 -10
- data/lib/liquid/tags/break.rb +8 -3
- data/lib/liquid/tags/capture.rb +11 -8
- data/lib/liquid/tags/case.rb +33 -27
- data/lib/liquid/tags/comment.rb +5 -3
- data/lib/liquid/tags/continue.rb +8 -3
- data/lib/liquid/tags/cycle.rb +25 -14
- data/lib/liquid/tags/decrement.rb +6 -3
- data/lib/liquid/tags/echo.rb +26 -0
- data/lib/liquid/tags/for.rb +68 -44
- data/lib/liquid/tags/if.rb +35 -23
- data/lib/liquid/tags/ifchanged.rb +11 -10
- data/lib/liquid/tags/include.rb +34 -47
- data/lib/liquid/tags/increment.rb +7 -3
- data/lib/liquid/tags/raw.rb +14 -11
- data/lib/liquid/tags/render.rb +84 -0
- data/lib/liquid/tags/table_row.rb +23 -19
- data/lib/liquid/tags/unless.rb +15 -15
- data/lib/liquid/template.rb +55 -71
- data/lib/liquid/template_factory.rb +9 -0
- data/lib/liquid/tokenizer.rb +17 -9
- data/lib/liquid/usage.rb +8 -0
- data/lib/liquid/utils.rb +5 -3
- data/lib/liquid/variable.rb +46 -41
- data/lib/liquid/variable_lookup.rb +8 -6
- data/lib/liquid/version.rb +2 -1
- data/test/integration/assign_test.rb +74 -5
- data/test/integration/blank_test.rb +11 -8
- data/test/integration/block_test.rb +47 -1
- data/test/integration/capture_test.rb +18 -10
- data/test/integration/context_test.rb +608 -5
- data/test/integration/document_test.rb +4 -2
- data/test/integration/drop_test.rb +67 -83
- data/test/integration/error_handling_test.rb +73 -61
- data/test/integration/expression_test.rb +46 -0
- data/test/integration/filter_test.rb +53 -42
- data/test/integration/hash_ordering_test.rb +5 -3
- data/test/integration/output_test.rb +26 -24
- data/test/integration/parsing_quirks_test.rb +19 -7
- data/test/integration/{render_profiling_test.rb → profiler_test.rb} +84 -25
- data/test/integration/security_test.rb +30 -21
- data/test/integration/standard_filter_test.rb +339 -281
- data/test/integration/tag/disableable_test.rb +59 -0
- data/test/integration/tag_test.rb +45 -0
- data/test/integration/tags/break_tag_test.rb +4 -2
- data/test/integration/tags/continue_tag_test.rb +4 -2
- data/test/integration/tags/echo_test.rb +13 -0
- data/test/integration/tags/for_tag_test.rb +107 -51
- data/test/integration/tags/if_else_tag_test.rb +5 -3
- data/test/integration/tags/include_tag_test.rb +70 -54
- data/test/integration/tags/increment_tag_test.rb +4 -2
- data/test/integration/tags/liquid_tag_test.rb +116 -0
- data/test/integration/tags/raw_tag_test.rb +14 -11
- data/test/integration/tags/render_tag_test.rb +213 -0
- data/test/integration/tags/standard_tag_test.rb +38 -31
- data/test/integration/tags/statements_test.rb +23 -21
- data/test/integration/tags/table_row_test.rb +2 -0
- data/test/integration/tags/unless_else_tag_test.rb +4 -2
- data/test/integration/template_test.rb +118 -124
- data/test/integration/trim_mode_test.rb +78 -44
- data/test/integration/variable_test.rb +43 -32
- data/test/test_helper.rb +75 -22
- data/test/unit/block_unit_test.rb +19 -24
- data/test/unit/condition_unit_test.rb +79 -77
- data/test/unit/file_system_unit_test.rb +6 -4
- data/test/unit/i18n_unit_test.rb +7 -5
- data/test/unit/lexer_unit_test.rb +11 -9
- data/test/{integration → unit}/parse_tree_visitor_test.rb +2 -2
- data/test/unit/parser_unit_test.rb +37 -35
- data/test/unit/partial_cache_unit_test.rb +128 -0
- data/test/unit/regexp_unit_test.rb +17 -15
- data/test/unit/static_registers_unit_test.rb +156 -0
- data/test/unit/strainer_factory_unit_test.rb +100 -0
- data/test/unit/strainer_template_unit_test.rb +82 -0
- data/test/unit/tag_unit_test.rb +5 -3
- data/test/unit/tags/case_tag_unit_test.rb +3 -1
- data/test/unit/tags/for_tag_unit_test.rb +4 -2
- data/test/unit/tags/if_tag_unit_test.rb +3 -1
- data/test/unit/template_factory_unit_test.rb +12 -0
- data/test/unit/template_unit_test.rb +19 -10
- data/test/unit/tokenizer_unit_test.rb +19 -17
- data/test/unit/variable_unit_test.rb +51 -49
- metadata +73 -47
- data/lib/liquid/strainer.rb +0 -66
- data/lib/liquid/truffle.rb +0 -5
- data/test/truffle/truffle_test.rb +0 -9
- data/test/unit/context_unit_test.rb +0 -489
- data/test/unit/strainer_unit_test.rb +0 -164
data/lib/liquid/tags/comment.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Liquid
|
2
4
|
class Comment < Block
|
3
|
-
def
|
4
|
-
|
5
|
+
def render_to_output_buffer(_context, output)
|
6
|
+
output
|
5
7
|
end
|
6
8
|
|
7
9
|
def unknown_tag(_tag, _markup, _tokens)
|
@@ -12,5 +14,5 @@ module Liquid
|
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
15
|
-
Template.register_tag('comment'
|
17
|
+
Template.register_tag('comment', Comment)
|
16
18
|
end
|
data/lib/liquid/tags/continue.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Liquid
|
2
4
|
# Continue tag to be used to break out of a for loop.
|
3
5
|
#
|
@@ -9,10 +11,13 @@ module Liquid
|
|
9
11
|
# {% endfor %}
|
10
12
|
#
|
11
13
|
class Continue < Tag
|
12
|
-
|
13
|
-
|
14
|
+
INTERRUPT = ContinueInterrupt.new.freeze
|
15
|
+
|
16
|
+
def render_to_output_buffer(context, output)
|
17
|
+
context.push_interrupt(INTERRUPT)
|
18
|
+
output
|
14
19
|
end
|
15
20
|
end
|
16
21
|
|
17
|
-
Template.register_tag('continue'
|
22
|
+
Template.register_tag('continue', Continue)
|
18
23
|
end
|
data/lib/liquid/tags/cycle.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Liquid
|
2
4
|
# Cycle is usually used within a loop to alternate between values, like colors or DOM classes.
|
3
5
|
#
|
@@ -21,28 +23,37 @@ module Liquid
|
|
21
23
|
super
|
22
24
|
case markup
|
23
25
|
when NamedSyntax
|
24
|
-
@variables = variables_from_string(
|
25
|
-
@name
|
26
|
+
@variables = variables_from_string(Regexp.last_match(2))
|
27
|
+
@name = parse_expression(Regexp.last_match(1))
|
26
28
|
when SimpleSyntax
|
27
29
|
@variables = variables_from_string(markup)
|
28
|
-
@name
|
30
|
+
@name = @variables.to_s
|
29
31
|
else
|
30
|
-
raise SyntaxError
|
32
|
+
raise SyntaxError, options[:locale].t("errors.syntax.cycle")
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
|
-
def
|
36
|
+
def render_to_output_buffer(context, output)
|
35
37
|
context.registers[:cycle] ||= {}
|
36
38
|
|
37
|
-
context.
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
key = context.evaluate(@name)
|
40
|
+
iteration = context.registers[:cycle][key].to_i
|
41
|
+
|
42
|
+
val = context.evaluate(@variables[iteration])
|
43
|
+
|
44
|
+
if val.is_a?(Array)
|
45
|
+
val = val.join
|
46
|
+
elsif !val.is_a?(String)
|
47
|
+
val = val.to_s
|
45
48
|
end
|
49
|
+
|
50
|
+
output << val
|
51
|
+
|
52
|
+
iteration += 1
|
53
|
+
iteration = 0 if iteration >= @variables.size
|
54
|
+
|
55
|
+
context.registers[:cycle][key] = iteration
|
56
|
+
output
|
46
57
|
end
|
47
58
|
|
48
59
|
private
|
@@ -50,7 +61,7 @@ module Liquid
|
|
50
61
|
def variables_from_string(markup)
|
51
62
|
markup.split(',').collect do |var|
|
52
63
|
var =~ /\s*(#{QuotedFragment})\s*/o
|
53
|
-
|
64
|
+
Regexp.last_match(1) ? parse_expression(Regexp.last_match(1)) : nil
|
54
65
|
end.compact
|
55
66
|
end
|
56
67
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Liquid
|
2
4
|
# decrement is used in a place where one needs to insert a counter
|
3
5
|
# into a template, and needs the counter to survive across
|
@@ -23,13 +25,14 @@ module Liquid
|
|
23
25
|
@variable = markup.strip
|
24
26
|
end
|
25
27
|
|
26
|
-
def
|
28
|
+
def render_to_output_buffer(context, output)
|
27
29
|
value = context.environments.first[@variable] ||= 0
|
28
30
|
value -= 1
|
29
31
|
context.environments.first[@variable] = value
|
30
|
-
value.to_s
|
32
|
+
output << value.to_s
|
33
|
+
output
|
31
34
|
end
|
32
35
|
end
|
33
36
|
|
34
|
-
Template.register_tag('decrement'
|
37
|
+
Template.register_tag('decrement', Decrement)
|
35
38
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Liquid
|
4
|
+
# Echo outputs an expression
|
5
|
+
#
|
6
|
+
# {% echo monkey %}
|
7
|
+
# {% echo user.name %}
|
8
|
+
#
|
9
|
+
# This is identical to variable output syntax, like {{ foo }}, but works
|
10
|
+
# inside {% liquid %} tags. The full syntax is supported, including filters:
|
11
|
+
#
|
12
|
+
# {% echo user | link %}
|
13
|
+
#
|
14
|
+
class Echo < Tag
|
15
|
+
def initialize(tag_name, markup, parse_context)
|
16
|
+
super
|
17
|
+
@variable = Variable.new(markup, parse_context)
|
18
|
+
end
|
19
|
+
|
20
|
+
def render(context)
|
21
|
+
@variable.render_to_output_buffer(context, +'')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Template.register_tag('echo', Echo)
|
26
|
+
end
|
data/lib/liquid/tags/for.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Liquid
|
2
4
|
# "For" iterates over an array or collection.
|
3
5
|
# Several useful variables are available to you within the loop.
|
@@ -52,13 +54,20 @@ module Liquid
|
|
52
54
|
super
|
53
55
|
@from = @limit = nil
|
54
56
|
parse_with_selected_parser(markup)
|
55
|
-
@for_block =
|
57
|
+
@for_block = new_body
|
56
58
|
@else_block = nil
|
57
59
|
end
|
58
60
|
|
59
61
|
def parse(tokens)
|
60
|
-
|
61
|
-
|
62
|
+
if parse_body(@for_block, tokens)
|
63
|
+
parse_body(@else_block, tokens)
|
64
|
+
end
|
65
|
+
if blank?
|
66
|
+
@else_block&.remove_blank_strings
|
67
|
+
@for_block.remove_blank_strings
|
68
|
+
end
|
69
|
+
@else_block&.freeze
|
70
|
+
@for_block.freeze
|
62
71
|
end
|
63
72
|
|
64
73
|
def nodelist
|
@@ -66,49 +75,53 @@ module Liquid
|
|
66
75
|
end
|
67
76
|
|
68
77
|
def unknown_tag(tag, markup, tokens)
|
69
|
-
return super unless tag == 'else'
|
70
|
-
@else_block =
|
78
|
+
return super unless tag == 'else'
|
79
|
+
@else_block = new_body
|
71
80
|
end
|
72
81
|
|
73
|
-
def
|
82
|
+
def render_to_output_buffer(context, output)
|
74
83
|
segment = collection_segment(context)
|
75
84
|
|
76
85
|
if segment.empty?
|
77
|
-
render_else(context)
|
86
|
+
render_else(context, output)
|
78
87
|
else
|
79
|
-
render_segment(context, segment)
|
88
|
+
render_segment(context, output, segment)
|
80
89
|
end
|
90
|
+
|
91
|
+
output
|
81
92
|
end
|
82
93
|
|
83
94
|
protected
|
84
95
|
|
85
96
|
def lax_parse(markup)
|
86
97
|
if markup =~ Syntax
|
87
|
-
@variable_name
|
88
|
-
collection_name
|
89
|
-
@reversed
|
90
|
-
@name
|
91
|
-
@collection_name =
|
98
|
+
@variable_name = Regexp.last_match(1)
|
99
|
+
collection_name = Regexp.last_match(2)
|
100
|
+
@reversed = !!Regexp.last_match(3)
|
101
|
+
@name = "#{@variable_name}-#{collection_name}"
|
102
|
+
@collection_name = parse_expression(collection_name)
|
92
103
|
markup.scan(TagAttributes) do |key, value|
|
93
104
|
set_attribute(key, value)
|
94
105
|
end
|
95
106
|
else
|
96
|
-
raise SyntaxError
|
107
|
+
raise SyntaxError, options[:locale].t("errors.syntax.for")
|
97
108
|
end
|
98
109
|
end
|
99
110
|
|
100
111
|
def strict_parse(markup)
|
101
112
|
p = Parser.new(markup)
|
102
113
|
@variable_name = p.consume(:id)
|
103
|
-
raise SyntaxError
|
104
|
-
|
105
|
-
|
106
|
-
@collection_name =
|
107
|
-
|
114
|
+
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_in") unless p.id?('in')
|
115
|
+
|
116
|
+
collection_name = p.expression
|
117
|
+
@collection_name = parse_expression(collection_name)
|
118
|
+
|
119
|
+
@name = "#{@variable_name}-#{collection_name}"
|
120
|
+
@reversed = p.id?('reversed')
|
108
121
|
|
109
122
|
while p.look(:id) && p.look(:colon, 1)
|
110
|
-
unless attribute = p.id?('limit'
|
111
|
-
raise SyntaxError
|
123
|
+
unless (attribute = p.id?('limit') || p.id?('offset'))
|
124
|
+
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_attribute")
|
112
125
|
end
|
113
126
|
p.consume
|
114
127
|
set_attribute(attribute, p.expression)
|
@@ -124,14 +137,23 @@ module Liquid
|
|
124
137
|
from = if @from == :continue
|
125
138
|
offsets[@name].to_i
|
126
139
|
else
|
127
|
-
context.evaluate(@from)
|
140
|
+
from_value = context.evaluate(@from)
|
141
|
+
if from_value.nil?
|
142
|
+
0
|
143
|
+
else
|
144
|
+
Utils.to_integer(from_value)
|
145
|
+
end
|
128
146
|
end
|
129
147
|
|
130
148
|
collection = context.evaluate(@collection_name)
|
131
149
|
collection = collection.to_a if collection.is_a?(Range)
|
132
150
|
|
133
|
-
|
134
|
-
to =
|
151
|
+
limit_value = context.evaluate(@limit)
|
152
|
+
to = if limit_value.nil?
|
153
|
+
nil
|
154
|
+
else
|
155
|
+
Utils.to_integer(limit_value) + from
|
156
|
+
end
|
135
157
|
|
136
158
|
segment = Utils.slice_collection(collection, from, to)
|
137
159
|
segment.reverse! if @reversed
|
@@ -141,11 +163,9 @@ module Liquid
|
|
141
163
|
segment
|
142
164
|
end
|
143
165
|
|
144
|
-
def render_segment(context, segment)
|
166
|
+
def render_segment(context, output, segment)
|
145
167
|
for_stack = context.registers[:for_stack] ||= []
|
146
|
-
length
|
147
|
-
|
148
|
-
result = ''
|
168
|
+
length = segment.length
|
149
169
|
|
150
170
|
context.stack do
|
151
171
|
loop_vars = Liquid::ForloopDrop.new(@name, length, for_stack[-1])
|
@@ -153,43 +173,47 @@ module Liquid
|
|
153
173
|
for_stack.push(loop_vars)
|
154
174
|
|
155
175
|
begin
|
156
|
-
context['forloop'
|
176
|
+
context['forloop'] = loop_vars
|
157
177
|
|
158
178
|
segment.each do |item|
|
159
179
|
context[@variable_name] = item
|
160
|
-
|
180
|
+
@for_block.render_to_output_buffer(context, output)
|
161
181
|
loop_vars.send(:increment!)
|
162
182
|
|
163
183
|
# Handle any interrupts if they exist.
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
end
|
184
|
+
next unless context.interrupt?
|
185
|
+
interrupt = context.pop_interrupt
|
186
|
+
break if interrupt.is_a?(BreakInterrupt)
|
187
|
+
next if interrupt.is_a?(ContinueInterrupt)
|
169
188
|
end
|
170
189
|
ensure
|
171
190
|
for_stack.pop
|
172
191
|
end
|
173
192
|
end
|
174
193
|
|
175
|
-
|
194
|
+
output
|
176
195
|
end
|
177
196
|
|
178
197
|
def set_attribute(key, expr)
|
179
198
|
case key
|
180
|
-
when 'offset'
|
181
|
-
@from = if expr == 'continue'
|
199
|
+
when 'offset'
|
200
|
+
@from = if expr == 'continue'
|
201
|
+
Usage.increment('for_offset_continue')
|
182
202
|
:continue
|
183
203
|
else
|
184
|
-
|
204
|
+
parse_expression(expr)
|
185
205
|
end
|
186
|
-
when 'limit'
|
187
|
-
@limit =
|
206
|
+
when 'limit'
|
207
|
+
@limit = parse_expression(expr)
|
188
208
|
end
|
189
209
|
end
|
190
210
|
|
191
|
-
def render_else(context)
|
192
|
-
|
211
|
+
def render_else(context, output)
|
212
|
+
if @else_block
|
213
|
+
@else_block.render_to_output_buffer(context, output)
|
214
|
+
else
|
215
|
+
output
|
216
|
+
end
|
193
217
|
end
|
194
218
|
|
195
219
|
class ParseTreeVisitor < Liquid::ParseTreeVisitor
|
@@ -199,5 +223,5 @@ module Liquid
|
|
199
223
|
end
|
200
224
|
end
|
201
225
|
|
202
|
-
Template.register_tag('for'
|
226
|
+
Template.register_tag('for', For)
|
203
227
|
end
|
data/lib/liquid/tags/if.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Liquid
|
2
4
|
# If is the conditional block
|
3
5
|
#
|
@@ -10,16 +12,16 @@ module Liquid
|
|
10
12
|
# There are {% if count < 5 %} less {% else %} more {% endif %} items than you need.
|
11
13
|
#
|
12
14
|
class If < Block
|
13
|
-
Syntax
|
15
|
+
Syntax = /(#{QuotedFragment})\s*([=!<>a-z_]+)?\s*(#{QuotedFragment})?/o
|
14
16
|
ExpressionsAndOperators = /(?:\b(?:\s?and\s?|\s?or\s?)\b|(?:\s*(?!\b(?:\s?and\s?|\s?or\s?)\b)(?:#{QuotedFragment}|\S+)\s*)+)/o
|
15
|
-
BOOLEAN_OPERATORS
|
17
|
+
BOOLEAN_OPERATORS = %w(and or).freeze
|
16
18
|
|
17
19
|
attr_reader :blocks
|
18
20
|
|
19
21
|
def initialize(tag_name, markup, options)
|
20
22
|
super
|
21
23
|
@blocks = []
|
22
|
-
push_block('if'
|
24
|
+
push_block('if', markup)
|
23
25
|
end
|
24
26
|
|
25
27
|
def nodelist
|
@@ -29,53 +31,63 @@ module Liquid
|
|
29
31
|
def parse(tokens)
|
30
32
|
while parse_body(@blocks.last.attachment, tokens)
|
31
33
|
end
|
34
|
+
@blocks.reverse_each do |block|
|
35
|
+
block.attachment.remove_blank_strings if blank?
|
36
|
+
block.attachment.freeze
|
37
|
+
end
|
32
38
|
end
|
33
39
|
|
40
|
+
ELSE_TAG_NAMES = ['elsif', 'else'].freeze
|
41
|
+
private_constant :ELSE_TAG_NAMES
|
42
|
+
|
34
43
|
def unknown_tag(tag, markup, tokens)
|
35
|
-
if
|
44
|
+
if ELSE_TAG_NAMES.include?(tag)
|
36
45
|
push_block(tag, markup)
|
37
46
|
else
|
38
47
|
super
|
39
48
|
end
|
40
49
|
end
|
41
50
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
return block.attachment.render(context)
|
47
|
-
end
|
51
|
+
def render_to_output_buffer(context, output)
|
52
|
+
@blocks.each do |block|
|
53
|
+
if block.evaluate(context)
|
54
|
+
return block.attachment.render_to_output_buffer(context, output)
|
48
55
|
end
|
49
|
-
''.freeze
|
50
56
|
end
|
57
|
+
|
58
|
+
output
|
51
59
|
end
|
52
60
|
|
53
61
|
private
|
54
62
|
|
55
63
|
def push_block(tag, markup)
|
56
|
-
block = if tag == 'else'
|
64
|
+
block = if tag == 'else'
|
57
65
|
ElseCondition.new
|
58
66
|
else
|
59
67
|
parse_with_selected_parser(markup)
|
60
68
|
end
|
61
69
|
|
62
70
|
@blocks.push(block)
|
63
|
-
block.attach(
|
71
|
+
block.attach(new_body)
|
72
|
+
end
|
73
|
+
|
74
|
+
def parse_expression(markup)
|
75
|
+
Condition.parse_expression(parse_context, markup)
|
64
76
|
end
|
65
77
|
|
66
78
|
def lax_parse(markup)
|
67
79
|
expressions = markup.scan(ExpressionsAndOperators)
|
68
|
-
raise
|
80
|
+
raise SyntaxError, options[:locale].t("errors.syntax.if") unless expressions.pop =~ Syntax
|
69
81
|
|
70
|
-
condition = Condition.new(
|
82
|
+
condition = Condition.new(parse_expression(Regexp.last_match(1)), Regexp.last_match(2), parse_expression(Regexp.last_match(3)))
|
71
83
|
|
72
84
|
until expressions.empty?
|
73
85
|
operator = expressions.pop.to_s.strip
|
74
86
|
|
75
|
-
raise
|
87
|
+
raise SyntaxError, options[:locale].t("errors.syntax.if") unless expressions.pop.to_s =~ Syntax
|
76
88
|
|
77
|
-
new_condition = Condition.new(
|
78
|
-
raise
|
89
|
+
new_condition = Condition.new(parse_expression(Regexp.last_match(1)), Regexp.last_match(2), parse_expression(Regexp.last_match(3)))
|
90
|
+
raise SyntaxError, options[:locale].t("errors.syntax.if") unless BOOLEAN_OPERATORS.include?(operator)
|
79
91
|
new_condition.send(operator, condition)
|
80
92
|
condition = new_condition
|
81
93
|
end
|
@@ -93,7 +105,7 @@ module Liquid
|
|
93
105
|
def parse_binary_comparisons(p)
|
94
106
|
condition = parse_comparison(p)
|
95
107
|
first_condition = condition
|
96
|
-
while op = (p.id?('and'
|
108
|
+
while (op = (p.id?('and') || p.id?('or')))
|
97
109
|
child_condition = parse_comparison(p)
|
98
110
|
condition.send(op, child_condition)
|
99
111
|
condition = child_condition
|
@@ -102,9 +114,9 @@ module Liquid
|
|
102
114
|
end
|
103
115
|
|
104
116
|
def parse_comparison(p)
|
105
|
-
a =
|
106
|
-
if op = p.consume?(:comparison)
|
107
|
-
b =
|
117
|
+
a = parse_expression(p.expression)
|
118
|
+
if (op = p.consume?(:comparison))
|
119
|
+
b = parse_expression(p.expression)
|
108
120
|
Condition.new(a, op, b)
|
109
121
|
else
|
110
122
|
Condition.new(a)
|
@@ -118,5 +130,5 @@ module Liquid
|
|
118
130
|
end
|
119
131
|
end
|
120
132
|
|
121
|
-
Template.register_tag('if'
|
133
|
+
Template.register_tag('if', If)
|
122
134
|
end
|