-- SPDX-FileCopyrightText: 2026 Alexandra de Wit
--
-- SPDX-License-Identifier: MIT

{- | The PEP 503 name grammar (PyPI): the canonical key a package name matches on.

'Ecluse.Core.Package.canonicalise' dispatches here on the ecosystem tag, and every other caller
reads the grammar through that dispatch.
-}
module Ecluse.Core.Package.Pep503 (
    normalisePyPI,
) where

import Data.Text qualified as T

{- | PEP 503 name normalisation: lower-case, then collapse each run of @-@, @_@ or @.@ to a
single @-@, so two spellings of one distribution share a canonical key.
-}
normalisePyPI :: Text -> Text
normalisePyPI :: Text -> Text
normalisePyPI Text
t =
    Text -> [Text] -> Text
T.intercalate Text
"-"
        ([Text] -> Text) -> (Text -> [Text]) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Bool
T.null)
        ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
T.splitOn Text
"-"
        (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ (Char -> Char) -> Text -> Text
T.map (\Char
c -> if Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'_' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.' then Char
'-' else Char
c) (Text -> Text
T.toLower Text
t)