diff options
Diffstat (limited to 'app/assets/javascripts/search_settings')
-rw-r--r-- | app/assets/javascripts/search_settings/components/search_settings.vue | 45 |
1 files changed, 23 insertions, 22 deletions
diff --git a/app/assets/javascripts/search_settings/components/search_settings.vue b/app/assets/javascripts/search_settings/components/search_settings.vue index 3e23b8a3435..f6439c6f4c4 100644 --- a/app/assets/javascripts/search_settings/components/search_settings.vue +++ b/app/assets/javascripts/search_settings/components/search_settings.vue @@ -1,6 +1,6 @@ <script> import { GlSearchBoxByType } from '@gitlab/ui'; -import { uniq, escapeRegExp } from 'lodash'; +import { escapeRegExp } from 'lodash'; import { EXCLUDED_NODES, HIDE_CLASS, @@ -60,41 +60,42 @@ const hideSectionsExcept = (sectionSelector, visibleSections) => { }); }; -const transformMatchElement = (element, searchTerm) => { - const textStr = element.textContent; +const highlightTextNode = (textNode, searchTerm) => { const escapedSearchTerm = new RegExp(`(${escapeRegExp(searchTerm)})`, 'gi'); + const textList = textNode.data.split(escapedSearchTerm); + + return textList.reduce((documentFragment, text) => { + let addElement; - const textList = textStr.split(escapedSearchTerm); - const replaceFragment = document.createDocumentFragment(); - textList.forEach((text) => { - let addElement = document.createTextNode(text); if (escapedSearchTerm.test(text)) { addElement = document.createElement('mark'); addElement.className = `${HIGHLIGHT_CLASS} ${NONE_PADDING_CLASS}`; addElement.textContent = text; escapedSearchTerm.lastIndex = 0; + } else { + addElement = document.createTextNode(text); } - replaceFragment.appendChild(addElement); - }); - return replaceFragment; + documentFragment.appendChild(addElement); + return documentFragment; + }, document.createDocumentFragment()); }; -const highlightElements = (elements = [], searchTerm) => { - elements.forEach((element) => { - const replaceFragment = transformMatchElement(element, searchTerm); - element.innerHTML = ''; - element.appendChild(replaceFragment); +const highlightText = (textNodes = [], searchTerm) => { + textNodes.forEach((textNode) => { + const fragmentWithHighlights = highlightTextNode(textNode, searchTerm); + textNode.parentElement.replaceChild(fragmentWithHighlights, textNode); }); }; -const displayResults = ({ sectionSelector, expandSection, searchTerm }, matches) => { - const elements = matches.map((match) => match.parentElement); - const sections = uniq(elements.map((element) => findSettingsSection(sectionSelector, element))); +const displayResults = ({ sectionSelector, expandSection, searchTerm }, matchingTextNodes) => { + const sections = Array.from( + new Set(matchingTextNodes.map((node) => findSettingsSection(sectionSelector, node))), + ); hideSectionsExcept(sectionSelector, sections); sections.forEach(expandSection); - highlightElements(elements, searchTerm); + highlightText(matchingTextNodes, searchTerm); }; const clearResults = (params) => { @@ -114,13 +115,13 @@ const search = (root, searchTerm) => { : NodeFilter.FILTER_REJECT; }, }); - const results = []; + const textNodes = []; for (let currentNode = iterator.nextNode(); currentNode; currentNode = iterator.nextNode()) { - results.push(currentNode); + textNodes.push(currentNode); } - return results; + return textNodes; }; export default { |