@@ -4,38 +4,56 @@ module Hakyll.Web.Template.Read
4 ( readTemplate
4 ( readTemplate
8--------------------------------------------------------------------------------
7--------------------------------------------------------------------------------
9−import Data.List (isPrefixOf)
8+import Control.Applicative ((<$>), (<$), (<*>))
10−
9+import Control.Monad (void, mzero, guard)
11+import Text.Parsec.String
12--------------------------------------------------------------------------------
13--------------------------------------------------------------------------------
13import Hakyll.Web.Template.Internal
14import Hakyll.Web.Template.Internal
16--------------------------------------------------------------------------------
16--------------------------------------------------------------------------------
17−-- | Construct a @Template@ from a string.
17+
18readTemplate :: String -> Template
18readTemplate :: String -> Template
19−readTemplate = Template . readTemplate'
19+readTemplate input =
20− where
20+ case parse template "" input of
21− readTemplate' [] = []
21+ Left err -> error $ "Cannot parse template: " ++ show err
22− readTemplate' string
22+ Right t -> t
23− | "$$" `isPrefixOf` string =
23+
24− Escaped : readTemplate' (drop 2 string)
24+template :: Parser Template
25− | "$" `isPrefixOf` string =
25+template = Template <$>
26− case readKey (drop 1 string) of
26+ (many1 $ chunk <|> escaped <|> conditional <|> key)
27− Just (key, rest) -> Key key : readTemplate' rest
27+
28− Nothing -> Chunk "$" : readTemplate' (drop 1 string)
28+chunk :: Parser TemplateElement
29− | otherwise =
29+chunk = Chunk <$> (many1 $ noneOf "$")
30− let (chunk, rest) = break (== '$') string
30+
31− in Chunk chunk : readTemplate' rest
31+escaped :: Parser TemplateElement
32−
32+escaped = Escaped <$ (try $ string "$$")
33− -- Parse an key into (key, rest) if it's valid, and return
33+
34− -- Nothing otherwise
34+conditional :: Parser TemplateElement
35− readKey string =
35+conditional = try $ do
36− let (key, rest) = span validKeyChar string
36+ void $ string "$if("
37− in if not (null key) && "$" `isPrefixOf` rest
37+ i <- ident
38− then Just (key, drop 1 rest)
38+ void $ string ")$"
39− else Nothing
39+ thenBranch <- template
40−
40+ elseBranch <- optionMaybe $ try (string "$else$") >> template
41− validKeyChar x = x `notElem` ['$', '\n', '\r']
41+ void $ string "$endif$"
42+ return $ If i thenBranch elseBranch
44+ident :: Parser String
46+ i <- (:) <$> letter <*> (many $ alphaNum <|> oneOf " _-.")
52+reserved = ["if", "else","endif"]
54+key :: Parser TemplateElement