Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use context in custom filters #99

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions lib/liquid/filters.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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 """
Expand Down Expand Up @@ -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 =
Expand All @@ -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 """
Expand Down
6 changes: 3 additions & 3 deletions lib/liquid/variable.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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
Expand Down
18 changes: 14 additions & 4 deletions test/liquid/custom_filter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions test/liquid/filter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
16 changes: 12 additions & 4 deletions test/liquid/global_filter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down