Press n or j to go to the next uncovered block, b, p or k for the previous block.
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | 1x 1x 1x 68x 33x 1x 1x 35x 1x 1x 6x 6x 6x 1x 1x 1x 1x 1x 24x 24x 97x 97x 97x 24x 24x 53x 53x 53x 53x 53x 53x 53x 53x 24x 30x 30x 4x 4x 4x 30x 30x 24x 24x 24x 1x 1x 1x 1x 1x 35x 35x 35x 35x 35x 35x 35x 35x 35x 311x 311x 311x 311x 28x 28x 28x 28x 28x 28x 28x 28x 28x 25x 25x 24x 24x 28x 24x 24x 24x 24x 24x 24x 28x 311x 311x 287x 287x 35x 35x | import { AcceptedInputType, ActiveTrigger, Item, Trigger } from '../types';
export function getInputSelectionStart(input: AcceptedInputType): number {
return input.selectionStart;
}
export function getInputValue(input: AcceptedInputType) {
return input.value;
}
export function setInputValue(input: AcceptedInputType, value: string) {
input.value = value;
input.dispatchEvent(new Event('input'));
}
/**
* Search items by matching the search string with the item value.
*/
export function searchItems(trigger: Trigger, search: string): Item[] {
return trigger.items
.filter((item) =>
(item.searchMatch ?? item.value)
.toLowerCase()
.includes(search.toLowerCase())
)
.map((item) => ({
item,
score: [
(item.searchMatch ?? item.value)
.toLowerCase()
.indexOf(search.toLowerCase()),
item.value.length,
],
}))
.sort((a, b) => {
// Return item whose match is closer to the beginning of the string
if (a.score[0] !== b.score[0]) {
return a.score[0] - b.score[0];
}
// Return shorter item
return a.score[1] - b.score[1];
})
.map(({ item }) => item)
.slice(0, trigger.maxRenderedItems ?? Infinity);
}
/**
* Get the current active trigger for a given input
*/
export function getActiveTrigger(
input: AcceptedInputType,
triggers: Trigger[],
maxSearchLength: number
): null | ActiveTrigger {
// Start from cursor position and search for trigger keys. When found, if search regex until cursor position matches, activate suggestions
const inputValue = getInputValue(input);
const cursorPosition = getInputSelectionStart(input);
let index = cursorPosition;
while (index >= 0 && index > cursorPosition - maxSearchLength) {
// For each potential trigger key
for (const trigger of triggers) {
// If the current character is the trigger key
if (inputValue[index] === trigger.char) {
// If the following characters until cursor position match the search regex
const search = inputValue.substring(index + 1, cursorPosition);
const searchRegExp =
trigger.searchRegExp?.source ?? /\S*/.source;
const regexp = new RegExp('^' + searchRegExp + '$');
const { whitespaceBefore = true } = trigger;
if (
// Matching regexp
search.match(regexp) &&
// Whitespace before trigger
(!whitespaceBefore ||
index === 0 ||
/\s/.test(inputValue[index - 1]))
) {
return {
trigger,
search,
index,
};
}
}
}
--index;
}
return null;
}
|