use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
const PRERENDERED_EXCEPTIONS: &[&str] = &[
"docs/llm/harn-quickref.html",
"docs/llm/harn-quickref.md",
"docs/llm/harn-triggers-quickref.md",
];
fn repo_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.and_then(Path::parent)
.expect("harn-cli lives two directories below the repo root")
.to_path_buf()
}
fn rust_sources(dir: &Path, out: &mut Vec<PathBuf>) {
let Ok(entries) = std::fs::read_dir(dir) else {
return;
};
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
rust_sources(&path, out);
} else if path.extension().is_some_and(|ext| ext == "rs") {
out.push(path);
}
}
}
fn referenced_doc_paths(root: &Path) -> BTreeSet<String> {
const PREFIX: &str = "https://harnlang.com/";
let mut sources = Vec::new();
for crate_name in ["harn-cli", "harn-vm"] {
rust_sources(
&root.join("crates").join(crate_name).join("src"),
&mut sources,
);
}
let mut referenced = BTreeSet::new();
for source in sources {
if source.components().any(|part| part.as_os_str() == "tests") {
continue;
}
let Ok(text) = std::fs::read_to_string(&source) else {
continue;
};
for tail in text.split(PREFIX).skip(1) {
let url_path: String = tail
.chars()
.take_while(|c| c.is_ascii_alphanumeric() || "._/-#".contains(*c))
.collect();
let page = url_path.split('#').next().unwrap_or_default();
if page.ends_with(".html") || page.ends_with(".md") {
referenced.insert(page.to_string());
}
}
}
referenced
}
#[test]
fn every_documentation_link_resolves_to_a_published_page() {
let root = repo_root();
let referenced = referenced_doc_paths(&root);
assert!(
referenced.contains("provider-setup.html"),
"the link scan found no known documentation URL — it is no longer \
reading the shipped sources (found {} path(s))",
referenced.len()
);
let mut broken = Vec::new();
for path in referenced {
if PRERENDERED_EXCEPTIONS.contains(&path.as_str()) {
continue;
}
let source = root
.join("docs/src")
.join(path.trim_end_matches(".html"))
.with_extension("md");
if !source.exists() {
broken.push(format!(
"https://harnlang.com/{path} -> {}",
source.display()
));
}
}
assert!(
broken.is_empty(),
"documentation links with no published page (docs/src/<page>.md is served \
at /<page>.html, with no /docs/ prefix):\n {}",
broken.join("\n ")
);
}