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.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +33 -0
  3. data/README.md +6 -0
  4. data/lib/liquid.rb +17 -5
  5. data/lib/liquid/block.rb +31 -14
  6. data/lib/liquid/block_body.rb +164 -54
  7. data/lib/liquid/condition.rb +39 -18
  8. data/lib/liquid/context.rb +106 -51
  9. data/lib/liquid/document.rb +47 -9
  10. data/lib/liquid/drop.rb +4 -2
  11. data/lib/liquid/errors.rb +20 -18
  12. data/lib/liquid/expression.rb +29 -34
  13. data/lib/liquid/extensions.rb +2 -0
  14. data/lib/liquid/file_system.rb +6 -4
  15. data/lib/liquid/forloop_drop.rb +11 -4
  16. data/lib/liquid/i18n.rb +5 -3
  17. data/lib/liquid/interrupts.rb +3 -1
  18. data/lib/liquid/lexer.rb +30 -23
  19. data/lib/liquid/locales/en.yml +3 -1
  20. data/lib/liquid/parse_context.rb +16 -4
  21. data/lib/liquid/parse_tree_visitor.rb +2 -2
  22. data/lib/liquid/parser.rb +30 -18
  23. data/lib/liquid/parser_switching.rb +17 -3
  24. data/lib/liquid/partial_cache.rb +24 -0
  25. data/lib/liquid/profiler.rb +67 -86
  26. data/lib/liquid/profiler/hooks.rb +26 -14
  27. data/lib/liquid/range_lookup.rb +5 -3
  28. data/lib/liquid/register.rb +6 -0
  29. data/lib/liquid/resource_limits.rb +47 -8
  30. data/lib/liquid/standardfilters.rb +63 -44
  31. data/lib/liquid/static_registers.rb +44 -0
  32. data/lib/liquid/strainer_factory.rb +36 -0
  33. data/lib/liquid/strainer_template.rb +53 -0
  34. data/lib/liquid/tablerowloop_drop.rb +6 -4
  35. data/lib/liquid/tag.rb +28 -6
  36. data/lib/liquid/tag/disableable.rb +22 -0
  37. data/lib/liquid/tag/disabler.rb +21 -0
  38. data/lib/liquid/tags/assign.rb +24 -10
  39. data/lib/liquid/tags/break.rb +8 -3
  40. data/lib/liquid/tags/capture.rb +11 -8
  41. data/lib/liquid/tags/case.rb +33 -27
  42. data/lib/liquid/tags/comment.rb +5 -3
  43. data/lib/liquid/tags/continue.rb +8 -3
  44. data/lib/liquid/tags/cycle.rb +25 -14
  45. data/lib/liquid/tags/decrement.rb +6 -3
  46. data/lib/liquid/tags/echo.rb +26 -0
  47. data/lib/liquid/tags/for.rb +68 -44
  48. data/lib/liquid/tags/if.rb +35 -23
  49. data/lib/liquid/tags/ifchanged.rb +11 -10
  50. data/lib/liquid/tags/include.rb +34 -47
  51. data/lib/liquid/tags/increment.rb +7 -3
  52. data/lib/liquid/tags/raw.rb +14 -11
  53. data/lib/liquid/tags/render.rb +84 -0
  54. data/lib/liquid/tags/table_row.rb +23 -19
  55. data/lib/liquid/tags/unless.rb +15 -15
  56. data/lib/liquid/template.rb +55 -71
  57. data/lib/liquid/template_factory.rb +9 -0
  58. data/lib/liquid/tokenizer.rb +17 -9
  59. data/lib/liquid/usage.rb +8 -0
  60. data/lib/liquid/utils.rb +5 -3
  61. data/lib/liquid/variable.rb +46 -41
  62. data/lib/liquid/variable_lookup.rb +8 -6
  63. data/lib/liquid/version.rb +2 -1
  64. data/test/integration/assign_test.rb +74 -5
  65. data/test/integration/blank_test.rb +11 -8
  66. data/test/integration/block_test.rb +47 -1
  67. data/test/integration/capture_test.rb +18 -10
  68. data/test/integration/context_test.rb +608 -5
  69. data/test/integration/document_test.rb +4 -2
  70. data/test/integration/drop_test.rb +67 -83
  71. data/test/integration/error_handling_test.rb +73 -61
  72. data/test/integration/expression_test.rb +46 -0
  73. data/test/integration/filter_test.rb +53 -42
  74. data/test/integration/hash_ordering_test.rb +5 -3
  75. data/test/integration/output_test.rb +26 -24
  76. data/test/integration/parsing_quirks_test.rb +19 -7
  77. data/test/integration/{render_profiling_test.rb → profiler_test.rb} +84 -25
  78. data/test/integration/security_test.rb +30 -21
  79. data/test/integration/standard_filter_test.rb +339 -281
  80. data/test/integration/tag/disableable_test.rb +59 -0
  81. data/test/integration/tag_test.rb +45 -0
  82. data/test/integration/tags/break_tag_test.rb +4 -2
  83. data/test/integration/tags/continue_tag_test.rb +4 -2
  84. data/test/integration/tags/echo_test.rb +13 -0
  85. data/test/integration/tags/for_tag_test.rb +107 -51
  86. data/test/integration/tags/if_else_tag_test.rb +5 -3
  87. data/test/integration/tags/include_tag_test.rb +70 -54
  88. data/test/integration/tags/increment_tag_test.rb +4 -2
  89. data/test/integration/tags/liquid_tag_test.rb +116 -0
  90. data/test/integration/tags/raw_tag_test.rb +14 -11
  91. data/test/integration/tags/render_tag_test.rb +213 -0
  92. data/test/integration/tags/standard_tag_test.rb +38 -31
  93. data/test/integration/tags/statements_test.rb +23 -21
  94. data/test/integration/tags/table_row_test.rb +2 -0
  95. data/test/integration/tags/unless_else_tag_test.rb +4 -2
  96. data/test/integration/template_test.rb +118 -124
  97. data/test/integration/trim_mode_test.rb +78 -44
  98. data/test/integration/variable_test.rb +43 -32
  99. data/test/test_helper.rb +75 -22
  100. data/test/unit/block_unit_test.rb +19 -24
  101. data/test/unit/condition_unit_test.rb +79 -77
  102. data/test/unit/file_system_unit_test.rb +6 -4
  103. data/test/unit/i18n_unit_test.rb +7 -5
  104. data/test/unit/lexer_unit_test.rb +11 -9
  105. data/test/{integration → unit}/parse_tree_visitor_test.rb +2 -2
  106. data/test/unit/parser_unit_test.rb +37 -35
  107. data/test/unit/partial_cache_unit_test.rb +128 -0
  108. data/test/unit/regexp_unit_test.rb +17 -15
  109. data/test/unit/static_registers_unit_test.rb +156 -0
  110. data/test/unit/strainer_factory_unit_test.rb +100 -0
  111. data/test/unit/strainer_template_unit_test.rb +82 -0
  112. data/test/unit/tag_unit_test.rb +5 -3
  113. data/test/unit/tags/case_tag_unit_test.rb +3 -1
  114. data/test/unit/tags/for_tag_unit_test.rb +4 -2
  115. data/test/unit/tags/if_tag_unit_test.rb +3 -1
  116. data/test/unit/template_factory_unit_test.rb +12 -0
  117. data/test/unit/template_unit_test.rb +19 -10
  118. data/test/unit/tokenizer_unit_test.rb +19 -17
  119. data/test/unit/variable_unit_test.rb +51 -49
  120. metadata +73 -47
  121. data/lib/liquid/strainer.rb +0 -66
  122. data/lib/liquid/truffle.rb +0 -5
  123. data/test/truffle/truffle_test.rb +0 -9
  124. data/test/unit/context_unit_test.rb +0 -489
  125. data/test/unit/strainer_unit_test.rb +0 -164
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Liquid
2
4
  class Comment < Block
3
- def render(_context)
4
- ''.freeze
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'.freeze, Comment)
17
+ Template.register_tag('comment', Comment)
16
18
  end
@@ -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
- def interrupt
13
- ContinueInterrupt.new
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'.freeze, Continue)
22
+ Template.register_tag('continue', Continue)
18
23
  end
@@ -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($2)
25
- @name = Expression.parse($1)
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 = @variables.to_s
30
+ @name = @variables.to_s
29
31
  else
30
- raise SyntaxError.new(options[:locale].t("errors.syntax.cycle".freeze))
32
+ raise SyntaxError, options[:locale].t("errors.syntax.cycle")
31
33
  end
32
34
  end
33
35
 
34
- def render(context)
36
+ def render_to_output_buffer(context, output)
35
37
  context.registers[:cycle] ||= {}
36
38
 
37
- context.stack do
38
- key = context.evaluate(@name)
39
- iteration = context.registers[:cycle][key].to_i
40
- result = context.evaluate(@variables[iteration])
41
- iteration += 1
42
- iteration = 0 if iteration >= @variables.size
43
- context.registers[:cycle][key] = iteration
44
- result
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
- $1 ? Expression.parse($1) : nil
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 render(context)
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'.freeze, 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
@@ -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 = BlockBody.new
57
+ @for_block = new_body
56
58
  @else_block = nil
57
59
  end
58
60
 
59
61
  def parse(tokens)
60
- return unless parse_body(@for_block, tokens)
61
- parse_body(@else_block, tokens)
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'.freeze
70
- @else_block = BlockBody.new
78
+ return super unless tag == 'else'
79
+ @else_block = new_body
71
80
  end
72
81
 
73
- def render(context)
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 = $1
88
- collection_name = $2
89
- @reversed = !!$3
90
- @name = "#{@variable_name}-#{collection_name}"
91
- @collection_name = Expression.parse(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.new(options[:locale].t("errors.syntax.for".freeze))
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.new(options[:locale].t("errors.syntax.for_invalid_in".freeze)) unless p.id?('in'.freeze)
104
- collection_name = p.expression
105
- @name = "#{@variable_name}-#{collection_name}"
106
- @collection_name = Expression.parse(collection_name)
107
- @reversed = p.id?('reversed'.freeze)
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'.freeze) || p.id?('offset'.freeze)
111
- raise SyntaxError.new(options[:locale].t("errors.syntax.for_invalid_attribute".freeze))
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).to_i
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
- limit = context.evaluate(@limit)
134
- to = limit ? limit.to_i + from : nil
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 = segment.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'.freeze] = loop_vars
176
+ context['forloop'] = loop_vars
157
177
 
158
178
  segment.each do |item|
159
179
  context[@variable_name] = item
160
- result << @for_block.render(context)
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
- if context.interrupt?
165
- interrupt = context.pop_interrupt
166
- break if interrupt.is_a? BreakInterrupt
167
- next if interrupt.is_a? ContinueInterrupt
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
- result
194
+ output
176
195
  end
177
196
 
178
197
  def set_attribute(key, expr)
179
198
  case key
180
- when 'offset'.freeze
181
- @from = if expr == 'continue'.freeze
199
+ when 'offset'
200
+ @from = if expr == 'continue'
201
+ Usage.increment('for_offset_continue')
182
202
  :continue
183
203
  else
184
- Expression.parse(expr)
204
+ parse_expression(expr)
185
205
  end
186
- when 'limit'.freeze
187
- @limit = Expression.parse(expr)
206
+ when 'limit'
207
+ @limit = parse_expression(expr)
188
208
  end
189
209
  end
190
210
 
191
- def render_else(context)
192
- @else_block ? @else_block.render(context) : ''.freeze
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'.freeze, For)
226
+ Template.register_tag('for', For)
203
227
  end
@@ -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 = /(#{QuotedFragment})\s*([=!<>a-z_]+)?\s*(#{QuotedFragment})?/o
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 = %w(and or).freeze
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'.freeze, markup)
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 ['elsif'.freeze, 'else'.freeze].include?(tag)
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 render(context)
43
- context.stack do
44
- @blocks.each do |block|
45
- if block.evaluate(context)
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'.freeze
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(BlockBody.new)
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(SyntaxError.new(options[:locale].t("errors.syntax.if".freeze))) unless expressions.pop =~ Syntax
80
+ raise SyntaxError, options[:locale].t("errors.syntax.if") unless expressions.pop =~ Syntax
69
81
 
70
- condition = Condition.new(Expression.parse($1), $2, Expression.parse($3))
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(SyntaxError.new(options[:locale].t("errors.syntax.if".freeze))) unless expressions.pop.to_s =~ Syntax
87
+ raise SyntaxError, options[:locale].t("errors.syntax.if") unless expressions.pop.to_s =~ Syntax
76
88
 
77
- new_condition = Condition.new(Expression.parse($1), $2, Expression.parse($3))
78
- raise(SyntaxError.new(options[:locale].t("errors.syntax.if".freeze))) unless BOOLEAN_OPERATORS.include?(operator)
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'.freeze) || p.id?('or'.freeze))
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 = Expression.parse(p.expression)
106
- if op = p.consume?(:comparison)
107
- b = Expression.parse(p.expression)
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'.freeze, If)
133
+ Template.register_tag('if', If)
122
134
  end