Current section
Files
Jump to
Current section
Files
src/sprocket@internal@render@html.erl
-module(sprocket@internal@render@html).
-compile([no_auto_import, nowarn_unused_vars]).
-export([renderer/0, preflight_renderer/2]).
-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 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>>]
)
)
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 preflight_renderer(
gleam@erlang@process:subject(sprocket@cassette:message()),
sprocket@element:element()
) -> sprocket@render:renderer(binary()).
preflight_renderer(Ca, View) ->
_assert_subject = sprocket@internal@utils@uuid:v4(),
{ok, Preflight_id} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"sprocket/internal/render/html"/utf8>>,
function => <<"preflight_renderer"/utf8>>,
line => 25})
end,
Csrf_token = sprocket@internal@csrf:generate(),
sprocket@cassette:push_preflight(
Ca,
{preflight, Preflight_id, View, Csrf_token, os:system_time(millisecond)}
),
Preflight_meta = begin
_pipe = sprocket@html:meta(
[sprocket@html@attribute:name(
sprocket@internal@constants:constant(meta_preflight_id)
),
sprocket@html@attribute:content(Preflight_id)]
),
sprocket@render:render_element(_pipe)
end,
Csrf_meta = begin
_pipe@1 = sprocket@html:meta(
[sprocket@html@attribute:name(
sprocket@internal@constants:constant(meta_crsf_token)
),
sprocket@html@attribute:content(Csrf_token)]
),
sprocket@render:render_element(_pipe@1)
end,
Sprocket_client = begin
_pipe@2 = sprocket@html:script(
[sprocket@html@attribute:src(
sprocket@internal@constants:constant(client_script)
)],
none
),
sprocket@render:render_element(_pipe@2)
end,
{renderer, fun(El) -> _pipe@3 = El,
_pipe@4 = inject_element(
_pipe@3,
<<"head"/utf8>>,
Preflight_meta,
append
),
_pipe@5 = inject_element(
_pipe@4,
<<"head"/utf8>>,
Csrf_meta,
append
),
_pipe@6 = inject_element(
_pipe@5,
<<"body"/utf8>>,
Sprocket_client,
append
),
_pipe@7 = render(_pipe@6),
gleam@string_builder:to_string(_pipe@7) 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
).