1 {-# LANGUAGE InstanceSigs #-}
3 module Literate.Web.Types.URL (
6 PathSegment (unPathSegment),
11 import Data.Data (Data)
13 import Data.Function (($), (.))
14 import Data.Functor ((<$>))
15 import Data.List (isInfixOf)
17 import Data.Semigroup (Semigroup (..))
18 import Data.String (IsString (..), String)
19 import Data.Text (Text)
20 import Data.Text qualified as Text
21 import Data.Text.Normalize qualified as UT
22 import GHC.Generics (Generic)
23 import GHC.Stack (HasCallStack)
24 import Network.URI.Encode qualified as UE
25 import Text.Show (Show)
26 import Prelude (FilePath, error)
29 type Path = [PathSegment]
31 encodePath :: [PathSegment] -> FilePath
34 Text.intercalate (Text.singleton '/') $
35 encodePathSegment <$> s
37 -- ** Type 'PathSegment'
38 newtype PathSegment = PathSegment {unPathSegment :: Text}
39 deriving (Eq, Show, Ord, Data, Generic)
41 instance IsString PathSegment where
42 fromString :: HasCallStack => String -> PathSegment
45 then error ("PathSegment cannot contain a slash: " <> s)
46 else PathSegment (normalizeUnicode (fromString s))
48 encodePathSegment :: PathSegment -> Text
49 encodePathSegment = UE.encodeText . unPathSegment
51 decodePathSegment :: Text -> PathSegment
52 decodePathSegment = fromString . UE.decode . Text.unpack
54 normalizeUnicode :: Text -> Text
55 normalizeUnicode = UT.normalize UT.NFC