Skip to content

Commit 8220f9d

Browse files
committed
Fix YAML tag serialization for Obsidian compatibility
When writing or updating frontmatter with tags, ensure proper YAML list format is used for Obsidian compatibility (Issue #132). Changes: - Keep default yaml.dump() settings which produce YAML list format - Add comprehensive test in test_file_utils.py - Prevent malformed tag serialization Fixes #132 Signed-off-by: Gilang Gumilar <gilangmlr@gmail.com>
1 parent 39f811f commit 8220f9d

2 files changed

Lines changed: 48 additions & 0 deletions

File tree

src/basic_memory/file_utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ async def update_frontmatter(path: FilePath, updates: Dict[str, Any]) -> str:
218218
new_fm = {**current_fm, **updates}
219219

220220
# Write new file with updated frontmatter
221+
# Use default YAML formatting for Obsidian compatibility (block style for lists)
221222
yaml_fm = yaml.dump(new_fm, sort_keys=False, allow_unicode=True)
222223
final_content = f"---\n{yaml_fm}---\n\n{content.strip()}"
223224

tests/utils/test_file_utils.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,50 @@ async def test_update_frontmatter_errors(tmp_path: Path):
241241
nonexistent = tmp_path / "nonexistent" / "test.md"
242242
with pytest.raises(FileError):
243243
await update_frontmatter(nonexistent, {"title": "Test"})
244+
245+
246+
@pytest.mark.asyncio
247+
async def test_yaml_tags_obsidian_compatible_format(tmp_path: Path):
248+
"""Test that tags are serialized in Obsidian-compatible YAML list format.
249+
250+
Addresses Issue #132: Tags should use YAML list format (with dashes)
251+
instead of JSON array format for better Obsidian compatibility.
252+
"""
253+
test_file = tmp_path / "test.md"
254+
255+
# Test 1: Create new file with tags
256+
content = "# Test Note\n\nThis is a test note for tag formatting."
257+
test_file.write_text(content)
258+
259+
tags = ["check-in", "qr-code", "architecture", "system-design"]
260+
await update_frontmatter(test_file, {"title": "Test Note", "tags": tags})
261+
262+
# Read back the file
263+
updated_content = test_file.read_text(encoding="utf-8")
264+
265+
# Parse frontmatter to verify tags are preserved correctly
266+
fm = parse_frontmatter(updated_content)
267+
assert fm["tags"] == tags
268+
269+
# Verify the YAML format uses list style (with dashes) for Obsidian
270+
assert "tags:\n - check-in" in updated_content or "tags:\n- check-in" in updated_content
271+
272+
# Ensure it's NOT in JSON array format
273+
assert 'tags: ["' not in updated_content
274+
275+
# Ensure it's NOT in the malformed format
276+
assert '- \'["' not in updated_content
277+
assert '- \'"' not in updated_content
278+
279+
# Test 2: Update existing file with empty tags list
280+
await update_frontmatter(test_file, {"tags": []})
281+
content2 = test_file.read_text(encoding="utf-8")
282+
fm2 = parse_frontmatter(content2)
283+
assert fm2["tags"] == []
284+
285+
# Test 3: Update with tags containing special characters
286+
special_tags = ["feat/check-in", "bug-fix", "v2.0", "high-priority"]
287+
await update_frontmatter(test_file, {"tags": special_tags})
288+
content3 = test_file.read_text(encoding="utf-8")
289+
fm3 = parse_frontmatter(content3)
290+
assert fm3["tags"] == special_tags

0 commit comments

Comments
 (0)