Add RSS support.

* haunt/builder/rss.scm: New file with support for RSS feeds.
* Makefile.am: Add it.
This commit is contained in:
Christopher Lemmer Webber 2018-11-19 16:11:56 -05:00 committed by David Thompson
parent 15c4605e1d
commit 8891da0e3a
2 changed files with 108 additions and 0 deletions

View File

@ -54,6 +54,7 @@ SOURCES = \
haunt/builder/assets.scm \ haunt/builder/assets.scm \
haunt/builder/atom.scm \ haunt/builder/atom.scm \
haunt/builder/blog.scm \ haunt/builder/blog.scm \
haunt/builder/rss.scm \
haunt/reader.scm \ haunt/reader.scm \
haunt/reader/texinfo.scm \ haunt/reader/texinfo.scm \
haunt/ui.scm \ haunt/ui.scm \

107
haunt/builder/rss.scm Normal file
View File

@ -0,0 +1,107 @@
;;; Haunt --- Static site generator for GNU Guile
;;; Copyright © 2018 Christopher Lemmer Webber <cwebber@dustycloud.org>
;;;
;;; 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 <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; RSS feed builder.
;;
;;; Code:
(define-module (haunt builder rss)
#: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)
#:use-module (haunt serve mime-types)
#:use-module (haunt builder atom)
#:export (rss-feed))
;; Reader beware: this isn't as nice as atom.scm, because rss isn't
;; as nice as atom. Worse beats better on the play field again...
;; RFC 822 dates are inferior to ISO 8601, but it's
;; what RSS wants, so...
(define (date->rfc822-str date)
(date->string date "~a, ~d ~b ~Y ~T ~z"))
(define (sxml->xml* sxml port)
"Write SXML to PORT, preceded by an <?xml> tag."
(display "<?xml version=\"1.0\" encoding=\"utf-8\"?>" port)
(sxml->xml sxml port))
(define* (post->rss-item site post #:key (blog-prefix ""))
"Convert POST into an RSS <item> node."
`(item
(title ,(post-ref post 'title))
;; Looks like: <author>lawyer@boyer.net (Lawyer Boyer)</author>
(author
,(let ((email (post-ref post 'email))
(author (post-ref post 'author)))
(string-append (if email
(string-append email " ")
"")
(if author
(string-append "(" author ")")
""))))
(pubDate ,(date->rfc822-str (post-date post)))
(link (@ (href ,(string-append blog-prefix "/"
(site-post-slug site post) ".html"))
(rel "alternate")))
(description ,(sxml->html-string (post-sxml post)))
,@(map (lambda (enclosure)
`(enclosure (@ (title ,(enclosure-title enclosure))
(url ,(enclosure-url enclosure))
(type ,(enclosure-mime-type enclosure))
,@(map (match-lambda
((key . value)
(list key value)))
(enclosure-extra enclosure)))))
(post-ref-all post 'enclosure))))
(define* (rss-feed #:key
(file-name "rss-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 RSS
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
`(rss (@ (version "2.0"))
(channel
(title ,(site-title site))
;; It looks like RSS's description and atom's subtitle
;; are equivalent?
(description ,subtitle)
(pubDate ,(date->rfc822-str (current-date)))
(link (@ (href ,(site-domain site))))
,@(map (cut post->rss-item site <>
#:blog-prefix blog-prefix)
(take-up-to max-entries (filter posts)))))
sxml->xml*)))