![]() ![]() We still use the contenteditable attribute in the final version, because of some practical implications we’ll discuss shortly, but we made a conscious decision to rely on it as little as possible. That’s because the browser generally only recognizes two types of editors: plain text editors, such as and elements, and free-form editors that are created using an attribute called contenteditable. ![]() At least not from the browser’s point of view. Viewĭuring the majority of the development of our RTE, our editor wasn’t even an editor. Our Rust reducer then processes these actions and handles all the edge cases, including things like making sure the cursor doesn’t end up in the middle of an mention. And the unit determines if we’re moving the cursor per Unicode grapheme cluster (what a user typically calls a “character”) or per word, for when the user holds the Ctrl/ ⌥ key. The extend_selection property is used when the user holds the Shift key, to extend the current selection, or create one if there isn’t one yet. The delta specifies whether the cursor moves forward or backward, by specifying a value of 1 or -1. For example, when the user presses the left arrow key, we dispatch a MoveCursor action with the following payload: One piece of logic that we had to introduce ourselves to accommodate the RTE (which we didn’t need yet when we were still using Slate), was cursor management. #Rich text editing codeWe created fp-bindgen to generate bindings between the Rust code and the TypeScript code that invokes it. To make this logic easily testable, it is implemented as pure functions that we invoke from Redux reducers in TypeScript. But now we were able to use the same primitives to power our editor as well. Mind you, we needed most of this logic anyway, because we also needed it for our OT algorithm. When you’re typing in a cell, where do we insert the newly typed characters? How does that affect the content and the associated formatting? What should happen if you toggle formatting on a selection? What if you split a cell in the middle? All of this and more is implemented in the core logic in Rust. With the data model also comes code for interacting with it. In addition, the simplicity of only having a single offset for each annotation makes it easy for us to implement the Operational Transformation (OT) algorithm we use for collaboration. We intentionally did not choose a tree-like structure similar to HTML because formatting ranges can overlap, which would lead to complicated tree manipulation. For this post, we’ll focus on the TextCell:Īs you can see, it’s nothing but a list of annotations that define the type of formatting to apply and the offset from where it starts. So we settled on a data model that would be beneficial both for our collaboration features, as well as for the RTE that powers any of the rich text fields that we use inside cells. A notebook is a block-based editor comprised of different types of cells, ranging from text cells to images and graphs. ![]() Our product is a collaborative notebook editor. In this post, we’ll discuss the challenges we faced and how we tackled those. The downside? RTEs are notorious for their need to support complex user interactions, and now we would need to handle every interaction ourselves. #Rich text editing fullIf we could just implement the view directly in React, we could simplify our stack considerably and have full control over every aspect of it. We used Slate for the view, though as a result, it pulled in its own data model as well. A view that renders the state of said data model and that handles the user interactions.A data model and the core logic to operate on it.So we got to thinking - what if we just built our own Rich Text Editor (RTE)?įrom a very high-level perspective, a rich text editor is comprised of two components: We used to use Slate.js - a fine editor - but as we’re implementing our own rich text primitives for collaborative editing, we discovered the disconnect between our own primitives and Slate’s data model to be somewhat of a hindrance. At Fiberplane, we recently encountered an interesting challenge: We were outgrowing the library we were using for our rich text editor. ![]()
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |