//! Pages build script - Using Provider pattern with Rustelo foundation traits //! //! This build script uses the Provider pattern with dependency injection //! instead of direct function calls. Follows PAP principles completely. mod build_page_generator; fn main() -> Result<(), Box> { // Use new PAP-compliant manifest system let manifest = rustelo_utils::ManifestResolver::load()?; let content_path = rustelo_utils::manifest_content_path(); let config_path = rustelo_utils::manifest_config_path(); println!("cargo:rerun-if-changed={}", config_path.display()); println!("cargo:rerun-if-changed=src/"); println!("cargo:rerun-if-changed={}", content_path.display()); println!("cargo:rerun-if-env-changed=ONTOREF_NICKEL_IMPORT_PATH"); // Generate page components using rustelo_tools SmartCache build_page_generator::generate_page_components(manifest.root())?; // Generate content graph static maps (related_map.rs, ontology_context_map.rs, // graph_mini_map.rs, content_graph.json) for the content_graph page module. generate_content_graph(manifest.root())?; // Generate pages documentation using rustelo_tools generate_pages_documentation(&manifest)?; println!("cargo:warning=Pages build completed with smart caching and documentation"); Ok(()) } /// Run the content-graph build pipeline, writing generated files into OUT_DIR. /// /// Requires `ONTOREF_NICKEL_IMPORT_PATH` to be set in the environment — /// this is the only path that cannot be derived from the workspace layout. /// All other paths default to conventional locations relative to the workspace root. fn generate_content_graph( workspace_root: &std::path::Path, ) -> Result<(), Box> { use content_graph::build::{codegen, graph_generator::GraphGeneratorConfig}; let framework_root = workspace_root .join("..") .join("rustelo") .canonicalize() .unwrap_or_else(|_| workspace_root.join("..").join("rustelo")); // ONTOREF_NICKEL_IMPORT_PATH must be set externally (points to /path/to/ontoref/ontology). // If absent, skip graph generation gracefully so builds without ontoref still succeed. let ontoref_path = match std::env::var("ONTOREF_NICKEL_IMPORT_PATH") { Ok(p) => std::path::PathBuf::from(p), Err(_) => { println!("cargo:warning=content-graph: ONTOREF_NICKEL_IMPORT_PATH not set — skipping graph generation. Set it to enable the content graph."); return write_empty_graph_outputs(); } }; let config = GraphGeneratorConfig::with_root(workspace_root, &framework_root, &ontoref_path); println!("cargo:rerun-if-changed={}", config.content_dir.display()); println!("cargo:rerun-if-changed={}", config.impl_ontology.display()); match content_graph::build::graph_generator::generate(&config) { Ok(graph) => { let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR")?); codegen::write_outputs(&graph, &out_dir)?; println!( "cargo:warning=content-graph: generated {} nodes, {} edges", graph.nodes.len(), graph.edges.len() ); } Err(e) => { println!("cargo:warning=content-graph: generation failed: {e} — writing empty outputs"); write_empty_graph_outputs()?; } } Ok(()) } /// Write empty (but valid) graph output files so the content_graph module compiles /// even when graph generation is skipped or fails. fn write_empty_graph_outputs() -> Result<(), Box> { let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR")?); std::fs::write( out_dir.join("content_graph.json"), r#"{"nodes":[],"edges":[]}"#, )?; std::fs::write( out_dir.join("related_map.rs"), "pub struct RelatedNode { pub id: &'static str, pub title: &'static str, pub kind: &'static str, pub url: &'static str }\n\ pub static RELATED_NODES: &[(&str, &[RelatedNode])] = &[];\n", )?; std::fs::write( out_dir.join("ontology_context_map.rs"), "pub struct OntologyRef { pub id: &'static str, pub name: &'static str, pub kind: &'static str }\n\ pub static ONTOLOGY_CONTEXT: &[(&str, &[OntologyRef])] = &[];\n", )?; std::fs::write( out_dir.join("graph_mini_map.rs"), "pub static GRAPH_MINI_SVGS: &[(&str, &str)] = &[];\n", )?; Ok(()) } /// Generate pages documentation using rustelo_tools comprehensive_analysis fn generate_pages_documentation( manifest: &rustelo_utils::ManifestResolver, ) -> Result<(), Box> { let project_root = manifest.root(); let info_path = project_root.join("site").join("info"); // Create info directory if it doesn't exist std::fs::create_dir_all(&info_path)?; // Generate pages documentation rustelo_tools::comprehensive_analysis::generate_pages_documentation( &project_root.to_string_lossy(), &rustelo_utils::manifest::content_path().to_string_lossy(), &info_path.to_string_lossy(), )?; println!("cargo:warning=Generated pages documentation in site/info"); Ok(()) }