mirror of
https://github.com/kemko/liquid.git
synced 2026-01-02 16:25:42 +03:00
Compare commits
4 Commits
filter-err
...
out-of-ban
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8daaad3b76 | ||
|
|
d36c6822da | ||
|
|
3d87d9ab1e | ||
|
|
71ff1f283a |
@@ -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'
|
||||
|
||||
@@ -12,17 +12,18 @@ module Liquid
|
||||
#
|
||||
# context['bob'] #=> nil class Context
|
||||
class Context
|
||||
attr_reader :scopes, :errors, :registers, :environments, :resource_limits
|
||||
attr_accessor :exception_handler, :render_errors
|
||||
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 = true
|
||||
@render_errors = render_errors
|
||||
|
||||
@this_stack_used = false
|
||||
|
||||
@@ -65,10 +66,12 @@ 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)
|
||||
render_errors ? Liquid::Error.render(e) : ''
|
||||
end
|
||||
|
||||
11
lib/liquid/error_location.rb
Normal file
11
lib/liquid/error_location.rb
Normal 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
|
||||
@@ -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 << ": "
|
||||
@@ -49,10 +51,6 @@ module Liquid
|
||||
end
|
||||
end
|
||||
|
||||
class FilterError < Error
|
||||
attr_accessor :original_exception
|
||||
end
|
||||
|
||||
ArgumentError = Class.new(Error)
|
||||
ContextError = Class.new(Error)
|
||||
FileSystemError = Class.new(Error)
|
||||
|
||||
@@ -47,20 +47,12 @@ module Liquid
|
||||
|
||||
def invoke(method, *args)
|
||||
if self.class.invokable?(method)
|
||||
begin
|
||||
send(method, *args)
|
||||
rescue ::ArgumentError => e
|
||||
raise Liquid::ArgumentError.new(e.message)
|
||||
rescue Liquid::Error
|
||||
raise
|
||||
rescue ::StandardError => exception
|
||||
error = Liquid::FilterError.new(exception.message)
|
||||
error.original_exception = exception
|
||||
raise error
|
||||
end
|
||||
send(method, *args)
|
||||
else
|
||||
args.first
|
||||
end
|
||||
rescue ::ArgumentError => e
|
||||
raise Liquid::ArgumentError.new(e.message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,17 +177,15 @@ 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
|
||||
|
||||
context.render_errors = self.render_errors unless self.render_errors.nil?
|
||||
|
||||
case args.last
|
||||
when Hash
|
||||
options = args.pop
|
||||
|
||||
@@ -185,11 +185,4 @@ class ErrorHandlingTest < Minitest::Test
|
||||
template.render('errors' => ErrorDrop.new)
|
||||
end
|
||||
end
|
||||
|
||||
def test_disabling_error_rendering
|
||||
template = Liquid::Template.parse('This is an argument error: {{ errors.argument_error }}')
|
||||
template.render_errors = false
|
||||
assert_equal 'This is an argument error: ', template.render('errors' => ErrorDrop.new)
|
||||
assert_equal [ArgumentError], template.errors.map(&:class)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,12 +22,6 @@ module SubstituteFilter
|
||||
end
|
||||
end
|
||||
|
||||
module ErrorFilter
|
||||
def standard_error(input)
|
||||
raise ::StandardError, 'standard error'
|
||||
end
|
||||
end
|
||||
|
||||
class FiltersTest < Minitest::Test
|
||||
include Liquid
|
||||
|
||||
@@ -164,14 +158,7 @@ class FiltersInTemplate < Minitest::Test
|
||||
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render!(nil, CanadianMoneyFilter)
|
||||
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render!(nil, [CanadianMoneyFilter])
|
||||
end
|
||||
|
||||
def test_filter_error
|
||||
context = Context.new
|
||||
context.add_filters(ErrorFilter)
|
||||
assert_equal "Liquid error: standard error", Template.parse("{{'var' | standard_error}}").render(context)
|
||||
assert_equal [Liquid::FilterError], context.errors.map(&:class)
|
||||
end
|
||||
end
|
||||
end # FiltersTest
|
||||
|
||||
class TestObject
|
||||
attr_accessor :a
|
||||
|
||||
@@ -201,16 +201,14 @@ class TemplateTest < Minitest::Test
|
||||
def test_exception_handler_doesnt_reraise_if_it_returns_false
|
||||
exception = nil
|
||||
Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_handler: ->(e) { exception = e; false })
|
||||
assert exception.is_a?(Liquid::FilterError)
|
||||
assert exception.original_exception.is_a?(ZeroDivisionError)
|
||||
assert exception.is_a?(ZeroDivisionError)
|
||||
end
|
||||
|
||||
def test_exception_handler_does_reraise_if_it_returns_true
|
||||
exception = nil
|
||||
assert_raises(Liquid::FilterError) do
|
||||
assert_raises(ZeroDivisionError) do
|
||||
Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_handler: ->(e) { exception = e; true })
|
||||
end
|
||||
assert exception.is_a?(Liquid::FilterError)
|
||||
assert exception.original_exception.is_a?(ZeroDivisionError)
|
||||
assert exception.is_a?(ZeroDivisionError)
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user