Compare commits
10 Commits
configurin
...
712b61059f
Author | SHA1 | Date | |
---|---|---|---|
712b61059f | |||
2ead146d6a | |||
0ac70566cd | |||
809599d830 | |||
2e2f7b9be1 | |||
b0f0d15475 | |||
e951f7217f | |||
f7023b4431 | |||
08ad6fb469 | |||
b93aab5742 |
@ -8,3 +8,4 @@ I live in Espoo Finland. You can contact me on any of the following services.
|
||||
- **Slack**: masser@functionalprogramming.slack.com
|
||||
- **IRC**: MasseR@freenode
|
||||
- **Mastodon**: MasseR@mastodon.social
|
||||
- **Keybase**: [https://keybase.io/MasseR](https://keybase.io/MasseR)
|
||||
|
@ -111,7 +111,7 @@ article .header {
|
||||
|
||||
@media (min-width: 640px) {
|
||||
body {
|
||||
width: 85rem;
|
||||
width: 60rem;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -1,18 +1,6 @@
|
||||
/* Generated by pandoc. */
|
||||
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre.sourceCode
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
/* border: 0; */
|
||||
vertical-align: baseline;
|
||||
}
|
||||
pre.sourceCode
|
||||
{
|
||||
border: 1px solid #ccc;
|
||||
background-color: rgb(238,238,255);
|
||||
padding: 10px;
|
||||
overflow: auto;
|
||||
}
|
||||
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre
|
||||
{ margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; }
|
||||
td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; }
|
||||
td.sourceCode { padding-left: 5px; }
|
||||
.sourceCode span.kw { color: #007020; font-weight: bold; }
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 25 KiB |
@ -28,4 +28,4 @@ My [GPG key](./resources/2104943D6033C.txt)
|
||||
- **Java**
|
||||
- Bunch of different smaller projects while working at Avoltus Oy.
|
||||
- **Other**
|
||||
- I was involved in creating an email solicit platform.
|
||||
- I was involved in creating an email advertising platform.
|
||||
|
22
js/api.js
22
js/api.js
@ -1,22 +0,0 @@
|
||||
|
||||
var getApiIpfsCurrent = function(onSuccess, onError) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '/api/ipfs/current', true);
|
||||
xhr.setRequestHeader('Accept', 'application/json');
|
||||
xhr.onreadystatechange = function () {
|
||||
var res = null;
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status === 204 || xhr.status === 205) {
|
||||
onSuccess();
|
||||
} else if (xhr.status >= 200 && xhr.status < 300) {
|
||||
try { res = JSON.parse(xhr.responseText); } catch (e) { onError(e); }
|
||||
if (res) onSuccess(res);
|
||||
} else {
|
||||
try { res = JSON.parse(xhr.responseText); } catch (e) { onError(e); }
|
||||
if (res) onError(res);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
};
|
||||
|
10
js/app.js
10
js/app.js
@ -1,10 +0,0 @@
|
||||
$(document).ready(function() {
|
||||
var success = function(x) {
|
||||
$("#ipfs > em").html(x);
|
||||
};
|
||||
var error = function(x) {
|
||||
$("#ipfs").hide();
|
||||
console.log("ipfs hash not found: " + x);
|
||||
};
|
||||
getApiIpfsCurrent(success, error);
|
||||
});
|
2
js/jquery-3.3.1.min.js
vendored
2
js/jquery-3.3.1.min.js
vendored
File diff suppressed because one or more lines are too long
7
nixpkgs.json
Normal file
7
nixpkgs.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"url": "https://github.com/NixOS/nixpkgs",
|
||||
"rev": "7e1f60dfbba67b975d1a77d710a6f1437fd9709c",
|
||||
"date": "2020-02-01T09:20:37-05:00",
|
||||
"sha256": "0vk55459iljr5dzwnr5661l44b0wdc15952lk2rjcmxr1620yr5v",
|
||||
"fetchSubmodules": false
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
---
|
||||
title: Extensible configuration Pt. 1
|
||||
date: 2019-03-27
|
||||
---
|
||||
|
||||
This is the first part of a series where I'm going through how to make
|
||||
extensible configuration. There is nothing groundbreaking or new in this
|
||||
series, it's just me going through different implementations and trying to
|
||||
understand them.
|
||||
|
||||
The source material for this post is [the fixed point implementation](https://github.com/NixOS/nixpkgs/blob/master/lib/fixed-points.nix) for nix.
|
||||
|
||||
By extensible configuration, I'm talking about nix style extensible
|
||||
configuration, like overlays, overrides and extensions. Let's see an example of
|
||||
an extensible configuration.
|
||||
|
||||
``` nix
|
||||
{ haskellPackages, fetchFromGitHub }:
|
||||
|
||||
let
|
||||
purescript = fetchFromGitHub {
|
||||
owner = "purescript";
|
||||
repo = "purescript";
|
||||
rev = "2cb4a6496052db726e099539be682b87585af494";
|
||||
sha256 = "1v4gs08xnqgym6jj3drkzbic7ln3hfmflpbpij3qzwxsmqd2abr7";
|
||||
}
|
||||
hp = haskellPackages.extend (self: super: {
|
||||
purescript = super.callCabal2nix "purescript" purescript {};
|
||||
});
|
||||
|
||||
in
|
||||
|
||||
hp.purescript;
|
||||
```
|
||||
|
||||
On a high level we are augmenting the `haskellPackages` attrset by replacing
|
||||
the existing purescript package with a different one. The extension is a
|
||||
function that takes two arguments, `self` and `super`. `super` is the original
|
||||
non-lazy value and `self` is the lazy value that corresponds to the value at
|
||||
end.
|
||||
|
||||
The first step on this journey is done by getting to know `fix`. Fix is
|
||||
described being the least fixed point of a function. In practice it's a
|
||||
function allowing declaring recursive functions without explicit recursion.
|
||||
|
||||
``` nix
|
||||
fix = f: let x = f x; in x
|
||||
```
|
||||
|
||||
With fix you can have access to the lazy `self` value. It's value is whatever
|
||||
would have been computed in the end. As it is lazy, it is possible to end up in
|
||||
a recursive loop if there is a cyclic dependency.
|
||||
|
||||
``` nix
|
||||
let recursive = fix (self: {
|
||||
foo = 3;
|
||||
bar = self.foo + 1;
|
||||
});
|
||||
infinite = fix (self: {
|
||||
foo = self.bar + 1;
|
||||
bar = self.foo + 1;
|
||||
});
|
||||
```
|
||||
|
||||
You can try those yourself. The first version is fine and returns an attrset
|
||||
like you would expect. The second one has a cyclic dependency and nix helpfully
|
||||
errors out.
|
||||
|
||||
The next step is making a function that has access to the unmodified original
|
||||
values. This is managed through the `extends` function. It took a while for me to understand what's happening in there, but luckily nix has [good documentation](https://github.com/NixOS/nixpkgs/blob/67b1265fb3d38ead5a57fee838405a2d997777c2/lib/fixed-points.nix#L37-L65) for it.
|
||||
|
||||
``` nix
|
||||
extends = f: rattrs: self: let super = rattrs self; in super // f self super
|
||||
```
|
||||
|
||||
- https://elvishjerricco.github.io/2017/04/01/nix-style-configs-in-haskell.html
|
||||
- https://github.com/NixOS/nixpkgs/blob/master/lib/fixed-points.nix
|
||||
- https://chshersh.github.io/posts/2019-03-25-comonadic-builders
|
29
release.nix
29
release.nix
@ -1,8 +1,32 @@
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
let
|
||||
pin = builtins.fromJSON (builtins.readFile ./nixpkgs.json);
|
||||
pinnedPkgs = with pin; import (builtins.fetchTarball {
|
||||
url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
|
||||
inherit sha256;
|
||||
}) {};
|
||||
|
||||
in
|
||||
|
||||
{ pkgs ? pinnedPkgs }:
|
||||
|
||||
let
|
||||
haskellPackages = pkgs.haskellPackages;
|
||||
site = pkgs.callPackage ./default.nix {};
|
||||
website = with pkgs; stdenv.mkDerivation {
|
||||
pname = "rauhala.info";
|
||||
version = "0.1.0";
|
||||
src = lib.cleanSource ./.;
|
||||
LANG = "en_US.UTF-8";
|
||||
LOCALE_ARCHIVE = lib.optionalString stdenv.isLinux "${glibcLocales}/lib/locale/locale-archive";
|
||||
buildPhase = ''
|
||||
${site}/bin/site clean
|
||||
${site}/bin/site build
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out/share/
|
||||
mv _site $out/share/html
|
||||
'';
|
||||
};
|
||||
shell = pkgs.buildEnv {
|
||||
name = "site-shell";
|
||||
paths = [];
|
||||
@ -16,6 +40,5 @@ let
|
||||
in
|
||||
|
||||
{
|
||||
site = site;
|
||||
shell = shell;
|
||||
inherit site shell website;
|
||||
}
|
||||
|
39
site.hs
39
site.hs
@ -1,12 +1,18 @@
|
||||
--------------------------------------------------------------------------------
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
import Data.List (sortOn)
|
||||
import Data.Time (defaultTimeLocale, formatTime)
|
||||
import Data.Monoid (mappend)
|
||||
import Hakyll
|
||||
import Data.List (sortBy, sortOn)
|
||||
import Data.Time (formatTime, defaultTimeLocale)
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
main :: IO ()
|
||||
main = hakyllWith defaultConfiguration{ deployCommand = "ipfs add -Q -r _site" } $do
|
||||
main = hakyllWith defaultConfiguration $ do
|
||||
match "well-known/*" $ do
|
||||
route (customRoute (prepend '.'. toFilePath))
|
||||
compile copyFileCompiler
|
||||
|
||||
match "images/*" $ do
|
||||
route idRoute
|
||||
compile copyFileCompiler
|
||||
@ -29,26 +35,6 @@ main = hakyllWith defaultConfiguration{ deployCommand = "ipfs add -Q -r _site" }
|
||||
>>= loadAndApplyTemplate "templates/default.html" defaultContext
|
||||
>>= relativizeUrls
|
||||
|
||||
match "posts/*" $ do
|
||||
route $ setExtension "html"
|
||||
compile $ pandocCompiler
|
||||
>>= loadAndApplyTemplate "templates/post.html" postCtx
|
||||
>>= loadAndApplyTemplate "templates/default.html" postCtx
|
||||
>>= relativizeUrls
|
||||
|
||||
create ["posts.html"] $ do
|
||||
route idRoute
|
||||
compile $ do
|
||||
posts <- modFirst =<< loadAll "posts/*"
|
||||
let archiveCtx =
|
||||
listField "posts" postCtx (return posts) <>
|
||||
constField "title" "Posts" <>
|
||||
defaultContext
|
||||
|
||||
makeItem ""
|
||||
>>= loadAndApplyTemplate "templates/guides.html" archiveCtx
|
||||
>>= loadAndApplyTemplate "templates/default.html" archiveCtx
|
||||
>>= relativizeUrls
|
||||
|
||||
|
||||
match "templates/*" $ compile templateBodyCompiler
|
||||
@ -62,10 +48,13 @@ modFirst = fmap reverse . modified
|
||||
--------------------------------------------------------------------------------
|
||||
postCtx :: Context String
|
||||
postCtx =
|
||||
dateField "date" "%B %e, %Y" <>
|
||||
modifiedField "modified" "%B %e, %Y" <>
|
||||
dateField "date" "%B %e, %Y" `mappend`
|
||||
modifiedField "modified" "%B %e, %Y" `mappend`
|
||||
defaultContext
|
||||
where
|
||||
modifiedField key format = field key $ \i -> do
|
||||
time <- getItemModificationTime $ itemIdentifier i
|
||||
return $ formatTime defaultTimeLocale format time
|
||||
|
||||
prepend :: a -> [a] -> [a]
|
||||
prepend = (:)
|
||||
|
@ -10,15 +10,14 @@
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="logo">
|
||||
<a href="/">rauhala.info</a>
|
||||
</div>
|
||||
<!-- <div class="logo"> -->
|
||||
<!-- <a href="/">rauhala.info</a> -->
|
||||
<!-- </div> -->
|
||||
<nav>
|
||||
<!-- Git logo from https://git-scm.com/downloads/logos -->
|
||||
<!-- Logo by Jason Long -->
|
||||
<a href="https://git.rauhala.info"><img src="/images/git_16.png" alt="git" /></a>
|
||||
<a href="/contact.html">Contact</a>
|
||||
<a href="/posts.html">Posts</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
@ -30,10 +29,6 @@
|
||||
<footer>
|
||||
Site proudly generated by
|
||||
<a href="http://jaspervdj.be/hakyll">Hakyll</a>
|
||||
<span id="ipfs">and found on IPFS as <em></em></ipfs>
|
||||
</footer>
|
||||
</body>
|
||||
<script type="application/javascript" src="/js/jquery-3.3.1.min.js"></script>
|
||||
<script type="application/javascript" src="/js/api.js"></script>
|
||||
<script type="application/javascript" src="/js/app.js"></script>
|
||||
</html>
|
||||
|
@ -1,3 +1,3 @@
|
||||
Me writing out interesting ideas and experiments.
|
||||
A list of small and big guides.
|
||||
|
||||
$partial("templates/post-list.html")$
|
||||
|
111
well-known/keybase.txt
Normal file
111
well-known/keybase.txt
Normal file
@ -0,0 +1,111 @@
|
||||
==================================================================
|
||||
https://keybase.io/masser
|
||||
--------------------------------------------------------------------
|
||||
|
||||
I hereby claim:
|
||||
|
||||
* I am an admin of https://masser.keybase.pub
|
||||
* I am masser (https://keybase.io/masser) on keybase.
|
||||
* I have a public key ASD7WFMicMJhoArgnvPuR7Dc92WStIUWWXcyngnsTE_IaQo
|
||||
|
||||
To do so, I am signing this object:
|
||||
|
||||
{
|
||||
"body": {
|
||||
"key": {
|
||||
"eldest_kid": "01202eb5d3b8d2fc63e4bc9c6edefb3a38f1043dfdc44a7268393951fe0ea5214cf00a",
|
||||
"host": "keybase.io",
|
||||
"kid": "0120fb58532270c261a00ae09ef3ee47b0dcf76592b485165977329e09ec4c4fc8690a",
|
||||
"uid": "b01557931e13482e9e646593a64e9119",
|
||||
"username": "masser"
|
||||
},
|
||||
"merkle_root": {
|
||||
"ctime": 1580587604,
|
||||
"hash": "890506579950548b2aa6fd0f35850b9fdb1d064786714f18515d0e3089cdc2458c5fe847d40ca71c2e021ca11677de055ac97804c53d1bef89432f88b57599d4",
|
||||
"hash_meta": "104419595abc52918530f85495417faf35c7a5a608d6730bf53152dfa7288970",
|
||||
"seqno": 14451686
|
||||
},
|
||||
"service": {
|
||||
"entropy": "QIvRp0qNOIZFplyzXERiwp75",
|
||||
"hostname": "masser.keybase.pub",
|
||||
"protocol": "https:"
|
||||
},
|
||||
"type": "web_service_binding",
|
||||
"version": 2
|
||||
},
|
||||
"client": {
|
||||
"name": "keybase.io go client",
|
||||
"version": "4.3.1"
|
||||
},
|
||||
"ctime": 1580587641,
|
||||
"expire_in": 504576000,
|
||||
"prev": "c99f66ba0bfa7ff6be736e24691c8007b0db41b6036b7f1e5f9335ab7f3550f4",
|
||||
"seqno": 34,
|
||||
"tag": "signature"
|
||||
}
|
||||
|
||||
which yields the signature:
|
||||
|
||||
hKRib2R5hqhkZXRhY2hlZMOpaGFzaF90eXBlCqNrZXnEIwEg+1hTInDCYaAK4J7z7kew3PdlkrSFFll3Mp4J7ExPyGkKp3BheWxvYWTESpcCIsQgyZ9mugv6f/a+c24kaRyAB7DbQbYDa38eX5M1q381UPTEIH8FtgpzXt/JJxrhAYknW7xL4+K57JBJnbhFpXWAfEH5AgHCo3NpZ8RApEnmCcZApdOTf+XAHRbbgoysAZHfyTHamWC/BEHKuqEf/BlUFSxo6ASa/YC+Y2sMJfW2iRFlP2bs822TyJTBA6hzaWdfdHlwZSCkaGFzaIKkdHlwZQildmFsdWXEINm3yJdAbmbGJd03EnpuKVh2JzkI8WkngbWbAxbbR0MMo3RhZ80CAqd2ZXJzaW9uAQ==
|
||||
|
||||
And finally, I am proving ownership of this host by posting or
|
||||
appending to this document.
|
||||
|
||||
View my publicly-auditable identity here: https://keybase.io/masser
|
||||
|
||||
===================================================================
|
||||
https://keybase.io/masser
|
||||
--------------------------------------------------------------------
|
||||
|
||||
I hereby claim:
|
||||
|
||||
* I am an admin of https://rauhala.info
|
||||
* I am masser (https://keybase.io/masser) on keybase.
|
||||
* I have a public key ASD7WFMicMJhoArgnvPuR7Dc92WStIUWWXcyngnsTE_IaQo
|
||||
|
||||
To do so, I am signing this object:
|
||||
|
||||
{
|
||||
"body": {
|
||||
"key": {
|
||||
"eldest_kid": "01202eb5d3b8d2fc63e4bc9c6edefb3a38f1043dfdc44a7268393951fe0ea5214cf00a",
|
||||
"host": "keybase.io",
|
||||
"kid": "0120fb58532270c261a00ae09ef3ee47b0dcf76592b485165977329e09ec4c4fc8690a",
|
||||
"uid": "b01557931e13482e9e646593a64e9119",
|
||||
"username": "masser"
|
||||
},
|
||||
"merkle_root": {
|
||||
"ctime": 1580591326,
|
||||
"hash": "2b1b8c5e3de98e3e80ec4b4c28270066744d5d0982c23e4c13ec97d9311e32996b0cc39ab07f51a2418f833d3f03c0219c7ebd8cdc9c99ac09d3f88d0b6129d1",
|
||||
"hash_meta": "0e85fd563e1159d6c5b32f5c424d4c97101c3a11346a0dad77bdbf043ca4f287",
|
||||
"seqno": 14452336
|
||||
},
|
||||
"service": {
|
||||
"entropy": "7UNm+4us1fZE3TRssgGatBC2",
|
||||
"hostname": "rauhala.info",
|
||||
"protocol": "https:"
|
||||
},
|
||||
"type": "web_service_binding",
|
||||
"version": 2
|
||||
},
|
||||
"client": {
|
||||
"name": "keybase.io go client",
|
||||
"version": "4.3.1"
|
||||
},
|
||||
"ctime": 1580591336,
|
||||
"expire_in": 504576000,
|
||||
"prev": "ed5dd9b2571746743f37dd55f59235bd46d7f7de01a2bafba14b9c0929751aee",
|
||||
"seqno": 35,
|
||||
"tag": "signature"
|
||||
}
|
||||
|
||||
which yields the signature:
|
||||
|
||||
hKRib2R5hqhkZXRhY2hlZMOpaGFzaF90eXBlCqNrZXnEIwEg+1hTInDCYaAK4J7z7kew3PdlkrSFFll3Mp4J7ExPyGkKp3BheWxvYWTESpcCI8Qg7V3ZslcXRnQ/N91V9ZI1vUbX994Borr7oUucCSl1Gu7EIJld9Pai+YxhSvZUIA+ZyzwEEbpy98uEqp975YKAEdz9AgHCo3NpZ8RAtksa9w0UQrwg8dPGEzahht+hY4QKQthbZ/yWuOSmfA3C5E1/KorbIEi+tcy5lkSJqNbZRSqBgpl9zerYw5bbAahzaWdfdHlwZSCkaGFzaIKkdHlwZQildmFsdWXEICy29OKKJc5LUELFLo8kW15N3zex43ussKLFeGLhTDapo3RhZ80CAqd2ZXJzaW9uAQ==
|
||||
|
||||
And finally, I am proving ownership of this host by posting or
|
||||
appending to this document.
|
||||
|
||||
View my publicly-auditable identity here: https://keybase.io/masser
|
||||
|
||||
===================================================================================================================================
|
Reference in New Issue
Block a user