Current section
Files
Jump to
Current section
Files
src/kirala@bbmarkdown@html_renderer.erl
-module(kirala@bbmarkdown@html_renderer).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([html_encode_/2, html_encode/1, emit/2, emit_text/2, convert_tokens_/2, convert_bytes/1, convert/1, convert_bytes_outline/1, convert_outline/1, convert_bytes_digest/1, convert_digest/1]).
-spec url_of(
gleam@dict:dict(binary(), binary()),
kirala@bbmarkdown@parser:url_data()
) -> binary().
url_of(Symbols, Url) ->
case Url of
{url_plain, Str} ->
Str;
{url_foot_note, Id} ->
case gleam@dict:get(Symbols, Id) of
{ok, Str@1} ->
Str@1;
_ ->
Id
end
end.
-spec html_encode_(bitstring(), bitstring()) -> bitstring().
html_encode_(Src, Acc) ->
case Src of
<<>> ->
Acc;
_ ->
{Newacc, Rest@4} = case Src of
<<"&"/utf8, Rest/bitstring>> ->
{<<Acc/bitstring, "&"/utf8>>, Rest};
<<"<"/utf8, Rest@1/bitstring>> ->
{<<Acc/bitstring, "<"/utf8>>, Rest@1};
<<">"/utf8, Rest@2/bitstring>> ->
{<<Acc/bitstring, ">"/utf8>>, Rest@2};
<<Chr, Rest@3/bitstring>> ->
{<<Acc/bitstring, Chr>>, Rest@3};
Unhandable ->
{<<Acc/bitstring>>, <<>>}
end,
html_encode_(Rest@4, Newacc)
end.
-spec html_encode(binary()) -> binary().
html_encode(Src) ->
_pipe = html_encode_(gleam_stdlib:identity(Src), <<>>),
kirala@bbmarkdown@parser:ret_string(_pipe).
-spec emit(
gleam@dict:dict(binary(), binary()),
kirala@bbmarkdown@parser:token()
) -> binary().
emit(Symbols, T) ->
case T of
{text, Text} ->
html_encode(
kirala@bbmarkdown@sub_ffi:format(<<"~ts"/utf8>>, {Text})
);
{bold, T@1} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<strong>~ts</strong>"/utf8>>,
{emit(Symbols, T@1)}
);
{italic, T@2} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<em>~ts</em>"/utf8>>,
{emit(Symbols, T@2)}
);
{strike_through, T@3} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<s>~ts</s>"/utf8>>,
{emit(Symbols, T@3)}
);
{marked_text, T@4} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<mark>~ts</mark>"/utf8>>,
{emit(Symbols, T@4)}
);
{inserted_text, T@5} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<ins>~ts</ins>"/utf8>>,
{emit(Symbols, T@5)}
);
{line_indent, _, Ts} ->
Str = begin
_pipe = gleam@list:map(Ts, fun(E) -> emit(Symbols, E) end),
gleam@string:concat(_pipe)
end,
case gleam@string:length(gleam@string:trim(Str)) =:= 0 of
true ->
<<"<br>"/utf8>>;
_ ->
kirala@bbmarkdown@sub_ffi:format(<<"~ts"/utf8>>, [Str])
end;
{line, Ts} ->
Str = begin
_pipe = gleam@list:map(Ts, fun(E) -> emit(Symbols, E) end),
gleam@string:concat(_pipe)
end,
case gleam@string:length(gleam@string:trim(Str)) =:= 0 of
true ->
<<"<br>"/utf8>>;
_ ->
kirala@bbmarkdown@sub_ffi:format(<<"~ts"/utf8>>, [Str])
end;
{h, Id, Level, Title} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<h~w id='H~w'>~ts</h~w>\n"/utf8>>,
{Level, Id, emit(Symbols, Title), Level}
);
{url, {url_foot_note, Url}} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<sup><a href='#~ts'>~ts</a></sup>"/utf8>>,
{Url, Url}
);
{url, Url@1} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<a href='~ts'>~ts</a>"/utf8>>,
{url_of(Symbols, Url@1), url_of(Symbols, Url@1)}
);
{url_link, Caption, Url@2} ->
Clen = gleam@string:length(Caption) - 1,
Tcaption = case gleam@string:starts_with(Caption, <<"\\"/utf8>>) of
true ->
html_encode(gleam@string:slice(Caption, 1, Clen));
_ ->
Caption
end,
kirala@bbmarkdown@sub_ffi:format(
<<"<a href='~ts'>~ts</a>"/utf8>>,
{url_of(Symbols, Url@2), Tcaption}
);
{img_link, Caption@1, Alt, Url@3} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<img src='~ts' alt='~ts'>~ts</a>"/utf8>>,
[url_of(Symbols, Url@3), Alt, Caption@1]
);
{foot_note, Id@1, T@6} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<div id='~ts'>※ ~ts</div>"/utf8>>,
[Id@1, emit(Symbols, T@6)]
);
{foot_note_url_def, Id@2, Url@4, Alt@1} ->
kirala@bbmarkdown@sub_ffi:format(
<<"[~ts]:~ts \"~ts\"<br>"/utf8>>,
[Id@2, Url@4, Alt@1]
);
{code_line, Code} ->
kirala@bbmarkdown@sub_ffi:format(<<"~ts\n"/utf8>>, [Code]);
{code_span, Code@1} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<code>~ts</code>"/utf8>>,
[Code@1]
);
{code_block, Syntax, Filename, Code@2} ->
case Syntax of
<<"csv"/utf8>> ->
kirala@bbmarkdown@sub_ffi:format(
<<"<div><nav class='nav'>~ts</nav><pre class='~ts'>~ts</pre>\n</div>"/utf8>>,
[Filename, Syntax, Code@2]
);
<<"tsv"/utf8>> ->
kirala@bbmarkdown@sub_ffi:format(
<<"<div><nav class='nav'>~ts</nav><pre class='~ts'>~ts</pre>\n</div>"/utf8>>,
[Filename, Syntax, Code@2]
);
_ ->
kirala@bbmarkdown@sub_ffi:format(
<<"<div class='highlight'><nav class='nav'>~ts</nav><pre><code class='~ts'>~ts</code></pre>\n</div>"/utf8>>,
[Filename, Syntax, Code@2]
)
end;
{definition_is, Obj, Verb} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<dl><dt class='line'>~ts</dt><dd class='line'>~ts</dd></dl>"/utf8>>,
[Obj, emit(Symbols, Verb)]
);
{note, Title@1, T@7} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<div class='~ts'>~ts</div>"/utf8>>,
[Title@1, emit(Symbols, T@7)]
);
{block_quote, Level@1, Code@3} ->
emit(Symbols, Code@3);
{list_item, std_list, Level@2, T@8} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<li>~ts</li>\n"/utf8>>,
[emit(Symbols, T@8)]
);
{list_item, checked_list, Check, T@9} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<li><input type='checkbox' checked='1'/>~ts</li>\n"/utf8>>,
[emit(Symbols, T@9)]
);
{list_item, unchecked_list, Check@1, T@10} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<li><input type='checkbox' />~ts</li>\n"/utf8>>,
[emit(Symbols, T@10)]
);
{list_item, ordered_list, Level@3, T@11} ->
kirala@bbmarkdown@sub_ffi:format(
<<"<li>~ts</li>\n"/utf8>>,
[emit(Symbols, T@11)]
);
{table, Header, Align, Rows} ->
Theader = begin
_pipe@1 = gleam@list:map(
Header,
fun(T@12) ->
kirala@bbmarkdown@sub_ffi:format(
<<"<th>~ts</th>"/utf8>>,
[emit(Symbols, T@12)]
)
end
),
gleam@string:concat(_pipe@1)
end,
Trows = begin
_pipe@2 = gleam@list:map(
Rows,
fun(Row) ->
Cols = Row,
Trow = gleam@list:map(
Cols,
fun(Col) ->
kirala@bbmarkdown@sub_ffi:format(
<<"<td>~ts</td>"/utf8>>,
[emit(Symbols, Col)]
)
end
),
kirala@bbmarkdown@sub_ffi:format(
<<"<tr>~ts</th>"/utf8>>,
[Trow]
)
end
),
gleam@string:concat(_pipe@2)
end,
kirala@bbmarkdown@sub_ffi:format(
<<"<section class='table'><table class='table table-light table-striped table-sm'><thead><tr>~ts</tr><thead><tbody>~ts<tbody></table></section>"/utf8>>,
[Theader, Trows]
);
hr ->
<<"<hr>"/utf8>>;
_ ->
kirala@bbmarkdown@sub_ffi:format(<<"~p"/utf8>>, [T])
end.
-spec emit_text(
gleam@dict:dict(binary(), binary()),
kirala@bbmarkdown@parser:token()
) -> binary().
emit_text(Symbols, T) ->
case T of
{text, Text} ->
html_encode(
kirala@bbmarkdown@sub_ffi:format(<<"~ts"/utf8>>, [Text])
);
{bold, T@1} ->
emit(Symbols, T@1);
{italic, T@1} ->
emit(Symbols, T@1);
{strike_through, T@1} ->
emit(Symbols, T@1);
{marked_text, T@1} ->
emit(Symbols, T@1);
{inserted_text, T@1} ->
emit(Symbols, T@1);
{line, Ts} ->
Str = begin
_pipe = gleam@list:map(Ts, fun(E) -> emit(Symbols, E) end),
gleam@string:concat(_pipe)
end,
case gleam@string:length(gleam@string:trim(Str)) =:= 0 of
true ->
<<"<br>"/utf8>>;
_ ->
kirala@bbmarkdown@sub_ffi:format(<<"~ts"/utf8>>, [Str])
end;
{url, {url_foot_note, Url}} ->
kirala@bbmarkdown@sub_ffi:format(<<"~ts"/utf8>>, [Url]);
{url, Url@1} ->
kirala@bbmarkdown@sub_ffi:format(<<"~ts"/utf8>>, [Url@1]);
{url_link, Caption, Url@2} ->
Clen = gleam@string:length(Caption) - 1,
Tcaption = case gleam@string:starts_with(Caption, <<"\\"/utf8>>) of
true ->
html_encode(gleam@string:slice(Caption, 1, Clen));
_ ->
Caption
end,
Tcaption;
_ ->
<<""/utf8>>
end.
-spec convert_(
integer(),
bitstring(),
list(kirala@bbmarkdown@parser:token()),
gleam@dict:dict(binary(), binary())
) -> {list(kirala@bbmarkdown@parser:token()),
gleam@dict:dict(binary(), binary())}.
convert_(Lineno, Bytes, Acc, Symbols) ->
case gleam@string:length(kirala@bbmarkdown@parser:ret_string_trim(Bytes)) of
Len when Len =:= 0 ->
{gleam@list:reverse(Acc), Symbols};
_ ->
{token_res, T, Rest} = kirala@bbmarkdown@parser:parse(Lineno, Bytes),
New_symbols = case T of
{foot_note_url_def, Id, Url, Alt} ->
gleam@dict:insert(Symbols, Id, Url);
_ ->
Symbols
end,
convert_(Lineno + 1, Rest, [T | Acc], New_symbols)
end.
-spec ntimes(integer(), binary()) -> binary().
ntimes(N, Str) ->
_pipe = gleam@list:map(gleam@list:range(0, N), fun(E) -> Str end),
gleam@string:concat(_pipe).
-spec convert_tokens_(
list(kirala@bbmarkdown@parser:token()),
gleam@dict:dict(binary(), binary())
) -> binary().
convert_tokens_(Tokens, Symbols) ->
{_, Strlist} = gleam@list:fold(
Tokens,
{hr, []},
fun(Acx, T) ->
{Prev, Acc} = Acx,
case {Prev, T} of
{{list_item, _, Indent1, T1}, {list_item, _, Indent2, T2}} when Indent1 =:= Indent2 ->
{T, [[emit(Symbols, T)] | Acc]};
{{list_item, _, Indent1@1, T1@1},
{list_item, _, Indent2@1, T2@1}} when Indent1@1 > Indent2@1 ->
{T,
[[ntimes(Indent1@1 - Indent2@1, <<"</ul>"/utf8>>),
emit(Symbols, T)] |
Acc]};
{{list_item, _, Indent1@2, T1@2},
{list_item, _, Indent2@2, T2@2}} when Indent1@2 < Indent2@2 ->
{T,
[[ntimes(Indent2@2 - Indent1@2, <<"<ul>"/utf8>>),
emit(Symbols, T)] |
Acc]};
{{list_item, _, Indent1@3, T1@3}, _} ->
{T,
[[ntimes(Indent1@3, <<"</ul>"/utf8>>), emit(Symbols, T)] |
Acc]};
{_, {list_item, _, Indent2@3, T2@3}} ->
{T,
[[ntimes(Indent2@3, <<"<ul>"/utf8>>), emit(Symbols, T)] |
Acc]};
{{block_quote, Indent1@4, T1@4}, {block_quote, Indent2@4, T2@4}} when Indent1@4 =:= Indent2@4 ->
{T, [[emit(Symbols, T)] | Acc]};
{{block_quote, Indent1@5, T1@5}, {block_quote, Indent2@5, T2@5}} when Indent1@5 > Indent2@5 ->
{T,
[[ntimes(
Indent1@5 - Indent2@5,
<<"</blockquote>"/utf8>>
),
emit(Symbols, T)] |
Acc]};
{{block_quote, Indent1@6, T1@6}, {block_quote, Indent2@6, T2@6}} when Indent1@6 < Indent2@6 ->
{T,
[[ntimes(Indent2@6 - Indent1@6, <<"<blockquote>"/utf8>>),
emit(Symbols, T)] |
Acc]};
{{block_quote, Indent1@7, T1@7}, _} ->
{T,
[[ntimes(Indent1@7, <<"</blockquote>"/utf8>>),
emit(Symbols, T)] |
Acc]};
{_, {block_quote, Indent2@7, T2@7}} ->
{T,
[[ntimes(Indent2@7, <<"<blockquote>"/utf8>>),
emit(Symbols, T)] |
Acc]};
{{code_line, T1@8}, {code_line, T2@8}} ->
{T, [[emit(Symbols, T)] | Acc]};
{{code_line, T1@9}, _} ->
{T, [[<<"</code></pre>"/utf8>>, emit(Symbols, T)] | Acc]};
{_, {code_line, T2@9}} ->
{T, [[<<"<pre><code>"/utf8>>, emit(Symbols, T)] | Acc]};
{_, {definition_of, T2@10}} ->
{T,
[[<<"<dl><dt>"/utf8>>,
emit(Symbols, T2@10),
<<"</dt>"/utf8>>] |
Acc]};
{_, {definition, T2@11}} ->
Tlines = begin
_pipe = gleam@list:map(
T2@11,
fun(E) -> [emit(Symbols, E), <<"<br>"/utf8>>] end
),
_pipe@1 = gleam@list:flatten(_pipe),
gleam@string:concat(_pipe@1)
end,
{T,
[[<<"<div><dd>"/utf8>>, Tlines, <<"</dd></div>"/utf8>>] |
Acc]};
{{definition, T1@10}, _} ->
{T, [[<<"</dl>"/utf8>>, emit(Symbols, T)] | Acc]};
_ ->
{T, [[emit(Symbols, T)] | Acc]}
end
end
),
_pipe@2 = Strlist,
_pipe@3 = gleam@list:reverse(_pipe@2),
_pipe@4 = gleam@list:flatten(_pipe@3),
gleam@string:concat(_pipe@4).
-spec convert_bytes(bitstring()) -> binary().
convert_bytes(Bytes) ->
{Tokens, Symbols} = convert_(0, Bytes, [], gleam@dict:new()),
convert_tokens_(Tokens, Symbols).
-spec convert(binary()) -> binary().
convert(Src) ->
convert_bytes(gleam_stdlib:identity(Src)).
-spec convert_bytes_outline(bitstring()) -> binary().
convert_bytes_outline(Bytes) ->
{Tokens, Symbols} = convert_(0, Bytes, [], gleam@dict:new()),
Filteredtokens = begin
_pipe = gleam@list:fold(Tokens, [], fun(Acc, T) -> case T of
{h, Id, Level, Title} ->
[{list_item,
std_list,
Level,
{url_link,
emit_text(Symbols, Title),
{url_plain,
kirala@bbmarkdown@sub_ffi:format(
<<"#H~w"/utf8>>,
[Id]
)}}} |
Acc];
_ ->
Acc
end end),
gleam@list:reverse(_pipe)
end,
convert_tokens_(Filteredtokens, Symbols).
-spec convert_outline(binary()) -> binary().
convert_outline(Src) ->
convert_bytes_outline(gleam_stdlib:identity(Src)).
-spec convert_bytes_digest(bitstring()) -> binary().
convert_bytes_digest(Bytes) ->
{Tokens, Symbols} = convert_(0, Bytes, [], gleam@dict:new()),
Filteredtokens = begin
_pipe = gleam@list:fold(Tokens, [], fun(Acc, T) -> case T of
{h, Id, Level, Title} ->
[[emit_text(Symbols, Title), <<"<br>\n"/utf8>>] | Acc];
{line, _} ->
[[emit_text(Symbols, T), <<"<br>\n"/utf8>>] | Acc];
_ ->
Acc
end end),
_pipe@1 = gleam@list:reverse(_pipe),
gleam@list:flatten(_pipe@1)
end,
gleam@string:concat(Filteredtokens).
-spec convert_digest(binary()) -> binary().
convert_digest(Src) ->
convert_bytes_digest(gleam_stdlib:identity(Src)).