diff --git a/Gupfile b/Gupfile
new file mode 100644
index 0000000..6902472
--- /dev/null
+++ b/Gupfile
@@ -0,0 +1,2 @@
+checksum.gup:
+ **/.*.chksum
diff --git a/checksum.gup b/checksum.gup
new file mode 100644
index 0000000..c27edd6
--- /dev/null
+++ b/checksum.gup
@@ -0,0 +1,14 @@
+#!/usr/bin/env zsh
+
+gup --always
+base=${2:t}
+base=${base#"."}
+base=${base%".chksum"}
+base=${2:h}/${base}
+while IFS= read -d $'\0' file; do
+ if [[ -f "${file}" ]]; then
+ b2sum "${file}"
+ else
+ echo "${file}"
+ fi
+done > >(gup --contents) < <(find "${base}" -print0)
diff --git a/content/markdown.md b/content/markdown.md
new file mode 100644
index 0000000..af2ea02
--- /dev/null
+++ b/content/markdown.md
@@ -0,0 +1,7 @@
+---
+title: Seite unterstützt Markdown
+tags: meta
+sort: 0
+---
+Text kann auch in allen Pandoc-unterstützten Formaten angegeben werden, statt nur in HTML.
+Hier: Markdown
diff --git a/content/tags.md b/content/tags.md
new file mode 100644
index 0000000..069df4f
--- /dev/null
+++ b/content/tags.md
@@ -0,0 +1,8 @@
+---
+title: Tags sind echte Tags
+tags:
+ - meta
+ - example
+sort: 100
+---
+Beliebig viele Tags pro Item.
diff --git a/content/index.html b/content/under-construction.md
similarity index 81%
rename from content/index.html
rename to content/under-construction.md
index b173985..8dbf4ec 100644
--- a/content/index.html
+++ b/content/under-construction.md
@@ -1,3 +1,11 @@
+---
+title: Seite befindet sich im Aufbau
+tags:
+ - index
+ - meta
+sort: -9001
+---
+```{=html}
UniWorX Systems
@@ -7,3 +15,4 @@
+```
diff --git a/frontend/dist.gup b/frontend/dist.gup
index 9905c96..3f52207 100644
--- a/frontend/dist.gup
+++ b/frontend/dist.gup
@@ -1,6 +1,6 @@
#!/usr/bin/env sh
-gup --always
-gup -u node_modules
+gup -u node_modules webpack.config.js postcss.config.js
+gup -u .src.chksum
rm -rf dist
yarn run build
diff --git a/frontend/node_modules.gup b/frontend/node_modules.gup
index bf6f29d..5ce3bf5 100644
--- a/frontend/node_modules.gup
+++ b/frontend/node_modules.gup
@@ -1,5 +1,5 @@
#!/usr/bin/env sh
-gup --always
+gup -u package.json yarn.lock
yarn install
touch node_modules
diff --git a/package.yaml b/package.yaml
index 23f678c..66ecb90 100644
--- a/package.yaml
+++ b/package.yaml
@@ -6,9 +6,8 @@ default-extensions:
- NoImplicitPrelude
- ViewPatterns
- DerivingStrategies
- - DeriveGeneric
- - GeneralizedNewtypeDeriving
- - TypeApplications
+ - MultiWayIf
+language: GHC2021
executables:
site:
diff --git a/src/Main.hs b/src/Main.hs
index 2e01ae2..70f9caa 100644
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -4,15 +4,15 @@ import Prelude
import Hakyll
-import qualified Data.List as List
+import Data.List qualified as List
import Data.Maybe
import System.FilePath
-import qualified System.FilePath.Glob as Glob
+import System.FilePath.Glob qualified as Glob
-import qualified Data.Yaml as Yaml
+import Data.Yaml qualified as Yaml
import Data.Map (Map)
-import qualified Data.Map as Map
+import Data.Map qualified as Map
import Control.Monad
@@ -32,15 +32,9 @@ main = hakyllWith config $ do
frontendManifest <-
preprocess $
Yaml.decodeFileThrow @_ @(Map String [FilePath]) "frontend/dist/.manifest.yaml"
-
- match "content/index.html" $ do
- route $ stripPathPrefix "content"
-
- let context =
- defaultContext
- <> jsContext
- <> cssContext
-
+ let
+ frontendContext = jsContext <> cssContext
+ where
cssContext = listField "css" innerContext genCSSItems
where
innerContext = urlField "url"
@@ -56,9 +50,56 @@ main = hakyllWith config $ do
resources = filter (Glob.match p) $ frontendManifest Map.! entryPoint
forM resources $ load . fromFilePath . ("frontend/dist" >) . dropDrive
+ tags <- buildTags "content/**" $ fromCapture "*.html"
+
+ match "content/**" $ do
compile $ do
- getResourceBody
- >>= loadAndApplyTemplate "templates/site-layout.html" context
+ pandocCompiler
+ >>= relativizeUrls
+
+ tagsRules tags $ \_tag posts -> do
+ route idRoute
+ compile $ do
+ let
+ ctx =
+ mconcat
+ [ listField "tags-nav" defaultContext (mapM (uncurry renderTagNav) $ tagsMap tags)
+ , listField "posts" postContext (postsSort =<< loadAll posts)
+ , frontendContext
+ , defaultContext
+ ]
+
+ renderTagNav tag ids = do
+ let
+ navRoute
+ | tag == "index" = "/"
+ | otherwise = "/" <> tag <> ".html"
+
+ tagNavCtx =
+ mconcat
+ [ constField "tag" tag
+ , constField "route" navRoute
+ , listField "posts" (constField "tag" tag <> constField "route" navRoute <> postContext) (postsSort =<< mapM load ids)
+ ]
+ makeItem (mempty :: String)
+ >>= loadAndApplyTemplate "templates/tag-nav.html" tagNavCtx
+ >>= relativizeUrls
+
+ postContext =
+ mconcat
+ [ field "identifier" (return . takeBaseName . toFilePath . itemIdentifier)
+ , defaultContext
+ ]
+
+ postsSort :: [Item w] -> Compiler [Item w]
+ postsSort = sortOnM $ \Item{itemIdentifier} -> getMetadataField itemIdentifier "sort"
+ where
+ sortOnM :: forall m a b. (Monad m, Ord b) => (a -> m b) -> [a] -> m [a]
+ sortOnM f = fmap (map snd . List.sortOn fst) . mapM (\x -> (,x) <$> f x)
+
+ makeItem (mempty :: String)
+ >>= loadAndApplyTemplate "templates/tag.html" ctx
+ >>= loadAndApplyTemplate "templates/site-layout.html" ctx
>>= relativizeUrls
match "frontend/dist/wp-*/**" $ do
diff --git a/templates/tag-nav.html b/templates/tag-nav.html
new file mode 100644
index 0000000..303dee4
--- /dev/null
+++ b/templates/tag-nav.html
@@ -0,0 +1,11 @@
+
+ $tag$
+
+
+ $for(posts)$
+ -
+ $title$
+
+ $endfor$
+
+
diff --git a/templates/tag.html b/templates/tag.html
new file mode 100644
index 0000000..ec02623
--- /dev/null
+++ b/templates/tag.html
@@ -0,0 +1,12 @@
+
+$for(posts)$
+
+ $body$
+
+$endfor$