Compare commits

..

No commits in common. "gh-pages" and "main" have entirely different histories.

31 changed files with 1529 additions and 389 deletions

View file

@ -0,0 +1,35 @@
name: CI
on:
pull_request:
push:
jobs:
build-nix:
runs-on: ubuntu-latest
steps:
- run: apt-get update -y && apt-get install sudo
- uses: actions/checkout@v4
- name: Install Nix
uses: cachix/install-nix-action@V28
with:
github_access_token: ${{ secrets.GH_TOKEN }}
extra_nix_config: |
access-tokens = github.com=${{ secrets.GH_TOKEN }}
allow-import-from-derivation = true
auto-optimise-store = true
experimental-features = nix-command flakes
substituters = https://cache.nixos.org https://cache.iog.io
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ=
- name: Build with cachix
uses: cachix/cachix-action@v15
env:
USER: $(whoami)
with:
name: hakyll-nix-template
- run: nix build --accept-flake-config
# TODO: Push artifact?

7
.ghci Normal file
View file

@ -0,0 +1,7 @@
:def hoogle \x -> return $ ":!hoogle --count=15 \"" ++ x ++ "\""
:def doc \x -> return $ ":!hoogle --info \"" ++ x ++ "\""
:set -Wall
:set -fno-warn-type-defaults -ferror-spans -freverse-errors -fprint-expanded-synonyms
:set prompt "\ESC[0;32m%s\n\ESC[m[ghci]\ESC[38;5;172mλ \ESC[m\STX"
:set prompt-cont " \ESC[38;5;172m> \ESC[m"
:load ssg/src/Main.hs

9
.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
!src/js/dist
.DS_Store
.ghc.environment.*
_cache
_tmp
dist
dist-newstyle
node_modules
result

29
LICENSE Normal file
View file

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2020, Robert Pearce
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

108
README.md Normal file
View file

@ -0,0 +1,108 @@
# hakyll-nix-template
[Hakyll](https://jaspervdj.be/hakyll/) + [Nix](https://nixos.org) template
## Quick tips
* Read the tutorial to get started! https://robertwpearce.com/the-hakyll-nix-template-tutorial.html
* If you make changes to anything inside of `ssg/`, you'll need to clean the
hakyll cache and rebuild. This is the preferred series of commands for
rebuilding (with logs), cleaning the cache, and re-running the dev server:
```default
nix build --print-build-logs && \
nix run . clean && \
nix run . watch
```
## Features
* Build your site into the `./result/dist` folder:
```
λ nix build
```
* Start hakyll's dev server that reloads when changes are made:
```
λ nix run . watch
Listening on http://127.0.0.1:8000
...more logs
```
* Run any hakyll command through `nix run .`!
```
λ nix run . clean
Removing dist...
Removing ssg/_cache...
Removing ssg/_tmp...
```
* Start a development environment that
* has your shell environment
* has `hakyll-site` (for building/watching/cleaning hakyll projects)
* has `hakyll-init` (for generating new projects)
* can have anything else you put in the `shell.buildInputs` of the
`hakyllProject` in `flake.nix`
* is set up to run `ghci` with some defaults and the modules loaded so you can
make your own changes and test them out in the ghci REPL
```
λ nix develop
[hakyll-nix]λ hakyll-site build
...
Success
[hakyll-nix]λ ghci
...
[1 of 1] Compiling Main ( ssg/src/Main.hs, interpreted )
...
λ >
```
### hakyll
All of this is custmomizable, and here are some things that are already done for
you:
* [pandoc](https://github.com/jgm/pandoc/) markdown customization to make it as
close to GitHub's markdown style as possible
* [`slugger`](https://hackage.haskell.org/package/slugger) module is included that makes nice link URIs based on post titles
* RSS & Atom XML feed generation
* Sitemap generation
* Code syntax highlighting customization
* ...other reasonable defaults
Configure the dev server, cache & tmp directories, and more in
`./ssg/src/Main.hs`.
### Deployment
Deployment is set up through a [GitHub
Action](https://github.com/features/actions) with [cachix](https://cachix.org),
and it deploys to a [GitHub Pages](https://pages.github.com/) branch,
`gh-pages`, when you merge code into your main branch.
Setup information can be found below in the "Cachix" section.
Note: If your main branch's name isn't `main`, ensure `'refs/heads/main'` gets
updated to `'refs/heads/my-main-branch'` in `./github/workflows/main.yml`.
## Setup
### Nix & Flakes
If you don't have [nix](https://nixos.org), follow [the nix installation
instructions](https://nixos.org/download.html).
Once you have nix installed, follow the instructions here to get access to
flakes: https://nixos.wiki/wiki/Flakes.
### Cachix
The `./.github/workflows/main.yml` file builds with help from
[cachix](https://app.cachix.org), so you'll need to generate a signing key to be
able to do this.
1. Create a cache on cachix for your project
1. Follow cachix's instructions to generate a signing keypair
1. Copy the signing keypair value to a new `CACHIX_SIGNING_KEY` secret on
https://github.com/settings/secrets

View file

@ -1,77 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>My Feed Title</title>
<link href="https://my-site.com/atom.xml" rel="self" />
<link href="https://my-site.com" />
<id>https://my-site.com/atom.xml</id>
<author>
<name>My Name</name>
<email>me@myemail.com</email>
</author>
<updated>2020-09-23T12:00:00Z</updated>
<entry>
<title>¡Hola Mundo!</title>
<link href="https://my-site.com/hola-mundo.html" />
<id>https://my-site.com/hola-mundo.html</id>
<published>2020-09-22T00:00:00Z</published>
<updated>2020-09-23T12:00:00Z</updated>
<summary type="html"><![CDATA[<main>
<article>
<header>
<h1>
<a href="./hola-mundo.html">¡Hola Mundo!</a>
</h1>
<div>
2020-09-22 (updated: 2020-09-23T12:00:00Z)
</div>
</header>
<section>
<p>¡Hola Mundo! ¡Estoy aquí!</p>
<p><img
alt="Grapevines among rolling hills leading to the sea"
src="./images/waiheke-stony-batter.jpg"
height="200"
/></p>
<p>Haskell, por ejemplo:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">toSlug ::</span> <span class="dt">T.Text</span> <span class="ot">-&gt;</span> <span class="dt">T.Text</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>toSlug <span class="ot">=</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> T.intercalate (T.singleton <span class="ch">&#39;-&#39;</span>) <span class="op">.</span> T.words <span class="op">.</span> T.toLower <span class="op">.</span> clean</span></code></pre></div>
</section>
</article>
</main>
]]></summary>
</entry>
<entry>
<title>Hello, world!</title>
<link href="https://my-site.com/hello-world.html" />
<id>https://my-site.com/hello-world.html</id>
<published>2020-09-21T00:00:00Z</published>
<updated>2020-09-22T12:00:00Z</updated>
<summary type="html"><![CDATA[<main>
<article>
<header>
<h1>
<a href="./hello-world.html">Hello, world!</a>
</h1>
<div>
2020-09-21 (updated: 2020-09-22T12:00:00Z)
</div>
</header>
<section>
<p>Hello, world! I am here!</p>
<p><img
alt="Grapevines among rolling hills leading to the sea"
src="./images/waiheke-stony-batter.jpg"
height="200"
/></p>
<p>Haskell, for example:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">toSlug ::</span> <span class="dt">T.Text</span> <span class="ot">-&gt;</span> <span class="dt">T.Text</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>toSlug <span class="ot">=</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> T.intercalate (T.singleton <span class="ch">&#39;-&#39;</span>) <span class="op">.</span> T.words <span class="op">.</span> T.toLower <span class="op">.</span> clean</span></code></pre></div>
</section>
</article>
</main>
]]></summary>
</entry>
</feed>

View file

@ -1 +0,0 @@
pre>code.sourceCode{white-space:pre;position:relative}pre>code.sourceCode>span{line-height:1.25}pre>code.sourceCode>span:empty{height:1.2em}.sourceCode{overflow:visible}code.sourceCode>span{color:inherit;text-decoration:inherit}div.sourceCode{margin:1em 0}pre.sourceCode{margin:0}@media screen{div.sourceCode{overflow:auto}}@media print{pre>code.sourceCode{white-space:pre-wrap}pre>code.sourceCode>span{text-indent:-5em;padding-left:5em}}pre.numberSource code{counter-reset:source-line 0}pre.numberSource code>span{position:relative;left:-4em;counter-increment:source-line}pre.numberSource code>span>a:first-child::before{content:counter(source-line);position:relative;left:-1em;text-align:right;vertical-align:baseline;border:none;display:inline-block;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:0 4px;width:4em;background-color:#232629;color:#7a7c7d}pre.numberSource{margin-left:3em;border-left:1px solid #7a7c7d;padding-left:4px}div.sourceCode{color:#cfcfc2;background-color:#232629}@media screen{pre>code.sourceCode>span>a:first-child::before{text-decoration:underline}}code span{color:#cfcfc2}code span.al{color:#95da4c;background-color:#4d1f24;font-weight:bold}code span.an{color:#3f8058}code span.at{color:#2980b9}code span.bn{color:#f67400}code span.bu{color:#7f8c8d}code span.cf{color:#fdbc4b;font-weight:bold}code span.ch{color:#3daee9}code span.cn{color:#27aeae;font-weight:bold}code span.co{color:#7a7c7d}code span.cv{color:#7f8c8d}code span.do{color:#a43340}code span.dt{color:#2980b9}code span.dv{color:#f67400}code span.er{color:#da4453;text-decoration:underline}code span.ex{color:#0099ff;font-weight:bold}code span.fl{color:#f67400}code span.fu{color:#8e44ad}code span.im{color:#27ae60}code span.in{color:#c45b00}code span.kw{color:#cfcfc2;font-weight:bold}code span.op{color:#cfcfc2}code span.ot{color:#27ae60}code span.pp{color:#27ae60}code span.re{color:#2980b9;background-color:#153042}code span.sc{color:#3daee9}code span.ss{color:#da4453}code span.st{color:#f44f4f}code span.va{color:#27aeae}code span.vs{color:#da4453}code span.wa{color:#da4453}

View file

@ -1 +0,0 @@
:root{font-size:62.5%;box-sizing:border-box;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}*,*:before,*:after{box-sizing:inherit}html,body{min-height:100vh}body{font-kerning:normal;-moz-font-feature-settings:"kern","liga","clig","calt";-ms-font-feature-settings:"kern","liga","clig","calt";-webkit-font-feature-settings:"kern","liga","clig","calt";font-feature-settings:"kern","liga","clig","calt";scroll-behavior:smooth;font-size:2rem}body,input,button{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}h1,h2{font-family:"Palatino Linotype","Book Antiqua",Palatino,serif}h1{font-size:4.0rem}h2{font-size:2.6rem}small,p{font-family:Tahoma,Arial,sans-serif}small{font-size:1.6rem;font-style:italic}p{font-size:1.8rem}pre.sourceCode{padding:2rem 1.5rem}

693
flake.lock generated Normal file
View file

@ -0,0 +1,693 @@
{
"nodes": {
"HTTP": {
"flake": false,
"locked": {
"lastModified": 1451647621,
"narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=",
"owner": "phadej",
"repo": "HTTP",
"rev": "9bc0996d412fef1787449d841277ef663ad9a915",
"type": "github"
},
"original": {
"owner": "phadej",
"repo": "HTTP",
"type": "github"
}
},
"cabal-32": {
"flake": false,
"locked": {
"lastModified": 1603716527,
"narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=",
"owner": "haskell",
"repo": "cabal",
"rev": "48bf10787e27364730dd37a42b603cee8d6af7ee",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "3.2",
"repo": "cabal",
"type": "github"
}
},
"cabal-34": {
"flake": false,
"locked": {
"lastModified": 1645834128,
"narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=",
"owner": "haskell",
"repo": "cabal",
"rev": "5ff598c67f53f7c4f48e31d722ba37172230c462",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "3.4",
"repo": "cabal",
"type": "github"
}
},
"cabal-36": {
"flake": false,
"locked": {
"lastModified": 1669081697,
"narHash": "sha256-I5or+V7LZvMxfbYgZATU4awzkicBwwok4mVoje+sGmU=",
"owner": "haskell",
"repo": "cabal",
"rev": "8fd619e33d34924a94e691c5fea2c42f0fc7f144",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "3.6",
"repo": "cabal",
"type": "github"
}
},
"cardano-shell": {
"flake": false,
"locked": {
"lastModified": 1608537748,
"narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=",
"owner": "input-output-hk",
"repo": "cardano-shell",
"rev": "9392c75087cb9a3d453998f4230930dea3a95725",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "cardano-shell",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1672831974,
"narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=",
"owner": "input-output-hk",
"repo": "flake-compat",
"rev": "45f2638735f8cdc40fe302742b79f248d23eb368",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"ref": "hkm/gitlab-fix",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1705309234,
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"ghc-8.6.5-iohk": {
"flake": false,
"locked": {
"lastModified": 1600920045,
"narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=",
"owner": "input-output-hk",
"repo": "ghc",
"rev": "95713a6ecce4551240da7c96b6176f980af75cae",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"ref": "release/8.6.5-iohk",
"repo": "ghc",
"type": "github"
}
},
"ghc98X": {
"flake": false,
"locked": {
"lastModified": 1696643148,
"narHash": "sha256-E02DfgISH7EvvNAu0BHiPvl1E5FGMDi0pWdNZtIBC9I=",
"ref": "ghc-9.8",
"rev": "443e870d977b1ab6fc05f47a9a17bc49296adbd6",
"revCount": 61642,
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
},
"original": {
"ref": "ghc-9.8",
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
}
},
"ghc99": {
"flake": false,
"locked": {
"lastModified": 1701580282,
"narHash": "sha256-drA01r3JrXnkKyzI+owMZGxX0JameMzjK0W5jJE/+V4=",
"ref": "refs/heads/master",
"rev": "f5eb0f2982e9cf27515e892c4bdf634bcfb28459",
"revCount": 62197,
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
},
"original": {
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
}
},
"hackage": {
"flake": false,
"locked": {
"lastModified": 1706574159,
"narHash": "sha256-OcE1NT4zQfV4h8Ybq1ttNT+TkXjTV1O2doiCfJzjCbw=",
"owner": "input-output-hk",
"repo": "hackage.nix",
"rev": "ccff69cc942afd51dbdd7466192e3f4cfe09cde2",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "hackage.nix",
"type": "github"
}
},
"haskellNix": {
"inputs": {
"HTTP": "HTTP",
"cabal-32": "cabal-32",
"cabal-34": "cabal-34",
"cabal-36": "cabal-36",
"cardano-shell": "cardano-shell",
"flake-compat": "flake-compat",
"ghc-8.6.5-iohk": "ghc-8.6.5-iohk",
"ghc98X": "ghc98X",
"ghc99": "ghc99",
"hackage": "hackage",
"hls-1.10": "hls-1.10",
"hls-2.0": "hls-2.0",
"hls-2.2": "hls-2.2",
"hls-2.3": "hls-2.3",
"hls-2.4": "hls-2.4",
"hls-2.5": "hls-2.5",
"hls-2.6": "hls-2.6",
"hpc-coveralls": "hpc-coveralls",
"hydra": "hydra",
"iserv-proxy": "iserv-proxy",
"nix-tools-static": "nix-tools-static",
"nixpkgs": [
"haskellNix",
"nixpkgs-unstable"
],
"nixpkgs-2003": "nixpkgs-2003",
"nixpkgs-2105": "nixpkgs-2105",
"nixpkgs-2111": "nixpkgs-2111",
"nixpkgs-2205": "nixpkgs-2205",
"nixpkgs-2211": "nixpkgs-2211",
"nixpkgs-2305": "nixpkgs-2305",
"nixpkgs-2311": "nixpkgs-2311",
"nixpkgs-unstable": "nixpkgs-unstable",
"old-ghc-nix": "old-ghc-nix",
"stackage": "stackage"
},
"locked": {
"lastModified": 1706575804,
"narHash": "sha256-/2oEg1CD3FtXOsF0dQm/5RLGZ5LwILA5Gnuw/FkNm4w=",
"owner": "input-output-hk",
"repo": "haskell.nix",
"rev": "8bc501003577cf9a1077f04d2dabf58f68b256b6",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "haskell.nix",
"type": "github"
}
},
"hls-1.10": {
"flake": false,
"locked": {
"lastModified": 1680000865,
"narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "1.10.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.0": {
"flake": false,
"locked": {
"lastModified": 1687698105,
"narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "783905f211ac63edf982dd1889c671653327e441",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.0.0.1",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.2": {
"flake": false,
"locked": {
"lastModified": 1693064058,
"narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.2.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.3": {
"flake": false,
"locked": {
"lastModified": 1695910642,
"narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.3.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.4": {
"flake": false,
"locked": {
"lastModified": 1699862708,
"narHash": "sha256-YHXSkdz53zd0fYGIYOgLt6HrA0eaRJi9mXVqDgmvrjk=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "54507ef7e85fa8e9d0eb9a669832a3287ffccd57",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.4.0.1",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.5": {
"flake": false,
"locked": {
"lastModified": 1701080174,
"narHash": "sha256-fyiR9TaHGJIIR0UmcCb73Xv9TJq3ht2ioxQ2mT7kVdc=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "27f8c3d3892e38edaef5bea3870161815c4d014c",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.5.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.6": {
"flake": false,
"locked": {
"lastModified": 1705325287,
"narHash": "sha256-+P87oLdlPyMw8Mgoul7HMWdEvWP/fNlo8jyNtwME8E8=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "6e0b342fa0327e628610f2711f8c3e4eaaa08b1e",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.6.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hpc-coveralls": {
"flake": false,
"locked": {
"lastModified": 1607498076,
"narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=",
"owner": "sevanspowell",
"repo": "hpc-coveralls",
"rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430",
"type": "github"
},
"original": {
"owner": "sevanspowell",
"repo": "hpc-coveralls",
"type": "github"
}
},
"hydra": {
"inputs": {
"nix": "nix",
"nixpkgs": [
"haskellNix",
"hydra",
"nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1671755331,
"narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=",
"owner": "NixOS",
"repo": "hydra",
"rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8",
"type": "github"
},
"original": {
"id": "hydra",
"type": "indirect"
}
},
"iserv-proxy": {
"flake": false,
"locked": {
"lastModified": 1691634696,
"narHash": "sha256-MZH2NznKC/gbgBu8NgIibtSUZeJ00HTLJ0PlWKCBHb0=",
"ref": "hkm/remote-iserv",
"rev": "43a979272d9addc29fbffc2e8542c5d96e993d73",
"revCount": 14,
"type": "git",
"url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git"
},
"original": {
"ref": "hkm/remote-iserv",
"type": "git",
"url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git"
}
},
"lowdown-src": {
"flake": false,
"locked": {
"lastModified": 1633514407,
"narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
"owner": "kristapsdz",
"repo": "lowdown",
"rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
"type": "github"
},
"original": {
"owner": "kristapsdz",
"repo": "lowdown",
"type": "github"
}
},
"nix": {
"inputs": {
"lowdown-src": "lowdown-src",
"nixpkgs": "nixpkgs",
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": {
"lastModified": 1661606874,
"narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=",
"owner": "NixOS",
"repo": "nix",
"rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "2.11.0",
"repo": "nix",
"type": "github"
}
},
"nix-tools-static": {
"flake": false,
"locked": {
"lastModified": 1706266250,
"narHash": "sha256-9t+GRk3eO9muCtKdNAwBtNBZ5dH1xHcnS17WaQyftwA=",
"owner": "input-output-hk",
"repo": "haskell-nix-example",
"rev": "580cb6db546a7777dad3b9c0fa487a366c045c4e",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"ref": "nix",
"repo": "haskell-nix-example",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1657693803,
"narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "365e1b3a859281cf11b94f87231adeabbdd878a2",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-22.05-small",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2003": {
"locked": {
"lastModified": 1620055814,
"narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-20.03-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2105": {
"locked": {
"lastModified": 1659914493,
"narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-21.05-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2111": {
"locked": {
"lastModified": 1659446231,
"narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "eabc38219184cc3e04a974fe31857d8e0eac098d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-21.11-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2205": {
"locked": {
"lastModified": 1685573264,
"narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "380be19fbd2d9079f677978361792cb25e8a3635",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-22.05-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2211": {
"locked": {
"lastModified": 1688392541,
"narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-22.11-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2305": {
"locked": {
"lastModified": 1701362232,
"narHash": "sha256-GVdzxL0lhEadqs3hfRLuj+L1OJFGiL/L7gCcelgBlsw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d2332963662edffacfddfad59ff4f709dde80ffe",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-23.05-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2311": {
"locked": {
"lastModified": 1701386440,
"narHash": "sha256-xI0uQ9E7JbmEy/v8kR9ZQan6389rHug+zOtZeZFiDJk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "293822e55ec1872f715a66d0eda9e592dc14419f",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-23.11-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-regression": {
"locked": {
"lastModified": 1643052045,
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
}
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1694822471,
"narHash": "sha256-6fSDCj++lZVMZlyqOe9SIOL8tYSBz1bI8acwovRwoX8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "47585496bcb13fb72e4a90daeea2f434e2501998",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "47585496bcb13fb72e4a90daeea2f434e2501998",
"type": "github"
}
},
"old-ghc-nix": {
"flake": false,
"locked": {
"lastModified": 1631092763,
"narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=",
"owner": "angerman",
"repo": "old-ghc-nix",
"rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8",
"type": "github"
},
"original": {
"owner": "angerman",
"ref": "master",
"repo": "old-ghc-nix",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"haskellNix": "haskellNix",
"nixpkgs": [
"haskellNix",
"nixpkgs-unstable"
]
}
},
"stackage": {
"flake": false,
"locked": {
"lastModified": 1706573344,
"narHash": "sha256-nOc8eVWcS//QjV4tdZlJVMWPyGauD71BNdCXjvTRXDs=",
"owner": "input-output-hk",
"repo": "stackage.nix",
"rev": "c911e99f7ab959a8d2b83c038a803c255a6d215a",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "stackage.nix",
"type": "github"
}
},
"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
}

93
flake.nix Normal file
View file

@ -0,0 +1,93 @@
{
description = "hakyll-nix-template";
nixConfig = {
allow-import-from-derivation = "true";
bash-prompt = "[hakyll-nix]λ ";
extra-substituters = [
"https://cache.iog.io"
];
extra-trusted-public-keys = [
"hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ="
];
};
inputs.haskellNix.url = "github:input-output-hk/haskell.nix";
inputs.nixpkgs.follows = "haskellNix/nixpkgs-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils, haskellNix }:
flake-utils.lib.eachDefaultSystem (system:
let
overlays = [ haskellNix.overlay
(final: prev: {
hakyllProject = final.haskell-nix.project' {
src = ./ssg;
compiler-nix-name = "ghc948";
modules = [{ doHaddock = false; }];
shell.buildInputs = [
hakyll-site
];
shell.tools = {
cabal = "latest";
hlint = "latest";
haskell-language-server = "latest";
};
};
})
];
pkgs = import nixpkgs {
inherit overlays system;
inherit (haskellNix) config;
};
flake = pkgs.hakyllProject.flake {};
executable = "ssg:exe:hakyll-site";
hakyll-site = flake.packages.${executable};
website = pkgs.stdenv.mkDerivation {
name = "website";
buildInputs = [];
src = pkgs.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 = pkgs.lib.optionalString
(pkgs.buildPlatform.libc == "glibc")
"${pkgs.glibcLocales}/lib/locale/locale-archive";
buildPhase = ''
${flake.packages.${executable}}/bin/hakyll-site build --verbose
'';
installPhase = ''
mkdir -p "$out/dist"
cp -a dist/. "$out/dist"
'';
};
in flake // rec {
apps = {
default = flake-utils.lib.mkApp {
drv = hakyll-site;
exePath = "/bin/hakyll-site";
};
};
packages = {
inherit hakyll-site website;
default = website;
};
}
);
}

View file

@ -1,75 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello, world!</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="I announce myself to the world">
<meta name="author" content="My name">
<meta name="keywords" content="hello, announcement">
<meta property="og:site_name" content="My Site Name">
<meta property="og:title" content="Hello, world!">
<meta property="og:url" content="https://my-site.com/hello-world.html">
<meta property="og:description" content="I announce myself to the world">
<meta property="og:image" content="https://my-site.com./images/waiheke-stony-batter.jpg">
<meta property="og:type" content="article">
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:image" content="https://my-site.com./images/waiheke-stony-batter.jpg">
<meta property="twitter:site" content="My Site Name">
<meta property="twitter:title" content="Hello, world!">
<meta property="twitter:description" content="I announce myself to the world">
<meta property="twitter:creator" content="@MyName">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="canonical" href="https://my-site.com/hello-world.html">
<link rel="alternate" href="./atom.xml" title="My Feed Title" type="application/atom+xml">
<link rel="alternate" href="./rss.xml" title="My Feed Title" type="application/rss+xml">
<link rel="stylesheet" href="./css/default.css" />
<link rel="stylesheet" href="./css/code.css" />
</head>
<body>
<main>
<article>
<header>
<h1>
<a href="./hello-world.html">Hello, world!</a>
</h1>
<div>
2020-09-21 (updated: 2020-09-22T12:00:00Z)
</div>
</header>
<section>
<p>Hello, world! I am here!</p>
<p><img
alt="Grapevines among rolling hills leading to the sea"
src="./images/waiheke-stony-batter.jpg"
height="200"
/></p>
<p>Haskell, for example:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">toSlug ::</span> <span class="dt">T.Text</span> <span class="ot">-&gt;</span> <span class="dt">T.Text</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>toSlug <span class="ot">=</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> T.intercalate (T.singleton <span class="ch">&#39;-&#39;</span>) <span class="op">.</span> T.words <span class="op">.</span> T.toLower <span class="op">.</span> clean</span></code></pre></div>
</section>
</article>
</main>
<script defer src="./js/script.js"></script>
</body>
</html>

View file

@ -1,75 +0,0 @@
<!DOCTYPE html>
<html lang="es">
<head>
<title>¡Hola Mundo!</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Me anuncio al mundo">
<meta name="author" content="Mi nombre">
<meta name="keywords" content="hola, anuncio">
<meta property="og:site_name" content="My Site Name">
<meta property="og:title" content="¡Hola Mundo!">
<meta property="og:url" content="https://my-site.com/hola-mundo.html">
<meta property="og:description" content="Me anuncio al mundo">
<meta property="og:image" content="https://my-site.com./images/waiheke-stony-batter.jpg">
<meta property="og:type" content="article">
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:image" content="https://my-site.com./images/waiheke-stony-batter.jpg">
<meta property="twitter:site" content="My Site Name">
<meta property="twitter:title" content="¡Hola Mundo!">
<meta property="twitter:description" content="Me anuncio al mundo">
<meta property="twitter:creator" content="@MiNombre">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="canonical" href="https://my-site.com/hola-mundo.html">
<link rel="alternate" href="./atom.xml" title="My Feed Title" type="application/atom+xml">
<link rel="alternate" href="./rss.xml" title="My Feed Title" type="application/rss+xml">
<link rel="stylesheet" href="./css/default.css" />
<link rel="stylesheet" href="./css/code.css" />
</head>
<body>
<main>
<article>
<header>
<h1>
<a href="./hola-mundo.html">¡Hola Mundo!</a>
</h1>
<div>
2020-09-22 (updated: 2020-09-23T12:00:00Z)
</div>
</header>
<section>
<p>¡Hola Mundo! ¡Estoy aquí!</p>
<p><img
alt="Grapevines among rolling hills leading to the sea"
src="./images/waiheke-stony-batter.jpg"
height="200"
/></p>
<p>Haskell, por ejemplo:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">toSlug ::</span> <span class="dt">T.Text</span> <span class="ot">-&gt;</span> <span class="dt">T.Text</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>toSlug <span class="ot">=</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> T.intercalate (T.singleton <span class="ch">&#39;-&#39;</span>) <span class="op">.</span> T.words <span class="op">.</span> T.toLower <span class="op">.</span> clean</span></code></pre></div>
</section>
</article>
</main>
<script defer src="./js/script.js"></script>
</body>
</html>

View file

@ -1,71 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello, world!</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="This is me saying hello to the world">
<meta property="og:site_name" content="My Site Name">
<meta property="og:title" content="Hello, world!">
<meta property="og:url" content="https://my-site.com/index.html">
<meta property="og:description" content="This is me saying hello to the world">
<meta property="og:image" content="https://my-site.com./images/robert-pearce-UwHN0jU_YqQ-unsplash-800w.jpg">
<meta property="og:type" content="website">
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:image" content="https://my-site.com./images/robert-pearce-UwHN0jU_YqQ-unsplash-800w.jpg">
<meta property="twitter:site" content="My Site Name">
<meta property="twitter:title" content="Hello, world!">
<meta property="twitter:description" content="This is me saying hello to the world">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="canonical" href="https://my-site.com/index.html">
<link rel="alternate" href="./atom.xml" title="My Feed Title" type="application/atom+xml">
<link rel="alternate" href="./rss.xml" title="My Feed Title" type="application/rss+xml">
<link rel="stylesheet" href="./css/default.css" />
<link rel="stylesheet" href="./css/code.css" />
</head>
<body>
<header>
<h1>Hello, world!</h1>
<img
alt="A woman sitting on a bench amongst trees at the end of a boardwalk leading to a pond with mountains in the background"
src="./images/robert-pearce-UwHN0jU_YqQ-unsplash-800w.jpg"
height="300"
/>
</header>
<main>
<section>
<h2>Blog Posts</h2>
<ul>
<li>
<div><a href="./hola-mundo.html">¡Hola Mundo!</a></div>
<small>2020-09-22</small>
</li>
<li>
<div><a href="./hello-world.html">Hello, world!</a></div>
<small>2020-09-21</small>
</li>
</ul>
</section>
</main>
<script defer src="./js/script.js"></script>
</body>
</html>

77
rss.xml
View file

@ -1,77 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>My Feed Title</title>
<link>https://my-site.com</link>
<description><![CDATA[My Site Description]]></description>
<atom:link href="https://my-site.com/rss.xml" rel="self"
type="application/rss+xml" />
<lastBuildDate>2020-09-23T12:00:00Z</lastBuildDate>
<item>
<title>¡Hola Mundo!</title>
<link>https://my-site.com/hola-mundo.html</link>
<description><![CDATA[<main>
<article>
<header>
<h1>
<a href="./hola-mundo.html">¡Hola Mundo!</a>
</h1>
<div>
2020-09-22 (updated: 2020-09-23T12:00:00Z)
</div>
</header>
<section>
<p>¡Hola Mundo! ¡Estoy aquí!</p>
<p><img
alt="Grapevines among rolling hills leading to the sea"
src="./images/waiheke-stony-batter.jpg"
height="200"
/></p>
<p>Haskell, por ejemplo:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">toSlug ::</span> <span class="dt">T.Text</span> <span class="ot">-&gt;</span> <span class="dt">T.Text</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>toSlug <span class="ot">=</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> T.intercalate (T.singleton <span class="ch">&#39;-&#39;</span>) <span class="op">.</span> T.words <span class="op">.</span> T.toLower <span class="op">.</span> clean</span></code></pre></div>
</section>
</article>
</main>
]]></description>
<pubDate>Tue, 22 Sep 2020 00:00:00 UT</pubDate>
<guid>https://my-site.com/hola-mundo.html</guid>
<dc:creator>My Name</dc:creator>
</item>
<item>
<title>Hello, world!</title>
<link>https://my-site.com/hello-world.html</link>
<description><![CDATA[<main>
<article>
<header>
<h1>
<a href="./hello-world.html">Hello, world!</a>
</h1>
<div>
2020-09-21 (updated: 2020-09-22T12:00:00Z)
</div>
</header>
<section>
<p>Hello, world! I am here!</p>
<p><img
alt="Grapevines among rolling hills leading to the sea"
src="./images/waiheke-stony-batter.jpg"
height="200"
/></p>
<p>Haskell, for example:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">toSlug ::</span> <span class="dt">T.Text</span> <span class="ot">-&gt;</span> <span class="dt">T.Text</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>toSlug <span class="ot">=</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> T.intercalate (T.singleton <span class="ch">&#39;-&#39;</span>) <span class="op">.</span> T.words <span class="op">.</span> T.toLower <span class="op">.</span> clean</span></code></pre></div>
</section>
</article>
</main>
]]></description>
<pubDate>Mon, 21 Sep 2020 00:00:00 UT</pubDate>
<guid>https://my-site.com/hello-world.html</guid>
<dc:creator>My Name</dc:creator>
</item>
</channel>
</rss>

View file

8
src/_config.yaml Normal file
View file

@ -0,0 +1,8 @@
# This is a Jekyll config file. Jekyll is used by GitHub
# Pages to manage static site generation / distribution.
# If you don't use GitHub Pages or don't need to customize
# it, you can delete this file and remove its entry in
# `../ssg/src/Main.hs`.
#
# https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/about-github-pages-and-jekyll
include: []

70
src/css/default.css Normal file
View file

@ -0,0 +1,70 @@
:root {
font-size: 62.5%;
box-sizing: border-box;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
html,
body {
min-height: 100vh;
}
body {
font-kerning: normal;
-moz-font-feature-settings: "kern", "liga", "clig", "calt";
-ms-font-feature-settings: "kern", "liga", "clig", "calt";
-webkit-font-feature-settings: "kern", "liga", "clig", "calt";
font-feature-settings: "kern", "liga", "clig", "calt";
scroll-behavior: smooth;
font-size: 2rem;
margin-left: 4ch;
margin-right: 4ch;
}
body,
input,
button {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
h1,
h2 {
font-family: "Palatino Linotype", "Book Antiqua", Palatino, serif;
}
h1 {
font-size: 4.0rem;
}
h2 {
font-size: 2.6rem;
}
small,
p {
font-family: Tahoma, Arial, sans-serif;
}
small {
font-size: 1.6rem;
font-style: italic;
}
p {
font-size: 1.8rem;
}
img,
.sourceCode {
width: max-content;
border-radius: 0.5ch;
}
pre.sourceCode {
padding: 1.5ch 3ch 1.5ch 1.5ch !important;
}
.postMetadata {
opacity: 0.6;
}
@media (prefers-color-scheme: dark) {
body {
background: black;
color: white;
}
}

View file

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View file

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 256 KiB

29
src/index.html Normal file
View file

@ -0,0 +1,29 @@
---
desc: "This is me saying hello to the world"
image: "./images/robert-pearce-UwHN0jU_YqQ-unsplash-800w.jpg"
lang: "en"
stylesheet: "default"
title: "Hello, world!"
---
<header>
<h1>Hello, world!</h1>
<img
alt="A woman sitting on a bench amongst trees at the end of a boardwalk leading to a pond with mountains in the background"
src="./images/robert-pearce-UwHN0jU_YqQ-unsplash-800w.jpg"
height="300"
/>
</header>
<main>
<section>
<h2>Blog Posts</h2>
<ul>
$for(posts)$
<li>
<div><a href=".$url$">$title$</a></div>
<small>$date$</small>
</li>
$endfor$
</ul>
</section>
</main>

View file

@ -0,0 +1,26 @@
---
author: "My name"
authorTwitter: "@MyName"
desc: "I announce myself to the world"
image: "./images/waiheke-stony-batter.jpg"
keywords: "hello, announcement"
lang: "en"
title: "Hello, world!"
updated: "2020-09-22T12:00:00Z"
---
Hello, world! I am here!
<img
alt="Grapevines among rolling hills leading to the sea"
src="./images/waiheke-stony-batter.jpg"
height="200"
/>
Haskell, for example:
```haskell
toSlug :: T.Text -> T.Text
toSlug =
T.intercalate (T.singleton '-') . T.words . T.toLower . clean
```

View file

@ -0,0 +1,26 @@
---
author: "Mi nombre"
authorTwitter: "@MiNombre"
desc: "Me anuncio al mundo"
image: "./images/waiheke-stony-batter.jpg"
keywords: "hola, anuncio"
lang: "es"
title: "¡Hola Mundo!"
updated: "2020-09-23T12:00:00Z"
---
¡Hola Mundo! ¡Estoy aquí!
<img
alt="Grapevines among rolling hills leading to the sea"
src="./images/waiheke-stony-batter.jpg"
height="200"
/>
Haskell, por ejemplo:
```haskell
toSlug :: T.Text -> T.Text
toSlug =
T.intercalate (T.singleton '-') . T.words . T.toLower . clean
```

View file

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="$lang$">
<head>
<title>$title$</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="$desc$">
$if(author)$
<meta name="author" content="$author$">
$endif$
$if(keywords)$
<meta name="keywords" content="$keywords$">
$endif$
<meta property="og:site_name" content="$siteName$">
<meta property="og:title" content="$title$">
<meta property="og:url" content="$root$$url$">
<meta property="og:description" content="$desc$">
$if(image)$
<meta property="og:image" content="$root$$image$">
$endif$
$if(type)$
<meta property="og:type" content="$type$">
$else$
<meta property="og:type" content="website">
$endif$
$if(image)$
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:image" content="$root$$image$">
$endif$
<meta property="twitter:site" content="$siteName$">
<meta property="twitter:title" content="$title$">
<meta property="twitter:description" content="$desc$">
$if(authorTwitter)$
<meta property="twitter:creator" content="$authorTwitter$">
$endif$
<link rel="shortcut icon" href="/favicon.ico">
<link rel="canonical" href="$root$$url$">
<link rel="alternate" href="./atom.xml" title="$feedTitle$" type="application/atom+xml">
<link rel="alternate" href="./rss.xml" title="$feedTitle$" type="application/rss+xml">
<link rel="stylesheet" href="./css/default.css" />
<link rel="stylesheet" href="./css/code.css" />
</head>
<body>
$body$
<script defer src="./js/script.js"></script>
</body>
</html>

16
src/templates/post.html Normal file
View file

@ -0,0 +1,16 @@
<main>
<article>
<header>
<h1>
<a href=".$url$">$title$</a>
</h1>
<div class="postMetadata">
$date$ $if(updated)$(updated: $updated$)$endif$ <br>
$author$
</div>
</header>
<section>
$body$
</section>
</article>
</main>

View file

@ -1,23 +1,16 @@
<?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>https://my-site.com</loc>
<loc>$root$</loc>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
$for(pages)$
<url>
<loc>https://my-site.com/hola-mundo.html</loc>
<lastmod>2020-09-23T12:00:00Z</lastmod>
<loc>$root$$url$</loc>
<lastmod>$if(updated)$$updated$$else$$if(date)$$date$$endif$$endif$</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://my-site.com/hello-world.html</loc>
<lastmod>2020-09-22T12:00:00Z</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
$endfor$
</urlset>

29
ssg/LICENSE Normal file
View file

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2020, Robert Pearce
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

264
ssg/src/Main.hs Normal file
View file

@ -0,0 +1,264 @@
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad (forM_)
import Data.List (isPrefixOf, isSuffixOf)
import Data.Maybe (fromMaybe)
import Hakyll
import qualified Data.Text as T
import qualified Data.Text.Slugger as Slugger
import System.FilePath (takeFileName)
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)
--------------------------------------------------------------------------------
-- PERSONALIZATION
mySiteName :: String
mySiteName = "My Site Name"
mySiteRoot :: String
mySiteRoot = "https://my-site.com"
myFeedTitle :: String
myFeedTitle = "My Feed Title"
myFeedDescription :: String
myFeedDescription = "My Site Description"
myFeedAuthorName :: String
myFeedAuthorName = "My Name"
myFeedAuthorEmail :: String
myFeedAuthorEmail = "me@myemail.com"
myFeedRoot :: String
myFeedRoot = mySiteRoot
--------------------------------------------------------------------------------
-- CONFIG
-- Default configuration: https://github.com/jaspervdj/hakyll/blob/cd74877d41f41c4fba27768f84255e797748a31a/lib/Hakyll/Core/Configuration.hs#L101-L125
config :: Configuration
config =
defaultConfiguration
{ destinationDirectory = "dist"
, ignoreFile = ignoreFile'
, previewHost = "127.0.0.1"
, previewPort = 8000
, providerDirectory = "src"
, storeDirectory = "ssg/_cache"
, tmpDirectory = "ssg/_tmp"
}
where
ignoreFile' path
| "." `isPrefixOf` fileName = False
| "#" `isPrefixOf` fileName = True
| "~" `isSuffixOf` fileName = True
| ".swp" `isSuffixOf` fileName = True
| otherwise = False
where
fileName = takeFileName path
--------------------------------------------------------------------------------
-- 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" mySiteRoot
<> constField "feedTitle" myFeedTitle
<> constField "siteName" mySiteName
<> 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" mySiteRoot
<> constField "siteName" mySiteName
<> 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" mySiteRoot
<> constField "feedTitle" myFeedTitle
<> constField "siteName" mySiteName
<> dateField "date" "%Y-%m-%d"
<> defaultContext
titleCtx :: Context String
titleCtx =
field "title" updatedTitle
--------------------------------------------------------------------------------
-- TITLE HELPERS
replaceAmp :: String -> String
replaceAmp =
replaceAll "&" (const "&amp;")
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 = myFeedTitle
, feedDescription = myFeedDescription
, feedAuthorName = myFeedAuthorName
, feedAuthorEmail = myFeedAuthorEmail
, feedRoot = myFeedRoot
}
--------------------------------------------------------------------------------
-- CUSTOM ROUTE
fileNameFromTitle :: Metadata -> FilePath
fileNameFromTitle =
T.unpack . (`T.append` ".html") . Slugger.toSlug . T.pack . safeTitle
titleRoute :: Metadata -> Routes
titleRoute =
constRoute . fileNameFromTitle

29
ssg/ssg.cabal Normal file
View file

@ -0,0 +1,29 @@
cabal-version: 3.6
name: ssg
version: 0.1.0.0
build-type: Simple
license: BSD-3-Clause
license-file: LICENSE
executable hakyll-site
default-language: Haskell2010
main-is: Main.hs
hs-source-dirs: src
build-depends: base == 4.*
, hakyll == 4.15.*
, filepath >= 1.0
, pandoc >= 2.11
, slugger >= 0.1.0.2
, text >= 1 && < 3
ghc-options: -Wall
-Wcompat
-Widentities
-Wincomplete-record-updates
-Wincomplete-uni-patterns
-Wpartial-fields
-Wredundant-constraints
-O2
-threaded
-rtsopts
-with-rtsopts=-N