@@ -14,6 +14,7 @@ import qualified Data.Map as M
1414import qualified Data.List as L
1515import qualified Data.ByteString.Lazy.Char8 as B
1616import Data.Maybe
17+import Control.Monad
1718
1819import System.FilePath
1920import System.IO
@@ -67,11 +68,30 @@ readMetaData handle = do
6768isDelimiter :: String -> Bool
6869isDelimiter = L.isPrefixOf "---"
6970
71+-- | Used for caching of files.
72+cachePage :: Page -> IO ()
73+cachePage page = do
74+ let destination = toCache $ getURL page
75+ makeDirectories destination
76+ handle <- openFile destination WriteMode
77+ hPutStrLn handle "---"
78+ mapM_ (writePair handle) $ M.toList page
79+ hPutStrLn handle "---"
80+ B.hPut handle $ getBody page
81+ hClose handle
82+ where writePair _ ("body", _) = return ()
83+ writePair h (k, v) = hPutStr h (k ++ ": ") >> B.hPut h v >> hPutStrLn h ""
84+
7085-- | Read a page from a file. Metadata is supported, and if the filename
7186-- has a .markdown extension, it will be rendered using pandoc. Note that
7287-- pages are not templates, so they should not contain $identifiers.
7388readPage :: FilePath -> IO Page
74−readPage path = do
89+readPage pagePath = do
90+ -- Check cache.
91+ getFromCache <- isCacheFileValid cacheFile pagePath
92+ let path = if getFromCache then cacheFile else pagePath
93+
94+ -- Read file.
7595 handle <- openFile path ReadMode
7696 line <- hGetLine handle
7797 (context, body) <- if isDelimiter line
@@ -80,10 +100,16 @@ readPage path = do
80100 return (md, c)
81101 else hGetContents handle >>= \b -> return ([], line ++ b)
82102
103+ -- Render file
83104 let rendered = B.pack $ (renderFunction $ takeExtension path) body
84− url = addExtension (dropExtension path) ".html"
85105 seq rendered $ hClose handle
86− return $ M.insert "body" rendered $ addContext "url" url $ pageFromList context
106+ let page = M.insert "body" rendered $ addContext "url" url $ pageFromList context
107+
108+ -- Cache if needed
109+ if getFromCache then return () else cachePage page
110+ return page
111+ where url = addExtension (dropExtension pagePath) ".html"
112+ cacheFile = toCache url
87113
88114-- | Create a key-value mapping page from an association list.
89115pageFromList :: [(String, String)] -> Page