# פרויקט Python מלא: מחולל אתרי אינטרנט AI אוטומטי להרצה ב-Hugging Face Spaces (Gradio) # גרסה: 1.0 # תואם בדיוק לדרישות: מודל AI, Gradio, עורך קוד, תצוגה מקדימה, ניהול פרויקטים, מספר דפים, יצוא ZIP # הסבר: הקוד משתמש ב-InferenceClient (huggingface_hub) למודל Qwen2.5-Coder-1.5B-Instruct – קל ומהיר ב-Spaces ללא צורך ב-GPU כבד. # כל הקבצים נשמרים בזיכרון (State), תומך בעריכה, תצוגה מקדימה עם inline CSS/JS, ושמירה/טעינה כ-JSON + ZIP. # הערות מפורטות בכל חלק – כפי שביקשת. import gradio as gr from huggingface_hub import InferenceClient import json import zipfile import io import re # ====================== 1. מודל AI חזק (Code Generation) ====================== # מודל Hugging Face מתאים במיוחד ליצירת HTML/CSS/JS איכותי ומוכן להרצה client = InferenceClient(model="Qwen/Qwen2.5-Coder-1.5B-Instruct") def generate_website(description: str, primary_color: str, design_style: str, page_names_str: str): """ יוצר את כל הקבצים באמצעות מודל AI. הפרומפט באנגלית (מודלים לקוד טובים יותר באנגלית) אבל התוצאה מותאמת לעברית/עיצוב. """ page_names = [p.strip() for p in page_names_str.split(",") if p.strip()] if not page_names: page_names = ["index"] prompt = f"""You are an expert full-stack web developer. Create a complete, beautiful, responsive multi-page website. Description: {description} Primary color: {primary_color} Design style: {design_style} (use Tailwind CSS via CDN + custom CSS) Pages: {', '.join(page_names)} Requirements: - Use HTML5, Tailwind CSS CDN, modern design. - Each HTML file must contain: and - Add nice navigation between pages. - Include some JavaScript interactivity (buttons, smooth scroll, mobile menu). - Make it production-ready and beautiful. Return ONLY a valid JSON object (no extra text): {{ "files": {{ "style.css": "FULL CSS CODE HERE", "script.js": "FULL JS CODE HERE", "index.html": "FULL HTML CODE HERE", "about.html": "FULL HTML CODE HERE", ... (one file for each page) }} }} """ try: response = client.text_generation( prompt=prompt, max_new_tokens=8192, temperature=0.6, top_p=0.9, do_sample=True ) # ניקוי אם המודל הוסיף markdown response = response.strip() if response.startswith("```json"): response = response[7:] if response.endswith("```"): response = response[:-3] data = json.loads(response) files = data.get("files", {}) # בדיקת בטיחות – תמיד קיימים קבצים בסיסיים if "style.css" not in files: files["style.css"] = f"body {{ color: {primary_color}; font-family: system-ui; }}" if "script.js" not in files: files["script.js"] = "// JS interactivity\nconsole.log('Site loaded!');" return files, "✅ האתר נוצר בהצלחה! ערוך, צפה והורד." except Exception as e: return {}, f"❌ שגיאה: {str(e)}\nנסה תיאור יותר מפורט או לחץ שוב." # ====================== 2. הכנת תצוגה מקדימה (iframe-like עם inline) ====================== def prepare_preview_html(files: dict, page_name: str): """הופך את הדף ל-single HTML עם CSS + JS inline כדי שיעבוד בתוך Gradio.""" if not files or page_name not in files: return "

בחר דף להצגה

" html = files[page_name] css = files.get("style.css", "") js = files.get("script.js", "") # הסרת קישורים חיצוניים (כדי שהכל יהיה inline) html = re.sub(r']*href=["\']style\.css["\'][^>]*>', '', html, flags=re.IGNORECASE) html = re.sub(r']*src=["\']script\.js["\'][^>]*>', '', html, flags=re.IGNORECASE) # הוספת inline CSS if re.search(r'', html, re.IGNORECASE): html = re.sub(r'(?i)', f'', html) else: html = f'\n{html}' # הוספת inline JS if re.search(r'', html, re.IGNORECASE): html = re.sub(r'(?i)', f'', html) else: html += f'\n' return html # ====================== 3. יצוא ZIP ====================== def create_zip_download(files: dict): """יוצר ZIP בזיכרון עם כל הקבצים הנפרדים.""" if not files: return None buffer = io.BytesIO() with zipfile.ZipFile(buffer, "w", zipfile.ZIP_DEFLATED) as zf: for filename, content in files.items(): zf.writestr(filename, content.encode("utf-8")) buffer.seek(0) return buffer.getvalue() # ====================== 4. שמירה וטעינה של פרויקט (JSON) ====================== def save_project_json(files: dict): if not files: return None return json.dumps(files, ensure_ascii=False, indent=2).encode("utf-8") def load_project(uploaded_file): """טוען פרויקט JSON שהמשתמש העלה.""" if uploaded_file is None: return {}, "לא נבחר קובץ" try: content = uploaded_file.decode("utf-8") files = json.loads(content) return files, "✅ פרויקט נטען בהצלחה!" except Exception as e: return {}, f"❌ שגיאה בטעינה: {str(e)}" # ====================== 5. פונקציות עזר לעורך ====================== def update_editor(selected_file, current_files): """מעדכן את עורך הקוד לפי הקובץ שנבחר.""" if not current_files or selected_file not in current_files: return "// אין קובץ", "javascript" ext = selected_file.split(".")[-1].lower() lang = "html" if ext == "html" else "css" if ext == "css" else "javascript" return current_files[selected_file], lang def save_edited_code(selected_file, new_code, current_files): """שומר שינויים מהעורך.""" if selected_file and current_files: current_files[selected_file] = new_code return current_files, "✅ שינויים נשמרו!", create_zip_download(current_files), save_project_json(current_files) return current_files, "❌ לא נשמר", None, None # ====================== 6. ממשק Gradio מלא ====================== with gr.Blocks(title="מחולל אתרי AI – Gradio", theme=gr.themes.Soft()) as iface: gr.Markdown("# 🛠️ מחולל אתרי אינטרנט אוטומטי עם AI\n" "תאר → בחר צבע וסגנון → יצור → ערוך → צפה → הורד ZIP\n" "תומך ב-Landing Page, Blog, Portfolio, Dashboard ועוד!") files_state = gr.State({}) # שומר את כל הקבצים בזיכרון with gr.Tab("✨ יצירת אתר חדש"): with gr.Row(): with gr.Column(scale=2): description_input = gr.Textbox( label="📝 תיאור האתר", placeholder="אתר Landing Page לחנות בגדים אופנתית עם דף מוצרים, בלוג וטופס יצירת קשר...", lines=4 ) primary_color_input = gr.ColorPicker(label="🎨 צבע עיקרי", value="#2563eb") design_style_input = gr.Dropdown( choices=["מודרני", "מינימליסטי", "כהה", "תוסס", "תאגידי", "פורטפוליו"], label="🎨 סגנון עיצוב", value="מודרני" ) page_names_input = gr.Textbox( label="📄 שמות הדפים (מופרדים בפסיקים)", value="index,about,services,contact", placeholder="index,blog,portfolio" ) generate_button = gr.Button("🚀 יצור אתר!", variant="primary", size="large") with gr.Column(scale=1): status_output = gr.Textbox(label="סטטוס", interactive=False, value="מוכן ליצירה...") gr.Markdown("### 👀 תצוגה מקדימה + עורך קוד") with gr.Row(): with gr.Column(scale=1): preview_page_dropdown = gr.Dropdown(label="בחר דף להצגה", choices=[], interactive=True) live_preview = gr.HTML( value="
התצוגה המקדימה תופיע כאן
", label="תצוגה מקדימה (מתעדכנת אוטומטית)" ) refresh_preview_btn = gr.Button("🔄 רענן תצוגה") with gr.Column(scale=1): file_dropdown = gr.Dropdown(label="בחר קובץ לעריכה", choices=[], interactive=True) code_editor = gr.Code( label="עורך קוד (HTML / CSS / JS)", language="html", lines=22, interactive=True ) save_edit_button = gr.Button("💾 שמור שינויים בקוד") with gr.Tab("📁 ניהול פרויקטים & יצוא"): gr.Markdown("### שמור / טען פרויקטים") with gr.Row(): upload_project = gr.File(label="העלה פרויקט JSON קודם", file_types=[".json"], type="binary") load_status = gr.Textbox(label="סטטוס טעינה", interactive=False) with gr.Row(): save_json_button = gr.DownloadButton(label="💾 שמור פרויקט כ-JSON", value=None, visible=False) download_zip_button = gr.DownloadButton(label="📦 הורד אתר מלא כ-ZIP", value=None, visible=False) # ====================== אירועים (Events) ====================== generate_button.click( fn=lambda desc, color, style, pages, state: ( *generate_website(desc, color, style, pages), # outputs: files, status, file_dropdown, preview_page_dropdown, live_preview, zip_bytes, json_bytes ), inputs=[description_input, primary_color_input, design_style_input, page_names_input, files_state], outputs=[ files_state, status_output, file_dropdown, preview_page_dropdown, live_preview, download_zip_button, save_json_button ] ) # עדכון עורך קוד file_dropdown.change( fn=update_editor, inputs=[file_dropdown, files_state], outputs=[code_editor] ) # שמירת עריכה + עדכון כפתורי הורדה save_edit_button.click( fn=save_edited_code, inputs=[file_dropdown, code_editor, files_state], outputs=[files_state, status_output, download_zip_button, save_json_button] ) # רענון תצוגה מקדימה def refresh_preview(page, state): return prepare_preview_html(state, page) preview_page_dropdown.change( fn=refresh_preview, inputs=[preview_page_dropdown, files_state], outputs=[live_preview] ) refresh_preview_btn.click( fn=refresh_preview, inputs=[preview_page_dropdown, files_state], outputs=[live_preview] ) # טעינת פרויקט JSON def handle_upload(uploaded, state): new_files, msg = load_project(uploaded) if new_files: html_pages = [f for f in new_files if f.endswith(".html")] all_files = list(new_files.keys()) return ( new_files, msg, gr.Dropdown(choices=all_files, value=all_files[0] if all_files else None), gr.Dropdown(choices=html_pages, value=html_pages[0] if html_pages else None), prepare_preview_html(new_files, html_pages[0] if html_pages else ""), create_zip_download(new_files), save_project_json(new_files) ) return state, msg, gr.Dropdown(), gr.Dropdown(), live_preview.value, None, None upload_project.upload( fn=handle_upload, inputs=[upload_project, files_state], outputs=[ files_state, load_status, file_dropdown, preview_page_dropdown, live_preview, download_zip_button, save_json_button ] ) gr.Markdown("---\n" "**טיפים:**\n" "• התצוגה המקדימה מראה דף אחד בכל פעם (קישורים לא עובדים כי אין שרת). הורד ZIP כדי לראות את כל האתר.\n" "• אחרי עריכה – לחץ \"שמור שינויים\" ואז \"רענן תצוגה\".\n" "• כל הפרויקטים נשמרים רק בדפדפן – הורד JSON כדי לשמור.") # ====================== 7. הרצה ====================== if __name__ == "__main__": iface.launch( server_name="0.0.0.0", server_port=7860, share=False, # ב-Spaces זה אוטומטי debug=True )