惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
博客园 - 三生石上(FineUI控件)
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
D
Docker
S
SegmentFault 最新的问题
博客园 - 聂微东
美团技术团队
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
GbyAI
GbyAI
L
LangChain Blog
Vercel News
Vercel News
博客园 - 叶小钗
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
Engineering at Meta
Engineering at Meta
T
Threat Research - Cisco Blogs
T
Threatpost
Scott Helme
Scott Helme
T
Tailwind CSS Blog
Latest news
Latest news
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
The Register - Security
The Register - Security
罗磊的独立博客
P
Proofpoint News Feed
腾讯CDC
S
Schneier on Security
雷峰网
雷峰网
A
About on SuperTechFans
T
Tenable Blog
F
Full Disclosure
Cyberwarzone
Cyberwarzone
博客园_首页
有赞技术团队
有赞技术团队
K
Kaspersky official blog

文章列表

Compulsive curiosity, or, how I built an infinite idea machine Gift details on the subscriber portal Portal link in the archive nav The physicists who convinced Fermilab to send Brazil's emails First, add no friction: How micropayments lost and subscriptions won Filter subscribers and automations by source Automations, rebuilt What email will look like in the future Filter subscribers by bounce date and reason Email could have been X.400 times better Three features are moving behind the paywall Firewall changes and improvements Put your name and voice into your company newsletter Simplified email address settings Subscription wall Inboxes were overwhelming before we'd even named them The US government tried really hard to screw up email Public postmortem: database connection exhaustion Ask a nerd: what is the best way to unsubscribe from newsletters? Bookshop.org embeds Email was into agents before they were cool Passwordless login Rename metadata keys in bulk A spring cleaning for our legal docs Ask a nerd: what happens when you click the spam button? Passkey support for two-factor authentication How Buttondown's API versioning works Safer defaults for the email creation API How to send email to space How we enabled Content Security Policy for everyone Recovery codes for two-factor authentication Filter sent emails by engagement rate How we migrated to TypeIDs without breaking clients How we check every link in your email Use newsletter metadata in your emails Should we bring back email exploders? Sort and filter by open and click rates Custom click tracking domains More newsletter settings in the API Revamped replies Custom email templates for everyone Simplified cancellation Ask a Nerd: Does email length affect deliverability? The changelog, reborn Swedish localization Forwarding an email is not always straightforward Public descriptions for tags OpenAPI spec for archives How Rodrigo brings a humanistic view to consumer technology How Brandon Lucas Green shares his music and supports artists Subscribers can come from anywhere. Even another newsletter platform's form. Your newsletter's archives are more valuable than your list Survey responses on the web Better tag self-management Smarter automation filters Granular API keys Ask A Nerd: How does newsletter cadence affect deliverability? New design settings pages Snippets Starred views More ways to customize your archives Inbox filtering Mastodon follower analytics Ask a Nerd: What are good open, click, and response rates for an email newsletter? How we migrated our database to PlanetScale Two new archive themes Ask a Nerd: Does attaching files to your newsletter hurt deliverability? Custom buttons now work in Markdown mode Seline and Tinylytics support Unban subscribers Announcement bars for your archives Public postmortem: archive downtime Bang paths, source routing, and how email trips were planned 2025 disposables.app Russian localization Ask a Nerd: Can you improve email deliverability with a personal domain? More locale options How we interview customers at Buttondown Bluesky analytics Minimum viable complexity Reply to conversations How Jeffery Hicks goes behind-the-scenes in his newsletter Changes to our stack in 2025 2026: Emails Randomize survey answer order TK reminders in the editor What the hell is a UTM? Why we insourced analytics Scroll sync in the editor 2026: Archives How Kelly Jensen uses Buttondown to discuss key library issues How Jamie Thingelstad uses Buttondown to explore tech topics Keeping feature creep at bay Improved filters Content Security Policy in archives Open source Sniperl.ink Auto-activating RSS reader subscriptions What the hell is ActivityPub? Gift subscriptions
Automatic image upload with Buttondown + Typora
Jon Sully · 2023-05-03 · via

Introduction

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's 'Newsprint' theme

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. <u>Make sure to grab your API key from Buttondown and add it to this script before pasting into Typora</u>:

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.com/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.com/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.com/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, <u>make sure you hit the "Test Uploader" button and get a green, "Successfully get uploaded image url" message</u>.

image-20230502070434529

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