@@ -10,15 +10,16 @@ module Text.Hakyll.Render
1010 , css
1111 ) where
1212
13−import Text.Template hiding (render)
14−import qualified Data.ByteString.Lazy.Char8 as B
1513import qualified Data.Map as M
14+import Data.List (isPrefixOf)
1615import Control.Monad (unless, liftM, foldM)
16+import Data.Char (isAlpha)
17+import Data.Maybe (fromMaybe)
1718
1819import System.Directory (copyFile)
1920import System.IO
2021
21−import Text.Hakyll.Context (ContextManipulation)
22+import Text.Hakyll.Context (Context, ContextManipulation)
2223import Text.Hakyll.Page
2324import Text.Hakyll.Renderable
2425import Text.Hakyll.File
@@ -33,6 +34,19 @@ depends file dependencies action = do
3334 valid <- isCacheValid (toDestination file) dependencies
3435 unless valid action
3536
37+-- | Substitutes `$identifiers` in the given string by values from the given
38+-- "Context". When a key is not found, it is left as it is.
39+substitute :: String -> Context -> String
40+substitute [] _ = []
41+substitute string context
42+ | "$$" `isPrefixOf` string = "$$" ++ (substitute (tail tail') context)
43+ | "$" `isPrefixOf` string = substitute'
44+ | otherwise = (head string) : (substitute tail' context)
45+ where tail' = tail string
46+ (key, rest) = break (not . isAlpha) tail'
47+ replacement = fromMaybe ('$' : key) $ M.lookup key context
48+ substitute' = replacement ++ substitute rest context
49+
3650-- | Render to a Page.
3751render :: Renderable a
3852 => FilePath -- ^ Template to use for rendering.
@@ -49,18 +63,18 @@ renderWith :: Renderable a
4963 -> IO Page -- ^ The body of the result will contain the render.
5064renderWith manipulation templatePath renderable = do
5165 handle <- openFile templatePath ReadMode
52− templateString <- liftM B.pack $ hGetContents handle
66+ templateString <- hGetContents handle
5367 seq templateString $ hClose handle
5468 context <- liftM manipulation $ toContext renderable
5569 -- Ignore $root when substituting here. We will only replace that in the
5670 -- final render (just before writing).
57− let contextIgnoringRoot = M.insert (B.pack "root") (B.pack "$root") context
71+ let contextIgnoringRoot = M.insert "root" "$root" context
5872 body = substitute templateString contextIgnoringRoot
59− return $ fromContext (M.insert (B.pack "body") body context)
73+ return $ fromContext (M.insert "body" body context)
6074
6175-- | Render each renderable with the given template, then concatenate the
6276-- result.
63−renderAndConcat :: Renderable a => FilePath -> [a] -> IO B.ByteString
77+renderAndConcat :: Renderable a => FilePath -> [a] -> IO String
6478renderAndConcat = renderAndConcatWith id
6579
6680-- | Render each renderable with the given template, then concatenate the
@@ -70,14 +84,14 @@ renderAndConcatWith :: Renderable a
7084 => ContextManipulation
7185 -> FilePath
7286 -> [a]
73− -> IO B.ByteString
87+ -> IO String
7488renderAndConcatWith manipulation templatePath renderables =
75− foldM concatRender' B.empty renderables
76− where concatRender' :: Renderable a => B.ByteString -> a -> IO B.ByteString
89+ foldM concatRender' [] renderables
90+ where concatRender' :: Renderable a => String -> a -> IO String
7791 concatRender' chunk renderable = do
7892 rendered <- renderWith manipulation templatePath renderable
7993 let body = getBody rendered
80− return $ B.append chunk $ body
94+ return $ chunk ++ body
8195
8296-- | Chain a render action for a page with a number of templates. This will
8397-- also write the result to the site destination. This is the preferred way
@@ -100,11 +114,11 @@ writePage :: Page -> IO ()
100114writePage page = do
101115 let destination = toDestination url
102116 makeDirectories destination
103− B.writeFile destination body
117+ writeFile destination body
104118 where url = getURL page
105− -- Substitute $root here, just before writing.
106− body = substitute (getBody page)
107− (M.singleton (B.pack "root") (B.pack $ toRoot url))
119+ -- Substitute $root here, just before writing.
120+ body = substitute (getBody page)
121+ (M.singleton "root" $ toRoot url)
108122
109123-- | Mark a certain file as static, so it will just be copied when the site is
110124-- generated.