Packages
kvs
0.12.1
13.5.22-aleph
13.4.16
13.4.15
13.4.14
13.4.13
13.3.1
13.2.28
11.9.1
10.8.3
10.8.2
10.3.0
9.9.2
9.9.1
9.9.0
9.8.0
9.7.0
9.4.8
9.4.7
9.4.6
9.4.5
9.4.4
9.4.3
9.4.2
9.4.1
9.4.0
8.12.0
8.11.2
8.11.1
8.10.4
8.10.3
8.10.2
8.10.1
8.10.0
8.5.2
8.5.1
8.5.0
8.4.1
8.4.0
8.3.1
8.3.0
7.11.5
7.9.1
7.7.0
7.1.3
7.1.2
7.1.1
6.12.11
6.12.10
6.12.9
6.12.8
6.12.7
6.12.6
6.12.5
6.12.4
6.12.3
6.12.2
6.12.1
6.12.0
6.11.2
6.11.1
6.11.0
6.10.2
6.10.1
6.10.0
6.9.2
6.9.1
6.9.0
6.7.7
6.7.6
6.7.5
6.7.4
6.7.3
6.7.2
6.7.1
6.7.0
6.6.0
2.1.0
0.12.1
retired
KVS Key-Value Store Abstraction Layer
Retired package: Release invalid - ERROR
Current section
Files
Jump to
Current section
Files
src/erlydtl_runtime.erl
-module(erlydtl_runtime).
-compile(export_all).
-type text() :: string() | binary().
-type phrase() :: text() | {text(), {PluralPhrase::text(), non_neg_integer()}}.
-type locale() :: term() | {Locale::term(), Context::binary()}.
-type old_translate_fun() :: fun((text()) -> iodata() | default).
-type new_translate_fun() :: fun((phrase(), locale()) -> iodata() | default).
-type translate_fun() :: new_translate_fun() | old_translate_fun().
-type init_translation() :: none
| fun (() -> init_translation())
| {M::atom(), F::atom()}
| {M::atom(), F::atom(), A::list()}
| translate_fun().
-define(IFCHANGED_CONTEXT_VARIABLE, erlydtl_ifchanged_context).
find_value(Key, Data, Options) when is_atom(Key), is_tuple(Data) ->
Rec = element(1, Data),
Info = proplists:get_value(record_info, Options, []),
case proplists:get_value(Rec, Info) of
Fields when is_list(Fields), length(Fields) == size(Data) - 1 ->
case proplists:get_value(Key, Fields) of
Idx when is_integer(Idx) -> element(Idx, Data);
_ -> undefined
end;
_ -> find_value(Key, Data)
end;
find_value(Key, Data, Options) when is_integer(Key), is_list(Data) ->
find_value(adjust_index(Key, 1, lists_0_based, Options), Data);
find_value(Key, Data, Options) when is_integer(Key), is_tuple(Data) ->
find_value(adjust_index(Key, 1, tuples_0_based, Options), Data);
find_value(Key, Data, _Options) ->
find_value(Key, Data).
adjust_index(Key, Off, Opt, Options) when is_list(Options) ->
case proplists:get_value(Opt, Options) of
defer ->
adjust_index(
Key, Off, Opt,
proplists:get_value(render_options, Options));
true ->
Key + Off;
_ ->
Key
end;
adjust_index(Key, _Off, _Opt, _Options) -> Key.
find_value(_, undefined) ->
undefined;
find_value(Key, Fun) when is_function(Fun, 1) ->
Fun(Key);
find_value(Key, L) when is_atom(Key), is_list(L) ->
case lists:keyfind(Key, 1, L) of
false -> find_value(atom_to_list(Key), L);
{Key, Value} -> Value
end;
find_value(Key, L) when is_list(Key), is_list(L) ->
case lists:keyfind(Key, 1, L) of
false -> find_value(list_to_binary(Key), L);
{Key, Value} -> Value
end;
find_value(Key, L) when is_binary(Key), is_list(L) ->
case lists:keyfind(Key, 1, L) of
false -> undefined;
{Key, Value} -> Value
end;
find_value(Key, L) when is_integer(Key), is_list(L) ->
if Key =< length(L) -> lists:nth(Key, L);
true -> undefined
end;
find_value(_, {0, nil}) -> undefined;
find_value(Key, {GBSize, {_, _, _, _}=GBData}) when is_integer(GBSize) ->
case gb_trees:lookup(Key, {GBSize, GBData}) of
{value, Val} ->
Val;
_ ->
undefined
end;
find_value(Key, Tuple) when is_tuple(Tuple) ->
case element(1, Tuple) of
L when is_list(L) andalso size(Tuple) =:= 1 ->
find_value(Key, L);
dict ->
case dict:find(Key, Tuple) of
{ok, Val} ->
Val;
_ ->
undefined
end;
_ when is_integer(Key) ->
if Key =< size(Tuple) -> element(Key, Tuple);
true -> undefined
end;
Module ->
case lists:member({Key, 1}, Module:module_info(exports)) of
true ->
case Tuple:Key() of
Val when is_tuple(Val) ->
case element(1, Val) of
'Elixir.Ecto.Associations.BelongsTo' -> Val:get();
'Elixir.Ecto.Associations.HasOne' -> Val:get();
_ -> Val
end;
Val -> Val
end;
_ ->
undefined
end
end;
find_value(Key, Map) ->
case erlang:is_builtin(erlang, is_map, 1) andalso erlang:is_map(Map) of
true -> find_map_value(Key, Map);
false -> undefined
end.
find_map_value(Key, Map) when is_atom(Key) ->
case maps:find(Key, Map) of
error -> find_map_value(atom_to_list(Key), Map);
{ok, Value} -> Value
end;
find_map_value(Key, Map) when is_list(Key) ->
case maps:find(Key, Map) of
error -> find_map_value(list_to_binary(Key), Map);
{ok, Value} -> Value
end;
find_map_value(Key, Map) when is_binary(Key) ->
case maps:find(Key, Map) of
error -> undefined;
{ok, Value} -> Value
end;
find_map_value(Key, Map) ->
case maps:find(Key, Map) of
error -> undefined;
{ok, Value} -> Value
end.
fetch_value(Key, Data, Options) ->
fetch_value(Key, Data, Options, []).
fetch_value(Key, Data, Options, Default) ->
case find_value(Key, Data, Options) of
undefined -> Default;
Val -> Val
end.
find_deep_value(Key, Data) ->
find_deep_value(Key, Data, []).
find_deep_value([Key|Rest], Item, Opts) ->
case find_value(Key, Item, Opts) of
undefined -> undefined;
NewItem -> find_deep_value(Rest, NewItem, Opts)
end;
find_deep_value([], Item, _Opts) -> Item.
regroup(List, Attribute) ->
do_regroup(List, Attribute, [], []).
regroup(List, Attribute, Options) ->
do_regroup(List, Attribute, Options, []).
do_regroup([], _, _, []) -> [];
do_regroup([], _, _, [[{grouper, LastGrouper}, {list, LastList}]|Acc]) ->
lists:reverse([[{grouper, LastGrouper}, {list, lists:reverse(LastList)}]|Acc]);
do_regroup([Item|Rest], Attribute, Options, []) ->
do_regroup(Rest, Attribute, Options, [[{grouper, find_deep_value(Attribute, Item, Options)}, {list, [Item]}]]);
do_regroup([Item|Rest], Attribute, Options, [[{grouper, PrevGrouper}, {list, PrevList}]|Acc]) ->
case find_deep_value(Attribute, Item, Options) of
Value when Value =:= PrevGrouper ->
do_regroup(Rest, Attribute, Options, [[{grouper, PrevGrouper}, {list, [Item|PrevList]}]|Acc]);
Value ->
do_regroup(Rest, Attribute, Options, [[{grouper, Value}, {list, [Item]}], [{grouper, PrevGrouper}, {list, lists:reverse(PrevList)}]|Acc])
end.
-spec init_translation(init_translation()) -> none | translate_fun().
init_translation(none) -> none;
init_translation(Fun) when is_function(Fun, 0) ->
init_translation(Fun());
init_translation({M, F}) ->
init_translation({M, F, []});
init_translation({M, F, A}) ->
init_translation(apply(M, F, A));
init_translation(Fun)
when is_function(Fun, 1); is_function(Fun, 2) -> Fun;
init_translation(Other) ->
throw({translation_fun, Other}).
-spec translate(Phrase, Locale, Fun) -> iodata() | default when
Phrase :: phrase(),
Locale :: locale(),
Fun :: none | translate_fun().
translate(Phrase, Locale, TranslationFun) ->
translate(Phrase, Locale, TranslationFun, trans_text(Phrase)).
translate(_Phrase, _Locale, none, Default) -> Default;
translate(Phrase, Locale, TranslationFun, Default) ->
case do_translate(Phrase, Locale, TranslationFun) of
default -> Default;
<<"">> -> Default;
"" -> Default;
Translated ->
Translated
end.
trans_text({Text, _}) -> Text;
trans_text(Text) -> Text.
do_translate(Phrase, _Locale, TranslationFun)
when is_function(TranslationFun, 1) ->
TranslationFun(trans_text(Phrase));
do_translate(Phrase, Locale, TranslationFun)
when is_function(TranslationFun, 2) ->
TranslationFun(Phrase, Locale).
%% @doc Translate and interpolate 'blocktrans' content.
%% Pre-requisites:
%% * `Variables' should be sorted
%% * Each interpolation variable should exist
%% (String="{{a}}", Variables=[{"b", "b-val"}] will fall)
%% * Orddict keys should be string(), not binary()
-spec translate_block(phrase(), locale(), atom(), orddict:orddict(), none | translate_fun()) -> iodata().
translate_block(Phrase, Locale, AutoEscape, Variables, TranslationFun) ->
case translate(Phrase, Locale, TranslationFun, default) of
default -> default;
Translated ->
try interpolate_variables(Translated, Variables, AutoEscape)
catch
{no_close_var, T} ->
io:format(standard_error, "Warning: template translation: variable not closed: \"~s\"~n", [T]),
default;
_:_ -> default
end
end.
interpolate_variables(Tpl, [], _) ->
Tpl;
interpolate_variables(Tpl, Variables, AutoEscape) ->
BTpl = iolist_to_binary(Tpl),
interpolate_variables1(BTpl, Variables, AutoEscape).
interpolate_variables1(Tpl, Vars, AutoEscape) ->
%% pre-compile binary patterns?
case binary:split(Tpl, <<"{{">>) of
[Tpl]=NoVars -> NoVars; %% need to enclose in list due to list tail call below..
[Pre, Post] ->
case binary:split(Post, <<"}}">>) of
[_] -> throw({no_close_var, Tpl});
[Var, Post1] ->
Var1 = string:strip(binary_to_list(Var)),
Value = cast(orddict:fetch(Var1, Vars), AutoEscape),
[Pre, Value | interpolate_variables1(Post1, Vars, AutoEscape)]
end
end.
cast(V, _) when is_integer(V); is_float(V) ->
erlydtl_filters:format_number(V);
cast(V, true) when is_binary(V); is_list(V) ->
erlydtl_filters:force_escape(V);
cast(V, false) when is_binary(V); is_list(V) ->
V;
cast(V, AutoEscape) ->
cast(io_lib:format("~p", [V]), AutoEscape).
are_equal(Arg1, Arg2) when Arg1 =:= Arg2 ->
true;
are_equal(Arg1, Arg2) when is_binary(Arg1) ->
are_equal(binary_to_list(Arg1), Arg2);
are_equal(Arg1, Arg2) when is_binary(Arg2) ->
are_equal(Arg1, binary_to_list(Arg2));
are_equal(Arg1, Arg2) when is_integer(Arg1) ->
are_equal(integer_to_list(Arg1), Arg2);
are_equal(Arg1, Arg2) when is_integer(Arg2) ->
are_equal(Arg1, integer_to_list(Arg2));
are_equal(Arg1, Arg2) when is_atom(Arg1), is_list(Arg2) ->
are_equal(atom_to_list(Arg1), Arg2);
are_equal(Arg1, Arg2) when is_list(Arg1), is_atom(Arg2) ->
are_equal(Arg1, atom_to_list(Arg2));
are_equal(_, _) ->
false.
is_false("") -> true;
is_false(false) -> true;
is_false(undefined) -> true;
is_false(null) -> true;
is_false(0) -> true;
is_false("0") -> true;
is_false(<<"0">>) -> true;
is_false(<<>>) -> true;
is_false(_) -> false.
is_true(V) -> not is_false(V).
'in'(Sublist, [Sublist|_]) ->
true;
'in'(Sublist, List) when is_atom(List) ->
'in'(Sublist, atom_to_list(List));
'in'(Sublist, List) when is_binary(Sublist) ->
'in'(binary_to_list(Sublist), List);
'in'(Sublist, List) when is_binary(List) ->
'in'(Sublist, binary_to_list(List));
'in'(Sublist, [C|Rest]) when is_list(Sublist) andalso is_binary(C) ->
'in'(Sublist, [binary_to_list(C)|Rest]);
'in'(Sublist, [C|Rest]) when is_list(Sublist) andalso is_list(C) ->
'in'(Sublist, Rest);
'in'(Sublist, List) when is_list(Sublist) andalso is_list(List) ->
string:str(List, Sublist) > 0;
'in'(Element, List) when is_list(List) ->
lists:member(Element, List);
'in'(_, _) ->
false.
'not'(Value) ->
not is_true(Value).
'or'(Value1, Value2) ->
is_true(Value1) or is_true(Value2).
'and'(Value1, Value2) ->
is_true(Value1) and is_true(Value2).
'eq'(Value1, Value2) ->
are_equal(Value1, Value2).
'ne'(Value1, Value2) ->
not are_equal(Value1, Value2).
'le'(Value1, Value2) ->
not 'gt'(Value1, Value2).
'ge'(Value1, Value2) ->
not 'lt'(Value1, Value2).
'gt'(Value1, Value2) when is_list(Value1) ->
'gt'(list_to_integer(Value1), Value2);
'gt'(Value1, Value2) when is_list(Value2) ->
'gt'(Value1, list_to_integer(Value2));
'gt'(Value1, Value2) when Value1 > Value2 ->
true;
'gt'(_, _) ->
false.
'lt'(Value1, Value2) when is_list(Value1) ->
'lt'(list_to_integer(Value1), Value2);
'lt'(Value1, Value2) when is_list(Value2) ->
'lt'(Value1, list_to_integer(Value2));
'lt'(Value1, Value2) when Value1 < Value2 ->
true;
'lt'(_, _) ->
false.
stringify_final(In, BinaryStrings) ->
stringify_final(In, [], BinaryStrings).
stringify_final([], Out, _) ->
lists:reverse(Out);
stringify_final([El | Rest], Out, false = BinaryStrings) when is_atom(El) ->
stringify_final(Rest, [atom_to_list(El) | Out], BinaryStrings);
stringify_final([El | Rest], Out, true = BinaryStrings) when is_atom(El) ->
stringify_final(Rest, [atom_to_binary(El, latin1) | Out], BinaryStrings);
stringify_final([El | Rest], Out, BinaryStrings) when is_list(El) ->
stringify_final(Rest, [stringify_final(El, BinaryStrings) | Out], BinaryStrings);
stringify_final([El | Rest], Out, false = BinaryStrings) when is_tuple(El) ->
stringify_final(Rest, [io_lib:print(El) | Out], BinaryStrings);
stringify_final([El | Rest], Out, true = BinaryStrings) when is_tuple(El) ->
stringify_final(Rest, [list_to_binary(io_lib:print(El)) | Out], BinaryStrings);
stringify_final([El | Rest], Out, BinaryStrings) ->
stringify_final(Rest, [El | Out], BinaryStrings).
to_list(Value, true) ->
lists:reverse(to_list(Value, false));
to_list(Value, false) when is_list(Value) ->
Value;
to_list(Value, false) when is_tuple(Value) ->
case element(1, Value) of
'Elixir.Ecto.Associations.HasMany' ->
Value:to_list();
_ ->
tuple_to_list(Value)
end.
init_counter_stats(List) ->
init_counter_stats(List, undefined).
init_counter_stats(List, Parent) when is_list(List) ->
ListLen = length(List),
[{counter, 1},
{counter0, 0},
{revcounter, ListLen},
{revcounter0, ListLen - 1},
{first, true},
{last, ListLen =:= 1},
{parentloop, Parent}].
increment_counter_stats([{counter, Counter}, {counter0, Counter0}, {revcounter, RevCounter},
{revcounter0, RevCounter0}, {first, _}, {last, _}, {parentloop, Parent}]) ->
[{counter, Counter + 1},
{counter0, Counter0 + 1},
{revcounter, RevCounter - 1},
{revcounter0, RevCounter0 - 1},
{first, false}, {last, RevCounter0 =:= 1},
{parentloop, Parent}].
forloop(_Fun, [], _Parent, Default) -> Default;
forloop(Fun, Values, Parent, _Default) ->
push_ifchanged_context(),
{Result, _Acc} = lists:mapfoldl(Fun, init_counter_stats(Values, Parent), Values),
pop_ifchanged_context(),
Result.
%% keep old version for backwards compatibility..
forloop(_Fun, [], _Parent) -> empty;
forloop(Fun, Values, Parent) ->
{forloop(Fun, Values, Parent, undefined), undefined}.
push_ifchanged_context() ->
IfChangedContextStack = case get(?IFCHANGED_CONTEXT_VARIABLE) of
undefined -> [];
Stack -> Stack
end,
put(?IFCHANGED_CONTEXT_VARIABLE, [[]|IfChangedContextStack]).
pop_ifchanged_context() ->
[_|Rest] = get(?IFCHANGED_CONTEXT_VARIABLE),
put(?IFCHANGED_CONTEXT_VARIABLE, Rest).
ifchanged(Expressions) ->
[IfChangedContext|Rest] = get(?IFCHANGED_CONTEXT_VARIABLE),
{Result, NewContext} = lists:foldl(fun (Expr, {ProvResult, Context}) when ProvResult == true ->
{_, NContext} = ifchanged2(Expr, Context),
{true, NContext};
(Expr, {_ProvResult, Context}) ->
ifchanged2(Expr, Context)
end, {false, IfChangedContext}, Expressions),
put(?IFCHANGED_CONTEXT_VARIABLE, [NewContext|Rest]),
Result.
ifchanged2({Key, Value}, IfChangedContext) ->
PreviousValue = proplists:get_value(Key, IfChangedContext),
if
PreviousValue =:= Value ->
{false, IfChangedContext};
true ->
NewContext = [{Key, Value}|proplists:delete(Key, IfChangedContext)],
{true, NewContext}
end.
cycle(NamesTuple, Counters) when is_tuple(NamesTuple) ->
element(find_value(counter0, Counters) rem size(NamesTuple) + 1, NamesTuple).
widthratio(Numerator, Denominator, Scale) ->
round(Numerator / Denominator * Scale).
spaceless(Contents) ->
Contents1 = lists:flatten(Contents),
Contents2 = re:replace(Contents1, "^\\s+<", "<", [{return,list}]),
Contents3 = re:replace(Contents2, ">\\s+$", ">", [{return,list}]),
Contents4 = re:replace(Contents3, ">\\s+<", "><", [global, {return,list}]),
Contents4.
read_file(Module, Function, DocRoot, FileName, ReaderOptions) ->
AbsName = case filename:absname(FileName) of
FileName -> FileName;
_ -> filename:join([DocRoot, FileName])
end,
case read_file_internal(Module, Function, AbsName, ReaderOptions) of
{ok, Data} -> Data;
{error, Reason} ->
throw({read_file, AbsName, Reason})
end.
read_file_internal(Module, Function, FileName, ReaderOptions) ->
case erlang:function_exported(Module, Function,1) of
true ->
Module:Function(FileName);
false ->
case erlang:function_exported(Module, Function,2) of
true ->
Module:Function(FileName, ReaderOptions);
false ->
{error, "Empty reader"}
end
end.