Packages

Handles is a templating language written in pure Gleam. Heavily inspired by Mustache and Handlebars.js

Current section

Files

Jump to
handles src handles@engine.erl
Raw

src/handles@engine.erl

-module(handles@engine).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([get_as_string/2, get_as_bool/2, get_as_list/2, run/2]).
-export_type([runtime_error/0]).
-type runtime_error() :: {unexpected_type_error,
list(binary()),
binary(),
list(binary())} |
{unknown_property_error, list(binary())}.
-spec get_from_ctx(gleam@dynamic:dynamic_(), list(binary())) -> {ok,
gleam@dynamic:dynamic_()} |
{error, runtime_error()}.
get_from_ctx(Root_ctx, Path) ->
_pipe = Path,
gleam@list:fold(
_pipe,
{ok, Root_ctx},
fun(Ctx, It) -> gleam@result:'try'(Ctx, fun(Ctx@1) -> _pipe@1 = Ctx@1,
_pipe@2 = (gleam@dynamic:field(
It,
fun gleam@dynamic:dynamic/1
))(_pipe@1),
gleam@result:map_error(
_pipe@2,
fun(_) -> {unknown_property_error, Path} end
) end) end
).
-spec get_as_string(gleam@dynamic:dynamic_(), list(binary())) -> {ok, binary()} |
{error, runtime_error()}.
get_as_string(Root_ctx, Path) ->
_pipe = get_from_ctx(Root_ctx, Path),
gleam@result:'try'(
_pipe,
fun(Value) -> case gleam@dynamic:classify(Value) of
<<"String"/utf8>> ->
_pipe@1 = Value,
_pipe@2 = gleam@dynamic:string(_pipe@1),
gleam@result:map_error(
_pipe@2,
fun(Err) ->
gleam@io:debug(Err),
erlang:error(#{gleam_error => panic,
message => <<"TypeConvertionError"/utf8>>,
module => <<"handles/engine"/utf8>>,
function => <<"get_as_string"/utf8>>,
line => 41})
end
);
<<"Int"/utf8>> ->
_pipe@3 = Value,
_pipe@4 = gleam@dynamic:int(_pipe@3),
_pipe@5 = gleam@result:map(
_pipe@4,
fun gleam@int:to_string/1
),
gleam@result:map_error(
_pipe@5,
fun(Err@1) ->
gleam@io:debug(Err@1),
erlang:error(#{gleam_error => panic,
message => <<"TypeConvertionError"/utf8>>,
module => <<"handles/engine"/utf8>>,
function => <<"get_as_string"/utf8>>,
line => 50})
end
);
<<"Float"/utf8>> ->
_pipe@6 = Value,
_pipe@7 = gleam@dynamic:float(_pipe@6),
_pipe@8 = gleam@result:map(
_pipe@7,
fun gleam@float:to_string/1
),
gleam@result:map_error(
_pipe@8,
fun(Err@2) ->
gleam@io:debug(Err@2),
erlang:error(#{gleam_error => panic,
message => <<"TypeConvertionError"/utf8>>,
module => <<"handles/engine"/utf8>>,
function => <<"get_as_string"/utf8>>,
line => 59})
end
);
Typ ->
{error,
{unexpected_type_error,
Path,
Typ,
[<<"String"/utf8>>,
<<"Int"/utf8>>,
<<"Float"/utf8>>]}}
end end
).
-spec get_as_bool(gleam@dynamic:dynamic_(), list(binary())) -> {ok, boolean()} |
{error, runtime_error()}.
get_as_bool(Root_ctx, Path) ->
_pipe = get_from_ctx(Root_ctx, Path),
gleam@result:'try'(
_pipe,
fun(Value) -> case gleam@dynamic:classify(Value) of
<<"Bool"/utf8>> ->
_pipe@1 = Value,
_pipe@2 = gleam@dynamic:bool(_pipe@1),
gleam@result:map_error(
_pipe@2,
fun(Err) ->
gleam@io:debug(Err),
erlang:error(#{gleam_error => panic,
message => <<"TypeConvertionError"/utf8>>,
module => <<"handles/engine"/utf8>>,
function => <<"get_as_bool"/utf8>>,
line => 79})
end
);
Typ ->
{error,
{unexpected_type_error, Path, Typ, [<<"Bool"/utf8>>]}}
end end
).
-spec get_as_list(gleam@dynamic:dynamic_(), list(binary())) -> {ok,
list(gleam@dynamic:dynamic_())} |
{error, runtime_error()}.
get_as_list(Root_ctx, Path) ->
_pipe = get_from_ctx(Root_ctx, Path),
gleam@result:'try'(
_pipe,
fun(Value) -> case gleam@dynamic:classify(Value) of
<<"List"/utf8>> ->
_pipe@1 = Value,
_pipe@2 = gleam@dynamic:shallow_list(_pipe@1),
gleam@result:map_error(
_pipe@2,
fun(Err) ->
gleam@io:debug(Err),
erlang:error(#{gleam_error => panic,
message => <<"TypeConvertionError"/utf8>>,
module => <<"handles/engine"/utf8>>,
function => <<"get_as_list"/utf8>>,
line => 99})
end
);
Typ ->
{error,
{unexpected_type_error, Path, Typ, [<<"List"/utf8>>]}}
end end
).
-spec run(list(handles@parser:ast()), gleam@dynamic:dynamic_()) -> {ok,
binary()} |
{error, runtime_error()}.
run(Ast, Ctx) ->
_pipe@8 = (gleam@list:fold(
Ast,
{ok, gleam@string_builder:new()},
fun(Acc, It) -> gleam@result:'try'(Acc, fun(Acc@1) -> case It of
{constant, Value} ->
{ok, gleam@string_builder:append(Acc@1, Value)};
{property, Path} ->
_pipe = get_as_string(Ctx, Path),
gleam@result:map(
_pipe,
fun(_capture) ->
gleam@string_builder:append(Acc@1, _capture)
end
);
{block, Kind, Path@1, Children} ->
case Kind of
<<"if"/utf8>> ->
_pipe@1 = get_as_bool(Ctx, Path@1),
_pipe@2 = gleam@result:'try'(
_pipe@1,
fun(_capture@1) ->
eval_if(_capture@1, Children, Ctx)
end
),
gleam@result:map(
_pipe@2,
fun(_capture@2) ->
gleam@string_builder:append(
Acc@1,
_capture@2
)
end
);
<<"unless"/utf8>> ->
_pipe@3 = get_as_bool(Ctx, Path@1),
_pipe@4 = gleam@result:map(
_pipe@3,
fun gleam@bool:negate/1
),
_pipe@5 = gleam@result:'try'(
_pipe@4,
fun(_capture@3) ->
eval_if(_capture@3, Children, Ctx)
end
),
gleam@result:map(
_pipe@5,
fun(_capture@4) ->
gleam@string_builder:append(
Acc@1,
_capture@4
)
end
);
<<"each"/utf8>> ->
_pipe@6 = get_as_list(Ctx, Path@1),
_pipe@7 = gleam@result:'try'(
_pipe@6,
fun(_capture@5) ->
eval_each(_capture@5, Children)
end
),
gleam@result:map(
_pipe@7,
fun(_capture@6) ->
gleam@string_builder:append(
Acc@1,
_capture@6
)
end
);
_ ->
erlang:error(#{gleam_error => panic,
message => <<"Unknown block"/utf8>>,
module => <<"handles/engine"/utf8>>,
function => <<"run"/utf8>>,
line => 161})
end
end end) end
)),
gleam@result:map(_pipe@8, fun gleam@string_builder:to_string/1).
-spec eval_if(boolean(), list(handles@parser:ast()), gleam@dynamic:dynamic_()) -> {ok,
binary()} |
{error, runtime_error()}.
eval_if(Condition, Children, Ctx) ->
case Condition of
false ->
{ok, <<""/utf8>>};
true ->
run(Children, Ctx)
end.
-spec eval_each(list(gleam@dynamic:dynamic_()), list(handles@parser:ast())) -> {ok,
binary()} |
{error, runtime_error()}.
eval_each(Ctx_list, Children) ->
_pipe@1 = (gleam@list:fold(
Ctx_list,
{ok, gleam@string_builder:new()},
fun(Acc, Ctx) ->
gleam@result:'try'(Acc, fun(Acc@1) -> _pipe = run(Children, Ctx),
gleam@result:map(
_pipe,
fun(_capture) ->
gleam@string_builder:append(Acc@1, _capture)
end
) end)
end
)),
gleam@result:map(_pipe@1, fun gleam@string_builder:to_string/1).