summaryrefslogtreecommitdiff
path: root/src/Hakyll/Web/Template
diff options
context:
space:
mode:
authorIvan N. Veselov <veselov@gmail.com>2013-05-03 19:10:57 +0300
committerIvan N. Veselov <veselov@gmail.com>2013-05-03 19:10:57 +0300
commitf86b9c5b0cd702788cfb1cc4db9b63f72c7105eb (patch)
tree9826732e7d585a237e05f416ac20511b0ac97225 /src/Hakyll/Web/Template
parent617322ae8ce039fcd36a7a7629a822522454a1af (diff)
downloadhakyll-f86b9c5b0cd702788cfb1cc4db9b63f72c7105eb.tar.gz
Added support for "$if$" statement in templates.
Diffstat (limited to 'src/Hakyll/Web/Template')
-rw-r--r--src/Hakyll/Web/Template/Internal.hs12
-rw-r--r--src/Hakyll/Web/Template/Read.hs74
2 files changed, 53 insertions, 33 deletions
diff --git a/src/Hakyll/Web/Template/Internal.hs b/src/Hakyll/Web/Template/Internal.hs
index e264731..0bd999e 100644
--- a/src/Hakyll/Web/Template/Internal.hs
+++ b/src/Hakyll/Web/Template/Internal.hs
@@ -9,7 +9,7 @@ module Hakyll.Web.Template.Internal
--------------------------------------------------------------------------------
-import Control.Applicative ((<$>))
+import Control.Applicative (pure, (<$>), (<*>))
import Data.Binary (Binary, get, getWord8, put, putWord8)
import Data.Typeable (Typeable)
@@ -38,18 +38,20 @@ data TemplateElement
= Chunk String
| Key String
| Escaped
+ | If String Template (Maybe Template) -- key, then branch, else branch
deriving (Show, Eq, Typeable)
-
--------------------------------------------------------------------------------
instance Binary TemplateElement where
- put (Chunk string) = putWord8 0 >> put string
- put (Key key) = putWord8 1 >> put key
+ put (Chunk string) = putWord8 0 >> put string
+ put (Key key) = putWord8 1 >> put key
put (Escaped) = putWord8 2
+ put (If key t f) = putWord8 3 >> put key >> put t >> put f
get = getWord8 >>= \tag -> case tag of
0 -> Chunk <$> get
1 -> Key <$> get
- 2 -> return Escaped
+ 2 -> pure Escaped
+ 3 -> If <$> get <*> get <*> get
_ -> error $ "Hakyll.Web.Template.Internal: "
++ "Error reading cached template"
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