on master help sign in
Allow ... as metadata delimiter
commit308323bfc1e7da4b88cd83c6db265e709bec3f2c authorJasper Van der Jeugt <jaspervdj@gmail.com> dateMon 18 Jul 2011, 18:47 (15 years ago) parent0341108
3 files changed+50−45
hakyll.cabal+1 src/Hakyll/Web/Page/Read.hs+38−42 tests/Hakyll/Web/Page/Tests.hs+11−3
hakyll.cabal+1
@@ -68,6 +68,7 @@ Library
6868 old-locale >= 1.0 && < 2.0,
6969 old-time >= 1.0 && < 1.3,
7070 pandoc >= 1.6 && < 2.0,
71+ parsec >= 2.1 && < 3.2,
7172 process >= 1.0 && < 1.4,
7273 regex-base >= 0.93 && < 1.0,
7374 regex-pcre >= 0.93 && < 1.0,
src/Hakyll/Web/Page/Read.hs+38−42
@@ -4,57 +4,53 @@ module Hakyll.Web.Page.Read
44 ( readPage
55 ) where
66
7−import Control.Applicative ((<$>), (<*>))
8−import Control.Arrow (second, (***))
9−import Control.Monad.State (State, get, put, evalState)
10−import Data.List (isPrefixOf)
11−import Data.Map (Map)
7+import Control.Applicative ((<$>), (<*>), (<*))
128import qualified Data.Map as M
139
14−import Hakyll.Web.Page.Internal
10+import Text.Parsec.Char (alphaNum, anyChar, char, newline, oneOf, string)
11+import Text.Parsec.Combinator (choice, many1, manyTill, option, skipMany1)
12+import Text.Parsec.Prim (many, parse, skipMany, (<?>))
13+import Text.Parsec.String (Parser)
14+
1515import Hakyll.Core.Util.String
16+import Hakyll.Web.Page.Internal
1617
17−-- | We're using a simple state monad as parser
18−--
19−type LineParser = State [String]
18+-- | Space or tab, no newline
19+inlineSpace :: Parser Char
20+inlineSpace = oneOf ['\t', ' '] <?> "space"
2021
21−-- | Read the metadata section from a page
22+-- | Parse a single metadata field
2223--
23−parseMetadata :: LineParser (Map String String)
24−parseMetadata = get >>= \content -> case content of
25− -- No lines means no metadata
26− [] -> return M.empty
27− -- Check if the file begins with a delimiter
28− (l : ls) -> if not (isPossibleDelimiter l)
29− then -- No delimiter means no metadata
30− return M.empty
31− else do -- Break the metadata section
32− let (metadata, rest) = second (drop 1) $ break (== l) ls
33− -- Put the rest back
34− put rest
35− -- Parse the metadata
36− return $ M.fromList $ map parseMetadata' metadata
24+metadataField :: Parser (String, String)
25+metadataField = do
26+ key <- manyTill alphaNum $ char ':'
27+ skipMany1 inlineSpace
28+ value <- manyTill anyChar newline
29+ trailing' <- many trailing
30+ return (key, trim $ value ++ concat trailing')
3731 where
38− -- Check if a line can be a delimiter
39− isPossibleDelimiter = isPrefixOf "---"
32+ trailing = (++) <$> many1 inlineSpace <*> manyTill anyChar newline
4033
41− -- Parse a "key: value" string to a (key, value) tupple
42− parseMetadata' = (trim *** trim . drop 1) . break (== ':')
43−
44−-- | Read the body section of a page
34+-- | Parse a metadata block, including delimiters and trailing newlines
4535--
46−parseBody :: LineParser String
47−parseBody = do
48− body <- get
49− put []
50− return $ unlines body
51−
52−-- | Read an entire page
36+metadata :: Parser [(String, String)]
37+metadata = do
38+ open <- many1 (char '-') <* many inlineSpace <* newline
39+ metadata' <- many metadataField
40+ _ <- choice $ map (string . replicate (length open)) ['-', '.']
41+ skipMany inlineSpace
42+ skipMany1 newline
43+ return metadata'
44+
45+-- | Parse a Hakyll page
5346--
54−parsePage :: LineParser (Page String)
55−parsePage = Page <$> parseMetadata <*> parseBody
47+page :: Parser ([(String, String)], String)
48+page = do
49+ metadata' <- option [] metadata
50+ body <- many anyChar
51+ return (metadata', body)
5652
57−-- | Read a page from a string
58−--
5953readPage :: String -> Page String
60−readPage = evalState parsePage . lines
54+readPage input = case parse page "page" input of
55+ Left err -> error (show err)
56+ Right (md, b) -> Page (M.fromList md) b
tests/Hakyll/Web/Page/Tests.hs+11−3
@@ -14,13 +14,13 @@ import TestSuite.Util
1414
1515tests :: [Test]
1616tests = fromAssertions "readPage"
17− [ Page (M.singleton "foo" "bar") "body\n" @=? readPage
17+ [ Page (M.singleton "foo" "bar") "body" @=? readPage
1818 "--- \n\
1919 \foo: bar \n\
2020 \--- \n\
2121 \body"
2222
23− , Page M.empty "line one\nlijn twee\n" @=? readPage
23+ , Page M.empty "line one\nlijn twee" @=? readPage
2424 "line one\n\
2525 \lijn twee"
2626
@@ -28,5 +28,13 @@ tests = fromAssertions "readPage"
2828 "---\n\
2929 \veld02: deux\n\
3030 \field1: unos\n\
31− \---"
31+ \---\n"
32+
33+ , Page (M.fromList [("author", "jasper"), ("title", "lol")]) "O hai\n"
34+ @=? readPage
35+ "---\n\
36+ \author: jasper\n\
37+ \title: lol\n\
38+ \...\n\
39+ \O hai\n"
3240 ]