module Shakebook.Data where
import Control.Comonad.Cofree
import Control.Comonad.Store
import Control.Comonad.Store.Zipper
import Control.Monad.Extra
import Data.Aeson as A
import Development.Shake as S
import Development.Shake.FilePath
import RIO hiding (view)
import RIO.List
import qualified RIO.Text as T
import Slick
import Slick.Pandoc
import Shakebook.Conventions
import Shakebook.Zipper
import Text.Pandoc.Options
type ToC = Cofree [] String
readMarkdownFile' :: ReaderOptions -> WriterOptions -> String -> Action Value
readMarkdownFile' readerOptions writerOptions srcPath = do
docContent <- readFile' srcPath
docData <- markdownToHTMLWithOpts readerOptions writerOptions . T.pack $ docContent
return $ withSrcPath (T.pack srcPath) docData
loadIfExists :: (FilePath -> Action Value) -> FilePath -> Action Value
loadIfExists f src = ifM (S.doesFileExist src) (f src) (return (Object mempty))
getDirectoryMarkdown :: ReaderOptions -> WriterOptions -> FilePath -> [FilePattern] -> Action [Value]
getDirectoryMarkdown readOpts writeOpts dir pat = do
getDirectoryFiles dir pat >>= mapM (readMarkdownFile' readOpts writeOpts . (dir </>))
getEnrichedMarkdown :: ReaderOptions -> WriterOptions -> (Value -> Value) -> FilePath -> [FilePattern] -> Action [Value]
getEnrichedMarkdown readOpts writeOpts f dir pat = fmap f <$> getDirectoryMarkdown readOpts writeOpts dir pat
genBuildPageAction :: FilePath
-> (FilePath -> Action Value)
-> (Value -> Value)
-> FilePath
-> Action Value
genBuildPageAction template getData withData out = do
pageT <- compileTemplate' template
dataT <- withData <$> getData out
writeFile' out . T.unpack $ substitute pageT dataT
return dataT
genIndexPageData :: [Value]
-> Text
-> (Text -> Text)
-> Int
-> Maybe (Zipper [] Value)
genIndexPageData xs g h n = fmap (extend (genPageData g h)) $ paginate n xs
traverseToSnd :: Functor f => (a -> f b) -> a -> f (a, b)
traverseToSnd f a = (a,) <$> f a
lower :: Cofree [] Value -> [Value]
lower (_ :< xs) = extract <$> xs
data SbConfig = SbConfig {
sbSrcDir :: FilePath
, sbOutDir :: FilePath
, sbBaseUrl :: Text
, sbMdRead :: ReaderOptions
, sbHTWrite :: WriterOptions
, sbPPP :: Int
} deriving (Show)
newtype Shakebook a = Shakebook ( ReaderT SbConfig Rules a )
deriving (Functor, Applicative, Monad, MonadReader SbConfig)
newtype ShakebookA a = ShakebookA ( ReaderT SbConfig Action a )
deriving (Functor, Applicative, Monad, MonadReader SbConfig)
runShakebook :: SbConfig -> Shakebook a -> Rules a
runShakebook c (Shakebook f) = runReaderT f c
runShakebookA :: SbConfig -> ShakebookA a -> Action a
runShakebookA c (ShakebookA f) = runReaderT f c
loadSortFilterEnrich :: Ord b => [FilePattern]
-> (Value -> b)
-> (Value -> Bool)
-> (Value -> Value)
-> ShakebookA [(String, Value)]
loadSortFilterEnrich pat s f e = ShakebookA $ ask >>= \SbConfig {..} -> lift $ do
allPosts <- getDirectoryFiles sbSrcDir $ map (-<.> ".md") pat
readPosts <- sequence $ traverseToSnd (readMarkdownFile' sbMdRead sbHTWrite . (sbSrcDir </>)) <$> allPosts
return $ fmap (second e) $ sortOn (s . snd) $ filter (f . snd) $ readPosts
loadSortEnrich :: Ord b => [FilePattern] -> (Value -> b) -> (Value -> Value) -> ShakebookA [(String, Value)]
loadSortEnrich pat s e = loadSortFilterEnrich pat s (const True) e