diff options
author | Stefan Kreutz <mail@skreutz.com> | 2025-08-24 22:21:37 +0200 |
---|---|---|
committer | Stefan Kreutz <mail@skreutz.com> | 2025-08-24 22:26:04 +0200 |
commit | a19cc6497a788742ea25bba82d2fcc2e217b2c29 (patch) | |
tree | 5252dcea82c70adb3b7c2d71ec3c8d8c842f8a0c | |
parent | c3a733cb0e2e937e39f809ba31f18c023738a313 (diff) | |
download | blog-a19cc6497a788742ea25bba82d2fcc2e217b2c29.tar |
Add experimental Nix flake
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | flake.lock | 61 | ||||
-rw-r--r-- | flake.nix | 55 | ||||
-rw-r--r-- | site.hs | 167 | ||||
-rw-r--r-- | site.nix | 13 |
5 files changed, 215 insertions, 82 deletions
@@ -1,3 +1,4 @@ +/result .stack-work _cache _site diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..94bba45 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1755829505, + "narHash": "sha256-4/Jd+LkQ2ssw8luQVkqVs9spDBVE6h/u/hC/tzngsPo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f937f8ecd1c70efd7e9f90ba13dfb400cf559de4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..7d153a9 --- /dev/null +++ b/flake.nix @@ -0,0 +1,55 @@ +{ + description = "Stefan Kreutz's personal website"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = inputs@{ self, nixpkgs, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { + inherit system; + config = { }; + overlays = [ ]; + }; + src = builtins.path { path = ./.; name = "blog"; }; + in rec { + # nix develop + devShells.default = pkgs.mkShell { + nativeBuildInputs = with pkgs; [ ghc cabal-install lychee ]; + }; + + # nix build . + # open ./result/srv/www.skreutz.com/index.html + packages.default = packages.site; + + # nix run .#generator -- --help + packages.generator = pkgs.haskell.lib.compose.justStaticExecutables ( + pkgs.haskellPackages.callCabal2nix "blog" src { } + ); + + # nix build .#site + packages.site = pkgs.callPackage ./site.nix { + inherit self; + inherit (packages) generator; + }; + + checks.links = pkgs.stdenvNoCC.mkDerivation { + inherit src; + name = "offline-link-check"; + dontBuild = true; + doCheck = true; + nativeBuildInputs = with pkgs; [ lychee ]; + checkPhase = '' + "${packages.generator}/bin/site" rebuild + lychee --offline --no-progress --require-https --root-dir "$( realpath _site )" _site + ''; + installPhase = '' + mkdir $out + ''; + }; + } + ); +} @@ -8,90 +8,93 @@ import System.FilePath.Posix ((</>), (<.>), splitExtension, splitFileName, takeD import Text.Pandoc (Pandoc, Inline(Link, Space, Str), Block(Header)) import Text.Pandoc.Shared (stringify) import Text.Pandoc.Walk (walk) +import qualified GHC.IO.Encoding as Encoding main :: IO () -main = hakyllWith hakyllConfig $ do - match ("images/*" .||. "files/*" .||. "robots.txt" .||. "health") $ do - route idRoute - compile copyFileCompiler - - match "css/*" $ do - route idRoute - -- WORKAROUND: compressCssCompiler removes copyright notices - compile copyFileCompiler - - match (fromList ["about.md", "contact.md", "privacy.md", "code.md"]) $ do - route $ setExtension "html" `composeRoutes` appendIndex - let context = dropIndexHtml "url" <> defaultContext - compile $ customPandocCompiler - >>= loadAndApplyTemplate "templates/direct.html" context - >>= loadAndApplyTemplate "templates/default.html" context - - match "posts/*" $ do - route $ setExtension "html" `composeRoutes` appendIndex - compile $ customPandocCompiler - >>= loadAndApplyTemplate "templates/post.html" postContext - >>= saveSnapshot "content" - >>= loadAndApplyTemplate "templates/default.html" postContext - - create ["posts.html"] $ do - route appendIndex - compile $ do - posts <- recentFirst =<< loadAll "posts/*" - let archiveContext = - listField "posts" postContext (return posts) <> - constField "title" "Blog" <> - dropIndexHtml "url" <> - defaultContext - - makeItem "" - >>= loadAndApplyTemplate "templates/posts.html" archiveContext - >>= loadAndApplyTemplate "templates/default.html" archiveContext - - create ["feeds/posts.rss"] $ do - route idRoute - compileFeed renderRss rfc822DateTimeFormat - - create ["feeds/posts.atom"] $ do - route idRoute - compileFeed renderAtom rfc3339DateTimeFormat - - create ["sitemap.xml"] $ do - route idRoute - compile $ do - posts <- recentFirst =<< loadAll "posts/*" - singles <- loadAll (fromList ["about.md", "contact.md", "privacy.md", "code.md", "posts.html"]) - let - pages = posts <> singles - sitemapContext = - constField "root" root <> - listField "pages" postContext (return pages) - makeItem "" - >>= loadAndApplyTemplate "templates/sitemap.xml" sitemapContext - - match "index.html" $ do - route idRoute - compile $ do - posts <- recentFirst =<< loadAll "posts/*" - let indexContext = - listField "posts" postContext (return posts) <> - defaultContext - - getResourceBody - >>= applyAsTemplate indexContext - >>= loadAndApplyTemplate "templates/default.html" indexContext - - match "err.html" $ do - route idRoute - compile $ customPandocCompiler - >>= loadAndApplyTemplate "templates/default.html" defaultContext - - match "404.html" $ do - route idRoute - compile $ customPandocCompiler - >>= loadAndApplyTemplate "templates/default.html" defaultContext - - match "templates/*" $ compile templateBodyCompiler +main = do + Encoding.setLocaleEncoding Encoding.utf8 + hakyllWith hakyllConfig $ do + match ("images/*" .||. "files/*" .||. "robots.txt" .||. "health") $ do + route idRoute + compile copyFileCompiler + + match "css/*" $ do + route idRoute + -- WORKAROUND: compressCssCompiler removes copyright notices + compile copyFileCompiler + + match (fromList ["about.md", "contact.md", "privacy.md", "code.md"]) $ do + route $ setExtension "html" `composeRoutes` appendIndex + let context = dropIndexHtml "url" <> defaultContext + compile $ customPandocCompiler + >>= loadAndApplyTemplate "templates/direct.html" context + >>= loadAndApplyTemplate "templates/default.html" context + + match "posts/*" $ do + route $ setExtension "html" `composeRoutes` appendIndex + compile $ customPandocCompiler + >>= loadAndApplyTemplate "templates/post.html" postContext + >>= saveSnapshot "content" + >>= loadAndApplyTemplate "templates/default.html" postContext + + create ["posts.html"] $ do + route appendIndex + compile $ do + posts <- recentFirst =<< loadAll "posts/*" + let archiveContext = + listField "posts" postContext (return posts) <> + constField "title" "Blog" <> + dropIndexHtml "url" <> + defaultContext + + makeItem "" + >>= loadAndApplyTemplate "templates/posts.html" archiveContext + >>= loadAndApplyTemplate "templates/default.html" archiveContext + + create ["feeds/posts.rss"] $ do + route idRoute + compileFeed renderRss rfc822DateTimeFormat + + create ["feeds/posts.atom"] $ do + route idRoute + compileFeed renderAtom rfc3339DateTimeFormat + + create ["sitemap.xml"] $ do + route idRoute + compile $ do + posts <- recentFirst =<< loadAll "posts/*" + singles <- loadAll (fromList ["about.md", "contact.md", "privacy.md", "code.md", "posts.html"]) + let + pages = posts <> singles + sitemapContext = + constField "root" root <> + listField "pages" postContext (return pages) + makeItem "" + >>= loadAndApplyTemplate "templates/sitemap.xml" sitemapContext + + match "index.html" $ do + route idRoute + compile $ do + posts <- recentFirst =<< loadAll "posts/*" + let indexContext = + listField "posts" postContext (return posts) <> + defaultContext + + getResourceBody + >>= applyAsTemplate indexContext + >>= loadAndApplyTemplate "templates/default.html" indexContext + + match "err.html" $ do + route idRoute + compile $ customPandocCompiler + >>= loadAndApplyTemplate "templates/default.html" defaultContext + + match "404.html" $ do + route idRoute + compile $ customPandocCompiler + >>= loadAndApplyTemplate "templates/default.html" defaultContext + + match "templates/*" $ compile templateBodyCompiler hakyllConfig :: Configuration hakyllConfig = defaultConfiguration diff --git a/site.nix b/site.nix new file mode 100644 index 0000000..6626ad6 --- /dev/null +++ b/site.nix @@ -0,0 +1,13 @@ +{ self, stdenv, generator }: + +stdenv.mkDerivation rec { + name = "www.skreutz.com"; + src = self; + buildPhase = '' + ${generator}/bin/site rebuild + ''; + installPhase = '' + mkdir -p $out + cp -a _site $out/srv/${name} + ''; +} |