24 May 2013

Lately, I've become enamoured of writing things in text files and avoiding proprietary formats as much as possible, but I still like to be able to render the text into nicer formats for printing (PDF) or sharing (HTML). There are many lightweight mark-up languages that support this, markdown and friends, but I prefer Emacs org-mode for its power with including source code, literate programming, strong LaTeX support, and table editing.

Not surprisingly, org-mode has a powerful publishing facility that, when combined with Jekyll and GitHub, can produce pretty a pretty reasonable blog with categories, tags, archives, and comments, all separate from the content.

Setting up Publishing and Source locations

Because the source material in org-mode can contain comments, code-snippets you don't want published, or other content intended for the author and collaborators, I keep the source separate from the publishing location.

Publishing: Jekyll and github.io

Although we won't use this content for a little while, it's important to make sure this works before getting too far. Also, the initial push of content to GitHub can take a little while to be recognized by GitHub, so this will give GitHub some time while we do other things.

To set up a username.github.io web page1 you need to get a "blank" Jekyll set up and push it to GitHub. Later we'll hard-code the local location of this repository in your .emacs file, so you might as well choose a good location for it now. On my MacOS computer, I have it in ~/Documents/.

The following four commands

  1. clone a blank Jekyll instance into the directory /username/.github.io
  2. go into your new directory
  3. set the git repository to push to and pull from your GitHub account
  4. In that directory there will be a file called _config.yml that you should edit and fill in the fields that need to be filled in.
  5. push the default Jekyll site as a repository named username.github.io to your GitHub account
git clone https://github.com/plusjade/jekyll-bootstrap.git ${USER}.github.io
cd ${USER}.github.io
git remote set-url origin git@github.com:${USER}/${USER}.github.com.git
 (edit _config.yml)
git push origin master

If you wait a little while and then go to http://username.github.io (replacing username with your GitHub user name) you'll see the default Jekyll pages. Don't worry, you'll replace them soon enough.

Source: org-mode files

As mentioned, I like to keep my source files separate from the published content, because org-mode can selectively export during the publishing step, but anyone can read a text file.

I keep my source content in another Git repository, although I keep that one at BitBucket because they let me have private repositories at no cost. You could also just keep them on your harddrive as files, or in a local revision control system. Anywhere that can be seen by Emacs as the same time as seeing the Git repository username.github.io will work.

For the sake of the examples below, I have all of the blog postings in one directory (blog/) and all of the images in an images directory in the blog directory (blog/images/). As with the location of the cloned username.github.io directory, these paths will be hard-coded in your .emacs file, so you should choose a good location for them now.

Writing Blog Postings

Writing a blog posting is like writing any other document in org-mode (which is what makes it so great), but there are three details to which you should pay attention.

The Jekyll Header

Jekyll, which is the formatting engine at GitHub that turns your the raw HTML from the org-mode export into formatted web pages, does not use Org's #TITLE:, #DESCRIPTION:, or other export template fields, it uses its own. However, Org does share that and you can reference those fields, by including things like { { {title} } } or { { {keywords} } } (but without the extra space; that's there to prevent expansion in my example)2. NB: This expansion doesn't seem to work in Org-Move version 8. The options are described in the Jekyll documentation and must be exported when Org exports as HTML. At the top of this document is a block that looks like:

#+BEGIN_HTML
---
layout: page
title: { { {title} } }
tagline: Blogging the way you should
categories: computers
tags: web org-mode emacs org blog github bitbucket git
---
#+END_HTML

The layout field is worth looking at. It has two options: page and post. page makes it a standard web page—there are no dates, comments, or other sort of bloggy things. post makes it a more bloggy post, enabling comments if you have them enabled in _config.yml and adding a date near the top of the file and Previous, Archive, Next buttons at the bottom of the page.

Content

Once you have the Jekyll header (which, frankly, is a lot easier to do than the preceding section merits), the rest of your document is standard org-mode paragraphs, sections, links, embedded code, etc.

The layout on the GihHub site will take the first paragraph or section and put that in the index, saving the rest for the click-through; I think it looks nice to have a paragraph before the first section that your reader will see on the main page, instead of a table of contents or a section heading and the first part of the section.

The filename needs to be of the format YYYY-MM-DD-the-actual-title for accurate parsing by Jekyll.

Images and Other Assests

The publishing template that will be in your .emacs file will move images around between your source content and the publishing location. This can lead to some confusion between standard HTML rendering, publishing to the Jekyll location, and LaTeX or other export formats.

Jekyll can support images in its assets/ that are referenced in the blog posts like <img src=/assets/img-name.jpg />, but the "root-ed" path doesn't work well with normal org-mode exports.

While there are likely more elegant solutions, I set up different export options depending on the type of export. For example:

#+BEGIN_HTML
<img src=/assets/YYYY-MM-DD-picture-name.jpg />
#+END_HTML
#+BEGIN_LATEX
\includegraphics[width=0.8\textwidth]{images/YYYY-MM-DD-picture-name.jpg}
#+END_LATEX

Although the image file names don't need the YYYY-MM-DD format the same way, they help me keep things organized.

Other files you'd like to reference can also be put in the /assets directory.

Publishing Blog Postings

With a written blog posting, you can remove the examples from username.github.io/_posts and leave the empty directory. It will be re-populated when you publish your blog post.

Configuring your .emacs file

org-mode has a "publish" facility3 that is configured in your .emacs file in two sections, once for the rendered HTML and one for the static content (usually images).

(require 'org-publish)
(setq org-publish-project-alist
      '(("org-acaird" (name1)
         ;; Path to your org files.
         :base-directory "~/Documents/blog" (srcdir)
         :base-extension "org" (extension)
         ;; Path to your Jekyll project.
         :publishing-directory "~/Documents/acaird.github.io/_posts" (destination)
         :recursive t
         ;; this was for org-mode pre-version 8
         ;;:publishing-function org-publish-org-to-html
         ;; this is for org-mode version 8 and on
         :publishing-function org-html-publish-to-html
         :headline-levels 4
         :html-extension "html"
         :body-only t ;; Only export section between <body> </body> (body-only)
         )
        ("org-static-acaird" (name2)
         :base-directory "~/Documents/blog/images" (imgsrc)
         :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf\\|php" (imgext)
         :publishing-directory "~/Documents/acaird.github.io/assets" (imgdest)
         :recursive t
         :publishing-function org-publish-attachment)

        ("blog" :components ("org-acaird" "org-static-acaird")) (combo)
        ))

While this is mostly readable, there are a few things to point out that you might want to edit.

  • Line name1 defines the name of the rendered section; it doesn't much matter what it is called because it is included in the definition of what you'll usually use (in line combo)
  • Line srcdir defines the source directory; this is where your .org files go
  • Line extension sets the extensions that the export will consider; this is set to only look at files ending in .org, but you can add to it following the pattern in line imgext if you use files that end in .txt or something else
  • Line destination defines where the .html files will be written on export
  • Line name2 is similar to line name1, but it defines the name for the rules that handle static items (images and other things not processed by org-mode)
  • Line imgsrc is the directory where the images are; it is the analog of line srcdir
  • Line imgext defines the extensions of the files that will be moved from the directory defined in line imgsrc to the directory defined in line imgdest
  • Line combo combines the rendered and static sections into one name (in the case, blog) to use for exporting

Once your .emacs file has those lines in it and they are evaluated, you can type C-c C-e to bring up the export menu. From the menu, choose X and when prompted, enter the name defined in line combo above.

That will export the HTML to the username.github.io/_posts directory (as defined in line destination above) and copy the images to the destination defined in line imgdest above.

Once the files are in the proper locations in the username.github.io directory, they need to be added to the repository and pushed to GitHub for publishing.

Using git commands to publish

To publish your newly created HTML files, go to your username.github.io directory and git add and git commit your new files and git push them to Github.

After waiting a few minutes for GitHub to process your file, you'll see the title and the first bit of text at http://username.github.io and clicking the title will show you the full post.

Advanced Topics

Themes

Jekyll supports themes to change the look of your blog pages. There are some sample themes at http://themes.jekyllbootstrap.com/ with installation instructions.

Jekyll themes are installed into your username.github.io directory and repository and when it is pushed to GitHub, the theme you have chosen is applied.

Jekyll uses rake (Ruby mAKE) to install and manage themes; rake comes with MacOS and, likely, with Linux. For Windows you might have to install Ruby.

To install the theme called the-minimum from http://themes.jekyllbootstrap.com/, follow these steps

  1. cd into your username.github.io directory
  2. type rake theme:install git"https://github.com/jekyllbootstrap/theme-the-minimum.git"=
  3. commit the new theme: git commit -a
  4. push the repository to GitHub, wait 5 minutes, and reload your pages to see the new themes.

Comments

Jekyll can use Disqus to support blog comments. This is described in the _config.yml file in your username.github.io directory.

Google Analytics

At www.google.com/analytics you can set up an analytics page for your github.io pages; the end of the set-up results in a tracking ID that is a 13 character (at least, mine is) string. Add that string to the analytics: section of _config.yml and push the changes to GitHub. After a few days, if anyone looks at your blog, you'll see some nice statistics at Google.

analytics :
  provider : google
  google :
      tracking_id : 'AA-12345678-9'

Footnotes:

1

Most of this came from http://jekyllbootstrap.com

2

More documentation on this in org-mode is at http://orgmode.org/org.html#Macro-replacement