-- |
-- Utilities, which execute the parser.
module HTMLEntities.Decoder where

import qualified Data.Attoparsec.Text as P
import qualified Data.Text.Lazy.Builder as TLB
import qualified HTMLEntities.Parser as P
import HTMLEntities.Prelude

-- |
-- A decoder of a single entity.
--
-- >>> mapM_ Data.Text.IO.putStrLn $ htmlEntity "©"
-- ©
htmlEntity :: Text -> Either String Text
htmlEntity :: Text -> Either String Text
htmlEntity =
  Parser Text -> Text -> Either String Text
forall a. Parser a -> Text -> Either String a
P.parseOnly (Parser Text -> Text -> Either String Text)
-> Parser Text -> Text -> Either String Text
forall a b. (a -> b) -> a -> b
$
    Parser Text
P.htmlEntity Parser Text -> Parser Text () -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text ()
forall t. Chunk t => Parser t ()
P.endOfInput

-- |
-- A decoder of a single entity.
--
-- >>> mapM_ Data.Text.IO.putStrLn $ htmlEntityBody "#169"
-- ©
htmlEntityBody :: Text -> Either String Text
htmlEntityBody :: Text -> Either String Text
htmlEntityBody =
  Parser Text -> Text -> Either String Text
forall a. Parser a -> Text -> Either String a
P.parseOnly (Parser Text -> Text -> Either String Text)
-> Parser Text -> Text -> Either String Text
forall a b. (a -> b) -> a -> b
$
    Parser Text
P.htmlEntityBody Parser Text -> Parser Text () -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text ()
forall t. Chunk t => Parser t ()
P.endOfInput

-- |
-- A decoder of a text with entities.
--
-- Produces a text builder,
-- which you can then convert into a text or a lazy text,
-- using the <http://hackage.haskell.org/package/text "text"> or
-- <http://hackage.haskell.org/package/conversion-text "conversion-text"> library.
--
-- >>> Data.Text.Lazy.IO.putStrLn $ Data.Text.Lazy.Builder.toLazyText $ htmlEncodedText "&euro;5 &cent;2"
-- €5 ¢2
htmlEncodedText :: Text -> TLB.Builder
htmlEncodedText :: Text -> Builder
htmlEncodedText =
  (Either String Builder -> Builder)
-> (Text -> Either String Builder) -> Text -> Builder
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((String -> Builder)
-> (Builder -> Builder) -> Either String Builder -> Builder
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (String -> String -> Builder
forall a. HasCallStack => String -> a
error String
"HTMLEntities.Decoder: impossible happened") Builder -> Builder
forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id) ((Text -> Either String Builder) -> Text -> Builder)
-> (Text -> Either String Builder) -> Text -> Builder
forall a b. (a -> b) -> a -> b
$
    Parser Builder -> Text -> Either String Builder
forall a. Parser a -> Text -> Either String a
P.parseOnly (Parser Builder -> Text -> Either String Builder)
-> Parser Builder -> Text -> Either String Builder
forall a b. (a -> b) -> a -> b
$
      ([Builder] -> Builder) -> Parser Text [Builder] -> Parser Builder
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Builder] -> Builder
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold (Parser Text [Builder] -> Parser Builder)
-> Parser Text [Builder] -> Parser Builder
forall a b. (a -> b) -> a -> b
$
        Parser Builder -> Parser Text [Builder]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (Parser Builder -> Parser Text [Builder])
-> Parser Builder -> Parser Text [Builder]
forall a b. (a -> b) -> a -> b
$
          (Text -> Builder) -> Parser Text -> Parser Builder
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Builder
TLB.fromText Parser Text
P.htmlEntity Parser Builder -> Parser Builder -> Parser Builder
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Char -> Builder) -> Parser Text Char -> Parser Builder
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Char -> Builder
TLB.singleton Parser Text Char
P.anyChar