lib/liquid/context.rb in locomotive_liquid-2.2.3 vs lib/liquid/context.rb in locomotive_liquid-2.4.1

- old
+ new

@@ -20,10 +20,12 @@ @scopes = [(outer_scope || {})] @registers = registers @errors = [] @rethrow_errors = rethrow_errors squash_instance_assigns_with_environments + + @interrupts = [] end def strainer @strainer ||= Strainer.create(self) end @@ -39,10 +41,25 @@ raise ArgumentError, "Expected module but got: #{f.class}" unless f.is_a?(Module) strainer.extend(f) end end + # are there any not handled interrupts? + def has_interrupt? + !@interrupts.empty? + end + + # push an interrupt to the stack. this interrupt is considered not handled. + def push_interrupt(e) + @interrupts.push(e) + end + + # pop an interrupt from the stack + def pop_interrupt + @interrupts.pop + end + def handle_error(e) errors.push(e) raise if @rethrow_errors case e @@ -61,12 +78,12 @@ end end # Push new local scope on the stack. use <tt>Context#stack</tt> instead def push(new_scope={}) - raise StackLevelError, "Nesting too deep" if @scopes.length > 100 @scopes.unshift(new_scope) + raise StackLevelError, "Nesting too deep" if @scopes.length > 100 end # Merge a hash of variables in the current local scope def merge(new_scopes) @scopes[0].merge!(new_scopes) @@ -84,21 +101,15 @@ # context.stack do # context['var'] = 'hi' # end # # context['var] #=> nil - def stack(new_scope={},&block) - result = nil + def stack(new_scope={}) push(new_scope) - - begin - result = yield - ensure - pop - end - - result + yield + ensure + pop end def clear_instance_assigns @scopes[0] = {} end @@ -115,41 +126,44 @@ def has_key?(key) resolve(key) != nil end private + + LITERALS = { + nil => nil, 'nil' => nil, 'null' => nil, '' => nil, + 'true' => true, + 'false' => false, + 'blank' => :blank?, + 'empty' => :empty? + } + # Look up variable, either resolve directly after considering the name. We can directly handle # Strings, digits, floats and booleans (true,false). # If no match is made we lookup the variable in the current scope and # later move up to the parent blocks to see if we can resolve the variable somewhere up the tree. # Some special keywords return symbols. Those symbols are to be called on the rhs object in expressions # # Example: # products == empty #=> products.empty? def resolve(key) - case key - when nil, 'nil', 'null', '' - nil - when 'true' - true - when 'false' - false - when 'blank' - :blank? - when 'empty' # Single quoted strings - :empty? - when /^'(.*)'$/ # Double quoted strings - $1.to_s - when /^"(.*)"$/ # Integer and floats - $1.to_s - when /^(\d+)$/ # Ranges - $1.to_i - when /^\((\S+)\.\.(\S+)\)$/ # Floats - (resolve($1).to_i..resolve($2).to_i) - when /^(\d[\d\.]+)$/ - $1.to_f + if LITERALS.key?(key) + LITERALS[key] else - variable(key) + case key + when /^'(.*)'$/ # Single quoted strings + $1 + when /^"(.*)"$/ # Double quoted strings + $1 + when /^(-?\d+)$/ # Integer and floats + $1.to_i + when /^\((\S+)\.\.(\S+)\)$/ # Ranges + (resolve($1).to_i..resolve($2).to_i) + when /^(-?\d[\d\.]+)$/ # Floats + $1.to_f + else + variable(key) + end end end # Fetches an object starting at the local scope and then moving up the hierachy def find_variable(key)