markdown-docx / main.py
JairoDanielMT's picture
Update main.py
ebb7ae8 verified
from fastapi import FastAPI
from fastapi.responses import FileResponse, JSONResponse
from pydantic import BaseModel
import uuid
import os
import glob
import re
import pypandoc
app = FastAPI()
# Control de descargas por archivo
descargas = {}
class MarkdownInput(BaseModel):
content: str
# Reemplaza '---' por saltos de línea
def limpiar_lineas_hr(markdown_text: str) -> str:
return re.sub(r'^\s*---\s*$', '\n', markdown_text, flags=re.MULTILINE)
# Convierte \[...\] y \(...\) a $$...$$ y $...$
def normalizar_ecuaciones(md: str) -> str:
md = re.sub(r'\\\[\s*(.*?)\s*\\\]', r'$$\1$$', md, flags=re.DOTALL)
md = re.sub(r'\\\(\s*(.*?)\s*\\\)', r'$\1$', md, flags=re.DOTALL)
return md
def save_markdown_to_file(content: str, path: str):
with open(path, "w", encoding="utf-8") as f:
f.write(content)
def convert_markdown_to_docx(input_md: str, output_docx: str):
pypandoc.convert_file(
source_file=input_md,
to="docx",
format="md",
outputfile=output_docx,
extra_args=["--standalone"]
)
def limpieza():
for ext in ["*.docx", "*.md"]:
for file in glob.glob(ext):
try:
os.remove(file)
except Exception as e:
print(f"No se pudo eliminar {file}: {e}")
@app.post("/convert/")
def convert(data: MarkdownInput):
try:
limpieza()
uid = str(uuid.uuid4())
input_md = f"{uid}.md"
output_docx = f"{uid}.docx"
contenido_limpio = limpiar_lineas_hr(data.content)
contenido_limpio = normalizar_ecuaciones(contenido_limpio)
save_markdown_to_file(contenido_limpio, input_md)
convert_markdown_to_docx(input_md, output_docx)
os.remove(input_md)
descargas[uid] = 0
return {
"message": "Archivo generado exitosamente, para descargar acceder a la URL",
"url": f"https://jairodanielmt-markdown-docx.hf.space/download/{uid}"
}
except Exception as e:
return JSONResponse(content={"error": str(e)}, status_code=500)
@app.get("/download/{file_id}")
def download(file_id: str):
output_docx = f"{file_id}.docx"
if not os.path.exists(output_docx):
return JSONResponse(
content={"error": "El archivo no existe o ya fue eliminado."},
status_code=404
)
if file_id not in descargas:
return JSONResponse(
content={"error": "ID de archivo no válido."},
status_code=400
)
if descargas[file_id] >= 2:
os.remove(output_docx)
del descargas[file_id]
return JSONResponse(
content={"error": "El archivo ya no está disponible. Genere uno nuevo."},
status_code=410
)
descargas[file_id] += 1
return FileResponse(
path=output_docx,
filename="material_educativo.docx",
media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
)