Finish the routing/slugs overhaul.

This commit is contained in:
Brit Butler 2014-08-27 14:08:48 -04:00
parent ab34400307
commit ef378b9b56
9 changed files with 42 additions and 35 deletions

View file

@ -4,7 +4,12 @@
(defclass tag ()
((name :initarg :name :reader tag-name)
(slug :initarg :slug :reader tag-slug)))
(slug :initarg :slug :reader tag-slug)
(url :initarg :url)))
(defmethod initialize-instance :after ((tag tag) &key)
(with-slots (url slug) tag
(setf url (compute-url nil slug 'tag-index))))
(defun make-tag (str)
"Takes a string and returns a TAG instance with a name and slug."

View file

@ -28,9 +28,15 @@
(defgeneric page-url (document)
(:documentation "The relative URL to the DOCUMENT."))
(defun compute-url (document unique-id)
"Compute the relative URL for a DOCUMENT based on its UNIQUE-ID."
(let* ((class-name (class-name (class-of document)))
(defgeneric render (document &key &allow-other-keys)
(:documentation "Render the given DOCUMENT to HTML."))
;; Helper Functions
(defun compute-url (document unique-id &optional class)
"Compute the relative URL for a DOCUMENT based on its UNIQUE-ID. If CLASS
is provided, it overrides the route used."
(let* ((class-name (or class (class-name (class-of document))))
(route (get-route class-name)))
(unless route
(error "No routing method found for: ~A" class-name))
@ -38,10 +44,9 @@
(type (or (pathname-type result) (page-ext *config*))))
(make-pathname :type type :defaults result))))
(defgeneric render (document &key &allow-other-keys)
(:documentation "Render the given DOCUMENT to HTML."))
;; Helper Functions
(defun get-route (doc-type)
"Return the route format string for DOC-TYPE."
(second (assoc (make-keyword doc-type) (routing *config*))))
(defun add-document (document)
"Add DOCUMENT to the in-memory database. Error if a matching entry is present."
@ -63,10 +68,6 @@ use it as the template passing any RENDER-ARGS."
(url (namestring (page-url document))))
(write-file (rel-path (staging-dir *config*) url) html)))
(defun get-route (doc-type)
"Return the route format string for DOC-TYPE."
(second (assoc (make-keyword doc-type) (routing *config*))))
(defun find-all (doc-type)
"Return a list of all instances of a given DOC-TYPE."
(loop for val being the hash-values in *site*

View file

@ -7,6 +7,7 @@
(defclass index ()
((url :initarg :url :reader page-url)
(name :initarg :name :reader index-name)
(title :initarg :title :reader title-of)
(content :initarg :content :reader index-content)))
@ -33,7 +34,7 @@
(defun index-by-tag (tag content)
"Return an index of all CONTENT matching the given TAG."
(make-instance 'tag-index :slug (tag-slug tag)
(make-instance 'tag-index :slug (tag-slug tag) :name (tag-name tag)
:content (remove-if-not (lambda (x) (tag-p tag x)) content)
:title (format nil "Content tagged ~a" (tag-name tag))))
@ -52,7 +53,7 @@
(defun index-by-month (month content)
"Return an index of all CONTENT matching the given MONTH."
(make-instance 'month-index :slug month
(make-instance 'month-index :slug month :name month
:content (remove-if-not (lambda (x) (month-p month x)) content)
:title (format nil "Content from ~a" month)))
@ -72,15 +73,15 @@
(defun index-by-n (i content)
"Return the index for the Ith page of CONTENT in reverse chronological order."
(let ((content (subseq content (* 10 i))))
(make-instance 'numeric-index :slug (1+ i)
(make-instance 'numeric-index :slug (1+ i) :name (1+ i)
:content (take-up-to 10 content)
:title "Recent Content")))
(defmethod publish ((doc-type (eql (find-class 'numeric-index))))
(let ((indexes (sort (find-all 'numeric-index) #'< :key #'index-slug)))
(let ((indexes (sort (find-all 'numeric-index) #'< :key #'index-name)))
(dolist (index indexes)
(let ((prev (1- (index-slug index)))
(next (1+ (index-slug index))))
(let ((prev (1- (index-name index)))
(next (1+ (index-name index))))
(write-document index nil
:prev (when (plusp prev) prev)
:next (when (<= next (length indexes)) next))))))

View file

@ -14,7 +14,7 @@
{foreach $post in $content.content}
<entry>
<link type="text/html" rel="alternate" href="{$config.domain}/{$post.path}"/>
<link type="text/html" rel="alternate" href="{$config.domain}/{$post.url}"/>
<title>{$post.title}</title>
<published>{$post.date}</published>
<updated>{$post.date}</updated>

View file

@ -4,20 +4,20 @@
<h1 class="title">{$index.title}</h1>
{foreach $obj in $index.content}
<div class="article-meta">
<a class="article-title" href="{$config.domain}/{$obj.path}">{$obj.title}</a>
<a class="article-title" href="{$config.domain}/{$obj.url}">{$obj.title}</a>
<div class="date"> posted on {$obj.date}</div>
<div class="article">{$obj.text |noAutoescape}</div>
</div>
{/foreach}
<div id="relative-nav">
{if $prev} <a href="{$config.domain}/{$prev.path}">Previous</a> {/if}
{if $next} <a href="{$config.domain}/{$next.path}">Next</a> {/if}
{if $prev} <a href="{$config.domain}/{$prev.url}">Previous</a> {/if}
{if $next} <a href="{$config.domain}/{$next.url}">Next</a> {/if}
</div>
{if $tags}
<div id="tagsoup">
<p>This blog covers
{foreach $tag in $tags}
<a href="{$config.domain}/${tag.path}">{$tag.name}</a>{nil}
<a href="{$config.domain}/${tag.url}">{$tag.name}</a>{nil}
{if not isLast($tag)},{sp}{/if}
{/foreach}
</div>
@ -26,7 +26,7 @@
<div id="monthsoup">
<p>View content from
{foreach $month in $months}
<a href="{$config.domain}/{$month.path}">{$month}</a>{nil}
<a href="{$config.domain}/{$month.url}">{$month.name}</a>{nil}
{if not isLast($month)},{sp}{/if}
{/foreach}
</div>

View file

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

View file

@ -4,7 +4,7 @@
<h1 class="page-header">{$index.title}</h1>
{foreach $obj in $index.content}
<div class="row-fluid">
<h1><a href="{$config.domain}/{$obj.path}">{$obj.title}</a></h1>
<h1><a href="{$config.domain}/{$obj.url}">{$obj.title}</a></h1>
<p class="date-posted">posted on {$obj.date}</p>
{$obj.text |noAutoescape}
</div>
@ -13,7 +13,7 @@
<div class="row-fluid">
<p>This blog covers
{foreach $tag in $tags}
<a href="{$config.domain}/{$tag.path}">{$tag.name}</a>{nil}
<a href="{$config.domain}/{$tag.url}">{$tag.name}</a>{nil}
{if not isLast($tag)},{sp}{/if}
{/foreach}
</p>
@ -23,7 +23,7 @@
<div class="row-fluid">
<p>View content from
{foreach $month in $months}
<a href="{$config.domain}/{$month.path}">{$month}</a>{nil}
<a href="{$config.domain}/{$month.url}">{$month.name}</a>{nil}
{if not isLast($month)},{sp}{/if}
{/foreach}
</p>

View file

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

View file

@ -13,10 +13,10 @@
{foreach $post in $content.content}
<item>
<title>{$post.title}</title>
<link>{$config.domain}/{$post.path}</link>
<link>{$config.domain}/{$post.url}</link>
<pubDate>{$post.date}</pubDate>
<author>{$config.author}</author>
<guid isPermaLink="true">{$config.domain}/{$post.path}</guid>
<guid isPermaLink="true">{$config.domain}/{$post.url}</guid>
{foreach $tag in $post.tags}
<category><![CDATA[ {$tag.name |noAutoescape} ]]></category>
{/foreach}