2020.destroytoday.com

Footnotes

After writing a few articles, a friend “Well, actually‘d” me about one of them. In the article, I suggested that Contentful should use a prefix for their API tokens, so you wouldn’t need to specify a different host between dev and production. I didn’t realize that Contentful’s “delivery” API, which is intended for production, is served through a CDN, while the “preview” API isn’t. I wanted to point this out on the original article, but I didn’t want to lose the original content. At first, I considered “highlights”, which could be hovered to show a tooltip, but it didn’t feel accessible enough, so I decided to lean on another pre-web writing element—the footnote.

In Contentful, there’s a “Rich Text” content model type that’s common for article bodies, like the text you’re reading now—potentially including bold, italic, and underlined text, or links, images, and code snippets. Within this rich text, you can embed assets, other entries, or inline entries.

Inline Entry

While regular embedded entries make up an entire block of content, an inline entry can live inline with your text—similar to the inline code snippets I’ve written in other articles, but existing as a referenced entry rather than embedded as text. With an inline entry, I was able to highlight the original words I needed to reference with a custom renderer that simply wraps the text with a <span> and adds a <sup> for the footnote number. Here is an example footnote reference.

*American Psycho voiceover* Oh, the background color? That’s moccasin.

The footnote number is tricky because I don’t have any context in the custom renderer. Typically, I would simply use the index number of the footnote if I had access to it. I still thought this was the most straightforward and least clever approach, so I cheated a bit to make it work. In my Vue component for the article, I created a mounted hook, looped through the <sup> elements, and set their textContent to one plus the index. Since I’m using Nuxt, and serving the site in “universal” mode, the number is still server-side rendered.

To display the footnotes below the article, I filtered the body payload for the footnote entries. Since these are inline, this means iterating through all content arrays within the body field, which definitely doesn’t feel performant, but it works, and I couldn’t easily find another way, so it’ll suffice for now. The request I get from Contentful does return an includes array with the footnote entries, but when retrieving multiple articles, I couldn’t find any references from the footnotes to the related articles, so there doesn’t seem to be a way to match them.

Now that I had the footnotes listed below the article and the references highlighted within the article, I could’ve stopped there, but I didn’t. While searching through footnote implementations, I came across this Daring Fireball article from 2005 that describes John Gruber’s approach of linking references to their footnotes and vice versa. Linking the reference is easy, by simply linking the footnote reference number, but for the footnote itself, John suggests using a “leftwards arrow with a hook” (↩, or &#x21A9;) that links back to the reference.

He also prefixes the anchors with “fn1” and “fnref1” for the footnote and reference, respectively, then includes the footnote number. I didn’t love the abbreviations or the use of the footnote numbers (in case they changed), so I prefix with “footnote” and “reference”, then append the Contentful UUID for the footnote entry. I don’t love using such a long ID string, but it’s unique to the footnote, which is worth more to me.