--- name: format_obsidian_note kind: function lang: py domain: obsidian version: "1.0.0" purity: pure signature: "def format_obsidian_note(frontmatter: dict, body: str) -> str" description: "Serializa una nota completa de Obsidian a partir de un dict de frontmatter y un body. Si frontmatter no esta vacio, emite '---\\n---\\n\\n' usando yaml.safe_dump(frontmatter, sort_keys=False, allow_unicode=True). Si frontmatter es vacio o None, devuelve solo el body. Es la inversa de parse_obsidian_frontmatter para un round-trip razonable. Pura, sin I/O." tags: [obsidian, frontmatter, yaml, markdown, format, serialize, note] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "" imports: ["yaml"] params: - name: frontmatter desc: "Dict con los metadatos YAML de la nota. Vacio o None significa que no se emite bloque frontmatter (solo el body). El orden de las claves se preserva (sort_keys=False)." - name: body desc: "Cuerpo Markdown de la nota. None se trata como cadena vacia." output: "String con el texto completo de la nota. Con frontmatter: '---\\n---\\n\\n' (unicode literal, orden de claves preservado). Sin frontmatter: solo el body." tested: true tests: - "con frontmatter" - "frontmatter vacio devuelve body" - "frontmatter none devuelve body" - "preserva orden de claves" - "unicode literal" - "round trip con parse" test_file_path: "python/functions/obsidian/format_obsidian_note_test.py" file_path: "python/functions/obsidian/format_obsidian_note.py" --- ## Ejemplo ```python out = format_obsidian_note({"title": "My Note", "tags": ["a", "b"]}, "Hello.") # "---\ntitle: My Note\ntags:\n- a\n- b\n---\n\nHello." format_obsidian_note({}, "just a body") # "just a body" ``` ## Cuando usarla Usala como ultimo paso del round-trip parse -> modificar -> format: tras leer una nota con `parse_obsidian_frontmatter`, mutar el dict de frontmatter (anadir un tag, cambiar status, actualizar una fecha) y volver a serializar la nota lista para escribir a disco. Tambien para generar notas nuevas desde cero con metadatos. ## Gotchas - Inserta una linea en blanco entre el bloque frontmatter y el body (`---\n\n`). En el round-trip con `parse_obsidian_frontmatter`, el body recuperado lleva un salto de linea inicial extra; comparar con `.strip()` o asumir ese separador. La inversa es "razonable", no byte-a-byte. - `yaml.safe_dump` reformatea el YAML a su estilo canonico: las listas salen en estilo bloque sin indentar (`tags:\n- a`), las claves no se reordenan (`sort_keys=False`) y el unicode queda literal (`allow_unicode=True`). El texto exacto del frontmatter original puede no preservarse aunque el mapping si. - Un dict vacio o `None` produce solo el body (sin `---`), coherente con que `parse_obsidian_frontmatter` trate un frontmatter vacio como ausente.