import type { TrackerAttribute } from "../types"; export interface ParsedEmmet { tag: string; id?: string; classes: string[]; attributes: Record; } /** * 解析 Emmet 风格的 tracker 语法 * 格式:tag#id.class1.class2[attr1=value1 attr2=value2] * 示例:npc#john.dwarf.warrior[hp=4/4 ac=15 name="John the Dwarf"] */ export function parseEmmet(input: string): ParsedEmmet { const result: ParsedEmmet = { tag: "", classes: [], attributes: {}, }; if (!input) return result; // 匹配属性部分 [...] const attrMatch = input.match(/\[(.+)\]$/); let attrString: string | undefined; let mainPart: string; if (attrMatch) { attrString = attrMatch[1]; mainPart = input.slice(0, attrMatch.index); } else { mainPart = input; } // 解析 tag、id 和 classes // 格式:tag#id.class1.class2.class3 const tagClassMatch = mainPart.match(/^([^#.\s]+)?(?:#([^.\s]+))?(?:\.([^.]+(?:\.[^.]+)*))?/); if (tagClassMatch) { if (tagClassMatch[1]) { result.tag = tagClassMatch[1]; } if (tagClassMatch[2]) { // # 后面的是 ID,不是 class result.id = tagClassMatch[2]; } if (tagClassMatch[3]) { result.classes.push(...tagClassMatch[3].split(".")); } } // 解析属性 if (attrString) { result.attributes = parseAttributes(attrString); } return result; } /** * 解析属性字符串 * 支持格式: * - hp=4/4 (progress 类型,自动检测) * - count=5 (count 类型,纯数字) * - name="John" (string 类型,带引号) * - name=John (string 类型,不带引号) */ function parseAttributes(attrString: string): Record { const attributes: Record = {}; // 匹配键值对:使用,分隔 const regex = /(\w+)=(?:"([^"]*)"|'([^']*)'|([^,]+))/g; let match: RegExpExecArray | null; while ((match = regex.exec(attrString)) !== null) { const key = match[1]; // 匹配的值可能是第 2、3 或 4 组(取决于引号类型) const value = match[2] ?? match[3] ?? match[4] ?? ""; // 自动检测类型 let attr: TrackerAttribute; // 检查是否是 progress 格式 (x/y) const progressMatch = value.match(/^(\d+)\/(\d+)$/); if (progressMatch) { attr = { name: key, type: "progress", value: { x: parseInt(progressMatch[1]), y: parseInt(progressMatch[2]) }, }; } // 检查是否是纯数字(count 类型) else if (/^\d+$/.test(value)) { attr = { name: key, type: "count", value: parseInt(value), }; } // 默认 string 类型 else { attr = { name: key, type: "string", value: value.replace(/^["']|["']$/g, ""), // 移除可能的引号 }; } attributes[key] = attr; } return attributes; }