(in-package :beesknees.pages) (defparameter *markdown-output-cache* (make-hash-table :test #'equalp ;; may need to just do locking manually for ;; portability... OTOH as long as an implementation ;; gurantees that concurrent writers won't corrupt ;; the hash table it doesn't particularly matter #+sbcl :synchronized #+sbcl t)) (defun find-cached-markdown-output (markdown-hash) (gethash markdown-hash *markdown-output-cache*)) (defun cache-markdown-output! (markdown-hash markdown-text) (setf (gethash markdown-hash *markdown-output-cache*) (multiple-value-bind (doc string) (markdown:markdown markdown-text :stream nil :format :html) (declare (ignore doc)) string))) (defextension (image :arguments ((name :required) alt (float :keyword)) :insertp t) (ecase phase (:parse nil) (:render (yaclml:with-yaclml-output-to-string ;; fixme: use url-prefix (<:img :src (format nil "/static/img/uploaded/~A" name) :alt (or alt "image") :style (case float ((:left) "float: left;") ((:right) "float: right"))))))) (pushnew 'cl-markdown-user:image *render-active-functions*) (defpclass bee-page (cacheable-persistent-object) ((name :accessor page-name :initarg :name :index t) (content :accessor page-content :initarg :content))) (defmethod initialize-instance :after ((page bee-page) &key (content nil content-supplied-p) &allow-other-keys) (when content-supplied-p (setf (page-content page) content))) (defmethod (setf page-content) :after (content (page bee-page)) (setf (golgonooza-db:object-hash page) (md5:md5sum-sequence content))) (defun page->html (bee-page) (ensure-transaction () (or (find-cached-markdown-output (golgonooza-db:object-hash bee-page)) (cache-markdown-output! (golgonooza-db:object-hash bee-page) (page-content bee-page)))))