Implement indices in a really nasty, "just get it done" sort of way, tweak API + update TODO.
This commit is contained in:
parent
bbe06ffe4d
commit
1d01f91c2b
7 changed files with 113 additions and 34 deletions
9
TODO
9
TODO
|
@ -12,16 +12,23 @@ Ideas:
|
|||
;;;; DYNAMIC
|
||||
|
||||
;;;; STATIC
|
||||
;;;; implement render-site, head-inject/body-inject/navigation.
|
||||
;;;; implement head-inject/body-inject/navigation!
|
||||
;;;; implement start-coleslaw, stop-coleslaw!
|
||||
;;;; non-disqus comment support?
|
||||
;;; indexes
|
||||
;; what should it really look like, keeping in mind the API should be mostly
|
||||
;; identical between the static and dynamic backend?
|
||||
;;; posts
|
||||
;; Make find-by-date, post-url not suck.
|
||||
;; -- re: find-by-date, aside from the subseq+string= grossness, the posts it
|
||||
;; -- returns are not in reverse chronological order. Fix it!
|
||||
;; -- re: post-url, escaping is insufficient and there are collisions by title.
|
||||
;; -- What are alternatives?
|
||||
|
||||
;;;; PLUGINS
|
||||
;;;; implement disqus support
|
||||
;;; import
|
||||
;; add output to HTML files when static-p is true
|
||||
;; add comment handling ... (when comments ...)
|
||||
;; support old URLs via use of post-aliases?
|
||||
|
||||
|
|
|
@ -6,8 +6,11 @@
|
|||
(defgeneric remove-index (id)
|
||||
(:documentation "Remove the index matching ID from *storage*."))
|
||||
|
||||
(defgeneric render-index (index)
|
||||
(:documentation "Generate the final HTML for INDEX."))
|
||||
(defgeneric render-index (id page)
|
||||
(:documentation "Generate the final HTML for the index with given ID."))
|
||||
|
||||
(defgeneric find-index (id)
|
||||
(:documentation "Retrieve the index matching ID from *storage*."))
|
||||
|
||||
(defgeneric index-url (id page)
|
||||
(:documentation "Return the URL for the PAGE of index with given ID."))
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
(aliases :initform nil :initarg :aliases
|
||||
:accessor post-aliases)))
|
||||
|
||||
(defgeneric make-post (title tags date content &key id &allow-other-keys)
|
||||
(defgeneric make-post (title tags date content
|
||||
&key id aliases &allow-other-keys)
|
||||
(:documentation "Create a POST with the given data."))
|
||||
|
||||
(defgeneric add-post (post id)
|
||||
|
@ -24,7 +25,7 @@
|
|||
(:documentation "Remove a post from *storage* matching ID."))
|
||||
|
||||
(defgeneric render-post (id)
|
||||
(:documentation "Generate the final HTML for post."))
|
||||
(:documentation "Generate the final HTML for the post with given ID."))
|
||||
|
||||
(defgeneric find-post (id)
|
||||
(:documentation "Retrieve a post from *storage* matching ID."))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
(defvar *site-root* nil
|
||||
"A string representing the base URL of the site,
|
||||
e.g. \"http://blog.redlinernotes.com/\".")
|
||||
e.g. \"http://blog.redlinernotes.com\".")
|
||||
|
||||
(defvar *site-title* nil
|
||||
"A string containing the title of the site,
|
||||
|
@ -39,3 +39,15 @@ e.g. \"CC-BY-SA\". Otherwise, standard copyright is assumed.")
|
|||
|
||||
(defmethod set-credentials (name credentials)
|
||||
(setf (gethash name (gethash :credentials *storage*)) credentials))
|
||||
|
||||
(defmethod render-page (content)
|
||||
(let ((result (funcall (find-symbol "BASE" (theme-package))
|
||||
(list :title *site-title*
|
||||
:siteroot *site-root*
|
||||
:head-inject nil
|
||||
:navigation nil
|
||||
:content content
|
||||
:body-inject nil
|
||||
:license *site-license*
|
||||
:credits *site-credits*))))
|
||||
result))
|
||||
|
|
|
@ -1,13 +1,61 @@
|
|||
(in-package :coleslaw)
|
||||
|
||||
(defmethod find-index (id)
|
||||
(gethash id (gethash :indices *storage*)))
|
||||
(defun monthlinks ()
|
||||
(loop for month in (gethash :months-index *storage*)
|
||||
collect (cons (index-url :date month) month) into months
|
||||
finally (return
|
||||
(pretty-list (mapcar (lambda (consp)
|
||||
(format nil "<a href=\"~a\">~a</a>"
|
||||
(car consp) (cdr consp)))
|
||||
months)))))
|
||||
|
||||
(defmethod add-index (index id)
|
||||
(setf (find-index id) index))
|
||||
(defun taglinks ()
|
||||
(loop for tag in (gethash :tags-index *storage*)
|
||||
collect (cons (index-url :tag tag) tag) into tags
|
||||
finally (return
|
||||
(pretty-list (mapcar (lambda (consp)
|
||||
(format nil "<a href=\"~a\">~a</a>"
|
||||
(car consp) (cdr consp)))
|
||||
tags)))))
|
||||
|
||||
(defmethod remove-index (id)
|
||||
(setf (find-index id) nil))
|
||||
(defun index-title (id &optional page)
|
||||
(case id
|
||||
(:range "Recent Posts")
|
||||
(:date (format nil "Posts from ~A" page))
|
||||
(:tag (format nil "Posts tagged ~A" page))))
|
||||
|
||||
(defmethod render-index (index)
|
||||
)
|
||||
(defun index-posts (id page)
|
||||
(case id
|
||||
(:range (let* ((count (hash-table-count (gethash :posts *storage*)))
|
||||
(start (- count (* 10 (1- page))))
|
||||
(end (- start 9)))
|
||||
(remove nil (find-by-range start end))))
|
||||
(:date (find-by-date page))
|
||||
(:tag (find-by-tag page))))
|
||||
|
||||
(defmethod render-index (id page)
|
||||
(let* ((posts (index-posts id page))
|
||||
(content (funcall (find-symbol "INDEX" (theme-package))
|
||||
(list :taglinks (taglinks)
|
||||
:monthlinks (monthlinks)
|
||||
:title (index-title id page)
|
||||
:posts (loop for post in posts collect
|
||||
(list :url (post-url (post-id post))
|
||||
:title (post-title post)
|
||||
:date (pretty-date (post-date post))
|
||||
:contents (post-content post)))
|
||||
:prev (when (and (numberp id)
|
||||
(index-posts id (1- page)))
|
||||
(index-url id (1- page)))
|
||||
:next (when (and (numberp id)
|
||||
(index-posts id (1+ page)))
|
||||
(index-url id (1+ page)))))))
|
||||
content))
|
||||
|
||||
(defmethod index-url (id page)
|
||||
(flet ((keyword-name (keyword)
|
||||
(format nil "~A" keyword)))
|
||||
(if (member id '(:date :tag))
|
||||
(concatenate 'string *site-root* "/"
|
||||
(string-downcase (keyword-name id)) "/" page)
|
||||
(concatenate 'string *site-root* "/page/" (write-to-string page)))))
|
||||
|
|
|
@ -11,20 +11,18 @@
|
|||
(defmethod add-post ((post post) id)
|
||||
(setf (gethash id (gethash :posts *storage*)) post)
|
||||
(loop for tag in (post-tags post)
|
||||
do (pushnew tag (gethash :tags-index *storage*) :test #'string=)))
|
||||
do (pushnew tag (gethash :tags-index *storage*) :test #'string=))
|
||||
(let ((date (post-date post))
|
||||
(month (format nil "~4d-~2,'0d" (local-time:timestamp-year date)
|
||||
(local-time:timestamp-month date))))
|
||||
(pushnew month (gethash :months-index *storage*) :test #'string=)))
|
||||
|
||||
(defmethod remove-post (id)
|
||||
(setf (gethash id (gethash :posts *storage*)) nil))
|
||||
|
||||
(defmethod render-post (id)
|
||||
(flet ((fn (name)
|
||||
(find-symbol name (theme-package)))
|
||||
(pretty-date (date)
|
||||
(subseq (local-time:format-rfc1123-timestring nil date) 0 16))
|
||||
(pretty-tags (tags)
|
||||
(format nil "~{~A~^, ~}" tags)))
|
||||
(let* ((post (find-post id))
|
||||
(result (funcall (fn "POST")
|
||||
(result (funcall (theme-fn "POST")
|
||||
(list :title (post-title post)
|
||||
:tags (pretty-tags (post-tags post))
|
||||
:date (pretty-date (post-date post))
|
||||
|
@ -33,7 +31,7 @@
|
|||
(post-url (1- id)))
|
||||
:next (when (find-post (1+ id))
|
||||
(post-url (1+ id)))))))
|
||||
result)))
|
||||
result))
|
||||
|
||||
(defmethod find-post (id)
|
||||
(gethash id (gethash :posts *storage*)))
|
||||
|
@ -41,7 +39,7 @@
|
|||
(defmethod find-by-tag (tag)
|
||||
(let ((results nil))
|
||||
(loop for post being the hash-values in (gethash :posts *storage*)
|
||||
do (when (search tag (post-tags post))
|
||||
do (when (member tag (post-tags post) :test #'string=)
|
||||
(push post results)))
|
||||
results))
|
||||
|
||||
|
@ -64,4 +62,4 @@
|
|||
(defmethod post-url (id)
|
||||
(flet ((escape (str)
|
||||
(substitute #\- #\Space str)))
|
||||
(concatenate 'string *site-root* (escape (post-title (find-post id))))))
|
||||
(concatenate 'string *site-root* "/" (escape (post-title (find-post id))))))
|
||||
|
|
10
static/util.lisp
Normal file
10
static/util.lisp
Normal file
|
@ -0,0 +1,10 @@
|
|||
(in-package :coleslaw)
|
||||
|
||||
(defun pretty-date (date)
|
||||
(subseq (local-time:format-rfc1123-timestring nil date) 0 16))
|
||||
|
||||
(defun pretty-list (list)
|
||||
(format nil "~{~A~^, ~}" list))
|
||||
|
||||
(defun theme-fn (name)
|
||||
(find-symbol name (theme-package)))
|
Loading…
Add table
Reference in a new issue