You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Right now there are three ways that mark-level formatting can be applied in Slate:
Via mark objects that are embedded in the document itself.
Via decoration ranges (which contain a mark object) that are added to a specific node by the decorateNode middleware. These never actually live in the data model, and are a render-time-only construct.
Via value.decorations which contains a group of decorations that live in the data model, but not necessarily inside the individual text nodes. They are rendered similarly to the other decorations.
Each one of these has their own uses cases. Marks are for classic formatting like bold, italic, etc. Render-time decorations are for code highlighting, markdown highlighting, etc. And top-level decorations are for comments, suggestions, collaborative cursors, etc.
But there are also some confusing overlaps between the three, which leads to sloppier code and less performance.
For example, decorations are usually rendered at the block level, but their ranges are relative to the entire document, which makes isolating them while rendering less performant than it could be. And top-level decorations are stored in an immutable list, when many use cases require referencing them by an identifier, which requires slowly traversing the entire list.
What's the expected behavior?
I think we need to split them apart.
MARKS
The current marks use case is the most solid and widely used, and it will stay as is.
DECORATIONS
The render-time decorations use case (which was the first use of "decorations") will also stay very similar.
Except, the paths on a decoration will change to be scoped to the specific node that they are decorating, instead of relative to the document itself. This makes it easy to use paths only (and drop keys support in the future). It also means that they can be compared more quickly while rendering the tree of nodes.
In addition, instead of using a nested decoration.mark property, and overloading the renderMark middleware, they contain that formatting information as top-level properties. So a decoration will contain:
And it will be rendered with a new renderDecoration middleware.
ANNOTATIONS
The top-level value.decorations use case is the most problematic. It solves the "search highlighting" use case fine, but it isn't well suited to other cases like attaching comments and suggestions, or rendering collaborative cursors.
The first change will be to introduce a new name called "annotations" to separate the concept from the render-time "decorations". They are really two separate concepts, and although they share some similarities, it makes more sense to give them first-class treatment.
The second change will be to add a new annotation.key property, which is a unique identifier for the annotations. Since they will be stored as a Map instead of a List. This way adding, removing and updating annotations can all happen in O(1) time instead of O(n).
Annotations, like decorations, will stop overloading marks. And will expose their properties at the top-level:
And they will use the new renderAnnotation middleware to render themselves.
And since they are a new type of data in our data model, we'll also add three new operations to deal with them: add_annotation, remove_annotation and set_annotation—which share a common structure to the existing *_mark operations.
Although these are big changes if you're currently using decorations, for most people who are just using marks things won't be different. But they do make the decoration and annotation behaviors and data model much clearer.
The text was updated successfully, but these errors were encountered:
Do you want to request a feature or report a bug?
Improvement.
What's the current behavior?
Right now there are three ways that mark-level formatting can be applied in Slate:
Via
mark
objects that are embedded in the document itself.Via decoration ranges (which contain a mark object) that are added to a specific node by the
decorateNode
middleware. These never actually live in the data model, and are a render-time-only construct.Via
value.decorations
which contains a group of decorations that live in the data model, but not necessarily inside the individual text nodes. They are rendered similarly to the other decorations.Each one of these has their own uses cases. Marks are for classic formatting like bold, italic, etc. Render-time decorations are for code highlighting, markdown highlighting, etc. And top-level decorations are for comments, suggestions, collaborative cursors, etc.
But there are also some confusing overlaps between the three, which leads to sloppier code and less performance.
For example, decorations are usually rendered at the block level, but their ranges are relative to the entire document, which makes isolating them while rendering less performant than it could be. And top-level decorations are stored in an immutable list, when many use cases require referencing them by an identifier, which requires slowly traversing the entire list.
What's the expected behavior?
I think we need to split them apart.
MARKS
The current marks use case is the most solid and widely used, and it will stay as is.
DECORATIONS
The render-time decorations use case (which was the first use of "decorations") will also stay very similar.
Except, the paths on a decoration will change to be scoped to the specific node that they are decorating, instead of relative to the document itself. This makes it easy to use paths only (and drop keys support in the future). It also means that they can be compared more quickly while rendering the tree of nodes.
In addition, instead of using a nested
decoration.mark
property, and overloading therenderMark
middleware, they contain that formatting information as top-level properties. So a decoration will contain:And it will be rendered with a new
renderDecoration
middleware.ANNOTATIONS
The top-level
value.decorations
use case is the most problematic. It solves the "search highlighting" use case fine, but it isn't well suited to other cases like attaching comments and suggestions, or rendering collaborative cursors.The first change will be to introduce a new name called "annotations" to separate the concept from the render-time "decorations". They are really two separate concepts, and although they share some similarities, it makes more sense to give them first-class treatment.
The second change will be to add a new
annotation.key
property, which is a unique identifier for the annotations. Since they will be stored as aMap
instead of aList
. This way adding, removing and updating annotations can all happen inO(1)
time instead ofO(n)
.Annotations, like decorations, will stop overloading marks. And will expose their properties at the top-level:
And they will use the new
renderAnnotation
middleware to render themselves.And since they are a new type of data in our data model, we'll also add three new operations to deal with them:
add_annotation
,remove_annotation
andset_annotation
—which share a common structure to the existing*_mark
operations.Although these are big changes if you're currently using decorations, for most people who are just using marks things won't be different. But they do make the decoration and annotation behaviors and data model much clearer.
The text was updated successfully, but these errors were encountered: