Blogging from your text editor with orgmode and middleman
Table of Contents
Before setting up this blog, I used emacs but had never really written any lisp. This post details some serious yak shaving, but it did give me a good excuse to write some lisp and some shitty web design.
I'm not suggesting that this is the most efficient way to publish words and pictures on the internet. This is simply a description of how I'm doing it at the moment.
Trying this at home
The workflow above is something of a simplification. The real approach is more like this:
Creating a new post
I use org capture templates to kick off a new post. My capture templates variable looks like this:
(setq org-capture-templates '(("t" "Todo (unsorted)" entry (file+headline org-default-notes-file "Unsorted Tasks") "* TODO %?\n %i\n %a") ("b" "Blog draft" entry (file (choose-new-post "~/site/org/blog/")) "\n* TODO %?\n") ("p" "Project Entry" entry (file (choose-project-file)) "* TODO %?\n %i\n %a\n\n")))
Where I have a function 'choose-new-post which looks like this:
(defun choose-blog-file (base-path) "Finds the project file, creating one if it doesn't already exist" (let* ((date (org-read-date "" 'totime nil nil (current-time) "")) ;;(date) (title (read-string "Post title: ")) ;;(title) (url-title (replace-regexp-in-string "\s+" "-" title)) ;;(url) (path (format "%s/%s/%s/index.org" base-path (format-time-string "%Y/%m/%d") url-title))) ;;(path) (make-directory (file-name-directory path) t) (append-to-file (format "#+begin_html\n---\ntitle: %s\ntags: \ndescription: \n---\n#+end_html\n\n" title) nil path) path))
- sets a variable 'date' to a day of the user's chossing.
- gets a working title and set the variable 'title'.
- gets a url-friendly title by replacing spaces with "-".
- composes a path based on the base-path given.
The 'Todo' and 'Project Entry' templates are for other uses, but the 'Blog draft' entry ensures that pressing "Ctrl-C, C" ("C-c c" in emacs-speak) and then "b" takes me directly to a new file (the filename returned by the function 'choose-new-post')
Somewhere within your emacs configuration, you need to set the variable 'org-publish-project-alist' to something like:
(setq org-publish-project-alist '(( "blog" :base-directory "~/site/org/blog/" ;;(base-dir) :base-extension "org" ;;(base-ext) :publishing-directory "~/site/source/blog/" ;;(pub-dir) :recursive t ;;(rec) :body-only t ;;(body) :html-extension "html.erb" ;;(html-ext) :publish-function org-publish-org-to-html) ( "blog-static" ;;(static) :base-directory "~/site/org/blog/" :base-extension "png\\|jpg\\|gif" :publishing-directory "~/site/source/blog/" :recursive t :publish-function org-publish-attachment) ("whole" :components ("blog" "blog-static")))) ;;(whole)
The publish directory is the source directory of a Middleman application, so the resulting html (or html.erb) is used as the content for the static site.
I also configure a shortcut to publish both the static resources and the org files with only one command.
The org-publish will render each of the org files in the base directory to html. It will generate a table of contents and wrap all of the source code in appropriate tags (see the source of the code block above).
Middleman has an excellent blogging plugin, but it manages the directory structure itself. It is useful if your posts contain no attachments. If you have posts that contain relative links to external files (mine do), the links will break when middleman constructs the new site structure.
I'm using the same setup for my lab notebook which includes lots of attached files, so I had to roll my own stipped-back version.
All of the lifting is done by the classes in orgblog.rb. A writeup of the Middleman configuration will have to wait for another time.