--- /dev/null
+from __future__ import annotations
+from pathlib import Path
+import tomlkit
+
+def parse_frontmatter(path: Path) -> tuple[dict, str]:
+ """Parse TOML frontmatter delimited by +++. Returns (frontmatter_dict, body_str)."""
+ text = path.read_text(encoding="utf-8")
+ if not text.startswith("+++"):
+ raise ValueError(f"No TOML frontmatter found in {path}")
+ parts = text.split("+++", 2)
+ if len(parts) < 3:
+ raise ValueError(f"Malformed frontmatter in {path}")
+ _, toml_block, body = parts
+ fm = dict(tomlkit.loads(toml_block))
+ return fm, body.lstrip("\n")
+
+def write_frontmatter(path: Path, frontmatter: dict, body: str) -> None:
+ """Write frontmatter + body back to file, preserving TOML format."""
+ text = path.read_text(encoding="utf-8")
+ parts = text.split("+++", 2)
+ if len(parts) < 3:
+ raise ValueError(f"Malformed frontmatter in {path}")
+ _, original_toml, _ = parts
+ doc = tomlkit.loads(original_toml)
+ for k, v in frontmatter.items():
+ doc[k] = v
+ new_text = f"+++\n{tomlkit.dumps(doc)}+++\n\n{body}"
+ path.write_text(new_text, encoding="utf-8")
--- /dev/null
+import pytest
+from pathlib import Path
+import tempfile
+from core.frontmatter import parse_frontmatter, write_frontmatter
+
+SAMPLE_MD = """\
++++
+title = "Test Article"
+type = "Tech"
+draft = false
+tags = ["linux", "python"]
++++
+
+# Body
+
+Some content here.
+"""
+
+def test_parse_returns_frontmatter_dict(tmp_path):
+ f = tmp_path / "index.md"
+ f.write_text(SAMPLE_MD)
+ fm, body = parse_frontmatter(f)
+ assert fm["title"] == "Test Article"
+ assert fm["type"] == "Tech"
+ assert fm["draft"] is False
+ assert "linux" in fm["tags"]
+
+def test_parse_returns_body(tmp_path):
+ f = tmp_path / "index.md"
+ f.write_text(SAMPLE_MD)
+ fm, body = parse_frontmatter(f)
+ assert "# Body" in body
+ assert "Some content here." in body
+
+def test_write_preserves_format(tmp_path):
+ f = tmp_path / "index.md"
+ f.write_text(SAMPLE_MD)
+ fm, body = parse_frontmatter(f)
+ fm["title"] = "Updated Title"
+ write_frontmatter(f, fm, body)
+ fm2, _ = parse_frontmatter(f)
+ assert fm2["title"] == "Updated Title"
+ assert fm2["type"] == "Tech"
+
+def test_parse_raises_on_missing_delimiters(tmp_path):
+ f = tmp_path / "index.md"
+ f.write_text("# No frontmatter\n\nJust body.")
+ with pytest.raises(ValueError, match="frontmatter"):
+ parse_frontmatter(f)