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/template.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Liquid
|
2
4
|
# Templates are central to liquid.
|
3
5
|
# Interpretating templates is a two step process. First you compile the
|
@@ -16,13 +18,11 @@ module Liquid
|
|
16
18
|
attr_accessor :root
|
17
19
|
attr_reader :resource_limits, :warnings
|
18
20
|
|
19
|
-
@@file_system = BlankFileSystem.new
|
20
|
-
|
21
21
|
class TagRegistry
|
22
22
|
include Enumerable
|
23
23
|
|
24
24
|
def initialize
|
25
|
-
@tags
|
25
|
+
@tags = {}
|
26
26
|
@cache = {}
|
27
27
|
end
|
28
28
|
|
@@ -50,7 +50,7 @@ module Liquid
|
|
50
50
|
private
|
51
51
|
|
52
52
|
def lookup_class(name)
|
53
|
-
|
53
|
+
Object.const_get(name)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
@@ -61,76 +61,53 @@ module Liquid
|
|
61
61
|
# :lax acts like liquid 2.5 and silently ignores malformed tags in most cases.
|
62
62
|
# :warn is the default and will give deprecation warnings when invalid syntax is used.
|
63
63
|
# :strict will enforce correct syntax.
|
64
|
-
|
65
|
-
|
66
|
-
# Sets how strict the taint checker should be.
|
67
|
-
# :lax is the default, and ignores the taint flag completely
|
68
|
-
# :warn adds a warning, but does not interrupt the rendering
|
69
|
-
# :error raises an error when tainted output is used
|
70
|
-
attr_writer :taint_mode
|
64
|
+
attr_accessor :error_mode
|
65
|
+
Template.error_mode = :lax
|
71
66
|
|
72
67
|
attr_accessor :default_exception_renderer
|
73
68
|
Template.default_exception_renderer = lambda do |exception|
|
74
69
|
exception
|
75
70
|
end
|
76
71
|
|
77
|
-
|
78
|
-
|
79
|
-
end
|
72
|
+
attr_accessor :file_system
|
73
|
+
Template.file_system = BlankFileSystem.new
|
80
74
|
|
81
|
-
|
82
|
-
|
83
|
-
|
75
|
+
attr_accessor :tags
|
76
|
+
Template.tags = TagRegistry.new
|
77
|
+
private :tags=
|
84
78
|
|
85
79
|
def register_tag(name, klass)
|
86
80
|
tags[name.to_s] = klass
|
87
81
|
end
|
88
82
|
|
89
|
-
def tags
|
90
|
-
@tags ||= TagRegistry.new
|
91
|
-
end
|
92
|
-
|
93
|
-
def error_mode
|
94
|
-
@error_mode ||= :lax
|
95
|
-
end
|
96
|
-
|
97
|
-
def taint_mode
|
98
|
-
@taint_mode ||= :lax
|
99
|
-
end
|
100
|
-
|
101
83
|
# Pass a module with filter methods which should be available
|
102
84
|
# to all liquid views. Good for registering the standard library
|
103
85
|
def register_filter(mod)
|
104
|
-
|
86
|
+
StrainerFactory.add_global_filter(mod)
|
105
87
|
end
|
106
88
|
|
107
|
-
|
108
|
-
|
109
|
-
|
89
|
+
attr_accessor :default_resource_limits
|
90
|
+
Template.default_resource_limits = {}
|
91
|
+
private :default_resource_limits=
|
110
92
|
|
111
93
|
# creates a new <tt>Template</tt> object from liquid source code
|
112
94
|
# To enable profiling, pass in <tt>profile: true</tt> as an option.
|
113
95
|
# See Liquid::Profiler for more information
|
114
96
|
def parse(source, options = {})
|
115
|
-
|
116
|
-
template.parse(source, options)
|
97
|
+
new.parse(source, options)
|
117
98
|
end
|
118
99
|
end
|
119
100
|
|
120
101
|
def initialize
|
121
|
-
@rethrow_errors
|
122
|
-
@resource_limits = ResourceLimits.new(
|
102
|
+
@rethrow_errors = false
|
103
|
+
@resource_limits = ResourceLimits.new(Template.default_resource_limits)
|
123
104
|
end
|
124
105
|
|
125
106
|
# Parse source code.
|
126
107
|
# Returns self for easy chaining
|
127
108
|
def parse(source, options = {})
|
128
|
-
|
129
|
-
@
|
130
|
-
@line_numbers = options[:line_numbers] || @profiling
|
131
|
-
parse_context = options.is_a?(ParseContext) ? options : ParseContext.new(options)
|
132
|
-
@root = Document.parse(tokenize(source), parse_context)
|
133
|
-
@warnings = parse_context.warnings
|
109
|
+
parse_context = configure_options(options)
|
110
|
+
@root = Document.parse(tokenize(source), parse_context)
|
134
111
|
self
|
135
112
|
end
|
136
113
|
|
@@ -165,19 +142,19 @@ module Liquid
|
|
165
142
|
# filters and tags and might be useful to integrate liquid more with its host application
|
166
143
|
#
|
167
144
|
def render(*args)
|
168
|
-
return ''
|
145
|
+
return '' if @root.nil?
|
169
146
|
|
170
147
|
context = case args.first
|
171
148
|
when Liquid::Context
|
172
149
|
c = args.shift
|
173
150
|
|
174
151
|
if @rethrow_errors
|
175
|
-
c.exception_renderer =
|
152
|
+
c.exception_renderer = Liquid::RAISE_EXCEPTION_LAMBDA
|
176
153
|
end
|
177
154
|
|
178
155
|
c
|
179
156
|
when Liquid::Drop
|
180
|
-
drop
|
157
|
+
drop = args.shift
|
181
158
|
drop.context = Context.new([drop, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits)
|
182
159
|
when Hash
|
183
160
|
Context.new([args.shift, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits)
|
@@ -187,11 +164,18 @@ module Liquid
|
|
187
164
|
raise ArgumentError, "Expected Hash or Liquid::Context as parameter"
|
188
165
|
end
|
189
166
|
|
167
|
+
output = nil
|
168
|
+
|
169
|
+
context_register = context.registers.is_a?(StaticRegisters) ? context.registers.static : context.registers
|
170
|
+
|
190
171
|
case args.last
|
191
172
|
when Hash
|
192
173
|
options = args.pop
|
174
|
+
output = options[:output] if options[:output]
|
193
175
|
|
194
|
-
|
176
|
+
options[:registers]&.each do |key, register|
|
177
|
+
context_register[key] = register
|
178
|
+
end
|
195
179
|
|
196
180
|
apply_options_to_context(context, options)
|
197
181
|
when Module, Array
|
@@ -201,13 +185,13 @@ module Liquid
|
|
201
185
|
# Retrying a render resets resource usage
|
202
186
|
context.resource_limits.reset
|
203
187
|
|
188
|
+
if @profiling && context.profiler.nil?
|
189
|
+
@profiler = context.profiler = Liquid::Profiler.new
|
190
|
+
end
|
191
|
+
|
204
192
|
begin
|
205
193
|
# render the nodelist.
|
206
|
-
|
207
|
-
result = with_profiling(context) do
|
208
|
-
@root.render(context)
|
209
|
-
end
|
210
|
-
result.respond_to?(:join) ? result.join : result
|
194
|
+
@root.render_to_output_buffer(context, output || +'')
|
211
195
|
rescue Liquid::MemoryError => e
|
212
196
|
context.handle_error(e)
|
213
197
|
ensure
|
@@ -220,35 +204,35 @@ module Liquid
|
|
220
204
|
render(*args)
|
221
205
|
end
|
222
206
|
|
223
|
-
|
224
|
-
|
225
|
-
def tokenize(source)
|
226
|
-
Tokenizer.new(source, @line_numbers)
|
207
|
+
def render_to_output_buffer(context, output)
|
208
|
+
render(context, output: output)
|
227
209
|
end
|
228
210
|
|
229
|
-
|
230
|
-
|
211
|
+
private
|
212
|
+
|
213
|
+
def configure_options(options)
|
214
|
+
if (profiling = options[:profile])
|
231
215
|
raise "Profiler not loaded, require 'liquid/profiler' first" unless defined?(Liquid::Profiler)
|
216
|
+
end
|
232
217
|
|
233
|
-
|
234
|
-
|
218
|
+
@options = options
|
219
|
+
@profiling = profiling
|
220
|
+
@line_numbers = options[:line_numbers] || @profiling
|
221
|
+
parse_context = options.is_a?(ParseContext) ? options : ParseContext.new(options)
|
222
|
+
@warnings = parse_context.warnings
|
223
|
+
parse_context
|
224
|
+
end
|
235
225
|
|
236
|
-
|
237
|
-
|
238
|
-
ensure
|
239
|
-
@profiler.stop
|
240
|
-
end
|
241
|
-
else
|
242
|
-
yield
|
243
|
-
end
|
226
|
+
def tokenize(source)
|
227
|
+
Tokenizer.new(source, @line_numbers)
|
244
228
|
end
|
245
229
|
|
246
230
|
def apply_options_to_context(context, options)
|
247
231
|
context.add_filters(options[:filters]) if options[:filters]
|
248
|
-
context.global_filter
|
232
|
+
context.global_filter = options[:global_filter] if options[:global_filter]
|
249
233
|
context.exception_renderer = options[:exception_renderer] if options[:exception_renderer]
|
250
|
-
context.strict_variables
|
251
|
-
context.strict_filters
|
234
|
+
context.strict_variables = options[:strict_variables] if options[:strict_variables]
|
235
|
+
context.strict_filters = options[:strict_filters] if options[:strict_filters]
|
252
236
|
end
|
253
237
|
end
|
254
238
|
end
|
data/lib/liquid/tokenizer.rb
CHANGED
@@ -1,29 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Liquid
|
2
4
|
class Tokenizer
|
3
|
-
attr_reader :line_number
|
5
|
+
attr_reader :line_number, :for_liquid_tag
|
4
6
|
|
5
|
-
def initialize(source, line_numbers = false)
|
6
|
-
@source
|
7
|
-
@line_number
|
8
|
-
@
|
7
|
+
def initialize(source, line_numbers = false, line_number: nil, for_liquid_tag: false)
|
8
|
+
@source = source
|
9
|
+
@line_number = line_number || (line_numbers ? 1 : nil)
|
10
|
+
@for_liquid_tag = for_liquid_tag
|
11
|
+
@tokens = tokenize
|
9
12
|
end
|
10
13
|
|
11
14
|
def shift
|
12
|
-
token = @tokens.shift
|
13
|
-
|
15
|
+
(token = @tokens.shift) || return
|
16
|
+
|
17
|
+
if @line_number
|
18
|
+
@line_number += @for_liquid_tag ? 1 : token.count("\n")
|
19
|
+
end
|
20
|
+
|
14
21
|
token
|
15
22
|
end
|
16
23
|
|
17
24
|
private
|
18
25
|
|
19
26
|
def tokenize
|
20
|
-
@source = @source.source if @source.respond_to?(:source)
|
21
27
|
return [] if @source.to_s.empty?
|
22
28
|
|
29
|
+
return @source.split("\n") if @for_liquid_tag
|
30
|
+
|
23
31
|
tokens = @source.split(TemplateParser)
|
24
32
|
|
25
33
|
# removes the rogue empty element at the beginning of the array
|
26
|
-
tokens.shift if tokens[0]
|
34
|
+
tokens.shift if tokens[0]&.empty?
|
27
35
|
|
28
36
|
tokens
|
29
37
|
end
|
data/lib/liquid/usage.rb
ADDED
data/lib/liquid/utils.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Liquid
|
2
4
|
module Utils
|
3
5
|
def self.slice_collection(collection, from, to)
|
@@ -10,7 +12,7 @@ module Liquid
|
|
10
12
|
|
11
13
|
def self.slice_collection_using_each(collection, from, to)
|
12
14
|
segments = []
|
13
|
-
index
|
15
|
+
index = 0
|
14
16
|
|
15
17
|
# Maintains Ruby 1.8.7 String#each behaviour on 1.9
|
16
18
|
if collection.is_a?(String)
|
@@ -50,7 +52,7 @@ module Liquid
|
|
50
52
|
when Numeric
|
51
53
|
obj
|
52
54
|
when String
|
53
|
-
|
55
|
+
/\A-?\d+\.\d+\z/.match?(obj.strip) ? BigDecimal(obj) : obj.to_i
|
54
56
|
else
|
55
57
|
if obj.respond_to?(:to_number)
|
56
58
|
obj.to_number
|
@@ -69,7 +71,7 @@ module Liquid
|
|
69
71
|
end
|
70
72
|
|
71
73
|
case obj
|
72
|
-
when 'now'
|
74
|
+
when 'now', 'today'
|
73
75
|
Time.now
|
74
76
|
when /\A\d+\z/, Integer
|
75
77
|
Time.at(obj.to_i)
|
data/lib/liquid/variable.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Liquid
|
2
4
|
# Holds variables. Variables are only loaded "just in time"
|
3
5
|
# and are not evaluated as part of the render stage
|
@@ -10,10 +12,10 @@ module Liquid
|
|
10
12
|
# {{ user | link }}
|
11
13
|
#
|
12
14
|
class Variable
|
13
|
-
FilterMarkupRegex
|
14
|
-
FilterParser
|
15
|
-
FilterArgsRegex
|
16
|
-
JustTagAttributes
|
15
|
+
FilterMarkupRegex = /#{FilterSeparator}\s*(.*)/om
|
16
|
+
FilterParser = /(?:\s+|#{QuotedFragment}|#{ArgumentSeparator})+/o
|
17
|
+
FilterArgsRegex = /(?:#{FilterArgumentSeparator}|#{ArgumentSeparator})\s*((?:\w+\s*\:\s*)?#{QuotedFragment})/o
|
18
|
+
JustTagAttributes = /\A#{TagAttributes}\z/o
|
17
19
|
MarkupWithQuotedFragment = /(#{QuotedFragment})(.*)/om
|
18
20
|
|
19
21
|
attr_accessor :filters, :name, :line_number
|
@@ -23,12 +25,12 @@ module Liquid
|
|
23
25
|
include ParserSwitching
|
24
26
|
|
25
27
|
def initialize(markup, parse_context)
|
26
|
-
@markup
|
27
|
-
@name
|
28
|
+
@markup = markup
|
29
|
+
@name = nil
|
28
30
|
@parse_context = parse_context
|
29
|
-
@line_number
|
31
|
+
@line_number = parse_context.line_number
|
30
32
|
|
31
|
-
|
33
|
+
strict_parse_with_error_mode_fallback(markup)
|
32
34
|
end
|
33
35
|
|
34
36
|
def raw
|
@@ -43,11 +45,11 @@ module Liquid
|
|
43
45
|
@filters = []
|
44
46
|
return unless markup =~ MarkupWithQuotedFragment
|
45
47
|
|
46
|
-
name_markup
|
47
|
-
filter_markup =
|
48
|
-
@name
|
48
|
+
name_markup = Regexp.last_match(1)
|
49
|
+
filter_markup = Regexp.last_match(2)
|
50
|
+
@name = Expression.parse(name_markup)
|
49
51
|
if filter_markup =~ FilterMarkupRegex
|
50
|
-
filters =
|
52
|
+
filters = Regexp.last_match(1).scan(FilterParser)
|
51
53
|
filters.each do |f|
|
52
54
|
next unless f =~ /\w+/
|
53
55
|
filtername = Regexp.last_match(0)
|
@@ -61,6 +63,8 @@ module Liquid
|
|
61
63
|
@filters = []
|
62
64
|
p = Parser.new(markup)
|
63
65
|
|
66
|
+
return if p.look(:end_of_string)
|
67
|
+
|
64
68
|
@name = Expression.parse(p.expression)
|
65
69
|
while p.consume?(:pipe)
|
66
70
|
filtername = p.consume(:id)
|
@@ -79,37 +83,57 @@ module Liquid
|
|
79
83
|
end
|
80
84
|
|
81
85
|
def render(context)
|
82
|
-
obj =
|
86
|
+
obj = context.evaluate(@name)
|
87
|
+
|
88
|
+
@filters.each do |filter_name, filter_args, filter_kwargs|
|
83
89
|
filter_args = evaluate_filter_expressions(context, filter_args, filter_kwargs)
|
84
|
-
context.invoke(filter_name,
|
90
|
+
obj = context.invoke(filter_name, obj, *filter_args)
|
91
|
+
end
|
92
|
+
|
93
|
+
context.apply_global_filter(obj)
|
94
|
+
end
|
95
|
+
|
96
|
+
def render_to_output_buffer(context, output)
|
97
|
+
obj = render(context)
|
98
|
+
|
99
|
+
if obj.is_a?(Array)
|
100
|
+
output << obj.join
|
101
|
+
elsif obj.nil?
|
102
|
+
else
|
103
|
+
output << obj.to_s
|
85
104
|
end
|
86
105
|
|
87
|
-
|
106
|
+
output
|
107
|
+
end
|
88
108
|
|
89
|
-
|
109
|
+
def disabled?(_context)
|
110
|
+
false
|
111
|
+
end
|
90
112
|
|
91
|
-
|
113
|
+
def disabled_tags
|
114
|
+
[]
|
92
115
|
end
|
93
116
|
|
94
117
|
private
|
95
118
|
|
96
119
|
def parse_filter_expressions(filter_name, unparsed_args)
|
97
|
-
filter_args
|
98
|
-
keyword_args =
|
120
|
+
filter_args = []
|
121
|
+
keyword_args = nil
|
99
122
|
unparsed_args.each do |a|
|
100
|
-
if matches = a.match(JustTagAttributes)
|
123
|
+
if (matches = a.match(JustTagAttributes))
|
124
|
+
keyword_args ||= {}
|
101
125
|
keyword_args[matches[1]] = Expression.parse(matches[2])
|
102
126
|
else
|
103
127
|
filter_args << Expression.parse(a)
|
104
128
|
end
|
105
129
|
end
|
106
130
|
result = [filter_name, filter_args]
|
107
|
-
result << keyword_args
|
131
|
+
result << keyword_args if keyword_args
|
108
132
|
result
|
109
133
|
end
|
110
134
|
|
111
135
|
def evaluate_filter_expressions(context, filter_args, filter_kwargs)
|
112
|
-
parsed_args = filter_args.map{ |expr| context.evaluate(expr) }
|
136
|
+
parsed_args = filter_args.map { |expr| context.evaluate(expr) }
|
113
137
|
if filter_kwargs
|
114
138
|
parsed_kwargs = {}
|
115
139
|
filter_kwargs.each do |key, expr|
|
@@ -120,25 +144,6 @@ module Liquid
|
|
120
144
|
parsed_args
|
121
145
|
end
|
122
146
|
|
123
|
-
def taint_check(context, obj)
|
124
|
-
return unless obj.tainted?
|
125
|
-
return if Template.taint_mode == :lax
|
126
|
-
|
127
|
-
@markup =~ QuotedFragment
|
128
|
-
name = Regexp.last_match(0)
|
129
|
-
|
130
|
-
error = TaintedError.new("variable '#{name}' is tainted and was not escaped")
|
131
|
-
error.line_number = line_number
|
132
|
-
error.template_name = context.template_name
|
133
|
-
|
134
|
-
case Template.taint_mode
|
135
|
-
when :warn
|
136
|
-
context.warnings << error
|
137
|
-
when :error
|
138
|
-
raise error
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
147
|
class ParseTreeVisitor < Liquid::ParseTreeVisitor
|
143
148
|
def children
|
144
149
|
[@node.name] + @node.filters.flatten
|