fix: Highlight matching mentions in find and replace (#8184)

This commit is contained in:
Tom Moor
2025-01-02 22:06:42 -05:00
committed by GitHub
parent 63d70c2cd5
commit db30d080ae
+38 -15
View File
@@ -79,15 +79,17 @@ export default class FindAndReplaceExtension extends Extension {
}
private get decorations() {
return this.results.map((deco, index) =>
Decoration.inline(deco.from, deco.to, {
return this.results.map((deco, index) => {
const decorationType =
deco.type === "node" ? Decoration.node : Decoration.inline;
return decorationType(deco.from, deco.to, {
class:
this.options.resultClassName +
(this.currentResultIndex === index
? ` ${this.options.resultCurrentClassName}`
: ""),
})
);
});
});
}
public replace(replace: string): Command {
@@ -212,11 +214,12 @@ export default class FindAndReplaceExtension extends Extension {
const { from: currentFrom, to: currentTo } = this.results[index];
const offset = currentTo - currentFrom - replace.length + lastOffset;
const { from, to } = this.results[nextIndex];
const { from, to, type } = this.results[nextIndex];
this.results[nextIndex] = {
to: to - offset,
from: from - offset,
type,
};
return offset;
@@ -224,10 +227,19 @@ export default class FindAndReplaceExtension extends Extension {
private search(doc: Node) {
this.results = [];
const mergedTextNodes: {
text: string | undefined;
pos: number;
}[] = [];
const mergedTextNodes: (
| {
text: string | undefined;
pos: number;
type: "inline";
}
| {
text: string | undefined;
pos: number;
type: "node";
nodeSize: number;
}
)[] = [];
let index = 0;
if (!this.searchTerm) {
@@ -238,21 +250,32 @@ export default class FindAndReplaceExtension extends Extension {
if (node.isText) {
if (mergedTextNodes[index]) {
mergedTextNodes[index] = {
type: "inline",
text: mergedTextNodes[index].text + (node.text ?? ""),
pos: mergedTextNodes[index].pos,
};
} else {
mergedTextNodes[index] = {
type: "inline",
text: node.text,
pos,
};
}
} else if (node.type.name === "mention") {
mergedTextNodes[++index] = {
type: "node",
nodeSize: node.nodeSize,
text: node.attrs.label,
pos,
};
++index;
} else {
index += 1;
++index;
}
});
mergedTextNodes.forEach(({ text = "", pos }) => {
mergedTextNodes.forEach((node) => {
const { text = "", pos, type } = node;
try {
let m;
const search = this.findRegExp;
@@ -266,8 +289,8 @@ export default class FindAndReplaceExtension extends Extension {
// Reconstruct the correct match position
const i = m.index >= text.length ? m.index - text.length : m.index;
const from = pos + i;
const to = from + m[0].length;
const from = type === "inline" ? pos + i : pos;
const to = from + (type === "inline" ? m[0].length : node.nodeSize);
// Check if already exists in results, possible due to duplicated
// search string on L257
@@ -275,7 +298,7 @@ export default class FindAndReplaceExtension extends Extension {
continue;
}
this.results.push({ from, to });
this.results.push({ from, to, type });
}
} catch (e) {
// Invalid RegExp
@@ -349,7 +372,7 @@ export default class FindAndReplaceExtension extends Extension {
private open = false;
@observable
private results: { from: number; to: number }[] = [];
private results: { from: number; to: number; type: "inline" | "node" }[] = [];
@observable
private currentResultIndex = 0;