Jekyll org mode


Reading time: about 3 minutes

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!

Citation

If you find this work useful, please cite it as:
@article{yaltirakli,
  title   = "Jekyll org mode",
  author  = "Yaltirakli, Gokberk",
  journal = "gkbrk.com",
  year    = "2024",
  url     = "https://www.gkbrk.com/jekyll-org-mode"
}
Not using BibTeX? Click here for more citation styles.
IEEE Citation
Gokberk Yaltirakli, "Jekyll org mode", November, 2024. [Online]. Available: https://www.gkbrk.com/jekyll-org-mode. [Accessed Nov. 12, 2024].
APA Style
Yaltirakli, G. (2024, November 12). Jekyll org mode. https://www.gkbrk.com/jekyll-org-mode
Bluebook Style
Gokberk Yaltirakli, Jekyll org mode, GKBRK.COM (Nov. 12, 2024), https://www.gkbrk.com/jekyll-org-mode

Comments

© 2024 Gokberk Yaltirakli