I know you need an nvUltra update, so I’ll attempt that in less than 50 words: 99% finished, beta testing going well, couple bugs left, need to finalize our pricing model. Our personal lives are dictating release timing, and it may be out another month or so. I promise a more thoughtful update soon.

But I do have this other thing you might like today.

I have a new update for Marked 2 almost ready for release. It incorporates a change to its very core, though, that there’s a nontrivial chance I’ve broken some part(s) of its extensive feature set and haven’t noticed yet. That’s why I’m asking anyone who uses Marked to download the beta below and give it a whirl. You can always switch back to the stable release, and I promise it won’t destroy any data or harm your machine (not liable, of course, standard disclaimer). It would just be very helpful to have people use it the way they always do and see if anything in their routine no longer works as expected.

If you’re into testing and don’t want to read all the stuff I’m about to say, and it might be a lot, just download the beta build below and get going. The beta is free to use and time-limited. You can run it alongside your current version. If you use the MAS or Setapp versions, your current preferences won’t show up in the beta, but it will work all the same.

Please use the Beta Testing category of the Marked support site for feedback and bug reports. (Note: please start a new conversation for every report, Tender is not great for multi-user, multi-threaded conversations.)

Download the beta here. Ok, antsy pants, just take it and go.

Generic NPR sign-off plays softly.

Did you stick around to learn more? Thanks! The suspense was killing me.

The Modest Release Notes

Release notes really have a way of compressing a hundred hours of work into a one-line summary, you know?


  • Support for Bear’s ::marker:: and -strikethrough- syntax when previewing a Bear note


  • Load preview contents via JavaScript DOM replacement instead of full refresh for smoother updates
  • Allow base URL to be sent with streaming preview to enable relative paths
  • Cleaned up Syntax Style and MathJax popup menus. Weeded out less common options, removed extensions from the display, and alphabetized
  • New layout for Help->Custom Processor Log, shows both preprocessor and processor, with STDIN and STDOUT side by side
  • Reduce download size by cleaning out some frameworks and moving Help assets to load remotely
  • Heavy-duty JavaScript refactoring
  • Smooth out section-collapsing animation


  • Replace horizontal rules with page breaks

Not even one of my longer changelog entries. It’s just that first improvement, the JavaScript DOM injection, was, well, a whole thing.

Let’s Have a Story

A long time ago I built a feature into Marked called the Streaming Preview. It was a special window in Marked which — instead of reading a Markdown file from the disk — watched a private pasteboard (fancy dev-speak for clipboard) for text to be copied onto it. This meant that any application could “stream” text to Marked’s preview just by writing it to this special, private pasteboard. I built the Streaming Preview to try and solve the issue of Markdown apps that didn’t always store text files on disk, such as Ulysses, Bear, Drafts, nvALT in database mode, etc.

To work, though, it requires that developers implement it in their apps. I can’t just watch their files like I do with most apps. I added it experimentally in nvALT (it’s still there), but I always used nvALT with plain text files, so even I wasn’t making a lot of use of it. The feature languished for a few years, and then suddenly in 2020, for some reason, apps started adding support for it. Drafts (for Mac) now implements it, as does The Archive, and I’m proud say nvUltra (beta) has a great implementation of it (largely because I’ve added features that none of the other devs know about yet… unfair advantage). So it’s gaining traction, but there was a problem.

It Just Kinda Sucked

Marked, in its current stable form, reloads the page on every update. This has been necessary for a good number of its features to operate smoothly. It works acceptably when you’re only updating on saves, but the result when picking up rapid changes as an app updates the pasteboard while you type is it basically just starts flickering until a couple seconds after you stop typing. Ugly.

The fix was pretty obvious, and it’s the way I’ve implemented most other Markdown previews (and the way most of the world does it): inject the changed content into the existing DOM via JavaScript. I won’t go into exactly how many of Marked’s features immediately broke when making the switch, but it was more than enough to have put me off doing it for years. But now was the time.

Stage lights dim. Laboratory set is wheeled out.

Two weeks of working in the lab ensue. Every bug that gets fixed reveals two more. Our main character builds it back up from the ground. He grows a beard. Then, he emerges from the lab, center stage. “Scathed but victorious,” he mutters to himself. “Yay, it finally works the way it should have from the beginning.” “Don’t get sarcastic with me.” Indistinct grumbling.

The first light of day creeps across the sky as our protagonist holds his creation before him. Scene.

In Marked 2.5.44 (beta), the rendered HTML now injects directly into the DOM, and features such as the table of contents, word count and document statistics, keyword highlights, bookmarks (even the mini map), MathJax and Katex, and syntax highlighting all keep pace. The result is noticeably smoother updates, less jerking around when scrolling to edit points, and in the case of the Streaming Preview, it went from barely useable to a downright delight.

A Good Idea

One potential issue with reading text from a pasteboard with no base file is that relative URLs are meaningless. That means that in some cases images which worked fine in another app would show up as missing in Marked when it processed the same text. I came up with a solution and, gosh darnit, it’s clever.

Obviously, I just needed to allow a URL to be passed from the outside app; a reference to a real point on the local system that the preview window could pretend it was rooted at. But I didn’t want to start requiring the pasteboard contents to be JSON or other structured data. In addition to being inconvenient, it would be difficult to make it backwards compatible for the apps that have already implemented it. I also didn’t really want to have a second named pasteboard to be polling, and I didn’t want to mess with making developers insert any metadata into the text they were sending. I like to be nice to developers, they’re great people.

You probably know that the macOS clipboard handles multiple types of data simultaneously. If you copy a link from a web page, there’s a plain text representation, a rich text representation, and a URL representation of it. There’s also an image clipboard, and it’s possible to have all four of those types filled with some kind of data at once. Depending on where you paste it, you get the appropriate version.

So my solution is to let the developer sneak a URL into the NSURLPasteboardType alongside the NSStringPasteboardType that holds the text when they write to the private pasteboard. It just takes an extra line of code or two to implement, and if the URL pasteboard type isn’t populated, it just moves along as it always did before. See? Smart.

When this update is complete I’ll be able to proudly suggest that other devs incorporate Markdown previews via Marked 2’s Streaming Preview. If you’re curious, here’s how easy it is.

So Help Me Test It

So I’ve put a couple of weeks into this so far, and I think I have the wrinkles smoothed out. Before I release it to automatic updates for everyone, though, I would really like to have some eyes on it, putting it through its real-world paces. I don’t care how you use Marked; if you use it at all, please help me test and make sure whatever you usually do with it still works!

As mentioned earlier, I’m reviving the beta testing category on the Marked support site for feedback. It’s far more helpful to me if you start any conversations there as opposed to Tweeting or emailing me. But by all means, start conversations there and let me know how it’s going! (Again: please start a new conversation for every report, Tender is not great for multi-user, multi-threaded conversations.)

Here’s the download link again. This build is on a separate Sparkle update feed, so you’ll get automatic updates as new beta builds come out. Once it’s stable, I’ll release an update to the beta channel that will bring everyone back together on the main feed. You can keep your existing version of Marked 2 as is, no harm will come to it.

Thanks for your time.