2020-09-25 23:45:58 +00:00
|
|
|
module Projects (build) where
|
|
|
|
|
2020-09-27 13:49:45 +00:00
|
|
|
import Lucid
|
2021-11-10 23:30:10 +00:00
|
|
|
import Data.Char (digitToInt, isDigit)
|
2020-09-27 13:49:45 +00:00
|
|
|
import qualified Data.Map.Strict as Map
|
2021-11-10 23:30:10 +00:00
|
|
|
import Control.Monad (unless)
|
2020-09-25 23:45:58 +00:00
|
|
|
|
|
|
|
import Common
|
2021-03-17 20:49:22 +00:00
|
|
|
import Route
|
2020-09-25 23:45:58 +00:00
|
|
|
import Types
|
|
|
|
import Config
|
|
|
|
import Templates
|
|
|
|
|
2021-11-10 23:30:10 +00:00
|
|
|
data Project = Project
|
2020-09-27 13:49:45 +00:00
|
|
|
{ title :: Text
|
|
|
|
, subtitle :: Text
|
|
|
|
, year :: Text
|
|
|
|
, labels :: Map.Map Text Text
|
|
|
|
} deriving (Generic, Eq, FromJSON, Binary)
|
2020-09-25 23:45:58 +00:00
|
|
|
|
2020-09-27 13:49:45 +00:00
|
|
|
|
|
|
|
build :: Task IO ()
|
|
|
|
build = do
|
|
|
|
projects <- matchDir "projects/*/" buildProject
|
|
|
|
|
2020-10-07 19:25:29 +00:00
|
|
|
watch projects $ match_ "./projects.rst" \src -> do
|
|
|
|
intro <- compilePandocWith def wopts src
|
2020-09-27 13:49:45 +00:00
|
|
|
write "projects.html" (renderIndex intro projects)
|
2020-09-25 23:45:58 +00:00
|
|
|
|
|
|
|
|
2022-12-06 19:59:09 +00:00
|
|
|
buildProject :: FilePath -> Task IO (Project, Text, FilePath)
|
2020-10-07 19:25:29 +00:00
|
|
|
buildProject src = do
|
2020-09-25 23:45:58 +00:00
|
|
|
match "*" copyFile
|
|
|
|
|
|
|
|
name <- takeBaseName <$> getCurrentDir
|
|
|
|
children <- buildChildren name
|
|
|
|
|
2022-12-06 19:59:09 +00:00
|
|
|
icon <- matchFile "logo.svg" readText
|
|
|
|
|
|
|
|
watch children $ watch icon $ matchFile "index.*" \src -> do
|
2020-10-07 19:25:29 +00:00
|
|
|
(meta, doc) <- readPandocMetadataWith ropts src
|
2020-09-27 13:49:45 +00:00
|
|
|
|
|
|
|
renderPandocWith wopts doc
|
2024-02-15 17:56:40 +00:00
|
|
|
<&> renderProject meta icon children
|
|
|
|
>>= write (src -<.> "html")
|
|
|
|
|
|
|
|
pure (meta, icon, "/projects" </> name <> "/")
|
2020-09-27 13:49:45 +00:00
|
|
|
|
2020-09-25 23:45:58 +00:00
|
|
|
where
|
2020-10-07 19:25:29 +00:00
|
|
|
buildChildren :: String -> Task IO [(Text, FilePath)]
|
|
|
|
buildChildren name = match "pages/*" \filepath -> do
|
2020-09-25 23:45:58 +00:00
|
|
|
let (key, file) = getKey $ takeFileName filepath
|
2020-10-07 19:25:29 +00:00
|
|
|
(TitledPage title _, doc) <- readPandocMetadataWith ropts filepath
|
2020-09-25 23:45:58 +00:00
|
|
|
renderPandocWith wopts doc
|
2020-09-26 23:33:50 +00:00
|
|
|
<&> toHtmlRaw
|
2021-03-17 20:49:22 +00:00
|
|
|
<&> outerWith (def { Config.title = title
|
|
|
|
, Config.route = ProjectPageRoute title (ProjectRoute $ fromString name)
|
|
|
|
})
|
2020-10-07 19:25:29 +00:00
|
|
|
>>= write (filepath -<.> "html")
|
2020-09-25 23:45:58 +00:00
|
|
|
<&> (title,)
|
|
|
|
|
|
|
|
|
2022-12-06 19:59:09 +00:00
|
|
|
renderProject :: Project -> Text -> [(Text, FilePath)] -> Text -> Html ()
|
|
|
|
renderProject Project{..} logo children content =
|
2020-09-27 13:49:45 +00:00
|
|
|
outerWith def { Config.title = title
|
|
|
|
, Config.description = subtitle
|
2021-03-17 20:49:22 +00:00
|
|
|
, Config.route = ProjectRoute title
|
2020-09-27 13:49:45 +00:00
|
|
|
} do
|
|
|
|
header_ [class_ "project"] do
|
2022-12-06 19:59:09 +00:00
|
|
|
div_ (toHtmlRaw logo)
|
2020-09-27 13:49:45 +00:00
|
|
|
div_ do
|
|
|
|
h1_ (toHtml title)
|
|
|
|
p_ (toHtml subtitle)
|
|
|
|
ul_ $ forM_ (Map.toList labels) \(k, v) -> li_ do
|
|
|
|
toHtml k <> ": "
|
|
|
|
if k == "repo" then
|
|
|
|
a_ [href_ $ "https://github.com/" <> v]
|
|
|
|
$ toHtml v
|
|
|
|
else toHtml v
|
2021-11-10 23:30:10 +00:00
|
|
|
unless (null children) $
|
2020-09-27 13:49:45 +00:00
|
|
|
ol_ [class_ "pages"] $ forM_ children \(title, path) ->
|
|
|
|
li_ $ a_ [href_ (fromString path)] (toHtml title)
|
|
|
|
toHtmlRaw content
|
2020-09-25 23:45:58 +00:00
|
|
|
|
|
|
|
|
2022-12-06 19:59:09 +00:00
|
|
|
renderIndex :: Text -> [(Project, Text, FilePath)] -> Html ()
|
2020-09-27 13:49:45 +00:00
|
|
|
renderIndex intro projects =
|
|
|
|
outerWith def { Config.title = "projects"
|
|
|
|
, Config.description = intro
|
|
|
|
} do
|
|
|
|
toHtmlRaw intro
|
|
|
|
ul_ [class_ "projects"] $ forM_ projects projectLink
|
|
|
|
where
|
2022-12-06 19:59:09 +00:00
|
|
|
projectLink :: (Project, Text, FilePath) -> Html ()
|
|
|
|
projectLink (Project{..}, logo, path) =
|
2020-09-27 13:49:45 +00:00
|
|
|
li_ $ a_ [href_ (fromString path)] do
|
2022-12-06 19:59:09 +00:00
|
|
|
div_ $ toHtmlRaw logo
|
2020-09-27 13:49:45 +00:00
|
|
|
div_ $ h2_ (toHtml title) >> p_ (toHtml subtitle)
|
2020-09-25 23:45:58 +00:00
|
|
|
|
2020-09-27 13:49:45 +00:00
|
|
|
|
|
|
|
getKey :: String -> (Int, String)
|
|
|
|
getKey xs = getKey' 0 xs
|
|
|
|
where
|
|
|
|
getKey' :: Int -> String -> (Int, String)
|
2021-11-10 23:30:10 +00:00
|
|
|
getKey' k (x : xs) | isDigit x =
|
2020-09-27 13:49:45 +00:00
|
|
|
getKey' (k * 10 + digitToInt x) xs
|
|
|
|
getKey' k ('-' : xs) = (k, xs)
|
|
|
|
getKey' k xs = (k, xs)
|