DLJPWVRPZ5E4TC7IXF4DBPN3KQZCC4F5GBT222Q4W4FAJSAIHBFQC
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url>
<loc>$root$</loc>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
$for(pages)$
<url>
<loc>$root$$url$</loc>
<lastmod>$if(updated)$$updated$$else$$if(date)$$date$$endif$$endif$</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
$endfor$
</urlset>
<article>
<section class="header">
Posted on $date$
$if(author)$
by $author$
$endif$
</section>
<section>
$body$
</section>
</article>
<ul>
$for(posts)$
<li>
<a href="$url$">$title$</a> - $date$
</li>
$endfor$
</ul>
<!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>My Hakyll Blog - $title$</title>
<link rel="stylesheet" href="/css/default.css" />
</head>
<body>
<header>
<div class="logo">
<a href="/">My Hakyll Blog</a>
</div>
<nav>
<a href="/">Home</a>
<a href="/about.html">About</a>
<a href="/contact.html">Contact</a>
<a href="/archive.html">Archive</a>
</nav>
</header>
<main role="main">
<h1>$title$</h1>
$body$
</main>
<footer>
Site proudly generated by
<a href="http://jaspervdj.be/hakyll">Hakyll</a>
</footer>
</body>
</html>
Here you can find all my previous posts:
$partial("templates/post-list.html")$
final: prev:
let
inherit (prev.stdenv) mkDerivation;
inherit (prev.lib.trivial) flip pipe;
inherit (prev.haskell.lib)
appendPatch
appendConfigureFlags
dontCheck
doJailbreak;
withPatch = flip appendPatch;
withFlags = flip appendConfigureFlags;
haskellCompiler = "ghc902";
in {
myHaskellPackages = prev.haskell.packages.${haskellCompiler}.override {
overrides = hpFinal: hpPrev:
let
hakyll-src = hpPrev.callHackage "hakyll" "4.15.1.1" {};
pandoc-src = hpPrev.callHackage "pandoc" "2.17.1.1" {}; # latest version on nixpkgs
slugger-src = hpPrev.callHackageDirect {
pkg = "slugger";
ver = "0.1.0.1";
sha256 = "sha256-ggeo5TcbI4UlK/CtG4878USX9Cm7Faz16phdjlDOGaI=";
} {}; # not available yet because it's so new
in rec {
hakyll = pipe hakyll-src [
doJailbreak
dontCheck
(withPatch ./hakyll.patch)
(withFlags [ "-f" "watchServer" "-f" "previewServer" ])
];
pandoc = pipe pandoc-src [
doJailbreak
dontCheck
];
slugger = slugger-src;
blog = hpPrev.callCabal2nix "blog-src" ./blog {};
blog-nix = prev.stdenv.mkDerivation {
#__contentAddressed = true; # uncomment if using cas: https://www.tweag.io/blog/2020-09-10-nix-cas/
name = "blog-nix";
buildInputs = [ blog ];
src = prev.nix-gitignore.gitignoreSourcePure [
./.gitignore
".git"
".github"
] ./.;
# LANG and LOCALE_ARCHIVE are fixes pulled from the community:
# https://github.com/jaspervdj/hakyll/issues/614#issuecomment-411520691
# https://github.com/NixOS/nix/issues/318#issuecomment-52986702
# https://github.com/MaxDaten/brutal-recipes/blob/source/default.nix#L24
LANG = "en_US.UTF-8";
LOCALE_ARCHIVE = prev.lib.optionalString
(prev.buildPlatform.libc == "glibc")
"${prev.glibcLocales}/lib/locale/locale-archive";
buildPhase = ''
hakyll-site build --verbose
'';
installPhase = ''
mkdir -p "$out/dist"
cp -r dist/* "$out/dist"
'';
};
};
};
}
{
description = "hakyll-nix-template";
nixConfig.bash-prompt = "[nix]λ ";
inputs = {
nixpkgs.url = "nixpkgs/nixos-22.05";
flake-utils = {
url = "github:numtide/flake-utils";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { flake-utils, nixpkgs, self }:
flake-utils.lib.eachDefaultSystem (system:
let
config = {};
overlays = [ (import ./haskell-overlay.nix) ];
pkgs = import nixpkgs { inherit config overlays system; };
in rec {
packages = with pkgs.myHaskellPackages; { inherit blog blog-nix; };
defaultPackage = packages.blog-nix;
apps.default = flake-utils.lib.mkApp {
drv = packages.blog;
exePath = "/bin/hakyll-site";
};
devShell = pkgs.myHaskellPackages.shellFor {
packages = p: [ p.blog ];
buildInputs = with pkgs.myHaskellPackages; [
blog
# Helpful tools for `nix develop` shells
#ghcid # https://github.com/ndmitchell/ghcid
#haskell-language-server # https://github.com/haskell/haskell-language-server
# hlint # https://github.com/ndmitchell/hlint
#ormolu # https://github.com/tweag/ormolu
];
};
}
);
}
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1664029467,
"narHash": "sha256-ir7JbsLp2mqseCs3qI+Z/pkt+Gh+GfANbYcI5I+Gvnk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "893b6b9f6c4ed0c7efdb84bd300a499a2da9fa51",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-22.05",
"type": "indirect"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}
html {
font-size: 62.5%;
}
body {
font-size: 1.6rem;
color: #000;
}
header {
border-bottom: 0.2rem solid #000;
}
nav {
text-align: right;
}
nav a {
font-size: 1.8rem;
font-weight: bold;
color: black;
text-decoration: none;
text-transform: uppercase;
}
footer {
margin-top: 3rem;
padding: 1.2rem 0;
border-top: 0.2rem solid #000;
font-size: 1.2rem;
color: #555;
}
h1 {
font-size: 2.4rem;
}
h2 {
font-size: 2rem;
}
article .header {
font-size: 1.4rem;
font-style: italic;
color: #555;
}
.logo a {
font-weight: bold;
color: #000;
text-decoration: none;
}
@media (max-width: 319px) {
body {
width: 90%;
margin: 0;
padding: 0 5%;
}
header {
margin: 4.2rem 0;
}
nav {
margin: 0 auto 3rem;
text-align: center;
}
footer {
text-align: center;
}
.logo {
text-align: center;
margin: 1rem auto 3rem;
}
.logo a {
font-size: 2.4rem;
}
nav a {
display: block;
line-height: 1.6;
}
}
@media (min-width: 320px) {
body {
width: 90%;
margin: 0;
padding: 0 5%;
}
header {
margin: 4.2rem 0;
}
nav {
margin: 0 auto 3rem;
text-align: center;
}
footer {
text-align: center;
}
.logo {
text-align: center;
margin: 1rem auto 3rem;
}
.logo a {
font-size: 2.4rem;
}
nav a {
display: inline;
margin: 0 0.6rem;
}
}
@media (min-width: 640px) {
body {
width: 60rem;
margin: 0 auto;
padding: 0;
}
header {
margin: 0 0 3rem;
padding: 1.2rem 0;
}
nav {
margin: 0;
text-align: right;
}
nav a {
margin: 0 0 0 1.2rem;
display: inline;
}
footer {
text-align: right;
}
.logo {
margin: 0;
text-align: left;
}
.logo a {
float: left;
font-size: 1.8rem;
}
}
cabal-version: 2.4
name: blog
version: 0.1.0.0
build-type: Simple
license: BSD-3-Clause
executable hakyll-site
main-is: Main.hs
hs-source-dirs: .
build-depends: base >= 4.8
, hakyll >= 4.15
, pandoc == 2.17.*
, slugger >= 0.1.0.1
, text >= 1.2
ghc-options: -Wall -threaded
default-language: Haskell2010
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad (forM_)
import Data.Maybe (fromMaybe)
import Hakyll
import qualified Data.Text as T
import qualified Data.Text.Slugger as Slugger
import Text.Pandoc
( Extension (Ext_fenced_code_attributes, Ext_footnotes, Ext_gfm_auto_identifiers, Ext_implicit_header_references, Ext_smart),
Extensions,
ReaderOptions,
WriterOptions (writerHighlightStyle),
extensionsFromList,
githubMarkdownExtensions,
readerExtensions,
writerExtensions,
)
import Text.Pandoc.Highlighting (Style, breezeDark, styleToCss)
--------------------------------------------------------------------------------
-- CONFIG
root :: String
root =
"https://alexis.praga.free.fr"
siteName :: String
siteName =
"Armadillo"
config :: Configuration
config =
defaultConfiguration
{ destinationDirectory = "dist"
, ignoreFile = const False
, previewHost = "127.0.0.1"
, previewPort = 8000
, providerDirectory = "."
, storeDirectory = "blog/_cache"
, tmpDirectory = "blog/_tmp"
}
--------------------------------------------------------------------------------
-- BUILD
main :: IO ()
main = hakyllWith config $ do
forM_
[ "CNAME"
, "favicon.ico"
, "robots.txt"
, "_config.yml"
, "images/*"
, "js/*"
, "fonts/*"
]
$ \f -> match f $ do
route idRoute
compile copyFileCompiler
match "css/*" $ do
route idRoute
compile compressCssCompiler
match "posts/*" $ do
let ctx = constField "type" "article" <> postCtx
route $ metadataRoute titleRoute
compile $
pandocCompilerCustom
>>= loadAndApplyTemplate "templates/post.html" ctx
>>= saveSnapshot "content"
>>= loadAndApplyTemplate "templates/default.html" ctx
match "index.html" $ do
route idRoute
compile $ do
posts <- recentFirst =<< loadAll "posts/*"
let indexCtx =
listField "posts" postCtx (return posts)
<> constField "root" root
<> constField "siteName" siteName
<> defaultContext
getResourceBody
>>= applyAsTemplate indexCtx
>>= loadAndApplyTemplate "templates/default.html" indexCtx
match "templates/*" $
compile templateBodyCompiler
create ["sitemap.xml"] $ do
route idRoute
compile $ do
posts <- recentFirst =<< loadAll "posts/*"
let pages = posts
sitemapCtx =
constField "root" root
<> constField "siteName" siteName
<> listField "pages" postCtx (return pages)
makeItem ("" :: String)
>>= loadAndApplyTemplate "templates/sitemap.xml" sitemapCtx
create ["rss.xml"] $ do
route idRoute
compile (feedCompiler renderRss)
create ["atom.xml"] $ do
route idRoute
compile (feedCompiler renderAtom)
create ["css/code.css"] $ do
route idRoute
compile (makeStyle pandocHighlightStyle)
--------------------------------------------------------------------------------
-- COMPILER HELPERS
makeStyle :: Style -> Compiler (Item String)
makeStyle =
makeItem . compressCss . styleToCss
--------------------------------------------------------------------------------
-- CONTEXT
feedCtx :: Context String
feedCtx =
titleCtx
<> postCtx
<> bodyField "description"
postCtx :: Context String
postCtx =
constField "root" root
<> constField "siteName" siteName
<> dateField "date" "%Y-%m-%d"
<> defaultContext
titleCtx :: Context String
titleCtx =
field "title" updatedTitle
--------------------------------------------------------------------------------
-- TITLE HELPERS
replaceAmp :: String -> String
replaceAmp =
replaceAll "&" (const "&")
replaceTitleAmp :: Metadata -> String
replaceTitleAmp =
replaceAmp . safeTitle
safeTitle :: Metadata -> String
safeTitle =
fromMaybe "no title" . lookupString "title"
updatedTitle :: Item a -> Compiler String
updatedTitle =
fmap replaceTitleAmp . getMetadata . itemIdentifier
--------------------------------------------------------------------------------
-- PANDOC
pandocCompilerCustom :: Compiler (Item String)
pandocCompilerCustom =
pandocCompilerWith pandocReaderOpts pandocWriterOpts
pandocExtensionsCustom :: Extensions
pandocExtensionsCustom =
githubMarkdownExtensions
<> extensionsFromList
[ Ext_fenced_code_attributes
, Ext_gfm_auto_identifiers
, Ext_implicit_header_references
, Ext_smart
, Ext_footnotes
]
pandocReaderOpts :: ReaderOptions
pandocReaderOpts =
defaultHakyllReaderOptions
{ readerExtensions = pandocExtensionsCustom
}
pandocWriterOpts :: WriterOptions
pandocWriterOpts =
defaultHakyllWriterOptions
{ writerExtensions = pandocExtensionsCustom
, writerHighlightStyle = Just pandocHighlightStyle
}
pandocHighlightStyle :: Style
pandocHighlightStyle =
breezeDark -- https://hackage.haskell.org/package/pandoc/docs/Text-Pandoc-Highlighting.html
-- FEEDS
type FeedRenderer =
FeedConfiguration ->
Context String ->
[Item String] ->
Compiler (Item String)
feedCompiler :: FeedRenderer -> Compiler (Item String)
feedCompiler renderer =
renderer feedConfiguration feedCtx
=<< recentFirst
=<< loadAllSnapshots "posts/*" "content"
feedConfiguration :: FeedConfiguration
feedConfiguration =
FeedConfiguration
{ feedTitle = "My Site"
, feedDescription = "My Site Description"
, feedAuthorName = "My Name"
, feedAuthorEmail = "me@myemail.com"
, feedRoot = root
}
--------------------------------------------------------------------------------
-- CUSTOM ROUTE
getTitleFromMeta :: Metadata -> String
getTitleFromMeta =
fromMaybe "no title" . lookupString "title"
fileNameFromTitle :: Metadata -> FilePath
fileNameFromTitle =
T.unpack . (`T.append` ".html") . Slugger.toSlug . T.pack . getTitleFromMeta
titleRoute :: Metadata -> Routes
titleRoute =
constRoute . fileNameFromTitle
A blog with [Hakyll](https://jaspervdj.be/hakyll/) + [Nix](https://nixos.org), with the template from [rpearce template](https://github.com/rpearce/hakyll-nix-template).
[![built with nix](https://builtwithnix.org/badge.svg)](https://builtwithnix.org)
# structure
- [blog](blog/) contains the rules for Hakyll to generate the static content
- [posts](posts/) contains a list of post in org-mode