Finish the routing/slugs overhaul.
This commit is contained in:
parent
ab34400307
commit
ef378b9b56
9 changed files with 42 additions and 35 deletions
|
@ -4,7 +4,12 @@
|
||||||
|
|
||||||
(defclass tag ()
|
(defclass tag ()
|
||||||
((name :initarg :name :reader tag-name)
|
((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)
|
(defun make-tag (str)
|
||||||
"Takes a string and returns a TAG instance with a name and slug."
|
"Takes a string and returns a TAG instance with a name and slug."
|
||||||
|
|
|
@ -28,9 +28,15 @@
|
||||||
(defgeneric page-url (document)
|
(defgeneric page-url (document)
|
||||||
(:documentation "The relative URL to the DOCUMENT."))
|
(:documentation "The relative URL to the DOCUMENT."))
|
||||||
|
|
||||||
(defun compute-url (document unique-id)
|
(defgeneric render (document &key &allow-other-keys)
|
||||||
"Compute the relative URL for a DOCUMENT based on its UNIQUE-ID."
|
(:documentation "Render the given DOCUMENT to HTML."))
|
||||||
(let* ((class-name (class-name (class-of document)))
|
|
||||||
|
;; 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)))
|
(route (get-route class-name)))
|
||||||
(unless route
|
(unless route
|
||||||
(error "No routing method found for: ~A" class-name))
|
(error "No routing method found for: ~A" class-name))
|
||||||
|
@ -38,10 +44,9 @@
|
||||||
(type (or (pathname-type result) (page-ext *config*))))
|
(type (or (pathname-type result) (page-ext *config*))))
|
||||||
(make-pathname :type type :defaults result))))
|
(make-pathname :type type :defaults result))))
|
||||||
|
|
||||||
(defgeneric render (document &key &allow-other-keys)
|
(defun get-route (doc-type)
|
||||||
(:documentation "Render the given DOCUMENT to HTML."))
|
"Return the route format string for DOC-TYPE."
|
||||||
|
(second (assoc (make-keyword doc-type) (routing *config*))))
|
||||||
;; Helper Functions
|
|
||||||
|
|
||||||
(defun add-document (document)
|
(defun add-document (document)
|
||||||
"Add DOCUMENT to the in-memory database. Error if a matching entry is present."
|
"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))))
|
(url (namestring (page-url document))))
|
||||||
(write-file (rel-path (staging-dir *config*) url) html)))
|
(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)
|
(defun find-all (doc-type)
|
||||||
"Return a list of all instances of a given DOC-TYPE."
|
"Return a list of all instances of a given DOC-TYPE."
|
||||||
(loop for val being the hash-values in *site*
|
(loop for val being the hash-values in *site*
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
(defclass index ()
|
(defclass index ()
|
||||||
((url :initarg :url :reader page-url)
|
((url :initarg :url :reader page-url)
|
||||||
|
(name :initarg :name :reader index-name)
|
||||||
(title :initarg :title :reader title-of)
|
(title :initarg :title :reader title-of)
|
||||||
(content :initarg :content :reader index-content)))
|
(content :initarg :content :reader index-content)))
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@
|
||||||
|
|
||||||
(defun index-by-tag (tag content)
|
(defun index-by-tag (tag content)
|
||||||
"Return an index of all CONTENT matching the given TAG."
|
"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)
|
:content (remove-if-not (lambda (x) (tag-p tag x)) content)
|
||||||
:title (format nil "Content tagged ~a" (tag-name tag))))
|
:title (format nil "Content tagged ~a" (tag-name tag))))
|
||||||
|
|
||||||
|
@ -52,7 +53,7 @@
|
||||||
|
|
||||||
(defun index-by-month (month content)
|
(defun index-by-month (month content)
|
||||||
"Return an index of all CONTENT matching the given MONTH."
|
"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)
|
:content (remove-if-not (lambda (x) (month-p month x)) content)
|
||||||
:title (format nil "Content from ~a" month)))
|
:title (format nil "Content from ~a" month)))
|
||||||
|
|
||||||
|
@ -72,15 +73,15 @@
|
||||||
(defun index-by-n (i content)
|
(defun index-by-n (i content)
|
||||||
"Return the index for the Ith page of CONTENT in reverse chronological order."
|
"Return the index for the Ith page of CONTENT in reverse chronological order."
|
||||||
(let ((content (subseq content (* 10 i))))
|
(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)
|
:content (take-up-to 10 content)
|
||||||
:title "Recent Content")))
|
:title "Recent Content")))
|
||||||
|
|
||||||
(defmethod publish ((doc-type (eql (find-class 'numeric-index))))
|
(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)
|
(dolist (index indexes)
|
||||||
(let ((prev (1- (index-slug index)))
|
(let ((prev (1- (index-name index)))
|
||||||
(next (1+ (index-slug index))))
|
(next (1+ (index-name index))))
|
||||||
(write-document index nil
|
(write-document index nil
|
||||||
:prev (when (plusp prev) prev)
|
:prev (when (plusp prev) prev)
|
||||||
:next (when (<= next (length indexes)) next))))))
|
:next (when (<= next (length indexes)) next))))))
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
{foreach $post in $content.content}
|
{foreach $post in $content.content}
|
||||||
<entry>
|
<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>
|
<title>{$post.title}</title>
|
||||||
<published>{$post.date}</published>
|
<published>{$post.date}</published>
|
||||||
<updated>{$post.date}</updated>
|
<updated>{$post.date}</updated>
|
||||||
|
|
|
@ -4,20 +4,20 @@
|
||||||
<h1 class="title">{$index.title}</h1>
|
<h1 class="title">{$index.title}</h1>
|
||||||
{foreach $obj in $index.content}
|
{foreach $obj in $index.content}
|
||||||
<div class="article-meta">
|
<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="date"> posted on {$obj.date}</div>
|
||||||
<div class="article">{$obj.text |noAutoescape}</div>
|
<div class="article">{$obj.text |noAutoescape}</div>
|
||||||
</div>
|
</div>
|
||||||
{/foreach}
|
{/foreach}
|
||||||
<div id="relative-nav">
|
<div id="relative-nav">
|
||||||
{if $prev} <a href="{$config.domain}/{$prev.path}">Previous</a> {/if}
|
{if $prev} <a href="{$config.domain}/{$prev.url}">Previous</a> {/if}
|
||||||
{if $next} <a href="{$config.domain}/{$next.path}">Next</a> {/if}
|
{if $next} <a href="{$config.domain}/{$next.url}">Next</a> {/if}
|
||||||
</div>
|
</div>
|
||||||
{if $tags}
|
{if $tags}
|
||||||
<div id="tagsoup">
|
<div id="tagsoup">
|
||||||
<p>This blog covers
|
<p>This blog covers
|
||||||
{foreach $tag in $tags}
|
{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}
|
{if not isLast($tag)},{sp}{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
<div id="monthsoup">
|
<div id="monthsoup">
|
||||||
<p>View content from
|
<p>View content from
|
||||||
{foreach $month in $months}
|
{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}
|
{if not isLast($month)},{sp}{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="tags">{\n}
|
<div class="tags">{\n}
|
||||||
{if $post.tags}
|
{if $post.tags}
|
||||||
Tagged as {foreach $tag in $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}
|
{if not isLast($tag)},{sp}{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
{$post.text |noAutoescape}
|
{$post.text |noAutoescape}
|
||||||
</div>{\n}
|
</div>{\n}
|
||||||
<div class="relative-nav">{\n}
|
<div class="relative-nav">{\n}
|
||||||
{if $prev} <a href="{$config.domain}/{$prev.path}">Previous</a><br> {/if}{\n}
|
{if $prev} <a href="{$config.domain}/{$prev.url}">Previous</a><br> {/if}{\n}
|
||||||
{if $next} <a href="{$config.domain}/{$next.path}">Next</a><br> {/if}{\n}
|
{if $next} <a href="{$config.domain}/{$next.url}">Next</a><br> {/if}{\n}
|
||||||
</div>{\n}
|
</div>{\n}
|
||||||
{/template}
|
{/template}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<h1 class="page-header">{$index.title}</h1>
|
<h1 class="page-header">{$index.title}</h1>
|
||||||
{foreach $obj in $index.content}
|
{foreach $obj in $index.content}
|
||||||
<div class="row-fluid">
|
<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>
|
<p class="date-posted">posted on {$obj.date}</p>
|
||||||
{$obj.text |noAutoescape}
|
{$obj.text |noAutoescape}
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<p>This blog covers
|
<p>This blog covers
|
||||||
{foreach $tag in $tags}
|
{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}
|
{if not isLast($tag)},{sp}{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</p>
|
</p>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<p>View content from
|
<p>View content from
|
||||||
{foreach $month in $months}
|
{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}
|
{if not isLast($month)},{sp}{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<p>
|
<p>
|
||||||
{if $post.tags}
|
{if $post.tags}
|
||||||
Tagged as {foreach $tag in $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}
|
{if not isLast($tag)},{sp}{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -20,8 +20,8 @@
|
||||||
{$post.text |noAutoescape}
|
{$post.text |noAutoescape}
|
||||||
|
|
||||||
<ul class="pager">
|
<ul class="pager">
|
||||||
{if $prev}<li class="previous"><a href="{$config.domain}/{$prev.path}">← Previous</a></li>{/if}{\n}
|
{if $prev}<li class="previous"><a href="{$config.domain}/{$prev.url}">← Previous</a></li>{/if}{\n}
|
||||||
{if $next}<li class="next"><a href="{$config.domain}/{$next.path}">Next →</a></li>{/if}{\n}
|
{if $next}<li class="next"><a href="{$config.domain}/{$next.url}">Next →</a></li>{/if}{\n}
|
||||||
</ul>
|
</ul>
|
||||||
</div>{\n}
|
</div>{\n}
|
||||||
{/template}
|
{/template}
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
{foreach $post in $content.content}
|
{foreach $post in $content.content}
|
||||||
<item>
|
<item>
|
||||||
<title>{$post.title}</title>
|
<title>{$post.title}</title>
|
||||||
<link>{$config.domain}/{$post.path}</link>
|
<link>{$config.domain}/{$post.url}</link>
|
||||||
<pubDate>{$post.date}</pubDate>
|
<pubDate>{$post.date}</pubDate>
|
||||||
<author>{$config.author}</author>
|
<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}
|
{foreach $tag in $post.tags}
|
||||||
<category><![CDATA[ {$tag.name |noAutoescape} ]]></category>
|
<category><![CDATA[ {$tag.name |noAutoescape} ]]></category>
|
||||||
{/foreach}
|
{/foreach}
|
||||||
|
|
Loading…
Add table
Reference in a new issue