Current section
Files
Jump to
Current section
Files
src/sprocket@renderers@html.erl
-module(sprocket@renderers@html).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([html_renderer/0]).
-spec safe_replace_char(binary()) -> binary().
safe_replace_char(Key) ->
case Key of
<<"&"/utf8>> ->
<<"&"/utf8>>;
<<"<"/utf8>> ->
<<"<"/utf8>>;
<<">"/utf8>> ->
<<">"/utf8>>;
<<"\""/utf8>> ->
<<"""/utf8>>;
<<"'"/utf8>> ->
<<"'"/utf8>>;
<<"/"/utf8>> ->
<<"/"/utf8>>;
<<"`"/utf8>> ->
<<"`"/utf8>>;
<<"="/utf8>> ->
<<"="/utf8>>;
_ ->
Key
end.
-spec escape_html(binary()) -> binary().
escape_html(Unsafe) ->
_pipe = gleam@string:to_graphemes(Unsafe),
_pipe@1 = gleam@list:fold(
_pipe,
gleam@string_builder:new(),
fun(Sb, Grapheme) ->
gleam@string_builder:append(Sb, safe_replace_char(Grapheme))
end
),
gleam@string_builder:to_string(_pipe@1).
-spec text(binary()) -> gleam@string_builder:string_builder().
text(T) ->
_pipe = escape_html(T),
gleam@string_builder:from_string(_pipe).
-spec element(
binary(),
gleam@option:option(binary()),
list(sprocket@internal@reconcile:reconciled_attribute()),
list(sprocket@internal@reconcile:reconciled_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
{reconciled_attribute, Name, Value} ->
gleam@string_builder:append_builder(
Acc,
gleam@string_builder:from_strings(
[<<" "/utf8>>,
Name,
<<"=\""/utf8>>,
Value,
<<"\""/utf8>>]
)
);
_ ->
Acc
end end
)
end,
Rendered_attrs@1 = case Key of
{some, K} ->
gleam@string_builder:append_builder(
Rendered_attrs,
gleam@string_builder:from_strings(
[<<" "/utf8>>,
<<"spkt-key"/utf8>>,
<<"=\""/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@internal@reconcile:reconciled_element()) -> gleam@string_builder:string_builder().
render(El) ->
case El of
{reconciled_element, Tag, Key, Attrs, Children} ->
element(Tag, Key, Attrs, Children);
{reconciled_component, _, _, _, _, El@1} ->
component(El@1);
{reconciled_fragment, _, Children@1} ->
fragment(Children@1);
{reconciled_ignore_update, El@2} ->
render(El@2);
{reconciled_text, T} ->
text(T)
end.
-spec html_renderer() -> sprocket@render:renderer(binary()).
html_renderer() ->
{renderer, fun(El) -> _pipe = render(El),
gleam@string_builder:to_string(_pipe) end}.
-spec component(sprocket@internal@reconcile:reconciled_element()) -> gleam@string_builder:string_builder().
component(El) ->
render(El).
-spec fragment(list(sprocket@internal@reconcile:reconciled_element())) -> gleam@string_builder:string_builder().
fragment(Children) ->
_pipe = Children,
gleam@list:fold(
_pipe,
gleam@string_builder:new(),
fun(Acc, Child) ->
gleam@string_builder:append_builder(Acc, render(Child))
end
).