ox-pollen: a way to integrate Org files into a Pollen project

After reading swyx - Learn in public, I realized I really have to write more on this blog to make use of some of my collection of 2000+ diary and note entries.

I haven’t been writing that much (at all) on this blog, mainly because this year I’ve been going through lots of changes in the way I take notes. I now use Org-roam to manage all notes (after briefly experimenting with my own implementation of backlinks in Emacs). But this has left this blog stuck in an old workflow that I’ve now abandoned, making it even harder for me to start wanting to write in public again.

To solve this, I first dabbled around remaking the entire site in another static site generator, but couldn’t find the motivation to do it. It’s just too much effort (porting all articles over and redesigning everything) for too little gain.

What I actually wanted is a way to link between my published posts and my private notes. Linking to private notes of course doesn’t work, but I at least want backlinks for public posts.

This can be accomplished by either implementing support for showing backlinks for any file in Org-roam, or by simply writing in Org and exporting it to a target format.

So now a key part of the puzzle is to write a converter to convert Org to Pollen, because I still don’t want to give up the flexibility of Pollen tag functions.

Writing an Org mode exporter: ox-pollen

It turns out writing an Org mode exporter isn’t that hard. There is already an existing exporting framework that allows you to write a finite number of functions to deal with each type of “element” as parsed by org-element. You just need to define functions to translate elements into your target syntax; elements are documented on Worg: Org Syntax (draft).

For example, this is the definition of source blocks:

(defun ox-pollen-src-block (obj &rest _)
  (format "◊highlight['%s]{\n%s}"
          (org-element-property :language obj)
          (ox-pollen--escape-lozenge
           (org-element-property :value obj))))

And if everything’s working alright, that block should be formatted as Emacs Lisp because this post itself is written in Org and converted with ox-pollen.

Another example for how simple this can be: this is how ox-md translates bold text in Org to bold text in Markdown.

(defun org-md-bold (_bold contents _info)
  "Transcode BOLD object into Markdown format.
CONTENTS is the text within bold markup.  INFO is a plist used as
a communication channel."
  (format "**%s**" contents))

Details about how the parsed element, “contents”, and the “communication channel” is written in Org Export Reference Documentation. (I actually didn’t realize Org Export Reference Document exists until now, and I wrote the current version of ox-pollen mostly by mimicking ox-md, the builtin Markdown export backend.)

Caveat

Pollen is really flexible, and ox-pollen is more opinionated than Pollen is.

For example, you could translate Org description lists to a Pollen tag function description-list, relying on the user to then define that tag function; or you could just emit <dl>, <dt>, and <dd> tags (in their equivalents in Pollen Markup) which will allow it to work out of the box.

As it stands, ox-pollen will probably emit what’s most convenient for me right now.

Getting it

ox-pollen is hosted on GitHub; there’s also a project page on this site.