Once I made the decision to use Drafts and DEVONthink for my knowledge base, my next step was to set it up. Most of the information I need to store contains code snippets, so it was important to get that functionality working before I started migrating everything into DEVONthink.

Setting Up PrismJS

Setting up a custom PrismJS is straightforward in DEVONthink. Go to the PrismJS website, choose the theme you want and then click on the giant “Download” button. On the next screen, choose all of the languages that you want available as well as any plugins you might want (like Copy to Clipboard Button). Once you have your selections, click on the “Download JS” and “Download CSS” buttons to get your files.

Once you have downloaded the files, you will need to load them into DEVONthink. I created a group called styles in my database and and just dropped them in. With the files in place, I right clicked on each file and clicked on Copy Item Link to get the DEVONThink link for each file. The final step was to create the links that will need to be inserted at the top of each of my markdown documents.

CSS File

<link href="x-devonthink-item://DB8A0D35-1B24-4299-8559-B88DAAD14CF6" rel="stylesheet">

JS File

<script src="x-devonthink-item://A413626F-AB37-4465-8906-9216649B7D59"></script>

Setting up Drafts

Getting Drafts configured was a little bit harder. I started with Rosemary Orchard’s Send to DEVONthink action, which basically just creates the markdown document in DEVONthink via a URL step.

x-devonthink://createmarkdown?title=[[title]]&text=[[body]]&tags=[[tags]]

This worked to get the draft into the DEVONthink, but there were a few problems. The first was that the first line of the draft was missing from the actual document in DEVONthink. I learned that Drafts considers the first line of a draft the title and everything after that the body, so based on my action it was using the Title for the name of the document and the body for the text. To fix that problem, I just changed body to draft (this represents the whole draft) to get the whole note. I also learned that Drafts has a template tag called safe_title that removes some characters that could be problematic so I incorporated that as well.

x-devonthink://createmarkdown?title=[[safe_title]]&text=[[draft]]

Now that my drafts were getting into DEVONthink in the proper format, the next step was to get PrismJS working on my code snippets. Since I use TextExpander already, I created a snippet to insert the two lines above and would insert them right after the title. However, when I created my first snippet, I came across a small problem. In normal markdown, you create a code block using three back ticks ``` and can include the language ```shell but with PrismJS, you need need to use ```language-shell which doesn’t format properly in Drafts. So I decided to add a script step before the URL step that would add language- to my codeblock language.

// Find anything that starts with ``` and has something after it.
const findRegex = /(```)([A-Za-z]+)/g;
// Replace with ``` + language + whatever is after it
const replaceWith = "$1language-$2";

// Replace the code blocks for Prism
draft.content = draft.content.replace(findRegex, replaceWith);
draft.update();

Now my note was properly formatted for PrismJS code blocks and everything was showing up in DEVONthink properly. My last step was to update the action to add the PrismJS bits automatically so I did not have to remember to add them with my TextExpander Snippet. The final action includes two steps. The first is a script that cleans up the note and the second step posts the draft to DEVONthink via the x-callback-url.

Script Step

const title = draft.title;
const body = draft.processTemplate("[[line|2..]]");
const css = '<link href="x-devonthink-item://DB8A0D35-1B24-4299-8559-B88DAAD14CF6" rel="stylesheet">'
const js = '<script src="x-devonthink-item://A413626F-AB37-4465-8906-9216649B7D59"></script>'
const findRegex = /(```)([A-Za-z]+)/g;
const replaceWith = "$1language-$2";

// Create the new draft
const newContent = title + "\n" + css + "\n" + js + "\n\n" + body;
draft.content = newContent;

// Replace the code blocks for Prism
draft.content = draft.content.replace(findRegex, replaceWith);
draft.update();

URL Step

x-devonthink://createmarkdown?title=[[safe_title]]&text=[[draft]]&tags=[[tags]]

Now all my notes and code snippets start in Drafts and when I’m done I can send them over to DEVONthink for reference and use later.