"""Markdown writer utility.""" import re from datetime import datetime from typing import Optional from tracker.models.session import Session class MarkdownWriter: """Escritura de archivos Markdown del proyecto.""" def format_log_entry(self, session: Session, summary: str) -> str: """Formatea una entrada para LOG.md. Formato: ## 2026-03-23 10:00–11:20 **Objetivo** ... **Trabajo realizado** - ... **Cambios relevantes** - ... **Bloqueos** - ... **Decisiones** - ... **Próximos pasos** - ... **Resumen** ... Returns string formateado. """ started = session.started_at.strftime("%Y-%m-%d %H:%M") ended = session.ended_at.strftime("%H:%M") if session.ended_at else "En Curso" date_range = f"{started}–{ended}" lines = [ f"## {date_range}", "", "**Objetivo**", f"{session.objective or 'No especificado'}", "", "**Trabajo realizado**", ] if session.work_done: for item in session.work_done: lines.append(f"- {item}") else: lines.append("- Sin trabajo registrado") lines.extend(["", "**Cambios relevantes**"]) if session.changes: for item in session.changes: lines.append(f"- {item}") else: lines.append("- Sin cambios") lines.extend(["", "**Bloqueos**"]) if session.blockers: for item in session.blockers: lines.append(f"- {item}") else: lines.append("- Sin bloqueos") lines.extend(["", "**Decisiones**"]) if session.decisions: for item in session.decisions: lines.append(f"- {item}") else: lines.append("- Sin decisiones") lines.extend(["", "**Próximos pasos**"]) if session.next_steps: for item in session.next_steps: lines.append(f"- {item}") else: lines.append("- Sin pasos definidos") lines.extend(["", "**Resumen**", summary]) return "\n".join(lines) + "\n\n" def format_session_file(self, session: Session) -> str: """Formatea archivo de sesion detalle en sessions/YYYY-MM-DD_HHMM.md. Formato: # Sesion: 2026-03-23 10:00–11:20 ## Objetivo ... ## Notas ... ## Trabajo realizado ... ## Cambios ... ## Decisiones ... ## Bloqueos ... ## Proximos pasos ... ## Referencias ... ## Duracion X minutos """ started = session.started_at.strftime("%Y-%m-%d %H:%M") ended = session.ended_at.strftime("%H:%M") if session.ended_at else "En Curso" lines = [ f"# Sesion: {started}–{ended}", "", "## Objetivo", f"{session.objective or 'No especificado'}", "", "## Notas", ] if session.raw_notes: for note in session.raw_notes: note_type = note.get("type", "work") note_text = note.get("text", "") lines.append(f"- [{note_type}] {note_text}") else: lines.append("- Sin notas") lines.extend([ "", "## Trabajo realizado", ]) if session.work_done: for item in session.work_done: lines.append(f"- {item}") else: lines.append("- Sin trabajo realizado") lines.extend([ "", "## Cambios", ]) if session.changes: for item in session.changes: lines.append(f"- {item}") else: lines.append("- Sin cambios") lines.extend([ "", "## Decisiones", ]) if session.decisions: for item in session.decisions: lines.append(f"- {item}") else: lines.append("- Sin decisiones") lines.extend([ "", "## Bloqueos", ]) if session.blockers: for item in session.blockers: lines.append(f"- {item}") else: lines.append("- Sin bloqueos") lines.extend([ "", "## Proximos pasos", ]) if session.next_steps: for item in session.next_steps: lines.append(f"- {item}") else: lines.append("- Sin pasos definidos") lines.extend([ "", "## Referencias", ]) if session.references: for item in session.references: lines.append(f"- {item}") else: lines.append("- Sin referencias") lines.extend([ "", "## Duracion", f"{session.duration_minutes} minutos", ]) return "\n".join(lines) + "\n" def format_autogen_section(self, content: str, section: str, new_content: str) -> str: """Reemplaza o inserta una seccion AUTOGEN en contenido Markdown. Busca ... Si existe, reemplaza el contenido entre los marcadores. Si no existe, inserta la seccion al final. Returns el contenido modificado. """ start_marker = f"" end_marker = f"" full_marker = f"{start_marker}\n{new_content}\n{end_marker}" # Buscar si existe la seccion pattern = rf"{re.escape(start_marker)}.*?{re.escape(end_marker)}" if re.search(pattern, content, re.DOTALL): # Reemplazar seccion existente return re.sub(pattern, full_marker, content, flags=re.DOTALL) else: # Insertar al final return content + "\n" + full_marker + "\n" def format_readme_section(self, section: str, content: str) -> str: """Formatea una seccion de README.md. Para usar con format_autogen_section. """ return content