eb8dbf66a1
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
60 lines
2.2 KiB
Python
60 lines
2.2 KiB
Python
"""Serialize an Obsidian note from a frontmatter mapping and a body."""
|
|
|
|
import yaml
|
|
|
|
|
|
def format_obsidian_note(frontmatter: dict, body: str) -> str:
|
|
"""Serialize a complete Obsidian note from frontmatter and body.
|
|
|
|
When `frontmatter` is a non-empty mapping, the result is:
|
|
|
|
---\n<yaml>---\n\n<body>
|
|
|
|
where `<yaml>` is produced by
|
|
`yaml.safe_dump(frontmatter, sort_keys=False, allow_unicode=True)` (which
|
|
already ends in a newline). When `frontmatter` is empty or None, only the
|
|
body is returned. This is the inverse of `parse_obsidian_frontmatter` for a
|
|
reasonable round-trip (key order preserved, unicode kept literal).
|
|
|
|
Pure and deterministic: no I/O, no mutation of the inputs.
|
|
|
|
Args:
|
|
frontmatter: Mapping of YAML metadata for the note. Empty or None means
|
|
no frontmatter block is emitted.
|
|
body: The Markdown body of the note.
|
|
|
|
Returns:
|
|
The full note text as a string.
|
|
"""
|
|
safe_body = body if body is not None else ""
|
|
|
|
if not frontmatter:
|
|
return safe_body
|
|
|
|
yaml_block = yaml.safe_dump(frontmatter, sort_keys=False, allow_unicode=True)
|
|
# yaml.safe_dump already terminates with a trailing newline.
|
|
return f"---\n{yaml_block}---\n\n{safe_body}"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
out = format_obsidian_note({"title": "My Note", "tags": ["a", "b"]}, "Hello.")
|
|
assert out == "---\ntitle: My Note\ntags:\n- a\n- b\n---\n\nHello.", repr(out)
|
|
|
|
# Empty frontmatter -> body only.
|
|
assert format_obsidian_note({}, "just a body") == "just a body"
|
|
assert format_obsidian_note(None, "just a body") == "just a body"
|
|
|
|
# Round-trip with parse_obsidian_frontmatter: the frontmatter mapping is
|
|
# recovered exactly; the body is recovered modulo the blank separator line
|
|
# that the format inserts between the frontmatter block and the body.
|
|
from parse_obsidian_frontmatter import parse_obsidian_frontmatter
|
|
|
|
fm = {"title": "Round Trip", "status": "open"}
|
|
body = "Body with a [[link]]."
|
|
note = format_obsidian_note(fm, body)
|
|
parsed = parse_obsidian_frontmatter(note)
|
|
assert parsed["frontmatter"] == fm, parsed
|
|
assert parsed["body"].strip() == body, repr(parsed["body"])
|
|
|
|
print("OK")
|