Browse Source

Finish the routing/slugs overhaul.

Brit Butler 10 years ago
parent
commit
ef378b9b56

+ 6 - 1
src/content.lisp

4
 
4
 
5
 (defclass tag ()
5
 (defclass tag ()
6
   ((name :initarg :name :reader tag-name)
6
   ((name :initarg :name :reader tag-name)
7
-   (slug :initarg :slug :reader tag-slug)))
7
+   (slug :initarg :slug :reader tag-slug)
8
+   (url  :initarg :url)))
9
+
10
+(defmethod initialize-instance :after ((tag tag) &key)
11
+  (with-slots (url slug) tag
12
+    (setf url (compute-url nil slug 'tag-index))))
8
 
13
 
9
 (defun make-tag (str)
14
 (defun make-tag (str)
10
   "Takes a string and returns a TAG instance with a name and slug."
15
   "Takes a string and returns a TAG instance with a name and slug."

+ 12 - 11
src/documents.lisp

28
 (defgeneric page-url (document)
28
 (defgeneric page-url (document)
29
   (:documentation "The relative URL to the DOCUMENT."))
29
   (:documentation "The relative URL to the DOCUMENT."))
30
 
30
 
31
-(defun compute-url (document unique-id)
32
-  "Compute the relative URL for a DOCUMENT based on its UNIQUE-ID."
33
-  (let* ((class-name (class-name (class-of document)))
31
+(defgeneric render (document &key &allow-other-keys)
32
+  (:documentation "Render the given DOCUMENT to HTML."))
33
+
34
+;; Helper Functions
35
+
36
+(defun compute-url (document unique-id &optional class)
37
+  "Compute the relative URL for a DOCUMENT based on its UNIQUE-ID. If CLASS
38
+is provided, it overrides the route used."
39
+  (let* ((class-name (or class (class-name (class-of document))))
34
          (route (get-route class-name)))
40
          (route (get-route class-name)))
35
     (unless route
41
     (unless route
36
       (error "No routing method found for: ~A" class-name))
42
       (error "No routing method found for: ~A" class-name))
38
            (type (or (pathname-type result) (page-ext *config*))))
44
            (type (or (pathname-type result) (page-ext *config*))))
39
       (make-pathname :type type :defaults result))))
45
       (make-pathname :type type :defaults result))))
40
 
46
 
41
-(defgeneric render (document &key &allow-other-keys)
42
-  (:documentation "Render the given DOCUMENT to HTML."))
43
-
44
-;; Helper Functions
47
+(defun get-route (doc-type)
48
+  "Return the route format string for DOC-TYPE."
49
+  (second (assoc (make-keyword doc-type) (routing *config*))))
45
 
50
 
46
 (defun add-document (document)
51
 (defun add-document (document)
47
   "Add DOCUMENT to the in-memory database. Error if a matching entry is present."
52
   "Add DOCUMENT to the in-memory database. Error if a matching entry is present."
63
         (url (namestring (page-url document))))
68
         (url (namestring (page-url document))))
64
     (write-file (rel-path (staging-dir *config*) url) html)))
69
     (write-file (rel-path (staging-dir *config*) url) html)))
65
 
70
 
66
-(defun get-route (doc-type)
67
-  "Return the route format string for DOC-TYPE."
68
-  (second (assoc (make-keyword doc-type) (routing *config*))))
69
-
70
 (defun find-all (doc-type)
71
 (defun find-all (doc-type)
71
   "Return a list of all instances of a given DOC-TYPE."
72
   "Return a list of all instances of a given DOC-TYPE."
72
   (loop for val being the hash-values in *site*
73
   (loop for val being the hash-values in *site*

+ 7 - 6
src/indexes.lisp

7
 
7
 
8
 (defclass index ()
8
 (defclass index ()
9
   ((url     :initarg :url     :reader page-url)
9
   ((url     :initarg :url     :reader page-url)
10
+   (name    :initarg :name    :reader index-name)
10
    (title   :initarg :title   :reader title-of)
11
    (title   :initarg :title   :reader title-of)
11
    (content :initarg :content :reader index-content)))
12
    (content :initarg :content :reader index-content)))
12
 
13
 
33
 
34
 
34
 (defun index-by-tag (tag content)
35
 (defun index-by-tag (tag content)
35
   "Return an index of all CONTENT matching the given TAG."
36
   "Return an index of all CONTENT matching the given TAG."
36
-  (make-instance 'tag-index :slug (tag-slug tag)
37
+  (make-instance 'tag-index :slug (tag-slug tag) :name (tag-name tag)
37
                  :content (remove-if-not (lambda (x) (tag-p tag x)) content)
38
                  :content (remove-if-not (lambda (x) (tag-p tag x)) content)
38
                  :title (format nil "Content tagged ~a" (tag-name tag))))
39
                  :title (format nil "Content tagged ~a" (tag-name tag))))
39
 
40
 
52
 
53
 
53
 (defun index-by-month (month content)
54
 (defun index-by-month (month content)
54
   "Return an index of all CONTENT matching the given MONTH."
55
   "Return an index of all CONTENT matching the given MONTH."
55
-  (make-instance 'month-index :slug month
56
+  (make-instance 'month-index :slug month :name month
56
                  :content (remove-if-not (lambda (x) (month-p month x)) content)
57
                  :content (remove-if-not (lambda (x) (month-p month x)) content)
57
                  :title (format nil "Content from ~a" month)))
58
                  :title (format nil "Content from ~a" month)))
58
 
59
 
72
 (defun index-by-n (i content)
73
 (defun index-by-n (i content)
73
   "Return the index for the Ith page of CONTENT in reverse chronological order."
74
   "Return the index for the Ith page of CONTENT in reverse chronological order."
74
   (let ((content (subseq content (* 10 i))))
75
   (let ((content (subseq content (* 10 i))))
75
-    (make-instance 'numeric-index :slug (1+ i)
76
+    (make-instance 'numeric-index :slug (1+ i) :name (1+ i)
76
                    :content (take-up-to 10 content)
77
                    :content (take-up-to 10 content)
77
                    :title "Recent Content")))
78
                    :title "Recent Content")))
78
 
79
 
79
 (defmethod publish ((doc-type (eql (find-class 'numeric-index))))
80
 (defmethod publish ((doc-type (eql (find-class 'numeric-index))))
80
-  (let ((indexes (sort (find-all 'numeric-index) #'< :key #'index-slug)))
81
+  (let ((indexes (sort (find-all 'numeric-index) #'< :key #'index-name)))
81
     (dolist (index indexes)
82
     (dolist (index indexes)
82
-      (let ((prev (1- (index-slug index)))
83
-            (next (1+ (index-slug index))))
83
+      (let ((prev (1- (index-name index)))
84
+            (next (1+ (index-name index))))
84
         (write-document index nil
85
         (write-document index nil
85
                         :prev (when (plusp prev) prev)
86
                         :prev (when (plusp prev) prev)
86
                         :next (when (<= next (length indexes)) next))))))
87
                         :next (when (<= next (length indexes)) next))))))

+ 1 - 1
themes/atom.tmpl

14
 
14
 
15
   {foreach $post in $content.content}
15
   {foreach $post in $content.content}
16
   <entry>
16
   <entry>
17
-    <link type="text/html" rel="alternate" href="{$config.domain}/{$post.path}"/>
17
+    <link type="text/html" rel="alternate" href="{$config.domain}/{$post.url}"/>
18
     <title>{$post.title}</title>
18
     <title>{$post.title}</title>
19
     <published>{$post.date}</published>
19
     <published>{$post.date}</published>
20
     <updated>{$post.date}</updated>
20
     <updated>{$post.date}</updated>

+ 5 - 5
themes/hyde/index.tmpl

4
 <h1 class="title">{$index.title}</h1>
4
 <h1 class="title">{$index.title}</h1>
5
 {foreach $obj in $index.content}
5
 {foreach $obj in $index.content}
6
   <div class="article-meta">
6
   <div class="article-meta">
7
-    <a class="article-title" href="{$config.domain}/{$obj.path}">{$obj.title}</a>
7
+    <a class="article-title" href="{$config.domain}/{$obj.url}">{$obj.title}</a>
8
     <div class="date"> posted on {$obj.date}</div>
8
     <div class="date"> posted on {$obj.date}</div>
9
     <div class="article">{$obj.text |noAutoescape}</div>
9
     <div class="article">{$obj.text |noAutoescape}</div>
10
   </div>
10
   </div>
11
 {/foreach}
11
 {/foreach}
12
 <div id="relative-nav">
12
 <div id="relative-nav">
13
-  {if $prev} <a href="{$config.domain}/{$prev.path}">Previous</a> {/if}
14
-  {if $next} <a href="{$config.domain}/{$next.path}">Next</a> {/if}
13
+  {if $prev} <a href="{$config.domain}/{$prev.url}">Previous</a> {/if}
14
+  {if $next} <a href="{$config.domain}/{$next.url}">Next</a> {/if}
15
 </div>
15
 </div>
16
 {if $tags}
16
 {if $tags}
17
 <div id="tagsoup">
17
 <div id="tagsoup">
18
   <p>This blog covers
18
   <p>This blog covers
19
     {foreach $tag in $tags}
19
     {foreach $tag in $tags}
20
-      <a href="{$config.domain}/${tag.path}">{$tag.name}</a>{nil}
20
+      <a href="{$config.domain}/${tag.url}">{$tag.name}</a>{nil}
21
       {if not isLast($tag)},{sp}{/if}
21
       {if not isLast($tag)},{sp}{/if}
22
     {/foreach}
22
     {/foreach}
23
 </div>
23
 </div>
26
 <div id="monthsoup">
26
 <div id="monthsoup">
27
   <p>View content from
27
   <p>View content from
28
     {foreach $month in $months}
28
     {foreach $month in $months}
29
-      <a href="{$config.domain}/{$month.path}">{$month}</a>{nil}
29
+      <a href="{$config.domain}/{$month.url}">{$month.name}</a>{nil}
30
       {if not isLast($month)},{sp}{/if}
30
       {if not isLast($month)},{sp}{/if}
31
     {/foreach}
31
     {/foreach}
32
 </div>
32
 </div>

+ 3 - 3
themes/hyde/post.tmpl

6
   <div class="tags">{\n}
6
   <div class="tags">{\n}
7
     {if $post.tags}
7
     {if $post.tags}
8
       Tagged as {foreach $tag in $post.tags}
8
       Tagged as {foreach $tag in $post.tags}
9
-        <a href="{$config.domain}/{$tag.path}">{$tag.name}</a>{nil}
9
+        <a href="{$config.domain}/{$tag.url}">{$tag.name}</a>{nil}
10
           {if not isLast($tag)},{sp}{/if}
10
           {if not isLast($tag)},{sp}{/if}
11
       {/foreach}
11
       {/foreach}
12
     {/if}
12
     {/if}
21
   {$post.text |noAutoescape}
21
   {$post.text |noAutoescape}
22
 </div>{\n}
22
 </div>{\n}
23
 <div class="relative-nav">{\n}
23
 <div class="relative-nav">{\n}
24
-  {if $prev} <a href="{$config.domain}/{$prev.path}">Previous</a><br> {/if}{\n}
25
-  {if $next} <a href="{$config.domain}/{$next.path}">Next</a><br> {/if}{\n}
24
+  {if $prev} <a href="{$config.domain}/{$prev.url}">Previous</a><br> {/if}{\n}
25
+  {if $next} <a href="{$config.domain}/{$next.url}">Next</a><br> {/if}{\n}
26
 </div>{\n}
26
 </div>{\n}
27
 {/template}
27
 {/template}

+ 3 - 3
themes/readable/index.tmpl

4
 <h1 class="page-header">{$index.title}</h1>
4
 <h1 class="page-header">{$index.title}</h1>
5
 {foreach $obj in $index.content}
5
 {foreach $obj in $index.content}
6
   <div class="row-fluid">
6
   <div class="row-fluid">
7
-    <h1><a href="{$config.domain}/{$obj.path}">{$obj.title}</a></h1>
7
+    <h1><a href="{$config.domain}/{$obj.url}">{$obj.title}</a></h1>
8
     <p class="date-posted">posted on {$obj.date}</p>
8
     <p class="date-posted">posted on {$obj.date}</p>
9
     {$obj.text |noAutoescape}
9
     {$obj.text |noAutoescape}
10
   </div>
10
   </div>
13
 <div class="row-fluid">
13
 <div class="row-fluid">
14
   <p>This blog covers
14
   <p>This blog covers
15
     {foreach $tag in $tags}
15
     {foreach $tag in $tags}
16
-      <a href="{$config.domain}/{$tag.path}">{$tag.name}</a>{nil}
16
+      <a href="{$config.domain}/{$tag.url}">{$tag.name}</a>{nil}
17
       {if not isLast($tag)},{sp}{/if}
17
       {if not isLast($tag)},{sp}{/if}
18
     {/foreach}
18
     {/foreach}
19
   </p>
19
   </p>
23
 <div class="row-fluid">
23
 <div class="row-fluid">
24
   <p>View content from
24
   <p>View content from
25
     {foreach $month in $months}
25
     {foreach $month in $months}
26
-      <a href="{$config.domain}/{$month.path}">{$month}</a>{nil}
26
+      <a href="{$config.domain}/{$month.url}">{$month.name}</a>{nil}
27
       {if not isLast($month)},{sp}{/if}
27
       {if not isLast($month)},{sp}{/if}
28
     {/foreach}
28
     {/foreach}
29
   </p>
29
   </p>

+ 3 - 3
themes/readable/post.tmpl

6
   <p>
6
   <p>
7
     {if $post.tags}
7
     {if $post.tags}
8
       Tagged as {foreach $tag in $post.tags}
8
       Tagged as {foreach $tag in $post.tags}
9
-        <a href="{$config.domain}/{$tag.path}">{$tag.name}</a>{nil}
9
+        <a href="{$config.domain}/{$tag.url}">{$tag.name}</a>{nil}
10
           {if not isLast($tag)},{sp}{/if}
10
           {if not isLast($tag)},{sp}{/if}
11
       {/foreach}
11
       {/foreach}
12
     {/if}
12
     {/if}
20
   {$post.text |noAutoescape}
20
   {$post.text |noAutoescape}
21
   
21
   
22
   <ul class="pager">
22
   <ul class="pager">
23
-    {if $prev}<li class="previous"><a href="{$config.domain}/{$prev.path}">&larr; Previous</a></li>{/if}{\n}
24
-    {if $next}<li class="next"><a href="{$config.domain}/{$next.path}">Next &rarr;</a></li>{/if}{\n}
23
+    {if $prev}<li class="previous"><a href="{$config.domain}/{$prev.url}">&larr; Previous</a></li>{/if}{\n}
24
+    {if $next}<li class="next"><a href="{$config.domain}/{$next.url}">Next &rarr;</a></li>{/if}{\n}
25
   </ul>
25
   </ul>
26
 </div>{\n}
26
 </div>{\n}
27
 {/template}
27
 {/template}

+ 2 - 2
themes/rss.tmpl

13
     {foreach $post in $content.content}
13
     {foreach $post in $content.content}
14
     <item>
14
     <item>
15
       <title>{$post.title}</title>
15
       <title>{$post.title}</title>
16
-      <link>{$config.domain}/{$post.path}</link>
16
+      <link>{$config.domain}/{$post.url}</link>
17
       <pubDate>{$post.date}</pubDate>
17
       <pubDate>{$post.date}</pubDate>
18
       <author>{$config.author}</author>
18
       <author>{$config.author}</author>
19
-      <guid isPermaLink="true">{$config.domain}/{$post.path}</guid>
19
+      <guid isPermaLink="true">{$config.domain}/{$post.url}</guid>
20
       {foreach $tag in $post.tags}
20
       {foreach $tag in $post.tags}
21
         <category><![CDATA[ {$tag.name |noAutoescape} ]]></category>
21
         <category><![CDATA[ {$tag.name |noAutoescape} ]]></category>
22
       {/foreach}
22
       {/foreach}