diff --git a/lib/liquid/context.rb b/lib/liquid/context.rb index b15f16b..225eec5 100644 --- a/lib/liquid/context.rb +++ b/lib/liquid/context.rb @@ -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 + attr_accessor :exception_handler, :template_name, :partial, :global_filter def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil) @environments = [environments].flatten @@ -32,6 +32,7 @@ module Liquid @interrupts = [] @filters = [] + @global_filter = nil end def warnings @@ -52,6 +53,10 @@ module Liquid @strainer = nil end + def apply_global_filter(obj) + global_filter.nil? ? obj : global_filter.call(obj) + end + # are there any not handled interrupts? def interrupt? !@interrupts.empty? diff --git a/lib/liquid/template.rb b/lib/liquid/template.rb index 07d56b2..b875e0b 100644 --- a/lib/liquid/template.rb +++ b/lib/liquid/template.rb @@ -179,20 +179,15 @@ module Liquid when Hash options = args.pop - if options[:registers].is_a?(Hash) - registers.merge!(options[:registers]) - end + registers.merge!(options[:registers]) if options[:registers].is_a?(Hash) - if options[:filters] - context.add_filters(options[:filters]) - end + context.add_filters(options[:filters]) if options[:filters] - if options[:exception_handler] - context.exception_handler = options[:exception_handler] - end - when Module - context.add_filters(args.pop) - when Array + context.global_filter = options[:global_filter] if options[:global_filter] + + context.exception_handler = options[:exception_handler] if options[:exception_handler] + + when Module, Array context.add_filters(args.pop) end diff --git a/lib/liquid/variable.rb b/lib/liquid/variable.rb index 5c62ffd..8006ac7 100644 --- a/lib/liquid/variable.rb +++ b/lib/liquid/variable.rb @@ -73,10 +73,16 @@ module Liquid end def render(context) - @filters.inject(context.evaluate(@name)) do |output, (filter_name, filter_args, filter_kwargs)| + obj = @filters.inject(context.evaluate(@name)) do |output, (filter_name, filter_args, filter_kwargs)| filter_args = evaluate_filter_expressions(context, filter_args, filter_kwargs) context.invoke(filter_name, output, *filter_args) - end.tap{ |obj| taint_check(context, obj) } + end + + obj = context.apply_global_filter(obj) + + taint_check(context, obj) + + obj end private diff --git a/test/integration/template_test.rb b/test/integration/template_test.rb index 09140c4..4fa420f 100644 --- a/test/integration/template_test.rb +++ b/test/integration/template_test.rb @@ -211,4 +211,18 @@ class TemplateTest < Minitest::Test end assert exception.is_a?(Liquid::ZeroDivisionError) end + + def test_global_filter_option_on_render + global_filter_proc = ->(output) { "#{output} filtered" } + rendered_template = Template.parse("{{name}}").render({ "name" => "bob" }, global_filter: global_filter_proc) + + assert_equal 'bob filtered', rendered_template + end + + def test_global_filter_option_when_native_filters_exist + global_filter_proc = ->(output) { "#{output} filtered" } + rendered_template = Template.parse("{{name | upcase}}").render({ "name" => "bob" }, global_filter: global_filter_proc) + + assert_equal 'BOB filtered', rendered_template + end end diff --git a/test/unit/context_unit_test.rb b/test/unit/context_unit_test.rb index 7963d27..e4768f9 100644 --- a/test/unit/context_unit_test.rb +++ b/test/unit/context_unit_test.rb @@ -466,4 +466,18 @@ class ContextUnitTest < Minitest::Test assert contx assert_nil contx['poutine'] end + + def test_apply_global_filter + global_filter_proc = ->(output) { "#{output} filtered" } + + context = Context.new + context.global_filter = global_filter_proc + + assert_equal 'hi filtered', context.apply_global_filter('hi') + end + + def test_apply_global_filter_when_no_global_filter_exist + context = Context.new + assert_equal 'hi', context.apply_global_filter('hi') + end end # ContextTest