1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- import React from 'react';
- type Match = {
- value: string;
- indices: [number, number][];
- };
- type HighlightResult = {
- highlight: boolean;
- text: string;
- };
- type MatchResult = HighlightResult[];
- const getFuseMatches = ({value, indices}: Match): MatchResult => {
- 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;
- };
- const highlightFuseMatches = (matchObj: Match, Marker: React.ElementType = 'mark') =>
- getFuseMatches(matchObj).map(({highlight, text}, index) => {
- if (!text) {
- return null;
- }
- if (highlight) {
- return <Marker key={index}>{text}</Marker>;
- }
- return <span key={index}>{text}</span>;
- });
- export {getFuseMatches};
- export default highlightFuseMatches;
|