Blogging with Emacs org-mode and Github Pages Blogging the way you should
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
- clone a blank Jekyll instance into the directory
/username/.github.io
- go into your new directory
- set the git repository to push to and pull from your GitHub account
- 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. - 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
cd
into yourusername.github.io
directory- type
rake theme:install git
"https://github.com/jekyllbootstrap/theme-the-minimum.git"= - commit the new theme:
git commit -a
- 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:
Most of this came from http://jekyllbootstrap.com
More documentation on this in org-mode
is at
http://orgmode.org/org.html#Macro-replacement
More on the org-mode
publishing is at
http://orgmode.org/worg/org-tutorials/org-publish-html-tutorial.html