A completely customizable framework for building rich text editors. (Currently in beta.)
MIT License
Bot releases are hidden (Show)
Published by juliankrispel over 3 years ago
Published by ianstormtaylor over 7 years ago
filterDescendants
and findDescendants
methods are now depth-first. This shouldn't affect almost anyone, since they are usually not the best things to be using for performance reasons. If you happen to have a very specific use case that needs breadth-first, (or even likely something better), you'll need to implement it yourself.Node
methods have been deprecated! There were a few methods that had been added over time that were either poorly named that have been deprecated and renamed, and a handful of methods that are no longer useful for the core library that have been deprecated. Here's a full list:
areDescendantSorted
-> areDescendantsSorted
getHighestChild
-> getFurthestAncestor
getHighestOnlyChildParent
-> getFurthestOnlyChildAncestor
concatChildren
decorateTexts
filterDescendantsDeep
findDescendantDeep
getChildrenBetween
getChildrenBetweenIncluding
isInlineSplitAtRange
Published by ianstormtaylor over 7 years ago
plugin.render
property is now called plugin.renderPortal
. This is to make way for the new plugin.render
property that offers HOC-like behavior, so that plugins can augment the editor however they choose.Published by ianstormtaylor over 7 years ago
Some Selection
methods have been deprecated! Previously there were many inconsistencies in the naming and handling of selection changes. This has all been cleaned up, but in the process some methods have been deprecated. Here is a full list of the deprecated methods and their new alternatives:
moveToOffsets
-> moveOffsetsTo
moveForward
-> move
moveBackward
-> move
moveAnchorOffset
-> moveAnchor
moveFocusOffset
-> moveFocus
moveStartOffset
-> moveStart
moveEndOffset
-> moveEnd
extendForward
-> extend
extendBackward
-> extend
unset
-> deselect
Some selection transforms have been deprecated! Along with the methods, the selection-based transforms have also been refactored, resulting in deprecations. Here is a full list of the deprecated transforms and their new alternatives:
moveTo
-> select
moveToOffsets
-> moveOffsetsTo
moveForward
-> move
moveBackward
-> move
moveStartOffset
-> moveStart
moveEndOffset
-> moveEnd
extendForward
-> extend
extendBackward
-> extend
flipSelection
-> flip
unsetSelection
-> deselect
unsetMarks
Published by ianstormtaylor over 7 years ago
isVoid: true
. Now, all inline nodes will always be surrounded by text nodes. If text nodes don't exist, empty ones will be created. This allows for more consistent behavior across Slate, and parity with other editing experiences.Published by ianstormtaylor almost 8 years ago
Raw
serializer is no longer terse by default! Previously, the Raw
serializer would return a "terse" representation of the document, omitting information that wasn't strictly necessary to deserialize later, like the key
of nodes. By default this no longer happens. You have to opt-in to the behavior by passing { terse: true }
as the second options
argument of the deserialize
and serialize
methods.Published by ianstormtaylor almost 8 years ago
isVoid: true
in a <Void>
component. But doing this prevented you from customizing the wrapper, like adding a className
or style
property. So you must now render the wrapper yourself, and it has been exported as Slate.Void
. This, combined with a small change to the <Void>
component's structure allows the "selected" state of void nodes to be rendered purely with CSS based on the :focus
property of a <Void>
element, which previously had to be handled in Javascript. This allows us to streamline selection-handling logic, improving performance and reducing complexity.data-offset-key
is now <key>-<index>
instead of <key>:<start>-<end>
. This shouldn't actually affect anyone, unless you were specifically relying on that attribute in the DOM. This change greatly reduces the number of re-renders needed, since previously any additional characters would cause a cascading change in the <start>
and <end>
offsets of latter text ranges.Published by ianstormtaylor almost 8 years ago
transform.mark()
is now transform.addMark()
and transform.unmark()
is now transform.removeMark()
. The new names make it clearer that the transforms are actions being performed, and it paves the way for adding a toggleMark
convenience as well.Published by ianstormtaylor almost 8 years ago
transform.unwrapBlock()
now unwraps selectively. Previously, calling unwrapBlock
with a range representing a middle sibling would unwrap all of the siblings, removing the wrapping block entirely. Now, calling it with those same arguments will only move the middle sibling up a layer in the hierarchy, preserving the nesting on any of its siblings. This changes makes it much simpler to implement functionality like unwrapping a single list item, which previously would unwrap the entire list.Published by ianstormtaylor almost 8 years ago
renderMark(mark, state, editor)
is now renderMark(mark, marks, state, editor)
. This change allows you to render marks based on multiple marks
presence at once on a given range of text, for example using a custom BoldItalic.otf
font when text has both bold
and italic
marks.Published by ianstormtaylor almost 8 years ago
node.getTextNodes()
is now node.getTexts()
. This is just for consistency with the other existing Node
methods like getBlocks()
, getInlines()
, etc. And it's nicely shorter. 😉Node
methods now throw
earlier during unexpected states. This shouldn't break anything for most folks, unless a strange edge-case was going undetected previously.Published by ianstormtaylor almost 8 years ago
onKeyDown
and onBeforeInput
handlers signatures have changed! Previously, some Slate handlers had a signature of (e, state, editor)
and others had a signature of (e, data, state, editor)
. Now all handlers will be passed a data
object—which contains Slate-specific data related to the event—even if it is empty. This is helpful for future compatibility where we might need to add data to a handler that previously didn't have any, and is nicer for consistency. The onKeyDown
handler's new data
object contains the key
name, code
and a series of is*
properties to make working with hotkeys easier. The onBeforeInput
handler's new data
object is empty.Utils
export has been removed. Previously, a Key
utility and the findDOMNode
utility were exposed under the Utils
object. The Key
has been removed in favor of the data
object passed to onKeyDown
. And then findDOMNode
utility has been upgraded to a top-level named export, so you'll now need to access it via import { findDOMNode } from 'slate'
." "
as content. Previously, they contained an empty string, but this isn't technically correct, since they have content and shouldn't be considered "empty". Now they will have a single space of content. This shouldn't really affect anyone, unless you happened to be accessing that string for serialization.contenteditable
behavior, where although technically the elements can exist, they have odd behavior and can never be selected.Published by ianstormtaylor almost 8 years ago
wrap
and unwrap
method signatures have changed! Previously, you would pass type
and data
as separate parameters, for example: wrapBlock('code', { src: true })
. This was inconsistent with other transforms, and has been updated such that a single argument of properties
is passed instead. So that example could now be: wrapBlock({ type: 'code', { data: { src: true }})
. You can still pass a type
string as shorthand, which will be the most frequent use case, for example: wrapBlock('code')
.Published by ianstormtaylor almost 8 years ago
style
object. Now you can return a style object, a class name string, or a full React component. Because of this, the DOM will be renderered slightly differently than before, resulting in an extra <span>
when rendering non-component marks. This won't affect you unless you were depending on the DOM output by Slate for some reason.Published by ianstormtaylor almost 8 years ago
<Void>
wrapping component. This was to allow for selection styling, but a change was made to make selection styling able to handled in Javascript. Now the <Void>
wrapper will be implicitly rendered by Slate, so you do not need to worry about it, and "voidness" only needs to toggled in one place, the isVoid: true
property of a node.Published by ianstormtaylor almost 8 years ago
data.files
property is now an Array
. Previously it was a native FileList
object, but needed to be changed to add full support for pasting an dropping files in all browsers. This shouldn't affect you unless you were specifically depending on it being array-like instead of a true Array
.Published by ianstormtaylor almost 8 years ago
renderNode
and renderMark
properties are gone! Previously, rendering nodes and marks happened via these two properties of the <Editor>
, but this has been replaced by the new schema
property. Check out the updated examples to see how to define a schema! There's a good chance this eliminates extra code for most use cases! 😄renderDecorations
property is gone! Decoration rendering has also been replaced by the new schema
property of the <Editor>
.Published by ianstormtaylor almost 8 years ago
undo
and redo
transforms need to be applied! Previously, undo
and redo
were special cased such that they did not require an .apply()
call, and instead would return a new State
directly. Now this is no longer the case, and they are just like every other transform.State
or Node
. The transforms API has been completely refactored to be built up of "operations" for collaborative editing support. As part of this refactor, the transforms are now only available via the state.transform()
API, and aren't exposed on the State
or Node
objects as they were before.Transform
objects are now mutable. Previously Transform
was an Immutable.js Record
, but now it is a simple constructor. This is because transforms are inherently mutating their representation of a state, but this decision is up for discussion.anchorKey
or focusKey
was null. This is no longer technically true, although this shouldn't really affect anyone in practice.Published by ianstormtaylor almost 8 years ago
key
generated values have changed. Previously, Slate generated unique keys that looked like '9dk3'
. But they were not very conflict-resistant. Now the keys are simple string of auto-incrementing numbers, like '0'
, '1'
, '2'
. This makes more clear that keys are simply a convenient way to uniquely reference nodes in the short-term lifespan of a single in-memory instance of Slate. They are not designed to be used for long-term uniqueness. A new setKeyGenerator
function has been exported that allows you to pass in your own key generating mechanism if you want to ensure uniqueness.Raw
serializer doesn't preserve keys by default. Previously, the Raw
serializer would omit keys when passed the terse: true
option, but preserve them without it. Now it will always omit keys, unless you pass the new preserveKeys: true
option. This better reflects that keys are temporary, in-memory IDs.node.getParent
could be passed either a key
string or a node
object. For performance reasons, passing in a node
object is being deprecated. So if you have any calls that look like: node.getParent(descendant)
, they will now need to be written as node.getParent(descendant.key)
. They will throw a warning for now, and will throw an error in a later version of Slate.