🐙 Templated web page generator for your git repositories
git clone https://github.com/m-col/gitja
Files | Refs | Readme | License

Commit 8bb23c2078666e141f05f866f4284d39187e4582
Parent: cb8b9f108c9ea0a48b759534fd16d52b9cac3da9
Author: mcol <mcol@posteo.net>
Date: 2021-09-26 00:39:34 +0100
Committer: mcol <mcol@posteo.net>
Committed: 2021-09-26 16:51:51 +0100

Create html page per commit using commitTemplate setting

templates/log.html Modified

@@ -14,7 +14,7 @@
     <p>{{- description }}</p>
     <p>git clone {{ host }}/{{- name }}</p>
     {% for commit in commits[:50] %}
-    <p>{{- commit.title }}</p>
+    <p><b><a href="{{ host }}/{{ name }}/commits/{{ commit.id }}.html">{{ commit.id[:7] }}</a></b> {{ commit.title }}</p>
     {% endfor %}
   </body>
 </html>

templates/commit.html Added

@@ -0,0 +1,22 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="x-ua-compatible" content="ie=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+		<title>{{ name }} -- {{ commit.id[:7] }}</title>
+    <link rel="stylesheet" href="{{- host }}/style.css" />
+  </head>
+
+  <body>
+    <p>{{- name }}</p>
+    <hr>
+		<p>Commit <b>{{ commit.id }}</b></p>
+		<p><b>{{ commit.title }}</b></p>
+    <p>{{ commit.body }}</p>
+    <hr>
+		<p>Authored {{ commit.authored }} by: {{ commit.author }} ({{ commit.author_email }})</p>
+		<p>Committed {{ commit.committed }} by: {{ commit.committer }} ({{ commit.committer_email }})</p>
+    <hr>
+  </body>
+</html>

src/Templates.hs Modified

@@ -4,7 +4,7 @@
     Template,
     templateGinger,
     loadTemplates,
-    loadIndexTemplate,
+    loadTemplate,
     generate,
     templatePath,
 ) where
@@ -47,14 +47,12 @@
 This takes the session's `Config` and maybe returns a loaded template for the
 ``indexTemplate`` setting.
 -}
-loadIndexTemplate :: Config -> IO (Maybe Template)
-loadIndexTemplate config = parseGingerFile includeResolver file >>= \case
-    Right parsed -> return . Just . Template file $ parsed
+loadTemplate :: FilePath -> IO (Maybe Template)
+loadTemplate path = parseGingerFile includeResolver path >>= \case
+    Right parsed -> return . Just . Template path $ parsed
     Left err -> do
         print . peErrorMessage $ err
         return Nothing
-  where
-    file = indexTemplate config
 
 ----------------------------------------------------------------------------------------
 
@@ -80,7 +78,7 @@
 config settings ``indexTemplate`` or ``commitTemplate``.
 -}
 isScoped :: Config -> FilePath -> Bool
-isScoped config path = path /= (indexTemplate config) && path /= (commitTemplate config)
+isScoped config path = path /= indexTemplate config && path /= commitTemplate config
 
 {-
 This wraps getDirectoryContents so that we get a list of fully qualified paths of the
@@ -101,7 +99,7 @@
 This function gets the output HTML data and is responsible for saving it to file.
 -}
 writeTo :: FilePath -> Html -> IO ()
-writeTo path html = appendFile path . unpack . htmlSource $ html
+writeTo path = appendFile path . unpack . htmlSource
 
 {-
 This is the generator function that receives repository-specific variables and uses

src/Repositories.hs Modified

@@ -15,7 +15,7 @@
 import Data.Default (def)
 import Data.Either (fromRight)
 import Data.Tagged
-import Data.Text (pack, Text, strip, breakOn)
+import Data.Text (pack, unpack, Text, strip, breakOn)
 import Data.Maybe (mapMaybe)
 import Git
 import Git.Libgit2 (lgFactory, LgRepo)
@@ -28,7 +28,7 @@
 import Text.Ginger.Parse (SourcePos)
 import qualified Data.HashMap.Strict as HashMap
 
-import Config (Config, repoPaths, outputDirectory, host)
+import Config (Config, repoPaths, outputDirectory, host, commitTemplate)
 import Templates (Template, generate, templatePath)
 
 {-
@@ -36,10 +36,10 @@
 repositories, reading from them and writing out their web pages using the given
 templates.
 -}
-run :: Config -> [Template] -> Maybe Template -> IO ()
-run config templates index = do
-    foldMap (processRepo templates config) . repoPaths $ config
-    runIndex config index
+run :: Config -> [Template] -> Maybe Template -> Maybe Template -> IO ()
+run config templates indexT commitT = do
+    foldMap (processRepo config templates commitT) . repoPaths $ config
+    runIndex config indexT
 
 ----------------------------------------------------------------------------------------
 
@@ -48,13 +48,13 @@
 repository doesn't exist or is unreadable in any way we can forget about it and move on
 (after informing the user of course).
 -}
-processRepo :: [Template] -> Config -> FilePath -> IO ()
-processRepo templates config path = withRepository lgFactory path $
-    processRepo' templates config path
+processRepo :: Config -> [Template] -> Maybe Template -> FilePath -> IO ()
+processRepo config templates commitT path = withRepository lgFactory path $
+    processRepo' config templates commitT path
 
 -- This is split out to make type reasoning a bit easier.
-processRepo' :: [Template] -> Config -> FilePath -> ReaderT LgRepo IO ()
-processRepo' templates config path = do
+processRepo' :: Config -> [Template] -> Maybe Template -> FilePath -> ReaderT LgRepo IO ()
+processRepo' config templates commitT path = do
     let name = takeFileName path
     let output = outputDirectory config </> name
     liftIO $ createDirectoryIfMissing True output
@@ -77,6 +77,8 @@
             -- Run the generator --
             let repo = package config name description commits tree
             liftIO . mapM (generate output repo) $ templates
+            let commitScope = packageCommit config name description
+            liftIO . mapM (generateCommit config name commitScope commitT) $ commits
             return ()
 
 {-
@@ -135,6 +137,7 @@
 
 commitAsLookup :: Commit LgRepo -> Text -> Maybe (GVal m)
 commitAsLookup commit = \case
+    "id" -> Just . toGVal . renderObjOid . commitOid $ commit
     "title" -> Just . toGVal . strip . fst . breakOn "\n" . commitLog $ commit
     "body" -> Just . toGVal . strip . snd . breakOn "\n" . commitLog $ commit
     "message" -> Just . toGVal . strip . commitLog $ commit
@@ -174,8 +177,8 @@
 runIndex _ Nothing = return ()
 runIndex config (Just template) = do
     let paths = repoPaths config
-    descriptions <- sequence . fmap (getDescription . flip (</>) "description") $ paths
-    let repos = zipWith ($) (Repo <$> takeFileName <$> paths) descriptions
+    descriptions <- mapM (getDescription . flip (</>) "description") paths
+    let repos = zipWith ($) (Repo . takeFileName <$> paths) descriptions
     let indexScope = packageIndex config repos
     generate (outputDirectory config) indexScope (template { templatePath = "index.html" })
     return ()
@@ -212,3 +215,34 @@
     "name" -> Just . toGVal . repoName $ repo
     "description" -> Just . toGVal . repoDescription $ repo
     _ -> Nothing
+
+----------------------------------------------------------------------------------------
+
+generateCommit
+    :: Config
+    -> FilePath
+    -> (Commit LgRepo -> HashMap.HashMap Text (GVal (Run SourcePos IO Html)))
+    -> Maybe Template
+    -> Commit LgRepo
+    -> IO ()
+generateCommit _ _ _ Nothing _ = return ()
+generateCommit config name commitScope (Just template) commit = do
+    let id = unpack . renderObjOid . commitOid $ commit
+    let template' = template { templatePath = id ++ ".html" }
+    let output = outputDirectory config </> name </> "commits"
+    liftIO $ createDirectoryIfMissing True output
+    generate output (commitScope commit) template'
+    return ()
+
+packageCommit
+    :: Config
+    -> FilePath
+    -> Text
+    -> Commit LgRepo
+    -> HashMap.HashMap Text (GVal (Run SourcePos IO Html))
+packageCommit config name description commit = HashMap.fromList
+    [ ("host", toGVal $ host config)
+    , ("name", toGVal $ pack name)
+    , ("description", toGVal description)
+    , ("commit", toGVal commit)
+    ]

src/Main.hs Modified

@@ -4,13 +4,14 @@
     main
 ) where
 
-import Config (getConfig)
+import Config (getConfig, indexTemplate, commitTemplate)
 import Repositories (run)
-import Templates (loadTemplates, loadIndexTemplate)
+import Templates (loadTemplates, loadTemplate)
 
 main :: IO ()
 main = do
     config <- getConfig "./config.dhall"
     templates <- loadTemplates config
-    index <- loadIndexTemplate config
-    run config templates index
+    indexT <- loadTemplate $ indexTemplate config
+    commitT <- loadTemplate $ commitTemplate config
+    run config templates indexT commitT

config.dhall Modified

@@ -14,6 +14,7 @@
     { repoPaths = folders
     , templateDirectory = "./templates"
     , indexTemplate = "./templates/index-main.html"
+    , commitTemplate = "./templates/commit.html"
     , outputDirectory = "./output"
     , host = "http://localhost"
     }

README.rst Modified

@@ -33,7 +33,7 @@
 To do
 -----
 
-[ ] Generate html file per commit with commit scope
+[x] Generate html file per commit with commit scope
 [ ] Generate html file per tree file with file scope
 [ ] Expose readme url in repo scope for convenient hyperlinking
 [ ] Expose license url in repo scope for convenient hyperlinking