---
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<yaml>---\\n\\n<body>' 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<yaml>---\\n\\n<body>' (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.
