From 4d6c13a31049d1da387d8fa2e572bb5487bdb1bb Mon Sep 17 00:00:00 2001 From: Mohamed Mansour Date: Fri, 19 Jun 2026 22:28:29 -0700 Subject: [PATCH 1/2] feat(webui-press): normalize duplicate folder/filename paths as index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Treat markdown files where the filename matches the parent folder name as index pages, avoiding redundant URL paths. Example: - Before: components/webui-button/webui-button.md → /webui-button/webui-button/ - After: components/webui-button/webui-button.md → /webui-button/ This enables cleaner component documentation URLs while preserving support for additional pages (e.g., webui-button/usage.md → /webui-button/usage). Changes: - Add normalize_path_as_index() helper to strip duplicate filenames - Update build_page_registry() to normalize paths before URL generation - Add comprehensive test coverage (6 test cases) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- crates/webui-press/src/content.rs | 80 +++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/crates/webui-press/src/content.rs b/crates/webui-press/src/content.rs index 0b5ebf17..015b112b 100644 --- a/crates/webui-press/src/content.rs +++ b/crates/webui-press/src/content.rs @@ -156,6 +156,29 @@ fn collect_sidebar_links(items: &[SidebarItem]) -> Vec<&str> { /// /// Discovery is filesystem-driven: any markdown file under content_dir becomes /// a page. The sidebar/nav config controls navigation, not discovery. +/// Strip redundant filename if it matches the parent folder name. +/// E.g., "my-button/my-button" → "my-button" +/// "my-button/usage" → "my-button/usage" (unchanged) +fn normalize_path_as_index(path: &str) -> &str { + // Find the last slash to split parent/filename + let Some(slash_pos) = path.rfind('/') else { + return path; + }; + + let parent = &path[..slash_pos]; + let filename = &path[slash_pos + 1..]; + + // Get the parent folder name (last segment before filename) + let folder_name = parent.rsplit('/').next().unwrap_or(""); + + // If folder name matches filename, treat as index and strip filename + if folder_name == filename { + parent + } else { + path + } +} + fn build_page_registry(content_dir: &Path, base_path: &str) -> Vec<(String, std::path::PathBuf)> { let mut pages = Vec::new(); let mut stack: Vec = vec![content_dir.to_path_buf()]; @@ -188,7 +211,14 @@ fn build_page_registry(content_dir: &Path, base_path: &str) -> Vec<(String, std: }; let rel_str = rel.to_string_lossy().replace('\\', "/"); let trimmed = rel_str.trim_end_matches(".md"); + + // Strip /index suffix let trimmed = trimmed.strip_suffix("/index").unwrap_or(trimmed); + + // Strip redundant filename if it matches parent folder + // e.g., "webui-button/webui-button" → "webui-button" + let trimmed = normalize_path_as_index(trimmed); + // Root index.md => "/" let url_path = if trimmed.is_empty() || trimmed == "index" { if base_path.is_empty() { @@ -743,6 +773,56 @@ mod tests { assert!(out.ends_with("é-page"), "got {out}"); } + // --- normalize_path_as_index ----------------------------------------- + + #[test] + fn normalize_path_as_index_strips_duplicate_folder_name() { + assert_eq!( + normalize_path_as_index("webui-button/webui-button"), + "webui-button" + ); + } + + #[test] + fn normalize_path_as_index_keeps_different_filename() { + assert_eq!( + normalize_path_as_index("webui-button/usage"), + "webui-button/usage" + ); + } + + #[test] + fn normalize_path_as_index_nested_folders() { + assert_eq!( + normalize_path_as_index("components/webui-button/webui-button"), + "components/webui-button" + ); + } + + #[test] + fn normalize_path_as_index_no_slash_returns_unchanged() { + assert_eq!( + normalize_path_as_index("webui-button"), + "webui-button" + ); + } + + #[test] + fn normalize_path_as_index_deep_nesting_with_match() { + assert_eq!( + normalize_path_as_index("a/b/c/webui-card/webui-card"), + "a/b/c/webui-card" + ); + } + + #[test] + fn normalize_path_as_index_deep_nesting_without_match() { + assert_eq!( + normalize_path_as_index("a/b/c/webui-card/examples"), + "a/b/c/webui-card/examples" + ); + } + // --- parse_frontmatter ----------------------------------------------- #[test] From af6efe3395cc9dd4ff66198d31161a7f8c511f97 Mon Sep 17 00:00:00 2001 From: Mohamed Mansour Date: Fri, 19 Jun 2026 22:37:02 -0700 Subject: [PATCH 2/2] fmt --- crates/webui-press/src/content.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/crates/webui-press/src/content.rs b/crates/webui-press/src/content.rs index 015b112b..faeec5cc 100644 --- a/crates/webui-press/src/content.rs +++ b/crates/webui-press/src/content.rs @@ -164,13 +164,13 @@ fn normalize_path_as_index(path: &str) -> &str { let Some(slash_pos) = path.rfind('/') else { return path; }; - + let parent = &path[..slash_pos]; let filename = &path[slash_pos + 1..]; - + // Get the parent folder name (last segment before filename) let folder_name = parent.rsplit('/').next().unwrap_or(""); - + // If folder name matches filename, treat as index and strip filename if folder_name == filename { parent @@ -211,14 +211,14 @@ fn build_page_registry(content_dir: &Path, base_path: &str) -> Vec<(String, std: }; let rel_str = rel.to_string_lossy().replace('\\', "/"); let trimmed = rel_str.trim_end_matches(".md"); - + // Strip /index suffix let trimmed = trimmed.strip_suffix("/index").unwrap_or(trimmed); - + // Strip redundant filename if it matches parent folder // e.g., "webui-button/webui-button" → "webui-button" let trimmed = normalize_path_as_index(trimmed); - + // Root index.md => "/" let url_path = if trimmed.is_empty() || trimmed == "index" { if base_path.is_empty() { @@ -801,10 +801,7 @@ mod tests { #[test] fn normalize_path_as_index_no_slash_returns_unchanged() { - assert_eq!( - normalize_path_as_index("webui-button"), - "webui-button" - ); + assert_eq!(normalize_path_as_index("webui-button"), "webui-button"); } #[test]