    {-# LANGUAGE DeriveAnyClass             #-}
    {-# LANGUAGE DeriveGeneric              #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE ScopedTypeVariables        #-}

    module Hakyll.Web.Template.Internal
        ( Template (..)
        , template
        , templateBodyCompiler
        , templateCompiler
        , applyTemplate
        , loadAndApplyTemplate
        , applyAsTemplate
        , readTemplate
        , compileTemplateItem
        , unsafeReadTemplateFile

        , module Hakyll.Web.Template.Internal.Element
        , module Hakyll.Web.Template.Internal.Trim
        ) where

    --------------------------------------------------------------------------------
    import           Control.Monad.Except                 (catchError)
    import           Data.Binary                          (Binary)
    import           Data.List                            (intercalate)
    import qualified Data.List.NonEmpty                   as NonEmpty
    import           Data.Typeable                        (Typeable)
    import           GHC.Exts                             (IsString (..))
    import           GHC.Generics                         (Generic)

    --------------------------------------------------------------------------------
    import           Hakyll.Core.Compiler
    import           Hakyll.Core.Compiler.Internal
    import           Hakyll.Core.Identifier
    import           Hakyll.Core.Item
    import           Hakyll.Core.Writable
    import           Hakyll.Web.Template.Context
    import           Hakyll.Web.Template.Internal.Element
    import           Hakyll.Web.Template.Internal.Trim

    --------------------------------------------------------------------------------
    -- | Datatype used for template substitutions.
    data Template = Template
        { Template -> [TemplateElement]
    tplElements :: [TemplateElement]
        , Template -> FilePath
    tplOrigin   :: FilePath  -- Only for error messages.
        } deriving (Int -> Template -> ShowS
    [Template] -> ShowS
    Template -> FilePath
    (Int -> Template -> ShowS)
    -> (Template -> FilePath) -> ([Template] -> ShowS) -> Show Template
    forall a.
    (Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Template -> ShowS
    showsPrec :: Int -> Template -> ShowS
    $cshow :: Template -> FilePath
    show :: Template -> FilePath
    $cshowList :: [Template] -> ShowS
    showList :: [Template] -> ShowS
    Show, Template -> Template -> Bool
    (Template -> Template -> Bool)
    -> (Template -> Template -> Bool) -> Eq Template
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Template -> Template -> Bool
    == :: Template -> Template -> Bool
    $c/= :: Template -> Template -> Bool
    /= :: Template -> Template -> Bool
    Eq, (forall x. Template -> Rep Template x)
    -> (forall x. Rep Template x -> Template) -> Generic Template
    forall x. Rep Template x -> Template
    forall x. Template -> Rep Template x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. Template -> Rep Template x
    from :: forall x. Template -> Rep Template x
    $cto :: forall x. Rep Template x -> Template
    to :: forall x. Rep Template x -> Template
    Generic, Get Template
    [Template] -> Put
    Template -> Put
    (Template -> Put)
    -> Get Template -> ([Template] -> Put) -> Binary Template
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    $cput :: Template -> Put
    put :: Template -> Put
    $cget :: Get Template
    get :: Get Template
    $cputList :: [Template] -> Put
    putList :: [Template] -> Put
    Binary, Typeable)

    --------------------------------------------------------------------------------
    instance Writable Template where
        -- Writing a template is impossible
        write :: FilePath -> Item Template -> IO ()
    write FilePath
    _ Item Template
    _ = () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    --------------------------------------------------------------------------------
    instance IsString Template where
        fromString :: FilePath -> Template
    fromString = FilePath -> Template
    readTemplate

    --------------------------------------------------------------------------------
    -- | Wrap the constructor to ensure trim is called.
    template :: FilePath -> [TemplateElement] -> Template
    template :: FilePath -> [TemplateElement] -> Template
    template FilePath
    p = ([TemplateElement] -> FilePath -> Template)
    -> FilePath -> [TemplateElement] -> Template
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip [TemplateElement] -> FilePath -> Template
    Template FilePath
    p ([TemplateElement] -> Template)
    -> ([TemplateElement] -> [TemplateElement])
    -> [TemplateElement]
    -> Template
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [TemplateElement] -> [TemplateElement]
    trim

    --------------------------------------------------------------------------------
    -- | Parse a string into a template.
    -- You should prefer 'compileTemplateItem' over this.
    readTemplate :: String -> Template
    readTemplate :: FilePath -> Template
    readTemplate = (FilePath -> Template)
    -> ([TemplateElement] -> Template)
    -> Either FilePath [TemplateElement]
    -> Template
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either FilePath -> Template
    forall a. HasCallStack => FilePath -> a
    error (FilePath -> [TemplateElement] -> Template
    template FilePath
    origin) (Either FilePath [TemplateElement] -> Template)
    -> (FilePath -> Either FilePath [TemplateElement])
    -> FilePath
    -> Template
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> FilePath -> Either FilePath [TemplateElement]
    parseTemplateElemsFile FilePath
    origin
      where
        origin :: FilePath
    origin = FilePath
    "{literal}"
    {-# DEPRECATED readTemplate "Use templateCompiler instead" #-}

    --------------------------------------------------------------------------------
    -- | Parse an item body into a template.
    -- Provides useful error messages in the 'Compiler' monad.
    compileTemplateItem :: Item String -> Compiler Template
    compileTemplateItem :: Item FilePath -> Compiler Template
    compileTemplateItem Item FilePath
    item = let file :: Identifier
    file = Item FilePath -> Identifier
    forall a. Item a -> Identifier
    itemIdentifier Item FilePath
    item
                               in Identifier -> FilePath -> Compiler Template
    compileTemplateFile Identifier
    file (Item FilePath -> FilePath
    forall a. Item a -> a
    itemBody Item FilePath
    item)

    --------------------------------------------------------------------------------
    compileTemplateFile :: Identifier -> String -> Compiler Template
    compileTemplateFile :: Identifier -> FilePath -> Compiler Template
    compileTemplateFile Identifier
    file = (FilePath -> Compiler Template)
    -> ([TemplateElement] -> Compiler Template)
    -> Either FilePath [TemplateElement]
    -> Compiler Template
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either FilePath -> Compiler Template
    forall a. FilePath -> Compiler a
    forall (m :: * -> *) a. MonadFail m => FilePath -> m a
    fail (Template -> Compiler Template
    forall a. a -> Compiler a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Template -> Compiler Template)
    -> ([TemplateElement] -> Template)
    -> [TemplateElement]
    -> Compiler Template
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> [TemplateElement] -> Template
    template FilePath
    origin)
                             (Either FilePath [TemplateElement] -> Compiler Template)
    -> (FilePath -> Either FilePath [TemplateElement])
    -> FilePath
    -> Compiler Template
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> FilePath -> Either FilePath [TemplateElement]
    parseTemplateElemsFile FilePath
    origin
      where
        origin :: FilePath
    origin = Identifier -> FilePath
    forall a. Show a => a -> FilePath
    show Identifier
    file

    --------------------------------------------------------------------------------
    -- | Read a template, without metadata header
    templateBodyCompiler :: Compiler (Item Template)
    templateBodyCompiler :: Compiler (Item Template)
    templateBodyCompiler = FilePath -> Compiler (Item Template) -> Compiler (Item Template)
    forall a.
    (Binary a, Typeable a) =>
    FilePath -> Compiler a -> Compiler a
    cached FilePath
    "Hakyll.Web.Template.templateBodyCompiler" (Compiler (Item Template) -> Compiler (Item Template))
    -> Compiler (Item Template) -> Compiler (Item Template)
    forall a b. (a -> b) -> a -> b
    $ do
        Item FilePath
    item <- Compiler (Item FilePath)
    getResourceBody
        Identifier
    file <- Compiler Identifier
    getUnderlying
        (FilePath -> Compiler Template)
    -> Item FilePath -> Compiler (Item Template)
    forall a b. (a -> Compiler b) -> Item a -> Compiler (Item b)
    withItemBody (Identifier -> FilePath -> Compiler Template
    compileTemplateFile Identifier
    file) Item FilePath
    item

    --------------------------------------------------------------------------------
    -- | Read complete file contents as a template
    templateCompiler :: Compiler (Item Template)
    templateCompiler :: Compiler (Item Template)
    templateCompiler = FilePath -> Compiler (Item Template) -> Compiler (Item Template)
    forall a.
    (Binary a, Typeable a) =>
    FilePath -> Compiler a -> Compiler a
    cached FilePath
    "Hakyll.Web.Template.templateCompiler" (Compiler (Item Template) -> Compiler (Item Template))
    -> Compiler (Item Template) -> Compiler (Item Template)
    forall a b. (a -> b) -> a -> b
    $ do
        Item FilePath
    item <- Compiler (Item FilePath)
    getResourceString
        Identifier
    file <- Compiler Identifier
    getUnderlying
        (FilePath -> Compiler Template)
    -> Item FilePath -> Compiler (Item Template)
    forall a b. (a -> Compiler b) -> Item a -> Compiler (Item b)
    withItemBody (Identifier -> FilePath -> Compiler Template
    compileTemplateFile Identifier
    file) Item FilePath
    item

    --------------------------------------------------------------------------------
    -- | Interpolate template expressions from context values in a page
    applyTemplate :: Template                -- ^ Template
                  -> Context a               -- ^ Context
                  -> Item a                  -- ^ Page
                  -> Compiler (Item String)  -- ^ Resulting item
    applyTemplate :: forall a.
    Template -> Context a -> Item a -> Compiler (Item FilePath)
    applyTemplate Template
    tpl Context a
    context Item a
    item = do
        FilePath
    body <- [TemplateElement] -> Context a -> Item a -> Compiler FilePath
    forall a.
    [TemplateElement] -> Context a -> Item a -> Compiler FilePath
    applyTemplate' (Template -> [TemplateElement]
    tplElements Template
    tpl) Context a
    context Item a
    item Compiler FilePath
    -> ([FilePath] -> Compiler FilePath) -> Compiler FilePath
    forall a. Compiler a -> ([FilePath] -> Compiler a) -> Compiler a
    forall e (m :: * -> *) a.
    MonadError e m =>
    m a -> (e -> m a) -> m a
    `catchError` [FilePath] -> Compiler FilePath
    forall {m :: * -> *} {a}. MonadFail m => [FilePath] -> m a
    handler
        Item FilePath -> Compiler (Item FilePath)
    forall a. a -> Compiler a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Item FilePath -> Compiler (Item FilePath))
    -> Item FilePath -> Compiler (Item FilePath)
    forall a b. (a -> b) -> a -> b
    $ FilePath -> Item a -> Item FilePath
    forall a b. a -> Item b -> Item a
    itemSetBody FilePath
    body Item a
    item
      where
        tplName :: FilePath
    tplName = Template -> FilePath
    tplOrigin Template
    tpl
        itemName :: FilePath
    itemName = Identifier -> FilePath
    forall a. Show a => a -> FilePath
    show (Identifier -> FilePath) -> Identifier -> FilePath
    forall a b. (a -> b) -> a -> b
    $ Item a -> Identifier
    forall a. Item a -> Identifier
    itemIdentifier Item a
    item
        handler :: [FilePath] -> m a
    handler [FilePath]
    es = FilePath -> m a
    forall a. FilePath -> m a
    forall (m :: * -> *) a. MonadFail m => FilePath -> m a
    fail (FilePath -> m a) -> FilePath -> m a
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "Hakyll.Web.Template.applyTemplate: Failed to " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++
            (if FilePath
    tplName FilePath -> FilePath -> Bool
    forall a. Eq a => a -> a -> Bool
    == FilePath
    itemName
              then FilePath
    "interpolate template in item " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    itemName
              else FilePath
    "apply template " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    tplName FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    " to item " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    itemName) FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++
            FilePath
    ":\n" FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath -> [FilePath] -> FilePath
    forall a. [a] -> [[a]] -> [a]
    intercalate FilePath
    ",\n" [FilePath]
    es

    --------------------------------------------------------------------------------
    applyTemplate'
        :: forall a.
           [TemplateElement] -- ^ Unwrapped Template
        -> Context a         -- ^ Context
        -> Item a            -- ^ Page
        -> Compiler String   -- ^ Resulting item
    applyTemplate' :: forall a.
    [TemplateElement] -> Context a -> Item a -> Compiler FilePath
    applyTemplate' [TemplateElement]
    tes Context a
    context Item a
    x = [TemplateElement] -> Compiler FilePath
    go [TemplateElement]
    tes
      where
        context' :: String -> [String] -> Item a -> Compiler ContextField
        context' :: FilePath -> [FilePath] -> Item a -> Compiler ContextField
    context' = Context a
    -> FilePath -> [FilePath] -> Item a -> Compiler ContextField
    forall a.
    Context a
    -> FilePath -> [FilePath] -> Item a -> Compiler ContextField
    unContext (Context a
    context Context a -> Context a -> Context a
    forall a. Monoid a => a -> a -> a
    `mappend` Context a
    forall a. Context a
    missingField)

        go :: [TemplateElement] -> Compiler FilePath
    go = ([FilePath] -> FilePath)
    -> Compiler [FilePath] -> Compiler FilePath
    forall a b. (a -> b) -> Compiler a -> Compiler b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap [FilePath] -> FilePath
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat (Compiler [FilePath] -> Compiler FilePath)
    -> ([TemplateElement] -> Compiler [FilePath])
    -> [TemplateElement]
    -> Compiler FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (TemplateElement -> Compiler FilePath)
    -> [TemplateElement] -> Compiler [FilePath]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM TemplateElement -> Compiler FilePath
    applyElem

        ---------------------------------------------------------------------------

        applyElem :: TemplateElement -> Compiler String

        applyElem :: TemplateElement -> Compiler FilePath
    applyElem TemplateElement
    TrimL = Compiler FilePath
    forall {a}. Compiler a
    trimError

        applyElem TemplateElement
    TrimR = Compiler FilePath
    forall {a}. Compiler a
    trimError

        applyElem (Chunk FilePath
    c) = FilePath -> Compiler FilePath
    forall a. a -> Compiler a
    forall (m :: * -> *) a. Monad m => a -> m a
    return FilePath
    c

        applyElem (Expr TemplateExpr
    e) = FilePath -> Compiler FilePath -> Compiler FilePath
    forall a. FilePath -> Compiler a -> Compiler a
    withErrorMessage FilePath
    evalMsg (FilePath -> TemplateExpr -> Compiler FilePath
    applyStringExpr FilePath
    typeMsg TemplateExpr
    e)
          where
            evalMsg :: FilePath
    evalMsg = FilePath
    "In expr '$" FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ TemplateExpr -> FilePath
    forall a. Show a => a -> FilePath
    show TemplateExpr
    e FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    "$'"
            typeMsg :: FilePath
    typeMsg = FilePath
    "expr '$" FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ TemplateExpr -> FilePath
    forall a. Show a => a -> FilePath
    show TemplateExpr
    e FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    "$'"

        applyElem TemplateElement
    Escaped = FilePath -> Compiler FilePath
    forall a. a -> Compiler a
    forall (m :: * -> *) a. Monad m => a -> m a
    return FilePath
    "$"

        applyElem (If TemplateExpr
    e [TemplateElement]
    t Maybe [TemplateElement]
    mf) = Compiler ContextField
    -> Compiler (Either (CompilerErrors FilePath) ContextField)
    forall a.
    Compiler a -> Compiler (Either (CompilerErrors FilePath) a)
    compilerTry (TemplateExpr -> Compiler ContextField
    applyExpr TemplateExpr
    e) Compiler (Either (CompilerErrors FilePath) ContextField)
    -> (Either (CompilerErrors FilePath) ContextField
        -> Compiler FilePath)
    -> Compiler FilePath
    forall a b. Compiler a -> (a -> Compiler b) -> Compiler b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Either (CompilerErrors FilePath) ContextField -> Compiler FilePath
    forall {b}. Either (CompilerErrors FilePath) b -> Compiler FilePath
    handle
          where
            f :: Compiler FilePath
    f = Compiler FilePath
    -> ([TemplateElement] -> Compiler FilePath)
    -> Maybe [TemplateElement]
    -> Compiler FilePath
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (FilePath -> Compiler FilePath
    forall a. a -> Compiler a
    forall (m :: * -> *) a. Monad m => a -> m a
    return FilePath
    "") [TemplateElement] -> Compiler FilePath
    go Maybe [TemplateElement]
    mf
            handle :: Either (CompilerErrors FilePath) b -> Compiler FilePath
    handle (Right b
    _)                      = [TemplateElement] -> Compiler FilePath
    go [TemplateElement]
    t
            handle (Left (CompilationNoResult [FilePath]
    _)) = Compiler FilePath
    f
            handle (Left (CompilationFailure NonEmpty FilePath
    es)) = [FilePath] -> Compiler ()
    debug (NonEmpty FilePath -> [FilePath]
    forall a. NonEmpty a -> [a]
    NonEmpty.toList NonEmpty FilePath
    es) Compiler () -> Compiler FilePath -> Compiler FilePath
    forall a b. Compiler a -> Compiler b -> Compiler b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Compiler FilePath
    f
            debug :: [FilePath] -> Compiler ()
    debug = FilePath -> [FilePath] -> Compiler ()
    compilerDebugEntries (FilePath
    "Hakyll.Web.Template.applyTemplate: " FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++
                FilePath
    "[ERROR] in 'if' condition on expr '" FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ TemplateExpr -> FilePath
    forall a. Show a => a -> FilePath
    show TemplateExpr
    e FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    "':")

        applyElem (For TemplateExpr
    e [TemplateElement]
    b Maybe [TemplateElement]
    s) = FilePath -> Compiler ContextField -> Compiler ContextField
    forall a. FilePath -> Compiler a -> Compiler a
    withErrorMessage FilePath
    headMsg (TemplateExpr -> Compiler ContextField
    applyExpr TemplateExpr
    e) Compiler ContextField
    -> (ContextField -> Compiler FilePath) -> Compiler FilePath
    forall a b. Compiler a -> (a -> Compiler b) -> Compiler b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \ContextField
    cf -> case ContextField
    cf of
            ContextField
    EmptyField     -> FilePath -> FilePath -> FilePath -> Compiler FilePath
    forall {m :: * -> *} {a}.
    MonadFail m =>
    FilePath -> FilePath -> FilePath -> m a
    expected FilePath
    "list" FilePath
    "boolean" FilePath
    typeMsg
            StringField FilePath
    _  -> FilePath -> FilePath -> FilePath -> Compiler FilePath
    forall {m :: * -> *} {a}.
    MonadFail m =>
    FilePath -> FilePath -> FilePath -> m a
    expected FilePath
    "list" FilePath
    "string" FilePath
    typeMsg
            ListField Context a
    c [Item a]
    xs -> FilePath -> Compiler FilePath -> Compiler FilePath
    forall a. FilePath -> Compiler a -> Compiler a
    withErrorMessage FilePath
    bodyMsg (Compiler FilePath -> Compiler FilePath)
    -> Compiler FilePath -> Compiler FilePath
    forall a b. (a -> b) -> a -> b
    $ do
                FilePath
    sep <- Compiler FilePath
    -> ([TemplateElement] -> Compiler FilePath)
    -> Maybe [TemplateElement]
    -> Compiler FilePath
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (FilePath -> Compiler FilePath
    forall a. a -> Compiler a
    forall (m :: * -> *) a. Monad m => a -> m a
    return FilePath
    "") [TemplateElement] -> Compiler FilePath
    go Maybe [TemplateElement]
    s
                [FilePath]
    bs  <- (Item a -> Compiler FilePath) -> [Item a] -> Compiler [FilePath]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM ([TemplateElement] -> Context a -> Item a -> Compiler FilePath
    forall a.
    [TemplateElement] -> Context a -> Item a -> Compiler FilePath
    applyTemplate' [TemplateElement]
    b Context a
    c) [Item a]
    xs
                FilePath -> Compiler FilePath
    forall a. a -> Compiler a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (FilePath -> Compiler FilePath) -> FilePath -> Compiler FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath -> [FilePath] -> FilePath
    forall a. [a] -> [[a]] -> [a]
    intercalate FilePath
    sep [FilePath]
    bs
          where
            headMsg :: FilePath
    headMsg = FilePath
    "In expr '$for(" FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ TemplateExpr -> FilePath
    forall a. Show a => a -> FilePath
    show TemplateExpr
    e FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    ")$'"
            typeMsg :: FilePath
    typeMsg = FilePath
    "loop expr '" FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ TemplateExpr -> FilePath
    forall a. Show a => a -> FilePath
    show TemplateExpr
    e FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    "'"
            bodyMsg :: FilePath
    bodyMsg = FilePath
    "In loop context of '$for(" FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ TemplateExpr -> FilePath
    forall a. Show a => a -> FilePath
    show TemplateExpr
    e FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    ")$'"

        applyElem (Partial TemplateExpr
    e) = FilePath -> Compiler FilePath -> Compiler FilePath
    forall a. FilePath -> Compiler a -> Compiler a
    withErrorMessage FilePath
    headMsg (Compiler FilePath -> Compiler FilePath)
    -> Compiler FilePath -> Compiler FilePath
    forall a b. (a -> b) -> a -> b
    $
            FilePath -> TemplateExpr -> Compiler FilePath
    applyStringExpr FilePath
    typeMsg TemplateExpr
    e Compiler FilePath
    -> (FilePath -> Compiler FilePath) -> Compiler FilePath
    forall a b. Compiler a -> (a -> Compiler b) -> Compiler b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \FilePath
    p ->
            FilePath -> Compiler FilePath -> Compiler FilePath
    forall a. FilePath -> Compiler a -> Compiler a
    withErrorMessage FilePath
    inclMsg (Compiler FilePath -> Compiler FilePath)
    -> Compiler FilePath -> Compiler FilePath
    forall a b. (a -> b) -> a -> b
    $ do
                Template
    tpl' <- Identifier -> Compiler Template
    forall a. (Binary a, Typeable a) => Identifier -> Compiler a
    loadBody (FilePath -> Identifier
    fromFilePath FilePath
    p)
                Item FilePath -> FilePath
    forall a. Item a -> a
    itemBody (Item FilePath -> FilePath)
    -> Compiler (Item FilePath) -> Compiler FilePath
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Template -> Context a -> Item a -> Compiler (Item FilePath)
    forall a.
    Template -> Context a -> Item a -> Compiler (Item FilePath)
    applyTemplate Template
    tpl' Context a
    context Item a
    x
          where
            headMsg :: FilePath
    headMsg = FilePath
    "In expr '$partial(" FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ TemplateExpr -> FilePath
    forall a. Show a => a -> FilePath
    show TemplateExpr
    e FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    ")$'"
            typeMsg :: FilePath
    typeMsg = FilePath
    "partial expr '" FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ TemplateExpr -> FilePath
    forall a. Show a => a -> FilePath
    show TemplateExpr
    e FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    "'"
            inclMsg :: FilePath
    inclMsg = FilePath
    "In inclusion of '$partial(" FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ TemplateExpr -> FilePath
    forall a. Show a => a -> FilePath
    show TemplateExpr
    e FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    ")$'"

        ---------------------------------------------------------------------------

        applyExpr :: TemplateExpr -> Compiler ContextField

        applyExpr :: TemplateExpr -> Compiler ContextField
    applyExpr (Ident (TemplateKey FilePath
    k)) = FilePath -> [FilePath] -> Item a -> Compiler ContextField
    context' FilePath
    k [] Item a
    x

        applyExpr (Call (TemplateKey FilePath
    k) [TemplateExpr]
    args) = do
            [FilePath]
    args' <- (TemplateExpr -> Compiler FilePath)
    -> [TemplateExpr] -> Compiler [FilePath]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM (\TemplateExpr
    e -> FilePath -> TemplateExpr -> Compiler FilePath
    applyStringExpr (TemplateExpr -> FilePath
    forall a. Show a => a -> FilePath
    typeMsg TemplateExpr
    e) TemplateExpr
    e) [TemplateExpr]
    args
            FilePath -> [FilePath] -> Item a -> Compiler ContextField
    context' FilePath
    k [FilePath]
    args' Item a
    x
          where
            typeMsg :: a -> FilePath
    typeMsg a
    e = FilePath
    "argument '" FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ a -> FilePath
    forall a. Show a => a -> FilePath
    show a
    e FilePath -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    "'"

        applyExpr (StringLiteral FilePath
    s) = ContextField -> Compiler ContextField
    forall a. a -> Compiler a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (FilePath -> ContextField
    StringField FilePath
    s)

        ----------------------------------------------------------------------------

        applyStringExpr :: String -> TemplateExpr -> Compiler String
        applyStringExpr :: FilePath -> TemplateExpr -> Compiler FilePath
    applyStringExpr FilePath
    msg TemplateExpr
    expr =
            TemplateExpr -> Compiler ContextField
    applyExpr TemplateExpr
    expr Compiler ContextField
    -> (ContextField -> Compiler FilePath) -> Compiler FilePath
    forall a b. Compiler a -> (a -> Compiler b) -> Compiler b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= ContextField -> Compiler FilePath
    forall {m :: * -> *}. MonadFail m => ContextField -> m FilePath
    getString
          where
            getString :: ContextField -> m FilePath
    getString ContextField
    EmptyField      = FilePath -> FilePath -> FilePath -> m FilePath
    forall {m :: * -> *} {a}.
    MonadFail m =>
    FilePath -> FilePath -> FilePath -> m a
    expected FilePath
    "string" FilePath
    "boolean" FilePath
    msg
            getString (StringField FilePath
    s) = FilePath -> m FilePath
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return FilePath
    s
            getString (ListField Context a
    _ [Item a]
    _) = FilePath -> FilePath -> FilePath -> m FilePath
    forall {m :: * -> *} {a}.
    MonadFail m =>
    FilePath -> FilePath -> FilePath -> m a
    expected FilePath
    "string" FilePath
    "list" FilePath
    msg

        expected :: FilePath -> FilePath -> FilePath -> m a
    expected FilePath
    typ FilePath
    act FilePath
    expr = FilePath -> m a
    forall a. FilePath -> m a
    forall (m :: * -> *) a. MonadFail m => FilePath -> m a
    fail (FilePath -> m a) -> FilePath -> m a
    forall a b. (a -> b) -> a -> b
    $ [FilePath] -> FilePath
    unwords [FilePath
    "Hakyll.Web.Template.applyTemplate:",
            FilePath
    "expected", FilePath
    typ, FilePath
    "but got", FilePath
    act, FilePath
    "for", FilePath
    expr]

        -- expected to never happen with all templates constructed by 'template'
        trimError :: Compiler a
    trimError = FilePath -> Compiler a
    forall a. FilePath -> Compiler a
    forall (m :: * -> *) a. MonadFail m => FilePath -> m a
    fail (FilePath -> Compiler a) -> FilePath -> Compiler a
    forall a b. (a -> b) -> a -> b
    $
            FilePath
    "Hakyll.Web.Template.applyTemplate: template not fully trimmed."

    --------------------------------------------------------------------------------
    -- | The following pattern is so common:
    --
    -- > tpl <- loadBody "templates/foo.html"
    -- > someCompiler
    -- >     >>= applyTemplate tpl context
    --
    -- That we have a single function which does this:
    --
    -- > someCompiler
    -- >     >>= loadAndApplyTemplate "templates/foo.html" context
    loadAndApplyTemplate :: Identifier              -- ^ Template identifier
                         -> Context a               -- ^ Context
                         -> Item a                  -- ^ Page
                         -> Compiler (Item String)  -- ^ Resulting item
    loadAndApplyTemplate :: forall a.
    Identifier -> Context a -> Item a -> Compiler (Item FilePath)
    loadAndApplyTemplate Identifier
    identifier Context a
    context Item a
    item = do
        Template
    tpl <- Identifier -> Compiler Template
    forall a. (Binary a, Typeable a) => Identifier -> Compiler a
    loadBody Identifier
    identifier
        Template -> Context a -> Item a -> Compiler (Item FilePath)
    forall a.
    Template -> Context a -> Item a -> Compiler (Item FilePath)
    applyTemplate Template
    tpl Context a
    context Item a
    item

    --------------------------------------------------------------------------------
    -- | It is also possible that you want to substitute @$key$@s within the body of
    -- an item. This function does that by interpreting the item body as a template,
    -- and then applying it to itself.
    applyAsTemplate :: Context String          -- ^ Context
                    -> Item String             -- ^ Item and template
                    -> Compiler (Item String)  -- ^ Resulting item
    applyAsTemplate :: Context FilePath -> Item FilePath -> Compiler (Item FilePath)
    applyAsTemplate Context FilePath
    context Item FilePath
    item = do
        Template
    tpl <- Item FilePath -> Compiler Template
    compileTemplateItem Item FilePath
    item
        Template
    -> Context FilePath -> Item FilePath -> Compiler (Item FilePath)
    forall a.
    Template -> Context a -> Item a -> Compiler (Item FilePath)
    applyTemplate Template
    tpl Context FilePath
    context Item FilePath
    item

    --------------------------------------------------------------------------------
    unsafeReadTemplateFile :: FilePath -> Compiler Template
    unsafeReadTemplateFile :: FilePath -> Compiler Template
    unsafeReadTemplateFile FilePath
    file = do
        FilePath
    tpl <- IO FilePath -> Compiler FilePath
    forall a. IO a -> Compiler a
    unsafeCompiler (IO FilePath -> Compiler FilePath)
    -> IO FilePath -> Compiler FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath -> IO FilePath
    readFile FilePath
    file
        Identifier -> FilePath -> Compiler Template
    compileTemplateFile (FilePath -> Identifier
    fromFilePath FilePath
    file) FilePath
    tpl
    {-# DEPRECATED unsafeReadTemplateFile "Use templateCompiler" #-}