1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-14 03:03:58 +02:00

fix bug: decorate is not called for immediate children of editor (#4394)

* fix bug: decorate is not called for immediate children of editor

* short-circuit return instead of else in Child

Co-authored-by: Tim Buckley <timothypbuckley@gmail.com>

* oops missing brace

* changeset

Co-authored-by: Tim Buckley <timothypbuckley@gmail.com>
This commit is contained in:
Jake Donham
2021-08-05 10:22:48 -07:00
committed by GitHub
parent 0214b63077
commit 0188980796
5 changed files with 409 additions and 49 deletions

View File

@@ -24,6 +24,8 @@
"tiny-invariant": "1.0.6"
},
"devDependencies": {
"jsdom": "^16.6.0",
"react-test-renderer": ">=16.8.0",
"slate": "^0.63.0",
"slate-hyperscript": "^0.62.0"
},

View File

@@ -1,5 +1,5 @@
import React from 'react'
import { Editor, Range, Element, NodeEntry, Ancestor, Descendant } from 'slate'
import { Editor, Range, Element, Path, Ancestor, Descendant } from 'slate'
import ElementComponent from '../components/element'
import TextComponent from '../components/text'
@@ -17,6 +17,67 @@ import {
* Children.
*/
const Child = (props: {
decorations: Range[]
parent: Ancestor
path: Path
child: Descendant
isLast: boolean
renderElement?: (props: RenderElementProps) => JSX.Element
renderPlaceholder: (props: RenderPlaceholderProps) => JSX.Element
renderLeaf?: (props: RenderLeafProps) => JSX.Element
selection: Range | null
}) => {
const {
decorations,
parent,
path,
child,
isLast,
renderElement,
renderPlaceholder,
renderLeaf,
selection,
} = props
const decorate = useDecorate()
const editor = useSlateStatic()
const range = Editor.range(editor, path)
const sel = selection && Range.intersection(range, selection)
const ds = decorate([child, path])
for (const dec of decorations) {
const d = Range.intersection(dec, range)
if (d) {
ds.push(d)
}
}
if (Element.isElement(child)) {
return (
<ElementComponent
decorations={ds}
element={child}
renderElement={renderElement}
renderPlaceholder={renderPlaceholder}
renderLeaf={renderLeaf}
selection={sel}
/>
)
}
return (
<TextComponent
decorations={ds}
isLast={isLast}
parent={parent}
renderPlaceholder={renderPlaceholder}
renderLeaf={renderLeaf}
text={child}
/>
)
}
const useChildren = (props: {
decorations: Range[]
node: Ancestor
@@ -33,7 +94,6 @@ const useChildren = (props: {
renderLeaf,
selection,
} = props
const decorate = useDecorate()
const editor = useSlateStatic()
const path = ReactEditor.findPath(editor, node)
const children = []
@@ -46,43 +106,21 @@ const useChildren = (props: {
const p = path.concat(i)
const n = node.children[i] as Descendant
const key = ReactEditor.findKey(editor, n)
const range = Editor.range(editor, p)
const sel = selection && Range.intersection(range, selection)
const ds = decorate([n, p])
for (const dec of decorations) {
const d = Range.intersection(dec, range)
if (d) {
ds.push(d)
}
}
if (Element.isElement(n)) {
children.push(
<ElementComponent
decorations={ds}
element={n}
key={key.id}
renderElement={renderElement}
renderPlaceholder={renderPlaceholder}
renderLeaf={renderLeaf}
selection={sel}
/>
)
} else {
children.push(
<TextComponent
decorations={ds}
key={key.id}
isLast={isLeafBlock && i === node.children.length - 1}
parent={node}
renderPlaceholder={renderPlaceholder}
renderLeaf={renderLeaf}
text={n}
/>
)
}
children.push(
<Child
decorations={decorations}
parent={node}
path={p}
child={n}
key={key.id}
isLast={isLeafBlock && i === node.children.length - 1}
renderElement={renderElement}
renderPlaceholder={renderPlaceholder}
renderLeaf={renderLeaf}
selection={selection}
/>
)
NODE_TO_INDEX.set(n, i)
NODE_TO_PARENT.set(n, node)

View File

@@ -1 +1,46 @@
describe('slate-react', () => {})
import * as Slate from 'slate'
import * as SlateReact from '..'
import { JSDOM } from 'jsdom'
import React from 'react'
import TestRenderer from 'react-test-renderer'
import assert from 'assert'
describe('slate-react', () => {
describe('Editable', () => {
describe('decorate', () => {
// stub out some DOM stuff to avoid crashes
before(() => {
const jsdom = new JSDOM()
global.window = jsdom.window
global.document = jsdom.window.document
global.Document = document.constructor
})
const createNodeMock = () => ({
ownerDocument: global.document,
getRootNode: () => global.document,
})
it('should be called on all nodes in document', () => {
const editor = SlateReact.withReact(Slate.createEditor())
const value = [{ type: 'block', children: [{ text: '' }] }]
let count = 0
const decorate = ([node, path]) => {
count++
return []
}
const el = React.createElement(
SlateReact.Slate,
{ editor, value },
React.createElement(SlateReact.Editable, { decorate })
)
TestRenderer.create(el, { createNodeMock })
// editor, block, text
assert.strictEqual(count, 3)
})
})
})
})