diff --git a/benchmarks/README.md b/benchmarks/README.md index c75a1e2..0da2cfa 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -3,8 +3,8 @@ |Library|Time | |:------|:-----| -|bbmustache | 70308 | -|mustache.erl | 946352 | +|bbmustache | 64638 | +|mustache.erl | 932479 | # Check the reference implementation :warning: For libraries other than bbmustache, there is a possibility that there is a miss. diff --git a/doc/bbmustache.md b/doc/bbmustache.md index 03764c5..b9cb4b3 100644 --- a/doc/bbmustache.md +++ b/doc/bbmustache.md @@ -60,11 +60,15 @@ data_value() = data() | iodata() | number() | atom() |

-option() = {key_type, atom | binary | string} | raise_on_context_miss
+option() = {key_type, atom | binary | string} | raise_on_context_miss | {escape_fun, fun((binary()) -> binary())}
 
- - key_type: Specify the type of the key in [`data/0`](#data-0). Default value is `string`. -- raise_on_contex_miss: If key exists in template does not exist in data, it will throw an exception (error). + - key_type: +-- Specify the type of the key in [`data/0`](#data-0). Default value is `string`. +- raise_on_contex_miss: +-- If key exists in template does not exist in data, it will throw an exception (error). +- escape_fun: +-- Specify your own escape function. diff --git a/src/bbmustache.erl b/src/bbmustache.erl index 085d785..10710a7 100644 --- a/src/bbmustache.erl +++ b/src/bbmustache.erl @@ -107,9 +107,14 @@ -type assoc_data() :: [{atom(), data_value()}] | [{binary(), data_value()}] | [{string(), data_value()}]. -type option() :: {key_type, atom | binary | string} - | raise_on_context_miss. -%% - key_type: Specify the type of the key in {@link data/0}. Default value is `string'. -%% - raise_on_contex_miss: If key exists in template does not exist in data, it will throw an exception (error). + | raise_on_context_miss + | {escape_fun, fun((binary()) -> binary())}. +%% - key_type: +%% -- Specify the type of the key in {@link data/0}. Default value is `string'. +%% - raise_on_contex_miss: +%% -- If key exists in template does not exist in data, it will throw an exception (error). +%% - escape_fun: +%% -- Specify your own escape function. -ifdef(namespaced_types). -type maps_data() :: #{atom() => data_value()} | #{binary() => data_value()} | #{string() => data_value()}. @@ -191,7 +196,9 @@ compile(#?MODULE{data = Tags} = T, Data, Options) -> compile_impl([], _, Result, _) -> Result; compile_impl([{n, Keys} | T], Map, Result, State) -> - compile_impl(T, Map, ?ADD(escape(to_iodata(get_data_recursive(Keys, Map, <<>>, State))), Result), State); + Value = iolist_to_binary(to_iodata(get_data_recursive(Keys, Map, <<>>, State))), + EscapeFun = proplists:get_value(escape_fun, State#?MODULE.options, fun escape/1), + compile_impl(T, Map, ?ADD(EscapeFun(Value), Result), State); compile_impl([{'&', Keys} | T], Map, Result, State) -> compile_impl(T, Map, ?ADD(to_iodata(get_data_recursive(Keys, Map, <<>>, State)), Result), State); compile_impl([{'#', Keys, Tags, Source} | T], Map, Result, State) -> @@ -534,9 +541,8 @@ to_binary(Str) when is_list(Str) -> list_to_binary(Str). %% @doc HTML Escape --spec escape(iodata()) -> binary(). -escape(IoData) -> - Bin = iolist_to_binary(IoData), +-spec escape(binary()) -> binary(). +escape(Bin) -> << <<(escape_char(X))/binary>> || <> <= Bin >>. %% @doc escape a character if needed. diff --git a/test/bbmustache_tests.erl b/test/bbmustache_tests.erl index 9d92c3a..28704e5 100644 --- a/test/bbmustache_tests.erl +++ b/test/bbmustache_tests.erl @@ -183,3 +183,12 @@ context_stack_test_() -> [{"parent", []}], [raise_on_context_miss]))} ]. + +escape_fun_test_() -> + [ + {"It is able to specified own escape function", + ?_assertEqual(<<"==>value<==">>, + bbmustache:render(<<"{{tag}}">>, + [{"tag", "value"}], + [{escape_fun, fun(X) -> <<"==>", X/binary, "<==">> end}]))} + ].