import { existsSync, readFileSync } from "node:fs" import path from "node:path" import { recolorSvg, stripSvgWrapper, extractRootAttrs } from "./recolor.ts" import { computeFit, parseViewBox } from "./fit.ts" import type { SlotSpec } from "./slot-parser.ts" import type { Brand } from "./config.ts" import { resolveColor } from "./config.ts" export type ResolveResult = { inner: string contentW: number contentH: number rootAttrs: { stroke?: string; fill?: string; strokeWidth?: string } } export function resolveSlotContent( slot: SlotSpec, brand: Brand, drawImageDir: string, slotValue: string, ): ResolveResult | null { const raw = loadSlotSvg(slotValue, drawImageDir) if (!raw) return null const color = resolveColor(brand, slot.recolor) const recolored = recolorSvg(raw, color) const rootAttrs = extractRootAttrs(recolored) const inner = stripSvgWrapper(recolored) const { width, height } = parseViewBox(raw) return { inner, contentW: width, contentH: height, rootAttrs } } export function loadSlotSvg(value: string, drawImageDir: string): string | null { if (value.startsWith("./") || value.startsWith("/") || value.startsWith("../")) { if (!existsSync(value)) return null return readFileSync(value, "utf-8") } const lucidePath = path.join(drawImageDir, "icons", "lucide", `${value}.svg`) if (existsSync(lucidePath)) { return readFileSync(lucidePath, "utf-8") } const brandPath = path.join(drawImageDir, "brand-logos", `${value}.svg`) if (existsSync(brandPath)) { return readFileSync(brandPath, "utf-8") } return null } export function renderSlotSvg(slot: SlotSpec, resolved: ResolveResult): string { const fit = computeFit( slot.fit, slot.x, slot.y, slot.w, slot.h, resolved.contentW, resolved.contentH, ) const attrs = resolved.rootAttrs const strokeAttr = attrs.stroke ? ` stroke="${attrs.stroke}"` : "" const fillAttr = attrs.fill ? ` fill="${attrs.fill}"` : "" const swAttr = attrs.strokeWidth ? ` stroke-width="${attrs.strokeWidth}"` : "" return `${resolved.inner}` } export function renderSlotBackground(slot: SlotSpec, brand: Brand): string { const parts: string[] = [] if (slot.bg !== "none") { const bg = resolveColor(brand, slot.bg) const r = slot.radius ? Math.min(slot.w, slot.h) * slot.radius / 2 : 0 parts.push(``) } if (slot.border !== "none") { const border = resolveColor(brand, slot.border) const r = slot.radius ? Math.min(slot.w, slot.h) * slot.radius / 2 : 0 parts.push(``) } return parts.join("\n") }