1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
{-|
WWWStaticus is a minimalistic yet modular static website generator
first coded in April 2018 by Michal Idziorek <m.i@gmx.at>.
Last Update: Mar, 2019
-}
module WWWStaticus
( runStaticus
,staticusPluginDummy
,getDirList
,StaticusPlugin(..)
) where
import qualified Data.Map.Strict as M
import Data.Foldable
import System.Directory
import Control.Monad
import Data.Tree
import Data.Maybe
import Data.List
-- |Runs WWWStaticus given an input and an output directory and a list of
-- plugins. This traverses 'inp' recursively and runs all the plugins
-- 'one by one' in each subdirectory recursively. 'root' is the html root
-- directory used in links etc.
runStaticus :: FilePath->FilePath->FilePath->[StaticusPlugin]->IO()
runStaticus inp outp root plug= trvDirTree inp (runPlugins plug root outp)
-- |The following structure represents a single WWWStaticus plugin.
-- A plugin is defined by a Name and two functions one pure and one that
-- can do IO. The functions have to return a new map based on the input
-- map. Initially only "path" (current in path) and
-- "dir_in" (top directory) and "dir_out" are set.
-- "log" can be used for logging.
data StaticusPlugin =
StaticusPlugin String
(M.Map String String->M.Map String String)
(M.Map String String->IO (M.Map String String))
-- |Example dummy plugin
staticusPluginDummy =
StaticusPlugin "Staticus Dummy Plugin" run runIO
where run m = M.union
(M.fromList [("log",(fromJust$M.lookup "log" m)
++"dummy was here!\n")]) m
runIO m = do
print $ "I can do IO!"
return m
-- |sequence the IO Action 'f' for each subdirectory of 'fp' recursively.
-- 'f' is passed 'fp' and the currently processed path as well.
trvDirTree :: FilePath -> (FilePath ->FilePath->IO()) ->IO ()
trvDirTree fp f = unfoldTreeM unf fp >>= sequence_
where unf p = getDirList p >>= \s -> f fp p >>= \l ->
return (return l, s)
-- |get list of subdirectories
getDirList :: FilePath -> IO [FilePath]
getDirList d = map ((d++"/")++) <$> filter (not.isPrefixOf ".") <$> listDirectory d
>>= filterM doesDirectoryExist
-- |run plugins in a single directory 'path'.
-- 'dir_in' and 'dir_out' have to be provided as well, since plugins
-- might rely on this
runPlugins::[StaticusPlugin]->FilePath->FilePath->FilePath->FilePath->IO()
runPlugins plug root dir_out dir_in path = foldlM f init plug >> return ()
where f m (StaticusPlugin name run runIO) = if M.lookup "abort" m == Nothing then runIO m >>= return.run else return m
init= M.fromList [("path",path)
,("dir_in",dir_in)
,("dir_out",dir_out)
,("html_root",root)
,("log","run plugins at: "++path++"\n")]
|