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@internal@engine.erl
Raw

src/handles@internal@engine.erl

-module(handles@internal@engine).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([eval/4, run/4]).
-export_type([action/0]).
-type action() :: {append, binary()} |
{set_ctx, handles@ctx:value()} |
{continue, list(handles@internal@parser:ast())} |
{stop, handles@error:runtime_error()}.
-spec eval(
list(action()),
handles@ctx:value(),
gleam@dict:dict(binary(), list(handles@internal@parser:ast())),
gleam@string_builder:string_builder()
) -> {ok, gleam@string_builder:string_builder()} |
{error, handles@error:runtime_error()}.
eval(Actions, Ctx, Partials, Builder) ->
case Actions of
[] ->
{ok, Builder};
[{stop, Err}] ->
{error, Err};
[{stop, Err@1} | _] ->
{error, Err@1};
[{append, Value} | Rest_action] ->
eval(
Rest_action,
Ctx,
Partials,
gleam@string_builder:append(Builder, Value)
);
[{set_ctx, Ctx@1} | Rest_action@1] ->
eval(Rest_action@1, Ctx@1, Partials, Builder);
[{continue, []} | Rest_action@2] ->
eval(Rest_action@2, Ctx, Partials, Builder);
[{continue, [{constant, _, Value@1} | Rest_ast]} | Rest_action@3] ->
eval(
[{append, Value@1}, {continue, Rest_ast} | Rest_action@3],
Ctx,
Partials,
Builder
);
[{continue, [{property, Index, Path} | Rest_ast@1]} | Rest_action@4] ->
case handles@internal@ctx_utils:get_property(Path, Ctx, Index) of
{ok, Str} ->
eval(
[{append, Str}, {continue, Rest_ast@1} | Rest_action@4],
Ctx,
Partials,
Builder
);
{error, Err@2} ->
eval([{stop, Err@2}], Ctx, Partials, Builder)
end;
[{continue, [{partial, Index@1, Id, Path@1} | Rest_ast@2]} |
Rest_action@5] ->
case gleam@dict:get(Partials, Id) of
{error, _} ->
eval(
[{stop, {unknown_partial, Index@1, Id}}],
Ctx,
Partials,
Builder
);
{ok, Partial} ->
case handles@internal@ctx_utils:get(Path@1, Ctx, Index@1) of
{error, Err@3} ->
eval([{stop, Err@3}], Ctx, Partials, Builder);
{ok, New_ctx} ->
eval(
[{set_ctx, New_ctx},
{continue, Partial},
{set_ctx, Ctx},
{continue, Rest_ast@2} |
Rest_action@5],
Ctx,
Partials,
Builder
)
end
end;
[{continue, [{if_block, Index@2, Path@2, Children} | Rest_ast@3]} |
Rest_action@6] ->
case handles@internal@ctx_utils:get_bool(Path@2, Ctx, Index@2) of
{error, Err@4} ->
eval([{stop, Err@4}], Ctx, Partials, Builder);
{ok, false} ->
eval(
[{continue, Rest_ast@3} | Rest_action@6],
Ctx,
Partials,
Builder
);
{ok, true} ->
eval(
[{continue, Children},
{continue, Rest_ast@3} |
Rest_action@6],
Ctx,
Partials,
Builder
)
end;
[{continue, [{unless_block, Index@3, Path@3, Children@1} | Rest_ast@4]} |
Rest_action@7] ->
case handles@internal@ctx_utils:get_bool(Path@3, Ctx, Index@3) of
{error, Err@5} ->
eval([{stop, Err@5}], Ctx, Partials, Builder);
{ok, true} ->
eval(
[{continue, Rest_ast@4} | Rest_action@7],
Ctx,
Partials,
Builder
);
{ok, false} ->
eval(
[{continue, Children@1},
{continue, Rest_ast@4} |
Rest_action@7],
Ctx,
Partials,
Builder
)
end;
[{continue, [{each_block, Index@4, Path@4, Children@2} | Rest_ast@5]} |
Rest_action@8] ->
case handles@internal@ctx_utils:get_list(Path@4, Ctx, Index@4) of
{error, Err@6} ->
eval([{stop, Err@6}], Ctx, Partials, Builder);
{ok, []} ->
eval(
[{continue, Rest_ast@5} | Rest_action@8],
Ctx,
Partials,
Builder
);
{ok, Ctxs} ->
eval(
begin
_pipe = Ctxs,
_pipe@1 = gleam@list:flat_map(
_pipe,
fun(New_ctx@1) ->
[{set_ctx, New_ctx@1},
{continue, Children@2},
{set_ctx, Ctx}]
end
),
lists:append(
_pipe@1,
[{continue, Rest_ast@5} | Rest_action@8]
)
end,
Ctx,
Partials,
Builder
)
end
end.
-spec run(
list(handles@internal@parser:ast()),
handles@ctx:value(),
gleam@dict:dict(binary(), list(handles@internal@parser:ast())),
gleam@string_builder:string_builder()
) -> {ok, gleam@string_builder:string_builder()} |
{error, handles@error:runtime_error()}.
run(Ast, Ctx, Partials, Builder) ->
eval([{continue, Ast}], Ctx, Partials, Builder).