from fastapi import FastAPI, Request from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates import json import os from fastapi.responses import HTMLResponse from contextlib import asynccontextmanager from markdown_render import render_markdown_with_jinja from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware from fastapi import FastAPI, Request from fastapi.responses import RedirectResponse from starlette.middleware.base import BaseHTTPMiddleware class ConditionalHTTPSRedirectMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): # Extract the host or remote address host = request.headers.get("host", "") client_ip = request.client.host # Get the client's IP address # Log for debugging print(f"Client IP: {client_ip}, Host: {host}") # Check condition: Redirect only if not on 127.0.0.1 if client_ip != "127.0.0.1" and request.url.scheme == "http": https_url = request.url.replace(scheme="https") return RedirectResponse(url=https_url) # Continue processing other requests response = await call_next(request) return response # Context manager for app lifespan @asynccontextmanager async def lifespan(app: FastAPI): print("App startup: Processing Markdown files...") process_markdown_files("./data", "./data") # Process all Markdown files print("Markdown processing complete!") yield # Allow the app to start print("App shutdown: Cleanup complete.") app = FastAPI(lifespan=lifespan) app.mount("/data", StaticFiles(directory="data"), name="data") # Mount static files app.mount("/static", StaticFiles(directory="static"), name="static") #app.add_middleware( HTTPSRedirectMiddleware ) app.add_middleware(ConditionalHTTPSRedirectMiddleware) # Templates directory templates = Jinja2Templates(directory="templates") # Load JSON data with open("mock_data.json") as file: data = json.load(file) @app.get("/test", response_class=HTMLResponse) async def home_test(): # Load the Markdown content from a file with open("templates/example.md", "r") as f: markdown_content = f.read() # Render Markdown first, then inject Jinja2 components rendered_html = render_markdown_with_jinja(markdown_content) # Wrap in a base HTML layout html_template = f""" Markdown + Jinja2
{rendered_html}
""" return HTMLResponse(content=html_template) def process_markdown_files(input_dir: str, output_dir: str): """ Recursively process all Markdown files in the input directory, render them to HTML, and save them in the output directory. """ for root, _, files in os.walk(input_dir): for file in files: if file.endswith(".md"): input_file_path = os.path.join(root, file) # Determine output file path (convert .md to .html) relative_path = os.path.relpath(input_file_path, input_dir) output_file_path = os.path.join(output_dir, os.path.splitext(relative_path)[0] + ".html") # Ensure the output directory exists os.makedirs(os.path.dirname(output_file_path), exist_ok=True) # Read Markdown content with open(input_file_path, "r", encoding="utf-8") as md_file: markdown_content = md_file.read() # Render Markdown with Jinja2 print(f"Processing: {input_file_path} -> {output_file_path}") rendered_html = render_markdown_with_jinja(markdown_content) # Write the rendered HTML to the output file with open(output_file_path, "w", encoding="utf-8") as html_file: html_file.write(rendered_html) # Index route @app.get("/", response_class=HTMLResponse) async def get_index(request: Request): return templates.TemplateResponse( "index.html", {"request": request, "data": data, "page_title": "Forside", "author": "Henrik"} ) @app.get("/sitemap", response_class=HTMLResponse) async def sitemap(): """Simple home page listing available HTML files.""" links = [] for root, _, files in os.walk("./data"): for file in files: if file.endswith(".html"): relative_path = os.path.relpath(os.path.join(root, file), "./data") link = f"{relative_path}" links.append(link) links_html = "
".join(links) return HTMLResponse(content=f"

Available Pages

{links_html}") # Category route @app.get("/category/{category_name}", response_class=HTMLResponse) async def get_category(request: Request, category_name: str): # Find den korrekte kategori category = next((cat for cat in data["categories"] if cat["path"] == category_name), None) if category: category_file = f"data/{category_name}/index.html" if os.path.exists(category_file): with open(category_file) as file: category_content = file.read() return templates.TemplateResponse( "category.html", { "request": request, "data": data, "page_title": category["name"], "author": category["author"], "content": category_content }, ) return HTMLResponse("Kategori ikke fundet", status_code=404)