Current section
Files
Jump to
Current section
Files
src/commonmark@internal@renderer@html.erl
-module(commonmark@internal@renderer@html).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([sanitize_href_property/1, sanitize_plain_text/1, block_to_html_safe/3, block_to_html/3]).
-spec sanitize_href_property(binary()) -> binary().
sanitize_href_property(Prop) ->
_pipe = Prop,
_pipe@1 = gleam@string:replace(_pipe, <<"&"/utf8>>, <<"&"/utf8>>),
_pipe@2 = gleam@string:replace(_pipe@1, <<"\""/utf8>>, <<"%22"/utf8>>),
_pipe@3 = gleam@string:replace(_pipe@2, <<"\\"/utf8>>, <<"%5C"/utf8>>),
gleam@string:replace(_pipe@3, <<" "/utf8>>, <<"%20"/utf8>>).
-spec sanitize_plain_text(binary()) -> binary().
sanitize_plain_text(Text) ->
_pipe = Text,
_pipe@1 = gleam@string:replace(_pipe, <<"&"/utf8>>, <<"&"/utf8>>),
_pipe@2 = gleam@string:replace(_pipe@1, <<"\""/utf8>>, <<"""/utf8>>),
_pipe@3 = gleam@string:replace(_pipe@2, <<"<"/utf8>>, <<"<"/utf8>>),
gleam@string:replace(_pipe@3, <<">"/utf8>>, <<">"/utf8>>).
-spec loose_list_item(list(binary())) -> binary().
loose_list_item(Content) ->
<<<<"<li>\n"/utf8, (gleam@string:join(Content, <<""/utf8>>))/binary>>/binary,
"</li>\n"/utf8>>.
-spec tight_list_item(
list(commonmark@ast:block_node()),
gleam@dict:dict(binary(), commonmark@ast:reference_()),
fun((commonmark@ast:block_node(), gleam@dict:dict(binary(), commonmark@ast:reference_()), boolean()) -> AHOH),
fun((list(AHOH)) -> AHOJ),
fun((AHOJ, fun((list(binary())) -> AHOH)) -> AHOH),
fun((AHOH, fun((binary()) -> binary())) -> AHOH),
fun(({AHOH, AHOH}, fun(({binary(), binary()}) -> binary())) -> AHOH),
fun((binary()) -> AHOH)
) -> AHOH.
tight_list_item(Contents, Refs, F, All, Try, Map, Map_pair, Unit) ->
Count = erlang:length(Contents),
R = begin
_pipe = Contents,
lists:reverse(_pipe)
end,
Try(
begin
_pipe@1 = R,
_pipe@2 = gleam@list:drop(_pipe@1, 1),
_pipe@3 = lists:reverse(_pipe@2),
_pipe@4 = gleam@list:drop(_pipe@3, 1),
_pipe@5 = gleam@list:map(_pipe@4, fun(B) -> case B of
{paragraph, C} ->
F(
{paragraph,
gleam@list:concat([C, [soft_line_break]])},
Refs,
true
);
_ ->
F(B, Refs, true)
end end),
All(_pipe@5)
end,
fun(Rest) ->
Map_pair(
case {Count, gleam@list:first(Contents), gleam@list:first(R)} of
{0, _, _} ->
{Unit(<<""/utf8>>), Unit(<<""/utf8>>)};
{_, {error, _}, _} ->
{Unit(<<""/utf8>>), Unit(<<""/utf8>>)};
{_, _, {error, _}} ->
{Unit(<<""/utf8>>), Unit(<<""/utf8>>)};
{1, {ok, {paragraph, _} = P}, _} ->
{F(P, Refs, true), Unit(<<""/utf8>>)};
{1, {ok, Block}, _} ->
{begin
_pipe@6 = F(Block, Refs, true),
Map(
_pipe@6,
fun(X) -> <<"\n"/utf8, X/binary>> end
)
end,
Unit(<<""/utf8>>)};
{_, {ok, {paragraph, _} = P@1}, {ok, Last}} ->
{begin
_pipe@7 = F(P@1, Refs, true),
Map(
_pipe@7,
fun(X@1) -> <<X@1/binary, "\n"/utf8>> end
)
end,
F(Last, Refs, true)};
{_, {ok, First}, {ok, Last@1}} ->
{begin
_pipe@8 = F(First, Refs, true),
Map(
_pipe@8,
fun(X@2) -> <<"\n"/utf8, X@2/binary>> end
)
end,
F(Last@1, Refs, true)}
end,
fun(_use0) ->
{First@1, Last@2} = _use0,
<<<<<<<<"<li>"/utf8, First@1/binary>>/binary,
(gleam@string:join(Rest, <<""/utf8>>))/binary>>/binary,
Last@2/binary>>/binary,
"</li>\n"/utf8>>
end
)
end
).
-spec blockquote(list(binary())) -> binary().
blockquote(Contents) ->
<<<<"<blockquote>\n"/utf8,
(gleam@string:join(Contents, <<""/utf8>>))/binary>>/binary,
"</blockquote>\n"/utf8>>.
-spec code(binary(), gleam@option:option(binary())) -> binary().
code(Contents, Language) ->
Class = begin
_pipe = Language,
_pipe@1 = gleam@option:map(
_pipe,
fun(S) ->
<<<<" class=\"language-"/utf8, S/binary>>/binary, "\""/utf8>>
end
),
gleam@option:unwrap(_pipe@1, <<""/utf8>>)
end,
<<<<<<<<"<pre><code"/utf8, Class/binary>>/binary, ">"/utf8>>/binary,
Contents/binary>>/binary,
"</code></pre>\n"/utf8>>.
-spec header(list(binary()), integer()) -> binary().
header(Contents, Level) ->
Tag = <<"h"/utf8, (gleam@int:to_string(Level))/binary>>,
<<<<<<<<<<<<"<"/utf8, Tag/binary>>/binary, ">"/utf8>>/binary,
(gleam@string:join(Contents, <<""/utf8>>))/binary>>/binary,
"</"/utf8>>/binary,
Tag/binary>>/binary,
">\n"/utf8>>.
-spec ol(list(binary()), gleam@option:option(integer())) -> binary().
ol(Content, Start) ->
Start_attr = begin
_pipe = Start,
_pipe@1 = gleam@option:map(
_pipe,
fun(S) ->
<<<<" start=\""/utf8, (gleam@int:to_string(S))/binary>>/binary,
"\""/utf8>>
end
),
gleam@option:unwrap(_pipe@1, <<""/utf8>>)
end,
<<<<<<<<"<ol"/utf8, Start_attr/binary>>/binary, ">\n"/utf8>>/binary,
(gleam@string:join(Content, <<""/utf8>>))/binary>>/binary,
"</ol>\n"/utf8>>.
-spec p(list(binary())) -> binary().
p(Content) ->
<<<<"<p>"/utf8, (gleam@string:join(Content, <<""/utf8>>))/binary>>/binary,
"</p>\n"/utf8>>.
-spec ul(list(binary())) -> binary().
ul(Content) ->
<<<<"<ul>\n"/utf8, (gleam@string:join(Content, <<""/utf8>>))/binary>>/binary,
"</ul>\n"/utf8>>.
-spec block_to_html_safe(
commonmark@ast:block_node(),
gleam@dict:dict(binary(), commonmark@ast:reference_()),
boolean()
) -> binary().
block_to_html_safe(Block, Refs, Tight) ->
case Block of
{alert_block, _, Contents} ->
blockquote(
begin
_pipe = Contents,
gleam@list:map(
_pipe,
fun(_capture) ->
block_to_html_safe(_capture, Refs, false)
end
)
end
);
{block_quote, Contents} ->
blockquote(
begin
_pipe = Contents,
gleam@list:map(
_pipe,
fun(_capture) ->
block_to_html_safe(_capture, Refs, false)
end
)
end
);
{code_block, Language, _, Contents@1} ->
code(
begin
_pipe@1 = Contents@1,
sanitize_plain_text(_pipe@1)
end,
Language
);
{heading, Level, Contents@2} ->
header(
begin
_pipe@2 = Contents@2,
gleam@list:map(
_pipe@2,
fun(_capture@1) ->
inline_to_html_safe(_capture@1, Refs)
end
)
end,
Level
);
horizontal_break ->
<<"<hr />\n"/utf8>>;
{html_block, Html} ->
<<Html/binary, "\n"/utf8>>;
{ordered_list, Items, 1, _} ->
ol(
begin
_pipe@3 = Items,
gleam@list:map(
_pipe@3,
fun(_capture@2) ->
list_item_to_html_safe(_capture@2, Refs)
end
)
end,
none
);
{ordered_list, Items@1, Start, _} ->
ol(
begin
_pipe@4 = Items@1,
gleam@list:map(
_pipe@4,
fun(_capture@3) ->
list_item_to_html_safe(_capture@3, Refs)
end
)
end,
{some, Start}
);
{paragraph, Contents@3} when Tight ->
_pipe@5 = Contents@3,
_pipe@6 = gleam@list:map(
_pipe@5,
fun(_capture@4) -> inline_to_html_safe(_capture@4, Refs) end
),
gleam@string:join(_pipe@6, <<""/utf8>>);
{paragraph, Contents@4} ->
p(
begin
_pipe@7 = Contents@4,
gleam@list:map(
_pipe@7,
fun(_capture@5) ->
inline_to_html_safe(_capture@5, Refs)
end
)
end
);
{unordered_list, Items@2, _} ->
ul(
begin
_pipe@8 = Items@2,
gleam@list:map(
_pipe@8,
fun(_capture@6) ->
list_item_to_html_safe(_capture@6, Refs)
end
)
end
)
end.
-spec list_item_to_html_safe(
commonmark@ast:list_item(),
gleam@dict:dict(binary(), commonmark@ast:reference_())
) -> binary().
list_item_to_html_safe(Item, Refs) ->
case Item of
{list_item, []} ->
<<"<li></li>\n"/utf8>>;
{tight_list_item, []} ->
<<"<li></li>\n"/utf8>>;
{list_item, Contents} ->
loose_list_item(
begin
_pipe = Contents,
gleam@list:map(
_pipe,
fun(_capture) ->
block_to_html_safe(_capture, Refs, false)
end
)
end
);
{tight_list_item, Contents@1} ->
Passthrough = fun(X, F) -> F(X) end,
tight_list_item(
Contents@1,
Refs,
fun block_to_html_safe/3,
fun gleam@function:identity/1,
Passthrough,
Passthrough,
Passthrough,
fun gleam@function:identity/1
)
end.
-spec block_to_html(
commonmark@ast:block_node(),
gleam@dict:dict(binary(), commonmark@ast:reference_()),
boolean()
) -> {ok, binary()} | {error, commonmark@ast:render_error()}.
block_to_html(Block, Refs, Tight) ->
case Block of
{alert_block, _, Contents} ->
_pipe = Contents,
_pipe@1 = gleam@list:map(
_pipe,
fun(_capture) -> block_to_html(_capture, Refs, false) end
),
_pipe@2 = gleam@result:all(_pipe@1),
gleam@result:map(_pipe@2, fun blockquote/1);
{block_quote, Contents} ->
_pipe = Contents,
_pipe@1 = gleam@list:map(
_pipe,
fun(_capture) -> block_to_html(_capture, Refs, false) end
),
_pipe@2 = gleam@result:all(_pipe@1),
gleam@result:map(_pipe@2, fun blockquote/1);
{code_block, Language, _, Contents@1} ->
{ok,
code(
begin
_pipe@3 = Contents@1,
sanitize_plain_text(_pipe@3)
end,
Language
)};
{heading, Level, Contents@2} ->
_pipe@4 = Contents@2,
_pipe@5 = gleam@list:map(
_pipe@4,
fun(_capture@1) -> inline_to_html(_capture@1, Refs) end
),
_pipe@6 = gleam@result:all(_pipe@5),
gleam@result:map(
_pipe@6,
fun(_capture@2) -> header(_capture@2, Level) end
);
horizontal_break ->
{ok, <<"<hr />\n"/utf8>>};
{html_block, Html} ->
{ok, <<Html/binary, "\n"/utf8>>};
{ordered_list, Items, 1, _} ->
_pipe@7 = Items,
_pipe@8 = gleam@list:map(
_pipe@7,
fun(_capture@3) -> list_item_to_html(_capture@3, Refs) end
),
_pipe@9 = gleam@result:all(_pipe@8),
gleam@result:map(
_pipe@9,
fun(_capture@4) -> ol(_capture@4, none) end
);
{ordered_list, Items@1, Start, _} ->
_pipe@10 = Items@1,
_pipe@11 = gleam@list:map(
_pipe@10,
fun(_capture@5) -> list_item_to_html(_capture@5, Refs) end
),
_pipe@12 = gleam@result:all(_pipe@11),
gleam@result:map(
_pipe@12,
fun(_capture@6) -> ol(_capture@6, {some, Start}) end
);
{paragraph, Contents@3} when Tight ->
_pipe@13 = Contents@3,
_pipe@14 = gleam@list:map(
_pipe@13,
fun(_capture@7) -> inline_to_html(_capture@7, Refs) end
),
_pipe@15 = gleam@result:all(_pipe@14),
gleam@result:map(
_pipe@15,
fun(_capture@8) ->
gleam@string:join(_capture@8, <<""/utf8>>)
end
);
{paragraph, Contents@4} ->
_pipe@16 = Contents@4,
_pipe@17 = gleam@list:map(
_pipe@16,
fun(_capture@9) -> inline_to_html(_capture@9, Refs) end
),
_pipe@18 = gleam@result:all(_pipe@17),
gleam@result:map(_pipe@18, fun p/1);
{unordered_list, Items@2, _} ->
_pipe@19 = Items@2,
_pipe@20 = gleam@list:map(
_pipe@19,
fun(_capture@10) -> list_item_to_html(_capture@10, Refs) end
),
_pipe@21 = gleam@result:all(_pipe@20),
gleam@result:map(_pipe@21, fun ul/1)
end.
-spec list_item_to_html(
commonmark@ast:list_item(),
gleam@dict:dict(binary(), commonmark@ast:reference_())
) -> {ok, binary()} | {error, commonmark@ast:render_error()}.
list_item_to_html(Item, Refs) ->
case Item of
{list_item, []} ->
{ok, <<"<li></li>\n"/utf8>>};
{tight_list_item, []} ->
{ok, <<"<li></li>\n"/utf8>>};
{list_item, Contents} ->
_pipe = Contents,
_pipe@1 = gleam@list:map(
_pipe,
fun(_capture) -> block_to_html(_capture, Refs, false) end
),
_pipe@2 = gleam@result:all(_pipe@1),
gleam@result:map(_pipe@2, fun loose_list_item/1);
{tight_list_item, Contents@1} ->
tight_list_item(
Contents@1,
Refs,
fun block_to_html/3,
fun gleam@result:all/1,
fun gleam@result:'try'/2,
fun gleam@result:map/2,
fun(X, F) ->
gleam@result:'try'(
erlang:element(1, X),
fun(First) ->
gleam@result:'try'(
erlang:element(2, X),
fun(Last) -> {ok, F({First, Last})} end
)
end
)
end,
fun(Field@0) -> {ok, Field@0} end
)
end.
-spec inline_to_html(
commonmark@ast:inline_node(),
gleam@dict:dict(binary(), commonmark@ast:reference_())
) -> {ok, binary()} | {error, commonmark@ast:render_error()}.
inline_to_html(Inline, Refs) ->
case Inline of
{emphasis, Contents, _} ->
_pipe = inline_list_to_html(Contents, Refs),
gleam@result:map(
_pipe,
fun(C) -> <<<<"<em>"/utf8, C/binary>>/binary, "</em>"/utf8>> end
);
{strong_emphasis, Contents@1, _} ->
_pipe@1 = inline_list_to_html(Contents@1, Refs),
gleam@result:map(
_pipe@1,
fun(C@1) ->
<<<<"<strong>"/utf8, C@1/binary>>/binary, "</strong>"/utf8>>
end
);
{strike_through, Contents@2} ->
_pipe@2 = inline_list_to_html(Contents@2, Refs),
gleam@result:map(
_pipe@2,
fun(C@2) ->
<<<<"<del>"/utf8, C@2/binary>>/binary, "</del>"/utf8>>
end
);
{html_inline, Html} ->
{ok, Html};
{reference_image, _, _} ->
{ok, <<"Image"/utf8>>};
{image, Alt, Title, Href} ->
Title@1 = begin
_pipe@3 = Title,
_pipe@4 = gleam@option:map(
_pipe@3,
fun(T) ->
<<<<" title=\""/utf8, (sanitize_plain_text(T))/binary>>/binary,
"\""/utf8>>
end
),
gleam@option:unwrap(_pipe@4, <<""/utf8>>)
end,
{ok,
<<<<<<<<<<<<"<img src=\""/utf8,
(sanitize_href_property(Href))/binary>>/binary,
"\" alt=\""/utf8>>/binary,
Alt/binary>>/binary,
"\""/utf8>>/binary,
Title@1/binary>>/binary,
" />"/utf8>>};
{reference_link, _, _} ->
{ok, <<"Link"/utf8>>};
{link, Contents@3, Title@2, Href@1} ->
Title@3 = begin
_pipe@5 = Title@2,
_pipe@6 = gleam@option:map(
_pipe@5,
fun(T@1) ->
<<<<" title=\""/utf8,
(sanitize_plain_text(T@1))/binary>>/binary,
"\""/utf8>>
end
),
gleam@option:unwrap(_pipe@6, <<""/utf8>>)
end,
_pipe@7 = inline_list_to_html(Contents@3, Refs),
gleam@result:map(
_pipe@7,
fun(C@3) ->
<<<<<<<<<<<<"<a href=\""/utf8,
(sanitize_href_property(Href@1))/binary>>/binary,
"\""/utf8>>/binary,
Title@3/binary>>/binary,
">"/utf8>>/binary,
C@3/binary>>/binary,
"</a>"/utf8>>
end
);
_ ->
{ok, inline_to_html_safe(Inline, Refs)}
end.
-spec inline_list_to_html(
list(commonmark@ast:inline_node()),
gleam@dict:dict(binary(), commonmark@ast:reference_())
) -> {ok, binary()} | {error, commonmark@ast:render_error()}.
inline_list_to_html(Nodes, Refs) ->
_pipe = Nodes,
_pipe@1 = gleam@list:map(
_pipe,
fun(_capture) -> inline_to_html(_capture, Refs) end
),
_pipe@2 = gleam@result:all(_pipe@1),
gleam@result:map(
_pipe@2,
fun(_capture@1) -> gleam@string:join(_capture@1, <<""/utf8>>) end
).
-spec inline_to_html_safe(
commonmark@ast:inline_node(),
gleam@dict:dict(binary(), commonmark@ast:reference_())
) -> binary().
inline_to_html_safe(Inline, Refs) ->
case Inline of
{code_span, Contents} ->
<<<<"<code>"/utf8, (sanitize_plain_text(Contents))/binary>>/binary,
"</code>"/utf8>>;
{email_autolink, Email} ->
<<<<<<<<"<a href=\"mailto:"/utf8,
(sanitize_href_property(Email))/binary>>/binary,
"\">"/utf8>>/binary,
(sanitize_plain_text(Email))/binary>>/binary,
"</a>"/utf8>>;
hard_line_break ->
<<"<br />\n"/utf8>>;
{html_inline, Html} ->
Html;
{plain_text, Contents@1} ->
sanitize_plain_text(Contents@1);
soft_line_break ->
<<"\n"/utf8>>;
{uri_autolink, Href} ->
<<<<<<<<"<a href=\""/utf8, (sanitize_href_property(Href))/binary>>/binary,
"\">"/utf8>>/binary,
Href/binary>>/binary,
"</a>"/utf8>>;
{emphasis, Contents@2, _} ->
<<<<"<em>"/utf8,
(inline_list_to_html_safe(Contents@2, Refs))/binary>>/binary,
"</em>"/utf8>>;
{strong_emphasis, Contents@3, _} ->
<<<<"<strong>"/utf8,
(inline_list_to_html_safe(Contents@3, Refs))/binary>>/binary,
"</strong>"/utf8>>;
{strike_through, Contents@4} ->
<<<<"<del>"/utf8,
(inline_list_to_html_safe(Contents@4, Refs))/binary>>/binary,
"</del>"/utf8>>;
{reference_image, _, _} ->
<<"Image"/utf8>>;
{image, Alt, Title, Href@1} ->
Title@1 = begin
_pipe = Title,
_pipe@1 = gleam@option:map(
_pipe,
fun(T) ->
<<<<" title=\""/utf8, (sanitize_plain_text(T))/binary>>/binary,
"\""/utf8>>
end
),
gleam@option:unwrap(_pipe@1, <<""/utf8>>)
end,
<<<<<<<<<<<<"<img src=\""/utf8,
(sanitize_href_property(Href@1))/binary>>/binary,
"\" alt=\""/utf8>>/binary,
Alt/binary>>/binary,
"\""/utf8>>/binary,
Title@1/binary>>/binary,
" />"/utf8>>;
{reference_link, _, _} ->
<<"Link"/utf8>>;
{link, Contents@5, Title@2, Href@2} ->
Title@3 = begin
_pipe@2 = Title@2,
_pipe@3 = gleam@option:map(
_pipe@2,
fun(T@1) ->
<<<<" title=\""/utf8,
(sanitize_plain_text(T@1))/binary>>/binary,
"\""/utf8>>
end
),
gleam@option:unwrap(_pipe@3, <<""/utf8>>)
end,
<<<<<<<<<<<<"<a href=\""/utf8,
(sanitize_href_property(Href@2))/binary>>/binary,
"\""/utf8>>/binary,
Title@3/binary>>/binary,
">"/utf8>>/binary,
(inline_list_to_html_safe(Contents@5, Refs))/binary>>/binary,
"</a>"/utf8>>
end.
-spec inline_list_to_html_safe(
list(commonmark@ast:inline_node()),
gleam@dict:dict(binary(), commonmark@ast:reference_())
) -> binary().
inline_list_to_html_safe(Nodes, Refs) ->
_pipe = Nodes,
_pipe@1 = gleam@list:map(
_pipe,
fun(_capture) -> inline_to_html_safe(_capture, Refs) end
),
gleam@string:join(_pipe@1, <<""/utf8>>).