use crate::builder::BuildOutput;
use std::fs;
use std::path::Path;
pub fn write_build_output(
output: &BuildOutput,
out_dir: &Path,
media_dir: &Path,
web_dist: &Path,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
if out_dir.exists() {
fs::remove_dir_all(out_dir)?;
}
fs::create_dir_all(out_dir)?;
for page in &output.pages {
let file_path = out_dir.join(&page.path);
if let Some(parent) = file_path.parent() {
fs::create_dir_all(parent)?;
}
fs::write(&file_path, &page.content)?;
}
let data_dir = out_dir.join("data");
fs::create_dir_all(&data_dir)?;
for (ext_id, data) in &output.extensions_data {
let path = data_dir.join(format!("{ext_id}.json"));
let json = serde_json::to_string_pretty(data)?;
fs::write(&path, &json)?;
}
let search_json = serde_json::to_string_pretty(&output.search_docs)?;
fs::write(data_dir.join("search-index.json"), &search_json)?;
if web_dist.exists() {
copy_dir_recursive(web_dist, &out_dir.join("assets"))?;
}
if media_dir.exists() {
let out_media = out_dir.join("media");
copy_dir_recursive(media_dir, &out_media)?;
}
tracing::info!(
pages = output.pages.len(),
extensions = output.extensions_data.len(),
dir = %out_dir.display(),
"build output written"
);
Ok(())
}
fn copy_dir_recursive(src: &Path, dst: &Path) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
if !src.is_dir() {
return Err(format!("not a directory: {}", src.display()).into());
}
fs::create_dir_all(dst)?;
for entry in fs::read_dir(src)? {
let entry = entry?;
let file_type = entry.file_type()?;
let src_path = entry.path();
let dst_path = dst.join(entry.file_name());
if file_type.is_dir() {
copy_dir_recursive(&src_path, &dst_path)?;
} else {
fs::copy(&src_path, &dst_path)?;
}
}
Ok(())
}