Skip to main content

src/gleamdoc@interface.erl

-module(gleamdoc@interface).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleamdoc/interface.gleam").
-export([lookup/2, lookup_packages/2, format_type/1, search/2, search_packages_filtered/5, search_packages/3, render/1, render_all/1, render_search_results/1, render_packages/1, entries_json/1, packages_json/1]).
-export_type([entry/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(" Lookup, search, and rendering for compiler-generated package interfaces.\n").

-type entry() :: {module_entry,
        gleam@package_interface:package(),
        binary(),
        gleam@package_interface:module_()} |
    {function_entry,
        gleam@package_interface:package(),
        binary(),
        binary(),
        gleam@package_interface:function_()} |
    {constant_entry,
        gleam@package_interface:package(),
        binary(),
        binary(),
        gleam@package_interface:constant()} |
    {type_entry,
        gleam@package_interface:package(),
        binary(),
        binary(),
        gleam@package_interface:type_definition()} |
    {variant_entry,
        gleam@package_interface:package(),
        binary(),
        binary(),
        integer(),
        binary(),
        gleam@package_interface:type_constructor()} |
    {alias_entry,
        gleam@package_interface:package(),
        binary(),
        binary(),
        gleam@package_interface:type_alias()}.

-file("src/gleamdoc/interface.gleam", 490).
-spec qualified(binary(), binary()) -> binary().
qualified(Module, Name) ->
    <<<<Module/binary, "."/utf8>>/binary, Name/binary>>.

-file("src/gleamdoc/interface.gleam", 501).
-spec qualified_name(entry()) -> binary().
qualified_name(Entry) ->
    case Entry of
        {module_entry, _, Name, _} ->
            Name;

        {function_entry, _, Module, Name@1, _} ->
            qualified(Module, Name@1);

        {constant_entry, _, Module@1, Name@2, _} ->
            qualified(Module@1, Name@2);

        {type_entry, _, Module@2, Name@3, _} ->
            qualified(Module@2, Name@3);

        {variant_entry, _, Module@3, _, _, Name@4, _} ->
            qualified(Module@3, Name@4);

        {alias_entry, _, Module@4, Name@5, _} ->
            qualified(Module@4, Name@5)
    end.

-file("src/gleamdoc/interface.gleam", 216).
-spec module_entries(
    gleam@package_interface:package(),
    binary(),
    gleam@package_interface:module_()
) -> list(entry()).
module_entries(Package, Module_name, Module) ->
    {module, _, Type_aliases, Types, Constants, Functions} = Module,
    Functions@1 = begin
        _pipe = Functions,
        _pipe@1 = maps:to_list(_pipe),
        gleam@list:map(
            _pipe@1,
            fun(Pair) ->
                {Name, Value} = Pair,
                {function_entry, Package, Module_name, Name, Value}
            end
        )
    end,
    Constants@1 = begin
        _pipe@2 = Constants,
        _pipe@3 = maps:to_list(_pipe@2),
        gleam@list:map(
            _pipe@3,
            fun(Pair@1) ->
                {Name@1, Value@1} = Pair@1,
                {constant_entry, Package, Module_name, Name@1, Value@1}
            end
        )
    end,
    Type_pairs = maps:to_list(Types),
    Type_entries = begin
        _pipe@4 = Type_pairs,
        gleam@list:map(
            _pipe@4,
            fun(Pair@2) ->
                {Name@2, Value@2} = Pair@2,
                {type_entry, Package, Module_name, Name@2, Value@2}
            end
        )
    end,
    Variants = begin
        _pipe@5 = Type_pairs,
        gleam@list:flat_map(
            _pipe@5,
            fun(Pair@3) ->
                {Type_name, {type_definition, _, _, Parameters, Constructors}} = Pair@3,
                _pipe@6 = Constructors,
                gleam@list:map(
                    _pipe@6,
                    fun(Constructor) ->
                        {type_constructor, _, Name@3, _} = Constructor,
                        {variant_entry,
                            Package,
                            Module_name,
                            Type_name,
                            Parameters,
                            Name@3,
                            Constructor}
                    end
                )
            end
        )
    end,
    Aliases = begin
        _pipe@7 = Type_aliases,
        _pipe@8 = maps:to_list(_pipe@7),
        gleam@list:map(
            _pipe@8,
            fun(Pair@4) ->
                {Name@4, Value@3} = Pair@4,
                {alias_entry, Package, Module_name, Name@4, Value@3}
            end
        )
    end,
    lists:append([Functions@1, Constants@1, Type_entries, Variants, Aliases]).

-file("src/gleamdoc/interface.gleam", 203).
-spec all_entries(gleam@package_interface:package()) -> list(entry()).
all_entries(Package) ->
    {package, _, _, _, Modules} = Package,
    _pipe = Modules,
    _pipe@1 = maps:to_list(_pipe),
    gleam@list:flat_map(
        _pipe@1,
        fun(Pair) ->
            {Module_name, Module} = Pair,
            [{module_entry, Package, Module_name, Module} |
                module_entries(Package, Module_name, Module)]
        end
    ).

-file("src/gleamdoc/interface.gleam", 39).
?DOC(" Looks up an exact module or qualified symbol in one package.\n").
-spec lookup(gleam@package_interface:package(), binary()) -> list(entry()).
lookup(Package, Query) ->
    {package, _, _, _, Modules} = Package,
    case gleam_stdlib:map_get(Modules, Query) of
        {ok, Module} ->
            [{module_entry, Package, Query, Module}];

        {error, nil} ->
            _pipe = all_entries(Package),
            gleam@list:filter(
                _pipe,
                fun(Entry) -> qualified_name(Entry) =:= Query end
            )
    end.

-file("src/gleamdoc/interface.gleam", 836).
-spec entry_package_name_from(gleam@package_interface:package()) -> binary().
entry_package_name_from(Package) ->
    {package, Name, _, _, _} = Package,
    Name.

-file("src/gleamdoc/interface.gleam", 671).
-spec entry_package(entry()) -> gleam@package_interface:package().
entry_package(Entry) ->
    case Entry of
        {module_entry, Package, _, _} ->
            Package;

        {function_entry, Package@1, _, _, _} ->
            Package@1;

        {constant_entry, Package@2, _, _, _} ->
            Package@2;

        {type_entry, Package@3, _, _, _} ->
            Package@3;

        {variant_entry, Package@4, _, _, _, _, _} ->
            Package@4;

        {alias_entry, Package@5, _, _, _} ->
            Package@5
    end.

-file("src/gleamdoc/interface.gleam", 516).
-spec entry_package_name(entry()) -> binary().
entry_package_name(Entry) ->
    _pipe = Entry,
    _pipe@1 = entry_package(_pipe),
    entry_package_name_from(_pipe@1).

-file("src/gleamdoc/interface.gleam", 512).
-spec package_qualified_name(entry()) -> binary().
package_qualified_name(Entry) ->
    <<<<(entry_package_name(Entry))/binary, ":"/utf8>>/binary,
        (qualified_name(Entry))/binary>>.

-file("src/gleamdoc/interface.gleam", 520).
-spec compare_entries(entry(), entry()) -> gleam@order:order().
compare_entries(A, B) ->
    gleam@string:compare(package_qualified_name(A), package_qualified_name(B)).

-file("src/gleamdoc/interface.gleam", 606).
-spec split_package_query(binary()) -> {gleam@option:option(binary()), binary()}.
split_package_query(Query) ->
    case gleam@string:split_once(Query, <<":"/utf8>>) of
        {ok, {Package, Symbol}} ->
            {{some, Package}, Symbol};

        {error, nil} ->
            {none, Query}
    end.

-file("src/gleamdoc/interface.gleam", 50).
?DOC(" Looks up an exact, optionally package-qualified symbol across packages.\n").
-spec lookup_packages(list(gleam@package_interface:package()), binary()) -> list(entry()).
lookup_packages(Packages, Query) ->
    {Package_name, Symbol} = split_package_query(Query),
    _pipe = Packages,
    _pipe@1 = gleam@list:filter(
        _pipe,
        fun(Package) ->
            {package, Name, _, _, _} = Package,
            case Package_name of
                {some, Wanted} ->
                    Name =:= Wanted;

                none ->
                    true
            end
        end
    ),
    _pipe@2 = gleam@list:flat_map(
        _pipe@1,
        fun(Package@1) -> lookup(Package@1, Symbol) end
    ),
    gleam@list:sort(_pipe@2, fun compare_entries/2).

-file("src/gleamdoc/interface.gleam", 754).
-spec entry_documentation(entry()) -> binary().
entry_documentation(Entry) ->
    case Entry of
        {module_entry, _, _, {module, Documentation, _, _, _, _}} ->
            gleam@string:join(Documentation, <<"\n"/utf8>>);

        {function_entry, _, _, _, {function, Documentation@1, _, _, _, _}} ->
            gleam@option:unwrap(Documentation@1, <<""/utf8>>);

        {constant_entry, _, _, _, {constant, Documentation@2, _, _, _}} ->
            gleam@option:unwrap(Documentation@2, <<""/utf8>>);

        {type_entry, _, _, _, {type_definition, Documentation@3, _, _, _}} ->
            gleam@option:unwrap(Documentation@3, <<""/utf8>>);

        {variant_entry,
            _,
            _,
            _,
            _,
            _,
            {type_constructor, Documentation@4, _, _}} ->
            gleam@option:unwrap(Documentation@4, <<""/utf8>>);

        {alias_entry, _, _, _, {type_alias, Documentation@5, _, _, _}} ->
            gleam@option:unwrap(Documentation@5, <<""/utf8>>)
    end.

-file("src/gleamdoc/interface.gleam", 494).
-spec named_type_name(binary(), binary(), binary()) -> binary().
named_type_name(Name, Package, Module) ->
    case Package of
        <<""/utf8>> ->
            Name;

        _ ->
            <<<<Package/binary, ":"/utf8>>/binary,
                (qualified(Module, Name))/binary>>
    end.

-file("src/gleamdoc/interface.gleam", 486).
-spec join_types(list(gleam@package_interface:type())) -> binary().
join_types(Types) ->
    _pipe = Types,
    _pipe@1 = gleam@list:map(_pipe, fun format_type/1),
    gleam@string:join(_pipe@1, <<", "/utf8>>).

-file("src/gleamdoc/interface.gleam", 187).
?DOC(" Formats a package-interface type as Gleam source syntax.\n").
-spec format_type(gleam@package_interface:type()) -> binary().
format_type(Type_) ->
    case Type_ of
        {tuple, Elements} ->
            <<<<"#("/utf8, (join_types(Elements))/binary>>/binary, ")"/utf8>>;

        {fn, Parameters, Return} ->
            <<<<<<"fn("/utf8, (join_types(Parameters))/binary>>/binary,
                    ") -> "/utf8>>/binary,
                (format_type(Return))/binary>>;

        {variable, Id} ->
            <<"a"/utf8, (erlang:integer_to_binary(Id))/binary>>;

        {named, Name, Package, Module, Parameters@1} ->
            Name@1 = named_type_name(Name, Package, Module),
            case Parameters@1 of
                [] ->
                    Name@1;

                _ ->
                    <<<<<<Name@1/binary, "("/utf8>>/binary,
                            (join_types(Parameters@1))/binary>>/binary,
                        ")"/utf8>>
            end
    end.

-file("src/gleamdoc/interface.gleam", 476).
-spec parameter_names(integer(), integer()) -> list(binary()).
parameter_names(Remaining, Index) ->
    case Remaining of
        0 ->
            [];

        _ ->
            [<<"a"/utf8, (erlang:integer_to_binary(Index))/binary>> |
                parameter_names(Remaining - 1, Index + 1)]
    end.

-file("src/gleamdoc/interface.gleam", 469).
-spec type_parameters(integer()) -> binary().
type_parameters(Count) ->
    case Count of
        0 ->
            <<""/utf8>>;

        _ ->
            <<<<"("/utf8,
                    (begin
                        _pipe = parameter_names(Count, 0),
                        gleam@string:join(_pipe, <<", "/utf8>>)
                    end)/binary>>/binary,
                ")"/utf8>>
    end.

-file("src/gleamdoc/interface.gleam", 789).
-spec format_parameters(list(gleam@package_interface:parameter())) -> binary().
format_parameters(Parameters) ->
    _pipe = Parameters,
    _pipe@1 = gleam@list:map(
        _pipe,
        fun(Parameter) ->
            {parameter, Label, Type_} = Parameter,
            case Label of
                {some, Label@1} ->
                    <<<<Label@1/binary, ": "/utf8>>/binary,
                        (format_type(Type_))/binary>>;

                none ->
                    format_type(Type_)
            end
        end
    ),
    gleam@string:join(_pipe@1, <<", "/utf8>>).

-file("src/gleamdoc/interface.gleam", 777).
-spec variant_signature(binary(), list(gleam@package_interface:parameter())) -> binary().
variant_signature(Name, Parameters) ->
    Parameters@1 = format_parameters(Parameters),
    <<Name/binary, (case Parameters@1 of
            <<""/utf8>> ->
                <<""/utf8>>;

            _ ->
                <<<<"("/utf8, Parameters@1/binary>>/binary, ")"/utf8>>
        end)/binary>>.

-file("src/gleamdoc/interface.gleam", 682).
-spec entry_signature(entry()) -> binary().
entry_signature(Entry) ->
    case Entry of
        {module_entry, _, Name, _} ->
            <<"module "/utf8, Name/binary>>;

        {function_entry, _, _, Name@1, Value} ->
            {function, _, _, _, Parameters, Return} = Value,
            Parameters@1 = format_parameters(Parameters),
            <<<<<<<<<<"pub fn "/utf8, Name@1/binary>>/binary, "("/utf8>>/binary,
                        Parameters@1/binary>>/binary,
                    ") -> "/utf8>>/binary,
                (format_type(Return))/binary>>;

        {constant_entry, _, _, Name@2, {constant, _, _, _, Type_}} ->
            <<<<<<"pub const "/utf8, Name@2/binary>>/binary, ": "/utf8>>/binary,
                (format_type(Type_))/binary>>;

        {type_entry,
            _,
            _,
            Name@3,
            {type_definition, _, _, Parameters@2, Constructors}} ->
            <<<<<<<<"pub "/utf8, (case Constructors of
                                [] ->
                                    <<"opaque "/utf8>>;

                                _ ->
                                    <<""/utf8>>
                            end)/binary>>/binary, "type "/utf8>>/binary, Name@3/binary>>/binary, (type_parameters(
                    Parameters@2
                ))/binary>>;

        {variant_entry,
            _,
            _,
            _,
            _,
            Name@4,
            {type_constructor, _, _, Parameters@3}} ->
            variant_signature(Name@4, Parameters@3);

        {alias_entry, _, _, Name@5, {type_alias, _, _, Parameters@4, Alias}} ->
            <<<<<<<<"pub type "/utf8, Name@5/binary>>/binary,
                        (type_parameters(Parameters@4))/binary>>/binary,
                    " = "/utf8>>/binary,
                (format_type(Alias))/binary>>
    end.

-file("src/gleamdoc/interface.gleam", 595).
-spec search_haystack(entry()) -> binary().
search_haystack(Entry) ->
    _pipe = (<<<<<<<<(package_qualified_name(Entry))/binary, "\n"/utf8>>/binary,
                (entry_signature(Entry))/binary>>/binary,
            "\n"/utf8>>/binary,
        (entry_documentation(Entry))/binary>>),
    string:lowercase(_pipe).

-file("src/gleamdoc/interface.gleam", 588).
-spec search_terms(binary()) -> list(binary()).
search_terms(Query) ->
    _pipe = Query,
    _pipe@1 = string:lowercase(_pipe),
    _pipe@2 = gleam@string:split(_pipe@1, <<" "/utf8>>),
    gleam@list:filter(_pipe@2, fun(Term) -> Term /= <<""/utf8>> end).

-file("src/gleamdoc/interface.gleam", 66).
?DOC(
    " Searches one package by symbol name, module, package name, signature, and\n"
    " documentation.\n"
).
-spec search(gleam@package_interface:package(), binary()) -> list(entry()).
search(Package, Query) ->
    Terms = search_terms(Query),
    case Terms of
        [] ->
            [];

        _ ->
            _pipe = all_entries(Package),
            gleam@list:filter(
                _pipe,
                fun(Entry) ->
                    Haystack = search_haystack(Entry),
                    gleam@list:all(
                        Terms,
                        fun(Term) ->
                            gleam_stdlib:contains_string(Haystack, Term)
                        end
                    )
                end
            )
    end.

-file("src/gleamdoc/interface.gleam", 743).
-spec prepend_when(list(binary()), boolean(), binary()) -> list(binary()).
prepend_when(Items, Condition, Item) ->
    case Condition of
        true ->
            [Item | Items];

        false ->
            Items
    end.

-file("src/gleamdoc/interface.gleam", 732).
-spec implementation_targets(gleam@package_interface:implementations()) -> list(binary()).
implementation_targets(Implementations) ->
    {implementations, _, _, _, Can_run_on_erlang, Can_run_on_javascript} = Implementations,
    _pipe = [],
    _pipe@1 = prepend_when(_pipe, Can_run_on_javascript, <<"javascript"/utf8>>),
    prepend_when(_pipe@1, Can_run_on_erlang, <<"erlang"/utf8>>).

-file("src/gleamdoc/interface.gleam", 723).
-spec entry_targets(entry()) -> list(binary()).
entry_targets(Entry) ->
    case Entry of
        {function_entry, _, _, _, {function, _, _, Implementations, _, _}} ->
            implementation_targets(Implementations);

        {constant_entry, _, _, _, {constant, _, _, Implementations, _}} ->
            implementation_targets(Implementations);

        _ ->
            []
    end.

-file("src/gleamdoc/interface.gleam", 584).
-spec matches_filter_list(list(binary()), binary()) -> boolean().
matches_filter_list(Values, Filter) ->
    (Filter =:= <<""/utf8>>) orelse gleam@list:contains(Values, Filter).

-file("src/gleamdoc/interface.gleam", 635).
-spec entry_kind(entry()) -> binary().
entry_kind(Entry) ->
    case Entry of
        {module_entry, _, _, _} ->
            <<"module"/utf8>>;

        {function_entry, _, _, _, _} ->
            <<"fn"/utf8>>;

        {constant_entry, _, _, _, _} ->
            <<"const"/utf8>>;

        {type_entry, _, _, _, _} ->
            <<"type"/utf8>>;

        {variant_entry, _, _, _, _, _, _} ->
            <<"variant"/utf8>>;

        {alias_entry, _, _, _, _} ->
            <<"alias"/utf8>>
    end.

-file("src/gleamdoc/interface.gleam", 580).
-spec matches_filter(binary(), binary()) -> boolean().
matches_filter(Value, Filter) ->
    (Filter =:= <<""/utf8>>) orelse (Value =:= Filter).

-file("src/gleamdoc/interface.gleam", 573).
-spec contains_score(binary(), binary(), integer()) -> integer().
contains_score(Haystack, Needle, Score) ->
    case gleam_stdlib:contains_string(Haystack, Needle) of
        true ->
            Score;

        false ->
            0
    end.

-file("src/gleamdoc/interface.gleam", 566).
-spec prefix_score(binary(), binary(), integer()) -> integer().
prefix_score(Haystack, Needle, Score) ->
    case gleam_stdlib:string_starts_with(Haystack, Needle) of
        true ->
            Score;

        false ->
            0
    end.

-file("src/gleamdoc/interface.gleam", 559).
-spec exact_score(binary(), binary(), integer()) -> integer().
exact_score(Haystack, Needle, Score) ->
    case Haystack =:= Needle of
        true ->
            Score;

        false ->
            0
    end.

-file("src/gleamdoc/interface.gleam", 624).
-spec entry_module(entry()) -> binary().
entry_module(Entry) ->
    case Entry of
        {module_entry, _, Name, _} ->
            Name;

        {function_entry, _, Module, _, _} ->
            Module;

        {constant_entry, _, Module@1, _, _} ->
            Module@1;

        {type_entry, _, Module@2, _, _} ->
            Module@2;

        {variant_entry, _, Module@3, _, _, _, _} ->
            Module@3;

        {alias_entry, _, Module@4, _, _} ->
            Module@4
    end.

-file("src/gleamdoc/interface.gleam", 613).
-spec entry_name(entry()) -> binary().
entry_name(Entry) ->
    case Entry of
        {module_entry, _, Name, _} ->
            Name;

        {function_entry, _, _, Name@1, _} ->
            Name@1;

        {constant_entry, _, _, Name@2, _} ->
            Name@2;

        {type_entry, _, _, Name@3, _} ->
            Name@3;

        {variant_entry, _, _, _, _, Name@4, _} ->
            Name@4;

        {alias_entry, _, _, Name@5, _} ->
            Name@5
    end.

-file("src/gleamdoc/interface.gleam", 533).
-spec search_score(entry(), binary()) -> integer().
search_score(Entry, Query) ->
    Needle = begin
        _pipe = Query,
        _pipe@1 = gleam@string:trim(_pipe),
        string:lowercase(_pipe@1)
    end,
    Name = begin
        _pipe@2 = entry_name(Entry),
        string:lowercase(_pipe@2)
    end,
    Qualified = begin
        _pipe@3 = qualified_name(Entry),
        string:lowercase(_pipe@3)
    end,
    Package_qualified = begin
        _pipe@4 = package_qualified_name(Entry),
        string:lowercase(_pipe@4)
    end,
    Module = begin
        _pipe@5 = entry_module(Entry),
        string:lowercase(_pipe@5)
    end,
    Signature = begin
        _pipe@6 = entry_signature(Entry),
        string:lowercase(_pipe@6)
    end,
    Docs = begin
        _pipe@7 = entry_documentation(Entry),
        string:lowercase(_pipe@7)
    end,
    Terms = search_terms(Query),
    ((((((exact_score(Package_qualified, Needle, 1200) + exact_score(
        Qualified,
        Needle,
        1100
    ))
    + exact_score(Name, Needle, 1000))
    + prefix_score(Name, Needle, 700))
    + contains_score(Name, Needle, 500))
    + prefix_score(Qualified, Needle, 400))
    + contains_score(Module, Needle, 250))
    + gleam@list:fold(
        Terms,
        0,
        fun(Score, Term) ->
            (((Score + contains_score(Name, Term, 80)) + contains_score(
                Module,
                Term,
                30
            ))
            + contains_score(Signature, Term, 10))
            + contains_score(Docs, Term, 5)
        end
    ).

-file("src/gleamdoc/interface.gleam", 524).
-spec compare_search_entries(binary()) -> fun((entry(), entry()) -> gleam@order:order()).
compare_search_entries(Query) ->
    fun(A, B) ->
        case gleam@int:compare(search_score(B, Query), search_score(A, Query)) of
            eq ->
                compare_entries(A, B);

            Ordering ->
                Ordering
        end
    end.

-file("src/gleamdoc/interface.gleam", 92).
?DOC(
    " Searches packages with optional entry-kind and runtime-target filters.\n"
    "\n"
    " An empty filter matches all entries. Target filters only match functions and\n"
    " constants because other entries do not have runtime-target metadata.\n"
).
-spec search_packages_filtered(
    list(gleam@package_interface:package()),
    binary(),
    integer(),
    binary(),
    binary()
) -> list(entry()).
search_packages_filtered(Packages, Query, Limit, Kind, Target) ->
    _pipe = Packages,
    _pipe@1 = gleam@list:flat_map(
        _pipe,
        fun(Package) -> search(Package, Query) end
    ),
    _pipe@2 = gleam@list:sort(_pipe@1, compare_search_entries(Query)),
    _pipe@3 = gleam@list:filter(
        _pipe@2,
        fun(Entry) ->
            matches_filter(entry_kind(Entry), Kind) andalso matches_filter_list(
                entry_targets(Entry),
                Target
            )
        end
    ),
    gleam@list:take(_pipe@3, Limit).

-file("src/gleamdoc/interface.gleam", 80).
?DOC(" Searches packages and returns at most the requested number of ranked entries.\n").
-spec search_packages(
    list(gleam@package_interface:package()),
    binary(),
    integer()
) -> list(entry()).
search_packages(Packages, Query, Limit) ->
    search_packages_filtered(Packages, Query, Limit, <<""/utf8>>, <<""/utf8>>).

-file("src/gleamdoc/interface.gleam", 819).
-spec documentation_block(binary()) -> binary().
documentation_block(Documentation) ->
    case gleam@string:trim(Documentation) of
        <<""/utf8>> ->
            <<""/utf8>>;

        Documentation@1 ->
            <<"\n\n"/utf8, Documentation@1/binary>>
    end.

-file("src/gleamdoc/interface.gleam", 812).
-spec optional_documentation(gleam@option:option(binary())) -> binary().
optional_documentation(Documentation) ->
    case Documentation of
        {some, Documentation@1} ->
            documentation_block(Documentation@1);

        none ->
            <<""/utf8>>
    end.

-file("src/gleamdoc/interface.gleam", 826).
-spec deprecation_block(
    gleam@option:option(gleam@package_interface:deprecation())
) -> binary().
deprecation_block(Deprecation) ->
    case Deprecation of
        {some, {deprecation, Message}} ->
            <<"\n\ndeprecated: "/utf8, Message/binary>>;

        none ->
            <<""/utf8>>
    end.

-file("src/gleamdoc/interface.gleam", 841).
-spec source_block(binary(), binary(), binary(), binary()) -> binary().
source_block(Package, Module, Kind, Name) ->
    case gleamdoc@index:source_location(Package, Module, Kind, Name) of
        <<""/utf8>> ->
            <<""/utf8>>;

        Location ->
            <<"\nsource: "/utf8, Location/binary>>
    end.

-file("src/gleamdoc/interface.gleam", 450).
-spec package_metadata(gleam@package_interface:package()) -> binary().
package_metadata(Package) ->
    {package, Name, Version, _, _} = Package,
    <<<<<<"\n\npackage: "/utf8, Name/binary>>/binary, " "/utf8>>/binary,
        Version/binary>>.

-file("src/gleamdoc/interface.gleam", 422).
-spec render_type_alias(
    gleam@package_interface:package(),
    binary(),
    binary(),
    gleam@package_interface:type_alias()
) -> binary().
render_type_alias(Package, Module, Name, Value) ->
    {type_alias, Documentation, Deprecation, Parameters, Alias} = Value,
    <<<<<<<<<<<<<<<<<<(qualified(Module, Name))/binary, "\n\npub type "/utf8>>/binary,
                                    Name/binary>>/binary,
                                (type_parameters(Parameters))/binary>>/binary,
                            " = "/utf8>>/binary,
                        (format_type(Alias))/binary>>/binary,
                    (package_metadata(Package))/binary>>/binary,
                (source_block(
                    entry_package_name_from(Package),
                    Module,
                    <<"alias"/utf8>>,
                    Name
                ))/binary>>/binary,
            (deprecation_block(Deprecation))/binary>>/binary,
        (optional_documentation(Documentation))/binary>>.

-file("src/gleamdoc/interface.gleam", 801).
-spec variant_type(
    gleam@package_interface:package(),
    binary(),
    binary(),
    integer()
) -> binary().
variant_type(Package, Module, Type_name, Type_parameter_count) ->
    {package, Package_name, _, _, _} = Package,
    <<(named_type_name(Type_name, Package_name, Module))/binary,
        (type_parameters(Type_parameter_count))/binary>>.

-file("src/gleamdoc/interface.gleam", 403).
-spec render_variant(
    gleam@package_interface:package(),
    binary(),
    binary(),
    integer(),
    binary(),
    gleam@package_interface:type_constructor()
) -> binary().
render_variant(Package, Module, Type_name, Type_parameter_count, Name, Value) ->
    {type_constructor, Documentation, _, Parameters} = Value,
    <<<<<<<<<<<<<<(qualified(Module, Name))/binary, "\n\n"/utf8>>/binary,
                            (variant_signature(Name, Parameters))/binary>>/binary,
                        (package_metadata(Package))/binary>>/binary,
                    "\ntype: "/utf8>>/binary,
                (variant_type(Package, Module, Type_name, Type_parameter_count))/binary>>/binary,
            (source_block(
                entry_package_name_from(Package),
                Module,
                <<"variant"/utf8>>,
                Name
            ))/binary>>/binary,
        (optional_documentation(Documentation))/binary>>.

-file("src/gleamdoc/interface.gleam", 358).
-spec render_type_definition(
    gleam@package_interface:package(),
    binary(),
    binary(),
    gleam@package_interface:type_definition()
) -> binary().
render_type_definition(Package, Module, Name, Value) ->
    {type_definition, Documentation, Deprecation, Parameters, Constructors} = Value,
    Rendered_variants = begin
        _pipe = Constructors,
        _pipe@1 = gleam@list:map(
            _pipe,
            fun(Constructor) ->
                {type_constructor, _, Name@1, Parameters@1} = Constructor,
                Parameters@2 = format_parameters(Parameters@1),
                <<<<"  "/utf8, Name@1/binary>>/binary, (case Parameters@2 of
                        <<""/utf8>> ->
                            <<""/utf8>>;

                        _ ->
                            <<<<"("/utf8, Parameters@2/binary>>/binary,
                                ")"/utf8>>
                    end)/binary>>
            end
        ),
        gleam@string:join(_pipe@1, <<"\n"/utf8>>)
    end,
    <<<<<<<<<<<<<<<<<<<<(qualified(Module, Name))/binary, "\n\npub "/utf8>>/binary,
                                        (case Constructors of
                                            [] ->
                                                <<"opaque "/utf8>>;

                                            _ ->
                                                <<""/utf8>>
                                        end)/binary>>/binary,
                                    "type "/utf8>>/binary,
                                Name/binary>>/binary,
                            (type_parameters(Parameters))/binary>>/binary,
                        (case Rendered_variants of
                            <<""/utf8>> ->
                                <<""/utf8>>;

                            _ ->
                                <<<<" {\n"/utf8, Rendered_variants/binary>>/binary,
                                    "\n}"/utf8>>
                        end)/binary>>/binary,
                    (package_metadata(Package))/binary>>/binary,
                (source_block(
                    entry_package_name_from(Package),
                    Module,
                    <<"type"/utf8>>,
                    Name
                ))/binary>>/binary,
            (deprecation_block(Deprecation))/binary>>/binary,
        (optional_documentation(Documentation))/binary>>.

-file("src/gleamdoc/interface.gleam", 455).
-spec targets(gleam@package_interface:implementations()) -> binary().
targets(Implementations) ->
    {implementations, _, _, _, Can_run_on_erlang, Can_run_on_javascript} = Implementations,
    case {Can_run_on_erlang, Can_run_on_javascript} of
        {true, true} ->
            <<"erlang, javascript"/utf8>>;

        {true, false} ->
            <<"erlang"/utf8>>;

        {false, true} ->
            <<"javascript"/utf8>>;

        {false, false} ->
            <<"none"/utf8>>
    end.

-file("src/gleamdoc/interface.gleam", 446).
-spec metadata(
    gleam@package_interface:package(),
    gleam@package_interface:implementations()
) -> binary().
metadata(Package, Implementations) ->
    <<<<(package_metadata(Package))/binary, "\ntargets: "/utf8>>/binary,
        (targets(Implementations))/binary>>.

-file("src/gleamdoc/interface.gleam", 335).
-spec render_constant(
    gleam@package_interface:package(),
    binary(),
    binary(),
    gleam@package_interface:constant()
) -> binary().
render_constant(Package, Module, Name, Value) ->
    {constant, Documentation, Deprecation, Implementations, Type_} = Value,
    <<<<<<<<<<<<<<<<(qualified(Module, Name))/binary, "\n\npub const "/utf8>>/binary,
                                Name/binary>>/binary,
                            ": "/utf8>>/binary,
                        (format_type(Type_))/binary>>/binary,
                    (metadata(Package, Implementations))/binary>>/binary,
                (source_block(
                    entry_package_name_from(Package),
                    Module,
                    <<"const"/utf8>>,
                    Name
                ))/binary>>/binary,
            (deprecation_block(Deprecation))/binary>>/binary,
        (optional_documentation(Documentation))/binary>>.

-file("src/gleamdoc/interface.gleam", 308).
-spec render_function(
    gleam@package_interface:package(),
    binary(),
    binary(),
    gleam@package_interface:function_()
) -> binary().
render_function(Package, Module, Name, Value) ->
    {function, Documentation, Deprecation, Implementations, Parameters, Return} = Value,
    Parameters@1 = format_parameters(Parameters),
    <<<<<<<<<<<<<<<<<<<<(qualified(Module, Name))/binary, "\n\npub fn "/utf8>>/binary,
                                        Name/binary>>/binary,
                                    "("/utf8>>/binary,
                                Parameters@1/binary>>/binary,
                            ") -> "/utf8>>/binary,
                        (format_type(Return))/binary>>/binary,
                    (metadata(Package, Implementations))/binary>>/binary,
                (source_block(
                    entry_package_name_from(Package),
                    Module,
                    <<"fn"/utf8>>,
                    Name
                ))/binary>>/binary,
            (deprecation_block(Deprecation))/binary>>/binary,
        (optional_documentation(Documentation))/binary>>.

-file("src/gleamdoc/interface.gleam", 281).
-spec render_module(
    gleam@package_interface:package(),
    binary(),
    gleam@package_interface:module_()
) -> binary().
render_module(Package, Name, Module) ->
    {package, Package_name, Version, _, _} = Package,
    {module, Documentation, _, _, _, _} = Module,
    Members = begin
        _pipe = module_entries(Package, Name, Module),
        _pipe@1 = gleam@list:sort(
            _pipe,
            fun(A, B) ->
                gleam@string:compare(qualified_name(A), qualified_name(B))
            end
        ),
        _pipe@2 = gleam@list:map(
            _pipe@1,
            fun(Entry) ->
                <<<<<<"  "/utf8, (entry_kind(Entry))/binary>>/binary,
                        "  "/utf8>>/binary,
                    (entry_name(Entry))/binary>>
            end
        ),
        gleam@string:join(_pipe@2, <<"\n"/utf8>>)
    end,
    Docs = begin
        _pipe@3 = Documentation,
        _pipe@4 = gleam@string:join(_pipe@3, <<"\n"/utf8>>),
        documentation_block(_pipe@4)
    end,
    <<<<<<<<<<<<<<Name/binary, "\n\nmodule\npackage: "/utf8>>/binary,
                            Package_name/binary>>/binary,
                        " "/utf8>>/binary,
                    Version/binary>>/binary,
                (source_block(
                    Package_name,
                    Name,
                    <<"module"/utf8>>,
                    <<""/utf8>>
                ))/binary>>/binary,
            Docs/binary>>/binary,
        (case Members of
            <<""/utf8>> ->
                <<""/utf8>>;

            _ ->
                <<"\n\nMembers:\n"/utf8, Members/binary>>
        end)/binary>>.

-file("src/gleamdoc/interface.gleam", 170).
?DOC(" Renders complete documentation for one entry.\n").
-spec render(entry()) -> binary().
render(Entry) ->
    case Entry of
        {module_entry, Package, Name, Module} ->
            render_module(Package, Name, Module);

        {function_entry, Package@1, Module@1, Name@1, Value} ->
            render_function(Package@1, Module@1, Name@1, Value);

        {constant_entry, Package@2, Module@2, Name@2, Value@1} ->
            render_constant(Package@2, Module@2, Name@2, Value@1);

        {type_entry, Package@3, Module@3, Name@3, Value@2} ->
            render_type_definition(Package@3, Module@3, Name@3, Value@2);

        {variant_entry,
            Package@4,
            Module@4,
            Type_name,
            Type_parameters,
            Name@4,
            Value@3} ->
            render_variant(
                Package@4,
                Module@4,
                Type_name,
                Type_parameters,
                Name@4,
                Value@3
            );

        {alias_entry, Package@5, Module@5, Name@5, Value@4} ->
            render_type_alias(Package@5, Module@5, Name@5, Value@4)
    end.

-file("src/gleamdoc/interface.gleam", 110).
?DOC(" Renders complete documentation for all entries.\n").
-spec render_all(list(entry())) -> binary().
render_all(Entries) ->
    _pipe = Entries,
    _pipe@1 = gleam@list:map(_pipe, fun render/1),
    gleam@string:join(_pipe@1, <<"\n\n"/utf8>>).

-file("src/gleamdoc/interface.gleam", 115).
?DOC(" Renders compact, one-line search results.\n").
-spec render_search_results(list(entry())) -> binary().
render_search_results(Entries) ->
    _pipe = Entries,
    _pipe@1 = gleam@list:map(
        _pipe,
        fun(Entry) ->
            <<<<(entry_kind(Entry))/binary, "  "/utf8>>/binary,
                (package_qualified_name(Entry))/binary>>
        end
    ),
    gleam@string:join(_pipe@1, <<"\n"/utf8>>).

-file("src/gleamdoc/interface.gleam", 124).
?DOC(" Renders package names, versions, and module counts.\n").
-spec render_packages(list(gleam@package_interface:package())) -> binary().
render_packages(Packages) ->
    _pipe = Packages,
    _pipe@1 = gleam@list:sort(
        _pipe,
        fun(A, B) ->
            {package, A_name, _, _, _} = A,
            {package, B_name, _, _, _} = B,
            gleam@string:compare(A_name, B_name)
        end
    ),
    _pipe@2 = gleam@list:map(
        _pipe@1,
        fun(Package) ->
            {package, Name, Version, _, Modules} = Package,
            <<<<<<<<<<Name/binary, " "/utf8>>/binary, Version/binary>>/binary,
                        "  "/utf8>>/binary,
                    (erlang:integer_to_binary(maps:size(Modules)))/binary>>/binary,
                " modules"/utf8>>
        end
    ),
    gleam@string:join(_pipe@2, <<"\n"/utf8>>).

-file("src/gleamdoc/interface.gleam", 646).
-spec entry_json(entry()) -> gleam@json:json().
entry_json(Entry) ->
    Package = entry_package(Entry),
    {package, Package_name, Version, _, _} = Package,
    Module = entry_module(Entry),
    Name = entry_name(Entry),
    Kind = entry_kind(Entry),
    Source = gleamdoc@index:source_location(Package_name, Module, Kind, Name),
    gleam@json:object(
        [{<<"package"/utf8>>, gleam@json:string(Package_name)},
            {<<"version"/utf8>>, gleam@json:string(Version)},
            {<<"module"/utf8>>, gleam@json:string(Module)},
            {<<"kind"/utf8>>, gleam@json:string(Kind)},
            {<<"name"/utf8>>, gleam@json:string(Name)},
            {<<"qualified_name"/utf8>>,
                gleam@json:string(qualified_name(Entry))},
            {<<"signature"/utf8>>, gleam@json:string(entry_signature(Entry))},
            {<<"documentation"/utf8>>,
                gleam@json:string(entry_documentation(Entry))},
            {<<"targets"/utf8>>,
                gleam@json:array(entry_targets(Entry), fun gleam@json:string/1)},
            {<<"source"/utf8>>, case Source of
                    <<""/utf8>> ->
                        gleam@json:null();

                    Source@1 ->
                        gleam@json:string(Source@1)
                end}]
    ).

-file("src/gleamdoc/interface.gleam", 144).
?DOC(" Encodes entries in Gleamdoc's versioned JSON response envelope.\n").
-spec entries_json(list(entry())) -> gleam@json:json().
entries_json(Entries) ->
    gleam@json:object(
        [{<<"schema_version"/utf8>>, gleam@json:int(1)},
            {<<"results"/utf8>>, gleam@json:array(Entries, fun entry_json/1)}]
    ).

-file("src/gleamdoc/interface.gleam", 152).
?DOC(" Encodes package summaries in Gleamdoc's versioned JSON response envelope.\n").
-spec packages_json(list(gleam@package_interface:package())) -> gleam@json:json().
packages_json(Packages) ->
    gleam@json:object(
        [{<<"schema_version"/utf8>>, gleam@json:int(1)},
            {<<"results"/utf8>>,
                gleam@json:array(
                    Packages,
                    fun(Package) ->
                        {package, Name, Version, _, Modules} = Package,
                        gleam@json:object(
                            [{<<"name"/utf8>>, gleam@json:string(Name)},
                                {<<"version"/utf8>>, gleam@json:string(Version)},
                                {<<"modules"/utf8>>,
                                    gleam@json:int(maps:size(Modules))}]
                        )
                    end
                )}]
    ).