123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- -module(erlydtl_runtime).
- -compile(export_all).
- -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) ->
- find_value(Key, Data).
- 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(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
- 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.
- fetch_value(Key, Data, Options) ->
- case find_value(Key, Data, Options) of
- undefined -> [];
- Val -> Val
- end.
- find_deep_value([Key|Rest],Item) ->
- case find_value(Key,Item) of
- undefined -> undefined;
- NewItem -> find_deep_value(Rest,NewItem)
- end;
- find_deep_value([],Item) -> Item.
- regroup(List, Attribute) ->
- regroup(List, Attribute, []).
- regroup([], _, []) ->
- [];
- regroup([], _, [[{grouper, LastGrouper}, {list, LastList}]|Acc]) ->
- lists:reverse([[{grouper, LastGrouper}, {list, lists:reverse(LastList)}]|Acc]);
- regroup([Item|Rest], Attribute, []) ->
- regroup(Rest, Attribute, [[{grouper, find_deep_value(Attribute, Item)}, {list, [Item]}]]);
- regroup([Item|Rest], Attribute, [[{grouper, PrevGrouper}, {list, PrevList}]|Acc]) ->
- case find_deep_value(Attribute, Item) of
- Value when Value =:= PrevGrouper ->
- regroup(Rest, Attribute, [[{grouper, PrevGrouper}, {list, [Item|PrevList]}]|Acc]);
- Value ->
- regroup(Rest, Attribute, [[{grouper, Value}, {list, [Item]}], [{grouper, PrevGrouper}, {list, lists:reverse(PrevList)}]|Acc])
- end.
- translate(_, none, Default) ->
- Default;
- translate(String, TranslationFun, Default) when is_function(TranslationFun) ->
- case TranslationFun(String) of
- undefined -> Default;
- <<"">> -> Default;
- "" -> Default;
- Str -> Str
- end.
- 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(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) ->
- [{counter, 1},
- {counter0, 0},
- {revcounter, length(List)},
- {revcounter0, length(List) - 1},
- {first, true},
- {last, length(List) =:= 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, Acc0, Values) ->
- push_ifchanged_context(),
- Result = lists:mapfoldl(Fun, Acc0, Values),
- pop_ifchanged_context(),
- Result.
- 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) ->
- AbsName = case filename:absname(FileName) of
- FileName -> FileName;
- _ -> filename:join([DocRoot, FileName])
- end,
- {ok, Binary} = Module:Function(AbsName),
- binary_to_list(Binary).
|