-module(sprocket@html@render). -compile([no_auto_import, nowarn_unused_vars]). -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(<<">), 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 ).