{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
module Html.Convert where
import Data.Proxy
import Data.String
import GHC.TypeLits
import Html.Type
import qualified Data.Text.Lazy as T
import qualified Data.Text.Lazy.Encoding as T
import qualified Data.Text.Lazy.Builder as TB
import qualified Data.Text.Lazy.Builder.Int as TB
import qualified Data.Text.Lazy.Builder.RealFloat as TB
import qualified Data.ByteString.Lazy.Char8 as B
{-# INLINE escapeString #-}
escapeString :: String -> String
escapeString = concatMap $ escape pure
{-# INLINE escapeText #-}
escapeText :: T.Text -> T.Text
escapeText = T.concatMap $ escape T.singleton
{-# INLINE escapeByteString #-}
escapeByteString :: B.ByteString -> B.ByteString
escapeByteString = B.concatMap $ escape B.singleton
{-# INLINE escape #-}
escape :: IsString a => (Char -> a) -> Char -> a
escape f = \case
'<' -> "<"
'>' -> ">"
'&' -> "&"
'"' -> """
'\'' -> "'"
x -> f x
class Conv b where
conv :: Convert a => a -> Converted b
instance Conv String where
{-# INLINE conv #-}
conv = convertString
instance Conv T.Text where
{-# INLINE conv #-}
conv = convertText
instance Conv B.ByteString where
{-# INLINE conv #-}
conv = convertByteString
class Convert a where
{-# MINIMAL convertText #-}
convertString :: a -> Converted String
{-# INLINE convertString #-}
convertString = Converted . T.unpack . unConv . convertText
convertText :: a -> Converted T.Text
convertByteString :: a -> Converted B.ByteString
{-# INLINE convertByteString #-}
convertByteString = Converted . T.encodeUtf8 . unConv . convertText
instance Convert (Raw String) where
{-# INLINE convertText #-}
convertText (Raw x) = Converted (T.pack x)
instance Convert (Raw T.Text) where
{-# INLINE convertText #-}
convertText (Raw x) = Converted x
instance Convert (Raw B.ByteString) where
{-# INLINE convertText #-}
convertText (Raw x) = Converted (T.decodeUtf8 x)
{-# INLINE convertByteString #-}
convertByteString (Raw x) = Converted x
instance Convert String where
{-# INLINE convertString #-}
convertString = Converted . escapeString
{-# INLINE convertText #-}
convertText = Converted . escapeText . T.pack
instance Convert T.Text where
{-# INLINE convertText #-}
convertText = Converted . escapeText
instance Convert Int where
{-# INLINE convertString #-}
convertString = Converted . show
{-# INLINE convertText #-}
convertText = Converted . TB.toLazyText . TB.decimal
{-# INLINE convertByteString #-}
convertByteString = Converted . B.pack . show
instance Convert Integer where
{-# INLINE convertString #-}
convertString = Converted . show
{-# INLINE convertText #-}
convertText = Converted . TB.toLazyText . TB.decimal
{-# INLINE convertByteString #-}
convertByteString = Converted . B.pack . show
instance Convert Float where
{-# INLINE convertString #-}
convertString = Converted . show
{-# INLINE convertText #-}
convertText = Converted . TB.toLazyText . TB.realFloat
{-# INLINE convertByteString #-}
convertByteString = Converted . B.pack . show
instance Convert Double where
convertString = Converted . show
{-# INLINE convertText #-}
convertText = Converted . TB.toLazyText . TB.realFloat
{-# INLINE convertByteString #-}
convertByteString = Converted . B.pack . show
instance Convert Word where
{-# INLINE convertString #-}
convertString = Converted . show
{-# INLINE convertText #-}
convertText = Converted . TB.toLazyText . TB.decimal
{-# INLINE convertByteString #-}
convertByteString = Converted . B.pack . show
instance KnownSymbol a => Convert (Proxy a) where
{-# INLINE convertString #-}
convertString = Converted . symbolVal
{-# INLINE convertText #-}
convertText = Converted . T.pack . symbolVal
{-# INLINE convertByteString #-}
convertByteString = Converted . B.pack . symbolVal