Browse Source

Make feeds a subclass of indexes. Cleanup!

Brit Butler 11 years ago
parent
commit
e429d94f3f
7 changed files with 59 additions and 59 deletions
  1. 8 8
      docs/hacking.md
  2. 2 3
      src/coleslaw.lisp
  3. 0 27
      src/feeds.lisp
  4. 39 19
      src/indexes.lisp
  5. 8 0
      src/util.lisp
  6. 1 1
      themes/atom.tmpl
  7. 1 1
      themes/rss.tmpl

+ 8 - 8
docs/hacking.md

41
 
41
 
42
 ### Current Content Types & Indexes
42
 ### Current Content Types & Indexes
43
 
43
 
44
-There are 3 INDEX subclasses at present: TAG-INDEX, DATE-INDEX, and
45
-NUMERIC-INDEX, for grouping content by tags, publishing date, and
46
-reverse chronological order, respectively. Currently, there is only 1
47
-content type: POST, for blog entries.
44
+There are 5 INDEX subclasses at present: TAG-INDEX, DATE-INDEX,
45
+NUMERIC-INDEX, FEED, and TAG-FEED. Respectively, they support
46
+grouping content by tags, publishing date, and reverse chronological
47
+order. Feeds exist to special case RSS and ATOM generation.
48
+Currently, there is only 1 content type: POST, for blog entries.
48
 
49
 
49
 I'm planning to add a content type PAGE, for static pages. It should
50
 I'm planning to add a content type PAGE, for static pages. It should
50
 be a pretty straightforward subclass of CONTENT with the necessary
51
 be a pretty straightforward subclass of CONTENT with the necessary
89
 appropriate fashion, rendering them, and passing the result to
90
 appropriate fashion, rendering them, and passing the result to
90
 `write-page` (which should probably just be renamed to `write-file`).
91
 `write-page` (which should probably just be renamed to `write-file`).
91
 
92
 
92
-After this, `render-indexes` and `render-feeds` are called, and an
93
-'index.html' symlink is created to point to the first reverse
94
-chronological index.
93
+After this, `render-indexes` is called, and an 'index.html' symlink
94
+is created to point to the first reverse chronological index.
95
 
95
 
96
 - `(deploy dir)`
96
 - `(deploy dir)`
97
 
97
 
116
    was installed in the theme package. The plugin would need to do
116
    was installed in the theme package. The plugin would need to do
117
    this itself or the template would need to be included in 'core'.
117
    this itself or the template would need to be included in 'core'.
118
 2. More seriously, there is no formal relationship between content
118
 2. More seriously, there is no formal relationship between content
119
-   types and indexes. Indices include *ALL* objects in the `*content*`
119
+   types and indexes. Indexes include *ALL* objects in the `*content*`
120
    hash table. This may be undesirable and doesn't permit indexes
120
    hash table. This may be undesirable and doesn't permit indexes
121
    dedicated to particular content types.
121
    dedicated to particular content types.
122
 
122
 

+ 2 - 3
src/coleslaw.lisp

59
       (when (probe-file dir)
59
       (when (probe-file dir)
60
         (run-program "rsync --delete -raz ~a ." dir)))
60
         (run-program "rsync --delete -raz ~a ." dir)))
61
     (do-ctypes (publish (make-keyword ctype)))
61
     (do-ctypes (publish (make-keyword ctype)))
62
-    (render-indexes)
63
-    (update-symlink "index.html" "1.html")
64
-    (render-feeds (feeds *config*))))
62
+    (render-indexes (feeds *config*))
63
+    (update-symlink "index.html" "1.html")))
65
 
64
 
66
 (defgeneric deploy (staging)
65
 (defgeneric deploy (staging)
67
   (:documentation "Deploy the STAGING dir, updating the .prev and .curr symlinks.")
66
   (:documentation "Deploy the STAGING dir, updating the .prev and .curr symlinks.")

+ 0 - 27
src/feeds.lisp

1
-(in-package :coleslaw)
2
-
3
-(defun make-pubdate ()
4
-  "Make a RFC1123 pubdate representing the current time."
5
-  (local-time:format-rfc1123-timestring nil (local-time:now)))
6
-
7
-(defun render-feed (posts &key path template tag)
8
-  (flet ((first-10 (list) (subseq list 0 (min (length list) 10)))
9
-         (tag-posts (list) (remove-if-not (lambda (x) (tag-p tag x)) list)))
10
-    (let ((template (theme-fn template "feeds"))
11
-          (index (if tag
12
-                     (make-instance 'tag-index :slug path
13
-                                    :posts (first-10 (tag-posts posts)))
14
-                     (make-instance 'index :slug path
15
-                                    :posts (first-10 posts)))))
16
-      (write-page (page-path index) (render-page index template)))))
17
-
18
-(defun render-feeds (tag-feeds)
19
-  "Render the default RSS and ATOM feeds along with any TAG-FEEDS."
20
-  (let ((posts (by-date (find-all 'post))))
21
-    (dolist (feed '((:path "rss.xml" :template :rss-feed)
22
-                    (:path "atom.xml" :template :atom-feed)))
23
-      (apply #'render-feed posts feed))
24
-    (dolist (feed tag-feeds)
25
-      (apply #'render-feed posts (list :path (format nil "~A-rss.xml" feed)
26
-                                       :tag (make-tag feed)
27
-                                       :template :rss-feed)))))

+ 39 - 19
src/indexes.lisp

9
 (defclass date-index (index) ())
9
 (defclass date-index (index) ())
10
 (defclass numeric-index (index) ())
10
 (defclass numeric-index (index) ())
11
 
11
 
12
-(defmethod page-url ((object index))
13
-  (index-id object))
12
+(defclass feed (index)
13
+  (format :initform nil :initarg :format :accessor feed-format))
14
+(defclass tag-feed (feed) ())
15
+
14
 (defmethod page-url ((object tag-index))
16
 (defmethod page-url ((object tag-index))
15
-  (format nil "tag/~a" (index-id object)))
17
+  (format nil "tag/~a" (index-slug object)))
16
 (defmethod page-url ((object date-index))
18
 (defmethod page-url ((object date-index))
17
-  (format nil "date/~a" (index-id object)))
19
+  (format nil "date/~a" (index-slug object)))
18
 (defmethod page-url ((object numeric-index))
20
 (defmethod page-url ((object numeric-index))
19
-  (format nil "~d" (index-id object)))
21
+  (format nil "~d" (index-slug object)))
22
+
23
+(defmethod page-url ((object feed))
24
+  (format nil "~(~a~).xml" (feed-format object)))
25
+(defmethod page-url ((object tag-feed))
26
+  (format nil "tag/~a~(~a~).xml" (index-slug object) (feed-format object)))
20
 
27
 
21
 (defmethod render ((object index) &key prev next)
28
 (defmethod render ((object index) &key prev next)
22
   (funcall (theme-fn 'index) (list :tags (all-tags)
29
   (funcall (theme-fn 'index) (list :tags (all-tags)
50
                  :posts (remove-if-not (lambda (x) (month-p month x)) content)
57
                  :posts (remove-if-not (lambda (x) (month-p month x)) content)
51
                  :title (format nil "Posts from ~a" month)))
58
                  :title (format nil "Posts from ~a" month)))
52
 
59
 
53
-(defun index-by-n (i content &optional (step 10))
60
+(defun index-by-n (i content)
54
   "Return the index for the Ith page of CONTENT in reverse chronological order."
61
   "Return the index for the Ith page of CONTENT in reverse chronological order."
55
-  (let* ((start (* step i))
56
-         (end (min (length content) (+ start step))))
62
+  (let ((content (subseq content (* 10 i))))
57
     (make-instance 'numeric-index :slug (1+ i)
63
     (make-instance 'numeric-index :slug (1+ i)
58
-                              :posts (subseq content start end)
59
-                              :title "Recent Posts")))
64
+                   :posts (take-up-to 10 content)
65
+                   :title "Recent Posts")))
66
+
67
+(defun render-feed (feed)
68
+  "Render the given FEED to both RSS and ATOM."
69
+  (let ((theme-fn (theme-fn (feed-format feed) "feeds")))
70
+    (write-page (page-path feed) (render-page feed theme-fn))))
60
 
71
 
61
 (defun render-index (index &rest render-args)
72
 (defun render-index (index &rest render-args)
62
   "Render the given INDEX using RENDER-ARGS if provided."
73
   "Render the given INDEX using RENDER-ARGS if provided."
63
   (write-page (page-path index) (apply #'render-page index nil render-args)))
74
   (write-page (page-path index) (apply #'render-page index nil render-args)))
64
 
75
 
65
-(defun render-indexes ()
66
-  "Render the indexes to view content in groups of size N, by month, and by tag."
67
-  (let ((results (by-date (find-all 'post))))
76
+(defun render-indexes (tag-feeds)
77
+  "Render the indexes to view content in groups of size N, by month, or by tag,
78
+along with RSS and ATOM feeds and any supplied TAG-FEEDS."
79
+  (let ((content (by-date (find-all 'post))))
68
     (dolist (tag (all-tags))
80
     (dolist (tag (all-tags))
69
-      (render-index (index-by-tag tag results)))
81
+      (render-index (index-by-tag tag content)))
70
     (dolist (month (all-months))
82
     (dolist (month (all-months))
71
-      (render-index (index-by-month month results)))
72
-    (dotimes (i (ceiling (length results) 10))
73
-      (render-index (index-by-n i results)
83
+      (render-index (index-by-month month content)))
84
+    (dotimes (i (ceiling (length content) 10))
85
+      (render-index (index-by-n i content)
74
                     :prev (and (plusp i) i)
86
                     :prev (and (plusp i) i)
75
-                    :next (and (< (* (1+ i) 10) (length results))
76
-                               (+ 2 i))))))
87
+                    :next (and (< (* (1+ i) 10) (length content))
88
+                               (+ 2 i))))
89
+    (dolist (format '(rss atom))
90
+      (dolist (tag tag-feeds)
91
+        (let ((posts (remove-if-now (lambda (x) (tag-p (make-tag tag) x)) content)))
92
+          (render-feed (make-instance 'tag-feed :posts (take-up-to 10 posts)
93
+                                      :format format
94
+                                      :slug tag))))
95
+      (render-feed (make-instance 'feed :posts (take-up-to 10 content)
96
+                                  :format format)))))

+ 8 - 0
src/util.lisp

69
                          (setf (current-directory) ,path)
69
                          (setf (current-directory) ,path)
70
                          ,@body)
70
                          ,@body)
71
          (setf (current-directory) ,old)))))
71
          (setf (current-directory) ,old)))))
72
+
73
+(defun take-up-to (n seq)
74
+  "Take elements from SEQ until all elements or N have been taken."
75
+  (subseq seq 0 (min (length seq) n)))
76
+
77
+(defun make-pubdate ()
78
+  "Make a RFC1123 pubdate representing the current time."
79
+  (local-time:format-rfc1123-timestring nil (local-time:now)))

+ 1 - 1
themes/atom.tmpl

1
 {namespace coleslaw.theme.feeds}
1
 {namespace coleslaw.theme.feeds}
2
 
2
 
3
-{template atom-feed}
3
+{template atom}
4
 <?xml version="1.0"?>{\n}
4
 <?xml version="1.0"?>{\n}
5
 <feed xmlns="http://www.w3.org/2005/Atom">
5
 <feed xmlns="http://www.w3.org/2005/Atom">
6
 
6
 

+ 1 - 1
themes/rss.tmpl

1
 {namespace coleslaw.theme.feeds}
1
 {namespace coleslaw.theme.feeds}
2
 
2
 
3
-{template rss-feed}
3
+{template rss}
4
 <?xml version="1.0"?>{\n}
4
 <?xml version="1.0"?>{\n}
5
 <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
5
 <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
6
   <channel>
6
   <channel>