Concepts
Migrating
12min
migrating from earlier versions of slate to the 0 50 x versions is not a simple task the entire framework was re considered from the ground up this has resulted in a much better set of abstractions, which will result in you writing less code but the migration process is not simple it's highly recommended that after reading this guide you read through the original installing slate from archbee docid\ jqm yk1kc19 cqwcxrhyh and the other interfaces docid\ nrx5owppulyg xgjbqxow to see how all of the new concepts get applied major differences here's an overview of the major differences in the 0 50 x version of slate from an architectural point of view json! the data model is now comprised of simple json objects previously, it used immutable js https //immutable js github io/immutable js/ data structures this is a huge change, and one that unlocks many other things hopefully it will also increase the average performance when using slate it also makes it much easier to get started for newcomers this will be a large change to migrate from, but it will be worth it interfaces the data model is interface based previously each model was an instance of a class now, not only is the data plain objects, but slate only expects that the objects implement an interface so custom properties that used to live in node data can now live at the top level of the nodes namespaces a lot of helper functions are exposed as a collection of helper functions on a namespace for example, node get(root, path) or range iscollapsed(range) this ends up making code much clearer because you can always quickly see what interface you're working with typescript the codebase now uses typescript working with pure json as a data model, and using an interface based api are two things that have been made easier by migrating to typescript you don't need to use it yourself, but if you do you'll get a lot more security when using the apis (and if you use vs code you'll get nice autocompletion regardless!) fewer concepts the number of interfaces and commands has been reduced previously selection , annotation , and decoration used to all be separate classes now they are simply objects that implement the range interface previously block and inline were separate; now they are objects that implement the element interface previously there was a document and value , but now the top level editor contains the children nodes of the document itself the number of commands has been reduced too previously we had commands for every type of input, like inserttext , inserttextatrange , inserttextatpath these have been merged into a smaller set of more customizable commands, eg inserttext which can take at path | range | point fewer packages in an attempt to decrease the maintenance burden, and because the new abstraction and apis in slate's core packages make things much easier, the total number of packages has been reduced things like slate plain serializer , slate base64 serializer , etc have been removed and can be implemented in userland easily if needed even the slate html deserializer can now be implemented in userland (in 10 loc leveraging slate hyperscript ) and internal packages like slate dev environment , slate dev test utils , etc are no longer exposed because they are implementation details commands a new "command" concept has been introduced (the old "commands" are now called "transforms" ) this new concept expresses the semantic intent of a user editing the document and they allow for the right abstraction to tap into user behaviorsβfor example to change what happens when a user presses enter, or backspace, etc instead of using keydown events you should likely override command behaviors instead commands are triggered by calling the editor core functions and they travel through a middleware like stack, but built from composed functions any plugin can override the behaviors to augment an editor plugins plugins are now plain functions that augment the editor object they receive and return it again for example, they can augment the command execution by composing the editor exec function or listen to operations by composing editor apply previously they relied on a custom middleware stack, and they were just bags of handlers that got merged onto an editor now we're using plain old function composition (aka wrapping) instead elements block ness and inline ness is now a runtime choice previously it was baked into the data model with the object 'block' or object 'inline' attributes now, it checks whether an "element" is inline or not at runtime for example, you might check to see that element type === 'link' and treat it as inline more react ish rendering and event handling are no longer a plugin's concern previously plugins had full control over the rendering and event handling logic in the editor this creates a bad incentive to start putting all rendering logic in plugins, which puts slate in a position of being a wrapper around all of react, which is very hard to do well instead, the new architecture has plugins focused purely on the richtext aspects, and leaves the rendering and event handling aspects to react context previously the \<editor> component was doing double duty as a sort of "controller" object and also the contenteditable dom element this led to a lot of awkwardness in how other components worked with slate in the new version, there is a new \<slate> context provider and a simpler \<editable> contenteditable like component by putting the \<slate> provider higher up in your component tree, you can share the editor directly with toolbars, buttons, etc using the useslate hook hooks in addition to the useslate hook, there are a handful of other hooks for example the useselected and usefocused hooks help with knowing when to render selected states (often for void nodes) and since they use react's context api they will automatically re render when their state changes beforeinput we now use the beforeinput event almost exclusively instead of relying on a series of shims and the quirks of react synthetic events, we're now using the standardized beforeinput event as our baseline it is fully supported in safari and chrome, will soon be supported in the new chromium based edge, and is currently being worked on in firefox in the meantime there are a few patches to make firefox work internet explorer is no longer supported in core out of the box history less the core history logic has now finally been extracted into a standalone plugin this makes it much easier for people to implement their own custom history behaviors and it ensures that plugins have enough control to augment the editor in complex ways, because the history requires it mark less marks have been removed from the slate data model now that we have the ability to define custom properties right on the nodes themselves, you can model marks as custom properties of text nodes for example bold can be modelled simply as a bold true property annotation less similarly, annotations have been removed from slate's core they can be fully implemented now in userland by defining custom operations and rendering annotated ranges using decorations but most cases should be using custom text node properties or decorations anyways there were not that many use cases that benefited from annotations reductions one of the goals was to dramatically simplify a lot of the logic in slate to make it easier to maintain and iterate on this was done by refactoring to better base abstractions that can be built on, by leveraging modern dom apis, and by migrating to simpler react patterns to give you a sense for the change in total lines of code slate 8,436 > 3,958 (47%) slate react 3,905 > 1,954 (50%) slate base64 serializer 38 > 0 slate dev benchmark 340 > 0 slate dev environment 102 > 0 slate dev test utils 44 > 0 slate history 0 > 211 slate hotkeys 62 > 0 slate html serializer 253 > 0 slate hyperscript 447 > 345 slate plain serializer 56 > 0 slate prop types 62 > 0 slate react placeholder 62 > 0 total 13,807 > 6,468 (47%) it's quite a big difference! and that doesn't even include the dependencies that were shed in the process too
π€
Have a question?
Our super-smart AI,knowledgeable support team and an awesome community will get you an answer in a flash.
To ask a question or participate in discussions, you'll need to authenticate first.