-module(glugify@internal@processors). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/glugify/internal/processors.gleam"). -export([normalize_whitespace/1, apply_separators/2, remove_invalid_chars/2, collapse_separators/2, trim_separators/2, truncate_slug/4, decamelize/1, apply_custom_replacements/2, filter_stop_words/3]). -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). -file("src/glugify/internal/processors.gleam", 34). ?DOC(false). -spec is_whitespace(binary()) -> boolean(). is_whitespace(Char) -> case Char of <<" "/utf8>> -> true; <<"\t"/utf8>> -> true; <<"\n"/utf8>> -> true; <<"\r"/utf8>> -> true; _ -> false end. -file("src/glugify/internal/processors.gleam", 14). ?DOC(false). -spec normalize_whitespace_graphemes(list(binary()), list(binary())) -> list(binary()). normalize_whitespace_graphemes(Graphemes, Acc) -> case Graphemes of [] -> lists:reverse(Acc); [Char | Rest] -> case is_whitespace(Char) of true -> case Acc of [<<" "/utf8>> | _] -> normalize_whitespace_graphemes(Rest, Acc); _ -> normalize_whitespace_graphemes( Rest, [<<" "/utf8>> | Acc] ) end; false -> normalize_whitespace_graphemes(Rest, [Char | Acc]) end end. -file("src/glugify/internal/processors.gleam", 6). ?DOC(false). -spec normalize_whitespace(binary()) -> {ok, binary()} | {error, glugify@errors:slugify_error()}. normalize_whitespace(Text) -> _pipe = Text, _pipe@1 = gleam@string:to_graphemes(_pipe), _pipe@2 = normalize_whitespace_graphemes(_pipe@1, []), _pipe@3 = gleam@string:join(_pipe@2, <<""/utf8>>), {ok, _pipe@3}. -file("src/glugify/internal/processors.gleam", 127). ?DOC(false). -spec is_alphanumeric(binary()) -> boolean(). is_alphanumeric(Char) -> case gleam@string:to_utf_codepoints(Char) of [Codepoint] -> Code = gleam_stdlib:identity(Codepoint), (((Code >= 48) andalso (Code =< 57)) orelse ((Code >= 65) andalso (Code =< 90))) orelse ((Code >= 97) andalso (Code =< 122)); _ -> false end. -file("src/glugify/internal/processors.gleam", 149). ?DOC(false). -spec is_unicode_char(binary()) -> boolean(). is_unicode_char(Char) -> case gleam@string:to_utf_codepoints(Char) of [] -> false; Codepoints -> gleam@list:any( Codepoints, fun(Codepoint) -> gleam_stdlib:identity(Codepoint) > 127 end ) end. -file("src/glugify/internal/processors.gleam", 142). ?DOC(false). -spec is_alphanumeric_or_unicode(binary(), boolean()) -> boolean(). is_alphanumeric_or_unicode(Char, Allow_unicode) -> case Allow_unicode of true -> is_alphanumeric(Char) orelse is_unicode_char(Char); false -> is_alphanumeric(Char) end. -file("src/glugify/internal/processors.gleam", 96). ?DOC(false). -spec is_slug_char(binary(), glugify@config:config()) -> boolean(). is_slug_char(Char, Config) -> is_alphanumeric_or_unicode(Char, erlang:element(7, Config)) orelse gleam@list:contains( erlang:element(16, Config), Char ). -file("src/glugify/internal/processors.gleam", 63). ?DOC(false). -spec apply_separators_simple( list(binary()), glugify@config:config(), list(binary()), boolean() ) -> list(binary()). apply_separators_simple(Graphemes, Config, Acc, Last_was_separator) -> case Graphemes of [] -> lists:reverse(Acc); [Char | Rest] -> case is_slug_char(Char, Config) of true -> apply_separators_simple(Rest, Config, [Char | Acc], false); false -> case Last_was_separator orelse gleam@list:is_empty(Acc) of true -> apply_separators_simple(Rest, Config, Acc, true); false -> Separator_chars = begin _pipe = gleam@string:to_graphemes( erlang:element(2, Config) ), lists:reverse(_pipe) end, apply_separators_simple( Rest, Config, lists:append(Separator_chars, Acc), true ) end end end. -file("src/glugify/internal/processors.gleam", 41). ?DOC(false). -spec apply_separators(binary(), glugify@config:config()) -> {ok, binary()} | {error, glugify@errors:slugify_error()}. apply_separators(Text, Config) -> case erlang:element(2, Config) of <<""/utf8>> -> _pipe = Text, _pipe@1 = gleam@string:to_graphemes(_pipe), _pipe@2 = gleam@list:filter( _pipe@1, fun(Char) -> is_slug_char(Char, Config) end ), _pipe@3 = gleam@string:join(_pipe@2, <<""/utf8>>), {ok, _pipe@3}; _ -> _pipe@4 = Text, _pipe@5 = gleam@string:to_graphemes(_pipe@4), _pipe@6 = apply_separators_simple(_pipe@5, Config, [], false), _pipe@7 = gleam@string:join(_pipe@6, <<""/utf8>>), {ok, _pipe@7} end. -file("src/glugify/internal/processors.gleam", 111). ?DOC(false). -spec ends_with_separator_helper(list(binary()), list(binary())) -> boolean(). ends_with_separator_helper(Acc, Separator_chars) -> case Separator_chars of [] -> true; [Sep_char | Rest_sep] -> case Acc of [Acc_char | Rest_acc] when Acc_char =:= Sep_char -> ends_with_separator_helper(Rest_acc, Rest_sep); _ -> false end end. -file("src/glugify/internal/processors.gleam", 101). ?DOC(false). -spec ends_with_separator(list(binary()), binary()) -> boolean(). ends_with_separator(Acc, Separator) -> case Separator of <<""/utf8>> -> false; _ -> Separator_chars = begin _pipe = gleam@string:to_graphemes(Separator), lists:reverse(_pipe) end, ends_with_separator_helper(Acc, Separator_chars) end. -file("src/glugify/internal/processors.gleam", 162). ?DOC(false). -spec is_char_in_separator(binary(), binary()) -> boolean(). is_char_in_separator(Char, Separator) -> case Separator of <<""/utf8>> -> false; _ -> gleam_stdlib:contains_string(Separator, Char) end. -file("src/glugify/internal/processors.gleam", 180). ?DOC(false). -spec filter_valid_chars_with_unicode( list(binary()), glugify@config:config(), list(binary()) ) -> list(binary()). filter_valid_chars_with_unicode(Graphemes, Config, Acc) -> case Graphemes of [] -> lists:reverse(Acc); [Char | Rest] -> case is_slug_char(Char, Config) orelse is_char_in_separator( Char, erlang:element(2, Config) ) of true -> filter_valid_chars_with_unicode(Rest, Config, [Char | Acc]); false -> filter_valid_chars_with_unicode(Rest, Config, Acc) end end. -file("src/glugify/internal/processors.gleam", 169). ?DOC(false). -spec remove_invalid_chars(binary(), glugify@config:config()) -> {ok, binary()} | {error, glugify@errors:slugify_error()}. remove_invalid_chars(Text, Config) -> _pipe = Text, _pipe@1 = gleam@string:to_graphemes(_pipe), _pipe@2 = filter_valid_chars_with_unicode(_pipe@1, Config, []), _pipe@3 = gleam@string:join(_pipe@2, <<""/utf8>>), {ok, _pipe@3}. -file("src/glugify/internal/processors.gleam", 288). ?DOC(false). -spec drop_separator_prefix_helper(list(binary()), list(binary())) -> list(binary()). drop_separator_prefix_helper(Graphemes, Separator_chars) -> case Separator_chars of [] -> Graphemes; [_ | Rest_sep] -> case Graphemes of [_ | Rest_graphemes] -> drop_separator_prefix_helper(Rest_graphemes, Rest_sep); [] -> [] end end. -file("src/glugify/internal/processors.gleam", 280). ?DOC(false). -spec drop_separator_prefix(list(binary()), binary()) -> list(binary()). drop_separator_prefix(Graphemes, Separator) -> Separator_chars = gleam@string:to_graphemes(Separator), drop_separator_prefix_helper(Graphemes, Separator_chars). -file("src/glugify/internal/processors.gleam", 264). ?DOC(false). -spec starts_with_separator_helper(list(binary()), list(binary())) -> boolean(). starts_with_separator_helper(Graphemes, Separator_chars) -> case Separator_chars of [] -> true; [Sep_char | Rest_sep] -> case Graphemes of [Grapheme | Rest_graphemes] when Grapheme =:= Sep_char -> starts_with_separator_helper(Rest_graphemes, Rest_sep); _ -> false end end. -file("src/glugify/internal/processors.gleam", 259). ?DOC(false). -spec starts_with_separator(list(binary()), binary()) -> boolean(). starts_with_separator(Graphemes, Separator) -> Separator_chars = gleam@string:to_graphemes(Separator), starts_with_separator_helper(Graphemes, Separator_chars). -file("src/glugify/internal/processors.gleam", 221). ?DOC(false). -spec collapse_separators_helper(list(binary()), binary(), list(binary())) -> list(binary()). collapse_separators_helper(Graphemes, Separator, Acc) -> case Graphemes of [] -> lists:reverse(Acc); _ -> case starts_with_separator(Graphemes, Separator) of true -> case ends_with_separator(Acc, Separator) of true -> Remaining = drop_separator_prefix( Graphemes, Separator ), collapse_separators_helper( Remaining, Separator, Acc ); false -> Separator_chars = gleam@string:to_graphemes( Separator ), Remaining@1 = drop_separator_prefix( Graphemes, Separator ), collapse_separators_helper( Remaining@1, Separator, lists:append( lists:reverse(Separator_chars), Acc ) ) end; false -> case Graphemes of [Char | Rest] -> collapse_separators_helper( Rest, Separator, [Char | Acc] ); [] -> lists:reverse(Acc) end end end. -file("src/glugify/internal/processors.gleam", 210). ?DOC(false). -spec collapse_separators_graphemes(list(binary()), binary(), list(binary())) -> list(binary()). collapse_separators_graphemes(Graphemes, Separator, Acc) -> case Separator of <<""/utf8>> -> lists:reverse(lists:append(lists:reverse(Graphemes), Acc)); _ -> collapse_separators_helper(Graphemes, Separator, Acc) end. -file("src/glugify/internal/processors.gleam", 199). ?DOC(false). -spec collapse_separators(binary(), glugify@config:config()) -> {ok, binary()} | {error, glugify@errors:slugify_error()}. collapse_separators(Text, Config) -> _pipe = Text, _pipe@1 = gleam@string:to_graphemes(_pipe), _pipe@2 = collapse_separators_graphemes( _pipe@1, erlang:element(2, Config), [] ), _pipe@3 = gleam@string:join(_pipe@2, <<""/utf8>>), {ok, _pipe@3}. -file("src/glugify/internal/processors.gleam", 341). ?DOC(false). -spec trim_separator_end(binary(), binary()) -> binary(). trim_separator_end(Text, Separator) -> case Separator of <<""/utf8>> -> Text; _ -> case gleam_stdlib:string_ends_with(Text, Separator) of true -> trim_separator_end( gleam@string:drop_end(Text, string:length(Separator)), Separator ); false -> Text end end. -file("src/glugify/internal/processors.gleam", 326). ?DOC(false). -spec trim_separator_start(binary(), binary()) -> binary(). trim_separator_start(Text, Separator) -> case Separator of <<""/utf8>> -> Text; _ -> case gleam_stdlib:string_starts_with(Text, Separator) of true -> trim_separator_start( gleam@string:drop_start(Text, string:length(Separator)), Separator ); false -> Text end end. -file("src/glugify/internal/processors.gleam", 320). ?DOC(false). -spec trim_separator_ends(binary(), binary()) -> binary(). trim_separator_ends(Text, Separator) -> _pipe = Text, _pipe@1 = trim_separator_start(_pipe, Separator), trim_separator_end(_pipe@1, Separator). -file("src/glugify/internal/processors.gleam", 304). ?DOC(false). -spec trim_separators(binary(), glugify@config:config()) -> {ok, binary()} | {error, glugify@errors:slugify_error()}. trim_separators(Text, Config) -> case erlang:element(12, Config) of true -> _pipe = Text, _pipe@1 = gleam@string:trim_start(_pipe), _pipe@2 = gleam@string:trim_end(_pipe@1), _pipe@3 = trim_separator_ends(_pipe@2, erlang:element(2, Config)), {ok, _pipe@3}; false -> {ok, Text} end. -file("src/glugify/internal/processors.gleam", 373). ?DOC(false). -spec truncate_without_word_boundary(binary(), integer(), binary()) -> {ok, binary()} | {error, glugify@errors:slugify_error()}. truncate_without_word_boundary(Text, Max_length, Separator) -> Truncated = gleam@string:slice(Text, 0, Max_length), case Separator of <<""/utf8>> -> {ok, Truncated}; _ -> case gleam_stdlib:string_ends_with(Truncated, Separator) of true -> {ok, gleam@string:drop_end( Truncated, string:length(Separator) )}; false -> {ok, Truncated} end end. -file("src/glugify/internal/processors.gleam", 420). ?DOC(false). -spec find_last_separator_by_string(binary(), binary(), integer()) -> {ok, integer()} | {error, nil}. find_last_separator_by_string(Text, Separator, Start_index) -> case Start_index < 0 of true -> {error, nil}; false -> Substr = gleam@string:slice( Text, Start_index, string:length(Separator) ), case Substr =:= Separator of true -> {ok, Start_index}; false -> find_last_separator_by_string( Text, Separator, Start_index - 1 ) end end. -file("src/glugify/internal/processors.gleam", 412). ?DOC(false). -spec find_last_separator(binary(), binary()) -> {ok, integer()} | {error, nil}. find_last_separator(Text, Separator) -> find_last_separator_by_string( Text, Separator, string:length(Text) - string:length(Separator) ). -file("src/glugify/internal/processors.gleam", 390). ?DOC(false). -spec truncate_at_word_boundary(binary(), integer(), binary()) -> {ok, binary()} | {error, glugify@errors:slugify_error()}. truncate_at_word_boundary(Text, Max_length, Separator) -> Truncated = gleam@string:slice(Text, 0, Max_length), case Separator of <<""/utf8>> -> {ok, Truncated}; _ -> case gleam_stdlib:string_ends_with(Truncated, Separator) of true -> {ok, gleam@string:drop_end( Truncated, string:length(Separator) )}; false -> case find_last_separator(Truncated, Separator) of {ok, Index} -> {ok, gleam@string:slice(Truncated, 0, Index)}; {error, _} -> {ok, Truncated} end end end. -file("src/glugify/internal/processors.gleam", 356). ?DOC(false). -spec truncate_slug(binary(), integer(), boolean(), binary()) -> {ok, binary()} | {error, glugify@errors:slugify_error()}. truncate_slug(Text, Max_length, Word_boundary, Separator) -> case string:length(Text) =< Max_length of true -> {ok, Text}; false -> case Word_boundary of true -> truncate_at_word_boundary(Text, Max_length, Separator); false -> truncate_without_word_boundary(Text, Max_length, Separator) end end. -file("src/glugify/internal/processors.gleam", 482). ?DOC(false). -spec is_lower_or_digit(binary()) -> boolean(). is_lower_or_digit(Char) -> case gleam@string:to_utf_codepoints(Char) of [Codepoint] -> Code = gleam_stdlib:identity(Codepoint), ((Code >= 97) andalso (Code =< 122)) orelse ((Code >= 48) andalso (Code =< 57)); _ -> false end. -file("src/glugify/internal/processors.gleam", 472). ?DOC(false). -spec is_upper(binary()) -> boolean(). is_upper(Char) -> case gleam@string:to_utf_codepoints(Char) of [Codepoint] -> Code = gleam_stdlib:identity(Codepoint), (Code >= 65) andalso (Code =< 90); _ -> false end. -file("src/glugify/internal/processors.gleam", 448). ?DOC(false). -spec decamelize_graphemes(list(binary()), list(binary())) -> list(binary()). decamelize_graphemes(Graphemes, Acc) -> case Graphemes of [A, B | Rest] -> case is_lower_or_digit(A) andalso is_upper(B) of true -> decamelize_graphemes([B | Rest], [<<" "/utf8>>, A | Acc]); false -> case Rest of [C | _] -> case (is_upper(A) andalso is_upper(B)) andalso is_lower_or_digit( C ) of true -> decamelize_graphemes( [B | Rest], [<<" "/utf8>>, A | Acc] ); false -> decamelize_graphemes([B | Rest], [A | Acc]) end; [] -> decamelize_graphemes([B | Rest], [A | Acc]) end end; [A@1] -> lists:reverse([A@1 | Acc]); [] -> lists:reverse(Acc) end. -file("src/glugify/internal/processors.gleam", 440). ?DOC(false). -spec decamelize(binary()) -> {ok, binary()} | {error, glugify@errors:slugify_error()}. decamelize(Text) -> _pipe = Text, _pipe@1 = gleam@string:to_graphemes(_pipe), _pipe@2 = decamelize_graphemes(_pipe@1, []), _pipe@3 = gleam@string:join(_pipe@2, <<""/utf8>>), {ok, _pipe@3}. -file("src/glugify/internal/processors.gleam", 499). ?DOC(false). -spec apply_replacements_helper(binary(), list({binary(), binary()})) -> binary(). apply_replacements_helper(Text, Replacements) -> case Replacements of [] -> Text; [{Find, Replace} | Rest] -> Updated = gleam@string:replace(Text, Find, Replace), apply_replacements_helper(Updated, Rest) end. -file("src/glugify/internal/processors.gleam", 492). ?DOC(false). -spec apply_custom_replacements(binary(), list({binary(), binary()})) -> {ok, binary()} | {error, glugify@errors:slugify_error()}. apply_custom_replacements(Text, Replacements) -> _pipe = apply_replacements_helper(Text, Replacements), {ok, _pipe}. -file("src/glugify/internal/processors.gleam", 529). ?DOC(false). -spec filter_stop_words_helper(list(binary()), list(binary()), list(binary())) -> list(binary()). filter_stop_words_helper(Words, Lowered_stop_words, Acc) -> case Words of [] -> lists:reverse(Acc); [Word | Rest] -> case gleam@list:contains(Lowered_stop_words, string:lowercase(Word)) of true -> filter_stop_words_helper(Rest, Lowered_stop_words, Acc); false -> filter_stop_words_helper( Rest, Lowered_stop_words, [Word | Acc] ) end end. -file("src/glugify/internal/processors.gleam", 512). ?DOC(false). -spec filter_stop_words(binary(), list(binary()), binary()) -> {ok, binary()} | {error, glugify@errors:slugify_error()}. filter_stop_words(Text, Stop_words, Separator) -> case gleam@list:is_empty(Stop_words) of true -> {ok, Text}; false -> Lowered_stop_words = gleam@list:map( Stop_words, fun string:lowercase/1 ), Words = gleam@string:split(Text, Separator), Filtered_words = filter_stop_words_helper( Words, Lowered_stop_words, [] ), _pipe = gleam@string:join(Filtered_words, Separator), {ok, _pipe} end.