2011-04-16 15:45:37 -04:00
|
|
|
(in-package :coleslaw)
|
|
|
|
|
2012-09-12 11:00:21 -04:00
|
|
|
(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)))
|
|
|
|
|
2012-08-20 17:26:12 -04:00
|
|
|
(defun all-months ()
|
|
|
|
"Retrieve a list of all months with published posts."
|
2012-09-12 11:00:21 -04:00
|
|
|
(sort (remove-duplicates (mapcar (lambda (x) (get-month (post-date x)))
|
|
|
|
(hash-table-values *posts*)) :test #'string=)
|
|
|
|
#'string>))
|
2012-08-20 17:26:12 -04:00
|
|
|
|
|
|
|
(defun all-tags ()
|
|
|
|
"Retrieve a list of all tags used in posts."
|
2012-09-12 11:00:21 -04:00
|
|
|
(sort (reduce (lambda (x y) (union x y :test #'string=))
|
|
|
|
(mapcar #'post-tags (hash-table-values *posts*)))
|
|
|
|
#'string<))
|
2011-04-22 17:16:42 -04:00
|
|
|
|
2012-08-21 20:10:41 -04:00
|
|
|
(defun get-month (timestamp)
|
|
|
|
"Extract the YYYY-MM portion of TIMESTAMP."
|
|
|
|
(subseq timestamp 0 7))
|
|
|
|
|
|
|
|
(defun by-date (posts)
|
|
|
|
"Sort POSTS in reverse chronological order."
|
|
|
|
(sort posts #'string> :key #'post-date))
|
|
|
|
|
2012-09-12 13:37:55 -04:00
|
|
|
(defun index-by-tag (tag posts)
|
|
|
|
"Return an index of all POSTS matching the given TAG."
|
|
|
|
(let ((content (remove-if-not (lambda (post) (member tag (post-tags post)
|
2012-09-12 11:00:21 -04:00
|
|
|
:test #'string=)) posts)))
|
2012-09-12 13:37:55 -04:00
|
|
|
(make-instance 'index :path (format nil "tag/~a.html" tag)
|
|
|
|
:posts (by-date content)
|
|
|
|
:title "Posts tagged ~a" tag)))
|
2011-04-16 15:45:37 -04:00
|
|
|
|
2012-09-12 13:37:55 -04:00
|
|
|
(defun index-by-month (month posts)
|
|
|
|
"Return an index of all POSTS matching the given MONTH."
|
|
|
|
(let ((content (remove-if-not (lambda (post) (search month (post-date post)))
|
|
|
|
posts)))
|
|
|
|
(make-instance 'index :path (format nil "date/~a.html" month)
|
|
|
|
:posts (by-date content)
|
|
|
|
:title (format nil "Posts from ~a" month))))
|
|
|
|
|
|
|
|
(defun index-by-n (i posts &optional (step 10))
|
|
|
|
"Return the index for the Ith page of POSTS in reverse chronological order."
|
|
|
|
(make-instance 'index :path (format nil "~d.html" i)
|
|
|
|
:posts (let ((index (* step (1- i))))
|
|
|
|
(subseq posts index (min (length posts)
|
|
|
|
(+ index step))))
|
|
|
|
:title "Recent Posts"))
|
2011-04-19 00:34:17 -04:00
|
|
|
|
2012-08-20 11:53:39 -04:00
|
|
|
(defun render-indices ()
|
2012-08-27 15:02:10 -04:00
|
|
|
"Render the indices to view posts in groups of size N, by month, and by tag."
|
2012-09-12 11:00:21 -04:00
|
|
|
(let ((posts (hash-table-values *posts*)))
|
2012-09-12 13:37:55 -04:00
|
|
|
(dolist (tag (all-tags))
|
|
|
|
(render-page (index-by-tag tag posts)))
|
|
|
|
(dolist (month (all-months))
|
|
|
|
(render-page (index-by-month month posts)))
|
|
|
|
(dolist (i (ceiling (length posts) 10))
|
|
|
|
(render-page (index-by-n i (by-date posts)) nil
|
|
|
|
:prev (and (plusp (1- i)) (1- i))
|
|
|
|
:next (and (< (* i 10) (length posts)) (1+ i)))))
|
|
|
|
(update-symlink "index.html" "1.html"))
|