Building a Technical Blog Site With Jekyll And Emacs

Reading time ~11 minutes

1 Introduction

Jekyll is a static web site generator written in Ruby. It can transform various text markups, using a templating language, into static html. The resulting site can be served by almost any web server without requiring additional components such as php. Jekyll is the tool used to produce Github's pages.

Org-mode of Emacs is very convenient for all-around editing, from simple note taking to managing one's tasks and to writing fully-fledged articles (which can later be exported to LaTeX, for instance). Hence it feels just natural to write blogs and articles in org-mode (rather than in markdown or textile, which are the formats supported by Jekyll).

This article shows how I set up my own blog site on GitHub, using the org-mode of Emacs for editing articles and HPSTR Jekyll Theme for displaying them.

2 Jekyll

2.1 Installing Jekyll and the HPSTR theme

  • Fork the HPSTR Jekyll Theme repo and rename it to something like this: username.github.io (where username is your GitHub username). Alternatively, you can fork the repo of my website.
  • Make a local clone of your website repo:
    sudo apt-get install git
    git clone https://github.com/username/username.github.io
    
  • Install Ruby and Bundler:
    sudo apt-get install build-essential nodejs
    sudo apt-get install ruby ruby-dev
    sudo gem install bundler
    
  • Install Jekyll and all dependencies:
    cd username.github.io/
    bundle install
    
  • Test it locally:
    bundle exec jekyll serve
    

    Now open in browser: http://localhost:4000

2.2 Customizing the HPSTR theme

Edit _config.yml to personalize your site. Most of the variables found here are used in the .html files found in _includes/ (if you need to add or remove anything).

Check out the sample posts in _posts/ to see examples for pulling in large feature images, assigning categories and tags, and other YAML data.

For more details about customizing the theme see: http://mmistakes.github.io/hpstr-jekyll-theme/theme-setup/

2.3 Uploading your website to GitHub

Since it is a git repository, we can commit our changes and push them to GitHub with git push origin master. In a few moments our changes will be available online and we can access it at http://username.github.io. However we should make sure first that the URL of the site on _config.yml is correct. It should be like this: url: http://username.github.io, not empty or url: http://localhost:4000, which are used for local development.

Here are a few tips that can be useful during development:

  • Tip1: Everytime that you make a git push origin master, you have to give the github username and password. To avoid this, you can modify the file .git/config like this:
    [remote "origin"]
    	url = https://username:password@github.com/usename/username.github.io
    

    (adding username:password@ before github.com).

  • Tip2: Since the line url: in _config.yml has to be different for the online and local copy of the website, I have created a git branch named local where I do the development and testing, and then cherry-pick commits to the branch master and push them to github.
  • Tip3: To automate the workflow on the previous tip I use the script push.sh with a content like this:
    #!/bin/bash
    
    ### get the parameter commit
    if [ "$1" = '' ]
    then
        echo "Usage: $0 <commit_id>"
        exit 1
    fi
    commit=$1
    
    ### transfer the commit to branch gh-pages
    git stash
    git checkout master
    git cherry-pick $commit
    
    ### push to github gh-pages
    git push origin master
    
    ### switch back to the local branch
    git checkout local
    git stash pop
    

2.4 Posting articles

Jekyll expects the posted articles to be on the directory _posts/, with a file name like yyyy-mm-dd-title-of-the-article.extension. They can be in markdown or textile format and jekyll will convert them to HTML. But they can also be just plain HTML and jekyll will not touch their content. The extension can be .markdown (or .md), .textile, or .html.

In each case jekyll expects a front-matter in YAML format at the very top of each file, which looks like this:

---
layout:     post
title:      Building a Technical Blog Site With Jekyll And Emacs
date:       2014-12-13
summary:    This article shows how I set up my own blog site on GitHub,
    using the org-mode of Emacs for editing articles and HPSTR Jekyll Theme
    for displaying them.
tags: [Jekyll, Emacs, org-mode, Blogging]
---

It defines the layout (from directory _layouts/) that will be used to render the article and other variables that are used in the templates.

2.5 Customizing CSS

To customize CSS, I added this line on assets/css/main.scss:

@import "custom";

Then created the file _sass/_custom.scss with a content like this:

// Change the colors of the selected text.
::-moz-selection { 
        background-color: blue;
        color: white; 
        text-shadow: none; 
}    
::selection { 
        background-color: blue;
        color: white; 
        text-shadow: none; 
}

// Decrease the space between the links in the section About.
#dl-menu .dl-submenu li a {
    padding: 10px 20px;
}

// Improve the display of figures by adding borders, centering, etc.
.figure {
    text-align: center;
    border: 1px solid #eeeeee;
    margin: 20px 0;
}
.figure img {
    border: 1px solid #cccccc;
    border-radius: 5px;
    box-shadow: 0 0 10px #cccccc;
}
.figure p:nth-child(2) {
    background-color: #eeeeee;
    margin: 0;
}
.figure .figure-number {
    font-style: italic;
}

Of course you will need to make your own customizations.

3 Org-mode

3.1 Using org-mode for creating and editing articles

I have created the directory _org/_posts/ for the articles in org-mode format. The filename of an article looks like this: 2014-12-13-building-technical-blog-site-with-jekyll-and-emacs.org.

The content of the article looks like this:

#+TITLE:     Building a Technical Blog Site With Jekyll And Emacs
#+AUTHOR:    Dashamir Hoxha
#+EMAIL:     dashohoxha@gmail.com
#+DATE:      2014-12-13
#+OPTIONS:   H:3 num:t toc:t \n:nil @:t ::t |:t ^:nil -:t f:t *:t <:t
#+OPTIONS:   TeX:nil LaTeX:nil skip:nil d:nil todo:t pri:nil tags:not-in-toc
# #+INFOJS_OPT: view:overview toc:t ltoc:t mouse:#aadddd buttons:0 path:js/org-info.js
# #+STYLE: <link rel="stylesheet" type="text/css" href="css/org-info.css" />
#+BEGIN_HTML
---
layout:     post
title:      Building a Technical Blog Site With Jekyll And Emacs
date:       2014-12-13
summary:    This article shows how I set up my own blog site on GitHub,
    using the org-mode of Emacs for editing articles and HPSTR Jekyll Theme
    for displaying them.
tags: [Jekyll, Emacs, org-mode, Blogging]
---
# +END_HTML

Jekyll is a static web site generator written in Ruby. It can
transform various text markups, using a templating language, into
static html. The resulting site can be served by almost any web server
without requiring additional components such as php. Jekyll is the
tool used to produce Github's pages.

. . . . . . . . . .

The top lines that start with #+TITLE:, #+AUTHOR:, etc. are not displayed on the converted HTML document. So, the first thing that is outputed is the YAML front matter, which is included between the lines #+BEGIN_HTML and #+END_HTML:

---
layout:     post
title:      Building a Technical Blog Site With Jekyll And Emacs
date:       2014-12-13
summary:    This article shows how I set up my own blog site on GitHub,
    using the org-mode of Emacs for editing articles and HPSTR Jekyll Theme
    for displaying them.
tags: [Jekyll, Emacs, org-mode, Blogging]
---

3.1.1 Other resources

3.2 Converting org-mode articles to HTML format

We need to export (convert) org-mode articles to HTML format and to place the HTML article in the directory _posts/, so that it can be found and processed by Jekyll. We do this by defining an org-mode publish project in the file ~/.emacs, with a content like this:

(setq org-publish-project-alist '(

  ("org-blog"
          ;; Path to your org files.
          :base-directory "~/username.github.io/_org/"
          :base-extension "org"

          ;; Path to your Jekyll project.
          :publishing-directory "~/username.github.io/"
          :recursive t
          :publishing-function org-html-publish-to-html
          :headline-levels 4
          :html-extension "html"
          :body-only t ;; Only export section between <body> </body>
          :section-numbers nil
          :with-toc nil
    )

    ("org-static-blog"
          :base-directory "~/username.github.io/_org/"
          :base-extension any
          :exclude ".*\.org"
          :publishing-directory "~/username.github.io/"
          :recursive t
          :publishing-function org-publish-attachment)

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

))

The first project ("org-blog") defines how the org files are published. :base-directory ~/username.github.io/_org/ is the directory that will be searched recursively for .org files. They will be converted to html with :publishing-function org-html-publish-to-html and will be saved to :publishing-directory ~/username.github.io/ with the same directory structure.

The setting :body-only t makes sure that only the body of the HTML document will be exported (the rest of the webpage will be constructed by jekyll according to the layout given in the config section).

The second project ("org-static-blog") just copies anything else from the _org/ directory to the main jekyll directory. They can be images, css/js files, etc.

The project "blog" calls both of these publishing projects.

Now we can export the project with C-c C-e P x blog.

Note: If you don't have org-mode version 8.0 or later (check it with M-x org-version), you should update it. You can do it like this:

  1. Go to the list of packages: M-x package-list-packages
  2. Find the package org: C-s org
  3. Go to it and press <Enter>
  4. Install it by clicking on [Install]

3.3 Generating a TOC for an article

Let us look closer at the export settings on the org file:

#+OPTIONS:   H:3 num:t toc:t \n:nil @:t ::t |:t ^:nil -:t f:t *:t <:t
#+OPTIONS:   TeX:nil LaTeX:nil skip:nil d:nil todo:t pri:nil tags:not-in-toc

We notice the option toc:t which tells the export function to generate a Table Of Content on the HTML file (to disable it use toc:nil).

However there is a problem because the TOC is generated before anything else, even before the YAML config section. We don't want this because jekyll can process the config section of an HTML file only if it is at the top of the file.

But we can fix it with commands like this:

(sed -n -e '/^---$/,/^---$/p' file.html; sed -e '/^---$/,/^---$/d' file.html) > file.new
mv file.new file.html

(More on it later.)

Now the TOC is displayed at the top of the article. However it is possible to make it look more nice and professional. Add these lines at the file _sass/_custom.scss and you will see that they create the splendid efect of a dynamic TOC:

// TOC copied from: http://orgmode.org/worg/
#table-of-contents {
    font-size: 10pt;
    position: fixed;
    right: 0em;
    top: 0em;
    background: white;
    line-height: 12pt;
    text-align: right;
    box-shadow: 0 0 1em #777777;
    -webkit-box-shadow: 0 0 1em #777777;
    -moz-box-shadow: 0 0 1em #777777;
    -webkit-border-bottom-left-radius: 5px;
    -moz-border-radius-bottomleft: 5px;
    /* ensure doesn't flow off the screen when expanded */
    max-height: 80%;
    overflow: auto;
}
#table-of-contents h2 {
    font-size: 13pt;
    max-width: 9em;
    border: 0;
    font-weight: normal;
    padding-left: 0.5em;
    padding-right: 0.5em;
    padding-top: 0.05em;
    padding-bottom: 0.05em;
}
#table-of-contents #text-table-of-contents {
    display: none;
    text-align: left;
}
#table-of-contents:hover #text-table-of-contents {
    display: block;
    padding: 0.5em;
    margin-top: -1.5em;
}

3.4 Displaying images properly

Images in the org-mode file are included like this:

#+CAPTION:    Tables and their relations.
#+NAME:       fig:db_diagram
#+ATTR_LaTeX: width=13cm
[[file:images/btranslator-project/db_diagram.png][file:images/btranslator-project/db_diagram.png] ]

On the final document it looks like this:

db_diagram.png

Figure 1: Tables and their relations.

The image itself is initially placed on the directory /_org/images/btranslator_project/. When the export comand is executed, besides converting to HTML it will also copy everything on the directory /_org/ to the main directory of jekyll, so it will go to /images/btranslator_project/. However the source of the image on the generated HTML file will look like this:

<img src="images/btranslator_project/db_diagram.png" />

It is missing a slash (/) in front. It can be corrected after exporting with a command like this:

sed -e 's|="images/|="/images/|g' -i file.html

3.5 Post-processing html exports

I have created a bash script for fixing the problems in the two sections above (making sure that the YAML section is at the very top of the generated HTML file, and correcting the URL of images). It is in the file _org/post-process.sh and looks like this:

#!/bin/bash
### Post-process .html files (after being converted from .org)
### to make sure that they are properly formatted for jekyll.
### Example:
###     ./post-process.sh ../_posts/*.html

### if there are no argument, display the usage
if [ $# -eq 0 ]
then
    echo "
Usage: $0 [<file>|<glob>]...

Example:
    ./post-process.sh ../_posts/*.html
"
    exit 1
fi

### process each file given as an argument
for file in $@
do
    echo $file

    ### make sure that the yaml front matter is on top of the file
    (sed -n -e '/^---$/,/^---$/p' $file; sed -e '/^---$/,/^---$/d' $file) > $file.new
    mv $file.new $file

    ### fix the path (url) of images by adding a slash (/) in front of it
    sed -i $file -e 's|="images/|="/images/|g'
done

To make sure that all the HTML posts are OK, I call it like this:

_org/post_process.sh _posts/*.html

It is also idempotent (runing it multiple times on the same HTML file will not break it).

3.6 Higlighting the syntax of the code examples

My articles often include code examples, so I am interested in displaying them prettily. I use the tags #+BEGIN_EXAMPLE and #+END_EXAMPLE to display terminal commands and output, and sometimes even for code, but it does not do syntax highlighting.

For syntax highlighting I let jekyll do it, using the tags { % highlight %} and { % endhighlight %}, like this:

#+BEGIN_HTML
{ % highlight bash %}
#!/bin/bash

. . . . . . . . . . .

{ % endhighlight %}
#+END_HTML

Of course it has to be wrapped in org tags #+BEGIN_HTML and #+END_HTML, so that it is copied verbatim while exporting to HTML.

For other tips about code examples see also this: http://mmistakes.github.io/hpstr-jekyll-theme/code-highlighting-post/

Moodle For Every School

Moodle For Every SchoolMoodle For Every SchoolTable of Contents1. Abstract2. Introduction3. Installing Moodle4. Moodle as a Service5. Ins...… Continue reading

Building SSH Tunnels

Published on March 25, 2017