diff --git a/NEWS.md b/NEWS.md index 3330d7f..fd65e1f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,14 @@ the old behavior. * Coleslaw no longer expects a particular repo layout. Use whatever directory hierarchy you like. +* New Content Type Plugin: Static Pages, accepting a title, url, and + optionally tags and a date. All files with a `.page` extension are + compiled as static pages and reuse the POST template. + To enable Static Pages, add `(static-pages)` to the `:plugins` + section of your config. +* Coleslaw now allows content without a date or tags. Note that POSTs + without a date will still show up in the reverse chronological + indexes at the very end. ## Changes for 0.9.3 (2013-04-16): diff --git a/docs/hacking.md b/docs/hacking.md index 327bbd7..f8adae3 100644 --- a/docs/hacking.md +++ b/docs/hacking.md @@ -168,25 +168,6 @@ freshly built site. ## Areas for Improvement -### Allow Tagless or Dateless Content - -Several users have expected to be able to not supply tags or a date -for their content. This is a reasonable expectation and requires -changes to at least the post templates and the `read-content` -function. There may be other areas where it was assumed tags/dates -will always be present. - -### New Content Type: Pages! - -Many users have requested a content type PAGE, for static pages. It -should be a pretty straightforward subclass of CONTENT with the -necessary methods: `render`, `page-url` and `publish`. It could have a -`url` slot with `page-url` as a reader to allow arbitrary layout on -the site. For now, we can be sloppy and reuse the post template and -limit static-pages to being written in markdown. If we want to support -other formats, consider moving the format slot from POST to CONTENT. -This has been implemented on the branch `static-pages`. - ### New Content Type: Shouts! I've also toyed with the idea of a content type called a SHOUT, which diff --git a/plugins/static-pages.lisp b/plugins/static-pages.lisp new file mode 100644 index 0000000..66d276a --- /dev/null +++ b/plugins/static-pages.lisp @@ -0,0 +1,32 @@ +(defpackage :coleslaw-static-pages + (:use :cl) + (:export #:enable) + (:import-from :coleslaw #:*config* + #:content + #:page-url + #:find-all + #:render + #:publish + #:write-document)) + +(in-package :coleslaw-static-pages) + +(defclass page (content) + ((title :initarg :title :reader page-title) + (url :initarg :url :reader page-url))) + +(defmethod initialize-instance :after ((object page) &key) + ;; Expect all static-pages to be written in Markdown for now. + (with-accessors ((text content-text)) object + (setf text (render-text text :md)))) + +(defmethod render ((object page) &key next prev) + ;; For the time being, we'll re-use the normal post theme. + (funcall (theme-fn 'post) (list :config *config* + :post object))) + +(defmethod publish ((doc-type (eql (find-class 'page)))) + (dolist (page (find-all 'page)) + (write-document page))) + +(defun enable ()) diff --git a/src/content.lisp b/src/content.lisp index dde3541..a80fc1f 100644 --- a/src/content.lisp +++ b/src/content.lisp @@ -36,6 +36,11 @@ (date :initform nil :initarg :date :accessor content-date) (text :initform nil :initarg :text :accessor content-text))) +(defmethod initialize-instance :after ((object content) &key) + (with-accessors ((tags content-tags)) object + (when (stringp tags) + (setf tags (mapcar #'make-tag (cl-ppcre:split "," tags)))))) + (defun read-content (file) "Returns a plist of metadata from FILE with :text holding the content as a string." (flet ((slurp-remainder (stream) @@ -46,9 +51,7 @@ (parse-field (str) (nth-value 1 (cl-ppcre:scan-to-strings "[a-zA-Z]+: (.*)" str))) (field-name (line) - (make-keyword (string-upcase (subseq line 0 (position #\: line))))) - (read-tags (str) - (mapcar #'make-tag (cl-ppcre:split "," str)))) + (make-keyword (string-upcase (subseq line 0 (position #\: line)))))) (with-open-file (in file :external-format '(:utf-8)) (unless (string= (read-line in) (separator *config*)) (error "The provided file lacks the expected header.")) @@ -57,9 +60,10 @@ appending (list (field-name line) (aref (parse-field line) 0)))) (content (slurp-remainder in))) - (setf (getf meta :tags) (read-tags (getf meta :tags))) (append meta (list :text content)))))) +;; Helper Functions + (defun tag-p (tag obj) "Test if OBJ is tagged with TAG." (let ((tag (if (typep tag 'tag) tag (make-tag tag)))) diff --git a/src/packages.lisp b/src/packages.lisp index 6c7b774..7b59711 100644 --- a/src/packages.lisp +++ b/src/packages.lisp @@ -15,6 +15,7 @@ #:index #:render-text #:add-injection + #:theme-fn ;; The Document Protocol #:add-document #:find-all diff --git a/themes/hyde/post.tmpl b/themes/hyde/post.tmpl index 6406035..cebe759 100644 --- a/themes/hyde/post.tmpl +++ b/themes/hyde/post.tmpl @@ -4,13 +4,17 @@
{\n}

{$post.title}

{\n}
{\n} - Tagged as {foreach $tag in $post.tags} - {$tag.name}{nil} - {if not isLast($tag)},{sp}{/if} - {/foreach} + {if $post.tags} + Tagged as {foreach $tag in $post.tags} + {$tag.name}{nil} + {if not isLast($tag)},{sp}{/if} + {/foreach} + {/if}
{\n}
{\n} - Written on {$post.date} + {if $post.date} + Written on {$post.date} + {/if}
{\n}
{\n}
{\n} diff --git a/themes/readable/post.tmpl b/themes/readable/post.tmpl index a5be92f..b655ce7 100644 --- a/themes/readable/post.tmpl +++ b/themes/readable/post.tmpl @@ -3,13 +3,19 @@ {template post}
{\n}

{$post.title}

{\n} -

Tagged as - {foreach $tag in $post.tags} - {$tag.name}{nil} - {if not isLast($tag)},{sp}{/if} - {/foreach} +

+ {if $post.tags} + Tagged as {foreach $tag in $post.tags} + {$tag.name}{nil} + {if not isLast($tag)},{sp}{/if} + {/foreach} + {/if} +

+

+ {if $post.date} + Written on {$post.date} + {/if}

-

Written on {$post.date}

{$post.text |noAutoescape}