AiCoderv2's picture
Update app.py from anycoder
8ca1c31 verified
raw
history blame
40.6 kB
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