;;; Haunt --- Static site generator for GNU Guile ;;; Copyright © 2015 David Thompson ;;; Copyright © 2016 Christopher Allan Webber ;;; ;;; This file is part of Haunt. ;;; ;;; Haunt 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. ;;; ;;; Haunt 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 Haunt. If not, see . ;;; Commentary: ;; ;; Atom feed builder. ;; ;;; Code: (define-module (haunt builder atom) #:use-module (srfi srfi-19) #:use-module (srfi srfi-26) #:use-module (ice-9 match) #:use-module (sxml simple) #:use-module (haunt site) #:use-module (haunt post) #:use-module (haunt page) #:use-module (haunt utils) #:use-module (haunt html) #:export (atom-feed atom-feeds-by-tag)) (define (sxml->xml* sxml port) "Write SXML to PORT, preceded by an tag." (display "" port) (sxml->xml sxml port)) (define (date->string* date) "Convert date to ISO-8601 formatted string." (date->string date "~4")) (define* (post->atom-entry site post #:key (blog-prefix "")) "Convert POST into an Atom XML node." `(entry (title ,(post-ref post 'title)) (author (name ,(post-ref post 'author)) ,(let ((email (post-ref post 'email))) (if email `(email ,email) '()))) (updated ,(date->string* (post-date post))) (link (@ (href ,(string-append blog-prefix "/" (site-post-slug site post) ".html")) (rel "alternate"))) (summary (@ (type "html")) ,(sxml->html-string (post-sxml post))))) (define* (atom-feed #:key (file-name "feed.xml") (subtitle "Recent Posts") (filter posts/reverse-chronological) (max-entries 20) (blog-prefix "")) "Return a builder procedure that renders a list of posts as an Atom feed. All arguments are optional: FILE-NAME: The page file name SUBTITLE: The feed subtitle FILTER: The procedure called to manipulate the posts list before rendering MAX-ENTRIES: The maximum number of posts to render in the feed" (lambda (site posts) (make-page file-name `(feed (@ (xmlns "http://www.w3.org/2005/Atom")) (title ,(site-title site)) (subtitle ,subtitle) (updated ,(date->string* (current-date))) (link (@ (href ,(string-append "/" file-name)) (rel "self"))) (link (@ (href ,(site-domain site)))) ,@(map (cut post->atom-entry site <> #:blog-prefix blog-prefix) (take-up-to max-entries (filter posts)))) sxml->xml*))) (define* (atom-feeds-by-tag #:key (prefix "feeds/tags") (filter posts/reverse-chronological) (max-entries 20) (blog-prefix "")) "Return a builder procedure that renders an atom feed for every tag used in a post. All arguments are optional: PREFIX: The directory in which to write the feeds FILTER: The procedure called to manipulate the posts list before rendering MAX-ENTRIES: The maximum number of posts to render in each feed" (lambda (site posts) (let ((tag-groups (posts/group-by-tag posts))) (map (match-lambda ((tag . posts) ((atom-feed #:file-name (string-append prefix "/" tag ".xml") #:subtitle (string-append "Tag: " tag) #:filter filter #:max-entries max-entries #:blog-prefix blog-prefix) site posts))) tag-groups))))