"use client"; /** * parseLayoutSchema.ts * Parses the new JSON-based element model for slide layouts. * Replaces the Babel/TSX compile approach for custom templates. */ export interface SlideElement { id: string; type: "text" | "image" | "chart" | "shape"; placeholder: string; x: number; y: number; w: number; h: number; style?: Record; defaultContent?: string; content?: string; imageUrl?: string; } export interface LayoutSchema { layoutId: string; layoutName: string; slideWidth: number; slideHeight: number; background: string; elements: SlideElement[]; } export interface ParsedLayout { layoutId: string; layoutName: string; layoutDescription: string; schema: LayoutSchema; sampleData: Record; isJsonLayout: true; } /** * Detect if a layout_code string is the new JSON element model format. */ export function isJsonLayoutCode(layoutCode: string): boolean { if (!layoutCode || !layoutCode.trim().startsWith("{")) return false; try { const parsed = JSON.parse(layoutCode); return Array.isArray(parsed.elements) && typeof parsed.layoutId === "string"; } catch { return false; } } /** * Parse a JSON layout schema string into a ParsedLayout. * Returns null if the string is not valid JSON or not the new format. */ export function parseLayoutSchema(layoutCode: string): ParsedLayout | null { try { const schema: LayoutSchema = JSON.parse(layoutCode); if (!schema.elements || !Array.isArray(schema.elements)) { return null; } // Build sample data from element defaults const sampleData: Record = {}; schema.elements.forEach((elem) => { if (elem.placeholder && elem.defaultContent) { sampleData[elem.placeholder] = elem.defaultContent; } }); return { layoutId: schema.layoutId || "layout-0", layoutName: schema.layoutName || "Layout", layoutDescription: `${schema.elements.length} elements`, schema, sampleData, isJsonLayout: true, }; } catch { return null; } } /** * Merge layout schema elements with slide content data. * Slide content keys map to element placeholder names. */ export function mergeElementsWithContent( schema: LayoutSchema, content?: Record ): SlideElement[] { return schema.elements.map((elem) => ({ ...elem, content: (content?.[elem.placeholder] as string) ?? (content?.[elem.id] as string) ?? elem.defaultContent ?? "", imageUrl: (content?.[`${elem.placeholder}_url`] as string) ?? (content?.[`image_url`] as string) ?? undefined, })); }