|
1 | 1 | import React from "react"; |
2 | 2 | import { useLLMGeneration } from "./useLLMGeneration.js"; |
| 3 | +export const SYSTEM_PROMPT = `You are a specialized HTML generator that creates complete, production-ready HTML using ONLY Tailwind CSS classes. |
| 4 | +
|
| 5 | +IMPORTANT: |
| 6 | +- Use EXCLUSIVELY Tailwind CSS classes for ALL styling - NO style attributes or style tags |
| 7 | +- Every visual styling must be done through Tailwind classes |
| 8 | +- Never use inline styles, CSS, or style tags |
| 9 | +- If you need a style that seems custom, use Tailwind's arbitrary value syntax like [w-123px] |
| 10 | +- Always write out the full, actual HTML elements with real content |
| 11 | +- Never use Lorem Ipsum - write realistic English content |
| 12 | +- Never include code comments or explanations |
| 13 | +- DO NOT wrap the output in markdown code blocks |
| 14 | +
|
| 15 | +STRICT STYLING RULES: |
| 16 | +- ❌ NO <style> tags |
| 17 | +- ❌ NO style="" attributes |
| 18 | +- ❌ NO CSS classes that aren't Tailwind |
| 19 | +- ✅ ONLY use Tailwind utility classes |
| 20 | +- ✅ Use Tailwind's arbitrary value syntax for custom values |
| 21 | +- ✅ Stack multiple Tailwind classes to achieve desired styling |
| 22 | +
|
| 23 | +Requirements: |
| 24 | +- Generate ONLY the HTML content for inside the <body> tag |
| 25 | +- EXCLUSIVELY use Tailwind CSS classes for ALL styling |
| 26 | +- NO placeholders, NO comments, NO explanations |
| 27 | +- NO server-side code or JavaScript |
| 28 | +- Every element must be complete with real content |
| 29 | +- Write out all actual HTML elements - never indicate "pending" or "todo" sections |
| 30 | +- DO NOT wrap the output in markdown code blocks |
| 31 | +
|
| 32 | +Example of CORRECT styling: |
| 33 | +<div class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> |
| 34 | +Instead of: |
| 35 | +<div style="background: blue; color: white;"> |
| 36 | +
|
| 37 | +Generate complete, functional HTML using ONLY Tailwind classes for styling.`; |
| 38 | + |
| 39 | +function cleanHtmlCode(fullHtml) { |
| 40 | + // First remove markdown code blocks |
| 41 | + let cleaned = fullHtml |
| 42 | + .replace(/```html/gi, "") |
| 43 | + .replace(/```(\s+)?html/gi, "") |
| 44 | + .replace(/```(\n)?html/gi, "") |
| 45 | + .replace(/```/g, "") |
| 46 | + .trim(); |
| 47 | + |
| 48 | + // If the content is already wrapped in our template, extract just the content |
| 49 | + const templateContentMatch = cleaned.match( |
| 50 | + /CONTENT_PLACEHOLDER">\s*([\s\S]*?)\s*<\/body>/i |
| 51 | + ); |
| 52 | + if (templateContentMatch) { |
| 53 | + return templateContentMatch[1].trim(); |
| 54 | + } |
| 55 | + |
| 56 | + // Try to extract content between body tags |
| 57 | + const bodyContent = cleaned.match(/<body[^>]*>\s*([\s\S]*?)\s*<\/body>/i); |
| 58 | + if (bodyContent) { |
| 59 | + // Further clean the body content of any nested body tags |
| 60 | + return bodyContent[1] |
| 61 | + .replace(/<\/?body[^>]*>/gi, "") // Remove any nested body tags |
| 62 | + .trim(); |
| 63 | + } |
| 64 | + |
| 65 | + // If no body tags found, remove any DOCTYPE and html wrapper if present |
| 66 | + cleaned = cleaned |
| 67 | + .replace(/<!DOCTYPE[^>]*>/gi, "") |
| 68 | + .replace(/<\/?html[^>]*>/gi, "") |
| 69 | + .replace(/<\/?body[^>]*>/gi, "") |
| 70 | + .replace(/<head>[\s\S]*?<\/head>/gi, "") |
| 71 | + .trim(); |
| 72 | + |
| 73 | + return cleaned; |
| 74 | +} |
3 | 75 |
|
4 | | -export const SYSTEM_PROMPT = `You are a specialized HTML generator that creates complete, production-ready HTML using ONLY Tailwind CSS classes.`; |
5 | 76 |
|
6 | 77 | export function useLLMVisionGeneration({ |
7 | 78 | modelConfig, |
8 | 79 | backend = 'qwen2vl', |
9 | 80 | systemPrompt = SYSTEM_PROMPT, |
10 | 81 | }) { |
11 | | - const [generatedText, setGeneratedText] = React.useState(""); |
12 | | - const lastGeneratedText = React.useRef(""); |
| 82 | + const [generatedText, setgeneratedText] = React.useState(""); |
| 83 | + const lastgeneratedText = React.useRef(""); |
13 | 84 |
|
14 | 85 | const { generate, isGenerating, error, partialText } = useLLMGeneration( |
15 | 86 | modelConfig, |
16 | 87 | systemPrompt, |
17 | | - backend, |
| 88 | + backend |
18 | 89 | ); |
19 | 90 |
|
20 | 91 | React.useEffect(() => { |
21 | 92 | if (partialText) { |
22 | | - setGeneratedText(partialText); |
23 | | - lastGeneratedText.current = partialText; |
| 93 | + const cleaned = cleanHtmlCode(partialText); |
| 94 | + const processedCode = cleaned; |
| 95 | + setgeneratedText(processedCode); |
| 96 | + lastgeneratedText.current = cleaned; // Store just the body content |
24 | 97 | } |
25 | 98 | }, [partialText]); |
26 | 99 |
|
27 | 100 | const generateText = React.useCallback( |
28 | | - async (prompt, extras) => { |
29 | | - const fullPrompt = lastGeneratedText.current |
30 | | - ? `Current Chat: \n${lastGeneratedCode.current}\n\nRequest: ${prompt}` |
31 | | - : `${prompt} `; |
| 101 | + async (prompt) => { |
| 102 | + const fullPrompt = lastgeneratedText.current |
| 103 | + ? `Current HTML: \n${lastgeneratedText.current}\n\nRequest: ${prompt}` |
| 104 | + : `Generate the HTML for: ${prompt}`; |
32 | 105 |
|
33 | | - await generate(fullPrompt, extras); |
| 106 | + console.log({ fullPrompt }); |
| 107 | + await generate(fullPrompt); |
34 | 108 | }, |
35 | 109 | [generate] |
36 | 110 | ); |
|
0 commit comments