hakyll 1.2 → 1.3
raw patch · 8 files changed
+146/−42 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Text.Hakyll.File: sortByBaseName :: [FilePath] -> [FilePath]
+ Text.Hakyll.Renderables: createListing :: (Renderable a) => String -> FilePath -> [a] -> [(String, String)] -> CustomPage
+ Text.Hakyll.Renderables: createListingWith :: (Renderable a) => ContextManipulation -> String -> FilePath -> [a] -> [(String, String)] -> CustomPage
+ Text.Hakyll.Renderables: instance Binary PagePath
+ Text.Hakyll.Tags: readCategoryMap :: String -> [PagePath] -> Hakyll TagMap
+ Text.Hakyll.Tags: type TagMap = Map String [PagePath]
- Text.Hakyll.Tags: readTagMap :: String -> [FilePath] -> Hakyll (Map String [FilePath])
+ Text.Hakyll.Tags: readTagMap :: String -> [PagePath] -> Hakyll TagMap
- Text.Hakyll.Tags: renderTagCloud :: Map String [FilePath] -> (String -> String) -> Float -> Float -> String
+ Text.Hakyll.Tags: renderTagCloud :: TagMap -> (String -> String) -> Float -> Float -> String
Files
- hakyll.cabal +1/−1
- src/Text/Hakyll/Context.hs +3/−3
- src/Text/Hakyll/File.hs +8/−1
- src/Text/Hakyll/Internal/Template.hs +10/−9
- src/Text/Hakyll/Page.hs +6/−3
- src/Text/Hakyll/Render.hs +3/−3
- src/Text/Hakyll/Renderables.hs +56/−3
- src/Text/Hakyll/Tags.hs +59/−19
hakyll.cabal view
@@ -1,5 +1,5 @@ Name: hakyll-Version: 1.2+Version: 1.3 Synopsis: A simple static site generator library. Description:
src/Text/Hakyll/Context.hs view
@@ -24,9 +24,9 @@ -- | Type for context manipulating functions. type ContextManipulation = Context -> Context --- | Do something with a value in a "Context", but keep the old value as well.+-- | Do something with a value in a @Context@, but keep the old value as well. -- This is probably the most common function to construct a--- "ContextManipulation".+-- @ContextManipulation@. renderValue :: String -- ^ Key of which the value should be copied. -> String -- ^ Key the value should be copied to. -> (String -> String) -- ^ Function to apply on the value.@@ -35,7 +35,7 @@ Nothing -> context (Just value) -> M.insert dst (f value) context --- | Change a value in a "Context".+-- | Change a value in a @Context@. -- -- > import Data.Char (toUpper) -- > changeValue "title" (map toUpper)
src/Text/Hakyll/File.hs view
@@ -8,6 +8,7 @@ , removeSpaces , makeDirectories , getRecursiveContents+ , sortByBaseName , havingExtension , isMoreRecent , directory@@ -16,7 +17,7 @@ import System.Directory import System.FilePath import Control.Monad-import Data.List (isPrefixOf)+import Data.List (isPrefixOf, sortBy) import Control.Monad.Reader (liftIO) import Text.Hakyll.Hakyll@@ -99,6 +100,12 @@ return (concat paths) where isProper = not . (== '.') . head++-- | Sort a list of filenames on the basename.+sortByBaseName :: [FilePath] -> [FilePath]+sortByBaseName = sortBy compareBaseName+ where+ compareBaseName f1 f2 = compare (takeFileName f1) (takeFileName f2) -- | A filter that takes all file names with a given extension. Prefix the -- extension with a dot:
src/Text/Hakyll/Internal/Template.hs view
@@ -12,6 +12,7 @@ import Data.Char (isAlphaNum) import Data.Binary import Control.Monad (liftM, liftM2, replicateM)+import Control.Applicative ((<$>)) import Data.Maybe (fromMaybe) import System.FilePath ((</>)) import Control.Monad.Reader (liftIO)@@ -29,7 +30,7 @@ | End deriving (Show, Read, Eq) --- | Construct a "Template" from a string.+-- | Construct a @Template@ from a string. fromString :: String -> Template fromString [] = End fromString string@@ -41,7 +42,7 @@ where tail' = tail string --- | Read a "Template" from a file. This function might fetch the "Template"+-- | Read a @Template@ from a file. This function might fetch the @Template@ -- from the cache, if available. readTemplate :: FilePath -> Hakyll Template readTemplate path = do@@ -54,7 +55,7 @@ where fileName = "templates" </> path --- | Substitutes @$identifiers@ in the given "Template" by values from the given+-- | Substitutes @$identifiers@ in the given @Template@ by values from the given -- "Context". When a key is not found, it is left as it is. You can specify -- the characters used to replace escaped dollars (@$$@) here. substitute :: String -> Template -> Context -> String @@ -68,12 +69,12 @@ escaper ++ substitute escaper template context substitute _ End _ = [] --- | "substitute" for use during a chain. This will leave escaped characters as+-- | @substitute@ for use during a chain. This will leave escaped characters as -- they are. regularSubstitute :: Template -> Context -> String regularSubstitute = substitute "$$" --- | "substitute" for the end of a chain (just before writing). This renders+-- | @substitute@ for the end of a chain (just before writing). This renders -- escaped characters. finalSubstitute :: Template -> Context -> String finalSubstitute = substitute "$"@@ -95,10 +96,10 @@ arbitraryTemplate :: Int -> Gen Template arbitraryTemplate 0 = return End arbitraryTemplate length' = oneof [ do chunk <- chunk'- template' >>= return . Chunk chunk+ Chunk chunk <$> template' , do key <- key'- template' >>= return . Identifier key- , template' >>= return . EscapeCharacter+ Identifier key <$> template'+ , EscapeCharacter <$> template' ] where template' = arbitraryTemplate (length' - 1)@@ -111,7 +112,7 @@ return $ if null sanitized then "foo" else sanitized --- | Make "Template" testable.+-- | Make @Template@ testable. instance Arbitrary Template where arbitrary = choose (0, 20) >>= arbitraryTemplate
src/Text/Hakyll/Page.hs view
@@ -1,4 +1,4 @@--- | A module for dealing with "Page"s. This module is mostly internally used.+-- | A module for dealing with @Page@s. This module is mostly internally used. module Text.Hakyll.Page ( Page , fromContext@@ -13,14 +13,14 @@ import Data.Maybe (fromMaybe) import Control.Monad (liftM, replicateM) import Control.Monad.Reader (liftIO)-import System.FilePath (takeExtension, (</>))+import System.FilePath import Test.QuickCheck import Text.Pandoc import Data.Binary import Text.Hakyll.Internal.Cache-import Text.Hakyll.Hakyll (Hakyll)+import Text.Hakyll.Hakyll import Text.Hakyll.File import Text.Hakyll.Util (trim) import Text.Hakyll.Context (Context)@@ -127,6 +127,7 @@ let sections = splitAtDelimiters $ lines contents context = concat $ zipWith ($) sectionFunctions sections page = fromContext $ M.fromList $+ category ++ [ ("url", url) , ("path", path) ] ++ context@@ -134,6 +135,8 @@ return page where url = toURL path+ category = let dirs = splitDirectories $ takeDirectory path+ in [("category", last dirs) | not (null dirs)] -- | Read a page. Might fetch it from the cache if available. Otherwise, it will -- read it from the file given and store it in the cache.
src/Text/Hakyll/Render.hs view
@@ -71,8 +71,8 @@ renderAndConcat = renderAndConcatWith id -- | Render each renderable with the given templates, then concatenate the--- result. This function allows you to specify a "ContextManipulation" to--- apply on every "Renderable".+-- result. This function allows you to specify a @ContextManipulation@ to+-- apply on every @Renderable@. renderAndConcatWith :: Renderable a => ContextManipulation -> [FilePath]@@ -97,7 +97,7 @@ renderChain = renderChainWith id -- | A more custom render chain that allows you to specify a--- "ContextManipulation" which to apply on the context when it is read first.+-- @ContextManipulation@ which to apply on the context when it is read first. renderChainWith :: Renderable a => ContextManipulation -> [FilePath] -> a -> Hakyll () renderChainWith manipulation templatePaths renderable =
src/Text/Hakyll/Renderables.hs view
@@ -1,6 +1,8 @@ module Text.Hakyll.Renderables ( CustomPage , createCustomPage+ , createListing+ , createListingWith , PagePath , createPagePath , CombinedRenderable@@ -9,11 +11,17 @@ ) where import qualified Data.Map as M+import Control.Arrow (second)+import Control.Monad (liftM) +import Data.Binary+ import Text.Hakyll.Hakyll (Hakyll) import Text.Hakyll.Page import Text.Hakyll.Renderable import Text.Hakyll.File+import Text.Hakyll.Context+import Text.Hakyll.Render -- | A custom page. data CustomPage = CustomPage @@ -35,6 +43,46 @@ -> CustomPage createCustomPage = CustomPage +-- | A @createCustomPage@ function specialized in creating listings.+--+-- This function creates a listing of a certain list of @Renderable@s. Every+-- item in the list is created by applying the given template to every+-- renderable. You can also specify additional context to be included in the+-- @CustomPage@.+--+-- > let customPage = createListingWith +-- > "index.html" -- Destination of the page.+-- > "templates/postitem.html" -- Path to template to+-- > -- render the items with.+-- > posts -- ^ Renderables to create the list with.+-- > [("title", "Home")] -- ^ Additional context+createListing :: (Renderable a)+ => String -- ^ Destination of the page.+ -> FilePath -- ^ Template to render all items with.+ -> [a] -- ^ Renderables in the list.+ -> [(String, String)] -- ^ Additional context.+ -> CustomPage+createListing = createListingWith id++-- | A @createCustomPage@ function specialized in creating listings.+--+-- In addition to @createListing@, this function allows you to specify an+-- extra @ContextManipulation@ for all @Renderable@s given.+createListingWith :: (Renderable a)+ => ContextManipulation -- ^ Manipulation for the renderables.+ -> String -- ^ Destination of the page.+ -> FilePath -- ^ Template to render all items with.+ -> [a] -- ^ Renderables in the list.+ -> [(String, String)] -- ^ Additional context.+ -> CustomPage+createListingWith manipulation url template renderables additional =+ createCustomPage url dependencies context+ where+ dependencies = template : concatMap getDependencies renderables+ context = ("body", Right concatenation) : additional'+ concatenation = renderAndConcatWith manipulation [template] renderables+ additional' = map (second Left) additional+ instance Renderable CustomPage where getDependencies = customPageDependencies getURL = customPageURL@@ -57,20 +105,25 @@ getURL (PagePath path) = toURL path toContext (PagePath path) = readPage path >>= toContext +-- We can serialize filepaths+instance Binary PagePath where+ put (PagePath path) = put path+ get = liftM PagePath get+ -- | A combination of two other renderables. data CombinedRenderable a b = CombinedRenderable a b | CombinedRenderableWithURL FilePath a b -- | Combine two renderables. The url will always be taken from the first--- "Renderable". Also, if a `$key` is present in both renderables, the--- value from the first "Renderable" will be taken as well.+-- @Renderable@. Also, if a `$key` is present in both renderables, the+-- value from the first @Renderable@ will be taken as well. -- -- Since renderables are always more or less key-value maps, you can see -- this as a @union@ between two maps. combine :: (Renderable a, Renderable b) => a -> b -> CombinedRenderable a b combine = CombinedRenderable --- | Combine two renderables and set a custom URL. This behaves like "combine",+-- | Combine two renderables and set a custom URL. This behaves like @combine@, -- except that for the @url@ field, the given URL is always chosen. combineWithURL :: (Renderable a, Renderable b) => FilePath
src/Text/Hakyll/Tags.hs view
@@ -13,38 +13,62 @@ -- > The novel is set in a post-apocalyptic near future, where the Earth and -- > its populations have been damaged greatly by Nuclear... ----- All the following functions would work with such a format.+-- All the following functions would work with such a format. In addition to+-- tags, Hakyll also supports categories. The convention when using categories+-- is to place pages in subdirectories.+--+-- An example, the page @posts\/coding\/2010-01-28-hakyll-categories.markdown@+-- would be placed under the `coding` category.+--+-- Tags or categories are read using the @readTagMap@ and @readCategoryMap@+-- functions. Because categories are implemented using tags - categories can+-- be seen as tags, with the restriction that a page can only have one+-- category - all functions for tags also work with categories.+--+-- When reading a @TagMap@ (which is also used for category maps) using the+-- @readTagMap@ or @readCategoryMap@ function, you also have to give a unique+-- identifier to it. This identifier is simply for caching reasons, so Hakyll+-- can tell different maps apart; it has no other use. module Text.Hakyll.Tags- ( readTagMap+ ( TagMap+ , readTagMap+ , readCategoryMap , renderTagCloud , renderTagLinks ) where import qualified Data.Map as M import Data.List (intercalate)+import Data.Maybe (fromMaybe, maybeToList) import Control.Monad (foldM) import Control.Arrow (second) import Control.Applicative ((<$>))-import System.FilePath ((</>))+import System.FilePath -import Text.Hakyll.Hakyll (Hakyll)-import Text.Hakyll.Context (ContextManipulation, changeValue)+import Text.Hakyll.Hakyll+import Text.Hakyll.Context import Text.Hakyll.Regex+import Text.Hakyll.Renderable+import Text.Hakyll.Renderables import Text.Hakyll.Util-import Text.Hakyll.Page import Text.Hakyll.Internal.Cache import Text.Hakyll.Internal.Template --- | Read a tag map. This creates a map from tags to page paths.+-- | Type for a tag map. ----- You also have to give a unique identifier for every tagmap. This is for--- caching reasons, so the tagmap will be stored in--- @_cache/_tagmap/identifier@.-readTagMap :: String -- ^ Unique identifier for the tagmap.- -> [FilePath]- -> Hakyll (M.Map String [FilePath])-readTagMap identifier paths = do- isCacheMoreRecent' <- isCacheMoreRecent fileName paths+-- This is a map associating tags or categories to the appropriate pages+-- using that tag or category. In the case of categories, each path will only+-- appear under one category - this is not the case with tags.+type TagMap = M.Map String [PagePath]++-- | Read a tag map. This is a internally used function that can be used for+-- tags as well as for categories.+readMap :: (Context -> [String]) -- ^ Function to get tags from a context.+ -> String -- ^ Unique identifier for the tagmap.+ -> [PagePath]+ -> Hakyll TagMap+readMap getTagsFunction identifier paths = do+ isCacheMoreRecent' <- isCacheMoreRecent fileName (getDependencies =<< paths) if isCacheMoreRecent' then M.fromAscList <$> getFromCache fileName else do tagMap <- readTagMap' storeInCache (M.toAscList tagMap) fileName@@ -54,12 +78,28 @@ readTagMap' = foldM addPaths M.empty paths addPaths current path = do- page <- readPage path- let tags = map trim $ splitRegex "," $ getValue "tags" page- return $ foldr (flip (M.insertWith (++)) [path]) current tags+ context <- toContext path+ let tags = getTagsFunction context+ addPaths' = flip (M.insertWith (++)) [path]+ return $ foldr addPaths' current tags +-- | Read a @TagMap@, using the @tags@ metadata field.+readTagMap :: String -- ^ Unique identifier for the map.+ -> [PagePath] -- ^ Paths to get tags from.+ -> Hakyll TagMap+readTagMap = readMap getTagsFunction+ where+ getTagsFunction = map trim . splitRegex ","+ . fromMaybe [] . M.lookup "tags"++-- | Read a @TagMap@, using the subdirectories the pages are placed in.+readCategoryMap :: String -- ^ Unique identifier for the map.+ -> [PagePath] -- ^ Paths to get tags from.+ -> Hakyll TagMap+readCategoryMap = readMap $ maybeToList . M.lookup "category"+ -- | Render a tag cloud.-renderTagCloud :: M.Map String [FilePath] -- ^ Map as produced by "readTagMap".+renderTagCloud :: TagMap -- ^ Map as produced by @readTagMap@. -> (String -> String) -- ^ Function to produce an url for a tag. -> Float -- ^ Smallest font size, in percent. -> Float -- ^ Biggest font size, in percent.