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
data/lib/liquid/tags/break.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module Liquid
|
2
|
-
|
3
2
|
# Break tag to be used to break out of a for loop.
|
4
3
|
#
|
5
4
|
# == Basic Usage:
|
@@ -10,11 +9,9 @@ module Liquid
|
|
10
9
|
# {% endfor %}
|
11
10
|
#
|
12
11
|
class Break < Tag
|
13
|
-
|
14
12
|
def interrupt
|
15
13
|
BreakInterrupt.new
|
16
14
|
end
|
17
|
-
|
18
15
|
end
|
19
16
|
|
20
17
|
Template.register_tag('break'.freeze, Break)
|
data/lib/liquid/tags/capture.rb
CHANGED
data/lib/liquid/tags/case.rb
CHANGED
@@ -8,18 +8,24 @@ module Liquid
|
|
8
8
|
@blocks = []
|
9
9
|
|
10
10
|
if markup =~ Syntax
|
11
|
-
@left = $1
|
11
|
+
@left = Expression.parse($1)
|
12
12
|
else
|
13
13
|
raise SyntaxError.new(options[:locale].t("errors.syntax.case".freeze))
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
def parse(tokens)
|
18
|
+
body = BlockBody.new
|
19
|
+
while parse_body(body, tokens)
|
20
|
+
body = @blocks.last.attachment
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
17
24
|
def nodelist
|
18
|
-
@blocks.
|
25
|
+
@blocks.map(&:attachment)
|
19
26
|
end
|
20
27
|
|
21
28
|
def unknown_tag(tag, markup, tokens)
|
22
|
-
@nodelist = []
|
23
29
|
case tag
|
24
30
|
when 'when'.freeze
|
25
31
|
record_when_condition(markup)
|
@@ -37,10 +43,10 @@ module Liquid
|
|
37
43
|
output = ''
|
38
44
|
@blocks.each do |block|
|
39
45
|
if block.else?
|
40
|
-
return
|
46
|
+
return block.attachment.render(context) if execute_else_block
|
41
47
|
elsif block.evaluate(context)
|
42
48
|
execute_else_block = false
|
43
|
-
output <<
|
49
|
+
output << block.attachment.render(context)
|
44
50
|
end
|
45
51
|
end
|
46
52
|
output
|
@@ -50,27 +56,28 @@ module Liquid
|
|
50
56
|
private
|
51
57
|
|
52
58
|
def record_when_condition(markup)
|
59
|
+
body = BlockBody.new
|
60
|
+
|
53
61
|
while markup
|
54
|
-
|
55
|
-
if not markup =~ WhenSyntax
|
62
|
+
unless markup =~ WhenSyntax
|
56
63
|
raise SyntaxError.new(options[:locale].t("errors.syntax.case_invalid_when".freeze))
|
57
64
|
end
|
58
65
|
|
59
66
|
markup = $2
|
60
67
|
|
61
|
-
block = Condition.new(@left, '=='.freeze, $1)
|
62
|
-
block.attach(
|
63
|
-
@blocks
|
68
|
+
block = Condition.new(@left, '=='.freeze, Expression.parse($1))
|
69
|
+
block.attach(body)
|
70
|
+
@blocks << block
|
64
71
|
end
|
65
72
|
end
|
66
73
|
|
67
74
|
def record_else_condition(markup)
|
68
|
-
|
75
|
+
unless markup.strip.empty?
|
69
76
|
raise SyntaxError.new(options[:locale].t("errors.syntax.case_invalid_else".freeze))
|
70
77
|
end
|
71
78
|
|
72
79
|
block = ElseCondition.new
|
73
|
-
block.attach(
|
80
|
+
block.attach(BlockBody.new)
|
74
81
|
@blocks << block
|
75
82
|
end
|
76
83
|
end
|
data/lib/liquid/tags/comment.rb
CHANGED
data/lib/liquid/tags/cycle.rb
CHANGED
@@ -20,10 +20,10 @@ module Liquid
|
|
20
20
|
case markup
|
21
21
|
when NamedSyntax
|
22
22
|
@variables = variables_from_string($2)
|
23
|
-
@name = $1
|
23
|
+
@name = Expression.parse($1)
|
24
24
|
when SimpleSyntax
|
25
25
|
@variables = variables_from_string(markup)
|
26
|
-
@name =
|
26
|
+
@name = @variables.to_s
|
27
27
|
else
|
28
28
|
raise SyntaxError.new(options[:locale].t("errors.syntax.cycle".freeze))
|
29
29
|
end
|
@@ -33,11 +33,11 @@ module Liquid
|
|
33
33
|
context.registers[:cycle] ||= Hash.new(0)
|
34
34
|
|
35
35
|
context.stack do
|
36
|
-
key = context
|
36
|
+
key = context.evaluate(@name)
|
37
37
|
iteration = context.registers[:cycle][key]
|
38
|
-
result = context
|
38
|
+
result = context.evaluate(@variables[iteration])
|
39
39
|
iteration += 1
|
40
|
-
iteration = 0
|
40
|
+
iteration = 0 if iteration >= @variables.size
|
41
41
|
context.registers[:cycle][key] = iteration
|
42
42
|
result
|
43
43
|
end
|
@@ -48,7 +48,7 @@ module Liquid
|
|
48
48
|
def variables_from_string(markup)
|
49
49
|
markup.split(',').collect do |var|
|
50
50
|
var =~ /\s*(#{QuotedFragment})\s*/o
|
51
|
-
$1 ? $1 : nil
|
51
|
+
$1 ? Expression.parse($1) : nil
|
52
52
|
end.compact
|
53
53
|
end
|
54
54
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module Liquid
|
2
|
-
|
3
2
|
# decrement is used in a place where one needs to insert a counter
|
4
3
|
# into a template, and needs the counter to survive across
|
5
4
|
# multiple instantiations of the template.
|
@@ -26,12 +25,10 @@ module Liquid
|
|
26
25
|
|
27
26
|
def render(context)
|
28
27
|
value = context.environments.first[@variable] ||= 0
|
29
|
-
value
|
28
|
+
value -= 1
|
30
29
|
context.environments.first[@variable] = value
|
31
30
|
value.to_s
|
32
31
|
end
|
33
|
-
|
34
|
-
private
|
35
32
|
end
|
36
33
|
|
37
34
|
Template.register_tag('decrement'.freeze, Decrement)
|
data/lib/liquid/tags/for.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module Liquid
|
2
|
-
|
3
2
|
# "For" iterates over an array or collection.
|
4
3
|
# Several useful variables are available to you within the loop.
|
5
4
|
#
|
@@ -42,6 +41,7 @@ module Liquid
|
|
42
41
|
# where 0 is the last item.
|
43
42
|
# forloop.first:: Returns true if the item is the first item.
|
44
43
|
# forloop.last:: Returns true if the item is the last item.
|
44
|
+
# forloop.parentloop:: Provides access to the parent loop, if present.
|
45
45
|
#
|
46
46
|
class For < Block
|
47
47
|
Syntax = /\A(#{VariableSegment}+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/o
|
@@ -49,78 +49,31 @@ module Liquid
|
|
49
49
|
def initialize(tag_name, markup, options)
|
50
50
|
super
|
51
51
|
parse_with_selected_parser(markup)
|
52
|
-
@
|
52
|
+
@for_block = BlockBody.new
|
53
|
+
end
|
54
|
+
|
55
|
+
def parse(tokens)
|
56
|
+
return unless parse_body(@for_block, tokens)
|
57
|
+
parse_body(@else_block, tokens)
|
53
58
|
end
|
54
59
|
|
55
60
|
def nodelist
|
56
|
-
|
57
|
-
@for_block + @else_block
|
58
|
-
else
|
59
|
-
@for_block
|
60
|
-
end
|
61
|
+
@else_block ? [@for_block, @else_block] : [@for_block]
|
61
62
|
end
|
62
63
|
|
63
64
|
def unknown_tag(tag, markup, tokens)
|
64
65
|
return super unless tag == 'else'.freeze
|
65
|
-
@
|
66
|
+
@else_block = BlockBody.new
|
66
67
|
end
|
67
68
|
|
68
69
|
def render(context)
|
69
|
-
|
70
|
-
|
71
|
-
collection = context[@collection_name]
|
72
|
-
collection = collection.to_a if collection.is_a?(Range)
|
73
|
-
|
74
|
-
# Maintains Ruby 1.8.7 String#each behaviour on 1.9
|
75
|
-
return render_else(context) unless iterable?(collection)
|
70
|
+
segment = collection_segment(context)
|
76
71
|
|
77
|
-
|
78
|
-
context
|
72
|
+
if segment.empty?
|
73
|
+
render_else(context)
|
79
74
|
else
|
80
|
-
context
|
75
|
+
render_segment(context, segment)
|
81
76
|
end
|
82
|
-
|
83
|
-
limit = context[@attributes['limit'.freeze]]
|
84
|
-
to = limit ? limit.to_i + from : nil
|
85
|
-
|
86
|
-
segment = Utils.slice_collection(collection, from, to)
|
87
|
-
|
88
|
-
return render_else(context) if segment.empty?
|
89
|
-
|
90
|
-
segment.reverse! if @reversed
|
91
|
-
|
92
|
-
result = ''
|
93
|
-
|
94
|
-
length = segment.length
|
95
|
-
|
96
|
-
# Store our progress through the collection for the continue flag
|
97
|
-
context.registers[:for][@name] = from + segment.length
|
98
|
-
|
99
|
-
context.stack do
|
100
|
-
segment.each_with_index do |item, index|
|
101
|
-
context[@variable_name] = item
|
102
|
-
context['forloop'.freeze] = {
|
103
|
-
'name'.freeze => @name,
|
104
|
-
'length'.freeze => length,
|
105
|
-
'index'.freeze => index + 1,
|
106
|
-
'index0'.freeze => index,
|
107
|
-
'rindex'.freeze => length - index,
|
108
|
-
'rindex0'.freeze => length - index - 1,
|
109
|
-
'first'.freeze => (index == 0),
|
110
|
-
'last'.freeze => (index == length - 1)
|
111
|
-
}
|
112
|
-
|
113
|
-
result << render_all(@for_block, context)
|
114
|
-
|
115
|
-
# Handle any interrupts if they exist.
|
116
|
-
if context.has_interrupt?
|
117
|
-
interrupt = context.pop_interrupt
|
118
|
-
break if interrupt.is_a? BreakInterrupt
|
119
|
-
next if interrupt.is_a? ContinueInterrupt
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
result
|
124
77
|
end
|
125
78
|
|
126
79
|
protected
|
@@ -128,12 +81,12 @@ module Liquid
|
|
128
81
|
def lax_parse(markup)
|
129
82
|
if markup =~ Syntax
|
130
83
|
@variable_name = $1
|
131
|
-
|
132
|
-
@
|
133
|
-
@
|
134
|
-
@
|
84
|
+
collection_name = $2
|
85
|
+
@reversed = !!$3
|
86
|
+
@name = "#{@variable_name}-#{collection_name}"
|
87
|
+
@collection_name = Expression.parse(collection_name)
|
135
88
|
markup.scan(TagAttributes) do |key, value|
|
136
|
-
|
89
|
+
set_attribute(key, value)
|
137
90
|
end
|
138
91
|
else
|
139
92
|
raise SyntaxError.new(options[:locale].t("errors.syntax.for".freeze))
|
@@ -143,31 +96,96 @@ module Liquid
|
|
143
96
|
def strict_parse(markup)
|
144
97
|
p = Parser.new(markup)
|
145
98
|
@variable_name = p.consume(:id)
|
146
|
-
raise SyntaxError.new(options[:locale].t("errors.syntax.for_invalid_in".freeze))
|
147
|
-
|
148
|
-
@name = "#{@variable_name}-#{
|
99
|
+
raise SyntaxError.new(options[:locale].t("errors.syntax.for_invalid_in".freeze)) unless p.id?('in'.freeze)
|
100
|
+
collection_name = p.expression
|
101
|
+
@name = "#{@variable_name}-#{collection_name}"
|
102
|
+
@collection_name = Expression.parse(collection_name)
|
149
103
|
@reversed = p.id?('reversed'.freeze)
|
150
104
|
|
151
|
-
@attributes = {}
|
152
105
|
while p.look(:id) && p.look(:colon, 1)
|
153
106
|
unless attribute = p.id?('limit'.freeze) || p.id?('offset'.freeze)
|
154
107
|
raise SyntaxError.new(options[:locale].t("errors.syntax.for_invalid_attribute".freeze))
|
155
108
|
end
|
156
109
|
p.consume
|
157
|
-
|
158
|
-
@attributes[attribute] = val
|
110
|
+
set_attribute(attribute, p.expression)
|
159
111
|
end
|
160
112
|
p.consume(:end_of_string)
|
161
113
|
end
|
162
114
|
|
163
115
|
private
|
164
116
|
|
165
|
-
def
|
166
|
-
|
117
|
+
def collection_segment(context)
|
118
|
+
offsets = context.registers[:for] ||= Hash.new(0)
|
119
|
+
|
120
|
+
from = if @from == :continue
|
121
|
+
offsets[@name].to_i
|
122
|
+
else
|
123
|
+
context.evaluate(@from).to_i
|
124
|
+
end
|
125
|
+
|
126
|
+
collection = context.evaluate(@collection_name)
|
127
|
+
collection = collection.to_a if collection.is_a?(Range)
|
128
|
+
|
129
|
+
limit = context.evaluate(@limit)
|
130
|
+
to = limit ? limit.to_i + from : nil
|
131
|
+
|
132
|
+
segment = Utils.slice_collection(collection, from, to)
|
133
|
+
segment.reverse! if @reversed
|
134
|
+
|
135
|
+
offsets[@name] = from + segment.length
|
136
|
+
|
137
|
+
segment
|
167
138
|
end
|
168
139
|
|
169
|
-
def
|
170
|
-
|
140
|
+
def render_segment(context, segment)
|
141
|
+
for_stack = context.registers[:for_stack] ||= []
|
142
|
+
length = segment.length
|
143
|
+
|
144
|
+
result = ''
|
145
|
+
|
146
|
+
context.stack do
|
147
|
+
loop_vars = Liquid::ForloopDrop.new(@name, length, for_stack[-1])
|
148
|
+
|
149
|
+
for_stack.push(loop_vars)
|
150
|
+
|
151
|
+
begin
|
152
|
+
context['forloop'.freeze] = loop_vars
|
153
|
+
|
154
|
+
segment.each_with_index do |item, index|
|
155
|
+
context[@variable_name] = item
|
156
|
+
result << @for_block.render(context)
|
157
|
+
loop_vars.send(:increment!)
|
158
|
+
|
159
|
+
# Handle any interrupts if they exist.
|
160
|
+
if context.interrupt?
|
161
|
+
interrupt = context.pop_interrupt
|
162
|
+
break if interrupt.is_a? BreakInterrupt
|
163
|
+
next if interrupt.is_a? ContinueInterrupt
|
164
|
+
end
|
165
|
+
end
|
166
|
+
ensure
|
167
|
+
for_stack.pop
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
result
|
172
|
+
end
|
173
|
+
|
174
|
+
def set_attribute(key, expr)
|
175
|
+
case key
|
176
|
+
when 'offset'.freeze
|
177
|
+
@from = if expr == 'continue'.freeze
|
178
|
+
:continue
|
179
|
+
else
|
180
|
+
Expression.parse(expr)
|
181
|
+
end
|
182
|
+
when 'limit'.freeze
|
183
|
+
@limit = Expression.parse(expr)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def render_else(context)
|
188
|
+
@else_block ? @else_block.render(context) : ''.freeze
|
171
189
|
end
|
172
190
|
end
|
173
191
|
|
data/lib/liquid/tags/if.rb
CHANGED
@@ -20,8 +20,13 @@ module Liquid
|
|
20
20
|
push_block('if'.freeze, markup)
|
21
21
|
end
|
22
22
|
|
23
|
+
def parse(tokens)
|
24
|
+
while parse_body(@blocks.last.attachment, tokens)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
23
28
|
def nodelist
|
24
|
-
@blocks.
|
29
|
+
@blocks.map(&:attachment)
|
25
30
|
end
|
26
31
|
|
27
32
|
def unknown_tag(tag, markup, tokens)
|
@@ -36,7 +41,7 @@ module Liquid
|
|
36
41
|
context.stack do
|
37
42
|
@blocks.each do |block|
|
38
43
|
if block.evaluate(context)
|
39
|
-
return
|
44
|
+
return block.attachment.render(context)
|
40
45
|
end
|
41
46
|
end
|
42
47
|
''.freeze
|
@@ -45,61 +50,61 @@ module Liquid
|
|
45
50
|
|
46
51
|
private
|
47
52
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
54
|
-
|
55
|
-
@blocks.push(block)
|
56
|
-
@nodelist = block.attach(Array.new)
|
53
|
+
def push_block(tag, markup)
|
54
|
+
block = if tag == 'else'.freeze
|
55
|
+
ElseCondition.new
|
56
|
+
else
|
57
|
+
parse_with_selected_parser(markup)
|
57
58
|
end
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
60
|
+
@blocks.push(block)
|
61
|
+
block.attach(BlockBody.new)
|
62
|
+
end
|
62
63
|
|
63
|
-
|
64
|
+
def lax_parse(markup)
|
65
|
+
expressions = markup.scan(ExpressionsAndOperators)
|
66
|
+
raise(SyntaxError.new(options[:locale].t("errors.syntax.if".freeze))) unless expressions.pop =~ Syntax
|
64
67
|
|
65
|
-
|
66
|
-
operator = expressions.pop.to_s.strip
|
68
|
+
condition = Condition.new(Expression.parse($1), $2, Expression.parse($3))
|
67
69
|
|
68
|
-
|
70
|
+
until expressions.empty?
|
71
|
+
operator = expressions.pop.to_s.strip
|
69
72
|
|
70
|
-
|
71
|
-
raise(SyntaxError.new(options[:locale].t("errors.syntax.if".freeze))) unless BOOLEAN_OPERATORS.include?(operator)
|
72
|
-
new_condition.send(operator, condition)
|
73
|
-
condition = new_condition
|
74
|
-
end
|
73
|
+
raise(SyntaxError.new(options[:locale].t("errors.syntax.if".freeze))) unless expressions.pop.to_s =~ Syntax
|
75
74
|
|
76
|
-
|
75
|
+
new_condition = Condition.new(Expression.parse($1), $2, Expression.parse($3))
|
76
|
+
raise(SyntaxError.new(options[:locale].t("errors.syntax.if".freeze))) unless BOOLEAN_OPERATORS.include?(operator)
|
77
|
+
new_condition.send(operator, condition)
|
78
|
+
condition = new_condition
|
77
79
|
end
|
78
80
|
|
79
|
-
|
80
|
-
|
81
|
-
condition = parse_binary_comparison(p)
|
82
|
-
p.consume(:end_of_string)
|
83
|
-
condition
|
84
|
-
end
|
81
|
+
condition
|
82
|
+
end
|
85
83
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
84
|
+
def strict_parse(markup)
|
85
|
+
p = Parser.new(markup)
|
86
|
+
condition = parse_binary_comparison(p)
|
87
|
+
p.consume(:end_of_string)
|
88
|
+
condition
|
89
|
+
end
|
90
|
+
|
91
|
+
def parse_binary_comparison(p)
|
92
|
+
condition = parse_comparison(p)
|
93
|
+
if op = (p.id?('and'.freeze) || p.id?('or'.freeze))
|
94
|
+
condition.send(op, parse_binary_comparison(p))
|
92
95
|
end
|
96
|
+
condition
|
97
|
+
end
|
93
98
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
99
|
+
def parse_comparison(p)
|
100
|
+
a = Expression.parse(p.expression)
|
101
|
+
if op = p.consume?(:comparison)
|
102
|
+
b = Expression.parse(p.expression)
|
103
|
+
Condition.new(a, op, b)
|
104
|
+
else
|
105
|
+
Condition.new(a)
|
102
106
|
end
|
107
|
+
end
|
103
108
|
end
|
104
109
|
|
105
110
|
Template.register_tag('if'.freeze, If)
|