mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-09-02 03:32:36 +02:00
Experimental chunking optimisation and other performance improvements (#5871)
* Chunking optimization * Fix comments * Remove redundant `insertionsMinusRemovals` variable * Fix typo * Unblock Netlify builds * Add placeholder * Upgrade Playwright (fixes crash when debugging) * Fix `autoFocus` not working * Fix huge document test * Fix the previous issue without changing `useSlateSelector` * Retry `test:integration` * Re-implement `useSlateWithV` * Retry `test:integration` * Update docs * Update JS examples to match TS examples * Upload Playwright's `test-results` directory in CI to access traces * Change trace mode to `retain-on-first-failure` * Fix: `Locator.fill(text)` is flaky on Editable * Add changesets * Increase minimum `slate-dom` version * Update changeset * Update 09-performance.md * Deprecate the `useSlateWithV` hook * Fix errors and improve clarity in 09-performance.md * Minimum `slate-dom` version is now 0.116 * Update `yarn.lock`
This commit is contained in:
@@ -59,6 +59,7 @@ export { Key } from './utils/key'
|
||||
export {
|
||||
isElementDecorationsEqual,
|
||||
isTextDecorationsEqual,
|
||||
splitDecorationsByChild,
|
||||
} from './utils/range-list'
|
||||
|
||||
export {
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { Range } from 'slate'
|
||||
import { Ancestor, DecoratedRange, Editor, Range } from 'slate'
|
||||
import { PLACEHOLDER_SYMBOL } from './weak-maps'
|
||||
import { DOMEditor } from '../plugin/dom-editor'
|
||||
|
||||
export const shallowCompare = (
|
||||
obj1: { [key: string]: unknown },
|
||||
@@ -29,9 +30,17 @@ const isDecorationFlagsEqual = (range: Range, other: Range) => {
|
||||
*/
|
||||
|
||||
export const isElementDecorationsEqual = (
|
||||
list: Range[],
|
||||
another: Range[]
|
||||
list: Range[] | null,
|
||||
another: Range[] | null
|
||||
): boolean => {
|
||||
if (list === another) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (!list || !another) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (list.length !== another.length) {
|
||||
return false
|
||||
}
|
||||
@@ -57,9 +66,17 @@ export const isElementDecorationsEqual = (
|
||||
*/
|
||||
|
||||
export const isTextDecorationsEqual = (
|
||||
list: Range[],
|
||||
another: Range[]
|
||||
list: Range[] | null,
|
||||
another: Range[] | null
|
||||
): boolean => {
|
||||
if (list === another) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (!list || !another) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (list.length !== another.length) {
|
||||
return false
|
||||
}
|
||||
@@ -80,3 +97,65 @@ export const isTextDecorationsEqual = (
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Split and group decorations by each child of a node.
|
||||
*
|
||||
* @returns An array with length equal to that of `node.children`. Each index
|
||||
* corresponds to a child of `node`, and the value is an array of decorations
|
||||
* for that child.
|
||||
*/
|
||||
|
||||
export const splitDecorationsByChild = (
|
||||
editor: Editor,
|
||||
node: Ancestor,
|
||||
decorations: DecoratedRange[]
|
||||
): DecoratedRange[][] => {
|
||||
const decorationsByChild = Array.from(
|
||||
node.children,
|
||||
(): DecoratedRange[] => []
|
||||
)
|
||||
|
||||
if (decorations.length === 0) {
|
||||
return decorationsByChild
|
||||
}
|
||||
|
||||
const path = DOMEditor.findPath(editor, node)
|
||||
const level = path.length
|
||||
const ancestorRange = Editor.range(editor, path)
|
||||
|
||||
const cachedChildRanges = new Array<Range | undefined>(node.children.length)
|
||||
|
||||
const getChildRange = (index: number) => {
|
||||
const cachedRange = cachedChildRanges[index]
|
||||
if (cachedRange) return cachedRange
|
||||
const childRange = Editor.range(editor, [...path, index])
|
||||
cachedChildRanges[index] = childRange
|
||||
return childRange
|
||||
}
|
||||
|
||||
for (const decoration of decorations) {
|
||||
const decorationRange = Range.intersection(ancestorRange, decoration)
|
||||
if (!decorationRange) continue
|
||||
|
||||
const [startPoint, endPoint] = Range.edges(decorationRange)
|
||||
const startIndex = startPoint.path[level]
|
||||
const endIndex = endPoint.path[level]
|
||||
|
||||
for (let i = startIndex; i <= endIndex; i++) {
|
||||
const ds = decorationsByChild[i]
|
||||
if (!ds) continue
|
||||
|
||||
const childRange = getChildRange(i)
|
||||
const childDecorationRange = Range.intersection(childRange, decoration)
|
||||
if (!childDecorationRange) continue
|
||||
|
||||
ds.push({
|
||||
...decoration,
|
||||
...childDecorationRange,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return decorationsByChild
|
||||
}
|
||||
|
Reference in New Issue
Block a user