import { SilkeCommand, SilkeCommandTextFieldValue, SilkeCommandType } from './utils'; /** Parse raw text into structured command values */ export function parseTextToSilkeCommands( text: string, availableCommands: SilkeCommand[], ): SilkeCommandTextFieldValue[] { // Normalize non-breaking spaces to regular spaces const normalizedText = text.replace(/\u00A0/g, ' '); const result: SilkeCommandTextFieldValue[] = []; let lastIndex = 0; // Match @ or / at start of string or after whitespace, followed by alphanumeric, underscore, or hyphen const commandRegexp = /(^|[\s])(@|\/)([a-z0-9_-]*)/gi; let match: RegExpExecArray | null; while ((match = commandRegexp.exec(normalizedText)) !== null) { const [, prefix, type, value = ''] = match; const commandStart = match.index + prefix.length; // Add any text before this command (including the whitespace prefix) if (commandStart > lastIndex) { result.push({ type: 'text', value: normalizedText.slice(lastIndex, commandStart) }); } const commandType = type as SilkeCommandType; const commandValue = value; // Check if this is a complete command (exists in availableCommands) const foundCommand = availableCommands.some( (cmd) => cmd.type === commandType && cmd.value === commandValue, ); const command: SilkeCommand = { type: commandType, value: commandValue }; if (!foundCommand) command.partialMatch = true; result.push(command); lastIndex = match.index + match[0].length; } // Add any remaining text after the last command if (lastIndex < normalizedText.length) { result.push({ type: 'text', value: normalizedText.slice(lastIndex) }); } return result; }