@@ -10,18 +10,32 @@ module Hakyll.Web.Template.Context
10 , pathField
10 , pathField
11 , categoryField
11 , categoryField
12 , titleField
12 , titleField
15+ , modificationTimeField
16+ , modificationTimeFieldWith
16--------------------------------------------------------------------------------
20--------------------------------------------------------------------------------
17−import Control.Applicative (Alternative (..), (<$>))
21+import Control.Applicative (Alternative (..), (<$>))
18−import Data.Monoid (Monoid (..))
22+import Control.Monad (msum)
23+import Data.List (intercalate)
24+import qualified Data.Map as M
25+import Data.Monoid (Monoid (..))
26+import Data.Time.Clock (UTCTime (..))
27+import Data.Time.Format (formatTime, parseTime)
19−import System.FilePath (takeBaseName, takeDirectory)
28+import System.FilePath (takeBaseName, takeDirectory,
30+import System.Locale (TimeLocale, defaultTimeLocale)
22--------------------------------------------------------------------------------
33--------------------------------------------------------------------------------
23import Hakyll.Core.Compiler
34import Hakyll.Core.Compiler
35+import Hakyll.Core.Compiler.Internal
24import Hakyll.Core.Identifier
36import Hakyll.Core.Identifier
37+import Hakyll.Core.ResourceProvider
38+import Hakyll.Core.Util.String (splitAll)
25import Hakyll.Web.Page.Internal
39import Hakyll.Web.Page.Internal
26import Hakyll.Web.Urls
40import Hakyll.Web.Urls
@@ -84,6 +98,90 @@ titleField :: String -> Context a
84titleField key = mapContext takeBaseName $ pathField key
98titleField key = mapContext takeBaseName $ pathField key
101+--------------------------------------------------------------------------------
102+-- | When the metadata has a field called @published@ in one of the
103+-- following formats then this function can render the date.
105+-- * @Sun, 01 Feb 2000 13:00:00 UT@ (RSS date format)
107+-- * @2000-02-01T13:00:00Z@ (Atom date format)
109+-- * @February 1, 2000 1:00 PM@ (PM is usually uppercase)
111+-- * @February 1, 2000@ (assumes 12:00 AM for the time)
113+-- Alternatively, when the metadata has a field called @path@ in a
114+-- @folder/yyyy-mm-dd-title.extension@ format (the convention for pages)
115+-- and no @published@ metadata field set, this function can render
118+-- > renderDateField "date" "%B %e, %Y" "Date unknown"
120+-- Will render something like @January 32, 2010@.
122+dateField :: String -- ^ Key in which the rendered date should be placed
123+ -> String -- ^ Format to use on the date
124+ -> Context a -- ^ Resulting context
125+dateField = dateFieldWith defaultTimeLocale
128+--------------------------------------------------------------------------------
129+-- | This is an extended version of 'dateField' that allows you to
130+-- specify a time locale that is used for outputting the date. For more
131+-- details, see 'dateField'.
132+dateFieldWith :: TimeLocale -- ^ Output time locale
133+ -> String -- ^ Destination key
134+ -> String -- ^ Format to use on the date
135+ -> Context a -- ^ Resulting context
136+dateFieldWith locale key format = field key $ \id' _ -> do
137+ time <- getUTC locale id'
138+ return $ formatTime locale format time
141+--------------------------------------------------------------------------------
142+-- | Parser to try to extract and parse the time from the @published@
143+-- field or from the filename. See 'renderDateField' for more information.
144+getUTC :: TimeLocale -- ^ Output time locale
145+ -> Identifier -- ^ Input page
146+ -> Compiler UTCTime -- ^ Parsed UTCTime
147+getUTC locale id' = do
148+ metadata <- getMetadataFor id'
149+ let tryField k fmt = M.lookup k metadata >>= parseTime' fmt
150+ fn = takeFileName $ toFilePath id'
152+ maybe empty return $ msum $
153+ [tryField "published" fmt | fmt <- formats] ++
154+ [tryField "date" fmt | fmt <- formats] ++
155+ [parseTime' "%Y-%m-%d" $ intercalate "-" $ take 3 $ splitAll "-" fn]
157+ parseTime' = parseTime locale
159+ [ "%a, %d %b %Y %H:%M:%S UT"
160+ , "%Y-%m-%dT%H:%M:%SZ"
161+ , "%Y-%m-%d %H:%M:%S"
163+ , "%B %e, %Y %l:%M %p"
168+--------------------------------------------------------------------------------
169+modificationTimeField :: String -- ^ Key
170+ -> String -- ^ Format
171+ -> Context a -- ^ Resuting context
172+modificationTimeField = modificationTimeFieldWith defaultTimeLocale
175+--------------------------------------------------------------------------------
176+modificationTimeFieldWith :: TimeLocale -- ^ Time output locale
178+ -> String -- ^ Format
179+ -> Context a -- ^ Resulting context
180+modificationTimeFieldWith locale key fmt = field key $ \id' _ -> do
181+ mtime <- compilerUnsafeIO $ resourceModificationTime id'
182+ return $ formatTime locale fmt mtime
87--------------------------------------------------------------------------------
185--------------------------------------------------------------------------------
88missingField :: Context a
186missingField :: Context a
89missingField = Context $ \k _ _ -> return $ "$" ++ k ++ "$"
187missingField = Context $ \k _ _ -> return $ "$" ++ k ++ "$"