Merge pull request #48 from redline6561/static-pages

Static pages
This commit is contained in:
Brit Butler 2014-04-29 14:06:18 -04:00
commit 4e6efa9d9e
7 changed files with 70 additions and 34 deletions

View file

@ -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):

View file

@ -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

32
plugins/static-pages.lisp Normal file
View file

@ -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 ())

View file

@ -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))))

View file

@ -15,6 +15,7 @@
#:index
#:render-text
#:add-injection
#:theme-fn
;; The Document Protocol
#:add-document
#:find-all

View file

@ -4,13 +4,17 @@
<div class="article-meta">{\n}
<h1 class="title">{$post.title}</h1>{\n}
<div class="tags">{\n}
Tagged as {foreach $tag in $post.tags}
<a href="../tag/{$tag.slug}.{$config.pageExt}">{$tag.name}</a>{nil}
{if not isLast($tag)},{sp}{/if}
{/foreach}
{if $post.tags}
Tagged as {foreach $tag in $post.tags}
<a href="../tag/{$tag.slug}.{$config.pageExt}">{$tag.name}</a>{nil}
{if not isLast($tag)},{sp}{/if}
{/foreach}
{/if}
</div>{\n}
<div class="date">{\n}
Written on {$post.date}
{if $post.date}
Written on {$post.date}
{/if}
</div>{\n}
</div>{\n}
<div class="article-content">{\n}

View file

@ -3,13 +3,19 @@
{template post}
<div class="row-fluid">{\n}
<h1 class="page-header">{$post.title}</h1>{\n}
<p>Tagged as
{foreach $tag in $post.tags}
<a href="../tag/{$tag.slug}{$config.pageExt}">{$tag.name}</a>{nil}
{if not isLast($tag)},{sp}{/if}
{/foreach}
<p>
{if $post.tags}
Tagged as {foreach $tag in $post.tags}
<a href="../tag/{$tag.slug}{$config.pageExt}">{$tag.name}</a>{nil}
{if not isLast($tag)},{sp}{/if}
{/foreach}
{/if}
</p>
<p class="date-posted">
{if $post.date}
Written on {$post.date}
{/if}
</p>
<p class="date-posted">Written on {$post.date}</p>
{$post.text |noAutoescape}