2016-07-12 10:36:55 -07:00
# Plugins
2016-07-12 10:33:35 -07:00
Plugins can be attached to an editor to alter its behavior in different ways. Plugins are just simple Javascript objects, containing a set of properties that control different behaviors—event handling, change handling, rendering, etc.
Each editor has a "middleware stack" of plugins, which has a specific order.
2017-09-05 18:03:41 -07:00
When the editor needs to resolve a plugin-related handler, it will loop through its plugin stack, searching for the first plugin that successfully returns a value. After receiving that value, the editor will **not** continue to search the remaining plugins; it returns early. If you'd like for the stack to continue, a plugin handler should return `undefined` .
2016-07-12 10:33:35 -07:00
## Conventions
A plugin should always export a function that takes options. This way even if it doesn't take any options now, it won't be a breaking API change to take more options in the future. So a basic plugin might look like this:
```js
2017-08-17 19:24:31 +02:00
export default function MySlatePlugin(options) {
2016-07-12 10:33:35 -07:00
return {
// Return properties that describe your logic here...
}
}
```
## Event Handler Properties
```js
{
onBeforeInput: Function,
2016-07-27 22:45:25 -07:00
onBlur: Function,
2017-03-19 05:40:22 +05:45
onFocus: Function,
2016-07-27 22:45:25 -07:00
onCopy: Function,
onCut: Function,
2016-07-22 17:15:46 -07:00
onDrop: Function,
2016-07-12 10:33:35 -07:00
onKeyDown: Function,
2017-08-25 15:24:15 +10:00
onKeyUp: Function,
2016-07-27 22:45:25 -07:00
onPaste: Function,
onSelect: Function
2016-07-12 10:33:35 -07:00
}
```
2017-10-16 21:13:07 -07:00
All of the event handler properties are passed the same React `event` object you are used to from React's event handlers. They are also passed a `change` object representing any changes that have resulted from the event, and the `editor` instance itself.
2016-07-12 10:36:55 -07:00
2018-02-07 15:58:41 +00:00
Each event handler can choose to call methods on the `change` object, in which case the editor's value will be updated.
2017-10-16 21:13:07 -07:00
If the return value of a plugin handler is `null` , the editor will simply continue resolving the plugin stack. However, if you return a non-null value, the editor will break out of the loop.
2016-07-12 10:36:55 -07:00
2016-08-04 22:11:23 +02:00
### `onBeforeInput`
2018-02-07 15:58:41 +00:00
2017-10-16 21:13:07 -07:00
`Function onBeforeInput(event: Event, change: Change, editor: Editor) => Change || Void`
2016-07-12 10:33:35 -07:00
2016-07-27 22:45:25 -07:00
This handler is called right before a string of text is inserted into the `contenteditable` element.
2016-07-12 10:33:35 -07:00
2017-10-16 21:13:07 -07:00
Make sure to `event.preventDefault()` if you do not want the default insertion behavior to occur!
2016-07-12 10:33:35 -07:00
2016-07-27 22:45:25 -07:00
### `onBlur`
2018-02-07 15:58:41 +00:00
2017-10-16 21:13:07 -07:00
`Function onBlur(event: Event, change: Change, editor: Editor) => Change || Void`
2016-07-27 22:45:25 -07:00
2018-02-07 15:58:41 +00:00
This handler is called when the editor's `contenteditable` element is blurred.
2016-07-27 22:45:25 -07:00
2017-03-19 05:40:22 +05:45
### `onFocus`
2018-02-07 15:58:41 +00:00
2017-10-16 21:13:07 -07:00
`Function onFocus(event: Event, change: Change, editor: Editor) => Change || Void`
2017-03-19 05:40:22 +05:45
2017-10-16 21:13:07 -07:00
This handler is called when the editor's `contenteditable` element is focused.
2017-03-19 05:40:22 +05:45
2016-07-27 22:45:25 -07:00
### `onCopy`
2018-02-07 15:58:41 +00:00
2017-10-16 21:13:07 -07:00
`Function onCopy(event: Event, change: Change, editor: Editor) => Change || Void`
2016-07-27 22:45:25 -07:00
2017-09-08 16:52:39 +02:00
This handler is called when there is a copy event in the editor's `contenteditable` element.
2016-07-27 22:45:25 -07:00
### `onCut`
2018-02-07 15:58:41 +00:00
2017-10-16 21:13:07 -07:00
`Function onCut(event: Event, change: Change, editor: Editor) => Change || Void`
2016-07-27 22:45:25 -07:00
2017-10-16 21:13:07 -07:00
This handler is equivalent to the `onCopy` handler.
2016-07-27 22:45:25 -07:00
2016-07-22 17:15:46 -07:00
### `onDrop`
2018-02-07 15:58:41 +00:00
2017-10-16 21:13:07 -07:00
`Function onDrop(event: Event, change: Change, editor: Editor) => Change || Void`
2016-07-22 17:15:46 -07:00
2017-10-27 13:39:06 -07:00
This handler is called when the user drops content into the `contenteditable` element. The event is already prevented by default, so you must define a value change to have any affect occur.
2016-07-22 17:15:46 -07:00
2016-08-04 22:11:23 +02:00
### `onKeyDown`
2018-02-07 15:58:41 +00:00
2017-10-16 21:13:07 -07:00
`Function onKeyDown(event: Event, change: Change, editor: Editor) => Change || Void`
2016-07-12 10:33:35 -07:00
2016-07-27 23:14:50 -07:00
This handler is called when any key is pressed in the `contenteditable` element, before any action is taken.
2017-10-16 21:13:07 -07:00
Make sure to `event.preventDefault()` if you do not want the default insertion behavior to occur!
2016-07-12 10:33:35 -07:00
2017-08-25 15:24:15 +10:00
### `onKeyUp`
2018-02-07 15:58:41 +00:00
2017-10-16 21:13:07 -07:00
`Function onKeyUp(event: Event, change: Change, editor: Editor) => Change || Void`
2017-08-25 15:24:15 +10:00
This handler is called when any key is released in the `contenteditable` element.
2016-07-12 11:17:59 -07:00
### `onPaste`
2018-02-07 15:58:41 +00:00
2017-10-16 21:13:07 -07:00
`Function onPaste(event: Event, change: Change, editor: Editor) => Change || Void`
2016-07-12 10:33:35 -07:00
2017-10-27 13:39:06 -07:00
This handler is called when the user pastes content into the `contenteditable` element. The event is already prevented by default, so you must define a value change to have any affect occur.
2016-07-12 10:33:35 -07:00
2016-07-27 22:45:25 -07:00
### `onSelect`
2018-02-07 15:58:41 +00:00
2017-10-16 21:13:07 -07:00
`Function onSelect(event: Event, change: Change, editor: Editor) => Change || Void`
2016-07-27 22:45:25 -07:00
2018-02-07 15:58:41 +00:00
This handler is called whenever the native DOM selection changes.
2016-07-27 22:45:25 -07:00
2017-09-11 18:11:45 -07:00
_Note: This is **not** Slate's internal selection representation (although it mirrors it). If you want to get notified when Slate's selection changes, use the [`onChange` ](../slate-react/editor.md#onchange ) property of the `<Editor>` . This handler is instead meant to give you lower-level access to the DOM selection handling, which **is not always triggered** as you'd expect._
2016-12-01 09:09:27 -08:00
2018-07-19 21:10:09 +02:00
## Slate-React Properties
2016-07-12 10:33:35 -07:00
```js
{
2018-07-19 21:10:09 +02:00
onChange: Function,
shouldNodeComponentUpdate: Function
2016-07-12 10:33:35 -07:00
}
```
2016-08-04 22:11:23 +02:00
### `onChange`
2018-02-07 15:58:41 +00:00
2018-09-27 23:37:01 -07:00
`Function onChange(change: Change, editor: Editor) => Any || Void`
2016-07-12 10:33:35 -07:00
2017-10-27 13:39:06 -07:00
The `onChange` handler isn't a native browser event handler. Instead, it is invoked whenever the editor value changes. This allows plugins to augment a change however they want.
2016-08-04 22:11:23 +02:00
2018-07-19 21:10:09 +02:00
### `shouldNodeComponentUpdate`
`Function shouldNodeComponentUpdate(previousEditorProps: Object, editorProps: Object) => true || Void`
If this function returns `true` , it can force updating the editor where otherwise it wouldn't.
## Slate-React Rendering
```js
{
renderEditor: Function,
renderMark: Function,
renderNode: Function,
renderPlaceholder: Function,
}
```
These renderProps are used to create the Editor UI. They are called for each plugin in reverse plugin order (so the last plugin in the array is called first) and results are passed on as `children` to the next plugin.
2017-10-27 13:39:06 -07:00
### `renderEditor`
2018-02-07 15:58:41 +00:00
2018-07-19 21:10:09 +02:00
`Function renderEditor(props: Object, editor: Editor) => ReactNode || Void`
2016-08-04 22:11:23 +02:00
2017-10-27 13:39:06 -07:00
The `renderEditor` property allows you to define higher-order-component-like behavior. It is passed all of the properties of the editor, including `props.children` . You can then choose to wrap the existing `children` in any custom elements or proxy the properties however you choose. This can be useful for rendering toolbars, styling the editor, rendering validation, etc. Remember that the `renderEditor` function has to render `props.children` for editor's children to render.
2017-03-02 18:19:39 -08:00
2018-07-19 21:10:09 +02:00
### `renderMark`
`Function renderMark({ editor, mark, marks, node, offset, text, children, attributes }) => ReactNode || Void`
Render a `Mark` .
### `renderNode`
`Function renderNode({ key, editor, isFocused, isSelected, node, parent, readOnly, children, attributes }) => ReactNode || Void`
Render a `Node` .
### `renderPlaceholder`
`Function renderPlaceholder({ editor, mark, marks, node, offset, text, children, attributes }) => ReactNode || Void`
Render the placeholder that is shown when the editor has no `value` .
The `placeholder` prop that was passed to the editor can be found at `editor.props.placeholder` .
## Other Properties
```js
{
decorateNode: Function,
Refactor schema (#1993)
#### Is this adding or improving a _feature_ or fixing a _bug_?
Improvement.
#### What's the new behavior?
- Tweaking the declarative schema definition syntax to make it easier to represent more complex states, as well as enable it to validate previously impossible things.
- Rename `validateNode` to `normalizeNode` for clarity.
- Introduce `validateNode`, `checkNode`, `assertNode` helpers for more advanced use cases, like front-end API validation of "invalid" fields that need to be fixed before they are sent to the server.
#### How does this change work?
The `schema.blocks/inlines/document` entries are now a shorthand for a more powerful `schema.rules` syntax. For example, this now allows for declaratively validating by a node's data, regardless of type:
```js
{
rules: [
{
match: {
data: { id: '2kd293lry' },
},
nodes: [
{ match: { type: 'paragraph' }},
{ match: { type: 'image' }},
]
}
]
}
```
Previously you'd have to use `validateNode` for this, since the syntax wasn't flexible enough to validate nodes without hard-coding their `type`.
This also simplifies the "concatenation" of schema rules, because under the covers all of them are implemented using the `schema.rules` array, so they simply take effect in order, just like everything else in plugins.
#### Have you checked that...?
<!--
Please run through this checklist for your pull request:
-->
* [x] The new code matches the existing patterns and styles.
* [x] The tests pass with `yarn test`.
* [x] The linter passes with `yarn lint`. (Fix errors with `yarn prettier`.)
* [x] The relevant examples still work. (Run examples with `yarn watch`.)
#### Does this fix any issues or need any specific reviewers?
Fixes: #1842
Fixes: #1923
2018-07-27 15:27:07 -07:00
normalizeNode: Function,
2018-07-19 21:10:09 +02:00
schema: Object
}
```
### `decorateNode`
`Function decorateNode(node: Node) => [Range] || Void`
Refactor schema (#1993)
#### Is this adding or improving a _feature_ or fixing a _bug_?
Improvement.
#### What's the new behavior?
- Tweaking the declarative schema definition syntax to make it easier to represent more complex states, as well as enable it to validate previously impossible things.
- Rename `validateNode` to `normalizeNode` for clarity.
- Introduce `validateNode`, `checkNode`, `assertNode` helpers for more advanced use cases, like front-end API validation of "invalid" fields that need to be fixed before they are sent to the server.
#### How does this change work?
The `schema.blocks/inlines/document` entries are now a shorthand for a more powerful `schema.rules` syntax. For example, this now allows for declaratively validating by a node's data, regardless of type:
```js
{
rules: [
{
match: {
data: { id: '2kd293lry' },
},
nodes: [
{ match: { type: 'paragraph' }},
{ match: { type: 'image' }},
]
}
]
}
```
Previously you'd have to use `validateNode` for this, since the syntax wasn't flexible enough to validate nodes without hard-coding their `type`.
This also simplifies the "concatenation" of schema rules, because under the covers all of them are implemented using the `schema.rules` array, so they simply take effect in order, just like everything else in plugins.
#### Have you checked that...?
<!--
Please run through this checklist for your pull request:
-->
* [x] The new code matches the existing patterns and styles.
* [x] The tests pass with `yarn test`.
* [x] The linter passes with `yarn lint`. (Fix errors with `yarn prettier`.)
* [x] The relevant examples still work. (Run examples with `yarn watch`.)
#### Does this fix any issues or need any specific reviewers?
Fixes: #1842
Fixes: #1923
2018-07-27 15:27:07 -07:00
### `normalizeNode`
2018-07-19 21:10:09 +02:00
Refactor schema (#1993)
#### Is this adding or improving a _feature_ or fixing a _bug_?
Improvement.
#### What's the new behavior?
- Tweaking the declarative schema definition syntax to make it easier to represent more complex states, as well as enable it to validate previously impossible things.
- Rename `validateNode` to `normalizeNode` for clarity.
- Introduce `validateNode`, `checkNode`, `assertNode` helpers for more advanced use cases, like front-end API validation of "invalid" fields that need to be fixed before they are sent to the server.
#### How does this change work?
The `schema.blocks/inlines/document` entries are now a shorthand for a more powerful `schema.rules` syntax. For example, this now allows for declaratively validating by a node's data, regardless of type:
```js
{
rules: [
{
match: {
data: { id: '2kd293lry' },
},
nodes: [
{ match: { type: 'paragraph' }},
{ match: { type: 'image' }},
]
}
]
}
```
Previously you'd have to use `validateNode` for this, since the syntax wasn't flexible enough to validate nodes without hard-coding their `type`.
This also simplifies the "concatenation" of schema rules, because under the covers all of them are implemented using the `schema.rules` array, so they simply take effect in order, just like everything else in plugins.
#### Have you checked that...?
<!--
Please run through this checklist for your pull request:
-->
* [x] The new code matches the existing patterns and styles.
* [x] The tests pass with `yarn test`.
* [x] The linter passes with `yarn lint`. (Fix errors with `yarn prettier`.)
* [x] The relevant examples still work. (Run examples with `yarn watch`.)
#### Does this fix any issues or need any specific reviewers?
Fixes: #1842
Fixes: #1923
2018-07-27 15:27:07 -07:00
`Function normalizeNode(node: Node) => Function(change: Change) || Void`
2018-07-19 21:10:09 +02:00
2016-08-14 15:58:41 -07:00
### `schema`
2018-02-07 15:58:41 +00:00
2016-08-14 15:58:41 -07:00
`Object`
2017-10-25 17:32:29 -07:00
The `schema` property allows you to define a set of rules that will be added to the editor's schema. The rules from each of the schemas returned by the plugins are collected into a single schema for the editor.