mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-17 04:34:00 +02:00
Fix stale decorations (#4876)
* test changes * fix decoration not updating * Add changeset * Fix lint issues * Tests with earlier version of Node.js * Bump node version on CI The base typescript config uses ESNext as target, so presumably the latest node should be used. Co-authored-by: Dylan Schiemann <dylan@dojotoolkit.org>
This commit is contained in:
@@ -25,9 +25,11 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/runtime": "^7.7.4",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/jsdom": "^16.2.14",
|
||||
"@types/react": "^16.9.13",
|
||||
"@types/react-dom": "^16.9.4",
|
||||
"jsdom": "^16.6.0",
|
||||
"@types/react-test-renderer": "^16.8.0",
|
||||
"react": ">=16.8.0",
|
||||
"react-dom": ">=16.8.0",
|
||||
"react-test-renderer": ">=16.8.0",
|
||||
|
@@ -563,7 +563,9 @@ export const Editable = (props: EditableProps) => {
|
||||
}
|
||||
}, [scheduleOnDOMSelectionChange])
|
||||
|
||||
const decorations = decorate([editor, []])
|
||||
const decorations = [...Node.nodes(editor)].flatMap(([n, p]) =>
|
||||
decorate([n, p])
|
||||
)
|
||||
|
||||
if (
|
||||
placeholder &&
|
||||
|
@@ -5,7 +5,7 @@ declare module 'slate' {
|
||||
interface CustomTypes {
|
||||
Editor: ReactEditor
|
||||
Text: BaseText & {
|
||||
placeholder: string
|
||||
placeholder?: string
|
||||
}
|
||||
Range: BaseRange & {
|
||||
placeholder?: string
|
||||
|
@@ -49,15 +49,8 @@ const useChildren = (props: {
|
||||
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)
|
||||
}
|
||||
}
|
||||
const ds = decorations.filter(dec => Range.intersection(dec, range))
|
||||
|
||||
if (Element.isElement(n)) {
|
||||
children.push(
|
||||
|
@@ -1,46 +0,0 @@
|
||||
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
|
||||
beforeEach(() => {
|
||||
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)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
101
packages/slate-react/test/index.spec.tsx
Normal file
101
packages/slate-react/test/index.spec.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import React from 'react'
|
||||
import { createEditor, NodeEntry, Range } from 'slate'
|
||||
import { create, act, ReactTestRenderer } from 'react-test-renderer'
|
||||
import {
|
||||
Slate,
|
||||
withReact,
|
||||
DefaultEditable,
|
||||
RenderElementProps,
|
||||
DefaultElement,
|
||||
} from '../src'
|
||||
|
||||
describe('slate-react', () => {
|
||||
describe('Editable', () => {
|
||||
describe('decorate', () => {
|
||||
const createNodeMock = () => ({
|
||||
ownerDocument: global.document,
|
||||
getRootNode: () => global.document,
|
||||
})
|
||||
|
||||
it('should be called on all nodes in document', () => {
|
||||
const editor = withReact(createEditor())
|
||||
const value = [{ type: 'block', children: [{ text: '' }] }]
|
||||
|
||||
const decorate = jest.fn<Range[], [NodeEntry]>(entry => [])
|
||||
|
||||
let el: ReactTestRenderer
|
||||
|
||||
act(() => {
|
||||
el = create(
|
||||
<Slate editor={editor} value={value} onChange={() => {}}>
|
||||
<DefaultEditable decorate={decorate} />
|
||||
</Slate>,
|
||||
{ createNodeMock }
|
||||
)
|
||||
})
|
||||
|
||||
expect(decorate).toHaveBeenCalledTimes(3)
|
||||
})
|
||||
|
||||
it('should rerender the part of the tree that received an updated decoration', () => {
|
||||
const editor = withReact(createEditor())
|
||||
|
||||
const value = [
|
||||
{ type: 'block', children: [{ text: '' }] },
|
||||
{ type: 'block', children: [{ text: '' }] },
|
||||
]
|
||||
|
||||
// initial render does not return
|
||||
const decorate = jest.fn<Range[], [NodeEntry]>(() => [])
|
||||
|
||||
const renderElement = jest.fn<JSX.Element, [RenderElementProps]>(
|
||||
DefaultElement
|
||||
)
|
||||
|
||||
const onChange = jest.fn<void, []>()
|
||||
|
||||
let el: ReactTestRenderer
|
||||
|
||||
act(() => {
|
||||
el = create(
|
||||
<Slate editor={editor} value={value} onChange={onChange}>
|
||||
<DefaultEditable
|
||||
decorate={decorate}
|
||||
renderElement={renderElement}
|
||||
/>
|
||||
</Slate>,
|
||||
{ createNodeMock }
|
||||
)
|
||||
})
|
||||
|
||||
expect(renderElement).toHaveBeenCalledTimes(2)
|
||||
|
||||
decorate.mockImplementation(([node]) => {
|
||||
if (node !== value[0].children[0]) {
|
||||
return []
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
anchor: { path: [0, 0], offset: 0 },
|
||||
focus: { path: [0, 0], offset: 0 },
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
act(() => {
|
||||
el.update(
|
||||
<Slate editor={editor} value={value} onChange={onChange}>
|
||||
<DefaultEditable
|
||||
decorate={decorate}
|
||||
renderElement={renderElement}
|
||||
/>
|
||||
</Slate>
|
||||
)
|
||||
})
|
||||
|
||||
expect(renderElement).toHaveBeenCalledTimes(3)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
4
packages/slate-react/test/tsconfig.json
Normal file
4
packages/slate-react/test/tsconfig.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "../../../config/typescript/tsconfig.json",
|
||||
"references": [{ "path": "../" }]
|
||||
}
|
Reference in New Issue
Block a user