diff --git a/README.md b/README.md index 78fd0294..ded9e27f 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,8 @@ You can add your own filters and tags/blocks inside your project: ``` elixir defmodule MyFilters do - def meaning_of_life(_), do: 42 - def one(_), do: 1 + def meaning_of_life(_, _context), do: 42 + def one(_, _context), do: 1 end defmodule ExampleTag do @@ -90,10 +90,10 @@ It's also possible to apply global filter to all rendered variables setting up t ``` elixir # config.exs config :liquid, - global_filter: &MyFilter.counting_sheeps/1 + global_filter: &MyFilter.counting_sheeps/2 ``` or adding a `"global_filter"` value to context for `Liquid.Template.render` function: -`Liquid.Template.render(tpl, %{global_filter: &MyFilter.counting_sheeps/1})` (you need to define filter function first) +`Liquid.Template.render(tpl, %{global_filter: &MyFilter.counting_sheeps/2})` (you need to define filter function first) ## File systems You can also set up the desired default file system for your project using the `config.exs` file diff --git a/lib/liquid/filters.ex b/lib/liquid/filters.ex index 7e3c353b..8cc55d6a 100644 --- a/lib/liquid/filters.ex +++ b/lib/liquid/filters.ex @@ -4,7 +4,7 @@ defmodule Liquid.Filters do """ import Kernel, except: [round: 1, abs: 1, floor: 1, ceil: 1] import Liquid.Utils, only: [to_number: 1] - alias Liquid.HTML + alias Liquid.{Context, HTML} defmodule Functions do @moduledoc """ @@ -484,9 +484,9 @@ defmodule Liquid.Filters do @doc """ Recursively pass through all of the input filters applying them """ - def filter([], value), do: value + def filter([], value, _context), do: value - def filter([filter | rest], value) do + def filter([filter | rest], value, %Context{} = context) do [name, args] = filter args = @@ -509,13 +509,13 @@ defmodule Liquid.Filters do # Fallback to custom if no standard {_, nil, _} -> - apply_function(custom_filters[name], name, [value | args]) + apply_function(custom_filters[name], name, [value, context | args]) _ -> apply_function(Functions, name, [value | args]) end - filter(rest, ret) + filter(rest, ret, context) end @doc """ diff --git a/lib/liquid/variable.ex b/lib/liquid/variable.ex index f213423f..03d0c9f1 100644 --- a/lib/liquid/variable.ex +++ b/lib/liquid/variable.ex @@ -31,7 +31,7 @@ defmodule Liquid.Variable do result = try do - {:ok, filters |> Filters.filter(ret) |> apply_global_filter(context)} + {:ok, filters |> Filters.filter(ret, context) |> apply_global_filter(context)} rescue e in UndefinedFunctionError -> {e, e.reason} e in ArgumentError -> {e, e.message} @@ -59,8 +59,8 @@ defmodule Liquid.Variable do defp apply_global_filter(input, %Context{global_filter: nil}), do: input - defp apply_global_filter(input, %Context{global_filter: global_filter}), - do: global_filter.(input) + defp apply_global_filter(input, %Context{global_filter: global_filter} = context), + do: global_filter.(input, context) @doc """ Parses the markup to a list of filters diff --git a/test/liquid/custom_filter_test.exs b/test/liquid/custom_filter_test.exs index b0a79b48..993a1c08 100644 --- a/test/liquid/custom_filter_test.exs +++ b/test/liquid/custom_filter_test.exs @@ -5,16 +5,22 @@ defmodule Liquid.CustomFilterTest do alias Liquid.Template defmodule MyFilter do - def meaning_of_life(_), do: 42 + def meaning_of_life(_, _), do: 42 end defmodule MyFilterTwo do - def meaning_of_life(_), do: 40 - def not_meaning_of_life(_), do: 2 + def meaning_of_life(_, _), do: 40 + def not_meaning_of_life(_, _), do: 2 + end + + defmodule MyFilterThree do + def stuff(_, context) do + context.assigns.test + end end setup_all do - Application.put_env(:liquid, :extra_filter_modules, [MyFilter, MyFilterTwo]) + Application.put_env(:liquid, :extra_filter_modules, [MyFilter, MyFilterTwo, MyFilterThree]) Liquid.start() on_exit(fn -> Liquid.stop() end) :ok @@ -38,6 +44,10 @@ defmodule Liquid.CustomFilterTest do ) end + test "custom filter can use context" do + assert_template_result("100", "{{ 'text' | stuff }}", %{test: 100}) + end + defp assert_template_result(expected, markup, assigns \\ %{}) do assert_result(expected, markup, assigns) end diff --git a/test/liquid/filter_test.exs b/test/liquid/filter_test.exs index 4e7f4476..1e6c981c 100644 --- a/test/liquid/filter_test.exs +++ b/test/liquid/filter_test.exs @@ -3,7 +3,7 @@ Code.require_file("../../test_helper.exs", __ENV__.file) defmodule Liquid.FilterTest do use ExUnit.Case use Timex - alias Liquid.{Filters, Template, Variable} + alias Liquid.{Context, Filters, Template, Variable} alias Liquid.Filters.Functions setup_all do @@ -22,7 +22,7 @@ defmodule Liquid.FilterTest do test :filter_parsed do name = "'foofoo'" filters = [[:replace, ["'foo'", "'bar'"]]] - assert "'barbar'" == Filters.filter(filters, name) + assert "'barbar'" == Filters.filter(filters, name, %Context{}) end test :size do diff --git a/test/liquid/global_filter_test.exs b/test/liquid/global_filter_test.exs index 21d4d2b8..5de0aeda 100644 --- a/test/liquid/global_filter_test.exs +++ b/test/liquid/global_filter_test.exs @@ -5,12 +5,13 @@ defmodule Liquid.GlobalFilterTest do alias Liquid.Template defmodule MyFilter do - def counting_sheeps(input) when is_binary(input), do: input <> " One, two, thr.. z-zz.." - def counting_bees(input) when is_binary(input), do: input <> " One, tw.. Ouch!" + def counting_sheeps(input, _) when is_binary(input), do: input <> " One, two, thr.. z-zz.." + def counting_bees(input, _) when is_binary(input), do: input <> " One, tw.. Ouch!" + def context_bees(input, context) when is_binary(input), do: input <> context.assigns.test end setup_all do - Application.put_env(:liquid, :global_filter, &MyFilter.counting_sheeps/1) + Application.put_env(:liquid, :global_filter, &MyFilter.counting_sheeps/2) Liquid.start() on_exit(fn -> Liquid.stop(Application.delete_env(:liquid, :global_filter)) end) :ok @@ -22,7 +23,14 @@ defmodule Liquid.GlobalFilterTest do test "preset filter overrides default applied" do assert_template_result("Initial One, tw.. Ouch!", "{{ 'initial' | capitalize }}", %{ - global_filter: &MyFilter.counting_bees/1 + global_filter: &MyFilter.counting_bees/2 + }) + end + + test "can use context" do + assert_template_result("Initial bee", "{{ 'initial' | capitalize }}", %{ + global_filter: &MyFilter.context_bees/2, + test: " bee" }) end