* Add failing test showing splitBlock with isVoid bug Not sure what I actually expected calling `splitBlock()` on void block, but I would expect `splitBlock()` to respect a given block type's isVoid property. This failing test demonstrates that `splitBlock()` always creates a the new block with `isVoid: false`. * Fix isVoid not being copied when using splitBlock() The bug was actually inside `splitBlockAtRange`, as that's what actual drives `splitBlock()` (I assume the bug was therefore present in both methods). The fix is to simply copy across the `isVoid` value from the block being copied.
This directory contains all of the immutable models that contain the data that powers Slate. They are built using Immutable.js. Here's what each of them does:
Block
Just like in the DOM, Block
nodes are one that contain other inline content. They can be split apart, and wrapped in other blocks, but they will always contain at least a single Text
node of inline content. They can also contain associated Data
Character
The content of each Text
node is modeled as a Character
list. Each character contains a single character string, and any associated Marks
that are applied to it.
Data
Data
is just a thin wrapper around Immutable.Map
, which allows for more easily creating maps without having to require Immutable
itself.
Document
The Document
is where all of the content in the editor is stored. It is a recursively nested tree of Nodes
, just like the DOM itself. Which can either be Block
, Inline
, or Text
nodes.
Inline
Similar to Block
nodes, but containing inline content instead of block-level contain. They too can be nested to any depth, but at the lowest level will always contain a single Text
node.
Mark
Marks are the pieces of "formatting" that can be applied to strings of text in the editor. Unlike Nodes
, Marks
are modeled as a flat set, such that each character can have multiple marks associated with it. This allows for cases where a link (ie. an inline node) can also have bold (ie. a mark) formatting attached to part of it.
Node
Node
isn't actually a model that is exposed, but instead it's an interface full of convenience methods that Document
, Block
, Inline
all implement.
Selection
The Selection
keeps track of where the user's cursor is. It's modeled after the DOM Selection API, using terms like "anchor", "focus" and "collapsed".
State
The State
is the highest-level model. It is really just a convenient wrapper around a few other models: Document
, Selection
, and a History
which is not publicly exposed.
Since State
has knowledge of both the Document
and the Selection
, it provides a handful of convenience methods for updating the both at the same time. For example, when inserting a new content fragment, it inserts the fragment and then moves the selection to the end of the newly inserted content.
The State
is the object that lets you apply "transforms" that change the current document or selection. By having them all be applied through the top-level state, it can keep track of changes in the History
, allowing for undoing and redoing changes.
Text
Text
is the lowest-level Node
in the tree. Each Text
node contains a list of Characters
, which can optionally be dynamically decorated.
Transform
Transform
is not publicly exposed; you access it by calling the transform()
method on a State
model. It's simply a wrapper around the somewhat-complex transformation logic that allows for a state's history to be populated correctly.