From 38a2e0107fd89035f849053a2722ca2f1c7bc501 Mon Sep 17 00:00:00 2001 From: Mogbeyi Date: Tue, 28 Oct 2025 22:54:59 +0100 Subject: [PATCH] Implement text to HTML page converter --- .../emmy/text_to_html.py | 222 ++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 week4/community-contributions/emmy/text_to_html.py diff --git a/week4/community-contributions/emmy/text_to_html.py b/week4/community-contributions/emmy/text_to_html.py new file mode 100644 index 0000000..a9ef113 --- /dev/null +++ b/week4/community-contributions/emmy/text_to_html.py @@ -0,0 +1,222 @@ +import os +from dotenv import load_dotenv +from openai import OpenAI +import gradio as gr + +# --- Load environment keys --- +load_dotenv(override=True) +openai_api_key = os.getenv("OPENAI_API_KEY") +google_api_key = os.getenv("GOOGLE_API_KEY") + +# --- Model config --- +MODEL_MAP = { + "GPT-4o-mini": { + "model": "gpt-4o-mini", + "key": openai_api_key, + "endpoint": "https://api.openai.com/v1" + }, + "Gemini-Flash": { + "model": "gemini-2.5-flash", + "key": google_api_key, + "endpoint": "https://generativelanguage.googleapis.com/v1beta/openai/" + } +} + +class PageBuilder: + def __init__(self, model_choice="GPT-4o-mini"): + self.set_model(model_choice) + + def set_model(self, model_choice: str): + spec = MODEL_MAP[model_choice] + self.client = OpenAI( + api_key=spec["key"], + base_url=spec["endpoint"] + ) + self.model_name = spec["model"] + + def build_page(self, raw_text: str, theme: str) -> str: + """ + Ask the model for a self-contained HTML page (HTML + + """ + return html_page.replace("", fix + "\n") if "" in html_page else fix + html_page + +def build_interface(): + with gr.Blocks( + title="PrettyPage", + theme=gr.themes.Soft(primary_hue="indigo", neutral_hue="slate") + ) as demo: + gr.Markdown( + """ +
+

✨ PrettyPage Generator

+

+ Paste any text. Get a clean, beautiful, responsive webpage using your exact words. +

+
+ """, + ) + + with gr.Row(): + model_choice = gr.Radio( + choices=list(MODEL_MAP.keys()), + value="GPT-4o-mini", + label="Model", + info="Which model should generate the page?" + ) + theme_choice = gr.Dropdown( + choices=[ + "Minimal", + "Professional", + "Colorful", + "Modern Gradient" + ], + value="Professional", + label="Style Theme", + info="Controls colors / layout vibe" + ) + + input_text = gr.Textbox( + label="Your Text Content", + lines=12, + placeholder=( + "Paste your notes, article, README, sales copy, lesson, etc.\n" + "We'll turn this into a styled webpage without changing your words." + ), + ) + + generate_btn = gr.Button("🎨 Generate Page", variant="primary") + + gr.Markdown("---") + + with gr.Row(): + with gr.Column(scale=1): + gr.Markdown("**Generated HTML (copy & save as .html):**") + html_code_output = gr.Textbox( + label="HTML Source", + interactive=False, + lines=20, + max_lines=20, + show_copy_button=True + ) + + with gr.Column(scale=1): + gr.Markdown("**Live Preview:**") + live_preview = gr.HTML( + value=( + "
" + "Your page preview will appear here.
" + ), + ) + + # click handler: build the page fresh each time + def handle_generate(user_text, chosen_model, chosen_theme): + porter = PageBuilder(chosen_model) + html_page = porter.build_page(user_text, chosen_theme) + fixed_preview = apply_readability_fix(html_page) + # left pane shows code, right pane renders preview + return html_page, fixed_preview + + generate_btn.click( + fn=handle_generate, + inputs=[input_text, model_choice, theme_choice], + outputs=[html_code_output, live_preview], + ) + + gr.Markdown( + """ +
+ Tip: Save the HTML Source above as index.html and open it in your browser. +
+ """ + ) + + return demo + +if __name__ == "__main__": + demo = build_interface() + demo.launch(inbrowser=True)