Development notes

Some miscellaneous notes I took while working on jorge.

Jekyll and Hugo

I’d been blogging with Jekyll for a few years now; first on GitHub Pages, from a fork of the beautiful-jekyll theme, then on a VPS with a design I wrote from scratch. It worked well for me; I was only attempting to write my own site generator because it made a good Go learning project. So, when designing jorge, I defaulted to whatever Jekyll did, except for the few parts that I felt added friction to my blogging workflow:

Since I would be writing a static site generator in Go, I also had Hugo on my radar as a reference. I hadn’t used Hugo but, from skimming through the documentation, I got the impression that it was more complex than Jekyll, certainly more than what I was planning to build. I used it occasionally to have an additional point of view for design choices, as well as a reference when looking for Go libraries to solve specific problems (the command-line interface, file-watching, etc.).

Liquid

One decision I took early on was to use liquid as the templating language (as Jekyll does) rather than Go’s html/template package (as Hugo does). I did so because:

I could use the osteele/liquid library (part of a Go port of Jekyll) for parsing and rendering the templates. I later realized that some of the template tags and filters I was using in my website weren’t native liquid but rather Jekyll extensions; since I didn’t want to add the entire gojekyll project as a dependency —which felt like it would defeat the purpose of building a site generator—, I ported and adapted the few filters I needed.

CLI

The Go standard library has reasonable support for building command-line programs —not as flexible as Python’s argparse but good enough for most purposes. I implemented the entire jorge interface out of a few basic programs from Go by Example. But before releasing the project I wanted to add some standard features like version and help flags, usage documentation, and user-friendly errors; things better served by a specialized library.

I assumed, from previous experience, that all CLI libraries would be more or less equivalent, but the most popular Go ones turned out not to be flexible enough to accommodate the usage patterns I had already implemented:

kong, on the other hand, allowed me to define my CLI concisely and declaratively, preserving the code structure and user experience I already had in place, and handling input validations for me. Once I adapted my code to use kong, further refactoring opportunities opened up.

Smartypants

In my old blogging workflow, I wrote posts as org-mode files, manually exported them to Markdown, and then passed them to Jekyll, since this produced better-formed documents than using org-html-export directly. One benefit I was inadvertently getting from this setup, which I didn’t notice until I started comparing the jorge output HTML with my online blog, was “smart quote” replacements: where my website showed “Joe’s Garage”, my jorge posts would render "Joe's Garage". Once I started noticing the difference, I couldn’t un-see those dumb apostrophes, so I started researching how to get that feature into jorge.

I was fixated on getting this feature —I didn’t want the jorge port of my website to feel like a downgrade in any way— but none of the options was usable as it was. What I ended up doing was extracting the text-replacement logic from gojekyll’s smartify filter —since it was the shortest and simplest of the lot, even if potentially slower— and used it in my own HTML traversal code, making sure to skip preformatted tags (pre, code, script, etc). The result is here.

CSS

One of the reasons why I decided to work on a command-line application was that it wouldn’t require building and polishing a graphical user interface. Although jorge init would generate a website, CSS included, I planned to just copy the styles from my home page. That didn’t go as planned, though: as soon as I started making minor tweaks to the page contents, I found myself struggling between CSS syntax nuances, browser quirks, and my own limitations.

I can tell what I like from what I don’t, aesthetically speaking; I occasionally get ideas to improve the look of my website, and I can Google my way into making them happen. But I am no designer; I don’t have the training to reason from first principles and think holistically about design as I can with program code —not to mention getting accessibility requirements right. I may get a site to look as I want but the CSS turns out to be brittle; any change may break things that were previously working and what looks good on my machine may not on my cellphone or a different browser. HTML and CSS have come a long way since the jQuery days, but I get war flashbacks whenever I see that iOS Firefox displays a completely different thing from Firefox Desktop because it’s just Safari under the hood, and then Safari Desktop’s responsive mode doesn’t match iOS Safari, either2.

One place where things got hairy was trying to honor the browser preferences for light/dark mode (through color-scheme and prefers-color-scheme media queries) while doing syntax highlighting of code blocks (with a library that’s unaware of color preferences) but without forcing the same highlighting theme on all generated sites.

Notes


1

I know you can get the same behavior in Jekyll by changing the configuration. As with other options, I wanted the jorge configuration to meet my preferences by default.

2

This WebKit quirk was especially annoying.