Add RSS support.

This commit is contained in:
Brit Butler 2012-08-21 23:50:36 -04:00
parent 2044751cde
commit f4d97379fc
5 changed files with 71 additions and 4 deletions

3
TODO
View file

@ -13,8 +13,7 @@ Plugins? Injection support for HEAD and BODY. What about predicate-based injecti
How is it served? Hunchentoot, Lighttpd, S3, whomever!
TODO:
; blockers to use this for redlinernotes: rss/atom feed, markdown support
; after that, focus on injections for code highlighting and latex
; after that, focus on markdown support, injections for code highlighting and latex
; doc themes and plugins
; fix plugins: s3

View file

@ -5,7 +5,7 @@
:license "BSD"
:author "Brit Butler <redline6561@gmail.com>"
:pathname "src/"
:depends-on (:closure-template :iolib.os :alexandria :cl-fad)
:depends-on (:closure-template :iolib.os :alexandria :cl-fad :local-time)
:serial t
:components ((:file "packages")
(:file "config")
@ -13,6 +13,7 @@
(:file "themes")
(:file "plugins")
(:file "coleslaw")
(:file "feeds")
(:file "posts")
(:file "indices"))
:in-order-to ((test-op (load-op coleslaw-tests)))

View file

@ -59,7 +59,8 @@ on files that match the given extension."
(when (probe-file dir)
(run-program "cp" `("-R" ,(namestring dir) ".")))))
(render-posts)
(render-indices))
(render-indices)
(render-feed))
(deploy staging)
(setf (last-published) (last-commit))))

37
src/feeds.lisp Normal file
View file

@ -0,0 +1,37 @@
(in-package :coleslaw)
(defun date-to-timestamp (date)
"Convert a post DATE to a local-time timestamp."
(destructuring-bind (date time) (cl-ppcre:split " " date)
(apply 'local-time:encode-timestamp 0
(mapcar #'parse-integer
(append (reverse (cl-ppcre:split ":" time))
(reverse (cl-ppcre:split "-" date)))))))
(defun make-pubdate (&optional date)
"Make a RFC1123 pubdate representing the current time or DATE, when supplied."
(let ((timestamp (if date
(date-to-timestamp date)
(local-time:now))))
(local-time:format-rfc1123-timestring nil timestamp)))
(defun xml-escape (string)
"Escape the given string for XML."
(format nil "<![CDATA[ ~A ]]>" string))
(defun render-feed ()
"Render and write the RSS feed for the site."
(let* ((posts (subseq (by-date (hash-table-values *posts*)) 0 10))
(content (loop for post in posts
collect (list :title (post-title post)
:url (post-url post)
:date (make-pubdate (post-date post))
:tags (mapcar #'xml-escape (post-tags post))
:content (xml-escape (post-content post))))))
(render-page "rss.xml"
(funcall (theme-fn "RSS")
:pubdate (make-pubdate)
:title (title *config*)
:siteroot (domain *config*)
:author (author *config*)
:posts content))))

29
themes/hyde/rss.tmpl Normal file
View file

@ -0,0 +1,29 @@
{namespace coleslaw.theme.hyde}
{template rss}
<?xml version="1.0"?>{\n}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{$title}</title>
<link>{$siteroot}</link>
<atom:link href="{$siteroot}/rss.xml" rel="self" type="application/rss+xml" />
<description>{$title}</description>
<language>en-us</language>
<pubDate>{$pubdate}</pubDate>
{foreach $post in $posts}
<item>
<title>{$post.title}</title>
<link>{$siteroot}/{$post.url}</link>
<pubDate>{$post.date}</pubDate>
<author>{$author}</author>
{foreach $tag in $tags}
<category>{$tag |noAutoescape}</category>
{/foreach}
<guid isPermaLink="true">{$siteroot}/{$post.url}</guid>
<content:encoded>{$post.content |noAutoescape}</content:encoded>
</item>
{% endfor %}
</channel>
</rss>