diff --git a/TODO b/TODO index e43ec24..2e3c782 100644 --- a/TODO +++ b/TODO @@ -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 diff --git a/coleslaw.asd b/coleslaw.asd index 744e0fa..91971fe 100644 --- a/coleslaw.asd +++ b/coleslaw.asd @@ -5,7 +5,7 @@ :license "BSD" :author "Brit Butler " :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))) diff --git a/src/coleslaw.lisp b/src/coleslaw.lisp index 06d23d0..ad552d6 100644 --- a/src/coleslaw.lisp +++ b/src/coleslaw.lisp @@ -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)))) diff --git a/src/feeds.lisp b/src/feeds.lisp new file mode 100644 index 0000000..3dce91d --- /dev/null +++ b/src/feeds.lisp @@ -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 "" 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)))) diff --git a/themes/hyde/rss.tmpl b/themes/hyde/rss.tmpl new file mode 100644 index 0000000..b5c3e05 --- /dev/null +++ b/themes/hyde/rss.tmpl @@ -0,0 +1,29 @@ +{namespace coleslaw.theme.hyde} + +{template rss} +{\n} + + + {$title} + {$siteroot} + + {$title} + en-us + {$pubdate} + + {foreach $post in $posts} + + {$post.title} + {$siteroot}/{$post.url} + {$post.date} + {$author} + {foreach $tag in $tags} + {$tag |noAutoescape} + {/foreach} + {$siteroot}/{$post.url} + {$post.content |noAutoescape} + + {% endfor %} + + +