From 3528bb7366f5b87a14fe9adef65a42d2e0eb712f Mon Sep 17 00:00:00 2001 From: Ian Storm Taylor Date: Tue, 9 Oct 2018 18:43:47 -0700 Subject: [PATCH] fix plugins stack ordering and defaulting --- docs/guides/rendering.md | 5 +- docs/guides/schemas.md | 10 +- docs/reference/slate-react/plugins.md | 4 +- examples/check-lists/index.js | 14 +- examples/code-highlighting/index.js | 25 +- examples/embeds/index.js | 7 +- examples/emojis/index.js | 9 +- examples/forced-layout/index.js | 6 +- examples/hovering-menu/index.js | 6 +- examples/huge-document/index.js | 12 +- examples/images/index.js | 25 +- examples/input-tester/index.js | 68 ++- examples/links/index.js | 18 +- examples/markdown-preview/index.js | 15 +- examples/markdown-shortcuts/index.js | 51 +- examples/paste-html/index.js | 15 +- examples/plugins/index.js | 5 +- examples/rich-text/index.js | 13 +- examples/rtl/index.js | 10 +- examples/search-highlighting/index.js | 4 +- examples/syncing-operations/index.js | 9 +- examples/tables/index.js | 43 +- packages/slate-react/src/components/editor.js | 14 +- packages/slate-react/src/components/node.js | 16 +- .../src/plugins/{browser.js => after.js} | 468 ++-------------- packages/slate-react/src/plugins/before.js | 505 ++++++++++++++++++ packages/slate-react/src/plugins/dom.js | 24 + packages/slate-react/src/plugins/props.js | 46 -- packages/slate-react/src/plugins/react.js | 74 ++- .../fixtures/custom-block-blurred.js | 4 +- .../fixtures/custom-block-focused.js | 4 +- .../fixtures/custom-block-multiple.js | 4 +- .../fixtures/custom-block-selected.js | 4 +- .../rendering/fixtures/custom-block-void.js | 4 +- .../test/rendering/fixtures/custom-block.js | 4 +- .../rendering/fixtures/custom-decorator.js | 4 +- .../fixtures/custom-inline-multiple.js | 4 +- .../rendering/fixtures/custom-inline-void.js | 4 +- .../test/rendering/fixtures/custom-inline.js | 4 +- .../test/rendering/fixtures/custom-mark.js | 4 +- .../fixtures/readonly-custom-block-void.js | 4 +- .../fixtures/readonly-custom-inline-void.js | 4 +- packages/slate/src/controllers/editor.js | 16 +- packages/slate/src/plugins/commands.js | 19 +- packages/slate/src/plugins/core.js | 31 +- packages/slate/src/plugins/queries.js | 18 +- packages/slate/src/plugins/schema.js | 7 +- 47 files changed, 943 insertions(+), 721 deletions(-) rename packages/slate-react/src/plugins/{browser.js => after.js} (62%) create mode 100644 packages/slate-react/src/plugins/before.js create mode 100644 packages/slate-react/src/plugins/dom.js delete mode 100644 packages/slate-react/src/plugins/props.js diff --git a/docs/guides/rendering.md b/docs/guides/rendering.md index 7a174de4d..336ea0ef6 100644 --- a/docs/guides/rendering.md +++ b/docs/guides/rendering.md @@ -139,11 +139,12 @@ This sounds weird, but it can be pretty useful if you want to render additional ```js function renderEditor(props, next) { - const { children, editor } = props + const { editor } = props const wordCount = countWords(editor.value.text) + const children = next() return ( - {props.children} + {children} {wordCount} ) diff --git a/docs/guides/schemas.md b/docs/guides/schemas.md index 047f32dc2..2c28d28ff 100644 --- a/docs/guides/schemas.md +++ b/docs/guides/schemas.md @@ -100,12 +100,12 @@ Sometimes though, the declarative validation syntax isn't fine-grained enough to When you define a `normalizeNode` function, you either return nothing if the node's already valid, or you return a normalizer function that will make the node valid if it isn't. Here's an example: ```js -function normalizeNode(node) { +function normalizeNode(node, next) { const { nodes } = node - if (node.object !== 'block') return - if (nodes.size !== 3) return - if (nodes.first().object !== 'text') return - if (nodes.last().object !== 'text') return + if (node.object !== 'block') return next() + if (nodes.size !== 3) return next() + if (nodes.first().object !== 'text') return next() + if (nodes.last().object !== 'text') return next() return change => change.removeNodeByKey(node.key) } ``` diff --git a/docs/reference/slate-react/plugins.md b/docs/reference/slate-react/plugins.md index 8d7ee6ee6..9e4541498 100644 --- a/docs/reference/slate-react/plugins.md +++ b/docs/reference/slate-react/plugins.md @@ -31,7 +31,7 @@ In addition to the [core plugin hooks](../slate/plugins.md), when using `slate-r The event hooks have a signature of `(event, change, next)`—the `event` is a React object that you are used to from React's event handlers. -The rendering hooks are just like render props common to other React API's, and receive `(props, editor, next)`. For more information, see the [Rendering](./rendering.md) reference. +The rendering hooks are just like render props common to other React API's, and receive `(props, next)`. For more information, see the [Rendering](./rendering.md) reference. ### `decorateNode` @@ -107,7 +107,7 @@ This handler is called whenever the native DOM selection changes. ### `renderEditor` -`Function renderEditor(props: Object, editor: Editor) => ReactNode|Void` +`Function renderEditor(props: Object, next: Function) => ReactNode|Void` 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 content to render. diff --git a/examples/check-lists/index.js b/examples/check-lists/index.js index 3c1e22788..c4cbd6355 100644 --- a/examples/check-lists/index.js +++ b/examples/check-lists/index.js @@ -124,10 +124,12 @@ class CheckLists extends React.Component { * @return {Element} */ - renderNode = props => { + renderNode = (props, next) => { switch (props.node.type) { case 'check-list-item': return + default: + return next() } } @@ -152,15 +154,15 @@ class CheckLists extends React.Component { * * @param {Event} event * @param {Change} change - * @return {Value|Void} + * @param {Function} next */ - onKeyDown = (event, change) => { + onKeyDown = (event, change, next) => { const { value } = change if (event.key == 'Enter' && value.startBlock.type == 'check-list-item') { change.splitBlock().setBlocks({ data: { checked: false } }) - return true + return } if ( @@ -170,8 +172,10 @@ class CheckLists extends React.Component { value.selection.startOffset == 0 ) { change.setBlocks('paragraph') - return true + return } + + next() } } diff --git a/examples/code-highlighting/index.js b/examples/code-highlighting/index.js index f80e07353..208637b05 100644 --- a/examples/code-highlighting/index.js +++ b/examples/code-highlighting/index.js @@ -106,12 +106,14 @@ class CodeHighlighting extends React.Component { * @return {Element} */ - renderNode = props => { + renderNode = (props, next) => { switch (props.node.type) { case 'code': return case 'code_line': return + default: + return next() } } @@ -122,7 +124,7 @@ class CodeHighlighting extends React.Component { * @return {Element} */ - renderMark = props => { + renderMark = (props, next) => { const { children, mark, attributes } = props switch (mark.type) { @@ -150,6 +152,8 @@ class CodeHighlighting extends React.Component { {children} ) + default: + return next() } } @@ -168,17 +172,20 @@ class CodeHighlighting extends React.Component { * * @param {Event} event * @param {Change} change + * @param {Function} next * @return {Change} */ - onKeyDown = (event, change) => { + onKeyDown = (event, change, next) => { const { value } = change - const { selection, startBlock } = value - if (event.key != 'Enter') return - if (startBlock.type != 'code') return - if (selection.isExpanded) change.delete() - change.insertText('\n') - return true + const { startBlock } = value + + if (event.key === 'Enter' && startBlock.type === 'code') { + change.insertText('\n') + return + } + + next() } /** diff --git a/examples/embeds/index.js b/examples/embeds/index.js index aa8253d5f..7595bef28 100644 --- a/examples/embeds/index.js +++ b/examples/embeds/index.js @@ -58,13 +58,16 @@ class Embeds extends React.Component { * Render a Slate node. * * @param {Object} props - * @return {Element} + * @param {Editor} editor + * @param {Function} next */ - renderNode = props => { + renderNode = (props, next) => { switch (props.node.type) { case 'video': return