-- | This module provides means for reading and applying 'Template's. -- -- Templates are tools to convert items into a string. They are perfectly suited -- for laying out your site. -- -- Let's look at an example template: -- -- > <html> -- > <head> -- > <title>My crazy homepage - $title$</title> -- > </head> -- > <body> -- > <div id="header"> -- > <h1>My crazy homepage - $title$</h1> -- > </div> -- > <div id="content"> -- > $body$ -- > </div> -- > <div id="footer"> -- > By reading this you agree that I now own your soul -- > </div> -- > </body> -- > </html> -- -- As you can see, the format is very simple -- @$key$@ is used to render the -- @$key$@ field from the page, everything else is literally copied. If you want -- to literally insert @\"$key$\"@ into your page (for example, when you're -- writing a Hakyll tutorial) you can use -- -- > <p> -- > A literal $$key$$. -- > </p> -- -- Because of it's simplicity, these templates can be used for more than HTML: -- you could make, for example, CSS or JS templates as well. -- -- Apart from interpolating @$key$@s from the 'Context' you can also -- use the following macros: -- -- * @$if(key)$@ -- -- > $if(key)$ -- > <b> Defined </b> -- > $else$ -- > <b> Non-defined </b> -- > $endif$ -- -- This example will print @Defined@ if @key@ is defined in the -- context and @Non-defined@ otherwise. The @$else$@ clause is -- optional. -- -- * @$for(key)$@ -- -- The @for@ macro is used for enumerating 'Context' elements that are -- lists, i.e. constructed using the 'listField' function. Assume that -- in a context we have an element @listField \"key\" c itms@. Then -- the snippet -- -- > $for(key)$ -- > $x$ -- > $sep$, -- > $endfor$ -- -- would, for each item @i@ in 'itms', lookup @$x$@ in the context @c@ -- with item @i@, interpolate it, and join the resulting list with -- @,@. -- -- Another concrete example one may consider is the following. Given the -- context -- -- > listField "things" (field "thing" (return . itemBody)) -- > (sequence [makeItem "fruits", makeItem "vegetables"]) -- -- and a template -- -- > I like -- > $for(things)$ -- > fresh $thing$$sep$, and -- > $endfor$ -- -- the resulting page would look like -- -- > <p> -- > I like -- > -- > fresh fruits, and -- > -- > fresh vegetables -- > </p> -- -- The @$sep$@ part can be omitted. Usually, you can get by using the -- 'applyListTemplate' and 'applyJoinListTemplate' functions. -- -- * @$partial(path)$@ -- -- Loads a template located in a separate file and interpolates it -- under the current context. -- -- Assuming that the file @test.html@ contains -- -- > <b>$key$</b> -- -- The result of rendering -- -- > <p> -- > $partial("test.html")$ -- > </p> -- -- is the same as the result of rendering -- -- > <p> -- > <b>$key$</b> -- > </p> -- -- That is, calling @$partial$@ is equivalent to just copying and pasting -- template code. -- -- In the examples above you can see that the outputs contain a lot of leftover -- whitespace that you may wish to remove. Using @'$-'@ or @'-$'@ instead of -- @'$'@ in a macro strips all whitespace to the left or right of that clause -- respectively. Given the context -- -- > listField "counts" (field "count" (return . itemBody)) -- > (sequence [makeItem "3", makeItem "2", makeItem "1"]) -- -- and a template -- -- > <p> -- > $for(counts)-$ -- > $count$ -- > $-sep$... -- > $-endfor$ -- > </p> -- -- the resulting page would look like -- -- > <p> -- > 3...2...1 -- > </p> -- {-# LANGUAGE TemplateHaskell #-} module Hakyll.Web.Template ( Template , templateBodyCompiler , templateCompiler , applyTemplate , loadAndApplyTemplate , applyAsTemplate , readTemplate , compileTemplateItem , unsafeReadTemplateFile , embedTemplate ) where -------------------------------------------------------------------------------- import Hakyll.Web.Template.Internal -------------------------------------------------------------------------------- import Data.FileEmbed (embedFile) import qualified Data.Text as T import qualified Data.Text.Encoding as T import Language.Haskell.TH (Exp, Q) -------------------------------------------------------------------------------- -- | Embed template allows you embed a template within the Haskell binary. -- Example: -- -- > myTemplate :: Template -- > myTemplate = $(embedTemplate "test.html") embedTemplate :: FilePath -> Q Exp embedTemplate :: FilePath -> Q Exp embedTemplate FilePath filePath = [| let source = T.unpack $ T.decodeUtf8 $(embedFile filePath) in case parseTemplateElemsFile filePath source of Left err -> error err Right tpl -> template filePath tpl |]