From f86b9c5b0cd702788cfb1cc4db9b63f72c7105eb Mon Sep 17 00:00:00 2001 From: "Ivan N. Veselov" Date: Fri, 3 May 2013 19:10:57 +0300 Subject: Added support for "$if$" statement in templates. --- src/Hakyll/Web/Template/Internal.hs | 12 +++--- src/Hakyll/Web/Template/Read.hs | 74 +++++++++++++++++++++++-------------- 2 files changed, 53 insertions(+), 33 deletions(-) (limited to 'src/Hakyll/Web/Template') 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 -- cgit v1.2.3