INDEX rendering cleanup.

This commit is contained in:
Brit Butler 2012-09-12 11:00:21 -04:00
parent 939c0be318
commit f1ea9e89ae
2 changed files with 62 additions and 75 deletions

View file

@ -1,24 +1,31 @@
(in-package :coleslaw)
(defclass index ()
((path :initform nil :initarg :path :accessor index-path)
(posts :initform nil :initarg :posts :accessor index-posts)
(title :initform nil :initarg :title :accessor index-title)))
(defmethod render ((content index) &key prev next)
(funcall (theme-fn 'index)
(list :tags (all-tags)
:months (all-months)
:config *config*
:title (index-title index)
:posts (index-posts index)
:prev prev
:next next)))
(defun all-months ()
"Retrieve a list of all months with published posts."
(remove-duplicates (mapcar (lambda (x) (get-month (post-date x)))
(hash-table-values *posts*)) :test #'string=))
(sort (remove-duplicates (mapcar (lambda (x) (get-month (post-date x)))
(hash-table-values *posts*)) :test #'string=)
#'string>))
(defun all-tags ()
"Retrieve a list of all tags used in posts."
(reduce (lambda (x y) (union x y :test #'string=))
(mapcar #'post-tags (hash-table-values *posts*))))
(defun taglinks (&optional (tags (all-tags)))
"Generate links to all the tag indices or those in TAGS."
(loop for tag in (sort tags #'string<)
collect (list :url (format nil "tag/~a.html" tag) :name tag)))
(defun monthlinks (&optional (months (all-months)))
"Generate links to all the month indices."
(loop for month in (sort months #'string<)
collect (list :url (format nil "date/~a.html" month) :name month)))
(sort (reduce (lambda (x y) (union x y :test #'string=))
(mapcar #'post-tags (hash-table-values *posts*)))
#'string<))
(defun get-month (timestamp)
"Extract the YYYY-MM portion of TIMESTAMP."
@ -28,61 +35,41 @@
"Sort POSTS in reverse chronological order."
(sort posts #'string> :key #'post-date))
(defun write-index (posts filename title &key prev next (relative t))
"Write out the HTML for POSTS to FILENAME.html."
(let ((content (loop for post in posts
collect (list :url (if relative
(format nil "../posts/~a" (post-url post))
(format nil "~a/posts/~a"
(domain *config*) (post-url post)))
:title (post-title post)
:date (post-date post)
:content (render-content (post-content post)
(post-format post))))))
(render-page filename
(funcall (theme-fn 'index)
(list :taglinks (taglinks)
:monthlinks (monthlinks)
:siteroot (domain *config*)
:title title
:posts content
:prev (and prev (format nil "~d.html" prev))
:next (and next (format nil "~d.html" next)))))))
(defun render-by-n (&optional n)
"Render the indices to view posts in reverse chronological order by N."
(defun render-by-n (posts &optional n)
"Render the indices to view POSTS in reverse chronological order by N."
(flet ((by-n (posts start)
(let ((index (* n (1- start))))
(subseq posts index (min (length posts) (+ index n))))))
(let ((posts (by-date (hash-table-values *posts*))))
(loop for i = 1 then (1+ i)
do (write-index (by-n posts i) (format nil "~d.html" i) "Recent Posts"
:prev (and (plusp (1- i)) (1- i))
:next (and (< (* i n) (length posts)) (1+ i))
:relative nil)
until (> (* i n) (length posts)))
(update-symlink "index.html" "1.html"))))
(loop for i = 1 then (1+ i)
do (render-page (make-instance 'index :path (format nil "~d.html" i)
:posts (by-n posts i)
:title "Recent Posts")
nil
:prev (and (plusp (1- i)) (1- i))
:next (and (< (* i n) (length posts)) (1+ i)))
until (> (* i n) (length posts))))
(update-symlink "index.html" "1.html"))
(defun render-by-tag (tags)
"Render the indices to view posts by tag for each tag in TAGS."
(defun render-by-tag (posts tags)
"Render the indices to view POSTS by tag for each tag in TAGS."
(dolist (tag tags)
(let ((posts (remove-if-not (lambda (post) (member tag (post-tags post) :test #'string=))
(hash-table-values *posts*))))
(write-index (by-date posts)
(format nil "tag/~a.html" tag)
(format nil "Posts tagged ~a" tag)))))
(let ((posts (remove-if-not (lambda (post) (member tag (post-tags post)
:test #'string=)) posts)))
(render-page (make-instance 'index :path (format nil "tag/~a.html" tag)
:posts (by-date posts)
:title (format nil "Posts tagged ~a" tag))))))
(defun render-by-month (months)
"Render the indices to view posts by month for each month in MONTHS."
(defun render-by-month (posts months)
"Render the indices to view POSTS by month for each month in MONTHS."
(dolist (month months)
(let ((posts (remove-if-not (lambda (post) (search month (post-date post)))
(hash-table-values *posts*))))
(write-index (by-date posts)
(format nil "date/~a.html" month)
(format nil "Posts from ~a" month)))))
(let ((posts (remove-if-not (lambda (post) (search month (post-date post))) posts)))
(render-page (make-instance 'index :path (format nil "date/~a.html" month)
:posts (by-date posts)
:title (format nil "Posts from ~a" month))))))
(defun render-indices ()
"Render the indices to view posts in groups of size N, by month, and by tag."
(render-by-n 10)
(render-by-tag (all-tags))
(render-by-month (all-months)))
(let ((posts (hash-table-values *posts*)))
(render-by-n (by-date posts) 10)
(render-by-tag posts (all-tags))
(render-by-month posts (all-months))))

View file

@ -1,33 +1,33 @@
{namespace coleslaw.theme.hyde}
{template index}
<h1 class="title">{$title}</h1>
{foreach $post in $posts}
<h1 class="title">{$index.title}</h1>
{foreach $post in $index.posts}
<div class="article-meta">
<a class="article-title" href="{$post.url}">{$post.title}</a>
<a class="article-title" href="{$config.domain}/posts/{$post.slug}.html">{$post.title}</a>
<div class="date"> posted on {$post.date}</div>
<div class="article">{$post.content |noAutoescape}</div>
</div>
{/foreach}
<div id="relative-nav">
{if $prev} <a href="{$prev}">Previous</a> {/if}
{if $next} <a href="{$next}">Next</a> {/if}
{if $prev} <a href="{$prev}.html">Previous</a> {/if}
{if $next} <a href="{$next}.html">Next</a> {/if}
</div>
{if $taglinks}
{if $tags}
<div id="tagsoup">
<p>This blog covers
{foreach $taglink in $taglinks}
<a href="{$siteroot}/{$taglink.url |noAutoescape}">{$taglink.name}</a>
{if not isLast($taglink)}, {/if}
{foreach $tag in $tags}
<a href="{$config.domain}/tag/{$tag}.html">{$tag}</a>
{if not isLast($tag)}, {/if}
{/foreach}
</div>
{/if}
{if $monthlinks}
{if $months}
<div id="monthsoup">
<p>View posts from
{foreach $monthlink in $monthlinks}
<a href="{$siteroot}/{$monthlink.url |noAutoescape}">{$monthlink.name}</a>
{if not isLast($monthlink)}, {/if}
{foreach $month in $months}
<a href="{$config.domain}/date/{$month}.html">{$month}</a>
{if not isLast($month)}, {/if}
{/foreach}
</div>
{/if}