scrod-0.2026.2.21: source/library/Scrod/Xml/Text.hs
{-# LANGUAGE TemplateHaskellQuotes #-}
module Scrod.Xml.Text where
import qualified Data.ByteString.Builder as Builder
import qualified Data.Text as Text
import qualified Scrod.Extra.Builder as Builder
import qualified Scrod.Spec as Spec
encode :: Text.Text -> Builder.Builder
encode = foldMap encodeChar . Text.unpack
encodeChar :: Char -> Builder.Builder
encodeChar c = case c of
'&' -> Builder.stringUtf8 "&"
'<' -> Builder.stringUtf8 "<"
'>' -> Builder.stringUtf8 ">"
_ -> Builder.charUtf8 c
-- | Encode for attribute values (also escapes quotes)
encodeAttr :: Text.Text -> Builder.Builder
encodeAttr = foldMap encodeAttrChar . Text.unpack
encodeAttrChar :: Char -> Builder.Builder
encodeAttrChar c = case c of
'\'' -> Builder.stringUtf8 "'"
'"' -> Builder.stringUtf8 """
_ -> encodeChar c
spec :: (Applicative m, Monad n) => Spec.Spec m n -> n ()
spec s = do
Spec.named s 'encode $ do
Spec.it s "encodes empty text" $ do
Spec.assertEq s (Builder.toString . encode $ Text.pack "") ""
Spec.it s "encodes plain text" $ do
Spec.assertEq s (Builder.toString . encode $ Text.pack "hello") "hello"
Spec.it s "encodes ampersand" $ do
Spec.assertEq s (Builder.toString . encode $ Text.pack "a & b") "a & b"
Spec.it s "encodes less-than" $ do
Spec.assertEq s (Builder.toString . encode $ Text.pack "a < b") "a < b"
Spec.it s "encodes greater-than" $ do
Spec.assertEq s (Builder.toString . encode $ Text.pack "a > b") "a > b"
Spec.named s 'encodeAttr $ do
Spec.it s "encodes single quote" $ do
Spec.assertEq s (Builder.toString . encodeAttr $ Text.pack "a ' b") "a ' b"
Spec.it s "encodes double quote" $ do
Spec.assertEq s (Builder.toString . encodeAttr $ Text.pack "a \" b") "a " b"