Current section
Files
Jump to
Current section
Files
src/nakai@render.erl
-module(nakai@render).
-compile(no_auto_import).
-export([new/0, append/2, render_attr/1, render_attrs/1, render_children/1, render_doctype/1, render_node/1, render_root/1]).
-export_type([attr_render/1]).
-type attr_render(GPK) :: {attr_render,
gleam@string_builder:string_builder(),
list(nakai@render@state:event_state(GPK))}.
-spec new() -> attr_render(any()).
new() ->
{attr_render, gleam@string_builder:new(), []}.
-spec append(attr_render(GPR), attr_render(GPR)) -> attr_render(GPR).
append(Before, Add) ->
{attr_render,
gleam@string_builder:append_builder(
erlang:element(2, Before),
erlang:element(2, Add)
),
gleam@list:append(erlang:element(3, Before), erlang:element(3, Add))}.
-spec render_attr(nakai@html@attrs:attr(GPV)) -> attr_render(GPV).
render_attr(Attr) ->
case Attr of
{attr, Name, Value} ->
_pipe = gleam@string_builder:from_strings(
[<<" "/utf8>>, Name, <<"=\""/utf8>>, Value, <<"\""/utf8>>]
),
{attr_render, _pipe, []};
{event, Name@1, Action} ->
Ref = <<"test-ref"/utf8>>,
_pipe@1 = gleam@string_builder:from_strings(
[<<" data-nakai-ref-"/utf8>>,
Name@1,
<<"=\""/utf8>>,
Ref,
<<"\""/utf8>>]
),
{attr_render, _pipe@1, [{event_state, Name@1, Ref, Action}]}
end.
-spec render_attrs(list(nakai@html@attrs:attr(GPY))) -> attr_render(GPY).
render_attrs(Attrs) ->
_pipe = Attrs,
_pipe@1 = gleam@list:map(_pipe, fun render_attr/1),
gleam@list:fold(_pipe@1, new(), fun append/2).
-spec render_children(list(nakai@html:node_(GQC))) -> nakai@render@state:state(GQC).
render_children(Children) ->
_pipe = Children,
_pipe@1 = gleam@list:map(_pipe, fun render_node/1),
gleam@list:fold(
_pipe@1,
nakai@render@state:new(),
fun nakai@render@state:append/2
).
-spec render_doctype(nakai@html@doctype:doctype()) -> gleam@string_builder:string_builder().
render_doctype(Doctype) ->
gleam@string_builder:from_strings(
[<<"<!DOCTYPE "/utf8>>, erlang:element(2, Doctype), <<">"/utf8>>]
).
-spec render_node(nakai@html:node_(GQG)) -> nakai@render@state:state(GQG).
render_node(Tree) ->
case Tree of
{head, Children} ->
_pipe = render_children(Children),
nakai@render@state:headify(_pipe);
{component, Factory} ->
render_node(Factory());
{fragment, Children@1} ->
render_children(Children@1);
{comment, Content} ->
_pipe@1 = gleam@string_builder:from_strings(
[<<"<!-- "/utf8>>, Content, <<" -->"/utf8>>]
),
nakai@render@state:body_only(_pipe@1, []);
{element, Tag, Attrs, Children@2} ->
State = render_children(Children@2),
Attr_render = render_attrs(Attrs),
_pipe@2 = gleam@string_builder:concat(
[gleam@string_builder:from_strings([<<"<"/utf8>>, Tag]),
erlang:element(2, Attr_render),
gleam@string_builder:from_string(<<">"/utf8>>),
erlang:element(3, State),
gleam@string_builder:from_strings(
[<<"</"/utf8>>, Tag, <<">"/utf8>>]
)]
),
{state,
erlang:element(2, State),
_pipe@2,
gleam@list:append(
erlang:element(4, State),
erlang:element(3, Attr_render)
)};
{leaf_element, Tag@1, Attrs@1} ->
Attr_render@1 = render_attrs(Attrs@1),
_pipe@3 = gleam@string_builder:concat(
[gleam@string_builder:from_strings([<<"<"/utf8>>, Tag@1]),
erlang:element(2, Attr_render@1),
gleam@string_builder:from_string(<<" />"/utf8>>)]
),
nakai@render@state:body_only(
_pipe@3,
erlang:element(3, Attr_render@1)
);
{text, Content@1} ->
_pipe@4 = gleam@string_builder:from_string(Content@1),
nakai@render@state:body_only(_pipe@4, []);
nothing ->
nakai@render@state:new()
end.
-spec render_root(nakai@html:node_(any())) -> gleam@string_builder:string_builder().
render_root(Tree) ->
Result = render_node(Tree),
gleam@string_builder:concat(
[gleam@string_builder:from_string(<<"<html>\n<head>"/utf8>>),
erlang:element(2, Result),
gleam@string_builder:from_string(<<"</head>\n<body>"/utf8>>),
erlang:element(3, Result),
generate_events_code(erlang:element(4, Result)),
gleam@string_builder:from_string(<<"</body>\n</html>"/utf8>>)]
).
-spec generate_events_code(list(nakai@render@state:event_state(any()))) -> gleam@string_builder:string_builder().
generate_events_code(Events) ->
case Events of
[] ->
gleam@string_builder:new();
_@1 ->
_pipe = Events,
_pipe@2 = gleam@list:map(
_pipe,
fun(Event) ->
Selector = begin
_pipe@1 = gleam@string_builder:from_strings(
[<<"[data-nakai-ref-"/utf8>>,
erlang:element(2, Event),
<<"=\""/utf8>>,
erlang:element(3, Event),
<<"\"]"/utf8>>]
),
gleam@string_builder:to_string(_pipe@1)
end,
gleam@string_builder:from_strings(
[<<"window.addEventListener(\"DOMContentLoaded\", function() {
document.querySelector('"/utf8>>,
Selector,
<<"')
.addEventListener('"/utf8>>,
erlang:element(2, Event),
<<"', () => console.log(\"doing the thing!!!\"));
});\n"/utf8>>]
)
end
),
_pipe@3 = gleam@string_builder:concat(_pipe@2),
_pipe@4 = gleam@string_builder:prepend(
_pipe@3,
<<"<script>\n"/utf8>>
),
gleam@string_builder:append(_pipe@4, <<"\n</script>"/utf8>>)
end.