<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>content/published/post/2009/cl_blog_generator_gets_comments.post</filename>
    </added>
    <added>
      <filename>content/site/post/2009/cl_blog_generator_gets_comments.xhtml</filename>
    </added>
    <added>
      <filename>content/site/tag/advogato.atom</filename>
    </added>
    <added>
      <filename>content/site/tag/advogato.xhtml</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -149,7 +149,7 @@ else
  &lt;/head&gt;
  &lt;body&gt;
   &lt;h2&gt;Thanks!&lt;/h2&gt;
-  &lt;p&gt;Your comment will be included the next time this blog is rebuilt.&lt;/p&gt;
+  &lt;p&gt;Your comment will be included the next time the comments are moderated.&lt;/p&gt;
   &lt;p&gt;&lt;a href=&quot;$ENV{'HTTP_REFERER'}&quot;&gt;Return to blog&lt;/a&gt;.&lt;/p&gt;
  &lt;/body&gt;
 &lt;/html&gt;</diff>
      <filename>cgi-bin/comments.cgi</filename>
    </modified>
    <modified>
      <diff>@@ -9,9 +9,14 @@
  &lt;author&gt;&lt;name&gt;Hugo Duncan&lt;/name&gt;&lt;/author&gt;
  &lt;subtitle&gt;Development Blog&lt;/subtitle&gt;
  &lt;rights&gt;All content written by Hugo Duncan and photos by Hugo Duncan Copyright Hugo Duncan, all rights reserved.&lt;/rights&gt;
- &lt;updated&gt;2009-03-30T20:47:43.919555-04:00&lt;/updated&gt;
+ &lt;updated&gt;2009-03-31T00:43:21.776272-04:00&lt;/updated&gt;
 
-&lt;entry xml:base=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/&quot;&gt;&lt;title&gt;Blog Site Generators&lt;/title&gt;&lt;link href=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&quot;/&gt;&lt;id&gt;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&lt;/id&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;updated&gt;2009-03-26T20:00:00.000000-04:00&lt;/updated&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;cl-blog-generator&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;lisp&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;blog&quot;/&gt;&lt;summary type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;
+&lt;entry xml:base=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/&quot;&gt;&lt;title&gt;cl-blog-generator Gets Comments&lt;/title&gt;&lt;link href=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml&quot;/&gt;&lt;id&gt;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml&lt;/id&gt;&lt;published&gt;2009-03-30T20:00:00.000000-04:00&lt;/published&gt;&lt;updated&gt;2009-03-30T20:00:00.000000-04:00&lt;/updated&gt;&lt;published&gt;2009-03-30T20:00:00.000000-04:00&lt;/published&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;advogato&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;cl-blog-generator&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;lisp&quot;/&gt;&lt;summary type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;I have now added a comment system to &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt;.  My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.&lt;/p&gt;&lt;/div&gt;&lt;/summary&gt;&lt;content type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;I have now added a comment system to &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt;.  My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.&lt;/p&gt;
+
+&lt;p&gt;The comment system was inspired by &lt;a href=&quot;http://www.steve.org.uk/Software/chronicle/&quot;&gt;Chronicle&lt;/a&gt;'s, with a slight modification in approach - the comments are never saved on the web server, and are just sent by email to a dedicated email address.  Spam filtering is delegated to the whatever spam filtering is implemented on the mail server, or in your email client.  The comment emails are then processed in CL using &lt;a href=&quot;http://common-lisp.net/project/mel-base/&quot;&gt;mel-base&lt;/a&gt; and written to the local filesystem.  Moderation can optionally occur on the CL side, if that is preferable to using the email client.&lt;/p&gt;
+
+&lt;p&gt;There is still some work left to do - I would like to be able to switch off comments on individual posts, either on demand on after a default time period - but I thought I would let real world usage drive my development.&lt;/p&gt;
+&lt;/div&gt;&lt;/content&gt;&lt;/entry&gt;&lt;entry xml:base=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/&quot;&gt;&lt;title&gt;Blog Site Generators&lt;/title&gt;&lt;link href=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&quot;/&gt;&lt;id&gt;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&lt;/id&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;updated&gt;2009-03-26T20:00:00.000000-04:00&lt;/updated&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;cl-blog-generator&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;lisp&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;blog&quot;/&gt;&lt;summary type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;
 I recently uploaded some links to my &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt; project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as &lt;a href=&quot;http://www.advogato.org/person/Stevey/&quot;&gt;Steve Kemp&lt;/a&gt;'s &lt;a href=&quot;http://www.steve.org.uk/Software/chronicle/&quot;&gt;Chronicle&lt;/a&gt;, or &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; as used on &lt;a href=&quot;http://github.com/blog/272-github-pages&quot;&gt;GitHub Pages&lt;/a&gt;.  Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that &lt;a href=&quot;http://advogato.org/person/chalst/&quot;&gt;Charles Stewart&lt;/a&gt; suggested might be worth exploring.  I look forward to any comments you might have.
 &lt;/p&gt;&lt;/div&gt;&lt;/summary&gt;&lt;content type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;
 I recently uploaded some links to my &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt; project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as &lt;a href=&quot;http://www.advogato.org/person/Stevey/&quot;&gt;Steve Kemp&lt;/a&gt;'s &lt;a href=&quot;http://www.steve.org.uk/Software/chronicle/&quot;&gt;Chronicle&lt;/a&gt;, or &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; as used on &lt;a href=&quot;http://github.com/blog/272-github-pages&quot;&gt;GitHub Pages&lt;/a&gt;.  Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that &lt;a href=&quot;http://advogato.org/person/chalst/&quot;&gt;Charles Stewart&lt;/a&gt; suggested might be worth exploring.  I look forward to any comments you might have.</diff>
      <filename>content/site/index.atom</filename>
    </modified>
    <modified>
      <diff>@@ -15,6 +15,11 @@
 &lt;div id=&quot;centercontent&quot;&gt;
 &lt;div class=&quot;posts&quot;&gt;
   &lt;div class=&quot;post-link-with-synopsis&quot;&gt;
+    &lt;span class=&quot;post-link&quot;&gt;&lt;a href=&quot;post/2009/cl_blog_generator_gets_comments.xhtml&quot;&gt;cl-blog-generator Gets Comments&lt;/a&gt;&lt;/span&gt; &#183;
+    &lt;span class=&quot;post-synopsis&quot;&gt;&lt;p&gt;I have now added a comment system to &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt;.  My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.&lt;/p&gt;&lt;/span&gt;
+  &lt;/div&gt;
+
+  &lt;div class=&quot;post-link-with-synopsis&quot;&gt;
     &lt;span class=&quot;post-link&quot;&gt;&lt;a href=&quot;post/2009/blog_site_generators.xhtml&quot;&gt;Blog Site Generators&lt;/a&gt;&lt;/span&gt; &#183;
     &lt;span class=&quot;post-synopsis&quot;&gt;&lt;p&gt;
 I recently uploaded some links to my &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt; project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as &lt;a href=&quot;http://www.advogato.org/person/Stevey/&quot;&gt;Steve Kemp&lt;/a&gt;'s &lt;a href=&quot;http://www.steve.org.uk/Software/chronicle/&quot;&gt;Chronicle&lt;/a&gt;, or &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; as used on &lt;a href=&quot;http://github.com/blog/272-github-pages&quot;&gt;GitHub Pages&lt;/a&gt;.  Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that &lt;a href=&quot;http://advogato.org/person/chalst/&quot;&gt;Charles Stewart&lt;/a&gt; suggested might be worth exploring.  I look forward to any comments you might have.</diff>
      <filename>content/site/index.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@
 &lt;meta content=&quot;text/html; charset=utf-8&quot; http-equiv=&quot;Content-Type&quot;/&gt;
 &lt;link href=&quot;../../style.css&quot; title=&quot;sans&quot; media=&quot;screen&quot; type=&quot;text/css&quot; rel=&quot;stylesheet&quot;/&gt;
 &lt;link href=&quot;../../feed.atom&quot; title=&quot;Atom (full content)&quot; type=&quot;application/atom+xml&quot; rel=&quot;alternate&quot;/&gt;
-&lt;title&gt;cl-blog-generator : Blog Site Generators&lt;/title&gt;&lt;link rel=&quot;prev&quot; href=&quot;/cl-blog-generator/content/site/post/2009/blog_generator_configuration.xhtml&quot; title=&quot;Blog Generator Configuration&quot;/&gt;&lt;meta name=&quot;description&quot; content=&quot;&amp;#10;I recently uploaded some links to my cl-blog-generator project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as Steve Kemp's Chronicle, or Jekyll as used on GitHub Pages.  Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that Charles Stewart suggested might be worth exploring.  I look forward to any comments you might have.&amp;#10;&quot;/&gt;&lt;meta name=&quot;keywords&quot; content=&quot;cl-blog-generator,lisp,blog&quot;/&gt;
+&lt;title&gt;cl-blog-generator : Blog Site Generators&lt;/title&gt;&lt;link rel=&quot;prev&quot; href=&quot;/cl-blog-generator/content/site/post/2009/blog_generator_configuration.xhtml&quot; title=&quot;Blog Generator Configuration&quot;/&gt;&lt;link rel=&quot;next&quot; href=&quot;/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml&quot; title=&quot;cl-blog-generator Gets Comments&quot;/&gt;&lt;meta name=&quot;description&quot; content=&quot;&amp;#10;I recently uploaded some links to my cl-blog-generator project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as Steve Kemp's Chronicle, or Jekyll as used on GitHub Pages.  Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that Charles Stewart suggested might be worth exploring.  I look forward to any comments you might have.&amp;#10;&quot;/&gt;&lt;meta name=&quot;keywords&quot; content=&quot;cl-blog-generator,lisp,blog&quot;/&gt;
 &lt;/head&gt;
 &lt;body&gt;
 &lt;div id=&quot;container&quot;&gt;</diff>
      <filename>content/site/post/2009/blog_site_generators.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -9,7 +9,7 @@
  &lt;author&gt;&lt;name&gt;Hugo Duncan&lt;/name&gt;&lt;/author&gt;
  &lt;subtitle&gt;Development Blog&lt;/subtitle&gt;
  &lt;rights&gt;All content written by Hugo Duncan and photos by Hugo Duncan Copyright Hugo Duncan, all rights reserved.&lt;/rights&gt;
- &lt;updated&gt;2009-03-30T20:47:44.151965-04:00&lt;/updated&gt;
+ &lt;updated&gt;2009-03-31T00:43:22.027729-04:00&lt;/updated&gt;
 
 &lt;entry xml:base=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/&quot;&gt;&lt;title&gt;Blog Site Generators&lt;/title&gt;&lt;link href=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&quot;/&gt;&lt;id&gt;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&lt;/id&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;updated&gt;2009-03-26T20:00:00.000000-04:00&lt;/updated&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;cl-blog-generator&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;lisp&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;blog&quot;/&gt;&lt;summary type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;
 I recently uploaded some links to my &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt; project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as &lt;a href=&quot;http://www.advogato.org/person/Stevey/&quot;&gt;Steve Kemp&lt;/a&gt;'s &lt;a href=&quot;http://www.steve.org.uk/Software/chronicle/&quot;&gt;Chronicle&lt;/a&gt;, or &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; as used on &lt;a href=&quot;http://github.com/blog/272-github-pages&quot;&gt;GitHub Pages&lt;/a&gt;.  Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that &lt;a href=&quot;http://advogato.org/person/chalst/&quot;&gt;Charles Stewart&lt;/a&gt; suggested might be worth exploring.  I look forward to any comments you might have.</diff>
      <filename>content/site/tag/blog.atom</filename>
    </modified>
    <modified>
      <diff>@@ -39,7 +39,7 @@ I recently uploaded some links to my &lt;a href=&quot;http://github.com/hugoduncan/cl-bl
   &lt;/a&gt;&lt;/div&gt;
 &lt;/div&gt;
 &lt;hr/&gt;
-Related Tags: &lt;div class=&quot;tags-related&quot;&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/clbloggenerator.xhtml&quot;&gt;cl-blog-generator&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/generator.xhtml&quot;&gt;generator&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/lisp.xhtml&quot;&gt;lisp&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
+Related Tags: &lt;div class=&quot;tags-related&quot;&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/advogato.xhtml&quot;&gt;advogato&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/clbloggenerator.xhtml&quot;&gt;cl-blog-generator&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/generator.xhtml&quot;&gt;generator&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/lisp.xhtml&quot;&gt;lisp&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/body&gt;</diff>
      <filename>content/site/tag/blog.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -9,9 +9,14 @@
  &lt;author&gt;&lt;name&gt;Hugo Duncan&lt;/name&gt;&lt;/author&gt;
  &lt;subtitle&gt;Development Blog&lt;/subtitle&gt;
  &lt;rights&gt;All content written by Hugo Duncan and photos by Hugo Duncan Copyright Hugo Duncan, all rights reserved.&lt;/rights&gt;
- &lt;updated&gt;2009-03-30T20:47:43.993889-04:00&lt;/updated&gt;
+ &lt;updated&gt;2009-03-31T00:43:21.859845-04:00&lt;/updated&gt;
 
-&lt;entry xml:base=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/&quot;&gt;&lt;title&gt;Blog Site Generators&lt;/title&gt;&lt;link href=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&quot;/&gt;&lt;id&gt;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&lt;/id&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;updated&gt;2009-03-26T20:00:00.000000-04:00&lt;/updated&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;cl-blog-generator&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;lisp&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;blog&quot;/&gt;&lt;summary type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;
+&lt;entry xml:base=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/&quot;&gt;&lt;title&gt;cl-blog-generator Gets Comments&lt;/title&gt;&lt;link href=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml&quot;/&gt;&lt;id&gt;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml&lt;/id&gt;&lt;published&gt;2009-03-30T20:00:00.000000-04:00&lt;/published&gt;&lt;updated&gt;2009-03-30T20:00:00.000000-04:00&lt;/updated&gt;&lt;published&gt;2009-03-30T20:00:00.000000-04:00&lt;/published&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;advogato&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;cl-blog-generator&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;lisp&quot;/&gt;&lt;summary type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;I have now added a comment system to &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt;.  My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.&lt;/p&gt;&lt;/div&gt;&lt;/summary&gt;&lt;content type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;I have now added a comment system to &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt;.  My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.&lt;/p&gt;
+
+&lt;p&gt;The comment system was inspired by &lt;a href=&quot;http://www.steve.org.uk/Software/chronicle/&quot;&gt;Chronicle&lt;/a&gt;'s, with a slight modification in approach - the comments are never saved on the web server, and are just sent by email to a dedicated email address.  Spam filtering is delegated to the whatever spam filtering is implemented on the mail server, or in your email client.  The comment emails are then processed in CL using &lt;a href=&quot;http://common-lisp.net/project/mel-base/&quot;&gt;mel-base&lt;/a&gt; and written to the local filesystem.  Moderation can optionally occur on the CL side, if that is preferable to using the email client.&lt;/p&gt;
+
+&lt;p&gt;There is still some work left to do - I would like to be able to switch off comments on individual posts, either on demand on after a default time period - but I thought I would let real world usage drive my development.&lt;/p&gt;
+&lt;/div&gt;&lt;/content&gt;&lt;/entry&gt;&lt;entry xml:base=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/&quot;&gt;&lt;title&gt;Blog Site Generators&lt;/title&gt;&lt;link href=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&quot;/&gt;&lt;id&gt;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&lt;/id&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;updated&gt;2009-03-26T20:00:00.000000-04:00&lt;/updated&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;cl-blog-generator&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;lisp&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;blog&quot;/&gt;&lt;summary type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;
 I recently uploaded some links to my &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt; project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as &lt;a href=&quot;http://www.advogato.org/person/Stevey/&quot;&gt;Steve Kemp&lt;/a&gt;'s &lt;a href=&quot;http://www.steve.org.uk/Software/chronicle/&quot;&gt;Chronicle&lt;/a&gt;, or &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; as used on &lt;a href=&quot;http://github.com/blog/272-github-pages&quot;&gt;GitHub Pages&lt;/a&gt;.  Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that &lt;a href=&quot;http://advogato.org/person/chalst/&quot;&gt;Charles Stewart&lt;/a&gt; suggested might be worth exploring.  I look forward to any comments you might have.
 &lt;/p&gt;&lt;/div&gt;&lt;/summary&gt;&lt;content type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;
 I recently uploaded some links to my &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt; project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as &lt;a href=&quot;http://www.advogato.org/person/Stevey/&quot;&gt;Steve Kemp&lt;/a&gt;'s &lt;a href=&quot;http://www.steve.org.uk/Software/chronicle/&quot;&gt;Chronicle&lt;/a&gt;, or &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; as used on &lt;a href=&quot;http://github.com/blog/272-github-pages&quot;&gt;GitHub Pages&lt;/a&gt;.  Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that &lt;a href=&quot;http://advogato.org/person/chalst/&quot;&gt;Charles Stewart&lt;/a&gt; suggested might be worth exploring.  I look forward to any comments you might have.</diff>
      <filename>content/site/tag/clbloggenerator.atom</filename>
    </modified>
    <modified>
      <diff>@@ -15,6 +15,11 @@
 &lt;div id=&quot;centercontent&quot;&gt;
 &lt;div class=&quot;posts&quot;&gt;
   &lt;div class=&quot;post-link-with-synopsis&quot;&gt;
+    &lt;span class=&quot;post-link&quot;&gt;&lt;a href=&quot;/Users/duncan/projects/blog/content/site/post/2009/cl_blog_generator_gets_comments.xhtml&quot;&gt;cl-blog-generator Gets Comments&lt;/a&gt;&lt;/span&gt; &#183;
+    &lt;span class=&quot;post-synopsis&quot;&gt;&lt;p&gt;I have now added a comment system to &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt;.  My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.&lt;/p&gt;&lt;/span&gt;
+  &lt;/div&gt;
+
+  &lt;div class=&quot;post-link-with-synopsis&quot;&gt;
     &lt;span class=&quot;post-link&quot;&gt;&lt;a href=&quot;/Users/duncan/projects/blog/content/site/post/2009/blog_site_generators.xhtml&quot;&gt;Blog Site Generators&lt;/a&gt;&lt;/span&gt; &#183;
     &lt;span class=&quot;post-synopsis&quot;&gt;&lt;p&gt;
 I recently uploaded some links to my &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt; project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as &lt;a href=&quot;http://www.advogato.org/person/Stevey/&quot;&gt;Steve Kemp&lt;/a&gt;'s &lt;a href=&quot;http://www.steve.org.uk/Software/chronicle/&quot;&gt;Chronicle&lt;/a&gt;, or &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; as used on &lt;a href=&quot;http://github.com/blog/272-github-pages&quot;&gt;GitHub Pages&lt;/a&gt;.  Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that &lt;a href=&quot;http://advogato.org/person/chalst/&quot;&gt;Charles Stewart&lt;/a&gt; suggested might be worth exploring.  I look forward to any comments you might have.
@@ -34,7 +39,7 @@ I recently uploaded some links to my &lt;a href=&quot;http://github.com/hugoduncan/cl-bl
   &lt;/a&gt;&lt;/div&gt;
 &lt;/div&gt;
 &lt;hr/&gt;
-Related Tags: &lt;div class=&quot;tags-related&quot;&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/generator.xhtml&quot;&gt;generator&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/blog.xhtml&quot;&gt;blog&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/lisp.xhtml&quot;&gt;lisp&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
+Related Tags: &lt;div class=&quot;tags-related&quot;&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/advogato.xhtml&quot;&gt;advogato&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/blog.xhtml&quot;&gt;blog&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/generator.xhtml&quot;&gt;generator&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/lisp.xhtml&quot;&gt;lisp&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/body&gt;</diff>
      <filename>content/site/tag/clbloggenerator.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -9,9 +9,14 @@
  &lt;author&gt;&lt;name&gt;Hugo Duncan&lt;/name&gt;&lt;/author&gt;
  &lt;subtitle&gt;Development Blog&lt;/subtitle&gt;
  &lt;rights&gt;All content written by Hugo Duncan and photos by Hugo Duncan Copyright Hugo Duncan, all rights reserved.&lt;/rights&gt;
- &lt;updated&gt;2009-03-30T20:47:44.043133-04:00&lt;/updated&gt;
+ &lt;updated&gt;2009-03-31T00:43:21.924992-04:00&lt;/updated&gt;
 
-&lt;entry xml:base=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/&quot;&gt;&lt;title&gt;Blog Site Generators&lt;/title&gt;&lt;link href=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&quot;/&gt;&lt;id&gt;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&lt;/id&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;updated&gt;2009-03-26T20:00:00.000000-04:00&lt;/updated&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;cl-blog-generator&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;lisp&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;blog&quot;/&gt;&lt;summary type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;
+&lt;entry xml:base=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/&quot;&gt;&lt;title&gt;cl-blog-generator Gets Comments&lt;/title&gt;&lt;link href=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml&quot;/&gt;&lt;id&gt;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml&lt;/id&gt;&lt;published&gt;2009-03-30T20:00:00.000000-04:00&lt;/published&gt;&lt;updated&gt;2009-03-30T20:00:00.000000-04:00&lt;/updated&gt;&lt;published&gt;2009-03-30T20:00:00.000000-04:00&lt;/published&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;advogato&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;cl-blog-generator&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;lisp&quot;/&gt;&lt;summary type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;I have now added a comment system to &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt;.  My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.&lt;/p&gt;&lt;/div&gt;&lt;/summary&gt;&lt;content type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;I have now added a comment system to &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt;.  My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.&lt;/p&gt;
+
+&lt;p&gt;The comment system was inspired by &lt;a href=&quot;http://www.steve.org.uk/Software/chronicle/&quot;&gt;Chronicle&lt;/a&gt;'s, with a slight modification in approach - the comments are never saved on the web server, and are just sent by email to a dedicated email address.  Spam filtering is delegated to the whatever spam filtering is implemented on the mail server, or in your email client.  The comment emails are then processed in CL using &lt;a href=&quot;http://common-lisp.net/project/mel-base/&quot;&gt;mel-base&lt;/a&gt; and written to the local filesystem.  Moderation can optionally occur on the CL side, if that is preferable to using the email client.&lt;/p&gt;
+
+&lt;p&gt;There is still some work left to do - I would like to be able to switch off comments on individual posts, either on demand on after a default time period - but I thought I would let real world usage drive my development.&lt;/p&gt;
+&lt;/div&gt;&lt;/content&gt;&lt;/entry&gt;&lt;entry xml:base=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/&quot;&gt;&lt;title&gt;Blog Site Generators&lt;/title&gt;&lt;link href=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&quot;/&gt;&lt;id&gt;http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml&lt;/id&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;updated&gt;2009-03-26T20:00:00.000000-04:00&lt;/updated&gt;&lt;published&gt;2009-03-26T20:00:00.000000-04:00&lt;/published&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;cl-blog-generator&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;lisp&quot;/&gt;&lt;category scheme=&quot;http://hugoduncan.github.com/cl-blog-generator/content/site/tags&quot; term=&quot;blog&quot;/&gt;&lt;summary type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;
 I recently uploaded some links to my &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt; project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as &lt;a href=&quot;http://www.advogato.org/person/Stevey/&quot;&gt;Steve Kemp&lt;/a&gt;'s &lt;a href=&quot;http://www.steve.org.uk/Software/chronicle/&quot;&gt;Chronicle&lt;/a&gt;, or &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; as used on &lt;a href=&quot;http://github.com/blog/272-github-pages&quot;&gt;GitHub Pages&lt;/a&gt;.  Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that &lt;a href=&quot;http://advogato.org/person/chalst/&quot;&gt;Charles Stewart&lt;/a&gt; suggested might be worth exploring.  I look forward to any comments you might have.
 &lt;/p&gt;&lt;/div&gt;&lt;/summary&gt;&lt;content type=&quot;xhtml&quot;&gt;&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;p&gt;
 I recently uploaded some links to my &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt; project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as &lt;a href=&quot;http://www.advogato.org/person/Stevey/&quot;&gt;Steve Kemp&lt;/a&gt;'s &lt;a href=&quot;http://www.steve.org.uk/Software/chronicle/&quot;&gt;Chronicle&lt;/a&gt;, or &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; as used on &lt;a href=&quot;http://github.com/blog/272-github-pages&quot;&gt;GitHub Pages&lt;/a&gt;.  Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that &lt;a href=&quot;http://advogato.org/person/chalst/&quot;&gt;Charles Stewart&lt;/a&gt; suggested might be worth exploring.  I look forward to any comments you might have.</diff>
      <filename>content/site/tag/lisp.atom</filename>
    </modified>
    <modified>
      <diff>@@ -15,6 +15,11 @@
 &lt;div id=&quot;centercontent&quot;&gt;
 &lt;div class=&quot;posts&quot;&gt;
   &lt;div class=&quot;post-link-with-synopsis&quot;&gt;
+    &lt;span class=&quot;post-link&quot;&gt;&lt;a href=&quot;/Users/duncan/projects/blog/content/site/post/2009/cl_blog_generator_gets_comments.xhtml&quot;&gt;cl-blog-generator Gets Comments&lt;/a&gt;&lt;/span&gt; &#183;
+    &lt;span class=&quot;post-synopsis&quot;&gt;&lt;p&gt;I have now added a comment system to &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt;.  My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.&lt;/p&gt;&lt;/span&gt;
+  &lt;/div&gt;
+
+  &lt;div class=&quot;post-link-with-synopsis&quot;&gt;
     &lt;span class=&quot;post-link&quot;&gt;&lt;a href=&quot;/Users/duncan/projects/blog/content/site/post/2009/blog_site_generators.xhtml&quot;&gt;Blog Site Generators&lt;/a&gt;&lt;/span&gt; &#183;
     &lt;span class=&quot;post-synopsis&quot;&gt;&lt;p&gt;
 I recently uploaded some links to my &lt;a href=&quot;http://github.com/hugoduncan/cl-blog-generator&quot;&gt;cl-blog-generator&lt;/a&gt; project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as &lt;a href=&quot;http://www.advogato.org/person/Stevey/&quot;&gt;Steve Kemp&lt;/a&gt;'s &lt;a href=&quot;http://www.steve.org.uk/Software/chronicle/&quot;&gt;Chronicle&lt;/a&gt;, or &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; as used on &lt;a href=&quot;http://github.com/blog/272-github-pages&quot;&gt;GitHub Pages&lt;/a&gt;.  Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that &lt;a href=&quot;http://advogato.org/person/chalst/&quot;&gt;Charles Stewart&lt;/a&gt; suggested might be worth exploring.  I look forward to any comments you might have.
@@ -44,7 +49,7 @@ I recently uploaded some links to my &lt;a href=&quot;http://github.com/hugoduncan/cl-bl
   &lt;/a&gt;&lt;/div&gt;
 &lt;/div&gt;
 &lt;hr/&gt;
-Related Tags: &lt;div class=&quot;tags-related&quot;&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/clbloggenerator.xhtml&quot;&gt;cl-blog-generator&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/generator.xhtml&quot;&gt;generator&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/blog.xhtml&quot;&gt;blog&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
+Related Tags: &lt;div class=&quot;tags-related&quot;&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/advogato.xhtml&quot;&gt;advogato&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/blog.xhtml&quot;&gt;blog&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/clbloggenerator.xhtml&quot;&gt;cl-blog-generator&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;/cl-blog-generator/content/site/tag/generator.xhtml&quot;&gt;generator&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/body&gt;</diff>
      <filename>content/site/tag/lisp.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -3,37 +3,43 @@
 ;;; Generate a blog site from input posts.
 
 ;;; TODO
-;;; tag links and pages
-;;; comments
+;;; Comment feed
+;;; Documentation
 
 (in-package #:cl-blog-generator)
 
 ;;;# Configuration
-;;; These are the special variables used to control the blog generator's behaviour.
+
+;;; These are the special variables used to control the blog generator's
+;;; behaviour.
+
+;;; Database connection specification for Elephant.  See Elephant documentation
+;;; for syntax.
+(defvar *blog-db-spec* nil
+  &quot;The database connection&quot;)
+
+;;; The blog's title.
 (defvar *blog-title* nil
   &quot;The blog's title.&quot;)
-(defvar *blog-db-spec* nil
-  &quot;The database to be used by elephant to maintain blog metadata.&quot;)
+
+;;;## Paths
+;;; These determine the URL of the blog on its website.
 (defvar *blog-domain* nil
   &quot;A domain for the blog. Used to generate unique ids.&quot;)
 (defvar *blog-root-path* nil
-  &quot;The path of the blog on whichever site the blog will be hosted at.&quot;) ;; should end in /
+  &quot;The path of the blog root on the hosted web site.&quot;) ; ends in /
+
+;;; Local file system paths for content.
 (defvar *site-path* nil
-  &quot;The local directory used to generate the site.&quot;)
+  &quot;The local directory in which to generate the site.&quot;)
 (defvar *published-path* nil
-  &quot;The local directory that will contain the published posts.&quot;)
+  &quot;The local directory that contains the published posts.&quot;)
 (defvar *template-path* nil
-  &quot;The local directory that contains the xhtml templates.&quot;)
-
-;;; Optional configuration for customising the behaviour of the system
-(defvar *id-generator-fn* nil
-  &quot;Function used to generate a unique id for an item.&quot;)
-
-(defvar *blog-post-relative-path-fn* nil
-  &quot;The function used to generate the path of content relative to *BLOG-ROOT-PATH* or *PUBLISHED-PATH*&quot;)
-(defvar *page-relative-path-fn* nil
-  &quot;The function used to generate the path of content relative to *BLOG-ROOT-PATH* or *PUBLISHED-PATH*&quot;)
+  &quot;The local directory that contains the XHTML templates.&quot;)
 
+;;; These determine the path components on the generated web site under
+;;; *BLOG-ROOT-PATH*, and on the local file system under the *PUBLISHED-PATH*
+;;; and *SITE-PATH*.  These are used by the default path functions.
 (defvar *blog-post-path* '(&quot;post&quot;)
   &quot;Default path list for BLOG-POST content.&quot;)
 (defvar *page-path* '(&quot;page&quot;)
@@ -41,53 +47,52 @@
 (defvar *tag-page-path* '(&quot;tag&quot;)
   &quot;Default path list for TAG-PAGE content.&quot;)
 (defvar *comment-path* '(&quot;comment&quot;)
-  &quot;Default path list for COMMENT.&quot;)
+  &quot;Default path list for COMMENT, relative to *PUBLISHED-PATH*&quot;)
+
+;;; These are customisation points for the content paths, and only need to be
+;;; altered if you want a path structure different to the default.
+(defvar *blog-post-relative-path-fn* nil
+  &quot;The function used to generate the path of content relative to
+  *BLOG-ROOT-PATH* or *PUBLISHED-PATH*&quot;)
+(defvar *page-relative-path-fn* nil
+  &quot;The function used to generate the path of content relative to
+  *BLOG-ROOT-PATH* or *PUBLISHED-PATH*&quot;)
 
+;;; Default templates to use when none are specified.
 (defvar *blog-post-template* &quot;post&quot;
   &quot;Template to use for each blog-post&quot;)
-
 (defvar *default-template* &quot;post&quot;
   &quot;Template to use if none specified&quot;)
 
+;;; File types (extensions) to use when generating published file names.
 (defvar *templated-content-file-types*
   '((page . &quot;page&quot;)
     (blog-post . &quot;post&quot;)
     (comment . &quot;comment&quot;))
   &quot;Default file extensions for the published content.&quot;)
 
-(defvar *category-scheme-uri* nil
-  &quot;URI for category scheme.  If left null this will be generated to point to the tags page.&quot;)
+;;;## Atom
 
-;;; Tags used for identifying elements
-(defparameter *xhtml-xmlns* &quot;http://www.w3.org/1999/xhtml&quot;)
-(defparameter *post-xmlns* &quot;http://hugoduncan.org/xmlns/post&quot;)
+;;; ATOM requires unique id's for each feed element.  The default is to use the
+;;; post's URL. This function can be set to overide the default.
+(defvar *id-generator-fn* nil
+  &quot;Function used to generate a unique id for an item.&quot;)
 
-(defparameter *post-when* &quot;when&quot;)
-(defparameter *post-updated* &quot;updated&quot;)
-(defparameter *post-linkname* &quot;linkname&quot;)
-(defparameter *post-tag* &quot;tag&quot;)
-(defparameter *post-title* &quot;title&quot;)
-(defparameter *post-head* &quot;head&quot;)
-(defparameter *post-body* &quot;body&quot;)
-(defparameter *post-meta* &quot;meta&quot;)
-(defparameter *post-link* &quot;link&quot;)
-(defparameter *post-description* &quot;description&quot;)
-(defparameter *post-name* &quot;name&quot;)
-(defparameter *post-content* &quot;content&quot;)
-(defparameter *post-template* &quot;template&quot;)
-(defparameter *page-link-for* &quot;page-link-for&quot;)
-(defparameter *element-id* &quot;id&quot;)
-(defparameter *element-class* &quot;class&quot;)
+;;; The post tags appear in the generatom ATOM feed.  The category scheme can be
+;;; customised here.
+(defvar *category-scheme-uri* nil
+  &quot;URI for category scheme.  If null, the tag page URL is used.&quot;)
 
-(defparameter *rel-alternate* &quot;alternate&quot;)
-(defparameter *atom-mime* &quot;application/atom+xml&quot;)
+;;;## Other
 
-(defparameter *href* &quot;href&quot;)
+;;; The indentation in the generated files can be controlled.  See CXML
+;;; documentation for values.
+(defparameter *publish-xml-indentation* nil
+  &quot;Controls the indentation in the generated files.&quot;)
 
-(defparameter *feed-title* &quot;title&quot;)
-(defparameter *feed-uri* &quot;id&quot;)
-(defparameter *feed-updated* &quot;updated&quot;)
 
+
+;;;# Template Id's and Class's
 (defparameter *post-content-id* &quot;post&quot;
   &quot;ID of element to contain the post content&quot;)
 (defparameter *post-title-id* &quot;post-title&quot;
@@ -96,6 +101,7 @@
   &quot;ID of element to contain the post when date&quot;)
 (defparameter *post-updated-id* &quot;post-updated&quot;
   &quot;ID of element to contain the post updated date&quot;)
+
 (defparameter *post-posts-class* &quot;posts&quot;
   &quot;Class of element to contain the posts list&quot;)
 (defparameter *post-synopsis-class* &quot;post-synopsis&quot;
@@ -131,8 +137,42 @@
 (defparameter *post-slug-hidden-input-class* &quot;post-slug-hidden-input&quot;
   &quot;Class of element to contain a hidden input element containing the page slug&quot;)
 
+(defparameter *delicious-class* &quot;delicious&quot;
+  &quot;Class for posting to delicious&quot;)
+(defparameter *digg-class* &quot;digg&quot;
+  &quot;Class for posting to digg&quot;)
+
+(defparameter *page-link-for-class* &quot;page-link-for&quot;)
+
+;;;# Tags used for identifying elements
+;;; These should be constants...
+(defparameter *xhtml-xmlns* &quot;http://www.w3.org/1999/xhtml&quot;)
+(defparameter *post-xmlns* &quot;http://hugoduncan.org/xmlns/post&quot;)
+
+(defparameter *post-when* &quot;when&quot;)
+(defparameter *post-updated* &quot;updated&quot;)
+(defparameter *post-linkname* &quot;linkname&quot;)
+(defparameter *post-tag* &quot;tag&quot;)
+
+(defparameter *post-title* &quot;title&quot;)
+(defparameter *post-head* &quot;head&quot;)
+(defparameter *post-body* &quot;body&quot;)
+(defparameter *post-meta* &quot;meta&quot;)
+(defparameter *post-link* &quot;link&quot;)
+(defparameter *post-description* &quot;description&quot;)
+(defparameter *post-name* &quot;name&quot;)
+(defparameter *post-content* &quot;content&quot;)
+(defparameter *post-template* &quot;template&quot;)
+(defparameter *element-id* &quot;id&quot;)
+(defparameter *element-class* &quot;class&quot;)
+(defparameter *rel-alternate* &quot;alternate&quot;)
+(defparameter *href* &quot;href&quot;)
+
+(defparameter *atom-mime* &quot;application/atom+xml&quot;)
+(defparameter *feed-title* &quot;title&quot;)
+(defparameter *feed-uri* &quot;id&quot;)
+(defparameter *feed-updated* &quot;updated&quot;)
 
-(defparameter *publish-xml-indentation* nil)
 
 ;;;# Configuration environments
 
@@ -143,7 +183,8 @@
 (defvar *environments* nil &quot;Registered environments&quot;)
 
 (defun set-environment (environment parameters)
-  &quot;Assign the configuration of an environment.  This does not make the environment active.&quot;
+  &quot;Assign the configuration of an environment.  This does not make the
+environment active.&quot;
   (let ((existing (assoc environment *environments*)))
     (if existing
 	(setf (cdr existing) parameters)
@@ -153,7 +194,8 @@
 (defun configure (environment)
   &quot;Activate an environment.&quot;
   (flet ((symbol-for-key (key)
-	   (find-symbol (format nil &quot;*~A*&quot; (symbol-name key)) '#:cl-blog-generator)))
+	   (find-symbol (format nil &quot;*~A*&quot; (symbol-name key))
+			'#:cl-blog-generator)))
     (let ((alist-cons (assoc environment *environments*)))
       (unless alist-cons
 	(error &quot;Request for unknown configuration environment ~A&quot; environment))
@@ -174,7 +216,8 @@
   &quot;Sanitise a title for use as a file system path or as a http uri&quot;
   (flet ((remove-character-p (char)
 	   (find char &quot;!.,/\\|+=`~-@#$%^&amp;*{}[]()\&quot;':;&lt;&gt;&quot;)))
-    (let ((sane (remove-if #'remove-character-p (string-downcase (substitute #\_ #\Space title)))))
+    (let ((sane (remove-if #'remove-character-p
+			   (string-downcase (substitute #\_ #\Space title)))))
       (values sane))))
 
 (defun %sanitise-synopsis (synopsis)
@@ -188,12 +231,25 @@
 	 do (when (eql key :characters)
 	      (format output (klacks:current-characters source)))))))
 
+(defun merge-assoc (a b &amp;key (test #'eql))
+  &quot;Merge association lists A and B, such that values from B take precedence.&quot;
+  (loop with result = (copy-seq a)
+     for kv in b
+     for assoc = (assoc (car kv) a :test test)
+     do
+       (if assoc
+	   (setf (cdr assoc) (cdr kv))
+	   (setf result (acons (car kv) (cdr kv) result)))
+     finally
+       (return result)))
+
 ;;;## File System Helpers
 ;;; These functions generate local file paths based on the configuration.
 (defun %template-path (key)
   &quot;Find the path to a template for the specified KEY.&quot;
   (make-pathname :name key
-		 :type (if (string= key &quot;atom&quot;) &quot;xml&quot; &quot;xhtml&quot;) :defaults *template-path*))
+		 :type (if (string= key &quot;atom&quot;) &quot;xml&quot; &quot;xhtml&quot;)
+		 :defaults *template-path*))
 
 
 
@@ -379,9 +435,9 @@ to SINK. Returns the attributes of the element found.&quot;
 ;;;# Database
 
 ;;;## Generated Content Persistent Classes
-;;; The various types of pages are handled by their own class.
-;;; The generated content class serves as a base class for our protocol, and enables
-;;; querying for all dirty content.
+;;; The various types of pages are handled by their own class.  The generated
+;;; content class serves as a base class for our protocol, and enables querying
+;;; for all dirty content.
 (defclass generated-content ()
   ((dirty :initform t :accessor dirty :type boolean :indexed t))
   (:index t)
@@ -396,7 +452,8 @@ to SINK. Returns the attributes of the element found.&quot;
   (:documentation &quot;Page for an atom feed.&quot;))
 
 (defmethod site-file-path-for ((atom-feed atom-feed))
-  (make-pathname :type &quot;atom&quot; :defaults (site-file-path-for (content-page atom-feed))))
+  (make-pathname :type &quot;atom&quot;
+		 :defaults (site-file-path-for (content-page atom-feed))))
 
 (defmethod path-for ((atom-feed atom-feed))
   (make-pathname :type &quot;atom&quot; :defaults (path-for (content-page atom-feed))))
@@ -430,14 +487,16 @@ to SINK. Returns the attributes of the element found.&quot;
 			 :content-page index-page))))
 
 (defmethod content-title ((index-page index-page))
-  &quot;The blog title is returned as empty in the expectation that it is specified in the template&quot;
+  &quot;The blog title is returned as empty in the expectation that it is specified
+in the template&quot;
   &quot;&quot;)
 
 ;;;### Tag pages
 (defclass tag-page (generated-content)
   ((filename :initarg :filename :reader content-filename)
    (tag :initarg :tag :initform nil :reader tag-page-tag :index t)
-   (related-tags :initarg :related-tags :initform nil :accessor tag-page-related-tags)
+   (related-tags :initarg :related-tags :initform nil
+		 :accessor tag-page-related-tags)
    (feed :accessor content-feed :transient t))
   (:metaclass elephant:persistent-metaclass)
   (:documentation &quot;Page for content matching a tag.&quot;))
@@ -487,7 +546,8 @@ to SINK. Returns the attributes of the element found.&quot;
    (updated :initarg :updated :initform nil :accessor content-updated
 	    :type unsigned-byte :index t
 	    :documentation &quot;Last update time&quot;)
-   (description :initarg :description :initform nil :accessor content-description)
+   (description :initarg :description :initform nil
+		:accessor content-description)
    (synopsis :initarg :synopsis :initform nil :accessor content-synopsis))
   (:metaclass elephant:persistent-metaclass)
   (:documentation &quot;Metadata for templated user content&quot;))
@@ -592,19 +652,20 @@ to SINK. Returns the attributes of the element found.&quot;
 	  (list (content-filename (content-page comment)))))
 
 (defmethod path-for ((comment comment))
-  (concatenate 'simple-string (path-for (content-page comment)) &quot;#&quot; (content-filename comment)))
+  (concatenate 'simple-string (path-for (content-page comment))
+	       &quot;#&quot; (content-filename comment)))
 
 
 ;;;### Blog post
-;;; A blog post is content with a template of &quot;post&quot; which is the default template.
+;;; A blog post is content with a template of &quot;post&quot; which is the default
+;;; template.
 (defclass blog-post (templated-content)
-  ((template :initform *blog-post-template* :reader content-template :allocation :class :transient t)
+  ((template :initform *blog-post-template* :reader content-template
+	     :allocation :class :transient t)
    (comments :initform (elephant:make-btree) :reader content-comments))
   (:metaclass elephant:persistent-metaclass)
   (:documentation &quot;Metadata for blog-posts&quot;))
 
-
-
 (defmethod print-object ((object blog-post) stream)
   &quot;Print a blog post instance showing date and filename&quot;
   (print-unreadable-object (object stream :type t)
@@ -614,7 +675,8 @@ to SINK. Returns the attributes of the element found.&quot;
 
 (defmethod relative-path-for ((blog-post blog-post))
   &quot;Relative path for a blog post&quot;
-  (append *blog-post-path* (list (format nil &quot;~A&quot; (content-year blog-post)))))
+  (append *blog-post-path*
+	  (list (format nil &quot;~A&quot; (content-year blog-post)))))
 
 (defmethod link-for ((blog-post blog-post) &amp;key url)
   (cxml:with-element &quot;a&quot;
@@ -657,15 +719,19 @@ to SINK. Returns the attributes of the element found.&quot;
 
 (defun %recent-posts (&amp;key (n 10))
   &quot;Create a list of recent posts.&quot;
-  (elephant:with-btree-cursor (cursor (elephant:find-inverted-index 'blog-post 'when))
+  (elephant:with-btree-cursor
+      (cursor (elephant:find-inverted-index 'blog-post 'when))
     (let (has-pair key value)
-      (multiple-value-setq (has-pair key value) (elephant:cursor-last cursor))
+      (multiple-value-setq (has-pair key value)
+	(elephant:cursor-last cursor))
       (loop
 	 for i from 0 below n
 	 while has-pair
-	 collect (elephant::controller-recreate-instance elephant:*store-controller* value)
+	 collect (elephant::controller-recreate-instance
+		  elephant:*store-controller* value)
 	 do
-	   (multiple-value-setq (has-pair key value) (elephant:cursor-prev cursor))))))
+	   (multiple-value-setq (has-pair key value)
+	     (elephant:cursor-prev cursor))))))
 
 (defun %tag-posts (tag)
   &quot;Create a list of recent posts for a given tag.&quot;
@@ -701,16 +767,19 @@ to SINK. Returns the attributes of the element found.&quot;
       (assert has-pair)
       (loop
 	 while (and has-pair (not (= oid value)))
-	 do (multiple-value-setq (has-pair key value) (elephant:cursor-next cursor)))
+	 do (multiple-value-setq (has-pair key value)
+	      (elephant:cursor-next cursor)))
       (assert (= oid value))
       (multiple-value-setq (has-pair key value) (elephant:cursor-prev cursor))
       (if has-pair
-	  (setf prior (elephant::controller-recreate-instance elephant:*store-controller* value)))
+	  (setf prior (elephant::controller-recreate-instance
+		       elephant:*store-controller* value)))
       (multiple-value-setq (has-pair key value) (elephant:cursor-next cursor))
       (assert (= oid value))
       (multiple-value-setq (has-pair key value) (elephant:cursor-next cursor))
       (if has-pair
-	  (setf next (elephant::controller-recreate-instance elephant:*store-controller* value)))
+	  (setf next (elephant::controller-recreate-instance
+		      elephant:*store-controller* value)))
       (values prior next))))
 
 
@@ -767,12 +836,14 @@ the path to the published file and the site path.&quot;
   NAME with EMAIL and URI.  TEXT is plain text.&quot;
   (macrolet ((with-each-paragraph ((var text) &amp;body body)
 	       (let ((paras (gensym)))
-		 `(let ((,paras (cl-ppcre:split &quot;(?:\\r\\n|\\n|\\r){2,}&quot; ,text)))
+		 `(let ((,paras
+			 (cl-ppcre:split &quot;(?:\\r\\n|\\n|\\r){2,}&quot; ,text)))
 		    (loop for ,var in ,paras
 		       do ,@body)))))
     (labels ((htmlify (para)
 	       (let ((i 0))
-		 (cl-ppcre:do-scans (ms me rs re &quot;(https?|mailto)://[\\S-/]+/\\S*&quot; para)
+		 (cl-ppcre:do-scans
+		     (ms me rs re &quot;(https?|mailto)://[\\S-/]+/\\S*&quot; para)
 		   (when (&gt; ms i)
 		     (cxml:text (subseq para i ms)))
 		   (let ((link (subseq para ms me)))
@@ -792,18 +863,21 @@ the path to the published file and the site path.&quot;
 	     (elephant::get-instance-by-value 'blog-post 'filename post-slug)))
 	(unless blog-post
 	  (error &quot;Unknown post ~A&quot; post-slug))
-	(let ((comment (make-instance 'comment :content-page blog-post :ip ip :name
-				      name :email email :uri uri :when when)))
+	(let ((comment
+	       (make-instance 'comment :content-page blog-post :ip ip
+			      :name name :email email :uri uri :when when)))
 	  (setf (elephant:get-value (content-filename comment)
 				    (content-comments blog-post))
 		comment)
 	  (setf (dirty blog-post) t)
 	  (with-open-file (stream (published-file-path-for comment)
 				  :element-type '(unsigned-byte 8)
-				  :direction :output :if-does-not-exist :create)
-	    (let ((output (cxml:make-octet-stream-sink stream :canonical nil
-						       :indentation nil
-						       :omit-xml-declaration-p t)))
+				  :direction :output
+				  :if-does-not-exist :create)
+	    (let ((output
+		   (cxml:make-octet-stream-sink
+		    stream :canonical nil :indentation nil
+		    :omit-xml-declaration-p t)))
 	      (cxml:with-xml-output output
 		(cxml:with-element &quot;comment&quot;
 		  (cxml:with-element &quot;ip&quot;
@@ -838,14 +912,15 @@ the path to the published file and the site path.&quot;
 		   :template template)))
 
 ;;; Publish a draft. This puts the draft into publish, and creates database meta
-;;; info for it. Returns the published file path and the blog-post metadata.
-;;; If a post with the same title already exists, then we assume this is an error
-;;; and raise a condition.  A restart is provided to delete the existing post and
-;;; proceed.
+;;; info for it. Returns the published file path and the blog-post metadata.  If
+;;; a post with the same title already exists, then we assume this is an error
+;;; and raise a condition.  A restart is provided to delete the existing post
+;;; and proceed.
 (defun %publish-draft (path)
   &quot;Publish the draft at the filesystem PATH.&quot;
-  (multiple-value-bind (title post-when post-updated tags linkname description
-			      synopsis template)
+  (multiple-value-bind
+	(title post-when post-updated tags linkname description synopsis
+	       template)
       (%parse-post-info path)
     (let ((existing-post
 	   (or
@@ -873,18 +948,24 @@ the path to the published file and the site path.&quot;
 ;;; path and the blog-post metadata.
 (defun %publish-updated-post (path)
   &quot;Publish the updated post at the filesystem PATH.&quot;
-  (multiple-value-bind (title post-when post-updated tags linkname description synopsis)
+  (multiple-value-bind
+	(title post-when post-updated tags linkname description synopsis
+	       template)
       (%parse-post-info path)
-    (declare (ignore post-when tags description))
+    (declare (ignore post-when template))
+    (break)
     (let ((existing-post
-	   (elephant:get-instances-by-value 'blog-post 'filename linkname)))
+	   (or (elephant:get-instances-by-value 'blog-post 'filename linkname)
+	       (elephant:get-instances-by-value 'page 'filename linkname))))
       (when existing-post
 	(assert (= 1 (length existing-post)))
 	(setf existing-post (first existing-post)))
       (unless existing-post
-	(error &quot;This blog post can not be found. Ensure that the linkname has not been changed.&quot;))
+	(error &quot;This blog post (~A) can not be found with slug ~A.
+Ensure that the linkname has not been changed.&quot; path linkname))
       (unless (equal (published-file-path-for existing-post) path)
-	(error &quot;This blog post is not in the expected location. Ensure that the file has not been moved.&quot;))
+	(error &quot;This blog post is not in the expected location.
+Ensure that the file has not been moved.&quot;))
 
       (unless post-updated
 	(setf post-updated (decode-local-date (get-universal-time))))
@@ -893,6 +974,8 @@ the path to the published file and the site path.&quot;
       (setf (content-updated existing-post) (encode-date post-updated))
       (setf (content-synopsis existing-post) synopsis)
       (setf (content-title existing-post) title)
+      (setf (content-description existing-post) description)
+      (setf (content-tags existing-post) tags)
 
       (let* ((output-path (make-pathname :type &quot;tmp&quot; :defaults path)))
 	(%publish-draft-updating-post-metadata path output-path existing-post)
@@ -902,18 +985,21 @@ the path to the published file and the site path.&quot;
 	(values output-path existing-post)))))
 
 
-;;; Parse the &quot;title&quot;, &quot;when&quot;, &quot;updated&quot;, &quot;linkname&quot; and &quot;tag&quot; elements.  Also store the first
-;;; paragraph of the post to act as a synopsis.
+;;; Parse the &quot;title&quot;, &quot;when&quot;, &quot;updated&quot;, &quot;linkname&quot; and &quot;tag&quot; elements.  Also
+;;; store the first paragraph of the post to act as a synopsis.
 (defun %parse-post-info (path)
   &quot;Parse the input file at PATH, extracting the metadata.  Returns title,
-when (day month year), updated (day month year), tags, linkname, description, and synopsis.&quot;
-  (let (title tags post-when post-updated linkname description synopsis template)
+when (day month year), updated (day month year), tags, linkname, description,
+and synopsis.&quot;
+  (let (title tags post-when post-updated linkname description
+	      synopsis template)
     (labels ((decode-date (date-data)
 	       (when date-data
 		 (loop for key in '(&quot;day&quot; &quot;month&quot; &quot;year&quot;)
 		    collect (parse-integer
 			     (cdr (assoc key date-data :test #'string=)))))))
-      (klacks:with-open-source (post (cxml:make-source path :entity-resolver #'null-resolver))
+      (klacks:with-open-source
+	  (post (cxml:make-source path :entity-resolver #'null-resolver))
 	(loop
 	do
 	(multiple-value-bind (key ns element) (klacks:consume post)
@@ -924,8 +1010,11 @@ when (day month year), updated (day month year), tags, linkname, description, an
 	     (setf post-updated (%capture-attributes post)))
 	    ((start-post-element-p key ns element *post-meta*)
 	     (let ((attribs (%capture-attributes post)))
-	       (when (string= *post-description* (cdr (assoc &quot;name&quot; attribs :test #'string=)))
-		 (setf description (cdr (assoc &quot;content&quot; attribs :test #'string=))))))
+	       (break)
+	       (when (string= *post-description*
+			      (cdr (assoc &quot;name&quot; attribs :test #'string=)))
+		 (setf description
+		       (cdr (assoc &quot;content&quot; attribs :test #'string=))))))
 	    ((start-post-element-p key ns element *post-title*)
 	     (setf title (klacks:consume-characters post)))
 	    ((start-post-element-p key ns element *post-tag*)
@@ -949,10 +1038,10 @@ when (day month year), updated (day month year), tags, linkname, description, an
       (values title (decode-date post-when) (decode-date post-updated)
 	      tags linkname description synopsis template))))
 
-;;; When a blog post is published or changes, then some of the pages that
-;;; link to the post will need to be updated.  This function finds all such
-;;; pages and marks them dirty.  The index and atom-feed will need updating
-;;; if the post is in the recent-posts list.
+;;; When a blog post is published or changes, then some of the pages that link
+;;; to the post will need to be updated.  This function finds all such pages and
+;;; marks them dirty.  The index and atom-feed will need updating if the post is
+;;; in the recent-posts list.
 (defgeneric %mark-connected-posts-dirty (content)
   (:documentation &quot;Mark connected objects as needing update&quot;))
 
@@ -961,6 +1050,7 @@ when (day month year), updated (day month year), tags, linkname, description, an
 (defmethod %mark-connected-posts-dirty ((blog-post blog-post))
   &quot;Mark as dirty anything that the post should cause to be regenerated&quot;
   (let ((recent-posts (%recent-posts)))
+    (setf *recent-posts* recent-posts)
     (when (find blog-post recent-posts)
       (setf (dirty (index-page)) t))
     (multiple-value-bind (prior next) (%adjacent-posts blog-post)
@@ -975,7 +1065,8 @@ when (day month year), updated (day month year), tags, linkname, description, an
   (setf (dirty (index-page)) t)
   (elephant:map-class #'(lambda (post) (setf (dirty post) t)) 'blog-post)
   (elephant:map-class #'(lambda (post) (setf (dirty post) t)) 'page)
-  (elephant:map-class #'(lambda (post) (setf (dirty post) t)) 'tag-page))
+  (elephant:map-class #'(lambda (post) (setf (dirty post) t)) 'tag-page)
+  (setf *recent-posts* nil))
 
 
 (defun %ensure-tag-page (tag &amp;optional tags)
@@ -1056,7 +1147,8 @@ when (day month year), updated (day month year), tags, linkname, description, an
   &quot;Copy the source inserting the post-when info.  If the output file exists,
 then it is overwritten (if the user has not chosen to delete an existing post,
 then this code will not be executed).&quot;
-  (klacks:with-open-source (draft (cxml:make-source path :entity-resolver #'null-resolver))
+  (klacks:with-open-source
+      (draft (cxml:make-source path :entity-resolver #'null-resolver))
     (with-open-file (stream output-path :direction :output
 			    :element-type '(unsigned-byte 8)
 			    :if-exists :supersede)
@@ -1068,25 +1160,30 @@ then this code will not be executed).&quot;
 					*post-linkname* *post-template*))
 	     (description-written-p nil))
 	(labels ((write-element (name)
-		   (funcall (cdr (assoc name *metadata-dispatch-table* :test #'string=))
-			    blog-post)))
+		   (funcall
+		    (cdr (assoc name *metadata-dispatch-table*
+				:test #'string=))
+		    blog-post)))
 	  (with-xml-fragment-output output
 	    (loop do
 		 (multiple-value-bind (key ns lname) (klacks:peek draft)
 		   (cond
 		     ((null key)
 		      (restart-case
-			  (error &quot;Error outputing updated post.  Please validate your editted post.&quot;)
+			  (error &quot;Error outputing updated post.
+Please validate your editted post.&quot;)
 			(return-from-output () (return nil))))
 		     ((and (eql key :start-element)
 			   (find lname elements-to-process :test #'string=))
-		      (setf elements-to-process (delete lname elements-to-process :test #'string=))
+		      (setf elements-to-process
+			    (delete lname elements-to-process :test #'string=))
 		      (write-element lname)
 		      (%suppress-current-element draft))
 		     ((start-post-element-p key ns lname *post-meta*)
 		      (let ((attribs (%capture-attributes draft)))
-			(if (string= *post-description*
-				     (cdr (assoc &quot;name&quot; attribs :test #'string=)))
+			(if (string=
+			     *post-description*
+			     (cdr (assoc &quot;name&quot; attribs :test #'string=)))
 			    (progn
 			      (write-post-description blog-post)
 			      (setf description-written-p t)
@@ -1106,7 +1203,8 @@ then this code will not be executed).&quot;
 
 ;;;# Site Generation
 (defun %generate-site ()
-  &quot;Generate all dirty content for the site.  Assumes an existing database connection.&quot;
+  &quot;Generate all dirty content for the site.  Assumes an existing database
+connection.&quot;
   (let (*recent-posts*)
     (%map-dirty-content #'generate)))
 
@@ -1121,7 +1219,7 @@ the templates).&quot;
     (list (url-for (index-page))
 	  (path-for (index-page)))))
 
-;;;## Output functions
+;;;## Output Macros
 
 ;;; Used to output the current element from the template, executing the macro's
 ;;; body before writing the end element tag
@@ -1141,7 +1239,8 @@ the templates).&quot;
 ;;; Ouput the template, executing body before closing the current element.  The
 ;;; content of the template element is expected to be a format template and is
 ;;; not output verbatim.
-(defmacro with-existing-element-as-format-template ((format-var template output) &amp;body body)
+(defmacro with-existing-element-as-format-template
+    ((format-var template output) &amp;body body)
   &quot;Execute BODY with the current element, assigning the inner content of the
 element to FORMAT-VAR.&quot;
   (let ((tp (gensym))
@@ -1161,23 +1260,12 @@ element to FORMAT-VAR.&quot;
        (klacks:serialize-event ,tp ,o))))
 
 
-(defun merge-assoc (a b &amp;key (test #'eql))
-  &quot;Merge association lists A and B, such that values from B take precedence.&quot;
-  (loop with result = (copy-seq a)
-     for kv in b
-     for assoc = (assoc (car kv) a :test test)
-     do
-       (if assoc
-	   (setf (cdr assoc) (cdr kv))
-	   (setf result (acons (car kv) (cdr kv) result)))
-     finally
-       (return result)))
-
 
 ;;; Ouput the template, executing body before closing the current element.  The
 ;;; content of the template element is expected to be a format template and is
 ;;; not output verbatim.
-(defmacro with-existing-element-setting-attributes ((content template output old-attributes new-attributes) &amp;body body)
+(defmacro with-existing-element-setting-attributes
+    ((content template output old-attributes new-attributes) &amp;body body)
   &quot;Execute BODY with the current element, ensuring that the specified
 NEW-ATTRIBUTES are merged with OLD-ATTRIBUTES and appear on the element.&quot;
   (let ((co (gensym))
@@ -1194,7 +1282,7 @@ NEW-ATTRIBUTES are merged with OLD-ATTRIBUTES and appear on the element.&quot;
 	   (,oa ,old-attributes)
 	   (,na ,new-attributes))
        (multiple-value-bind (,k ,ns ,d) (klacks:consume ,tp)
-	 (declare (ignore ,ns ,k))
+	 (declare (ignore ,ns))
 	 (assert (eql ,k :start-element))
 	 (cxml:with-element ,d
 	   (mapc #'(lambda (x) (cxml:attribute (car x) (cdr x)))
@@ -1205,11 +1293,37 @@ NEW-ATTRIBUTES are merged with OLD-ATTRIBUTES and appear on the element.&quot;
        (klacks:consume ,tp))))
 
 
+;;;## Output Functions
+
+
+;;;### Template Helper Functions
+
+;;; Create a template from the current element.  To be valid XML the template
+;;; needs to include a wrapping element, but this will not be output.
+(defun current-element-as-template (source)
+  &quot;Create an octect vector from the content of the current element&quot;
+  (let ((template-sink
+	 (cxml:make-octet-vector-sink :canonical nil :indentation
+				      nil :omit-xml-declaration-p t)))
+    (cxml:with-xml-output template-sink
+      (cxml:with-element &quot;div&quot;
+	(cxml:text &quot;&quot;) ; force output of div
+	(%copy-current-element-content source template-sink)
+	(sax:end-document template-sink)))))
 
+(defun output-content-using-template (content template output)
+  (klacks:with-open-source
+      (source (cxml:make-source template :entity-resolver #'null-resolver))
+    (loop for key =  (klacks:consume source)
+	 until (eql key :start-element)) ; consume the start element
+    (output-with-rewrite content source output)
+    (klacks:consume source))) ; consume the end element
 
+;;;### Post and Page Output Functions
 (defun output-post-content-no-template (blog-post output)
   (klacks:with-open-source
-      (source (cxml:make-source (published-file-path-for blog-post) :entity-resolver #'null-resolver))
+      (source (cxml:make-source (published-file-path-for blog-post)
+				:entity-resolver #'null-resolver))
     (klacks:find-element source *post-body*)
     (loop for key = (klacks:peek-next source)
        while key
@@ -1252,7 +1366,8 @@ NEW-ATTRIBUTES are merged with OLD-ATTRIBUTES and appear on the element.&quot;
 (defun output-post-when (blog-post template output attributes)
   (declare (ignore attributes))
   (with-existing-element (template output)
-    (cxml:text (format nil &quot;~{~A~^-~}&quot; (decode-date (content-when blog-post))))))
+    (cxml:text (format nil &quot;~{~A~^-~}&quot;
+		       (decode-date (content-when blog-post))))))
 
 (defun output-post-updated (blog-post template output attributes)
   (declare (ignore attributes))
@@ -1266,7 +1381,8 @@ NEW-ATTRIBUTES are merged with OLD-ATTRIBUTES and appear on the element.&quot;
 (defun write-post-synopsis (blog-post output)
   &quot;Output the synopsis&quot;
   (klacks:with-open-source
-      (source (cxml:make-source (content-synopsis blog-post) :entity-resolver #'null-resolver))
+      (source (cxml:make-source (content-synopsis blog-post)
+				:entity-resolver #'null-resolver))
     (%skip-preamble source)
     (output-with-rewrite blog-post source output)))
 
@@ -1275,15 +1391,6 @@ NEW-ATTRIBUTES are merged with OLD-ATTRIBUTES and appear on the element.&quot;
 (defparameter *index-collection* nil)
 
 
-;;; Table mapping element id's to the corresponding output function
-(defparameter *id-dispatch-table*
-  (list
-    (cons *post-content-id*  #'output-post-content)
-    (cons *post-title-id*  #'output-post-title)
-    (cons *post-when-id* #'output-post-when)
-    (cons *post-updated-id*  #'output-post-updated))
-  &quot;Map elements with specific id atributes to content.&quot;)
-
 
 (defun output-link-for (blog-post template output attributes)
   &quot;Output a link for the specified post or page specified in the href
@@ -1300,38 +1407,12 @@ attribute.&quot;
   (klacks:serialize-event template output)
   (cxml:with-element &quot;a&quot;
     (mapc #'(lambda (x)
-	      (cxml:attribute (car x) (cdr x))
-;; 	      (let* ((attrib (string-downcase (string (car x))))
-;; 		     (a1 (make-array (length attrib) :element-type 'character :initial-contents attrib)))
-;; 		(cxml:attribute a1 (cdr x)))
-	      )  ;; not sure why we have to copy this
+	      (cxml:attribute (car x) (cdr x)))
 	  attributes)
     (cxml:text &quot;&quot;)
     (%copy-current-element-content template output)
     (klacks:serialize-event template output)))
 
-;;; Create a template from the current element.  To be valid XML the template
-;;; needs to include a wrapping element, but this will not be output.
-(defun current-element-as-template (source)
-  &quot;Create an octect vector from the content of the current element&quot;
-  (let ((template-sink
-	 (cxml:make-octet-vector-sink :canonical nil :indentation
-				      nil :omit-xml-declaration-p t)))
-    (cxml:with-xml-output template-sink
-      (cxml:with-element &quot;div&quot;
-	(cxml:text &quot;&quot;) ; force output of div
-	(%copy-current-element-content source template-sink)
-	(sax:end-document template-sink)))))
-
-(defun output-content-using-template (content template output)
-  (klacks:with-open-source
-      (source (cxml:make-source template :entity-resolver #'null-resolver))
-    (loop for key =  (klacks:consume source)
-	 until (eql key :start-element)) ; consume the start element
-    (output-with-rewrite content source output)
-    (klacks:consume source))) ; consume the end element
-
-
 (defun output-post-tag (tag template output attributes)
   (declare (ignore attributes))
   (with-existing-element (template output)
@@ -1373,17 +1454,45 @@ attribute.&quot;
   (with-existing-element (template output)
     (write-post-synopsis blog-post output)))
 
+;;; If the current element is not a link, insert a link as content, else
+;;; set the href of the link.
 (defun output-post-link (blog-post template output attributes)
   &quot;Output a link to the specified BLOG-POST, using the post's title as link
   text.&quot;
-  (declare (ignore attributes))
-  (with-existing-element (template output)
-    (if *collection-route-path*
-	(link-for blog-post
-		  :url (enough-namestring
-			(site-file-path-for blog-post)
-			*collection-route-path*))
-	(link-for blog-post))))
+  (multiple-value-bind (key ns lname) (klacks:peek template)
+    (declare (ignore ns))
+    (assert (eql key :start-element))
+    (if (string= &quot;a&quot; lname)
+	(with-existing-element-setting-attributes
+	    (blog-post template output attributes
+		       (list (cons *href* (path-for blog-post)))))
+	(with-existing-element (template output)
+	  (if nil			;	*collection-route-path*
+	      (link-for blog-post
+			:url (enough-namestring
+			      (path-for blog-post)
+			      *collection-route-path*))
+	      (link-for blog-post))))))
+
+(defun output-delicious-link (blog-post template output attributes)
+  &quot;Modify an anchor element to point to delicious post.&quot;
+  (with-existing-element-setting-attributes
+      (blog-post
+       template output attributes
+       (list (cons *href*
+		   (format nil &quot;http://del.icio.us/post?url=~A&amp;title=~A&quot;
+			   (url-for blog-post)
+			   (content-title blog-post)))))))
+
+(defun output-digg-link (blog-post template output attributes)
+  &quot;Modify an anchor element to point to digg post.&quot;
+  (with-existing-element-setting-attributes
+      (blog-post
+       template output attributes
+       (list (cons *href*
+		   (format nil &quot;http://digg.com/submit?phase=2&amp;url=~A&amp;title=~A&quot;
+			   (url-for blog-post)
+			   (content-title blog-post)))))))
 
 (defun output-posts (content template output attributes)
   &quot;Output posts&quot;
@@ -1392,11 +1501,28 @@ attribute.&quot;
   (let ((post-template (current-element-as-template template)))
     (flet ((output-post (post)
 	     (output-content-using-template post post-template output)))
-      (let ((*collection-route-path* (site-file-path-for content)))
+      (let ((*collection-route-path* (path-for content)))
 	(mapc #'output-post *index-collection*))))
   (klacks:serialize-event template output)) ; end element
 
 
+(defun output-post-slug-value-attr (content template output attributes)
+  &quot;Output a value attribute containing the post slug&quot;
+  (if (assoc &quot;value&quot; attributes :test #'string=)
+      (setf (cdr (assoc &quot;value&quot; attributes :test #'string=))
+	    (content-filename content))
+      (setf attributes (acons &quot;value&quot; (content-filename content) attributes)))
+  (multiple-value-bind (key ns lname) (klacks:consume template)
+    (declare (ignore key ns))
+    (cxml:with-element lname
+      (mapc #'(lambda (x)
+		(cxml:attribute (car x) (cdr x)))
+	    attributes)
+      (%copy-current-element-content template output))
+    (klacks:consume template)))
+
+;;;### Comment Output Functions
+
 (defun split-fmt (fmt)
   (when fmt
     (setf fmt (string-trim '(#\Space #\Tab #\Newline #\Return)  fmt))
@@ -1487,27 +1613,42 @@ attribute.&quot;
 		(list (cons &quot;id&quot; (content-filename content))))))
 
 
-(defun output-post-slug-value-attr (content template output attributes)
-  &quot;Output a value attribute containing the post slug&quot;
-  (if (assoc &quot;value&quot; attributes :test #'string=)
-      (setf (cdr (assoc &quot;value&quot; attributes :test #'string=))
-	    (content-filename content))
-      (setf attributes (acons &quot;value&quot; (content-filename content) attributes)))
-  (multiple-value-bind (key ns lname) (klacks:consume template)
-    (declare (ignore key ns))
-    (cxml:with-element lname
-      (mapc #'(lambda (x)
-		(cxml:attribute (car x) (cdr x)))
-	    attributes)
-      (%copy-current-element-content template output))
-    (klacks:consume template)))
+;;;### Feed Output functions
+(defun output-feed-title (atom-feed template output attributes)
+  (declare (ignore attributes))
+  &quot;Output the feed title.&quot;
+  (with-existing-element (template output)
+    (cxml:text (atom-feed-title atom-feed))))
+
+(defun output-feed-uri (atom-feed template output attributes)
+  (declare (ignore attributes))
+  &quot;Output the feed uri.&quot;
+  (with-existing-element (template output)
+    (cxml:text (atom-feed-uri atom-feed))))
+
+(defun output-feed-updated (atom-feed template output attributes)
+  (declare (ignore atom-feed attributes))
+  &quot;Output the feed updated date.&quot;
+  (with-existing-element (template output)
+    (cxml:text (local-time:format-rfc3339-timestring nil (local-time:now)))))
+
+;;;### Template dispatch tables
+;;; Table mapping element id's to the corresponding output function
+(defparameter *id-dispatch-table*
+  (list
+    (cons *post-content-id*  #'output-post-content)
+    (cons *post-title-id*  #'output-post-title)
+    (cons *post-when-id* #'output-post-when)
+    (cons *post-updated-id*  #'output-post-updated))
+  &quot;Map elements with specific id atributes to content.&quot;)
 
+;;; This maps the template class-id's to corresponding output functions
 (defparameter *class-dispatch-table*
   (list
    (cons *post-posts-class*  #'output-posts)
    (cons *post-synopsis-class*  #'output-post-synopsis)
    (cons *post-link-class*  #'output-post-link)
-   (cons *page-link-for* #'output-link-for)
+   (cons *page-link-for-class* #'output-link-for)
    (cons *post-tags-class* #'output-tags-for)
    (cons *post-tag-class* #'output-post-tag)
    (cons *tag-name-class* #'output-tag-name)
@@ -1519,27 +1660,16 @@ attribute.&quot;
    (cons *comment-when-class* #'output-comment-when)
    (cons *comment-id-class* #'output-comment-id)
    (cons *comment-link-class* #'output-comment-link)
+   (cons *delicious-class* #'output-delicious-link)
+   (cons *digg-class* #'output-digg-link)
    (cons *post-slug-hidden-input-class* #'output-post-slug-value-attr))
   &quot;Map elements with specific class atributes to content.&quot;)
 
-
-(defun output-feed-title (atom-feed template output attributes)
-  (declare (ignore attributes))
-  &quot;Output the feed title.&quot;
-  (with-existing-element (template output)
-    (cxml:text (atom-feed-title atom-feed))))
-
-(defun output-feed-uri (atom-feed template output attributes)
-  (declare (ignore attributes))
-  &quot;Output the feed uri.&quot;
-  (with-existing-element (template output)
-    (cxml:text (atom-feed-uri atom-feed))))
-
-(defun output-feed-updated (atom-feed template output attributes)
-  (declare (ignore atom-feed attributes))
-  &quot;Output the feed updated date.&quot;
-  (with-existing-element (template output)
-    (cxml:text (local-time:format-rfc3339-timestring nil (local-time:now)))))
+(defparameter *element-dispatch-table*
+  (list
+   (cons *post-title* #'output-post-title)
+   (cons *post-link* #'output-post-meta-link))
+  &quot;Map specific elements to content.&quot;)
 
 (defparameter *feed-element-dispatch-table*
   (list
@@ -1548,12 +1678,9 @@ attribute.&quot;
    (cons *feed-updated* #'output-feed-updated))
   &quot;Map specific elements to content.&quot;)
 
-(defparameter *element-dispatch-table*
-  (list
-   (cons *post-title* #'output-post-title)
-   (cons *post-link* #'output-post-meta-link))
-  &quot;Map specific elements to content.&quot;)
 
+;;;### Template Engine
+;;; A helper macro.
 (defmacro with-each-word ((var string) &amp;body body)
   &quot;Split STRING into space seperated words.&quot;
   (let ((i (gensym))
@@ -1567,19 +1694,22 @@ attribute.&quot;
 	     ,@body)
 	while ,j)))
 
-;;; The template rewriting function
+;;; The main template rewriting function.
 (defun output-with-rewrite (templated-content source output)
   &quot;Outputs a SOURCE, rewriting content as required to the OUTPUT sink.  Writes
 only the current element.&quot;
   (labels ((dispatch (cmd attributes)
 	     (when cmd
-	       (funcall (cdr cmd) templated-content source output attributes)))
+	       (funcall (cdr cmd)
+			templated-content source output attributes)))
 	   (element-cmd (lname)
 	     (assoc lname *element-dispatch-table* :test #'string=))
 	   (id-cmd (attributes)
-	     (assoc (cdr (assoc &quot;id&quot; attributes :test #'string=)) *id-dispatch-table* :test #'string=))
+	     (assoc (cdr (assoc &quot;id&quot; attributes :test #'string=))
+		    *id-dispatch-table* :test #'string=))
 	   (class-cmd (attributes)
-	     (with-each-word (c (cdr (assoc &quot;class&quot; attributes :test #'string=)))
+	     (with-each-word
+		 (c (cdr (assoc &quot;class&quot; attributes :test #'string=)))
 	       (let ((cmd (assoc c *class-dispatch-table* :test #'string=)))
 		 (when cmd
 		   (return cmd))))))
@@ -1628,29 +1758,28 @@ only the current element.&quot;
   (generate-page index-page :collection *recent-posts*)
   (generate-page (content-feed index-page) :collection *recent-posts*))
 
-;; (defmethod generate ((atom-feed atom-feed))
-;;   (unless *recent-posts*
-;;     (setf *recent-posts* (%recent-posts)))
-;;   (generate-page atom-feed :collection *recent-posts*))
-
 (defmethod generate ((tag-page tag-page))
   (let ((tag-posts (%tag-posts (tag-page-tag tag-page))))
     (generate-page tag-page :collection tag-posts)
     (generate-page (content-feed tag-page) :collection tag-posts)))
 
 
-
-;;; Generates a page.
-(defmethod generate-page ((templated-content templated-content) &amp;key next prior &amp;allow-other-keys)
-  &quot;Generate the page for a templated-content.  Takes the template and merges the post into it.&quot;
+;;;### Templated Pages
+;;; Generates a BLOG-POST or a PAGE.
+(defmethod generate-page ((templated-content templated-content)
+			  &amp;key next prior &amp;allow-other-keys)
+  &quot;Generate the page for a templated-content.  Takes the template and merges the
+post into it.&quot;
   (format t &quot;Generating post '~A'~%&quot; (content-title templated-content))
   (flet ((output-post-head-title (template output)
 	   &quot;Assusmes current element is the template title&quot;
+	   ;; consume title tag and title text
 	   (loop for key = (klacks:peek template)
-		until (eql key :end-element)
-	      do (klacks:serialize-event template output)) ; consume title tag and title text
+	      until (eql key :end-element)
+	      do (klacks:serialize-event template output))
 	   (cxml:text (content-title templated-content))
-	   (klacks:serialize-event template output)) ; close the title tag
+	   ;; close the title tag
+	   (klacks:serialize-event template output))
 	 (output-post-link (post rel)
 	   &quot;Assusmes current element is in the document head&quot;
 	   (cxml:with-element &quot;link&quot;
@@ -1662,9 +1791,9 @@ only the current element.&quot;
 	   (when (content-description templated-content)
 	     (cxml:with-element &quot;meta&quot;
 	       (cxml:attribute &quot;name&quot; &quot;description&quot;)
-	       (cxml:attribute &quot;content&quot;
-			       (format nil &quot;~A&quot;
-				       (content-description templated-content))))))
+	       (cxml:attribute
+		&quot;content&quot;
+		(format nil &quot;~A&quot; (content-description templated-content))))))
 	 (output-post-tags ()
 	   &quot;Assusmes current element is in the document head&quot;
 	   (when (content-tags templated-content)
@@ -1675,13 +1804,17 @@ only the current element.&quot;
 				       (content-tags templated-content)))))))
     (let ((output-path (site-file-path-for templated-content)))
       (klacks:with-open-source
-	  (template (cxml:make-source (%template-path (content-template templated-content))
-				      :entity-resolver #'null-resolver))
+	  (template
+	   (cxml:make-source
+	    (%template-path (content-template templated-content))
+	    :entity-resolver #'null-resolver))
 	(with-open-file (stream output-path :direction :output
 				:element-type '(unsigned-byte 8)
 				:if-exists :supersede
 				:if-does-not-exist :create)
-	  (let ((output (cxml:make-octet-stream-sink stream :canonical nil :omit-xml-declaration-p nil)))
+	  (let ((output
+		 (cxml:make-octet-stream-sink
+		  stream :canonical nil :omit-xml-declaration-p nil)))
 	    (with-xml-fragment-output output
 	      (%copy-to-next-start-element template output *post-title*)
 	      (output-post-head-title template output)
@@ -1699,13 +1832,15 @@ only the current element.&quot;
 
 
 
+;;;### Index Page
 ;;; Generates the index page using a list of recent posts, and listing
 ;;; links to them with a synopsis of each (the first paragraph, anyway).
 (defmethod generate-page ((index-page index-page) &amp;key collection)
   &quot;Generate the index page for the blog.&quot;
   (format t &quot;Generating index page~%&quot;)
-  (klacks:with-open-source (template (cxml:make-source (%template-path &quot;index&quot;)
-						       :entity-resolver #'null-resolver))
+  (klacks:with-open-source
+      (template (cxml:make-source (%template-path &quot;index&quot;)
+				  :entity-resolver #'null-resolver))
     (with-open-file
 	(stream (site-file-path-for index-page) :direction :output
 		:element-type '(unsigned-byte 8) :if-exists :supersede)
@@ -1720,21 +1855,21 @@ only the current element.&quot;
 	    (output-with-rewrite index-page template output))))))
   (setf (dirty index-page) nil))
 
+;;;### Tag Pages
 ;;; Generates a tag page using a list of posts, and listing
 ;;; links to them with a synopsis of each (the first paragraph, anyway).
 (defmethod generate-page ((tag-page tag-page) &amp;key collection)
   &quot;Generate the index page for the blog.&quot;
   (format t &quot;Generating tag page ~A~%&quot; (tag-page-tag tag-page))
-  (klacks:with-open-source (template (cxml:make-source (%template-path &quot;tag&quot;)
-						       :entity-resolver #'null-resolver))
+  (klacks:with-open-source
+      (template (cxml:make-source (%template-path &quot;tag&quot;)
+				  :entity-resolver #'null-resolver))
     (with-open-file
 	(stream (site-file-path-for tag-page) :direction :output
 		:element-type '(unsigned-byte 8) :if-exists :supersede)
       (let* ((output (cxml:make-octet-stream-sink
 		      stream :canonical nil :omit-xml-declaration-p nil)))
 	(with-xml-fragment-output output
-;; TODO
-;;   links to connected tags
 	  (let ((*index-collection* collection))
 	    (loop for key = (klacks:peek template)
 	       while key
@@ -1744,6 +1879,7 @@ only the current element.&quot;
   (setf (dirty tag-page) nil))
 
 
+;;;### Atom Feeds
 (defun output-post-atom-entry (blog-post output)
   &quot;Output an atom entry for the post.&quot;
   (cxml:with-element &quot;entry&quot;
@@ -1791,32 +1927,26 @@ only the current element.&quot;
 (defmethod generate-page ((atom-feed atom-feed) &amp;key collection)
   &quot;Generate the atom feed for the blog.&quot;
   (format t &quot;Generating Atom feed~%&quot;)
-  (klacks:with-open-source (template (cxml:make-source (%template-path &quot;atom&quot;)
-						       :entity-resolver #'null-resolver))
+  (klacks:with-open-source
+      (template (cxml:make-source (%template-path &quot;atom&quot;)
+				  :entity-resolver #'null-resolver))
     (with-open-file
 	(stream (site-file-path-for atom-feed) :direction :output
 		:element-type '(unsigned-byte 8) :if-exists :supersede)
-      (let* ((output (cxml:make-octet-stream-sink stream :canonical nil
-						  :indentation nil
-						  :omit-xml-declaration-p nil)))
+      (let* ((output (cxml:make-octet-stream-sink
+		      stream :canonical nil :indentation nil
+		      :omit-xml-declaration-p nil)))
 	(with-xml-fragment-output output
 	  (%copy-to-next-start-element template output &quot;feed&quot;)
 	  (klacks:serialize-event template output)
 	  (let ((*element-dispatch-table* *feed-element-dispatch-table*))
 	    (output-with-rewrite atom-feed template output))
-
-;; 	  (%copy-to-next-start-element template output &quot;updated&quot;)
-;; 	  (klacks:serialize-event template output)
-;; 	  (cxml:text (local-time:format-rfc3339-timestring nil (local-time:now)))
-;; 	  (klacks:serialize-event template output)
 	  (loop for blog-post in collection
 	     do (output-post-atom-entry blog-post output))
-	  (klacks:serialize-source template output)))))
-  ;; (setf (dirty atom-feed) nil)
-  )
-
+	  (klacks:serialize-source template output))))))
 
-;;; Defaults for configuration
+;;;# Default configuration
+;;; Defaults for configurable paths and id's
 (eval-when (:load-toplevel :execute)
   (setf *blog-post-relative-path-fn* #'relative-path-for)
   (setf *page-relative-path-fn* #'relative-path-for)</diff>
      <filename>src/post.lisp</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>1c6f249de3b689124e4aa4757a79b834ec2c01f5</id>
    </parent>
  </parents>
  <author>
    <name>Hugo Duncan</name>
    <email>hugo_duncan@yahoo.com</email>
  </author>
  <url>http://github.com/hugoduncan/cl-blog-generator/commit/0bdb31ed4a4c8e349c2b39a1427df7f1f467505f</url>
  <id>0bdb31ed4a4c8e349c2b39a1427df7f1f467505f</id>
  <committed-date>2009-04-01T06:51:11-07:00</committed-date>
  <authored-date>2009-04-01T06:51:11-07:00</authored-date>
  <message>added tags for digg and delicious links.  code cleanup.</message>
  <tree>57eb43774b329c8c23e39e27e5312af7f828048b</tree>
  <committer>
    <name>Hugo Duncan</name>
    <email>hugo_duncan@yahoo.com</email>
  </committer>
</commit>
