Browse Source

Merge pull request #48 from redline6561/static-pages

Static pages
Brit Butler 11 years ago
parent
commit
4e6efa9d9e
7 changed files with 70 additions and 34 deletions
  1. 8 0
      NEWS.md
  2. 0 19
      docs/hacking.md
  3. 32 0
      plugins/static-pages.lisp
  4. 8 4
      src/content.lisp
  5. 1 0
      src/packages.lisp
  6. 9 5
      themes/hyde/post.tmpl
  7. 12 6
      themes/readable/post.tmpl

+ 8 - 0
NEWS.md

7
   the old behavior.
7
   the old behavior.
8
 * Coleslaw no longer expects a particular repo layout. Use whatever
8
 * Coleslaw no longer expects a particular repo layout. Use whatever
9
   directory hierarchy you like.
9
   directory hierarchy you like.
10
+* New Content Type Plugin: Static Pages, accepting a title, url, and
11
+  optionally tags and a date. All files with a `.page` extension are
12
+  compiled as static pages and reuse the POST template.
13
+  To enable Static Pages, add `(static-pages)` to the `:plugins`
14
+  section of your config.
15
+* Coleslaw now allows content without a date or tags. Note that POSTs
16
+  without a date will still show up in the reverse chronological
17
+  indexes at the very end.
10
 
18
 
11
 ## Changes for 0.9.3 (2013-04-16):
19
 ## Changes for 0.9.3 (2013-04-16):
12
 
20
 

+ 0 - 19
docs/hacking.md

168
 
168
 
169
 ## Areas for Improvement
169
 ## Areas for Improvement
170
 
170
 
171
-### Allow Tagless or Dateless Content
172
-
173
-Several users have expected to be able to not supply tags or a date
174
-for their content. This is a reasonable expectation and requires
175
-changes to at least the post templates and the `read-content`
176
-function. There may be other areas where it was assumed tags/dates
177
-will always be present.
178
-
179
-### New Content Type: Pages!
180
-
181
-Many users have requested a content type PAGE, for static pages. It
182
-should be a pretty straightforward subclass of CONTENT with the
183
-necessary methods: `render`, `page-url` and `publish`. It could have a
184
-`url` slot with `page-url` as a reader to allow arbitrary layout on
185
-the site.  For now, we can be sloppy and reuse the post template and
186
-limit static-pages to being written in markdown. If we want to support
187
-other formats, consider moving the format slot from POST to CONTENT.
188
-This has been implemented on the branch `static-pages`.
189
-
190
 ### New Content Type: Shouts!
171
 ### New Content Type: Shouts!
191
 
172
 
192
 I've also toyed with the idea of a content type called a SHOUT, which
173
 I've also toyed with the idea of a content type called a SHOUT, which

+ 32 - 0
plugins/static-pages.lisp

1
+(defpackage :coleslaw-static-pages
2
+  (:use :cl)
3
+  (:export #:enable)
4
+  (:import-from :coleslaw #:*config*
5
+                          #:content
6
+                          #:page-url
7
+                          #:find-all
8
+                          #:render
9
+                          #:publish
10
+                          #:write-document))
11
+
12
+(in-package :coleslaw-static-pages)
13
+
14
+(defclass page (content)
15
+  ((title :initarg :title :reader page-title)
16
+   (url :initarg :url :reader page-url)))
17
+
18
+(defmethod initialize-instance :after ((object page) &key)
19
+  ;; Expect all static-pages to be written in Markdown for now.
20
+  (with-accessors ((text content-text)) object
21
+    (setf text (render-text text :md))))
22
+
23
+(defmethod render ((object page) &key next prev)
24
+  ;; For the time being, we'll re-use the normal post theme.
25
+  (funcall (theme-fn 'post) (list :config *config*
26
+                                  :post object)))
27
+
28
+(defmethod publish ((doc-type (eql (find-class 'page))))
29
+  (dolist (page (find-all 'page))
30
+    (write-document page)))
31
+
32
+(defun enable ())

+ 8 - 4
src/content.lisp

36
    (date :initform nil :initarg :date :accessor content-date)
36
    (date :initform nil :initarg :date :accessor content-date)
37
    (text :initform nil :initarg :text :accessor content-text)))
37
    (text :initform nil :initarg :text :accessor content-text)))
38
 
38
 
39
+(defmethod initialize-instance :after ((object content) &key)
40
+  (with-accessors ((tags content-tags)) object
41
+    (when (stringp tags)
42
+      (setf tags (mapcar #'make-tag (cl-ppcre:split "," tags))))))
43
+
39
 (defun read-content (file)
44
 (defun read-content (file)
40
   "Returns a plist of metadata from FILE with :text holding the content as a string."
45
   "Returns a plist of metadata from FILE with :text holding the content as a string."
41
   (flet ((slurp-remainder (stream)
46
   (flet ((slurp-remainder (stream)
46
          (parse-field (str)
51
          (parse-field (str)
47
            (nth-value 1 (cl-ppcre:scan-to-strings "[a-zA-Z]+: (.*)" str)))
52
            (nth-value 1 (cl-ppcre:scan-to-strings "[a-zA-Z]+: (.*)" str)))
48
          (field-name (line)
53
          (field-name (line)
49
-           (make-keyword (string-upcase (subseq line 0 (position #\: line)))))
50
-         (read-tags (str)
51
-           (mapcar #'make-tag (cl-ppcre:split "," str))))
54
+           (make-keyword (string-upcase (subseq line 0 (position #\: line))))))
52
     (with-open-file (in file :external-format '(:utf-8))
55
     (with-open-file (in file :external-format '(:utf-8))
53
       (unless (string= (read-line in) (separator *config*))
56
       (unless (string= (read-line in) (separator *config*))
54
         (error "The provided file lacks the expected header."))
57
         (error "The provided file lacks the expected header."))
57
                      appending (list (field-name line)
60
                      appending (list (field-name line)
58
                                      (aref (parse-field line) 0))))
61
                                      (aref (parse-field line) 0))))
59
             (content (slurp-remainder in)))
62
             (content (slurp-remainder in)))
60
-        (setf (getf meta :tags) (read-tags (getf meta :tags)))
61
         (append meta (list :text content))))))
63
         (append meta (list :text content))))))
62
 
64
 
65
+;; Helper Functions
66
+
63
 (defun tag-p (tag obj)
67
 (defun tag-p (tag obj)
64
   "Test if OBJ is tagged with TAG."
68
   "Test if OBJ is tagged with TAG."
65
   (let ((tag (if (typep tag 'tag) tag (make-tag tag))))
69
   (let ((tag (if (typep tag 'tag) tag (make-tag tag))))

+ 1 - 0
src/packages.lisp

15
            #:index
15
            #:index
16
            #:render-text
16
            #:render-text
17
            #:add-injection
17
            #:add-injection
18
+           #:theme-fn
18
            ;; The Document Protocol
19
            ;; The Document Protocol
19
            #:add-document
20
            #:add-document
20
            #:find-all
21
            #:find-all

+ 9 - 5
themes/hyde/post.tmpl

4
 <div class="article-meta">{\n}
4
 <div class="article-meta">{\n}
5
   <h1 class="title">{$post.title}</h1>{\n}
5
   <h1 class="title">{$post.title}</h1>{\n}
6
   <div class="tags">{\n}
6
   <div class="tags">{\n}
7
-    Tagged as {foreach $tag in $post.tags}
8
-                <a href="../tag/{$tag.slug}.{$config.pageExt}">{$tag.name}</a>{nil}
9
-                    {if not isLast($tag)},{sp}{/if}
10
-              {/foreach}
7
+    {if $post.tags}
8
+      Tagged as {foreach $tag in $post.tags}
9
+        <a href="../tag/{$tag.slug}.{$config.pageExt}">{$tag.name}</a>{nil}
10
+          {if not isLast($tag)},{sp}{/if}
11
+      {/foreach}
12
+    {/if}
11
   </div>{\n}
13
   </div>{\n}
12
   <div class="date">{\n}
14
   <div class="date">{\n}
13
-    Written on {$post.date}
15
+    {if $post.date}
16
+      Written on {$post.date}
17
+    {/if}
14
   </div>{\n}
18
   </div>{\n}
15
 </div>{\n}
19
 </div>{\n}
16
 <div class="article-content">{\n}
20
 <div class="article-content">{\n}

+ 12 - 6
themes/readable/post.tmpl

3
 {template post}
3
 {template post}
4
 <div class="row-fluid">{\n}
4
 <div class="row-fluid">{\n}
5
   <h1 class="page-header">{$post.title}</h1>{\n}
5
   <h1 class="page-header">{$post.title}</h1>{\n}
6
-  <p>Tagged as 
7
-    {foreach $tag in $post.tags}
8
-      <a href="../tag/{$tag.slug}{$config.pageExt}">{$tag.name}</a>{nil}
9
-      {if not isLast($tag)},{sp}{/if}
10
-    {/foreach}
6
+  <p>
7
+    {if $post.tags}
8
+      Tagged as {foreach $tag in $post.tags}
9
+        <a href="../tag/{$tag.slug}{$config.pageExt}">{$tag.name}</a>{nil}
10
+          {if not isLast($tag)},{sp}{/if}
11
+      {/foreach}
12
+    {/if}
13
+  </p>
14
+  <p class="date-posted">
15
+    {if $post.date}
16
+      Written on {$post.date}
17
+    {/if}
11
   </p>
18
   </p>
12
-  <p class="date-posted">Written on {$post.date}</p>
13
 
19
 
14
   {$post.text |noAutoescape}
20
   {$post.text |noAutoescape}
15
   
21