Skip to content

Commit

Permalink
fix: #3813
Browse files Browse the repository at this point in the history
  • Loading branch information
yf-yang committed Nov 27, 2024
1 parent e7127e8 commit 9b870c5
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ it('should be', () => {
expect(
decorateFindReplace({
...getEditorPlugin(editor, FindReplacePlugin),
entry: [{ text: '' }, [0, 0]],
entry: [{ type: 'p', children: [{ text: '' }] }, [0]],
})
).toEqual(output);
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ it('should decorate matching text', () => {
expect(
plugin.decorate?.({
...getEditorPlugin(editor, plugin),
entry: [{ text: 'test' }, [0, 0]],
entry: [{ type: 'p', children: [{ text: 'test' }] }, [0]],
})
).toEqual([
{
Expand Down Expand Up @@ -45,7 +45,7 @@ it('should decorate matching text case-insensitively', () => {
expect(
plugin.decorate?.({
...getEditorPlugin(editor, plugin),
entry: [{ text: 'test' }, [0, 0]],
entry: [{ type: 'p', children: [{ text: 'test' }] }, [0]],
})
).toEqual([
{
Expand All @@ -62,3 +62,48 @@ it('should decorate matching text case-insensitively', () => {
},
]);
});

it('should decorate matching consecutive text nodes', () => {
const editor = createSlateEditor({
plugins: [FindReplacePlugin],
});

const plugin = editor.getPlugin(FindReplacePlugin);

editor.setOption(FindReplacePlugin, 'search', 'test');

expect(
plugin.decorate?.({
...getEditorPlugin(editor, plugin),
entry: [
{ type: 'p', children: [{ text: 'tes' }, { text: 't', bold: true }] },
[0],
],
})
).toEqual([
{
[FindReplacePlugin.key]: true,
anchor: {
offset: 0,
path: [0, 0],
},
focus: {
offset: 3,
path: [0, 0],
},
search: 'tes',
},
{
[FindReplacePlugin.key]: true,
anchor: {
offset: 0,
path: [0, 1],
},
focus: {
offset: 1,
path: [0, 1],
},
search: 't',
},
]);
});
59 changes: 45 additions & 14 deletions packages/find-replace/src/lib/decorateFindReplace.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Decorate } from '@udecode/plate-common';
import type { Range } from 'slate';

import { isText } from '@udecode/plate-common';
import { isElement, isText } from '@udecode/plate-common';

import type { FindReplaceConfig } from './FindReplacePlugin';

Expand All @@ -12,27 +12,58 @@ export const decorateFindReplace: Decorate<FindReplaceConfig> = ({
}) => {
const { search } = getOptions();

const ranges: SearchRange[] = [];
if (!(search && isElement(node) && node.children.every(isText))) {
return [];
}

const texts = node.children.map((it) => it.text);

if (!search || !isText(node)) {
return ranges;
// Try to find a match
const matchStart = texts.join('').toLowerCase().indexOf(search.toLowerCase());
if (matchStart === -1) {
return [];
}

const { text } = node;
const parts = text.toLowerCase().split(search.toLowerCase());
let offset = 0;
parts.forEach((part, i) => {
if (i !== 0) {
const matchEnd = matchStart + search.length;
let cumulativePosition = 0;
const ranges: SearchRange[] = [];

for (const [i, text] of texts.entries()) {
const textStart = cumulativePosition;
const textEnd = cumulativePosition + text.length;

// Corresponding offsets within the text string
const overlapStart = Math.max(matchStart, textStart);
const overlapEnd = Math.min(matchEnd, textEnd);

if (overlapStart < overlapEnd) {
// Overlapping region exists
const anchorOffset = overlapStart - textStart;
const focusOffset = overlapEnd - textStart;

// Corresponding offsets within the search string
const searchOverlapStart = overlapStart - matchStart;
const searchOverlapEnd = overlapEnd - matchStart;

const textNodePath = [...path, i];

ranges.push({
anchor: { offset: offset - search.length, path },
focus: { offset, path },
search,
anchor: {
path: textNodePath,
offset: anchorOffset,
},
focus: {
path: textNodePath,
offset: focusOffset,
},
search: search.substring(searchOverlapStart, searchOverlapEnd),
[type]: true,
});
}

offset = offset + part.length + search.length;
});
// Update the cumulative position for the next iteration
cumulativePosition = textEnd;
}

return ranges;
};
Expand Down

0 comments on commit 9b870c5

Please sign in to comment.