diff --git a/frontend/plugins/highlight-search.js b/frontend/plugins/highlight-search.js
index ac0b906016..120f752330 100644
--- a/frontend/plugins/highlight-search.js
+++ b/frontend/plugins/highlight-search.js
@@ -16,72 +16,60 @@
*/
export default (context, inject) => {
- const htmlText = function (text) {
- return text
- .toString()
- .replace(/&/g, "&")
- .replace(//g, ">")
- .replace(/"/g, """);
+ const highlightKeywords = function (text, keywords) {
+ const sortedKeywords = sortByLength([...keywords]);
+ const pattern = sortedKeywords.map((keyword) => createPattern(keyword));
+ const regExp = createRegExp(pattern.join("|"));
+ return replaceText(regExp, text);
};
- function htmlHighlightText(text) {
- return `${htmlText(text)}`;
+ const keywordsSpans = function (text, keywords) {
+ return (keywords || []).flatMap((keyword) => {
+ const regex = createRegExp(createPattern(keyword));
+ return [...text.matchAll(regex)].map((match) => {
+ return {
+ start: match.index,
+ end: match.index + match[0].length,
+ };
+ });
+ });
+ };
+
+ function sortByLength(keywords) {
+ return (keywords || []).sort((a, b) => b.length - a.length);
}
- const regexFromTerm = function (term) {
- let q = term.replace(/[-[\]{}()*+?.,\\/^$|#\s]/g, "");
- return new RegExp(q, "gi");
- };
+ function createPattern(value) {
+ return `([^a-zA-ZÀ-ÿ\u00f1\u00d1]|^)${escapeRegExp(value)}`;
+ }
const escapeRegExp = function (text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
};
- const highlightSearch = function (query, text) {
- const escapedText = htmlText(text);
- if (!query) {
- return text;
- }
-
- return escapedText.replace(
- regexFromTerm(query),
- (match) => `${match}`
- );
- };
+ function createRegExp(pattern) {
+ return new RegExp(pattern, "gmi");
+ }
- const highlightKeywords = function (text, keywords) {
- const sortedKeywords = ([...keywords] || []).sort(
- (a, b) => b.length - a.length
+ function replaceText(regex, text) {
+ return htmlText(text).replace(regex, (matched) =>
+ htmlHighlightText(matched)
);
- text = htmlText(text);
- sortedKeywords.forEach((keyword) => {
- const regex = new RegExp(
- `([^a-zA-ZÀ-ÿ\u00f1\u00d1]|^)${escapeRegExp(keyword)}`,
- "gmi"
- );
- text = text.replace(regex, (match) => htmlHighlightText(match));
- });
+ }
- return text;
- };
+ function htmlHighlightText(text) {
+ return `${htmlText(text)}`;
+ }
- const keywordsSpans = function (text, keywords) {
- return (keywords || []).flatMap((keyword) => {
- const regex = new RegExp(
- `([^a-zA-ZÀ-ÿ\u00f1\u00d1]|^)${escapeRegExp(keyword)}`,
- "gmi"
- );
- return [...text.matchAll(regex)].map((match) => {
- return {
- start: match.index,
- end: match.index + match[0].length,
- };
- });
- });
+ const htmlText = function (text) {
+ return text
+ .toString()
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """);
};
- inject("highlightSearch", highlightSearch);
inject("highlightKeywords", highlightKeywords);
inject("keywordsSpans", keywordsSpans);
inject("htmlText", htmlText);