File size: 13,008 Bytes
5987614
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24c2853
5987614
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24c2853
5987614
 
 
 
 
 
 
 
 
 
 
 
 
d2e2bdc
5987614
 
f238294
bdd9f2a
d2e2bdc
5987614
f238294
5987614
 
f238294
bdd9f2a
d2e2bdc
bdd9f2a
f238294
5987614
 
 
d2e2bdc
24c2853
6de726e
 
f238294
 
6de726e
f238294
6de726e
 
f238294
6de726e
 
 
24c2853
3395169
24c2853
 
f238294
6de726e
 
 
f238294
6de726e
 
 
 
 
 
 
 
24c2853
6de726e
f238294
5987614
 
 
 
 
 
 
 
 
 
 
 
24c2853
 
 
 
3395169
6de726e
 
24c2853
6de726e
5987614
d2e2bdc
 
 
 
 
 
5987614
 
 
 
 
 
 
d2e2bdc
5987614
 
 
6de726e
5987614
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6de726e
 
24c2853
 
 
 
 
 
 
 
 
 
 
 
 
 
6de726e
f238294
6de726e
 
 
 
 
3395169
 
6de726e
 
 
 
 
 
 
 
 
3395169
6de726e
 
 
5987614
f238294
24c2853
3395169
f238294
 
24c2853
3395169
f238294
 
24c2853
3395169
f238294
5987614
d2e2bdc
5987614
 
 
6de726e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
import gradio as gr
import requests
import os
import re

SYSTEM_PROMPT = """You are an expert UI/UX designer specializing in redesigning HTML components with TailwindCSS. Transform the input HTML into a cleaner, more modern version with focus on spacing and layout precision.

Core Design Philosophy:
- SPACING FIRST: Prioritize proper spacing over complex styling
- PRESERVE EXISTING: Maintain the original color scheme and fonts when they exist
- SIMPLE & CLEAN: Focus on clean, minimal designs rather than overly decorative ones
- FLEXIBLE LAYOUTS: Use flexbox with proper flex properties for better control

Spacing & Layout Rules:
- Use consistent spacing scales: p-4, p-6, p-8 for padding; m-4, m-6, m-8 for margins
- Apply gap-4, gap-6, or gap-8 for flex/grid container spacing
- Use space-y-4, space-y-6 for vertical stacking
- Add flex-none to elements that should NOT stretch (buttons, labels, icons, fixed-width items)
- Use flex-1 or flex-auto only for elements that should grow/stretch
- Prefer specific widths (w-32, w-48, w-64) over arbitrary values

Color & Typography Preservation:
- ANALYZE the input HTML for existing color schemes (bg-*, text-*, border-*)
- REUSE those exact color classes in the redesigned version
- If input uses blue-500, continue using blue-* variants throughout
- If input has specific font classes (font-medium, text-lg), maintain that typography scale
- MANDATORY: ALWAYS add text-balance class to ALL titles and headings (h1, h2, h3, h4, h5, h6, and any element with large text like text-xl, text-2xl, etc.) for better text wrapping and visual balance
- Only introduce new colors if the original has none or uses basic colors

Dark Mode Support:
- DETECT dark mode classes in input (dark:*, bg-gray-900, text-white, etc.)
- If input HAS dark mode classes, PRESERVE and EXTEND them in the redesign
- If input has dark:bg-gray-800, continue using dark:* variants throughout
- If input has NO dark mode classes, DO NOT add any dark mode styling
- Maintain the same dark mode approach as the original (toggle-based or system-based)

Design Enhancement Guidelines:
- Improve visual hierarchy with better spacing, not more colors
- Add subtle shadows (shadow-sm, shadow-md) for depth
- Use rounded corners appropriately (rounded-lg, rounded-xl)
- Add hover states with opacity or subtle color shifts
- Implement focus states with ring utilities
- Use border utilities for clean separation
- Apply proper contrast ratios for accessibility

Layout Techniques:
- Use flex with gap instead of space-x/space-y when possible
- Apply justify-between, justify-center, items-center for alignment
- Use flex-none for buttons, icons, and fixed elements
- Apply max-w-* for content width constraints
- Use grid for complex layouts, flex for simple ones

Responsive Design Rules:
- ALWAYS ensure mobile-first responsive design
- Use responsive breakpoints: sm:, md:, lg:, xl: appropriately
- Stack elements vertically on mobile, arrange horizontally on larger screens
- Apply responsive padding: p-4 sm:p-6 lg:p-8
- Use responsive text sizes: text-sm md:text-base lg:text-lg
- Implement responsive flexbox: flex-col md:flex-row
- Add responsive gaps: gap-4 md:gap-6 lg:gap-8
- Ensure buttons and inputs are touch-friendly on mobile (min-h-10, p-3)
- Use responsive widths: w-full md:w-auto or w-full md:w-1/2
- Apply responsive margins: mt-4 md:mt-0 for layout adjustments

Technical Requirements:
- Return ONLY the redesigned HTML code
- PRESERVE ALL FUNCTIONALITY: Keep every link (href), image (src), form action, onclick, etc.
- MAINTAIN ALL ATTRIBUTES: Preserve all IDs, classes, data-*, aria-*, name, value, placeholder, etc.
- KEEP ALL CONTENT: Preserve all text content, alt texts, button labels exactly as provided
- DO NOT REMOVE: Never remove links, images, inputs, buttons, or any functional elements
- DO NOT CHANGE: Keep all URLs, image sources, form targets, and JavaScript references unchanged
- ENHANCE ONLY STYLING: Only modify TailwindCSS classes for visual improvements
- PRESERVE STRUCTURE: Maintain the same HTML element hierarchy and nesting

Critical Preservation Rules:
- If input has <a href="...">Link</a>, output must have identical href and link text
- If input has <img src="..." alt="...">, output must preserve exact src and alt
- If input has form inputs with name/value/placeholder, keep them exactly the same
- If input has buttons with onclick or type attributes, preserve them completely
- If input has any data attributes (data-*), maintain them unchanged
- All original text content must remain identical
- MANDATORY TEXT-BALANCE RULE: Every heading (h1-h6) and large text element (text-xl, text-2xl, text-3xl, etc.) MUST include the text-balance class

Framework-Specific Preservation (React/Vue/Svelte/Angular):
- REACT: Preserve all JSX syntax: {variable}, {function()}, className, onClick, onChange, etc.
- VUE: Preserve all Vue directives: v-if, v-for, v-model, @click, :class, {{interpolation}}, etc.
- SVELTE: Preserve all Svelte syntax: {#if}, {#each}, on:click, bind:value, {variable}, etc.
- ANGULAR: Preserve all Angular syntax: *ngIf, *ngFor, (click), [class], {{interpolation}}, etc.
- ALPINE.JS: Preserve all Alpine directives: x-data, x-show, x-if, @click, :class, etc.
- HTMX: Preserve all HTMX attributes: hx-get, hx-post, hx-target, hx-swap, etc.
- Keep all curly braces, template literals, and dynamic expressions unchanged
- Maintain all event handlers and binding syntax exactly as provided

Focus on creating clean, spacious, and well-proportioned designs that feel premium through proper spacing rather than complex styling, while ensuring zero functional changes."""


def extract_html_from_response(response_text):
    """Extract HTML code from model response"""

    # Try to find HTML within code blocks first
    html_pattern = r"```(?:html)?\s*(.*?)```"
    matches = re.findall(html_pattern, response_text, re.DOTALL | re.IGNORECASE)

    if matches:
        return matches[0].strip()

    # If no code blocks but response contains HTML tags, return the whole response
    if re.search(r"<[^>]+>", response_text):
        return response_text.strip()

    # If no HTML found, return error
    raise ValueError("No HTML content found in the response")


def redesign_html(html_input: str, user_prompt: str = "") -> str:
    """
    Redesign HTML+TailwindCSS code with improved spacing, responsive design, and modern aesthetics.

    This tool takes existing HTML with TailwindCSS classes and transforms it into a cleaner,
    more modern version with better spacing, responsive design, and improved user experience.

    IMPORTANT: This tool should only be used when users explicitly request to "redesign" HTML code.
    Users must say "redesign" or similar intent for this tool to be activated.

    Args:
        html_input (str): The HTML code with TailwindCSS classes to be redesigned.
                         Can include React/Vue/Svelte/Angular syntax which will be preserved.
        user_prompt (str, optional): Custom instructions for the redesign process.
                                   Examples: "make it more colorful", "add animations",
                                   "make it minimal", "improve mobile layout".
                                   If empty, uses default redesign approach.

    Returns:
        str: The redesigned HTML code with improved TailwindCSS styling, preserving all
             functionality, links, images, and framework-specific syntax.

    Features:
    - Preserves all functionality (links, images, forms, JavaScript)
    - Maintains framework syntax (React JSX, Vue directives, etc.)
    - Improves spacing and responsive design
    - Preserves existing color schemes and fonts
    - Adds proper flex-none for non-stretching elements
    - Ensures mobile-first responsive design
    - Supports dark mode when present in input
    - Accepts custom user instructions for targeted redesign approaches
    """

    # Check if HF_TOKEN is set
    hf_token = os.getenv("HF_TOKEN")
    if not hf_token:
        return "Error: HF_TOKEN environment variable not set. Please set your HuggingFace token."

    # Prepare the API request
    url = "https://router.huggingface.co/sambanova/v1/chat/completions"
    headers = {
        "Authorization": f"Bearer {hf_token}",
        "Content-Type": "application/json",
    }

    # Build messages with system prompt and user prompt
    user_content = html_input
    if user_prompt.strip():
        user_content = f"User instructions: {user_prompt.strip()}\n\nHTML to redesign:\n{html_input}"

    messages = [
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": user_content},
    ]

    data = {
        "messages": messages,
        "model": "DeepSeek-V3-0324",
        "stream": False,
        "temperature": 0.8,
    }

    try:
        response = requests.post(url, headers=headers, json=data, timeout=30)
        response.raise_for_status()

        result = response.json()
        response_content = result["choices"][0]["message"]["content"]

        # Extract HTML from the response
        try:
            html_content = extract_html_from_response(response_content)
            return html_content
        except ValueError as e:
            return f"Error: {str(e)}. Response was: {response_content[:200]}..."

    except requests.exceptions.RequestException as e:
        return f"Error: Failed to connect to API - {str(e)}"
    except KeyError as e:
        return f"Error: Unexpected API response format - {str(e)}"
    except Exception as e:
        return f"Error: {str(e)}"


# Custom CSS for better HTML code display
custom_css = """
<style>
/* Better formatting for HTML code display */
.message-wrap .prose {
    max-width: none !important;
}
.message-wrap pre {
    white-space: pre-wrap !important;
    word-break: break-all !important;
    background: #1e1e1e !important;
    color: #d4d4d4 !important;
    padding: 16px !important;
    border-radius: 8px !important;
    border: 1px solid #333 !important;
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important;
    font-size: 14px !important;
    line-height: 1.5 !important;
}
</style>
"""

# Create Gradio interface
demo = gr.Interface(
    fn=redesign_html,
    inputs=[
        gr.Textbox(
            label="Custom Instructions (Optional)",
            placeholder="Enter specific instructions for the redesign (e.g., 'make it more colorful', 'add animations', 'make it minimal')...",
            lines=2,
            value="",
        ),
        gr.Textbox(
            label="HTML Input",
            placeholder="Paste your HTML+TailwindCSS code here...",
            lines=10,
            value='<div class="p-4 border"><h1 class="text-xl">Welcome</h1><p>This is a basic card</p><button class="bg-blue-500 text-white px-4 py-2">Click me</button></div>',
        ),
    ],
    outputs=gr.Code(language="html", label="Redesigned HTML"),
    title="Redesigner (MCP Server)",
    description="""
    **MCP Server Tool for HTML Redesigning**
    
    This is an MCP (Model Context Protocol) server that provides HTML redesign capabilities to LLMs.
    
    **Powered by DeepSeek-V3-0324** - An advanced model specifically excellent at UI/UX design tasks.
    
    **IMPORTANT FOR LLM USAGE:** This tool should only be activated when users explicitly request to "redesign" HTML code. 
    Users must use the word "redesign" or similar intent (e.g., "improve the design", "make it look better") for this tool to be used.
    
    **Features:**
    - Improves HTML+TailwindCSS with better spacing and responsive design
    - Preserves all functionality (links, images, forms, JavaScript)
    - Maintains framework syntax (React, Vue, Svelte, Angular)
    - Supports dark mode when present in input
    - Mobile-first responsive design implementation
    - Custom user instructions for targeted redesign approaches
    
    **Usage:** LLMs can use this tool when users ask to redesign HTML code by providing the HTML as input.
    """,
    examples=[
        [
            "Make it more modern and colorful",
            '<div class="p-4 border"><h1 class="text-xl">Welcome</h1><p>This is a basic card</p><button class="bg-blue-500 text-white px-4 py-2">Click me</button></div>',
        ],
        [
            "Add subtle animations and improve spacing",
            '<form class="space-y-4"><input type="email" placeholder="Email" class="border p-2 w-full"><input type="password" placeholder="Password" class="border p-2 w-full"><button type="submit" class="bg-green-500 text-white p-2">Login</button></form>',
        ],
        [
            "",
            '<nav class="flex justify-between p-4 bg-gray-100"><div class="font-bold">Logo</div><ul class="flex space-x-4"><li><a href="#" class="text-blue-500">Home</a></li><li><a href="#" class="text-blue-500">About</a></li></ul></nav>',
        ],
    ],
    css=custom_css,
)

if __name__ == "__main__":
    demo.launch(mcp_server=True)