40 lines
1.2 KiB
TypeScript
40 lines
1.2 KiB
TypeScript
import { useCallback } from "react";
|
|
|
|
const HighlightContent: React.FC<{
|
|
html: string;
|
|
highlightPhrases: string[],
|
|
firstOccurence?: boolean
|
|
}> = ({
|
|
html,
|
|
highlightPhrases,
|
|
firstOccurence = false
|
|
}) => {
|
|
|
|
const createHighlightedContent = useCallback(() => {
|
|
if (highlightPhrases.length === 0) {
|
|
return { __html: html };
|
|
}
|
|
|
|
const escapeRegExp = (string: string) => {
|
|
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
};
|
|
|
|
const regex = new RegExp(`(${highlightPhrases.map(escapeRegExp).join('|')})`, 'i');
|
|
const globalRegex = new RegExp(`(${highlightPhrases.map(escapeRegExp).join('|')})`, 'gi');
|
|
|
|
let highlightedHtml = html;
|
|
|
|
if (firstOccurence) {
|
|
highlightedHtml = html.replace(regex, (match) => `<span style="background-color: yellow;">${match}</span>`);
|
|
} else {
|
|
highlightedHtml = html.replace(globalRegex, (match) => `<span style="background-color: yellow;">${match}</span>`);
|
|
}
|
|
|
|
return { __html: highlightedHtml };
|
|
}, [html, highlightPhrases, firstOccurence]);
|
|
|
|
return <div dangerouslySetInnerHTML={createHighlightedContent()} />;
|
|
};
|
|
|
|
export default HighlightContent;
|