packages feed

hakyll-series (empty) → 0.1.0.1

raw patch · 4 files changed

+205/−0 lines, 4 filesdep +basedep +containersdep +hakyllsetup-changed

Dependencies added: base, containers, hakyll

Files

+ LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2016 Oisin Kidney++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ hakyll-series.cabal view
@@ -0,0 +1,92 @@+name:               hakyll-series+version:            0.1.0.1+synopsis:           Adds series functionality to hakyll+description:+  Module for adding series functionality to hakyll.+  .+  Example <https://oisdk.github.io/hakyll-series/ here>.+  .+  In your posts, provide metadata at the top like so:+  .+  > ---+  > title: something+  > series: things+  > ---+  .+  This will add the following fields to the post:+  .+    [@series@]: The name of the series+    [@seriesLength@]: The total number of posts in the series+    [@seriesCurPos@]: The position of the current post in the series+    [@seriesUrl@]: The URL of the series page+  .+  Using that, in your post template, something like this:+  .+  >+  > $if(series)$+  >     <a href="$seriesUrl$">Part $seriesCurPos$ of a $seriesLength$-part series on $series$</a>+  > $endif$+  .+  Will render like this:+  .+  > Part 1 of a 5-part series on things+  .+  Linked to the aggregate page for the series, which would render something like this:+  .+  > Things+  > Part 1: something+  .+  To add it to your blog, add something like this to your @main@:+  .+  > series <- buildSeries "posts/*" (fromCapture "series/*.html")+  >+  > tagsRules series $ \(s:erie) pattrn -> do+  >     let title = toUpper s : erie+  >     route idRoute+  >     compile $ do+  >         posts <- chronological =<< loadAll pattrn+  >         let ctx = constField "title" title `mappend`+  >                   listField "posts" postCtx (pure posts) `mappend`+  >                   defaultContext+  >+  >         makeItem ""+  >             >>= loadAndApplyTemplate "templates/series.html" ctx+  >             >>= loadAndApplyTemplate "templates/default.html" ctx+  >             >>= relativizeUrls+  .+  To have access to the series context in each post, change the post rule to something like this:+  .+  > match "posts/*" $ do+  >     route $ setExtension "html"+  >     compile $ pandocCompiler+  >         >>= loadAndApplyTemplate "templates/post.html"    (postCtxWithSeries series)+  >         >>= loadAndApplyTemplate "templates/default.html" (postCtxWithSeries series)+  >         >>= relativizeUrls+  .+  Where `postCtxWithSeries` can be something like:+  .+  > postCtxWithSeries :: Tags -> Context String+  > postCtxWithSeries series = seriesField series `mappend` postCtx+  .+  A minimal example is provided in this repo, on top of the default hakyll setup. (it also provides the templates)+build-type:         Simple+cabal-version:      >= 1.10+homepage:           https://github.com/oisdk/hakyll-series+license:            MIT+license-file:       LICENSE+author:             Donnacha Oisín Kidney+copyright:          2016 Donnacha Oisín Kidney+maintainer:         mail@doisinkidney.com+category:           Web++library+  hs-source-dirs:   src+  exposed-modules:  Hakyll.Web.Series+  build-depends:    base == 4.*+                  , hakyll >= 4.8.0+                  , containers >= 0.5+  default-language: Haskell2010++source-repository head+  type:     git+  location: https://github.com/oisdk/hakyll-series
+ src/Hakyll/Web/Series.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE LambdaCase #-}++-- | Module for adding series functionality to a blog, similar to tags.++module Hakyll.Web.Series+  ( seriesField+  , getSeries+  , buildSeries+  ) where++import           Control.Applicative+import           Control.Arrow+import           Control.Monad+import           Data.List           (elemIndex)+import qualified Data.Map.Strict     as Map+import           Data.Monoid+import qualified Data.Set            as Set+import           Hakyll++-- | Gets the series from an identifier. Similar to 'getTags',+-- except it only accepts one series per identifier.+getSeries :: MonadMetadata m => Identifier -> m (Maybe String)+getSeries = flip getMetadataField "series"++toAlt :: (Foldable f, Alternative m) => f a -> m a+toAlt = getAlt . foldMap pure++infixr 1 >->+(>->) :: Functor f =>  (a -> f b) -> (b -> c) -> a -> f c+f >-> g = f >>> fmap g++-- | Generates four fields:+--+--    [@series@] The name of the series+--+--    [@seriesLength@] The total number of posts in the series+--+--    [@seriesCurPos@] The position of the current post in the series+--+--    [@seriesUrl@] The URL of the series page++seriesField :: Tags -> Context a+seriesField tags = Context $ const . \case+    "series"       -> seriesName+                  >-> StringField++    "seriesCurPos" -> itemIdentifier &&& otherPostsInSeries+                  >>> sequence+                  >>> fmap (uncurry elemIndex)+                  >=> toAlt+                  >-> succ+                  >>> show+                  >>> StringField++    "seriesLength" -> otherPostsInSeries+                  >-> length+                  >>> show+                  >>> StringField++    "seriesUrl"    -> seriesName+                  >=> tagsMakeId tags+                  >>> getRoute+                  >=> toAlt+                  >-> toUrl+                  >>> StringField++    _ -> const empty+  where+    seriesName = itemIdentifier+             >>> getSeries+             >=> toAlt+    otherPostsInSeries = seriesName+                     >=> flip lookup (tagsMap tags)+                     >>> toAlt++-- | Similar to the 'buildTags' function in "Hakyll.Web.Tags", except+-- checks the series field, and can only accept one series per item.+buildSeries :: MonadMetadata m+            => Pattern+            -> (String -> Identifier) -- ^ Function for converting a given series name into an identifier for its page+            -> m Tags+buildSeries pattrn makeId = do+    ids <- getMatches pattrn+    tagMap <- foldM addTags Map.empty ids+    let set' = Set.fromList ids+    inOrder <- (traverse.traverse) sortChronological (Map.assocs tagMap)+    pure $ Tags inOrder makeId (PatternDependency pattrn set')+  where+    addTags tagMap id' =+        maybe tagMap (\k -> Map.insertWith (++) k [id'] tagMap) <$> getSeries id'