By default, Jekyll comes with Markdown support. However, you might have content written in another format, especially if you are migrating from another Content Management System.
One such format is org-mode, which is a very popular format for note-taking, TODO lists, project planning, and more. I happened to have some content written in org-mode that I didn’t want to convert to Markdown. So I needed to teach Jekyll how to handle org-mode files.
Thankfully, Jekyll has a plugin system that makes it easy to add new features. All you need to do is write your plugin code in Ruby and put it in the _plugins
directory. On the next build, Jekyll will automatically run your plugin code.
Converting org-mode to HTML
There are multiple ways to do this. The two most obvious ways are using Emacs, or using Pandoc.
These have different trade-offs. Let’s discuss both options briefly.
Using Pandoc
Pandoc is a standalone tool that can be used to convert between many formats, and it’s very easy to integrate into anything. But due to being a separate tool, it might deviate from the way org-mode is interpreted by Emacs. Most likely, you won’t notice any significant differences unless you use some advanced features.
You can run pandoc -f org -t html
to convert an org-mode file to HTML. After running this command, you will need to send the org-mode file to the standard input of the command, and the HTML will be printed to the standard output.
In Ruby, it looks like this:
require 'open3'
def org_to_html(content)
cmd = 'pandoc -f org -t html'
stdout, _status = Open3.capture2(cmd, stdin_data: content)
stdout
end
Using Emacs
Using Emacs for this is a little more tricky, because unlike the Pandoc version, Emacs wants to read from and write to files. So we need to create a temporary file, write the org-mode content to it, and then run Emacs in batch mode to convert it to HTML.
require 'tmpdir'
require 'open3'
def org_to_html(content)
Dir.mktmpdir do |dir|
input_file = File.join(dir, 'myfile.org')
output_file = File.join(dir, 'myfile.html')
File.write(input_file, content)
cmd = "emacs -Q --batch #{input_file} --eval '(org-html-export-to-html nil nil nil t)'"
stdout, _status = Open3.capture2(cmd)
File.read(output_file)
end
end
Jekyll plugin
Now that we have a way to convert org-mode to HTML, we can write the Jekyll plugin. Here’s the most straightforward version:
require 'open3'
class OrgModeConverter < Jekyll::Converter
priority :low
def matches(ext)
ext =~ /^\.org$/i
end
def output_ext(_ext)
'.html'
end
def convert(content)
cmd = 'pandoc -f org -t html'
stdout, _status = Open3.capture2(cmd, stdin_data: content)
stdout
end
end
If you want to use the Emacs version, just replace the
convert
method with the Emacs one we wrote earlier.
Caching
This plugin works, and it’s very simple. However, if you have a lot of org-mode files, it’s going to slow down your build process a little. To overcome this, we should use a cache. Jekyll has a built-in cache system that we can use.
Here’s the same plugin, but with caching:
require 'open3'
class OrgModeConverter < Jekyll::Converter
priority :low
def matches(ext)
ext =~ /^\.org$/i
end
def output_ext(_ext)
'.html'
end
def convert(content)
cache.getset(content) do
cmd = 'pandoc -f org -t html'
stdout, _status = Open3.capture2(cmd, stdin_data: content)
stdout
end
end
def cache
@cache ||= Jekyll::Cache.new('org_mode_converter')
end
end
Conclusion
In this post, we’ve explored how to extend Jekyll’s functionality to support org-mode files. We’ve discussed two methods of converting org-mode to HTML, using either Pandoc or Emacs, and how to implement these methods in a Jekyll plugin. We also looked at how to optimize the conversion process by caching the results to speed up the build process.
This is a great example of how flexible and extensible Jekyll is. With its plugin system, you can easily add support for new file formats or add new features to your site. Whether you’re migrating from another CMS or just prefer writing in org-mode, this plugin will make your life a lot easier.
Remember, the key to a successful blog or website is to use tools that fit your workflow. If org-mode is a big part of your workflow, then this plugin is definitely worth considering. Happy blogging with Jekyll and org-mode!