website-htmx-rustelo-code/crates/pages/build.rs
2026-07-10 03:44:13 +01:00

131 lines
5.2 KiB
Rust

//! 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<dyn std::error::Error>> {
// 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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
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(())
}