mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-15 03:33:59 +02:00
remove change, fold into editor (#2337)
#### Is this adding or improving a _feature_ or fixing a _bug_? Improvement / debt. #### What's the new behavior? This pull request removes the `Change` object as we know it, and folds all of its behaviors into the new `Editor` controller instead, simplifying a lot of the confusion around what is a "change vs. editor" and when to use which. It makes the standard API a **lot** nicer to use I think. --- ###### NEW **The `editor.command` and `editor.query` methods can take functions.** Previously they only accepted a `type` string and would look up the command or query by type. Now, they also accept a custom function. This is helpful for plugin authors, who want to accept a "command option", since it gives users more flexibility to write one-off commands or queries. For example a plugin could be passed either: ```js Hotkey({ hotkey: 'cmd+b', command: 'addBoldMark', }) ``` Or a custom command function: ```js Hotkey({ hotkey: 'cmd+b', command: editor => editor.addBoldMark().moveToEnd() }) ``` ###### BREAKING **The `Change` object has been removed.** The `Change` object as we know it previously has been removed, and all of its behaviors have been folded into the `Editor` controller. This includes the top-level commands and queries methods, as well as methods like `applyOperation` and `normalize`. _All places that used to receive `change` now receive `editor`, which is API equivalent._ **Changes are now flushed to `onChange` asynchronously.** Previously this was done synchronously, which resulted in some strange race conditions in React environments. Now they will always be flushed asynchronously, just like `setState`. **The `render*` and `decorate*` middleware signatures have changed!** Previously the `render*` and `decorate*` middleware was passed `(props, next)`. However now, for consistency with the other middleware they are all passed `(props, editor, next)`. This way, all middleware always receive `editor` and `next` as their final two arguments. **The `normalize*` and `validate*` middleware signatures have changed!** Previously the `normalize*` and `validate*` middleware was passed `(node, next)`. However now, for consistency with the other middleware they are all passed `(node, editor, next)`. This way, all middleware always receive `editor` and `next` as their final two arguments. **The `editor.event` method has been removed.** Previously this is what you'd use when writing tests to simulate events being fired—which were slightly different to other running other middleware. With the simplification to the editor and to the newly-consistent middleware signatures, you can now use `editor.run` directly to simulate events: ```js editor.run('onKeyDown', { key: 'Tab', ... }) ``` ###### DEPRECATED **The `editor.change` method is deprecated.** With the removal of the `Change` object, there's no need anymore to create the small closures with `editor.change()`. Instead you can directly invoke commands on the editor in series, and all of the changes will be emitted asynchronously on the next tick. ```js editor .insertText('word') .moveFocusForward(10) .addMark('bold') ``` **The `applyOperations` method is deprecated.** Instead you can loop a set of operations and apply each one using `applyOperation`. This is to reduce the number of methods exposed on the `Editor` to keep it simpler. **The `change.call` method is deprecated.** Previously this was used to call a one-off function as a change method. Now this behavior is equivalent to calling `editor.command(fn)` instead. --- Fixes: https://github.com/ianstormtaylor/slate/issues/2334 Fixes: https://github.com/ianstormtaylor/slate/issues/2282
This commit is contained in:
@@ -14,13 +14,13 @@ This document maintains a list of changes to the `slate-react` package with each
|
||||
|
||||
```js
|
||||
// Previously, you'd return `undefined` to continue.
|
||||
function onKeyDown(event, change, editor) {
|
||||
function onKeyDown(event, editor, next) {
|
||||
if (event.key !== 'Enter') return
|
||||
...
|
||||
}
|
||||
|
||||
// Now, you call `next()` to continue...
|
||||
function onKeyDown(event, change, next) {
|
||||
function onKeyDown(event, editor, next) {
|
||||
if (event.key !== 'Enter') return next()
|
||||
...
|
||||
}
|
||||
@@ -29,7 +29,7 @@ function onKeyDown(event, change, next) {
|
||||
While that may seem inconvenient, it opens up an entire new behavior, which is deferring to the plugins later in the stack to see if they "handle" a specific case, and if not, handling it yourself:
|
||||
|
||||
```js
|
||||
function onKeyDown(event, change, next) {
|
||||
function onKeyDown(event, editor, next) {
|
||||
if (event.key === 'Enter') {
|
||||
const handled = next()
|
||||
if (handled) return handled
|
||||
@@ -45,7 +45,7 @@ Under the covers, the `schema`, `commands` and `queries` concept are all impleme
|
||||
|
||||
```js
|
||||
const plugin = {
|
||||
onCommand(command, change, next) {
|
||||
onCommand(command, editor, next) {
|
||||
...
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ This allows you to actually listen in to all commands, and override individual b
|
||||
**The `editor` object is no longer passed to event handlers.** Previously, the third argument to event handlers would be the React `editor` instance. However, now that `Change` objects contain a direct reference to the editor, you can access this on `change.editor` instead.
|
||||
|
||||
```js
|
||||
function onKeyDown(event, change, next) {
|
||||
function onKeyDown(event, editor, next) {
|
||||
const { editor } = change
|
||||
...
|
||||
}
|
||||
@@ -206,7 +206,7 @@ In its place is the new `next` argument, which allows you to choose to defer to
|
||||
|
||||
###### BREAKING
|
||||
|
||||
**The `data` argument to event handlers has been removed.** Previously event handlers had a signature of `(event, data, change, editor)`, but now they have a signature of just `(event, change, editor)`. This leads to simpler internal Slate logic, and less complex relationship dependencies between plugins. All of the information inside the old `data` argument can be accessed via the similar properties on the `event` argument, or via the `getEventRange`, `getEventTransfer` and `setEventTransfer` helpers.
|
||||
**The `data` argument to event handlers has been removed.** Previously event handlers had a signature of `(event, data, change, editor)`, but now they have a signature of just `(event, editor, next)`. This leads to simpler internal Slate logic, and less complex relationship dependencies between plugins. All of the information inside the old `data` argument can be accessed via the similar properties on the `event` argument, or via the `getEventRange`, `getEventTransfer` and `setEventTransfer` helpers.
|
||||
|
||||
###### NEW
|
||||
|
||||
|
@@ -99,7 +99,7 @@ class Editor extends React.Component {
|
||||
this.tmp.updates++
|
||||
|
||||
if (this.props.autoFocus) {
|
||||
this.change(c => c.focus())
|
||||
this.focus()
|
||||
}
|
||||
|
||||
if (this.tmp.change) {
|
||||
@@ -121,20 +121,6 @@ class Editor extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On controller change, call `onChange` or queue the change for flushing.
|
||||
*
|
||||
* @param {Change} change
|
||||
*/
|
||||
|
||||
onControllerChange = change => {
|
||||
if (this.tmp.mounted) {
|
||||
this.props.onChange(change)
|
||||
} else {
|
||||
this.tmp.change = change
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the editor.
|
||||
*
|
||||
@@ -181,8 +167,21 @@ class Editor extends React.Component {
|
||||
|
||||
this.tmp.resolves++
|
||||
const react = ReactPlugin(this.props)
|
||||
const attrs = { onChange: this.onControllerChange, plugins: [react] }
|
||||
this.controller = new Controller(attrs, { editor: this, normalize: false })
|
||||
|
||||
const onChange = change => {
|
||||
if (this.tmp.mounted) {
|
||||
this.props.onChange(change)
|
||||
} else {
|
||||
this.tmp.change = change
|
||||
}
|
||||
}
|
||||
|
||||
this.controller = new Controller(
|
||||
{ plugins: [react], onChange },
|
||||
{ controller: this, construct: false }
|
||||
)
|
||||
|
||||
this.controller.run('onConstruct')
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -190,6 +189,10 @@ class Editor extends React.Component {
|
||||
* can be passed in its place to plugins.
|
||||
*/
|
||||
|
||||
get operations() {
|
||||
return this.controller.operations
|
||||
}
|
||||
|
||||
get readOnly() {
|
||||
return this.controller.readOnly
|
||||
}
|
||||
@@ -198,59 +201,91 @@ class Editor extends React.Component {
|
||||
return this.controller.value
|
||||
}
|
||||
|
||||
change = (...args) => {
|
||||
return this.controller.change(...args)
|
||||
applyOperation(...args) {
|
||||
return this.controller.applyOperation(...args)
|
||||
}
|
||||
|
||||
command = (...args) => {
|
||||
command(...args) {
|
||||
return this.controller.command(...args)
|
||||
}
|
||||
|
||||
event = (...args) => {
|
||||
return this.controller.event(...args)
|
||||
normalize(...args) {
|
||||
return this.controller.normalize(...args)
|
||||
}
|
||||
|
||||
onChange = (...args) => {
|
||||
return this.controller.onChange(...args)
|
||||
}
|
||||
|
||||
query = (...args) => {
|
||||
query(...args) {
|
||||
return this.controller.query(...args)
|
||||
}
|
||||
|
||||
run = (...args) => {
|
||||
registerCommand(...args) {
|
||||
return this.controller.registerCommand(...args)
|
||||
}
|
||||
|
||||
registerQuery(...args) {
|
||||
return this.controller.registerQuery(...args)
|
||||
}
|
||||
|
||||
run(...args) {
|
||||
return this.controller.run(...args)
|
||||
}
|
||||
|
||||
/**
|
||||
* Mimic the API of a DOM input/textarea, to maintain a React-like interface.
|
||||
*/
|
||||
|
||||
blur = () => {
|
||||
this.change(c => c.blur())
|
||||
}
|
||||
|
||||
focus = () => {
|
||||
this.change(c => c.focus())
|
||||
withoutNormalizing(...args) {
|
||||
return this.controller.withoutNormalizing(...args)
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
*/
|
||||
|
||||
get editor() {
|
||||
return this.controller.editor
|
||||
}
|
||||
|
||||
get schema() {
|
||||
invariant(
|
||||
false,
|
||||
'As of Slate 0.42.0, the `editor.schema` property no longer exists, and its functionality has been folded into the editor itself. Use the `editor` instead.'
|
||||
'As of Slate 0.42, the `editor.schema` property no longer exists, and its functionality has been folded into the editor itself. Use the `editor` instead.'
|
||||
)
|
||||
}
|
||||
|
||||
get stack() {
|
||||
invariant(
|
||||
false,
|
||||
'As of Slate 0.42.0, the `editor.stack` property no longer exists, and its functionality has been folded into the editor itself. Use the `editor` instead.'
|
||||
'As of Slate 0.42, the `editor.stack` property no longer exists, and its functionality has been folded into the editor itself. Use the `editor` instead.'
|
||||
)
|
||||
}
|
||||
|
||||
call(...args) {
|
||||
return this.controller.call(...args)
|
||||
}
|
||||
|
||||
change(...args) {
|
||||
return this.controller.change(...args)
|
||||
}
|
||||
|
||||
onChange(...args) {
|
||||
return this.controller.onChange(...args)
|
||||
}
|
||||
|
||||
applyOperations(...args) {
|
||||
return this.controller.applyOperations(...args)
|
||||
}
|
||||
|
||||
setOperationFlag(...args) {
|
||||
return this.controller.setOperationFlag(...args)
|
||||
}
|
||||
|
||||
getFlag(...args) {
|
||||
return this.controller.getFlag(...args)
|
||||
}
|
||||
|
||||
unsetOperationFlag(...args) {
|
||||
return this.controller.unsetOperationFlag(...args)
|
||||
}
|
||||
|
||||
withoutNormalization(...args) {
|
||||
return this.controller.withoutNormalization(...args)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -36,12 +36,12 @@ function AfterPlugin(options = {}) {
|
||||
* On before input.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onBeforeInput(event, change, next) {
|
||||
const { editor, value } = change
|
||||
function onBeforeInput(event, editor, next) {
|
||||
const { value } = editor
|
||||
const isSynthetic = !!event.nativeEvent
|
||||
|
||||
// If the event is synthetic, it's React's polyfill of `beforeinput` that
|
||||
@@ -49,7 +49,7 @@ function AfterPlugin(options = {}) {
|
||||
// gets triggered for character insertions, so we can just insert directly.
|
||||
if (isSynthetic) {
|
||||
event.preventDefault()
|
||||
change.insertText(event.data)
|
||||
editor.insertText(event.data)
|
||||
return next()
|
||||
}
|
||||
|
||||
@@ -71,29 +71,29 @@ function AfterPlugin(options = {}) {
|
||||
case 'deleteContent':
|
||||
case 'deleteContentBackward':
|
||||
case 'deleteContentForward': {
|
||||
change.deleteAtRange(range)
|
||||
editor.deleteAtRange(range)
|
||||
break
|
||||
}
|
||||
|
||||
case 'deleteWordBackward': {
|
||||
change.deleteWordBackwardAtRange(range)
|
||||
editor.deleteWordBackwardAtRange(range)
|
||||
break
|
||||
}
|
||||
|
||||
case 'deleteWordForward': {
|
||||
change.deleteWordForwardAtRange(range)
|
||||
editor.deleteWordForwardAtRange(range)
|
||||
break
|
||||
}
|
||||
|
||||
case 'deleteSoftLineBackward':
|
||||
case 'deleteHardLineBackward': {
|
||||
change.deleteLineBackwardAtRange(range)
|
||||
editor.deleteLineBackwardAtRange(range)
|
||||
break
|
||||
}
|
||||
|
||||
case 'deleteSoftLineForward':
|
||||
case 'deleteHardLineForward': {
|
||||
change.deleteLineForwardAtRange(range)
|
||||
editor.deleteLineForwardAtRange(range)
|
||||
break
|
||||
}
|
||||
|
||||
@@ -105,9 +105,9 @@ function AfterPlugin(options = {}) {
|
||||
)
|
||||
|
||||
if (hasVoidParent) {
|
||||
change.moveToStartOfNextText()
|
||||
editor.moveToStartOfNextText()
|
||||
} else {
|
||||
change.splitBlockAtRange(range)
|
||||
editor.splitBlockAtRange(range)
|
||||
}
|
||||
|
||||
break
|
||||
@@ -127,12 +127,12 @@ function AfterPlugin(options = {}) {
|
||||
|
||||
if (text == null) break
|
||||
|
||||
change.insertTextAtRange(range, text, selection.marks)
|
||||
editor.insertTextAtRange(range, text, selection.marks)
|
||||
|
||||
// If the text was successfully inserted, and the selection had marks
|
||||
// on it, unset the selection's marks.
|
||||
if (selection.marks && value.document != change.value.document) {
|
||||
change.select({ marks: null })
|
||||
if (selection.marks && value.document != editor.value.document) {
|
||||
editor.select({ marks: null })
|
||||
}
|
||||
|
||||
break
|
||||
@@ -146,13 +146,13 @@ function AfterPlugin(options = {}) {
|
||||
* On blur.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onBlur(event, change, next) {
|
||||
function onBlur(event, editor, next) {
|
||||
debug('onBlur', { event })
|
||||
change.blur()
|
||||
editor.blur()
|
||||
next()
|
||||
}
|
||||
|
||||
@@ -160,12 +160,11 @@ function AfterPlugin(options = {}) {
|
||||
* On click.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onClick(event, change, next) {
|
||||
const { editor } = change
|
||||
function onClick(event, editor, next) {
|
||||
if (editor.readOnly) return next()
|
||||
|
||||
const { value } = editor
|
||||
@@ -177,14 +176,14 @@ function AfterPlugin(options = {}) {
|
||||
|
||||
const ancestors = document.getAncestors(node.key)
|
||||
const isVoid =
|
||||
node && (change.isVoid(node) || ancestors.some(a => change.isVoid(a)))
|
||||
node && (editor.isVoid(node) || ancestors.some(a => editor.isVoid(a)))
|
||||
|
||||
if (isVoid) {
|
||||
// COMPAT: In Chrome & Safari, selections that are at the zero offset of
|
||||
// an inline node will be automatically replaced to be at the last offset
|
||||
// of a previous inline node, which screws us up, so we always want to set
|
||||
// it to the end of the node. (2016/11/29)
|
||||
change.focus().moveToEndOfNode(node)
|
||||
editor.focus().moveToEndOfNode(node)
|
||||
}
|
||||
|
||||
next()
|
||||
@@ -194,13 +193,12 @@ function AfterPlugin(options = {}) {
|
||||
* On copy.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onCopy(event, change, next) {
|
||||
function onCopy(event, editor, next) {
|
||||
debug('onCopy', { event })
|
||||
const { editor } = change
|
||||
cloneFragment(event, editor)
|
||||
next()
|
||||
}
|
||||
@@ -209,31 +207,30 @@ function AfterPlugin(options = {}) {
|
||||
* On cut.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onCut(event, change, next) {
|
||||
function onCut(event, editor, next) {
|
||||
debug('onCut', { event })
|
||||
const { editor } = change
|
||||
|
||||
// Once the fake cut content has successfully been added to the clipboard,
|
||||
// delete the content in the current selection.
|
||||
cloneFragment(event, editor, () => {
|
||||
// If user cuts a void block node or a void inline node,
|
||||
// manually removes it since selection is collapsed in this case.
|
||||
const { value } = change
|
||||
const { value } = editor
|
||||
const { endBlock, endInline, selection } = value
|
||||
const { isCollapsed } = selection
|
||||
const isVoidBlock = endBlock && change.isVoid(endBlock) && isCollapsed
|
||||
const isVoidInline = endInline && change.isVoid(endInline) && isCollapsed
|
||||
const isVoidBlock = endBlock && editor.isVoid(endBlock) && isCollapsed
|
||||
const isVoidInline = endInline && editor.isVoid(endInline) && isCollapsed
|
||||
|
||||
if (isVoidBlock) {
|
||||
editor.change(c => c.removeNodeByKey(endBlock.key))
|
||||
editor.editor(c => c.removeNodeByKey(endBlock.key))
|
||||
} else if (isVoidInline) {
|
||||
editor.change(c => c.removeNodeByKey(endInline.key))
|
||||
editor.editor(c => c.removeNodeByKey(endInline.key))
|
||||
} else {
|
||||
editor.change(c => c.delete())
|
||||
editor.editor(c => c.delete())
|
||||
}
|
||||
})
|
||||
|
||||
@@ -244,11 +241,11 @@ function AfterPlugin(options = {}) {
|
||||
* On drag end.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onDragEnd(event, change, next) {
|
||||
function onDragEnd(event, editor, next) {
|
||||
debug('onDragEnd', { event })
|
||||
isDraggingInternally = null
|
||||
next()
|
||||
@@ -258,32 +255,31 @@ function AfterPlugin(options = {}) {
|
||||
* On drag start.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onDragStart(event, change, next) {
|
||||
function onDragStart(event, editor, next) {
|
||||
debug('onDragStart', { event })
|
||||
|
||||
isDraggingInternally = true
|
||||
|
||||
const { editor } = change
|
||||
const { value } = editor
|
||||
const { document } = value
|
||||
const node = findNode(event.target, editor)
|
||||
const ancestors = document.getAncestors(node.key)
|
||||
const isVoid =
|
||||
node && (change.isVoid(node) || ancestors.some(a => change.isVoid(a)))
|
||||
node && (editor.isVoid(node) || ancestors.some(a => editor.isVoid(a)))
|
||||
const selectionIncludesNode = value.blocks.some(
|
||||
block => block.key === node.key
|
||||
)
|
||||
|
||||
// If a void block is dragged and is not selected, select it (necessary for local drags).
|
||||
if (isVoid && !selectionIncludesNode) {
|
||||
change.moveToRangeOfNode(node)
|
||||
editor.moveToRangeOfNode(node)
|
||||
}
|
||||
|
||||
const fragment = change.value.fragment
|
||||
const fragment = editor.value.fragment
|
||||
const encoded = Base64.serializeNode(fragment)
|
||||
setEventTransfer(event, 'fragment', encoded)
|
||||
next()
|
||||
@@ -293,12 +289,12 @@ function AfterPlugin(options = {}) {
|
||||
* On drop.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onDrop(event, change, next) {
|
||||
const { editor, value } = change
|
||||
function onDrop(event, editor, next) {
|
||||
const { value } = editor
|
||||
const { document, selection } = value
|
||||
const window = getWindow(event.target)
|
||||
let target = getEventRange(event, editor)
|
||||
@@ -309,7 +305,7 @@ function AfterPlugin(options = {}) {
|
||||
const transfer = getEventTransfer(event)
|
||||
const { type, fragment, text } = transfer
|
||||
|
||||
change.focus()
|
||||
editor.focus()
|
||||
|
||||
// If the drag is internal and the target is after the selection, it
|
||||
// needs to account for the selection's content being deleted.
|
||||
@@ -326,10 +322,10 @@ function AfterPlugin(options = {}) {
|
||||
}
|
||||
|
||||
if (isDraggingInternally) {
|
||||
change.delete()
|
||||
editor.delete()
|
||||
}
|
||||
|
||||
change.select(target)
|
||||
editor.select(target)
|
||||
|
||||
if (type == 'text' || type == 'html') {
|
||||
const { anchor } = target
|
||||
@@ -344,19 +340,19 @@ function AfterPlugin(options = {}) {
|
||||
hasVoidParent = document.hasVoidParent(n.key, editor)
|
||||
}
|
||||
|
||||
if (n) change.moveToStartOfNode(n)
|
||||
if (n) editor.moveToStartOfNode(n)
|
||||
}
|
||||
|
||||
if (text) {
|
||||
text.split('\n').forEach((line, i) => {
|
||||
if (i > 0) change.splitBlock()
|
||||
change.insertText(line)
|
||||
if (i > 0) editor.splitBlock()
|
||||
editor.insertText(line)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (type == 'fragment') {
|
||||
change.insertFragment(fragment)
|
||||
editor.insertFragment(fragment)
|
||||
}
|
||||
|
||||
// COMPAT: React's onSelect event breaks after an onDrop event
|
||||
@@ -383,13 +379,13 @@ function AfterPlugin(options = {}) {
|
||||
* On input.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onInput(event, change, next) {
|
||||
function onInput(event, editor, next) {
|
||||
const window = getWindow(event.target)
|
||||
const { editor, value } = change
|
||||
const { value } = editor
|
||||
|
||||
// Get the selection point.
|
||||
const native = window.getSelection()
|
||||
@@ -443,7 +439,7 @@ function AfterPlugin(options = {}) {
|
||||
entire = document.resolveRange(entire)
|
||||
|
||||
// Change the current value to have the leaf's text replaced.
|
||||
change.insertTextAtRange(entire, textContent, leaf.marks).select(corrected)
|
||||
editor.insertTextAtRange(entire, textContent, leaf.marks).select(corrected)
|
||||
next()
|
||||
}
|
||||
|
||||
@@ -451,14 +447,14 @@ function AfterPlugin(options = {}) {
|
||||
* On key down.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onKeyDown(event, change, next) {
|
||||
function onKeyDown(event, editor, next) {
|
||||
debug('onKeyDown', { event })
|
||||
|
||||
const { editor, value } = change
|
||||
const { value } = editor
|
||||
const { document, selection } = value
|
||||
const hasVoidParent = document.hasVoidParent(selection.start.path, editor)
|
||||
|
||||
@@ -467,40 +463,40 @@ function AfterPlugin(options = {}) {
|
||||
// preserve native autocorrect behavior, so they shouldn't be handled here.
|
||||
if (Hotkeys.isSplitBlock(event) && !IS_IOS) {
|
||||
return hasVoidParent
|
||||
? change.moveToStartOfNextText()
|
||||
: change.splitBlock()
|
||||
? editor.moveToStartOfNextText()
|
||||
: editor.splitBlock()
|
||||
}
|
||||
|
||||
if (Hotkeys.isDeleteBackward(event) && !IS_IOS) {
|
||||
return change.deleteCharBackward()
|
||||
return editor.deleteCharBackward()
|
||||
}
|
||||
|
||||
if (Hotkeys.isDeleteForward(event) && !IS_IOS) {
|
||||
return change.deleteCharForward()
|
||||
return editor.deleteCharForward()
|
||||
}
|
||||
|
||||
if (Hotkeys.isDeleteLineBackward(event)) {
|
||||
return change.deleteLineBackward()
|
||||
return editor.deleteLineBackward()
|
||||
}
|
||||
|
||||
if (Hotkeys.isDeleteLineForward(event)) {
|
||||
return change.deleteLineForward()
|
||||
return editor.deleteLineForward()
|
||||
}
|
||||
|
||||
if (Hotkeys.isDeleteWordBackward(event)) {
|
||||
return change.deleteWordBackward()
|
||||
return editor.deleteWordBackward()
|
||||
}
|
||||
|
||||
if (Hotkeys.isDeleteWordForward(event)) {
|
||||
return change.deleteWordForward()
|
||||
return editor.deleteWordForward()
|
||||
}
|
||||
|
||||
if (Hotkeys.isRedo(event)) {
|
||||
return change.redo()
|
||||
return editor.redo()
|
||||
}
|
||||
|
||||
if (Hotkeys.isUndo(event)) {
|
||||
return change.undo()
|
||||
return editor.undo()
|
||||
}
|
||||
|
||||
// COMPAT: Certain browsers don't handle the selection updates properly. In
|
||||
@@ -508,22 +504,22 @@ function AfterPlugin(options = {}) {
|
||||
// selection isn't properly collapsed. (2017/10/17)
|
||||
if (Hotkeys.isMoveLineBackward(event)) {
|
||||
event.preventDefault()
|
||||
return change.moveToStartOfBlock()
|
||||
return editor.moveToStartOfBlock()
|
||||
}
|
||||
|
||||
if (Hotkeys.isMoveLineForward(event)) {
|
||||
event.preventDefault()
|
||||
return change.moveToEndOfBlock()
|
||||
return editor.moveToEndOfBlock()
|
||||
}
|
||||
|
||||
if (Hotkeys.isExtendLineBackward(event)) {
|
||||
event.preventDefault()
|
||||
return change.moveFocusToStartOfBlock()
|
||||
return editor.moveFocusToStartOfBlock()
|
||||
}
|
||||
|
||||
if (Hotkeys.isExtendLineForward(event)) {
|
||||
event.preventDefault()
|
||||
return change.moveFocusToEndOfBlock()
|
||||
return editor.moveFocusToEndOfBlock()
|
||||
}
|
||||
|
||||
// COMPAT: If a void node is selected, or a zero-width text node adjacent to
|
||||
@@ -533,30 +529,30 @@ function AfterPlugin(options = {}) {
|
||||
event.preventDefault()
|
||||
|
||||
if (!selection.isCollapsed) {
|
||||
return change.moveToStart()
|
||||
return editor.moveToStart()
|
||||
}
|
||||
|
||||
return change.moveBackward()
|
||||
return editor.moveBackward()
|
||||
}
|
||||
|
||||
if (Hotkeys.isMoveForward(event)) {
|
||||
event.preventDefault()
|
||||
|
||||
if (!selection.isCollapsed) {
|
||||
return change.moveToEnd()
|
||||
return editor.moveToEnd()
|
||||
}
|
||||
|
||||
return change.moveForward()
|
||||
return editor.moveForward()
|
||||
}
|
||||
|
||||
if (Hotkeys.isMoveWordBackward(event)) {
|
||||
event.preventDefault()
|
||||
return change.moveWordBackward()
|
||||
return editor.moveWordBackward()
|
||||
}
|
||||
|
||||
if (Hotkeys.isMoveWordForward(event)) {
|
||||
event.preventDefault()
|
||||
return change.moveWordForward()
|
||||
return editor.moveWordForward()
|
||||
}
|
||||
|
||||
if (Hotkeys.isExtendBackward(event)) {
|
||||
@@ -566,7 +562,7 @@ function AfterPlugin(options = {}) {
|
||||
|
||||
if (hasVoidParent || isPreviousInVoid || startText.text == '') {
|
||||
event.preventDefault()
|
||||
return change.moveFocusBackward()
|
||||
return editor.moveFocusBackward()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,7 +573,7 @@ function AfterPlugin(options = {}) {
|
||||
|
||||
if (hasVoidParent || isNextInVoid || startText.text == '') {
|
||||
event.preventDefault()
|
||||
return change.moveFocusForward()
|
||||
return editor.moveFocusForward()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,31 +584,31 @@ function AfterPlugin(options = {}) {
|
||||
* On paste.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onPaste(event, change, next) {
|
||||
function onPaste(event, editor, next) {
|
||||
debug('onPaste', { event })
|
||||
|
||||
const { value } = change
|
||||
const { value } = editor
|
||||
const transfer = getEventTransfer(event)
|
||||
const { type, fragment, text } = transfer
|
||||
|
||||
if (type == 'fragment') {
|
||||
change.insertFragment(fragment)
|
||||
editor.insertFragment(fragment)
|
||||
}
|
||||
|
||||
if (type == 'text' || type == 'html') {
|
||||
if (!text) return next()
|
||||
const { document, selection, startBlock } = value
|
||||
if (change.isVoid(startBlock)) return next()
|
||||
if (editor.isVoid(startBlock)) return next()
|
||||
|
||||
const defaultBlock = startBlock
|
||||
const defaultMarks = document.getInsertMarksAtRange(selection)
|
||||
const frag = Plain.deserialize(text, { defaultBlock, defaultMarks })
|
||||
.document
|
||||
change.insertFragment(frag)
|
||||
editor.insertFragment(frag)
|
||||
}
|
||||
|
||||
next()
|
||||
@@ -622,21 +618,21 @@ function AfterPlugin(options = {}) {
|
||||
* On select.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onSelect(event, change, next) {
|
||||
function onSelect(event, editor, next) {
|
||||
debug('onSelect', { event })
|
||||
|
||||
const window = getWindow(event.target)
|
||||
const { editor, value } = change
|
||||
const { value } = editor
|
||||
const { document } = value
|
||||
const native = window.getSelection()
|
||||
|
||||
// If there are no ranges, the editor was blurred natively.
|
||||
if (!native.rangeCount) {
|
||||
change.blur()
|
||||
editor.blur()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -661,10 +657,10 @@ function AfterPlugin(options = {}) {
|
||||
// selection, go with `0`. (2017/09/07)
|
||||
if (
|
||||
anchorBlock &&
|
||||
!change.isVoid(anchorBlock) &&
|
||||
!editor.isVoid(anchorBlock) &&
|
||||
anchor.offset == 0 &&
|
||||
focusBlock &&
|
||||
change.isVoid(focusBlock) &&
|
||||
editor.isVoid(focusBlock) &&
|
||||
focus.offset != 0
|
||||
) {
|
||||
range = range.setFocus(focus.setOffset(0))
|
||||
@@ -675,7 +671,7 @@ function AfterPlugin(options = {}) {
|
||||
// standardizes the behavior, since it's indistinguishable to the user.
|
||||
if (
|
||||
anchorInline &&
|
||||
!change.isVoid(anchorInline) &&
|
||||
!editor.isVoid(anchorInline) &&
|
||||
anchor.offset == anchorText.text.length
|
||||
) {
|
||||
const block = document.getClosestBlock(anchor.key)
|
||||
@@ -685,7 +681,7 @@ function AfterPlugin(options = {}) {
|
||||
|
||||
if (
|
||||
focusInline &&
|
||||
!change.isVoid(focusInline) &&
|
||||
!editor.isVoid(focusInline) &&
|
||||
focus.offset == focusText.text.length
|
||||
) {
|
||||
const block = document.getClosestBlock(focus.key)
|
||||
@@ -697,10 +693,10 @@ function AfterPlugin(options = {}) {
|
||||
selection = selection.setIsFocused(true)
|
||||
|
||||
// Preserve active marks from the current selection.
|
||||
// They will be cleared by `change.select` if the selection actually moved.
|
||||
// They will be cleared by `editor.select` if the selection actually moved.
|
||||
selection = selection.set('marks', value.selection.marks)
|
||||
|
||||
change.select(selection)
|
||||
editor.select(selection)
|
||||
next()
|
||||
}
|
||||
|
||||
|
@@ -36,12 +36,11 @@ function BeforePlugin() {
|
||||
* On before input.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onBeforeInput(event, change, next) {
|
||||
const { editor } = change
|
||||
function onBeforeInput(event, editor, next) {
|
||||
const isSynthetic = !!event.nativeEvent
|
||||
if (editor.readOnly) return
|
||||
|
||||
@@ -58,12 +57,11 @@ function BeforePlugin() {
|
||||
* On blur.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onBlur(event, change, next) {
|
||||
const { editor } = change
|
||||
function onBlur(event, editor, next) {
|
||||
if (isCopying) return
|
||||
if (editor.readOnly) return
|
||||
|
||||
@@ -94,7 +92,7 @@ function BeforePlugin() {
|
||||
// editable section of an element that isn't a void node (eg. a list item
|
||||
// of the check list example).
|
||||
const node = findNode(relatedTarget, editor)
|
||||
if (el.contains(relatedTarget) && node && !change.isVoid(node)) return
|
||||
if (el.contains(relatedTarget) && node && !editor.isVoid(node)) return
|
||||
}
|
||||
|
||||
debug('onBlur', { event })
|
||||
@@ -105,12 +103,11 @@ function BeforePlugin() {
|
||||
* On composition end.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onCompositionEnd(event, change, next) {
|
||||
const { editor } = change
|
||||
function onCompositionEnd(event, editor, next) {
|
||||
const n = compositionCount
|
||||
|
||||
// The `count` check here ensures that if another composition starts
|
||||
@@ -137,11 +134,11 @@ function BeforePlugin() {
|
||||
* On click.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onClick(event, change, next) {
|
||||
function onClick(event, editor, next) {
|
||||
debug('onClick', { event })
|
||||
next()
|
||||
}
|
||||
@@ -150,14 +147,13 @@ function BeforePlugin() {
|
||||
* On composition start.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onCompositionStart(event, change, next) {
|
||||
function onCompositionStart(event, editor, next) {
|
||||
isComposing = true
|
||||
compositionCount++
|
||||
const { editor } = change
|
||||
|
||||
// HACK: we need to re-render the editor here so that it will update its
|
||||
// placeholder in case one is currently rendered. This should be handled
|
||||
@@ -167,7 +163,7 @@ function BeforePlugin() {
|
||||
editor.setState({ isComposing: true })
|
||||
}
|
||||
|
||||
const { value } = change
|
||||
const { value } = editor
|
||||
const { selection } = value
|
||||
|
||||
if (!selection.isCollapsed) {
|
||||
@@ -178,7 +174,7 @@ function BeforePlugin() {
|
||||
// (because it cannot find <span> nodes in DOM). This is a workaround that
|
||||
// erases selection as soon as composition starts and preventing <spans>
|
||||
// to be dropped.
|
||||
change.delete()
|
||||
editor.delete()
|
||||
}
|
||||
|
||||
debug('onCompositionStart', { event })
|
||||
@@ -189,11 +185,11 @@ function BeforePlugin() {
|
||||
* On copy.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onCopy(event, change, next) {
|
||||
function onCopy(event, editor, next) {
|
||||
const window = getWindow(event.target)
|
||||
isCopying = true
|
||||
window.requestAnimationFrame(() => (isCopying = false))
|
||||
@@ -206,12 +202,11 @@ function BeforePlugin() {
|
||||
* On cut.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onCut(event, change, next) {
|
||||
const { editor } = change
|
||||
function onCut(event, editor, next) {
|
||||
if (editor.readOnly) return
|
||||
|
||||
const window = getWindow(event.target)
|
||||
@@ -226,11 +221,11 @@ function BeforePlugin() {
|
||||
* On drag end.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onDragEnd(event, change, next) {
|
||||
function onDragEnd(event, editor, next) {
|
||||
isDragging = false
|
||||
debug('onDragEnd', { event })
|
||||
next()
|
||||
@@ -240,11 +235,11 @@ function BeforePlugin() {
|
||||
* On drag enter.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onDragEnter(event, change, next) {
|
||||
function onDragEnter(event, editor, next) {
|
||||
debug('onDragEnter', { event })
|
||||
next()
|
||||
}
|
||||
@@ -253,11 +248,11 @@ function BeforePlugin() {
|
||||
* On drag exit.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onDragExit(event, change, next) {
|
||||
function onDragExit(event, editor, next) {
|
||||
debug('onDragExit', { event })
|
||||
next()
|
||||
}
|
||||
@@ -266,11 +261,11 @@ function BeforePlugin() {
|
||||
* On drag leave.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onDragLeave(event, change, next) {
|
||||
function onDragLeave(event, editor, next) {
|
||||
debug('onDragLeave', { event })
|
||||
next()
|
||||
}
|
||||
@@ -279,18 +274,17 @@ function BeforePlugin() {
|
||||
* On drag over.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onDragOver(event, change, next) {
|
||||
function onDragOver(event, editor, next) {
|
||||
// If the target is inside a void node, and only in this case,
|
||||
// call `preventDefault` to signal that drops are allowed.
|
||||
// When the target is editable, dropping is already allowed by
|
||||
// default, and calling `preventDefault` hides the cursor.
|
||||
const { editor } = change
|
||||
const node = findNode(event.target, editor)
|
||||
if (change.isVoid(node)) event.preventDefault()
|
||||
if (editor.isVoid(node)) event.preventDefault()
|
||||
|
||||
// COMPAT: IE won't call onDrop on contentEditables unless the
|
||||
// default dragOver is prevented:
|
||||
@@ -319,11 +313,11 @@ function BeforePlugin() {
|
||||
* On drag start.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onDragStart(event, change, next) {
|
||||
function onDragStart(event, editor, next) {
|
||||
isDragging = true
|
||||
debug('onDragStart', { event })
|
||||
next()
|
||||
@@ -333,12 +327,11 @@ function BeforePlugin() {
|
||||
* On drop.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onDrop(event, change, next) {
|
||||
const { editor } = change
|
||||
function onDrop(event, editor, next) {
|
||||
if (editor.readOnly) return
|
||||
|
||||
// Prevent default so the DOM's value isn't corrupted.
|
||||
@@ -352,12 +345,11 @@ function BeforePlugin() {
|
||||
* On focus.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onFocus(event, change, next) {
|
||||
const { editor } = change
|
||||
function onFocus(event, editor, next) {
|
||||
if (isCopying) return
|
||||
if (editor.readOnly) return
|
||||
|
||||
@@ -383,13 +375,13 @@ function BeforePlugin() {
|
||||
* On input.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onInput(event, change, next) {
|
||||
function onInput(event, editor, next) {
|
||||
if (isComposing) return
|
||||
if (change.value.selection.isBlurred) return
|
||||
if (editor.value.selection.isBlurred) return
|
||||
debug('onInput', { event })
|
||||
next()
|
||||
}
|
||||
@@ -398,12 +390,11 @@ function BeforePlugin() {
|
||||
* On key down.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onKeyDown(event, change, next) {
|
||||
const { editor } = change
|
||||
function onKeyDown(event, editor, next) {
|
||||
if (editor.readOnly) return
|
||||
|
||||
// When composing, we need to prevent all hotkeys from executing while
|
||||
@@ -415,7 +406,7 @@ function BeforePlugin() {
|
||||
}
|
||||
|
||||
// Certain hotkeys have native editing behaviors in `contenteditable`
|
||||
// elements which will change the DOM and cause our value to be out of sync,
|
||||
// elements which will editor the DOM and cause our value to be out of sync,
|
||||
// so they need to always be prevented.
|
||||
if (
|
||||
!IS_IOS &&
|
||||
@@ -443,12 +434,11 @@ function BeforePlugin() {
|
||||
* On paste.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onPaste(event, change, next) {
|
||||
const { editor } = change
|
||||
function onPaste(event, editor, next) {
|
||||
if (editor.readOnly) return
|
||||
|
||||
// Prevent defaults so the DOM state isn't corrupted.
|
||||
@@ -462,15 +452,14 @@ function BeforePlugin() {
|
||||
* On select.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {Change} change
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
*/
|
||||
|
||||
function onSelect(event, change, next) {
|
||||
function onSelect(event, editor, next) {
|
||||
if (isCopying) return
|
||||
if (isComposing) return
|
||||
|
||||
const { editor } = change
|
||||
if (editor.readOnly) return
|
||||
|
||||
// Save the new `activeElement`.
|
||||
|
12
packages/slate-react/src/plugins/react.js
vendored
12
packages/slate-react/src/plugins/react.js
vendored
@@ -41,14 +41,13 @@ function ReactPlugin(options = {}) {
|
||||
* @return {Object}
|
||||
*/
|
||||
|
||||
function renderEditor(props, next) {
|
||||
const { editor } = props
|
||||
function renderEditor(props, editor, next) {
|
||||
return (
|
||||
<Content
|
||||
onEvent={editor.event}
|
||||
autoCorrect={props.autoCorrect}
|
||||
className={props.className}
|
||||
editor={editor}
|
||||
onEvent={(handler, event) => editor.run(handler, event)}
|
||||
readOnly={props.readOnly}
|
||||
role={props.role}
|
||||
spellCheck={props.spellCheck}
|
||||
@@ -63,11 +62,12 @@ function ReactPlugin(options = {}) {
|
||||
* Render node.
|
||||
*
|
||||
* @param {Object} props
|
||||
* @param {Editor} editor
|
||||
* @param {Function} next
|
||||
* @return {Element}
|
||||
*/
|
||||
|
||||
function renderNode(props, next) {
|
||||
function renderNode(props, editor, next) {
|
||||
const { attributes, children, node } = props
|
||||
const { object } = node
|
||||
if (object != 'block' && object != 'inline') return null
|
||||
@@ -89,8 +89,8 @@ function ReactPlugin(options = {}) {
|
||||
* @return {Element}
|
||||
*/
|
||||
|
||||
function renderPlaceholder(props, next) {
|
||||
const { editor, node } = props
|
||||
function renderPlaceholder(props, editor, next) {
|
||||
const { node } = props
|
||||
if (!editor.props.placeholder) return null
|
||||
if (editor.state.isComposing) return null
|
||||
if (node.object != 'block') return null
|
||||
|
@@ -11,7 +11,7 @@ function Image(props) {
|
||||
})
|
||||
}
|
||||
|
||||
function renderNode(props, next) {
|
||||
function renderNode(props, editor, next) {
|
||||
switch (props.node.type) {
|
||||
case 'image':
|
||||
return Image(props)
|
||||
|
@@ -11,7 +11,7 @@ function Image(props) {
|
||||
})
|
||||
}
|
||||
|
||||
function renderNode(props, next) {
|
||||
function renderNode(props, editor, next) {
|
||||
switch (props.node.type) {
|
||||
case 'image':
|
||||
return Image(props)
|
||||
|
@@ -11,7 +11,7 @@ function Code(props) {
|
||||
)
|
||||
}
|
||||
|
||||
function renderNode(props, next) {
|
||||
function renderNode(props, editor, next) {
|
||||
switch (props.node.type) {
|
||||
case 'code':
|
||||
return Code(props)
|
||||
|
@@ -11,7 +11,7 @@ function Image(props) {
|
||||
})
|
||||
}
|
||||
|
||||
function renderNode(props, next) {
|
||||
function renderNode(props, editor, next) {
|
||||
switch (props.node.type) {
|
||||
case 'image':
|
||||
return Image(props)
|
||||
|
@@ -10,7 +10,7 @@ function Image(props) {
|
||||
})
|
||||
}
|
||||
|
||||
function renderNode(props, next) {
|
||||
function renderNode(props, editor, next) {
|
||||
switch (props.node.type) {
|
||||
case 'image':
|
||||
return Image(props)
|
||||
|
@@ -26,7 +26,7 @@ function Bold(props) {
|
||||
return React.createElement('strong', { ...props.attributes }, props.children)
|
||||
}
|
||||
|
||||
function renderMark(props, next) {
|
||||
function renderMark(props, editor, next) {
|
||||
switch (props.mark.type) {
|
||||
case 'bold':
|
||||
return Bold(props)
|
||||
|
@@ -11,7 +11,7 @@ function Link(props) {
|
||||
)
|
||||
}
|
||||
|
||||
function renderNode(props, next) {
|
||||
function renderNode(props, editor, next) {
|
||||
switch (props.node.type) {
|
||||
case 'link':
|
||||
return Link(props)
|
||||
|
@@ -7,7 +7,7 @@ function Emoji(props) {
|
||||
return React.createElement('img', props.attributes)
|
||||
}
|
||||
|
||||
function renderNode(props, next) {
|
||||
function renderNode(props, editor, next) {
|
||||
switch (props.node.type) {
|
||||
case 'emoji':
|
||||
return Emoji(props)
|
||||
|
@@ -11,7 +11,7 @@ function Link(props) {
|
||||
)
|
||||
}
|
||||
|
||||
function renderNode(props, next) {
|
||||
function renderNode(props, editor, next) {
|
||||
switch (props.node.type) {
|
||||
case 'link':
|
||||
return Link(props)
|
||||
|
@@ -7,7 +7,7 @@ function Bold(props) {
|
||||
return React.createElement('strong', { ...props.attributes }, props.children)
|
||||
}
|
||||
|
||||
function renderMark(props, next) {
|
||||
function renderMark(props, editor, next) {
|
||||
switch (props.mark.type) {
|
||||
case 'bold':
|
||||
return Bold(props)
|
||||
|
@@ -10,7 +10,7 @@ function Image(props) {
|
||||
})
|
||||
}
|
||||
|
||||
function renderNode(props, next) {
|
||||
function renderNode(props, editor, next) {
|
||||
switch (props.node.type) {
|
||||
case 'image':
|
||||
return Image(props)
|
||||
|
@@ -7,7 +7,7 @@ function Emoji(props) {
|
||||
return React.createElement('img', props.attributes)
|
||||
}
|
||||
|
||||
function renderNode(props, next) {
|
||||
function renderNode(props, editor, next) {
|
||||
switch (props.node.type) {
|
||||
case 'emoji':
|
||||
return Emoji(props)
|
||||
|
Reference in New Issue
Block a user