Drafts Syntax Development Tip13 Nov 2021
Earlier this year, Drafts version 26 was released with support for custom syntaxes and themes. Syntaxes are used within the Drafts editor to specify the look and in-app behaviours of the content. Themes are used within the Drafts editor to specify how the editor interface is displayed. The two work closely together.
For example you may have a syntax for lists where the syntax is configured to allow you to toggle a single character check mark at the end of a line. The theme could then specify what colour a checked line is and what colour an unchecked line is.
I have been experimenting in a bit more depth with this functionality over the last couple of months, and I want to share a little tip I have been using in speeding up my theme development process.
The Issue I Encountered
When developing themes and syntaxes for Drafts, sometimes you need to reload a draft or reapply a theme to get it to take effect. The larger and more complicated the draft the more likely this is to be required. This is partly to do with Drafts trying to be memory efficient (quick) and processing only what it likely needs to. But I think there are some other factors too where it just isn’t picking up triggers for changes when you might have thought it should.
I noticed this during my experimentation when sometimes the changes I had applied would not show. But when I returned later having made no further changes, they would display perfectly. My conclusion was that an occasional enforced refresh can help smooth out the process. Of course, this being Drafts, I could automate this process to make it trivial to apply a full refresh.
Refreshing the Theme
To refresh the theme, I needed to reload it, which meant applying a different theme and then reapplying the original. I decided that the best way to manage this for development purposes was through the use of workspaces. Each workspace can be assigned a preferred light and/or dark theme.
I created a workspace called “
_ThemeSyntaxDev” that filters for drafts tagged
syntax - I tag my drafts for developing new syntax with this tag. I then set the preferred themes to whatever themes I am developing with at the time. These will of course get changed as I change what theme I am working on.
Here’s how it looks today for example.
I created a second workspace called “
_ThemeSyntaxSwitch”. This workspace is a duplicate of the “
_ThemeSyntaxDev” workspace, but explicitly uses some standard themes. Therefore, themes I could never be editing and so would never be the same as the ones in the “
As I work in the “
_ThemeSyntaxDev” workspace, when I want to refresh the theme I am using, I can switch to the “
_ThemeSyntaxSwitch” workspace and then back. This is guaranteed to change the workspace being used and force Drafts to carry out full re-evaluations.
While I can manually do this, I can also tie it to a couple of lines of code through a Drafts script action step.
// Toggle workspaces --> Reapply theme app.applyWorkspace(Workspace.find("_ThemeSyntaxSwitch")); app.applyWorkspace(Workspace.find("_ThemeSyntaxDev"));
Refreshing the Syntax
With the theme refreshed, we can turn our attention to the syntax. The syntax is very much something tied to the individual draft, so we can either start switching the draft’s syntax back and forth or start switching drafts. I elected to do the latter as this then leaves modification dates unaffected on the draft being used to test the syntax.
Once again, while I could manually navigate between drafts, it is a simple matter to automate this. Originally I was navigating between the previously loaded draft and the current draft to keep the access order intact. However, when writing this post for broader consumption I decided to change this behaviour. This was in order to keep the access timestamps as clean as possible, and to account for scenarios where there may simply not be a previous draft available to switch to.
The result is I am creating a new empty draft, switching to that and then switching back to the original draft. Such a draft is managed automatically by Drafts in the same way as it would for an automatically created new, empty draft and a user navigating immediately to an existing draft - the new blank draft is discarded. The code to accomplish the reload of the current draft is therefore as follows.
// Toggle draft --> Reapply syntax let dNew = Draft.create(); dNew.update(); editor.load(dNew); editor.load(draft);
You can download the action from the Drafts directory. If you are developing your own themes or syntaxes, then I hope that this will give you a little bit of extra refresh power, and make your development workflow a little quicker and easier,