use super::engine::Engine;
use super::router::Params;
use super::{site, store, Kind, ThemeError};
use crate::StaticSite;
use laterite_core::Db;
use std::path::Path;
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct BuildReport {
pub pages: Vec<String>,
pub assets: Vec<String>,
pub skipped: Vec<String>,
}
pub async fn build(
db: &Db,
code: &str,
out_dir: &Path,
base_url: &str,
) -> Result<BuildReport, ThemeError> {
let theme = store::find_theme(db, code)
.await?
.ok_or_else(|| ThemeError::NotFound(code.to_string()))?;
let origin = base_url.trim_end_matches('/').to_string();
let engine = Engine::build_with(db, code, {
let origin = origin.clone();
move |env| site::add_url(env, origin)
})
.await?;
let mut out = StaticSite::new(out_dir, &origin)?;
let mut report = BuildReport::default();
let mut names: Vec<&str> = engine.routes().names();
names.sort_unstable();
for name in names {
let settings = engine.page(name).cloned().unwrap_or_default();
let pattern = match settings.pattern() {
Ok(p) => p,
Err(_) => continue,
};
if !pattern.is_static() || settings.hidden {
report.skipped.push(name.to_string());
continue;
}
let url = pattern.source().to_string();
let html = site::render_page(&engine, &theme, name, &Params::new(), &url, false, &origin)
.map_err(ThemeError::Template)?;
out.page(&url, &html)?;
if url == "/404" {
out.file("404.html", &html)?;
}
report.pages.push(url);
}
report.pages.sort();
report.skipped.sort();
for template in engine.names() {
let Some(path) = template.strip_prefix("assets/") else {
continue;
};
let body = engine
.render(Kind::Asset, path, ())
.map_err(ThemeError::Template)?;
let target = format!("themes/{code}/assets/{path}");
out.file(&target, &body)?;
report.assets.push(target);
}
Ok(report)
}