hablo/src/JSON.hs

70 lines
2.2 KiB
Haskell
Raw Normal View History

2019-02-04 18:30:23 +01:00
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE NamedFieldPuns #-}
2019-01-27 21:41:21 +01:00
module JSON (
generate
) where
2019-02-04 18:30:23 +01:00
import Article (Article)
import qualified Article (Article(..))
import Blog (Blog)
import qualified Blog (Blog(..), get)
2019-01-27 21:41:21 +01:00
import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad.Reader (ReaderT, ask)
2019-02-04 18:30:23 +01:00
import Data.Aeson (ToJSON(..), genericToEncoding, defaultOptions, encode)
2019-01-27 21:41:21 +01:00
import Data.ByteString.Lazy (writeFile)
import Data.Map (Map, (!), foldlWithKey, mapKeys, mapWithKey)
import qualified Data.Map as Map (empty, filter, insert, keys)
import qualified Data.Set as Set (elems, member)
2019-02-04 18:30:23 +01:00
import System.FilePath.Posix ((</>), (<.>))
import System.Posix.Files (modificationTime)
import System.Posix.Types (EpochTime, FileID)
2019-01-27 21:41:21 +01:00
import Prelude hiding (writeFile)
2019-02-04 18:30:23 +01:00
import GHC.Generics
type ArticleID = Int
2019-02-04 18:30:23 +01:00
data ArticleExport = ArticleExport {
source :: String
, title :: String
, date :: EpochTime
, tagged :: [String]
2019-02-04 18:30:23 +01:00
} deriving (Generic)
instance ToJSON ArticleExport where
toEncoding = genericToEncoding defaultOptions
data BlogDB = BlogDB {
articles :: Map ArticleID ArticleExport
, tags :: Map String [ArticleID]
2019-02-04 18:30:23 +01:00
} deriving (Generic)
instance ToJSON BlogDB where
toEncoding = genericToEncoding defaultOptions
remap :: (Ord k1, Enum k2, Ord k2) => Map k1 a -> Map k1 k2
remap =
snd . foldlWithKey (\(i, tempMap) key _ -> (succ i, Map.insert key i tempMap)) (toEnum 0, Map.empty)
export :: Blog -> FileID -> Article -> ArticleExport
export blog fileID article = ArticleExport {
2019-02-04 18:30:23 +01:00
source = "/" </> Article.urlPath article <.> "md"
, title = Article.title article
, date = modificationTime $ Article.fileStatus article
, tagged = Map.keys . Map.filter (Set.member fileID) $ Blog.tags blog
2019-02-04 18:30:23 +01:00
}
exportBlog :: ReaderT Blog IO BlogDB
exportBlog = do
blog <- ask
let reindex = remap $ Blog.articles blog
2019-02-04 18:30:23 +01:00
return $ BlogDB {
articles = mapKeys (reindex !) $ mapWithKey (export blog) (Blog.articles blog)
, tags = fmap (reindex !) . Set.elems <$> Blog.tags blog
2019-02-04 18:30:23 +01:00
}
2019-01-27 21:41:21 +01:00
generate :: ReaderT Blog IO ()
generate = do
2019-02-04 18:30:23 +01:00
path <- Blog.get Blog.root
jsonContent <- exportBlog
liftIO $ writeFile (path </> "articles.json") (encode jsonContent)