60
*/
61
export function parseLabelWithIcons(input: string): IParsedLabelWithIcons {
63
>
_parseIconsRegex.lastIndex = 0;
64
>
65
>
let text = '';
66
>
const iconOffsets: number[] = [];
67
>
let iconsOffset = 0;
68
>
69
>
while (true) {
70
>
const pos = _parseIconsRegex.lastIndex;
71
>
const match = _parseIconsRegex.exec(input);
72
>
73
>
const chars = input.substring(pos, match?.index);
74
>
if (chars.length > 0) {
75
>
text += chars;
76
>
for (let i = 0; i < chars.length; i++) {
77
>
iconOffsets.push(iconsOffset);
78
>
}
79
>
}
80
>
if (!match) {
81
>
break;
82
>
}
83
>
iconsOffset += match[0].length;
84
>
}
85
>
86
>
return { text, iconOffsets };
87
>
}
88
89
90
export function matchesFuzzyIconAware(query: string, target: IParsedLabelWithIcons, enableSeparateSubstringMatching = false): IMatch[] | null {
92
>
93
>
// Return early if there are no icon markers in the word to match against
94
>
if (!iconOffsets || iconOffsets.length === 0) {
95
return matchesFuzzy(query, text, enableSeparateSubstringMatching);
96
}
98
>
// Trim the word to match against because it could have leading
99
>
// whitespace now if the word started with an icon
100
>
const wordToMatchAgainstWithoutIconsTrimmed = ltrim(text, ' ');
101
>
const leadingWhitespaceOffset = text.length - wordToMatchAgainstWithoutIconsTrimmed.length;
102
>
103
>
// match on value without icon
104
>
const matches = matchesFuzzy(query, wordToMatchAgainstWithoutIconsTrimmed, enableSeparateSubstringMatching);
105
>
106
>
// Map matches back to offsets with icon and trimming
107
>
if (matches) {
108
>
for (const match of matches) {
109
>
const iconOffset = iconOffsets[match.start + leadingWhitespaceOffset] /* icon offsets at index */ + leadingWhitespaceOffset /* overall leading whitespace offset */;
110
>
match.start += iconOffset;
111
>
match.end += iconOffset;
112
>
}
113
>
}
114
>
115
>
return matches;
116
>
}