@easybits.cloud/html-tailwind-generator 0.2.117 → 0.2.119
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-O3F4GY2V.js → chunk-CSBLPJAL.js} +14 -2
- package/dist/chunk-CSBLPJAL.js.map +1 -0
- package/dist/chunk-D7YHQJET.js +192 -0
- package/dist/chunk-D7YHQJET.js.map +1 -0
- package/dist/{chunk-QF7UX3XK.js → chunk-FCTMY3FR.js} +2 -2
- package/dist/{chunk-VKIIKF4Q.js → chunk-L7D64X7G.js} +6 -3
- package/dist/{chunk-VKIIKF4Q.js.map → chunk-L7D64X7G.js.map} +1 -1
- package/dist/{chunk-5MDDRBEO.js → chunk-TDZO6X4O.js} +5 -3
- package/dist/{chunk-5MDDRBEO.js.map → chunk-TDZO6X4O.js.map} +1 -1
- package/dist/{chunk-RUOBAHYV.js → chunk-WI62YIOF.js} +13 -2
- package/dist/chunk-WI62YIOF.js.map +1 -0
- package/dist/{chunk-MNGVR2ND.js → chunk-YTVJTJRN.js} +2 -2
- package/dist/{chunk-OZ3RKRER.js → chunk-YYHFKHOQ.js} +6 -189
- package/dist/chunk-YYHFKHOQ.js.map +1 -0
- package/dist/components.js +3 -2
- package/dist/deploy.js +3 -2
- package/dist/directions.js +1 -1
- package/dist/generate.js +3 -2
- package/dist/generateDocument.js +2 -2
- package/dist/images.js +1 -1
- package/dist/index.js +13 -11
- package/dist/refine.js +3 -2
- package/package.json +1 -1
- package/dist/chunk-O3F4GY2V.js.map +0 -1
- package/dist/chunk-OZ3RKRER.js.map +0 -1
- package/dist/chunk-RUOBAHYV.js.map +0 -1
- /package/dist/{chunk-QF7UX3XK.js.map → chunk-FCTMY3FR.js.map} +0 -0
- /package/dist/{chunk-MNGVR2ND.js.map → chunk-YTVJTJRN.js.map} +0 -0
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LANDING_THEMES
|
|
3
|
+
} from "./chunk-D7YHQJET.js";
|
|
1
4
|
import {
|
|
2
5
|
currentDateLine,
|
|
3
6
|
enrichImages,
|
|
4
7
|
resolveModel,
|
|
5
8
|
sanitizeSemanticColors
|
|
6
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-L7D64X7G.js";
|
|
7
10
|
|
|
8
11
|
// src/refine.ts
|
|
9
12
|
import { streamText } from "ai";
|
|
@@ -124,6 +127,15 @@ Return the updated HTML.`
|
|
|
124
127
|
## Active Theme
|
|
125
128
|
Theme: "${themeName}" \u2014 ${desc}
|
|
126
129
|
The CSS variables are already loaded. Keep using semantic classes (bg-primary, text-on-surface, etc).`;
|
|
130
|
+
const themeObj = LANDING_THEMES.find((t) => t.id === themeName);
|
|
131
|
+
if (themeObj) {
|
|
132
|
+
finalSystem += "\nActual color values:";
|
|
133
|
+
for (const [key, hex] of Object.entries(themeObj.colors)) {
|
|
134
|
+
finalSystem += `
|
|
135
|
+
- ${key}: ${hex}`;
|
|
136
|
+
}
|
|
137
|
+
finalSystem += "\nUse these to understand the visual mood. Designs should COMPLEMENT these specific colors.";
|
|
138
|
+
}
|
|
127
139
|
}
|
|
128
140
|
if (brandKit) {
|
|
129
141
|
const bkLines = [];
|
|
@@ -168,4 +180,4 @@ export {
|
|
|
168
180
|
extractSectionDescription,
|
|
169
181
|
refineLanding
|
|
170
182
|
};
|
|
171
|
-
//# sourceMappingURL=chunk-
|
|
183
|
+
//# sourceMappingURL=chunk-CSBLPJAL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/refine.ts"],"sourcesContent":["import { streamText } from \"ai\";\nimport { enrichImages } from \"./images/enrichImages\";\nimport { sanitizeSemanticColors } from \"./sanitizeColors\";\nimport { resolveModel, currentDateLine } from \"./streamCore\";\nimport { LANDING_THEMES } from \"./themes\";\n\nexport const REFINE_SYSTEM = `You are an expert HTML/Tailwind CSS developer. You receive the current HTML of a landing page section and a user instruction.\n\nRULES:\n- Return ONLY the modified HTML — no full page, no <html>/<head>/<body> tags\n- Use Tailwind CSS classes (CDN loaded)\n- You may use inline styles for specific adjustments\n- Images: use data-image-query=\"english search query\" for new images\n- Keep all text in its original language unless asked to translate\n- Be creative — don't just make minimal changes, improve the design\n- Return raw HTML only — no markdown fences, no explanations\n\nCOLOR SYSTEM — CRITICAL:\n- Use semantic color classes: bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary, bg-surface, bg-surface-alt, text-on-surface, text-on-surface-muted, bg-secondary, text-secondary, bg-accent, text-accent\n- NEVER use hardcoded colors: NO bg-gray-*, bg-black, bg-white, text-gray-*, text-black, text-white, etc.\n- The ONLY exception: border-gray-200 or border-gray-700 for subtle dividers.\n- ALL text MUST use: text-on-surface, text-on-surface-muted, text-on-primary, text-accent. Use text-primary ONLY on bg-surface/bg-surface-alt (it's the same hue as bg-primary — invisible on primary backgrounds).\n- CONTRAST RULE: on bg-primary or bg-primary-dark → use ONLY text-on-primary. On bg-surface or bg-surface-alt → use text-on-surface, text-on-surface-muted, or text-primary. NEVER use text-primary on bg-primary — they are the SAME COLOR. NEVER put text-on-surface on bg-primary or text-on-primary on bg-surface.\n- Use bg-accent, bg-secondary, text-accent, text-secondary for visual variety — not everything should be primary.\n\nIMAGE OVERLAYS:\n- When placing text over images, ALWAYS add a gradient overlay for readability\n- Pattern: <div class=\"relative\"><img .../><div class=\"absolute inset-0 bg-gradient-to-r from-primary/80 to-transparent\"></div><div class=\"relative z-10\">...text...</div></div>\n- NEVER place text directly on images without an overlay\n\nTAILWIND v3 NOTES:\n- Standard Tailwind v3 classes (shadow-sm, shadow-md, rounded-md, etc.)\n- Borders: border + border-gray-200 for visible borders`;\n\n/**\n * Extract a text description from HTML for variant generation.\n * Instead of sending full HTML to the model, we send a content summary\n * so the model generates a completely new layout rather than tweaking colors.\n */\nexport function extractSectionDescription(html: string, label?: string): { content: string; layoutHint: string } {\n // Extract headings\n const headings = [...html.matchAll(/<h[1-6][^>]*>([\\s\\S]*?)<\\/h[1-6]>/gi)]\n .map(m => m[1].replace(/<[^>]+>/g, \"\").trim())\n .filter(Boolean);\n\n // Extract paragraphs\n const paragraphs = [...html.matchAll(/<p[^>]*>([\\s\\S]*?)<\\/p>/gi)]\n .map(m => m[1].replace(/<[^>]+>/g, \"\").trim())\n .filter(Boolean);\n\n // Extract button/CTA text\n const buttons = [...html.matchAll(/<(?:button|a)[^>]*>([\\s\\S]*?)<\\/(?:button|a)>/gi)]\n .map(m => m[1].replace(/<[^>]+>/g, \"\").trim())\n .filter(t => t.length > 0 && t.length < 60);\n\n // Count items (cards, list items, grid children)\n const listItems = (html.match(/<li[\\s>]/gi) || []).length;\n const gridMatch = html.match(/grid-cols-(\\d)/);\n const gridCols = gridMatch ? parseInt(gridMatch[1]) : 0;\n\n // Detect layout patterns for negative prompt\n const layouts: string[] = [];\n if (html.includes(\"grid\")) layouts.push(\"grid\");\n if (html.includes(\"flex-col\")) layouts.push(\"vertical-stack\");\n if (html.includes(\"flex-row\") || html.includes(\"md:flex-row\")) layouts.push(\"horizontal-flex\");\n if (html.includes(\"text-center\") && !html.includes(\"text-left\")) layouts.push(\"centered\");\n if (gridCols) layouts.push(`${gridCols}-column-grid`);\n\n const content = [\n label ? `Section: ${label}` : \"\",\n headings.length ? `Headings: ${headings.join(\" | \")}` : \"\",\n paragraphs.length ? `Text: ${paragraphs.slice(0, 3).join(\" \")}` : \"\",\n buttons.length ? `CTAs: ${buttons.join(\", \")}` : \"\",\n listItems > 0 ? `${listItems} list/card items` : \"\",\n ].filter(Boolean).join(\"\\n\");\n\n return { content, layoutHint: layouts.join(\", \") };\n}\n\nexport interface RefineOptions {\n /** Anthropic API key. Falls back to ANTHROPIC_API_KEY env var */\n anthropicApiKey?: string;\n /** OpenAI API key. If provided, uses GPT-4o-mini instead of Claude */\n openaiApiKey?: string;\n /** Current HTML of the section being refined */\n currentHtml: string;\n /** User instruction for refinement */\n instruction: string;\n /** Reference image (base64 data URI) for vision-based refinement */\n referenceImage?: string;\n /** When true, generates a completely new layout variant instead of refining */\n isVariant?: boolean;\n /** Custom system prompt (overrides default REFINE_SYSTEM) */\n systemPrompt?: string;\n /** Model ID (default: gpt-4o-mini/gpt-4o for OpenAI, claude-haiku/claude-sonnet for Anthropic) */\n model?: string;\n /** Pexels API key for image enrichment. Falls back to PEXELS_API_KEY env var */\n pexelsApiKey?: string;\n /** Called with temp DALL-E URL + query, returns permanent URL. Use to persist to S3/etc. */\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n /** Called with accumulated HTML as it streams */\n onChunk?: (html: string) => void;\n /** Called when refinement is complete with final enriched HTML */\n onDone?: (html: string) => void;\n /** Called on error */\n onError?: (error: Error) => void;\n /** Theme colors for AI context (deprecated — use themeName) */\n themeColors?: Record<string, string>;\n /** Theme name (e.g. \"minimal\", \"noche\") — tells the AI the design mood */\n themeName?: string;\n /** Brand kit info for AI context */\n brandKit?: {\n fonts?: { heading?: string; body?: string };\n mood?: string;\n logoUrl?: string;\n };\n}\n\n/**\n * Refine a landing page section with streaming AI.\n * Returns the final enriched HTML.\n */\nexport async function refineLanding(options: RefineOptions): Promise<string> {\n const {\n anthropicApiKey,\n openaiApiKey: _openaiApiKey,\n currentHtml,\n instruction,\n referenceImage,\n isVariant,\n systemPrompt = REFINE_SYSTEM,\n model: modelId,\n pexelsApiKey,\n persistImage,\n onChunk,\n onDone,\n onError,\n themeColors: _themeColors,\n themeName,\n brandKit,\n } = options;\n\n const openaiApiKey = _openaiApiKey || process.env.OPENAI_API_KEY;\n const useVision = !!referenceImage;\n const defaultOpenai = useVision ? \"gpt-4o\" : \"gpt-4o-mini\";\n const defaultAnthropic = useVision ? \"claude-sonnet-4-6\" : \"claude-haiku-4-5-20251001\";\n const model = await resolveModel({ openaiApiKey, anthropicApiKey, modelId, defaultOpenai, defaultAnthropic });\n\n // Build content (supports multimodal with reference image)\n const content: any[] = [];\n if (referenceImage) {\n content.push({ type: \"image\", image: referenceImage });\n }\n\n if (isVariant && !referenceImage) {\n // Variant mode: send description instead of HTML to force creative layout\n const { content: desc, layoutHint } = extractSectionDescription(currentHtml);\n content.push({\n type: \"text\",\n text: `Generate a COMPLETELY NEW section with the following content. Create an original, creative layout.\\n\\nContent:\\n${desc}\\n\\n${layoutHint ? `DO NOT use these layout patterns (the current design already uses them): ${layoutHint}. Choose a radically different structure.` : \"\"}\\n\\nReturn ONLY the <section>...</section> HTML with Tailwind classes.`,\n });\n } else {\n content.push({\n type: \"text\",\n text: `Current HTML:\\n${currentHtml}\\n\\nInstruction: ${instruction}\\n\\nReturn the updated HTML.`,\n });\n }\n\n // Inject theme + brand kit context\n let finalSystem = systemPrompt + currentDateLine();\n\n const THEME_DESCS: Record<string, string> = {\n minimal: \"Clean, light, professional — white surfaces, subtle grays\",\n calido: \"Warm tones — amber/orange primary, cream surfaces, cozy\",\n oceano: \"Cool blue tones — deep ocean blues, clean white surfaces\",\n noche: \"DARK theme — very dark surfaces, purple/violet accents, moody. Surfaces are dark, text is light.\",\n bosque: \"Nature-inspired — deep green primary, warm earth tones\",\n rosa: \"Soft pink/rose tones — delicate, feminine, elegant\",\n };\n\n if (themeName && themeName !== \"custom\") {\n const desc = THEME_DESCS[themeName] || themeName;\n finalSystem += `\\n\\n## Active Theme\\nTheme: \"${themeName}\" — ${desc}\\nThe CSS variables are already loaded. Keep using semantic classes (bg-primary, text-on-surface, etc).`;\n const themeObj = LANDING_THEMES.find(t => t.id === themeName);\n if (themeObj) {\n finalSystem += \"\\nActual color values:\";\n for (const [key, hex] of Object.entries(themeObj.colors)) {\n finalSystem += `\\n - ${key}: ${hex}`;\n }\n finalSystem += \"\\nUse these to understand the visual mood. Designs should COMPLEMENT these specific colors.\";\n }\n }\n\n if (brandKit) {\n const bkLines: string[] = [];\n if (brandKit.fonts?.heading) bkLines.push(`- Heading font: use font-family: '${brandKit.fonts.heading}' via inline style on h1-h6`);\n if (brandKit.fonts?.body) bkLines.push(`- Body font: use font-family: '${brandKit.fonts.body}' via inline style on p, li, span`);\n if (brandKit.mood) bkLines.push(`- Design mood: ${brandKit.mood} — adapt spacing, imagery style, and visual weight to match`);\n if (brandKit.logoUrl) bkLines.push(`- Brand logo: include <img src=\"${brandKit.logoUrl}\" alt=\"Logo\" class=\"h-8 w-auto\" /> in the navbar/hero area`);\n if (bkLines.length) finalSystem += `\\n\\n## Brand Kit\\n${bkLines.join(\"\\n\")}`;\n }\n\n const result = streamText({\n model,\n system: finalSystem,\n messages: [{ role: \"user\", content }],\n ...(isVariant && !referenceImage ? { temperature: 1.2 } : {}),\n });\n\n try {\n let accumulated = \"\";\n\n for await (const chunk of result.textStream) {\n accumulated += chunk;\n onChunk?.(accumulated);\n }\n\n // Clean up markdown fences if present\n let html = accumulated.trim();\n if (html.startsWith(\"```\")) {\n html = html.replace(/^```(?:html|xml)?\\s*/, \"\").replace(/\\s*```$/, \"\");\n }\n\n // Sanitize hardcoded colors to semantic classes\n html = sanitizeSemanticColors(html);\n\n // Enrich images (DALL-E if openaiApiKey, otherwise Pexels)\n html = await enrichImages(html, { pexelsApiKey, openaiApiKey, persistImage });\n\n onDone?.(html);\n return html;\n } catch (err: any) {\n const error = err instanceof Error ? err : new Error(err?.message || \"Refine failed\");\n onError?.(error);\n throw error;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// src/themes.ts
|
|
2
|
+
var LANDING_THEMES = [
|
|
3
|
+
{
|
|
4
|
+
id: "minimal",
|
|
5
|
+
label: "Minimal",
|
|
6
|
+
colors: {
|
|
7
|
+
primary: "#18181b",
|
|
8
|
+
"primary-light": "#3f3f46",
|
|
9
|
+
"primary-dark": "#09090b",
|
|
10
|
+
secondary: "#71717a",
|
|
11
|
+
accent: "#2563eb",
|
|
12
|
+
surface: "#ffffff",
|
|
13
|
+
"surface-alt": "#f4f4f5",
|
|
14
|
+
"on-surface": "#18181b",
|
|
15
|
+
"on-surface-muted": "#71717a",
|
|
16
|
+
"on-primary": "#ffffff"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: "calido",
|
|
21
|
+
label: "C\xE1lido",
|
|
22
|
+
colors: {
|
|
23
|
+
primary: "#9a3412",
|
|
24
|
+
"primary-light": "#c2410c",
|
|
25
|
+
"primary-dark": "#7c2d12",
|
|
26
|
+
secondary: "#78716c",
|
|
27
|
+
accent: "#d97706",
|
|
28
|
+
surface: "#fafaf9",
|
|
29
|
+
"surface-alt": "#f5f5f4",
|
|
30
|
+
"on-surface": "#1c1917",
|
|
31
|
+
"on-surface-muted": "#78716c",
|
|
32
|
+
"on-primary": "#ffffff"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "oceano",
|
|
37
|
+
label: "Oc\xE9ano",
|
|
38
|
+
colors: {
|
|
39
|
+
primary: "#0f4c75",
|
|
40
|
+
"primary-light": "#1a6fa0",
|
|
41
|
+
"primary-dark": "#0a3555",
|
|
42
|
+
secondary: "#6b7280",
|
|
43
|
+
accent: "#0d9488",
|
|
44
|
+
surface: "#ffffff",
|
|
45
|
+
"surface-alt": "#f0fdfa",
|
|
46
|
+
"on-surface": "#0f172a",
|
|
47
|
+
"on-surface-muted": "#64748b",
|
|
48
|
+
"on-primary": "#ffffff"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "noche",
|
|
53
|
+
label: "Noche",
|
|
54
|
+
colors: {
|
|
55
|
+
primary: "#a78bfa",
|
|
56
|
+
"primary-light": "#c4b5fd",
|
|
57
|
+
"primary-dark": "#8b5cf6",
|
|
58
|
+
secondary: "#9ca3af",
|
|
59
|
+
accent: "#a78bfa",
|
|
60
|
+
surface: "#111827",
|
|
61
|
+
"surface-alt": "#1f2937",
|
|
62
|
+
"on-surface": "#f9fafb",
|
|
63
|
+
"on-surface-muted": "#9ca3af",
|
|
64
|
+
"on-primary": "#111827"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: "bosque",
|
|
69
|
+
label: "Bosque",
|
|
70
|
+
colors: {
|
|
71
|
+
primary: "#16a34a",
|
|
72
|
+
"primary-light": "#22c55e",
|
|
73
|
+
"primary-dark": "#15803d",
|
|
74
|
+
secondary: "#a3a3a3",
|
|
75
|
+
accent: "#16a34a",
|
|
76
|
+
surface: "#0a0a0a",
|
|
77
|
+
"surface-alt": "#171717",
|
|
78
|
+
"on-surface": "#fafafa",
|
|
79
|
+
"on-surface-muted": "#a3a3a3",
|
|
80
|
+
"on-primary": "#000000"
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: "rosa",
|
|
85
|
+
label: "Rosa",
|
|
86
|
+
colors: {
|
|
87
|
+
primary: "#be185d",
|
|
88
|
+
"primary-light": "#db2777",
|
|
89
|
+
"primary-dark": "#9d174d",
|
|
90
|
+
secondary: "#6b7280",
|
|
91
|
+
accent: "#be185d",
|
|
92
|
+
surface: "#ffffff",
|
|
93
|
+
"surface-alt": "#fdf2f8",
|
|
94
|
+
"on-surface": "#1f2937",
|
|
95
|
+
"on-surface-muted": "#6b7280",
|
|
96
|
+
"on-primary": "#ffffff"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
];
|
|
100
|
+
function parseHex(hex) {
|
|
101
|
+
return {
|
|
102
|
+
r: parseInt(hex.slice(1, 3), 16),
|
|
103
|
+
g: parseInt(hex.slice(3, 5), 16),
|
|
104
|
+
b: parseInt(hex.slice(5, 7), 16)
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function toHex(r, g, b) {
|
|
108
|
+
return `#${[r, g, b].map((c) => Math.max(0, Math.min(255, c)).toString(16).padStart(2, "0")).join("")}`;
|
|
109
|
+
}
|
|
110
|
+
function luminance(hex) {
|
|
111
|
+
const { r, g, b } = parseHex(hex);
|
|
112
|
+
return (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
113
|
+
}
|
|
114
|
+
function lighten(hex, amount = 40) {
|
|
115
|
+
const { r, g, b } = parseHex(hex);
|
|
116
|
+
return toHex(r + amount, g + amount, b + amount);
|
|
117
|
+
}
|
|
118
|
+
function darken(hex, amount = 40) {
|
|
119
|
+
const { r, g, b } = parseHex(hex);
|
|
120
|
+
return toHex(r - amount, g - amount, b - amount);
|
|
121
|
+
}
|
|
122
|
+
function buildCustomTheme(colors) {
|
|
123
|
+
const { primary, secondary = "#f59e0b", accent = "#06b6d4", surface = "#ffffff" } = colors;
|
|
124
|
+
const onPrimary = luminance(primary) > 0.5 ? "#111827" : "#ffffff";
|
|
125
|
+
const surfaceLum = luminance(surface);
|
|
126
|
+
const isDarkSurface = surfaceLum < 0.5;
|
|
127
|
+
return {
|
|
128
|
+
id: "custom",
|
|
129
|
+
label: "Custom",
|
|
130
|
+
colors: {
|
|
131
|
+
primary,
|
|
132
|
+
"primary-light": lighten(primary),
|
|
133
|
+
"primary-dark": darken(primary),
|
|
134
|
+
secondary,
|
|
135
|
+
accent,
|
|
136
|
+
surface,
|
|
137
|
+
"surface-alt": isDarkSurface ? lighten(surface, 20) : darken(surface, 5),
|
|
138
|
+
"on-surface": isDarkSurface ? "#f1f5f9" : "#111827",
|
|
139
|
+
"on-surface-muted": isDarkSurface ? "#94a3b8" : "#6b7280",
|
|
140
|
+
"on-primary": onPrimary
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function buildCustomThemeCss(colors) {
|
|
145
|
+
const theme = buildCustomTheme(colors);
|
|
146
|
+
return `[data-theme="custom"] {
|
|
147
|
+
${buildCssVars(theme.colors)}
|
|
148
|
+
}`;
|
|
149
|
+
}
|
|
150
|
+
function buildCssVars(colors) {
|
|
151
|
+
return Object.entries(colors).map(([k, v]) => ` --color-${k}: ${v};`).join("\n");
|
|
152
|
+
}
|
|
153
|
+
function buildTailwindConfig() {
|
|
154
|
+
const colorEntries = Object.keys(LANDING_THEMES[0].colors).map((k) => ` '${k}': 'var(--color-${k})'`).join(",\n");
|
|
155
|
+
return `{
|
|
156
|
+
theme: {
|
|
157
|
+
extend: {
|
|
158
|
+
colors: {
|
|
159
|
+
${colorEntries}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}`;
|
|
164
|
+
}
|
|
165
|
+
function buildThemeCss() {
|
|
166
|
+
const defaultTheme = LANDING_THEMES[0];
|
|
167
|
+
const overrides = LANDING_THEMES.slice(1).map((t) => `[data-theme="${t.id}"] {
|
|
168
|
+
${buildCssVars(t.colors)}
|
|
169
|
+
}`).join("\n\n");
|
|
170
|
+
const css = `:root {
|
|
171
|
+
${buildCssVars(defaultTheme.colors)}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
${overrides}`;
|
|
175
|
+
return { css, tailwindConfig: buildTailwindConfig() };
|
|
176
|
+
}
|
|
177
|
+
function buildSingleThemeCss(themeId) {
|
|
178
|
+
const theme = LANDING_THEMES.find((t) => t.id === themeId) || LANDING_THEMES[0];
|
|
179
|
+
const css = `:root {
|
|
180
|
+
${buildCssVars(theme.colors)}
|
|
181
|
+
}`;
|
|
182
|
+
return { css, tailwindConfig: buildTailwindConfig() };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export {
|
|
186
|
+
LANDING_THEMES,
|
|
187
|
+
buildCustomTheme,
|
|
188
|
+
buildCustomThemeCss,
|
|
189
|
+
buildThemeCss,
|
|
190
|
+
buildSingleThemeCss
|
|
191
|
+
};
|
|
192
|
+
//# sourceMappingURL=chunk-D7YHQJET.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/themes.ts"],"sourcesContent":["export interface LandingTheme {\n id: string;\n label: string;\n colors: {\n primary: string;\n \"primary-light\": string;\n \"primary-dark\": string;\n secondary: string;\n accent: string;\n surface: string;\n \"surface-alt\": string;\n \"on-surface\": string;\n \"on-surface-muted\": string;\n \"on-primary\": string;\n };\n}\n\nexport const LANDING_THEMES: LandingTheme[] = [\n {\n id: \"minimal\",\n label: \"Minimal\",\n colors: {\n primary: \"#18181b\",\n \"primary-light\": \"#3f3f46\",\n \"primary-dark\": \"#09090b\",\n secondary: \"#71717a\",\n accent: \"#2563eb\",\n surface: \"#ffffff\",\n \"surface-alt\": \"#f4f4f5\",\n \"on-surface\": \"#18181b\",\n \"on-surface-muted\": \"#71717a\",\n \"on-primary\": \"#ffffff\",\n },\n },\n {\n id: \"calido\",\n label: \"Cálido\",\n colors: {\n primary: \"#9a3412\",\n \"primary-light\": \"#c2410c\",\n \"primary-dark\": \"#7c2d12\",\n secondary: \"#78716c\",\n accent: \"#d97706\",\n surface: \"#fafaf9\",\n \"surface-alt\": \"#f5f5f4\",\n \"on-surface\": \"#1c1917\",\n \"on-surface-muted\": \"#78716c\",\n \"on-primary\": \"#ffffff\",\n },\n },\n {\n id: \"oceano\",\n label: \"Océano\",\n colors: {\n primary: \"#0f4c75\",\n \"primary-light\": \"#1a6fa0\",\n \"primary-dark\": \"#0a3555\",\n secondary: \"#6b7280\",\n accent: \"#0d9488\",\n surface: \"#ffffff\",\n \"surface-alt\": \"#f0fdfa\",\n \"on-surface\": \"#0f172a\",\n \"on-surface-muted\": \"#64748b\",\n \"on-primary\": \"#ffffff\",\n },\n },\n {\n id: \"noche\",\n label: \"Noche\",\n colors: {\n primary: \"#a78bfa\",\n \"primary-light\": \"#c4b5fd\",\n \"primary-dark\": \"#8b5cf6\",\n secondary: \"#9ca3af\",\n accent: \"#a78bfa\",\n surface: \"#111827\",\n \"surface-alt\": \"#1f2937\",\n \"on-surface\": \"#f9fafb\",\n \"on-surface-muted\": \"#9ca3af\",\n \"on-primary\": \"#111827\",\n },\n },\n {\n id: \"bosque\",\n label: \"Bosque\",\n colors: {\n primary: \"#16a34a\",\n \"primary-light\": \"#22c55e\",\n \"primary-dark\": \"#15803d\",\n secondary: \"#a3a3a3\",\n accent: \"#16a34a\",\n surface: \"#0a0a0a\",\n \"surface-alt\": \"#171717\",\n \"on-surface\": \"#fafafa\",\n \"on-surface-muted\": \"#a3a3a3\",\n \"on-primary\": \"#000000\",\n },\n },\n {\n id: \"rosa\",\n label: \"Rosa\",\n colors: {\n primary: \"#be185d\",\n \"primary-light\": \"#db2777\",\n \"primary-dark\": \"#9d174d\",\n secondary: \"#6b7280\",\n accent: \"#be185d\",\n surface: \"#ffffff\",\n \"surface-alt\": \"#fdf2f8\",\n \"on-surface\": \"#1f2937\",\n \"on-surface-muted\": \"#6b7280\",\n \"on-primary\": \"#ffffff\",\n },\n },\n];\n\nexport interface CustomColors {\n primary: string;\n secondary?: string;\n accent?: string;\n surface?: string;\n}\n\nfunction parseHex(hex: string) {\n return {\n r: parseInt(hex.slice(1, 3), 16),\n g: parseInt(hex.slice(3, 5), 16),\n b: parseInt(hex.slice(5, 7), 16),\n };\n}\n\nfunction toHex(r: number, g: number, b: number) {\n return `#${[r, g, b].map((c) => Math.max(0, Math.min(255, c)).toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\nfunction luminance(hex: string) {\n const { r, g, b } = parseHex(hex);\n return (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n}\n\nfunction lighten(hex: string, amount = 40) {\n const { r, g, b } = parseHex(hex);\n return toHex(r + amount, g + amount, b + amount);\n}\n\nfunction darken(hex: string, amount = 40) {\n const { r, g, b } = parseHex(hex);\n return toHex(r - amount, g - amount, b - amount);\n}\n\nexport function buildCustomTheme(colors: CustomColors): LandingTheme {\n const { primary, secondary = \"#f59e0b\", accent = \"#06b6d4\", surface = \"#ffffff\" } = colors;\n\n const onPrimary = luminance(primary) > 0.5 ? \"#111827\" : \"#ffffff\";\n const surfaceLum = luminance(surface);\n const isDarkSurface = surfaceLum < 0.5;\n\n return {\n id: \"custom\",\n label: \"Custom\",\n colors: {\n primary,\n \"primary-light\": lighten(primary),\n \"primary-dark\": darken(primary),\n secondary,\n accent,\n surface,\n \"surface-alt\": isDarkSurface ? lighten(surface, 20) : darken(surface, 5),\n \"on-surface\": isDarkSurface ? \"#f1f5f9\" : \"#111827\",\n \"on-surface-muted\": isDarkSurface ? \"#94a3b8\" : \"#6b7280\",\n \"on-primary\": onPrimary,\n },\n };\n}\n\nexport function buildCustomThemeCss(colors: CustomColors): string {\n const theme = buildCustomTheme(colors);\n return `[data-theme=\"custom\"] {\\n${buildCssVars(theme.colors)}\\n}`;\n}\n\n/** CSS custom properties for a theme */\nfunction buildCssVars(colors: LandingTheme[\"colors\"]): string {\n return Object.entries(colors)\n .map(([k, v]) => ` --color-${k}: ${v};`)\n .join(\"\\n\");\n}\n\n/** Build the tailwind.config JS object string for TW v3 CDN */\nfunction buildTailwindConfig(): string {\n const colorEntries = Object.keys(LANDING_THEMES[0].colors)\n .map((k) => ` '${k}': 'var(--color-${k})'`)\n .join(\",\\n\");\n\n return `{\n theme: {\n extend: {\n colors: {\n${colorEntries}\n }\n }\n }\n }`;\n}\n\nexport function buildThemeCss(): { css: string; tailwindConfig: string } {\n const defaultTheme = LANDING_THEMES[0];\n\n const overrides = LANDING_THEMES.slice(1)\n .map((t) => `[data-theme=\"${t.id}\"] {\\n${buildCssVars(t.colors)}\\n}`)\n .join(\"\\n\\n\");\n\n const css = `:root {\\n${buildCssVars(defaultTheme.colors)}\\n}\\n\\n${overrides}`;\n return { css, tailwindConfig: buildTailwindConfig() };\n}\n\nexport function buildSingleThemeCss(themeId: string): { css: string; tailwindConfig: string } {\n const theme = LANDING_THEMES.find((t) => t.id === themeId) || LANDING_THEMES[0];\n const css = `:root {\\n${buildCssVars(theme.colors)}\\n}`;\n return { css, tailwindConfig: buildTailwindConfig() };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
resolveModel,
|
|
10
10
|
sanitizeSemanticColors,
|
|
11
11
|
streamGenerate
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-L7D64X7G.js";
|
|
13
13
|
|
|
14
14
|
// src/generateDocument.ts
|
|
15
15
|
import { generateObject, streamText } from "ai";
|
|
@@ -505,4 +505,4 @@ export {
|
|
|
505
505
|
generateDocument,
|
|
506
506
|
generateDocumentParallel
|
|
507
507
|
};
|
|
508
|
-
//# sourceMappingURL=chunk-
|
|
508
|
+
//# sourceMappingURL=chunk-FCTMY3FR.js.map
|
|
@@ -285,8 +285,11 @@ function sanitizeSemanticColors(html) {
|
|
|
285
285
|
for (const [pattern, replacement] of neutralReplacements) {
|
|
286
286
|
result = result.replace(pattern, replacement);
|
|
287
287
|
}
|
|
288
|
-
|
|
289
|
-
|
|
288
|
+
const hasSemanticClasses = /\b(?:bg-primary|bg-secondary|bg-accent|bg-surface)\b/.test(result);
|
|
289
|
+
if (!hasSemanticClasses) {
|
|
290
|
+
for (const [pattern, replacer] of chromaticReplacements) {
|
|
291
|
+
result = result.replace(pattern, replacer);
|
|
292
|
+
}
|
|
290
293
|
}
|
|
291
294
|
return result;
|
|
292
295
|
}
|
|
@@ -712,4 +715,4 @@ export {
|
|
|
712
715
|
enrichSectionSvgCharts,
|
|
713
716
|
streamGenerate
|
|
714
717
|
};
|
|
715
|
-
//# sourceMappingURL=chunk-
|
|
718
|
+
//# sourceMappingURL=chunk-L7D64X7G.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/images/pexels.ts","../src/images/dalleImages.ts","../src/images/enrichImages.ts","../src/images/svgGenerator.ts","../src/streamCore.ts","../src/sanitizeColors.ts"],"sourcesContent":["export interface PexelsResult {\n url: string;\n photographer: string;\n alt: string;\n}\n\nexport async function searchImage(query: string, apiKey?: string): Promise<PexelsResult | null> {\n const key = apiKey || process.env.PEXELS_API_KEY;\n if (!key) return null;\n try {\n const res = await fetch(\n `https://api.pexels.com/v1/search?query=${encodeURIComponent(query)}&per_page=5&orientation=landscape&locale=en-US`,\n { headers: { Authorization: key } }\n );\n if (!res.ok) {\n console.warn(`[pexels] ${res.status} for \"${query}\", trying unsplash fallback`);\n return searchUnsplash(query);\n }\n const data = await res.json();\n const photos = data.photos;\n if (!photos || photos.length === 0) {\n console.warn(`[pexels] 0 results for \"${query}\"`);\n return null;\n }\n const photo = photos[Math.floor(Math.random() * photos.length)];\n return {\n url: photo.src.large,\n photographer: photo.photographer,\n alt: photo.alt || query,\n };\n } catch {\n return searchUnsplash(query);\n }\n}\n\nasync function searchUnsplash(query: string): Promise<PexelsResult | null> {\n try {\n const res = await fetch(\n `https://unsplash.com/napi/search/photos?query=${encodeURIComponent(query)}&per_page=5&orientation=landscape`\n );\n if (!res.ok) return null;\n const data = await res.json();\n const results = data.results;\n if (!results || results.length === 0) return null;\n const photo = results[Math.floor(Math.random() * results.length)];\n return {\n url: photo.urls?.regular || photo.urls?.small,\n photographer: photo.user?.name || \"Unsplash\",\n alt: photo.alt_description || query,\n };\n } catch {\n return null;\n }\n}\n","/**\n * Generate an image using DALL-E 3 API.\n */\nexport async function generateImage(\n query: string,\n openaiApiKey: string\n): Promise<string> {\n const res = await fetch(\"https://api.openai.com/v1/images/generations\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${openaiApiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n model: \"dall-e-3\",\n prompt: query,\n n: 1,\n size: \"1792x1024\",\n }),\n });\n\n if (!res.ok) {\n const err = await res.text().catch(() => \"Unknown error\");\n throw new Error(`DALL-E API error ${res.status}: ${err}`);\n }\n\n const data = await res.json();\n return data.data[0].url;\n}\n","import { searchImage } from \"./pexels\";\nimport { generateImage } from \"./dalleImages\";\n\ninterface ImageMatch {\n query: string;\n searchStr: string;\n replaceStr: string;\n}\n\nexport interface EnrichImagesOptions {\n pexelsApiKey?: string;\n openaiApiKey?: string;\n /** Called with temp URL + query, returns permanent URL. Use to persist DALL-E images to S3/etc. */\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n}\n\nconst FAKE_DOMAINS = [\n \"images.unsplash.com\",\n \"unsplash.com\",\n \"via.placeholder.com\",\n \"placeholder.com\",\n \"placehold.co\",\n \"placehold.it\",\n \"placekitten.com\",\n \"picsum.photos\",\n \"loremflickr.com\",\n \"source.unsplash.com\",\n \"dummyimage.com\",\n \"fakeimg.pl\",\n \"example.com\",\n \"img.freepik.com\",\n \"cdn.pixabay.com\",\n];\n\n/**\n * Find all images in HTML that need Pexels enrichment.\n * Two strategies:\n * 1. data-image-query=\"...\" — AI followed instructions\n * 2. <img src=\"fake-url\" — detect fake domains, use alt/class/nearby text as query\n */\nexport function findImageSlots(html: string): ImageMatch[] {\n const matches: ImageMatch[] = [];\n const seen = new Set<string>();\n\n // 1. data-image-query=\"...\" or '...' — match the full <img> tag so we can replace src + data-image-query together\n const diqRegex = /<img\\s[^>]*data-image-query=[\"']([^\"']+)[\"'][^>]*>/gi;\n let m: RegExpExecArray | null;\n while ((m = diqRegex.exec(html)) !== null) {\n const fullTag = m[0];\n const query = m[1];\n if (seen.has(query)) continue;\n seen.add(query);\n // Build replacement tag: replace src (if any) and data-image-query with final src\n const cleanedTag = fullTag\n .replace(/\\ssrc=[\"'][^\"']*[\"']/, \"\")\n .replace(/\\sdata-image-query=[\"'][^\"']*[\"']/, \"\");\n // Insert src and data-enriched right after <img\n const replaceTag = cleanedTag.replace(\n /^<img/,\n `<img src=\"{url}\" data-enriched=\"true\"`\n );\n matches.push({\n query,\n searchStr: fullTag,\n replaceStr: replaceTag,\n });\n }\n\n // 2. <img with fake/non-existent src URLs\n const imgRegex = /<img\\s[^>]*src=\"(https?:\\/\\/[^\"]+)\"[^>]*>/gi;\n while ((m = imgRegex.exec(html)) !== null) {\n const fullTag = m[0];\n const srcUrl = m[1];\n\n if (fullTag.includes(\"data-enriched\")) continue;\n if (srcUrl.includes(\"pexels.com\")) continue;\n if (seen.has(srcUrl)) continue;\n\n // Check if domain is fake\n let isFake = false;\n try {\n const domain = new URL(srcUrl).hostname;\n isFake = FAKE_DOMAINS.some((d) => domain.includes(d));\n } catch {\n isFake = true;\n }\n if (!isFake) continue;\n\n // Extract query: try alt, then class context, then URL path words\n const altMatch = fullTag.match(/alt=\"([^\"]*?)\"/);\n let query = altMatch?.[1]?.trim() || \"\";\n\n if (!query) {\n // Try to extract meaningful words from the URL path\n try {\n const path = new URL(srcUrl).pathname;\n const words = path\n .replace(/[^a-zA-Z]/g, \" \")\n .split(/\\s+/)\n .filter((w) => w.length > 2)\n .slice(0, 4)\n .join(\" \");\n if (words.length > 3) query = words;\n } catch { /* ignore */ }\n }\n\n if (!query) query = \"professional website hero image\";\n\n seen.add(srcUrl);\n matches.push({\n query,\n searchStr: `src=\"${srcUrl}\"`,\n replaceStr: `src=\"{url}\" data-enriched=\"true\"`,\n });\n }\n\n return matches;\n}\n\n/**\n * Enrich all images in an HTML string.\n * Strategy: Pexels (free) → DALL-E fallback (if openaiApiKey) → placeholder.\n * All images resolved in parallel. If persistImage callback provided, temp DALL-E URLs are persisted.\n */\nexport async function enrichImages(html: string, pexelsApiKeyOrOpts?: string | EnrichImagesOptions, openaiApiKey?: string): Promise<string> {\n // Support both legacy (string, string) and new (options object) signatures\n let opts: EnrichImagesOptions;\n if (typeof pexelsApiKeyOrOpts === \"object\" && pexelsApiKeyOrOpts !== null) {\n opts = pexelsApiKeyOrOpts;\n } else {\n opts = { pexelsApiKey: pexelsApiKeyOrOpts, openaiApiKey };\n }\n\n const slots = findImageSlots(html);\n if (slots.length === 0) return html;\n\n // Resolve all images in parallel\n const resolved = await Promise.allSettled(\n slots.map(async (slot) => {\n let url: string | null = null;\n\n // 1. Pexels first (free)\n if (opts.pexelsApiKey) {\n const img = await searchImage(slot.query, opts.pexelsApiKey).catch(() => null);\n url = img?.url || null;\n }\n\n // 2. DALL-E fallback if Pexels found nothing\n if (!url && opts.openaiApiKey) {\n try {\n const tempUrl = await generateImage(slot.query, opts.openaiApiKey);\n url = opts.persistImage\n ? await opts.persistImage(tempUrl, slot.query)\n : tempUrl;\n } catch (e) {\n console.warn(`[dalle] failed for \"${slot.query}\":`, e);\n }\n }\n\n // 3. Placeholder fallback\n url ??= `https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(slot.query.slice(0, 30))}`;\n\n return { slot, url };\n })\n );\n\n let result = html;\n for (const r of resolved) {\n if (r.status === \"fulfilled\" && r.value) {\n const { slot, url } = r.value;\n const replacement = slot.replaceStr.replace(\"{url}\", url);\n result = result.replaceAll(slot.searchStr, replacement);\n }\n }\n\n // Catch any remaining <img> tags without src\n result = result.replace(/<img\\s(?![^>]*\\bsrc=)([^>]*?)>/gi, (_match, attrs) => {\n const altMatch = attrs.match(/alt=\"([^\"]*?)\"/);\n const query = altMatch?.[1] || \"professional image\";\n return `<img src=\"https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(query.slice(0, 30))}\" ${attrs}>`;\n });\n\n return result;\n}\n","import { createAnthropic } from \"@ai-sdk/anthropic\";\nimport { generateText } from \"ai\";\nimport { currentDateLine } from \"../streamCore\";\n\nconst SVG_SYSTEM_PROMPT = `You are a professional SVG designer. Generate clean, compact SVG graphics for documents.\n\nSTRICT SIZE RULES:\n- ALWAYS use viewBox=\"0 0 600 300\" (2:1 ratio) — no exceptions\n- ALWAYS set width=\"100%\" height=\"auto\" — NEVER use fixed pixel width/height\n- NO internal padding or margins — content fills the viewBox edge-to-edge (leave only 10-20px padding)\n- Keep SVGs under 2KB — simplicity is key\n\nSTYLE RULES:\n- Output ONLY the <svg>...</svg> tag — no markdown, no explanation\n- Flat design: solid fills, no drop shadows, minimal gradients (max 1-2)\n- Max 8-10 elements total — prefer fewer, larger shapes over many small ones\n- Color palette: use the provided theme colors, or defaults (#6366f1, #8b5cf6, #ec4899, #14b8a6, #f59e0b)\n- Text: font-family=\"system-ui, sans-serif\", font-size 12-16px, max 5 text labels\n- Self-contained: no external references, all styles inline\n\nCHART TYPES:\n- Bar charts (vertical/horizontal) — max 6 bars, rounded caps\n- Pie/donut charts — max 5 segments\n- Line charts — smooth paths, max 8 data points\n- Progress/gauge charts\n- Simple comparison charts\n- Stat cards with visual elements\n\nAVOID: complex illustrations, many small elements, decorative borders, nested groups deeper than 2 levels.`;\n\n\nexport async function generateSvg(\n prompt: string,\n anthropicApiKey?: string,\n options?: { width?: number; height?: number; themeColors?: string }\n): Promise<string> {\n const apiKey = anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n const anthropic = createAnthropic({ apiKey: apiKey || undefined });\n\n const sizeHint = options?.width && options?.height\n ? ` Target dimensions: ${options.width}x${options.height}px.`\n : \"\";\n const colorHint = options?.themeColors\n ? ` Use these theme colors: ${options.themeColors}.`\n : \"\";\n\n const result = await generateText({\n model: anthropic(\"claude-haiku-4-5-20251001\"),\n system: SVG_SYSTEM_PROMPT + currentDateLine(),\n messages: [\n {\n role: \"user\",\n content: `Generate an SVG for: ${prompt}${sizeHint}${colorHint}`,\n },\n ],\n maxOutputTokens: 2000,\n });\n\n // Extract just the SVG tag\n const svgMatch = result.text.match(/<svg[\\s\\S]*<\\/svg>/i);\n if (!svgMatch) {\n throw new Error(\"SVG generation failed — no <svg> tag in response\");\n }\n\n return svgMatch[0];\n}\n","import { streamText } from \"ai\";\nimport { createAnthropic } from \"@ai-sdk/anthropic\";\nimport { nanoid } from \"nanoid\";\nimport { findImageSlots } from \"./images/enrichImages\";\nimport { searchImage } from \"./images/pexels\";\nimport { generateImage } from \"./images/dalleImages\";\nimport { generateSvg } from \"./images/svgGenerator\";\nimport type { Section3 } from \"./types\";\nimport { sanitizeSemanticColors } from \"./sanitizeColors\";\n\nexport function currentDateLine(): string {\n return `\\nToday's date is ${new Date().toISOString().split(\"T\")[0]}. Use this for any date references.\\n`;\n}\n\n/**\n * Resolve AI model from available keys.\n * If modelId is already a LanguageModel object, return it directly.\n * Prefers Anthropic, falls back to OpenAI.\n */\nfunction isOpenAiModel(id: string): boolean {\n return /^(gpt-|o[1-9]|dall-e|tts-|whisper|chatgpt-)/.test(id);\n}\n\nfunction isLanguageModel(value: unknown): value is import(\"ai\").LanguageModel {\n return typeof value === \"object\" && value !== null && \"modelId\" in value && \"provider\" in value;\n}\n\nexport async function resolveModel(opts: {\n openaiApiKey?: string;\n anthropicApiKey?: string;\n modelId?: string | import(\"ai\").LanguageModel;\n defaultOpenai: string;\n defaultAnthropic: string;\n}) {\n // If modelId is already a model object, return it directly\n if (opts.modelId && isLanguageModel(opts.modelId)) {\n return opts.modelId;\n }\n\n const modelId = opts.modelId as string | undefined;\n\n if (modelId && isOpenAiModel(modelId)) {\n const openaiKey = opts.openaiApiKey || process.env.OPENAI_API_KEY;\n if (openaiKey) {\n const { createOpenAI } = await import(\"@ai-sdk/openai\");\n return createOpenAI({ apiKey: openaiKey })(modelId);\n }\n // OpenAI model requested but no key — fall through to Anthropic default\n } else if (modelId) {\n const anthropicKey = opts.anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n if (anthropicKey) {\n return createAnthropic({ apiKey: anthropicKey })(modelId);\n }\n }\n // No explicit modelId — prefer Anthropic, fallback to OpenAI\n const anthropicKey = opts.anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n if (anthropicKey) {\n return createAnthropic({ apiKey: anthropicKey })(opts.defaultAnthropic);\n }\n const openaiKey = opts.openaiApiKey || process.env.OPENAI_API_KEY;\n if (openaiKey) {\n const { createOpenAI } = await import(\"@ai-sdk/openai\");\n return createOpenAI({ apiKey: openaiKey })(opts.defaultOpenai);\n }\n return createAnthropic()(opts.defaultAnthropic);\n}\n\n/**\n * Convert data URL to Uint8Array for AI SDK vision.\n */\nexport function dataUrlToImagePart(dataUrl: string): { image: Uint8Array; mimeType: string } | null {\n const match = dataUrl.match(/^data:([^;]+);base64,(.+)$/);\n if (!match) return null;\n return {\n image: new Uint8Array(Buffer.from(match[2], \"base64\")),\n mimeType: match[1],\n };\n}\n\n/**\n * Extract complete JSON objects from accumulated text using brace-depth tracking.\n */\nexport function extractJsonObjects(text: string): [any[], string] {\n const objects: any[] = [];\n let remaining = text;\n\n while (remaining.length > 0) {\n remaining = remaining.trimStart();\n if (!remaining.startsWith(\"{\")) {\n const nextBrace = remaining.indexOf(\"{\");\n if (nextBrace === -1) break;\n remaining = remaining.slice(nextBrace);\n continue;\n }\n\n let depth = 0;\n let inString = false;\n let escape = false;\n let end = -1;\n\n for (let i = 0; i < remaining.length; i++) {\n const ch = remaining[i];\n if (escape) { escape = false; continue; }\n if (ch === \"\\\\\") { escape = true; continue; }\n if (ch === '\"') { inString = !inString; continue; }\n if (inString) continue;\n if (ch === \"{\") depth++;\n if (ch === \"}\") { depth--; if (depth === 0) { end = i; break; } }\n }\n\n if (end === -1) break;\n\n const candidate = remaining.slice(0, end + 1);\n remaining = remaining.slice(end + 1);\n\n try {\n objects.push(JSON.parse(candidate));\n } catch {\n // malformed, skip\n }\n }\n\n return [objects, remaining];\n}\n\n/** Inline shimmer SVG used as src for loading image placeholders */\nconst LOADING_PLACEHOLDER_SRC = `data:image/svg+xml,${encodeURIComponent('<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"800\" height=\"500\" viewBox=\"0 0 800 500\"><rect fill=\"#f3f4f6\" width=\"800\" height=\"500\" rx=\"12\"/><g opacity=\".4\"><rect x=\"320\" y=\"200\" width=\"160\" height=\"4\" rx=\"2\" fill=\"#d1d5db\"><animate attributeName=\"opacity\" values=\".3;.8;.3\" dur=\"1.5s\" repeatCount=\"indefinite\"/></rect><rect x=\"280\" y=\"215\" width=\"240\" height=\"4\" rx=\"2\" fill=\"#d1d5db\"><animate attributeName=\"opacity\" values=\".3;.8;.3\" dur=\"1.5s\" begin=\".3s\" repeatCount=\"indefinite\"/></rect><rect x=\"340\" y=\"230\" width=\"120\" height=\"4\" rx=\"2\" fill=\"#d1d5db\"><animate attributeName=\"opacity\" values=\".3;.8;.3\" dur=\"1.5s\" begin=\".6s\" repeatCount=\"indefinite\"/></rect></g><g transform=\"translate(376,150)\" opacity=\".3\"><path d=\"M0 28V4a4 4 0 014-4h40a4 4 0 014 4v24a4 4 0 01-4 4H4a4 4 0 01-4-4z\" fill=\"#d1d5db\"/><circle cx=\"14\" cy=\"12\" r=\"4\" fill=\"#9ca3af\"/><path d=\"M4 28l10-10 6 6 8-8 16 16H4z\" fill=\"#9ca3af\" opacity=\".5\"/></g></svg>')}`;\n\n/** Inline SVG placeholder for loading charts */\nconst SVG_LOADING_PLACEHOLDER = `<div class=\"w-full h-48 bg-gray-50 rounded-lg flex items-center justify-center animate-pulse\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"48\" height=\"48\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#9ca3af\" stroke-width=\"1.5\"><rect x=\"3\" y=\"12\" width=\"4\" height=\"9\" rx=\"1\"/><rect x=\"10\" y=\"7\" width=\"4\" height=\"14\" rx=\"1\"/><rect x=\"17\" y=\"3\" width=\"4\" height=\"18\" rx=\"1\"/></svg></div>`;\n\n/** Replace data-svg-chart divs with loading placeholders */\nexport function addSvgLoadingPlaceholders(html: string): string {\n return html.replace(\n /<div\\s([^>]*?)data-svg-chart=\"([^\"]+)\"([^>]*?)>[\\s\\S]*?<\\/div>/gi,\n (_match, before, chart, after) => {\n return `<div ${before}data-svg-chart=\"${chart}\"${after}>${SVG_LOADING_PLACEHOLDER}</div>`;\n }\n );\n}\n\n/** Replace data-image-query attrs with animated loading placeholders */\nexport function addLoadingPlaceholders(html: string): string {\n return html.replace(\n /(<img\\s[^>]*)data-image-query=\"([^\"]+)\"([^>]*?)(?:\\s*\\/?>)/gi,\n (_match, before, query, after) => {\n if (before.includes('src=') || after.includes('src=')) return _match;\n return `${before}src=\"${LOADING_PLACEHOLDER_SRC}\" data-image-query=\"${query}\" alt=\"${query}\"${after}>`;\n }\n );\n}\n\n/** Enrich a section's images (Pexels → DALL-E → placeholder fallback). Mutates section.html in place. */\nexport async function enrichSectionImages(\n section: Section3,\n opts: {\n pexelsApiKey?: string;\n openaiApiKey?: string;\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n onImageUpdate?: (sectionId: string, html: string) => void;\n }\n): Promise<void> {\n const slots = findImageSlots(section.html);\n if (slots.length === 0) return;\n const results = await Promise.allSettled(\n slots.map(async (slot) => {\n let url: string | null = null;\n if (opts.pexelsApiKey) {\n const img = await searchImage(slot.query, opts.pexelsApiKey).catch(() => null);\n url = img?.url || null;\n }\n if (!url && opts.openaiApiKey) {\n try {\n const tempUrl = await generateImage(slot.query, opts.openaiApiKey);\n url = opts.persistImage ? await opts.persistImage(tempUrl, slot.query) : tempUrl;\n } catch (e) {\n console.warn(`[dalle] failed for \"${slot.query}\":`, e);\n }\n }\n url ??= `https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(slot.query.slice(0, 30))}`;\n return { slot, url };\n })\n );\n let html = section.html;\n for (const r of results) {\n if (r.status === \"fulfilled\" && r.value) {\n const { slot, url } = r.value;\n const replacement = slot.replaceStr.replace(\"{url}\", url);\n html = html.replaceAll(slot.searchStr, replacement);\n }\n }\n if (html !== section.html) {\n section.html = html;\n opts.onImageUpdate?.(section.id, html);\n }\n}\n\n/** Enrich a section's SVG chart placeholders. Mutates section.html in place. */\nexport async function enrichSectionSvgCharts(\n section: Section3,\n opts: {\n anthropicApiKey?: string;\n onImageUpdate?: (sectionId: string, html: string) => void;\n }\n): Promise<void> {\n const svgRegex = /<div\\s[^>]*data-svg-chart=\"([^\"]+)\"[^>]*>[\\s\\S]*?<\\/div>/gi;\n const svgMatches: { fullMatch: string; prompt: string }[] = [];\n let svgM: RegExpExecArray | null;\n while ((svgM = svgRegex.exec(section.html)) !== null) {\n svgMatches.push({ fullMatch: svgM[0], prompt: svgM[1] });\n }\n if (svgMatches.length === 0) return;\n const anthropicKey = opts.anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n const results = await Promise.allSettled(\n svgMatches.map(async ({ fullMatch, prompt }) => {\n try {\n const svg = await generateSvg(prompt, anthropicKey);\n return { fullMatch, svg };\n } catch (e) {\n console.warn(`[svg] failed for \"${prompt}\":`, e);\n return { fullMatch, svg: `<div class=\"w-full h-48 bg-gray-100 rounded-lg flex items-center justify-center text-gray-400 text-sm\">${prompt}</div>` };\n }\n })\n );\n let html = section.html;\n for (const r of results) {\n if (r.status === \"fulfilled\" && r.value) {\n html = html.replace(r.value.fullMatch, r.value.svg);\n }\n }\n if (html !== section.html) {\n section.html = html;\n opts.onImageUpdate?.(section.id, html);\n }\n}\n\nexport interface StreamGenerateOptions {\n /** Anthropic API key */\n anthropicApiKey?: string;\n /** OpenAI API key */\n openaiApiKey?: string;\n /** Model ID override or pre-built LanguageModel object */\n model?: string | import(\"ai\").LanguageModel;\n /** System prompt */\n systemPrompt: string;\n /** User message content (text or multimodal parts) */\n userContent: any[];\n /** Pexels API key for image enrichment */\n pexelsApiKey?: string;\n /** Persist DALL-E images to permanent storage */\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n /** Called when a new section is parsed */\n onSection?: (section: Section3) => void;\n /** Called when a section's images are enriched */\n onImageUpdate?: (sectionId: string, html: string) => void;\n /** Called with raw text buffer for real-time partial streaming */\n onRawChunk?: (buffer: string, completedCount: number) => void;\n /** Called when generation is complete */\n onDone?: (sections: Section3[]) => void;\n /** Called on error */\n onError?: (error: Error) => void;\n}\n\n/**\n * Core streaming generation: stream AI text → parse NDJSON → emit sections → enrich images.\n * Used by both generateLanding and generateDocument.\n */\nexport async function streamGenerate(options: StreamGenerateOptions): Promise<Section3[]> {\n const {\n anthropicApiKey,\n openaiApiKey: _openaiApiKey,\n model: modelId,\n systemPrompt,\n userContent,\n pexelsApiKey,\n persistImage,\n onSection,\n onImageUpdate,\n onRawChunk,\n onDone,\n onError,\n } = options;\n\n const openaiApiKey = _openaiApiKey || process.env.OPENAI_API_KEY;\n const model = await resolveModel({\n openaiApiKey,\n anthropicApiKey,\n modelId,\n defaultOpenai: \"gpt-4o\",\n defaultAnthropic: \"claude-sonnet-4-6\",\n });\n\n const result = streamText({\n model,\n system: systemPrompt + currentDateLine(),\n messages: [{ role: \"user\", content: userContent }],\n });\n\n const allSections: Section3[] = [];\n const imagePromises: Promise<void>[] = [];\n let sectionOrder = 0;\n let buffer = \"\";\n\n function enrichSvgCharts(sectionRef: Section3) {\n const svgRegex = /<div\\s[^>]*data-svg-chart=\"([^\"]+)\"[^>]*>[\\s\\S]*?<\\/div>/gi;\n const svgMatches: { fullMatch: string; prompt: string }[] = [];\n let svgM: RegExpExecArray | null;\n while ((svgM = svgRegex.exec(sectionRef.html)) !== null) {\n svgMatches.push({ fullMatch: svgM[0], prompt: svgM[1] });\n }\n if (svgMatches.length === 0) return;\n\n const anthropicKey = anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n imagePromises.push(\n (async () => {\n const results = await Promise.allSettled(\n svgMatches.map(async ({ fullMatch, prompt }) => {\n try {\n const svg = await generateSvg(prompt, anthropicKey);\n return { fullMatch, svg };\n } catch (e) {\n console.warn(`[svg] failed for \"${prompt}\":`, e);\n return { fullMatch, svg: `<div class=\"w-full h-48 bg-gray-100 rounded-lg flex items-center justify-center text-gray-400 text-sm\">${prompt}</div>` };\n }\n })\n );\n let html = sectionRef.html;\n for (const r of results) {\n if (r.status === \"fulfilled\" && r.value) {\n html = html.replace(r.value.fullMatch, r.value.svg);\n }\n }\n if (html !== sectionRef.html) {\n sectionRef.html = html;\n onImageUpdate?.(sectionRef.id, html);\n }\n })()\n );\n }\n\n function enrichSection(sectionRef: Section3) {\n const slots = findImageSlots(sectionRef.html);\n if (slots.length === 0) return;\n const slotsSnapshot = slots.map((s) => ({ ...s }));\n imagePromises.push(\n (async () => {\n const results = await Promise.allSettled(\n slotsSnapshot.map(async (slot) => {\n let url: string | null = null;\n // 1. Pexels first (free, fast)\n if (pexelsApiKey) {\n const img = await searchImage(slot.query, pexelsApiKey).catch(() => null);\n url = img?.url || null;\n }\n // 2. DALL-E fallback\n if (!url && openaiApiKey) {\n try {\n const tempUrl = await generateImage(slot.query, openaiApiKey);\n url = persistImage ? await persistImage(tempUrl, slot.query) : tempUrl;\n } catch (e) {\n console.warn(`[dalle] failed for \"${slot.query}\":`, e);\n }\n }\n url ??= `https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(slot.query.slice(0, 30))}`;\n return { slot, url };\n })\n );\n let html = sectionRef.html;\n for (const r of results) {\n if (r.status === \"fulfilled\" && r.value) {\n const { slot, url } = r.value;\n const replacement = slot.replaceStr.replace(\"{url}\", url);\n html = html.replaceAll(slot.searchStr, replacement);\n }\n }\n if (html !== sectionRef.html) {\n sectionRef.html = html;\n onImageUpdate?.(sectionRef.id, html);\n }\n })()\n );\n }\n\n function processObject(obj: any) {\n if (!obj.html || !obj.label) return;\n const section: Section3 = {\n id: nanoid(8),\n order: sectionOrder++,\n html: sanitizeSemanticColors(addSvgLoadingPlaceholders(addLoadingPlaceholders(obj.html))),\n label: obj.label,\n };\n allSections.push(section);\n onSection?.(section);\n enrichSection(section);\n enrichSvgCharts(section);\n }\n\n try {\n let chunkCount = 0;\n for await (const chunk of result.textStream) {\n buffer += chunk;\n chunkCount++;\n\n const [objects, remaining] = extractJsonObjects(buffer);\n buffer = remaining;\n for (const obj of objects) {\n chunkCount = 0;\n processObject(obj);\n }\n\n if (onRawChunk && chunkCount % 5 === 0 && buffer.length > 20) {\n onRawChunk(buffer, allSections.length);\n }\n }\n\n // Parse remaining buffer\n if (buffer.trim()) {\n let cleaned = buffer.trim();\n if (cleaned.startsWith(\"```\")) {\n cleaned = cleaned.replace(/^```(?:json)?\\s*/, \"\").replace(/\\s*```$/, \"\");\n }\n const [lastObjects] = extractJsonObjects(cleaned);\n for (const obj of lastObjects) processObject(obj);\n }\n\n // Wait for image enrichment\n await Promise.allSettled(imagePromises);\n\n // Final fallback for images without src\n for (const section of allSections) {\n const before = section.html;\n section.html = section.html.replace(\n /<img\\s(?![^>]*\\bsrc=)([^>]*?)>/gi,\n (_match, attrs) => {\n const altMatch = attrs.match(/alt=\"([^\"]*?)\"/);\n const query = altMatch?.[1] || \"image\";\n return `<img src=\"https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(query.slice(0, 30))}\" ${attrs}>`;\n }\n );\n section.html = section.html.replace(\n /data-image-query=\"([^\"]+)\"/g,\n (_match, query) => {\n return `src=\"https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(query.slice(0, 30))}\" data-enriched=\"placeholder\"`;\n }\n );\n if (section.html !== before) {\n onImageUpdate?.(section.id, section.html);\n }\n }\n\n onDone?.(allSections);\n return allSections;\n } catch (err: any) {\n const error = err instanceof Error ? err : new Error(err?.message || \"Generation failed\");\n onError?.(error);\n throw error;\n }\n}\n","/**\n * Replace hardcoded Tailwind color classes with semantic color classes.\n *\n * Two layers:\n * 1. Neutral colors: bg-white → bg-surface, text-black → text-on-surface, bg-gray-* → semantic\n * 2. Chromatic colors: bg-blue-500 → bg-secondary, bg-green-500 → bg-accent, etc.\n *\n * Maps chromatic colors by family:\n * - Blues/indigos/violet → secondary\n * - Greens/teals/emerald/cyan → accent\n * - Everything else → primary\n */\n\nconst COLORS =\n \"red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose\";\n\nconst SECONDARY_COLORS = \"blue|indigo|violet\";\nconst ACCENT_COLORS = \"green|emerald|teal|cyan\";\n\nfunction categorize(color: string): \"primary\" | \"secondary\" | \"accent\" {\n if (new RegExp(`^(?:${SECONDARY_COLORS})$`).test(color)) return \"secondary\";\n if (new RegExp(`^(?:${ACCENT_COLORS})$`).test(color)) return \"accent\";\n return \"primary\";\n}\n\n// ── Neutral replacements (bg-white, text-black, bg-gray-*, text-gray-*, etc.) ──\nconst NEUTRALS = \"slate|gray|zinc|neutral|stone\";\n\nconst neutralReplacements: [RegExp, string][] = [\n // bg-white → bg-surface\n [/\\bbg-white\\b/g, \"bg-surface\"],\n // bg-black → bg-primary-dark\n [/\\bbg-black\\b/g, \"bg-primary-dark\"],\n // text-white → text-on-primary\n [/\\btext-white\\b/g, \"text-on-primary\"],\n // text-black → text-on-surface\n [/\\btext-black\\b/g, \"text-on-surface\"],\n\n // bg-gray-50/100 → bg-surface\n [new RegExp(`\\\\bbg-(${NEUTRALS})-(50|100)\\\\b`, \"g\"), \"bg-surface\"],\n // bg-gray-200/300 → bg-surface-alt\n [new RegExp(`\\\\bbg-(${NEUTRALS})-(200|300)\\\\b`, \"g\"), \"bg-surface-alt\"],\n // bg-gray-400-600 → bg-primary\n [new RegExp(`\\\\bbg-(${NEUTRALS})-(400|500|600)\\\\b`, \"g\"), \"bg-primary\"],\n // bg-gray-700-950 → bg-primary-dark\n [new RegExp(`\\\\bbg-(${NEUTRALS})-(700|800|900|950)\\\\b`, \"g\"), \"bg-primary-dark\"],\n\n // text-gray-300/400 → text-on-surface-muted\n [new RegExp(`\\\\btext-(${NEUTRALS})-(300|400)\\\\b`, \"g\"), \"text-on-surface-muted\"],\n // text-gray-500/600 → text-on-surface-muted\n [new RegExp(`\\\\btext-(${NEUTRALS})-(500|600)\\\\b`, \"g\"), \"text-on-surface-muted\"],\n // text-gray-700/800/900 → text-on-surface\n [new RegExp(`\\\\btext-(${NEUTRALS})-(700|800|900|950)\\\\b`, \"g\"), \"text-on-surface\"],\n // text-gray-50/100/200 → text-on-primary\n [new RegExp(`\\\\btext-(${NEUTRALS})-(50|100|200)\\\\b`, \"g\"), \"text-on-primary\"],\n\n // hover:bg-gray → hover semantic\n [new RegExp(`\\\\bhover:bg-(${NEUTRALS})-(50|100|200|300)\\\\b`, \"g\"), \"hover:bg-surface-alt\"],\n [new RegExp(`\\\\bhover:bg-(${NEUTRALS})-(400|500|600|700|800|900|950)\\\\b`, \"g\"), \"hover:bg-primary-dark\"],\n\n // hover:text neutrals\n [new RegExp(`\\\\bhover:text-(${NEUTRALS})-\\\\d{2,3}\\\\b`, \"g\"), \"hover:text-on-surface\"],\n];\n\n// ── Chromatic replacements ──\nfunction buildChromaticReplacements(): [RegExp, (match: string, color: string) => string][] {\n const re = (prefix: string, shades: string) =>\n new RegExp(`\\\\b${prefix}-(${COLORS})-(${shades})\\\\b`, \"g\");\n\n return [\n // Background\n [re(\"bg\", \"500|600|700\"), (_m, c) => `bg-${categorize(c)}`],\n [re(\"bg\", \"50|100\"), (_m, c) => `bg-${categorize(c)}-light`],\n [re(\"bg\", \"800|900|950\"), (_m, c) => `bg-${categorize(c)}-dark`],\n [re(\"bg\", \"200|300|400\"), (_m, c) => `bg-${categorize(c)}`],\n\n // Text\n [re(\"text\", \"500|600|700\"), (_m, c) => `text-${categorize(c)}`],\n [re(\"text\", \"800|900|950\"), (_m, c) => `text-${categorize(c)}-dark`],\n [re(\"text\", \"50|100|200|300\"), (_m, c) => `text-on-${categorize(c)}`],\n [re(\"text\", \"400\"), (_m, c) => `text-${categorize(c)}`],\n\n // Border\n [re(\"border\", \"\\\\d{2,3}\"), (_m, c) => `border-${categorize(c)}`],\n\n // Ring\n [re(\"ring\", \"\\\\d{2,3}\"), (_m, c) => `ring-${categorize(c)}`],\n\n // Gradients\n [re(\"from\", \"\\\\d{2,3}\"), (_m, c) => `from-${categorize(c)}`],\n [re(\"to\", \"\\\\d{2,3}\"), (_m, c) => `to-${categorize(c)}`],\n [re(\"via\", \"\\\\d{2,3}\"), (_m, c) => `via-${categorize(c)}`],\n\n // Hover/focus variants\n [new RegExp(`\\\\bhover:bg-(${COLORS})-(500|600|700|800|900|950)\\\\b`, \"g\"), (_m, c) => `hover:bg-${categorize(c)}-dark`],\n [new RegExp(`\\\\bhover:bg-(${COLORS})-(50|100|200|300|400)\\\\b`, \"g\"), (_m, c) => `hover:bg-${categorize(c)}-light`],\n [new RegExp(`\\\\bhover:text-(${COLORS})-\\\\d{2,3}\\\\b`, \"g\"), (_m, c) => `hover:text-${categorize(c)}`],\n [new RegExp(`\\\\bfocus:ring-(${COLORS})-\\\\d{2,3}\\\\b`, \"g\"), (_m, c) => `focus:ring-${categorize(c)}`],\n [new RegExp(`\\\\bfocus:border-(${COLORS})-\\\\d{2,3}\\\\b`, \"g\"), (_m, c) => `focus:border-${categorize(c)}`],\n\n // Divide\n [re(\"divide\", \"\\\\d{2,3}\"), (_m, c) => `divide-${categorize(c)}`],\n\n // Placeholder\n [re(\"placeholder\", \"\\\\d{2,3}\"), (_m, c) => `placeholder-${categorize(c)}`],\n\n // Outline\n [re(\"outline\", \"\\\\d{2,3}\"), (_m, c) => `outline-${categorize(c)}`],\n\n // Shadow colored\n [re(\"shadow\", \"\\\\d{2,3}\"), (_m, c) => `shadow-${categorize(c)}`],\n\n // Decoration\n [re(\"decoration\", \"\\\\d{2,3}\"), (_m, c) => `decoration-${categorize(c)}`],\n\n // Accent (form accent color)\n [re(\"accent\", \"\\\\d{2,3}\"), (_m, c) => `accent-${categorize(c)}`],\n ];\n}\n\nconst chromaticReplacements = buildChromaticReplacements();\n\nexport function sanitizeSemanticColors(html: string): string {\n let result = html;\n\n // 1. Replace neutral colors (bg-white, text-black, bg-gray-*, etc.)\n for (const [pattern, replacement] of neutralReplacements) {\n result = result.replace(pattern, replacement);\n }\n\n // 2. Replace chromatic colors (bg-blue-500, text-red-700, etc.)\n for (const [pattern, replacer] of chromaticReplacements) {\n result = result.replace(pattern, replacer as any);\n }\n\n return result;\n}\n"],"mappings":"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","names":["createAnthropic","openaiKey","anthropicKey","createAnthropic"]}
|
|
1
|
+
{"version":3,"sources":["../src/images/pexels.ts","../src/images/dalleImages.ts","../src/images/enrichImages.ts","../src/images/svgGenerator.ts","../src/streamCore.ts","../src/sanitizeColors.ts"],"sourcesContent":["export interface PexelsResult {\n url: string;\n photographer: string;\n alt: string;\n}\n\nexport async function searchImage(query: string, apiKey?: string): Promise<PexelsResult | null> {\n const key = apiKey || process.env.PEXELS_API_KEY;\n if (!key) return null;\n try {\n const res = await fetch(\n `https://api.pexels.com/v1/search?query=${encodeURIComponent(query)}&per_page=5&orientation=landscape&locale=en-US`,\n { headers: { Authorization: key } }\n );\n if (!res.ok) {\n console.warn(`[pexels] ${res.status} for \"${query}\", trying unsplash fallback`);\n return searchUnsplash(query);\n }\n const data = await res.json();\n const photos = data.photos;\n if (!photos || photos.length === 0) {\n console.warn(`[pexels] 0 results for \"${query}\"`);\n return null;\n }\n const photo = photos[Math.floor(Math.random() * photos.length)];\n return {\n url: photo.src.large,\n photographer: photo.photographer,\n alt: photo.alt || query,\n };\n } catch {\n return searchUnsplash(query);\n }\n}\n\nasync function searchUnsplash(query: string): Promise<PexelsResult | null> {\n try {\n const res = await fetch(\n `https://unsplash.com/napi/search/photos?query=${encodeURIComponent(query)}&per_page=5&orientation=landscape`\n );\n if (!res.ok) return null;\n const data = await res.json();\n const results = data.results;\n if (!results || results.length === 0) return null;\n const photo = results[Math.floor(Math.random() * results.length)];\n return {\n url: photo.urls?.regular || photo.urls?.small,\n photographer: photo.user?.name || \"Unsplash\",\n alt: photo.alt_description || query,\n };\n } catch {\n return null;\n }\n}\n","/**\n * Generate an image using DALL-E 3 API.\n */\nexport async function generateImage(\n query: string,\n openaiApiKey: string\n): Promise<string> {\n const res = await fetch(\"https://api.openai.com/v1/images/generations\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${openaiApiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n model: \"dall-e-3\",\n prompt: query,\n n: 1,\n size: \"1792x1024\",\n }),\n });\n\n if (!res.ok) {\n const err = await res.text().catch(() => \"Unknown error\");\n throw new Error(`DALL-E API error ${res.status}: ${err}`);\n }\n\n const data = await res.json();\n return data.data[0].url;\n}\n","import { searchImage } from \"./pexels\";\nimport { generateImage } from \"./dalleImages\";\n\ninterface ImageMatch {\n query: string;\n searchStr: string;\n replaceStr: string;\n}\n\nexport interface EnrichImagesOptions {\n pexelsApiKey?: string;\n openaiApiKey?: string;\n /** Called with temp URL + query, returns permanent URL. Use to persist DALL-E images to S3/etc. */\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n}\n\nconst FAKE_DOMAINS = [\n \"images.unsplash.com\",\n \"unsplash.com\",\n \"via.placeholder.com\",\n \"placeholder.com\",\n \"placehold.co\",\n \"placehold.it\",\n \"placekitten.com\",\n \"picsum.photos\",\n \"loremflickr.com\",\n \"source.unsplash.com\",\n \"dummyimage.com\",\n \"fakeimg.pl\",\n \"example.com\",\n \"img.freepik.com\",\n \"cdn.pixabay.com\",\n];\n\n/**\n * Find all images in HTML that need Pexels enrichment.\n * Two strategies:\n * 1. data-image-query=\"...\" — AI followed instructions\n * 2. <img src=\"fake-url\" — detect fake domains, use alt/class/nearby text as query\n */\nexport function findImageSlots(html: string): ImageMatch[] {\n const matches: ImageMatch[] = [];\n const seen = new Set<string>();\n\n // 1. data-image-query=\"...\" or '...' — match the full <img> tag so we can replace src + data-image-query together\n const diqRegex = /<img\\s[^>]*data-image-query=[\"']([^\"']+)[\"'][^>]*>/gi;\n let m: RegExpExecArray | null;\n while ((m = diqRegex.exec(html)) !== null) {\n const fullTag = m[0];\n const query = m[1];\n if (seen.has(query)) continue;\n seen.add(query);\n // Build replacement tag: replace src (if any) and data-image-query with final src\n const cleanedTag = fullTag\n .replace(/\\ssrc=[\"'][^\"']*[\"']/, \"\")\n .replace(/\\sdata-image-query=[\"'][^\"']*[\"']/, \"\");\n // Insert src and data-enriched right after <img\n const replaceTag = cleanedTag.replace(\n /^<img/,\n `<img src=\"{url}\" data-enriched=\"true\"`\n );\n matches.push({\n query,\n searchStr: fullTag,\n replaceStr: replaceTag,\n });\n }\n\n // 2. <img with fake/non-existent src URLs\n const imgRegex = /<img\\s[^>]*src=\"(https?:\\/\\/[^\"]+)\"[^>]*>/gi;\n while ((m = imgRegex.exec(html)) !== null) {\n const fullTag = m[0];\n const srcUrl = m[1];\n\n if (fullTag.includes(\"data-enriched\")) continue;\n if (srcUrl.includes(\"pexels.com\")) continue;\n if (seen.has(srcUrl)) continue;\n\n // Check if domain is fake\n let isFake = false;\n try {\n const domain = new URL(srcUrl).hostname;\n isFake = FAKE_DOMAINS.some((d) => domain.includes(d));\n } catch {\n isFake = true;\n }\n if (!isFake) continue;\n\n // Extract query: try alt, then class context, then URL path words\n const altMatch = fullTag.match(/alt=\"([^\"]*?)\"/);\n let query = altMatch?.[1]?.trim() || \"\";\n\n if (!query) {\n // Try to extract meaningful words from the URL path\n try {\n const path = new URL(srcUrl).pathname;\n const words = path\n .replace(/[^a-zA-Z]/g, \" \")\n .split(/\\s+/)\n .filter((w) => w.length > 2)\n .slice(0, 4)\n .join(\" \");\n if (words.length > 3) query = words;\n } catch { /* ignore */ }\n }\n\n if (!query) query = \"professional website hero image\";\n\n seen.add(srcUrl);\n matches.push({\n query,\n searchStr: `src=\"${srcUrl}\"`,\n replaceStr: `src=\"{url}\" data-enriched=\"true\"`,\n });\n }\n\n return matches;\n}\n\n/**\n * Enrich all images in an HTML string.\n * Strategy: Pexels (free) → DALL-E fallback (if openaiApiKey) → placeholder.\n * All images resolved in parallel. If persistImage callback provided, temp DALL-E URLs are persisted.\n */\nexport async function enrichImages(html: string, pexelsApiKeyOrOpts?: string | EnrichImagesOptions, openaiApiKey?: string): Promise<string> {\n // Support both legacy (string, string) and new (options object) signatures\n let opts: EnrichImagesOptions;\n if (typeof pexelsApiKeyOrOpts === \"object\" && pexelsApiKeyOrOpts !== null) {\n opts = pexelsApiKeyOrOpts;\n } else {\n opts = { pexelsApiKey: pexelsApiKeyOrOpts, openaiApiKey };\n }\n\n const slots = findImageSlots(html);\n if (slots.length === 0) return html;\n\n // Resolve all images in parallel\n const resolved = await Promise.allSettled(\n slots.map(async (slot) => {\n let url: string | null = null;\n\n // 1. Pexels first (free)\n if (opts.pexelsApiKey) {\n const img = await searchImage(slot.query, opts.pexelsApiKey).catch(() => null);\n url = img?.url || null;\n }\n\n // 2. DALL-E fallback if Pexels found nothing\n if (!url && opts.openaiApiKey) {\n try {\n const tempUrl = await generateImage(slot.query, opts.openaiApiKey);\n url = opts.persistImage\n ? await opts.persistImage(tempUrl, slot.query)\n : tempUrl;\n } catch (e) {\n console.warn(`[dalle] failed for \"${slot.query}\":`, e);\n }\n }\n\n // 3. Placeholder fallback\n url ??= `https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(slot.query.slice(0, 30))}`;\n\n return { slot, url };\n })\n );\n\n let result = html;\n for (const r of resolved) {\n if (r.status === \"fulfilled\" && r.value) {\n const { slot, url } = r.value;\n const replacement = slot.replaceStr.replace(\"{url}\", url);\n result = result.replaceAll(slot.searchStr, replacement);\n }\n }\n\n // Catch any remaining <img> tags without src\n result = result.replace(/<img\\s(?![^>]*\\bsrc=)([^>]*?)>/gi, (_match, attrs) => {\n const altMatch = attrs.match(/alt=\"([^\"]*?)\"/);\n const query = altMatch?.[1] || \"professional image\";\n return `<img src=\"https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(query.slice(0, 30))}\" ${attrs}>`;\n });\n\n return result;\n}\n","import { createAnthropic } from \"@ai-sdk/anthropic\";\nimport { generateText } from \"ai\";\nimport { currentDateLine } from \"../streamCore\";\n\nconst SVG_SYSTEM_PROMPT = `You are a professional SVG designer. Generate clean, compact SVG graphics for documents.\n\nSTRICT SIZE RULES:\n- ALWAYS use viewBox=\"0 0 600 300\" (2:1 ratio) — no exceptions\n- ALWAYS set width=\"100%\" height=\"auto\" — NEVER use fixed pixel width/height\n- NO internal padding or margins — content fills the viewBox edge-to-edge (leave only 10-20px padding)\n- Keep SVGs under 2KB — simplicity is key\n\nSTYLE RULES:\n- Output ONLY the <svg>...</svg> tag — no markdown, no explanation\n- Flat design: solid fills, no drop shadows, minimal gradients (max 1-2)\n- Max 8-10 elements total — prefer fewer, larger shapes over many small ones\n- Color palette: use the provided theme colors, or defaults (#6366f1, #8b5cf6, #ec4899, #14b8a6, #f59e0b)\n- Text: font-family=\"system-ui, sans-serif\", font-size 12-16px, max 5 text labels\n- Self-contained: no external references, all styles inline\n\nCHART TYPES:\n- Bar charts (vertical/horizontal) — max 6 bars, rounded caps\n- Pie/donut charts — max 5 segments\n- Line charts — smooth paths, max 8 data points\n- Progress/gauge charts\n- Simple comparison charts\n- Stat cards with visual elements\n\nAVOID: complex illustrations, many small elements, decorative borders, nested groups deeper than 2 levels.`;\n\n\nexport async function generateSvg(\n prompt: string,\n anthropicApiKey?: string,\n options?: { width?: number; height?: number; themeColors?: string }\n): Promise<string> {\n const apiKey = anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n const anthropic = createAnthropic({ apiKey: apiKey || undefined });\n\n const sizeHint = options?.width && options?.height\n ? ` Target dimensions: ${options.width}x${options.height}px.`\n : \"\";\n const colorHint = options?.themeColors\n ? ` Use these theme colors: ${options.themeColors}.`\n : \"\";\n\n const result = await generateText({\n model: anthropic(\"claude-haiku-4-5-20251001\"),\n system: SVG_SYSTEM_PROMPT + currentDateLine(),\n messages: [\n {\n role: \"user\",\n content: `Generate an SVG for: ${prompt}${sizeHint}${colorHint}`,\n },\n ],\n maxOutputTokens: 2000,\n });\n\n // Extract just the SVG tag\n const svgMatch = result.text.match(/<svg[\\s\\S]*<\\/svg>/i);\n if (!svgMatch) {\n throw new Error(\"SVG generation failed — no <svg> tag in response\");\n }\n\n return svgMatch[0];\n}\n","import { streamText } from \"ai\";\nimport { createAnthropic } from \"@ai-sdk/anthropic\";\nimport { nanoid } from \"nanoid\";\nimport { findImageSlots } from \"./images/enrichImages\";\nimport { searchImage } from \"./images/pexels\";\nimport { generateImage } from \"./images/dalleImages\";\nimport { generateSvg } from \"./images/svgGenerator\";\nimport type { Section3 } from \"./types\";\nimport { sanitizeSemanticColors } from \"./sanitizeColors\";\n\nexport function currentDateLine(): string {\n return `\\nToday's date is ${new Date().toISOString().split(\"T\")[0]}. Use this for any date references.\\n`;\n}\n\n/**\n * Resolve AI model from available keys.\n * If modelId is already a LanguageModel object, return it directly.\n * Prefers Anthropic, falls back to OpenAI.\n */\nfunction isOpenAiModel(id: string): boolean {\n return /^(gpt-|o[1-9]|dall-e|tts-|whisper|chatgpt-)/.test(id);\n}\n\nfunction isLanguageModel(value: unknown): value is import(\"ai\").LanguageModel {\n return typeof value === \"object\" && value !== null && \"modelId\" in value && \"provider\" in value;\n}\n\nexport async function resolveModel(opts: {\n openaiApiKey?: string;\n anthropicApiKey?: string;\n modelId?: string | import(\"ai\").LanguageModel;\n defaultOpenai: string;\n defaultAnthropic: string;\n}) {\n // If modelId is already a model object, return it directly\n if (opts.modelId && isLanguageModel(opts.modelId)) {\n return opts.modelId;\n }\n\n const modelId = opts.modelId as string | undefined;\n\n if (modelId && isOpenAiModel(modelId)) {\n const openaiKey = opts.openaiApiKey || process.env.OPENAI_API_KEY;\n if (openaiKey) {\n const { createOpenAI } = await import(\"@ai-sdk/openai\");\n return createOpenAI({ apiKey: openaiKey })(modelId);\n }\n // OpenAI model requested but no key — fall through to Anthropic default\n } else if (modelId) {\n const anthropicKey = opts.anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n if (anthropicKey) {\n return createAnthropic({ apiKey: anthropicKey })(modelId);\n }\n }\n // No explicit modelId — prefer Anthropic, fallback to OpenAI\n const anthropicKey = opts.anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n if (anthropicKey) {\n return createAnthropic({ apiKey: anthropicKey })(opts.defaultAnthropic);\n }\n const openaiKey = opts.openaiApiKey || process.env.OPENAI_API_KEY;\n if (openaiKey) {\n const { createOpenAI } = await import(\"@ai-sdk/openai\");\n return createOpenAI({ apiKey: openaiKey })(opts.defaultOpenai);\n }\n return createAnthropic()(opts.defaultAnthropic);\n}\n\n/**\n * Convert data URL to Uint8Array for AI SDK vision.\n */\nexport function dataUrlToImagePart(dataUrl: string): { image: Uint8Array; mimeType: string } | null {\n const match = dataUrl.match(/^data:([^;]+);base64,(.+)$/);\n if (!match) return null;\n return {\n image: new Uint8Array(Buffer.from(match[2], \"base64\")),\n mimeType: match[1],\n };\n}\n\n/**\n * Extract complete JSON objects from accumulated text using brace-depth tracking.\n */\nexport function extractJsonObjects(text: string): [any[], string] {\n const objects: any[] = [];\n let remaining = text;\n\n while (remaining.length > 0) {\n remaining = remaining.trimStart();\n if (!remaining.startsWith(\"{\")) {\n const nextBrace = remaining.indexOf(\"{\");\n if (nextBrace === -1) break;\n remaining = remaining.slice(nextBrace);\n continue;\n }\n\n let depth = 0;\n let inString = false;\n let escape = false;\n let end = -1;\n\n for (let i = 0; i < remaining.length; i++) {\n const ch = remaining[i];\n if (escape) { escape = false; continue; }\n if (ch === \"\\\\\") { escape = true; continue; }\n if (ch === '\"') { inString = !inString; continue; }\n if (inString) continue;\n if (ch === \"{\") depth++;\n if (ch === \"}\") { depth--; if (depth === 0) { end = i; break; } }\n }\n\n if (end === -1) break;\n\n const candidate = remaining.slice(0, end + 1);\n remaining = remaining.slice(end + 1);\n\n try {\n objects.push(JSON.parse(candidate));\n } catch {\n // malformed, skip\n }\n }\n\n return [objects, remaining];\n}\n\n/** Inline shimmer SVG used as src for loading image placeholders */\nconst LOADING_PLACEHOLDER_SRC = `data:image/svg+xml,${encodeURIComponent('<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"800\" height=\"500\" viewBox=\"0 0 800 500\"><rect fill=\"#f3f4f6\" width=\"800\" height=\"500\" rx=\"12\"/><g opacity=\".4\"><rect x=\"320\" y=\"200\" width=\"160\" height=\"4\" rx=\"2\" fill=\"#d1d5db\"><animate attributeName=\"opacity\" values=\".3;.8;.3\" dur=\"1.5s\" repeatCount=\"indefinite\"/></rect><rect x=\"280\" y=\"215\" width=\"240\" height=\"4\" rx=\"2\" fill=\"#d1d5db\"><animate attributeName=\"opacity\" values=\".3;.8;.3\" dur=\"1.5s\" begin=\".3s\" repeatCount=\"indefinite\"/></rect><rect x=\"340\" y=\"230\" width=\"120\" height=\"4\" rx=\"2\" fill=\"#d1d5db\"><animate attributeName=\"opacity\" values=\".3;.8;.3\" dur=\"1.5s\" begin=\".6s\" repeatCount=\"indefinite\"/></rect></g><g transform=\"translate(376,150)\" opacity=\".3\"><path d=\"M0 28V4a4 4 0 014-4h40a4 4 0 014 4v24a4 4 0 01-4 4H4a4 4 0 01-4-4z\" fill=\"#d1d5db\"/><circle cx=\"14\" cy=\"12\" r=\"4\" fill=\"#9ca3af\"/><path d=\"M4 28l10-10 6 6 8-8 16 16H4z\" fill=\"#9ca3af\" opacity=\".5\"/></g></svg>')}`;\n\n/** Inline SVG placeholder for loading charts */\nconst SVG_LOADING_PLACEHOLDER = `<div class=\"w-full h-48 bg-gray-50 rounded-lg flex items-center justify-center animate-pulse\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"48\" height=\"48\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#9ca3af\" stroke-width=\"1.5\"><rect x=\"3\" y=\"12\" width=\"4\" height=\"9\" rx=\"1\"/><rect x=\"10\" y=\"7\" width=\"4\" height=\"14\" rx=\"1\"/><rect x=\"17\" y=\"3\" width=\"4\" height=\"18\" rx=\"1\"/></svg></div>`;\n\n/** Replace data-svg-chart divs with loading placeholders */\nexport function addSvgLoadingPlaceholders(html: string): string {\n return html.replace(\n /<div\\s([^>]*?)data-svg-chart=\"([^\"]+)\"([^>]*?)>[\\s\\S]*?<\\/div>/gi,\n (_match, before, chart, after) => {\n return `<div ${before}data-svg-chart=\"${chart}\"${after}>${SVG_LOADING_PLACEHOLDER}</div>`;\n }\n );\n}\n\n/** Replace data-image-query attrs with animated loading placeholders */\nexport function addLoadingPlaceholders(html: string): string {\n return html.replace(\n /(<img\\s[^>]*)data-image-query=\"([^\"]+)\"([^>]*?)(?:\\s*\\/?>)/gi,\n (_match, before, query, after) => {\n if (before.includes('src=') || after.includes('src=')) return _match;\n return `${before}src=\"${LOADING_PLACEHOLDER_SRC}\" data-image-query=\"${query}\" alt=\"${query}\"${after}>`;\n }\n );\n}\n\n/** Enrich a section's images (Pexels → DALL-E → placeholder fallback). Mutates section.html in place. */\nexport async function enrichSectionImages(\n section: Section3,\n opts: {\n pexelsApiKey?: string;\n openaiApiKey?: string;\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n onImageUpdate?: (sectionId: string, html: string) => void;\n }\n): Promise<void> {\n const slots = findImageSlots(section.html);\n if (slots.length === 0) return;\n const results = await Promise.allSettled(\n slots.map(async (slot) => {\n let url: string | null = null;\n if (opts.pexelsApiKey) {\n const img = await searchImage(slot.query, opts.pexelsApiKey).catch(() => null);\n url = img?.url || null;\n }\n if (!url && opts.openaiApiKey) {\n try {\n const tempUrl = await generateImage(slot.query, opts.openaiApiKey);\n url = opts.persistImage ? await opts.persistImage(tempUrl, slot.query) : tempUrl;\n } catch (e) {\n console.warn(`[dalle] failed for \"${slot.query}\":`, e);\n }\n }\n url ??= `https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(slot.query.slice(0, 30))}`;\n return { slot, url };\n })\n );\n let html = section.html;\n for (const r of results) {\n if (r.status === \"fulfilled\" && r.value) {\n const { slot, url } = r.value;\n const replacement = slot.replaceStr.replace(\"{url}\", url);\n html = html.replaceAll(slot.searchStr, replacement);\n }\n }\n if (html !== section.html) {\n section.html = html;\n opts.onImageUpdate?.(section.id, html);\n }\n}\n\n/** Enrich a section's SVG chart placeholders. Mutates section.html in place. */\nexport async function enrichSectionSvgCharts(\n section: Section3,\n opts: {\n anthropicApiKey?: string;\n onImageUpdate?: (sectionId: string, html: string) => void;\n }\n): Promise<void> {\n const svgRegex = /<div\\s[^>]*data-svg-chart=\"([^\"]+)\"[^>]*>[\\s\\S]*?<\\/div>/gi;\n const svgMatches: { fullMatch: string; prompt: string }[] = [];\n let svgM: RegExpExecArray | null;\n while ((svgM = svgRegex.exec(section.html)) !== null) {\n svgMatches.push({ fullMatch: svgM[0], prompt: svgM[1] });\n }\n if (svgMatches.length === 0) return;\n const anthropicKey = opts.anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n const results = await Promise.allSettled(\n svgMatches.map(async ({ fullMatch, prompt }) => {\n try {\n const svg = await generateSvg(prompt, anthropicKey);\n return { fullMatch, svg };\n } catch (e) {\n console.warn(`[svg] failed for \"${prompt}\":`, e);\n return { fullMatch, svg: `<div class=\"w-full h-48 bg-gray-100 rounded-lg flex items-center justify-center text-gray-400 text-sm\">${prompt}</div>` };\n }\n })\n );\n let html = section.html;\n for (const r of results) {\n if (r.status === \"fulfilled\" && r.value) {\n html = html.replace(r.value.fullMatch, r.value.svg);\n }\n }\n if (html !== section.html) {\n section.html = html;\n opts.onImageUpdate?.(section.id, html);\n }\n}\n\nexport interface StreamGenerateOptions {\n /** Anthropic API key */\n anthropicApiKey?: string;\n /** OpenAI API key */\n openaiApiKey?: string;\n /** Model ID override or pre-built LanguageModel object */\n model?: string | import(\"ai\").LanguageModel;\n /** System prompt */\n systemPrompt: string;\n /** User message content (text or multimodal parts) */\n userContent: any[];\n /** Pexels API key for image enrichment */\n pexelsApiKey?: string;\n /** Persist DALL-E images to permanent storage */\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n /** Called when a new section is parsed */\n onSection?: (section: Section3) => void;\n /** Called when a section's images are enriched */\n onImageUpdate?: (sectionId: string, html: string) => void;\n /** Called with raw text buffer for real-time partial streaming */\n onRawChunk?: (buffer: string, completedCount: number) => void;\n /** Called when generation is complete */\n onDone?: (sections: Section3[]) => void;\n /** Called on error */\n onError?: (error: Error) => void;\n}\n\n/**\n * Core streaming generation: stream AI text → parse NDJSON → emit sections → enrich images.\n * Used by both generateLanding and generateDocument.\n */\nexport async function streamGenerate(options: StreamGenerateOptions): Promise<Section3[]> {\n const {\n anthropicApiKey,\n openaiApiKey: _openaiApiKey,\n model: modelId,\n systemPrompt,\n userContent,\n pexelsApiKey,\n persistImage,\n onSection,\n onImageUpdate,\n onRawChunk,\n onDone,\n onError,\n } = options;\n\n const openaiApiKey = _openaiApiKey || process.env.OPENAI_API_KEY;\n const model = await resolveModel({\n openaiApiKey,\n anthropicApiKey,\n modelId,\n defaultOpenai: \"gpt-4o\",\n defaultAnthropic: \"claude-sonnet-4-6\",\n });\n\n const result = streamText({\n model,\n system: systemPrompt + currentDateLine(),\n messages: [{ role: \"user\", content: userContent }],\n });\n\n const allSections: Section3[] = [];\n const imagePromises: Promise<void>[] = [];\n let sectionOrder = 0;\n let buffer = \"\";\n\n function enrichSvgCharts(sectionRef: Section3) {\n const svgRegex = /<div\\s[^>]*data-svg-chart=\"([^\"]+)\"[^>]*>[\\s\\S]*?<\\/div>/gi;\n const svgMatches: { fullMatch: string; prompt: string }[] = [];\n let svgM: RegExpExecArray | null;\n while ((svgM = svgRegex.exec(sectionRef.html)) !== null) {\n svgMatches.push({ fullMatch: svgM[0], prompt: svgM[1] });\n }\n if (svgMatches.length === 0) return;\n\n const anthropicKey = anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n imagePromises.push(\n (async () => {\n const results = await Promise.allSettled(\n svgMatches.map(async ({ fullMatch, prompt }) => {\n try {\n const svg = await generateSvg(prompt, anthropicKey);\n return { fullMatch, svg };\n } catch (e) {\n console.warn(`[svg] failed for \"${prompt}\":`, e);\n return { fullMatch, svg: `<div class=\"w-full h-48 bg-gray-100 rounded-lg flex items-center justify-center text-gray-400 text-sm\">${prompt}</div>` };\n }\n })\n );\n let html = sectionRef.html;\n for (const r of results) {\n if (r.status === \"fulfilled\" && r.value) {\n html = html.replace(r.value.fullMatch, r.value.svg);\n }\n }\n if (html !== sectionRef.html) {\n sectionRef.html = html;\n onImageUpdate?.(sectionRef.id, html);\n }\n })()\n );\n }\n\n function enrichSection(sectionRef: Section3) {\n const slots = findImageSlots(sectionRef.html);\n if (slots.length === 0) return;\n const slotsSnapshot = slots.map((s) => ({ ...s }));\n imagePromises.push(\n (async () => {\n const results = await Promise.allSettled(\n slotsSnapshot.map(async (slot) => {\n let url: string | null = null;\n // 1. Pexels first (free, fast)\n if (pexelsApiKey) {\n const img = await searchImage(slot.query, pexelsApiKey).catch(() => null);\n url = img?.url || null;\n }\n // 2. DALL-E fallback\n if (!url && openaiApiKey) {\n try {\n const tempUrl = await generateImage(slot.query, openaiApiKey);\n url = persistImage ? await persistImage(tempUrl, slot.query) : tempUrl;\n } catch (e) {\n console.warn(`[dalle] failed for \"${slot.query}\":`, e);\n }\n }\n url ??= `https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(slot.query.slice(0, 30))}`;\n return { slot, url };\n })\n );\n let html = sectionRef.html;\n for (const r of results) {\n if (r.status === \"fulfilled\" && r.value) {\n const { slot, url } = r.value;\n const replacement = slot.replaceStr.replace(\"{url}\", url);\n html = html.replaceAll(slot.searchStr, replacement);\n }\n }\n if (html !== sectionRef.html) {\n sectionRef.html = html;\n onImageUpdate?.(sectionRef.id, html);\n }\n })()\n );\n }\n\n function processObject(obj: any) {\n if (!obj.html || !obj.label) return;\n const section: Section3 = {\n id: nanoid(8),\n order: sectionOrder++,\n html: sanitizeSemanticColors(addSvgLoadingPlaceholders(addLoadingPlaceholders(obj.html))),\n label: obj.label,\n };\n allSections.push(section);\n onSection?.(section);\n enrichSection(section);\n enrichSvgCharts(section);\n }\n\n try {\n let chunkCount = 0;\n for await (const chunk of result.textStream) {\n buffer += chunk;\n chunkCount++;\n\n const [objects, remaining] = extractJsonObjects(buffer);\n buffer = remaining;\n for (const obj of objects) {\n chunkCount = 0;\n processObject(obj);\n }\n\n if (onRawChunk && chunkCount % 5 === 0 && buffer.length > 20) {\n onRawChunk(buffer, allSections.length);\n }\n }\n\n // Parse remaining buffer\n if (buffer.trim()) {\n let cleaned = buffer.trim();\n if (cleaned.startsWith(\"```\")) {\n cleaned = cleaned.replace(/^```(?:json)?\\s*/, \"\").replace(/\\s*```$/, \"\");\n }\n const [lastObjects] = extractJsonObjects(cleaned);\n for (const obj of lastObjects) processObject(obj);\n }\n\n // Wait for image enrichment\n await Promise.allSettled(imagePromises);\n\n // Final fallback for images without src\n for (const section of allSections) {\n const before = section.html;\n section.html = section.html.replace(\n /<img\\s(?![^>]*\\bsrc=)([^>]*?)>/gi,\n (_match, attrs) => {\n const altMatch = attrs.match(/alt=\"([^\"]*?)\"/);\n const query = altMatch?.[1] || \"image\";\n return `<img src=\"https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(query.slice(0, 30))}\" ${attrs}>`;\n }\n );\n section.html = section.html.replace(\n /data-image-query=\"([^\"]+)\"/g,\n (_match, query) => {\n return `src=\"https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(query.slice(0, 30))}\" data-enriched=\"placeholder\"`;\n }\n );\n if (section.html !== before) {\n onImageUpdate?.(section.id, section.html);\n }\n }\n\n onDone?.(allSections);\n return allSections;\n } catch (err: any) {\n const error = err instanceof Error ? err : new Error(err?.message || \"Generation failed\");\n onError?.(error);\n throw error;\n }\n}\n","/**\n * Replace hardcoded Tailwind color classes with semantic color classes.\n *\n * Two layers:\n * 1. Neutral colors: bg-white → bg-surface, text-black → text-on-surface, bg-gray-* → semantic\n * 2. Chromatic colors: bg-blue-500 → bg-secondary, bg-green-500 → bg-accent, etc.\n *\n * Maps chromatic colors by family:\n * - Blues/indigos/violet → secondary\n * - Greens/teals/emerald/cyan → accent\n * - Everything else → primary\n */\n\nconst COLORS =\n \"red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose\";\n\nconst SECONDARY_COLORS = \"blue|indigo|violet\";\nconst ACCENT_COLORS = \"green|emerald|teal|cyan\";\n\nfunction categorize(color: string): \"primary\" | \"secondary\" | \"accent\" {\n if (new RegExp(`^(?:${SECONDARY_COLORS})$`).test(color)) return \"secondary\";\n if (new RegExp(`^(?:${ACCENT_COLORS})$`).test(color)) return \"accent\";\n return \"primary\";\n}\n\n// ── Neutral replacements (bg-white, text-black, bg-gray-*, text-gray-*, etc.) ──\nconst NEUTRALS = \"slate|gray|zinc|neutral|stone\";\n\nconst neutralReplacements: [RegExp, string][] = [\n // bg-white → bg-surface\n [/\\bbg-white\\b/g, \"bg-surface\"],\n // bg-black → bg-primary-dark\n [/\\bbg-black\\b/g, \"bg-primary-dark\"],\n // text-white → text-on-primary\n [/\\btext-white\\b/g, \"text-on-primary\"],\n // text-black → text-on-surface\n [/\\btext-black\\b/g, \"text-on-surface\"],\n\n // bg-gray-50/100 → bg-surface\n [new RegExp(`\\\\bbg-(${NEUTRALS})-(50|100)\\\\b`, \"g\"), \"bg-surface\"],\n // bg-gray-200/300 → bg-surface-alt\n [new RegExp(`\\\\bbg-(${NEUTRALS})-(200|300)\\\\b`, \"g\"), \"bg-surface-alt\"],\n // bg-gray-400-600 → bg-primary\n [new RegExp(`\\\\bbg-(${NEUTRALS})-(400|500|600)\\\\b`, \"g\"), \"bg-primary\"],\n // bg-gray-700-950 → bg-primary-dark\n [new RegExp(`\\\\bbg-(${NEUTRALS})-(700|800|900|950)\\\\b`, \"g\"), \"bg-primary-dark\"],\n\n // text-gray-300/400 → text-on-surface-muted\n [new RegExp(`\\\\btext-(${NEUTRALS})-(300|400)\\\\b`, \"g\"), \"text-on-surface-muted\"],\n // text-gray-500/600 → text-on-surface-muted\n [new RegExp(`\\\\btext-(${NEUTRALS})-(500|600)\\\\b`, \"g\"), \"text-on-surface-muted\"],\n // text-gray-700/800/900 → text-on-surface\n [new RegExp(`\\\\btext-(${NEUTRALS})-(700|800|900|950)\\\\b`, \"g\"), \"text-on-surface\"],\n // text-gray-50/100/200 → text-on-primary\n [new RegExp(`\\\\btext-(${NEUTRALS})-(50|100|200)\\\\b`, \"g\"), \"text-on-primary\"],\n\n // hover:bg-gray → hover semantic\n [new RegExp(`\\\\bhover:bg-(${NEUTRALS})-(50|100|200|300)\\\\b`, \"g\"), \"hover:bg-surface-alt\"],\n [new RegExp(`\\\\bhover:bg-(${NEUTRALS})-(400|500|600|700|800|900|950)\\\\b`, \"g\"), \"hover:bg-primary-dark\"],\n\n // hover:text neutrals\n [new RegExp(`\\\\bhover:text-(${NEUTRALS})-\\\\d{2,3}\\\\b`, \"g\"), \"hover:text-on-surface\"],\n];\n\n// ── Chromatic replacements ──\nfunction buildChromaticReplacements(): [RegExp, (match: string, color: string) => string][] {\n const re = (prefix: string, shades: string) =>\n new RegExp(`\\\\b${prefix}-(${COLORS})-(${shades})\\\\b`, \"g\");\n\n return [\n // Background\n [re(\"bg\", \"500|600|700\"), (_m, c) => `bg-${categorize(c)}`],\n [re(\"bg\", \"50|100\"), (_m, c) => `bg-${categorize(c)}-light`],\n [re(\"bg\", \"800|900|950\"), (_m, c) => `bg-${categorize(c)}-dark`],\n [re(\"bg\", \"200|300|400\"), (_m, c) => `bg-${categorize(c)}`],\n\n // Text\n [re(\"text\", \"500|600|700\"), (_m, c) => `text-${categorize(c)}`],\n [re(\"text\", \"800|900|950\"), (_m, c) => `text-${categorize(c)}-dark`],\n [re(\"text\", \"50|100|200|300\"), (_m, c) => `text-on-${categorize(c)}`],\n [re(\"text\", \"400\"), (_m, c) => `text-${categorize(c)}`],\n\n // Border\n [re(\"border\", \"\\\\d{2,3}\"), (_m, c) => `border-${categorize(c)}`],\n\n // Ring\n [re(\"ring\", \"\\\\d{2,3}\"), (_m, c) => `ring-${categorize(c)}`],\n\n // Gradients\n [re(\"from\", \"\\\\d{2,3}\"), (_m, c) => `from-${categorize(c)}`],\n [re(\"to\", \"\\\\d{2,3}\"), (_m, c) => `to-${categorize(c)}`],\n [re(\"via\", \"\\\\d{2,3}\"), (_m, c) => `via-${categorize(c)}`],\n\n // Hover/focus variants\n [new RegExp(`\\\\bhover:bg-(${COLORS})-(500|600|700|800|900|950)\\\\b`, \"g\"), (_m, c) => `hover:bg-${categorize(c)}-dark`],\n [new RegExp(`\\\\bhover:bg-(${COLORS})-(50|100|200|300|400)\\\\b`, \"g\"), (_m, c) => `hover:bg-${categorize(c)}-light`],\n [new RegExp(`\\\\bhover:text-(${COLORS})-\\\\d{2,3}\\\\b`, \"g\"), (_m, c) => `hover:text-${categorize(c)}`],\n [new RegExp(`\\\\bfocus:ring-(${COLORS})-\\\\d{2,3}\\\\b`, \"g\"), (_m, c) => `focus:ring-${categorize(c)}`],\n [new RegExp(`\\\\bfocus:border-(${COLORS})-\\\\d{2,3}\\\\b`, \"g\"), (_m, c) => `focus:border-${categorize(c)}`],\n\n // Divide\n [re(\"divide\", \"\\\\d{2,3}\"), (_m, c) => `divide-${categorize(c)}`],\n\n // Placeholder\n [re(\"placeholder\", \"\\\\d{2,3}\"), (_m, c) => `placeholder-${categorize(c)}`],\n\n // Outline\n [re(\"outline\", \"\\\\d{2,3}\"), (_m, c) => `outline-${categorize(c)}`],\n\n // Shadow colored\n [re(\"shadow\", \"\\\\d{2,3}\"), (_m, c) => `shadow-${categorize(c)}`],\n\n // Decoration\n [re(\"decoration\", \"\\\\d{2,3}\"), (_m, c) => `decoration-${categorize(c)}`],\n\n // Accent (form accent color)\n [re(\"accent\", \"\\\\d{2,3}\"), (_m, c) => `accent-${categorize(c)}`],\n ];\n}\n\nconst chromaticReplacements = buildChromaticReplacements();\n\nexport function sanitizeSemanticColors(html: string): string {\n let result = html;\n\n // 1. Replace neutral colors (bg-white, text-black, bg-gray-*, etc.)\n for (const [pattern, replacement] of neutralReplacements) {\n result = result.replace(pattern, replacement);\n }\n\n // 2. Skip chromatic sanitization if the AI already used semantic classes.\n // If bg-primary/bg-secondary/bg-accent/bg-surface appear, the AI followed\n // instructions and we should NOT rewrite its color choices.\n const hasSemanticClasses = /\\b(?:bg-primary|bg-secondary|bg-accent|bg-surface)\\b/.test(result);\n if (!hasSemanticClasses) {\n // AI ignored semantic instructions — apply chromatic replacements as safety net\n for (const [pattern, replacer] of chromaticReplacements) {\n result = result.replace(pattern, replacer as any);\n }\n }\n\n return result;\n}\n"],"mappings":";AAMA,eAAsB,YAAY,OAAe,QAA+C;AAC9F,QAAM,MAAM,UAAU,QAAQ,IAAI;AAClC,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI;AACF,UAAM,MAAM,MAAM;AAAA,MAChB,0CAA0C,mBAAmB,KAAK,CAAC;AAAA,MACnE,EAAE,SAAS,EAAE,eAAe,IAAI,EAAE;AAAA,IACpC;AACA,QAAI,CAAC,IAAI,IAAI;AACX,cAAQ,KAAK,YAAY,IAAI,MAAM,SAAS,KAAK,6BAA6B;AAC9E,aAAO,eAAe,KAAK;AAAA,IAC7B;AACA,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC,UAAU,OAAO,WAAW,GAAG;AAClC,cAAQ,KAAK,2BAA2B,KAAK,GAAG;AAChD,aAAO;AAAA,IACT;AACA,UAAM,QAAQ,OAAO,KAAK,MAAM,KAAK,OAAO,IAAI,OAAO,MAAM,CAAC;AAC9D,WAAO;AAAA,MACL,KAAK,MAAM,IAAI;AAAA,MACf,cAAc,MAAM;AAAA,MACpB,KAAK,MAAM,OAAO;AAAA,IACpB;AAAA,EACF,QAAQ;AACN,WAAO,eAAe,KAAK;AAAA,EAC7B;AACF;AAEA,eAAe,eAAe,OAA6C;AACzE,MAAI;AACF,UAAM,MAAM,MAAM;AAAA,MAChB,iDAAiD,mBAAmB,KAAK,CAAC;AAAA,IAC5E;AACA,QAAI,CAAC,IAAI,GAAI,QAAO;AACpB,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAM,UAAU,KAAK;AACrB,QAAI,CAAC,WAAW,QAAQ,WAAW,EAAG,QAAO;AAC7C,UAAM,QAAQ,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,QAAQ,MAAM,CAAC;AAChE,WAAO;AAAA,MACL,KAAK,MAAM,MAAM,WAAW,MAAM,MAAM;AAAA,MACxC,cAAc,MAAM,MAAM,QAAQ;AAAA,MAClC,KAAK,MAAM,mBAAmB;AAAA,IAChC;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AClDA,eAAsB,cACpB,OACA,cACiB;AACjB,QAAM,MAAM,MAAM,MAAM,gDAAgD;AAAA,IACtE,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,eAAe,UAAU,YAAY;AAAA,MACrC,gBAAgB;AAAA,IAClB;AAAA,IACA,MAAM,KAAK,UAAU;AAAA,MACnB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,GAAG;AAAA,MACH,MAAM;AAAA,IACR,CAAC;AAAA,EACH,CAAC;AAED,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,MAAM,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,eAAe;AACxD,UAAM,IAAI,MAAM,oBAAoB,IAAI,MAAM,KAAK,GAAG,EAAE;AAAA,EAC1D;AAEA,QAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,SAAO,KAAK,KAAK,CAAC,EAAE;AACtB;;;ACZA,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,SAAS,eAAe,MAA4B;AACzD,QAAM,UAAwB,CAAC;AAC/B,QAAM,OAAO,oBAAI,IAAY;AAG7B,QAAM,WAAW;AACjB,MAAI;AACJ,UAAQ,IAAI,SAAS,KAAK,IAAI,OAAO,MAAM;AACzC,UAAM,UAAU,EAAE,CAAC;AACnB,UAAM,QAAQ,EAAE,CAAC;AACjB,QAAI,KAAK,IAAI,KAAK,EAAG;AACrB,SAAK,IAAI,KAAK;AAEd,UAAM,aAAa,QAChB,QAAQ,wBAAwB,EAAE,EAClC,QAAQ,qCAAqC,EAAE;AAElD,UAAM,aAAa,WAAW;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AACA,YAAQ,KAAK;AAAA,MACX;AAAA,MACA,WAAW;AAAA,MACX,YAAY;AAAA,IACd,CAAC;AAAA,EACH;AAGA,QAAM,WAAW;AACjB,UAAQ,IAAI,SAAS,KAAK,IAAI,OAAO,MAAM;AACzC,UAAM,UAAU,EAAE,CAAC;AACnB,UAAM,SAAS,EAAE,CAAC;AAElB,QAAI,QAAQ,SAAS,eAAe,EAAG;AACvC,QAAI,OAAO,SAAS,YAAY,EAAG;AACnC,QAAI,KAAK,IAAI,MAAM,EAAG;AAGtB,QAAI,SAAS;AACb,QAAI;AACF,YAAM,SAAS,IAAI,IAAI,MAAM,EAAE;AAC/B,eAAS,aAAa,KAAK,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAAA,IACtD,QAAQ;AACN,eAAS;AAAA,IACX;AACA,QAAI,CAAC,OAAQ;AAGb,UAAM,WAAW,QAAQ,MAAM,gBAAgB;AAC/C,QAAI,QAAQ,WAAW,CAAC,GAAG,KAAK,KAAK;AAErC,QAAI,CAAC,OAAO;AAEV,UAAI;AACF,cAAM,OAAO,IAAI,IAAI,MAAM,EAAE;AAC7B,cAAM,QAAQ,KACX,QAAQ,cAAc,GAAG,EACzB,MAAM,KAAK,EACX,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,EAC1B,MAAM,GAAG,CAAC,EACV,KAAK,GAAG;AACX,YAAI,MAAM,SAAS,EAAG,SAAQ;AAAA,MAChC,QAAQ;AAAA,MAAe;AAAA,IACzB;AAEA,QAAI,CAAC,MAAO,SAAQ;AAEpB,SAAK,IAAI,MAAM;AACf,YAAQ,KAAK;AAAA,MACX;AAAA,MACA,WAAW,QAAQ,MAAM;AAAA,MACzB,YAAY;AAAA,IACd,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAOA,eAAsB,aAAa,MAAc,oBAAmD,cAAwC;AAE1I,MAAI;AACJ,MAAI,OAAO,uBAAuB,YAAY,uBAAuB,MAAM;AACzE,WAAO;AAAA,EACT,OAAO;AACL,WAAO,EAAE,cAAc,oBAAoB,aAAa;AAAA,EAC1D;AAEA,QAAM,QAAQ,eAAe,IAAI;AACjC,MAAI,MAAM,WAAW,EAAG,QAAO;AAG/B,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,MAAM,IAAI,OAAO,SAAS;AACxB,UAAI,MAAqB;AAGzB,UAAI,KAAK,cAAc;AACrB,cAAM,MAAM,MAAM,YAAY,KAAK,OAAO,KAAK,YAAY,EAAE,MAAM,MAAM,IAAI;AAC7E,cAAM,KAAK,OAAO;AAAA,MACpB;AAGA,UAAI,CAAC,OAAO,KAAK,cAAc;AAC7B,YAAI;AACF,gBAAM,UAAU,MAAM,cAAc,KAAK,OAAO,KAAK,YAAY;AACjE,gBAAM,KAAK,eACP,MAAM,KAAK,aAAa,SAAS,KAAK,KAAK,IAC3C;AAAA,QACN,SAAS,GAAG;AACV,kBAAQ,KAAK,uBAAuB,KAAK,KAAK,MAAM,CAAC;AAAA,QACvD;AAAA,MACF;AAGA,cAAQ,mDAAmD,mBAAmB,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;AAEtG,aAAO,EAAE,MAAM,IAAI;AAAA,IACrB,CAAC;AAAA,EACH;AAEA,MAAI,SAAS;AACb,aAAW,KAAK,UAAU;AACxB,QAAI,EAAE,WAAW,eAAe,EAAE,OAAO;AACvC,YAAM,EAAE,MAAM,IAAI,IAAI,EAAE;AACxB,YAAM,cAAc,KAAK,WAAW,QAAQ,SAAS,GAAG;AACxD,eAAS,OAAO,WAAW,KAAK,WAAW,WAAW;AAAA,IACxD;AAAA,EACF;AAGA,WAAS,OAAO,QAAQ,oCAAoC,CAAC,QAAQ,UAAU;AAC7E,UAAM,WAAW,MAAM,MAAM,gBAAgB;AAC7C,UAAM,QAAQ,WAAW,CAAC,KAAK;AAC/B,WAAO,6DAA6D,mBAAmB,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,KAAK;AAAA,EACtH,CAAC;AAED,SAAO;AACT;;;ACvLA,SAAS,mBAAAA,wBAAuB;AAChC,SAAS,oBAAoB;;;ACD7B,SAAS,kBAAkB;AAC3B,SAAS,uBAAuB;AAChC,SAAS,cAAc;;;ACWvB,IAAM,SACJ;AAEF,IAAM,mBAAmB;AACzB,IAAM,gBAAgB;AAEtB,SAAS,WAAW,OAAmD;AACrE,MAAI,IAAI,OAAO,OAAO,gBAAgB,IAAI,EAAE,KAAK,KAAK,EAAG,QAAO;AAChE,MAAI,IAAI,OAAO,OAAO,aAAa,IAAI,EAAE,KAAK,KAAK,EAAG,QAAO;AAC7D,SAAO;AACT;AAGA,IAAM,WAAW;AAEjB,IAAM,sBAA0C;AAAA;AAAA,EAE9C,CAAC,iBAAiB,YAAY;AAAA;AAAA,EAE9B,CAAC,iBAAiB,iBAAiB;AAAA;AAAA,EAEnC,CAAC,mBAAmB,iBAAiB;AAAA;AAAA,EAErC,CAAC,mBAAmB,iBAAiB;AAAA;AAAA,EAGrC,CAAC,IAAI,OAAO,UAAU,QAAQ,iBAAiB,GAAG,GAAG,YAAY;AAAA;AAAA,EAEjE,CAAC,IAAI,OAAO,UAAU,QAAQ,kBAAkB,GAAG,GAAG,gBAAgB;AAAA;AAAA,EAEtE,CAAC,IAAI,OAAO,UAAU,QAAQ,sBAAsB,GAAG,GAAG,YAAY;AAAA;AAAA,EAEtE,CAAC,IAAI,OAAO,UAAU,QAAQ,0BAA0B,GAAG,GAAG,iBAAiB;AAAA;AAAA,EAG/E,CAAC,IAAI,OAAO,YAAY,QAAQ,kBAAkB,GAAG,GAAG,uBAAuB;AAAA;AAAA,EAE/E,CAAC,IAAI,OAAO,YAAY,QAAQ,kBAAkB,GAAG,GAAG,uBAAuB;AAAA;AAAA,EAE/E,CAAC,IAAI,OAAO,YAAY,QAAQ,0BAA0B,GAAG,GAAG,iBAAiB;AAAA;AAAA,EAEjF,CAAC,IAAI,OAAO,YAAY,QAAQ,qBAAqB,GAAG,GAAG,iBAAiB;AAAA;AAAA,EAG5E,CAAC,IAAI,OAAO,gBAAgB,QAAQ,yBAAyB,GAAG,GAAG,sBAAsB;AAAA,EACzF,CAAC,IAAI,OAAO,gBAAgB,QAAQ,sCAAsC,GAAG,GAAG,uBAAuB;AAAA;AAAA,EAGvG,CAAC,IAAI,OAAO,kBAAkB,QAAQ,iBAAiB,GAAG,GAAG,uBAAuB;AACtF;AAGA,SAAS,6BAAmF;AAC1F,QAAM,KAAK,CAAC,QAAgB,WAC1B,IAAI,OAAO,MAAM,MAAM,KAAK,MAAM,MAAM,MAAM,QAAQ,GAAG;AAE3D,SAAO;AAAA;AAAA,IAEL,CAAC,GAAG,MAAM,aAAa,GAAG,CAAC,IAAI,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE;AAAA,IAC1D,CAAC,GAAG,MAAM,QAAQ,GAAG,CAAC,IAAI,MAAM,MAAM,WAAW,CAAC,CAAC,QAAQ;AAAA,IAC3D,CAAC,GAAG,MAAM,aAAa,GAAG,CAAC,IAAI,MAAM,MAAM,WAAW,CAAC,CAAC,OAAO;AAAA,IAC/D,CAAC,GAAG,MAAM,aAAa,GAAG,CAAC,IAAI,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE;AAAA;AAAA,IAG1D,CAAC,GAAG,QAAQ,aAAa,GAAG,CAAC,IAAI,MAAM,QAAQ,WAAW,CAAC,CAAC,EAAE;AAAA,IAC9D,CAAC,GAAG,QAAQ,aAAa,GAAG,CAAC,IAAI,MAAM,QAAQ,WAAW,CAAC,CAAC,OAAO;AAAA,IACnE,CAAC,GAAG,QAAQ,gBAAgB,GAAG,CAAC,IAAI,MAAM,WAAW,WAAW,CAAC,CAAC,EAAE;AAAA,IACpE,CAAC,GAAG,QAAQ,KAAK,GAAG,CAAC,IAAI,MAAM,QAAQ,WAAW,CAAC,CAAC,EAAE;AAAA;AAAA,IAGtD,CAAC,GAAG,UAAU,UAAU,GAAG,CAAC,IAAI,MAAM,UAAU,WAAW,CAAC,CAAC,EAAE;AAAA;AAAA,IAG/D,CAAC,GAAG,QAAQ,UAAU,GAAG,CAAC,IAAI,MAAM,QAAQ,WAAW,CAAC,CAAC,EAAE;AAAA;AAAA,IAG3D,CAAC,GAAG,QAAQ,UAAU,GAAG,CAAC,IAAI,MAAM,QAAQ,WAAW,CAAC,CAAC,EAAE;AAAA,IAC3D,CAAC,GAAG,MAAM,UAAU,GAAG,CAAC,IAAI,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE;AAAA,IACvD,CAAC,GAAG,OAAO,UAAU,GAAG,CAAC,IAAI,MAAM,OAAO,WAAW,CAAC,CAAC,EAAE;AAAA;AAAA,IAGzD,CAAC,IAAI,OAAO,gBAAgB,MAAM,kCAAkC,GAAG,GAAG,CAAC,IAAI,MAAM,YAAY,WAAW,CAAC,CAAC,OAAO;AAAA,IACrH,CAAC,IAAI,OAAO,gBAAgB,MAAM,6BAA6B,GAAG,GAAG,CAAC,IAAI,MAAM,YAAY,WAAW,CAAC,CAAC,QAAQ;AAAA,IACjH,CAAC,IAAI,OAAO,kBAAkB,MAAM,iBAAiB,GAAG,GAAG,CAAC,IAAI,MAAM,cAAc,WAAW,CAAC,CAAC,EAAE;AAAA,IACnG,CAAC,IAAI,OAAO,kBAAkB,MAAM,iBAAiB,GAAG,GAAG,CAAC,IAAI,MAAM,cAAc,WAAW,CAAC,CAAC,EAAE;AAAA,IACnG,CAAC,IAAI,OAAO,oBAAoB,MAAM,iBAAiB,GAAG,GAAG,CAAC,IAAI,MAAM,gBAAgB,WAAW,CAAC,CAAC,EAAE;AAAA;AAAA,IAGvG,CAAC,GAAG,UAAU,UAAU,GAAG,CAAC,IAAI,MAAM,UAAU,WAAW,CAAC,CAAC,EAAE;AAAA;AAAA,IAG/D,CAAC,GAAG,eAAe,UAAU,GAAG,CAAC,IAAI,MAAM,eAAe,WAAW,CAAC,CAAC,EAAE;AAAA;AAAA,IAGzE,CAAC,GAAG,WAAW,UAAU,GAAG,CAAC,IAAI,MAAM,WAAW,WAAW,CAAC,CAAC,EAAE;AAAA;AAAA,IAGjE,CAAC,GAAG,UAAU,UAAU,GAAG,CAAC,IAAI,MAAM,UAAU,WAAW,CAAC,CAAC,EAAE;AAAA;AAAA,IAG/D,CAAC,GAAG,cAAc,UAAU,GAAG,CAAC,IAAI,MAAM,cAAc,WAAW,CAAC,CAAC,EAAE;AAAA;AAAA,IAGvE,CAAC,GAAG,UAAU,UAAU,GAAG,CAAC,IAAI,MAAM,UAAU,WAAW,CAAC,CAAC,EAAE;AAAA,EACjE;AACF;AAEA,IAAM,wBAAwB,2BAA2B;AAElD,SAAS,uBAAuB,MAAsB;AAC3D,MAAI,SAAS;AAGb,aAAW,CAAC,SAAS,WAAW,KAAK,qBAAqB;AACxD,aAAS,OAAO,QAAQ,SAAS,WAAW;AAAA,EAC9C;AAKA,QAAM,qBAAqB,uDAAuD,KAAK,MAAM;AAC7F,MAAI,CAAC,oBAAoB;AAEvB,eAAW,CAAC,SAAS,QAAQ,KAAK,uBAAuB;AACvD,eAAS,OAAO,QAAQ,SAAS,QAAe;AAAA,IAClD;AAAA,EACF;AAEA,SAAO;AACT;;;ADpIO,SAAS,kBAA0B;AACxC,SAAO;AAAA,mBAAqB,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA;AACpE;AAOA,SAAS,cAAc,IAAqB;AAC1C,SAAO,8CAA8C,KAAK,EAAE;AAC9D;AAEA,SAAS,gBAAgB,OAAqD;AAC5E,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,aAAa,SAAS,cAAc;AAC5F;AAEA,eAAsB,aAAa,MAMhC;AAED,MAAI,KAAK,WAAW,gBAAgB,KAAK,OAAO,GAAG;AACjD,WAAO,KAAK;AAAA,EACd;AAEA,QAAM,UAAU,KAAK;AAErB,MAAI,WAAW,cAAc,OAAO,GAAG;AACrC,UAAMC,aAAY,KAAK,gBAAgB,QAAQ,IAAI;AACnD,QAAIA,YAAW;AACb,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,gBAAgB;AACtD,aAAO,aAAa,EAAE,QAAQA,WAAU,CAAC,EAAE,OAAO;AAAA,IACpD;AAAA,EAEF,WAAW,SAAS;AAClB,UAAMC,gBAAe,KAAK,mBAAmB,QAAQ,IAAI;AACzD,QAAIA,eAAc;AAChB,aAAO,gBAAgB,EAAE,QAAQA,cAAa,CAAC,EAAE,OAAO;AAAA,IAC1D;AAAA,EACF;AAEA,QAAM,eAAe,KAAK,mBAAmB,QAAQ,IAAI;AACzD,MAAI,cAAc;AAChB,WAAO,gBAAgB,EAAE,QAAQ,aAAa,CAAC,EAAE,KAAK,gBAAgB;AAAA,EACxE;AACA,QAAM,YAAY,KAAK,gBAAgB,QAAQ,IAAI;AACnD,MAAI,WAAW;AACb,UAAM,EAAE,aAAa,IAAI,MAAM,OAAO,gBAAgB;AACtD,WAAO,aAAa,EAAE,QAAQ,UAAU,CAAC,EAAE,KAAK,aAAa;AAAA,EAC/D;AACA,SAAO,gBAAgB,EAAE,KAAK,gBAAgB;AAChD;AAKO,SAAS,mBAAmB,SAAiE;AAClG,QAAM,QAAQ,QAAQ,MAAM,4BAA4B;AACxD,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO;AAAA,IACL,OAAO,IAAI,WAAW,OAAO,KAAK,MAAM,CAAC,GAAG,QAAQ,CAAC;AAAA,IACrD,UAAU,MAAM,CAAC;AAAA,EACnB;AACF;AAKO,SAAS,mBAAmB,MAA+B;AAChE,QAAM,UAAiB,CAAC;AACxB,MAAI,YAAY;AAEhB,SAAO,UAAU,SAAS,GAAG;AAC3B,gBAAY,UAAU,UAAU;AAChC,QAAI,CAAC,UAAU,WAAW,GAAG,GAAG;AAC9B,YAAM,YAAY,UAAU,QAAQ,GAAG;AACvC,UAAI,cAAc,GAAI;AACtB,kBAAY,UAAU,MAAM,SAAS;AACrC;AAAA,IACF;AAEA,QAAI,QAAQ;AACZ,QAAI,WAAW;AACf,QAAI,SAAS;AACb,QAAI,MAAM;AAEV,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,YAAM,KAAK,UAAU,CAAC;AACtB,UAAI,QAAQ;AAAE,iBAAS;AAAO;AAAA,MAAU;AACxC,UAAI,OAAO,MAAM;AAAE,iBAAS;AAAM;AAAA,MAAU;AAC5C,UAAI,OAAO,KAAK;AAAE,mBAAW,CAAC;AAAU;AAAA,MAAU;AAClD,UAAI,SAAU;AACd,UAAI,OAAO,IAAK;AAChB,UAAI,OAAO,KAAK;AAAE;AAAS,YAAI,UAAU,GAAG;AAAE,gBAAM;AAAG;AAAA,QAAO;AAAA,MAAE;AAAA,IAClE;AAEA,QAAI,QAAQ,GAAI;AAEhB,UAAM,YAAY,UAAU,MAAM,GAAG,MAAM,CAAC;AAC5C,gBAAY,UAAU,MAAM,MAAM,CAAC;AAEnC,QAAI;AACF,cAAQ,KAAK,KAAK,MAAM,SAAS,CAAC;AAAA,IACpC,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO,CAAC,SAAS,SAAS;AAC5B;AAGA,IAAM,0BAA0B,sBAAsB,mBAAmB,06BAA06B,CAAC;AAGp/B,IAAM,0BAA0B;AAGzB,SAAS,0BAA0B,MAAsB;AAC9D,SAAO,KAAK;AAAA,IACV;AAAA,IACA,CAAC,QAAQ,QAAQ,OAAO,UAAU;AAChC,aAAO,QAAQ,MAAM,mBAAmB,KAAK,IAAI,KAAK,IAAI,uBAAuB;AAAA,IACnF;AAAA,EACF;AACF;AAGO,SAAS,uBAAuB,MAAsB;AAC3D,SAAO,KAAK;AAAA,IACV;AAAA,IACA,CAAC,QAAQ,QAAQ,OAAO,UAAU;AAChC,UAAI,OAAO,SAAS,MAAM,KAAK,MAAM,SAAS,MAAM,EAAG,QAAO;AAC9D,aAAO,GAAG,MAAM,QAAQ,uBAAuB,uBAAuB,KAAK,UAAU,KAAK,IAAI,KAAK;AAAA,IACrG;AAAA,EACF;AACF;AAGA,eAAsB,oBACpB,SACA,MAMe;AACf,QAAM,QAAQ,eAAe,QAAQ,IAAI;AACzC,MAAI,MAAM,WAAW,EAAG;AACxB,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,MAAM,IAAI,OAAO,SAAS;AACxB,UAAI,MAAqB;AACzB,UAAI,KAAK,cAAc;AACrB,cAAM,MAAM,MAAM,YAAY,KAAK,OAAO,KAAK,YAAY,EAAE,MAAM,MAAM,IAAI;AAC7E,cAAM,KAAK,OAAO;AAAA,MACpB;AACA,UAAI,CAAC,OAAO,KAAK,cAAc;AAC7B,YAAI;AACF,gBAAM,UAAU,MAAM,cAAc,KAAK,OAAO,KAAK,YAAY;AACjE,gBAAM,KAAK,eAAe,MAAM,KAAK,aAAa,SAAS,KAAK,KAAK,IAAI;AAAA,QAC3E,SAAS,GAAG;AACV,kBAAQ,KAAK,uBAAuB,KAAK,KAAK,MAAM,CAAC;AAAA,QACvD;AAAA,MACF;AACA,cAAQ,mDAAmD,mBAAmB,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;AACtG,aAAO,EAAE,MAAM,IAAI;AAAA,IACrB,CAAC;AAAA,EACH;AACA,MAAI,OAAO,QAAQ;AACnB,aAAW,KAAK,SAAS;AACvB,QAAI,EAAE,WAAW,eAAe,EAAE,OAAO;AACvC,YAAM,EAAE,MAAM,IAAI,IAAI,EAAE;AACxB,YAAM,cAAc,KAAK,WAAW,QAAQ,SAAS,GAAG;AACxD,aAAO,KAAK,WAAW,KAAK,WAAW,WAAW;AAAA,IACpD;AAAA,EACF;AACA,MAAI,SAAS,QAAQ,MAAM;AACzB,YAAQ,OAAO;AACf,SAAK,gBAAgB,QAAQ,IAAI,IAAI;AAAA,EACvC;AACF;AAGA,eAAsB,uBACpB,SACA,MAIe;AACf,QAAM,WAAW;AACjB,QAAM,aAAsD,CAAC;AAC7D,MAAI;AACJ,UAAQ,OAAO,SAAS,KAAK,QAAQ,IAAI,OAAO,MAAM;AACpD,eAAW,KAAK,EAAE,WAAW,KAAK,CAAC,GAAG,QAAQ,KAAK,CAAC,EAAE,CAAC;AAAA,EACzD;AACA,MAAI,WAAW,WAAW,EAAG;AAC7B,QAAM,eAAe,KAAK,mBAAmB,QAAQ,IAAI;AACzD,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,WAAW,IAAI,OAAO,EAAE,WAAW,OAAO,MAAM;AAC9C,UAAI;AACF,cAAM,MAAM,MAAM,YAAY,QAAQ,YAAY;AAClD,eAAO,EAAE,WAAW,IAAI;AAAA,MAC1B,SAAS,GAAG;AACV,gBAAQ,KAAK,qBAAqB,MAAM,MAAM,CAAC;AAC/C,eAAO,EAAE,WAAW,KAAK,0GAA0G,MAAM,SAAS;AAAA,MACpJ;AAAA,IACF,CAAC;AAAA,EACH;AACA,MAAI,OAAO,QAAQ;AACnB,aAAW,KAAK,SAAS;AACvB,QAAI,EAAE,WAAW,eAAe,EAAE,OAAO;AACvC,aAAO,KAAK,QAAQ,EAAE,MAAM,WAAW,EAAE,MAAM,GAAG;AAAA,IACpD;AAAA,EACF;AACA,MAAI,SAAS,QAAQ,MAAM;AACzB,YAAQ,OAAO;AACf,SAAK,gBAAgB,QAAQ,IAAI,IAAI;AAAA,EACvC;AACF;AAiCA,eAAsB,eAAe,SAAqD;AACxF,QAAM;AAAA,IACJ;AAAA,IACA,cAAc;AAAA,IACd,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,eAAe,iBAAiB,QAAQ,IAAI;AAClD,QAAM,QAAQ,MAAM,aAAa;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,kBAAkB;AAAA,EACpB,CAAC;AAED,QAAM,SAAS,WAAW;AAAA,IACxB;AAAA,IACA,QAAQ,eAAe,gBAAgB;AAAA,IACvC,UAAU,CAAC,EAAE,MAAM,QAAQ,SAAS,YAAY,CAAC;AAAA,EACnD,CAAC;AAED,QAAM,cAA0B,CAAC;AACjC,QAAM,gBAAiC,CAAC;AACxC,MAAI,eAAe;AACnB,MAAI,SAAS;AAEb,WAAS,gBAAgB,YAAsB;AAC7C,UAAM,WAAW;AACjB,UAAM,aAAsD,CAAC;AAC7D,QAAI;AACJ,YAAQ,OAAO,SAAS,KAAK,WAAW,IAAI,OAAO,MAAM;AACvD,iBAAW,KAAK,EAAE,WAAW,KAAK,CAAC,GAAG,QAAQ,KAAK,CAAC,EAAE,CAAC;AAAA,IACzD;AACA,QAAI,WAAW,WAAW,EAAG;AAE7B,UAAM,eAAe,mBAAmB,QAAQ,IAAI;AACpD,kBAAc;AAAA,OACX,YAAY;AACX,cAAM,UAAU,MAAM,QAAQ;AAAA,UAC5B,WAAW,IAAI,OAAO,EAAE,WAAW,OAAO,MAAM;AAC9C,gBAAI;AACF,oBAAM,MAAM,MAAM,YAAY,QAAQ,YAAY;AAClD,qBAAO,EAAE,WAAW,IAAI;AAAA,YAC1B,SAAS,GAAG;AACV,sBAAQ,KAAK,qBAAqB,MAAM,MAAM,CAAC;AAC/C,qBAAO,EAAE,WAAW,KAAK,0GAA0G,MAAM,SAAS;AAAA,YACpJ;AAAA,UACF,CAAC;AAAA,QACH;AACA,YAAI,OAAO,WAAW;AACtB,mBAAW,KAAK,SAAS;AACvB,cAAI,EAAE,WAAW,eAAe,EAAE,OAAO;AACvC,mBAAO,KAAK,QAAQ,EAAE,MAAM,WAAW,EAAE,MAAM,GAAG;AAAA,UACpD;AAAA,QACF;AACA,YAAI,SAAS,WAAW,MAAM;AAC5B,qBAAW,OAAO;AAClB,0BAAgB,WAAW,IAAI,IAAI;AAAA,QACrC;AAAA,MACF,GAAG;AAAA,IACL;AAAA,EACF;AAEA,WAAS,cAAc,YAAsB;AAC3C,UAAM,QAAQ,eAAe,WAAW,IAAI;AAC5C,QAAI,MAAM,WAAW,EAAG;AACxB,UAAM,gBAAgB,MAAM,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;AACjD,kBAAc;AAAA,OACX,YAAY;AACX,cAAM,UAAU,MAAM,QAAQ;AAAA,UAC5B,cAAc,IAAI,OAAO,SAAS;AAChC,gBAAI,MAAqB;AAEzB,gBAAI,cAAc;AAChB,oBAAM,MAAM,MAAM,YAAY,KAAK,OAAO,YAAY,EAAE,MAAM,MAAM,IAAI;AACxE,oBAAM,KAAK,OAAO;AAAA,YACpB;AAEA,gBAAI,CAAC,OAAO,cAAc;AACxB,kBAAI;AACF,sBAAM,UAAU,MAAM,cAAc,KAAK,OAAO,YAAY;AAC5D,sBAAM,eAAe,MAAM,aAAa,SAAS,KAAK,KAAK,IAAI;AAAA,cACjE,SAAS,GAAG;AACV,wBAAQ,KAAK,uBAAuB,KAAK,KAAK,MAAM,CAAC;AAAA,cACvD;AAAA,YACF;AACA,oBAAQ,mDAAmD,mBAAmB,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;AACtG,mBAAO,EAAE,MAAM,IAAI;AAAA,UACrB,CAAC;AAAA,QACH;AACA,YAAI,OAAO,WAAW;AACtB,mBAAW,KAAK,SAAS;AACvB,cAAI,EAAE,WAAW,eAAe,EAAE,OAAO;AACvC,kBAAM,EAAE,MAAM,IAAI,IAAI,EAAE;AACxB,kBAAM,cAAc,KAAK,WAAW,QAAQ,SAAS,GAAG;AACxD,mBAAO,KAAK,WAAW,KAAK,WAAW,WAAW;AAAA,UACpD;AAAA,QACF;AACA,YAAI,SAAS,WAAW,MAAM;AAC5B,qBAAW,OAAO;AAClB,0BAAgB,WAAW,IAAI,IAAI;AAAA,QACrC;AAAA,MACF,GAAG;AAAA,IACL;AAAA,EACF;AAEA,WAAS,cAAc,KAAU;AAC/B,QAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,MAAO;AAC7B,UAAM,UAAoB;AAAA,MACxB,IAAI,OAAO,CAAC;AAAA,MACZ,OAAO;AAAA,MACP,MAAM,uBAAuB,0BAA0B,uBAAuB,IAAI,IAAI,CAAC,CAAC;AAAA,MACxF,OAAO,IAAI;AAAA,IACb;AACA,gBAAY,KAAK,OAAO;AACxB,gBAAY,OAAO;AACnB,kBAAc,OAAO;AACrB,oBAAgB,OAAO;AAAA,EACzB;AAEA,MAAI;AACF,QAAI,aAAa;AACjB,qBAAiB,SAAS,OAAO,YAAY;AAC3C,gBAAU;AACV;AAEA,YAAM,CAAC,SAAS,SAAS,IAAI,mBAAmB,MAAM;AACtD,eAAS;AACT,iBAAW,OAAO,SAAS;AACzB,qBAAa;AACb,sBAAc,GAAG;AAAA,MACnB;AAEA,UAAI,cAAc,aAAa,MAAM,KAAK,OAAO,SAAS,IAAI;AAC5D,mBAAW,QAAQ,YAAY,MAAM;AAAA,MACvC;AAAA,IACF;AAGA,QAAI,OAAO,KAAK,GAAG;AACjB,UAAI,UAAU,OAAO,KAAK;AAC1B,UAAI,QAAQ,WAAW,KAAK,GAAG;AAC7B,kBAAU,QAAQ,QAAQ,oBAAoB,EAAE,EAAE,QAAQ,WAAW,EAAE;AAAA,MACzE;AACA,YAAM,CAAC,WAAW,IAAI,mBAAmB,OAAO;AAChD,iBAAW,OAAO,YAAa,eAAc,GAAG;AAAA,IAClD;AAGA,UAAM,QAAQ,WAAW,aAAa;AAGtC,eAAW,WAAW,aAAa;AACjC,YAAM,SAAS,QAAQ;AACvB,cAAQ,OAAO,QAAQ,KAAK;AAAA,QAC1B;AAAA,QACA,CAAC,QAAQ,UAAU;AACjB,gBAAM,WAAW,MAAM,MAAM,gBAAgB;AAC7C,gBAAM,QAAQ,WAAW,CAAC,KAAK;AAC/B,iBAAO,6DAA6D,mBAAmB,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,KAAK;AAAA,QACtH;AAAA,MACF;AACA,cAAQ,OAAO,QAAQ,KAAK;AAAA,QAC1B;AAAA,QACA,CAAC,QAAQ,UAAU;AACjB,iBAAO,wDAAwD,mBAAmB,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QACvG;AAAA,MACF;AACA,UAAI,QAAQ,SAAS,QAAQ;AAC3B,wBAAgB,QAAQ,IAAI,QAAQ,IAAI;AAAA,MAC1C;AAAA,IACF;AAEA,aAAS,WAAW;AACpB,WAAO;AAAA,EACT,SAAS,KAAU;AACjB,UAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,KAAK,WAAW,mBAAmB;AACxF,cAAU,KAAK;AACf,UAAM;AAAA,EACR;AACF;;;ADrcA,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2B1B,eAAsB,YACpB,QACA,iBACA,SACiB;AACjB,QAAM,SAAS,mBAAmB,QAAQ,IAAI;AAC9C,QAAM,YAAYC,iBAAgB,EAAE,QAAQ,UAAU,OAAU,CAAC;AAEjE,QAAM,WAAW,SAAS,SAAS,SAAS,SACxC,uBAAuB,QAAQ,KAAK,IAAI,QAAQ,MAAM,QACtD;AACJ,QAAM,YAAY,SAAS,cACvB,4BAA4B,QAAQ,WAAW,MAC/C;AAEJ,QAAM,SAAS,MAAM,aAAa;AAAA,IAChC,OAAO,UAAU,2BAA2B;AAAA,IAC5C,QAAQ,oBAAoB,gBAAgB;AAAA,IAC5C,UAAU;AAAA,MACR;AAAA,QACE,MAAM;AAAA,QACN,SAAS,wBAAwB,MAAM,GAAG,QAAQ,GAAG,SAAS;AAAA,MAChE;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,EACnB,CAAC;AAGD,QAAM,WAAW,OAAO,KAAK,MAAM,qBAAqB;AACxD,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,uDAAkD;AAAA,EACpE;AAEA,SAAO,SAAS,CAAC;AACnB;","names":["createAnthropic","openaiKey","anthropicKey","createAnthropic"]}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
LANDING_THEMES,
|
|
3
2
|
buildPreviewHtml
|
|
4
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YYHFKHOQ.js";
|
|
4
|
+
import {
|
|
5
|
+
LANDING_THEMES
|
|
6
|
+
} from "./chunk-D7YHQJET.js";
|
|
5
7
|
|
|
6
8
|
// src/components/Canvas.tsx
|
|
7
9
|
import { useRef, useEffect, useCallback, useState, forwardRef, useImperativeHandle } from "react";
|
|
@@ -1366,4 +1368,4 @@ export {
|
|
|
1366
1368
|
ViewportToggle,
|
|
1367
1369
|
useUndoStack
|
|
1368
1370
|
};
|
|
1369
|
-
//# sourceMappingURL=chunk-
|
|
1371
|
+
//# sourceMappingURL=chunk-TDZO6X4O.js.map
|