summaryrefslogtreecommitdiff
path: root/src/Hakyll/Web/Page/Read.hs
diff options
context:
space:
mode:
authorJasper Van der Jeugt <jaspervdj@gmail.com>2010-12-27 10:07:31 +0100
committerJasper Van der Jeugt <jaspervdj@gmail.com>2010-12-27 10:07:31 +0100
commitc1d16cdab337274a9f5aca40b887371ca1a1f5a1 (patch)
tree8023b11f53870ac46726423403d344b11bb00e8b /src/Hakyll/Web/Page/Read.hs
parent4981cfbb7f5e2630f8b41a34a8e55796283d531c (diff)
downloadhakyll-c1d16cdab337274a9f5aca40b887371ca1a1f5a1.tar.gz
Add Page parser
Diffstat (limited to 'src/Hakyll/Web/Page/Read.hs')
-rw-r--r--src/Hakyll/Web/Page/Read.hs62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/Hakyll/Web/Page/Read.hs b/src/Hakyll/Web/Page/Read.hs
new file mode 100644
index 0000000..f840eba
--- /dev/null
+++ b/src/Hakyll/Web/Page/Read.hs
@@ -0,0 +1,62 @@
+-- | Module providing a function to parse a page from a file
+--
+module Hakyll.Web.Page.Read
+ ( readPage
+ ) where
+
+import Control.Applicative ((<$>), (<*>))
+import Control.Arrow (second, (***))
+import Control.Monad.State
+import Data.List (isPrefixOf)
+import Data.Map (Map)
+import qualified Data.Map as M
+
+import Hakyll.Web.Page
+import Hakyll.Web.Util.String
+
+-- | We're using a simple state monad as parser
+--
+type LineParser = State [String]
+
+-- | Check if the given string is a metadata delimiter.
+--
+isPossibleDelimiter :: String -> Bool
+isPossibleDelimiter = isPrefixOf "---"
+
+-- | Read the metadata section from a page
+--
+parseMetadata :: LineParser (Map String String)
+parseMetadata = get >>= \content -> case content of
+ -- No lines means no metadata
+ [] -> return M.empty
+ -- Check if the file begins with a delimiter
+ (l : ls) -> if not (isPossibleDelimiter l)
+ then -- No delimiter means no body
+ return M.empty
+ else do -- Break the metadata section
+ let (metadata, rest) = second (drop 1) $ break (== l) ls
+ -- Put the rest back
+ put rest
+ -- Parse the metadata
+ return $ M.fromList $ map parseMetadata' metadata
+ where
+ parseMetadata' :: String -> (String, String)
+ parseMetadata' = (trim *** trim . drop 1) . break (== ':')
+
+-- | Read the body section of a page
+--
+parseBody :: LineParser String
+parseBody = do
+ body <- get
+ put []
+ return $ unlines body
+
+-- | Read an entire page
+--
+parsePage :: LineParser (Page String)
+parsePage = Page <$> parseMetadata <*> parseBody
+
+-- | Read a page from a string
+--
+readPage :: String -> Page String
+readPage = evalState parsePage . lines