|
|
@@ -20,6 +20,7 @@
|
|
|
-export([parse/2]).
|
|
|
-export([parse_deep/1]).
|
|
|
-export([parse_deep/2]).
|
|
|
+-export([placeholders/1]).
|
|
|
-export([validate/2]).
|
|
|
-export([is_const/1]).
|
|
|
-export([unparse/1]).
|
|
|
@@ -143,14 +144,19 @@ parse_accessor(Var) ->
|
|
|
Name
|
|
|
end.
|
|
|
|
|
|
+-spec placeholders(t()) -> [varname()].
|
|
|
+placeholders(Template) when is_list(Template) ->
|
|
|
+ [Name || {var, Name, _} <- Template];
|
|
|
+placeholders({'$tpl', Template}) ->
|
|
|
+ placeholders_deep(Template).
|
|
|
+
|
|
|
%% @doc Validate a template against a set of allowed variables.
|
|
|
%% If the given template contains any variable not in the allowed set, an error
|
|
|
%% is returned.
|
|
|
-spec validate([varname() | {var_namespace, varname()}], t()) ->
|
|
|
ok | {error, [_Error :: {varname(), disallowed}]}.
|
|
|
validate(Allowed, Template) ->
|
|
|
- {_, Errors} = render(Template, #{}),
|
|
|
- {Used, _} = lists:unzip(Errors),
|
|
|
+ Used = placeholders(Template),
|
|
|
case find_disallowed(lists:usort(Used), Allowed) of
|
|
|
[] ->
|
|
|
ok;
|
|
|
@@ -192,10 +198,13 @@ is_allowed(Var, [{var_namespace, VarPrefix} | Allowed]) ->
|
|
|
false ->
|
|
|
is_allowed(Var, Allowed)
|
|
|
end;
|
|
|
-is_allowed(Var, [Var | _Allowed]) ->
|
|
|
+is_allowed(Var, [VarAllowed | Rest]) ->
|
|
|
+ is_same_varname(Var, VarAllowed) orelse is_allowed(Var, Rest).
|
|
|
+
|
|
|
+is_same_varname("", ".") ->
|
|
|
true;
|
|
|
-is_allowed(Var, [_ | Allowed]) ->
|
|
|
- is_allowed(Var, Allowed).
|
|
|
+is_same_varname(V1, V2) ->
|
|
|
+ V1 =:= V2.
|
|
|
|
|
|
%% @doc Check if a template is constant with respect to rendering, i.e. does not
|
|
|
%% contain any placeholders.
|
|
|
@@ -322,6 +331,22 @@ parse_deep_term(Term, Opts) when is_binary(Term) ->
|
|
|
parse_deep_term(Term, _Opts) ->
|
|
|
Term.
|
|
|
|
|
|
+-spec placeholders_deep(deeptpl()) -> [varname()].
|
|
|
+placeholders_deep(Template) when is_map(Template) ->
|
|
|
+ maps:fold(
|
|
|
+ fun(KT, VT, Acc) -> placeholders_deep(KT) ++ placeholders_deep(VT) ++ Acc end,
|
|
|
+ [],
|
|
|
+ Template
|
|
|
+ );
|
|
|
+placeholders_deep({list, Template}) when is_list(Template) ->
|
|
|
+ lists:flatmap(fun placeholders_deep/1, Template);
|
|
|
+placeholders_deep({tuple, Template}) when is_list(Template) ->
|
|
|
+ lists:flatmap(fun placeholders_deep/1, Template);
|
|
|
+placeholders_deep(Template) when is_list(Template) ->
|
|
|
+ placeholders(Template);
|
|
|
+placeholders_deep(_Term) ->
|
|
|
+ [].
|
|
|
+
|
|
|
render_deep(Template, Context, Opts) when is_map(Template) ->
|
|
|
maps:fold(
|
|
|
fun(KT, VT, {Acc, Errors}) ->
|