Update the wordpress importer and make deploy a bit safer.

This commit is contained in:
Brit Butler 2012-08-20 20:17:30 -04:00
parent 4e27bcf8cd
commit 4b61c1115b
2 changed files with 35 additions and 63 deletions

View file

@ -1,19 +1,19 @@
(eval-when (:compile-toplevel) (eval-when (:load-toplevel)
(ql:quickload '(cxml cl-ppcre))) (ql:quickload '(coleslaw cxml cl-ppcre local-time)))
(defpackage :coleslaw-import (defpackage :coleslaw-import
(:use :cl :coleslaw :cxml) (:use :cl :cxml)
(:import-from :coleslaw #:slugify
#:load-config
#:*config*
#:repo)
(:import-from :local-time #:+short-month-names+ (:import-from :local-time #:+short-month-names+
#:encode-timestamp) #:encode-timestamp)
(:import-from :cl-ppcre #:regex-replace-all)) (:import-from :cl-ppcre #:regex-replace-all))
(in-package :coleslaw-import) (in-package :coleslaw-import)
(defgeneric import-post (service post &key static-p) (defun import-post (post)
(:documentation "Import POST into *storage*. The method to construct the POST
object is determined by SERVICE."))
(defmethod import-post ((service (eql :wordpress)) post &key static-p)
(labels ((nodes (name) (labels ((nodes (name)
(dom:get-elements-by-tag-name post name)) (dom:get-elements-by-tag-name post name))
(value (node) (value (node)
@ -23,61 +23,32 @@ object is determined by SERVICE."))
(let ((nodes (nodes name))) (let ((nodes (nodes name)))
(if (string= "category" name) (if (string= "category" name)
(loop for node across nodes collecting (value node)) (loop for node across nodes collecting (value node))
(when (plusp (length nodes)) (value (elt nodes 0)))))) (when (plusp (length nodes)) (value (elt nodes 0)))))))
(public-p () (when (and (string= "publish" (node-val "wp:status")) ; is it public?
(string= "publish" (node-val "wp:status"))) (string= "post" (node-val "wp:post_type"))) ; is it a post?
(post-p () (export-post (node-val "title") (node-val "category") (node-val "pubDate")
(string= "post" (node-val "wp:post_type")))
(make-timestamp (pubdate)
(let* ((date (cl-ppcre:split " " (subseq pubdate 5)))
(time (cl-ppcre:split ":" (fourth date))))
(encode-timestamp 0
(parse-integer (third time))
(parse-integer (second time))
(parse-integer (first time))
(parse-integer (first date))
(position (second date) +short-month-names+
:test #'string=)
(parse-integer (third date))))))
(when (and (public-p)
(post-p))
(let ((new-post (make-post (node-val "title")
(node-val "category")
(make-timestamp (node-val "pubDate"))
(regex-replace-all (string #\Newline) (regex-replace-all (string #\Newline)
(node-val "content:encoded") (node-val "content:encoded") "<br>")
"<br>") (format nil "~a.post" (slugify (node-val "title")))))))
:aliases (parse-integer (node-val "wp:post_id"))))
(comments (nodes "wp:comment")))
(add-post new-post (post-id new-post))
(when static-p
(ensure-directories-exist coleslaw::*input-dir*)
(export-post new-post))))))
(defmethod export-post (post) (defun export-post (title tags date content path)
(let ((filepath (merge-pathnames (format nil "~5,'0d-~a.post" (with-open-file (out (merge-pathnames path (repo *config*))
(post-id post) :direction :output
(coleslaw::escape (post-title post))) :if-exists :supersede
coleslaw::*input-dir*))) :if-does-not-exist :create)
(with-open-file (out filepath :direction :output
:if-exists :supersede :if-does-not-exist :create)
;; TODO: What other data/metadata should we write out? ;; TODO: What other data/metadata should we write out?
(format out ";;;;;~%") (format out ";;;;;~%")
(format out "title: ~A~%" (post-title post)) (format out "title: ~A~%" title)
(format out "tags: ~A~%" (coleslaw::pretty-list (post-tags post))) (format out "tags: ~A~%" (format nil "~{~A, ~}" tags))
(format out "date: ~A~%" (coleslaw::year-month (post-date post))) (format out "date: ~A~%" date)
(format out "type: html~%") ; post format: html, md, rst, etc
(format out ";;;;;~%") (format out ";;;;;~%")
(format out "~A~%" (post-content post))))) (format out "~A~%" (post-content post))))
(defgeneric import-posts (service filepath &key static-p) (defun import-posts (filepath)
(:documentation "Import the posts (and potentially comments or other data)
from FILEPATH, converting them to appropriate coleslaw objects and inserting
them into *storage*. The method to parse the file is determined by SERVICE.
If STATIC-P is true, the posts will also be written into *.html files in
*input-dir*."))
(defmethod import-posts ((service (eql :wordpress)) filepath &key static-p)
(let* ((xml (cxml:parse-file filepath (cxml-dom:make-dom-builder))) (let* ((xml (cxml:parse-file filepath (cxml-dom:make-dom-builder)))
(posts (dom:get-elements-by-tag-name xml "item"))) (posts (dom:get-elements-by-tag-name xml "item")))
(loop for post across posts do (load-config)
(import-post service post :static-p static-p)))) (ensure-directories-exist (repo *config*))
(dolist (post posts)
(import-post post))))

View file

@ -51,7 +51,8 @@ on files that match the given extension."
(let ((css-dir (app-path "themes/~a/css/" (theme *config*))) (let ((css-dir (app-path "themes/~a/css/" (theme *config*)))
(static-dir (merge-pathnames "static/" (repo *config*)))) (static-dir (merge-pathnames "static/" (repo *config*))))
(dolist (dir (list css-dir static-dir)) (dolist (dir (list css-dir static-dir))
(run-program "cp" `("-R" ,dir ".")))) (when (probe-file dir)
(run-program "cp" `("-R" ,dir ".")))))
(render-posts) (render-posts)
(render-indices)) (render-indices))
(deploy staging) (deploy staging)