-module(gleedoc@parse).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleedoc/parse.gleam").
-export([extract_code_blocks/1, gleam_blocks/1]).
-export_type([code_block/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-type code_block() :: {code_block,
binary(),
binary(),
gleedoc@extract:doc_block(),
integer(),
list(binary())}.
-file("src/gleedoc/parse.gleam", 76).
?DOC(" Extract import statements from code and return them separately.\n").
-spec extract_imports(binary()) -> {list(binary()), binary()}.
extract_imports(Code) ->
{Imports, Rest} = begin
_pipe = Code,
_pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>),
_pipe@2 = gleam@list:map(
_pipe@1,
fun(Line) -> {gleam@string:trim(Line), Line} end
),
gleam@list:partition(
_pipe@2,
fun(Pair) ->
gleam_stdlib:string_starts_with(
erlang:element(1, Pair),
<<"import "/utf8>>
)
end
)
end,
{begin
_pipe@3 = Imports,
gleam@list:map(
_pipe@3,
fun(Pair@1) -> erlang:element(1, Pair@1) end
)
end,
begin
_pipe@4 = Rest,
_pipe@5 = gleam@list:map(
_pipe@4,
fun(Pair@2) -> erlang:element(2, Pair@2) end
),
gleam@string:join(_pipe@5, <<"\n"/utf8>>)
end}.
-file("src/gleedoc/parse.gleam", 58).
-spec build_block(
binary(),
list(binary()),
integer(),
gleedoc@extract:doc_block()
) -> code_block().
build_block(Lang, Code_lines, Start, Doc) ->
Code = begin
_pipe = lists:reverse(Code_lines),
gleam@string:join(_pipe, <<"\n"/utf8>>)
end,
{Imports, Code@1} = extract_imports(Code),
{code_block, Lang, Code@1, Doc, Start, Imports}.
-file("src/gleedoc/parse.gleam", 27).
-spec extract_code_blocks_from_doc(gleedoc@extract:doc_block()) -> list(code_block()).
extract_code_blocks_from_doc(Doc) ->
{Accumulated@1, Current@1} = gleam@list:index_fold(
erlang:element(2, Doc),
{[], none},
fun(State, Line, Line_no) ->
{Accumulated, Current} = State,
Trimmed = gleam@string:trim(Line),
case {Current, Trimmed} of
{none, <<"```"/utf8, Rest/binary>>} ->
Lang = gleam@string:trim(Rest),
{Accumulated, {some, {Lang, [], Line_no + 1}}};
{none, _} ->
State;
{{some, {Lang@1, Code_lines, Start}}, <<"```"/utf8>>} ->
{[build_block(Lang@1, Code_lines, Start, Doc) | Accumulated],
none};
{{some, {Lang@2, Code_lines@1, Start@1}}, _} ->
{Accumulated,
{some, {Lang@2, [Line | Code_lines@1], Start@1}}}
end
end
),
Final_accumulated = case Current@1 of
{some, {Lang@3, Code_lines@2, Start@2}} ->
[build_block(Lang@3, Code_lines@2, Start@2, Doc) | Accumulated@1];
none ->
Accumulated@1
end,
lists:reverse(Final_accumulated).
-file("src/gleedoc/parse.gleam", 23).
?DOC(" Extract all fenced code blocks from a list of doc blocks.\n").
-spec extract_code_blocks(list(gleedoc@extract:doc_block())) -> list(code_block()).
extract_code_blocks(Doc_blocks) ->
_pipe = Doc_blocks,
gleam@list:flat_map(_pipe, fun extract_code_blocks_from_doc/1).
-file("src/gleedoc/parse.gleam", 90).
?DOC(" Filter code blocks to only those tagged as `gleam`.\n").
-spec gleam_blocks(list(code_block())) -> list(code_block()).
gleam_blocks(Blocks) ->
gleam@list:filter(
Blocks,
fun(B) ->
string:lowercase(erlang:element(2, B)) =:= <<"gleam"/utf8>>
end
).