Welcome to the lab.

Automated web image workflow, part 1

[Tweet : nvALT]

I’ve been using a workflow for web images for a while. The final part of the workflow is specific to my Jekyll install, so I’ll be taking a look at whether I can make that of more general interest or not. I think the first two parts are pretty cool, though.

We’ll start at the beginning of the optimization stage. You’ve created (or received) the final image destined for the web. You know the specific sizes the destination site needs for optimal display. On this blog, I start with 1600px-wide image for full-width, 700px for inset, both being the @2x size for high-resolution displays. The step between hitting “Save” and uploading it to the web, then, is usually to resize, output 1x and 2x versions, and optimize the results.

I do this with Hazel and a special naming pattern. When I save an image, I can add a series of special characters at the end, separated from the name by a double percent symbol (%%). When Hazel detects an image on the desktop or other defined folder that matches that scheme, it runs a script that parses out the options, does the conversions and optimizations, and then outputs file(s) with the correct names to the original location.

For example, if I save a file to the Desktop titled header_image@2x%%oh.png, the h will cause a 1/2 size version (i.e. @1x) to be output, and the o will cause both versions to be optimized (shrunk, squished, crushed, whatever is appropriate).

Any combination of options can be used, and in any order after the %% in the filename. Here are all the options:

ooptimize image
Tool chosen automatically based on file extension
cconvert PNG to JPEG
Ignored if the file is already a JPEG.
Because photographic images with a wide color range and no need for transparent background are significantly smaller as JPEG, I mostly use this one to automate processing of files sent to me by others.
hcreate a half size image
Assumes the original file is the high res (retina) version and creates a 1x version at exactly half the original dimensions. If the original filename (before the %%) includes @2x, it will just create the same file without the @2x in the name. If not, it will add _sm to the second filename.
rXXX[xXXX]resize to width or max-[width]x[height]
r followed by a numeric width will resize the image to a maximum width of that size (e.g. %%r800 resizes the image to 800px wide, with the height automatically determined). %%r800x600 will resize the image to a maximum width of 800px, or a maximum height of 600px, whichever is the larger dimension.


The script requires jpegoptim, pngcrush, and convert from the ImageMagick package. These command line tools have the benefit of being exceptionally scriptable, but also usually give me better lossless compression than any of the commercial image compression tools. Win-win.

All of the aforementioned tools can be installed with Homebrew:

brew update && brew install jpegoptim pngcrush imagemagick

Save the script from this Gist to a local file, make it executable, and add a Hazel rule to whatever folder(s) you want to watch for file saves.

The criteria of the rule should ensure that the file is an image format, and that the name contains %%. Then it should just run a shell script action, pointing to the script you saved above.

From here, just save images with the special filename format and give it a few seconds to run all of the other stuff in the background. Obviously, the same script and techniques could be used to just automate the build process in certain types of blogs, but this method gives me the flexibility to use the naming scheme on images with any destination, and handle/automate the actual upload and as a separate step.

As an example, the Hazel screenshot above was created using macOS screen capture in crosshair mode on my Retina display, saving a PNG to the Desktop. I renamed the file to ImageOptimHazelRule@2x%%r1600hoc.png and got an optimized JPEG version of the screenshot in 800px width and a 1600px @2x version.

I do, as always, hope that this script is useful to at least 5 people because then I feel like it further justifies the time I spend on saving time. If you’ve read this far, you probably know what I mean. On the next episode, I’ll share my scripts and tips for automating the generation of Open Graph images for social media sharing.

Web Excursions for March 13, 2018

[Tweet : nvALT]

Web excursions brought to you by MightyDeals.com, featuring great deals on software, training, and design resources.

A general date-picker script for any tag type - TaskPaper
I learned a lot about JSX and nibs playing with this one (from Rob Trew, of course).
Dictionary.com now offers definitions for emoji
It’s about time.
Devhints — TL;DR for developer documentation
A large collection of developer cheatsheets, created by @ricostacruz.
PSA: iOS Markup is not designed to be a redaction tool for sensitive information
Side note, don’t expect iOS Markup tools to cover your tracks.
Leonard Cohen - Peel Session 1968
For LC fans, the complete July 1968 session recorded with John Peel on BBC Radio 1.

Deckset 2.0 is more of a great thing

[Tweet : nvALT]

I first wrote about Deckset back in 2014. Since then I’ve continued to love it as an alternative to Keynote, using it whenever I can for presentations. At CMD-D last summer, I hadn’t expected to be speaking, but when Andy Ithnako had to call in sick, I wrote a full slide deck in Markdown on breaks between talks. I’m very excited to let you know that version 2.0 has been released, and it covers some of the requests I and other users have had over the years.

First, you can customize the themes. It comes with a wide selection of styles, but I’ve always longed to be able to change them just slightly for my needs. Now you can adjust colors, fonts, and general layout, and even export and share the theme with others.

You can also just use Markdown headers as slide dividers (as opposed to horizontal rules), making presentation creation that much faster. You can also add customization to a single slide using metadata headers to do such things as temporarily disable slide numbering or change a footer.

With the release of version 2, Deckset has announced they’re leaving the Mac App Store. The new version is available exclusively via direct purchase, which — as a side effect — gives them a lot more flexibility with coupons, pricing, and educational discounts.

Deckset is definitely the coolest, easiest tool I’ve found for creating slide decks quickly and beautifully. The current version runs $29 US, with site licenses available. If you bought Deckset after March 1st, 2017, you can receive a free upgrade. Check it out!

The OmniOutliner 3 winners!

[Tweet : nvALT]

Congratulations to the winners of the OmniOutliner 3 giveaway! It turned out to be one of the most popular giveaways I’ve ever run here.

There ended up being 6 instead of 5 because the Giveaway Robot made its first ever mistake1. Omni was very gracious and provided an extra code to remedy the snafu.

I’ve heard back from most of the winners already, but if you’re on the list and haven’t heard from me yet, let me know and I’ll re-send the email.

  • Guillaume Barrette
  • Mac
  • Vincent Oostindie
  • Abhishek Jain
  • Adam Hansen
  • Florent Costiou

Thanks again to everyone who entered, and if you didn’t win, you can grab the free trial and there’s still a little time to snag the intro price!

  1. Ok, fine, it was human error. I hit CTRL-c because I realized I’d made a typo in the email template, but the first random winner had already been sent. If the Killotron has any fault, it would be that it’s too good to be stopped.

RocketTab malware and the Tab Manager Chrome extension

[Tweet : nvALT]

Chrome slowed down for me this week. It’s always been a memory and CPU hog, but this got ridiculous. Like grind-my-system-to-a-halt ridiculous. Unable to determine the problem, I switched to Firefox. But I figured out the Chrome issue today.

Side note: I haven’t used Firefox for years but I’m pleased to report it’s become an amazing browser in the meantime. I’ll definitely be continuing to use it as more than just a testing browser for web development.

So the clue for me was that my DuckDuckGo search pages started coming up with ads injected at the top.

The perpetrator was kind enough to add a label, “RocketTab powered by Advertise,” at the top and bottom of the injected results, so it was easy enough to search for. Apparently the RocketTab ad/malware has been around for a long time, and the “powered by Advertise” mutation is only the most recent incarnation. Over its lifespan it’s been everything from a bundled application to browser extensions. It purportedly just injects ads across a bunch of different services with redirects and affiliate links to gather commissions. It also slows your entire computer down tremendously, which seems odd for something so supposedly innocuous.

I started by searching through all of my recently-installed apps. I’m not careless about installing untrusted apps, so that wasn’t likely, but I deleted some cruft. No change.

I ran MalwareBytes, which specifically lists RocketTab as one it detects (and which is, by the way, a very good anti-malware app), but no results there.

So I jumped into the web inspector and started tracing the XHR calls that were made when the ads were injected, then searching for the strings in my Chrome extensions folder. I turned up nothing. Convinced it had to be an extension — and I run a lot of them1 — I disabled all of them. Ads went away. Enabled them one by one, repeatedly refreshing the DuckDuckGo search page to see when they came back. Boom: Tab Manager.

I’m not going to link it here, but see the image above if you need to confirm which one I’m talking about. You’ll immediately note on the Reviews tab that it’s reported as malware. Repeatedly. Many, many times. I reported abuse, as I assume many of the dozens of commenters have, so it’s unfathomable to me that the Chrome Web Store has continued to allow its presence. This apparently only happened with the latest update to the extension published this month (February, 2018).

Long story short, if you see “RocketTab powered by [anything],” figure it out, fast. I read reports that “YouTube Video Downloader” also had the same PUP, and I’m sure there are a dozen others. Disable all your extensions and re-enable them until you find it.

Deleting the offending extension fixed the problem and all of the issues I was having. I’m adding adware (and malware) creators to the list.

  1. I know, I know, “and then you wonder why Chrome gets so slow.”

Web Excursions for February 26, 2018

[Tweet : nvALT]

Web excursions brought to you by MightyDeals.com, featuring great deals on software, training, and design resources.

The app formerly known as MacID has been renamed to Unlox and updated to work with Face ID on the iPhone X. If you fancy unlocking your Mac with your face, here you go.
Omoshiro Block
Not my usual type of link, but this is beautiful. The Omoshiro Block utilizes laser-cutting to reveal objects as the pages are used. Go see the pictures.
ShotBox on the Mac App Store
A handy little (free) utility that adds markup capability to screenshots taken with macOS system tools. No organizer, no built in screenshot tools, just a handy augmentation to default screenshots. If apps like Capto, Monosnap, Pixa, and others are overkill for you, this might be a great solution.
Another warning: Don’t convert your Time Machine volume from HFS+ to APFS
A warning from Macworld about APFS (macOS High Sierra) and Time Machine. Basically, don’t convert your Time Machine disk to APFS, but the details are worth understanding.
ARKit+CoreLocation is an open source library that allows items to be placed within an AR world using real-world coordinates and, by using CoreLocation, improves accuracy to a point where things like Point-of-Interest AR get easier. I’m not currently working on any AR, but it’s exciting to watch the apps and the tools grow.

OmniOutliner 3 (+giveaway!)

[Tweet : nvALT]

OmniOutliner 3 for iOS is out and it’s a big update. See the bottom of the post for a chance to win a Pro license.

This iOS release brings parity with OmniOutliner 5 on Mac, and adds iPhone X and iOS 11 support. It also includes support for printing, new drag & drop features, PDF export, document encryption, and interface updates, including inspectors and new focus and filtering options.

OmniOutliner is now split into two versions: Essentials, and Pro (like the Mac version is now, too). Essentials is a limited in features, but also less expensive ($9.99 US), and easily serves the needs of many people just looking for a solid outliner app. It can print, add notes, export multiple formats, and sync via OmniPresence. It also features “Open In Place,” which allows you to open a file from Dropbox or the Files app, edit in OmniOutliner, and save changes in its original location. Man, I always hated that old sandbox dance.

The Pro version is a $39.99 in-app purchase (both versions are free downloads with 14-day trials). It has everything that Essentials has, plus the ability to “focus” on sections of your outline (including support for multiple selections), and filters with saved searches (including searches set up on your Mac). It can also encrypt your documents on disk (so on the server as well) with AES-256 encryption. If you’re brainstorming in OmniOutliner, encryption means trust and peace of mind, so this is great news (I refer you to Joel Anderson on Systematic).

Perhaps the most exciting thing to me is the inclusion of Omni’s new scripting tool, Omni Automation. Sal Soghoian talked about it a bit on (another great episode of) Systematic, and focused heavily on it in talks at the CMD-D conference (where I was lucky enough to get to speak alongside a bunch of automation heroes). It’s a JavaScript-based scripting language that provides cross-platform automation. If it works on iOS, it works on Mac without alteration. You can see some of the things people have already done with it in OmniGraffle via Omni’s Discourse section.

Omni has kindly offered five Pro version codes ($39.99 US value) for BrettTerpstra.com readers. Enter below with your name (full please) and an email address (as always, only for contacting winners, lists are discarded after the drawing). Five winners will be drawn on Tuesday, February 27 at 12pm CST.

Also check out the free trial of OmniOutliner 3 in the meantime!

Sorry, this giveaway has ended.