Skip to content

Instantly share code, notes, and snippets.

@unnoq
Last active May 31, 2024 09:55
Show Gist options
  • Save unnoq/15d747dbb45f04b5ceb02b1f73c6666b to your computer and use it in GitHub Desktop.
Save unnoq/15d747dbb45f04b5ceb02b1f73c6666b to your computer and use it in GitHub Desktop.
tiptap
import { clone } from 'radash';
import type { JSONContent } from '@tiptap/core';
export function highlightContent(content: JSONContent[], words: string[]) {
let i = 0;
const result: JSONContent[] = [];
while (i < content.length) {
const child = content[i]!;
if (child.text) {
const matches: { pos: number; word: string }[] = [];
for (const word of words) {
let start = 0;
while (start < child.text.length) {
const pos = child.text.indexOf(word, start);
if (pos < 0) break;
start = pos + word.length;
matches.push({
pos,
word,
});
}
}
const sortedMatches = matches.sort((a, b) => a.pos - b.pos);
let currentPos = 0;
for (const match of sortedMatches) {
if (match.pos > currentPos) {
const pre = clone(child);
pre.text = child.text.slice(0, match.pos);
result.push(pre);
}
const mid = clone(child);
mid.text = match.word;
mid.marks = [
...(mid.marks ?? []),
{
type: 'highlight',
},
];
result.push(mid);
currentPos += match.word.length;
}
if (currentPos < child.text.length - 1) {
const suf = clone(child);
suf.text = child.text.slice(currentPos);
result.push(suf);
}
}
if (child.content) {
child.content = highlightContent(child.content, words);
result.push(child);
}
i++;
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment