Packages
nitro
8.2.4
11.4.16
11.4.15
11.4.14
9.9.7
9.9.6
8.2.4
8.2.3
8.2.2
8.2.1
8.2.0
7.12.1
7.10.0
7.9.3
7.9.2
7.9.1
7.9.0
7.8.3
7.8.2
7.8.0
7.7.1
7.7.0
7.6.2
7.6.1
7.6.0
7.5.0
7.4.2
7.4.1
7.4.0
7.2.1
7.2.0
7.1.1
7.1.0
6.12.0
6.11.11
6.11.10
6.11.9
6.11.8
6.11.7
6.11.6
6.11.4
6.11.2
6.11.1
6.10.9
6.10.8
6.10.7
6.10.6
6.10.5
6.10.4
6.10.3
6.10.2
6.10.1
6.9.1
6.6.1
6.5.0
6.4.4
6.4.3
6.4.2
6.4.1
6.4.0
5.12.4
5.12.3
5.12.2
5.12.1
5.12.0
5.11.1
5.11.0
5.9.2
5.9.1
5.8.5
5.8.4
5.8.3
5.8.1
5.8.0
5.6.1
5.5.1
5.4.3
5.4.2
5.4.1
5.3.1
5.3.0
5.2.1
5.1.7
5.1.6
5.1.5
5.1.4
5.1.3
5.1.2
5.1.1
4.12.11
4.12.10
4.12.9
4.12.8
4.12.7
4.12.6
4.12.5
4.12.4
4.12.3
4.12.2
4.12.1
4.12.0
4.11.13
4.11.12
4.11.11
4.11.10
4.11.9
4.11.8
4.11.7
4.11.6
4.11.5
4.11.4
4.11.3
4.11.2
4.11.1
4.11.0
4.10.9
4.10.8
4.10.7
4.10.6
4.10.5
4.10.4
4.10.3
4.10.2
4.10.1
4.10.0
4.7.7
4.7.4
4.7.3
4.7.2
4.7.1
4.7.0
4.4.1
4.4.0
1.4.0
NITRO Nitrogen Web Framework
Current section
Files
Jump to
Current section
Files
src/nitro.erl
-module(nitro).
-include_lib("nitro/include/cx.hrl").
-include_lib("nitro/include/nitro.hrl").
-include_lib("nitro/include/event.hrl").
-compile(export_all).
-behaviour(application).
-export([start/2, stop/1, init/1]).
atom(List) when is_list(List) ->
string:join([nitro:to_list(L) || L <- List], "_");
atom(Scalar) -> nitro:to_list(Scalar).
q(Key) -> q(Key, []).
q(Key, Def) ->
case get(Key) of
undefined -> Def;
Val -> Val
end.
qc(Key) ->
CX = get(context),
qc(Key, CX#cx.req).
qc(Key, Req) ->
proplists:get_value(nitro:to_binary(Key),
cowboy_req:parse_qs(Req)).
start(_StartType, _StartArgs) ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
stop(_State) -> ok.
init([]) -> {ok, {{one_for_one, 5, 10}, []}}.
f(S) -> f(S, []).
f(S, Args) -> lists:flatten(io_lib:format(S, Args)).
coalesce([]) -> undefined;
coalesce([H]) -> H;
coalesce([undefined | T]) -> coalesce(T);
coalesce([[] | T]) -> coalesce(T);
coalesce([H | _]) -> H.
jse(X) -> js_escape(X).
hte(X) when is_binary(X) ->
nitro:to_binary(nitro_conv:html_encode(X));
hte(X) -> nitro_conv:html_encode(X).
js_escape(Value) -> nitro_conv:js_escape(Value).
-define(IS_STRING(Term),
is_list(Term) andalso
Term /= [] andalso is_integer(hd(Term))).
to_list(L) when ?IS_STRING(L) -> L;
to_list(L) when is_list(L) ->
SubLists = [inner_to_list(X) || X <- L],
lists:flatten(SubLists);
to_list(A) -> inner_to_list(A).
inner_to_list(A) when is_atom(A) -> atom_to_list(A);
inner_to_list(B) when is_binary(B) -> binary_to_list(B);
inner_to_list(I) when is_integer(I) ->
integer_to_list(I);
inner_to_list(L) when is_tuple(L) ->
lists:flatten(io_lib:format("~p", [L]));
inner_to_list(L) when is_pid(L) ->
lists:flatten(io_lib:format("~p", [L]));
inner_to_list(L) when is_list(L) -> L;
inner_to_list(F) when is_float(F) ->
float_to_list(F, [{decimals, 9}, compact]).
to_atom(A) when is_atom(A) -> A;
to_atom(B) when is_binary(B) ->
to_atom(binary_to_list(B));
to_atom(I) when is_integer(I) ->
to_atom(integer_to_list(I));
to_atom(F) when is_float(F) ->
to_atom(float_to_list(F, [{decimals, 9}, compact]));
to_atom(L) when is_list(L) ->
list_to_atom(binary_to_list(list_to_binary(L))).
to_binary(A) when is_atom(A) ->
atom_to_binary(A, latin1);
to_binary(B) when is_binary(B) -> B;
to_binary(I) when is_integer(I) ->
to_binary(integer_to_list(I));
to_binary(F) when is_float(F) ->
float_to_binary(F, [{decimals, 9}, compact]);
to_binary(L) when is_list(L) -> iolist_to_binary(L);
to_binary(X) when is_tuple(X) -> term_to_binary(X).
-ifndef(PICKLER).
-define(PICKLER,
application:get_env(n2o, pickler, nitro_conv)).
-endif.
pickle(Data) -> (?PICKLER):pickle(Data).
depickle(SerializedData) ->
(?PICKLER):depickle(SerializedData).
prolongate() ->
case application:get_env(n2o, session) of
{ok, M} -> M:prolongate();
undefined -> false
end.
authenticate(I, Auth) ->
(application:get_env(n2o,
session,
n2o_session)):authenticate(I, Auth).
render(X) -> wf_render:render(X).
wire(Actions) -> action_wire:wire(Actions).
unique_integer() -> erlang:unique_integer().
temp_id() ->
"auto" ++ integer_to_list(unique_integer() rem 1000000).
html_encode(L, Fun) when is_function(Fun) -> Fun(L);
html_encode(L, EncType) when is_atom(L) ->
html_encode(nitro:to_list(L), EncType);
html_encode(L, EncType) when is_integer(L) ->
html_encode(integer_to_list(L), EncType);
html_encode(L, EncType) when is_float(L) ->
html_encode(float_to_list(L, [{decimals, 9}, compact]),
EncType);
html_encode(L, false) -> L;
html_encode(L, true) -> L;
html_encode(L, whites) ->
html_encode_whites(nitro:to_list(lists:flatten([L]))).
html_encode(<<>>) -> [];
html_encode([]) -> [];
html_encode([H | T]) ->
case H of
$< -> "<" ++ html_encode(T);
$> -> ">" ++ html_encode(T);
$" -> """ ++ html_encode(T);
$' -> "'" ++ html_encode(T);
$& -> "&" ++ html_encode(T);
BigNum when is_integer(BigNum) andalso BigNum > 255 ->
[$&, $# | nitro:to_list(BigNum)] ++
";" ++ html_encode(T);
Tup when is_tuple(Tup) ->
throw({html_encode, encountered_tuple, Tup});
_ -> [H | html_encode(T)]
end.
html_encode_whites([]) -> [];
html_encode_whites([H | T]) ->
case H of
$\s -> " " ++ html_encode_whites(T);
$\t ->
" " ++
html_encode_whites(T);
$< -> "<" ++ html_encode_whites(T);
$> -> ">" ++ html_encode_whites(T);
$" -> """ ++ html_encode_whites(T);
$' -> "'" ++ html_encode_whites(T);
$& -> "&" ++ html_encode_whites(T);
$\n -> "<br>" ++ html_encode_whites(T);
_ -> [H | html_encode_whites(T)]
end.
script() -> get(script).
script(Script) -> put(script, Script).
% Update DOM nitro:update
update(Target, Elements) ->
{Render, _, Actions} = render_html(Elements),
nitro:wire(nitro:f("var x=qi('~s'); if(x) x.outerHTML=`~s`;", [Target, Render])),
nitro:wire(nitro:render(Actions)).
insert_top(Tag, Target, Elements) ->
{Render, _Ref, Actions} = render_html(Elements),
nitro:wire(nitro:f("var x=qi('~s'); if(x) { x.insertBefore((function(){var "
"div = qn('~s'); div.innerHTML = `~s`; "
"return div.firstChild; })(),qi('~s').firstChi"
"ld); }",
[Target, Tag, Render, Target])),
nitro:wire(nitro:render(Actions)).
insert_bottom(Tag, Target, Elements) ->
{Render, _Ref, Actions} = render_html(Elements),
nitro:wire(nitro:f("(function(){ var div = qn('~s');"
"let x = qi('~s'); if(x){ div.innerHTML = `~s`;"
"x.appendChild(div.firstChild);"
"}})();",
[Tag, Target, Render])),
nitro:wire(nitro:render(Actions)).
insert_before(Target, Elements) ->
insert_adjacent(beforebegin, Target, Elements).
insert_after(Target, Elements) ->
insert_adjacent(afterend, Target, Elements).
insert_adjacent(Command, Target, Elements) ->
insert_adjacent(Command, Target, Elements, "qi").
insert_adjacent(Command, Target, Elements, Q) ->
{Render, _Ref, Actions} = render_html(Elements),
nitro:wire(nitro:f("~s('~s').insertAdjacentHTML('~s', `~s`);",
[Q, Target, Command, Render])),
nitro:wire(nitro:render(Actions)).
render_html(Elements) ->
Pid = self(),
Ref = make_ref(),
spawn(fun () ->
R = nitro:render(Elements),
Pid ! {R, Ref, nitro:actions()}
end),
{Render, Ref, Actions} = receive
{_, Ref, _} = A -> A
end,
{Render, Ref, Actions}.
actions() -> get(actions).
actions(Ac) -> put(actions, Ac).
insert_top(Target, Elements)
when element(1, Elements) == tr ->
insert_top(tbody, Target, Elements);
insert_top(Target, Elements) ->
insert_top('div', Target, Elements).
insert_bottom(Target, Elements)
when element(1, Elements) == tr ->
insert_bottom(tbody, Target, Elements);
insert_bottom(Target, Elements) ->
insert_bottom('div', Target, Elements).
clear(Target) ->
nitro:wire("var x = qi('" ++
nitro:to_list(Target) ++
"'); while (x && x.firstChild) x.removeChild(x"
".firstChild);").
remove(Target) ->
nitro:wire("var x=qi('" ++
nitro:to_list(Target) ++
"'); x && x.parentNode.removeChild(x);").
% Wire JavaScript nitro:wire
state(Key) -> erlang:get(Key).
state(Key, Value) -> erlang:put(Key, Value).
% Redirect and purge connection nitro:redirect
redirect(Url) ->
nitro:wire(#jq{target = window, property = location,
args = simple, right = Url}).
%header(K,V) -> nitro:context((?CTX)#cx{req=cowboy_req:set_resp_header(K,V,?CTX#cx.req)}).
setAttr(Element, Attr, Value) ->
nitro:wire("{ var x = qi('" ++
nitro:to_list(Element) ++
"'); if (x) x.setAttribute('" ++
nitro:to_list(Attr) ++
"', '" ++ nitro:to_list(Value) ++ "'); }").
style(Element, Style) ->
setAttr(Element, "style", Style).
style(Element, Style, Value) ->
nitro:wire("{ var x = qi('" ++
nitro:to_list(Element) ++
"'); if (x) x.style." ++
nitro:to_list(Style) ++
" = '" ++ nitro:to_list(Value) ++ "'; }").
display(Element, Status) ->
style(Element, "display", Status).
show(Element) -> display(Element, block).
hide(Element) -> display(Element, none).
compact([]) -> "[]";
compact("\n") -> "[]";
compact([X | _] = Y) when is_tuple(X) ->
[compact(F) || F <- Y];
compact(Tuple) when is_binary(Tuple) ->
unicode:characters_to_binary(Tuple);
compact(Tuple) when is_tuple(Tuple) ->
Min = erlang:min(9, size(Tuple)),
Fields = lists:zip(lists:seq(1, Min),
lists:sublist(tuple_to_list(Tuple), 1, Min)),
"{" ++
string:join([io_lib:format("~s", [compact(F)])
|| {_, F} <- Fields],
",")
++ "}";
compact(Tuple) -> nitro:jse(nitro:to_list(Tuple)).
meg(X) -> integer_to_list(X div 1000000) ++ "M".
rev(X) -> lists:reverse(X).
num(S) ->
case rev(S) of
[$K | K] -> list_to_integer(rev(K)) * 1000;
[$M | M] -> list_to_integer(rev(M)) * 1000 * 1000;
[$G | G] ->
list_to_integer(rev(G)) * 1000 * 1000 * 1000;
[$T | T] ->
list_to_integer(rev(T)) * 1000 * 1000 * 1000 * 1000
end.
cookie_expire(SecondsToLive) ->
Seconds =
calendar:datetime_to_gregorian_seconds(calendar:local_time()),
DateTime =
calendar:gregorian_seconds_to_datetime(Seconds +
SecondsToLive),
cow_date:rfc2109(DateTime).
cookie(Id, Value) ->
cookie(Id, Value, 2147483647). % expire never
cookie(Id, Value, Expire) ->
Format = "document.cookie='~s=~s; path=/; expires=~s';",
nitro:wire(nitro:f(Format,
[nitro:to_list(Id),
nitro:to_list(Value),
cookie_expire(Expire)])).
cookies() ->
cowboy_req:parse_cookies((get(context))#cx.req).
cookie(Key) ->
case lists:keyfind(Key,
1,
cowboy_req:parse_cookies((get(context))#cx.req))
of
false -> undefined;
{_, Value} -> Value
end.