on master help sign in
ContextManipulations → Metadata
fef1172Jasper Van der Jeugt
src/Text/Hakyll/ContextManipulations.hs → src/Text/Hakyll/Metadata.hsrenamed+30−46
@@ -1,5 +1,6 @@
1−-- | This module exports a number of functions that produce @HakyllAction@s to
1+-- | This module exports a number of functions to manipulate metadata of
2−-- manipulate @Context@s.
2+-- resources
3+--
3module Text.Hakyll.ContextManipulations
4module Text.Hakyll.ContextManipulations
4 ( renderValue
5 ( renderValue
5 , changeValue
6 , changeValue
@@ -8,12 +9,8 @@ module Text.Hakyll.ContextManipulations
8 , renderDate
9 , renderDate
9 , renderDateWithLocale
10 , renderDateWithLocale
10 , changeExtension
11 , changeExtension
11− , renderBody
12− , takeBody
13 ) where
12 ) where
14
13
15−import Control.Monad (liftM)
16−import Control.Arrow (arr)
17import System.Locale (TimeLocale, defaultTimeLocale)
14import System.Locale (TimeLocale, defaultTimeLocale)
18import System.FilePath (takeFileName, addExtension, dropExtension)
15import System.FilePath (takeFileName, addExtension, dropExtension)
19import Data.Time.Format (parseTime, formatTime)
16import Data.Time.Format (parseTime, formatTime)
@@ -22,8 +19,8 @@ import Data.Maybe (fromMaybe)
22import qualified Data.Map as M
19import qualified Data.Map as M
23
20
24import Text.Hakyll.Regex (substituteRegex)
21import Text.Hakyll.Regex (substituteRegex)
25−import Text.Hakyll.HakyllAction (HakyllAction (..))
22+import Text.Hakyll.Transformer (Transformer (..), transformMetadata)
26−import Text.Hakyll.Context (Context (..))
23+import Text.Hakyll.Resource
27
24
28-- | Do something with a value in a @Context@, but keep the old value as well.
25-- | Do something with a value in a @Context@, but keep the old value as well.
29-- If the key given is not present in the @Context@, nothing will happen.
26-- If the key given is not present in the @Context@, nothing will happen.
@@ -31,35 +28,37 @@ import Text.Hakyll.Context (Context (..))
31renderValue :: String -- ^ Key of which the value should be copied.
28renderValue :: String -- ^ Key of which the value should be copied.
32 -> String -- ^ Key the value should be copied to.
29 -> String -- ^ Key the value should be copied to.
33 -> (String -> String) -- ^ Function to apply on the value.
30 -> (String -> String) -- ^ Function to apply on the value.
34− -> HakyllAction Context Context
31+ -> Transformer a a -- ^ Resulting transformer
35−renderValue source destination f = arr $ \(Context context) -> Context $
32+renderValue source destination f = transformMetadata $ \(Metadata m) ->
36− case M.lookup source context of
33+ Metadata $ case M.lookup source m of
37− Nothing -> context
34+ Nothing -> m
38− (Just value) -> M.insert destination (f value) context
35+ (Just value) -> M.insert destination (f value) m
39
36
40−-- | Change a value in a @Context@.
37+-- | Change a value in the metadata
41--
38--
42-- > import Data.Char (toUpper)
39-- > import Data.Char (toUpper)
43-- > changeValue "title" (map toUpper)
40-- > changeValue "title" (map toUpper)
44--
41--
45-- Will put the title in UPPERCASE.
42-- Will put the title in UPPERCASE.
46−changeValue :: String -- ^ Key to change.
43+changeValue :: String -- ^ Key to change.
47− -> (String -> String) -- ^ Function to apply on the value.
44+ -> (String -> String) -- ^ Function to apply on the value.
48− -> HakyllAction Context Context
45+ -> Transformer a a
49changeValue key = renderValue key key
46changeValue key = renderValue key key
50
47
51−-- | Change the URL of a page. This requires a special function, so dependency
48+-- | Change the URL of a page. You should always use this function instead of
52−-- handling can happen correctly.
49+-- 'changeValue' for this, because using 'changeValue' might break dependency
50+-- handling when changing the @url@ field.
53--
51--
54−changeUrl :: (String -> String) -- ^ Function to change URL with.
52+changeUrl :: (String -> String) -- ^ Function to change URL with.
55− -> HakyllAction Context Context -- ^ Resulting action.
53+ -> Transformer a a -- ^ Resulting action.
56−changeUrl f = let action = changeValue "url" f
54+changeUrl f = let t = changeValue "url" f
57− in action {actionUrl = Right $ liftM f}
55+ in t {transformerUrl = return . f}
58
56
59−-- | Copy a value from one key to another in a @Context@.
57+-- | Copy a metadata value from one key to another
58+--
60−copyValue :: String -- ^ Source key.
59+copyValue :: String -- ^ Source key.
61− -> String -- ^ Destination key.
60+ -> String -- ^ Destination key.
62− -> HakyllAction Context Context
61+ -> Transformer a a -- ^ Resulting transformer
63copyValue source destination = renderValue source destination id
62copyValue source destination = renderValue source destination id
64
63
65-- | When the context has a key called @path@ in a
64-- | When the context has a key called @path@ in a
@@ -73,7 +72,7 @@ copyValue source destination = renderValue source destination id
73renderDate :: String -- ^ Key in which the rendered date should be placed.
72renderDate :: String -- ^ Key in which the rendered date should be placed.
74 -> String -- ^ Format to use on the date.
73 -> String -- ^ Format to use on the date.
75 -> String -- ^ Default key, in case the date cannot be parsed.
74 -> String -- ^ Default key, in case the date cannot be parsed.
76− -> HakyllAction Context Context
75+ -> Transformer a a
77renderDate = renderDateWithLocale defaultTimeLocale
76renderDate = renderDateWithLocale defaultTimeLocale
78
77
79-- | This is an extended version of 'renderDate' that allows you to specify a
78-- | This is an extended version of 'renderDate' that allows you to specify a
@@ -84,7 +83,7 @@ renderDateWithLocale :: TimeLocale -- ^ Output time locale.
84 -> String -- ^ Destination key.
83 -> String -- ^ Destination key.
85 -> String -- ^ Format to use on the date.
84 -> String -- ^ Format to use on the date.
86 -> String -- ^ Default key.
85 -> String -- ^ Default key.
87− -> HakyllAction Context Context
86+ -> Transformer a a
88renderDateWithLocale locale key format defaultValue =
87renderDateWithLocale locale key format defaultValue =
89 renderValue "path" key renderDate'
88 renderValue "path" key renderDate'
90 where
89 where
@@ -102,23 +101,8 @@ renderDateWithLocale locale key format defaultValue =
102-- > changeExtension "php"
101-- > changeExtension "php"
103--
102--
104-- Will render @test.markdown@ to @test.php@ instead of @test.html@.
103-- Will render @test.markdown@ to @test.php@ instead of @test.html@.
105−changeExtension :: String -- ^ Extension to change to.
104+changeExtension :: String -- ^ Extension to change to.
106− -> HakyllAction Context Context
105+ -> Transformer a a -- ^ Resulting transformer
107changeExtension extension = changeValue "url" changeExtension'
106changeExtension extension = changeValue "url" changeExtension'
108 where
107 where
109 changeExtension' = flip addExtension extension . dropExtension
108 changeExtension' = flip addExtension extension . dropExtension
110−
111−-- | Change the body of a file using a certain manipulation.
112−--
113−-- > import Data.Char (toUpper)
114−-- > renderBody (map toUpper)
115−--
116−-- Will put the entire body of the page in UPPERCASE.
117−renderBody :: (String -> String)
118− -> HakyllAction Context Context
119−renderBody = renderValue "body" "body"
120−
121−-- | Get the resulting body text from a context
122−--
123−takeBody :: HakyllAction Context String
124−takeBody = arr $ fromMaybe "" . M.lookup "body" . unContext
src/Text/Hakyll/Resource.hs+9−12
@@ -1,21 +1,25 @@
1-- | A resource represents data for a website
1-- | A resource represents data for a website
2--
2--
3−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4module Text.Hakyll.Resource
3module Text.Hakyll.Resource
5 ( Metadata (..)
4 ( Metadata (..)
6 , Resource (..)
5 , Resource (..)
7 , getData
6 , getData
8 , getMetadata
7 , getMetadata
9− , getMetadataList
10 ) where
8 ) where
11
9
12import Data.Monoid (Monoid, mempty, mappend)
10import Data.Monoid (Monoid, mempty, mappend)
13import Control.Applicative (Applicative, (<*>), pure)
11import Control.Applicative (Applicative, (<*>), pure)
12+import Data.Map (Map)
13+import qualified Data.Map as M
14
14
15-- | Metadata for a resource
15-- | Metadata for a resource
16--
16--
17−newtype Metadata = Metadata {unMetadata :: [(String, String)]}
17+newtype Metadata = Metadata {unMetadata :: Map String String}
18− deriving (Show, Eq, Ord, Monoid)
18+ deriving (Show, Eq, Ord)
19+
20+instance Monoid Metadata where
21+ mempty = Metadata M.empty
22+ (Metadata m1) `mappend` (Metadata m2) = Metadata $ m1 `M.union` m2
19
23
20-- | A resource represents a data source for the website. It contains a value
24-- | A resource represents a data source for the website. It contains a value
21-- and a number of metadata fields
25-- and a number of metadata fields
@@ -50,11 +54,4 @@ getData = resourceData
50-- | Get a metadata field from a resource
54-- | Get a metadata field from a resource
51--
55--
52getMetadata :: String -> Resource a -> Maybe String
56getMetadata :: String -> Resource a -> Maybe String
53−getMetadata k (Resource m _) = lookup k $ unMetadata m
57+getMetadata k (Resource m _) = M.lookup k $ unMetadata m
54−
55−-- | Get a metadata field from a resource. If multiple fields with the same name
56−-- exist, they will all be returned
57−--
58−getMetadataList :: String -> Resource a -> [String]
59−getMetadataList k = map snd . filter ((== k) . fst)
60− . unMetadata . resourceMetadata
src/Text/Hakyll/Transformer.hs+18−8
@@ -5,17 +5,17 @@ module Text.Hakyll.Transformer
5 , transformResourceM
5 , transformResourceM
6 , transformData
6 , transformData
7 , transformDataM
7 , transformDataM
8− , transformMetaData
8+ , transformMetadata
9− , transformMetaDataM
9+ , transformMetadataM
10 , runTransformer
10 , runTransformer
11 , runTransformerForced
11 , runTransformerForced
12 ) where
12 ) where
13
13
14−import Data.Monoid (mappend, mempty)
14+import Data.Monoid (Monoid, mappend, mempty)
15import Control.Arrow
15import Control.Arrow
16import Control.Category
16import Control.Category
17import Control.Applicative ((<$>))
17import Control.Applicative ((<$>))
18−import Control.Monad ((<=<), unless)
18+import Control.Monad ((<=<), unless, liftM2)
19import Prelude hiding ((.), id)
19import Prelude hiding ((.), id)
20
20
21import Text.Hakyll.Resource
21import Text.Hakyll.Resource
@@ -34,6 +34,16 @@ data Transformer a b = Transformer
34 transformerFunction :: Resource a -> Hakyll (Resource b)
34 transformerFunction :: Resource a -> Hakyll (Resource b)
35 }
35 }
36
36
37+instance Monoid b => Monoid (Transformer a b) where
38+ mempty = arr (const mempty)
39+ mappend x y = Transformer
40+ { transformerDependencies =
41+ transformerDependencies x ++ transformerDependencies y
42+ , transformerUrl = transformerUrl x
43+ , transformerFunction = \r ->
44+ liftM2 mappend (transformerFunction x r) (transformerFunction y r)
45+ }
46+
37instance Category Transformer where
47instance Category Transformer where
38 id = Transformer
48 id = Transformer
39 { transformerDependencies = []
49 { transformerDependencies = []
@@ -70,11 +80,11 @@ transformDataM :: (a -> Hakyll b) -> Transformer a b
70transformDataM f = transformResourceM $ \(Resource m x) ->
80transformDataM f = transformResourceM $ \(Resource m x) ->
71 f x >>= return . Resource m
81 f x >>= return . Resource m
72
82
73−transformMetaData :: (Metadata -> Metadata) -> Transformer a a
83+transformMetadata :: (Metadata -> Metadata) -> Transformer a a
74−transformMetaData = transformMetaDataM . (return .)
84+transformMetadata = transformMetadataM . (return .)
75
85
76−transformMetaDataM :: (Metadata -> Hakyll Metadata) -> Transformer a a
86+transformMetadataM :: (Metadata -> Hakyll Metadata) -> Transformer a a
77−transformMetaDataM f = transformResourceM $ \(Resource m x) -> do
87+transformMetadataM f = transformResourceM $ \(Resource m x) -> do
78 m' <- f m
88 m' <- f m
79 return $ Resource m' x
89 return $ Resource m' x
80
90