78Scribe: the editor bake-off nobody won
In the first post I promised a bake-off between two editor engines, with a simple and strict test. Here's how that went. Short version: nobody won, and that turned out to be the most useful result we could have got.
The rule
78Scribe's whole promise is your notes are plain files you own. An editor that quietly reformats those files breaks that promise, even if every change it makes is "harmless". You open a page, fix one typo, and suddenly git shows 200 changed lines, your tables are re-padded, and the AI assistant that also edits those files is looking at something it didn't write.
So the first test was as strict as I could make it:
- Open a real file and save it without touching anything. Not one byte may change.
- Change one word and save. Only that word may change.
Plus some practical ones: does it render tables, task lists, code and diagrams, can you paste an image, and does it feel nice to type in.
The contenders
After a longer shortlist (the decision record covers Tiptap, BlockNote, Toast UI and CodeMirror too), two made the final:
- Milkdown, built on ProseMirror and the remark Markdown parser, with Crepe, its ready-made editor UI.
- Vditor, a very complete editor with a Typora-style "instant render" mode.
Bob (the Claude session that writes the code) built a small Electron shell, put each engine behind the same interface, and ran them against two sets of files: 24 handmade edge cases, and 41 real Markdown files from my other projects.
The results
| Untouched, real files (41) | Untouched, edge cases (24) | One-word edit, real files | |
|---|---|---|---|
| Milkdown | 2 / 41 | 8 / 24 | 2 / 41 |
| Vditor (both modes) | 5 / 41 | 7–8 / 24 | 5 / 41 |
Both failed, badly. Not because they're bad editors, but because of how they work: they read your Markdown into their own document model and, when you save, write the whole file back out from that model, in their own style.
What that looked like in practice:
- Both re-padded every table into neat aligned columns. 26 of my 41 real files have tables, so that one habit failed most of them on its own.
- Milkdown "tidied" things:
P&LbecameP\&L, underlined-style headings became#headings, reference links were turned into inline links and their definitions deleted, and its image block replaced my image descriptions with a number (![Sample square]became![1.00]). - Vditor tidied less, but it damaged content: lines ending in a two-space line break were glued onto the next line, an indented code block turned into a plain paragraph, and some images disappeared entirely.
That last bit matters most. Reformatting is annoying. Losing text is disqualifying.
The part that changed everything
Buried in Bob's results was one number that changed the question. When you compare a one-word edit against the engine's own untouched output, the change stayed inside that one paragraph in 40 of 41 files for Milkdown. The edit itself was local; all the other noise was the engine's fixed habits, applied to everything on every save.
So instead of asking "which editor saves my file faithfully?" (answer: neither), we asked "what if the editor only gets to write the parts I actually changed?"
That's splice-on-save:
- When a page opens, remember exactly where every top-level block (paragraph, heading, list, table…) sits in the original text. Milkdown's parser records those positions, which is a big part of why it won.
- When you save, compare the blocks now with the blocks then.
- Copy every untouched block from the original file, byte for byte, odd spacing and all. Only the blocks you changed are written fresh.
- Read the result back and check it shows exactly what's on screen. If it doesn't, widen the patch a little and try again. If it still can't be sure, save the whole page, and say so loudly.
We kept Milkdown's core and built our own editor around it, without Crepe, so we control every piece that touches the file.
Proving it
A rule like "not one byte" needs tests that are just as strict, so two of them now run before every merge:
- The fidelity check opens every test file, makes specific edits (one word, one table cell, add and delete a paragraph, tick a checkbox), saves, and diffs the result against the original. Today: 76 of 76 files come back byte-identical untouched, and every edit changes only its own block.
- The stress test makes thousands of random edits and saves on the same files, the way a real person bashes at a page. The latest run: 1,672 sequences, 3,404 saves, 0 failures, and 0 whole-page fallbacks.
The bug I found by hand
The tests didn't catch everything at first. When I tried the editor myself, I added a few words to a title, made a phrase bold-italic, typed into a heading, and saved. The file came back completely rewritten: escaped characters, headings converted, a reference link inlined and its definition gone. Everything splice-on-save was supposed to prevent.
The cause: on the second save, an empty line I'd made by pressing Enter knocked the block map out of line, and the code quietly fell back to saving the whole page. Two lessons came out of that, and both are now rules:
- A fallback must never be silent. If 78Scribe ever has to rewrite a whole page, it now says so in red, every time.
- Test like a person, not like a script. That's where the random stress test came from. Its first runs found nine more ways to trip the save, all fixed now.
Where it's at now
Since the bake-off, 78Scribe has grown a fixed toolbar and the 78 UI Kit look (light and dark), autosave, the ability to notice when another program (VS Code, an AI, OneDrive) changes a page you have open, right-click menus, and spell check. Each of those went through the same fidelity and stress tests before it was merged. Autosave even found a nasty one: words typed while a save was in flight could have been silently lost. Caught, fixed, and now part of the stress test.
What's next
The next step, polish in the same spirit, landed just as I was finishing this post: when you do edit a table or a list, 78Scribe now keeps the style you typed it in, not just the blocks you didn't touch. Next, I want to write about the other half of the promise: why the files are the database, and what that means for working with an AI that reads and writes your notes too.
78Scribe also has a home now: 78scribe.com.
If you want to follow along, there's an RSS feed.