shakebook 0.5.0.0 → 0.5.1.0
raw patch · 4 files changed
+27/−43 lines, 4 filesdep −hashable-timedep −ixset-typed
Dependencies removed: hashable-time, ixset-typed
Files
- ChangeLog.md +5/−0
- shakebook.cabal +2/−5
- src/Shakebook/Conventions.hs +13/−24
- test/Spec.hs +7/−14
ChangeLog.md view
@@ -1,5 +1,10 @@ # Changelog for Shakebook +## (v0.5.1.0)++* Add `tagIndex` and `monthIndex` instead of filter and partition functions.+* Drop `hashable-time` dependency.+ ## (v0.5.0.0) * Upgrade to [shake-plus](https://hackage.haskell.org/package/shake-plus) v0.1.6.0.
shakebook.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 166b471f6106f0f5cbd0ce94e44b3042fb7f4d1b5da4deed5e14c7aea3195b8c+-- hash: f5bb0ca4ec7dfb075bca03025667a052ba4df3ca169c5d2746369855586f78fd name: shakebook-version: 0.5.0.0+version: 0.5.1.0 synopsis: Shake-based technical documentation generator; HTML & PDF description: Shakebook is a documentation generator aimed at covering all the bases for mathematical, technical and scientific diagrams and typesetting. Shakebook provides combinators for taking markdown files and combining them into documents, but allowing the user to control how. Shakebook provides general combinators for templating single pages, cofree comonads for representing tables of contents, and zipper comonads for representing pagers. category: Web@@ -45,7 +45,6 @@ , doctemplates , feed , free- , ixset-typed , lens , lens-aeson , mustache@@ -79,8 +78,6 @@ , doctemplates , feed , free- , hashable-time- , ixset-typed , lens , lens-aeson , mustache
src/Shakebook/Conventions.hs view
@@ -44,9 +44,8 @@ , genTocNavbarData , dateSortPosts-, monthFilterPosts-, sameMonth-, tagFilterPosts+, monthIndex+, tagIndex ) where import Control.Comonad.Cofree@@ -58,6 +57,7 @@ import Data.Aeson.With import Data.Text.Time import RIO hiding (view)+import qualified RIO.HashMap as HM import RIO.List import RIO.List.Partial import qualified RIO.Text as T@@ -181,29 +181,18 @@ genLinkData :: Text -> Text -> Value genLinkData x u = object ["id" A..= String x, "url" A..= String u] --- | Filter a lists of posts by tag.-tagFilterPosts :: Text -> [Value] -> [Value]-tagFilterPosts tag = filter (elem tag . viewTags)+-- | Create a `HashMap` of posts indexed by tag.+tagIndex :: [Value] -> HashMap Text [Value]+tagIndex xs = HM.fromList [(t, filter (elem t . viewTags) xs) | t <- viewAllPostTags xs] +-- | Create a `HashMap` of posts indexed by year-month..+monthIndex :: [Value] -> HashMap Text [Value]+monthIndex xs = HM.fromList [(t, filter ((== t) . T.pack . formatTime defaultTimeLocale "%Y-%m" . viewPostTime) xs) | t <- nub (T.pack . formatTime defaultTimeLocale "%Y-%m" <$> viewAllPostTimes xs)]+ -- | Sort a lists of posts by date. dateSortPosts :: [Value] -> [Value] dateSortPosts = sortOn (Down . viewPostTime) --- | Check whether two posts were posted in the same month.-sameMonth :: UTCTime -> UTCTime -> Bool-sameMonth a b = y1 == y2 && m1 == m2 where- (y1, m1, _) = f a- (y2, m2, _) = f b- f = toGregorian . utctDay--monthFilterPosts :: UTCTime -> [Value] -> [Value]-monthFilterPosts time = filter (sameMonth time . viewPostTime)----- | Partition a list of posts by the month they were posted.-partitionToMonths :: [Value] -> [[Value]]-partitionToMonths = groupBy (on sameMonth viewPostTime) . dateSortPosts- -- | Create a blog navbar object for a posts section, with layers "toc1", "toc2", and "toc3". genBlogNavbarData :: Text -- ^ "Top level title, e.g "Blog" -> Text -- ^ Root page, e.g "/posts"@@ -214,12 +203,12 @@ genBlogNavbarData a b f g xs = object [ "toc1" A..= object [ "title" A..= String a , "url" A..= String b- , "toc2" A..= Array (V.fromList $ map toc2 (partitionToMonths xs)) ]+ , "toc2" A..= Array (V.fromList $ map toc2 (HM.elems $ monthIndex xs)) ] ] where toc2 [] = object [] toc2 t@(x : _) = object [ "title" A..= String (f (viewPostTime x))- , "url" A..= String (g (viewPostTime x))- , "toc3" A..= Array (V.fromList t) ]+ , "url" A..= String (g (viewPostTime x))+ , "toc3" A..= Array (V.fromList t) ] -- | Create a toc navbar object for a docs section, with layers "toc1", "toc2" and "toc3". genTocNavbarData :: Cofree [] Value -> Value
test/Spec.hs view
@@ -2,7 +2,6 @@ import Control.Lens hiding ((:<)) import Data.Aeson.With-import Data.Hashable.Time() import Data.List.Split import Data.Text.Time import Path.Extensions@@ -86,22 +85,16 @@ blogTagIndexPageData <- newCache $ \fp -> do xs <- sortedPosts fp- zs <- forM (viewAllPostTags (snd <$> xs)) $ \t -> do- let ys = filter (elem t . viewTags . snd) xs- k <- genIndexPageData (snd <$> ys) ("Posts tagged " <> t) (("/posts/tags/" <> t <> "/pages/") <>) postsPerPage- return (t, k)- return $ HM.fromList zs+ flip HM.traverseWithKey (tagIndex (snd <$> xs)) $ \t ys ->+ genIndexPageData ys ("Posts tagged " <> t) (("/posts/tags/" <> t <> "/pages/") <>) postsPerPage blogMonthIndexPageData <- newCache $ \fp -> do xs <- sortedPosts fp- zs <- forM (nub $ defaultMonthUrlFormat <$> viewAllPostTimes (snd <$> xs)) $ \t -> do- let t' = parseISODateTime . T.pack $ t- let ys = filter (sameMonth t' . viewPostTime . snd) xs- k <- genIndexPageData (snd <$> ys)+ flip HM.traverseWithKey (monthIndex (snd <$> xs)) $ \t ys ->+ let t' = parseISODateTime t+ in genIndexPageData ys (("Posts from " <>) . T.pack . defaultPrettyMonthFormat $ t') (("/posts/months/" <> T.pack (defaultMonthUrlFormat t') <> "/pages/") <>) postsPerPage- return (t', k)- return $ HM.fromList zs let myPosts = ["posts/*.md"] `within` sourceFolder @@ -172,7 +165,7 @@ copyFileChangedWithin (o' i) out o' "posts/months/*/pages/*/index.html" %^> \out -> do- let t = parseISODateTime . T.pack . (!! 2) . splitOn "/" . toFilePath . extract $ out+ let t = T.pack . (!! 2) . splitOn "/" . toFilePath . extract $ out let n = (+ (-1)) . read . (!! 4) . splitOn "/" . toFilePath . extract $ out xs <- blogMonthIndexPageData myPosts case HM.lookup t xs of@@ -205,7 +198,7 @@ phony "by-month-index" $ do ps <- blogMonthIndexPageData myPosts void $ flip HM.traverseWithKey ps $ \t z -> do- u <- parseRelDir $ defaultMonthUrlFormat t+ u <- parseRelDir $ T.unpack t fs <- defaultPagePaths [1..size z] let monthFolder = outputFolder </> $(mkRelDir "posts/months") </> u needIn monthFolder ($(mkRelFile "index.html") : fs)