aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob L. Kreuze2019-07-12 20:10:32 -0400
committerJakob L. Kreuze2019-07-13 19:24:32 -0400
commitc9a30e04e8603c9796fec663a2d374e41e2e6031 (patch)
tree013bb0edb1e7d7285cdc6590e16c0bd209284df4
parented1e5a14dc8c13a564b784ee0fa618cd2f63835b (diff)
Rewrite Haunt configuration.
-rw-r--r--haunt/css/jakob.css302
-rw-r--r--haunt/custom/alias.scm44
-rw-r--r--haunt/custom/tag.scm64
-rw-r--r--haunt/custom/theme.scm133
-rw-r--r--haunt/data/blogroll.scm866
-rw-r--r--haunt/data/bookmarks.scm184
-rw-r--r--haunt/haunt.scm116
-rw-r--r--haunt/jakob/builder/blog.scm178
-rw-r--r--haunt/jakob/builder/htaccess.scm (renamed from haunt/weblabels.scm)27
-rw-r--r--haunt/jakob/builder/outbox.scm51
-rw-r--r--haunt/jakob/builder/static-pages.scm48
-rw-r--r--haunt/jakob/reader/html-prime.scm44
-rw-r--r--haunt/jakob/theme.scm101
-rw-r--r--haunt/jakob/utils.scm59
-rw-r--r--haunt/jakob/utils/sxml.scm (renamed from haunt/custom/sxml.scm)35
-rw-r--r--haunt/js/webmention.js140
-rw-r--r--haunt/other/gpg.txt190
-rw-r--r--haunt/outbox.scm57
-rw-r--r--haunt/pages/about.sxml (renamed from haunt/about.scm)6
-rw-r--r--haunt/projects.scm82
-rw-r--r--haunt/static/css/fonts.css (renamed from haunt/css/fonts.css)16
-rw-r--r--haunt/static/css/highlight.css (renamed from haunt/css/highlight.css)0
-rw-r--r--haunt/static/css/normalize.css349
-rw-r--r--haunt/static/css/style.css151
-rw-r--r--haunt/static/font/Cantarell-Bold.otf (renamed from haunt/fonts/Cantarell-Bold.otf)bin69196 -> 69196 bytes
-rw-r--r--haunt/static/font/Cantarell-BoldOblique.otf (renamed from haunt/fonts/Cantarell-BoldOblique.otf)bin75888 -> 75888 bytes
-rw-r--r--haunt/static/font/Cantarell-Oblique.otf (renamed from haunt/fonts/Cantarell-Oblique.otf)bin74892 -> 74892 bytes
-rw-r--r--haunt/static/font/Cantarell-Regular.otf (renamed from haunt/fonts/Cantarell-Regular.otf)bin68340 -> 68340 bytes
-rw-r--r--haunt/static/font/Hack-Bold.ttf (renamed from haunt/fonts/Hack-Bold.ttf)bin317628 -> 317628 bytes
-rw-r--r--haunt/static/font/Hack-BoldItalic.ttf (renamed from haunt/fonts/Hack-BoldItalic.ttf)bin322288 -> 322288 bytes
-rw-r--r--haunt/static/font/Hack-Italic.ttf (renamed from haunt/fonts/Hack-Italic.ttf)bin316156 -> 316156 bytes
-rw-r--r--haunt/static/font/Hack-Regular.ttf (renamed from haunt/fonts/Hack-Regular.ttf)bin309408 -> 309408 bytes
-rw-r--r--haunt/static/image/bad-behavior-debug-prints.pngbin0 -> 2108 bytes
-rw-r--r--haunt/static/image/bad-behavior-vanilla-hexen-vulnerability.pngbin0 -> 82603 bytes
-rw-r--r--haunt/static/image/cc-by-sa-4.0.pngbin0 -> 475 bytes
-rw-r--r--haunt/static/image/favicon.icobin0 -> 5430 bytes
-rw-r--r--haunt/static/image/lambda.svg53
-rw-r--r--haunt/static/image/making-your-own-music-player-analog-vs-digital.pngbin0 -> 11919 bytes
-rw-r--r--haunt/static/image/reverse-engineering-babbys-first-archive-format-basic-parsing.pngbin0 -> 15718 bytes
-rw-r--r--haunt/static/image/reverse-engineering-babbys-first-archive-format-binary-dump.pngbin0 -> 61514 bytes
-rw-r--r--haunt/static/image/reverse-engineering-babbys-first-archive-format-catching-file-reads.pngbin0 -> 407274 bytes
-rw-r--r--haunt/static/image/reverse-engineering-babbys-first-archive-format-xp3-header.pngbin0 -> 9290 bytes
-rw-r--r--haunt/static/image/sdl-tutorial-part-0x00-finished-window.pngbin0 -> 11966 bytes
-rw-r--r--haunt/static/image/sdl-tutorial-part-0x00-window.pngbin0 -> 9405 bytes
44 files changed, 2145 insertions, 1151 deletions
diff --git a/haunt/css/jakob.css b/haunt/css/jakob.css
deleted file mode 100644
index b8a3846..0000000
--- a/haunt/css/jakob.css
+++ /dev/null
@@ -1,302 +0,0 @@
-/* Use smaller fonts and line-height on smaller screens. */
-
-@media (max-width: 54rem) {
- body {
- font-size: 14px;
- line-height: 160%;
- }
-}
-
-@media (max-width: 26rem) {
- body {
- font-size: 12px;
- line-height: 150%;
- }
-}
-
-body {
- color: #4D4D4D;
- background-color: #eee;
- font-family: 'Cantarell', serif;
- line-height: 140%;
- text-rendering: optimizeLegibility;
-}
-
-h1, h2, h3 {
- font-family: 'Cantarell', sans;
-}
-
-h1 {
- font-size: 150%;
- line-height: 110%;
-}
-
-h2 {
- font-size: 115%;
-}
-
-h3 {
- font-size: 100%;
-}
-
-a {
- color: #159957;
- text-decoration: none;
-}
-
-pre {
- font-family: "Hack", monospace;
- font-size: 90%;
- line-height: 110%;
- background-color: #303539;
- padding: 1rem;
- color: #f0e9dc;
- border-radius: 4px;
- overflow-x: scroll;
-}
-
-code {
- font-family: "Hack", monospace;
-}
-
-blockquote {
- padding-left: 2rem;
- border-left: 5px solid #eee;
- font-style: italic;
-}
-
-/* Footer */
-
-footer {
- border-top: 1px solid #ccc;
- font-size: 80%;
-}
-
-.copyright {
- text-align: center;
-}
-
-.cc-button {
- margin-left: 1rem;
-}
-
-/* Navigation */
-
-nav {
- font-family: "Cantarell", sans;
- padding-top: 1rem;
- padding-bottom: 1rem;
- border-bottom: 1px solid #eee;
-}
-
-nav ul {
- list-style-type: none;
- margin: 0;
- padding: 0;
-}
-
-nav a {
- display: inline-block;
- color: #000;
-}
-
-nav a:hover {
- color: #000;
-}
-
-nav a:visited {
- color: #000;
-}
-
-@media (min-width: 800px) {
- nav {
- margin-bottom: 3rem;
- }
-
- nav ul {
- display: inline-block;
- }
-
- nav li {
- display: inline;
- padding: 1rem;
- }
-
- nav li:first-child {
- padding-left: 0;
- }
-}
-
-@media (max-width: 800px) {
- nav ul {
- list-style-type: none;
- margin: 0;
- padding: 0;
- }
-}
-
-/* Container */
-
-@media (min-width: 1140px) {
- .container {
- margin-left: 14rem;
- margin-right: 4rem;
- max-width: 52rem;
- }
-}
-
-@media (min-width: 800px) and (max-width: 1140px) {
- .container {
- margin-left: 6rem;
- margin-right: 4rem;
- max-width: 52rem;
- }
-}
-
-@media (max-width: 800px) {
- .container {
- margin: 1rem;
- }
-}
-
-.fade-text {
- color: #ddd;
-}
-
-/* Summaries */
-
-.summary {
- margin-bottom: 3rem;
-}
-
-.summary .date {
- margin-bottom: 0rem;
-}
-
-.summary p {
- margin-top: 1rem;
- margin-bottom: 1rem;
-}
-
-/* Posts */
-
-.date {
- margin-top: -1rem;
- margin-bottom: 2rem;
- color: #666;
-}
-
-.tags {
- margin-top: -2rem;
- color: #666;
-}
-
-.tags ul {
- display: inline;
- list-style: none;
- padding-left: 0;
-}
-
-.tags li {
- display: inline;
- padding-right: 0.5rem;
-}
-
-.post img, .centered-image {
- display: block;
- max-width: 100%;
- height: auto;
- margin: 0 auto;
- padding: 0px;
- border-radius: 4px;
-}
-
-.post video {
- display: block;
- margin: 0 auto;
- padding: 0px;
- max-width: 100%;
-}
-
-figcaption {
- margin: 1rem 1rem 0 1rem;
- color: #717171;
- font-style: italic;
- font-size: 90%;
-}
-
-.footpara {
- display: inline;
-}
-
-.mastodon {
- width: 70%;
- margin: auto;
-}
-
-.mastodon iframe {
- width: 100%;
-}
-
-#MathJax-Element-4-Frame {
- padding-right: 8px;
-}
-
-table {
- border-spacing: 0;
- border-collapse: collapse;
-}
-
-td, th {
- padding: 8px;
- line-height: 1.42857143;
- vertical-align: top;
- border-top: 1px solid #ddd;
-}
-
-.info {
- background-color: #5bc0de;
-}
-
-.good {
- background-color: #5cb85c;
- border-color: #4cae4c;
-}
-
-.okay {
- background-color: #ec971f;
- border-color: #d58512;
-}
-
-.bad {
- background-color: #dc3545;
-}
-
-.label {
- display: inline;
- padding: .3em .6em .3em;
- font-size: 75%;
- font-weight: 700;
- line-height: 1;
- color: #fff;
- text-align: center;
- white-space: nowrap;
- vertical-align: baseline;
- border-radius: .25em;
-}
-
-/* Webmention */
-
-ul#webmention-container {
- list-style-type: none;
-}
-
-ul#webmention-container img.u-photo {
- width: 4rem;
- padding: 1rem;
- float: left;
-}
-
-ul#webmention-container div.p-author * {
- padding-right: 1rem;
-}
diff --git a/haunt/custom/alias.scm b/haunt/custom/alias.scm
deleted file mode 100644
index 388842a..0000000
--- a/haunt/custom/alias.scm
+++ /dev/null
@@ -1,44 +0,0 @@
-;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
-;;;
-;;; This program is free software; you can redistribute it and/or
-;;; modify it under the terms of the GNU General Public License as
-;;; published by the Free Software Foundation; either version 3 of the
-;;; License, or (at your option) any later version.
-;;;
-;;; This program is distributed in the hope that it will be useful,
-;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;;; General Public License for more details.
-;;;
-;;; You should have received a copy of the GNU General Public License
-;;; along with this program. If not, see
-;;; <http://www.gnu.org/licenses/>.
-
-(define-module (custom alias)
- #:use-module (haunt html)
- #:use-module (haunt page)
- #:export (article-aliases))
-
-(define (article-alias alias target)
- "Create a page named ALIAS that redirects to TARGET."
- (make-page (string-append alias "/index.html")
- `((doctype "html")
- (html
- (head
- (title ,target)
- (link (@ (rel "canonical") (href ,target)))
- (meta (@ (name "robots") (content "noindex")))
- (meta (@ (charset "utf-8")))
- (meta (@ (http-equiv "refresh")
- (content ,(string-append "0; " target)))))))
- sxml->html))
-
-(define (article-aliases aliases)
- "Return a procedure that transforms a list of article ALIASES into pages
-redirecting from one arbitrary file to another."
- (lambda (site posts)
- (map (lambda (pair)
- (let ((alias (car pair))
- (target (cdr pair)))
- (article-alias alias target)))
- aliases)))
diff --git a/haunt/custom/tag.scm b/haunt/custom/tag.scm
deleted file mode 100644
index 3821499..0000000
--- a/haunt/custom/tag.scm
+++ /dev/null
@@ -1,64 +0,0 @@
-;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
-;;;
-;;; This program is free software; you can redistribute it and/or
-;;; modify it under the terms of the GNU General Public License as
-;;; published by the Free Software Foundation; either version 3 of the
-;;; License, or (at your option) any later version.
-;;;
-;;; This program is distributed in the hope that it will be useful,
-;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;;; General Public License for more details.
-;;;
-;;; You should have received a copy of the GNU General Public License
-;;; along with this program. If not, see
-;;; <http://www.gnu.org/licenses/>.
-
-(define-module (custom tag)
- #:use-module (custom theme)
- #:use-module (haunt builder blog)
- #:use-module (haunt html)
- #:use-module (haunt page)
- #:use-module (haunt post)
- #:export (all-tags
- sort-by-tag))
-
-(define (tag-counts posts)
- "Return an alist of every tag used in POSTS paired with the number of times it
-is used."
- (sort (map (lambda (tag) (cons (car tag) (length (cdr tag))))
- (posts/group-by-tag posts))
- (lambda (a b) (> (cdr a) (cdr b)))))
-
-(define (format-tag pair)
- "Return an SXML expression for the tag-count pair."
- (let* ((tag (car pair))
- (count (cdr pair))
- (target (format #f "/tag-~a.html" tag)))
- `(p (a (@ (href ,target)) ,tag)
- ,(format #f " (~a)" count))))
-
-(define (all-tags)
- "Return a procedure creating a page listing all of the tags used in the blog."
- (lambda (site posts)
- (let ((body (append `((h1 "All Tags"))
- (map format-tag (tag-counts posts)))))
- (make-page "tags.html"
- (with-layout jakob-theme site "All Tags" body)
- sxml->html))))
-
-(define (sort-by-tag)
- "Return a procedure that transforms a list of posts into pages containing only
-the posts that have a certain tag."
- (lambda (site posts)
- (map (lambda (pair)
- (let* ((tag-name (car pair))
- (posts (posts/reverse-chronological (cdr pair)))
- (title (format #f "Posts tagged as \"~a\"" tag-name))
- (file-name (format #f "tag-~a.html" tag-name))
- (body `(h1 ,(format #f "Tagged as \"~a\"" tag-name))))
- (make-page
- file-name
- (render-collection jakob-theme site title posts #f)
- sxml->html)))
- (posts/group-by-tag posts))))
diff --git a/haunt/custom/theme.scm b/haunt/custom/theme.scm
deleted file mode 100644
index 64bb87a..0000000
--- a/haunt/custom/theme.scm
+++ /dev/null
@@ -1,133 +0,0 @@
-;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
-;;;
-;;; This program is free software; you can redistribute it and/or
-;;; modify it under the terms of the GNU General Public License as
-;;; published by the Free Software Foundation; either version 3 of the
-;;; License, or (at your option) any later version.
-;;;
-;;; This program is distributed in the hope that it will be useful,
-;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;;; General Public License for more details.
-;;;
-;;; You should have received a copy of the GNU General Public License
-;;; along with this program. If not, see
-;;; <http://www.gnu.org/licenses/>.
-
-(define-module (custom theme)
- #:use-module (custom sxml)
- #:use-module (haunt builder blog)
- #:use-module (haunt post)
- #:use-module (haunt site)
- #:use-module (ice-9 match)
- #:use-module (srfi srfi-19)
- #:export (jakob-theme))
-
-(define (first-paragraph post)
- (let loop ((sxml (post-sxml post))
- (result '()))
- (match sxml
- (() (reverse result))
- ((or (('p ...) _ ...) (paragraph _ ...))
- (reverse (cons paragraph result)))
- ((head . tail)
- (loop tail (cons head result))))))
-
-(define %page-style
- (list (stylesheet "fonts")
- (stylesheet "highlight")
- (stylesheet "jakob")))
-
-(define %page-meta
- '((meta (@ (charset "utf-8")))
- (meta (@ (name "viewport")
- (content "width=device-width, initial-scale=1.0")))))
-
-(define %page-link
- '((link (@ (rel "alternate")
- (type "application/atom+xml")
- (href "/index.xml")))
- (link (@ (rel "icon")
- (type "image/vnd.microsoft.icon")
- (href "/favicon.ico")))
- (link (@ (rel "webmention")
- (href "https://webmention.io/jakob.space/webmention")))
- (link (@ (rel "pingback")
- (href "https://webmention.io/jakob.space/xmlrpc")))
- (link (@ (rel "me")
- (href "https://mastodon.sdf.org/@jakob")))
- (link (@ (rel "pgpkey authn")
- (href "/gpg.txt")))))
-
-(define jakob-theme
- (theme #:name "jakob"
- #:layout
- (lambda (site title body)
- `((doctype "html")
- (html
- (head
- (title ,(string-append title " — " (site-title site)))
- ,@%page-style
- ,@%page-meta
- ,@%page-link)
- (body
- (div (@ (class "container"))
- (nav
- (ul (li ,(link "Jakob L. Kreuze" "/"))
- (li (@ (class "fade-text")) " ")
- (li ,(link "About" "/about.html"))
- (li ,(link "Projects" "/projects.html"))
- (li ,(link "Tags" "/tags.html"))
- (li ,(link "Atom" "/atom.xml"))))
- ,body
- (footer (@ (class "text-center"))
- (p (@ (class "copyright"))
- "© 2019 Jakob L. Kreuze"
- ,%cc-by-sa-button)
- (p "Unless otherwise specified, the text and images
-on this site are free culture works available under the " ,%cc-by-sa-link "
-license.")
- (p "This website is built with "
- ,(link "Haunt" "http://haunt.dthompson.us")
- ", a static site generator written in "
- ,(link "Guile Scheme" "https://gnu.org/software/guile")
- ".")
- (a (@ (href "/weblabels.html")
- (rel "jslicense"))
- (p "JavaScript license information"))))))))
- #:post-template
- (lambda (post)
- `((h1 (@ (class "title"))
- ,(post-ref post 'title))
- (div (@ (class "date"))
- ,(date->string (post-date post) "~B ~d, ~Y"))
- (div (@ (class "tags"))
- (ul
- (li "Tagged as"
- ,@(map (lambda (tag)
- `(li ,(link tag (format #f "/tag-~a.html" tag))))
- (post-ref post 'tags)))))
- (div (@ (class "post")) ,(post-sxml post))
- (hr)
- (h2 ,(link "Webmentions" "https://indieweb.org/Webmention") " for this Page")
- (ul (@ (id "webmention-container")))
- (script (@ (src "/js/webmention.js")))))
- #:collection-template
- (lambda (site title posts prefix)
- (define (post-uri post)
- (string-append "/" (or prefix "")
- (site-post-slug site post) ".html"))
- `((h1 ,title)
- ,(map (lambda (post)
- (let ((uri (string-append "/"
- (site-post-slug site post)
- ".html")))
- `(div (@ (class "summary"))
- (h2 (a (@ (href ,uri))
- ,(post-ref post 'title)))
- (div (@ (class "date"))
- ,(date->string (post-date post) "~B ~d, ~Y"))
- (div (@ (class "post"))
- ,(first-paragraph post))
- (a (@ (href ,uri)) "read more ➔"))))
- posts)))))
diff --git a/haunt/data/blogroll.scm b/haunt/data/blogroll.scm
new file mode 100644
index 0000000..e7a3d2e
--- /dev/null
+++ b/haunt/data/blogroll.scm
@@ -0,0 +1,866 @@
+'(("Adam Sawicki"
+ "http://asawicki.info/"
+ (c++
+ game-development
+ graphics
+ programming
+ video-games
+ windows))
+ ("Bit Cannon"
+ "http://bitcannon.net/"
+ (linux
+ rust
+ programming))
+ ("(proclaim λ)"
+ "http://blog.macrolet.net/"
+ (common-lisp
+ functional-programming
+ hardware
+ lisp
+ programming))
+ ("Brads Blog"
+ "http://bradhodge.ca/blog/"
+ (hardware
+ retro-tech))
+ ("Charlie the Ninja"
+ "http://charliethe.ninja/"
+ (bsd
+ c
+ game-development
+ graphics
+ programming
+ video-games
+ x86))
+ ("DSASMBLR"
+ "http://dsasmblr.com/"
+ (game-hacking
+ reversing
+ security
+ video-games))
+ ("Emacs Horrors"
+ "http://emacshorrors.com/"
+ (emacs
+ emacs-lisp
+ lisp
+ programming))
+ ("Emacs Ninja"
+ "http://emacsninja.com/"
+ (emacs
+ emacs-lisp
+ lisp
+ programming))
+ ("Fabien Sanglard"
+ "http://fabiensanglard.net/"
+ (c
+ c++
+ game-development
+ graphics
+ hardware
+ programming
+ video-games))
+ ("faehnri.ch"
+ "http://faehnri.ch/"
+ (c
+ c++
+ game-hacking
+ reversing
+ video-games))
+ ("gynvael.coldwind//vx.log"
+ "https://gynvael.coldwind.pl/?blog=1&lang=en"
+ (capture-the-flag
+ game-development
+ programming
+ reversing
+ security
+ video-games))
+ ("Michael Nielsen"
+ "http://michaelnielsen.org/blog/"
+ (cogsci
+ math
+ practices
+ programming))
+ ("steve losh"
+ "http://stevelosh.com/blog/"
+ (clojure
+ common-lisp
+ game-development
+ lisp
+ programming
+ video-games))
+ ("jooru//vx tech blog"
+ "http://j00ru.vexillium.org/"
+ (binary-exploitation
+ malware
+ operating-systems
+ reversing
+ security
+ windows))
+ ("Bob Nystrom"
+ "http://journal.stuffwithstuff.com/"
+ (game-development
+ programming
+ video-games))
+ ("Lambda the Ultimate"
+ "http://lambda-the-ultimate.org/"
+ (functional-programming
+ lisp
+ programming
+ scheme))
+ ("Zach Beane Common Lisp"
+ "http://lispblog.xach.com/"
+ (common-lisp
+ lisp
+ programming))
+ ("meh."
+ "http://meh.schizofreni.co/"
+ (c
+ linux
+ programming
+ rust))
+ ("null program"
+ "http://nullprogram.com/"
+ (bsd
+ c
+ c++
+ emacs
+ emacs-lisp
+ graphics
+ linux
+ lisp
+ programming
+ python
+ x86))
+ ("The Official Radare Blog"
+ "http://radare.today/"
+ (c
+ radare2
+ programming
+ reversing))
+ ("妖怪世捨て人"
+ "http://reader.tymoon.eu/"
+ (common-lisp
+ game-development
+ lisp
+ video-games))
+ ("Richard Kallos"
+ "http://rkallos.com/"
+ (functional-programming
+ emacs
+ erlang
+ lisp
+ programming
+ scheme))
+ ("samskivert"
+ "http://samskivert.com/blog/"
+ (functional-programming
+ programming))
+ ("The sh3llc0d3rs blog"
+ "http://sh3llc0d3r.com/"
+ (binary-exploitation
+ capture-the-flag
+ computer-networking
+ security))
+ ("shell-storm"
+ "http://shell-storm.org/"
+ (binary-exploitation
+ c
+ capture-the-flag
+ linux
+ operating-systems
+ reversing
+ security))
+ ("Technomancy"
+ "https://technomancy.us/list"
+ (fennel
+ game-development
+ hardware
+ lisp
+ lua
+ programming
+ video-games))
+ ("Vi Hart"
+ "http://vihart.com/"
+ (math))
+ ("Charles, etc"
+ "http://www.charlesetc.com/"
+ (linux
+ programming
+ rust))
+ ("Notes on Programming"
+ "http://www.codersnotes.com/notes/"
+ (graphics
+ programming
+ reversing
+ video-games))
+ ("defmacro"
+ "http://www.defmacro.org/"
+ (functional-programming
+ linux
+ lisp
+ programming))
+ ("Home Page of Evan Miler"
+ "http://www.evanmiller.org/"
+ (c
+ erlang
+ math
+ programming
+ rust
+ video-games))
+ ("Style Warning"
+ "http://www.stylewarning.com/blog/"
+ (common-lisp
+ lisp
+ math))
+ ("WezM.net"
+ "https://www.wezm.net/"
+ (programming
+ rust))
+ ("0x90r00t"
+ "https://0x90r00t.com/"
+ (binary-exploitation
+ capture-the-flag
+ reversing
+ security))
+ ("aixxe"
+ "https://aixxe.net/"
+ (game-hacking
+ linux
+ reversing
+ video-games))
+ ("Pierre Neidhardts homepage"
+ "https://ambrevar.xyz/"
+ (emacs
+ functional-programming
+ linux
+ lisp
+ programming
+ scheme))
+ ("arp242.net"
+ "https://arp242.net/"
+ (linux
+ programming
+ python))
+ ("The Neo-Babbage Files"
+ "https://babbagefiles.xyz/"
+ (emacs
+ lisp
+ programming))
+ ("Max Bernstein"
+ "https://bernsteinbear.com/blog/"
+ (functional-programming
+ lisp
+ programming))
+ ("dmbaturins blog"
+ "https://blog.baturin.org/"
+ (computer-networking
+ functional-programming
+ linux
+ ocaml
+ programming
+ python
+ x86))
+ ("Andrew Gallants Blog"
+ "https://blog.burntsushi.net/"
+ (linux
+ programming
+ rust))
+ ("The blog at the bottom of the sea"
+ "https://blog.demofox.org/"
+ (crypto
+ game-development
+ graphics
+ math
+ programming
+ video-games))
+ ("Improved Means for Achieving Deteriorated Ends"
+ "https://blog.kingcons.io/"
+ (common-lisp
+ hardware
+ lisp
+ programming
+ retro-tech))
+ ("KRNL386"
+ "https://blog.krnl386.com/"
+ (retro-tech
+ reversing
+ windows))
+ ("Separate Concerns"
+ "https://blog.separateconcerns.com/"
+ (c
+ linux
+ lua
+ programming))
+ ("Lainblog"
+ "https://blog.soykaf.com/"
+ (decentralization
+ programming
+ retro-tech))
+ ("Bluish Coder"
+ "https://bluishcoder.co.nz/"
+ (programming))
+ ("Cryogenix"
+ "https://cryogenix.net/"
+ (bsd
+ retro-tech
+ reversing
+ x86))
+ ("Fedor Indutnys Blog"
+ "https://darksi.de/"
+ (binary-exploitation
+ c++
+ crypto
+ programming
+ security))
+ ("Deftly.net"
+ "https://deftly.net/"
+ (bsd
+ erlang
+ functional-programming
+ haskell
+ programming))
+ ("Bill de hÓra"
+ "https://dehora.net/journal/"
+ (programming
+ rust))
+ ("/dev/krzaq"
+ "https://dev.krzaq.cc/"
+ (c++
+ programming
+ reversing
+ video-games))
+ ("Drew DeVaults Blog"
+ "https://drewdevault.com/"
+ (c
+ go
+ linux
+ programming))
+ ("fuzzy notepad"
+ "https://eev.ee/blog/"
+ (art
+ c
+ doom
+ game-development
+ programming
+ python
+ retro-tech
+ rust
+ video-games))
+ ("Eli Grey"
+ "https://eligrey.com/"
+ (javascript
+ programming))
+ ("https://erkaman.github.io/articles.html"
+ "graphics"
+ (math
+ programming))
+ ("The Brain Dump"
+ "https://floooh.github.io/"
+ (c
+ programming
+ retro-tech
+ reversing))
+ ("Frederik Braun"
+ "https://frederik-braun.com/archives.html"
+ (programming
+ python))
+ ("General Protection Fault"
+ "https://gpfault.net/"
+ (c++
+ graphics
+ opengl
+ programming
+ retro-tech
+ reversing))
+ ("Comfortably Numbered"
+ "https://hardmath123.github.io/"
+ (capture-the-flag
+ functional-programming
+ linux
+ lisp
+ math
+ programming
+ python
+ scheme))
+ ("Infinity Plus One"
+ "https://infinityplusonemath.wordpress.com/"
+ (math))
+ ("jamchambs blog"
+ "https://jamchamb.github.io/"
+ (c
+ hardware
+ powerpc
+ programming
+ retro-tech
+ reversing))
+ ("Daniel Lemires Blog"
+ "https://lemire.me/blog/"
+ (math
+ programming
+ x86))
+ ("Patterns in Cyberspace"
+ "https://leotindall.com/"
+ (decentralization
+ linux
+ programming
+ retro-tech
+ rust))
+ ("Marios Lab"
+ "https://marioslab.io/posts/"
+ (programming))
+ ("Tyler Glaiel"
+ "https://medium.com/@tglaiel"
+ (game-development
+ programming))
+ ("Barely Functional"
+ "https://mgattozzi.com/"
+ (programming
+ rust))
+ ("Mutos Blog"
+ "https://muto.ca/"
+ (emacs
+ functional-programming
+ programming
+ scheme))
+ ("Nerderati"
+ "https://nerderati.com/"
+ (linux
+ math
+ programming
+ python))
+ ("... and another thing ..."
+ "https://nick.zoic.org/"
+ (hardware
+ linux
+ programming
+ python))
+ ("Nick Cano"
+ "https://nickcano.com/"
+ (capture-the-flag
+ game-hacking
+ hardware
+ programming
+ reversing
+ video-games))
+ ("Nora Sandler"
+ "https://norasandler.com/"
+ (c
+ compilers
+ programming))
+ ("codeblog"
+ "https://outflux.net/blog/"
+ (linux
+ operating-systems
+ programming))
+ ("Objective-See"
+ "https://objective-see.com/"
+ (malware
+ reversing
+ security))
+ ("Matt Pharrs blog"
+ "https://pharr.org/matt/blog/"
+ (graphics
+ programming
+ x86))
+ ("phoenhex team"
+ "https://phoenhex.re/"
+ (binary-exploitation
+ reversing
+ security))
+ ("programming is terrible"
+ "https://programmingisterrible.com/"
+ (programming))
+ ("./pwnaccelerator BLOG"
+ "https://pwnaccelerator.github.io/"
+ (crypto
+ hardware
+ reversing
+ security))
+ ("Computable Multiverse"
+ "https://rakhim.org/"
+ (emacs
+ linux
+ math))
+ ("John Ramsden"
+ "https://ramsdenj.com/"
+ (bsd
+ linux))
+ ("RETRO.MOE"
+ "https://retro.moe/"
+ (hardware
+ retro-tech))
+ ("Rufflewinds Scratchpad"
+ "https://rufflewind.com/"
+ (haskell
+ linux
+ programming
+ rust))
+ ("Brandon Skerritt"
+ "https://skerritt.blog/"
+ (crypto
+ programming
+ security))
+ ("Causal Agency"
+ "https://text.causal.agency/"
+ (c
+ programming))
+ ("η (eta)"
+ "https://theta.eu.org/posts.html"
+ (crypto
+ hardware
+ linux
+ programming
+ rust))
+ ("Travis Goodspeeds Blog"
+ "https://travisgoodspeed.blogspot.com/"
+ (ham
+ hardware
+ reversing
+ sdr
+ security))
+ ("Two-Bit History"
+ "https://twobithistory.org/"
+ (linux
+ lisp
+ programming
+ retro-tech))
+ ("Occasionally sane"
+ "https://vfoley.xyz/"
+ (emacs
+ programming
+ rust
+ video-games))
+ ("vmcall"
+ "https://vmcall.github.io/"
+ (game-hacking
+ programming
+ reversing
+ video-games))
+ ("/dev/ram0"
+ "https://wargio.github.io/"
+ (hardware
+ programming
+ radare2
+ reversing))
+ ("mindless-area"
+ "https://wbenny.github.io/posts/"
+ (hardware
+ reversing
+ windows))
+ ("wingolog"
+ "https://wingolog.org/"
+ (functional-programming
+ linux
+ lisp
+ lua
+ programming
+ scheme))
+ ("Wolf480pl"
+ "https://wolf480pl.github.io/"
+ (linux
+ programming))
+ ("Frederic Cambus"
+ "https://www.cambus.net/"
+ (bsd
+ c
+ programming
+ x86))
+ ("The Digital Antiquarian"
+ "https://www.filfre.net/"
+ (hardware
+ retro-tech
+ video-games))
+ ("Kirsle.net"
+ "https://www.kirsle.net/"
+ (crypto
+ go
+ programming
+ security))
+ ("Project Nayuki"
+ "https://www.nayuki.io/"
+ (art
+ c
+ c++
+ crypto
+ math
+ programming
+ x86))
+ ("Inane Observations"
+ "https://yingtongli.me/blog/"
+ (crypto
+ linux
+ math
+ reversing
+ security
+ video-games))
+ ("zayenz"
+ "https://zayenz.se/blog"
+ (programming
+ rust))
+ ("The Stone Zone"
+ "http://thestone.zone/"
+ (hardware
+ lisp
+ programming
+ reversing))
+ ("David Boddie"
+ "http://www.boddie.org.uk/david/www-repo/Personal/Updates/index.html"
+ (programming
+ python
+ reversing))
+ ("Alicefs website"
+ "https://alicef.me/"
+ (gentoo
+ linux))
+ ("~ben"
+ "https://ben.tild3.org/"
+ (linux))
+ ("0day rocks!"
+ "https://0day.rocks/"
+ (crypto
+ hardware
+ linux
+ math
+ programming
+ reversing
+ security
+ tor))
+ ("Eccentric J"
+ "https://eccentric-j.com/"
+ (art
+ clojure
+ functional-programming
+ lisp
+ programming))
+ ("Prosthetic Conscience"
+ "https://jfm.carcosa.net/blog/"
+ (linux
+ programming))
+ ("Max Justicz"
+ "https://justi.cz/"
+ (binary-exploitation
+ reversing
+ security))
+ ("The Obscuritory"
+ "https://obscuritory.com/feed/"
+ (retro-tech
+ video-games))
+ ("Jon Gjengset"
+ "https://thesquareplanet.com/"
+ (linux
+ programming
+ rust
+ security))
+ ("rtl-sdr.com"
+ "https://www.rtl-sdr.com/"
+ (gnuradio
+ ham
+ hardware
+ programming
+ sdr))
+ ("pancake"
+ "https://medium.com/@trufae"
+ (c
+ programming
+ radare2
+ rust))
+ ("hexxendmns.motd.org"
+ "https://hexxendmns.motd.org/"
+ (doom
+ linux
+ mapping
+ programming
+ quake
+ video-games))
+ ("Random ASCII – tech blog of Bruce Dawson"
+ "https://randomascii.wordpress.com/"
+ (compilers
+ hardware
+ powerpc
+ programming
+ windows
+ x86))
+ ("David Thompson"
+ "https://dthompson.us/"
+ (emacs
+ guile
+ guix
+ linux
+ programming
+ scheme))
+ ("InvisibleUp"
+ "https://invisibleup.com/"
+ (graphics
+ programming
+ retro-tech
+ reversing
+ video-games))
+ ("ancientelectronics"
+ "https://ancientelectronics.wordpress.com/"
+ (hardware
+ retro-tech))
+ ("North Coast News"
+ "https://northcoastsynthesis.com/news/"
+ (hardware))
+ ("Bodil dot lol"
+ "https://bodil.lol/"
+ (compilers
+ programming
+ rust))
+ ("Bits, pixels, cycles and more"
+ "https://zeux.io/"
+ (c++
+ graphics
+ programming))
+ ("Bill Demirkapis Blog"
+ "https://d4stiny.github.io/"
+ (reversing
+ security))
+ ("blitter.net"
+ "https://blitter.net/"
+ (hardware
+ retro-tech
+ reversing))
+ ("Breaking Eggs And Making Omelettes"
+ "https://multimedia.cx/eggs/feed/"
+ (programming
+ retro-tech
+ reversing
+ video-games
+ x86))
+ ("Halestroms Peregrinations"
+ "https://halestrom.net/darksleep/"
+ (hardware
+ linux
+ programming))
+ ("VeXation"
+ "https://log.vexation.ca/"
+ (malware
+ programming
+ retro-tech
+ reversing
+ windows))
+ ("Skys blog"
+ "https://byebyesky.github.io/blog/"
+ (capture-the-flag
+ hardware
+ programming
+ reversing
+ security))
+ ("Something Something Programming"
+ "https://nickdrozd.github.io/"
+ (common-lisp
+ emacs
+ functional-programming
+ lisp
+ math
+ programming
+ rust))
+ ("evilsocket"
+ "https://www.evilsocket.net/"
+ (computer-networking
+ go
+ programming
+ reversing
+ security))
+ ("GovanifY"
+ "https://govanify.com/post/"
+ (capture-the-flag
+ linux
+ programming
+ retro-tech
+ reversing
+ security))
+ ("Code of Connor"
+ "https://codeofconnor.com/"
+ (game-development
+ linux
+ programming))
+ ("cowlark.com"
+ "http://cowlark.com/"
+ (hardware
+ programming
+ retro-tech))
+ ("danluu.com/"
+ "https://danluu.com/"
+ (hardware
+ linux
+ programming))
+ ("PapaTutuWawas Blog"
+ "https://blog.latinise.me/"
+ (linux))
+ ("Catbolis Blog"
+ "linux"
+ (programming
+ retro-tech))
+ ("Tristans Site"
+ "http://thume.ca/archive.html"
+ (capture-the-flag
+ compilers
+ programming
+ rust
+ security))
+ ("people.kernel.org"
+ "https://people.kernel.org/read"
+ (linux
+ operating-systems
+ programming))
+ ("TheFloWs security blog"
+ "https://theofficialflow.github.io/"
+ (binary-exploitation
+ hardware
+ reversing
+ security))
+ ("Christine Dodrills Blog"
+ "https://christine.website/blog"
+ (linux
+ programming))
+ ("DustyCloud Brainstorms"
+ "https://dustycloud.org/blog/"
+ (functional-programming
+ lisp
+ programming
+ scheme))
+ ("Hot Leaves in a Cold Worlds"
+ "http://www.philipzucker.com/"
+ (functional-programming
+ hardware
+ haskell
+ math
+ programming
+ python))
+ ("Youve Reached the Center of the Internet"
+ "http://blog.benwiener.com/"
+ (functional-programming
+ ham
+ hardware
+ haskell
+ programming))
+ ("Grievers Notes"
+ "https://romhack.github.io/doc/"
+ (programming
+ retro-tech
+ reversing
+ video-games))
+ ("samiss blag"
+ "https://foldmap.ml/~samis/"
+ (gentoo
+ guix
+ linux))
+ ("James Technical Notes"
+ "https://jamestechnotes.com/blog/"
+ (android
+ c
+ functional-programming
+ guile
+ guix
+ linux
+ programming
+ scheme))
+ ("Aearnus' Realm"
+ "https://aearnus.github.io/"
+ '(functional-programming
+ haskell
+ math
+ perl6
+ programming
+ python)))
diff --git a/haunt/data/bookmarks.scm b/haunt/data/bookmarks.scm
new file mode 100644
index 0000000..3a27614
--- /dev/null
+++ b/haunt/data/bookmarks.scm
@@ -0,0 +1,184 @@
+'(("Finding and Exploiting Hidden Features of Animal Crossings NES Emulator"
+ "https://jamchamb.github.io/2018/07/11/animal-crossing-nes-emulator-hacks.html"
+ (binary-exploitation
+ c
+ dolphin
+ game-hacking
+ ida
+ powerpc
+ retro-tech
+ reversing
+ video-games))
+ ("Disassembling Jak & Daxter"
+ "http://www.codersnotes.com/notes/disassembling-jak/"
+ (lisp
+ mips
+ retro-tech
+ reversing
+ video-games))
+ ("VMU Hackery"
+ "http://dmitry.gr/index.php?r=05.Projects&proj=25.%20VMU%20Hacking"
+ (hardware
+ retro-tech
+ reversing))
+ ("Fixing a bug in an 18 year old Shockwave game"
+ "https://mattbruv.github.io/ccsr-bugfix/"
+ (game-hacking
+ retro-tech
+ reversing
+ video-games))
+ ("Battletoads text decompression (huffman)"
+ "https://forums.nesdev.com/viewtopic.php?t=8609"
+ (6502
+ retro-tech
+ reversing
+ video-games))
+ ("Investigating a recent ebook DRM system (c. 2018)"
+ "https://yingtongli.me/blog/2019/03/28/drm2.html"
+ (android
+ arm
+ reversing))
+ ("Looking inside the box"
+ "https://anvilventures.com/blog/looking-inside-the-box.html"
+ (python
+ reversing))
+ ("Adventures in reverse engineering Broadcom NIC firmware"
+ "https://www.devever.net/~hl/ortega"
+ (arm
+ hardware
+ reversing
+ x86))
+ ("A Great Old-Timey Game-Programming Hack"
+ "http://blog.moertel.com/posts/2013-12-14-great-old-timey-game-programming-hack.html"
+ (6502
+ game-development
+ programming
+ retro-tech
+ video-games))
+ ("CGA in 1024 Colors - a New Mode: the Illustrated Guide"
+ "https://int10h.org/blog/2015/04/cga-in-1024-colors-new-mode-illustrated/"
+ (dos
+ hardware
+ graphics
+ retro-tech))
+ ("Ubershaders: A Ridiculous Solution to an Impossible Problem"
+ "https://dolphin-emu.org/blog/2017/07/30/ubershaders/"
+ (dolphin
+ graphics
+ hardware
+ opengl
+ programming
+ video-games))
+ ("GDCCs Memory Model"
+ "http://ipfsgw.greyserv.net/ipns/davidph.greyserv.net/blog/GDCC_Memory_Model.html"
+ (c
+ doom
+ programming
+ video-games))
+ ("What the Hero Sees: Field-of-View for Roguelikes "
+ "http://journal.stuffwithstuff.com/2015/09/07/what-the-hero-sees/"
+ (programming
+ algorithms
+ dart
+ game-development
+ interactive
+ video-games))
+ ("A Constructive Look At TempleOS"
+ "http://www.codersnotes.com/notes/a-constructive-look-at-templeos/"
+ (operating-systems
+ programming))
+ ("Guix: A most advanced operating system"
+ "https://ambrevar.xyz/guix-advance/index.html"
+ (functional-programming
+ guile
+ guix
+ linux
+ lisp
+ programming
+ scheme))
+ ("Lisp Hackers"
+ "https://leanpub.com/lisphackers/read"
+ (culture
+ lisp
+ practices
+ programming))
+ ("Pascal Costanzas Highly Opinionated Guide to Lisp"
+ "http://www.p-cos.net/lisp/guide.html"
+ (common-lisp
+ lisp
+ programming))
+ ("The Nature of Lisp"
+ "http://www.defmacro.org/ramblings/lisp.html"
+ (java
+ lisp
+ programming))
+ ("A Road to Common Lisp"
+ "http://stevelosh.com/blog/2018/08/a-road-to-common-lisp/"
+ (common-lisp
+ lisp
+ programming))
+ ("Meta-Circular Adventures in Functional Abstraction"
+ "https://web.archive.org/web/20160609222905/https://chriskohlhepp.wordpress.com/metacircular-adventures-in-functional-abstraction-challenging-clojure-in-common-lisp/"
+ (common-lisp
+ functional-programming
+ lisp
+ programming))
+ ("fibs, lies, and benchmarks"
+ "https://wingolog.org/archives/2019/06/26/fibs-lies-and-benchmarks"
+ (functional-programming
+ lisp
+ optimization
+ programming
+ programming-languages
+ scheme))
+ ("Chaining Functions Without Returning Self"
+ "https://randompoison.github.io/posts/returning-self/"
+ (programming
+ rust))
+ ("Implementing a NES Emulator in Rust"
+ "http://www.michaelburge.us/2019/03/18/nes-design.html"
+ (6502
+ hardware
+ programming
+ rust
+ video-games))
+ ("Building a Homebrew Video Game Console"
+ "https://internalregister.github.io/2019/03/14/Homebrew-Console.html"
+ (c
+ hardware
+ programming
+ z80))
+ ("In Noisy Digital Era, Elegant Internet Still Thrives"
+ "https://www.npr.org/2012/04/17/150817325/in-noisy-digital-era-elegant-internet-still-thrives"
+ (culture))
+ ("Codecademy vs. The BBC Micro"
+ "https://twobithistory.org/2019/03/31/bbc-micro.html"
+ (culture
+ historical))
+ ("Graying Out"
+ "https://www.tbray.org/ongoing/When/201x/2019/03/11/Lights-Going-Out"
+ (culture
+ jabber))
+ ("Does Visual Studio Rot the Mind?"
+ "http://www.charlespetzold.com/etc/DoesVisualStudioRotTheMind.html"
+ (practices
+ programming))
+ ("Software disenchantment"
+ "http://tonsky.me/blog/disenchantment/"
+ (culture
+ programming))
+ ("Writing system software: code comments."
+ "http://antirez.com/news/124"
+ (programming))
+ ("Indirection Is Not Abstraction"
+ "https://www.silasreinagel.com/blog/2018/10/30/indirection-is-not-abstraction/"
+ (programming))
+ ("Augmenting Long-term Memory"
+ "http://augmentingcognition.com/ltm.html"
+ (cogsci))
+ ("The Process of Mastering a Skill"
+ "https://azeria-labs.com/the-process-of-mastering-a-skill/"
+ (cogsci))
+ ("Writing well"
+ "http://www.defmacro.org/2016/12/22/writing-well.html"
+ (writing)))
diff --git a/haunt/haunt.scm b/haunt/haunt.scm
index 1700068..c5ef247 100644
--- a/haunt/haunt.scm
+++ b/haunt/haunt.scm
@@ -14,53 +14,16 @@
;;; along with this program. If not, see
;;; <http://www.gnu.org/licenses/>.
-(use-modules (custom alias)
- (custom tag)
- (custom theme)
- (haunt asset)
+(use-modules (haunt builder assets)
(haunt builder atom)
- (haunt builder assets)
- (haunt builder blog)
- (haunt html)
- (haunt page)
(haunt post)
- (haunt reader)
(haunt site)
- (sxml simple)
+ (jakob builder blog)
+ (jakob builder htaccess)
+ (jakob builder static-pages)
+ (jakob reader html-prime)
(srfi srfi-19)
- (srfi srfi-26)
- (ice-9 match))
-
-(define (static-page title slug)
- "Return a procedure serving statically-defined SXML."
- (lambda (site posts)
- (let ((file-name (format #f "~a.html" slug))
- (body (load (format #f "~a.scm" slug))))
- (make-page file-name
- (with-layout jakob-theme site title body)
- sxml->html))))
-
-(define (make-slug post)
- "Create a post slug from the source's filename."
- (let* ((file-name (post-file-name post))
- (splice-start (1+ (string-rindex file-name (cut char=? <> #\/))))
- (splice-end (string-rindex file-name (cut char=? <> #\.))))
- (substring file-name splice-start splice-end)))
-
-;; Use a temporary reader until my patch makes it into an upstream release.
-(define (read-html-post-prime port)
- (values (read-metadata-headers port)
- (let loop ((ret '()))
- (catch 'parser-error
- (lambda ()
- (match (xml->sxml port)
- (('*TOP* sxml) (loop (cons sxml ret)))))
- (lambda (key . parameters)
- (reverse ret))))))
-
-(define html-reader-prime
- (make-reader (make-file-extension-matcher "html")
- (cut call-with-input-file <> read-html-post-prime)))
+ (srfi srfi-26))
;; Replace Haunt's default 'string->date* function with one that recognizes the
;; date format that Org uses.
@@ -72,70 +35,15 @@
(register-metadata-parser! 'date org-string->date)
-(define %collections
- `(("Recent Posts" "index.html" ,posts/reverse-chronological)))
-
-(define %aliases
- (list (cons "blog/post/Bad BEHAVIOR"
- "/reverse-engineering-babbys-first-archive-format.html")
- (cons "blog/post/First Impressions of the Rust Programming Language"
- "/first-impressions-of-the-rust-programming-language.html")
- (cons "blog/post/Duke on FluidSynth"
- "/duke-on-fluidsynth.html")
- (cons "posts/analyzing-executable-size-part-0"
- "/analyzing-executable-size-part-0.html")
- (cons "posts/backdoorctf-2017-funsignals"
- "/backdoorctf-2017-funsignals.html")
- (cons "posts/bad-behavior"
- "/bad-behavior.html")
- (cons "posts/challenges-re-writeups-1"
- "/challenges-re-writeups-1.html")
- (cons "posts/decompilation-by-hand"
- "/decompilation-by-hand.html")
- (cons "posts/duke-on-fluidsynth"
- "/duke-on-fluidsynth.html")
- (cons "posts/first-impressions-of-the-kotlin-programming-language"
- "/first-impressions-of-the-kotlin-programming-language.html")
- (cons "posts/first-impressions-of-the-rust-programming-language"
- "/first-impressions-of-the-rust-programming-language.html")
- (cons "posts/installing-gentoo-one-month-later"
- "/installing-gentoo-one-month-later.html")
- (cons "posts/making-your-own-music-player"
- "/making-your-own-music-player.html")
- (cons "posts/new-ambitions-for-a-new-year"
- "/new-ambitions-for-a-new-year.html")
- (cons "posts/plaidctf-2019"
- "/plaidctf-2019.html")
- (cons "posts/reverse-engineering-babbys-first-archive-format"
- "/reverse-engineering-babbys-first-archive-format.html")
- (cons "posts/sdl-tutorial-part-0x00"
- "/sdl-tutorial-part-0x00.html")
- (cons "posts/slime-the-world-postmortem"
- "/slime-the-world-postmortem.html")
- (cons "posts/understand-game-hacking-in-one-post"
- "/understand-game-hacking-in-one-post.html")))
-
(site #:title "Jakob's Personal Webpage"
#:domain "jakob.space"
#:default-metadata
'((author . "Jakob L. Kreuze")
(email . "zerodaysfordays@sdf.lonestar.org"))
- #:make-slug make-slug
#:readers (list html-reader-prime)
- #:builders (list (blog #:theme jakob-theme #:collections %collections)
- (article-aliases %aliases)
- (atom-feed #:file-name "atom.xml")
- (all-tags)
- (sort-by-tag)
- (static-page "About Me" "about")
- (static-page "Projects" "projects")
- (static-page "Webmention Outbox" "outbox")
- (static-page "JavaScript Web Labels" "weblabels")
- (static-directory "css")
- (static-directory "fonts")
- (static-directory "js")
- (static-directory "images")
- (lambda (site posts)
- (make-asset "other/gpg.txt" "/gpg.txt"))
- (lambda (site posts)
- (make-asset "images/favicon.ico" "/favicon.ico"))))
+ #:builders
+ (list (atom-feed)
+ (blog)
+ (htaccess #:handler-404 "pages/404.html")
+ (static-pages)
+ (static-directory "static")))
diff --git a/haunt/jakob/builder/blog.scm b/haunt/jakob/builder/blog.scm
new file mode 100644
index 0000000..2ed99e3
--- /dev/null
+++ b/haunt/jakob/builder/blog.scm
@@ -0,0 +1,178 @@
+;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License as
+;;; published by the Free Software Foundation; either version 3 of the
+;;; License, or (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+(define-module (jakob builder blog)
+ #:use-module (haunt html)
+ #:use-module (haunt page)
+ #:use-module (haunt post)
+ #:use-module (haunt utils)
+ #:use-module (ice-9 format)
+ #:use-module (ice-9 match)
+ #:use-module (jakob theme)
+ #:use-module (jakob utils)
+ #:use-module (jakob utils sxml)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-19)
+ #:use-module (srfi srfi-26)
+ #:export (blog))
+
+;;; Commentary:
+;;;
+;;; In favor of greater flexibility, Haunt's default 'blog' builder was not used
+;;; for this site. This modules implements a similar builder, 'blog', with
+;;; pagination and support for tag navigation.
+;;;
+;;; Code:
+
+
+;;;
+;;; Rendering.
+;;;
+
+(define (render-article post)
+ "Return the SHTML for POST's contents."
+ `(main
+ (h1 ,(post-ref post 'title))
+ (p ,(date->string (post-date post) "~B ~d, ~Y")
+ " ❖ "
+ "Tags: "
+ ,@(intersperse
+ (map (lambda (tag)
+ (hyperlink (format #f "/tag-~a.html" tag) tag))
+ (post-ref post 'tags))
+ ", "))
+ (article
+ ,(post-sxml post))))
+
+(define (render-preview post)
+ "Return the SHTML for a preview of POST."
+ (let ((crosspost-uri (post-ref post 'crosspost))
+ (local-uri (post-uri post)))
+ `(section
+ (h2 ,(hyperlink (or crosspost-uri local-uri) (post-ref post 'title)))
+ (p ,@(maybe-cons*
+ (date->string (post-date post) "~B ~d, ~Y")
+ (when crosspost-uri
+ (list " ⮀ " (hyperlink local-uri "Crosspost")))
+ " ❖ Tags: "
+ (intersperse
+ (map (lambda (tag)
+ (hyperlink (format #f "/tag-~a.html" tag) tag))
+ (post-ref post 'tags))
+ ", ")))
+ (p ,(first-paragraph post))
+ ,(hyperlink (or crosspost-uri local-uri) "read more 🢩"))))
+
+(define (render-listing posts title previous-page next-page)
+ "Return SHTML presenting previews for POSTS, with the header TITLE and links
+to PREVIOUS-PAGE and NEXT-PAGE."
+ `((h1 ,title)
+ ,@(map render-preview posts)
+ (nav
+ (@ (id "pagination"))
+ ,@(maybe-list
+ (when previous-page
+ (hyperlink previous-page "🢨 Previous Page"))
+ (when next-page
+ (hyperlink next-page "Next Page 🢩"))))))
+
+
+;;;
+;;; Creation of permalink pages for individual posts.
+;;;
+
+;; Subdirectory for permalink pages.
+(define %prefix "blog")
+
+(define (post-uri post)
+ "Return the path of POST relative to the site's base directory."
+ (let* ((file-name (post-file-name post))
+ (splice-start (1+ (string-rindex file-name (cut char=? <> #\/))))
+ (splice-end (string-rindex file-name (cut char=? <> #\.)))
+ (slug (substring file-name splice-start splice-end)))
+ (string-append %prefix "/" slug ".html")))
+
+(define (post->page post)
+ "Return a Haunt page for POST."
+ (make-page (post-uri post)
+ (theme #:title (post-ref post 'title)
+ #:description (first-paragraph post)
+ #:keywords (post-ref post 'tags)
+ #:content (render-article post))
+ sxml->html))
+
+
+;;;
+;;; Implementation of pagination.
+;;;
+
+(define %posts-per-page 10)
+
+(define* (paginate posts #:optional (posts-per-page %posts-per-page))
+ "Partition POSTS into list of no more than POSTS-PER-PAGE posts, of the
+form (index, posts)."
+ (let loop ((index 1)
+ (lst posts)
+ (result '()))
+ (if (null? lst)
+ result
+ (let ((how-many (min %posts-per-page (length lst))))
+ (loop (1+ index)
+ (drop lst how-many)
+ (cons (list index (take lst how-many))
+ result))))))
+
+(define (post-list->pages base-title base-file-name posts)
+ "Return a list of Haunt pages for POST, with headers containing BASE-TITLE and
+output file names beginning with BASE-FILE-NAME."
+ (define (index->file-name index)
+ (if (= index 1)
+ (format #f "~a.html" base-file-name)
+ (format #f "~a-~a.html" base-file-name index)))
+ (map (match-lambda
+ ((index subset)
+ (let ((title (if (= index 1)
+ base-title
+ (format #f "~a — Page ~a" base-title index)))
+ (previous-page (if (>= (1- index) 1)
+ (index->file-name (1- index))
+ #f))
+ (next-page (if (<= (1+ index) (ceiling/ (length posts)
+ %posts-per-page))
+ (index->file-name (1+ index))
+ #f)))
+ (make-page (index->file-name index)
+ (theme #:title title
+ #:content
+ (render-listing subset title
+ previous-page next-page))
+ sxml->html))))
+ (paginate posts)))
+
+
+;;;
+;;; Builder.
+;;;
+
+(define (blog)
+ "Return a Haunt build procedure to create permalinks and post listings for all
+of the 'post' objects associated with the site."
+ (lambda (site posts)
+ (append
+ (map post->page posts)
+ (post-list->pages
+ "Recent Posts" "index"
+ (posts/reverse-chronological posts)))))
diff --git a/haunt/weblabels.scm b/haunt/jakob/builder/htaccess.scm
index 9e0851a..fd20eca 100644
--- a/haunt/weblabels.scm
+++ b/haunt/jakob/builder/htaccess.scm
@@ -14,11 +14,22 @@
;;; along with this program. If not, see
;;; <http://www.gnu.org/licenses/>.
-`((h2 "JavaScript Web Labels")
- (table (@ (id "jslicense-labels1"))
- (tr (td (a (@ (href "/js/webmention.js"))
- (p "/js/webmention.js")))
- (td (a (@ (href "http://www.gnu.org/licenses/gpl-3.0.html"))
- (p "GNU General Public License 3.0 or later")))
- (td (a (@ (href "/js/webmention.js"))
- (p "/js/webmention.js"))))))
+(define-module (jakob builder htaccess)
+ #:use-module (haunt page)
+ #:export (htaccess))
+
+(define* (htaccess-writer contents #:optional (port (current-output-port)))
+ (display (string-join contents "\n") port)
+ (newline port))
+
+;; TODO: https://help.dreamhost.com/hc/en-us/articles/215747748-How-can-I-redirect-and-rewrite-my-URLs-with-an-htaccess-file-
+(define* (htaccess #:key handler-404)
+ "Create an .htaccess file at the site's root.
+
+HANDLER-404 specifies the file name of the page to display for a 404 not found."
+ (define contents
+ `(,(if handler-404
+ (format #f "ErrorDocument 404 ~a" handler-404))))
+
+ (lambda (site posts)
+ (make-page ".htaccess" contents htaccess-writer)))
diff --git a/haunt/jakob/builder/outbox.scm b/haunt/jakob/builder/outbox.scm
new file mode 100644
index 0000000..851ed88
--- /dev/null
+++ b/haunt/jakob/builder/outbox.scm
@@ -0,0 +1,51 @@
+;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License as
+;;; published by the Free Software Foundation; either version 3 of the
+;;; License, or (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+(define-module (jakob builder outbox)
+ #:use-module (haunt page)
+ #:export (outbox))
+
+;;; Commentary:
+;;;
+;;; Implementation of a multi-page Webmention outbox. See
+;;; <https://webmention.net/> for details.
+;;;
+;;; Code:
+
+;; `((doctype "html")
+;; (meta (@ (charset "utf-8")))
+;; (title ,title)
+;; (div (@ (class "h-entry"))
+;; (img (@ (src ,profile-picture) (class "u-photo") (width "40")))
+;; (a (@ (href ,profile-url) (class "u-url p-name")) ,profile-name))
+;; (p "in reply to:" (a (@ (href ,target-url) (class "u-in-reply-to"))
+;; ,target-handle))
+;; (p (@ (class "e-content")) ,content)
+;; (p (a (@ (href "self") (class "u-url"))
+;; (time (@ (datetime ,datetime) (class "dt-published"))
+;; ,datetime-pretty))))
+
+;; (define* (htaccess #:key profile-url
+;; profile-name
+;; profile-picture
+;; (comment-dir "webmentions"))
+;; "Create a multi-page Webmention outbox, reading comments from COMMENT-DIR."
+;; (define contents
+;; `(,(if handler-404
+;; (format #f "ErrorDocument 404 ~a" handler-404))))
+
+;; (lambda (site posts)
+;; (make-page ".htaccess" contents htaccess-writer)))
diff --git a/haunt/jakob/builder/static-pages.scm b/haunt/jakob/builder/static-pages.scm
new file mode 100644
index 0000000..9089789
--- /dev/null
+++ b/haunt/jakob/builder/static-pages.scm
@@ -0,0 +1,48 @@
+;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License as
+;;; published by the Free Software Foundation; either version 3 of the
+;;; License, or (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+(define-module (jakob builder static-pages)
+ #:use-module (haunt html)
+ #:use-module (haunt page)
+ #:use-module (ice-9 ftw)
+ #:use-module (jakob builder blog)
+ #:use-module (srfi srfi-1)
+ #:export (static-pages))
+
+(define* (static-pages)
+ (lambda (site posts)
+ (define enter? (const #t))
+
+ (define (leaf file-name stat memo)
+ (let* ((dest (if (string-suffix? ".sxml" file-name)
+ (string-append (string-drop-right file-name
+ (string-length ".sxml"))
+ ".html")
+ file-name))
+ (name (first (string-split (basename dest) #\.)))
+ (sxml (primitive-load file-name))
+ ;; (contents (with-layout theme site name sxml))
+ (contents sxml)
+ )
+ (cons (make-page dest contents sxml->html) memo)))
+
+ (define (noop file-name stat result)
+ result)
+
+ (define (err file-name stat errno result)
+ (error "file processing failed with errno: " file-name errno))
+
+ (file-system-fold enter? leaf noop noop noop err '() "pages")))
diff --git a/haunt/jakob/reader/html-prime.scm b/haunt/jakob/reader/html-prime.scm
new file mode 100644
index 0000000..373edd5
--- /dev/null
+++ b/haunt/jakob/reader/html-prime.scm
@@ -0,0 +1,44 @@
+;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License as
+;;; published by the Free Software Foundation; either version 3 of the
+;;; License, or (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;;
+;;; Temporary reader containing my changes to 'html-reader'. This module will
+;;; remain until Haunt sees another release and, thus, the fixes are available.
+;;;
+;;; Code:
+
+(define-module (jakob reader html-prime)
+ #:use-module (haunt post)
+ #:use-module (haunt reader)
+ #:use-module (ice-9 match)
+ #:use-module (srfi srfi-26)
+ #:use-module (sxml simple)
+ #:export (html-reader-prime))
+
+(define (read-html-post-prime port)
+ (values (read-metadata-headers port)
+ (let loop ((ret '()))
+ (catch 'parser-error
+ (lambda ()
+ (match (xml->sxml port)
+ (('*TOP* sxml) (loop (cons sxml ret)))))
+ (lambda (key . parameters)
+ (reverse ret))))))
+
+(define html-reader-prime
+ (make-reader (make-file-extension-matcher "html")
+ (cut call-with-input-file <> read-html-post-prime)))
diff --git a/haunt/jakob/theme.scm b/haunt/jakob/theme.scm
new file mode 100644
index 0000000..23d3929
--- /dev/null
+++ b/haunt/jakob/theme.scm
@@ -0,0 +1,101 @@
+;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License as
+;;; published by the Free Software Foundation; either version 3 of the
+;;; License, or (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+(define-module (jakob theme)
+ #:use-module (ice-9 match)
+ #:use-module (jakob utils sxml)
+ #:export (theme))
+
+
+;;;
+;;; SHTML generation in the site's theme.
+;;;
+
+(define %stylesheets '("normalize.css" "fonts.css" "highlight.css" "style.css"))
+(define %link-rel '(("alternate" "/index.xml" "application/atom+xml")
+ ("icon" "/static/image/favicon.ico" "image/vnd.microsoft.icon")
+ ("me" "https://mastodon.sdf.org/@jakob")
+ ("webmention" "https://webmention.io/jakob.space/webmention")
+ ("pingback" "https://webmention.io/jakob.space/xmlrpc")
+ ("pgpkey authn" "/gpg.txt")))
+(define %nav-bar-tabs '(("About" "/pages/about.html")
+ ("Projects" "/pages/projects.html")
+ ("Tags" "/tag.html")
+ ("Atom" "/feed.xml")))
+
+(define %title "Jakob's Personal Webpage")
+
+(define %header
+ `(header
+ ,(hyperlink "/" (image "lambda.svg" "home"))
+ (nav (ul
+ ,@(map (lambda (tuple)
+ `(li ,(apply hyperlink (reverse tuple))))
+ %nav-bar-tabs)))))
+
+(define %footer
+ `(footer
+ (div
+ (p "© 2019 Jakob L. Kreuze")
+ ,(image "cc-by-sa-4.0.png"
+ "Creative Commons Attribution-ShareAlike 4.0 International (CC
+BY-SA 4.0) Logo"))
+ (p "Unless otherwise specified, the text and images on this site are free
+culture works available under the "
+ ,(hyperlink "https://creativecommons.org/licenses/by-sa/4.0/"
+ "Creative Commons Attribution Share-Alike 4.0
+International")
+ " license.")
+ (p "This website is built with "
+ ,(hyperlink "http://haunt.dthompson.us/" "Haunt")
+ ", a static site generator written in "
+ ,(hyperlink "https://gnu.org/software/guile" "Guile Scheme")
+ ".")))
+
+(define* (theme #:key
+ (title '())
+ (description "")
+ (keywords '())
+ (content '(div "")))
+ "Return an SHTML document using the website's theme."
+ `((doctype "html")
+ (html
+ (@ (lang "en"))
+
+ (head
+ ,(if (null? title)
+ `(title %title)
+ `(title ,(string-join (list title %title) " — ")))
+
+ (meta (@ (charset "utf-8")))
+ (meta (@ (name "keywords")
+ (content ,(string-join keywords ", "))))
+ (meta (@ (name "description")
+ (content ,description)))
+ (meta (@ (name "viewport")
+ (content "width=device-width, initial-scale=1.0")))
+
+ ,@(map (lambda (file-name) (stylesheet file-name)) %stylesheets)
+
+ ,@(map (match-lambda
+ ((rel href) `(link (@ (rel ,rel) (href ,href))))
+ ((rel href type) `(link (@ (rel ,rel) (href ,href) (type ,type)))))
+ %link-rel))
+
+ (body
+ ,%header
+ ,content
+ ,%footer))))
diff --git a/haunt/jakob/utils.scm b/haunt/jakob/utils.scm
new file mode 100644
index 0000000..33f8f93
--- /dev/null
+++ b/haunt/jakob/utils.scm
@@ -0,0 +1,59 @@
+;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License as
+;;; published by the Free Software Foundation; either version 3 of the
+;;; License, or (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+(define-module (jakob utils)
+ #:use-module (haunt post)
+ #:use-module (ice-9 match)
+ #:use-module (srfi srfi-1)
+ #:export (maybe-cons*
+ maybe-list
+ date->string*
+ intersperse
+ first-paragraph))
+
+(define (maybe-list . args)
+ "Create a list of all ARGS that are neither #f nor unspecified."
+ (remove (lambda (element)
+ (or (not element) (unspecified? element)))
+ args))
+
+(define (maybe-cons* . args)
+ "Cons all ARGS that are neither #f nor unspecified."
+ (apply cons* (apply maybe-list args)))
+
+(define (date->string* date)
+ "Convert DATE to human readable string."
+ (date->string date "~a ~d ~B ~Y"))
+
+(define (intersperse lst delim)
+ "Return the elements of LST delimited by DELIM, such that the resultant list
+is of an odd length and every second element is DELIM."
+ (if (<= (length lst) 1)
+ lst
+ (cons* (car lst)
+ delim
+ (intersperse (cdr lst) delim))))
+
+(define (first-paragraph post)
+ (let loop ((sxml (post-sxml post))
+ (result '()))
+ (match sxml
+ (() (reverse result))
+ ((or (('p ...) _ ...) (paragraph _ ...))
+ (reverse (cons paragraph result)))
+ ((head . tail)
+ (loop tail (cons head result))))))
+
diff --git a/haunt/custom/sxml.scm b/haunt/jakob/utils/sxml.scm
index 1fbdc97..c4ce33d 100644
--- a/haunt/custom/sxml.scm
+++ b/haunt/jakob/utils/sxml.scm
@@ -14,24 +14,25 @@
;;; along with this program. If not, see
;;; <http://www.gnu.org/licenses/>.
-(define-module (custom sxml)
- #:export (%cc-by-sa-button
- %cc-by-sa-link
- link
- stylesheet))
+;;; Commentary:
+;;;
+;;; A number of utility procedure to aid in writing SXML by hand.
+;;;
+;;; Code:
-(define %cc-by-sa-button
- '(a (@ (class "cc-button")
- (href "https://creativecommons.org/licenses/by-sa/4.0/"))
- (img (@ (src "https://licensebuttons.net/l/by-sa/4.0/80x15.png")))))
+(define-module (jakob utils sxml)
+ #:export (hyperlink
+ image
+ stylesheet))
-(define %cc-by-sa-link
- '(a (@ (href "https://creativecommons.org/licenses/by-sa/4.0/"))
- "Creative Commons Attribution Share-Alike 4.0 International"))
+(define (hyperlink target text)
+ `(a (@ (href ,target)) ,text))
-(define (link name uri)
- `(a (@ (href ,uri)) ,name))
+(define* (image filename #:optional description)
+ (let ((src (string-append "/static/image/" filename)))
+ (if description
+ `(img (@ (src ,src) (alt ,description) (title ,description)))
+ `(img (@ (src ,src))))))
-(define (stylesheet name)
- `(link (@ (rel "stylesheet")
- (href ,(string-append "/css/" name ".css")))))
+(define (stylesheet file-name)
+ `(link (@ (rel "stylesheet") (href ,(format #f "/static/css/~a" file-name)))))
diff --git a/haunt/js/webmention.js b/haunt/js/webmention.js
deleted file mode 100644
index d1bb8e8..0000000
--- a/haunt/js/webmention.js
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * webmention.js -- Fetch and display mentions from webmention.io.
- * Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- * <http://www.gnu.org/licenses/>.
- */
-
-function buildApiUri() {
- const snip = /https?:\/\/.*?\//.exec(window.location.href);
- const page = window.location.href.substring(snip[0].length);
-
- // TODO: Build up from aliases, etc.
- const aliases = [page];
-
- return Array.concat(
- ["https://webmention.io/api/mentions.jf2?"],
- aliases.flatMap((alias) => {
- const ref = "jakob.space";
- return [
- `target[]=http://${ref}/${alias}`,
- `target[]=https://${ref}/${alias}`
- ];
- }).join("&")
- ).join("");
-}
-
-function getData(url, callback) {
- if (fetch) {
- fetch(url).then(function(response) {
- if (response.status >= 200 && response.status < 300) {
- return Promise.resolve(response);
- } else {
- return Promise.reject(new Error(`Request failed: ${response.statusText}`));
- }
- }).then(function(response) {
- return response.json();
- }).then(callback);
- } else {
- let xhr = new XMLHttpRequest();
- xhr.onload = function(data) {
- callback(JSON.parse(data));
- }
- xhr.onerror = function(error) {
- throw new Error(`Request failed: ${error}`);
- }
- }
-}
-
-function makeComment(comment) {
- const strip = (uri) => {
- const sep = "://";
- return uri.substring(uri.indexOf(sep) + sep.length);
- };
-
- const element = (type, attributes) => {
- let res = document.createElement(type);
- for (const attribute in attributes) {
- res.setAttribute(attribute, attributes[attribute]);
- }
- return res;
- };
-
- // Create the h-card section.
- let avatar = element("img", {
- "class": "u-photo",
- "src": comment.author.photo
- });
-
- let authorName = element("a", {
- "class": "p-name u-url",
- "href": comment.author.url
- });
- authorName.textContent = comment.author.name;
-
- let authorURI = element("a", {
- "class": "author_url",
- "href": comment.author.url
- });
- authorURI.textContent = strip(comment.author.url);
-
- let hCardContainer = element("div", {
- "class": "p-author h-card author"
- });
- hCardContainer.appendChild(avatar);
- hCardContainer.appendChild(authorName);
- hCardContainer.appendChild(authorURI);
-
- // Create the content section.
- let contentContainer = element("div", {
- "class": "e-content p-name comment-content",
- });
- contentContainer.textContent = comment.content.text;
-
- // Create the metaline section.
- let time = element("time", {
- "class": "dt-published",
- "datetime": comment.published
- });
- time.textContent = (new Date(comment.published)).toString();
-
- let linkBack = element("a", {
- "class": "u-url",
- "href": comment.url
- });
- linkBack.appendChild(time);
-
- let metalineContainer = element("div", {
- "class": "metaline"
- });
- metalineContainer.appendChild(linkBack);
-
- // Put it all together.
- let wrapper = element("li", {
- "class": "p-comment h-cite comment",
- });
- wrapper.appendChild(hCardContainer);
- wrapper.appendChild(contentContainer);
- wrapper.appendChild(metalineContainer);
-
- return wrapper;
-}
-
-getData(buildApiUri(), (json) => {
- json.children
- .map(makeComment)
- .forEach((elem) => {
- document.getElementById("webmention-container").appendChild(elem);
- })});
diff --git a/haunt/other/gpg.txt b/haunt/other/gpg.txt
deleted file mode 100644
index aaa2630..0000000
--- a/haunt/other/gpg.txt
+++ /dev/null
@@ -1,190 +0,0 @@
------BEGIN PGP PUBLIC KEY BLOCK-----
-
-mQINBFyL0CEBEACrmHInpe3ZUJ5f0lhgYbvVobjBaSgu6XKt1Lm640XR/d5RmCsh
-RS2oJ0zghzRQMx+BBTxr62OmuI8FU9MfU+ySHNJWcyobmGaPH0VG3n6xlkBY9g7l
-zm+lccrxpXTd8QH5KRQNUYcL7/aYRNgtqYrYWmkxPSTM2ydFHc+W9wEAZTHLOQsc
-aQJold5KJHM7DTwOq21oltLwWKCOL+MfMejjYoYRMT0UE9DduyR1H/cKsF9VvNjV
-AHFaxCcibtYK0s5jyq/fVIq8ZqU9AEnwUtspqVzWINaDCbVPL/NzFkjDlzu5Y9Bi
-ff9B/Ncd5TmstnsJ9cj6IgYjtwEPLw+aSJNsuzLlQROPDqDM6gaq8v+q8cjk2EH0
-ft0uFlWENf3kfql/WMMn8iVtYon0h9LLI480dQix4+OjNQFVrryPstuA2wTvGqIH
-ECYJeI5hLT5EdShHEXGQEE5JAqXhd19lrWfoV0HI7IKnxE2UI+riaUNSJE8VCmIm
-Y/e2YU/YFIzbrGOh/q0M2te+4ATrexwyBAxrlzl8gFiM3vTQGwJSIeIIlcVoUbti
-/UcywO9pKQlga7AN0oQ0GnmWkGmdLj44wFFuIQSDdkGDyxurh+RPspnSW4HAz3fC
-IbC5h9ACGcLWYT3p7JZGiR9SRbAHBDTgBF5F3hV9ORJpZ8ykN1V9iMq9pwARAQAB
-tEdKYWtvYiBMLiBLcmV1emUgKGh0dHA6Ly9qYWtvYi5zcGFjZSkgPHplcm9kYXlz
-Zm9yZGF5c0BzZGYubG9uZXN0YXIub3JnPokCUwQTAQgAPQIbAwUJAeEzgAIeAQIX
-gBYhBMr8F0Od9PwacViMZSdn1f7sIYnvBQJci9d+BQsJCAcCBhUKCQgLAgMWAgEA
-CgkQJ2fV/uwhie9HqA//SY9dIX46hjNIQpvWWLq8yKKMPZeC1B81JwyK3vimPrNz
-MWeMTJcnmzupNfHXtSaYGh3GlBj6sRONLEGQVS25qBOLgo5TOtPD4V/F4rbqmwRN
-scIMmHPN7s/n60if7dF2bOmrasCpkhROj8CCTsaImbFCYQW5kOywkvxP3tPM6sJd
-6yIqMeb/LR+7VOYYZuCGx3VTXmLdB4eMtY7fHE3K9iZp4yNYsxib+mgeIFPhsdQ2
-uGC7aGm9XusKVLMx4zGrm0ddZdsQyGosp6Ynd4t+5Xb3PM6UyvTNVwTxh6vEBIMb
-yIdz/6tC53xw0RlA86FUH+IY3CQLECjbZDPsjmKkD7KNcckUk11eQkhgMDHxgZAl
-v3Qe4qiDb89UdVpkBJJvxjJztgVyjfHwJdsErzktgOZpnBP/TxNlKwmvKaffMe35
-kIzl0RHrQffQlLhWaw6nndsWzD33jqyd6LzVxhLP+s5QKFIC7KN63d0BeUqEQirD
-Z6t1oKSaRWbK67MRRdTQ/hPb2wthw1TQ0ANXWMcpOHyyyZj2F64PLT6sWXvaE9Ky
-PAUZP2StHWztz6sGyshmCWQot2gROUxbVqyRLxKu158BSbqKbjf2DuwTju8Vtpcn
-qXJDE7L9LvuJo79CmGR/4cGN8SVY/yEfXPQh8+tqHJ0asXQ/iJ2pVZk5up9Wnr7R
-0DbQNAEQAAEBAAAAAAAAAAAAAAAA/9j/4AAQSkZJRgABAQEASABIAAD//gATQ3Jl
-YXRlZCB3aXRoIEdJTVD/2wEEEAA1ADUANQA1ADkANQA8AEMAQwA8AFMAWgBQAFoA
-UwB7AHEAZwBnAHEAewC6AIUAjwCFAI8AhQC6ARsAsADOALAAsADOALABGwD6AS8A
-9gDmAPYBLwD6AcIBYQE5ATkBYQHCAgcBtAGdAbQCBwJ1AjMCMwJ1AxkC8QMZBAwE
-DAVwEQA1ADUANQA1ADkANQA8AEMAQwA8AFMAWgBQAFoAUwB7AHEAZwBnAHEAewC6
-AIUAjwCFAI8AhQC6ARsAsADOALAAsADOALABGwD6AS8A9gDmAPYBLwD6AcIBYQE5
-ATkBYQHCAgcBtAGdAbQCBwJ1AjMCMwJ1AxkC8QMZBAwEDAVw/8IAEQgBIADwAwEi
-AAIRAQMRAf/EABoAAAIDAQEAAAAAAAAAAAAAAAAEAgMFAQb/2gAIAQEAAAAA0CYA
-AcVbAyuMq0t2dDgJnHXgAELWgyS9K1kAAI3ClWvMCvB3rDK5eg3aAABRfZSJ6LHF
-kObpmVsJM2gAAEOMKFiseswacz12V+NAAABXW5VUdhB1LZWzm4o6IAAAC0C+htS/
-i+vZiuxVtnYAAACN0Zyu5SvrXU5jUUY6EwAAAz5aE6Vhp3pTmNVZ12iRkAAAx3L2
-OgAV5DlC97NfLSidgAU2r6F4ABhPRRemm1Kii1kAL4UWuAAGI5zO0u52jXS9mvAB
-nxnptAAGM1FDSM3Rz3OoaYBzPvT9DOFdMSdyE+5+kZ17rgotU2cV0cxdzhbcEIUw
-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
-BC2J8VM1ySLIhdpwOpBmfBui8bkX1s2dedJ+XQ==
-=c2uQ
------END PGP PUBLIC KEY BLOCK-----
diff --git a/haunt/outbox.scm b/haunt/outbox.scm
deleted file mode 100644
index 04ea775..0000000
--- a/haunt/outbox.scm
+++ /dev/null
@@ -1,57 +0,0 @@
-;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
-;;;
-;;; This program is free software; you can redistribute it and/or
-;;; modify it under the terms of the GNU General Public License as
-;;; published by the Free Software Foundation; either version 3 of the
-;;; License, or (at your option) any later version.
-;;;
-;;; This program is distributed in the hope that it will be useful,
-;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;;; General Public License for more details.
-;;;
-;;; You should have received a copy of the GNU General Public License
-;;; along with this program. If not, see
-;;; <http://www.gnu.org/licenses/>.
-
-(use-modules (srfi srfi-19))
-
-(define %comments
- `(("https://aaronparecki.com/2018/06/30/11/your-first-webmention"
- "@aaronpk"
- "<2019-05-11 Sat 17:07>"
- (p (@ (class "e-content"))
- "Hoo, this comments section is a bit of a mess. "
- "Anyway, I'm just testing out Webmentions like everyone else. "
- "Don't mind me..."))
- ("http://jakob.space/transition-to-haunt.html"
- "@jakob"
- "<2019-05-12 Sun 12:07>"
- (p (@ (class "e-content"))
- "Just testing out my Webmention inbox widget."))))
-
-(define (h-card)
- `(div (@ (class "u-author h-card"))
- (img (@ (src "/images/favicon.png")
- (class "u-photo")))
- (a (@ (href "http://jakob.space")
- (class "u-url p-name"))
- (p "Jakob L. Kreuze"))))
-
-(define (comment target-uri target-handle date sxml)
- (let ((date (string->date date "<~Y-~m-~d ~a ~H:~M>")))
- `(li (@ (class "h-entry"))
- ,(h-card)
- (p "in reply to: " (a (@ (class "u-in-reply-to")
- (href ,target-uri))
- ,target-handle))
- ,sxml
- (a (@ (href "http://jakob.space/outbox.html")
- (class "u-url"))
- (time (@ (class "dt-published")
- (datetime ,(date->string date "~Y-~m-~dT~H:~M:~S~z")))
- ,(date->string date "~c"))))))
-
-`((h2 "Webmention Outbox")
- (ul (@ (id "webmention-container"))
- ,@(map (lambda (args) (apply comment args)) %comments)))
diff --git a/haunt/about.scm b/haunt/pages/about.sxml
index 46ce42f..8bce651 100644
--- a/haunt/about.scm
+++ b/haunt/pages/about.sxml
@@ -1,3 +1,5 @@
+;;; -*- scheme -*-
+
;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
;;;
;;; This program is free software; you can redistribute it and/or
@@ -14,13 +16,13 @@
;;; along with this program. If not, see
;;; <http://www.gnu.org/licenses/>.
-(use-modules (custom sxml))
+(use-modules (jakob utils sxml))
`((h2 "Hey.")
(p "I'm still in the process of putting things together, so this page is a bit empty.")
(p "For those interested in contacting me, here's my info.")
(ul
(li "Email: zerodaysfordays at ‌​‌‌‌​‌‌‍‌​‌‌​​​​‍‌​‌‌​​​‌‍‌‌​‌‌​​​‍‌​‌​‌​‌‌‍‌‌​‌‌‌‌‌‍‌​‌‌‌​​‌‍‌​‌​‌​‌​‍‌​‌‌‌‌​​‍‌​‌‌​‌​​‍‌​‌‌​‌‌​‍‌​‌‌​​​‌‍‌​‌‌‌​​​‍‌‌​‌‌‌‌‌‍‌​‌​‌‌​​‍‌​‌​‌‌‌‌‍‌​‌‌‌‌‌​‍‌​‌‌​​‌​‍‌‌​‌‌‌‌‌‍‌​‌‌​​‌​‍‌​‌‌‌​‌​sdf.lonestar.org")
- (li "GPG: " ,(link "5A7B 8C4C 70D5 FC3F 5E35 4625 3FE7 8039 D0E5 C118" "/gpg.txt"))
+ (li "GPG: " ,(hyperlink "5A7B 8C4C 70D5 FC3F 5E35 4625 3FE7 8039 D0E5 C118" "/gpg.txt"))
(li "XMPP: jakob at ‌​‌‌‌​‌‌‍‌​‌‌​​​​‍‌​‌‌​​​‌‍‌‌​‌‌​​​‍‌​‌​‌​‌‌‍‌‌​‌‌‌‌‌‍‌​‌‌‌​​‌‍‌​‌​‌​‌​‍‌​‌‌‌‌​​‍‌​‌‌​‌​​‍‌​‌‌​‌‌​‍‌​‌‌​​​‌‍‌​‌‌‌​​​‍‌‌​‌‌‌‌‌‍‌​‌​‌‌​​‍‌​‌​‌‌‌‌‍‌​‌‌‌‌‌​‍‌​‌‌​​‌​‍‌‌​‌‌‌‌‌‍‌​‌‌​​‌​‍‌​‌‌‌​‌​xmpp.is")
(li "IRC: tsarfox on freenode.net, and jakob everywhere else. I frequent #lobsters and the #tildetown on the tilde.town internal IRC.")))
diff --git a/haunt/projects.scm b/haunt/projects.scm
deleted file mode 100644
index 9173aea..0000000
--- a/haunt/projects.scm
+++ /dev/null
@@ -1,82 +0,0 @@
-;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
-;;;
-;;; This program is free software; you can redistribute it and/or
-;;; modify it under the terms of the GNU General Public License as
-;;; published by the Free Software Foundation; either version 3 of the
-;;; License, or (at your option) any later version.
-;;;
-;;; This program is distributed in the hope that it will be useful,
-;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;;; General Public License for more details.
-;;;
-;;; You should have received a copy of the GNU General Public License
-;;; along with this program. If not, see
-;;; <http://www.gnu.org/licenses/>.
-
-(use-modules (custom sxml))
-
-(define %software-projects
- '(("Mines" "Dormant"
- "https://git.sr.ht/~jakob/mines"
- ("Android implementation of the classic video game \"Minesweeper\"."))
- ("Rebuild" "Dormant"
- "https://git.sr.ht/~jakob/rebuild"
- ("An attempt at reimplementing Ken Silverman's Build engine, with the goal of being modular enough to host a modern Blood source port."))
- ("wildmidi" "Dormant"
- "https://git.sr.ht/~jakob/wildmidi"
- ("A simple [Rust] wrapper around the WildMIDI software synthesizer library."))
- ("Slime the World" "Finished"
- "https://git.sr.ht/~jakob/slime-the-world"
- ("My entry for the 2018 Autumn Lisp Game Jam; a game about covering everything in slime."))
- ("Nekopack" "Finished"
- "https://git.sr.ht/~jakob/nekopack"
- ("Tool for extracting game data from Nekopara's XP3 archives."))
- ("skullfuck" "Finished"
- "https://git.sr.ht/~jakob/skullfuck"
- ("Optimizing compiler for Brainfuck, contained in a single C source file."))
- ("Brisket" "Abandoned"
- "https://git.sr.ht/~jakob/brisket"
- ("Primitive newsreader script for interacting with NNTP servers."))
- ("Hypodermic" "Abandoned"
- "https://git.sr.ht/~jakob/hypodermic"
- ("Proof-of-concept shared object injector that will eventually be integrated with PINCE."))
- ("Duke on FluidSynth" "Abandoned"
- "https://git.sr.ht/~jakob/duke-on-fluidsynth"
- ("Experimental FluidSynth MIDI driver for EDuke32."))))
-
-(define %software-contributions
- `(("Haiku" "Finished"
- "https://www.haiku-os.org/"
- ("The Haiku operating system."
- (ul (li ,(link "1337: mediaplayer: Implement AppendM3uToPlaylist"
- "https://review.haiku-os.org/c/haiku/+/1337"))
- (li ,(link "1351: Add mime_db entry for application/vnd.apple.mpegurl (M3U)"
- "https://review.haiku-os.org/c/haiku/+/1351")))))))
-
-(define %packaging-projects
- '(("zerodaysfordays" "Active"
- "https://git.sr.ht/~jakob/zerodaysfordays"
- ("My personal Gentoo ebuild overlay."))))
-
-(define (project name status url description)
- (let ((status-class (cond ((string= status "Active") "info")
- ((string= status "Finished") "good")
- ((string= status "Dormant") "okay")
- ((string= status "Abandoned") "bad")
- (else "info"))))
- `(tr (td ,(link name url))
- (td (span (@ (class ,(string-append "label " status-class))) ,status))
- (td ,@description))))
-
-(define (project-section name projects)
- `((h2 ,name)
- (table
- (tbody
- ,@(map (lambda (args) (apply project args)) projects)))))
-
-`((h2 "Projects")
- (p "I'm still in the process of putting things together, so this page is a bit empty.")
- ,@(project-section "Software" %software-projects)
- ,@(project-section "Packaging" %packaging-projects)
- ,@(project-section "Other Contributions" %software-contributions))
diff --git a/haunt/css/fonts.css b/haunt/static/css/fonts.css
index b17b8fd..05a70c6 100644
--- a/haunt/css/fonts.css
+++ b/haunt/static/css/fonts.css
@@ -2,28 +2,28 @@
@font-face {
font-family: 'Cantarell';
- src: url('/fonts/Cantarell-Bold.otf') format('opentype');
+ src: url('/static/font/Cantarell-Bold.otf') format('opentype');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'Cantarell';
- src: url('/fonts/Cantarell-BoldOblique.otf') format('opentype');
+ src: url('/static/font/Cantarell-BoldOblique.otf') format('opentype');
font-weight: bold;
font-style: italic;
}
@font-face {
font-family: 'Cantarell';
- src: url('/fonts/Cantarell-Oblique.otf') format('opentype');
+ src: url('/static/font/Cantarell-Oblique.otf') format('opentype');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: 'Cantarell';
- src: url('/fonts/Cantarell-Regular.otf') format('opentype');
+ src: url('/static/font/Cantarell-Regular.otf') format('opentype');
font-weight: normal;
font-style: normal;
}
@@ -32,28 +32,28 @@
@font-face {
font-family: 'Hack';
- src: url('/fonts/Hack-Bold.ttf');
+ src: url('/static/font/Hack-Bold.ttf');
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'Hack';
- src: url('/fonts/Hack-BoldItalic.ttf');
+ src: url('/static/font/Hack-BoldItalic.ttf');
font-weight: bold;
font-style: italic;
}
@font-face {
font-family: 'Hack';
- src: url('/fonts/Hack-Italic.ttf');
+ src: url('/static/font/Hack-Italic.ttf');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: 'Hack';
- src: url('/fonts/Hack-Regular.ttf');
+ src: url('/static/font/Hack-Regular.ttf');
font-weight: normal;
font-style: normal;
}
diff --git a/haunt/css/highlight.css b/haunt/static/css/highlight.css
index 401f18d..401f18d 100644
--- a/haunt/css/highlight.css
+++ b/haunt/static/css/highlight.css
diff --git a/haunt/static/css/normalize.css b/haunt/static/css/normalize.css
new file mode 100644
index 0000000..192eb9c
--- /dev/null
+++ b/haunt/static/css/normalize.css
@@ -0,0 +1,349 @@
+/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
+
+/* Document
+ ========================================================================== */
+
+/**
+ * 1. Correct the line height in all browsers.
+ * 2. Prevent adjustments of font size after orientation changes in iOS.
+ */
+
+html {
+ line-height: 1.15; /* 1 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/* Sections
+ ========================================================================== */
+
+/**
+ * Remove the margin in all browsers.
+ */
+
+body {
+ margin: 0;
+}
+
+/**
+ * Render the `main` element consistently in IE.
+ */
+
+main {
+ display: block;
+}
+
+/**
+ * Correct the font size and margin on `h1` elements within `section` and
+ * `article` contexts in Chrome, Firefox, and Safari.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * 1. Add the correct box sizing in Firefox.
+ * 2. Show the overflow in Edge and IE.
+ */
+
+hr {
+ box-sizing: content-box; /* 1 */
+ height: 0; /* 1 */
+ overflow: visible; /* 2 */
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+pre {
+ font-family: monospace, monospace; /* 1 */
+ font-size: 1em; /* 2 */
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Remove the gray background on active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+/**
+ * 1. Remove the bottom border in Chrome 57-
+ * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+ */
+
+abbr[title] {
+ border-bottom: none; /* 1 */
+ text-decoration: underline; /* 2 */
+ text-decoration: underline dotted; /* 2 */
+}
+
+/**
+ * Add the correct font weight in Chrome, Edge, and Safari.
+ */
+
+b,
+strong {
+ font-weight: bolder;
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+code,
+kbd,
+samp {
+ font-family: monospace, monospace; /* 1 */
+ font-size: 1em; /* 2 */
+}
+
+/**
+ * Add the correct font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` elements from affecting the line height in
+ * all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+sup {
+ top: -0.5em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove the border on images inside links in IE 10.
+ */
+
+img {
+ border-style: none;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * 1. Change the font styles in all browsers.
+ * 2. Remove the margin in Firefox and Safari.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ font-family: inherit; /* 1 */
+ font-size: 100%; /* 1 */
+ line-height: 1.15; /* 1 */
+ margin: 0; /* 2 */
+}
+
+/**
+ * Show the overflow in IE.
+ * 1. Show the overflow in Edge.
+ */
+
+button,
+input { /* 1 */
+ overflow: visible;
+}
+
+/**
+ * Remove the inheritance of text transform in Edge, Firefox, and IE.
+ * 1. Remove the inheritance of text transform in Firefox.
+ */
+
+button,
+select { /* 1 */
+ text-transform: none;
+}
+
+/**
+ * Correct the inability to style clickable types in iOS and Safari.
+ */
+
+button,
+[type="button"],
+[type="reset"],
+[type="submit"] {
+ -webkit-appearance: button;
+}
+
+/**
+ * Remove the inner border and padding in Firefox.
+ */
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+ border-style: none;
+ padding: 0;
+}
+
+/**
+ * Restore the focus styles unset by the previous rule.
+ */
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+ outline: 1px dotted ButtonText;
+}
+
+/**
+ * Correct the padding in Firefox.
+ */
+
+fieldset {
+ padding: 0.35em 0.75em 0.625em;
+}
+
+/**
+ * 1. Correct the text wrapping in Edge and IE.
+ * 2. Correct the color inheritance from `fieldset` elements in IE.
+ * 3. Remove the padding so developers are not caught out when they zero out
+ * `fieldset` elements in all browsers.
+ */
+
+legend {
+ box-sizing: border-box; /* 1 */
+ color: inherit; /* 2 */
+ display: table; /* 1 */
+ max-width: 100%; /* 1 */
+ padding: 0; /* 3 */
+ white-space: normal; /* 1 */
+}
+
+/**
+ * Add the correct vertical alignment in Chrome, Firefox, and Opera.
+ */
+
+progress {
+ vertical-align: baseline;
+}
+
+/**
+ * Remove the default vertical scrollbar in IE 10+.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * 1. Add the correct box sizing in IE 10.
+ * 2. Remove the padding in IE 10.
+ */
+
+[type="checkbox"],
+[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Correct the cursor style of increment and decrement buttons in Chrome.
+ */
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Correct the odd appearance in Chrome and Safari.
+ * 2. Correct the outline style in Safari.
+ */
+
+[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ outline-offset: -2px; /* 2 */
+}
+
+/**
+ * Remove the inner padding in Chrome and Safari on macOS.
+ */
+
+[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * 1. Correct the inability to style clickable types in iOS and Safari.
+ * 2. Change font properties to `inherit` in Safari.
+ */
+
+::-webkit-file-upload-button {
+ -webkit-appearance: button; /* 1 */
+ font: inherit; /* 2 */
+}
+
+/* Interactive
+ ========================================================================== */
+
+/*
+ * Add the correct display in Edge, IE 10+, and Firefox.
+ */
+
+details {
+ display: block;
+}
+
+/*
+ * Add the correct display in all browsers.
+ */
+
+summary {
+ display: list-item;
+}
+
+/* Misc
+ ========================================================================== */
+
+/**
+ * Add the correct display in IE 10+.
+ */
+
+template {
+ display: none;
+}
+
+/**
+ * Add the correct display in IE 10.
+ */
+
+[hidden] {
+ display: none;
+}
diff --git a/haunt/static/css/style.css b/haunt/static/css/style.css
new file mode 100644
index 0000000..b9f7beb
--- /dev/null
+++ b/haunt/static/css/style.css
@@ -0,0 +1,151 @@
+html {
+ font-family: "Cantarell", sans-serif;
+}
+
+@media (max-width: 54em) {
+ html {
+ font-size: 14px;
+ line-height: 160%;
+ }
+}
+
+@media (max-width: 26em) {
+ html {
+ font-size: 12px;
+ line-height: 150%;
+ }
+}
+
+body {
+ max-width: 54rem;
+ margin: .5rem auto;
+ position: relative;
+}
+
+@media (max-width: 54em) {
+ body {
+ max-width: 100%;
+ padding: 0 1rem;
+ }
+}
+
+/* Top-level header. */
+
+body > header {
+ display: flex;
+ align-items: center;
+}
+
+@media screen and (max-width: 480px) {
+ body > header {
+ flex-direction: column;
+ flex-wrap: wrap;
+ justify-content: space-around;
+ }
+}
+
+body > header > a > img {
+ max-width: 4rem;
+}
+
+@media screen and (min-width: 480px) {
+ body > header > a {
+ padding-right: 1rem;
+ }
+}
+
+body > header > nav > ul {
+ list-style-type: none;
+ padding-left: 0;
+}
+
+@media screen and (min-width: 480px) {
+ body > header > nav > ul > li {
+ display: inline-block;
+ padding: 1rem 2rem;
+ border-bottom: 2px solid #d2d6dd;
+ text-align: center;
+ }
+
+ body > header > nav > ul > li > a {
+ color: #000;
+ text-decoration: none;
+ }
+}
+
+/* Pagination navigation. */
+
+#pagination {
+ display: flex;
+ justify-content: space-around;
+}
+
+/* Links. */
+
+a:link, a:visited { color:#0000EE; }
+
+/* Figures */
+
+figure > img {
+ display: block;
+ max-width: 90%;
+ margin: auto;
+
+ border-radius: 2px;
+}
+
+figure > figcaption {
+ padding-top: 1rem;
+}
+
+/* Embeds. */
+
+.mastodon > iframe,
+.peertube > iframe {
+ display: block;
+ width: 90%;
+ min-height: 100%;
+ margin: auto;
+ border-radius: 4px;
+}
+
+/* Footnotes. */
+
+.footdef {
+ margin-bottom: 1rem;
+}
+
+.footdef > sup, .footpara {
+ display: inline;
+}
+
+/* Source code. */
+
+pre {
+ color: #f0e9dc;
+ font-family: "Hack", monospace;
+ font-size: 90%;
+
+ background-color: #303539;
+ border-radius: 4px;
+ padding: 1rem;
+ overflow-x: scroll;
+}
+
+/* Footer. */
+
+body > footer {
+ margin-top: 1.2rem;
+ border-top: 2px solid #d2d6dd;
+}
+
+body > footer > div {
+ margin-top: 1rem;
+ display: flex;
+ align-items: center;
+}
+
+body > footer > div > p {
+ margin: 0;
+ padding-right: 1rem;
+}
diff --git a/haunt/fonts/Cantarell-Bold.otf b/haunt/static/font/Cantarell-Bold.otf
index a5b620b..a5b620b 100644
--- a/haunt/fonts/Cantarell-Bold.otf
+++ b/haunt/static/font/Cantarell-Bold.otf
Binary files differ
diff --git a/haunt/fonts/Cantarell-BoldOblique.otf b/haunt/static/font/Cantarell-BoldOblique.otf
index 5f49d64..5f49d64 100644
--- a/haunt/fonts/Cantarell-BoldOblique.otf
+++ b/haunt/static/font/Cantarell-BoldOblique.otf
Binary files differ
diff --git a/haunt/fonts/Cantarell-Oblique.otf b/haunt/static/font/Cantarell-Oblique.otf
index 70539ed..70539ed 100644
--- a/haunt/fonts/Cantarell-Oblique.otf
+++ b/haunt/static/font/Cantarell-Oblique.otf
Binary files differ
diff --git a/haunt/fonts/Cantarell-Regular.otf b/haunt/static/font/Cantarell-Regular.otf
index fca6759..fca6759 100644
--- a/haunt/fonts/Cantarell-Regular.otf
+++ b/haunt/static/font/Cantarell-Regular.otf
Binary files differ
diff --git a/haunt/fonts/Hack-Bold.ttf b/haunt/static/font/Hack-Bold.ttf
index 7ff4975..7ff4975 100644
--- a/haunt/fonts/Hack-Bold.ttf
+++ b/haunt/static/font/Hack-Bold.ttf
Binary files differ
diff --git a/haunt/fonts/Hack-BoldItalic.ttf b/haunt/static/font/Hack-BoldItalic.ttf
index 3b137d9..3b137d9 100644
--- a/haunt/fonts/Hack-BoldItalic.ttf
+++ b/haunt/static/font/Hack-BoldItalic.ttf
Binary files differ
diff --git a/haunt/fonts/Hack-Italic.ttf b/haunt/static/font/Hack-Italic.ttf
index d26198a..d26198a 100644
--- a/haunt/fonts/Hack-Italic.ttf
+++ b/haunt/static/font/Hack-Italic.ttf
Binary files differ
diff --git a/haunt/fonts/Hack-Regular.ttf b/haunt/static/font/Hack-Regular.ttf
index 92a90cb..92a90cb 100644
--- a/haunt/fonts/Hack-Regular.ttf
+++ b/haunt/static/font/Hack-Regular.ttf
Binary files differ
diff --git a/haunt/static/image/bad-behavior-debug-prints.png b/haunt/static/image/bad-behavior-debug-prints.png
new file mode 100644
index 0000000..538ccec
--- /dev/null
+++ b/haunt/static/image/bad-behavior-debug-prints.png
Binary files differ
diff --git a/haunt/static/image/bad-behavior-vanilla-hexen-vulnerability.png b/haunt/static/image/bad-behavior-vanilla-hexen-vulnerability.png
new file mode 100644
index 0000000..510cf5f
--- /dev/null
+++ b/haunt/static/image/bad-behavior-vanilla-hexen-vulnerability.png
Binary files differ
diff --git a/haunt/static/image/cc-by-sa-4.0.png b/haunt/static/image/cc-by-sa-4.0.png
new file mode 100644
index 0000000..003dd0a
--- /dev/null
+++ b/haunt/static/image/cc-by-sa-4.0.png
Binary files differ
diff --git a/haunt/static/image/favicon.ico b/haunt/static/image/favicon.ico
new file mode 100644
index 0000000..929e6ad
--- /dev/null
+++ b/haunt/static/image/favicon.ico
Binary files differ
diff --git a/haunt/static/image/lambda.svg b/haunt/static/image/lambda.svg
new file mode 100644
index 0000000..d82b062
--- /dev/null
+++ b/haunt/static/image/lambda.svg
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="176.52748"
+ height="185.1386"
+ id="svg2">
+ <defs
+ id="defs4">
+ <marker
+ refX="0"
+ refY="0"
+ orient="auto"
+ style="overflow:visible"
+ id="Arrow1Mstart">
+ <path
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z "
+ transform="matrix(0.4,0,0,0.4,4,0)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ id="path3206" />
+ </marker>
+ <marker
+ refX="0"
+ refY="0"
+ orient="auto"
+ style="overflow:visible"
+ id="Arrow1Mend">
+ <path
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z "
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ id="path3209" />
+ </marker>
+ <marker
+ refX="0"
+ refY="0"
+ orient="auto"
+ style="overflow:visible"
+ id="Arrow1Lstart">
+ <path
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z "
+ transform="matrix(0.8,0,0,0.8,10,0)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ id="path3200" />
+ </marker>
+ </defs>
+ <path
+ d="M 47.243238,12.929372 L 47.243238,38.836954 L 68.578895,38.836954 L 77.341753,65.887518 L 12.191803,166.85089 L 44.195288,166.85089 L 90.676538,98.271996 L 121.15605,175.23276 L 169.16127,159.993 L 161.5414,136.37138 L 139.44375,143.22927 L 87.628587,12.929372 L 47.243238,12.929372 z "
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="path2255" />
+</svg>
diff --git a/haunt/static/image/making-your-own-music-player-analog-vs-digital.png b/haunt/static/image/making-your-own-music-player-analog-vs-digital.png
new file mode 100644
index 0000000..6841598
--- /dev/null
+++ b/haunt/static/image/making-your-own-music-player-analog-vs-digital.png
Binary files differ
diff --git a/haunt/static/image/reverse-engineering-babbys-first-archive-format-basic-parsing.png b/haunt/static/image/reverse-engineering-babbys-first-archive-format-basic-parsing.png
new file mode 100644
index 0000000..0513350
--- /dev/null
+++ b/haunt/static/image/reverse-engineering-babbys-first-archive-format-basic-parsing.png
Binary files differ
diff --git a/haunt/static/image/reverse-engineering-babbys-first-archive-format-binary-dump.png b/haunt/static/image/reverse-engineering-babbys-first-archive-format-binary-dump.png
new file mode 100644
index 0000000..0a8774c
--- /dev/null
+++ b/haunt/static/image/reverse-engineering-babbys-first-archive-format-binary-dump.png
Binary files differ
diff --git a/haunt/static/image/reverse-engineering-babbys-first-archive-format-catching-file-reads.png b/haunt/static/image/reverse-engineering-babbys-first-archive-format-catching-file-reads.png
new file mode 100644
index 0000000..2ce8f62
--- /dev/null
+++ b/haunt/static/image/reverse-engineering-babbys-first-archive-format-catching-file-reads.png
Binary files differ
diff --git a/haunt/static/image/reverse-engineering-babbys-first-archive-format-xp3-header.png b/haunt/static/image/reverse-engineering-babbys-first-archive-format-xp3-header.png
new file mode 100644
index 0000000..0fac996
--- /dev/null
+++ b/haunt/static/image/reverse-engineering-babbys-first-archive-format-xp3-header.png
Binary files differ
diff --git a/haunt/static/image/sdl-tutorial-part-0x00-finished-window.png b/haunt/static/image/sdl-tutorial-part-0x00-finished-window.png
new file mode 100644
index 0000000..4e9a146
--- /dev/null
+++ b/haunt/static/image/sdl-tutorial-part-0x00-finished-window.png
Binary files differ
diff --git a/haunt/static/image/sdl-tutorial-part-0x00-window.png b/haunt/static/image/sdl-tutorial-part-0x00-window.png
new file mode 100644
index 0000000..0bbe5fc
--- /dev/null
+++ b/haunt/static/image/sdl-tutorial-part-0x00-window.png
Binary files differ

© 2015 - 2026 Jakob L. Kreuze