Saved unchanged
A typo fixed in one paragraph. That is the whole change the author made, and that is how the archive should record it: one paragraph different, the rest as they were. On a real archive, by the road a phone sends posts along, the engine could not do that up to 1.9. Measured on October 8: 101 posts changed by being saved unchanged.
What markdown cannot say
A post is stored as blocks, and the editor shows text. Between the two stands a conversion that mostly loses nothing — a paragraph is a paragraph, a heading is a heading. But an archive that came from an import carries things on its blocks that markdown has no word for: a paragraph Tumblr marked as indented, as a list item or as a line of a chat; a video's provider and the address it was first seen at; a player a service handed over as HTML. The text the editor shows carries none of it. And a save used to rebuild every block from that text: fixing one typo rewrote every other block of the post without them. At the desk and from a program alike; only at the desk nobody thought to measure it.
The question the other way round
Fixing it one thing at a time — bringing back a video's poster, a player's address, where a file came from — is the road the engine had taken three times, and there are more such things than anybody has listed. So 1.10 asks the question the other way round: not "what did this block lose" but "did the author touch it".
A stored block is written out as the text an editor would show and read back, on its own: that is what it looks like when nobody has touched it. Which is not always what it was stored as — a paragraph stored with a space at its end comes back without one. Where a block of the new text is written exactly like that, the stored block is what is saved, whole, with everything on it. What the text changed is the author's, as written. A block the text rewrote still keeps what the text could not have said about it — the kind an import gave a paragraph, a video's first address — where it can be told which stored block it rewrote: between two blocks kept as they were, the rewritten blocks are paired in order with the stored ones of their kind, when there are as many of each. A paragraph inserted beside a corrected one makes two for one, and both are saved as written.
Three kinds are left alone. A link card travels in the header, not in the text, and has its own road back. A stored block that does not read back as one block has no single block of the new text to be recognised in. And a block naming a file that arrived with this very save: what was measured from the bytes a moment ago is what is true now, and the stored block describes the file that was.
What is refused as a loss
What remains is what the text cannot carry at all. A second link card, a player from somewhere the engine does not know: such a block is lost by any save of that text, whoever makes it. At the desk, edit asks before letting it go. A program cannot ask, so a file that would lose it is refused as content_lost, and such a post is marked editable: false the moment its text is handed out — the phone shows it, but does not open it. Refused as a loss is only what the author never saw going; what they struck out of the text is the edit.
And a file with no text is not an edit. It is refused as empty, as a new post with no text is, because that is exactly what a program sends when it never had the text. The exception is a post that never had a body — a title with its tags, a link card — which is saved.
Against which version
The text a program sends back says edits: <slug> and base: <digest> in its header: the digest of the post's file at the moment the text was handed out. When the post has changed since — somebody edited it at the desk, or published it — the file is refused as changed, instead of quietly undoing whatever happened in between. A draft may come without base:; a published post may not. And a published post can now be edited from a program at all: up to 1.9 the road from the phone ended at the drafts.
Under all of that stays what was there before: what a post said before its last ten saves lies in content.nosync/versions/, and the [v] key restores from it.
Two deliveries at once
One more thing about saving, because it too showed up only in real use. incoming/ knows a picture by the name it was sent under, and every phone calls its first picture the same: of two posts sent at the same moment, the one made first got the other's 01.jpg, and both were answered ok. The receiver now takes deliveries one at a time; one that has waited five minutes is told busy and stores nothing. An answer that can be trusted is better than two oks.
One paragraph different
A save should change what the author edited and nothing else. It sounds like a definition rather than a feature, and that is exactly why it went unchecked for so long: at the desk, where a post was written in this engine and carries nothing from an import, it was always true. It has to be true of a post from 2011 that came from Tumblr and had a comma fixed today. The number it shows in is zero: that is how many posts now change by being saved unchanged.

Comments