on master help sign in
Add some time-related fields
commit1347b0fa6cdd98986f927368e76e849068f69e1a authorJasper Van der Jeugt <m@jaspervdj.be> dateSun 18 Nov 2012, 11:22 (14 years ago) parent07a721f
1 file changed+101−3
src/Hakyll/Web/Template/Context.hs+101−3
src/Hakyll/Web/Template/Context.hs+101−3
@@ -10,18 +10,32 @@ module Hakyll.Web.Template.Context
1010 , pathField
1111 , categoryField
1212 , titleField
13+ , dateField
14+ , dateFieldWith
15+ , modificationTimeField
16+ , modificationTimeFieldWith
1317 ) where
1418
1519
1620--------------------------------------------------------------------------------
17−import Control.Applicative (Alternative (..), (<$>))
18−import Data.Monoid (Monoid (..))
19−import System.FilePath (takeBaseName, takeDirectory)
21+import Control.Applicative (Alternative (..), (<$>))
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)
28+import System.FilePath (takeBaseName, takeDirectory,
29+ takeFileName)
30+import System.Locale (TimeLocale, defaultTimeLocale)
2031
2132
2233--------------------------------------------------------------------------------
2334import Hakyll.Core.Compiler
35+import Hakyll.Core.Compiler.Internal
2436import Hakyll.Core.Identifier
37+import Hakyll.Core.ResourceProvider
38+import Hakyll.Core.Util.String (splitAll)
2539import Hakyll.Web.Page.Internal
2640import Hakyll.Web.Urls
2741
@@ -84,6 +98,90 @@ titleField :: String -> Context a
8498titleField key = mapContext takeBaseName $ pathField key
8599
86100
101+--------------------------------------------------------------------------------
102+-- | When the metadata has a field called @published@ in one of the
103+-- following formats then this function can render the date.
104+--
105+-- * @Sun, 01 Feb 2000 13:00:00 UT@ (RSS date format)
106+--
107+-- * @2000-02-01T13:00:00Z@ (Atom date format)
108+--
109+-- * @February 1, 2000 1:00 PM@ (PM is usually uppercase)
110+--
111+-- * @February 1, 2000@ (assumes 12:00 AM for the time)
112+--
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
116+-- the date.
117+--
118+-- > renderDateField "date" "%B %e, %Y" "Date unknown"
119+--
120+-- Will render something like @January 32, 2010@.
121+--
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
126+
127+
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
139+
140+
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'
151+
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]
156+ where
157+ parseTime' = parseTime locale
158+ formats =
159+ [ "%a, %d %b %Y %H:%M:%S UT"
160+ , "%Y-%m-%dT%H:%M:%SZ"
161+ , "%Y-%m-%d %H:%M:%S"
162+ , "%Y-%m-%d"
163+ , "%B %e, %Y %l:%M %p"
164+ , "%B %e, %Y"
165+ ]
166+
167+
168+--------------------------------------------------------------------------------
169+modificationTimeField :: String -- ^ Key
170+ -> String -- ^ Format
171+ -> Context a -- ^ Resuting context
172+modificationTimeField = modificationTimeFieldWith defaultTimeLocale
173+
174+
175+--------------------------------------------------------------------------------
176+modificationTimeFieldWith :: TimeLocale -- ^ Time output locale
177+ -> String -- ^ Key
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
183+
184+
87185--------------------------------------------------------------------------------
88186missingField :: Context a
89187missingField = Context $ \k _ _ -> return $ "$" ++ k ++ "$"