module Text.Hakyll.Render.Internal
( substitute
, regularSubstitute
, finalSubstitute
, pureRenderWith
, pureRenderAndConcatWith
, pureRenderChainWith
, writePage
) where
import qualified Data.Map as M
import Text.Hakyll.Context (Context, ContextManipulation)
import Control.Monad.Reader (liftIO)
import Data.List (isPrefixOf, foldl')
import Data.Char (isAlphaNum)
import Data.Maybe (fromMaybe)
import Control.Parallel.Strategies (rdeepseq, ($|))
import Text.Hakyll.Renderable
import Text.Hakyll.Page
import Text.Hakyll.File
import Text.Hakyll.Hakyll
substitute :: String -> String -> Context -> String
substitute _ [] _ = []
substitute escaper string context
| "$$" `isPrefixOf` string = escaper ++ substitute' (tail tail')
| "$" `isPrefixOf` string = substituteKey
| otherwise = head string : substitute' tail'
where
tail' = tail string
(key, rest) = span isAlphaNum tail'
replacement = fromMaybe ('$' : key) $ M.lookup key context
substituteKey = replacement ++ substitute' rest
substitute' str = substitute escaper str context
regularSubstitute :: String -> Context -> String
regularSubstitute = substitute "$$"
finalSubstitute :: String -> Context -> String
finalSubstitute = substitute "$"
pureRenderWith :: ContextManipulation
-> String
-> Context
-> Context
pureRenderWith manipulation template context =
let contextIgnoringRoot = M.insert "root" "$root" (manipulation context)
body = regularSubstitute template contextIgnoringRoot
in ($|) id rdeepseq (M.insert "body" body context)
pureRenderAndConcatWith :: ContextManipulation
-> [String]
-> [Context]
-> String
pureRenderAndConcatWith manipulation templates contexts =
foldl' renderAndConcat [] contexts
where
renderAndConcat chunk context =
let rendered = pureRenderChainWith manipulation templates context
in chunk ++ fromMaybe "" (M.lookup "body" rendered)
pureRenderChainWith :: ContextManipulation
-> [String]
-> Context
-> Context
pureRenderChainWith manipulation templates context =
let initial = manipulation context
in foldl' (flip $ pureRenderWith id) initial templates
writePage :: Page -> Hakyll ()
writePage page = do
additionalContext' <- askHakyll additionalContext
let destination = toDestination url
context = additionalContext' `M.union` M.singleton "root" (toRoot url)
makeDirectories destination
liftIO $ writeFile destination $ finalSubstitute (getBody page) context
where
url = getURL page