Restructuring and API rewrite.

This commit is contained in:
Brit Butler 2011-04-16 15:45:37 -04:00
parent 052e430ed4
commit c75ba4bc50
20 changed files with 213 additions and 127 deletions

13
README
View file

@ -1 +1,12 @@
Coleslaw aims to be flexible blog software suitable for replacing a single-user wordpress install or jekyll. The primary difference is that the coleslaw-dynamic backend uses PostgreSQL and RESTAS to generate and serve the site while the coleslaw-static backend compiles a static site to be served by Amazon S3.
Coleslaw aims to be flexible blog software suitable for replacing a single-user wordpress install or jekyll.
There will be at least two backends: a dynamic one using RESTAS and PostgreSQL and a static one served by Hunchentoot or, optionally, S3.
References:
Static Backend
-- Jekyll
-- Hakyll
-- Hyde
Dynamic Backend
-- Wordpress
-- Nuclblog

22
TODO
View file

@ -1 +1,23 @@
Everything.
Ideas:
-- Replace cl-markdown with 3bmd down the line?
-- Use cl-inotify or similar for notifications instead of timers?
-- plugins -> lastfm widget, analytics, rss/atom, disqus, akismet, etc.
;; TODO:
;; consider add-to-index/setf-index, create-index, create-post.
;; then ensure the indices API is okay and GET GOING.
;;;; rendering hooks (eg. :pygmentize, :xpost-lj?)
;; may need pre- and post- but for now stick to post-.
;; get run on rendered html before "storage"
;; xposting may be a rendering hook but may necessitate publishing hooks
;; again, these should be methods on a generic function
;;;; template hooks *ARE* pre-rendering-hooks. or methods on GFs.
;;;; they're methods on GFs you fool! work on the classes/constructors for post+indices
;;;; that's the only thing that makes sense. (eg 'disqus, 'mathjax)
;; run before the template is called to generate html or javascript includes
;; for a given template property (eg. comments, includes). they should probably be
;; methods on a generic function (eg. blog-comments, blog-includes)

View file

@ -1,12 +0,0 @@
(defsystem :coleslaw-dynamic
:name "coleslaw-dynamic"
:description "Flexible Lisp Blogware, Dynamic+PostgreSQL edition"
:version "0.0.1"
:maintainer "Brit Butler <redline6561@gmail.com>"
:author "Brit Butler <redline6561@gmail.com>"
:licence "LLGPL"
:depends-on (:coleslaw-core :postmodern :restas)
:components ((:module dynamic
:components ((:file "comments")
(:file "admin"
:depends-on ("comments"))))))

View file

@ -1,10 +0,0 @@
(defsystem :coleslaw-static
:name "coleslaw-static"
:description "Flexible Lisp Blogware, Static+S3 edition"
:version "0.0.1"
:maintainer "Brit Butler <redline6561@gmail.com>"
:author "Brit Butler <redline6561@gmail.com>"
:licence "LLGPL"
:depends-on (:coleslaw-core :zs3 :trivial-timers)
:components ((:module static
:components ((:file "comments")))))

View file

@ -1,19 +1,21 @@
(defsystem :coleslaw-core
(defsystem :coleslaw
:name "coleslaw-core"
:description "Flexible Lisp Blogware, Core utilities"
:description "Flexible Lisp Blogware"
:version "0.0.1"
:maintainer "Brit Butler <redline6561@gmail.com>"
:author "Brit Butler <redline6561@gmail.com>"
:licence "LLGPL"
:depends-on (:cl-markdown :docutils :closure-template
:external-program :local-time) ; parenscript?
:components ((:module core
:depends-on (:cl-markdown :docutils
:closure-template :cl-fad)
:components ((:module src
:components ((:file "packages")
(:file "coleslaw"
:depends-on ("packages"))
(:file "storage"
(:file "themes"
:depends-on ("coleslaw"))
(:file "comments"
:depends-on ("coleslaw"))
(:file "posts"
:depends-on ("storage"))
:depends-on ("coleslaw"))
(:file "indices"
:depends-on ("posts"))))))

View file

@ -1,4 +0,0 @@
(in-package :coleslaw)
(defgeneric start-coleslaw (&rest options)
(:documentation "Start the coleslaw server with any specified OPTIONS."))

View file

@ -1,11 +0,0 @@
(in-package :coleslaw)
(defparameter *credentials* nil
"A map of names to credentials, potentially an alist. Names should be
keywords or symbols, credentials should be dotted pairs.")
(defgeneric get-credentials (name)
(:documentation "Retrieve the credentials keyed by NAME from *credentials*."))
(defgeneric set-credentials (name credentials)
(:documentation "Store the given CREDENTIALS in *credentials* under NAME."))

View file

@ -1,17 +0,0 @@
(in-package :coleslaw)
(defgeneric create-index (name ids dates urls)
(:documentation "Create an index in *storage* with the given NAME, post IDs,
post DATEs and post URLs."))
(defgeneric get-index (name)
(:documentation "Retrieve the index matching NAME from *storage*."))
(defgeneric add-to-index (index post)
(:documentation "Add the given POST to INDEX."))
(defgeneric remove-from-index (index post)
(:documentation "Remove the given POST from INDEX."))
(defgeneric render-index (index)
(:documentation "Generate the final HTML for INDEX."))

View file

@ -1,2 +0,0 @@
(defpackage :coleslaw
(:use :cl :closure-template :local-time))

View file

@ -1,19 +0,0 @@
(in-package :coleslaw)
(defgeneric add-post (id title timestamp permalink tags
content &key &allow-other-keys)
(:documentation "Create a post with the given ID, TITLE, TIMESTAMP,
PERMALINK, TAGS and CONTENT and add it to *storage*."))
(defgeneric prettify-code (post)
(:documentation "Ensure that any escaped code in POST is prettified."))
(defgeneric prettify-math-p (post)
(:documentation "Returns T if post needs MathJAX loaded, NIL otherwise."))
(defgeneric render-post (post)
(:documentation "Generate the final HTML for POST."))
(defgeneric remove-post (post)
(:documentation "Remove POST from *storage* and, if necessary,
update the running site."))

View file

@ -1,19 +0,0 @@
(in-package :coleslaw)
(defparameter *storage* nil
"A db-spec for postmodern or a hash-table cache of metadata.
It is expected that *storage* has methods for each Generic Function
in coleslaw-core implemented.")
(defgeneric find-by-id (id)
(:documentation "Retrieve a POST object from *storage* matching ID."))
(defgeneric find-by-tag (tag)
(:documentation "Retrieve all POST objects from *storage* tagged with TAG."))
(defgeneric find-by-date (date)
(:documentation "Retrieve all POST objects from *storage* matching DATE."))
(defgeneric find-by-range (start end)
(:documentation "Retrieve all POST objects from *storage* with ids between
START and END."))

View file

@ -1,2 +0,0 @@
(in-package :coleslaw)

View file

@ -1,20 +0,0 @@
(in-package :coleslaw)
(defclass comment ()
((id :initarg :id
:accessor id)
(post-id :initarg :post-id
:accessor post-id)
(author-ip :initarg :author-ip
:accessor author-ip)
(author-name :initarg :author-name
:accessor author-name)
(author-url :initarg :author-url
:accessor author-url)
(timestamp :initarg :timestamp
:accessor timestamp)
(content :initarg :content
:accessor content)
(parent :initarg :parent
:accessor parent))
(:metaclass dao-class))

17
src/coleslaw.lisp Normal file
View file

@ -0,0 +1,17 @@
(in-package :coleslaw)
(defgeneric start-coleslaw (&rest options)
(:documentation "Start the coleslaw server with any specified OPTIONS."))
(defgeneric stop-coleslaw (&rest options)
(:documentation "Stop the coleslaw server with any specified OPTIONS."))
(defparameter *storage* nil
"A db-spec for postmodern or a hash-table cache. It is expected that
*storage* has methods for each Generic Function in coleslaw implemented.")
(defgeneric get-credentials (name)
(:documentation "Retrieve the credentials keyed by NAME from *storage*."))
(defgeneric set-credentials (name credentials)
(:documentation "Store the given CREDENTIALS in *storage* under NAME."))

39
src/comments.lisp Normal file
View file

@ -0,0 +1,39 @@
(in-package :coleslaw)
(defclass author ()
((name :initform nil
:accessor author-name)
(url :initform nil
:accessor author-url)
(ip :initform nil
:accessor author-ip)))
(defclass comment ()
((id :initform nil
:accessor comment-id)
(post :initform nil
:accessor comment-post)
(author :initform nil
:accessor comment-author)
(timestamp :initform nil
:accessor comment-timestamp)
(content :initform nil
:accessor comment-content)
(parent :initform nil
:accessor comment-parent)))
(defgeneric make-comment (post author timestamp content
parent &key &allow-other-key)
(:documentation "Create a COMMENT with the given data."))
(defgeneric add-comment (comment post-id)
(:documentation "Add COMMENT to POST-ID."))
(defgeneric delete-comment (comment post-id)
(:documentation "Delete COMMENT from POST-ID."))
(defgeneric render-comments (post-id)
(:documentation "Render the comments for POST-ID."))
(defgeneric find-comments (post-id)
(:documentation "Find the comments for POST-ID."))

13
src/indices.lisp Normal file
View file

@ -0,0 +1,13 @@
(in-package :coleslaw)
(defgeneric add-index (index id)
(:documentation "Insert INDEX into *storage* with the given ID."))
(defgeneric remove-index (id)
(:documentation "Remove the index matching ID from *storage*."))
(defgeneric render-index (index)
(:documentation "Generate the final HTML for INDEX."))
(defgeneric find-index (id)
(:documentation "Retrieve the index matching ID from *storage*."))

37
src/packages.lisp Normal file
View file

@ -0,0 +1,37 @@
(defpackage :coleslaw
(:use :cl :closure-template)
(:export ;; coleslaw-core
#:*storage*
#:start-coleslaw
#:stop-coleslaw
#:get-credentials
#:set-credentials
;; themes
#:*current-theme*
#:*theme-dir*
;; WARNING: STILL IN FLUX
;; posts
#:make-post
#:add-post
#:remove-post
#:render-post
#:find-post
#:find-by-tag
#:find-by-date
#:find-by-range
;; comments
#:make-comment
#:add-comment
#:remove-comment
#:render-comments
#:find-comments
;; indices
#:add-index
#:remove-index
#:render-index
#:find-index
))

38
src/posts.lisp Normal file
View file

@ -0,0 +1,38 @@
(in-package :coleslaw)
(defclass post ()
((id :initform nil
:accessor post-id)
(title :initform nil
:accessor post-title)
(tags :initform nil
:accessor post-tags)
(date :initform nil
:accessor post-date)
(content :initform nil
:accessor post-content)))
(defgeneric make-post (title tags date content &key &allow-other-keys)
(:documentation "Create a POST with the given data."))
(defgeneric add-post (post id)
(:documentation "Insert a post into *storage* with the given ID."))
(defgeneric remove-post (id)
(:documentation "Remove a post from *storage* matching ID."))
(defgeneric render-post (id)
(:documentation "Generate the final HTML for post."))
(defgeneric find-post (id)
(:documentation "Retrieve a post from *storage* matching ID."))
(defgeneric find-by-tag (tag)
(:documentation "Retrieve all posts from *storage* tagged with TAG."))
(defgeneric find-by-date (date)
(:documentation "Retrieve all posts from *storage* matching DATE."))
(defgeneric find-by-range (start end)
(:documentation "Retrieve all posts from *storage* with ids between
START and END."))

26
src/themes.lisp Normal file
View file

@ -0,0 +1,26 @@
(in-package :coleslaw)
(defparameter *current-theme* "hyde"
"The name of a directory containing templates for HTML generation.")
(defparameter *theme-dir* (merge-pathnames
(concatenate 'string "themes/" *current-theme*)
(asdf:system-source-directory 'coleslaw))
"The directory containing the current theme and other site templates.")
(defun theme-package (&key (name *current-theme*))
(find-package (string-upcase (concatenate 'string "coleslaw.theme." name))))
(defun compile-theme (&key (theme-dir *theme-dir*))
(loop for file in (cl-fad:list-directory theme-dir) do
(let ((extension (pathname-type file)))
(when (and extension (string= extension "tmpl"))
(compile-template :common-lisp-backend file)))))
;; DOCUMENTATION
;; A theme directory should be named after the theme and contain *.tmpl files
;; that define the following functions in a coleslaw.theme.$NAME namespace.
;; Required templates follow with suggested args (args will be in plists):
;; {template base} // title navigation siteroot content credits &key license headInject bodyInject
;; {template post} // title tags date content prev next &key comments
;; {template index} // title posts prev next &key taglinks monthlinks count

View file

@ -1,3 +0,0 @@
(in-package :coleslaw)
;; disqus integration?