suppfactsdaily / html_handler.py
RidhiD.
Stable working version , published after first batch
2132d78
"""
HTML generation and file management for dev flow.
"""
import os
from datetime import datetime
from pathlib import Path
from logger import logger
from config import HTML_OUTPUT_DIR
class HTMLHandler:
"""Handles HTML generation and file management."""
def __init__(self, output_dir=HTML_OUTPUT_DIR):
"""Initialize HTML handler."""
self.output_dir = output_dir
Path(self.output_dir).mkdir(exist_ok=True)
logger.debug(f"HTMLHandler initialized with output dir: {output_dir}")
def generate_html(self, title, body, tags, image_url=None, original_url=None):
"""
Generate HTML content from article data.
Args:
title (str): Article title
body (str): Article body (HTML)
tags (list): List of tags
image_url (str, optional): Featured image URL
original_url (str, optional): Original article URL
Returns:
str: Generated HTML content
"""
try:
# Format tags as HTML
tags_html = " ".join([f'<span class="tag">{tag}</span>' for tag in tags])
# Build featured image section
image_section = ""
if image_url:
image_section = (
f'<div class="featured-image">'
f'<img src="{image_url}" alt="{title}">'
f"</div>"
)
# Generate complete HTML
html_content = f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{title}</title>
<style>
* {{
margin: 0;
padding: 0;
box-sizing: border-box;
}}
body {{
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
line-height: 1.6;
color: #333;
background-color: #f5f5f5;
}}
.container {{
max-width: 800px;
margin: 0 auto;
padding: 40px 20px;
background-color: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}}
header {{
margin-bottom: 30px;
border-bottom: 3px solid #007bff;
padding-bottom: 20px;
}}
h1 {{
font-size: 2.2em;
margin-bottom: 15px;
line-height: 1.3;
color: #1a1a1a;
}}
.meta {{
font-size: 0.9em;
color: #666;
margin-bottom: 10px;
}}
.tags {{
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 10px;
}}
.tag {{
background-color: #e9ecef;
color: #007bff;
padding: 4px 12px;
border-radius: 20px;
font-size: 0.85em;
font-weight: 500;
}}
.featured-image {{
margin: 30px 0;
text-align: center;
}}
.featured-image img {{
max-width: 100%;
height: auto;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}}
.content {{
font-size: 1.1em;
margin-bottom: 30px;
line-height: 1.8;
}}
.content p {{
margin-bottom: 15px;
text-align: justify;
}}
.content figure {{
margin: 20px 0;
}}
.content img {{
max-width: 100%;
height: auto;
border-radius: 6px;
}}
footer {{
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid #ddd;
font-size: 0.9em;
color: #666;
text-align: center;
}}
/* Desktop: max-width 1200px and above */
@media (min-width: 1200px) {{
.featured-image img {{
max-width: 300px;
}}
}}
/* Tablet: 768px to 1199px */
@media (min-width: 768px) and (max-width: 1199px) {{
.featured-image img {{
max-width: 250px;
}}
}}
/* Responsive container and content font size remain */
@media (max-width: 600px) {{
.container {{
padding: 20px;
}}
h1 {{
font-size: 1.6em;
}}
.content {{
font-size: 1em;
}}
}}
</style>
</head>
<body>
<div class="container">
<header>
<h1>{title}</h1>
<div class="meta">
Generated on {datetime.now().strftime('%B %d, %Y at %I:%M %p')}
</div>
<div class="tags">
{tags_html}
</div>
</header>
{image_section}
<div class="content">
{body}
</div>
</div>
</body>
</html>"""
logger.debug("HTML content generated successfully")
return html_content
except Exception as e:
logger.error(f"Failed to generate HTML: {e}")
raise
def save_html(self, html_content, filename=None):
"""
Save HTML content to file.
Args:
html_content (str): HTML content to save
filename (str, optional): Filename to use. If None, generates timestamp-based name.
Returns:
str: Full path to saved file
"""
try:
if not filename:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"article_{timestamp}.html"
file_path = os.path.join(self.output_dir, filename)
with open(file_path, "w", encoding="utf-8") as f:
f.write(html_content)
logger.info(f"✓ HTML file saved: {file_path}")
return file_path
except Exception as e:
logger.error(f"Failed to save HTML file: {e}")
raise
def generate_and_save(self, title, body, tags, image_url=None, original_url=None, filename=None):
"""
Generate and save HTML in one call.
Args:
title (str): Article title
body (str): Article body (HTML)
tags (list): List of tags
image_url (str, optional): Featured image URL
original_url (str, optional): Original article URL
filename (str, optional): Custom filename
Returns:
str: Full path to saved file
"""
html_content = self.generate_html(title, body, tags, image_url, original_url)
return self.save_html(html_content, filename)