diff --git a/src/coleslaw.lisp b/src/coleslaw.lisp index f627279..d4a1ffc 100644 --- a/src/coleslaw.lisp +++ b/src/coleslaw.lisp @@ -12,14 +12,18 @@ (with-output-to-string (str) (3bmd:parse-string-and-print-to-stream text str))))) -(defgeneric page-path (object) - (:documentation "The path to store OBJECT at once rendered.")) +(defgeneric page-url (object) + (:documentation "The url to the object, without the domain")) -(defmethod page-path :around ((object t)) +(defmethod page-url :around ((object t)) (let ((result (call-next-method))) - (if (pathname-type result) - result - (make-pathname :type "html" :defaults result)))) + (namestring (if (pathname-type result) + result + (make-pathname :type "html" :defaults result))))) + +(defun page-path (object) + "The path to store OBJECT at once rendered." + (rel-path (staging-dir *config*) (page-url object))) (defun render-page (content &optional theme-fn &rest render-args) "Render the given CONTENT to disk using THEME-FN if supplied. @@ -51,6 +55,7 @@ Additional args to render CONTENT can be passed via RENDER-ARGS." (when (probe-file dir) (run-program "cp -R ~a ." dir))) (do-ctypes (publish ctype)) + (render-sitemap) (render-indices) (render-feeds (feeds *config*)))) diff --git a/src/content.lisp b/src/content.lisp index 19c1ec1..2e6f1e9 100644 --- a/src/content.lisp +++ b/src/content.lisp @@ -7,6 +7,9 @@ ((name :initform nil :initarg :name :accessor tag-name) (slug :initform nil :Initarg :slug :accessor tag-slug))) +(defmethod page-url ((object tag)) + (format nil "tag/~a" (tag-slug object))) + (defun make-tag (str) "Takes a string and returns a TAG instance with a name and slug." (let ((trimmed (string-trim " " str))) diff --git a/src/feeds.lisp b/src/feeds.lisp index 83ba3a0..75a2860 100644 --- a/src/feeds.lisp +++ b/src/feeds.lisp @@ -4,6 +4,20 @@ "Make a RFC1123 pubdate representing the current time." (local-time:format-rfc1123-timestring nil (local-time:now))) +(defun render-sitemap () + "Render sitemap.xml under document root" + (let* ((template (theme-fn :sitemap "feeds")) + (urls (cons "" ; for root url + (append (mapcar #'page-url (find-all 'post)) + (mapcar #'page-url (all-tags)) + (mapcar #'(lambda (m) + (format nil "date/~a.html" m)) + (all-months))))) + (index (make-instance 'url-index + :id "sitemap.xml" + :urls urls))) + (write-page (page-path index) (render-page index template)))) + (defun render-feed (posts &key path template tag) (flet ((first-10 (list) (subseq list 0 (min (length list) 10))) (tag-posts (list) (remove-if-not (lambda (x) (tag-p tag x)) list))) diff --git a/src/indices.lisp b/src/indices.lisp index 818b8a6..29a1e4a 100644 --- a/src/indices.lisp +++ b/src/indices.lisp @@ -16,15 +16,13 @@ (defclass tag-index (index) ()) (defclass date-index (index) ()) (defclass int-index (index) ()) +(defclass url-index (index) + ((urls :initform nil :initarg :urls :accessor urls))) -(defmethod page-path ((object index)) - (rel-path (staging-dir *config*) (index-id object))) -(defmethod page-path ((object tag-index)) - (rel-path (staging-dir *config*) "tag/~a" (index-id object))) -(defmethod page-path ((object date-index)) - (rel-path (staging-dir *config*) "date/~a" (index-id object))) -(defmethod page-path ((object int-index)) - (rel-path (staging-dir *config*) "~d" (index-id object))) +(defmethod page-url ((object index)) + (index-id object)) +(defmethod page-url ((object date-index)) + (format nil "date/~a" (index-id object))) (defun all-months () "Retrieve a list of all months with published content." @@ -40,7 +38,7 @@ (defun index-by-tag (tag content) "Return an index of all CONTENT matching the given TAG." - (make-instance 'tag-index :id (tag-slug tag) + (make-instance 'tag-index :id (page-url tag) :posts (remove-if-not (lambda (x) (tag-p tag x)) content) :title (format nil "Posts tagged ~a" (tag-name tag)))) @@ -54,7 +52,7 @@ "Return the index for the Ith page of CONTENT in reverse chronological order." (let* ((start (* step i)) (end (min (length content) (+ start step)))) - (make-instance 'int-index :id (1+ i) + (make-instance 'int-index :id (format nil "~d" (1+ i)) :posts (subseq content start end) :title "Recent Posts"))) diff --git a/src/posts.lisp b/src/posts.lisp index 5301ab1..50856b5 100644 --- a/src/posts.lisp +++ b/src/posts.lisp @@ -10,8 +10,8 @@ :prev prev :next next))) -(defmethod page-path ((object post)) - (rel-path (staging-dir *config*) "posts/~a" (content-slug object))) +(defmethod page-url ((object post)) + (rel-path "posts/~a" (content-slug object))) (defmethod initialize-instance :after ((object post) &key) (with-accessors ((title post-title) diff --git a/themes/sitemap.tmpl b/themes/sitemap.tmpl new file mode 100644 index 0000000..31d94bf --- /dev/null +++ b/themes/sitemap.tmpl @@ -0,0 +1,12 @@ +{namespace coleslaw.theme.feeds} + +{template sitemap} +{\n} + + {foreach $url in $content.urls} + + {$config.domain}{$url} + + {/foreach} + +{/template}