1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-13 02:34:05 +02:00

Compare only decorations offsets in MemoizedText. Code highlighting example improvements. (#5271)

* add basePath prop to Range inside slate-react custom types, calculate absolute ranges on passing them into TextComponent

* code highlighting example improvements, minor markdown preview refactoring

* changeset added

* Revert "add basePath prop to Range inside slate-react custom types, calculate absolute ranges on passing them into TextComponent"

This reverts commit afa085c289bc67ce3d27dd33b1f074ab8153efe8.

* add basePath prop to Point inside slate-react custom types, resolve relative ranges on passing them to TextComponent

* Update changeset

* linter fixes

* remove redundant checks inside renderElement function

* custom types fixes for Range and Point in examples

* wrap intervals and ranges extractors in useMemo hook for running them only if editor.children is changed

* revert basePath changes, compare only offsets for MemoizedText decorations

* use an element as a key in decorations ranges map instead of id

* simplify code highlighting implementation, make code block nested

* fix code-highlighting example, add toolbar code block button

* remove redundant code

* fix code highlighting playwright integration test
This commit is contained in:
Sergei Dedkov
2023-02-10 00:53:21 +06:00
committed by GitHub
parent 7d1e60b88f
commit 9635b992a0
11 changed files with 782 additions and 272 deletions

View File

@@ -12,7 +12,7 @@ import {
NODE_TO_INDEX,
EDITOR_TO_KEY_TO_ELEMENT,
} from '../utils/weak-maps'
import { isDecoratorRangeListEqual } from '../utils/range-list'
import { isElementDecorationsEqual } from '../utils/range-list'
import {
RenderElementProps,
RenderLeafProps,
@@ -139,7 +139,7 @@ const MemoizedElement = React.memo(Element, (prev, next) => {
prev.element === next.element &&
prev.renderElement === next.renderElement &&
prev.renderLeaf === next.renderLeaf &&
isDecoratorRangeListEqual(prev.decorations, next.decorations) &&
isElementDecorationsEqual(prev.decorations, next.decorations) &&
(prev.selection === next.selection ||
(!!prev.selection &&
!!next.selection &&

View File

@@ -2,7 +2,7 @@ import React, { useRef } from 'react'
import { Element, Range, Text as SlateText } from 'slate'
import { ReactEditor, useSlateStatic } from '..'
import { useIsomorphicLayoutEffect } from '../hooks/use-isomorphic-layout-effect'
import { isDecoratorRangeListEqual } from '../utils/range-list'
import { isTextDecorationsEqual } from '../utils/range-list'
import {
EDITOR_TO_KEY_TO_ELEMENT,
ELEMENT_TO_NODE,
@@ -79,7 +79,7 @@ const MemoizedText = React.memo(Text, (prev, next) => {
next.isLast === prev.isLast &&
next.renderLeaf === prev.renderLeaf &&
next.text === prev.text &&
isDecoratorRangeListEqual(next.decorations, prev.decorations)
isTextDecorationsEqual(next.decorations, prev.decorations)
)
})

View File

@@ -7,6 +7,16 @@ export const shallowCompare = (obj1: {}, obj2: {}) =>
key => obj2.hasOwnProperty(key) && obj1[key] === obj2[key]
)
const isDecorationFlagsEqual = (range: Range, other: Range) => {
const { anchor: rangeAnchor, focus: rangeFocus, ...rangeOwnProps } = range
const { anchor: otherAnchor, focus: otherFocus, ...otherOwnProps } = other
return (
range[PLACEHOLDER_SYMBOL] === other[PLACEHOLDER_SYMBOL] &&
shallowCompare(rangeOwnProps, otherOwnProps)
)
}
/**
* Check if a list of decorator ranges are equal to another.
*
@@ -15,7 +25,7 @@ export const shallowCompare = (obj1: {}, obj2: {}) =>
* kept in order, and the odd case where they aren't is okay to re-render for.
*/
export const isDecoratorRangeListEqual = (
export const isElementDecorationsEqual = (
list: Range[],
another: Range[]
): boolean => {
@@ -27,13 +37,39 @@ export const isDecoratorRangeListEqual = (
const range = list[i]
const other = another[i]
const { anchor: rangeAnchor, focus: rangeFocus, ...rangeOwnProps } = range
const { anchor: otherAnchor, focus: otherFocus, ...otherOwnProps } = other
if (!Range.equals(range, other) || !isDecorationFlagsEqual(range, other)) {
return false
}
}
return true
}
/**
* Check if a list of decorator ranges are equal to another.
*
* PERF: this requires the two lists to also have the ranges inside them in the
* same order, but this is an okay constraint for us since decorations are
* kept in order, and the odd case where they aren't is okay to re-render for.
*/
export const isTextDecorationsEqual = (
list: Range[],
another: Range[]
): boolean => {
if (list.length !== another.length) {
return false
}
for (let i = 0; i < list.length; i++) {
const range = list[i]
const other = another[i]
// compare only offsets because paths doesn't matter for text
if (
!Range.equals(range, other) ||
range[PLACEHOLDER_SYMBOL] !== other[PLACEHOLDER_SYMBOL] ||
!shallowCompare(rangeOwnProps, otherOwnProps)
range.anchor.offset !== other.anchor.offset ||
range.focus.offset !== other.focus.offset ||
!isDecorationFlagsEqual(range, other)
) {
return false
}