Hacker News new | ask | show | jobs
by lewisjoe 884 days ago
It's great work improvising over Peritext using joseph's latest CRDT work. Much needed literature in "applying CRDTs for richtext" space.

But I'm surprised why this one too hasn't focussed a lot on rich-text block elements (like lists, tables & sections) as much as it focussed on text attributes (like bold and italics).

4 comments

I've gone through the Peritext paper several times, and attempted to implement support for lists/tables/sections myself, but found it to be difficult owing to the limited scope of the original paper. I reached out to Martin Kleppman about this, and this is what he told me:

"Thanks for your message. I've written up a document on how to extend Patreon with nested block elements such as bullet points. It's not properly published yet, but you can find a draft here: https://martinkl.notion.site/Block-elements-in-rich-text-CRD... My colleagues are currently in the process of integrating this algorithm into Automerge, and creating bindings to the ProseMirror rich text editor."

Personally, I found the document to be very helpful.

I've recently implemented a rich text editor on top of Automerge and Peritext that supports blocks, inline-blocks (or whatever you call them: images, tables, etc.), unaware that this was in the works. The implementation ended up _very_ close to what's described in the linked post.
Adding to the other great responses -

Coming from Google Wave, I still think of this problem the way we dealt with it in wave. In Wave, a document was a sequence of items + annotations. Items were either characters (collectively making up normal text), an item could be an embedded child item, like a table, image, nested document, etc. Embedded items were "in the document" just like any other document content, and could be inserted or deleted the same as text.

Then annotations were used for formatting, like bolded regions or links. This is how peritext and quill work. There are no "annotation items" (since managing them sounds tedious).

It looks like loro works slightly differently. I'd like to take my own stab at rich text in diamond types soon, since I need it for a project. I think there's a cleaner way to do it - though until I write the code, who knows how it'll turn out.

As others have said, once nice thing about this model is that embedded items can themselves be targets of editing events. For example, you could add a map to google wave and then users could collaboratively add and remove pins to the map.

By "annotation items" - you mean the special "boundary characters" that Loro CRDT uses to mark formatting boundaries right?

Yes, Google docs doesn't use such special annotation characters for bold/italics-like formattings. But it does use special boundary characters for marking "comment" boundaries. These characters simplify a few things from a comment perspective (as they shouldn't merge like formatting options). Zoho Writer uses a similar design for differentiating formatting boundaries vs comment boundaries.

> I'd like to take my own stab at rich text in diamond types soon, since I need it for a project. I think there's a cleaner way to do it - though until I write the code, who knows how it'll turn out.

Curious to take a look at your approach. Do write more on your blog Joseph :)

- Joe Lewis

> But I'm surprised why this one too hasn't focussed a lot on rich-text block elements (like lists, tables & sections)

This is where the real strength of crdts is, IMO. Tree-like structures turn into DAGs once you have multiple edits happening (two users editing a tree node create children with two parents) and are much more interesting than linear data like a string. It's definitely not the most efficient way to store data, but it's incredibly convenient for reconciling versions of pretty complex UI.

A few years ago I threw together a report-writing app for car crash data that let you drop different graphs, maps, visualizations, table excerpts (eg "select top 5 worst roads") that could all reference each other. You make a report for your hometown, and some other team could fork it to see the results for their area.

Data were all update live, even if it was pinned to a specific time, since things could be updated after the fact. That other team could then add in a new section of the report or change the conclusion section, and still get the first team's updates to the shared sections (with an option to revert).

You can do like... most stuff like that, if you want. Slides, tables, drawings, whatever. It's not great for graphs but idk what is good for graphs.

The demo they show uses the Quill rich-text editor, which handles block elements analogously to text attributes: a block's type is determined by the attributes on its trailing newline. E.g., for a block that is part of an ordered list, the newline's format is `{ list: "ordered" }`.

https://quilljs.com/docs/delta/#line-formatting