useChatCommandSelector.helpers.ts 2.1 Ko
Télécharger le fichier
import { CommandDefinition } from '../../../api';
export interface RankedCommandDefinition extends CommandDefinition {
matchType: 'prefix' | 'contains' | 'description' | 'all';
}
const normalize = (value: string) => value.trim().toLowerCase();
export const getChatCommandQuery = (chatValue: string): string | null => {
if (!chatValue.startsWith(':') || chatValue.includes(' ')) return null;
return normalize(chatValue.slice(1));
};
const getCommandScore = (command: CommandDefinition, query: string): { score: number; matchType: RankedCommandDefinition['matchType'] } | null => {
const key = normalize(command.key);
const description = normalize(command.description || '');
if (!query) return { score: 100 + key.length, matchType: 'all' };
if (key === query) return { score: 0, matchType: 'prefix' };
if (key.startsWith(query)) return { score: 10 + (key.length - query.length), matchType: 'prefix' };
if (key.includes(query)) return { score: 40 + key.indexOf(query), matchType: 'contains' };
if (description.includes(query)) return { score: 70 + description.indexOf(query), matchType: 'description' };
return null;
};
export const getRankedCommandSuggestions = (commands: CommandDefinition[], query: string, limit: number): RankedCommandDefinition[] => {
const seen = new Set<string>();
return commands
.map((command) => {
const match = getCommandScore(command, query);
if (!match) return null;
return { command, score: match.score, matchType: match.matchType };
})
.filter((entry): entry is { command: CommandDefinition; score: number; matchType: RankedCommandDefinition['matchType'] } => !!entry)
.sort((a, b) => a.score - b.score || a.command.key.localeCompare(b.command.key))
.filter((entry) => {
const key = normalize(entry.command.key);
if (seen.has(key)) return false;
seen.add(key);
return true;
})
.slice(0, limit)
.map((entry) => ({ ...entry.command, matchType: entry.matchType }));
};
