import type {Fuse} from 'sentry/utils/fuzzySearch'; type Match = Fuse.FuseResultMatch; type HighlightResult = { highlight: boolean; text: string; }; type MatchResult = HighlightResult[]; /** * Parses matches from fuse.js library * * Example `match` would be * * { * value: 'Authentication tokens allow you to perform actions', * indices: [[4, 6], [12, 13], [15, 16]], * } * * So: * * 00-03 -> not highlighted, * 04-06 -> highlighted, * 07-11 -> not highlighted, * 12-13 -> highlighted, * ...etc * * @param match The match object from fuse * @param match.value The entire string that has matches * @param match.indices Array of indices that represent matches */ const getFuseMatches = ({value, indices}: Match): MatchResult => { if (value === undefined) { return []; } if (indices.length === 0) { return [{highlight: false, text: value}]; } const strLength = value.length; const result: MatchResult = []; let prev = [0, -1]; indices.forEach(([start, end]) => { // Unhighlighted string before the match const stringBeforeMatch = value.substring(prev[1] + 1, start); // Only add to result if non-empty string if (stringBeforeMatch) { result.push({ highlight: false, text: stringBeforeMatch, }); } // This is the matched string, which should be highlighted const matchedString = value.substring(start, end + 1); result.push({ highlight: true, text: matchedString, }); prev = [start, end]; }); // The rest of the string starting from the last match index const restOfString = value.substring(prev[1] + 1, strLength); // Only add to result if non-empty string if (restOfString) { result.push({highlight: false, text: restOfString}); } return result; }; /** * Given a match object from fuse.js, returns an array of components with * "highlighted" (bold) substrings. */ const highlightFuseMatches = (matchObj: Match, Marker: React.ElementType = 'mark') => getFuseMatches(matchObj).map(({highlight, text}, index) => { if (!text) { return null; } if (highlight) { return {text}; } return {text}; }); export {getFuseMatches}; export default highlightFuseMatches;