liquid 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +10 -6
- data/Rakefile +27 -12
- data/lib/extras/liquid_view.rb +27 -16
- data/lib/liquid.rb +3 -3
- data/lib/liquid/block.rb +30 -26
- data/lib/liquid/condition.rb +31 -34
- data/lib/liquid/context.rb +47 -25
- data/lib/liquid/document.rb +7 -7
- data/lib/liquid/drop.rb +17 -16
- data/lib/liquid/htmltags.rb +27 -27
- data/lib/liquid/module_ex.rb +4 -4
- data/lib/liquid/standardfilters.rb +18 -5
- data/lib/liquid/strainer.rb +17 -18
- data/lib/liquid/tag.rb +8 -8
- data/lib/liquid/tags/assign.rb +1 -1
- data/lib/liquid/tags/capture.rb +9 -9
- data/lib/liquid/tags/case.rb +2 -2
- data/lib/liquid/tags/cycle.rb +3 -3
- data/lib/liquid/tags/for.rb +1 -1
- data/lib/liquid/tags/if.rb +3 -2
- data/lib/liquid/tags/include.rb +2 -1
- data/lib/liquid/template.rb +57 -54
- data/lib/liquid/variable.rb +7 -8
- metadata +25 -21
- data/init.rb +0 -8
- data/test/test_helper.rb +0 -20
data/CHANGELOG
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
* Ruby 1.9.1 bugfixes
|
2
|
+
|
3
|
+
* Fix LiquidView for Rails 2.2. Fix local assigns for all versions of Rails
|
4
|
+
|
1
5
|
* Fixed gem install rake task
|
2
6
|
* Improve Error encapsulation in liquid by maintaining a own set of exceptions instead of relying on ruby build ins
|
3
7
|
|
4
8
|
* Added If with or / and expressions
|
5
9
|
|
6
|
-
* Implemented .to_liquid for all objects which can be passed to liquid like Strings Arrays Hashes Numerics and Booleans. To export new objects to liquid just implement .to_liquid on them and return objects which themselves have .to_liquid methods.
|
10
|
+
* Implemented .to_liquid for all objects which can be passed to liquid like Strings Arrays Hashes Numerics and Booleans. To export new objects to liquid just implement .to_liquid on them and return objects which themselves have .to_liquid methods.
|
7
11
|
|
8
12
|
* Added more tags to standard library
|
9
13
|
|
@@ -22,17 +26,17 @@
|
|
22
26
|
* Fixed bug with string filter parameters failing to tolerate commas in strings. [Paul Hammond]
|
23
27
|
|
24
28
|
* Improved filter parameters. Filter parameters are now context sensitive; Types are resolved according to the rules of the context. Multiple parameters are now separated by the Liquid::ArgumentSeparator: , by default [Paul Hammond]
|
25
|
-
|
26
|
-
{{ 'Typo' | link_to: 'http://typo.leetsoft.com', 'Typo - a modern weblog engine' }}
|
27
|
-
|
28
29
|
|
29
|
-
|
30
|
+
{{ 'Typo' | link_to: 'http://typo.leetsoft.com', 'Typo - a modern weblog engine' }}
|
31
|
+
|
32
|
+
|
33
|
+
* Added Liquid::Drop. A base class which you can use for exporting proxy objects to liquid which can acquire more data when used in liquid. [Tobias Luetke]
|
30
34
|
|
31
35
|
class ProductDrop < Liquid::Drop
|
32
36
|
def top_sales
|
33
37
|
Shop.current.products.find(:all, :order => 'sales', :limit => 10 )
|
34
38
|
end
|
35
|
-
end
|
39
|
+
end
|
36
40
|
t = Liquid::Template.parse( ' {% for product in product.top_sales %} {{ product.name }} {% endfor %} ' )
|
37
41
|
t.render('product' => ProductDrop.new )
|
38
42
|
|
data/Rakefile
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'rubygems'
|
3
3
|
require 'rake'
|
4
|
-
require '
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/gempackagetask'
|
5
6
|
|
6
|
-
|
7
|
-
PKG_NAME = "liquid"
|
8
|
-
PKG_DESC = "A secure non evaling end user template engine with aesthetic markup."
|
7
|
+
task :default => 'test'
|
9
8
|
|
10
9
|
Rake::TestTask.new(:test) do |t|
|
11
10
|
t.libs << "lib"
|
@@ -14,11 +13,27 @@ Rake::TestTask.new(:test) do |t|
|
|
14
13
|
t.verbose = false
|
15
14
|
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
16
|
+
gemspec = eval(File.read('liquid.gemspec'))
|
17
|
+
Rake::GemPackageTask.new(gemspec) do |pkg|
|
18
|
+
pkg.gem_spec = gemspec
|
19
|
+
end
|
20
|
+
|
21
|
+
namespace :profile do
|
22
|
+
|
23
|
+
|
24
|
+
task :default => [:run]
|
25
|
+
|
26
|
+
desc "Run the liquid profile/perforamce coverage"
|
27
|
+
task :run do
|
28
|
+
|
29
|
+
ruby "performance/shopify.rb"
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Run KCacheGrind"
|
34
|
+
task :grind => :run do
|
35
|
+
system "kcachegrind /tmp/liquid.rubyprof_calltreeprinter.txt"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
data/lib/extras/liquid_view.rb
CHANGED
@@ -5,32 +5,43 @@
|
|
5
5
|
#
|
6
6
|
# ActionView::Base::register_template_handler :liquid, LiquidView
|
7
7
|
class LiquidView
|
8
|
+
PROTECTED_ASSIGNS = %w( template_root response _session template_class action_name request_origin session template
|
9
|
+
_response url _request _cookies variables_added _flash params _headers request cookies
|
10
|
+
ignore_missing_templates flash _params logger before_filter_chain_aborted headers )
|
11
|
+
PROTECTED_INSTANCE_VARIABLES = %w( @_request @controller @_first_render @_memoized__pick_template @view_paths
|
12
|
+
@helpers @assigns_added @template @_render_stack @template_format @assigns )
|
13
|
+
|
14
|
+
def self.call(template)
|
15
|
+
"LiquidView.new(self).render(template, local_assigns)"
|
16
|
+
end
|
8
17
|
|
9
|
-
def initialize(
|
10
|
-
@
|
18
|
+
def initialize(view)
|
19
|
+
@view = view
|
11
20
|
end
|
12
21
|
|
13
|
-
|
14
|
-
|
15
|
-
@action_view.controller.headers["Content-Type"] ||= 'text/html; charset=utf-8'
|
16
|
-
assigns = @action_view.assigns.dup
|
22
|
+
def render(template, local_assigns = nil)
|
23
|
+
@view.controller.headers["Content-Type"] ||= 'text/html; charset=utf-8'
|
17
24
|
|
18
|
-
#
|
19
|
-
if template.respond_to? :
|
20
|
-
|
21
|
-
|
25
|
+
# Rails 2.2 Template has source, but not locals
|
26
|
+
if template.respond_to?(:source) && !template.respond_to?(:locals)
|
27
|
+
assigns = (@view.instance_variables - PROTECTED_INSTANCE_VARIABLES).inject({}) do |hash, ivar|
|
28
|
+
hash[ivar[1..-1]] = @view.instance_variable_get(ivar)
|
29
|
+
hash
|
30
|
+
end
|
22
31
|
else
|
23
|
-
|
24
|
-
local_assigns = local_assigns_for_rails_less_than_2_1_0
|
32
|
+
assigns = @view.assigns.reject{ |k,v| PROTECTED_ASSIGNS.include?(k) }
|
25
33
|
end
|
26
|
-
|
27
|
-
|
34
|
+
|
35
|
+
source = template.respond_to?(:source) ? template.source : template
|
36
|
+
local_assigns = (template.respond_to?(:locals) ? template.locals : local_assigns) || {}
|
37
|
+
|
38
|
+
if content_for_layout = @view.instance_variable_get("@content_for_layout")
|
28
39
|
assigns['content_for_layout'] = content_for_layout
|
29
40
|
end
|
30
|
-
assigns.merge!(local_assigns)
|
41
|
+
assigns.merge!(local_assigns.stringify_keys)
|
31
42
|
|
32
43
|
liquid = Liquid::Template.parse(source)
|
33
|
-
liquid.render(assigns, :filters => [@
|
44
|
+
liquid.render(assigns, :filters => [@view.controller.master_helper_module], :registers => {:action_view => @view, :controller => @view.controller})
|
34
45
|
end
|
35
46
|
|
36
47
|
def compilable?
|
data/lib/liquid.rb
CHANGED
@@ -29,11 +29,11 @@ module Liquid
|
|
29
29
|
TagStart = /\{\%/
|
30
30
|
TagEnd = /\%\}/
|
31
31
|
VariableSignature = /\(?[\w\-\.\[\]]\)?/
|
32
|
-
VariableSegment = /[\w\-]
|
32
|
+
VariableSegment = /[\w\-]/
|
33
33
|
VariableStart = /\{\{/
|
34
34
|
VariableEnd = /\}\}/
|
35
35
|
VariableIncompleteEnd = /\}\}?/
|
36
|
-
QuotedString = /"[^"]
|
36
|
+
QuotedString = /"[^"]*"|'[^']*'/
|
37
37
|
QuotedFragment = /#{QuotedString}|(?:[^\s,\|'"]|#{QuotedString})+/
|
38
38
|
StrictQuotedFragment = /"[^"]+"|'[^']+'|[^\s,\|,\:,\,]+/
|
39
39
|
FirstFilterArgument = /#{FilterArgumentSeparator}(?:#{StrictQuotedFragment})/
|
@@ -44,7 +44,7 @@ module Liquid
|
|
44
44
|
AnyStartingTag = /\{\{|\{\%/
|
45
45
|
PartialTemplateParser = /#{TagStart}.*?#{TagEnd}|#{VariableStart}.*?#{VariableIncompleteEnd}/
|
46
46
|
TemplateParser = /(#{PartialTemplateParser}|#{AnyStartingTag})/
|
47
|
-
VariableParser = /\[[^\]]+\]|#{VariableSegment}
|
47
|
+
VariableParser = /\[[^\]]+\]|#{VariableSegment}+\??/
|
48
48
|
end
|
49
49
|
|
50
50
|
require 'liquid/drop'
|
data/lib/liquid/block.rb
CHANGED
@@ -1,19 +1,23 @@
|
|
1
1
|
module Liquid
|
2
|
-
|
2
|
+
|
3
3
|
class Block < Tag
|
4
|
+
IsTag = /^#{TagStart}/
|
5
|
+
IsVariable = /^#{VariableStart}/
|
6
|
+
FullToken = /^#{TagStart}\s*(\w+)\s*(.*)?#{TagEnd}$/
|
7
|
+
ContentOfVariable = /^#{VariableStart}(.*)#{VariableEnd}$/
|
4
8
|
|
5
9
|
def parse(tokens)
|
6
10
|
@nodelist ||= []
|
7
11
|
@nodelist.clear
|
8
12
|
|
9
|
-
while token = tokens.shift
|
13
|
+
while token = tokens.shift
|
10
14
|
|
11
15
|
case token
|
12
|
-
when
|
13
|
-
if token =~
|
16
|
+
when IsTag
|
17
|
+
if token =~ FullToken
|
14
18
|
|
15
19
|
# if we found the proper block delimitor just end parsing here and let the outer block
|
16
|
-
# proceed
|
20
|
+
# proceed
|
17
21
|
if block_delimiter == $1
|
18
22
|
end_tag
|
19
23
|
return
|
@@ -23,33 +27,33 @@ module Liquid
|
|
23
27
|
if tag = Template.tags[$1]
|
24
28
|
@nodelist << tag.new($1, $2, tokens)
|
25
29
|
else
|
26
|
-
# this tag is not registered with the system
|
30
|
+
# this tag is not registered with the system
|
27
31
|
# pass it to the current block for special handling or error reporting
|
28
32
|
unknown_tag($1, $2, tokens)
|
29
|
-
end
|
33
|
+
end
|
30
34
|
else
|
31
35
|
raise SyntaxError, "Tag '#{token}' was not properly terminated with regexp: #{TagEnd.inspect} "
|
32
36
|
end
|
33
|
-
when
|
37
|
+
when IsVariable
|
34
38
|
@nodelist << create_variable(token)
|
35
39
|
when ''
|
36
40
|
# pass
|
37
41
|
else
|
38
42
|
@nodelist << token
|
39
43
|
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# Make sure that its ok to end parsing in the current block.
|
43
|
-
# Effectively this method will throw and exception unless the current block is
|
44
|
-
# of type Document
|
44
|
+
end
|
45
|
+
|
46
|
+
# Make sure that its ok to end parsing in the current block.
|
47
|
+
# Effectively this method will throw and exception unless the current block is
|
48
|
+
# of type Document
|
45
49
|
assert_missing_delimitation!
|
46
|
-
end
|
47
|
-
|
48
|
-
def end_tag
|
50
|
+
end
|
51
|
+
|
52
|
+
def end_tag
|
49
53
|
end
|
50
54
|
|
51
55
|
def unknown_tag(tag, params, tokens)
|
52
|
-
case tag
|
56
|
+
case tag
|
53
57
|
when 'else'
|
54
58
|
raise SyntaxError, "#{block_name} tag does not expect else tag"
|
55
59
|
when 'end'
|
@@ -61,14 +65,14 @@ module Liquid
|
|
61
65
|
|
62
66
|
def block_delimiter
|
63
67
|
"end#{block_name}"
|
64
|
-
end
|
68
|
+
end
|
65
69
|
|
66
70
|
def block_name
|
67
71
|
@tag_name
|
68
72
|
end
|
69
73
|
|
70
74
|
def create_variable(token)
|
71
|
-
token.scan(
|
75
|
+
token.scan(ContentOfVariable) do |content|
|
72
76
|
return Variable.new(content.first)
|
73
77
|
end
|
74
78
|
raise SyntaxError.new("Variable '#{token}' was not properly terminated with regexp: #{VariableEnd.inspect} ")
|
@@ -77,7 +81,7 @@ module Liquid
|
|
77
81
|
def render(context)
|
78
82
|
render_all(@nodelist, context)
|
79
83
|
end
|
80
|
-
|
84
|
+
|
81
85
|
protected
|
82
86
|
|
83
87
|
def assert_missing_delimitation!
|
@@ -86,12 +90,12 @@ module Liquid
|
|
86
90
|
|
87
91
|
def render_all(list, context)
|
88
92
|
list.collect do |token|
|
89
|
-
begin
|
93
|
+
begin
|
90
94
|
token.respond_to?(:render) ? token.render(context) : token
|
91
|
-
rescue Exception => e
|
95
|
+
rescue Exception => e
|
92
96
|
context.handle_error(e)
|
93
|
-
end
|
94
|
-
end
|
97
|
+
end
|
98
|
+
end
|
95
99
|
end
|
96
|
-
end
|
97
|
-
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/liquid/condition.rb
CHANGED
@@ -3,7 +3,7 @@ module Liquid
|
|
3
3
|
#
|
4
4
|
# Example:
|
5
5
|
#
|
6
|
-
# c = Condition.new('1', '==', '1')
|
6
|
+
# c = Condition.new('1', '==', '1')
|
7
7
|
# c.evaluate #=> true
|
8
8
|
#
|
9
9
|
class Condition #:nodoc:
|
@@ -15,35 +15,35 @@ module Liquid
|
|
15
15
|
'>' => :>,
|
16
16
|
'>=' => :>=,
|
17
17
|
'<=' => :<=,
|
18
|
-
'contains' => lambda { |cond, left, right| left.include?(right) }
|
18
|
+
'contains' => lambda { |cond, left, right| left && right ? left.include?(right) : false }
|
19
19
|
}
|
20
|
-
|
20
|
+
|
21
21
|
def self.operators
|
22
22
|
@@operators
|
23
23
|
end
|
24
24
|
|
25
25
|
attr_reader :attachment
|
26
26
|
attr_accessor :left, :operator, :right
|
27
|
-
|
27
|
+
|
28
28
|
def initialize(left = nil, operator = nil, right = nil)
|
29
29
|
@left, @operator, @right = left, operator, right
|
30
30
|
@child_relation = nil
|
31
31
|
@child_condition = nil
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
def evaluate(context = Context.new)
|
35
|
-
result = interpret_condition(left, right, operator, context)
|
36
|
-
|
35
|
+
result = interpret_condition(left, right, operator, context)
|
36
|
+
|
37
37
|
case @child_relation
|
38
|
-
when :or
|
38
|
+
when :or
|
39
39
|
result || @child_condition.evaluate(context)
|
40
|
-
when :and
|
40
|
+
when :and
|
41
41
|
result && @child_condition.evaluate(context)
|
42
42
|
else
|
43
43
|
result
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
47
|
def or(condition)
|
48
48
|
@child_relation, @child_condition = :or, condition
|
49
49
|
end
|
@@ -51,25 +51,25 @@ module Liquid
|
|
51
51
|
def and(condition)
|
52
52
|
@child_relation, @child_condition = :and, condition
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
def attach(attachment)
|
56
56
|
@attachment = attachment
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
def else?
|
60
60
|
false
|
61
|
-
end
|
62
|
-
|
61
|
+
end
|
62
|
+
|
63
63
|
def inspect
|
64
64
|
"#<Condition #{[@left, @operator, @right].compact.join(' ')}>"
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
private
|
68
|
-
|
68
|
+
|
69
69
|
def equal_variables(left, right)
|
70
70
|
if left.is_a?(Symbol)
|
71
71
|
if right.respond_to?(left)
|
72
|
-
return right.send(left.to_s)
|
72
|
+
return right.send(left.to_s)
|
73
73
|
else
|
74
74
|
return nil
|
75
75
|
end
|
@@ -77,47 +77,44 @@ module Liquid
|
|
77
77
|
|
78
78
|
if right.is_a?(Symbol)
|
79
79
|
if left.respond_to?(right)
|
80
|
-
return left.send(right.to_s)
|
80
|
+
return left.send(right.to_s)
|
81
81
|
else
|
82
82
|
return nil
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
-
left == right
|
87
|
-
end
|
86
|
+
left == right
|
87
|
+
end
|
88
88
|
|
89
89
|
def interpret_condition(left, right, op, context)
|
90
|
-
|
91
|
-
#
|
92
|
-
# a single variable. We can just poll this variable from the context and
|
90
|
+
# If the operator is empty this means that the decision statement is just
|
91
|
+
# a single variable. We can just poll this variable from the context and
|
93
92
|
# return this as the result.
|
94
|
-
return context[left] if op == nil
|
93
|
+
return context[left] if op == nil
|
95
94
|
|
96
95
|
left, right = context[left], context[right]
|
97
|
-
|
98
96
|
|
99
97
|
operation = self.class.operators[op] || raise(ArgumentError.new("Unknown operator #{op}"))
|
100
98
|
|
101
99
|
if operation.respond_to?(:call)
|
102
100
|
operation.call(self, left, right)
|
103
|
-
elsif left.respond_to?(operation) and right.respond_to?(operation)
|
101
|
+
elsif left.respond_to?(operation) and right.respond_to?(operation)
|
104
102
|
left.send(operation, right)
|
105
103
|
else
|
106
104
|
nil
|
107
105
|
end
|
108
|
-
end
|
109
|
-
end
|
106
|
+
end
|
107
|
+
end
|
110
108
|
|
111
109
|
|
112
110
|
class ElseCondition < Condition
|
113
|
-
|
114
|
-
def else?
|
111
|
+
def else?
|
115
112
|
true
|
116
113
|
end
|
117
|
-
|
114
|
+
|
118
115
|
def evaluate(context)
|
119
116
|
true
|
120
117
|
end
|
121
118
|
end
|
122
119
|
|
123
|
-
end
|
120
|
+
end
|
data/lib/liquid/context.rb
CHANGED
@@ -13,14 +13,15 @@ module Liquid
|
|
13
13
|
#
|
14
14
|
# context['bob'] #=> nil class Context
|
15
15
|
class Context
|
16
|
-
attr_reader :scopes
|
17
|
-
attr_reader :errors, :registers
|
16
|
+
attr_reader :scopes, :errors, :registers, :environments
|
18
17
|
|
19
|
-
def initialize(
|
20
|
-
@
|
21
|
-
@
|
22
|
-
@
|
18
|
+
def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false)
|
19
|
+
@environments = [environments].flatten
|
20
|
+
@scopes = [(outer_scope || {})]
|
21
|
+
@registers = registers
|
22
|
+
@errors = []
|
23
23
|
@rethrow_errors = rethrow_errors
|
24
|
+
squash_instance_assigns_with_environments
|
24
25
|
end
|
25
26
|
|
26
27
|
def strainer
|
@@ -61,9 +62,9 @@ module Liquid
|
|
61
62
|
end
|
62
63
|
|
63
64
|
# push new local scope on the stack. use <tt>Context#stack</tt> instead
|
64
|
-
def push
|
65
|
+
def push(new_scope={})
|
65
66
|
raise StackLevelError, "Nesting too deep" if @scopes.length > 100
|
66
|
-
@scopes.unshift(
|
67
|
+
@scopes.unshift(new_scope)
|
67
68
|
end
|
68
69
|
|
69
70
|
# merge a hash of variables in the current local scope
|
@@ -86,9 +87,9 @@ module Liquid
|
|
86
87
|
# end
|
87
88
|
# context['var] #=> nil
|
88
89
|
#
|
89
|
-
def stack(
|
90
|
+
def stack(new_scope={},&block)
|
90
91
|
result = nil
|
91
|
-
push
|
92
|
+
push(new_scope)
|
92
93
|
begin
|
93
94
|
result = yield
|
94
95
|
ensure
|
@@ -96,6 +97,10 @@ module Liquid
|
|
96
97
|
end
|
97
98
|
result
|
98
99
|
end
|
100
|
+
|
101
|
+
def clear_instance_assigns
|
102
|
+
@scopes[0] = {}
|
103
|
+
end
|
99
104
|
|
100
105
|
# Only allow String, Numeric, Hash, Array, Proc, Boolean or <tt>Liquid::Drop</tt>
|
101
106
|
def []=(key, value)
|
@@ -133,9 +138,6 @@ module Liquid
|
|
133
138
|
:blank?
|
134
139
|
when 'empty'
|
135
140
|
:empty?
|
136
|
-
# filtered variables
|
137
|
-
when SpacelessFilter
|
138
|
-
filtered_variable(key)
|
139
141
|
# Single quoted strings
|
140
142
|
when /^'(.*)'$/
|
141
143
|
$1.to_s
|
@@ -159,16 +161,21 @@ module Liquid
|
|
159
161
|
# fetches an object starting at the local scope and then moving up
|
160
162
|
# the hierachy
|
161
163
|
def find_variable(key)
|
162
|
-
@scopes.
|
163
|
-
|
164
|
-
|
165
|
-
variable =
|
166
|
-
|
167
|
-
|
168
|
-
|
164
|
+
scope = @scopes.find { |s| s.has_key?(key) }
|
165
|
+
if scope.nil?
|
166
|
+
@environments.each do |e|
|
167
|
+
if variable = lookup_and_evaluate(e, key)
|
168
|
+
scope = e
|
169
|
+
break
|
170
|
+
end
|
169
171
|
end
|
170
172
|
end
|
171
|
-
|
173
|
+
scope ||= @environments.last || @scopes.last
|
174
|
+
variable ||= lookup_and_evaluate(scope, key)
|
175
|
+
|
176
|
+
variable = variable.to_liquid
|
177
|
+
variable.context = self if variable.respond_to?(:context=)
|
178
|
+
return variable
|
172
179
|
end
|
173
180
|
|
174
181
|
# resolves namespaced queries gracefully.
|
@@ -200,8 +207,7 @@ module Liquid
|
|
200
207
|
(object.respond_to?(:fetch) and part.is_a?(Integer)))
|
201
208
|
|
202
209
|
# if its a proc we will replace the entry with the proc
|
203
|
-
res = object
|
204
|
-
res = object[part] = res.call(self) if res.is_a?(Proc) and object.respond_to?(:[]=)
|
210
|
+
res = lookup_and_evaluate(object, part)
|
205
211
|
object = res.to_liquid
|
206
212
|
|
207
213
|
# Some special cases. If the part wasn't in square brackets and
|
@@ -225,8 +231,24 @@ module Liquid
|
|
225
231
|
object
|
226
232
|
end
|
227
233
|
|
228
|
-
def
|
229
|
-
|
234
|
+
def lookup_and_evaluate(obj, key)
|
235
|
+
if (value = obj[key]).is_a?(Proc) && obj.respond_to?(:[]=)
|
236
|
+
obj[key] = value.call(self)
|
237
|
+
else
|
238
|
+
value
|
239
|
+
end
|
230
240
|
end
|
241
|
+
|
242
|
+
def squash_instance_assigns_with_environments
|
243
|
+
@scopes.last.each_key do |k|
|
244
|
+
@environments.each do |env|
|
245
|
+
if env.has_key?(k)
|
246
|
+
scopes.last[k] = lookup_and_evaluate(env, k)
|
247
|
+
break
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
231
253
|
end
|
232
254
|
end
|