from fastapi import FastAPI, Request from fastapi.staticfiles import StaticFiles from starlette.middleware.base import BaseHTTPMiddleware import uvicorn import os from pathlib import Path # Import PDF router and Visual HTML Editor router from html_to_pdf_router import router as pdf_router from visual_html_editor_router import router as editor_router # Ensure we're serving from the /workspace directory workspace_dir = "/workspace" class WorkspaceDirMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): # Check if workspace directory exists and recreate if deleted if not os.path.exists(workspace_dir): print(f"Workspace directory {workspace_dir} not found, recreating...") os.makedirs(workspace_dir, exist_ok=True) return await call_next(request) app = FastAPI() app.add_middleware(WorkspaceDirMiddleware) # Include routers app.include_router(pdf_router) app.include_router(editor_router) # Create output directory for generated PDFs (needed by PDF router) output_dir = Path("generated_pdfs") output_dir.mkdir(exist_ok=True) # Mount static files for PDF downloads app.mount("/downloads", StaticFiles(directory=str(output_dir)), name="downloads") # Initial directory creation os.makedirs(workspace_dir, exist_ok=True) # Add visual HTML editor root endpoint @app.get("/editor") async def list_html_files(): """List all HTML files in the workspace for easy access""" from fastapi.responses import HTMLResponse try: html_files = [f for f in os.listdir(workspace_dir) if f.endswith('.html')] html_content = """ Visual HTML Editor

Visual HTML Editor

Click-to-edit any HTML file with live preview

""" if html_files: for file in sorted(html_files): html_content += f"""
{file}
""" else: html_content += """

No files found

Add .html files to this directory to start editing

""" html_content += """

How to use

Edit text: Hover over any text and click the edit icon
Delete elements: Click the trash icon to remove content
Save changes: Press Ctrl+Enter or click Save
Cancel editing: Press Escape or click Cancel
""" return HTMLResponse(content=html_content) except Exception as e: print(f"❌ Error listing HTML files: {e}") from fastapi import HTTPException raise HTTPException(status_code=500, detail=str(e)) # Serve HTML files directly at root level @app.get("/{file_name}") async def serve_html_file(file_name: str): """Serve HTML files directly for viewing""" from fastapi import HTTPException from fastapi.responses import HTMLResponse if not file_name.endswith('.html'): raise HTTPException(status_code=404, detail="File must be .html") file_path = os.path.join(workspace_dir, file_name) if not os.path.exists(file_path): raise HTTPException(status_code=404, detail="File not found") with open(file_path, 'r', encoding='utf-8') as f: content = f.read() return HTMLResponse(content=content) app.mount('/', StaticFiles(directory=workspace_dir, html=True), name='site') # This is needed for the import string approach with uvicorn if __name__ == '__main__': print(f"Starting server with auto-reload, serving files from: {workspace_dir}") # Don't use reload directly in the run call uvicorn.run("server:app", host="0.0.0.0", port=8080, reload=True)