Notes
2026/04/13

Hypertext: editing all instances and the Unix philosophy

In any system where you can link to the same content from multiple places by embedding the content, you run into an interesting UX problem: When you're in a document that contains an embedded block (and which is also embedded in another document), how can you support both editing this embedded block across all instances (so that your change affects the other document as well) and as a single instance (so that your current document embeds a modified block, while the other document still embeds the original version of the block)?

Editing all instances

One option is to just disallow editing of embedded blocks in the documents where they are embedded. Editing is then only allowed by going to the page of the embedded block and editing it there directly. This is much more viable in hypertext systems with bidirectional links, because then the page of the embedded block shows its context by displaying the incoming links from other documents that embed the current block.

But what if we can't disallow editing? What if the hypertext system is just a viewer that processes and displays text files, which can be edited at will? What if pages are implicitly linked together whenever they share the same content and an embedded block of text is included, as text, in multiple documents?

In such a scenario, editing the embedded text in a single document should only edit this instance of the embedded text, effectively breaking the link to the other documents that still embed the previous version of that text block. But how can all instances of an embedded text be edited in such a system, where linked documents are just text files that happen to embed identical text blocks?

Well, if documents are just text files, we can just grep to find all files that contain the text block and sed to replace the text block, which produces a classic Unix one-liner:

grep -rl "old line" /path/to/dir | xargs sed -i 's/old line/new line/g'

The hypertext system can then stay focused on linking together documents and displaying them, without having to worry about how to edit text, which remains an orthogonal concern. The tool does one thing and does it well, by relying on a universal interface.

This is the Unix philosophy: Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.

This makes it much easier to integrate such a system into existing workflows. Want to use your $EDITOR to edit your files? Easy, just write a script that opens a file in your editor and then syncs the changes to all the other documents. Don't want to see the whole file when you just want to change a single paragraph? Well, just put the old paragraph and the new paragraph in a new file, then write a script that applies this “diff file” to all files. Want a more interactive experience? Write a small CLI tool that lets you jump from paragraph to paragraph until you select one, then opens your editor just for that paragraph, and finally writes that changed paragraph to all files.

The Unix philosophy

Let's see if we can apply the unix philosophy in other places: What if we put the hypertext system in charge of linking together documents, but made it as oblivious as possible to the markup language being used? In many hypertext models, these two aspects have been combined, but is that really necessary?

Decoupling linking from markup would allow us to use different flavors of markup. But isn't everyone using Markdown these days? Well, which Markdown? Gruber's original Markdown? CommonMark? GitHub Flavored Markdown? A Markdown superset? A Markdown subset? Something only Markdown-ish, like Gemini's Gemtext? The point is, what you think of as Markdown might not be what I think of as Markdown.

Decoupling linking from markup completely is difficult however. We might want to preserve the notion that a blockquoted > Some long quote here is the same as the original text block Some long quote here (without the leading >). We also might want to support wikilink-style [[Page X]] jump links that link directly to a page with title Page X. But does that mean that our hypertext system has to know about what block markup like > quote or # heading means, let alone which inline markup is available? (What does your favorite Markdown dialect use for intra-word emphasis and how do you escape your various inline markup characters?)

What we need is a notion of content blocks that can be preserved when a block is arbitrarily edited. This is what makes inline markup messy when considering links: It would be easy enough to say that This is an example sentence and This is an _example_ sentence should be linked together, because they are “basically” the same sentence, but what happens if we edit all instances of this embedded block simultaneously? Do we just ignore the inline markup? Then our edits would suddenly become lossy and drop the markup. Do we try to preserve it when we can? That becomes complicated very fast. Do we just block edit operations that involve markup? Or only apply the edit to blocks without markup? It's hard to see a clear winner here.

Applying arbitrary edits is much easier when we limit ourselves to block markup that is applied as a fixed prefix or suffix, effectively wrapping around the block that we're editing. We can then just reapply the prefix and suffix after making the edit. Normal blocks in a Markdown-like document system would then just be delimited by newlines at the start and the end, whereas blockquotes, lists, and headings are delimited by >, -, (one or more) #, some whitespace and then a newline at the end. We could even treat fenced code blocks as single blocks by treating triple backticks as the start and end delimiters. All without having to know anything about how these are rendered by the markup postprocessing of our hypertext system.

(And if we really, really wanted to use XML-like <block> and </block> delimiters, we could do that, too. Not that you should ever want that. But hey, you can't will what you will.)