from fastapi import FastAPI, Request, Form from fastapi.responses import HTMLResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates import re from typing import Dict, Optional app = FastAPI(title="Business Model Canvas Parser") # Montar static files y templates app.mount("/static", StaticFiles(directory="static"), name="static") templates = Jinja2Templates(directory="templates") # Mapeo de secciones del BMC BMC_SECTIONS = { "socios_clave": "Socios Clave", "actividades_clave": "Actividades Clave", "recursos_clave": "Recursos Clave", "propuesta_de_valor": "Propuesta de valor", "relacion_con_clientes": "Relación Con Clientes", "canales": "Canales", "segmentos": "Segmentos", "estructura_de_costos": "Estructura de Costos", "fuentes_de_ingresos": "Fuentes de Ingresos", } def parse_markdown_to_bmc(markdown_text: str) -> Dict[str, str]: """ Parsea el markdown y extrae el contenido de cada sección del BMC """ bmc_data = {key: "" for key in BMC_SECTIONS.keys()} # Patrones para buscar cada sección (case insensitive) patterns = { "socios_clave": r"##\s*Socios\s*Clave.*?(?=##|$)", "actividades_clave": r"##\s*Actividades\s*Clave.*?(?=##|$)", "recursos_clave": r"##\s*Recursos\s*Clave.*?(?=##|$)", "propuesta_de_valor": r"##\s*Propuesta\s*de\s*valor.*?(?=##|$)", "relacion_con_clientes": r"##\s*Relacion\s*Con\s*Clientes.*?(?=##|$)", "canales": r"##\s*Canales.*?(?=##|$)", "segmentos": r"##\s*Segmentos.*?(?=##|$)", "estructura_de_costos": r"##\s*Estructura\s*de\s*Costos.*?(?=##|$)", "fuentes_de_ingresos": r"##\s*Fuentes\s*de\s*Ingresos.*?(?=##|$)", } for key, pattern in patterns.items(): match = re.search(pattern, markdown_text, re.IGNORECASE | re.DOTALL) if match: content = match.group(0) # Remover el header y limpiar content = re.sub(r"^##.*\n", "", content, flags=re.IGNORECASE) # Remover numeración inicial si existe content = re.sub(r"^\d+\s*", "", content.strip()) key2 = key bmc_data[key2] = content.strip() return bmc_data @app.get("/") def home(request: Request): return templates.TemplateResponse(request=request, name="bmc.html") @app.post("/render", response_class=HTMLResponse) async def render_bmc(request: Request, markdown_text: str = Form()): """Procesa el markdown y renderiza el BMC""" bmc_data = parse_markdown_to_bmc(markdown_text) return templates.TemplateResponse( request=request, name="bmc.html", context={"markdown_text": markdown_text, "bmc_data": bmc_data}, ) @app.post("/api/parse") async def api_parse_bmc(markdown_text: str = Form(...)): """API endpoint que retorna JSON con los datos parseados""" bmc_data = parse_markdown_to_bmc(markdown_text) return {"bmc": bmc_data} if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8001)