;;; Copyright © 2018 David Thompson ;;; ;;; 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 ;;; . (use-modules (haunt asset) (haunt builder blog) (haunt builder atom) (haunt builder assets) (haunt html) (haunt page) (haunt post) (haunt reader) (haunt reader commonmark) (haunt site) (haunt utils) (commonmark) (syntax-highlight) (syntax-highlight scheme) (syntax-highlight xml) (syntax-highlight c) (sxml match) (sxml transform) (texinfo) (texinfo html) (srfi srfi-1) (srfi srfi-19) (ice-9 rdelim) (ice-9 regex) (ice-9 match) (web uri)) (define (date year month day) "Create a SRFI-19 date for the given YEAR, MONTH, DAY" (let ((tzoffset (tm:gmtoff (localtime (time-second (current-time)))))) (make-date 0 0 0 0 day month year tzoffset))) (define (stylesheet name) `(link (@ (rel "stylesheet") (href ,(string-append "/css/" name ".css"))))) (define* (anchor content #:optional (uri content)) `(a (@ (href ,uri)) ,content)) (define %cc-by-sa-link '(a (@ (href "https://creativecommons.org/licenses/by-sa/4.0/")) "Creative Commons Attribution Share-Alike 4.0 International")) (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 %piwik-code '((script (@ (type "text/javascript") (src "/js/piwik.js"))) (noscript (p (img (@ (src "//stats.dthompson.us/piwik.php?idsite=1") (style "border:0;") (alt ""))))))) (define (link name uri) `(a (@ (href ,uri)) ,name)) (define* (centered-image url #:optional alt) `(img (@ (class "centered-image") (src ,url) ,@(if alt `((alt ,alt)) '())))) (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 dthompson-theme (theme #:name "dthompson" #:layout (lambda (site title body) `((doctype "html") (head (meta (@ (charset "utf-8"))) (title ,(string-append title " — " (site-title site))) ,(stylesheet "reset") ,(stylesheet "fonts") ,(stylesheet "dthompson")) (body (div (@ (class "container")) (div (@ (class "nav")) (ul (li ,(link "David Thompson" "/")) (li (@ (class "fade-text")) " ") (li ,(link "About" "/about.html")) (li ,(link "Blog" "/index.html")) (li ,(link "Projects" "/projects.html")))) ,body (footer (@ (class "text-center")) (p (@ (class "copyright")) "© 2018 David Thompson" ,%cc-by-sa-button) (p "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 " (a (@ (href "http://haunt.dthompson.us")) "Haunt") ", a static site generator written in " (a (@ (href "https://gnu.org/software/guile")) "Guile Scheme") "."))) ,%piwik-code))) #:post-template (lambda (post) `((h1 (@ (class "title")),(post-ref post 'title)) (div (@ (class "date")) ,(date->string (post-date post) "~B ~d, ~Y")) (div (@ (class "post")) ,(post-sxml post)))) #: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))))) (define %collections `(("Recent Blog Posts" "index.html" ,posts/reverse-chronological))) (define parse-lang (let ((rx (make-regexp "-*-[ ]+([a-z]*)[ ]+-*-"))) (lambda (port) (let ((line (read-line port))) (match:substring (regexp-exec rx line) 1))))) (define (maybe-highlight-code lang source) (let ((lexer (match lang ('scheme lex-scheme) ('xml lex-xml) ('c lex-c) (_ #f)))) (if lexer (highlights->sxml (highlight lexer source)) source))) (define (sxml-identity . args) args) (define (highlight-code . tree) (sxml-match tree ((code (@ (class ,class) . ,attrs) ,source) (let ((lang (string->symbol (string-drop class (string-length "language-"))))) `(code (@ ,@attrs) ,(maybe-highlight-code lang source)))) (,other other))) (define (highlight-scheme code) `(pre (code ,(highlights->sxml (highlight lex-scheme code))))) (define (raw-snippet code) `(pre (code ,(if (string? code) code (read-string code))))) ;; Markdown doesn't support video, so let's hack around that! Find ;; tags with a ".webm" source and substitute a