ianstormtaylor / slate

A completely customizable framework for building rich text editors. (Currently in beta.)
http://slatejs.org
MIT License
29.71k stars 3.24k forks source link

Can't search highlight with decorations #5101

Open Sotatek-TiepLe opened 2 years ago

Sotatek-TiepLe commented 2 years ago

Description Unable to search the entire text

Recording image

Steps To reproduce the behavior: Go to: https://www.slatejs.org/examples/search-highlighting

Context Loop by node, each node is independent for searching. Hope to get support from you. Thank you very much

siebigteroth commented 2 years ago

This not a bug, it's just how decorations work right now.

In the example, the decorate functionality is only checking the text in the text node. But to get highlighting also for the bolder part, you'd have to check the parent element in your decorate function.

The reason is, that the document structure looks like this: [ { 'type': 'paragraph', 'children': [ { 'type': 'text', 'text': 'hello', 'bold': false }, { 'type': 'text', 'text': 'big', 'bold': true }, { 'type': 'text', 'text': 'world', 'bold': false } ] } ]

In my example, we'd see the text: hello big world Because "big" is bold, the whole text in the paragraph is splitted into three parts.

If your decorate function would then just search for "hello big" in the text of a text node, this won't work. Because "hello big" is part of two nodes. So you'd have to check the parent element instead.

And you'd have to do that ahead (e.g. in a useMemo for the whole text), because the decorate function only checks the current node.

Therefore, you'd collect in that useMemo all the characters of the whole document, that should be highlighted. Plus their position (Point / Range) in the whole document (editor.children).

Then you'd only have to compare in your decorate function whether the current node is a Text node and which previously collected highlighted positions are part of that text node. You could use Range.includes for that.