    -- | This module provides means for reading and applying 'Template's.
    --
    -- Templates are tools to convert items into a string. They are perfectly suited
    -- for laying out your site.
    --
    -- Let's look at an example template:
    --
    -- > <html>
    -- >     <head>
    -- >         <title>My crazy homepage - $title$</title>
    -- >     </head>
    -- >     <body>
    -- >         <div id="header">
    -- >             <h1>My crazy homepage - $title$</h1>
    -- >         </div>
    -- >         <div id="content">
    -- >             $body$
    -- >         </div>
    -- >         <div id="footer">
    -- >             By reading this you agree that I now own your soul
    -- >         </div>
    -- >     </body>
    -- > </html>
    --
    -- As you can see, the format is very simple -- @$key$@ is used to render the
    -- @$key$@ field from the page, everything else is literally copied. If you want
    -- to literally insert @\"$key$\"@ into your page (for example, when you're
    -- writing a Hakyll tutorial) you can use
    --
    -- > <p>
    -- >     A literal $$key$$.
    -- > </p>
    --
    -- Because of it's simplicity, these templates can be used for more than HTML:
    -- you could make, for example, CSS or JS templates as well.
    --
    -- Apart from interpolating @$key$@s from the 'Context' you can also
    -- use the following macros:
    --
    -- * @$if(key)$@
    --
    -- > $if(key)$
    -- >  <b> Defined </b>
    -- > $else$
    -- >  <b> Non-defined </b>
    -- > $endif$
    --
    -- This example will print @Defined@ if @key@ is defined in the
    -- context and @Non-defined@ otherwise. The @$else$@ clause is
    -- optional.
    --
    -- * @$for(key)$@
    --
    -- The @for@ macro is used for enumerating 'Context' elements that are
    -- lists, i.e. constructed using the 'listField' function. Assume that
    -- in a context we have an element @listField \"key\" c itms@. Then
    -- the snippet
    --
    -- > $for(key)$
    -- >   $x$
    -- > $sep$,
    -- > $endfor$
    --
    -- would, for each item @i@ in 'itms', lookup @$x$@ in the context @c@
    -- with item @i@, interpolate it, and join the resulting list with
    -- @,@.
    --
    -- Another concrete example one may consider is the following. Given the
    -- context
    --
    -- > listField "things" (field "thing" (return . itemBody))
    -- >    (sequence [makeItem "fruits", makeItem "vegetables"])
    --
    -- and a template
    --
    -- >  I like
    -- >  $for(things)$
    -- >    fresh $thing$$sep$, and
    -- >  $endfor$
    --
    -- the resulting page would look like
    --
    -- > <p>
    -- >  I like
    -- >
    -- >   fresh fruits, and
    -- >
    -- >   fresh vegetables
    -- > </p>
    --
    -- The @$sep$@ part can be omitted. Usually, you can get by using the
    -- 'applyListTemplate' and 'applyJoinListTemplate' functions.
    --
    -- * @$partial(path)$@
    --
    -- Loads a template located in a separate file and interpolates it
    -- under the current context.
    --
    -- Assuming that the file @test.html@ contains
    --
    -- > <b>$key$</b>
    --
    -- The result of rendering
    --
    -- > <p>
    -- >   $partial("test.html")$
    -- > </p>
    --
    -- is the same as the result of rendering
    --
    -- > <p>
    -- >   <b>$key$</b>
    -- > </p>
    --
    -- That is, calling @$partial$@ is equivalent to just copying and pasting
    -- template code.
    --
    -- In the examples above you can see that the outputs contain a lot of leftover
    -- whitespace that you may wish to remove. Using @'$-'@ or @'-$'@ instead of
    -- @'$'@ in a macro strips all whitespace to the left or right of that clause
    -- respectively. Given the context
    --
    -- > listField "counts" (field "count" (return . itemBody))
    -- >    (sequence [makeItem "3", makeItem "2", makeItem "1"])
    --
    -- and a template
    --
    -- > <p>
    -- >     $for(counts)-$
    -- >       $count$
    -- >       $-sep$...
    -- >     $-endfor$
    -- > </p>
    --
    -- the resulting page would look like
    --
    -- > <p>
    -- >     3...2...1
    -- > </p>
    --
    {-# LANGUAGE TemplateHaskell #-}
    module Hakyll.Web.Template
        ( Template
        , templateBodyCompiler
        , templateCompiler
        , applyTemplate
        , loadAndApplyTemplate
        , applyAsTemplate
        , readTemplate
        , compileTemplateItem
        , unsafeReadTemplateFile
        , embedTemplate
        ) where

    --------------------------------------------------------------------------------
    import           Hakyll.Web.Template.Internal

    --------------------------------------------------------------------------------
    import           Data.FileEmbed               (embedFile)
    import qualified Data.Text                    as T
    import qualified Data.Text.Encoding           as T
    import           Language.Haskell.TH          (Exp, Q)

    --------------------------------------------------------------------------------
    -- | Embed template allows you embed a template within the Haskell binary.
    -- Example:
    --
    -- > myTemplate :: Template
    -- > myTemplate = $(embedTemplate "test.html")
    embedTemplate :: FilePath -> Q Exp
    embedTemplate :: FilePath -> Q Exp
    embedTemplate filePath :: FilePath
    filePath = [|
        let source = T.unpack $ T.decodeUtf8 $(embedFile filePath) in
        case parseTemplateElemsFile filePath source of
            Left  err -> error err
            Right tpl -> template filePath tpl |]