coleslaw/src/documents.lisp

65 lines
2.2 KiB
Common Lisp
Raw Normal View History

2014-04-15 11:28:41 -04:00
(in-package :coleslaw)
;;;; The Document Protocol
;; Data Storage
(defvar *site* (make-hash-table :test #'equal)
"An in-memory database to hold all site documents, keyed on page-url.")
2014-04-15 15:27:46 -04:00
(defun add-document (doc)
2014-04-15 19:25:19 -04:00
"Add DOC to the in-memory database. Error if a matching entry is present."
2014-04-15 15:27:46 -04:00
(let ((url (page-url doc)))
(if (gethash url *site*)
(error "There is already an existing document with the url ~a" url)
(setf (gethash url *site*) doc))))
2014-04-15 11:28:41 -04:00
;; Class Methods
(defun find-all (doc-type)
"Return a list of all instances of a given DOC-TYPE."
(loop for val being the hash-values in *site*
when (typep val doc-type) collect val))
(defun purge-all (doc-type)
"Remove all instances of DOC-TYPE from memory."
(dolist (obj (find-all doc-type))
(remhash (page-url obj) *site*)))
(defgeneric publish (doc-type)
(:documentation "Write pages to disk for all documents of the given DOC-TYPE."))
(defgeneric discover (doc-type)
(:documentation "Load all documents of the given DOC-TYPE into memory.")
(:method (doc-type)
(let* ((class-name (class-name doc-type))
(file-type (string-downcase (symbol-name class-name))))
(do-files (file (repo *config*) file-type)
(let ((obj (construct class-name (read-content file))))
2014-04-15 15:27:46 -04:00
(add-document obj))))))
2014-04-15 11:28:41 -04:00
(defmethod discover :before (doc-type)
(purge-all (class-name doc-type)))
2014-04-15 11:28:41 -04:00
;; Instance Methods
(defgeneric page-url (document)
(:documentation "The url to the DOCUMENT without the domain."))
2014-04-15 11:28:41 -04:00
(defmethod page-url :around ((document t))
(let ((result (call-next-method)))
(if (pathname-type result)
result
(make-pathname :type "html" :defaults result))))
(defgeneric render (document &key &allow-other-keys)
(:documentation "Render the given DOCUMENT to HTML."))
(defun write-document (document &optional theme-fn &rest render-args)
"Write the given DOCUMENT to disk as HTML. If THEME-FN is present,
use it as the template passing any RENDER-ARGS."
2014-04-28 14:09:27 -04:00
(let ((html (if (or theme-fn render-args)
(apply #'render-page document theme-fn render-args)
(render-page document nil))))
(write-file (page-path obj) html)))