Current section

Files

Jump to
sprocket src sprocket@html@render.erl
Raw

src/sprocket@html@render.erl

-module(sprocket@html@render).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]).
-export([renderer/0]).
-export_type([inject_element_operation/0]).
-type inject_element_operation() :: append | prepend.
-spec text(binary()) -> gleam@string_builder:string_builder().
text(T) ->
gleam@string_builder:from_string(T).
-spec inject_element(
sprocket@render:rendered_element(),
binary(),
sprocket@render:rendered_element(),
inject_element_operation()
) -> sprocket@render:rendered_element().
inject_element(Root, Target_tag, Inject_element, Insert_op) ->
sprocket@render:traverse(Root, fun(El) -> case El of
{rendered_element, Tag, Key, Attrs, Children} when Tag =:= Target_tag ->
{rendered_element, Target_tag, Key, Attrs, case Insert_op of
append ->
gleam@list:append(Children, [Inject_element]);
prepend ->
[Inject_element | Children]
end};
_ ->
El
end end).
-spec inject_attribute(
sprocket@render:rendered_element(),
binary(),
sprocket@render:rendered_attribute()
) -> sprocket@render:rendered_element().
inject_attribute(Root, Target_tag, Inject_attr) ->
sprocket@render:traverse(Root, fun(El) -> case El of
{rendered_element, _, Key, Attrs, Children} ->
{rendered_element,
Target_tag,
Key,
begin
_pipe = Attrs,
gleam@list:fold(
_pipe,
[],
fun(Acc, Attr) -> case {Attr, Inject_attr} of
{{rendered_attribute, Name, _},
{rendered_attribute,
Inject_attr_name,
_}} when Name =:= Inject_attr_name ->
gleam@list:append(
Acc,
[Inject_attr, Attr]
);
{_, _} ->
gleam@list:append(Acc, [Attr])
end end
)
end,
Children};
_ ->
El
end end).
-spec element(
binary(),
gleam@option:option(binary()),
list(sprocket@render:rendered_attribute()),
list(sprocket@render:rendered_element())
) -> gleam@string_builder:string_builder().
element(Tag, Key, Attrs, Children) ->
Rendered_attrs = begin
_pipe = Attrs,
gleam@list:fold(
_pipe,
gleam@string_builder:new(),
fun(Acc, Attr) -> case Attr of
{rendered_attribute, Name, Value} ->
gleam@string_builder:append_builder(
Acc,
gleam@string_builder:from_strings(
[<<" "/utf8>>,
Name,
<<"=\""/utf8>>,
Value,
<<"\""/utf8>>]
)
);
{rendered_event_handler, Kind, Id} ->
gleam@string_builder:append_builder(
Acc,
gleam@string_builder:from_strings(
[<<" "/utf8>>,
sprocket@internal@constants:constant(
event_attr_prefix
),
<<"-"/utf8>>,
Kind,
<<"=\""/utf8>>,
Id,
<<"\""/utf8>>]
)
);
{rendered_client_hook, Name@1, Id@1} ->
gleam@string_builder:append_builder(
Acc,
gleam@string_builder:from_strings(
[<<" "/utf8>>,
sprocket@internal@constants:constant(
client_hook_attr_prefix
),
<<"=\""/utf8>>,
Name@1,
<<"\" "/utf8>>,
sprocket@internal@constants:constant(
client_hook_attr_prefix
),
<<"-id=\""/utf8>>,
Id@1,
<<"\""/utf8>>]
)
)
end end
)
end,
Rendered_attrs@1 = case Key of
{some, K} ->
gleam@string_builder:append_builder(
Rendered_attrs,
gleam@string_builder:from_strings(
[<<" "/utf8>>,
sprocket@internal@constants:constant(key_attr),
<<"=\""/utf8>>,
K,
<<"\""/utf8>>]
)
);
none ->
Rendered_attrs
end,
Inner_html = begin
_pipe@1 = Children,
gleam@list:fold(
_pipe@1,
gleam@string_builder:new(),
fun(Acc@1, Child) ->
gleam@string_builder:append_builder(Acc@1, render(Child))
end
)
end,
gleam@string_builder:concat(
[gleam@string_builder:from_string(<<"<"/utf8>>),
gleam@string_builder:from_string(Tag),
Rendered_attrs@1,
gleam@string_builder:from_string(<<">"/utf8>>),
Inner_html,
gleam@string_builder:from_string(<<"</"/utf8>>),
gleam@string_builder:from_string(Tag),
gleam@string_builder:from_string(<<">"/utf8>>)]
).
-spec render(sprocket@render:rendered_element()) -> gleam@string_builder:string_builder().
render(El) ->
case El of
{rendered_element, Tag, Key, Attrs, Children} ->
element(Tag, Key, Attrs, Children);
{rendered_component, _, _, _, _, Children@1} ->
component(Children@1);
{rendered_text, T} ->
text(T)
end.
-spec renderer() -> sprocket@render:renderer(binary()).
renderer() ->
{renderer, fun(El) -> gleam@string_builder:to_string(render(El)) end}.
-spec component(list(sprocket@render:rendered_element())) -> gleam@string_builder:string_builder().
component(Children) ->
_pipe = Children,
gleam@list:fold(
_pipe,
gleam@string_builder:new(),
fun(Acc, Child) ->
gleam@string_builder:append_builder(Acc, render(Child))
end
).