-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathShakefile.hs
More file actions
331 lines (296 loc) · 14 KB
/
Shakefile.hs
File metadata and controls
331 lines (296 loc) · 14 KB
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
-- Shakefile Stuff
import Development.Shake
import Development.Shake.FilePath
import Text.Regex
import qualified Data.Text as T
import qualified Data.Text.Lazy as LT
import qualified Data.Text.Lazy.IO as LTIO
import Data.Text.ICU (regex, Regex)
-- import Data.Text.Lazy as TL
import qualified Data.Text.IO as TIO
import qualified Data.Text.ICU.Replace as TR
-- Server stuff
import Network.Wai.Application.Static (defaultFileServerSettings, ssListing, staticApp)
import qualified Network.Wai.Handler.Warp as Warp
import WaiAppStatic.Types (StaticSettings)
import Main.Utf8 (withUtf8)
import Lucid
import Template ( pageHtml, prefatoryPageHtml, includeHtml )
import Text.HTML.TagSoup
import Text.StringLike ( StringLike )
import Data.Maybe (fromMaybe)
readFileText text = need [text] >> liftIO (TIO.readFile text)
-- | Convert "00-introduction/introduction-v01.org" to "dest/00-introduction/introduction-v01.html"
sourceToDest :: FilePath -> FilePath
sourceToDest fp = "dest/" </> fp <.> "html"
-- | Convert "00-introduction/introduction-v01.org" to "dest/00-introduction/introduction-v01.html"
destToSource :: FilePath -> FilePath
destToSource fp = dropDirectory1 $ fp -<.> "org"
chapters :: [FilePath]
chapters =
[ "dest/00-introduction/introduction-v01.html",
"dest/01-colors/ch-1-v01.html",
"dest/02-shapes/ch-2-v01.html",
"dest/03-images/ch-3-v01.html"
]
main :: IO ()
main = withUtf8 $ shakeArgs shakeOptions{shakeColor=True} $ do
want ( "dest/index.html" : chapters )
-- To serve the generated files (useful for previewing),
-- run `shake serve`.
phony "serve" $
liftIO $ serve 8080 "dest/"
-- Regenerate references bibtex file, but only if we're me, not GitHub Actions.
"references.bib" %> \f -> do
let sources = [ "/home/jon/Dokumentujo/Papers/library.bib"
, "/home/jon/Dokumentujo/Papers/library2.bib"
]
user <- getEnv "USERNAME"
let username = fromMaybe "" user
if username == "jon" then do
need sources
Stdout stdout <- cmd "cat" sources
writeFileChanged f stdout
else putInfo "We're in CI. Skipping regeneration of references."
-- Automatically generate a list of figures and illustrations.
"templates/figures.html" %> \f -> do
need chapters
liftIO $ findAllFigures f
let bib = "references.bib"
csl = "templates/modern-language-association.csl"
template = "templates/template.html"
prefatoryTemplate = "templates/prefatoryTemplate.html"
figuresList = "templates/figures.html"
"templates/template.html" %> \f -> do
need ["Template.hs"]
liftIO $ renderToFile f pageHtml
"templates/prefatoryTemplate.html" %> \f -> do
need ["Template.hs"]
liftIO $ renderToFile f prefatoryPageHtml
"dest/index.html" %> \f -> do
let source = destToSource f
need [ source, template, prefatoryTemplate, figuresList ]
contents <- liftIO $ readFile source
cmd (Stdin contents) "pandoc" ["-f", "org+smart",
"--template", prefatoryTemplate,
"--standalone",
"--section-divs",
"--variable=autoSectionLabels:true",
"-o", f
]
["dest//images/*", "dest//includes/*.js", "dest/assets/**"] |%> \f -> do
let source = dropDirectory1 f
need [source]
copyFileChanged source f
"dest//includes/*.html" %> \f -> do
-- wrap exported includes in HTML so they can be displayed on their own
let source = dropDirectory1 f
need [source]
contents <- readFileText source
let wrapped = includeHtml contents
writeFileChanged f $ T.unpack $ LT.toStrict $ Lucid.renderText wrapped
"dest/00-introduction/introduction-v01.html" %> \f -> do
assets <- getDirectoryFiles "" [ "00-introduction/images/*"
, "assets//*"
]
let outAssets = map ("dest/" <>) assets
let source = destToSource f
need ([ source, prefatoryTemplate, csl, bib ] ++ outAssets)
contents <- readFileText source
let replaced = T.unpack contents
cmd (Stdin replaced) "pandoc" ["-f", "org+smart",
"--template", template,
"--standalone",
"--section-divs",
"--reference-location=block",
"--csl=" ++ csl,
"--variable=autoSectionLabels:true",
"--toc",
"--metadata=tblPrefix:table",
"--metadata=linkReferences:true",
"--metadata=link-citations:true",
"--filter=templates/PandocSidenote.hs",
"--filter=pandoc-crossref",
"--citeproc",
"--mathjax",
"--bibliography", bib,
"-o", f
]
"dest/01-colors/ch-1-v01.html" %> \f -> do
assets <- getDirectoryFiles "" [ "01-colors/images/*"
, "01-colors/includes/*"
, "assets/*/*" -- Global assets
]
liftIO $ print assets
let source = destToSource f
let outAssets = map ("dest/" <>) assets
filters = [ "templates/PandocSidenote.hs"
, "templates/hexFilter.hs"
]
need ([ source, template, csl, bib ]
++ outAssets
++ filters)
contents <- readFileText source
let replaced = T.unpack contents
cmd (Stdin replaced) "pandoc" ["-f", "org+smart",
"--template", template,
"--standalone",
"--section-divs",
"--reference-location=block",
"--csl=" ++ csl,
"--toc",
"--variable=autoSectionLabels:true",
"--metadata=linkReferences:true",
"--metadata=link-citations:true",
"--metadata=tblPrefix:table",
"--citation-abbreviations=01-colors/abbreviations.json",
"--filter=templates/PandocSidenote.hs",
"--filter=pandoc-crossref",
"--citeproc",
"--filter=templates/hexFilter.hs",
"--mathjax",
"--bibliography", bib,
"-o", f
]
"dest/02-shapes/ch-2-v01.html" %> \f -> do
assets <- getDirectoryFiles "" [ "02-shapes/images/*"
, "02-shapes/includes/*"
, "assets/*/*"
]
liftIO $ print assets
let outAssets = map ("dest/" <>) assets
let source = destToSource f
filters = [ "templates/PandocSidenote.hs"
, "templates/synsetFilter.hs"
]
need ([ source, template, csl, bib ]
++ outAssets
++ filters)
contents <- readFileText source
let replaced = T.unpack contents
cmd (Stdin replaced) "pandoc" ["-f", "org+smart",
"--template", template,
"--standalone",
"--section-divs",
"--reference-location=block",
"--csl=" ++ csl,
"--toc",
"--variable=autoSectionLabels:true",
"--metadata=linkReferences:true",
"--metadata=link-citations:true",
"--metadata=tblPrefix:table",
"--filter=templates/PandocSidenote.hs",
"--filter=pandoc-crossref",
"--citeproc",
"--filter=templates/synsetFilter.hs",
"--mathjax",
"--bibliography", bib,
"-o", f
]
"dest/03-images/ch-3-v01.html" %> \f -> do
assets <- getDirectoryFiles "" [ "03-images/images/*"
, "assets/*/*"
, "03-images/includes/*"
]
let outAssets = map ("dest/" <>) assets
liftIO $ print outAssets
let source = destToSource f
filters = [ "templates/PandocSidenote.hs"
, "templates/synsetFilter.hs"
]
need ([ source, template, csl, bib ]
++ outAssets
++ filters)
contents <- readFileText source
let replaced = T.unpack contents
cmd (Stdin replaced) "pandoc" ["-f", "org+smart",
"--template", template,
"--standalone",
"--section-divs",
"--reference-location=block",
"--csl=" ++ csl,
"--toc",
"--variable=autoSectionLabels:true",
"--metadata=linkReferences:true",
"--metadata=link-citations:true",
"--metadata=tblPrefix:table",
"--filter=templates/PandocSidenote.hs",
"--filter=pandoc-crossref",
"--citeproc",
"--filter=templates/synsetFilter.hs",
"--mathjax",
"--bibliography", bib,
"-o", f
]
-- | WAI Settings suited for serving statically generated websites.
staticSiteServerSettings :: FilePath -> StaticSettings
staticSiteServerSettings root =
defaultSettings
-- Disable directory listings
{ ssListing = Nothing }
where
defaultSettings = defaultFileServerSettings root
-- | Run a HTTP server to serve a directory of static files
serve ::
-- | Port number to bind to
Int ->
-- | Directory to serve.
FilePath ->
IO ()
serve port path = do
putStrLn $ "Serving at http://localhost:" <> show port
Warp.run port $ staticApp $ staticSiteServerSettings path
-- | Automatically find figures and generate a list of chapters with their figures.
type HtmlString = String
type TagName = String
type FigureTags = [Tag String]
data ChapterFigures = ChapterFigures {
chapterPath :: FilePath,
chapterTitle :: String,
figures :: [Figure]
} deriving Show
data Figure = Figure {
figCaption :: String,
figId :: String
} deriving Show
-- | Scrape HTML for some tag, but preserve the inner HTML
innerHtml :: TagName -> HtmlString -> [HtmlString]
innerHtml tagName rawText = let
tag = "<" ++ tagName ++ ">"
unTag = "</" ++ tagName ++ ">" in
map (renderTags . takeWhile (~/= unTag) . tail) $
sections (~== tag) $ parseTags rawText
getFigures :: HtmlString -> [FigureTags]
getFigures fileContents = map (takeWhile (~/= "</figure>")) $
sections (~== "<figure>") $ parseTags fileContents
-- | Gets chapter names and figures for each chapter
-- Storing them in structured data
getChapterFigures :: (FilePath, HtmlString) -> ChapterFigures
getChapterFigures (path, fileContents) = ChapterFigures path title figs where
title = head $ innerHtml "title" fileContents
figs = map figuresData $ getFigures fileContents
-- Takes parsed Html (Tags list) and returns structured data Figure
figuresData :: FigureTags -> Figure
figuresData figTags = Figure (figureCaption figTags) (figureId figTags) where
figureId fig = fromAttrib "id" $ head $ filter (~== "<img>") fig
figureCaption fig = renderTags $ takeWhile (~/= "</figcaption>") $ tail $ dropWhile (~/= "<figcaption>") fig
-- | Takes structured data about chapters and figures and returns HTML formatted text
formatChapterFigures :: ChapterFigures -> LT.Text
formatChapterFigures cf = Lucid.renderText $ ul_ $ title >> figs where
title = li_ $ toHtml $ chapterTitle cf
path = chapterPath cf
figs = ul_ $ mconcat $ map formatFigure $ figures cf where
formatFigure :: Figure -> Lucid.Html ()
formatFigure fig = li_ $ a_ [href_ url] caption where
caption = toHtmlRaw $ figCaption fig
url = T.pack $
drop 5 $ -- Remove "dest/"
path ++ "#" ++ figId fig
-- | The main IO function for reading all the chapters and finding all the figures
findAllFigures :: FilePath -> IO ()
findAllFigures fn = do
fileContents <- mapM readFile chapters
let pathsAndContents = zip chapters fileContents
let chapterFigures = map getChapterFigures pathsAndContents
let chapterFiguresFormatted = map formatChapterFigures chapterFigures
LTIO.writeFile fn $ LT.concat chapterFiguresFormatted