@@ -14,6 +14,7 @@ import qualified Data.Map as M
14import qualified Data.List as L
14import qualified Data.List as L
15import qualified Data.ByteString.Lazy.Char8 as B
15import qualified Data.ByteString.Lazy.Char8 as B
16import Data.Maybe
16import Data.Maybe
18import System.FilePath
19import System.FilePath
19import System.IO
20import System.IO
@@ -67,11 +68,30 @@ readMetaData handle = do
67isDelimiter :: String -> Bool
68isDelimiter :: String -> Bool
68isDelimiter = L.isPrefixOf "---"
69isDelimiter = L.isPrefixOf "---"
71+-- | Used for caching of files.
72+cachePage :: Page -> IO ()
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
82+ where writePair _ ("body", _) = return ()
83+ writePair h (k, v) = hPutStr h (k ++ ": ") >> B.hPut h v >> hPutStrLn h ""
70-- | Read a page from a file. Metadata is supported, and if the filename
85-- | Read a page from a file. Metadata is supported, and if the filename
71-- has a .markdown extension, it will be rendered using pandoc. Note that
86-- has a .markdown extension, it will be rendered using pandoc. Note that
72-- pages are not templates, so they should not contain $identifiers.
87-- pages are not templates, so they should not contain $identifiers.
73readPage :: FilePath -> IO Page
88readPage :: FilePath -> IO Page
74−readPage path = do
89+readPage pagePath = do
91+ getFromCache <- isCacheFileValid cacheFile pagePath
92+ let path = if getFromCache then cacheFile else pagePath
75 handle <- openFile path ReadMode
95 handle <- openFile path ReadMode
76 line <- hGetLine handle
96 line <- hGetLine handle
77 (context, body) <- if isDelimiter line
97 (context, body) <- if isDelimiter line
@@ -80,10 +100,16 @@ readPage path = do
80 return (md, c)
100 return (md, c)
81 else hGetContents handle >>= \b -> return ([], line ++ b)
101 else hGetContents handle >>= \b -> return ([], line ++ b)
83 let rendered = B.pack $ (renderFunction $ takeExtension path) body
104 let rendered = B.pack $ (renderFunction $ takeExtension path) body
84− url = addExtension (dropExtension path) ".html"
85 seq rendered $ hClose handle
105 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
109+ if getFromCache then return () else cachePage page
111+ where url = addExtension (dropExtension pagePath) ".html"
112+ cacheFile = toCache url
88-- | Create a key-value mapping page from an association list.
114-- | Create a key-value mapping page from an association list.
89pageFromList :: [(String, String)] -> Page
115pageFromList :: [(String, String)] -> Page