So I needed to update my menu screenshots for the nvUltra documentation, which meant revisiting my NiftyMenu setup. In case you haven’t been raptly following the progress on that little side project, it’s a little tool that replicates any macOS app’s menus in HTML and allows for more flexible and consistent screenshot creation.

For a while it’s been 90% of the way to being a perfect tool for updating my documentation’s screenshots. It can easily set the background image, lock a menu item in place, add callouts, and even automatically shoot the screenshot, all repeatable via JavaScript. I’ve let go of the idea of ever having it so automated that I can include it as part of a build script, but I do have it to a point where it’s pretty close.

I added two new features to get me there: the screenshot (.shoot()) command now allows you to specify a filename, and there’s a Nifty “terminal.” The former means I can script menu screenshots and save them with filenames that match (and therefore update) existing screenshots in my documentation. The latter simply avoids the step of opening the Web Inspector, which is more a novelty than a requirement.

I will reiterate at this point that the screenshot capability of this tool only works in Chrome. But it works so well in Chrome that it’s worth running Chrome for it even if it’s not your primary browser.

The Terminal is opened by hitting $ while viewing a NiftyMenu HTML page. Paste JavaScript into it and hit Run. The pasted text will be split at semicolons and trimmed, run one “command” at a time. Because the NiftyAPI is all about chaining, you can write the entire script as one “command.” Here’s one that updates three nvUltra screenshots:

NiftyAPI
.config({
    darkMode   : false,
    bgImage    : true,
    arrowStyle : 'arrow',
    wallpaper: 'https://cdn3.brettterpstra.com/uploads/2020/05/uDTexture0015.jpg'
})
.find('edit/paste as').arrow().shoot('paste-as@2x%%r1000oh')
.find('format/convert selection').arrow().shoot('convert-selection-to@2x%%r1000oh')
.find('format/cleanup').arrow().shoot('format-cleanup@2x%%r1000oh')

I just keep that snippet in a text file in the same folder as my Markdown documentation, updating it as I add new screenshots. Whenever I paste it into the Nifty Terminal and run it, it instantly saves the updated screenshots to Downloads (occasionally shooting so quickly that I have to tell Chrome to “allow multiple downloads”). The weird %% suffixes on the specified filenames trigger a Hazel rule that then creates 1x and 2x versions, optimized and ready to move to my documentation folder.

Because the .find() command is fuzzy (it will find the closest menu item title match, even if the letters are non-contiguous), it’s resistant to changes to the menu ordering and wording. This means that as new menu items are added and I need to update the screenshots, I just have to regenerate the menus themselves (simply running the niftymenu.rb script); the script to generate the screenshots rarely has to change. And I can switch it to shoot in Dark Mode or with a different wallpaper just by editing the .config() call.

YouTube Video

The latest version with these changes is up on GitHub, if anyone else is tempted by the siren call of automating mundane tech documentation screenshots.