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:
@@ -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 &&
|
||||
|
@@ -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)
|
||||
)
|
||||
})
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user