Skip to main content

max / makenotwork

2.8 KB · 66 lines History Blame Raw
1 //! Loading the published documentation tree (`site-docs/public`).
2 //!
3 //! Lives in the library rather than in `main.rs` so the test harness builds the
4 //! loader the same way production does. One definition means the harness cannot
5 //! drift from the server, and `/docs`, the sitemap and the search index are
6 //! coverable under test.
7
8 use docengine::{DocLoader, DocLoaderConfig};
9 use mnw_assumptions::Assumptions;
10 use std::sync::Arc;
11
12 /// Where the published docs live. `DOCS_PATH` overrides for a deployment whose
13 /// working directory is not the crate root.
14 pub fn docs_path() -> String {
15 std::env::var("DOCS_PATH").unwrap_or_else(|_| "site-docs/public".to_string())
16 }
17
18 /// Where the business assumptions live, substituted into doc bodies.
19 pub fn assumptions_path() -> String {
20 std::env::var("ASSUMPTIONS_PATH")
21 .unwrap_or_else(|_| "docs/business/assumptions.toml".to_string())
22 }
23
24 /// Load and validate business assumptions. `Err` carries a human-readable
25 /// message; normal startup turns it into a panic, the check modes into a
26 /// sentinel line. Shared so the two paths validate identically.
27 pub fn load_assumptions() -> Result<Arc<Assumptions>, String> {
28 let path = assumptions_path();
29 let a = Assumptions::load(&path)
30 .map_err(|e| format!("failed to load assumptions from {path}: {e}"))?;
31 a.validate()
32 .map_err(|e| format!("assumptions validation failed:\n{e}"))?;
33 tracing::info!(path = %path, "assumptions loaded and validated");
34 Ok(Arc::new(a))
35 }
36
37 /// Build the documentation loader from disk with the production config.
38 ///
39 /// Shared by normal startup, the `MNW_CHECK_DOCS` integrity check, and the test
40 /// harness, so all three see the exact same sections, link prefix, examples
41 /// path, and assumption substitution. The broken-link report cannot drift from
42 /// what is served, and a test asserting over `/docs` is asserting over the real
43 /// tree.
44 pub fn build_doc_loader(assumptions: Arc<Assumptions>) -> DocLoader {
45 let docs_path = docs_path();
46 DocLoader::load(
47 std::path::Path::new(&docs_path),
48 &DocLoaderConfig {
49 sections: vec![
50 ("about".to_string(), "About".to_string()),
51 ("guide".to_string(), "Guide".to_string()),
52 ("developer".to_string(), "Developer".to_string()),
53 ("legal".to_string(), "Legal".to_string()),
54 ("support".to_string(), "Support".to_string()),
55 ("tech".to_string(), "Tech".to_string()),
56 ],
57 link_prefix: "/docs".to_string(),
58 unpublished_pattern: Some("unpublished/".to_string()),
59 examples_path: Some(std::path::Path::new(&docs_path).join("../examples")),
60 pre_process: Some(Box::new(move |md: &str| {
61 assumptions.substitute(md).map_err(|e| e.to_string())
62 })),
63 },
64 )
65 }
66