hablo/src/JSON.hs

75 lines
2.3 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 (
exportBlog
2019-01-27 21:41:21 +01:00
) where
2019-02-04 18:30:23 +01:00
import Article (Article)
import qualified Article (Article(..))
import Blog (Blog)
2019-02-15 14:13:43 +01:00
import qualified Blog (Blog(..), Skin(..))
import Control.Monad.Reader (ReaderT, ask)
2019-02-04 18:30:23 +01:00
import Data.Aeson (ToJSON(..), genericToEncoding, defaultOptions, encode)
import Data.ByteString.Lazy (ByteString)
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-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
2019-02-15 14:13:43 +01:00
, metadata :: Map String String
, tagged :: [String]
2019-02-04 18:30:23 +01:00
} deriving (Generic)
instance ToJSON ArticleExport where
toEncoding = genericToEncoding defaultOptions
2019-02-15 14:13:43 +01:00
data SkinExport = SkinExport {
previewArticlesCount :: Int
, previewLinesCount :: Int
} deriving (Generic)
instance ToJSON SkinExport where
toEncoding = genericToEncoding defaultOptions
2019-02-04 18:30:23 +01:00
data BlogDB = BlogDB {
articles :: Map ArticleID ArticleExport
, tags :: Map String [ArticleID]
2019-02-15 14:13:43 +01:00
, skin :: SkinExport
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
2019-02-15 14:13:43 +01:00
, metadata = Article.metadata article
, tagged = Map.keys . Map.filter (Set.member fileID) $ Blog.tags blog
2019-02-04 18:30:23 +01:00
}
exportBlog :: ReaderT Blog IO ByteString
2019-02-04 18:30:23 +01:00
exportBlog = do
blog <- ask
let reindex = remap $ Blog.articles blog
return . encode $ BlogDB {
articles = mapKeys (reindex !) $ mapWithKey (export blog) (Blog.articles blog)
, tags = fmap (reindex !) . Set.elems <$> Blog.tags blog
2019-02-15 14:13:43 +01:00
, skin = SkinExport {
previewArticlesCount = Blog.previewArticlesCount $ Blog.skin blog
, previewLinesCount = Blog.previewLinesCount $ Blog.skin blog
}
2019-02-04 18:30:23 +01:00
}