Footnotes. Writers love ’em. But if you’re not paying proper attention when creating them, you can quickly make a mess of your website or blog. In fact, until very recently, this site had broken footnote links all over the place. I’m going to pretend like none of you noticed, and tell you about how I fixed the problem, gently glossing over my past stupidity.
Thing is, since I’m creating the post locally on my Mac, with no reference to the site as a whole, Marked has no way of knowing which footnote IDs have already been used, and which have not. Therefore each post labels its first footnote
fn:1 and subsequent footnotes increase by 1, as you’d expect. The problem occurs when viewing the home page that shows 10 posts on a single page, each with their own
fn:1. When you click on the
 link in the body text, where do you think it’s going to take you? That’s right, to the first footnote it finds with the label
fn:1, regardless of which post it was intended to link to .
Now, Marked has a setting in its preference pane called
Use Random Footnote IDs which is used “to avoid conflicts when multiple documents are displayed on the web.” So this is already a solved problem, right? Probably, but there’s a part of my brain that feels uneasy about using randomly generated IDs. I’m sure using this feature would solve my problem and everything would be fine, but since I’m a nut, I want to control exactly how these unique footnotes are created.
Enter MultiMarkdown. MultiMarkdown includes a number of enhancements to the original Markdown syntax , including support for customizable metadata fields . So, I created a custom metadata key called
footnote:. Here’s what my boilerplate MultiMarkdown header looks like  :
Title: Author: Dan Sturm Date: %snippet:ddate% Marked Style: ds_doc footnote:
Now, whatever keyword I choose to add after the
footnote: label will show up in the HTML header as
Make With The Magic
The next thing I needed was a script to scan the HTML for the metadata key, and add it to all the footnote IDs, turning
import sys import re import subprocess # Open the file and convert it to searchable text fileText = open (sys.argv, "r+") searchText = fileText.read() # Pull the MultiMarkdown metadata key from the header mmdkey = re.search("(?<=\"footnote\" content=\")(.*)(?=\"/>)", searchText, re .I) mmdkey = mmdkey.group() # Create the new footnote IDs fnnew = ("fn:", mmdkey) fnrefnew = ("fnref:", mmdkey) fnnew = "".join(fnnew) fnrefnew = "".join(fnrefnew) # Swap the footnote IDs for the new ones fnfix = re.sub("(fn:)", fnnew, searchText) fnreffix = re.sub("(fnref:)", fnrefnew, fnfix) # Strip HTML Header and Body tags. Copy the result to Clipboard def setClipboardData(data): p = subprocess.Popen(['pbcopy'], stdin=subprocess.PIPE) p.stdin.write(data) p.stdin.close() retcode = p.wait() fixStripped = re.sub("(?s).*(\n)\n", "", fnreffix) fixStripped = re.sub("(?s)\n\n\n().*", "", fixStripped) setClipboardData(fixStripped) # Write the updated code to the same file # fileText.seek(0) # fileText.write(fnreffix) # fileText.truncate() # fileText.close()
Simply put, it watches the folder for a new file and, when it sees one, it runs the script, displays a confirmation message, then trashes the now-unnecessary file, leaving the cleaned up, new code on the clipboard for easy pasting into your CMS of choice. So, when I like what I see in Marked and I’m ready to post, I hit
CMD+S and save the HTML file to my
Create Unique Footnotes folder, head over to my site, and hit
CMD+V into a new post.
A Small Rabbit Hole
There are a few specific things I want to point out, just to make sure we’re clear.
The new HTML code is copied to the clipboard by the Python script, not by the Hazel rule. My workflow involves pasting HTML code into Squarespace, not uploading an HTML file and, since my MultiMarkdown file is the master copy of the post, that’s why I’m deleting the HTML file after running the script.
The HTML file being used as input for the script is a complete HTML document with a header, body tags, the whole shebang. I don’t need those extra bits when I’m pasting the code into Squarespace, so the Python script removes them before placing the code on the clipboard. In fact, the code on the clipboard looks exactly like what you see when you toggle the
Switch to HTML Source View button in Marked  while previewing your MultiMarkdown document.
Another important note; keen observers will notice the last four lines of the Python script are commented out. That code is there for people who actually want a fully processed HTML document with fixed footnote IDs. Un-commenting-out  those four lines will write the fixed code over the original HTML document, while maintaining the header, et cetera. If you plan on using this workflow, you’ll want to remove the step in the Hazel rule that throws away the HTML document. I’d suggest you change that part of the rule to move the new HTML file to the Desktop as a sort of visual confirmation that the file has been updated.
I Believe Some Recognition is in Order
When I initially conceived of this idea I hadn’t the slightest idea how to best go about tackling it. I am not a programmer in any sense of the word. A Twitter conversation with my pal Sid O’Neill revealed that REGEX is the method by which I could find and replace items in the code. I don’t know how to do that, so…
Patterns is a Mac app for creating Regular Expressions that I’ve heard a number of people compliment in the past. It lets you see a live preview of the current pattern matches and, when you’ve got the selection you want, will generate the appropriate code for you; Python in my case. Completely indispensable and only $2.99.
Next, of course I have to thank Stack Overflow from whence I acquired some REGEX knowledge and code. Patterns comes with a great Reference Sheet for REGEX commands, but some of the descriptions still left me befuddled. Stack Overflow also linked me to…
This article by Gabe at Macdrifter, where I got the code that places the HTML on the clipboard. It was exactly what I needed, so I took it. And I would have gotten away with it if it wasn’t for you pesky kids and…nevermind.
In any case, high-fives all around. Go team.
Like footnotes, for one. ↩
Obviously, I need to choose a unique key for each post or this whole exercise is pointless. ↩
You do use Hazel, don’t you? Good. ↩
It’s in the upper right corner of your document, next to the fullscreen button. ↩
That’s so not a word, is it? ↩