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);