summaryrefslogtreecommitdiff
path: root/src/Hakyll/Web/Template/Read.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Hakyll/Web/Template/Read.hs')
-rw-r--r--src/Hakyll/Web/Template/Read.hs74
1 files changed, 46 insertions, 28 deletions
diff --git a/src/Hakyll/Web/Template/Read.hs b/src/Hakyll/Web/Template/Read.hs
index 7dfe003..4ef5f2f 100644
--- a/src/Hakyll/Web/Template/Read.hs
+++ b/src/Hakyll/Web/Template/Read.hs
@@ -4,38 +4,56 @@ module Hakyll.Web.Template.Read
( readTemplate
) where
-
--------------------------------------------------------------------------------
-import Data.List (isPrefixOf)
-
+import Control.Applicative ((<$>), (<$), (<*>))
+import Control.Monad (void, mzero, guard)
+import Text.Parsec
+import Text.Parsec.String
--------------------------------------------------------------------------------
import Hakyll.Web.Template.Internal
-
--------------------------------------------------------------------------------
--- | Construct a @Template@ from a string.
+
readTemplate :: String -> Template
-readTemplate = Template . readTemplate'
- where
- readTemplate' [] = []
- readTemplate' string
- | "$$" `isPrefixOf` string =
- Escaped : readTemplate' (drop 2 string)
- | "$" `isPrefixOf` string =
- case readKey (drop 1 string) of
- Just (key, rest) -> Key key : readTemplate' rest
- Nothing -> Chunk "$" : readTemplate' (drop 1 string)
- | otherwise =
- let (chunk, rest) = break (== '$') string
- in Chunk chunk : readTemplate' rest
-
- -- Parse an key into (key, rest) if it's valid, and return
- -- Nothing otherwise
- readKey string =
- let (key, rest) = span validKeyChar string
- in if not (null key) && "$" `isPrefixOf` rest
- then Just (key, drop 1 rest)
- else Nothing
-
- validKeyChar x = x `notElem` ['$', '\n', '\r']
+readTemplate input =
+ case parse template "" input of
+ Left err -> error $ "Cannot parse template: " ++ show err
+ Right t -> t
+
+template :: Parser Template
+template = Template <$>
+ (many1 $ chunk <|> escaped <|> conditional <|> key)
+
+chunk :: Parser TemplateElement
+chunk = Chunk <$> (many1 $ noneOf "$")
+
+escaped :: Parser TemplateElement
+escaped = Escaped <$ (try $ string "$$")
+
+conditional :: Parser TemplateElement
+conditional = try $ do
+ void $ string "$if("
+ i <- ident
+ void $ string ")$"
+ thenBranch <- template
+ elseBranch <- optionMaybe $ try (string "$else$") >> template
+ void $ string "$endif$"
+ return $ If i thenBranch elseBranch
+
+ident :: Parser String
+ident = do
+ i <- (:) <$> letter <*> (many $ alphaNum <|> oneOf " _-.")
+ if i `elem` reserved
+ then mzero
+ else return i
+
+reserved :: [String]
+reserved = ["if", "else","endif"]
+
+key :: Parser TemplateElement
+key = try $ do
+ void $ char '$'
+ k <- ident
+ void $ char '$'
+ return $ Key k