{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Text.Mustache.Type
( Template (..)
, Node (..)
, Key (..)
, showKey
, PName (..)
, MustacheException (..)
, MustacheWarning (..)
, displayMustacheWarning )
where
import Control.DeepSeq
import Control.Exception (Exception(..))
import Data.Data (Data)
import Data.Map (Map)
import Data.String (IsString (..))
import Data.Text (Text)
import Data.Typeable (Typeable, cast)
import Data.Void
import GHC.Generics
import Text.Megaparsec
import qualified Data.Map as M
import qualified Data.Text as T
import qualified Language.Haskell.TH.Syntax as TH
#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup
#endif
data Template = Template
{ templateActual :: PName
, templateCache :: Map PName [Node]
} deriving (Eq, Ord, Show, Data, Typeable, Generic)
instance Semigroup Template where
(Template pname x) <> (Template _ y) = Template pname (M.union x y)
instance TH.Lift Template where
lift = liftData
data Node
= TextBlock Text
| EscapedVar Key
| UnescapedVar Key
| Section Key [Node]
| InvertedSection Key [Node]
| Partial PName (Maybe Pos)
deriving (Eq, Ord, Show, Data, Typeable, Generic)
instance TH.Lift Node where
lift = liftData
newtype Key = Key { unKey :: [Text] }
deriving (Eq, Ord, Show, Semigroup, Monoid, Data, Typeable, Generic)
instance NFData Key
instance TH.Lift Key where
lift = liftData
showKey :: Key -> Text
showKey (Key []) = "<implicit>"
showKey (Key xs) = T.intercalate "." xs
newtype PName = PName { unPName :: Text }
deriving (Eq, Ord, Show, Data, Typeable, Generic)
instance IsString PName where
fromString = PName . T.pack
instance NFData PName
instance TH.Lift PName where
lift = liftData
newtype MustacheException
= MustacheParserException (ParseErrorBundle Text Void)
deriving (Eq, Show, Typeable, Generic)
instance Exception MustacheException where
displayException (MustacheParserException b) = errorBundlePretty b
data MustacheWarning
= MustacheVariableNotFound Key
| MustacheDirectlyRenderedValue Key
deriving (Eq, Show, Typeable, Generic)
displayMustacheWarning :: MustacheWarning -> String
displayMustacheWarning (MustacheVariableNotFound key) =
"Referenced value was not provided, key: " ++ T.unpack (showKey key)
displayMustacheWarning (MustacheDirectlyRenderedValue key) =
"Complex value rendered as such, key: " ++ T.unpack (showKey key)
liftData :: Data a => a -> TH.Q TH.Exp
liftData = TH.dataToExpQ (fmap liftText . cast)
liftText :: Text -> TH.Q TH.Exp
liftText t = TH.AppE (TH.VarE 'T.pack) <$> TH.lift (T.unpack t)