mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-16 09:20:42 -07:00
Merge branch 'master' into contains-strict-fix
This commit is contained in:
@@ -96,7 +96,8 @@ module Liquid
|
||||
context.handle_error(e, token.line_number)
|
||||
output << nil
|
||||
rescue ::StandardError => e
|
||||
output << context.handle_error(e, token.line_number)
|
||||
line_number = token.is_a?(String) ? nil : token.line_number
|
||||
output << context.handle_error(e, line_number)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -106,7 +107,7 @@ module Liquid
|
||||
private
|
||||
|
||||
def render_node(node, context)
|
||||
node_output = (node.respond_to?(:render) ? node.render(context) : node)
|
||||
node_output = node.is_a?(String) ? node : node.render(context)
|
||||
node_output = node_output.is_a?(Array) ? node_output.join : node_output.to_s
|
||||
|
||||
context.resource_limits.render_length += node_output.length
|
||||
|
||||
@@ -110,7 +110,7 @@ module Liquid
|
||||
|
||||
if operation.respond_to?(:call)
|
||||
operation.call(self, left, right)
|
||||
elsif left.respond_to?(operation) && right.respond_to?(operation)
|
||||
elsif left.respond_to?(operation) && right.respond_to?(operation) && !left.is_a?(Hash) && !right.is_a?(Hash)
|
||||
begin
|
||||
left.send(operation, right)
|
||||
rescue ::ArgumentError => e
|
||||
|
||||
+19
-30
@@ -13,7 +13,7 @@ module Liquid
|
||||
# context['bob'] #=> nil class Context
|
||||
class Context
|
||||
attr_reader :scopes, :errors, :registers, :environments, :resource_limits
|
||||
attr_accessor :exception_handler, :template_name, :partial, :global_filter, :strict_variables, :strict_filters
|
||||
attr_accessor :exception_renderer, :template_name, :partial, :global_filter, :strict_variables, :strict_filters
|
||||
|
||||
def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil)
|
||||
@environments = [environments].flatten
|
||||
@@ -27,8 +27,9 @@ module Liquid
|
||||
|
||||
@this_stack_used = false
|
||||
|
||||
self.exception_renderer = Template.default_exception_renderer
|
||||
if rethrow_errors
|
||||
self.exception_handler = ->(e) { raise }
|
||||
self.exception_renderer = ->(e) { raise }
|
||||
end
|
||||
|
||||
@interrupts = []
|
||||
@@ -74,30 +75,11 @@ module Liquid
|
||||
end
|
||||
|
||||
def handle_error(e, line_number = nil)
|
||||
if e.is_a?(Liquid::Error)
|
||||
e.template_name ||= template_name
|
||||
e.line_number ||= line_number
|
||||
end
|
||||
|
||||
output = nil
|
||||
|
||||
if exception_handler
|
||||
result = exception_handler.call(e)
|
||||
case result
|
||||
when Exception
|
||||
e = result
|
||||
if e.is_a?(Liquid::Error)
|
||||
e.template_name ||= template_name
|
||||
e.line_number ||= line_number
|
||||
end
|
||||
when String
|
||||
output = result
|
||||
else
|
||||
raise if result
|
||||
end
|
||||
end
|
||||
e = internal_error unless e.is_a?(Liquid::Error)
|
||||
e.template_name ||= template_name
|
||||
e.line_number ||= line_number
|
||||
errors.push(e)
|
||||
output || Liquid::Error.render(e)
|
||||
exception_renderer.call(e).to_s
|
||||
end
|
||||
|
||||
def invoke(method, *args)
|
||||
@@ -178,7 +160,7 @@ module Liquid
|
||||
end
|
||||
|
||||
# Fetches an object starting at the local scope and then moving up the hierachy
|
||||
def find_variable(key)
|
||||
def find_variable(key, raise_on_not_found: true)
|
||||
# This was changed from find() to find_index() because this is a very hot
|
||||
# path and find_index() is optimized in MRI to reduce object allocation
|
||||
index = @scopes.find_index { |s| s.key?(key) }
|
||||
@@ -188,7 +170,7 @@ module Liquid
|
||||
|
||||
if scope.nil?
|
||||
@environments.each do |e|
|
||||
variable = lookup_and_evaluate(e, key)
|
||||
variable = lookup_and_evaluate(e, key, raise_on_not_found: raise_on_not_found)
|
||||
unless variable.nil?
|
||||
scope = e
|
||||
break
|
||||
@@ -197,7 +179,7 @@ module Liquid
|
||||
end
|
||||
|
||||
scope ||= @environments.last || @scopes.last
|
||||
variable ||= lookup_and_evaluate(scope, key)
|
||||
variable ||= lookup_and_evaluate(scope, key, raise_on_not_found: raise_on_not_found)
|
||||
|
||||
variable = variable.to_liquid
|
||||
variable.context = self if variable.respond_to?(:context=)
|
||||
@@ -205,8 +187,8 @@ module Liquid
|
||||
variable
|
||||
end
|
||||
|
||||
def lookup_and_evaluate(obj, key)
|
||||
if @strict_variables && obj.respond_to?(:key?) && !obj.key?(key)
|
||||
def lookup_and_evaluate(obj, key, raise_on_not_found: true)
|
||||
if @strict_variables && raise_on_not_found && obj.respond_to?(:key?) && !obj.key?(key)
|
||||
raise Liquid::UndefinedVariable, "undefined variable #{key}"
|
||||
end
|
||||
|
||||
@@ -221,6 +203,13 @@ module Liquid
|
||||
|
||||
private
|
||||
|
||||
def internal_error
|
||||
# raise and catch to set backtrace and cause on exception
|
||||
raise Liquid::InternalError, 'internal'
|
||||
rescue Liquid::InternalError => exc
|
||||
exc
|
||||
end
|
||||
|
||||
def squash_instance_assigns_with_environments
|
||||
@scopes.last.each_key do |k|
|
||||
@environments.each do |env|
|
||||
|
||||
@@ -17,14 +17,6 @@ module Liquid
|
||||
str
|
||||
end
|
||||
|
||||
def self.render(e)
|
||||
if e.is_a?(Liquid::Error)
|
||||
e.to_s
|
||||
else
|
||||
"Liquid error: #{e}"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def message_prefix
|
||||
@@ -60,4 +52,5 @@ module Liquid
|
||||
UndefinedDropMethod = Class.new(Error)
|
||||
UndefinedFilter = Class.new(Error)
|
||||
MethodOverrideError = Class.new(Error)
|
||||
InternalError = Class.new(Error)
|
||||
end
|
||||
|
||||
@@ -22,3 +22,5 @@
|
||||
tag_never_closed: "'%{block_name}' tag was never closed"
|
||||
meta_syntax_error: "Liquid syntax error: #{e.message}"
|
||||
table_row: "Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3"
|
||||
argument:
|
||||
include: "Argument error in tag 'include' - Illegal template name"
|
||||
|
||||
@@ -65,9 +65,10 @@ module Liquid
|
||||
return if input.nil?
|
||||
input_str = input.to_s
|
||||
length = Utils.to_integer(length)
|
||||
l = length - truncate_string.length
|
||||
truncate_string_str = truncate_string.to_s
|
||||
l = length - truncate_string_str.length
|
||||
l = 0 if l < 0
|
||||
input_str.length > length ? input_str[0...l] + truncate_string : input_str
|
||||
input_str.length > length ? input_str[0...l] + truncate_string_str : input_str
|
||||
end
|
||||
|
||||
def truncatewords(input, words = 15, truncate_string = "...".freeze)
|
||||
@@ -76,7 +77,7 @@ module Liquid
|
||||
words = Utils.to_integer(words)
|
||||
l = words - 1
|
||||
l = 0 if l < 0
|
||||
wordlist.length > l ? wordlist[0..l].join(" ".freeze) + truncate_string : input
|
||||
wordlist.length > l ? wordlist[0..l].join(" ".freeze) + truncate_string.to_s : input
|
||||
end
|
||||
|
||||
# Split input string into an array of substrings separated by given pattern.
|
||||
@@ -85,7 +86,7 @@ module Liquid
|
||||
# <div class="summary">{{ post | split '//' | first }}</div>
|
||||
#
|
||||
def split(input, pattern)
|
||||
input.to_s.split(pattern)
|
||||
input.to_s.split(pattern.to_s)
|
||||
end
|
||||
|
||||
def strip(input)
|
||||
@@ -124,7 +125,15 @@ module Liquid
|
||||
elsif ary.empty? # The next two cases assume a non-empty array.
|
||||
[]
|
||||
elsif ary.first.respond_to?(:[]) && !ary.first[property].nil?
|
||||
ary.sort { |a, b| a[property] <=> b[property] }
|
||||
ary.sort do |a, b|
|
||||
a = a[property]
|
||||
b = b[property]
|
||||
if a && b
|
||||
a <=> b
|
||||
else
|
||||
a ? -1 : 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -375,7 +384,7 @@ module Liquid
|
||||
end
|
||||
|
||||
def join(glue)
|
||||
to_a.join(glue)
|
||||
to_a.join(glue.to_s)
|
||||
end
|
||||
|
||||
def concat(args)
|
||||
|
||||
@@ -27,7 +27,7 @@ module Liquid
|
||||
|
||||
def self.add_filter(filter)
|
||||
raise ArgumentError, "Expected module but got: #{filter.class}" unless filter.is_a?(Module)
|
||||
unless self.class.include?(filter)
|
||||
unless self.include?(filter)
|
||||
invokable_non_public_methods = (filter.private_instance_methods + filter.protected_instance_methods).select { |m| invokable?(m) }
|
||||
if invokable_non_public_methods.any?
|
||||
raise MethodOverrideError, "Filter overrides registered public methods as non public: #{invokable_non_public_methods.join(', ')}"
|
||||
@@ -39,6 +39,7 @@ module Liquid
|
||||
end
|
||||
|
||||
def self.global_filter(filter)
|
||||
@@strainer_class_cache.clear
|
||||
@@global_strainer.add_filter(filter)
|
||||
end
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ module Liquid
|
||||
# {{ item.name }}
|
||||
# {% end %}
|
||||
#
|
||||
# To reverse the for loop simply use {% for item in collection reversed %}
|
||||
# To reverse the for loop simply use {% for item in collection reversed %} (note that the flag's spelling is different to the filter `reverse`)
|
||||
#
|
||||
# == Available variables:
|
||||
#
|
||||
|
||||
@@ -42,14 +42,15 @@ module Liquid
|
||||
|
||||
def render(context)
|
||||
template_name = context.evaluate(@template_name_expr)
|
||||
partial = load_cached_partial(template_name, context)
|
||||
raise ArgumentError.new(options[:locale].t("errors.argument.include")) unless template_name
|
||||
|
||||
partial = load_cached_partial(template_name, context)
|
||||
context_variable_name = template_name.split('/'.freeze).last
|
||||
|
||||
variable = if @variable_name_expr
|
||||
context.evaluate(@variable_name_expr)
|
||||
else
|
||||
context.find_variable(template_name)
|
||||
context.find_variable(template_name, raise_on_not_found: false)
|
||||
end
|
||||
|
||||
old_template_name = context.template_name
|
||||
|
||||
@@ -69,6 +69,11 @@ module Liquid
|
||||
# :error raises an error when tainted output is used
|
||||
attr_writer :taint_mode
|
||||
|
||||
attr_accessor :default_exception_renderer
|
||||
Template.default_exception_renderer = lambda do |exception|
|
||||
exception
|
||||
end
|
||||
|
||||
def file_system
|
||||
@@file_system
|
||||
end
|
||||
@@ -167,7 +172,7 @@ module Liquid
|
||||
c = args.shift
|
||||
|
||||
if @rethrow_errors
|
||||
c.exception_handler = ->(e) { raise }
|
||||
c.exception_renderer = ->(e) { raise }
|
||||
end
|
||||
|
||||
c
|
||||
@@ -241,7 +246,7 @@ module Liquid
|
||||
def apply_options_to_context(context, options)
|
||||
context.add_filters(options[:filters]) if options[:filters]
|
||||
context.global_filter = options[:global_filter] if options[:global_filter]
|
||||
context.exception_handler = options[:exception_handler] if options[:exception_handler]
|
||||
context.exception_renderer = options[:exception_renderer] if options[:exception_renderer]
|
||||
context.strict_variables = options[:strict_variables] if options[:strict_variables]
|
||||
context.strict_filters = options[:strict_filters] if options[:strict_filters]
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# encoding: utf-8
|
||||
module Liquid
|
||||
VERSION = "4.0.0.rc2"
|
||||
VERSION = "4.0.0"
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user