feat: details

This commit is contained in:
2026-03-01 09:49:01 +08:00
parent f7eabbdeba
commit a55f55505c
8 changed files with 317 additions and 173 deletions
@@ -0,0 +1,114 @@
import type { TrackerAttribute } from "../types";
export interface ParsedEmmet {
tag: string;
id?: string;
classes: string[];
attributes: Record<string, TrackerAttribute>;
}
/**
* 解析 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<string, TrackerAttribute> {
const attributes: Record<string, TrackerAttribute> = {};
// 匹配键值对:key=value 或 key="value with spaces"
const regex = /(\w+)=(?:"([^"]*)"|'([^']*)'|([^\s]+))/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;
}