Skip to content

Commit 8e9b03d

Browse files
committed
feat
1 parent 1e9785a commit 8e9b03d

6 files changed

Lines changed: 39 additions & 12 deletions

File tree

docs/api/nodes/text.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,16 @@ If a `props.text` property is passed in, it will be ignored.
2626

2727
If there are properties in `text` that are not in `props`, those will be ignored when it comes to testing for a match.
2828

29-
#### `Text.decorations(node: Text, decorations: DecoratedRange[]) => Text[]`
29+
#### `Text.decorations(node: Text, decorations: DecoratedRange[]) => Leaf[]`
3030

3131
Get the leaves for a text node, given `decorations`.
3232

33+
Each `Leaf` object includes all properties of the original `Text` node, plus `start` and `end` properties indicating the offset range within the original `node.text` that the leaf represents.
34+
35+
```typescript
36+
type Leaf = Text & { start: number; end: number }
37+
```
38+
3339
### Check methods
3440
3541
#### `Text.equals(text: Text, another: Text, options?) => boolean`

docs/libraries/slate-react/editable.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ The `renderLeaf` function receives an object of type `RenderLeafProps` as its ar
117117
```typescript
118118
export interface RenderLeafProps {
119119
children: any
120-
leaf: Text
120+
leaf: Leaf
121121
text: Text
122122
attributes: {
123123
'data-slate-leaf': true

packages/slate-react/src/components/editable.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
Text,
2424
Transforms,
2525
DecoratedRange,
26+
Leaf,
2627
} from 'slate'
2728
import { useAndroidInputManager } from '../hooks/android-input-manager/use-android-input-manager'
2829
import useChildren from '../hooks/use-children'
@@ -105,8 +106,9 @@ export interface RenderElementProps {
105106

106107
export interface RenderLeafProps {
107108
children: any
108-
leaf: Text
109+
leaf: Leaf
109110
text: Text
111+
isLast: boolean
110112
attributes: {
111113
'data-slate-leaf': true
112114
}
@@ -1828,6 +1830,7 @@ export const Editable = forwardRef(
18281830
<Children
18291831
decorations={decorations}
18301832
node={editor}
1833+
path={[]}
18311834
renderElement={renderElement}
18321835
renderPlaceholder={renderPlaceholder}
18331836
renderLeaf={renderLeaf}

packages/slate-react/src/components/leaf.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import React, {
66
useEffect,
77
} from 'react'
88
import { JSX } from 'react'
9-
import { Element, Text } from 'slate'
9+
import { Element, Leaf as LeafType, Text } from 'slate'
1010
import { ResizeObserver as ResizeObserverPolyfill } from '@juggle/resize-observer'
1111
import String from './string'
1212
import {
@@ -48,7 +48,7 @@ function clearTimeoutRef(timeoutRef: MutableRefObject<TimerId>) {
4848
*/
4949
const Leaf = (props: {
5050
isLast: boolean
51-
leaf: Text
51+
leaf: LeafType
5252
parent: Element
5353
renderPlaceholder: (props: RenderPlaceholderProps) => JSX.Element
5454
renderLeaf?: (props: RenderLeafProps) => JSX.Element
@@ -157,7 +157,7 @@ const Leaf = (props: {
157157
'data-slate-leaf': true,
158158
}
159159

160-
return renderLeaf({ attributes, children, leaf, text })
160+
return renderLeaf({ attributes, children, leaf, text, isLast })
161161
}
162162

163163
const MemoizedLeaf = React.memo(Leaf, (prev, next) => {

packages/slate-react/src/components/string.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { forwardRef, memo, useRef, useState } from 'react'
2-
import { Editor, Text, Path, Element, Node } from 'slate'
2+
import { Editor, Text, Path, Element, Node, Leaf } from 'slate'
33

44
import { ReactEditor, useSlateStatic } from '..'
55
import { useIsomorphicLayoutEffect } from '../hooks/use-isomorphic-layout-effect'
@@ -12,7 +12,7 @@ import { MARK_PLACEHOLDER_SYMBOL } from 'slate-dom'
1212

1313
const String = (props: {
1414
isLast: boolean
15-
leaf: Text
15+
leaf: Leaf
1616
parent: Element
1717
text: Text
1818
}) => {

packages/slate/src/interfaces/text.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { isPlainObject } from 'is-plain-object'
2-
import { Range } from '..'
2+
import { Path, Range } from '..'
33
import { ExtendedType } from '../types/custom-types'
44
import { isDeepEqual } from '../utils/deep-equal'
55

@@ -15,6 +15,8 @@ export interface BaseText {
1515

1616
export type Text = ExtendedType<'Text', BaseText>
1717

18+
export type Leaf = Text & { start: number; end: number }
19+
1820
export interface TextEqualsOptions {
1921
loose?: boolean
2022
}
@@ -62,7 +64,7 @@ export interface TextInterface {
6264
/**
6365
* Get the leaves for a text node given decorations.
6466
*/
65-
decorations: (node: Text, decorations: DecoratedRange[]) => Text[]
67+
decorations: (node: Text, decorations: DecoratedRange[]) => Leaf[]
6668
}
6769

6870
// eslint-disable-next-line no-redeclare
@@ -111,8 +113,14 @@ export const Text: TextInterface = {
111113
return true
112114
},
113115

114-
decorations(node: Text, decorations: DecoratedRange[]): Text[] {
115-
let leaves: Text[] = [{ ...node }]
116+
decorations(node: Text, decorations: DecoratedRange[]): Leaf[] {
117+
let leaves: Leaf[] = [
118+
{
119+
...node,
120+
start: 0,
121+
end: node.text.length,
122+
},
123+
]
116124

117125
for (const dec of decorations) {
118126
const { anchor, focus, merge: mergeDecoration, ...rest } = dec
@@ -182,6 +190,16 @@ export const Text: TextInterface = {
182190
leaves = next
183191
}
184192

193+
let currentOffset = 0
194+
for (const leaf of leaves) {
195+
const start = currentOffset
196+
const end = start + leaf.text.length
197+
198+
leaf.start = start
199+
leaf.end = end
200+
currentOffset = end
201+
}
202+
185203
return leaves
186204
},
187205
}

0 commit comments

Comments
 (0)