forked from ianstormtaylor/slate
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrange-list.ts
82 lines (69 loc) · 2.17 KB
/
range-list.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import { Range } from 'slate'
import { PLACEHOLDER_SYMBOL } from './weak-maps'
export const shallowCompare = (
obj1: { [key: string]: unknown },
obj2: { [key: string]: unknown }
) =>
Object.keys(obj1).length === Object.keys(obj2).length &&
Object.keys(obj1).every(
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.
*
* 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 isElementDecorationsEqual = (
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]
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.anchor.offset !== other.anchor.offset ||
range.focus.offset !== other.focus.offset ||
!isDecorationFlagsEqual(range, other)
) {
return false
}
}
return true
}