Add IsString instance for Template

Closes #150
This commit is contained in:
Jasper Van der Jeugt 2014-01-19 21:24:52 +01:00
parent c024ed8a93
commit 677cca0578
6 changed files with 94 additions and 104 deletions

View file

@ -119,7 +119,6 @@ Library
Hakyll.Web.Template
Hakyll.Web.Template.Context
Hakyll.Web.Template.List
Hakyll.Web.Template.Read
Other-Modules:
Hakyll.Check

View file

@ -28,7 +28,6 @@ module Hakyll
, module Hakyll.Web.Template
, module Hakyll.Web.Template.Context
, module Hakyll.Web.Template.List
, module Hakyll.Web.Template.Read
) where
@ -59,4 +58,3 @@ import Hakyll.Web.Tags
import Hakyll.Web.Template
import Hakyll.Web.Template.Context
import Hakyll.Web.Template.List
import Hakyll.Web.Template.Read

View file

@ -35,7 +35,6 @@ import Hakyll.Core.Item
import Hakyll.Web.Template
import Hakyll.Web.Template.Context
import Hakyll.Web.Template.List
import Hakyll.Web.Template.Read
--------------------------------------------------------------------------------

View file

@ -122,6 +122,7 @@ module Hakyll.Web.Template
, applyTemplate
, loadAndApplyTemplate
, applyAsTemplate
, readTemplate
) where
@ -139,7 +140,6 @@ import Hakyll.Core.Identifier
import Hakyll.Core.Item
import Hakyll.Web.Template.Context
import Hakyll.Web.Template.Internal
import Hakyll.Web.Template.Read
--------------------------------------------------------------------------------

View file

@ -5,16 +5,22 @@
module Hakyll.Web.Template.Internal
( Template (..)
, TemplateElement (..)
, readTemplate
) where
--------------------------------------------------------------------------------
import Control.Applicative (pure, (<$>), (<*>))
import Data.Binary (Binary, get, getWord8, put, putWord8)
import Data.Typeable (Typeable)
import Control.Applicative (pure, (<$), (<$>), (<*>), (<|>))
import Control.Monad (void)
import Data.Binary (Binary, get, getWord8, put, putWord8)
import Data.Typeable (Typeable)
import GHC.Exts (IsString (..))
import qualified Text.Parsec as P
import qualified Text.Parsec.String as P
--------------------------------------------------------------------------------
import Hakyll.Core.Util.Parser
import Hakyll.Core.Writable
@ -46,10 +52,10 @@ data TemplateElement
--------------------------------------------------------------------------------
instance Binary TemplateElement where
put (Chunk string) = putWord8 0 >> put string
put (Key key) = putWord8 1 >> put key
put (Key k) = putWord8 1 >> put k
put (Escaped) = putWord8 2
put (If key t f) = putWord8 3 >> put key >> put t >> put f
put (For key b s) = putWord8 4 >> put key >> put b >> put s
put (If k t f ) = putWord8 3 >> put k >> put t >> put f
put (For k b s) = putWord8 4 >> put k >> put b >> put s
put (Partial p) = putWord8 5 >> put p
get = getWord8 >>= \tag -> case tag of
@ -61,3 +67,84 @@ instance Binary TemplateElement where
5 -> Partial <$> get
_ -> error $
"Hakyll.Web.Template.Internal: Error reading cached template"
--------------------------------------------------------------------------------
instance IsString Template where
fromString = readTemplate
--------------------------------------------------------------------------------
readTemplate :: String -> Template
readTemplate input = case P.parse template "" input of
Left err -> error $ "Cannot parse template: " ++ show err
Right t -> t
--------------------------------------------------------------------------------
template :: P.Parser Template
template = Template <$>
(P.many1 $ chunk <|> escaped <|> conditional <|> for <|> partial <|> key)
--------------------------------------------------------------------------------
chunk :: P.Parser TemplateElement
chunk = Chunk <$> (P.many1 $ P.noneOf "$")
--------------------------------------------------------------------------------
escaped :: P.Parser TemplateElement
escaped = Escaped <$ (P.try $ P.string "$$")
--------------------------------------------------------------------------------
conditional :: P.Parser TemplateElement
conditional = P.try $ do
void $ P.string "$if("
i <- metadataKey
void $ P.string ")$"
thenBranch <- template
elseBranch <- P.optionMaybe $ P.try (P.string "$else$") >> template
void $ P.string "$endif$"
return $ If i thenBranch elseBranch
--------------------------------------------------------------------------------
for :: P.Parser TemplateElement
for = P.try $ do
void $ P.string "$for("
i <- metadataKey
void $ P.string ")$"
body <- template
sep <- P.optionMaybe $ P.try (P.string "$sep$") >> template
void $ P.string "$endfor$"
return $ For i body sep
--------------------------------------------------------------------------------
partial :: P.Parser TemplateElement
partial = P.try $ do
void $ P.string "$partial("
i <- stringLiteral
void $ P.string ")$"
return $ Partial i
--------------------------------------------------------------------------------
key :: P.Parser TemplateElement
key = P.try $ do
void $ P.char '$'
k <- metadataKey
void $ P.char '$'
return $ Key k
--------------------------------------------------------------------------------
stringLiteral :: P.Parser String
stringLiteral = do
void $ P.char '\"'
str <- P.many $ do
x <- P.noneOf "\""
if x == '\\' then P.anyChar else return x
void $ P.char '\"'
return str

View file

@ -1,93 +0,0 @@
--------------------------------------------------------------------------------
-- | Read templates in Hakyll's native format
module Hakyll.Web.Template.Read
( readTemplate
) where
--------------------------------------------------------------------------------
import Control.Applicative ((<$), (<$>))
import Control.Monad (void)
import Text.Parsec
import Text.Parsec.String
--------------------------------------------------------------------------------
import Hakyll.Core.Util.Parser
import Hakyll.Web.Template.Internal
--------------------------------------------------------------------------------
readTemplate :: String -> Template
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 <|> for <|> partial <|> 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 <- metadataKey
void $ string ")$"
thenBranch <- template
elseBranch <- optionMaybe $ try (string "$else$") >> template
void $ string "$endif$"
return $ If i thenBranch elseBranch
--------------------------------------------------------------------------------
for :: Parser TemplateElement
for = try $ do
void $ string "$for("
i <- metadataKey
void $ string ")$"
body <- template
sep <- optionMaybe $ try (string "$sep$") >> template
void $ string "$endfor$"
return $ For i body sep
--------------------------------------------------------------------------------
partial :: Parser TemplateElement
partial = try $ do
void $ string "$partial("
i <- stringLiteral
void $ string ")$"
return $ Partial i
--------------------------------------------------------------------------------
key :: Parser TemplateElement
key = try $ do
void $ char '$'
k <- metadataKey
void $ char '$'
return $ Key k
--------------------------------------------------------------------------------
stringLiteral :: Parser String
stringLiteral = do
void $ char '\"'
str <- many $ do
x <- noneOf "\""
if x == '\\' then anyChar else return x
void $ char '\"'
return str