I am making one React highlight component to highlight keywords on a result paragraph.
The component takes an array of keywords and text(search result).
My goal is any keyword from the array if found in the text should be highlighted in a different color.
export default function HighlightWord(props) {
const { keyWords, text } = props;
const highLightWords = keyWords.filter((keyword) => {
return keyword !== "";
});
//just color use on highlight, so far just assume only four keywords in the array
const color = [
"#f3ff33",
"#e285f5",
"#c8fae9",
"#f5e385",
];
let tempArray = [];
let keyValue = 0;
// so each keyword with has its color
for (let i = 0; i < highLightWords.length; i ) {
tempArray[i] = [highLightWords[i], color[i]];
}
return text && highLightWords.length ? (
<div>
{textToHighlight
.split(
new RegExp(
`(?<=${highLightWords.join("|")})|(?=${highLightWords.join("|")})`
)
)
.map((str) => {
if (highLightWords.includes(str)) {
let colorIndex = 0;
for (let i = 0; i < tempArray.length; i ) {
if (tempArray[i][0] == str) {
colorIndex = i;
}
}
return (
<span
key={`${str}` `${keyValue }`}
style={{ backgroundColor: color[colorIndex] }}
>
{str}
{console.log(str)}
</span>
);
} else {
return str;
}
})}
</div>
) : (
<>{text || ""}</>
);
}
I have two problems couldn't figure out how to fix them.
The first one is the keywords for some reason are all in lower case, but the text is in a normal format so if I use text.includes(keywords[index]) in some cases it won't find the keyword in the text. How can I modify my regular expression to make it case insensitive.
The second problem is if in the keyword array, one element is another element substring, for example, ["flu","influenza","health","drug"], the function will only highlight the "flu","health" and "drug". It will also highlight the "flu" inside influenza but influenza itself won't be highlighted. How to fix this on my regular expression ? thank you
CodePudding user response:
- use text.toLowerCase().includes(keywords[index])
- split the text per word - text.split(' ') and sort the keywords in descending order using length - keywords.sort((i, j) => j.length - i.length). Then check for keywords position for each splitted words from text.
let text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit";
let highLightWords = ["lorem", "olo", "dolor"];
highLightWords.sort((i, j) => j.length - i.length);
text.toLowerCase()
.split(' ')
.map((str, index) => {
for (let i = 0; i < highLightWords.length; i ) {
let temp = str.search(highLightWords[i]);
if (temp >= 0) {
console.log(str.substring(temp, temp highLightWords[i].length));
//break;
}
}
});