Current section
Files
Jump to
Current section
Files
src/ginger.erl
-module(ginger).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/ginger.gleam").
-export([from_file/1, from_string/1, render/2, render_with_loops/2, new_context/0, set_variable/3, set_list/3, new_engine/1, load_template_content/2, render_template/3, render_simple_template/3, clear_cache/1, context_from_list/1]).
-export_type([template/0, template_context/0, template_engine/0, template_error/0]).
-type template() :: {template, binary()}.
-type template_context() :: {template_context,
gleam@dict:dict(binary(), binary()),
gleam@dict:dict(binary(), list(binary()))}.
-type template_engine() :: {template_engine,
binary(),
gleam@dict:dict(binary(), binary())}.
-type template_error() :: {io_error, binary()} | {regex_error, binary()}.
-file("src/ginger.gleam", 29).
-spec from_file(binary()) -> {ok, template()} | {error, template_error()}.
from_file(Path) ->
case simplifile:read(Path) of
{ok, Content} ->
{ok, {template, Content}};
{error, _} ->
{error, {io_error, <<"Failed to read file: "/utf8, Path/binary>>}}
end.
-file("src/ginger.gleam", 36).
-spec from_string(binary()) -> template().
from_string(Content) ->
{template, Content}.
-file("src/ginger.gleam", 72).
-spec replace_matches(
binary(),
list(gleam@regexp:match()),
gleam@dict:dict(binary(), binary())
) -> binary().
replace_matches(Content, Matches, Context) ->
gleam@list:fold(
Matches,
Content,
fun(Acc, Match) -> case erlang:element(3, Match) of
[{some, Var_name}] ->
case gleam_stdlib:map_get(Context, Var_name) of
{ok, Value} ->
gleam@string:replace(
Acc,
erlang:element(2, Match),
Value
);
{error, _} ->
Acc
end;
_ ->
Acc
end end
).
-file("src/ginger.gleam", 58).
-spec render_variables(binary(), gleam@dict:dict(binary(), binary())) -> {ok,
binary()} |
{error, template_error()}.
render_variables(Content, Context) ->
case gleam@regexp:from_string(<<"\\{\\%\\s*(\\w+)\\s*\\%\\}"/utf8>>) of
{ok, Re} ->
Matches = gleam@regexp:scan(Re, Content),
Result = replace_matches(Content, Matches, Context),
{ok, Result};
{error, _} ->
{error, {regex_error, <<"Failed to compile variable regex"/utf8>>}}
end.
-file("src/ginger.gleam", 40).
-spec render(template(), gleam@dict:dict(binary(), binary())) -> {ok, binary()} |
{error, template_error()}.
render(Template, Context) ->
{template, Content} = Template,
render_variables(Content, Context).
-file("src/ginger.gleam", 137).
-spec replace_loop_variable(binary(), binary(), binary()) -> binary().
replace_loop_variable(Template, Var_name, Value) ->
Target = <<<<"{{ "/utf8, Var_name/binary>>/binary, " }}"/utf8>>,
Target_no_spaces = <<<<"{{"/utf8, Var_name/binary>>/binary, "}}"/utf8>>,
_pipe = Template,
_pipe@1 = gleam@string:replace(_pipe, Target, Value),
gleam@string:replace(_pipe@1, Target_no_spaces, Value).
-file("src/ginger.gleam", 106).
-spec process_loops_recursive(
binary(),
template_context(),
gleam@regexp:regexp()
) -> {ok, binary()} | {error, template_error()}.
process_loops_recursive(Content, Context, Loop_re) ->
case gleam@regexp:scan(Loop_re, Content) of
[] ->
{ok, Content};
[First_match | _] ->
case erlang:element(3, First_match) of
[{some, Var_name}, {some, List_name}, {some, Loop_body}] ->
Loop_result = case gleam_stdlib:map_get(
erlang:element(3, Context),
List_name
) of
{ok, Items} ->
gleam@list:fold(
Items,
<<""/utf8>>,
fun(Acc, Item) ->
Item_content = replace_loop_variable(
Loop_body,
Var_name,
Item
),
<<Acc/binary, Item_content/binary>>
end
);
{error, _} ->
<<""/utf8>>
end,
New_content = gleam@string:replace(
Content,
erlang:element(2, First_match),
Loop_result
),
process_loops_recursive(New_content, Context, Loop_re);
_ ->
{ok, Content}
end
end.
-file("src/ginger.gleam", 90).
-spec process_loops(binary(), template_context()) -> {ok, binary()} |
{error, template_error()}.
process_loops(Content, Context) ->
case gleam@regexp:from_string(
<<"\\{%\\s*for\\s+(\\w+)\\s+in\\s+(\\w+)\\s*%\\}([\\s\\S]*?)\\{%\\s*endfor\\s*%\\}"/utf8>>
) of
{ok, Loop_re} ->
process_loops_recursive(Content, Context, Loop_re);
{error, _} ->
{error, {regex_error, <<"Failed to compile loop regex"/utf8>>}}
end.
-file("src/ginger.gleam", 48).
-spec render_with_loops(template(), template_context()) -> {ok, binary()} |
{error, template_error()}.
render_with_loops(Template, Context) ->
{template, Content} = Template,
gleam@result:'try'(
process_loops(Content, Context),
fun(Looped_content) ->
render_variables(Looped_content, erlang:element(2, Context))
end
).
-file("src/ginger.gleam", 150).
-spec new_context() -> template_context().
new_context() ->
{template_context, maps:new(), maps:new()}.
-file("src/ginger.gleam", 154).
-spec set_variable(template_context(), binary(), binary()) -> template_context().
set_variable(Context, Key, Value) ->
{template_context,
gleam@dict:insert(erlang:element(2, Context), Key, Value),
erlang:element(3, Context)}.
-file("src/ginger.gleam", 165).
-spec set_list(template_context(), binary(), list(binary())) -> template_context().
set_list(Context, Key, Items) ->
{template_context,
erlang:element(2, Context),
gleam@dict:insert(erlang:element(3, Context), Key, Items)}.
-file("src/ginger.gleam", 176).
-spec new_engine(binary()) -> template_engine().
new_engine(Template_dir) ->
{template_engine, Template_dir, maps:new()}.
-file("src/ginger.gleam", 180).
-spec load_template_content(template_engine(), binary()) -> {ok,
{template_engine(), binary()}} |
{error, template_error()}.
load_template_content(Engine, Name) ->
case gleam_stdlib:map_get(erlang:element(3, Engine), Name) of
{ok, Content} ->
{ok, {Engine, Content}};
{error, _} ->
Template_path = <<<<<<(erlang:element(2, Engine))/binary, "/"/utf8>>/binary,
Name/binary>>/binary,
".html"/utf8>>,
case simplifile:read(Template_path) of
{ok, Content@1} ->
New_cache = gleam@dict:insert(
erlang:element(3, Engine),
Name,
Content@1
),
New_engine = {template_engine,
erlang:element(2, Engine),
New_cache},
{ok, {New_engine, Content@1}};
{error, _} ->
{error,
{io_error,
<<"Failed to load template: "/utf8,
Template_path/binary>>}}
end
end.
-file("src/ginger.gleam", 200).
-spec render_template(template_engine(), binary(), template_context()) -> {ok,
{template_engine(), binary()}} |
{error, template_error()}.
render_template(Engine, Template_name, Context) ->
gleam@result:'try'(
load_template_content(Engine, Template_name),
fun(_use0) ->
{New_engine, Content} = _use0,
Template = {template, Content},
gleam@result:'try'(
render_with_loops(Template, Context),
fun(Rendered) -> {ok, {New_engine, Rendered}} end
)
end
).
-file("src/ginger.gleam", 214).
-spec render_simple_template(
template_engine(),
binary(),
gleam@dict:dict(binary(), binary())
) -> {ok, {template_engine(), binary()}} | {error, template_error()}.
render_simple_template(Engine, Template_name, Context) ->
gleam@result:'try'(
load_template_content(Engine, Template_name),
fun(_use0) ->
{New_engine, Content} = _use0,
Template = {template, Content},
gleam@result:'try'(
render(Template, Context),
fun(Rendered) -> {ok, {New_engine, Rendered}} end
)
end
).
-file("src/ginger.gleam", 228).
-spec clear_cache(template_engine()) -> template_engine().
clear_cache(Engine) ->
{template_engine, erlang:element(2, Engine), maps:new()}.
-file("src/ginger.gleam", 232).
-spec context_from_list(list({binary(), binary()})) -> template_context().
context_from_list(Variables) ->
Var_dict = maps:from_list(Variables),
{template_context, Var_dict, maps:new()}.