1
0
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:
Joe Anderson
2025-06-07 00:42:11 +01:00
committed by GitHub
parent 583d28fe13
commit fb87646e86
65 changed files with 5234 additions and 876 deletions

View File

@@ -59,6 +59,7 @@ export { Key } from './utils/key'
export {
isElementDecorationsEqual,
isTextDecorationsEqual,
splitDecorationsByChild,
} from './utils/range-list'
export {

View File

@@ -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
}