From c8b26b1caad7a447ac16e2f964ad9c138ecbb829 Mon Sep 17 00:00:00 2001 From: lucaronin Date: Sun, 5 Apr 2026 04:19:14 +0200 Subject: [PATCH] feat: show YAML name field as title for .yml files in breadcrumb bar When a .yml file is opened in the raw editor, the breadcrumb bar now shows the YAML `name` field (e.g., "Active Projects") instead of the filename. Falls back to filename if no name field is present. Co-Authored-By: Claude Opus 4.6 (1M context) --- src-tauri/src/vault/mod.rs | 16 ++++++++++++++-- src-tauri/src/vault/mod_tests.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/vault/mod.rs b/src-tauri/src/vault/mod.rs index 23e78599..b77e63ae 100644 --- a/src-tauri/src/vault/mod.rs +++ b/src-tauri/src/vault/mod.rs @@ -127,7 +127,7 @@ pub fn parse_md_file(path: &Path, git_dates: Option<(u64, u64)>) -> Result, @@ -142,11 +142,12 @@ pub(crate) fn parse_non_md_file( None => (fs_modified, fs_created), }; let file_kind = classify_file_kind(path).to_string(); + let title = extract_yml_name(path).unwrap_or_else(|| filename.clone()); Ok(VaultEntry { path: path.to_string_lossy().to_string(), filename: filename.clone(), - title: filename, + title, file_kind, modified_at, created_at, @@ -155,6 +156,17 @@ pub(crate) fn parse_non_md_file( }) } +/// For `.yml` files, try to extract the `name` field from the YAML content. +fn extract_yml_name(path: &Path) -> Option { + let ext = path.extension()?.to_str()?; + if ext != "yml" && ext != "yaml" { + return None; + } + let content = std::fs::read_to_string(path).ok()?; + let mapping: serde_yaml::Value = serde_yaml::from_str(&content).ok()?; + mapping.get("name")?.as_str().map(|s| s.to_string()) +} + /// Re-read a single file from disk and return a fresh VaultEntry. /// Uses filesystem dates (no git lookup) since the file was likely just saved. pub fn reload_entry(path: &Path) -> Result { diff --git a/src-tauri/src/vault/mod_tests.rs b/src-tauri/src/vault/mod_tests.rs index 39d4d04c..14fd600f 100644 --- a/src-tauri/src/vault/mod_tests.rs +++ b/src-tauri/src/vault/mod_tests.rs @@ -1491,6 +1491,36 @@ fn test_list_properties_display_not_in_properties_or_relationships() { ); } +#[test] +fn test_yml_file_uses_name_field_as_title() { + let dir = TempDir::new().unwrap(); + let yml_content = "name: Active Projects\nicon: rocket\ncolor: blue\n"; + let yml_path = dir.path().join("active-projects.yml"); + std::fs::write(&yml_path, yml_content).unwrap(); + let entry = super::parse_non_md_file(&yml_path, None).unwrap(); + assert_eq!(entry.title, "Active Projects"); + assert_eq!(entry.filename, "active-projects.yml"); +} + +#[test] +fn test_yml_file_without_name_falls_back_to_filename() { + let dir = TempDir::new().unwrap(); + let yml_content = "key: value\n"; + let yml_path = dir.path().join("config.yml"); + std::fs::write(&yml_path, yml_content).unwrap(); + let entry = super::parse_non_md_file(&yml_path, None).unwrap(); + assert_eq!(entry.title, "config.yml"); +} + +#[test] +fn test_non_yml_file_uses_filename_as_title() { + let dir = TempDir::new().unwrap(); + let txt_path = dir.path().join("notes.txt"); + std::fs::write(&txt_path, "some content").unwrap(); + let entry = super::parse_non_md_file(&txt_path, None).unwrap(); + assert_eq!(entry.title, "notes.txt"); +} + // Frontmatter update/delete tests are in frontmatter.rs // save_image tests are in vault/image.rs // purge_trash tests are in vault/trash.rs