blob: 7726e36aea07e0f60cf463029ee1ae929a0f058f [file]
// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::ffi::OsStr;
use std::path::{Component, Path};
/// Extension methods for `std::path::Path` specific to Fuchsia
/// documentation checking.
pub trait DocPathExt {
/// Returns true if this path lies within developer-facing tools
/// (e.g., under 'skills').
fn is_ignored_doc(&self) -> bool;
/// Returns true if this path represents a doc navbar.
fn is_navbar_doc(&self) -> bool;
/// Returns true if the file is a macOS metadata file (starts with '._').
fn is_macos_hidden_doc(&self) -> bool;
/// Returns true if this path has hidden/private components (starts with
/// '_') relative to the documentation roots.
///
/// Strips `root_dir` and `reference_docs_root` prefixes before performing
/// the check, to prevent false-positive ignore matches if the checkout
/// directory itself contains an underscore.
fn is_hidden_doc(&self, root_dir: &Path, reference_docs_root: Option<&Path>) -> bool;
}
impl DocPathExt for Path {
fn is_ignored_doc(&self) -> bool {
self.components().any(|c| match c {
Component::Normal(name) => name == OsStr::new("skills"),
_ => false,
})
}
fn is_navbar_doc(&self) -> bool {
self.file_name() == Some(OsStr::new("navbar.md"))
}
fn is_macos_hidden_doc(&self) -> bool {
self.file_name().and_then(|name| name.to_str()).map_or(false, |s| s.starts_with("._"))
}
fn is_hidden_doc(&self, root_dir: &Path, reference_docs_root: Option<&Path>) -> bool {
let rel_p = self
.strip_prefix(root_dir)
.or_else(|_| reference_docs_root.map(|r| self.strip_prefix(r)).unwrap_or(Ok(self)))
.unwrap_or(self);
rel_p.components().any(|c| match c {
Component::Normal(s) => s.to_str().unwrap_or_default().starts_with('_'),
_ => false,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
fn test_is_ignored_doc() {
assert!(Path::new("docs/skills/SKILL.md").is_ignored_doc());
assert!(Path::new("vendor/google/skills/yaml/config.yaml").is_ignored_doc());
assert!(!Path::new("docs/contribute/governance.md").is_ignored_doc());
assert!(!Path::new("docs/_toc.yaml").is_ignored_doc());
}
#[test]
fn test_is_navbar_doc() {
assert!(Path::new("docs/navbar.md").is_navbar_doc());
assert!(Path::new("navbar.md").is_navbar_doc());
assert!(!Path::new("docs/README.md").is_navbar_doc());
}
#[test]
fn test_is_macos_hidden_doc() {
assert!(Path::new("docs/._README.md").is_macos_hidden_doc());
assert!(Path::new("._index.md").is_macos_hidden_doc());
assert!(!Path::new("docs/README.md").is_macos_hidden_doc());
}
#[test]
fn test_is_hidden_doc() {
let root_dir = PathBuf::from("/home/user/fuchsia");
let ref_dir = PathBuf::from("/home/user/reference_docs");
// Standard file (should not be hidden)
let p1 = PathBuf::from("/home/user/fuchsia/docs/getting-started.md");
assert!(!p1.is_hidden_doc(&root_dir, None));
// File starting with underscore (should be hidden)
let p2 = PathBuf::from("/home/user/fuchsia/docs/_index.md");
assert!(p2.is_hidden_doc(&root_dir, None));
// File inside a hidden folder (should be hidden)
let p3 = PathBuf::from("/home/user/fuchsia/docs/_common/header.md");
assert!(p3.is_hidden_doc(&root_dir, None));
// Standard file in reference docs (should not be hidden)
let p4 = PathBuf::from("/home/user/reference_docs/sdk/overview.md");
assert!(!p4.is_hidden_doc(&root_dir, Some(&ref_dir)));
// File inside a hidden folder in reference docs (should be hidden)
let p5 = PathBuf::from("/home/user/reference_docs/_internal/helper.md");
assert!(p5.is_hidden_doc(&root_dir, Some(&ref_dir)));
}
#[test]
fn test_is_hidden_doc_with_underscore_in_workspace_roots() {
// Scenario where workspace path contains underscore (e.g., /home/user/_workspace)
let root_dir = PathBuf::from("/home/user/_workspace/fuchsia");
let ref_dir = PathBuf::from("/home/user/_workspace/reference");
// Standard file should NOT be hidden, even though workspace path has underscore
let p1 = PathBuf::from("/home/user/_workspace/fuchsia/docs/getting-started.md");
assert!(!p1.is_hidden_doc(&root_dir, Some(&ref_dir)));
let p2 = PathBuf::from("/home/user/_workspace/reference/sdk/overview.md");
assert!(!p2.is_hidden_doc(&root_dir, Some(&ref_dir)));
// Hidden file inside workspace with underscore should still be detected correctly
let p3 = PathBuf::from("/home/user/_workspace/fuchsia/docs/_common/header.md");
assert!(p3.is_hidden_doc(&root_dir, Some(&ref_dir)));
let p4 = PathBuf::from("/home/user/_workspace/reference/_internal/helper.md");
assert!(p4.is_hidden_doc(&root_dir, Some(&ref_dir)));
}
}