@easybits.cloud/html-tailwind-generator 0.2.132 → 0.2.134
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-YZHRLDQF.js → chunk-32JWNJFY.js} +133 -16
- package/dist/chunk-32JWNJFY.js.map +1 -0
- package/dist/{chunk-X5MEN76P.js → chunk-B3TDPWJD.js} +2 -2
- package/dist/{chunk-RJQKHWIH.js → chunk-QSEPSXL7.js} +2 -2
- package/dist/{chunk-CQXBVGVC.js → chunk-UQELTLRO.js} +2 -2
- package/dist/directions.js +1 -1
- package/dist/generate.js +2 -2
- package/dist/generateDocument.js +2 -2
- package/dist/images.js +1 -1
- package/dist/index.js +4 -4
- package/dist/refine.js +2 -2
- package/package.json +3 -3
- package/dist/chunk-YZHRLDQF.js.map +0 -1
- /package/dist/{chunk-X5MEN76P.js.map → chunk-B3TDPWJD.js.map} +0 -0
- /package/dist/{chunk-RJQKHWIH.js.map → chunk-QSEPSXL7.js.map} +0 -0
- /package/dist/{chunk-CQXBVGVC.js.map → chunk-UQELTLRO.js.map} +0 -0
|
@@ -271,10 +271,6 @@ var neutralReplacements = [
|
|
|
271
271
|
[/\bbg-white\b/g, "bg-surface"],
|
|
272
272
|
// bg-black → bg-primary-dark
|
|
273
273
|
[/\bbg-black\b/g, "bg-primary-dark"],
|
|
274
|
-
// text-white → text-on-primary
|
|
275
|
-
[/\btext-white\b/g, "text-on-primary"],
|
|
276
|
-
// text-black → text-on-surface
|
|
277
|
-
[/\btext-black\b/g, "text-on-surface"],
|
|
278
274
|
// bg-gray-50/100 → bg-surface
|
|
279
275
|
[new RegExp(`\\bbg-(${NEUTRALS})-(50|100)\\b`, "g"), "bg-surface"],
|
|
280
276
|
// bg-gray-200/300 → bg-surface-alt
|
|
@@ -283,18 +279,18 @@ var neutralReplacements = [
|
|
|
283
279
|
[new RegExp(`\\bbg-(${NEUTRALS})-(400|500|600)\\b`, "g"), "bg-primary"],
|
|
284
280
|
// bg-gray-700-950 → bg-primary-dark
|
|
285
281
|
[new RegExp(`\\bbg-(${NEUTRALS})-(700|800|900|950)\\b`, "g"), "bg-primary-dark"],
|
|
286
|
-
//
|
|
287
|
-
[new RegExp(`\\btext-(${NEUTRALS})-(300|400)\\b`, "g"), "text-on-surface-muted"],
|
|
288
|
-
// text-gray-500/600 → text-on-surface-muted
|
|
289
|
-
[new RegExp(`\\btext-(${NEUTRALS})-(500|600)\\b`, "g"), "text-on-surface-muted"],
|
|
290
|
-
// text-gray-700/800/900 → text-on-surface
|
|
291
|
-
[new RegExp(`\\btext-(${NEUTRALS})-(700|800|900|950)\\b`, "g"), "text-on-surface"],
|
|
292
|
-
// text-gray-50/100/200 → text-on-primary
|
|
293
|
-
[new RegExp(`\\btext-(${NEUTRALS})-(50|100|200)\\b`, "g"), "text-on-primary"],
|
|
294
|
-
// hover:bg-gray → hover semantic
|
|
282
|
+
// hover:bg neutrals
|
|
295
283
|
[new RegExp(`\\bhover:bg-(${NEUTRALS})-(50|100|200|300)\\b`, "g"), "hover:bg-surface-alt"],
|
|
296
|
-
[new RegExp(`\\bhover:bg-(${NEUTRALS})-(400|500|600|700|800|900|950)\\b`, "g"), "hover:bg-primary-dark"]
|
|
297
|
-
|
|
284
|
+
[new RegExp(`\\bhover:bg-(${NEUTRALS})-(400|500|600|700|800|900|950)\\b`, "g"), "hover:bg-primary-dark"]
|
|
285
|
+
];
|
|
286
|
+
var textSeedReplacements = [
|
|
287
|
+
[/\btext-white\b/g, "text-on-surface-LIGHT"],
|
|
288
|
+
// marker: "was light text"
|
|
289
|
+
[/\btext-black\b/g, "text-on-surface-DARK"],
|
|
290
|
+
// marker: "was dark text"
|
|
291
|
+
[new RegExp(`\\btext-(${NEUTRALS})-(50|100|200)\\b`, "g"), "text-on-surface-LIGHT"],
|
|
292
|
+
[new RegExp(`\\btext-(${NEUTRALS})-(300|400|500|600)\\b`, "g"), "text-on-surface-MUTED"],
|
|
293
|
+
[new RegExp(`\\btext-(${NEUTRALS})-(700|800|900|950)\\b`, "g"), "text-on-surface-DARK"],
|
|
298
294
|
[new RegExp(`\\bhover:text-(${NEUTRALS})-\\d{2,3}\\b`, "g"), "hover:text-on-surface"]
|
|
299
295
|
];
|
|
300
296
|
function buildChromaticReplacements() {
|
|
@@ -339,17 +335,138 @@ function buildChromaticReplacements() {
|
|
|
339
335
|
];
|
|
340
336
|
}
|
|
341
337
|
var chromaticReplacements = buildChromaticReplacements();
|
|
338
|
+
var VOID_TAGS = /* @__PURE__ */ new Set([
|
|
339
|
+
"br",
|
|
340
|
+
"hr",
|
|
341
|
+
"img",
|
|
342
|
+
"input",
|
|
343
|
+
"meta",
|
|
344
|
+
"link",
|
|
345
|
+
"area",
|
|
346
|
+
"base",
|
|
347
|
+
"col",
|
|
348
|
+
"embed",
|
|
349
|
+
"source",
|
|
350
|
+
"track",
|
|
351
|
+
"wbr"
|
|
352
|
+
]);
|
|
353
|
+
function detectBgFamily(classStr) {
|
|
354
|
+
const tokens = classStr.split(/\s+/).filter((c) => c && !c.includes(":"));
|
|
355
|
+
let found = null;
|
|
356
|
+
for (const t of tokens) {
|
|
357
|
+
const opMatch = t.match(/\/(\d{1,3})$/);
|
|
358
|
+
if (opMatch) {
|
|
359
|
+
const op = parseInt(opMatch[1], 10);
|
|
360
|
+
if (op < 50) continue;
|
|
361
|
+
}
|
|
362
|
+
if (/^bg-primary(?:-light|-dark)?(?:\/\d+)?$/.test(t)) found = "primary";
|
|
363
|
+
else if (/^bg-secondary(?:\/\d+)?$/.test(t)) found = "secondary";
|
|
364
|
+
else if (/^bg-accent(?:\/\d+)?$/.test(t)) found = "accent";
|
|
365
|
+
else if (/^bg-surface(?:-alt)?(?:\/\d+)?$/.test(t)) found = "surface";
|
|
366
|
+
}
|
|
367
|
+
if (found) return found;
|
|
368
|
+
if (tokens.some((t) => /^bg-gradient-/.test(t))) {
|
|
369
|
+
for (const t of tokens) {
|
|
370
|
+
const m = t.match(/^from-(primary|secondary|accent|surface)(?:-light|-dark|-alt)?(?:\/\d+)?$/);
|
|
371
|
+
if (m) return m[1];
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
function effectiveBg(stack) {
|
|
377
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
378
|
+
const v = stack[i];
|
|
379
|
+
if (v !== null) return v;
|
|
380
|
+
}
|
|
381
|
+
return "surface";
|
|
382
|
+
}
|
|
383
|
+
function onClass(bg) {
|
|
384
|
+
return `text-on-${bg}`;
|
|
385
|
+
}
|
|
386
|
+
function onMutedClass(bg) {
|
|
387
|
+
return bg === "surface" ? "text-on-surface-muted" : `text-on-${bg}`;
|
|
388
|
+
}
|
|
389
|
+
function fixTextClassesForBg(classStr, bg) {
|
|
390
|
+
let s = classStr;
|
|
391
|
+
const on = onClass(bg);
|
|
392
|
+
const onMuted = onMutedClass(bg);
|
|
393
|
+
s = s.replace(/\btext-on-surface-LIGHT\b/g, on);
|
|
394
|
+
s = s.replace(/\btext-on-surface-DARK\b/g, on);
|
|
395
|
+
s = s.replace(/\btext-on-surface-MUTED\b/g, onMuted);
|
|
396
|
+
if (bg === "primary") {
|
|
397
|
+
s = s.replace(/\btext-on-surface(?:-muted)?\b/g, "text-on-primary");
|
|
398
|
+
s = s.replace(/\btext-on-secondary\b/g, "text-on-primary");
|
|
399
|
+
s = s.replace(/\btext-on-accent\b/g, "text-on-primary");
|
|
400
|
+
s = s.replace(/\btext-primary(?!-(?:light|dark))\b/g, "text-on-primary");
|
|
401
|
+
} else if (bg === "secondary") {
|
|
402
|
+
s = s.replace(/\btext-on-surface(?:-muted)?\b/g, "text-on-secondary");
|
|
403
|
+
s = s.replace(/\btext-on-primary\b/g, "text-on-secondary");
|
|
404
|
+
s = s.replace(/\btext-on-accent\b/g, "text-on-secondary");
|
|
405
|
+
s = s.replace(/\btext-secondary\b/g, "text-on-secondary");
|
|
406
|
+
} else if (bg === "accent") {
|
|
407
|
+
s = s.replace(/\btext-on-surface(?:-muted)?\b/g, "text-on-accent");
|
|
408
|
+
s = s.replace(/\btext-on-primary\b/g, "text-on-accent");
|
|
409
|
+
s = s.replace(/\btext-on-secondary\b/g, "text-on-accent");
|
|
410
|
+
s = s.replace(/\btext-accent\b/g, "text-on-accent");
|
|
411
|
+
} else {
|
|
412
|
+
s = s.replace(/\btext-on-primary\b/g, "text-on-surface");
|
|
413
|
+
s = s.replace(/\btext-on-secondary\b/g, "text-on-surface");
|
|
414
|
+
s = s.replace(/\btext-on-accent\b/g, "text-on-surface");
|
|
415
|
+
}
|
|
416
|
+
return s;
|
|
417
|
+
}
|
|
418
|
+
function ancestorAwareTextPass(html) {
|
|
419
|
+
try {
|
|
420
|
+
const tagRe = /<(\/?)([a-zA-Z][a-zA-Z0-9]*)\b([^>]*?)(\/?)>/g;
|
|
421
|
+
const stack = [];
|
|
422
|
+
let out = "";
|
|
423
|
+
let lastIdx = 0;
|
|
424
|
+
let m;
|
|
425
|
+
while ((m = tagRe.exec(html)) !== null) {
|
|
426
|
+
const [full, slash, tagName, attrs, selfCloseSlash] = m;
|
|
427
|
+
out += html.slice(lastIdx, m.index);
|
|
428
|
+
lastIdx = m.index + full.length;
|
|
429
|
+
if (slash === "/") {
|
|
430
|
+
stack.pop();
|
|
431
|
+
out += full;
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
const classMatch = attrs.match(/\bclass="([^"]*)"/);
|
|
435
|
+
const ownBg = classMatch ? detectBgFamily(classMatch[1]) : null;
|
|
436
|
+
const effective = ownBg ?? effectiveBg(stack);
|
|
437
|
+
let newAttrs = attrs;
|
|
438
|
+
if (classMatch) {
|
|
439
|
+
const fixed = fixTextClassesForBg(classMatch[1], effective);
|
|
440
|
+
if (fixed !== classMatch[1]) {
|
|
441
|
+
newAttrs = attrs.replace(/\bclass="[^"]*"/, `class="${fixed}"`);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
out += `<${tagName}${newAttrs}${selfCloseSlash}>`;
|
|
445
|
+
const isVoid = VOID_TAGS.has(tagName.toLowerCase()) || selfCloseSlash === "/";
|
|
446
|
+
if (!isVoid) stack.push(ownBg);
|
|
447
|
+
}
|
|
448
|
+
out += html.slice(lastIdx);
|
|
449
|
+
out = out.replace(/\btext-on-surface-LIGHT\b/g, "text-on-surface").replace(/\btext-on-surface-DARK\b/g, "text-on-surface").replace(/\btext-on-surface-MUTED\b/g, "text-on-surface-muted");
|
|
450
|
+
return out;
|
|
451
|
+
} catch {
|
|
452
|
+
return html.replace(/\btext-on-surface-LIGHT\b/g, "text-on-surface").replace(/\btext-on-surface-DARK\b/g, "text-on-surface").replace(/\btext-on-surface-MUTED\b/g, "text-on-surface-muted");
|
|
453
|
+
}
|
|
454
|
+
}
|
|
342
455
|
function sanitizeSemanticColors(html) {
|
|
343
456
|
let result = html;
|
|
344
457
|
for (const [pattern, replacement] of neutralReplacements) {
|
|
345
458
|
result = result.replace(pattern, replacement);
|
|
346
459
|
}
|
|
460
|
+
for (const [pattern, replacement] of textSeedReplacements) {
|
|
461
|
+
result = result.replace(pattern, replacement);
|
|
462
|
+
}
|
|
347
463
|
const hasSemanticClasses = /\b(?:bg-primary|bg-secondary|bg-accent|bg-surface)\b/.test(result);
|
|
348
464
|
if (!hasSemanticClasses) {
|
|
349
465
|
for (const [pattern, replacer] of chromaticReplacements) {
|
|
350
466
|
result = result.replace(pattern, replacer);
|
|
351
467
|
}
|
|
352
468
|
}
|
|
469
|
+
result = ancestorAwareTextPass(result);
|
|
353
470
|
return result;
|
|
354
471
|
}
|
|
355
472
|
|
|
@@ -793,4 +910,4 @@ export {
|
|
|
793
910
|
enrichSectionIconSlots,
|
|
794
911
|
streamGenerate
|
|
795
912
|
};
|
|
796
|
-
//# sourceMappingURL=chunk-
|
|
913
|
+
//# sourceMappingURL=chunk-32JWNJFY.js.map
|
|
@@ -0,0 +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/images/enrichIcons.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 { enrichSectionIcons } from \"./images/enrichIcons\";\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\n/** Enrich a section's icon placeholders (data-icon-query → Iconify SVGs). Mutates section.html in place. */\nexport async function enrichSectionIconSlots(\n section: Section3,\n opts?: { onImageUpdate?: (sectionId: string, html: string) => void }\n): Promise<void> {\n const before = section.html;\n section.html = await enrichSectionIcons(section.html);\n if (section.html !== before) {\n opts?.onImageUpdate?.(section.id, section.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 // Enrich icons (data-icon-query → real SVGs from Iconify)\n imagePromises.push(\n (async () => {\n const before = section.html;\n section.html = await enrichSectionIcons(section.html);\n if (section.html !== before) {\n onImageUpdate?.(section.id, section.html);\n }\n })()\n );\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","interface IconMatch {\n query: string;\n fullMatch: string;\n}\n\nconst ICON_PREFIXES = [\"lucide\", \"heroicons\", \"material-symbols\"] as const;\n\nconst iconCache = new Map<string, string | null>();\n\n/**\n * Find all `data-icon-query=\"name\"` spans in HTML.\n */\nexport function findIconSlots(html: string): IconMatch[] {\n const matches: IconMatch[] = [];\n const regex = /<span\\s[^>]*data-icon-query=\"([^\"]+)\"[^>]*><\\/span>/gi;\n let m: RegExpExecArray | null;\n while ((m = regex.exec(html)) !== null) {\n matches.push({ query: m[1], fullMatch: m[0] });\n }\n return matches;\n}\n\n/**\n * Fetch an SVG icon from Iconify API, trying multiple icon sets.\n */\nasync function fetchIcon(name: string): Promise<string | null> {\n if (iconCache.has(name)) return iconCache.get(name)!;\n\n for (const prefix of ICON_PREFIXES) {\n try {\n const url = `https://api.iconify.design/${prefix}/${name}.svg?height=1em&color=currentColor`;\n const res = await fetch(url);\n if (res.ok) {\n const svg = await res.text();\n if (svg.startsWith(\"<svg\")) {\n iconCache.set(name, svg);\n return svg;\n }\n }\n } catch {\n // try next prefix\n }\n }\n\n iconCache.set(name, null);\n return null;\n}\n\n/**\n * Replace all `data-icon-query` spans with real inline SVGs from Iconify.\n */\nexport async function enrichSectionIcons(html: string): Promise<string> {\n const slots = findIconSlots(html);\n if (slots.length === 0) return html;\n\n // Dedupe queries\n const uniqueQueries = [...new Set(slots.map((s) => s.query))];\n const resolved = await Promise.allSettled(\n uniqueQueries.map(async (query) => {\n const svg = await fetchIcon(query);\n return { query, svg };\n })\n );\n\n const svgMap = new Map<string, string>();\n for (const r of resolved) {\n if (r.status === \"fulfilled\" && r.value.svg) {\n svgMap.set(r.value.query, r.value.svg);\n }\n }\n\n let result = html;\n for (const slot of slots) {\n const svg = svgMap.get(slot.query);\n if (!svg) continue;\n\n // Extract classes from the original span to apply to the SVG\n const classMatch = slot.fullMatch.match(/class=\"([^\"]*)\"/);\n const classes = classMatch?.[1] || \"inline-block w-5 h-5\";\n\n // Add classes to the SVG element\n const svgWithClasses = svg.replace(\"<svg\", `<svg class=\"${classes}\"`);\n result = result.replace(slot.fullMatch, svgWithClasses);\n }\n\n return result;\n}\n","/**\n * Replace hardcoded Tailwind color classes with semantic color classes.\n *\n * Three layers:\n * 1. Neutral bg replacements: bg-white → bg-surface, bg-gray-900 → bg-primary-dark, etc.\n * 2. Chromatic replacements: bg-blue-500 → bg-secondary, bg-green-500 → bg-accent, etc.\n * (only if the AI didn't already use semantic classes)\n * 3. Ancestor-aware text-color pass: walks the DOM with a stack of effective\n * background family (primary | secondary | accent | surface) and rewrites\n * every text-* that conflicts with its ancestor bg. This fixes \"black-on-black\"\n * and \"text-on-primary on bg-surface\" invisible-text bugs regardless of theme.\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 bg replacements (text rewrites moved to ancestor-aware walker) ──\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\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 // hover:bg neutrals\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\n// Hardcoded text colors get a SEEDED rewrite to text-on-surface (the default fallback).\n// The ancestor-aware walker will then re-target them to the correct on-X variant.\nconst textSeedReplacements: [RegExp, string][] = [\n [/\\btext-white\\b/g, \"text-on-surface-LIGHT\"], // marker: \"was light text\"\n [/\\btext-black\\b/g, \"text-on-surface-DARK\"], // marker: \"was dark text\"\n [new RegExp(`\\\\btext-(${NEUTRALS})-(50|100|200)\\\\b`, \"g\"), \"text-on-surface-LIGHT\"],\n [new RegExp(`\\\\btext-(${NEUTRALS})-(300|400|500|600)\\\\b`, \"g\"), \"text-on-surface-MUTED\"],\n [new RegExp(`\\\\btext-(${NEUTRALS})-(700|800|900|950)\\\\b`, \"g\"), \"text-on-surface-DARK\"],\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\n// ==================== ANCESTOR-AWARE WALKER ====================\n\ntype BgFamily = \"primary\" | \"secondary\" | \"accent\" | \"surface\" | null;\n\nconst VOID_TAGS = new Set([\n \"br\", \"hr\", \"img\", \"input\", \"meta\", \"link\", \"area\", \"base\", \"col\",\n \"embed\", \"source\", \"track\", \"wbr\",\n]);\n\n/** Parse a class string and determine the effective bg family (ignoring state variants like hover:).\n * Returns null for low-opacity tints (< 50%) — those are overlays that pass the ancestor bg through,\n * so the text color should be decided against the real ancestor, not the tint.\n */\nfunction detectBgFamily(classStr: string): BgFamily {\n const tokens = classStr.split(/\\s+/).filter((c) => c && !c.includes(\":\"));\n // Last-wins: if an element has multiple bg classes, the rightmost one should reflect intent.\n let found: BgFamily = null;\n for (const t of tokens) {\n // Extract opacity suffix if present (e.g. \"/10\", \"/50\") and ignore anything below 50 —\n // those look through to the ancestor bg and should NOT be treated as a solid background.\n const opMatch = t.match(/\\/(\\d{1,3})$/);\n if (opMatch) {\n const op = parseInt(opMatch[1], 10);\n if (op < 50) continue;\n }\n if (/^bg-primary(?:-light|-dark)?(?:\\/\\d+)?$/.test(t)) found = \"primary\";\n else if (/^bg-secondary(?:\\/\\d+)?$/.test(t)) found = \"secondary\";\n else if (/^bg-accent(?:\\/\\d+)?$/.test(t)) found = \"accent\";\n else if (/^bg-surface(?:-alt)?(?:\\/\\d+)?$/.test(t)) found = \"surface\";\n }\n if (found) return found;\n // Gradient: infer from from-X stop (only when bg-gradient is present)\n if (tokens.some((t) => /^bg-gradient-/.test(t))) {\n for (const t of tokens) {\n const m = t.match(/^from-(primary|secondary|accent|surface)(?:-light|-dark|-alt)?(?:\\/\\d+)?$/);\n if (m) return m[1] as BgFamily;\n }\n }\n return null;\n}\n\n/** Walk the stack bottom-to-top to find the nearest defined bg family; default to surface. */\nfunction effectiveBg(stack: BgFamily[]): Exclude<BgFamily, null> {\n for (let i = stack.length - 1; i >= 0; i--) {\n const v = stack[i];\n if (v !== null) return v;\n }\n return \"surface\";\n}\n\nfunction onClass(bg: Exclude<BgFamily, null>): string {\n return `text-on-${bg}`;\n}\n\nfunction onMutedClass(bg: Exclude<BgFamily, null>): string {\n return bg === \"surface\" ? \"text-on-surface-muted\" : `text-on-${bg}`;\n}\n\n/** Rewrite text-* classes inside a single element's class string based on its effective bg. */\nfunction fixTextClassesForBg(classStr: string, bg: Exclude<BgFamily, null>): string {\n let s = classStr;\n const on = onClass(bg);\n const onMuted = onMutedClass(bg);\n\n // Seeded markers from pass 1 → resolve to correct on-X for this ancestor\n s = s.replace(/\\btext-on-surface-LIGHT\\b/g, on);\n s = s.replace(/\\btext-on-surface-DARK\\b/g, on);\n s = s.replace(/\\btext-on-surface-MUTED\\b/g, onMuted);\n\n // Re-target mis-assigned on-X classes (e.g. text-on-primary inside bg-surface)\n if (bg === \"primary\") {\n s = s.replace(/\\btext-on-surface(?:-muted)?\\b/g, \"text-on-primary\");\n s = s.replace(/\\btext-on-secondary\\b/g, \"text-on-primary\");\n s = s.replace(/\\btext-on-accent\\b/g, \"text-on-primary\");\n // text-primary on bg-primary is INVISIBLE (same hue) — rewrite to on-primary\n s = s.replace(/\\btext-primary(?!-(?:light|dark))\\b/g, \"text-on-primary\");\n } else if (bg === \"secondary\") {\n s = s.replace(/\\btext-on-surface(?:-muted)?\\b/g, \"text-on-secondary\");\n s = s.replace(/\\btext-on-primary\\b/g, \"text-on-secondary\");\n s = s.replace(/\\btext-on-accent\\b/g, \"text-on-secondary\");\n s = s.replace(/\\btext-secondary\\b/g, \"text-on-secondary\");\n } else if (bg === \"accent\") {\n s = s.replace(/\\btext-on-surface(?:-muted)?\\b/g, \"text-on-accent\");\n s = s.replace(/\\btext-on-primary\\b/g, \"text-on-accent\");\n s = s.replace(/\\btext-on-secondary\\b/g, \"text-on-accent\");\n s = s.replace(/\\btext-accent\\b/g, \"text-on-accent\");\n } else {\n // bg === \"surface\" — text-on-primary/secondary/accent likely invisible on surface\n s = s.replace(/\\btext-on-primary\\b/g, \"text-on-surface\");\n s = s.replace(/\\btext-on-secondary\\b/g, \"text-on-surface\");\n s = s.replace(/\\btext-on-accent\\b/g, \"text-on-surface\");\n }\n\n return s;\n}\n\n/** Ancestor-aware pass: walk HTML, maintain bg stack, rewrite text-* per element. */\nfunction ancestorAwareTextPass(html: string): string {\n try {\n const tagRe = /<(\\/?)([a-zA-Z][a-zA-Z0-9]*)\\b([^>]*?)(\\/?)>/g;\n const stack: BgFamily[] = [];\n let out = \"\";\n let lastIdx = 0;\n let m: RegExpExecArray | null;\n\n while ((m = tagRe.exec(html)) !== null) {\n const [full, slash, tagName, attrs, selfCloseSlash] = m;\n out += html.slice(lastIdx, m.index);\n lastIdx = m.index + full.length;\n\n if (slash === \"/\") {\n // Closing tag\n stack.pop();\n out += full;\n continue;\n }\n\n // Opening (or self-closing) tag\n const classMatch = attrs.match(/\\bclass=\"([^\"]*)\"/);\n const ownBg = classMatch ? detectBgFamily(classMatch[1]) : null;\n const effective: Exclude<BgFamily, null> = ownBg ?? effectiveBg(stack);\n\n let newAttrs = attrs;\n if (classMatch) {\n const fixed = fixTextClassesForBg(classMatch[1], effective);\n if (fixed !== classMatch[1]) {\n newAttrs = attrs.replace(/\\bclass=\"[^\"]*\"/, `class=\"${fixed}\"`);\n }\n }\n out += `<${tagName}${newAttrs}${selfCloseSlash}>`;\n\n const isVoid = VOID_TAGS.has(tagName.toLowerCase()) || selfCloseSlash === \"/\";\n if (!isVoid) stack.push(ownBg);\n }\n out += html.slice(lastIdx);\n\n // Clean up any remaining markers that slipped through (e.g. in malformed fragments)\n out = out\n .replace(/\\btext-on-surface-LIGHT\\b/g, \"text-on-surface\")\n .replace(/\\btext-on-surface-DARK\\b/g, \"text-on-surface\")\n .replace(/\\btext-on-surface-MUTED\\b/g, \"text-on-surface-muted\");\n\n return out;\n } catch {\n // Defensive: if tokenizer trips on weird HTML, return input with markers stripped.\n return html\n .replace(/\\btext-on-surface-LIGHT\\b/g, \"text-on-surface\")\n .replace(/\\btext-on-surface-DARK\\b/g, \"text-on-surface\")\n .replace(/\\btext-on-surface-MUTED\\b/g, \"text-on-surface-muted\");\n }\n}\n\nexport function sanitizeSemanticColors(html: string): string {\n let result = html;\n\n // 1. Replace neutral bg classes (bg-white, bg-gray-*, etc.)\n for (const [pattern, replacement] of neutralReplacements) {\n result = result.replace(pattern, replacement);\n }\n\n // 2. Seed hardcoded text colors with markers that the walker will resolve per ancestor.\n for (const [pattern, replacement] of textSeedReplacements) {\n result = result.replace(pattern, replacement);\n }\n\n // 3. Skip chromatic sanitization if the AI already used semantic classes.\n const hasSemanticClasses = /\\b(?:bg-primary|bg-secondary|bg-accent|bg-surface)\\b/.test(result);\n if (!hasSemanticClasses) {\n for (const [pattern, replacer] of chromaticReplacements) {\n result = result.replace(pattern, replacer as any);\n }\n }\n\n // 4. Ancestor-aware pass: resolve seed markers and fix mis-matched text-on-X classes.\n result = ancestorAwareTextPass(result);\n\n return result;\n}\n"],"mappings":"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","names":["createAnthropic","openaiKey","anthropicKey","createAnthropic"]}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
resolveModel,
|
|
11
11
|
sanitizeSemanticColors,
|
|
12
12
|
streamGenerate
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-32JWNJFY.js";
|
|
14
14
|
|
|
15
15
|
// src/generateDocument.ts
|
|
16
16
|
import { generateObject, streamText } from "ai";
|
|
@@ -556,4 +556,4 @@ export {
|
|
|
556
556
|
generateDocument,
|
|
557
557
|
generateDocumentParallel
|
|
558
558
|
};
|
|
559
|
-
//# sourceMappingURL=chunk-
|
|
559
|
+
//# sourceMappingURL=chunk-B3TDPWJD.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
enrichImages,
|
|
4
4
|
resolveModel,
|
|
5
5
|
sanitizeSemanticColors
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-32JWNJFY.js";
|
|
7
7
|
import {
|
|
8
8
|
buildThemePromptContext
|
|
9
9
|
} from "./chunk-VV5I53WR.js";
|
|
@@ -161,4 +161,4 @@ export {
|
|
|
161
161
|
extractSectionDescription,
|
|
162
162
|
refineLanding
|
|
163
163
|
};
|
|
164
|
-
//# sourceMappingURL=chunk-
|
|
164
|
+
//# sourceMappingURL=chunk-QSEPSXL7.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
dataUrlToImagePart,
|
|
3
3
|
streamGenerate
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-32JWNJFY.js";
|
|
5
5
|
import {
|
|
6
6
|
buildThemePromptContext
|
|
7
7
|
} from "./chunk-VV5I53WR.js";
|
|
@@ -196,4 +196,4 @@ export {
|
|
|
196
196
|
PROMPT_SUFFIX,
|
|
197
197
|
generateLanding
|
|
198
198
|
};
|
|
199
|
-
//# sourceMappingURL=chunk-
|
|
199
|
+
//# sourceMappingURL=chunk-UQELTLRO.js.map
|
package/dist/directions.js
CHANGED
package/dist/generate.js
CHANGED
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
PROMPT_SUFFIX,
|
|
3
3
|
SYSTEM_PROMPT,
|
|
4
4
|
generateLanding
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-UQELTLRO.js";
|
|
6
6
|
import {
|
|
7
7
|
extractJsonObjects
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-32JWNJFY.js";
|
|
9
9
|
import "./chunk-VV5I53WR.js";
|
|
10
10
|
export {
|
|
11
11
|
PROMPT_SUFFIX,
|
package/dist/generateDocument.js
CHANGED
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
generateDocumentParallel,
|
|
7
7
|
getDocumentPromptSuffix,
|
|
8
8
|
getDocumentSystemPrompt
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-B3TDPWJD.js";
|
|
10
|
+
import "./chunk-32JWNJFY.js";
|
|
11
11
|
export {
|
|
12
12
|
DOCUMENT_PROMPT_SUFFIX,
|
|
13
13
|
DOCUMENT_SYSTEM_PROMPT,
|
package/dist/images.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -19,16 +19,16 @@ import {
|
|
|
19
19
|
PROMPT_SUFFIX,
|
|
20
20
|
SYSTEM_PROMPT,
|
|
21
21
|
generateLanding
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-UQELTLRO.js";
|
|
23
23
|
import {
|
|
24
24
|
DOCUMENT_PROMPT_SUFFIX,
|
|
25
25
|
DOCUMENT_SYSTEM_PROMPT,
|
|
26
26
|
generateDocument
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-B3TDPWJD.js";
|
|
28
28
|
import {
|
|
29
29
|
REFINE_SYSTEM,
|
|
30
30
|
refineLanding
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-QSEPSXL7.js";
|
|
32
32
|
import {
|
|
33
33
|
enrichImages,
|
|
34
34
|
extractJsonObjects,
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
generateImage,
|
|
37
37
|
generateSvg,
|
|
38
38
|
searchImage
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-32JWNJFY.js";
|
|
40
40
|
import {
|
|
41
41
|
deployToEasyBits,
|
|
42
42
|
deployToS3
|
package/dist/refine.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easybits.cloud/html-tailwind-generator",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.134",
|
|
4
4
|
"description": "AI-powered landing page generator with Tailwind CSS — canvas editor, streaming generation, and one-click deploy",
|
|
5
5
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
6
6
|
"type": "module",
|
|
@@ -75,10 +75,10 @@
|
|
|
75
75
|
"@codemirror/theme-one-dark": ">=6",
|
|
76
76
|
"@codemirror/view": ">=6",
|
|
77
77
|
"ai": ">=4",
|
|
78
|
+
"grapesjs": ">=0.21",
|
|
78
79
|
"react": ">=18",
|
|
79
80
|
"react-dom": ">=18",
|
|
80
81
|
"react-icons": ">=5",
|
|
81
|
-
"grapesjs": ">=0.21",
|
|
82
82
|
"tailwind-merge": ">=2"
|
|
83
83
|
},
|
|
84
84
|
"peerDependenciesMeta": {
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
}
|
|
124
124
|
},
|
|
125
125
|
"dependencies": {
|
|
126
|
-
"@easybits.cloud/html-tailwind-generator": "^0.2.
|
|
126
|
+
"@easybits.cloud/html-tailwind-generator": "^0.2.132",
|
|
127
127
|
"nanoid": "^5.1.5"
|
|
128
128
|
},
|
|
129
129
|
"devDependencies": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/images/pexels.ts","../src/images/dalleImages.ts","../src/images/enrichImages.ts","../src/images/svgGenerator.ts","../src/streamCore.ts","../src/images/enrichIcons.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 { enrichSectionIcons } from \"./images/enrichIcons\";\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\n/** Enrich a section's icon placeholders (data-icon-query → Iconify SVGs). Mutates section.html in place. */\nexport async function enrichSectionIconSlots(\n section: Section3,\n opts?: { onImageUpdate?: (sectionId: string, html: string) => void }\n): Promise<void> {\n const before = section.html;\n section.html = await enrichSectionIcons(section.html);\n if (section.html !== before) {\n opts?.onImageUpdate?.(section.id, section.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 // Enrich icons (data-icon-query → real SVGs from Iconify)\n imagePromises.push(\n (async () => {\n const before = section.html;\n section.html = await enrichSectionIcons(section.html);\n if (section.html !== before) {\n onImageUpdate?.(section.id, section.html);\n }\n })()\n );\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","interface IconMatch {\n query: string;\n fullMatch: string;\n}\n\nconst ICON_PREFIXES = [\"lucide\", \"heroicons\", \"material-symbols\"] as const;\n\nconst iconCache = new Map<string, string | null>();\n\n/**\n * Find all `data-icon-query=\"name\"` spans in HTML.\n */\nexport function findIconSlots(html: string): IconMatch[] {\n const matches: IconMatch[] = [];\n const regex = /<span\\s[^>]*data-icon-query=\"([^\"]+)\"[^>]*><\\/span>/gi;\n let m: RegExpExecArray | null;\n while ((m = regex.exec(html)) !== null) {\n matches.push({ query: m[1], fullMatch: m[0] });\n }\n return matches;\n}\n\n/**\n * Fetch an SVG icon from Iconify API, trying multiple icon sets.\n */\nasync function fetchIcon(name: string): Promise<string | null> {\n if (iconCache.has(name)) return iconCache.get(name)!;\n\n for (const prefix of ICON_PREFIXES) {\n try {\n const url = `https://api.iconify.design/${prefix}/${name}.svg?height=1em&color=currentColor`;\n const res = await fetch(url);\n if (res.ok) {\n const svg = await res.text();\n if (svg.startsWith(\"<svg\")) {\n iconCache.set(name, svg);\n return svg;\n }\n }\n } catch {\n // try next prefix\n }\n }\n\n iconCache.set(name, null);\n return null;\n}\n\n/**\n * Replace all `data-icon-query` spans with real inline SVGs from Iconify.\n */\nexport async function enrichSectionIcons(html: string): Promise<string> {\n const slots = findIconSlots(html);\n if (slots.length === 0) return html;\n\n // Dedupe queries\n const uniqueQueries = [...new Set(slots.map((s) => s.query))];\n const resolved = await Promise.allSettled(\n uniqueQueries.map(async (query) => {\n const svg = await fetchIcon(query);\n return { query, svg };\n })\n );\n\n const svgMap = new Map<string, string>();\n for (const r of resolved) {\n if (r.status === \"fulfilled\" && r.value.svg) {\n svgMap.set(r.value.query, r.value.svg);\n }\n }\n\n let result = html;\n for (const slot of slots) {\n const svg = svgMap.get(slot.query);\n if (!svg) continue;\n\n // Extract classes from the original span to apply to the SVG\n const classMatch = slot.fullMatch.match(/class=\"([^\"]*)\"/);\n const classes = classMatch?.[1] || \"inline-block w-5 h-5\";\n\n // Add classes to the SVG element\n const svgWithClasses = svg.replace(\"<svg\", `<svg class=\"${classes}\"`);\n result = result.replace(slot.fullMatch, svgWithClasses);\n }\n\n return result;\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":"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","names":["createAnthropic","openaiKey","anthropicKey","createAnthropic"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|