-
Notifications
You must be signed in to change notification settings - Fork 278
Expand file tree
/
Copy pathgenerateHighlightedMarkupFirstMatch.ts
More file actions
43 lines (35 loc) · 1.87 KB
/
generateHighlightedMarkupFirstMatch.ts
File metadata and controls
43 lines (35 loc) · 1.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import escapeRegex from "./escapeRegex.js";
// @ts-expect-error
import encodeXML from "../sap/base/security/encodeXML.js";
/**
* Generate markup for a raw string where the first match following StartsWithPerTerm pattern is wrapped with `<b>` tag.
* StartsWithPerTerm pattern: finds the first word (at start or after whitespace) that starts with the search text.
* All inputs to this function are considered literal text, and special characters will always be escaped.
* @param {string} text The text to add highlighting to
* @param {string} textToHighlight The text which should be highlighted (case-insensitive)
* @return {string} the markup HTML which contains the first match surrounded with a `<b>` tag.
*/
function generateHighlightedMarkupFirstMatch(text: string, textToHighlight: string): string {
const normalizedText = text || "";
if (!normalizedText || !textToHighlight) {
return encodeXML(normalizedText) as string;
}
const filterValue = textToHighlight.toLowerCase();
const lowerText = normalizedText.toLowerCase();
const matchLength = textToHighlight.length;
// Find the first word that starts with textToHighlight (StartsWithPerTerm pattern)
let matchIndex = lowerText.search(new RegExp(`(^|\\s)${escapeRegex(filterValue)}`));
if (matchIndex !== -1 && lowerText[matchIndex] === " ") {
matchIndex++; // Skip the space
}
// If no match found, return encoded text
if (matchIndex === -1) {
return encodeXML(normalizedText) as string;
}
// Build highlighted markup with only the first match
const beforeMatch = encodeXML(normalizedText.substring(0, matchIndex)) as string;
const match = encodeXML(normalizedText.substring(matchIndex, matchIndex + matchLength)) as string;
const afterMatch = encodeXML(normalizedText.substring(matchIndex + matchLength)) as string;
return `${beforeMatch}<b>${match}</b>${afterMatch}`;
}
export default generateHighlightedMarkupFirstMatch;