Skip to main content

src/gg_cn@internal@class_map.erl

-module(gg_cn@internal@class_map).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gg_cn/internal/class_map.gleam").
-export([build/1, get_class_group_id/2, get_conflicting_class_group_ids/3]).
-export_type([class_part/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 class_part() :: {class_part,
        gleam@dict:dict(binary(), class_part()),
        list({binary(), fun((binary()) -> boolean())}),
        gleam@option:option(binary())}.

-file("src/gg_cn/internal/class_map.gleam", 26).
?DOC(false).
-spec empty() -> class_part().
empty() ->
    {class_part, maps:new(), [], none}.

-file("src/gg_cn/internal/class_map.gleam", 79).
?DOC(false).
-spec update_at_path(
    class_part(),
    list(binary()),
    fun((class_part()) -> class_part())
) -> class_part().
update_at_path(Part, Path, Update) ->
    case Path of
        [] ->
            Update(Part);

        [Head | Tail] ->
            Child = case gleam_stdlib:map_get(erlang:element(2, Part), Head) of
                {ok, Node} ->
                    Node;

                {error, _} ->
                    empty()
            end,
            Updated = update_at_path(Child, Tail, Update),
            {class_part,
                gleam@dict:insert(erlang:element(2, Part), Head, Updated),
                erlang:element(3, Part),
                erlang:element(4, Part)}
    end.

-file("src/gg_cn/internal/class_map.gleam", 48).
?DOC(false).
-spec process_def(
    gg_cn@internal@config:class_def(),
    class_part(),
    binary(),
    gleam@dict:dict(binary(), list(gg_cn@internal@config:class_def()))
) -> class_part().
process_def(Def, Part, Group_id, Theme) ->
    case Def of
        {lit, <<""/utf8>>} ->
            {class_part,
                erlang:element(2, Part),
                erlang:element(3, Part),
                {some, Group_id}};

        {lit, Literal} ->
            update_at_path(
                Part,
                gleam@string:split(Literal, <<"-"/utf8>>),
                fun(Node) ->
                    {class_part,
                        erlang:element(2, Node),
                        erlang:element(3, Node),
                        {some, Group_id}}
                end
            );

        {theme, Key} ->
            Resolved = begin
                _pipe = gleam_stdlib:map_get(Theme, Key),
                gleam@result:unwrap(_pipe, [])
            end,
            process_defs(Resolved, Part, Group_id, Theme);

        {val, Validator} ->
            {class_part,
                erlang:element(2, Part),
                lists:append(erlang:element(3, Part), [{Group_id, Validator}]),
                erlang:element(4, Part)};

        {obj, Entries} ->
            gleam@list:fold(
                Entries,
                Part,
                fun(Acc, Entry) ->
                    {Key@1, Child_defs} = Entry,
                    update_at_path(
                        Acc,
                        gleam@string:split(Key@1, <<"-"/utf8>>),
                        fun(Node@1) ->
                            process_defs(Child_defs, Node@1, Group_id, Theme)
                        end
                    )
                end
            )
    end.

-file("src/gg_cn/internal/class_map.gleam", 39).
?DOC(false).
-spec process_defs(
    list(gg_cn@internal@config:class_def()),
    class_part(),
    binary(),
    gleam@dict:dict(binary(), list(gg_cn@internal@config:class_def()))
) -> class_part().
process_defs(Defs, Part, Group_id, Theme) ->
    gleam@list:fold(
        Defs,
        Part,
        fun(Acc, Def) -> process_def(Def, Acc, Group_id, Theme) end
    ).

-file("src/gg_cn/internal/class_map.gleam", 32).
?DOC(false).
-spec build(gg_cn@internal@config:config()) -> class_part().
build(Cfg) ->
    gleam@list:fold(
        erlang:element(3, Cfg),
        empty(),
        fun(Part, Group) ->
            {Group_id, Defs} = Group,
            process_defs(Defs, Part, Group_id, erlang:element(2, Cfg))
        end
    ).

-file("src/gg_cn/internal/class_map.gleam", 151).
?DOC(false).
-spec find_validator(list({binary(), fun((binary()) -> boolean())}), binary()) -> gleam@option:option(binary()).
find_validator(Validators, Class_rest) ->
    case Validators of
        [] ->
            none;

        [{Group_id, Validator} | Rest] ->
            case Validator(Class_rest) of
                true ->
                    {some, Group_id};

                false ->
                    find_validator(Rest, Class_rest)
            end
    end.

-file("src/gg_cn/internal/class_map.gleam", 131).
?DOC(false).
-spec get_group_recursive(list(binary()), class_part()) -> gleam@option:option(binary()).
get_group_recursive(Parts, Part) ->
    case Parts of
        [] ->
            erlang:element(4, Part);

        [Head | Tail] ->
            From_next = case gleam_stdlib:map_get(erlang:element(2, Part), Head) of
                {ok, Child} ->
                    get_group_recursive(Tail, Child);

                {error, _} ->
                    none
            end,
            case From_next of
                {some, _} ->
                    From_next;

                none ->
                    case erlang:element(3, Part) of
                        [] ->
                            none;

                        Validators ->
                            find_validator(
                                Validators,
                                gleam@string:join(Parts, <<"-"/utf8>>)
                            )
                    end
            end
    end.

-file("src/gg_cn/internal/class_map.gleam", 119).
?DOC(false).
-spec arbitrary_property_group_id(binary()) -> gleam@option:option(binary()).
arbitrary_property_group_id(Class_name) ->
    Content = gleam@string:slice(Class_name, 1, string:length(Class_name) - 2),
    case gleam@string:split_once(Content, <<":"/utf8>>) of
        {ok, {Property, _}} ->
            case Property of
                <<""/utf8>> ->
                    none;

                _ ->
                    {some, <<"arbitrary.."/utf8, Property/binary>>}
            end;

        {error, _} ->
            none
    end.

-file("src/gg_cn/internal/class_map.gleam", 99).
?DOC(false).
-spec get_class_group_id(class_part(), binary()) -> gleam@option:option(binary()).
get_class_group_id(Class_map, Class_name) ->
    case gleam_stdlib:string_starts_with(Class_name, <<"["/utf8>>) andalso gleam_stdlib:string_ends_with(
        Class_name,
        <<"]"/utf8>>
    ) of
        true ->
            arbitrary_property_group_id(Class_name);

        false ->
            Parts = gleam@string:split(Class_name, <<"-"/utf8>>),
            Parts@1 = case Parts of
                [<<""/utf8>>, _ | _] ->
                    gleam@list:drop(Parts, 1);

                _ ->
                    Parts
            end,
            get_group_recursive(Parts@1, Class_map)
    end.

-file("src/gg_cn/internal/class_map.gleam", 165).
?DOC(false).
-spec get_conflicting_class_group_ids(
    gg_cn@internal@config:config(),
    binary(),
    boolean()
) -> list(binary()).
get_conflicting_class_group_ids(Cfg, Class_group_id, Has_postfix_modifier) ->
    case Has_postfix_modifier of
        true ->
            Base = gleam_stdlib:map_get(erlang:element(4, Cfg), Class_group_id),
            case gleam_stdlib:map_get(erlang:element(5, Cfg), Class_group_id) of
                {ok, Modifier_conflicts} ->
                    case Base of
                        {ok, Base_conflicts} ->
                            lists:append(Base_conflicts, Modifier_conflicts);

                        {error, _} ->
                            Modifier_conflicts
                    end;

                {error, _} ->
                    gleam@result:unwrap(Base, [])
            end;

        false ->
            gleam@result:unwrap(
                gleam_stdlib:map_get(erlang:element(4, Cfg), Class_group_id),
                []
            )
    end.