Posting To Jekyll Blog With Org Publish Meta

Remy Honig bio photo By Remy Honig Comment

1 Introduction

If I have to keep a blog then I want it to be integrated in my trusted org-mode setup. That way I can write and publish my posts straight from the place I keep my notes and tasks which should lower the threshold as much as possible to actually post regularly to my new blog. This is how it looks:

*** Posting to Jekyll Blog with Org-Publish-Meta         :_blog_:
:PROPERTIES:
:AUTHOR: remyhonig
:DATE: [2014-09-07 Sun]
:COMMENTS: true
:SHARING: true
:LAYOUT: post
:IMAGE: movabletype.jpg
:ID:       0236FFF2-B956-4682-B99E-219ADD97B197
:END:

***** Introduction
If I have to keep a blog then I want it to be integrated in my trusted
org-mode setup. That way I can write and publish my posts straight
from the place I keep my notes and tasks which should lower the
threshold as much as possible to actually post regularly to my new
blog.

******* Versions
These are the versions of the relevant packages and software used for
this post.

| emacs            | 24.4.50.1 |
| org-mode         | 8.2.7c    |
| org-publish-meta | 9aa9aa8b  |

1.0.1 Versions

These are the versions of the relevant packages and software used for this post.

emacs 24.4.50.1
org-mode 8.2.7c
org-publish-meta 9aa9aa8b

2 Alternatives

I already tried some approaches that I found right away by a search for "jekyll orgmode". These approaches had problems that I with my beginner knowledge of elisp could not solve or they did not match my requirements. I'll explain how they work and why they didn't for me.

2.1 Org-Jekyll by Juan Reyero

This is his description of the Org-jekyll package:

Extracts subtrees from your org-publish project files that have a :blog: keyword and an :on: property with a timestamp, and exports them to a subdirectory _posts of your project's publishing directory in the year-month-day-title.html format that Jekyll expects. Properties are passed over as yaml front-matter in the exported files. The title of the entry is the title of the subtree.

But he starts of by stating (Please note: I am no longer using org-jekyll.) which - I assume - also means the package is not maintained any longer.

The problem I had is that while running an export using the command org-jekyll-export-blog it crashed with an error. I guess this is due to a newer Orgmode version I'm using.

I liked this approach of the alternatives the best but I could not get it to work.

2.2 Org-mode to GitHub Pages with Jekyll by Cute-Jumper

Cute-Jumper's approach is to have one org file per post and this is reason enough for me to not use it. It means I have to manage a bunch of files outside of my existing and regularly used org files. Also I'll have to export them one-by-one. That means I have to keep track of what post is already published and what post is not. Too much bookkeeping for my taste.

2.3 Jekyll-Org by Eggcaker

Eggcakers's approach is to use a Ruby gem to convert org-mode files to Jekyll files. This moves the responsibility of the conversion from org-mode out of Emacs and into Jekyll. This also uses one file per post and has a deal-breaking disadvantage. It can only convert the most common org-mode syntax. It cannot evaluate source blocks and include it into the export. Considering I'm writing a developer blog this will be something I want for certain posts.

3 Solution

3.1 Org-Publish-Metadata by Iani

Iana's approach makes it possible to not only store the blog posts in a single org-mode file but also to store the publish project configuration in the same org-mode file!

I found out about it through Sacha Chua's tweet:

Not all was well tough. I had to perform some fixes for my particular setup.

3.2 So Simple Theme Support

I use the So Simple theme for Jekyll which has a front matter property named image. I edited org-pm.el to look for this org-mode property in addition to the standard Jekyll front matter it already supports.

diff -c /Users/rhonig/.autosaves/\!Users\!rhonig\!.emacs.d\!lisp\!org-publish-meta\!org-pm.el.\~1\~ /Users/rhonig/.emacs.d/lisp/org-publish-meta/org-pm.el
*** /Users/rhonig/.autosaves/!Users!rhonig!.emacs.d!lisp!org-publish-meta!org-pm.el.~1~ 2014-09-06 13:41:10.000000000 +0200
--- /Users/rhonig/.emacs.d/lisp/org-publish-meta/org-pm.el      2014-09-06 21:42:33.000000000 +0200
***************
*** 914,919 ****
--- 914,920 ----
               (permalink (plist-get section-plist :PERMALINK))
               (published (plist-get section-plist :PUBLISHED))
               (sharing (plist-get section-plist :SHARING))
+              (image (plist-get section-plist :IMAGE))
               (footer (plist-get section-plist :FOOTER)))
            (setq layout  (or layout (plist-get section-plist :LAYOUT)
                              (if date "blog" "default")))
***************
*** 937,942 ****
--- 939,945 ----
              (if comments (insert (format "comments: %s\n" comments)))
              (if sharing (insert (format "sharing: %s\n" sharing)))
              (if footer (insert (format "footer: %s\n" footer)))
+             (if image (insert (format "image: \n  feature: %s\n" image)))
              (when categories
                (insert "categories:\n")
                (dolist (category (split-string categories ", "))

Diff finished.  Sun Sep  7 11:19:35 2014

3.3 Bio Photo Broken

Because org-publish-metadata sets an Author property. The default site.owner is not used in the So Simple Theme which causes the bio photo to break.

I fixed this by adding an author in _data/authors.yml.

# Authors
remyhonig:
  name: Remy Honig
  avatar: bio-photo.jpg

I refer to that author in the properties of the post.

3.4 Grizzl autoloading

Grizzl is a dependency of org-publish-metadata.Installing grizzle is as easy as running M-x package-install grizzl but either org-publish-metadata cannot autoload it properly or grizzle isn't setup properly for autoloading (maybe Cask causes it, I'm not sure). I get a Required feature `grizzl-core' was not provided when running M-x org-pm-menu.

To solve this I load grizzl manually.

(add-to-list 'load-path "~/.emacs.d/lisp/org-publish-meta")
(add-hook 'org-mode-hook
        (lambda ()
          (load "grizzl-core.el")
          (load "grizzl-read.el")
          (require 'org-pm)))

3.5 Dark Themed Source Code

I use a dark theme in Emacs so the exported source code blocks also have this theme. To display them nicely I added some css to the site

.org-src-container, .example {
  background-color: #353535;
  color: #fff;
  margin-left: 5px;
  padding-left: 10px;
  padding-top: 2px;
  padding-bottom: 2px;
}

4 Workflow

This is the workflow I can now use to write posts.

4.1 Configuration

This will be needed only once.

4.1.1 Open an org file that will contain the publishing configuration.

This also triggers org-pm to load.

4.1.2 Create new publishing configuration

M-x org-pm-insert-new-project

*** org-publish projects                      :PROJECT_DEFS:
***** blog
:PROPERTIES:
:ID:       96AC22C1-B805-46D5-B6FC-C2B9C6C05A12
:END:
******* body-only t
******* publish-to-jekyll t
******* default-layout "page"
******* base-directory "~/blog/org-pm/"
******* base-extension "org"
******* recursive t
******* publishing-directory "~/blog/_posts/blog/"
******* publishing-function 'org-html-publish-to-html
******* headline-levels 4
******* section-numbers nil
******* with-toc t
******* with-author t
******* with-creator t
******* with-emphasize t
******* with-sub-superscript nil
******* with-tables t
******* with-tags t
******* with-tasks t
******* with-todo-keywords nil
******* with-latex t
******* with-drawers nil
******* toc-heading "Contents"
******* static-base-directory "~/blog/org-pm/images/"
******* static-publishing-directory "~/blog/images/"
******* static-base-extension "css\\|js\\|less\\|scss\\|php\\|rb\\|py\\|pdf\\|jpg\\|gif\\|png"
******* static-publishing-function 'org-publish-attachment
******* static-recursive t...

4.1.3 Lower the level of the new heading

For me the indentation of the new configuration heading was a level to high. Maybe this is caused by the #+STARTUP: odd org config, maybe by me. I don't really care about this as this step will only be taken once. Failing to do this will cause the org-publish-metada to not find the configuration under the right header. See the org-publish-metadata tutorial for details about the form of the configuration.

4.2 Posting

For creating a post.

posting_workflow.png

4.2.1 Create post

Creating a post by simply adding a new heading and giving it the _blog_ tag in this case. The tag name depends on the name of the publishing configuration heading and must be wrapped in underscores.

4.2.2 Add a date

When adding a date, use an inactive timestamp [2014-01-01] as an active timestamp <2014-01-01> leads to a double date in the exported post's filename. 2014-01-01-2014-01-01-hello.html instead of 2014-01-01-hello.html.

4.2.3 Export all posts

M-x org-pm-export. You might need to expand all headings if you get an error message when executing this command with S-tab S-tab S-tab.

4.2.4 Edit properties

After the export I add the appropriate properties by copying them from the example post at the top. This could be done even faster by using yasnippet.

4.2.5 Generate and preview the Jekyll site

jekyll serve

4.2.6 Commit and push

cd ~/blog/_posts && git add . && git commit -m "New post" && git push origin