Automatic Image Upload With Buttondown + Typora

This post was originally written for Buttondown and you can find it here!

If you’re a fan of writing content in Markdown there’s a high chance you’ve heard of the absolutely fantastic editor / real-time Markdown rendering genius, Typora. Aside from being simplistic while still having an absolute boat-load of features that we don’t have time to get into, suffice it to say that Markdown + Typora is my favorite way to write. The Newsprint Theme is where it’s at:

Typora

And writing content intended to be sent in Buttondown couldn’t be easier. Just write everything up how you like, hit Cmd+/ to switch to source code mode and copy the raw markdown text, then paste it into Buttondown and send! Except… images.

Images are tricky. Typora is more than happy to render your images inline as you write a new document, which is really nice:

image-20230502070736404

But if you’re using local images in your document (as you likely would be) you might run into trouble when copying that document over to Buttondown. And ‘local’ is the keyword here. When Typora renders those local images inline, all it’s doing is reading the image content from your filesystem:

image-20230502070822228

Failing Email Images Ahead

And there in-lies the problem. If you were to copy that document over to Buttondown and send it out, that image wouldn’t load for anyone!

image-20230502071207221

The source of the generated HTML would still be looking for an image on that local file path, which isn’t going to exist on your recipients’ machines (or be accessible by their mail clients anyway). Worse still, if you send a draft email to yourself beforehand and open it in your own local email client, since you’d be looking at that draft from the same machine where that image file-path does exist, you may well have the experience of “everything working” and not realize that your images will fail when sending to anybody else.

Upload Magic

Good news, though. Typora has a neat, extensible system built in to automatically upload images to a third-party web service instead of just rendering local images inline. And Buttondown exposes their image upload functionality through their API! Together, with a small chunk of glue-script, we get an experience like this:

trimmed

Any time we paste or drag an image into Typora, it automatically uploads that image to Buttondown’s image hosting service and injects the resulting URL into the Markdown for you. Now our image is publicly hosted on the cloud! Even better, once we finish writing our document, we can have confidence that copying it over to Buttondown for sending will bring portable (publicly accessible) image URLs that are safe and ready to be sent in emails!

image-20230502072617589

We’ve essentially cloned Buttondown’s “drag an image into the editor for auto-upload” into Typora 😎

But How Do I Do That?

It’s actually pretty easy! As Typora notes in their “custom” image upload docs, we just need to provide a script into the Settings -> Image -> Image Uploader: Custom field and set When Insert… to “Upload Image”.

image-20230502072821391

We’re going to use an inline one-liner bash script to do the uploads for us. This one took some time to craft just right, but does exactly what we need it to. Make sure to grab your API key from Buttondown and add it to this script before pasting into Typora:

API_TOKEN="YOUR_API_KEY" && upload() { for file_path in "$@"; do response=$(curl -s -X POST -H "Authorization: Token $API_TOKEN" -H "Content-Type: multipart/form-data" -F "image=@$file_path" "https://api.buttondown.email/v1/images"); echo $(echo $response | sed 's/.*"image": "\([^"]*\)".*/\1/'); done; return; }; upload 

And be careful to copy and paste that code as a single line. It is not a multi-line script.

image-20230502072943868

So what does it do? Let’s break it down into multiple lines for readability and we’ll see it’s not too complicated:

API_TOKEN="YOUR_API_KEY" &&
upload() { 
	for file_path in "$@"; 
	do 
	  response=$(curl -s -X POST -H "Authorization: Token $API_TOKEN" -H "Content-Type: multipart/form-data" -F "image=@$file_path" "https://api.buttondown.email/v1/images");
		echo $(echo $response | sed 's/.*"image": "\([^"]*\)".*/\1/');
  done;
  return;
}; 
upload 

Essentially we setup the “upload” routine to iterate over all arguments given to it ($@) and for each, POST it to https://api.buttondown.email/v1/images, Buttondown’s image API. We pull the "image" key out of the JSON response with sed and output it to StdOut (which is what Typora wants) — specifically avoiding more eloquent JSON tools like jq since not all Typora users will have that tool installed (or globally available). Once we’ve gotten through all the arguments, we return!

We’re setting this up as a method then ending the command with a call to the method because of how Typora invokes the command. Typora essentially invokes COMMAND "file/path_1.jpg" "file/path_2.jpg" — it just adds the local file-paths as strings immediately after the command. Since we’re setting up upload as a routine and ending the command with a call to upload, those appended strings actually get regarded as arguments to upload, exactly what we want.

As always, once you paste in the one-liner, make sure you hit the “Test Uploader” button and get a green, “Successfully get uploaded image url” message.

image-20230502070434529

That’s it! Automatic image-upload and ultimate Markdown portability. Enjoy writing your future Buttondown content in Typora!

Join the Conversation

Latest Blog Posts