-module(checkmark@internal@parser). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/checkmark/internal/parser.gleam"). -export([parse/2]). -export_type([section/0, fence/0, section_builder/0, line_content/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. ?MODULEDOC(false). -type section() :: {other, integer(), list(binary())} | {fenced_code, integer(), binary(), list(binary()), fence(), gleam@option:option(fence())}. -type fence() :: {fence, binary(), binary(), integer()}. -type section_builder() :: {other_builder, integer(), list(binary())} | {fenced_code_builder, integer(), list(binary()), binary(), fence()}. -type line_content() :: {line_content, binary(), binary()}. -file("src/checkmark/internal/parser.gleam", 34). ?DOC(false). -spec to_string_with_prefix(line_content()) -> binary(). to_string_with_prefix(Line) -> <<(erlang:element(2, Line))/binary, (erlang:element(3, Line))/binary>>. -file("src/checkmark/internal/parser.gleam", 45). ?DOC(false). -spec add_parts(section_builder(), line_content()) -> section_builder(). add_parts(Builder, Line) -> case Builder of {fenced_code_builder, _, _, _, _} -> {fenced_code_builder, erlang:element(2, Builder), [erlang:element(3, Line) | erlang:element(3, Builder)], erlang:element(4, Builder), erlang:element(5, Builder)}; {other_builder, _, _} -> {other_builder, erlang:element(2, Builder), [to_string_with_prefix(Line) | erlang:element(3, Builder)]} end. -file("src/checkmark/internal/parser.gleam", 185). ?DOC(false). -spec should_close(fence(), fence()) -> boolean(). should_close(Start, End) -> gleam_stdlib:string_starts_with( erlang:element(2, End), erlang:element(2, Start) ). -file("src/checkmark/internal/parser.gleam", 194). ?DOC(false). -spec remove_indent_up_to(binary(), integer()) -> binary(). remove_indent_up_to(String, Indent) -> case {Indent, String} of {0, _} -> String; {_, <<" "/utf8, Rest/binary>>} -> remove_indent_up_to(Rest, Indent - 1); {_, _} -> String end. -file("src/checkmark/internal/parser.gleam", 189). ?DOC(false). -spec strip_indent(list(binary()), integer()) -> list(binary()). strip_indent(Lines, Indent) -> _pipe = Lines, gleam@list:map( _pipe, fun(_capture) -> remove_indent_up_to(_capture, Indent) end ). -file("src/checkmark/internal/parser.gleam", 57). ?DOC(false). -spec to_section(section_builder(), gleam@option:option(fence())) -> section(). to_section(Builder, End_fence) -> case Builder of {fenced_code_builder, Line_number, Lines, Prefix, Start_fence} -> {fenced_code, Line_number, Prefix, begin _pipe = strip_indent(Lines, erlang:element(4, Start_fence)), lists:reverse(_pipe) end, Start_fence, End_fence}; {other_builder, Line_number@1, Lines@1} -> {other, Line_number@1, lists:reverse(Lines@1)} end. -file("src/checkmark/internal/parser.gleam", 203). ?DOC(false). -spec parse_comment(binary()) -> {binary(), binary(), boolean()}. parse_comment(Line) -> case Line of <<"/// "/utf8, Rest/binary>> -> {<<"/// "/utf8>>, Rest, true}; <<"//// "/utf8, Rest@1/binary>> -> {<<"//// "/utf8>>, Rest@1, true}; _ -> {<<""/utf8>>, Line, false} end. -file("src/checkmark/internal/parser.gleam", 230). ?DOC(false). -spec build_fence(binary(), integer(), integer(), binary()) -> fence(). build_fence(Character, Indent, Delimiters, Rest) -> case gleam_stdlib:string_pop_grapheme(Rest) of {ok, {First, Rest@1}} when First =:= Character -> build_fence(Character, Indent, Delimiters + 1, Rest@1); _ -> Fence = gleam@string:repeat(Character, Delimiters), {fence, Fence, Rest, Indent} end. -file("src/checkmark/internal/parser.gleam", 211). ?DOC(false). -spec parse_fence(line_content()) -> gleam@option:option(fence()). parse_fence(Line) -> case erlang:element(3, Line) of <<"```"/utf8, Rest/binary>> -> {some, build_fence(<<"`"/utf8>>, 0, 3, Rest)}; <<" ```"/utf8, Rest@1/binary>> -> {some, build_fence(<<"`"/utf8>>, 1, 3, Rest@1)}; <<" ```"/utf8, Rest@2/binary>> -> {some, build_fence(<<"`"/utf8>>, 2, 3, Rest@2)}; <<" ```"/utf8, Rest@3/binary>> -> {some, build_fence(<<"`"/utf8>>, 3, 3, Rest@3)}; <<"~~~"/utf8, Rest@4/binary>> -> {some, build_fence(<<"~"/utf8>>, 0, 3, Rest@4)}; <<" ~~~"/utf8, Rest@5/binary>> -> {some, build_fence(<<"~"/utf8>>, 1, 3, Rest@5)}; <<" ~~~"/utf8, Rest@6/binary>> -> {some, build_fence(<<"~"/utf8>>, 2, 3, Rest@6)}; <<" ~~~"/utf8, Rest@7/binary>> -> {some, build_fence(<<"~"/utf8>>, 3, 3, Rest@7)}; _ -> none end. -file("src/checkmark/internal/parser.gleam", 73). ?DOC(false). -spec parse_lines( boolean(), integer(), list(section()), gleam@option:option(section_builder()), binary(), list(binary()) ) -> list(section()). parse_lines( Search_in_comments, Line_number, Sections, Current_builder, Line, Rest ) -> {Prefix, Line@1, Is_comment} = case Search_in_comments of true -> parse_comment(Line); false -> {<<""/utf8>>, Line, false} end, Line@2 = {line_content, Prefix, Line@1}, {Sections@1, Current_section@1} = case Search_in_comments andalso not Is_comment of true -> case Current_builder of none -> {Sections, {some, {other_builder, Line_number, [to_string_with_prefix(Line@2)]}}}; {some, Builder} -> case Builder of {fenced_code_builder, _, _, _, _} -> {[to_section(Builder, none) | Sections], {some, {other_builder, Line_number, [to_string_with_prefix(Line@2)]}}}; {other_builder, _, _} -> {Sections, {some, add_parts(Builder, Line@2)}} end end; false -> case parse_fence(Line@2) of none -> Current_section = case Current_builder of none -> {other_builder, Line_number, [to_string_with_prefix(Line@2)]}; {some, Builder@1} -> add_parts(Builder@1, Line@2) end, {Sections, {some, Current_section}}; {some, Current_fence} -> case Current_builder of none -> {Sections, {some, {fenced_code_builder, Line_number, [], erlang:element(2, Line@2), Current_fence}}}; {some, {other_builder, _, _} = Other_builder} -> {[to_section(Other_builder, none) | Sections], {some, {fenced_code_builder, Line_number, [], erlang:element(2, Line@2), Current_fence}}}; {some, {fenced_code_builder, _, _, _, Start_fence} = Fence_builder} -> case should_close(Start_fence, Current_fence) of true -> {[to_section( Fence_builder, {some, Current_fence} ) | Sections], none}; false -> {Sections, {some, add_parts(Fence_builder, Line@2)}} end end end end, case Rest of [] -> Sections@2 = case Current_section@1 of none -> Sections@1; {some, Builder@2} -> [to_section(Builder@2, none) | Sections@1] end, lists:reverse(Sections@2); [Next_line | Rest@1] -> parse_lines( Search_in_comments, Line_number + 1, Sections@1, Current_section@1, Next_line, Rest@1 ) end. -file("src/checkmark/internal/parser.gleam", 38). ?DOC(false). -spec parse(list(binary()), boolean()) -> list(section()). parse(Lines, Search_in_comments) -> case Lines of [First | Rest] -> parse_lines(Search_in_comments, 1, [], none, First, Rest); [] -> [] end.