editableweb / app.py
AkashKumarave's picture
Update app.py
76f26db verified
raw
history blame
6.11 kB
import gradio as gr
import requests
from bs4 import BeautifulSoup
import json
import base64
from PIL import Image
import io
import os
from urllib.parse import urlparse
import re
def clean_url(url):
"""Ensure URL has proper protocol"""
if not url.startswith(('http://', 'https://')):
url = 'https://' + url
return url
def get_page_screenshot(url):
"""Get screenshot of the webpage using a screenshot API"""
try:
# Using a free screenshot API (limited, for demo purposes)
api_url = f"https://api.apiflash.com/v1/urltoimage?access_key=demo&url={url}&format=jpeg&quality=80"
response = requests.get(api_url)
if response.status_code == 200:
return response.content
else:
return None
except Exception as e:
print(f"Screenshot error: {str(e)}")
return None
def extract_styles(element):
"""Extract CSS styles from an element"""
styles = {}
if element.has_attr('style'):
style_text = element.get('style')
style_pairs = [s.strip() for s in style_text.split(';') if s.strip()]
for pair in style_pairs:
if ':' in pair:
prop, val = pair.split(':', 1)
styles[prop.strip()] = val.strip()
return styles
def extract_colors(styles):
"""Extract colors from CSS styles"""
colors = []
color_props = ['color', 'background-color', 'border-color']
for prop in color_props:
if prop in styles and styles[prop] not in ['transparent', 'inherit', 'initial']:
colors.append(styles[prop])
return colors
def extract_fonts(styles):
"""Extract fonts from CSS styles"""
fonts = []
if 'font-family' in styles:
font_str = styles['font-family']
# Split by comma and clean up quotes
font_list = [f.strip().strip('"\'') for f in font_str.split(',')]
fonts.extend(font_list)
return fonts
def process_website(url):
"""Process a website and extract design elements"""
url = clean_url(url)
try:
# Fetch the webpage
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
response = requests.get(url, headers=headers, timeout=15)
if response.status_code != 200:
return {"error": f"Failed to fetch website (Status code: {response.status_code})"}
# Parse HTML
soup = BeautifulSoup(response.text, 'html.parser')
# Get screenshot
screenshot = get_page_screenshot(url)
screenshot_base64 = None
if screenshot:
screenshot_base64 = base64.b64encode(screenshot).decode('utf-8')
# Extract text content
text_elements = []
for text_tag in soup.find_all(['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'span', 'a', 'button']):
if text_tag.text.strip():
text_elements.append({
"tag": text_tag.name,
"text": text_tag.text.strip(),
"styles": extract_styles(text_tag)
})
# Extract colors
all_colors = []
for tag in soup.find_all(True):
styles = extract_styles(tag)
colors = extract_colors(styles)
all_colors.extend(colors)
# Extract fonts
all_fonts = []
for tag in soup.find_all(True):
styles = extract_styles(tag)
fonts = extract_fonts(styles)
all_fonts.extend(fonts)
# Extract images
images = []
for img in soup.find_all('img'):
if img.has_attr('src'):
src = img['src']
if src.startswith('//'):
src = 'https:' + src
elif not src.startswith(('http://', 'https://')):
# Handle relative URLs
base_url = '{uri.scheme}://{uri.netloc}'.format(uri=urlparse(url))
if src.startswith('/'):
src = base_url + src
else:
src = base_url + '/' + src
images.append({
"src": src,
"alt": img.get('alt', ''),
"width": img.get('width', ''),
"height": img.get('height', '')
})
# Create result
result = {
"url": url,
"title": soup.title.string if soup.title else "",
"screenshot": screenshot_base64,
"text_elements": text_elements[:50], # Limit to 50 elements
"colors": list(set(all_colors))[:20], # Remove duplicates and limit
"fonts": list(set(all_fonts))[:10], # Remove duplicates and limit
"images": images[:20] # Limit to 20 images
}
return result
except Exception as e:
return {"error": str(e)}
def figma_conversion_api(url):
"""API endpoint for Figma plugin to convert websites"""
if not url:
return {"error": "No URL provided"}
result = process_website(url)
return result
# Create Gradio interface
with gr.Blocks() as demo:
gr.Markdown("# Website to Figma Converter API")
with gr.Tab("API Endpoint"):
gr.Markdown("""
## API Usage
This API provides website conversion functionality for the Figma plugin.
### Example usage:
Send a POST request with a URL parameter to convert a website to Figma-compatible format.
""")
with gr.Tab("Test Interface"):
with gr.Row():
url_input = gr.Textbox(label="Enter Website URL", placeholder="https://example.com")
convert_button = gr.Button("Convert Website")
output = gr.JSON(label="Conversion Result")
convert_button.click(figma_conversion_api, inputs=url_input, outputs=output)
# Mount the Gradio app
demo.launch()