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/condition.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Liquid
|
2
4
|
# Container for liquid nodes which conveniently wraps decision making logic
|
3
5
|
#
|
@@ -8,34 +10,53 @@ module Liquid
|
|
8
10
|
#
|
9
11
|
class Condition #:nodoc:
|
10
12
|
@@operators = {
|
11
|
-
'=='
|
12
|
-
'!='
|
13
|
-
'<>'
|
14
|
-
'<'
|
15
|
-
'>'
|
16
|
-
'>='
|
17
|
-
'<='
|
18
|
-
'contains'
|
13
|
+
'==' => ->(cond, left, right) { cond.send(:equal_variables, left, right) },
|
14
|
+
'!=' => ->(cond, left, right) { !cond.send(:equal_variables, left, right) },
|
15
|
+
'<>' => ->(cond, left, right) { !cond.send(:equal_variables, left, right) },
|
16
|
+
'<' => :<,
|
17
|
+
'>' => :>,
|
18
|
+
'>=' => :>=,
|
19
|
+
'<=' => :<=,
|
20
|
+
'contains' => lambda do |_cond, left, right|
|
19
21
|
if left && right && left.respond_to?(:include?)
|
20
22
|
right = right.to_s if left.is_a?(String)
|
21
23
|
left.include?(right)
|
22
24
|
else
|
23
25
|
false
|
24
26
|
end
|
27
|
+
end,
|
28
|
+
}
|
29
|
+
|
30
|
+
class MethodLiteral
|
31
|
+
attr_reader :method_name, :to_s
|
32
|
+
|
33
|
+
def initialize(method_name, to_s)
|
34
|
+
@method_name = method_name
|
35
|
+
@to_s = to_s
|
25
36
|
end
|
37
|
+
end
|
38
|
+
|
39
|
+
@@method_literals = {
|
40
|
+
'blank' => MethodLiteral.new(:blank?, '').freeze,
|
41
|
+
'empty' => MethodLiteral.new(:empty?, '').freeze,
|
26
42
|
}
|
27
43
|
|
28
44
|
def self.operators
|
29
45
|
@@operators
|
30
46
|
end
|
31
47
|
|
48
|
+
def self.parse_expression(parse_context, markup)
|
49
|
+
@@method_literals[markup] || parse_context.parse_expression(markup)
|
50
|
+
end
|
51
|
+
|
32
52
|
attr_reader :attachment, :child_condition
|
33
53
|
attr_accessor :left, :operator, :right
|
34
54
|
|
35
55
|
def initialize(left = nil, operator = nil, right = nil)
|
36
|
-
@left
|
56
|
+
@left = left
|
37
57
|
@operator = operator
|
38
|
-
@right
|
58
|
+
@right = right
|
59
|
+
|
39
60
|
@child_relation = nil
|
40
61
|
@child_condition = nil
|
41
62
|
end
|
@@ -60,12 +81,12 @@ module Liquid
|
|
60
81
|
end
|
61
82
|
|
62
83
|
def or(condition)
|
63
|
-
@child_relation
|
84
|
+
@child_relation = :or
|
64
85
|
@child_condition = condition
|
65
86
|
end
|
66
87
|
|
67
88
|
def and(condition)
|
68
|
-
@child_relation
|
89
|
+
@child_relation = :and
|
69
90
|
@child_condition = condition
|
70
91
|
end
|
71
92
|
|
@@ -78,7 +99,7 @@ module Liquid
|
|
78
99
|
end
|
79
100
|
|
80
101
|
def inspect
|
81
|
-
"#<Condition #{[@left, @operator, @right].compact.join(' '
|
102
|
+
"#<Condition #{[@left, @operator, @right].compact.join(' ')}>"
|
82
103
|
end
|
83
104
|
|
84
105
|
protected
|
@@ -88,7 +109,7 @@ module Liquid
|
|
88
109
|
private
|
89
110
|
|
90
111
|
def equal_variables(left, right)
|
91
|
-
if left.is_a?(
|
112
|
+
if left.is_a?(MethodLiteral)
|
92
113
|
if right.respond_to?(left.method_name)
|
93
114
|
return right.send(left.method_name)
|
94
115
|
else
|
@@ -96,7 +117,7 @@ module Liquid
|
|
96
117
|
end
|
97
118
|
end
|
98
119
|
|
99
|
-
if right.is_a?(
|
120
|
+
if right.is_a?(MethodLiteral)
|
100
121
|
if left.respond_to?(right.method_name)
|
101
122
|
return left.send(right.method_name)
|
102
123
|
else
|
@@ -113,10 +134,10 @@ module Liquid
|
|
113
134
|
# return this as the result.
|
114
135
|
return context.evaluate(left) if op.nil?
|
115
136
|
|
116
|
-
left
|
137
|
+
left = context.evaluate(left)
|
117
138
|
right = context.evaluate(right)
|
118
139
|
|
119
|
-
operation = self.class.operators[op] || raise(Liquid::ArgumentError
|
140
|
+
operation = self.class.operators[op] || raise(Liquid::ArgumentError, "Unknown operator #{op}")
|
120
141
|
|
121
142
|
if operation.respond_to?(:call)
|
122
143
|
operation.call(self, left, right)
|
@@ -124,7 +145,7 @@ module Liquid
|
|
124
145
|
begin
|
125
146
|
left.send(operation, right)
|
126
147
|
rescue ::ArgumentError => e
|
127
|
-
raise Liquid::ArgumentError
|
148
|
+
raise Liquid::ArgumentError, e.message
|
128
149
|
end
|
129
150
|
end
|
130
151
|
end
|
data/lib/liquid/context.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Liquid
|
2
4
|
# Context keeps the variable stack and resolves variables, as well as keywords
|
3
5
|
#
|
@@ -12,37 +14,49 @@ module Liquid
|
|
12
14
|
#
|
13
15
|
# context['bob'] #=> nil class Context
|
14
16
|
class Context
|
15
|
-
attr_reader :scopes, :errors, :registers, :environments, :resource_limits
|
17
|
+
attr_reader :scopes, :errors, :registers, :environments, :resource_limits, :static_registers, :static_environments
|
16
18
|
attr_accessor :exception_renderer, :template_name, :partial, :global_filter, :strict_variables, :strict_filters
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
@errors = []
|
23
|
-
@partial = false
|
24
|
-
@strict_variables = false
|
25
|
-
@resource_limits = resource_limits || ResourceLimits.new(Template.default_resource_limits)
|
26
|
-
squash_instance_assigns_with_environments
|
20
|
+
# rubocop:disable Metrics/ParameterLists
|
21
|
+
def self.build(environments: {}, outer_scope: {}, registers: {}, rethrow_errors: false, resource_limits: nil, static_environments: {}, &block)
|
22
|
+
new(environments, outer_scope, registers, rethrow_errors, resource_limits, static_environments, &block)
|
23
|
+
end
|
27
24
|
|
28
|
-
|
25
|
+
def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil, static_environments = {})
|
26
|
+
@environments = [environments]
|
27
|
+
@environments.flatten!
|
28
|
+
|
29
|
+
@static_environments = [static_environments].flat_map(&:freeze).freeze
|
30
|
+
@scopes = [(outer_scope || {})]
|
31
|
+
@registers = registers
|
32
|
+
@errors = []
|
33
|
+
@partial = false
|
34
|
+
@strict_variables = false
|
35
|
+
@resource_limits = resource_limits || ResourceLimits.new(Template.default_resource_limits)
|
36
|
+
@base_scope_depth = 0
|
37
|
+
@interrupts = []
|
38
|
+
@filters = []
|
39
|
+
@global_filter = nil
|
40
|
+
@disabled_tags = {}
|
29
41
|
|
30
42
|
self.exception_renderer = Template.default_exception_renderer
|
31
43
|
if rethrow_errors
|
32
|
-
self.exception_renderer =
|
44
|
+
self.exception_renderer = Liquid::RAISE_EXCEPTION_LAMBDA
|
33
45
|
end
|
34
46
|
|
35
|
-
|
36
|
-
|
37
|
-
|
47
|
+
yield self if block_given?
|
48
|
+
|
49
|
+
# Do this last, since it could result in this object being passed to a Proc in the environment
|
50
|
+
squash_instance_assigns_with_environments
|
38
51
|
end
|
52
|
+
# rubocop:enable Metrics/ParameterLists
|
39
53
|
|
40
54
|
def warnings
|
41
55
|
@warnings ||= []
|
42
56
|
end
|
43
57
|
|
44
58
|
def strainer
|
45
|
-
@strainer ||=
|
59
|
+
@strainer ||= StrainerFactory.create(self, @filters)
|
46
60
|
end
|
47
61
|
|
48
62
|
# Adds filters to this context.
|
@@ -77,7 +91,7 @@ module Liquid
|
|
77
91
|
def handle_error(e, line_number = nil)
|
78
92
|
e = internal_error unless e.is_a?(Liquid::Error)
|
79
93
|
e.template_name ||= template_name
|
80
|
-
e.line_number
|
94
|
+
e.line_number ||= line_number
|
81
95
|
errors.push(e)
|
82
96
|
exception_renderer.call(e).to_s
|
83
97
|
end
|
@@ -89,7 +103,7 @@ module Liquid
|
|
89
103
|
# Push new local scope on the stack. use <tt>Context#stack</tt> instead
|
90
104
|
def push(new_scope = {})
|
91
105
|
@scopes.unshift(new_scope)
|
92
|
-
|
106
|
+
check_overflow
|
93
107
|
end
|
94
108
|
|
95
109
|
# Merge a hash of variables in the current local scope
|
@@ -111,19 +125,31 @@ module Liquid
|
|
111
125
|
# end
|
112
126
|
#
|
113
127
|
# context['var] #=> nil
|
114
|
-
def stack(new_scope =
|
115
|
-
|
116
|
-
if new_scope
|
117
|
-
push(new_scope)
|
118
|
-
@this_stack_used = true
|
119
|
-
else
|
120
|
-
@this_stack_used = false
|
121
|
-
end
|
122
|
-
|
128
|
+
def stack(new_scope = {})
|
129
|
+
push(new_scope)
|
123
130
|
yield
|
124
131
|
ensure
|
125
|
-
pop
|
126
|
-
|
132
|
+
pop
|
133
|
+
end
|
134
|
+
|
135
|
+
# Creates a new context inheriting resource limits, filters, environment etc.,
|
136
|
+
# but with an isolated scope.
|
137
|
+
def new_isolated_subcontext
|
138
|
+
check_overflow
|
139
|
+
|
140
|
+
self.class.build(
|
141
|
+
resource_limits: resource_limits,
|
142
|
+
static_environments: static_environments,
|
143
|
+
registers: StaticRegisters.new(registers)
|
144
|
+
).tap do |subcontext|
|
145
|
+
subcontext.base_scope_depth = base_scope_depth + 1
|
146
|
+
subcontext.exception_renderer = exception_renderer
|
147
|
+
subcontext.filters = @filters
|
148
|
+
subcontext.strainer = nil
|
149
|
+
subcontext.errors = errors
|
150
|
+
subcontext.warnings = warnings
|
151
|
+
subcontext.disabled_tags = @disabled_tags
|
152
|
+
end
|
127
153
|
end
|
128
154
|
|
129
155
|
def clear_instance_assigns
|
@@ -132,10 +158,6 @@ module Liquid
|
|
132
158
|
|
133
159
|
# Only allow String, Numeric, Hash, Array, Proc, Boolean or <tt>Liquid::Drop</tt>
|
134
160
|
def []=(key, value)
|
135
|
-
unless @this_stack_used
|
136
|
-
@this_stack_used = true
|
137
|
-
push({})
|
138
|
-
end
|
139
161
|
@scopes[0][key] = value
|
140
162
|
end
|
141
163
|
|
@@ -164,26 +186,14 @@ module Liquid
|
|
164
186
|
# This was changed from find() to find_index() because this is a very hot
|
165
187
|
# path and find_index() is optimized in MRI to reduce object allocation
|
166
188
|
index = @scopes.find_index { |s| s.key?(key) }
|
167
|
-
scope = @scopes[index] if index
|
168
|
-
|
169
|
-
variable = nil
|
170
189
|
|
171
|
-
if
|
172
|
-
@
|
173
|
-
|
174
|
-
|
175
|
-
# then it is the value we are looking for.
|
176
|
-
if !variable.nil? || @strict_variables && raise_on_not_found
|
177
|
-
scope = e
|
178
|
-
break
|
179
|
-
end
|
180
|
-
end
|
190
|
+
variable = if index
|
191
|
+
lookup_and_evaluate(@scopes[index], key, raise_on_not_found: raise_on_not_found)
|
192
|
+
else
|
193
|
+
try_variable_find_in_environments(key, raise_on_not_found: raise_on_not_found)
|
181
194
|
end
|
182
195
|
|
183
|
-
|
184
|
-
variable ||= lookup_and_evaluate(scope, key, raise_on_not_found: raise_on_not_found)
|
185
|
-
|
186
|
-
variable = variable.to_liquid
|
196
|
+
variable = variable.to_liquid
|
187
197
|
variable.context = self if variable.respond_to?(:context=)
|
188
198
|
|
189
199
|
variable
|
@@ -197,14 +207,59 @@ module Liquid
|
|
197
207
|
value = obj[key]
|
198
208
|
|
199
209
|
if value.is_a?(Proc) && obj.respond_to?(:[]=)
|
200
|
-
obj[key] =
|
210
|
+
obj[key] = value.arity == 0 ? value.call : value.call(self)
|
201
211
|
else
|
202
212
|
value
|
203
213
|
end
|
204
214
|
end
|
205
215
|
|
216
|
+
def with_disabled_tags(tag_names)
|
217
|
+
tag_names.each do |name|
|
218
|
+
@disabled_tags[name] = @disabled_tags.fetch(name, 0) + 1
|
219
|
+
end
|
220
|
+
yield
|
221
|
+
ensure
|
222
|
+
tag_names.each do |name|
|
223
|
+
@disabled_tags[name] -= 1
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def tag_disabled?(tag_name)
|
228
|
+
@disabled_tags.fetch(tag_name, 0) > 0
|
229
|
+
end
|
230
|
+
|
231
|
+
protected
|
232
|
+
|
233
|
+
attr_writer :base_scope_depth, :warnings, :errors, :strainer, :filters, :disabled_tags
|
234
|
+
|
206
235
|
private
|
207
236
|
|
237
|
+
attr_reader :base_scope_depth
|
238
|
+
|
239
|
+
def try_variable_find_in_environments(key, raise_on_not_found:)
|
240
|
+
@environments.each do |environment|
|
241
|
+
found_variable = lookup_and_evaluate(environment, key, raise_on_not_found: raise_on_not_found)
|
242
|
+
if !found_variable.nil? || @strict_variables && raise_on_not_found
|
243
|
+
return found_variable
|
244
|
+
end
|
245
|
+
end
|
246
|
+
@static_environments.each do |environment|
|
247
|
+
found_variable = lookup_and_evaluate(environment, key, raise_on_not_found: raise_on_not_found)
|
248
|
+
if !found_variable.nil? || @strict_variables && raise_on_not_found
|
249
|
+
return found_variable
|
250
|
+
end
|
251
|
+
end
|
252
|
+
nil
|
253
|
+
end
|
254
|
+
|
255
|
+
def check_overflow
|
256
|
+
raise StackLevelError, "Nesting too deep" if overflow?
|
257
|
+
end
|
258
|
+
|
259
|
+
def overflow?
|
260
|
+
base_scope_depth + @scopes.length > Block::MAX_DEPTH
|
261
|
+
end
|
262
|
+
|
208
263
|
def internal_error
|
209
264
|
# raise and catch to set backtrace and cause on exception
|
210
265
|
raise Liquid::InternalError, 'internal'
|
data/lib/liquid/document.rb
CHANGED
@@ -1,26 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Liquid
|
2
|
-
class Document
|
4
|
+
class Document
|
3
5
|
def self.parse(tokens, parse_context)
|
4
|
-
doc = new
|
6
|
+
doc = new(parse_context)
|
5
7
|
doc.parse(tokens, parse_context)
|
6
8
|
doc
|
7
9
|
end
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
attr_reader :parse_context, :body
|
12
|
+
|
13
|
+
def initialize(parse_context)
|
14
|
+
@parse_context = parse_context
|
15
|
+
@body = new_body
|
16
|
+
end
|
17
|
+
|
18
|
+
def nodelist
|
19
|
+
@body.nodelist
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse(tokenizer, parse_context)
|
23
|
+
while parse_body(tokenizer)
|
12
24
|
end
|
25
|
+
@body.freeze
|
13
26
|
rescue SyntaxError => e
|
14
27
|
e.line_number ||= parse_context.line_number
|
15
28
|
raise
|
16
29
|
end
|
17
30
|
|
18
|
-
def unknown_tag(tag,
|
31
|
+
def unknown_tag(tag, _markup, _tokenizer)
|
19
32
|
case tag
|
20
|
-
when 'else'
|
21
|
-
raise SyntaxError
|
33
|
+
when 'else', 'end'
|
34
|
+
raise SyntaxError, parse_context.locale.t("errors.syntax.unexpected_outer_tag", tag: tag)
|
22
35
|
else
|
23
|
-
raise SyntaxError
|
36
|
+
raise SyntaxError, parse_context.locale.t("errors.syntax.unknown_tag", tag: tag)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def render_to_output_buffer(context, output)
|
41
|
+
@body.render_to_output_buffer(context, output)
|
42
|
+
end
|
43
|
+
|
44
|
+
def render(context)
|
45
|
+
render_to_output_buffer(context, +'')
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def new_body
|
51
|
+
parse_context.new_block_body
|
52
|
+
end
|
53
|
+
|
54
|
+
def parse_body(tokenizer)
|
55
|
+
@body.parse(tokenizer, parse_context) do |unknown_tag_name, unknown_tag_markup|
|
56
|
+
if unknown_tag_name
|
57
|
+
unknown_tag(unknown_tag_name, unknown_tag_markup, tokenizer)
|
58
|
+
true
|
59
|
+
else
|
60
|
+
false
|
61
|
+
end
|
24
62
|
end
|
25
63
|
end
|
26
64
|
end
|
data/lib/liquid/drop.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'set'
|
2
4
|
|
3
5
|
module Liquid
|
@@ -25,7 +27,7 @@ module Liquid
|
|
25
27
|
|
26
28
|
# Catch all for the method
|
27
29
|
def liquid_method_missing(method)
|
28
|
-
return nil unless @context
|
30
|
+
return nil unless @context&.strict_variables
|
29
31
|
raise Liquid::UndefinedDropMethod, "undefined method #{method}"
|
30
32
|
end
|
31
33
|
|
@@ -67,7 +69,7 @@ module Liquid
|
|
67
69
|
|
68
70
|
if include?(Enumerable)
|
69
71
|
blacklist += Enumerable.public_instance_methods
|
70
|
-
blacklist -= [:sort, :count, :first, :min, :max
|
72
|
+
blacklist -= [:sort, :count, :first, :min, :max]
|
71
73
|
end
|
72
74
|
|
73
75
|
whitelist = [:to_liquid] + (public_instance_methods - blacklist)
|