AiCoderv2's picture
Update app.py from anycoder
8ca1c31 verified
import gradio as gr
import time
import random
import re
from typing import List, Dict, Any
import json
def generate_website_code(description: str, complexity: str, color_scheme: str = "Blue", layout_style: str = "Modern") -> Dict[str, str]:
"""
Enhanced AI website generation with multiple customization options.
"""
start_time = time.time()
# Generate HTML, CSS, and JS with new features
description_lower = description.lower()
# Smart template selection
if "portfolio" in description_lower or "personal" in description_lower:
html_code = generate_portfolio_site(description, color_scheme, layout_style)
elif "business" in description_lower or "company" in description_lower:
html_code = generate_business_site(description, color_scheme, layout_style)
elif "blog" in description_lower:
html_code = generate_blog_site(description, color_scheme, layout_style)
elif "landing" in description_lower or "product" in description_lower:
html_code = generate_landing_site(description, color_scheme, layout_style)
elif "ecommerce" in description_lower or "shop" in description_lower or "store" in description_lower:
html_code = generate_ecommerce_site(description, color_scheme, layout_style)
else:
html_code = generate_simple_site(description, color_scheme, layout_style)
css_code = generate_enhanced_css(complexity, color_scheme, layout_style)
js_code = generate_enhanced_javascript(complexity)
# Add SEO and accessibility features
html_code = enhance_html_with_seo_accessibility(html_code, description)
# Code quality analysis
quality_metrics = analyze_code_quality(html_code, css_code, js_code)
generation_time = time.time() - start_time
return {
"html": html_code,
"css": css_code,
"javascript": js_code,
"generation_time": f"{generation_time:.2f}s",
"quality_score": f"{quality_metrics['score']}/100",
"performance_tips": quality_metrics['tips'],
"accessibility_score": f"{quality_metrics['accessibility']}/100",
"seo_score": f"{quality_metrics['seo']}/100",
"status": "βœ… Website generated successfully!" if generation_time < 15 else "⚠️ Generation took longer than expected"
}
def generate_ecommerce_site(description: str, color_scheme: str, layout_style: str) -> str:
"""Generate an e-commerce website template"""
return f'''<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>E-Commerce Store - Generated Website</title>
<link rel="stylesheet" href="style.css">
<meta name="description" content="Generated e-commerce store based on: {description}">
</head>
<body>
<header>
<nav>
<div class="logo">ShopNow</div>
<div class="search-bar">
<input type="text" placeholder="Search products..." aria-label="Search products">
<button class="search-btn" aria-label="Search">πŸ”</button>
</div>
<div class="nav-icons">
<button class="icon-btn" aria-label="User account">πŸ‘€</button>
<button class="icon-btn cart-btn" aria-label="Shopping cart">πŸ›’ <span class="cart-count">0</span></button>
</div>
</nav>
</header>
<main>
<section id="hero" class="hero ecommerce-hero">
<div class="hero-content">
<h1>Premium Quality Products</h1>
<p>Generated for: "{description}"</p>
<p>Discover amazing products at unbeatable prices!</p>
<button class="cta-button">Shop Now</button>
</div>
</section>
<section id="products" class="products">
<div class="container">
<h2>Featured Products</h2>
<div class="product-grid">
<div class="product-card">
<div class="product-image">
<div class="placeholder-img">πŸ›οΈ</div>
</div>
<div class="product-info">
<h3>Product 1</h3>
<p class="price">$29.99</p>
<button class="add-to-cart">Add to Cart</button>
</div>
</div>
<div class="product-card">
<div class="product-image">
<div class="placeholder-img">πŸ‘•</div>
</div>
<div class="product-info">
<h3>Product 2</h3>
<p class="price">$49.99</p>
<button class="add-to-cart">Add to Cart</button>
</div>
</div>
<div class="product-card">
<div class="product-image">
<div class="placeholder-img">πŸ‘Ÿ</div>
</div>
<div class="product-info">
<h3>Product 3</h3>
<p class="price">$79.99</p>
<button class="add-to-cart">Add to Cart</button>
</div>
</div>
</div>
</div>
</section>
<section id="categories" class="categories">
<div class="container">
<h2>Shop by Category</h2>
<div class="category-grid">
<div class="category-card">
<div class="category-icon">πŸ“±</div>
<h3>Electronics</h3>
</div>
<div class="category-card">
<div class="category-icon">πŸ‘•</div>
<h3>Clothing</h3>
</div>
<div class="category-card">
<div class="category-icon">🏠</div>
<h3>Home & Garden</h3>
</div>
</div>
</div>
</section>
</main>
<footer>
<div class="container">
<div class="footer-content">
<div class="footer-section">
<h3>Customer Service</h3>
<ul>
<li><a href="#">Contact Us</a></li>
<li><a href="#">Shipping Info</a></li>
<li><a href="#">Returns</a></li>
</ul>
</div>
<div class="footer-section">
<h3>About Us</h3>
<ul>
<li><a href="#">Our Story</a></li>
<li><a href="#">Careers</a></li>
<li><a href="#">Press</a></li>
</ul>
</div>
<div class="footer-section">
<h3>Connect</h3>
<div class="social-links">
<a href="#" aria-label="Facebook">πŸ“˜</a>
<a href="#" aria-label="Twitter">🐦</a>
<a href="#" aria-label="Instagram">πŸ“·</a>
</div>
</div>
</div>
<p>&copy; 2024 ShopNow. All rights reserved.</p>
</div>
</footer>
<script src="script.js"></script>
</body>
</html>'''
def generate_enhanced_css(complexity: str, color_scheme: str, layout_style: str) -> str:
"""Generate enhanced CSS with multiple themes and layouts"""
# Color schemes
color_schemes = {
"Blue": {
"primary": "#007bff",
"secondary": "#0056b3",
"accent": "#17a2b8",
"background": "#f8f9fa",
"text": "#333333"
},
"Green": {
"primary": "#28a745",
"secondary": "#1e7e34",
"accent": "#20c997",
"background": "#f8fff8",
"text": "#333333"
},
"Purple": {
"primary": "#6f42c1",
"secondary": "#5a32a3",
"accent": "#e83e8c",
"background": "#faf8ff",
"text": "#333333"
},
"Orange": {
"primary": "#fd7e14",
"secondary": "#e8650e",
"accent": "#ffc107",
"background": "#fffbf5",
"text": "#333333"
}
}
colors = color_schemes.get(color_scheme, color_schemes["Blue"])
base_css = f'''
/* Reset and base styles */
* {{
margin: 0;
padding: 0;
box-sizing: border-box;
:root {{
--primary-color: {colors['primary']};
--secondary-color: {colors['secondary']};
--accent-color: {colors['accent']};
--background-color: {colors['background']};
--text-color: {colors['text']};
--border-radius: 8px;
--shadow: 0 2px 10px rgba(0,0,0,0.1);
--transition: all 0.3s ease;
body {{
font-family: 'Inter', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: var(--text-color);
background-color: var(--background-color);
.container {{
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
/* Enhanced header */
header {{
background: #fff;
box-shadow: var(--shadow);
position: fixed;
width: 100%;
top: 0;
z-index: 1000;
backdrop-filter: blur(10px);
nav {{
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
.logo {{
font-size: 1.5rem;
font-weight: bold;
color: var(--primary-color);
transition: var(--transition);
.logo:hover {{
color: var(--secondary-color);
.search-bar {{
display: flex;
flex: 1;
max-width: 400px;
margin: 0 2rem;
.search-bar input {{
flex: 1;
padding: 10px 15px;
border: 2px solid #e0e0e0;
border-radius: var(--border-radius) 0 0 var(--border-radius);
font-size: 14px;
transition: var(--transition);
.search-bar input:focus {{
outline: none;
border-color: var(--primary-color);
.search-btn {{
padding: 10px 15px;
background: var(--primary-color);
color: white;
border: none;
border-radius: 0 var(--border-radius) var(--border-radius) 0;
cursor: pointer;
transition: var(--transition);
.search-btn:hover {{
background: var(--secondary-color);
.nav-icons {{
display: flex;
gap: 1rem;
.icon-btn {{
background: none;
border: none;
font-size: 1.2rem;
cursor: pointer;
padding: 8px;
border-radius: 50%;
transition: var(--transition);
position: relative;
.icon-btn:hover {{
background: var(--background-color);
.cart-count {{
position: absolute;
top: -5px;
right: -5px;
background: var(--primary-color);
color: white;
border-radius: 50%;
width: 18px;
height: 18px;
font-size: 10px;
display: flex;
align-items: center;
justify-content: center;
.nav-links {{
display: flex;
list-style: none;
gap: 2rem;
.nav-links a {{
text-decoration: none;
color: var(--text-color);
font-weight: 500;
transition: var(--transition);
position: relative;
.nav-links a:hover {{
color: var(--primary-color);
.nav-links a::after {{
content: '';
position: absolute;
width: 0;
height: 2px;
bottom: -5px;
left: 0;
background: var(--primary-color);
transition: var(--transition);
.nav-links a:hover::after {{
width: 100%;
/* Enhanced hero sections */
.hero {{
background: linear-gradient(135deg, var(--primary-color) 0%, var(--accent-color) 100%);
color: white;
text-align: center;
padding: 150px 0 100px;
margin-top: 80px;
position: relative;
overflow: hidden;
.ecommerce-hero {{
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
.landing-hero {{
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
.hero::before {{
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.1);
z-index: 1;
.hero-content {{
position: relative;
z-index: 2;
.hero-content h1 {{
font-size: 3.5rem;
margin-bottom: 1rem;
font-weight: 700;
animation: fadeInUp 0.8s ease;
.hero-content p {{
font-size: 1.2rem;
margin-bottom: 2rem;
opacity: 0.9;
animation: fadeInUp 0.8s ease 0.2s both;
.hero-buttons {{
display: flex;
gap: 1rem;
justify-content: center;
flex-wrap: wrap;
animation: fadeInUp 0.8s ease 0.4s both;
.cta-button {{
background: var(--primary-color);
color: white;
border: none;
padding: 15px 35px;
border-radius: var(--border-radius);
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: var(--transition);
text-decoration: none;
display: inline-block;
position: relative;
overflow: hidden;
.cta-button::before {{
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
transition: var(--transition);
.cta-button:hover::before {{
left: 100%;
.cta-button:hover {{
background: var(--secondary-color);
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(0,0,0,0.2);
.secondary-button {{
background: transparent;
color: white;
border: 2px solid white;
padding: 13px 33px;
border-radius: var(--border-radius);
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: var(--transition);
text-decoration: none;
display: inline-block;
.secondary-button:hover {{
background: white;
color: var(--primary-color);
transform: translateY(-2px);
/* Enhanced sections */
.features, .products, .services, .blog-posts, .categories {{
padding: 80px 0;
.features {{
background: var(--background-color);
.products {{
background: #fff;
.categories {{
background: var(--background-color);
.features h2, .products h2, .services h2, .blog-posts h2, .categories h2 {{
text-align: center;
font-size: 2.5rem;
margin-bottom: 3rem;
color: var(--text-color);
position: relative;
.features h2::after, .products h2::after, .services h2::after, .blog-posts h2::after, .categories h2::after {{
content: '';
position: absolute;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
width: 60px;
height: 3px;
background: var(--primary-color);
border-radius: 2px;
/* Enhanced grid layouts */
.feature-grid, .product-grid, .service-grid, .post-grid, .category-grid {{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-top: 3rem;
.product-grid {{
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
.category-grid {{
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
/* Enhanced cards */
.feature-card, .product-card, .service-card, .post-card, .category-card {{
background: white;
padding: 2rem;
border-radius: var(--border-radius);
box-shadow: var(--shadow);
transition: var(--transition);
position: relative;
overflow: hidden;
.feature-card::before, .product-card::before, .service-card::before, .post-card::before, .category-card::before {{
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, var(--primary-color), var(--accent-color));
.feature-card:hover, .product-card:hover, .service-card:hover, .post-card:hover, .category-card:hover {{
transform: translateY(-10px);
box-shadow: 0 20px 40px rgba(0,0,0,0.15);
.product-card {{
text-align: center;
.product-image {{
margin-bottom: 1rem;
.placeholder-img {{
width: 100%;
height: 200px;
background: var(--background-color);
display: flex;
align-items: center;
justify-content: center;
font-size: 3rem;
border-radius: var(--border-radius);
.product-info h3 {{
margin-bottom: 0.5rem;
color: var(--text-color);
.price {{
font-size: 1.5rem;
font-weight: bold;
color: var(--primary-color);
margin-bottom: 1rem;
.add-to-cart {{
background: var(--primary-color);
color: white;
border: none;
padding: 10px 20px;
border-radius: var(--border-radius);
cursor: pointer;
transition: var(--transition);
.add-to-cart:hover {{
background: var(--secondary-color);
transform: translateY(-2px);
.category-card {{
text-align: center;
padding: 3rem 2rem;
.category-icon {{
font-size: 3rem;
margin-bottom: 1rem;
.category-card h3 {{
color: var(--text-color);
font-size: 1.3rem;
/* Footer enhancements */
footer {{
background: var(--text-color);
color: white;
padding: 3rem 0 1rem;
.footer-content {{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
margin-bottom: 2rem;
.footer-section h3 {{
margin-bottom: 1rem;
color: var(--accent-color);
.footer-section ul {{
list-style: none;
.footer-section li {{
margin-bottom: 0.5rem;
.footer-section a {{
color: #ccc;
text-decoration: none;
transition: var(--transition);
.footer-section a:hover {{
color: var(--accent-color);
.social-links {{
display: flex;
gap: 1rem;
.social-links a {{
font-size: 1.5rem;
transition: var(--transition);
.social-links a:hover {{
transform: scale(1.2);
/* Animations */
@keyframes fadeInUp {{
from {{
opacity: 0;
transform: translateY(30px);
to {{
opacity: 1;
transform: translateY(0);
@keyframes pulse {{
0%, 100% {{ transform: scale(1); }}
50% {{ transform: scale(1.05); }}
.pulse {{
animation: pulse 2s infinite;
/* Responsive design */
@media (max-width: 768px) {{
.nav-links {{
display: none;
.search-bar {{
margin: 0 1rem;
.hero-content h1 {{
font-size: 2.5rem;
.hero-content p {{
font-size: 1rem;
.hero-buttons {{
flex-direction: column;
align-items: center;
.feature-grid, .product-grid, .service-grid, .post-grid, .category-grid {{
grid-template-columns: 1fr;
.footer-content {{
grid-template-columns: 1fr;
text-align: center;
@media (max-width: 480px) {{
nav {{
padding: 1rem;
.search-bar {{
display: none;
.hero-content h1 {{
font-size: 2rem;
.container {{
padding: 0 15px;
'''
if complexity == "Advanced":
base_css += '''
/* Advanced styling additions */
.hero {
background-attachment: fixed;
}
.feature-card:nth-child(1) { border-left: 4px solid #e74c3c; }
.feature-card:nth-child(2) { border-left: 4px solid #3498db; }
.feature-card:nth-child(3) { border-left: 4px solid #2ecc71; }
.post-excerpt {
color: #666;
margin-bottom: 1rem;
line-height: 1.6;
}
/* Glass morphism effects */
.glass {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
/* Gradient text */
.gradient-text {
background: linear-gradient(45deg, var(--primary-color), var(--accent-color));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
/* Advanced hover effects */
.hover-lift:hover {
transform: translateY(-8px) scale(1.02);
box-shadow: 0 25px 50px rgba(0,0,0,0.15);
}
/* Loading animations */
.loading {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid rgba(255,255,255,.3);
border-radius: 50%;
border-top-color: #fff;
animation: spin 1s ease-in-out infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
/* Enhanced mobile menu */
@media (max-width: 768px) {
.mobile-menu-toggle {
display: block;
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: var(--primary-color);
}
.nav-links.active {
display: flex;
flex-direction: column;
position: absolute;
top: 100%;
left: 0;
right: 0;
background: white;
box-shadow: var(--shadow);
padding: 1rem;
}
}
.mobile-menu-toggle {
display: none;
}
'''
return base_css
def generate_enhanced_javascript(complexity: str) -> str:
"""Generate enhanced JavaScript with advanced functionality"""
base_js = '''
// Enhanced functionality for AI Web Coder
document.addEventListener('DOMContentLoaded', function() {
// Initialize all components
initializeNavigation();
initializeButtons();
initializeCards();
initializeCart();
initializeSearch();
initializeAnimations();
function initializeNavigation() {
// Smooth scrolling for navigation links
const navLinks = document.querySelectorAll('.nav-links a');
navLinks.forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const targetId = this.getAttribute('href').substring(1);
const targetSection = document.getElementById(targetId);
if (targetSection) {
const headerHeight = document.querySelector('header').offsetHeight;
const targetPosition = targetSection.offsetTop - headerHeight;
window.scrollTo({
top: targetPosition,
behavior: 'smooth'
});
}
});
});
// Mobile menu toggle
const mobileMenuToggle = document.querySelector('.mobile-menu-toggle');
const navLinks = document.querySelector('.nav-links');
if (mobileMenuToggle && navLinks) {
mobileMenuToggle.addEventListener('click', function() {
navLinks.classList.toggle('active');
});
}
}
function initializeButtons() {
// Enhanced CTA button functionality
const ctaButtons = document.querySelectorAll('.cta-button');
ctaButtons.forEach(button => {
button.addEventListener('click', function(e) {
e.preventDefault();
// Add loading state
const originalText = this.textContent;
this.innerHTML = '<span class="loading"></span> Processing...';
this.disabled = true;
// Simulate processing
setTimeout(() => {
this.textContent = originalText;
this.disabled = false;
// Show success message
showNotification('Thank you! This would redirect to the next step.', 'success');
}, 2000);
});
});
// Add to cart functionality
const addToCartButtons = document.querySelectorAll('.add-to-cart');
addToCartButtons.forEach(button => {
button.addEventListener('click', function() {
const productName = this.closest('.product-card').querySelector('h3').textContent;
addToCart(productName);
// Visual feedback
this.textContent = 'Added! βœ“';
this.style.background = '#28a745';
setTimeout(() => {
this.textContent = 'Add to Cart';
this.style.background = '';
}, 2000);
});
});
}
function initializeCart() {
let cartCount = 0;
window.addToCart = function(productName) {
cartCount++;
const cartCountElement = document.querySelector('.cart-count');
if (cartCountElement) {
cartCountElement.textContent = cartCount;
cartCountElement.style.display = 'block';
// Animate cart count
cartCountElement.style.transform = 'scale(1.3)';
setTimeout(() => {
cartCountElement.style.transform = 'scale(1)';
}, 200);
}
showNotification(`${productName} added to cart!`, 'info');
};
}
function initializeSearch() {
const searchInput = document.querySelector('.search-bar input');
const searchBtn = document.querySelector('.search-btn');
if (searchInput && searchBtn) {
function performSearch() {
const query = searchInput.value.trim();
if (query) {
showNotification(`Searching for: "${query}"`, 'info');
// In a real app, this would perform the actual search
}
}
searchBtn.addEventListener('click', performSearch);
searchInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
performSearch();
}
});
}
}
function initializeCards() {
// Enhanced card animations with intersection observer
const cards = document.querySelectorAll('.feature-card, .project-card, .service-card, .post-card, .product-card, .category-card');
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry, index) => {
if (entry.isIntersecting) {
setTimeout(() => {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}, index * 100); // Staggered animation
}
});
}, {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
});
cards.forEach((card, index) => {
card.style.opacity = '0';
card.style.transform = 'translateY(30px)';
card.style.transition = `opacity 0.6s ease ${index * 0.1}s, transform 0.6s ease ${index * 0.1}s`;
observer.observe(card);
});
}
function initializeAnimations() {
// Parallax effect for hero section
window.addEventListener('scroll', function() {
const scrolled = window.pageYOffset;
const hero = document.querySelector('.hero');
if (hero) {
const rate = scrolled * -0.5;
hero.style.transform = `translateY(${rate}px)`;
}
});
// Add typing effect to hero text
const heroHeading = document.querySelector('.hero-content h1');
if (heroHeading && heroHeading.textContent.length > 20) {
const originalText = heroHeading.textContent;
heroHeading.textContent = '';
setTimeout(() => {
typeWriter(heroHeading, originalText, 100);
}, 500);
}
// Add counter animations for prices
const priceElements = document.querySelectorAll('.price');
const priceObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const priceText = entry.target.textContent;
const priceNumber = parseFloat(priceText.replace(/[^0-9.]/g, ''));
animateCounter(entry.target, priceNumber);
priceObserver.unobserve(entry.target);
}
});
});
priceElements.forEach(price => {
priceObserver.observe(price);
});
}
// Utility functions
function typeWriter(element, text, speed = 50) {
let i = 0;
element.innerHTML = '';
function type() {
if (i < text.length) {
element.innerHTML += text.charAt(i);
i++;
setTimeout(type, speed);
}
}
type();
}
function animateCounter(element, target, duration = 2000) {
let start = 0;
const increment = target / (duration / 16);
function updateCounter() {
start += increment;
if (start < target) {
element.textContent = '$' + Math.floor(start).toFixed(2);
requestAnimationFrame(updateCounter);
} else {
element.textContent = '$' + target.toFixed(2);
}
}
updateCounter();
}
function showNotification(message, type = 'info') {
// Create notification element
const notification = document.createElement('div');
notification.className = `notification notification-${type}`;
notification.textContent = message;
// Style the notification
Object.assign(notification.style, {
position: 'fixed',
top: '20px',
right: '20px',
padding: '15px 20px',
borderRadius: '8px',
color: 'white',
fontWeight: '500',
zIndex: '10000',
transform: 'translateX(100%)',
transition: 'transform 0.3s ease',
maxWidth: '300px'
});
// Set colors based on type
const colors = {
success: '#28a745',
error: '#dc3545',
info: '#007bff',
warning: '#ffc107'
};
notification.style.backgroundColor = colors[type] || colors.info;
// Add to document
document.body.appendChild(notification);
// Animate in
setTimeout(() => {
notification.style.transform = 'translateX(0)';
}, 100);
// Remove after delay
setTimeout(() => {
notification.style.transform = 'translateX(100%)';
setTimeout(() => {
if (notification.parentNode) {
notification.parentNode.removeChild(notification);
}
}, 300);
}, 3000);
}
// Performance monitoring
if (typeof window.performance !== 'undefined') {
window.addEventListener('load', function() {
setTimeout(() => {
const perfData = window.performance.timing;
const loadTime = perfData.loadEventEnd - perfData.navigationStart;
console.log(`Page load time: ${loadTime}ms`);
}, 0);
});
}
});
'''
if complexity == "Advanced":
base_js += '''
// Advanced JavaScript features
class AdvancedFeatures {
constructor() {
this.init();
}
init() {
this.initWebGL();
this.initServiceWorker();
this.initAnalytics();
this.initAccessibility();
}
initWebGL() {
// Simple WebGL demo for advanced features
const canvas = document.createElement('canvas');
canvas.style.cssText = 'position: absolute; top: 0; left: 0; z-index: -1; opacity: 0.1;';
document.body.appendChild(canvas);
if (canvas.getContext) {
this.initParticles(canvas);
}
}
initParticles(canvas) {
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const particles = [];
for (let i = 0; i < 50; i++) {
particles.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
vx: (Math.random() - 0.5) * 0.5,
vy: (Math.random() - 0.5) * 0.5
});
}
const animate = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
particles.forEach(particle => {
particle.x += particle.vx;
particle.y += particle.vy;
if (particle.x < 0 || particle.x > canvas.width) particle.vx *= -1;
if (particle.y < 0 || particle.y > canvas.height) particle.vy *= -1;
ctx.beginPath();
ctx.arc(particle.x, particle.y, 1, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(0, 123, 255, 0.5)';
ctx.fill();
});
requestAnimationFrame(animate);
};
animate();
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
}
initServiceWorker() {
if ('serviceWorker' in navigator) {
// Register service worker for PWA functionality
navigator.serviceWorker.register('/sw.js').then(registration => {
console.log('SW registered: ', registration);
}).catch(registrationError => {
console.log('SW registration failed: ', registrationError);
});
}
}
initAnalytics() {
// Simple analytics tracking
this.trackUserInteractions();
}
trackUserInteractions() {
document.addEventListener('click', function(e) {
if (e.target.tagName === 'BUTTON') {
console.log('Button clicked:', e.target.textContent);
// In a real app, send to analytics service
}
});
}
initAccessibility() {
// Enhance keyboard navigation
document.addEventListener('keydown', function(e) {
if (e.key === 'Tab') {
document.body.classList.add('keyboard-navigation');
}
});
document.addEventListener('mousedown', function() {
document.body.classList.remove('keyboard-navigation');
});
}
}
// Initialize advanced features
new AdvancedFeatures();
// Add keyboard shortcuts
document.addEventListener('keydown', function(e) {
// Ctrl/Cmd + K for search
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
e.preventDefault();
const searchInput = document.querySelector('.search-bar input');
if (searchInput) {
searchInput.focus();
}
}
});
// Progressive enhancement
if ('IntersectionObserver' in window) {
// Lazy loading for images (if any were added)
const imageObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
if (img.dataset.src) {
img.src = img.dataset.src;
img.removeAttribute('data-src');
imageObserver.unobserve(img);
}
}
});
});
document.querySelectorAll('img[data-src]').forEach(img => {
imageObserver.observe(img);
});
}
'''
return base_js
def enhance_html_with_seo_accessibility(html_code: str, description: str) -> str:
"""Add SEO and accessibility improvements to HTML"""
# Add meta tags for SEO
seo_meta = f'''
<meta name="description" content="Generated website based on: {description}">
<meta name="keywords" content="{description.split()[:10]}">
<meta name="author" content="AI Web Coder">
<meta property="og:title" content="Generated Website">
<meta property="og:description" content="Generated website based on: {description}">
<meta property="og:type" content="website">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Generated Website">
<meta name="twitter:description" content="Generated website based on: {description}">
<link rel="canonical" href="#">
'''
# Add accessibility improvements
accessibility_fixes = '''
<meta name="theme-color" content="#007bff">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
'''
# Insert meta tags after the existing charset meta tag
html_code = html_code.replace(
'<meta charset="UTF-8">',
'<meta charset="UTF-8">\n ' + seo_meta.strip() + '\n ' + accessibility_fixes.strip()
)
# Add skip link for accessibility
skip_link = ''' <a href="#main" class="skip-link">Skip to main content</a>'''
html_code = html_code.replace('<body>', '<body>\n' + skip_link)
# Add ARIA labels and improve accessibility
html_code = html_code.replace('<nav>', '<nav role="navigation" aria-label="Main navigation">')
return html_code
def analyze_code_quality(html_code: str, css_code: str, js_code: str) -> Dict[str, Any]:
"""Analyze code quality and provide metrics"""
score = 0
tips = []
accessibility_score = 0
seo_score = 0
# HTML Quality Checks
if '<!DOCTYPE html>' in html_code:
score += 5
if 'lang="en"' in html_code:
score += 5
accessibility_score += 10
if 'viewport' in html_code:
score += 5
seo_score += 10
if 'aria-label' in html_code or 'alt=' in html_code:
accessibility_score += 15
if '<meta name="description"' in html_code:
seo_score += 15
# CSS Quality Checks
if ':root' in css_code or 'var(' in css_code:
score += 10
if '@media' in css_code:
score += 10
accessibility_score += 10
if 'transition' in css_code:
score += 5
if 'flexbox' in css_code or 'grid' in css_code:
score += 5
# JavaScript Quality Checks
if 'addEventListener' in js_code:
score += 10
if 'DOMContentLoaded' in js_code:
score += 10
if 'const ' in js_code or 'let ' in js_code:
score += 5
if 'async' in js_code or 'await' in js_code:
score += 5
# Accessibility Score (max 100)
accessibility_score = min(accessibility_score, 100)
# SEO Score (max 100)
seo_score = min(seo_score, 100)
# Generate tips
if score < 50:
tips.append("Consider adding more semantic HTML elements")
if accessibility_score < 70:
tips.append("Add more ARIA labels and alt text for images")
if seo_score < 70:
tips.append("Include meta descriptions and proper heading structure")
if ':root' not in css_code:
tips.append("Use CSS custom properties for better maintainability")
if '@media' not in css_code:
tips.append("Add responsive design with media queries")
if 'addEventListener' not in js_code:
tips.append("Use modern JavaScript event handling")
if not tips:
tips.append("Great code quality! Your website follows modern best practices.")
return {
'score': min(score, 100),
'tips': tips,
'accessibility': accessibility_score,
'seo': seo_score
}
def save_project(project_name: str, description: str, complexity: str, html_code: str, css_code: str, js_code: str) -> str:
"""Save project data (simulated)"""
project_data = {
"name": project_name,
"description": description,
"complexity": complexity,
"html": html_code,
"css": css_code,
"js": js_code,
"timestamp": time.time()
}
# In a real implementation, this would save to a database
return f"Project '{project_name}' saved successfully! (Simulated - would save to database)"
def load_projects() -> List[str]:
"""Load saved projects (simulated)"""
# In a real implementation, this would load from a database
return [
"Portfolio Site",
"Business Landing Page",
"E-commerce Store",
"Blog Template"
]
# Enhanced theme with better styling
enhanced_theme = gr.themes.Soft(
primary_hue="blue",
secondary_hue="indigo",
neutral_hue="slate",
font=gr.themes.GoogleFont("Inter"),
text_size="lg",
spacing_size="lg",
radius_size="md"
).set(
button_primary_background_fill="*primary