export type FitMode = "contain" | "cover" | "stretch" export type SlotSpec = { name: string x: number y: number w: number h: number fit: FitMode recolor: string bg: string border: string radius: number } const SLOT_RE = //g export function parseSlots(svg: string): SlotSpec[] { const slots: SlotSpec[] = [] let m: RegExpExecArray | null while ((m = SLOT_RE.exec(svg)) !== null) { const body = m[1].trim() const spec = parseSlotBody(body) if (spec) slots.push(spec) } return slots } function parseSlotBody(body: string): SlotSpec | null { const fields = new Map() for (const part of body.split(",")) { const eq = part.indexOf("=") if (eq === -1) continue const key = part.slice(0, eq).trim() const val = part.slice(eq + 1).trim() fields.set(key, val) } const name = fields.get("name") if (!name) return null const x = num(fields, "x") const y = num(fields, "y") const w = num(fields, "w") const h = num(fields, "h") if ([x, y, w, h].some((v) => Number.isNaN(v))) return null const fit = (fields.get("fit") as FitMode) ?? "contain" const recolor = fields.get("recolor") ?? "none" const bg = fields.get("bg") ?? "none" const border = fields.get("border") ?? "none" const radius = num(fields, "radius") || 0 return { name, x, y, w, h, fit, recolor, bg, border, radius } } function num(fields: Map, key: string): number { const v = fields.get(key) if (v === undefined) return NaN return parseFloat(v) }