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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE RecordWildCards #-}
-- | Separated-out main types of the deployment scriptage.
module Types where
import Control.Monad.Trans.State.Lazy
import Data.List.NonEmpty
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.Yaml as Y
import Lens.Micro.TH
import Options.Applicative
import qualified Text.Mustache as Mu
import qualified Text.Pandoc.Definition
-- | Information about a single deployed page (with metadata etc).
data PageInfo =
PageInfo
{ _pagePath :: FilePath -- ^ original path to the markdown file
, _pageMeta :: Y.Value -- ^ YAML metadata extracted from the file
, _pageDoc :: Text.Pandoc.Definition.Pandoc -- ^ Page data
}
deriving (Show)
makeLenses ''PageInfo
-- | Complete internal state of the deployment process that holds all data
data SiteState =
SiteState
-- | Map of page mounts to `PageInfo`
{ _pages :: M.Map FilePath PageInfo
-- | Map of redirects (from -> to)
, _redirects :: M.Map FilePath FilePath
-- | Map of tags, assigning to each tag sequence a list of
-- tagged page mounts
, _htags :: M.Map [String] [FilePath]
-- | Map of tags, assigning to each tag sequence a list of tagged page
-- mounts. This one is expanded (tags imply parent categories).
, _ehtags :: M.Map [String] [FilePath]
-- | Map of "short" tags to expanded human-friendly names
, _tagNames :: M.Map String String
-- | List of installed files (enables sharing)
, _installs :: S.Set (String, FilePath)
-- | List of installed files (prevents overwriting)
, _targets :: S.Set FilePath
-- | Map of Mustache templates organized by template search path (within
-- the template directory)
, _templates :: M.Map FilePath Mu.Template
, _outputDir :: FilePath -- ^ Directory for output
, _searchDataOut :: Maybe FilePath -- ^ File to write the searchable versions of pages to (as JSON)
, _assetDir :: FilePath -- ^ Directory for output
, _sourceDirs :: [FilePath] -- ^ Path to page source data
, _notSourceDirs :: [FilePath] -- ^ Subdirectories of source dirs where pages should not be sourced
, _templateDir :: FilePath -- ^ Path to template directory
, _defaultTemplate :: FilePath -- ^ Name of the default template
, _redirectTemplate :: FilePath -- ^ Name of the template for redirect pages
, _tagTemplate :: FilePath -- ^ Name of the template for category pages
, _listTemplate :: FilePath -- ^ Name of the template for listing pages
, _urlBase :: FilePath -- ^ "Root route" to prepend to all absolute links.
, _dumpFinalState :: Bool -- ^ Triggers printing out the structure when the processing finishes.
}
deriving (Show)
makeLenses ''SiteState
-- | Monad for running the site generator.
type Site a = StateT SiteState IO a
-- | Parser for commandline options
siteOptions' :: Parser SiteState
siteOptions' = do
_outputDir <-
strOption $
long "output" <>
short 'd' <>
help "Directory to render the site to" <> value "_site" <> showDefault
_searchDataOut <-
Just <$>
(strOption $
long "search-data-output" <>
help "Output JSON with searchable page data to this file") <|>
pure Nothing
_assetDir <-
strOption $
long "assets" <>
short 'a' <>
help "Assets directory to be copied verbatim" <>
value "assets" <> showDefault
_sourceDirs <-
fmap (maybe ["cards"] toList . nonEmpty) . many . strOption $
long "source-directory" <>
short 's' <>
help
"Path to the directory with source data (possibly multiple paths, defaults to a single directory \"cards\")"
_notSourceDirs <-
fmap (maybe ["assets"] toList . nonEmpty) . many . strOption $
long "exclude-source-directory" <>
help
"Names of subdirectories of the sources that should never be used for sourcing pages (possibly multiple directory names, defaults to a single directory \"assets\")"
_templateDir <-
strOption $
long "template-directory" <>
help "Path to the directory with templates" <>
value "templates" <> showDefault
_defaultTemplate <-
strOption $
long "default-template" <>
help "Default template to use for stuff (found in templates directory)" <>
value "default.html" <> showDefault
_redirectTemplate <-
strOption $
long "redirect-template" <>
help "Template for making redirect pages" <>
value "redirect.html" <> showDefault
_tagTemplate <-
strOption $
long "tag-template" <>
help "Template for making category view pages" <>
value "tag.html" <> showDefault
_listTemplate <-
strOption $
long "list-template" <>
help "Template for making tag-listing pages" <>
value "list.html" <> showDefault
_urlBase <-
strOption $
long "url-base" <>
short 'u' <> help "Base absolute URL" <> value "/" <> showDefault
_dumpFinalState <-
switch $
long "dump-state" <>
short 'D' <>
help "Print out the complete internal state after the site is built"
pure
SiteState
{ _pages = M.empty
, _redirects = M.empty
, _htags = M.empty
, _ehtags = M.empty
, _tagNames = M.empty
, _installs = S.empty
, _targets = S.empty
, _templates = M.empty
, ..
}
-- | ParserInfo for commandline options
siteOptions =
info
(siteOptions' <**> helper)
(fullDesc <>
progDesc "Build a R3 Cards-like site" <>
header "site - the R3 site builder")
|