Ver código fonte

WARNING: This commit breaks indices and feeds.
Factor write-page from render-page. Reorganization to allow for new content types.

Brit Butler 12 anos atrás
pai
commit
3ddd50bf7f
3 arquivos alterados com 61 adições e 52 exclusões
  1. 28 17
      src/coleslaw.lisp
  2. 26 32
      src/posts.lisp
  3. 7 3
      src/util.lisp

+ 28 - 17
src/coleslaw.lisp

@@ -1,26 +1,37 @@
1 1
 (in-package :coleslaw)
2 2
 
3
-(defgeneric render (content &key &allow-other-keys)
4
-  (:documentation "Render the given CONTENT to HTML."))
3
+(defgeneric render (object &key &allow-other-keys)
4
+  (:documentation "Render the given OBJECT to HTML."))
5
+
6
+(defgeneric render-content (text format)
7
+  (:documentation "Compile TEXT from the given FORMAT to HTML for display.")
8
+  (:method (text (format (eql :html)))
9
+    text)
10
+  (:method (test (format (eql :md)))
11
+    (let ((3bmd-code-blocks:*code-blocks* t))
12
+      (with-output-to-string (str)
13
+        (3bmd:parse-string-and-print-to-stream text str)))))
14
+
15
+(defgeneric page-path (content)
16
+  (:documentation "The path to store CONTENT at once rendered."))
5 17
 
6 18
 (defun render-page (content &optional theme-fn &rest render-args)
7 19
   "Render the given CONTENT to disk using THEME-FN if supplied.
8 20
 Additional args to render CONTENT can be passed via RENDER-ARGS."
9
-  (let* ((path (etypecase content
10
-                 (post (format nil "posts/~a.html" (post-slug content)))
11
-                 (index (index-path content))))
12
-         (filepath (merge-pathnames path (staging *config*)))
13
-         (page (funcall (theme-fn (or theme-fn 'base))
14
-                        (list :config *config*
15
-                              :content content
16
-                              :raw (apply 'render content render-args)
17
-                              :pubdate (make-pubdate)
18
-                              :injections (find-injections content)))))
19
-    (ensure-directories-exist filepath)
20
-    (with-open-file (out filepath
21
-                     :direction :output
22
-                     :if-does-not-exist :create)
23
-      (write-line page out))))
21
+  (funcall (theme-fn (or theme-fn 'base))
22
+           (list :config *config*
23
+                 :content content
24
+                 :raw (apply 'render content render-args)
25
+                 :pubdate (make-pubdate)
26
+                 :injections (find-injections content))))
27
+
28
+(defun write-page (filepath page)
29
+  "Write the given PAGE to FILEPATH."
30
+  (ensure-directories-exist filepath)
31
+  (with-open-file (out filepath
32
+                   :direction :output
33
+                   :if-does-not-exist :create)
34
+    (write-line page out)))
24 35
 
25 36
 (defun compile-blog (staging)
26 37
   "Compile the blog to a STAGING directory as specified in .coleslawrc."

+ 26 - 32
src/posts.lisp

@@ -11,38 +11,14 @@
11 11
    (format :initform nil :initarg :format :accessor post-format)
12 12
    (content :initform nil :initarg :content :accessor post-content)))
13 13
 
14
-(defmethod render ((content post) &key prev next)
14
+(defmethod render ((object post) &key prev next)
15 15
   (funcall (theme-fn 'post) (list :config *config*
16
-                                  :post content
16
+                                  :post object
17 17
                                   :prev prev
18 18
                                   :next next)))
19 19
 
20
-(defun load-posts ()
21
-  "Read the stored .post files from the repo."
22
-  (clrhash *posts*)
23
-  (do-files (file (repo *config*) "post")
24
-    (with-open-file (in file)
25
-      (let ((post (read-post in)))
26
-        (if (gethash (post-slug post) *posts*)
27
-            (error "There is already an existing post with the slug ~a."
28
-                   (post-slug post))
29
-            (setf (gethash (post-slug post) *posts*) post))))))
30
-
31
-(defun render-posts ()
32
-  "Iterate through the files in the repo to render+write the posts out to disk."
33
-    (loop for (prev post next) on (append '(nil) (sort (hash-table-values *posts*)
34
-                                                       #'string< :key #'post-date))
35
-       while post do (render-page post nil :prev prev :next next)))
36
-
37
-(defgeneric render-content (text format)
38
-  (:documentation "Compile TEXT from the given FORMAT to HTML for display.")
39
-  (:method (text (format (eql :html)))
40
-    text))
41
-
42
-(defmethod render-content (text (format (eql :md)))
43
-  (let ((3bmd-code-blocks:*code-blocks* t))
44
-    (with-output-to-string (str)
45
-      (3bmd:parse-string-and-print-to-stream text str))))
20
+(defmethod page-path ((post post))
21
+  (rel-path (staging *config*) "posts/~a.html" (post-slug post)))
46 22
 
47 23
 (defun read-post (in)
48 24
   "Make a POST instance based on the data from the stream IN."
@@ -51,6 +27,8 @@
51 27
              (error "The provided file lacks the expected header.")))
52 28
          (parse-field (str)
53 29
            (nth-value 1 (cl-ppcre:scan-to-strings "[a-zA-Z]+: (.*)" str)))
30
+         (field-name (line)
31
+           (subseq line 0 (position #\: line)))
54 32
          (read-tags (str)
55 33
            (mapcar #'string-downcase (cl-ppcre:split ", " str)))
56 34
          (slurp-remainder ()
@@ -58,11 +36,9 @@
58 36
              (read-sequence seq in)
59 37
              (remove #\Nul seq))))
60 38
     (check-header)
61
-    (let ((args (loop for field in '("title" "tags" "date" "format")
62
-                   for line = (read-line in nil)
63
-                   appending (list (make-keyword (string-upcase field))
39
+    (let ((args (loop for line = (read-line in nil) until (string= line ";;;;;")
40
+                   appending (list (make-keyword (string-upcase (field-name line)))
64 41
                                    (aref (parse-field line) 0)))))
65
-      (check-header)
66 42
       (setf (getf args :tags) (read-tags (getf args :tags))
67 43
             (getf args :format) (make-keyword (string-upcase (getf args :format))))
68 44
       (apply 'make-instance 'post
@@ -70,6 +46,24 @@
70 46
                                                          (getf args :format))
71 47
                                 :slug (slugify (getf args :title))))))))
72 48
 
49
+(defun load-posts ()
50
+  "Read the stored .post files from the repo."
51
+  (clrhash *posts*)
52
+  (do-files (file (repo *config*) "post")
53
+    (with-open-file (in file)
54
+      (let ((post (read-post in)))
55
+        (if (gethash (post-slug post) *posts*)
56
+            (error "There is already an existing post with the slug ~a."
57
+                   (post-slug post))
58
+            (setf (gethash (post-slug post) *posts*) post))))))
59
+
60
+(defun render-posts ()
61
+  "Iterate through the files in the repo to render+write the posts out to disk."
62
+  (loop for (prev post next) on (append '(nil) (sort (hash-table-values *posts*)
63
+                                                     #'string< :key #'post-date))
64
+     while post do (write-page (page-path post)
65
+                               (render-page post nil :prev prev :next next))))
66
+
73 67
 (defun slug-char-p (char)
74 68
   "Determine if CHAR is a valid slug (i.e. URL) character."
75 69
   (or (char<= #\0 char #\9)

+ 7 - 3
src/util.lisp

@@ -1,9 +1,13 @@
1 1
 (in-package :coleslaw)
2 2
 
3
-(defun app-path (path &rest args)
4
-  "Take a relative PATH and return the corresponding pathname beneath coleslaw.
3
+(defun rel-path (base path &rest args)
4
+  "Take a relative PATH and return the corresponding pathname beneath BASE.
5 5
 If ARGS is provided, use (apply 'format nil PATH ARGS) as the value of PATH."
6
-  (merge-pathnames (apply 'format nil path args) coleslaw-conf:*basedir*))
6
+  (merge-pathnames (apply 'format nil path args) base))
7
+
8
+(defun app-path (path &rest args)
9
+  "Return a relative path beneath coleslaw."
10
+  (apply 'rel-path coleslaw-conf:*basedir* path args))
7 11
 
8 12
 (defun run-program (program &rest args)
9 13
   "Take a PROGRAM and execute the corresponding shell command. If ARGS is provided,