On this past sunny, long Memorial Day weekend, I decided to play around with static site generation for a new blogging platform.
I’ve used a self-hosted Wordpress site for a while now, but I don’t use it enough to justify the resources. Plus, I found its new “blocks” WYSIWYG editor wasn’t great with links and code.
When dealing with links and code in prose, what better choice than a markup language? I’d love to use some form of markup, and avoid spending tons of time styling.
Those requirements lead me to Jekyll.
I’ve been an Emacs user for the better part of 4 years, and still use Org mode for a handful of tasks. I love the Emacs-native code snippet styling, simple LaTeX, and ease of exporting to other formats. `org-latex-export-to-pdf` was incredibly useful in college: I know enough about LaTeX to write math, but when organizing responses on an assignment, I’d prefer to let Org handle it.
I set out with a simple goal:
This should not be a challenging problem: Org has been around for a while, Jekyll has been around for a while. Surely a plugin exists to tackle this exact task. Or at worst, go from Org->Markdown (even Org->HTML), and let Jekyll take it from there.
If you’ve heard of/used Jekyll before, here’s a brief intro, relative to what I’ll be touching.
Jekyll generates a cohesive, static site from various markup templates. I’m using it for a blog, but it offers colections, several templating/layout options, and more.
For my use case, markup goes in
_posts, and is added to a list of posts on the
home page. Example:
// _posts/2020-05-24-Hello-world.md --- title: "Welcome to Jekyll!" date: 2020-05-24 17:33:51 -0400 categories: - category1 - category2 tags: - tag1 - tag2 --- Hello world!
example.com, this will generate
with the requested tags + content.
In traditional Emacs fashion, you have your pick of solutions. Worg lists a majority of popular ones. Many looked out of date or unmaintained, but some looked promising.
Using that list + some searching, I had a handful of projects to try out.
All of them fell short for one reason or another, which surprised me. It changed my view of this ecosystem a bit, and I’d like to explore each potential solution a bit to identify sources of shortcomings.
jekyll-org is a Jekyll plugin, allowing Jekyll to treat
.org files as any
other markup file, and auto-generate pages from it.
This means Jekyll handles everything: no exporting through Emacs necessary. Sounds great! Less I need to worry about.
I tried adding a code snippet. Org indicates a code block using the following format.
##+BEGIN_SRC python import pprint pprint.pprint("Hello world!") ##+END_SRC
With only one
# on each line.
In my editor, syntax highlighting is all honky dory. Syntax highlighting is borderline essential for a tech blog: I post various code snippets so folks can follow along, so it’s a must-for the rendered output.
For one blog entry, this snippet gave me some hassle (ARM assembly):
// A ==> B MOV R3, #0x2 // R3 Button mask MOV R4, #0x3 // R4 EOR mask AND R5, R6, R3 // Extract desired values
This rendered as:
<div class="highlight"><pre><span></span><span class="err">//</span> <span class="nf">A</span> <span class="err">==></span> <span class="no">B</span> <span class="nf">MOV</span> <span class="no">R3</span><span class="p">,</span> <span class="c">#0x2 // R3 Button mask</span> <span class="no">MOV</span> <span class="no">R4</span><span class="p">,</span> <span class="c">#0x3 // R4 EOR mask</span> <span class="no">AND</span> <span class="no">R5</span><span class="p">,</span> <span class="no">R6</span><span class="p">,</span> <span class="no">R3</span> <span class="err">//</span> <span class="no">Extract</span> <span class="no">desired</span> <span class="no">values</span>
Notice how each token is given a
span tag, so it can be identified and highlighted individually.
…Why does the second
MOV instruction have a different class than the first?
Why is a comment (
//) given an
err class, but the first “token” in the
A) is a seemingly valid
Clearly something under the hood was weird. This begs the question: if it’s not using Emacs, what does it use?
To avoid running Emacs every time Jekyll publishes,
org-ruby. This library + standalone program handles conversion from Org to a
handful of popular formats. It’s used by GitHub and GitLab to render
org-ruby isn’t feature complete, which isn’t a surprise. The Org manual is
big, and it’s the closest thing Org has to
a specification. This makes the
two interoperable implementations
rule tough, much less a modest subset such as
jekyll-org supports syntax highlighting with
a Ruby library. (Note: Jekyll no longer uses it under the hood, and instead
uses Rouge. I’m not sure if this will stop
working in a newer version of Jekyll.)
Under the hood, syntax highlighting + exporting to HTML is a tricky problem. You need to know something about the target language in order to highlight it properly. You can’t get away with the horrible regexp hack Emacs uses to accomplish syntax highlighting, when you’re only working with HTML+CSS.
Since I’m essentially using two Org implementations, there will be discrepancies between what I see & what’s actually rendered. And you can forget about Evaluating Code Blocks to show code output alongside source. So I can’t use any advanced Org features with this library.
Not a deal breaker, but certainly disappointing.
Jekyll supports a handful of markup formats: one Emacs-compatabile approach is to export Org as another markup format, and hand that off to Jekyll.
Off the bat, I’m not that fond of this approach.
source->inbetween->target I can accept,
inbetween is essentially just an HTML
body that Jekyll will
drop into a new page.
What I don’t like is the placement of the burden: myself. I need to remember to export Org as HTML before I commit, or even when I want to test something.
This is partially mitigated by git hooks, but git hooks are hard to manage.
Org supports “publishing” configured projects for situations such as these. Worg has a segment on setting up such a project: https://orgmode.org/worg/org-tutorials/org-jekyll.html#org14785a7.
#org14785a7 at the end bothers me more than it should. A
Markdown-rendered page would link that header tag as
configuring-org-html-export, or the like. But, I digress.)/
That example works, and you can change the hardlink to the writer’s directory if you like. But I hate that there’s a hardlink in the first place. This took me down my first rabbit hole: how to I make that a dynamic configuration?