Compare commits

...

4 Commits

Author SHA1 Message Date
Dylan Thacker-Smith
8daaad3b76 Make error locations available for non-Liquid::Error exceptions. 2015-05-21 19:03:17 -04:00
Dylan Thacker-Smith
d36c6822da Include template name with line numbers in render errors. 2015-05-21 16:50:05 -04:00
Dylan Thacker-Smith
3d87d9ab1e Raise Liquid::ZeroDivisionError instead of ZeroDivisionError. 2015-05-21 12:18:58 -04:00
Dylan Thacker-Smith
71ff1f283a Make liquid rendering optional.
Although the author of the liquid template wants to see these errors, they
probably don't want the visitor to see the liquid errors.  Probably the
best fallback when rendering the page for visitors is to render the empty
string for tags with errors.
2015-05-21 10:49:32 -04:00
6 changed files with 51 additions and 25 deletions

View File

@@ -50,6 +50,7 @@ require 'liquid/i18n'
require 'liquid/drop'
require 'liquid/extensions'
require 'liquid/errors'
require 'liquid/error_location'
require 'liquid/interrupts'
require 'liquid/strainer'
require 'liquid/expression'

View File

@@ -12,16 +12,18 @@ module Liquid
#
# context['bob'] #=> nil class Context
class Context
attr_reader :scopes, :errors, :registers, :environments, :resource_limits
attr_accessor :exception_handler
attr_reader :scopes, :errors, :error_locations, :registers, :environments, :resource_limits
attr_accessor :exception_handler, :render_errors, :template_name
def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil)
def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil, render_errors = true)
@environments = [environments].flatten
@scopes = [(outer_scope || {})]
@registers = registers
@errors = []
@error_locations = []
@resource_limits = resource_limits || ResourceLimits.new(Template.default_resource_limits)
squash_instance_assigns_with_environments
@render_errors = render_errors
@this_stack_used = false
@@ -64,12 +66,14 @@ module Liquid
def handle_error(e, token = nil)
if e.is_a?(Liquid::Error)
e.template_name = template_name
e.set_line_number_from_token(token)
end
errors.push(e)
error_locations.push(ErrorLocation.from_token(template_name, token))
raise if exception_handler && exception_handler.call(e)
Liquid::Error.render(e)
render_errors ? Liquid::Error.render(e) : ''
end
def invoke(method, *args)

View File

@@ -0,0 +1,11 @@
module Liquid
ErrorLocation = Struct.new(:template_name, :line_number) do
def self.line_number_from_token(token)
token.respond_to?(:line_number) ? token.line_number : nil
end
def self.from_token(template_name, token)
new(template_name, line_number_from_token(token))
end
end
end

View File

@@ -1,6 +1,7 @@
module Liquid
class Error < ::StandardError
attr_accessor :line_number
attr_accessor :template_name
attr_accessor :markup_context
def to_s(with_prefix = true)
@@ -17,9 +18,8 @@ module Liquid
end
def set_line_number_from_token(token)
return unless token.respond_to?(:line_number)
return if line_number
self.line_number = token.line_number
self.line_number = ErrorLocation.line_number_from_token(token)
end
def self.render(e)
@@ -41,7 +41,9 @@ module Liquid
end
if line_number
str << " (line #{line_number})"
str << " ("
str << template_name << " " if template_name
str << "line " << line_number.to_s << ")"
end
str << ": "

View File

@@ -41,9 +41,9 @@ module Liquid
end
def render(context)
partial = load_cached_partial(context)
template_name = context.evaluate(@template_name_expr)
partial = load_cached_partial(template_name, context)
context_variable_name = template_name.split('/'.freeze).last
variable = if @variable_name_expr
@@ -52,28 +52,33 @@ module Liquid
context.find_variable(template_name)
end
context.stack do
@attributes.each do |key, value|
context[key] = context.evaluate(value)
end
old_template_name = context.template_name
begin
context.template_name = template_name
context.stack do
@attributes.each do |key, value|
context[key] = context.evaluate(value)
end
if variable.is_a?(Array)
variable.collect do |var|
context[context_variable_name] = var
if variable.is_a?(Array)
variable.collect do |var|
context[context_variable_name] = var
partial.render(context)
end
else
context[context_variable_name] = variable
partial.render(context)
end
else
context[context_variable_name] = variable
partial.render(context)
end
ensure
context.template_name = old_template_name
end
end
private
def load_cached_partial(context)
def load_cached_partial(template_name, context)
cached_partials = context.registers[:cached_partials] || {}
template_name = context.evaluate(@template_name_expr)
if cached = cached_partials[template_name]
return cached

View File

@@ -17,7 +17,7 @@ module Liquid
locale: I18n.new
}
attr_accessor :root
attr_accessor :root, :render_errors
attr_reader :resource_limits
@@file_system = BlankFileSystem.new
@@ -112,6 +112,7 @@ module Liquid
def initialize
@resource_limits = ResourceLimits.new(self.class.default_resource_limits)
@render_errors = true
end
# Parse source code.
@@ -163,6 +164,8 @@ module Liquid
def render(*args)
return ''.freeze if @root.nil?
render_errors = self.render_errors
context = case args.first
when Liquid::Context
c = args.shift
@@ -174,11 +177,11 @@ module Liquid
c
when Liquid::Drop
drop = args.shift
drop.context = Context.new([drop, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits)
drop.context = Context.new([drop, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits, render_errors)
when Hash
Context.new([args.shift, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits)
Context.new([args.shift, assigns], instance_assigns, registers, @rethrow_errors, @resource_limits, render_errors)
when nil
Context.new(assigns, instance_assigns, registers, @rethrow_errors, @resource_limits)
Context.new(assigns, instance_assigns, registers, @rethrow_errors, @resource_limits, render_errors)
else
raise ArgumentError, "Expected Hash or Liquid::Context as parameter"
end