export type DirectiveToken = { type: "if" | "elseif" | "else" | "endif" condition?: string index: number end: number } function readCondition(text: string, start: number): { condition: string; end: number } | null { let depth = 0 let inString = false let escaped = false for (let i = start; i < text.length; i++) { const char = text[i]! if (escaped) { escaped = false continue } if (char === "\\") { escaped = true continue } if (char === "\"") { inString = !inString continue } if (inString) continue if (char === "(") { depth += 1 continue } if (char === ")") { depth -= 1 if (depth === 0 && text[i + 1] === ">") { return { condition: text.slice(start + 1, i), end: i + 2 } } } } return null } export function getDirectiveTokens(text: string): DirectiveToken[] { const tokens: DirectiveToken[] = [] for (let i = 0; i < text.length; i++) { if (text[i] !== "<" || text[i + 1] !== "@") continue const rest = text.slice(i + 2) const type = ["elseif", "endif", "else", "if"].find(name => rest.startsWith(name)) as DirectiveToken["type"] | undefined if (!type) continue const afterName = i + 2 + type.length if ((type === "if" || type === "elseif") && text[afterName] === "(") { const parsed = readCondition(text, afterName) if (!parsed) continue tokens.push({ type, condition: parsed.condition, index: i, end: parsed.end }) i = parsed.end - 1 } else if ((type === "else" || type === "endif") && text[afterName] === ">") { tokens.push({ type, index: i, end: afterName + 1 }) i = afterName } } return tokens } export function splitArgs(args: string): string[] { const result: string[] = [] let current = "" let depth = 0 let inString = false let escaped = false for (const char of args) { if (escaped) { current += char escaped = false continue } if (char === "\\") { current += char escaped = true continue } if (char === "\"") { current += char inString = !inString continue } if (!inString && char === "(") depth += 1 if (!inString && char === ")") depth -= 1 if (!inString && depth === 0 && char === ",") { result.push(current.trim()) current = "" continue } current += char } if (current.trim() !== "") result.push(current.trim()) return result }