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>> || <