From 273d4ad6a7e9b8e1b86a227d5f882392b9cea9cc Mon Sep 17 00:00:00 2001 From: Do Nhat Minh Date: Fri, 26 Apr 2013 10:03:04 +0800 Subject: [PATCH 1/9] added sitemap generation --- src/coleslaw.lisp | 17 +++++++++++------ src/content.lisp | 3 +++ src/feeds.lisp | 14 ++++++++++++++ src/indices.lisp | 18 ++++++++---------- src/posts.lisp | 4 ++-- themes/sitemap.tmpl | 12 ++++++++++++ 6 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 themes/sitemap.tmpl 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} From 67594d4bca6785c6ad2a29114b14d208b409c060 Mon Sep 17 00:00:00 2001 From: Do Nhat Minh Date: Fri, 26 Apr 2013 10:15:41 +0800 Subject: [PATCH 2/9] fix missing slash in url in sitemap.tmpl --- themes/sitemap.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/sitemap.tmpl b/themes/sitemap.tmpl index 31d94bf..d9b5f91 100644 --- a/themes/sitemap.tmpl +++ b/themes/sitemap.tmpl @@ -5,7 +5,7 @@ {foreach $url in $content.urls} - {$config.domain}{$url} + {$config.domain}/{$url} {/foreach} From 99f57f35136d6f22e2390050645018ba9f43e18d Mon Sep 17 00:00:00 2001 From: Do Nhat Minh Date: Fri, 26 Apr 2013 10:29:32 +0800 Subject: [PATCH 3/9] added lastmod for each url in sitemap.xml --- src/indices.lisp | 6 +++++- themes/sitemap.tmpl | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/indices.lisp b/src/indices.lisp index 29a1e4a..65732cd 100644 --- a/src/indices.lisp +++ b/src/indices.lisp @@ -17,7 +17,11 @@ (defclass date-index (index) ()) (defclass int-index (index) ()) (defclass url-index (index) - ((urls :initform nil :initarg :urls :accessor urls))) + ((urls :initform nil :initarg :urls :accessor urls) + (pubdate :initform (local-time:format-rfc3339-timestring nil + (local-time:now)) + :initarg :pubdate + :accessor index-pubdate))) (defmethod page-url ((object index)) (index-id object)) diff --git a/themes/sitemap.tmpl b/themes/sitemap.tmpl index d9b5f91..4833858 100644 --- a/themes/sitemap.tmpl +++ b/themes/sitemap.tmpl @@ -6,6 +6,7 @@ {foreach $url in $content.urls} {$config.domain}/{$url} + {$content.pubdate} {/foreach} From a3ed5b7719ae652f7ee33000a1c60d0f6f41d68e Mon Sep 17 00:00:00 2001 From: Do Nhat Minh Date: Fri, 26 Apr 2013 22:14:57 +0800 Subject: [PATCH 4/9] added robots.txt generation --- src/feeds.lisp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/feeds.lisp b/src/feeds.lisp index 75a2860..6650f6c 100644 --- a/src/feeds.lisp +++ b/src/feeds.lisp @@ -7,15 +7,24 @@ (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))))) + (urls (append '("" "robots.txt") ; empty string is for root url + (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))) + (with-open-file (robots (rel-path (staging-dir *config*) "robots.txt") + :direction :output + :if-exists :supersede) + (format robots + "User-agent: *~%Disallow: ~2%Sitemap: ~a~%" + (concatenate 'string + (domain *config*) + "/" + (page-url index)))) (write-page (page-path index) (render-page index template)))) (defun render-feed (posts &key path template tag) From edcd1022abafdfc67ae6089f1b2d66e924e0a3a4 Mon Sep 17 00:00:00 2001 From: Do Nhat Minh Date: Fri, 26 Apr 2013 22:26:41 +0800 Subject: [PATCH 5/9] add documentation --- src/feeds.lisp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/feeds.lisp b/src/feeds.lisp index 6650f6c..e137beb 100644 --- a/src/feeds.lisp +++ b/src/feeds.lisp @@ -5,7 +5,7 @@ (local-time:format-rfc1123-timestring nil (local-time:now))) (defun render-sitemap () - "Render sitemap.xml under document root" + "Render sitemap.xml and write robots.txt under document root" (let* ((template (theme-fn :sitemap "feeds")) (urls (append '("" "robots.txt") ; empty string is for root url (mapcar #'page-url (find-all 'post)) From 488191b23797ffab1f4aed9b854805148f9eec18 Mon Sep 17 00:00:00 2001 From: Do Nhat Minh Date: Sat, 27 Apr 2013 02:13:56 +0800 Subject: [PATCH 6/9] move sitemap to plugins --- src/coleslaw.lisp | 1 - src/content.lisp | 3 --- src/feeds.lisp | 23 ----------------------- src/indices.lisp | 14 ++++++-------- themes/sitemap.tmpl | 6 +++--- 5 files changed, 9 insertions(+), 38 deletions(-) diff --git a/src/coleslaw.lisp b/src/coleslaw.lisp index d4a1ffc..25c6b73 100644 --- a/src/coleslaw.lisp +++ b/src/coleslaw.lisp @@ -55,7 +55,6 @@ 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 2e6f1e9..19c1ec1 100644 --- a/src/content.lisp +++ b/src/content.lisp @@ -7,9 +7,6 @@ ((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 e137beb..83ba3a0 100644 --- a/src/feeds.lisp +++ b/src/feeds.lisp @@ -4,29 +4,6 @@ "Make a RFC1123 pubdate representing the current time." (local-time:format-rfc1123-timestring nil (local-time:now))) -(defun render-sitemap () - "Render sitemap.xml and write robots.txt under document root" - (let* ((template (theme-fn :sitemap "feeds")) - (urls (append '("" "robots.txt") ; empty string is for root url - (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))) - (with-open-file (robots (rel-path (staging-dir *config*) "robots.txt") - :direction :output - :if-exists :supersede) - (format robots - "User-agent: *~%Disallow: ~2%Sitemap: ~a~%" - (concatenate 'string - (domain *config*) - "/" - (page-url index)))) - (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 65732cd..64ac6c6 100644 --- a/src/indices.lisp +++ b/src/indices.lisp @@ -16,17 +16,15 @@ (defclass tag-index (index) ()) (defclass date-index (index) ()) (defclass int-index (index) ()) -(defclass url-index (index) - ((urls :initform nil :initarg :urls :accessor urls) - (pubdate :initform (local-time:format-rfc3339-timestring nil - (local-time:now)) - :initarg :pubdate - :accessor index-pubdate))) (defmethod page-url ((object index)) (index-id object)) +(defmethod page-url ((object tag-index)) + (format nil "tags/~a" (index-id object))) (defmethod page-url ((object date-index)) (format nil "date/~a" (index-id object))) +(defmethod page-url ((object int-index)) + (format nil "~d" (index-id object))) (defun all-months () "Retrieve a list of all months with published content." @@ -42,7 +40,7 @@ (defun index-by-tag (tag content) "Return an index of all CONTENT matching the given TAG." - (make-instance 'tag-index :id (page-url tag) + (make-instance 'tag-index :id (tag-slug tag) :posts (remove-if-not (lambda (x) (tag-p tag x)) content) :title (format nil "Posts tagged ~a" (tag-name tag)))) @@ -56,7 +54,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 (format nil "~d" (1+ i)) + (make-instance 'int-index :id (1+ i) :posts (subseq content start end) :title "Recent Posts"))) diff --git a/themes/sitemap.tmpl b/themes/sitemap.tmpl index 4833858..89b77bb 100644 --- a/themes/sitemap.tmpl +++ b/themes/sitemap.tmpl @@ -3,10 +3,10 @@ {template sitemap} {\n} - {foreach $url in $content.urls} + {foreach $url in $urls} - {$config.domain}/{$url} - {$content.pubdate} + {$domain}/{$url} + {$pubdate} {/foreach} From e28729b0de1cf5ed95eccc6d668efbfab5ff84e7 Mon Sep 17 00:00:00 2001 From: Do Nhat Minh Date: Sat, 27 Apr 2013 02:16:22 +0800 Subject: [PATCH 7/9] add sitemap.lisp in plugins --- plugins/sitemap.lisp | 29 +++++++++++++++++++++++++++++ src/indices.lisp | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 plugins/sitemap.lisp diff --git a/plugins/sitemap.lisp b/plugins/sitemap.lisp new file mode 100644 index 0000000..ef8cbaa --- /dev/null +++ b/plugins/sitemap.lisp @@ -0,0 +1,29 @@ +(defpackage :coleslaw-sitemap + (:use :cl) + (:import-from :coleslaw + #:*config* + #:deploy + #:domain + #:find-all + #:page-url + #:rel-path + #:staging-dir + #:theme-fn + #:write-page) + (:export #:enable)) + +(in-package :coleslaw-sitemap) + +(defmethod deploy :before (staging) + "Render sitemap.xml under document root" + (let* ((urls (append '("" "sitemap.xml") ; empty string is for root url + (mapcar #'page-url (find-all 'coleslaw:post))))) + (write-page (rel-path (staging-dir *config*) "sitemap.xml") + (funcall (theme-fn :sitemap "feeds") + (list :domain (domain *config*) + :urls urls + :pubdate (local-time:format-rfc3339-timestring + nil + (local-time:now))))))) + +(defun enable ()) diff --git a/src/indices.lisp b/src/indices.lisp index 64ac6c6..a28ef50 100644 --- a/src/indices.lisp +++ b/src/indices.lisp @@ -20,7 +20,7 @@ (defmethod page-url ((object index)) (index-id object)) (defmethod page-url ((object tag-index)) - (format nil "tags/~a" (index-id object))) + (format nil "tag/~a" (index-id object))) (defmethod page-url ((object date-index)) (format nil "date/~a" (index-id object))) (defmethod page-url ((object int-index)) From 5dac19c696cb3314bf27a57c7cf4db09e3918af3 Mon Sep 17 00:00:00 2001 From: Do Nhat Minh Date: Sat, 27 Apr 2013 02:20:08 +0800 Subject: [PATCH 8/9] consistency --- src/posts.lisp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/posts.lisp b/src/posts.lisp index 50856b5..4962054 100644 --- a/src/posts.lisp +++ b/src/posts.lisp @@ -11,7 +11,7 @@ :next next))) (defmethod page-url ((object post)) - (rel-path "posts/~a" (content-slug object))) + (format nil "posts/~a" (content-slug object))) (defmethod initialize-instance :after ((object post) &key) (with-accessors ((title post-title) From dfcb669d686af82cb5bbb783e199e1aab72f183a Mon Sep 17 00:00:00 2001 From: Do Nhat Minh Date: Sat, 27 Apr 2013 02:40:53 +0800 Subject: [PATCH 9/9] added doc for sitemap plugin --- docs/plugin-use.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/plugin-use.md b/docs/plugin-use.md index 2a380e3..025112a 100644 --- a/docs/plugin-use.md +++ b/docs/plugin-use.md @@ -55,3 +55,9 @@ **Description**: Import blog posts from Wordpress using their export tool. Blog entries will be read from the XML and converted into .post files. Afterwards the XML file will be deleted to prevent reimporting. Optionally an ```:output``` argument may be supplied to the plugin. If provided, it should be a directory in which to store the .post files. Otherwise, the value of ```:repo``` in your .coleslawrc will be used. **Example**: ```(import :filepath "/home/redline/redlinernotes-export.timestamp.xml" :output "/home/redlinernotes/blog/")``` + +## Sitemap generator + +**Description**: this plugin generates a sitemap.xml under the page root, which is useful if you want google to crawl your site. + +**Example**: ```(sitemap)```