-- | This module provides means for reading and applying 'Template's.
--
-- Templates are tools to convert data (pages) into a string. They are
-- perfectly suited for laying out your site.
--
-- Let's look at an example template:
--
-- >
-- >
-- > My crazy homepage - $title$
-- >
-- >
-- >
-- >
-- > $body$
-- >
-- >
-- >
-- >
--
-- We can use this template to render a 'Page' which has a body and a @$title$@
-- metadata field.
--
-- 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
--
-- >
-- > A literal $$key$$.
-- >
--
-- 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.
--
-- In addition to the native format, Hakyll also supports hamlet templates. For
-- more information on hamlet templates, please refer to:
-- .
--
module Hakyll.Web.Template
( Template
, applyTemplate
, applySelf
, templateCompiler
, templateCompilerWith
, applyTemplateCompiler
) where
import Control.Arrow
import Data.Maybe (fromMaybe)
import System.FilePath (takeExtension)
import qualified Data.Map as M
import Text.Hamlet (HamletSettings, defaultHamletSettings)
import Hakyll.Core.Compiler
import Hakyll.Core.Identifier
import Hakyll.Core.Resource
import Hakyll.Web.Template.Internal
import Hakyll.Web.Template.Read
import Hakyll.Web.Page.Internal
-- | Substitutes @$identifiers@ in the given @Template@ by values from the given
-- "Page". When a key is not found, it is left as it is. You can specify
-- the characters used to replace escaped dollars (@$$@) here.
--
applyTemplate :: Template -> Page String -> Page String
applyTemplate template page =
fmap (const $ substitute =<< unTemplate template) page
where
map' = toMap page
substitute (Chunk chunk) = chunk
substitute (Key key) = fromMaybe ("$" ++ key ++ "$") $ M.lookup key map'
substitute (Escaped) = "$"
-- | Apply a page as it's own template. This is often very useful to fill in
-- certain keys like @$root@ and @$url@.
--
applySelf :: Page String -> Page String
applySelf page = applyTemplate (readTemplate $ pageBody page) page
-- | Read a template. If the extension of the file we're compiling is
-- @.hml@ or @.hamlet@, it will be considered as a Hamlet template, and parsed
-- as such.
--
templateCompiler :: Compiler Resource Template
templateCompiler = templateCompilerWith defaultHamletSettings
-- | Version of 'templateCompiler' that enables custom settings.
--
templateCompilerWith :: HamletSettings -> Compiler Resource Template
templateCompilerWith settings =
cached "Hakyll.Web.Template.templateCompilerWith" $
getIdentifier &&& getResourceString >>^ uncurry read'
where
read' identifier string =
if takeExtension (toFilePath identifier) `elem` [".hml", ".hamlet"]
-- Hamlet template
then readHamletTemplateWith settings string
-- Hakyll template
else readTemplate string
applyTemplateCompiler :: Identifier -- ^ Template
-> Compiler (Page String) (Page String) -- ^ Compiler
applyTemplateCompiler identifier = require identifier (flip applyTemplate)